Adjustment merge + new brightness settings (#359)

* add new rgbtransform

* activate rgbtransform

* integrate new transform and gamma in adjustment, disable transform

* fix brighness limit

* advance upper and lower thresholds

* start removing color transform

* adjust configs/schema

* implement json for new color adjustment

* finish hyperion-remote extension for new adjustment settings

* fix typos

* rename luminance to brightness
fix jsonapi for new adjustment

* fix some bugs in adjustments

* fix i18n

* fix gamma via json

* now brighness values goes from 0-1 with 0.5 is the default for all brighness is equal between the channels. less 0.5 all channels scaled down
to new brighness, above 0.5 if possible channel gets brighter - but brighness is not equal between the channels anymore
brighness value curve is now exponential instead of linear - this feels more natural

* hslv cleanup
This commit is contained in:
redPanther
2017-01-06 14:25:55 +01:00
committed by GitHub
parent c433504b81
commit caab8e819b
34 changed files with 645 additions and 1807 deletions

View File

@@ -18,14 +18,12 @@
#include <hyperion/Hyperion.h>
#include <hyperion/ImageProcessorFactory.h>
#include <hyperion/ImageProcessor.h>
#include <hyperion/ColorTransform.h>
#include <hyperion/ColorAdjustment.h>
// Leddevice includes
#include <leddevice/LedDevice.h>
#include <leddevice/LedDeviceFactory.h>
#include "MultiColorTransform.h"
#include "MultiColorAdjustment.h"
#include "LinearColorSmoothing.h"
@@ -56,37 +54,6 @@ ColorOrder Hyperion::createColorOrder(const QJsonObject &deviceConfig)
return stringToColorOrder(deviceConfig["colorOrder"].toString("rgb"));
}
ColorTransform * Hyperion::createColorTransform(const QJsonObject & transformConfig)
{
const std::string id = transformConfig["id"].toString("default").toStdString();
RgbChannelTransform * redTransform = createRgbChannelTransform(transformConfig["red"].toObject());
RgbChannelTransform * greenTransform = createRgbChannelTransform(transformConfig["green"].toObject());
RgbChannelTransform * blueTransform = createRgbChannelTransform(transformConfig["blue"].toObject());
HsvTransform * hsvTransform = createHsvTransform(transformConfig["hsv"].toObject());
HslTransform * hslTransform = createHslTransform(transformConfig["hsl"].toObject());
ColorTransform * transform = new ColorTransform();
transform->_id = id;
transform->_rgbRedTransform = *redTransform;
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;
}
ColorAdjustment * Hyperion::createColorAdjustment(const QJsonObject & adjustmentConfig)
{
const std::string id = adjustmentConfig["id"].toString("default").toStdString();
@@ -109,7 +76,8 @@ ColorAdjustment * Hyperion::createColorAdjustment(const QJsonObject & adjustment
RgbChannelAdjustment * cyanAdjustment = createRgbChannelAdjustment(adjustmentConfig["cyan"].toArray(),CYAN);
RgbChannelAdjustment * magentaAdjustment = createRgbChannelAdjustment(adjustmentConfig["magenta"].toArray(),MAGENTA);
RgbChannelAdjustment * yellowAdjustment = createRgbChannelAdjustment(adjustmentConfig["yellow"].toArray(),YELLOW);
RgbTransform * rgbTransform = createRgbTransform(adjustmentConfig);
ColorAdjustment * adjustment = new ColorAdjustment();
adjustment->_id = id;
adjustment->_rgbBlackAdjustment = *blackAdjustment;
@@ -120,6 +88,7 @@ ColorAdjustment * Hyperion::createColorAdjustment(const QJsonObject & adjustment
adjustment->_rgbCyanAdjustment = *cyanAdjustment;
adjustment->_rgbMagentaAdjustment = *magentaAdjustment;
adjustment->_rgbYellowAdjustment = *yellowAdjustment;
adjustment->_rgbTransform = *rgbTransform;
// Cleanup the allocated individual adjustments
delete blackAdjustment;
@@ -130,86 +99,12 @@ ColorAdjustment * Hyperion::createColorAdjustment(const QJsonObject & adjustment
delete cyanAdjustment;
delete magentaAdjustment;
delete yellowAdjustment;
delete rgbTransform;
return adjustment;
}
MultiColorTransform * Hyperion::createLedColorsTransform(const unsigned ledCnt, const QJsonObject & colorConfig)
{
// Create the result, the transforms are added to this
MultiColorTransform * transform = new MultiColorTransform(ledCnt);
Logger * log = Logger::getInstance("Core");
const QJsonValue transformConfig = colorConfig["transform"];
if (transformConfig.isNull())
{
// Old style color transformation config (just one for all leds)
ColorTransform * colorTransform = createColorTransform(colorConfig);
transform->addTransform(colorTransform);
transform->setTransformForLed(colorTransform->_id, 0, ledCnt-1);
}
else if (transformConfig.isObject())
{
ColorTransform * colorTransform = createColorTransform(transformConfig.toObject());
transform->addTransform(colorTransform);
transform->setTransformForLed(colorTransform->_id, 0, ledCnt-1);
}
else if (transformConfig.isArray())
{
const QRegExp overallExp("([0-9]+(\\-[0-9]+)?)(,[ ]*([0-9]+(\\-[0-9]+)?))*");
const QJsonArray & transformConfigArray = transformConfig.toArray();
for (signed i = 0; i < transformConfigArray.size(); ++i)
{
const QJsonObject & config = transformConfigArray[i].toObject();
ColorTransform * colorTransform = createColorTransform(config);
transform->addTransform(colorTransform);
const QString ledIndicesStr = config["leds"].toString("").trimmed();
if (ledIndicesStr.compare("*") == 0)
{
// Special case for indices '*' => all leds
transform->setTransformForLed(colorTransform->_id, 0, ledCnt-1);
Info(log, "ColorTransform '%s' => [0; %d]", colorTransform->_id.c_str(), ledCnt-1);
continue;
}
if (!overallExp.exactMatch(ledIndicesStr))
{
Error(log, "Given led indices %d not correct format: %s", i, ledIndicesStr.toStdString().c_str());
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();
transform->setTransformForLed(colorTransform->_id, startInd, endInd);
ss << startInd << "-" << endInd;
}
else
{
int index = ledIndexList[i].toInt();
transform->setTransformForLed(colorTransform->_id, index, index);
ss << index;
}
}
Info(log, "ColorTransform '%s' => [%s]", colorTransform->_id.c_str(), ss.str().c_str());
}
}
return transform;
}
MultiColorAdjustment * Hyperion::createLedColorsAdjustment(const unsigned ledCnt, const QJsonObject & colorConfig)
{
// Create the result, the transforms are added to this
@@ -285,31 +180,15 @@ MultiColorAdjustment * Hyperion::createLedColorsAdjustment(const unsigned ledCnt
return adjustment;
}
HsvTransform * Hyperion::createHsvTransform(const QJsonObject & hsvConfig)
RgbTransform* Hyperion::createRgbTransform(const QJsonObject& colorConfig)
{
const double saturationGain = hsvConfig["saturationGain"].toDouble(1.0);
const double valueGain = hsvConfig["valueGain"].toDouble(1.0);
const double brightnessMin = colorConfig["brightnessMin"].toDouble(0.0);
const double brightness = colorConfig["brightness"].toDouble(0.5);
const double gammaR = colorConfig["gammaRed"].toDouble(1.0);
const double gammaG = colorConfig["gammaGreen"].toDouble(1.0);
const double gammaB = colorConfig["gammaBlue"].toDouble(1.0);
return new HsvTransform(saturationGain, valueGain);
}
HslTransform * Hyperion::createHslTransform(const QJsonObject & hslConfig)
{
const double saturationGain = hslConfig["saturationGain"].toDouble(1.0);
const double luminanceGain = hslConfig["luminanceGain"].toDouble(1.0);
const double luminanceMinimum = hslConfig["luminanceMinimum"].toDouble(0.0);
return new HslTransform(saturationGain, luminanceGain, luminanceMinimum);
}
RgbChannelTransform* Hyperion::createRgbChannelTransform(const QJsonObject& colorConfig)
{
const double threshold = colorConfig["threshold"].toDouble(0.0);
const double gamma = colorConfig["gamma"].toDouble(1.0);
const double blacklevel = colorConfig["blacklevel"].toDouble(0.0);
const double whitelevel = colorConfig["whitelevel"].toDouble(1.0);
RgbChannelTransform* transform = new RgbChannelTransform(threshold, gamma, blacklevel, whitelevel);
RgbTransform* transform = new RgbTransform(gammaR, gammaG, gammaB, brightnessMin, brightness);
return transform;
}
@@ -575,7 +454,6 @@ Hyperion::Hyperion(const QJsonObject &qjsonConfig, const QString configFile)
: _ledString(createLedString(qjsonConfig["leds"], createColorOrder(qjsonConfig["device"].toObject())))
, _ledStringClone(createLedStringClone(qjsonConfig["leds"], createColorOrder(qjsonConfig["device"].toObject())))
, _muxer(_ledString.leds().size())
, _raw2ledTransform(createLedColorsTransform(_ledString.leds().size(), qjsonConfig["color"].toObject()))
, _raw2ledAdjustment(createLedColorsAdjustment(_ledString.leds().size(), qjsonConfig["color"].toObject()))
, _effectEngine(nullptr)
, _messageForwarder(createMessageForwarder(qjsonConfig["forwarder"].toObject()))
@@ -585,33 +463,22 @@ Hyperion::Hyperion(const QJsonObject &qjsonConfig, const QString configFile)
, _log(Logger::getInstance("Core"))
, _hwLedCount(_ledString.leds().size())
, _colorAdjustmentV4Lonly(false)
, _colorTransformV4Lonly(false)
, _sourceAutoSelectEnabled(true)
, _configHash()
, _ledGridSize(getLedLayoutGridSize(qjsonConfig["leds"]))
{
registerPriority("Off", PriorityMuxer::LOWEST_PRIORITY);
if (!_raw2ledAdjustment->verifyAdjustments())
{
throw std::runtime_error("Color adjustment incorrectly set");
}
if (!_raw2ledTransform->verifyTransforms())
{
throw std::runtime_error("Color transformation incorrectly set");
}
// set color correction activity state
const QJsonObject& color = qjsonConfig["color"].toObject();
_transformEnabled = color["transform_enable"].toBool(true);
_adjustmentEnabled = color["channelAdjustment_enable"].toBool(true);
_colorTransformV4Lonly = color["transform_v4l_only"].toBool(false);
_colorAdjustmentV4Lonly = color["channelAdjustment_v4l_only"].toBool(false);
InfoIf(!_transformEnabled , _log, "Color transformation disabled" );
InfoIf(!_adjustmentEnabled , _log, "Color adjustment disabled" );
InfoIf(_colorTransformV4Lonly , _log, "Color transformation for v4l inputs only" );
InfoIf(_colorAdjustmentV4Lonly , _log, "Color adjustment for v4l inputs only" );
// initialize the image processor factory
@@ -659,7 +526,6 @@ void Hyperion::freeObjects()
// delete components on exit of hyperion core
delete _effectEngine;
delete _device;
delete _raw2ledTransform;
delete _raw2ledAdjustment;
delete _messageForwarder;
}
@@ -805,31 +671,16 @@ void Hyperion::setImage(int priority, const Image<ColorRgb> & image, int duratio
}
}
const std::vector<std::string> & Hyperion::getTransformIds() const
{
return _raw2ledTransform->getTransformIds();
}
const std::vector<std::string> & Hyperion::getAdjustmentIds() const
{
return _raw2ledAdjustment->getAdjustmentIds();
}
ColorTransform * Hyperion::getTransform(const std::string& id)
{
return _raw2ledTransform->getTransform(id);
}
ColorAdjustment * Hyperion::getAdjustment(const std::string& id)
{
return _raw2ledAdjustment->getAdjustment(id);
}
void Hyperion::transformsUpdated()
{
update();
}
void Hyperion::adjustmentsUpdated()
{
update();
@@ -929,11 +780,7 @@ void Hyperion::update()
_ledBuffer.reserve(_hwLedCount);
_ledBuffer = priorityInfo.ledColors;
if ( _transformEnabled && (!_colorTransformV4Lonly || priorityInfo.componentId == hyperion::COMP_V4L) )
{
_raw2ledTransform->applyTransform(_ledBuffer);
}
if ( _adjustmentEnabled && (!_colorAdjustmentV4Lonly || priorityInfo.componentId == hyperion::COMP_V4L) )
if ( _adjustmentEnabled && priority < PriorityMuxer::LOWEST_PRIORITY && (!_colorAdjustmentV4Lonly || priorityInfo.componentId == hyperion::COMP_V4L) )
{
_raw2ledAdjustment->applyAdjustment(_ledBuffer);
}