2013-09-13 14:24:49 +02:00
|
|
|
#include <iostream>
|
2013-08-23 18:24:10 +02:00
|
|
|
#include <utils/HsvTransform.h>
|
2013-08-21 21:50:17 +02:00
|
|
|
|
2016-12-18 00:47:53 +01:00
|
|
|
HsvTransform::HsvTransform()
|
|
|
|
: _saturationGain(1.0)
|
|
|
|
, _valueGain(1.0)
|
2013-08-21 21:50:17 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
HsvTransform::HsvTransform(double saturationGain, double valueGain) :
|
|
|
|
_saturationGain(saturationGain),
|
|
|
|
_valueGain(valueGain)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
HsvTransform::~HsvTransform()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void HsvTransform::setSaturationGain(double saturationGain)
|
|
|
|
{
|
|
|
|
_saturationGain = saturationGain;
|
|
|
|
}
|
|
|
|
|
|
|
|
double HsvTransform::getSaturationGain() const
|
|
|
|
{
|
|
|
|
return _saturationGain;
|
|
|
|
}
|
|
|
|
|
|
|
|
void HsvTransform::setValueGain(double valueGain)
|
|
|
|
{
|
|
|
|
_valueGain = valueGain;
|
|
|
|
}
|
|
|
|
|
|
|
|
double HsvTransform::getValueGain() const
|
|
|
|
{
|
|
|
|
return _valueGain;
|
|
|
|
}
|
|
|
|
|
|
|
|
void HsvTransform::transform(uint8_t & red, uint8_t & green, uint8_t & blue) const
|
|
|
|
{
|
|
|
|
if (_saturationGain != 1.0 || _valueGain != 1.0)
|
|
|
|
{
|
2013-08-22 20:31:57 +02:00
|
|
|
uint16_t hue;
|
|
|
|
uint8_t saturation, value;
|
2013-08-21 21:50:17 +02:00
|
|
|
rgb2hsv(red, green, blue, hue, saturation, value);
|
|
|
|
|
|
|
|
int s = saturation * _saturationGain;
|
|
|
|
if (s > 255)
|
|
|
|
saturation = 255;
|
|
|
|
else
|
|
|
|
saturation = s;
|
|
|
|
|
|
|
|
int v = value * _valueGain;
|
|
|
|
if (v > 255)
|
|
|
|
value = 255;
|
|
|
|
else
|
|
|
|
value = v;
|
|
|
|
|
|
|
|
hsv2rgb(hue, saturation, value, red, green, blue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-22 20:31:57 +02:00
|
|
|
void HsvTransform::rgb2hsv(uint8_t red, uint8_t green, uint8_t blue, uint16_t & hue, uint8_t & saturation, uint8_t & value)
|
2013-08-21 21:50:17 +02:00
|
|
|
{
|
|
|
|
uint8_t rgbMin, rgbMax;
|
|
|
|
|
|
|
|
rgbMin = red < green ? (red < blue ? red : blue) : (green < blue ? green : blue);
|
|
|
|
rgbMax = red > green ? (red > blue ? red : blue) : (green > blue ? green : blue);
|
|
|
|
|
|
|
|
value = rgbMax;
|
|
|
|
if (value == 0)
|
|
|
|
{
|
|
|
|
hue = 0;
|
|
|
|
saturation = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
saturation = 255 * long(rgbMax - rgbMin) / value;
|
|
|
|
if (saturation == 0)
|
|
|
|
{
|
|
|
|
hue = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rgbMax == red)
|
2013-09-13 14:24:49 +02:00
|
|
|
{
|
|
|
|
// start from 360 to be sure that we won't assign a negative number to the unsigned hue value
|
|
|
|
hue = 360 + 60 * (green - blue) / (rgbMax - rgbMin);
|
|
|
|
|
|
|
|
if (hue > 359)
|
|
|
|
hue -= 360;
|
|
|
|
}
|
2013-08-21 21:50:17 +02:00
|
|
|
else if (rgbMax == green)
|
2013-09-13 14:24:49 +02:00
|
|
|
{
|
2013-08-22 20:31:57 +02:00
|
|
|
hue = 120 + 60 * (blue - red) / (rgbMax - rgbMin);
|
2013-09-13 14:24:49 +02:00
|
|
|
}
|
2013-08-21 21:50:17 +02:00
|
|
|
else
|
2013-09-13 14:24:49 +02:00
|
|
|
{
|
2013-08-22 20:31:57 +02:00
|
|
|
hue = 240 + 60 * (red - green) / (rgbMax - rgbMin);
|
2013-09-13 14:24:49 +02:00
|
|
|
}
|
2013-08-21 21:50:17 +02:00
|
|
|
}
|
|
|
|
|
2013-08-22 20:31:57 +02:00
|
|
|
void HsvTransform::hsv2rgb(uint16_t hue, uint8_t saturation, uint8_t value, uint8_t & red, uint8_t & green, uint8_t & blue)
|
2013-08-21 21:50:17 +02:00
|
|
|
{
|
|
|
|
uint8_t region, remainder, p, q, t;
|
|
|
|
|
|
|
|
if (saturation == 0)
|
|
|
|
{
|
|
|
|
red = value;
|
|
|
|
green = value;
|
|
|
|
blue = value;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-08-22 20:31:57 +02:00
|
|
|
region = hue / 60;
|
2013-09-13 14:03:12 +02:00
|
|
|
remainder = (hue - (region * 60)) * 256 / 60;
|
2013-08-21 21:50:17 +02:00
|
|
|
|
|
|
|
p = (value * (255 - saturation)) >> 8;
|
|
|
|
q = (value * (255 - ((saturation * remainder) >> 8))) >> 8;
|
|
|
|
t = (value * (255 - ((saturation * (255 - remainder)) >> 8))) >> 8;
|
|
|
|
|
|
|
|
switch (region)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
red = value; green = t; blue = p;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
red = q; green = value; blue = p;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
red = p; green = value; blue = t;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
red = p; green = q; blue = value;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
red = t; green = p; blue = value;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
red = value; green = p; blue = q;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|