[gimp] app: add gimp_gegl_convert_color_profile()



commit b03f0fc6e25001f0e76f801bd9537821047aeb29
Author: Michael Natterer <mitch gimp org>
Date:   Fri Aug 14 22:39:18 2015 +0200

    app: add gimp_gegl_convert_color_profile()
    
    which converts a buffer with a profile into another one with another
    profile. The function tries to avoid the lcms transform by checking if
    a simple gegl_buffer_copy() has the same result.

 app/gegl/Makefile.am       |    1 +
 app/gegl/gimp-gegl-loops.c |  106 +++++++++++++++++++++++++++++++++++++++++++
 app/gegl/gimp-gegl-loops.h |  107 ++++++++++++++++++++++++--------------------
 3 files changed, 165 insertions(+), 49 deletions(-)
---
diff --git a/app/gegl/Makefile.am b/app/gegl/Makefile.am
index 5217fdf..3b6ccef 100644
--- a/app/gegl/Makefile.am
+++ b/app/gegl/Makefile.am
@@ -9,6 +9,7 @@ AM_CPPFLAGS = \
        $(CAIRO_CFLAGS)                 \
        $(GEGL_CFLAGS)                  \
        $(GDK_PIXBUF_CFLAGS)            \
+       $(LCMS_CFLAGS)                  \
        -I$(includedir)
 
 noinst_LIBRARIES = libappgegl.a
diff --git a/app/gegl/gimp-gegl-loops.c b/app/gegl/gimp-gegl-loops.c
index dcf1015..52c5359 100644
--- a/app/gegl/gimp-gegl-loops.c
+++ b/app/gegl/gimp-gegl-loops.c
@@ -20,9 +20,14 @@
 
 #include "config.h"
 
+#include <lcms2.h>
+
+#include <cairo.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
 #include <gegl.h>
 
 #include "libgimpmath/gimpmath.h"
+#include "libgimpcolor/gimpcolor.h"
 
 #include "gimp-gegl-types.h"
 
@@ -618,3 +623,104 @@ gimp_gegl_replace (GeglBuffer          *top_buffer,
         }
     }
 }
