From c8ce23e6528b959f4a33c387649eb7cd9a11eb0a Mon Sep 17 00:00:00 2001 From: "T. van der Zwan" Date: Tue, 19 Nov 2013 20:17:59 +0000 Subject: [PATCH 01/18] Renamed ColorTransform to RgbChannelTransform Former-commit-id: 390b832ba2d463710d4a063692f00b83a8c6c8ad --- include/hyperion/Hyperion.h | 10 +++---- ...ColorTransform.h => RgbChannelTransform.h} | 16 +++++------ libsrc/hyperion/Hyperion.cpp | 10 +++---- libsrc/hyperion/ImageProcessor.cpp | 2 -- libsrc/utils/CMakeLists.txt | 6 ++--- ...rTransform.cpp => RgbChannelTransform.cpp} | 27 ++++++++++--------- test/TestColorTransform.cpp | 11 ++++---- 7 files changed, 41 insertions(+), 41 deletions(-) rename include/utils/{ColorTransform.h => RgbChannelTransform.h} (81%) rename libsrc/utils/{ColorTransform.cpp => RgbChannelTransform.cpp} (60%) diff --git a/include/hyperion/Hyperion.h b/include/hyperion/Hyperion.h index 5026ef08..ade46e24 100644 --- a/include/hyperion/Hyperion.h +++ b/include/hyperion/Hyperion.h @@ -17,7 +17,7 @@ // Forward class declaration class HsvTransform; -class ColorTransform; +class RgbChannelTransform; /// /// The main class of Hyperion. This gives other 'users' access to the attached LedDevice through @@ -145,7 +145,7 @@ public: static ColorOrder createColorOrder(const Json::Value & deviceConfig); static LedString createLedString(const Json::Value & ledsConfig); static HsvTransform * createHsvTransform(const Json::Value & hsvConfig); - static ColorTransform * createColorTransform(const Json::Value & colorConfig); + static RgbChannelTransform * createColorTransform(const Json::Value & colorConfig); static LedDevice * createColorSmoothing(const Json::Value & smoothingConfig, LedDevice * ledDevice); private slots: @@ -173,11 +173,11 @@ private: /// The HSV Transform for applying Saturation and Value transforms HsvTransform * _hsvTransform; /// The RED-Channel (RGB) transform - ColorTransform * _redTransform; + RgbChannelTransform * _redTransform; /// The GREEN-Channel (RGB) transform - ColorTransform * _greenTransform; + RgbChannelTransform * _greenTransform; /// The BLUE-Channel (RGB) transform - ColorTransform * _blueTransform; + RgbChannelTransform * _blueTransform; /// Value with the desired color byte order ColorOrder _colorOrder; diff --git a/include/utils/ColorTransform.h b/include/utils/RgbChannelTransform.h similarity index 81% rename from include/utils/ColorTransform.h rename to include/utils/RgbChannelTransform.h index c89b3916..7f524d81 100644 --- a/include/utils/ColorTransform.h +++ b/include/utils/RgbChannelTransform.h @@ -12,21 +12,21 @@ /// 4) finally, in case of a weird choice of parameters, the output is clamped between [0:1] /// /// All configuration values are doubles and assume the color value to be between 0 and 1 -class ColorTransform +class RgbChannelTransform { public: /// Default constructor - ColorTransform(); + RgbChannelTransform(); /// Constructor - /// @param threshold - /// @param gamma - /// @param blacklevel - /// @param whitelevel - ColorTransform(double threshold, double gamma, double blacklevel, double whitelevel); + /// @param threshold The minimum threshold + /// @param gamma The gamma of the gamma-curve correction + /// @param blacklevel The minimum value for the RGB-Channel + /// @param whitelevel The maximum value for the RGB-Channel + RgbChannelTransform(double threshold, double gamma, double blacklevel, double whitelevel); /// Destructor - ~ColorTransform(); + ~RgbChannelTransform(); /// @return The current threshold value double getThreshold() const; diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp index b7c71183..ce4bd9ab 100644 --- a/libsrc/hyperion/Hyperion.cpp +++ b/libsrc/hyperion/Hyperion.cpp @@ -24,7 +24,7 @@ #include "LinearColorSmoothing.h" -#include +#include #include LedDevice* Hyperion::createDevice(const Json::Value& deviceConfig) @@ -163,14 +163,14 @@ HsvTransform * Hyperion::createHsvTransform(const Json::Value & hsvConfig) return new HsvTransform(saturationGain, valueGain); } -ColorTransform* Hyperion::createColorTransform(const Json::Value& colorConfig) +RgbChannelTransform* Hyperion::createColorTransform(const Json::Value& colorConfig) { const double threshold = colorConfig.get("threshold", 0.0).asDouble(); const double gamma = colorConfig.get("gamma", 1.0).asDouble(); const double blacklevel = colorConfig.get("blacklevel", 0.0).asDouble(); const double whitelevel = colorConfig.get("whitelevel", 1.0).asDouble(); - ColorTransform* transform = new ColorTransform(threshold, gamma, blacklevel, whitelevel); + RgbChannelTransform* transform = new RgbChannelTransform(threshold, gamma, blacklevel, whitelevel); return transform; } @@ -322,7 +322,7 @@ void Hyperion::setColors(int priority, const std::vector& ledColors, c void Hyperion::setTransform(Hyperion::Transform transform, Hyperion::Color color, double value) { // select the transform of the requested color - ColorTransform * t = nullptr; + RgbChannelTransform * t = nullptr; switch (color) { case RED: @@ -396,7 +396,7 @@ void Hyperion::clearall() double Hyperion::getTransform(Hyperion::Transform transform, Hyperion::Color color) const { // select the transform of the requested color - ColorTransform * t = nullptr; + RgbChannelTransform * t = nullptr; switch (color) { case RED: diff --git a/libsrc/hyperion/ImageProcessor.cpp b/libsrc/hyperion/ImageProcessor.cpp index d3bfba3d..a0af2077 100644 --- a/libsrc/hyperion/ImageProcessor.cpp +++ b/libsrc/hyperion/ImageProcessor.cpp @@ -4,8 +4,6 @@ #include #include -#include - using namespace hyperion; ImageProcessor::ImageProcessor(const LedString& ledString, bool enableBlackBorderDetector) : diff --git a/libsrc/utils/CMakeLists.txt b/libsrc/utils/CMakeLists.txt index 18dfd98c..52094a61 100644 --- a/libsrc/utils/CMakeLists.txt +++ b/libsrc/utils/CMakeLists.txt @@ -11,11 +11,11 @@ add_library(hyperion-utils ${CURRENT_HEADER_DIR}/ColorRgba.h ${CURRENT_SOURCE_DIR}/ColorRgba.cpp ${CURRENT_HEADER_DIR}/Image.h - ${CURRENT_HEADER_DIR}/ColorTransform.h - ${CURRENT_HEADER_DIR}/HsvTransform.h - ${CURRENT_SOURCE_DIR}/ColorTransform.cpp + ${CURRENT_HEADER_DIR}/HsvTransform.h ${CURRENT_SOURCE_DIR}/HsvTransform.cpp + ${CURRENT_HEADER_DIR}/RgbChannelTransform.h + ${CURRENT_SOURCE_DIR}/RgbChannelTransform.cpp ${CURRENT_HEADER_DIR}/jsonschema/JsonFactory.h ${CURRENT_HEADER_DIR}/jsonschema/JsonSchemaChecker.h diff --git a/libsrc/utils/ColorTransform.cpp b/libsrc/utils/RgbChannelTransform.cpp similarity index 60% rename from libsrc/utils/ColorTransform.cpp rename to libsrc/utils/RgbChannelTransform.cpp index abe7bded..bdd4ec1b 100644 --- a/libsrc/utils/ColorTransform.cpp +++ b/libsrc/utils/RgbChannelTransform.cpp @@ -1,9 +1,10 @@ // STL includes #include -#include +// Utils includes +#include -ColorTransform::ColorTransform() : +RgbChannelTransform::RgbChannelTransform() : _threshold(0), _gamma(1.0), _blacklevel(0.0), @@ -12,7 +13,7 @@ ColorTransform::ColorTransform() : initializeMapping(); } -ColorTransform::ColorTransform(double threshold, double gamma, double blacklevel, double whitelevel) : +RgbChannelTransform::RgbChannelTransform(double threshold, double gamma, double blacklevel, double whitelevel) : _threshold(threshold), _gamma(gamma), _blacklevel(blacklevel), @@ -21,55 +22,55 @@ ColorTransform::ColorTransform(double threshold, double gamma, double blacklevel initializeMapping(); } -ColorTransform::~ColorTransform() +RgbChannelTransform::~RgbChannelTransform() { } -double ColorTransform::getThreshold() const +double RgbChannelTransform::getThreshold() const { return _threshold; } -void ColorTransform::setThreshold(double threshold) +void RgbChannelTransform::setThreshold(double threshold) { _threshold = threshold; initializeMapping(); } -double ColorTransform::getGamma() const +double RgbChannelTransform::getGamma() const { return _gamma; } -void ColorTransform::setGamma(double gamma) +void RgbChannelTransform::setGamma(double gamma) { _gamma = gamma; initializeMapping(); } -double ColorTransform::getBlacklevel() const +double RgbChannelTransform::getBlacklevel() const { return _blacklevel; } -void ColorTransform::setBlacklevel(double blacklevel) +void RgbChannelTransform::setBlacklevel(double blacklevel) { _blacklevel = blacklevel; initializeMapping(); } -double ColorTransform::getWhitelevel() const +double RgbChannelTransform::getWhitelevel() const { return _whitelevel; } -void ColorTransform::setWhitelevel(double whitelevel) +void RgbChannelTransform::setWhitelevel(double whitelevel) { _whitelevel = whitelevel; initializeMapping(); } -void ColorTransform::initializeMapping() +void RgbChannelTransform::initializeMapping() { // initialize the mapping as a linear array for (int i = 0; i < 256; ++i) diff --git a/test/TestColorTransform.cpp b/test/TestColorTransform.cpp index b52c941c..21af454b 100644 --- a/test/TestColorTransform.cpp +++ b/test/TestColorTransform.cpp @@ -2,13 +2,14 @@ #include #include -#include +// Utils includes +#include int main() { { std::cout << "Testing linear transform" << std::endl; - ColorTransform t; + RgbChannelTransform t; for (int i = 0; i < 256; ++i) { uint8_t input = i; @@ -29,7 +30,7 @@ int main() { std::cout << "Testing threshold" << std::endl; - ColorTransform t(.10, 1.0, 0.0, 1.0); + RgbChannelTransform t(.10, 1.0, 0.0, 1.0); for (int i = 0; i < 256; ++i) { uint8_t input = i; @@ -50,7 +51,7 @@ int main() { std::cout << "Testing blacklevel and whitelevel" << std::endl; - ColorTransform t(0, 1.0, 0.2, 0.8); + RgbChannelTransform t(0, 1.0, 0.2, 0.8); for (int i = 0; i < 256; ++i) { uint8_t input = i; @@ -71,7 +72,7 @@ int main() { std::cout << "Testing gamma" << std::endl; - ColorTransform t(0, 2.0, 0.0, 1.0); + RgbChannelTransform t(0, 2.0, 0.0, 1.0); for (int i = 0; i < 256; ++i) { uint8_t input = i; From ba2939f9ec4706edbab18fe2c73472a0b43ffad8 Mon Sep 17 00:00:00 2001 From: "T. van der Zwan" Date: Wed, 20 Nov 2013 08:25:49 +0000 Subject: [PATCH 02/18] Added multi colortransform (not working yet) Former-commit-id: 691a0a9d83e57e00d305cf18718cab05156c2dce --- include/hyperion/Hyperion.h | 30 +++---- libsrc/hyperion/CMakeLists.txt | 3 + libsrc/hyperion/Hyperion.cpp | 82 ++++++++++-------- libsrc/hyperion/MultiColorTransform.cpp | 105 ++++++++++++++++++++++++ libsrc/hyperion/MultiColorTransform.h | 73 ++++++++++++++++ 5 files changed, 241 insertions(+), 52 deletions(-) create mode 100644 libsrc/hyperion/MultiColorTransform.cpp create mode 100644 libsrc/hyperion/MultiColorTransform.h diff --git a/include/hyperion/Hyperion.h b/include/hyperion/Hyperion.h index ade46e24..6f726241 100644 --- a/include/hyperion/Hyperion.h +++ b/include/hyperion/Hyperion.h @@ -18,6 +18,7 @@ // Forward class declaration class HsvTransform; class RgbChannelTransform; +class MultiColorTransform; /// /// The main class of Hyperion. This gives other 'users' access to the attached LedDevice through @@ -33,7 +34,7 @@ public: /// /// RGB-Color channel enumeration /// - enum Color + enum RgbChannel { RED, GREEN, BLUE, INVALID }; @@ -96,7 +97,7 @@ public: /// Transform::WHITELEVEL) /// @param[in] value The new value for the given transform /// - void setTransform(Transform transform, Color color, double value); + void setTransform(Transform transform, RgbChannel color, double value); /// /// Clears the given priority channel. This will switch the led-colors to the colors of the next @@ -121,7 +122,7 @@ public: /// /// @return The value of the specified color transform /// - double getTransform(Transform transform, Color color) const; + double getTransform(Transform transform, RgbChannel color) const; /// /// Returns a list of active priorities @@ -144,8 +145,11 @@ public: static LedDevice * createDevice(const Json::Value & deviceConfig); static ColorOrder createColorOrder(const Json::Value & deviceConfig); static LedString createLedString(const Json::Value & ledsConfig); + + static MultiColorTransform * createLedColorsTransform(const unsigned ledCnt, const Json::Value & colorTransformConfig); static HsvTransform * createHsvTransform(const Json::Value & hsvConfig); - static RgbChannelTransform * createColorTransform(const Json::Value & colorConfig); + static RgbChannelTransform * createColorTransform(const Json::Value& colorConfig); + static LedDevice * createColorSmoothing(const Json::Value & smoothingConfig, LedDevice * ledDevice); private slots: @@ -156,28 +160,14 @@ private slots: void update(); private: - /// - /// Applies all color transmforms to the given list of colors. The transformation is performed - /// in place. - /// - /// @param colors The colors to be transformed - /// - void applyTransform(std::vector& colors) const; - /// The specifiation of the led frame construction and picture integration LedString _ledString; /// The priority muxer PriorityMuxer _muxer; - /// The HSV Transform for applying Saturation and Value transforms - HsvTransform * _hsvTransform; - /// The RED-Channel (RGB) transform - RgbChannelTransform * _redTransform; - /// The GREEN-Channel (RGB) transform - RgbChannelTransform * _greenTransform; - /// The BLUE-Channel (RGB) transform - RgbChannelTransform * _blueTransform; + /// The transformation from raw colors to led colors + MultiColorTransform * _raw2ledTransform; /// Value with the desired color byte order ColorOrder _colorOrder; diff --git a/libsrc/hyperion/CMakeLists.txt b/libsrc/hyperion/CMakeLists.txt index 937a8906..4ad8df23 100644 --- a/libsrc/hyperion/CMakeLists.txt +++ b/libsrc/hyperion/CMakeLists.txt @@ -24,6 +24,8 @@ SET(Hyperion_HEADERS ${CURRENT_HEADER_DIR}/BlackBorderDetector.h ${CURRENT_HEADER_DIR}/BlackBorderProcessor.h + ${CURRENT_SOURCE_DIR}/MultiColorTransform.h + ${CURRENT_SOURCE_DIR}/device/LedSpiDevice.h ${CURRENT_SOURCE_DIR}/device/LedRs232Device.h ${CURRENT_SOURCE_DIR}/device/LedDeviceTest.h @@ -45,6 +47,7 @@ SET(Hyperion_SOURCES ${CURRENT_SOURCE_DIR}/BlackBorderDetector.cpp ${CURRENT_SOURCE_DIR}/BlackBorderProcessor.cpp ${CURRENT_SOURCE_DIR}/ImageToLedsMap.cpp + ${CURRENT_SOURCE_DIR}/MultiColorTransform.cpp ${CURRENT_SOURCE_DIR}/LinearColorSmoothing.cpp ${CURRENT_SOURCE_DIR}/device/LedSpiDevice.cpp diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp index ce4bd9ab..757ef10c 100644 --- a/libsrc/hyperion/Hyperion.cpp +++ b/libsrc/hyperion/Hyperion.cpp @@ -22,11 +22,9 @@ #include "device/LedDeviceLightpack.h" #include "device/LedDeviceMultiLightpack.h" +#include "MultiColorTransform.h" #include "LinearColorSmoothing.h" -#include -#include - LedDevice* Hyperion::createDevice(const Json::Value& deviceConfig) { std::cout << "Device configuration: " << deviceConfig << std::endl; @@ -155,6 +153,33 @@ Hyperion::ColorOrder Hyperion::createColorOrder(const Json::Value &deviceConfig) return ORDER_RGB; } +MultiColorTransform * Hyperion::createLedColorsTransform(const unsigned ledCnt, const Json::Value & colorConfig) +{ + MultiColorTransform * transform = new MultiColorTransform(); + if (!colorConfig.isArray()) + { + // Old style color transformation config (just one for all leds) + const std::string id = "default"; + + RgbChannelTransform * redTransform = createColorTransform(colorConfig["red"]); + RgbChannelTransform * greenTransform = createColorTransform(colorConfig["green"]); + RgbChannelTransform * blueTransform = createColorTransform(colorConfig["blue"]); + + HsvTransform * hsvTransform = createHsvTransform("hsv"); + transform->addTransform(id, *redTransform, *greenTransform, *blueTransform, *hsvTransform); + transform->setTransformForLed(id, 0, ledCnt-1); + + delete redTransform; + delete greenTransform; + delete blueTransform; + } + else + { + + } + return transform; +} + HsvTransform * Hyperion::createHsvTransform(const Json::Value & hsvConfig) { const double saturationGain = hsvConfig.get("saturationGain", 1.0).asDouble(); @@ -246,10 +271,7 @@ LedDevice * Hyperion::createColorSmoothing(const Json::Value & smoothingConfig, Hyperion::Hyperion(const Json::Value &jsonConfig) : _ledString(createLedString(jsonConfig["leds"])), _muxer(_ledString.leds().size()), - _hsvTransform(createHsvTransform(jsonConfig["color"]["hsv"])), - _redTransform(createColorTransform(jsonConfig["color"]["red"])), - _greenTransform(createColorTransform(jsonConfig["color"]["green"])), - _blueTransform(createColorTransform(jsonConfig["color"]["blue"])), + _raw2ledTransform(createLedColorsTransform(_ledString.leds().size(), jsonConfig["color"])), _colorOrder(createColorOrder(jsonConfig["device"])), _device(createDevice(jsonConfig["device"])), _timer() @@ -278,13 +300,8 @@ Hyperion::~Hyperion() // Delete the Led-String delete _device; - // delete he hsv transform - delete _hsvTransform; - - // Delete the color-transform - delete _blueTransform; - delete _greenTransform; - delete _redTransform; + // delete the color transform + delete _raw2ledTransform; } unsigned Hyperion::getLedCount() const @@ -319,20 +336,23 @@ void Hyperion::setColors(int priority, const std::vector& ledColors, c } } -void Hyperion::setTransform(Hyperion::Transform transform, Hyperion::Color color, double value) +void Hyperion::setTransform(Hyperion::Transform transform, Hyperion::RgbChannel color, double value) { + ColorTransform* colorTransform = _raw2ledTransform->getTransform("default"); + assert(colorTransform != nullptr); + // select the transform of the requested color RgbChannelTransform * t = nullptr; switch (color) { case RED: - t = _redTransform; + t = &(colorTransform->_rgbRedTransform); break; case GREEN: - t = _greenTransform; + t = &(colorTransform->_rgbGreenTransform); break; case BLUE: - t = _blueTransform; + t = &(colorTransform->_rgbBlueTransform); break; default: break; @@ -342,10 +362,10 @@ void Hyperion::setTransform(Hyperion::Transform transform, Hyperion::Color color switch (transform) { case SATURATION_GAIN: - _hsvTransform->setSaturationGain(value); + colorTransform->_hsvTransform.setSaturationGain(value); break; case VALUE_GAIN: - _hsvTransform->setValueGain(value); + colorTransform->_hsvTransform.setValueGain(value); break; case THRESHOLD: assert (t != nullptr); @@ -393,20 +413,23 @@ void Hyperion::clearall() update(); } -double Hyperion::getTransform(Hyperion::Transform transform, Hyperion::Color color) const +double Hyperion::getTransform(Hyperion::Transform transform, Hyperion::RgbChannel color) const { + ColorTransform * colorTransform = _raw2ledTransform->getTransform("default"); + assert(colorTransform != nullptr); + // select the transform of the requested color RgbChannelTransform * t = nullptr; switch (color) { case RED: - t = _redTransform; + t = &(colorTransform->_rgbRedTransform); break; case GREEN: - t = _greenTransform; + t = &(colorTransform->_rgbGreenTransform); break; case BLUE: - t = _blueTransform; + t = &(colorTransform->_rgbBlueTransform); break; default: break; @@ -416,9 +439,9 @@ double Hyperion::getTransform(Hyperion::Transform transform, Hyperion::Color col switch (transform) { case SATURATION_GAIN: - return _hsvTransform->getSaturationGain(); + return colorTransform->_hsvTransform.getSaturationGain(); case VALUE_GAIN: - return _hsvTransform->getValueGain(); + return colorTransform->_hsvTransform.getValueGain(); case THRESHOLD: assert (t != nullptr); return t->getThreshold(); @@ -458,14 +481,9 @@ void Hyperion::update() const PriorityMuxer::InputInfo & priorityInfo = _muxer.getInputInfo(priority); // Apply the transform to each led and color-channel - std::vector ledColors(priorityInfo.ledColors); + std::vector ledColors = _raw2ledTransform->applyTransform(priorityInfo.ledColors); for (ColorRgb& color : ledColors) { - _hsvTransform->transform(color.red, color.green, color.blue); - color.red = _redTransform->transform(color.red); - color.green = _greenTransform->transform(color.green); - color.blue = _blueTransform->transform(color.blue); - // correct the color byte order switch (_colorOrder) { diff --git a/libsrc/hyperion/MultiColorTransform.cpp b/libsrc/hyperion/MultiColorTransform.cpp new file mode 100644 index 00000000..99b81b27 --- /dev/null +++ b/libsrc/hyperion/MultiColorTransform.cpp @@ -0,0 +1,105 @@ + +// STL includes +#include + +// Hyperion includes +#include "MultiColorTransform.h" + +MultiColorTransform::MultiColorTransform() +{ +} + +MultiColorTransform::~MultiColorTransform() +{ + // Clean up all the transforms + for (ColorTransform * transform : _transform) + { + delete transform; + } +} + +void MultiColorTransform::addTransform(const std::string & id, + const RgbChannelTransform & redTransform, + const RgbChannelTransform & greenTransform, + const RgbChannelTransform & blueTransform, + const HsvTransform & hsvTransform) +{ + ColorTransform * transform = new ColorTransform(); + transform->_id = id; + + transform->_rgbRedTransform = redTransform; + transform->_rgbGreenTransform = greenTransform; + transform->_rgbBlueTransform = blueTransform; + + transform->_hsvTransform = hsvTransform; + + _transform.push_back(transform); +} + +void MultiColorTransform::setTransformForLed(const std::string& id, const unsigned startLed, const unsigned endLed) +{ + assert(startLed <= endLed); + + // Make sure that there are at least enough led transforms to match the given indices + if (_ledTransforms.size() < endLed+1) + { + _ledTransforms.resize(endLed+1, nullptr); + } + + // Get the identified transform (don't care if is nullptr) + ColorTransform * transform = getTransform(id); + for (unsigned iLed=startLed; iLed<=endLed; ++iLed) + { + _ledTransforms[iLed] = transform; + } +} + +std::vector MultiColorTransform::getTransformIds() +{ + // Create the list on the fly + std::vector transformIds; + for (ColorTransform* transform : _transform) + { + transformIds.push_back(transform->_id); + } + return transformIds; +} + +ColorTransform* MultiColorTransform::getTransform(const std::string& id) +{ + // Iterate through the unique transforms until we find the one with the given id + for (ColorTransform* transform : _transform) + { + if (transform->_id == id) + { + return transform; + } + } + + // The ColorTransform was not found + return nullptr; +} + +std::vector MultiColorTransform::applyTransform(const std::vector& rawColors) +{ + // Create a copy, as we will do the rest of the transformation in place + std::vector ledColors(rawColors); + + const size_t itCnt = std::min(_transform.size(), rawColors.size()); + for (size_t i=0; i_hsvTransform.transform(color.red, color.green, color.blue); + color.red = transform->_rgbRedTransform.transform(color.red); + color.green = transform->_rgbGreenTransform.transform(color.green); + color.blue = transform->_rgbBlueTransform.transform(color.blue); + } + return ledColors; +} diff --git a/libsrc/hyperion/MultiColorTransform.h b/libsrc/hyperion/MultiColorTransform.h new file mode 100644 index 00000000..1fcb4849 --- /dev/null +++ b/libsrc/hyperion/MultiColorTransform.h @@ -0,0 +1,73 @@ +#pragma once + +// STL includes +#include + +// Utils includes +#include + +#include +#include + +struct ColorTransform +{ + std::string _id; + /// The RED-Channel (RGB) transform + RgbChannelTransform _rgbRedTransform; + /// The GREEN-Channel (RGB) transform + RgbChannelTransform _rgbGreenTransform; + /// The BLUE-Channel (RGB) transform + RgbChannelTransform _rgbBlueTransform; + /// The HSV Transform for applying Saturation and Value transforms + HsvTransform _hsvTransform; +}; + +/// +/// The LedColorTransform is responsible for performing color transformation from 'raw' colors +/// received as input to colors mapped to match the color-properties of the leds. +/// +class MultiColorTransform +{ +public: + MultiColorTransform(); + ~MultiColorTransform(); + + void addTransform(const std::string & id, + const RgbChannelTransform & redTransform, + const RgbChannelTransform & greenTransform, + const RgbChannelTransform & blueTransform, + const HsvTransform & hsvTransform); + + void setTransformForLed(const std::string& id, const unsigned startLed, const unsigned endLed); + + /// + /// Returns the identifier of all the unique ColorTransform + /// + /// @return The list with unique id's of the ColorTransforms + std::vector getTransformIds(); + + /// + /// Returns the pointer to the ColorTransform with the given id + /// + /// @param id The identifier of the ColorTransform + /// + /// @return The ColorTransform with the given id (or nullptr if it does not exist) + /// + ColorTransform* getTransform(const std::string& id); + + /// + /// Performs the color transoformation from raw-color to led-color + /// + /// @param rawColors The list with raw colors + /// + /// @return The list with led-colors + /// + std::vector applyTransform(const std::vector& rawColors); + +private: + /// List with unique ColorTransforms + std::vector _transform; + + /// List with a pointer to the ColorTransform for each individual led + std::vector _ledTransforms; +}; From 747e0dbfaeabc1e9aaba1716cba7b1225192abc2 Mon Sep 17 00:00:00 2001 From: "T. van der Zwan" Date: Wed, 20 Nov 2013 09:05:21 +0000 Subject: [PATCH 03/18] Added build-x86 to ignore Former-commit-id: 7e901bcbbe26033902b446f4c85680d8017ccfdb --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 28305334..6a5b347a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /*.user /build +/build-x86 From a52215ac8a62d5d4d7952bf1cea9d1d0e9080c5a Mon Sep 17 00:00:00 2001 From: "T. van der Zwan" Date: Wed, 20 Nov 2013 09:05:49 +0000 Subject: [PATCH 04/18] Added configuration file for x86 platform (output device switched to 'test') Former-commit-id: bea158c81f3d13f6761cbe3d59ab28502830e787 --- config/hyperion_x86.config.json | 400 ++++++++++++++++++++++++++++++++ 1 file changed, 400 insertions(+) create mode 100644 config/hyperion_x86.config.json diff --git a/config/hyperion_x86.config.json b/config/hyperion_x86.config.json new file mode 100644 index 00000000..08b0ce8e --- /dev/null +++ b/config/hyperion_x86.config.json @@ -0,0 +1,400 @@ +// Automatically generated configuration file for 'Hyperion daemon' +// Generated by: HyperCon (The Hyperion deamon configuration file builder + +{ + /// Device configuration contains the following fields: + /// * 'name' : The user friendly name of the device (only used for display purposes) + /// * 'type' : The type of the device or leds (known types for now are 'ws2801', 'ldp8806', + /// 'lpd6803', 'sedu', 'adalight', 'lightpack', 'test' and 'none') + /// * 'output' : The output specification depends on selected device. This can for example be the + /// device specifier, device serial number, or the output file name + /// * 'rate' : The baudrate of the output to the device + /// * 'colorOrder' : The order of the color bytes ('rgb', 'rbg', 'bgr', etc.). + "device" : + { + "name" : "MyPi", + "type" : "test", + "output" : "./hyperiond.test.out", + "rate" : 500000, + "colorOrder" : "rgb" + }, + + /// Color manipulation configuration used to tune the output colors to specific surroundings. Contains the following fields: + /// * 'hsv' : The manipulation in the Hue-Saturation-Value color domain with the following tuning parameters: + /// - 'saturationGain' The gain adjustement of the saturation + /// - 'valueGain' The gain adjustement of the value + /// * 'red'/'green'/'blue' : The manipulation in the Red-Green-Blue color domain with the following tuning parameters for each channel: + /// - 'threshold' The minimum required input value for the channel to be on (else zero) + /// - 'gamma' The gamma-curve correction factor + /// - 'blacklevel' The lowest possible value (when the channel is black) + /// - 'whitelevel' The highest possible value (when the channel is white) + /// * 'smoothing' : Smoothing of the colors in the time-domain with the following tuning parameters: + /// - 'type' The type of smoothing algorithm ('linear' or 'none') + /// - 'time_ms' The time constant for smoothing algorithm in milliseconds + /// - 'updateFrequency' The update frequency of the leds in Hz + "color" : + { + "hsv" : + { + "saturationGain" : 1.0000, + "valueGain" : 1.5000 + }, + "red" : + { + "threshold" : 0.1000, + "gamma" : 2.0000, + "blacklevel" : 0.0000, + "whitelevel" : 0.8000 + }, + "green" : + { + "threshold" : 0.1000, + "gamma" : 2.0000, + "blacklevel" : 0.0000, + "whitelevel" : 1.0000 + }, + "blue" : + { + "threshold" : 0.1000, + "gamma" : 2.0000, + "blacklevel" : 0.0000, + "whitelevel" : 1.0000 + }, + "smoothing" : + { + "type" : "none", + "time_ms" : 200, + "updateFrequency" : 20.0000 + } + }, + + /// The configuration for each individual led. This contains the specification of the area + /// averaged of an input image for each led to determine its color. Each item in the list + /// contains the following fields: + /// * index: The index of the led. This determines its location in the string of leds; zero + /// being the first led. + /// * hscan: The fractional part of the image along the horizontal used for the averaging + /// (minimum and maximum inclusive) + /// * vscan: The fractional part of the image along the vertical used for the averaging + /// (minimum and maximum inclusive) + "leds" : + [ + { + "index" : 0, + "hscan" : { "minimum" : 0.4375, "maximum" : 0.5000 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + }, + { + "index" : 1, + "hscan" : { "minimum" : 0.3750, "maximum" : 0.4375 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + }, + { + "index" : 2, + "hscan" : { "minimum" : 0.3125, "maximum" : 0.3750 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + }, + { + "index" : 3, + "hscan" : { "minimum" : 0.2500, "maximum" : 0.3125 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + }, + { + "index" : 4, + "hscan" : { "minimum" : 0.1875, "maximum" : 0.2500 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + }, + { + "index" : 5, + "hscan" : { "minimum" : 0.1250, "maximum" : 0.1875 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + }, + { + "index" : 6, + "hscan" : { "minimum" : 0.0625, "maximum" : 0.1250 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + }, + { + "index" : 7, + "hscan" : { "minimum" : 0.0000, "maximum" : 0.0625 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + }, + { + "index" : 8, + "hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + }, + { + "index" : 9, + "hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, + "vscan" : { "minimum" : 0.8571, "maximum" : 1.0000 } + }, + { + "index" : 10, + "hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, + "vscan" : { "minimum" : 0.7143, "maximum" : 0.8571 } + }, + { + "index" : 11, + "hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, + "vscan" : { "minimum" : 0.5714, "maximum" : 0.7143 } + }, + { + "index" : 12, + "hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, + "vscan" : { "minimum" : 0.4286, "maximum" : 0.5714 } + }, + { + "index" : 13, + "hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, + "vscan" : { "minimum" : 0.2857, "maximum" : 0.4286 } + }, + { + "index" : 14, + "hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, + "vscan" : { "minimum" : 0.1429, "maximum" : 0.2857 } + }, + { + "index" : 15, + "hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.1429 } + }, + { + "index" : 16, + "hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 17, + "hscan" : { "minimum" : 0.0000, "maximum" : 0.0625 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 18, + "hscan" : { "minimum" : 0.0625, "maximum" : 0.1250 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 19, + "hscan" : { "minimum" : 0.1250, "maximum" : 0.1875 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 20, + "hscan" : { "minimum" : 0.1875, "maximum" : 0.2500 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 21, + "hscan" : { "minimum" : 0.2500, "maximum" : 0.3125 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 22, + "hscan" : { "minimum" : 0.3125, "maximum" : 0.3750 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 23, + "hscan" : { "minimum" : 0.3750, "maximum" : 0.4375 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 24, + "hscan" : { "minimum" : 0.4375, "maximum" : 0.5000 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 25, + "hscan" : { "minimum" : 0.5000, "maximum" : 0.5625 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 26, + "hscan" : { "minimum" : 0.5625, "maximum" : 0.6250 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 27, + "hscan" : { "minimum" : 0.6250, "maximum" : 0.6875 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 28, + "hscan" : { "minimum" : 0.6875, "maximum" : 0.7500 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 29, + "hscan" : { "minimum" : 0.7500, "maximum" : 0.8125 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 30, + "hscan" : { "minimum" : 0.8125, "maximum" : 0.8750 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 31, + "hscan" : { "minimum" : 0.8750, "maximum" : 0.9375 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 32, + "hscan" : { "minimum" : 0.9375, "maximum" : 1.0000 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 33, + "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 34, + "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.1429 } + }, + { + "index" : 35, + "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, + "vscan" : { "minimum" : 0.1429, "maximum" : 0.2857 } + }, + { + "index" : 36, + "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, + "vscan" : { "minimum" : 0.2857, "maximum" : 0.4286 } + }, + { + "index" : 37, + "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, + "vscan" : { "minimum" : 0.4286, "maximum" : 0.5714 } + }, + { + "index" : 38, + "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, + "vscan" : { "minimum" : 0.5714, "maximum" : 0.7143 } + }, + { + "index" : 39, + "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, + "vscan" : { "minimum" : 0.7143, "maximum" : 0.8571 } + }, + { + "index" : 40, + "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, + "vscan" : { "minimum" : 0.8571, "maximum" : 1.0000 } + }, + { + "index" : 41, + "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + }, + { + "index" : 42, + "hscan" : { "minimum" : 0.9375, "maximum" : 1.0000 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + }, + { + "index" : 43, + "hscan" : { "minimum" : 0.8750, "maximum" : 0.9375 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + }, + { + "index" : 44, + "hscan" : { "minimum" : 0.8125, "maximum" : 0.8750 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + }, + { + "index" : 45, + "hscan" : { "minimum" : 0.7500, "maximum" : 0.8125 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + }, + { + "index" : 46, + "hscan" : { "minimum" : 0.6875, "maximum" : 0.7500 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + }, + { + "index" : 47, + "hscan" : { "minimum" : 0.6250, "maximum" : 0.6875 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + }, + { + "index" : 48, + "hscan" : { "minimum" : 0.5625, "maximum" : 0.6250 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + }, + { + "index" : 49, + "hscan" : { "minimum" : 0.5000, "maximum" : 0.5625 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + } + ], + + /// The black border configuration, contains the following items: + /// * enable : true if the detector should be activated + "blackborderdetector" : + { + "enable" : true + }, + + /// The boot-sequence configuration, contains the following items: + /// * type : The type of the boot-sequence ('rainbow', 'knight_rider', 'none') + /// * duration_ms : The length of the boot-sequence [ms] + "bootsequence" : + { + "type" : "Rainbow", + "duration_ms" : 3000 + }, + + /// The configuration for the frame-grabber, contains the following items: + /// * width : The width of the grabbed frames [pixels] + /// * height : The height of the grabbed frames [pixels] + /// * frequency_Hz : The frequency of the frame grab [Hz] + "framegrabber" : + { + "width" : 64, + "height" : 64, + "frequency_Hz" : 10.0 + }, + + /// The configuration of the XBMC connection used to enable and disable the frame-grabber. Contains the following fields: + /// * xbmcAddress : The IP address of the XBMC-host + /// * xbmcTcpPort : The TCP-port of the XBMC-server + /// * grabVideo : Flag indicating that the frame-grabber is on(true) during video playback + /// * grabPictures : Flag indicating that the frame-grabber is on(true) during picture show + /// * grabAudio : Flag indicating that the frame-grabber is on(true) during audio playback + /// * grabMenu : Flag indicating that the frame-grabber is on(true) in the XBMC menu + "xbmcVideoChecker" : + { + "xbmcAddress" : "127.0.0.1", + "xbmcTcpPort" : 9090, + "grabVideo" : true, + "grabPictures" : true, + "grabAudio" : true, + "grabMenu" : false + }, + + /// The configuration of the Json server which enables the json remote interface + /// * port : Port at which the json server is started + "jsonServer" : + { + "port" : 19444 + }, + + /// The configuration of the Proto server which enables the protobuffer remote interface + /// * port : Port at which the protobuffer server is started + "protoServer" : + { + "port" : 19445 + }, + + /// The configuration of the boblight server which enables the boblight remote interface + /// * port : Port at which the boblight server is started +// "boblightServer" : +// { +// "port" : 19333 +// }, + + "end-of-json" : "end-of-json" +} From d78cbe55d6b8551da174afd0f18aab2cea855bab Mon Sep 17 00:00:00 2001 From: "T. van der Zwan" Date: Wed, 20 Nov 2013 09:06:12 +0000 Subject: [PATCH 05/18] Fixed BlackBorder test after changes to blackborder detector Former-commit-id: fc09afcbe23227cd44a72c23ddd0c4ee484b7478 --- test/TestBlackBorderProcessor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/TestBlackBorderProcessor.cpp b/test/TestBlackBorderProcessor.cpp index beb018f0..f5317f05 100644 --- a/test/TestBlackBorderProcessor.cpp +++ b/test/TestBlackBorderProcessor.cpp @@ -148,7 +148,7 @@ int main() // Switch back (in one shot) to no border assert(processor.process(noBorderImage)); - assert(processor.getCurrentBorder().type == BlackBorder::none); + assert(processor.getCurrentBorder().verticalSize == 0 && processor.getCurrentBorder().horizontalSize == 0); return 0; } From eaec09f02998f9f37e0fcdcaf640c75d446048b7 Mon Sep 17 00:00:00 2001 From: "T. van der Zwan" Date: Wed, 20 Nov 2013 09:06:41 +0000 Subject: [PATCH 06/18] Fixed MultiColorTransform creation for 'hsv' Former-commit-id: 6963e2d022c38f31fcb5371ac5bd9057c4eaf088 --- libsrc/hyperion/Hyperion.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp index 757ef10c..64b1be63 100644 --- a/libsrc/hyperion/Hyperion.cpp +++ b/libsrc/hyperion/Hyperion.cpp @@ -165,7 +165,7 @@ MultiColorTransform * Hyperion::createLedColorsTransform(const unsigned ledCnt, RgbChannelTransform * greenTransform = createColorTransform(colorConfig["green"]); RgbChannelTransform * blueTransform = createColorTransform(colorConfig["blue"]); - HsvTransform * hsvTransform = createHsvTransform("hsv"); + HsvTransform * hsvTransform = createHsvTransform(colorConfig["hsv"]); transform->addTransform(id, *redTransform, *greenTransform, *blueTransform, *hsvTransform); transform->setTransformForLed(id, 0, ledCnt-1); From ddc7bdd3315cb08658608c80c4a9fe95349e037c Mon Sep 17 00:00:00 2001 From: "T. van der Zwan" Date: Wed, 20 Nov 2013 09:07:01 +0000 Subject: [PATCH 07/18] Fixed use of 'enum' as type is schema Former-commit-id: 017cfe70198b37a05b9a852b30d783e239bf604b --- libsrc/utils/jsonschema/JsonSchemaChecker.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libsrc/utils/jsonschema/JsonSchemaChecker.cpp b/libsrc/utils/jsonschema/JsonSchemaChecker.cpp index 2ace25a5..4cfa0935 100644 --- a/libsrc/utils/jsonschema/JsonSchemaChecker.cpp +++ b/libsrc/utils/jsonschema/JsonSchemaChecker.cpp @@ -162,6 +162,8 @@ void JsonSchemaChecker::checkType(const Json::Value & value, const Json::Value & wrongType = !value.isArray(); else if (type == "null") wrongType = !value.isNull(); + else if (type == "enum") + wrongType = !value.isString(); else if (type == "any") wrongType = false; else From e43778b08b3af53080be2688836c41d32795f2df Mon Sep 17 00:00:00 2001 From: "T. van der Zwan" Date: Fri, 22 Nov 2013 10:44:41 +0000 Subject: [PATCH 08/18] Added small test to parse some parts of the json file Former-commit-id: 2ecdb7d12289d63a5fde051262162d01d768c328 --- test/CMakeLists.txt | 4 ++++ test/TestQRegExp.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 test/TestQRegExp.cpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 5e2844e3..22957155 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -41,5 +41,9 @@ add_executable(test_blackborderprocessor target_link_libraries(test_blackborderprocessor hyperion) +add_executable(test_qregexp TestQRegExp.cpp) +target_link_libraries(test_qregexp + ${QT_LIBRARIES}) + add_executable(spidev_test spidev_test.c) add_executable(gpio2spi switchPinCtrl.c) diff --git a/test/TestQRegExp.cpp b/test/TestQRegExp.cpp new file mode 100644 index 00000000..efc74227 --- /dev/null +++ b/test/TestQRegExp.cpp @@ -0,0 +1,50 @@ + +// STL includes +#include + +// QT includes +#include +#include +#include + +int main() +{ + QString testString = "1-9, 11, 12,13,16-17"; + + QRegExp overallExp("([0-9]+(\\-[0-9]+)?)(,[ ]*([0-9]+(\\-[0-9]+)?))*"); + { + + std::cout << "[1] Match found: " << (overallExp.exactMatch("5")?"true":"false") << std::endl; + std::cout << "[1] Match found: " << (overallExp.exactMatch("4-")?"true":"false") << std::endl; + std::cout << "[1] Match found: " << (overallExp.exactMatch("-4")?"true":"false") << std::endl; + std::cout << "[1] Match found: " << (overallExp.exactMatch("3-9")?"true":"false") << std::endl; + std::cout << "[1] Match found: " << (overallExp.exactMatch("1-90")?"true":"false") << std::endl; + std::cout << "[1] Match found: " << (overallExp.exactMatch("1-90,100")?"true":"false") << std::endl; + std::cout << "[1] Match found: " << (overallExp.exactMatch("1-90, 100")?"true":"false") << std::endl; + std::cout << "[1] Match found: " << (overallExp.exactMatch("1-90, 100-200")?"true":"false") << std::endl; + std::cout << "[1] Match found: " << (overallExp.exactMatch("1-90, 100-200, 100")?"true":"false") << std::endl; + } + { + if (!overallExp.exactMatch(testString)) { + std::cout << "No correct match" << std::endl; + return -1; + } + QStringList splitString = testString.split(QChar(',')); + for (int i=0; i " << startInd << "-" << endInd << std::endl; + } + else + { + int index = splitString[i].toInt(); + std::cout << "==> " << index << std::endl; + } + } + } + + return 0; +} From 42b322a0118ea5845b4bcddb779484e9730ab722 Mon Sep 17 00:00:00 2001 From: "T. van der Zwan" Date: Fri, 22 Nov 2013 10:46:40 +0000 Subject: [PATCH 09/18] Updated x86 config file with more color transforms Former-commit-id: 062ab180f30f3b1c3c236e6c3d0286da82e991ab --- CMakeLists.txt | 2 + config/hyperion_x86.config.json | 132 ++++++++++++++++++++------------ 2 files changed, 87 insertions(+), 47 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index eaf2690b..cc92e72c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,6 +37,7 @@ include_directories(${CMAKE_SOURCE_DIR}/include) # Prefer static linking over dynamic set(CMAKE_FIND_LIBRARY_SUFFIXES ".a;.so") +#set(CMAKE_BUILD_TYPE "Debug") set(CMAKE_BUILD_TYPE "Release") # enable C++11 @@ -60,6 +61,7 @@ link_directories(${CMAKE_FIND_ROOT_PATH}/lib/arm-linux-gnueabihf) configure_file(bin/install_hyperion.sh ${LIBRARY_OUTPUT_PATH} @ONLY) configure_file(config/hyperion.config.json ${LIBRARY_OUTPUT_PATH} @ONLY) +configure_file(config/hyperion_x86.config.json ${LIBRARY_OUTPUT_PATH} @ONLY) # Add the source/lib directories add_subdirectory(dependencies) diff --git a/config/hyperion_x86.config.json b/config/hyperion_x86.config.json index 08b0ce8e..807177e4 100644 --- a/config/hyperion_x86.config.json +++ b/config/hyperion_x86.config.json @@ -2,7 +2,7 @@ // Generated by: HyperCon (The Hyperion deamon configuration file builder { - /// Device configuration contains the following fields: + /// Device configuration contains the following fields: /// * 'name' : The user friendly name of the device (only used for display purposes) /// * 'type' : The type of the device or leds (known types for now are 'ws2801', 'ldp8806', /// 'lpd6803', 'sedu', 'adalight', 'lightpack', 'test' and 'none') @@ -34,32 +34,70 @@ /// - 'updateFrequency' The update frequency of the leds in Hz "color" : { - "hsv" : - { - "saturationGain" : 1.0000, - "valueGain" : 1.5000 - }, - "red" : - { - "threshold" : 0.1000, - "gamma" : 2.0000, - "blacklevel" : 0.0000, - "whitelevel" : 0.8000 - }, - "green" : - { - "threshold" : 0.1000, - "gamma" : 2.0000, - "blacklevel" : 0.0000, - "whitelevel" : 1.0000 - }, - "blue" : - { - "threshold" : 0.1000, - "gamma" : 2.0000, - "blacklevel" : 0.0000, - "whitelevel" : 1.0000 - }, + "transform" : + [ + { + "id" : "device_1", + "leds" : "0,1,2,3-10, 12-32, 33, 34, 35-49", + "hsv" : + { + "saturationGain" : 1.0000, + "valueGain" : 1.5000 + }, + "red" : + { + "threshold" : 0.1000, + "gamma" : 2.0000, + "blacklevel" : 0.0000, + "whitelevel" : 0.8000 + }, + "green" : + { + "threshold" : 0.1000, + "gamma" : 2.0000, + "blacklevel" : 0.0000, + "whitelevel" : 1.0000 + }, + "blue" : + { + "threshold" : 0.1000, + "gamma" : 2.0000, + "blacklevel" : 0.0000, + "whitelevel" : 1.0000 + } + }, + { + "id" : "device_2", + "leds" : "11", + "hsv" : + { + "saturationGain" : 1.0000, + "valueGain" : 1.5000 + }, + "red" : + { + "threshold" : 0.1000, + "gamma" : 2.0000, + "blacklevel" : 0.0000, + "whitelevel" : 0.8000 + }, + "green" : + { + "threshold" : 0.1000, + "gamma" : 2.0000, + "blacklevel" : 0.0000, + "whitelevel" : 1.0000 + }, + "blue" : + { + "threshold" : 0.1000, + "gamma" : 2.0000, + "blacklevel" : 0.0000, + "whitelevel" : 1.0000 + } + } + ], + "smoothing" : { "type" : "none", @@ -68,16 +106,16 @@ } }, - /// The configuration for each individual led. This contains the specification of the area - /// averaged of an input image for each led to determine its color. Each item in the list + /// The configuration for each individual led. This contains the specification of the area + /// averaged of an input image for each led to determine its color. Each item in the list /// contains the following fields: - /// * index: The index of the led. This determines its location in the string of leds; zero + /// * index: The index of the led. This determines its location in the string of leds; zero /// being the first led. - /// * hscan: The fractional part of the image along the horizontal used for the averaging + /// * hscan: The fractional part of the image along the horizontal used for the averaging /// (minimum and maximum inclusive) - /// * vscan: The fractional part of the image along the vertical used for the averaging + /// * vscan: The fractional part of the image along the vertical used for the averaging /// (minimum and maximum inclusive) - "leds" : + "leds" : [ { "index" : 0, @@ -331,15 +369,15 @@ } ], - /// The black border configuration, contains the following items: + /// The black border configuration, contains the following items: /// * enable : true if the detector should be activated "blackborderdetector" : { "enable" : true }, - /// The boot-sequence configuration, contains the following items: - /// * type : The type of the boot-sequence ('rainbow', 'knight_rider', 'none') + /// The boot-sequence configuration, contains the following items: + /// * type : The type of the boot-sequence ('rainbow', 'knight_rider', 'none') /// * duration_ms : The length of the boot-sequence [ms] "bootsequence" : { @@ -347,7 +385,7 @@ "duration_ms" : 3000 }, - /// The configuration for the frame-grabber, contains the following items: + /// The configuration for the frame-grabber, contains the following items: /// * width : The width of the grabbed frames [pixels] /// * height : The height of the grabbed frames [pixels] /// * frequency_Hz : The frequency of the frame grab [Hz] @@ -358,22 +396,22 @@ "frequency_Hz" : 10.0 }, - /// The configuration of the XBMC connection used to enable and disable the frame-grabber. Contains the following fields: + /// The configuration of the XBMC connection used to enable and disable the frame-grabber. Contains the following fields: /// * xbmcAddress : The IP address of the XBMC-host /// * xbmcTcpPort : The TCP-port of the XBMC-server /// * grabVideo : Flag indicating that the frame-grabber is on(true) during video playback /// * grabPictures : Flag indicating that the frame-grabber is on(true) during picture show /// * grabAudio : Flag indicating that the frame-grabber is on(true) during audio playback /// * grabMenu : Flag indicating that the frame-grabber is on(true) in the XBMC menu - "xbmcVideoChecker" : - { - "xbmcAddress" : "127.0.0.1", - "xbmcTcpPort" : 9090, - "grabVideo" : true, - "grabPictures" : true, - "grabAudio" : true, - "grabMenu" : false - }, +// "xbmcVideoChecker" : +// { +// "xbmcAddress" : "127.0.0.1", +// "xbmcTcpPort" : 9090, +// "grabVideo" : true, +// "grabPictures" : true, +// "grabAudio" : true, +// "grabMenu" : false +// }, /// The configuration of the Json server which enables the json remote interface /// * port : Port at which the json server is started From 958feabf5bc377387314ac2c25ed71a0eb147cbf Mon Sep 17 00:00:00 2001 From: "T. van der Zwan" Date: Fri, 22 Nov 2013 10:47:05 +0000 Subject: [PATCH 10/18] Added double as possible type Former-commit-id: 0caa8d0cb81db4d6592db296cb1f775e91efce50 --- libsrc/utils/jsonschema/JsonSchemaChecker.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libsrc/utils/jsonschema/JsonSchemaChecker.cpp b/libsrc/utils/jsonschema/JsonSchemaChecker.cpp index 4cfa0935..da0c51d8 100644 --- a/libsrc/utils/jsonschema/JsonSchemaChecker.cpp +++ b/libsrc/utils/jsonschema/JsonSchemaChecker.cpp @@ -154,6 +154,8 @@ void JsonSchemaChecker::checkType(const Json::Value & value, const Json::Value & wrongType = !value.isNumeric(); else if (type == "integer") wrongType = !value.isIntegral(); + else if (type == "double") + wrongType = !value.isDouble(); else if (type == "boolean") wrongType = !value.isBool(); else if (type == "object") From 826b964bf6aefc87751a22c4218109898087a8d8 Mon Sep 17 00:00:00 2001 From: "T. van der Zwan" Date: Fri, 22 Nov 2013 10:48:10 +0000 Subject: [PATCH 11/18] Implemented the multi-color transform including in hyperion-remote Former-commit-id: ebdb0688b47d51bd6dccf6dafd580d3ce9ed80a7 --- config/hyperion.config.json | 82 +++---- include/hyperion/ColorTransform.h | 26 +++ include/hyperion/Hyperion.h | 31 +-- libsrc/hyperion/CMakeLists.txt | 1 + libsrc/hyperion/Hyperion.cpp | 209 ++++++++---------- libsrc/hyperion/MultiColorTransform.cpp | 48 ++-- libsrc/hyperion/MultiColorTransform.h | 37 ++-- libsrc/jsonserver/JsonClientConnection.cpp | 103 +++++---- .../jsonserver/schema/schema-transform.json | 136 ++++++------ src/hyperion-remote/JsonConnection.cpp | 7 +- src/hyperion-remote/JsonConnection.h | 2 + src/hyperion-remote/hyperion-remote.cpp | 5 + 12 files changed, 357 insertions(+), 330 deletions(-) create mode 100644 include/hyperion/ColorTransform.h diff --git a/config/hyperion.config.json b/config/hyperion.config.json index bba5ce09..fa6a7535 100644 --- a/config/hyperion.config.json +++ b/config/hyperion.config.json @@ -2,7 +2,7 @@ // Generated by: HyperCon (The Hyperion deamon configuration file builder { - /// Device configuration contains the following fields: + /// Device configuration contains the following fields: /// * 'name' : The user friendly name of the device (only used for display purposes) /// * 'type' : The type of the device or leds (known types for now are 'ws2801', 'ldp8806', /// 'lpd6803', 'sedu', 'adalight', 'lightpack', 'test' and 'none') @@ -34,32 +34,38 @@ /// - 'updateFrequency' The update frequency of the leds in Hz "color" : { - "hsv" : - { - "saturationGain" : 1.0000, - "valueGain" : 1.5000 - }, - "red" : - { - "threshold" : 0.1000, - "gamma" : 2.0000, - "blacklevel" : 0.0000, - "whitelevel" : 0.8000 - }, - "green" : - { - "threshold" : 0.1000, - "gamma" : 2.0000, - "blacklevel" : 0.0000, - "whitelevel" : 1.0000 - }, - "blue" : - { - "threshold" : 0.1000, - "gamma" : 2.0000, - "blacklevel" : 0.0000, - "whitelevel" : 1.0000 - }, + "transforms" : + [ + { + "id" : "default", + "hsv" : + { + "saturationGain" : 1.0000, + "valueGain" : 1.5000 + }, + "red" : + { + "threshold" : 0.1000, + "gamma" : 2.0000, + "blacklevel" : 0.0000, + "whitelevel" : 0.8000 + }, + "green" : + { + "threshold" : 0.1000, + "gamma" : 2.0000, + "blacklevel" : 0.0000, + "whitelevel" : 1.0000 + }, + "blue" : + { + "threshold" : 0.1000, + "gamma" : 2.0000, + "blacklevel" : 0.0000, + "whitelevel" : 1.0000 + }, + } + ], "smoothing" : { "type" : "none", @@ -68,16 +74,16 @@ } }, - /// The configuration for each individual led. This contains the specification of the area - /// averaged of an input image for each led to determine its color. Each item in the list + /// The configuration for each individual led. This contains the specification of the area + /// averaged of an input image for each led to determine its color. Each item in the list /// contains the following fields: - /// * index: The index of the led. This determines its location in the string of leds; zero + /// * index: The index of the led. This determines its location in the string of leds; zero /// being the first led. - /// * hscan: The fractional part of the image along the horizontal used for the averaging + /// * hscan: The fractional part of the image along the horizontal used for the averaging /// (minimum and maximum inclusive) - /// * vscan: The fractional part of the image along the vertical used for the averaging + /// * vscan: The fractional part of the image along the vertical used for the averaging /// (minimum and maximum inclusive) - "leds" : + "leds" : [ { "index" : 0, @@ -331,15 +337,15 @@ } ], - /// The black border configuration, contains the following items: + /// The black border configuration, contains the following items: /// * enable : true if the detector should be activated "blackborderdetector" : { "enable" : true }, - /// The boot-sequence configuration, contains the following items: - /// * type : The type of the boot-sequence ('rainbow', 'knight_rider', 'none') + /// The boot-sequence configuration, contains the following items: + /// * type : The type of the boot-sequence ('rainbow', 'knight_rider', 'none') /// * duration_ms : The length of the boot-sequence [ms] "bootsequence" : { @@ -347,7 +353,7 @@ "duration_ms" : 3000 }, - /// The configuration for the frame-grabber, contains the following items: + /// The configuration for the frame-grabber, contains the following items: /// * width : The width of the grabbed frames [pixels] /// * height : The height of the grabbed frames [pixels] /// * frequency_Hz : The frequency of the frame grab [Hz] @@ -358,7 +364,7 @@ "frequency_Hz" : 10.0 }, - /// The configuration of the XBMC connection used to enable and disable the frame-grabber. Contains the following fields: + /// The configuration of the XBMC connection used to enable and disable the frame-grabber. Contains the following fields: /// * xbmcAddress : The IP address of the XBMC-host /// * xbmcTcpPort : The TCP-port of the XBMC-server /// * grabVideo : Flag indicating that the frame-grabber is on(true) during video playback diff --git a/include/hyperion/ColorTransform.h b/include/hyperion/ColorTransform.h new file mode 100644 index 00000000..50cbedba --- /dev/null +++ b/include/hyperion/ColorTransform.h @@ -0,0 +1,26 @@ +#pragma once + +// STL includes +#include + +// Utils includes +#include +#include + +class ColorTransform +{ +public: + + /// Unique identifier for this color transform + std::string _id; + + /// The RED-Channel (RGB) transform + RgbChannelTransform _rgbRedTransform; + /// The GREEN-Channel (RGB) transform + RgbChannelTransform _rgbGreenTransform; + /// The BLUE-Channel (RGB) transform + RgbChannelTransform _rgbBlueTransform; + + /// The HSV Transform for applying Saturation and Value transforms + HsvTransform _hsvTransform; +}; diff --git a/include/hyperion/Hyperion.h b/include/hyperion/Hyperion.h index 6f726241..605ce6a1 100644 --- a/include/hyperion/Hyperion.h +++ b/include/hyperion/Hyperion.h @@ -16,6 +16,7 @@ #include // Forward class declaration +class ColorTransform; class HsvTransform; class RgbChannelTransform; class MultiColorTransform; @@ -89,15 +90,16 @@ public: void setColors(int priority, const std::vector &ledColors, const int timeout_ms); /// - /// Sets/Updates a part of the color transformation. + /// Returns the list with unique transform identifiers + /// @return The list with transform identifiers /// - /// @param[in] transform The type of transform to configure - /// @param[in] color The color channel to which the transform applies (only applicable for - /// Transform::THRESHOLD, Transform::GAMMA, Transform::BLACKLEVEL, - /// Transform::WHITELEVEL) - /// @param[in] value The new value for the given transform + const std::vector & getTransformIds() const; + /// - void setTransform(Transform transform, RgbChannel color, double value); + /// Returns the ColorTransform with the given identifier + /// @return The transform with the given identifier (or nullptr if the identifier does not exist) + /// + ColorTransform * getTransform(const std::string& id); /// /// Clears the given priority channel. This will switch the led-colors to the colors of the next @@ -112,18 +114,6 @@ public: /// void clearall(); - /// - /// Returns the value of a specific color transform - /// - /// @param[in] transform The type of transform - /// @param[in] color The color channel to which the transform applies (only applicable for - /// Transform::THRESHOLD, Transform::GAMMA, Transform::BLACKLEVEL, - /// Transform::WHITELEVEL) - /// - /// @return The value of the specified color transform - /// - double getTransform(Transform transform, RgbChannel color) const; - /// /// Returns a list of active priorities /// @@ -147,8 +137,9 @@ public: static LedString createLedString(const Json::Value & ledsConfig); static MultiColorTransform * createLedColorsTransform(const unsigned ledCnt, const Json::Value & colorTransformConfig); + static ColorTransform * createColorTransform(const Json::Value & transformConfig); static HsvTransform * createHsvTransform(const Json::Value & hsvConfig); - static RgbChannelTransform * createColorTransform(const Json::Value& colorConfig); + static RgbChannelTransform * createRgbChannelTransform(const Json::Value& colorConfig); static LedDevice * createColorSmoothing(const Json::Value & smoothingConfig, LedDevice * ledDevice); diff --git a/libsrc/hyperion/CMakeLists.txt b/libsrc/hyperion/CMakeLists.txt index 03d9df24..c984aa62 100644 --- a/libsrc/hyperion/CMakeLists.txt +++ b/libsrc/hyperion/CMakeLists.txt @@ -77,6 +77,7 @@ add_library(hyperion ${Hyperion_SOURCES} ${Hyperion_RESOURCES_RCC} ) +message("{QT_LIBRARIES} = ${QT_LIBRARIES}") target_link_libraries(hyperion hyperion-utils diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp index 64b1be63..472ae96f 100644 --- a/libsrc/hyperion/Hyperion.cpp +++ b/libsrc/hyperion/Hyperion.cpp @@ -4,6 +4,9 @@ // QT includes #include +#include +#include +#include // JsonSchema include #include @@ -153,29 +156,94 @@ Hyperion::ColorOrder Hyperion::createColorOrder(const Json::Value &deviceConfig) return ORDER_RGB; } +ColorTransform * Hyperion::createColorTransform(const Json::Value & transformConfig) +{ + const std::string id = transformConfig.get("id", "default").asString(); + + RgbChannelTransform * redTransform = createRgbChannelTransform(transformConfig["red"]); + RgbChannelTransform * greenTransform = createRgbChannelTransform(transformConfig["green"]); + RgbChannelTransform * blueTransform = createRgbChannelTransform(transformConfig["blue"]); + + HsvTransform * hsvTransform = createHsvTransform(transformConfig["hsv"]); + + ColorTransform * transform = new ColorTransform(); + transform->_id = id; + transform->_rgbRedTransform = *redTransform; + transform->_rgbGreenTransform = *greenTransform; + transform->_rgbBlueTransform = *blueTransform; + transform->_hsvTransform = *hsvTransform; + + // Cleanup the allocated individual transforms + delete redTransform; + delete greenTransform; + delete blueTransform; + delete hsvTransform; + + return transform; +} + MultiColorTransform * Hyperion::createLedColorsTransform(const unsigned ledCnt, const Json::Value & colorConfig) { - MultiColorTransform * transform = new MultiColorTransform(); - if (!colorConfig.isArray()) + // Create the result, the transforms are added to this + MultiColorTransform * transform = new MultiColorTransform(ledCnt); + + const Json::Value transformConfig = colorConfig.get("transform", Json::nullValue); + if (transformConfig.isNull()) { // Old style color transformation config (just one for all leds) - const std::string id = "default"; - - RgbChannelTransform * redTransform = createColorTransform(colorConfig["red"]); - RgbChannelTransform * greenTransform = createColorTransform(colorConfig["green"]); - RgbChannelTransform * blueTransform = createColorTransform(colorConfig["blue"]); - - HsvTransform * hsvTransform = createHsvTransform(colorConfig["hsv"]); - transform->addTransform(id, *redTransform, *greenTransform, *blueTransform, *hsvTransform); - transform->setTransformForLed(id, 0, ledCnt-1); - - delete redTransform; - delete greenTransform; - delete blueTransform; + ColorTransform * colorTransform = createColorTransform(colorConfig); + transform->addTransform(colorTransform); + transform->setTransformForLed(colorTransform->_id, 0, ledCnt-1); + } + else if (!transformConfig.isArray()) + { + ColorTransform * colorTransform = createColorTransform(transformConfig); + transform->addTransform(colorTransform); + transform->setTransformForLed(colorTransform->_id, 0, ledCnt-1); } else { + const QRegExp overallExp("([0-9]+(\\-[0-9]+)?)(,[ ]*([0-9]+(\\-[0-9]+)?))*"); + for (Json::UInt i = 0; i < transformConfig.size(); ++i) + { + const Json::Value & config = transformConfig[i]; + ColorTransform * colorTransform = createColorTransform(config); + transform->addTransform(colorTransform); + + const QString ledIndicesStr = config.get("leds", "").asCString(); + if (!overallExp.exactMatch(ledIndicesStr)) + { + std::cerr << "Given led indices " << i << " not correct format: " << ledIndicesStr.toStdString() << std::endl; + continue; + } + + std::cout << "ColorTransform '" << colorTransform->_id << "' => ["; + + const QStringList ledIndexList = ledIndicesStr.split(","); + for (int i=0; i 0) + { + std::cout << ", "; + } + if (ledIndexList[i].contains("-")) + { + QStringList ledIndices = ledIndexList[i].split("-"); + int startInd = ledIndices[0].toInt(); + int endInd = ledIndices[1].toInt(); + + transform->setTransformForLed(colorTransform->_id, startInd, endInd); + std::cout << startInd << "-" << endInd; + } + else + { + int index = ledIndexList[i].toInt(); + transform->setTransformForLed(colorTransform->_id, index, index); + std::cout << index; + } + } + std::cout << "]" << std::endl; + } } return transform; } @@ -188,7 +256,7 @@ HsvTransform * Hyperion::createHsvTransform(const Json::Value & hsvConfig) return new HsvTransform(saturationGain, valueGain); } -RgbChannelTransform* Hyperion::createColorTransform(const Json::Value& colorConfig) +RgbChannelTransform* Hyperion::createRgbChannelTransform(const Json::Value& colorConfig) { const double threshold = colorConfig.get("threshold", 0.0).asDouble(); const double gamma = colorConfig.get("gamma", 1.0).asDouble(); @@ -276,6 +344,10 @@ Hyperion::Hyperion(const Json::Value &jsonConfig) : _device(createDevice(jsonConfig["device"])), _timer() { + if (!_raw2ledTransform->verifyTransforms()) + { + throw std::runtime_error("Color transformation incorrectly set"); + } // initialize the image processor factory ImageProcessorFactory::getInstance().init(_ledString, jsonConfig["blackborderdetector"].get("enable", true).asBool()); @@ -336,59 +408,14 @@ void Hyperion::setColors(int priority, const std::vector& ledColors, c } } -void Hyperion::setTransform(Hyperion::Transform transform, Hyperion::RgbChannel color, double value) +const std::vector & Hyperion::getTransformIds() const { - ColorTransform* colorTransform = _raw2ledTransform->getTransform("default"); - assert(colorTransform != nullptr); + return _raw2ledTransform->getTransformIds(); +} - // select the transform of the requested color - RgbChannelTransform * t = nullptr; - switch (color) - { - case RED: - t = &(colorTransform->_rgbRedTransform); - break; - case GREEN: - t = &(colorTransform->_rgbGreenTransform); - break; - case BLUE: - t = &(colorTransform->_rgbBlueTransform); - break; - default: - break; - } - - // set transform value - switch (transform) - { - case SATURATION_GAIN: - colorTransform->_hsvTransform.setSaturationGain(value); - break; - case VALUE_GAIN: - colorTransform->_hsvTransform.setValueGain(value); - break; - case THRESHOLD: - assert (t != nullptr); - t->setThreshold(value); - break; - case GAMMA: - assert (t != nullptr); - t->setGamma(value); - break; - case BLACKLEVEL: - assert (t != nullptr); - t->setBlacklevel(value); - break; - case WHITELEVEL: - assert (t != nullptr); - t->setWhitelevel(value); - break; - default: - assert(false); - } - - // update the led output - update(); +ColorTransform * Hyperion::getTransform(const std::string& id) +{ + return _raw2ledTransform->getTransform(id); } void Hyperion::clear(int priority) @@ -413,54 +440,6 @@ void Hyperion::clearall() update(); } -double Hyperion::getTransform(Hyperion::Transform transform, Hyperion::RgbChannel color) const -{ - ColorTransform * colorTransform = _raw2ledTransform->getTransform("default"); - assert(colorTransform != nullptr); - - // select the transform of the requested color - RgbChannelTransform * t = nullptr; - switch (color) - { - case RED: - t = &(colorTransform->_rgbRedTransform); - break; - case GREEN: - t = &(colorTransform->_rgbGreenTransform); - break; - case BLUE: - t = &(colorTransform->_rgbBlueTransform); - break; - default: - break; - } - - // set transform value - switch (transform) - { - case SATURATION_GAIN: - return colorTransform->_hsvTransform.getSaturationGain(); - case VALUE_GAIN: - return colorTransform->_hsvTransform.getValueGain(); - case THRESHOLD: - assert (t != nullptr); - return t->getThreshold(); - case GAMMA: - assert (t != nullptr); - return t->getGamma(); - case BLACKLEVEL: - assert (t != nullptr); - return t->getBlacklevel(); - case WHITELEVEL: - assert (t != nullptr); - return t->getWhitelevel(); - default: - assert(false); - } - - return 999.0; -} - QList Hyperion::getActivePriorities() const { return _muxer.getPriorities(); diff --git a/libsrc/hyperion/MultiColorTransform.cpp b/libsrc/hyperion/MultiColorTransform.cpp index 99b81b27..d15f020e 100644 --- a/libsrc/hyperion/MultiColorTransform.cpp +++ b/libsrc/hyperion/MultiColorTransform.cpp @@ -5,7 +5,8 @@ // Hyperion includes #include "MultiColorTransform.h" -MultiColorTransform::MultiColorTransform() +MultiColorTransform::MultiColorTransform(const unsigned ledCnt) : + _ledTransforms(ledCnt, nullptr) { } @@ -18,33 +19,16 @@ MultiColorTransform::~MultiColorTransform() } } -void MultiColorTransform::addTransform(const std::string & id, - const RgbChannelTransform & redTransform, - const RgbChannelTransform & greenTransform, - const RgbChannelTransform & blueTransform, - const HsvTransform & hsvTransform) +void MultiColorTransform::addTransform(ColorTransform * transform) { - ColorTransform * transform = new ColorTransform(); - transform->_id = id; - - transform->_rgbRedTransform = redTransform; - transform->_rgbGreenTransform = greenTransform; - transform->_rgbBlueTransform = blueTransform; - - transform->_hsvTransform = hsvTransform; - + _transformIds.push_back(transform->_id); _transform.push_back(transform); } void MultiColorTransform::setTransformForLed(const std::string& id, const unsigned startLed, const unsigned endLed) { assert(startLed <= endLed); - - // Make sure that there are at least enough led transforms to match the given indices - if (_ledTransforms.size() < endLed+1) - { - _ledTransforms.resize(endLed+1, nullptr); - } + assert(endLed < _ledTransforms.size()); // Get the identified transform (don't care if is nullptr) ColorTransform * transform = getTransform(id); @@ -54,15 +38,23 @@ void MultiColorTransform::setTransformForLed(const std::string& id, const unsign } } -std::vector MultiColorTransform::getTransformIds() +bool MultiColorTransform::verifyTransforms() const { - // Create the list on the fly - std::vector transformIds; - for (ColorTransform* transform : _transform) + bool allLedsSet = true; + for (unsigned iLed=0; iLed<_ledTransforms.size(); ++iLed) { - transformIds.push_back(transform->_id); + if (_ledTransforms[iLed] == nullptr) + { + std::cerr << "No transform set for " << iLed << std::endl; + allLedsSet = false; + } } - return transformIds; + return allLedsSet; +} + +const std::vector & MultiColorTransform::getTransformIds() +{ + return _transformIds; } ColorTransform* MultiColorTransform::getTransform(const std::string& id) @@ -85,7 +77,7 @@ std::vector MultiColorTransform::applyTransform(const std::vector ledColors(rawColors); - const size_t itCnt = std::min(_transform.size(), rawColors.size()); + const size_t itCnt = std::min(_ledTransforms.size(), rawColors.size()); for (size_t i=0; i -#include -#include - -struct ColorTransform -{ - std::string _id; - /// The RED-Channel (RGB) transform - RgbChannelTransform _rgbRedTransform; - /// The GREEN-Channel (RGB) transform - RgbChannelTransform _rgbGreenTransform; - /// The BLUE-Channel (RGB) transform - RgbChannelTransform _rgbBlueTransform; - /// The HSV Transform for applying Saturation and Value transforms - HsvTransform _hsvTransform; -}; +// Hyperion includes +#include /// /// The LedColorTransform is responsible for performing color transformation from 'raw' colors @@ -29,22 +16,25 @@ struct ColorTransform class MultiColorTransform { public: - MultiColorTransform(); + MultiColorTransform(const unsigned ledCnt); ~MultiColorTransform(); - void addTransform(const std::string & id, - const RgbChannelTransform & redTransform, - const RgbChannelTransform & greenTransform, - const RgbChannelTransform & blueTransform, - const HsvTransform & hsvTransform); + /** + * Adds a new ColorTransform to this MultiColorTransform + * + * @param transform The new ColorTransform (ownership is transfered) + */ + void addTransform(ColorTransform * transform); void setTransformForLed(const std::string& id, const unsigned startLed, const unsigned endLed); + bool verifyTransforms() const; + /// /// Returns the identifier of all the unique ColorTransform /// /// @return The list with unique id's of the ColorTransforms - std::vector getTransformIds(); + const std::vector & getTransformIds(); /// /// Returns the pointer to the ColorTransform with the given id @@ -65,6 +55,9 @@ public: std::vector applyTransform(const std::vector& rawColors); private: + /// List with transform ids + std::vector _transformIds; + /// List with unique ColorTransforms std::vector _transform; diff --git a/libsrc/jsonserver/JsonClientConnection.cpp b/libsrc/jsonserver/JsonClientConnection.cpp index 1c99b13d..cd5894db 100644 --- a/libsrc/jsonserver/JsonClientConnection.cpp +++ b/libsrc/jsonserver/JsonClientConnection.cpp @@ -12,9 +12,10 @@ #include // hyperion util includes -#include "hyperion/ImageProcessorFactory.h" -#include "hyperion/ImageProcessor.h" -#include "utils/ColorRgb.h" +#include +#include +#include +#include // project includes #include "JsonClientConnection.h" @@ -173,25 +174,39 @@ void JsonClientConnection::handleServerInfoCommand(const Json::Value &message) } // collect transform information - Json::Value & transform = info["transform"]; - transform["saturationGain"] = _hyperion->getTransform(Hyperion::SATURATION_GAIN, Hyperion::INVALID); - transform["valueGain"] = _hyperion->getTransform(Hyperion::VALUE_GAIN, Hyperion::INVALID); - Json::Value & threshold = transform["threshold"]; - threshold.append(_hyperion->getTransform(Hyperion::THRESHOLD, Hyperion::RED)); - threshold.append(_hyperion->getTransform(Hyperion::THRESHOLD, Hyperion::GREEN)); - threshold.append(_hyperion->getTransform(Hyperion::THRESHOLD, Hyperion::BLUE)); - Json::Value & gamma = transform["gamma"]; - gamma.append(_hyperion->getTransform(Hyperion::GAMMA, Hyperion::RED)); - gamma.append(_hyperion->getTransform(Hyperion::GAMMA, Hyperion::GREEN)); - gamma.append(_hyperion->getTransform(Hyperion::GAMMA, Hyperion::BLUE)); - Json::Value & blacklevel = transform["blacklevel"]; - blacklevel.append(_hyperion->getTransform(Hyperion::BLACKLEVEL, Hyperion::RED)); - blacklevel.append(_hyperion->getTransform(Hyperion::BLACKLEVEL, Hyperion::GREEN)); - blacklevel.append(_hyperion->getTransform(Hyperion::BLACKLEVEL, Hyperion::BLUE)); - Json::Value & whitelevel = transform["whitelevel"]; - whitelevel.append(_hyperion->getTransform(Hyperion::WHITELEVEL, Hyperion::RED)); - whitelevel.append(_hyperion->getTransform(Hyperion::WHITELEVEL, Hyperion::GREEN)); - whitelevel.append(_hyperion->getTransform(Hyperion::WHITELEVEL, Hyperion::BLUE)); + Json::Value & transformArray = info["transform"]; + for (const std::string& transformId : _hyperion->getTransformIds()) + { + const ColorTransform * colorTransform = _hyperion->getTransform(transformId); + if (colorTransform == nullptr) + { + std::cerr << "Incorrect color transform id: " << transformId << std::endl; + continue; + } + + Json::Value & transform = transformArray.append(Json::Value()); + transform["id"] = transformId; + + transform["saturationGain"] = colorTransform->_hsvTransform.getSaturationGain(); + transform["valueGain"] = colorTransform->_hsvTransform.getValueGain(); + + Json::Value & threshold = transform["threshold"]; + threshold.append(colorTransform->_rgbRedTransform.getThreshold()); + threshold.append(colorTransform->_rgbGreenTransform.getThreshold()); + threshold.append(colorTransform->_rgbBlueTransform.getThreshold()); + Json::Value & gamma = transform["gamma"]; + gamma.append(colorTransform->_rgbRedTransform.getGamma()); + gamma.append(colorTransform->_rgbGreenTransform.getGamma()); + gamma.append(colorTransform->_rgbBlueTransform.getGamma()); + Json::Value & blacklevel = transform["blacklevel"]; + blacklevel.append(colorTransform->_rgbRedTransform.getBlacklevel()); + blacklevel.append(colorTransform->_rgbGreenTransform.getBlacklevel()); + blacklevel.append(colorTransform->_rgbBlueTransform.getBlacklevel()); + Json::Value & whitelevel = transform["whitelevel"]; + whitelevel.append(colorTransform->_rgbRedTransform.getWhitelevel()); + whitelevel.append(colorTransform->_rgbGreenTransform.getWhitelevel()); + whitelevel.append(colorTransform->_rgbBlueTransform.getWhitelevel()); + } // send the result sendMessage(result); @@ -222,46 +237,54 @@ void JsonClientConnection::handleTransformCommand(const Json::Value &message) { const Json::Value & transform = message["transform"]; + const std::string transformId = transform.get("id", _hyperion->getTransformIds().front()).asString(); + ColorTransform * colorTransform = _hyperion->getTransform(transformId); + if (colorTransform == nullptr) + { + //sendErrorReply(std::string("Incorrect transform identifier: ") + transformId); + return; + } + if (transform.isMember("saturationGain")) { - _hyperion->setTransform(Hyperion::SATURATION_GAIN, Hyperion::INVALID, transform["saturationGain"].asDouble()); + colorTransform->_hsvTransform.setSaturationGain(transform["saturationGain"].asDouble()); } if (transform.isMember("valueGain")) { - _hyperion->setTransform(Hyperion::VALUE_GAIN, Hyperion::INVALID, transform["valueGain"].asDouble()); + colorTransform->_hsvTransform.setValueGain(transform["valueGain"].asDouble()); } if (transform.isMember("threshold")) { - const Json::Value & threshold = transform["threshold"]; - _hyperion->setTransform(Hyperion::THRESHOLD, Hyperion::RED, threshold[0u].asDouble()); - _hyperion->setTransform(Hyperion::THRESHOLD, Hyperion::GREEN, threshold[1u].asDouble()); - _hyperion->setTransform(Hyperion::THRESHOLD, Hyperion::BLUE, threshold[2u].asDouble()); + const Json::Value & values = transform["threshold"]; + colorTransform->_rgbRedTransform .setThreshold(values[0u].asDouble()); + colorTransform->_rgbGreenTransform.setThreshold(values[1u].asDouble()); + colorTransform->_rgbBlueTransform .setThreshold(values[2u].asDouble()); } if (transform.isMember("gamma")) { - const Json::Value & threshold = transform["gamma"]; - _hyperion->setTransform(Hyperion::GAMMA, Hyperion::RED, threshold[0u].asDouble()); - _hyperion->setTransform(Hyperion::GAMMA, Hyperion::GREEN, threshold[1u].asDouble()); - _hyperion->setTransform(Hyperion::GAMMA, Hyperion::BLUE, threshold[2u].asDouble()); + const Json::Value & values = transform["gamma"]; + colorTransform->_rgbRedTransform .setGamma(values[0u].asDouble()); + colorTransform->_rgbGreenTransform.setGamma(values[1u].asDouble()); + colorTransform->_rgbBlueTransform .setGamma(values[2u].asDouble()); } if (transform.isMember("blacklevel")) { - const Json::Value & threshold = transform["blacklevel"]; - _hyperion->setTransform(Hyperion::BLACKLEVEL, Hyperion::RED, threshold[0u].asDouble()); - _hyperion->setTransform(Hyperion::BLACKLEVEL, Hyperion::GREEN, threshold[1u].asDouble()); - _hyperion->setTransform(Hyperion::BLACKLEVEL, Hyperion::BLUE, threshold[2u].asDouble()); + const Json::Value & values = transform["blacklevel"]; + colorTransform->_rgbRedTransform .setBlacklevel(values[0u].asDouble()); + colorTransform->_rgbGreenTransform.setBlacklevel(values[1u].asDouble()); + colorTransform->_rgbBlueTransform .setBlacklevel(values[2u].asDouble()); } if (transform.isMember("whitelevel")) { - const Json::Value & threshold = transform["whitelevel"]; - _hyperion->setTransform(Hyperion::WHITELEVEL, Hyperion::RED, threshold[0u].asDouble()); - _hyperion->setTransform(Hyperion::WHITELEVEL, Hyperion::GREEN, threshold[1u].asDouble()); - _hyperion->setTransform(Hyperion::WHITELEVEL, Hyperion::BLUE, threshold[2u].asDouble()); + const Json::Value & values = transform["whitelevel"]; + colorTransform->_rgbRedTransform .setWhitelevel(values[0u].asDouble()); + colorTransform->_rgbGreenTransform.setWhitelevel(values[1u].asDouble()); + colorTransform->_rgbBlueTransform .setWhitelevel(values[2u].asDouble()); } sendSuccessReply(); diff --git a/libsrc/jsonserver/schema/schema-transform.json b/libsrc/jsonserver/schema/schema-transform.json index 26fdf787..a135e12f 100644 --- a/libsrc/jsonserver/schema/schema-transform.json +++ b/libsrc/jsonserver/schema/schema-transform.json @@ -1,68 +1,72 @@ { - "type":"object", - "required":true, - "properties":{ - "command": { - "type" : "string", - "required" : true, - "enum" : ["transform"] - }, - "transform": { - "type": "object", - "required": true, - "properties": { - "saturationGain" : { - "type" : "double", - "required" : false, - "minimum" : 0.0 - }, - "valueGain" : { - "type" : "double", - "required" : false, - "minimum" : 0.0 - }, - "threshold": { - "type": "array", - "required": false, - "items" : { - "type": "double", - "minimum": 0.0, - "maximum": 1.0 - }, - "minItems": 3, - "maxItems": 3 - }, - "gamma": { - "type": "array", - "required": false, - "items" : { - "type": "double", - "minimum": 0.0 - }, - "minItems": 3, - "maxItems": 3 - }, - "blacklevel": { - "type": "array", - "required": false, - "items" : { - "type": "double" - }, - "minItems": 3, - "maxItems": 3 - }, - "whitelevel": { - "type": "array", - "required": false, - "items" : { - "type": "double" - }, - "minItems": 3, - "maxItems": 3 - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false + "type":"object", + "required":true, + "properties":{ + "command": { + "type" : "string", + "required" : true, + "enum" : ["transform"] + }, + "transform": { + "type": "object", + "required": true, + "properties": { + "id" : { + "type" : "string", + "required" : false + }, + "saturationGain" : { + "type" : "double", + "required" : false, + "minimum" : 0.0 + }, + "valueGain" : { + "type" : "double", + "required" : false, + "minimum" : 0.0 + }, + "threshold": { + "type": "array", + "required": false, + "items" : { + "type": "double", + "minimum": 0.0, + "maximum": 1.0 + }, + "minItems": 3, + "maxItems": 3 + }, + "gamma": { + "type": "array", + "required": false, + "items" : { + "type": "double", + "minimum": 0.0 + }, + "minItems": 3, + "maxItems": 3 + }, + "blacklevel": { + "type": "array", + "required": false, + "items" : { + "type": "double" + }, + "minItems": 3, + "maxItems": 3 + }, + "whitelevel": { + "type": "array", + "required": false, + "items" : { + "type": "double" + }, + "minItems": 3, + "maxItems": 3 + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false } diff --git a/src/hyperion-remote/JsonConnection.cpp b/src/hyperion-remote/JsonConnection.cpp index d742daaa..641c7681 100644 --- a/src/hyperion-remote/JsonConnection.cpp +++ b/src/hyperion-remote/JsonConnection.cpp @@ -160,7 +160,7 @@ void JsonConnection::clearAll() parseReply(reply); } -void JsonConnection::setTransform(double * saturation, double * value, ColorTransformValues *threshold, ColorTransformValues *gamma, ColorTransformValues *blacklevel, ColorTransformValues *whitelevel) +void JsonConnection::setTransform(std::string * transformId, double * saturation, double * value, ColorTransformValues *threshold, ColorTransformValues *gamma, ColorTransformValues *blacklevel, ColorTransformValues *whitelevel) { std::cout << "Set color transforms" << std::endl; @@ -169,6 +169,11 @@ void JsonConnection::setTransform(double * saturation, double * value, ColorTran command["command"] = "transform"; Json::Value & transform = command["transform"]; + if (transformId != nullptr) + { + transform["id"] = *transformId; + } + if (saturation != nullptr) { transform["saturationGain"] = *saturation; diff --git a/src/hyperion-remote/JsonConnection.h b/src/hyperion-remote/JsonConnection.h index 33fc5b4a..6bd358b5 100644 --- a/src/hyperion-remote/JsonConnection.h +++ b/src/hyperion-remote/JsonConnection.h @@ -76,6 +76,7 @@ public: /// /// @note Note that providing a NULL will leave the settings on the server unchanged /// + /// @param transformId The identifier of the transform to set /// @param saturation The HSV saturation gain /// @param value The HSV value gain /// @param threshold The threshold @@ -84,6 +85,7 @@ public: /// @param whitelevel The whitelevel /// void setTransform( + std::string * transformId, double * saturation, double * value, ColorTransformValues * threshold, diff --git a/src/hyperion-remote/hyperion-remote.cpp b/src/hyperion-remote/hyperion-remote.cpp index bbe4f408..b290b4f2 100644 --- a/src/hyperion-remote/hyperion-remote.cpp +++ b/src/hyperion-remote/hyperion-remote.cpp @@ -45,6 +45,7 @@ int main(int argc, char * argv[]) SwitchParameter<> & argServerInfo = parameters.add >('l', "list" , "List server info"); SwitchParameter<> & argClear = parameters.add >('x', "clear" , "Clear data for the priority channel provided by the -p option"); SwitchParameter<> & argClearAll = parameters.add >(0x0, "clearall" , "Clear data for all active priority channels"); + StringParameter & argId = parameters.add ('q', "qualifier" , "Identifier(qualifier) of the transform to set"); DoubleParameter & argSaturation = parameters.add ('s', "saturation", "Set the HSV saturation gain of the leds"); DoubleParameter & argValue = parameters.add ('v', "value" , "Set the HSV value gain of the leds"); TransformParameter & argGamma = parameters.add('g', "gamma" , "Set the gamma of the leds (requires 3 space seperated values)"); @@ -83,6 +84,7 @@ int main(int argc, char * argv[]) std::cerr << " " << argClear.usageLine() << std::endl; std::cerr << " " << argClearAll.usageLine() << std::endl; std::cerr << "or one or more of the available color transformations:" << std::endl; + std::cerr << " " << argId.usageLine() << std::endl; std::cerr << " " << argSaturation.usageLine() << std::endl; std::cerr << " " << argValue.usageLine() << std::endl; std::cerr << " " << argThreshold.usageLine() << std::endl; @@ -119,9 +121,11 @@ int main(int argc, char * argv[]) } else if (colorTransform) { + std::string transId; double saturation, value; ColorTransformValues threshold, gamma, blacklevel, whitelevel; + if (argId.isSet()) transId = argId.getValue(); if (argSaturation.isSet()) saturation = argSaturation.getValue(); if (argValue.isSet()) value = argValue.getValue(); if (argThreshold.isSet()) threshold = argThreshold.getValue(); @@ -130,6 +134,7 @@ int main(int argc, char * argv[]) if (argWhitelevel.isSet()) whitelevel = argWhitelevel.getValue(); connection.setTransform( + argId.isSet() ? &transId : nullptr, argSaturation.isSet() ? &saturation : nullptr, argValue.isSet() ? &value : nullptr, argThreshold.isSet() ? &threshold : nullptr, From 08b4980ac5649bf173a44c31beb8db2e2d7422c6 Mon Sep 17 00:00:00 2001 From: "T. van der Zwan" Date: Fri, 22 Nov 2013 13:51:19 +0000 Subject: [PATCH 12/18] Removed unused code lines Former-commit-id: 199de062788fd0fb391f20ac7fc530cde23bf338 --- CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cc92e72c..b30dc4d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,8 +53,6 @@ find_package(Protobuf REQUIRED) find_package(libusb-1.0 REQUIRED) find_package(Threads REQUIRED) -#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) From 996beae750ecc03f742412c561c29cb4118b6082 Mon Sep 17 00:00:00 2001 From: "T. van der Zwan" Date: Fri, 22 Nov 2013 13:51:39 +0000 Subject: [PATCH 13/18] Added multi transforms for testing purpose Former-commit-id: d821e759e3f3f583132a5f21c397b2652337cd28 --- config/hyperion.config.json | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/config/hyperion.config.json b/config/hyperion.config.json index fa6a7535..1c5963ce 100644 --- a/config/hyperion.config.json +++ b/config/hyperion.config.json @@ -34,10 +34,11 @@ /// - 'updateFrequency' The update frequency of the leds in Hz "color" : { - "transforms" : + "transform" : [ { - "id" : "default", + "id" : "device_1", + "leds" : "0-24", "hsv" : { "saturationGain" : 1.0000, @@ -63,12 +64,42 @@ "gamma" : 2.0000, "blacklevel" : 0.0000, "whitelevel" : 1.0000 + } + }, + { + "id" : "device_2", + "leds" : "25-49", + "hsv" : + { + "saturationGain" : 1.0000, + "valueGain" : 1.5000 }, + "red" : + { + "threshold" : 0.1000, + "gamma" : 2.0000, + "blacklevel" : 0.0000, + "whitelevel" : 0.8000 + }, + "green" : + { + "threshold" : 0.1000, + "gamma" : 2.0000, + "blacklevel" : 0.0000, + "whitelevel" : 1.0000 + }, + "blue" : + { + "threshold" : 0.1000, + "gamma" : 2.0000, + "blacklevel" : 0.0000, + "whitelevel" : 1.0000 + } } ], "smoothing" : { - "type" : "none", + "type" : "linear", "time_ms" : 200, "updateFrequency" : 20.0000 } From ba54f3d8ce218d29fd8dac462f2d77e24cc9cac6 Mon Sep 17 00:00:00 2001 From: "T. van der Zwan" Date: Fri, 22 Nov 2013 13:51:54 +0000 Subject: [PATCH 14/18] Removed unused lines Former-commit-id: 8e4a62de33bd0622614884c771d8e74177016121 --- libsrc/hyperion/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/libsrc/hyperion/CMakeLists.txt b/libsrc/hyperion/CMakeLists.txt index c984aa62..03d9df24 100644 --- a/libsrc/hyperion/CMakeLists.txt +++ b/libsrc/hyperion/CMakeLists.txt @@ -77,7 +77,6 @@ add_library(hyperion ${Hyperion_SOURCES} ${Hyperion_RESOURCES_RCC} ) -message("{QT_LIBRARIES} = ${QT_LIBRARIES}") target_link_libraries(hyperion hyperion-utils From 336647b95b0296fb69445aaca14794f0752e3ca5 Mon Sep 17 00:00:00 2001 From: "T. van der Zwan" Date: Mon, 25 Nov 2013 12:16:16 +0100 Subject: [PATCH 15/18] Added multi-color specifications to the model of HyperCon (not GUI yet) Former-commit-id: 3b3f38f1514bd2925e043333555461b3af1f7d88 --- .../hyperion/hypercon/ConfigurationFile.java | 107 +++++++++++++++--- .../org/hyperion/hypercon/gui/ColorPanel.java | 5 +- .../hyperion/hypercon/spec/ColorConfig.java | 98 +++------------- .../hypercon/spec/TransformConfig.java | 101 +++++++++++++++++ 4 files changed, 210 insertions(+), 101 deletions(-) create mode 100644 src/config-tool/ConfigTool/src/org/hyperion/hypercon/spec/TransformConfig.java diff --git a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/ConfigurationFile.java b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/ConfigurationFile.java index 285978f8..1abd46c1 100644 --- a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/ConfigurationFile.java +++ b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/ConfigurationFile.java @@ -8,19 +8,19 @@ import java.io.OutputStream; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; import java.util.Properties; -import java.util.zip.GZIPInputStream; -import java.util.zip.GZIPOutputStream; +import java.util.Vector; public class ConfigurationFile { - private final Properties pProps = new Properties(); + private final Properties mProps = new Properties(); public void load(String pFilename) { - pProps.clear(); + mProps.clear(); // try (InputStream in = new InflaterInputStream(new FileInputStream(pFilename))){ - try (InputStream in = new GZIPInputStream(new FileInputStream(pFilename))){ -// try (InputStream in = new FileInputStream(pFilename)) { - pProps.load(in); +// try (InputStream in = new GZIPInputStream(new FileInputStream(pFilename))){ + try (InputStream in = new FileInputStream(pFilename)) { + mProps.load(in); } catch (Throwable t) { // TODO Auto-generated catch block t.printStackTrace(); @@ -29,15 +29,18 @@ public class ConfigurationFile { public void save(String pFilename) { // try (OutputStream out = new DeflaterOutputStream(new FileOutputStream(pFilename))) { - try (OutputStream out = new GZIPOutputStream(new FileOutputStream(pFilename))) { -// try (OutputStream out = (new FileOutputStream(pFilename))) { - pProps.store(out, "Pesistent settings file for HyperCon"); +// try (OutputStream out = new GZIPOutputStream(new FileOutputStream(pFilename))) { + try (OutputStream out = (new FileOutputStream(pFilename))) { + mProps.store(out, "Pesistent settings file for HyperCon"); } catch (IOException e) { e.printStackTrace(); } } public void store(Object pObj) { + store(pObj, pObj.getClass().getSimpleName(), ""); + } + public void store(Object pObj, String preamble, String postamble) { String className = pObj.getClass().getSimpleName(); // Retrieve the member variables Field[] fields = pObj.getClass().getDeclaredFields(); @@ -48,27 +51,99 @@ public class ConfigurationFile { continue; } - String key = className + "." + field.getName(); + String key = preamble + "." + field.getName() + postamble; try { Object value = field.get(pObj); if (value.getClass().isEnum()) { - pProps.setProperty(key, ((Enum)value).name()); + mProps.setProperty(key, ((Enum)value).name()); + } else if (value.getClass().isAssignableFrom(Vector.class)) { + @SuppressWarnings("unchecked") + Vector v = (Vector) value; + for (int i=0; i vector; + try { + vector = (Vector)field.get(pObj); + } catch (Throwable t) { + t.printStackTrace(); + break; + } + // Clear existing elements from the vector + vector.clear(); + + // Iterate through the properties to find the indices of the vector + int i=0; + while (true) { + String curIndexKey = pPreamble + field.getName() + "[" + i + "]"; + Properties elemProps = new Properties(); + // Find all the elements for the current vector index + for (Object keyObj : pProps.keySet()) { + String keyStr = (String)keyObj; + if (keyStr.startsWith(curIndexKey)) { + // Remove the name and dot + elemProps.put(keyStr.substring(curIndexKey.length()+1), pProps.get(keyStr)); + } + } + if (elemProps.isEmpty()) { + // Found no more elements for the vector + break; + } + + // Construct new instance of vectors generic type + ParameterizedType vectorElementType = (ParameterizedType) field.getGenericType(); + Class vectorElementClass = (Class) vectorElementType.getActualTypeArguments()[0]; + // Find the constructor with no arguments and create a new instance + Object newElement = null; + try { + newElement = vectorElementClass.getConstructor().newInstance(); + } catch (Throwable t) { + System.err.println("Failed to find empty default constructor for " + vectorElementClass.getName()); + break; + } + if (newElement == null) { + System.err.println("Failed to construct instance for " + vectorElementClass.getName()); + break; + } + + // Restore the instance members from the collected properties + restore(newElement, elemProps, ""); + + // Add the instance to the vector + vector.addElement(newElement); + + ++i; + } + + continue; + } + + String key = pPreamble + field.getName(); String value = pProps.getProperty(key); if (value == null) { System.out.println("Persistent settings does not contain value for " + key); @@ -97,6 +172,6 @@ public class ConfigurationFile { @Override public String toString() { - return pProps.toString(); + return mProps.toString(); } } diff --git a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/ColorPanel.java b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/ColorPanel.java index 531aad0f..52c16b16 100644 --- a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/ColorPanel.java +++ b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/ColorPanel.java @@ -16,6 +16,7 @@ import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.hyperion.hypercon.spec.ColorConfig; +import org.hyperion.hypercon.spec.TransformConfig; /** * Configuration panel for the ColorConfig. @@ -24,7 +25,7 @@ import org.hyperion.hypercon.spec.ColorConfig; */ public class ColorPanel extends JPanel { - private final ColorConfig mColorConfig; + private final TransformConfig mColorConfig; private JPanel mRgbTransformPanel; private JLabel mThresholdLabel; @@ -56,7 +57,7 @@ public class ColorPanel extends JPanel { public ColorPanel(ColorConfig pColorConfig) { super(); - mColorConfig = pColorConfig; + mColorConfig = pColorConfig.mTransforms.get(0); initialise(); } diff --git a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/spec/ColorConfig.java b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/spec/ColorConfig.java index ea4c2279..c9baf768 100644 --- a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/spec/ColorConfig.java +++ b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/spec/ColorConfig.java @@ -1,42 +1,19 @@ package org.hyperion.hypercon.spec; +import java.util.List; import java.util.Locale; +import java.util.Vector; /** * The color tuning parameters of the different color channels (both in RGB space as in HSV space) */ public class ColorConfig { - /** The saturation gain (in HSV space) */ - public double mSaturationGain = 1.0; - /** The value gain (in HSV space) */ - public double mValueGain = 1.5; - /** The minimum required RED-value (in RGB space) */ - public double mRedThreshold = 0.1; - /** The gamma-curve correct for the RED-value (in RGB space) */ - public double mRedGamma = 2.0; - /** The black-level of the RED-value (in RGB space) */ - public double mRedBlacklevel = 0.0; - /** The white-level of the RED-value (in RGB space) */ - public double mRedWhitelevel = 0.8; - - /** The minimum required GREEN-value (in RGB space) */ - public double mGreenThreshold = 0.1; - /** The gamma-curve correct for the GREEN-value (in RGB space) */ - public double mGreenGamma = 2.0; - /** The black-level of the GREEN-value (in RGB space) */ - public double mGreenBlacklevel = 0.0; - /** The white-level of the GREEN-value (in RGB space) */ - public double mGreenWhitelevel = 1.0; - - /** The minimum required BLUE-value (in RGB space) */ - public double mBlueThreshold = 0.1; - /** The gamma-curve correct for the BLUE-value (in RGB space) */ - public double mBlueGamma = 2.0; - /** The black-level of the BLUE-value (in RGB space) */ - public double mBlueBlacklevel = 0.0; - /** The white-level of the BLUE-value (in RGB space) */ - public double mBlueWhitelevel = 1.0; + /** List with color transformations */ + public List mTransforms = new Vector<>(); + { + mTransforms.add(new TransformConfig()); + } public boolean mSmoothingEnabled = false; /** The type of smoothing algorithm */ @@ -70,65 +47,20 @@ public class ColorConfig { strBuf.append("\t\"color\" :\n"); strBuf.append("\t{\n"); - strBuf.append(hsvToJsonString() + ",\n"); - strBuf.append(rgbToJsonString() + ",\n"); + + strBuf.append("\t\t\"transform\" :\n"); + strBuf.append("\t\t[\n"); + for (TransformConfig transform : mTransforms) { + strBuf.append(transform.toJsonString()); + } + strBuf.append("\t\t]\n"); + strBuf.append(smoothingToString() + "\n"); strBuf.append("\t}"); return strBuf.toString(); } - /** - * Creates the JSON string of the HSV-subconfiguration as used in the Hyperion deamon configfile - * - * @return The JSON string of the HSV-config - */ - private String hsvToJsonString() { - StringBuffer strBuf = new StringBuffer(); - strBuf.append("\t\t\"hsv\" :\n"); - strBuf.append("\t\t{\n"); - strBuf.append(String.format(Locale.ROOT, "\t\t\t\"saturationGain\" : %.4f,\n", mSaturationGain)); - strBuf.append(String.format(Locale.ROOT, "\t\t\t\"valueGain\" : %.4f\n", mValueGain)); - - strBuf.append("\t\t}"); - return strBuf.toString(); - } - - /** - * Creates the JSON string of the RGB-subconfiguration as used in the Hyperion deamon configfile - * - * @return The JSON string of the RGB-config - */ - private String rgbToJsonString() { - StringBuffer strBuf = new StringBuffer(); - - strBuf.append("\t\t\"red\" :\n"); - strBuf.append("\t\t{\n"); - strBuf.append(String.format(Locale.ROOT, "\t\t\t\"threshold\" : %.4f,\n", mRedThreshold)); - strBuf.append(String.format(Locale.ROOT, "\t\t\t\"gamma\" : %.4f,\n", mRedGamma)); - strBuf.append(String.format(Locale.ROOT, "\t\t\t\"blacklevel\" : %.4f,\n", mRedBlacklevel)); - strBuf.append(String.format(Locale.ROOT, "\t\t\t\"whitelevel\" : %.4f\n", mRedWhitelevel)); - strBuf.append("\t\t},\n"); - - strBuf.append("\t\t\"green\" :\n"); - strBuf.append("\t\t{\n"); - strBuf.append(String.format(Locale.ROOT, "\t\t\t\"threshold\" : %.4f,\n", mGreenThreshold)); - strBuf.append(String.format(Locale.ROOT, "\t\t\t\"gamma\" : %.4f,\n", mGreenGamma)); - strBuf.append(String.format(Locale.ROOT, "\t\t\t\"blacklevel\" : %.4f,\n", mGreenBlacklevel)); - strBuf.append(String.format(Locale.ROOT, "\t\t\t\"whitelevel\" : %.4f\n", mGreenWhitelevel)); - strBuf.append("\t\t},\n"); - - strBuf.append("\t\t\"blue\" :\n"); - strBuf.append("\t\t{\n"); - strBuf.append(String.format(Locale.ROOT, "\t\t\t\"threshold\" : %.4f,\n", mBlueThreshold)); - strBuf.append(String.format(Locale.ROOT, "\t\t\t\"gamma\" : %.4f,\n", mBlueGamma)); - strBuf.append(String.format(Locale.ROOT, "\t\t\t\"blacklevel\" : %.4f,\n", mBlueBlacklevel)); - strBuf.append(String.format(Locale.ROOT, "\t\t\t\"whitelevel\" : %.4f\n", mBlueWhitelevel)); - strBuf.append("\t\t}"); - - return strBuf.toString(); - } - /** * Creates the JSON string of the smoothing subconfiguration as used in the Hyperion deamon configfile * diff --git a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/spec/TransformConfig.java b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/spec/TransformConfig.java new file mode 100644 index 00000000..e3ddf221 --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/spec/TransformConfig.java @@ -0,0 +1,101 @@ +package org.hyperion.hypercon.spec; + +import java.util.Locale; + +public class TransformConfig { + /** The identifier of this ColorTransform configuration */ + public String mId = ""; + + /** The saturation gain (in HSV space) */ + public double mSaturationGain = 1.0; + /** The value gain (in HSV space) */ + public double mValueGain = 1.5; + + /** The minimum required RED-value (in RGB space) */ + public double mRedThreshold = 0.1; + /** The gamma-curve correct for the RED-value (in RGB space) */ + public double mRedGamma = 2.0; + /** The black-level of the RED-value (in RGB space) */ + public double mRedBlacklevel = 0.0; + /** The white-level of the RED-value (in RGB space) */ + public double mRedWhitelevel = 0.8; + + /** The minimum required GREEN-value (in RGB space) */ + public double mGreenThreshold = 0.1; + /** The gamma-curve correct for the GREEN-value (in RGB space) */ + public double mGreenGamma = 2.0; + /** The black-level of the GREEN-value (in RGB space) */ + public double mGreenBlacklevel = 0.0; + /** The white-level of the GREEN-value (in RGB space) */ + public double mGreenWhitelevel = 1.0; + + /** The minimum required BLUE-value (in RGB space) */ + public double mBlueThreshold = 0.1; + /** The gamma-curve correct for the BLUE-value (in RGB space) */ + public double mBlueGamma = 2.0; + /** The black-level of the BLUE-value (in RGB space) */ + public double mBlueBlacklevel = 0.0; + /** The white-level of the BLUE-value (in RGB space) */ + public double mBlueWhitelevel = 1.0; + + public String toJsonString() { + StringBuffer strBuf = new StringBuffer(); + + strBuf.append("\t\t{\n"); + strBuf.append(hsvToJsonString() + ",\n"); + strBuf.append(rgbToJsonString() + ",\n"); + strBuf.append("\t\t}"); + + return strBuf.toString(); + } + /** + * Creates the JSON string of the HSV-subconfiguration as used in the Hyperion deamon configfile + * + * @return The JSON string of the HSV-config + */ + private String hsvToJsonString() { + StringBuffer strBuf = new StringBuffer(); + strBuf.append("\t\t\t\"hsv\" :\n"); + strBuf.append("\t\t\t{\n"); + strBuf.append(String.format(Locale.ROOT, "\t\t\t\t\"saturationGain\" : %.4f,\n", mSaturationGain)); + strBuf.append(String.format(Locale.ROOT, "\t\t\t\t\"valueGain\" : %.4f\n", mValueGain)); + + strBuf.append("\t\t\t}"); + return strBuf.toString(); + } + + /** + * Creates the JSON string of the RGB-subconfiguration as used in the Hyperion deamon configfile + * + * @return The JSON string of the RGB-config + */ + private String rgbToJsonString() { + StringBuffer strBuf = new StringBuffer(); + + strBuf.append("\t\t\t\"red\" :\n"); + strBuf.append("\t\t\t{\n"); + strBuf.append(String.format(Locale.ROOT, "\t\t\t\t\"threshold\" : %.4f,\n", mRedThreshold)); + strBuf.append(String.format(Locale.ROOT, "\t\t\t\t\"gamma\" : %.4f,\n", mRedGamma)); + strBuf.append(String.format(Locale.ROOT, "\t\t\t\t\"blacklevel\" : %.4f,\n", mRedBlacklevel)); + strBuf.append(String.format(Locale.ROOT, "\t\t\t\t\"whitelevel\" : %.4f\n", mRedWhitelevel)); + strBuf.append("\t\t},\n"); + + strBuf.append("\t\t\t\"green\" :\n"); + strBuf.append("\t\t\t{\n"); + strBuf.append(String.format(Locale.ROOT, "\t\t\t\t\"threshold\" : %.4f,\n", mGreenThreshold)); + strBuf.append(String.format(Locale.ROOT, "\t\t\t\t\"gamma\" : %.4f,\n", mGreenGamma)); + strBuf.append(String.format(Locale.ROOT, "\t\t\t\t\"blacklevel\" : %.4f,\n", mGreenBlacklevel)); + strBuf.append(String.format(Locale.ROOT, "\t\t\t\t\"whitelevel\" : %.4f\n", mGreenWhitelevel)); + strBuf.append("\t\t\t},\n"); + + strBuf.append("\t\t\t\"blue\" :\n"); + strBuf.append("\t\t\t{\n"); + strBuf.append(String.format(Locale.ROOT, "\t\t\t\t\"threshold\" : %.4f,\n", mBlueThreshold)); + strBuf.append(String.format(Locale.ROOT, "\t\t\t\t\"gamma\" : %.4f,\n", mBlueGamma)); + strBuf.append(String.format(Locale.ROOT, "\t\t\t\t\"blacklevel\" : %.4f,\n", mBlueBlacklevel)); + strBuf.append(String.format(Locale.ROOT, "\t\t\t\t\"whitelevel\" : %.4f\n", mBlueWhitelevel)); + strBuf.append("\t\t\t}"); + + return strBuf.toString(); + } +} From 602afa14f6822565a590f220c0e4b42e4e0432b9 Mon Sep 17 00:00:00 2001 From: "T. van der Zwan" Date: Mon, 25 Nov 2013 12:26:20 +0100 Subject: [PATCH 16/18] Fixed json generation of multi-colortransform Former-commit-id: ecd587d1e623e34b8841d634b2217ef350e25210 --- .../hyperion/hypercon/spec/ColorConfig.java | 10 +++- .../hypercon/spec/TransformConfig.java | 58 +++++++++---------- 2 files changed, 37 insertions(+), 31 deletions(-) diff --git a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/spec/ColorConfig.java b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/spec/ColorConfig.java index c9baf768..b8bab28c 100644 --- a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/spec/ColorConfig.java +++ b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/spec/ColorConfig.java @@ -50,10 +50,16 @@ public class ColorConfig { strBuf.append("\t\t\"transform\" :\n"); strBuf.append("\t\t[\n"); - for (TransformConfig transform : mTransforms) { + for (int i=0; i Date: Tue, 26 Nov 2013 12:24:48 +0100 Subject: [PATCH 17/18] Added the multi color transform to the gui. Former-commit-id: 96ff1aa60098871a8597f716c0788cc749e149ef --- ...lorPanel.java => ColorTransformPanel.java} | 51 ++++++- .../hyperion/hypercon/gui/ColorsPanel.java | 130 ++++++++++++++++++ .../hyperion/hypercon/gui/ConfigPanel.java | 2 +- .../hyperion/hypercon/spec/ColorConfig.java | 24 +++- .../hypercon/spec/TransformConfig.java | 12 +- 5 files changed, 205 insertions(+), 14 deletions(-) rename src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/{ColorPanel.java => ColorTransformPanel.java} (83%) create mode 100644 src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/ColorsPanel.java diff --git a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/ColorPanel.java b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/ColorTransformPanel.java similarity index 83% rename from src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/ColorPanel.java rename to src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/ColorTransformPanel.java index 52c16b16..e7dd3278 100644 --- a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/ColorPanel.java +++ b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/ColorTransformPanel.java @@ -1,5 +1,6 @@ package org.hyperion.hypercon.gui; +import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.GridLayout; import java.beans.Transient; @@ -11,11 +12,13 @@ import javax.swing.GroupLayout; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JSpinner; +import javax.swing.JTextField; import javax.swing.SpinnerNumberModel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; -import org.hyperion.hypercon.spec.ColorConfig; import org.hyperion.hypercon.spec.TransformConfig; /** @@ -23,10 +26,14 @@ import org.hyperion.hypercon.spec.TransformConfig; * * NB This has not been integrated in the GUI jet! */ -public class ColorPanel extends JPanel { +public class ColorTransformPanel extends JPanel { private final TransformConfig mColorConfig; + private JPanel mIndexPanel; + private JLabel mIndexLabel; + private JTextField mIndexField; + private JPanel mRgbTransformPanel; private JLabel mThresholdLabel; private JLabel mGammaLabel; @@ -54,10 +61,10 @@ public class ColorPanel extends JPanel { private JLabel mValueAdjustLabel; private JSpinner mValueAdjustSpinner; - public ColorPanel(ColorConfig pColorConfig) { + public ColorTransformPanel(TransformConfig pTransformConfig) { super(); - mColorConfig = pColorConfig.mTransforms.get(0); + mColorConfig = pTransformConfig; initialise(); } @@ -71,12 +78,32 @@ public class ColorPanel extends JPanel { } private void initialise() { - setBorder(BorderFactory.createTitledBorder("Color transform")); + setBorder(BorderFactory.createTitledBorder("Transform [" + mColorConfig.mId + "]")); setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + add(getIndexPanel()); + add(Box.createVerticalStrut(10)); add(getRgbPanel()); add(Box.createVerticalStrut(10)); add(getHsvPanel()); + add(Box.createVerticalGlue()); + } + + private JPanel getIndexPanel() { + if (mIndexPanel == null) { + mIndexPanel = new JPanel(); + mIndexPanel.setMaximumSize(new Dimension(1024, 25)); + mIndexPanel.setLayout(new BorderLayout(10,10)); + + mIndexLabel = new JLabel("Indices:"); + mIndexPanel.add(mIndexLabel, BorderLayout.WEST); + + mIndexField = new JTextField(mColorConfig.mLedIndexString); + mIndexField.setToolTipText("Comma seperated indices or index ranges (eg '1-10, 13, 14, 17-19')"); + mIndexField.getDocument().addDocumentListener(mDocumentListener); + mIndexPanel.add(mIndexField, BorderLayout.CENTER); + } + return mIndexPanel; } private JPanel getRgbPanel() { @@ -217,4 +244,18 @@ public class ColorPanel extends JPanel { mColorConfig.mValueGain = (Double)mValueAdjustSpinner.getValue(); } }; + private final DocumentListener mDocumentListener = new DocumentListener() { + @Override + public void removeUpdate(DocumentEvent e) { + mColorConfig.mLedIndexString = mIndexField.getText(); + } + @Override + public void insertUpdate(DocumentEvent e) { + mColorConfig.mLedIndexString = mIndexField.getText(); + } + @Override + public void changedUpdate(DocumentEvent e) { + mColorConfig.mLedIndexString = mIndexField.getText(); + } + }; } diff --git a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/ColorsPanel.java b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/ColorsPanel.java new file mode 100644 index 00000000..29f50840 --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/ColorsPanel.java @@ -0,0 +1,130 @@ +package org.hyperion.hypercon.gui; + +import java.awt.BorderLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.HashMap; +import java.util.Map; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.DefaultComboBoxModel; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JOptionPane; +import javax.swing.JPanel; + +import org.hyperion.hypercon.spec.ColorConfig; +import org.hyperion.hypercon.spec.TransformConfig; + +public class ColorsPanel extends JPanel { + + private final ColorConfig mColorConfig; + private final DefaultComboBoxModel mTransformsModel; + + private JPanel mControlPanel; + private JComboBox mTransformCombo; + private JButton mAddTransformButton; + private JButton mDelTransformButton; + + private JPanel mTransformPanel; + + private final Map mTransformPanels = new HashMap<>(); + + + public ColorsPanel(ColorConfig pColorConfig) { + super(); + + mColorConfig = pColorConfig; + mTransformsModel = new DefaultComboBoxModel(mColorConfig.mTransforms); + + initialise(); + } + + private void initialise() { + setLayout(new BorderLayout(10,10)); + setBorder(BorderFactory.createTitledBorder("Colors")); + + add(getControlPanel(), BorderLayout.NORTH); + + mTransformPanel = new JPanel(); + mTransformPanel.setLayout(new BorderLayout()); + add(mTransformPanel, BorderLayout.CENTER); + + for (TransformConfig config : mColorConfig.mTransforms) { + mTransformPanels.put(config, new ColorTransformPanel(config)); + } + ColorTransformPanel currentPanel = mTransformPanels.get(mColorConfig.mTransforms.get(0)); + mTransformPanel.add(currentPanel, BorderLayout.CENTER); + } + + private JPanel getControlPanel() { + if (mControlPanel == null) { + mControlPanel = new JPanel(); + mControlPanel.setLayout(new BoxLayout(mControlPanel, BoxLayout.LINE_AXIS)); + + mTransformCombo = new JComboBox<>(mTransformsModel); + mTransformCombo.addActionListener(mComboListener); + mControlPanel.add(mTransformCombo); + + mAddTransformButton = new JButton(mAddAction); + mControlPanel.add(mAddTransformButton); + + mDelTransformButton = new JButton(mDelAction); + mDelTransformButton.setEnabled(mTransformCombo.getItemCount() > 1); + mControlPanel.add(mDelTransformButton); + } + return mControlPanel; + } + + private final Action mAddAction = new AbstractAction("Add") { + @Override + public void actionPerformed(ActionEvent e) { + String newId = JOptionPane.showInputDialog("Give an identifier for the new color-transform:"); + if (newId == null || newId.isEmpty()) { + // No proper value given + return; + } + + TransformConfig config = new TransformConfig(); + config.mId = newId; + + ColorTransformPanel panel = new ColorTransformPanel(config); + mTransformPanels.put(config, panel); + + mTransformsModel.addElement(config); + mTransformsModel.setSelectedItem(config); + + mDelTransformButton.setEnabled(true); + } + }; + private final Action mDelAction = new AbstractAction("Del") { + @Override + public void actionPerformed(ActionEvent e) { + TransformConfig config = (TransformConfig) mTransformCombo.getSelectedItem(); + mTransformPanels.remove(config); + mTransformsModel.removeElement(config); + + mDelTransformButton.setEnabled(mTransformCombo.getItemCount() > 1); + } + }; + + private final ActionListener mComboListener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + TransformConfig selConfig = (TransformConfig) mTransformsModel.getSelectedItem(); + if (selConfig == null) { + // Something went wrong here, there should always be a selection! + return; + } + + ColorTransformPanel panel = mTransformPanels.get(selConfig); + mTransformPanel.removeAll(); + mTransformPanel.add(panel, BorderLayout.CENTER); + mTransformPanel.revalidate(); + mTransformPanel.repaint(); + } + }; +} diff --git a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/ConfigPanel.java b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/ConfigPanel.java index 6c56bc44..84e1636d 100644 --- a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/ConfigPanel.java +++ b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/ConfigPanel.java @@ -174,7 +174,7 @@ public class ConfigPanel extends JPanel { mProcessPanel.add(new BootSequencePanel(ledString.mMiscConfig)); mProcessPanel.add(new FrameGrabberPanel(ledString.mMiscConfig)); mProcessPanel.add(new ColorSmoothingPanel(ledString.mColorConfig)); - mProcessPanel.add(new ColorPanel(ledString.mColorConfig)); + mProcessPanel.add(new ColorsPanel(ledString.mColorConfig)); mProcessPanel.add(Box.createVerticalGlue()); } return mProcessPanel; diff --git a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/spec/ColorConfig.java b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/spec/ColorConfig.java index b8bab28c..824c3f1d 100644 --- a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/spec/ColorConfig.java +++ b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/spec/ColorConfig.java @@ -1,6 +1,5 @@ package org.hyperion.hypercon.spec; -import java.util.List; import java.util.Locale; import java.util.Vector; @@ -10,7 +9,7 @@ import java.util.Vector; public class ColorConfig { /** List with color transformations */ - public List mTransforms = new Vector<>(); + public Vector mTransforms = new Vector<>(); { mTransforms.add(new TransformConfig()); } @@ -31,16 +30,27 @@ public class ColorConfig { public String toJsonString() { StringBuffer strBuf = new StringBuffer(); - strBuf.append("\t/// Color manipulation configuration used to tune the output colors to specific surroundings. Contains the following fields:\n"); - strBuf.append("\t/// * 'hsv' : The manipulation in the Hue-Saturation-Value color domain with the following tuning parameters:\n"); + strBuf.append("\t/// Color manipulation configuration used to tune the output colors to specific surroundings. \n"); + strBuf.append("\t/// The configuration contains a list of color-transforms. Each transform contains the \n"); + strBuf.append("\t/// following fields:\n"); + strBuf.append("\t/// * 'id' : The unique identifier of the color transformation (eg 'device_1')"); + strBuf.append("\t/// * 'leds' : The indices (or index ranges) of the leds to which this color transform applies\n"); + strBuf.append("\t/// (eg '0-5, 9, 11, 12-17'). The indices are zero based."); + strBuf.append("\t/// * 'hsv' : The manipulation in the Hue-Saturation-Value color domain with the following \n"); + strBuf.append("\t/// tuning parameters:\n"); strBuf.append("\t/// - 'saturationGain' The gain adjustement of the saturation\n"); strBuf.append("\t/// - 'valueGain' The gain adjustement of the value\n"); - strBuf.append("\t/// * 'red'/'green'/'blue' : The manipulation in the Red-Green-Blue color domain with the following tuning parameters for each channel:\n"); - strBuf.append("\t/// - 'threshold' The minimum required input value for the channel to be on (else zero)\n"); + strBuf.append("\t/// * 'red'/'green'/'blue' : The manipulation in the Red-Green-Blue color domain with the \n"); + strBuf.append("\t/// following tuning parameters for each channel:\n"); + strBuf.append("\t/// - 'threshold' The minimum required input value for the channel to be on \n"); + strBuf.append("\t/// (else zero)\n"); strBuf.append("\t/// - 'gamma' The gamma-curve correction factor\n"); strBuf.append("\t/// - 'blacklevel' The lowest possible value (when the channel is black)\n"); strBuf.append("\t/// - 'whitelevel' The highest possible value (when the channel is white)\n"); - strBuf.append("\t/// * 'smoothing' : Smoothing of the colors in the time-domain with the following tuning parameters:\n"); + strBuf.append("\t///"); + strBuf.append("\t/// Next to the list with color transforms there is also a smoothing option."); + strBuf.append("\t/// * 'smoothing' : Smoothing of the colors in the time-domain with the following tuning \n"); + strBuf.append("\t/// parameters:\n"); strBuf.append("\t/// - 'type' The type of smoothing algorithm ('linear' or 'none')\n"); strBuf.append("\t/// - 'time_ms' The time constant for smoothing algorithm in milliseconds\n"); strBuf.append("\t/// - 'updateFrequency' The update frequency of the leds in Hz\n"); diff --git a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/spec/TransformConfig.java b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/spec/TransformConfig.java index 5877f10f..a5893210 100644 --- a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/spec/TransformConfig.java +++ b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/spec/TransformConfig.java @@ -4,7 +4,10 @@ import java.util.Locale; public class TransformConfig { /** The identifier of this ColorTransform configuration */ - public String mId = ""; + public String mId = "default"; + + /** The indices to which this transform applies */ + public String mLedIndexString = "0-49"; /** The saturation gain (in HSV space) */ public double mSaturationGain = 1.0; @@ -42,6 +45,8 @@ public class TransformConfig { StringBuffer strBuf = new StringBuffer(); strBuf.append("\t\t\t{\n"); + strBuf.append("\t\t\t\t\"id\" : \"" + mId + "\",\n"); + strBuf.append("\t\t\t\t\"leds\" : \"" + mLedIndexString + "\",\n"); strBuf.append(hsvToJsonString() + ",\n"); strBuf.append(rgbToJsonString() + "\n"); strBuf.append("\t\t\t}"); @@ -98,4 +103,9 @@ public class TransformConfig { return strBuf.toString(); } + + @Override + public String toString() { + return mId; + } } From dc4a41c64a5b9fe6ebd104c2db85514f3e97c867 Mon Sep 17 00:00:00 2001 From: "T. van der Zwan" Date: Wed, 27 Nov 2013 12:00:05 +0100 Subject: [PATCH 18/18] Added test dialog for dividing leds over transforms Former-commit-id: 0d4549d32c40df3fcbd0c308b249566721445b13 --- .../hypercon/gui/LedDivideDialog.java | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/LedDivideDialog.java diff --git a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/LedDivideDialog.java b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/LedDivideDialog.java new file mode 100644 index 00000000..d0072df1 --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/LedDivideDialog.java @@ -0,0 +1,48 @@ +package org.hyperion.hypercon.gui; + +import java.awt.GridLayout; + +import javax.swing.ButtonGroup; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JRadioButton; + +public class LedDivideDialog extends JFrame { + + private final int mLedCount; + private final int mTransformCount; + + private JPanel mContentPanel; + + public LedDivideDialog(int pLedCnt, int pTransformCnt) { + super(); + + mLedCount = pLedCnt; + mTransformCount = pTransformCnt; + + initialise(); + } + + private void initialise() { + mContentPanel = new JPanel(); + mContentPanel.setLayout(new GridLayout(mLedCount, mTransformCount, 5, 5)); + + for (int iLed=0; iLed