common ledbuffer for color transform (#77)

* common ledbuffer for color transform

hyperion class uses a common buffer for all operations on ledColors got from muxer
all color transforms uses new ledBuffer instead of making copies of ledbuffer

other fixes:
fix compile bug in profiler
update doxygen config

* migrate logging for color transform classes

* prepare new logger in hyperion class

* implement hwledcount

* Update Hyperion.cpp

Fix off color

* remove ledscount equivalent from apa102
migrate logging in hyperion.cpp
remove unused and duuplicate colorcorrection - but same is available through tempertature

* remove colorcorrection completly
fix compile

* set colororder back to static

* in remote: using correction is the same as using temperature - correction is obsolete, command not delete atm for compat reasons
This commit is contained in:
redPanther
2016-07-01 23:20:41 +02:00
committed by brindosch
parent 9101d7f604
commit 36b4d072c5
16 changed files with 1728 additions and 1017 deletions

View File

@@ -2,6 +2,7 @@
// STL includes
#include <cassert>
#include <exception>
#include <sstream>
// QT includes
#include <QDateTime>
@@ -53,41 +54,29 @@ Hyperion* Hyperion::getInstance()
ColorOrder Hyperion::createColorOrder(const Json::Value &deviceConfig)
{
// deprecated: force BGR when the deprecated flag is present and set to true
if (deviceConfig.get("bgr-output", false).asBool())
{
return ORDER_BGR;
}
std::string order = deviceConfig.get("colorOrder", "rgb").asString();
if (order == "rgb")
{
return ORDER_RGB;
}
else if (order == "bgr")
if (order == "bgr")
{
return ORDER_BGR;
}
else if (order == "rbg")
if (order == "rbg")
{
return ORDER_RBG;
}
else if (order == "brg")
if (order == "brg")
{
return ORDER_BRG;
}
else if (order == "gbr")
if (order == "gbr")
{
return ORDER_GBR;
}
else if (order == "grb")
if (order == "grb")
{
return ORDER_GRB;
}
else
{
std::cout << "HYPERION ERROR: Unknown color order defined (" << order << "). Using RGB." << std::endl;
}
WarningIf( order != "rgb", Logger::getInstance("Core"), "Unknown color order defined (%s). Using RGB.", order.c_str());
return ORDER_RGB;
}
@@ -167,6 +156,7 @@ MultiColorTransform * Hyperion::createLedColorsTransform(const unsigned ledCnt,
{
// Create the result, the transforms are added to this
MultiColorTransform * transform = new MultiColorTransform(ledCnt);
Logger * log = Logger::getInstance("Core");
const Json::Value transformConfig = colorConfig.get("transform", Json::nullValue);
if (transformConfig.isNull())
@@ -197,18 +187,17 @@ MultiColorTransform * Hyperion::createLedColorsTransform(const unsigned ledCnt,
{
// Special case for indices '*' => all leds
transform->setTransformForLed(colorTransform->_id, 0, ledCnt-1);
std::cout << "HYPERION INFO: ColorTransform '" << colorTransform->_id << "' => [0; "<< ledCnt-1 << "]" << std::endl;
Info(log, "ColorTransform '%s' => [0; %d]", colorTransform->_id.c_str(), ledCnt-1);
continue;
}
if (!overallExp.exactMatch(ledIndicesStr))
{
std::cerr << "HYPERION ERROR: Given led indices " << i << " not correct format: " << ledIndicesStr.toStdString() << std::endl;
Error(log, "Given led indices %d not correct format: %s", i, ledIndicesStr.toStdString().c_str());
continue;
}
std::cout << "HYPERION INFO: ColorTransform '" << colorTransform->_id << "' => [";
std::stringstream ss;
const QStringList ledIndexList = ledIndicesStr.split(",");
for (int i=0; i<ledIndexList.size(); ++i) {
if (i > 0)
@@ -231,92 +220,20 @@ MultiColorTransform * Hyperion::createLedColorsTransform(const unsigned ledCnt,
std::cout << index;
}
}
std::cout << "]" << std::endl;
Info(log, "ColorTransform '%s' => [%s]", colorTransform->_id.c_str(), ss.str().c_str());
}
}
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(correctionConfig);
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 << "HYPERION INFO: ColorCorrection '" << colorCorrection->_id << "' => [0; "<< ledCnt-1 << "]" << std::endl;
continue;
}
if (!overallExp.exactMatch(ledIndicesStr))
{
std::cerr << "HYPERION ERROR: Given led indices " << i << " not correct format: " << ledIndicesStr.toStdString() << std::endl;
continue;
}
std::cout << "HYPERION INFO: ColorCorrection '" << colorCorrection->_id << "' => [";
const QStringList ledIndexList = ledIndicesStr.split(",");
for (int i=0; i<ledIndexList.size(); ++i) {
if (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);
Logger * log = Logger::getInstance("Core");
const Json::Value correctionConfig = colorConfig.get("temperature", Json::nullValue);
const std::string jsonKey = colorConfig.isMember("temperature") ? "temperature" : "correction";
const Json::Value correctionConfig = colorConfig.get(jsonKey, Json::nullValue);
if (correctionConfig.isNull())
{
// Old style color correction config (just one for all leds)
@@ -345,23 +262,22 @@ MultiColorCorrection * Hyperion::createLedColorsTemperature(const unsigned ledCn
{
// Special case for indices '*' => all leds
correction->setCorrectionForLed(colorCorrection->_id, 0, ledCnt-1);
std::cout << "HYPERION INFO: ColorCorrection '" << colorCorrection->_id << "' => [0; "<< ledCnt-1 << "]" << std::endl;
Info(log, "ColorTemperature '%s' => [0; %d]", colorCorrection->_id.c_str(), ledCnt-1);
continue;
}
if (!overallExp.exactMatch(ledIndicesStr))
{
std::cerr << "HYPERION ERROR: Given led indices " << i << " not correct format: " << ledIndicesStr.toStdString() << std::endl;
Error(log, "Given led indices %d not correct format: %s", i, ledIndicesStr.toStdString().c_str());
continue;
}
std::cout << "HYPERION INFO: ColorCorrection '" << colorCorrection->_id << "' => [";
std::stringstream ss;
const QStringList ledIndexList = ledIndicesStr.split(",");
for (int i=0; i<ledIndexList.size(); ++i) {
if (i > 0)
{
std::cout << ", ";
ss << ", ";
}
if (ledIndexList[i].contains("-"))
{
@@ -370,25 +286,27 @@ MultiColorCorrection * Hyperion::createLedColorsTemperature(const unsigned ledCn
int endInd = ledIndices[1].toInt();
correction->setCorrectionForLed(colorCorrection->_id, startInd, endInd);
std::cout << startInd << "-" << endInd;
ss << startInd << "-" << endInd;
}
else
{
int index = ledIndexList[i].toInt();
correction->setCorrectionForLed(colorCorrection->_id, index, index);
std::cout << index;
ss << index;
}
}
std::cout << "]" << std::endl;
Info(log, "ColorTemperature '%s' => [%s]", colorCorrection->_id.c_str(), ss.str().c_str());
}
}
return correction;
}
MultiColorAdjustment * Hyperion::createLedColorsAdjustment(const unsigned ledCnt, const Json::Value & colorConfig)
{
// Create the result, the transforms are added to this
MultiColorAdjustment * adjustment = new MultiColorAdjustment(ledCnt);
Logger * log = Logger::getInstance("Core");
const Json::Value adjustmentConfig = colorConfig.get("channelAdjustment", Json::nullValue);
if (adjustmentConfig.isNull())
@@ -419,23 +337,22 @@ MultiColorAdjustment * Hyperion::createLedColorsAdjustment(const unsigned ledCnt
{
// Special case for indices '*' => all leds
adjustment->setAdjustmentForLed(colorAdjustment->_id, 0, ledCnt-1);
std::cout << "HYPERION INFO: ColorAdjustment '" << colorAdjustment->_id << "' => [0; "<< ledCnt-1 << "]" << std::endl;
Info(log, "ColorAdjustment '%s' => [0; %d]", colorAdjustment->_id.c_str(), ledCnt-1);
continue;
}
if (!overallExp.exactMatch(ledIndicesStr))
{
std::cerr << "HYPERION ERROR: Given led indices " << i << " not correct format: " << ledIndicesStr.toStdString() << std::endl;
Error(log, "Given led indices %d not correct format: %s", i, ledIndicesStr.toStdString().c_str());
continue;
}
std::cout << "HYPERION INFO: ColorAdjustment '" << colorAdjustment->_id << "' => [";
std::stringstream ss;
const QStringList ledIndexList = ledIndicesStr.split(",");
for (int i=0; i<ledIndexList.size(); ++i) {
if (i > 0)
{
std::cout << ", ";
ss << ", ";
}
if (ledIndexList[i].contains("-"))
{
@@ -444,16 +361,16 @@ MultiColorAdjustment * Hyperion::createLedColorsAdjustment(const unsigned ledCnt
int endInd = ledIndices[1].toInt();
adjustment->setAdjustmentForLed(colorAdjustment->_id, startInd, endInd);
std::cout << startInd << "-" << endInd;
ss << startInd << "-" << endInd;
}
else
{
int index = ledIndexList[i].toInt();
adjustment->setAdjustmentForLed(colorAdjustment->_id, index, index);
std::cout << index;
ss << index;
}
}
std::cout << "]" << std::endl;
Info(log, "ColorAdjustment '%s' => [%s]", colorAdjustment->_id.c_str(), ss.str().c_str());
}
}
return adjustment;
@@ -611,7 +528,7 @@ MessageForwarder * Hyperion::createMessageForwarder(const Json::Value & forwarde
{
for (const Json::Value& addr : forwarderConfig["json"])
{
std::cout << "HYPERION INFO: Json forward to " << addr.asString() << std::endl;
Info(Logger::getInstance("Core"), "Json forward to %s", addr.asString().c_str());
forwarder->addJsonSlave(addr.asString());
}
}
@@ -620,7 +537,7 @@ MessageForwarder * Hyperion::createMessageForwarder(const Json::Value & forwarde
{
for (const Json::Value& addr : forwarderConfig["proto"])
{
std::cout << "HYPERION INFO: Proto forward to " << addr.asString() << std::endl;
Info(Logger::getInstance("Core"), "Proto forward to %s", addr.asString().c_str());
forwarder->addProtoSlave(addr.asString());
}
}
@@ -638,7 +555,6 @@ Hyperion::Hyperion(const Json::Value &jsonConfig, const std::string configFile)
_ledString(createLedString(jsonConfig["leds"], createColorOrder(jsonConfig["device"]))),
_muxer(_ledString.leds().size()),
_raw2ledTransform(createLedColorsTransform(_ledString.leds().size(), jsonConfig["color"])),
_raw2ledCorrection(createLedColorsCorrection(_ledString.leds().size(), jsonConfig["color"])),
_raw2ledTemperature(createLedColorsTemperature(_ledString.leds().size(), jsonConfig["color"])),
_raw2ledAdjustment(createLedColorsAdjustment(_ledString.leds().size(), jsonConfig["color"])),
_device(LedDeviceFactory::construct(jsonConfig["device"])),
@@ -646,16 +562,14 @@ Hyperion::Hyperion(const Json::Value &jsonConfig, const std::string configFile)
_messageForwarder(createMessageForwarder(jsonConfig["forwarder"])),
_jsonConfig(jsonConfig),
_configFile(configFile),
_timer()
_timer(),
_log(Logger::getInstance("Core")),
_hwLedCount(_ledString.leds().size())
{
if (!_raw2ledAdjustment->verifyAdjustments())
{
throw std::runtime_error("HYPERION ERROR: Color adjustment incorrectly set");
}
if (!_raw2ledCorrection->verifyCorrections())
{
throw std::runtime_error("HYPERION ERROR: Color correction incorrectly set");
}
if (!_raw2ledTemperature->verifyCorrections())
{
throw std::runtime_error("HYPERION ERROR: Color temperature incorrectly set");
@@ -679,6 +593,11 @@ Hyperion::Hyperion(const Json::Value &jsonConfig, const std::string configFile)
// create the effect engine
_effectEngine = new EffectEngine(this, jsonConfig["effects"]);
unsigned int hwLedCount = jsonConfig["device"].get("ledCount",getLedCount()).asUInt();
_hwLedCount = std::max(hwLedCount, getLedCount());
Debug(_log,"configured leds: %d hw leds: %d", getLedCount(), _hwLedCount);
WarningIf(hwLedCount < getLedCount(), _log, "more leds configured than available. check 'ledCount' in 'device' section");
// initialize the leds
update();
@@ -691,25 +610,12 @@ Hyperion::~Hyperion()
clearall();
_device->switchOff();
// delete the effect engine
// delete components on exit of hyperion core
delete _effectEngine;
// Delete the Led-String
delete _device;
// delete the color transform
delete _raw2ledTransform;
// delete the color correction
delete _raw2ledCorrection;
// delete the color temperature correction
delete _raw2ledTemperature;
// delete the color adjustment
delete _raw2ledAdjustment;
// delete the message forwarder
delete _messageForwarder;
}
@@ -756,11 +662,6 @@ const std::vector<std::string> & Hyperion::getTransformIds() const
return _raw2ledTransform->getTransformIds();
}
const std::vector<std::string> & Hyperion::getCorrectionIds() const
{
return _raw2ledCorrection->getCorrectionIds();
}
const std::vector<std::string> & Hyperion::getTemperatureIds() const
{
return _raw2ledTemperature->getCorrectionIds();
@@ -776,11 +677,6 @@ ColorTransform * Hyperion::getTransform(const std::string& id)
return _raw2ledTransform->getTransform(id);
}
ColorCorrection * Hyperion::getCorrection(const std::string& id)
{
return _raw2ledCorrection->getCorrection(id);
}
ColorCorrection * Hyperion::getTemperature(const std::string& id)
{
return _raw2ledTemperature->getCorrection(id);
@@ -884,15 +780,20 @@ void Hyperion::update()
int priority = _muxer.getCurrentPriority();
const PriorityMuxer::InputInfo & priorityInfo = _muxer.getInputInfo(priority);
// copy ledcolors to local buffer
_ledBuffer.reserve(_hwLedCount);
_ledBuffer = priorityInfo.ledColors;
// Apply the correction and the transform to each led and color-channel
// Avoid applying correction, the same task is performed by adjustment
// std::vector<ColorRgb> correctedColors = _raw2ledCorrection->applyCorrection(priorityInfo.ledColors);
std::vector<ColorRgb> transformColors =_raw2ledTransform->applyTransform(priorityInfo.ledColors);
std::vector<ColorRgb> adjustedColors = _raw2ledAdjustment->applyAdjustment(transformColors);
std::vector<ColorRgb> ledColors = _raw2ledTemperature->applyCorrection(adjustedColors);
_raw2ledTransform->applyTransform(_ledBuffer);
_raw2ledAdjustment->applyAdjustment(_ledBuffer);
_raw2ledTemperature->applyCorrection(_ledBuffer);
const std::vector<Led>& leds = _ledString.leds();
int i = 0;
for (ColorRgb& color : ledColors)
for (ColorRgb& color : _ledBuffer)
{
const ColorOrder ledColorOrder = leds.at(i).colorOrder;
// correct the color byte order
@@ -926,8 +827,13 @@ void Hyperion::update()
i++;
}
if ( _hwLedCount > _ledBuffer.size() )
{
_ledBuffer.resize(_hwLedCount, ColorRgb::BLACK);
}
// Write the data to the device
_device->write(ledColors);
_device->write(_ledBuffer);
// Start the timeout-timer
if (priorityInfo.timeoutTime_ms == -1)

View File

@@ -3,10 +3,11 @@
#include <cassert>
// Hyperion includes
#include <utils/Logger.h>
#include "MultiColorAdjustment.h"
MultiColorAdjustment::MultiColorAdjustment(const unsigned ledCnt) :
_ledAdjustments(ledCnt, nullptr)
MultiColorAdjustment::MultiColorAdjustment(const unsigned ledCnt)
: _ledAdjustments(ledCnt, nullptr)
{
}
@@ -40,16 +41,15 @@ void MultiColorAdjustment::setAdjustmentForLed(const std::string& id, const unsi
bool MultiColorAdjustment::verifyAdjustments() const
{
bool allLedsSet = true;
for (unsigned iLed=0; iLed<_ledAdjustments.size(); ++iLed)
{
if (_ledAdjustments[iLed] == nullptr)
{
std::cerr << "HYPERION (C.adjustment) ERROR: No adjustment set for " << iLed << std::endl;
allLedsSet = false;
Warning(Logger::getInstance("ColorAdjust"), "No adjustment set for %d", iLed);
return false;
}
}
return allLedsSet;
return true;
}
const std::vector<std::string> & MultiColorAdjustment::getAdjustmentIds()
@@ -72,12 +72,9 @@ ColorAdjustment* MultiColorAdjustment::getAdjustment(const std::string& id)
return nullptr;
}
std::vector<ColorRgb> MultiColorAdjustment::applyAdjustment(const std::vector<ColorRgb>& rawColors)
void MultiColorAdjustment::applyAdjustment(std::vector<ColorRgb>& ledColors)
{
// Create a copy, as we will do the rest of the adjustment in place
std::vector<ColorRgb> ledColors(rawColors);
const size_t itCnt = std::min(_ledAdjustments.size(), rawColors.size());
const size_t itCnt = std::min(_ledAdjustments.size(), ledColors.size());
for (size_t i=0; i<itCnt; ++i)
{
ColorAdjustment* adjustment = _ledAdjustments[i];
@@ -122,5 +119,4 @@ std::vector<ColorRgb> MultiColorAdjustment::applyAdjustment(const std::vector<Co
else
color.blue = (uint8_t)ledB;
}
return ledColors;
}

View File

@@ -48,11 +48,9 @@ public:
///
/// Performs the color adjustment from raw-color to led-color
///
/// @param rawColors The list with raw colors
/// @param ledColors The list with raw colors
///
/// @return The list with led-colors
///
std::vector<ColorRgb> applyAdjustment(const std::vector<ColorRgb>& rawColors);
void applyAdjustment(std::vector<ColorRgb>& ledColors);
private:
/// List with transform ids

View File

@@ -3,6 +3,7 @@
#include <cassert>
// Hyperion includes
#include <utils/Logger.h>
#include "MultiColorCorrection.h"
MultiColorCorrection::MultiColorCorrection(const unsigned ledCnt) :
@@ -40,16 +41,15 @@ void MultiColorCorrection::setCorrectionForLed(const std::string& id, const unsi
bool MultiColorCorrection::verifyCorrections() const
{
bool allLedsSet = true;
for (unsigned iLed=0; iLed<_ledCorrections.size(); ++iLed)
{
if (_ledCorrections[iLed] == nullptr)
{
std::cerr << "HYPERION (C.correction) ERROR: No correction set for " << iLed << std::endl;
allLedsSet = false;
Warning(Logger::getInstance("ColorCorrect"), "No adjustment set for %d", iLed);
return false;
}
}
return allLedsSet;
return true;
}
const std::vector<std::string> & MultiColorCorrection::getCorrectionIds()
@@ -72,12 +72,9 @@ ColorCorrection* MultiColorCorrection::getCorrection(const std::string& id)
return nullptr;
}
std::vector<ColorRgb> MultiColorCorrection::applyCorrection(const std::vector<ColorRgb>& rawColors)
void MultiColorCorrection::applyCorrection(std::vector<ColorRgb>& ledColors)
{
// Create a copy, as we will do the rest of the correction in place
std::vector<ColorRgb> ledColors(rawColors);
const size_t itCnt = std::min(_ledCorrections.size(), rawColors.size());
const size_t itCnt = std::min(_ledCorrections.size(), ledColors.size());
for (size_t i=0; i<itCnt; ++i)
{
ColorCorrection * correction = _ledCorrections[i];
@@ -92,5 +89,4 @@ std::vector<ColorRgb> MultiColorCorrection::applyCorrection(const std::vector<Co
color.green = correction->_rgbCorrection.correctionG(color.green);
color.blue = correction->_rgbCorrection.correctionB(color.blue);
}
return ledColors;
}

View File

@@ -48,11 +48,9 @@ public:
///
/// Performs the color transoformation from raw-color to led-color
///
/// @param rawColors The list with raw colors
/// @param ledColors The list with led colors
///
/// @return The list with led-colors
///
std::vector<ColorRgb> applyCorrection(const std::vector<ColorRgb>& rawColors);
void applyCorrection(std::vector<ColorRgb>& ledColors);
private:
/// List with Correction ids

View File

@@ -3,6 +3,7 @@
#include <cassert>
// Hyperion includes
#include <utils/Logger.h>
#include "MultiColorTransform.h"
MultiColorTransform::MultiColorTransform(const unsigned ledCnt) :
@@ -40,16 +41,15 @@ void MultiColorTransform::setTransformForLed(const std::string& id, const unsign
bool MultiColorTransform::verifyTransforms() const
{
bool allLedsSet = true;
for (unsigned iLed=0; iLed<_ledTransforms.size(); ++iLed)
{
if (_ledTransforms[iLed] == nullptr)
{
std::cerr << "HYPERION (C.transform) ERROR: No transform set for " << iLed << std::endl;
allLedsSet = false;
Warning(Logger::getInstance("ColorTransform"), "No adjustment set for %d", iLed);
return false;
}
}
return allLedsSet;
return true;
}
const std::vector<std::string> & MultiColorTransform::getTransformIds()
@@ -72,12 +72,9 @@ ColorTransform* MultiColorTransform::getTransform(const std::string& id)
return nullptr;
}
std::vector<ColorRgb> MultiColorTransform::applyTransform(const std::vector<ColorRgb>& rawColors)
void MultiColorTransform::applyTransform(std::vector<ColorRgb>& ledColors)
{
// Create a copy, as we will do the rest of the transformation in place
std::vector<ColorRgb> ledColors(rawColors);
const size_t itCnt = std::min(_ledTransforms.size(), rawColors.size());
const size_t itCnt = std::min(_ledTransforms.size(), ledColors.size());
for (size_t i=0; i<itCnt; ++i)
{
ColorTransform* transform = _ledTransforms[i];
@@ -94,5 +91,4 @@ std::vector<ColorRgb> MultiColorTransform::applyTransform(const std::vector<Colo
color.green = transform->_rgbGreenTransform.transform(color.green);
color.blue = transform->_rgbBlueTransform.transform(color.blue);
}
return ledColors;
}

View File

@@ -48,11 +48,9 @@ public:
///
/// Performs the color transoformation from raw-color to led-color
///
/// @param rawColors The list with raw colors
/// @param ledColors The list with raw colors
///
/// @return The list with led-colors
///
std::vector<ColorRgb> applyTransform(const std::vector<ColorRgb>& rawColors);
void applyTransform(std::vector<ColorRgb>& ledColors);
private:
/// List with transform ids