Imported from libpng-0.97a.tar

This commit is contained in:
Glenn Randers-Pehrson 1998-01-03 22:40:55 -06:00
parent b6ce43d6ff
commit 70e3f543f1
14 changed files with 460 additions and 135 deletions

3
TODO
View File

@ -3,8 +3,9 @@ pngtodo.txt - list of things to do for libpng
add "grayscale->palette" transformation and "palette->grayscale" detection
improved dithering
multi-lingual error and warning message support
sPLT chunk handling
cHRM transformation
sRGB chunk handling
complete sRGB transformation (presently it simply uses gamma=0.5)
man pages for function calls
high-level API for reading images
final bug fixes

12
png.h
View File

@ -997,8 +997,10 @@ extern PNG_EXPORT(void,png_set_compression_method) PNGARG((png_structp png_ptr,
* more information.
*/
#if !defined(PNG_NO_STDIO)
/* Initialize the input/output for the PNG file to the default functions. */
extern PNG_EXPORT(void,png_init_io) PNGARG((png_structp png_ptr, FILE *fp));
#endif
/* Replace the (error and abort), and warning functions with user
* supplied functions. If no messages are to be printed you must still
@ -1066,10 +1068,18 @@ extern void *far_to_near PNGARG((png_structp png_ptr,png_voidp ptr,int check));
extern PNG_EXPORT(void,png_error) PNGARG((png_structp png_ptr,
png_const_charp error));
/* The same, but the chunk name is prepended to the error string. */
extern PNG_EXPORT(void,png_chunk_error) PNGARG((png_structp png_ptr,
png_const_charp error));
/* Non-fatal error in libpng. Can continue, but may have a problem. */
extern PNG_EXPORT(void,png_warning) PNGARG((png_structp png_ptr,
png_const_charp message));
/* Non-fatal error in libpng, chunk name is prepended to message. */
extern PNG_EXPORT(void,png_chunk_warning) PNGARG((png_structp png_ptr,
png_const_charp message));
/* The png_set_<chunk> functions are for storing values in the png_info_struct.
* Similarly, the png_get_<chunk> calls are used to read values from the
* png_info_struct, either storing the parameters in the passed variables, or
@ -1202,7 +1212,7 @@ extern PNG_EXPORT(void,png_set_sBIT) PNGARG((png_structp png_ptr,
#if defined(PNG_READ_sRGB_SUPPORTED)
extern PNG_EXPORT(png_uint_32,png_get_sRGB) PNGARG((png_structp png_ptr,
png_infop info_ptr, png_byte *srgb_intent));
png_infop info_ptr, png_bytep srgb_intent));
#endif /* PNG_READ_sRGB_SUPPORTED */
#if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)

View File

@ -21,7 +21,7 @@
* an IDAT chunk. Make this whatever size you feel is best for your
* machine. One of these will be allocated per png_struct. When this
* is full, it writes the data to the disk, and does some other
* calculations. Making this an extreamly small size will slow
* calculations. Making this an extremely small size will slow
* the library down, but you may want to experiment to determine
* where it becomes significant, if you are concerned with memory
* usage. Note that zlib allocates at least 32Kb also. For readers,
@ -30,7 +30,9 @@
* it should not make much difference how big this is.
*/
#ifndef PNG_ZBUF_SIZE
#define PNG_ZBUF_SIZE 8192
#endif
/* If you are running on a machine where you cannot allocate more
* than 64K of memory at once, uncomment this. While libpng will not
@ -54,8 +56,9 @@
/* We still need stdio.h for FILE even when PNG_NO_STDIO is defined.
*/
#ifndef PNG_NO_STDIO
#include <stdio.h>
#endif
/* This macro protects us against machines that don't have function
* prototypes (ie K&R style headers). If your compiler does not handle
@ -170,9 +173,15 @@ __dont__ include it again
* a largish chunk of memory (32K), those who are not as concerned
* with dithering quality can decrease some or all of these.
*/
#ifndef PNG_DITHER_RED_BITS
#define PNG_DITHER_RED_BITS 5
#endif
#ifndef PNG_DITHER_GREEN_BITS
#define PNG_DITHER_GREEN_BITS 5
#endif
#ifndef PNG_DITHER_BLUE_BITS
#define PNG_DITHER_BLUE_BITS 5
#endif
/* This controls how fine the gamma correction becomes when you
* are only interested in 8 bits anyway. Increasing this value
@ -235,7 +244,6 @@ __dont__ include it again
#ifdef PNG_READ_FULLY_SUPPORTED
#define PNG_PROGRESSIVE_READ_SUPPORTED
#define PNG_READ_OPT_PLTE_SUPPORTED
#define PNG_READ_INTERLACING_SUPPORTED
#define PNG_READ_EXPAND_SUPPORTED
#define PNG_READ_SHIFT_SUPPORTED
#define PNG_READ_PACK_SUPPORTED
@ -252,6 +260,7 @@ __dont__ include it again
#define PNG_READ_SWAP_ALPHA_SUPPORTED
#define PNG_READ_STRIP_ALPHA_SUPPORTED
#endif /* PNG_READ_FULLY_SUPPORTED */
#define PNG_READ_INTERLACING_SUPPORTED
#ifdef PNG_WRITE_FULLY_SUPPORTED
#define PNG_WRITE_INTERLACING_SUPPORTED
@ -267,7 +276,9 @@ __dont__ include it again
#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
#endif /*PNG_WRITE_FULLY_SUPPORTED */
#if !defined(PNG_NO_STDIO)
#define PNG_TIME_RFC1152_SUPPORTED
#endif
/* These are currently experimental features */
#undef PNG_READ_16_TO_8_ACCURATE_SHIFT_SUPPORTED /* very little testing */

View File

@ -51,6 +51,60 @@ png_warning(png_structp png_ptr, png_const_charp message)
png_default_warning(png_ptr, message);
}
/* These utilities are used internally to build an error message which relates
* to the current chunk. The chunk name comes from png_ptr->chunk_name,
* this is used to prefix the message. The message is limited in length
* to 63 bytes, the name characters are output as hex digits wrapped in []
* if the character is invalid.
*/
#define isnonalpha(c) ((c) < 41 || (c) > 122 || ((c) > 90 && (c) < 97))
static const char png_digit[16] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
static void
png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp message)
{
int iout = 0, iin = 0;
while (iin < 4) {
int c = png_ptr->chunk_name[iin++];
if (isnonalpha(c)) {
buffer[iout++] = '[';
buffer[iout++] = png_digit[(c & 0xf0) >> 4];
buffer[iout++] = png_digit[c & 0xf];
buffer[iout++] = ']';
} else {
buffer[iout++] = c;
}
}
if (message == NULL)
buffer[iout++] = 0;
else {
buffer[iout++] = ':';
buffer[iout++] = ' ';
strncpy(buffer+iout, message, 64);
buffer[iout+63] = 0;
}
}
void
png_chunk_error(png_structp png_ptr, png_const_charp message)
{
char msg[16+64];
png_format_buffer(png_ptr, msg, message);
png_error(png_ptr, msg);
}
void
png_chunk_warning(png_structp png_ptr, png_const_charp message)
{
char msg[16+64];
png_format_buffer(png_ptr, msg, message);
png_warning(png_ptr, msg);
}
/* This is the default error handling function. Note that replacements for
* this function MUST NOT RETURN, or the program will likely crash. This
* function is used by default, or if the program supplies NULL for the

View File

@ -111,13 +111,14 @@ png_get_gAMA(png_structp png_ptr, png_infop info_ptr, double *file_gamma)
#if defined(PNG_READ_sRGB_SUPPORTED)
png_uint_32
png_get_sRGB(png_structp png_ptr, png_infop info_ptr, png_byte *file_srgb_intent)
png_get_sRGB(png_structp png_ptr, png_infop info_ptr, png_bytep
file_srgb_intent)
{
if (info_ptr != NULL && info_ptr->valid & PNG_INFO_sRGB &&
*file_srgb_intent != NULL)
file_srgb_intent != NULL)
{
png_debug1(1, "in %s retrieval function\n", "sRGB");
*file_srgb_intent = (png_byte)info_ptr->srgb_intent;
*file_srgb_intent = info_ptr->srgb_intent;
return (PNG_INFO_sRGB);
}
return (0);

View File

@ -1056,10 +1056,7 @@ png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 len
if (!(png_ptr->chunk_name[0] & 0x20))
{
char msg[40];
sprintf(msg, "Unknown critical chunk %s", png_ptr->chunk_name);
png_error(png_ptr, msg);
png_chunk_error(png_ptr, "unknown critical chunk");
}
png_push_crc_skip(png_ptr, length);

View File

@ -33,6 +33,7 @@ png_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
png_error(png_ptr, "Call to NULL read function");
}
#if !defined(PNG_NO_STDIO)
/* This is the function which does the actual reading of data. If you are
not reading from a standard C stream, you should create a replacement
read_data function and use it at run time with png_set_read_fn(), rather
@ -103,6 +104,7 @@ png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
}
}
#endif
#endif
/* This function allows the application to supply a new input function
for libpng if standard C streams aren't being used.
@ -123,10 +125,14 @@ png_set_read_fn(png_structp png_ptr, png_voidp io_ptr,
{
png_ptr->io_ptr = io_ptr;
#if !defined(PNG_NO_STDIO)
if (read_data_fn != NULL)
png_ptr->read_data_fn = read_data_fn;
else
png_ptr->read_data_fn = png_default_read_data;
#else
png_ptr->read_data_fn = read_data_fn;
#endif
/* It is an error to write to a read device */
png_ptr->write_data_fn = NULL;

