app: s/sprintf/g_snprintf/ in xcf_save_image()
[gimp.git] / libgimpcolor / gimprgb.c
blob5bdc20e6f3576b05a215aeffc8aa108e0f61da6d
1 /* LIBGIMP - The GIMP Library
2 * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
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.
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.
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/>.
19 #include "config.h"
21 #include <babl/babl.h>
22 #include <glib-object.h>
24 #include "libgimpmath/gimpmath.h"
26 #include "gimpcolortypes.h"
27 #include "gimprgb.h"
30 /**
31 * SECTION: gimprgb
32 * @title: GimpRGB
33 * @short_description: Definitions and Functions relating to RGB colors.
35 * Definitions and Functions relating to RGB colors.
36 **/
40 * GIMP_TYPE_RGB
43 static GimpRGB * gimp_rgb_copy (const GimpRGB *rgb);
46 GType
47 gimp_rgb_get_type (void)
49 static GType rgb_type = 0;
51 if (!rgb_type)
52 rgb_type = g_boxed_type_register_static ("GimpRGB",
53 (GBoxedCopyFunc) gimp_rgb_copy,
54 (GBoxedFreeFunc) g_free);
56 return rgb_type;
59 void
60 gimp_value_get_rgb (const GValue *value,
61 GimpRGB *rgb)
63 g_return_if_fail (GIMP_VALUE_HOLDS_RGB (value));
64 g_return_if_fail (rgb != NULL);
66 if (value->data[0].v_pointer)
67 *rgb = *((GimpRGB *) value->data[0].v_pointer);
68 else
69 gimp_rgba_set (rgb, 0.0, 0.0, 0.0, 1.0);
72 void
73 gimp_value_set_rgb (GValue *value,
74 const GimpRGB *rgb)
76 g_return_if_fail (GIMP_VALUE_HOLDS_RGB (value));
77 g_return_if_fail (rgb != NULL);
79 g_value_set_boxed (value, rgb);
82 static GimpRGB *
83 gimp_rgb_copy (const GimpRGB *rgb)
85 return g_memdup (rgb, sizeof (GimpRGB));
89 /* RGB functions */
91 /**
92 * gimp_rgb_set:
93 * @rgb: a #GimpRGB struct
94 * @red: the red component
95 * @green: the green component
96 * @blue: the blue component
98 * Sets the red, green and blue components of @rgb and leaves the
99 * alpha component unchanged. The color values should be between 0.0
100 * and 1.0 but there is no check to enforce this and the values are
101 * set exactly as they are passed in.
103 void
104 gimp_rgb_set (GimpRGB *rgb,
105 gdouble r,
106 gdouble g,
107 gdouble b)
109 g_return_if_fail (rgb != NULL);
111 rgb->r = r;
112 rgb->g = g;
113 rgb->b = b;
117 * gimp_rgb_set_alpha:
118 * @rgb: a #GimpRGB struct
119 * @alpha: the alpha component
121 * Sets the alpha component of @rgb and leaves the RGB components unchanged.
123 void
124 gimp_rgb_set_alpha (GimpRGB *rgb,
125 gdouble a)
127 g_return_if_fail (rgb != NULL);
129 rgb->a = a;
133 * gimp_rgb_set_pixel:
134 * @rgb: a #GimpRGB struct
135 * @format: a Babl format
136 * @pixel: pointer to the source pixel
138 * Sets the red, green and blue components of @rgb from the color
139 * stored in @pixel. The pixel format of @pixel is determined by
140 * @format.
142 * Since: 2.10
144 void
145 gimp_rgb_set_pixel (GimpRGB *rgb,
146 const Babl *format,
147 gconstpointer pixel)
149 g_return_if_fail (rgb != NULL);
150 g_return_if_fail (format != NULL);
151 g_return_if_fail (pixel != NULL);
153 babl_process (babl_fish (format,
154 babl_format ("R'G'B' double")),
155 pixel, rgb, 1);
159 * gimp_rgb_get_pixel:
160 * @rgb: a #GimpRGB struct
161 * @format: a Babl format
162 * @pixel: pointer to the destination pixel
164 * Writes the red, green, blue and alpha components of @rgb to the
165 * color stored in @pixel. The pixel format of @pixel is determined by
166 * @format.
168 * Since: 2.10
170 void
171 gimp_rgb_get_pixel (const GimpRGB *rgb,
172 const Babl *format,
173 gpointer pixel)
175 g_return_if_fail (rgb != NULL);
176 g_return_if_fail (format != NULL);
177 g_return_if_fail (pixel != NULL);
179 babl_process (babl_fish (babl_format ("R'G'B' double"),
180 format),
181 rgb, pixel, 1);
185 * gimp_rgb_set_uchar:
186 * @rgb: a #GimpRGB struct
187 * @red: the red component
188 * @green: the green component
189 * @blue: the blue component
191 * Sets the red, green and blue components of @rgb from 8bit values
192 * (0 to 255) and leaves the alpha component unchanged.
194 void
195 gimp_rgb_set_uchar (GimpRGB *rgb,
196 guchar r,
197 guchar g,
198 guchar b)
200 g_return_if_fail (rgb != NULL);
202 rgb->r = (gdouble) r / 255.0;
203 rgb->g = (gdouble) g / 255.0;
204 rgb->b = (gdouble) b / 255.0;
207 void
208 gimp_rgb_get_uchar (const GimpRGB *rgb,
209 guchar *r,
210 guchar *g,
211 guchar *b)
213 g_return_if_fail (rgb != NULL);
215 if (r) *r = ROUND (CLAMP (rgb->r, 0.0, 1.0) * 255.0);
216 if (g) *g = ROUND (CLAMP (rgb->g, 0.0, 1.0) * 255.0);
217 if (b) *b = ROUND (CLAMP (rgb->b, 0.0, 1.0) * 255.0);
220 void
221 gimp_rgb_add (GimpRGB *rgb1,
222 const GimpRGB *rgb2)
224 g_return_if_fail (rgb1 != NULL);
225 g_return_if_fail (rgb2 != NULL);
227 rgb1->r += rgb2->r;
228 rgb1->g += rgb2->g;
229 rgb1->b += rgb2->b;
232 void
233 gimp_rgb_subtract (GimpRGB *rgb1,
234 const GimpRGB *rgb2)
236 g_return_if_fail (rgb1 != NULL);
237 g_return_if_fail (rgb2 != NULL);
239 rgb1->r -= rgb2->r;
240 rgb1->g -= rgb2->g;
241 rgb1->b -= rgb2->b;
244 void
245 gimp_rgb_multiply (GimpRGB *rgb,
246 gdouble factor)
248 g_return_if_fail (rgb != NULL);
250 rgb->r *= factor;
251 rgb->g *= factor;
252 rgb->b *= factor;
255 gdouble
256 gimp_rgb_distance (const GimpRGB *rgb1,
257 const GimpRGB *rgb2)
259 g_return_val_if_fail (rgb1 != NULL, 0.0);
260 g_return_val_if_fail (rgb2 != NULL, 0.0);
262 return (fabs (rgb1->r - rgb2->r) +
263 fabs (rgb1->g - rgb2->g) +
264 fabs (rgb1->b - rgb2->b));
267 gdouble
268 gimp_rgb_max (const GimpRGB *rgb)
270 g_return_val_if_fail (rgb != NULL, 0.0);
272 if (rgb->r > rgb->g)
273 return (rgb->r > rgb->b) ? rgb->r : rgb->b;
274 else
275 return (rgb->g > rgb->b) ? rgb->g : rgb->b;
278 gdouble
279 gimp_rgb_min (const GimpRGB *rgb)
281 g_return_val_if_fail (rgb != NULL, 0.0);
283 if (rgb->r < rgb->g)
284 return (rgb->r < rgb->b) ? rgb->r : rgb->b;
285 else
286 return (rgb->g < rgb->b) ? rgb->g : rgb->b;
289 void
290 gimp_rgb_clamp (GimpRGB *rgb)
292 g_return_if_fail (rgb != NULL);
294 rgb->r = CLAMP (rgb->r, 0.0, 1.0);
295 rgb->g = CLAMP (rgb->g, 0.0, 1.0);
296 rgb->b = CLAMP (rgb->b, 0.0, 1.0);
297 rgb->a = CLAMP (rgb->a, 0.0, 1.0);
300 void
301 gimp_rgb_gamma (GimpRGB *rgb,
302 gdouble gamma)
304 gdouble ig;
306 g_return_if_fail (rgb != NULL);
308 if (gamma != 0.0)
309 ig = 1.0 / gamma;
310 else
311 ig = 0.0;
313 rgb->r = pow (rgb->r, ig);
314 rgb->g = pow (rgb->g, ig);
315 rgb->b = pow (rgb->b, ig);
319 * gimp_rgb_luminance:
320 * @rgb: a #GimpRGB struct
322 * Return value: the luminous intensity of the range from 0.0 to 1.0.
324 * Since: 2.4
326 gdouble
327 gimp_rgb_luminance (const GimpRGB *rgb)
329 gdouble luminance;
331 g_return_val_if_fail (rgb != NULL, 0.0);
333 luminance = GIMP_RGB_LUMINANCE (rgb->r, rgb->g, rgb->b);
335 return CLAMP (luminance, 0.0, 1.0);
339 * gimp_rgb_luminance_uchar:
340 * @rgb: a #GimpRGB struct
342 * Return value: the luminous intensity in the range from 0 to 255.
344 * Since: 2.4
346 guchar
347 gimp_rgb_luminance_uchar (const GimpRGB *rgb)
349 g_return_val_if_fail (rgb != NULL, 0);
351 return ROUND (gimp_rgb_luminance (rgb) * 255.0);
354 void
355 gimp_rgb_composite (GimpRGB *color1,
356 const GimpRGB *color2,
357 GimpRGBCompositeMode mode)
359 g_return_if_fail (color1 != NULL);
360 g_return_if_fail (color2 != NULL);
362 switch (mode)
364 case GIMP_RGB_COMPOSITE_NONE:
365 break;
367 case GIMP_RGB_COMPOSITE_NORMAL:
368 /* put color2 on top of color1 */
369 if (color2->a == 1.0)
371 *color1 = *color2;
373 else
375 gdouble factor = color1->a * (1.0 - color2->a);
377 color1->r = color1->r * factor + color2->r * color2->a;
378 color1->g = color1->g * factor + color2->g * color2->a;
379 color1->b = color1->b * factor + color2->b * color2->a;
380 color1->a = factor + color2->a;
382 break;
384 case GIMP_RGB_COMPOSITE_BEHIND:
385 /* put color2 below color1 */
386 if (color1->a < 1.0)
388 gdouble factor = color2->a * (1.0 - color1->a);
390 color1->r = color2->r * factor + color1->r * color1->a;
391 color1->g = color2->g * factor + color1->g * color1->a;
392 color1->b = color2->b * factor + color1->b * color1->a;
393 color1->a = factor + color1->a;
395 break;
399 /* RGBA functions */
402 * gimp_rgba_set_pixel:
403 * @rgba: a #GimpRGB struct
404 * @format: a Babl format
405 * @pixel: pointer to the source pixel
407 * Sets the red, green, blue and alpha components of @rgba from the
408 * color stored in @pixel. The pixel format of @pixel is determined
409 * by @format.
411 * Since: 2.10
413 void
414 gimp_rgba_set_pixel (GimpRGB *rgba,
415 const Babl *format,
416 gconstpointer pixel)
418 g_return_if_fail (rgba != NULL);
419 g_return_if_fail (format != NULL);
420 g_return_if_fail (pixel != NULL);
422 babl_process (babl_fish (format,
423 babl_format ("R'G'B'A double")),
424 pixel, rgba, 1);
428 * gimp_rgba_get_pixel:
429 * @rgba: a #GimpRGB struct
430 * @format: a Babl format
431 * @pixel: pointer to the destination pixel
433 * Writes the red, green, blue and alpha components of @rgba to the
434 * color stored in @pixel. The pixel format of @pixel is determined by
435 * @format.
437 * Since: 2.10
439 void
440 gimp_rgba_get_pixel (const GimpRGB *rgba,
441 const Babl *format,
442 gpointer pixel)
444 g_return_if_fail (rgba != NULL);
445 g_return_if_fail (format != NULL);
446 g_return_if_fail (pixel != NULL);
448 babl_process (babl_fish (babl_format ("R'G'B'A double"),
449 format),
450 rgba, pixel, 1);
454 * gimp_rgba_set:
455 * @rgba: a #GimpRGB struct
456 * @red: the red component
457 * @green: the green component
458 * @blue: the blue component
459 * @alpha: the alpha component
461 * Sets the red, green, blue and alpha components of @rgb. The values
462 * should be between 0.0 and 1.0 but there is no check to enforce this
463 * and the values are set exactly as they are passed in.
465 void
466 gimp_rgba_set (GimpRGB *rgba,
467 gdouble r,
468 gdouble g,
469 gdouble b,
470 gdouble a)
472 g_return_if_fail (rgba != NULL);
474 rgba->r = r;
475 rgba->g = g;
476 rgba->b = b;
477 rgba->a = a;
481 * gimp_rgba_set_uchar:
482 * @rgba: a #GimpRGB struct
483 * @red: the red component
484 * @green: the green component
485 * @blue: the blue component
486 * @alpha: the alpha component
488 * Sets the red, green, blue and alpha components of @rgb from 8bit
489 * values (0 to 255).
491 void
492 gimp_rgba_set_uchar (GimpRGB *rgba,
493 guchar r,
494 guchar g,
495 guchar b,
496 guchar a)
498 g_return_if_fail (rgba != NULL);
500 rgba->r = (gdouble) r / 255.0;
501 rgba->g = (gdouble) g / 255.0;
502 rgba->b = (gdouble) b / 255.0;
503 rgba->a = (gdouble) a / 255.0;
506 void
507 gimp_rgba_get_uchar (const GimpRGB *rgba,
508 guchar *r,
509 guchar *g,
510 guchar *b,
511 guchar *a)
513 g_return_if_fail (rgba != NULL);
515 if (r) *r = ROUND (CLAMP (rgba->r, 0.0, 1.0) * 255.0);
516 if (g) *g = ROUND (CLAMP (rgba->g, 0.0, 1.0) * 255.0);
517 if (b) *b = ROUND (CLAMP (rgba->b, 0.0, 1.0) * 255.0);
518 if (a) *a = ROUND (CLAMP (rgba->a, 0.0, 1.0) * 255.0);
521 void
522 gimp_rgba_add (GimpRGB *rgba1,
523 const GimpRGB *rgba2)
525 g_return_if_fail (rgba1 != NULL);
526 g_return_if_fail (rgba2 != NULL);
528 rgba1->r += rgba2->r;
529 rgba1->g += rgba2->g;
530 rgba1->b += rgba2->b;
531 rgba1->a += rgba2->a;
534 void
535 gimp_rgba_subtract (GimpRGB *rgba1,
536 const GimpRGB *rgba2)
538 g_return_if_fail (rgba1 != NULL);
539 g_return_if_fail (rgba2 != NULL);
541 rgba1->r -= rgba2->r;
542 rgba1->g -= rgba2->g;
543 rgba1->b -= rgba2->b;
544 rgba1->a -= rgba2->a;
547 void
548 gimp_rgba_multiply (GimpRGB *rgba,
549 gdouble factor)
551 g_return_if_fail (rgba != NULL);
553 rgba->r *= factor;
554 rgba->g *= factor;
555 rgba->b *= factor;
556 rgba->a *= factor;
559 gdouble
560 gimp_rgba_distance (const GimpRGB *rgba1,
561 const GimpRGB *rgba2)
563 g_return_val_if_fail (rgba1 != NULL, 0.0);
564 g_return_val_if_fail (rgba2 != NULL, 0.0);
566 return (fabs (rgba1->r - rgba2->r) +
567 fabs (rgba1->g - rgba2->g) +
568 fabs (rgba1->b - rgba2->b) +
569 fabs (rgba1->a - rgba2->a));
574 * GIMP_TYPE_PARAM_RGB
577 #define GIMP_PARAM_SPEC_RGB(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), GIMP_TYPE_PARAM_RGB, GimpParamSpecRGB))
579 typedef struct _GimpParamSpecRGB GimpParamSpecRGB;
581 struct _GimpParamSpecRGB
583 GParamSpecBoxed parent_instance;
585 gboolean has_alpha;
586 gboolean validate; /* change this to enable [0.0...1.0] */
587 GimpRGB default_value;
590 static void gimp_param_rgb_class_init (GParamSpecClass *class);
591 static void gimp_param_rgb_init (GParamSpec *pspec);
592 static void gimp_param_rgb_set_default (GParamSpec *pspec,
593 GValue *value);
594 static gboolean gimp_param_rgb_validate (GParamSpec *pspec,
595 GValue *value);
596 static gint gimp_param_rgb_values_cmp (GParamSpec *pspec,
597 const GValue *value1,
598 const GValue *value2);
601 * gimp_param_rgb_get_type:
603 * Reveals the object type
605 * Returns: the #GType for a GimpParamRGB object
607 * Since: 2.4
609 GType
610 gimp_param_rgb_get_type (void)
612 static GType spec_type = 0;
614 if (! spec_type)
616 const GTypeInfo type_info =
618 sizeof (GParamSpecClass),
619 NULL, NULL,
620 (GClassInitFunc) gimp_param_rgb_class_init,
621 NULL, NULL,
622 sizeof (GimpParamSpecRGB),
624 (GInstanceInitFunc) gimp_param_rgb_init
627 spec_type = g_type_register_static (G_TYPE_PARAM_BOXED,
628 "GimpParamRGB",
629 &type_info, 0);
632 return spec_type;
635 static void
636 gimp_param_rgb_class_init (GParamSpecClass *class)
638 class->value_type = GIMP_TYPE_RGB;
639 class->value_set_default = gimp_param_rgb_set_default;
640 class->value_validate = gimp_param_rgb_validate;
641 class->values_cmp = gimp_param_rgb_values_cmp;
644 static void
645 gimp_param_rgb_init (GParamSpec *pspec)
647 GimpParamSpecRGB *cspec = GIMP_PARAM_SPEC_RGB (pspec);
649 gimp_rgba_set (&cspec->default_value, 0.0, 0.0, 0.0, 1.0);
652 static void
653 gimp_param_rgb_set_default (GParamSpec *pspec,
654 GValue *value)
656 GimpParamSpecRGB *cspec = GIMP_PARAM_SPEC_RGB (pspec);
658 g_value_set_static_boxed (value, &cspec->default_value);
661 static gboolean
662 gimp_param_rgb_validate (GParamSpec *pspec,
663 GValue *value)
665 GimpParamSpecRGB *rgb_spec = GIMP_PARAM_SPEC_RGB (pspec);
666 GimpRGB *rgb = value->data[0].v_pointer;
668 if (rgb_spec->validate && rgb)
670 GimpRGB oval = *rgb;
672 gimp_rgb_clamp (rgb);
674 return (oval.r != rgb->r ||
675 oval.g != rgb->g ||
676 oval.b != rgb->b ||
677 (rgb_spec->has_alpha && oval.a != rgb->a));
680 return FALSE;
683 static gint
684 gimp_param_rgb_values_cmp (GParamSpec *pspec,
685 const GValue *value1,
686 const GValue *value2)
688 GimpRGB *rgb1 = value1->data[0].v_pointer;
689 GimpRGB *rgb2 = value2->data[0].v_pointer;
691 /* try to return at least *something*, it's useless anyway... */
693 if (! rgb1)
695 return rgb2 != NULL ? -1 : 0;
697 else if (! rgb2)
699 return rgb1 != NULL;
701 else
703 guint32 int1 = 0;
704 guint32 int2 = 0;
706 if (GIMP_PARAM_SPEC_RGB (pspec)->has_alpha)
708 gimp_rgba_get_uchar (rgb1,
709 ((guchar *) &int1) + 0,
710 ((guchar *) &int1) + 1,
711 ((guchar *) &int1) + 2,
712 ((guchar *) &int1) + 3);
713 gimp_rgba_get_uchar (rgb2,
714 ((guchar *) &int2) + 0,
715 ((guchar *) &int2) + 1,
716 ((guchar *) &int2) + 2,
717 ((guchar *) &int2) + 3);
719 else
721 gimp_rgb_get_uchar (rgb1,
722 ((guchar *) &int1) + 0,
723 ((guchar *) &int1) + 1,
724 ((guchar *) &int1) + 2);
725 gimp_rgb_get_uchar (rgb2,
726 ((guchar *) &int2) + 0,
727 ((guchar *) &int2) + 1,
728 ((guchar *) &int2) + 2);
731 return int1 - int2;
736 * gimp_param_spec_rgb:
737 * @name: Canonical name of the param
738 * @nick: Nickname of the param
739 * @blurb: Brief description of param.
740 * @has_alpha: %TRUE if the alpha channel has relevance.
741 * @default_value: Value to use if none is assigned.
742 * @flags: a combination of #GParamFlags
744 * Creates a param spec to hold an #GimpRGB value.
745 * See g_param_spec_internal() for more information.
747 * Returns: a newly allocated #GParamSpec instance
749 * Since: 2.4
751 GParamSpec *
752 gimp_param_spec_rgb (const gchar *name,
753 const gchar *nick,
754 const gchar *blurb,
755 gboolean has_alpha,
756 const GimpRGB *default_value,
757 GParamFlags flags)
759 GimpParamSpecRGB *cspec;
761 cspec = g_param_spec_internal (GIMP_TYPE_PARAM_RGB,
762 name, nick, blurb, flags);
764 cspec->has_alpha = has_alpha;
766 if (default_value)
767 cspec->default_value = *default_value;
769 return G_PARAM_SPEC (cspec);
773 * gimp_param_spec_rgb_has_alpha:
774 * @pspec: a #GParamSpec to hold an #GimpRGB value.
776 * Returns: %TRUE if the alpha channel is relevant.
778 * Since: 2.4
780 gboolean
781 gimp_param_spec_rgb_has_alpha (GParamSpec *pspec)
783 g_return_val_if_fail (GIMP_IS_PARAM_SPEC_RGB (pspec), FALSE);
785 return GIMP_PARAM_SPEC_RGB (pspec)->has_alpha;