Blame gtkmm-osx/jpeg-6b/rdswitch.c

Carlos Lopez a09598
/*
Carlos Lopez a09598
 * rdswitch.c
Carlos Lopez a09598
 *
Carlos Lopez a09598
 * Copyright (C) 1991-1996, Thomas G. Lane.
Carlos Lopez a09598
 * This file is part of the Independent JPEG Group's software.
Carlos Lopez a09598
 * For conditions of distribution and use, see the accompanying README file.
Carlos Lopez a09598
 *
Carlos Lopez a09598
 * This file contains routines to process some of cjpeg's more complicated
Carlos Lopez a09598
 * command-line switches.  Switches processed here are:
Carlos Lopez a09598
 *	-qtables file		Read quantization tables from text file
Carlos Lopez a09598
 *	-scans file		Read scan script from text file
Carlos Lopez a09598
 *	-qslots N[,N,...]	Set component quantization table selectors
Carlos Lopez a09598
 *	-sample HxV[,HxV,...]	Set component sampling factors
Carlos Lopez a09598
 */
Carlos Lopez a09598
Carlos Lopez a09598
#include "cdjpeg.h"		/* Common decls for cjpeg/djpeg applications */
Carlos Lopez a09598
#include <ctype.h>		/* to declare isdigit(), isspace() */</ctype.h>
Carlos Lopez a09598
Carlos Lopez a09598
Carlos Lopez a09598
LOCAL(int)
Carlos Lopez a09598
text_getc (FILE * file)
Carlos Lopez a09598
/* Read next char, skipping over any comments (# to end of line) */
Carlos Lopez a09598
/* A comment/newline sequence is returned as a newline */
Carlos Lopez a09598
{
Carlos Lopez a09598
  register int ch;
Carlos Lopez a09598
  
Carlos Lopez a09598
  ch = getc(file);
Carlos Lopez a09598
  if (ch == '#') {
Carlos Lopez a09598
    do {
Carlos Lopez a09598
      ch = getc(file);
Carlos Lopez a09598
    } while (ch != '\n' && ch != EOF);
Carlos Lopez a09598
  }
Carlos Lopez a09598
  return ch;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
Carlos Lopez a09598
LOCAL(boolean)
Carlos Lopez a09598
read_text_integer (FILE * file, long * result, int * termchar)
Carlos Lopez a09598
/* Read an unsigned decimal integer from a file, store it in result */
Carlos Lopez a09598
/* Reads one trailing character after the integer; returns it in termchar */
Carlos Lopez a09598
{
Carlos Lopez a09598
  register int ch;
Carlos Lopez a09598
  register long val;
Carlos Lopez a09598
  
Carlos Lopez a09598
  /* Skip any leading whitespace, detect EOF */
Carlos Lopez a09598
  do {
Carlos Lopez a09598
    ch = text_getc(file);
Carlos Lopez a09598
    if (ch == EOF) {
Carlos Lopez a09598
      *termchar = ch;
Carlos Lopez a09598
      return FALSE;
Carlos Lopez a09598
    }
Carlos Lopez a09598
  } while (isspace(ch));
Carlos Lopez a09598
  
Carlos Lopez a09598
  if (! isdigit(ch)) {
Carlos Lopez a09598
    *termchar = ch;
Carlos Lopez a09598
    return FALSE;
Carlos Lopez a09598
  }
Carlos Lopez a09598
Carlos Lopez a09598
  val = ch - '0';
Carlos Lopez a09598
  while ((ch = text_getc(file)) != EOF) {
Carlos Lopez a09598
    if (! isdigit(ch))
Carlos Lopez a09598
      break;
Carlos Lopez a09598
    val *= 10;
Carlos Lopez a09598
    val += ch - '0';
Carlos Lopez a09598
  }
Carlos Lopez a09598
  *result = val;
Carlos Lopez a09598
  *termchar = ch;
Carlos Lopez a09598
  return TRUE;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
Carlos Lopez a09598
GLOBAL(boolean)
Carlos Lopez a09598
read_quant_tables (j_compress_ptr cinfo, char * filename,
Carlos Lopez a09598
		   int scale_factor, boolean force_baseline)
Carlos Lopez a09598
/* Read a set of quantization tables from the specified file.
Carlos Lopez a09598
 * The file is plain ASCII text: decimal numbers with whitespace between.
Carlos Lopez a09598
 * Comments preceded by '#' may be included in the file.
Carlos Lopez a09598
 * There may be one to NUM_QUANT_TBLS tables in the file, each of 64 values.
Carlos Lopez a09598
 * The tables are implicitly numbered 0,1,etc.
Carlos Lopez a09598
 * NOTE: does not affect the qslots mapping, which will default to selecting
Carlos Lopez a09598
 * table 0 for luminance (or primary) components, 1 for chrominance components.
Carlos Lopez a09598
 * You must use -qslots if you want a different component->table mapping.
Carlos Lopez a09598
 */
Carlos Lopez a09598
{
Carlos Lopez a09598
  FILE * fp;
Carlos Lopez a09598
  int tblno, i, termchar;
Carlos Lopez a09598
  long val;
Carlos Lopez a09598
  unsigned int table[DCTSIZE2];
Carlos Lopez a09598
Carlos Lopez a09598
  if ((fp = fopen(filename, "r")) == NULL) {
Carlos Lopez a09598
    fprintf(stderr, "Can't open table file %s\n", filename);
Carlos Lopez a09598
    return FALSE;
Carlos Lopez a09598
  }
Carlos Lopez a09598
  tblno = 0;
Carlos Lopez a09598
Carlos Lopez a09598
  while (read_text_integer(fp, &val, &termchar)) { /* read 1st element of table */
Carlos Lopez a09598
    if (tblno >= NUM_QUANT_TBLS) {
Carlos Lopez a09598
      fprintf(stderr, "Too many tables in file %s\n", filename);
Carlos Lopez a09598
      fclose(fp);
Carlos Lopez a09598
      return FALSE;
Carlos Lopez a09598
    }
Carlos Lopez a09598
    table[0] = (unsigned int) val;
Carlos Lopez a09598
    for (i = 1; i < DCTSIZE2; i++) {
Carlos Lopez a09598
      if (! read_text_integer(fp, &val, &termchar)) {
Carlos Lopez a09598
	fprintf(stderr, "Invalid table data in file %s\n", filename);
Carlos Lopez a09598
	fclose(fp);
Carlos Lopez a09598
	return FALSE;
Carlos Lopez a09598
      }
Carlos Lopez a09598
      table[i] = (unsigned int) val;
Carlos Lopez a09598
    }
Carlos Lopez a09598
    jpeg_add_quant_table(cinfo, tblno, table, scale_factor, force_baseline);
Carlos Lopez a09598
    tblno++;
Carlos Lopez a09598
  }
Carlos Lopez a09598
Carlos Lopez a09598
  if (termchar != EOF) {
Carlos Lopez a09598
    fprintf(stderr, "Non-numeric data in file %s\n", filename);
Carlos Lopez a09598
    fclose(fp);
Carlos Lopez a09598
    return FALSE;
Carlos Lopez a09598
  }
Carlos Lopez a09598
Carlos Lopez a09598
  fclose(fp);
Carlos Lopez a09598
  return TRUE;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
Carlos Lopez a09598
#ifdef C_MULTISCAN_FILES_SUPPORTED
Carlos Lopez a09598
Carlos Lopez a09598
LOCAL(boolean)
Carlos Lopez a09598
read_scan_integer (FILE * file, long * result, int * termchar)
Carlos Lopez a09598
/* Variant of read_text_integer that always looks for a non-space termchar;
Carlos Lopez a09598
 * this simplifies parsing of punctuation in scan scripts.
Carlos Lopez a09598
 */
Carlos Lopez a09598
{
Carlos Lopez a09598
  register int ch;
Carlos Lopez a09598
Carlos Lopez a09598
  if (! read_text_integer(file, result, termchar))
Carlos Lopez a09598
    return FALSE;
Carlos Lopez a09598
  ch = *termchar;
Carlos Lopez a09598
  while (ch != EOF && isspace(ch))
Carlos Lopez a09598
    ch = text_getc(file);
Carlos Lopez a09598
  if (isdigit(ch)) {		/* oops, put it back */
Carlos Lopez a09598
    if (ungetc(ch, file) == EOF)
Carlos Lopez a09598
      return FALSE;
Carlos Lopez a09598
    ch = ' ';
Carlos Lopez a09598
  } else {
Carlos Lopez a09598
    /* Any separators other than ';' and ':' are ignored;
Carlos Lopez a09598
     * this allows user to insert commas, etc, if desired.
Carlos Lopez a09598
     */
Carlos Lopez a09598
    if (ch != EOF && ch != ';' && ch != ':')
Carlos Lopez a09598
      ch = ' ';
Carlos Lopez a09598
  }
Carlos Lopez a09598
  *termchar = ch;
Carlos Lopez a09598
  return TRUE;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
Carlos Lopez a09598
GLOBAL(boolean)
Carlos Lopez a09598
read_scan_script (j_compress_ptr cinfo, char * filename)
Carlos Lopez a09598
/* Read a scan script from the specified text file.
Carlos Lopez a09598
 * Each entry in the file defines one scan to be emitted.
Carlos Lopez a09598
 * Entries are separated by semicolons ';'.
Carlos Lopez a09598
 * An entry contains one to four component indexes,
Carlos Lopez a09598
 * optionally followed by a colon ':' and four progressive-JPEG parameters.
Carlos Lopez a09598
 * The component indexes denote which component(s) are to be transmitted
Carlos Lopez a09598
 * in the current scan.  The first component has index 0.
Carlos Lopez a09598
 * Sequential JPEG is used if the progressive-JPEG parameters are omitted.
Carlos Lopez a09598
 * The file is free format text: any whitespace may appear between numbers
Carlos Lopez a09598
 * and the ':' and ';' punctuation marks.  Also, other punctuation (such
Carlos Lopez a09598
 * as commas or dashes) can be placed between numbers if desired.
Carlos Lopez a09598
 * Comments preceded by '#' may be included in the file.
Carlos Lopez a09598
 * Note: we do very little validity checking here;
Carlos Lopez a09598
 * jcmaster.c will validate the script parameters.
Carlos Lopez a09598
 */
Carlos Lopez a09598
{
Carlos Lopez a09598
  FILE * fp;
Carlos Lopez a09598
  int scanno, ncomps, termchar;
Carlos Lopez a09598
  long val;
Carlos Lopez a09598
  jpeg_scan_info * scanptr;
Carlos Lopez a09598
#define MAX_SCANS  100		/* quite arbitrary limit */
Carlos Lopez a09598
  jpeg_scan_info scans[MAX_SCANS];
Carlos Lopez a09598
Carlos Lopez a09598
  if ((fp = fopen(filename, "r")) == NULL) {
Carlos Lopez a09598
    fprintf(stderr, "Can't open scan definition file %s\n", filename);
Carlos Lopez a09598
    return FALSE;
Carlos Lopez a09598
  }
Carlos Lopez a09598
  scanptr = scans;
Carlos Lopez a09598
  scanno = 0;
Carlos Lopez a09598
Carlos Lopez a09598
  while (read_scan_integer(fp, &val, &termchar)) {
Carlos Lopez a09598
    if (scanno >= MAX_SCANS) {
Carlos Lopez a09598
      fprintf(stderr, "Too many scans defined in file %s\n", filename);
Carlos Lopez a09598
      fclose(fp);
Carlos Lopez a09598
      return FALSE;
Carlos Lopez a09598
    }
Carlos Lopez a09598
    scanptr->component_index[0] = (int) val;
Carlos Lopez a09598
    ncomps = 1;
Carlos Lopez a09598
    while (termchar == ' ') {
Carlos Lopez a09598
      if (ncomps >= MAX_COMPS_IN_SCAN) {
Carlos Lopez a09598
	fprintf(stderr, "Too many components in one scan in file %s\n",
Carlos Lopez a09598
		filename);
Carlos Lopez a09598
	fclose(fp);
Carlos Lopez a09598
	return FALSE;
Carlos Lopez a09598
      }
Carlos Lopez a09598
      if (! read_scan_integer(fp, &val, &termchar))
Carlos Lopez a09598
	goto bogus;
Carlos Lopez a09598
      scanptr->component_index[ncomps] = (int) val;
Carlos Lopez a09598
      ncomps++;
Carlos Lopez a09598
    }
Carlos Lopez a09598
    scanptr->comps_in_scan = ncomps;
Carlos Lopez a09598
    if (termchar == ':') {
Carlos Lopez a09598
      if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ')
Carlos Lopez a09598
	goto bogus;
Carlos Lopez a09598
      scanptr->Ss = (int) val;
Carlos Lopez a09598
      if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ')
Carlos Lopez a09598
	goto bogus;
Carlos Lopez a09598
      scanptr->Se = (int) val;
Carlos Lopez a09598
      if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ')
Carlos Lopez a09598
	goto bogus;
Carlos Lopez a09598
      scanptr->Ah = (int) val;
Carlos Lopez a09598
      if (! read_scan_integer(fp, &val, &termchar))
Carlos Lopez a09598
	goto bogus;
Carlos Lopez a09598
      scanptr->Al = (int) val;
Carlos Lopez a09598
    } else {
Carlos Lopez a09598
      /* set non-progressive parameters */
Carlos Lopez a09598
      scanptr->Ss = 0;
Carlos Lopez a09598
      scanptr->Se = DCTSIZE2-1;
Carlos Lopez a09598
      scanptr->Ah = 0;
Carlos Lopez a09598
      scanptr->Al = 0;
Carlos Lopez a09598
    }
Carlos Lopez a09598
    if (termchar != ';' && termchar != EOF) {
Carlos Lopez a09598
bogus:
Carlos Lopez a09598
      fprintf(stderr, "Invalid scan entry format in file %s\n", filename);
Carlos Lopez a09598
      fclose(fp);
Carlos Lopez a09598
      return FALSE;
Carlos Lopez a09598
    }
Carlos Lopez a09598
    scanptr++, scanno++;
Carlos Lopez a09598
  }
Carlos Lopez a09598
Carlos Lopez a09598
  if (termchar != EOF) {
Carlos Lopez a09598
    fprintf(stderr, "Non-numeric data in file %s\n", filename);
Carlos Lopez a09598
    fclose(fp);
Carlos Lopez a09598
    return FALSE;
Carlos Lopez a09598
  }
Carlos Lopez a09598
Carlos Lopez a09598
  if (scanno > 0) {
Carlos Lopez a09598
    /* Stash completed scan list in cinfo structure.
Carlos Lopez a09598
     * NOTE: for cjpeg's use, JPOOL_IMAGE is the right lifetime for this data,
Carlos Lopez a09598
     * but if you want to compress multiple images you'd want JPOOL_PERMANENT.
Carlos Lopez a09598
     */
Carlos Lopez a09598
    scanptr = (jpeg_scan_info *)
Carlos Lopez a09598
      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
Carlos Lopez a09598
				  scanno * SIZEOF(jpeg_scan_info));
Carlos Lopez a09598
    MEMCOPY(scanptr, scans, scanno * SIZEOF(jpeg_scan_info));
Carlos Lopez a09598
    cinfo->scan_info = scanptr;
Carlos Lopez a09598
    cinfo->num_scans = scanno;
Carlos Lopez a09598
  }
Carlos Lopez a09598
Carlos Lopez a09598
  fclose(fp);
Carlos Lopez a09598
  return TRUE;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
#endif /* C_MULTISCAN_FILES_SUPPORTED */
Carlos Lopez a09598
Carlos Lopez a09598
Carlos Lopez a09598
GLOBAL(boolean)
Carlos Lopez a09598
set_quant_slots (j_compress_ptr cinfo, char *arg)
Carlos Lopez a09598
/* Process a quantization-table-selectors parameter string, of the form
Carlos Lopez a09598
 *     N[,N,...]
Carlos Lopez a09598
 * If there are more components than parameters, the last value is replicated.
Carlos Lopez a09598
 */
Carlos Lopez a09598
{
Carlos Lopez a09598
  int val = 0;			/* default table # */
Carlos Lopez a09598
  int ci;
Carlos Lopez a09598
  char ch;
Carlos Lopez a09598
Carlos Lopez a09598
  for (ci = 0; ci < MAX_COMPONENTS; ci++) {
Carlos Lopez a09598
    if (*arg) {
Carlos Lopez a09598
      ch = ',';			/* if not set by sscanf, will be ',' */
Carlos Lopez a09598
      if (sscanf(arg, "%d%c", &val, &ch) < 1)
Carlos Lopez a09598
	return FALSE;
Carlos Lopez a09598
      if (ch != ',')		/* syntax check */
Carlos Lopez a09598
	return FALSE;
Carlos Lopez a09598
      if (val < 0 || val >= NUM_QUANT_TBLS) {
Carlos Lopez a09598
	fprintf(stderr, "JPEG quantization tables are numbered 0..%d\n",
Carlos Lopez a09598
		NUM_QUANT_TBLS-1);
Carlos Lopez a09598
	return FALSE;
Carlos Lopez a09598
      }
Carlos Lopez a09598
      cinfo->comp_info[ci].quant_tbl_no = val;
Carlos Lopez a09598
      while (*arg && *arg++ != ',') /* advance to next segment of arg string */
Carlos Lopez a09598
	;
Carlos Lopez a09598
    } else {
Carlos Lopez a09598
      /* reached end of parameter, set remaining components to last table */
Carlos Lopez a09598
      cinfo->comp_info[ci].quant_tbl_no = val;
Carlos Lopez a09598
    }
Carlos Lopez a09598
  }
Carlos Lopez a09598
  return TRUE;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
Carlos Lopez a09598
GLOBAL(boolean)
Carlos Lopez a09598
set_sample_factors (j_compress_ptr cinfo, char *arg)
Carlos Lopez a09598
/* Process a sample-factors parameter string, of the form
Carlos Lopez a09598
 *     HxV[,HxV,...]
Carlos Lopez a09598
 * If there are more components than parameters, "1x1" is assumed for the rest.
Carlos Lopez a09598
 */
Carlos Lopez a09598
{
Carlos Lopez a09598
  int ci, val1, val2;
Carlos Lopez a09598
  char ch1, ch2;
Carlos Lopez a09598
Carlos Lopez a09598
  for (ci = 0; ci < MAX_COMPONENTS; ci++) {
Carlos Lopez a09598
    if (*arg) {
Carlos Lopez a09598
      ch2 = ',';		/* if not set by sscanf, will be ',' */
Carlos Lopez a09598
      if (sscanf(arg, "%d%c%d%c", &val1, &ch1, &val2, &ch2) < 3)
Carlos Lopez a09598
	return FALSE;
Carlos Lopez a09598
      if ((ch1 != 'x' && ch1 != 'X') || ch2 != ',') /* syntax check */
Carlos Lopez a09598
	return FALSE;
Carlos Lopez a09598
      if (val1 <= 0 || val1 > 4 || val2 <= 0 || val2 > 4) {
Carlos Lopez a09598
	fprintf(stderr, "JPEG sampling factors must be 1..4\n");
Carlos Lopez a09598
	return FALSE;
Carlos Lopez a09598
      }
Carlos Lopez a09598
      cinfo->comp_info[ci].h_samp_factor = val1;
Carlos Lopez a09598
      cinfo->comp_info[ci].v_samp_factor = val2;
Carlos Lopez a09598
      while (*arg && *arg++ != ',') /* advance to next segment of arg string */
Carlos Lopez a09598
	;
Carlos Lopez a09598
    } else {
Carlos Lopez a09598
      /* reached end of parameter, set remaining components to 1x1 sampling */
Carlos Lopez a09598
      cinfo->comp_info[ci].h_samp_factor = 1;
Carlos Lopez a09598
      cinfo->comp_info[ci].v_samp_factor = 1;
Carlos Lopez a09598
    }
Carlos Lopez a09598
  }
Carlos Lopez a09598
  return TRUE;
Carlos Lopez a09598
}