Imported from libpng-0.97a.tar
diff --git a/TODO b/TODO
index 605e591..e8c95ea 100644
--- a/TODO
+++ b/TODO
@@ -3,8 +3,9 @@
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
diff --git a/png.h b/png.h
index 3441beb..ae7ddf0 100644
--- a/png.h
+++ b/png.h
@@ -997,8 +997,10 @@
* 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 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 @@
#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)
diff --git a/pngconf.h b/pngconf.h
index 70b77c1..81f21fc 100644
--- a/pngconf.h
+++ b/pngconf.h
@@ -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 @@
* 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 @@
#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 @@
#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 @@
#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 */
diff --git a/pngerror.c b/pngerror.c
index a800884..77232d7 100644
--- a/pngerror.c
+++ b/pngerror.c
@@ -51,6 +51,60 @@
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
diff --git a/pngget.c b/pngget.c
index 549c17a..f06dde0 100644
--- a/pngget.c
+++ b/pngget.c
@@ -111,13 +111,14 @@
#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);
diff --git a/pngpread.c b/pngpread.c
index a333513..e892a62 100644
--- a/pngpread.c
+++ b/pngpread.c
@@ -1056,10 +1056,7 @@
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);
diff --git a/pngrio.c b/pngrio.c
index 119f582..1f4865a 100644
--- a/pngrio.c
+++ b/pngrio.c
@@ -33,6 +33,7 @@
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 @@
}
}
#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_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;
diff --git a/pngrtran.c b/pngrtran.c
index 28b0415..b72f0af 100644
--- a/pngrtran.c
+++ b/pngrtran.c
@@ -986,11 +986,15 @@
#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
diff --git a/pngrutil.c b/pngrutil.c
index bd225b6..4fe7a4d 100644
--- a/pngrutil.c
+++ b/pngrutil.c
@@ -88,20 +88,16 @@
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 @@
}
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 @@
{
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 @@
/* 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 @@
#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 @@
#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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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");
}
}
diff --git a/pngset.c b/pngset.c
index 2855207..2652b76 100644
--- a/pngset.c
+++ b/pngset.c
@@ -238,19 +238,19 @@
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);
diff --git a/pngtest.c b/pngtest.c
index 1348f2d..cea4c8e 100644
--- a/pngtest.c
+++ b/pngtest.c
@@ -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 @@
#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 @@
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 @@
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 @@
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 @@
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 @@
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;
+}
diff --git a/pngwio.c b/pngwio.c
index 0fa2a94..497c5ca 100644
--- a/pngwio.c
+++ b/pngwio.c
@@ -33,6 +33,7 @@
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
@@ -99,6 +100,7 @@
}
#endif
+#endif
/* This function is called to output any data pending writing (normally
to disk). After png_flush is called, there should be no data pending
@@ -111,6 +113,7 @@
(*(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 @@
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_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 */
diff --git a/pngwrite.c b/pngwrite.c
index 584254d..6a7b060 100644
--- a/pngwrite.c
+++ b/pngwrite.c
@@ -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 @@
/* 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_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 @@
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)
diff --git a/pngwutil.c b/pngwutil.c
index bad95a9..b4575e4 100644
--- a/pngwutil.c
+++ b/pngwutil.c
@@ -593,10 +593,7 @@
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 @@
/* 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 @@
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 @@
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 @@
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_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 @@
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 @@
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 @@
* 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)
{