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>
This commit is contained in:
Peter TB Brett 2016-09-09 22:35:55 +09:30 committed by Adrian Johnson
parent a69e5af9cd
commit b207a932a2
3 changed files with 24 additions and 0 deletions

View file

@ -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

View file

@ -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

View file

@ -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);
}