[gimp] Bug 750874 - Displayed colors look clipped after profile conversion...



commit c876e281b1a707ea908bedc46934c09c0479b628
Author: Michael Natterer <mitch gimp org>
Date:   Sat Jun 13 00:27:21 2015 +0200

    Bug 750874 - Displayed colors look clipped after profile conversion...
    
    but they aren't clipped
    
    Add gimp_display_shell_profile_can_convert_to_u8() which returns
    whether the lcms transform can safely write directly into an u8 buffer
    without destroying out-of-gammut pixel values, which we assume is the
    case for all integer formats. If the function returns FALSE, always
    convert via the R'G'B'A float filter_buffer.
    
    Also connect to the image's "precision-changed" signal and update the
    profile transform when it's emitted.

 app/display/gimpdisplayshell-handlers.c |   19 +++++++++++++++-
 app/display/gimpdisplayshell-profile.c  |   36 ++++++++++++++++++++++++++++--
 app/display/gimpdisplayshell-profile.h  |   16 +++++++------
 app/display/gimpdisplayshell-render.c   |   11 +++++++-
 4 files changed, 69 insertions(+), 13 deletions(-)
---
diff --git a/app/display/gimpdisplayshell-handlers.c b/app/display/gimpdisplayshell-handlers.c
index ea319b4..9849d65 100644
--- a/app/display/gimpdisplayshell-handlers.c
+++ b/app/display/gimpdisplayshell-handlers.c
@@ -117,6 +117,8 @@ static void   gimp_display_shell_sample_point_move_handler  (GimpImage        *i
                                                              GimpDisplayShell *shell);
 static void   gimp_display_shell_invalidate_preview_handler (GimpImage        *image,
                                                              GimpDisplayShell *shell);
+static void   gimp_display_shell_precision_changed_handler  (GimpImage        *image,
+                                                             GimpDisplayShell *shell);
 static void   gimp_display_shell_profile_changed_handler    (GimpColorManaged *image,
                                                              GimpDisplayShell *shell);
 static void   gimp_display_shell_saved_handler              (GimpImage        *image,
@@ -251,9 +253,15 @@ gimp_display_shell_connect (GimpDisplayShell *shell)
   g_signal_connect (image, "invalidate-preview",
                     G_CALLBACK (gimp_display_shell_invalidate_preview_handler),
                     shell);
+  g_signal_connect (image, "precision-changed",
+                    G_CALLBACK (gimp_display_shell_precision_changed_handler),
+                    shell);
   g_signal_connect (image, "profile-changed",
                     G_CALLBACK (gimp_display_shell_profile_changed_handler),
                     shell);
+  g_signal_connect (image, "precision-changed",
+                    G_CALLBACK (gimp_display_shell_precision_changed_handler),
+                    shell);
   g_signal_connect (image, "saved",
                     G_CALLBACK (gimp_display_shell_saved_handler),
                     shell);
@@ -454,6 +462,9 @@ gimp_display_shell_disconnect (GimpDisplayShell *shell)
                                         gimp_display_shell_profile_changed_handler,
                                         shell);
   g_signal_handlers_disconnect_by_func (image,
+                                        gimp_display_shell_precision_changed_handler,
+                                        shell);
+  g_signal_handlers_disconnect_by_func (image,
                                         gimp_display_shell_invalidate_preview_handler,
                                         shell);
 
@@ -791,13 +802,19 @@ gimp_display_shell_invalidate_preview_handler (GimpImage        *image,
 }
 
 static void
+gimp_display_shell_precision_changed_handler (GimpImage        *image,
+                                              GimpDisplayShell *shell)
+{
+  gimp_display_shell_profile_update (shell);
+}
+
+static void
 gimp_display_shell_profile_changed_handler (GimpColorManaged *image,
                                             GimpDisplayShell *shell)
 {
   gimp_color_managed_profile_changed (GIMP_COLOR_MANAGED (shell));
 }
 
-
 static void
 gimp_display_shell_saved_handler (GimpImage        *image,
                                   GFile            *file,
diff --git a/app/display/gimpdisplayshell-profile.c b/app/display/gimpdisplayshell-profile.c
index 699e9dc..38cc9e2 100644
--- a/app/display/gimpdisplayshell-profile.c
+++ b/app/display/gimpdisplayshell-profile.c
@@ -34,6 +34,7 @@
 
 #include "gegl/gimp-babl.h"
 
+#include "core/gimpimage.h"
 #include "core/gimppickable.h"
 
 #include "gimpdisplay.h"
@@ -92,10 +93,15 @@ gimp_display_shell_profile_update (GimpDisplayShell *shell)
                                  gimp_image_get_precision (image),
                                  TRUE);
 
