diff --git a/libsrc/utils/HslTransform.cpp b/libsrc/utils/HslTransform.cpp new file mode 100644 index 00000000..09056bb2 --- /dev/null +++ b/libsrc/utils/HslTransform.cpp @@ -0,0 +1,158 @@ +#include +#include +#include + +HslTransform::HslTransform() : + _saturationGain(1.0), + _luminanceGain(1.0) +{ +} + +HslTransform::HslTransform(double saturationGain, double luminanceGain) : + _saturationGain(saturationGain), + _luminanceGain(luminanceGain) +{ +} + +HslTransform::~HslTransform() +{ +} + +void HslTransform::setSaturationGain(double saturationGain) +{ + _saturationGain = saturationGain; +} + +double HslTransform::getSaturationGain() const +{ + return _saturationGain; +} + +void HslTransform::setLuminanceGain(double luminanceGain) +{ + _luminanceGain = luminanceGain; +} + +double HslTransform::getLuminanceGain() const +{ + return _luminanceGain; +} + +void HslTransform::transform(uint8_t & red, uint8_t & green, uint8_t & blue) const +{ + if (_saturationGain != 1.0 || _luminanceGain != 1.0) + { + uint16_t hue; + float saturation, luminance; + rgb2hsl(red, green, blue, hue, saturation, luminance); + + float s = saturation * _saturationGain; + if (s > 1.0f) + saturation = 1.0f; + else + saturation = s; + + float l = luminance * _luminanceGain; + if (l > 1.0f) + luminance = 1.0f; + else + luminance = l; + + hsl2rgb(hue, saturation, luminance, red, green, blue); + } +} + +void HslTransform::rgb2hsl(uint8_t red, uint8_t green, uint8_t blue, uint16_t & hue, float & saturation, float & luminance) +{ + float r = red / 255.0f; + float g = green / 255.0f; + float b = blue / 255.0f; + + float rgbMin = r < g ? (r < b ? r : b) : (g < b ? g : b); + float rgbMax = r > g ? (r > b ? r : b) : (g > b ? g : b); + float diff = rgbMax - rgbMin; + + //luminance + luminance = (rgbMin + rgbMax) / 2.0f; + + if (diff == 0.0f) { + saturation = 0.0f; + hue = 0; + return; + } + + //saturation + if (luminance < 0.5f) + saturation = diff / (rgbMin + rgbMax); + else + saturation = diff / (2.0f - rgbMin - rgbMax); + + if (rgbMax == r) + { + // start from 360 to be sure that we won't assign a negative number to the unsigned hue value + hue = 360 + 60 * (g - b) / (rgbMax - rgbMin); + + if (hue > 359) + hue -= 360; + } + else if (rgbMax == g) + { + hue = 120 + 60 * (b - r) / (rgbMax - rgbMin); + } + else + { + hue = 240 + 60 * (r - g) / (rgbMax - rgbMin); + } + +} + +void HslTransform::hsl2rgb(uint16_t hue, float saturation, float luminance, uint8_t & red, uint8_t & green, uint8_t & blue) +{ + if (saturation == 0.0f){ + red = (uint8_t)(luminance * 255.0f); + green = (uint8_t)(luminance * 255.0f); + blue = (uint8_t)(luminance * 255.0f); + return; + } + + float q; + + if (luminance < 0.5f) + q = luminance * (1.0f + saturation); + else + q = (luminance + saturation) - (luminance * saturation); + + float p = (2.0f * luminance) - q; + float h = hue / 360.0f; + + float t[3]; + + t[0] = h + (1.0f / 3.0f); + t[1] = h; + t[2] = h - (1.0f / 3.0f); + + for (int i = 0; i < 3; i++) { + if (t[i] < 0.0f) + t[i] += 1.0f; + if (t[i] > 1.0f) + t[i] -= 1.0f; + } + + float out[3]; + + for (int i = 0; i < 3; i++) { + if (t[i] * 6.0f < 1.0f) + out[i] = p + (q - p) * 6.0f * t[i]; + else if (t[i] * 2.0f < 1.0f) + out[i] = q; + else if (t[i] * 3.0f < 2.0f) + out[i] = p + (q - p) * ((2.0f / 3.0f) - t[i]) * 6.0f; + else out[i] = p; + } + + //convert back to 0...255 range + red = (uint8_t)(out[0] * 255.0f); + green = (uint8_t)(out[1] * 255.0f); + blue = (uint8_t)(out[2] * 255.0f); + +} diff --git a/libsrc/utils/RgbChannelCorrection.cpp b/libsrc/utils/RgbChannelCorrection.cpp new file mode 100644 index 00000000..2cced20b --- /dev/null +++ b/libsrc/utils/RgbChannelCorrection.cpp @@ -0,0 +1,120 @@ +// STL includes +#include + +// Utils includes +#include + +RgbChannelCorrection::RgbChannelCorrection() : + _correctionR(255), + _correctionB(255), + _correctionG(255) +{ + initializeMapping(); +} + +RgbChannelCorrection::RgbChannelCorrection(int correctionR, int correctionG, int correctionB) : + _correctionR(correctionR), + _correctionG(correctionG), + _correctionB(correctionB) +{ + initializeMapping(); +} + +RgbChannelCorrection::~RgbChannelCorrection() +{ +} + +uint8_t RgbChannelCorrection::getcorrectionR() const +{ + return _correctionR; +} + +void RgbChannelCorrection::setcorrectionR(uint8_t correctionR) +{ + _correctionR = correctionR; + initializeMapping(); +} + +uint8_t RgbChannelCorrection::getcorrectionG() const +{ + return _correctionG; +} + +void RgbChannelCorrection::setcorrectionG(uint8_t correctionG) +{ + _correctionG = correctionG; + initializeMapping(); +} + +uint8_t RgbChannelCorrection::getcorrectionB() const +{ + return _correctionB; +} + +void RgbChannelCorrection::setcorrectionB(uint8_t correctionB) +{ + _correctionB = correctionB; + initializeMapping(); +} + +uint8_t RgbChannelCorrection::correctionR(uint8_t inputR) const +{ + return _mappingR[inputR]; +} + +uint8_t RgbChannelCorrection::correctionG(uint8_t inputG) const +{ + return _mappingG[inputG]; +} + +uint8_t RgbChannelCorrection::correctionB(uint8_t inputB) const +{ + return _mappingB[inputB]; +} + +void RgbChannelCorrection::initializeMapping() +{ + // initialize the mapping + for (int i = 0; i < 256; ++i) + { + int outputR = (i * _correctionR) / 255; + if (outputR < -255) + { + outputR = -255; + } + else if (outputR > 255) + { + outputR = 255; + } + _mappingR[i] = outputR; + } + for (int i = 0; i < 256; ++i) + { + int outputG = (i * _correctionG) / 255; + if (outputG < -255) + { + outputG = -255; + } + else if (outputG > 255) + { + outputG = 255; + } + _mappingG[i] = outputG; + } + for (int i = 0; i < 256; ++i) + { + int outputB = (i * _correctionB) / 255; + if (outputB < -255) + { + outputB = -255; + } + else if (outputB > 255) + { + outputB = 255; + } + _mappingB[i] = outputB; + } + + +} +