В данном приложении приведены процедуры перевода из RGB в HSV и наоборот и процедуры перевода из RGB в HLS и наоборот, соответствующие процедурам из [Род89] и [Фол85]. В процедурах используется вещественная арифметика. Переход на целочисленную арифметику, более подходящую для реальных применений, может быть выполнен определением констант для максимальных значений координат цвета - R,G,B, оттенка (hue), насыщенности (saturation), светлоты (value или lightness) и соответствующей модификацией текстов процедур.
/*==================================================== RGB_HSV * Преобразования из модели HSV в RGB и наоборот */ #include <stdio.h> #define UNDEFINED -1.0 /* Неопределенное значение для Hue */
/*--------------------------------------------------- V_HSVRGB * Переводит из модели HSV в модель RGB * * void V_HSVRGB (float *r, float *g, float *b, * float hue, float sat, float val) * * Вход: * 0 <= hue <= 360 градусов - оттенок. Основные цвета: * 0 - красный, 60 - желтый, * 120 - зеленый, 180 - голубой * 240 - синий, 300 - пурпурный * Остальные цвета между ними * 0.0 <= sat <= 1.0 - Saturation - насыщенность * 0.0 <= val <= 1.0 - Value - светлота * * Выход: * 0.0 <= r,g,b <= 1.0 - значения красного, зеленого, синего * V_HSVRGB= 0 - норма * 1/2/3 - ошибка в hue/ошибка в sat/ошибка в val */ int V_HSVRGB (r, g, b, hue, sat, val) float *r, *g, *b, hue, sat, val; { int ii, otw; float c1, c2, c3, fr; otw= 0; if (sat == 0.0) { /* Ахроматический цвет */ *r= val; *g= val; *b= val; if (hue != UNDEFINED) ++otw; } else { /* Хроматический цвет */ hue-= (ii= (int)(hue/360.0)) * 360.0; if (ii < 0) hue= -hue; ii= (int)(hue /= 60.0); fr= hue - ii; c1= val*(1.0 - sat); c2= val*(1.0 - sat*fr); c3= val*(1.0 - sat*(1.0 - fr)); switch (ii) { case 0: *r= val; *g= c3; *b= c1; break; case 1: *r= c2; *g= val; *b= c1; break; case 2: *r= c1; *g= val; *b= c3; break; case 3: *r= c1; *g= c2; *b= val; break; case 4: *r= c3; *g= c1; *b= val; break; case 5: *r= val; *g= c1; *b= c2; break; } } return (otw); } /* V_HSVRGB */
/*--------------------------------------------------- V_RGBHSV * Переводит из модели RGB в модель HSV * * void V_RGBHSV (float r, float g, float b, * float *hue, float *sat, float *val) * * Вход: * 0.0 <= r,g,b <= 1.0 - значения красного, зеленого, синего * * * Выход: * 0 <= hue <= 360 градусов - оттенок. Основные цвета: * 0 - красный, 60 - желтый, * 120 - зеленый, 180 - голубой * 240 - синий, 300 - пурпурный * Остальные цвета между ними * 0.0 <= sat <= 1.0 - Saturation - насыщенность * 0.0 <= val <= 1.0 - Value - светлота * * V_RGBHSV= 0 - норма * 1/2/3 - ошибка в r/ошибка в g/ошибка в b */ int V_RGBHSV (r, g, b, hue, sat, val) float r, g, b, *hue, *sat, *val; { int otw; float minc, maxc, h, s, v, dmax, rc, gc, bc; otw= 0; if (r < 0.0 || r > 1.0) ++otw; /* Проверки значений */ if (g < 0.0 || g > 1.0) otw= 2; if (b < 0.0 || b > 1.0) otw= 3; if (!otw) { if ((maxc= r) < b) maxc= b; /* Поиск макс значения */ if (maxc < g) maxc= g; if ((minc= r) > b) minc= b; /* Поиск мин значения */ if (minc > g) minc= g; s= 0.0; /* Насыщенность */ if (maxc != 0.0) s= (maxc-minc)/maxc; if (s == 0.0) h= UNDEFINED; /* Ахроматический цвет */ else { /* Хроматический цвет */ dmax= maxc-minc; rc= (maxc-r)/dmax; /* rc - удаленность */ gc= (maxc-g)/dmax; /* цвета от красного */ bc= (maxc-b)/dmax; if (r == maxc) h= bc-gc; else /* Цвет между жел- */ /* тым и пурпурным */ if (g == maxc) h= 2+rc-bc; else /* Цвет между голу-*/ /* бым и желтым */ h= 4+gc-rc; /* Цвет между пур- */ /* пурным и голубым*/ if ((h*= 60.0) < 0.0) h+= 360.0; } *hue= h; *sat= s; *val= maxc; } return (otw); } /* V_RGBHSV */
/*----------------------------------------------- MAIN RGB_HSV * Тестовая программа проверки прдпрограмм * преобразований из системы HSV в RGB и наоборот. */ void main(void) { int ii; float r, g, b, r1, g1, b1, hue, sat, val; r= 0.0; g= 0.0; b= 0.0; hue= 0.0; m0:printf ("HSV r,g,b= (%f %f %f) ? ", r,g,b); scanf ("%f%f%f", &r, &g, &b); ii= V_RGBHSV (r, g, b, &hue, &sat, &val); printf ("V_RGBHSV: otw=%d hue=%f sat=%f val=%f\n", ii, hue, sat, val); ii= V_HSVRGB (&r1, &g1, &b1, hue, sat, val); printf ("V_HSVRGB: otw=%d r=%f g=%f b=%f\n", ii, r1, g1, b1); goto m0; } /*==================================================== RGB_HLS * Преобразования из модели HLS в RGB и наоборот */ #include <stdio.h> #define UNDEFINED -1.0 /* Неопределенное значение для Hue */
/*--------------------------------------------------- V_HLSRGB * Переводит из модели HLS в модель RGB * * void V_HLSRGB (float *r, float *g, float *b, * float hue, float sat, float lig) * * Вход: * 0 <= hue <= 360 градусов - оттенок. Основные цвета: * 0 - красный, 60 - желтый, * 120 - зеленый, 180 - голубой * 240 - синий, 300 - пурпурный * Остальные цвета между ними * 0.0 <= sat <= 1.0 - Saturation - насыщенность * 0.0 <= lig <= 1.0 - Value - светлота * * Выход: * 0.0 <= r,g,b <= 1.0 - значения красного, зеленого, синего * V_HLSRGB= 0 - норма * 1/2/3 - ошибка в hue/ошибка в sat/ошибка в lig */ static float VAL_RGB (n1, n2, hue) float n1, n2, hue; { float otw; if (hue < 0) hue+= 360.0; hue= hue - ((int)(hue/360.0)) * 360.0; if (hue < 60.0) otw= n1+(n2-n1)*hue/60.0; else if (hue < 180.0) otw= n2; else if (hue < 240.0) otw= n1+(n2-n1)*(240.0-hue)/60.0; else otw= n1; return (otw); } /* VAL_RGB */ int V_HLSRGB (r, g, b, hue, sat, lig) float *r, *g, *b, hue, sat, lig; { int otw; float m1, m2; otw= 0; if (sat == 0.0) { /* Ахроматический случай */ if (hue == UNDEFINED) { *r= lig; *b= lig; *g= lig; } else ++otw; } else { /* Хроматический случай */ if ((m2= lig) > 0.5) m2= 1.0 - lig; m2= lig + sat*m2; m1= 2*lig - m2; *r= VAL_RGB (m1, m2, hue+120.0); *g= VAL_RGB (m1, m2, hue); *b= VAL_RGB (m1, m2, hue-120.0); } return (otw); } /* V_HLSRGB */
/*--------------------------------------------------- V_RGBHLS * Переводит из модели RGB в модель HLS * * void V_RGBHLS (float r, float g, float b, * float *hue, float *sat, float *lig) * * Вход: * 0.0 <= r,g,b <= 1.0 - значения красного, зеленого, синего * * * Выход: * 0 <= hue <= 360 градусов - оттенок. Основные цвета: * 0 - красный, 60 - желтый, * 120 - зеленый, 180 - голубой * 240 - синий, 300 - пурпурный * Остальные цвета между ними * 0.0 <= sat <= 1.0 - Saturation - насыщенность * 0.0 <= lig <= 1.0 - Value - светлота * * V_RGBHLS= 0 - норма * 1/2/3 - ошибка в r/ошибка в g/ошибка в b */ int V_RGBHLS (r, g, b, hue, sat, lig) float r, g, b, *hue, *sat, *lig; { int otw; float minc, maxc, h, s, l, dm, rc, gc, bc; otw= 0; if (r < 0.0 || r > 1.0) ++otw; if (g < 0.0 || g > 1.0) otw= 2; if (b < 0.0 || b > 1.0) otw= 3; if (!otw) { if ((maxc= r) < b) maxc= b; if (maxc < g) maxc= g; if ((minc= r) > b) minc= b; if (minc > g) minc= g; l= (maxc + minc) / 2; /* Светлота */ if (maxc == minc) { /* r=g=b - ахроматический */ s= 0.0; /* случай */ h= UNDEFINED; } else { /* Хроматический случай */ dm= maxc-minc; s= (l < 0.5) ? dm/(maxc+minc) : dm/(2-maxc-minc); rc= (maxc-r)/dm; /* Вычисление тона */ gc= (maxc-g)/dm; /* rc задает удаленность */ bc= (maxc-b)/dm; /* цвета от красного */ if (r == maxc) h= bc-gc; else /* Цвет между жел- */ /* тым и пурпурным */ if (g == maxc) h= 2+rc-bc; else /* Цвет между голу-*/ /* бым и желтым */ h= 4+gc-rc; /* Цвет между пур- */ /* пурным и голубым*/ if ((h*= 60.0) < 0.0) h+= 360.0; } *hue= h; *sat= s; *lig= l; } return (otw); } /* V_RGBHLS */
/*----------------------------------------------- MAIN RGB_HLS * Тестовая программа проверки подпрограмм * преобразований из системы HLS в RGB и наоборот. */ void main(void) { int ii; float r, g, b, r1, g1, b1, hue, sat, lig; r= 0.0; g= 0.0; b= 0.0; hue= 0.0; m1:printf ("HLS r,g,b= (%f %f %f) ? ", r,g,b); scanf ("%f%f%f", &r, &g, &b); ii= V_RGBHLS (r, g, b, &hue, &sat, &lig); printf ("V_RGBHLS: otw=%d hue=%f sat=%f lig=%f\n", ii, hue, sat, lig); ii= V_HLSRGB (&r1, &g1, &b1, hue, sat, lig); printf ("V_HLSRGB: otw=%d r=%f g=%f b=%f\n", ii, r1, g1, b1); goto m1; }