[libpng17] Added pngimage test program for png_read_png and png_write_png.

This is a work-in-progress; no tests are run automatically at present and
the program by virtue of exhaustively testing all the transforms is
very slow.
This commit is contained in:
Glenn Randers-Pehrson
2014-01-31 22:00:27 -06:00
parent 39fee3cee1
commit 302c58b8cf
4 changed files with 271 additions and 3 deletions

View File

@@ -500,7 +500,7 @@ Version 1.7.0beta30 [February 1, 2014]
Fixed a large number of instances where PNGCBAPI was omitted from Fixed a large number of instances where PNGCBAPI was omitted from
function definitions. function definitions.
Added pngimage test program for png_read_png and png_write_png. This Added pngimage test program for png_read_png and png_write_png. This
is a work-in-progress, no tests are run automatically at present and is a work-in-progress; no tests are run automatically at present and
the program by virtue of exhaustively testing all the transforms is the program by virtue of exhaustively testing all the transforms is
very slow. very slow.

View File

@@ -4789,7 +4789,7 @@ Version 1.7.0beta30 [February 1, 2014]
Fixed a large number of instances where PNGCBAPI was omitted from Fixed a large number of instances where PNGCBAPI was omitted from
function definitions. function definitions.
Added pngimage test program for png_read_png and png_write_png. This Added pngimage test program for png_read_png and png_write_png. This
is a work-in-progress, no tests are run automatically at present and is a work-in-progress; no tests are run automatically at present and
the program by virtue of exhaustively testing all the transforms is the program by virtue of exhaustively testing all the transforms is
very slow. very slow.

View File

@@ -7,7 +7,7 @@ PNGLIB_BASENAME= libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@
ACLOCAL_AMFLAGS = -I scripts ACLOCAL_AMFLAGS = -I scripts
# test programs - run on make check, make distcheck # test programs - run on make check, make distcheck
check_PROGRAMS= pngtest pngunknown pngstest pngvalid check_PROGRAMS= pngtest pngunknown pngstest pngvalid pngimage
# Utilities - installed # Utilities - installed
bin_PROGRAMS= pngfix png-fix-itxt bin_PROGRAMS= pngfix png-fix-itxt
@@ -34,6 +34,9 @@ pngstest_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
pngunknown_SOURCES = contrib/libtests/pngunknown.c pngunknown_SOURCES = contrib/libtests/pngunknown.c
pngunknown_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la pngunknown_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
pngimage_SOURCES = contrib/libtests/pngimage.c
pngimage_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
pngfix_SOURCES = contrib/tools/pngfix.c pngfix_SOURCES = contrib/tools/pngfix.c
pngfix_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la pngfix_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
@@ -214,6 +217,7 @@ pngtest.o: pnglibconf.h
contrib/libtests/makepng.o: pnglibconf.h contrib/libtests/makepng.o: pnglibconf.h
contrib/libtests/pngstest.o: pnglibconf.h contrib/libtests/pngstest.o: pnglibconf.h
contrib/libtests/pngunknown.o: pnglibconf.h contrib/libtests/pngunknown.o: pnglibconf.h
contrib/libtests/pngimage.o: pnglibconf.h
contrib/libtests/pngvalid.o: pnglibconf.h contrib/libtests/pngvalid.o: pnglibconf.h
contrib/libtests/readpng.o: pnglibconf.h contrib/libtests/readpng.o: pnglibconf.h
contrib/libtests/tarith.o: pnglibconf.h contrib/libtests/tarith.o: pnglibconf.h

264
contrib/libtests/pngimage.c Normal file
View File

