[gimp] app: apply display filters in sRGB, not monitor profile



commit 9cd8e7f9c6ce01adda07d0c25fc18f43b3f56fda
Author: Ell <ell_se yahoo com>
Date:   Fri Nov 3 03:59:06 2017 -0400

    app: apply display filters in sRGB, not monitor profile
    
    When we have display filters, break the color profile transform in
    two: first, convert from the image profile to sRGB, then apply the
    filters, then convert from sRGB to the monitor profile.

 app/display/gimpdisplayshell-profile.c |   54 ++++++++++++---
 app/display/gimpdisplayshell-render.c  |  121 +++++++++++++++++++++----------
 app/display/gimpdisplayshell.h         |   11 ++--
 3 files changed, 133 insertions(+), 53 deletions(-)
---
diff --git a/app/display/gimpdisplayshell-profile.c b/app/display/gimpdisplayshell-profile.c
index b035bf4..23a580d 100644
--- a/app/display/gimpdisplayshell-profile.c
+++ b/app/display/gimpdisplayshell-profile.c
@@ -87,6 +87,8 @@ gimp_display_shell_profile_update (GimpDisplayShell *shell)
   GimpImage        *image;
   GimpColorProfile *src_profile;
   const Babl       *src_format;
+  GimpColorProfile *filter_profile;
+  const Babl       *filter_format;
   const Babl       *dest_format;
 
   gimp_display_shell_profile_free (shell);
@@ -103,8 +105,18 @@ gimp_display_shell_profile_update (GimpDisplayShell *shell)
 
   src_format = gimp_projectable_get_format (GIMP_PROJECTABLE (image));
 
-  if (gimp_display_shell_has_filter (shell) ||
-      ! gimp_display_shell_profile_can_convert_to_u8 (shell))
+  if (gimp_display_shell_has_filter (shell))
+    {
+      filter_format  = shell->filter_format;
+      filter_profile = gimp_babl_format_get_color_profile (filter_format);
+    }
+  else
+    {
+      filter_format  = src_format;
+      filter_profile = src_profile;
+    }
+
+  if (! gimp_display_shell_profile_can_convert_to_u8 (shell))
     {
       dest_format = shell->filter_format;
     }
@@ -114,22 +126,38 @@ gimp_display_shell_profile_update (GimpDisplayShell *shell)
     }
 
 #if 0
