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] 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; +};