mirror of
https://git.code.sf.net/p/libpng/code.git
synced 2025-07-10 18:04:09 +02:00
Improve, refactor and clean up pngtest.c
Improve: The pngtest program used to be rather relaxed upon seeing invalid parameters in callbacks: it either ignored them, or it bailed out of the callbacks, essentially sweeping the bug under the rug. But no more. Now it terminates with a severe `png_error`, in which it says what's broken and where. Improve: `PNG_DEBUG`, defined externally at build time, and defaulting to zero, was assumed to be non-negative. Now it's checked. Clean up: In a very distant past, the pngtest program used to "travel" across libpng versions, on its own, not necessarily accompanied by the actual library version that it was meant to test. However, this stopped being the case, and now is as good a time as any to remove the compatibility workarounds that had made the aforementioned "travel" possible. Other chores include: * The refactoring of the user-defined chunk handling routines; * The cleanup of an unnecessary use of volatile; * The various cosmetic improvements of code and comments.
This commit is contained in:
parent
ce1f1f001e
commit
9138be341b
360
pngtest.c
360
pngtest.c
@ -37,64 +37,62 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Defined so I can write to a file on gui/windowing platforms */
|
||||
/* #define STDERR stderr */
|
||||
#define STDERR stdout /* For DOS */
|
||||
#ifdef PNG_ZLIB_HEADER
|
||||
# include PNG_ZLIB_HEADER /* defined by pnglibconf.h from 1.7 */
|
||||
#else
|
||||
# include <zlib.h>
|
||||
#endif
|
||||
|
||||
#include "png.h"
|
||||
|
||||
/* 1.6.1 added support for the configure test harness, which uses 77 to indicate
|
||||
* a skipped test, in earlier versions and cmake builds we need to succeed on
|
||||
* a skipped test, so:
|
||||
/* KEEPME in libpng-1.6.x */
|
||||
#define STDERR stdout
|
||||
|
||||
/* In version 1.6.1, we added support for the configure test harness, which
|
||||
* uses 77 to indicate a skipped test. On the other hand, in cmake build tests,
|
||||
* we still need to succeed on a skipped test, so:
|
||||
*/
|
||||
#if PNG_LIBPNG_VER >= 10601 && defined(HAVE_CONFIG_H)
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
# define SKIP 77
|
||||
#else
|
||||
# define SKIP 0
|
||||
#endif
|
||||
|
||||
|
||||
/* Known chunks that exist in pngtest.png must be supported or pngtest will fail
|
||||
* simply as a result of re-ordering them. This may be fixed in 1.7
|
||||
/* Known chunks that exist in pngtest.png must be supported, or pngtest will
|
||||
* fail simply as a result of re-ordering them. This may be fixed in the next
|
||||
* generation of libpng.
|
||||
*
|
||||
* pngtest allocates a single row buffer for each row and overwrites it,
|
||||
* therefore if the write side doesn't support the writing of interlaced images
|
||||
* nothing can be done for an interlaced image (and the code below will fail
|
||||
* horribly trying to write extra data after writing garbage).
|
||||
*/
|
||||
#if defined PNG_READ_SUPPORTED && /* else nothing can be done */\
|
||||
defined PNG_READ_bKGD_SUPPORTED &&\
|
||||
defined PNG_READ_cHRM_SUPPORTED &&\
|
||||
defined PNG_READ_gAMA_SUPPORTED &&\
|
||||
defined PNG_READ_oFFs_SUPPORTED &&\
|
||||
defined PNG_READ_pCAL_SUPPORTED &&\
|
||||
defined PNG_READ_pHYs_SUPPORTED &&\
|
||||
defined PNG_READ_sBIT_SUPPORTED &&\
|
||||
defined PNG_READ_sCAL_SUPPORTED &&\
|
||||
defined PNG_READ_sRGB_SUPPORTED &&\
|
||||
defined PNG_READ_sPLT_SUPPORTED &&\
|
||||
defined PNG_READ_tEXt_SUPPORTED &&\
|
||||
defined PNG_READ_tIME_SUPPORTED &&\
|
||||
defined PNG_READ_zTXt_SUPPORTED &&\
|
||||
(defined PNG_WRITE_INTERLACING_SUPPORTED || PNG_LIBPNG_VER >= 10700)
|
||||
|
||||
#ifdef PNG_ZLIB_HEADER
|
||||
# include PNG_ZLIB_HEADER /* defined by pnglibconf.h from 1.7 */
|
||||
#else
|
||||
# include "zlib.h"
|
||||
#endif
|
||||
#if defined PNG_READ_SUPPORTED && /* else nothing can be done */ \
|
||||
defined PNG_READ_bKGD_SUPPORTED && \
|
||||
defined PNG_READ_cHRM_SUPPORTED && \
|
||||
defined PNG_READ_gAMA_SUPPORTED && \
|
||||
defined PNG_READ_oFFs_SUPPORTED && \
|
||||
defined PNG_READ_pCAL_SUPPORTED && \
|
||||
defined PNG_READ_pHYs_SUPPORTED && \
|
||||
defined PNG_READ_sBIT_SUPPORTED && \
|
||||
defined PNG_READ_sCAL_SUPPORTED && \
|
||||
defined PNG_READ_sRGB_SUPPORTED && \
|
||||
defined PNG_READ_sPLT_SUPPORTED && \
|
||||
defined PNG_READ_tEXt_SUPPORTED && \
|
||||
defined PNG_READ_tIME_SUPPORTED && \
|
||||
defined PNG_READ_zTXt_SUPPORTED && \
|
||||
(defined PNG_WRITE_INTERLACING_SUPPORTED || PNG_LIBPNG_VER >= 10700)
|
||||
|
||||
/* Copied from pngpriv.h but only used in error messages below. */
|
||||
#ifndef PNG_ZBUF_SIZE
|
||||
# define PNG_ZBUF_SIZE 8192
|
||||
#endif
|
||||
#define FCLOSE(file) fclose(file)
|
||||
|
||||
#ifndef PNG_STDIO_SUPPORTED
|
||||
typedef FILE * png_FILE_p;
|
||||
typedef FILE * png_FILE_p;
|
||||
#endif
|
||||
|
||||
/* Makes pngtest verbose so we can find problems. */
|
||||
#ifndef PNG_DEBUG
|
||||
# define PNG_DEBUG 0
|
||||
#endif
|
||||
@ -109,12 +107,12 @@ typedef FILE * png_FILE_p;
|
||||
# define pngtest_debug2(m,p1,p2) ((void)0)
|
||||
#endif
|
||||
|
||||
#if !PNG_DEBUG
|
||||
#if PNG_DEBUG == 0
|
||||
# define SINGLE_ROWBUF_ALLOC /* Makes buffer overruns easier to nail */
|
||||
#endif
|
||||
|
||||
#ifndef PNG_UNUSED
|
||||
# define PNG_UNUSED(param) (void)param;
|
||||
#if PNG_DEBUG < 0
|
||||
# error "Bad PNG_DEBUG value"
|
||||
#endif
|
||||
|
||||
/* Turn on CPU timing
|
||||
@ -131,25 +129,8 @@ static float t_start, t_stop, t_decode, t_encode, t_misc;
|
||||
#endif
|
||||
|
||||
#ifdef PNG_TIME_RFC1123_SUPPORTED
|
||||
#define PNG_tIME_STRING_LENGTH 29
|
||||
static int tIME_chunk_present = 0;
|
||||
static char tIME_string[PNG_tIME_STRING_LENGTH] = "tIME chunk is not present";
|
||||
|
||||
#if PNG_LIBPNG_VER < 10619
|
||||
#define png_convert_to_rfc1123_buffer(ts, t) tIME_to_str(read_ptr, ts, t)
|
||||
|
||||
static int
|
||||
tIME_to_str(png_structp png_ptr, png_charp ts, png_const_timep t)
|
||||
{
|
||||
png_const_charp str = png_convert_to_rfc1123(png_ptr, t);
|
||||
|
||||
if (str == NULL)
|
||||
return 0;
|
||||
|
||||
strcpy(ts, str);
|
||||
return 1;
|
||||
}
|
||||
#endif /* older libpng */
|
||||
static char tIME_string[] = "tIME chunk is not present";
|
||||
#endif
|
||||
|
||||
static int verbose = 0;
|
||||
@ -160,22 +141,6 @@ static int unsupported_chunks = 0; /* chunk unsupported by libpng in input */
|
||||
static int error_count = 0; /* count calls to png_error */
|
||||
static int warning_count = 0; /* count calls to png_warning */
|
||||
|
||||
/* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */
|
||||
#ifndef png_jmpbuf
|
||||
# define png_jmpbuf(png_ptr) png_ptr->jmpbuf
|
||||
#endif
|
||||
|
||||
/* Defines for unknown chunk handling if required. */
|
||||
#ifndef PNG_HANDLE_CHUNK_ALWAYS
|
||||
# define PNG_HANDLE_CHUNK_ALWAYS 3
|
||||
#endif
|
||||
#ifndef PNG_HANDLE_CHUNK_IF_SAFE
|
||||
# define PNG_HANDLE_CHUNK_IF_SAFE 2
|
||||
#endif
|
||||
|
||||
/* Utility to save typing/errors, the argument must be a name */
|
||||
#define MEMZERO(var) ((void)memset(&var, 0, sizeof var))
|
||||
|
||||
/* Example of using row callbacks to make a simple progress meter */
|
||||
static int status_pass = 1;
|
||||
static int status_dots_requested = 0;
|
||||
@ -184,8 +149,13 @@ static int status_dots = 1;
|
||||
static void PNGCBAPI
|
||||
read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass)
|
||||
{
|
||||
if (png_ptr == NULL || row_number > PNG_UINT_31_MAX)
|
||||
return;
|
||||
/* The callback should always receive correct parameters. */
|
||||
if (png_ptr == NULL)
|
||||
png_error(png_ptr, "read_row_callback: bad png_ptr");
|
||||
if (row_number > PNG_UINT_31_MAX)
|
||||
png_error(png_ptr, "read_row_callback: bad row number");
|
||||
if (pass < 0 || pass > 7)
|
||||
png_error(png_ptr, "read_row_callback: bad pass");
|
||||
|
||||
if (status_pass != pass)
|
||||
{
|
||||
@ -199,7 +169,7 @@ read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass)
|
||||
if (status_dots == 0)
|
||||
{
|
||||
fprintf(stdout, "\n ");
|
||||
status_dots=30;
|
||||
status_dots = 30;
|
||||
}
|
||||
|
||||
fprintf(stdout, "r");
|
||||
@ -209,8 +179,13 @@ read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass)
|
||||
static void PNGCBAPI
|
||||
write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass)
|
||||
{
|
||||
if (png_ptr == NULL || row_number > PNG_UINT_31_MAX || pass > 7)
|
||||
return;
|
||||
/* The callback should always receive correct parameters. */
|
||||
if (png_ptr == NULL)
|
||||
png_error(png_ptr, "write_row_callback: bad png_ptr");
|
||||
if (row_number > PNG_UINT_31_MAX)
|
||||
png_error(png_ptr, "write_row_callback: bad row number");
|
||||
if (pass < 0 || pass > 7)
|
||||
png_error(png_ptr, "write_row_callback: bad pass");
|
||||
|
||||
fprintf(stdout, "w");
|
||||
}
|
||||
@ -223,9 +198,13 @@ write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass)
|
||||
static void PNGCBAPI
|
||||
read_user_callback(png_structp png_ptr, png_row_infop row_info, png_bytep data)
|
||||
{
|
||||
PNG_UNUSED(png_ptr)
|
||||
PNG_UNUSED(row_info)
|
||||
PNG_UNUSED(data)
|
||||
/* The callback should always receive correct parameters. */
|
||||
if (png_ptr == NULL)
|
||||
png_error(png_ptr, "read_user_callback: bad png_ptr");
|
||||
if (row_info == NULL)
|
||||
png_error(png_ptr, "read_user_callback: bad row info");
|
||||
if (data == NULL)
|
||||
png_error(png_ptr, "read_user_callback: bad data");
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -240,8 +219,14 @@ static void PNGCBAPI
|
||||
count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data)
|
||||
{
|
||||
png_bytep dp = data;
|
||||
|
||||
/* The callback should always receive correct parameters. */
|
||||
if (png_ptr == NULL)
|
||||
return;
|
||||
png_error(png_ptr, "count_zero_samples: bad png_ptr");
|
||||
if (row_info == NULL)
|
||||
png_error(png_ptr, "count_zero_samples: bad row info");
|
||||
if (data == NULL)
|
||||
png_error(png_ptr, "count_zero_samples: bad data");
|
||||
|
||||
/* Contents of row_info:
|
||||
* png_uint_32 width width of row
|
||||
@ -259,7 +244,7 @@ count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data)
|
||||
int pos = 0;
|
||||
png_uint_32 n, nstop;
|
||||
|
||||
for (n = 0, nstop=row_info->width; n<nstop; n++)
|
||||
for (n = 0, nstop = row_info->width; n < nstop; n++)
|
||||
{
|
||||
if (row_info->bit_depth == 1)
|
||||
{
|
||||
@ -305,7 +290,7 @@ count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data)
|
||||
{
|
||||
if ((*dp | *(dp+1)) == 0)
|
||||
zero_samples++;
|
||||
dp+=2;
|
||||
dp += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -317,7 +302,7 @@ count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data)
|
||||
if (row_info->color_type > 3)
|
||||
color_channels--;
|
||||
|
||||
for (n = 0, nstop=row_info->width; n<nstop; n++)
|
||||
for (n = 0, nstop = row_info->width; n < nstop; n++)
|
||||
{
|
||||
for (channel = 0; channel < color_channels; channel++)
|
||||
{
|
||||
@ -330,7 +315,7 @@ count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data)
|
||||
if ((*dp | *(dp+1)) == 0)
|
||||
zero_samples++;
|
||||
|
||||
dp+=2;
|
||||
dp += 2;
|
||||
}
|
||||
}
|
||||
if (row_info->color_type > 3)
|
||||
@ -356,9 +341,6 @@ count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data)
|
||||
|
||||
#ifdef PNG_IO_STATE_SUPPORTED
|
||||
void
|
||||
pngtest_check_io_state(png_structp png_ptr, size_t data_length,
|
||||
png_uint_32 io_op);
|
||||
void
|
||||
pngtest_check_io_state(png_structp png_ptr, size_t data_length,
|
||||
png_uint_32 io_op)
|
||||
{
|
||||
@ -372,7 +354,7 @@ pngtest_check_io_state(png_structp png_ptr, size_t data_length,
|
||||
/* Check if the buffer size specific to the current location
|
||||
* (file signature / header / data / crc) is as expected.
|
||||
*/
|
||||
switch (io_state & PNG_IO_MASK_LOC)
|
||||
switch ((io_state & PNG_IO_MASK_LOC) != 0)
|
||||
{
|
||||
case PNG_IO_SIGNATURE:
|
||||
if (data_length > 8)
|
||||
@ -402,19 +384,18 @@ pngtest_read_data(png_structp png_ptr, png_bytep data, size_t length)
|
||||
size_t check = 0;
|
||||
png_voidp io_ptr;
|
||||
|
||||
if (png_ptr == NULL)
|
||||
png_error(png_ptr, "pngtest_read_data: bad png_ptr");
|
||||
|
||||
/* fread() returns 0 on error, so it is OK to store this in a size_t
|
||||
* instead of an int, which is what fread() actually returns.
|
||||
*/
|
||||
io_ptr = png_get_io_ptr(png_ptr);
|
||||
if (io_ptr != NULL)
|
||||
{
|
||||
check = fread(data, 1, length, (png_FILE_p)io_ptr);
|
||||
}
|
||||
|
||||
if (check != length)
|
||||
{
|
||||
png_error(png_ptr, "Read Error");
|
||||
}
|
||||
|
||||
#ifdef PNG_IO_STATE_SUPPORTED
|
||||
pngtest_check_io_state(png_ptr, length, PNG_IO_READING);
|
||||
@ -425,8 +406,10 @@ pngtest_read_data(png_structp png_ptr, png_bytep data, size_t length)
|
||||
static void PNGCBAPI
|
||||
pngtest_flush(png_structp png_ptr)
|
||||
{
|
||||
if (png_ptr == NULL)
|
||||
png_error(png_ptr, "pngtest_flush: bad png_ptr");
|
||||
|
||||
/* Do nothing; fflush() is said to be just a waste of energy. */
|
||||
PNG_UNUSED(png_ptr) /* Stifle compiler warning */
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -440,12 +423,13 @@ pngtest_write_data(png_structp png_ptr, png_bytep data, size_t length)
|
||||
{
|
||||
size_t check;
|
||||
|
||||
if (png_ptr == NULL)
|
||||
png_error(png_ptr, "pngtest_write_data: bad png_ptr");
|
||||
|
||||
check = fwrite(data, 1, length, (png_FILE_p)png_get_io_ptr(png_ptr));
|
||||
|
||||
if (check != length)
|
||||
{
|
||||
png_error(png_ptr, "Write Error");
|
||||
}
|
||||
|
||||
#ifdef PNG_IO_STATE_SUPPORTED
|
||||
pngtest_check_io_state(png_ptr, length, PNG_IO_WRITING);
|
||||
@ -548,7 +532,7 @@ PNGCBAPI png_debug_malloc(png_structp png_ptr, png_alloc_size_t size)
|
||||
pinfo->size = size;
|
||||
current_allocation += size;
|
||||
total_allocation += size;
|
||||
num_allocations ++;
|
||||
++num_allocations;
|
||||
|
||||
if (current_allocation > maximum_allocation)
|
||||
maximum_allocation = current_allocation;
|
||||
@ -646,15 +630,14 @@ png_debug_free(png_structp png_ptr, png_voidp ptr)
|
||||
/* (sTER is a public chunk not yet known by libpng. vpAg is a private
|
||||
chunk used in ImageMagick to store "virtual page" size). */
|
||||
|
||||
static struct user_chunk_data
|
||||
typedef struct user_chunk_info_def
|
||||
{
|
||||
png_const_infop info_ptr;
|
||||
png_uint_32 vpAg_width, vpAg_height;
|
||||
png_byte vpAg_units;
|
||||
png_byte sTER_mode;
|
||||
int location[2];
|
||||
}
|
||||
user_chunk_data;
|
||||
} user_chunk_info;
|
||||
|
||||
/* Used for location and order; zero means nothing. */
|
||||
#define have_sTER 0x01
|
||||
@ -664,37 +647,38 @@ user_chunk_data;
|
||||
#define after_IDAT 0x40
|
||||
|
||||
static void
|
||||
init_callback_info(png_const_infop info_ptr)
|
||||
init_user_chunk_info(png_const_infop info_ptr, user_chunk_info *chunk_data)
|
||||
{
|
||||
MEMZERO(user_chunk_data);
|
||||
user_chunk_data.info_ptr = info_ptr;
|
||||
memset(chunk_data, 0, sizeof(*chunk_data));
|
||||
chunk_data->info_ptr = info_ptr;
|
||||
}
|
||||
|
||||
static int
|
||||
set_location(png_structp png_ptr, struct user_chunk_data *data, int what)
|
||||
set_chunk_location(png_structp png_ptr, user_chunk_info *chunk_data, int what)
|
||||
{
|
||||
int location;
|
||||
|
||||
if ((data->location[0] & what) != 0 || (data->location[1] & what) != 0)
|
||||
return 0; /* already have one of these */
|
||||
if ((chunk_data->location[0] & what) != 0 ||
|
||||
(chunk_data->location[1] & what) != 0)
|
||||
return 0; /* we already have one of these */
|
||||
|
||||
/* Find where we are (the code below zeroes info_ptr to indicate that the
|
||||
* chunks before the first IDAT have been read.)
|
||||
*/
|
||||
if (data->info_ptr == NULL) /* after IDAT */
|
||||
if (chunk_data->info_ptr == NULL) /* after IDAT */
|
||||
location = what | after_IDAT;
|
||||
|
||||
else if (png_get_valid(png_ptr, data->info_ptr, PNG_INFO_PLTE) != 0)
|
||||
else if (png_get_valid(png_ptr, chunk_data->info_ptr, PNG_INFO_PLTE) != 0)
|
||||
location = what | before_IDAT;
|
||||
|
||||
else
|
||||
location = what | before_PLTE;
|
||||
|
||||
if (data->location[0] == 0)
|
||||
data->location[0] = location;
|
||||
if (chunk_data->location[0] == 0)
|
||||
chunk_data->location[0] = location;
|
||||
|
||||
else
|
||||
data->location[1] = location;
|
||||
chunk_data->location[1] = location;
|
||||
|
||||
return 1; /* handled */
|
||||
}
|
||||
@ -702,11 +686,11 @@ set_location(png_structp png_ptr, struct user_chunk_data *data, int what)
|
||||
static int PNGCBAPI
|
||||
read_user_chunk_callback(png_struct *png_ptr, png_unknown_chunkp chunk)
|
||||
{
|
||||
struct user_chunk_data *my_user_chunk_data =
|
||||
(struct user_chunk_data*)png_get_user_chunk_ptr(png_ptr);
|
||||
user_chunk_info *my_user_chunk_data =
|
||||
(user_chunk_info*)png_get_user_chunk_ptr(png_ptr);
|
||||
|
||||
if (my_user_chunk_data == NULL)
|
||||
png_error(png_ptr, "lost user chunk pointer");
|
||||
png_error(png_ptr, "lost pointer to user chunk data");
|
||||
|
||||
/* Return one of the following:
|
||||
* return -n; chunk had an error
|
||||
@ -731,9 +715,9 @@ read_user_chunk_callback(png_struct *png_ptr, png_unknown_chunkp chunk)
|
||||
if (chunk->data[0] != 0 && chunk->data[0] != 1)
|
||||
return -1; /* Invalid mode */
|
||||
|
||||
if (set_location(png_ptr, my_user_chunk_data, have_sTER) != 0)
|
||||
if (set_chunk_location(png_ptr, my_user_chunk_data, have_sTER) != 0)
|
||||
{
|
||||
my_user_chunk_data->sTER_mode=chunk->data[0];
|
||||
my_user_chunk_data->sTER_mode = chunk->data[0];
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -750,7 +734,7 @@ read_user_chunk_callback(png_struct *png_ptr, png_unknown_chunkp chunk)
|
||||
if (chunk->size != 9)
|
||||
return -1; /* Error return */
|
||||
|
||||
if (set_location(png_ptr, my_user_chunk_data, have_vpAg) == 0)
|
||||
if (set_chunk_location(png_ptr, my_user_chunk_data, have_vpAg) == 0)
|
||||
return 0; /* duplicate vpAg */
|
||||
|
||||
my_user_chunk_data->vpAg_width = png_get_uint_31(png_ptr, chunk->data);
|
||||
@ -762,18 +746,18 @@ read_user_chunk_callback(png_struct *png_ptr, png_unknown_chunkp chunk)
|
||||
|
||||
#ifdef PNG_WRITE_SUPPORTED
|
||||
static void
|
||||
write_sTER_chunk(png_structp write_ptr)
|
||||
write_sTER_chunk(png_structp write_ptr, user_chunk_info *data)
|
||||
{
|
||||
png_byte sTER[5] = {115, 84, 69, 82, '\0'};
|
||||
|
||||
if (verbose != 0)
|
||||
fprintf(STDERR, "\n stereo mode = %d\n", user_chunk_data.sTER_mode);
|
||||
fprintf(STDERR, "\n stereo mode = %d\n", data->sTER_mode);
|
||||
|
||||
png_write_chunk(write_ptr, sTER, &user_chunk_data.sTER_mode, 1);
|
||||
png_write_chunk(write_ptr, sTER, &data->sTER_mode, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
write_vpAg_chunk(png_structp write_ptr)
|
||||
write_vpAg_chunk(png_structp write_ptr, user_chunk_info *data)
|
||||
{
|
||||
png_byte vpAg[5] = {118, 112, 65, 103, '\0'};
|
||||
|
||||
@ -781,18 +765,18 @@ write_vpAg_chunk(png_structp write_ptr)
|
||||
|
||||
if (verbose != 0)
|
||||
fprintf(STDERR, " vpAg = %lu x %lu, units = %d\n",
|
||||
(unsigned long)user_chunk_data.vpAg_width,
|
||||
(unsigned long)user_chunk_data.vpAg_height,
|
||||
user_chunk_data.vpAg_units);
|
||||
(unsigned long)data->vpAg_width,
|
||||
(unsigned long)data->vpAg_height,
|
||||
data->vpAg_units);
|
||||
|
||||
png_save_uint_32(vpag_chunk_data, user_chunk_data.vpAg_width);
|
||||
png_save_uint_32(vpag_chunk_data + 4, user_chunk_data.vpAg_height);
|
||||
vpag_chunk_data[8] = user_chunk_data.vpAg_units;
|
||||
png_save_uint_32(vpag_chunk_data, data->vpAg_width);
|
||||
png_save_uint_32(vpag_chunk_data + 4, data->vpAg_height);
|
||||
vpag_chunk_data[8] = data->vpAg_units;
|
||||
png_write_chunk(write_ptr, vpAg, vpag_chunk_data, 9);
|
||||
}
|
||||
|
||||
static void
|
||||
write_chunks(png_structp write_ptr, int location)
|
||||
write_chunks(png_structp write_ptr, user_chunk_info *data, int location)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -802,13 +786,13 @@ write_chunks(png_structp write_ptr, int location)
|
||||
* vpAg chunks, resulting in an error later. This is not worth worrying
|
||||
* about - the chunks should not be duplicated!
|
||||
*/
|
||||
for (i=0; i<2; ++i)
|
||||
for (i = 0; i < 2; ++i)
|
||||
{
|
||||
if (user_chunk_data.location[i] == (location | have_sTER))
|
||||
write_sTER_chunk(write_ptr);
|
||||
if (data->location[i] == (location | have_sTER))
|
||||
write_sTER_chunk(write_ptr, data);
|
||||
|
||||
else if (user_chunk_data.location[i] == (location | have_vpAg))
|
||||
write_vpAg_chunk(write_ptr);
|
||||
else if (data->location[i] == (location | have_vpAg))
|
||||
write_vpAg_chunk(write_ptr, data);
|
||||
}
|
||||
}
|
||||
#endif /* WRITE */
|
||||
@ -883,9 +867,9 @@ test_one_file(const char *inname, const char *outname)
|
||||
png_bytep row_buf;
|
||||
png_uint_32 y;
|
||||
png_uint_32 width, height;
|
||||
volatile int num_passes;
|
||||
int pass;
|
||||
int bit_depth, color_type;
|
||||
user_chunk_info my_user_chunk_data;
|
||||
int pass, num_passes;
|
||||
|
||||
row_buf = NULL;
|
||||
error_parameters.file_name = inname;
|
||||
@ -899,7 +883,7 @@ test_one_file(const char *inname, const char *outname)
|
||||
if ((fpout = fopen(outname, "wb")) == NULL)
|
||||
{
|
||||
fprintf(STDERR, "Could not open output file %s\n", outname);
|
||||
FCLOSE(fpin);
|
||||
fclose(fpin);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -936,8 +920,8 @@ test_one_file(const char *inname, const char *outname)
|
||||
#endif
|
||||
|
||||
#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
|
||||
init_callback_info(read_info_ptr);
|
||||
png_set_read_user_chunk_fn(read_ptr, &user_chunk_data,
|
||||
init_user_chunk_info(read_info_ptr, &my_user_chunk_data);
|
||||
png_set_read_user_chunk_fn(read_ptr, &my_user_chunk_data,
|
||||
read_user_chunk_callback);
|
||||
#endif
|
||||
|
||||
@ -957,8 +941,8 @@ test_one_file(const char *inname, const char *outname)
|
||||
png_destroy_info_struct(write_ptr, &write_end_info_ptr);
|
||||
png_destroy_write_struct(&write_ptr, &write_info_ptr);
|
||||
#endif
|
||||
FCLOSE(fpin);
|
||||
FCLOSE(fpout);
|
||||
fclose(fpin);
|
||||
fclose(fpout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -977,8 +961,8 @@ test_one_file(const char *inname, const char *outname)
|
||||
fprintf(STDERR, " destroying write structs\n");
|
||||
png_destroy_info_struct(write_ptr, &write_end_info_ptr);
|
||||
png_destroy_write_struct(&write_ptr, &write_info_ptr);
|
||||
FCLOSE(fpin);
|
||||
FCLOSE(fpout);
|
||||
fclose(fpin);
|
||||
fclose(fpout);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
@ -1064,13 +1048,13 @@ test_one_file(const char *inname, const char *outname)
|
||||
#endif
|
||||
|
||||
#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
|
||||
/* Preserve all the unknown chunks, if possible. If this is disabled then,
|
||||
/* Preserve all the unknown chunks, if possible. If this is disabled, then
|
||||
* even if the png_{get,set}_unknown_chunks stuff is enabled, we can't use
|
||||
* libpng to *save* the unknown chunks on read (because we can't switch the
|
||||
* save option on!)
|
||||
*
|
||||
* Notice that if SET_UNKNOWN_CHUNKS is *not* supported read will discard all
|
||||
* unknown chunks and write will write them all.
|
||||
* Notice that if SET_UNKNOWN_CHUNKS is *not* supported, the reader will
|
||||
* discard all unknown chunks, and the writer will write them all.
|
||||
*/
|
||||
#ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
|
||||
png_set_keep_unknown_chunks(read_ptr, PNG_HANDLE_CHUNK_ALWAYS,
|
||||
@ -1091,7 +1075,7 @@ test_one_file(const char *inname, const char *outname)
|
||||
* remove the info_ptr (which is only used to determine position relative to
|
||||
* PLTE) here to indicate that we are after the IDAT.
|
||||
*/
|
||||
user_chunk_data.info_ptr = NULL;
|
||||
my_user_chunk_data.info_ptr = NULL;
|
||||
#endif
|
||||
|
||||
pngtest_debug("Transferring info struct");
|
||||
@ -1207,14 +1191,12 @@ test_one_file(const char *inname, const char *outname)
|
||||
png_color_16p background;
|
||||
|
||||
if (png_get_bKGD(read_ptr, read_info_ptr, &background) != 0)
|
||||
{
|
||||
png_set_bKGD(write_ptr, write_info_ptr, background);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef PNG_READ_eXIf_SUPPORTED
|
||||
{
|
||||
png_bytep exif=NULL;
|
||||
png_bytep exif = NULL;
|
||||
png_uint_32 exif_length;
|
||||
|
||||
if (png_get_eXIf_1(read_ptr, read_info_ptr, &exif_length, &exif) != 0)
|
||||
@ -1243,9 +1225,7 @@ test_one_file(const char *inname, const char *outname)
|
||||
|
||||
if (png_get_oFFs(read_ptr, read_info_ptr, &offset_x, &offset_y,
|
||||
&unit_type) != 0)
|
||||
{
|
||||
png_set_oFFs(write_ptr, write_info_ptr, offset_x, offset_y, unit_type);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef PNG_pCAL_SUPPORTED
|
||||
@ -1257,10 +1237,8 @@ test_one_file(const char *inname, const char *outname)
|
||||
|
||||
if (png_get_pCAL(read_ptr, read_info_ptr, &purpose, &X0, &X1, &type,
|
||||
&nparams, &units, ¶ms) != 0)
|
||||
{
|
||||
png_set_pCAL(write_ptr, write_info_ptr, purpose, X0, X1, type,
|
||||
nparams, units, params);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef PNG_pHYs_SUPPORTED
|
||||
@ -1290,9 +1268,7 @@ test_one_file(const char *inname, const char *outname)
|
||||
|
||||
if (png_get_sCAL(read_ptr, read_info_ptr, &unit, &scal_width,
|
||||
&scal_height) != 0)
|
||||
{
|
||||
png_set_sCAL(write_ptr, write_info_ptr, unit, scal_width, scal_height);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#ifdef PNG_FIXED_POINT_SUPPORTED
|
||||
@ -1315,11 +1291,9 @@ test_one_file(const char *inname, const char *outname)
|
||||
{
|
||||
png_sPLT_tp entries;
|
||||
|
||||
int num_entries = (int) png_get_sPLT(read_ptr, read_info_ptr, &entries);
|
||||
if (num_entries)
|
||||
{
|
||||
int num_entries = png_get_sPLT(read_ptr, read_info_ptr, &entries);
|
||||
if (num_entries != 0)
|
||||
png_set_sPLT(write_ptr, write_info_ptr, entries, num_entries);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1339,7 +1313,7 @@ test_one_file(const char *inname, const char *outname)
|
||||
int i;
|
||||
|
||||
fprintf(STDERR,"\n");
|
||||
for (i=0; i<num_text; i++)
|
||||
for (i = 0; i < num_text; i++)
|
||||
{
|
||||
fprintf(STDERR," Text compression[%d]=%d\n",
|
||||
i, text_ptr[i].compression);
|
||||
@ -1401,22 +1375,8 @@ test_one_file(const char *inname, const char *outname)
|
||||
&unknowns);
|
||||
|
||||
if (num_unknowns != 0)
|
||||
{
|
||||
png_set_unknown_chunks(write_ptr, write_info_ptr, unknowns,
|
||||
num_unknowns);
|
||||
#if PNG_LIBPNG_VER < 10600
|
||||
/* Copy the locations from the read_info_ptr. The automatically
|
||||
* generated locations in write_end_info_ptr are wrong prior to 1.6.0
|
||||
* because they are reset from the write pointer (removed in 1.6.0).
|
||||
*/
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < num_unknowns; i++)
|
||||
png_set_unknown_chunk_location(write_ptr, write_info_ptr, i,
|
||||
unknowns[i].location);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1428,15 +1388,15 @@ test_one_file(const char *inname, const char *outname)
|
||||
*/
|
||||
png_write_info_before_PLTE(write_ptr, write_info_ptr);
|
||||
|
||||
write_chunks(write_ptr, before_PLTE); /* before PLTE */
|
||||
write_chunks(write_ptr, &my_user_chunk_data, before_PLTE); /* before PLTE */
|
||||
|
||||
png_write_info(write_ptr, write_info_ptr);
|
||||
|
||||
write_chunks(write_ptr, before_IDAT); /* after PLTE */
|
||||
write_chunks(write_ptr, &my_user_chunk_data, before_IDAT); /* after PLTE */
|
||||
|
||||
png_write_info(write_ptr, write_end_info_ptr);
|
||||
|
||||
write_chunks(write_ptr, after_IDAT); /* after IDAT */
|
||||
write_chunks(write_ptr, &my_user_chunk_data, after_IDAT); /* after IDAT */
|
||||
|
||||
#ifdef PNG_COMPRESSION_COMPAT
|
||||
/* Test the 'compatibility' setting here, if it is available. */
|
||||
@ -1559,7 +1519,7 @@ test_one_file(const char *inname, const char *outname)
|
||||
int i;
|
||||
|
||||
fprintf(STDERR,"\n");
|
||||
for (i=0; i<num_text; i++)
|
||||
for (i = 0; i < num_text; i++)
|
||||
{
|
||||
fprintf(STDERR," Text compression[%d]=%d\n",
|
||||
i, text_ptr[i].compression);
|
||||
@ -1572,7 +1532,7 @@ test_one_file(const char *inname, const char *outname)
|
||||
#endif
|
||||
#ifdef PNG_READ_eXIf_SUPPORTED
|
||||
{
|
||||
png_bytep exif=NULL;
|
||||
png_bytep exif = NULL;
|
||||
png_uint_32 exif_length;
|
||||
|
||||
if (png_get_eXIf_1(read_ptr, end_info_ptr, &exif_length, &exif) != 0)
|
||||
@ -1615,22 +1575,8 @@ test_one_file(const char *inname, const char *outname)
|
||||
&unknowns);
|
||||
|
||||
if (num_unknowns != 0)
|
||||
{
|
||||
png_set_unknown_chunks(write_ptr, write_end_info_ptr, unknowns,
|
||||
num_unknowns);
|
||||
#if PNG_LIBPNG_VER < 10600
|
||||
/* Copy the locations from the read_info_ptr. The automatically
|
||||
* generated locations in write_end_info_ptr are wrong prior to 1.6.0
|
||||
* because they are reset from the write pointer (removed in 1.6.0).
|
||||
*/
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < num_unknowns; i++)
|
||||
png_set_unknown_chunk_location(write_ptr, write_end_info_ptr, i,
|
||||
unknowns[i].location);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1649,7 +1595,7 @@ test_one_file(const char *inname, const char *outname)
|
||||
* There seems to be no way round this, however vpAg/sTER are not expected
|
||||
* after IDAT.
|
||||
*/
|
||||
write_chunks(write_ptr, after_IDAT);
|
||||
write_chunks(write_ptr, &my_user_chunk_data, after_IDAT);
|
||||
|
||||
png_write_end(write_ptr, write_end_info_ptr);
|
||||
#endif
|
||||
@ -1681,8 +1627,8 @@ test_one_file(const char *inname, const char *outname)
|
||||
#endif
|
||||
pngtest_debug("Destruction complete.");
|
||||
|
||||
FCLOSE(fpin);
|
||||
FCLOSE(fpout);
|
||||
fclose(fpin);
|
||||
fclose(fpout);
|
||||
|
||||
/* Summarize any warnings or errors and in 'strict' mode fail the test.
|
||||
* Unsupported chunks can result in warnings, in that case ignore the strict
|
||||
@ -1728,7 +1674,7 @@ test_one_file(const char *inname, const char *outname)
|
||||
if ((fpout = fopen(outname, "rb")) == NULL)
|
||||
{
|
||||
fprintf(STDERR, "Could not find file %s\n", outname);
|
||||
FCLOSE(fpin);
|
||||
fclose(fpin);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1764,8 +1710,8 @@ test_one_file(const char *inname, const char *outname)
|
||||
wrote_question = 1;
|
||||
}
|
||||
|
||||
FCLOSE(fpin);
|
||||
FCLOSE(fpout);
|
||||
fclose(fpin);
|
||||
fclose(fpout);
|
||||
|
||||
if (strict != 0 && unsupported_chunks == 0)
|
||||
return 1;
|
||||
@ -1796,8 +1742,8 @@ test_one_file(const char *inname, const char *outname)
|
||||
wrote_question = 1;
|
||||
}
|
||||
|
||||
FCLOSE(fpin);
|
||||
FCLOSE(fpout);
|
||||
fclose(fpin);
|
||||
fclose(fpout);
|
||||
|
||||
/* NOTE: the unsupported_chunks escape is permitted here because
|
||||
* unsupported text chunk compression will result in the compression
|
||||
@ -1814,8 +1760,8 @@ test_one_file(const char *inname, const char *outname)
|
||||
}
|
||||
#endif /* WRITE && WRITE_FILTER */
|
||||
|
||||
FCLOSE(fpin);
|
||||
FCLOSE(fpout);
|
||||
fclose(fpin);
|
||||
fclose(fpout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1901,7 +1847,7 @@ main(int argc, char *argv[])
|
||||
inname = argv[2];
|
||||
strict++;
|
||||
relaxed = 0;
|
||||
multiple=1;
|
||||
multiple = 1;
|
||||
}
|
||||
|
||||
else if (strcmp(argv[1], "--relaxed") == 0)
|
||||
@ -1911,7 +1857,7 @@ main(int argc, char *argv[])
|
||||
inname = argv[2];
|
||||
strict = 0;
|
||||
relaxed++;
|
||||
multiple=1;
|
||||
multiple = 1;
|
||||
}
|
||||
else if (strcmp(argv[1], "--xfail") == 0)
|
||||
{
|
||||
@ -1921,7 +1867,7 @@ main(int argc, char *argv[])
|
||||
strict = 0;
|
||||
xfail++;
|
||||
relaxed++;
|
||||
multiple=1;
|
||||
multiple = 1;
|
||||
}
|
||||
|
||||
else
|
||||
@ -1953,7 +1899,7 @@ main(int argc, char *argv[])
|
||||
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
|
||||
int allocation_now = current_allocation;
|
||||
#endif
|
||||
for (i=2; i<argc; ++i)
|
||||
for (i = 2; i < argc; ++i)
|
||||
{
|
||||
int kerror;
|
||||
fprintf(STDERR, "\n Testing %s:", argv[i]);
|
||||
@ -2024,7 +1970,7 @@ main(int argc, char *argv[])
|
||||
else
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i<3; ++i)
|
||||
for (i = 0; i < 3; ++i)
|
||||
{
|
||||
int kerror;
|
||||
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
|
||||
@ -2152,7 +2098,7 @@ main(int argc, char *argv[])
|
||||
(unsigned long) png_get_chunk_malloc_max(dummy_ptr));
|
||||
png_destroy_read_struct(&dummy_ptr, NULL, NULL);
|
||||
|
||||
return (int)(ierror != 0);
|
||||
return (ierror != 0);
|
||||
}
|
||||
#else
|
||||
int
|
||||
|
Loading…
x
Reference in New Issue
Block a user