<출처: 마이크로소프트웨어>
/* List : ColorModel.c
If you want to compile with original C compiler,
you will convert from C++ comment type to C comment type. */
#include <stdio.h>
#include <conio.h>
#include "ColorModel.h"
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define UNDEFINED (0.0)
//////////////////////////////////////////////////////////////////////////////////
// RGB_To_Gray - RGB값을 Gray로 바꾼다.
//
// Gray 는 각각 [0,1]사이 값을 갖는다.
// R,G,B는 각각 [0,1]사이 값을 갖는다.
void RGB_To_Gray(double r, double g, double b, double *gray)
{
*gray = r * 0.30 + g * 0.59 + b * 0.11;
}
//////////////////////////////////////////////////////////////////////////////////
// Gray_To_RGB - Gray 값을 RGB로 바꾼다.
// 이과정은 promotion에 해당하는 과정으로 사실상 별의미가 없다.
// Gray 는 각각 [0,1]사이 값을 갖는다.
// R,G,B는 각각 [0,1]사이 값을 갖는다.
void Gray_To_RGB(double gray, double *r, double *g, double *b)
{
*r = *g = *b = gray;
}
//////////////////////////////////////////////////////////////////////////////////
// CMY_To_RGB - CMY값을 RGB로 바꾼다.
//
// R,G,B는 각각 [0,1]사이 값을 갖는다.
// C,M,Y는 각각 [0,1]사이 값을 갖는다.
void RGB_To_CMY(double r, double g, double b, double *c, double *m, double *y)
{
*c = 1.0 - r;
*m = 1.0 - g;
*y = 1.0 - b;
}
//////////////////////////////////////////////////////////////////////////////////
// CMY_To_RGB - CMY값을 RGB로 바꾼다.
//
// R,G,B는 각각 [0,1]사이 값을 갖는다.
// C,M,Y는 각각 [0,1]사이 값을 갖는다.
void CMY_To_RGB(double c, double m, double y, double *r, double *g, double *b)
{
*r = 1.0 - c;
*g = 1.0 - m;
*b = 1.0 - y;
}
//////////////////////////////////////////////////////////////////////////////////
// RGB_To_HSV - RGB값을 HSV로 바꾼다.
//
// R,G,B는 각각 [0,1]사이 값을 갖는다.
// H는 [0,360) 범위, S,V값은 각각 [0,1]범위를 갖는다.
void RGB_To_HSV(double r, double g, double b, double *h, double *s, double *v)
{
double max, min;
max = MAX(r,g);
max = MAX(max,b);
min = MIN(r,g);
min = MIN(min,b);
*v = max; // 명도(V) = max(r,g,b)
*s = (max != 0.0) ? (max-min)/max : 0.0; // 채도(S)을 계산, S=0이면 R=G=B=0
if(*s == 0.0)
*h = UNDEFINED;
else { // 채도(S)는 != 0
double delta = max - min; // 색상(H)를 구한다.
if(r == max)
*h = (g - b) / delta; // 색상이 Yello와 Magenta사이
else if( g == max)
*h = 2.0 + (b - r) / delta; // 색상이 Cyan와 Yello사이
else if( b == max)
*h = 4.0 + (r - g) / delta; // 색상이 Magenta와 Cyan사이
*h *= 60.0;
if(*h < 0.0) // 색상값을 각도로 바꾼다.
*h += 360.0;
}
}
//////////////////////////////////////////////////////////////////////////////////
// HSV_To_RGB - HSV값을 RGB로 바꾼다.
//
// H는 [0,360) 범위, S,V값은 각각 [0,1]범위를 갖는다.
// R,G,B는 각각 [0,1]값을 갖는다.
void HSV_To_RGB(double h, double s, double v, double *r, double *g, double *b)
{
if(s == 0.0) // 컬러값은 흑백명암값.
{
if(h == UNDEFINED) // 이경우 색상 값은 없다.
*r = *g = *b = v;
else
*r = *g = *b = UNDEFINED;
} else
{ // S != 0 이므로 색상(H)이 있다.
double f, p, q, t;
int i;
if(h == 360.0)
h = 0.0;
h /= 60.0; // H 값은 [0,360)사이 값
i = (int)h; // <=H 인 가장 큰 정수값
f = h - i; // F 는 H 의 실수 부분
p = v * (1.0 - s);
q = v * (1.0 - (s * f));
t = v * (1.0 - (s * (1.0 - f)));
switch(i)
{
case 0: *r = v; *g = t; *b = p; break;
case 1: *r = q; *g = v; *b = p; break;
case 2: *r = p; *g = v; *b = t; break;
case 3: *r = p; *g = q; *b = v; break;
case 4: *r = t; *g = p; *b = v; break;
case 5: *r = v; *g = p; *b = q; break;
}
}
}
//////////////////////////////////////////////////////////////////////////////////
// RGB_To_HLS - RGB값을 HLS로 바꾼다.
//
// R,G,B는 각각 [0,1]값을 갖는다.
// H는 [0,360) 범위, S,V값은 각각 [0,1]범위를 갖는다.
void RGB_To_HSL(double r, double g, double b, double *h, double *s, double *l)
{
double v;
double m;
double vm;
double r2, g2, b2;
v = MAX(r,g);
v = MAX(v,b);
m = MIN(r,g);
m = MIN(m,b);
if ((*l = (m + v) / 2.0) <= 0.0)
return;
if ((*s = vm = v - m) > 0.0) {
*s /= (*l <= 0.5) ? (v + m ) : (2.0 - v - m) ;
} else
return;
r2 = (v - r) / vm;
g2 = (v - g) / vm;
b2 = (v - b) / vm;
if (r == v)
*h = (g == m ? 5.0 + b2 : 1.0 - g2);
else if (g == v)
*h = (b == m ? 1.0 + r2 : 3.0 - b2);
else
*h = (r == m ? 3.0 + g2 : 5.0 - r2);
*h *= 60.0;
}
//////////////////////////////////////////////////////////////////////////////////
// HLS_To_RGB - HLS값을 RGB로 바꾼다.
//
// H는 [0,360) 범위, S,V값은 각각 [0,1]범위를 갖는다.
// R,G,B는 각각 [0,1]값을 갖는다.
void HSL_To_RGB(double h, double sl, double l, double *r, double *g, double *b)
{
double v;
v = (l <= 0.5) ? (l * (1.0 + sl)) : (l + sl - l * sl);
if (v <= 0) {
*r = *g = *b = 0.0;
} else
{
double m;
double sv;
int sextant;
double fract, vsf, mid1, mid2;
m = l + l - v;
sv = (v - m ) / v;
h /= 60.0;
sextant = (int)h;
fract = h - sextant;
vsf = v * sv * fract;
mid1 = m + vsf;
mid2 = v - vsf;
switch (sextant) {
case 0: *r = v; *g = mid1; *b = m; break;
case 1: *r = mid2; *g = v; *b = m; break;
case 2: *r = m; *g = v; *b = mid1; break;
case 3: *r = m; *g = mid2; *b = v; break;
case 4: *r = mid1; *g = m; *b = v; break;
case 5: *r = v; *g = m; *b = mid2; break;
}
}
}
// 간단한 테스트 프로그램
//
main()
{
double a, b, c;
RGB_To_HSV( 0.60, 0.20, 0.30, &a, &b, &c );
printf( "RGB(0.60, 0.20, 0.30) -> HSV(%.2f, %.2f, %.2f)\n", a, b, c );
HSV_To_RGB( 345.0, 0.67, 0.60, &a, &b, &c );
printf( "HLS(345.0, 0.67, 0.60) -> RGB(%.2f, %.2f, %.2f)\n", a, b, c );
RGB_To_HSL( 0.30, 0.40, 0.80, &a, &b, &c );
printf( "RGB(0.30, 0.40, 0.80) -> HSL(%.2f, %.2f, %.2f)\n", a, b, c );
HSL_To_RGB(228.0, 0.55, 0.56, &a, &b, &c );
printf( "HSL(228.0, 0.55, 0.56) -> RGB(%.2f, %.2f, %.2f)\n", a, b, c );
return 0;
}
-------------------------------------------------------------------------------------
/* List : ColorModel.h */
void RGB_To_Gray(double r, double g, double b, double *gray);
void Gray_To_RGB(double gray, double *r, double *g, double *b);
void RGB_To_CMY(double r, double g, double b, double *c, double *m, double *y);
void CMY_To_RGB(double c, double m, double y, double *r, double *g, double *b);
void RGB_To_HSV(double r, double g, double b, double *h, double *s, double *v);
void HSV_To_RGB(double h, double s, double v, double *r, double *g, double *b);
void RGB_To_HSL(double r, double g, double b, double *h, double *l, double *s);
void HSL_To_RGB(double h, double l, double s, double *r, double *g, double *b);
/* The End */