Beispiel #1
0
static int
scan_JPEG_header (int verbose)
{
  int marker;

  /* Expect SOI at start of file */
  if (first_marker() != M_SOI)
    ERREXIT("Expected SOI marker first");

  /* Scan miscellaneous markers until we reach SOS. */
  for (;;) {
    marker = next_marker();
    switch (marker) {
    case M_SOF0:		/* Baseline */
    case M_SOF1:		/* Extended sequential, Huffman */
    case M_SOF2:		/* Progressive, Huffman */
    case M_SOF3:		/* Lossless, Huffman */
    case M_SOF5:		/* Differential sequential, Huffman */
    case M_SOF6:		/* Differential progressive, Huffman */
    case M_SOF7:		/* Differential lossless, Huffman */
    case M_SOF9:		/* Extended sequential, arithmetic */
    case M_SOF10:		/* Progressive, arithmetic */
    case M_SOF11:		/* Lossless, arithmetic */
    case M_SOF13:		/* Differential sequential, arithmetic */
    case M_SOF14:		/* Differential progressive, arithmetic */
    case M_SOF15:		/* Differential lossless, arithmetic */
      if (verbose)
	process_SOFn(marker);
      else
	skip_variable();
      break;

    case M_SOS:			/* stop before hitting compressed data */
      return marker;

    case M_EOI:			/* in case it's a tables-only JPEG stream */
      return marker;

    case M_COM:
      process_COM();
      break;

    default:			/* Anything else just gets skipped */
      skip_variable();		/* we assume it has a parameter count... */
      break;
    }
  } /* end loop */
}
Beispiel #2
0
static int get_jpeg_image_dimensions(ImageSize *is, int *width, int *height)
{
	int marker = -1, jpeg_ok = 0;

	*width = *height = -1;

	if (is->infile || !is->file) {
		/* Expect SOI at start of file */
		if (first_marker(is) == M_SOI) {
			jpeg_ok = 1;
			/* Scan miscellaneous markers until we reach SOS. */
			for (; marker != M_SOS && marker != M_EOI; ) {
				marker = next_marker(is);
				switch (marker) {
				/* Note that marker codes 0xC4, 0xC8, 0xCC are not, and must not be,
				 * treated as SOFn.  C4 in particular is actually DHT.
				 */
				case M_SOF0:		/* Baseline */
				case M_SOF1:		/* Extended sequential, Huffman */
				case M_SOF2:		/* Progressive, Huffman */
				case M_SOF3:		/* Lossless, Huffman */
				case M_SOF5:		/* Differential sequential, Huffman */
				case M_SOF6:		/* Differential progressive, Huffman */
				case M_SOF7:		/* Differential lossless, Huffman */
				case M_SOF9:		/* Extended sequential, arithmetic */
				case M_SOF10:		/* Progressive, arithmetic */
				case M_SOF11:		/* Lossless, arithmetic */
				case M_SOF13:		/* Differential sequential, arithmetic */
				case M_SOF14:		/* Differential progressive, arithmetic */
				case M_SOF15:		/* Differential lossless, arithmetic */
					get_image_dimensions(is, width, height);
					break;
				default:			/* Anything else just gets skipped */
					if (skip_variable(is) < 0)
						return -1;
					break;
				}
			}
		}
	}
	return jpeg_ok;
}
Beispiel #3
0
static int
scan_JPEG_header (int verbose)
{
  int marker;

  /* Expect SOI at start of file */
  if (first_marker() != M_SOI)
    ERREXIT("Expected SOI marker first");

  /* Scan miscellaneous markers until we reach SOS. */
  for (;;) {
    marker = next_marker();
    switch (marker) {
      /* Note that marker codes 0xC4, 0xC8, 0xCC are not, and must not be,
       * treated as SOFn.  C4 in particular is actually DHT.
       */
    case M_SOF0:		/* Baseline */
    case M_SOF1:		/* Extended sequential, Huffman */
    case M_SOF2:		/* Progressive, Huffman */
    case M_SOF3:		/* Lossless, Huffman */
    case M_SOF5:		/* Differential sequential, Huffman */
    case M_SOF6:		/* Differential progressive, Huffman */
    case M_SOF7:		/* Differential lossless, Huffman */
    case M_SOF9:		/* Extended sequential, arithmetic */
    case M_SOF10:		/* Progressive, arithmetic */
    case M_SOF11:		/* Lossless, arithmetic */
    case M_SOF13:		/* Differential sequential, arithmetic */
    case M_SOF14:		/* Differential progressive, arithmetic */
    case M_SOF15:		/* Differential lossless, arithmetic */
      if (verbose)
	process_SOFn(marker);
      else
	skip_variable();
      break;

    case M_SOS:			/* stop before hitting compressed data */
      return marker;

    case M_EOI:			/* in case it's a tables-only JPEG stream */
      return marker;

    case M_COM:
      process_COM();
      break;

    case M_APP12:
      /* Some digital camera makers put useful textual information into
       * APP12 markers, so we print those out too when in -verbose mode.
       */
      if (verbose) {
	printf("APP12 contains:\n");
	process_COM();
      } else
	skip_variable();
      break;

    default:			/* Anything else just gets skipped */
      skip_variable();		/* we assume it has a parameter count... */
      break;
    }
  } /* end loop */
}
Beispiel #4
0
/** Read image info
 * @param info	the information structure
 * @param comm	(output) pointer to the comment structure (optional)
 * @param file	the file pointer to the image
 * @return	NULL on success, error message on failure
 */