+
+static gboolean
+gimp_color_profile_can_gegl_copy (GimpColorProfile *src_profile,
+                                  GimpColorProfile *dest_profile)
+{
+  static GimpColorProfile *srgb_profile       = NULL;
+  static GimpColorProfile *linear_rgb_profile = NULL;
+
+  if (gimp_color_profile_is_equal (src_profile, dest_profile))
+    return TRUE;
+
+  if (! srgb_profile)
+    {
+      srgb_profile       = gimp_color_profile_new_srgb ();
+      linear_rgb_profile = gimp_color_profile_new_linear_rgb ();
+    }
+
+  if ((gimp_color_profile_is_equal (src_profile, srgb_profile) ||
+       gimp_color_profile_is_equal (src_profile, linear_rgb_profile))
+      &&
+      (gimp_color_profile_is_equal (dest_profile, srgb_profile) ||
+       gimp_color_profile_is_equal (dest_profile, linear_rgb_profile)))
+    return TRUE;
+
+  return FALSE;
+}
+
+void
+gimp_gegl_convert_color_profile (GeglBuffer               *src_buffer,
+                                 const GeglRectangle      *src_rect,
+                                 GimpColorProfile         *src_profile,
+                                 GeglBuffer               *dest_buffer,
+                                 const GeglRectangle      *dest_rect,
+                                 GimpColorProfile         *dest_profile,
+                                 GimpColorRenderingIntent  intent,
+                                 gboolean                  bpc)
+{
+  const Babl       *src_format;
+  const Babl       *dest_format;
+  cmsHPROFILE       src_lcms;
+  cmsHPROFILE       dest_lcms;
+  cmsUInt32Number   lcms_src_format;
+  cmsUInt32Number   lcms_dest_format;
+  cmsUInt32Number   flags;
+  cmsHTRANSFORM     transform;
+
+  /*  FIXME: we need the unconditional full copy only in two cases:
+   *  - if we return without doing anything
+   *  - if there is an alpha channel, because lcms doesn't copy it
+   */
+  gegl_buffer_copy (src_buffer,  src_rect, GEGL_ABYSS_NONE,
+                    dest_buffer, dest_rect);
+
+  src_format  = gegl_buffer_get_format (src_buffer);
+  dest_format = gegl_buffer_get_format (dest_buffer);
+
+  if ((gimp_babl_format_get_base_type (src_format)  != GIMP_RGB) ||
+      (gimp_babl_format_get_base_type (dest_format) != GIMP_RGB))
+    return;
+
+  if (gimp_color_profile_can_gegl_copy (src_profile, dest_profile))
+    return;
+
+  src_lcms  = gimp_color_profile_get_lcms_profile (src_profile);
+  dest_lcms = gimp_color_profile_get_lcms_profile (dest_profile);
+
+  src_format  = gimp_color_profile_get_format (src_format,  &lcms_src_format);
+  dest_format = gimp_color_profile_get_format (dest_format, &lcms_dest_format);
+
+  flags = cmsFLAGS_NOOPTIMIZE;
+
+  if (bpc)
+    flags |= cmsFLAGS_BLACKPOINTCOMPENSATION;
+
+  transform = cmsCreateTransform (src_lcms,  lcms_src_format,
+                                  dest_lcms, lcms_dest_format,
+                                  intent, flags);
+
+  if (transform)
+    {
+      GeglBufferIterator *iter;
+
+      iter = gegl_buffer_iterator_new (src_buffer, src_rect, 0,
+                                       src_format,
+                                       GEGL_ACCESS_READ,
+                                       GEGL_ABYSS_NONE);
+
+      gegl_buffer_iterator_add (iter, dest_buffer, dest_rect, 0,
+                                dest_format,
+                                GEGL_ACCESS_WRITE,
+                                GEGL_ABYSS_NONE);
+
+      while (gegl_buffer_iterator_next (iter))
+        {
+          cmsDoTransform (transform,
+                          iter->data[0], iter->data[1], iter->length);
+        }
+
+      cmsDeleteTransform (transform);
+    }
+}
diff --git a/app/gegl/gimp-gegl-loops.h b/app/gegl/gimp-gegl-loops.h
index f166967..1938af9 100644
--- a/app/gegl/gimp-gegl-loops.h
+++ b/app/gegl/gimp-gegl-loops.h
@@ -25,61 +25,70 @@
 /*  this is a pretty stupid port of concolve_region() that only works
  *  on a linear source buffer
  */
-void   gimp_gegl_convolve           (GeglBuffer          *src_buffer,
-                                     const GeglRectangle *src_rect,
-                                     GeglBuffer          *dest_buffer,
-                                     const GeglRectangle *dest_rect,
-                                     const gfloat        *kernel,
-                                     gint                 kernel_size,
-                                     gdouble              divisor,
-                                     GimpConvolutionType  mode,
-                                     gboolean             alpha_weighting);
+void   gimp_gegl_convolve              (GeglBuffer               *src_buffer,
+                                        const GeglRectangle      *src_rect,
+                                        GeglBuffer               *dest_buffer,
+                                        const GeglRectangle      *dest_rect,
+                                        const gfloat             *kernel,
+                                        gint                      kernel_size,
+                                        gdouble                   divisor,
+                                        GimpConvolutionType       mode,
+                                        gboolean                  alpha_weighting);
 
-void   gimp_gegl_dodgeburn          (GeglBuffer          *src_buffer,
-                                     const GeglRectangle *src_rect,
-                                     GeglBuffer          *dest_buffer,
-                                     const GeglRectangle *dest_rect,
-                                     gdouble              exposure,
-                                     GimpDodgeBurnType    type,
-                                     GimpTransferMode     mode);
+void   gimp_gegl_dodgeburn             (GeglBuffer               *src_buffer,
+                                        const GeglRectangle      *src_rect,
+                                        GeglBuffer               *dest_buffer,
+                                        const GeglRectangle      *dest_rect,
+                                        gdouble                   exposure,
+                                        GimpDodgeBurnType         type,
+                                        GimpTransferMode          mode);
 