View File

@ -986,11 +986,15 @@ png_do_read_transformations(png_structp png_ptr)
#if !defined(PNG_USELESS_TESTS_SUPPORTED)
if (png_ptr->row_buf == NULL)
{
#if !defined(PNG_NO_STDIO)
char msg[50];
sprintf(msg, "NULL row buffer for row %ld, pass %d", png_ptr->row_number,
png_ptr->pass);
png_error(png_ptr, msg);
#else
png_error(png_ptr, "NULL row buffer");
#endif
}
#endif

View File

@ -88,20 +88,16 @@ png_crc_finish(png_structp png_ptr, png_uint_32 skip)
if (png_crc_error(png_ptr))
{
char msg[80];
sprintf(msg,"CRC error in %s", png_ptr->chunk_name);
if ((png_ptr->chunk_name[0] & 0x20 && /* Ancillary */
!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
(!(png_ptr->chunk_name[0] & 0x20) && /* Critical */
png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE))
{
png_warning(png_ptr, msg);
png_chunk_warning(png_ptr, "CRC error");
}
else
{
png_error(png_ptr, msg);
png_chunk_error(png_ptr, "CRC error");
}
return 1;
}
@ -307,10 +303,6 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
}
else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */
{
char msg[80];
sprintf(msg,"CRC error in %s", png_ptr->chunk_name);
/* If we don't want to use the data from an ancillary chunk,
we have two options: an error abort, or a warning and we
ignore the data in this chunk (which should be OK, since
@ -319,11 +311,11 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
{
if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
{
png_error(png_ptr, msg);
png_chunk_error(png_ptr, "CRC error");
}
else
{
png_warning(png_ptr, msg);
png_chunk_warning(png_ptr, "CRC error");
png_ptr->flags &= ~PNG_FLAG_FREE_PALETTE;
png_free(png_ptr, palette);
return;
@ -332,7 +324,7 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
/* Otherwise, we (optionally) emit a warning and use the chunk. */
else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
{
png_warning(png_ptr, msg);
png_chunk_warning(png_ptr, "CRC error");
}
}
@ -406,7 +398,7 @@ png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#if defined(PNG_READ_sRGB_SUPPORTED)
if ((png_ptr->mode & PNG_HAVE_sRGB))
if(igamma != 50000)
if(igamma != (png_uint_32)50000L)
{
png_warning(png_ptr,
"Ignoring incorrect gAMA value when sRGB is also present");
@ -416,7 +408,7 @@ png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#if defined(PNG_READ_sRGB_SUPPORTED)
if (png_ptr->mode & PNG_HAVE_sRGB)
if(igamma != 50000)
if(igamma != (png_uint_32)50000L)
{
png_warning(png_ptr,
"Ignoring incorrect gAMA value when sRGB is also present");
@ -585,8 +577,8 @@ png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
val = png_get_uint_32(buf);
blue_y = (float)val / (float)100000.0;
if (blue_x < 0 || blue_x > 0.8 || blue_y < 0 || blue_y > 0.8 ||
blue_x + blue_y > 1.0)
if (blue_x < (float)0 || blue_x > (float)0.8 || blue_y < (float)0 ||
blue_y > (float)0.8 || blue_x + blue_y > (float)1.0)
{
png_warning(png_ptr, "Invalid cHRM blue point");
png_crc_finish(png_ptr, 0);
@ -597,12 +589,20 @@ png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
return;
#if defined(PNG_READ_sRGB_SUPPORTED)
if ((png_ptr->mode & PNG_HAVE_sRGB))
if(white_x != .3127 || white_y != .329 || red_x != .64 || red_y != .33 ||
green_x != .3 || green_y != .6 || blue_x != .15 || blue_y != .06)
if (png_ptr->mode & PNG_HAVE_sRGB)
{
png_warning(png_ptr,
"Ignoring incorrect cHRM value when sRGB is also present");
if (fabs(white_x - (float).3127) > (float).001 ||
fabs(white_y - (float).3290) > (float).001 ||
fabs( red_x - (float).6400) > (float).001 ||
fabs( red_y - (float).3300) > (float).001 ||
fabs(green_x - (float).3000) > (float).001 ||
fabs(green_y - (float).6000) > (float).001 ||
fabs( blue_x - (float).1500) > (float).001 ||
fabs( blue_y - (float).6000) > (float).001)
{
png_warning(png_ptr,
"Ignoring incorrect cHRM value when sRGB is also present");
}
return;
}
#endif /* PNG_READ_sRGB_SUPPORTED */
@ -664,17 +664,17 @@ png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
already defined gamma and chrm with values that are
inconsistent with sRGB -- for now, just ignore them */
file_gamma = 0.45;
file_gamma = (float)45000./(float)100000.;
png_set_gAMA(png_ptr, info_ptr, file_gamma);
white_x = 0.3127;
white_y = 0.3290;
red_x = 0.6400;
red_y = 0.3300;
green_x = 0.3000;
green_y = 0.6000;
blue_x = 0.1500;
blue_y = 0.0600;
white_x = (float)31270./(float)100000.;
white_y = (float)32900./(float)100000.;
red_x = (float)64000./(float)100000.;
red_y = (float)33000./(float)100000.;
green_x = (float)30000./(float)100000.;
green_y = (float)60000./(float)100000.;
blue_x = (float)15000./(float)100000.;
blue_y = (float) 6000./(float)100000.;
png_set_cHRM(png_ptr, info_ptr,
white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
@ -1342,10 +1342,14 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
else /* if (comp_type >= PNG_TEXT_COMPRESSION_LAST) */
{
png_size_t text_size;
#if !defined(PNG_NO_STDIO)
char umsg[50];
sprintf(umsg, "Unknown zTXt compression type %d", comp_type);
png_warning(png_ptr, umsg);
#else
png_warning(png_ptr, "Unknown zTXt compression type");
#endif
/* Copy what we can of the error message into the text chunk */
text_size = (png_size_t)length - (text - key) - 1;
@ -1380,10 +1384,7 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
if (!(png_ptr->chunk_name[0] & 0x20))
{
char msg[40];
sprintf(msg, "Unknown critical chunk %s", png_ptr->chunk_name);
png_error(png_ptr, msg);
png_chunk_error(png_ptr, "unknown critical chunk");
}
if (png_ptr->mode & PNG_HAVE_IDAT)
@ -1407,11 +1408,7 @@ png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
{
char msg[45];
sprintf(msg, "Invalid chunk type 0x%02X 0x%02X 0x%02X 0x%02X",
chunk_name[0], chunk_name[1], chunk_name[2], chunk_name[3]);
png_error(png_ptr, msg);
png_chunk_error(png_ptr, "invalid chunk type");
}
}

View File

@ -238,19 +238,19 @@ png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr,
png_set_sRGB(png_ptr, info_ptr, intent);
#if defined(PNG_READ_gAMA_SUPPORTED) || defined(PNG_WRITE_gAMA_SUPPORTED)
file_gamma = 0.45;
file_gamma = (float).45;
png_set_gAMA(png_ptr, info_ptr, file_gamma);
#endif
#if defined(PNG_READ_cHRM_SUPPORTED) || defined(PNG_WRITE_cHRM_SUPPORTED)
white_x = 0.3127;
white_y = 0.3290;
red_x = 0.6400;
red_y = 0.3300;
green_x = 0.3000;
green_y = 0.6000;
blue_x = 0.1500;
blue_y = 0.0600;
white_x = (float).3127;
white_y = (float).3290;
red_x = (float).64;
red_y = (float).33;
green_x = (float).30;
green_y = (float).60;
blue_x = (float).15;
blue_y = (float).06;
png_set_cHRM(png_ptr, info_ptr,
white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);

298
pngtest.c
View File

@ -44,19 +44,190 @@
/* #define STDERR stderr */
#define STDERR stdout /* for DOS */
/* input and output filenames */
#ifdef RISCOS
PNG_CONST char *inname = "pngtest_png";
PNG_CONST char *outname = "pngout_png";
/* START of code to validate stdio-free compilation */
/* These copies of the default read/write functions come from pngrio.c and */
/* pngwio.c. They allow "don't include stdio" testing of the library. */
#if defined(PNG_NO_STDIO)
/* This is the function which does the actual reading of data. If you are
not reading from a standard C stream, you should create a replacement
read_data function and use it at run time with png_set_read_fn(), rather
than changing the library. */
#ifndef USE_FAR_KEYWORD
static void
png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
{
png_size_t check;
/* fread() returns 0 on error, so it is OK to store this in a png_size_t
* instead of an int, which is what fread() actually returns.
*/
check = (png_size_t)fread(data, (png_size_t)1, length,
(FILE *)png_ptr->io_ptr);
if (check != length)
{
png_error(png_ptr, "Read Error");
}
}
#else
PNG_CONST char *inname = "pngtest.png";
PNG_CONST char *outname = "pngout.png";
/* this is the model-independent version. Since the standard I/O library
can't handle far buffers in the medium and small models, we have to copy
the data.
*/
#define NEAR_BUF_SIZE 1024
#define MIN(a,b) (a <= b ? a : b)
static void
png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
{
int check;
png_byte *n_data;
FILE *io_ptr;
/* Check if data really is near. If so, use usual code. */
n_data = (png_byte *)CVT_PTR_NOCHECK(data);
io_ptr = (FILE *)CVT_PTR(png_ptr->io_ptr);
if ((png_bytep)n_data == data)
{
check = fread(n_data, 1, length, io_ptr);
}
else
{
png_byte buf[NEAR_BUF_SIZE];
png_size_t read, remaining, err;
check = 0;
remaining = length;
do
{
read = MIN(NEAR_BUF_SIZE, remaining);
err = fread(buf, (png_size_t)1, read, io_ptr);
png_memcpy(data, buf, read); /* copy far buffer to near buffer */
if(err != read)
break;
else
check += err;
data += read;
remaining -= read;
}
while (remaining != 0);
}
if (check != length)
{
png_error(png_ptr, "read Error");
}
}
#endif
char inbuf[256], outbuf[256];
#if defined(PNG_WRITE_FLUSH_SUPPORTED)
static void
png_default_flush(png_structp png_ptr)
{
FILE *io_ptr;
io_ptr = (FILE *)CVT_PTR((png_ptr->io_ptr));
if (io_ptr != NULL)
fflush(io_ptr);
}
#endif
int
main(int argc, char *argv[])
/* This is the function which does the actual writing of data. If you are
not writing to a standard C stream, you should create a replacement
write_data function and use it at run time with png_set_write_fn(), rather
than changing the library. */
#ifndef USE_FAR_KEYWORD
static void
png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
{
png_uint_32 check;
check = fwrite(data, 1, length, (FILE *)(png_ptr->io_ptr));
if (check != length)
{
png_error(png_ptr, "Write Error");
}
}
#else
/* this is the model-independent version. Since the standard I/O library
can't handle far buffers in the medium and small models, we have to copy
the data.
*/
#define NEAR_BUF_SIZE 1024
#define MIN(a,b) (a <= b ? a : b)
static void
png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
{
png_uint_32 check;
png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */
FILE *io_ptr;
/* Check if data really is near. If so, use usual code. */
near_data = (png_byte *)CVT_PTR_NOCHECK(data);
io_ptr = (FILE *)CVT_PTR(png_ptr->io_ptr);
if ((png_bytep)near_data == data)
{
check = fwrite(near_data, 1, length, io_ptr);
}
else
{
png_byte buf[NEAR_BUF_SIZE];
png_size_t written, remaining, err;
check = 0;
remaining = length;
do
{
written = MIN(NEAR_BUF_SIZE, remaining);
png_memcpy(buf, data, written); /* copy far buffer to near buffer */
err = fwrite(buf, 1, written, io_ptr);
if (err != written)
break;
else
check += err;
data += written;
remaining -= written;
}
while (remaining != 0);
}
if (check != length)
{
png_error(png_ptr, "Write Error");
}
}
#endif
/* This function is called when there is a warning, but the library thinks
* it can continue anyway. Replacement functions don't have to do anything
* here if you don't want to. In the default configuration, png_ptr is
* not used, but it is passed in case it may be useful.
*/
static void
png_default_warning(png_structp png_ptr, png_const_charp message)
{
PNG_CONST char *name = "UNKNOWN (ERROR!)";
if (png_ptr != NULL && png_ptr->error_ptr != NULL)
name = png_ptr->error_ptr;
fprintf(STDERR, "%s: libpng warning: %s\n", name, message);
}
/* This is the default error handling function. Note that replacements for
* this function MUST NOT RETURN, or the program will likely crash. This
* function is used by default, or if the program supplies NULL for the
* error function pointer in png_set_error_fn().
*/
static void
png_default_error(png_structp png_ptr, png_const_charp message)
{
png_default_warning(png_ptr, message);
/* We can return because png_error calls the default handler which is
* actually ok in this case. */
}
#endif
/* END of code to validate stdio-free compilation */
/* Test one file */
int test(PNG_CONST char *inname, PNG_CONST char *outname)
{
FILE *fpin, *fpout;
png_structp read_ptr, write_ptr;
@ -69,30 +240,11 @@ main(int argc, char *argv[])
#ifdef USE_FAR_KEYWORD
jmp_buf jmpbuf;
#endif
char inbuf[256], outbuf[256];
row_buf = (png_bytep)NULL;
fprintf(STDERR, "Testing libpng version %s\n", PNG_LIBPNG_VER_STRING);
if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING))
{
fprintf(STDERR,
"Warning: versions are different between png.h and png.c\n");
fprintf(STDERR, " png.h version: %s\n", PNG_LIBPNG_VER_STRING);
fprintf(STDERR, " png.c version: %s\n\n", png_libpng_ver);
}
if (argc > 1)
inname = argv[1];
if (argc > 2)
outname = argv[2];
if (argc > 3)
{
fprintf(stderr, "usage: %s [infile.png] [outfile.png]\n", argv[0]);
exit(1);
}
if ((fpin = fopen(inname, "rb")) == NULL)
{
fprintf(STDERR, "Could not find input file %s\n", inname);
@ -109,8 +261,14 @@ main(int argc, char *argv[])
png_debug(0, "Allocating read and write structures\n");
read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
(png_error_ptr)NULL, (png_error_ptr)NULL);
#if defined(PNG_NO_STDIO)
png_set_error_fn(read_ptr, (png_voidp)inname, png_default_error, png_default_warning);
#endif
write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
(png_error_ptr)NULL, (png_error_ptr)NULL);
#if defined(PNG_NO_STDIO)
png_set_error_fn(write_ptr, (png_voidp)inname, png_default_error, png_default_warning);
#endif
png_debug(0, "Allocating read_info, write_info and end_info structures\n");
read_info_ptr = png_create_info_struct(read_ptr);
write_info_ptr = png_create_info_struct(read_ptr);
@ -123,7 +281,7 @@ main(int argc, char *argv[])
if (setjmp(read_ptr->jmpbuf))
#endif
{
fprintf(STDERR, "libpng read error\n");
fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname);
png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
png_destroy_write_struct(&write_ptr, &write_info_ptr);
fclose(fpin);
@ -139,7 +297,7 @@ main(int argc, char *argv[])
if (setjmp(write_ptr->jmpbuf))
#endif
{
fprintf(STDERR, "libpng write error\n");
fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname);
png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
png_destroy_write_struct(&write_ptr, &write_info_ptr);
fclose(fpin);
@ -151,8 +309,18 @@ main(int argc, char *argv[])
png_memcpy(write_ptr->jmpbuf,jmpbuf,sizeof(jmp_buf));
#endif
png_debug(0, "Initializing input and output streams\n");
#if !defined(PNG_NO_STDIO)
png_init_io(read_ptr, fpin);
png_init_io(write_ptr, fpout);
#else
png_set_read_fn(read_ptr, (png_voidp)fpin, png_default_read_data);
png_set_write_fn(write_ptr, (png_voidp)fpout, png_default_write_data,
#if defined(PNG_WRITE_FLUSH_SUPPORTED)
png_default_flush);
#else
NULL);
#endif
#endif
png_debug(0, "Reading info struct\n");
png_read_info(read_ptr, read_info_ptr);
@ -398,8 +566,70 @@ main(int argc, char *argv[])
fclose(fpin);
fclose(fpout);
fprintf(STDERR, "libpng passes test\n");
return 0;
}
/* input and output filenames */
#ifdef RISCOS
PNG_CONST char *inname = "pngtest_png";
PNG_CONST char *outname = "pngout_png";
#else
PNG_CONST char *inname = "pngtest.png";
PNG_CONST char *outname = "pngout.png";
#endif
int
main(int argc, char *argv[])
{
int multiple = 0;
int ierror = 0;
fprintf(STDERR, "Testing libpng version %s\n", PNG_LIBPNG_VER_STRING);
if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING))
{
fprintf(STDERR,
"Warning: versions are different between png.h and png.c\n");
fprintf(STDERR, " png.h version: %s\n", PNG_LIBPNG_VER_STRING);
fprintf(STDERR, " png.c version: %s\n\n", png_libpng_ver);
++ierror;
}
if (argc > 1)
{
if (strcmp(argv[1], "-m") == 0)
multiple = 1;
else
inname = argv[1];
}
if (!multiple && argc == 3)
outname = argv[2];
if (!multiple && argc > 3 || multiple && argc < 2)
{
fprintf(STDERR, "usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n",
argv[0], argv[0]);
fprintf(STDERR, " reads/writes one PNG file (without -m) or multiple files (-m)\n");
fprintf(STDERR, " with -m %s is used as a temporary file\n", outname);
exit(1);
}
if (multiple)
{
int i;
for (i=2; i<argc; ++i)
ierror += test(argv[i], outname);
}
else
{
ierror += test(inname, outname);
}
if (ierror == 0)
fprintf(STDERR, "libpng passes test\n");
else
fprintf(STDERR, "libpng FAILS test\n");
return ierror != 0;
}

