[gimp] plug-ins: improve decision of exported data format in TIFF export.



commit 8d9e70011d493e82632e9b1195872274ed4bfdec
Author: Jehan <jehan girinstud io>
Date:   Wed Jun 5 17:16:43 2019 +0200

    plug-ins: improve decision of exported data format in TIFF export.
    
    Same as we did for PNG and JPEG, we want to always export data with the
    TRC of a profile manually assigned, and in particular NOT the curve of
    the storage in GIMP (i.e. you may work on 32-bit linear, yet if you
    assigned a sRGB TRC profile, this is what you should export). The
    storage format will only dictate the exported data TRC when writing out
    the default profile (i.e. no explicit profile assignement).
    As a last case, when no profile is saved, we always export as sRGB.
    
    As for the export precision, we always follow the storage one's, except
    sometimes for 8-bit images. We promote 8-bit images to 16-bit if and
    only if the storage does not match the export data linearity, to avoid
    too much quality loss during format conversion.

 plug-ins/file-tiff/file-tiff-save.c | 89 ++++++++++++++-----------------------
 1 file changed, 33 insertions(+), 56 deletions(-)
---
diff --git a/plug-ins/file-tiff/file-tiff-save.c b/plug-ins/file-tiff/file-tiff-save.c
index ac42dc791b..df7cba355a 100644
--- a/plug-ins/file-tiff/file-tiff-save.c
+++ b/plug-ins/file-tiff/file-tiff-save.c
@@ -274,6 +274,7 @@ save_layer (TIFF         *tif,
             gint32        orig_image, /* the export function might */
                                       /* have created a duplicate  */
             gint         *saved_bpp,
+            gboolean      out_linear,
             GError      **error)
 {
   gboolean          status = FALSE;
@@ -287,7 +288,6 @@ save_layer (TIFF         *tif,
   gboolean          alpha;
   gshort            predictor;
   gshort            photometric;
-  gboolean          linear  = FALSE;
   const Babl       *format;
   const Babl       *type;
   gshort            samplesperpixel;
@@ -340,8 +340,11 @@ save_layer (TIFF         *tif,
   switch (gimp_image_get_precision (image))
     {
     case GIMP_PRECISION_U8_LINEAR:
-      /* only keep 8 bit linear RGB if we also save a profile */
-      if (tsvals->save_profile)
+    case GIMP_PRECISION_U8_NON_LINEAR:
+    case GIMP_PRECISION_U8_PERCEPTUAL:
+      /* Promote to 16-bit if storage and export TRC don't match. */
+      if ((gimp_image_get_precision (image) == GIMP_PRECISION_U8_LINEAR && out_linear) ||
+          (gimp_image_get_precision (image) != GIMP_PRECISION_U8_LINEAR && ! out_linear))
         {
           bitspersample = 8;
           sampleformat  = SAMPLEFORMAT_UINT;
@@ -354,12 +357,6 @@ save_layer (TIFF         *tif,
         }
       break;
 
-    case GIMP_PRECISION_U8_NON_LINEAR:
-    case GIMP_PRECISION_U8_PERCEPTUAL:
-      bitspersample = 8;
-      sampleformat  = SAMPLEFORMAT_UINT;
-      break;
-
     case GIMP_PRECISION_U16_LINEAR:
     case GIMP_PRECISION_U16_NON_LINEAR:
     case GIMP_PRECISION_U16_PERCEPTUAL:
@@ -397,28 +394,6 @@ save_layer (TIFF         *tif,
       break;
     }
 
-  switch (gimp_image_get_precision (image))
-    {
-    case GIMP_PRECISION_U8_LINEAR:
-    case GIMP_PRECISION_U16_LINEAR:
-    case GIMP_PRECISION_U32_LINEAR:
-    case GIMP_PRECISION_HALF_LINEAR:
-    case GIMP_PRECISION_FLOAT_LINEAR:
-    case GIMP_PRECISION_DOUBLE_LINEAR:
-      /* save linear RGB only if we save a profile, or a loader won't
-       * do the right thing
-       */
-      if (tsvals->save_profile)
-        linear = TRUE;
-      else
-        linear = FALSE;
-      break;
-
-    default:
-      linear = FALSE;
-      break;
-    }
-
   *saved_bpp = bitspersample;
 
   cols = gegl_buffer_get_width (buffer);
@@ -431,7 +406,7 @@ save_layer (TIFF         *tif,
       samplesperpixel = 3;
       photometric     = PHOTOMETRIC_RGB;
       alpha           = FALSE;
-      if (linear)
+      if (out_linear)
         {
           format = babl_format_new (babl_model ("RGB"),
                                     type,
@@ -455,7 +430,7 @@ save_layer (TIFF         *tif,
       samplesperpixel = 1;
       photometric     = PHOTOMETRIC_MINISBLACK;
       alpha           = FALSE;
-      if (linear)
+      if (out_linear)
         {
           format = babl_format_new (babl_model ("Y"),
                                     type,
@@ -478,7 +453,7 @@ save_layer (TIFF         *tif,
       alpha           = TRUE;
       if (tsvals->save_transp_pixels)
         {
-          if (linear)
+          if (out_linear)
             {
               format = babl_format_new (babl_model ("RGBA"),
                                         type,
@@ -501,7 +476,7 @@ save_layer (TIFF         *tif,
         }
       else
         {
-          if (linear)
+          if (out_linear)
             {
               format = babl_format_new (babl_model ("RaGaBaA"),
                                         type,
@@ -530,7 +505,7 @@ save_layer (TIFF         *tif,
       alpha           = TRUE;
       if (tsvals->save_transp_pixels)
         {
-          if (linear)
+          if (out_linear)
             {
               format = babl_format_new (babl_model ("YA"),
                                         type,
@@ -549,7 +524,7 @@ save_layer (TIFF         *tif,
         }
       else
         {
-          if (linear)
+          if (out_linear)
             {
               format = babl_format_new (babl_model ("YaA"),
                                         type,
@@ -973,12 +948,12 @@ save_image (GFile                  *file,
             GimpMetadataSaveFlags   metadata_flags,
             GError                **error)
 {
-  gboolean          status = FALSE;
-  TIFF             *tif;
-  GimpColorProfile *profile = NULL;
-  gint              number_of_sub_IFDs = 1;
-  toff_t            sub_IFDs_offsets[1] = { 0UL };
-  gint32            num_layers, *layers, current_layer = 0;
+  TIFF     *tif;
+  gboolean  status              = FALSE;
+  gboolean  out_linear          = FALSE;
+  gint      number_of_sub_IFDs  = 1;
+  toff_t    sub_IFDs_offsets[1] = { 0UL };
+  gint32    num_layers, *layers, current_layer = 0;
 
   layers = gimp_image_get_layers (image, &num_layers);
 
@@ -1033,23 +1008,25 @@ save_image (GFile                  *file,
       gimp_parasite_free (parasite);
     }
 
-  /* do we have an ICC profile? If so, write it to the TIFF file */
 #ifdef TIFFTAG_ICCPROFILE
   if (tsvals->save_profile)
     {
-      profile = gimp_image_get_effective_color_profile (orig_image);
-
-      if (profile)
-        {
-          const guint8 *icc_data;
-          gsize         icc_length;
+      GimpColorProfile *profile;
+      const guint8     *icc_data;
+      gsize             icc_length;
 
-          icc_data = gimp_color_profile_get_icc_profile (profile, &icc_length);
+      profile = gimp_image_get_effective_color_profile (orig_image);
 
-          TIFFSetField (tif, TIFFTAG_ICCPROFILE, icc_length, icc_data);
+      /* Curve of the exported data depends on the saved profile, i.e.
+       * any explicitly-set profile in priority, or the default one for
+       * the storage format as fallback.
+       */
+      out_linear = (gimp_color_profile_is_linear (profile));
 
-          g_object_unref (profile);
-        }
+      /* Write the profile to the TIFF file. */
+      icc_data = gimp_color_profile_get_icc_profile (profile, &icc_length);
+      TIFFSetField (tif, TIFFTAG_ICCPROFILE, icc_length, icc_data);
+      g_object_unref (profile);
     }
 #endif
 
@@ -1061,7 +1038,7 @@ save_image (GFile                  *file,
   if (! save_layer (tif,  tsvals, image,
                     layers[num_layers - current_layer - 1],
                     current_layer, num_layers,
-                    orig_image, saved_bpp, error))
+                    orig_image, saved_bpp, out_linear, error))
     {
       goto out;
     }
@@ -1102,7 +1079,7 @@ save_image (GFile                  *file,
           if (! save_layer (tif,  tsvals, image,
                             layers[num_layers - current_layer - 1],
                             current_layer, num_layers, orig_image,
-                            &tmp_saved_bpp, error))
+                            &tmp_saved_bpp, out_linear, error))
             {
               goto out;
             }


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