-void   gimp_gegl_smudge_blend       (GeglBuffer          *top_buffer,
-                                     const GeglRectangle *top_rect,
-                                     GeglBuffer          *bottom_buffer,
-                                     const GeglRectangle *bottom_rect,
-                                     GeglBuffer          *dest_buffer,
-                                     const GeglRectangle *dest_rect,
-                                     gdouble              blend);
+void   gimp_gegl_smudge_blend          (GeglBuffer               *top_buffer,
+                                        const GeglRectangle      *top_rect,
+                                        GeglBuffer               *bottom_buffer,
+                                        const GeglRectangle      *bottom_rect,
+                                        GeglBuffer               *dest_buffer,
+                                        const GeglRectangle      *dest_rect,
+                                        gdouble                   blend);
 
-void   gimp_gegl_apply_mask         (GeglBuffer          *mask_buffer,
-                                     const GeglRectangle *mask_rect,
-                                     GeglBuffer          *dest_buffer,
-                                     const GeglRectangle *dest_rect,
-                                     gdouble              opacity);
+void   gimp_gegl_apply_mask            (GeglBuffer               *mask_buffer,
+                                        const GeglRectangle      *mask_rect,
+                                        GeglBuffer               *dest_buffer,
+                                        const GeglRectangle      *dest_rect,
+                                        gdouble                   opacity);
 
-void   gimp_gegl_combine_mask       (GeglBuffer          *mask_buffer,
-                                     const GeglRectangle *mask_rect,
-                                     GeglBuffer          *dest_buffer,
-                                     const GeglRectangle *dest_rect,
-                                     gdouble              opacity);
+void   gimp_gegl_combine_mask          (GeglBuffer               *mask_buffer,
+                                        const GeglRectangle      *mask_rect,
+                                        GeglBuffer               *dest_buffer,
+                                        const GeglRectangle      *dest_rect,
+                                        gdouble                   opacity);
 
-void   gimp_gegl_combine_mask_weird (GeglBuffer          *mask_buffer,
-                                     const GeglRectangle *mask_rect,
-                                     GeglBuffer          *dest_buffer,
-                                     const GeglRectangle *dest_rect,
-                                     gdouble              opacity,
-                                     gboolean             stipple);
+void   gimp_gegl_combine_mask_weird    (GeglBuffer               *mask_buffer,
+                                        const GeglRectangle      *mask_rect,
+                                        GeglBuffer               *dest_buffer,
+                                        const GeglRectangle      *dest_rect,
+                                        gdouble                   opacity,
+                                        gboolean                  stipple);
 
-void   gimp_gegl_replace            (GeglBuffer          *top_buffer,
-                                     const GeglRectangle *top_rect,
-                                     GeglBuffer          *bottom_buffer,
-                                     const GeglRectangle *bottom_rect,
-                                     GeglBuffer          *mask_buffer,
-                                     const GeglRectangle *mask_rect,
-                                     GeglBuffer          *dest_buffer,
-                                     const GeglRectangle *dest_rect,
-                                     gdouble              opacity,
-                                     const gboolean      *affect);
+void   gimp_gegl_replace               (GeglBuffer               *top_buffer,
+                                        const GeglRectangle      *top_rect,
+                                        GeglBuffer               *bottom_buffer,
+                                        const GeglRectangle      *bottom_rect,
+                                        GeglBuffer               *mask_buffer,
+                                        const GeglRectangle      *mask_rect,
+                                        GeglBuffer               *dest_buffer,
+                                        const GeglRectangle      *dest_rect,
+                                        gdouble                   opacity,
+                                        const gboolean           *affect);
+
+void   gimp_gegl_convert_color_profile (GeglBuffer               *src_buffer,
+                                        const GeglRectangle      *src_rect,
+                                        GimpColorProfile         *src_profile,
+                                        GeglBuffer               *dest_buffer,
+                                        const GeglRectangle      *dest_rect,
+                                        GimpColorProfile         *dest_profile,
+                                        GimpColorRenderingIntent  intent,
+                                        gboolean                  bpc);
 
 
 #endif /* __GIMP_GEGL_LOOPS_H__ */


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