summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter TB Brett <peter.brett@livecode.com>2016-09-09 22:35:55 +0930
committerAdrian Johnson <ajohnson@redneon.com>2016-09-09 22:35:55 +0930
commitb207a932a2d3740984319dffd58a0791580597cd (patch)
tree31ea9b66f924a671d7a4b52809493ca2a8cb09b6
parenta69e5af9cd62d1e8d9f503a9d74338a49e31f9cd (diff)
Correctly decode Adobe CMYK JPEGs in PDF export
Adobe PhotoShop generates CMYK JPEG files with inverted CMYK. When a JPEG file with this format is included in a PDF file, a `/Decode` array must be included to convert to "normal" CMYK. These JPEG files can be detected via the presence of the APP14 "Adobe" marker. However, PDF viewers are not required to detect and handle this private marker, so it must be detected and handled (by adding a `/Decode`) by the PDF generator. Signed-Off-By: Peter TB Brett <peter.brett@livecode.com>
-rw-r--r--src/cairo-image-info-private.h1
-rw-r--r--src/cairo-image-info.c21
-rw-r--r--src/cairo-pdf-surface.c2
3 files changed, 24 insertions, 0 deletions
diff --git a/src/cairo-image-info-private.h b/src/cairo-image-info-private.h
index e64928e40..99cbbcc02 100644
--- a/src/cairo-image-info-private.h
+++ b/src/cairo-image-info-private.h
@@ -43,6 +43,7 @@ typedef struct _cairo_image_info {
int height;
int num_components;
int bits_per_component;
+ int is_adobe_jpeg;
} cairo_image_info_t;
cairo_private cairo_int_status_t
diff --git a/src/cairo-image-info.c b/src/cairo-image-info.c
index 26e7ae5af..2ecce954a 100644
--- a/src/cairo-image-info.c
+++ b/src/cairo-image-info.c
@@ -67,6 +67,9 @@
#define SOF14 0xce
#define SOF15 0xcf
+/* Start of tag markers */
+#define APP14 0xee /* Adobe */
+
static const unsigned char *
_jpeg_skip_segment (const unsigned char *p)
{
@@ -94,6 +97,8 @@ _cairo_image_info_get_jpeg_info (cairo_image_info_t *info,
{
const unsigned char *p = data;
+ info->is_adobe_jpeg = FALSE;
+
while (p + 1 < data + length) {
if (*p != 0xff)
return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -131,6 +136,18 @@ _cairo_image_info_get_jpeg_info (cairo_image_info_t *info,
_jpeg_extract_info (info, p);
return CAIRO_STATUS_SUCCESS;
+ case APP14:
+ /* "Adobe" tags segment indicates inverted CMYK (in
+ * CMYK images). */
+ if (p + 12 > data + length)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ info->is_adobe_jpeg =
+ (0 == strncmp((const char *)(p + 3), "Adobe", 5));
+
+ p = _jpeg_skip_segment(p);
+ break;
+
default:
if (*p >= RST_begin && *p <= RST_end) {
p++;
@@ -206,6 +223,7 @@ _jpx_extract_info (const unsigned char *p, cairo_image_info_t *info)
info->width = get_unaligned_be32 (p + 4);
info->num_components = (p[8] << 8) + p[9];
info->bits_per_component = p[10];
+ info->is_adobe_jpeg = FALSE;
}
cairo_int_status_t
@@ -283,6 +301,8 @@ _cairo_image_info_get_png_info (cairo_image_info_t *info,
p += 4;
info->height = get_unaligned_be32 (p);
+ info->is_adobe_jpeg = FALSE;
+
return CAIRO_STATUS_SUCCESS;
}
@@ -395,6 +415,7 @@ _jbig2_extract_info (cairo_image_info_t *info, const unsigned char *p)
info->height = get_unaligned_be32 (p + 4);
info->num_components = 1;
info->bits_per_component = 1;
+ info->is_adobe_jpeg = FALSE;
}
cairo_int_status_t
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 09094ff49..944e9d62f 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -2959,6 +2959,7 @@ _cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t *surface,
" /Height %d\n"
" /ColorSpace %s\n"
" /Interpolate %s\n"
+ "%s"
" /BitsPerComponent %d\n"
"%s"
" /Filter /DCTDecode\n",
@@ -2966,6 +2967,7 @@ _cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t *surface,
info.height,
colorspace,
surface_entry->interpolate ? "true" : "false",
+ info.is_adobe_jpeg && info.num_components == 4 ? " /Decode [ 1 0 1 0 1 0 1 0 ]\n" : "",
info.bits_per_component,
smask_buf);
}