Skip to content

Commit

Permalink
Further partial image decompression fixes
Browse files Browse the repository at this point in the history
- Referring to 073b0e8 and #185, the
  reason why BMP and RLE didn't (and won't) work with partial image
  decompression is that the output engines for both formats maintain a
  whole-image buffer, which is used to reverse the order of scanlines.
  However, it was straightforward to add -crop support for GIF and
  Targa, which is useful for testing partial image decompression along
  with color quantization.
- Such testing reproduced a bug reported by Mozilla (refer to PR #182)
  whereby jpeg_skip_scanlines() would segfault if color quantization was
  enabled.  To fix this issue, read_and_discard_scanlines() now sets up
  a dummy quantize function in the same manner that it sets up a dummy
  color conversion function.

Closes #182
  • Loading branch information
dcommander committed Nov 14, 2017
1 parent f3ad13e commit 5bc43c7
Show file tree
Hide file tree
Showing 11 changed files with 110 additions and 52 deletions.
13 changes: 10 additions & 3 deletions ChangeLog.md
Expand Up @@ -10,9 +10,16 @@ image planes and allocates memory for the image planes.
2. Fixed an issue whereby the Java version of TJUnitTest would fail when
testing BufferedImage encoding/decoding on big endian systems.

3. djpeg will now exit gracefully if an output image format other than PPM/PGM
is selected along with the `-crop` option. That option does not currently work
with other output image formats.
3. Fixed a segfault in djpeg that would occur if an output format other than
PPM/PGM was selected along with the `-crop` option. The `-crop` option now
works with the GIF and Targa formats as well (unfortunately, it cannot be made
to work with the BMP and RLE formats due to the fact that those output engines
write scanlines in bottom-up order.) djpeg will now exit gracefully if an
output format other than PPM/PGM, GIF, or Targa is selected along with the
`-crop` option.

4. Fixed an issue whereby `jpeg_skip_scanlines()` would segfault if color
quantization was enabled.

4. TJBench (both C and Java versions) will now display usage information if any
command-line argument is unrecognized. This prevents the program from silently
Expand Down
12 changes: 10 additions & 2 deletions cdjpeg.h
Expand Up @@ -3,8 +3,8 @@
*
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1994-1997, Thomas G. Lane.
* It was modified by The libjpeg-turbo Project to include only code relevant
* to libjpeg-turbo.
* libjpeg-turbo Modifications:
* Copyright (C) 2017, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
Expand Down Expand Up @@ -54,6 +54,14 @@ struct djpeg_dest_struct {
JDIMENSION rows_supplied);
/* Finish up at the end of the image. */
void (*finish_output) (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo);
/* Re-calculate buffer dimensions based on output dimensions (for use with
partial image decompression.) If this is NULL, then the output format
does not support partial image decompression (BMP and RLE, in particular,
cannot support partial decompression because they use an inversion buffer
to write the image in bottom-up order.) */
void (*calc_buffer_dimensions) (j_decompress_ptr cinfo,
djpeg_dest_ptr dinfo);


/* Target file spec; filled in by djpeg.c after object is created. */
FILE *output_file;
Expand Down
4 changes: 2 additions & 2 deletions djpeg.1
@@ -1,4 +1,4 @@
.TH DJPEG 1 "8 November 2017"
.TH DJPEG 1 "13 November 2017"
.SH NAME
djpeg \- decompress a JPEG file to an image file
.SH SYNOPSIS
Expand Down Expand Up @@ -205,7 +205,7 @@ with width W and height H. If necessary, X will be shifted left to the nearest
iMCU boundary, and the width will be increased accordingly. Note that if
decompression scaling is being used, then X, Y, W, and H are relative to the
scaled image dimensions. Currently this option only works with the
PBMPLUS (PPM/PGM) output format.
PBMPLUS (PPM/PGM), GIF, and Targa output formats.
.TP
.B \-verbose
Enable debug printout. More
Expand Down
10 changes: 4 additions & 6 deletions djpeg.c
Expand Up @@ -31,7 +31,6 @@
#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
#include "jversion.h" /* for version message */
#include "jconfigint.h"
#include "wrppm.h"

#include <ctype.h> /* to declare isprint() */

Expand Down Expand Up @@ -173,7 +172,7 @@ usage (void)

fprintf(stderr, " -skip Y0,Y1 Decompress all rows except those between Y0 and Y1 (inclusive)\n");
fprintf(stderr, " -crop WxH+X+Y Decompress only a rectangular subregion of the image\n");
fprintf(stderr, " [requires PBMPLUS (PPM/PGM) output format]\n");
fprintf(stderr, " [requires PBMPLUS (PPM/PGM), GIF, or Targa output format]\n");
fprintf(stderr, " -verbose or -debug Emit debug output\n");
fprintf(stderr, " -version Print version information and exit\n");
exit(EXIT_FAILURE);
Expand Down Expand Up @@ -714,11 +713,10 @@ main (int argc, char **argv)
}

