1 /* Copyright (C) 1994, 1997, 1998 Aladdin Enterprises. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: gshsb.c,v 1.5 2002/06/16 05:48:55 lpd Exp $ */
18 /* HSB color operators for Ghostscript library */
19 #include "gx.h"
20 #include "gscolor.h"
21 #include "gshsb.h" /* interface definition */
22 #include "gxfrac.h"
23
24 /* Forward references */
25 private void color_hsb_to_rgb(floatp h, floatp s, floatp b, float rgb[3]);
26 private void color_rgb_to_hsb(floatp r, floatp g, floatp b, float hsb[3]);
27
28 /* Force a parameter into the range [0.0..1.0]. */
29 #define force_unit(p) (p < 0.0 ? 0.0 : p > 1.0 ? 1.0 : p)
30
31 /* sethsbcolor */
32 int
gs_sethsbcolor(gs_state * pgs,floatp h,floatp s,floatp b)33 gs_sethsbcolor(gs_state * pgs, floatp h, floatp s, floatp b)
34 {
35 float rgb[3];
36
37 color_hsb_to_rgb(force_unit(h), force_unit(s), force_unit(b), rgb);
38 return gs_setrgbcolor(pgs, rgb[0], rgb[1], rgb[2]);
39 }
40
41 /* currenthsbcolor */
42 int
gs_currenthsbcolor(const gs_state * pgs,float pr3[3])43 gs_currenthsbcolor(const gs_state * pgs, float pr3[3])
44 {
45 float rgb[3];
46
47 gs_currentrgbcolor(pgs, rgb);
48 color_rgb_to_hsb(rgb[0], rgb[1], rgb[2], pr3);
49 return 0;
50 }
51
52 /* ------ Internal routines ------ */
53
54 /* Note: the color model conversion algorithms are taken from */
55 /* Rogers, Procedural Elements for Computer Graphics, pp. 401-403. */
56
57 /* Convert RGB to HSB. */
58 private void
color_rgb_to_hsb(floatp r,floatp g,floatp b,float hsb[3])59 color_rgb_to_hsb(floatp r, floatp g, floatp b, float hsb[3])
60 {
61 frac red = float2frac(r), green = float2frac(g), blue = float2frac(b);
62
63 #define rhue hsb[0]
64 #define rsat hsb[1]
65 #define rbri hsb[2]
66 if (red == green && green == blue) {
67 rhue = 0; /* arbitrary */
68 rsat = 0;
69 rbri = r; /* pick any one */
70 } else { /* Convert rgb to hsb */
71 frac V, Temp, diff;
72 long H;
73
74 V = (red > green ? red : green);
75 if (blue > V)
76 V = blue;
77 Temp = (red > green ? green : red);
78 if (blue < Temp)
79 Temp = blue;
80 diff = V - Temp;
81 if (V == red)
82 H = (green - blue) * frac_1_long / diff;
83 else if (V == green)
84 H = (blue - red) * frac_1_long / diff + 2 * frac_1_long;
85 else /* V == blue */
86 H = (red - green) * frac_1_long / diff + 4 * frac_1_long;
87 if (H < 0)
88 H += 6 * frac_1_long;
89 rhue = H / (frac_1 * 6.0);
90 rsat = diff / (float)V;
91 rbri = frac2float(V);
92 }
93 #undef rhue
94 #undef rsat
95 #undef rbri
96 }
97
98 /* Convert HSB to RGB. */
99 private void
color_hsb_to_rgb(floatp hue,floatp saturation,floatp brightness,float rgb[3])100 color_hsb_to_rgb(floatp hue, floatp saturation, floatp brightness, float rgb[3])
101 {
102 if (saturation == 0) {
103 rgb[0] = rgb[1] = rgb[2] = brightness;
104 } else { /* Convert hsb to rgb. */
105 /* We rely on the fact that the product of two */
106 /* fracs fits into an unsigned long. */
107 floatp h6 = hue * 6;
108 ulong V = float2frac(brightness); /* force arithmetic to long */
109 frac S = float2frac(saturation);
110 int I = (int)h6;
111 ulong F = float2frac(h6 - I); /* ditto */
112
113 /* M = V*(1-S), N = V*(1-S*F), K = V*(1-S*(1-F)) = M-N+V */
114 frac M = V * (frac_1_long - S) / frac_1_long;
115 frac N = V * (frac_1_long - S * F / frac_1_long) / frac_1_long;
116 frac K = M - N + V;
117 frac R, G, B;
118
119 switch (I) {
120 default:
121 R = V;
122 G = K;
123 B = M;
124 break;
125 case 1:
126 R = N;
127 G = V;
128 B = M;
129 break;
130 case 2:
131 R = M;
132 G = V;
133 B = K;
134 break;
135 case 3:
136 R = M;
137 G = N;
138 B = V;
139 break;
140 case 4:
141 R = K;
142 G = M;
143 B = V;
144 break;
145 case 5:
146 R = V;
147 G = M;
148 B = N;
149 break;
150 }
151 rgb[0] = frac2float(R);
152 rgb[1] = frac2float(G);
153 rgb[2] = frac2float(B);
154 #ifdef DEBUG
155 if (gs_debug_c('c')) {
156 dlprintf7("[c]hsb(%g,%g,%g)->VSFI(%ld,%d,%ld,%d)->\n",
157 hue, saturation, brightness, V, S, F, I);
158 dlprintf6(" RGB(%d,%d,%d)->rgb(%g,%g,%g)\n",
159 R, G, B, rgb[0], rgb[1], rgb[2]);
160 }
161 #endif
162 }
163 }
164