OLD | NEW |
1 /* | 1 /* |
2 * djpeg.c | 2 * djpeg.c |
3 * | 3 * |
4 * This file was part of the Independent JPEG Group's software: | 4 * This file was part of the Independent JPEG Group's software: |
5 * Copyright (C) 1991-1997, Thomas G. Lane. | 5 * Copyright (C) 1991-1997, Thomas G. Lane. |
6 * libjpeg-turbo Modifications: | 6 * libjpeg-turbo Modifications: |
7 * Copyright (C) 2010-2011, 2013, D. R. Commander. | 7 * Copyright (C) 2010-2011, 2013-2015, D. R. Commander. |
| 8 * Copyright (C) 2015, Google, Inc. |
8 * For conditions of distribution and use, see the accompanying README file. | 9 * For conditions of distribution and use, see the accompanying README file. |
9 * | 10 * |
10 * This file contains a command-line user interface for the JPEG decompressor. | 11 * This file contains a command-line user interface for the JPEG decompressor. |
11 * It should work on any system with Unix- or MS-DOS-style command lines. | 12 * It should work on any system with Unix- or MS-DOS-style command lines. |
12 * | 13 * |
13 * Two different command line styles are permitted, depending on the | 14 * Two different command line styles are permitted, depending on the |
14 * compile-time switch TWO_FILE_COMMANDLINE: | 15 * compile-time switch TWO_FILE_COMMANDLINE: |
15 * djpeg [options] inputfile outputfile | 16 * djpeg [options] inputfile outputfile |
16 * djpeg [options] [inputfile] | 17 * djpeg [options] [inputfile] |
17 * In the second style, output is always to standard output, which you'd | 18 * In the second style, output is always to standard output, which you'd |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 * The switch parser is designed to be useful with DOS-style command line | 82 * The switch parser is designed to be useful with DOS-style command line |
82 * syntax, ie, intermixed switches and file names, where only the switches | 83 * syntax, ie, intermixed switches and file names, where only the switches |
83 * to the left of a given file name affect processing of that file. | 84 * to the left of a given file name affect processing of that file. |
84 * The main program in this file doesn't actually use this capability... | 85 * The main program in this file doesn't actually use this capability... |
85 */ | 86 */ |
86 | 87 |
87 | 88 |
88 static const char * progname; /* program name for error messages */ | 89 static const char * progname; /* program name for error messages */ |
89 static char * outfilename; /* for -outfile switch */ | 90 static char * outfilename; /* for -outfile switch */ |
90 boolean memsrc; /* for -memsrc switch */ | 91 boolean memsrc; /* for -memsrc switch */ |
| 92 boolean strip, skip; |
| 93 JDIMENSION startY, endY; |
91 #define INPUT_BUF_SIZE 4096 | 94 #define INPUT_BUF_SIZE 4096 |
92 | 95 |
93 | 96 |
94 LOCAL(void) | 97 LOCAL(void) |
95 usage (void) | 98 usage (void) |
96 /* complain about bad command line */ | 99 /* complain about bad command line */ |
97 { | 100 { |
98 fprintf(stderr, "usage: %s [switches] ", progname); | 101 fprintf(stderr, "usage: %s [switches] ", progname); |
99 #ifdef TWO_FILE_COMMANDLINE | 102 #ifdef TWO_FILE_COMMANDLINE |
100 fprintf(stderr, "inputfile outputfile\n"); | 103 fprintf(stderr, "inputfile outputfile\n"); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
156 fprintf(stderr, " -nosmooth Don't use high-quality upsampling\n"); | 159 fprintf(stderr, " -nosmooth Don't use high-quality upsampling\n"); |
157 #ifdef QUANT_1PASS_SUPPORTED | 160 #ifdef QUANT_1PASS_SUPPORTED |
158 fprintf(stderr, " -onepass Use 1-pass quantization (fast, low quality)\
n"); | 161 fprintf(stderr, " -onepass Use 1-pass quantization (fast, low quality)\
n"); |
159 #endif | 162 #endif |
160 fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n"); | 163 fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n"); |
161 fprintf(stderr, " -outfile name Specify name for output file\n"); | 164 fprintf(stderr, " -outfile name Specify name for output file\n"); |
162 #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) | 165 #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) |
163 fprintf(stderr, " -memsrc Load input file into memory before decompres
sing\n"); | 166 fprintf(stderr, " -memsrc Load input file into memory before decompres
sing\n"); |
164 #endif | 167 #endif |
165 | 168 |
| 169 fprintf(stderr, " -skip Y0,Y1 Decode all rows except those between Y0 and
Y1 (inclusive)\n"); |
| 170 fprintf(stderr, " -strip Y0,Y1 Decode only rows between Y0 and Y1 (inclusiv
e)\n"); |
166 fprintf(stderr, " -verbose or -debug Emit debug output\n"); | 171 fprintf(stderr, " -verbose or -debug Emit debug output\n"); |
167 exit(EXIT_FAILURE); | 172 exit(EXIT_FAILURE); |
168 } | 173 } |
169 | 174 |
170 | 175 |
171 LOCAL(int) | 176 LOCAL(int) |
172 parse_switches (j_decompress_ptr cinfo, int argc, char **argv, | 177 parse_switches (j_decompress_ptr cinfo, int argc, char **argv, |
173 int last_file_arg_seen, boolean for_real) | 178 int last_file_arg_seen, boolean for_real) |
174 /* Parse optional switches. | 179 /* Parse optional switches. |
175 * Returns argv[] index of first file-name argument (== argc if none). | 180 * Returns argv[] index of first file-name argument (== argc if none). |
176 * Any file names with indexes <= last_file_arg_seen are ignored; | 181 * Any file names with indexes <= last_file_arg_seen are ignored; |
177 * they have presumably been processed in a previous iteration. | 182 * they have presumably been processed in a previous iteration. |
178 * (Pass 0 for last_file_arg_seen on the first or only iteration.) | 183 * (Pass 0 for last_file_arg_seen on the first or only iteration.) |
179 * for_real is FALSE on the first (dummy) pass; we may skip any expensive | 184 * for_real is FALSE on the first (dummy) pass; we may skip any expensive |
180 * processing. | 185 * processing. |
181 */ | 186 */ |
182 { | 187 { |
183 int argn; | 188 int argn; |
184 char * arg; | 189 char * arg; |
185 | 190 |
186 /* Set up default JPEG parameters. */ | 191 /* Set up default JPEG parameters. */ |
187 requested_fmt = DEFAULT_FMT; /* set default output file format */ | 192 requested_fmt = DEFAULT_FMT; /* set default output file format */ |
188 outfilename = NULL; | 193 outfilename = NULL; |
189 memsrc = FALSE; | 194 memsrc = FALSE; |
| 195 strip = FALSE; |
| 196 skip = FALSE; |
190 cinfo->err->trace_level = 0; | 197 cinfo->err->trace_level = 0; |
191 | 198 |
192 /* Scan command line options, adjust parameters */ | 199 /* Scan command line options, adjust parameters */ |
193 | 200 |
194 for (argn = 1; argn < argc; argn++) { | 201 for (argn = 1; argn < argc; argn++) { |
195 arg = argv[argn]; | 202 arg = argv[argn]; |
196 if (*arg != '-') { | 203 if (*arg != '-') { |
197 /* Not a switch, must be a file name argument */ | 204 /* Not a switch, must be a file name argument */ |
198 if (argn <= last_file_arg_seen) { | 205 if (argn <= last_file_arg_seen) { |
199 outfilename = NULL; /* -outfile applies to just one input file */ | 206 outfilename = NULL; /* -outfile applies to just one input file */ |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
343 #endif | 350 #endif |
344 | 351 |
345 } else if (keymatch(arg, "pnm", 1) || keymatch(arg, "ppm", 1)) { | 352 } else if (keymatch(arg, "pnm", 1) || keymatch(arg, "ppm", 1)) { |
346 /* PPM/PGM output format. */ | 353 /* PPM/PGM output format. */ |
347 requested_fmt = FMT_PPM; | 354 requested_fmt = FMT_PPM; |
348 | 355 |
349 } else if (keymatch(arg, "rle", 1)) { | 356 } else if (keymatch(arg, "rle", 1)) { |
350 /* RLE output format. */ | 357 /* RLE output format. */ |
351 requested_fmt = FMT_RLE; | 358 requested_fmt = FMT_RLE; |
352 | 359 |
353 } else if (keymatch(arg, "scale", 1)) { | 360 } else if (keymatch(arg, "scale", 2)) { |
354 /* Scale the output image by a fraction M/N. */ | 361 /* Scale the output image by a fraction M/N. */ |
355 if (++argn >= argc) /* advance to next argument */ | 362 if (++argn >= argc) /* advance to next argument */ |
356 usage(); | 363 usage(); |
357 if (sscanf(argv[argn], "%d/%d", | 364 if (sscanf(argv[argn], "%d/%d", |
358 &cinfo->scale_num, &cinfo->scale_denom) != 2) | 365 &cinfo->scale_num, &cinfo->scale_denom) != 2) |
359 usage(); | 366 usage(); |
360 | 367 |
| 368 } else if (keymatch(arg, "strip", 2)) { |
| 369 if (++argn >= argc) |
| 370 usage(); |
| 371 if (sscanf(argv[argn], "%d,%d", &startY, &endY) != 2 || startY > endY) |
| 372 usage(); |
| 373 strip = TRUE; |
| 374 |
| 375 } else if (keymatch(arg, "skip", 2)) { |
| 376 if (++argn >= argc) |
| 377 usage(); |
| 378 if (sscanf(argv[argn], "%d,%d", &startY, &endY) != 2 || startY > endY) |
| 379 usage(); |
| 380 skip = TRUE; |
| 381 |
361 } else if (keymatch(arg, "targa", 1)) { | 382 } else if (keymatch(arg, "targa", 1)) { |
362 /* Targa output format. */ | 383 /* Targa output format. */ |
363 requested_fmt = FMT_TARGA; | 384 requested_fmt = FMT_TARGA; |
364 | 385 |
365 } else { | 386 } else { |
366 usage(); /* bogus switch */ | 387 usage(); /* bogus switch */ |
367 } | 388 } |
368 } | 389 } |
369 | 390 |
370 return argn; /* return index of next arg (file name) */ | 391 return argn; /* return index of next arg (file name) */ |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
621 #endif | 642 #endif |
622 default: | 643 default: |
623 ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT); | 644 ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT); |
624 break; | 645 break; |
625 } | 646 } |
626 dest_mgr->output_file = output_file; | 647 dest_mgr->output_file = output_file; |
627 | 648 |
628 /* Start decompressor */ | 649 /* Start decompressor */ |
629 (void) jpeg_start_decompress(&cinfo); | 650 (void) jpeg_start_decompress(&cinfo); |
630 | 651 |
631 /* Write output file header */ | 652 /* Strip decode */ |
632 (*dest_mgr->start_output) (&cinfo, dest_mgr); | 653 if (strip || skip) { |
| 654 JDIMENSION tmp; |
633 | 655 |
634 /* Process data */ | 656 /* Check for valid endY. We cannot check this value until after |
635 while (cinfo.output_scanline < cinfo.output_height) { | 657 * jpeg_start_decompress() is called. Note that we have already verified |
636 num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer, | 658 * that startY <= endY. |
637 » » » » » dest_mgr->buffer_height); | 659 */ |
638 (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines); | 660 if (endY > cinfo.output_height - 1) { |
| 661 fprintf(stderr, "%s: strip %d-%d exceeds image height %d\n", progname, |
| 662 startY, endY, cinfo.output_height); |
| 663 exit(EXIT_FAILURE); |
| 664 } |
| 665 |
| 666 /* Write output file header. This is a hack to ensure that the destination |
| 667 * manager creates an image of the proper size for the partial decode. |
| 668 */ |
| 669 tmp = cinfo.output_height; |
| 670 cinfo.output_height = endY - startY + 1; |
| 671 if (skip) |
| 672 cinfo.output_height = tmp - cinfo.output_height; |
| 673 (*dest_mgr->start_output) (&cinfo, dest_mgr); |
| 674 cinfo.output_height = tmp; |
| 675 |
| 676 /* Process data */ |
| 677 if (skip) { |
| 678 while (cinfo.output_scanline < startY) { |
| 679 num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer, |
| 680 dest_mgr->buffer_height); |
| 681 (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines); |
| 682 } |
| 683 jpeg_skip_scanlines(&cinfo, endY - startY + 1); |
| 684 while (cinfo.output_scanline < cinfo.output_height) { |
| 685 num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer, |
| 686 dest_mgr->buffer_height); |
| 687 (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines); |
| 688 } |
| 689 } else { |
| 690 jpeg_skip_scanlines(&cinfo, startY); |
| 691 while (cinfo.output_scanline <= endY) { |
| 692 num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer, |
| 693 dest_mgr->buffer_height); |
| 694 (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines); |
| 695 } |
| 696 jpeg_skip_scanlines(&cinfo, cinfo.output_height - endY + 1); |
| 697 } |
| 698 |
| 699 /* Normal full image decode */ |
| 700 } else { |
| 701 /* Write output file header */ |
| 702 (*dest_mgr->start_output) (&cinfo, dest_mgr); |
| 703 |
| 704 /* Process data */ |
| 705 while (cinfo.output_scanline < cinfo.output_height) { |
| 706 num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer, |
| 707 dest_mgr->buffer_height); |
| 708 (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines); |
| 709 } |
639 } | 710 } |
640 | 711 |
641 #ifdef PROGRESS_REPORT | 712 #ifdef PROGRESS_REPORT |
642 /* Hack: count final pass as done in case finish_output does an extra pass. | 713 /* Hack: count final pass as done in case finish_output does an extra pass. |
643 * The library won't have updated completed_passes. | 714 * The library won't have updated completed_passes. |
644 */ | 715 */ |
645 progress.pub.completed_passes = progress.pub.total_passes; | 716 progress.pub.completed_passes = progress.pub.total_passes; |
646 #endif | 717 #endif |
647 | 718 |
648 /* Finish decompression and release memory. | 719 /* Finish decompression and release memory. |
(...skipping 14 matching lines...) Expand all Loading... |
663 end_progress_monitor((j_common_ptr) &cinfo); | 734 end_progress_monitor((j_common_ptr) &cinfo); |
664 #endif | 735 #endif |
665 | 736 |
666 if (memsrc && inbuffer != NULL) | 737 if (memsrc && inbuffer != NULL) |
667 free(inbuffer); | 738 free(inbuffer); |
668 | 739 |
669 /* All done. */ | 740 /* All done. */ |
670 exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS); | 741 exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS); |
671 return 0; /* suppress no-return-value warnings */ | 742 return 0; /* suppress no-return-value warnings */ |
672 } | 743 } |
OLD | NEW |