Implemented the multi-color transform including in hyperion-remote

Former-commit-id: ebdb0688b47d51bd6dccf6dafd580d3ce9ed80a7
This commit is contained in:
T. van der Zwan
2013-11-22 10:48:10 +00:00
parent 958feabf5b
commit 826b964bf6
12 changed files with 357 additions and 330 deletions

View File

@@ -77,6 +77,7 @@ add_library(hyperion
${Hyperion_SOURCES}
${Hyperion_RESOURCES_RCC}
)
message("{QT_LIBRARIES} = ${QT_LIBRARIES}")
target_link_libraries(hyperion
hyperion-utils

View File

@@ -4,6 +4,9 @@
// QT includes
#include <QDateTime>
#include <QRegExp>
#include <QString>
#include <QStringList>
// JsonSchema include
#include <utils/jsonschema/JsonFactory.h>
@@ -153,29 +156,94 @@ Hyperion::ColorOrder Hyperion::createColorOrder(const Json::Value &deviceConfig)
return ORDER_RGB;
}
ColorTransform * Hyperion::createColorTransform(const Json::Value & transformConfig)
{
const std::string id = transformConfig.get("id", "default").asString();
RgbChannelTransform * redTransform = createRgbChannelTransform(transformConfig["red"]);
RgbChannelTransform * greenTransform = createRgbChannelTransform(transformConfig["green"]);
RgbChannelTransform * blueTransform = createRgbChannelTransform(transformConfig["blue"]);
HsvTransform * hsvTransform = createHsvTransform(transformConfig["hsv"]);
ColorTransform * transform = new ColorTransform();
transform->_id = id;
transform->_rgbRedTransform = *redTransform;
transform->_rgbGreenTransform = *greenTransform;
transform->_rgbBlueTransform = *blueTransform;
transform->_hsvTransform = *hsvTransform;
// Cleanup the allocated individual transforms
delete redTransform;
delete greenTransform;
delete blueTransform;
delete hsvTransform;
return transform;
}
MultiColorTransform * Hyperion::createLedColorsTransform(const unsigned ledCnt, const Json::Value & colorConfig)
{
MultiColorTransform * transform = new MultiColorTransform();
if (!colorConfig.isArray())
// Create the result, the transforms are added to this
MultiColorTransform * transform = new MultiColorTransform(ledCnt);
const Json::Value transformConfig = colorConfig.get("transform", Json::nullValue);
if (transformConfig.isNull())
{
// Old style color transformation config (just one for all leds)
const std::string id = "default";
RgbChannelTransform * redTransform = createColorTransform(colorConfig["red"]);
RgbChannelTransform * greenTransform = createColorTransform(colorConfig["green"]);
RgbChannelTransform * blueTransform = createColorTransform(colorConfig["blue"]);
HsvTransform * hsvTransform = createHsvTransform(colorConfig["hsv"]);
transform->addTransform(id, *redTransform, *greenTransform, *blueTransform, *hsvTransform);
transform->setTransformForLed(id, 0, ledCnt-1);
delete redTransform;
delete greenTransform;
delete blueTransform;
ColorTransform * colorTransform = createColorTransform(colorConfig);
transform->addTransform(colorTransform);
transform->setTransformForLed(colorTransform->_id, 0, ledCnt-1);
}
else if (!transformConfig.isArray())
{
ColorTransform * colorTransform = createColorTransform(transformConfig);
transform->addTransform(colorTransform);
transform->setTransformForLed(colorTransform->_id, 0, ledCnt-1);
}
else
{
const QRegExp overallExp("([0-9]+(\\-[0-9]+)?)(,[ ]*([0-9]+(\\-[0-9]+)?))*");
for (Json::UInt i = 0; i < transformConfig.size(); ++i)
{
const Json::Value & config = transformConfig[i];
ColorTransform * colorTransform = createColorTransform(config);
transform->addTransform(colorTransform);
const QString ledIndicesStr = config.get("leds", "").asCString();
if (!overallExp.exactMatch(ledIndicesStr))
{
std::cerr << "Given led indices " << i << " not correct format: " << ledIndicesStr.toStdString() << std::endl;
continue;
}
std::cout << "ColorTransform '" << colorTransform->_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();
transform->setTransformForLed(colorTransform->_id, startInd, endInd);
std::cout << startInd << "-" << endInd;
}
else
{
int index = ledIndexList[i].toInt();
transform->setTransformForLed(colorTransform->_id, index, index);
std::cout << index;
}
}
std::cout << "]" << std::endl;
}
}
return transform;
}
@@ -188,7 +256,7 @@ HsvTransform * Hyperion::createHsvTransform(const Json::Value & hsvConfig)
return new HsvTransform(saturationGain, valueGain);
}
RgbChannelTransform* Hyperion::createColorTransform(const Json::Value& colorConfig)
RgbChannelTransform* Hyperion::createRgbChannelTransform(const Json::Value& colorConfig)
{
const double threshold = colorConfig.get("threshold", 0.0).asDouble();
const double gamma = colorConfig.get("gamma", 1.0).asDouble();
@@ -276,6 +344,10 @@ Hyperion::Hyperion(const Json::Value &jsonConfig) :
_device(createDevice(jsonConfig["device"])),
_timer()
{
if (!_raw2ledTransform->verifyTransforms())
{
throw std::runtime_error("Color transformation incorrectly set");
}
// initialize the image processor factory
ImageProcessorFactory::getInstance().init(_ledString, jsonConfig["blackborderdetector"].get("enable", true).asBool());
@@ -336,59 +408,14 @@ void Hyperion::setColors(int priority, const std::vector<ColorRgb>& ledColors, c
}
}
void Hyperion::setTransform(Hyperion::Transform transform, Hyperion::RgbChannel color, double value)
const std::vector<std::string> & Hyperion::getTransformIds() const
{
ColorTransform* colorTransform = _raw2ledTransform->getTransform("default");
assert(colorTransform != nullptr);
return _raw2ledTransform->getTransformIds();
}
// select the transform of the requested color
RgbChannelTransform * t = nullptr;
switch (color)
{
case RED:
t = &(colorTransform->_rgbRedTransform);
break;
case GREEN:
t = &(colorTransform->_rgbGreenTransform);
break;
case BLUE:
t = &(colorTransform->_rgbBlueTransform);
break;
default:
break;
}
// set transform value
switch (transform)
{
case SATURATION_GAIN:
colorTransform->_hsvTransform.setSaturationGain(value);
break;
case VALUE_GAIN:
colorTransform->_hsvTransform.setValueGain(value);
break;
case THRESHOLD:
assert (t != nullptr);
t->setThreshold(value);
break;
case GAMMA:
assert (t != nullptr);
t->setGamma(value);
break;
case BLACKLEVEL:
assert (t != nullptr);
t->setBlacklevel(value);
break;
case WHITELEVEL:
assert (t != nullptr);
t->setWhitelevel(value);
break;
default:
assert(false);
}
// update the led output
update();
ColorTransform * Hyperion::getTransform(const std::string& id)
{
return _raw2ledTransform->getTransform(id);
}
void Hyperion::clear(int priority)
@@ -413,54 +440,6 @@ void Hyperion::clearall()
update();
}
double Hyperion::getTransform(Hyperion::Transform transform, Hyperion::RgbChannel color) const
{
ColorTransform * colorTransform = _raw2ledTransform->getTransform("default");
assert(colorTransform != nullptr);
// select the transform of the requested color
RgbChannelTransform * t = nullptr;
switch (color)
{
case RED:
t = &(colorTransform->_rgbRedTransform);
break;
case GREEN:
t = &(colorTransform->_rgbGreenTransform);
break;
case BLUE:
t = &(colorTransform->_rgbBlueTransform);
break;
default:
break;
}
// set transform value
switch (transform)
{
case SATURATION_GAIN:
return colorTransform->_hsvTransform.getSaturationGain();
case VALUE_GAIN:
return colorTransform->_hsvTransform.getValueGain();
case THRESHOLD:
assert (t != nullptr);
return t->getThreshold();
case GAMMA:
assert (t != nullptr);
return t->getGamma();
case BLACKLEVEL:
assert (t != nullptr);
return t->getBlacklevel();
case WHITELEVEL:
assert (t != nullptr);
return t->getWhitelevel();
default:
assert(false);
}
return 999.0;
}
QList<int> Hyperion::getActivePriorities() const
{
return _muxer.getPriorities();

View File

@@ -5,7 +5,8 @@
// Hyperion includes
#include "MultiColorTransform.h"
MultiColorTransform::MultiColorTransform()
MultiColorTransform::MultiColorTransform(const unsigned ledCnt) :
_ledTransforms(ledCnt, nullptr)
{
}
@@ -18,33 +19,16 @@ MultiColorTransform::~MultiColorTransform()
}
}
void MultiColorTransform::addTransform(const std::string & id,
const RgbChannelTransform & redTransform,
const RgbChannelTransform & greenTransform,
const RgbChannelTransform & blueTransform,
const HsvTransform & hsvTransform)
void MultiColorTransform::addTransform(ColorTransform * transform)
{
ColorTransform * transform = new ColorTransform();
transform->_id = id;
transform->_rgbRedTransform = redTransform;
transform->_rgbGreenTransform = greenTransform;
transform->_rgbBlueTransform = blueTransform;
transform->_hsvTransform = hsvTransform;
_transformIds.push_back(transform->_id);
_transform.push_back(transform);
}
void MultiColorTransform::setTransformForLed(const std::string& id, const unsigned startLed, const unsigned endLed)
{
assert(startLed <= endLed);
// Make sure that there are at least enough led transforms to match the given indices
if (_ledTransforms.size() < endLed+1)
{
_ledTransforms.resize(endLed+1, nullptr);
}
assert(endLed < _ledTransforms.size());
// Get the identified transform (don't care if is nullptr)
ColorTransform * transform = getTransform(id);
@@ -54,15 +38,23 @@ void MultiColorTransform::setTransformForLed(const std::string& id, const unsign
}
}
std::vector<std::string> MultiColorTransform::getTransformIds()
bool MultiColorTransform::verifyTransforms() const
{
// Create the list on the fly
std::vector<std::string> transformIds;
for (ColorTransform* transform : _transform)
bool allLedsSet = true;
for (unsigned iLed=0; iLed<_ledTransforms.size(); ++iLed)
{
transformIds.push_back(transform->_id);
if (_ledTransforms[iLed] == nullptr)
{
std::cerr << "No transform set for " << iLed << std::endl;
allLedsSet = false;
}
}
return transformIds;
return allLedsSet;
}
const std::vector<std::string> & MultiColorTransform::getTransformIds()
{
return _transformIds;
}
ColorTransform* MultiColorTransform::getTransform(const std::string& id)
@@ -85,7 +77,7 @@ std::vector<ColorRgb> MultiColorTransform::applyTransform(const std::vector<Colo
// 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(_transform.size(), rawColors.size());
const size_t itCnt = std::min(_ledTransforms.size(), rawColors.size());
for (size_t i=0; i<itCnt; ++i)
{
ColorTransform* transform = _ledTransforms[i];

View File

@@ -6,21 +6,8 @@
// Utils includes
#include <utils/ColorRgb.h>
#include <utils/RgbChannelTransform.h>
#include <utils/HsvTransform.h>
struct ColorTransform
{
std::string _id;
/// The RED-Channel (RGB) transform
RgbChannelTransform _rgbRedTransform;
/// The GREEN-Channel (RGB) transform
RgbChannelTransform _rgbGreenTransform;
/// The BLUE-Channel (RGB) transform
RgbChannelTransform _rgbBlueTransform;
/// The HSV Transform for applying Saturation and Value transforms
HsvTransform _hsvTransform;
};
// Hyperion includes
#include <hyperion/ColorTransform.h>
///
/// The LedColorTransform is responsible for performing color transformation from 'raw' colors
@@ -29,22 +16,25 @@ struct ColorTransform
class MultiColorTransform
{
public:
MultiColorTransform();
MultiColorTransform(const unsigned ledCnt);
~MultiColorTransform();
void addTransform(const std::string & id,
const RgbChannelTransform & redTransform,
const RgbChannelTransform & greenTransform,
const RgbChannelTransform & blueTransform,
const HsvTransform & hsvTransform);
/**
* Adds a new ColorTransform to this MultiColorTransform
*
* @param transform The new ColorTransform (ownership is transfered)
*/
void addTransform(ColorTransform * transform);
void setTransformForLed(const std::string& id, const unsigned startLed, const unsigned endLed);
bool verifyTransforms() const;
///
/// Returns the identifier of all the unique ColorTransform
///
/// @return The list with unique id's of the ColorTransforms
std::vector<std::string> getTransformIds();
const std::vector<std::string> & getTransformIds();
///
/// Returns the pointer to the ColorTransform with the given id
@@ -65,6 +55,9 @@ public:
std::vector<ColorRgb> applyTransform(const std::vector<ColorRgb>& rawColors);
private:
/// List with transform ids
std::vector<std::string> _transformIds;
/// List with unique ColorTransforms
std::vector<ColorTransform*> _transform;