Merge pull request #534 from AEtHeLsYn/master

Color correction

Former-commit-id: 7be726f1adb8698684a2b4726650082ed517901f
This commit is contained in:
brindosch
2016-03-22 00:56:41 +01:00
39 changed files with 1586 additions and 233 deletions

View File

@@ -0,0 +1,12 @@
#pragma once
/// Simple structure to contain the values of a color transformation
struct ColorCorrectionValues
{
/// The value for the red color-channel
int valueRed;
/// The value for the green color-channel
int valueGreen;
/// The value for the blue color-channel
int valueBlue;
};

View File

@@ -12,6 +12,7 @@
// hyperion-remote includes
#include "ColorTransformValues.h"
#include "ColorCorrectionValues.h"
/// Data parameter for a color
typedef vlofgren::PODParameter<std::vector<QColor>> ColorParameter;
@@ -22,6 +23,9 @@ typedef vlofgren::PODParameter<QImage> ImageParameter;
/// Data parameter for color transform values (list of three values)
typedef vlofgren::PODParameter<ColorTransformValues> TransformParameter;
/// Data parameter for color correction values (list of three values)
typedef vlofgren::PODParameter<ColorCorrectionValues> CorrectionParameter;
namespace vlofgren {
///
/// Translates a string (as passed on the commandline) to a vector of colors
@@ -128,4 +132,33 @@ namespace vlofgren {
return transform;
}
template<>
ColorCorrectionValues CorrectionParameter::validate(const std::string& s) throw (Parameter::ParameterRejected)
{
ColorCorrectionValues correction;
// s should be split in 3 parts
// seperators are either a ',' or a space
QStringList components = QString(s.c_str()).split(" ", QString::SkipEmptyParts);
if (components.size() == 3)
{
bool ok1, ok2, ok3;
correction.valueRed = components[0].toInt(&ok1);
correction.valueGreen = components[1].toInt(&ok2);
correction.valueBlue = components[2].toInt(&ok3);
if (ok1 && ok2 && ok3)
{
return correction;
}
}
std::stringstream errorMessage;
errorMessage << "Argument " << s << " can not be parsed to 3 integer values";
throw Parameter::ParameterRejected(errorMessage.str());
return correction;
}
}

View File

