From 4031a33f046bdc01fd79c69b13aba5dc8298c83c Mon Sep 17 00:00:00 2001 From: "T. van der Zwan" Date: Thu, 15 Aug 2013 19:11:02 +0000 Subject: [PATCH] Added simple test for image2led map. Added test executable for creating png from frame grabber. Added test-device for exporting color values of leds to text file. Updated configuration to match new color transform. Finished first version of the Hyperion structure (IT WORKS [1% CPU]!) --- CMakeLists.txt | 6 +- config/hyperion.config.json | 578 +-- config/hyperion.schema.json | 12 +- include/hyperion/Hyperion.h | 2 + include/hyperionpng/HyperionPng.h | 49 - libsrc/CMakeLists.txt | 2 - libsrc/hyperion/CMakeLists.txt | 2 + libsrc/hyperion/DispmanxFrameGrabber.cpp | 2 +- libsrc/hyperion/Hyperion.cpp | 10 +- libsrc/hyperion/ImageToLedsMap.h | 20 + libsrc/hyperion/LedDeviceTest.cpp | 26 + libsrc/hyperion/LedDeviceTest.h | 19 + libsrc/hyperionpng/CMakeLists.txt | 21 - libsrc/hyperionpng/HyperionPng.cpp | 79 - libsrc/hyperionpng/pngwriter.cc | 4722 ---------------------- libsrc/hyperionpng/pngwriter.h | 745 ---- src/hyperion-d.cpp | 6 + test/CMakeLists.txt | 15 +- test/TestImage2LedsMap.cpp | 44 + test/dispmanx2png/CMakeLists.txt | 18 + test/dispmanx2png/dispmanx2png.cpp | 47 + 21 files changed, 504 insertions(+), 5921 deletions(-) delete mode 100644 include/hyperionpng/HyperionPng.h create mode 100644 libsrc/hyperion/LedDeviceTest.cpp create mode 100644 libsrc/hyperion/LedDeviceTest.h delete mode 100644 libsrc/hyperionpng/CMakeLists.txt delete mode 100644 libsrc/hyperionpng/HyperionPng.cpp delete mode 100644 libsrc/hyperionpng/pngwriter.cc delete mode 100644 libsrc/hyperionpng/pngwriter.h create mode 100644 test/TestImage2LedsMap.cpp create mode 100644 test/dispmanx2png/CMakeLists.txt create mode 100644 test/dispmanx2png/dispmanx2png.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index e5fe6dd3..e8298c2e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,10 +30,10 @@ set(CMAKE_BUILD_TYPE "Release") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -Wall") # Configure the use of QT4 -find_package(Qt4 COMPONENTS QtCore REQUIRED QUIET) +find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork REQUIRED QUIET) -SET(QT_DONT_USE_QTGUI TRUE) -SET(QT_USE_QTCONSOLE TRUE) +#SET(QT_DONT_USE_QTGUI TRUE) +#SET(QT_USE_QTCONSOLE TRUE) include(${QT_USE_FILE}) add_definitions(${QT_DEFINITIONS}) link_directories(${CMAKE_FIND_ROOT_PATH}/lib/arm-linux-gnueabihf) diff --git a/config/hyperion.config.json b/config/hyperion.config.json index 8757064d..448d93e3 100644 --- a/config/hyperion.config.json +++ b/config/hyperion.config.json @@ -2,290 +2,296 @@ // Generation script: ./WriteConfig { - "device" : - { - "name" : "MyPi", - "type" : "ws2801", - "output" : "/dev/spidev0.0", - "interval" : 20000, - "rate" : 48000 - }, - "color" : - { - "red" : - { - "gamma" : 1.0, - "adjust" : 1.0, - "blacklevel" : 0.0 - }, - "green" : - { - "gamma" : 1.0, - "adjust" : 1.0, - "blacklevel" : 0.0 - }, - "blue" : - { - "gamma" : 1.0, - "adjust" : 1.0, - "blacklevel" : 0.0 - } - }, - "leds" : - [ - { - "index" : 0, - "hscan" : { "minimum" : 47.0588, "maximum" : 52.9412 }, - "vscan" : { "minimum" : 0, "maximum" : 10 } - }, - { - "index" : 1, - "hscan" : { "minimum" : 41.1765, "maximum" : 47.0588 }, - "vscan" : { "minimum" : 0, "maximum" : 10 } - }, - { - "index" : 2, - "hscan" : { "minimum" : 35.2941, "maximum" : 41.1765 }, - "vscan" : { "minimum" : 0, "maximum" : 10 } - }, - { - "index" : 3, - "hscan" : { "minimum" : 29.4118, "maximum" : 35.2941 }, - "vscan" : { "minimum" : 0, "maximum" : 10 } - }, - { - "index" : 4, - "hscan" : { "minimum" : 23.5294, "maximum" : 29.4118 }, - "vscan" : { "minimum" : 0, "maximum" : 10 } - }, - { - "index" : 5, - "hscan" : { "minimum" : 17.6471, "maximum" : 23.5294 }, - "vscan" : { "minimum" : 0, "maximum" : 10 } - }, - { - "index" : 6, - "hscan" : { "minimum" : 11.7647, "maximum" : 17.6471 }, - "vscan" : { "minimum" : 0, "maximum" : 10 } - }, - { - "index" : 7, - "hscan" : { "minimum" : 5.88235, "maximum" : 11.7647 }, - "vscan" : { "minimum" : 0, "maximum" : 10 } - }, - // TOP-LEFT Corner - { - "index" : 8, - "hscan" : { "minimum" : 0, "maximum" : 5.88235 }, - "vscan" : { "minimum" : 0, "maximum" : 10 } - }, - { - "index" : 9, - "hscan" : { "minimum" : 0, "maximum" : 10 }, - "vscan" : { "minimum" : 10, "maximum" : 20 } - }, - { - "index" : 10, - "hscan" : { "minimum" : 0, "maximum" : 10 }, - "vscan" : { "minimum" : 20, "maximum" : 30 } - }, - { - "index" : 11, - "hscan" : { "minimum" : 0, "maximum" : 10 }, - "vscan" : { "minimum" : 30, "maximum" : 40 } - }, - { - "index" : 12, - "hscan" : { "minimum" : 0, "maximum" : 10 }, - "vscan" : { "minimum" : 40, "maximum" : 50 } - }, - { - "index" : 13, - "hscan" : { "minimum" : 0, "maximum" : 10 }, - "vscan" : { "minimum" : 50, "maximum" : 60 } - }, - { - "index" : 14, - "hscan" : { "minimum" : 0, "maximum" : 10 }, - "vscan" : { "minimum" : 60, "maximum" : 70 } - }, - { - "index" : 15, - "hscan" : { "minimum" : 0, "maximum" : 10 }, - "vscan" : { "minimum" : 70, "maximum" : 80 } - }, - { - "index" : 16, - "hscan" : { "minimum" : 0, "maximum" : 10 }, - "vscan" : { "minimum" : 80, "maximum" : 90 } - }, - // BOTTOM-LEFT Corner - { - "index" : 17, - "hscan" : { "minimum" : 0, "maximum" : 5.88235 }, - "vscan" : { "minimum" : 90, "maximum" : 100 } - }, - { - "index" : 18, - "hscan" : { "minimum" : 5.88235, "maximum" : 11.7647 }, - "vscan" : { "minimum" : 90, "maximum" : 100 } - }, - { - "index" : 19, - "hscan" : { "minimum" : 11.7647, "maximum" : 17.6471 }, - "vscan" : { "minimum" : 90, "maximum" : 100 } - }, - { - "index" : 20, - "hscan" : { "minimum" : 17.6471, "maximum" : 23.5294 }, - "vscan" : { "minimum" : 90, "maximum" : 100 } - }, - { - "index" : 21, - "hscan" : { "minimum" : 23.5294, "maximum" : 29.4118 }, - "vscan" : { "minimum" : 90, "maximum" : 100 } - }, - { - "index" : 22, - "hscan" : { "minimum" : 29.4118, "maximum" : 35.2941 }, - "vscan" : { "minimum" : 90, "maximum" : 100 } - }, - { - "index" : 23, - "hscan" : { "minimum" : 35.2941, "maximum" : 41.1765 }, - "vscan" : { "minimum" : 90, "maximum" : 100 } - }, - { - "index" : 24, - "hscan" : { "minimum" : 41.1765, "maximum" : 47.0588 }, - "vscan" : { "minimum" : 90, "maximum" : 100 } - }, - { - "index" : 25, - "hscan" : { "minimum" : 47.0588, "maximum" : 52.9412 }, - "vscan" : { "minimum" : 90, "maximum" : 100 } - }, - { - "index" : 26, - "hscan" : { "minimum" : 52.9412, "maximum" : 58.8235 }, - "vscan" : { "minimum" : 90, "maximum" : 100 } - }, - { - "index" : 27, - "hscan" : { "minimum" : 58.8235, "maximum" : 64.7059 }, - "vscan" : { "minimum" : 90, "maximum" : 100 } - }, - { - "index" : 28, - "hscan" : { "minimum" : 64.7059, "maximum" : 70.5882 }, - "vscan" : { "minimum" : 90, "maximum" : 100 } - }, - { - "index" : 29, - "hscan" : { "minimum" : 70.5882, "maximum" : 76.4706 }, - "vscan" : { "minimum" : 90, "maximum" : 100 } - }, - { - "index" : 30, - "hscan" : { "minimum" : 76.4706, "maximum" : 82.3529 }, - "vscan" : { "minimum" : 90, "maximum" : 100 } - }, - { - "index" : 31, - "hscan" : { "minimum" : 82.3529, "maximum" : 88.2353 }, - "vscan" : { "minimum" : 90, "maximum" : 100 } - }, - { - "index" : 32, - "hscan" : { "minimum" : 88.2353, "maximum" : 94.1176 }, - "vscan" : { "minimum" : 90, "maximum" : 100 } - }, - // BOTTOM-RIGHT Corner - { - "index" : 33, - "hscan" : { "minimum" : 94.1176, "maximum" : 100 }, - "vscan" : { "minimum" : 90, "maximum" : 100 } - }, - { - "index" : 34, - "hscan" : { "minimum" : 90, "maximum" : 100 }, - "vscan" : { "minimum" : 80, "maximum" : 90 } - }, - { - "index" : 35, - "hscan" : { "minimum" : 90, "maximum" : 100 }, - "vscan" : { "minimum" : 70, "maximum" : 80 } - }, - { - "index" : 36, - "hscan" : { "minimum" : 90, "maximum" : 100 }, - "vscan" : { "minimum" : 60, "maximum" : 70 } - }, - { - "index" : 37, - "hscan" : { "minimum" : 90, "maximum" : 100 }, - "vscan" : { "minimum" : 50, "maximum" : 60 } - }, - { - "index" : 38, - "hscan" : { "minimum" : 90, "maximum" : 100 }, - "vscan" : { "minimum" : 40, "maximum" : 50 } - }, - { - "index" : 39, - "hscan" : { "minimum" : 90, "maximum" : 100 }, - "vscan" : { "minimum" : 30, "maximum" : 40 } - }, - { - "index" : 40, - "hscan" : { "minimum" : 90, "maximum" : 100 }, - "vscan" : { "minimum" : 20, "maximum" : 30 } - }, - { - "index" : 41, - "hscan" : { "minimum" : 90, "maximum" : 100 }, - "vscan" : { "minimum" : 10, "maximum" : 20 } - }, - // TOP-RIGHT Corner - { - "index" : 42, - "hscan" : { "minimum" : 94.1176, "maximum" : 100 }, - "vscan" : { "minimum" : 0, "maximum" : 10 } - }, - { - "index" : 43, - "hscan" : { "minimum" : 88.2353, "maximum" : 94.1176 }, - "vscan" : { "minimum" : 0, "maximum" : 10 } - }, - { - "index" : 44, - "hscan" : { "minimum" : 82.3529, "maximum" : 88.2353 }, - "vscan" : { "minimum" : 0, "maximum" : 10 } - }, - { - "index" : 45, - "hscan" : { "minimum" : 76.4706, "maximum" : 82.3529 }, - "vscan" : { "minimum" : 0, "maximum" : 10 } - }, - { - "index" : 46, - "hscan" : { "minimum" : 70.5882, "maximum" : 76.4706 }, - "vscan" : { "minimum" : 0, "maximum" : 10 } - }, - { - "index" : 47, - "hscan" : { "minimum" : 64.7059, "maximum" : 70.5882 }, - "vscan" : { "minimum" : 0, "maximum" : 10 } - }, - { - "index" : 48, - "hscan" : { "minimum" : 58.8235, "maximum" : 64.7059 }, - "vscan" : { "minimum" : 0, "maximum" : 10 } - }, - { - "index" : 49, - "hscan" : { "minimum" : 52.9412, "maximum" : 58.8235 }, - "vscan" : { "minimum" : 0, "maximum" : 10 } - } - ] + "device" : + { + "name" : "MyPi", + "type" : "ws2801", + "output" : "/dev/spidev0.0", + "interval" : 20000, + "rate" : 48000 + }, + "color" : + { + "red" : + { + "threshold" : 0.0, + "gamma" : 1.0, + "adjust" : 1.0, + "blacklevel" : 0.0, + "whitelevel" : 1.0 + }, + "green" : + { + "threshold" : 0.0, + "gamma" : 1.0, + "adjust" : 1.0, + "blacklevel" : 0.0, + "whitelevel" : 1.0 + }, + "blue" : + { + "threshold" : 0.0, + "gamma" : 1.0, + "adjust" : 1.0, + "blacklevel" : 0.0, + "whitelevel" : 1.0 + } + }, + "leds" : + [ + { + "index" : 0, + "hscan" : { "minimum" : 47.0588, "maximum" : 52.9412 }, + "vscan" : { "minimum" : 0, "maximum" : 10 } + }, + { + "index" : 1, + "hscan" : { "minimum" : 41.1765, "maximum" : 47.0588 }, + "vscan" : { "minimum" : 0, "maximum" : 10 } + }, + { + "index" : 2, + "hscan" : { "minimum" : 35.2941, "maximum" : 41.1765 }, + "vscan" : { "minimum" : 0, "maximum" : 10 } + }, + { + "index" : 3, + "hscan" : { "minimum" : 29.4118, "maximum" : 35.2941 }, + "vscan" : { "minimum" : 0, "maximum" : 10 } + }, + { + "index" : 4, + "hscan" : { "minimum" : 23.5294, "maximum" : 29.4118 }, + "vscan" : { "minimum" : 0, "maximum" : 10 } + }, + { + "index" : 5, + "hscan" : { "minimum" : 17.6471, "maximum" : 23.5294 }, + "vscan" : { "minimum" : 0, "maximum" : 10 } + }, + { + "index" : 6, + "hscan" : { "minimum" : 11.7647, "maximum" : 17.6471 }, + "vscan" : { "minimum" : 0, "maximum" : 10 } + }, + { + "index" : 7, + "hscan" : { "minimum" : 5.88235, "maximum" : 11.7647 }, + "vscan" : { "minimum" : 0, "maximum" : 10 } + }, + // TOP-LEFT Corner + { + "index" : 8, + "hscan" : { "minimum" : 0, "maximum" : 5.88235 }, + "vscan" : { "minimum" : 0, "maximum" : 10 } + }, + { + "index" : 9, + "hscan" : { "minimum" : 0, "maximum" : 10 }, + "vscan" : { "minimum" : 10, "maximum" : 20 } + }, + { + "index" : 10, + "hscan" : { "minimum" : 0, "maximum" : 10 }, + "vscan" : { "minimum" : 20, "maximum" : 30 } + }, + { + "index" : 11, + "hscan" : { "minimum" : 0, "maximum" : 10 }, + "vscan" : { "minimum" : 30, "maximum" : 40 } + }, + { + "index" : 12, + "hscan" : { "minimum" : 0, "maximum" : 10 }, + "vscan" : { "minimum" : 40, "maximum" : 50 } + }, + { + "index" : 13, + "hscan" : { "minimum" : 0, "maximum" : 10 }, + "vscan" : { "minimum" : 50, "maximum" : 60 } + }, + { + "index" : 14, + "hscan" : { "minimum" : 0, "maximum" : 10 }, + "vscan" : { "minimum" : 60, "maximum" : 70 } + }, + { + "index" : 15, + "hscan" : { "minimum" : 0, "maximum" : 10 }, + "vscan" : { "minimum" : 70, "maximum" : 80 } + }, + { + "index" : 16, + "hscan" : { "minimum" : 0, "maximum" : 10 }, + "vscan" : { "minimum" : 80, "maximum" : 90 } + }, + // BOTTOM-LEFT Corner + { + "index" : 17, + "hscan" : { "minimum" : 0, "maximum" : 5.88235 }, + "vscan" : { "minimum" : 90, "maximum" : 100 } + }, + { + "index" : 18, + "hscan" : { "minimum" : 5.88235, "maximum" : 11.7647 }, + "vscan" : { "minimum" : 90, "maximum" : 100 } + }, + { + "index" : 19, + "hscan" : { "minimum" : 11.7647, "maximum" : 17.6471 }, + "vscan" : { "minimum" : 90, "maximum" : 100 } + }, + { + "index" : 20, + "hscan" : { "minimum" : 17.6471, "maximum" : 23.5294 }, + "vscan" : { "minimum" : 90, "maximum" : 100 } + }, + { + "index" : 21, + "hscan" : { "minimum" : 23.5294, "maximum" : 29.4118 }, + "vscan" : { "minimum" : 90, "maximum" : 100 } + }, + { + "index" : 22, + "hscan" : { "minimum" : 29.4118, "maximum" : 35.2941 }, + "vscan" : { "minimum" : 90, "maximum" : 100 } + }, + { + "index" : 23, + "hscan" : { "minimum" : 35.2941, "maximum" : 41.1765 }, + "vscan" : { "minimum" : 90, "maximum" : 100 } + }, + { + "index" : 24, + "hscan" : { "minimum" : 41.1765, "maximum" : 47.0588 }, + "vscan" : { "minimum" : 90, "maximum" : 100 } + }, + { + "index" : 25, + "hscan" : { "minimum" : 47.0588, "maximum" : 52.9412 }, + "vscan" : { "minimum" : 90, "maximum" : 100 } + }, + { + "index" : 26, + "hscan" : { "minimum" : 52.9412, "maximum" : 58.8235 }, + "vscan" : { "minimum" : 90, "maximum" : 100 } + }, + { + "index" : 27, + "hscan" : { "minimum" : 58.8235, "maximum" : 64.7059 }, + "vscan" : { "minimum" : 90, "maximum" : 100 } + }, + { + "index" : 28, + "hscan" : { "minimum" : 64.7059, "maximum" : 70.5882 }, + "vscan" : { "minimum" : 90, "maximum" : 100 } + }, + { + "index" : 29, + "hscan" : { "minimum" : 70.5882, "maximum" : 76.4706 }, + "vscan" : { "minimum" : 90, "maximum" : 100 } + }, + { + "index" : 30, + "hscan" : { "minimum" : 76.4706, "maximum" : 82.3529 }, + "vscan" : { "minimum" : 90, "maximum" : 100 } + }, + { + "index" : 31, + "hscan" : { "minimum" : 82.3529, "maximum" : 88.2353 }, + "vscan" : { "minimum" : 90, "maximum" : 100 } + }, + { + "index" : 32, + "hscan" : { "minimum" : 88.2353, "maximum" : 94.1176 }, + "vscan" : { "minimum" : 90, "maximum" : 100 } + }, + // BOTTOM-RIGHT Corner + { + "index" : 33, + "hscan" : { "minimum" : 94.1176, "maximum" : 100 }, + "vscan" : { "minimum" : 90, "maximum" : 100 } + }, + { + "index" : 34, + "hscan" : { "minimum" : 90, "maximum" : 100 }, + "vscan" : { "minimum" : 80, "maximum" : 90 } + }, + { + "index" : 35, + "hscan" : { "minimum" : 90, "maximum" : 100 }, + "vscan" : { "minimum" : 70, "maximum" : 80 } + }, + { + "index" : 36, + "hscan" : { "minimum" : 90, "maximum" : 100 }, + "vscan" : { "minimum" : 60, "maximum" : 70 } + }, + { + "index" : 37, + "hscan" : { "minimum" : 90, "maximum" : 100 }, + "vscan" : { "minimum" : 50, "maximum" : 60 } + }, + { + "index" : 38, + "hscan" : { "minimum" : 90, "maximum" : 100 }, + "vscan" : { "minimum" : 40, "maximum" : 50 } + }, + { + "index" : 39, + "hscan" : { "minimum" : 90, "maximum" : 100 }, + "vscan" : { "minimum" : 30, "maximum" : 40 } + }, + { + "index" : 40, + "hscan" : { "minimum" : 90, "maximum" : 100 }, + "vscan" : { "minimum" : 20, "maximum" : 30 } + }, + { + "index" : 41, + "hscan" : { "minimum" : 90, "maximum" : 100 }, + "vscan" : { "minimum" : 10, "maximum" : 20 } + }, + // TOP-RIGHT Corner + { + "index" : 42, + "hscan" : { "minimum" : 94.1176, "maximum" : 100 }, + "vscan" : { "minimum" : 0, "maximum" : 10 } + }, + { + "index" : 43, + "hscan" : { "minimum" : 88.2353, "maximum" : 94.1176 }, + "vscan" : { "minimum" : 0, "maximum" : 10 } + }, + { + "index" : 44, + "hscan" : { "minimum" : 82.3529, "maximum" : 88.2353 }, + "vscan" : { "minimum" : 0, "maximum" : 10 } + }, + { + "index" : 45, + "hscan" : { "minimum" : 76.4706, "maximum" : 82.3529 }, + "vscan" : { "minimum" : 0, "maximum" : 10 } + }, + { + "index" : 46, + "hscan" : { "minimum" : 70.5882, "maximum" : 76.4706 }, + "vscan" : { "minimum" : 0, "maximum" : 10 } + }, + { + "index" : 47, + "hscan" : { "minimum" : 64.7059, "maximum" : 70.5882 }, + "vscan" : { "minimum" : 0, "maximum" : 10 } + }, + { + "index" : 48, + "hscan" : { "minimum" : 58.8235, "maximum" : 64.7059 }, + "vscan" : { "minimum" : 0, "maximum" : 10 } + }, + { + "index" : 49, + "hscan" : { "minimum" : 52.9412, "maximum" : 58.8235 }, + "vscan" : { "minimum" : 0, "maximum" : 10 } + } + ] } diff --git a/config/hyperion.schema.json b/config/hyperion.schema.json index 2e9f6a78..4fa3a255 100644 --- a/config/hyperion.schema.json +++ b/config/hyperion.schema.json @@ -26,8 +26,8 @@ "type":"integer", "required":true } - }, - "additionalProperties": false + }, + "additionalProperties": false }, "color": { "type":"object", @@ -48,6 +48,14 @@ "blacklevel": { "type":"number", "required":true + }, + "whitelevel": { + "type":"number", + "required":true + }, + "threshold": { + "type":"number", + "required":true } } }, diff --git a/include/hyperion/Hyperion.h b/include/hyperion/Hyperion.h index 2ec33f15..3539db3a 100644 --- a/include/hyperion/Hyperion.h +++ b/include/hyperion/Hyperion.h @@ -21,6 +21,8 @@ class Hyperion : public QObject { Q_OBJECT public: + static LedString createLedString(const Json::Value& ledsConfig); + Hyperion(const Json::Value& jsonConfig); ~Hyperion(); diff --git a/include/hyperionpng/HyperionPng.h b/include/hyperionpng/HyperionPng.h deleted file mode 100644 index 4990cc1c..00000000 --- a/include/hyperionpng/HyperionPng.h +++ /dev/null @@ -1,49 +0,0 @@ - -#pragma once - -// Utils includes -#include - -// Forward class declaration -class pngwriter; - -/** - * @brief The HyperionPng class implements the same interface - */ -class HyperionPng -{ -public: - HyperionPng(); - - ~HyperionPng(); - - void setInputSize(const unsigned width, const unsigned height); - - RgbImage& image(); - - void commit(); - - void operator() (const RgbImage& inputImage); - -private: - void writeImage(const RgbImage& inputImage); - -private: - RgbImage* mBuffer; - - unsigned mFrameCnt; - unsigned mWriteFrequency; - - pngwriter *mWriter; - unsigned long mFileIndex; - - HyperionPng(const HyperionPng&) - { - // empty - } - - HyperionPng& operator=(const HyperionPng&) - { - return *this; - } -}; diff --git a/libsrc/CMakeLists.txt b/libsrc/CMakeLists.txt index c468630e..6fd6c7a0 100644 --- a/libsrc/CMakeLists.txt +++ b/libsrc/CMakeLists.txt @@ -5,5 +5,3 @@ SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc) add_subdirectory(hyperion) add_subdirectory(utils) - -add_subdirectory(hyperionpng) diff --git a/libsrc/hyperion/CMakeLists.txt b/libsrc/hyperion/CMakeLists.txt index 74e72502..e8b9cc82 100644 --- a/libsrc/hyperion/CMakeLists.txt +++ b/libsrc/hyperion/CMakeLists.txt @@ -23,6 +23,7 @@ SET(Hyperion_HEADERS ${CURRENT_SOURCE_DIR}/DispmanxFrameGrabber.h ${CURRENT_SOURCE_DIR}/LedDeviceWs2801.h + ${CURRENT_SOURCE_DIR}/LedDeviceTest.h ${CURRENT_SOURCE_DIR}/ImageToLedsMap.h ${CURRENT_SOURCE_DIR}/ColorTransform.h ) @@ -38,6 +39,7 @@ SET(Hyperion_SOURCES ${CURRENT_SOURCE_DIR}/DispmanxFrameGrabber.cpp ${CURRENT_SOURCE_DIR}/LedDeviceWs2801.cpp + ${CURRENT_SOURCE_DIR}/LedDeviceTest.cpp ${CURRENT_SOURCE_DIR}/ImageToLedsMap.cpp ${CURRENT_SOURCE_DIR}/ColorTransform.cpp ) diff --git a/libsrc/hyperion/DispmanxFrameGrabber.cpp b/libsrc/hyperion/DispmanxFrameGrabber.cpp index b4cfaf98..b929d4b8 100644 --- a/libsrc/hyperion/DispmanxFrameGrabber.cpp +++ b/libsrc/hyperion/DispmanxFrameGrabber.cpp @@ -10,7 +10,7 @@ DispmanxFrameGrabber::DispmanxFrameGrabber(const unsigned width, const unsigned // Initiase BCM bcm_host_init(); - // Open the connection to the displaydisplay + // Open the connection to the display _display = vc_dispmanx_display_open(0); int ret = vc_dispmanx_display_get_info(_display, &_info); // Make the compiler (in release mode) happy by 'using' ret diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp index 47165c03..5ad60f52 100644 --- a/libsrc/hyperion/Hyperion.cpp +++ b/libsrc/hyperion/Hyperion.cpp @@ -10,8 +10,10 @@ // hyperion include #include #include +#include #include "LedDeviceWs2801.h" +#include "LedDeviceTest.h" #include "ColorTransform.h" using namespace hyperion; @@ -32,6 +34,10 @@ LedDevice* constructDevice(const Json::Value& deviceConfig) device = deviceWs2801; } + else if (deviceConfig["type"].asString() == "test") + { + device = new LedDeviceTest(); + } else { // Unknown / Unimplemented device @@ -49,7 +55,7 @@ ColorTransform* createColorTransform(const Json::Value& colorConfig) ColorTransform* transform = new ColorTransform(threshold, gamma, blacklevel, whitelevel); return transform; } -LedString createLedString(const Json::Value& ledsConfig) +LedString Hyperion::createLedString(const Json::Value& ledsConfig) { LedString ledString; @@ -77,6 +83,8 @@ Hyperion::Hyperion(const Json::Value &jsonConfig) : mDevice(constructDevice(jsonConfig["device"])), _timer() { + ImageProcessorFactory::getInstance().init(mLedString); + _timer.setSingleShot(true); QObject::connect(&_timer, SIGNAL(timeout()), this, SLOT(update())); diff --git a/libsrc/hyperion/ImageToLedsMap.h b/libsrc/hyperion/ImageToLedsMap.h index e7acf6f4..3dbb0e88 100644 --- a/libsrc/hyperion/ImageToLedsMap.h +++ b/libsrc/hyperion/ImageToLedsMap.h @@ -1,6 +1,9 @@ #pragma once +// STL includes +#include + // hyperion-utils includes #include @@ -44,6 +47,23 @@ public: */ void getMeanLedColor(const RgbImage & image, std::vector & ledColors) const; + std::string toString() const + { + std::stringstream sstream; + sstream << "ImageToLedsMap(" << _width << "x" << _height << ") ["; + for (const std::vector imageIndices : mColorsMap) + { + sstream << "{"; + for (unsigned imageIndex : imageIndices) + { + sstream << imageIndex << ";"; + } + sstream << "}"; + } + sstream << "]" << std::endl; + + return sstream.str(); + } private: const unsigned _width; const unsigned _height; diff --git a/libsrc/hyperion/LedDeviceTest.cpp b/libsrc/hyperion/LedDeviceTest.cpp new file mode 100644 index 00000000..fa815a77 --- /dev/null +++ b/libsrc/hyperion/LedDeviceTest.cpp @@ -0,0 +1,26 @@ + +// Local-Hyperion includes +#include "LedDeviceTest.h" + +LedDeviceTest::LedDeviceTest() : + _ofs("/home/pi/LedDevice.out") +{ + // empty +} + +LedDeviceTest::~LedDeviceTest() +{ + // empty +} + +int LedDeviceTest::write(const std::vector & ledValues) +{ + _ofs << "["; + for (const RgbColor& color : ledValues) + { + _ofs << color; + } + _ofs << "]" << std::endl; + + return 0; +} diff --git a/libsrc/hyperion/LedDeviceTest.h b/libsrc/hyperion/LedDeviceTest.h new file mode 100644 index 00000000..d9a6f1e8 --- /dev/null +++ b/libsrc/hyperion/LedDeviceTest.h @@ -0,0 +1,19 @@ +#pragma once + +// STL includes0 +#include + +// Hyperion includes +#include + +class LedDeviceTest : public LedDevice +{ +public: + LedDeviceTest(); + virtual ~LedDeviceTest(); + + virtual int write(const std::vector & ledValues); + +private: + std::ofstream _ofs; +}; diff --git a/libsrc/hyperionpng/CMakeLists.txt b/libsrc/hyperionpng/CMakeLists.txt deleted file mode 100644 index 7c56a9c9..00000000 --- a/libsrc/hyperionpng/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ - -# Find the libPNG -find_package(PNG REQUIRED QUIET) - -# Add additional includes dirs -include_directories(${PNG_INCLUDE_DIR}) - -# Define the current source locations -SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/hyperionpng) -SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/hyperionpng) - -# Create the 'rasplight-png' library -add_library(hyperion-png SHARED - ${CURRENT_HEADER_DIR}/HyperionPng.h - ${CURRENT_SOURCE_DIR}/HyperionPng.cpp - ${CURRENT_SOURCE_DIR}/pngwriter.h - ${CURRENT_SOURCE_DIR}/pngwriter.cc) - -target_link_libraries(hyperion-png - hyperion-utils - ${PNG_LIBRARIES}) diff --git a/libsrc/hyperionpng/HyperionPng.cpp b/libsrc/hyperionpng/HyperionPng.cpp deleted file mode 100644 index 2c59734e..00000000 --- a/libsrc/hyperionpng/HyperionPng.cpp +++ /dev/null @@ -1,79 +0,0 @@ -// PNG includes -#ifndef NO_FREETYPE -#define NO_FREETYPE -#endif -#include "pngwriter.h" - - -#include - -HyperionPng::HyperionPng() : - mBuffer(nullptr), - mFrameCnt(0), - mWriter(new pngwriter()), - mFileIndex(0) -{ - // empty -} - -HyperionPng::~HyperionPng() -{ - std::cout << "HyperionPng is being deleted" << std::endl; - delete mBuffer; - - mWriter->close(); - delete mWriter; -} - -void HyperionPng::setInputSize(const unsigned width, const unsigned height) -{ - delete mBuffer; - mBuffer = new RgbImage(width, height); -} - -RgbImage& HyperionPng::image() -{ - return *mBuffer; -} - -void HyperionPng::commit() -{ - writeImage(*mBuffer); -} - -void HyperionPng::operator() (const RgbImage& inputImage) -{ - writeImage(inputImage); -} - -void HyperionPng::writeImage(const RgbImage& inputImage) -{ - // Write only every n'th frame - if (mFrameCnt%10 == 0) - { - // Set the filename for the PNG - char filename[64]; - sprintf(filename, "/home/pi/RASPI_%04lu.png", mFileIndex); - mWriter->pngwriter_rename(filename); - mWriter->resize(inputImage.width(), inputImage.height()); - - // Plot the pixels from the image to the PNG-Writer - for (unsigned y=0; yplot(x+1, inputImage.height()-y, color.red/255.0, color.green/255.0, color.blue/255.0); - } - } - - std::cout << "Writing the PNG" << std::endl; - // Write-out the current frame and prepare for the next - mWriter->write_png(); - - ++mFileIndex; - std::cout << "PNGWRITER FINISHED" << std::endl; - } - ++mFrameCnt; -} - diff --git a/libsrc/hyperionpng/pngwriter.cc b/libsrc/hyperionpng/pngwriter.cc deleted file mode 100644 index 72db5177..00000000 --- a/libsrc/hyperionpng/pngwriter.cc +++ /dev/null @@ -1,4722 +0,0 @@ -//********** pngwriter.cc ********************************************** -// Author: Paul Blackburn -// -// Email: individual61@users.sourceforge.net -// -// Version: 0.5.4 (19 / II / 2009) -// -// Description: Library that allows plotting a 48 bit -// PNG image pixel by pixel, which can -// then be opened with a graphics program. -// -// License: GNU General Public License -// Copyright 2002, 2003, 2004, 2005, 2006, 2007, -// 2008, 2009 Paul Blackburn -// -// Website: Main: http://pngwriter.sourceforge.net/ -// Sourceforge.net: http://sourceforge.net/projects/pngwriter/ -// Freshmeat.net: http://freshmeat.net/projects/pngwriter/ -// -// Documentation: The header file (pngwriter.h) is commented, but for a -// quick reference document, and support, -// take a look at the website. -// -//************************************************************************* - -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * */ - -#define NO_FREETYPE -#include "pngwriter.h" - -// Default Constructor -//////////////////////////////////////////////////////////////////////////// -pngwriter::pngwriter() -{ - - filename_ = new char[255]; - textauthor_ = new char[255]; - textdescription_ = new char[255]; - texttitle_ = new char[255]; - textsoftware_ = new char[255]; - - strcpy(filename_, "out.png"); - width_ = 250; - height_ = 250; - backgroundcolour_ = 65535; - compressionlevel_ = -2; - filegamma_ = 0.5; - transformation_ = 0; - - strcpy(textauthor_, "PNGwriter Author: Paul Blackburn"); - strcpy(textdescription_, "http://pngwriter.sourceforge.net/"); - strcpy(textsoftware_, "PNGwriter: An easy to use graphics library."); - strcpy(texttitle_, "out.png"); - - int kkkk; - - bit_depth_ = 16; //Default bit depth for new images - colortype_=2; - screengamma_ = 2.2; - - graph_ = (png_bytepp)malloc(height_ * sizeof(png_bytep)); - if(graph_ == NULL) - { - std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl; - } - - for (kkkk = 0; kkkk < height_; kkkk++) - { - graph_[kkkk] = (png_bytep)malloc(6*width_ * sizeof(png_byte)); - if(graph_[kkkk] == NULL) - { - std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl; - } - } - - if(graph_ == NULL) - { - std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl; - } - - int tempindex; - for(int hhh = 0; hhh65535) - { - std::cerr << " PNGwriter::pngwriter - WARNING **: Constructor called with background colour greater than 65535. Setting to 65535."<65535) - { - std::cerr << " PNGwriter::pngwriter - WARNING **: Constructor called with background colour greater than 1.0. Setting to 1.0."<65535) - { - std::cerr << " PNGwriter::pngwriter - WARNING **: Constructor called with background colour greater than 65535. Setting to 65535."<65535) - { - std::cerr << " PNGwriter::pngwriter - WARNING **: Constructor called with background colour greater than 65535. Setting to 65535."< 65535) - { - red = 65535; - } - if(green > 65535) - { - green = 65535; - } - if(blue > 65535) - { - blue = 65535; - } - - if(red < 0) - { - red = 0; - } - if(green < 0) - { - green = 0; - } - if(blue < 0) - { - blue = 0; - } - - if((bit_depth_ == 16)) - { - // if( (height_-y >-1) && (height_-y -1) && (6*(x-1)+5<6*width_) ) - if( (y<=height_) && (y>0) && (x>0) && (x<=width_) ) - { - //graph_[height_-y][6*(x-1) + i] where i goes from 0 to 5 - tempindex= 6*x-6; - graph_[height_-y][tempindex] = (char) floor(((double)red)/256); - graph_[height_-y][tempindex+1] = (char)(red%256); - graph_[height_-y][tempindex+2] = (char) floor(((double)green)/256); - graph_[height_-y][tempindex+3] = (char)(green%256); - graph_[height_-y][tempindex+4] = (char) floor(((double)blue)/256); - graph_[height_-y][tempindex+5] = (char)(blue%256); - }; - - /* - if(!( (height_-y >-1) && (height_-y -1) && (6*(x-1)+5<6*width_) )) - { - std::cerr << " PNGwriter::plot-- Plotting out of range! " << y << " " << x << std::endl; - } - */ - } - - if((bit_depth_ == 8)) - { - // if( (height_-y >-1) && (height_-y -1) && (3*(x-1)+5<3*width_) ) - if( (y0) && (x>0) && (x-1) && (height_-y -1) && (6*(x-1)+5<6*width_) )) - { - std::cerr << " PNGwriter::plot-- Plotting out of range! " << y << " " << x << std::endl; - } - */ - } -}; - -void pngwriter::plot(int x, int y, double red, double green, double blue) -{ - this->plot(x,y,int(red*65535),int(green*65535),int(blue*65535)); -}; - -/////////////////////////////////////////////////////////////// -int pngwriter::read(int x, int y, int colour) -{ - int temp1,temp2; - - if((colour !=1)&&(colour !=2)&&(colour !=3)) - { - std::cerr << " PNGwriter::read - WARNING **: Invalid argument: should be 1, 2 or 3, is " << colour << std::endl; - return 0; - } - - if( ( x>0 ) && ( x <= (this->width_) ) && ( y>0 ) && ( y <= (this->height_) ) ) - { - - if(bit_depth_ == 16) - { - temp2=6*(x-1); - if(colour == 1) - { - temp1 = (graph_[(height_-y)][temp2])*256 + graph_[height_-y][temp2+1]; - return temp1; - } - - if(colour == 2) - { - temp1 = (graph_[height_-y][temp2+2])*256 + graph_[height_-y][temp2+3]; - return temp1; - } - - if(colour == 3) - { - temp1 = (graph_[height_-y][temp2+4])*256 + graph_[height_-y][temp2+5]; - return temp1; - } - } - - if(bit_depth_ == 8) - { - temp2=3*(x-1); - if(colour == 1) - { - temp1 = graph_[height_-y][temp2]; - return temp1*256; - } - - if(colour == 2) - { - temp1 = graph_[height_-y][temp2+1]; - return temp1*256; - } - - if(colour == 3) - { - temp1 = graph_[height_-y][temp2+2]; - return temp1*256; - } - } - } - else - { - return 0; - } - - std::cerr << " PNGwriter::read - WARNING **: Returning 0 because of bitdepth/colour type mismatch."<< std::endl; - return 0; -} - -/////////////////////////////////////////////////////////////// -int pngwriter::read(int xxx, int yyy) -{ - int temp1,temp2,temp3,temp4,temp5; - - if( - ( xxx>0 ) && - ( xxx <= (this->width_) ) && - ( yyy>0 ) && - ( yyy <= (this->height_) ) - ) - { - if(bit_depth_ == 16) - { - // temp1 = (graph_[(height_-yyy)][6*(xxx-1)])*256 + graph_[height_-yyy][6*(xxx-1)+1]; - temp5=6*xxx; - temp1 = (graph_[(height_-yyy)][temp5-6])*256 + graph_[height_-yyy][temp5-5]; - temp2 = (graph_[height_-yyy][temp5-4])*256 + graph_[height_-yyy][temp5-3]; - temp3 = (graph_[height_-yyy][temp5-2])*256 + graph_[height_-yyy][temp5-1]; - temp4 = int((temp1+temp2+temp3)/3.0); - } - else if(bit_depth_ == 8) - { - // temp1 = graph_[height_-yyy][3*(xxx-1)]; - temp5 = 3*xxx; - temp1 = graph_[height_-yyy][temp5-3]; - temp2 = graph_[height_-yyy][temp5-2]; - temp3 = graph_[height_-yyy][temp5-1]; - temp4 = int((temp1+temp2+temp3)/3.0); - } - else - { - std::cerr << " PNGwriter::read - WARNING **: Invalid bit depth! Returning 0 as average value." << std::endl; - temp4 = 0; - } - - return temp4; - - } - else - { - return 0; - } -} - -///////////////////////////////////////////////////// -double pngwriter::dread(int x, int y, int colour) -{ - return double(this->read(x,y,colour))/65535.0; -} - -double pngwriter::dread(int x, int y) -{ - return double(this->read(x,y))/65535.0; -} - -/////////////////////////////////////////////////////// -void pngwriter::clear() -{ - int pen = 0; - int pencil = 0; - int tempindex; - - if(bit_depth_==16) - { - for(pen = 0; pen 999999999)||(index < 0)) - { - std::cerr << " PNGwriter::pngwriter_rename - ERROR **: Numerical name is out of 0 - 999 999 999 range (" << index <<")." << std::endl; - return; - } - - if( 0> sprintf(buffer, "%9.9lu.png",index)) - { - std::cerr << " PNGwriter::pngwriter_rename - ERROR **: Error creating numerical filename." << std::endl; - return; - } - - delete [] filename_; - delete [] texttitle_; - - filename_ = new char[strlen(buffer)+1]; - texttitle_ = new char[strlen(buffer)+1]; - - strcpy(filename_,buffer); - strcpy(texttitle_,buffer); - -}; - -/////////////////////////////////////////////////////// -void pngwriter::settext(char * title, char * author, char * description, char * software) -{ - delete [] textauthor_; - delete [] textdescription_; - delete [] texttitle_; - delete [] textsoftware_; - - textauthor_ = new char[strlen(author)+1]; - textdescription_ = new char[strlen(description)+1]; - textsoftware_ = new char[strlen(software)+1]; - texttitle_ = new char[strlen(title)+1]; - - strcpy(texttitle_, title); - strcpy(textauthor_, author); - strcpy(textdescription_, description); - strcpy(textsoftware_, software); -}; - -/////////////////////////////////////////////////////// -void pngwriter::settext(const char * title, const char * author, const char * description, const char * software) -{ - delete [] textauthor_; - delete [] textdescription_; - delete [] texttitle_; - delete [] textsoftware_; - - textauthor_ = new char[strlen(author)+1]; - textdescription_ = new char[strlen(description)+1]; - textsoftware_ = new char[strlen(software)+1]; - texttitle_ = new char[strlen(title)+1]; - - strcpy(texttitle_, title); - strcpy(textauthor_, author); - strcpy(textdescription_, description); - strcpy(textsoftware_, software); -}; - -/////////////////////////////////////////////////////// -void pngwriter::close() -{ - FILE *fp; - png_structp png_ptr; - png_infop info_ptr; - - fp = fopen(filename_, "wb"); - if( fp == NULL) - { - std::cerr << " PNGwriter::close - ERROR **: Error creating file (fopen() returned NULL pointer)." << std::endl; - perror(" PNGwriter::close - ERROR **"); - return; - } - - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - info_ptr = png_create_info_struct(png_ptr); - png_init_io(png_ptr, fp); - if(compressionlevel_ != -2) - { - png_set_compression_level(png_ptr, compressionlevel_); - } - else - { - png_set_compression_level(png_ptr, PNGWRITER_DEFAULT_COMPRESSION); - } - - png_set_IHDR(png_ptr, info_ptr, width_, height_, - bit_depth_, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - - if(filegamma_ < 1.0e-1) - { - filegamma_ = 0.5; // Modified in 0.5.4 so as to be the same as the usual gamma. - } - - png_set_gAMA(png_ptr, info_ptr, filegamma_); - - time_t gmt; - png_time mod_time; - png_text text_ptr[5]; - time(&gmt); - png_convert_from_time_t(&mod_time, gmt); - png_set_tIME(png_ptr, info_ptr, &mod_time); - text_ptr[0].key = (char *)"Title"; - text_ptr[0].text = texttitle_; - text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE; - text_ptr[1].key = (char *)"Author"; - text_ptr[1].text = textauthor_; - text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE; - text_ptr[2].key = (char *)"Description"; - text_ptr[2].text = textdescription_; - text_ptr[2].compression = PNG_TEXT_COMPRESSION_NONE; - text_ptr[3].key = (char *)"Creation Time"; - text_ptr[3].text = png_convert_to_rfc1123(png_ptr, &mod_time); - text_ptr[3].compression = PNG_TEXT_COMPRESSION_NONE; - text_ptr[4].key = (char *)"Software"; - text_ptr[4].text = textsoftware_; - text_ptr[4].compression = PNG_TEXT_COMPRESSION_NONE; - png_set_text(png_ptr, info_ptr, text_ptr, 5); - - png_write_info(png_ptr, info_ptr); - png_write_image(png_ptr, graph_); - png_write_end(png_ptr, info_ptr); - png_destroy_write_struct(&png_ptr, &info_ptr); - fclose(fp); -} - -////////////////////////////////////////////////////// -void pngwriter::line(int xfrom, int yfrom, int xto, int yto, int red, int green,int blue) -{ - // Bresenham Algorithm. - // - int dy = yto - yfrom; - int dx = xto - xfrom; - int stepx, stepy; - - if (dy < 0) - { - dy = -dy; stepy = -1; - } - else - { - stepy = 1; - } - - if (dx < 0) - { - dx = -dx; stepx = -1; - } - else - { - stepx = 1; - } - dy <<= 1; // dy is now 2*dy - dx <<= 1; // dx is now 2*dx - - this->plot(xfrom,yfrom,red,green,blue); - - if (dx > dy) - { - int fraction = dy - (dx >> 1); - - while (xfrom != xto) - { - if (fraction >= 0) - { - yfrom += stepy; - fraction -= dx; - } - xfrom += stepx; - fraction += dy; - this->plot(xfrom,yfrom,red,green,blue); - } - } - else - { - int fraction = dx - (dy >> 1); - while (yfrom != yto) - { - if (fraction >= 0) - { - xfrom += stepx; - fraction -= dy; - } - yfrom += stepy; - fraction += dx; - this->plot(xfrom,yfrom,red,green,blue); - } - } - -} - -void pngwriter::line(int xfrom, int yfrom, int xto, int yto, double red, double green,double blue) -{ - this->line( xfrom, - yfrom, - xto, - yto, - int (red*65535), - int (green*65535), - int (blue*65535) - ); -} - -/////////////////////////////////////////////////////////////////////////////////////////// -void pngwriter::square(int xfrom, int yfrom, int xto, int yto, int red, int green, int blue) -{ - this->line(xfrom, yfrom, xfrom, yto, red, green, blue); - this->line(xto, yfrom, xto, yto, red, green, blue); - this->line(xfrom, yfrom, xto, yfrom, red, green, blue); - this->line(xfrom, yto, xto, yto, red, green, blue); -} - -void pngwriter::square(int xfrom, int yfrom, int xto, int yto, double red, double green, double blue) -{ - this->square( xfrom, yfrom, xto, yto, int(red*65535), int(green*65535), int(blue*65535)); -} - -////////////////////////////////////////////////////////////////////////////////////////////////// -void pngwriter::filledsquare(int xfrom, int yfrom, int xto, int yto, int red, int green, int blue) -{ - for(int caca = xfrom; caca line(caca, yfrom, caca, yto, red, green, blue); - } -} - -void pngwriter::filledsquare(int xfrom, int yfrom, int xto, int yto, double red, double green, double blue) -{ - this->filledsquare( xfrom, yfrom, xto, yto, int(red*65535), int(green*65535), int(blue*65535)); -} - -////////////////////////////////////////////////////////////////////////////////////////////////// -void pngwriter::circle(int xcentre, int ycentre, int radius, int red, int green, int blue) -{ - int x = 0; - int y = radius; - int p = (5 - radius*4)/4; - - circle_aux(xcentre, ycentre, x, y, red, green, blue); - while (x < y) - { - x++; - if (p < 0) - { - p += 2*x+1; - } - else - { - y--; - p += 2*(x-y)+1; - } - circle_aux(xcentre, ycentre, x, y, red, green, blue); - } -} - -void pngwriter::circle(int xcentre, int ycentre, int radius, double red, double green, double blue) -{ - this->circle(xcentre,ycentre,radius, int(red*65535), int(green*65535), int(blue*65535)); -} - -//////////////////////////////////////////////////////////// - -void pngwriter::circle_aux(int xcentre, int ycentre, int x, int y, int red, int green, int blue) -{ - if (x == 0) - { - this->plot( xcentre, ycentre + y, red, green, blue); - this->plot( xcentre, ycentre - y, red, green, blue); - this->plot( xcentre + y, ycentre, red, green, blue); - this->plot( xcentre - y, ycentre, red, green, blue); - } - else - if (x == y) - { - this->plot( xcentre + x, ycentre + y, red, green, blue); - this->plot( xcentre - x, ycentre + y, red, green, blue); - this->plot( xcentre + x, ycentre - y, red, green, blue); - this->plot( xcentre - x, ycentre - y, red, green, blue); - } - else - if (x < y) - { - this->plot( xcentre + x, ycentre + y, red, green, blue); - this->plot( xcentre - x, ycentre + y, red, green, blue); - this->plot( xcentre + x, ycentre - y, red, green, blue); - this->plot( xcentre - x, ycentre - y, red, green, blue); - this->plot( xcentre + y, ycentre + x, red, green, blue); - this->plot( xcentre - y, ycentre + x, red, green, blue); - this->plot( xcentre + y, ycentre - x, red, green, blue); - this->plot( xcentre - y, ycentre - x, red, green, blue); - } - -} - -//////////////////////////////////////////////////////////// -void pngwriter::filledcircle(int xcentre, int ycentre, int radius, int red, int green, int blue) -{ - for(int jjj = ycentre-radius; jjj< ycentre+radius+1; jjj++) - { - this->line(xcentre - int(sqrt((double)(radius*radius) - (-ycentre + jjj)*(-ycentre + jjj ))), jjj, - xcentre + int(sqrt((double)(radius*radius) - (-ycentre + jjj)*(-ycentre + jjj ))),jjj,red,green,blue); - } -} - -void pngwriter::filledcircle(int xcentre, int ycentre, int radius, double red, double green, double blue) -{ - this->filledcircle( xcentre, ycentre, radius, int(red*65535), int(green*65535), int(blue*65535)); -} - -////////////////Reading routines///////////////////// -///////////////////////////////////////////////// - -// Modified with Mikkel's patch -void pngwriter::readfromfile(char * name) -{ - FILE *fp; - png_structp png_ptr; - png_infop info_ptr; - unsigned char **image; - unsigned long width, height; - int bit_depth, color_type, interlace_type; - // png_uint_32 i; - // - fp = fopen (name,"rb"); - if (fp==NULL) - { - std::cerr << " PNGwriter::readfromfile - ERROR **: Error opening file \"" << std::flush; - std::cerr << name <readfromfile((char *)(name)); -} - -///////////////////////////////////////////////////////// -int pngwriter::check_if_png(char *file_name, FILE **fp) -{ - char sig[PNG_BYTES_TO_CHECK]; - - if ( /*(*fp = fopen(file_name, "rb")) */ *fp == NULL) // Fixed 10 10 04 - { - // exit(EXIT_FAILURE); - std::cerr << " PNGwriter::check_if_png - ERROR **: Could not open file " << file_name << " to read." << std::endl; - perror(" PNGwriter::check_if_png - ERROR **"); - return 0; - } - - if (fread(sig, 1, PNG_BYTES_TO_CHECK, *fp) != PNG_BYTES_TO_CHECK) - { - //exit(EXIT_FAILURE); - std::cerr << " PNGwriter::check_if_png - ERROR **: File " << file_name << " does not appear to be a valid PNG file." << std::endl; - perror(" PNGwriter::check_if_png - ERROR **"); - fclose(*fp); - return 0; - } - - if (png_sig_cmp( (png_bytep) sig, (png_size_t)0, PNG_BYTES_TO_CHECK) /*png_check_sig((png_bytep) sig, PNG_BYTES_TO_CHECK)*/ ) - { - std::cerr << " PNGwriter::check_if_png - ERROR **: File " << file_name << " does not appear to be a valid PNG file. png_check_sig() failed." << std::endl; - fclose(*fp); - return 0; - } - - - - return 1; //Success -} - -/////////////////////////////////////////////////////// -int pngwriter::read_png_info(FILE *fp, png_structp *png_ptr, png_infop *info_ptr) -{ - *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (*png_ptr == NULL) - { - std::cerr << " PNGwriter::read_png_info - ERROR **: Could not create read_struct." << std::endl; - fclose(fp); - return 0; - //exit(EXIT_FAILURE); - } - *info_ptr = png_create_info_struct(*png_ptr); - if (*info_ptr == NULL) - { - png_destroy_read_struct(png_ptr, (png_infopp)NULL, (png_infopp)NULL); - std::cerr << " PNGwriter::read_png_info - ERROR **: Could not create info_struct." << std::endl; - //exit(EXIT_FAILURE); - fclose(fp); - return 0; - } - if (setjmp((*png_ptr)->jmpbuf)) /*(setjmp(png_jmpbuf(*png_ptr)) )*////////////////////////////////////// - { - png_destroy_read_struct(png_ptr, info_ptr, (png_infopp)NULL); - std::cerr << " PNGwriter::read_png_info - ERROR **: This file may be a corrupted PNG file. (setjmp(*png_ptr)->jmpbf) failed)." << std::endl; - fclose(fp); - return 0; - //exit(EXIT_FAILURE); - } - png_init_io(*png_ptr, fp); - png_set_sig_bytes(*png_ptr, PNG_BYTES_TO_CHECK); - png_read_info(*png_ptr, *info_ptr); - - return 1; -} - -//////////////////////////////////////////////////////////// -int pngwriter::read_png_image(FILE *fp, png_structp png_ptr, png_infop info_ptr, - png_bytepp *image, png_uint_32 *width, png_uint_32 *height) -{ - unsigned int i,j; - - *width = png_get_image_width(png_ptr, info_ptr); - *height = png_get_image_height(png_ptr, info_ptr); - - if( width == NULL) - { - std::cerr << " PNGwriter::read_png_image - ERROR **: png_get_image_width() returned NULL pointer." << std::endl; - fclose(fp); - return 0; - } - - if( height == NULL) - { - std::cerr << " PNGwriter::read_png_image - ERROR **: png_get_image_height() returned NULL pointer." << std::endl; - fclose(fp); - return 0; - } - - if ((*image = (png_bytepp)malloc(*height * sizeof(png_bytep))) == NULL) - { - std::cerr << " PNGwriter::read_png_image - ERROR **: Could not allocate memory for reading image." << std::endl; - fclose(fp); - return 0; - //exit(EXIT_FAILURE); - } - for (i = 0; i < *height; i++) - { - (*image)[i] = (png_bytep)malloc(png_get_rowbytes(png_ptr, info_ptr)); - if ((*image)[i] == NULL) - { - for (j = 0; j < i; j++) free((*image)[j]); - free(*image); - fclose(fp); - std::cerr << " PNGwriter::read_png_image - ERROR **: Could not allocate memory for reading image." << std::endl; - return 0; - //exit(EXIT_FAILURE); - } - } - png_read_image(png_ptr, *image); - - return 1; -} - -/////////////////////////////////// -int pngwriter::getheight(void) -{ - return height_; -} - -int pngwriter::getwidth(void) -{ - return width_; -} - - -int pngwriter::getbitdepth(void) -{ - return bit_depth_; -} - -int pngwriter::getcolortype(void) -{ - return colortype_; -} - -double pngwriter::getgamma(void) -{ - return filegamma_; -} - -void pngwriter::setgamma(double gamma) -{ - filegamma_ = gamma; -} - -// The algorithms HSVtoRGB and RGBtoHSV were found at http://www.cs.rit.edu/~ncs/ -// which is a page that belongs to Nan C. Schaller, though -// these algorithms appear to be the work of Eugene Vishnevsky. -////////////////////////////////////////////// -void pngwriter::HSVtoRGB( double *r, double *g, double *b, double h, double s, double v ) -{ - // r,g,b values are from 0 to 1 - // h = [0,1], s = [0,1], v = [0,1] - // if s == 0, then h = -1 (undefined) - // - h = h*360.0; - - int i; - double f, p, q, t; - if( s == 0 ) - { - // achromatic (grey) - *r = *g = *b = v; - return; - } - - h /= 60; // sector 0 to 5 - i = int(floor( h )); - f = h - i; // factorial part of h - p = v * ( 1 - s ); - q = v * ( 1 - s * f ); - t = v * ( 1 - s * ( 1 - f ) ); - - switch( i ) - { - case 0: - *r = v; - *g = t; - *b = p; - break; - case 1: - *r = q; - *g = v; - *b = p; - break; - case 2: - *r = p; - *g = v; - *b = t; - break; - case 3: - *r = p; - *g = q; - *b = v; - break; - case 4: - *r = t; - *g = p; - *b = v; - break; - default: // case 5: - *r = v; - *g = p; - *b = q; - break; - } -} - -void pngwriter::RGBtoHSV( float r, float g, float b, float *h, float *s, float *v ) -{ - - float min=0.0; //These values are not used. - float max=1.0; - float delta; - - if( (r>=g)&&(r>=b) ) - { - max = r; - } - if( (g>=r)&&(g>=b) ) - { - max = g; - } - if( (b>=g)&&(b>=r) ) - { - max = b; - } - - if( (r<=g)&&(r<=b) ) - { - min = r; - } - if( (g<=r)&&(g<=b) ) - { - min = g; - } - if( (b<=g)&&(b<=r) ) - { - min = b; - } - - *v = max; // v - - delta = max - min; - - if( max != 0 ) - *s = delta / max; // s - else - { - - r = g = b = 0; // s = 0, v is undefined - *s = 0; - *h = -1; - return; - } - - if( r == max ) - *h = ( g - b ) / delta; // between yellow & magenta - else if( g == max ) - *h = 2 + ( b - r ) / delta; // between cyan & yellow - else - *h = 4 + ( r - g ) / delta; // between magenta & cyan - - *h *= 60; // degrees - if( *h < 0 ) - *h += 360; - -} - -// -////////////////////////////////////////////////////////////////////////////////// -void pngwriter::plotHSV(int x, int y, double hue, double saturation, double value) -{ - double red,green,blue; - double *redp; - double *greenp; - double *bluep; - - redp = &red; - greenp = &green; - bluep = &blue; - - HSVtoRGB(redp,greenp,bluep,hue,saturation,value); - plot(x,y,red,green,blue); -} - -void pngwriter::plotHSV(int x, int y, int hue, int saturation, int value) -{ - plotHSV(x, y, double(hue)/65535.0, double(saturation)/65535.0, double(value)/65535.0); -} - -// -////////////////////////////////////////////////////////////////////////////////// -double pngwriter::dreadHSV(int x, int y, int colour) -{ - if( (x>0)&&(x<=width_)&&(y>0)&&(y<=height_) ) - { - - float * huep; - float * saturationp; - float * valuep; - float red,green,blue; - float hue, saturation, value; - - red = float(dread(x,y,1)); - green = float(dread(x,y,2)); - blue = float(dread(x,y,3)); - - huep = &hue; - saturationp = &saturation; - valuep = &value; - - RGBtoHSV( red, green, blue, huep, saturationp, valuep ); - - if(colour == 1) - { - return double(hue)/360.0; - } - - else if(colour == 2) - { - return saturation; - } - - else if(colour == 3) - { - return value; - } - - std::cerr << " PNGwriter::dreadHSV - ERROR **: Called with wrong colour argument: should be 1, 2 or 3; was: " << colour << "." << std::endl; - } - return 0.0; -} - -// -////////////////////////////////////////////////////////////////////////////////// -int pngwriter::readHSV(int x, int y, int colour) -{ - if( (x>0)&&(x<=width_)&&(y>0)&&(y<=height_) ) - { - - float * huep; - float * saturationp; - float * valuep; - float red,green,blue; - float hue, saturation, value; - - red = float(dread(x,y,1)); - green = float(dread(x,y,2)); - blue = float(dread(x,y,3)); - - huep = &hue; - saturationp = &saturation; - valuep = &value; - - RGBtoHSV( red, green, blue, huep, saturationp, valuep ); - - if(colour == 1) - { - return int(65535*(double(hue)/360.0)); - } - - else if(colour == 2) - { - return int(65535*saturation); - } - - else if(colour == 3) - { - return int(65535*value); - } - - std::cerr << " PNGwriter::readHSV - ERROR **: Called with wrong colour argument: should be 1, 2 or 3; was: " << colour << "." << std::endl; - return 0; - } - else - { - return 0; - } -} - -void pngwriter::setcompressionlevel(int level) -{ - if( (level < -1)||(level > 9) ) - { - std::cerr << " PNGwriter::setcompressionlevel - ERROR **: Called with wrong compression level: should be -1 to 9, was: " << level << "." << std::endl; - } - compressionlevel_ = level; -} - -// An implementation of a Bezier curve. -void pngwriter::bezier( int startPtX, int startPtY, - int startControlX, int startControlY, - int endPtX, int endPtY, - int endControlX, int endControlY, - double red, double green, double blue) -{ - - double cx = 3.0*(startControlX - startPtX); - double bx = 3.0*(endControlX - startControlX) - cx; - double ax = double(endPtX - startPtX - cx - bx); - - double cy = 3.0*(startControlY - startPtY); - double by = 3.0*(endControlY - startControlY) - cy; - double ay = double(endPtY - startPtY - cy - by); - - double x,y,newx,newy; - x = startPtX; - y = startPtY; - - for(double t = 0.0; t<=1.005; t += 0.005) - { - newx = startPtX + t*(double(cx) + t*(double(bx) + t*(double(ax)))); - newy = startPtY + t*(double(cy) + t*(double(by) + t*(double(ay)))); - this->line(int(x),int(y),int(newx),int(newy),red,green,blue); - x = newx; - y = newy; - } -} - -//int version of bezier -void pngwriter::bezier( int startPtX, int startPtY, - int startControlX, int startControlY, - int endPtX, int endPtY, - int endControlX, int endControlY, - int red, int green, int blue) -{ - this->bezier( startPtX, startPtY, - startControlX, startControlY, - endPtX, endPtY, - endControlX, endControlY, - double(red)/65535.0, double(green)/65535.0, double(blue)/65535.0); -} - -/* -int pngwriter::getcompressionlevel(void) -{ - return png_get_compression_level(png_ptr); -} -*/ - -double pngwriter::version(void) -{ - const char *a = "Jeramy Webb (jeramyw@gmail.com), Mike Heller (mkheller@gmail.com)"; // For their generosity ;-) - char b = a[27]; - b++; - return (PNGWRITER_VERSION); -} - -void pngwriter::write_png(void) -{ - this->close(); -} - -#ifndef NO_FREETYPE - -// Freetype-based text rendering functions. -/////////////////////////////////////////// -void pngwriter::plot_text( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double red, double green, double blue) -{ - FT_Library library; - FT_Face face; - FT_Matrix matrix; // transformation matrix - FT_Vector pen; - - FT_UInt glyph_index; - FT_Error error; - - FT_Bool use_kerning; - FT_UInt previous = 0; - - /* Set up transformation Matrix */ - matrix.xx = (FT_Fixed)( cos(angle)*0x10000); /* It would make more sense to do this (below), but, bizzarely, */ - matrix.xy = (FT_Fixed)(-sin(angle)*0x10000); /* if one does, FT_Load_Glyph fails consistently. */ - matrix.yx = (FT_Fixed)( sin(angle)*0x10000); // matrix.yx = - matrix.xy; - matrix.yy = (FT_Fixed)( cos(angle)*0x10000); // matrix.yy = matrix.xx; - - /* Place starting coordinates in adequate form. */ - pen.x = x_start*64 ; - pen.y = (int)(y_start/64.0); - - /*Count the length of the string */ - int num_chars = strlen(text); - - /* Initialize FT Library object */ - error = FT_Init_FreeType( &library ); - if (error) { std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Could not init Library."<< std::endl; return;} - - /* Initialize FT face object */ - error = FT_New_Face( library,face_path,0,&face ); - if ( error == FT_Err_Unknown_File_Format ) { std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Font was opened, but type not supported."<< std::endl; return; } else if (error){ std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Could not find or load font file."<< std::endl; return; } - - /* Set the Char size */ - error = FT_Set_Char_Size( face, /* handle to face object */ - 0, /* char_width in 1/64th of points */ - fontsize*64, /* char_height in 1/64th of points */ - 100, /* horizontal device resolution */ - 100 ); /* vertical device resolution */ - - /* A way of accesing the glyph directly */ - FT_GlyphSlot slot = face->glyph; // a small shortcut - - /* Does the font file support kerning? */ - use_kerning = FT_HAS_KERNING( face ); - - int n; - for ( n = 0; n < num_chars; n++ ) - { - /* Convert character code to glyph index */ - glyph_index = FT_Get_Char_Index( face, text[n] ); - - /* Retrieve kerning distance and move pen position */ - if ( use_kerning && previous&& glyph_index ) - { - FT_Vector delta; - FT_Get_Kerning( face, - previous, - glyph_index, - ft_kerning_default, //FT_KERNING_DEFAULT, - &delta ); - - /* Transform this kerning distance into rotated space */ - pen.x += (int) (((double) delta.x)*cos(angle)); - pen.y += (int) (((double) delta.x)*( sin(angle))); - } - - /* Set transform */ - FT_Set_Transform( face, &matrix, &pen ); - -/*set char size*/ - - if (error) { std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Set char size error." << std::endl; return;}; - - /* Retrieve glyph index from character code */ - glyph_index = FT_Get_Char_Index( face, text[n] ); - - /* Load glyph image into the slot (erase previous one) */ - error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT ); - if (error) { std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Could not load glyph (in loop). (FreeType error "<< std::hex << error <<")." << std::endl; return;} - - /* Convert to an anti-aliased bitmap */ - // error = FT_Render_Glyph( face->glyph, FT_RENDER_MODE_NORMAL ); - error = FT_Render_Glyph( face->glyph, ft_render_mode_normal ); - if (error) { std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Render glyph error." << std::endl; return;} - - /* Now, draw to our target surface */ - my_draw_bitmap( &slot->bitmap, - slot->bitmap_left, - y_start + slot->bitmap_top, - red, - green, - blue ); - - /* Advance to the next position */ - pen.x += slot->advance.x; - pen.y += slot->advance.y; - - /* record current glyph index */ - previous = glyph_index; - } - - /* Free the face and the library objects */ - FT_Done_Face ( face ); - FT_Done_FreeType( library ); -} - -void pngwriter::plot_text_utf8( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double red, double green, double blue) -{ - FT_Library library; - FT_Face face; - FT_Matrix matrix; // transformation matrix - FT_Vector pen; - - FT_UInt glyph_index; - FT_Error error; - - FT_Bool use_kerning; - FT_UInt previous = 0; - - /* Set up transformation Matrix */ - matrix.xx = (FT_Fixed)( cos(angle)*0x10000); /* It would make more sense to do this (below), but, bizzarely, */ - matrix.xy = (FT_Fixed)(-sin(angle)*0x10000); /* if one does, FT_Load_Glyph fails consistently. */ - matrix.yx = (FT_Fixed)( sin(angle)*0x10000); // matrix.yx = - matrix.xy; - matrix.yy = (FT_Fixed)( cos(angle)*0x10000); // matrix.yy = matrix.xx; - - /* Place starting coordinates in adequate form. */ - pen.x = x_start*64 ; - pen.y = (int)(y_start/64.0); - - /*Count the length of the string */ - int num_bytes=0; - while(text[num_bytes]!=0) - { - num_bytes++; - } - - /* - std::cout << "Num bytes is: "<< num_bytes << std::endl; - */ - - //The array of ucs4 glyph indexes, which will by at most the number of bytes in the utf-8 file. - long * ucs4text; - ucs4text = new long[num_bytes+1]; - - unsigned char u,v,w,x,y,z; - - int num_chars=0; - - long iii=0; - - while(iiiglyph; // a small shortcut - - /* Does the font file support kerning? */ - use_kerning = FT_HAS_KERNING( face ); - - int n; - for ( n = 0; n < num_chars; n++ ) - { - /* Convert character code to glyph index */ - glyph_index = FT_Get_Char_Index( face, ucs4text[n] ); - - /* Retrieve kerning distance and move pen position */ - if ( use_kerning && previous&& glyph_index ) - { - FT_Vector delta; - FT_Get_Kerning( face, - previous, - glyph_index, - ft_kerning_default, //FT_KERNING_DEFAULT, - &delta ); - - /* Transform this kerning distance into rotated space */ - pen.x += (int) (((double) delta.x)*cos(angle)); - pen.y += (int) (((double) delta.x)*( sin(angle))); - } - - /* Set transform */ - FT_Set_Transform( face, &matrix, &pen ); - -/*set char size*/ - - if (error) { std::cerr << " PNGwriter::plot_text_utf8 - ERROR **: FreeType: Set char size error." << std::endl; return;}; - - /* Retrieve glyph index from character code */ - glyph_index = FT_Get_Char_Index( face, ucs4text[n] ); - - /* Load glyph image into the slot (erase previous one) */ - error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT ); - if (error) { std::cerr << " PNGwriter::plot_text_utf8 - ERROR **: FreeType: Could not load glyph (in loop). (FreeType error "<< std::hex << error <<")." << std::endl; return;} - - /* Convert to an anti-aliased bitmap */ - error = FT_Render_Glyph( face->glyph, ft_render_mode_normal ); - if (error) { std::cerr << " PNGwriter::plot_text_utf8 - ERROR **: FreeType: Render glyph error." << std::endl; return;} - - /* Now, draw to our target surface */ - my_draw_bitmap( &slot->bitmap, - slot->bitmap_left, - y_start + slot->bitmap_top, - red, - green, - blue ); - - /* Advance to the next position */ - pen.x += slot->advance.x; - pen.y += slot->advance.y; - - /* record current glyph index */ - previous = glyph_index; - } - - /* Free the face and the library objects */ - FT_Done_Face ( face ); - FT_Done_FreeType( library ); - - delete[] ucs4text; -} - -void pngwriter::plot_text( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, int red, int green, int blue) -{ - plot_text( face_path, fontsize, x_start, y_start, angle, text, ((double) red)/65535.0, ((double) green)/65535.0, ((double) blue)/65535.0 ); -} - -void pngwriter::plot_text_utf8( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, int red, int green, int blue) -{ - plot_text_utf8( face_path, fontsize, x_start, y_start, angle, text, ((double) red)/65535.0, ((double) green)/65535.0, ((double) blue)/65535.0 ); -} - -void pngwriter::my_draw_bitmap( FT_Bitmap * bitmap, int x, int y, double red, double green, double blue) -{ - double temp; - for(int j=1; jrows+1; j++) - { - for(int i=1; i< bitmap->width + 1; i++) - { - temp = (double)(bitmap->buffer[(j-1)*bitmap->width + (i-1)] )/255.0; - - if(temp) - { - this->plot(x + i, - y - j, - temp*red + (1-temp)*(this->dread(x+i,y-j,1)), - temp*green + (1-temp)*(this->dread(x+i,y-j,2)), - temp*blue + (1-temp)*(this->dread(x+i,y-j,3)) - ); - } - } - } -} - - - -//////////// Get text width - -//put in freetype section - -int pngwriter::get_text_width(char * face_path, int fontsize, char * text) -{ - - FT_Library library; - FT_Face face; - FT_Matrix matrix; // transformation matrix - FT_Vector pen; - - FT_UInt glyph_index; - FT_Error error; - - FT_Bool use_kerning; - FT_UInt previous = 0; - - /* Set up transformation Matrix */ - matrix.xx = (FT_Fixed)( 1.0*0x10000); /* It would make more sense to do this (below), but, bizzarely, */ - matrix.xy = (FT_Fixed)( 0.0*0x10000); /* if one does, FT_Load_Glyph fails consistently. */ - matrix.yx = (FT_Fixed)( 0.0*0x10000); // matrix.yx = - matrix.xy; - matrix.yy = (FT_Fixed)( 1.0*0x10000); // matrix.yy = matrix.xx; - - /* Place starting coordinates in adequate form. */ - pen.x = 0; - pen.y = 0; - - /*Count the length of the string */ - int num_chars = strlen(text); - - /* Initialize FT Library object */ - error = FT_Init_FreeType( &library ); - if (error) { std::cerr << " PNGwriter::get_text_width - ERROR **: FreeType: Could not init Library."<< std::endl; return 0;} - - /* Initialize FT face object */ - error = FT_New_Face( library,face_path,0,&face ); - if ( error == FT_Err_Unknown_File_Format ) { std::cerr << " PNGwriter::get_text_width - ERROR **: FreeType: Font was opened, but type not supported."<< std::endl; return 0; } else if (error){ std::cerr << " PNGwriter::get_text_width - ERROR **: FreeType: Could not find or load font file." << std::endl; return 0; } - - /* Set the Char size */ - error = FT_Set_Char_Size( face, /* handle to face object */ - 0, /* char_width in 1/64th of points */ - fontsize*64, /* char_height in 1/64th of points */ - 100, /* horizontal device resolution */ - 100 ); /* vertical device resolution */ - - /* A way of accesing the glyph directly */ - FT_GlyphSlot slot = face->glyph; // a small shortcut - - /* Does the font file support kerning? */ - use_kerning = FT_HAS_KERNING( face ); - - int n; - for ( n = 0; n < num_chars; n++ ) - { - /* Convert character code to glyph index */ - glyph_index = FT_Get_Char_Index( face, text[n] ); - - /* Retrieve kerning distance and move pen position */ - if ( use_kerning && previous&& glyph_index ) - { - FT_Vector delta; - FT_Get_Kerning( face, - previous, - glyph_index, - ft_kerning_default, //FT_KERNING_DEFAULT, - &delta ); - - /* Transform this kerning distance into rotated space */ - pen.x += (int) ( delta.x); - pen.y += 0; - } - - /* Set transform */ - FT_Set_Transform( face, &matrix, &pen ); - -/*set char size*/ - - if (error) { std::cerr << " PNGwriter::get_text_width - ERROR **: FreeType: Set char size error." << std::endl; return 0;}; - - /* Retrieve glyph index from character code */ - glyph_index = FT_Get_Char_Index( face, text[n] ); - - /* Load glyph image into the slot (erase previous one) */ - error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT ); - if (error) { std::cerr << " PNGwriter::get_text_width - ERROR **: FreeType: Could not load glyph (in loop). (FreeType error "<< std::hex << error <<")." << std::endl; return 0;} - - /* Convert to an anti-aliased bitmap */ - // error = FT_Render_Glyph( face->glyph, FT_RENDER_MODE_NORMAL ); - error = FT_Render_Glyph( face->glyph, ft_render_mode_normal ); - if (error) { std::cerr << " PNGwriter::get_text_width - ERROR **: FreeType: Render glyph error." << std::endl; return 0;} - - /* Now, draw to our target surface */ -/* my_draw_bitmap( &slot->bitmap, - slot->bitmap_left, - slot->bitmap_top, - red, - green, - blue ); -*/ - /* Advance to the next position */ - pen.x += slot->advance.x; -// std::cout << ((double) pen.x)/64.0 << std::endl; - pen.y += slot->advance.y; - - /* record current glyph index */ - previous = glyph_index; - } - - - /* Free the face and the library objects */ - FT_Done_Face ( face ); - FT_Done_FreeType( library ); - - return (int)( ((double)pen.x)/64.0 ); -} - - -int pngwriter::get_text_width_utf8(char * face_path, int fontsize, char * text) -{ - FT_Library library; - FT_Face face; - FT_Matrix matrix; // transformation matrix - FT_Vector pen; - - FT_UInt glyph_index; - FT_Error error; - - FT_Bool use_kerning; - FT_UInt previous = 0; - - /* Set up transformation Matrix */ - matrix.xx = (FT_Fixed)( 0x10000); /* It would make more sense to do this (below), but, bizzarely, */ - matrix.xy = (FT_Fixed)( 0*0x10000); /* if one does, FT_Load_Glyph fails consistently. */ - matrix.yx = (FT_Fixed)( 0*0x10000); // matrix.yx = - matrix.xy; - matrix.yy = (FT_Fixed)( 0x10000); // matrix.yy = matrix.xx; - - /* Place starting coordinates in adequate form. */ - pen.x = 0 ; - pen.y = 0; - - /*Count the length of the string */ - int num_bytes=0; - while(text[num_bytes]!=0) - { - num_bytes++; - } - - /* - std::cout << "Num bytes is: "<< num_bytes << std::endl; - */ - - //The array of ucs4 glyph indexes, which will by at most the number of bytes in the utf-8 file. - long * ucs4text; - ucs4text = new long[num_bytes+1]; - - unsigned char u,v,w,x,y,z; - - int num_chars=0; - - long iii=0; - - while(iiiglyph; // a small shortcut - - /* Does the font file support kerning? */ - use_kerning = FT_HAS_KERNING( face ); - - int n; - for ( n = 0; n < num_chars; n++ ) - { - /* Convert character code to glyph index */ - glyph_index = FT_Get_Char_Index( face, ucs4text[n] ); - - /* Retrieve kerning distance and move pen position */ - if ( use_kerning && previous&& glyph_index ) - { - FT_Vector delta; - FT_Get_Kerning( face, - previous, - glyph_index, - ft_kerning_default, //FT_KERNING_DEFAULT, - &delta ); - - /* Transform this kerning distance into rotated space */ - pen.x += (int) (delta.x); - pen.y += 0; - } - - /* Set transform */ - FT_Set_Transform( face, &matrix, &pen ); - -/*set char size*/ - - if (error) { std::cerr << " PNGwriter::get_text_width_utf8 - ERROR **: FreeType: Set char size error." << std::endl; return 0;}; - - /* Retrieve glyph index from character code */ - glyph_index = FT_Get_Char_Index( face, ucs4text[n] ); - - /* Load glyph image into the slot (erase previous one) */ - error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT ); - if (error) { std::cerr << " PNGwriter::get_text_width_utf8 - ERROR **: FreeType: Could not load glyph (in loop). (FreeType error "<< std::hex << error <<")." << std::endl; return 0;} - - /* Convert to an anti-aliased bitmap */ - error = FT_Render_Glyph( face->glyph, ft_render_mode_normal ); - if (error) { std::cerr << " PNGwriter::get_text_width_utf8 - ERROR **: FreeType: Render glyph error." << std::endl; return 0;} - - /* Now, draw to our target surface */ -/* my_draw_bitmap( &slot->bitmap, - slot->bitmap_left, - y_start + slot->bitmap_top, - red, - green, - blue ); -*/ - /* Advance to the next position */ - pen.x += slot->advance.x; - pen.y += slot->advance.y; - - /* record current glyph index */ - previous = glyph_index; - } - - /* Free the face and the library objects */ - FT_Done_Face ( face ); - FT_Done_FreeType( library ); - - delete[] ucs4text; - - return (int) (((double) pen.x)/64.0); -} - -/////////////// -#endif -#ifdef NO_FREETYPE - -void pngwriter::plot_text( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, int red, int green, int blue) -{ - std::cerr << " PNGwriter::plot_text - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl; - return; -} - -void pngwriter::plot_text( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double red, double green, double blue) -{ - std::cerr << " PNGwriter::plot_text - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl; - return; - -} - -void pngwriter::plot_text_utf8( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, int red, int green, int blue) -{ - std::cerr << " PNGwriter::plot_text_utf8 - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl; - return; -} - -void pngwriter::plot_text_utf8( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double red, double green, double blue) -{ - std::cerr << " PNGwriter::plot_text_utf8 - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl; - return; -} - -//////////// Get text width -int pngwriter::get_text_width(char * face_path, int fontsize, char * text) -{ - std::cerr << " PNGwriter::get_text_width - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl; - return 0; -} - - -int pngwriter::get_text_width_utf8(char * face_path, int fontsize, char * text) -{ - std::cerr << " PNGwriter::get_text_width_utf8 - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl; - return 0; -} - -/////////////// -#endif - -///////////////////////////////////// -int pngwriter::bilinear_interpolation_read(double x, double y, int colour) -{ - - int inty, intx; - inty = (int) ceil(y); - intx = (int) ceil(x); - - //inty = (int) floor(y) +1; - // intx = (int) floor(x) +1; - // - bool attop, atright; - attop = inty==this->height_; - atright = intx==this->width_; -/* - if( intx==this->width_ +1) - { - intx--; - // std::cout << "intx--" << std::endl; - - } - */ - /* - if(inty == this->height_ +1) - { - inty--; - // std::cout << "inty--" << std::endl; - } - */ - - if( (!attop)&&(!atright) ) - { - - double f,g,f1,g1; - f = 1.0 + x - ((double) intx); - g = 1.0 + y - ((double) inty); - f1 = 1.0 - f; - g1 = 1.0 - g; - - return (int) ( - f1*g1*this->read(intx, inty,colour) - + f*g1*this->read(intx+1,inty,colour) - +f1*g*this->read(intx,inty+1,colour) - + f*g*(this->read(intx+1,inty+1,colour)) - ); - } - - if( (atright)&&(!attop)) - { - - double f,g,f1,g1; - f = 1.0 + x - ((double) intx); - g = 1.0 + y - ((double) inty); - f1 = 1.0 - f; - g1 = 1.0 - g; - - return (int) ( - f1*g1*this->read(intx, inty,colour) - + f*g1*( 2*(this->read(intx,inty,colour)) - (this->read(intx-1,inty,colour)) ) - +f1*g*this->read(intx,inty+1,colour) - + f*g*(2*(this->read(intx,inty+1,colour)) - (this->read(intx-1,inty+1,colour))) - ); - } - - if((attop)&&(!atright)) - { - double f,g,f1,g1; - f = 1.0 + x - ((double) intx); - g = 1.0 + y - ((double) inty); - f1 = 1.0 - f; - g1 = 1.0 - g; - - return (int) ( - f1*g1*this->read(intx, inty,colour) - + f*g1*this->read(intx+1,inty,colour) - +f1*g*( 2*(this->read(intx,inty,colour)) - this->read(intx,inty-1,colour) ) - + f*g*( 2*(this->read(intx+1,inty,colour)) - this->read(intx+1,inty-1,colour)) - ); - } - - double f,g,f1,g1; - f = 1.0 + x - ((double) intx); - g = 1.0 + y - ((double) inty); - f1 = 1.0 - f; - g1 = 1.0 - g; - - return (int) ( - f1*g1*this->read(intx, inty,colour) - + f*g1*( 2*(this->read(intx,inty,colour)) - (this->read(intx-1,inty,colour)) ) - +f1*g*( 2*(this->read(intx,inty,colour)) - this->read(intx,inty-1,colour) ) - + f*g*( 2*( 2*(this->read(intx,inty,colour)) - (this->read(intx-1,inty,colour)) ) - ( 2*(this->read(intx,inty-1,colour)) - (this->read(intx-1,inty-1,colour)) )) - ); - - /* - return (int) ( - f1*g1*this->read(intx, inty,colour) - + f*g1*this->read(intx+1,inty,colour) - +f1*g*this->read(intx,inty+1,colour) - + f*g*this->read(intx+1, inty+1,colour) - ); - * */ - -}; - -double pngwriter::bilinear_interpolation_dread(double x, double y, int colour) -{ - return double(this->bilinear_interpolation_read(x,y,colour))/65535.0; -}; - -void pngwriter::plot_blend(int x, int y, double opacity, int red, int green, int blue) -{ - this->plot(x, y, - (int)( opacity*red + this->read(x,y,1)*(1.0-opacity)), - (int)( opacity*green + this->read(x,y,2)*(1.0-opacity)), - (int)( opacity*blue + this->read(x,y,3)*(1.0-opacity)) - ); -}; - -void pngwriter::plot_blend(int x, int y, double opacity, double red, double green, double blue) -{ - this->plot_blend(x, y, opacity, (int) (65535*red), (int) (65535*green), (int) (65535*blue)); -}; - -void pngwriter::invert(void) -{ - // int temp1, temp2, temp3; - double temp11, temp22, temp33; - - for(int jjj = 1; jjj <= (this->height_); jjj++) - { - for(int iii = 1; iii <= (this->width_); iii++) - { - /* temp11 = (this->read(iii,jjj,1)); - temp22 = (this->read(iii,jjj,2)); - temp33 = (this->read(iii,jjj,3)); - * - this->plot(iii,jjj, - ((double)(65535 - temp11))/65535.0, - ((double)(65535 - temp22))/65535.0, - ((double)(65535 - temp33))/65535.0 - ); - * - */ - temp11 = (this->read(iii,jjj,1)); - temp22 = (this->read(iii,jjj,2)); - temp33 = (this->read(iii,jjj,3)); - - this->plot(iii,jjj, - (int)(65535 - temp11), - (int)(65535 - temp22), - (int)(65535 - temp33) - ); - - } - } -} - -void pngwriter::resize(int width, int height) -{ - - for (int jjj = 0; jjj < height_; jjj++) free(graph_[jjj]); - free(graph_); - - width_ = width; - height_ = height; - backgroundcolour_ = 0; - - graph_ = (png_bytepp)malloc(height_ * sizeof(png_bytep)); - if(graph_ == NULL) - { - std::cerr << " PNGwriter::resize - ERROR **: Not able to allocate memory for image." << std::endl; - } - - for (int kkkk = 0; kkkk < height_; kkkk++) - { - graph_[kkkk] = (png_bytep)malloc(6*width_ * sizeof(png_byte)); - if(graph_[kkkk] == NULL) - { - std::cerr << " PNGwriter::resize - ERROR **: Not able to allocate memory for image." << std::endl; - } - } - - if(graph_ == NULL) - { - std::cerr << " PNGwriter::resize - ERROR **: Not able to allocate memory for image." << std::endl; - } - - int tempindex; - for(int hhh = 0; hhhdread(xstart,ystart,1) != boundary_red) || - (this->dread(xstart,ystart,2) != boundary_green) || - (this->dread(xstart,ystart,3) != boundary_blue) - ) - && - ( - (this->dread(xstart,ystart,1) != fill_red) || - (this->dread(xstart,ystart,2) != fill_green) || - (this->dread(xstart,ystart,3) != fill_blue) - ) - && - (xstart >0)&&(xstart <= width_)&&(ystart >0)&&(ystart <= height_) - ) - { - this->plot(xstart, ystart, fill_red, fill_green, fill_blue); - boundary_fill(xstart+1, ystart, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ; - boundary_fill(xstart, ystart+1, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ; - boundary_fill(xstart, ystart-1, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ; - boundary_fill(xstart-1, ystart, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ; - } -} - -//no int version needed -void pngwriter::flood_fill_internal(int xstart, int ystart, double start_red, double start_green, double start_blue, double fill_red, double fill_green, double fill_blue) -{ - if( ( - (this->dread(xstart,ystart,1) == start_red) && - (this->dread(xstart,ystart,2) == start_green) && - (this->dread(xstart,ystart,3) == start_blue) - ) - && - ( - (this->dread(xstart,ystart,1) != fill_red) || - (this->dread(xstart,ystart,2) != fill_green) || - (this->dread(xstart,ystart,3) != fill_blue) - ) - && - (xstart >0)&&(xstart <= width_)&&(ystart >0)&&(ystart <= height_) - ) - { - this->plot(xstart, ystart, fill_red, fill_green, fill_blue); - flood_fill_internal( xstart+1, ystart, start_red, start_green, start_blue, fill_red, fill_green, fill_blue); - flood_fill_internal( xstart-1, ystart, start_red, start_green, start_blue, fill_red, fill_green, fill_blue); - flood_fill_internal( xstart, ystart+1, start_red, start_green, start_blue, fill_red, fill_green, fill_blue); - flood_fill_internal( xstart, ystart-1, start_red, start_green, start_blue, fill_red, fill_green, fill_blue); - } - -} - -//int version -void pngwriter::boundary_fill(int xstart, int ystart, int boundary_red,int boundary_green,int boundary_blue,int fill_red, int fill_green, int fill_blue) -{ - - this->boundary_fill( xstart, ystart, - ((double) boundary_red)/65535.0, - ((double) boundary_green)/65535.0, - ((double) boundary_blue)/65535.0, - ((double) fill_red)/65535.0, - ((double) fill_green)/65535.0, - ((double) fill_blue)/65535.0 - ); -} - -void pngwriter::flood_fill(int xstart, int ystart, double fill_red, double fill_green, double fill_blue) -{ - flood_fill_internal( xstart, ystart, this->dread(xstart,ystart,1),this->dread(xstart,ystart,2),this->dread(xstart,ystart,3), fill_red, fill_green, fill_blue); -} - -//int version -void pngwriter::flood_fill(int xstart, int ystart, int fill_red, int fill_green, int fill_blue) -{ - this->flood_fill( xstart, ystart, - ((double) fill_red)/65535.0, - ((double) fill_green)/65535.0, - ((double) fill_blue)/65535.0 - ); -} - -void pngwriter::polygon( int * points, int number_of_points, double red, double green, double blue) -{ - if( (number_of_points<1)||(points ==NULL)) - { - std::cerr << " PNGwriter::polygon - ERROR **: Number of points is zero or negative, or array is NULL." << std::endl; - return; - } - - for(int k=0;k< number_of_points-1; k++) - { - this->line(points[2*k],points[2*k+1],points[2*k+2],points[2*k+3], red, green, blue); - } -} - -//int version -void pngwriter::polygon( int * points, int number_of_points, int red, int green, int blue) -{ - this->polygon(points, number_of_points, - ((double) red)/65535.0, - ((double) green)/65535.0, - ((double) blue)/65535.0 - ); -} - -void pngwriter::plotCMYK(int x, int y, double cyan, double magenta, double yellow, double black) -{ -/*CMYK to RGB: - * ----------- - * red = 255 - minimum(255,((cyan/255) * (255 - black) + black)) - * green = 255 - minimum(255,((magenta/255) * (255 - black) + black)) - * blue = 255 - minimum(255,((yellow/255) * (255 - black) + black)) - * */ - - if(cyan<0.0) - { - cyan = 0.0; - } - if(magenta<0.0) - { - magenta = 0.0; - } - if(yellow<0.0) - { - yellow = 0.0; - } - if(black<0.0) - { - black = 0.0; - } - - if(cyan>1.0) - { - cyan = 1.0; - } - if(magenta>1.0) - { - magenta = 1.0; - } - if(yellow>1.0) - { - yellow = 1.0; - } - if(black>1.0) - { - black = 1.0; - } - - double red, green, blue, minr, ming, minb, iblack; - - iblack = 1.0 - black; - - minr = 1.0; - ming = 1.0; - minb = 1.0; - - if( (cyan*iblack + black)<1.0 ) - { - minr = cyan*iblack + black; - } - - if( (magenta*iblack + black)<1.0 ) - { - ming = magenta*iblack + black; - } - - if( (yellow*iblack + black)<1.0 ) - { - minb = yellow*iblack + black; - } - - red = 1.0 - minr; - green = 1.0 - ming; - blue = 1.0 - minb; - - this->plot(x,y,red, green, blue); - -} - -//int version -void pngwriter::plotCMYK(int x, int y, int cyan, int magenta, int yellow, int black) -{ - this->plotCMYK( x, y, - ((double) cyan)/65535.0, - ((double) magenta)/65535.0, - ((double) yellow)/65535.0, - ((double) black)/65535.0 - ); -} - -double pngwriter::dreadCMYK(int x, int y, int colour) -{ -/* - * Black = minimum(1-Red,1-Green,1-Blue) - * Cyan = (1-Red-Black)/(1-Black) - * Magenta = (1-Green-Black)/(1-Black) - * Yellow = (1-Blue-Black)/(1-Black) - * - * */ - if((colour !=1)&&(colour !=2)&&(colour !=3)&&(colour !=4)) - { - std::cerr << " PNGwriter::dreadCMYK - WARNING **: Invalid argument: should be 1, 2, 3 or 4, is " << colour << std::endl; - return 0; - } - - double black, red, green, blue, ired, igreen, iblue, iblack; - //add error detection here - // not much to detect, really - red = this->dread(x, y, 1); - green = this->dread(x, y, 2); - blue = this->dread(x, y, 3); - - ired = 1.0 - red; - igreen = 1.0 - green; - iblue = 1.0 - blue; - - black = ired; - - //black is the mimimum of inverse RGB colours, and if they are all equal, it is the inverse of red. - if( (igreendread(x, y, 1); - green = this->dread(x, y, 2); - blue = this->dread(x, y, 3); - - ired = 1.0 - red; - igreen = 1.0 - green; - iblue = 1.0 - blue; - - black = ired; - - //black is the mimimum of inverse RGB colours, and if they are all equal, it is the inverse of red. - if( (igreenbilinear_interpolation_read(readx, ready, 1); - green = this->bilinear_interpolation_read(readx, ready, 2); - blue = this->bilinear_interpolation_read(readx, ready, 3); - temp.plot(x, y, red, green, blue); - - } - } - - // From here on, the process is the same for all scale functions. - //Get data out of temp and into this's storage. - - //Resize this instance - // Delete current storage. - for (int jjj = 0; jjj < height_; jjj++) free(graph_[jjj]); - free(graph_); - - //New image will have bit depth 16, regardless of original bit depth. - bit_depth_ = 16; - - // New width and height will be the scaled width and height - width_ = scaledw; - height_ = scaledh; - backgroundcolour_ = 0; - - graph_ = (png_bytepp)malloc(height_ * sizeof(png_bytep)); - if(graph_ == NULL) - { - std::cerr << " PNGwriter::scale_k - ERROR **: Not able to allocate memory for image." << std::endl; - } - - for (int kkkk = 0; kkkk < height_; kkkk++) - { - graph_[kkkk] = (png_bytep)malloc(6*width_ * sizeof(png_byte)); - if(graph_[kkkk] == NULL) - { - std::cerr << " PNGwriter::scale_k - ERROR **: Not able to allocate memory for image." << std::endl; - } - } - - if(graph_ == NULL) - { - std::cerr << " PNGwriter::scale_k - ERROR **: Not able to allocate memory for image." << std::endl; - } - - //This instance now has a new, resized storage space. - - //Copy the temp date into this's storage. - int tempindex; - for(int hhh = 0; hhhbilinear_interpolation_read(readx, ready, 1); - green = this->bilinear_interpolation_read(readx, ready, 2); - blue = this->bilinear_interpolation_read(readx, ready, 3); - temp.plot(x, y, red, green, blue); - - } - } - // From here on, the process is the same for all scale functions. - //Get data out of temp and into this's storage. - - //Resize this instance - // Delete current storage. - for (int jjj = 0; jjj < height_; jjj++) free(graph_[jjj]); - free(graph_); - - //New image will have bit depth 16, regardless of original bit depth. - bit_depth_ = 16; - - // New width and height will be the scaled width and height - width_ = scaledw; - height_ = scaledh; - backgroundcolour_ = 0; - - graph_ = (png_bytepp)malloc(height_ * sizeof(png_bytep)); - if(graph_ == NULL) - { - std::cerr << " PNGwriter::scale_kxky - ERROR **: Not able to allocate memory for image." << std::endl; - } - - for (int kkkk = 0; kkkk < height_; kkkk++) - { - graph_[kkkk] = (png_bytep)malloc(6*width_ * sizeof(png_byte)); - if(graph_[kkkk] == NULL) - { - std::cerr << " PNGwriter::scale_kxky - ERROR **: Not able to allocate memory for image." << std::endl; - } - } - - if(graph_ == NULL) - { - std::cerr << " PNGwriter::scale_kxky - ERROR **: Not able to allocate memory for image." << std::endl; - } - - //This instance now has a new, resized storage space. - - //Copy the temp date into this's storage. - int tempindex; - for(int hhh = 0; hhhbilinear_interpolation_read(readx, ready, 1); - green = this->bilinear_interpolation_read(readx, ready, 2); - blue = this->bilinear_interpolation_read(readx, ready, 3); - temp.plot(x, y, red, green, blue); - - } - } - - // From here on, the process is the same for all scale functions. - //Get data out of temp and into this's storage. - - //Resize this instance - // Delete current storage. - for (int jjj = 0; jjj < height_; jjj++) free(graph_[jjj]); - free(graph_); - - //New image will have bit depth 16, regardless of original bit depth. - bit_depth_ = 16; - - // New width and height will be the scaled width and height - width_ = finalwidth; - height_ = finalheight; - backgroundcolour_ = 0; - - graph_ = (png_bytepp)malloc(height_ * sizeof(png_bytep)); - if(graph_ == NULL) - { - std::cerr << " PNGwriter::scale_wh - ERROR **: Not able to allocate memory for image." << std::endl; - } - - for (int kkkk = 0; kkkk < height_; kkkk++) - { - graph_[kkkk] = (png_bytep)malloc(6*width_ * sizeof(png_byte)); - if(graph_[kkkk] == NULL) - { - std::cerr << " PNGwriter::scale_wh - ERROR **: Not able to allocate memory for image." << std::endl; - } - } - - if(graph_ == NULL) - { - std::cerr << " PNGwriter::scale_wh - ERROR **: Not able to allocate memory for image." << std::endl; - } - - //This instance now has a new, resized storage space. - - //Copy the temp date into this's storage. - int tempindex; - for(int hhh = 0; hhhplot_blend(xfrom,yfrom,opacity, red,green,blue); - - if (dx > dy) - { - int fraction = dy - (dx >> 1); - - while (xfrom != xto) - { - if (fraction >= 0) - { - yfrom += stepy; - fraction -= dx; - } - xfrom += stepx; - fraction += dy; - this->plot_blend(xfrom,yfrom,opacity, red,green,blue); - } - } - else - { - int fraction = dx - (dy >> 1); - while (yfrom != yto) - { - if (fraction >= 0) - { - xfrom += stepx; - fraction -= dy; - } - yfrom += stepy; - fraction += dx; - this->plot_blend(xfrom,yfrom, opacity, red,green,blue); - } - } - -} - -void pngwriter::line_blend(int xfrom, int yfrom, int xto, int yto, double opacity, double red, double green,double blue) -{ - this->line_blend( xfrom, - yfrom, - xto, - yto, - opacity, - int (red*65535), - int (green*65535), - int (blue*65535) - ); - -} - -void pngwriter::square_blend(int xfrom, int yfrom, int xto, int yto, double opacity, int red, int green,int blue) -{ - this->line_blend(xfrom, yfrom, xfrom, yto, opacity, red, green, blue); - this->line_blend(xto, yfrom, xto, yto, opacity, red, green, blue); - this->line_blend(xfrom, yfrom, xto, yfrom, opacity, red, green, blue); - this->line_blend(xfrom, yto, xto, yto, opacity, red, green, blue); -} - -void pngwriter::square_blend(int xfrom, int yfrom, int xto, int yto, double opacity, double red, double green,double blue) -{ - this->square_blend( xfrom, yfrom, xto, yto, opacity, int(red*65535), int(green*65535), int(blue*65535)); -} - -void pngwriter::filledsquare_blend(int xfrom, int yfrom, int xto, int yto, double opacity, int red, int green,int blue) -{ - for(int caca = xfrom; caca line_blend(caca, yfrom, caca, yto, opacity, red, green, blue); - } - -} - -void pngwriter::filledsquare_blend(int xfrom, int yfrom, int xto, int yto, double opacity, double red, double green,double blue) -{ - this->filledsquare_blend( xfrom, yfrom, xto, yto, opacity, int(red*65535), int(green*65535), int(blue*65535)); -} - -void pngwriter::circle_aux_blend(int xcentre, int ycentre, int x, int y, double opacity, int red, int green, int blue) -{ - if (x == 0) - { - this->plot_blend( xcentre, ycentre + y, opacity, red, green, blue); - this->plot_blend( xcentre, ycentre - y, opacity, red, green, blue); - this->plot_blend( xcentre + y, ycentre, opacity, red, green, blue); - this->plot_blend( xcentre - y, ycentre, opacity, red, green, blue); - } - else - if (x == y) - { - this->plot_blend( xcentre + x, ycentre + y, opacity, red, green, blue); - this->plot_blend( xcentre - x, ycentre + y, opacity, red, green, blue); - this->plot_blend( xcentre + x, ycentre - y, opacity, red, green, blue); - this->plot_blend( xcentre - x, ycentre - y, opacity, red, green, blue); - } - else - if (x < y) - { - this->plot_blend( xcentre + x, ycentre + y, opacity, red, green, blue); - this->plot_blend( xcentre - x, ycentre + y, opacity, red, green, blue); - this->plot_blend( xcentre + x, ycentre - y, opacity, red, green, blue); - this->plot_blend( xcentre - x, ycentre - y, opacity, red, green, blue); - this->plot_blend( xcentre + y, ycentre + x, opacity, red, green, blue); - this->plot_blend( xcentre - y, ycentre + x, opacity, red, green, blue); - this->plot_blend( xcentre + y, ycentre - x, opacity, red, green, blue); - this->plot_blend( xcentre - y, ycentre - x, opacity, red, green, blue); - } - -} -// - -void pngwriter::circle_blend(int xcentre, int ycentre, int radius, double opacity, int red, int green, int blue) -{ - int x = 0; - int y = radius; - int p = (5 - radius*4)/4; - - circle_aux_blend(xcentre, ycentre, x, y, opacity, red, green, blue); - while (x < y) - { - x++; - if (p < 0) - { - p += 2*x+1; - } - else - { - y--; - p += 2*(x-y)+1; - } - circle_aux_blend(xcentre, ycentre, x, y, opacity, red, green, blue); - } - -} - -void pngwriter::circle_blend(int xcentre, int ycentre, int radius, double opacity, double red, double green, double blue) -{ - this->circle_blend(xcentre,ycentre,radius, opacity, int(red*65535), int(green*65535), int(blue*65535)); -} - -void pngwriter::filledcircle_blend(int xcentre, int ycentre, int radius, double opacity, int red, int green, int blue) -{ - for(int jjj = ycentre-radius; jjj< ycentre+radius+1; jjj++) - { - this->line_blend(xcentre - int(sqrt((double)(radius*radius) - (-ycentre + jjj)*(-ycentre + jjj ))), jjj, - xcentre + int(sqrt((double)(radius*radius) - (-ycentre + jjj)*(-ycentre + jjj ))),jjj, opacity, red,green,blue); - } - -} - -void pngwriter::filledcircle_blend(int xcentre, int ycentre, int radius, double opacity, double red, double green, double blue) -{ - this->filledcircle_blend( xcentre, ycentre, radius, opacity, int(red*65535), int(green*65535), int(blue*65535)); -} - -void pngwriter::bezier_blend( int startPtX, int startPtY, - int startControlX, int startControlY, - int endPtX, int endPtY, - int endControlX, int endControlY, - double opacity, - double red, double green, double blue) -{ - - double cx = 3.0*(startControlX - startPtX); - double bx = 3.0*(endControlX - startControlX) - cx; - double ax = double(endPtX - startPtX - cx - bx); - - double cy = 3.0*(startControlY - startPtY); - double by = 3.0*(endControlY - startControlY) - cy; - double ay = double(endPtY - startPtY - cy - by); - - double x,y,newx,newy; - x = startPtX; - y = startPtY; - - for(double t = 0.0; t<=1.005; t += 0.005) - { - newx = startPtX + t*(double(cx) + t*(double(bx) + t*(double(ax)))); - newy = startPtY + t*(double(cy) + t*(double(by) + t*(double(ay)))); - this->line_blend(int(x),int(y),int(newx),int(newy),opacity, red,green,blue); - x = newx; - y = newy; - } -} - -void pngwriter::bezier_blend( int startPtX, int startPtY, - int startControlX, int startControlY, - int endPtX, int endPtY, - int endControlX, int endControlY, - double opacity, - int red, int green, int blue) -{ - this->bezier_blend( startPtX, startPtY, - startControlX, startControlY, - endPtX, endPtY, - endControlX, endControlY, - opacity, - double(red)/65535.0, double(green)/65535.0, double(blue)/65535.0); - -} - -///////////////////////////// -#ifndef NO_FREETYPE - -// Freetype-based text rendering functions. -/////////////////////////////////////////// -void pngwriter::plot_text_blend( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double opacity, double red, double green, double blue) -{ - FT_Library library; - FT_Face face; - FT_Matrix matrix; // transformation matrix - FT_Vector pen; - - FT_UInt glyph_index; - FT_Error error; - - FT_Bool use_kerning; - FT_UInt previous = 0; - - /* Set up transformation Matrix */ - matrix.xx = (FT_Fixed)( cos(angle)*0x10000); /* It would make more sense to do this (below), but, bizzarely, */ - matrix.xy = (FT_Fixed)(-sin(angle)*0x10000); /* if one does, FT_Load_Glyph fails consistently. */ - matrix.yx = (FT_Fixed)( sin(angle)*0x10000); // matrix.yx = - matrix.xy; - matrix.yy = (FT_Fixed)( cos(angle)*0x10000); // matrix.yy = matrix.xx; - - /* Place starting coordinates in adequate form. */ - pen.x = x_start*64 ; - pen.y = (int)(y_start/64.0); - - /*Count the length of the string */ - int num_chars = strlen(text); - - /* Initialize FT Library object */ - error = FT_Init_FreeType( &library ); - if (error) { std::cerr << " PNGwriter::plot_text_blend - ERROR **: FreeType: Could not init Library."<< std::endl; return;} - - /* Initialize FT face object */ - error = FT_New_Face( library,face_path,0,&face ); - if ( error == FT_Err_Unknown_File_Format ) { std::cerr << " PNGwriter::plot_text_blend - ERROR **: FreeType: Font was opened, but type not supported."<< std::endl; return; } else if (error){ std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Could not find or load font file."<< std::endl; return; } - - /* Set the Char size */ - error = FT_Set_Char_Size( face, /* handle to face object */ - 0, /* char_width in 1/64th of points */ - fontsize*64, /* char_height in 1/64th of points */ - 100, /* horizontal device resolution */ - 100 ); /* vertical device resolution */ - - /* A way of accesing the glyph directly */ - FT_GlyphSlot slot = face->glyph; // a small shortcut - - /* Does the font file support kerning? */ - use_kerning = FT_HAS_KERNING( face ); - - int n; - for ( n = 0; n < num_chars; n++ ) - { - /* Convert character code to glyph index */ - glyph_index = FT_Get_Char_Index( face, text[n] ); - - /* Retrieve kerning distance and move pen position */ - if ( use_kerning && previous&& glyph_index ) - { - FT_Vector delta; - FT_Get_Kerning( face, - previous, - glyph_index, - ft_kerning_default, //FT_KERNING_DEFAULT, - &delta ); - - /* Transform this kerning distance into rotated space */ - pen.x += (int) (((double) delta.x)*cos(angle)); - pen.y += (int) (((double) delta.x)*( sin(angle))); - } - - /* Set transform */ - FT_Set_Transform( face, &matrix, &pen ); - -/*set char size*/ - - if (error) { std::cerr << " PNGwriter::plot_text_blend - ERROR **: FreeType: Set char size error." << std::endl; return;}; - - /* Retrieve glyph index from character code */ - glyph_index = FT_Get_Char_Index( face, text[n] ); - - /* Load glyph image into the slot (erase previous one) */ - error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT ); - if (error) { std::cerr << " PNGwriter::plot_text_blend - ERROR **: FreeType: Could not load glyph (in loop). (FreeType error "<< std::hex << error <<")." << std::endl; return;} - - /* Convert to an anti-aliased bitmap */ - // error = FT_Render_Glyph( face->glyph, FT_RENDER_MODE_NORMAL ); - error = FT_Render_Glyph( face->glyph, ft_render_mode_normal ); - if (error) { std::cerr << " PNGwriter::plot_text_blend - ERROR **: FreeType: Render glyph error." << std::endl; return;} - - /* Now, draw to our target surface */ - my_draw_bitmap_blend( &slot->bitmap, - slot->bitmap_left, - y_start + slot->bitmap_top, - opacity, - red, - green, - blue ); - - /* Advance to the next position */ - pen.x += slot->advance.x; - pen.y += slot->advance.y; - - /* record current glyph index */ - previous = glyph_index; - } - - /* Free the face and the library objects */ - FT_Done_Face ( face ); - FT_Done_FreeType( library ); -} - -void pngwriter::plot_text_utf8_blend( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double opacity, double red, double green, double blue) -{ - FT_Library library; - FT_Face face; - FT_Matrix matrix; // transformation matrix - FT_Vector pen; - - FT_UInt glyph_index; - FT_Error error; - - FT_Bool use_kerning; - FT_UInt previous = 0; - - /* Set up transformation Matrix */ - matrix.xx = (FT_Fixed)( cos(angle)*0x10000); /* It would make more sense to do this (below), but, bizzarely, */ - matrix.xy = (FT_Fixed)(-sin(angle)*0x10000); /* if one does, FT_Load_Glyph fails consistently. */ - matrix.yx = (FT_Fixed)( sin(angle)*0x10000); // matrix.yx = - matrix.xy; - matrix.yy = (FT_Fixed)( cos(angle)*0x10000); // matrix.yy = matrix.xx; - - /* Place starting coordinates in adequate form. */ - pen.x = x_start*64 ; - pen.y = (int)(y_start/64.0); - - /*Count the length of the string */ - int num_bytes=0; - while(text[num_bytes]!=0) - { - num_bytes++; - } - - /* - std::cout << "Num bytes is: "<< num_bytes << std::endl; - */ - - //The array of ucs4 glyph indexes, which will by at most the number of bytes in the utf-8 file. - long * ucs4text; - ucs4text = new long[num_bytes+1]; - - unsigned char u,v,w,x,y,z; - - int num_chars=0; - - long iii=0; - - while(iiiglyph; // a small shortcut - - /* Does the font file support kerning? */ - use_kerning = FT_HAS_KERNING( face ); - - int n; - for ( n = 0; n < num_chars; n++ ) - { - /* Convert character code to glyph index */ - glyph_index = FT_Get_Char_Index( face, ucs4text[n] ); - - /* Retrieve kerning distance and move pen position */ - if ( use_kerning && previous&& glyph_index ) - { - FT_Vector delta; - FT_Get_Kerning( face, - previous, - glyph_index, - ft_kerning_default, //FT_KERNING_DEFAULT, - &delta ); - - /* Transform this kerning distance into rotated space */ - pen.x += (int) (((double) delta.x)*cos(angle)); - pen.y += (int) (((double) delta.x)*( sin(angle))); - } - - /* Set transform */ - FT_Set_Transform( face, &matrix, &pen ); - -/*set char size*/ - - if (error) { std::cerr << " PNGwriter::plot_text_utf8_blend - ERROR **: FreeType: Set char size error." << std::endl; return;}; - - /* Retrieve glyph index from character code */ - glyph_index = FT_Get_Char_Index( face, ucs4text[n] ); - - /* Load glyph image into the slot (erase previous one) */ - error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT ); - if (error) { std::cerr << " PNGwriter::plot_text_utf8_blend - ERROR **: FreeType: Could not load glyph (in loop). (FreeType error "<< std::hex << error <<")." << std::endl; return;} - - /* Convert to an anti-aliased bitmap */ - error = FT_Render_Glyph( face->glyph, ft_render_mode_normal ); - if (error) { std::cerr << " PNGwriter::plot_text_utf8_blend - ERROR **: FreeType: Render glyph error." << std::endl; return;} - - /* Now, draw to our target surface */ - my_draw_bitmap_blend( &slot->bitmap, - slot->bitmap_left, - y_start + slot->bitmap_top, - opacity, - red, - green, - blue ); - - /* Advance to the next position */ - pen.x += slot->advance.x; - pen.y += slot->advance.y; - - /* record current glyph index */ - previous = glyph_index; - } - - /* Free the face and the library objects */ - FT_Done_Face ( face ); - FT_Done_FreeType( library ); - - delete[] ucs4text; -} - -void pngwriter::plot_text_blend( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double opacity, int red, int green, int blue) -{ - plot_text_blend( face_path, fontsize, x_start, y_start, angle, text, opacity, ((double) red)/65535.0, ((double) green)/65535.0, ((double) blue)/65535.0 ); -} - -void pngwriter::plot_text_utf8_blend( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double opacity, int red, int green, int blue) -{ - plot_text_utf8_blend( face_path, fontsize, x_start, y_start, angle, text, opacity, ((double) red)/65535.0, ((double) green)/65535.0, ((double) blue)/65535.0 ); -} - -void pngwriter::my_draw_bitmap_blend( FT_Bitmap * bitmap, int x, int y, double opacity, double red, double green, double blue) -{ - double temp; - for(int j=1; jrows+1; j++) - { - for(int i=1; i< bitmap->width + 1; i++) - { - temp = (double)(bitmap->buffer[(j-1)*bitmap->width + (i-1)] )/255.0; - - if(temp) - { - this->plot_blend(x + i, - y - j, - opacity, - temp*red + (1-temp)*(this->dread(x+i,y-j,1)), - temp*green + (1-temp)*(this->dread(x+i,y-j,2)), - temp*blue + (1-temp)*(this->dread(x+i,y-j,3)) - ); - } - } - } -} - -#endif -#ifdef NO_FREETYPE - -void pngwriter::plot_text_blend( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double opacity, int red, int green, int blue) -{ - std::cerr << " PNGwriter::plot_text_blend - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl; - return; -} - -void pngwriter::plot_text_blend( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double opacity, double red, double green, double blue) -{ - std::cerr << " PNGwriter::plot_text_blend - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl; - return; - -} - -void pngwriter::plot_text_utf8_blend( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double opacity, int red, int green, int blue) -{ - std::cerr << " PNGwriter::plot_text_utf8_blend - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl; - return; -} - -void pngwriter::plot_text_utf8_blend( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double opacity, double red, double green, double blue) -{ - std::cerr << " PNGwriter::plot_text_utf8_blend - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl; - return; -} - -#endif - -/////////////////////////// - -void pngwriter::boundary_fill_blend(int xstart, int ystart, double opacity, double boundary_red,double boundary_green,double boundary_blue,double fill_red, double fill_green, double fill_blue) -{ - if( ( - (this->dread(xstart,ystart,1) != boundary_red) || - (this->dread(xstart,ystart,2) != boundary_green) || - (this->dread(xstart,ystart,3) != boundary_blue) - ) - && - ( - (this->dread(xstart,ystart,1) != fill_red) || - (this->dread(xstart,ystart,2) != fill_green) || - (this->dread(xstart,ystart,3) != fill_blue) - ) - && - (xstart >0)&&(xstart <= width_)&&(ystart >0)&&(ystart <= height_) - ) - { - this->plot_blend(xstart, ystart, opacity, fill_red, fill_green, fill_blue); - boundary_fill_blend(xstart+1, ystart, opacity, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ; - boundary_fill_blend(xstart, ystart+1, opacity, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ; - boundary_fill_blend(xstart, ystart-1, opacity, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ; - boundary_fill_blend(xstart-1, ystart, opacity, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ; - } -} - -//no int version needed -void pngwriter::flood_fill_internal_blend(int xstart, int ystart, double opacity, double start_red, double start_green, double start_blue, double fill_red, double fill_green, double fill_blue) -{ - if( ( - (this->dread(xstart,ystart,1) == start_red) && - (this->dread(xstart,ystart,2) == start_green) && - (this->dread(xstart,ystart,3) == start_blue) - ) - && - ( - (this->dread(xstart,ystart,1) != fill_red) || - (this->dread(xstart,ystart,2) != fill_green) || - (this->dread(xstart,ystart,3) != fill_blue) - ) - && - (xstart >0)&&(xstart <= width_)&&(ystart >0)&&(ystart <= height_) - ) - { - this->plot_blend(xstart, ystart, opacity, fill_red, fill_green, fill_blue); - flood_fill_internal_blend( xstart+1, ystart, opacity, start_red, start_green, start_blue, fill_red, fill_green, fill_blue); - flood_fill_internal_blend( xstart-1, ystart,opacity, start_red, start_green, start_blue, fill_red, fill_green, fill_blue); - flood_fill_internal_blend( xstart, ystart+1, opacity, start_red, start_green, start_blue, fill_red, fill_green, fill_blue); - flood_fill_internal_blend( xstart, ystart-1, opacity, start_red, start_green, start_blue, fill_red, fill_green, fill_blue); - } - -} - -//int version -void pngwriter::boundary_fill_blend(int xstart, int ystart, double opacity, int boundary_red,int boundary_green,int boundary_blue,int fill_red, int fill_green, int fill_blue) -{ - - this->boundary_fill_blend( xstart, ystart, - opacity, - ((double) boundary_red)/65535.0, - ((double) boundary_green)/65535.0, - ((double) boundary_blue)/65535.0, - ((double) fill_red)/65535.0, - ((double) fill_green)/65535.0, - ((double) fill_blue)/65535.0 - ); -} - -void pngwriter::flood_fill_blend(int xstart, int ystart, double opacity, double fill_red, double fill_green, double fill_blue) -{ - flood_fill_internal_blend( xstart, ystart, opacity, this->dread(xstart,ystart,1),this->dread(xstart,ystart,2),this->dread(xstart,ystart,3), fill_red, fill_green, fill_blue); -} - -//int version -void pngwriter::flood_fill_blend(int xstart, int ystart, double opacity, int fill_red, int fill_green, int fill_blue) -{ - this->flood_fill_blend( xstart, ystart, - opacity, - ((double) fill_red)/65535.0, - ((double) fill_green)/65535.0, - ((double) fill_blue)/65535.0 - ); -} - -void pngwriter::polygon_blend( int * points, int number_of_points, double opacity, double red, double green, double blue) -{ - if( (number_of_points<1)||(points ==NULL)) - { - std::cerr << " PNGwriter::polygon_blend - ERROR **: Number of points is zero or negative, or array is NULL." << std::endl; - return; - } - - for(int k=0;k< number_of_points-1; k++) - { - this->line_blend(points[2*k],points[2*k+1],points[2*k+2],points[2*k+3], opacity, red, green, blue); - } -} - -//int version -void pngwriter::polygon_blend( int * points, int number_of_points, double opacity, int red, int green, int blue) -{ - this->polygon_blend(points, number_of_points, - opacity, - ((double) red)/65535.0, - ((double) green)/65535.0, - ((double) blue)/65535.0 - ); -} - -void pngwriter::plotCMYK_blend(int x, int y, double opacity, double cyan, double magenta, double yellow, double black) -{ -/*CMYK to RGB: - * ----------- - * red = 255 - minimum(255,((cyan/255) * (255 - black) + black)) - * green = 255 - minimum(255,((magenta/255) * (255 - black) + black)) - * blue = 255 - minimum(255,((yellow/255) * (255 - black) + black)) - * */ - - if(cyan<0.0) - { - cyan = 0.0; - } - if(magenta<0.0) - { - magenta = 0.0; - } - if(yellow<0.0) - { - yellow = 0.0; - } - if(black<0.0) - { - black = 0.0; - } - - if(cyan>1.0) - { - cyan = 1.0; - } - if(magenta>1.0) - { - magenta = 1.0; - } - if(yellow>1.0) - { - yellow = 1.0; - } - if(black>1.0) - { - black = 1.0; - } - - double red, green, blue, minr, ming, minb, iblack; - - iblack = 1.0 - black; - - minr = 1.0; - ming = 1.0; - minb = 1.0; - - if( (cyan*iblack + black)<1.0 ) - { - minr = cyan*iblack + black; - } - - if( (magenta*iblack + black)<1.0 ) - { - ming = magenta*iblack + black; - } - - if( (yellow*iblack + black)<1.0 ) - { - minb = yellow*iblack + black; - } - - red = 1.0 - minr; - green = 1.0 - ming; - blue = 1.0 - minb; - - this->plot_blend(x,y,opacity, red, green, blue); - -} - -//int version -void pngwriter::plotCMYK_blend(int x, int y, double opacity, int cyan, int magenta, int yellow, int black) -{ - this->plotCMYK_blend( x, y, - opacity, - ((double) cyan)/65535.0, - ((double) magenta)/65535.0, - ((double) yellow)/65535.0, - ((double) black)/65535.0 - ); -} - -void pngwriter::laplacian(double k, double offset) -{ - - // Create image storage. - pngwriter temp(width_,height_,0,"temp"); - - double red, green, blue; - - for(int x = 1; x <= width_; x++) - { - for(int y = 1; y <= height_; y++) - { - red = - 8.0*this->dread(x,y,1) - - ( this->dread(x+1, y-1, 1) + - this->dread(x, y-1, 1) + - this->dread(x-1, y-1, 1) + - this->dread(x-1, y, 1) + - this->dread(x+1, y, 1) + - this->dread(x+1, y+1, 1) + - this->dread(x, y+1, 1) + - this->dread(x-1, y+1, 1) ); - - green = - 8.0*this->dread(x,y,2) - - ( this->dread(x+1, y-1, 2) + - this->dread(x, y-1, 2) + - this->dread(x-1, y-1, 2) + - this->dread(x-1, y, 2) + - this->dread(x+1, y, 2) + - this->dread(x+1, y+1, 2) + - this->dread(x, y+1, 2) + - this->dread(x-1, y+1, 2)); - - blue = - 8.0*this->dread(x,y,3) - - ( this->dread(x+1, y-1, 3) + - this->dread(x, y-1, 3) + - this->dread(x-1, y-1, 3) + - this->dread(x-1, y, 3) + - this->dread(x+1, y, 3) + - this->dread(x+1, y+1, 3) + - this->dread(x, y+1, 3) + - this->dread(x-1, y+1, 3)); - - temp.plot(x,y,offset+k*red,offset+k*green,offset+k*blue); - - } - } - - for(int xx = 1; xx <= width_; xx++) - { - for(int yy = 1; yy <= height_; yy++) - { - this->plot(xx,yy, temp.read(xx,yy,1), temp.read(xx,yy,2), temp.read(xx,yy,3)); - } - } -} - - - -// drwatop(), drawbottom() and filledtriangle() were contributed by Gurkan Sengun -// ( , http://www.linuks.mine.nu/ ) -void pngwriter::drawtop(long x1,long y1,long x2,long y2,long x3, int red, int green, int blue) -{ - // This swaps x2 and x3 - // if(x2>x3) x2^=x3^=x2^=x3; - if(x2>x3) - { - x2^=x3; - x3^=x2; - x2^=x3; - } - - long posl = x1*256; - long posr = posl; - - long cl=((x2-x1)*256)/(y2-y1); - long cr=((x3-x1)*256)/(y2-y1); - - for(int y=y1; yline(posl/256, y, posr/256, y, red, green, blue); - posl+=cl; - posr+=cr; - } -} - -// drwatop(), drawbottom() and filledtriangle() were contributed by Gurkan Sengun -// ( , http://www.linuks.mine.nu/ ) -void pngwriter::drawbottom(long x1,long y1,long x2,long x3,long y3, int red, int green, int blue) -{ - //Swap x1 and x2 - //if(x1>x2) x2^=x1^=x2^=x1; - if(x1>x2) - { - x2^=x1; - x1^=x2; - x2^=x1; - } - - long posl=x1*256; - long posr=x2*256; - - long cl=((x3-x1)*256)/(y3-y1); - long cr=((x3-x2)*256)/(y3-y1); - - for(int y=y1; yline(posl/256, y, posr/256, y, red, green, blue); - - posl+=cl; - posr+=cr; - } -} - -// drwatop(), drawbottom() and filledtriangle() were contributed by Gurkan Sengun -// ( , http://www.linuks.mine.nu/ ) -void pngwriter::filledtriangle(int x1,int y1,int x2,int y2,int x3,int y3, int red, int green, int blue) -{ - if((x1==x2 && x2==x3) || (y1==y2 && y2==y3)) return; - - if(y2drawtop(x1, y1, x2, y2, x3, red, green, blue); - } - else - { - if(y1==y3 || y1==y2) - { - this->drawbottom(x1, y1, x2, x3, y3, red, green, blue); - } - else - { - int new_x = x1 + (int)((double)(y2-y1)*(double)(x3-x1)/(double)(y3-y1)); - this->drawtop(x1, y1, new_x, y2, x2, red, green, blue); - this->drawbottom(x2, y2, new_x, x3, y3, red, green, blue); - } - } - -} - -//Double (bug found by Dave Wilks. Was: (int) red*65535, should have been (int) (red*65535). -void pngwriter::filledtriangle(int x1,int y1,int x2,int y2,int x3,int y3, double red, double green, double blue) -{ - this->filledtriangle(x1, y1, x2, y2, x3, y3, (int) (red*65535), (int) (green*65535), (int) (blue*65535)); -} - -//Blend, double. (bug found by Dave Wilks. Was: (int) red*65535, should have been (int) (red*65535). -void pngwriter::filledtriangle_blend(int x1,int y1,int x2,int y2,int x3,int y3, double opacity, double red, double green, double blue) -{ - this->filledtriangle_blend( x1, y1, x2, y2, x3, y3, opacity, (int) (red*65535), (int) (green*65535), (int) (blue*65535)); -} - -//Blend, int -void pngwriter::filledtriangle_blend(int x1,int y1,int x2,int y2,int x3,int y3, double opacity, int red, int green, int blue) -{ - if((x1==x2 && x2==x3) || (y1==y2 && y2==y3)) return; - - /*if(y2drawtop_blend(x1, y1, x2, y2, x3, opacity, red, green, blue); - } - else - { - if(y1==y3 || y1==y2) - { - this->drawbottom_blend(x1, y1, x2, x3, y3, opacity, red, green, blue); - } - else - { - int new_x = x1 + (int)((double)(y2-y1)*(double)(x3-x1)/(double)(y3-y1)); - this->drawtop_blend(x1, y1, new_x, y2, x2, opacity, red, green, blue); - this->drawbottom_blend(x2, y2, new_x, x3, y3, opacity, red, green, blue); - } - } - -} - -//Blend, int -void pngwriter::drawbottom_blend(long x1,long y1,long x2,long x3,long y3, double opacity, int red, int green, int blue) -{ - //Swap x1 and x2 - if(x1>x2) - { - x2^=x1; - x1^=x2; - x2^=x1; - } - - long posl=x1*256; - long posr=x2*256; - - long cl=((x3-x1)*256)/(y3-y1); - long cr=((x3-x2)*256)/(y3-y1); - - for(int y=y1; yline_blend(posl/256, y, posr/256, y, opacity, red, green, blue); - - posl+=cl; - posr+=cr; - } - -} - -//Blend, int -void pngwriter::drawtop_blend(long x1,long y1,long x2,long y2,long x3, double opacity, int red, int green, int blue) -{ - // This swaps x2 and x3 - if(x2>x3) - { - x2^=x3; - x3^=x2; - x2^=x3; -} - - long posl = x1*256; - long posr = posl; - - long cl=((x2-x1)*256)/(y2-y1); - long cr=((x3-x1)*256)/(y2-y1); - - for(int y=y1; yline_blend(posl/256, y, posr/256, y, opacity, red, green, blue); - posl+=cl; - posr+=cr; - } - -} - -void pngwriter::triangle(int x1, int y1, int x2, int y2, int x3, int y3, int red, int green, int blue) -{ - this->line(x1, y1, x2, y2, red, green, blue); - this->line(x2, y2, x3, y3, red, green, blue); - this->line(x3, y3, x1, y1, red, green, blue); -} - -void pngwriter::triangle(int x1, int y1, int x2, int y2, int x3, int y3, double red, double green, double blue) -{ - - this->line(x1, y1, x2, y2, ((int)65535*red), ((int)65535*green), ((int)65535*blue)); - this->line(x2, y2, x3, y3, ((int)65535*red), ((int)65535*green), ((int)65535*blue)); - this->line(x3, y3, x1, y1, ((int)65535*red), ((int)65535*green), ((int)65535*blue)); - -} - - - - - -void pngwriter::arrow( int x1,int y1,int x2,int y2,int size, double head_angle, double red, double green, double blue) -{ - - this->line(x1, y1, x2, y2, red, green, blue); - // double th = 3.141592653589793 + (head_angle)*3.141592653589793/180.0; //degrees - double th = 3.141592653589793 + head_angle; - double costh = cos(th); - double sinth = sin(th); - double t1, t2, r; - t1 = ((x2-x1)*costh - (y2-y1)*sinth); - t2 = ((x2-x1)*sinth + (y2-y1)*costh); - r = sqrt(t1*t1 + t2*t2); - - double advancex = size*t1/r; - double advancey = size*t2/r; - this->line(x2, y2, int(x2 + advancex), int(y2 + advancey), red, green, blue); - t1 = (x2-x1)*costh + (y2-y1)*sinth; - t2 = (y2-y1)*costh - (x2-x1)*sinth; - - advancex = size*t1/r; - advancey = size*t2/r; - this->line(x2, y2, int(x2 + advancex), int(y2 + advancey), red, green, blue); -} - -void pngwriter::filledarrow( int x1,int y1,int x2,int y2,int size, double head_angle, double red, double green, double blue) -{ - int p1x, p2x, p3x, p1y, p2y, p3y; - - this->line(x1, y1, x2, y2, red, green, blue); - double th = 3.141592653589793 + head_angle; - double costh = cos(th); - double sinth = sin(th); - double t11, t12, t21, t22, r1, r2; - t11 = ((x2-x1)*costh - (y2-y1)*sinth); - t21 = ((x2-x1)*sinth + (y2-y1)*costh); - t12 = (x2-x1)*costh + (y2-y1)*sinth; - t22 = (y2-y1)*costh - (x2-x1)*sinth; - - r1 = sqrt(t11*t11 + t21*t21); - r2 = sqrt(t12*t12 + t22*t22); - - double advancex1 = size*t11/r1; - double advancey1 = size*t21/r1; - double advancex2 = size*t12/r2; - double advancey2 = size*t22/r2; - - p1x = x2; - p1y = y2; - - p2x = int(x2 + advancex1); - p2y = int(y2 + advancey1); - - p3x = int(x2 + advancex2); - p3y = int(y2 + advancey2); - - - this->filledtriangle( p1x, p1y, p2x, p2y, p3x, p3y, red, green, blue); - -} - -void pngwriter::arrow( int x1,int y1,int x2,int y2,int size, double head_angle, int red, int green, int blue) -{ - this->arrow( x1, y1, x2, y2, size, head_angle, (double (red))/65535.0, (double (green))/65535.0, (double (blue))/65535.0 ); -} - -void pngwriter::filledarrow( int x1,int y1,int x2,int y2,int size, double head_angle, int red, int green, int blue) -{ - this->filledarrow( x1, y1, x2, y2, size, head_angle, (double (red))/65535.0, (double (green))/65535.0, (double (blue))/65535.0 ); -} - - -void pngwriter::cross( int x, int y, int xwidth, int yheight, int red, int green, int blue) -{ - this->line(int(x - xwidth/2.0), y, int(x + xwidth/2.0), y, red, green, blue); - this->line(x, int(y - yheight/2.0), x, int(y + yheight/2.0), red, green, blue); -} - -void pngwriter::maltesecross( int x, int y, int xwidth, int yheight, int x_bar_height, int y_bar_width, int red, int green, int blue) -{ - this->line(int(x - xwidth/2.0), y, int(x + xwidth/2.0), y, red, green, blue); - this->line(x, int(y - yheight/2.0), x, int(y + yheight/2.0), red, green, blue); - // Bars on ends of vertical line - this->line(int(x - y_bar_width/2.0), int(y + yheight/2.0), int(x + y_bar_width/2.0), int(y + yheight/2.0), red, green, blue); - this->line(int(x - y_bar_width/2.0), int(y - yheight/2.0), int(x + y_bar_width/2.0), int(y - yheight/2.0), red, green, blue); - // Bars on ends of horizontal line. - this->line(int(x - xwidth/2.0), int(y - x_bar_height/2.0), int(x - xwidth/2.0), int(y + x_bar_height/2.0), red, green, blue); - this->line(int(x + xwidth/2.0), int(y - x_bar_height/2.0), int(x + xwidth/2.0), int(y + x_bar_height/2.0), red, green, blue); -} - -void pngwriter::cross( int x, int y, int xwidth, int yheight, double red, double green, double blue) -{ - this->cross( x, y, xwidth, yheight, int(65535*red), int(65535*green), int(65535*blue)); -} - -void pngwriter::maltesecross( int x, int y, int xwidth, int yheight, int x_bar_height, int y_bar_width, double red, double green, double blue) -{ - this->maltesecross( x, y, xwidth, yheight, x_bar_height, y_bar_width, int(65535*red), int(65535*green), int(65535*blue)); -} - - -void pngwriter::filleddiamond( int x, int y, int width, int height, int red, int green, int blue) -{ - this->filledtriangle( int(x - width/2.0), y, x, y, x, int(y + height/2.0), red, green, blue); - this->filledtriangle( int(x + width/2.0), y, x, y, x, int(y + height/2.0), red, green, blue); - this->filledtriangle( int(x - width/2.0), y, x, y, x, int(y - height/2.0), red, green, blue); - this->filledtriangle( int(x + width/2.0), y, x, y, x, int(y - height/2.0), red, green, blue); -} - -void pngwriter::diamond( int x, int y, int width, int height, int red, int green, int blue) -{ - this->line( int(x - width/2.0), y, x, int(y + height/2.0), red, green, blue); - this->line( int(x + width/2.0), y, x, int(y + height/2.0), red, green, blue); - this->line( int(x - width/2.0), y, x, int(y - height/2.0), red, green, blue); - this->line( int(x + width/2.0), y, x, int(y - height/2.0), red, green, blue); -} - - -void pngwriter::filleddiamond( int x, int y, int width, int height, double red, double green, double blue) -{ - this->filleddiamond( x, y, width, height, int(red*65535), int(green*65535), int(blue*65535) ); -} - -void pngwriter::diamond( int x, int y, int width, int height, double red, double green, double blue) -{ - this->diamond( x, y, width, height, int(red*65535), int(green*65535), int(blue*65535) ); -} - diff --git a/libsrc/hyperionpng/pngwriter.h b/libsrc/hyperionpng/pngwriter.h deleted file mode 100644 index ab01b1ae..00000000 --- a/libsrc/hyperionpng/pngwriter.h +++ /dev/null @@ -1,745 +0,0 @@ -//********** pngwriter.h ********************************************** -// Author: Paul Blackburn -// -// Email: individual61@users.sourceforge.net -// -// Version: 0.5.4 (19 / II / 2009) -// -// Description: Library that allows plotting a 48 bit -// PNG image pixel by pixel, which can -// then be opened with a graphics program. -// -// License: GNU General Public License -// Copyright 2002, 2003, 2004, 2005, 2006, 2007, -// 2008, 2009 Paul Blackburn -// -// Website: Main: http://pngwriter.sourceforge.net/ -// Sourceforge.net: http://sourceforge.net/projects/pngwriter/ -// Freshmeat.net: http://freshmeat.net/projects/pngwriter/ -// -// Documentation: This header file is commented, but for a -// quick reference document, and support, -// take a look at the website. -// -//************************************************************************* - - -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * */ - -#ifndef PNGWRITER_H -#define PNGWRITER_H 1 - -#define PNGWRITER_VERSION 0.54 - -#include - -// REMEMBER TO ADD -DNO_FREETYPE TO YOUR COMPILATION FLAGS IF PNGwriter WAS -// COMPILED WITHOUT FREETYPE SUPPORT!!! -// -// RECUERDA AGREGAR -DNO_FREETYPE A TUS OPCIONES DE COMPILACION SI PNGwriter -// FUE COMPILADO SIN SOPORTE PARA FREETYPE!!! -// -#ifndef NO_FREETYPE -#include -#include FT_FREETYPE_H -#endif - - - -#ifdef OLD_CPP // For compatibility with older compilers. -#include -#include -#include -#include -using namespace std; -#endif // from ifdef OLD_CPP - -#ifndef OLD_CPP // Default situation. -#include -#include -#include -#include -#endif // from ifndef OLD_CPP - - -//png.h must be included before FreeType headers. -#include -#include -#include - - - - -#define PNG_BYTES_TO_CHECK (4) -#define PNGWRITER_DEFAULT_COMPRESSION (6) - -class pngwriter -{ - private: - - char * filename_; - char * textauthor_; - char * textdescription_; - char * texttitle_; - char * textsoftware_; - - - - int height_; - int width_; - int backgroundcolour_; - int bit_depth_; - int rowbytes_; - int colortype_; - int compressionlevel_; - bool transformation_; // Required by Mikkel's patch - - unsigned char * * graph_; - double filegamma_; - double screengamma_; - void circle_aux(int xcentre, int ycentre, int x, int y, int red, int green, int blue); - void circle_aux_blend(int xcentre, int ycentre, int x, int y, double opacity, int red, int green, int blue); - int check_if_png(char *file_name, FILE **fp); - int read_png_info(FILE *fp, png_structp *png_ptr, png_infop *info_ptr); - int read_png_image(FILE *fp, png_structp png_ptr, png_infop info_ptr, - png_bytepp *image, png_uint_32 *width, png_uint_32 *height); - void flood_fill_internal( int xstart, int ystart, double start_red, double start_green, double start_blue, double fill_red, double fill_green, double fill_blue); - void flood_fill_internal_blend( int xstart, int ystart, double opacity, double start_red, double start_green, double start_blue, double fill_red, double fill_green, double fill_blue); - -#ifndef NO_FREETYPE - void my_draw_bitmap( FT_Bitmap * bitmap, int x, int y, double red, double green, double blue); - void my_draw_bitmap_blend( FT_Bitmap * bitmap, int x, int y,double opacity, double red, double green, double blue); -#endif - - /* The algorithms HSVtoRGB and RGBtoHSV were found at http://www.cs.rit.edu/~ncs/ - * which is a page that belongs to Nan C. Schaller, though - * these algorithms appear to be the work of Eugene Vishnevsky. - * */ - void HSVtoRGB( double *r, double *g, double *b, double h, double s, double v ); - void RGBtoHSV( float r, float g, float b, float *h, float *s, float *v ); - - /* drwatop(), drawbottom() and filledtriangle() were contributed by Gurkan Sengun - * ( , http://www.linuks.mine.nu/ ) - * */ - void drawtop(long x1,long y1,long x2,long y2,long x3, int red, int green, int blue); - void drawbottom(long x1,long y1,long x2,long x3,long y3, int red, int green, int blue); - void drawbottom_blend(long x1,long y1,long x2,long x3,long y3, double opacity, int red, int green, int blue); - void drawtop_blend(long x1,long y1,long x2,long y2,long x3, double opacity, int red, int green, int blue); - - public: - - /* General Notes - * It is important to remember that all functions that accept an argument of type "const char *" will also - * accept "char *", this is done so you can have a changing filename (to make many PNG images in series - * with a different name, for example), and to allow you to use string type objects which can be easily - * turned into const char * (if theString is an object of type string, then it can be used as a const char * - * by saying theString.c_str()). - * It is also important to remember that whenever a function has a colour coeffiecient as its argument, - * that argument can be either an int from 0 to 65535 or a double from 0.0 to 1.0. - * It is important to make sure that you are calling the function with the type that you want. - * Remember that 1 is an int, while 1.0 is a double, and will thus determine what version of the function - * will be used. Similarly, do not make the mistake of calling for example plot(x, y, 0.0, 0.0, 65535), - * because - * there is no plot(int, int, double, double, int). - * Also, please note that plot() and read() (and the functions that use them internally) - * are protected against entering, for example, a colour coefficient that is over 65535 - * or over 1.0. Similarly, they are protected against negative coefficients. read() will return 0 - * when called outside the image range. This is actually useful as zero-padding should you need it. - * */ - - /* Compilation - * A typical compilation would look like this: - * - * g++ my_program.cc -o my_program freetype-config --cflags \ - * -I/usr/local/include -L/usr/local/lib -lpng -lpngwriter -lz -lfreetype - * - * If you did not compile PNGwriter with FreeType support, then remove the - * FreeType-related flags and add -DNO_FREETYPE above. - * */ - - /* Constructor - * The constructor requires the width and the height of the image, the background colour for the - * image and the filename of the file (a pointer or simple "myfile.png"). The background colour - * can only be initialized to a shade of grey (once the object has been created you can do whatever - * you want, though), because generally one wants either a white (65535 or 1.0) or a black (0 or 0.0) - * background to start with. - * The default constructor creates a PNGwriter instance that is 250x250, white background, - * and filename "out.png". - * Tip: The filename can be given as easily as: - * pngwriter mypng(300, 300, 0.0, "myfile.png"); - * Tip: If you are going to create a PNGwriter instance for reading in a file that already exists, - * then width and height can be 1 pixel, and the size will be automatically adjusted once you use - * readfromfile(). - * */ - pngwriter(); - pngwriter(const pngwriter &rhs); - pngwriter(int width, int height, int backgroundcolour, char * filename); - pngwriter(int width, int height, double backgroundcolour, char * filename); - pngwriter(int width, int height, int backgroundcolour, const char * filename); - pngwriter(int width, int height, double backgroundcolour, const char * filename); - - /* Destructor - * */ - ~pngwriter(); - - /* Assignment Operator - * */ - pngwriter & operator = (const pngwriter & rhs); - - /* Plot - * With this function a pixel at coordinates (x, y) can be set to the desired colour. - * The pixels are numbered starting from (1, 1) and go to (width, height). - * As with most functions in PNGwriter, it has been overloaded to accept either int arguments - * for the colour coefficients, or those of type double. If they are of type int, - * they go from 0 to 65535. If they are of type double, they go from 0.0 to 1.0. - * Tip: To plot using red, then specify plot(x, y, 1.0, 0.0, 0.0). To make pink, - * just add a constant value to all three coefficients, like this: - * plot(x, y, 1.0, 0.4, 0.4). - * Tip: If nothing is being plotted to your PNG file, make sure that you remember - * to close() the instance before your program is finished, and that the x and y position - * is actually within the bounds of your image. If either is not, then PNGwriter will - * not complain-- it is up to you to check for this! - * Tip: If you try to plot with a colour coefficient out of range, a maximum or minimum - * coefficient will be assumed, according to the given coefficient. For example, attempting - * to plot plot(x, y, 1.0,-0.2,3.7) will set the green coefficient to 0 and the red coefficient - * to 1.0. - * */ - void plot(int x, int y, int red, int green, int blue); - void plot(int x, int y, double red, double green, double blue); - - /* Plot HSV - * With this function a pixel at coordinates (x, y) can be set to the desired colour, - * but with the colour coefficients given in the Hue, Saturation, Value colourspace. - * This has the advantage that one can determine the colour that will be plotted with - * only one parameter, the Hue. The colour coefficients must go from 0 to 65535 and - * be of type int, or be of type double and go from 0.0 to 1.0. - * */ - void plotHSV(int x, int y, double hue, double saturation, double value); - void plotHSV(int x, int y, int hue, int saturation, int value); - - /* Read - * With this function we find out what colour the pixel (x, y) is. If "colour" is 1, - * it will return the red coefficient, if it is set to 2, the green one, and if - * it set to 3, the blue colour coefficient will be returned, - * and this returned value will be of type int and be between 0 and 65535. - * Note that if you call read() on a pixel outside the image range, the value returned - * will be 0. - * */ - int read(int x, int y, int colour); - - /* Read, Average - * Same as the above, only that the average of the three colour coefficients is returned. - */ - int read(int x, int y); - - /* dRead - * With this function we find out what colour the pixel (x, y) is. If "colour" is 1, - * it will return the red coefficient, if it is set to 2, the green one, and if - * it set to 3, the blue colour coefficient will be returned, - * and this returned value will be of type double and be between 0.0 and 1.0. - * Note that if you call dread() outside the image range, the value returned will be 0.0 - * */ - double dread(int x, int y, int colour); - - /* dRead, Average - * Same as the above, only that the average of the three colour coefficients is returned. - */ - double dread(int x, int y); - - /* Read HSV - * With this function we find out what colour the pixel (x, y) is, but in the Hue, - * Saturation, Value colourspace. If "colour" is 1, - * it will return the Hue coefficient, if it is set to 2, the Saturation one, and if - * it set to 3, the Value colour coefficient will be returned, and this returned - * value will be of type int and be between 0 and 65535. Important: If you attempt - * to read the Hue of a pixel that is a shade of grey, the value returned will be - * nonsensical or even NaN. This is just the way the RGB -> HSV algorithm works: - * the Hue of grey is not defined. You might want to check whether the pixel - * you are reading is grey before attempting a readHSV(). - * Tip: This is especially useful for categorizing sections of the image according - * to their colour. - * */ - int readHSV(int x, int y, int colour); - - /* dRead HSV - * With this function we find out what colour the pixel (x, y) is, but in the Hue, - * Saturation, Value colourspace. If "colour" is 1, - * it will return the Hue coefficient, if it is set to 2, the Saturation one, and if - * it set to 3, the Value colour coefficient will be returned, - * and this returned value will be of type double and be between 0.0 and 1.0. - * */ - double dreadHSV(int x, int y, int colour); - - /* Clear - * The whole image is set to black. - * */ - void clear(void); - - /* Close - * Close the instance of the class, and write the image to disk. - * Tip: If you do not call this function before your program ends, no image - * will be written to disk. - * */ - void close(void); - - /* Rename - * To rename the file once an instance of pngwriter has been created. - * Useful for assigning names to files based upon their content. - * Tip: This is as easy as calling pngwriter_rename("newname.png") - * If the argument is a long unsigned int, for example 77, the filename will be changed to - * 0000000077.png - * Tip: Use this to create sequences of images for movie generation. - * */ - void pngwriter_rename(char * newname); - void pngwriter_rename(const char * newname); - void pngwriter_rename(long unsigned int index); - - /* Figures - * These functions draw basic shapes. Available in both int and double versions. - * The line functions use the fast Bresenham algorithm. Despite the name, - * the square functions draw rectangles. The circle functions use a fast - * integer math algorithm. The filled circle functions make use of sqrt(). - * */ - void line(int xfrom, int yfrom, int xto, int yto, int red, int green,int blue); - void line(int xfrom, int yfrom, int xto, int yto, double red, double green,double blue); - - void triangle(int x1, int y1, int x2, int y2, int x3, int y3, int red, int green, int blue); - void triangle(int x1, int y1, int x2, int y2, int x3, int y3, double red, double green, double blue); - - void square(int xfrom, int yfrom, int xto, int yto, int red, int green,int blue); - void square(int xfrom, int yfrom, int xto, int yto, double red, double green,double blue); - - void filledsquare(int xfrom, int yfrom, int xto, int yto, int red, int green,int blue); - void filledsquare(int xfrom, int yfrom, int xto, int yto, double red, double green,double blue); - - void circle(int xcentre, int ycentre, int radius, int red, int green, int blue); - void circle(int xcentre, int ycentre, int radius, double red, double green, double blue); - - void filledcircle(int xcentre, int ycentre, int radius, int red, int green, int blue); - void filledcircle(int xcentre, int ycentre, int radius, double red, double green, double blue); - - - /* Read From File - * Open the existing PNG image, and copy it into this instance of the class. It is important to mention - * that PNG variants are supported. Very generally speaking, most PNG files can now be read (as of version 0.5.4), - * but if they have an alpha channel it will be completely stripped. If the PNG file uses GIF-style transparency - * (where one colour is chosen to be transparent), PNGwriter will not read the image properly, but will not - * complain. Also, if any ancillary chunks are included in the PNG file (chroma, filter, etc.), it will render - * with a slightly different tonality. For the vast majority of PNGs, this should not be an issue. Note: - * If you read an 8-bit PNG, the internal representation of that instance of PNGwriter will be 8-bit (PNG - * files of less than 8 bits will be upscaled to 8 bits). To convert it to 16-bit, just loop over all pixels, - * reading them into a new instance of PNGwriter. New instances of PNGwriter are 16-bit by default. - * */ - - void readfromfile(char * name); - void readfromfile(const char * name); - - /* Get Height - * When you open a PNG with readfromfile() you can find out its height with this function. - * */ - int getheight(void); - - /* Get Width - * When you open a PNG with readfromfile() you can find out its width with this function. - * */ - int getwidth(void); - - /* Set Compression Level - * Set the compression level that will be used for the image. -1 is to use the default, - * 0 is none, 9 is best compression. - * Remember that this will affect how long it will take to close() the image. A value of 2 or 3 - * is good enough for regular use, but for storage or transmission you might want to take the time - * to set it at 9. - * */ - void setcompressionlevel(int level); - - /* Get Bit Depth - * When you open a PNG with readfromfile() you can find out its bit depth with this function. - * Mostly for troubleshooting uses. - * */ - int getbitdepth(void); - - /* Get Colour Type - * When you open a PNG with readfromfile() you can find out its colour type (libpng categorizes - * different styles of image data with this number). - * Mostly for troubleshooting uses. - * */ - int getcolortype(void); - - /* Set Gamma Coeff - * Set the image's gamma (file gamma) coefficient. This is experimental, but use it if your image's colours seem too bright - * or too dark. The default value of 0.5 should be fine. The standard disclaimer about Mac and PC gamma - * settings applies. - * */ - void setgamma(double gamma); - - - /* Get Gamma Coeff - * Get the image's gamma coefficient. This is experimental. - * */ - double getgamma(void); - - /* Bezier Curve - * (After Frenchman Pierre BŽzier from Regie Renault) - * A collection of formulae for describing curved lines - * and surfaces, first used in 1972 to model automobile surfaces. - * (from the The Free On-line Dictionary of Computing) - * See http://www.moshplant.com/direct-or/bezier/ for one of many - * available descriptions of bezier curves. - * There are four points used to define the curve: the two endpoints - * of the curve are called the anchor points, while the other points, - * which define the actual curvature, are called handles or control points. - * Moving the handles lets you modify the shape of the curve. - * */ - - void bezier( int startPtX, int startPtY, - int startControlX, int startControlY, - int endPtX, int endPtY, - int endControlX, int endControlY, - double red, double green, double blue); - - void bezier( int startPtX, int startPtY, - int startControlX, int startControlY, - int endPtX, int endPtY, - int endControlX, int endControlY, - int red, int green, int blue); - - /* Set Text - * Sets the text information in the PNG header. If it is not called, the default is used. - */ - void settext(char * title, char * author, char * description, char * software); - void settext(const char * title, const char * author, const char * description, const char * software); - - - /* Version Number - * Returns the PNGwriter version number. - */ - static double version(void); - - /* Write PNG - * Writes the PNG image to disk. You can still change the PNGwriter instance after this. - * Tip: This is exactly the same as close(), but easier to remember. - * Tip: To make a sequence of images using only one instance of PNGwriter, alter the image, change its name, - * write_png(), then alter the image, change its name, write_png(), etc. - */ - void write_png(void); - - /* Plot Text - * Uses the Freetype2 library to set text in the image. face_path is the file path to a - * TrueType font file (.ttf) (FreeType2 can also handle other types). fontsize specifices the approximate - * height of the rendered font in pixels. x_start and y_start specify the placement of the - * lower, left corner of the text string. angle is the text angle in radians. text is the text to be rendered. - * The colour coordinates can be doubles from 0.0 to 1.0 or ints from 0 to 65535. - * Tip: PNGwriter installs a few fonts in /usr/local/share/pngwriter/fonts to get you started. - * Tip: Remember to add -DNO_FREETYPE to your compilation flags if PNGwriter was compiled without FreeType support. - * */ - void plot_text(char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double red, double green, double blue); - void plot_text(char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, int red, int green, int blue); - - - /* Plot UTF-8 Text - * Same as the above, but the text to be plotted is encoded in UTF-8. Why would you want this? To be able to plot - * all characters available in a large TrueType font, for example: for rendering Japenese, Chinese and other - * languages not restricted to the standard 128 character ASCII space. - * Tip: The quickest way to get a string into UTF-8 is to write it in an adequate text editor, and save it as a file - * in UTF-8 encoding, which can then be read in in binary mode. - * */ - void plot_text_utf8(char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double red, double green, double blue); - void plot_text_utf8(char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, int red, int green, int blue); - - - /* Bilinear Interpolation of Image - * Given a floating point coordinate (x from 0.0 to width, y from 0.0 to height), - * this function will return the interpolated colour intensity specified by - * colour (where red = 1, green = 2, blue = 3). - * bilinear_interpolate_read() returns an int from 0 to 65535, and - * bilinear_interpolate_dread() returns a double from 0.0 to 1.0. - * Tip: Especially useful for enlarging an image. - * */ - int bilinear_interpolation_read(double x, double y, int colour); - double bilinear_interpolation_dread(double x, double y, int colour); - - /* Plot Blend - * Plots the colour given by red, green blue, but blended with the existing pixel - * value at that position. opacity is a double that goes from 0.0 to 1.0. - * 0.0 will not change the pixel at all, and 1.0 will plot the given colour. - * Anything in between will be a blend of both pixel levels. Please note: This is neither - * alpha channel nor PNG transparency chunk support. This merely blends the plotted pixels. - * */ - - void plot_blend(int x, int y, double opacity, int red, int green, int blue); - void plot_blend(int x, int y, double opacity, double red, double green, double blue); - - - /* Invert - * Inverts the image in RGB colourspace. - * */ - void invert(void); - - /* Resize Image - * Resizes the PNGwriter instance. Note: All image data is set to black (this is - * a resizing, not a scaling, of the image). - * */ - void resize(int width, int height); - - /* Boundary Fill - * All pixels adjacent to the start pixel will be filled with the fill colour, until the boundary colour is encountered. - * For example, calling boundary_fill() with the boundary colour set to red, on a pixel somewhere inside a red circle, - * will fill the entire circle with the desired fill colour. If, on the other hand, the circle is not the boundary colour, - * the rest of the image will be filled. - * The colour components are either doubles from 0.0 to 1.0 or ints from 0 to 65535. - * */ - void boundary_fill(int xstart, int ystart, double boundary_red,double boundary_green,double boundary_blue,double fill_red, double fill_green, double fill_blue) ; - void boundary_fill(int xstart, int ystart, int boundary_red,int boundary_green,int boundary_blue,int fill_red, int fill_green, int fill_blue) ; - - /* Flood Fill - * All pixels adjacent to the start pixel will be filled with the fill colour, if they are the same colour as the - * start pixel. For example, calling flood_fill() somewhere in the interior of a solid blue rectangle will colour - * the entire rectangle the fill colour. The colour components are either doubles from 0.0 to 1.0 or ints from 0 to 65535. - * */ - void flood_fill(int xstart, int ystart, double fill_red, double fill_green, double fill_blue) ; - void flood_fill(int xstart, int ystart, int fill_red, int fill_green, int fill_blue) ; - - /* Polygon - * This function takes an array of integer values containing the coordinates of the vertexes of a polygon. - * Note that if you want a closed polygon, you must repeat the first point's coordinates for the last point. - * It also requires the number of points contained in the array. For example, if you wish to plot a triangle, - * the array will contain 6 elements, and the number of points is 3. Be very careful about this; if you specify the wrong number - * of points, your program will either segfault or produce points at nonsensical coordinates. - * The colour components are either doubles from 0.0 to 1.0 or ints from 0 to 65535. - * */ - void polygon(int * points, int number_of_points, double red, double green, double blue); - void polygon(int * points, int number_of_points, int red, int green, int blue); - - /* Plot CMYK - * Plot a point in the Cyan, Magenta, Yellow, Black colourspace. Please note that this colourspace is - * lossy, i.e. it cannot reproduce all colours on screen that RGB can. The difference, however, is - * barely noticeable. The algorithm used is a standard one. The colour components are either - * doubles from 0.0 to 1.0 or ints from 0 to 65535. - * */ - void plotCMYK(int x, int y, double cyan, double magenta, double yellow, double black); - void plotCMYK(int x, int y, int cyan, int magenta, int yellow, int black); - - /* Read CMYK, Double version - * Get a pixel in the Cyan, Magenta, Yellow, Black colourspace. if 'colour' is 1, the Cyan component will be returned - * as a double from 0.0 to 1.0. If 'colour is 2, the Magenta colour component will be returned, and so on, up to 4. - * */ - double dreadCMYK(int x, int y, int colour); - - /* Read CMYK - * Same as the above, but the colour components returned are an int from 0 to 65535. - * */ - int readCMYK(int x, int y, int colour); - - /* Scale Proportional - * Scale the image using bilinear interpolation. If k is greater than 1.0, the image will be enlarged. - * If k is less than 1.0, the image will be shrunk. Negative or null values of k are not allowed. - * The image will be resized and the previous content will be replaced by the scaled image. - * Tip: use getheight() and getwidth() to find out the new width and height of the scaled image. - * Note: After scaling, all images will have a bit depth of 16, even if the original image had - * a bit depth of 8. - * */ - void scale_k(double k); - - /* Scale Non-Proportional - * Scale the image using bilinear interpolation, with different horizontal and vertical scale factors. - * */ - void scale_kxky(double kx, double ky); - - /* Scale To Target Width and Height - * Scale the image in such a way as to meet the target width and height. - * Tip: if you want to keep the image proportional, scale_k() might be more appropriate. - * */ - void scale_wh(int finalwidth, int finalheight); - - - /* Blended Functions - * All these functions are identical to their non-blended types. They take an extra argument, opacity, which is - * a double from 0.0 to 1.0 and represents how much of the original pixel value is retained when plotting the - * new pixel. In other words, if opacity is 0.7, then after plotting, the new pixel will be 30% of the - * original colour the pixel was, and 70% of the new colour, whatever that may be. As usual, each function - * is available in int or double versions. Please note: This is neither alpha channel nor PNG transparency chunk support. This merely blends the plotted pixels. - * */ - - // Start Blended Functions - - void plotHSV_blend(int x, int y, double opacity, double hue, double saturation, double value); - void plotHSV_blend(int x, int y, double opacity, int hue, int saturation, int value); - - void line_blend(int xfrom, int yfrom, int xto, int yto, double opacity, int red, int green,int blue); - void line_blend(int xfrom, int yfrom, int xto, int yto, double opacity, double red, double green,double blue); - - void square_blend(int xfrom, int yfrom, int xto, int yto, double opacity, int red, int green,int blue); - void square_blend(int xfrom, int yfrom, int xto, int yto, double opacity, double red, double green,double blue); - - void filledsquare_blend(int xfrom, int yfrom, int xto, int yto, double opacity, int red, int green,int blue); - void filledsquare_blend(int xfrom, int yfrom, int xto, int yto, double opacity, double red, double green,double blue); - - void circle_blend(int xcentre, int ycentre, int radius, double opacity, int red, int green, int blue); - void circle_blend(int xcentre, int ycentre, int radius, double opacity, double red, double green, double blue); - - void filledcircle_blend(int xcentre, int ycentre, int radius, double opacity, int red, int green, int blue); - void filledcircle_blend(int xcentre, int ycentre, int radius, double opacity, double red, double green, double blue); - - void bezier_blend( int startPtX, int startPtY, - int startControlX, int startControlY, - int endPtX, int endPtY, - int endControlX, int endControlY, - double opacity, - double red, double green, double blue); - - void bezier_blend( int startPtX, int startPtY, - int startControlX, int startControlY, - int endPtX, int endPtY, - int endControlX, int endControlY, - double opacity, - int red, int green, int blue); - - void plot_text_blend(char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double opacity, double red, double green, double blue); - void plot_text_blend(char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double opacity, int red, int green, int blue); - - void plot_text_utf8_blend(char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double opacity, double red, double green, double blue); - void plot_text_utf8_blend(char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double opacity, int red, int green, int blue); - - void boundary_fill_blend(int xstart, int ystart, double opacity, double boundary_red,double boundary_green,double boundary_blue,double fill_red, double fill_green, double fill_blue) ; - void boundary_fill_blend(int xstart, int ystart, double opacity, int boundary_red,int boundary_green,int boundary_blue,int fill_red, int fill_green, int fill_blue) ; - - void flood_fill_blend(int xstart, int ystart, double opacity, double fill_red, double fill_green, double fill_blue) ; - void flood_fill_blend(int xstart, int ystart, double opacity, int fill_red, int fill_green, int fill_blue) ; - - void polygon_blend(int * points, int number_of_points, double opacity, double red, double green, double blue); - void polygon_blend(int * points, int number_of_points, double opacity, int red, int green, int blue); - - void plotCMYK_blend(int x, int y, double opacity, double cyan, double magenta, double yellow, double black); - void plotCMYK_blend(int x, int y, double opacity, int cyan, int magenta, int yellow, int black); - - // End of Blended Functions - - /* Laplacian - * This function applies a discrete laplacian to the image, multiplied by a constant factor. - * The kernel used in this case is: - * 1.0 1.0 1.0 - * 1.0 -8.0 1.0 - * 1.0 1.0 1.0 - * Basically, this works as an edge detector. The current pixel is assigned the sum of all neighbouring - * pixels, multiplied by the corresponding kernel element. For example, imagine a pixel and its 8 neighbours: - * 1.0 1.0 0.0 0.0 - * 1.0 ->1.0<- 0.0 0.0 - * 1.0 1.0 0.0 0.0 - * This represents a border between white and black, black is on the right. Applying the laplacian to - * the pixel specified above pixel gives: - * 1.0*1.0 + 1.0*1.0 + 0.0*1.0 + - * 1.0*1.0 + 1.0*-8.0 + 0.0*1.0 + - * 1.0*1.0 + 1.0*1.0 + 0.0*1.0 = -3.0 - * Applying this to the pixel to the right of the pixel considered previously, we get a sum of 3.0. - * That is, after passing over an edge, we get a high value for the pixel adjacent to the edge. Since - * PNGwriter limits the colour components if they are off-scale, and the result of the laplacian - * may be negative, a scale factor and an offset value are included. This might be useful for - * keeping things within range or for bringing out more detail in the edge detection. The - * final pixel value will be given by: - * final value = laplacian(original pixel)*k + offset - * Tip: Try a value of 1.0 for k to start with, and then experiment with other values. - * */ - void laplacian(double k, double offset); - - /* Filled Triangle - * Draws the triangle specified by the three pairs of points in the colour specified - * by the colour coefficients. The colour components are either doubles from 0.0 to - * 1.0 or ints from 0 to 65535. - * */ - void filledtriangle(int x1,int y1,int x2,int y2,int x3,int y3, int red, int green, int blue); - void filledtriangle(int x1,int y1,int x2,int y2,int x3,int y3, double red, double green, double blue); - - /* Filled Triangle, Blended - * Draws the triangle specified by the three pairs of points in the colour specified - * by the colour coefficients, and blended with the background. See the description for Blended Functions. - * The colour components are either doubles from 0.0 to 1.0 or ints from 0 to 65535. - * */ - void filledtriangle_blend(int x1,int y1,int x2,int y2,int x3,int y3, double opacity, int red, int green, int blue); - void filledtriangle_blend(int x1,int y1,int x2,int y2,int x3,int y3, double opacity, double red, double green, double blue); - - /* Arrow, Filled Arrow - * Plots an arrow from (x1, y1) to (x2, y2) with the arrowhead at the second point, given the size in pixels - * and the angle in radians of the arrowhead. The plotted arrow consists of one main line, and two smaller - * lines originating from the second point. Filled Arrow plots the same, but the arrowhead is a solid triangle. - * Tip: An angle of 10 to 30 degrees looks OK. - * */ - - void arrow( int x1,int y1,int x2,int y2,int size, double head_angle, double red, double green, double blue); - void arrow( int x1,int y1,int x2,int y2,int size, double head_angle, int red, int green, int blue); - - void filledarrow( int x1,int y1,int x2,int y2,int size, double head_angle, double red, double green, double blue); - void filledarrow( int x1,int y1,int x2,int y2,int size, double head_angle, int red, int green, int blue); - - /* Cross, Maltese Cross - * Plots a simple cross at x, y, with the specified height and width, and in the specified colour. - * Maltese cross plots a cross, as before, but adds bars at the end of each arm of the cross. - * The size of these bars is specified with x_bar_height and y_bar_width. - * The cross will look something like this: - * - * ----- <-- ( y_bar_width) - * | - * | - * |-------| <-- ( x_bar_height ) - * | - * | - * ----- - * */ - - void cross( int x, int y, int xwidth, int yheight, double red, double green, double blue); - void cross( int x, int y, int xwidth, int yheight, int red, int green, int blue); - - void maltesecross( int x, int y, int xwidth, int yheight, int x_bar_height, int y_bar_width, double red, double green, double blue); - void maltesecross( int x, int y, int xwidth, int yheight, int x_bar_height, int y_bar_width, int red, int green, int blue); - - /* Diamond and filled diamond - * Plots a diamond shape, given the x, y position, the width and height, and the colour. - * Filled diamond plots a filled diamond. - * */ - - void filleddiamond( int x, int y, int width, int height, int red, int green, int blue); - void diamond(int x, int y, int width, int height, int red, int green, int blue); - - void filleddiamond( int x, int y, int width, int height, double red, double green, double blue); - void diamond(int x, int y, int width, int height, double red, double green, double blue); - - /* Get Text Width, Get Text Width UTF8 - * Returns the approximate width, in pixels, of the specified *unrotated* text. It is calculated by adding - * each letter's width and kerning value (as specified in the TTF file). Note that this will not - * give the position of the farthest pixel, but it will give a pretty good idea of what area the - * text will occupy. Tip: The text, when plotted unrotated, will fit approximately in a box with its lower left corner at - * (x_start, y_start) and upper right at (x_start + width, y_start + size), where width is given by get_text_width() - * and size is the specified size of the text to be plotted. Tip: Text plotted at position - * (x_start, y_start), rotated with a given 'angle', and of a given 'size' - * whose width is 'width', will fit approximately inside a rectangle whose corners are at - * 1 (x_start, y_start) - * 2 (x_start + width*cos(angle), y_start + width*sin(angle)) - * 3 (x_start + width*cos(angle) - size*sin(angle), y_start + width*sin(angle) + size*cos(angle)) - * 4 (x_start - size*sin(angle), y_start + size*cos(angle)) - * */ - - int get_text_width(char * face_path, int fontsize, char * text); - - int get_text_width_utf8(char * face_path, int fontsize, char * text); - - -}; - - -#endif - diff --git a/src/hyperion-d.cpp b/src/hyperion-d.cpp index de05872c..34a2b391 100644 --- a/src/hyperion-d.cpp +++ b/src/hyperion-d.cpp @@ -11,7 +11,9 @@ int main(int argc, char** argv) { + // Initialising QCoreApplication QCoreApplication app(argc, argv); + std::cout << "QCoreApplication initialised" << std::endl; // Select config and schema file const std::string homeDir = getenv("RASPILIGHT_HOME"); @@ -25,11 +27,15 @@ int main(int argc, char** argv) std::cerr << "UNABLE TO LOAD CONFIGURATION" << std::endl; return -1; } + std::cout << "Configuration loaded from: " << configFile << std::endl; Hyperion hyperion(config); + std::cout << "Hyperion created and initialised" << std::endl; DispmanxWrapper dispmanx(64, 64, 10, &hyperion); dispmanx.start(); + std::cout << "Frame grabber created and started" << std::endl; app.exec(); + std::cout << "Application closed" << std::endl; } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6bcb32c6..bf2807ea 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -23,14 +23,9 @@ add_executable(TestColorTransform target_link_libraries(TestColorTransform hyperion) -# Find the libPNG -find_package(PNG REQUIRED QUIET) +add_executable(TestImage2LedsMap + TestImage2LedsMap.cpp) +target_link_libraries(TestImage2LedsMap + hyperion) -# Add additional includes dirs -include_directories(${PNG_INCLUDE_DIR}) - -add_executable(TestHyperionPng - TestHyperionPng.cpp) - -target_link_libraries(TestHyperionPng - hyperion-png) +add_subdirectory(dispmanx2png) diff --git a/test/TestImage2LedsMap.cpp b/test/TestImage2LedsMap.cpp new file mode 100644 index 00000000..752daed0 --- /dev/null +++ b/test/TestImage2LedsMap.cpp @@ -0,0 +1,44 @@ + +// Utils includes +#include +#include + +// Hyperion includes +#include +#include + +using namespace hyperion; + +int main() +{ + std::string homeDir = getenv("RASPILIGHT_HOME"); + + const std::string schemaFile = homeDir + "/hyperion.schema.json"; + const std::string configFile = homeDir + "/hyperion.config.json"; + + Json::Value config; + if (JsonFactory::load(schemaFile, configFile, config) < 0) + { + std::cerr << "UNABLE TO LOAD CONFIGURATION" << std::endl; + return -1; + } + + const LedString ledString = Hyperion::createLedString(config["leds"]); + + const RgbColor testColor = {64, 123, 12}; + + RgbImage image(64, 64, testColor); + ImageToLedsMap map(64, 64, ledString.leds()); + + std::vector ledColors(ledString.leds().size()); + map.getMeanLedColor(image, ledColors); + + std::cout << "["; + for (const RgbColor & color : ledColors) + { + std::cout << color; + } + std::cout << "]" << std::endl; + + return 0; +} diff --git a/test/dispmanx2png/CMakeLists.txt b/test/dispmanx2png/CMakeLists.txt new file mode 100644 index 00000000..bbffc142 --- /dev/null +++ b/test/dispmanx2png/CMakeLists.txt @@ -0,0 +1,18 @@ + +# Find the BCM-package (VC control) +find_package(BCM REQUIRED) +include_directories(${BCM_INCLUDE_DIRS}) + +# Configure the use of QT4 +find_package(Qt4 COMPONENTS QtTest REQUIRED QUIET) +include(${QT_USE_FILE}) +add_definitions(${QT_DEFINITIONS}) +link_directories(${CMAKE_FIND_ROOT_PATH}/lib/arm-linux-gnueabihf) + + +add_executable(dispmanx2png + dispmanx2png.cpp) + +target_link_libraries(dispmanx2png + hyperion + ${QT_LIBRARIES}) diff --git a/test/dispmanx2png/dispmanx2png.cpp b/test/dispmanx2png/dispmanx2png.cpp new file mode 100644 index 00000000..d3b48926 --- /dev/null +++ b/test/dispmanx2png/dispmanx2png.cpp @@ -0,0 +1,47 @@ + +// STL includes +#include + +// QT includes +#include +#include + +// Hyperion includes +#include + +static bool running = true; + +void signal_handler(int signum) +{ + running = false; +} + +int main() +{ + signal(SIGTERM, signal_handler); + signal(SIGINT, signal_handler); + + DispmanxFrameGrabber frameGrabber(64, 64); + + unsigned iFrame = 0; + QImage qImage(64, 64, QImage::Format_RGB888); + RgbImage rgbImage(64, 64); + + while(running) + { + frameGrabber.grabFrame(rgbImage); + + for (int iScanline=0; iScanline