Integrate color temperature into RGB transformations

This commit is contained in:
LordGrey
2024-05-30 19:11:51 +02:00
parent 07dfce68f6
commit 5897e24316
17 changed files with 177 additions and 654 deletions

View File

@@ -277,11 +277,9 @@ private:
///
void handleSystemCommand(const QJsonObject &message, const JsonApiCommand& cmd);
void applyColorAdjustments(const QJsonObject &adjustment, ColorAdjustment *colorAdjustment);
void applyColorAdjustment(const QString &colorName, const QJsonObject &adjustment, RgbChannelAdjustment &rgbAdjustment);
void applyGammaTransform(const QString &transformName, const QJsonObject &adjustment, RgbTransform &rgbTransform, char channel);
void applyTemperatureAdjustment(const QJsonObject &adjustment, ColorCorrection *colorCorrection);
void applyTransforms(const QJsonObject &adjustment, ColorAdjustment *colorAdjustment);
template<typename T>
@@ -289,6 +287,8 @@ private:
template<typename T>
void applyTransform(const QString &transformName, const QJsonObject &adjustment, T &transform, void (T::*setFunction)(double));
template<typename T>
void applyTransform(const QString &transformName, const QJsonObject &adjustment, T &transform, void (T::*setFunction)(int));
template<typename T>
void applyTransform(const QString &transformName, const QJsonObject &adjustment, T &transform, void (T::*setFunction)(uint8_t));
void handleTokenRequired(const JsonApiCommand& cmd);

View File

@@ -1,18 +0,0 @@
#pragma once
// Qt includes
#include <QString>
// Utils includes
#include <utils/RgbChannelCorrection.h>
class ColorCorrection
{
public:
/// Unique identifier for this color correction
QString _id;
/// The RGB correction
RgbChannelCorrection _rgbCorrection;
};

View File

@@ -22,7 +22,6 @@
#include <hyperion/LedString.h>
#include <hyperion/PriorityMuxer.h>
#include <hyperion/ColorAdjustment.h>
#include <hyperion/ColorCorrection.h>
#include <hyperion/ComponentRegister.h>
#if defined(ENABLE_EFFECTENGINE)
@@ -184,30 +183,15 @@ 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)

View File

@@ -26,7 +26,7 @@ public:
*/
void addAdjustment(ColorAdjustment * adjustment);
void setAdjustmentForLed(const QString& id, int startLed, int endLed);
void setAdjustmentForLed(const QString& adjutmentId, int startLed, int endLed);
bool verifyAdjustments() const;
@@ -41,11 +41,11 @@ public:
///
/// Returns the pointer to the ColorAdjustment with the given id
///
/// @param id The identifier of the ColorAdjustment
/// @param adjutmentId The identifier of the ColorAdjustment
///
/// @return The ColorAdjustment with the given id (or nullptr if it does not exist)
///
ColorAdjustment* getAdjustment(const QString& id);
ColorAdjustment* getAdjustment(const QString& adjutmentId);
///
/// Performs the color adjustment from raw-color to led-color

View File

@@ -1,69 +0,0 @@
#pragma once
// STL includes
#include <vector>
// Utils includes
#include <utils/ColorRgb.h>
#include "utils/Logger.h"
// Hyperion includes
#include <hyperion/ColorCorrection.h>
///
/// 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<ColorRgb>& ledColors);
private:
/// List with Correction ids
QStringList _correctionIds;
/// List with unique ColorCorrections
std::vector<ColorCorrection*> _correction;
/// List with a pointer to the ColorCorrection for each individual led
std::vector<ColorCorrection*> _ledCorrections;
// logger instance
Logger * _log;
};

View File

@@ -1,66 +0,0 @@
#pragma once
// STL includes
#include <cstdint>
/// 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];
};

View File