-  g_printerr ("src_profile: %s\n"
-              "src_format:  %s\n"
-              "dest_format: %s\n",
+  g_printerr ("src_profile:    %s\n"
+              "src_format:     %s\n"
+              "filter_profile: %s\n"
+              "filter_format:  %s\n"
+              "dest_format:    %s\n",
               gimp_color_profile_get_label (src_profile),
               babl_get_name (src_format),
+              gimp_color_profile_get_label (filter_profile),
+              babl_get_name (filter_format),
               babl_get_name (dest_format));
 #endif
 
+  if (! gimp_color_transform_can_gegl_copy (src_profile, filter_profile))
+    {
+      shell->filter_transform =
+        gimp_color_transform_new (src_profile,
+                                  src_format,
+                                  filter_profile,
+                                  filter_format,
+                                  GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC,
+                                  GIMP_COLOR_TRANSFORM_FLAGS_BLACK_POINT_COMPENSATION |
+                                  GIMP_COLOR_TRANSFORM_FLAGS_NOOPTIMIZE);
+    }
+
   shell->profile_transform =
     gimp_widget_get_color_transform (gtk_widget_get_toplevel (GTK_WIDGET (shell)),
                                      gimp_display_shell_get_color_config (shell),
-                                     src_profile,
-                                     src_format,
+                                     filter_profile,
+                                     filter_format,
                                      dest_format);
 
-  if (shell->profile_transform)
+  if (shell->filter_transform || shell->profile_transform)
     {
       gint w = GIMP_DISPLAY_RENDER_BUF_WIDTH  * GIMP_DISPLAY_RENDER_MAX_SCALE;
       gint h = GIMP_DISPLAY_RENDER_BUF_HEIGHT * GIMP_DISPLAY_RENDER_MAX_SCALE;
@@ -157,7 +185,14 @@ gimp_display_shell_profile_can_convert_to_u8 (GimpDisplayShell *shell)
 
   if (image)
     {
-      switch (gimp_image_get_component_type (image))
+      GimpComponentType component_type;
+
+      if (! gimp_display_shell_has_filter (shell))
+        component_type = gimp_image_get_component_type (image);
+      else
+        component_type = gimp_babl_format_get_component_type (shell->filter_format);
+
+      switch (component_type)
         {
         case GIMP_COMPONENT_TYPE_U8:
 #if 0
@@ -184,6 +219,7 @@ static void
 gimp_display_shell_profile_free (GimpDisplayShell *shell)
 {
   g_clear_object (&shell->profile_transform);
+  g_clear_object (&shell->filter_transform);
   g_clear_object (&shell->profile_buffer);
   shell->profile_data   = NULL;
   shell->profile_stride = 0;
diff --git a/app/display/gimpdisplayshell-render.c b/app/display/gimpdisplayshell-render.c
index cb36652..21f0cc1 100644
--- a/app/display/gimpdisplayshell-render.c
+++ b/app/display/gimpdisplayshell-render.c
@@ -171,7 +171,8 @@ gimp_display_shell_render (GimpDisplayShell *shell,
 
       can_convert_to_u8 = gimp_display_shell_profile_can_convert_to_u8 (shell);
 
-      /*  create the filter buffer if we have filters
+      /*  create the filter buffer if we have filters, or can't convert
+       *  to u8 directly
        */
       if ((gimp_display_shell_has_filter (shell) || ! can_convert_to_u8) &&
           ! shell->filter_buffer)
@@ -194,10 +195,10 @@ gimp_display_shell_render (GimpDisplayShell *shell,
                                               shell->filter_data);
         }
 
-      if (shell->profile_transform)
+      if (! gimp_display_shell_has_filter (shell) || shell->filter_transform)
         {
-          /*  if there is a profile transform, load the projection
-           *  pixels into the profile_buffer
+          /*  if there are no filters, or there is a filter transform,
+           *  load the projection pixels into the profile_buffer
            */
 #ifndef USE_NODE_BLIT
           gegl_buffer_get (buffer,
@@ -216,42 +217,10 @@ gimp_display_shell_render (GimpDisplayShell *shell,
                           shell->profile_data, shell->profile_stride,
                           GEGL_BLIT_CACHE);
 #endif
-
-          if (gimp_display_shell_has_filter (shell) || ! can_convert_to_u8)
-            {
-              /*  if there are filters, convert the pixels from the
-               *  profile_buffer to the filter_buffer
-               */
-              gimp_color_transform_process_buffer (shell->profile_transform,
-                                                   shell->profile_buffer,
-                                                   GEGL_RECTANGLE (0, 0,
-                                                                   scaled_width,
-                                                                   scaled_height),
-                                                   shell->filter_buffer,
-                                                   GEGL_RECTANGLE (0, 0,
-                                                                   scaled_width,
-                                                                   scaled_height));
-            }
-          else
-            {
-              /*  otherwise, convert the profile_buffer directly into
-               *  the cairo_buffer
-               */
-              gimp_color_transform_process_buffer (shell->profile_transform,
-                                                   shell->profile_buffer,
-                                                   GEGL_RECTANGLE (0, 0,
-                                                                   scaled_width,
-                                                                   scaled_height),
-                                                   cairo_buffer,
-                                                   GEGL_RECTANGLE (0, 0,
-                                                                   scaled_width,
-                                                                   scaled_height));
-            }
         }
       else
         {
-          /*  otherwise, load the projection pixels directly into the
-           *  filter_buffer
+          /*  otherwise, load the pixels directly into the filter_buffer
            */
 #ifndef USE_NODE_BLIT
           gegl_buffer_get (buffer,
@@ -272,10 +241,32 @@ gimp_display_shell_render (GimpDisplayShell *shell,
 #endif
         }
 
+      /*  if there is a filter transform, convert the pixels from
+       *  the profile_buffer to the filter_buffer
+       */
+      if (shell->filter_transform)
+        {
+          gimp_color_transform_process_buffer (shell->filter_transform,
+                                               shell->profile_buffer,
+                                               GEGL_RECTANGLE (0, 0,
+                                                               scaled_width,
+                                                               scaled_height),
+                                               shell->filter_buffer,
+                                               GEGL_RECTANGLE (0, 0,
+                                                               scaled_width,
+                                                               scaled_height));
+        }
+
+      /*  if there are filters, apply them
+       */
       if (gimp_display_shell_has_filter (shell))
         {
           GeglBuffer *filter_buffer;
 
+          /*  shift the filter_buffer so that the area passed to
+           *  the filters is the real render area, allowing for
+           *  position-dependent filters
+           */
           filter_buffer = g_object_new (GEGL_TYPE_BUFFER,
                                         "source", shell->filter_buffer,
                                         "shift-x", -scaled_x,
@@ -293,10 +284,62 @@ gimp_display_shell_render (GimpDisplayShell *shell,
           g_object_unref (filter_buffer);
         }
 
+      /*  if there is a profile transform...
+       */
+      if (shell->profile_transform)
+        {
+          if (gimp_display_shell_has_filter (shell))
+            {
+              /*  if we have filters, convert the pixels in the filter_buffer
+               *  in-place
+               */
+              gimp_color_transform_process_buffer (shell->profile_transform,
+                                                   shell->filter_buffer,
+                                                   GEGL_RECTANGLE (0, 0,
+                                                                   scaled_width,
+                                                                   scaled_height),
+                                                   shell->filter_buffer,
+                                                   GEGL_RECTANGLE (0, 0,
+                                                                   scaled_width,
+                                                                   scaled_height));
+            }
+          else if (! can_convert_to_u8)
+            {
+              /*  otherwise, if we can't convert to u8 directly, convert
+               *  the pixels from the profile_buffer to the filter_buffer
+               */
+              gimp_color_transform_process_buffer (shell->profile_transform,
+                                                   shell->profile_buffer,
+                                                   GEGL_RECTANGLE (0, 0,
+                                                                   scaled_width,
+                                                                   scaled_height),
+                                                   shell->filter_buffer,
+                                                   GEGL_RECTANGLE (0, 0,
+                                                                   scaled_width,
+                                                                   scaled_height));
+            }
+          else
+            {
+              /*  otherwise, convert the profile_buffer directly into
+               *  the cairo_buffer
+               */
+              gimp_color_transform_process_buffer (shell->profile_transform,
+                                                   shell->profile_buffer,
+                                                   GEGL_RECTANGLE (0, 0,
+                                                                   scaled_width,
+                                                                   scaled_height),
+                                                   cairo_buffer,
+                                                   GEGL_RECTANGLE (0, 0,
+                                                                   scaled_width,
+                                                                   scaled_height));
+            }
+        }
+
+      /*  finally, copy the filter buffer to the cairo-ARGB32 buffer,
+       *  if necessary
+       */
       if (gimp_display_shell_has_filter (shell) || ! can_convert_to_u8)
         {
-          /*  finally, copy the filter buffer to the cairo-ARGB32 buffer
-           */
           gegl_buffer_get (shell->filter_buffer,
                            GEGL_RECTANGLE (0, 0,
                                            scaled_width,
diff --git a/app/display/gimpdisplayshell.h b/app/display/gimpdisplayshell.h
index 565edb8..9c5cb19 100644
--- a/app/display/gimpdisplayshell.h
+++ b/app/display/gimpdisplayshell.h
@@ -157,13 +157,14 @@ struct _GimpDisplayShell
   guchar             *profile_data;    /*  profile_buffer's pixels            */
   gint                profile_stride;  /*  profile_buffer's stride            */
 
-  GimpColorDisplayStack *filter_stack;   /* color display conversion stuff    */
+  GimpColorDisplayStack *filter_stack; /*  color display conversion stuff     */
   guint                  filter_idle_id;
 
-  const Babl        *filter_format;    /*  filter_buffer's format             */
-  GeglBuffer        *filter_buffer;    /*  buffer for display filters         */
-  guchar            *filter_data;      /*  filter_buffer's pixels             */
-  gint               filter_stride;    /*  filter_buffer's stride             */
+  GimpColorTransform *filter_transform;
+  const Babl         *filter_format;   /*  filter_buffer's format             */
+  GeglBuffer         *filter_buffer;   /*  buffer for display filters         */
+  guchar             *filter_data;     /*  filter_buffer's pixels             */
+  gint                filter_stride;   /*  filter_buffer's stride             */
 
   GimpDisplayXfer   *xfer;             /*  manages image buffer transfers     */
   cairo_surface_t   *mask_surface;     /*  buffer for rendering the mask      */


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