comparison mupdf-source/thirdparty/libjpeg/djpegalt.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 /*
2 * alternate djpeg.c
3 *
4 * Copyright (C) 1991-1997, Thomas G. Lane.
5 * Modified 2009-2023 by Guido Vollbeding.
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 an alternate user interface for the JPEG decompressor.
10 * One or more input files are named on the command line, and output file
11 * names are created by substituting an appropriate extension.
12 */
13
14 #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
15 #include "jversion.h" /* for version message */
16
17 #include <ctype.h> /* to declare isprint() */
18
19 #ifdef USE_CCOMMAND /* command-line reader for Macintosh */
20 #ifdef __MWERKS__
21 #include <SIOUX.h> /* Metrowerks needs this */
22 #include <console.h> /* ... and this */
23 #endif
24 #ifdef THINK_C
25 #include <console.h> /* Think declares it here */
26 #endif
27 #endif
28
29 #ifndef PATH_MAX /* ANSI maximum-pathname-length constant */
30 #define PATH_MAX 256
31 #endif
32
33
34 /* Create the add-on message string table. */
35
36 #define JMESSAGE(code,string) string ,
37
38 static const char * const cdjpeg_message_table[] = {
39 #include "cderror.h"
40 NULL
41 };
42
43
44 /*
45 * Automatic determination of available memory.
46 */
47
48 static long default_maxmem; /* saves value determined at startup, or 0 */
49
50 #ifndef FREE_MEM_ESTIMATE /* may be defined from command line */
51
52 #ifdef MSDOS /* For MS-DOS (unless flat-memory model) */
53
54 #include <dos.h> /* for access to intdos() call */
55
56 LOCAL(long)
57 unused_dos_memory (void)
58 /* Obtain total amount of unallocated DOS memory */
59 {
60 union REGS regs;
61 long nparas;
62
63 regs.h.ah = 0x48; /* DOS function Allocate Memory Block */
64 regs.x.bx = 0xFFFF; /* Ask for more memory than DOS can have */
65 (void) intdos(&regs, &regs);
66 /* DOS will fail and return # of paragraphs actually available in BX. */
67 nparas = (unsigned int) regs.x.bx;
68 /* Times 16 to convert to bytes. */
69 return nparas << 4;
70 }
71
72 /* The default memory setting is 95% of the available space. */
73 #define FREE_MEM_ESTIMATE ((unused_dos_memory() * 95L) / 100L)
74
75 #endif /* MSDOS */
76
77 #ifdef ATARI /* For Atari ST/Mega/STE/TT/Falcon, Pure C or Turbo C */
78
79 #include <ext.h>
80
81 /* The default memory setting is 90% of the available space. */
82 #define FREE_MEM_ESTIMATE (((long) coreleft() * 90L) / 100L)
83
84 #endif /* ATARI */
85
86 /* Add memory-estimation procedures for other operating systems here,
87 * with appropriate #ifdef's around them.
88 */
89
90 #endif /* !FREE_MEM_ESTIMATE */
91
92
93 /*
94 * This list defines the known output image formats
95 * (not all of which need be supported by a given version).
96 * You can change the default output format by defining DEFAULT_FMT;
97 * indeed, you had better do so if you undefine PPM_SUPPORTED.
98 */
99
100 typedef enum {
101 FMT_BMP, /* BMP format (Windows flavor) */
102 FMT_GIF, /* GIF format (LZW compressed) */
103 FMT_GIF0, /* GIF format (uncompressed) */
104 FMT_OS2, /* BMP format (OS/2 flavor) */
105 FMT_PPM, /* PPM/PGM (PBMPLUS formats) */
106 FMT_RLE, /* RLE format */
107 FMT_TARGA, /* Targa format */
108 FMT_TIFF /* TIFF format */
109 } IMAGE_FORMATS;
110
111 #ifndef DEFAULT_FMT /* so can override from CFLAGS in Makefile */
112 #define DEFAULT_FMT FMT_BMP
113 #endif
114
115 static IMAGE_FORMATS requested_fmt;
116
117
118 /*
119 * Argument-parsing code.
120 * The switch parser is designed to be useful with DOS-style command line
121 * syntax, ie, intermixed switches and file names, where only the switches
122 * to the left of a given file name affect processing of that file.
123 */
124
125
126 static const char * progname; /* program name for error messages */
127 static char * outfilename; /* for -outfile switch */
128
129
130 LOCAL(void)
131 usage (void)
132 /* complain about bad command line */
133 {
134 fprintf(stderr, "usage: %s [switches] inputfile(s)\n", progname);
135 fprintf(stderr, "List of input files may use wildcards (* and ?)\n");
136 fprintf(stderr, "Output filename is same as input filename except for extension\n");
137
138 fprintf(stderr, "Switches (names may be abbreviated):\n");
139 fprintf(stderr, " -colors N Reduce image to no more than N colors\n");
140 fprintf(stderr, " -fast Fast, low-quality processing\n");
141 fprintf(stderr, " -grayscale Force grayscale output\n");
142 fprintf(stderr, " -rgb Force RGB output\n");
143 #ifdef IDCT_SCALING_SUPPORTED
144 fprintf(stderr, " -scale M/N Scale output image by fraction M/N, eg, 1/8\n");
145 #endif
146 #ifdef BMP_SUPPORTED
147 fprintf(stderr, " -bmp Select BMP output format (Windows style)%s\n",
148 (DEFAULT_FMT == FMT_BMP ? " (default)" : ""));
149 #endif
150 #ifdef GIF_SUPPORTED
151 fprintf(stderr, " -gif Select GIF output format (LZW compressed)%s\n",
152 (DEFAULT_FMT == FMT_GIF ? " (default)" : ""));
153 fprintf(stderr, " -gif0 Select GIF output format (uncompressed)%s\n",
154 (DEFAULT_FMT == FMT_GIF0 ? " (default)" : ""));
155 #endif
156 #ifdef BMP_SUPPORTED
157 fprintf(stderr, " -os2 Select BMP output format (OS/2 style)%s\n",
158 (DEFAULT_FMT == FMT_OS2 ? " (default)" : ""));
159 #endif
160 #ifdef PPM_SUPPORTED
161 fprintf(stderr, " -pnm Select PBMPLUS (PPM/PGM) output format%s\n",
162 (DEFAULT_FMT == FMT_PPM ? " (default)" : ""));
163 #endif
164 #ifdef RLE_SUPPORTED
165 fprintf(stderr, " -rle Select Utah RLE output format%s\n",
166 (DEFAULT_FMT == FMT_RLE ? " (default)" : ""));
167 #endif
168 #ifdef TARGA_SUPPORTED
169 fprintf(stderr, " -targa Select Targa output format%s\n",
170 (DEFAULT_FMT == FMT_TARGA ? " (default)" : ""));
171 #endif
172 fprintf(stderr, "Switches for advanced users:\n");
173 #ifdef DCT_ISLOW_SUPPORTED
174 fprintf(stderr, " -dct int Use integer DCT method%s\n",
175 (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : ""));
176 #endif
177 #ifdef DCT_IFAST_SUPPORTED
178 fprintf(stderr, " -dct fast Use fast integer DCT (less accurate)%s\n",
179 (JDCT_DEFAULT == JDCT_IFAST ? " (default)" : ""));
180 #endif
181 #ifdef DCT_FLOAT_SUPPORTED
182 fprintf(stderr, " -dct float Use floating-point DCT method%s\n",
183 (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
184 #endif
185 fprintf(stderr, " -dither fs Use F-S dithering (default)\n");
186 fprintf(stderr, " -dither none Don't use dithering in quantization\n");
187 fprintf(stderr, " -dither ordered Use ordered dither (medium speed, quality)\n");
188 #ifdef QUANT_2PASS_SUPPORTED
189 fprintf(stderr, " -map FILE Map to colors used in named image file\n");
190 #endif
191 fprintf(stderr, " -nosmooth Don't use high-quality upsampling\n");
192 #ifdef QUANT_1PASS_SUPPORTED
193 fprintf(stderr, " -onepass Use 1-pass quantization (fast, low quality)\n");
194 #endif
195 #ifndef FREE_MEM_ESTIMATE
196 fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n");
197 #endif
198 fprintf(stderr, " -outfile name Specify name for output file\n");
199 fprintf(stderr, " -verbose or -debug Emit debug output\n");
200 exit(EXIT_FAILURE);
201 }
202
203
204 LOCAL(int)
205 parse_switches (j_decompress_ptr cinfo, int argc, char **argv,
206 int last_file_arg_seen, boolean for_real)
207 /* Parse optional switches.
208 * Returns argv[] index of first file-name argument (== argc if none).
209 * Any file names with indexes <= last_file_arg_seen are ignored;
210 * they have presumably been processed in a previous iteration.
211 * (Pass 0 for last_file_arg_seen on the first or only iteration.)
212 * for_real is FALSE on the first (dummy) pass; we may skip any expensive
213 * processing.
214 */
215 {
216 int argn;
217 char * arg;
218
219 /* Set up default JPEG parameters. */
220 requested_fmt = DEFAULT_FMT; /* set default output file format */
221 outfilename = NULL;
222 cinfo->err->trace_level = 0;
223 if (default_maxmem > 0) /* override library's default value */
224 cinfo->mem->max_memory_to_use = default_maxmem;
225
226 /* Scan command line options, adjust parameters */
227
228 for (argn = 1; argn < argc; argn++) {
229 arg = argv[argn];
230 if (*arg != '-') {
231 /* Not a switch, must be a file name argument */
232 if (argn <= last_file_arg_seen) {
233 outfilename = NULL; /* -outfile applies to just one input file */
234 continue; /* ignore this name if previously processed */
235 }
236 break; /* else done parsing switches */
237 }
238 arg++; /* advance past switch marker character */
239
240 if (keymatch(arg, "bmp", 1)) {
241 /* BMP output format (Windows flavor). */
242 requested_fmt = FMT_BMP;
243
244 } else if (keymatch(arg, "colors", 1) || keymatch(arg, "colours", 1) ||
245 keymatch(arg, "quantize", 1) || keymatch(arg, "quantise", 1)) {
246 /* Do color quantization. */
247 int val;
248
249 if (++argn >= argc) /* advance to next argument */
250 usage();
251 if (sscanf(argv[argn], "%d", &val) != 1)
252 usage();
253 cinfo->desired_number_of_colors = val;
254 cinfo->quantize_colors = TRUE;
255
256 } else if (keymatch(arg, "dct", 2)) {
257 /* Select IDCT algorithm. */
258 if (++argn >= argc) /* advance to next argument */
259 usage();
260 if (keymatch(argv[argn], "int", 1)) {
261 cinfo->dct_method = JDCT_ISLOW;
262 } else if (keymatch(argv[argn], "fast", 2)) {
263 cinfo->dct_method = JDCT_IFAST;
264 } else if (keymatch(argv[argn], "float", 2)) {
265 cinfo->dct_method = JDCT_FLOAT;
266 } else
267 usage();
268
269 } else if (keymatch(arg, "dither", 2)) {
270 /* Select dithering algorithm. */
271 if (++argn >= argc) /* advance to next argument */
272 usage();
273 if (keymatch(argv[argn], "fs", 2)) {
274 cinfo->dither_mode = JDITHER_FS;
275 } else if (keymatch(argv[argn], "none", 2)) {
276 cinfo->dither_mode = JDITHER_NONE;
277 } else if (keymatch(argv[argn], "ordered", 2)) {
278 cinfo->dither_mode = JDITHER_ORDERED;
279 } else
280 usage();
281
282 } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
283 /* Enable debug printouts. */
284 /* On first -d, print version identification */
285 static boolean printed_version = FALSE;
286
287 if (! printed_version) {
288 fprintf(stderr, "Independent JPEG Group's DJPEG, version %s\n%s\n",
289 JVERSION, JCOPYRIGHT);
290 printed_version = TRUE;
291 }
292 cinfo->err->trace_level++;
293
294 } else if (keymatch(arg, "fast", 1)) {
295 /* Select recommended processing options for quick-and-dirty output. */
296 cinfo->two_pass_quantize = FALSE;
297 cinfo->dither_mode = JDITHER_ORDERED;
298 if (! cinfo->quantize_colors) /* don't override an earlier -colors */
299 cinfo->desired_number_of_colors = 216;
300 cinfo->dct_method = JDCT_FASTEST;
301 cinfo->do_fancy_upsampling = FALSE;
302
303 } else if (keymatch(arg, "gif", 1)) {
304 /* GIF output format (LZW compressed). */
305 requested_fmt = FMT_GIF;
306
307 } else if (keymatch(arg, "gif0", 4)) {
308 /* GIF output format (uncompressed). */
309 requested_fmt = FMT_GIF0;
310
311 } else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
312 /* Force monochrome output. */
313 cinfo->out_color_space = JCS_GRAYSCALE;
314
315 } else if (keymatch(arg, "rgb", 3)) {
316 /* Force RGB output. */
317 cinfo->out_color_space = JCS_RGB;
318
319 } else if (keymatch(arg, "map", 3)) {
320 /* Quantize to a color map taken from an input file. */
321 if (++argn >= argc) /* advance to next argument */
322 usage();
323 if (for_real) { /* too expensive to do twice! */
324 #ifdef QUANT_2PASS_SUPPORTED /* otherwise can't quantize to supplied map */
325 FILE * mapfile;
326
327 if ((mapfile = fopen(argv[argn], READ_BINARY)) == NULL) {
328 fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]);
329 exit(EXIT_FAILURE);
330 }
331 read_color_map(cinfo, mapfile);
332 fclose(mapfile);
333 cinfo->quantize_colors = TRUE;
334 #else
335 ERREXIT(cinfo, JERR_NOT_COMPILED);
336 #endif
337 }
338
339 } else if (keymatch(arg, "maxmemory", 3)) {
340 /* Maximum memory in Kb (or Mb with 'm'). */
341 long lval;
342 char ch = 'x';
343
344 if (++argn >= argc) /* advance to next argument */
345 usage();
346 if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
347 usage();
348 if (ch == 'm' || ch == 'M')
349 lval *= 1000L;
350 cinfo->mem->max_memory_to_use = lval * 1000L;
351
352 } else if (keymatch(arg, "nosmooth", 3)) {
353 /* Suppress fancy upsampling. */
354 cinfo->do_fancy_upsampling = FALSE;
355
356 } else if (keymatch(arg, "onepass", 3)) {
357 /* Use fast one-pass quantization. */
358 cinfo->two_pass_quantize = FALSE;
359
360 } else if (keymatch(arg, "os2", 3)) {
361 /* BMP output format (OS/2 flavor). */
362 requested_fmt = FMT_OS2;
363
364 } else if (keymatch(arg, "outfile", 4)) {
365 /* Set output file name. */
366 if (++argn >= argc) /* advance to next argument */
367 usage();
368 outfilename = argv[argn]; /* save it away for later use */
369
370 } else if (keymatch(arg, "pnm", 1) || keymatch(arg, "ppm", 1)) {
371 /* PPM/PGM output format. */
372 requested_fmt = FMT_PPM;
373
374 } else if (keymatch(arg, "rle", 1)) {
375 /* RLE output format. */
376 requested_fmt = FMT_RLE;
377
378 } else if (keymatch(arg, "scale", 1)) {
379 /* Scale the output image by a fraction M/N. */
380 if (++argn >= argc) /* advance to next argument */
381 usage();
382 if (sscanf(argv[argn], "%u/%u",
383 &cinfo->scale_num, &cinfo->scale_denom) < 1)
384 usage();
385
386 } else if (keymatch(arg, "targa", 1)) {
387 /* Targa output format. */
388 requested_fmt = FMT_TARGA;
389
390 } else {
391 usage(); /* bogus switch */
392 }
393 }
394
395 return argn; /* return index of next arg (file name) */
396 }
397
398
399 /*
400 * Marker processor for COM and interesting APPn markers.
401 * This replaces the library's built-in processor, which just skips the marker.
402 * We want to print out the marker as text, to the extent possible.
403 * Note this code relies on a non-suspending data source.
404 */
405
406 LOCAL(unsigned int)
407 jpeg_getc (j_decompress_ptr cinfo)
408 /* Read next byte */
409 {
410 struct jpeg_source_mgr * datasrc = cinfo->src;
411
412 if (datasrc->bytes_in_buffer == 0) {
413 if (! (*datasrc->fill_input_buffer) (cinfo))
414 ERREXIT(cinfo, JERR_CANT_SUSPEND);
415 }
416 datasrc->bytes_in_buffer--;
417 return GETJOCTET(*datasrc->next_input_byte++);
418 }
419
420
421 METHODDEF(boolean)
422 print_text_marker (j_decompress_ptr cinfo)
423 {
424 boolean traceit = (cinfo->err->trace_level >= 1);
425 INT32 length;
426 unsigned int ch;
427 unsigned int lastch = 0;
428
429 length = jpeg_getc(cinfo) << 8;
430 length += jpeg_getc(cinfo);
431 length -= 2; /* discount the length word itself */
432
433 if (traceit) {
434 if (cinfo->unread_marker == JPEG_COM)
435 fprintf(stderr, "Comment, length %ld:\n", (long) length);
436 else /* assume it is an APPn otherwise */
437 fprintf(stderr, "APP%d, length %ld:\n",
438 cinfo->unread_marker - JPEG_APP0, (long) length);
439 }
440
441 while (--length >= 0) {
442 ch = jpeg_getc(cinfo);
443 if (traceit) {
444 /* Emit the character in a readable form.
445 * Nonprintables are converted to \nnn form,
446 * while \ is converted to \\.
447 * Newlines in CR, CR/LF, or LF form will be printed as one newline.
448 */
449 if (ch == '\r') {
450 fprintf(stderr, "\n");
451 } else if (ch == '\n') {
452 if (lastch != '\r')
453 fprintf(stderr, "\n");
454 } else if (ch == '\\') {
455 fprintf(stderr, "\\\\");
456 } else if (isprint(ch)) {
457 putc(ch, stderr);
458 } else {
459 fprintf(stderr, "\\%03o", ch);
460 }
461 lastch = ch;
462 }
463 }
464
465 if (traceit)
466 fprintf(stderr, "\n");
467
468 return TRUE;
469 }
470
471
472 /*
473 * Check for overwrite of an existing file; clear it with user
474 */
475
476 #ifndef NO_OVERWRITE_CHECK
477
478 LOCAL(boolean)
479 is_write_ok (char * outfname)
480 {
481 FILE * ofile;
482 int ch;
483
484 ofile = fopen(outfname, READ_BINARY);
485 if (ofile == NULL)
486 return TRUE; /* not present */
487 fclose(ofile); /* oops, it is present */
488
489 for (;;) {
490 fprintf(stderr, "%s already exists, overwrite it? [y/n] ",
491 outfname);
492 fflush(stderr);
493 ch = getc(stdin);
494 if (ch != '\n') /* flush rest of line */
495 while (getc(stdin) != '\n')
496 /* nothing */;
497
498 switch (ch) {
499 case 'Y':
500 case 'y':
501 return TRUE;
502 case 'N':
503 case 'n':
504 return FALSE;
505 /* otherwise, ask again */
506 }
507 }
508 }
509
510 #endif
511
512
513 /*
514 * Process a single input file name, and return its index in argv[].
515 * File names at or to left of old_file_index have been processed already.
516 */
517
518 LOCAL(int)
519 process_one_file (int argc, char **argv, int old_file_index)
520 {
521 struct jpeg_decompress_struct cinfo;
522 struct jpeg_error_mgr jerr;
523 char *infilename;
524 char workfilename[PATH_MAX];
525 const char *default_extension = NULL;
526 #ifdef PROGRESS_REPORT
527 struct cdjpeg_progress_mgr progress;
528 #endif
529 int file_index;
530 djpeg_dest_ptr dest_mgr = NULL;
531 FILE * input_file = NULL;
532 FILE * output_file = NULL;
533 JDIMENSION num_scanlines;
534
535 /* Initialize the JPEG decompression object with default error handling. */
536 cinfo.err = jpeg_std_error(&jerr);
537 jpeg_create_decompress(&cinfo);
538 /* Add some application-specific error messages (from cderror.h) */
539 jerr.addon_message_table = cdjpeg_message_table;
540 jerr.first_addon_message = JMSG_FIRSTADDONCODE;
541 jerr.last_addon_message = JMSG_LASTADDONCODE;
542
543 /* Insert custom marker processor for COM and APP12.
544 * APP12 is used by some digital camera makers for textual info,
545 * so we provide the ability to display it as text.
546 * If you like, additional APPn marker types can be selected for display,
547 * but don't try to override APP0 or APP14 this way (see libjpeg.txt).
548 */
549 jpeg_set_marker_processor(&cinfo, JPEG_COM, print_text_marker);
550 jpeg_set_marker_processor(&cinfo, JPEG_APP0+12, print_text_marker);
551
552 /* Now safe to enable signal catcher. */
553 #ifdef NEED_SIGNAL_CATCHER
554 enable_signal_catcher((j_common_ptr) &cinfo);
555 #endif
556
557 /* Scan command line to find next file name.
558 * It is convenient to use just one switch-parsing routine, but the switch
559 * values read here are ignored; we will rescan the switches after opening
560 * the input file.
561 * (Exception: tracing level set here controls verbosity for COM markers
562 * found during jpeg_read_header...)
563 */
564
565 file_index = parse_switches(&cinfo, argc, argv, old_file_index, FALSE);
566 if (file_index >= argc) {
567 fprintf(stderr, "%s: missing input file name\n", progname);
568 usage();
569 }
570
571 /* Open the input file. */
572 infilename = argv[file_index];
573 if ((input_file = fopen(infilename, READ_BINARY)) == NULL) {
574 fprintf(stderr, "%s: can't open %s\n", progname, infilename);
575 goto fail;
576 }
577
578 #ifdef PROGRESS_REPORT
579 start_progress_monitor((j_common_ptr) &cinfo, &progress);
580 #endif
581
582 /* Specify data source for decompression */
583 jpeg_stdio_src(&cinfo, input_file);
584
585 /* Read file header, set default decompression parameters */
586 (void) jpeg_read_header(&cinfo, TRUE);
587
588 /* Adjust default decompression parameters by re-parsing the options */
589 file_index = parse_switches(&cinfo, argc, argv, old_file_index, TRUE);
590
591 /* Initialize the output module now to let it override any crucial
592 * option settings (for instance, GIF wants to force color quantization).
593 */
594 switch (requested_fmt) {
595 #ifdef BMP_SUPPORTED
596 case FMT_BMP:
597 dest_mgr = jinit_write_bmp(&cinfo, FALSE);
598 default_extension = ".bmp";
599 break;
600 case FMT_OS2:
601 dest_mgr = jinit_write_bmp(&cinfo, TRUE);
602 default_extension = ".bmp";
603 break;
604 #endif
605 #ifdef GIF_SUPPORTED
606 case FMT_GIF:
607 dest_mgr = jinit_write_gif(&cinfo, TRUE);
608 default_extension = ".gif";
609 break;
610 case FMT_GIF0:
611 dest_mgr = jinit_write_gif(&cinfo, FALSE);
612 default_extension = ".gif";
613 break;
614 #endif
615 #ifdef PPM_SUPPORTED
616 case FMT_PPM:
617 dest_mgr = jinit_write_ppm(&cinfo);
618 default_extension = ".ppm";
619 break;
620 #endif
621 #ifdef RLE_SUPPORTED
622 case FMT_RLE:
623 dest_mgr = jinit_write_rle(&cinfo);
624 default_extension = ".rle";
625 break;
626 #endif
627 #ifdef TARGA_SUPPORTED
628 case FMT_TARGA:
629 dest_mgr = jinit_write_targa(&cinfo);
630 default_extension = ".tga";
631 break;
632 #endif
633 default:
634 ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT);
635 }
636
637 /* If user didn't supply -outfile switch, select output file name. */
638 if (outfilename == NULL) {
639 int i;
640
641 outfilename = workfilename;
642 /* Make outfilename be infilename with appropriate extension */
643 strcpy(outfilename, infilename);
644 for (i = (int)strlen(outfilename)-1; i >= 0; i--) {
645 switch (outfilename[i]) {
646 case ':':
647 case '/':
648 case '\\':
649 i = 0; /* stop scanning */
650 break;
651 case '.':
652 outfilename[i] = '\0'; /* lop off existing extension */
653 i = 0; /* stop scanning */
654 break;
655 default:
656 break; /* keep scanning */
657 }
658 }
659 strcat(outfilename, default_extension);
660 }
661
662 fprintf(stderr, "Decompressing %s => %s\n", infilename, outfilename);
663 #ifndef NO_OVERWRITE_CHECK
664 if (! is_write_ok(outfilename))
665 goto fail;
666 #endif
667
668 /* Open the output file. */
669 if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
670 fprintf(stderr, "%s: can't create %s\n", progname, outfilename);
671 goto fail;
672 }
673 dest_mgr->output_file = output_file;
674
675 /* Start decompressor */
676 (void) jpeg_start_decompress(&cinfo);
677
678 /* Write output file header */
679 (*dest_mgr->start_output) (&cinfo, dest_mgr);
680
681 /* Process data */
682 while (cinfo.output_scanline < cinfo.output_height) {
683 num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
684 dest_mgr->buffer_height);
685 (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
686 }
687
688 #ifdef PROGRESS_REPORT
689 /* Hack: count final pass as done in case finish_output does an extra pass.
690 * The library won't have updated completed_passes.
691 */
692 progress.pub.completed_passes = progress.pub.total_passes;
693 #endif
694
695 /* Finish decompression and release memory.
696 * I must do it in this order because output module has allocated memory
697 * of lifespan JPOOL_IMAGE; it needs to finish before releasing memory.
698 */
699 (*dest_mgr->finish_output) (&cinfo, dest_mgr);
700 (void) jpeg_finish_decompress(&cinfo);
701
702 /* Clean up and exit */
703 fail:
704 jpeg_destroy_decompress(&cinfo);
705
706 if (input_file != NULL) fclose(input_file);
707 if (output_file != NULL) fclose(output_file);
708
709 #ifdef PROGRESS_REPORT
710 end_progress_monitor((j_common_ptr) &cinfo);
711 #endif
712
713 /* Disable signal catcher. */
714 #ifdef NEED_SIGNAL_CATCHER
715 enable_signal_catcher((j_common_ptr) NULL);
716 #endif
717
718 return file_index;
719 }
720
721
722 /*
723 * The main program.
724 */
725
726 int
727 main (int argc, char **argv)
728 {
729 int file_index;
730
731 /* On Mac, fetch a command line. */
732 #ifdef USE_CCOMMAND
733 argc = ccommand(&argv);
734 #endif
735
736 #ifdef MSDOS
737 progname = "djpeg"; /* DOS tends to be too verbose about argv[0] */
738 #else
739 progname = argv[0];
740 if (progname == NULL || progname[0] == 0)
741 progname = "djpeg"; /* in case C library doesn't provide it */
742 #endif
743
744 /* The default maxmem must be computed only once at program startup,
745 * since releasing memory with free() won't give it back to the OS.
746 */
747 #ifdef FREE_MEM_ESTIMATE
748 default_maxmem = FREE_MEM_ESTIMATE;
749 #else
750 default_maxmem = 0;
751 #endif
752
753 /* Scan command line, parse switches and locate input file names */
754
755 if (argc < 2)
756 usage(); /* nothing on the command line?? */
757
758 file_index = 0;
759
760 while (file_index < argc-1)
761 file_index = process_one_file(argc, argv, file_index);
762
763 /* All done. */
764 exit(EXIT_SUCCESS);
765 return 0; /* suppress no-return-value warnings */
766 }