Squashed commit of the following:

commit fc4b42b1d56f95efeb1b9fe42dc35b7d98d246bb
Merge: 74516c7 9eb1413
Author: John Bowler <jbowler@acm.org>
Date:   Sun Nov 22 19:37:54 2015 -0800

    Merge branch 'libpng17' into libpng17-filter-enhancements

commit 74516c7257f1a28a69985684c5673caa390c700a
Author: John Bowler <jbowler@acm.org>
Date:   Sun Nov 22 19:32:43 2015 -0800

    Make check full pass on gcc/g++ x86_64

    Signed-off-by: John Bowler <jbowler@acm.org>

commit e891e34737fc0bc9ee873a5d56b83c1e777b990c
Author: John Bowler <jbowler@acm.org>
Date:   Sun Nov 22 12:01:37 2015 -0800

    Checkpoint: write buffering changes

    This version fails in pngvalid --size because of an error handling very narrow
    images, otherwise a standard build passes make check.

    Signed-off-by: John Bowler <jbowler@acm.org>

commit 457a046ebdab737eefb477126cf855e49df6de50
Author: John Bowler <jbowler@acm.org>
Date:   Sun Nov 22 06:39:36 2015 -0800

    Fix previous bad merge

commit b4f426c97267317637d43f41fe0b05d1659bc63d
Merge: 07b9b90 a3458a6
Author: John Bowler <jbowler@acm.org>
Date:   Sun Nov 22 06:32:34 2015 -0800

    Merge branch 'libpng17' into libpng17-filter-enhancements

commit 07b9b90dfd653b744dbc3710b096facf6b4605f6
Merge: ed43306 5592e0b
Author: John Bowler <jbowler@acm.org>
Date:   Sat Nov 21 17:07:23 2015 -0800

    Merge branch 'libpng17' into libpng17-filter-enhancements

commit ed43306599f7039a90187862db82273fca3a4c3d
Merge: 772aed7 d3c0359
Author: John Bowler <jbowler@acm.org>
Date:   Tue Nov 17 17:47:26 2015 -0800

    Merge branch 'libpng17' into libpng17-filter-enhancements

commit 772aed72378df9c8fccc5a4594b095d02d410a9c
Merge: 73ae431 801608f
Author: John Bowler <jbowler@acm.org>
Date:   Mon Nov 16 14:26:38 2015 -0800

    Merge branch 'libpng17' into libpng17-filter-enhancements

commit 73ae4316cb6db7d7f6756583a1c213c35ca4e3f4
Merge: 687e6e3 c09b3ab
Author: John Bowler <jbowler@acm.org>
Date:   Sun Nov 15 09:31:30 2015 -0800

    Merge branch 'libpng17' into libpng17-filter-enhancements

commit 687e6e393e9d0220c2a12ec474aa01b83c5e9f25
Merge: fedd6da e916d9b
Author: John Bowler <jbowler@acm.org>
Date:   Thu Nov 5 08:45:14 2015 -0800

    Merge branch 'libpng17' into libpng17-filter-enhancements

commit fedd6da8798a14b2e002b0bc1379f5a09a03598a
Merge: 2e2fc5f ea41fd2
Author: John Bowler <jbowler@acm.org>
Date:   Tue Nov 3 21:05:01 2015 -0800

    Merge branch 'libpng17' into libpng17-filter-enhancements

commit 2e2fc5f6d7678b710c52b7ea081ac4add677d8d5
Merge: 990d5f8 5b05197
Author: John Bowler <jbowler@acm.org>
Date:   Mon Oct 12 08:28:30 2015 -0700

    Merge branch 'libpng17' into libpng17-filter-enhancements

commit 990d5f88688635dc0888657b689e30ffe7e7a7b3
Author: John Bowler <jbowler@acm.org>
Date:   Sun Oct 4 17:04:53 2015 -0700

    Read row buffer changes

    The read code now allocates one row buffer of the size of the input PNG row and,
    only if required, one buffer of the size of the output.

    The output buffer is required for the progressive reader (always) and for the
    sequential reader if libpng is de-interlacing an image (because the output row
    is used multiple times if png_read_row is called with a display row parameter.)

    This should reduce memory utilization by libpng significantly, but it has no
    detectable effect on overall performance figures of the test programs, these are
    probably dominated by memory allocations for the whole image within the test
    programs.

    Signed-off-by: John Bowler <jbowler@acm.org>

commit 527bf989bf0e30440f9e07a5544a6ebb1d6fd039
Merge: 50ebbc2 9099254
Author: John Bowler <jbowler@acm.org>
Date:   Sat Oct 3 13:39:17 2015 -0700

    Merge branch 'libpng17' into libpng17-filter-enhancements

commit 50ebbc2c9a24cf1a6b428db53d55fbd5af4d6be6
Merge: 21a7f40 2cd6d56
Author: John Bowler <jbowler@acm.org>
Date:   Sat Oct 3 11:16:32 2015 -0700

    Merge branch 'libpng17' into libpng17-filter-enhancements

commit 21a7f401ab40c79ead9e35882a8066e2cf1d6902
Merge: b512e1c 15a143e
Author: John Bowler <jbowler@acm.org>
Date:   Wed Sep 30 19:01:23 2015 -0700

    Merge branch 'libpng17' into libpng17-filter-enhancements

commit b512e1c2c5bfe6df8b6dca32f862d325ec22115e
Author: John Bowler <jbowler@acm.org>
Date:   Wed Sep 30 17:33:34 2015 -0700

    Transform rewrite: perform transforms in small chunks

    The intent of this change is to reduce the memory footprint during transform
    sequences by performing transforms in fixed (small) sized blocks of pixels.
    The change is incomplete; the filter code still works row-by-row, so the whole
    tranform also works row-by-row, the intent is to fix this so that everything
    works in small(ish) chunks.

    At present the change has no discernable effect on pngvalid --speed or pngstest
    with (e.g.) rgb-8-1.8.png; user time and (minor) page faults are the same in old
    and new versions.  The same applies to real-world 15MP PNG images; even on these
    the presence of the filter code causes a cyclical progress through memory which
    will interfere with any caching otherwise possible (useful word, 'otherwise'.)

    Signed-off-by: John Bowler <jbowler@acm.org>

commit 781cb3699b92beb0e6bc5e03cef8fba820267082
Author: John Bowler <jbowler@acm.org>
Date:   Wed Sep 30 17:12:53 2015 -0700

    Fix NO_WRITE_INTERLACE in pngvalid.c

    The support for writing interlaced images directly from libpng 1.7 was
    unintentionally disabled (INTERLACE_LAST was defined incorrectly, excluding the
    interlaced images).  This obscured the fact that the transform and error test
    case generators lacked the support for writing interlaced images from libpng.

    Signed-off-by: John Bowler <jbowler@acm.org>

commit 406ee2fd7946a384f1d7713712dc646080c5c52c
Author: John Bowler <jbowler@acm.org>
Date:   Wed Sep 30 17:11:40 2015 -0700

    Add pngvalid --transform --interlace test

    This increases code coverage by generating test cases with smaller length rows
    as a result of the interlacing.  Without this packswap handling was incompletely
    tested.

    Signed-off-by: John Bowler <jbowler@acm.org>

Signed-off-by: John Bowler <jbowler@acm.org>
This commit is contained in:
John Bowler 2015-11-22 19:41:41 -08:00
parent 9eb14136d8
commit 0f2554a5e6
18 changed files with 2299 additions and 2053 deletions

View File

@ -53,7 +53,7 @@ TESTS =\
tests/pngvalid-gamma-threshold tests/pngvalid-gamma-transform\
tests/pngvalid-progressive-size\
tests/pngvalid-progressive-interlace-standard\
tests/pngvalid-transform\
tests/pngvalid-transform tests/pngvalid-interlace-transform\
tests/pngvalid-progressive-standard tests/pngvalid-standard\
tests/pngstest-1.8 tests/pngstest-1.8-alpha tests/pngstest-linear\
tests/pngstest-linear-alpha tests/pngstest-none tests/pngstest-none-alpha\

View File

