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