const char*
readinfo (struct imageinfo* info,
	  struct comment** comm,
	  FILE* file)
{
  memset (info, 0, sizeof *info);
  if (read_word (file) != 0xffd8)
    return "not a JPEG image file";
  /* scan markers until SOS */
  for (;;) {
    unsigned length;
    int marker = next_marker (file);
    if (marker == EOF) {
    eof:
      return "premature end of file";
    }
    if ((marker & 0xf0) == 0xc0 &&
	marker != 0xc4 && marker != 0xcc) {
      /* start of frame marker (image dimensions) */
      /** number of colour components */
      int c;
      length = read_word (file);
      if (length < 2)
	goto invalid_length;
      (void) getc (file); /* skip data precision */
      info->height = read_word (file);
      info->width = read_word (file);
      c = getc (file);
      if (c == EOF)
	goto eof;
      if (length != (8 + ((unsigned) c) * 3))
	return "inconsistent SOF marker length";
      while (c--)
	if (getc (file) == EOF /* component ID code */ ||
	    getc (file) == EOF /* sampling factors */ ||
	    getc (file) == EOF /* quantization table number */)
	  goto eof;
      continue;
    }
    else switch (marker) {
    case 0xfe:
      if (!comm)
	goto skip_marker;
      /* comment */
      length = read_word (file);
      if (length < 2)
	goto invalid_length;
      else {
	/* read the image comment */
	struct comment* comment = malloc (length + sizeof *comment);
	if (!comment)
	  return "out of memory";
	length -= 2;
	comment->next = 0;
	if (length != fread (comment->text, 1, length, file)) {
	  free (comment);
	  goto eof;
	}
	comment->text[length] = 0;
	/* append the comment to the list */
	if (!*comm)
	  *comm = comment;
	else {
	  struct comment* c;
	  for (c = *comm; c->next; c = c->next);
	  c->next = comment;
	}
      }
      continue;
    case 0xda: /* start of scan (compressed data) */
    case 0xd9: /* end of image */
      return 0;
    }
    if (feof (file))
      goto eof;
  skip_marker:
    /* skip the rest of the marker */
    length = read_word (file);
    if (length < 2) {
    invalid_length:
      return "erroneous JPEG marker length";
    }
    length -= 2;
    while (length--)
      if (getc (file) == EOF)
	goto eof;
  }
}
/* analyze JPEG marker */
BOOL AnalyzeJPEG P1(imagedata *, image) {
  int b, c, unit;
  unsigned long i, length = 0;
#define APP_MAX 255
  unsigned char appstring[APP_MAX];
  BOOL SOF_done = FALSE;

  /* 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  */

	image->bits_per_component = getc(image->fp);
	image->height             = get_2bytes(image->fp);
	image->width              = get_2bytes(image->fp);
	image->components         = getc(image->fp);

	SOF_done = TRUE;
	break;

      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;

	    default:				/* unknown ==> ignore */
	      fprintf(stderr, 
		"Warning: JPEG file contains unknown JFIF resolution unit - ignored!\n");
	      image->dpi = DPI_IGNORE;
	      break;
	  }
	}
        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;

      default:			/* skip variable length markers */
	length = get_2bytes(image->fp);
	for (length -= 2; length > 0; length--)
	  (void) getc(image->fp);
	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;
  }

  return TRUE;
}