@@ -192,7 +192,7 @@ void JsonConnection::clearAll()
parseReply(reply);
}
void JsonConnection::setTransform(std::string * transformId, double * saturation, double * value, ColorTransformValues *threshold, ColorTransformValues *gamma, ColorTransformValues *blacklevel, ColorTransformValues *whitelevel)
void JsonConnection::setTransform(std::string * transformId, double * saturation, double * value, double * saturationL, double * luminance, ColorTransformValues *threshold, ColorTransformValues *gamma, ColorTransformValues *blacklevel, ColorTransformValues *whitelevel)
{
std::cout << "Set color transforms" << std::endl;
@@ -215,7 +215,16 @@ void JsonConnection::setTransform(std::string * transformId, double * saturation
{
transform["valueGain"] = *value;
}
if (saturationL != nullptr)
{
transform["saturationLGain"] = *saturationL;
}
if (luminance != nullptr)
{
transform["luminanceGain"] = *luminance;
}
if (threshold != nullptr)
{
Json::Value & v = transform["threshold"];
@@ -255,6 +264,64 @@ void JsonConnection::setTransform(std::string * transformId, double * saturation
parseReply(reply);
}
void JsonConnection::setCorrection(std::string * correctionId, ColorCorrectionValues *correction)
{
std::cout << "Set color corrections" << std::endl;
// create command
Json::Value command;
command["command"] = "correction";
Json::Value & correct = command["correction"];
if (correctionId != nullptr)
{
correct["id"] = *correctionId;
}
if (correction != nullptr)
{
Json::Value & v = correct["correctionValues"];
v.append(correction->valueRed);
v.append(correction->valueGreen);
v.append(correction->valueBlue);
}
// send command message
Json::Value reply = sendMessage(command);
// parse reply message
parseReply(reply);
}
void JsonConnection::setTemperature(std::string * temperatureId, ColorCorrectionValues *temperature)
{
std::cout << "Set color temperature corrections" << std::endl;
// create command
Json::Value command;
command["command"] = "temperature";
Json::Value & temp = command["temperature"];
if (temperatureId != nullptr)
{
temp["id"] = *temperatureId;
}
if (temperature != nullptr)
{
Json::Value & v = temp["correctionValues"];
v.append(temperature->valueRed);
v.append(temperature->valueGreen);
v.append(temperature->valueBlue);
}
// send command message
Json::Value reply = sendMessage(command);
// parse reply message
parseReply(reply);
}
Json::Value JsonConnection::sendMessage(const Json::Value & message)
{
// serialize message (FastWriter already appends a newline)

View File

@@ -14,6 +14,7 @@
// hyperion-remote includes
#include "ColorTransformValues.h"
#include "ColorCorrectionValues.h"
///
/// Connection class to setup an connection to the hyperion server and execute commands
@@ -89,6 +90,8 @@ public:
/// @param transformId The identifier of the transform to set
/// @param saturation The HSV saturation gain
/// @param value The HSV value gain
/// @param saturationL The HSL saturation gain
/// @param luminance The HSL luminance gain
/// @param threshold The threshold
/// @param gamma The gamma value
/// @param blacklevel The blacklevel
@@ -98,10 +101,34 @@ public:
std::string * transformId,
double * saturation,
double * value,
double * saturationL,
double * luminance,
ColorTransformValues * threshold,
ColorTransformValues * gamma,
ColorTransformValues * blacklevel,
ColorTransformValues * whitelevel);
///
/// Set the color correction of the leds
///
/// @note Note that providing a NULL will leave the settings on the server unchanged
///
/// @param correctionId The identifier of the correction to set
/// @param correction The correction values
void setCorrection(
std::string * correctionId,
ColorCorrectionValues * correction);
///
/// Set the color temperature of the leds
///
/// @note Note that providing a NULL will leave the settings on the server unchanged
///
/// @param temperatureId The identifier of the correction to set
/// @param temperature The temperature correction values
void setTemperature(
std::string * temperatureId,
ColorCorrectionValues * temperature);
private:
///

View File

@@ -61,20 +61,26 @@ int main(int argc, char * argv[])
IntParameter & argDuration = parameters.add<IntParameter> ('d', "duration" , "Specify how long the leds should be switched on in millseconds [default: infinity]");
ColorParameter & argColor = parameters.add<ColorParameter> ('c', "color" , "Set all leds to a constant color (either RRGGBB hex value or a color name. The color may be repeated multiple time like: RRGGBBRRGGBB)");
ImageParameter & argImage = parameters.add<ImageParameter> ('i', "image" , "Set the leds to the colors according to the given image file");
StringParameter & argEffect = parameters.add<StringParameter> ('e', "effect" , "Enable the effect with the given name");
StringParameter & argEffectArgs = parameters.add<StringParameter> (0x0, "effectArgs", "Arguments to use in combination with the specified effect. Should be a Json object string.");
StringParameter & argEffect = parameters.add<StringParameter> ('e', "effect" , "Enable the effect with the given name");
StringParameter & argEffectArgs = parameters.add<StringParameter> (0x0, "effectArgs", "Arguments to use in combination with the specified effect. Should be a Json object string.");
SwitchParameter<> & argServerInfo = parameters.add<SwitchParameter<> >('l', "list" , "List server info");
SwitchParameter<> & argClear = parameters.add<SwitchParameter<> >('x', "clear" , "Clear data for the priority channel provided by the -p option");
SwitchParameter<> & argClearAll = parameters.add<SwitchParameter<> >(0x0, "clearall" , "Clear data for all active priority channels");
StringParameter & argId = parameters.add<StringParameter> ('q', "qualifier" , "Identifier(qualifier) of the transform to set");
DoubleParameter & argSaturation = parameters.add<DoubleParameter> ('s', "saturation", "Set the HSV saturation gain of the leds");
DoubleParameter & argValue = parameters.add<DoubleParameter> ('v', "value" , "Set the HSV value gain of the leds");
DoubleParameter & argSaturationL = parameters.add<DoubleParameter> ('u', "saturationL", "Set the HSL saturation gain of the leds");
DoubleParameter & argLuminance = parameters.add<DoubleParameter> ('m', "luminance" , "Set the HSL luminance gain of the leds");
TransformParameter & argGamma = parameters.add<TransformParameter>('g', "gamma" , "Set the gamma of the leds (requires 3 space seperated values)");
TransformParameter & argThreshold = parameters.add<TransformParameter>('t', "threshold" , "Set the threshold of the leds (requires 3 space seperated values between 0.0 and 1.0)");
TransformParameter & argBlacklevel = parameters.add<TransformParameter>('b', "blacklevel", "Set the blacklevel of the leds (requires 3 space seperated values which are normally between 0.0 and 1.0)");
TransformParameter & argWhitelevel = parameters.add<TransformParameter>('w', "whitelevel", "Set the whitelevel of the leds (requires 3 space seperated values which are normally between 0.0 and 1.0)");
SwitchParameter<> & argPrint = parameters.add<SwitchParameter<> >(0x0, "print" , "Print the json input and output messages on stdout");
SwitchParameter<> & argHelp = parameters.add<SwitchParameter<> >('h', "help" , "Show this help message and exit");
StringParameter & argIdC = parameters.add<StringParameter> ('y', "qualifier" , "Identifier(qualifier) of the correction to set");
CorrectionParameter & argCorrection = parameters.add<CorrectionParameter>('Y', "correction" , "Set the correction of the leds (requires 3 space seperated values between 0 and 255)");
StringParameter & argIdT = parameters.add<StringParameter> ('z', "qualifier" , "Identifier(qualifier) of the temperature to set");
CorrectionParameter & argTemperature = parameters.add<CorrectionParameter>('Z', "temperature" , "Set the temperature correction of the leds (requires 3 space seperated values between 0 and 255)");
// set the default values
argAddress.setDefault(defaultServerAddress.toStdString());
@@ -93,27 +99,35 @@ int main(int argc, char * argv[])
}
// check if at least one of the available color transforms is set
bool colorTransform = argSaturation.isSet() || argValue.isSet() || argThreshold.isSet() || argGamma.isSet() || argBlacklevel.isSet() || argWhitelevel.isSet();
bool colorTransform = argSaturation.isSet() || argValue.isSet() || argSaturationL.isSet() || argLuminance.isSet() || argThreshold.isSet() || argGamma.isSet() || argBlacklevel.isSet() || argWhitelevel.isSet();
// check that exactly one command was given
int commandCount = count({argColor.isSet(), argImage.isSet(), argEffect.isSet(), argServerInfo.isSet(), argClear.isSet(), argClearAll.isSet(), colorTransform});
int commandCount = count({argColor.isSet(), argImage.isSet(), argEffect.isSet(), argServerInfo.isSet(), argClear.isSet(), argClearAll.isSet(), colorTransform, argCorrection.isSet(), argTemperature.isSet()});
if (commandCount != 1)
{
std::cerr << (commandCount == 0 ? "No command found." : "Multiple commands found.") << " Provide exactly one of the following options:" << std::endl;
std::cerr << " " << argColor.usageLine() << std::endl;
std::cerr << " " << argImage.usageLine() << std::endl;
std::cerr << " " << argEffect.usageLine() << std::endl;
std::cerr << " " << argEffect.usageLine() << std::endl;
std::cerr << " " << argServerInfo.usageLine() << std::endl;
std::cerr << " " << argClear.usageLine() << std::endl;
std::cerr << " " << argClearAll.usageLine() << std::endl;
std::cerr << "or one or more of the available color transformations:" << std::endl;
std::cerr << "one or more of the available color transformations:" << std::endl;
std::cerr << " " << argId.usageLine() << std::endl;
std::cerr << " " << argSaturation.usageLine() << std::endl;
std::cerr << " " << argValue.usageLine() << std::endl;
std::cerr << " " << argSaturationL.usageLine() << std::endl;
std::cerr << " " << argLuminance.usageLine() << std::endl;
std::cerr << " " << argThreshold.usageLine() << std::endl;
std::cerr << " " << argGamma.usageLine() << std::endl;
std::cerr << " " << argBlacklevel.usageLine() << std::endl;
std::cerr << " " << argWhitelevel.usageLine() << std::endl;
std::cerr << "one or more of the available color corrections:" << std::endl;
std::cerr << " " << argIdC.usageLine() << std::endl;
std::cerr << " " << argCorrection.usageLine() << std::endl;
std::cerr << "or one or more of the available color temperature adjustment:" << std::endl;
std::cerr << " " << argIdT.usageLine() << std::endl;
std::cerr << " " << argTemperature.usageLine() << std::endl;
return 1;
}
@@ -129,11 +143,11 @@ int main(int argc, char * argv[])
{
connection.setImage(argImage.getValue(), argPriority.getValue(), argDuration.getValue());
}
else if (argEffect.isSet())
{
connection.setEffect(argEffect.getValue(), argEffectArgs.getValue(), argPriority.getValue(), argDuration.getValue());
}
else if (argServerInfo.isSet())
else if (argEffect.isSet())
{
connection.setEffect(argEffect.getValue(), argEffectArgs.getValue(), argPriority.getValue(), argDuration.getValue());
}
else if (argServerInfo.isSet())
{
QString info = connection.getServerInfo();
std::cout << "Server info:\n" << info.toStdString() << std::endl;
@@ -149,26 +163,54 @@ int main(int argc, char * argv[])
else if (colorTransform)
{
std::string transId;
double saturation, value;
double saturation, value, saturationL, luminance;
ColorTransformValues threshold, gamma, blacklevel, whitelevel;
if (argId.isSet()) transId = argId.getValue();
if (argSaturation.isSet()) saturation = argSaturation.getValue();
if (argValue.isSet()) value = argValue.getValue();
if (argSaturationL.isSet()) saturationL = argSaturationL.getValue();
if (argLuminance.isSet()) luminance = argLuminance.getValue();
if (argThreshold.isSet()) threshold = argThreshold.getValue();
if (argGamma.isSet()) gamma = argGamma.getValue();
if (argBlacklevel.isSet()) blacklevel = argBlacklevel.getValue();
if (argWhitelevel.isSet()) whitelevel = argWhitelevel.getValue();
connection.setTransform(
argId.isSet() ? &transId : nullptr,
argSaturation.isSet() ? &saturation : nullptr,
argValue.isSet() ? &value : nullptr,
argSaturationL.isSet() ? &saturationL : nullptr,
argLuminance.isSet() ? &luminance : nullptr,
argThreshold.isSet() ? &threshold : nullptr,
argGamma.isSet() ? &gamma : nullptr,
argBlacklevel.isSet() ? &blacklevel : nullptr,
argWhitelevel.isSet() ? &whitelevel : nullptr);
}
else if (argCorrection.isSet())
{
std::string corrId;
ColorCorrectionValues correction;
if (argIdC.isSet()) corrId = argIdC.getValue();
if (argCorrection.isSet()) correction = argCorrection.getValue();
connection.setCorrection(
argIdC.isSet() ? &corrId : nullptr,
argCorrection.isSet() ? &correction : nullptr);
}
else if (argTemperature.isSet())
{
std::string tempId;
ColorCorrectionValues temperature;
if (argIdT.isSet()) tempId = argIdT.getValue();
if (argTemperature.isSet()) temperature = argTemperature.getValue();
connection.setTemperature(
argIdT.isSet() ? &tempId : nullptr,
argTemperature.isSet() ? &temperature : nullptr);
}
}
catch (const std::runtime_error & e)
{