Line data Source code
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 : #include <gimage.h>
28 : #include <math.h>
29 : #include <string.h>
30 :
31 0 : void gRGB2HSL(struct hslrgb *col) {
32 : double mx, mn;
33 :
34 : /* Algorithm from http://en.wikipedia.org/wiki/HSL_color_space */
35 0 : if ( col->r>col->g ) {
36 0 : mx = ( col->r>col->b ) ? col->r : col->b;
37 0 : mn = ( col->g<col->b ) ? col->g : col->b;
38 : } else {
39 0 : mx = ( col->g>col->b ) ? col->g : col->b;
40 0 : mn = ( col->r<col->b ) ? col->r : col->b;
41 : }
42 0 : if ( mx==mn )
43 0 : col->h = 0;
44 0 : else if ( mx==col->r ) {
45 0 : col->h = fmod(60*(col->g-col->b)/(mx-mn),360);
46 0 : } else if ( mx==col->g ) {
47 0 : col->h = 60*(col->b-col->r)/(mx-mn) + 120;
48 : } else {
49 0 : col->h = 60*(col->r-col->g)/(mx-mn) + 240;
50 : }
51 0 : col->l = (mx+mn)/2;
52 0 : if ( mx==mn )
53 0 : col->s = 0;
54 0 : else if ( col->l<=.5 )
55 0 : col->s = (mx-mn)/(mx+mn);
56 : else
57 0 : col->s = (mx-mn)/(2-(mx+mn));
58 0 : col->hsl = true; col->hsv = false;
59 0 : }
60 :
61 0 : void gHSL2RGB(struct hslrgb *col) {
62 : double q,p,hk, ts[3], cs[3];
63 : int i;
64 :
65 : /* Algorithm from http://en.wikipedia.org/wiki/HSL_color_space */
66 0 : if ( col->l<.5 )
67 0 : q = col->l*(1 + col->s);
68 : else
69 0 : q = col->l+col->s - (col->l*col->s);
70 0 : p = 2*col->l - q;
71 0 : hk = fmod(col->h,360)/360;
72 0 : if ( hk<0 ) hk += 1.0;
73 0 : ts[0] = hk + 1./3.;
74 0 : ts[1] = hk;
75 0 : ts[2] = hk - 1./3.;
76 :
77 0 : for ( i=0; i<3; ++i ) {
78 0 : if ( ts[i]<0 ) ts[i] += 1.0;
79 0 : else if ( ts[i]>1 ) ts[i] -= 1.0;
80 0 : if ( ts[i]<1./6. )
81 0 : cs[i] = p + ((q-p)*6*ts[i]);
82 0 : else if ( ts[i]<.5 )
83 0 : cs[i] = q;
84 0 : else if ( ts[i]<2./3. )
85 0 : cs[i] = p + ((q-p)*6*(2./3.-ts[i]));
86 : else
87 0 : cs[i] = p;
88 : }
89 0 : col->r = cs[0];
90 0 : col->g = cs[1];
91 0 : col->b = cs[2];
92 0 : col->rgb = true;
93 0 : }
94 :
95 0 : void gRGB2HSV(struct hslrgb *col) {
96 : double mx, mn;
97 :
98 : /* Algorithm from http://en.wikipedia.org/wiki/HSL_color_space */
99 0 : if ( col->r>col->g ) {
100 0 : mx = ( col->r>col->b ) ? col->r : col->b;
101 0 : mn = ( col->g<col->b ) ? col->g : col->b;
102 : } else {
103 0 : mx = ( col->g>col->b ) ? col->g : col->b;
104 0 : mn = ( col->r<col->b ) ? col->r : col->b;
105 : }
106 0 : if ( mx==mn )
107 0 : col->h = 0;
108 0 : else if ( mx==col->r ) {
109 0 : col->h = fmod(60*(col->g-col->b)/(mx-mn),360);
110 0 : } else if ( mx==col->g ) {
111 0 : col->h = 60*(col->b-col->r)/(mx-mn) + 120;
112 : } else {
113 0 : col->h = 60*(col->r-col->g)/(mx-mn) + 240;
114 : }
115 0 : col->v = mx;
116 0 : if ( mx==0 )
117 0 : col->s = 0;
118 : else
119 0 : col->s = (mx-mn)/mx;
120 0 : col->hsv = true; col->hsl = false;
121 0 : }
122 :
123 0 : void gHSV2RGB(struct hslrgb *col) {
124 : double q,p,t,f;
125 : int h;
126 :
127 : /* Algorithm from http://en.wikipedia.org/wiki/HSL_color_space */
128 0 : h = ((int) floor(col->h/60)) % 6;
129 0 : if ( h<0 ) h+=6;
130 0 : f = col->h/60 - floor(col->h/60);
131 :
132 0 : p = col->v*(1-col->s);
133 0 : q = col->v*(1-f*col->s);
134 0 : t = col->v*(1-(1-f)*col->s);
135 :
136 0 : if ( h==0 ) {
137 0 : col->r = col->v; col->g = t; col->b = p;
138 0 : } else if ( h==1 ) {
139 0 : col->r = q; col->g = col->v; col->b = p;
140 0 : } else if ( h==2 ) {
141 0 : col->r = p; col->g = col->v; col->b = t;
142 0 : } else if ( h==3 ) {
143 0 : col->r = p; col->g = q; col->b = col->v;
144 0 : } else if ( h==4 ) {
145 0 : col->r = t; col->g = p; col->b = col->v;
146 0 : } else if ( h==5 ) {
147 0 : col->r = col->v; col->g = p; col->b = q;
148 : }
149 0 : col->rgb = true;
150 0 : }
151 :
152 0 : Color gHslrgb2Color(struct hslrgb *col) {
153 0 : if ( !col->rgb ) {
154 0 : if ( col->hsv )
155 0 : gHSV2RGB(col);
156 0 : else if ( col->hsl )
157 0 : gHSL2RGB(col);
158 : else
159 0 : return( COLOR_UNKNOWN );
160 : }
161 0 : return( (((int) rint(255.*col->r))<<16 ) | \
162 0 : (((int) rint(255.*col->g))<<8 ) | \
163 0 : (((int) rint(255.*col->b)) ) );
164 : }
165 :
166 0 : Color gHslrgba2Color(struct hslrgba *col) {
167 0 : if ( !col->rgb ) {
168 0 : if ( col->hsv )
169 0 : gHSV2RGB((struct hslrgb *) col);
170 0 : else if ( col->hsl )
171 0 : gHSL2RGB((struct hslrgb *) col);
172 : else
173 0 : return( COLOR_UNKNOWN );
174 : }
175 0 : if ( !col->has_alpha || col->alpha==1.0 )
176 0 : return( (((int) rint(255.*col->r))<<16 ) | \
177 0 : (((int) rint(255.*col->g))<<8 ) | \
178 0 : (((int) rint(255.*col->b)) ) );
179 0 : else if ( col->alpha==0.0 )
180 0 : return( COLOR_TRANSPARENT );
181 : else
182 0 : return( (((int) rint(255.*col->alpha))<<24 ) | \
183 0 : (((int) rint(255.*col->r))<<16) | \
184 0 : (((int) rint(255.*col->g))<<8 ) | \
185 0 : (((int) rint(255.*col->b)) ) );
186 : }
187 :
188 0 : void gColor2Hslrgb(struct hslrgb *col,Color from) {
189 0 : col->rgb = true;
190 0 : col->r = ((from>>16)&0xff)/255.0;
191 0 : col->g = ((from>>8 )&0xff)/255.0;
192 0 : col->b = ((from )&0xff)/255.0;
193 0 : col->hsl = col->hsv = false;
194 0 : }
195 :
196 0 : void gColor2Hslrgba(struct hslrgba *col,Color from) {
197 0 : if ( from == COLOR_TRANSPARENT ) {
198 0 : memset(col,0,sizeof(*col));
199 0 : col->has_alpha = 1;
200 : } else {
201 0 : col->alpha = ((from>>24)&0xff)/255.0;
202 0 : col->r = ((from>>16)&0xff)/255.0;
203 0 : col->g = ((from>>8 )&0xff)/255.0;
204 0 : col->b = ((from )&0xff)/255.0;
205 0 : col->hsl = col->hsv = false;
206 0 : col->has_alpha = col->alpha!=0;
207 0 : if ( !col->has_alpha )
208 0 : col->alpha = 1.0;
209 : }
210 0 : col->rgb = true;
211 0 : }
|