View File

@ -33,6 +33,7 @@ png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
png_error(png_ptr, "Call to NULL write function");
}
#if !defined(PNG_NO_STDIO)
/* This is the function which does the actual writing of data. If you are
not writing to a standard C stream, you should create a replacement
write_data function and use it at run time with png_set_write_fn(), rather
@ -98,6 +99,7 @@ png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
}
}
#endif
#endif
/* This function is called to output any data pending writing (normally
@ -111,6 +113,7 @@ png_flush(png_structp png_ptr)
(*(png_ptr->output_flush_fn))(png_ptr);
}
#if !defined(PNG_NO_STDIO)
static void
png_default_flush(png_structp png_ptr)
{
@ -120,6 +123,7 @@ png_default_flush(png_structp png_ptr)
fflush(io_ptr);
}
#endif
#endif
/* This function allows the application to supply new output functions for
libpng if standard C streams aren't being used.
@ -149,16 +153,24 @@ png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
{
png_ptr->io_ptr = io_ptr;
#if !defined(PNG_NO_STDIO)
if (write_data_fn != NULL)
png_ptr->write_data_fn = write_data_fn;
else
png_ptr->write_data_fn = png_default_write_data;
#else
png_ptr->write_data_fn = write_data_fn;
#endif
#if defined(PNG_WRITE_FLUSH_SUPPORTED)
#if !defined(PNG_NO_STDIO)
if (output_flush_fn != NULL)
png_ptr->output_flush_fn = output_flush_fn;
else
png_ptr->output_flush_fn = png_default_flush;
#else
png_ptr->output_flush_fn = output_flush_fn;
#endif
#endif /* PNG_WRITE_FLUSH_SUPPORTED */
/* It is an error to read while writing a png file */

