summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'devices/gdevpsd.c')
-rw-r--r--devices/gdevpsd.c328
1 files changed, 272 insertions, 56 deletions
diff --git a/devices/gdevpsd.c b/devices/gdevpsd.c
index 3c9f6b01..d538b784 100644
--- a/devices/gdevpsd.c
+++ b/devices/gdevpsd.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -57,6 +57,7 @@ static dev_proc_get_params(psd_get_params);
static dev_proc_put_params(psd_put_params);
static dev_proc_get_params(psd_get_params_cmyk);
static dev_proc_put_params(psd_put_params_cmyk);
+static dev_proc_put_params(psd_put_params_cmyktag);
static dev_proc_print_page(psd_print_page);
static dev_proc_map_color_rgb(psd_map_color_rgb);
static dev_proc_get_color_mapping_procs(get_psdrgb_color_mapping_procs);
@@ -69,9 +70,19 @@ typedef enum {
psd_DEVICE_GRAY,
psd_DEVICE_RGB,
psd_DEVICE_CMYK,
+ psd_DEVICE_CMYKT,
psd_DEVICE_N
} psd_color_model;
+fixed_colorant_name DevCMYKTComponents[] = {
+ "Cyan",
+ "Magenta",
+ "Yellow",
+ "Black",
+ "Tags",
+ 0 /* List terminator */
+};
+
/*
* A structure definition for a DeviceN type device
*/
@@ -205,7 +216,7 @@ const psd_device gs_psdrgb_device =
{ true }, /* equivalent CMYK colors for spot colors */
/* PSD device specific parameters */
psd_DEVICE_RGB, /* Color model */
- GS_SOFT_MAX_SPOTS, /* max_spots */
+ GS_SOFT_MAX_SPOTS, /* max_spots */
false, /* colorants not locked */
GX_DOWNSCALER_PARAMS_DEFAULTS
};
@@ -215,13 +226,13 @@ const psd_device gs_psdrgb16_device =
psd_device_body(psd_initialize_device_procs, "psdrgb16", 3, GX_CINFO_POLARITY_ADDITIVE, 48, 65535, 65535, GX_CINFO_SEP_LIN, "DeviceRGB"),
/* devn_params specific parameters */
{ 16, /* Bits per color - must match ncomp, depth, etc. above */
- DeviceRGBComponents, /* Names of color model colorants */
- 3, /* Number colorants for RGB */
- 0, /* MaxSeparations has not been specified */
- -1, /* PageSpotColors has not been specified */
- { 0 }, /* SeparationNames */
- 0, /* SeparationOrder names */
- { 0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */
+ DeviceRGBComponents, /* Names of color model colorants */
+ 3, /* Number colorants for RGB */
+ 0, /* MaxSeparations has not been specified */
+ -1, /* PageSpotColors has not been specified */
+ { 0 }, /* SeparationNames */
+ 0, /* SeparationOrder names */
+ {0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */
},
{ true }, /* equivalent CMYK colors for spot colors */
/* PSD device specific parameters */
@@ -244,6 +255,19 @@ psdcmyk_initialize_device_procs(gx_device *dev)
set_dev_proc(dev, get_color_mapping_procs, get_psd_color_mapping_procs);
}
+/*
+ * PSD device with CMYK process color model, spot color support, and tags.
+ */
+static void
+psdcmyktag_initialize_device_procs(gx_device *dev)
+{
+ psd_initialize_device_procs(dev);
+
+ set_dev_proc(dev, get_params, psd_get_params_cmyk);
+ set_dev_proc(dev, put_params, psd_put_params_cmyktag);
+ set_dev_proc(dev, get_color_mapping_procs, get_psd_color_mapping_procs);
+}
+
const psd_device gs_psdcmyk_device =
{
psd_device_body(psdcmyk_initialize_device_procs, "psdcmyk",
@@ -269,22 +293,47 @@ const psd_device gs_psdcmyk_device =
GX_DOWNSCALER_PARAMS_DEFAULTS
};
+const psd_device gs_psdcmyktags_device =
+{
+ psd_device_body(psdcmyktag_initialize_device_procs, "psdcmyktags",
+ ARCH_SIZEOF_GX_COLOR_INDEX, /* Number of components - need a nominal 1 bit for each */
+ GX_CINFO_POLARITY_SUBTRACTIVE,
+ ARCH_SIZEOF_GX_COLOR_INDEX * 8, /* 8 bits per component (albeit in planes) */
+ 255, 255, GX_CINFO_SEP_LIN, "DeviceCMYK"),
+ /* devn_params specific parameters */
+ { 8, /* Bits per color - must match ncomp, depth, etc. above */
+ DevCMYKTComponents, /* Names of color model colorants */
+ 4, /* Number colorants for CMYK. Tags added to extra in DevCMYKTComponents */
+ 0, /* MaxSeparations has not been specified */
+ -1, /* PageSpotColors has not been specified */
+ {0}, /* SeparationNames */
+ 0, /* SeparationOrder names */
+ {0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */
+ },
+ { true }, /* equivalent CMYK colors for spot colors */
+ /* PSD device specific parameters */
+ psd_DEVICE_CMYKT, /* Color model */
+ GS_SOFT_MAX_SPOTS, /* max_spots */
+ false, /* colorants not locked */
+ GX_DOWNSCALER_PARAMS_DEFAULTS
+};
+
const psd_device gs_psdcmyk16_device =
{
psd_device_body(psdcmyk_initialize_device_procs, "psdcmyk16",
- ARCH_SIZEOF_GX_COLOR_INDEX, /* Number of components - need a nominal 1 bit for each */
- GX_CINFO_POLARITY_SUBTRACTIVE,
- ARCH_SIZEOF_GX_COLOR_INDEX * 16, /* 8 bits per component (albeit in planes) */
- 65535, 65535, GX_CINFO_SEP_LIN, "DeviceCMYK"),
+ ARCH_SIZEOF_GX_COLOR_INDEX, /* Number of components - need a nominal 1 bit for each */
+ GX_CINFO_POLARITY_SUBTRACTIVE,
+ ARCH_SIZEOF_GX_COLOR_INDEX * 16, /* 8 bits per component (albeit in planes) */
+ 65535, 65535, GX_CINFO_SEP_LIN, "DeviceCMYK"),
/* devn_params specific parameters */
{ 16, /* Bits per color - must match ncomp, depth, etc. above */
- DeviceCMYKComponents, /* Names of color model colorants */
- 4, /* Number colorants for CMYK */
- 0, /* MaxSeparations has not been specified */
- -1, /* PageSpotColors has not been specified */
- { 0 }, /* SeparationNames */
- 0, /* SeparationOrder names */
- { 0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */
+ DeviceCMYKComponents, /* Names of color model colorants */
+ 4, /* Number colorants for CMYK */
+ 0, /* MaxSeparations has not been specified */
+ -1, /* PageSpotColors has not been specified */
+ { 0 }, /* SeparationNames */
+ 0, /* SeparationOrder names */
+ {0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */
},
{ true }, /* equivalent CMYK colors for spot colors */
/* PSD device specific parameters */
@@ -294,6 +343,31 @@ const psd_device gs_psdcmyk16_device =
GX_DOWNSCALER_PARAMS_DEFAULTS
};
+const psd_device gs_psdcmyktags16_device =
+{
+ psd_device_body(psdcmyktag_initialize_device_procs, "psdcmyktags16",
+ ARCH_SIZEOF_GX_COLOR_INDEX, /* Number of components - need a nominal 1 bit for each */
+ GX_CINFO_POLARITY_SUBTRACTIVE,
+ ARCH_SIZEOF_GX_COLOR_INDEX * 16, /* 8 bits per component (albeit in planes) */
+ 65535, 65535, GX_CINFO_SEP_LIN, "DeviceCMYK"),
+ /* devn_params specific parameters */
+ { 16, /* Bits per color - must match ncomp, depth, etc. above */
+ DevCMYKTComponents, /* Names of color model colorants */
+ 4, /* Number colorants for CMYK. Tags added to extra in DevCMYKTComponents */
+ 0, /* MaxSeparations has not been specified */
+ -1, /* PageSpotColors has not been specified */
+ { 0 }, /* SeparationNames */
+ 0, /* SeparationOrder names */
+ {0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */
+ },
+ { true }, /* equivalent CMYK colors for spot colors */
+ /* PSD device specific parameters */
+ psd_DEVICE_CMYKT, /* Color model */
+ GS_SOFT_MAX_SPOTS, /* max_spots */
+ false, /* colorants not locked */
+ GX_DOWNSCALER_PARAMS_DEFAULTS
+};
+
/* Open the psd devices */
int
psd_prn_open(gx_device * pdev)
@@ -302,6 +376,7 @@ psd_prn_open(gx_device * pdev)
int code;
int k;
cmm_dev_profile_t *profile_struct;
+ bool has_tags = (pdev_psd->color_model == psd_DEVICE_CMYKT);
#ifdef TEST_PAD_AND_ALIGN
pdev->pad = 5;
@@ -340,7 +415,7 @@ psd_prn_open(gx_device * pdev)
}
pdev->color_info.num_components =
(profile_struct->spotnames->count
- + pdev_psd->devn_params.page_spot_colors);
+ + pdev_psd->devn_params.page_spot_colors + has_tags);
if (pdev->color_info.num_components > pdev->color_info.max_components)
pdev->color_info.num_components = pdev->color_info.max_components;
} else {
@@ -351,7 +426,7 @@ psd_prn_open(gx_device * pdev)
if (!(pdev_psd->lock_colorants)) {
pdev->color_info.num_components =
(pdev_psd->devn_params.page_spot_colors
- + pdev_psd->devn_params.num_std_colorant_names);
+ + pdev_psd->devn_params.num_std_colorant_names + has_tags);
if (pdev->color_info.num_components > pdev->color_info.max_components)
pdev->color_info.num_components = pdev->color_info.max_components;
}
@@ -369,7 +444,7 @@ psd_prn_open(gx_device * pdev)
was set (Default is GS_SOFT_MAX_SPOTS which is 10),
it is made use of here. */
if (!(pdev_psd->lock_colorants)) {
- int num_comp = pdev_psd->max_spots + 4; /* Spots + CMYK */
+ int num_comp = pdev_psd->max_spots + 4 + has_tags; /* Spots + CMYK */
if (num_comp > GS_CLIENT_COLOR_MAX_COMPONENTS)
num_comp = GS_CLIENT_COLOR_MAX_COMPONENTS;
pdev->color_info.num_components = num_comp;
@@ -474,6 +549,49 @@ rgb_cs_to_psdcmyk_cm(const gx_device * dev, const gs_gstate *pgs,
}
static void
+cmyk_cs_to_psdcmyktags_cm(const gx_device *dev,
+ frac c, frac m, frac y, frac k, frac out[])
+{
+ const gs_devn_params *devn = gx_devn_prn_ret_devn_params_const(dev);
+ const int *map = devn->separation_order_map;
+ int j;
+
+ if (devn->num_separation_order_names > 0) {
+ /* This is to set only those that we are using */
+ int ncomps = dev->color_info.num_components;
+ for (j = 0; j < ncomps; j++)
+ out[j] = 0;
+ for (j = 0; j < devn->num_separation_order_names; j++) {
+ switch (map[j]) {
+ case 0:
+ out[0] = c;
+ break;
+ case 1:
+ out[1] = m;
+ break;
+ case 2:
+ out[2] = y;
+ break;
+ case 3:
+ out[3] = k;
+ break;
+ default:
+ break;
+ }
+ }
+ } else {
+ cmyk_cs_to_devn_cm(dev, map, c, m, y, k, out);
+ }
+ /* And set the tags. At this point, the color values
+ are frac representation for the range [0.0 1.0]. We
+ need to encode the graphics type, which is 0 to 255
+ accordingly, as it goes through the same mappings on
+ its way to devn and then eventually to 8 or 16 bit values */
+ if (map[4] != GX_DEVICE_COLOR_MAX_COMPONENTS)
+ out[4] = byte2frac(dev->graphics_type_tag & ~GS_DEVICE_ENCODES_TAGS);
+}
+
+static void
cmyk_cs_to_psdcmyk_cm(const gx_device * dev,
frac c, frac m, frac y, frac k, frac out[])
{
@@ -602,6 +720,10 @@ static const gx_cm_color_map_procs psdCMYK_procs = {
gray_cs_to_psdcmyk_cm, rgb_cs_to_psdcmyk_cm, cmyk_cs_to_psdcmyk_cm
};
+static const gx_cm_color_map_procs psdCMYKtags_procs = {
+ gray_cs_to_psdcmyk_cm, rgb_cs_to_psdcmyk_cm, cmyk_cs_to_psdcmyktags_cm
+};
+
static const gx_cm_color_map_procs psdN_procs = {
gray_cs_to_spotn_cm, rgb_cs_to_spotn_cm, cmyk_cs_to_spotn_cm
};
@@ -627,6 +749,8 @@ get_psd_color_mapping_procs(const gx_device * dev, const gx_device **map_dev)
return &psdRGB_procs;
else if (xdev->color_model == psd_DEVICE_CMYK)
return &psdCMYK_procs;
+ else if (xdev->color_model == psd_DEVICE_CMYKT)
+ return &psdCMYKtags_procs;
else if (xdev->color_model == psd_DEVICE_N)
return &psdN_procs;
else if (xdev->color_model == psd_DEVICE_GRAY)
@@ -744,6 +868,13 @@ psd_put_params_cmyk(gx_device * pdev, gs_param_list * plist)
return psd_put_params_generic(pdev, plist, 1);
}
+static int
+psd_put_params_cmyktag(gx_device *pdev, gs_param_list* plist)
+{
+ pdev->graphics_type_tag |= GS_DEVICE_ENCODES_TAGS;
+ return psd_put_params_generic(pdev, plist, 1);
+}
+
/*
* This routine will check to see if the color component name match those
* that are available amoung the current device's color components.
@@ -812,7 +943,18 @@ psd_setup(psd_write_ctx *xc, gx_devn_prn_device *dev, gp_file *file, int w, int
if (dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE
&& strcmp(dev->dname, "psdcmykog") != 0) {
if (dev->devn_params.num_separation_order_names == 0) {
- xc->n_extra_channels = dev->devn_params.separations.num_separations;
+ /* Page spot colors has been truncated to ensure max
+ colorants of the target device is not exceeded. This
+ is set if PDF file was encountered and should be used.
+ Also make sure PS file does not exceed limit of device. */
+ if (dev->devn_params.page_spot_colors > 0)
+ xc->n_extra_channels = dev->devn_params.page_spot_colors;
+ else {
+ if (dev->devn_params.separations.num_separations <= (dev->color_info.max_components - NUM_CMYK_COMPONENTS))
+ xc->n_extra_channels = dev->devn_params.separations.num_separations;
+ else
+ xc->n_extra_channels = dev->color_info.max_components - NUM_CMYK_COMPONENTS;
+ }
} else {
/* Have to figure out how many in the order list were not std
colorants */
@@ -856,24 +998,33 @@ psd_setup(psd_write_ctx *xc, gx_devn_prn_device *dev, gp_file *file, int w, int
/* No order specified, map them alpabetically */
/* This isn't at all speed critical -- only runs once per page and */
/* there are never very many spot colors, so just search in a loop */
- byte *prev = " ";
+
+ /* If the device has tags, then that goes at the end, after all the
+ spot colors */
+
+ const char *prev = " ";
int prev_size = 1;
+ psd_device *pdev_psd = (psd_device*)dev;
+ bool has_tags = (pdev_psd->color_model == psd_DEVICE_CMYKT);
xc->num_channels += xc->n_extra_channels;
for (i=xc->base_num_channels; i < xc->num_channels; i++) {
int j;
- byte* curr = "\377";
+ const char *curr = "\377";
int curr_size = 1;
+ bool compare;
- for (j=xc->base_num_channels; j < xc->num_channels; j++) {
- const devn_separation_name *separation_name;
+ for (j=xc->base_num_channels; j < (xc->num_channels - has_tags); j++) {
+ devn_separation_name *separation_name;
separation_name = &(dev->devn_params.separations.names[j - xc->base_num_channels]);
- if (strncmp(separation_name->data, curr, min(curr_size, separation_name->size)) < 0) {
- if (strncmp(separation_name->data, prev, min(prev_size, separation_name->size)) > 0) {
+ compare = strncmp((const char*) separation_name->data, curr, min(curr_size, separation_name->size));
+ if (compare < 0 || (compare == 0 && separation_name->size < curr_size)) {
+ compare = strncmp((const char*) separation_name->data, prev, min(prev_size, separation_name->size));
+ if (compare > 0 || (compare == 0 && separation_name->size > prev_size)) {
xc->chnl_to_position[i] = j;
xc->chnl_to_orig_sep[i] = j;
- curr = separation_name->data;
+ curr = (const char*) separation_name->data;
curr_size = separation_name->size;
}
}
@@ -934,8 +1085,36 @@ get_sep_name(gx_devn_prn_device *pdev, int n)
return p;
}
+static inline void
+psd_write_src_spot_names(psd_write_ctx *xc, gx_devn_prn_device *pdev, int chan_idx, bool has_tags)
+{
+ int sep_num;
+ const devn_separation_name *separation_name;
+
+ for (; chan_idx < xc->num_channels; chan_idx++) {
+ sep_num = xc->chnl_to_orig_sep[chan_idx] - NUM_CMYK_COMPONENTS - has_tags;
+ separation_name = &(pdev->devn_params.separations.names[sep_num]);
+ psd_write_8(xc, (byte)separation_name->size);
+ psd_write(xc, separation_name->data, separation_name->size);
+ }
+}
+
+static inline void
+psd_write_std_extra_names(psd_write_ctx *xc, gx_devn_prn_device *pdev, int chan_idx)
+{
+ for (; chan_idx < xc->num_channels; chan_idx++) {
+ int len;
+ fixed_colorant_name n = pdev->devn_params.std_colorant_names[chan_idx];
+ if (n == NULL)
+ break;
+ len = strlen(n);
+ psd_write_8(xc, (byte)len);
+ psd_write(xc, (const byte*)n, len);
+ }
+}
+
int
-psd_write_header(psd_write_ctx *xc, gx_devn_prn_device *pdev)
+psd_write_header(psd_write_ctx* xc, gx_devn_prn_device* pdev)
{
int code = 0;
int num_channels = xc->num_channels;
@@ -944,8 +1123,14 @@ psd_write_header(psd_write_ctx *xc, gx_devn_prn_device *pdev)
int chan_names_len = 0;
int sep_num;
const devn_separation_name *separation_name;
+ cmm_dev_profile_t *profile_struct;
+ cmm_profile_t *dev_profile;
+ int profile_resource_size;
+ psd_device *pdev_psd = (psd_device*)pdev;
+ bool has_tags = (pdev_psd->color_model == psd_DEVICE_CMYKT);
+ int extra_std_colors = 0;
- psd_write(xc, (const byte *)"8BPS", 4); /* Signature */
+ psd_write(xc, (const byte*)"8BPS", 4); /* Signature */
psd_write_16(xc, 1); /* Version - Always equal to 1*/
/* Reserved 6 Bytes - Must be zero */
psd_write_32(xc, 0);
@@ -955,51 +1140,71 @@ psd_write_header(psd_write_ctx *xc, gx_devn_prn_device *pdev)
psd_write_32(xc, xc->width); /* Columns */
psd_write_16(xc, bpc); /* Depth - 1, 8 and 16 */
/* Modes: Bitmap=0, Grayscale=1, RGB=3, CMYK=4 MultiChannel=7 Lab=9 */
- psd_write_16(xc, (bits16) xc->base_num_channels); /* We use 1, 3 or 4. */
+ psd_write_16(xc, (bits16)xc->base_num_channels); /* We use 1, 3 or 4. */
- /* Color Mode Data */
- psd_write_32(xc, 0); /* No color mode data */
+ /* Color Mode Data. Only used for indexed and duotone */
+ psd_write_32(xc, 0);
- /* Image Resources */
+ /* Resources */
- /* Channel Names */
+ /* ICC profile */
+ code = dev_proc(pdev, get_profile)((gx_device*)pdev, &profile_struct);
+ if (code < 0) {
+ dev_profile = NULL;
+ profile_resource_size = 0;
+ } else {
+ dev_profile = profile_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE];
+
+ /* Resource has to be padded to even size */
+ profile_resource_size = dev_profile->buffer_size + dev_profile->buffer_size % 2;
+ }
+
+ /* Channel Names size computation -- this will get the "Tags" name */
for (chan_idx = NUM_CMYK_COMPONENTS; chan_idx < xc->num_channels; chan_idx++) {
fixed_colorant_name n = pdev->devn_params.std_colorant_names[chan_idx];
if (n == NULL)
break;
chan_names_len += strlen(n) + 1;
}
+ extra_std_colors = chan_idx - NUM_CMYK_COMPONENTS;
+
for (; chan_idx < xc->num_channels; chan_idx++) {
- sep_num = xc->chnl_to_orig_sep[chan_idx] - NUM_CMYK_COMPONENTS;
+ sep_num = xc->chnl_to_orig_sep[chan_idx] - NUM_CMYK_COMPONENTS - has_tags;
separation_name = &(pdev->devn_params.separations.names[sep_num]);
chan_names_len += (separation_name->size + 1);
}
+
+ /* Length of resource section */
psd_write_32(xc, 12 + (chan_names_len + (chan_names_len % 2))
+ (12 + (14 * (xc->num_channels - xc->base_num_channels)))
- + 28);
+ + (profile_resource_size ? (12 + profile_resource_size) : 0) + 28);
+
+ /* Channel names resource */
psd_write(xc, (const byte *)"8BIM", 4);
psd_write_16(xc, 1006); /* 0x03EE */
psd_write_16(xc, 0); /* PString */
psd_write_32(xc, chan_names_len + (chan_names_len % 2));
- for (chan_idx = NUM_CMYK_COMPONENTS; chan_idx < xc->num_channels; chan_idx++) {
- int len;
- fixed_colorant_name n = pdev->devn_params.std_colorant_names[chan_idx];
- if (n == NULL)
- break;
- len = strlen(n);
- psd_write_8(xc, (byte)len);
- psd_write(xc, (const byte *)n, len);
- }
- for (; chan_idx < xc->num_channels; chan_idx++) {
- sep_num = xc->chnl_to_orig_sep[chan_idx] - NUM_CMYK_COMPONENTS;
- separation_name = &(pdev->devn_params.separations.names[sep_num]);
- psd_write_8(xc, (byte) separation_name->size);
- psd_write(xc, separation_name->data, separation_name->size);
+
+ /* If it has tags, do the spots first (if there are any),
+ then the tags. We will need to rework this if we were
+ to add tags to psdcmykog or similar such device that
+ has pre-defined spots with the tags plane */
+ if (has_tags) {
+ chan_idx = NUM_CMYK_COMPONENTS + extra_std_colors;
+ psd_write_src_spot_names(xc, pdev, chan_idx, has_tags);
+ chan_idx = NUM_CMYK_COMPONENTS;
+ psd_write_std_extra_names(xc, pdev, chan_idx);
+
+ } else {
+ chan_idx = NUM_CMYK_COMPONENTS;
+ psd_write_std_extra_names(xc, pdev, chan_idx);
+ chan_idx = NUM_CMYK_COMPONENTS + extra_std_colors;
+ psd_write_src_spot_names(xc, pdev, chan_idx, has_tags);
}
if (chan_names_len % 2)
psd_write_8(xc, 0); /* pad */
- /* DisplayInfo - Colors for each spot channels */
+ /* DisplayInfo - Colors for each spot channels resource*/
psd_write(xc, (const byte *)"8BIM", 4);
psd_write_16(xc, 1007); /* 0x03EF */
psd_write_16(xc, 0); /* PString */
@@ -1044,7 +1249,7 @@ psd_write_header(psd_write_ctx *xc, gx_devn_prn_device *pdev)
psd_write_8(xc, 0); /* Padding - Always Zero */
}
- /* Image resolution */
+ /* Image resolution resource */
psd_write(xc, (const byte *)"8BIM", 4);
psd_write_16(xc, 1005); /* 0x03ED */
psd_write_16(xc, 0); /* PString */
@@ -1057,6 +1262,17 @@ psd_write_header(psd_write_ctx *xc, gx_devn_prn_device *pdev)
psd_write_16(xc, 1); /* height: 1 --> resolution is pixels per inch */
psd_write_16(xc, 1); /* height: 1 --> resolution is pixels per inch */
+ /* ICC Profile resource */
+ if (profile_resource_size) {
+ psd_write(xc, (const byte*)"8BIM", 4);
+ psd_write_16(xc, 1039); /* 0x040F */
+ psd_write_16(xc, 0); /* PString */
+ psd_write_32(xc, profile_resource_size);
+ psd_write(xc, dev_profile->buffer, dev_profile->buffer_size);
+ if (dev_profile->buffer_size % 2)
+ psd_write_8(xc, 0);
+ }
+
/* Layer and Mask information */
psd_write_32(xc, 0); /* No layer or mask information */