legacy-imlib2/src/lib/color_helpers.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);
}
}