View File

@ -24,7 +24,9 @@
void
png_write_info(png_structp png_ptr, png_infop info_ptr)
{
#if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
int i;
#endif
png_debug(1, "in png_write_info\n");
png_write_sig(png_ptr); /* write PNG signature */
@ -146,7 +148,9 @@ png_write_end(png_structp png_ptr, png_infop info_ptr)
/* see if user wants us to write information chunks */
if (info_ptr != NULL)
{
#if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
int i; /* local index variable */
#endif
#if defined(PNG_WRITE_tIME_SUPPORTED)
/* check to see if user has supplied a time chunk */
if (info_ptr->valid & PNG_INFO_tIME &&
@ -210,9 +214,22 @@ png_convert_to_rfc1152(png_structp png_ptr, png_timep ptime)
png_ptr->time_buffer = (png_charp)png_malloc(png_ptr, 29*sizeof(char));
}
#ifdef USE_FAR_KEYWORD
{
char near_time_buf[29];
sprintf(near_time_buf, "%d %s %d %02d:%02d:%02d +0000",
ptime->day % 31, short_months[ptime->month],
ptime->year, ptime->hour % 24, ptime->minute % 60,
ptime->second % 61);
png_memcpy(png_ptr->time_buffer, near_time_buf,
29*sizeof(char));
}
#else
sprintf(png_ptr->time_buffer, "%d %s %d %02d:%02d:%02d +0000",
ptime->day % 31, short_months[ptime->month], ptime->year,
ptime->hour % 24, ptime->minute % 60, ptime->second % 61);
ptime->day % 31, short_months[ptime->month],
ptime->year, ptime->hour % 24, ptime->minute % 60,
ptime->second % 61);
#endif
return png_ptr->time_buffer;
}
#endif /* PNG_TIME_RFC1152_SUPPORTED */
@ -732,7 +749,9 @@ png_set_filter_heuristics(png_structp png_ptr, int heuristic_method,
int num_weights, png_doublep filter_weights,
png_doublep filter_costs)
{
#if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
int i;
#endif
png_debug(1, "in png_set_filter_heuristics\n");
if (heuristic_method >= PNG_FILTER_HEURISTIC_LAST)

View File

@ -593,10 +593,7 @@ png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key)
if (key == NULL || (key_len = png_strlen(key)) == 0)
{
char msg[40];
sprintf(msg, "Zero length %s keyword", png_ptr->chunk_name);
png_warning(png_ptr, msg);
png_chunk_warning(png_ptr, "zero length keyword");
return 0;
}
@ -607,13 +604,16 @@ png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key)
/* Replace non-printing characters with a blank and print a warning */
for (kp = key, dp = *new_key; *kp != '\0'; kp++, dp++)
{
if (*kp < 0x20 || (*kp > 0x7E && *kp < 0xA1))
if (*kp < 0x20 || (*kp > 0x7E && (png_byte)*kp < 0xA1))
{
#if !defined(PNG_NO_STDIO)
char msg[40];
sprintf(msg, "Invalid %s keyword character 0x%02X",
png_ptr->chunk_name, *kp);
png_warning(png_ptr, msg);
sprintf(msg, "invalid keyword character 0x%02X", *kp);
png_chunk_warning(png_ptr, msg);
#else
png_chunk_warning(png_ptr, "invalid character in keyword");
#endif
*dp = ' ';
}
else
@ -627,11 +627,7 @@ png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key)
kp = *new_key + key_len - 1;
if (*kp == ' ')
{
char msg[50];
sprintf(msg, "Trailing spaces removed from %s keyword",
png_ptr->chunk_name);
png_warning(png_ptr, msg);
png_chunk_warning(png_ptr, "trailing spaces removed from keyword");
while (*kp == ' ')
{
@ -644,11 +640,7 @@ png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key)
kp = *new_key;
if (*kp == ' ')
{
char msg[50];
sprintf(msg, "Leading spaces removed from %s keyword",
png_ptr->chunk_name);
png_warning(png_ptr, msg);
png_chunk_warning(png_ptr, "leading spaces removed from keyword");
while (*kp == ' ')
{
@ -681,19 +673,12 @@ png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key)
if (key_len == 0)
{
char msg[40];
sprintf(msg, "Zero length %s keyword", png_ptr->chunk_name);
png_warning(png_ptr, msg);
png_chunk_warning(png_ptr, "zero length keyword");
}
if (key_len > 79)
{
char msg[50];
sprintf(msg, "%s keyword length must be 1 - 79 characters",
png_ptr->chunk_name);
png_warning(png_ptr, msg);
png_chunk_warning(png_ptr, "keyword length must be 1 - 79 characters");
new_key[79] = '\0';
key_len = 79;
}
@ -714,10 +699,7 @@ png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text,
png_debug(1, "in png_write_tEXt\n");
if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0)
{
char msg[40];
sprintf(msg, "Empty keyword in %s chunk", "tEXt");
png_warning(png_ptr, msg);
png_warning(png_ptr, "Empty keyword in tEXt chunk");
return;
}
@ -753,10 +735,7 @@ png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text,
if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0)
{
char msg[40];
sprintf(msg, "Empty keyword in %s chunk", "zTXt");
png_warning(png_ptr, msg);
png_warning(png_ptr, "Empty keyword in zTXt chunk");
return;
}
@ -771,9 +750,13 @@ png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text,
if (compression >= PNG_TEXT_COMPRESSION_LAST)
{
#if !defined(PNG_NO_STDIO)
char msg[50];
sprintf(msg, "Unknown zTXt compression type %d", compression);
png_warning(png_ptr, msg);
#else
png_warning(png_ptr, "Unknown zTXt compression type");
#endif
compression = PNG_TEXT_COMPRESSION_zTXt;
}
@ -1389,10 +1372,10 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
* been specified by the application, and then writes the row out with the
* chosen filter.
*/
#define PNG_MAXSUM (~0x0UL >> 1)
#define PNG_MAXSUM (png_uint_32)(~0x0UL >> 1)
#define PNG_HISHIFT 10
#define PNG_LOMASK 0xffffL
#define PNG_HIMASK (~PNG_LOMASK >> PNG_HISHIFT)
#define PNG_LOMASK (png_uint_32)0xffffL
#define PNG_HIMASK (png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT)
void
png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
{