forked from old/legacy-imlib2
209 lines
4.3 KiB
C
209 lines
4.3 KiB
C
#include "color_helpers.h"
|
|
/*
|
|
* Color space conversion helper routines
|
|
* Convert between rgb and hsv and between rgb and hls
|
|
*/
|
|
|
|
void
|
|
__imlib_rgb_to_hsv(int r, int g, int b, float *h, float *s, float *v)
|
|
{
|
|
float min, max, delta;
|
|
|
|
min = (((r < g) ? r : g) < b) ? ((r < g) ? r : g) : b;
|
|
max = (((r > g) ? r : g) > b) ? ((r > g) ? r : g) : b;
|
|
|
|
*v = max / 255.0;
|
|
delta = (max - min);
|
|
if (delta == 0)
|
|
{
|
|
*h = 0.0;
|
|
*s = 0.0;
|
|
return;
|
|
}
|
|
*s = delta / max;
|
|
if (r == max)
|
|
*h = (g - b) / delta;
|
|
else if (g == max)
|
|
*h = 2.0 + (b - r) / delta;
|
|
else
|
|
*h = 4.0 + (r - g) / delta;
|
|
*h *= 60.0;
|
|
if (*h < 0)
|
|
*h += 360.0;
|
|
}
|
|
|
|
void
|
|
__imlib_hsv_to_rgb(float h, float s, float v, int *r, int *g, int *b)
|
|
{
|
|
float f, vf;
|
|
int i, p, q, t, vv;
|
|
|
|
vf = 255.0 * v;
|
|
vv = (int)round(vf);
|
|
|
|
if (s == 0.0)
|
|
{
|
|
*r = *g = *b = vv;
|
|
return;
|
|
}
|
|
|
|
h /= 60.0;
|
|
i = floor(h);
|
|
f = h - (float)i;
|
|
p = (int)round(vf * (1.0 - s));
|
|
q = (int)round(vf * (1.0 - (s * f)));
|
|
t = (int)round(vf * (1.0 - s * (1.0 - f)));
|
|
|
|
switch (i % 6)
|
|
{
|
|
case 0:
|
|
*r = vv;
|
|
*g = t;
|
|
*b = p;
|
|
break;
|
|
case 1:
|
|
*r = q;
|
|
*g = vv;
|
|
*b = p;
|
|
break;
|
|
case 2:
|
|
*r = p;
|
|
*g = vv;
|
|
*b = t;
|
|
break;
|
|
case 3:
|
|
*r = p;
|
|
*g = q;
|
|
*b = vv;
|
|
break;
|
|
case 4:
|
|
*r = t;
|
|
*g = p;
|
|
*b = vv;
|
|
break;
|
|
case 5:
|
|
default:
|
|
*r = vv;
|
|
*g = p;
|
|
*b = q;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void
|
|
__imlib_rgb_to_hls(int r, int g, int b, float *hue, float *lightness,
|
|
float *saturation)
|
|
{
|
|
int f;
|
|
float i, j, k, max, min, d;
|
|
|
|
i = ((float)r) / 255.0;
|
|
j = ((float)g) / 255.0;
|
|
k = ((float)b) / 255.0;
|
|
|
|
f = 0;
|
|
max = min = i;
|
|
if (j > max)
|
|
{
|
|
max = j;
|
|
f = 1;
|
|
}
|
|
else
|
|
min = j;
|
|
if (k > max)
|
|
{
|
|
max = k;
|
|
f = 2;
|
|
}
|
|
else if (k < min)
|
|
min = k;
|
|
d = max - min;
|
|
|
|
*lightness = (max + min) / 2.0;
|
|
if (d == 0)
|
|
{
|
|
*saturation = 0;
|
|
*hue = 0;
|
|
}
|
|
else
|
|
{
|
|
if (*lightness < 0.5)
|
|
*saturation = d / (max + min);
|
|
else
|
|
*saturation = d / (2 - max - min);
|
|
switch (f)
|
|
{
|
|
case 0:
|
|
*hue = (j - k) / d;
|
|
break;
|
|
case 1:
|
|
*hue = 2 + (k - i) / d;
|
|
break;
|
|
case 2:
|
|
*hue = 4 + (i - j) / d;
|
|
break;
|
|
}
|
|
*hue *= 60.0;
|
|
if (*hue < 0)
|
|
*hue += 360.0;
|
|
}
|
|
}
|
|
|
|
void
|
|
__imlib_hls_to_rgb(float hue, float lightness, float saturation, int *r, int *g,
|
|
int *b)
|
|
{
|
|
float m1, m2, m21, h;
|
|
|
|
if (saturation == 0)
|
|
*r = *g = *b = (int)(lightness * 255.0);
|
|
else
|
|
{
|
|
if (lightness <= 0.5)
|
|
m2 = lightness * (1 + saturation);
|
|
else
|
|
m2 = lightness + saturation + lightness * saturation;
|
|
m1 = 2 * lightness - m2;
|
|
m21 = m2 - m1;
|
|
h = hue + 120;
|
|
if (h > 360)
|
|
h -= 360;
|
|
else if (h < 0)
|
|
h += 360;
|
|
if (h < 60)
|
|
*r = (int)(255.0 * (m1 + m21 * h / 60.0));
|
|
else if (h < 180)
|
|
*r = (int)(255.0 * m2);
|
|
else if (h < 240)
|
|
*r = (int)(255.0 * (m1 + m21 * (240.0 - h) / 60.0));
|
|
else
|
|
*r = (int)(255.0 * m1);
|
|
h = hue;
|
|
if (h > 360)
|
|
h -= 360;
|
|
else if (h < 0)
|
|
h += 360;
|
|
if (h < 60)
|
|
*g = (int)(255.0 * (m1 + m21 * h / 60.0));
|
|
else if (h < 180)
|
|
*g = (int)(255.0 * m2);
|
|
else if (h < 240)
|
|
*g = (int)(255.0 * (m1 + m21 * (240.0 - h) / 60.0));
|
|
else
|
|
*g = (int)(255.0 * m1);
|
|
h = hue - 120;
|
|
if (h > 360)
|
|
h -= 360;
|
|
else if (h < 0)
|
|
h += 360;
|
|
if (h < 60)
|
|
*b = (int)(255.0 * (m1 + m21 * h / 60.0));
|
|
else if (h < 180)
|
|
*b = (int)(255.0 * m2);
|
|
else if (h < 240)
|
|
*b = (int)(255.0 * (m1 + m21 * (240.0 - h) / 60.0));
|
|
else
|
|
*b = (int)(255.0 * m1);
|
|
}
|
|
}
|