@@ -3,6 +3,8 @@
// STL includes
#include <cstdint>
#include <utils/ColorRgb.h>
///
/// Color transformation to adjust the saturation and value of a RGB color value
///
@@ -23,8 +25,9 @@ public:
/// @param backlightThreshold The used lower brightness
/// @param backlightColored use color in backlight
/// @param brightnessHigh The used higher brightness
/// @param temeprature The given color temperature (in Kelvin)
///
RgbTransform(double gammaR, double gammaG, double gammaB, double backlightThreshold, bool backlightColored, uint8_t brightness, uint8_t brightnessCompensation);
RgbTransform(double gammaR, double gammaG, double gammaB, double backlightThreshold, bool backlightColored, uint8_t brightness, uint8_t brightnessCompensation, int temperature);
/// @return The current red gamma value
double getGammaR() const;
@@ -79,10 +82,10 @@ public:
///
/// @note The values are updated in place.
///
void getBrightnessComponents(uint8_t & rgb, uint8_t & cmy, uint8_t & w) const;
void getBrightnessComponents(uint8_t & rgb, uint8_t & cmy, uint8_t & white) const;
///
/// Apply the transform the the given RGB values.
/// Apply Gamma the the given RGB values.
///
/// @param red The red color component
/// @param green The green color component
@@ -90,7 +93,22 @@ public:
///
/// @note The values are updated in place.
///
void transform(uint8_t & red, uint8_t & green, uint8_t & blue);
void applyGamma(uint8_t & red, uint8_t & green, uint8_t & blue);
///
/// Apply Backlight the the given RGB values.
///
/// @param red The red color component
/// @param green The green color component
/// @param blue The blue color component
///
/// @note The values are updated in place.
///
void applyBacklight(uint8_t & red, uint8_t & green, uint8_t & blue) const;
int getTemperature() const;
void setTemperature(int temperature);
void applyTemperature(ColorRgb& color) const;
private:
///
@@ -103,8 +121,9 @@ private:
/// @param backlightColored en/disable color in backlight
/// @param brightness The used brightness
/// @param brightnessCompensation The used brightness compensation
/// @param temeprature apply the given color temperature (in Kelvin)
///
void init(double gammaR, double gammaG, double gammaB, double backlightThreshold, bool backlightColored, uint8_t brightness, uint8_t brightnessCompensation);
void init(double gammaR, double gammaG, double gammaB, double backlightThreshold, bool backlightColored, uint8_t brightness, uint8_t brightnessCompensation, int temperature);
/// (re)-initilize the color mapping
void initializeMapping(); /// The saturation gain
@@ -112,25 +131,28 @@ private:
void updateBrightnessComponents();
/// backlight variables
bool _backLightEnabled
, _backlightColored;
double _backlightThreshold
, _sumBrightnessLow;
bool _backLightEnabled;
bool _backlightColored;
double _backlightThreshold;
double _sumBrightnessLow;
/// gamma variables
double _gammaR
, _gammaG
, _gammaB;
double _gammaR;
double _gammaG;
double _gammaB;
/// The mapping from input color to output color
uint8_t _mappingR[256]
, _mappingG[256]
, _mappingB[256];
uint8_t _mappingR[256];
uint8_t _mappingG[256];
uint8_t _mappingB[256];
/// brightness variables
uint8_t _brightness
, _brightnessCompensation
, _brightness_rgb
, _brightness_cmy
, _brightness_w;
uint8_t _brightness;
uint8_t _brightnessCompensation;
uint8_t _brightness_rgb;
uint8_t _brightness_cmy;
uint8_t _brightness_w;
int _temperature;
ColorRgb _temperatureRGB;
};

View File

@@ -4,10 +4,8 @@
#include <hyperion/ColorAdjustment.h>
#include <hyperion/MultiColorAdjustment.h>
#include "hyperion/MultiColorCorrection.h"
#include <hyperion/LedString.h>
#include <QRegularExpression>
#include <utils/KelvinToRgb.h>
// fg effect
#include <hyperion/Hyperion.h>
@@ -79,8 +77,9 @@ namespace hyperion {
const double gammaR = colorConfig["gammaRed"].toDouble(1.0);
const double gammaG = colorConfig["gammaGreen"].toDouble(1.0);
const double gammaB = colorConfig["gammaBlue"].toDouble(1.0);
const int temperature = colorConfig["temperature"].toInt(6600);
return RgbTransform(gammaR, gammaG, gammaB, backlightThreshold, backlightColored, static_cast<uint8_t>(brightness), static_cast<uint8_t>(brightnessComp));
return RgbTransform(gammaR, gammaG, gammaB, backlightThreshold, backlightColored, static_cast<uint8_t>(brightness), static_cast<uint8_t>(brightnessComp), temperature);
}
static OkhsvTransform createOkhsvTransform(const QJsonObject& colorConfig)
@@ -102,32 +101,6 @@ namespace hyperion {
);
}
static 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;
}
static 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;
}
static ColorAdjustment* createColorAdjustment(const QJsonObject & adjustmentConfig)
{
const QString id = adjustmentConfig["id"].toString("default");
@@ -205,74 +178,6 @@ namespace hyperion {
return adjustment;
}
static 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);
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<ledIndexList.size(); ++i) {
if (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