jpeg_crop_scanline(&cinfo, &crop_x, &crop_width);
if (requested_fmt != FMT_PPM)
if (dest_mgr->calc_buffer_dimensions)
(*dest_mgr->calc_buffer_dimensions) (&cinfo, dest_mgr);
else
ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT);
((ppm_dest_ptr) dest_mgr)->buffer_width = cinfo.output_width *
cinfo.out_color_components *
sizeof(JSAMPLE);

/* Write output file header. This is a hack to ensure that the destination
* manager creates an output image of the proper size.
Expand Down
18 changes: 17 additions & 1 deletion jdapistd.c
Expand Up @@ -4,7 +4,7 @@
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1994-1996, Thomas G. Lane.
* libjpeg-turbo Modifications:
* Copyright (C) 2010, 2015-2016, D. R. Commander.
* Copyright (C) 2010, 2015-2017, D. R. Commander.
* Copyright (C) 2015, Google, Inc.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
Expand Down Expand Up @@ -293,6 +293,14 @@ noop_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
}


/* Dummy quantize function used by jpeg_skip_scanlines() */
LOCAL(void)
noop_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
JSAMPARRAY output_buf, int num_rows)
{
}


/*
* In some cases, it is best to call jpeg_read_scanlines() and discard the
* output, rather than skipping the scanlines, because this allows us to
Expand All @@ -308,14 +316,22 @@ read_and_discard_scanlines (j_decompress_ptr cinfo, JDIMENSION num_lines)
void (*color_convert) (j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
JDIMENSION input_row, JSAMPARRAY output_buf,
int num_rows);
void (*color_quantize) (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
JSAMPARRAY output_buf, int num_rows) = NULL;

color_convert = cinfo->cconvert->color_convert;
cinfo->cconvert->color_convert = noop_convert;
if (cinfo->cquantize && cinfo->cquantize->color_quantize) {
color_quantize = cinfo->cquantize->color_quantize;
cinfo->cquantize->color_quantize = noop_quantize;
}

for (n = 0; n < num_lines; n++)
jpeg_read_scanlines(cinfo, NULL, 1);

cinfo->cconvert->color_convert = color_convert;
if (color_quantize)
cinfo->cquantize->color_quantize = color_quantize;
}


Expand Down
3 changes: 2 additions & 1 deletion wrbmp.c
Expand Up @@ -5,7 +5,7 @@
* Copyright (C) 1994-1996, Thomas G. Lane.
* libjpeg-turbo Modifications:
* Copyright (C) 2013, Linaro Limited.
* Copyright (C) 2014-2015, D. R. Commander.
* Copyright (C) 2014-2015, 2017, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
Expand Down Expand Up @@ -437,6 +437,7 @@ jinit_write_bmp (j_decompress_ptr cinfo, boolean is_os2)
sizeof(bmp_dest_struct));
dest->pub.start_output = start_output_bmp;
dest->pub.finish_output = finish_output_bmp;
dest->pub.calc_buffer_dimensions = NULL;
dest->is_os2 = is_os2;

if (cinfo->out_color_space == JCS_GRAYSCALE) {
Expand Down
13 changes: 12 additions & 1 deletion wrgif.c
Expand Up @@ -4,7 +4,7 @@
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1991-1997, Thomas G. Lane.
* libjpeg-turbo Modifications:
* Copyright (C) 2015, D. R. Commander.
* Copyright (C) 2015, 2017, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
Expand Down Expand Up @@ -355,6 +355,16 @@ finish_output_gif (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
}


/*
* Re-calculate buffer dimensions based on output dimensions.
*/

