[gimp] app: switch gimpdisplayshell-render.c to the new profile filter code



commit 08545ad5492f186eca6b111f634cd480ca5a3fd9
Author: Michael Natterer <mitch gimp org>
Date:   Mon Jun 1 23:30:03 2015 +0200

    app: switch gimpdisplayshell-render.c to the new profile filter code
    
    - disable auto-adding of the lcms display filter module
    
    - change profile convert dest formats to be always R'G'B'A, a display
      profile transform outputs something that can be displayed directly,
      so no additional gamma transform must happen when the pixels are
      copied to a cairo-ARGB32 buffer
    
    - add a medium forest of if() branches to gimpdisplayshell-filter.c
      which cover all combinations of profile and display filter
      transforms
    
    - all of this is still very broken when changing an image to linear,
      because the configured RGB profile from prefs will do horrible
      nonsense (things work fine though with a per-image profile that is
      for linear data)

 app/display/gimpdisplayshell-filter.c  |    5 +
 app/display/gimpdisplayshell-profile.c |   13 +--
 app/display/gimpdisplayshell-render.c  |  189 +++++++++++++++++++++++---------
 3 files changed, 148 insertions(+), 59 deletions(-)
---
diff --git a/app/display/gimpdisplayshell-filter.c b/app/display/gimpdisplayshell-filter.c
index 773ce75..b1fa583 100644
--- a/app/display/gimpdisplayshell-filter.c
+++ b/app/display/gimpdisplayshell-filter.c
@@ -89,6 +89,10 @@ gimp_display_shell_filter_new (GimpDisplayShell *shell,
   g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), NULL);
   g_return_val_if_fail (GIMP_IS_COLOR_CONFIG (config), NULL);
 
+#if 0
+  /*  disabled because we use gimpdisplayshell-profile now, keep
+   *  the code around for reference.
+   */
   if (config->display_module)
     {
       GType type = g_type_from_name (config->display_module);
@@ -111,6 +115,7 @@ gimp_display_shell_filter_new (GimpDisplayShell *shell,
           return stack;
         }
     }
+#endif
 
   return NULL;
 }
diff --git a/app/display/gimpdisplayshell-profile.c b/app/display/gimpdisplayshell-profile.c
index c0fc41b..ad070ee 100644
--- a/app/display/gimpdisplayshell-profile.c
+++ b/app/display/gimpdisplayshell-profile.c
@@ -38,6 +38,7 @@
 
 #include "gimpdisplay.h"
 #include "gimpdisplayshell.h"
+#include "gimpdisplayshell-filter.h"
 #include "gimpdisplayshell-profile.h"
 #include "gimpdisplayxfer.h"
 
@@ -89,16 +90,10 @@ gimp_display_shell_profile_update (GimpDisplayShell *shell)
 
   src_format = gimp_pickable_get_format (GIMP_PICKABLE (image));
 
-  if (shell->filter_stack && shell->filter_stack->filters)
-    dest_format = gimp_babl_format (GIMP_RGB,
-                                    gimp_babl_precision (GIMP_COMPONENT_TYPE_FLOAT,
-                                                         gimp_babl_format_get_linear (src_format)),
-                                    TRUE);
+  if (gimp_display_shell_has_filter (shell))
+    dest_format = babl_format ("R'G'B'A float");
   else
-    dest_format = gimp_babl_format (GIMP_RGB,
-                                    gimp_babl_precision (GIMP_COMPONENT_TYPE_FLOAT,
-                                                         gimp_babl_format_get_linear (src_format)),
-                                    TRUE);
+    dest_format = babl_format ("R'G'B'A u8");
 
   g_printerr ("src_format: %s\n", babl_get_name (src_format));
   g_printerr ("dest_format: %s\n", babl_get_name (dest_format));
diff --git a/app/display/gimpdisplayshell-render.c b/app/display/gimpdisplayshell-render.c
index af63f90..d8f8f1b 100644
--- a/app/display/gimpdisplayshell-render.c
+++ b/app/display/gimpdisplayshell-render.c
@@ -41,6 +41,7 @@
 #include "gimpdisplayshell.h"
 #include "gimpdisplayshell-transform.h"
 #include "gimpdisplayshell-filter.h"
+#include "gimpdisplayshell-profile.h"
 #include "gimpdisplayshell-render.h"
 #include "gimpdisplayshell-scroll.h"
 #include "gimpdisplayxfer.h"
