From 9acdf946bf5aae27ae995e6039e644fd9c3f053c Mon Sep 17 00:00:00 2001 From: AEtHeLsYn Date: Tue, 22 Dec 2015 10:01:47 +0100 Subject: [PATCH] Update Hyperion.cpp Former-commit-id: acf5e5c722402f7527ae0b942437d4c01917dccb --- libsrc/hyperion/Hyperion.cpp | 219 ++++++++++++++++++++++++++++++++++- 1 file changed, 217 insertions(+), 2 deletions(-) diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp index d6657046..dc6ca3fb 100644 --- a/libsrc/hyperion/Hyperion.cpp +++ b/libsrc/hyperion/Hyperion.cpp @@ -15,12 +15,15 @@ // hyperion include #include #include +#include +#include // Leddevice includes #include #include #include "MultiColorTransform.h" +#include "MultiColorCorrection.h" #include "LinearColorSmoothing.h" // effect engine includes @@ -77,6 +80,7 @@ ColorTransform * Hyperion::createColorTransform(const Json::Value & transformCon RgbChannelTransform * blueTransform = createRgbChannelTransform(transformConfig["blue"]); HsvTransform * hsvTransform = createHsvTransform(transformConfig["hsv"]); + HslTransform * hslTransform = createHslTransform(transformConfig["hsl"]); ColorTransform * transform = new ColorTransform(); transform->_id = id; @@ -84,16 +88,35 @@ ColorTransform * Hyperion::createColorTransform(const Json::Value & transformCon transform->_rgbGreenTransform = *greenTransform; transform->_rgbBlueTransform = *blueTransform; transform->_hsvTransform = *hsvTransform; + transform->_hslTransform = *hslTransform; + // Cleanup the allocated individual transforms delete redTransform; delete greenTransform; delete blueTransform; delete hsvTransform; + delete hslTransform; return transform; } +ColorCorrection * Hyperion::createColorCorrection(const Json::Value & correctionConfig) +{ + const std::string id = correctionConfig.get("id", "default").asString(); + + RgbChannelCorrection * rgbCorrection = createRgbChannelCorrection(correctionConfig["correctionValues"]); + + ColorCorrection * correction = new ColorCorrection(); + correction->_id = id; + correction->_rgbCorrection = *rgbCorrection; + + // Cleanup the allocated individual transforms + delete rgbCorrection; + + return correction; +} + MultiColorTransform * Hyperion::createLedColorsTransform(const unsigned ledCnt, const Json::Value & colorConfig) { // Create the result, the transforms are added to this @@ -168,6 +191,154 @@ MultiColorTransform * Hyperion::createLedColorsTransform(const unsigned ledCnt, return transform; } +MultiColorCorrection * Hyperion::createLedColorsCorrection(const unsigned ledCnt, const Json::Value & colorConfig) +{ + // Create the result, the corrections are added to this + MultiColorCorrection * correction = new MultiColorCorrection(ledCnt); + + const Json::Value correctionConfig = colorConfig.get("correction", Json::nullValue); + if (correctionConfig.isNull()) + { + // Old style color correction config (just one for all leds) + ColorCorrection * colorCorrection = createColorCorrection(colorConfig); + correction->addCorrection(colorCorrection); + correction->setCorrectionForLed(colorCorrection->_id, 0, ledCnt-1); + } + else if (!correctionConfig.isArray()) + { + ColorCorrection * colorCorrection = createColorCorrection(colorConfig); + correction->addCorrection(colorCorrection); + correction->setCorrectionForLed(colorCorrection->_id, 0, ledCnt-1); + } + else + { + const QRegExp overallExp("([0-9]+(\\-[0-9]+)?)(,[ ]*([0-9]+(\\-[0-9]+)?))*"); + + for (Json::UInt i = 0; i < correctionConfig.size(); ++i) + { + const Json::Value & config = correctionConfig[i]; + ColorCorrection * colorCorrection = createColorCorrection(config); + correction->addCorrection(colorCorrection); + + const QString ledIndicesStr = QString(config.get("leds", "").asCString()).trimmed(); + if (ledIndicesStr.compare("*") == 0) + { + // Special case for indices '*' => all leds + correction->setCorrectionForLed(colorCorrection->_id, 0, ledCnt-1); + std::cout << "ColorCorrection '" << colorCorrection->_id << "' => [0; "<< ledCnt-1 << "]" << std::endl; + continue; + } + + if (!overallExp.exactMatch(ledIndicesStr)) + { + std::cerr << "Given led indices " << i << " not correct format: " << ledIndicesStr.toStdString() << std::endl; + continue; + } + + std::cout << "ColorCorrection '" << colorCorrection->_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(); + + correction->setCorrectionForLed(colorCorrection->_id, startInd, endInd); + std::cout << startInd << "-" << endInd; + } + else + { + int index = ledIndexList[i].toInt(); + correction->setCorrectionForLed(colorCorrection->_id, index, index); + std::cout << index; + } + } + std::cout << "]" << std::endl; + } + } + return correction; +} + +MultiColorCorrection * Hyperion::createLedColorsTemperature(const unsigned ledCnt, const Json::Value & colorConfig) +{ + // Create the result, the corrections are added to this + MultiColorCorrection * correction = new MultiColorCorrection(ledCnt); + + const Json::Value correctionConfig = colorConfig.get("temperature", Json::nullValue); + if (correctionConfig.isNull()) + { + // Old style color correction config (just one for all leds) + ColorCorrection * colorCorrection = createColorCorrection(colorConfig); + correction->addCorrection(colorCorrection); + correction->setCorrectionForLed(colorCorrection->_id, 0, ledCnt-1); + } + else if (!correctionConfig.isArray()) + { + ColorCorrection * colorCorrection = createColorCorrection(colorConfig); + correction->addCorrection(colorCorrection); + correction->setCorrectionForLed(colorCorrection->_id, 0, ledCnt-1); + } + else + { + const QRegExp overallExp("([0-9]+(\\-[0-9]+)?)(,[ ]*([0-9]+(\\-[0-9]+)?))*"); + + for (Json::UInt i = 0; i < correctionConfig.size(); ++i) + { + const Json::Value & config = correctionConfig[i]; + ColorCorrection * colorCorrection = createColorCorrection(config); + correction->addCorrection(colorCorrection); + + const QString ledIndicesStr = QString(config.get("leds", "").asCString()).trimmed(); + if (ledIndicesStr.compare("*") == 0) + { + // Special case for indices '*' => all leds + correction->setCorrectionForLed(colorCorrection->_id, 0, ledCnt-1); + std::cout << "ColorCorrection '" << colorCorrection->_id << "' => [0; "<< ledCnt-1 << "]" << std::endl; + continue; + } + + if (!overallExp.exactMatch(ledIndicesStr)) + { + std::cerr << "Given led indices " << i << " not correct format: " << ledIndicesStr.toStdString() << std::endl; + continue; + } + + std::cout << "ColorCorrection '" << colorCorrection->_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(); + + correction->setCorrectionForLed(colorCorrection->_id, startInd, endInd); + std::cout << startInd << "-" << endInd; + } + else + { + int index = ledIndexList[i].toInt(); + correction->setCorrectionForLed(colorCorrection->_id, index, index); + std::cout << index; + } + } + std::cout << "]" << std::endl; + } + } + return correction; +} + HsvTransform * Hyperion::createHsvTransform(const Json::Value & hsvConfig) { const double saturationGain = hsvConfig.get("saturationGain", 1.0).asDouble(); @@ -176,6 +347,14 @@ HsvTransform * Hyperion::createHsvTransform(const Json::Value & hsvConfig) return new HsvTransform(saturationGain, valueGain); } +HslTransform * Hyperion::createHslTransform(const Json::Value & hslConfig) +{ + const double saturationGain = hslConfig.get("saturationGain", 1.0).asDouble(); + const double luminanceGain = hslConfig.get("luminanceGain", 1.0).asDouble(); + + return new HslTransform(saturationGain, luminanceGain); +} + RgbChannelTransform* Hyperion::createRgbChannelTransform(const Json::Value& colorConfig) { const double threshold = colorConfig.get("threshold", 0.0).asDouble(); @@ -187,6 +366,16 @@ RgbChannelTransform* Hyperion::createRgbChannelTransform(const Json::Value& colo return transform; } +RgbChannelCorrection* Hyperion::createRgbChannelCorrection(const Json::Value& colorConfig) +{ + const int varR = colorConfig.get("red", 255).asInt(); + const int varG = colorConfig.get("green", 255).asInt(); + const int varB = colorConfig.get("blue", 255).asInt(); + + RgbChannelCorrection* correction = new RgbChannelCorrection(varR, varG, varB); + return correction; +} + LedString Hyperion::createLedString(const Json::Value& ledsConfig, const ColorOrder deviceOrder) { LedString ledString; @@ -270,11 +459,17 @@ LedDevice * Hyperion::createColorSmoothing(const Json::Value & smoothingConfig, Hyperion::Hyperion(const Json::Value &jsonConfig) : _ledString(createLedString(jsonConfig["leds"], createColorOrder(jsonConfig["device"]))), _muxer(_ledString.leds().size()), + _raw2ledCorrection(createLedColorsCorrection(_ledString.leds().size(), jsonConfig["color"])), + _raw2ledTemperature(createLedColorsTemperature(_ledString.leds().size(), jsonConfig["color"])), _raw2ledTransform(createLedColorsTransform(_ledString.leds().size(), jsonConfig["color"])), _device(LedDeviceFactory::construct(jsonConfig["device"])), _effectEngine(nullptr), _timer() { + if (!_raw2ledCorrection->verifyCorrections()) + { + throw std::runtime_error("Color correction incorrectly set"); + } if (!_raw2ledTransform->verifyTransforms()) { throw std::runtime_error("Color transformation incorrectly set"); @@ -314,6 +509,9 @@ Hyperion::~Hyperion() // delete the color transform delete _raw2ledTransform; + + // delete the color correction + delete _raw2ledCorrection; } unsigned Hyperion::getLedCount() const @@ -359,16 +557,31 @@ const std::vector & Hyperion::getTransformIds() const return _raw2ledTransform->getTransformIds(); } +const std::vector & Hyperion::getCorrectionIds() const +{ + return _raw2ledCorrection->getCorrectionIds(); +} + ColorTransform * Hyperion::getTransform(const std::string& id) { return _raw2ledTransform->getTransform(id); } +ColorCorrection * Hyperion::getCorrection(const std::string& id) +{ + return _raw2ledCorrection->getCorrection(id); +} + void Hyperion::transformsUpdated() { update(); } +void Hyperion::correctionsUpdated() +{ + update(); +} + void Hyperion::clear(int priority) { if (_muxer.hasPriority(priority)) @@ -432,8 +645,10 @@ void Hyperion::update() int priority = _muxer.getCurrentPriority(); const PriorityMuxer::InputInfo & priorityInfo = _muxer.getInputInfo(priority); - // Apply the transform to each led and color-channel - std::vector ledColors = _raw2ledTransform->applyTransform(priorityInfo.ledColors); + // 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); const std::vector& leds = _ledString.leds(); int i = 0; for (ColorRgb& color : ledColors)