[gimp] plug-ins: Convert CMYK u8 .psd to R'G'B' float on load
- From: Øyvind "pippin" Kolås <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] plug-ins: Convert CMYK u8 .psd to R'G'B' float on load
- Date: Fri, 21 Feb 2020 11:33:54 +0000 (UTC)
commit 1462a91d86ee31d98ee70bfd7fe0fad913a87883
Author: Øyvind Kolås <pippin gimp org>
Date: Fri Feb 21 12:08:19 2020 +0100
plug-ins: Convert CMYK u8 .psd to R'G'B' float on load
Patch from Massimo Valentini in issue #354, adapted for the new object
based plug-in APIs.
plug-ins/file-psd/psd-image-res-load.c | 16 +++-
plug-ins/file-psd/psd-load.c | 142 ++++++++++++++++++++++++++++++++-
plug-ins/file-psd/psd.h | 4 +
3 files changed, 155 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 650ed44cb1..73b619d006 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,
GimpImage *image,
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, f, error))
+ if (! load_resource_1039 (res_a, img_a, image, 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,
GimpImage *image,
FILE *f,
GError **error)
@@ -1128,8 +1130,16 @@ load_resource_1039 (const PSDimageres *res_a,
NULL);
if (profile)
{
- gimp_image_set_color_profile (image, 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, 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 6d429832ee..f4c8950d16 100644
--- a/plug-ins/file-psd/psd-load.c
+++ b/plug-ins/file-psd/psd-load.c
@@ -129,6 +129,8 @@ load_image (GFile *file,
filename = g_file_get_path (file);
+ img_a.cmyk_transform = img_a.cmyk_transform_alpha = NULL;
+ img_a.cmyk_profile = NULL;
/* ----- Open PSD file ----- */
if (g_stat (filename, &st) == -1)
{
@@ -338,6 +340,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,
@@ -346,6 +349,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)
{
@@ -1003,6 +1017,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;
@@ -1026,7 +1041,10 @@ create_gimp_image (PSDimage *img_a,
case 8:
case 1:
- precision = GIMP_PRECISION_U8_NON_LINEAR;
+ if (img_a->color_mode == PSD_CMYK)
+ precision = GIMP_PRECISION_FLOAT_NON_LINEAR;
+ else
+ precision = GIMP_PRECISION_U8_NON_LINEAR;
break;
default:
@@ -1121,6 +1139,74 @@ add_image_resources (GimpImage *image,
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 (GimpImage *image,
PSDimage *img_a,
@@ -1554,6 +1640,48 @@ add_layers (GimpImage *image,
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;
@@ -1873,11 +2001,14 @@ add_merged_image (GimpImage *image,
gimp_image_insert_layer (image, layer, NULL, 0);
buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (layer));
+ 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. */
@@ -2344,6 +2475,7 @@ get_layer_format (PSDimage *img_a,
case 8:
case 1:
format = babl_format ("Y' u8");
+
break;
default:
@@ -2387,7 +2519,8 @@ 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:
@@ -2409,7 +2542,8 @@ 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 5deb61c0d5..c185bc3207 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]