// Program: RGB <-> HSI conversion program
// File: rgb2hsi.c / hsi2rgb.c
// Description: Convert between RGB and HSI format
// Author: Leiming Qian <lqian@uiuc.edu> (LQ)
// Environment: ANSI C++
// Notes: C++ version of the Javascript conversion code in
// http://www.ndirect.co.uk/~thomas.green/
// javascripts/hexAndRGB.html
// REvisions: 1.0 09/01/01 (LQ) first release
// first make sure we have enough arguments
if (argc!=4) {
cout << "Usage: rgb2hsi R G B" << endl;
cout << " or hsi2rgb H S I" << endl;
return(1);
}
// next determine if we are calling RGB2HSI or HSI2RGB
if ( strstr(argv[0], "rgb2hsi") != NULL ) {
// RGB to HSI
R = atof(argv[1]);
G = atof(argv[2]);
B = atof(argv[3]);
if (R<0 || R>255 || G<0 || G>255 || B<0 || B>255) {
cout << "Value out of range!" << endl;
return(1);
}
// find out the min, mid, and max of R, G, B
double min, mid, max;
if (R>G && R>B) {
max = R;
mid = MAX(G, B);
min = MIN(G, B);
}
else {
if (G>B) {
max = G;
mid = MAX(R, B);
min = MIN(R, B);
}
else {
max = B;
mid = MAX(R, G);
min = MIN(R, G);
}
}
I = max / 255;
S = 0;
H = 0;
if (I==0 || max==min) {
// this is a black image or grayscale image
S = 0;
H = 0;
}
else {
S = (I - min/255) / I;
// domains are 60 degrees of
// red, yellow, green, cyan, blue or magenta
double domainBase = 0.0;
double oneSixth = 1.0/6.0;
double domainOffset = ( (mid-min) / (max-min) ) / 6.0;
if (R==max) {
if (mid==G) { // green is ascending
domainBase = 0; // red domain
}
else { // blue is descending
domainBase = 5.0/6.0; // magenta domain
domainOffset = oneSixth - domainOffset;
}
}
else {
if (G==max) {
if (mid==B) { // blue is ascending
domainBase = 2.0/6.0; // green domain
}
else { // red is ascending
domainBase = 1.0/6.0; // yellow domain
domainOffset = oneSixth - domainOffset;
}
}
else {
if (mid==R) { // red is ascending
domainBase = 4.0/6.0; // blue domain
}
else { // green is descending
domainBase = 3.0/6.0; // cyan domain
domainOffset = oneSixth - domainOffset;
}
}
}
H = domainBase + domainOffset;
}
cout << "H = " << H << "\t";
cout << "S = " << S << "\t";
cout << "I = " << I << "\n";
}
else {
// HSI to RGB
H = atof(argv[1]);
S = atof(argv[2]);
I = atof(argv[3]);
if (H<0 || H>1 || S<0 || S>1) {
cout << "Value out of range!" << endl;
return(1);
}
if (I==0.0) {
// black image
R = G = B = 0;
}
else {
if (S==0.0) {
// grayscale image
R = G = B = I;
}
else {
double domainOffset = 0.0;
if (H<1.0/6.0) { // red domain; green acending
domainOffset = H;
R = I;
B = I * (1-S);
G = B + (I-B)*domainOffset*6;
}
else {
if (H<2.0/6) { // yellow domain; red acending
domainOffset = H - 1.0/6.0;
G = I;
B = I * (1-S);
R = G - (I-B)*domainOffset*6;
}
else {
if (H<3.0/6) { // green domain; blue descending
domainOffset = H-2.0/6;
G = I;
R = I * (1-S);
B = R + (I-R)*domainOffset * 6;
}
else {
if (H<4.0/6) { // cyan domain, green acsending
domainOffset = H - 3.0/6;
B = I;
R = I * (1-S);
G = B - (I-R) * domainOffset * 6;
}
else {
if (H<5.0/6) { // blue domain, red ascending
domainOffset = H - 4.0/6;
B = I;
G = I * (1-S);
R = G + (I-G) * domainOffset * 6;
}
else { // magenta domain, blue descending
domainOffset = H - 5.0/6;
R = I;
G = I * (1-S);
B = R - (I-G) * domainOffset * 6;
}
}
}
}
}
}
}
R = RINT(R*255);
G = RINT(G*255);
B = RINT(B*255);
cout << "R = " << R << "\t";
cout << "G = " << G << "\t";
cout << "B = " << B << "\n";
}
Bookmarks