METHODDEF(void)
calc_buffer_dimensions_gif (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
{
}


/*
* The module selection routine for GIF format output.
*/
Expand All @@ -372,6 +382,7 @@ jinit_write_gif (j_decompress_ptr cinfo)
dest->pub.start_output = start_output_gif;
dest->pub.put_pixel_rows = put_pixel_rows;
dest->pub.finish_output = finish_output_gif;
dest->pub.calc_buffer_dimensions = calc_buffer_dimensions_gif;

if (cinfo->out_color_space != JCS_GRAYSCALE &&
cinfo->out_color_space != JCS_RGB)
Expand Down
38 changes: 33 additions & 5 deletions wrppm.c
Expand Up @@ -4,8 +4,8 @@
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1991-1996, Thomas G. Lane.
* Modified 2009 by Guido Vollbeding.
* It was modified by The libjpeg-turbo Project to include only code and
* information relevant to libjpeg-turbo.
* libjpeg-turbo Modifications:
* Copyright (C) 2017, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
Expand All @@ -20,7 +20,6 @@
*/

#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
#include "wrppm.h"

#ifdef PPM_SUPPORTED

Expand Down Expand Up @@ -63,6 +62,21 @@
*/


/* Private version of data destination object */

typedef struct {
struct djpeg_dest_struct pub; /* public fields */

/* Usually these two pointers point to the same place: */
char *iobuffer; /* fwrite's I/O buffer */
JSAMPROW pixrow; /* decompressor output buffer */
size_t buffer_width; /* width of I/O buffer */
JDIMENSION samples_per_row; /* JSAMPLEs per output row */
} ppm_dest_struct;

typedef ppm_dest_struct *ppm_dest_ptr;


/*
* Write some pixel data.
* In this module rows_supplied will always be 1.
Expand Down Expand Up @@ -196,6 +210,20 @@ finish_output_ppm (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
}


/*
* Re-calculate buffer dimensions based on output dimensions.
*/

METHODDEF(void)
calc_buffer_dimensions_ppm (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
{
ppm_dest_ptr dest = (ppm_dest_ptr) dinfo;

dest->samples_per_row = cinfo->output_width * cinfo->out_color_components;
dest->buffer_width = dest->samples_per_row * (BYTESPERSAMPLE * sizeof(char));
}


/*
* The module selection routine for PPM format output.
*/
Expand All @@ -211,13 +239,13 @@ jinit_write_ppm (j_decompress_ptr cinfo)
sizeof(ppm_dest_struct));
dest->pub.start_output = start_output_ppm;
dest->pub.finish_output = finish_output_ppm;
dest->pub.calc_buffer_dimensions = calc_buffer_dimensions_ppm;

/* Calculate output image dimensions so we can allocate space */
jpeg_calc_output_dimensions(cinfo);

/* Create physical I/O buffer */
dest->samples_per_row = cinfo->output_width * cinfo->out_color_components;
dest->buffer_width = dest->samples_per_row * (BYTESPERSAMPLE * sizeof(char));
dest->pub.calc_buffer_dimensions (cinfo, (djpeg_dest_ptr) dest);
dest->iobuffer = (char *) (*cinfo->mem->alloc_small)
((j_common_ptr) cinfo, JPOOL_IMAGE, dest->buffer_width);

Expand Down
26 changes: 0 additions & 26 deletions wrppm.h

This file was deleted.

5 changes: 3 additions & 2 deletions wrrle.c
Expand Up @@ -3,8 +3,8 @@
*
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1991-1996, Thomas G. Lane.
* It was modified by The libjpeg-turbo Project to include only code and
* information relevant to libjpeg-turbo.
* libjpeg-turbo Modifications:
* Copyright (C) 2017, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
Expand Down Expand Up @@ -286,6 +286,7 @@ jinit_write_rle (j_decompress_ptr cinfo)
sizeof(rle_dest_struct));
dest->pub.start_output = start_output_rle;
dest->pub.finish_output = finish_output_rle;
dest->pub.calc_buffer_dimensions = NULL;

/* Calculate output image dimensions so we can allocate space */
jpeg_calc_output_dimensions(cinfo);
Expand Down
20 changes: 17 additions & 3 deletions wrtarga.c
Expand Up @@ -3,8 +3,8 @@
*
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1991-1996, Thomas G. Lane.
* It was modified by The libjpeg-turbo Project to include only code and
* information relevant to libjpeg-turbo.
* libjpeg-turbo Modifications:
* Copyright (C) 2017, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
Expand Down Expand Up @@ -211,6 +211,19 @@ finish_output_tga (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
}


/*
* Re-calculate buffer dimensions based on output dimensions.
*/

METHODDEF(void)
calc_buffer_dimensions_tga (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
{
tga_dest_ptr dest = (tga_dest_ptr) dinfo;

dest->buffer_width = cinfo->output_width * cinfo->output_components;
}


/*
* The module selection routine for Targa format output.
*/
Expand All @@ -226,12 +239,13 @@ jinit_write_targa (j_decompress_ptr cinfo)
sizeof(tga_dest_struct));
dest->pub.start_output = start_output_tga;
dest->pub.finish_output = finish_output_tga;
dest->pub.calc_buffer_dimensions = calc_buffer_dimensions_tga;

/* Calculate output image dimensions so we can allocate space */
jpeg_calc_output_dimensions(cinfo);

/* Create I/O buffer. */
dest->buffer_width = cinfo->output_width * cinfo->output_components;
dest->pub.calc_buffer_dimensions (cinfo, (djpeg_dest_ptr) dest);
dest->iobuffer = (char *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
(size_t) (dest->buffer_width * sizeof(char)));
Expand Down

0 comments on commit 5bc43c7

Please sign in to comment.