1 /* Copyright (C) 2008-2012 by George Williams */
2 /*
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are met:
5
6 * Redistributions of source code must retain the above copyright notice, this
7 * list of conditions and the following disclaimer.
8
9 * Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
12
13 * The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include <fontforge-config.h>
29
30 #include "gimage.h"
31
32 #include <math.h>
33 #include <string.h>
34
gRGB2HSL(struct hslrgb * col)35 void gRGB2HSL(struct hslrgb *col) {
36 double mx, mn;
37
38 /* Algorithm from http://en.wikipedia.org/wiki/HSL_color_space */
39 if ( col->r>col->g ) {
40 mx = ( col->r>col->b ) ? col->r : col->b;
41 mn = ( col->g<col->b ) ? col->g : col->b;
42 } else {
43 mx = ( col->g>col->b ) ? col->g : col->b;
44 mn = ( col->r<col->b ) ? col->r : col->b;
45 }
46 if ( mx==mn )
47 col->h = 0;
48 else if ( mx==col->r ) {
49 col->h = fmod(60*(col->g-col->b)/(mx-mn),360);
50 } else if ( mx==col->g ) {
51 col->h = 60*(col->b-col->r)/(mx-mn) + 120;
52 } else {
53 col->h = 60*(col->r-col->g)/(mx-mn) + 240;
54 }
55 col->l = (mx+mn)/2;
56 if ( mx==mn )
57 col->s = 0;
58 else if ( col->l<=.5 )
59 col->s = (mx-mn)/(mx+mn);
60 else
61 col->s = (mx-mn)/(2-(mx+mn));
62 col->hsl = true; col->hsv = false;
63 }
64
gHSL2RGB(struct hslrgb * col)65 void gHSL2RGB(struct hslrgb *col) {
66 double q,p,hk, ts[3], cs[3];
67 int i;
68
69 /* Algorithm from http://en.wikipedia.org/wiki/HSL_color_space */
70 if ( col->l<.5 )
71 q = col->l*(1 + col->s);
72 else
73 q = col->l+col->s - (col->l*col->s);
74 p = 2*col->l - q;
75 hk = fmod(col->h,360)/360;
76 if ( hk<0 ) hk += 1.0;
77 ts[0] = hk + 1./3.;
78 ts[1] = hk;
79 ts[2] = hk - 1./3.;
80
81 for ( i=0; i<3; ++i ) {
82 if ( ts[i]<0 ) ts[i] += 1.0;
83 else if ( ts[i]>1 ) ts[i] -= 1.0;
84 if ( ts[i]<1./6. )
85 cs[i] = p + ((q-p)*6*ts[i]);
86 else if ( ts[i]<.5 )
87 cs[i] = q;
88 else if ( ts[i]<2./3. )
89 cs[i] = p + ((q-p)*6*(2./3.-ts[i]));
90 else
91 cs[i] = p;
92 }
93 col->r = cs[0];
94 col->g = cs[1];
95 col->b = cs[2];
96 col->rgb = true;
97 }
98
gRGB2HSV(struct hslrgb * col)99 void gRGB2HSV(struct hslrgb *col) {
100 double mx, mn;
101
102 /* Algorithm from http://en.wikipedia.org/wiki/HSL_color_space */
103 if ( col->r>col->g ) {
104 mx = ( col->r>col->b ) ? col->r : col->b;
105 mn = ( col->g<col->b ) ? col->g : col->b;
106 } else {
107 mx = ( col->g>col->b ) ? col->g : col->b;
108 mn = ( col->r<col->b ) ? col->r : col->b;
109 }
110 if ( mx==mn )
111 col->h = 0;
112 else if ( mx==col->r ) {
113 col->h = fmod(60*(col->g-col->b)/(mx-mn),360);
114 } else if ( mx==col->g ) {
115 col->h = 60*(col->b-col->r)/(mx-mn) + 120;
116 } else {
117 col->h = 60*(col->r-col->g)/(mx-mn) + 240;
118 }
119 col->v = mx;
120 if ( mx==0 )
121 col->s = 0;
122 else
123 col->s = (mx-mn)/mx;
124 col->hsv = true; col->hsl = false;
125 }
126
gHSV2RGB(struct hslrgb * col)127 void gHSV2RGB(struct hslrgb *col) {
128 double q,p,t,f;
129 int h;
130
131 /* Algorithm from http://en.wikipedia.org/wiki/HSL_color_space */
132 h = ((int) floor(col->h/60)) % 6;
133 if ( h<0 ) h+=6;
134 f = col->h/60 - floor(col->h/60);
135
136 p = col->v*(1-col->s);
137 q = col->v*(1-f*col->s);
138 t = col->v*(1-(1-f)*col->s);
139
140 if ( h==0 ) {
141 col->r = col->v; col->g = t; col->b = p;
142 } else if ( h==1 ) {
143 col->r = q; col->g = col->v; col->b = p;
144 } else if ( h==2 ) {
145 col->r = p; col->g = col->v; col->b = t;
146 } else if ( h==3 ) {
147 col->r = p; col->g = q; col->b = col->v;
148 } else if ( h==4 ) {
149 col->r = t; col->g = p; col->b = col->v;
150 } else if ( h==5 ) {
151 col->r = col->v; col->g = p; col->b = q;
152 }
153 col->rgb = true;
154 }
155
gHslrgb2Color(struct hslrgb * col)156 Color gHslrgb2Color(struct hslrgb *col) {
157 if ( !col->rgb ) {
158 if ( col->hsv )
159 gHSV2RGB(col);
160 else if ( col->hsl )
161 gHSL2RGB(col);
162 else
163 return( COLOR_UNKNOWN );
164 }
165 return( (((int) rint(255.*col->r))<<16 ) | \
166 (((int) rint(255.*col->g))<<8 ) | \
167 (((int) rint(255.*col->b)) ) );
168 }
169
gHslrgba2Color(struct hslrgba * col)170 Color gHslrgba2Color(struct hslrgba *col) {
171 if ( !col->rgb ) {
172 if ( col->hsv )
173 gHSV2RGB((struct hslrgb *) col);
174 else if ( col->hsl )
175 gHSL2RGB((struct hslrgb *) col);
176 else
177 return( COLOR_UNKNOWN );
178 }
179 if ( !col->has_alpha || col->alpha==1.0 )
180 return( (((int) rint(255.*col->r))<<16 ) | \
181 (((int) rint(255.*col->g))<<8 ) | \
182 (((int) rint(255.*col->b)) ) );
183 else if ( col->alpha==0.0 )
184 return( COLOR_TRANSPARENT );
185 else
186 return( (((int) rint(255.*col->alpha))<<24 ) | \
187 (((int) rint(255.*col->r))<<16) | \
188 (((int) rint(255.*col->g))<<8 ) | \
189 (((int) rint(255.*col->b)) ) );
190 }
191
gColor2Hslrgb(struct hslrgb * col,Color from)192 void gColor2Hslrgb(struct hslrgb *col,Color from) {
193 col->rgb = true;
194 col->r = ((from>>16)&0xff)/255.0;
195 col->g = ((from>>8 )&0xff)/255.0;
196 col->b = ((from )&0xff)/255.0;
197 col->hsl = col->hsv = false;
198 }
199
gColor2Hslrgba(struct hslrgba * col,Color from)200 void gColor2Hslrgba(struct hslrgba *col,Color from) {
201 if ( from == COLOR_TRANSPARENT ) {
202 memset(col,0,sizeof(*col));
203 col->has_alpha = 1;
204 } else {
205 col->alpha = ((from>>24)&0xff)/255.0;
206 col->r = ((from>>16)&0xff)/255.0;
207 col->g = ((from>>8 )&0xff)/255.0;
208 col->b = ((from )&0xff)/255.0;
209 col->hsl = col->hsv = false;
210 col->has_alpha = col->alpha!=0;
211 if ( !col->has_alpha )
212 col->alpha = 1.0;
213 }
214 col->rgb = true;
215 }
216