1 /* LIBGIMP - The GIMP Library
2 * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
3 *
4 * This library is free software: you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 3 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see
16 * <https://www.gnu.org/licenses/>.
17 */
18
19 #include "config.h"
20
21 #include <babl/babl.h>
22 #include <glib-object.h>
23
24 #include "libgimpmath/gimpmath.h"
25
26 #include "gimpcolortypes.h"
27
28 #include "gimpcolorspace.h"
29 #include "gimprgb.h"
30 #include "gimphsv.h"
31
32
33
34 /**
35 * SECTION: gimpcolorspace
36 * @title: GimpColorSpace
37 * @short_description: Utility functions which convert colors between
38 * different color models.
39 *
40 * When programming pixel data manipulation functions you will often
41 * use algorithms operating on a color model different from the one
42 * GIMP uses. This file provides utility functions to convert colors
43 * between different color spaces.
44 **/
45
46
47 #define GIMP_HSV_UNDEFINED -1.0
48 #define GIMP_HSL_UNDEFINED -1.0
49
50 /*********************************
51 * color conversion routines *
52 *********************************/
53
54
55 /* GimpRGB functions */
56
57
58 /**
59 * gimp_rgb_to_hsv:
60 * @rgb: A color value in the RGB colorspace
61 * @hsv: The value converted to the HSV colorspace
62 *
63 * Does a conversion from RGB to HSV (Hue, Saturation,
64 * Value) colorspace.
65 **/
66 void
gimp_rgb_to_hsv(const GimpRGB * rgb,GimpHSV * hsv)67 gimp_rgb_to_hsv (const GimpRGB *rgb,
68 GimpHSV *hsv)
69 {
70 gdouble max, min, delta;
71
72 g_return_if_fail (rgb != NULL);
73 g_return_if_fail (hsv != NULL);
74
75 max = gimp_rgb_max (rgb);
76 min = gimp_rgb_min (rgb);
77
78 hsv->v = max;
79 delta = max - min;
80
81 if (delta > 0.0001)
82 {
83 hsv->s = delta / max;
84
85 if (rgb->r == max)
86 {
87 hsv->h = (rgb->g - rgb->b) / delta;
88 if (hsv->h < 0.0)
89 hsv->h += 6.0;
90 }
91 else if (rgb->g == max)
92 {
93 hsv->h = 2.0 + (rgb->b - rgb->r) / delta;
94 }
95 else
96 {
97 hsv->h = 4.0 + (rgb->r - rgb->g) / delta;
98 }
99
100 hsv->h /= 6.0;
101 }
102 else
103 {
104 hsv->s = 0.0;
105 hsv->h = 0.0;
106 }
107
108 hsv->a = rgb->a;
109 }
110
111 /**
112 * gimp_hsv_to_rgb:
113 * @hsv: A color value in the HSV colorspace
114 * @rgb: The returned RGB value.
115 *
116 * Converts a color value from HSV to RGB colorspace
117 **/
118 void
gimp_hsv_to_rgb(const GimpHSV * hsv,GimpRGB * rgb)119 gimp_hsv_to_rgb (const GimpHSV *hsv,
120 GimpRGB *rgb)
121 {
122 gint i;
123 gdouble f, w, q, t;
124
125 gdouble hue;
126
127 g_return_if_fail (rgb != NULL);
128 g_return_if_fail (hsv != NULL);
129
130 if (hsv->s == 0.0)
131 {
132 rgb->r = hsv->v;
133 rgb->g = hsv->v;
134 rgb->b = hsv->v;
135 }
136 else
137 {
138 hue = hsv->h;
139
140 if (hue == 1.0)
141 hue = 0.0;
142
143 hue *= 6.0;
144
145 i = (gint) hue;
146 f = hue - i;
147 w = hsv->v * (1.0 - hsv->s);
148 q = hsv->v * (1.0 - (hsv->s * f));
149 t = hsv->v * (1.0 - (hsv->s * (1.0 - f)));
150
151 switch (i)
152 {
153 case 0:
154 rgb->r = hsv->v;
155 rgb->g = t;
156 rgb->b = w;
157 break;
158 case 1:
159 rgb->r = q;
160 rgb->g = hsv->v;
161 rgb->b = w;
162 break;
163 case 2:
164 rgb->r = w;
165 rgb->g = hsv->v;
166 rgb->b = t;
167 break;
168 case 3:
169 rgb->r = w;
170 rgb->g = q;
171 rgb->b = hsv->v;
172 break;
173 case 4:
174 rgb->r = t;
175 rgb->g = w;
176 rgb->b = hsv->v;
177 break;
178 case 5:
179 rgb->r = hsv->v;
180 rgb->g = w;
181 rgb->b = q;
182 break;
183 }
184 }
185
186 rgb->a = hsv->a;
187 }
188
189
190 /**
191 * gimp_rgb_to_hsl:
192 * @rgb: A color value in the RGB colorspace
193 * @hsl: The value converted to HSL
194 *
195 * Convert an RGB color value to a HSL (Hue, Saturation, Lightness)
196 * color value.
197 **/
198 void
gimp_rgb_to_hsl(const GimpRGB * rgb,GimpHSL * hsl)199 gimp_rgb_to_hsl (const GimpRGB *rgb,
200 GimpHSL *hsl)
201 {
202 gdouble max, min, delta;
203
204 g_return_if_fail (rgb != NULL);
205 g_return_if_fail (hsl != NULL);
206
207 max = gimp_rgb_max (rgb);
208 min = gimp_rgb_min (rgb);
209
210 hsl->l = (max + min) / 2.0;
211
212 if (max == min)
213 {
214 hsl->s = 0.0;
215 hsl->h = GIMP_HSL_UNDEFINED;
216 }
217 else
218 {
219 if (hsl->l <= 0.5)
220 hsl->s = (max - min) / (max + min);
221 else
222 hsl->s = (max - min) / (2.0 - max - min);
223
224 delta = max - min;
225
226 if (delta == 0.0)
227 delta = 1.0;
228
229 if (rgb->r == max)
230 {
231 hsl->h = (rgb->g - rgb->b) / delta;
232 }
233 else if (rgb->g == max)
234 {
235 hsl->h = 2.0 + (rgb->b - rgb->r) / delta;
236 }
237 else
238 {
239 hsl->h = 4.0 + (rgb->r - rgb->g) / delta;
240 }
241
242 hsl->h /= 6.0;
243
244 if (hsl->h < 0.0)
245 hsl->h += 1.0;
246 }
247
248 hsl->a = rgb->a;
249 }
250
251 static inline gdouble
gimp_hsl_value(gdouble n1,gdouble n2,gdouble hue)252 gimp_hsl_value (gdouble n1,
253 gdouble n2,
254 gdouble hue)
255 {
256 gdouble val;
257
258 if (hue > 6.0)
259 hue -= 6.0;
260 else if (hue < 0.0)
261 hue += 6.0;
262
263 if (hue < 1.0)
264 val = n1 + (n2 - n1) * hue;
265 else if (hue < 3.0)
266 val = n2;
267 else if (hue < 4.0)
268 val = n1 + (n2 - n1) * (4.0 - hue);
269 else
270 val = n1;
271
272 return val;
273 }
274
275
276 /**
277 * gimp_hsl_to_rgb:
278 * @hsl: A color value in the HSL colorspace
279 * @rgb: The value converted to a value in the RGB colorspace
280 *
281 * Convert a HSL color value to an RGB color value.
282 **/
283 void
gimp_hsl_to_rgb(const GimpHSL * hsl,GimpRGB * rgb)284 gimp_hsl_to_rgb (const GimpHSL *hsl,
285 GimpRGB *rgb)
286 {
287 g_return_if_fail (hsl != NULL);
288 g_return_if_fail (rgb != NULL);
289
290 if (hsl->s == 0)
291 {
292 /* achromatic case */
293 rgb->r = hsl->l;
294 rgb->g = hsl->l;
295 rgb->b = hsl->l;
296 }
297 else
298 {
299 gdouble m1, m2;
300
301 if (hsl->l <= 0.5)
302 m2 = hsl->l * (1.0 + hsl->s);
303 else
304 m2 = hsl->l + hsl->s - hsl->l * hsl->s;
305
306 m1 = 2.0 * hsl->l - m2;
307
308 rgb->r = gimp_hsl_value (m1, m2, hsl->h * 6.0 + 2.0);
309 rgb->g = gimp_hsl_value (m1, m2, hsl->h * 6.0);
310 rgb->b = gimp_hsl_value (m1, m2, hsl->h * 6.0 - 2.0);
311 }
312
313 rgb->a = hsl->a;
314 }
315
316
317 /**
318 * gimp_rgb_to_cmyk:
319 * @rgb: A value in the RGB colorspace
320 * @pullout: A scaling value (0-1) indicating how much black should be
321 * pulled out
322 * @cmyk: The input value naively converted to the CMYK colorspace
323 *
324 * Does a naive conversion from RGB to CMYK colorspace. A simple
325 * formula that doesn't take any color-profiles into account is used.
326 * The amount of black pullout how can be controlled via the @pullout
327 * parameter. A @pullout value of 0 makes this a conversion to CMY.
328 * A value of 1 causes the maximum amount of black to be pulled out.
329 **/
330 void
gimp_rgb_to_cmyk(const GimpRGB * rgb,gdouble pullout,GimpCMYK * cmyk)331 gimp_rgb_to_cmyk (const GimpRGB *rgb,
332 gdouble pullout,
333 GimpCMYK *cmyk)
334 {
335 gdouble c, m, y, k;
336
337 g_return_if_fail (rgb != NULL);
338 g_return_if_fail (cmyk != NULL);
339
340 c = 1.0 - rgb->r;
341 m = 1.0 - rgb->g;
342 y = 1.0 - rgb->b;
343
344 k = 1.0;
345 if (c < k) k = c;
346 if (m < k) k = m;
347 if (y < k) k = y;
348
349 k *= pullout;
350
351 if (k < 1.0)
352 {
353 cmyk->c = (c - k) / (1.0 - k);
354 cmyk->m = (m - k) / (1.0 - k);
355 cmyk->y = (y - k) / (1.0 - k);
356 }
357 else
358 {
359 cmyk->c = 0.0;
360 cmyk->m = 0.0;
361 cmyk->y = 0.0;
362 }
363
364 cmyk->k = k;
365 cmyk->a = rgb->a;
366 }
367
368 /**
369 * gimp_cmyk_to_rgb:
370 * @cmyk: A color value in the CMYK colorspace
371 * @rgb: The value converted to the RGB colorspace
372 *
373 * Does a simple transformation from the CMYK colorspace to the RGB
374 * colorspace, without taking color profiles into account.
375 **/
376 void
gimp_cmyk_to_rgb(const GimpCMYK * cmyk,GimpRGB * rgb)377 gimp_cmyk_to_rgb (const GimpCMYK *cmyk,
378 GimpRGB *rgb)
379 {
380 gdouble c, m, y, k;
381
382 g_return_if_fail (cmyk != NULL);
383 g_return_if_fail (rgb != NULL);
384
385 k = cmyk->k;
386
387 if (k < 1.0)
388 {
389 c = cmyk->c * (1.0 - k) + k;
390 m = cmyk->m * (1.0 - k) + k;
391 y = cmyk->y * (1.0 - k) + k;
392 }
393 else
394 {
395 c = 1.0;
396 m = 1.0;
397 y = 1.0;
398 }
399
400 rgb->r = 1.0 - c;
401 rgb->g = 1.0 - m;
402 rgb->b = 1.0 - y;
403 rgb->a = cmyk->a;
404 }
405
406
407 #define GIMP_RETURN_RGB(x, y, z) { rgb->r = x; rgb->g = y; rgb->b = z; return; }
408
409 /****************************************************************************
410 * Theoretically, hue 0 (pure red) is identical to hue 6 in these transforms.
411 * Pure red always maps to 6 in this implementation. Therefore UNDEFINED can
412 * be defined as 0 in situations where only unsigned numbers are desired.
413 ****************************************************************************/
414
415 /**
416 * gimp_rgb_to_hwb:
417 * @rgb: A color value in the RGB colorspace
418 * @hue: The hue value of the above color, in the range 0 to 6
419 * @whiteness: The whiteness value of the above color, in the range 0 to 1
420 * @blackness: The blackness value of the above color, in the range 0 to 1
421 *
422 * Theoretically, hue 0 (pure red) is identical to hue 6 in these transforms.
423 * Pure red always maps to 6 in this implementation. Therefore UNDEFINED can
424 * be defined as 0 in situations where only unsigned numbers are desired.
425 *
426 * RGB are each on [0, 1]. Whiteness and Blackness are returned in the
427 * range [0, 1] and H is returned in the range [0, 6]. If W == 1 - B, H is
428 * undefined.
429 **/
430 void
gimp_rgb_to_hwb(const GimpRGB * rgb,gdouble * hue,gdouble * whiteness,gdouble * blackness)431 gimp_rgb_to_hwb (const GimpRGB *rgb,
432 gdouble *hue,
433 gdouble *whiteness,
434 gdouble *blackness)
435 {
436 /* RGB are each on [0, 1]. W and B are returned on [0, 1] and H is */
437 /* returned on [0, 6]. Exception: H is returned UNDEFINED if W == 1 - B. */
438 /* ====================================================================== */
439
440 gdouble R = rgb->r, G = rgb->g, B = rgb->b, w, v, b, f;
441 gint i;
442
443 w = gimp_rgb_min (rgb);
444 v = gimp_rgb_max (rgb);
445 b = 1.0 - v;
446
447 if (v == w)
448 {
449 *hue = GIMP_HSV_UNDEFINED;
450 *whiteness = w;
451 *blackness = b;
452 }
453 else
454 {
455 f = (R == w) ? G - B : ((G == w) ? B - R : R - G);
456 i = (R == w) ? 3.0 : ((G == w) ? 5.0 : 1.0);
457
458 *hue = (360.0 / 6.0) * (i - f / (v - w));
459 *whiteness = w;
460 *blackness = b;
461 }
462 }
463
464 /**
465 * gimp_hwb_to_rgb:
466 * @hue: A hue value, in the range 0 to 6
467 * @whiteness: A whiteness value, in the range 0 to 1
468 * @blackness: A blackness value, in the range 0 to 1
469 * @rgb: The above color converted to the RGB colorspace
470 *
471 * H is defined in the range [0, 6] or UNDEFINED, B and W are both in the
472 * range [0, 1]. The returned RGB values are all in the range [0, 1].
473 **/
474 void
gimp_hwb_to_rgb(gdouble hue,gdouble whiteness,gdouble blackness,GimpRGB * rgb)475 gimp_hwb_to_rgb (gdouble hue,
476 gdouble whiteness,
477 gdouble blackness,
478 GimpRGB *rgb)
479 {
480 /* H is given on [0, 6] or UNDEFINED. whiteness and
481 * blackness are given on [0, 1].
482 * RGB are each returned on [0, 1].
483 */
484
485 gdouble h = hue, w = whiteness, b = blackness, v, n, f;
486 gint i;
487
488 h = 6.0 * h/ 360.0;
489
490 v = 1.0 - b;
491 if (h == GIMP_HSV_UNDEFINED)
492 {
493 rgb->r = v;
494 rgb->g = v;
495 rgb->b = v;
496 }
497 else
498 {
499 i = floor (h);
500 f = h - i;
501
502 if (i & 1)
503 f = 1.0 - f; /* if i is odd */
504
505 n = w + f * (v - w); /* linear interpolation between w and v */
506
507 switch (i)
508 {
509 case 6:
510 case 0: GIMP_RETURN_RGB (v, n, w);
511 break;
512 case 1: GIMP_RETURN_RGB (n, v, w);
513 break;
514 case 2: GIMP_RETURN_RGB (w, v, n);
515 break;
516 case 3: GIMP_RETURN_RGB (w, n, v);
517 break;
518 case 4: GIMP_RETURN_RGB (n, w, v);
519 break;
520 case 5: GIMP_RETURN_RGB (v, w, n);
521 break;
522 }
523 }
524
525 }
526
527
528 /* gint functions */
529
530 /**
531 * gimp_rgb_to_hsv_int:
532 * @red: The red channel value, returns the Hue channel
533 * @green: The green channel value, returns the Saturation channel
534 * @blue: The blue channel value, returns the Value channel
535 *
536 * The arguments are pointers to int representing channel values in
537 * the RGB colorspace, and the values pointed to are all in the range
538 * [0, 255].
539 *
540 * The function changes the arguments to point to the HSV value
541 * corresponding, with the returned values in the following
542 * ranges: H [0, 359], S [0, 255], V [0, 255].
543 **/
544 void
gimp_rgb_to_hsv_int(gint * red,gint * green,gint * blue)545 gimp_rgb_to_hsv_int (gint *red,
546 gint *green,
547 gint *blue)
548 {
549 gdouble r, g, b;
550 gdouble h, s, v;
551 gint min;
552 gdouble delta;
553
554 r = *red;
555 g = *green;
556 b = *blue;
557
558 if (r > g)
559 {
560 v = MAX (r, b);
561 min = MIN (g, b);
562 }
563 else
564 {
565 v = MAX (g, b);
566 min = MIN (r, b);
567 }
568
569 delta = v - min;
570
571 if (v == 0.0)
572 s = 0.0;
573 else
574 s = delta / v;
575
576 if (s == 0.0)
577 {
578 h = 0.0;
579 }
580 else
581 {
582 if (r == v)
583 h = 60.0 * (g - b) / delta;
584 else if (g == v)
585 h = 120 + 60.0 * (b - r) / delta;
586 else
587 h = 240 + 60.0 * (r - g) / delta;
588
589 if (h < 0.0)
590 h += 360.0;
591
592 if (h > 360.0)
593 h -= 360.0;
594 }
595
596 *red = ROUND (h);
597 *green = ROUND (s * 255.0);
598 *blue = ROUND (v);
599
600 /* avoid the ambiguity of returning different values for the same color */
601 if (*red == 360)
602 *red = 0;
603 }
604
605 /**
606 * gimp_hsv_to_rgb_int:
607 * @hue: The hue channel, returns the red channel
608 * @saturation: The saturation channel, returns the green channel
609 * @value: The value channel, returns the blue channel
610 *
611 * The arguments are pointers to int, with the values pointed to in the
612 * following ranges: H [0, 360], S [0, 255], V [0, 255].
613 *
614 * The function changes the arguments to point to the RGB value
615 * corresponding, with the returned values all in the range [0, 255].
616 **/
617 void
gimp_hsv_to_rgb_int(gint * hue,gint * saturation,gint * value)618 gimp_hsv_to_rgb_int (gint *hue,
619 gint *saturation,
620 gint *value)
621 {
622 gdouble h, s, v, h_temp;
623 gdouble f, p, q, t;
624 gint i;
625
626 if (*saturation == 0)
627 {
628 *hue = *value;
629 *saturation = *value;
630 *value = *value;
631 }
632 else
633 {
634 h = *hue;
635 s = *saturation / 255.0;
636 v = *value / 255.0;
637
638 if (h == 360)
639 h_temp = 0;
640 else
641 h_temp = h;
642
643 h_temp = h_temp / 60.0;
644 i = floor (h_temp);
645 f = h_temp - i;
646 p = v * (1.0 - s);
647 q = v * (1.0 - (s * f));
648 t = v * (1.0 - (s * (1.0 - f)));
649
650 switch (i)
651 {
652 case 0:
653 *hue = ROUND (v * 255.0);
654 *saturation = ROUND (t * 255.0);
655 *value = ROUND (p * 255.0);
656 break;
657
658 case 1:
659 *hue = ROUND (q * 255.0);
660 *saturation = ROUND (v * 255.0);
661 *value = ROUND (p * 255.0);
662 break;
663
664 case 2:
665 *hue = ROUND (p * 255.0);
666 *saturation = ROUND (v * 255.0);
667 *value = ROUND (t * 255.0);
668 break;
669
670 case 3:
671 *hue = ROUND (p * 255.0);
672 *saturation = ROUND (q * 255.0);
673 *value = ROUND (v * 255.0);
674 break;
675
676 case 4:
677 *hue = ROUND (t * 255.0);
678 *saturation = ROUND (p * 255.0);
679 *value = ROUND (v * 255.0);
680 break;
681
682 case 5:
683 *hue = ROUND (v * 255.0);
684 *saturation = ROUND (p * 255.0);
685 *value = ROUND (q * 255.0);
686 break;
687 }
688 }
689 }
690
691 /**
692 * gimp_rgb_to_hsl_int:
693 * @red: Red channel, returns Hue channel
694 * @green: Green channel, returns Lightness channel
695 * @blue: Blue channel, returns Saturation channel
696 *
697 * The arguments are pointers to int representing channel values in the
698 * RGB colorspace, and the values pointed to are all in the range [0, 255].
699 *
700 * The function changes the arguments to point to the corresponding HLS
701 * value with the values pointed to in the following ranges: H [0, 360],
702 * L [0, 255], S [0, 255].
703 **/
704 void
gimp_rgb_to_hsl_int(gint * red,gint * green,gint * blue)705 gimp_rgb_to_hsl_int (gint *red,
706 gint *green,
707 gint *blue)
708 {
709 gint r, g, b;
710 gdouble h, s, l;
711 gint min, max;
712 gint delta;
713
714 r = *red;
715 g = *green;
716 b = *blue;
717
718 if (r > g)
719 {
720 max = MAX (r, b);
721 min = MIN (g, b);
722 }
723 else
724 {
725 max = MAX (g, b);
726 min = MIN (r, b);
727 }
728
729 l = (max + min) / 2.0;
730
731 if (max == min)
732 {
733 s = 0.0;
734 h = 0.0;
735 }
736 else
737 {
738 delta = (max - min);
739
740 if (l < 128)
741 s = 255 * (gdouble) delta / (gdouble) (max + min);
742 else
743 s = 255 * (gdouble) delta / (gdouble) (511 - max - min);
744
745 if (r == max)
746 h = (g - b) / (gdouble) delta;
747 else if (g == max)
748 h = 2 + (b - r) / (gdouble) delta;
749 else
750 h = 4 + (r - g) / (gdouble) delta;
751
752 h = h * 42.5;
753
754 if (h < 0)
755 h += 255;
756 else if (h > 255)
757 h -= 255;
758 }
759
760 *red = ROUND (h);
761 *green = ROUND (s);
762 *blue = ROUND (l);
763 }
764
765 /**
766 * gimp_rgb_to_l_int:
767 * @red: Red channel
768 * @green: Green channel
769 * @blue: Blue channel
770 *
771 * Calculates the lightness value of an RGB triplet with the formula
772 * L = (max(R, G, B) + min (R, G, B)) / 2
773 *
774 * Return value: Luminance value corresponding to the input RGB value
775 **/
776 gint
gimp_rgb_to_l_int(gint red,gint green,gint blue)777 gimp_rgb_to_l_int (gint red,
778 gint green,
779 gint blue)
780 {
781 gint min, max;
782
783 if (red > green)
784 {
785 max = MAX (red, blue);
786 min = MIN (green, blue);
787 }
788 else
789 {
790 max = MAX (green, blue);
791 min = MIN (red, blue);
792 }
793
794 return ROUND ((max + min) / 2.0);
795 }
796
797 static inline gint
gimp_hsl_value_int(gdouble n1,gdouble n2,gdouble hue)798 gimp_hsl_value_int (gdouble n1,
799 gdouble n2,
800 gdouble hue)
801 {
802 gdouble value;
803
804 if (hue > 255)
805 hue -= 255;
806 else if (hue < 0)
807 hue += 255;
808
809 if (hue < 42.5)
810 value = n1 + (n2 - n1) * (hue / 42.5);
811 else if (hue < 127.5)
812 value = n2;
813 else if (hue < 170)
814 value = n1 + (n2 - n1) * ((170 - hue) / 42.5);
815 else
816 value = n1;
817
818 return ROUND (value * 255.0);
819 }
820
821 /**
822 * gimp_hsl_to_rgb_int:
823 * @hue: Hue channel, returns Red channel
824 * @saturation: Saturation channel, returns Green channel
825 * @lightness: Lightness channel, returns Blue channel
826 *
827 * The arguments are pointers to int, with the values pointed to in the
828 * following ranges: H [0, 360], L [0, 255], S [0, 255].
829 *
830 * The function changes the arguments to point to the RGB value
831 * corresponding, with the returned values all in the range [0, 255].
832 **/
833 void
gimp_hsl_to_rgb_int(gint * hue,gint * saturation,gint * lightness)834 gimp_hsl_to_rgb_int (gint *hue,
835 gint *saturation,
836 gint *lightness)
837 {
838 gdouble h, s, l;
839
840 h = *hue;
841 s = *saturation;
842 l = *lightness;
843
844 if (s == 0)
845 {
846 /* achromatic case */
847 *hue = l;
848 *lightness = l;
849 *saturation = l;
850 }
851 else
852 {
853 gdouble m1, m2;
854
855 if (l < 128)
856 m2 = (l * (255 + s)) / 65025.0;
857 else
858 m2 = (l + s - (l * s) / 255.0) / 255.0;
859
860 m1 = (l / 127.5) - m2;
861
862 /* chromatic case */
863 *hue = gimp_hsl_value_int (m1, m2, h + 85);
864 *saturation = gimp_hsl_value_int (m1, m2, h);
865 *lightness = gimp_hsl_value_int (m1, m2, h - 85);
866 }
867 }
868
869 /**
870 * gimp_rgb_to_cmyk_int:
871 * @red: the red channel; returns the cyan value (0-255)
872 * @green: the green channel; returns the magenta value (0-255)
873 * @blue: the blue channel; returns the yellow value (0-255)
874 * @pullout: the percentage of black to pull out (0-100); returns
875 * the black value (0-255)
876 *
877 * Does a naive conversion from RGB to CMYK colorspace. A simple
878 * formula that doesn't take any color-profiles into account is used.
879 * The amount of black pullout how can be controlled via the @pullout
880 * parameter. A @pullout value of 0 makes this a conversion to CMY.
881 * A value of 100 causes the maximum amount of black to be pulled out.
882 **/
883 void
gimp_rgb_to_cmyk_int(gint * red,gint * green,gint * blue,gint * pullout)884 gimp_rgb_to_cmyk_int (gint *red,
885 gint *green,
886 gint *blue,
887 gint *pullout)
888 {
889 gint c, m, y;
890
891 c = 255 - *red;
892 m = 255 - *green;
893 y = 255 - *blue;
894
895 if (*pullout == 0)
896 {
897 *red = c;
898 *green = m;
899 *blue = y;
900 }
901 else
902 {
903 gint k = 255;
904
905 if (c < k) k = c;
906 if (m < k) k = m;
907 if (y < k) k = y;
908
909 k = (k * CLAMP (*pullout, 0, 100)) / 100;
910
911 *red = ((c - k) << 8) / (256 - k);
912 *green = ((m - k) << 8) / (256 - k);
913 *blue = ((y - k) << 8) / (256 - k);
914 *pullout = k;
915 }
916 }
917
918 /**
919 * gimp_cmyk_to_rgb_int:
920 * @cyan: the cyan channel; returns the red value (0-255)
921 * @magenta: the magenta channel; returns the green value (0-255)
922 * @yellow: the yellow channel; returns the blue value (0-255)
923 * @black: the black channel (0-255); doesn't change
924 *
925 * Does a naive conversion from CMYK to RGB colorspace. A simple
926 * formula that doesn't take any color-profiles into account is used.
927 **/
928 void
gimp_cmyk_to_rgb_int(gint * cyan,gint * magenta,gint * yellow,gint * black)929 gimp_cmyk_to_rgb_int (gint *cyan,
930 gint *magenta,
931 gint *yellow,
932 gint *black)
933 {
934 gint c, m, y, k;
935
936 c = *cyan;
937 m = *magenta;
938 y = *yellow;
939 k = *black;
940
941 if (k)
942 {
943 c = ((c * (256 - k)) >> 8) + k;
944 m = ((m * (256 - k)) >> 8) + k;
945 y = ((y * (256 - k)) >> 8) + k;
946 }
947
948 *cyan = 255 - c;
949 *magenta = 255 - m;
950 *yellow = 255 - y;
951 }
952
953 /**
954 * gimp_rgb_to_hsv4:
955 * @rgb: RGB triplet, rgb[0] is red channel, rgb[1] is green,
956 * rgb[2] is blue (0..255)
957 * @hue: Pointer to hue channel (0..1)
958 * @saturation: Pointer to saturation channel (0..1)
959 * @value: Pointer to value channel (0..1)
960 **/
961 void
gimp_rgb_to_hsv4(const guchar * rgb,gdouble * hue,gdouble * saturation,gdouble * value)962 gimp_rgb_to_hsv4 (const guchar *rgb,
963 gdouble *hue,
964 gdouble *saturation,
965 gdouble *value)
966 {
967 gdouble red, green, blue;
968 gdouble h, s, v;
969 gdouble min, max;
970 gdouble delta;
971
972 red = rgb[0] / 255.0;
973 green = rgb[1] / 255.0;
974 blue = rgb[2] / 255.0;
975
976 if (red > green)
977 {
978 max = MAX (red, blue);
979 min = MIN (green, blue);
980 }
981 else
982 {
983 max = MAX (green, blue);
984 min = MIN (red, blue);
985 }
986
987 v = max;
988
989 if (max != 0.0)
990 s = (max - min) / max;
991 else
992 s = 0.0;
993
994 if (s == 0.0)
995 h = 0.0;
996 else
997 {
998 delta = max - min;
999
1000 if (delta == 0.0)
1001 delta = 1.0;
1002
1003 if (red == max)
1004 h = (green - blue) / delta;
1005 else if (green == max)
1006 h = 2 + (blue - red) / delta;
1007 else
1008 h = 4 + (red - green) / delta;
1009
1010 h /= 6.0;
1011
1012 if (h < 0.0)
1013 h += 1.0;
1014 else if (h > 1.0)
1015 h -= 1.0;
1016 }
1017
1018 *hue = h;
1019 *saturation = s;
1020 *value = v;
1021 }
1022
1023 /**
1024 * gimp_hsv_to_rgb4:
1025 * @rgb: RGB triplet, rgb[0] is red channel, rgb[1] is green,
1026 * rgb[2] is blue (0..255)
1027 * @hue: Hue channel (0..1)
1028 * @saturation: Saturation channel (0..1)
1029 * @value: Value channel (0..1)
1030 **/
1031 void
gimp_hsv_to_rgb4(guchar * rgb,gdouble hue,gdouble saturation,gdouble value)1032 gimp_hsv_to_rgb4 (guchar *rgb,
1033 gdouble hue,
1034 gdouble saturation,
1035 gdouble value)
1036 {
1037 gdouble h, s, v;
1038 gdouble f, p, q, t;
1039
1040 if (saturation == 0.0)
1041 {
1042 hue = value;
1043 saturation = value;
1044 /*value = value;*/
1045 }
1046 else
1047 {
1048 h = hue * 6.0;
1049 s = saturation;
1050 v = value;
1051
1052 if (h == 6.0)
1053 h = 0.0;
1054
1055 f = h - (gint) h;
1056 p = v * (1.0 - s);
1057 q = v * (1.0 - s * f);
1058 t = v * (1.0 - s * (1.0 - f));
1059
1060 switch ((int) h)
1061 {
1062 case 0:
1063 hue = v;
1064 saturation = t;
1065 value = p;
1066 break;
1067
1068 case 1:
1069 hue = q;
1070 saturation = v;
1071 value = p;
1072 break;
1073
1074 case 2:
1075 hue = p;
1076 saturation = v;
1077 value = t;
1078 break;
1079
1080 case 3:
1081 hue = p;
1082 saturation = q;
1083 value = v;
1084 break;
1085
1086 case 4:
1087 hue = t;
1088 saturation = p;
1089 value = v;
1090 break;
1091
1092 case 5:
1093 hue = v;
1094 saturation = p;
1095 value = q;
1096 break;
1097 }
1098 }
1099
1100 rgb[0] = ROUND (hue * 255.0);
1101 rgb[1] = ROUND (saturation * 255.0);
1102 rgb[2] = ROUND (value * 255.0);
1103 }
1104