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