@@ -0,0 +1,264 @@
/* pngimage.c
*
* Copyright (c) 2014 John Cunningham Bowler
*
* Last changed in libpng 1.6.9 [January 30, 2014]
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*
* Test the png_read_png and png_write_png interfaces. Given a PNG file load it
* using png_read_png and then write with png_write_png. Test all possible
* transforms.
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H)
# include <config.h>
#endif
/* Define the following to use this test against your installed libpng, rather
* than the one being built here:
*/
#ifdef PNG_FREESTANDING_TESTS
# include <png.h>
#else
# include "../../png.h"
#endif
#if defined(PNG_INFO_IMAGE_SUPPORTED) && defined(PNG_READ_SUPPORTED)
#ifdef PNG_WRITE_SUPPORTED
/* File data, held in a linked list of buffers - not all of these are in use. */
struct buffer_list
{
struct buffer_list *next; /* next buffer in list */
png_byte buffer[1024]; /* the actual buffer */
};
struct buffer
{
struct buffer_list *last; /* last buffer in use */
size_t end_count; /* bytes in the last buffer */
struct buffer_list first; /* the very first buffer */
};
static struct buffer *
get_buffer(png_structp png_ptr)
{
return (struct buffer*)png_get_io_ptr(png_ptr);
}
static void PNGCBAPI
write_function(png_structp png_ptr, png_bytep data, png_size_t size)
{
static struct buffer write_buffer; /* Preallocated list for write */
struct buffer *buffer = get_buffer(png_ptr);
if (buffer == NULL)
{
/* This is the first write for this PNG, use the global buffer but rewind
* it to the start of the buffer list:
*/
write_buffer.last = &write_buffer.first;
write_buffer.end_count = 0;
buffer = &write_buffer;
png_set_write_fn(png_ptr, buffer, write_function, NULL/*flush*/);
}
/* Write the data into the buffer, adding buffers as required */
while (size > 0)
{
struct buffer_list *last = buffer->last;
size_t avail;
if (buffer->end_count >= sizeof last->buffer)
{
if (last->next == NULL)
{
struct buffer_list *add =
(struct buffer_list*)malloc(sizeof *add);
if (add == NULL)
png_error(png_ptr, "pngimage: out of memory buffering output");
add->next = NULL;
last->next = add;
}
last = last->next;
buffer->last = last;
buffer->end_count = 0;
}
avail = (sizeof last->buffer) - buffer->end_count;
if (avail > size)
avail = size;
memcpy(last->buffer + buffer->end_count, data, avail);
buffer->end_count -= avail;
size -= avail;
data += avail;
}
}
static int
write_png(png_infop info_ptr, int transforms)
{
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,0,0,0);
if (png_ptr == NULL)
{
fprintf(stderr, "png_image: failed to create write png_struct\n");
return 0;
}
if (setjmp(png_jmpbuf(png_ptr)))
{
png_destroy_write_struct(&png_ptr, NULL);
return 0;
}
/* Passing NULL for io_ptr causes write_function to initialize the buffer on
* the first write.
*/
png_set_write_fn(png_ptr, NULL/*io_ptr*/, write_function, NULL/*flush*/);
# ifdef PNG_SET_USER_LIMITS_SUPPORTED
/* Remove the user limits, if any */
png_set_user_limits(png_ptr, 0x7fffffff, 0x7fffffff);
# endif
png_write_png(png_ptr, info_ptr, transforms, NULL/*params*/);
png_destroy_write_struct(&png_ptr, NULL);
return 1; /* success */
}
static void
do_write_tests(png_infop info_ptr, int read_transforms)
{
/* TODO: fix this, it currently crashes (probably because of the re-use of
* the info_ptr!)
*/
if (!write_png(info_ptr, 0/*transform*/))
exit(1);
(void)read_transforms;
}
#endif
static int
read_png(FILE *fp /*input image*/, png_bytepp rows /*may be NULL*/,
int transforms, int test_write)
{
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0);
png_infop info_ptr = NULL;
if (png_ptr == NULL)
return 0;
if (setjmp(png_jmpbuf(png_ptr)))
{
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
return 0;
}
# ifdef PNG_SET_USER_LIMITS_SUPPORTED
/* Remove the user limits, if any */
png_set_user_limits(png_ptr, 0x7fffffff, 0x7fffffff);
# endif
# ifdef PNG_STDIO_SUPPORTED
rewind(fp);
png_init_io(png_ptr, fp);
# else
fprintf(stderr, "png_image: no stdio support, test skipped\n");
exit(77);
# endif
/* The png_read_png API requires us to make the info struct, but it does the
* call to png_read_info.
*/
info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL)
png_error(png_ptr, "OOM allocating info structure");
/* The test uses either local allocation of the info structure or allocation
* by libpng depending on the passed in row pointer buffer.
*/
if (rows != NULL)
png_set_rows(png_ptr, info_ptr, rows);
png_read_png(png_ptr, info_ptr, transforms, NULL);
/* Now get the rows if necessary. */
if (rows == NULL)
{
rows = png_get_rows(png_ptr, info_ptr);
if (rows == NULL)
png_error(png_ptr, "pngimage: no image allocated");
}
if (test_write)
{
# ifdef PNG_WRITE_SUPPORTED
/* This just exits on error */
do_write_tests(info_ptr, transforms);
# endif
}
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
return 1;
}
int
main(int argc, const char * const *argv)
{
/* For each file on the command line test it with a range of transforms */
int i;
for (i=1; i<argc;)
{
const char *name = argv[i++];
FILE *fp = fopen(name, "rb");
unsigned int transform;
if (fp == NULL)
{
fprintf(stderr, "pngimage: %s: open failed (%s)\n", name,
strerror(errno));
exit(99/*hard fail, not libpng*/);
}
/* There are 65536 possible combinations. For the moment test all of them
* (this needs to be reduced for a practical test!)
*/
for (transform=0; transform<0xffff; ++transform)
if (!read_png(fp, NULL/*rows*/, (int)/*SAFE*/transform, 1/*write*/))
{
fprintf(stderr, "pngimage: %s: %x: transform failed\n", name,
transform);
/* Exit on the first detected error */
exit(1);
}
fclose(fp);
}
/* Here on success */
return 0;
}
#else /* !PNG_INFO_IMAGE_SUPPORTED || !PNG_READ_SUPPORTED */
int
main(void)
{
fprintf(stderr, "pngimage: no support for png_read/write_image\n");
return 77;
}
#endif