summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Vrhel <michael.vrhel@artifex.com>2010-06-15 17:24:45 +0000
committerMichael Vrhel <michael.vrhel@artifex.com>2010-06-15 17:24:45 +0000
commit37b58b80d018f877ead71c90462a804997bdb98f (patch)
tree6cb222f50cf39e4895997da0f65db9333cb98187
parent2c498847e1354f9c5c3b36003693d8ac4a431378 (diff)
Addition of code to use new icc color architecture in xps rendering. Tor to provide minor fixes to this, primarily to remove the ctx->icc object. There will be xps differences with this commit since icc profiles were previously ignored.
git-svn-id: http://svn.ghostscript.com/ghostscript/trunk@11379 a1074d23-0009-0410-80fe-cf8c14f379e6
-rw-r--r--xps/ghostxps.h21
-rw-r--r--xps/xpscolor.c86
-rw-r--r--xps/xpsgradient.c46
-rw-r--r--xps/xpshdp.c4
-rw-r--r--xps/xpsimage.c195
-rw-r--r--xps/xpsjpeg.c30
-rw-r--r--xps/xpspage.c8
-rw-r--r--xps/xpspng.c17
-rw-r--r--xps/xpstiff.c43
-rw-r--r--xps/xpstop.c13
10 files changed, 382 insertions, 81 deletions
diff --git a/xps/ghostxps.h b/xps/ghostxps.h
index d95a9bccb..256b1ac1f 100644
--- a/xps/ghostxps.h
+++ b/xps/ghostxps.h
@@ -64,6 +64,8 @@
#include "gzpath.h"
#include "gsicc_manage.h"
+#include "gscms.h"
+#include "gsicc_cache.h"
#include "zlib.h"
@@ -196,6 +198,7 @@ struct xps_context_s
gs_color_space *srgb;
gs_color_space *scrgb;
gs_color_space *cmyk;
+ gs_color_space *icc;
char *directory;
FILE *file;
@@ -249,7 +252,8 @@ xps_part_t *xps_read_part(xps_context_t *ctx, char *partname);
/* type for the information derived directly from the raster file format */
-enum { XPS_GRAY, XPS_GRAY_A, XPS_RGB, XPS_RGB_A, XPS_CMYK, XPS_CMYK_A };
+enum { XPS_GRAY, XPS_GRAY_A, XPS_RGB, XPS_RGB_A, XPS_CMYK, XPS_CMYK_A,
+ XPS_ICC, XPS_ICC_A, XPS_NOTICC };
struct xps_image_s
{
@@ -263,12 +267,18 @@ struct xps_image_s
int yres;
byte *samples;
byte *alpha; /* isolated alpha plane */
+ bool embeddedprofile;
};
-int xps_decode_jpeg(gs_memory_t *mem, byte *rbuf, int rlen, xps_image_t *image);
-int xps_decode_png(gs_memory_t *mem, byte *rbuf, int rlen, xps_image_t *image);
-int xps_decode_tiff(gs_memory_t *mem, byte *rbuf, int rlen, xps_image_t *image);
-int xps_decode_hdphoto(gs_memory_t *mem, byte *buf, int len, xps_image_t *image);
+/* Probably need to clean this up to make different proc types */
+int xps_decode_jpeg(gs_memory_t *mem, byte *rbuf, int rlen, xps_image_t *image,
+ unsigned char **profile, int *profile_size);
+int xps_decode_png(gs_memory_t *mem, byte *rbuf, int rlen, xps_image_t *image,
+ unsigned char **profile, int *profile_size);
+int xps_decode_tiff(gs_memory_t *mem, byte *rbuf, int rlen, xps_image_t *image,
+ unsigned char **profile, int *profile_size);
+int xps_decode_hdphoto(gs_memory_t *mem, byte *buf, int len, xps_image_t *image,
+ unsigned char **profile, int *profile_size);
int xps_hasalpha_png(gs_memory_t *mem, byte *rbuf, int rlen);
int xps_hasalpha_tiff(gs_memory_t *mem, byte *rbuf, int rlen);
int xps_hasalpha_hdphoto(gs_memory_t *mem, byte *buf, int len);
@@ -333,6 +343,7 @@ void xps_debug_path(xps_context_t *ctx);
int xps_parse_color(xps_context_t *ctx, char *base_uri, char *hexstring, gs_color_space **csp, float *samples);
int xps_set_color(xps_context_t *ctx, gs_color_space *colorspace, float *samples);
int xps_parse_icc_profile(xps_context_t *ctx, gs_color_space **csp, byte *data, int length, int ncomp);
+int xps_set_icc(xps_context_t *ctx, char *base_uri, char *profile, gs_color_space **csp);
/*
* XML document model
diff --git a/xps/xpscolor.c b/xps/xpscolor.c
index d4ffbc3af..5c4451841 100644
--- a/xps/xpscolor.c
+++ b/xps/xpscolor.c
@@ -60,16 +60,15 @@ static int count_commas(char *s)
}
return n;
}
-
+
int
xps_parse_color(xps_context_t *ctx, char *base_uri, char *string, gs_color_space **csp, float *samples)
{
- xps_part_t *part;
- char *profile, *p;
+ char *p;
int i, n;
-
- char partname[1024];
char buf[1024];
+ int code;
+ char *profile;
samples[0] = 1.0;
samples[1] = 0.0;
@@ -145,34 +144,14 @@ xps_parse_color(xps_context_t *ctx, char *base_uri, char *string, gs_color_space
}
/* Default fallbacks if the ICC stuff fails */
-
if (n == 2) /* alpha + tint */
*csp = ctx->gray;
- if (n == 5) /* alpha + CMYK */
+ if (n >= 5) /* alpha + CMYK */
*csp = ctx->cmyk;
-#if 0 /* disable ICC profiles until gsicc_manager is available */
- /* Find ICC colorspace part */
- xps_absolute_path(partname, base_uri, profile, sizeof partname);
-
- colorspace = xps_hash_lookup(ctx->colorspace_table, partname);
- if (!colorspace)
- {
- part = xps_read_part(ctx, partname);
- if (!part)
- return gs_throw1(-1, "cannot find icc profile part '%s'", partname);
- code = xps_parse_icc_profile(ctx, &colorspace, part, n - 1);
- if (code < 0)
- return gs_rethrow1(code, "cannot parse icc profile part '%s'", partname);
- xps_hash_insert(ctx->colorspace_table, xps_strdup(ctx, partname), colorspace);
- xps_free_part(ctx, part);
- }
-
- *csp = colorspace;
-#endif
-
- return 0;
+ code = xps_set_icc(ctx, base_uri, profile, csp);
+ return code;
}
else
@@ -182,6 +161,57 @@ xps_parse_color(xps_context_t *ctx, char *base_uri, char *string, gs_color_space
}
int
+xps_set_icc(xps_context_t *ctx, char *base_uri, char *profile, gs_color_space **csp)
+{
+ cmm_profile_t *iccprofile;
+ xps_part_t *part;
+ char partname[1024];
+
+ /* Find ICC colorspace part */
+ xps_absolute_path(partname, base_uri, profile, sizeof partname);
+
+ /* See if we cached the profile */
+ iccprofile = (cmm_profile_t*) xps_hash_lookup(ctx->colorspace_table, partname);
+ if (!iccprofile)
+ {
+ part = xps_read_part(ctx, partname);
+ /* Problem finding profile. Don't fail, just use default */
+ if (!part)
+ return 0;
+
+ /* Create the profile */
+ iccprofile = gsicc_profile_new(NULL, ctx->memory, NULL, 0);
+ /* Set buffer */
+ iccprofile->buffer = part->data;
+ iccprofile->buffer_size = part->size;
+ /* Parse */
+ gsicc_init_profile_info(iccprofile);
+ /* Problem with profile. Don't fail, just use the default */
+ if (iccprofile->profile_handle == NULL)
+ {
+ gsicc_profile_reference(iccprofile, -1);
+ return 0;
+ }
+
+ /* Done with the buffer */
+ xps_free_part(ctx, part);
+ iccprofile->buffer = NULL;
+ iccprofile->buffer_size = 0;
+
+ /* Add profile to xps color cache. It appears never to remove
+ these except at the end of processing */
+ xps_hash_insert(ctx, ctx->colorspace_table, xps_strdup(ctx, partname),
+ (void*) iccprofile);
+ }
+
+ /* Associate icc color space with the profile */
+ ctx->icc->cmm_icc_profile_data = iccprofile;
+ *csp = ctx->icc;
+
+ return 0;
+}
+
+int
xps_parse_solid_color_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *node)
{
char *opacity_att;
diff --git a/xps/xpsgradient.c b/xps/xpsgradient.c
index a51c65a68..c333decef 100644
--- a/xps/xpsgradient.c
+++ b/xps/xpsgradient.c
@@ -32,7 +32,11 @@ xps_parse_gradient_stops(xps_context_t *ctx, char *base_uri, xps_item_t *node,
int count = 0;
gs_color_space *colorspace;
float sample[32], f;
+ unsigned short sample_in[8], sample_out[8]; /* XPS allows up to 8 bands */
int i, done;
+ gsicc_link_t *icclink = NULL;
+ gsicc_rendering_param_t rendering_params;
+ int num_colors;
while (node && count < maxcount)
{
@@ -46,17 +50,49 @@ xps_parse_gradient_stops(xps_context_t *ctx, char *base_uri, xps_item_t *node,
xps_parse_color(ctx, base_uri, color, &colorspace, sample);
- /* TODO: Convert colors to sRGB using icc_work branch */
+ /* Set the rendering parameters */
+ rendering_params.black_point_comp = BP_ON;
+ rendering_params.object_type = GS_PATH_TAG;
+ rendering_params.rendering_intent = gsPERCEPTUAL;
+
+ /* Get link to map from source to sRGB */
+ icclink = gsicc_get_link((gs_imager_state*) ctx->pgs, colorspace,
+ ctx->srgb, &rendering_params,
+ ctx->memory, false);
+
+ if (icclink != NULL && !icclink->is_identity)
+ {
+ /* Transform the color */
+ num_colors = gsicc_getsrc_channel_count(colorspace->cmm_icc_profile_data);
+ for (i = 0; i < num_colors; i++)
+ {
+ sample_in[i] = sample[i+1]*65535;
+ }
+ gscms_transform_color(icclink, sample_in, sample_out, 2, NULL);
+
+ colors[count * 4 + 0] = sample[0]; /* Alpha */
+ colors[count * 4 + 1] = (float) sample_out[0] / 65535.0; /* sRGB */
+ colors[count * 4 + 2] = (float) sample_out[1] / 65535.0;
+ colors[count * 4 + 3] = (float) sample_out[2] / 65535.0;
+
+ }
+ else
+ {
+ colors[count * 4 + 0] = sample[0];
+ colors[count * 4 + 1] = sample[1];
+ colors[count * 4 + 2] = sample[2];
+ colors[count * 4 + 3] = sample[3];
+ }
- colors[count * 4 + 0] = sample[0];
- colors[count * 4 + 1] = sample[1];
- colors[count * 4 + 2] = sample[2];
- colors[count * 4 + 3] = sample[3];
count ++;
}
}
+ if (icclink != NULL)
+ gsicc_release_link(icclink);
+ icclink = NULL;
node = xps_next(node);
+
}
if (count == maxcount)
diff --git a/xps/xpshdp.c b/xps/xpshdp.c
index a83ac7833..e637a8292 100644
--- a/xps/xpshdp.c
+++ b/xps/xpshdp.c
@@ -18,8 +18,10 @@
/* HD-Photo decoder should go here. */
int
-xps_decode_hdphoto(gs_memory_t *mem, byte *buf, int len, xps_image_t *image)
+xps_decode_hdphoto(gs_memory_t *mem, byte *buf, int len, xps_image_t *image,
+ unsigned char **profile, int *profile_size)
{
+ *profile = NULL;
return gs_throw(-1, "HD-Photo codec is not available");
}
diff --git a/xps/xpsimage.c b/xps/xpsimage.c
index 08a5d63fb..1f0ae5fe1 100644
--- a/xps/xpsimage.c
+++ b/xps/xpsimage.c
@@ -33,7 +33,8 @@ xps_isolate_alpha_channel_8(xps_context_t *ctx, xps_image_t *image)
if ((image->colorspace != XPS_GRAY_A) &&
(image->colorspace != XPS_RGB_A) &&
- (image->colorspace != XPS_CMYK_A))
+ (image->colorspace != XPS_CMYK_A) &&
+ (image->colorspace != XPS_ICC_A))
return 0;
image->alpha = xps_alloc(ctx, image->width * image->height);
@@ -59,6 +60,8 @@ xps_isolate_alpha_channel_8(xps_context_t *ctx, xps_image_t *image)
image->colorspace = XPS_RGB;
if (image->colorspace == XPS_CMYK_A)
image->colorspace = XPS_CMYK;
+ if (image->colorspace == XPS_ICC_A)
+ image->colorspace = XPS_ICC;
image->comps --;
image->stride = image->width * image->comps;
@@ -75,7 +78,8 @@ xps_isolate_alpha_channel_16(xps_context_t *ctx, xps_image_t *image)
if ((image->colorspace != XPS_GRAY_A) &&
(image->colorspace != XPS_RGB_A) &&
- (image->colorspace != XPS_CMYK_A))
+ (image->colorspace != XPS_CMYK_A) &&
+ (image->colorspace != XPS_ICC_A))
return 0;
image->alpha = xps_alloc(ctx, image->width * image->height * 2);
@@ -101,6 +105,8 @@ xps_isolate_alpha_channel_16(xps_context_t *ctx, xps_image_t *image)
image->colorspace = XPS_RGB;
if (image->colorspace == XPS_CMYK_A)
image->colorspace = XPS_CMYK;
+ if (image->colorspace == XPS_ICC_A)
+ image->colorspace = XPS_ICC;
image->comps --;
image->stride = image->width * image->comps * 2;
@@ -137,13 +143,18 @@ xps_image_has_alpha(xps_context_t *ctx, xps_part_t *part)
return code;
}
-
static int
-xps_decode_image(xps_context_t *ctx, xps_part_t *part, xps_image_t *image)
+xps_decode_image(xps_context_t *ctx, char *profilename, int profile_comp,
+ xps_part_t *imagepart, xps_image_t *image)
{
- byte *buf = (byte*)part->data;
- int len = part->size;
+ byte *buf = (byte*)imagepart->data;
+ int len = imagepart->size;
int error;
+ int iccinfo = image->colorspace; /* So that we know if external profile was valid */
+ unsigned char *embedded_profile;
+ int profile_size;
+ cmm_profile_t *iccprofile;
+ bool has_alpha;
if (len < 2)
error = gs_throw(-1, "unknown image file format");
@@ -153,24 +164,107 @@ xps_decode_image(xps_context_t *ctx, xps_part_t *part, xps_image_t *image)
image->alpha = NULL;
if (buf[0] == 0xff && buf[1] == 0xd8)
- error = xps_decode_jpeg(ctx->memory, buf, len, image);
+ error = xps_decode_jpeg(ctx->memory, buf, len, image,
+ &embedded_profile, &profile_size);
else if (memcmp(buf, "\211PNG\r\n\032\n", 8) == 0)
- error = xps_decode_png(ctx->memory, buf, len, image);
+ error = xps_decode_png(ctx->memory, buf, len, image,
+ &embedded_profile, &profile_size);
else if (memcmp(buf, "II", 2) == 0 && buf[2] == 0xBC)
- error = xps_decode_hdphoto(ctx->memory, buf, len, image);
+ error = xps_decode_hdphoto(ctx->memory, buf, len, image,
+ &embedded_profile, &profile_size);
else if (memcmp(buf, "MM", 2) == 0)
- error = xps_decode_tiff(ctx->memory, buf, len, image);
+ error = xps_decode_tiff(ctx->memory, buf, len, image,
+ &embedded_profile, &profile_size);
else if (memcmp(buf, "II", 2) == 0)
- error = xps_decode_tiff(ctx->memory, buf, len, image);
+ error = xps_decode_tiff(ctx->memory, buf, len, image,
+ &embedded_profile, &profile_size);
else
error = gs_throw(-1, "unknown image file format");
if (error)
return gs_rethrow(error, "could not decode image");
- if (image->colorspace == XPS_GRAY_A ||
- image->colorspace == XPS_RGB_A ||
- image->colorspace == XPS_CMYK_A)
+ has_alpha = (image->colorspace == XPS_GRAY_A ||
+ image->colorspace == XPS_RGB_A ||
+ image->colorspace == XPS_CMYK_A);
+
+ /* Make sure profile matches data type */
+ if (iccinfo == XPS_ICC)
+ {
+ if (profile_comp == image->comps)
+ {
+ /* Profile is OK for this image. Change color space type. */
+ if (has_alpha)
+ {
+ image->colorspace = XPS_ICC_A;
+ }
+ else
+ {
+ image->colorspace = XPS_ICC;
+ }
+ }
+ }
+
+ /* See if we need to use the embedded profile. Only used if we
+ have one and a valid external profile was not specified */
+ image->embeddedprofile = false;
+ if (image->colorspace != XPS_ICC_A && image->colorspace != XPS_ICC &&
+ embedded_profile != NULL)
+ {
+ /* See if we can set up to use the embedded profile. Note
+ these profiles are NOT added to the xps color cache.
+ As such, they must be destroyed when the image brush ends.
+ Hence we need to make a note that we are using an embedded
+ profile. */
+
+ /* Create the profile */
+ iccprofile = gsicc_profile_new(NULL, ctx->memory, NULL, 0);
+ /* Set buffer */
+ iccprofile->buffer = embedded_profile;
+ iccprofile->buffer_size = profile_size;
+ /* Parse */
+ gsicc_init_profile_info(iccprofile);
+
+ /* Free up the buffer */
+ gs_free_object(ctx->memory, embedded_profile, "Embedded Profile");
+ iccprofile->buffer = NULL;
+ iccprofile->buffer_size = 0;
+
+ if (iccprofile->profile_handle == NULL)
+ {
+ /* Problem with profile. Just ignore it */
+ gsicc_profile_reference(iccprofile, -1);
+ }
+ else
+ {
+ /* Check the profile is OK for channel data count.
+ Need to be careful here since alpha is put into
+ comps */
+ if ((image->comps - has_alpha) == gsicc_getsrc_channel_count(iccprofile))
+ {
+ /* Use the embedded profile */
+ image->embeddedprofile = true;
+ ctx->icc->cmm_icc_profile_data = iccprofile;
+ if (has_alpha)
+ {
+ image->colorspace = XPS_ICC_A;
+ }
+ else
+ {
+ image->colorspace = XPS_ICC;
+ }
+ }
+ else
+ {
+ /* Problem with profile. Just ignore it */
+ gsicc_profile_reference(iccprofile, -1);
+ }
+
+ }
+ }
+
+ /* XPS_ICC_A potentially not set when has_alpha evaluated */
+ if (has_alpha || image->colorspace == XPS_ICC_A )
{
if (image->bits < 8)
dprintf1("cannot isolate alpha channel in %d bpc images\n", image->bits);
@@ -209,6 +303,7 @@ xps_paint_image_brush_imp(xps_context_t *ctx, xps_image_t *image, int alpha)
case XPS_GRAY: colorspace = ctx->gray; break;
case XPS_RGB: colorspace = ctx->srgb; break;
case XPS_CMYK: colorspace = ctx->cmyk; break;
+ case XPS_ICC: colorspace = ctx->icc; break;
default:
return gs_throw(-1, "cannot draw images with interleaved alpha");
}
@@ -290,14 +385,14 @@ xps_paint_image_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict,
}
static int
-xps_find_image_brush_source_part(xps_context_t *ctx, char *base_uri, xps_item_t *root, xps_part_t **partp)
+xps_find_image_brush_source_part(xps_context_t *ctx, char *base_uri, xps_item_t *root,
+ xps_part_t **imagepartp, char **profile_name)
{
- xps_part_t *part;
+ xps_part_t *imagepart, *iccpart;
char *image_source_att;
char buf[1024];
char partname[1024];
char *image_name;
- char *profile_name;
char *p;
image_source_att = xps_att(root, "ImageSource");
@@ -308,7 +403,7 @@ xps_find_image_brush_source_part(xps_context_t *ctx, char *base_uri, xps_item_t
if (strstr(image_source_att, "{ColorConvertedBitmap") == image_source_att)
{
image_name = NULL;
- profile_name = NULL;
+ *profile_name = NULL;
strcpy(buf, image_source_att);
p = strchr(buf, ' ');
@@ -319,7 +414,7 @@ xps_find_image_brush_source_part(xps_context_t *ctx, char *base_uri, xps_item_t
if (p)
{
*p = 0;
- profile_name = p + 1;
+ *profile_name = p + 1;
p = strchr(p + 1, '}');
if (p)
*p = 0;
@@ -329,33 +424,33 @@ xps_find_image_brush_source_part(xps_context_t *ctx, char *base_uri, xps_item_t
else
{
image_name = image_source_att;
- profile_name = NULL;
+ *profile_name = NULL;
}
if (!image_name)
return gs_throw1(-1, "cannot parse image resource name '%s'", image_source_att);
- if (profile_name)
- dprintf2("warning: ignoring color profile '%s' associated with image '%s'\n",
- profile_name, image_name);
-
xps_absolute_path(partname, base_uri, image_name, sizeof partname);
- part = xps_read_part(ctx, partname);
- if (!part)
+ imagepart = xps_read_part(ctx, partname);
+ if (!imagepart)
return gs_throw1(-1, "cannot find image resource part '%s'", partname);
- *partp = part;
+ *imagepartp = imagepart;
+
return 0;
}
int
xps_parse_image_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *root)
{
- xps_part_t *part;
+ xps_part_t *imagepart;
xps_image_t *image;
int code;
+ char *profilename;
+ gs_color_space *colorspace;
+ int profile_comp = 0;
- code = xps_find_image_brush_source_part(ctx, base_uri, root, &part);
+ code = xps_find_image_brush_source_part(ctx, base_uri, root, &imagepart, &profilename);
if (code < 0)
return gs_rethrow(code, "cannot find image source");
@@ -363,15 +458,43 @@ xps_parse_image_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict,
if (!image)
return gs_throw(-1, "out of memory: image struct");
- code = xps_decode_image(ctx, part, image);
+ /* If we have an ICC profile, go ahead and set the color space now.
+ Make sure the profile is valid etc. If we find one in the image
+ then we will use that if one is not externally defined. If it is
+ we get back our ICC color space object. However, we also need
+ to see if the profile count matches the number of channels in the image.
+ If it does not, then we do not use the profile. Also we may need
+ to use the embedded profile */
+
+ image->colorspace = XPS_NOTICC;
+ if (profilename != NULL)
+ {
+ colorspace = NULL;
+ xps_set_icc(ctx, base_uri, profilename, &colorspace);
+ if (colorspace != NULL)
+ {
+ /* Now, see what the channel count is */
+ profile_comp =
+ gsicc_getsrc_channel_count(colorspace->cmm_icc_profile_data);
+ image->colorspace = XPS_ICC;
+ }
+ }
+
+ code = xps_decode_image(ctx, profilename, profile_comp, imagepart, image);
if (code < 0)
return gs_rethrow(-1, "cannot decode image resource");
xps_parse_tiling_brush(ctx, base_uri, dict, root, xps_paint_image_brush, image);
+ /* If we used an embedded profile. then release as these are not cached */
+ if (image->embeddedprofile)
+ {
+ gsicc_profile_reference(ctx->icc->cmm_icc_profile_data, -1);
+ }
+
xps_free_image(ctx, image);
- xps_free_part(ctx, part);
+ xps_free_part(ctx, imagepart);
return 0;
}
@@ -379,25 +502,27 @@ xps_parse_image_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict,
int
xps_image_brush_has_transparency(xps_context_t *ctx, char *base_uri, xps_item_t *root)
{
- xps_part_t *part;
- xps_image_t *image;
+ xps_part_t *imagepart, *iccpart;
int code;
int has_alpha;
+ char *profilename;
- code = xps_find_image_brush_source_part(ctx, base_uri, root, &part);
+ code = xps_find_image_brush_source_part(ctx, base_uri, root, &imagepart, &profilename);
if (code < 0)
{
gs_catch(code, "cannot find image source");
return 0;
}
- has_alpha = xps_image_has_alpha(ctx, part);
+ has_alpha = xps_image_has_alpha(ctx, imagepart);
if (has_alpha < 0)
{
gs_catch(-1, "cannot decode image resource");
return 0;
}
+ xps_free_part(ctx, imagepart);
+
return has_alpha;
}
diff --git a/xps/xpsjpeg.c b/xps/xpsjpeg.c
index e86f037d8..8a59d1e2f 100644
--- a/xps/xpsjpeg.c
+++ b/xps/xpsjpeg.c
@@ -30,7 +30,8 @@ xps_report_error(stream_state * st, const char *str)
}
int
-xps_decode_jpeg(gs_memory_t *mem, byte *rbuf, int rlen, xps_image_t *image)
+xps_decode_jpeg(gs_memory_t *mem, byte *rbuf, int rlen, xps_image_t *image,
+ unsigned char **profile, int *profile_size)
{
jpeg_decompress_data jddp;
stream_DCT_state state;
@@ -39,6 +40,9 @@ xps_decode_jpeg(gs_memory_t *mem, byte *rbuf, int rlen, xps_image_t *image)
int code;
int wlen;
byte *wbuf;
+ jpeg_saved_marker_ptr curr_marker;
+
+ *profile = NULL;
s_init_state((stream_state*)&state, &s_DCTD_template, mem);
state.report_error = xps_report_error;
@@ -64,10 +68,34 @@ xps_decode_jpeg(gs_memory_t *mem, byte *rbuf, int rlen, xps_image_t *image)
wp.ptr = 0;
wp.limit = 0;
+ /* Set up to save the ICC marker APP2. According to the spec
+ we should be getting APP1 APP2 and APP13. Library gets APP0 and APP14 */
+ jpeg_save_markers(&(jddp.dinfo), 0xe2, 0xFFFF);
+
code = s_DCTD_template.process((stream_state*)&state, &rp, &wp, true);
if (code != 1)
return gs_throw(-1, "premature EOF or error in jpeg");
+ /* Check if we had an ICC profile */
+ curr_marker = jddp.dinfo.marker_list;
+ while (curr_marker != NULL)
+ {
+ if (curr_marker->marker == 0xe2)
+ {
+ /* Found ICC profile. Create a buffer and copy over now. Strip
+ JPEG APP2 14 byte header */
+ *profile = (unsigned char*) gs_alloc_bytes(mem, curr_marker->data_length - 14, "JPEG ICC Profile");
+ if (*profile != NULL)
+ {
+ /* If we can't create it, just ignore */
+ memcpy(*profile, &(curr_marker->data[14]), (curr_marker->data_length) - 14);
+ *profile_size = curr_marker->data_length - 14;
+ }
+ break;
+ }
+ curr_marker = curr_marker->next;
+ }
+
image->width = jddp.dinfo.output_width;
image->height = jddp.dinfo.output_height;
image->comps = jddp.dinfo.output_components;
diff --git a/xps/xpspage.c b/xps/xpspage.c
index 2fbeec11c..50879c82c 100644
--- a/xps/xpspage.c
+++ b/xps/xpspage.c
@@ -221,6 +221,14 @@ xps_parse_fixed_page(xps_context_t *ctx, xps_part_t *part)
return gs_rethrow(code, "cannot install transparency device");
}
+ /* Initialize the default profiles in the ctx to what is in the manager */
+ ctx->gray->cmm_icc_profile_data = ctx->pgs->icc_manager->default_gray;
+ ctx->srgb->cmm_icc_profile_data = ctx->pgs->icc_manager->default_rgb;
+ /* scrgb really needs to be a bit different. Unless we are handling nonlinearity
+ before conversion from float . ToDo. */
+ ctx->scrgb->cmm_icc_profile_data = ctx->pgs->icc_manager->default_rgb;
+ ctx->cmyk->cmm_icc_profile_data = ctx->pgs->icc_manager->default_cmyk;
+
/* Draw contents */
for (node = xps_down(root); node; node = xps_next(node))
diff --git a/xps/xpspng.c b/xps/xpspng.c
index 1d99eab14..68616f931 100644
--- a/xps/xpspng.c
+++ b/xps/xpspng.c
@@ -133,7 +133,8 @@ xps_hasalpha_png(gs_memory_t *mem, byte *rbuf, int rlen)
}
int
-xps_decode_png(gs_memory_t *mem, byte *rbuf, int rlen, xps_image_t *image)
+xps_decode_png(gs_memory_t *mem, byte *rbuf, int rlen, xps_image_t *image,
+ unsigned char **profile, int *profile_size)
{
png_structp png;
png_infop info;
@@ -149,6 +150,8 @@ xps_decode_png(gs_memory_t *mem, byte *rbuf, int rlen, xps_image_t *image)
io.ptr = rbuf;
io.lim = rbuf + rlen;
+ *profile = NULL;
+
png = png_create_read_struct_2(PNG_LIBPNG_VER_STRING,
NULL, NULL, NULL,
mem, xps_png_malloc, xps_png_free);
@@ -205,6 +208,18 @@ xps_decode_png(gs_memory_t *mem, byte *rbuf, int rlen, xps_image_t *image)
image->comps = png_get_channels(png, info);
image->bits = png_get_bit_depth(png, info);
+ /* See if we have an icc profile */
+ if (info->iccp_profile != NULL)
+ {
+ *profile = (unsigned char*) gs_alloc_bytes(mem, info->iccp_proflen, "PNG ICC Profile");
+ if (*profile != NULL)
+ {
+ /* If we can't create it, just ignore */
+ memcpy(*profile, info->iccp_profile, info->iccp_proflen);
+ *profile_size = info->iccp_proflen;
+ }
+ }
+
switch (png_get_color_type(png, info))
{
case PNG_COLOR_TYPE_GRAY:
diff --git a/xps/xpstiff.c b/xps/xpstiff.c
index 88a794a35..6dcb8d961 100644
--- a/xps/xpstiff.c
+++ b/xps/xpstiff.c
@@ -76,6 +76,9 @@ struct xps_tiff_s
byte *jpegtables; /* point into "file" buffer */
unsigned jpegtableslen;
+
+ byte *iccprofile;
+ int profile_size;
};
enum
@@ -115,6 +118,7 @@ enum
#define ExtraSamples 338
#define JPEGTables 347
#define YCbCrSubSampling 520
+#define ICCProfile 34675
static const byte bitrev[256] =
{
@@ -644,6 +648,7 @@ xps_decode_tiff_strips(gs_memory_t *mem, xps_tiff_t *tiff, xps_image_t *image)
case 3:
image->xres = tiff->xresolution * 2.54 + 0.5;
image->yres = tiff->yresolution * 2.54 + 0.5;
+
break;
default:
image->xres = 96;
@@ -651,6 +656,14 @@ xps_decode_tiff_strips(gs_memory_t *mem, xps_tiff_t *tiff, xps_image_t *image)
break;
}
+ /* Note xres and yres could be 0 even if unit was set. If so
+ default to 96dpi */
+ if (image->xres == 0 || image->yres == 0)
+ {
+ image->xres = 96;
+ image->yres = 96;
+ }
+
image->samples = gs_alloc_bytes(mem, image->stride * image->height, "samples");
if (!image->samples)
return gs_throw(-1, "could not allocate image samples");
@@ -769,6 +782,20 @@ xps_decode_tiff_strips(gs_memory_t *mem, xps_tiff_t *tiff, xps_image_t *image)
}
static void
+xps_read_tiff_bytes(unsigned char *p, xps_tiff_t *tiff, unsigned ofs, unsigned n)
+{
+ tiff->rp = tiff->bp + ofs;
+ if (tiff->rp > tiff->ep)
+ tiff->rp = tiff->bp;
+
+ while (n--)
+ {
+ *p++ = readbyte(tiff);
+ }
+}
+
+
+static void
xps_read_tiff_tag_value(unsigned *p, xps_tiff_t *tiff, unsigned type, unsigned ofs, unsigned n)
{
tiff->rp = tiff->bp + ofs;
@@ -869,6 +896,15 @@ xps_read_tiff_tag(gs_memory_t *mem, xps_tiff_t *tiff, unsigned offset)
case ExtraSamples:
xps_read_tiff_tag_value(&tiff->extrasamples, tiff, type, value, 1);
break;
+ case ICCProfile:
+ tiff->iccprofile = (unsigned char*) gs_alloc_bytes(mem, count , "TIFF ICC Profile");
+ if (!tiff->iccprofile)
+ return gs_throw(-1, "could not allocate embedded icc profile");
+ /* ICC profile data type is set to UNDEFINED. TBYTE reading not correct
+ in xps_read_tiff_tag_value */
+ xps_read_tiff_bytes((unsigned*) tiff->iccprofile, tiff, value, count);
+ tiff->profile_size = count;
+ break;
case JPEGTables:
tiff->jpegtables = tiff->bp + value;
@@ -925,7 +961,8 @@ xps_swap_byte_order(byte *buf, int n)
}
int
-xps_decode_tiff(gs_memory_t *mem, byte *buf, int len, xps_image_t *image)
+xps_decode_tiff(gs_memory_t *mem, byte *buf, int len, xps_image_t *image,
+ unsigned char **profile, int *profile_size)
{
int error;
xps_tiff_t tiffst;
@@ -937,6 +974,7 @@ xps_decode_tiff(gs_memory_t *mem, byte *buf, int len, xps_image_t *image)
unsigned i;
memset(tiff, 0, sizeof(xps_tiff_t));
+ *profile = NULL;
tiff->bp = buf;
tiff->rp = buf;
@@ -1011,6 +1049,9 @@ xps_decode_tiff(gs_memory_t *mem, byte *buf, int len, xps_image_t *image)
if (tiff->stripoffsets) gs_free_object(mem, tiff->stripoffsets, "StripOffsets");
if (tiff->stripbytecounts) gs_free_object(mem, tiff->stripbytecounts, "StripByteCounts");
+ *profile = tiff->iccprofile;
+ *profile_size = tiff->profile_size;
+
/*
* Byte swap 16-bit images to big endian if necessary.
*/
diff --git a/xps/xpstop.c b/xps/xpstop.c
index 6a2894223..a213c47c4 100644
--- a/xps/xpstop.c
+++ b/xps/xpstop.c
@@ -90,6 +90,7 @@ xps_imp_allocate_interp_instance(pl_interp_instance_t **ppinstance,
xps_interp_instance_t *instance;
xps_context_t *ctx;
gs_state *pgs;
+ int code;
instance = (xps_interp_instance_t *) gs_alloc_bytes(pmem,
sizeof(xps_interp_instance_t), "xps_imp_allocate_interp_instance");
@@ -122,11 +123,15 @@ xps_imp_allocate_interp_instance(pl_interp_instance_t **ppinstance,
ctx->zip_count = 0;
ctx->zip_table = NULL;
- /* TODO: load some builtin ICC profiles here */
- ctx->gray = gs_cspace_new_DeviceGray(ctx->memory); /* profile for gray images */
- ctx->cmyk = gs_cspace_new_DeviceCMYK(ctx->memory); /* profile for cmyk images */
+ /* Gray, RGB and CMYK profiles set when color spaces installed in graphics lib */
+ ctx->gray = gs_cspace_new_DeviceGray(ctx->memory);
+ ctx->cmyk = gs_cspace_new_DeviceCMYK(ctx->memory);
ctx->srgb = gs_cspace_new_DeviceRGB(ctx->memory);
- ctx->scrgb = gs_cspace_new_DeviceRGB(ctx->memory);
+ ctx->scrgb = gs_cspace_new_DeviceRGB(ctx->memory); /* This needs a different profile */
+ code = gs_cspace_build_ICC(&(ctx->icc), NULL, ctx->memory); /* For profile color spaces */
+ if (code < 0)
+ return gs_error_VMerror;
+
instance->pre_page_action = 0;
instance->pre_page_closure = 0;