@ -148,6 +148,13 @@
#include <zlib.h>
#if PNG_LIBPNG_VER < 10700
/* WRITE_INTERLACING was used instead of WRITE_INTERLACE prior to 1.7 */
# ifdef PNG_WRITE_INTERLACING_SUPPORTED
# define PNG_WRITE_INTERLACE_SUPPORTED
# endif
#endif /* WRITE_INTERLACE check */
/* Work round for GCC complaints about casting a (double) function result to
* an unsigned:
*/
@ -944,11 +951,11 @@ write_png(const char **name, FILE *fp, int color_type, int bit_depth,
png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, filters);
{
# ifdef PNG_WRITE_INTERLACING_SUPPORTED
# ifdef PNG_WRITE_INTERLACE_SUPPORTED
int passes = png_set_interlace_handling(png_ptr);
# else /* !WRITE_INTERLACING */
# else /* !WRITE_INTERLACE */
int passes = 1;
# endif /* !WRITE_INTERLACING */
# endif /* !WRITE_INTERLACE */
int pass;
png_size_t rowbytes = png_get_rowbytes(png_ptr, info_ptr);

View File

@ -120,6 +120,10 @@ typedef png_byte *png_const_bytep;
/* READ_INTERLACING was used instead of READ_DEINTERLACE. */
# ifdef PNG_READ_INTERLACING_SUPPORTED
# define PNG_READ_DEINTERLACE_SUPPORTED
# endif
/* WRITE_INTERLACING was used instead of WRITE_INTERLACE. */
# ifdef PNG_WRITE_INTERLACING_SUPPORTED
# define PNG_WRITE_INTERLACE_SUPPORTED
# endif
#endif
@ -3545,17 +3549,18 @@ transform_row(png_const_structp pp, png_byte buffer[TRANSFORM_ROWMAX],
* interlacing support. If there is no write interlacing we can't generate test
* cases with interlace:
*/
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
#ifdef PNG_WRITE_INTERLACE_SUPPORTED
# define INTERLACE_LAST PNG_INTERLACE_LAST
# define check_interlace_type(type) ((void)(type))
# define set_write_interlace_handling(pp,type) png_set_interlace_handling(pp)
# define do_own_interlace 0
#elif PNG_LIBPNG_VER < 10700
# define set_write_interlace_handling(pp,type) (1)
static void
check_interlace_type(int const interlace_type)
{
/* Prior to 1.7.0 libpng does not support the write of an interlaced image
* unless PNG_WRITE_INTERLACING_SUPPORTED, even with do_interlace so the
* unless PNG_WRITE_INTERLACE_SUPPORTED, even with do_interlace so the
* code here does the pixel interlace itself, so:
*/
if (interlace_type != PNG_INTERLACE_NONE)
@ -3568,15 +3573,66 @@ check_interlace_type(int const interlace_type)
}
}
# define INTERLACE_LAST (PNG_INTERLACE_NONE+1)
# define do_own_interlace 0
#else /* libpng 1.7+ */
# define set_write_interlace_handling(pp,type)\
npasses_from_interlace_type(pp,type)
# define check_interlace_type(type) ((void)(type))
# define INTERLACE_LAST (PNG_INTERLACE_NONE+1)
#endif /* WRITE_INTERLACING tests */
# define INTERLACE_LAST PNG_INTERLACE_LAST
# define do_own_interlace 1
#endif /* WRITE_INTERLACE tests */
#define CAN_WRITE_INTERLACE\
PNG_LIBPNG_VER >= 10700 || defined PNG_WRITE_INTERLACING_SUPPORTED
PNG_LIBPNG_VER >= 10700 || defined PNG_WRITE_INTERLACE_SUPPORTED
/* The following two routines use the PNG interlace support macros from
* png.h to interlace or deinterlace rows.
*/
static void
interlace_row(png_bytep buffer, png_const_bytep imageRow,
unsigned int pixel_size, png_uint_32 w, int pass)
{
png_uint_32 xin, xout, xstep;
/* Note that this can, trivially, be optimized to a memcpy on pass 7, the
* code is presented this way to make it easier to understand. In practice
* consult the code in the libpng source to see other ways of doing this.
*
* It is OK for buffer and imageRow to be identical, because 'xin' moves
* faster than 'xout' and we copy up.
*/
xin = PNG_PASS_START_COL(pass);
xstep = 1U<<PNG_PASS_COL_SHIFT(pass);
for (xout=0; xin<w; xin+=xstep)
{
pixel_copy(buffer, xout, imageRow, xin, pixel_size);
++xout;
}
}
#ifdef PNG_READ_SUPPORTED
static void
deinterlace_row(png_bytep buffer, png_const_bytep row,
unsigned int pixel_size, png_uint_32 w, int pass)
{
/* The inverse of the above, 'row' is part of row 'y' of the output image,
* in 'buffer'. The image is 'w' wide and this is pass 'pass', distribute
* the pixels of row into buffer and return the number written (to allow
* this to be checked).
*/
png_uint_32 xin, xout, xstep;
xout = PNG_PASS_START_COL(pass);
xstep = 1U<<PNG_PASS_COL_SHIFT(pass);
for (xin=0; xout<w; xout+=xstep)
{
pixel_copy(buffer, xout, row, xin, pixel_size);
++xin;
}
}
#endif /* PNG_READ_SUPPORTED */
/* Make a standardized image given an image colour type, bit depth and
* interlace type. The standard images have a very restricted range of
@ -3597,7 +3653,7 @@ make_transform_image(png_store* const ps, png_byte const colour_type,
{
png_infop pi;
png_structp pp = set_store_for_write(ps, &pi, name);
png_uint_32 h;
png_uint_32 h, w;
/* In the event of a problem return control to the Catch statement below
* to do the clean up - it is not possible to 'return' directly from a Try
@ -3606,10 +3662,10 @@ make_transform_image(png_store* const ps, png_byte const colour_type,
if (pp == NULL)
Throw ps;
w = transform_width(pp, colour_type, bit_depth);
h = transform_height(pp, colour_type, bit_depth);
png_set_IHDR(pp, pi, transform_width(pp, colour_type, bit_depth), h,
bit_depth, colour_type, interlace_type,
png_set_IHDR(pp, pi, w, h, bit_depth, colour_type, interlace_type,
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
#ifdef PNG_TEXT_SUPPORTED
@ -3671,11 +3727,36 @@ make_transform_image(png_store* const ps, png_byte const colour_type,
{
png_uint_32 y;
/* do_own_interlace is a pre-defined boolean (a #define) which is
* set if we have to work out the interlaced rows here.
*/
for (y=0; y<h; ++y)
{
png_byte buffer[TRANSFORM_ROWMAX];
transform_row(pp, buffer, colour_type, bit_depth, y);
# if do_own_interlace
/* If do_own_interlace *and* the image is interlaced we need a
* reduced interlace row; this may be reduced to empty.
*/
if (interlace_type == PNG_INTERLACE_ADAM7)
{
/* The row must not be written if it doesn't exist, notice
* that there are two conditions here, either the row isn't
* ever in the pass or the row would be but isn't wide
* enough to contribute any pixels. In fact the wPass test
* can be used to skip the whole y loop in this case.
*/
if (PNG_ROW_IN_INTERLACE_PASS(y, pass) &&
PNG_PASS_COLS(w, pass) > 0)
interlace_row(buffer, buffer,
bit_size(pp, colour_type, bit_depth), w, pass);
else
continue;
}
# endif /* do_own_interlace */
png_write_row(pp, buffer);
}
}
@ -3745,59 +3826,13 @@ make_transform_images(png_modifier *pm)
char name[FILE_NAME_SIZE];
standard_name(name, sizeof name, 0, colour_type, bit_depth,
palette_number, interlace_type, 0, 0, 0);
palette_number, interlace_type, 0, 0, do_own_interlace);
make_transform_image(&pm->this, colour_type, bit_depth, palette_number,
interlace_type, name);
}
}
}
/* The following two routines use the PNG interlace support macros from
* png.h to interlace or deinterlace rows.
*/
static void
interlace_row(png_bytep buffer, png_const_bytep imageRow,
unsigned int pixel_size, png_uint_32 w, int pass)
{
png_uint_32 xin, xout, xstep;
/* Note that this can, trivially, be optimized to a memcpy on pass 7, the
* code is presented this way to make it easier to understand. In practice
* consult the code in the libpng source to see other ways of doing this.
*/
xin = PNG_PASS_START_COL(pass);
xstep = 1U<<PNG_PASS_COL_SHIFT(pass);
for (xout=0; xin<w; xin+=xstep)
{
pixel_copy(buffer, xout, imageRow, xin, pixel_size);
++xout;
}
}
#ifdef PNG_READ_SUPPORTED
static void
deinterlace_row(png_bytep buffer, png_const_bytep row,
unsigned int pixel_size, png_uint_32 w, int pass)
{
/* The inverse of the above, 'row' is part of row 'y' of the output image,
* in 'buffer'. The image is 'w' wide and this is pass 'pass', distribute
* the pixels of row into buffer and return the number written (to allow
* this to be checked).
*/
png_uint_32 xin, xout, xstep;
xout = PNG_PASS_START_COL(pass);
xstep = 1U<<PNG_PASS_COL_SHIFT(pass);
for (xin=0; xout<w; xout+=xstep)
{
pixel_copy(buffer, xout, row, xin, pixel_size);
++xin;
}
}
#endif /* PNG_READ_SUPPORTED */
/* Build a single row for the 'size' test images; this fills in only the
* first bit_width bits of the sample row.
*/
@ -4039,13 +4074,13 @@ make_size(png_store* const ps, png_byte const colour_type, int bdlo,
width, height, 0);
make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_NONE,
width, height, 1);
# ifdef PNG_WRITE_INTERLACING_SUPPORTED
# ifdef PNG_WRITE_INTERLACE_SUPPORTED
make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_ADAM7,
width, height, 0);
# endif
# if CAN_WRITE_INTERLACE
/* 1.7.0 removes the hack that prevented app write of an interlaced
* image if WRITE_INTERLACING was not supported
* image if WRITE_INTERLACE was not supported
*/
make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_ADAM7,
width, height, 1);
@ -4147,14 +4182,18 @@ make_error(png_store* const ps, png_byte const colour_type,
{
png_infop pi;
const png_structp pp = set_store_for_write(ps, &pi, name);
png_uint_32 w, h;
gnu_volatile(pp)
if (pp == NULL)
Throw ps;
png_set_IHDR(pp, pi, transform_width(pp, colour_type, bit_depth),
transform_height(pp, colour_type, bit_depth), bit_depth, colour_type,
interlace_type, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
w = transform_width(pp, colour_type, bit_depth);
gnu_volatile(w)
h = transform_height(pp, colour_type, bit_depth);
gnu_volatile(h)
png_set_IHDR(pp, pi, w, h, bit_depth, colour_type, interlace_type,
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
if (colour_type == 3) /* palette */
init_standard_palette(ps, pp, pi, 1U << bit_depth, 0/*do tRNS*/);
@ -4206,7 +4245,6 @@ make_error(png_store* const ps, png_byte const colour_type,
else
{
png_uint_32 h = transform_height(pp, colour_type, bit_depth);
int npasses = set_write_interlace_handling(pp, interlace_type);
int pass;
@ -4222,6 +4260,28 @@ make_error(png_store* const ps, png_byte const colour_type,
png_byte buffer[TRANSFORM_ROWMAX];
transform_row(pp, buffer, colour_type, bit_depth, y);
# if do_own_interlace
/* If do_own_interlace *and* the image is interlaced we need a
* reduced interlace row; this may be reduced to empty.
*/
if (interlace_type == PNG_INTERLACE_ADAM7)
{
/* The row must not be written if it doesn't exist, notice
* that there are two conditions here, either the row isn't
* ever in the pass or the row would be but isn't wide
* enough to contribute any pixels. In fact the wPass test
* can be used to skip the whole y loop in this case.
*/
if (PNG_ROW_IN_INTERLACE_PASS(y, pass) &&
PNG_PASS_COLS(w, pass) > 0)
interlace_row(buffer, buffer,
bit_size(pp, colour_type, bit_depth), w, pass);
else
continue;
}
# endif /* do_own_interlace */
png_write_row(pp, buffer);
}
}
@ -4254,7 +4314,7 @@ make_errors(png_modifier* const pm, png_byte const colour_type,
char name[FILE_NAME_SIZE];
standard_name(name, sizeof name, 0, colour_type, 1<<bdlo, 0,
interlace_type, 0, 0, 0);
interlace_type, 0, 0, do_own_interlace);
for (test=0; test<ARRAY_SIZE(error_test); ++test)
{
@ -5130,7 +5190,7 @@ standard_row_validate(standard_display *dp, png_const_structp pp,
dp->bit_width)) != 0)
{
char msg[64];
sprintf(msg, "display row[%lu][%d] changed from %.2x to %.2x",
sprintf(msg, "display row[%lu][%d] changed from %.2x to %.2x",
(unsigned long)y, where-1, std[where-1],
store_image_row(dp->ps, pp, iDisplay, y)[where-1]);
png_error(pp, msg);
@ -5396,7 +5456,7 @@ test_size(png_modifier* const pm, png_byte const colour_type,
# endif
# endif /* READ_DEINTERLACE */
# ifdef PNG_WRITE_INTERLACING_SUPPORTED
# ifdef PNG_WRITE_INTERLACE_SUPPORTED
/* Test the libpng write side against the pngvalid read side: */
standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/,
PNG_INTERLACE_ADAM7, w, h, 0), 1/*do_interlace*/,
@ -5407,7 +5467,7 @@ test_size(png_modifier* const pm, png_byte const colour_type,
# endif
# ifdef PNG_READ_DEINTERLACE_SUPPORTED
# ifdef PNG_WRITE_INTERLACING_SUPPORTED
# ifdef PNG_WRITE_INTERLACE_SUPPORTED
/* Test both together: */
standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/,
PNG_INTERLACE_ADAM7, w, h, 0), 0/*do_interlace*/,

106
png.c
View File

@ -237,6 +237,19 @@ png_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
jmp_buf create_jmp_buf;
# endif
/* This is a compile-type only test to ensure that the build satisifies the
* contraints for the row buffer stack allocations. A 'duplicate case
* statements' style of error means that one of the tests below failed:
*/
switch (0)
{
case 0:
case PNG_ROW_BUFFER_SIZE >= PNG_MIN_ROW_BUFFER_SIZE: /*1*/
case 2*(PNG_ROW_BUFFER_SIZE <= PNG_MAX_ROW_BUFFER_SIZE): /*2*/
default:
break;
}
/* This temporary stack-allocated structure is used to provide a place to
* build enough context to allow the user provided memory allocator (if any)
* to be called.
@ -2362,6 +2375,99 @@ png_calc_rowbytes(png_const_structrp png_ptr, unsigned int pixel_depth,
return rowbytes;
}
unsigned int /*PRIVATE*/
png_max_pixel_block(png_const_structrp png_ptr)
{
/* Need the *smallest* pixel size that must occur in alignment units. On
* read this is the PNG pixel depth because the read transforms cannot reduce
* the pixel size below the input size or 8-bits, whichever is smaller.
*
* On write the 'pack' transform can pack 8-bit pixels back to a lower bit
* depth, but the lowest bit depth is still given by the PNG pixel size.
*/
const unsigned int pixel_depth = PNG_PIXEL_DEPTH(*png_ptr);
const unsigned int pixel_block = /* count of pixels in a block */
pixel_depth < 8U ?
PNG_ROW_BUFFER_BYTE_ALIGN * (8U/pixel_depth) :
PNG_ROW_BUFFER_BYTE_ALIGN; /* pixels may be any whole byte size */
/* The maximum block size in bits is MAX_PIXEL_DEPTH*pixel_block so work out
* the minimum number of pixel blocks that can fit in PNG_ROW_BUFFER_SIZE
* bytes and use this to calculate the maximum number of pixels:
*/
return pixel_block *
((8U*PNG_ROW_BUFFER_SIZE) / (png_ptr->row_max_pixel_depth*pixel_block));
}
void /* PRIVATE */
png_copy_row(png_const_structrp png_ptr, png_bytep dp, png_const_bytep sp,
png_uint_32 x/*in INPUT*/, png_uint_32 width/*of INPUT*/,
unsigned int pixel_depth, int clear/*clear the final byte*/)
/* Copy the row in row_buffer; this is the non-interlaced copy used in both
* the read and write code.
*/
{
png_alloc_size_t cb;
unsigned int remaining; /* remaining bits in a partial byte */
/* Copy 'cb' pixels, but take care with the last byte because it may
* be partially written. 'x' must correspond to the start of a byte, check
* that too:
*/
switch (pixel_depth)
{
case 1U: remaining = width & 7U;
debug((x & 7U) == 0U);
cb = width >> 3;
dp += x >> 3;
break;
case 2U: remaining = (width << 1) & 6U;
debug((x & 3U) == 0U);
cb = width >> 2;
dp += x >> 2;
break;
case 4U: remaining = (width << 2) & 4U;
debug((x & 1U) == 0U);
cb = width >> 1;
dp += x >> 1;
break;
case 8U: remaining = 0U;
cb = width;
dp += x;
break;
default: remaining = 0U;
cb = png_calc_rowbytes(png_ptr, pixel_depth, width);
dp += png_calc_rowbytes(png_ptr, pixel_depth, x);
break;
}
memcpy(dp, sp, cb);
if (remaining > 0U)
{
/* 'remaining' is the number of bits still to be copied. Format may be
* little endian; bits to copy in the bottom of 's'. Make 'remaining'
* into a mask of the bits to *preserve* in dp.
*/
if ((png_ptr->row_format & PNG_FORMAT_FLAG_SWAPPED) == 0U)
remaining = 0xffU >> remaining;
else
remaining = 0xffU << remaining;
/* remaining is now the bits to *keep* from the destination byte, if
* 'clear' is true the source bytes aren't copied - this is for security
* reasons to avoid copying undefined bits at the end of a row. If
* 'clear' is set the destination bits are not preserved, they are just
* set to 0.
*/
if (clear)
dp[cb] = PNG_BYTE(sp[cb] & ~remaining);
else
dp[cb] = PNG_BYTE((sp[cb] & ~remaining) | (dp[cb] & remaining));
}
}
void /* PRIVATE */
png_check_IHDR(png_const_structrp png_ptr,
png_uint_32 width, png_uint_32 height, int bit_depth,

19
png.h
View File

@ -1463,7 +1463,7 @@ PNG_EXPORT(44, void, png_set_shift, (png_structrp png_ptr, png_const_color_8p
#endif
#if defined(PNG_READ_DEINTERLACE_SUPPORTED) || \
defined(PNG_WRITE_INTERLACING_SUPPORTED)
defined(PNG_WRITE_INTERLACE_SUPPORTED)
/* Have the code handle the interlacing. Returns the number of passes.
* MUST be called before png_read_update_info or png_start_read_image,
* otherwise it will not have the desired effect. Note that it is still
@ -1676,11 +1676,12 @@ PNG_EXPORT(67, void, png_set_filter, (png_structrp png_ptr, int method,
*
* The resultant argument fits in a single byte.
*/
#define PNG_FILTER_NONE (0x08 << PNG_FILTER_VALUE_NONE)
#define PNG_FILTER_SUB (0x08 << PNG_FILTER_VALUE_SUB)
#define PNG_FILTER_UP (0x08 << PNG_FILTER_VALUE_UP)
#define PNG_FILTER_AVG (0x08 << PNG_FILTER_VALUE_AVG)
#define PNG_FILTER_PAETH (0x08 << PNG_FILTER_VALUE_PAETH)
#define PNG_FILTER_MASK(value) (0x08 << (value))
#define PNG_FILTER_NONE PNG_FILTER_MASK(PNG_FILTER_VALUE_NONE)
#define PNG_FILTER_SUB PNG_FILTER_MASK(PNG_FILTER_VALUE_SUB)
#define PNG_FILTER_UP PNG_FILTER_MASK(PNG_FILTER_VALUE_UP)
#define PNG_FILTER_AVG PNG_FILTER_MASK(PNG_FILTER_VALUE_AVG)
#define PNG_FILTER_PAETH PNG_FILTER_MASK(PNG_FILTER_VALUE_PAETH)
/* Then two convenience values. PNG_NO_FILTERS is the same as
* PNG_FILTER_VALUE_NONE, but this is harmless because they mean the same thing.
@ -2710,9 +2711,9 @@ PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type,
/* A macro to find the last pass (in the range 0 to 6) given an image width and
* height. Then two macros two find whether a given image row or column which
* is prsent in the pass is the last row or column in the pass. Note that these
* macros return 'true' for earlier rows or columns of the image that are *not*
* in the pass.
* is present in the pass is the last row or column in the pass. Note that
* these macros return 'true' for earlier rows or columns of the image that are
* *not* in the pass.
*/
#define PNG_LAST_PASS(width, height) ((height) > 1 ? 6 : ((width) > 1 ? 5 : 0))
#define PNG_LAST_PASS_ROW(y, pass, height)\

View File

@ -335,13 +335,11 @@ png_push_read_unknown(png_structrp png_ptr, png_inforp info_ptr)
/* Now check the CRC, before attempting the unknown handling. */
png_calculate_crc(png_ptr, buffer, chunk_length);
png_crc_finish(png_ptr, 0);
# ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
png_handle_unknown(png_ptr, info_ptr, buffer);
png_handle_unknown(png_ptr, info_ptr, buffer);
# else /* !READ_UNKNOWN_CHUNKS */
PNG_UNUSED(info_ptr)
PNG_UNUSED(info_ptr)
# endif /* !READ_UNKNOWN_CHUNKS */
png_ptr->process_mode = png_read_chunk_header;
}
@ -362,7 +360,7 @@ png_push_have_row(png_structrp png_ptr, png_bytep row)
* one:
*/
# ifdef PNG_READ_DEINTERLACE_SUPPORTED
if (!png_ptr->do_interlace)
if (!png_ptr->do_interlace)
# endif
{
affirm(PNG_ROW_IN_INTERLACE_PASS(row_number, pass) && row != NULL);
@ -482,7 +480,8 @@ png_push_read_process_IDAT(png_structp png_ptr, png_bytep *bufferp,
if (!png_ptr->zstream_eod)
{
png_bytep row_buffer = NULL;
png_row_op row_op = png_read_process_IDAT(png_ptr);
png_row_op row_op =
png_read_process_IDAT(png_ptr, NULL, NULL, 1/*save row*/);
if (row_op != png_row_incomplete)
{
@ -517,28 +516,34 @@ png_push_read_process_IDAT(png_structp png_ptr, png_bytep *bufferp,
*/
affirm(buffer_lengthp != NULL || png_ptr->zstream_error);
/* png_struct::row_buffer contains a complete, transformed, row;
* this is processed in both 'sparkle' and 'block' mode.
/* png_struct::transformed_row contains a complete, transformed,
* row; this is processed in both 'sparkle' and 'block' mode.
*/
row_buffer = png_ptr->row_buffer;
# ifdef PNG_TRANSFORM_MECH_SUPPORTED
row_buffer = png_ptr->transformed_row;
if (row_buffer == NULL)
# endif /* TRANSFORM_MECH */
row_buffer = png_ptr->row_buffer;
break;
case png_row_repeat:
/* row not in this pass, but the existing row in
* png_struct::row_buffer may be used, this is only required if
* the 'block' or 'rectangle' mode of display is done and libpng
* is handling the de-interlace; when the app does it it only
* see the real rows.
* png_struct::transformed_row may be used, this is only required
* if the 'block' or 'rectangle' mode of display is done and
* libpng is handling the de-interlace; when the app does it it
* only see the real rows.
*/
# ifdef PNG_READ_DEINTERLACE_SUPPORTED
if (png_ptr->do_interlace)
{
row_buffer = png_ptr->row_buffer;
break;
}
if (png_ptr->do_interlace)
{
# ifdef PNG_TRANSFORM_MECH_SUPPORTED
row_buffer = png_ptr->transformed_row;
if (row_buffer == NULL)
# endif
row_buffer = png_ptr->row_buffer;
break;
}
# endif
continue;
case png_row_skip:
@ -833,23 +838,6 @@ png_process_data(png_structrp png_ptr, png_inforp info_ptr,
png_process_some_data(png_ptr, info_ptr);
}
#ifdef PNG_READ_DEINTERLACE_SUPPORTED
void PNGAPI
png_progressive_combine_row(png_const_structrp png_ptr, png_bytep old_row,
png_const_bytep new_row)
{
if (png_ptr == NULL)
return;
/* new_row is a flag here - if it is NULL then the app callback was called
* from an empty row (see the calls to png_struct::row_fn above), otherwise
* it must be png_ptr->row_buffer
*/
if (new_row != NULL)
png_combine_row(png_ptr, old_row, 1/*blocky display*/);
}
#endif /* READ_DEINTERLACE */
void PNGAPI
png_set_progressive_read_fn(png_structrp png_ptr, png_voidp progressive_ptr,
png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,

145
pngpriv.h
View File

@ -556,6 +556,47 @@
# define png_isaligned(ptr, type) 0
#endif
/* Buffer alignment control. These #defines control how the buffers used during
* read are aligned and how big they are.
*/
#ifndef PNG_ROW_BUFFER_ALIGN_TYPE
/* The absolute minimum alignment for a row buffer is that required for
* png_uint_32 direct access. The #define is of a legal C type that can be
* used as the type in the definition of the first member of a C union; give
* a typedef name if in doubt.
*/
# define PNG_ROW_BUFFER_ALIGN_TYPE png_uint_32
#endif /* !ROW_BUFFER_ALIGN_TYPE */
#ifndef PNG_ROW_BUFFER_BYTE_ALIGN
/* This is the minimum size in bytes of the buffer used while processing
* parts of row. Except at the end of the row pixels will always be
* processed in blocks such that the block size is a multiple of this number
*/
# define PNG_ROW_BUFFER_BYTE_ALIGN\
((unsigned int)/*SAFE*/(sizeof (PNG_ROW_BUFFER_ALIGN_TYPE)))
#endif /* !ROW_BUFFER_BYTE_ALIGN */
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
# define PNG_MAX_PIXEL_BYTES 16U /* 4x32-bit channels */
#else /* !READ_USER_TRANSFORM */
# define PNG_MAX_PIXEL_BYTES 8U /* 4x16-bit channels */
#endif /* !READ_USER_TRANSFORM */
/* PNG_ROW_BUFFER_SIZE is a compile time constant for the size of the row
* buffer. The minimum size of 2048 bytes is intended to allow the buffer to
* hold a complete 256 entry color map of 64-bit (8-byte) pixels. This is a
* requirement at some points of the colormap handling code.
*
* The maximum size is intended to allow (unsigned int) indexing of the buffer,
* it only affects systems with a 16-bit unsigned value where it limits the
* maximum to 4096 bytes.
*/
#define PNG_MIN_ROW_BUFFER_SIZE\
(PNG_MAX_PIXEL_BYTES * PNG_ROW_BUFFER_BYTE_ALIGN * 8U)
#define PNG_MAX_ROW_BUFFER_SIZE ((UINT_MAX / 16U) + 1U)
#ifndef PNG_ROW_BUFFER_SIZE
# define PNG_ROW_BUFFER_SIZE\
(PNG_MIN_ROW_BUFFER_SIZE < 2048U ? 2048U : PNG_MIN_ROW_BUFFER_SIZE)
#endif /* ROW_BUFFER_SIZE */
/* End of memory model/platform independent support */
/* End of 1.5.0beta36 move from pngconf.h */
@ -892,9 +933,23 @@ PNG_INTERNAL_FUNCTION(png_uint_16, png_u16_affirm,(png_const_structrp png_ptr,
/* Safe calculation of a rowbytes value; does a png_error if the system limits
* are exceeded.
*/
png_alloc_size_t /* PRIVATE */
png_calc_rowbytes(png_const_structrp png_ptr, unsigned int pixel_depth,
png_uint_32 row_width);
PNG_INTERNAL_FUNCTION(png_alloc_size_t,png_calc_rowbytes,
(png_const_structrp png_ptr, unsigned int pixel_depth,
png_uint_32 row_width),PNG_EMPTY);
/* Common code to calculate the maximum number of pixels to transform or filter
* at one time; controlled by PNG_ROW_BUFFER_SIZE above:
*/
PNG_INTERNAL_FUNCTION(unsigned int,png_max_pixel_block,
(png_const_structrp png_ptr),PNG_EMPTY);
/* Copy the row in row_buffer; this is the non-interlaced copy used in both
* the read and write code.
*/
PNG_INTERNAL_FUNCTION(void, png_copy_row,(png_const_structrp png_ptr,
png_bytep dp, png_const_bytep sp, png_uint_32 x/*in INPUT*/,
png_uint_32 width/*of INPUT*/, unsigned int pixel_depth,
int clear/*clear the final byte*/),PNG_EMPTY);
/* Zlib support */
#define PNG_UNEXPECTED_ZLIB_RETURN (-7)
@ -1149,33 +1204,21 @@ PNG_INTERNAL_FUNCTION(void,png_write_sCAL_s,(png_structrp png_ptr,
int unit, png_const_charp width, png_const_charp height),PNG_EMPTY);
#endif
PNG_INTERNAL_FUNCTION(void,png_copy_row,(png_const_structrp png_ptr,
png_bytep dp),PNG_EMPTY);
/* Copy the row in row_buffer; this is the 'simple' case of png_combine_row
* where no adjustment to the pixel spacing is required.
*/
#ifdef PNG_READ_DEINTERLACE_SUPPORTED
PNG_INTERNAL_FUNCTION(void,png_combine_row,(png_const_structrp png_ptr,
png_bytep row, int display),PNG_EMPTY);
#endif /* READ_DEINTERLACE */
/* GRR TO DO (2.0 or whenever): simplify other internal calling interfaces */
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
/* Turn on write interlacing */
PNG_INTERNAL_FUNCTION(void,png_set_write_interlace,(png_structrp),PNG_EMPTY);
#endif
#ifdef PNG_WRITE_FILTER_SUPPORTED
/* Choose the best filter to use and filter the row data returning a buffer to
* the result and filling in 'filter_byte' appropriately.
/* Choose the best filter to use and filter the row data then write it out. If
* WRITE_FILTERING is not supported this just writes the data out with a zero
* (NONE) filter byte.
*
* This may be called multiple times per row, but calls must be in 'x' order;
* first a call with x 0 to mark the start of the row and, at the end, one with
* 'end_of_row' set (this can be done in the same function call if the whole row
* is passed.)
*/
PNG_INTERNAL_FUNCTION(png_const_bytep,png_write_filter_row,
(png_structrp png_ptr, png_const_bytep unfiltered_row, int first_pass_row,
png_const_bytep previous_row, png_alloc_size_t rowbytes, unsigned int bpp,
png_bytep filter_byte),PNG_EMPTY);
#endif
PNG_INTERNAL_FUNCTION(unsigned int, png_write_filter_row,
(png_structrp png_ptr, png_bytep prev_pixels, png_const_bytep unfiltered_row,
png_uint_32 x, png_uint_32 width/*pixels*/, int first_row_in_pass,
int last_pass_row, unsigned int filters_to_try/*from previous call*/,
int end_of_image),
PNG_EMPTY);
#ifdef PNG_TRANSFORM_MECH_SUPPORTED
PNG_INTERNAL_FUNCTION(void,png_transform_free,(png_const_structrp png_ptr,
@ -1595,17 +1638,52 @@ typedef enum
png_row_incomplete,
/* more IDAT data needed for row */
png_row_process,
/* png_struct::row_buffer contains a complete, transformed, row */
/* png_struct::row_buffer contains a complete row */
png_row_repeat,
/* row not in this pass, but the existing row may be used */
png_row_skip
/* row not in pass and no appropriate data; skip this row */
} png_row_op;
PNG_INTERNAL_FUNCTION(png_row_op,png_read_process_IDAT,(png_structrp png_ptr),
PNG_EMPTY);
PNG_INTERNAL_FUNCTION(png_row_op,png_read_process_IDAT,(png_structrp png_ptr,
png_bytep transformed_row, png_bytep display_row, int save_row),
PNG_EMPTY);
/* Process a block of IDAT data; the routine returns early if it has
* obtained a row. It is valid to call this routine with no input data;
* it will return PNG_ROW_INCOMPLETE if it needs input.
* it will return png_row_incomplete if it needs input.
*
* transformed_row: The transformed pixels of the input are written here.
* For interlaced images only the pixels in the pass will
* be written, the other pixels will not be touched.
*
* display_row: The transformed pixels but replicated to that the entire
* buffer will have been initialized. For passes after the
* first the pixels written are determined by the 'block'
* algorithm; only those *following* pixels which are
* written by *later* passes are written (with a copy of the
* pixel from the pass.)
*
* save_row: A boolean which indicates that the row (unexpanded)
* should be saved in png_struct::transformed_row. This can
* be used in a later call to png_combine_row.
*
* During reading the row is built up until png_row_process is returned. At
* this point png_struct::row_buffer contains the original PNG row from the
* file and, if save_row was set, png_struct::transformed_row contains the
* row after the selected row transforms have been performed. For interlaced
* images both are the width of the interlace pass.
*
* When png_row_repeat is returned the same is true, except that the buffers
* still contain the contents of the preceding row (the one where this
* funciton returned png_row_pricess).
*
* The row buffers should not be accessed if png_row_skip is returned; this
* row is not modified in the current pass.
*/
PNG_INTERNAL_FUNCTION(void,png_read_free_row_buffers,(png_structrp png_ptr),
PNG_EMPTY);
/* Free allocated row buffers; done as soon as possible to avoid carrying
* around all the memory for longer than necessary.
*/
PNG_INTERNAL_FUNCTION(int,png_read_finish_IDAT,(png_structrp png_ptr),
@ -1671,7 +1749,6 @@ PNG_INTERNAL_FUNCTION(void,png_handle_chunk,(png_structrp png_ptr,
* png_handle_chunk (via the libpng read callback.)
*/
/* Handle the transformations for reading and writing */
PNG_INTERNAL_FUNCTION(void,png_init_row_info,(png_structrp png_ptr),PNG_EMPTY);
/* Set the png_struct::row_ members from the PNG file information, running
* transforms if required.

View File

@ -353,11 +353,6 @@ png_read_IDAT(png_structrp png_ptr)
png_ptr->zstream.avail_in = IDAT_size;
}
#ifndef PNG_READ_DEINTERLACE_SUPPORTED
/* No png_combine_row; just copy the row bytes: */
# define png_combine_row(pp, pb, display) png_copy_row((pp), (pb))
#endif
void PNGAPI
png_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row)
/* It is valid to call this API with both 'row' and 'dsp_row' NULL, all
@ -406,60 +401,42 @@ png_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row)
* has PNG_AFTER_IDAT set, by either doing png_error or using 0 bytes for
* the data (after issuing a warning.)
*/
switch (png_read_process_IDAT(png_ptr))
switch (png_read_process_IDAT(png_ptr, row, dsp_row, 0/*no save*/))
{
case png_row_incomplete:
/* more IDAT data needed for row */
debug(png_ptr->zstream.avail_in == 0);
continue;
case png_row_process:
/* png_struct::row_buffer contains a complete, transformed, row;
* this is processed in both 'sparkle' and 'block' mode. The final
* parameter to png_combine_row is false, meaning only overwrite
* the pixels corresponding to this pass:
*/
if (row != NULL)
png_combine_row(png_ptr, row, 0/*'sparkle'*/);
goto display_row; /* Skip the 'DEINT' check */
case png_row_repeat:
/* row not in this pass, but the existing row in
* png_struct::row_buffer may be used, this is only done if the
* 'block' or 'rectangle' mode of display is required. The final
* parameter to png_combine_row is true, meaning overwrite all the
* pixels belong to this and *later* passes.
/* row not in this pass, but the existing row in row_buffer or (if
* transforms are happening) png_struct::transformed_row is
* available from a previous row.
*/
#ifdef PNG_READ_DEINTERLACE_SUPPORTED
if (!png_ptr->do_interlace)
continue;
#else
continue;
#endif
display_row:
if (dsp_row != NULL)
png_combine_row(png_ptr, dsp_row, 1/*'rectangle/block'*/);
goto row_fn; /* Skip the 'DEINT' check */
/* FALL THROUGH */
case png_row_skip:
/* row not in pass and no appropriate data; skip this row, nothing
* more need be done, except the read_row_fn:
* more need be done, except the read_row_fn and then only if libpng
* is doing the interlace handling (this is the historical
* behavior!)
*/
#ifdef PNG_READ_DEINTERLACE_SUPPORTED
if (!png_ptr->do_interlace)
# ifdef PNG_READ_DEINTERLACE_SUPPORTED
if (!png_ptr->do_interlace) continue;
# else /* !do_interlace */
continue;
#else
continue;
#endif
row_fn:
# endif /* !do_interlace */
/* FALL THROUGH */
case png_row_process:
/* png_read_process_IDAT has done everything we need, the only extra
* required is to call the application row callback.
*/
if (png_ptr->read_row_fn != NULL)
png_ptr->read_row_fn(png_ptr, png_ptr->row_number,
png_ptr->pass);
/* And return now because the next row has been processed; so there
* is exactly one read_row_fn callback for each call to
* png_read_process_IDAT.
*/
return;
default:
@ -732,10 +709,8 @@ png_read_destroy(png_structrp png_ptr)
{
png_debug(1, "in png_read_destroy");
png_free(png_ptr, png_ptr->row_buffer);
png_ptr->row_buffer = NULL;
png_free(png_ptr, png_ptr->alt_buffer);
png_ptr->alt_buffer = NULL;
png_read_free_row_buffers(png_ptr);
png_free(png_ptr, png_ptr->read_buffer);
png_ptr->read_buffer = NULL;

1160
pngrutil.c

File diff suppressed because it is too large Load Diff

View File

@ -446,15 +446,20 @@ struct png_struct_def
* filter byte (which is in next_filter.) All fields are only used during
* IDAT processing and start of 0.
*/
png_bytep row_buffer; /* primary row buffer */
#if defined(PNG_WRITE_FILTER_SUPPORTED) || defined(PNG_READ_SUPPORTED)
png_bytep alt_buffer; /* if two row buffers needed */
#endif
#ifdef PNG_WRITE_FILTER_SUPPORTED
png_bytep write_row[2]; /* Two rows to test filers */
#endif
png_bytep row_buffer; /* primary row buffer */
#endif /* WRITE_FILTER || READ */
#if (defined(PNG_PROGRESSIVE_READ_SUPPORTED) ||\
defined(PNG_READ_DEINTERLACE_SUPPORTED)) &&\
defined(PNG_TRANSFORM_MECH_SUPPORTED)
png_bytep transformed_row; /* pointer to the transformed row, if
* required. May point to row_buffer.
*/
#endif /* (PROGRESSIVE_READ || READ_DEINTERLACE) && TRANSFORM_MECH */
png_alloc_size_t row_allocated_bytes; /* Total amount allocated */
#ifdef PNG_READ_SUPPORTED
png_alloc_size_t row_bytes_read; /* Total read in row */
#endif /* READ */
png_uint_32 row_number; /* current row in pass */
#ifdef PNG_READ_GAMMA_SUPPORTED
@ -484,16 +489,34 @@ struct png_struct_def
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
unsigned int read_started :1; /* at least one call to png_read_row */
#endif
#if defined (PNG_READ_DEINTERLACE_SUPPORTED) ||\
defined (PNG_WRITE_INTERLACE_SUPPORTED)
unsigned int do_interlace :1; /* libpng handles the interlace */
# endif /* READ_DEINTERLACE, WRITE_INTERLACE */
unsigned int pass :3; /* current (interlace) pass (0 - 6) */
/* The next two fields are just used by the IDAT process functions to store
* the state of IDAT processing; they should not be altered or used by other
* functions.
*/
unsigned int prev_in_alt :1; /* previous row is stored in alt_buffer */
unsigned int row_state :2; /* state of row parsing (internal) */
/* The following fields are set by png_row_init to the pixel depths of the
* pixels at various states. If transforms are not supported they will
* always be the same value:
*
* READ WRITE
* input: PNG From application
* output: To application PNG
* max: Largest in transform
*/
unsigned int row_input_pixel_depth :8;
unsigned int row_output_pixel_depth :8;
unsigned int row_max_pixel_depth :8;
#ifdef PNG_WRITE_FILTER_SUPPORTED
unsigned int filter_mask :8; /* mask of filters to consider on write */
#endif /* WRITE_FILTER */
# define PNG_RF_BITS 9 /* Number of bits required for the row format (below) */
#ifdef PNG_TRANSFORM_MECH_SUPPORTED
/* The following fields describe the format of the user row; the output on
@ -528,9 +551,8 @@ struct png_struct_def
* alpha or gray) have been inverted.
* PNG_FORMAT_FLAG_INVALID NOT STORED HERE
*/
unsigned int row_max_pixel :8; /* maximum pixel depth used */
#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
unsigned int info_format:PNG_RF_BITS;
unsigned int info_format:PNG_RF_BITS;
/* This field is used to validate the png_info used to write the
* IHDR. This is a new check in 1.7.0; previously it was possible to pass
* a png_info from a png_read with the read tranform information in the
@ -539,27 +561,20 @@ struct png_struct_def
*/
#endif /* WRITE_TRANSFORMS */
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
unsigned int write_invert_alpha :1;
unsigned int write_invert_alpha :1;
/* This indicates the png_set_invert_alpha was called, it is used by the
* write code to implement the transform without needing to run the whole
* transform mechanism on the PNG palette data.
*/
#endif /* WRITE_INVERT_ALPHA */
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
unsigned int rgb_to_gray_status :1;
unsigned int rgb_to_gray_status :1;
/* If set an RGB pixel was encountered by the RGB to gray transform
* wherein !(r==g==b).
*/
#endif /* RGB_TO_GRAY */
#endif /* TRANFORM_MECH */
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_FILTER_SUPPORTED)
png_byte next_filter; /* Filter byte for upcoming row (read or
* filters+masks to try (write, if WRITE_FILTER is
* supported).
*/
#endif
#ifdef PNG_READ_SUPPORTED
/* These, and IDAT_read_size below, control how much input and output (at
* most) is available to zlib.
@ -629,7 +644,8 @@ struct png_struct_def
* un-filter function, this allows per-image and per-processor optimization.
*/
void (*read_filter[PNG_FILTER_VALUE_LAST-1])(png_alloc_size_t row_bytes,
unsigned int bpp, png_bytep row, png_const_bytep prev_row);
unsigned int bpp, png_bytep row, png_const_bytep prev_row,
png_const_bytep prev_pixels);
#endif /* READ */
#ifdef PNG_WRITE_SUPPORTED
@ -749,5 +765,10 @@ struct png_struct_def
#ifdef PNG_MNG_FEATURES_SUPPORTED
unsigned int mng_features_permitted :3;
#endif
/* SCRATCH buffers, used when control returns to the application or a read
* loop.
*/
png_byte scratch[PNG_ROW_BUFFER_SIZE+16U];
};
#endif /* PNGSTRUCT_H */

View File

@ -65,7 +65,7 @@
defined PNG_READ_tEXt_SUPPORTED &&\
defined PNG_READ_tIME_SUPPORTED &&\
defined PNG_READ_zTXt_SUPPORTED &&\
defined PNG_WRITE_INTERLACING_SUPPORTED
defined PNG_WRITE_INTERLACE_SUPPORTED
#ifdef PNG_ZLIB_HEADER
# include PNG_ZLIB_HEADER /* defined by pnglibconf.h from 1.7 */
@ -844,12 +844,14 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
png_structp write_ptr;
png_infop write_info_ptr;
png_infop write_end_info_ptr;
#ifdef PNG_WRITE_FILTER_SUPPORTED
int interlace_preserved = 1;
#else
#endif /* WRITE_FILTER */
#else /* !WRITE */
png_structp write_ptr = NULL;
png_infop write_info_ptr = NULL;
png_infop write_end_info_ptr = NULL;
#endif
#endif /* !WRITE */
png_bytep row_buf;
png_uint_32 y;
png_uint_32 width, height;
@ -1380,7 +1382,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
pngtest_debug("Writing row data");
#if defined(PNG_READ_DEINTERLACE_SUPPORTED) &&\
defined(PNG_WRITE_INTERLACING_SUPPORTED)
defined(PNG_WRITE_INTERLACE_SUPPORTED)
/* Both must be defined for libpng to be able to handle the interlace,
* otherwise it gets handled below by simply reading and writing the passes
* directly.
@ -1622,7 +1624,8 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
return (1);
}
#ifdef PNG_WRITE_SUPPORTED /* else nothing was written */
#if defined (PNG_WRITE_SUPPORTED) /* else nothing was written */ &&\
defined (PNG_WRITE_FILTER_SUPPORTED)
if (interlace_preserved != 0) /* else the files will be changed */
{
for (;;)
@ -1699,7 +1702,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
}
}
}
#endif /* WRITE */
#endif /* WRITE && WRITE_FILTER */
FCLOSE(fpin);
FCLOSE(fpout);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@ -558,7 +558,7 @@ png_run_transform_list_backwards(png_structp png_ptr, png_transform_controlp tc)
/* Better late than never (if this fires a memory overwrite has happened):
*/
affirm(max_depth <= png_ptr->row_max_pixel);
affirm(max_depth <= png_ptr->row_max_pixel_depth);
}
}
#endif /* WRITE */
@ -832,52 +832,42 @@ png_set_check_for_invalid_index(png_structrp png_ptr, int enabled)
void /* PRIVATE */
png_init_row_info(png_structrp png_ptr)
{
unsigned int max_depth = PNG_PIXEL_DEPTH(*png_ptr);
/* PNG pixels never exceed 64 bits in depth: */
const png_byte png_depth =
png_check_bits(png_ptr, PNG_PIXEL_DEPTH(*png_ptr), 7U);
#ifdef PNG_TRANSFORM_MECH_SUPPORTED
# ifdef PNG_PALETTE_MAX_SUPPORTED
/* The palette index check stuff is *on* automatically. To handle this
* add it here, if it is supported.
*
* The logic here is a little complex because of the plethora of
* #defines controlling this stuff.
*/
# undef PNG_READ_CHECK_PALETTE
# undef PNG_WRITE_CHECK_PALETTE
# if defined(PNG_READ_GET_PALETTE_MAX_SUPPORTED) ||\
defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED)
# ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
# define PNG_READ_CHECK_PALETTE \
(png_ptr->read_struct && !png_ptr->palette_index_check_disabled)
# else
# define PNG_READ_CHECK_PALETTE (png_ptr->read_struct)
# ifdef PNG_TRANSFORM_MECH_SUPPORTED
/* The palette index check stuff is *on* automatically. To handle this
* add it here, if it is supported.
*/
# ifdef PNG_PALETTE_MAX_SUPPORTED
/* The logic here is a little complex because of the plethora of
* #defines controlling this stuff.
*/
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE/* fast escape */ && (
# if defined (PNG_READ_GET_PALETTE_MAX_SUPPORTED) ||\
defined (PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED)
(png_ptr->read_struct
# ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
&& !png_ptr->palette_index_check_disabled)
# endif /* READ_CHECK_FOR_INVALID_INDEX */
# else /* no READ support */
0
# endif /* READ checks */
||
# if defined (PNG_WRITE_GET_PALETTE_MAX_SUPPORTED) ||\
defined (PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED)
(!png_ptr->read_struct
# ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
&& !png_ptr->palette_index_check_disabled)
# endif /* WRITE_CHECK_FOR_INVALID_INDEX */
# else /* no WRITE support */
0
# endif /* WRITE checks */
))
png_add_transform(png_ptr, 0/*size*/, palette_max_init,
PNG_TR_CHECK_PALETTE);
# endif
# else /* no READ support */
# define PNG_READ_CHECK_PALETTE 0
# endif
# if defined(PNG_WRITE_GET_PALETTE_MAX_SUPPORTED) ||\
defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED)
# ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
# define PNG_WRITE_CHECK_PALETTE \
(!png_ptr->read_struct && !png_ptr->palette_index_check_disabled)
# else
# define PNG_WRITE_CHECK_PALETTE (!png_ptr->read_struct)
# endif
# else /* no WRITE support */
# define PNG_WRITE_CHECK_PALETTE 0
# endif
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE/* fast escape */ &&
(PNG_READ_CHECK_PALETTE || PNG_WRITE_CHECK_PALETTE))
{
png_add_transform(png_ptr, 0/*size*/, palette_max_init,
PNG_TR_CHECK_PALETTE);
}
# undef PNG_READ_CHECK_PALETTE
# undef PNG_WRITE_CHECK_PALETTE
# endif /* PALETTE_MAX */
/* Application transforms may change the format of the data or, when
* producing interlaced images, the number of pixels in a line. This code
@ -894,9 +884,9 @@ png_init_row_info(png_structrp png_ptr)
affirm(tc.bit_depth <= 32);
png_ptr->row_bit_depth = png_check_bits(png_ptr, tc.bit_depth, 6);
png_ptr->row_range = png_check_bits(png_ptr, tc.range, 3);
# ifdef PNG_READ_GAMMA_SUPPORTED
png_ptr->row_gamma = tc.gamma;
# endif /* READ_GAMMA */
# ifdef PNG_READ_GAMMA_SUPPORTED
png_ptr->row_gamma = tc.gamma;
# endif /* READ_GAMMA */
/* The above may have cancelled all the transforms in the list. */
if (png_ptr->transform_list != NULL)
@ -905,25 +895,60 @@ png_init_row_info(png_structrp png_ptr)
* maximum pixel depth. At this point the transforms can swap
* out their initialization code.
*/
unsigned int depth = init_transform_mech(png_ptr, &tc, 0/*final*/);
unsigned int max_depth =
init_transform_mech(png_ptr, &tc, 0/*final*/);
if (depth > max_depth)
max_depth = depth;
# ifdef PNG_READ_TRANSFORMS_SUPPORTED
/* Set this now because it only gets resolved finally at this
* point.
/* init_transform_mech is expected to take the input depth into
* account:
*/
png_ptr->invalid_info = tc.invalid_info;
# endif /* READ_TRANSFORMS */
debug(max_depth >= png_depth);
if (max_depth < png_depth)
max_depth = png_depth;
affirm(max_depth <= (png_ptr->read_struct ? 128U : 64U));
# ifdef PNG_READ_TRANSFORMS_SUPPORTED
/* Set this now because it only gets resolved finally at this
* point.
*/
png_ptr->invalid_info = tc.invalid_info;
# endif /* READ_TRANSFORMS */
/* And check the transform fields: */
affirm(png_ptr->row_format == tc.format &&
png_ptr->row_range == tc.range &&
png_ptr->row_bit_depth == tc.bit_depth);
# ifdef PNG_READ_GAMMA_SUPPORTED
affirm(png_ptr->row_gamma == tc.gamma);
# endif /* READ_GAMMA */
# ifdef PNG_READ_GAMMA_SUPPORTED
affirm(png_ptr->row_gamma == tc.gamma);
# endif /* READ_GAMMA */
png_ptr->row_max_pixel_depth =
png_check_bits(png_ptr, max_depth, 8U);
/* On 'read' input_depth is the PNG pixel depth and output_depth is
* the depth of the pixels passed to the application, but on 'write'
* the transform list is reversed so output_depth is the PNG depth
* and input_depth the application depth.
*/
{
const png_byte app_depth =
png_check_bits(png_ptr, PNG_TC_PIXEL_DEPTH(tc), 8U);
affirm(app_depth <= max_depth);
if (png_ptr->read_struct)
{
png_ptr->row_input_pixel_depth = png_depth;
png_ptr->row_output_pixel_depth = app_depth;
}
else
{
png_ptr->row_input_pixel_depth = app_depth;
png_ptr->row_output_pixel_depth = png_depth;
}
return; /* to skip the default settings below */
}
}
}
@ -934,46 +959,27 @@ png_init_row_info(png_structrp png_ptr)
png_ptr->row_bit_depth = png_check_bits(png_ptr, png_ptr->bit_depth,
6);
png_ptr->row_range = 0;
# ifdef PNG_READ_GAMMA_SUPPORTED
if ((png_ptr->colorspace.flags &
(PNG_COLORSPACE_INVALID|PNG_COLORSPACE_HAVE_GAMMA)) ==
PNG_COLORSPACE_HAVE_GAMMA)
png_ptr->row_gamma = png_ptr->colorspace.gamma;
# endif /* READ_GAMMA */
# ifdef PNG_READ_TRANSFORMS_SUPPORTED
png_ptr->invalid_info = 0U;
# endif /* READ_TRANSFORMS */
# ifdef PNG_READ_GAMMA_SUPPORTED
if ((png_ptr->colorspace.flags &
(PNG_COLORSPACE_INVALID|PNG_COLORSPACE_HAVE_GAMMA)) ==
PNG_COLORSPACE_HAVE_GAMMA)
png_ptr->row_gamma = png_ptr->colorspace.gamma;
# endif /* READ_GAMMA */
# ifdef PNG_READ_TRANSFORMS_SUPPORTED
png_ptr->invalid_info = 0U;
# endif /* READ_TRANSFORMS */
}
# endif /* TRANSFORM_MECH */
/* 'max_depth' is now the maximum size of a pixel, including intermediate
* results during the transforms. The current limit is 4 32-bit channels:
*/
affirm(max_depth <= 128);
png_ptr->row_max_pixel = png_check_bits(png_ptr, max_depth, 8);
#endif /* TRANSFORM_MECH */
/* png_calc_rowbytes does a png_error on overflow. This is how the libpng
* code validates that there won't be overflows on future PNG_ROWBYTES
* calls.
*
* The largest integer we can guarantee with ANSI-C is a 32-bit one (unsigned
* long). To allow the row to be accessed as png_uint_32[] this code sets
* the allocation to a multiple of 4:
/* We get here if there are no transforms therefore no change to the pixel
* bit depths.
*/
{
png_alloc_size_t rowbytes = png_calc_rowbytes(png_ptr, max_depth,
png_ptr->width);
png_alloc_size_t alloc = (rowbytes + 3U) & ~3U;
if (alloc < rowbytes)
png_error(png_ptr, "PNG row exceeds system limits");
png_ptr->row_allocated_bytes = alloc;
}
png_ptr->row_output_pixel_depth = png_ptr->row_max_pixel_depth =
png_ptr->row_input_pixel_depth = png_depth;
}
#if defined(PNG_READ_DEINTERLACE_SUPPORTED) || \
defined(PNG_WRITE_INTERLACING_SUPPORTED)
defined(PNG_WRITE_INTERLACE_SUPPORTED)
int PNGAPI
png_set_interlace_handling(png_structrp png_ptr)
{
@ -999,26 +1005,25 @@ png_set_interlace_handling(png_structrp png_ptr)
else /* write */
{
# ifdef PNG_WRITE_INTERLACING_SUPPORTED
# ifdef PNG_WRITE_INTERLACE_SUPPORTED
if (png_ptr->interlaced)
{
png_ptr->do_interlace = 1;
png_set_write_interlace(png_ptr);
return PNG_INTERLACE_ADAM7_PASSES;
}
return 1;
# else /* !WRITE_INTERLACING */
# else /* !WRITE_INTERLACE */
png_app_error(png_ptr, "no interlace support");
/* return 0 below */
# endif /* !WRITE_INTERLACING */
# endif /* !WRITE_INTERLACE */
}
}
/* API CHANGE: 1.7.0: returns 0 if called with a NULL png_ptr */
return 0;
}
#endif /* READ_DEINTERLACE || WRITE_INTERLACING */
#endif /* READ_DEINTERLACE || WRITE_INTERLACE */
#ifdef PNG_MNG_READ_FEATURES_SUPPORTED
/* Undoes intrapixel differencing, this is called immediately after the PNG

File diff suppressed because it is too large Load Diff

View File

@ -14,236 +14,6 @@
#include "pngpriv.h"
#define PNG_SRC_FILE PNG_SRC_FILE_pngwtran
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
/* Pick out the correct pixels for the interlace pass.
* The basic idea here is to go through the row with a source
* pointer and a destination pointer (sp and dp), and copy the
* correct pixels for the pass. As the row gets compacted,
* sp will always be >= dp, so we should never overwrite anything.
* See the default: case for the easiest code to understand.
*/
static void
png_do_write_interlace_lbd(png_transformp *transform, png_transform_controlp tc)
{
const png_const_structrp png_ptr = tc->png_ptr;
const unsigned int pass = png_ptr->pass;
const png_uint_32 row_width = tc->width;
const png_uint_32 output_width = PNG_PASS_COLS(row_width, pass);
png_uint_32 i = PNG_PASS_START_COL(pass);
png_debug(1, "in png_do_write_interlace");
debug(!tc->init);
/* The data can be used in place (tc->sp) if the width isn't changed or
* the first pixel in the output is the first in the input and there is
* only one pixel in the output; this covers the last pass (PNG pass 7,
* libpng 6) and PNG passes 1, 3 and 5 with narrow images.
*/
tc->width = output_width;
if (row_width != output_width && (output_width != 1 || i > 0))
{
/* For passes before the last the pixels must be picked from the input
* row (tc->sp) and placed into the output row (tc->dp).
*/
png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);
png_bytep dp = png_voidcast(png_bytep, tc->dp);
const unsigned int inc = PNG_PASS_COL_OFFSET(pass);
unsigned int B = (*transform)->args & 0x3; /* 0, 1 or 2 */
/* The row data will be moved, so do this now before 'dp' is advanced:
*/
tc->sp = dp;
/* For pixels less than one byte wide the correct pixels have to be
* extracted from the input bytes. Because we are reading data in
* the application memory format we cannot rely on the PNG big
* endian order. Notice that this was apparently broken before
* 1.7.0.
*
* In libpng 1.7.0 libpng uses a classic bit-pump to optimize the
* extraction. In all passes before the last (6/7) no two pixels
* are adjacent in the input, so we are always extracting 1 bit.
* At present the code uses an 8-bit buffer to avoid coding for
* different byte sexes, but this could easily be changed.
*
* 'i' is the bit-index of bit in the input (sp[]), so,
* considering the 1-bit per pixel case, sp[i>>3] is the byte
* and the bit is bit (i&7) (0 lowest) on swapped (little endian)
* data or 7-(i&7) on PNG default (big-endian) data.
*
* Define these macros, where:
*
* B: the log2 bit depth (0, 1, 2 for 1bpp, 2bpp or 4bpp) of
* the data; this should be a constant.
* sp: the source pointer (sp) (a png_const_bytep)
* i: the pixel index in the input (png_uint_32)
* j: the bit index in the output (unsigned int)
*
* Unlike 'i', 'j' is interpreted directly; for LSB bytes it counts
* up, for MSB it counts down.
*
* NOTE: this could all be expanded to eliminate the code below by
* the time honoured copy'n'paste into three separate functions. This
* might be worth doing in the future.
*/
# define PIXEL_MASK ((1U << (1<<B))-1U)
# define BIT_MASK ((1U << (3-(B)))-1U) /* within a byte */
# define SP_BYTE (sp[i>>(3-(B))]) /* byte to use */
# define SP_OFFSET_LSB ((BIT_MASK & i) << (B))
# define SP_OFFSET_MSB ((BIT_MASK & ~i) << (B))
# define SP_PIXEL(sex) ((SP_BYTE >> SP_OFFSET_ ## sex) & PIXEL_MASK)
{
unsigned int j;
unsigned int d;
# ifdef PNG_WRITE_PACKSWAP_SUPPORTED
if (tc->format & PNG_FORMAT_FLAG_SWAPPED)
for (j = 0, d = 0; i < row_width; i += inc)
{ /* little-endian */
d |= SP_PIXEL(LSB) << j;
j += 1<<B;
if (j == 8) *dp++ = png_check_byte(png_ptr, d), j = 0, d = 0;
}
else
# endif /* WRITE_PACKSWAP */
for (j = 8, d = 0; i < row_width; i += inc)
{ /* big-endian */
j -= 1<<B;
d |= SP_PIXEL(MSB) << j;
if (j == 0) *dp++ = png_check_byte(png_ptr, d), j = 8, d = 0;
}
/* The end condition: if j is not 0 the last byte was not
* written:
*/
if (j != 0) *dp = png_check_byte(png_ptr, d);
}
# undef PIXEL_MASK
# undef BIT_MASK
# undef SP_BYTE
# undef SP_OFFSET_MSB
# undef SP_OFFSET_LSB
# undef SP_PIXEL
}
/* The transform is removed on the last pass. It can be removed earlier
* in other cases if the row width (the image width) is only 1, however
* this does not seem worth the overhead to check; PNG pass 5(4) happens
* if there are just three rows.
*/
else /* the source can be used in place */ if (pass == 6)
(*transform)->fn = NULL; /* remove me to caller */
}
static void
png_do_write_interlace_byte(png_transformp *transform,
png_transform_controlp tc)
{
const png_const_structrp png_ptr = tc->png_ptr;
const unsigned int pass = png_ptr->pass;
const png_uint_32 row_width = tc->width;
const png_uint_32 output_width = PNG_PASS_COLS(row_width, pass);
png_uint_32 i = PNG_PASS_START_COL(pass);
png_debug(1, "in png_do_write_interlace");
debug(!tc->init);
/* The data can be used in place (tc->sp) if the width isn't changed or
* the first pixel in the output is the first in the input and there is
* only one pixel in the output; this covers the last pass (PNG pass 7,
* libpng 6) and PNG passes 1, 3 and 5 with narrow images.
*/
tc->width = output_width;
if (row_width != output_width && (output_width != 1 || i > 0))
{
/* For passes before the last the pixels must be picked from the input
* row (tc->sp) and placed into the output row (tc->dp).
*/
png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);
png_bytep dp = png_voidcast(png_bytep, tc->dp);
const unsigned int inc = PNG_PASS_COL_OFFSET(pass);
unsigned int cbytes = (*transform)->args;
/* The row data will be moved, so do this now before 'dp' is advanced:
*/
tc->sp = dp;
/* Loop through the input copying each pixel to the correct place
* in the output. Note that the loop may be executed 0 times if
* this is called on a narrow image that does not contain this
* pass.
*/
for (sp += i * cbytes; i < row_width;
i += inc, sp += inc * cbytes, dp += cbytes)
if (dp != sp) /* cannot happen in practice */
memcpy(dp, sp, cbytes);
}
/* The transform is removed on the last pass. It can be removed earlier
* in other cases if the row width (the image width) is only 1, however
* this does not seem worth the overhead to check; PNG pass 5(4) happens
* if there are just three rows.
*/
else /* the source can be used in place */ if (pass == 6)
(*transform)->fn = NULL; /* remove me to caller */
}
static void
png_init_write_interlace(png_transformp *transform, png_transform_controlp tc)
{
# define png_ptr (tc->png_ptr)
png_debug(1, "in png_do_write_interlace");
debug(tc->init);
/* Do nothing on PNG_TC_INIT_FORMAT because we don't change the format, bit
* depth or gamma of the data.
*/
if (tc->init == PNG_TC_INIT_FINAL)
{
png_transformp tf = *transform;
unsigned int pixel_depth = PNG_TC_PIXEL_DEPTH(*tc);
png_uint_16 B = 0;
switch (pixel_depth)
{
case 4: /* B == 2 */
++B;
/* FALL THROUGH */
case 2: /* B == 1 */
++B;
/* FALL THROUGH */
case 1: /* B == 0 */
/* This is the low bit depth case: */
tf->args = B;
tf->fn = png_do_write_interlace_lbd;
break;
default:
affirm((pixel_depth & 7) == 0);
pixel_depth >>= 3;
affirm(pixel_depth > 0 && pixel_depth <= 8);
tf->args = pixel_depth & 0xf;
tf->fn = png_do_write_interlace_byte;
break;
}
}
# undef png_ptr
}
void /* PRIVATE */
png_set_write_interlace(png_structrp png_ptr)
{
/* This is checked in the caller: */
debug(png_ptr->interlaced == PNG_INTERLACE_ADAM7);
png_add_transform(png_ptr, 0, png_init_write_interlace, PNG_TR_INTERLACE);
}
#endif /* WRITE_INTERLACING */
#ifdef PNG_WRITE_PACK_SUPPORTED
/* Pack pixels into bytes. */
static void

1069
pngwutil.c

File diff suppressed because it is too large Load Diff

View File

@ -593,9 +593,10 @@ option WRITE_SWAP_ALPHA requires WRITE_TRANSFORMS enables TRANSFORM_MECH
option WRITE_INVERT_ALPHA requires WRITE_TRANSFORMS
option WRITE_USER_TRANSFORM requires WRITE_TRANSFORMS enables TRANSFORM_MECH
# This is not required for PNG-compliant encoders, but can cause
# trouble if left undefined
option WRITE_INTERLACING requires WRITE enables TRANSFORM_MECH
# This just disables the code within libpng to implement image interlacing on
# write; the app can still write interlaced images by doing it itself.
option WRITE_INTERLACING disabled
option WRITE_INTERLACE requires WRITE enables WRITE_INTERLACING
# The following is no longer implemented:
option WRITE_WEIGHTED_FILTER requires WRITE

View File

@ -0,0 +1,2 @@
#!/bin/sh
exec ./pngvalid --strict --transform --interlace