/* * Convert a color from RGB specification to HLS specification * * The code in this file includes: * * The program described in figure 13.36, page 595 of: * _Computer Graphics: Principles and Practice_, * 2nd edition, (1990), by * J.D. Foley, A. van Dam, S.K. Feiner, and J.F. Hughes * Addison-Wesley Publishing Company * ISBN: 0-201-12110-7 * */ /* HISTORY: * Date Pro Spec Rev Prgmr Description * ------- ------------ ----- ----------- * 03Jan91 tbb Initial implementation as per the text. */ #include "stdio.h" #include "ctype.h" #include "math.h" #define ML_MIN(a,b) (((a)<(b))?(a):(b)) #define ML_MAX(a,b) (((a)>(b))?(a):(b)) static void aux_rgb_to_hls (r, g, b, h, l, s) float *r; /* IN Red value (0.0 <= r <= 1.0) */ float *g; /* IN Green value (0.0 <= g <= 1.0) */ float *b; /* IN Blue value (0.0 <= b <= 1.0) */ float *h; /* OUT Hue (0.0 <= h < 360.0)*/ float *l; /* OUT Lightness (0.0 <= l <= 1.0) */ float *s; /* OUT Saturation (0.0 <= s <= 1.0) */ /* * If s == 0, then h is undefined. * * The procedure described in Foley & van Dam places red at 0 degrees of * hue angle, whereas DIGITAL VT3xx terminals place blue at 0 degrees. * This routine has blue at 0 degrees. */ { /* Reference: figure 13.36, page 595 of Foley & van Dam */ float maxval; float minval; float delta; maxval = ML_MAX (*r, ML_MAX (*g, *b)); minval = ML_MIN (*r, ML_MIN (*g, *b)); *l = (maxval + minval) / 2.0; /* This is the lightness value. */ if (maxval == minval) { /* * Achromatic case, because r==g==b */ *s = 0.0; *h = -1.0; /* The Hue is UNDEFINED in this case. */ } else { /* * Chromatic case. */ /* Calculate the saturation. */ if (*l <= 0.5) { *s = (maxval - minval) / (maxval + minval); } else { *s = (maxval - minval) / (2.0 - maxval - minval); } /* Calculate the hue. */ delta = maxval - minval; if (*r == maxval) { /* The resulting color is between yellow and magenta. */ *h = (*g - *b) / delta; } else { if (*g == maxval) { /* The resulting color is between cyan and yellow. */ *h = 2.0 + (*b - *r) / delta; } else { if (*b == maxval) { /* The resulting color is between magenta and cyan. */ *h = 4.0 + (*r - *g) / delta; } } } *h = *h * 60.0; /* Convert to degrees */ *h = *h - 240.0; /* Subtract to shift from Red at */ /* zero hue to Blue at zero hue. */ while (*h < 0.0) { /* Be sure 0.0 <= hue <= 360.0 */ *h = *h + 360.0; } while (*h > 360.0) { *h = *h - 360.0; } } /* End else Chromatic case.*/ } /* End of aux_rgb_to_hls routine. */ int main (argc, argv) int argc; char **argv; { float red, green, blue; float hue, lightness, saturation; /* Test cases */ /* Convert BLUE */ red = (float) 0x00; green = (float) 0x00; blue = (float) 0xFF; (void) fprintf (stdout, "\nInput RGB value is: %X%X%X\n", (int) red, (int) green, (int) blue); red = red / 0xFF; /* Convert to percentages. */ green = green / 0xFF; blue = blue / 0xFF; aux_rgb_to_hls (&red, &green, &blue, &hue, &lightness, &saturation); (void) fprintf (stdout, "Output HLS value is: Hue = %f Lightness = %f Saturation =%f\n", hue, lightness, saturation); /* Convert RED */ red = (float) 0xFF; green = (float) 0x00; blue = (float) 0x00; (void) fprintf (stdout, "\nInput RGB value is: %X%X%X\n", (int) red, (int) green, (int) blue); red = red / 0xFF; /* Convert to percentages. */ green = green / 0xFF; blue = blue / 0xFF; aux_rgb_to_hls (&red, &green, &blue, &hue, &lightness, &saturation); (void) fprintf (stdout, "Output HLS value is: Hue = %f Lightness = %f Saturation =%f\n", hue, lightness, saturation); /* Convert GREEN */ red = (float) 0x00; green = (float) 0xFF; blue = (float) 0x00; (void) fprintf (stdout, "\nInput RGB value is: %X%X%X\n", (int) red, (int) green, (int) blue); red = red / 0xFF; /* Convert to percentages. */ green = green / 0xFF; blue = blue / 0xFF; aux_rgb_to_hls (&red, &green, &blue, &hue, &lightness, &saturation); (void) fprintf (stdout, "Output HLS value is: Hue = %f Lightness = %f Saturation =%f\n", hue, lightness, saturation); /* End of test cases: */ /* Convert terra cotta (0xC86446) */ red = (float) 0xC8; green = (float) 0x64; blue = (float) 0x46; (void) fprintf (stdout, "\nInput RGB value is: %X%X%X\n", (int) red, (int) green, (int) blue); red = red / 0xFF; /* Convert to percentages. */ green = green / 0xFF; blue = blue / 0xFF; aux_rgb_to_hls (&red, &green, &blue, &hue, &lightness, &saturation); (void) fprintf (stdout, "Output HLS value is: Hue = %f Lightness = %f Saturation =%f\n", hue, lightness, saturation); /* Convert gray (0xAAAA96)*/ red = (float) 0xAA; green = (float) 0xAA; blue = (float) 0x96; (void) fprintf (stdout, "\nInput RGB value is: %X%X%X\n", (int) red, (int) green, (int) blue); red = red / 0xFF; /* Convert to percentages. */ green = green / 0xFF; blue = blue / 0xFF; aux_rgb_to_hls (&red, &green, &blue, &hue, &lightness, &saturation); (void) fprintf (stdout, "Output HLS value is: Hue = %f Lightness = %f Saturation =%f\n", hue, lightness, saturation); } /* End of main RGB2HLS.C routine.*/