mirror of https://github.com/GNOME/gimp.git
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.
This commit is contained in:
parent
0f07f1baa5
commit
1462a91d86
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue