| Index: djpeg.c
|
| diff --git a/djpeg.c b/djpeg.c
|
| index 589c5805cb54a1a39b2ffe4f2edb707062876c70..925ca8a8d71aaf90ee726bfec9478b0d3009cc54 100644
|
| --- a/djpeg.c
|
| +++ b/djpeg.c
|
| @@ -4,7 +4,8 @@
|
| * This file was part of the Independent JPEG Group's software:
|
| * Copyright (C) 1991-1997, Thomas G. Lane.
|
| * libjpeg-turbo Modifications:
|
| - * Copyright (C) 2010-2011, 2013, D. R. Commander.
|
| + * Copyright (C) 2010-2011, 2013-2015, D. R. Commander.
|
| + * Copyright (C) 2015, Google, Inc.
|
| * For conditions of distribution and use, see the accompanying README file.
|
| *
|
| * This file contains a command-line user interface for the JPEG decompressor.
|
| @@ -88,6 +89,8 @@ static IMAGE_FORMATS requested_fmt;
|
| static const char * progname; /* program name for error messages */
|
| static char * outfilename; /* for -outfile switch */
|
| boolean memsrc; /* for -memsrc switch */
|
| +boolean strip, skip;
|
| +JDIMENSION startY, endY;
|
| #define INPUT_BUF_SIZE 4096
|
|
|
|
|
| @@ -163,6 +166,8 @@ usage (void)
|
| fprintf(stderr, " -memsrc Load input file into memory before decompressing\n");
|
| #endif
|
|
|
| + fprintf(stderr, " -skip Y0,Y1 Decode all rows except those between Y0 and Y1 (inclusive)\n");
|
| + fprintf(stderr, " -strip Y0,Y1 Decode only rows between Y0 and Y1 (inclusive)\n");
|
| fprintf(stderr, " -verbose or -debug Emit debug output\n");
|
| exit(EXIT_FAILURE);
|
| }
|
| @@ -187,6 +192,8 @@ parse_switches (j_decompress_ptr cinfo, int argc, char **argv,
|
| requested_fmt = DEFAULT_FMT; /* set default output file format */
|
| outfilename = NULL;
|
| memsrc = FALSE;
|
| + strip = FALSE;
|
| + skip = FALSE;
|
| cinfo->err->trace_level = 0;
|
|
|
| /* Scan command line options, adjust parameters */
|
| @@ -350,7 +357,7 @@ parse_switches (j_decompress_ptr cinfo, int argc, char **argv,
|
| /* RLE output format. */
|
| requested_fmt = FMT_RLE;
|
|
|
| - } else if (keymatch(arg, "scale", 1)) {
|
| + } else if (keymatch(arg, "scale", 2)) {
|
| /* Scale the output image by a fraction M/N. */
|
| if (++argn >= argc) /* advance to next argument */
|
| usage();
|
| @@ -358,6 +365,20 @@ parse_switches (j_decompress_ptr cinfo, int argc, char **argv,
|
| &cinfo->scale_num, &cinfo->scale_denom) != 2)
|
| usage();
|
|
|
| + } else if (keymatch(arg, "strip", 2)) {
|
| + if (++argn >= argc)
|
| + usage();
|
| + if (sscanf(argv[argn], "%d,%d", &startY, &endY) != 2 || startY > endY)
|
| + usage();
|
| + strip = TRUE;
|
| +
|
| + } else if (keymatch(arg, "skip", 2)) {
|
| + if (++argn >= argc)
|
| + usage();
|
| + if (sscanf(argv[argn], "%d,%d", &startY, &endY) != 2 || startY > endY)
|
| + usage();
|
| + skip = TRUE;
|
| +
|
| } else if (keymatch(arg, "targa", 1)) {
|
| /* Targa output format. */
|
| requested_fmt = FMT_TARGA;
|
| @@ -628,14 +649,64 @@ main (int argc, char **argv)
|
| /* Start decompressor */
|
| (void) jpeg_start_decompress(&cinfo);
|
|
|
| - /* Write output file header */
|
| - (*dest_mgr->start_output) (&cinfo, dest_mgr);
|
| + /* Strip decode */
|
| + if (strip || skip) {
|
| + JDIMENSION tmp;
|
| +
|
| + /* Check for valid endY. We cannot check this value until after
|
| + * jpeg_start_decompress() is called. Note that we have already verified
|
| + * that startY <= endY.
|
| + */
|
| + if (endY > cinfo.output_height - 1) {
|
| + fprintf(stderr, "%s: strip %d-%d exceeds image height %d\n", progname,
|
| + startY, endY, cinfo.output_height);
|
| + exit(EXIT_FAILURE);
|
| + }
|
| +
|
| + /* Write output file header. This is a hack to ensure that the destination
|
| + * manager creates an image of the proper size for the partial decode.
|
| + */
|
| + tmp = cinfo.output_height;
|
| + cinfo.output_height = endY - startY + 1;
|
| + if (skip)
|
| + cinfo.output_height = tmp - cinfo.output_height;
|
| + (*dest_mgr->start_output) (&cinfo, dest_mgr);
|
| + cinfo.output_height = tmp;
|
| +
|
| + /* Process data */
|
| + if (skip) {
|
| + while (cinfo.output_scanline < startY) {
|
| + num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
|
| + dest_mgr->buffer_height);
|
| + (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
|
| + }
|
| + jpeg_skip_scanlines(&cinfo, endY - startY + 1);
|
| + while (cinfo.output_scanline < cinfo.output_height) {
|
| + num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
|
| + dest_mgr->buffer_height);
|
| + (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
|
| + }
|
| + } else {
|
| + jpeg_skip_scanlines(&cinfo, startY);
|
| + while (cinfo.output_scanline <= endY) {
|
| + num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
|
| + dest_mgr->buffer_height);
|
| + (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
|
| + }
|
| + jpeg_skip_scanlines(&cinfo, cinfo.output_height - endY + 1);
|
| + }
|
|
|
| - /* Process data */
|
| - while (cinfo.output_scanline < cinfo.output_height) {
|
| - num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
|
| - dest_mgr->buffer_height);
|
| - (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
|
| + /* Normal full image decode */
|
| + } else {
|
| + /* Write output file header */
|
| + (*dest_mgr->start_output) (&cinfo, dest_mgr);
|
| +
|
| + /* Process data */
|
| + while (cinfo.output_scanline < cinfo.output_height) {
|
| + num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
|
| + dest_mgr->buffer_height);
|
| + (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
|
| + }
|
| }
|
|
|
| #ifdef PROGRESS_REPORT
|
|
|