[gtk/wip/otte/color-profiles: 7/30] memoryformat: Take a color profile when converting




commit 89b5c30f9b4ab82c1cfbb6d3ac346635e855c4ac
Author: Benjamin Otte <otte redhat com>
Date:   Wed Sep 22 05:38:07 2021 +0200

    memoryformat: Take a color profile when converting

 gdk/gdkglcontext.c           |  6 ++++-
 gdk/gdkglcontextprivate.h    |  1 +
 gdk/gdkmemoryformat.c        | 55 ++++++++++++++++++++++++++++++++++++--------
 gdk/gdkmemoryformatprivate.h |  2 ++
 gdk/gdkmemorytexture.c       |  5 ++++
 gsk/ngl/gsknglcommandqueue.c |  4 +++-
 gsk/ngl/gsknglglyphlibrary.c |  2 ++
 gsk/ngl/gskngliconlibrary.c  |  5 +++-
 8 files changed, 68 insertions(+), 12 deletions(-)
---
diff --git a/gdk/gdkglcontext.c b/gdk/gdkglcontext.c
index 3c9b337cf9..afeb3b5358 100644
--- a/gdk/gdkglcontext.c
+++ b/gdk/gdkglcontext.c
@@ -227,6 +227,7 @@ gdk_gl_context_upload_texture (GdkGLContext    *context,
                                int              height,
                                int              stride,
                                GdkMemoryFormat  data_format,
+                               GdkColorProfile *color_profile,
                                guint            texture_target)
 {
   GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
@@ -297,7 +298,10 @@ gdk_gl_context_upload_texture (GdkGLContext    *context,
       copy = g_malloc (width * height * 4);
       gdk_memory_convert (copy, width * 4,
                           GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
-                          data, stride, data_format,
+                          gdk_color_profile_get_srgb (),
+                          data, stride,
+                          data_format,
+                          color_profile,
                           width, height);
       data_format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
       stride = width * 4;
diff --git a/gdk/gdkglcontextprivate.h b/gdk/gdkglcontextprivate.h
index 050e757608..abe8ae43b9 100644
--- a/gdk/gdkglcontextprivate.h
+++ b/gdk/gdkglcontextprivate.h
@@ -111,6 +111,7 @@ void                    gdk_gl_context_upload_texture           (GdkGLContext
                                                                  int              height,
                                                                  int              stride,
                                                                  GdkMemoryFormat  data_format,
+                                                                 GdkColorProfile *color_profile,
                                                                  guint            texture_target);
 GdkGLContextPaintData * gdk_gl_context_get_paint_data           (GdkGLContext    *context);
 gboolean                gdk_gl_context_use_texture_rectangle    (GdkGLContext    *context);
diff --git a/gdk/gdkmemoryformat.c b/gdk/gdkmemoryformat.c
index 7db5d3f56a..e78851e5e8 100644
--- a/gdk/gdkmemoryformat.c
+++ b/gdk/gdkmemoryformat.c
@@ -21,6 +21,7 @@
 
 #include "gdkmemoryformatprivate.h"
 
+#include "gdkcolorprofileprivate.h"
 #include "gsk/ngl/fp16private.h"
 
 typedef struct _GdkMemoryFormatDescription GdkMemoryFormatDescription;
@@ -44,6 +45,7 @@ name ## _to_float (float        *dest, \
       dest[1] = (float) src[G] / scale; \
       dest[2] = (float) src[B] / scale; \
       if (A >= 0) dest[3] = (float) src[A] / scale; else dest[3] = 1.0; \
+      dest += 4; \
     } \
 } \
 \
@@ -59,6 +61,7 @@ name ## _from_float (guchar      *dest_data, \
       dest[G] = CLAMP (src[1] * (scale + 1), 0, scale); \
       dest[B] = CLAMP (src[2] * (scale + 1), 0, scale); \
       if (A >= 0) dest[A] = CLAMP (src[3] * (scale + 1), 0, scale); \
+      src += 4; \
     } \
 }
 
