[gimp/gimp-2-10] Add naive support for CMYK u8 PSD files



commit 9faef1b7ad5779a9cba21ef9345ad75daab6fe9f
Author: Massimo Valentini <mvalentini src gnome org>
Date:   Tue Dec 1 11:30:22 2015 +0100

    Add naive support for CMYK u8 PSD files

 plug-ins/file-psd/psd-image-res-load.c |  16 +++-
 plug-ins/file-psd/psd-load.c           | 137 ++++++++++++++++++++++++++++++++-
 plug-ins/file-psd/psd.h                |   4 +
 3 files changed, 150 insertions(+), 7 deletions(-)
---
diff --git a/plug-ins/file-psd/psd-image-res-load.c b/plug-ins/file-psd/psd-image-res-load.c
index 7949c6ca52..23dec2871e 100644
--- a/plug-ins/file-psd/psd-image-res-load.c
+++ b/plug-ins/file-psd/psd-image-res-load.c
@@ -196,6 +196,7 @@ static gint     load_resource_1033     (const PSDimageres     *res_a,
                                         GError               **error);
 
 static gint     load_resource_1039     (const PSDimageres     *res_a,
+                                        PSDimage              *img_a,
                                         gint32                 image_id,
                                         FILE                  *f,
                                         GError               **error);
