source: trunk/third/jpeg/rdswitch.c @ 15227

Revision 15227, 9.4 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r15226, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * rdswitch.c
3 *
4 * Copyright (C) 1991-1996, Thomas G. Lane.
5 * This file is part of the Independent JPEG Group's software.
6 * For conditions of distribution and use, see the accompanying README file.
7 *
8 * This file contains routines to process some of cjpeg's more complicated
9 * command-line switches.  Switches processed here are:
10 *      -qtables file           Read quantization tables from text file
11 *      -scans file             Read scan script from text file
12 *      -qslots N[,N,...]       Set component quantization table selectors
13 *      -sample HxV[,HxV,...]   Set component sampling factors
14 */
15
16#include "cdjpeg.h"             /* Common decls for cjpeg/djpeg applications */
17#include <ctype.h>              /* to declare isdigit(), isspace() */
18
19
20LOCAL(int)
21text_getc (FILE * file)
22/* Read next char, skipping over any comments (# to end of line) */
23/* A comment/newline sequence is returned as a newline */
24{
25  register int ch;
26 
27  ch = getc(file);
28  if (ch == '#') {
29    do {
30      ch = getc(file);
31    } while (ch != '\n' && ch != EOF);
32  }
33  return ch;
34}
35
36
37LOCAL(boolean)
38read_text_integer (FILE * file, long * result, int * termchar)
39/* Read an unsigned decimal integer from a file, store it in result */
40/* Reads one trailing character after the integer; returns it in termchar */
41{
42  register int ch;
43  register long val;
44 
45  /* Skip any leading whitespace, detect EOF */
46  do {
47    ch = text_getc(file);
48    if (ch == EOF) {
49      *termchar = ch;
50      return FALSE;
51    }
52  } while (isspace(ch));
53 
54  if (! isdigit(ch)) {
55    *termchar = ch;
56    return FALSE;
57  }
58
59  val = ch - '0';
60  while ((ch = text_getc(file)) != EOF) {
61    if (! isdigit(ch))
62      break;
63    val *= 10;
64    val += ch - '0';
65  }
66  *result = val;
67  *termchar = ch;
68  return TRUE;
69}
70
71
72GLOBAL(boolean)
73read_quant_tables (j_compress_ptr cinfo, char * filename,
74                   int scale_factor, boolean force_baseline)
75/* Read a set of quantization tables from the specified file.
76 * The file is plain ASCII text: decimal numbers with whitespace between.
77 * Comments preceded by '#' may be included in the file.
78 * There may be one to NUM_QUANT_TBLS tables in the file, each of 64 values.
79 * The tables are implicitly numbered 0,1,etc.
80 * NOTE: does not affect the qslots mapping, which will default to selecting
81 * table 0 for luminance (or primary) components, 1 for chrominance components.
82 * You must use -qslots if you want a different component->table mapping.
83 */
84{
85  FILE * fp;
86  int tblno, i, termchar;
87  long val;
88  unsigned int table[DCTSIZE2];
89
90  if ((fp = fopen(filename, "r")) == NULL) {
91    fprintf(stderr, "Can't open table file %s\n", filename);
92    return FALSE;
93  }
94  tblno = 0;
95
96  while (read_text_integer(fp, &val, &termchar)) { /* read 1st element of table */
97    if (tblno >= NUM_QUANT_TBLS) {
98      fprintf(stderr, "Too many tables in file %s\n", filename);
99      fclose(fp);
100      return FALSE;
101    }
102    table[0] = (unsigned int) val;
103    for (i = 1; i < DCTSIZE2; i++) {
104      if (! read_text_integer(fp, &val, &termchar)) {
105        fprintf(stderr, "Invalid table data in file %s\n", filename);
106        fclose(fp);
107        return FALSE;
108      }
109      table[i] = (unsigned int) val;
110    }
111    jpeg_add_quant_table(cinfo, tblno, table, scale_factor, force_baseline);
112    tblno++;
113  }
114
115  if (termchar != EOF) {
116    fprintf(stderr, "Non-numeric data in file %s\n", filename);
117    fclose(fp);
118    return FALSE;
119  }
120
121  fclose(fp);
122  return TRUE;
123}
124
125
126#ifdef C_MULTISCAN_FILES_SUPPORTED
127
128LOCAL(boolean)
129read_scan_integer (FILE * file, long * result, int * termchar)
130/* Variant of read_text_integer that always looks for a non-space termchar;
131 * this simplifies parsing of punctuation in scan scripts.
132 */
133{
134  register int ch;
135
136  if (! read_text_integer(file, result, termchar))
137    return FALSE;
138  ch = *termchar;
139  while (ch != EOF && isspace(ch))
140    ch = text_getc(file);
141  if (isdigit(ch)) {            /* oops, put it back */
142    if (ungetc(ch, file) == EOF)
143      return FALSE;
144    ch = ' ';
145  } else {
146    /* Any separators other than ';' and ':' are ignored;
147     * this allows user to insert commas, etc, if desired.
148     */
149    if (ch != EOF && ch != ';' && ch != ':')
150      ch = ' ';
151  }
152  *termchar = ch;
153  return TRUE;
154}
155
156
157GLOBAL(boolean)
158read_scan_script (j_compress_ptr cinfo, char * filename)
159/* Read a scan script from the specified text file.
160 * Each entry in the file defines one scan to be emitted.
161 * Entries are separated by semicolons ';'.
162 * An entry contains one to four component indexes,
163 * optionally followed by a colon ':' and four progressive-JPEG parameters.
164 * The component indexes denote which component(s) are to be transmitted
165 * in the current scan.  The first component has index 0.
166 * Sequential JPEG is used if the progressive-JPEG parameters are omitted.
167 * The file is free format text: any whitespace may appear between numbers
168 * and the ':' and ';' punctuation marks.  Also, other punctuation (such
169 * as commas or dashes) can be placed between numbers if desired.
170 * Comments preceded by '#' may be included in the file.
171 * Note: we do very little validity checking here;
172 * jcmaster.c will validate the script parameters.
173 */
174{
175  FILE * fp;
176  int scanno, ncomps, termchar;
177  long val;
178  jpeg_scan_info * scanptr;
179#define MAX_SCANS  100          /* quite arbitrary limit */
180  jpeg_scan_info scans[MAX_SCANS];
181
182  if ((fp = fopen(filename, "r")) == NULL) {
183    fprintf(stderr, "Can't open scan definition file %s\n", filename);
184    return FALSE;
185  }
186  scanptr = scans;
187  scanno = 0;
188
189  while (read_scan_integer(fp, &val, &termchar)) {
190    if (scanno >= MAX_SCANS) {
191      fprintf(stderr, "Too many scans defined in file %s\n", filename);
192      fclose(fp);
193      return FALSE;
194    }
195    scanptr->component_index[0] = (int) val;
196    ncomps = 1;
197    while (termchar == ' ') {
198      if (ncomps >= MAX_COMPS_IN_SCAN) {
199        fprintf(stderr, "Too many components in one scan in file %s\n",
200                filename);
201        fclose(fp);
202        return FALSE;
203      }
204      if (! read_scan_integer(fp, &val, &termchar))
205        goto bogus;
206      scanptr->component_index[ncomps] = (int) val;
207      ncomps++;
208    }
209    scanptr->comps_in_scan = ncomps;
210    if (termchar == ':') {
211      if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ')
212        goto bogus;
213      scanptr->Ss = (int) val;
214      if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ')
215        goto bogus;
216      scanptr->Se = (int) val;
217      if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ')
218        goto bogus;
219      scanptr->Ah = (int) val;
220      if (! read_scan_integer(fp, &val, &termchar))
221        goto bogus;
222      scanptr->Al = (int) val;
223    } else {
224      /* set non-progressive parameters */
225      scanptr->Ss = 0;
226      scanptr->Se = DCTSIZE2-1;
227      scanptr->Ah = 0;
228      scanptr->Al = 0;
229    }
230    if (termchar != ';' && termchar != EOF) {
231bogus:
232      fprintf(stderr, "Invalid scan entry format in file %s\n", filename);
233      fclose(fp);
234      return FALSE;
235    }
236    scanptr++, scanno++;
237  }
238
239  if (termchar != EOF) {
240    fprintf(stderr, "Non-numeric data in file %s\n", filename);
241    fclose(fp);
242    return FALSE;
243  }
244
245  if (scanno > 0) {
246    /* Stash completed scan list in cinfo structure.
247     * NOTE: for cjpeg's use, JPOOL_IMAGE is the right lifetime for this data,
248     * but if you want to compress multiple images you'd want JPOOL_PERMANENT.
249     */
250    scanptr = (jpeg_scan_info *)
251      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
252                                  scanno * SIZEOF(jpeg_scan_info));
253    MEMCOPY(scanptr, scans, scanno * SIZEOF(jpeg_scan_info));
254    cinfo->scan_info = scanptr;
255    cinfo->num_scans = scanno;
256  }
257
258  fclose(fp);
259  return TRUE;
260}
261
262#endif /* C_MULTISCAN_FILES_SUPPORTED */
263
264
265GLOBAL(boolean)
266set_quant_slots (j_compress_ptr cinfo, char *arg)
267/* Process a quantization-table-selectors parameter string, of the form
268 *     N[,N,...]
269 * If there are more components than parameters, the last value is replicated.
270 */
271{
272  int val = 0;                  /* default table # */
273  int ci;
274  char ch;
275
276  for (ci = 0; ci < MAX_COMPONENTS; ci++) {
277    if (*arg) {
278      ch = ',';                 /* if not set by sscanf, will be ',' */
279      if (sscanf(arg, "%d%c", &val, &ch) < 1)
280        return FALSE;
281      if (ch != ',')            /* syntax check */
282        return FALSE;
283      if (val < 0 || val >= NUM_QUANT_TBLS) {
284        fprintf(stderr, "JPEG quantization tables are numbered 0..%d\n",
285                NUM_QUANT_TBLS-1);
286        return FALSE;
287      }
288      cinfo->comp_info[ci].quant_tbl_no = val;
289      while (*arg && *arg++ != ',') /* advance to next segment of arg string */
290        ;
291    } else {
292      /* reached end of parameter, set remaining components to last table */
293      cinfo->comp_info[ci].quant_tbl_no = val;
294    }
295  }
296  return TRUE;
297}
298
299
300GLOBAL(boolean)
301set_sample_factors (j_compress_ptr cinfo, char *arg)
302/* Process a sample-factors parameter string, of the form
303 *     HxV[,HxV,...]
304 * If there are more components than parameters, "1x1" is assumed for the rest.
305 */
306{
307  int ci, val1, val2;
308  char ch1, ch2;
309
310  for (ci = 0; ci < MAX_COMPONENTS; ci++) {
311    if (*arg) {
312      ch2 = ',';                /* if not set by sscanf, will be ',' */
313      if (sscanf(arg, "%d%c%d%c", &val1, &ch1, &val2, &ch2) < 3)
314        return FALSE;
315      if ((ch1 != 'x' && ch1 != 'X') || ch2 != ',') /* syntax check */
316        return FALSE;
317      if (val1 <= 0 || val1 > 4 || val2 <= 0 || val2 > 4) {
318        fprintf(stderr, "JPEG sampling factors must be 1..4\n");
319        return FALSE;
320      }
321      cinfo->comp_info[ci].h_samp_factor = val1;
322      cinfo->comp_info[ci].v_samp_factor = val2;
323      while (*arg && *arg++ != ',') /* advance to next segment of arg string */
324        ;
325    } else {
326      /* reached end of parameter, set remaining components to 1x1 sampling */
327      cinfo->comp_info[ci].h_samp_factor = 1;
328      cinfo->comp_info[ci].v_samp_factor = 1;
329    }
330  }
331  return TRUE;
332}
Note: See TracBrowser for help on using the repository browser.