You've already forked libjpeg-turbo
mirror of
https://github.com/libjpeg-turbo/libjpeg-turbo.git
synced 2026-10-23 11:48:53 +03:00
djpeg: Opt. read multiple scanlines at a time
... when writing PBMPLUS files. This exercises certain partial image decompression and RGB565 conversion code paths that djpeg otherwise wouldn't touch, which helps expose issues such as #915 and #929.
This commit is contained in:
11
src/cdjpeg.h
11
src/cdjpeg.h
@@ -13,8 +13,19 @@
|
||||
* cjpeg and djpeg. It is NOT used by the core JPEG library.
|
||||
*/
|
||||
|
||||
/* Uncomment this to make djpeg process more than one scanline at a time when
|
||||
* writing PBMPLUS (PPM/PGM) files, which exercises esoteric code paths in the
|
||||
* library that would otherwise be difficult to test.
|
||||
*
|
||||
#define DJPEG_MULTILINE
|
||||
*/
|
||||
|
||||
#define JPEG_CJPEG_DJPEG /* define proper options in jconfig.h */
|
||||
#ifdef DJPEG_MULTILINE
|
||||
#define JPEG_INTERNALS
|
||||
#else
|
||||
#define JPEG_INTERNAL_OPTIONS /* cjpeg.c,djpeg.c need to see xxx_SUPPORTED */
|
||||
#endif
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jerror.h" /* get library error codes too */
|
||||
|
||||
26
src/djpeg.c
26
src/djpeg.c
@@ -808,8 +808,12 @@ main(int argc, char **argv)
|
||||
if (cinfo.data_precision == 8) {
|
||||
/* Process data */
|
||||
while (cinfo.output_scanline < skip_start) {
|
||||
JDIMENSION max_lines = dest_mgr->buffer_height;
|
||||
#ifdef DJPEG_MULTILINE
|
||||
max_lines = MIN(max_lines, skip_start - cinfo.output_scanline);
|
||||
#endif
|
||||
num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
|
||||
dest_mgr->buffer_height);
|
||||
max_lines);
|
||||
(*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
|
||||
}
|
||||
if ((tmp = jpeg_skip_scanlines(&cinfo, skip_end - skip_start + 1)) !=
|
||||
@@ -826,8 +830,12 @@ main(int argc, char **argv)
|
||||
} else if (cinfo.data_precision == 12) {
|
||||
/* Process data */
|
||||
while (cinfo.output_scanline < skip_start) {
|
||||
JDIMENSION max_lines = dest_mgr->buffer_height;
|
||||
#ifdef DJPEG_MULTILINE
|
||||
max_lines = MIN(max_lines, skip_start - cinfo.output_scanline);
|
||||
#endif
|
||||
num_scanlines = jpeg12_read_scanlines(&cinfo, dest_mgr->buffer12,
|
||||
dest_mgr->buffer_height);
|
||||
max_lines);
|
||||
(*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
|
||||
}
|
||||
if ((tmp = jpeg12_skip_scanlines(&cinfo, skip_end - skip_start + 1)) !=
|
||||
@@ -885,8 +893,13 @@ main(int argc, char **argv)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
while (cinfo.output_scanline < crop_y + crop_height) {
|
||||
JDIMENSION max_lines = dest_mgr->buffer_height;
|
||||
#ifdef DJPEG_MULTILINE
|
||||
max_lines = MIN(max_lines,
|
||||
crop_y + crop_height - cinfo.output_scanline);
|
||||
#endif
|
||||
num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
|
||||
dest_mgr->buffer_height);
|
||||
max_lines);
|
||||
(*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
|
||||
}
|
||||
if ((tmp =
|
||||
@@ -905,8 +918,13 @@ main(int argc, char **argv)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
while (cinfo.output_scanline < crop_y + crop_height) {
|
||||
JDIMENSION max_lines = dest_mgr->buffer_height;
|
||||
#ifdef DJPEG_MULTILINE
|
||||
max_lines = MIN(max_lines,
|
||||
crop_y + crop_height - cinfo.output_scanline);
|
||||
#endif
|
||||
num_scanlines = jpeg12_read_scanlines(&cinfo, dest_mgr->buffer12,
|
||||
dest_mgr->buffer_height);
|
||||
max_lines);
|
||||
(*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
|
||||
}
|
||||
if ((tmp =
|
||||
|
||||
171
src/wrppm.c
171
src/wrppm.c
@@ -19,6 +19,7 @@
|
||||
* an ordinary stdio stream.
|
||||
*/
|
||||
|
||||
|
||||
#include "cmyk.h"
|
||||
#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
|
||||
|
||||
@@ -99,6 +100,8 @@ static INLINE boolean is_big_endian(void)
|
||||
* output buffer is physically the same as the fwrite buffer.
|
||||
*/
|
||||
|
||||
#ifndef DJPEG_MULTILINE
|
||||
|
||||
METHODDEF(void)
|
||||
put_pixel_rows(j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
|
||||
JDIMENSION rows_supplied)
|
||||
@@ -110,6 +113,8 @@ put_pixel_rows(j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* This code is used when we have to copy the data and apply a pixel
|
||||
@@ -123,14 +128,20 @@ copy_pixel_rows(j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
|
||||
ppm_dest_ptr dest = (ppm_dest_ptr)dinfo;
|
||||
register char *bufferptr;
|
||||
register _JSAMPROW ptr;
|
||||
register JDIMENSION col;
|
||||
register JDIMENSION row = 0, col;
|
||||
|
||||
ptr = dest->pub._buffer[0];
|
||||
bufferptr = dest->iobuffer;
|
||||
for (col = dest->samples_per_row; col > 0; col--) {
|
||||
PUTPPMSAMPLE(bufferptr, *ptr++);
|
||||
#ifdef DJPEG_MULTILINE
|
||||
for (row = 0; row < MIN(dest->pub.buffer_height, rows_supplied); row++) {
|
||||
#endif
|
||||
ptr = dest->pub._buffer[row];
|
||||
bufferptr = dest->iobuffer;
|
||||
for (col = dest->samples_per_row; col > 0; col--) {
|
||||
PUTPPMSAMPLE(bufferptr, *ptr++);
|
||||
}
|
||||
fwrite(dest->iobuffer, 1, dest->buffer_width, dest->pub.output_file);
|
||||
#ifdef DJPEG_MULTILINE
|
||||
}
|
||||
fwrite(dest->iobuffer, 1, dest->buffer_width, dest->pub.output_file);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -144,21 +155,27 @@ put_rgb(j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, JDIMENSION rows_supplied)
|
||||
ppm_dest_ptr dest = (ppm_dest_ptr)dinfo;
|
||||
register char *bufferptr;
|
||||
register _JSAMPROW ptr;
|
||||
register JDIMENSION col;
|
||||
register JDIMENSION row = 0, col;
|
||||
register int rindex = rgb_red[cinfo->out_color_space];
|
||||
register int gindex = rgb_green[cinfo->out_color_space];
|
||||
register int bindex = rgb_blue[cinfo->out_color_space];
|
||||
register int ps = rgb_pixelsize[cinfo->out_color_space];
|
||||
|
||||
ptr = dest->pub._buffer[0];
|
||||
bufferptr = dest->iobuffer;
|
||||
for (col = cinfo->output_width; col > 0; col--) {
|
||||
PUTPPMSAMPLE(bufferptr, ptr[rindex]);
|
||||
PUTPPMSAMPLE(bufferptr, ptr[gindex]);
|
||||
PUTPPMSAMPLE(bufferptr, ptr[bindex]);
|
||||
ptr += ps;
|
||||
#ifdef DJPEG_MULTILINE
|
||||
for (row = 0; row < MIN(dest->pub.buffer_height, rows_supplied); row++) {
|
||||
#endif
|
||||
ptr = dest->pub._buffer[row];
|
||||
bufferptr = dest->iobuffer;
|
||||
for (col = cinfo->output_width; col > 0; col--) {
|
||||
PUTPPMSAMPLE(bufferptr, ptr[rindex]);
|
||||
PUTPPMSAMPLE(bufferptr, ptr[gindex]);
|
||||
PUTPPMSAMPLE(bufferptr, ptr[bindex]);
|
||||
ptr += ps;
|
||||
}
|
||||
fwrite(dest->iobuffer, 1, dest->buffer_width, dest->pub.output_file);
|
||||
#ifdef DJPEG_MULTILINE
|
||||
}
|
||||
fwrite(dest->iobuffer, 1, dest->buffer_width, dest->pub.output_file);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -175,25 +192,31 @@ put_rgb565(j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
|
||||
ppm_dest_ptr dest = (ppm_dest_ptr)dinfo;
|
||||
register char *bufferptr;
|
||||
register unsigned short *ptr;
|
||||
register JDIMENSION col;
|
||||
register JDIMENSION row = 0, col;
|
||||
boolean big_endian = is_big_endian();
|
||||
|
||||
ptr = (unsigned short *)dest->pub._buffer[0];
|
||||
bufferptr = dest->iobuffer;
|
||||
for (col = cinfo->output_width; col > 0; col--) {
|
||||
if (big_endian) {
|
||||
bufferptr[0] = *ptr & 0xF8;
|
||||
bufferptr[1] = ((*ptr << 5) & 0xE0) | ((*ptr >> 11) & 0x1C);
|
||||
bufferptr[2] = (*ptr >> 5) & 0xF8;
|
||||
} else {
|
||||
bufferptr[0] = (*ptr >> 8) & 0xF8;
|
||||
bufferptr[1] = (*ptr >> 3) & 0xFC;
|
||||
bufferptr[2] = (*ptr << 3) & 0xF8;
|
||||
#ifdef DJPEG_MULTILINE
|
||||
for (row = 0; row < MIN(dest->pub.buffer_height, rows_supplied); row++) {
|
||||
#endif
|
||||
ptr = (unsigned short *)dest->pub._buffer[row];
|
||||
bufferptr = dest->iobuffer;
|
||||
for (col = cinfo->output_width; col > 0; col--) {
|
||||
if (big_endian) {
|
||||
bufferptr[0] = *ptr & 0xF8;
|
||||
bufferptr[1] = ((*ptr << 5) & 0xE0) | ((*ptr >> 11) & 0x1C);
|
||||
bufferptr[2] = (*ptr >> 5) & 0xF8;
|
||||
} else {
|
||||
bufferptr[0] = (*ptr >> 8) & 0xF8;
|
||||
bufferptr[1] = (*ptr >> 3) & 0xFC;
|
||||
bufferptr[2] = (*ptr << 3) & 0xF8;
|
||||
}
|
||||
bufferptr += 3;
|
||||
ptr++;
|
||||
}
|
||||
bufferptr += 3;
|
||||
ptr++;
|
||||
fwrite(dest->iobuffer, 1, dest->buffer_width, dest->pub.output_file);
|
||||
#ifdef DJPEG_MULTILINE
|
||||
}
|
||||
fwrite(dest->iobuffer, 1, dest->buffer_width, dest->pub.output_file);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -210,18 +233,24 @@ put_cmyk(j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
|
||||
ppm_dest_ptr dest = (ppm_dest_ptr)dinfo;
|
||||
register char *bufferptr;
|
||||
register _JSAMPROW ptr;
|
||||
register JDIMENSION col;
|
||||
register JDIMENSION row = 0, col;
|
||||
|
||||
ptr = dest->pub._buffer[0];
|
||||
bufferptr = dest->iobuffer;
|
||||
for (col = cinfo->output_width; col > 0; col--) {
|
||||
_JSAMPLE r, g, b, c = *ptr++, m = *ptr++, y = *ptr++, k = *ptr++;
|
||||
cmyk_to_rgb(PPM_MAXVAL, c, m, y, k, &r, &g, &b);
|
||||
PUTPPMSAMPLE(bufferptr, r);
|
||||
PUTPPMSAMPLE(bufferptr, g);
|
||||
PUTPPMSAMPLE(bufferptr, b);
|
||||
#ifdef DJPEG_MULTILINE
|
||||
for (row = 0; row < MIN(dest->pub.buffer_height, rows_supplied); row++) {
|
||||
#endif
|
||||
ptr = dest->pub._buffer[row];
|
||||
bufferptr = dest->iobuffer;
|
||||
for (col = cinfo->output_width; col > 0; col--) {
|
||||
_JSAMPLE r, g, b, c = *ptr++, m = *ptr++, y = *ptr++, k = *ptr++;
|
||||
cmyk_to_rgb(PPM_MAXVAL, c, m, y, k, &r, &g, &b);
|
||||
PUTPPMSAMPLE(bufferptr, r);
|
||||
PUTPPMSAMPLE(bufferptr, g);
|
||||
PUTPPMSAMPLE(bufferptr, b);
|
||||
}
|
||||
fwrite(dest->iobuffer, 1, dest->buffer_width, dest->pub.output_file);
|
||||
#ifdef DJPEG_MULTILINE
|
||||
}
|
||||
fwrite(dest->iobuffer, 1, dest->buffer_width, dest->pub.output_file);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -244,17 +273,23 @@ put_demapped_rgb(j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
|
||||
((_JSAMPARRAY)cinfo->colormap)[rgb_green[cinfo->out_color_space]];
|
||||
register _JSAMPROW color_map2 =
|
||||
((_JSAMPARRAY)cinfo->colormap)[rgb_blue[cinfo->out_color_space]];
|
||||
register JDIMENSION col;
|
||||
register JDIMENSION row = 0, col;
|
||||
|
||||
ptr = dest->pub._buffer[0];
|
||||
bufferptr = dest->iobuffer;
|
||||
for (col = cinfo->output_width; col > 0; col--) {
|
||||
pixval = *ptr++;
|
||||
PUTPPMSAMPLE(bufferptr, color_map0[pixval]);
|
||||
PUTPPMSAMPLE(bufferptr, color_map1[pixval]);
|
||||
PUTPPMSAMPLE(bufferptr, color_map2[pixval]);
|
||||
#ifdef DJPEG_MULTILINE
|
||||
for (row = 0; row < MIN(dest->pub.buffer_height, rows_supplied); row++) {
|
||||
#endif
|
||||
ptr = dest->pub._buffer[row];
|
||||
bufferptr = dest->iobuffer;
|
||||
for (col = cinfo->output_width; col > 0; col--) {
|
||||
pixval = *ptr++;
|
||||
PUTPPMSAMPLE(bufferptr, color_map0[pixval]);
|
||||
PUTPPMSAMPLE(bufferptr, color_map1[pixval]);
|
||||
PUTPPMSAMPLE(bufferptr, color_map2[pixval]);
|
||||
}
|
||||
fwrite(dest->iobuffer, 1, dest->buffer_width, dest->pub.output_file);
|
||||
#ifdef DJPEG_MULTILINE
|
||||
}
|
||||
fwrite(dest->iobuffer, 1, dest->buffer_width, dest->pub.output_file);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -266,14 +301,20 @@ put_demapped_gray(j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
|
||||
register char *bufferptr;
|
||||
register _JSAMPROW ptr;
|
||||
register _JSAMPROW color_map = ((_JSAMPARRAY)cinfo->colormap)[0];
|
||||
register JDIMENSION col;
|
||||
register JDIMENSION row = 0, col;
|
||||
|
||||
ptr = dest->pub._buffer[0];
|
||||
bufferptr = dest->iobuffer;
|
||||
for (col = cinfo->output_width; col > 0; col--) {
|
||||
PUTPPMSAMPLE(bufferptr, color_map[*ptr++]);
|
||||
#ifdef DJPEG_MULTILINE
|
||||
for (row = 0; row < MIN(dest->pub.buffer_height, rows_supplied); row++) {
|
||||
#endif
|
||||
ptr = dest->pub._buffer[row];
|
||||
bufferptr = dest->iobuffer;
|
||||
for (col = cinfo->output_width; col > 0; col--) {
|
||||
PUTPPMSAMPLE(bufferptr, color_map[*ptr++]);
|
||||
}
|
||||
fwrite(dest->iobuffer, 1, dest->buffer_width, dest->pub.output_file);
|
||||
#ifdef DJPEG_MULTILINE
|
||||
}
|
||||
fwrite(dest->iobuffer, 1, dest->buffer_width, dest->pub.output_file);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -395,7 +436,7 @@ _jinit_write_ppm(j_decompress_ptr cinfo)
|
||||
dest->iobuffer = (char *)(*cinfo->mem->alloc_small)
|
||||
((j_common_ptr)cinfo, JPOOL_IMAGE, dest->buffer_width);
|
||||
|
||||
#if BITS_IN_JSAMPLE == 8
|
||||
#if BITS_IN_JSAMPLE == 8 && !defined(DJPEG_MULTILINE)
|
||||
if (cinfo->quantize_colors ||
|
||||
(cinfo->out_color_space != JCS_EXT_RGB &&
|
||||
#if RGB_RED == 0 && RGB_GREEN == 1 && RGB_BLUE == 2 && RGB_PIXELSIZE == 3
|
||||
@@ -408,10 +449,26 @@ _jinit_write_ppm(j_decompress_ptr cinfo)
|
||||
* that's separate from the physical I/O buffer. We also need a
|
||||
* separate buffer if pixel format translation must take place.
|
||||
*/
|
||||
#if BITS_IN_JSAMPLE == 8 && defined(DJPEG_MULTILINE)
|
||||
/* Allocate the sample array manually to ensure that the rows are
|
||||
* contiguous in memory, which further exercises esoteric code paths in the
|
||||
* library.
|
||||
*/
|
||||
JDIMENSION row_width = cinfo->output_width * cinfo->output_components;
|
||||
dest->pub._buffer = (JSAMPARRAY)(*cinfo->mem->alloc_small)
|
||||
((j_common_ptr)cinfo, JPOOL_IMAGE, 4 * sizeof(JSAMPROW));
|
||||
dest->pub._buffer[0] = (JSAMPROW)(*cinfo->mem->alloc_small)
|
||||
((j_common_ptr)cinfo, JPOOL_IMAGE, row_width * 4);
|
||||
dest->pub._buffer[1] = dest->pub._buffer[0] + row_width;
|
||||
dest->pub._buffer[2] = dest->pub._buffer[1] + row_width;
|
||||
dest->pub._buffer[3] = dest->pub._buffer[2] + row_width;
|
||||
dest->pub.buffer_height = 4;
|
||||
#else
|
||||
dest->pub._buffer = (_JSAMPARRAY)(*cinfo->mem->alloc_sarray)
|
||||
((j_common_ptr)cinfo, JPOOL_IMAGE,
|
||||
cinfo->output_width * cinfo->output_components, (JDIMENSION)1);
|
||||
dest->pub.buffer_height = 1;
|
||||
#endif
|
||||
if (!cinfo->quantize_colors) {
|
||||
if (IsExtRGB(cinfo->out_color_space))
|
||||
dest->pub.put_pixel_rows = put_rgb;
|
||||
@@ -428,7 +485,7 @@ _jinit_write_ppm(j_decompress_ptr cinfo)
|
||||
else
|
||||
dest->pub.put_pixel_rows = put_demapped_rgb;
|
||||
}
|
||||
#if BITS_IN_JSAMPLE == 8
|
||||
#if BITS_IN_JSAMPLE == 8 && !defined(DJPEG_MULTILINE)
|
||||
else {
|
||||
/* We will fwrite() directly from decompressor output buffer. */
|
||||
/* Synthesize a _JSAMPARRAY pointer structure */
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Uncomment #define DJPEG_MULTILINE in cdjpeg.h to fully exercise all of the
|
||||
# partial image decompression code paths.
|
||||
|
||||
set -u
|
||||
set -e
|
||||
trap onexit INT
|
||||
|
||||
Reference in New Issue
Block a user