@@ -368,7 +369,7 @@ load_image_resource (PSDimageres  *res_a,
             break;
 
           case PSD_ICC_PROFILE:
-            if (! load_resource_1039 (res_a, image_id, f, error))
+            if (! load_resource_1039 (res_a, img_a, image_id, f, error))
               *profile_loaded = TRUE;
             break;
 
@@ -1105,6 +1106,7 @@ load_resource_1033 (const PSDimageres  *res_a,
 
 static gint
 load_resource_1039 (const PSDimageres  *res_a,
+                    PSDimage           *img_a,
                     gint32              image_id,
                     FILE               *f,
                     GError            **error)
@@ -1128,8 +1130,16 @@ load_resource_1039 (const PSDimageres  *res_a,
                                                      NULL);
   if (profile)
     {
-      gimp_image_set_color_profile (image_id, profile);
-      g_object_unref (profile);
+      if (img_a->color_mode == PSD_CMYK &&
+          gimp_color_profile_is_cmyk (profile))
+        {
+          img_a->cmyk_profile = profile;
+        }
+      else
+        {
+          gimp_image_set_color_profile (image_id, profile);
+          g_object_unref (profile);
+        }
     }
 
   g_free (icc_profile);
diff --git a/plug-ins/file-psd/psd-load.c b/plug-ins/file-psd/psd-load.c
index cc1487c05e..fefae1708c 100644
--- a/plug-ins/file-psd/psd-load.c
+++ b/plug-ins/file-psd/psd-load.c
@@ -126,6 +126,8 @@ load_image (const gchar  *filename,
   gint32        image_id = -1;
   GError       *error    = NULL;
 
+  img_a.cmyk_transform = img_a.cmyk_transform_alpha = NULL;
+  img_a.cmyk_profile = NULL;
   /* ----- Open PSD file ----- */
   if (g_stat (filename, &st) == -1)
     return -1;
@@ -329,6 +331,7 @@ read_header_block (PSDimage  *img_a,
       && img_a->color_mode != PSD_INDEXED
       && img_a->color_mode != PSD_RGB
       && img_a->color_mode != PSD_MULTICHANNEL
+      && img_a->color_mode != PSD_CMYK
       && img_a->color_mode != PSD_DUOTONE)
     {
       g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
@@ -337,6 +340,17 @@ read_header_block (PSDimage  *img_a,
       return -1;
     }
 
+  if (img_a->color_mode == PSD_CMYK)
+    {
+      if (img_a->bps != 8)
+        {
+          g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+                       _("Unsupported color mode: %s"),
+                       get_psd_color_mode_name (img_a->color_mode));
+          return -1;
+        }
+    }
+
   /* Warning for unsupported bit depth */
   switch (img_a->bps)
     {
@@ -994,6 +1008,7 @@ create_gimp_image (PSDimage    *img_a,
       img_a->base_type = GIMP_INDEXED;
       break;
 
+    case PSD_CMYK:
     case PSD_RGB:
       img_a->base_type = GIMP_RGB;
       break;
@@ -1017,7 +1032,10 @@ create_gimp_image (PSDimage    *img_a,
 
       case 8:
       case 1:
-        precision = GIMP_PRECISION_U8_GAMMA;
+        if (img_a->color_mode == PSD_CMYK)
+          precision = GIMP_PRECISION_FLOAT_GAMMA;
+        else
+          precision = GIMP_PRECISION_U8_GAMMA;
         break;
 
       default:
@@ -1112,6 +1130,72 @@ add_image_resources (gint32     image_id,
   return 0;
 }
 
+static guchar *
+psd_convert_cmyk_to_srgb (PSDimage *img_a,
+                          guchar   *dst,
+                          guchar   *src,
+                          gint      width,
+                          gint      height,
+                          gboolean  alpha)
+{
+  if (img_a->cmyk_profile)
+    {
+      if (alpha)
+        {
+          if (! img_a->cmyk_transform_alpha)
+            {
+              GimpColorProfile *srgb = gimp_color_profile_new_rgb_srgb ();
+
+              img_a->cmyk_transform_alpha = gimp_color_transform_new (img_a->cmyk_profile, babl_format 
("cmykA u8"),
+                                                                      srgb, babl_format ("R'G'B'A float"),
+                                                                      0, 0);
+
+              g_object_unref (srgb);
+            }
+
+        gimp_color_transform_process_pixels (img_a->cmyk_transform_alpha,
+                                             babl_format ("cmykA u8"),
+                                             src,
+                                             babl_format ("R'G'B'A float"),
+                                             dst,
+                                             width * height);
+        }
+      else
+        {
+          if (! img_a->cmyk_transform)
+            {
+              GimpColorProfile *srgb = gimp_color_profile_new_rgb_srgb ();
+
+              img_a->cmyk_transform = gimp_color_transform_new (img_a->cmyk_profile, babl_format ("cmyk u8"),
+                                                                      srgb, babl_format ("R'G'B' float"),
+                                                                      0, 0);
+
+              g_object_unref (srgb);
+            }
+
+          gimp_color_transform_process_pixels (img_a->cmyk_transform_alpha,
+                                               babl_format ("cmyk u8"),
+                                               src,
+                                               babl_format ("R'G'B' float"),
+                                               dst,
+                                               width * height);
+        }
+    }
+  else
+    {
+      const Babl *fish;
+
+      if (alpha)
+        fish = babl_fish ("cmykA u8", "R'G'B'A float");
+      else
+        fish = babl_fish ("cmyk u8", "R'G'B' float");
+
+      babl_process (fish, src, dst, width * height);
+    }
+
+  return (guchar*) dst;
+}
+
 static gint
 add_layers (gint32     image_id,
             PSDimage  *img_a,
@@ -1545,6 +1629,48 @@ add_layers (gint32     image_id,
                           gint                 src_step = bps;
                           gint                 dst_step = bps * layer_channels;
 
+                          if (img_a->color_mode == PSD_CMYK)
+                            {
+                              guchar              *cmyk = g_new (guchar, layer_channels * iter->length);
+
+                              for (cidx = 0; cidx < layer_channels; ++cidx)
+                                {
+                                  gint b, y, x;
+
+                                  if (roi->x == 0 && roi->y == 0)
+                                    IFDBG(3) g_debug ("Start channel %d", channel_idx[cidx]);
+
+                                  for (b = 0; b < bps; ++b)
+                                    {
+                                      guint8 *dst = &cmyk[cidx * bps + b];
+
+                                      for (y = 0; y < roi->height; y++)
+                                        {
+                                          const guint8 *src;
+
+                                          src = (const guint8 *)
+                                            &lyr_chn[channel_idx[cidx]]->data[
+                                            ((roi->y + y) * l_w +
+                                             roi->x)      * bps +
+                                              b];
+
+                                          for (x = 0; x < roi->width; ++x)
+                                            {
+                                              *dst = *src;
+
+                                              src += src_step;
+                                              dst += dst_step;
+                                            }
+                                        }
+                                    }
+                                }
+
+                              psd_convert_cmyk_to_srgb (img_a, dst0, cmyk, roi->width, roi->height, alpha);
+
+                              g_free (cmyk);
+                              continue;
+                            }
+
                           for (cidx = 0; cidx < layer_channels; ++cidx)
                             {
                               gint b;
@@ -1864,11 +1990,14 @@ add_merged_image (gint32     image_id,
       gimp_image_insert_layer (image_id, layer_id, -1, 0);
 
       buffer = gimp_drawable_get_buffer (layer_id);
+      if (img_a->color_mode == PSD_CMYK)
+        img_a->color_mode = PSD_RGB;
+
       gegl_buffer_set (buffer,
                        GEGL_RECTANGLE (0, 0,
                                        gegl_buffer_get_width (buffer),
                                        gegl_buffer_get_height (buffer)),
-                       0, get_layer_format (img_a, img_a->transparency),
+                       0, get_layer_format (img_a, (base_channels % 2) == 0),
                        pixels, GEGL_AUTO_ROWSTRIDE);
 
       /* Merged image data is blended against white.  Unblend it. */
@@ -2378,7 +2507,7 @@ get_layer_format (PSDimage *img_a,
 
         case 8:
         case 1:
-          format = babl_format ("R'G'B' u8");
+          format = babl_format (img_a->color_mode == PSD_CMYK ? "R'G'B' float" : "R'G'B' u8");
           break;
 
         default:
@@ -2400,7 +2529,7 @@ get_layer_format (PSDimage *img_a,
 
         case 8:
         case 1:
-          format = babl_format ("R'G'B'A u8");
+          format = babl_format (img_a->color_mode == PSD_CMYK ? "R'G'B'A float" : "R'G'B'A u8");
           break;
 
         default:
diff --git a/plug-ins/file-psd/psd.h b/plug-ins/file-psd/psd.h
index 50f8349a5f..724609dd09 100644
--- a/plug-ins/file-psd/psd.h
+++ b/plug-ins/file-psd/psd.h
@@ -673,6 +673,10 @@ typedef struct
   guint32              *alpha_id;               /* Alpha channel ids (tattoos) */
   guint16               alpha_id_count;         /* Number of alpha channel id items */
   guint16               quick_mask_id;          /* Channel number containing quick mask */
+
+  GimpColorProfile     *cmyk_profile;
+  gpointer              cmyk_transform;
+  gpointer              cmyk_transform_alpha;
 } PSDimage;
 
 /* Public functions */


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