diff --git a/assets/webconfig/i18n/en.json b/assets/webconfig/i18n/en.json
index bb3453b8..455979b4 100644
--- a/assets/webconfig/i18n/en.json
+++ b/assets/webconfig/i18n/en.json
@@ -227,6 +227,7 @@
"edt_append_degree": "°",
"edt_append_frames": "frames",
"edt_append_hz": "Hz",
+ "edt_append_kelvin": "K",
"edt_append_leds": "LEDs",
"edt_append_ms": "ms",
"edt_append_ns": "ns",
@@ -261,6 +262,8 @@
"edt_conf_color_blue_title": "Blue",
"edt_conf_color_brightnessComp_expl": "Compensates brightness differences between red green blue, cyan magenta yellow and white. 100 means full compensation, 0 no compensation",
"edt_conf_color_brightnessComp_title": "Brightness compensation",
+ "edt_conf_color_brightnessGain_expl": "Adjusts the brightness of colors. 1.0 means no change, over 1.0 increases brightness, under 1.0 decreases brightness.",
+ "edt_conf_color_brightnessGain_title": "Brightness gain",
"edt_conf_color_brightness_expl": "set overall brightness of LEDs",
"edt_conf_color_brightness_title": "Brightness",
"edt_conf_color_channelAdjustment_header_expl": "Create color profiles that could be assigned to a specific component. Adjust color, gamma, brightness, compensation and more.",
@@ -287,10 +290,10 @@
"edt_conf_color_magenta_title": "Magenta",
"edt_conf_color_red_expl": "The calibrated red value.",
"edt_conf_color_red_title": "Red",
+ "edt_conf_color_temperature_expl": "Adjusts the corlor temperature.",
+ "edt_conf_color_temperature_title": "Temperature",
"edt_conf_color_saturationGain_expl": "Adjusts the saturation of colors. 1.0 means no change, over 1.0 increases saturation, under 1.0 desaturates.",
"edt_conf_color_saturationGain_title": "Saturation gain",
- "edt_conf_color_brightnessGain_expl": "Adjusts the brightness of colors. 1.0 means no change, over 1.0 increases brightness, under 1.0 decreases brightness.",
- "edt_conf_color_brightnessGain_title": "Brightness gain",
"edt_conf_color_white_expl": "The calibrated white value.",
"edt_conf_color_white_title": "White",
"edt_conf_color_yellow_expl": "The calibrated yellow value.",
@@ -446,6 +449,8 @@
"edt_conf_smooth_heading_title": "Smoothing",
"edt_conf_smooth_interpolationRate_expl": "Speed of the calculation of smooth intermediate frames.",
"edt_conf_smooth_interpolationRate_title": "Interpolation Rate",
+ "edt_conf_smooth_outputRate_expl": "The output speed to your LED controller.",
+ "edt_conf_smooth_outputRate_title": "Output Rate",
"edt_conf_smooth_time_ms_expl": "How long should the smoothing gather pictures?",
"edt_conf_smooth_time_ms_title": "Time",
"edt_conf_smooth_type_expl": "Type of smoothing.",
diff --git a/assets/webconfig/js/content_remote.js b/assets/webconfig/js/content_remote.js
index d0c1d9c2..a999b5fc 100644
--- a/assets/webconfig/js/content_remote.js
+++ b/assets/webconfig/js/content_remote.js
@@ -75,11 +75,12 @@ $(document).ready(function () {
sColor[key].key == "brightnessCompensation" ||
sColor[key].key == "backlightThreshold" ||
sColor[key].key == "saturationGain" ||
- sColor[key].key == "brightnessGain") {
+ sColor[key].key == "brightnessGain" ||
+ sColor[key].key == "temperature" ) {
property = '';
- if (sColor[key].append === "edt_append_percent") {
- property = '
' + property + '' + $.i18n("edt_append_percent") + '
';
+ if (sColor[key].append && sColor[key].append !== "" ) {
+ property = '' + property + '' + $.i18n(sColor[key].append) + '
';
}
}
else {
diff --git a/assets/webconfig/js/wizard.js b/assets/webconfig/js/wizard.js
index dedd50ed..e977e402 100755
--- a/assets/webconfig/js/wizard.js
+++ b/assets/webconfig/js/wizard.js
@@ -854,7 +854,12 @@ function checkUserResult(reply, usr) {
function useGroupId(id) {
$('#groupId').val(id);
- groupLights = hueGroups[id].lights;
+
+ //Ensure ligthIDs are strings
+ groupLights = hueGroups[id].lights.map(num => {
+ return String(num);
+ });
+
groupLightsLocations = hueGroups[id].locations;
get_hue_lights();
}
diff --git a/cmake/packages.cmake b/cmake/packages.cmake
index bc73057d..1dd8f6a6 100644
--- a/cmake/packages.cmake
+++ b/cmake/packages.cmake
@@ -72,7 +72,7 @@ endif()
# .deb files for apt
# https://cmake.org/cmake/help/latest/cpack_gen/deb.html
SET ( CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_SOURCE_DIR}/cmake/package-scripts/preinst;${CMAKE_SOURCE_DIR}/cmake/package-scripts/postinst;${CMAKE_SOURCE_DIR}/cmake/package-scripts/prerm" )
-SET ( CPACK_DEBIAN_PACKAGE_DEPENDS "libcec6 | libcec4" )
+SET ( CPACK_DEBIAN_PACKAGE_DEPENDS "libcec6 | libcec4 | libcec (>= 4.0)" )
SET ( CPACK_DEBIAN_PACKAGE_SECTION "Miscellaneous" )
# .rpm for rpm
diff --git a/config/hyperion.config.json.default b/config/hyperion.config.json.default
index a52f64ba..14333eb9 100644
--- a/config/hyperion.config.json.default
+++ b/config/hyperion.config.json.default
@@ -48,7 +48,8 @@
"brightness" : 100,
"brightnessCompensation" : 100,
"saturationGain" : 1.0,
- "brightnessGain" : 1.0
+ "brightnessGain" : 1.0,
+ "temperature" : 6600
}
]
},
diff --git a/include/hyperion/ColorAdjustment.h b/include/hyperion/ColorAdjustment.h
index 3e9b8dc8..99dd9315 100644
--- a/include/hyperion/ColorAdjustment.h
+++ b/include/hyperion/ColorAdjustment.h
@@ -1,7 +1,7 @@
#ifndef COLORADJUSTMENT_H
#define COLORADJUSTMENT_H
-// STL includes
+// Qt includes
#include
// Utils includes
diff --git a/include/hyperion/ColorCorrection.h b/include/hyperion/ColorCorrection.h
new file mode 100644
index 00000000..478cd35d
--- /dev/null
+++ b/include/hyperion/ColorCorrection.h
@@ -0,0 +1,18 @@
+#pragma once
+
+// Qt includes
+#include
+
+// Utils includes
+#include
+
+class ColorCorrection
+{
+public:
+
+ /// Unique identifier for this color correction
+ QString _id;
+
+ /// The RGB correction
+ RgbChannelCorrection _rgbCorrection;
+};
diff --git a/include/hyperion/Hyperion.h b/include/hyperion/Hyperion.h
index 34351502..ca812f90 100644
--- a/include/hyperion/Hyperion.h
+++ b/include/hyperion/Hyperion.h
@@ -22,6 +22,7 @@
#include
#include
#include
+#include
#include
#if defined(ENABLE_EFFECTENGINE)
@@ -48,6 +49,7 @@ class LinearColorSmoothing;
class EffectEngine;
#endif
class MultiColorAdjustment;
+class MultiColorCorrection;
class ColorAdjustment;
class SettingsManager;
class BGEffectHandler;
@@ -181,15 +183,30 @@ public slots:
///
QStringList getAdjustmentIds() const;
+ ///
+ /// Returns the list with unique correction identifiers
+ /// @return The list with correction identifiers
+ ///
+ QStringList getTemperatureIds() const;
+
///
/// 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 QString& id) const;
+ ///
+ /// Returns the ColorCorrection with the given identifier
+ /// @return The correction with the given identifier (or nullptr if the identifier does not exist)
+ ///
+ ColorCorrection * getTemperature(const QString& id) const;
+
/// Tell Hyperion that the corrections have changed and the leds need to be updated
void adjustmentsUpdated();
+ /// Tell Hyperion that the corrections have changed and the leds need to be updated
+ void temperaturesUpdated();
+
///
/// 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)
@@ -566,6 +583,9 @@ private:
/// The adjustment from raw colors to led colors
MultiColorAdjustment * _raw2ledAdjustment;
+ /// The temperature from raw colors to led colors
+ MultiColorCorrection * _raw2ledTemperature;
+
/// The actual LedDeviceWrapper
LedDeviceWrapper* _ledDeviceWrapper;
diff --git a/include/hyperion/MultiColorCorrection.h b/include/hyperion/MultiColorCorrection.h
new file mode 100644
index 00000000..36422871
--- /dev/null
+++ b/include/hyperion/MultiColorCorrection.h
@@ -0,0 +1,69 @@
+#pragma once
+
+// STL includes
+
+#include
+
+// Utils includes
+#include
+#include "utils/Logger.h"
+
+// Hyperion includes
+#include
+
+///
+/// The LedColorCorrection is responsible for performing color correction from 'raw' colors
+/// received as input to colors mapped to match the color-properties of the leds.
+///
+class MultiColorCorrection
+{
+public:
+ MultiColorCorrection(int ledCnt);
+ ~MultiColorCorrection();
+
+ /**
+ * Adds a new ColorCorrection to this MultiColorCorrection
+ *
+ * @param Correction The new ColorCorrection (ownership is transfered)
+ */
+ void addCorrection(ColorCorrection * correction);
+
+ void setCorrectionForLed(const QString& id, int startLed, int endLed);
+
+ bool verifyCorrections() const;
+
+ ///
+ /// Returns the identifier of all the unique ColorCorrection
+ ///
+ /// @return The list with unique id's of the ColorCorrections
+ QStringList & getCorrectionIds();
+
+ ///
+ /// Returns the pointer to the ColorCorrection with the given id
+ ///
+ /// @param id The identifier of the ColorCorrection
+ ///
+ /// @return The ColorCorrection with the given id (or nullptr if it does not exist)
+ ///
+ ColorCorrection* getCorrection(const QString& id);
+
+ ///
+ /// Performs the color transoformation from raw-color to led-color
+ ///
+ /// @param ledColors The list with raw colors
+ ///
+ void applyCorrection(std::vector& ledColors);
+
+private:
+ /// List with Correction ids
+ QStringList _correctionIds;
+
+ /// List with unique ColorCorrections
+ std::vector _correction;
+
+ /// List with a pointer to the ColorCorrection for each individual led
+ std::vector _ledCorrections;
+
+ // logger instance
+ Logger * _log;
+};
diff --git a/include/utils/KelvinToRgb.h b/include/utils/KelvinToRgb.h
new file mode 100644
index 00000000..e044375a
--- /dev/null
+++ b/include/utils/KelvinToRgb.h
@@ -0,0 +1,72 @@
+#ifndef KELVINTORGB_H
+#define KELVINTORGB_H
+
+#include
+
+#include
+
+
+// Constants
+namespace {
+const int TEMPERATURE_MINIMUM = 1000;
+const int TEMPERATUR_MAXIMUM = 40000;
+} //End of constants
+
+static ColorRgb getRgbFromTemperature(int temperature)
+{
+ //Temperature input in Kelvin valid in the range 1000 K to 40000 K. White light = 6600K
+ temperature = qBound(TEMPERATURE_MINIMUM, temperature, TEMPERATUR_MAXIMUM);
+
+ // All calculations require temperature / 100, so only do the conversion once.
+ temperature /= 100;
+
+ // Compute each color in turn.
+ int red, green, blue;
+
+ // red
+ if (temperature <= 66)
+ {
+ red = 255;
+ }
+ else
+ {
+ // Note: the R-squared value for this approximation is 0.988.
+ red = static_cast(329.698727446 * (pow(temperature - 60, -0.1332047592)));
+ }
+
+ // green
+ if (temperature <= 66)
+ {
+ // Note: the R-squared value for this approximation is 0.996.
+ green = static_cast(99.4708025861 * log(temperature) - 161.1195681661);
+
+ }
+ else
+ {
+ // Note: the R-squared value for this approximation is 0.987.
+ green = static_cast(288.1221695283 * (pow(temperature - 60, -0.0755148492)));
+ }
+
+ // blue
+ if (temperature >= 66)
+ {
+ blue = 255;
+ }
+ else if (temperature <= 19)
+ {
+ blue = 0;
+ }
+ else
+ {
+ // Note: the R-squared value for this approximation is 0.998.
+ blue = static_cast(138.5177312231 * log(temperature - 10) - 305.0447927307);
+ }
+
+ return {
+ static_cast(qBound(0, red, 255)),
+ static_cast(qBound(0, green, 255)),
+ static_cast(qBound(0, blue, 255)),
+ };
+}
+
+#endif // KELVINTORGB_H
diff --git a/include/utils/RgbChannelCorrection.h b/include/utils/RgbChannelCorrection.h
new file mode 100644
index 00000000..f09b9cef
--- /dev/null
+++ b/include/utils/RgbChannelCorrection.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 RgbChannelCorrection
+{
+public:
+ /// Default constructor
+ RgbChannelCorrection();
+
+ /// Constructor
+ /// @param correctionR
+ /// @param correctionG
+ /// @param correctionB
+
+ RgbChannelCorrection(int correctionR, int correctionG, int correctionB);
+
+ /// Destructor
+ ~RgbChannelCorrection();
+
+ /// @return The current correctionR value
+ uint8_t getcorrectionR() const;
+
+ /// @param threshold New correctionR value
+ void setcorrectionR(uint8_t correctionR);
+
+ /// @return The current correctionG value
+ uint8_t getcorrectionG() const;
+
+ /// @param gamma New correctionG value
+ void setcorrectionG(uint8_t correctionG);
+
+ /// @return The current correctionB value
+ uint8_t getcorrectionB() const;
+
+ /// @param blacklevel New correctionB value
+ void setcorrectionB(uint8_t correctionB);
+
+ /// Transform the given array value
+ /// @param input The input color bytes
+ /// @return The corrected byte value
+ uint8_t correctionR(uint8_t inputR) const;
+ uint8_t correctionG(uint8_t inputG) const;
+ uint8_t correctionB(uint8_t inputB) const;
+
+
+private:
+ /// (re)-initilize the color mapping
+ void initializeMapping();
+
+private:
+ /// The correction of R channel
+ int _correctionR;
+ /// The correction of G channel
+ int _correctionG;
+ /// The correction of B channel
+ int _correctionB;
+
+ /// The mapping from input color to output color
+ int _mappingR[256];
+ int _mappingG[256];
+ int _mappingB[256];
+};
diff --git a/include/utils/hyperion.h b/include/utils/hyperion.h
index 5349d38d..704c121a 100644
--- a/include/utils/hyperion.h
+++ b/include/utils/hyperion.h
@@ -4,8 +4,10 @@
#include
#include
+#include "hyperion/MultiColorCorrection.h"
#include
#include
+#include
// fg effect
#include
@@ -14,6 +16,8 @@
#include
#endif
+#include
+
///
/// @brief Provide utility methods for Hyperion class
///
@@ -100,6 +104,32 @@ namespace hyperion {
);
}
+ RgbChannelCorrection* createRgbChannelCorrection(const QJsonObject& colorConfig)
+ {
+ int varR = colorConfig["red"].toInt(255);
+ int varG = colorConfig["green"].toInt(255);
+ int varB = colorConfig["blue"].toInt(255);
+
+ RgbChannelCorrection* correction = new RgbChannelCorrection(varR, varG, varB);
+ return correction;
+ }
+
+ ColorCorrection * createColorCorrection(const QJsonObject& correctionConfig)
+ {
+ const QString id = correctionConfig["id"].toString("default");
+
+ RgbChannelCorrection * rgbCorrection = createRgbChannelCorrection(correctionConfig);
+
+ ColorCorrection * correction = new ColorCorrection();
+ correction->_id = id;
+ correction->_rgbCorrection = *rgbCorrection;
+
+ // Cleanup the allocated individual transforms
+ delete rgbCorrection;
+
+ return correction;
+ }
+
ColorAdjustment* createColorAdjustment(const QJsonObject & adjustmentConfig)
{
const QString id = adjustmentConfig["id"].toString("default");
@@ -179,6 +209,77 @@ namespace hyperion {
return adjustment;
}
+ MultiColorCorrection * createLedColorsTemperature(int ledCnt, const QJsonObject & colorConfig)
+ {
+ // Create the result, the corrections are added to this
+ MultiColorCorrection * correction = new MultiColorCorrection(ledCnt);
+
+ const QJsonValue adjustmentConfig = colorConfig["channelAdjustment"];
+ const QRegularExpression overallExp("([0-9]+(\\-[0-9]+)?)(,[ ]*([0-9]+(\\-[0-9]+)?))*");
+
+ const QJsonArray & adjustmentConfigArray = adjustmentConfig.toArray();
+ for (signed i = 0; i < adjustmentConfigArray.size(); ++i)
+ {
+ const QJsonObject & config = adjustmentConfigArray.at(i).toObject();
+ ColorAdjustment * colorAdjustment = createColorAdjustment(config);
+
+ int temperature = config["temperature"].toInt();
+
+ ColorRgb rgb = getRgbFromTemperature(temperature);
+
+ qDebug() << "createLedColorsTemperature: adjustment[temperture]: " << temperature << "-> " << rgb.toQString();
+
+ QJsonObject correctionConfig {
+ {"red", rgb.red},
+ {"green", rgb.green},
+ {"blue", rgb.blue}
+ };
+
+ ColorCorrection * colorCorrection = createColorCorrection(correctionConfig);
+ correction->addCorrection(colorCorrection);
+
+ const QString ledIndicesStr = config["leds"].toString("").trimmed();
+ if (ledIndicesStr.compare("*") == 0)
+ {
+ // Special case for indices '*' => all leds
+ correction->setCorrectionForLed(colorCorrection->_id, 0, ledCnt-1);
+ Info(Logger::getInstance("HYPERION"), "ColorCorrection '%s' => [0-%d]", QSTRING_CSTR(colorCorrection->_id), ledCnt-1);
+ continue;
+ }
+
+ if (!overallExp.match(ledIndicesStr).hasMatch())
+ {
+ Error(Logger::getInstance("HYPERION"), "Given led indices %d not correct format: %s", i, QSTRING_CSTR(ledIndicesStr));
+ continue;
+ }
+
+ std::stringstream ss;
+ const QStringList ledIndexList = ledIndicesStr.split(",");
+ for (int i=0; i 0)
+ {
+ ss << ", ";
+ }
+ 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);
+ ss << startInd << "-" << endInd;
+ }
+ else
+ {
+ int index = ledIndexList[i].toInt();
+ correction->setCorrectionForLed(colorCorrection->_id, index, index);
+ ss << index;
+ }
+ }
+ Info(Logger::getInstance("HYPERION"), "ColorCorrection '%s' => [%s]", QSTRING_CSTR(colorAdjustment->_id), ss.str().c_str());
+ }
+ return correction;
+ }
+
/**
* Construct the 'led-string' with the integration area definition per led and the color
* ordering of the RGB channels
diff --git a/libsrc/api/JSONRPC_schema/schema-adjustment.json b/libsrc/api/JSONRPC_schema/schema-adjustment.json
index b8856ef9..b0663736 100644
--- a/libsrc/api/JSONRPC_schema/schema-adjustment.json
+++ b/libsrc/api/JSONRPC_schema/schema-adjustment.json
@@ -146,6 +146,13 @@
"required" : false,
"minimum" : 0.1,
"maximum": 10.0
+ },
+ "temperature" :
+ {
+ "type" : "integer",
+ "required" : false,
+ "minimum" : 1000,
+ "maximum": 40000
}
},
"additionalProperties": false
diff --git a/libsrc/api/JsonAPI.cpp b/libsrc/api/JsonAPI.cpp
index 60a832b4..f937873c 100644
--- a/libsrc/api/JsonAPI.cpp
+++ b/libsrc/api/JsonAPI.cpp
@@ -60,6 +60,7 @@
#include
#include
#include
+#include
#include
#include
@@ -519,6 +520,8 @@ void JsonAPI::handleServerInfoCommand(const QJsonObject &message, const QString
adjustment["saturationGain"] = colorAdjustment->_okhsvTransform.getSaturationGain();
adjustment["brightnessGain"] = colorAdjustment->_okhsvTransform.getBrightnessGain();
+ adjustment["temperature"] = 6600;
+
adjustmentArray.append(adjustment);
}
@@ -936,6 +939,17 @@ void JsonAPI::handleAdjustmentCommand(const QJsonObject &message, const QString
if (adjustment.contains("brightnessGain"))
{
colorAdjustment->_okhsvTransform.setBrightnessGain(adjustment["brightnessGain"].toDouble());
+ }
+
+ if (adjustment.contains("temperature"))
+ {
+ int temperature = adjustment["temperature"].toInt(6500);
+ ColorRgb rgb = getRgbFromTemperature(temperature);
+
+ ColorCorrection *colorCorrection = _hyperion->getTemperature(adjustmentId);
+ colorCorrection->_rgbCorrection.setcorrectionR(rgb.red);
+ colorCorrection->_rgbCorrection.setcorrectionG(rgb.green);
+ colorCorrection->_rgbCorrection.setcorrectionB(rgb.blue);
}
// commit the changes
diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp
index 52216f02..26a26241 100644
--- a/libsrc/hyperion/Hyperion.cpp
+++ b/libsrc/hyperion/Hyperion.cpp
@@ -26,6 +26,7 @@
#include
#include
+#include
#include
#if defined(ENABLE_EFFECTENGINE)
@@ -56,6 +57,7 @@ Hyperion::Hyperion(quint8 instance, bool readonlyMode)
, _imageProcessor(nullptr)
, _muxer(nullptr)
, _raw2ledAdjustment(hyperion::createLedColorsAdjustment(static_cast(_ledString.leds().size()), getSetting(settings::COLOR).object()))
+ , _raw2ledTemperature(hyperion::createLedColorsTemperature(static_cast(_ledString.leds().size()), getSetting(settings::COLOR).object()))
, _ledDeviceWrapper(nullptr)
, _deviceSmooth(nullptr)
#if defined(ENABLE_EFFECTENGINE)
@@ -100,6 +102,11 @@ void Hyperion::start()
// get newVideoMode from HyperionIManager
connect(this, &Hyperion::newVideoMode, this, &Hyperion::handleNewVideoMode);
+ if (!_raw2ledTemperature->verifyCorrections())
+ {
+ Warning(_log, "Color temperature incorrectly set");
+ }
+
if (!_raw2ledAdjustment->verifyAdjustments())
{
Warning(_log, "At least one led has no color calibration, please add all leds from your led layout to an 'LED index' field!");
@@ -219,6 +226,9 @@ void Hyperion::freeObjects()
delete _raw2ledAdjustment;
+ // delete the color temperature correction
+ delete _raw2ledTemperature;
+
#if defined(ENABLE_FORWARDER)
delete _messageForwarder;
#endif
@@ -247,6 +257,15 @@ void Hyperion::handleSettingsUpdate(settings::type type, const QJsonDocument& co
{
Warning(_log, "At least one led has no color calibration, please add all leds from your led layout to an 'LED index' field!");
}
+
+ // change in color recreate ledTemperature
+ delete _raw2ledTemperature;
+ _raw2ledTemperature = hyperion::createLedColorsTemperature(static_cast(_ledString.leds().size()), obj);
+
+ if (!_raw2ledTemperature->verifyCorrections())
+ {
+ Warning(_log, "At least one led has no color calibration, please add all leds from your led layout to an 'LED index' field!");
+ }
}
else if(type == settings::LEDS)
{
@@ -279,6 +298,10 @@ void Hyperion::handleSettingsUpdate(settings::type type, const QJsonDocument& co
delete _raw2ledAdjustment;
_raw2ledAdjustment = hyperion::createLedColorsAdjustment(static_cast(_ledString.leds().size()), getSetting(settings::COLOR).object());
+ // change in leds recreate ledTemperature
+ delete _raw2ledTemperature;
+ _raw2ledTemperature = hyperion::createLedColorsTemperature(static_cast(_ledString.leds().size()), getSetting(settings::COLOR).object());
+
#if defined(ENABLE_EFFECTENGINE)
// start cached effects
_effectEngine->startCachedEffects();
@@ -494,17 +517,33 @@ QStringList Hyperion::getAdjustmentIds() const
return _raw2ledAdjustment->getAdjustmentIds();
}
+QStringList Hyperion::getTemperatureIds() const
+{
+ return _raw2ledTemperature->getCorrectionIds();
+}
+
ColorAdjustment * Hyperion::getAdjustment(const QString& id) const
{
return _raw2ledAdjustment->getAdjustment(id);
}
+ColorCorrection * Hyperion::getTemperature(const QString& id) const
+{
+ return _raw2ledTemperature->getCorrection(id);
+}
+
void Hyperion::adjustmentsUpdated()
{
emit adjustmentChanged();
update();
}
+void Hyperion::temperaturesUpdated()
+{
+ emit adjustmentChanged();
+ update();
+}
+
bool Hyperion::clear(int priority, bool forceClearAll)
{
bool isCleared = false;
@@ -680,6 +719,7 @@ void Hyperion::update()
emit rawLedColors(_ledBuffer);
_raw2ledAdjustment->applyAdjustment(_ledBuffer);
+ _raw2ledTemperature->applyCorrection(_ledBuffer);
int i = 0;
for (ColorRgb& color : _ledBuffer)
diff --git a/libsrc/hyperion/MultiColorCorrection.cpp b/libsrc/hyperion/MultiColorCorrection.cpp
new file mode 100644
index 00000000..74148e43
--- /dev/null
+++ b/libsrc/hyperion/MultiColorCorrection.cpp
@@ -0,0 +1,103 @@
+// Hyperion includes
+#include
+#include
+
+MultiColorCorrection::MultiColorCorrection(int ledCnt) :
+ _ledCorrections(ledCnt, nullptr)
+, _log(Logger::getInstance("CORRECTION"))
+{
+}
+
+MultiColorCorrection::~MultiColorCorrection()
+{
+ // Clean up all the correctinos
+ for (ColorCorrection * correction : _correction)
+ {
+ delete correction;
+ }
+}
+
+void MultiColorCorrection::addCorrection(ColorCorrection * correction)
+{
+ _correctionIds.push_back(correction->_id);
+ _correction.push_back(correction);
+}
+
+void MultiColorCorrection::setCorrectionForLed(const QString& id, int startLed, int endLed)
+{
+ // abort
+ if(startLed > endLed)
+ {
+ Error(_log,"startLed > endLed -> %d > %d", startLed, endLed);
+ return;
+ }
+ // catch wrong values
+ if(endLed > static_cast(_ledCorrections.size()-1))
+ {
+ Warning(_log,"The color correction 'LED index' field has LEDs specified which aren't part of your led layout");
+ endLed = static_cast(_ledCorrections.size()-1);
+ }
+
+ // Get the identified correction (don't care if is nullptr)
+ ColorCorrection * correction = getCorrection(id);
+ for (int iLed=startLed; iLed<=endLed; ++iLed)
+ {
+ _ledCorrections[iLed] = correction;
+ }
+}
+
+bool MultiColorCorrection::verifyCorrections() const
+{
+ bool ok = true;
+ for (unsigned iLed=0; iLed<_ledCorrections.size(); ++iLed)
+ {
+ ColorCorrection* adjustment = _ledCorrections[iLed];
+
+ if (adjustment == nullptr)
+ {
+ Warning(_log, "No correction set for led %d", iLed);
+ ok = false;
+ }
+ }
+ return ok;
+}
+
+QStringList & MultiColorCorrection::getCorrectionIds()
+{
+ return _correctionIds;
+}
+
+ColorCorrection* MultiColorCorrection::getCorrection(const QString& id)
+{
+ // Iterate through the unique corrections until we find the one with the given id
+ for (ColorCorrection * correction : _correction)
+ {
+ if (correction->_id == id)
+ {
+ return correction;
+ }
+ }
+
+ // The ColorCorrection was not found
+ return nullptr;
+}
+
+void MultiColorCorrection::applyCorrection(std::vector& ledColors)
+{
+ const size_t itCnt = qMin(_ledCorrections.size(), ledColors.size());
+ for (size_t i=0; i_rgbCorrection.correctionR(color.red);
+ color.green = correction->_rgbCorrection.correctionG(color.green);
+ color.blue = correction->_rgbCorrection.correctionB(color.blue);
+ }
+}
diff --git a/libsrc/hyperion/schema/schema-color.json b/libsrc/hyperion/schema/schema-color.json
index abe39560..33b1bdfe 100644
--- a/libsrc/hyperion/schema/schema-color.json
+++ b/libsrc/hyperion/schema/schema-color.json
@@ -221,6 +221,18 @@
"step" : 0.1,
"propertyOrder" : 16
},
+ "temperature" :
+ {
+ "type" : "integer",
+ "title" : "edt_conf_color_temperature_title",
+ "required" : true,
+ "minimum" : 1000,
+ "maximum": 40000,
+ "default" : 6600,
+ "step" : 100,
+ "append" : "edt_append_kelvin",
+ "propertyOrder" : 17
+ },
"gammaRed" :
{
"type" : "number",
@@ -230,7 +242,7 @@
"maximum": 100.0,
"default" : 2.2,
"step" : 0.1,
- "propertyOrder" : 17
+ "propertyOrder" : 18
},
"gammaGreen" :
{
@@ -241,7 +253,7 @@
"maximum": 100.0,
"default" : 2.2,
"step" : 0.1,
- "propertyOrder" : 18
+ "propertyOrder" : 19
},
"gammaBlue" :
{
@@ -252,7 +264,7 @@
"maximum": 100.0,
"default" : 2.2,
"step" : 0.1,
- "propertyOrder" : 19
+ "propertyOrder" : 20
}
},
"additionalProperties" : false
diff --git a/libsrc/utils/RgbChannelCorrection.cpp b/libsrc/utils/RgbChannelCorrection.cpp
new file mode 100644
index 00000000..7fb16884
--- /dev/null
+++ b/libsrc/utils/RgbChannelCorrection.cpp
@@ -0,0 +1,120 @@
+// STL includes
+#include
+
+// Utils includes
+#include
+
+RgbChannelCorrection::RgbChannelCorrection() :
+ _correctionR(255),
+ _correctionG(255),
+ _correctionB(255)
+{
+ initializeMapping();
+}
+
+RgbChannelCorrection::RgbChannelCorrection(int correctionR, int correctionG, int correctionB) :
+ _correctionR(correctionR),
+ _correctionG(correctionG),
+ _correctionB(correctionB)
+{
+ initializeMapping();
+}
+
+RgbChannelCorrection::~RgbChannelCorrection()
+{
+}
+
+uint8_t RgbChannelCorrection::getcorrectionR() const
+{
+ return _correctionR;
+}
+
+void RgbChannelCorrection::setcorrectionR(uint8_t correctionR)
+{
+ _correctionR = correctionR;
+ initializeMapping();
+}
+
+uint8_t RgbChannelCorrection::getcorrectionG() const
+{
+ return _correctionG;
+}
+
+void RgbChannelCorrection::setcorrectionG(uint8_t correctionG)
+{
+ _correctionG = correctionG;
+ initializeMapping();
+}
+
+uint8_t RgbChannelCorrection::getcorrectionB() const
+{
+ return _correctionB;
+}
+
+void RgbChannelCorrection::setcorrectionB(uint8_t correctionB)
+{
+ _correctionB = correctionB;
+ initializeMapping();
+}
+
+uint8_t RgbChannelCorrection::correctionR(uint8_t inputR) const
+{
+ return _mappingR[inputR];
+}
+
+uint8_t RgbChannelCorrection::correctionG(uint8_t inputG) const
+{
+ return _mappingG[inputG];
+}
+
+uint8_t RgbChannelCorrection::correctionB(uint8_t inputB) const
+{
+ return _mappingB[inputB];
+}
+
+void RgbChannelCorrection::initializeMapping()
+{
+ // initialize the mapping
+ for (int i = 0; i < 256; ++i)
+ {
+ int outputR = (i * _correctionR) / 255;
+ if (outputR < -255)
+ {
+ outputR = -255;
+ }
+ else if (outputR > 255)
+ {
+ outputR = 255;
+ }
+ _mappingR[i] = outputR;
+ }
+ for (int i = 0; i < 256; ++i)
+ {
+ int outputG = (i * _correctionG) / 255;
+ if (outputG < -255)
+ {
+ outputG = -255;
+ }
+ else if (outputG > 255)
+ {
+ outputG = 255;
+ }
+ _mappingG[i] = outputG;
+ }
+ for (int i = 0; i < 256; ++i)
+ {
+ int outputB = (i * _correctionB) / 255;
+ if (outputB < -255)
+ {
+ outputB = -255;
+ }
+ else if (outputB > 255)
+ {
+ outputB = 255;
+ }
+ _mappingB[i] = outputB;
+ }
+
+
+}
+