blob: 33347f3f425bbe8789a63536071eeadddf158789 [file] [log] [blame]
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +00001/*
2 * cjpeg.c
3 *
4 * Copyright (C) 1991-1994, 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 the JPEG compressor.
9 * It should work on any system with Unix- or MS-DOS-style command lines.
10 *
11 * Two different command line styles are permitted, depending on the
12 * compile-time switch TWO_FILE_COMMANDLINE:
13 * cjpeg [options] inputfile outputfile
14 * cjpeg [options] [inputfile]
15 * In the second style, output is always to standard output, which you'd
16 * normally redirect to a file or pipe to some other program. Input is
17 * either from a named file or from standard input (typically redirected).
18 * The second style is convenient on Unix but is unhelpful on systems that
19 * don't support pipes. Also, you MUST use the first style if your system
20 * doesn't do binary I/O to stdin/stdout.
21 * To simplify script writing, the "-outfile" switch is provided. The syntax
22 * cjpeg [options] -outfile outputfile inputfile
23 * works regardless of which command line style is used.
24 */
25
26#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
27#define JMAKE_MSG_TABLE
28#include "cderror.h" /* create message string table */
29#include "jversion.h" /* for version message */
30
31#include <ctype.h> /* to declare isupper(), tolower() */
32#ifdef NEED_SIGNAL_CATCHER
33#include <signal.h> /* to declare signal() */
34#endif
35#ifdef USE_SETMODE
36#include <fcntl.h> /* to declare setmode()'s parameter macros */
37/* If you have setmode() but not <io.h>, just delete this line: */
38#include <io.h> /* to declare setmode() */
39#endif
40
41#ifdef USE_CCOMMAND /* command-line reader for Macintosh */
42#ifdef __MWERKS__
43#include <SIOUX.h> /* Metrowerks declares it here */
44#endif
45#ifdef THINK_C
46#include <console.h> /* Think declares it here */
47#endif
48#endif
49
50#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */
51#define READ_BINARY "r"
52#define WRITE_BINARY "w"
53#else
54#define READ_BINARY "rb"
55#define WRITE_BINARY "wb"
56#endif
57
58#ifndef EXIT_FAILURE /* define exit() codes if not provided */
59#define EXIT_FAILURE 1
60#endif
61#ifndef EXIT_SUCCESS
62#ifdef VMS
63#define EXIT_SUCCESS 1 /* VMS is very nonstandard */
64#else
65#define EXIT_SUCCESS 0
66#endif
67#endif
68#ifndef EXIT_WARNING
69#ifdef VMS
70#define EXIT_WARNING 1 /* VMS is very nonstandard */
71#else
72#define EXIT_WARNING 2
73#endif
74#endif
75
76
77/*
78 * This routine determines what format the input file is,
79 * and selects the appropriate input-reading module.
80 *
81 * To determine which family of input formats the file belongs to,
82 * we may look only at the first byte of the file, since C does not
83 * guarantee that more than one character can be pushed back with ungetc.
84 * Looking at additional bytes would require one of these approaches:
85 * 1) assume we can fseek() the input file (fails for piped input);
86 * 2) assume we can push back more than one character (works in
87 * some C implementations, but unportable);
88 * 3) provide our own buffering (breaks input readers that want to use
89 * stdio directly, such as the RLE library);
90 * or 4) don't put back the data, and modify the input_init methods to assume
91 * they start reading after the start of file (also breaks RLE library).
92 * #1 is attractive for MS-DOS but is untenable on Unix.
93 *
94 * The most portable solution for file types that can't be identified by their
95 * first byte is to make the user tell us what they are. This is also the
96 * only approach for "raw" file types that contain only arbitrary values.
97 * We presently apply this method for Targa files. Most of the time Targa
98 * files start with 0x00, so we recognize that case. Potentially, however,
99 * a Targa file could start with any byte value (byte 0 is the length of the
100 * seldom-used ID field), so we provide a switch to force Targa input mode.
101 */
102
103static boolean is_targa; /* records user -targa switch */
104
105
106LOCAL cjpeg_source_ptr
107select_file_type (j_compress_ptr cinfo, FILE * infile)
108{
109 int c;
110
111 if (is_targa) {
112#ifdef TARGA_SUPPORTED
113 return jinit_read_targa(cinfo);
114#else
115 ERREXIT(cinfo, JERR_TGA_NOTCOMP);
116#endif
117 }
118
119 if ((c = getc(infile)) == EOF)
120 ERREXIT(cinfo, JERR_INPUT_EMPTY);
121 if (ungetc(c, infile) == EOF)
122 ERREXIT(cinfo, JERR_UNGETC_FAILED);
123
124 switch (c) {
125#ifdef BMP_SUPPORTED
126 case 'B':
127 return jinit_read_bmp(cinfo);
128#endif
129#ifdef GIF_SUPPORTED
130 case 'G':
131 return jinit_read_gif(cinfo);
132#endif
133#ifdef PPM_SUPPORTED
134 case 'P':
135 return jinit_read_ppm(cinfo);
136#endif
137#ifdef RLE_SUPPORTED
138 case 'R':
139 return jinit_read_rle(cinfo);
140#endif
141#ifdef TARGA_SUPPORTED
142 case 0x00:
143 return jinit_read_targa(cinfo);
144#endif
145 default:
146 ERREXIT(cinfo, JERR_UNKNOWN_FORMAT);
147 break;
148 }
149
150 return NULL; /* suppress compiler warnings */
151}
152
153
154/*
155 * Signal catcher to ensure that temporary files are removed before aborting.
156 * NB: for Amiga Manx C this is actually a global routine named _abort();
157 * we put "#define signal_catcher _abort" in jconfig.h. Talk about bogus...
158 */
159
160#ifdef NEED_SIGNAL_CATCHER
161
162static j_common_ptr sig_cinfo;
163
164GLOBAL void
165signal_catcher (int signum)
166{
167 if (sig_cinfo != NULL) {
168 if (sig_cinfo->err != NULL) /* turn off trace output */
169 sig_cinfo->err->trace_level = 0;
170 jpeg_destroy(sig_cinfo); /* clean up memory allocation & temp files */
171 }
172 exit(EXIT_FAILURE);
173}
174
175#endif
176
177
178/*
179 * Optional routine to display a percent-done figure on stderr.
180 */
181
182#ifdef PROGRESS_REPORT
183
184METHODDEF void
185progress_monitor (j_common_ptr cinfo)
186{
187 cd_progress_ptr prog = (cd_progress_ptr) cinfo->progress;
188 int total_passes = prog->pub.total_passes + prog->total_extra_passes;
189 int percent_done = (int) (prog->pub.pass_counter*100L/prog->pub.pass_limit);
190
191 if (percent_done != prog->percent_done) {
192 prog->percent_done = percent_done;
193 if (total_passes > 1) {
194 fprintf(stderr, "\rPass %d/%d: %3d%% ",
195 prog->pub.completed_passes + prog->completed_extra_passes + 1,
196 total_passes, percent_done);
197 } else {
198 fprintf(stderr, "\r %3d%% ", percent_done);
199 }
200 fflush(stderr);
201 }
202}
203
204#endif
205
206
207/*
208 * Argument-parsing code.
209 * The switch parser is designed to be useful with DOS-style command line
210 * syntax, ie, intermixed switches and file names, where only the switches
211 * to the left of a given file name affect processing of that file.
212 * The main program in this file doesn't actually use this capability...
213 */
214
215
216static const char * progname; /* program name for error messages */
217static char * outfilename; /* for -outfile switch */
218
219
220LOCAL void
221usage (void)
222/* complain about bad command line */
223{
224 fprintf(stderr, "usage: %s [switches] ", progname);
225#ifdef TWO_FILE_COMMANDLINE
226 fprintf(stderr, "inputfile outputfile\n");
227#else
228 fprintf(stderr, "[inputfile]\n");
229#endif
230
231 fprintf(stderr, "Switches (names may be abbreviated):\n");
232 fprintf(stderr, " -quality N Compression quality (0..100; 5-95 is useful range)\n");
233 fprintf(stderr, " -grayscale Create monochrome JPEG file\n");
234#ifdef ENTROPY_OPT_SUPPORTED
235 fprintf(stderr, " -optimize Optimize Huffman table (smaller file, but slow compression)\n");
236#endif
237#ifdef TARGA_SUPPORTED
238 fprintf(stderr, " -targa Input file is Targa format (usually not needed)\n");
239#endif
240 fprintf(stderr, "Switches for advanced users:\n");
241#ifdef DCT_ISLOW_SUPPORTED
242 fprintf(stderr, " -dct int Use integer DCT method%s\n",
243 (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : ""));
244#endif
245#ifdef DCT_IFAST_SUPPORTED
246 fprintf(stderr, " -dct fast Use fast integer DCT (less accurate)%s\n",
247 (JDCT_DEFAULT == JDCT_IFAST ? " (default)" : ""));
248#endif
249#ifdef DCT_FLOAT_SUPPORTED
250 fprintf(stderr, " -dct float Use floating-point DCT method%s\n",
251 (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
252#endif
253 fprintf(stderr, " -restart N Set restart interval in rows, or in blocks with B\n");
254#ifdef INPUT_SMOOTHING_SUPPORTED
255 fprintf(stderr, " -smooth N Smooth dithered input (N=1..100 is strength)\n");
256#endif
257 fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n");
258 fprintf(stderr, " -outfile name Specify name for output file\n");
259 fprintf(stderr, " -verbose or -debug Emit debug output\n");
260 fprintf(stderr, "Switches for wizards:\n");
261#ifdef C_ARITH_CODING_SUPPORTED
262 fprintf(stderr, " -arithmetic Use arithmetic coding\n");
263#endif
264 fprintf(stderr, " -baseline Force baseline output\n");
265#ifdef C_MULTISCAN_FILES_SUPPORTED
266 fprintf(stderr, " -nointerleave Create noninterleaved JPEG file\n");
267#endif
268 fprintf(stderr, " -qtables file Use quantization tables given in file\n");
269 fprintf(stderr, " -qslots N[,...] Set component quantization tables\n");
270 fprintf(stderr, " -sample HxV[,...] Set component sampling factors\n");
271 exit(EXIT_FAILURE);
272}
273
274
275LOCAL boolean
276keymatch (char * arg, const char * keyword, int minchars)
277/* Case-insensitive matching of (possibly abbreviated) keyword switches. */
278/* keyword is the constant keyword (must be lower case already), */
279/* minchars is length of minimum legal abbreviation. */
280{
281 register int ca, ck;
282 register int nmatched = 0;
283
284 while ((ca = *arg++) != '\0') {
285 if ((ck = *keyword++) == '\0')
286 return FALSE; /* arg longer than keyword, no good */
287 if (isupper(ca)) /* force arg to lcase (assume ck is already) */
288 ca = tolower(ca);
289 if (ca != ck)
290 return FALSE; /* no good */
291 nmatched++; /* count matched characters */
292 }
293 /* reached end of argument; fail if it's too short for unique abbrev */
294 if (nmatched < minchars)
295 return FALSE;
296 return TRUE; /* A-OK */
297}
298
299
300LOCAL int
301qt_getc (FILE * file)
302/* Read next char, skipping over any comments (# to end of line) */
303/* A comment/newline sequence is returned as a newline */
304{
305 register int ch;
306
307 ch = getc(file);
308 if (ch == '#') {
309 do {
310 ch = getc(file);
311 } while (ch != '\n' && ch != EOF);
312 }
313 return ch;
314}
315
316
317LOCAL long
318read_qt_integer (FILE * file)
319/* Read an unsigned decimal integer from a quantization-table file */
320/* Swallows one trailing character after the integer */
321{
322 register int ch;
323 register long val;
324
325 /* Skip any leading whitespace, detect EOF */
326 do {
327 ch = qt_getc(file);
328 if (ch == EOF)
329 return EOF;
330 } while (isspace(ch));
331
332 if (! isdigit(ch)) {
333 fprintf(stderr, "%s: bogus data in quantization file\n", progname);
334 exit(EXIT_FAILURE);
335 }
336
337 val = ch - '0';
338 while (ch = qt_getc(file), isdigit(ch)) {
339 val *= 10;
340 val += ch - '0';
341 }
342 return val;
343}
344
345
346LOCAL void
347read_quant_tables (j_compress_ptr cinfo, char * filename, int scale_factor,
348 boolean force_baseline)
349/* Read a set of quantization tables from the specified file.
350 * The file is plain ASCII text: decimal numbers with whitespace between.
351 * Comments preceded by '#' may be included in the file.
352 * There may be one to NUM_QUANT_TBLS tables in the file, each of 64 values.
353 * The tables are implicitly numbered 0,1,etc.
354 * NOTE: does not affect the qslots mapping, which will default to selecting
355 * table 0 for luminance (or primary) components, 1 for chrominance components.
356 * You must use -qslots if you want a different component->table mapping.
357 */
358{
359 /* ZIG[i] is the zigzag-order position of the i'th element of a DCT block */
360 /* read in natural order (left to right, top to bottom). */
361 static const int ZIG[DCTSIZE2] = {
362 0, 1, 5, 6, 14, 15, 27, 28,
363 2, 4, 7, 13, 16, 26, 29, 42,
364 3, 8, 12, 17, 25, 30, 41, 43,
365 9, 11, 18, 24, 31, 40, 44, 53,
366 10, 19, 23, 32, 39, 45, 52, 54,
367 20, 22, 33, 38, 46, 51, 55, 60,
368 21, 34, 37, 47, 50, 56, 59, 61,
369 35, 36, 48, 49, 57, 58, 62, 63
370 };
371 FILE * fp;
372 int tblno, i;
373 long val;
374 unsigned int table[DCTSIZE2];
375
376 if ((fp = fopen(filename, "r")) == NULL) {
377 fprintf(stderr, "%s: can't open %s\n", progname, filename);
378 exit(EXIT_FAILURE);
379 }
380 tblno = 0;
381
382 while ((val = read_qt_integer(fp)) != EOF) { /* read 1st element of table */
383 if (tblno >= NUM_QUANT_TBLS) {
384 fprintf(stderr, "%s: too many tables in file %s\n", progname, filename);
385 exit(EXIT_FAILURE);
386 }
387 table[0] = (unsigned int) val;
388 for (i = 1; i < DCTSIZE2; i++) {
389 if ((val = read_qt_integer(fp)) == EOF) {
390 fprintf(stderr, "%s: incomplete table in file %s\n", progname, filename);
391 exit(EXIT_FAILURE);
392 }
393 table[ZIG[i]] = (unsigned int) val;
394 }
395 jpeg_add_quant_table(cinfo, tblno, table, scale_factor, force_baseline);
396 tblno++;
397 }
398
399 fclose(fp);
400}
401
402
403LOCAL void
404set_quant_slots (j_compress_ptr cinfo, char *arg)
405/* Process a quantization-table-selectors parameter string, of the form
406 * N[,N,...]
407 * If there are more components than parameters, the last value is replicated.
408 */
409{
410 int val = 0; /* default table # */
411 int ci;
412 char ch;
413
414 for (ci = 0; ci < MAX_COMPONENTS; ci++) {
415 if (*arg) {
416 ch = ','; /* if not set by sscanf, will be ',' */
417 if (sscanf(arg, "%d%c", &val, &ch) < 1)
418 usage();
419 if (ch != ',')
420 usage(); /* syntax check */
421 if (val < 0 || val >= NUM_QUANT_TBLS) {
422 fprintf(stderr, "JPEG quantization tables are numbered 0..%d\n",
423 NUM_QUANT_TBLS-1);
424 exit(EXIT_FAILURE);
425 }
426 cinfo->comp_info[ci].quant_tbl_no = val;
427 while (*arg && *arg++ != ',') /* advance to next segment of arg string */
428 ;
429 } else {
430 /* reached end of parameter, set remaining components to last table */
431 cinfo->comp_info[ci].quant_tbl_no = val;
432 }
433 }
434}
435
436
437LOCAL void
438set_sample_factors (j_compress_ptr cinfo, char *arg)
439/* Process a sample-factors parameter string, of the form
440 * HxV[,HxV,...]
441 * If there are more components than parameters, "1x1" is assumed.
442 */
443{
444 int ci, val1, val2;
445 char ch1, ch2;
446
447 for (ci = 0; ci < MAX_COMPONENTS; ci++) {
448 if (*arg) {
449 ch2 = ','; /* if not set by sscanf, will be ',' */
450 if (sscanf(arg, "%d%c%d%c", &val1, &ch1, &val2, &ch2) < 3)
451 usage();
452 if ((ch1 != 'x' && ch1 != 'X') || ch2 != ',')
453 usage(); /* syntax check */
454 if (val1 <= 0 || val1 > 4 || val2 <= 0 || val2 > 4) {
455 fprintf(stderr, "JPEG sampling factors must be 1..4\n");
456 exit(EXIT_FAILURE);
457 }
458 cinfo->comp_info[ci].h_samp_factor = val1;
459 cinfo->comp_info[ci].v_samp_factor = val2;
460 while (*arg && *arg++ != ',') /* advance to next segment of arg string */
461 ;
462 } else {
463 /* reached end of parameter, set remaining components to 1x1 sampling */
464 cinfo->comp_info[ci].h_samp_factor = 1;
465 cinfo->comp_info[ci].v_samp_factor = 1;
466 }
467 }
468}
469
470
471LOCAL int
472parse_switches (j_compress_ptr cinfo, int argc, char **argv,
473 int last_file_arg_seen, boolean for_real)
474/* Parse optional switches.
475 * Returns argv[] index of first file-name argument (== argc if none).
476 * Any file names with indexes <= last_file_arg_seen are ignored;
477 * they have presumably been processed in a previous iteration.
478 * (Pass 0 for last_file_arg_seen on the first or only iteration.)
479 * for_real is FALSE on the first (dummy) pass; we may skip any expensive
480 * processing.
481 */
482{
483 int argn;
484 char * arg;
485 int quality; /* -quality parameter */
486 int q_scale_factor; /* scaling percentage for -qtables */
487 boolean force_baseline;
488 char * qtablefile = NULL; /* saves -qtables filename if any */
489 char * qslotsarg = NULL; /* saves -qslots parm if any */
490 char * samplearg = NULL; /* saves -sample parm if any */
491
492 /* Set up default JPEG parameters. */
493 /* Note that default -quality level need not, and does not,
494 * match the default scaling for an explicit -qtables argument.
495 */
496 quality = 75; /* default -quality value */
497 q_scale_factor = 100; /* default to no scaling for -qtables */
498 force_baseline = FALSE; /* by default, allow 16-bit quantizers */
499 is_targa = FALSE;
500 outfilename = NULL;
501 cinfo->err->trace_level = 0;
502
503 /* Scan command line options, adjust parameters */
504
505 for (argn = 1; argn < argc; argn++) {
506 arg = argv[argn];
507 if (*arg != '-') {
508 /* Not a switch, must be a file name argument */
509 if (argn <= last_file_arg_seen) {
510 outfilename = NULL; /* -outfile applies to just one input file */
511 continue; /* ignore this name if previously processed */
512 }
513 break; /* else done parsing switches */
514 }
515 arg++; /* advance past switch marker character */
516
517 if (keymatch(arg, "arithmetic", 1)) {
518 /* Use arithmetic coding. */
519#ifdef C_ARITH_CODING_SUPPORTED
520 cinfo->arith_code = TRUE;
521#else
522 fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
523 progname);
524 exit(EXIT_FAILURE);
525#endif
526
527 } else if (keymatch(arg, "baseline", 1)) {
528 /* Force baseline output (8-bit quantizer values). */
529 force_baseline = TRUE;
530
531 } else if (keymatch(arg, "dct", 2)) {
532 /* Select DCT algorithm. */
533 if (++argn >= argc) /* advance to next argument */
534 usage();
535 if (keymatch(argv[argn], "int", 1)) {
536 cinfo->dct_method = JDCT_ISLOW;
537 } else if (keymatch(argv[argn], "fast", 2)) {
538 cinfo->dct_method = JDCT_IFAST;
539 } else if (keymatch(argv[argn], "float", 2)) {
540 cinfo->dct_method = JDCT_FLOAT;
541 } else
542 usage();
543
544 } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
545 /* Enable debug printouts. */
546 /* On first -d, print version identification */
547 static boolean printed_version = FALSE;
548
549 if (! printed_version) {
550 fprintf(stderr, "Independent JPEG Group's CJPEG, version %s\n%s\n",
551 JVERSION, JCOPYRIGHT);
552 printed_version = TRUE;
553 }
554 cinfo->err->trace_level++;
555
556 } else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
557 /* Force a monochrome JPEG file to be generated. */
558 jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
559
560 } else if (keymatch(arg, "maxmemory", 3)) {
561 /* Maximum memory in Kb (or Mb with 'm'). */
562 long lval;
563 char ch = 'x';
564
565 if (++argn >= argc) /* advance to next argument */
566 usage();
567 if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
568 usage();
569 if (ch == 'm' || ch == 'M')
570 lval *= 1000L;
571 cinfo->mem->max_memory_to_use = lval * 1000L;
572
573 } else if (keymatch(arg, "nointerleave", 3)) {
574 /* Create noninterleaved file. */
575#ifdef C_MULTISCAN_FILES_SUPPORTED
576 cinfo->interleave = FALSE;
577#else
578 fprintf(stderr, "%s: sorry, multiple-scan support was not compiled\n",
579 progname);
580 exit(EXIT_FAILURE);
581#endif
582
583 } else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) {
584 /* Enable entropy parm optimization. */
585#ifdef ENTROPY_OPT_SUPPORTED
586 cinfo->optimize_coding = TRUE;
587#else
588 fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n",
589 progname);
590 exit(EXIT_FAILURE);
591#endif
592
593 } else if (keymatch(arg, "outfile", 4)) {
594 /* Set output file name. */
595 if (++argn >= argc) /* advance to next argument */
596 usage();
597 outfilename = argv[argn]; /* save it away for later use */
598
599 } else if (keymatch(arg, "quality", 1)) {
600 /* Quality factor (quantization table scaling factor). */
601 if (++argn >= argc) /* advance to next argument */
602 usage();
603 if (sscanf(argv[argn], "%d", &quality) != 1)
604 usage();
605 /* Change scale factor in case -qtables is present. */
606 q_scale_factor = jpeg_quality_scaling(quality);
607
608 } else if (keymatch(arg, "qslots", 2)) {
609 /* Quantization table slot numbers. */
610 if (++argn >= argc) /* advance to next argument */
611 usage();
612 qslotsarg = argv[argn];
613 /* Must delay setting qslots until after we have processed any
614 * colorspace-determining switches, since jpeg_set_colorspace sets
615 * default quant table numbers.
616 */
617
618 } else if (keymatch(arg, "qtables", 2)) {
619 /* Quantization tables fetched from file. */
620 if (++argn >= argc) /* advance to next argument */
621 usage();
622 qtablefile = argv[argn];
623 /* We postpone actually reading the file in case -quality comes later. */
624
625 } else if (keymatch(arg, "restart", 1)) {
626 /* Restart interval in MCU rows (or in MCUs with 'b'). */
627 long lval;
628 char ch = 'x';
629
630 if (++argn >= argc) /* advance to next argument */
631 usage();
632 if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
633 usage();
634 if (lval < 0 || lval > 65535L)
635 usage();
636 if (ch == 'b' || ch == 'B') {
637 cinfo->restart_interval = (unsigned int) lval;
638 cinfo->restart_in_rows = 0; /* else prior '-restart n' overrides me */
639 } else {
640 cinfo->restart_in_rows = (int) lval;
641 /* restart_interval will be computed during startup */
642 }
643
644 } else if (keymatch(arg, "sample", 2)) {
645 /* Set sampling factors. */
646 if (++argn >= argc) /* advance to next argument */
647 usage();
648 samplearg = argv[argn];
649 /* Must delay setting sample factors until after we have processed any
650 * colorspace-determining switches, since jpeg_set_colorspace sets
651 * default sampling factors.
652 */
653
654 } else if (keymatch(arg, "smooth", 2)) {
655 /* Set input smoothing factor. */
656 int val;
657
658 if (++argn >= argc) /* advance to next argument */
659 usage();
660 if (sscanf(argv[argn], "%d", &val) != 1)
661 usage();
662 if (val < 0 || val > 100)
663 usage();
664 cinfo->smoothing_factor = val;
665
666 } else if (keymatch(arg, "targa", 1)) {
667 /* Input file is Targa format. */
668 is_targa = TRUE;
669
670 } else {
671 usage(); /* bogus switch */
672 }
673 }
674
675 /* Post-switch-scanning cleanup */
676
677 if (for_real) {
678
679 /* Set quantization tables for selected quality. */
680 /* Some or all may be overridden if -qtables is present. */
681 jpeg_set_quality(cinfo, quality, force_baseline);
682
683 if (qtablefile != NULL) /* process -qtables if it was present */
684 read_quant_tables(cinfo, qtablefile, q_scale_factor, force_baseline);
685
686 if (qslotsarg != NULL) /* process -qslots if it was present */
687 set_quant_slots(cinfo, qslotsarg);
688
689 if (samplearg != NULL) /* process -sample if it was present */
690 set_sample_factors(cinfo, samplearg);
691
692 }
693
694 return argn; /* return index of next arg (file name) */
695}
696
697
698/*
699 * The main program.
700 */
701
702GLOBAL int
703main (int argc, char **argv)
704{
705 struct jpeg_compress_struct cinfo;
706 struct jpeg_error_mgr jerr;
707#ifdef PROGRESS_REPORT
708 struct cdjpeg_progress_mgr progress;
709#endif
710 int file_index;
711 cjpeg_source_ptr src_mgr;
712 FILE * input_file;
713 FILE * output_file;
714 JDIMENSION num_scanlines;
715
716 /* On Mac, fetch a command line. */
717#ifdef USE_CCOMMAND
718 argc = ccommand(&argv);
719#endif
720
721 progname = argv[0];
722 if (progname == NULL || progname[0] == 0)
723 progname = "cjpeg"; /* in case C library doesn't provide it */
724
725 /* Initialize the JPEG compression object with default error handling. */
726 cinfo.err = jpeg_std_error(&jerr);
727 jpeg_create_compress(&cinfo);
728 /* Add some application-specific error messages (from cderror.h) */
729 jerr.addon_message_table = addon_message_table;
730 jerr.first_addon_message = JMSG_FIRSTADDONCODE;
731 jerr.last_addon_message = JMSG_LASTADDONCODE;
732
733 /* Now safe to enable signal catcher. */
734#ifdef NEED_SIGNAL_CATCHER
735 sig_cinfo = (j_common_ptr) &cinfo;
736 signal(SIGINT, signal_catcher);
737#ifdef SIGTERM /* not all systems have SIGTERM */
738 signal(SIGTERM, signal_catcher);
739#endif
740#endif
741
742 /* Initialize JPEG parameters.
743 * Much of this may be overridden later.
744 * In particular, we don't yet know the input file's color space,
745 * but we need to provide some value for jpeg_set_defaults() to work.
746 */
747
748 cinfo.in_color_space = JCS_RGB; /* arbitrary guess */
749 jpeg_set_defaults(&cinfo);
750
751 /* Scan command line to find file names.
752 * It is convenient to use just one switch-parsing routine, but the switch
753 * values read here are ignored; we will rescan the switches after opening
754 * the input file.
755 */
756
757 file_index = parse_switches(&cinfo, argc, argv, 0, FALSE);
758
759#ifdef TWO_FILE_COMMANDLINE
760 /* Must have either -outfile switch or explicit output file name */
761 if (outfilename == NULL) {
762 if (file_index != argc-2) {
763 fprintf(stderr, "%s: must name one input and one output file\n",
764 progname);
765 usage();
766 }
767 outfilename = argv[file_index+1];
768 } else {
769 if (file_index != argc-1) {
770 fprintf(stderr, "%s: must name one input and one output file\n",
771 progname);
772 usage();
773 }
774 }
775#else
776 /* Unix style: expect zero or one file name */
777 if (file_index < argc-1) {
778 fprintf(stderr, "%s: only one input file\n", progname);
779 usage();
780 }
781#endif /* TWO_FILE_COMMANDLINE */
782
783 /* Open the input file. */
784 if (file_index < argc) {
785 if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
786 fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
787 exit(EXIT_FAILURE);
788 }
789 } else {
790 /* default input file is stdin */
791#ifdef USE_SETMODE /* need to hack file mode? */
792 setmode(fileno(stdin), O_BINARY);
793#endif
794#ifdef USE_FDOPEN /* need to re-open in binary mode? */
795 if ((input_file = fdopen(fileno(stdin), READ_BINARY)) == NULL) {
796 fprintf(stderr, "%s: can't open stdin\n", progname);
797 exit(EXIT_FAILURE);
798 }
799#else
800 input_file = stdin;
801#endif
802 }
803
804 /* Open the output file. */
805 if (outfilename != NULL) {
806 if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
807 fprintf(stderr, "%s: can't open %s\n", progname, outfilename);
808 exit(EXIT_FAILURE);
809 }
810 } else {
811 /* default output file is stdout */
812#ifdef USE_SETMODE /* need to hack file mode? */
813 setmode(fileno(stdout), O_BINARY);
814#endif
815#ifdef USE_FDOPEN /* need to re-open in binary mode? */
816 if ((output_file = fdopen(fileno(stdout), WRITE_BINARY)) == NULL) {
817 fprintf(stderr, "%s: can't open stdout\n", progname);
818 exit(EXIT_FAILURE);
819 }
820#else
821 output_file = stdout;
822#endif
823 }
824
825#ifdef PROGRESS_REPORT
826 /* Enable progress display, unless trace output is on */
827 if (jerr.trace_level == 0) {
828 progress.pub.progress_monitor = progress_monitor;
829 progress.completed_extra_passes = 0;
830 progress.total_extra_passes = 0;
831 progress.percent_done = -1;
832 cinfo.progress = &progress.pub;
833 }
834#endif
835
836 /* Figure out the input file format, and set up to read it. */
837 src_mgr = select_file_type(&cinfo, input_file);
838 src_mgr->input_file = input_file;
839
840 /* Read the input file header to obtain file size & colorspace. */
841 (*src_mgr->start_input) (&cinfo, src_mgr);
842
843 /* Now that we know input colorspace, fix colorspace-dependent defaults */
844 jpeg_default_colorspace(&cinfo);
845
846 /* Adjust default compression parameters by re-parsing the options */
847 file_index = parse_switches(&cinfo, argc, argv, 0, TRUE);
848
849 /* Specify data destination for compression */
850 jpeg_stdio_dest(&cinfo, output_file);
851
852 /* Start compressor */
853 jpeg_start_compress(&cinfo, TRUE);
854
855 /* Process data */
856 while (cinfo.next_scanline < cinfo.image_height) {
857 num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr);
858 (void) jpeg_write_scanlines(&cinfo, src_mgr->buffer, num_scanlines);
859 }
860
861 /* Finish compression and release memory */
862 (*src_mgr->finish_input) (&cinfo, src_mgr);
863 jpeg_finish_compress(&cinfo);
864 jpeg_destroy_compress(&cinfo);
865
866#ifdef PROGRESS_REPORT
867 /* Clear away progress display */
868 if (jerr.trace_level == 0) {
869 fprintf(stderr, "\r \r");
870 fflush(stderr);
871 }
872#endif
873
874 /* All done. */
875 exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);
876 return 0; /* suppress no-return-value warnings */
877}