summaryrefslogtreecommitdiff
path: root/Build
diff options
context:
space:
mode:
authorAkira Kakuto <kakuto@fuk.kindai.ac.jp>2015-04-12 13:30:04 +0000
committerAkira Kakuto <kakuto@fuk.kindai.ac.jp>2015-04-12 13:30:04 +0000
commit71f42391beb675e61c1760a652d172c20513cffb (patch)
treed2daa5d3758cede55955f2d72d09e12de58b4a58 /Build
parentd984cfa161205fb12b161143bc2ad34fab8f62e7 (diff)
dvipdfm-x: Fixes by S. Hirata.
git-svn-id: svn://tug.org/texlive/trunk@36782 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build')
-rw-r--r--Build/source/texk/dvipdfm-x/ChangeLog4
-rw-r--r--Build/source/texk/dvipdfm-x/jp2image.c100
-rw-r--r--Build/source/texk/dvipdfm-x/jpegimage.c742
-rw-r--r--Build/source/texk/dvipdfm-x/pdfcolor.c8
4 files changed, 487 insertions, 367 deletions
diff --git a/Build/source/texk/dvipdfm-x/ChangeLog b/Build/source/texk/dvipdfm-x/ChangeLog
index 5bfe0d88a94..536367742cd 100644
--- a/Build/source/texk/dvipdfm-x/ChangeLog
+++ b/Build/source/texk/dvipdfm-x/ChangeLog
@@ -2,6 +2,10 @@
* pdfobj.c: Fix some problems in reading cross-reference streams.
* pngimage.c: Support PNG gAMA chunk.
+ * jpegimage.c: Various fixes in handling JPEG Exif data
+ (possible overflow and buffer overrun), adjusting indent and spaces.
+ * jp2image.c: JPEG2000 opacity channel support.
+ * pdfcolor.c: Update for PDF 1.7 in pdfcolor.c.
2015-04-05 Shunsaku Hirata <shunsaku.hirata74@gmail.com>
diff --git a/Build/source/texk/dvipdfm-x/jp2image.c b/Build/source/texk/dvipdfm-x/jp2image.c
index aa601fabebd..09d3b227c25 100644
--- a/Build/source/texk/dvipdfm-x/jp2image.c
+++ b/Build/source/texk/dvipdfm-x/jp2image.c
@@ -25,7 +25,10 @@
#endif
/*
- * JP2 & JPX baseline SUPPORT:
+ * JP2 & JPX baseline support
+ *
+ * 20150412 Added opacity (transparency) support.
+ * TODO: XMP Metadata
*/
#include <math.h>
@@ -69,11 +72,11 @@ read_box_hdr (FILE *fp, unsigned int *lbox, unsigned int *tbox)
bytesread += 8;
if (*lbox == 1) {
if (get_unsigned_quad(fp) != 0)
- ERROR("LBox value in JP2 file >32 bits.\nI can't handle this!");
+ ERROR("JPEG2000: LBox value in JP2 file >32 bits.\nI can't handle this!");
*lbox = get_unsigned_quad(fp);
bytesread += 8;
} else if (*lbox > 1 && *lbox < 8) {
- WARN("Unknown LBox value %lu in JP2 file!", lbox);
+ WARN("JPEG2000: Unknown LBox value %lu in JP2 file!", lbox);
}
return bytesread;
@@ -121,7 +124,7 @@ check_ftyp_data (FILE *fp, unsigned int size)
}
break;
default:
- WARN("Unknown JPEG 2000 File Type box Brand field value.");
+ WARN("JPEG2000: Unknown JPEG 2000 File Type box Brand field value.");
seek_relative(fp, size);
size = 0;
supported = 0;
@@ -160,7 +163,7 @@ scan_res_ (ximage_info *info, FILE *fp, unsigned int size)
while (size > 0) {
len = read_box_hdr(fp, &lbox, &tbox);
if (lbox == 0) {
- WARN("Unexpected lbox value 0 in JP2 Resolution box.");
+ WARN("JPEG2000: Unexpected lbox value 0 in JP2 Resolution box.");
break;
}
switch (tbox) {
@@ -176,7 +179,7 @@ scan_res_ (ximage_info *info, FILE *fp, unsigned int size)
have_resd = 1;
break;
default:
- WARN("Unknown JPEG 2000 box type in Resolution box.");
+ WARN("JPEG2000: Unknown JPEG 2000 box type in Resolution box.");
seek_relative(fp, lbox - len);
}
size -= lbox;
@@ -185,8 +188,50 @@ scan_res_ (ximage_info *info, FILE *fp, unsigned int size)
return size == 0 ? 0 : -1;
}
+/* Acrobat seems require Channel Definition box to be defined when image data
+ * contains opacity channel. However, OpenJPEG (and maybe most of JPEG 2000 coders?)
+ * does not write Channel Definition box so transparency will be ignored.
+ */
static int
-scan_jp2h (ximage_info *info, FILE *fp, unsigned int size)
+scan_cdef (ximage_info *info, int *smask, FILE *fp, unsigned int size)
+{
+ int opacity_channels = 0;
+ int have_type0 = 0;
+ unsigned int i, Cn, N, Typ, Asoc;
+
+ *smask = 0;
+
+ N = get_unsigned_pair(fp);
+ if (size < N * 6 + 2) {
+ WARN("JPEG2000: Inconsistent N value in Channel Definition box.");
+ return -1;
+ }
+ for (i = 0; i < N; i++) {
+ Cn = get_unsigned_pair(fp); /* Cn */
+ Typ = get_unsigned_pair(fp);
+ Asoc = get_unsigned_pair(fp); /* must be 0 for SMask */
+ if (Cn > N)
+ WARN("JPEG2000: Invalid Cn value in Channel Definition box.");
+ if (Typ == 1) {
+ if (Asoc == 0)
+ have_type0 = 1;
+ opacity_channels++;
+ } else if (Typ == 2) {
+ opacity_channels++;
+ }
+ }
+
+ if (opacity_channels == 1)
+ *smask = have_type0 ? 1 : 0;
+ else if (opacity_channels > 1) {
+ WARN("JPEG2000: Unsupported transparency type. (ignored)");
+ }
+
+ return 0;
+}
+
+static int
+scan_jp2h (ximage_info *info, int *smask, FILE *fp, unsigned int size)
{
int error = 0, have_ihdr = 0;
unsigned int len, lbox, tbox;
@@ -194,7 +239,7 @@ scan_jp2h (ximage_info *info, FILE *fp, unsigned int size)
while (size > 0 && !error) {
len = read_box_hdr(fp, &lbox, &tbox);
if (lbox == 0) {
- WARN("Unexpected lbox value 0 in JP2 Header box...");
+ WARN("JPEG2000: Unexpected lbox value 0 in JP2 Header box...");
error = -1;
break;
}
@@ -212,13 +257,16 @@ scan_jp2h (ximage_info *info, FILE *fp, unsigned int size)
case JP2_BOX_RES_:
error = scan_res_(info, fp, lbox - len);
break;
+ case JP2_BOX_CDEF:
+ error = scan_cdef(info, smask, fp, lbox - len);
+ break;
case JP2_BOX_BPCC: case JP2_BOX_COLR: case JP2_BOX_PCLR:
- case JP2_BOX_CMAP: case JP2_BOX_CDEF:
+ case JP2_BOX_CMAP:
case JPX_BOX_LBL_:
seek_relative(fp, lbox - len);
break;
default:
- WARN("Unknown JPEG 2000 box in JP2 Header box.");
+ WARN("JPEG2000: Unknown JPEG 2000 box in JP2 Header box.");
seek_relative(fp, lbox - len);
error = -1;
}
@@ -226,12 +274,12 @@ scan_jp2h (ximage_info *info, FILE *fp, unsigned int size)
}
if (!have_ihdr)
- WARN("Expecting JPEG 2000 Image Header box but could not find.");
+ WARN("JPEG2000: Expecting JPEG 2000 Image Header box but could not find.");
return (!error && have_ihdr && size == 0) ? 0 : -1;
}
static int
-scan_file (ximage_info *info, FILE *fp)
+scan_file (ximage_info *info, int *smask, FILE *fp)
{
int error = 0, have_jp2h = 0;
int size;
@@ -260,13 +308,13 @@ scan_file (ximage_info *info, FILE *fp)
lbox = size;
switch (tbox) {
case JP2_BOX_JP2H:
- error = scan_jp2h(info, fp, lbox - len);
+ error = scan_jp2h(info, smask, fp, lbox - len);
have_jp2h = 1;
break;
case JP2_BOX_JP2C:
/* JP2 requires JP2H appears before JP2C. */
if (!have_jp2h)
- WARN("JPEG 2000 Codestream box found before JP2 Header box.");
+ WARN("JPEG2000: JPEG 2000 Codestream box found before JP2 Header box.");
seek_relative(fp, lbox - len);
break;
default:
@@ -276,12 +324,12 @@ scan_file (ximage_info *info, FILE *fp)
}
/* From ISO/IEC 15444-2 M.9.2.7
- The JP2 Header box shall be found in the file before the first
- Contiguous Codestream box, Fragment Table box, Media Data box,
- Codestream Header box, and Compositing Layer Header box. ...
- */
+ * The JP2 Header box shall be found in the file before the first
+ * Contiguous Codestream box, Fragment Table box, Media Data box,
+ * Codestream Header box, and Compositing Layer Header box. ...
+ */
if (!have_jp2h && !error) {
- WARN("No JP2 Header box found. Not a JP2/JPX baseline file?");
+ WARN("JPEG2000: No JP2 Header box found. Not a JP2/JPX baseline file?");
error = -1;
}
return error;
@@ -315,6 +363,7 @@ int
jp2_include_image (pdf_ximage *ximage, FILE *fp)
{
unsigned pdf_version;
+ int smask = 0;
pdf_obj *stream, *stream_dict;
ximage_info info;
@@ -328,15 +377,18 @@ jp2_include_image (pdf_ximage *ximage, FILE *fp)
stream = stream_dict = NULL;
rewind(fp);
- if (scan_file(&info, fp) < 0) {
- WARN("Reading JPEG 2000 file failed.");
+ if (scan_file(&info, &smask, fp) < 0) {
+ WARN("JPEG2000: Reading JPEG 2000 file failed.");
return -1;
}
stream = pdf_new_stream(0);
stream_dict = pdf_stream_dict(stream);
pdf_add_dict(stream_dict,
- pdf_new_name("Filter"), pdf_new_name("JPXDecode"));
+ pdf_new_name("Filter"), pdf_new_name("JPXDecode"));
+ if (smask)
+ pdf_add_dict(stream_dict,
+ pdf_new_name("SMaskInData"), pdf_new_number(1));
/* Read whole file */
{
size_t nb_read;
@@ -355,13 +407,13 @@ int
jp2_get_bbox (FILE *fp, int *width, int *height,
double *xdensity, double *ydensity)
{
- int r;
+ int r, smask = 0;
ximage_info info;
pdf_ximage_init_image_info(&info);
rewind(fp);
- r = scan_file(&info, fp);
+ r = scan_file(&info, &smask, fp);
*width = info.width;
*height = info.height;
diff --git a/Build/source/texk/dvipdfm-x/jpegimage.c b/Build/source/texk/dvipdfm-x/jpegimage.c
index f600b4538e3..19e7d0108d4 100644
--- a/Build/source/texk/dvipdfm-x/jpegimage.c
+++ b/Build/source/texk/dvipdfm-x/jpegimage.c
@@ -123,16 +123,17 @@ typedef enum {
typedef enum {
JS_APPn_JFIF,
JS_APPn_ADOBE,
- JS_APPn_ICC
+ JS_APPn_ICC,
+ JS_APPn_XMP
} JPEG_APPn_sig;
struct JPEG_APPn_JFIF /* APP0 */
{
unsigned short version;
unsigned char units; /* 0: only aspect ratio
- * 1: dots per inch
- * 2: dots per cm
- */
+ * 1: dots per inch
+ * 2: dots per cm
+ */
unsigned short Xdensity;
unsigned short Ydensity;
unsigned char Xthumbnail;
@@ -158,6 +159,14 @@ struct JPEG_APPn_Adobe /* APP14 */
unsigned char transform; /* color transform code */
};
+struct JPEG_APPn_XMP /* APP1 */
+{
+ unsigned char *packet; /* XMP packet */
+
+ /* Length of XMP packet data */
+ unsigned short length;
+};
+
struct JPEG_ext
{
JPEG_marker marker;
@@ -190,16 +199,16 @@ struct JPEG_info
#define HAVE_APPn_ADOBE (1 << 1)
#define HAVE_APPn_ICC (1 << 2)
#define HAVE_APPn_Exif (1 << 3)
+#define HAVE_APPn_XMP (1 << 4)
static int JPEG_scan_file (struct JPEG_info *j_info, FILE *fp);
-static int JPEG_copy_stream (struct JPEG_info *j_info,
- pdf_obj *stream, FILE *fp);
+static int JPEG_copy_stream (struct JPEG_info *j_info, pdf_obj *stream, FILE *fp);
static void JPEG_info_init (struct JPEG_info *j_info);
static void JPEG_info_clear (struct JPEG_info *j_info);
+static pdf_obj *JPEG_get_XMP (struct JPEG_info *j_info);
static pdf_obj *JPEG_get_iccp (struct JPEG_info *j_info);
-static void jpeg_get_density (struct JPEG_info *j_info,
- double *xdensity, double *ydensity);
+static void jpeg_get_density (struct JPEG_info *j_info, double *xdensity, double *ydensity);
int
check_for_jpeg (FILE *fp)
@@ -218,11 +227,11 @@ check_for_jpeg (FILE *fp)
int
jpeg_include_image (pdf_ximage *ximage, FILE *fp)
{
- pdf_obj *stream;
- pdf_obj *stream_dict;
- pdf_obj *colorspace;
- int colortype;
- ximage_info info;
+ pdf_obj *stream;
+ pdf_obj *stream_dict;
+ pdf_obj *colorspace;
+ int colortype;
+ ximage_info info;
struct JPEG_info j_info;
if (!check_for_jpeg(fp)) {
@@ -253,8 +262,7 @@ jpeg_include_image (pdf_ximage *ximage, FILE *fp)
colortype = PDF_COLORSPACE_TYPE_CMYK;
break;
default:
- WARN("%s: Unknown color space (num components: %d)",
- JPEG_DEBUG_STR, info.num_components);
+ WARN("%s: Unknown color space (num components: %d)", JPEG_DEBUG_STR, info.num_components);
JPEG_info_clear(&j_info);
return -1;
}
@@ -262,42 +270,50 @@ jpeg_include_image (pdf_ximage *ximage, FILE *fp)
/* JPEG image use DCTDecode. */
stream = pdf_new_stream (0);
stream_dict = pdf_stream_dict(stream);
- pdf_add_dict(stream_dict,
- pdf_new_name("Filter"), pdf_new_name("DCTDecode"));
+ pdf_add_dict(stream_dict, pdf_new_name("Filter"), pdf_new_name("DCTDecode"));
+
+ /* XMP Metadata */
+ if (pdf_get_version() >= 4) {
+ if (j_info.flags & HAVE_APPn_XMP) {
+ pdf_obj *XMP_stream;
+
+ XMP_stream = JPEG_get_XMP(&j_info);
+ pdf_add_dict(stream_dict,
+ pdf_new_name("Metadata"), pdf_ref_obj(XMP_stream));
+ pdf_release_obj(XMP_stream);
+ }
+ }
+ /* Check embedded ICC Profile */
colorspace = NULL;
if (j_info.flags & HAVE_APPn_ICC) {
pdf_obj *icc_stream, *intent;
+ int cspc_id;
icc_stream = JPEG_get_iccp(&j_info);
-
if (!icc_stream)
colorspace = NULL;
else {
- int cspc_id;
-
if (iccp_check_colorspace(colortype,
- pdf_stream_dataptr(icc_stream),
- pdf_stream_length (icc_stream)) < 0)
- colorspace = NULL;
+ pdf_stream_dataptr(icc_stream), pdf_stream_length (icc_stream)) < 0)
+ colorspace = NULL;
else {
- cspc_id = iccp_load_profile(NULL, /* noname */
- pdf_stream_dataptr(icc_stream),
- pdf_stream_length (icc_stream));
- if (cspc_id < 0)
- colorspace = NULL;
- else {
- colorspace = pdf_get_colorspace_reference(cspc_id);
- intent = iccp_get_rendering_intent(pdf_stream_dataptr(icc_stream),
- pdf_stream_length (icc_stream));
- if (intent)
- pdf_add_dict(stream_dict, pdf_new_name("Intent"), intent);
- }
+ cspc_id = iccp_load_profile(NULL, /* noname */
+ pdf_stream_dataptr(icc_stream),
+ pdf_stream_length (icc_stream));
+ if (cspc_id < 0)
+ colorspace = NULL;
+ else {
+ colorspace = pdf_get_colorspace_reference(cspc_id);
+ intent = iccp_get_rendering_intent(pdf_stream_dataptr(icc_stream),
+ pdf_stream_length (icc_stream));
+ if (intent)
+ pdf_add_dict(stream_dict, pdf_new_name("Intent"), intent);
+ }
}
pdf_release_obj(icc_stream);
}
}
-
/* No ICC or invalid ICC profile. */
if (!colorspace) {
switch (colortype) {
@@ -315,7 +331,6 @@ jpeg_include_image (pdf_ximage *ximage, FILE *fp)
pdf_add_dict(stream_dict, pdf_new_name("ColorSpace"), colorspace);
#define IS_ADOBE_CMYK(j) (((j).flags & HAVE_APPn_ADOBE) && (j).num_components == 4)
-
if (IS_ADOBE_CMYK(j_info)) {
pdf_obj *decode;
int i;
@@ -346,8 +361,7 @@ jpeg_include_image (pdf_ximage *ximage, FILE *fp)
}
static void
-jpeg_get_density (struct JPEG_info *j_info,
- double *xdensity, double *ydensity)
+jpeg_get_density (struct JPEG_info *j_info, double *xdensity, double *ydensity)
{
if (compat_mode) {
*xdensity = *ydensity = 72.0 / 100.0;
@@ -355,53 +369,26 @@ jpeg_get_density (struct JPEG_info *j_info,
}
/*
- j_info->xdpi and j_info->ydpi are already determined
- because jpeg_get_density() is always called after
- JPEG_scan_file().
-*/
+ * j_info->xdpi and j_info->ydpi are already determined
+ * because jpeg_get_density() is always called after
+ * JPEG_scan_file().
+ */
*xdensity = 72.0 / j_info->xdpi;
*ydensity = 72.0 / j_info->ydpi;
- return;
-#if 0
- *xdensity = *ydensity = 1.0;
- if (j_info->flags & HAVE_APPn_JFIF) {
- struct JPEG_APPn_JFIF *app_data;
- int i;
- for (i = 0; i < j_info->num_appn; i++) {
- if (j_info->appn[i].marker == JM_APP0 &&
- j_info->appn[i].app_sig == JS_APPn_JFIF)
- break;
- }
- if (i < j_info->num_appn) {
- app_data = (struct JPEG_APPn_JFIF *)j_info->appn[i].app_data;
- switch (app_data->units) {
- case 1: /* pixels per inch */
- *xdensity = 72.0 / app_data->Xdensity;
- *ydensity = 72.0 / app_data->Ydensity;
- break;
- case 2: /* pixels per centimeter */
- *xdensity = 72.0 / 2.54 / app_data->Xdensity;
- *ydensity = 72.0 / 2.54 / app_data->Ydensity;
- break;
- default:
- break;
- }
- }
- }
-#endif
+ return;
}
static void
JPEG_info_init (struct JPEG_info *j_info)
{
- j_info->width = 0;
- j_info->height = 0;
+ j_info->width = 0;
+ j_info->height = 0;
j_info->bits_per_component = 0;
- j_info->num_components = 0;
+ j_info->num_components = 0;
- j_info->xdpi = 0.0;
- j_info->ydpi = 0.0;
+ j_info->xdpi = 0.0;
+ j_info->ydpi = 0.0;
j_info->flags = 0;
j_info->num_appn = 0;
@@ -424,8 +411,7 @@ JPEG_release_APPn_data (JPEG_marker marker, JPEG_APPn_sig app_sig, void *app_dat
data->thumbnail = NULL;
RELEASE(data);
- } else if (marker == JM_APP2 &&
- app_sig == JS_APPn_ICC) {
+ } else if (marker == JM_APP2 && app_sig == JS_APPn_ICC) {
struct JPEG_APPn_ICC *data;
data = (struct JPEG_APPn_ICC *) app_data;
@@ -434,13 +420,20 @@ JPEG_release_APPn_data (JPEG_marker marker, JPEG_APPn_sig app_sig, void *app_dat
data->chunk = NULL;
RELEASE(data);
- } else if (marker == JM_APP14 &&
- app_sig == JS_APPn_ADOBE) {
+ } else if (marker == JM_APP14 && app_sig == JS_APPn_ADOBE) {
struct JPEG_APPn_Adobe *data;
data = (struct JPEG_APPn_Adobe *) app_data;
RELEASE(data);
+ } else if (marker == JM_APP1 && app_sig == JS_APPn_XMP) {
+ struct JPEG_APPn_XMP *data;
+
+ data = (struct JPEG_APPn_XMP *) app_data;
+ if (data->packet)
+ RELEASE(data->packet);
+
+ RELEASE(data);
}
}
@@ -453,7 +446,7 @@ JPEG_info_clear (struct JPEG_info *j_info)
for (i = 0; i < j_info->num_appn; i++)
JPEG_release_APPn_data(j_info->appn[i].marker,
- j_info->appn[i].app_sig, j_info->appn[i].app_data);
+ j_info->appn[i].app_sig, j_info->appn[i].app_data);
RELEASE(j_info->appn);
}
j_info->appn = NULL;
@@ -465,36 +458,63 @@ JPEG_info_clear (struct JPEG_info *j_info)
static pdf_obj *
JPEG_get_iccp (struct JPEG_info *j_info)
{
- pdf_obj *icc_stream;
+ pdf_obj *icc_stream;
struct JPEG_APPn_ICC *icc;
- int i, prev_id = 0, num_icc_seg = -1;
+ int i, prev_id = 0, num_icc_seg = -1;
icc_stream = pdf_new_stream(STREAM_COMPRESS);
for (i = 0; i < j_info->num_appn; i++) {
if (j_info->appn[i].marker != JM_APP2 ||
- j_info->appn[i].app_sig != JS_APPn_ICC)
+ j_info->appn[i].app_sig != JS_APPn_ICC)
continue;
icc = (struct JPEG_APPn_ICC *) j_info->appn[i].app_data;
if (num_icc_seg < 0 && prev_id == 0) {
num_icc_seg = icc->num_chunks;
/* ICC chunks are sorted? */
} else if (icc->seq_id != prev_id + 1 ||
- num_icc_seg != icc->num_chunks ||
- icc->seq_id > icc->num_chunks) {
- WARN("Invalid JPEG ICC chunk: %d (p:%d, n:%d)",
- icc->seq_id, prev_id, icc->num_chunks);
+ num_icc_seg != icc->num_chunks || icc->seq_id > icc->num_chunks) {
+ WARN("Invalid JPEG ICC chunk: %d (p:%d, n:%d)", icc->seq_id, prev_id, icc->num_chunks);
pdf_release_obj(icc_stream);
icc_stream = NULL;
break;
}
pdf_add_stream(icc_stream, icc->chunk, icc->length);
- prev_id = icc->seq_id;
+ prev_id = icc->seq_id;
num_icc_seg = icc->num_chunks;
}
return icc_stream;
}
+static pdf_obj *
+JPEG_get_XMP (struct JPEG_info *j_info)
+{
+ pdf_obj *XMP_stream, *stream_dict;
+ struct JPEG_APPn_XMP *XMP;
+ int i, count = 0;
+
+ /* I don't know if XMP Metadata should be compressed here.*/
+ XMP_stream = pdf_new_stream(STREAM_COMPRESS);
+ stream_dict = pdf_stream_dict(XMP_stream);
+ pdf_add_dict(stream_dict,
+ pdf_new_name("Type"), pdf_new_name("Metadata"));
+ pdf_add_dict(stream_dict,
+ pdf_new_name("Subtype"), pdf_new_name("XML"));
+ for (i = 0; i < j_info->num_appn; i++) {
+ /* Not sure for the case of multiple segments */
+ if (j_info->appn[i].marker != JM_APP1 ||
+ j_info->appn[i].app_sig != JS_APPn_XMP)
+ continue;
+ XMP = (struct JPEG_APPn_XMP *) j_info->appn[i].app_data;
+ pdf_add_stream(XMP_stream, XMP->packet, XMP->length);
+ count++;
+ }
+ if (count > 1)
+ WARN("%s: Multiple XMP segments found in JPEG file. (untested)", JPEG_DEBUG_STR);
+
+ return XMP_stream;
+}
+
static JPEG_marker
JPEG_get_marker (FILE *fp)
{
@@ -515,8 +535,7 @@ JPEG_get_marker (FILE *fp)
}
static int
-add_APPn_marker (struct JPEG_info *j_info,
- JPEG_marker marker, int app_sig, void *app_data)
+add_APPn_marker (struct JPEG_info *j_info, JPEG_marker marker, int app_sig, void *app_data)
{
int n;
@@ -551,131 +570,171 @@ read_APP14_Adobe (struct JPEG_info *j_info, FILE *fp)
return 7;
}
-static unsigned int
-read_exif_bytes(unsigned char **p, int n, int b)
+#define JPEG_EXIF_BIGENDIAN 0
+#define JPEG_EXIF_LITTLEENDIAN 1
+static long
+read_exif_bytes (unsigned char **pp, int n, int endian)
{
- unsigned int rval = 0;
- unsigned char *pp = *p;
- if (b) {
- switch (n) {
- case 4:
- rval += *pp++; rval <<= 8;
- rval += *pp++; rval <<= 8;
- case 2:
- rval += *pp++; rval <<= 8;
- rval += *pp;
- break;
+ long rval = 0;
+ unsigned char *p = *pp;
+ int i;
+
+ switch (endian) {
+ case JPEG_EXIF_BIGENDIAN:
+ for (i = 0; i < n; i++) {
+ rval = (rval << 8) + p[i];
}
- }
- else {
- pp += n;
- switch (n) {
- case 4:
- rval += *--pp; rval <<= 8;
- rval += *--pp; rval <<= 8;
- case 2:
- rval += *--pp; rval <<= 8;
- rval += *--pp;
- break;
+ break;
+ case JPEG_EXIF_LITTLEENDIAN:
+ for (i = n - 1; i >= 0; i--) {
+ rval = (rval << 8) + p[i];
}
+ break;
}
- *p += n;
+
+ *pp += n;
return rval;
}
+#define JPEG_EXIF_TYPE_BYTE 1
+#define JPEG_EXIF_TYPE_ASCII 2
+#define JPEG_EXIF_TYPE_SHORT 3
+#define JPEG_EXIF_TYPE_LONG 4
+#define JPEG_EXIF_TYPE_RATIONAL 5
+#define JPEG_EXIF_TYPE_UNDEFINED 7
+#define JPEG_EXIF_TYPE_SLONG 9
+#define JPEG_EXIF_TYPE_SRATIONAL 10
+
+#define JPEG_EXIF_TAG_XRESOLUTION 282
+#define JPEG_EXIF_TAG_YRESOLUTION 283
+#define JPEG_EXIF_TAG_RESOLUTIONUNIT 296
static unsigned short
read_APP1_Exif (struct JPEG_info *j_info, FILE *fp, unsigned short length)
{
/* this doesn't save the data, just reads the tags we need */
/* based on info from http://www.exif.org/Exif2-2.PDF */
unsigned char *buffer = NEW(length, unsigned char);
- unsigned char *p, *rp;
+ unsigned char *p, *endptr;
unsigned char *tiff_header;
- char bigendian;
- int i;
- int num_fields, tag, type;
- int value = 0, num = 0, den = 0; /* silence uninitialized warnings */
- double xres = 72.0;
- double yres = 72.0;
- double res_unit = 1.0;
+ int endian;
+ int num_fields;
+ long value = 0, offset;
+ double xres = 72.0, yres = 72.0;
+ double res_unit = 1.0;
+
fread(buffer, length, 1, fp);
- p = buffer;
- while ((p < buffer + length) && (*p == 0))
- ++p;
+ if (length < 10)
+ goto err;
+
+ p = buffer; endptr = buffer + length;
+ while ((p < endptr) && (*p == 0))
+ p++;
+
+ /* TIFF header */
tiff_header = p;
- if ((*p == 'M') && (*(p+1) == 'M'))
- bigendian = 1;
- else if ((*p == 'I') && (*(p+1) == 'I'))
- bigendian = 0;
- else
+ if ((p[0] == 'M') && (p[1] == 'M'))
+ endian = JPEG_EXIF_BIGENDIAN;
+ else if ((p[0] == 'I') && (p[1] == 'I'))
+ endian = JPEG_EXIF_LITTLEENDIAN;
+ else {
+ WARN("%s: Invalid value in Exif TIFF header.", JPEG_DEBUG_STR);
goto err;
- p += 2;
- i = read_exif_bytes(&p, 2, bigendian);
- if (i != 42)
+ }
+ p += 2;
+ value = read_exif_bytes(&p, 2, endian);
+ if (value != 42) {
+ WARN("%s: Invalid value in Exif TIFF header.", JPEG_DEBUG_STR);
goto err;
- i = read_exif_bytes(&p, 4, bigendian);
- p = tiff_header + i;
- num_fields = read_exif_bytes(&p, 2, bigendian);
- while (num_fields-- > 0) {
- tag = read_exif_bytes(&p, 2, bigendian);
- type = read_exif_bytes(&p, 2, bigendian);
- read_exif_bytes(&p, 4, bigendian);
- switch (type) {
- case 1: /* byte */
- value = *p++;
- p += 3;
- break;
- case 3: /* short */
- value = read_exif_bytes(&p, 2, bigendian);
- p += 2;
- break;
- case 4: /* long */
- case 9: /* slong */
- value = read_exif_bytes(&p, 4, bigendian);
- break;
- case 5: /* rational */
- case 10: /* srational */
- value = read_exif_bytes(&p, 4, bigendian);
- rp = tiff_header + value;
- num = read_exif_bytes(&rp, 4, bigendian);
- den = read_exif_bytes(&rp, 4, bigendian);
- break;
- case 7: /* undefined */
- value = *p++;
- p += 3;
- break;
- case 2: /* ascii */
- default:
- p += 4;
- break;
+ }
+ /* Offset to 0th IFD */
+ offset = read_exif_bytes(&p, 4, endian);
+
+ p = tiff_header + offset;
+ num_fields = read_exif_bytes(&p, 2, endian);
+ while (num_fields-- > 0 && p < endptr) {
+ int tag, type;
+ long count;
+ unsigned long den, num;
+
+ if (p + 12 > endptr) {
+ WARN("%s: Truncated Exif data...", JPEG_DEBUG_STR);
+ goto err;
}
+ tag = (int) read_exif_bytes(&p, 2, endian);
+ type = (int) read_exif_bytes(&p, 2, endian);
+ count = read_exif_bytes(&p, 4, endian);
+ /* Exif data is redundant... */
switch (tag) {
- case 282: /* x res */
- if (den != 0)
- xres = num / den;
- break;
- case 283: /* y res */
- if (den != 0)
- yres = num / den;
- break;
- case 296: /* res unit */
- switch (value) {
- case 2:
- res_unit = 1.0;
- break;
- case 3:
- res_unit = 2.54;
- break;
- }
+ case JPEG_EXIF_TAG_XRESOLUTION:
+ if (type != JPEG_EXIF_TYPE_RATIONAL || count != 1) {
+ WARN("%s: Invalid data for XResolution in Exif chunk.", JPEG_DEBUG_STR);
+ goto err;
+ }
+ offset = read_exif_bytes(&p, 4, endian);
+ if (tiff_header + offset + 8 > buffer + length) {
+ WARN("%s: Invalid offset value in Exif data.", JPEG_DEBUG_STR);
+ goto err;
+ } else {
+ unsigned char *vp = tiff_header + offset;
+ num = (unsigned long) read_exif_bytes(&vp, 4, endian);
+ den = (unsigned long) read_exif_bytes(&vp, 4, endian);
+ }
+ if (den > 0)
+ xres = (double) num / den;
+ break;
+ case JPEG_EXIF_TAG_YRESOLUTION:
+ if (type != JPEG_EXIF_TYPE_RATIONAL || count != 1) {
+ WARN("%s: Invalid data for XResolution in Exif chunk.", JPEG_DEBUG_STR);
+ goto err;
+ }
+ offset = read_exif_bytes(&p, 4, endian);
+ if (tiff_header + offset + 8 > buffer + length) {
+ WARN("%s: Invalid offset value in Exif data.", JPEG_DEBUG_STR);
+ goto err;
+ } else {
+ unsigned char *vp = tiff_header + offset;
+ num = (unsigned long) read_exif_bytes(&vp, 4, endian);
+ den = (unsigned long) read_exif_bytes(&vp, 4, endian);
+ }
+ if (den > 0)
+ yres = (double) num / den;
+ break;
+ case JPEG_EXIF_TAG_RESOLUTIONUNIT:
+ if (type != JPEG_EXIF_TYPE_SHORT || count != 1) {
+ WARN("%s: Invalid data for ResolutionUnit in Exif chunk.", JPEG_DEBUG_STR);
+ goto err;
+ }
+ value = read_exif_bytes(&p, 2, endian);
+ p += 2;
+ if (value == 2)
+ res_unit = 1.0 ; /* inch */
+ else if (value == 3)
+ res_unit = 2.54; /* cm */
+ break;
+ default:
+ /* 40901 ColorSpace and 42240 Gamma unsupported... */
+ p += 4;
+ break;
}
}
-/*
- Do not overwrite if j_info->xdpi and j_info->ydpi are
- already determined as JFIF
-*/
+ if (num_fields > 0) {
+ WARN("%s: Truncated Exif data...", JPEG_DEBUG_STR);
+ goto err;
+ }
+
+/* Do not overwrite j_info->xdpi and j_info->ydpi if they are
+ * already determined in JFIF.
+ */
if (j_info->xdpi < 0.1 && j_info->ydpi < 0.1) {
j_info->xdpi = xres * res_unit;
j_info->ydpi = yres * res_unit;
+ } else {
+ if (j_info->xdpi != xres * res_unit ||
+ j_info->ydpi != yres * res_unit) {
+ WARN("%s: Inconsistent resolution may have " \
+ "specified in Exif and JFIF: %gx%g - %gx%g", JPEG_DEBUG_STR,
+ xres * res_unit, yres * res_unit, j_info->xdpi, j_info->ydpi);
+ }
}
err:
@@ -690,10 +749,10 @@ read_APP0_JFIF (struct JPEG_info *j_info, FILE *fp)
unsigned short thumb_data_len;
app_data = NEW(1, struct JPEG_APPn_JFIF);
- app_data->version = get_unsigned_pair(fp);
- app_data->units = get_unsigned_byte(fp);
- app_data->Xdensity = get_unsigned_pair(fp);
- app_data->Ydensity = get_unsigned_pair(fp);
+ app_data->version = get_unsigned_pair(fp);
+ app_data->units = get_unsigned_byte(fp);
+ app_data->Xdensity = get_unsigned_pair(fp);
+ app_data->Ydensity = get_unsigned_pair(fp);
app_data->Xthumbnail = get_unsigned_byte(fp);
app_data->Ythumbnail = get_unsigned_byte(fp);
thumb_data_len = 3 * app_data->Xthumbnail * app_data->Ythumbnail;
@@ -734,7 +793,7 @@ read_APP0_JFXX (FILE *fp, unsigned short length)
* 0x11: Thumbnail stored using 1 byte/pixel
* 0x13: Thumbnail stored using 3 bytes/pixel
*/
- seek_relative(fp, length-1); /* Thunbnail image */
+ seek_relative(fp, length - 1); /* Thunbnail image */
/* Ignore */
@@ -742,6 +801,21 @@ read_APP0_JFXX (FILE *fp, unsigned short length)
}
static unsigned short
+read_APP1_XMP (struct JPEG_info *j_info, FILE *fp, unsigned short length)
+{
+ struct JPEG_APPn_XMP *app_data;
+
+ app_data = NEW(1, struct JPEG_APPn_XMP);
+ app_data->length = length;
+ app_data->packet = NEW(app_data->length, unsigned char);
+ fread(app_data->packet, 1, app_data->length, fp);
+
+ add_APPn_marker(j_info, JM_APP1, JS_APPn_XMP, app_data);
+
+ return length;
+}
+
+static unsigned short
read_APP2_ICC (struct JPEG_info *j_info, FILE *fp, unsigned short length)
{
struct JPEG_APPn_ICC *app_data;
@@ -749,8 +823,8 @@ read_APP2_ICC (struct JPEG_info *j_info, FILE *fp, unsigned short length)
app_data = NEW(1, struct JPEG_APPn_ICC);
app_data->seq_id = get_unsigned_byte(fp); /* Starting at 1 */
app_data->num_chunks = get_unsigned_byte(fp);
- app_data->length = length - 2;
- app_data->chunk = NEW(app_data->length, unsigned char);
+ app_data->length = length - 2;
+ app_data->chunk = NEW(app_data->length, unsigned char);
fread(app_data->chunk, 1, app_data->length, fp);
add_APPn_marker(j_info, JM_APP2, JS_APPn_ICC, app_data);
@@ -762,173 +836,162 @@ static int
JPEG_copy_stream (struct JPEG_info *j_info, pdf_obj *stream, FILE *fp)
{
JPEG_marker marker;
- int length, nb_read;
- int found_SOFn, count;
-
+ long length;
+ int found_SOFn, count;
+
+#define SKIP_CHUNK(j,c) ((j)->skipbits[(c) / 8] & (1 << (7 - (c) % 8)))
+#define COPY_CHUNK(f,s,l) while ((l) > 0) { \
+ size_t nb_read = fread(work_buffer, sizeof(char), MIN((l), WORK_BUFFER_SIZE), (f)); \
+ if (nb_read > 0) \
+ pdf_add_stream((s), work_buffer, nb_read); \
+ (l) -= nb_read; \
+}
rewind(fp);
count = 0;
found_SOFn = 0;
- while (!found_SOFn &&
- count < MAX_COUNT &&
- (marker = JPEG_get_marker(fp)) != (JPEG_marker) -1) {
- if (marker == JM_SOI ||
- (marker >= JM_RST0 && marker <= JM_RST7)) {
+ while (!found_SOFn && count < MAX_COUNT &&
+ (marker = JPEG_get_marker(fp)) != (JPEG_marker) - 1) {
+ if ( marker == JM_SOI ||
+ (marker >= JM_RST0 && marker <= JM_RST7)) {
work_buffer[0] = (char) 0xff;
work_buffer[1] = (char) marker;
pdf_add_stream(stream, work_buffer, 2);
- count++;
- continue;
- }
- length = get_unsigned_pair(fp) - 2;
- switch (marker) {
- case JM_SOF0: case JM_SOF1: case JM_SOF2: case JM_SOF3:
- case JM_SOF5: case JM_SOF6: case JM_SOF7: case JM_SOF9:
- case JM_SOF10: case JM_SOF11: case JM_SOF13: case JM_SOF14:
- case JM_SOF15:
- work_buffer[0] = (char) 0xff;
- work_buffer[1] = (char) marker;
- work_buffer[2] = ((length + 2) >> 8) & 0xff;
- work_buffer[3] = (length + 2) & 0xff;
- pdf_add_stream(stream, work_buffer, 4);
- while (length > 0) {
- nb_read = fread(work_buffer, sizeof(char),
- MIN(length, WORK_BUFFER_SIZE), fp);
- if (nb_read > 0)
- pdf_add_stream(stream, work_buffer, nb_read);
- length -= nb_read;
- }
- found_SOFn = 1;
- break;
- default:
- if (j_info->skipbits[count / 8] & (1 << (7 - (count % 8)))) {
- /* skip */
- while (length > 0) {
- nb_read = fread(work_buffer, sizeof(char),
- MIN(length, WORK_BUFFER_SIZE), fp);
- length -= nb_read;
- }
- } else {
- work_buffer[0] = (char) 0xff;
- work_buffer[1] = (char) marker;
- work_buffer[2] = ((length + 2) >> 8) & 0xff;
- work_buffer[3] = (length + 2) & 0xff;
- pdf_add_stream(stream, work_buffer, 4);
- while (length > 0) {
- nb_read = fread(work_buffer, sizeof(char),
- MIN(length, WORK_BUFFER_SIZE), fp);
- if (nb_read > 0)
- pdf_add_stream(stream, work_buffer, nb_read);
- length -= nb_read;
- }
+ } else {
+ length = get_unsigned_pair(fp) - 2;
+ switch (marker) {
+ case JM_SOF0: case JM_SOF1: case JM_SOF2: case JM_SOF3:
+ case JM_SOF5: case JM_SOF6: case JM_SOF7: case JM_SOF9:
+ case JM_SOF10: case JM_SOF11: case JM_SOF13: case JM_SOF14:
+ case JM_SOF15:
+ work_buffer[0] = (char) 0xff;
+ work_buffer[1] = (char) marker;
+ work_buffer[2] = ((length + 2) >> 8) & 0xff;
+ work_buffer[3] = (length + 2) & 0xff;
+ pdf_add_stream(stream, work_buffer, 4);
+ COPY_CHUNK(fp, stream, length);
+ found_SOFn = 1;
+ break;
+ default:
+ if (SKIP_CHUNK(j_info, count)) {
+ seek_relative(fp, length);
+ } else {
+ work_buffer[0] = (char) 0xff;
+ work_buffer[1] = (char) marker;
+ work_buffer[2] = ((length + 2) >> 8) & 0xff;
+ work_buffer[3] = (length + 2) & 0xff;
+ pdf_add_stream(stream, work_buffer, 4);
+ COPY_CHUNK(fp, stream, length);
+ }
}
}
count++;
}
-
while ((length = fread(work_buffer,
- sizeof(char), WORK_BUFFER_SIZE, fp)) > 0) {
+ sizeof(char), WORK_BUFFER_SIZE, fp)) > 0) {
pdf_add_stream(stream, work_buffer, length);
}
return (found_SOFn ? 0 : -1);
}
+#define SET_SKIP(j,c) if ((c) < MAX_COUNT) { \
+ (j)->skipbits[(c) / 8] |= (1 << (7 - ((c) % 8))); \
+}
static int
JPEG_scan_file (struct JPEG_info *j_info, FILE *fp)
{
JPEG_marker marker;
- unsigned short length;
- int found_SOFn, count;
- char app_sig[128];
+ int found_SOFn, count;
+ char app_sig[128];
rewind(fp);
count = 0;
found_SOFn = 0;
while (!found_SOFn &&
- (marker = JPEG_get_marker(fp)) != (JPEG_marker) -1) {
- if (marker == JM_SOI ||
- (marker >= JM_RST0 && marker <= JM_RST7)) {
- count++;
- continue;
- }
- length = get_unsigned_pair(fp) - 2;
- switch (marker) {
- case JM_SOF0: case JM_SOF1: case JM_SOF2: case JM_SOF3:
- case JM_SOF5: case JM_SOF6: case JM_SOF7: case JM_SOF9:
- case JM_SOF10: case JM_SOF11: case JM_SOF13: case JM_SOF14:
- case JM_SOF15:
- j_info->bits_per_component = get_unsigned_byte(fp);
- j_info->height = get_unsigned_pair(fp);
- j_info->width = get_unsigned_pair(fp);
- j_info->num_components = get_unsigned_byte(fp);
- found_SOFn = 1;
- break;
- case JM_APP0:
- if (length > 5) {
- if (fread(app_sig, sizeof(char), 5, fp) != 5)
- return -1;
- length -= 5;
- if (!memcmp(app_sig, "JFIF\000", 5)) {
- j_info->flags |= HAVE_APPn_JFIF;
- length -= read_APP0_JFIF(j_info, fp);
- } else if (!memcmp(app_sig, "JFXX", 5)) {
- length -= read_APP0_JFXX(fp, length);
- }
- }
- seek_relative(fp, length);
- break;
- case JM_APP1:
- if (length > 5) {
- if (fread(app_sig, sizeof(char), 5, fp) != 5)
- return -1;
- length -= 5;
- if (!memcmp(app_sig, "Exif\000", 5)) {
- j_info->flags |= HAVE_APPn_Exif;
- length -= read_APP1_Exif(j_info, fp, length);
- }
- }
- seek_relative(fp, length);
- break;
- case JM_APP2:
- if (length >= 14) {
- if (fread(app_sig, sizeof(char), 12, fp) != 12)
- return -1;
- length -= 12;
- if (!memcmp(app_sig, "ICC_PROFILE\000", 12)) {
- j_info->flags |= HAVE_APPn_ICC;
- length -= read_APP2_ICC(j_info, fp, length);
- if (count < MAX_COUNT) {
- j_info->skipbits[count / 8] |= (1 << (7 - (count % 8)));
- }
- }
- }
- seek_relative(fp, length);
- break;
- case JM_APP14:
- if (length > 5) {
- if (fread(app_sig, sizeof(char), 5, fp) != 5)
- return -1;
- length -= 5;
- if (!memcmp(app_sig, "Adobe", 5)) {
- j_info->flags |= HAVE_APPn_ADOBE;
- length -= read_APP14_Adobe(j_info, fp);
- } else {
- if (count < MAX_COUNT) {
- j_info->skipbits[count/8] |= (1 << (7 - (count % 8)));
- }
- }
- }
- seek_relative(fp, length);
- break;
- default:
- seek_relative(fp, length);
- if (marker >= JM_APP0 &&
- marker <= JM_APP15) {
- if (count < MAX_COUNT) {
- j_info->skipbits[count / 8] |= (1 << (7 - (count % 8)));
- }
+ (marker = JPEG_get_marker(fp)) != (JPEG_marker) -1) {
+ if ( marker != JM_SOI &&
+ (marker < JM_RST0 || marker > JM_RST7)) {
+ long length = get_unsigned_pair(fp) - 2;
+ switch (marker) {
+ case JM_SOF0: case JM_SOF1: case JM_SOF2: case JM_SOF3:
+ case JM_SOF5: case JM_SOF6: case JM_SOF7: case JM_SOF9:
+ case JM_SOF10: case JM_SOF11: case JM_SOF13: case JM_SOF14:
+ case JM_SOF15:
+ j_info->bits_per_component = get_unsigned_byte(fp);
+ j_info->height = get_unsigned_pair(fp);
+ j_info->width = get_unsigned_pair(fp);
+ j_info->num_components = get_unsigned_byte(fp);
+ found_SOFn = 1;
+ break;
+ case JM_APP0:
+ if (length > 5) {
+ if (fread(app_sig, sizeof(char), 5, fp) != 5)
+ return -1;
+ length -= 5;
+ if (!memcmp(app_sig, "JFIF\000", 5)) {
+ j_info->flags |= HAVE_APPn_JFIF;
+ length -= read_APP0_JFIF(j_info, fp);
+ } else if (!memcmp(app_sig, "JFXX", 5)) {
+ length -= read_APP0_JFXX(fp, length);
+ }
+ }
+ seek_relative(fp, length);
+ break;
+ case JM_APP1:
+ if (length > 5) {
+ if (fread(app_sig, sizeof(char), 5, fp) != 5)
+ return -1;
+ length -= 5;
+ if (!memcmp(app_sig, "Exif\000", 5)) {
+ j_info->flags |= HAVE_APPn_Exif;
+ length -= read_APP1_Exif(j_info, fp, length);
+ } else if (!memcmp(app_sig, "http:", 5) && length > 24) {
+ if (fread(app_sig, sizeof(char), 24, fp) != 24)
+ return -1;
+ length -= 24;
+ if (!memcmp(app_sig, "//ns.adobe.com/xap/1.0/\000", 24)) {
+ j_info->flags |= HAVE_APPn_XMP;
+ length -= read_APP1_XMP(j_info, fp, length);
+ SET_SKIP(j_info, count);
+ }
+ }
+ }
+ seek_relative(fp, length);
+ break;
+ case JM_APP2:
+ if (length >= 14) {
+ if (fread(app_sig, sizeof(char), 12, fp) != 12)
+ return -1;
+ length -= 12;
+ if (!memcmp(app_sig, "ICC_PROFILE\000", 12)) {
+ j_info->flags |= HAVE_APPn_ICC;
+ length -= read_APP2_ICC(j_info, fp, length);
+ SET_SKIP(j_info, count);
+ }
+ }
+ seek_relative(fp, length);
+ break;
+ case JM_APP14:
+ if (length > 5) {
+ if (fread(app_sig, sizeof(char), 5, fp) != 5)
+ return -1;
+ length -= 5;
+ if (!memcmp(app_sig, "Adobe", 5)) {
+ j_info->flags |= HAVE_APPn_ADOBE;
+ length -= read_APP14_Adobe(j_info, fp);
+ } else {
+ SET_SKIP(j_info, count);
+ }
+ }
+ seek_relative(fp, length);
+ break;
+ default:
+ seek_relative(fp, length);
+ if (marker >= JM_APP0 && marker <= JM_APP15) {
+ SET_SKIP(j_info, count);
+ }
+ break;
}
- break;
}
count++;
}
@@ -937,8 +1000,7 @@ JPEG_scan_file (struct JPEG_info *j_info, FILE *fp)
}
int
-jpeg_get_bbox (FILE *fp, int *width, int *height,
- double *xdensity, double *ydensity)
+jpeg_get_bbox (FILE *fp, int *width, int *height, double *xdensity, double *ydensity)
{
struct JPEG_info j_info;
diff --git a/Build/source/texk/dvipdfm-x/pdfcolor.c b/Build/source/texk/dvipdfm-x/pdfcolor.c
index eea24abf57b..ee6dac5490d 100644
--- a/Build/source/texk/dvipdfm-x/pdfcolor.c
+++ b/Build/source/texk/dvipdfm-x/pdfcolor.c
@@ -599,7 +599,9 @@ static struct
{0, 0}, /* PDF-1.2, we don't support them */
{0x02, 0x10}, /* PDF-1.3 */
{0x02, 0x20}, /* PDF-1.4 */
- {0x04, 0x00} /* PDF-1.5 */
+ {0x04, 0x00}, /* PDF-1.5 */
+ {0x04, 0x00}, /* PDF-1.6 */
+ {0x04, 0x20}, /* PDF-1.7 */
};
static int
@@ -608,11 +610,11 @@ iccp_version_supported (int major, int minor)
int pdf_ver;
pdf_ver = pdf_get_version();
- if (pdf_ver < 6) {
+ if (pdf_ver < 8) {
if (icc_versions[pdf_ver].major < major)
return 0;
else if (icc_versions[pdf_ver].major == major &&
- icc_versions[pdf_ver].minor < minor)
+ icc_versions[pdf_ver].minor < minor)
return 0;
else {
return 1;