Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6417 ashmew2 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 		/* to declare isdigit(), isspace() */
18
 
19
 
20
LOCAL(int)
21
text_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
 
37
LOCAL(boolean)
38
read_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
 
72
GLOBAL(boolean)
73
read_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
 
128
LOCAL(boolean)
129
read_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
 
157
GLOBAL(boolean)
158
read_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) {
231
bogus:
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
 
265
GLOBAL(boolean)
266
set_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
 
300
GLOBAL(boolean)
301
set_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
}