/* The following enum is stolen from the IJG JPEG library
* Comments added by tm
* This table contains far too many names since jpeg2ps
* is rather simple-minded about markers
*/
M_ERROR = 0x100 /* dummy marker, internal use only */
} JPEG_MARKER;
/*
* The following routine used to be a macro in its first incarnation:
* #define get_2bytes(fp) ((unsigned int) (getc(fp) << 8) + getc(fp))
* However, this is bad programming since C doesn't guarantee
* the evaluation order of the getc() calls! As suggested by
* Murphy's law, there are indeed compilers which produce the wrong
* order of the getc() calls, e.g. the Metrowerks C compilers for BeOS
* and Macintosh.
* Since there are only few calls we don't care about the performance
* penalty and use a simplistic C function.
*/
/* read two byte parameter, MSB first */
static unsigned int
get_2bytes(FILE *fp)
{
unsigned int val;
val = getc(fp) << 8;
val += getc(fp);
return val;
}
static int
next_marker P1(FILE *, fp)
{ /* look for next JPEG Marker */
int c, nbytes = 0;
if (feof(fp))
return M_ERROR; /* dummy marker */
do {
do { /* skip to FF */
nbytes++;
c = getc(fp);
} while (c != 0xFF);
do { /* skip repeated FFs */
c = getc(fp);
} while (c == 0xFF);
} while (c == 0); /* repeat if FF/00 */
/* Tommy's special trick for Macintosh JPEGs: simply skip some */
/* hundred bytes at the beginning of the file! */
do {
do { /* skip if not FF */
c = getc(image->fp);
} while (!feof(image->fp) && c != 0xFF);
do { /* skip repeated FFs */
c = getc(image->fp);
} while (c == 0xFF);
/* remember start position */
if ((image->startpos = ftell(image->fp)) < 0L) {
fprintf(stderr, "Error: internal error in ftell()!\n");
return FALSE;
}
image->startpos -= 2; /* subtract marker length */
if (c == M_SOI) {
fseek(image->fp, image->startpos, SEEK_SET);
break;
}
} while (!feof(image->fp));
if (feof(image->fp)) {
fprintf(stderr, "Error: SOI marker not found!\n");
return FALSE;
}
if (image->startpos > 0L && !quiet) {
fprintf(stderr, "Note: skipped %ld bytes ", image->startpos);
fprintf(stderr, "Probably Macintosh JPEG file?\n");
}
/* process JPEG markers */
while (!SOF_done && (c = next_marker(image->fp)) != M_EOI) {
switch (c) {
case M_ERROR:
fprintf(stderr, "Error: unexpected end of JPEG file!\n");
return FALSE;
/* The following are not officially supported in PostScript level 2 */
case M_SOF2:
case M_SOF3:
case M_SOF5:
case M_SOF6:
case M_SOF7:
case M_SOF9:
case M_SOF10:
case M_SOF11:
case M_SOF13:
case M_SOF14:
case M_SOF15:
fprintf(stderr,
"Warning: JPEG file uses compression method %X - proceeding anyway.\n",
c);
fprintf(stderr,
"PostScript output does not work on all PS interpreters!\n");
/* FALLTHROUGH */
case M_SOF0:
case M_SOF1:
length = get_2bytes(image->fp); /* read segment length */
case M_APP0: /* check for JFIF marker with resolution */
length = get_2bytes(image->fp);
for (i = 0; i < length-2; i++) { /* get contents of marker */
b = getc(image->fp);
if (i < APP_MAX) /* store marker in appstring */
appstring[i] = b;
}
/* Check for JFIF application marker and read density values
* per JFIF spec version 1.02.
* We only check X resolution, assuming X and Y resolution are equal.
* Use values only if resolution not preset by user or to be ignored.
*/
#define ASPECT_RATIO 0 /* JFIF unit byte: aspect ratio only */
#define DOTS_PER_INCH 1 /* JFIF unit byte: dots per inch */
#define DOTS_PER_CM 2 /* JFIF unit byte: dots per cm */
if (image->dpi == DPI_USE_FILE && length >= 14 &&
!strncmp((const char *)appstring, "JFIF", 4)) {
unit = appstring[7]; /* resolution unit */
/* resolution value */
image->dpi = (float) ((appstring[8]<<8) + appstring[9]);
if (image->dpi == 0.0) {
image->dpi = DPI_USE_FILE;
break;
}
switch (unit) {
/* tell the caller we didn't find a resolution value */
case ASPECT_RATIO:
image->dpi = DPI_USE_FILE;
break;
case DOTS_PER_INCH:
break;
case DOTS_PER_CM:
image->dpi *= (float) 2.54;
break;
case M_APP14: /* check for Adobe marker */
length = get_2bytes(image->fp);
for (i = 0; i < length-2; i++) { /* get contents of marker */
b = getc(image->fp);
if (i < APP_MAX) /* store marker in appstring */
appstring[i] = b;
}
/* Check for Adobe application marker. It is known (per Adobe's TN5116)
* to contain the string "Adobe" at the start of the APP14 marker.
*/
if (length >= 12 && !strncmp((const char *) appstring, "Adobe", 5))
image->adobe = TRUE; /* set Adobe flag */
break;
case M_SOI: /* ignore markers without parameters */
case M_EOI:
case M_TEM:
case M_RST0:
case M_RST1:
case M_RST2:
case M_RST3:
case M_RST4:
case M_RST5:
case M_RST6:
case M_RST7:
break;
/* do some sanity checks with the parameters */
if (image->height <= 0 || image->width <= 0 || image->components <= 0) {
fprintf(stderr, "Error: DNL marker not supported in PostScript Level 2!\n");
return FALSE;
}
/* some broken JPEG files have this but they print anyway... */
if (length != (unsigned int) (image->components * 3 + 8))
fprintf(stderr, "Warning: SOF marker has incorrect length - ignored!\n");
if (image->bits_per_component != 8) {
fprintf(stderr, "Error: %d bits per color component ",
image->bits_per_component);
fprintf(stderr, "not supported in PostScript level 2!\n");
return FALSE;
}
if (image->components!=1 && image->components!=3 && image->components!=4) {
fprintf(stderr, "Error: unknown color space (%d components)!\n",
image->components);
return FALSE;
}