synfig-studio  1.0.3
helpers.hpp
Go to the documentation of this file.
1 /* brushlib - The MyPaint Brush Library
2  * Copyright (C) 2007-2008 Martin Renold <martinxyz@gmx.ch>
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #ifndef __helpers_h__
18 #define __helpers_h__
19 
20 #include <glib.h>
21 #include <assert.h>
22 
23 // MAX, MIN, ABS, CLAMP are already available from gmacros.h
24 #define ROUND(x) ((int) ((x) + 0.5))
25 #define SIGN(x) ((x)>0?1:(-1))
26 #define SQR(x) ((x)*(x))
27 
28 #define MAX3(a, b, c) ((a)>(b)?MAX((a),(c)):MAX((b),(c)))
29 #define MIN3(a, b, c) ((a)<(b)?MIN((a),(c)):MIN((b),(c)))
30 
31 namespace brushlib {
32 
33 typedef struct { int x, y, w, h; } Rect;
34 // originally from my mass project (mass.sourceforge.net)
35 void ExpandRectToIncludePoint(Rect * r, int x, int y)
36 {
37  if (r->w == 0) {
38  r->w = 1; r->h = 1;
39  r->x = x; r->y = y;
40  } else {
41  if (x < r->x) { r->w += r->x-x; r->x = x; } else
42  if (x >= r->x+r->w) { r->w = x - r->x + 1; }
43 
44  if (y < r->y) { r->h += r->y-y; r->y = y; } else
45  if (y >= r->y+r->h) { r->h = y - r->y + 1; }
46  }
47 }
48 
49 // Optimized version from one in GIMP (noisify.c), where it was
50 // adapted from ppmforge.c, which is part of PBMPLUS. The algorithm
51 // comes from: 'The Science Of Fractal Images'. Peitgen, H.-O., and
52 // Saupe, D. eds. Springer Verlag, New York, 1988.
53 float rand_gauss (GRand * rng)
54 {
55  float sum = 0.0;
56  uint32_t rand1 = g_rand_int(rng);
57  uint32_t rand2 = g_rand_int(rng);
58  sum += rand1 & 0x7FFF;
59  sum += (rand1 >> 16) & 0x7FFF;
60  sum += rand2 & 0x7FFF;
61  sum += (rand2 >> 16) & 0x7FFF;
62  return sum * 5.28596089837e-5 - 3.46410161514;
63 }
64 
65 // stolen from GIMP (gimpcolorspace.c)
66 // (from gimp_rgb_to_hsv)
67 void
68 rgb_to_hsv_float (float *r_ /*h*/, float *g_ /*s*/, float *b_ /*v*/)
69 {
70  float max, min, delta;
71  float h, s, v;
72  float r, g, b;
73 
74  h = 0.0; // silence gcc warning
75 
76  r = *r_;
77  g = *g_;
78  b = *b_;
79 
80  r = CLAMP(r, 0.0, 1.0);
81  g = CLAMP(g, 0.0, 1.0);
82  b = CLAMP(b, 0.0, 1.0);
83 
84  max = MAX3(r, g, b);
85  min = MIN3(r, g, b);
86 
87  v = max;
88  delta = max - min;
89 
90  if (delta > 0.0001)
91  {
92  s = delta / max;
93 
94  if (r == max)
95  {
96  h = (g - b) / delta;
97  if (h < 0.0)
98  h += 6.0;
99  }
100  else if (g == max)
101  {
102  h = 2.0 + (b - r) / delta;
103  }
104  else if (b == max)
105  {
106  h = 4.0 + (r - g) / delta;
107  }
108 
109  h /= 6.0;
110  }
111  else
112  {
113  s = 0.0;
114  h = 0.0;
115  }
116 
117  *r_ = h;
118  *g_ = s;
119  *b_ = v;
120 }
121 
122 // (from gimp_hsv_to_rgb)
123 void
124 hsv_to_rgb_float (float *h_, float *s_, float *v_)
125 {
126  gint i;
127  gdouble f, w, q, t;
128  float h, s, v;
129  float r, g, b;
130  r = g = b = 0.0; // silence gcc warning
131 
132  h = *h_;
133  s = *s_;
134  v = *v_;
135 
136  h = h - floor(h);
137  s = CLAMP(s, 0.0, 1.0);
138  v = CLAMP(v, 0.0, 1.0);
139 
140  gdouble hue;
141 
142  if (s == 0.0)
143  {
144  r = v;
145  g = v;
146  b = v;
147  }
148  else
149  {
150  hue = h;
151 
152  if (hue == 1.0)
153  hue = 0.0;
154 
155  hue *= 6.0;
156 
157  i = (gint) hue;
158  f = hue - i;
159  w = v * (1.0 - s);
160  q = v * (1.0 - (s * f));
161  t = v * (1.0 - (s * (1.0 - f)));
162 
163  switch (i)
164  {
165  case 0:
166  r = v;
167  g = t;
168  b = w;
169  break;
170  case 1:
171  r = q;
172  g = v;
173  b = w;
174  break;
175  case 2:
176  r = w;
177  g = v;
178  b = t;
179  break;
180  case 3:
181  r = w;
182  g = q;
183  b = v;
184  break;
185  case 4:
186  r = t;
187  g = w;
188  b = v;
189  break;
190  case 5:
191  r = v;
192  g = w;
193  b = q;
194  break;
195  }
196  }
197 
198  *h_ = r;
199  *s_ = g;
200  *v_ = b;
201 }
202 
203 // (from gimp_rgb_to_hsl)
204 void
205 rgb_to_hsl_float (float *r_, float *g_, float *b_)
206 {
207  gdouble max, min, delta;
208 
209  float h, s, l;
210  float r, g, b;
211 
212  // silence gcc warnings
213  h=0;
214 
215  r = *r_;
216  g = *g_;
217  b = *b_;
218 
219  r = CLAMP(r, 0.0, 1.0);
220  g = CLAMP(g, 0.0, 1.0);
221  b = CLAMP(b, 0.0, 1.0);
222 
223  max = MAX3(r, g, b);
224  min = MIN3(r, g, b);
225 
226  l = (max + min) / 2.0;
227 
228  if (max == min)
229  {
230  s = 0.0;
231  h = 0.0; //GIMP_HSL_UNDEFINED;
232  }
233  else
234  {
235  if (l <= 0.5)
236  s = (max - min) / (max + min);
237  else
238  s = (max - min) / (2.0 - max - min);
239 
240  delta = max - min;
241 
242  if (delta == 0.0)
243  delta = 1.0;
244 
245  if (r == max)
246  {
247  h = (g - b) / delta;
248  }
249  else if (g == max)
250  {
251  h = 2.0 + (b - r) / delta;
252  }
253  else if (b == max)
254  {
255  h = 4.0 + (r - g) / delta;
256  }
257 
258  h /= 6.0;
259 
260  if (h < 0.0)
261  h += 1.0;
262  }
263 
264  *r_ = h;
265  *g_ = s;
266  *b_ = l;
267 }
268 
269 static double
270 hsl_value (gdouble n1,
271  gdouble n2,
272  gdouble hue)
273 {
274  gdouble val;
275 
276  if (hue > 6.0)
277  hue -= 6.0;
278  else if (hue < 0.0)
279  hue += 6.0;
280 
281  if (hue < 1.0)
282  val = n1 + (n2 - n1) * hue;
283  else if (hue < 3.0)
284  val = n2;
285  else if (hue < 4.0)
286  val = n1 + (n2 - n1) * (4.0 - hue);
287  else
288  val = n1;
289 
290  return val;
291 }
292 
293 
301 void
302 hsl_to_rgb_float (float *h_, float *s_, float *l_)
303 {
304  float h, s, l;
305  float r, g, b;
306 
307  h = *h_;
308  s = *s_;
309  l = *l_;
310 
311  h = h - floor(h);
312  s = CLAMP(s, 0.0, 1.0);
313  l = CLAMP(l, 0.0, 1.0);
314 
315  if (s == 0)
316  {
317  /* achromatic case */
318  r = l;
319  g = l;
320  b = l;
321  }
322  else
323  {
324  gdouble m1, m2;
325 
326  if (l <= 0.5)
327  m2 = l * (1.0 + s);
328  else
329  m2 = l + s - l * s;
330 
331  m1 = 2.0 * l - m2;
332 
333  r = hsl_value (m1, m2, h * 6.0 + 2.0);
334  g = hsl_value (m1, m2, h * 6.0);
335  b = hsl_value (m1, m2, h * 6.0 - 2.0);
336  }
337 
338  *h_ = r;
339  *s_ = g;
340  *l_ = b;
341 }
342 
343 }
344 #endif