-  if (gimp_display_shell_has_filter (shell))
-    dest_format = shell->filter_format;
+  if (gimp_display_shell_has_filter (shell) ||
+      ! gimp_display_shell_profile_can_convert_to_u8 (shell))
+    {
+      dest_format = shell->filter_format;
+    }
   else
-    dest_format = babl_format ("R'G'B'A u8");
+    {
+      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));
@@ -130,6 +136,30 @@ gimp_display_shell_profile_update (GimpDisplayShell *shell)
     }
 }
 
+gboolean
+gimp_display_shell_profile_can_convert_to_u8 (GimpDisplayShell *shell)
+{
+  GimpImage *image;
+
+  image = gimp_display_get_image (shell->display);
+
+  if (image)
+    {
+      switch (gimp_image_get_component_type (image))
+        {
+        case GIMP_COMPONENT_TYPE_U8:
+        case GIMP_COMPONENT_TYPE_U16:
+        case GIMP_COMPONENT_TYPE_U32:
+          return TRUE;
+
+        default:
+          break;
+        }
+    }
+
+  return FALSE;
+}
+
 void
 gimp_display_shell_profile_convert_buffer (GimpDisplayShell *shell,
                                            GeglBuffer       *src_buffer,
diff --git a/app/display/gimpdisplayshell-profile.h b/app/display/gimpdisplayshell-profile.h
index 09f2ea9..a961f6c 100644
--- a/app/display/gimpdisplayshell-profile.h
+++ b/app/display/gimpdisplayshell-profile.h
@@ -19,14 +19,16 @@
 #define __GIMP_DISPLAY_SHELL_PROFILE_H__
 
 
-void   gimp_display_shell_profile_dispose        (GimpDisplayShell *shell);
-void   gimp_display_shell_profile_update         (GimpDisplayShell *shell);
+void     gimp_display_shell_profile_dispose           (GimpDisplayShell *shell);
+void     gimp_display_shell_profile_update            (GimpDisplayShell *shell);
 
-void   gimp_display_shell_profile_convert_buffer (GimpDisplayShell *shell,
-                                                  GeglBuffer       *src_buffer,
-                                                  GeglRectangle    *src_area,
-                                                  GeglBuffer       *dest_buffer,
-                                                  GeglRectangle    *dest_area);
+gboolean gimp_display_shell_profile_can_convert_to_u8 (GimpDisplayShell *shell);
+
+void     gimp_display_shell_profile_convert_buffer    (GimpDisplayShell *shell,
+                                                       GeglBuffer       *src_buffer,
+                                                       GeglRectangle    *src_area,
+                                                       GeglBuffer       *dest_buffer,
+                                                       GeglRectangle    *dest_area);
 
 
 #endif /*  __GIMP_DISPLAY_SHELL_PROFILE_H__  */
diff --git a/app/display/gimpdisplayshell-render.c b/app/display/gimpdisplayshell-render.c
index 9936876..6fa65e5 100644
--- a/app/display/gimpdisplayshell-render.c
+++ b/app/display/gimpdisplayshell-render.c
@@ -163,13 +163,17 @@ gimp_display_shell_render (GimpDisplayShell *shell,
   if (shell->profile_transform ||
       gimp_display_shell_has_filter (shell))
     {
+      gboolean can_convert_to_u8;
+
       /*  if there is a profile transform or a display filter, we need
        *  to use temp buffers
        */
 
+      can_convert_to_u8 = gimp_display_shell_profile_can_convert_to_u8 (shell);
+
       /*  create the filter buffer if we have filters
        */
-      if (gimp_display_shell_has_filter (shell) &&
+      if ((gimp_display_shell_has_filter (shell) || ! can_convert_to_u8) &&
           ! shell->filter_buffer)
         {
           gint w = GIMP_DISPLAY_RENDER_BUF_WIDTH  * GIMP_DISPLAY_RENDER_MAX_SCALE;
@@ -213,7 +217,7 @@ gimp_display_shell_render (GimpDisplayShell *shell,
                           GEGL_BLIT_CACHE);
 #endif
 
-          if (gimp_display_shell_has_filter (shell))
+          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
@@ -277,7 +281,10 @@ gimp_display_shell_render (GimpDisplayShell *shell,
                                                    GEGL_RECTANGLE (0, 0,
                                                                    scaled_width,
                                                                    scaled_height));
+        }
 
+      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,


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