summaryrefslogtreecommitdiffstats
path: root/app/gegl/gimp-babl.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/gegl/gimp-babl.c')
-rw-r--r--app/gegl/gimp-babl.c1415
1 files changed, 1415 insertions, 0 deletions
diff --git a/app/gegl/gimp-babl.c b/app/gegl/gimp-babl.c
new file mode 100644
index 0000000..b2dc20a
--- /dev/null
+++ b/app/gegl/gimp-babl.c
@@ -0,0 +1,1415 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimp-babl.c
+ * Copyright (C) 2012 Michael Natterer <mitch@gimp.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <cairo.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gegl.h>
+
+#include "libgimpcolor/gimpcolor.h"
+
+#include "gimp-gegl-types.h"
+
+#include "gimp-babl.h"
+
+#include "gimp-intl.h"
+
+
+void
+gimp_babl_init (void)
+{
+ babl_format_new ("name", "R u8",
+ babl_model ("RGBA"),
+ babl_type ("u8"),
+ babl_component ("R"),
+ NULL);
+ babl_format_new ("name", "R' u8",
+ babl_model ("R'G'B'A"),
+ babl_type ("u8"),
+ babl_component ("R'"),
+ NULL);
+ babl_format_new ("name", "G u8",
+ babl_model ("RGBA"),
+ babl_type ("u8"),
+ babl_component ("G"),
+ NULL);
+ babl_format_new ("name", "G' u8",
+ babl_model ("R'G'B'A"),
+ babl_type ("u8"),
+ babl_component ("G'"),
+ NULL);
+ babl_format_new ("name", "B u8",
+ babl_model ("RGBA"),
+ babl_type ("u8"),
+ babl_component ("B"),
+ NULL);
+ babl_format_new ("name", "B' u8",
+ babl_model ("R'G'B'A"),
+ babl_type ("u8"),
+ babl_component ("B'"),
+ NULL);
+ babl_format_new ("name", "A u8",
+ babl_model ("RGBA"),
+ babl_type ("u8"),
+ babl_component ("A"),
+ NULL);
+
+ babl_format_new ("name", "R u16",
+ babl_model ("RGBA"),
+ babl_type ("u16"),
+ babl_component ("R"),
+ NULL);
+ babl_format_new ("name", "R' u16",
+ babl_model ("R'G'B'A"),
+ babl_type ("u16"),
+ babl_component ("R'"),
+ NULL);
+ babl_format_new ("name", "G u16",
+ babl_model ("RGBA"),
+ babl_type ("u16"),
+ babl_component ("G"),
+ NULL);
+ babl_format_new ("name", "G' u16",
+ babl_model ("R'G'B'A"),
+ babl_type ("u16"),
+ babl_component ("G'"),
+ NULL);
+ babl_format_new ("name", "B u16",
+ babl_model ("RGBA"),
+ babl_type ("u16"),
+ babl_component ("B"),
+ NULL);
+ babl_format_new ("name", "B' u16",
+ babl_model ("R'G'B'A"),
+ babl_type ("u16"),
+ babl_component ("B'"),
+ NULL);
+ babl_format_new ("name", "A u16",
+ babl_model ("RGBA"),
+ babl_type ("u16"),
+ babl_component ("A"),
+ NULL);
+
+ babl_format_new ("name", "R u32",
+ babl_model ("RGBA"),
+ babl_type ("u32"),
+ babl_component ("R"),
+ NULL);
+ babl_format_new ("name", "R' u32",
+ babl_model ("R'G'B'A"),
+ babl_type ("u32"),
+ babl_component ("R'"),
+ NULL);
+ babl_format_new ("name", "G u32",
+ babl_model ("RGBA"),
+ babl_type ("u32"),
+ babl_component ("G"),
+ NULL);
+ babl_format_new ("name", "G' u32",
+ babl_model ("R'G'B'A"),
+ babl_type ("u32"),
+ babl_component ("G'"),
+ NULL);
+ babl_format_new ("name", "B u32",
+ babl_model ("RGBA"),
+ babl_type ("u32"),
+ babl_component ("B"),
+ NULL);
+ babl_format_new ("name", "B' u32",
+ babl_model ("R'G'B'A"),
+ babl_type ("u32"),
+ babl_component ("B'"),
+ NULL);
+ babl_format_new ("name", "A u32",
+ babl_model ("RGBA"),
+ babl_type ("u32"),
+ babl_component ("A"),
+ NULL);
+
+ babl_format_new ("name", "R half",
+ babl_model ("RGBA"),
+ babl_type ("half"),
+ babl_component ("R"),
+ NULL);
+ babl_format_new ("name", "R' half",
+ babl_model ("R'G'B'A"),
+ babl_type ("half"),
+ babl_component ("R'"),
+ NULL);
+ babl_format_new ("name", "G half",
+ babl_model ("RGBA"),
+ babl_type ("half"),
+ babl_component ("G"),
+ NULL);
+ babl_format_new ("name", "G' half",
+ babl_model ("R'G'B'A"),
+ babl_type ("half"),
+ babl_component ("G'"),
+ NULL);
+ babl_format_new ("name", "B half",
+ babl_model ("RGBA"),
+ babl_type ("half"),
+ babl_component ("B"),
+ NULL);
+ babl_format_new ("name", "B' half",
+ babl_model ("R'G'B'A"),
+ babl_type ("half"),
+ babl_component ("B'"),
+ NULL);
+ babl_format_new ("name", "A half",
+ babl_model ("RGBA"),
+ babl_type ("half"),
+ babl_component ("A"),
+ NULL);
+
+ babl_format_new ("name", "R float",
+ babl_model ("RGBA"),
+ babl_type ("float"),
+ babl_component ("R"),
+ NULL);
+ babl_format_new ("name", "R' float",
+ babl_model ("R'G'B'A"),
+ babl_type ("float"),
+ babl_component ("R'"),
+ NULL);
+ babl_format_new ("name", "G float",
+ babl_model ("RGBA"),
+ babl_type ("float"),
+ babl_component ("G"),
+ NULL);
+ babl_format_new ("name", "G' float",
+ babl_model ("R'G'B'A"),
+ babl_type ("float"),
+ babl_component ("G'"),
+ NULL);
+ babl_format_new ("name", "B float",
+ babl_model ("RGBA"),
+ babl_type ("float"),
+ babl_component ("B"),
+ NULL);
+ babl_format_new ("name", "B' float",
+ babl_model ("R'G'B'A"),
+ babl_type ("float"),
+ babl_component ("B'"),
+ NULL);
+ babl_format_new ("name", "A float",
+ babl_model ("RGBA"),
+ babl_type ("float"),
+ babl_component ("A"),
+ NULL);
+
+ babl_format_new ("name", "R double",
+ babl_model ("RGBA"),
+ babl_type ("double"),
+ babl_component ("R"),
+ NULL);
+ babl_format_new ("name", "R' double",
+ babl_model ("R'G'B'A"),
+ babl_type ("double"),
+ babl_component ("R'"),
+ NULL);
+ babl_format_new ("name", "G double",
+ babl_model ("RGBA"),
+ babl_type ("double"),
+ babl_component ("G"),
+ NULL);
+ babl_format_new ("name", "G' double",
+ babl_model ("R'G'B'A"),
+ babl_type ("double"),
+ babl_component ("G'"),
+ NULL);
+ babl_format_new ("name", "B double",
+ babl_model ("RGBA"),
+ babl_type ("double"),
+ babl_component ("B"),
+ NULL);
+ babl_format_new ("name", "B' double",
+ babl_model ("R'G'B'A"),
+ babl_type ("double"),
+ babl_component ("B'"),
+ NULL);
+ babl_format_new ("name", "A double",
+ babl_model ("RGBA"),
+ babl_type ("double"),
+ babl_component ("A"),
+ NULL);
+}
+
+void
+gimp_babl_init_fishes (GimpInitStatusFunc status_callback)
+{
+ /* create a bunch of fishes - to decrease the initial lazy
+ * initialization cost for some interactions
+ */
+ static const struct
+ {
+ const gchar *from_format;
+ const gchar *to_format;
+ }
+ fishes[] =
+ {
+ { "Y' u8", "RaGaBaA float" },
+ { "Y u8", "RaGaBaA float" },
+ { "R'G'B'A u8", "RaGaBaA float" },
+ { "R'G'B'A float", "R'G'B'A u8" },
+ { "R'G'B'A float", "R'G'B' u8" },
+ { "R'G'B'A u8", "RGBA float" },
+ { "RGBA float", "R'G'B'A u8" },
+ { "RGBA float", "R'G'B'A u8" },
+ { "RGBA float", "R'G'B'A float" },
+ { "Y' u8", "R'G'B' u8" },
+ { "Y u8", "Y float" },
+ { "R'G'B' u8", "cairo-RGB24" },
+ { "R'G'B' u8", "R'G'B'A float" },
+ { "R'G'B' u8", "R'G'B'A u8" },
+ { "R'G'B'A u8", "R'G'B'A float" },
+ { "R'G'B'A u8", "cairo-ARGB32" },
+ { "R'G'B'A double", "RGBA float" },
+ { "R'G'B'A float", "RGBA double" },
+ { "R'G'B' u8", "RGB float" },
+ { "RGB float", "R'G'B'A float" },
+ { "R'G'B' u8", "RGBA float" },
+ { "RaGaBaA float", "R'G'B'A float" },
+ { "RaGaBaA float", "RGBA float" },
+ { "RGBA float", "RaGaBaA float" },
+ { "R'G'B' u8", "RaGaBaA float" },
+ { "cairo-ARGB32", "R'G'B'A u8" }
+ };
+
+ gint i;
+
+ for (i = 0; i < G_N_ELEMENTS (fishes); i++)
+ {
+ status_callback (NULL, NULL,
+ (gdouble) (i + 1) /
+ (gdouble) G_N_ELEMENTS (fishes) * 0.8);
+
+ babl_fish (babl_format (fishes[i].from_format),
+ babl_format (fishes[i].to_format));
+ }
+}
+
+static const struct
+{
+ const gchar *name;
+ const gchar *description;
+}
+babl_descriptions[] =
+{
+ { "RGB u8", N_("RGB") },
+ { "R'G'B' u8", N_("RGB") },
+ { "RGB u16", N_("RGB") },
+ { "R'G'B' u16", N_("RGB") },
+ { "RGB u32", N_("RGB") },
+ { "R'G'B' u32", N_("RGB") },
+ { "RGB half", N_("RGB") },
+ { "R'G'B' half", N_("RGB") },
+ { "RGB float", N_("RGB") },
+ { "R'G'B' float", N_("RGB") },
+ { "RGB double", N_("RGB") },
+ { "R'G'B' double", N_("RGB") },
+
+ { "RGBA u8", N_("RGB-alpha") },
+ { "R'G'B'A u8", N_("RGB-alpha") },
+ { "RGBA u16", N_("RGB-alpha") },
+ { "R'G'B'A u16", N_("RGB-alpha") },
+ { "RGBA u32", N_("RGB-alpha") },
+ { "R'G'B'A u32", N_("RGB-alpha") },
+ { "RGBA half", N_("RGB-alpha") },
+ { "R'G'B'A half", N_("RGB-alpha") },
+ { "RGBA float", N_("RGB-alpha") },
+ { "R'G'B'A float", N_("RGB-alpha") },
+ { "RGBA double", N_("RGB-alpha") },
+ { "R'G'B'A double", N_("RGB-alpha") },
+
+ { "Y u8", N_("Grayscale") },
+ { "Y' u8", N_("Grayscale") },
+ { "Y u16", N_("Grayscale") },
+ { "Y' u16", N_("Grayscale") },
+ { "Y u32", N_("Grayscale") },
+ { "Y' u32", N_("Grayscale") },
+ { "Y half", N_("Grayscale") },
+ { "Y' half", N_("Grayscale") },
+ { "Y float", N_("Grayscale") },
+ { "Y' float", N_("Grayscale") },
+ { "Y double", N_("Grayscale") },
+ { "Y' double", N_("Grayscale") },
+
+ { "YA u8", N_("Grayscale-alpha") },
+ { "Y'A u8", N_("Grayscale-alpha") },
+ { "YA u16", N_("Grayscale-alpha") },
+ { "Y'A u16", N_("Grayscale-alpha") },
+ { "YA u32", N_("Grayscale-alpha") },
+ { "Y'A u32", N_("Grayscale-alpha") },
+ { "YA half", N_("Grayscale-alpha") },
+ { "Y'A half", N_("Grayscale-alpha") },
+ { "YA float", N_("Grayscale-alpha") },
+ { "Y'A float", N_("Grayscale-alpha") },
+ { "YA double", N_("Grayscale-alpha") },
+ { "Y'A double", N_("Grayscale-alpha") },
+
+ { "R u8", N_("Red component") },
+ { "R' u8", N_("Red component") },
+ { "R u16", N_("Red component") },
+ { "R' u16", N_("Red component") },
+ { "R u32", N_("Red component") },
+ { "R' u32", N_("Red component") },
+ { "R half", N_("Red component") },
+ { "R' half", N_("Red component") },
+ { "R float", N_("Red component") },
+ { "R' float", N_("Red component") },
+ { "R double", N_("Red component") },
+ { "R' double", N_("Red component") },
+
+ { "G u8", N_("Green component") },
+ { "G' u8", N_("Green component") },
+ { "G u16", N_("Green component") },
+ { "G' u16", N_("Green component") },
+ { "G u32", N_("Green component") },
+ { "G' u32", N_("Green component") },
+ { "G half", N_("Green component") },
+ { "G' half", N_("Green component") },
+ { "G float", N_("Green component") },
+ { "G' float", N_("Green component") },
+ { "G double", N_("Green component") },
+ { "G' double", N_("Green component") },
+
+ { "B u8", N_("Blue component") },
+ { "B' u8", N_("Blue component") },
+ { "B u16", N_("Blue component") },
+ { "B' u16", N_("Blue component") },
+ { "B u32", N_("Blue component") },
+ { "B' u32", N_("Blue component") },
+ { "B half", N_("Blue component") },
+ { "B' half", N_("Blue component") },
+ { "B float", N_("Blue component") },
+ { "B' float", N_("Blue component") },
+ { "B double", N_("Blue component") },
+ { "B' double", N_("Blue component") },
+
+ { "A u8", N_("Alpha component") },
+ { "A u16", N_("Alpha component") },
+ { "A u32", N_("Alpha component") },
+ { "A half", N_("Alpha component") },
+ { "A float", N_("Alpha component") },
+ { "A double", N_("Alpha component") }
+};
+
+static GHashTable *babl_description_hash = NULL;
+
+const gchar *
+gimp_babl_format_get_description (const Babl *babl)
+{
+ const gchar *description;
+
+ g_return_val_if_fail (babl != NULL, NULL);
+
+ if (G_UNLIKELY (! babl_description_hash))
+ {
+ gint i;
+
+ babl_description_hash = g_hash_table_new (g_str_hash,
+ g_str_equal);
+
+ for (i = 0; i < G_N_ELEMENTS (babl_descriptions); i++)
+ g_hash_table_insert (babl_description_hash,
+ (gpointer) babl_descriptions[i].name,
+ gettext (babl_descriptions[i].description));
+ }
+
+ if (babl_format_is_palette (babl))
+ {
+ if (babl_format_has_alpha (babl))
+ return _("Indexed-alpha");
+ else
+ return _("Indexed");
+ }
+
+ description = g_hash_table_lookup (babl_description_hash,
+ babl_get_name (babl));
+
+ if (description)
+ return description;
+
+ return g_strconcat ("ERROR: unknown Babl format ",
+ babl_get_name (babl), NULL);
+}
+
+GimpColorProfile *
+gimp_babl_format_get_color_profile (const Babl *format)
+{
+ static GimpColorProfile *srgb_profile = NULL;
+ static GimpColorProfile *linear_rgb_profile = NULL;
+ static GimpColorProfile *gray_profile = NULL;
+ static GimpColorProfile *linear_gray_profile = NULL;
+
+ g_return_val_if_fail (format != NULL, NULL);
+
+ if (gimp_babl_format_get_base_type (format) == GIMP_GRAY)
+ {
+ if (gimp_babl_format_get_linear (format))
+ {
+ if (! linear_gray_profile)
+ {
+ linear_gray_profile = gimp_color_profile_new_d65_gray_linear ();
+ g_object_add_weak_pointer (G_OBJECT (linear_gray_profile),
+ (gpointer) &linear_gray_profile);
+ }
+
+ return linear_gray_profile;
+ }
+ else
+ {
+ if (! gray_profile)
+ {
+ gray_profile = gimp_color_profile_new_d65_gray_srgb_trc ();
+ g_object_add_weak_pointer (G_OBJECT (gray_profile),
+ (gpointer) &gray_profile);
+ }
+
+ return gray_profile;
+ }
+ }
+ else
+ {
+ if (gimp_babl_format_get_linear (format))
+ {
+ if (! linear_rgb_profile)
+ {
+ linear_rgb_profile = gimp_color_profile_new_rgb_srgb_linear ();
+ g_object_add_weak_pointer (G_OBJECT (linear_rgb_profile),
+ (gpointer) &linear_rgb_profile);
+ }
+
+ return linear_rgb_profile;
+ }
+ else
+ {
+ if (! srgb_profile)
+ {
+ srgb_profile = gimp_color_profile_new_rgb_srgb ();
+ g_object_add_weak_pointer (G_OBJECT (srgb_profile),
+ (gpointer) &srgb_profile);
+ }
+
+ return srgb_profile;
+ }
+ }
+}
+
+GimpImageBaseType
+gimp_babl_format_get_base_type (const Babl *format)
+{
+ const Babl *model;
+
+ g_return_val_if_fail (format != NULL, -1);
+
+ model = babl_format_get_model (format);
+
+ if (model == babl_model ("Y") ||
+ model == babl_model ("Y'") ||
+ model == babl_model ("YA") ||
+ model == babl_model ("Y'A"))
+ {
+ return GIMP_GRAY;
+ }
+ else if (model == babl_model ("RGB") ||
+ model == babl_model ("R'G'B'") ||
+ model == babl_model ("RGBA") ||
+ model == babl_model ("R'G'B'A") ||
+ model == babl_model ("RaGaBaA") ||
+ model == babl_model ("R'aG'aB'aA"))
+ {
+ return GIMP_RGB;
+ }
+ else if (babl_format_is_palette (format))
+ {
+ return GIMP_INDEXED;
+ }
+
+ g_return_val_if_reached (-1);
+}
+
+GimpComponentType
+gimp_babl_format_get_component_type (const Babl *format)
+{
+ const Babl *type;
+
+ g_return_val_if_fail (format != NULL, -1);
+
+ type = babl_format_get_type (format, 0);
+
+ if (type == babl_type ("u8"))
+ return GIMP_COMPONENT_TYPE_U8;
+ else if (type == babl_type ("u16"))
+ return GIMP_COMPONENT_TYPE_U16;
+ else if (type == babl_type ("u32"))
+ return GIMP_COMPONENT_TYPE_U32;
+ else if (type == babl_type ("half"))
+ return GIMP_COMPONENT_TYPE_HALF;
+ else if (type == babl_type ("float"))
+ return GIMP_COMPONENT_TYPE_FLOAT;
+ else if (type == babl_type ("double"))
+ return GIMP_COMPONENT_TYPE_DOUBLE;
+
+ g_return_val_if_reached (-1);
+}
+
+GimpPrecision
+gimp_babl_format_get_precision (const Babl *format)
+{
+ const Babl *type;
+
+ g_return_val_if_fail (format != NULL, -1);
+
+ type = babl_format_get_type (format, 0);
+
+ if (gimp_babl_format_get_linear (format))
+ {
+ if (type == babl_type ("u8"))
+ return GIMP_PRECISION_U8_LINEAR;
+ else if (type == babl_type ("u16"))
+ return GIMP_PRECISION_U16_LINEAR;
+ else if (type == babl_type ("u32"))
+ return GIMP_PRECISION_U32_LINEAR;
+ else if (type == babl_type ("half"))
+ return GIMP_PRECISION_HALF_LINEAR;
+ else if (type == babl_type ("float"))
+ return GIMP_PRECISION_FLOAT_LINEAR;
+ else if (type == babl_type ("double"))
+ return GIMP_PRECISION_DOUBLE_LINEAR;
+ }
+ else
+ {
+ if (type == babl_type ("u8"))
+ return GIMP_PRECISION_U8_GAMMA;
+ else if (type == babl_type ("u16"))
+ return GIMP_PRECISION_U16_GAMMA;
+ else if (type == babl_type ("u32"))
+ return GIMP_PRECISION_U32_GAMMA;
+ else if (type == babl_type ("half"))
+ return GIMP_PRECISION_HALF_GAMMA;
+ else if (type == babl_type ("float"))
+ return GIMP_PRECISION_FLOAT_GAMMA;
+ else if (type == babl_type ("double"))
+ return GIMP_PRECISION_DOUBLE_GAMMA;
+ }
+
+ g_return_val_if_reached (-1);
+}
+
+gboolean
+gimp_babl_format_get_linear (const Babl *format)
+{
+ const Babl *model;
+
+ g_return_val_if_fail (format != NULL, FALSE);
+
+ model = babl_format_get_model (format);
+
+ if (model == babl_model ("Y") ||
+ model == babl_model ("YA") ||
+ model == babl_model ("RGB") ||
+ model == babl_model ("RGBA") ||
+ model == babl_model ("RaGaBaA"))
+ {
+ return TRUE;
+ }
+ else if (model == babl_model ("Y'") ||
+ model == babl_model ("Y'A") ||
+ model == babl_model ("R'G'B'") ||
+ model == babl_model ("R'G'B'A") ||
+ model == babl_model ("R'aG'aB'aA"))
+ {
+ return FALSE;
+ }
+ else if (babl_format_is_palette (format))
+ {
+ return FALSE;
+ }
+
+ g_return_val_if_reached (FALSE);
+}
+
+GimpComponentType
+gimp_babl_component_type (GimpPrecision precision)
+{
+ switch (precision)
+ {
+ case GIMP_PRECISION_U8_LINEAR:
+ case GIMP_PRECISION_U8_GAMMA:
+ return GIMP_COMPONENT_TYPE_U8;
+
+ case GIMP_PRECISION_U16_LINEAR:
+ case GIMP_PRECISION_U16_GAMMA:
+ return GIMP_COMPONENT_TYPE_U16;
+
+ case GIMP_PRECISION_U32_LINEAR:
+ case GIMP_PRECISION_U32_GAMMA:
+ return GIMP_COMPONENT_TYPE_U32;
+
+ case GIMP_PRECISION_HALF_LINEAR:
+ case GIMP_PRECISION_HALF_GAMMA:
+ return GIMP_COMPONENT_TYPE_HALF;
+
+ case GIMP_PRECISION_FLOAT_LINEAR:
+ case GIMP_PRECISION_FLOAT_GAMMA:
+ return GIMP_COMPONENT_TYPE_FLOAT;
+
+ case GIMP_PRECISION_DOUBLE_LINEAR:
+ case GIMP_PRECISION_DOUBLE_GAMMA:
+ return GIMP_COMPONENT_TYPE_DOUBLE;
+ }
+
+ g_return_val_if_reached (-1);
+}
+
+gboolean
+gimp_babl_linear (GimpPrecision precision)
+{
+ switch (precision)
+ {
+ case GIMP_PRECISION_U8_LINEAR:
+ case GIMP_PRECISION_U16_LINEAR:
+ case GIMP_PRECISION_U32_LINEAR:
+ case GIMP_PRECISION_HALF_LINEAR:
+ case GIMP_PRECISION_FLOAT_LINEAR:
+ case GIMP_PRECISION_DOUBLE_LINEAR:
+ return TRUE;
+
+ case GIMP_PRECISION_U8_GAMMA:
+ case GIMP_PRECISION_U16_GAMMA:
+ case GIMP_PRECISION_U32_GAMMA:
+ case GIMP_PRECISION_HALF_GAMMA:
+ case GIMP_PRECISION_FLOAT_GAMMA:
+ case GIMP_PRECISION_DOUBLE_GAMMA:
+ return FALSE;
+ }
+
+ g_return_val_if_reached (FALSE);
+}
+
+GimpPrecision
+gimp_babl_precision (GimpComponentType component,
+ gboolean linear)
+{
+ switch (component)
+ {
+ case GIMP_COMPONENT_TYPE_U8:
+ if (linear)
+ return GIMP_PRECISION_U8_LINEAR;
+ else
+ return GIMP_PRECISION_U8_GAMMA;
+
+ case GIMP_COMPONENT_TYPE_U16:
+ if (linear)
+ return GIMP_PRECISION_U16_LINEAR;
+ else
+ return GIMP_PRECISION_U16_GAMMA;
+
+ case GIMP_COMPONENT_TYPE_U32:
+ if (linear)
+ return GIMP_PRECISION_U32_LINEAR;
+ else
+ return GIMP_PRECISION_U32_GAMMA;
+
+ case GIMP_COMPONENT_TYPE_HALF:
+ if (linear)
+ return GIMP_PRECISION_HALF_LINEAR;
+ else
+ return GIMP_PRECISION_HALF_GAMMA;
+
+ case GIMP_COMPONENT_TYPE_FLOAT:
+ if (linear)
+ return GIMP_PRECISION_FLOAT_LINEAR;
+ else
+ return GIMP_PRECISION_FLOAT_GAMMA;
+
+ case GIMP_COMPONENT_TYPE_DOUBLE:
+ if (linear)
+ return GIMP_PRECISION_DOUBLE_LINEAR;
+ else
+ return GIMP_PRECISION_DOUBLE_GAMMA;
+
+ default:
+ break;
+ }
+
+ g_return_val_if_reached (-1);
+}
+
+gboolean
+gimp_babl_is_valid (GimpImageBaseType base_type,
+ GimpPrecision precision)
+{
+ switch (base_type)
+ {
+ case GIMP_RGB:
+ case GIMP_GRAY:
+ return TRUE;
+
+ case GIMP_INDEXED:
+ switch (precision)
+ {
+ case GIMP_PRECISION_U8_GAMMA:
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+ }
+
+ g_return_val_if_reached (FALSE);
+}
+
+GimpComponentType
+gimp_babl_is_bounded (GimpPrecision precision)
+{
+ switch (gimp_babl_component_type (precision))
+ {
+ case GIMP_COMPONENT_TYPE_U8:
+ case GIMP_COMPONENT_TYPE_U16:
+ case GIMP_COMPONENT_TYPE_U32:
+ return TRUE;
+
+ case GIMP_COMPONENT_TYPE_HALF:
+ case GIMP_COMPONENT_TYPE_FLOAT:
+ case GIMP_COMPONENT_TYPE_DOUBLE:
+ return FALSE;
+ }
+
+ g_return_val_if_reached (FALSE);
+}
+
+const Babl *
+gimp_babl_format (GimpImageBaseType base_type,
+ GimpPrecision precision,
+ gboolean with_alpha)
+{
+ switch (base_type)
+ {
+ case GIMP_RGB:
+ switch (precision)
+ {
+ case GIMP_PRECISION_U8_LINEAR:
+ if (with_alpha)
+ return babl_format ("RGBA u8");
+ else
+ return babl_format ("RGB u8");
+
+ case GIMP_PRECISION_U8_GAMMA:
+ if (with_alpha)
+ return babl_format ("R'G'B'A u8");
+ else
+ return babl_format ("R'G'B' u8");
+
+ case GIMP_PRECISION_U16_LINEAR:
+ if (with_alpha)
+ return babl_format ("RGBA u16");
+ else
+ return babl_format ("RGB u16");
+
+ case GIMP_PRECISION_U16_GAMMA:
+ if (with_alpha)
+ return babl_format ("R'G'B'A u16");
+ else
+ return babl_format ("R'G'B' u16");
+
+ case GIMP_PRECISION_U32_LINEAR:
+ if (with_alpha)
+ return babl_format ("RGBA u32");
+ else
+ return babl_format ("RGB u32");
+
+ case GIMP_PRECISION_U32_GAMMA:
+ if (with_alpha)
+ return babl_format ("R'G'B'A u32");
+ else
+ return babl_format ("R'G'B' u32");
+
+ case GIMP_PRECISION_HALF_LINEAR:
+ if (with_alpha)
+ return babl_format ("RGBA half");
+ else
+ return babl_format ("RGB half");
+
+ case GIMP_PRECISION_HALF_GAMMA:
+ if (with_alpha)
+ return babl_format ("R'G'B'A half");
+ else
+ return babl_format ("R'G'B' half");
+
+ case GIMP_PRECISION_FLOAT_LINEAR:
+ if (with_alpha)
+ return babl_format ("RGBA float");
+ else
+ return babl_format ("RGB float");
+
+ case GIMP_PRECISION_FLOAT_GAMMA:
+ if (with_alpha)
+ return babl_format ("R'G'B'A float");
+ else
+ return babl_format ("R'G'B' float");
+
+ case GIMP_PRECISION_DOUBLE_LINEAR:
+ if (with_alpha)
+ return babl_format ("RGBA double");
+ else
+ return babl_format ("RGB double");
+
+ case GIMP_PRECISION_DOUBLE_GAMMA:
+ if (with_alpha)
+ return babl_format ("R'G'B'A double");
+ else
+ return babl_format ("R'G'B' double");
+
+ default:
+ break;
+ }
+ break;
+
+ case GIMP_GRAY:
+ switch (precision)
+ {
+ case GIMP_PRECISION_U8_LINEAR:
+ if (with_alpha)
+ return babl_format ("YA u8");
+ else
+ return babl_format ("Y u8");
+
+ case GIMP_PRECISION_U8_GAMMA:
+ if (with_alpha)
+ return babl_format ("Y'A u8");
+ else
+ return babl_format ("Y' u8");
+
+ case GIMP_PRECISION_U16_LINEAR:
+ if (with_alpha)
+ return babl_format ("YA u16");
+ else
+ return babl_format ("Y u16");
+
+ case GIMP_PRECISION_U16_GAMMA:
+ if (with_alpha)
+ return babl_format ("Y'A u16");
+ else
+ return babl_format ("Y' u16");
+
+ case GIMP_PRECISION_U32_LINEAR:
+ if (with_alpha)
+ return babl_format ("YA u32");
+ else
+ return babl_format ("Y u32");
+
+ case GIMP_PRECISION_U32_GAMMA:
+ if (with_alpha)
+ return babl_format ("Y'A u32");
+ else
+ return babl_format ("Y' u32");
+
+ case GIMP_PRECISION_HALF_LINEAR:
+ if (with_alpha)
+ return babl_format ("YA half");
+ else
+ return babl_format ("Y half");
+
+ case GIMP_PRECISION_HALF_GAMMA:
+ if (with_alpha)
+ return babl_format ("Y'A half");
+ else
+ return babl_format ("Y' half");
+
+ case GIMP_PRECISION_FLOAT_LINEAR:
+ if (with_alpha)
+ return babl_format ("YA float");
+ else
+ return babl_format ("Y float");
+
+ case GIMP_PRECISION_FLOAT_GAMMA:
+ if (with_alpha)
+ return babl_format ("Y'A float");
+ else
+ return babl_format ("Y' float");
+
+ case GIMP_PRECISION_DOUBLE_LINEAR:
+ if (with_alpha)
+ return babl_format ("YA double");
+ else
+ return babl_format ("Y double");
+
+ case GIMP_PRECISION_DOUBLE_GAMMA:
+ if (with_alpha)
+ return babl_format ("Y'A double");
+ else
+ return babl_format ("Y' double");
+
+ default:
+ break;
+ }
+ break;
+
+ case GIMP_INDEXED:
+ /* need to use the image's api for this */
+ break;
+ }
+
+ g_return_val_if_reached (NULL);
+}
+
+const Babl *
+gimp_babl_mask_format (GimpPrecision precision)
+{
+ switch (gimp_babl_component_type (precision))
+ {
+ case GIMP_COMPONENT_TYPE_U8: return babl_format ("Y u8");
+ case GIMP_COMPONENT_TYPE_U16: return babl_format ("Y u16");
+ case GIMP_COMPONENT_TYPE_U32: return babl_format ("Y u32");
+ case GIMP_COMPONENT_TYPE_HALF: return babl_format ("Y half");
+ case GIMP_COMPONENT_TYPE_FLOAT: return babl_format ("Y float");
+ case GIMP_COMPONENT_TYPE_DOUBLE: return babl_format ("Y double");
+ }
+
+ g_return_val_if_reached (NULL);
+}
+
+const Babl *
+gimp_babl_component_format (GimpImageBaseType base_type,
+ GimpPrecision precision,
+ gint index)
+{
+ switch (base_type)
+ {
+ case GIMP_RGB:
+ switch (precision)
+ {
+ case GIMP_PRECISION_U8_LINEAR:
+ switch (index)
+ {
+ case 0: return babl_format ("R u8");
+ case 1: return babl_format ("G u8");
+ case 2: return babl_format ("B u8");
+ case 3: return babl_format ("A u8");
+ default:
+ break;
+ }
+ break;
+
+ case GIMP_PRECISION_U8_GAMMA:
+ switch (index)
+ {
+ case 0: return babl_format ("R' u8");
+ case 1: return babl_format ("G' u8");
+ case 2: return babl_format ("B' u8");
+ case 3: return babl_format ("A u8");
+ default:
+ break;
+ }
+ break;
+
+ case GIMP_PRECISION_U16_LINEAR:
+ switch (index)
+ {
+ case 0: return babl_format ("R u16");
+ case 1: return babl_format ("G u16");
+ case 2: return babl_format ("B u16");
+ case 3: return babl_format ("A u16");
+ default:
+ break;
+ }
+ break;
+
+ case GIMP_PRECISION_U16_GAMMA:
+ switch (index)
+ {
+ case 0: return babl_format ("R' u16");
+ case 1: return babl_format ("G' u16");
+ case 2: return babl_format ("B' u16");
+ case 3: return babl_format ("A u16");
+ default:
+ break;
+ }
+ break;
+
+ case GIMP_PRECISION_U32_LINEAR:
+ switch (index)
+ {
+ case 0: return babl_format ("R u32");
+ case 1: return babl_format ("G u32");
+ case 2: return babl_format ("B u32");
+ case 3: return babl_format ("A u32");
+ default:
+ break;
+ }
+ break;
+
+ case GIMP_PRECISION_U32_GAMMA:
+ switch (index)
+ {
+ case 0: return babl_format ("R' u32");
+ case 1: return babl_format ("G' u32");
+ case 2: return babl_format ("B' u32");
+ case 3: return babl_format ("A u32");
+ default:
+ break;
+ }
+ break;
+
+ case GIMP_PRECISION_HALF_LINEAR:
+ switch (index)
+ {
+ case 0: return babl_format ("R half");
+ case 1: return babl_format ("G half");
+ case 2: return babl_format ("B half");
+ case 3: return babl_format ("A half");
+ default:
+ break;
+ }
+ break;
+
+ case GIMP_PRECISION_HALF_GAMMA:
+ switch (index)
+ {
+ case 0: return babl_format ("R' half");
+ case 1: return babl_format ("G' half");
+ case 2: return babl_format ("B' half");
+ case 3: return babl_format ("A half");
+ default:
+ break;
+ }
+ break;
+
+ case GIMP_PRECISION_FLOAT_LINEAR:
+ switch (index)
+ {
+ case 0: return babl_format ("R float");
+ case 1: return babl_format ("G float");
+ case 2: return babl_format ("B float");
+ case 3: return babl_format ("A float");
+ default:
+ break;
+ }
+ break;
+
+ case GIMP_PRECISION_FLOAT_GAMMA:
+ switch (index)
+ {
+ case 0: return babl_format ("R' float");
+ case 1: return babl_format ("G' float");
+ case 2: return babl_format ("B' float");
+ case 3: return babl_format ("A float");
+ default:
+ break;
+ }
+ break;
+
+ case GIMP_PRECISION_DOUBLE_LINEAR:
+ switch (index)
+ {
+ case 0: return babl_format ("R double");
+ case 1: return babl_format ("G double");
+ case 2: return babl_format ("B double");
+ case 3: return babl_format ("A double");
+ default:
+ break;
+ }
+ break;
+
+ case GIMP_PRECISION_DOUBLE_GAMMA:
+ switch (index)
+ {
+ case 0: return babl_format ("R' double");
+ case 1: return babl_format ("G' double");
+ case 2: return babl_format ("B' double");
+ case 3: return babl_format ("A double");
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case GIMP_GRAY:
+ switch (precision)
+ {
+ case GIMP_PRECISION_U8_LINEAR:
+ switch (index)
+ {
+ case 0: return babl_format ("Y u8");
+ case 1: return babl_format ("A u8");
+ default:
+ break;
+ }
+ break;
+
+ case GIMP_PRECISION_U8_GAMMA:
+ switch (index)
+ {
+ case 0: return babl_format ("Y' u8");
+ case 1: return babl_format ("A u8");
+ default:
+ break;
+ }
+ break;
+
+ case GIMP_PRECISION_U16_LINEAR:
+ switch (index)
+ {
+ case 0: return babl_format ("Y u16");
+ case 1: return babl_format ("A u16");
+ default:
+ break;
+ }
+ break;
+
+ case GIMP_PRECISION_U16_GAMMA:
+ switch (index)
+ {
+ case 0: return babl_format ("Y' u16");
+ case 1: return babl_format ("A u16");
+ default:
+ break;
+ }
+ break;
+
+ case GIMP_PRECISION_U32_LINEAR:
+ switch (index)
+ {
+ case 0: return babl_format ("Y u32");
+ case 1: return babl_format ("A u32");
+ default:
+ break;
+ }
+ break;
+
+ case GIMP_PRECISION_U32_GAMMA:
+ switch (index)
+ {
+ case 0: return babl_format ("Y' u32");
+ case 1: return babl_format ("A u32");
+ default:
+ break;
+ }
+ break;
+
+ case GIMP_PRECISION_HALF_LINEAR:
+ switch (index)
+ {
+ case 0: return babl_format ("Y half");
+ case 1: return babl_format ("A half");
+ default:
+ break;
+ }
+ break;
+
+ case GIMP_PRECISION_HALF_GAMMA:
+ switch (index)
+ {
+ case 0: return babl_format ("Y' half");
+ case 1: return babl_format ("A half");
+ default:
+ break;
+ }
+ break;
+
+ case GIMP_PRECISION_FLOAT_LINEAR:
+ switch (index)
+ {
+ case 0: return babl_format ("Y float");
+ case 1: return babl_format ("A float");
+ default:
+ break;
+ }
+ break;
+
+ case GIMP_PRECISION_FLOAT_GAMMA:
+ switch (index)
+ {
+ case 0: return babl_format ("Y' float");
+ case 1: return babl_format ("A float");
+ default:
+ break;
+ }
+ break;
+
+ case GIMP_PRECISION_DOUBLE_LINEAR:
+ switch (index)
+ {
+ case 0: return babl_format ("Y double");
+ case 1: return babl_format ("A double");
+ default:
+ break;
+ }
+ break;
+
+ case GIMP_PRECISION_DOUBLE_GAMMA:
+ switch (index)
+ {
+ case 0: return babl_format ("Y' double");
+ case 1: return babl_format ("A double");
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case GIMP_INDEXED:
+ /* need to use the image's api for this */
+ break;
+ }
+
+ g_return_val_if_reached (NULL);
+}
+
+const Babl *
+gimp_babl_format_change_component_type (const Babl *format,
+ GimpComponentType component)
+{
+ g_return_val_if_fail (format != NULL, NULL);
+
+ return gimp_babl_format (gimp_babl_format_get_base_type (format),
+ gimp_babl_precision (
+ component,
+ gimp_babl_format_get_linear (format)),
+ babl_format_has_alpha (format));
+}
+
+const Babl *
+gimp_babl_format_change_linear (const Babl *format,
+ gboolean linear)
+{
+ g_return_val_if_fail (format != NULL, NULL);
+
+ return gimp_babl_format (gimp_babl_format_get_base_type (format),
+ gimp_babl_precision (
+ gimp_babl_format_get_component_type (format),
+ linear),
+ babl_format_has_alpha (format));
+}
+
+gchar **
+gimp_babl_print_pixel (const Babl *format,
+ gpointer pixel)
+{
+ GimpPrecision precision;
+ gint n_components;
+ guchar tmp_pixel[32];
+ gchar **strings;
+
+ g_return_val_if_fail (format != NULL, NULL);
+ g_return_val_if_fail (pixel != NULL, NULL);
+
+ precision = gimp_babl_format_get_precision (format);
+
+ if (babl_format_is_palette (format))
+ {
+ const Babl *f = gimp_babl_format (GIMP_RGB, precision,
+ babl_format_has_alpha (format));
+
+ babl_process (babl_fish (format, f), pixel, tmp_pixel, 1);
+
+ format = f;
+ pixel = tmp_pixel;
+ }
+
+ n_components = babl_format_get_n_components (format);
+
+ strings = g_new0 (gchar *, n_components + 1);
+
+ switch (gimp_babl_format_get_component_type (format))
+ {
+ case GIMP_COMPONENT_TYPE_U8:
+ {
+ guchar *color = pixel;
+ gint i;
+
+ for (i = 0; i < n_components; i++)
+ strings[i] = g_strdup_printf ("%d", color[i]);
+ }
+ break;
+
+ case GIMP_COMPONENT_TYPE_U16:
+ {
+ guint16 *color = pixel;
+ gint i;
+
+ for (i = 0; i < n_components; i++)
+ strings[i] = g_strdup_printf ("%u", color[i]);
+ }
+ break;
+
+ case GIMP_COMPONENT_TYPE_U32:
+ {
+ guint32 *color = pixel;
+ gint i;
+
+ for (i = 0; i < n_components; i++)
+ strings[i] = g_strdup_printf ("%u", color[i]);
+ }
+ break;
+
+ case GIMP_COMPONENT_TYPE_HALF:
+ {
+ GimpPrecision p;
+ const Babl *f;
+
+ p = gimp_babl_precision (GIMP_COMPONENT_TYPE_FLOAT,
+ gimp_babl_format_get_linear (format));
+
+ f = gimp_babl_format (gimp_babl_format_get_base_type (format),
+ p,
+ babl_format_has_alpha (format));
+
+ babl_process (babl_fish (format, f), pixel, tmp_pixel, 1);
+
+ pixel = tmp_pixel;
+ }
+ /* fall through */
+
+ case GIMP_COMPONENT_TYPE_FLOAT:
+ {
+ gfloat *color = pixel;
+ gint i;
+
+ for (i = 0; i < n_components; i++)
+ strings[i] = g_strdup_printf ("%0.6f", color[i]);
+ }
+ break;
+
+ case GIMP_COMPONENT_TYPE_DOUBLE:
+ {
+ gdouble *color = pixel;
+ gint i;
+
+ for (i = 0; i < n_components; i++)
+ strings[i] = g_strdup_printf ("%0.6f", color[i]);
+ }
+ break;
+ }
+
+ return strings;
+}