@@ -62,9 +63,10 @@ gimp_display_shell_render (GimpDisplayShell *shell,
 #ifdef USE_NODE_BLIT
   GeglNode        *node;
 #endif
-  gdouble          scale_x      = 1.0;
-  gdouble          scale_y      = 1.0;
-  gdouble          buffer_scale = 1.0;
+  const Babl      *filter_format = babl_format ("R'G'B'A float");
+  gdouble          scale_x       = 1.0;
+  gdouble          scale_y       = 1.0;
+  gdouble          buffer_scale  = 1.0;
   gint             viewport_offset_x;
   gint             viewport_offset_y;
   gint             viewport_width;
@@ -78,8 +80,9 @@ gimp_display_shell_render (GimpDisplayShell *shell,
   gint             xfer_src_y;
   gint             mask_src_x = 0;
   gint             mask_src_y = 0;
-  gint             stride;
-  guchar          *data;
+  gint             cairo_stride;
+  guchar          *cairo_data;
+  GeglBuffer      *cairo_buffer;
 
   g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
   g_return_if_fail (cr != NULL);
@@ -146,16 +149,29 @@ gimp_display_shell_render (GimpDisplayShell *shell,
                                             &xfer_src_y);
     }
 
-  stride = cairo_image_surface_get_stride (xfer);
-  data = cairo_image_surface_get_data (xfer);
-  data += xfer_src_y * stride + xfer_src_x * 4;
+  cairo_stride = cairo_image_surface_get_stride (xfer);
+  cairo_data   = cairo_image_surface_get_data (xfer) +
+                 xfer_src_y * cairo_stride + xfer_src_x * 4;
 
-  /*  apply filters to the rendered projection  */
-  if (shell->filter_stack)
-    {
-      const Babl *filter_format = babl_format ("R'G'B'A float");
+  cairo_buffer = gegl_buffer_linear_new_from_data (cairo_data,
+                                                   babl_format ("cairo-ARGB32"),
+                                                   GEGL_RECTANGLE (0, 0,
+                                                                   scaled_width,
+                                                                   scaled_height),
+                                                   cairo_stride,
+                                                   NULL, NULL);
 
-      if (! shell->filter_buffer)
+  if (shell->profile_transform ||
+      gimp_display_shell_has_filter (shell))
+    {
+      /*  if there is a profile transform or a display filter, we need
+       *  to use temp buffers
+       */
+
+      /*  create the filter buffer if we have filters
+       */
+      if (gimp_display_shell_has_filter (shell) &&
+          ! shell->filter_buffer)
         {
           gint w = GIMP_DISPLAY_RENDER_BUF_WIDTH  * GIMP_DISPLAY_RENDER_MAX_SCALE;
           gint h = GIMP_DISPLAY_RENDER_BUF_HEIGHT * GIMP_DISPLAY_RENDER_MAX_SCALE;
@@ -163,7 +179,8 @@ gimp_display_shell_render (GimpDisplayShell *shell,
           shell->filter_data =
             gegl_malloc (w * h * babl_format_get_bytes_per_pixel (filter_format));
 
-          shell->filter_stride = w * babl_format_get_bytes_per_pixel (filter_format);
+          shell->filter_stride =
+            w * babl_format_get_bytes_per_pixel (filter_format);
 
           shell->filter_buffer =
             gegl_buffer_linear_new_from_data (shell->filter_data,
@@ -174,48 +191,118 @@ gimp_display_shell_render (GimpDisplayShell *shell,
                                               shell->filter_data);
         }
 
+      if (shell->profile_transform)
+        {
+          /*  if there is a profile transform, load the projection
+           *  pixels into the profile_buffer
+           */
 #ifndef USE_NODE_BLIT
-      gegl_buffer_get (buffer,
-                       GEGL_RECTANGLE (scaled_x, scaled_y,
-                                       scaled_width, scaled_height),
-                       buffer_scale,
-                       filter_format,
-                       shell->filter_data, shell->filter_stride,
-                       GEGL_ABYSS_CLAMP);
+          gegl_buffer_get (buffer,
+                           GEGL_RECTANGLE (scaled_x, scaled_y,
+                                           scaled_width, scaled_height),
+                           buffer_scale,
+                           shell->profile_src_format,
+                           shell->profile_data, shell->profile_stride,
+                           GEGL_ABYSS_CLAMP);
 #else
-      gegl_node_blit (node,
-                      buffer_scale,
-                      GEGL_RECTANGLE (scaled_x, scaled_y,
-                                      scaled_width, scaled_height),
-                      filter_format,
-                      shell->filter_data, shell->filter_stride,
-                      GEGL_BLIT_CACHE);
+          gegl_node_blit (node,
+                          buffer_scale,
+                          GEGL_RECTANGLE (scaled_x, scaled_y,
+                                          scaled_width, scaled_height),
+                          shell->profile_src_format,
+                          shell->profile_data, shell->profile_stride,
+                          GEGL_BLIT_CACHE);
 #endif
 
-      gimp_color_display_stack_convert_buffer (shell->filter_stack,
-                                               shell->filter_buffer,
-                                               GEGL_RECTANGLE (0, 0,
-                                                               scaled_width,
-                                                               scaled_height));
-
-      gegl_buffer_get (shell->filter_buffer,
-                       GEGL_RECTANGLE (0, 0,
-                                       scaled_width,
-                                       scaled_height),
-                       1.0,
-                       babl_format ("cairo-ARGB32"),
-                       data, stride,
-                       GEGL_ABYSS_CLAMP);
+          if (gimp_display_shell_has_filter (shell))
+            {
+              /*  if there are filters, convert the pixels from the
+               *  profile_buffer to the filter_buffer
+               */
+              gimp_display_shell_profile_convert_buffer (shell,
+                                                         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_display_shell_profile_convert_buffer (shell,
+                                                         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
+           */
+#ifndef USE_NODE_BLIT
+          gegl_buffer_get (buffer,
+                           GEGL_RECTANGLE (scaled_x, scaled_y,
+                                           scaled_width, scaled_height),
+                           buffer_scale,
+                           filter_format,
+                           shell->filter_data, shell->filter_stride,
+                           GEGL_ABYSS_CLAMP);
+#else
+          gegl_node_blit (node,
+                          buffer_scale,
+                          GEGL_RECTANGLE (scaled_x, scaled_y,
+                                          scaled_width, scaled_height),
+                          filter_format,
+                          shell->filter_data, shell->filter_stride,
+                          GEGL_BLIT_CACHE);
+#endif
+        }
+
+      if (gimp_display_shell_has_filter (shell))
+        {
+          /*  convert the filter_buffer in place
+           */
+          gimp_color_display_stack_convert_buffer (shell->filter_stack,
+                                                   shell->filter_buffer,
+                                                   GEGL_RECTANGLE (0, 0,
+                                                                   scaled_width,
+                                                                   scaled_height));
+
+          /*  finally, copy the filter buffer to the cairo-ARGB32 buffer
+           */
+          gegl_buffer_get (shell->filter_buffer,
+                           GEGL_RECTANGLE (0, 0,
+                                           scaled_width,
+                                           scaled_height),
+                           1.0,
+                           babl_format ("cairo-ARGB32"),
+                           cairo_data, cairo_stride,
+                           GEGL_ABYSS_CLAMP);
+        }
     }
   else
     {
+      /*  otherwise we can copy the projection pixels straight to the
+       *  cairo-ARGB32 buffer
+       */
 #ifndef USE_NODE_BLIT
       gegl_buffer_get (buffer,
                        GEGL_RECTANGLE (scaled_x, scaled_y,
                                        scaled_width, scaled_height),
                        buffer_scale,
                        babl_format ("cairo-ARGB32"),
-                       data, stride,
+                       cairo_data, cairo_stride,
                        GEGL_ABYSS_CLAMP);
 #else
       gegl_node_blit (node,
@@ -223,11 +310,13 @@ gimp_display_shell_render (GimpDisplayShell *shell,
                       GEGL_RECTANGLE (scaled_x, scaled_y,
                                       scaled_width, scaled_height),
                       babl_format ("cairo-ARGB32"),
-                      data, stride,
+                      cairo_data, cairo_stride,
                       GEGL_BLIT_CACHE);
 #endif
     }
 
+  g_object_unref (cairo_buffer);
+
   if (shell->mask)
     {
       if (! shell->mask_surface)
@@ -242,16 +331,16 @@ gimp_display_shell_render (GimpDisplayShell *shell,
 
       cairo_surface_mark_dirty (shell->mask_surface);
 
-      stride = cairo_image_surface_get_stride (shell->mask_surface);
-      data = cairo_image_surface_get_data (shell->mask_surface);
-      data += mask_src_y * stride + mask_src_x * 4;
+      cairo_stride = cairo_image_surface_get_stride (shell->mask_surface);
+      cairo_data   = cairo_image_surface_get_data (shell->mask_surface) +
+                     mask_src_y * cairo_stride + mask_src_x * 4;
 
       gegl_buffer_get (shell->mask,
                        GEGL_RECTANGLE (scaled_x, scaled_y,
                                        scaled_width, scaled_height),
                        buffer_scale,
                        babl_format ("Y u8"),
-                       data, stride,
+                       cairo_data, cairo_stride,
                        GEGL_ABYSS_CLAMP);
 
       if (shell->mask_inverted)
@@ -261,7 +350,7 @@ gimp_display_shell_render (GimpDisplayShell *shell,
           while (mask_height--)
             {
               gint    mask_width = scaled_width;
-              guchar *d          = data;
+              guchar *d          = cairo_data;
 
               while (mask_width--)
                 {
@@ -270,7 +359,7 @@ gimp_display_shell_render (GimpDisplayShell *shell,
                   *d++ = inv;
                 }
 
-              data += stride;
+              cairo_data += cairo_stride;
             }
         }
     }


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