Visualization Library 2.0.0-b5

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
jpegtran.c
Go to the documentation of this file.
1 /*
2  * jpegtran.c
3  *
4  * Copyright (C) 1995-1997, 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 a command-line user interface for JPEG transcoding.
9  * It is very similar to cjpeg.c, but provides lossless transcoding between
10  * different JPEG file formats. It also provides some lossless and sort-of-
11  * lossless transformations of JPEG data.
12  */
13 
14 #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
15 #include "transupp.h" /* Support routines for jpegtran */
16 #include "jversion.h" /* for version message */
17 
18 #ifdef USE_CCOMMAND /* command-line reader for Macintosh */
19 #ifdef __MWERKS__
20 #include <SIOUX.h> /* Metrowerks needs this */
21 #include <console.h> /* ... and this */
22 #endif
23 #ifdef THINK_C
24 #include <console.h> /* Think declares it here */
25 #endif
26 #endif
27 
28 
29 /*
30  * Argument-parsing code.
31  * The switch parser is designed to be useful with DOS-style command line
32  * syntax, ie, intermixed switches and file names, where only the switches
33  * to the left of a given file name affect processing of that file.
34  * The main program in this file doesn't actually use this capability...
35  */
36 
37 
38 static const char * progname; /* program name for error messages */
39 static char * outfilename; /* for -outfile switch */
40 static JCOPY_OPTION copyoption; /* -copy switch */
41 static jpeg_transform_info transformoption; /* image transformation options */
42 
43 
44 LOCAL(void)
45 usage (void)
46 /* complain about bad command line */
47 {
48  fprintf(stderr, "usage: %s [switches] ", progname);
49 #ifdef TWO_FILE_COMMANDLINE
50  fprintf(stderr, "inputfile outputfile\n");
51 #else
52  fprintf(stderr, "[inputfile]\n");
53 #endif
54 
55  fprintf(stderr, "Switches (names may be abbreviated):\n");
56  fprintf(stderr, " -copy none Copy no extra markers from source file\n");
57  fprintf(stderr, " -copy comments Copy only comment markers (default)\n");
58  fprintf(stderr, " -copy all Copy all extra markers\n");
59 #ifdef ENTROPY_OPT_SUPPORTED
60  fprintf(stderr, " -optimize Optimize Huffman table (smaller file, but slow compression)\n");
61 #endif
62 #ifdef C_PROGRESSIVE_SUPPORTED
63  fprintf(stderr, " -progressive Create progressive JPEG file\n");
64 #endif
65 #if TRANSFORMS_SUPPORTED
66  fprintf(stderr, "Switches for modifying the image:\n");
67  fprintf(stderr, " -grayscale Reduce to grayscale (omit color data)\n");
68  fprintf(stderr, " -flip [horizontal|vertical] Mirror image (left-right or top-bottom)\n");
69  fprintf(stderr, " -rotate [90|180|270] Rotate image (degrees clockwise)\n");
70  fprintf(stderr, " -transpose Transpose image\n");
71  fprintf(stderr, " -transverse Transverse transpose image\n");
72  fprintf(stderr, " -trim Drop non-transformable edge blocks\n");
73 #endif /* TRANSFORMS_SUPPORTED */
74  fprintf(stderr, "Switches for advanced users:\n");
75  fprintf(stderr, " -restart N Set restart interval in rows, or in blocks with B\n");
76  fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n");
77  fprintf(stderr, " -outfile name Specify name for output file\n");
78  fprintf(stderr, " -verbose or -debug Emit debug output\n");
79  fprintf(stderr, "Switches for wizards:\n");
80 #ifdef C_ARITH_CODING_SUPPORTED
81  fprintf(stderr, " -arithmetic Use arithmetic coding\n");
82 #endif
83 #ifdef C_MULTISCAN_FILES_SUPPORTED
84  fprintf(stderr, " -scans file Create multi-scan JPEG per script file\n");
85 #endif
86  exit(EXIT_FAILURE);
87 }
88 
89 
90 LOCAL(void)
92 /* Silly little routine to detect multiple transform options,
93  * which we can't handle.
94  */
95 {
96 #if TRANSFORMS_SUPPORTED
97  if (transformoption.transform == JXFORM_NONE ||
98  transformoption.transform == transform) {
99  transformoption.transform = transform;
100  } else {
101  fprintf(stderr, "%s: can only do one image transformation at a time\n",
102  progname);
103  usage();
104  }
105 #else
106  fprintf(stderr, "%s: sorry, image transformation was not compiled\n",
107  progname);
108  exit(EXIT_FAILURE);
109 #endif
110 }
111 
112 
113 LOCAL(int)
114 parse_switches (j_compress_ptr cinfo, int argc, char **argv,
115  int last_file_arg_seen, boolean for_real)
116 /* Parse optional switches.
117  * Returns argv[] index of first file-name argument (== argc if none).
118  * Any file names with indexes <= last_file_arg_seen are ignored;
119  * they have presumably been processed in a previous iteration.
120  * (Pass 0 for last_file_arg_seen on the first or only iteration.)
121  * for_real is FALSE on the first (dummy) pass; we may skip any expensive
122  * processing.
123  */
124 {
125  int argn;
126  char * arg;
127  boolean simple_progressive;
128  char * scansarg = NULL; /* saves -scans parm if any */
129 
130  /* Set up default JPEG parameters. */
131  simple_progressive = FALSE;
132  outfilename = NULL;
133  copyoption = JCOPYOPT_DEFAULT;
134  transformoption.transform = JXFORM_NONE;
135  transformoption.trim = FALSE;
136  transformoption.force_grayscale = FALSE;
137  cinfo->err->trace_level = 0;
138 
139  /* Scan command line options, adjust parameters */
140 
141  for (argn = 1; argn < argc; argn++) {
142  arg = argv[argn];
143  if (*arg != '-') {
144  /* Not a switch, must be a file name argument */
145  if (argn <= last_file_arg_seen) {
146  outfilename = NULL; /* -outfile applies to just one input file */
147  continue; /* ignore this name if previously processed */
148  }
149  break; /* else done parsing switches */
150  }
151  arg++; /* advance past switch marker character */
152 
153  if (keymatch(arg, "arithmetic", 1)) {
154  /* Use arithmetic coding. */
155 #ifdef C_ARITH_CODING_SUPPORTED
156  cinfo->arith_code = TRUE;
157 #else
158  fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
159  progname);
160  exit(EXIT_FAILURE);
161 #endif
162 
163  } else if (keymatch(arg, "copy", 1)) {
164  /* Select which extra markers to copy. */
165  if (++argn >= argc) /* advance to next argument */
166  usage();
167  if (keymatch(argv[argn], "none", 1)) {
168  copyoption = JCOPYOPT_NONE;
169  } else if (keymatch(argv[argn], "comments", 1)) {
170  copyoption = JCOPYOPT_COMMENTS;
171  } else if (keymatch(argv[argn], "all", 1)) {
172  copyoption = JCOPYOPT_ALL;
173  } else
174  usage();
175 
176  } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
177  /* Enable debug printouts. */
178  /* On first -d, print version identification */
179  static boolean printed_version = FALSE;
180 
181  if (! printed_version) {
182  fprintf(stderr, "Independent JPEG Group's JPEGTRAN, version %s\n%s\n",
184  printed_version = TRUE;
185  }
186  cinfo->err->trace_level++;
187 
188  } else if (keymatch(arg, "flip", 1)) {
189  /* Mirror left-right or top-bottom. */
190  if (++argn >= argc) /* advance to next argument */
191  usage();
192  if (keymatch(argv[argn], "horizontal", 1))
194  else if (keymatch(argv[argn], "vertical", 1))
196  else
197  usage();
198 
199  } else if (keymatch(arg, "grayscale", 1) || keymatch(arg, "greyscale",1)) {
200  /* Force to grayscale. */
201 #if TRANSFORMS_SUPPORTED
202  transformoption.force_grayscale = TRUE;
203 #else
204  select_transform(JXFORM_NONE); /* force an error */
205 #endif
206 
207  } else if (keymatch(arg, "maxmemory", 3)) {
208  /* Maximum memory in Kb (or Mb with 'm'). */
209  long lval;
210  char ch = 'x';
211 
212  if (++argn >= argc) /* advance to next argument */
213  usage();
214  if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
215  usage();
216  if (ch == 'm' || ch == 'M')
217  lval *= 1000L;
218  cinfo->mem->max_memory_to_use = lval * 1000L;
219 
220  } else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) {
221  /* Enable entropy parm optimization. */
222 #ifdef ENTROPY_OPT_SUPPORTED
223  cinfo->optimize_coding = TRUE;
224 #else
225  fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n",
226  progname);
227  exit(EXIT_FAILURE);
228 #endif
229 
230  } else if (keymatch(arg, "outfile", 4)) {
231  /* Set output file name. */
232  if (++argn >= argc) /* advance to next argument */
233  usage();
234  outfilename = argv[argn]; /* save it away for later use */
235 
236  } else if (keymatch(arg, "progressive", 1)) {
237  /* Select simple progressive mode. */
238 #ifdef C_PROGRESSIVE_SUPPORTED
239  simple_progressive = TRUE;
240  /* We must postpone execution until num_components is known. */
241 #else
242  fprintf(stderr, "%s: sorry, progressive output was not compiled\n",
243  progname);
244  exit(EXIT_FAILURE);
245 #endif
246 
247  } else if (keymatch(arg, "restart", 1)) {
248  /* Restart interval in MCU rows (or in MCUs with 'b'). */
249  long lval;
250  char ch = 'x';
251 
252  if (++argn >= argc) /* advance to next argument */
253  usage();
254  if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
255  usage();
256  if (lval < 0 || lval > 65535L)
257  usage();
258  if (ch == 'b' || ch == 'B') {
259  cinfo->restart_interval = (unsigned int) lval;
260  cinfo->restart_in_rows = 0; /* else prior '-restart n' overrides me */
261  } else {
262  cinfo->restart_in_rows = (int) lval;
263  /* restart_interval will be computed during startup */
264  }
265 
266  } else if (keymatch(arg, "rotate", 2)) {
267  /* Rotate 90, 180, or 270 degrees (measured clockwise). */
268  if (++argn >= argc) /* advance to next argument */
269  usage();
270  if (keymatch(argv[argn], "90", 2))
272  else if (keymatch(argv[argn], "180", 3))
274  else if (keymatch(argv[argn], "270", 3))
276  else
277  usage();
278 
279  } else if (keymatch(arg, "scans", 1)) {
280  /* Set scan script. */
281 #ifdef C_MULTISCAN_FILES_SUPPORTED
282  if (++argn >= argc) /* advance to next argument */
283  usage();
284  scansarg = argv[argn];
285  /* We must postpone reading the file in case -progressive appears. */
286 #else
287  fprintf(stderr, "%s: sorry, multi-scan output was not compiled\n",
288  progname);
289  exit(EXIT_FAILURE);
290 #endif
291 
292  } else if (keymatch(arg, "transpose", 1)) {
293  /* Transpose (across UL-to-LR axis). */
295 
296  } else if (keymatch(arg, "transverse", 6)) {
297  /* Transverse transpose (across UR-to-LL axis). */
299 
300  } else if (keymatch(arg, "trim", 3)) {
301  /* Trim off any partial edge MCUs that the transform can't handle. */
302  transformoption.trim = TRUE;
303 
304  } else {
305  usage(); /* bogus switch */
306  }
307  }
308 
309  /* Post-switch-scanning cleanup */
310 
311  if (for_real) {
312 
313 #ifdef C_PROGRESSIVE_SUPPORTED
314  if (simple_progressive) /* process -progressive; -scans can override */
316 #endif
317 
318 #ifdef C_MULTISCAN_FILES_SUPPORTED
319  if (scansarg != NULL) /* process -scans if it was present */
320  if (! read_scan_script(cinfo, scansarg))
321  usage();
322 #endif
323  }
324 
325  return argn; /* return index of next arg (file name) */
326 }
327 
328 
329 /*
330  * The main program.
331  */
332 
333 int
334 main (int argc, char **argv)
335 {
336  struct jpeg_decompress_struct srcinfo;
337  struct jpeg_compress_struct dstinfo;
338  struct jpeg_error_mgr jsrcerr, jdsterr;
339 #ifdef PROGRESS_REPORT
340  struct cdjpeg_progress_mgr progress;
341 #endif
342  jvirt_barray_ptr * src_coef_arrays;
343  jvirt_barray_ptr * dst_coef_arrays;
344  int file_index;
345  FILE * input_file;
346  FILE * output_file;
347 
348  /* On Mac, fetch a command line. */
349 #ifdef USE_CCOMMAND
350  argc = ccommand(&argv);
351 #endif
352 
353  progname = argv[0];
354  if (progname == NULL || progname[0] == 0)
355  progname = "jpegtran"; /* in case C library doesn't provide it */
356 
357  /* Initialize the JPEG decompression object with default error handling. */
358  srcinfo.err = jpeg_std_error(&jsrcerr);
359  jpeg_create_decompress(&srcinfo);
360  /* Initialize the JPEG compression object with default error handling. */
361  dstinfo.err = jpeg_std_error(&jdsterr);
362  jpeg_create_compress(&dstinfo);
363 
364  /* Now safe to enable signal catcher.
365  * Note: we assume only the decompression object will have virtual arrays.
366  */
367 #ifdef NEED_SIGNAL_CATCHER
368  enable_signal_catcher((j_common_ptr) &srcinfo);
369 #endif
370 
371  /* Scan command line to find file names.
372  * It is convenient to use just one switch-parsing routine, but the switch
373  * values read here are mostly ignored; we will rescan the switches after
374  * opening the input file. Also note that most of the switches affect the
375  * destination JPEG object, so we parse into that and then copy over what
376  * needs to affects the source too.
377  */
378 
379  file_index = parse_switches(&dstinfo, argc, argv, 0, FALSE);
380  jsrcerr.trace_level = jdsterr.trace_level;
381  srcinfo.mem->max_memory_to_use = dstinfo.mem->max_memory_to_use;
382 
383 #ifdef TWO_FILE_COMMANDLINE
384  /* Must have either -outfile switch or explicit output file name */
385  if (outfilename == NULL) {
386  if (file_index != argc-2) {
387  fprintf(stderr, "%s: must name one input and one output file\n",
388  progname);
389  usage();
390  }
391  outfilename = argv[file_index+1];
392  } else {
393  if (file_index != argc-1) {
394  fprintf(stderr, "%s: must name one input and one output file\n",
395  progname);
396  usage();
397  }
398  }
399 #else
400  /* Unix style: expect zero or one file name */
401  if (file_index < argc-1) {
402  fprintf(stderr, "%s: only one input file\n", progname);
403  usage();
404  }
405 #endif /* TWO_FILE_COMMANDLINE */
406 
407  /* Open the input file. */
408  if (file_index < argc) {
409  if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
410  fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
411  exit(EXIT_FAILURE);
412  }
413  } else {
414  /* default input file is stdin */
415  input_file = read_stdin();
416  }
417 
418  /* Open the output file. */
419  if (outfilename != NULL) {
420  if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
421  fprintf(stderr, "%s: can't open %s\n", progname, outfilename);
422  exit(EXIT_FAILURE);
423  }
424  } else {
425  /* default output file is stdout */
426  output_file = write_stdout();
427  }
428 
429 #ifdef PROGRESS_REPORT
430  start_progress_monitor((j_common_ptr) &dstinfo, &progress);
431 #endif
432 
433  /* Specify data source for decompression */
434  jpeg_stdio_src(&srcinfo, input_file);
435 
436  /* Enable saving of extra markers that we want to copy */
437  jcopy_markers_setup(&srcinfo, copyoption);
438 
439  /* Read file header */
440  (void) jpeg_read_header(&srcinfo, TRUE);
441 
442  /* Any space needed by a transform option must be requested before
443  * jpeg_read_coefficients so that memory allocation will be done right.
444  */
445 #if TRANSFORMS_SUPPORTED
446  jtransform_request_workspace(&srcinfo, &transformoption);
447 #endif
448 
449  /* Read source file as DCT coefficients */
450  src_coef_arrays = jpeg_read_coefficients(&srcinfo);
451 
452  /* Initialize destination compression parameters from source values */
453  jpeg_copy_critical_parameters(&srcinfo, &dstinfo);
454 
455  /* Adjust destination parameters if required by transform options;
456  * also find out which set of coefficient arrays will hold the output.
457  */
458 #if TRANSFORMS_SUPPORTED
459  dst_coef_arrays = jtransform_adjust_parameters(&srcinfo, &dstinfo,
460  src_coef_arrays,
461  &transformoption);
462 #else
463  dst_coef_arrays = src_coef_arrays;
464 #endif
465 
466  /* Adjust default compression parameters by re-parsing the options */
467  file_index = parse_switches(&dstinfo, argc, argv, 0, TRUE);
468 
469  /* Specify data destination for compression */
470  jpeg_stdio_dest(&dstinfo, output_file);
471 
472  /* Start compressor (note no image data is actually written here) */
473  jpeg_write_coefficients(&dstinfo, dst_coef_arrays);
474 
475  /* Copy to the output file any extra markers that we want to preserve */
476  jcopy_markers_execute(&srcinfo, &dstinfo, copyoption);
477 
478  /* Execute image transformation, if any */
479 #if TRANSFORMS_SUPPORTED
480  jtransform_execute_transformation(&srcinfo, &dstinfo,
481  src_coef_arrays,
482  &transformoption);
483 #endif
484 
485  /* Finish compression and release memory */
486  jpeg_finish_compress(&dstinfo);
487  jpeg_destroy_compress(&dstinfo);
488  (void) jpeg_finish_decompress(&srcinfo);
489  jpeg_destroy_decompress(&srcinfo);
490 
491  /* Close files, if we opened them */
492  if (input_file != stdin)
493  fclose(input_file);
494  if (output_file != stdout)
495  fclose(output_file);
496 
497 #ifdef PROGRESS_REPORT
498  end_progress_monitor((j_common_ptr) &dstinfo);
499 #endif
500 
501  /* All done. */
502  exit(jsrcerr.num_warnings + jdsterr.num_warnings ?EXIT_WARNING:EXIT_SUCCESS);
503  return 0; /* suppress no-return-value warnings */
504 }
jpeg_read_header(j_decompress_ptr cinfo, boolean require_image)
Definition: jdapimin.c:241
long num_warnings
Definition: jpeglib.h:676
jpeg_finish_compress(j_compress_ptr cinfo)
Definition: jcapimin.c:147
#define NULL
Definition: ftobjs.h:61
jpeg_destroy_compress(j_compress_ptr cinfo)
Definition: jcapimin.c:88
#define WRITE_BINARY
Definition: cdjpeg.h:164
select_transform(JXFORM_CODE transform)
Definition: jpegtran.c:91
jpeg_stdio_dest(j_compress_ptr cinfo, FILE *outfile)
Definition: jdatadst.c:130
parse_switches(j_compress_ptr cinfo, int argc, char **argv, int last_file_arg_seen, boolean for_real)
Definition: jpegtran.c:114
#define EXIT_SUCCESS
Definition: cdjpeg.h:175
typedef void(APIENTRY *GLDEBUGPROCARB)(GLenum source
read_stdin(void)
Definition: cdjpeg.c:149
#define jpeg_create_decompress(cinfo)
Definition: jpeglib.h:897
jpeg_copy_critical_parameters(j_decompress_ptr srcinfo, j_compress_ptr dstinfo)
Definition: jctrans.c:63
jcopy_markers_execute(j_decompress_ptr srcinfo, j_compress_ptr dstinfo, JCOPY_OPTION option)
Definition: transupp.c:886
#define EXIT_WARNING
Definition: cdjpeg.h:182
#define JCOPYRIGHT
Definition: jversion.h:14
GLsizeiptr const GLvoid GLenum usage
#define READ_BINARY
Definition: cdjpeg.h:163
int trace_level
Definition: jpeglib.h:668
boolean force_grayscale
Definition: transupp.h:90
keymatch(char *arg, const char *keyword, int minchars)
Definition: cdjpeg.c:122
#define LOCAL(type)
Definition: jmorecfg.h:189
JXFORM_CODE transform
Definition: transupp.h:88
jpeg_stdio_src(j_decompress_ptr cinfo, FILE *infile)
Definition: jdatasrc.c:182
usage(void)
Definition: jpegtran.c:45
jpeg_finish_decompress(j_decompress_ptr cinfo)
Definition: jdapimin.c:369
#define FALSE
Definition: ftobjs.h:57
read_scan_script(j_compress_ptr cinfo, char *filename)
Definition: rdswitch.c:158
jpeg_simple_progression(j_compress_ptr cinfo)
Definition: jcparam.c:537
jpeg_destroy_decompress(j_decompress_ptr cinfo)
Definition: jdapimin.c:91
struct jvirt_barray_control * jvirt_barray_ptr
Definition: jpeglib.h:753
#define JCOPYOPT_DEFAULT
Definition: transupp.h:127
typedef int
Definition: png.h:978
JXFORM_CODE
Definition: transupp.h:40
jcopy_markers_setup(j_decompress_ptr srcinfo, JCOPY_OPTION option)
Definition: transupp.c:861
#define jpeg_create_compress(cinfo)
Definition: jpeglib.h:894
GLuint GLenum GLenum transform
write_stdout(void)
Definition: cdjpeg.c:167
char * arg
Definition: cdjpeg.h:136
jpeg_std_error(struct jpeg_error_mgr *err)
Definition: jerror.c:231
#define EXIT_FAILURE
Definition: cdjpeg.h:169
JCOPY_OPTION
Definition: transupp.h:121
#define TRUE
Definition: ftobjs.h:53
#define JVERSION
Definition: jversion.h:12
int main(int argc, char **argv)
Definition: jpegtran.c:334