| 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 |