diff --git a/config/hyperion.config.json b/config/hyperion.config.json index 748781fd..62c7d70e 100644 --- a/config/hyperion.config.json +++ b/config/hyperion.config.json @@ -68,6 +68,31 @@ } } ], + "channelAdjustment" : + [ + { + "id" : "default", + "leds" : "*", + "pureRed" : + { + "redChannel" : 255, + "greenChannel" : 0, + "blueChannel" : 0 + }, + "pureGreen" : + { + "redChannel" : 0, + "greenChannel" : 255, + "blueChannel" : 0 + }, + "pureBlue" : + { + "redChannel" : 0, + "greenChannel" : 0, + "blueChannel" : 255 + } + } + ], "transform" : [ { diff --git a/doc/calibration/Gamma/000000.png b/doc/calibration/Gamma/000000.png new file mode 100644 index 00000000..f4c09261 Binary files /dev/null and b/doc/calibration/Gamma/000000.png differ diff --git a/doc/calibration/Gamma/3F3F3F.png b/doc/calibration/Gamma/3F3F3F.png new file mode 100644 index 00000000..7c9d7e81 Binary files /dev/null and b/doc/calibration/Gamma/3F3F3F.png differ diff --git a/doc/calibration/Gamma/7F7F7F.png b/doc/calibration/Gamma/7F7F7F.png new file mode 100644 index 00000000..dcf7a3f6 Binary files /dev/null and b/doc/calibration/Gamma/7F7F7F.png differ diff --git a/doc/calibration/Gamma/BFBFBF.png b/doc/calibration/Gamma/BFBFBF.png new file mode 100644 index 00000000..f61f7297 Binary files /dev/null and b/doc/calibration/Gamma/BFBFBF.png differ diff --git a/doc/calibration/Gamma/FFFFFF.png b/doc/calibration/Gamma/FFFFFF.png new file mode 100644 index 00000000..8e5dc2d5 Binary files /dev/null and b/doc/calibration/Gamma/FFFFFF.png differ diff --git a/doc/calibration/Gamma/HGradient_1.png b/doc/calibration/Gamma/HGradient_1.png new file mode 100644 index 00000000..b681c709 Binary files /dev/null and b/doc/calibration/Gamma/HGradient_1.png differ diff --git a/doc/calibration/Gamma/HGradient_2.png b/doc/calibration/Gamma/HGradient_2.png new file mode 100644 index 00000000..d9f99f95 Binary files /dev/null and b/doc/calibration/Gamma/HGradient_2.png differ diff --git a/doc/calibration/Gamma/VGradient_1.png b/doc/calibration/Gamma/VGradient_1.png new file mode 100644 index 00000000..974b087e Binary files /dev/null and b/doc/calibration/Gamma/VGradient_1.png differ diff --git a/doc/calibration/Gamma/VGradient_2.png b/doc/calibration/Gamma/VGradient_2.png new file mode 100644 index 00000000..940dcda0 Binary files /dev/null and b/doc/calibration/Gamma/VGradient_2.png differ diff --git a/doc/calibration/RGB/blue_00007F.png b/doc/calibration/RGB/blue_00007F.png new file mode 100644 index 00000000..8ca29242 Binary files /dev/null and b/doc/calibration/RGB/blue_00007F.png differ diff --git a/doc/calibration/RGB/blue_0000FF.png b/doc/calibration/RGB/blue_0000FF.png new file mode 100644 index 00000000..727f8cf3 Binary files /dev/null and b/doc/calibration/RGB/blue_0000FF.png differ diff --git a/doc/calibration/RGB/cyan_007F7F.png b/doc/calibration/RGB/cyan_007F7F.png new file mode 100644 index 00000000..334e191b Binary files /dev/null and b/doc/calibration/RGB/cyan_007F7F.png differ diff --git a/doc/calibration/RGB/cyan_00FFFF.png b/doc/calibration/RGB/cyan_00FFFF.png new file mode 100644 index 00000000..5bf23750 Binary files /dev/null and b/doc/calibration/RGB/cyan_00FFFF.png differ diff --git a/doc/calibration/RGB/green_007F00.png b/doc/calibration/RGB/green_007F00.png new file mode 100644 index 00000000..d6e76dd1 Binary files /dev/null and b/doc/calibration/RGB/green_007F00.png differ diff --git a/doc/calibration/RGB/green_00FF00.png b/doc/calibration/RGB/green_00FF00.png new file mode 100644 index 00000000..01e18f12 Binary files /dev/null and b/doc/calibration/RGB/green_00FF00.png differ diff --git a/doc/calibration/RGB/magenta_7F007F.png b/doc/calibration/RGB/magenta_7F007F.png new file mode 100644 index 00000000..07e8f130 Binary files /dev/null and b/doc/calibration/RGB/magenta_7F007F.png differ diff --git a/doc/calibration/RGB/magenta_FF00FF.png b/doc/calibration/RGB/magenta_FF00FF.png new file mode 100644 index 00000000..891ac731 Binary files /dev/null and b/doc/calibration/RGB/magenta_FF00FF.png differ diff --git a/doc/calibration/RGB/red_7F0000.png b/doc/calibration/RGB/red_7F0000.png new file mode 100644 index 00000000..7dc59c7d Binary files /dev/null and b/doc/calibration/RGB/red_7F0000.png differ diff --git a/doc/calibration/RGB/red_FF0000.png b/doc/calibration/RGB/red_FF0000.png new file mode 100644 index 00000000..93d40815 Binary files /dev/null and b/doc/calibration/RGB/red_FF0000.png differ diff --git a/doc/calibration/RGB/yellow_7F7F00.png b/doc/calibration/RGB/yellow_7F7F00.png new file mode 100644 index 00000000..02967645 Binary files /dev/null and b/doc/calibration/RGB/yellow_7F7F00.png differ diff --git a/doc/calibration/RGB/yellow_FFFF00.png b/doc/calibration/RGB/yellow_FFFF00.png new file mode 100644 index 00000000..b2eb1711 Binary files /dev/null and b/doc/calibration/RGB/yellow_FFFF00.png differ diff --git a/include/hyperion/ColorAdjustment.h b/include/hyperion/ColorAdjustment.h new file mode 100644 index 00000000..0ce7f1a6 --- /dev/null +++ b/include/hyperion/ColorAdjustment.h @@ -0,0 +1,22 @@ +#pragma once + +// STL includes +#include + +// Utils includes +#include + +class ColorAdjustment +{ +public: + + /// Unique identifier for this color transform + std::string _id; + + /// The RED-Channel (RGB) adjustment + RgbChannelAdjustment _rgbRedAdjustment; + /// The GREEN-Channel (RGB) transform + RgbChannelAdjustment _rgbGreenAdjustment; + /// The BLUE-Channel (RGB) transform + RgbChannelAdjustment _rgbBlueAdjustment; +}; diff --git a/include/hyperion/Hyperion.h b/include/hyperion/Hyperion.h index 88c480d3..57440cf9 100644 --- a/include/hyperion/Hyperion.h +++ b/include/hyperion/Hyperion.h @@ -15,6 +15,7 @@ #include #include #include +#include #include // Effect engine includes @@ -28,10 +29,11 @@ class HsvTransform; class HslTransform; class RgbChannelTransform; class RgbChannelCorrection; +class RgbChannelAdjustment; class MultiColorTransform; class MultiColorCorrection; class MultiColorTemperature; - +class MultiColorAdjustment; /// /// The main class of Hyperion. This gives other 'users' access to the attached LedDevice through /// the priority muxer. @@ -135,6 +137,12 @@ public slots: /// const std::vector & getTemperatureIds() const; + /// + /// Returns the list with unique adjustment identifiers + /// @return The list with adjustment identifiers + /// + const std::vector & getAdjustmentIds() const; + /// /// Returns the ColorTransform with the given identifier /// @return The transform with the given identifier (or nullptr if the identifier does not exist) @@ -153,6 +161,12 @@ public slots: /// ColorCorrection * getTemperature(const std::string& id); + /// + /// Returns the ColorAdjustment with the given identifier + /// @return The adjustment with the given identifier (or nullptr if the identifier does not exist) + /// + ColorAdjustment * getAdjustment(const std::string& id); + /// /// Returns MessageForwarder Object /// @return instance of message forwarder object @@ -168,6 +182,9 @@ public slots: /// Tell Hyperion that the corrections have changed and the leds need to be updated void temperaturesUpdated(); + /// Tell Hyperion that the corrections have changed and the leds need to be updated + void adjustmentsUpdated(); + /// /// Clears the given priority channel. This will switch the led-colors to the colors of the next /// lower priority channel (or off if no more channels are set) @@ -208,16 +225,19 @@ public: static MultiColorTransform * createLedColorsTransform(const unsigned ledCnt, const Json::Value & colorTransformConfig); static MultiColorCorrection * createLedColorsCorrection(const unsigned ledCnt, const Json::Value & colorCorrectionConfig); static MultiColorCorrection * createLedColorsTemperature(const unsigned ledCnt, const Json::Value & colorTemperatureConfig); + static MultiColorAdjustment * createLedColorsAdjustment(const unsigned ledCnt, const Json::Value & colorAdjustmentConfig); static ColorTransform * createColorTransform(const Json::Value & transformConfig); static ColorCorrection * createColorCorrection(const Json::Value & correctionConfig); + static ColorAdjustment * createColorAdjustment(const Json::Value & adjustmentConfig); static HsvTransform * createHsvTransform(const Json::Value & hsvConfig); static HslTransform * createHslTransform(const Json::Value & hslConfig); static RgbChannelTransform * createRgbChannelTransform(const Json::Value& colorConfig); static RgbChannelCorrection * createRgbChannelCorrection(const Json::Value& colorConfig); + static RgbChannelAdjustment * createRgbChannelAdjustment(const Json::Value& colorConfig, const RgbChannel color); static LedDevice * createColorSmoothing(const Json::Value & smoothingConfig, LedDevice * ledDevice); static MessageForwarder * createMessageForwarder(const Json::Value & forwarderConfig); - + signals: /// Signal which is emitted when a priority channel is actively cleared /// This signal will not be emitted when a priority channel time out @@ -241,15 +261,18 @@ private: /// The priority muxer PriorityMuxer _muxer; - /// The transformation from corrected colors to led colors + /// The transformation from raw colors to led colors MultiColorTransform * _raw2ledTransform; /// The correction from raw colors to led colors MultiColorCorrection * _raw2ledCorrection; - /// The temperature from corrected colors to led colors + /// The temperature from raw colors to led colors MultiColorCorrection * _raw2ledTemperature; + /// The adjustment from raw colors to led colors + MultiColorAdjustment * _raw2ledAdjustment; + /// The actual LedDevice LedDevice * _device; diff --git a/include/utils/RgbChannelAdjustment.h b/include/utils/RgbChannelAdjustment.h new file mode 100644 index 00000000..4b0130bd --- /dev/null +++ b/include/utils/RgbChannelAdjustment.h @@ -0,0 +1,66 @@ +#pragma once + +// STL includes +#include + +/// Correction for a single color byte value +/// All configuration values are unsigned int and assume the color value to be between 0 and 255 +class RgbChannelAdjustment +{ +public: + /// Default constructor + RgbChannelAdjustment(); + + /// Constructor + /// @param adjustR + /// @param adjustG + /// @param adjustB + + RgbChannelAdjustment(int adjustR, int adjustG, int adjustB); + + /// Destructor + ~RgbChannelAdjustment(); + + /// @return The current adjustR value + uint8_t getadjustmentR() const; + + /// @param threshold New adjustR value + void setadjustmentR(uint8_t adjustR); + + /// @return The current adjustG value + uint8_t getadjustmentG() const; + + /// @param gamma New adjustG value + void setadjustmentG(uint8_t adjustG); + + /// @return The current adjustB value + uint8_t getadjustmentB() const; + + /// @param blacklevel New adjustB value + void setadjustmentB(uint8_t adjustB); + + /// Transform the given array value + /// @param input The input color bytes + /// @return The corrected byte value + uint8_t adjustmentR(uint8_t inputR) const; + uint8_t adjustmentG(uint8_t inputG) const; + uint8_t adjustmentB(uint8_t inputB) const; + + +private: + /// (re)-initilize the color mapping + void initializeMapping(); + +private: + /// The adjustment of R channel + int _adjustR; + /// The adjustment of G channel + int _adjustG; + /// The adjustment of B channel + int _adjustB; + + /// The mapping from input color to output color + int _mappingR[256]; + int _mappingG[256]; + int _mappingB[256]; +}; diff --git a/libsrc/hyperion/CMakeLists.txt b/libsrc/hyperion/CMakeLists.txt index a2188127..b4f53a19 100644 --- a/libsrc/hyperion/CMakeLists.txt +++ b/libsrc/hyperion/CMakeLists.txt @@ -19,6 +19,7 @@ SET(Hyperion_HEADERS ${CURRENT_SOURCE_DIR}/MultiColorTransform.h ${CURRENT_SOURCE_DIR}/MultiColorCorrection.h + ${CURRENT_SOURCE_DIR}/MultiColorAdjustment.h ${CURRENT_HEADER_DIR}/MessageForwarder.h ) @@ -32,6 +33,7 @@ SET(Hyperion_SOURCES ${CURRENT_SOURCE_DIR}/ImageToLedsMap.cpp ${CURRENT_SOURCE_DIR}/MultiColorTransform.cpp ${CURRENT_SOURCE_DIR}/MultiColorCorrection.cpp + ${CURRENT_SOURCE_DIR}/MultiColorAdjustment.cpp ${CURRENT_SOURCE_DIR}/LinearColorSmoothing.cpp ${CURRENT_SOURCE_DIR}/MessageForwarder.cpp ) diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp index 1d6925da..a5a85ff4 100644 --- a/libsrc/hyperion/Hyperion.cpp +++ b/libsrc/hyperion/Hyperion.cpp @@ -17,6 +17,7 @@ #include #include #include +#include // Leddevice includes #include @@ -24,6 +25,7 @@ #include "MultiColorTransform.h" #include "MultiColorCorrection.h" +#include "MultiColorAdjustment.h" #include "LinearColorSmoothing.h" // effect engine includes @@ -101,6 +103,7 @@ ColorTransform * Hyperion::createColorTransform(const Json::Value & transformCon return transform; } + ColorCorrection * Hyperion::createColorCorrection(const Json::Value & correctionConfig) { const std::string id = correctionConfig.get("id", "default").asString(); @@ -117,6 +120,30 @@ ColorCorrection * Hyperion::createColorCorrection(const Json::Value & correction return correction; } + +ColorAdjustment * Hyperion::createColorAdjustment(const Json::Value & adjustmentConfig) +{ + const std::string id = adjustmentConfig.get("id", "default").asString(); + + RgbChannelAdjustment * redAdjustment = createRgbChannelAdjustment(adjustmentConfig["pureRed"],RED); + RgbChannelAdjustment * greenAdjustment = createRgbChannelAdjustment(adjustmentConfig["pureGreen"],GREEN); + RgbChannelAdjustment * blueAdjustment = createRgbChannelAdjustment(adjustmentConfig["pureBlue"],BLUE); + + ColorAdjustment * adjustment = new ColorAdjustment(); + adjustment->_id = id; + adjustment->_rgbRedAdjustment = *redAdjustment; + adjustment->_rgbGreenAdjustment = *greenAdjustment; + adjustment->_rgbBlueAdjustment = *blueAdjustment; + + // Cleanup the allocated individual adjustments + delete redAdjustment; + delete greenAdjustment; + delete blueAdjustment; + + return adjustment; +} + + MultiColorTransform * Hyperion::createLedColorsTransform(const unsigned ledCnt, const Json::Value & colorConfig) { // Create the result, the transforms are added to this @@ -206,7 +233,7 @@ MultiColorCorrection * Hyperion::createLedColorsCorrection(const unsigned ledCnt } else if (!correctionConfig.isArray()) { - ColorCorrection * colorCorrection = createColorCorrection(colorConfig); + ColorCorrection * colorCorrection = createColorCorrection(correctionConfig); correction->addCorrection(colorCorrection); correction->setCorrectionForLed(colorCorrection->_id, 0, ledCnt-1); } @@ -280,7 +307,7 @@ MultiColorCorrection * Hyperion::createLedColorsTemperature(const unsigned ledCn } else if (!correctionConfig.isArray()) { - ColorCorrection * colorCorrection = createColorCorrection(colorConfig); + ColorCorrection * colorCorrection = createColorCorrection(correctionConfig); correction->addCorrection(colorCorrection); correction->setCorrectionForLed(colorCorrection->_id, 0, ledCnt-1); } @@ -339,6 +366,80 @@ MultiColorCorrection * Hyperion::createLedColorsTemperature(const unsigned ledCn return correction; } +MultiColorAdjustment * Hyperion::createLedColorsAdjustment(const unsigned ledCnt, const Json::Value & colorConfig) +{ + // Create the result, the transforms are added to this + MultiColorAdjustment * adjustment = new MultiColorAdjustment(ledCnt); + + const Json::Value adjustmentConfig = colorConfig.get("channelAdjustment", Json::nullValue); + if (adjustmentConfig.isNull()) + { + // Old style color transformation config (just one for all leds) + ColorAdjustment * colorAdjustment = createColorAdjustment(colorConfig); + adjustment->addAdjustment(colorAdjustment); + adjustment->setAdjustmentForLed(colorAdjustment->_id, 0, ledCnt-1); + } + else if (!adjustmentConfig.isArray()) + { + ColorAdjustment * colorAdjustment = createColorAdjustment(adjustmentConfig); + adjustment->addAdjustment(colorAdjustment); + adjustment->setAdjustmentForLed(colorAdjustment->_id, 0, ledCnt-1); + } + else + { + const QRegExp overallExp("([0-9]+(\\-[0-9]+)?)(,[ ]*([0-9]+(\\-[0-9]+)?))*"); + + for (Json::UInt i = 0; i < adjustmentConfig.size(); ++i) + { + const Json::Value & config = adjustmentConfig[i]; + ColorAdjustment * colorAdjustment = createColorAdjustment(config); + adjustment->addAdjustment(colorAdjustment); + + const QString ledIndicesStr = QString(config.get("leds", "").asCString()).trimmed(); + if (ledIndicesStr.compare("*") == 0) + { + // Special case for indices '*' => all leds + adjustment->setAdjustmentForLed(colorAdjustment->_id, 0, ledCnt-1); + std::cout << "HYPERION INFO: ColorAdjustment '" << colorAdjustment->_id << "' => [0; "<< ledCnt-1 << "]" << std::endl; + continue; + } + + if (!overallExp.exactMatch(ledIndicesStr)) + { + std::cerr << "HYPERION ERROR: Given led indices " << i << " not correct format: " << ledIndicesStr.toStdString() << std::endl; + continue; + } + + std::cout << "HYPERION INFO: ColorAdjustment '" << colorAdjustment->_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(); + + adjustment->setAdjustmentForLed(colorAdjustment->_id, startInd, endInd); + std::cout << startInd << "-" << endInd; + } + else + { + int index = ledIndexList[i].toInt(); + adjustment->setAdjustmentForLed(colorAdjustment->_id, index, index); + std::cout << index; + } + } + std::cout << "]" << std::endl; + } + } + return adjustment; +} + HsvTransform * Hyperion::createHsvTransform(const Json::Value & hsvConfig) { const double saturationGain = hsvConfig.get("saturationGain", 1.0).asDouble(); @@ -376,6 +477,32 @@ RgbChannelCorrection* Hyperion::createRgbChannelCorrection(const Json::Value& co return correction; } +RgbChannelAdjustment* Hyperion::createRgbChannelAdjustment(const Json::Value& colorConfig, const RgbChannel color) +{ + int varR, varG, varB; + if (color == RED) + { + varR = colorConfig.get("redChannel", 255).asInt(); + varG = colorConfig.get("greenChannel", 0).asInt(); + varB = colorConfig.get("blueChannel", 0).asInt(); + } + else if (color == GREEN) + { + varR = colorConfig.get("redChannel", 0).asInt(); + varG = colorConfig.get("greenChannel", 255).asInt(); + varB = colorConfig.get("blueChannel", 0).asInt(); + } + else if (color == BLUE) + { + varR = colorConfig.get("redChannel", 0).asInt(); + varG = colorConfig.get("greenChannel", 0).asInt(); + varB = colorConfig.get("blueChannel", 255).asInt(); + } + + RgbChannelAdjustment* adjustment = new RgbChannelAdjustment(varR, varG, varB); + return adjustment; +} + LedString Hyperion::createLedString(const Json::Value& ledsConfig, const ColorOrder deviceOrder) { LedString ledString; @@ -490,6 +617,7 @@ MessageForwarder * Hyperion::getForwarder() Hyperion::Hyperion(const Json::Value &jsonConfig) : _ledString(createLedString(jsonConfig["leds"], createColorOrder(jsonConfig["device"]))), _muxer(_ledString.leds().size()), + _raw2ledAdjustment(createLedColorsAdjustment(_ledString.leds().size(), jsonConfig["color"])), _raw2ledCorrection(createLedColorsCorrection(_ledString.leds().size(), jsonConfig["color"])), _raw2ledTemperature(createLedColorsTemperature(_ledString.leds().size(), jsonConfig["color"])), _raw2ledTransform(createLedColorsTransform(_ledString.leds().size(), jsonConfig["color"])), @@ -498,6 +626,10 @@ Hyperion::Hyperion(const Json::Value &jsonConfig) : _messageForwarder(createMessageForwarder(jsonConfig["forwarder"])), _timer() { + if (!_raw2ledAdjustment->verifyAdjustments()) + { + throw std::runtime_error("HYPERION ERROR: Color adjustment incorrectly set"); + } if (!_raw2ledCorrection->verifyCorrections()) { throw std::runtime_error("HYPERION ERROR: Color correction incorrectly set"); @@ -551,6 +683,9 @@ Hyperion::~Hyperion() // delete the color temperature correction delete _raw2ledTemperature; + + // delete the color adjustment + delete _raw2ledAdjustment; // delete the message forwarder delete _messageForwarder; @@ -609,6 +744,11 @@ const std::vector & Hyperion::getTemperatureIds() const return _raw2ledTemperature->getCorrectionIds(); } +const std::vector & Hyperion::getAdjustmentIds() const +{ + return _raw2ledAdjustment->getAdjustmentIds(); +} + ColorTransform * Hyperion::getTransform(const std::string& id) { return _raw2ledTransform->getTransform(id); @@ -624,6 +764,11 @@ ColorCorrection * Hyperion::getTemperature(const std::string& id) return _raw2ledTemperature->getCorrection(id); } +ColorAdjustment * Hyperion::getAdjustment(const std::string& id) +{ + return _raw2ledAdjustment->getAdjustment(id); +} + void Hyperion::transformsUpdated() { update(); @@ -639,6 +784,11 @@ void Hyperion::temperaturesUpdated() update(); } +void Hyperion::adjustmentsUpdated() +{ + update(); +} + void Hyperion::clear(int priority) { if (_muxer.hasPriority(priority)) @@ -703,9 +853,11 @@ void Hyperion::update() const PriorityMuxer::InputInfo & priorityInfo = _muxer.getInputInfo(priority); // Apply the correction and the transform to each led and color-channel - std::vector correctedColors = _raw2ledCorrection->applyCorrection(priorityInfo.ledColors); - std::vector temperatureColors = _raw2ledTemperature->applyCorrection(correctedColors); - std::vector ledColors =_raw2ledTransform->applyTransform(temperatureColors); + // Avoid applying correction, the same task is performed by adjustment + // std::vector correctedColors = _raw2ledCorrection->applyCorrection(priorityInfo.ledColors); + std::vector adjustedColors = _raw2ledAdjustment->applyAdjustment(priorityInfo.ledColors); + std::vector transformColors =_raw2ledTransform->applyTransform(adjustedColors); + std::vector ledColors = _raw2ledTemperature->applyCorrection(transformColors); const std::vector& leds = _ledString.leds(); int i = 0; for (ColorRgb& color : ledColors) diff --git a/libsrc/hyperion/MultiColorAdjustment.cpp b/libsrc/hyperion/MultiColorAdjustment.cpp new file mode 100644 index 00000000..79ba1d21 --- /dev/null +++ b/libsrc/hyperion/MultiColorAdjustment.cpp @@ -0,0 +1,124 @@ + +// STL includes +#include + +// Hyperion includes +#include "MultiColorAdjustment.h" + +MultiColorAdjustment::MultiColorAdjustment(const unsigned ledCnt) : + _ledAdjustments(ledCnt, nullptr) +{ +} + +MultiColorAdjustment::~MultiColorAdjustment() +{ + // Clean up all the transforms + for (ColorAdjustment * adjustment : _adjustment) + { + delete adjustment; + } +} + +void MultiColorAdjustment::addAdjustment(ColorAdjustment * adjustment) +{ + _adjustmentIds.push_back(adjustment->_id); + _adjustment.push_back(adjustment); +} + +void MultiColorAdjustment::setAdjustmentForLed(const std::string& id, const unsigned startLed, const unsigned endLed) +{ + assert(startLed <= endLed); + assert(endLed < _ledAdjustments.size()); + + // Get the identified adjustment (don't care if is nullptr) + ColorAdjustment * adjustment = getAdjustment(id); + for (unsigned iLed=startLed; iLed<=endLed; ++iLed) + { + _ledAdjustments[iLed] = adjustment; + } +} + +bool MultiColorAdjustment::verifyAdjustments() const +{ + bool allLedsSet = true; + for (unsigned iLed=0; iLed<_ledAdjustments.size(); ++iLed) + { + if (_ledAdjustments[iLed] == nullptr) + { + std::cerr << "HYPERION (C.adjustment) ERROR: No adjustment set for " << iLed << std::endl; + allLedsSet = false; + } + } + return allLedsSet; +} + +const std::vector & MultiColorAdjustment::getAdjustmentIds() +{ + return _adjustmentIds; +} + +ColorAdjustment* MultiColorAdjustment::getAdjustment(const std::string& id) +{ + // Iterate through the unique adjustments until we find the one with the given id + for (ColorAdjustment* adjustment : _adjustment) + { + if (adjustment->_id == id) + { + return adjustment; + } + } + + // The ColorAdjustment was not found + return nullptr; +} + +std::vector MultiColorAdjustment::applyAdjustment(const std::vector& rawColors) +{ + // Create a copy, as we will do the rest of the adjustment in place + std::vector ledColors(rawColors); + + const size_t itCnt = std::min(_ledAdjustments.size(), rawColors.size()); + for (size_t i=0; i_rgbRedAdjustment.adjustmentR(color.red); + int RG = adjustment->_rgbRedAdjustment.adjustmentG(color.red); + int RB = adjustment->_rgbRedAdjustment.adjustmentB(color.red); + int GR = adjustment->_rgbGreenAdjustment.adjustmentR(color.green); + int GG = adjustment->_rgbGreenAdjustment.adjustmentG(color.green); + int GB = adjustment->_rgbGreenAdjustment.adjustmentB(color.green); + int BR = adjustment->_rgbBlueAdjustment.adjustmentR(color.blue); + int BG = adjustment->_rgbBlueAdjustment.adjustmentG(color.blue); + int BB = adjustment->_rgbBlueAdjustment.adjustmentB(color.blue); + + int ledR = RR + GR + BR; + int maxR = (int)adjustment->_rgbRedAdjustment.getadjustmentR(); + int ledG = RG + GG + BG; + int maxG = (int)adjustment->_rgbGreenAdjustment.getadjustmentG(); + int ledB = RB + GB + BB; + int maxB = (int)adjustment->_rgbBlueAdjustment.getadjustmentB(); + + if (ledR > maxR) + color.red = (uint8_t)maxR; + else + color.red = (uint8_t)ledR; + + if (ledG > maxG) + color.green = (uint8_t)maxG; + else + color.green = (uint8_t)ledG; + + if (ledB > maxB) + color.blue = (uint8_t)maxB; + else + color.blue = (uint8_t)ledB; + } + return ledColors; +} diff --git a/libsrc/hyperion/MultiColorAdjustment.h b/libsrc/hyperion/MultiColorAdjustment.h new file mode 100644 index 00000000..7f02b815 --- /dev/null +++ b/libsrc/hyperion/MultiColorAdjustment.h @@ -0,0 +1,66 @@ +#pragma once + +// STL includes +#include + +// Utils includes +#include + +// Hyperion includes +#include + +/// +/// 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 MultiColorAdjustment +{ +public: + MultiColorAdjustment(const unsigned ledCnt); + ~MultiColorAdjustment(); + + /** + * Adds a new ColorAdjustment to this MultiColorTransform + * + * @param adjustment The new ColorAdjustment (ownership is transfered) + */ + void addAdjustment(ColorAdjustment * adjustment); + + void setAdjustmentForLed(const std::string& id, const unsigned startLed, const unsigned endLed); + + bool verifyAdjustments() const; + + /// + /// Returns the identifier of all the unique ColorAdjustment + /// + /// @return The list with unique id's of the ColorAdjustment + const std::vector & getAdjustmentIds(); + + /// + /// Returns the pointer to the ColorAdjustment with the given id + /// + /// @param id The identifier of the ColorAdjustment + /// + /// @return The ColorAdjustment with the given id (or nullptr if it does not exist) + /// + ColorAdjustment* getAdjustment(const std::string& id); + + /// + /// Performs the color adjustment from raw-color to led-color + /// + /// @param rawColors The list with raw colors + /// + /// @return The list with led-colors + /// + std::vector applyAdjustment(const std::vector& rawColors); + +private: + /// List with transform ids + std::vector _adjustmentIds; + + /// List with unique ColorTransforms + std::vector _adjustment; + + /// List with a pointer to the ColorAdjustment for each individual led + std::vector _ledAdjustments; +}; diff --git a/libsrc/jsonserver/JsonClientConnection.cpp b/libsrc/jsonserver/JsonClientConnection.cpp index 033f5f6d..62346623 100644 --- a/libsrc/jsonserver/JsonClientConnection.cpp +++ b/libsrc/jsonserver/JsonClientConnection.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include // project includes @@ -252,6 +253,8 @@ void JsonClientConnection::handleMessage(const std::string &messageString) handleCorrectionCommand(message); else if (command == "temperature") handleTemperatureCommand(message); + else if (command == "adjustment") + handleAdjustmentCommand(message); else handleNotImplemented(); } @@ -470,6 +473,34 @@ void JsonClientConnection::handleServerInfoCommand(const Json::Value &) whitelevel.append(colorTransform->_rgbGreenTransform.getWhitelevel()); whitelevel.append(colorTransform->_rgbBlueTransform.getWhitelevel()); } + + // collect adjustment information + Json::Value & adjustmentArray = info["adjustment"]; + for (const std::string& adjustmentId : _hyperion->getAdjustmentIds()) + { + const ColorAdjustment * colorAdjustment = _hyperion->getAdjustment(adjustmentId); + if (colorAdjustment == nullptr) + { + std::cerr << "JSONCLIENT ERROR: Incorrect color adjustment id: " << adjustmentId << std::endl; + continue; + } + + Json::Value & adjustment = adjustmentArray.append(Json::Value()); + adjustment["id"] = adjustmentId; + + Json::Value & redAdjust = adjustment["redAdjust"]; + redAdjust.append(colorAdjustment->_rgbRedAdjustment.getadjustmentR()); + redAdjust.append(colorAdjustment->_rgbRedAdjustment.getadjustmentG()); + redAdjust.append(colorAdjustment->_rgbRedAdjustment.getadjustmentB()); + Json::Value & greenAdjust = adjustment["greenAdjust"]; + greenAdjust.append(colorAdjustment->_rgbGreenAdjustment.getadjustmentR()); + greenAdjust.append(colorAdjustment->_rgbGreenAdjustment.getadjustmentG()); + greenAdjust.append(colorAdjustment->_rgbGreenAdjustment.getadjustmentB()); + Json::Value & blueAdjust = adjustment["blueAdjust"]; + blueAdjust.append(colorAdjustment->_rgbBlueAdjustment.getadjustmentR()); + blueAdjust.append(colorAdjustment->_rgbBlueAdjustment.getadjustmentG()); + blueAdjust.append(colorAdjustment->_rgbBlueAdjustment.getadjustmentB()); + } // collect effect info Json::Value & effects = info["effects"] = Json::Value(Json::arrayValue); @@ -634,6 +665,47 @@ void JsonClientConnection::handleTemperatureCommand(const Json::Value &message) sendSuccessReply(); } + +void JsonClientConnection::handleAdjustmentCommand(const Json::Value &message) +{ + const Json::Value & adjustment = message["adjustment"]; + + const std::string adjustmentId = adjustment.get("id", _hyperion->getAdjustmentIds().front()).asString(); + ColorAdjustment * colorAdjustment = _hyperion->getAdjustment(adjustmentId); + if (colorAdjustment == nullptr) + { + //sendErrorReply(std::string("Incorrect transform identifier: ") + transformId); + return; + } + + if (adjustment.isMember("redAdjust")) + { + const Json::Value & values = adjustment["redAdjust"]; + colorAdjustment->_rgbRedAdjustment.setadjustmentR(values[0u].asInt()); + colorAdjustment->_rgbRedAdjustment.setadjustmentG(values[1u].asInt()); + colorAdjustment->_rgbRedAdjustment.setadjustmentB(values[2u].asInt()); + } + + if (adjustment.isMember("greenAdjust")) + { + const Json::Value & values = adjustment["greenAdjust"]; + colorAdjustment->_rgbGreenAdjustment.setadjustmentR(values[0u].asInt()); + colorAdjustment->_rgbGreenAdjustment.setadjustmentG(values[1u].asInt()); + colorAdjustment->_rgbGreenAdjustment.setadjustmentB(values[2u].asInt()); + } + + if (adjustment.isMember("blueAdjust")) + { + const Json::Value & values = adjustment["blueAdjust"]; + colorAdjustment->_rgbBlueAdjustment.setadjustmentR(values[0u].asInt()); + colorAdjustment->_rgbBlueAdjustment.setadjustmentG(values[1u].asInt()); + colorAdjustment->_rgbBlueAdjustment.setadjustmentB(values[2u].asInt()); + } + // commit the changes + _hyperion->adjustmentsUpdated(); + + sendSuccessReply(); +} void JsonClientConnection::handleNotImplemented() { @@ -712,7 +784,6 @@ void JsonClientConnection::sendMessage(const Json::Value & message, QTcpSocket * } - void JsonClientConnection::sendSuccessReply() { // create reply diff --git a/libsrc/jsonserver/JsonClientConnection.h b/libsrc/jsonserver/JsonClientConnection.h index acf58d7d..ff8da15a 100644 --- a/libsrc/jsonserver/JsonClientConnection.h +++ b/libsrc/jsonserver/JsonClientConnection.h @@ -126,6 +126,13 @@ private: /// @param message the incoming message /// void handleTemperatureCommand(const Json::Value & message); + + /// + /// Handle an incoming JSON Adjustment message + /// + /// @param message the incoming message + /// + void handleAdjustmentCommand(const Json::Value & message); /// /// Handle an incoming JSON message of unknown type diff --git a/libsrc/jsonserver/JsonSchemas.qrc b/libsrc/jsonserver/JsonSchemas.qrc index 193624ba..6556bf32 100644 --- a/libsrc/jsonserver/JsonSchemas.qrc +++ b/libsrc/jsonserver/JsonSchemas.qrc @@ -9,6 +9,7 @@ schema/schema-transform.json schema/schema-correction.json schema/schema-temperature.json + schema/schema-adjustment.json schema/schema-effect.json diff --git a/libsrc/jsonserver/schema/schema-adjustment.json b/libsrc/jsonserver/schema/schema-adjustment.json new file mode 100644 index 00000000..c6e2ba5d --- /dev/null +++ b/libsrc/jsonserver/schema/schema-adjustment.json @@ -0,0 +1,56 @@ +{ + "type":"object", + "required":true, + "properties":{ + "command": { + "type" : "string", + "required" : true, + "enum" : ["adjustment"] + }, + "adjustment": { + "type": "object", + "required": true, + "properties": { + "id" : { + "type" : "string", + "required" : false + }, + "redAdjust": { + "type": "array", + "required": false, + "items" : { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "minItems": 3, + "maxItems": 3 + }, + "greenAdjust": { + "type": "array", + "required": false, + "items" : { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "minItems": 3, + "maxItems": 3 + }, + "blueAdjust": { + "type": "array", + "required": false, + "items" : { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "minItems": 3, + "maxItems": 3 + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false +} diff --git a/libsrc/jsonserver/schema/schema.json b/libsrc/jsonserver/schema/schema.json index 061339d1..91106162 100644 --- a/libsrc/jsonserver/schema/schema.json +++ b/libsrc/jsonserver/schema/schema.json @@ -5,7 +5,7 @@ "command": { "type" : "string", "required" : true, - "enum" : ["color", "image", "effect", "serverinfo", "clear", "clearall", "transform", "correction", "temperature"] + "enum" : ["color", "image", "effect", "serverinfo", "clear", "clearall", "transform", "correction", "temperature", "adjustment"] } } } diff --git a/libsrc/utils/CMakeLists.txt b/libsrc/utils/CMakeLists.txt index 8de00707..5978c2c1 100644 --- a/libsrc/utils/CMakeLists.txt +++ b/libsrc/utils/CMakeLists.txt @@ -29,6 +29,8 @@ add_library(hyperion-utils ${CURRENT_SOURCE_DIR}/RgbChannelTransform.cpp ${CURRENT_HEADER_DIR}/RgbChannelCorrection.h ${CURRENT_SOURCE_DIR}/RgbChannelCorrection.cpp + ${CURRENT_HEADER_DIR}/RgbChannelAdjustment.h + ${CURRENT_SOURCE_DIR}/RgbChannelAdjustment.cpp ${CURRENT_HEADER_DIR}/jsonschema/JsonFactory.h ${CURRENT_HEADER_DIR}/jsonschema/JsonSchemaChecker.h diff --git a/libsrc/utils/RgbChannelAdjustment.cpp b/libsrc/utils/RgbChannelAdjustment.cpp new file mode 100644 index 00000000..0c5468c7 --- /dev/null +++ b/libsrc/utils/RgbChannelAdjustment.cpp @@ -0,0 +1,107 @@ +// STL includes +#include + +// Utils includes +#include + +RgbChannelAdjustment::RgbChannelAdjustment() : + _adjustR(255), + _adjustG(255), + _adjustB(255) +{ + initializeMapping(); +} + +RgbChannelAdjustment::RgbChannelAdjustment(int adjustR, int adjustG, int adjustB) : + _adjustR(adjustR), + _adjustG(adjustG), + _adjustB(adjustB) +{ + initializeMapping(); +} + +RgbChannelAdjustment::~RgbChannelAdjustment() +{ +} + +uint8_t RgbChannelAdjustment::getadjustmentR() const +{ + return _adjustR; +} + +void RgbChannelAdjustment::setadjustmentR(uint8_t adjustR) +{ + _adjustR = adjustR; + initializeMapping(); +} + +uint8_t RgbChannelAdjustment::getadjustmentG() const +{ + return _adjustG; +} + +void RgbChannelAdjustment::setadjustmentG(uint8_t adjustG) +{ + _adjustG = adjustG; + initializeMapping(); +} + +uint8_t RgbChannelAdjustment::getadjustmentB() const +{ + return _adjustB; +} + +void RgbChannelAdjustment::setadjustmentB(uint8_t adjustB) +{ + _adjustB = adjustB; + initializeMapping(); +} + +uint8_t RgbChannelAdjustment::adjustmentR(uint8_t inputR) const +{ + return _mappingR[inputR]; +} + +uint8_t RgbChannelAdjustment::adjustmentG(uint8_t inputG) const +{ + return _mappingG[inputG]; +} + +uint8_t RgbChannelAdjustment::adjustmentB(uint8_t inputB) const +{ + return _mappingB[inputB]; +} + +void RgbChannelAdjustment::initializeMapping() +{ + // initialize the mapping + for (int i = 0; i < 256; ++i) + { + int outputR = (i * _adjustR) / 255; + if (outputR > 255) + { + outputR = 255; + } + _mappingR[i] = outputR; + } + for (int i = 0; i < 256; ++i) + { + int outputG = (i * _adjustG) / 255; + if (outputG > 255) + { + outputG = 255; + } + _mappingG[i] = outputG; + } + for (int i = 0; i < 256; ++i) + { + int outputB = (i * _adjustB) / 255; + if (outputB > 255) + { + outputB = 255; + } + _mappingB[i] = outputB; + } + + +} diff --git a/src/hyperion-remote/ColorAdjustmentValues.h b/src/hyperion-remote/ColorAdjustmentValues.h new file mode 100644 index 00000000..9aaefc7c --- /dev/null +++ b/src/hyperion-remote/ColorAdjustmentValues.h @@ -0,0 +1,12 @@ +#pragma once + +/// Simple structure to contain the values of a color transformation +struct ColorAdjustmentValues +{ + /// The value for the red color-channel + int valueRed; + /// The value for the green color-channel + int valueGreen; + /// The value for the blue color-channel + int valueBlue; +}; diff --git a/src/hyperion-remote/CustomParameter.h b/src/hyperion-remote/CustomParameter.h index af1836a6..3e7dd826 100644 --- a/src/hyperion-remote/CustomParameter.h +++ b/src/hyperion-remote/CustomParameter.h @@ -13,6 +13,7 @@ // hyperion-remote includes #include "ColorTransformValues.h" #include "ColorCorrectionValues.h" +#include "ColorAdjustmentValues.h" /// Data parameter for a color typedef vlofgren::PODParameter> ColorParameter; @@ -26,6 +27,9 @@ typedef vlofgren::PODParameter TransformParameter; /// Data parameter for color correction values (list of three values) typedef vlofgren::PODParameter CorrectionParameter; +/// Data parameter for color correction values (list of three values) +typedef vlofgren::PODParameter AdjustmentParameter; + namespace vlofgren { /// /// Translates a string (as passed on the commandline) to a vector of colors @@ -161,4 +165,33 @@ namespace vlofgren { return correction; } + + template<> + ColorAdjustmentValues AdjustmentParameter::validate(const std::string& s) throw (Parameter::ParameterRejected) + { + ColorAdjustmentValues adjustment; + + // s should be split in 3 parts + // seperators are either a ',' or a space + QStringList components = QString(s.c_str()).split(" ", QString::SkipEmptyParts); + + if (components.size() == 3) + { + bool ok1, ok2, ok3; + adjustment.valueRed = components[0].toInt(&ok1); + adjustment.valueGreen = components[1].toInt(&ok2); + adjustment.valueBlue = components[2].toInt(&ok3); + + if (ok1 && ok2 && ok3) + { + return adjustment; + } + } + + std::stringstream errorMessage; + errorMessage << "Argument " << s << " can not be parsed to 3 integer values"; + throw Parameter::ParameterRejected(errorMessage.str()); + + return adjustment; + } } diff --git a/src/hyperion-remote/JsonConnection.cpp b/src/hyperion-remote/JsonConnection.cpp index 61367104..16438b7e 100644 --- a/src/hyperion-remote/JsonConnection.cpp +++ b/src/hyperion-remote/JsonConnection.cpp @@ -322,6 +322,51 @@ void JsonConnection::setTemperature(std::string * temperatureId, ColorCorrection parseReply(reply); } +void JsonConnection::setAdjustment(std::string * adjustmentId, ColorAdjustmentValues * redAdjustment, ColorAdjustmentValues * greenAdjustment, ColorAdjustmentValues * blueAdjustment) +{ + std::cout << "Set color adjustments" << std::endl; + + // create command + Json::Value command; + command["command"] = "adjustment"; + Json::Value & adjust = command["adjustment"]; + + if (adjustmentId != nullptr) + { + adjust["id"] = *adjustmentId; + } + + if (redAdjustment != nullptr) + { + Json::Value & v = adjust["redAdjust"]; + v.append(redAdjustment->valueRed); + v.append(redAdjustment->valueGreen); + v.append(redAdjustment->valueBlue); + } + + if (greenAdjustment != nullptr) + { + Json::Value & v = adjust["greenAdjust"]; + v.append(greenAdjustment->valueRed); + v.append(greenAdjustment->valueGreen); + v.append(greenAdjustment->valueBlue); + } + + if (blueAdjustment != nullptr) + { + Json::Value & v = adjust["blueAdjust"]; + v.append(blueAdjustment->valueRed); + v.append(blueAdjustment->valueGreen); + v.append(blueAdjustment->valueBlue); + } + + // send command message + Json::Value reply = sendMessage(command); + + // parse reply message + parseReply(reply); +} + Json::Value JsonConnection::sendMessage(const Json::Value & message) { // serialize message (FastWriter already appends a newline) diff --git a/src/hyperion-remote/JsonConnection.h b/src/hyperion-remote/JsonConnection.h index 48455110..d71ff3a3 100644 --- a/src/hyperion-remote/JsonConnection.h +++ b/src/hyperion-remote/JsonConnection.h @@ -15,6 +15,7 @@ // hyperion-remote includes #include "ColorTransformValues.h" #include "ColorCorrectionValues.h" +#include "ColorAdjustmentValues.h" /// /// Connection class to setup an connection to the hyperion server and execute commands @@ -130,6 +131,21 @@ public: std::string * temperatureId, ColorCorrectionValues * temperature); + /// + /// Set the color adjustment of the leds + /// + /// @note Note that providing a NULL will leave the settings on the server unchanged + /// + /// @param adjustmentId The identifier of the correction to set + /// @param redAdjustment The red channel adjustment values + /// @param greenAdjustment The green channel adjustment values + /// @param blueAdjustment The blue channel adjustment values + void setAdjustment( + std::string * adjustmentId, + ColorAdjustmentValues * redAdjustment, + ColorAdjustmentValues * greenAdjustment, + ColorAdjustmentValues * blueAdjustment); + private: /// /// Send a json command message and receive its reply diff --git a/src/hyperion-remote/hyperion-remote.cpp b/src/hyperion-remote/hyperion-remote.cpp index 2da4ecfa..8686a540 100644 --- a/src/hyperion-remote/hyperion-remote.cpp +++ b/src/hyperion-remote/hyperion-remote.cpp @@ -81,6 +81,10 @@ int main(int argc, char * argv[]) CorrectionParameter & argCorrection = parameters.add('Y', "correction" , "Set the correction of the leds (requires 3 space seperated values between 0 and 255)"); StringParameter & argIdT = parameters.add ('z', "qualifier" , "Identifier(qualifier) of the temperature correction to set"); CorrectionParameter & argTemperature = parameters.add('Z', "temperature" , "Set the temperature correction of the leds (requires 3 space seperated values between 0 and 255)"); + StringParameter & argIdA = parameters.add ('j', "qualifier" , "Identifier(qualifier) of the adjustment to set"); + AdjustmentParameter & argRAdjust = parameters.add('R', "redAdjustment" , "Set the adjustment of the red color (requires 3 space seperated values between 0 and 255)"); + AdjustmentParameter & argGAdjust = parameters.add('G', "greenAdjustment", "Set the adjustment of the green color (requires 3 space seperated values between 0 and 255)"); + AdjustmentParameter & argBAdjust = parameters.add('B', "blueAdjustment", "Set the adjustment of the blue color (requires 3 space seperated values between 0 and 255)"); // set the default values argAddress.setDefault(defaultServerAddress.toStdString()); @@ -100,10 +104,11 @@ int main(int argc, char * argv[]) // check if at least one of the available color transforms is set bool colorTransform = argSaturation.isSet() || argValue.isSet() || argSaturationL.isSet() || argLuminance.isSet() || argThreshold.isSet() || argGamma.isSet() || argBlacklevel.isSet() || argWhitelevel.isSet(); - bool colorModding = colorTransform || argCorrection.isSet() || argTemperature.isSet(); + bool colorAdjust = argRAdjust.isSet() || argGAdjust.isSet() || argBAdjust.isSet(); + bool colorModding = colorTransform || colorAdjust || argCorrection.isSet() || argTemperature.isSet(); // check that exactly one command was given - int commandCount = count({argColor.isSet(), argImage.isSet(), argEffect.isSet(), argServerInfo.isSet(), argClear.isSet(), argClearAll.isSet(), colorModding}); + int commandCount = count({argColor.isSet(), argImage.isSet(), argEffect.isSet(), argServerInfo.isSet(), argClear.isSet(), argClearAll.isSet(), colorModding}); if (commandCount != 1) { std::cerr << (commandCount == 0 ? "No command found." : "Multiple commands found.") << " Provide exactly one of the following options:" << std::endl; @@ -127,6 +132,10 @@ int main(int argc, char * argv[]) std::cerr << " " << argCorrection.usageLine() << std::endl; std::cerr << " " << argIdT.usageLine() << std::endl; std::cerr << " " << argTemperature.usageLine() << std::endl; + std::cerr << " " << argIdA.usageLine() << std::endl; + std::cerr << " " << argRAdjust.usageLine() << std::endl; + std::cerr << " " << argGAdjust.usageLine() << std::endl; + std::cerr << " " << argBAdjust.usageLine() << std::endl; return 1; } @@ -186,6 +195,24 @@ int main(int argc, char * argv[]) argIdT.isSet() ? &tempId : nullptr, argTemperature.isSet() ? &temperature : nullptr); } + + if (colorAdjust) + { + std::string adjustId; + ColorAdjustmentValues redChannel, greenChannel, blueChannel; + + if (argIdA.isSet()) adjustId = argIdA.getValue(); + if (argRAdjust.isSet()) redChannel = argRAdjust.getValue(); + if (argGAdjust.isSet()) greenChannel = argGAdjust.getValue(); + if (argBAdjust.isSet()) blueChannel = argBAdjust.getValue(); + + connection.setAdjustment( + argIdA.isSet() ? &adjustId : nullptr, + argRAdjust.isSet() ? &redChannel : nullptr, + argGAdjust.isSet() ? &greenChannel : nullptr, + argBAdjust.isSet() ? &blueChannel : nullptr); + + } if (colorTransform) { std::string transId;