mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2025-03-01 10:33:28 +00:00
Re-add Temperture adjustment (#1710)
* Add Temperature adjustment * Add Temperature adjustment - add missing cmake updates * Add missing ENABLE_MDNS guards * Reapply temperature on JSONAPI * Integrate color temperature into RGB transformations * Fix imagestream update * fix cast * Cleanups * Windows Fix * Fix inner loop * Simplify * Reapply default temperature setting * Fix adjustments calculation * Updates
This commit is contained in:
@@ -285,7 +285,6 @@ 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);
|
||||
@@ -296,6 +295,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);
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#ifndef COLORADJUSTMENT_H
|
||||
#define COLORADJUSTMENT_H
|
||||
|
||||
// STL includes
|
||||
// Qt includes
|
||||
#include <QString>
|
||||
|
||||
// Utils includes
|
||||
|
@@ -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
|
||||
|
@@ -33,6 +33,10 @@ struct ColorRgb
|
||||
static const ColorRgb YELLOW;
|
||||
/// 'White' RgbColor (255, 255, 255)
|
||||
static const ColorRgb WHITE;
|
||||
/// 'Cyan' RgbColor (0, 255, 255)
|
||||
static const ColorRgb CYAN;
|
||||
/// 'Magenta' RgbColor (255, 0,255)
|
||||
static const ColorRgb MAGENTA;
|
||||
|
||||
ColorRgb() = default;
|
||||
|
||||
|
75
include/utils/KelvinToRgb.h
Normal file
75
include/utils/KelvinToRgb.h
Normal file
@@ -0,0 +1,75 @@
|
||||
#ifndef KELVINTORGB_H
|
||||
#define KELVINTORGB_H
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <utils/ColorRgb.h>
|
||||
|
||||
// Constants
|
||||
namespace ColorTemperature {
|
||||
constexpr int MINIMUM {1000};
|
||||
constexpr int MAXIMUM {40000};
|
||||
constexpr int DEFAULT {6600};
|
||||
}
|
||||
//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(ColorTemperature::MINIMUM, temperature, ColorTemperature::MAXIMUM);
|
||||
|
||||
// All calculations require temperature / 100, so only do the conversion once.
|
||||
temperature /= 100;
|
||||
|
||||
// Compute each color in turn.
|
||||
int red;
|
||||
int green;
|
||||
int blue;
|
||||
|
||||
// red
|
||||
if (temperature <= 66)
|
||||
{
|
||||
red = UINT8_MAX;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Note: the R-squared value for this approximation is 0.988.
|
||||
red = static_cast<int>(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<int>(99.4708025861 * log(temperature) - 161.1195681661);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// Note: the R-squared value for this approximation is 0.987.
|
||||
green = static_cast<int>(288.1221695283 * (pow(temperature - 60, -0.0755148492)));
|
||||
}
|
||||
|
||||
// blue
|
||||
if (temperature >= 66)
|
||||
{
|
||||
blue = UINT8_MAX;
|
||||
}
|
||||
else if (temperature <= 19)
|
||||
{
|
||||
blue = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Note: the R-squared value for this approximation is 0.998.
|
||||
blue = static_cast<int>(138.5177312231 * log(temperature - 10) - 305.0447927307);
|
||||
}
|
||||
|
||||
return {
|
||||
static_cast<uint8_t>(qBound(0, red, static_cast<int>(UINT8_MAX))),
|
||||
static_cast<uint8_t>(qBound(0, green, static_cast<int>(UINT8_MAX))),
|
||||
static_cast<uint8_t>(qBound(0, blue, static_cast<int>(UINT8_MAX))),
|
||||
};
|
||||
}
|
||||
|
||||
#endif // KELVINTORGB_H
|
@@ -1,23 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
// STL includes
|
||||
#include <cstdint>
|
||||
|
||||
#include <QString>
|
||||
#include <utils/Logger.h>
|
||||
#include <utils/ColorRgb.h>
|
||||
|
||||
/// 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(QString channelName="");
|
||||
explicit RgbChannelAdjustment(const QString& channelName="");
|
||||
|
||||
explicit RgbChannelAdjustment(const ColorRgb& adjust, const QString& channelName="");
|
||||
|
||||
/// Constructor
|
||||
/// @param adjustR
|
||||
/// @param adjustG
|
||||
/// @param adjustB
|
||||
RgbChannelAdjustment(uint8_t adjustR, uint8_t adjustG, uint8_t adjustB, QString channelName="");
|
||||
explicit RgbChannelAdjustment(uint8_t adjustR, uint8_t adjustG, uint8_t adjustB, const QString& channelName="");
|
||||
|
||||
///
|
||||
/// Transform the given array value
|
||||
@@ -40,6 +44,7 @@ public:
|
||||
/// @param adjustB
|
||||
///
|
||||
void setAdjustment(uint8_t adjustR, uint8_t adjustG, uint8_t adjustB);
|
||||
void setAdjustment(const ColorRgb& adjust);
|
||||
|
||||
/// @return The current adjustR value
|
||||
uint8_t getAdjustmentR() const;
|
||||
@@ -51,24 +56,28 @@ public:
|
||||
uint8_t getAdjustmentB() const;
|
||||
|
||||
private:
|
||||
/// color channels
|
||||
enum ColorChannel { RED=0, GREEN=1, BLUE=2 };
|
||||
|
||||
struct ColorMapping {
|
||||
uint8_t red[256];
|
||||
uint8_t green[256];
|
||||
uint8_t blue[256];
|
||||
};
|
||||
|
||||
/// reset init of color mapping
|
||||
void resetInitialized();
|
||||
|
||||
/// The adjustment of RGB channel
|
||||
uint8_t _adjust[3];
|
||||
|
||||
/// The mapping from input color to output color
|
||||
uint8_t _mapping[3][256];
|
||||
|
||||
/// Name of this channel, usefull for debug messages
|
||||
QString _channelName;
|
||||
|
||||
/// Logger instance
|
||||
Logger * _log;
|
||||
|
||||
/// The adjustment of RGB channel
|
||||
ColorRgb _adjust;
|
||||
|
||||
/// The mapping from input color to output color
|
||||
ColorMapping _mapping;
|
||||
|
||||
/// bitfield to determine white value is alreade initialized
|
||||
bool _initialized[256];
|
||||
|
||||
|
@@ -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;
|
||||
};
|
||||
|
@@ -1,6 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <QList>
|
||||
|
||||
#define QSTRING_CSTR(str) str.toUtf8().constData()
|
||||
typedef QList< int > QIntList;
|
||||
|
||||
|
||||
constexpr double DOUBLE_UINT8_MAX_SQUARED = static_cast<double>(UINT8_MAX) * UINT8_MAX;
|
||||
|
@@ -5,6 +5,7 @@
|
||||
#include <hyperion/ColorAdjustment.h>
|
||||
#include <hyperion/MultiColorAdjustment.h>
|
||||
#include <hyperion/LedString.h>
|
||||
#include <utils/KelvinToRgb.h>
|
||||
#include <QRegularExpression>
|
||||
|
||||
// fg effect
|
||||
@@ -77,8 +78,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(ColorTemperature::DEFAULT);
|
||||
|
||||
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)
|
||||
@@ -89,13 +91,13 @@ namespace hyperion {
|
||||
return OkhsvTransform(saturationGain, brightnessGain);
|
||||
}
|
||||
|
||||
static RgbChannelAdjustment createRgbChannelAdjustment(const QJsonObject& colorConfig, const QString& channelName, int defaultR, int defaultG, int defaultB)
|
||||
static RgbChannelAdjustment createRgbChannelAdjustment(const QJsonObject& colorConfig, const QString& channelName, const ColorRgb& color)
|
||||
{
|
||||
const QJsonArray& channelConfig = colorConfig[channelName].toArray();
|
||||
return RgbChannelAdjustment(
|
||||
static_cast<uint8_t>(channelConfig[0].toInt(defaultR)),
|
||||
static_cast<uint8_t>(channelConfig[1].toInt(defaultG)),
|
||||
static_cast<uint8_t>(channelConfig[2].toInt(defaultB)),
|
||||
static_cast<uint8_t>(channelConfig[0].toInt(color.red)),
|
||||
static_cast<uint8_t>(channelConfig[1].toInt(color.green)),
|
||||
static_cast<uint8_t>(channelConfig[2].toInt(color.blue)),
|
||||
channelName
|
||||
);
|
||||
}
|
||||
@@ -106,14 +108,14 @@ namespace hyperion {
|
||||
|
||||
ColorAdjustment * adjustment = new ColorAdjustment();
|
||||
adjustment->_id = id;
|
||||
adjustment->_rgbBlackAdjustment = createRgbChannelAdjustment(adjustmentConfig, "black" , 0, 0, 0);
|
||||
adjustment->_rgbWhiteAdjustment = createRgbChannelAdjustment(adjustmentConfig, "white" , 255,255,255);
|
||||
adjustment->_rgbRedAdjustment = createRgbChannelAdjustment(adjustmentConfig, "red" , 255, 0, 0);
|
||||
adjustment->_rgbGreenAdjustment = createRgbChannelAdjustment(adjustmentConfig, "green" , 0,255, 0);
|
||||
adjustment->_rgbBlueAdjustment = createRgbChannelAdjustment(adjustmentConfig, "blue" , 0, 0,255);
|
||||
adjustment->_rgbCyanAdjustment = createRgbChannelAdjustment(adjustmentConfig, "cyan" , 0,255,255);
|
||||
adjustment->_rgbMagentaAdjustment = createRgbChannelAdjustment(adjustmentConfig, "magenta", 255, 0,255);
|
||||
adjustment->_rgbYellowAdjustment = createRgbChannelAdjustment(adjustmentConfig, "yellow" , 255,255, 0);
|
||||
adjustment->_rgbBlackAdjustment = createRgbChannelAdjustment(adjustmentConfig, "black" , ColorRgb::BLACK);
|
||||
adjustment->_rgbWhiteAdjustment = createRgbChannelAdjustment(adjustmentConfig, "white" , ColorRgb::WHITE);
|
||||
adjustment->_rgbRedAdjustment = createRgbChannelAdjustment(adjustmentConfig, "red" , ColorRgb::RED);
|
||||
adjustment->_rgbGreenAdjustment = createRgbChannelAdjustment(adjustmentConfig, "green" , ColorRgb::GREEN);
|
||||
adjustment->_rgbBlueAdjustment = createRgbChannelAdjustment(adjustmentConfig, "blue" , ColorRgb::BLUE);
|
||||
adjustment->_rgbCyanAdjustment = createRgbChannelAdjustment(adjustmentConfig, "cyan" , ColorRgb::CYAN);
|
||||
adjustment->_rgbMagentaAdjustment = createRgbChannelAdjustment(adjustmentConfig, "magenta", ColorRgb::MAGENTA);
|
||||
adjustment->_rgbYellowAdjustment = createRgbChannelAdjustment(adjustmentConfig, "yellow" , ColorRgb::YELLOW);
|
||||
adjustment->_rgbTransform = createRgbTransform(adjustmentConfig);
|
||||
adjustment->_okhsvTransform = createOkhsvTransform(adjustmentConfig);
|
||||
|
||||
@@ -149,27 +151,27 @@ namespace hyperion {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
std::stringstream sStream;
|
||||
const QStringList ledIndexList = ledIndicesStr.split(",");
|
||||
for (int i=0; i<ledIndexList.size(); ++i) {
|
||||
if (i > 0)
|
||||
for (int j=0; j<ledIndexList.size(); ++j) {
|
||||
if (j > 0)
|
||||
{
|
||||
ss << ", ";
|
||||
sStream << ", ";
|
||||
}
|
||||
if (ledIndexList[i].contains("-"))
|
||||
if (ledIndexList[j].contains("-"))
|
||||
{
|
||||
QStringList ledIndices = ledIndexList[i].split("-");
|
||||
QStringList ledIndices = ledIndexList[j].split("-");
|
||||
int startInd = ledIndices[0].toInt();
|
||||
int endInd = ledIndices[1].toInt();
|
||||
|
||||
adjustment->setAdjustmentForLed(colorAdjustment->_id, startInd, endInd);
|
||||
ss << startInd << "-" << endInd;
|
||||
sStream << startInd << "-" << endInd;
|
||||
}
|
||||
else
|
||||
{
|
||||
int index = ledIndexList[i].toInt();
|
||||
adjustment->setAdjustmentForLed(colorAdjustment->_id, index, index);
|
||||
ss << index;
|
||||
sStream << index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user