[gtk/matthiasc/color-profile-rebased: 6/51] gdk: Add GdkLcmsColorSpace
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/matthiasc/color-profile-rebased: 6/51] gdk: Add GdkLcmsColorSpace
- Date: Sat, 1 Oct 2022 01:36:39 +0000 (UTC)
commit 28f670d5fa21301a187eda0ceba0c0e11acddb50
Author: Benjamin Otte <otte redhat com>
Date: Mon Sep 20 09:17:28 2021 +0200
gdk: Add GdkLcmsColorSpace
This is a colorspace implementation using LCMS to implement support
for random colorspaces from ICC profiles.
gdk/gdkcolorspace.c | 2 +-
gdk/gdkcolorspace.h | 3 +
gdk/gdkcolorspaceprivate.h | 2 +
gdk/gdklcmscolorspace.c | 255 +++++++++++++++++++++++++++++++++++++++++
gdk/gdklcmscolorspaceprivate.h | 48 ++++++++
gdk/meson.build | 1 +
6 files changed, 310 insertions(+), 1 deletion(-)
---
diff --git a/gdk/gdkcolorspace.c b/gdk/gdkcolorspace.c
index 7b18edcfff..b6c7cd2f15 100644
--- a/gdk/gdkcolorspace.c
+++ b/gdk/gdkcolorspace.c
@@ -185,7 +185,7 @@ gdk_color_space_is_linear (GdkColorSpace *self)
{
g_return_val_if_fail (GDK_IS_COLOR_SPACE (self), FALSE);
- return FALSE:
+ return self == gdk_color_space_get_srgb_linear ();
}
int
diff --git a/gdk/gdkcolorspace.h b/gdk/gdkcolorspace.h
index 5f855a97b5..a3c61dfa5f 100644
--- a/gdk/gdkcolorspace.h
+++ b/gdk/gdkcolorspace.h
@@ -45,6 +45,9 @@ typedef struct _GdkColorSpaceClass GdkColorSpaceClass;
GDK_AVAILABLE_IN_4_10
GType gdk_color_space_get_type (void) G_GNUC_CONST;
+GDK_AVAILABLE_IN_4_10
+GdkColorSpace * gdk_color_space_get_srgb (void) G_GNUC_CONST;
+
GDK_AVAILABLE_IN_4_10
GdkColorSpace * gdk_color_space_new_from_icc_profile (GBytes *icc_profile,
GError **error);
diff --git a/gdk/gdkcolorspaceprivate.h b/gdk/gdkcolorspaceprivate.h
index db168e4168..b85bbc65fa 100644
--- a/gdk/gdkcolorspaceprivate.h
+++ b/gdk/gdkcolorspaceprivate.h
@@ -26,6 +26,8 @@ struct _GdkColorSpaceClass
};
+GdkColorSpace * gdk_color_space_get_srgb_linear (void) G_GNUC_CONST;
+
G_END_DECLS
#endif /* __GDK_COLOR_SPACE_PRIVATE_H__ */
diff --git a/gdk/gdklcmscolorspace.c b/gdk/gdklcmscolorspace.c
new file mode 100644
index 0000000000..80e3721819
--- /dev/null
+++ b/gdk/gdklcmscolorspace.c
@@ -0,0 +1,255 @@
+/* gdklcmscolorspace.c
+ *
+ * Copyright 2021 (c) Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gdklcmscolorspaceprivate.h"
+
+#include <glib/gi18n-lib.h>
+
+struct _GdkLcmsColorSpace
+{
+ GdkColorSpace parent_instance;
+
+ cmsHPROFILE lcms_profile;
+};
+
+struct _GdkLcmsColorSpaceClass
+{
+ GdkColorSpaceClass parent_class;
+};
+
+G_DEFINE_TYPE (GdkLcmsColorSpace, gdk_lcms_color_space, GDK_TYPE_COLOR_SPACE)
+
+static gboolean
+gdk_lcms_color_space_supports_format (GdkColorSpace *space,
+ GdkMemoryFormat format)
+{
+ GdkLcmsColorSpace *self = GDK_LCMS_COLOR_SPACE (space);
+
+ return cmsGetColorSpace (self->lcms_profile) == cmsSigRgbData;
+}
+
+static GBytes *
+gdk_lcms_color_space_save_to_icc_profile (GdkColorSpace *space,
+ GError **error)
+{
+ GdkLcmsColorSpace *self = GDK_LCMS_COLOR_SPACE (space);
+ cmsUInt32Number size;
+ guchar *data;
+
+ size = 0;
+ if (!cmsSaveProfileToMem (self->lcms_profile, NULL, &size))
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Could not prepare ICC profile"));
+ return NULL;
+ }
+
+ data = g_malloc (size);
+ if (!cmsSaveProfileToMem (self->lcms_profile, data, &size))
+ {
+ g_free (data);
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Failed to save ICC profile"));
+ return NULL;
+ }
+
+ return g_bytes_new_take (data, size);
+}
+
+static int
+gdk_lcms_color_space_get_n_components (GdkColorSpace *space)
+{
+ return 3;
+}
+
+static gboolean
+gdk_lcms_color_space_equal (GdkColorSpace *profile1,
+ GdkColorSpace *profile2)
+{
+ GBytes *icc1, *icc2;
+ gboolean res;
+
+ icc1 = gdk_color_space_save_to_icc_profile (profile1, NULL);
+ icc2 = gdk_color_space_save_to_icc_profile (profile2, NULL);
+
+ res = g_bytes_equal (icc1, icc2);
+
+ g_bytes_unref (icc1);
+ g_bytes_unref (icc2);
+
+ return res;
+}
+
+static void
+gdk_lcms_color_space_dispose (GObject *object)
+{
+ GdkLcmsColorSpace *self = GDK_LCMS_COLOR_SPACE (object);
+
+ g_clear_pointer (&self->lcms_profile, cmsCloseProfile);
+
+ G_OBJECT_CLASS (gdk_lcms_color_space_parent_class)->dispose (object);
+}
+
+static void
+gdk_lcms_color_space_class_init (GdkLcmsColorSpaceClass *klass)
+{
+ GdkColorSpaceClass *color_space_class = GDK_COLOR_SPACE_CLASS (klass);
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ color_space_class->supports_format = gdk_lcms_color_space_supports_format;
+ color_space_class->save_to_icc_profile = gdk_lcms_color_space_save_to_icc_profile;
+ color_space_class->get_n_components = gdk_lcms_color_space_get_n_components;
+ color_space_class->equal = gdk_lcms_color_space_equal;
+
+ gobject_class->dispose = gdk_lcms_color_space_dispose;
+}
+
+static void
+gdk_lcms_color_space_init (GdkLcmsColorSpace *self)
+{
+}
+
+GdkColorSpace *
+gdk_lcms_color_space_new_from_lcms_profile (cmsHPROFILE lcms_profile)
+{
+ GdkLcmsColorSpace *result;
+
+ result = g_object_new (GDK_TYPE_LCMS_COLOR_SPACE, NULL);
+ result->lcms_profile = lcms_profile;
+
+ return GDK_COLOR_SPACE (result);
+}
+
+/**
+ * gdk_color_space_new_from_icc_profile:
+ * @icc_profile: The ICC profiles given as a `GBytes`
+ * @error: Return location for an error
+ *
+ * Creates a new color profile for the given ICC profile data.
+ *
+ * if the profile is not valid, %NULL is returned and an error
+ * is raised.
+ *
+ * Returns: a new `GdkLcmsColorSpace` or %NULL on error
+ *
+ * Since: 4.10
+ */
+GdkColorSpace *
+gdk_color_space_new_from_icc_profile (GBytes *icc_profile,
+ GError **error)
+{
+ cmsHPROFILE lcms_profile;
+ const guchar *data;
+ gsize size;
+
+ g_return_val_if_fail (icc_profile != NULL, NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ data = g_bytes_get_data (icc_profile, &size);
+
+ lcms_profile = cmsOpenProfileFromMem (data, size);
+ if (lcms_profile == NULL)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Failed to load ICC profile"));
+ return NULL;
+ }
+
+ return gdk_lcms_color_space_new_from_lcms_profile (lcms_profile);
+}
+
+cmsHPROFILE
+gdk_lcms_color_space_get_lcms_profile (GdkColorSpace *self)
+{
+ g_return_val_if_fail (GDK_IS_LCMS_COLOR_SPACE (self), NULL);
+
+ return GDK_LCMS_COLOR_SPACE (self)->lcms_profile;
+}
+
+/**
+ * gdk_color_space_get_srgb:
+ *
+ * Returns the object representing the sRGB color space.
+ *
+ * If you don't know anything about color spaces but need one for
+ * use with some function, this one is most likely the right one.
+ *
+ * Returns: (transfer none): the object for the sRGB color space.
+ *
+ * Since: 4.8
+ */
+GdkColorSpace *
+gdk_color_space_get_srgb (void)
+{
+ static GdkColorSpace *srgb_color_space;
+
+ if (g_once_init_enter (&srgb_color_space))
+ {
+ GdkColorSpace *color_space;
+
+ color_space = gdk_lcms_color_space_new_from_lcms_profile (cmsCreate_sRGBProfile ());
+ g_assert (color_space);
+
+ g_once_init_leave (&srgb_color_space, color_space);
+ }
+
+ return srgb_color_space;
+}
+
+/*<private>
+ * gdk_color_space_get_srgb_linear:
+ *
+ * Returns the object corresponding to the linear sRGB color space.
+ *
+ * It can display the same colors as the sRGB color space, but it
+ * does not have a gamma curve.
+ *
+ * Returns: (transfer none): the object for the linear sRGB color space.
+ *
+ * Since: 4.8
+ */
+GdkColorSpace *
+gdk_color_space_get_srgb_linear (void)
+{
+ static GdkColorSpace *srgb_linear_color_space;
+
+ if (g_once_init_enter (&srgb_linear_color_space))
+ {
+ cmsToneCurve *curve;
+ cmsHPROFILE lcms_profile;
+ GdkColorSpace *color_space;
+
+ curve = cmsBuildGamma (NULL, 1.0);
+ lcms_profile = cmsCreateRGBProfile (&(cmsCIExyY) {
+ 0.3127, 0.3290, 1.0
+ },
+ &(cmsCIExyYTRIPLE) {
+ { 0.6400, 0.3300, 1.0 },
+ { 0.3000, 0.6000, 1.0 },
+ { 0.1500, 0.0600, 1.0 }
+ },
+ (cmsToneCurve*[3]) { curve, curve, curve });
+ cmsFreeToneCurve (curve);
+
+ color_space = gdk_lcms_color_space_new_from_lcms_profile (lcms_profile);
+ g_assert (color_space);
+
+ g_once_init_leave (&srgb_linear_color_space, color_space);
+ }
+
+ return srgb_linear_color_space;
+}
diff --git a/gdk/gdklcmscolorspaceprivate.h b/gdk/gdklcmscolorspaceprivate.h
new file mode 100644
index 0000000000..2251c394d2
--- /dev/null
+++ b/gdk/gdklcmscolorspaceprivate.h
@@ -0,0 +1,48 @@
+/* gdklcmscolorspace.h
+ *
+ * Copyright 2021 (c) Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GDK_LCMS_COLOR_SPACE_PRIVATE_H__
+#define __GDK_LCMS_COLOR_SPACE_PRIVATE_H__
+
+#include "gdkcolorspaceprivate.h"
+
+#include <lcms2.h>
+
+G_BEGIN_DECLS
+
+#define GDK_TYPE_LCMS_COLOR_SPACE (gdk_lcms_color_space_get_type ())
+
+#define GDK_LCMS_COLOR_SPACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),
GDK_TYPE_LCMS_COLOR_SPACE, GdkLcmsColorSpace))
+#define GDK_IS_LCMS_COLOR_SPACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),
GDK_TYPE_LCMS_COLOR_SPACE))
+#define GDK_LCMS_COLOR_SPACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass),
GDK_TYPE_LCMS_COLOR_SPACE, GdkLcmsColorSpaceClass))
+#define GDK_IS_LCMS_COLOR_SPACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),
GDK_TYPE_LCMS_COLOR_SPACE))
+#define GDK_LCMS_COLOR_SPACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),
GDK_TYPE_LCMS_COLOR_SPACE, GdkLcmsColorSpaceClass))
+
+typedef struct _GdkLcmsColorSpace GdkLcmsColorSpace;
+typedef struct _GdkLcmsColorSpaceClass GdkLcmsColorSpaceClass;
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkLcmsColorSpace, g_object_unref)
+
+GType gdk_lcms_color_space_get_type (void) G_GNUC_CONST;
+
+GdkColorSpace * gdk_lcms_color_space_new_from_lcms_profile (cmsHPROFILE
lcms_profile);
+cmsHPROFILE gdk_lcms_color_space_get_lcms_profile (GdkColorSpace
*color_space);
+
+G_END_DECLS
+
+#endif /* __GDK_LCMS_COLOR_SPACE_PRIVATE_H__ */
diff --git a/gdk/meson.build b/gdk/meson.build
index 67f6789c9b..f82d41d687 100644
--- a/gdk/meson.build
+++ b/gdk/meson.build
@@ -31,6 +31,7 @@ gdk_public_sources = files([
'gdkhsla.c',
'gdkkeys.c',
'gdkkeyuni.c',
+ 'gdklcmscolorspace.c',
'gdkmemoryformat.c',
'gdkmemorytexture.c',
'gdkmonitor.c',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]