@@ -318,11 +321,13 @@ unpremultiply (float *rgba,
 {
   for (gsize i = 0; i < n; i++)
     {
-      if (rgba[3] <= 1/255.0)
-        continue;
-      rgba[0] /= rgba[3];
-      rgba[1] /= rgba[3];
-      rgba[2] /= rgba[3];
+      if (rgba[3] > 1/255.0)
+        {
+          rgba[0] /= rgba[3];
+          rgba[1] /= rgba[3];
+          rgba[2] /= rgba[3];
+        }
+      rgba += 4;
     }
 }
 
@@ -330,14 +335,17 @@ void
 gdk_memory_convert (guchar              *dest_data,
                     gsize                dest_stride,
                     GdkMemoryFormat      dest_format,
+                    GdkColorProfile     *dest_profile,
                     const guchar        *src_data,
                     gsize                src_stride,
                     GdkMemoryFormat      src_format,
+                    GdkColorProfile     *src_profile,
                     gsize                width,
                     gsize                height)
 {
   const GdkMemoryFormatDescription *dest_desc = &memory_formats[dest_format];
   const GdkMemoryFormatDescription *src_desc = &memory_formats[src_format];
+  cmsHTRANSFORM transform;
   float *tmp;
   gsize y;
 
@@ -346,17 +354,46 @@ gdk_memory_convert (guchar              *dest_data,
 
   tmp = g_new (float, width * 4);
 
+  if (gdk_color_profile_equal (src_profile, dest_profile))
+    {
+      transform = NULL;
+    }
+  else
+    {
+      transform = cmsCreateTransform (gdk_color_profile_get_lcms_profile (src_profile),
+                                      TYPE_RGBA_FLT,
+                                      gdk_color_profile_get_lcms_profile (dest_profile),
+                                      TYPE_RGBA_FLT,
+                                      INTENT_PERCEPTUAL,
+                                      cmsFLAGS_COPY_ALPHA);
+    }
+
   for (y = 0; y < height; y++)
     {
       src_desc->to_float (tmp, src_data, width);
-      if (src_desc->alpha == GDK_MEMORY_ALPHA_PREMULTIPLIED && dest_desc->alpha == GDK_MEMORY_ALPHA_STRAIGHT)
-        unpremultiply (tmp, width);
-      else if (src_desc->alpha == GDK_MEMORY_ALPHA_STRAIGHT && dest_desc->alpha != GDK_MEMORY_ALPHA_STRAIGHT)
-        premultiply (tmp, width);
+      if (transform)
+        {
+          if (src_desc->alpha == GDK_MEMORY_ALPHA_PREMULTIPLIED)
+            unpremultiply (tmp, width);
+          cmsDoTransform (transform,
+                          tmp,
+                          tmp,
+                          width);
+          if (dest_desc->alpha != GDK_MEMORY_ALPHA_STRAIGHT)
+            premultiply (tmp, width);
+        }
+      else
+        {
+          if (src_desc->alpha == GDK_MEMORY_ALPHA_PREMULTIPLIED && dest_desc->alpha == 
GDK_MEMORY_ALPHA_STRAIGHT)
+            unpremultiply (tmp, width);
+          else if (src_desc->alpha == GDK_MEMORY_ALPHA_STRAIGHT && dest_desc->alpha != 
GDK_MEMORY_ALPHA_STRAIGHT)
+            premultiply (tmp, width);
+        }
       dest_desc->from_float (dest_data, tmp, width);
       src_data += src_stride;
       dest_data += dest_stride;
     }
 
   g_free (tmp);
+  g_clear_pointer (&transform, cmsDeleteTransform);
 }
diff --git a/gdk/gdkmemoryformatprivate.h b/gdk/gdkmemoryformatprivate.h
index 0de89f0756..ca0e4c2c1b 100644
--- a/gdk/gdkmemoryformatprivate.h
+++ b/gdk/gdkmemoryformatprivate.h
@@ -30,9 +30,11 @@ gsize                   gdk_memory_format_bytes_per_pixel   (GdkMemoryFormat
 void                    gdk_memory_convert                  (guchar                     *dest_data,
                                                              gsize                       dest_stride,
                                                              GdkMemoryFormat             dest_format,
+                                                             GdkColorProfile            *dest_profile,
                                                              const guchar               *src_data,
                                                              gsize                       src_stride,
                                                              GdkMemoryFormat             src_format,
+                                                             GdkColorProfile            *src_profile,
                                                              gsize                       width,
                                                              gsize                       height);
 
diff --git a/gdk/gdkmemorytexture.c b/gdk/gdkmemorytexture.c
index 33ba90fe5c..61ac5d31fc 100644
--- a/gdk/gdkmemorytexture.c
+++ b/gdk/gdkmemorytexture.c
@@ -21,6 +21,7 @@
 
 #include "gdkmemorytextureprivate.h"
 
+#include "gdkcolorprofile.h"
 #include "gdkmemoryformatprivate.h"
 #include "gsk/ngl/fp16private.h"
 
@@ -72,9 +73,11 @@ gdk_memory_texture_download (GdkTexture *texture,
 
   gdk_memory_convert (data, stride,
                       GDK_MEMORY_DEFAULT,
+                      gdk_color_profile_get_srgb (),
                       (guchar *) g_bytes_get_data (self->bytes, NULL),
                       self->stride,
                       self->format,
+                      gdk_texture_get_color_profile (texture),
                       gdk_texture_get_width (texture),
                       gdk_texture_get_height (texture));
 }
@@ -89,9 +92,11 @@ gdk_memory_texture_download_float (GdkTexture *texture,
   gdk_memory_convert ((guchar *) data,
                       stride * sizeof (float),
                       GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED,
+                      gdk_color_profile_get_srgb (),
                       (guchar *) g_bytes_get_data (self->bytes, NULL),
                       self->stride,
                       self->format,
+                      gdk_texture_get_color_profile (texture),
                       gdk_texture_get_width (texture),
                       gdk_texture_get_height (texture));
 }
diff --git a/gsk/ngl/gsknglcommandqueue.c b/gsk/ngl/gsknglcommandqueue.c
index b2a474cf59..e8c44243aa 100644
--- a/gsk/ngl/gsknglcommandqueue.c
+++ b/gsk/ngl/gsknglcommandqueue.c
@@ -1386,7 +1386,9 @@ gsk_ngl_command_queue_upload_texture (GskNglCommandQueue *self,
   gdk_gl_context_upload_texture (gdk_gl_context_get_current (),
                                  data + x_offset * bpp + y_offset * data_stride,
                                  width, height, data_stride,
-                                 data_format, GL_TEXTURE_2D);
+                                 data_format,
+                                 gdk_color_profile_get_srgb (),
+                                 GL_TEXTURE_2D);
 
   /* Restore previous texture state if any */
   if (self->attachments->textures[0].id > 0)
diff --git a/gsk/ngl/gsknglglyphlibrary.c b/gsk/ngl/gsknglglyphlibrary.c
index ede4f19105..df477b05f1 100644
--- a/gsk/ngl/gsknglglyphlibrary.c
+++ b/gsk/ngl/gsknglglyphlibrary.c
@@ -238,9 +238,11 @@ gsk_ngl_glyph_library_upload_glyph (GskNglGlyphLibrary     *self,
       gdk_memory_convert (pixel_data,
                           width * 4,
                           GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
+                          gdk_color_profile_get_srgb (),
                           cairo_image_surface_get_data (surface),
                           width * 4,
                           GDK_MEMORY_DEFAULT,
+                          gdk_color_profile_get_srgb (),
                           width, height);
       gl_format = GL_RGBA;
       gl_type = GL_UNSIGNED_BYTE;
diff --git a/gsk/ngl/gskngliconlibrary.c b/gsk/ngl/gskngliconlibrary.c
index cfc662a9e6..815ab0acd5 100644
--- a/gsk/ngl/gskngliconlibrary.c
+++ b/gsk/ngl/gskngliconlibrary.c
@@ -116,8 +116,11 @@ gsk_ngl_icon_library_add (GskNglIconLibrary     *self,
       pixel_data = free_data = g_malloc (width * height * 4);
       gdk_memory_convert (pixel_data, width * 4,
                           GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
+                          gdk_color_profile_get_srgb (),
                           surface_data, cairo_image_surface_get_stride (surface),
-                          GDK_MEMORY_DEFAULT, width, height);
+                          GDK_MEMORY_DEFAULT,
+                          gdk_color_profile_get_srgb (),
+                          width, height);
       gl_format = GL_RGBA;
       gl_type = GL_UNSIGNED_BYTE;
     }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]