]> git.saurik.com Git - wxWidgets.git/commitdiff
libPNG 1.0.3
authorRobert Roebling <robert@roebling.de>
Sat, 17 Apr 1999 13:43:15 +0000 (13:43 +0000)
committerRobert Roebling <robert@roebling.de>
Sat, 17 Apr 1999 13:43:15 +0000 (13:43 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@2216 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

27 files changed:
src/png/CHANGES
src/png/INSTALL
src/png/README
src/png/TODO
src/png/ansi2knr.c
src/png/example.c
src/png/libpng.3
src/png/libpngpf.3
src/png/png.5
src/png/png.c
src/png/png.h
src/png/pngconf.h
src/png/pngerror.c
src/png/pngget.c
src/png/pngmem.c
src/png/pngpread.c
src/png/pngread.c
src/png/pngrio.c
src/png/pngrtran.c
src/png/pngrutil.c
src/png/pngset.c
src/png/pngtest.c
src/png/pngtrans.c
src/png/pngwio.c
src/png/pngwrite.c
src/png/pngwtran.c
src/png/pngwutil.c

index 9cb33a1e8942c7ac590226e4f5fe7bcb0b40dab5..d2dcde3ae0bd44aeea130a73b8e8af7c5254df19 100644 (file)
 CHANGES - changes for libpng
 
 version 0.2
-   added reader into png.h
-   fixed small problems in stub file
+  added reader into png.h
+  fixed small problems in stub file
 version 0.3
-   added pull reader
-   split up pngwrite.c to several files
-   added pnglib.txt
-   added example.c
-   cleaned up writer, adding a few new tranformations
-   fixed some bugs in writer
-   interfaced with zlib 0.5
-   added K&R support
-   added check for 64 KB blocks for 16 bit machines
+  added pull reader
+  split up pngwrite.c to several files
+  added pnglib.txt
+  added example.c
+  cleaned up writer, adding a few new tranformations
+  fixed some bugs in writer
+  interfaced with zlib 0.5
+  added K&R support
+  added check for 64 KB blocks for 16 bit machines
 version 0.4
-   cleaned up code and commented code
-   simplified time handling into png_time
-   created png_color_16 and png_color_8 to handle color needs
-   cleaned up color type defines
-   fixed various bugs
-   made various names more consistant
-   interfaced with zlib 0.71
-   cleaned up zTXt reader and writer (using zlib's Reset functions)
-   split transformations into pngrtran.c and pngwtran.c
+  cleaned up code and commented code
+  simplified time handling into png_time
+  created png_color_16 and png_color_8 to handle color needs
+  cleaned up color type defines
+  fixed various bugs
+  made various names more consistant
+  interfaced with zlib 0.71
+  cleaned up zTXt reader and writer (using zlib's Reset functions)
+  split transformations into pngrtran.c and pngwtran.c
 version 0.5
-   interfaced with zlib 0.8
-   fixed many reading and writing bugs
-   saved using 3 spaces instead of tabs
+  interfaced with zlib 0.8
+  fixed many reading and writing bugs
+  saved using 3 spaces instead of tabs
 version 0.6
-   added png_large_malloc() and png_large_free()
-   added png_size_t
-   cleaned up some compiler warnings
-   added png_start_read_image()
+  added png_large_malloc() and png_large_free()
+  added png_size_t
+  cleaned up some compiler warnings
+  added png_start_read_image()
 version 0.7
-   cleaned up lots of bugs
-   finished dithering and other stuff
-   added test program
-   changed name from pnglib to libpng
+  cleaned up lots of bugs
+  finished dithering and other stuff
+  added test program
+  changed name from pnglib to libpng
 version 0.71 [June, 1995]
-   changed pngtest.png for zlib 0.93
-   fixed error in libpng.txt and example.c
+  changed pngtest.png for zlib 0.93
+  fixed error in libpng.txt and example.c
 version 0.8
-   cleaned up some bugs
-   added png_set_filler()
-   split up pngstub.c into pngmem.c, pngio.c, and pngerror.c
-   added #define's to remove unwanted code
-   moved png_info_init() to png.c
-   added old_size into png_realloc()
-   added functions to manually set filtering and compression info
-   changed compression parameters based on image type
-   optimized filter selection code
-   added version info
-   changed external functions passing floats to doubles (k&r problems?)
-   put all the configurable stuff in pngconf.h
-   enabled png_set_shift to work with paletted images on read
-   added png_read_update_info() - updates info structure with
-      transformations
+  cleaned up some bugs
+  added png_set_filler()
+  split up pngstub.c into pngmem.c, pngio.c, and pngerror.c
+  added #define's to remove unwanted code
+  moved png_info_init() to png.c
+  added old_size into png_realloc()
+  added functions to manually set filtering and compression info
+  changed compression parameters based on image type
+  optimized filter selection code
+  added version info
+  changed external functions passing floats to doubles (k&r problems?)
+  put all the configurable stuff in pngconf.h
+  enabled png_set_shift to work with paletted images on read
+  added png_read_update_info() - updates info structure with
+     transformations
 version 0.81 [August, 1995]
-   incorporated Tim Wegner's medium model code (thanks, Tim)
+  incorporated Tim Wegner's medium model code (thanks, Tim)
 version 0.82 [September, 1995]
-   [unspecified changes]
+  [unspecified changes]
 version 0.85 [December, 1995]
-   added more medium model code (almost everything's a far)
-   added i/o, error, and memory callback functions
-   fixed some bugs (16 bit, 4 bit interlaced, etc.)
-   added first run progressive reader (barely tested)
+  added more medium model code (almost everything's a far)
+  added i/o, error, and memory callback functions
+  fixed some bugs (16 bit, 4 bit interlaced, etc.)
+  added first run progressive reader (barely tested)
 version 0.86 [January, 1996]
-   fixed bugs
-   improved documentation
+  fixed bugs
+  improved documentation
 version 0.87 [January, 1996]
-   fixed medium model bugs
-   fixed other bugs introduced in 0.85 and 0.86
-   added some minor documentation
+  fixed medium model bugs
+  fixed other bugs introduced in 0.85 and 0.86
+  added some minor documentation
 version 0.88 [January, 1996]
-   fixed progressive bugs
-   replaced tabs with spaces
-   cleaned up documentation
-   added callbacks for read/write and warning/error functions
+  fixed progressive bugs
+  replaced tabs with spaces
+  cleaned up documentation
+  added callbacks for read/write and warning/error functions
 version 0.89 [July, 1996]
-   added new initialization API to make libpng work better with shared libs
-      we now have png_create_read_struct(), png_create_write_struct(),
-      png_create_info_struct(), png_destroy_read_struct(), and
-      png_destroy_write_struct() instead of the separate calls to
-      malloc and png_read_init(), png_info_init(), and png_write_init()
-   changed warning/error callback functions to fix bug - this means you
-      should use the new initialization API if you were using the old
-      png_set_message_fn() calls, and that the old API no longer exists
-      so that people are aware that they need to change their code
-   changed filter selection API to allow selection of multiple filters
-      since it didn't work in previous versions of libpng anyways
-   optimized filter selection code    
-   fixed png_set_background() to allow using an arbitrary RGB color for
-      paletted images
-   fixed gamma and background correction for paletted images, so
-      png_correct_palette is not needed unless you are correcting an
-      external palette (you will need to #define PNG_CORRECT_PALETTE_SUPPORTED
-      in pngconf.h) - if nobody uses this, it may disappear in the future.
-   fixed bug with Borland 64K memory allocation (Alexander Lehmann)
-   fixed bug in interlace handling (Smarasderagd, I think)
-   added more error checking for writing and image to reduce invalid files
-   separated read and write functions so that they won't both be linked
-      into a binary when only reading or writing functionality is used
-   new pngtest image also has interlacing and zTXt
-   updated documentation to reflect new API
+  added new initialization API to make libpng work better with shared libs
+     we now have png_create_read_struct(), png_create_write_struct(),
+     png_create_info_struct(), png_destroy_read_struct(), and
+     png_destroy_write_struct() instead of the separate calls to
+     malloc and png_read_init(), png_info_init(), and png_write_init()
+  changed warning/error callback functions to fix bug - this means you
+     should use the new initialization API if you were using the old
+     png_set_message_fn() calls, and that the old API no longer exists
+     so that people are aware that they need to change their code
+  changed filter selection API to allow selection of multiple filters
+     since it didn't work in previous versions of libpng anyways
+  optimized filter selection code
+  fixed png_set_background() to allow using an arbitrary RGB color for
+     paletted images
+  fixed gamma and background correction for paletted images, so
+     png_correct_palette is not needed unless you are correcting an
+     external palette (you will need to #define PNG_CORRECT_PALETTE_SUPPORTED
+     in pngconf.h) - if nobody uses this, it may disappear in the future.
+  fixed bug with Borland 64K memory allocation (Alexander Lehmann)
+  fixed bug in interlace handling (Smarasderagd, I think)
+  added more error checking for writing and image to reduce invalid files
+  separated read and write functions so that they won't both be linked
+     into a binary when only reading or writing functionality is used
+  new pngtest image also has interlacing and zTXt
+  updated documentation to reflect new API
 version 0.90 [January, 1997]
-   made CRC errors/warnings on critical and ancillary chunks configurable
-   libpng will use the zlib CRC routines by (compile-time) default
-   changed DOS small/medium model memory support - needs zlib 1.04 (Tim Wegner)
-   added external C++ wrapper statements to png.h (Gilles Dauphin)
-   allow PNG file to be read when some or all of file signature has already
-      been read from the beginning of the stream.  ****This affects the size
-      of info_struct and invalidates all programs that use a shared libpng****
-   fixed png_filler() declarations
-   fixed? background color conversions
-   fixed order of error function pointers to match documentation
-   current chunk name is now available in png_struct to reduce the number
-      of nearly identical error messages (will simplify multi-lingual
-      support when available)
-   try to get ready for unknown-chunk callback functions:
-      - previously read critical chunks are flagged, so the chunk handling
-        routines can determine if the chunk is in the right place
-      - all chunk handling routines have the same prototypes, so we will
-        be able to handle all chunks via a callback mechanism
-   try to fix Linux "setjmp" buffer size problems
+  made CRC errors/warnings on critical and ancillary chunks configurable
+  libpng will use the zlib CRC routines by (compile-time) default
+  changed DOS small/medium model memory support - needs zlib 1.04 (Tim Wegner)
+  added external C++ wrapper statements to png.h (Gilles Dauphin)
+  allow PNG file to be read when some or all of file signature has already
+     been read from the beginning of the stream.  ****This affects the size
+     of info_struct and invalidates all programs that use a shared libpng****
+  fixed png_filler() declarations
+  fixed? background color conversions
+  fixed order of error function pointers to match documentation
+  current chunk name is now available in png_struct to reduce the number
+     of nearly identical error messages (will simplify multi-lingual
+     support when available)
+  try to get ready for unknown-chunk callback functions:
+     - previously read critical chunks are flagged, so the chunk handling
+       routines can determine if the chunk is in the right place
+     - all chunk handling routines have the same prototypes, so we will
+       be able to handle all chunks via a callback mechanism
+  try to fix Linux "setjmp" buffer size problems
 version 0.95 [March, 1997]
-   fixed bug in pngwutil.c allocating "up_row" twice and "avg_row" never
-   fixed bug in PNG file signature compares when start != 0
-   changed parameter type of png_set_filler(...filler...) from png_byte
-      to png_uint_32
-   added test for MACOS to ensure that both math.h and fp.h are not #included
-   added macros for libpng to be compiled as a Windows DLL (Andreas Kupries)
-   added "packswap" transformation, which changes the endianness of
-      packed-pixel bytes (Kevin Bracey)
-   added "strip_alpha" transformation, which removes the alpha channel of
-      input images without using it (not neccesarily a good idea)
-   added "swap_alpha" transformation, which puts the alpha channel in front
-      of the color bytes instead of after
-   removed all implicit variable tests which assume NULL == 0 (I think)
-   changed several variables to "png_size_t" to show 16/32-bit limitations
-   added new pCAL chunk read/write support
-   added experimental filter selection weighting (Greg Roelofs)
-   removed old png_set_rgbx() and png_set_xrgb() functions that have been
-      obsolete for about 2 years now (use png_set_filler() instead)
-   added macros to read 16- and 32-bit ints directly from buffer, to be
-      used only on those systems that support it (namely PowerPC and 680x0)
-      With some testing, this may become the default for MACOS/PPC systems.
-   only calculate CRC on data if we are going to use it
-   added macros for zTXt compression type PNG_zTXt_COMPRESSION_???
-   added macros for simple libpng debugging output selectable at compile time
-   removed PNG_READ_END_MODE in progressive reader (Smarasderagd)
-   more description of info_struct in libpng.txt and png.h
-   more instructions in example.c
-   more chunk types tested in pngtest.c
-   renamed pngrcb.c to pngset.c, and all png_read_<chunk> functions to be
-      png_set_<chunk>.  We now have corresponding png_get_<chunk>
-      functions in pngget.c to get infomation in info_ptr.  This isolates
-      the application from the internal organization of png_info_struct
-      (good for shared library implementations).
+  fixed bug in pngwutil.c allocating "up_row" twice and "avg_row" never
+  fixed bug in PNG file signature compares when start != 0
+  changed parameter type of png_set_filler(...filler...) from png_byte
+     to png_uint_32
+  added test for MACOS to ensure that both math.h and fp.h are not #included
+  added macros for libpng to be compiled as a Windows DLL (Andreas Kupries)
+  added "packswap" transformation, which changes the endianness of
+     packed-pixel bytes (Kevin Bracey)
+  added "strip_alpha" transformation, which removes the alpha channel of
+     input images without using it (not neccesarily a good idea)
+  added "swap_alpha" transformation, which puts the alpha channel in front
+     of the color bytes instead of after
+  removed all implicit variable tests which assume NULL == 0 (I think)
+  changed several variables to "png_size_t" to show 16/32-bit limitations
+  added new pCAL chunk read/write support
+  added experimental filter selection weighting (Greg Roelofs)
+  removed old png_set_rgbx() and png_set_xrgb() functions that have been
+     obsolete for about 2 years now (use png_set_filler() instead)
+  added macros to read 16- and 32-bit ints directly from buffer, to be
+     used only on those systems that support it (namely PowerPC and 680x0)
+     With some testing, this may become the default for MACOS/PPC systems.
+  only calculate CRC on data if we are going to use it
+  added macros for zTXt compression type PNG_zTXt_COMPRESSION_???
+  added macros for simple libpng debugging output selectable at compile time
+  removed PNG_READ_END_MODE in progressive reader (Smarasderagd)
+  more description of info_struct in libpng.txt and png.h
+  more instructions in example.c
+  more chunk types tested in pngtest.c
+  renamed pngrcb.c to pngset.c, and all png_read_<chunk> functions to be
+     png_set_<chunk>.  We now have corresponding png_get_<chunk>
+     functions in pngget.c to get infomation in info_ptr.  This isolates
+     the application from the internal organization of png_info_struct
+     (good for shared library implementations).
 version 0.96 [May, 1997]
-   fixed serious bug with < 8bpp images introduced in 0.95
-   fixed 256-color transparency bug (Greg Roelofs)
-   fixed up documentation (Greg Roelofs, Laszlo Nyul)
-   fixed "error" in pngconf.h for Linux setjmp() behaviour
-   fixed DOS medium model support (Tim Wegner)
-   fixed png_check_keyword() for case with error in static string text
-   added read of CRC after IEND chunk for embedded PNGs (Laszlo Nyul)
-   added typecasts to quiet compiler errors
-   added more debugging info
+  fixed serious bug with < 8bpp images introduced in 0.95
+  fixed 256-color transparency bug (Greg Roelofs)
+  fixed up documentation (Greg Roelofs, Laszlo Nyul)
+  fixed "error" in pngconf.h for Linux setjmp() behaviour
+  fixed DOS medium model support (Tim Wegner)
+  fixed png_check_keyword() for case with error in static string text
+  added read of CRC after IEND chunk for embedded PNGs (Laszlo Nyul)
+  added typecasts to quiet compiler errors
+  added more debugging info
 version 0.97 [January, 1998]
-   removed PNG_USE_OWN_CRC capability
-   relocated png_set_crc_action from pngrutil.c to pngrtran.c
-   fixed typecasts of "new_key", etc. (Andreas Dilger)
-   added RFC 1152 [sic] date support
-   fixed bug in gamma handling of 4-bit grayscale
-   added 2-bit grayscale gamma handling (Glenn R-P)
-   added more typecasts. 65536L becomes (png_uint_32)65536L, etc. (Glenn R-P)
-   minor corrections in libpng.txt
-   added simple sRGB support (Glenn R-P)
-   easier conditional compiling, e.g. define PNG_READ/WRITE_NOT_FULLY_SUPPORTED;
-      all configurable options can be selected from command-line instead
-      of having to edit pngconf.h (Glenn R-P)
-   fixed memory leak in pngwrite.c (free info_ptr->text) (Glenn R-P)
-   added more conditions for png_do_background, to avoid changing
-      black pixels to background when a background is supplied and
-      no pixels are transparent
-   repaired PNG_NO_STDIO behaviour
-   tested NODIV support and made it default behaviour (Greg Roelofs)
-   added "-m" option and PNGTEST_DEBUG_MEMORY to pngtest (John Bowler)
-   regularized version numbering scheme and bumped shared-library major
-      version number to 2 to avoid problems with libpng 0.89 apps (Greg Roelofs)
+  removed PNG_USE_OWN_CRC capability
+  relocated png_set_crc_action from pngrutil.c to pngrtran.c
+  fixed typecasts of "new_key", etc. (Andreas Dilger)
+  added RFC 1152 [sic] date support
+  fixed bug in gamma handling of 4-bit grayscale
+  added 2-bit grayscale gamma handling (Glenn R-P)
+  added more typecasts. 65536L becomes (png_uint_32)65536L, etc. (Glenn R-P)
+  minor corrections in libpng.txt
+  added simple sRGB support (Glenn R-P)
+  easier conditional compiling, e.g. define PNG_READ/WRITE_NOT_FULLY_SUPPORTED;
+     all configurable options can be selected from command-line instead
+     of having to edit pngconf.h (Glenn R-P)
+  fixed memory leak in pngwrite.c (free info_ptr->text) (Glenn R-P)
+  added more conditions for png_do_background, to avoid changing
+     black pixels to background when a background is supplied and
+     no pixels are transparent
+  repaired PNG_NO_STDIO behaviour
+  tested NODIV support and made it default behaviour (Greg Roelofs)
+  added "-m" option and PNGTEST_DEBUG_MEMORY to pngtest (John Bowler)
+  regularized version numbering scheme and bumped shared-library major
+     version number to 2 to avoid problems with libpng 0.89 apps (Greg Roelofs)
 version 0.98 [January, 1998]
-   cleaned up some typos in libpng.txt and in code documentation
-   fixed memory leaks in pCAL chunk processing (Glenn R-P and John Bowler)
-   cosmetic change "display_gamma" to "screen_gamma" in pngrtran.c
-   changed recommendation about file_gamma for PC images to .51 from .45,
-      in example.c and libpng.txt, added comments to distinguish between
-      screen_gamma, viewing_gamma, and display_gamma.
-   changed all references to RFC1152 to read RFC1123 and changed the
-      PNG_TIME_RFC1152_SUPPORTED macro to PNG_TIME_RFC1123_SUPPORTED
-   added png_invert_alpha capability (Glenn R-P -- suggestion by Jon Vincent)
-   changed srgb_intent from png_byte to int to avoid compiler bugs
+  cleaned up some typos in libpng.txt and in code documentation
+  fixed memory leaks in pCAL chunk processing (Glenn R-P and John Bowler)
+  cosmetic change "display_gamma" to "screen_gamma" in pngrtran.c
+  changed recommendation about file_gamma for PC images to .51 from .45,
+     in example.c and libpng.txt, added comments to distinguish between
+     screen_gamma, viewing_gamma, and display_gamma.
+  changed all references to RFC1152 to read RFC1123 and changed the
+     PNG_TIME_RFC1152_SUPPORTED macro to PNG_TIME_RFC1123_SUPPORTED
+  added png_invert_alpha capability (Glenn R-P -- suggestion by Jon Vincent)
+  changed srgb_intent from png_byte to int to avoid compiler bugs
 version 0.99 [January 30, 1998]
-   free info_ptr->text instead of end_info_ptr->text in pngread.c (John Bowler)
-   fixed a longstanding "packswap" bug in pngtrans.c
-   fixed some inconsistencies in pngconf.h that prevented compiling with
-      PNG_READ_GAMMA_SUPPORTED and PNG_READ_hIST_SUPPORTED undefined
-   fixed some typos and made other minor rearrangement of libpng.txt (Andreas)
-   changed recommendation about file_gamma for PC images to .50 from .51 in
-      example.c and libpng.txt, and changed file_gamma for sRGB images to .45
-   added a number of functions to access information from the png structure
-      png_get_image_height(), etc. (Glenn R-P, suggestion by Brad Pettit)
-   added TARGET_MACOS similar to zlib-1.0.8
-   define PNG_ALWAYS_EXTERN when __MWERKS__ && WIN32 are defined
-   added type casting to all png_malloc() function calls
+  free info_ptr->text instead of end_info_ptr->text in pngread.c (John Bowler)
+  fixed a longstanding "packswap" bug in pngtrans.c
+  fixed some inconsistencies in pngconf.h that prevented compiling with
+     PNG_READ_GAMMA_SUPPORTED and PNG_READ_hIST_SUPPORTED undefined
+  fixed some typos and made other minor rearrangement of libpng.txt (Andreas)
+  changed recommendation about file_gamma for PC images to .50 from .51 in
+     example.c and libpng.txt, and changed file_gamma for sRGB images to .45
+  added a number of functions to access information from the png structure
+     png_get_image_height(), etc. (Glenn R-P, suggestion by Brad Pettit)
+  added TARGET_MACOS similar to zlib-1.0.8
+  define PNG_ALWAYS_EXTERN when __MWERKS__ && WIN32 are defined
+  added type casting to all png_malloc() function calls
 version 0.99a [January 31, 1998]
-   Added type casts and parentheses to all returns that return a value.(Tim W.)
+  Added type casts and parentheses to all returns that return a value.(Tim W.)
 version 0.99b [February 4, 1998]
-   Added type cast png_uint_32 on malloc function calls where needed.
-   Changed type of num_hist from png_uint_32 to int (same as num_palette).
-   Added checks for rowbytes overflow, in case png_size_t is less than 32 bits.
-   Renamed makefile.elf to makefile.lnx.
+  Added type cast png_uint_32 on malloc function calls where needed.
+  Changed type of num_hist from png_uint_32 to int (same as num_palette).
+  Added checks for rowbytes overflow, in case png_size_t is less than 32 bits.
+  Renamed makefile.elf to makefile.lnx.
 version 0.99c [February 7, 1998]
-   More type casting.  Removed erroneous overflow test in pngmem.c.
-   Added png_buffered_memcpy() and png_buffered_memset(), apply them to rowbytes.
-   Added UNIX manual pages libpng.3 (incorporating libpng.txt) and  png.5.
+  More type casting.  Removed erroneous overflow test in pngmem.c.
+  Added png_buffered_memcpy() and png_buffered_memset(), apply them to rowbytes.
+  Added UNIX manual pages libpng.3 (incorporating libpng.txt) and  png.5.
 version 0.99d [February 11, 1998]
-   Renamed "far_to_near()" "png_far_to_near()"
-   Revised libpng.3
-   Version 99c "buffered" operations didn't work as intended.  Replaced them
-     with png_memcpy_check() and png_memset_check().
-   Added many "if (png_ptr == NULL) return" to quell compiler warnings about
-     unused png_ptr, mostly in pngget.c and pngset.c.
-   Check for overlength tRNS chunk present when indexed-color PLTE is read.
-   Cleaned up spelling errors in libpng.3/libpng.txt
-   Corrected a problem with png_get_tRNS() which returned undefined trans array
+  Renamed "far_to_near()" "png_far_to_near()"
+  Revised libpng.3
+  Version 99c "buffered" operations didn't work as intended.  Replaced them
+    with png_memcpy_check() and png_memset_check().
+  Added many "if (png_ptr == NULL) return" to quell compiler warnings about
+    unused png_ptr, mostly in pngget.c and pngset.c.
+  Check for overlength tRNS chunk present when indexed-color PLTE is read.
+  Cleaned up spelling errors in libpng.3/libpng.txt
+  Corrected a problem with png_get_tRNS() which returned undefined trans array
 version 0.99e [February 28, 1998]
-   Corrected png_get_tRNS() again.
-   Add parentheses for easier reading of pngget.c, fixed "||" should be "&&".
-   Touched up example.c to make more of it compileable, although the entire
-     file still can't be compiled (Willem van Schaik)
-   Fixed a bug in png_do_shift() (Bryan Tsai)
-   Added a space in png.h prototype for png_write_chunk_start()
-   Replaced pngtest.png with one created with zlib 1.1.1
-   Changed pngtest to report PASS even when file size is different (Jean-loup G.)
-   Corrected some logic errors in png_do_invert_alpha() (Chris Patterson)
+  Corrected png_get_tRNS() again.
+  Add parentheses for easier reading of pngget.c, fixed "||" should be "&&".
+  Touched up example.c to make more of it compileable, although the entire
+    file still can't be compiled (Willem van Schaik)
+  Fixed a bug in png_do_shift() (Bryan Tsai)
+  Added a space in png.h prototype for png_write_chunk_start()
+  Replaced pngtest.png with one created with zlib 1.1.1
+  Changed pngtest to report PASS even when file size is different (Jean-loup G.)
+  Corrected some logic errors in png_do_invert_alpha() (Chris Patterson)
 version 0.99f [March 5, 1998]
-   Corrected a bug in pngpread() introduced in version 99c (Kevin Bracey)
-   Moved makefiles into a "scripts" directory, and added INSTALL instruction file
-   Added makefile.os2 and pngos2.def (A. Zabolotny) and makefile.s2x (W. Sebok)
-   Added pointers to "note on libpng versions" in makefile.lnx and README
-   Added row callback feature when reading and writing nonprogressive rows
-      and added a test of this feature in pngtest.c
-   Added user transform callbacks, with test of the feature in pngtest.c
+  Corrected a bug in pngpread() introduced in version 99c (Kevin Bracey)
+  Moved makefiles into a "scripts" directory, and added INSTALL instruction file
+  Added makefile.os2 and pngos2.def (A. Zabolotny) and makefile.s2x (W. Sebok)
+  Added pointers to "note on libpng versions" in makefile.lnx and README
+  Added row callback feature when reading and writing nonprogressive rows
+     and added a test of this feature in pngtest.c
+  Added user transform callbacks, with test of the feature in pngtest.c
 version 0.99g [March 6, 1998, morning]
-   Minor changes to pngtest.c to suppress compiler warnings.
-   Removed "beta" language from documentation.
+  Minor changes to pngtest.c to suppress compiler warnings.
+  Removed "beta" language from documentation.
 version 0.99h [March 6, 1998, evening]
-   Minor changes to previous minor changes to pngtest.c 
-   Changed PNG_READ_NOT_FULLY_SUPPORTED to PNG_READ_TRANSFORMS_NOT_SUPPORTED
-   and added PNG_PROGRESSIVE_READ_NOT_SUPPORTED macro
+  Minor changes to previous minor changes to pngtest.c
+  Changed PNG_READ_NOT_FULLY_SUPPORTED to PNG_READ_TRANSFORMS_NOT_SUPPORTED
+  and added PNG_PROGRESSIVE_READ_NOT_SUPPORTED macro
 version 1.00 [March 7, 1998]
-   Changed several typedefs in pngrutil.c
-   Added makefile.wat (Pawel Mrochen), updated makefile.tc3 (Willem van Schaik)
-   replaced "while(1)" with "for(;;)"
-   added PNGARG() to prototypes in pngtest.c and removed some prototypes
-   updated some of the makefiles (Tom Lane)
-   changed some typedefs (s_start, etc.) in pngrutil.c
-   fixed dimensions of "short_months" array in pngwrite.c
-   Replaced ansi2knr.c with the one from jpeg-v6
+  Changed several typedefs in pngrutil.c
+  Added makefile.wat (Pawel Mrochen), updated makefile.tc3 (Willem van Schaik)
+  replaced "while(1)" with "for(;;)"
+  added PNGARG() to prototypes in pngtest.c and removed some prototypes
+  updated some of the makefiles (Tom Lane)
+  changed some typedefs (s_start, etc.) in pngrutil.c
+  fixed dimensions of "short_months" array in pngwrite.c
+  Replaced ansi2knr.c with the one from jpeg-v6
 version 1.0.0 [March 8, 1998]
-   Changed name from 1.00 to 1.0.0 (Adam Costello)
-   Added smakefile.ppc (with SCOPTIONS.ppc) for Amiga PPC (Andreas Kleinert)
+  Changed name from 1.00 to 1.0.0 (Adam Costello)
+  Added smakefile.ppc (with SCOPTIONS.ppc) for Amiga PPC (Andreas Kleinert)
 version 1.0.0a [March 9, 1998]
-   Fixed three bugs in pngrtran.c to make gamma+background handling consistent
-   (Greg Roelofs)
-   Changed format of the PNG_LIBPNG_VER integer to xyyzz instead of xyz
-   for major, minor, and bugfix releases.  This is 10001. (Adam Costello,
-   Tom Lane)
-   Make months range from 1-12 in png_convert_to_rfc1123
+  Fixed three bugs in pngrtran.c to make gamma+background handling consistent
+  (Greg Roelofs)
+  Changed format of the PNG_LIBPNG_VER integer to xyyzz instead of xyz
+  for major, minor, and bugfix releases.  This is 10001. (Adam Costello,
+  Tom Lane)
+  Make months range from 1-12 in png_convert_to_rfc1123
 version 1.0.0b [March 13, 1998]
-   Quieted compiler complaints about two empty "for" loops in pngrutil.c
-   Minor changes to makefile.s2x
-   Removed #ifdef/#endif around a png_free() in pngread.c
+  Quieted compiler complaints about two empty "for" loops in pngrutil.c
+  Minor changes to makefile.s2x
+  Removed #ifdef/#endif around a png_free() in pngread.c
 version 1.0.1 [March 14, 1998]
-   Changes makefile.s2x to reduce security risk of using a relative pathname
-   Fixed some typos in the documentation (Greg).
-   Fixed a problem with value of "channels" returned by png_read_update_info()
+  Changed makefile.s2x to reduce security risk of using a relative pathname
+  Fixed some typos in the documentation (Greg).
+  Fixed a problem with value of "channels" returned by png_read_update_info()
+version 1.0.1a [April 21, 1998]
+  Optimized Paeth calculations by replacing abs() function calls with intrinsics
+  plus other loop optimizations. Improves avg decoding speed by about 20%.
+  Commented out i386istic "align" compiler flags in makefile.lnx.
+  Reduced the default warning level in some makefiles, to make them consistent.
+  Removed references to IJG and JPEG in the ansi2knr.c copyright statement.
+  Fixed a bug in png_do_strip_filler with XXRRGGBB => RRGGBB transformation.
+  Added grayscale and 16-bit capability to png_do_read_filler().
+  Fixed a bug in pngset.c, introduced in version 0.99c, that sets rowbytes
+    too large when writing an image with bit_depth < 8 (Bob Dellaca).
+  Corrected some bugs in the experimental weighted filtering heuristics.
+  Moved a misplaced pngrutil code block that truncates tRNS if it has more
+    than num_palette entries -- test was done before num_palette was defined.
+  Fixed a png_convert_to_rfc1123() bug that converts day 31 to 0 (Steve Eddins).
+  Changed compiler flags in makefile.wat for better optimization (Pawel Mrochen).
+version 1.0.1b [May 2, 1998]
+  Relocated png_do_gray_to_rgb() within png_do_read_transformations() (Greg).
+  Relocated the png_composite macros from pngrtran.c to png.h (Greg).
+  Added makefile.sco (contributed by Mike Hopkirk).
+  Fixed two bugs (missing definitions of "istop") introduced in libpng-1.0.1a.
+  Fixed a bug in pngrtran.c that would set channels=5 under some circumstances.
+  More work on the Paeth-filtering, achieving imperceptible speedup (A Kleinert).
+  More work on loop optimization which may help when compiled with C++ compilers.
+  Added warnings when people try to use transforms they've defined out.
+  Collapsed 4 "i" and "c" loops into single "i" loops in pngrtran and pngwtran.
+  Revised paragraph about png_set_expand() in libpng.txt and libpng.3 (Greg)
+version 1.0.1c [May 11, 1998]
+  Fixed a bug in pngrtran.c (introduced in libpng-1.0.1a) where the masks for
+    filler bytes should have been 0xff instead of 0xf.
+  Added max_pixel_depth=32 in pngrutil.c when using FILLER with palette images.
+  Moved PNG_WRITE_WEIGHTED_FILTER_SUPPORTED and PNG_WRITE_FLUSH_SUPPORTED
+    out of the PNG_WRITE_TRANSFORMS_NOT_SUPPORTED block of pngconf.h
+  Added "PNG_NO_WRITE_TRANSFORMS" etc., as alternatives for *_NOT_SUPPORTED,
+    for consistency, in pngconf.h
+  Added individual "ifndef PNG_NO_[CAPABILITY]" in pngconf.h to make it easier
+    to remove unwanted capabilities via the compile line
+  Made some corrections to grammar (which, it's) in documentation (Greg).
+  Corrected example.c, use of row_pointers in png_write_image().
+version 1.0.1d [May 24, 1998]
+  Corrected several statements that used side effects illegally in pngrutil.c
+    and pngtrans.c, that were introduced in version 1.0.1b
+  Revised png_read_rows() to avoid repeated if-testing for NULL (A Kleinert)
+  More corrections to example.c, use of row_pointers in png_write_image()
+    and png_read_rows().
+  Added pngdll.mak and pngdef.pas to scripts directory, contributed by
+    Bob Dellaca, to make a png32bd.dll with Borland C++ 4.5
+  Fixed error in example.c with png_set_text: num_text is 3, not 2 (Guido V.)
+  Changed several loops from count-down to count-up, for consistency.
+version 1.0.1e [June 6, 1998]
+  Revised libpng.txt and libpng.3 description of png_set_read|write_fn(), and
+    added warnings when people try to set png_read_fn and png_write_fn in
+    the same structure.
+  Added a test such that png_do_gamma will be done when num_trans==0
+    for truecolor images that have defined a background.  This corrects an
+    error that was introduced in libpng-0.90 that can cause gamma processing
+    to be skipped.
+  Added tests in png.h to include "trans" and "trans_values" in structures
+    when PNG_READ_BACKGROUND_SUPPORTED or PNG_READ_EXPAND_SUPPORTED is defined.
+  Add png_free(png_ptr->time_buffer) in png_destroy_read_struct()
+  Moved png_convert_to_rfc_1123() from pngwrite.c to png.c
+  Added capability for user-provided malloc_fn() and free_fn() functions,
+    and revised pngtest.c to demonstrate their use, replacing the
+    PNGTEST_DEBUG_MEM feature.
+  Added makefile.w32, for Microsoft C++ 4.0 and later (Tim Wegner).
+version 1.0.2 [June 14, 1998]
+  Fixed two bugs in makefile.bor .
+version 1.0.2a [December 30, 1998]
+  Replaced and extended code that was removed from png_set_filler() in 1.0.1a.
+  Fixed a bug in png_do_filler() that made it fail to write filler bytes in
+    the left-most pixel of each row (Kevin Bracey).
+  Changed "static pngcharp tIME_string" to "static char tIME_string[30]"
+    in pngtest.c (Duncan Simpson).
+  Fixed a bug in pngtest.c that caused pngtest to try to write a tIME chunk
+    even when no tIME chunk was present in the source file.
+  Fixed a problem in pngrutil.c: gray_to_rgb didn't always work with 16-bit.
+  Fixed a problem in png_read_push_finish_row(), which would not skip some
+    passes that it should skip, for images that are less than 3 pixels high.
+  Interchanged the order of calls to png_do_swap() and png_do_shift()
+    in pngwtran.c (John Cromer).
+  Added #ifdef PNG_DEBUG/#endif surrounding use of PNG_DEBUG in png.h .
+  Changed "bad adaptive filter type" from error to warning in pngrutil.c .
+  Fixed a documentation error about default filtering with 8-bit indexed-color.
+  Separated the PNG_NO_STDIO macro into PNG_NO_STDIO and PNG_NO_CONSOLE_IO
+    (L. Peter Deutsch).
+  Added png_set_rgb_to_gray() and png_get_rgb_to_gray_status() functions.
+  Added png_get_copyright() and png_get_header_version() functions.
+  Revised comments on png_set_progressive_read_fn() in libpng.txt and example.c
+  Added information about debugging in libpng.txt and libpng.3 .
+  Changed "ln -sf" to "ln -s -f" in makefile.s2x, makefile.lnx, and makefile.sco.
+  Removed lines after Dynamic Dependencies" in makefile.aco .
+  Revised makefile.dec to make a shared library (Jeremie Petit).
+  Removed trailing blanks from all files. 
+version 1.0.2a [January 6, 1999]
+  Removed misplaced #endif and #ifdef PNG_NO_EXTERN near the end of png.h
+  Added "if" tests to silence complaints about unused png_ptr in png.h and png.c
+  Changed "check_if_png" function in example.c to return true (nonzero) if PNG.
+  Changed libpng.txt to demonstrate png_sig_cmp() instead of png_check_sig()
+    which is obsolete.
+version 1.0.3 [January 14, 1999]
+  Added makefile.hux, for Hewlett Packard HPUX 10.20 and 11.00 (Jim Rice)
+  Added a statement of Y2K compliance in png.h, libpng.1, and Y2KINFO.
index 4978740993f304546b2aaea6c5d54bed1bdce53a..554b7719494dc349f1973719ff1110b7a6d643be 100644 (file)
@@ -1,17 +1,17 @@
 
-Installing libpng version 1.0.1 March 15, 1998
+Installing libpng version 1.0.3 - January 14, 1999
 
 Before installing libpng, you must first install zlib.  zlib
 can usually be found wherever you got libpng.  zlib can be
 placed in another directory, at the same level as libpng.
 Note that your system might already have a preinstalled
-zlib, but you will still need to have access to the 
+zlib, but you will still need to have access to the
 zlib.h and zconf.h include files that correspond to the
 version of zlib that's installed.
 
 You can rename the directories that you downloaded (they
-might be called "libpng-1.0.1 or "lpng100" and "zlib-1.1.1"
-or "zlib111") so that you have directories called "zlib" and "libpng".
+might be called "libpng-1.0.3" or "lpng103" and "zlib-1.1.3"
+or "zlib113") so that you have directories called "zlib" and "libpng".
 
 Your directory structure should look like this:
 
@@ -42,6 +42,7 @@ include
       makefile.std  =>  Generic UNIX makefile
       makefile.knr  =>  Archaic UNIX Makefile that converts files with ansi2knr
       makefile.dec  =>  DEC Alpha UNIX makefile
+      makefile.hux  =>  HPUX (10.20 and 11.00) makefile
       makefile.sgi  =>  Silicon Graphics IRIX makefile
       makefile.sun  =>  Sun makefile
       makefile.s2x  =>  Solaris 2.X makefile (gcc, creates libpng.so.2.1.0)
@@ -56,11 +57,14 @@ include
       build.bat     =>  MS-DOS batch file for Borland compiler
       makefile.dj2  =>  DJGPP 2 makefile
       makefile.msc  =>  Microsoft C makefile
+      makefile.w32  =>  makefile for Microsoft Visual C++ 4.0 and later
       makefile.tc3  =>  Turbo C 3.0 makefile
       makefile.os2  =>  OS/2 Makefile (gcc and emx, requires pngos2.def)
       pngos2.def    =>  OS/2 module definition file used by makefile.os2
       makefile.wat  =>  Watcom 10a+ Makefile, 32-bit flat memory model
       makevms.com   =>  VMS build script
+      pngdll.mak    =>  To make a png32bd.dll with Borland C++ 4.5
+      pngdef.pas    =>  Defines for a png32bd.dll with Borland C++ 4.5
 
 Copy the file (or files) that you need from the
 scripts directory into this directory, for example
index ea463cd9c51a9d564e8b553c9cf1c8c666583768..3bd089325a955b966af10c7cccd927e7dde8fac1 100644 (file)
@@ -1,4 +1,4 @@
-README for libpng 1.0.1 (shared library 2.1)
+README for libpng 1.0.3 - January 14, 1999 (shared library 2.1)
 See the note about version numbers near the top of png.h
 
 See INSTALL for instructions on how to install libpng.
@@ -159,6 +159,7 @@ Files in this distribution:
         makefile.std  =>  Generic UNIX makefile
         makefile.knr  =>  Archaic UNIX Makefile that converts files with ansi2knr
         makefile.dec  =>  DEC Alpha UNIX makefile
+        makefile.hux  =>  HPUX (10.20 and 11.00) makefile
         makefile.sgi  =>  Silicon Graphics IRIX makefile
         makefile.sun  =>  Sun makefile
         makefile.s2x  =>  Solaris 2.X makefile (gcc, creates libpng.so.2.1.0)
@@ -173,11 +174,14 @@ Files in this distribution:
         build.bat     =>  MS-DOS batch file for Borland compiler
         makefile.dj2  =>  DJGPP 2 makefile
         makefile.msc  =>  Microsoft C makefile
+        makefile.w32  =>  makefile for Microsoft Visual C++ 4.0 and later
         makefile.tc3  =>  Turbo C 3.0 makefile
         makefile.os2  =>  OS/2 Makefile (gcc and emx, requires pngos2.def)
         makefile.wat  =>  Watcom 10a+ Makefile, 32-bit flat memory model
         pngos2.def    =>  OS/2 module definition file used by makefile.os2
         makevms.com   =>  VMS build script
+        pngdll.mak    =>  To make a png32bd.dll with Borland C++ 4.5
+        pngdef.pas    =>  Defines for a png32bd.dll with Borland C++ 4.5
 
 Good luck, and happy coding.
 
index 562859a22fca18b13e29a91024e11b8b5f89eb78..52f32b8949809a14b39c892165731bcecfcc3118 100644 (file)
@@ -1,22 +1,24 @@
-TODO - list of things to do for libpng
+TODO - list of things to do for libpng:
 
-fix problem with C++ and EXTERN "C"
-add "grayscale->palette" transformation and "palette->grayscale" detection
-add "grayscale" -> "grayscale+alpha" and "grayscale+FILLER" transformations
-improved dithering
-multi-lingual error and warning message support
-sPLT chunk handling
-cHRM transformation
-complete sRGB transformation (presently it simply uses gamma=0.45)
-man pages for function calls
-high-level API for reading images
-final bug fixes
-better documentation
-better filter selection
-   (counting huffman bits/precompression?  filter inertia?  filter costs?)
-optional palette creation
-histogram creation
-support for application-defined chunk handlers
-keep up with public chunks
-better C++ wrapper/full C++ implementation?
-text conversion between different code pages (Latin-1 -> Mac and DOS)
+Final bug fixes.
+Fix problem with C++ and EXTERN "C".
+Better C++ wrapper/full C++ implementation?
+Keep up with public chunks.
+sPLT chunk handling.
+cHRM transformation.
+Support for application-defined chunk handlers.
+Improve setjmp/longjmp usage or remove it in favor of returning error codes.
+High-level API for reading images.
+Add "grayscale->palette" transformation and "palette->grayscale" detection.
+Color to gray transformation.
+Improved dithering.
+Multi-lingual error and warning message support.
+Complete sRGB transformation (presently it simply uses gamma=0.45455).
+Man pages for function calls.
+Better documentation.
+Better filter selection
+   (counting huffman bits/precompression?  filter inertia?  filter costs?).
+Optional palette (sPLT) creation.
+Histogram creation.
+Text conversion between different code pages (Latin-1 -> Mac and DOS).
+Improve API by hiding the info_ptr.
index 4e05fc2d321aff643f0885bb12b1a7a3eb16608b..dfb29a24483974568c55eb52f1147debc44fab3b 100644 (file)
@@ -1,7 +1,9 @@
 /* ansi2knr.c */
-/* Convert ANSI C function definitions to K&R ("traditional C") syntax */
 
-/*
+/* Convert ANSI C function definitions to K&R ("traditional C") syntax
+Copyright (C) 1989 Aladdin Enterprises.  All rights reserved.
+Copyright (C) 1988 Richard M. Stallman
+
 ansi2knr is distributed in the hope that it will be useful, but WITHOUT ANY
 WARRANTY.  No author or distributor accepts responsibility to anyone for the
 consequences of using it or for whether it serves any particular purpose or
@@ -12,12 +14,12 @@ Everyone is granted permission to copy, modify and redistribute ansi2knr,
 but only under the conditions described in the GPL.  A copy of this license
 is supposed to have been given to you along with ansi2knr so you can know
 your rights and responsibilities.  It should be in a file named COPYLEFT.
-[In the IJG distribution, the GPL appears below, not in a separate file.]
+[In the LIBPNG distribution, the GPL appears below, not in a separate file.]
 Among other things, the copyright notice and this notice must be preserved
 on all copies.
 
 We explicitly state here what we believe is already implied by the GPL: if
-the ansi2knr program is distributed as a separate set of sources and a
+the ansi2knr program is distributed as a separate source file and a
 separate executable file which are aggregated on a storage medium together
 with another program, this in itself does not bring the other program under
 the GPL, nor does the mere fact that such a program or the procedures for
@@ -27,7 +29,7 @@ program under the GPL.
 
 /*
 ---------- Here is the GNU GPL file COPYLEFT, referred to above ----------
------ These terms do NOT apply to the JPEG software itself; see README ------
+----- These terms do NOT apply to the LIBPNG software itself; see README ------
 
                    GHOSTSCRIPT GENERAL PUBLIC LICENSE
                    (Clarified 11 Feb 1988)
index 4b22852ee2e628f077aea79fd1f6301171b2bcdb..088aad3a764d5c073fc01b58c3286cfb636f5c23 100644 (file)
  * working PNG reader/writer, see pngtest.c, included in this distribution.
  */
 
-#include "../png/png.h"
+#include "png.h"
 
-/* Check to see if a file is a PNG file using png_sig_cmp().  Returns
- * non-zero if the image is a PNG, and 0 if it isn't a PNG.
+/* Check to see if a file is a PNG file using png_sig_cmp().  png_sig_cmp()
+ * returns zero if the image is a PNG and nonzero if it isn't a PNG.
+ *
+ * The function check_if_png() shown here, but not used, returns nonzero (true)
+ * if the file can be opened and is a PNG, 0 (false) otherwise.
  *
  * If this call is successful, and you are going to keep the file open,
  * you should call png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); once
@@ -41,12 +44,14 @@ int check_if_png(char *file_name, FILE **fp)
    if ((*fp = fopen(file_name, "rb")) != NULL);
       return 0;
 
-   /* Read in the signature bytes */
+   /* Read in some of the signature bytes */
    if (fread(buf, 1, PNG_BYTES_TO_CHECK, *fp) != PNG_BYTES_TO_CHECK)
       return 0;
 
-   /* Compare the first PNG_BYTES_TO_CHECK bytes of the signature. */
-   return(png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK));
+   /* Compare the first PNG_BYTES_TO_CHECK bytes of the signature.
+      Return nonzero (true) if they match */
+
+   return(!png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK));
 }
 
 /* Read a PNG file.  You may want to return an error code if the read
@@ -83,7 +88,7 @@ void read_png(FILE *fp, unsigned int sig_read)  /* file is already open */
     * was compiled with a compatible version of the library.  REQUIRED
     */
    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
-      (void *)user_error_ptr, user_error_fn, user_warning_fn);
+      png_voidp user_error_ptr, user_error_fn, user_warning_fn);
 
    if (png_ptr == NULL)
    {
@@ -220,11 +225,14 @@ void read_png(FILE *fp, unsigned int sig_read)  /* file is already open */
 
    if (png_get_sRGB(png_ptr, info_ptr, &intent))
       png_set_sRGB(png_ptr, intent, 0);
-   else 
+   else
+   {
+      double image_gamma;
       if (png_get_gAMA(png_ptr, info_ptr, &image_gamma))
          png_set_gamma(png_ptr, screen_gamma, image_gamma);
       else
-         png_set_gamma(png_ptr, screen_gamma, 0.50);
+         png_set_gamma(png_ptr, screen_gamma, 0.45455);
+   }
 
    /* Dither RGB files down to 8 bit palette or reduce palettes
     * to the number of colors available on your screen.
@@ -316,21 +324,21 @@ void read_png(FILE *fp, unsigned int sig_read)  /* file is already open */
 #ifdef single /* Read the image a single row at a time */
       for (y = 0; y < height; y++)
       {
-         png_bytep row_pointers = row[y];
-         png_read_rows(png_ptr, &row_pointers, NULL, 1);
+         png_read_rows(png_ptr, &row_pointers[y], NULL, 1);
       }
 
 #else no_single /* Read the image several rows at a time */
       for (y = 0; y < height; y += number_of_rows)
       {
 #ifdef sparkle /* Read the image using the "sparkle" effect. */
-         png_read_rows(png_ptr, row_pointers, NULL, number_of_rows);
-        
+         png_read_rows(png_ptr, &row_pointers[y], NULL, number_of_rows);
+
+         png_read_rows(png_ptr, NULL, row_pointers[y], number_of_rows);
 #else no_sparkle /* Read the image using the "rectangle" effect */
-         png_read_rows(png_ptr, NULL, row_pointers, number_of_rows);
+         png_read_rows(png_ptr, NULL, &row_pointers[y], number_of_rows);
 #endif no_sparkle /* use only one of these two methods */
       }
-     
+
       /* if you want to display the image after every pass, do
          so here */
 #endif no_single /* use only one of these two methods */
@@ -362,7 +370,7 @@ initialize_png_reader(png_structp *png_ptr, png_infop *info_ptr)
     * linked libraries.
     */
    *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
-       (void *)user_error_ptr, user_error_fn, user_warning_fn);
+       png_voidp user_error_ptr, user_error_fn, user_warning_fn);
 
    if (*png_ptr == NULL)
    {
@@ -384,8 +392,11 @@ initialize_png_reader(png_structp *png_ptr, png_infop *info_ptr)
       return ERROR;
    }
 
-   /* this one's new.  You will need to provide all three
+   /* This one's new.  You will need to provide all three
     * function callbacks, even if you aren't using them all.
+    * If you aren't using all functions, you can specify NULL
+    * parameters.  Even when all three functions are NULL,
+    * you need to call png_set_progressive_read_fn().
     * These functions shouldn't be dependent on global or
     * static variables if you are decoding several images
     * simultaneously.  You should store stream specific data
@@ -498,7 +509,7 @@ void write_png(char *file_name /* , ... other image information ... */)
     * in case we are using dynamically linked libraries.  REQUIRED.
     */
    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
-      (void *)user_error_ptr, user_error_fn, user_warning_fn);
+      png_voidp user_error_ptr, user_error_fn, user_warning_fn);
 
    if (png_ptr == NULL)
    {
@@ -565,7 +576,7 @@ void write_png(char *file_name /* , ... other image information ... */)
    sig_bit.alpha = true_alpha_bit_depth;
    png_set_sBIT(png_ptr, info_ptr, sig_bit);
 
-  
+
    /* Optional gamma chunk is strongly suggested if you have any guess
     * as to the correct gamma of the image.
     */
@@ -581,7 +592,7 @@ void write_png(char *file_name /* , ... other image information ... */)
    text_ptr[2].key = "Description";
    text_ptr[2].text = "<long text>";
    text_ptr[2].compression = PNG_TEXT_COMPRESSION_zTXt;
-   png_set_text(png_ptr, info_ptr, text_ptr, 2);
+   png_set_text(png_ptr, info_ptr, text_ptr, 3);
 
    /* other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs, */
    /* note that if sRGB is present the cHRM chunk must be ignored
@@ -638,7 +649,11 @@ void write_png(char *file_name /* , ... other image information ... */)
     * layout, however, so choose what fits your needs best).  You need to
     * use the first method if you aren't handling interlacing yourself.
     */
-   png_byte row_pointers[height][width];
+   png_uint_32 k, height, width;
+   png_byte image[height][width];
+   png_bytep row_pointers[height];
+   for (k = 0; k < height; k++)
+     row_pointers[k] = image + k*width;
 
    /* One of the following output methods is REQUIRED */
 #ifdef entire /* write out the entire image data in one call */
@@ -653,13 +668,12 @@ void write_png(char *file_name /* , ... other image information ... */)
    for (pass = 0; pass < number_passes; pass++)
    {
       /* Write a few rows at a time. */
-      png_write_rows(png_ptr, row_pointers, number_of_rows);
+      png_write_rows(png_ptr, &row_pointers[first_row], number_of_rows);
 
       /* If you are only writing one row at a time, this works */
       for (y = 0; y < height; y++)
       {
-         png_bytep row_pointers = row[y];
-         png_write_rows(png_ptr, &row_pointers, 1);
+         png_write_rows(png_ptr, &row_pointers[y], 1);
       }
    }
 #endif no_entire /* use only one output method */
index 88d8c9642c80bd95415cabedc2122ffe89b06cbd..f970736092d903347885db3f637fca2276b273e4 100644 (file)
@@ -1,6 +1,6 @@
-.TH LIBPNG 3 "March 15, 1998"
+.TH LIBPNG 3 "January 14, 1999"
 .SH NAME
-libpng \- Portable Network Graphics (PNG) Reference Library
+libpng \- Portable Network Graphics (PNG) Reference Library 1.0.3 - January 14, 1999
 .SH SYNOPSIS
 
 #include <png.h>
@@ -27,14 +27,25 @@ png_structp png_create_read_struct (png_const_charp
 user_png_ver, voidp error_ptr, png_error_ptr error_fn,
 png_error_ptr warn_fn);
 
+png_structp png_create_read_struct_2(png_const_charp user_png_ver,
+png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr
+warn_fn, png_voidp mem_ptr, png_malloc_ptr malloc_fn,
+png_free_ptr free_fn)
+
 png_structp png_create_write_struct (png_const_charp
 user_png_ver, voidp error_ptr, png_error_ptr error_fn,
 png_error_ptr warn_fn);
 
-void png_debug_free (png_structp png_ptr, png_voidp ptr);
+png_structp png_create_write_struct_2(png_const_charp
+user_png_ver, png_voidp error_ptr, png_error_ptr error_fn,
+png_error_ptr warn_fn, png_voidp mem_ptr,
+png_malloc_ptr malloc_fn, png_free_ptr free_fn)
+
+int png_debug(int level, png_const_charp message)
+
+int png_debug1(int level, png_const_charp message, p1)
 
-png_voidp png_debug_malloc (png_structp png_ptr, png_uint_32
-size);
+int png_debug2(int level, png_const_charp message, p1, p2)
 
 void png_destroy_info_struct (png_structp png_ptr, png_infopp
 info_ptr_ptr);
@@ -49,6 +60,8 @@ void png_error (png_structp png_ptr, png_const_charp error);
 
 void png_free (png_structp png_ptr, png_voidp ptr);
 
+void png_free_default(png_structp png_ptr, png_voidp ptr)
+
 png_byte png_get_bit_depth (png_structp png_ptr, png_infop
 info_ptr);
 
@@ -69,6 +82,8 @@ info_ptr);
 png_byte png_get_compression_type (png_structp png_ptr,
 png_infop info_ptr);
 
+png_byte png_get_copyright (png_structp png_ptr);
+
 png_voidp png_get_error_ptr (png_structp png_ptr);
 
 png_byte png_get_filter_type (png_structp png_ptr, png_infop
@@ -77,9 +92,16 @@ info_ptr);
 png_uint_32 png_get_gAMA (png_structp png_ptr, png_infop
 info_ptr, double *file_gamma);
 
+png_byte png_get_header_version (png_structp png_ptr);
+
 png_uint_32 png_get_hIST (png_structp png_ptr, png_infop
 info_ptr, png_uint_16p *hist);
 
+png_uint_32 png_get_IHDR (png_structp png_ptr, png_infop
+info_ptr, png_uint_32 *width, png_uint_32 *height, int
+*bit_depth, int *color_type, int *interlace_type, int
+*compression_type, int *filter_type);
+
 png_uint_32 png_get_image_height (png_structp png_ptr,
 png_infop info_ptr);
 
@@ -91,10 +113,7 @@ info_ptr);
 
 png_voidp png_get_io_ptr (png_structp png_ptr);
 
-png_uint_32 png_get_IHDR (png_structp png_ptr, png_infop
-info_ptr, png_uint_32 *width, png_uint_32 *height, int
-*bit_depth, int *color_type, int *interlace_type, int
-*compression_type, int *filter_type);
+png_voidp png_get_mem_ptr(png_structp png_ptr)
 
 png_uint_32 png_get_oFFs (png_structp png_ptr, png_infop
 info_ptr, png_uint_32 *offset_x, png_uint_32 *offset_y, int
@@ -119,6 +138,8 @@ png_voidp png_get_progressive_ptr (png_structp png_ptr);
 png_uint_32 png_get_PLTE (png_structp png_ptr, png_infop
 info_ptr, png_colorp *palette, int *num_palette);
 
+png_byte png_get_rgb_to_gray_status (png_structp png_ptr)
+
 png_uint_32 png_get_rowbytes (png_structp png_ptr, png_infop
 info_ptr);
 
@@ -168,6 +189,9 @@ void png_init_io (png_structp png_ptr, FILE *fp);
 
 png_voidp png_malloc (png_structp png_ptr, png_uint_32 size);
 
+png_voidp png_malloc_default(png_structp png_ptr,
+png_uint_32 size)
+
 voidp png_memcpy (png_voidp s1, png_voidp s2, png_size_t size);
 
 png_voidp png_memcpy_check (png_structp png_ptr, png_voidp s1,
@@ -276,6 +300,9 @@ png_uint_32 width, png_uint_32 height, int bit_depth, int
 color_type, int interlace_type, int compression_type, int
 filter_type);
 
+void png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr,
+png_malloc_ptr malloc_fn, png_free_ptr free_fn)
+
 void png_set_oFFs (png_structp png_ptr, png_infop info_ptr,
 png_uint_32 offset_x, png_uint_32 offset_y, int unit_type);
 
@@ -302,12 +329,12 @@ void png_set_read_fn (png_structp png_ptr, png_voidp io_ptr,
 png_rw_ptr read_data_fn);
 
 void png_set_read_status_fn (png_structp png_ptr, png_read_status_ptr
-   read_row_fn);
+read_row_fn);
 
 void png_set_read_user_transform_fn (png_structp png_ptr,
-   png_user_transform_ptr read_user_transform_fn);
+png_user_transform_ptr read_user_transform_fn);
 
-void png_set_rgb_to_gray (png_structp png_ptr);
+void png_set_rgb_to_gray (png_structp png_ptr, int error_action);
 
 void png_set_sBIT (png_structp png_ptr, png_infop info_ptr,
 png_color_8p sig_bit);
@@ -344,10 +371,10 @@ void png_set_write_fn (png_structp png_ptr, png_voidp io_ptr,
 png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn);
 
 void png_set_write_status_fn (png_structp png_ptr, png_write_status_ptr
-   write_row_fn);
+write_row_fn);
 
 void png_set_write_user_transform_fn (png_structp png_ptr,
-   png_user_transform_ptr write_user_transform_fn);
+png_user_transform_ptr write_user_transform_fn);
 
 int png_sig_cmp (png_bytep sig, png_size_t start, png_size_t
 num_to_check);
@@ -375,7 +402,7 @@ void png_write_destroy_info (png_infop info_ptr);
 void png_write_end (png_structp png_ptr, png_infop info_ptr);
 
 void png_write_flush (png_structp png_ptr);
+
 void png_write_image (png_structp png_ptr, png_bytepp image);
 
 void png_write_info (png_structp png_ptr, png_infop info_ptr);
@@ -396,17 +423,17 @@ Following is a copy of the libpng.txt file that accompanies libpng.
 .SH LIBPNG.TXT
 libpng.txt - A description on how to use and modify libpng
 
- libpng version 1.0.1 March 15, 1998
+ libpng version 1.0.3 - January 14, 1999
  Updated and distributed by Glenn Randers-Pehrson
  <randeg@alumni.rpi.edu>
- Copyright (c) 1998, Glenn Randers-Pehrson
+ Copyright (c) 1998, 1999 Glenn Randers-Pehrson
  For conditions of distribution and use, see copyright
  notice in png.h.
 
  based on:
 
  libpng 1.0 beta 6  version 0.96 May 28, 1997
- Updated and distributed by Andreas Dilger 
+ Updated and distributed by Andreas Dilger
  Copyright (c) 1996, 1997 Andreas Dilger
 
  libpng 1.0 beta 2 - version 0.88  January 26, 1996
@@ -436,7 +463,8 @@ as RFC 2083 <ftp://ftp.uu.net/graphics/png/documents/> and as a
 W3C Recommendation <http://www.w3.org/TR/REC.png.html>. Some
 additional chunks are described in the special-purpose public chunks
 documents at <ftp://ftp.uu.net/graphics/png/documents/>.  Other information
-about PNG can be found at the PNG home page, <http://www.cdrom.com/pub/png/>.
+about PNG, and the latest version of libpng, can be found at the PNG home
+page, <http://www.cdrom.com/pub/png/>.
 
 Most users will not have to modify the library significantly; advanced
 users may want to modify it more.  All attempts were made to make it as
@@ -453,6 +481,8 @@ work to be done (see the TODO file), libpng should cover the
 majority of the needs of its users.
 
 Libpng uses zlib for its compression and decompression of PNG files.
+Further information about zlib, and the latest version of zlib, can
+be found at the zlib home page, <http://www.cdrom.com/pub/infozip/zlib/>.
 The zlib compression utility is a general purpose utility that is
 useful for more than PNG files, and can be used without libpng.
 See the documentation delivered with zlib for more details.
@@ -522,7 +552,7 @@ Customizing libpng.
         return;
     }
     fread(header, 1, number, fp);
-    is_png = png_check_sig(header, 0, number);
+    is_png = !png_sig_cmp(header, 0, number);
     if (!is_png)
     {
         return;
@@ -539,7 +569,7 @@ be NULL if the default error handlers are to be used).  See the section
 on Changes to Libpng below regarding the old initialization functions.
 
     png_structp png_ptr = png_create_read_struct
-       (PNG_LIBPNG_VER_STRING, (void *)user_error_ptr,
+       (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
         user_error_fn, user_warning_fn);
     if (!png_ptr)
         return;
@@ -560,12 +590,23 @@ on Changes to Libpng below regarding the old initialization functions.
         return;
     }
 
+If you want to use your own memory allocation routines,
+define PNG_USER_MEM_SUPPORTED and use
+png_create_read_struct_2() instead of png_create_read_struct():
+
+    png_structp png_ptr = png_create_read_struct_2
+       (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
+        user_error_fn, user_warning_fn, (png_voidp)
+        user_mem_ptr, user_malloc_fn, user_free_fn);
+
+The error handling routines passed to png_create_read_struct()
+and the memory alloc/free routines passed to png_create_struct_2()
+are only necessary if you are not using the libpng supplied error
+handling and memory alloc/free functions.
 
-The error handling routines passed to png_create_read_struct() are only
-necessary if you are not using the libpng supplied error handling
-functions.  When libpng encounters an error, it expects to longjmp back
-to your routine.  Therefore, you will need to call setjmp and pass the
-jmpbuf field of your png_struct.  If you read the file from different
+When libpng encounters an error, it expects to longjmp back
+to your routine.  Therefore, you will need to call setjmp and pass
+your png_ptr->jmpbuf.  If you read the file from different
 routines, you will need to update the jmpbuf field every time you enter
 a new routine that will call a png_ function.
 
@@ -638,7 +679,7 @@ with
 You must supply the function
 
     void read_transform_fn(png_ptr ptr, row_info_ptr
-       row_info, png_bytep data) 
+       row_info, png_bytep data)
 
 See pngtest.c for a working example.  Your function will be called
 after all of the other transformations have been processed.
@@ -667,7 +708,7 @@ Functions are used to get the information from the info_ptr:
                          are present.
                      PNG_COLOR_TYPE_GRAY
                         (bit depths 1, 2, 4, 8, 16)
-                     PNG_COLOR_TYPE_GRAY_ALPHA  
+                     PNG_COLOR_TYPE_GRAY_ALPHA
                         (bit depths 8, 16)
                      PNG_COLOR_TYPE_PALETTE
                         (bit depths 1, 2, 4, 8)
@@ -872,11 +913,14 @@ unless the library has been told to transform it into another format.
 For example, 4 bit/pixel paletted or grayscale data will be returned
 2 pixels/byte with the leftmost pixel in the high-order bits of the
 byte, unless png_set_packing() is called.  8-bit RGB data will be stored
-in RGBRGBRGB format unless png_set_filler() is called to insert filler
+in RGB RGB RGB format unless png_set_filler() is called to insert filler
 bytes, either before or after each RGB triplet.  16-bit RGB data will
-be returned RRGGBBRRGGBB, with the most significant byte of the color
+be returned RRGGBB RRGGBB, with the most significant byte of the color
 value first, unless png_set_strip_16() is called to transform it to
-regular RGBRGB triplets.
+regular RGB RGB triplets, or png_set_filler() is called to insert
+filler bytes, either before or after each RRGGBB triplet.  Similarly,
+8-bit or 16-bit grayscale data can be modified with png_set_filler()
+or png_set_strip_16().
 
 The following code transforms grayscale images of less than 8 to 8 bits,
 changes paletted images to RGB, and adds a full alpha channel if there is
@@ -952,7 +996,7 @@ into 4 bytes for windowing systems that need them in this format:
         PNG_COLOR_TYPE_RGB) png_set_filler(png_ptr,
         filler, PNG_FILLER_BEFORE);
 
-where "filler" is the number to fill with, and the location is
+where "filler" is the 8 or 16-bit number to fill with, and the location is
 either PNG_FILLER_BEFORE or PNG_FILLER_AFTER, depending upon whether
 you want the filler before the RGB or after.  This transformation
 does not affect images that already have full alpha channels.
@@ -970,22 +1014,77 @@ RGB.  This code will do that conversion:
         color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
           png_set_gray_to_rgb(png_ptr);
 
+Conversely, you can convert an RGB or RGBA image to grayscale or grayscale
+with alpha.  This is intended for conversion of images that really are
+gray (red == green == blue), so the function simply strips out the red
+and blue channels, leaving the green channel in the gray position.
+
+    if (color_type == PNG_COLOR_TYPE_RGB ||
+        color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+          png_set_rgb_to_gray(png_ptr, error_action,
+             float red_weight, float green_weight);
+
+    error_action = 1: silently do the conversion
+    error_action = 2: issue a warning if the original
+                      image has any pixel where
+                      red != green or red != blue
+    error_action = 3: issue an error and abort the
+                      conversion if the original
+                      image has any pixel where
+                      red != green or red != blue
+
+    red_weight:       weight of red component
+                      (NULL -> default 54/256)
+    green_weight:     weight of green component
+                      (NULL -> default 183/256)
+
+If you have set error_action = 1 or 2, you can
+later check whether the image really was gray, after processing
+the image rows, with the png_get_rgb_to_gray_status(png_ptr) function.
+It will return a png_byte that is zero if the image was gray or
+1 if there were any non-gray pixels.  bKGD and sBIT data
+will be silently converted to grayscale, using the green channel
+data, regardless of the error_action setting.
+
+With 0.0<=red_weight+green_weight<=1.0,
+the normalized graylevel is computed:
+
+    int rw = red_weight * 256;
+    int gw = green_weight * 256;
+    int bw = 256 - (rw + gw);
+    gray = (rw*red + gw*green + bw*blue)/256;
+
+The default values approximate those recommended in the Charles
+Poynton's Color FAQ, <http://www.inforamp.net/~poynton/>
+Copyright (c) 1998-01-04 Charles Poynton poynton@inforamp.net
+
+    Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
+
+Libpng approximates this with
+
+    Y = 0.211 * R    + 0.715 * G    + 0.074 * B
+
+which can be expressed with integers as
+
+    Y = (54 * R + 183 * G + 19 * B)/256
+
+The calculation is done in a linear colorspace, if the image gamma
+is known.
+
 If you have a grayscale and you are using png_set_expand() to change to
-a higher bit-depth you must indicate if the supplied background gray
-is supplied in the original file bit depth (need_expand = 1) or in the
-expanded bit depth (need_expand = 0).  Similarly, if you are reading
-a paletted image, you must indicate if you have supplied the background
-as a palette index that needs to be expanded (need_expand = 1).  You can
-also specify an RGB triplet that isn't in the palette when setting your
-background for a paletted image.
+a higher bit-depth, you must either supply the background color as a gray
+value at the original file bit-depth (need_expand = 1) or else supply the
+background color as an RGB triplet at the final, expanded bit depth
+(need_expand = 0).  Similarly, if you are reading a paletted image, you
+must either supply the background color as a palette index (need_expand = 1)
+or as an RGB triplet that may or may not be in the palette (need_expand = 0).
 
     png_color_16 my_background;
     png_color_16p image_background;
 
-    if (png_get_bKGD(png_ptr, info_ptr,
-        &image_background))
-        png_set_background(png_ptr, image_background),
-        PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
+    if (png_get_bKGD(png_ptr, info_ptr, &image_background))
+        png_set_background(png_ptr, image_background,
+          PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
     else
         png_set_background(png_ptr, &my_background,
           PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
@@ -1031,7 +1130,7 @@ compensation other than the display_gamma is needed (viewing_gamma=1.0).
 The png_set_gamma() function handles gamma transformations of the data.
 Pass both the file gamma and the current screen_gamma.  If the file does
 not have a gamma value, you can pass one anyway if you have an idea what
-it is (usually 0.50 is a good guess for GIF images on PCs).  Note
+it is (usually 0.45455 is a good guess for GIF images on PCs).  Note
 that file gammas are inverted from screen gammas.  See the discussions
 on gamma in the PNG specification for an excellent description of what
 gamma is, and why all applications should support it.  It is strongly
@@ -1040,7 +1139,7 @@ recommended that PNG viewers support gamma correction.
    if (png_get_gAMA(png_ptr, info_ptr, &gamma))
       png_set_gamma(png_ptr, screen_gamma, gamma);
    else
-      png_set_gamma(png_ptr, screen_gamma, 0.50);
+      png_set_gamma(png_ptr, screen_gamma, 0.45455);
 
 If you need to reduce an RGB file to a paletted file, or if a paletted
 file has more entries then will fit on your screen, png_set_dither()
@@ -1268,7 +1367,7 @@ png_infop info_ptr;
  initialize_png_reader()
  {
     png_ptr = png_create_read_struct
-        (PNG_LIBPNG_VER_STRING, (void *)user_error_ptr,
+        (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
          user_error_fn, user_warning_fn);
     if (!png_ptr)
         return -1;
@@ -1291,7 +1390,9 @@ png_infop info_ptr;
        to be called when the header info is valid,
        when each row is completed, and when the image
        is finished.  If you aren't using all functions,
-       you can specify a NULL parameter.  You can use
+       you can specify NULL parameters.  Even when all
+       three functions are NULL, you need to call
+       png_set_progressive_read_fn().  You can use
        any struct as the user_ptr (cast to a void pointer
        for the function call), and retrieve the pointer
        from inside the callbacks using the function
@@ -1323,21 +1424,21 @@ png_infop info_ptr;
        of data from the file stream (in order, of
        course).  On machines with segmented memory
        models machines, don't give it any more than
-       64K.  The library seems to run fine with sizes 
+       64K.  The library seems to run fine with sizes
        of 4K. Although you can give it much less if
        necessary (I assume you can give it chunks of
        1 byte, I haven't tried less then 256 bytes
        yet).  When this function returns, you may
        want to display any rows that were generated
        in the row callback if you don't already do
-       so there. 
+       so there.
      */
     png_process_data(png_ptr, info_ptr, buffer, length);
     return 0;
  }
 
  /* This function is called (as set by
-    png_set_progressive_fn() above) when enough data
+    png_set_progressive_read_fn() above) when enough data
     has been supplied so all of the header has been
     read.
  */
@@ -1387,14 +1488,14 @@ png_infop info_ptr;
           new_row);
 
     /* where old_row is what was displayed for
-       previous rows.  Note that the first pass
-       (pass == 0, really) will completely cover
+       previously for the row.  Note that the first
+       pass (pass == 0, really) will completely cover
        the old row, so the rows do not have to be
        initialized.  After the first pass (and only
        for interlaced images), you will have to pass
        the current row, and the function will combine
        the old row and the new row.
-    */  
+    */
  }
 
  void
@@ -1412,6 +1513,8 @@ png_infop info_ptr;
      */
  }
 
+
+
 .SH IV. Writing
 
 Much of this is very similar to reading.  However, everything of
@@ -1422,7 +1525,7 @@ You will want to do the I/O initialization before you get into libpng,
 so if it doesn't work, you don't have anything to undo. If you are not
 using the standard I/O functions, you will need to replace them with
 custom writing functions.  See the discussion under Customizing libpng.
-    
+
     FILE *fp = fopen(file_name, "wb");
     if (!fp)
     {
@@ -1438,7 +1541,7 @@ both "png_ptr"; you can call them anything you like, such as
 "read_ptr" and "write_ptr".  Look at pngtest.c, for example.
 
     png_structp png_ptr = png_create_write_struct
-       (PNG_LIBPNG_VER_STRING, (void *)user_error_ptr,
+       (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
         user_error_fn, user_warning_fn);
     if (!png_ptr)
        return;
@@ -1451,23 +1554,34 @@ both "png_ptr"; you can call them anything you like, such as
        return;
     }
 
+If you want to use your own memory allocation routines,
+define PNG_USER_MEM_SUPPORTED and use
+png_create_write_struct_2() instead of png_create_read_struct():
+
+    png_structp png_ptr = png_create_write_struct_2
+       (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
+        user_error_fn, user_warning_fn, (png_voidp)
+        user_mem_ptr, user_malloc_fn, user_free_fn);
+
 After you have these structures, you will need to set up the
 error handling.  When libpng encounters an error, it expects to
 longjmp() back to your routine.  Therefore, you will need to call
-setjmp and pass the jmpbuf field of your png_struct.  If you
+setjmp() and pass the png_ptr->jmpbuf.  If you
 write the file from different routines, you will need to update
 the jmpbuf field every time you enter a new routine that will
 call a png_ function.  See your documentation of setjmp/longjmp
 for your compiler for more information on setjmp/longjmp.  See
 the discussion on libpng error handling in the Customizing Libpng
 section below for more information on the libpng error handling.
-    
+
     if (setjmp(png_ptr->jmpbuf))
-    {    
+    {
         png_destroy_write_struct(&png_ptr, &info_ptr);
         fclose(fp);
         return;
     }
+    ...
+    return;
 
 Now you need to set up the output code.  The default for libpng is to
 use the C function fwrite().  If you use this, you will need to pass a
@@ -1504,11 +1618,11 @@ not calling this function at all, as it has been tuned to deliver a good
 speed/compression ratio. The second parameter to png_set_filter() is
 the filter method, for which the only valid value is '0' (as of the
 October 1996 PNG specification, version 1.0).  The third parameter is a
-flag that indicates
-which filter type(s) are to be tested for each scanline.  See the
-Compression Library for details on the specific filter types.
+flag that indicates which filter type(s) are to be tested for each
+scanline.  See the Compression Library for details on the specific filter
+types.
+
 
-    
     /* turn on or off filtering, and/or choose
        specific filters */
     png_set_filter(png_ptr, 0,
@@ -1607,7 +1721,7 @@ Some of the more important parts of the png_info are:
                      PNG_SRGB_INTENT_PERCEPTUAL,
                      PNG_SRGB_INTENT_ABSOLUTE, or
                      PNG_SRGB_INTENT_RELATIVE.
-                        
+
 
     png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr,
        srgb_intent);
@@ -1698,7 +1812,7 @@ png_text structure holds a keyword-text value, and a compression type.
 The compression types have the same valid numbers as the compression
 types of the image data.  Currently, the only valid number is zero.
 However, you can store text either compressed or uncompressed, unlike
-images which always have to be compressed.  So if you don't want the
+images, which always have to be compressed.  So if you don't want the
 text compressed, set the compression type to PNG_TEXT_COMPRESSION_NONE.
 Until text gets around 1000 bytes, it is not worth compressing it.
 After the text has been written out to the file, the compression type
@@ -1758,7 +1872,7 @@ depending on whether you mean the PNG file, the time the image was
 created in a non-PNG format, a still photo from which the image was
 scanned, or possibly the subject matter itself.  In order to facilitate
 machine-readable dates, it is recommended that the "Creation Time"
-tEXt chunk use RFC 1123 format dates (e.g. 22 May 1997 18:07:10 GMT"),
+tEXt chunk use RFC 1123 format dates (e.g. "22 May 1997 18:07:10 GMT"),
 although this isn't a requirement.  Unlike the tIME chunk, the
 "Creation Time" tEXt chunk is not expected to be automatically changed
 by the software.  To facilitate the use of RFC 1123 dates, a function
@@ -1780,8 +1894,9 @@ checks to see if it has data that it can do something with, you should
 make sure to only enable a transformation if it will be valid for the
 data.  For example, don't swap red and blue on grayscale data.
 
-PNG files store RGB pixels packed into 3 bytes.  This code tells
-the library to expect input data with 4 bytes per pixel
+PNG files store RGB pixels packed into 3 or 6 bytes.  This code tells
+the library to expand the input data to 4 or 8 bytes per pixel
+(or expand 1 or 2-byte grayscale data to 2 or 4 bytes per pixel).
 
     png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
 
@@ -1799,7 +1914,7 @@ correctly pack the pixels into a single byte:
 PNG files reduce possible bit depths to 1, 2, 4, 8, and 16.  If your
 data is of another bit depth, you can write an sBIT chunk into the
 file so that decoders can get the original data if desired.
-    
+
     /* Set the true bit depth of the image data */
     if (color_type & PNG_COLOR_MASK_COLOR)
     {
@@ -1860,7 +1975,7 @@ with
 You must supply the function
 
     void write_transform_fn(png_ptr ptr, row_info_ptr
-       row_info, png_bytep data) 
+       row_info, png_bytep data)
 
 See pngtest.c for a working example.  Your function will be called
 before any of the other transformations have been processed.
@@ -1899,11 +2014,11 @@ times, or any of that other stuff necessary with png_write_rows().
 
 where row_pointers is:
 
-    png_bytef *row_pointers[height];
+    png_byte *row_pointers[height];
 
 You can point to void or char or whatever you use for pixels.
 
-If you can't want to write the whole image at once, you can
+If you don't want to write the whole image at once, you can
 use png_write_rows() instead.  If the file is not interlaced,
 this is simple:
 
@@ -1975,7 +2090,7 @@ The second deals with more complicated things like adding new chunks,
 adding new transformations, and generally changing how libpng works.
 
 All of the memory allocation, input/output, and error handling in libpng
-goes through callbacks which are user settable.  The default routines are
+goes through callbacks that are user settable.  The default routines are
 in pngmem.c, pngrio.c, pngwio.c, and pngerror.c respectively.  To change
 these functions, call the appropriate png_set_???_fn() function.
 
@@ -1997,14 +2112,15 @@ time, instead of calling the png_init_io() function.  These functions
 also provide a void pointer that can be retrieved via the function
 png_get_io_ptr().  For example:
 
-    png_set_read_fn(png_structp png_ptr,
-        voidp io_ptr, png_rw_ptr read_data_fn)
+    png_set_read_fn(png_structp read_ptr,
+        voidp read_io_ptr, png_rw_ptr read_data_fn)
 
-    png_set_write_fn(png_structp png_ptr,
-        voidp io_ptr, png_rw_ptr write_data_fn,
+    png_set_write_fn(png_structp write_ptr,
+        voidp write_io_ptr, png_rw_ptr write_data_fn,
         png_flush_ptr output_flush_fn);
 
-    voidp io_ptr = png_get_io_ptr(png_ptr);
+    voidp read_io_ptr = png_get_io_ptr(read_ptr);
+    voidp write_io_ptr = png_get_io_ptr(write_ptr);
 
 The replacement I/O functions should have prototypes as follows:
 
@@ -2083,7 +2199,7 @@ won't be accessible.  So limit zlib and libpng to 64K by defining MAXSEG_64K.
 
 Configuring for DOS:
 
-For DOS users which only have access to the lower 640K, you will
+For DOS users who only have access to the lower 640K, you will
 have to limit zlib's memory usage via a png_set_compression_mem_level()
 call.  See zlib.h or zconf.h in the zlib library for more information.
 
@@ -2095,7 +2211,7 @@ defined, and FAR gets defined to far in pngconf.h, and you should be
 all set.  Everything in the library (except for zlib's structure) is
 expecting far data.  You must use the typedefs with the p or pp on
 the end for pointers (or at least look at them and be careful).  Make
-note that the row's of data are defined as png_bytepp which is a
+note that the row's of data are defined as png_bytepp, which is an
 unsigned char far * far *.
 
 Configuring for gui/windowing platforms:
@@ -2155,8 +2271,8 @@ can call one of these functions.  The selection and configuration
 of row filters can have a significant impact on the size and
 encoding speed and a somewhat lesser impact on the decoding speed
 of an image.  Filtering is enabled by default for RGB and grayscale
-images (with and without alpha), and for 8-bit paletted images, but
-not for paletted images with bit depths less than 8 bits/pixel.
+images (with and without alpha), but not for paletted images nor
+for any images with bit depths less than 8 bits/pixel.
 
 The 'method' parameter sets the main filtering method, which is
 currently only '0' in the PNG 1.0 specification.  The 'filters'
@@ -2191,10 +2307,10 @@ by telling it the relative computational costs of the filters.
        PNG_FILTER_SELECTION_WEIGHTED, 3,
        weights, costs);
 
-The weights are multiplying factors which indicate to libpng that row
-should be the same for successive rows unless another row filter is that
-many times better than the previous filter.  In the above example, if
-the previous 3 filters were SUB, SUB, NONE, the SUB filter could have a
+The weights are multiplying factors that indicate to libpng that the
+row filter should be the same for successive rows unless another row filter
+is that many times better than the previous filter.  In the above example,
+if the previous 3 filters were SUB, SUB, NONE, the SUB filter could have a
 "sum of absolute differences" 1.5 x 1.3 times higher than other filters
 and still be chosen, while the NONE filter could have a sum 1.1 times
 higher than other filters and still be chosen.  Unspecified weights are
@@ -2217,19 +2333,23 @@ Removing unwanted object code:
 
 There are a bunch of #define's in pngconf.h that control what parts of
 libpng are compiled.  All the defines end in _SUPPORTED.  If you are
-never going to use an ability, you can change the #define to #undef
-before recompiling libpng and save yourself code and data space.
-You can also turn a number of them off en masse with a compiler directive
-that defines PNG_READ[or WRITE]_TRANSFORMS_NOT_SUPPORTED, or
-PNG_READ[or WRITE]_ANCILLARY_CHUNKS_NOT_SUPPORTED, or all four,
+never going to use a capability, you can change the #define to #undef
+before recompiling libpng and save yourself code and data space, or
+you can turn off individual capabilities with defines that begin with
+PNG_NO_.
+
+You can also turn all of the transforms and ancillary chunk capabilities
+off en masse with  compiler directives that define
+PNG_NO_READ[or WRITE]_TRANSFORMS, or PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS,
+or all four,
 along with directives to turn on any of the capabilities that you do
-want.  The PNG_READ[or WRITE]_TRANSFORMS_NOT_SUPPORTED directives disable
+want.  The PNG_NO_READ[or WRITE]_TRANSFORMS directives disable
 the extra transformations but still leave the library fully capable of reading
 and writing PNG files with all known public chunks [except for sPLT].
-Use of the PNG_READ[or WRITE]_ANCILLARY_CHUNKS_NOT_SUPPORTED directive
+Use of the PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS directive
 produces a library that is incapable of reading or writing ancillary chunks.
 If you are not using the progressive reading capability, you can
-turn that off with PNG_PROGRESSIVE_READ_NOT_SUPPORTED (don't confuse
+turn that off with PNG_NO_PROGRESSIVE_READ (don't confuse
 this with the INTERLACING capability, which you'll still have).
 
 All the reading and writing specific code are in separate files, so the
@@ -2245,10 +2365,46 @@ or DLL file), you should not remove or disable any parts of the library,
 as this will cause applications linked with different versions of the
 library to fail if they call functions not available in your library.
 The size of the library itself should not be an issue, because only
-those sections which are actually used will be loaded into memory.
+those sections that are actually used will be loaded into memory.
+
+Requesting debug printout:
+
+The macro definition PNG_DEBUG can be used to request debugging
+printout.  Set it to an integer value in the range 0 to 3.  Higher
+numbers result in increasing amounts of debugging information.  The
+information is printed to the "stderr" file, unless another file
+name is specified in the PNG_DEBUG_FILE macro definition.
+
+When PNG_DEBUG > 0, the following functions (macros) become available:
+
+   png_debug(level, message)
+   png_debug1(level, message, p1)
+   png_debug2(level, message, p1, p2)
+
+in which "level" is compared to PNG_DEBUG to decide whether to print
+the message, "message" is the formatted string to be printed,
+and p1 and p2 are parameters that are to be embedded in the string
+according to printf-style formatting directives.  For example,
+
+   png_debug1(2, "foo=%d\n", foo);
 
+is expanded to
 
-Changes to Libpng from version 0.88
+   if(PNG_DEBUG > 2)
+     fprintf(PNG_DEBUG_FILE, "foo=%d\n", foo);
+
+When PNG_DEBUG is defined but is zero, the macros aren't defined, but you
+can still use PNG_DEBUG to control your own debugging:
+
+   #ifdef PNG_DEBUG
+       fprintf(stderr, ...
+   #endif
+
+When PNG_DEBUG = 1, the macros are defined, but only png_debug statements
+having level = 0 will be printed.  There aren't any such statements in
+this version of libpng, but if you insert some they will be printed.
+
+.SH VI.  Changes to Libpng from version 0.88
 
 It should be noted that versions of libpng later than 0.96 are not
 distributed by the original libpng author, Guy Schalnat, nor by
@@ -2274,13 +2430,65 @@ allocating and freeing the png_struct for each image read.
 
 Setting the error callbacks via png_set_message_fn() before
 png_read_init() as was suggested in libpng-0.88 is no longer supported
-because this caused applications which do not use custom error functions
+because this caused applications that do not use custom error functions
 to fail if the png_ptr was not initialized to zero.  It is still possible
 to set the error callbacks AFTER png_read_init(), or to change them with
 png_set_error_fn(), which is essentially the same function, but with a
 new name to force compilation errors with applications that try to use
 the old method.
 
+.SH VII. Y2K Compliance in libpng
+
+January 13, 1999
+
+Since the PNG Development group is an ad-hoc body, we can't make
+an official declaration.
+
+This is your unofficial assurance that libpng from version 0.81 and
+upward are Y2K compliant.  It is my belief that earlier versions were
+also Y2K compliant.
+
+Libpng only has three year fields.  One is a 2-byte unsigned integer that
+will hold years up to 65535.  The other two hold the date in text
+format, and will hold years up to 9999.
+
+The integer is
+    "png_uint_16 year" in png_time_struct.
+
+The strings are
+    "png_charp time_buffer" in png_struct and
+    "near_time_buffer", which is a local character string in png.c.
+
+There are seven time-related functions:
+
+    png_convert_to_rfc_1123() in png.c 
+      (formerly png_convert_to_rfc_1152() in error)
+    png_convert_from_struct_tm() in pngwrite.c, called in pngwrite.c
+    png_convert_from_time_t() in pngwrite.c
+    png_get_tIME() in pngget.c
+    png_handle_tIME() in pngrutil.c, called in pngread.c
+    png_set_tIME() in pngset.c
+    png_write_tIME() in pngwutil.c, called in pngwrite.c
+
+All appear to handle dates properly in a Y2K environment.  The 
+png_convert_from_time_t() function calls gmtime() to convert from system
+clock time, which returns (year - 1900), which we properly convert to
+the full 4-digit year.  There is a possibility that applications using
+libpng are not passing 4-digit years into the png_convert_to_rfc_1123()
+function, or incorrectly passing only a 2-digit year instead of
+"year - 1900" into the png_convert_from_struct_tm() function, but this
+is not under our control.  The libpng documentation has always stated
+that it works with 4-digit years, and the APIs have been documented as
+such.
+
+The tIME chunk itself is also Y2K compliant.  It uses a 2-byte unsigned
+integer to hold the year, and can hold years as large as 65535.
+
+
+   Glenn Randers-Pehrson
+   libpng maintainer
+   PNG Development Group
+
 .SH NOTE
 
 Note about libpng version numbers:
@@ -2366,7 +2574,7 @@ possible without all of you.
 
 Thanks to Frank J. T. Wojcik for helping with the documentation.
   
-Libpng version 1.0.1 March 15, 1998:
+Libpng version 1.0.3 - January 14, 1999:
 Initially created in 1995 by Guy Eric Schalnat, then of Group 42, Inc.
 Currently maintained by Glenn Randers-Pehrson (randeg@alumni.rpi.edu).
 
@@ -2376,6 +2584,10 @@ Supported by the PNG development group
 
 .SH COPYRIGHT NOTICE:
 
+Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
+Copyright (c) 1996, 1997 Andreas Dilger
+Copyright (c) 1998, 1999 Glenn Randers-Pehrson
+
 The PNG Reference Library (libpng) is supplied "AS IS".  The Contributing
 Authors and Group 42, Inc. disclaim all warranties, expressed or implied,
 including, without limitation, the warranties of merchantability and of
index 7ba582ebe2f4dece0e67201e93d8f7c4aa7c9195..c2654e7f8a273647c6ebb1751ff4d28e66563411 100644 (file)
@@ -1,6 +1,6 @@
-.TH LIBPNGPF 3 "March 15, 1998"
+.TH LIBPNGPF 3 "January 14, 1999"
 .SH NAME
-libpng \- Portable Network Graphics (PNG) Reference Library
+libpng \- Portable Network Graphics (PNG) Reference Library 1.0.3 - January 14, 1999
 (private functions)
 .SH SYNOPSIS
 #include <png.h>
@@ -31,10 +31,15 @@ int png_crc_finish (png_structp png_ptr, png_uint_32 skip);
 void png_crc_read (png_structp png_ptr, png_bytep buf,
 png_size_t length);
 
-png_voidp png_create_struct (int type);
+png_voidp png_create_struct (int type, png_malloc_ptr malloc_fn);
+
+png_voidp png_create_struct_2 (int type);
 
 void png_destroy_struct (png_voidp struct_ptr);
 
+void png_destroy_struct_2 (png_voidp struct_ptr, png_free_ptr
+free_fn);
+
 void png_do_background (png_row_infop row_info, png_bytep row,
 png_color_16p trans_values, png_color_16p background,
 png_color_16p background_1, png_bytep gamma_table, png_bytep
@@ -83,7 +88,7 @@ row);
 
 void png_do_read_transformations (png_structp png_ptr);
 
-void png_do_rgb_to_gray (png_row_infop row_info, png_bytep
+int png_do_rgb_to_gray (png_row_infop row_info, png_bytep
 row);
 
 void png_do_shift (png_row_infop row_info, png_bytep row,
index 30244aabb86dc3b1f2d10e4dc992772b02dc4a7b..2c0fcde12e562ea17a101fce0152fa8c3c77017c 100644 (file)
@@ -1,4 +1,4 @@
-.TH PNG 5 "March 15, 1998"
+.TH PNG 5 "January 14, 1999"
 .SH NAME
 png \- Portable Network Graphics (PNG) format
 .SH DESCRIPTION
@@ -7,7 +7,7 @@ lossless, portable, well-compressed storage of raster images. PNG provides
 a patent-free replacement for GIF and can also replace many
 common uses of TIFF. Indexed-color, grayscale, and truecolor images are
 supported, plus an optional alpha channel. Sample depths range from
-1 to 16 bits. 
+1 to 16 bits.
 .br
 
 PNG is designed to work well in online viewing applications, such as the
@@ -15,7 +15,7 @@ World Wide Web, so it is fully streamable with a progressive display
 option. PNG is robust, providing both full file integrity checking and
 fast, simple detection of common transmission errors. Also, PNG can store
 gamma and chromaticity data for improved color matching on heterogeneous
-platforms. 
+platforms.
 
 .SH "SEE ALSO"
 .IR libpng(3), zlib(3), deflate(5), and zlib(5)
index 33009674d61f42f809e07e1ff6a982ecc992d137..e422332186202150847b488eb4fac562fbc874e9 100644 (file)
@@ -1,22 +1,22 @@
 
 /* png.c - location for general purpose libpng functions
  *
- * libpng 1.0.1
- * For conditions of distribution and use, see copyright notice in png.h
+ * libpng version 1.0.3 - January 14, 1999
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, Glenn Randers-Pehrson
- * March 15, 1998
+ * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
+ * 
  */
 
 #define PNG_INTERNAL
 #define PNG_NO_EXTERN
-#include "../png/png.h"
+#include "png.h"
 
 /* Version information for C files.  This had better match the version
  * string defined in png.h.
  */
-char png_libpng_ver[12] = "1.0.1";
+
+char png_libpng_ver[12] = "1.0.3";
 
 /* Place to hold the signature string for a PNG file. */
 png_byte FARDATA png_sig[8] = {137, 80, 78, 71, 13, 10, 26, 10};
@@ -115,8 +115,8 @@ png_sig_cmp(png_bytep sig, png_size_t start, png_size_t num_to_check)
 }
 
 /* (Obsolete) function to check signature bytes.  It does not allow one
- * to check a partial signature.  This function will be removed in the
- * future - use png_sig_cmp().
+ * to check a partial signature.  This function might be removed in the
+ * future - use png_sig_cmp().  Returns true (nonzero) if the file is a PNG.
  */
 int
 png_check_sig(png_bytep sig, int num)
@@ -128,12 +128,10 @@ png_check_sig(png_bytep sig, int num)
 voidpf
 png_zalloc(voidpf png_ptr, uInt items, uInt size)
 {
-   png_voidp ptr;
-   png_uint_32 num_bytes;
+   png_uint_32 num_bytes = (png_uint_32)items * size;
+   png_voidp ptr = (png_voidp)png_malloc((png_structp)png_ptr, num_bytes);
 
-   num_bytes = (png_uint_32)items * size;
-   ptr = (png_voidp)png_malloc((png_structp)png_ptr, num_bytes);
-   if (num_bytes > (png_uint_32)0x8000)
+   if (num_bytes > (png_uint_32)0x8000L)
    {
       png_memset(ptr, 0, (png_size_t)0x8000L);
       png_memset((png_bytep)ptr + (png_size_t)0x8000L, 0,
@@ -201,7 +199,12 @@ png_create_info_struct(png_structp png_ptr)
 
    png_debug(1, "in png_create_info_struct\n");
    if(png_ptr == NULL) return (NULL);
+#ifdef PNG_USER_MEM_SUPPORTED
+   if ((info_ptr = (png_infop)png_create_struct_2(PNG_STRUCT_INFO,
+      png_ptr->malloc_fn)) != NULL)
+#else
    if ((info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO)) != NULL)
+#endif
    {
       png_info_init(info_ptr);
    }
@@ -227,7 +230,11 @@ png_destroy_info_struct(png_structp png_ptr, png_infopp info_ptr_ptr)
    {
       png_info_destroy(png_ptr, info_ptr);
 
+#ifdef PNG_USER_MEM_SUPPORTED
+      png_destroy_struct_2((png_voidp)info_ptr, png_ptr->free_fn);
+#else
       png_destroy_struct((png_voidp)info_ptr);
+#endif
       *info_ptr_ptr = (png_infop)NULL;
    }
 }
@@ -252,11 +259,10 @@ void
 png_info_destroy(png_structp png_ptr, png_infop info_ptr)
 {
 #if defined(PNG_READ_tEXt_SUPPORTED) || defined(PNG_READ_zTXt_SUPPORTED)
-   int i;
-
    png_debug(1, "in png_info_destroy\n");
    if (info_ptr->text != NULL)
    {
+      int i;
       for (i = 0; i < info_ptr->num_text; i++)
       {
          png_free(png_ptr, info_ptr->text[i].key);
@@ -269,6 +275,7 @@ png_info_destroy(png_structp png_ptr, png_infop info_ptr)
    png_free(png_ptr, info_ptr->pcal_units);
    if (info_ptr->pcal_params != NULL)
    {
+      int i;
       for (i = 0; i < (int)info_ptr->pcal_nparams; i++)
       {
          png_free(png_ptr, info_ptr->pcal_params[i]);
@@ -302,3 +309,51 @@ png_init_io(png_structp png_ptr, FILE *fp)
    png_ptr->io_ptr = (png_voidp)fp;
 }
 #endif
+
+#if defined(PNG_TIME_RFC1123_SUPPORTED)
+/* Convert the supplied time into an RFC 1123 string suitable for use in
+ * a "Creation Time" or other text-based time string.
+ */
+png_charp
+png_convert_to_rfc1123(png_structp png_ptr, png_timep ptime)
+{
+   static PNG_CONST char short_months[12][4] =
+        {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+
+   if (png_ptr->time_buffer == NULL)
+   {
+      png_ptr->time_buffer = (png_charp)png_malloc(png_ptr, (png_uint_32)(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 % 32, short_months[(ptime->month - 1) % 12],
+               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 % 32, short_months[(ptime->month - 1) % 12],
+               ptime->year, ptime->hour % 24, ptime->minute % 60,
+               ptime->second % 61);
+#endif
+   return ((png_charp)png_ptr->time_buffer);
+}
+#endif /* PNG_TIME_RFC1123_SUPPORTED */
+
+png_charp
+png_get_copyright(png_structp png_ptr)
+{
+   if(png_ptr == NULL)
+     /* silence compiler warning about unused png_ptr */ ;
+   return("\n libpng version 1.0.3 - January 14, 1999\n\
+   Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.\n\
+   Copyright (c) 1996, 1997 Andreas Dilger\n\
+   Copyright (c) 1998, 1999, Glenn Randers-Pehrson\n");
+}
index 3c5ad6007ebde9006ec92489a510d12de6972847..b48e1507e72b6e0d5aefc0ca3f4658ce388f38fe 100644 (file)
 
 /* png.h - header file for PNG reference library
  *
- * libpng 1.0.1
- * For conditions of distribution and use, see the COPYRIGHT NOTICE below.
+ * libpng version 1.0.3 - January 14, 1999
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998 Glenn Randers-Pehrson
- * March 15, 1998
+ * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
  *
+ * Y2K compliance in libpng:
+ * =========================
+ *    
+ *    January 13, 1999
+ *    
+ *    Since the PNG Development group is an ad-hoc body, we can't make
+ *    an official declaration.
+ *    
+ *    This is your unofficial assurance that libpng from version 0.81 and
+ *    upward are Y2K compliant.  It is my belief that earlier versions were
+ *    also Y2K compliant.
+ *    
+ *    Libpng only has three year fields.  One is a 2-byte unsigned integer
+ *    that will hold years up to 65535.  The other two hold the date in text
+ *    format, and will hold years up to 9999.
+ *    
+ *    The integer is
+ *        "png_uint_16 year" in png_time_struct.
+ *    
+ *    The strings are
+ *        "png_charp time_buffer" in png_struct and
+ *        "near_time_buffer", which is a local character string in png.c.
+ *    
+ *    There are seven time-related functions:
+ *        png.c: png_convert_to_rfc_1123() in png.c 
+ *          (formerly png_convert_to_rfc_1152() in error)
+ *        png_convert_from_struct_tm() in pngwrite.c, called in pngwrite.c
+ *        png_convert_from_time_t() in pngwrite.c
+ *        png_get_tIME() in pngget.c
+ *        png_handle_tIME() in pngrutil.c, called in pngread.c
+ *        png_set_tIME() in pngset.c
+ *        png_write_tIME() in pngwutil.c, called in pngwrite.c
+ *    
+ *    All handle dates properly in a Y2K environment.  The 
+ *    png_convert_from_time_t() function calls gmtime() to convert from system
+ *    clock time, which returns (year - 1900), which we properly convert to
+ *    the full 4-digit year.  There is a possibility that applications using
+ *    libpng are not passing 4-digit years into the png_convert_to_rfc_1123()
+ *    function, or incorrectly passing only a 2-digit year instead of
+ *    "year - 1900" into the png_convert_from_struct_tm() function, but this
+ *    is not under our control.  The libpng documentation has always stated
+ *    that it works with 4-digit years, and the APIs have been documented as
+ *    such.
+ *    
+ *    The tIME chunk itself is also Y2K compliant.  It uses a 2-byte unsigned
+ *    integer to hold the year, and can hold years as large as 65535.
+ *    
+ *    
+ *       Glenn Randers-Pehrson
+ *       libpng maintainer
+ *       PNG Development Group
+ * 
  * Note about libpng version numbers:
- *
+ * 
  *    Due to various miscommunications, unforeseen code incompatibilities
  *    and occasional factors outside the authors' control, version numbering
  *    on the library has not always been consistent and straightforward.
  *    The following table summarizes matters since version 0.89c, which was
  *    the first widely used release:
  *
- *      source                    png.h   png.h   shared-lib
- *      version                   string    int   version
- *      -------                   ------  ------  ----------
- *      0.89c ("1.0 beta 3")      0.89        89  1.0.89
- *      0.90  ("1.0 beta 4")      0.90        90  0.90  [should have been 2.0.90]
- *      0.95  ("1.0 beta 5")      0.95        95  0.95  [should have been 2.0.95]
- *      0.96  ("1.0 beta 6")      0.96        96  0.96  [should have been 2.0.96]
- *      0.97b ("1.00.97 beta 7")  1.00.97     97  1.0.1 [should have been 2.0.97]
- *      0.97c                     0.97        97  2.0.97
- *      0.98                      0.98        98  2.0.98
- *      0.99                      0.99        98  2.0.99
- *      0.99a-m                   0.99        99  2.0.99
- *      1.00                      1.00       100  2.1.0 [int should be 10000]
- *      1.0.0                     1.0.0      100  2.1.0 [int should be 10000]
- *      1.0.1                     1.0.1    10001  2.1.0
+ *    source                    png.h    png.h   shared-lib
+ *    version                   string     int   version
+ *    -------                   ------   -----  ----------
+ *    0.89c ("1.0 beta 3")      0.89        89  1.0.89
+ *    0.90  ("1.0 beta 4")      0.90        90  0.90  [should have been 2.0.90]
+ *    0.95  ("1.0 beta 5")      0.95        95  0.95  [should have been 2.0.95]
+ *    0.96  ("1.0 beta 6")      0.96        96  0.96  [should have been 2.0.96]
+ *    0.97b ("1.00.97 beta 7")  1.00.97     97  1.0.1 [should have been 2.0.97]
+ *    0.97c                     0.97        97  2.0.97
+ *    0.98                      0.98        98  2.0.98
+ *    0.99                      0.99        98  2.0.99
+ *    0.99a-m                   0.99        99  2.0.99
+ *    1.00                      1.00       100  2.1.0 [int should be 10000]
+ *    1.0.0                     1.0.0      100  2.1.0 [int should be 10000]
+ *    1.0.1                     1.0.1    10001  2.1.0
+ *    1.0.1a-e                  1.0.1a-e 10002  2.1.0.1a-e
+ *    1.0.2                     1.0.2    10002  2.1.0.2
+ *    1.0.2a-c                  1.0.2a   10003  2.1.0.2a-c
+ *    1.0.3                     1.0.3    10003  2.1.0.3
  *
  *    Henceforth the source version will match the shared-library minor
  *    and patch numbers; the shared-library major version number will be
- *    used for changes in backward compatibility, as it is intended.
- *    The PNG_PNGLIB_VER macro, which is not used within libpng but
- *    is available for applications, is an unsigned integer of the form
- *    xyyzz corresponding to the source version x.y.z (leading zeros in y and z).
- *    
+ *    used for changes in backward compatibility, as it is intended.  The
+ *    PNG_PNGLIB_VER macro, which is not used within libpng but is available
+ *    for applications, is an unsigned integer of the form xyyzz corresponding
+ *    to the source version x.y.z (leading zeros in y and z).
  *
- * See libpng.txt for more information.  The PNG specification is available
- * as RFC 2083 <ftp://ftp.uu.net/graphics/png/documents/>
+ * See libpng.txt or libpng.3 for more information.  The PNG specification
+ * is available as RFC 2083 <ftp://ftp.uu.net/graphics/png/documents/>
  * and as a W3C Recommendation <http://www.w3.org/TR/REC.png.html>
  *
  * Contributing Authors:
  * appreciated.
  */
 
+
 #ifndef _PNG_H
 #define _PNG_H
 
@@ -106,10 +160,10 @@ extern "C" {
  */
 
 /* include the compression library's header */
-#include "../zlib/zlib.h"
+#include "zlib.h"
 
 /* include all user configurable info */
-#include "../png/pngconf.h"
+#include "pngconf.h"
 
 /* This file is arranged in several sections.  The first section contains
  * structure and type definitions.  The second section contains the external
@@ -118,14 +172,14 @@ extern "C" {
  */
 
 /* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.0.1"
+#define PNG_LIBPNG_VER_STRING "1.0.3"
 
 /* Careful here.  At one time, Guy wanted to use 082, but that would be octal.
  * We must not include leading zeros.
  * Versions 0.7 through 1.0.0 were in the range 0 to 100 here (only
  * version 1.0.0 was mis-numbered 100 instead of 10000).  From
  * version 1.0.1 it's    xxyyzz, where x=major, y=minor, z=bugfix */
-#define PNG_LIBPNG_VER    10001  /* 1.0.1 */
+#define PNG_LIBPNG_VER    10003  /* 1.0.3 */
 
 /* variables declared in png.c - only it needs to define PNG_NO_EXTERN */
 #if !defined(PNG_NO_EXTERN) || defined(PNG_ALWAYS_EXTERN)
@@ -145,6 +199,7 @@ extern int FARDATA png_pass_dsp_mask[7];
 extern int FARDATA png_pass_width[7];
 extern int FARDATA png_pass_height[7];
 */
+
 #endif /* PNG_NO_EXTERN */
 
 /* Three color definitions.  The order of the red, green, and blue, (and the
@@ -231,7 +286,7 @@ typedef png_time FAR * FAR * png_timepp;
  * With libpng < 0.95, it was only possible to directly set and read the
  * the values in the png_info_struct, which meant that the contents and
  * order of the values had to remain fixed.  With libpng 0.95 and later,
- * however, * there are now functions which abstract the contents of
+ * however, there are now functions that abstract the contents of
  * png_info_struct from the application, so this makes it easier to use
  * libpng with dynamic libraries, and even makes it possible to use
  * libraries that don't have all of the libpng ancillary chunk-handing
@@ -289,14 +344,14 @@ typedef struct png_info_struct
    /* The tEXt and zTXt chunks contain human-readable textual data in
     * uncompressed and compressed forms, respectively.  The data in "text"
     * is an array of pointers to uncompressed, null-terminated C strings.
-    * Each chunk has a keyword which describes the textual data contained
+    * Each chunk has a keyword that describes the textual data contained
     * in that chunk.  Keywords are not required to be unique, and the text
     * string may be empty.  Any number of text chunks may be in an image.
     */
    int num_text; /* number of comments read/to write */
    int max_text; /* current size of text array */
    png_textp text; /* array of comments read/to write */
-#endif /* PNG_READ_tEXt/zTXt_SUPPORTED || PNG_WRITE_tEXt/zTXt_SUPPORTED */
+#endif /* PNG_READ_OR_WRITE_tEXt_OR_zTXt_SUPPORTED */
 #if defined(PNG_READ_tIME_SUPPORTED) || defined(PNG_WRITE_tIME_SUPPORTED)
    /* The tIME chunk holds the last time the displayed image data was
     * modified.  See the png_time struct for the contents of this struct.
@@ -312,14 +367,15 @@ typedef struct png_info_struct
     */
    png_color_8 sig_bit; /* significant bits in color channels */
 #endif /* PNG_READ_sBIT_SUPPORTED || PNG_WRITE_sBIT_SUPPORTED */
-#if defined(PNG_READ_tRNS_SUPPORTED) || defined(PNG_WRITE_tRNS_SUPPORTED)
+#if defined(PNG_READ_tRNS_SUPPORTED) || defined(PNG_WRITE_tRNS_SUPPORTED) || \
+    defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
    /* The tRNS chunk supplies transparency data for paletted images and
     * other image types that don't need a full alpha channel.  There are
     * "num_trans" transparency values for a paletted image, stored in the
     * same order as the palette colors, starting from index 0.  Values
     * for the data are in the range [0, 255], ranging from fully transparent
     * to fully opaque, respectively.  For non-paletted images, there is a
-    * single color specified which should be treated as fully transparent.
+    * single color specified that should be treated as fully transparent.
     * Data is valid if (valid & PNG_INFO_tRNS) is non-zero.
     */
    png_bytep trans; /* transparent values for paletted image */
@@ -453,7 +509,7 @@ typedef png_info FAR * FAR * png_infopp;
 #define PNG_sRGB_INTENT_ABSOLUTE   2
 #define PNG_sRGB_INTENT_RELATIVE   3
 #define PNG_sRGB_INTENT_LAST       4 /* Not a valid value */
-                        
+
 
 
 /* These determine if an ancillary chunk's data has been successfully read
@@ -491,10 +547,11 @@ typedef struct png_row_info_struct
 typedef png_row_info FAR * png_row_infop;
 typedef png_row_info FAR * FAR * png_row_infopp;
 
-/* These are the function types for the I/O functions, and the functions which
- * modify the default I/O functions to user I/O functions.  The png_error_ptr
- * type should match that of user supplied warning and error functions, while
- * the png_rw_ptr type should match that of the user read/write data functions.
+/* These are the function types for the I/O functions and for the functions
+ * that allow the user to override the default I/O functions with his or her
+ * own.  The png_error_ptr type should match that of user-supplied warning
+ * and error functions, while the png_rw_ptr type should match that of the
+ * user read/write data functions.
  */
 typedef struct png_struct_def png_struct;
 typedef png_struct FAR * png_structp;
@@ -517,6 +574,9 @@ typedef void (*png_user_transform_ptr) PNGARG((png_structp,
     png_row_infop, png_bytep));
 #endif /* PNG_READ|WRITE_USER_TRANSFORM_SUPPORTED */
 
+typedef png_voidp (*png_malloc_ptr) PNGARG((png_structp, png_size_t));
+typedef void (*png_free_ptr) PNGARG((png_structp, png_structp));
+
 /* The structure that holds the information to read and write PNG files.
  * The only people who need to care about what is inside of this are the
  * people who will be modifying the library for their own special needs.
@@ -589,7 +649,7 @@ struct png_struct_def
    png_byte sig_bytes;        /* magic bytes read/written from start of file */
 
 #if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
-   png_byte filler;           /* filler byte for 24->32-bit pixel expansion */
+   png_uint_16 filler;           /* filler bytes for pixel expansion */
 #endif /* PNG_READ_FILLER_SUPPORTED */
 #if defined(PNG_READ_bKGD_SUPPORTED)
    png_byte background_gamma_type;
@@ -604,7 +664,7 @@ struct png_struct_def
    png_uint_32 flush_dist;    /* how many rows apart to flush, 0 - no flush */
    png_uint_32 flush_rows;    /* number of rows written since last flush */
 #endif /* PNG_WRITE_FLUSH_SUPPORTED */
-#if defined(PNG_READ_GAMMA_SUPPORTED)
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
    int gamma_shift;      /* number of "insignificant" bits 16-bit gamma */
    float gamma;          /* file gamma value */
    float screen_gamma;   /* screen gamma value (display_gamma/viewing_gamma */
@@ -623,10 +683,11 @@ struct png_struct_def
 #if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
    png_color_8 shift;         /* shift for significant bit tranformation */
 #endif /* PNG_READ_SHIFT_SUPPORTED || PNG_WRITE_SHIFT_SUPPORTED */
-#if defined(PNG_READ_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+#if defined(PNG_READ_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \
+ || defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
    png_bytep trans;           /* transparency values for paletted files */
    png_color_16 trans_values; /* transparency values for non-paletted files */
-#endif /* PNG_READ_tRNS_SUPPORTED || PNG_READ_BACKGROUND_SUPPORTED */
+#endif /* PNG_READ|WRITE_tRNS_SUPPORTED||PNG_READ_EXPAND|BACKGROUND_SUPPORTED */
    png_read_status_ptr read_row_fn;   /* called after each row is decoded */
    png_write_status_ptr write_row_fn; /* called after each row is encoded */
 #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
@@ -679,6 +740,17 @@ struct png_struct_def
 #if defined(PNG_TIME_RFC1123_SUPPORTED)
    png_charp time_buffer;            /* String to hold RFC 1123 time text */
 #endif /* PNG_TIME_RFC1123_SUPPORTED */
+#ifdef PNG_USER_MEM_SUPPORTED
+   png_voidp mem_ptr;                /* user supplied struct for mem functions */
+   png_malloc_ptr malloc_fn;         /* function for allocating memory */
+   png_free_ptr free_fn;             /* function for freeing memory */
+#endif /* PNG_USER_MEM_SUPPORTED */
+#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+   png_byte rgb_to_gray_status;
+   png_byte rgb_to_gray_red_coeff;
+   png_byte rgb_to_gray_green_coeff;
+   png_byte rgb_to_gray_blue_coeff;
+#endif
 };
 
 typedef png_struct FAR * FAR * png_structpp;
@@ -710,14 +782,25 @@ extern PNG_EXPORT(int,png_check_sig) PNGARG((png_bytep sig, int num));
 
 /* Allocate and initialize png_ptr struct for reading, and any other memory. */
 extern PNG_EXPORT(png_structp,png_create_read_struct)
-   PNGARG((png_const_charp user_png_ver, voidp error_ptr,
+   PNGARG((png_const_charp user_png_ver, png_voidp error_ptr,
    png_error_ptr error_fn, png_error_ptr warn_fn));
 
-/* Allocate and initialize png_ptr struct for reading, and any other memory */
+/* Allocate and initialize png_ptr struct for writing, and any other memory */
 extern PNG_EXPORT(png_structp,png_create_write_struct)
-   PNGARG((png_const_charp user_png_ver, voidp error_ptr,
+   PNGARG((png_const_charp user_png_ver, png_voidp error_ptr,
    png_error_ptr error_fn, png_error_ptr warn_fn));
 
+#ifdef PNG_USER_MEM_SUPPORTED
+extern PNG_EXPORT(png_structp,png_create_read_struct_2)
+   PNGARG((png_const_charp user_png_ver, png_voidp error_ptr,
+   png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
+   png_malloc_ptr malloc_fn, png_free_ptr free_fn));
+extern PNG_EXPORT(png_structp,png_create_write_struct_2)
+   PNGARG((png_const_charp user_png_ver, png_voidp error_ptr,
+   png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
+   png_malloc_ptr malloc_fn, png_free_ptr free_fn));
+#endif
+
 /* Write a PNG chunk - size, type, (optional) data, CRC. */
 extern PNG_EXPORT(void,png_write_chunk) PNGARG((png_structp png_ptr,
    png_bytep chunk_name, png_bytep data, png_size_t length));
@@ -779,8 +862,11 @@ extern PNG_EXPORT(void,png_set_gray_to_rgb) PNGARG((png_structp png_ptr));
 #endif /* PNG_READ_GRAY_TO_RGB_SUPPORTED */
 
 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
-/* Reduce RGB to grayscale. (Not yet implemented) */
-extern PNG_EXPORT(void,png_set_rgb_to_gray) PNGARG((png_structp png_ptr));
+/* Reduce RGB to grayscale. */
+extern PNG_EXPORT(void,png_set_rgb_to_gray) PNGARG((png_structp png_ptr,
+   int error_action, float red, float green ));
+extern PNG_EXPORT(png_byte,png_get_rgb_to_gray_status) PNGARG((png_structp
+   png_ptr));
 #endif /* PNG_READ_RGB_TO_GRAY_SUPPORTED */
 
 extern PNG_EXPORT(void,png_build_grayscale_palette) PNGARG((int bit_depth,
@@ -1084,6 +1170,7 @@ extern PNG_EXPORT(void,png_init_io) PNGARG((png_structp png_ptr, FILE *fp));
  * method of error handling.  If error_fn or warning_fn is NULL, the
  * default function will be used.
  */
+
 extern PNG_EXPORT(void,png_set_error_fn) PNGARG((png_structp png_ptr,
    png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn));
 
@@ -1111,6 +1198,15 @@ extern PNG_EXPORT(void,png_set_read_status_fn) PNGARG((png_structp png_ptr,
 extern PNG_EXPORT(void,png_set_write_status_fn) PNGARG((png_structp png_ptr,
    png_write_status_ptr write_row_fn));
 
+#ifdef PNG_USER_MEM_SUPPORTED
+/* Replace the default memory allocation functions with user supplied one(s). */
+extern PNG_EXPORT(void,png_set_mem_fn) PNGARG((png_structp png_ptr,
+   png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn));
+
+/* Return the user pointer associated with the memory functions */
+extern PNG_EXPORT(png_voidp,png_get_mem_ptr) PNGARG((png_structp png_ptr));
+#endif /* PNG_USER_MEM_SUPPORTED */
+
 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
 extern PNG_EXPORT(void,png_set_read_user_transform_fn) PNGARG((png_structp
    png_ptr, png_user_transform_ptr read_user_transform_fn));
@@ -1138,7 +1234,7 @@ extern PNG_EXPORT(png_voidp,png_get_progressive_ptr)
 extern PNG_EXPORT(void,png_process_data) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_bytep buffer, png_size_t buffer_size));
 
-/* function which combines rows.  Not very much different than the
+/* function that combines rows.  Not very much different than the
  * png_combine_row() call.  Is this even used?????
  */
 extern PNG_EXPORT(void,png_progressive_combine_row) PNGARG((png_structp png_ptr,
@@ -1151,19 +1247,19 @@ extern PNG_EXPORT(png_voidp,png_malloc) PNGARG((png_structp png_ptr,
 /* frees a pointer allocated by png_malloc() */
 extern PNG_EXPORT(void,png_free) PNGARG((png_structp png_ptr, png_voidp ptr));
 
+#ifdef PNG_USER_MEM_SUPPORTED
+extern PNG_EXPORT(png_voidp,png_malloc_default) PNGARG((png_structp png_ptr,
+   png_uint_32 size));
+extern PNG_EXPORT(void,png_free_default) PNGARG((png_structp png_ptr,
+   png_voidp ptr));
+#endif /* PNG_USER_MEM_SUPPORTED */
+
 extern PNG_EXPORT(png_voidp,png_memcpy_check) PNGARG((png_structp png_ptr,
    png_voidp s1, png_voidp s2, png_uint_32 size));
 
 extern PNG_EXPORT(png_voidp,png_memset_check) PNGARG((png_structp png_ptr,
    png_voidp s1, int value, png_uint_32 size));
 
-#ifdef PNGTEST_MEMORY_DEBUG
-/* debugging versions of png_malloc() and png_free() */
-extern PNG_EXPORT(png_voidp,png_debug_malloc) PNGARG((png_structp png_ptr,
-   png_uint_32 size));
-extern PNG_EXPORT(void,png_debug_free) PNGARG((png_structp png_ptr,
-   png_voidp ptr));
-#endif
 #if defined(USE_FAR_KEYWORD)  /* memory model conversion function */
 extern void *png_far_to_near PNGARG((png_structp png_ptr,png_voidp ptr,
    int check));
@@ -1313,7 +1409,7 @@ extern PNG_EXPORT(png_uint_32,png_get_IHDR) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_uint_32 *width, png_uint_32 *height,
    int *bit_depth, int *color_type, int *interlace_type,
    int *compression_type, int *filter_type));
-  
+
 extern PNG_EXPORT(void,png_set_IHDR) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth,
    int color_type, int interlace_type, int compression_type, int filter_type));
@@ -1390,8 +1486,7 @@ extern PNG_EXPORT(png_uint_32,png_get_text) PNGARG((png_structp png_ptr,
     defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
 extern PNG_EXPORT(void,png_set_text) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_textp text_ptr, int num_text));
-#endif /* PNG_READ_tEXt_SUPPORTED || PNG_WRITE_tEXt_SUPPORTED ||
-          PNG_READ_zTXt_SUPPORTED || PNG_WRITE_zTXt_SUPPORTED */
+#endif /* PNG_READ_OR_WRITE_tEXt_OR_zTXt_SUPPORTED */
 
 #if defined(PNG_READ_tIME_SUPPORTED)
 extern PNG_EXPORT(png_uint_32,png_get_tIME) PNGARG((png_structp png_ptr,
@@ -1420,28 +1515,87 @@ extern PNG_EXPORT(void,png_set_tRNS) PNGARG((png_structp png_ptr,
  * only been added since version 0.95 so it is not implemented throughout
  * libpng yet, but more support will be added as needed.
  */
+#ifdef PNG_DEBUG
 #if (PNG_DEBUG > 0)
-#ifdef PNG_NO_STDIO
-#include <stdio.h>
-#endif
 #ifndef PNG_DEBUG_FILE
 #define PNG_DEBUG_FILE stderr
 #endif /* PNG_DEBUG_FILE */
 
 #define png_debug(l,m)        if (PNG_DEBUG > l) \
                                  fprintf(PNG_DEBUG_FILE,"%s"m,(l==1 ? "\t" : \
-                                    (l==2 ? "\t\t":(l==3 ? "\t\t\t":""))))
+                                    (l==2 ? "\t\t":(l>2 ? "\t\t\t":""))))
 #define png_debug1(l,m,p1)    if (PNG_DEBUG > l) \
                                  fprintf(PNG_DEBUG_FILE,"%s"m,(l==1 ? "\t" : \
-                                    (l==2 ? "\t\t":(l==3 ? "\t\t\t":""))),p1)
+                                    (l==2 ? "\t\t":(l>2 ? "\t\t\t":""))),p1)
 #define png_debug2(l,m,p1,p2) if (PNG_DEBUG > l) \
                                  fprintf(PNG_DEBUG_FILE,"%s"m,(l==1 ? "\t" : \
-                                    (l==2 ? "\t\t":(l==3 ? "\t\t\t":""))),p1,p2)
-#else
+                                    (l==2 ? "\t\t":(l>2 ? "\t\t\t":""))),p1,p2)
+#endif /* (PNG_DEBUG > 0) */
+#endif /* PNG_DEBUG */
+#ifndef png_debug
 #define png_debug(l, m)
+#endif
+#ifndef png_debug1
 #define png_debug1(l, m, p1)
+#endif
+#ifndef png_debug2
 #define png_debug2(l, m, p1, p2)
-#endif /* (PNG_DEBUG > 0) */
+#endif
+
+extern PNG_EXPORT(png_charp,png_get_copyright) PNGARG((png_structp png_ptr));
+extern PNG_EXPORT(png_charp,png_get_header_version) PNGARG((png_structp png_ptr));
+
+#ifdef PNG_NO_EXTERN
+/* this only gets included in png.c */
+png_charp
+png_get_header_version(png_structp png_ptr)
+{
+   if(png_ptr == NULL)
+     /* silence compiler warning about unused png_ptr */ ;
+   return("\n libpng version 1.0.3 - January 14, 1999 (header)\n");
+}
+#endif
+
+#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED
+/* With these routines we avoid an integer divide, which will be slower on
+ * most machines.  However, it does take more operations than the corresponding
+ * divide method, so it may be slower on a few RISC systems.  There are two
+ * shifts (by 8 or 16 bits) and an addition, versus a single integer divide.
+ *
+ * Note that the rounding factors are NOT supposed to be the same!  128 and
+ * 32768 are correct for the NODIV code; 127 and 32767 are correct for the
+ * standard method.
+ *
+ * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ]
+ */
+
+ /* fg and bg should be in `gamma 1.0' space; alpha is the opacity          */
+
+#  define png_composite(composite, fg, alpha, bg)                            \
+     { png_uint_16 temp = ((png_uint_16)(fg) * (png_uint_16)(alpha) +        \
+                        (png_uint_16)(bg)*(png_uint_16)(255 -                \
+                        (png_uint_16)(alpha)) + (png_uint_16)128);           \
+       (composite) = (png_byte)((temp + (temp >> 8)) >> 8); }
+
+#  define png_composite_16(composite, fg, alpha, bg)                         \
+     { png_uint_32 temp = ((png_uint_32)(fg) * (png_uint_32)(alpha) +        \
+                        (png_uint_32)(bg)*(png_uint_32)(65535L -             \
+                        (png_uint_32)(alpha)) + (png_uint_32)32768L);        \
+       (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); }
+
+#else  /* standard method using integer division */
+
+#  define png_composite(composite, fg, alpha, bg)                            \
+     (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) +    \
+       (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) +       \
+       (png_uint_16)127) / 255)
+
+#  define png_composite_16(composite, fg, alpha, bg)                         \
+     (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \
+       (png_uint_32)(bg)*(png_uint_32)(65535L - (png_uint_32)(alpha)) +      \
+       (png_uint_32)32767) / (png_uint_32)65535L)
+
+#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */
 
 /* These next functions are used internally in the code.  They generally
  * shouldn't be used unless you are writing code to add or replace some
@@ -1484,7 +1638,7 @@ extern PNG_EXPORT(void,png_set_tRNS) PNGARG((png_structp png_ptr,
 #define PNG_DITHER             0x0040
 #define PNG_BACKGROUND         0x0080
 #define PNG_BACKGROUND_EXPAND  0x0100
-#define PNG_RGB_TO_GRAY        0x0200 /* Not currently implemented */
+                          /*   0x0200 unused */
 #define PNG_16_TO_8            0x0400
 #define PNG_RGBA               0x0800
 #define PNG_EXPAND             0x1000
@@ -1496,6 +1650,9 @@ extern PNG_EXPORT(void,png_set_tRNS) PNGARG((png_structp png_ptr,
 #define PNG_STRIP_ALPHA       0x40000L
 #define PNG_INVERT_ALPHA      0x80000L
 #define PNG_USER_TRANSFORM   0x100000L
+#define PNG_RGB_TO_GRAY_ERR  0x200000L
+#define PNG_RGB_TO_GRAY_WARN 0x400000L
+#define PNG_RGB_TO_GRAY      0x600000L  /* two bits, RGB_TO_GRAY_ERR|WARN */
 
 /* flags for png_create_struct */
 #define PNG_STRUCT_PNG   0x0001
@@ -1525,6 +1682,7 @@ extern PNG_EXPORT(void,png_set_tRNS) PNGARG((png_structp png_ptr,
 #define PNG_FLAG_FREE_HIST                0x4000
 #define PNG_FLAG_HAVE_CHUNK_HEADER        0x8000L
 #define PNG_FLAG_WROTE_tIME              0x10000L
+#define PNG_FLAG_BACKGROUND_IS_GRAY      0x20000L
 
 #define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \
                                      PNG_FLAG_CRC_ANCILLARY_NOWARN)
@@ -1590,7 +1748,7 @@ PNG_EXTERN png_int_32 png_get_int_32 PNGARG((png_bytep buf));
 #endif /* PNG_READ_pCAL_SUPPORTED */
 PNG_EXTERN png_uint_32 png_get_uint_32 PNGARG((png_bytep buf));
 PNG_EXTERN png_uint_16 png_get_uint_16 PNGARG((png_bytep buf));
-#endif /* PNG_BIG_ENDIAN_GET_SUPPORTED */
+#endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */
 
 /* Initialize png_ptr struct for reading, and allocate any other memory.
  * (old interface - NOT DLL EXPORTED).
@@ -1608,6 +1766,11 @@ PNG_EXTERN png_voidp png_create_struct PNGARG((int type));
 /* free memory from internal libpng struct */
 PNG_EXTERN void png_destroy_struct PNGARG((png_voidp struct_ptr));
 
+PNG_EXTERN png_voidp png_create_struct_2 PNGARG((int type, png_malloc_ptr
+  malloc_fn));
+PNG_EXTERN void png_destroy_struct_2 PNGARG((png_voidp struct_ptr,
+   png_free_ptr free_fn));
+
 /* free any memory that info_ptr points to and reset struct. */
 PNG_EXTERN void png_info_destroy PNGARG((png_structp png_ptr,
    png_infop info_ptr));
@@ -1651,8 +1814,8 @@ PNG_EXTERN void png_flush PNGARG((png_structp png_ptr));
 #endif
 
 /* Place a 32-bit number into a buffer in PNG byte order (big-endian).
- * The only currently known PNG chunk that uses signed numbers is
- * the ancillary extension chunk, pCAL.
+ * The only currently known PNG chunks that use signed numbers are
+ * the ancillary extension chunks, oFFs and pCAL.
  */
 PNG_EXTERN void png_save_uint_32 PNGARG((png_bytep buf, png_uint_32 i));
 
@@ -1723,7 +1886,8 @@ PNG_EXTERN void png_write_hIST PNGARG((png_structp png_ptr, png_uint_16p hist,
    int num_hist));
 #endif
 
-#if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
+#if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED) || \
+    defined(PNG_WRITE_pCAL_SUPPORTED)
 PNG_EXTERN png_size_t png_check_keyword PNGARG((png_structp png_ptr,
    png_charp key, png_charpp new_key));
 #endif
@@ -1847,8 +2011,8 @@ PNG_EXTERN void png_do_packswap PNGARG((png_row_infop row_info, png_bytep row));
 #endif
 
 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
-PNG_EXTERN void png_do_rgb_to_gray PNGARG((png_row_infop row_info,
-   png_bytep row));
+PNG_EXTERN int png_do_rgb_to_gray PNGARG((png_structp png_ptr, png_row_infop
+   row_info, png_bytep row));
 #endif
 
 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
index 675f292babdeee0892af6c179a4fd6af236aa29d..028f2a1a70cbfa642e1caa47b46ca2c48cfcb79f 100644 (file)
@@ -1,12 +1,11 @@
 
 /* pngconf.h - machine configurable file for libpng
  *
- * libpng 1.0.1
+ * libpng 1.0.3 - January 14, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, Glenn Randers-Pehrson
- * March 15, 1998
+ * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
  */
 
 /* Any machine specific code is near the front of this file, so if you
@@ -18,6 +17,7 @@
 #ifndef PNGCONF_H
 #define PNGCONF_H
 
+
 /* This is the size of the compression buffer, and thus the size of
  * 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
 #define PNG_MAX_MALLOC_64K
 #endif
 
-/* This protects us against compilers which run on a windowing system
+/* This protects us against compilers that run on a windowing system
  * and thus don't have or would rather us not use the stdio types:
  * stdin, stdout, and stderr.  The only one currently used is stderr
- * in png_error() and png_warning().  #defining PNG_NO_STDIO will
- * prevent these from being compiled and used.
+ * in png_error() and png_warning().  #defining PNG_NO_CONSOLE_IO will
+ * prevent these from being compiled and used. #defining PNG_NO_STDIO
+ * will also prevent these, plus will prevent the entire set of stdio
+ * macros and functions (FILE *, printf, etc.) from being compiled and used,
+ * unless PNG_DEBUG has been #defined.
+ *
+ * #define PNG_NO_CONSOLE_IO
  * #define PNG_NO_STDIO
  */
 
-#ifndef PNG_NO_STDIO 
-#include <stdio.h>
+#ifdef PNG_DEBUG
+#  if (PNG_DEBUG > 0)
+#    include <stdio.h>
+#  endif
+#else
+#  ifdef PNG_NO_STDIO
+#    ifndef PNG_NO_CONSOLE_IO
+#      define PNG_NO_CONSOLE_IO
+#    endif
+#  else
+#    include <stdio.h>
+#  endif
 #endif
 
 /* This macro protects us against machines that don't have function
@@ -237,72 +252,139 @@ __dont__ include it again
 /* Any transformations you will not be using can be undef'ed here */
 
 /* GR-P, 0.96a: Set "*TRANSFORMS_SUPPORTED as default but allow user
-   to turn it off with "*TRANSFORMS_NOT_SUPPORTED" on the compile line,
-   then pick and choose which ones to define without having to edit
-   this file. It is safe to use the *TRANSFORMS_NOT_SUPPORTED if you
-   only want to have a png-compliant reader/writer but don't need
+   to turn it off with "*TRANSFORMS_NOT_SUPPORTED" or *PNG_NO_*_TRANSFORMS
+   on the compile line, then pick and choose which ones to define without
+   having to edit this file. It is safe to use the *TRANSFORMS_NOT_SUPPORTED
+   if you only want to have a png-compliant reader/writer but don't need
    any of the extra transformations.  This saves about 80 kbytes in a
-   typical installation of the library.
+   typical installation of the library. (PNG_NO_* form added in version
+   1.0.1c, for consistency)
  */
 
 
-#ifndef PNG_READ_TRANSFORMS_NOT_SUPPORTED
+#if !defined(PNG_READ_TRANSFORMS_NOT_SUPPORTED) && \
+    !defined(PNG_NO_READ_TRANSFORMS)
 #define PNG_READ_TRANSFORMS_SUPPORTED
 #endif
-#ifndef PNG_WRITE_TRANSFORMS_NOT_SUPPORTED
+#if !defined(PNG_WRITE_TRANSFORMS_NOT_SUPPORTED) && \
+    !defined(PNG_NO_WRITE_TRANSFORMS)
 #define PNG_WRITE_TRANSFORMS_SUPPORTED
 #endif
 
 #ifdef PNG_READ_TRANSFORMS_SUPPORTED
+#ifndef PNG_NO_READ_EXPAND
 #define PNG_READ_EXPAND_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_SHIFT
 #define PNG_READ_SHIFT_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_PACK
 #define PNG_READ_PACK_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_BGR
 #define PNG_READ_BGR_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_SWAP
 #define PNG_READ_SWAP_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_PACKSWAP
 #define PNG_READ_PACKSWAP_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_INVERT
 #define PNG_READ_INVERT_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_DITHER
 #define PNG_READ_DITHER_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_BACKGROUND
 #define PNG_READ_BACKGROUND_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_16_TO_8
 #define PNG_READ_16_TO_8_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_FILLER
 #define PNG_READ_FILLER_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_GAMMA
 #define PNG_READ_GAMMA_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_GRAY_TO_RGB
 #define PNG_READ_GRAY_TO_RGB_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_SWAP_ALPHA
 #define PNG_READ_SWAP_ALPHA_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_INVERT_ALPHA
 #define PNG_READ_INVERT_ALPHA_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_STRIP_ALPHA
 #define PNG_READ_STRIP_ALPHA_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_USER_TRANSFORM
 #define PNG_READ_USER_TRANSFORM_SUPPORTED
-/* the following aren't implemented yet
+#endif
+#ifndef PNG_NO_READ_RGB_TO_GRAY
 #define PNG_READ_RGB_TO_GRAY_SUPPORTED
- */
+#endif
 #endif /* PNG_READ_TRANSFORMS_SUPPORTED */
 
-#ifndef PNG_PROGRESSIVE_READ_NOT_SUPPORTED   /* if you don't do progressive   */
+#if !defined(PNG_NO_PROGRESSIVE_READ) && \
+ !defined(PNG_PROGRESSIVE_READ_NOT_SUPPORTED) /* if you don't do progressive   */
 #define PNG_PROGRESSIVE_READ_SUPPORTED       /* reading.  This is not talking */
 #endif                               /* about interlacing capability!  You'll */
               /* still have interlacing unless you change the following line: */
 #define PNG_READ_INTERLACING_SUPPORTED /* required for PNG-compliant decoders */
+
+#ifndef PNG_NO_READ_COMPOSITED_NODIV
 #define PNG_READ_COMPOSITE_NODIV_SUPPORTED    /* well tested on Intel and SGI */
+#endif
 
 #ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
+#ifndef PNG_NO_WRITE_SHIFT
 #define PNG_WRITE_SHIFT_SUPPORTED
+#endif
+#ifndef PNG_NO_WRITE_PACK
 #define PNG_WRITE_PACK_SUPPORTED
+#endif
+#ifndef PNG_NO_WRITE_BGR
 #define PNG_WRITE_BGR_SUPPORTED
+#endif
+#ifndef PNG_NO_WRITE_SWAP
 #define PNG_WRITE_SWAP_SUPPORTED
+#endif
+#ifndef PNG_NO_WRITE_PACKSWAP
 #define PNG_WRITE_PACKSWAP_SUPPORTED
+#endif
+#ifndef PNG_NO_WRITE_INVERT
 #define PNG_WRITE_INVERT_SUPPORTED
+#endif
+#ifndef PNG_NO_WRITE_FILLER
 #define PNG_WRITE_FILLER_SUPPORTED  /* This is the same as WRITE_STRIP_ALPHA */
-#define PNG_WRITE_FLUSH_SUPPORTED
+#endif
+#ifndef PNG_NO_WRITE_SWAP_ALPHA
 #define PNG_WRITE_SWAP_ALPHA_SUPPORTED
+#endif
+#ifndef PNG_NO_WRITE_INVERT_ALPHA
 #define PNG_WRITE_INVERT_ALPHA_SUPPORTED
-#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
+#endif
+#ifndef PNG_NO_WRITE_USER_TRANSFORM
 #define PNG_WRITE_USER_TRANSFORM_SUPPORTED
+#endif
 #endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */
 
 #define PNG_WRITE_INTERLACING_SUPPORTED  /* not required for PNG-compliant
                                             encoders, but can cause trouble
                                             if left undefined */
 
-#if !defined(PNG_NO_STDIO)
+#ifndef PNG_NO_WRITE_WEIGHTED_FILTER
+#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
+#endif
+
+#ifndef PNG_NO_WRITE_FLUSH
+#define PNG_WRITE_FLUSH_SUPPORTED
+#endif
+
+#ifndef PNG_NO_STDIO
 #define PNG_TIME_RFC1123_SUPPORTED
 #endif
 
@@ -322,7 +404,7 @@ __dont__ include it again
  * png_get_x_offset_microns()
  * png_get_y_offset_microns()
  */
-#if !defined(PNG_NO_EASY_ACCESS)
+#ifndef PNG_NO_EASY_ACCESS
 #define PNG_EASY_ACCESS_SUPPORTED
 #endif
 
@@ -331,6 +413,7 @@ __dont__ include it again
 /* very little testing */
 /*
 #define PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED
+#define PNG_USER_MEM_SUPPORTED
 */
 
 /* This is only for PowerPC big-endian and 680x0 systems */
@@ -351,45 +434,100 @@ __dont__ include it again
  * a bit smaller.
  */
 
-#ifndef PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED
+#if !defined(PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \
+    !defined(PNG_NO_READ_ANCILLARY_CHUNKS)
 #define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED
 #endif
-#ifndef PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED
+#if !defined(PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \
+    !defined(PNG_NO_WRITE_ANCILLARY_CHUNKS)
 #define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED
 #endif
 
 #ifdef PNG_READ_ANCILLARY_CHUNKS_SUPPORTED
+#ifndef PNG_NO_READ_bKGD
 #define PNG_READ_bKGD_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_cHRM
 #define PNG_READ_cHRM_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_gAMA
 #define PNG_READ_gAMA_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_hIST
 #define PNG_READ_hIST_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_oFFs
 #define PNG_READ_oFFs_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_pCAL
 #define PNG_READ_pCAL_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_pHYs
 #define PNG_READ_pHYs_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_sBIT
 #define PNG_READ_sBIT_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_sRGB
 #define PNG_READ_sRGB_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_tEXt
 #define PNG_READ_tEXt_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_tIME
 #define PNG_READ_tIME_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_tRNS
 #define PNG_READ_tRNS_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_zTXt
 #define PNG_READ_zTXt_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_OPT_PLTE
 #define PNG_READ_OPT_PLTE_SUPPORTED /* only affects support of the optional */
-                                    /* PLTE chunk in RGB and RGBA images */
+#endif                              /* PLTE chunk in RGB and RGBA images */
 #endif /* PNG_READ_ANCILLARY_CHUNKS_SUPPORTED */
 
 #ifdef PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED
+#ifndef PNG_NO_WRITE_bKGD
 #define PNG_WRITE_bKGD_SUPPORTED
+#endif
+#ifndef PNG_NO_WRITE_cHRM
 #define PNG_WRITE_cHRM_SUPPORTED
+#endif
+#ifndef PNG_NO_WRITE_gAMA
 #define PNG_WRITE_gAMA_SUPPORTED
+#endif
+#ifndef PNG_NO_WRITE_hIST
 #define PNG_WRITE_hIST_SUPPORTED
+#endif
+#ifndef PNG_NO_WRITE_oFFs
 #define PNG_WRITE_oFFs_SUPPORTED
+#endif
+#ifndef PNG_NO_WRITE_pCAL
 #define PNG_WRITE_pCAL_SUPPORTED
+#endif
+#ifndef PNG_NO_WRITE_pHYs
 #define PNG_WRITE_pHYs_SUPPORTED
+#endif
+#ifndef PNG_NO_WRITE_sBIT
 #define PNG_WRITE_sBIT_SUPPORTED
+#endif
+#ifndef PNG_NO_WRITE_sRGB
 #define PNG_WRITE_sRGB_SUPPORTED
+#endif
+#ifndef PNG_NO_WRITE_tEXt
 #define PNG_WRITE_tEXt_SUPPORTED
+#endif
+#ifndef PNG_NO_WRITE_tIME
 #define PNG_WRITE_tIME_SUPPORTED
+#endif
+#ifndef PNG_NO_WRITE_tRNS
 #define PNG_WRITE_tRNS_SUPPORTED
+#endif
+#ifndef PNG_NO_WRITE_zTXt
 #define PNG_WRITE_zTXt_SUPPORTED
+#endif
 #endif /* PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED */
 
 /* need the time information for reading tIME chunks */
@@ -507,7 +645,7 @@ typedef char            FAR * FAR * FAR * png_charppp;
  */
 typedef charf *         png_zcharp;
 typedef charf * FAR *   png_zcharpp;
-typedef z_stream FAR *  png_zstreamp; 
+typedef z_stream FAR *  png_zstreamp;
 
 /* allow for compilation as dll under MS Windows */
 #ifdef __WIN32DLL__
@@ -539,6 +677,7 @@ typedef z_stream FAR *  png_zstreamp;
 #   define NOCHECK 0
 #   define CVT_PTR(ptr) (png_far_to_near(png_ptr,ptr,CHECK))
 #   define CVT_PTR_NOCHECK(ptr) (png_far_to_near(png_ptr,ptr,NOCHECK))
+#   define png_strcpy _fstrcpy
 #   define png_strlen _fstrlen
 #   define png_memcmp _fmemcmp      /* SJT: added */
 #   define png_memcpy _fmemcpy
@@ -546,6 +685,7 @@ typedef z_stream FAR *  png_zstreamp;
 #else /* use the usual functions */
 #   define CVT_PTR(ptr)         (ptr)
 #   define CVT_PTR_NOCHECK(ptr) (ptr)
+#   define png_strcpy strcpy
 #   define png_strlen strlen
 #   define png_memcmp memcmp     /* SJT: added */
 #   define png_memcpy memcpy
@@ -554,7 +694,7 @@ typedef z_stream FAR *  png_zstreamp;
 /* End of memory model independent support */
 
 /* Just a double check that someone hasn't tried to define something
- * contradictory. 
+ * contradictory.
  */
 #if (PNG_ZBUF_SIZE > 65536) && defined(PNG_MAX_MALLOC_64K)
 #undef PNG_ZBUF_SIZE
index c31201bdf4ebedb49c85714b99d5065185848d06..c591000d1edef20f5a78d53f22979362962d3f6c 100644 (file)
@@ -1,21 +1,20 @@
 
 /* pngerror.c - stub functions for i/o and memory allocation
  *
- * libpng 1.0.1
+ * libpng 1.0.3 - January 14, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, Glenn Randers-Pehrson
- * March 15, 1998
+ * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
  *
- * This file provides a location for all error handling.  Users which
+ * This file provides a location for all error handling.  Users who
  * need special error handling are expected to write replacement functions
  * and use png_set_error_fn() to use those functions.  See the instructions
  * at each function.
  */
 
 #define PNG_INTERNAL
-#include "../png/png.h"
+#include "png.h"
 
 static void png_default_error PNGARG((png_structp png_ptr,
                                       png_const_charp message));
@@ -52,7 +51,7 @@ 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
+/* These utilities are used internally to build an error message that 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 []
@@ -114,7 +113,7 @@ png_chunk_warning(png_structp png_ptr, png_const_charp message)
 static void
 png_default_error(png_structp png_ptr, png_const_charp message)
 {
-#ifndef PNG_NO_STDIO
+#ifndef PNG_NO_CONSOLE_IO
    fprintf(stderr, "libpng error: %s\n", message);
 #endif
 
@@ -131,18 +130,17 @@ png_default_error(png_structp png_ptr, png_const_charp message)
 
 /* 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
+ * here if you don't want them 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)
 {
-   if (png_ptr == NULL)
-      return;
-
-#ifndef PNG_NO_STDIO
+#ifndef PNG_NO_CONSOLE_IO
    fprintf(stderr, "libpng warning: %s\n", message);
 #endif
+   if (png_ptr == NULL)
+      return;
 }
 
 /* This function is called when the application wants to use another method
index f45fa418aa3a0841f557dc8925eb66132e2d5a65..484a0117c857ffa7ada7fd30fc2de679c43b82df 100644 (file)
@@ -1,16 +1,15 @@
 
 /* pngget.c - retrieval of values from info struct
  *
- * libpng 1.0.1
+ * libpng 1.0.3 - January 14, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, Glenn Randers-Pehrson
- * March 15, 1998
+ * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
  */
 
 #define PNG_INTERNAL
-#include "../png/png.h"
+#include "png.h"
 
 png_uint_32
 png_get_valid(png_structp png_ptr, png_infop info_ptr, png_uint_32 flag)
@@ -302,11 +301,11 @@ png_get_pHYs_dpi(png_structp png_ptr, png_infop info_ptr,
    }
    return (retval);
 }
-#endif
-
+#endif /* PNG_READ_pHYs_SUPPORTED */
 #endif  /* PNG_INCH_CONVERSIONS */
 
 /* png_get_channels really belongs in here, too, but it's been around longer */
+
 #endif  /* PNG_EASY_ACCESS_SUPPORTED */
 
 png_byte
@@ -424,7 +423,7 @@ png_get_IHDR(png_structp png_ptr, png_infop info_ptr,
    png_uint_32 *width, png_uint_32 *height, int *bit_depth,
    int *color_type, int *interlace_type, int *compression_type,
    int *filter_type)
-   
+
 {
    if (png_ptr != NULL && info_ptr != NULL && width != NULL && height != NULL &&
       bit_depth != NULL && color_type != NULL)
@@ -642,3 +641,10 @@ png_get_tRNS(png_structp png_ptr, png_infop info_ptr,
 }
 #endif
 
+#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+png_byte
+png_get_rgb_to_gray_status (png_structp png_ptr)
+{
+   return png_ptr->rgb_to_gray_status;
+}
+#endif
index b92fcc8ae08ac4f583d684533eaef576981d4249..06c4c1b7ea30b7a60958da87f3768658bf4d54eb 100644 (file)
@@ -1,30 +1,21 @@
 
 /* pngmem.c - stub functions for memory allocation
  *
- * libpng 1.0.1
+ * libpng 1.0.3 - January 14, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, Glenn Randers-Pehrson
- * March 15, 1998
+ * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
  *
- * This file provides a location for all memory allocation.  Users which
- * need special memory handling are expected to modify the code in this file
- * to meet their needs.  See the instructions at each function.
+ * This file provides a location for all memory allocation.  Users who
+ * need special memory handling are expected to supply replacement
+ * functions for png_malloc() and png_free(), and to use
+ * png_create_read_struct_2() and png_create_write_struct_2() to
+ * identify the replacement functions.
  */
 
 #define PNG_INTERNAL
-#include "../png/png.h"
-
-/* The following "hides" PNG_MALLOC and PNG_FREE thus allowing the pngtest
-   application to put a wrapper on top of them. */
-#ifdef PNGTEST_MEMORY_DEBUG
-#define PNG_MALLOC png_debug_malloc
-#define PNG_FREE   png_debug_free
-#else
-#define PNG_MALLOC png_malloc
-#define PNG_FREE   png_free
-#endif
+#include "png.h"
 
 /* Borland DOS special memory handler */
 #if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
 png_voidp
 png_create_struct(int type)
 {
+#ifdef PNG_USER_MEM_SUPPORTED
+   return (png_create_struct_2(type, NULL));
+}
+
+/* Alternate version of png_create_struct, for use with user-defined malloc. */
+png_voidp
+png_create_struct_2(int type, png_malloc_ptr malloc_fn)
+{
+#endif /* PNG_USER_MEM_SUPPORTED */
    png_size_t size;
    png_voidp struct_ptr;
 
@@ -45,11 +45,18 @@ png_create_struct(int type)
    else
      return ((png_voidp)NULL);
 
+#ifdef PNG_USER_MEM_SUPPORTED
+   if(malloc_fn != NULL)
+   {
+      if ((struct_ptr = (*(malloc_fn))(NULL, size)) != NULL)
+         png_memset(struct_ptr, 0, size);
+         return (struct_ptr);
+   }
+#endif /* PNG_USER_MEM_SUPPORTED */
    if ((struct_ptr = (png_voidp)farmalloc(size)) != NULL)
    {
       png_memset(struct_ptr, 0, size);
    }
-
    return (struct_ptr);
 }
 
@@ -58,8 +65,27 @@ png_create_struct(int type)
 void
 png_destroy_struct(png_voidp struct_ptr)
 {
+#ifdef PNG_USER_MEM_SUPPORTED
+   png_destroy_struct_2(struct_ptr, (png_free_ptr)NULL);
+}
+
+/* Free memory allocated by a png_create_struct() call */
+void
+png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn)
+{
+#endif
    if (struct_ptr != NULL)
    {
+#ifdef PNG_USER_MEM_SUPPORTED
+      if(free_fn != NULL)
+      {
+         png_struct dummy_struct;
+         png_structp png_ptr = &dummy_struct;
+         (*(free_fn))(png_ptr, struct_ptr);
+         struct_ptr = NULL;
+         return;
+      }
+#endif /* PNG_USER_MEM_SUPPORTED */
       farfree (struct_ptr);
       struct_ptr = NULL;
    }
@@ -72,7 +98,7 @@ png_destroy_struct(png_voidp struct_ptr)
  * have the ability to do that.
  *
  * Borland seems to have a problem in DOS mode for exactly 64K.
- * It gives you a segment with an offset of 8 (perhaps to store it's
+ * It gives you a segment with an offset of 8 (perhaps to store its
  * memory stuff).  zlib doesn't like this at all, so we have to
  * detect and deal with it.  This code should not be needed in
  * Windows or OS/2 modes, and only in 16 bit mode.  This code has
@@ -85,12 +111,27 @@ png_destroy_struct(png_voidp struct_ptr)
  * (which should cause a fatal error) and introducing major problems.
  */
 png_voidp
-PNG_MALLOC(png_structp png_ptr, png_uint_32 size)
+png_malloc(png_structp png_ptr, png_uint_32 size)
 {
+#ifndef PNG_USER_MEM_SUPPORTED
    png_voidp ret;
+#endif
    if (png_ptr == NULL || size == 0)
       return ((png_voidp)NULL);
 
+#ifdef PNG_USER_MEM_SUPPORTED
+   if(png_ptr->malloc_fn != NULL)
+       return ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, size));
+   else
+       return png_malloc_default(png_ptr, size);
+}
+
+png_voidp
+png_malloc_default(png_structp png_ptr, png_uint_32 size)
+{
+   png_voidp ret;
+#endif /* PNG_USER_MEM_SUPPORTED */
+
 #ifdef PNG_MAX_MALLOC_64K
    if (size > (png_uint_32)65536L)
       png_error(png_ptr, "Cannot Allocate > 64K");
@@ -181,15 +222,30 @@ PNG_MALLOC(png_structp png_ptr, png_uint_32 size)
    return (ret);
 }
 
-/* free a pointer allocated by PNG_MALLOC().  In the default
+/* free a pointer allocated by png_malloc().  In the default
    configuration, png_ptr is not used, but is passed in case it
    is needed.  If ptr is NULL, return without taking any action. */
 void
-PNG_FREE(png_structp png_ptr, png_voidp ptr)
+png_free(png_structp png_ptr, png_voidp ptr)
 {
    if (png_ptr == NULL || ptr == NULL)
       return;
 
+#ifdef PNG_USER_MEM_SUPPORTED
+   if (png_ptr->free_fn != NULL)
+   {
+      (*(png_ptr->free_fn))(png_ptr, ptr);
+      ptr = NULL;
+      return;
+   }
+   else png_free_default(png_ptr, ptr);
+}
+
+void
+png_free_default(png_structp png_ptr, png_voidp ptr)
+{
+#endif /* PNG_USER_MEM_SUPPORTED */
+
    if (png_ptr->offset_table != NULL)
    {
       int i;
@@ -227,6 +283,17 @@ PNG_FREE(png_structp png_ptr, png_voidp ptr)
 png_voidp
 png_create_struct(int type)
 {
+#ifdef PNG_USER_MEM_SUPPORTED
+   return (png_create_struct_2(type, NULL));
+}
+
+/* Allocate memory for a png_struct or a png_info.  The malloc and
+   memset can be replaced by a single call to calloc() if this is thought
+   to improve performance noticably.*/
+png_voidp
+png_create_struct_2(int type, png_malloc_ptr malloc_fn)
+{
+#endif /* PNG_USER_MEM_SUPPORTED */
    png_size_t size;
    png_voidp struct_ptr;
 
@@ -237,6 +304,15 @@ png_create_struct(int type)
    else
       return ((png_voidp)NULL);
 
+#ifdef PNG_USER_MEM_SUPPORTED
+   if(malloc_fn != NULL)
+   {
+      if ((struct_ptr = (*(malloc_fn))(NULL, size)) != NULL)
+         png_memset(struct_ptr, 0, size);
+      return (struct_ptr);
+   }
+#endif /* PNG_USER_MEM_SUPPORTED */
+
 #if defined(__TURBOC__) && !defined(__FLAT__)
    if ((struct_ptr = (png_voidp)farmalloc(size)) != NULL)
 #else
@@ -258,15 +334,37 @@ png_create_struct(int type)
 void
 png_destroy_struct(png_voidp struct_ptr)
 {
+#ifdef PNG_USER_MEM_SUPPORTED
+   png_destroy_struct_2(struct_ptr, (png_free_ptr)NULL);
+}
+
+/* Free memory allocated by a png_create_struct() call */
+void
+png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn)
+{
+#endif /* PNG_USER_MEM_SUPPORTED */
    if (struct_ptr != NULL)
    {
+#ifdef PNG_USER_MEM_SUPPORTED
+      if(free_fn != NULL)
+      {
+         png_struct dummy_struct;
+         png_structp png_ptr = &dummy_struct;
+         (*(free_fn))(png_ptr, struct_ptr);
+         struct_ptr = NULL;
+         return;
+      }
+#endif /* PNG_USER_MEM_SUPPORTED */
 #if defined(__TURBOC__) && !defined(__FLAT__)
       farfree(struct_ptr);
+      struct_ptr = NULL;
 #else
 # if defined(_MSC_VER) && defined(MAXSEG_64K)
       hfree(struct_ptr);
+      struct_ptr = NULL;
 # else
       free(struct_ptr);
+      struct_ptr = NULL;
 # endif
 #endif
    }
@@ -280,13 +378,26 @@ png_destroy_struct(png_voidp struct_ptr)
    have the ability to do that. */
 
 png_voidp
-PNG_MALLOC(png_structp png_ptr, png_uint_32 size)
+png_malloc(png_structp png_ptr, png_uint_32 size)
 {
+#ifndef PNG_USER_MEM_SUPPORTED
    png_voidp ret;
-
+#endif
    if (png_ptr == NULL || size == 0)
       return ((png_voidp)NULL);
 
+#ifdef PNG_USER_MEM_SUPPORTED
+   if(png_ptr->malloc_fn != NULL)
+       return ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, size));
+   else
+       return (png_malloc_default(png_ptr, size));
+}
+png_voidp
+png_malloc_default(png_structp png_ptr, png_uint_32 size)
+{
+   png_voidp ret;
+#endif /* PNG_USER_MEM_SUPPORTED */
+
 #ifdef PNG_MAX_MALLOC_64K
    if (size > (png_uint_32)65536L)
       png_error(png_ptr, "Cannot Allocate > 64K");
@@ -310,22 +421,38 @@ PNG_MALLOC(png_structp png_ptr, png_uint_32 size)
    return (ret);
 }
 
-/* Free a pointer allocated by PNG_MALLOC().  In the default
-  configuration, png_ptr is not used, but is passed in case it
-  is needed.  If ptr is NULL, return without taking any action. */
+/* Free a pointer allocated by png_malloc().  If ptr is NULL, return
+   without taking any action. */
 void
-PNG_FREE(png_structp png_ptr, png_voidp ptr)
+png_free(png_structp png_ptr, png_voidp ptr)
 {
    if (png_ptr == NULL || ptr == NULL)
       return;
 
+#ifdef PNG_USER_MEM_SUPPORTED
+   if (png_ptr->free_fn != NULL)
+   {
+      (*(png_ptr->free_fn))(png_ptr, ptr);
+      ptr = NULL;
+      return;
+   }
+   else png_free_default(png_ptr, ptr);
+}
+void
+png_free_default(png_structp png_ptr, png_voidp ptr)
+{
+#endif /* PNG_USER_MEM_SUPPORTED */
+
 #if defined(__TURBOC__) && !defined(__FLAT__)
    farfree(ptr);
+   ptr = NULL;
 #else
 # if defined(_MSC_VER) && defined(MAXSEG_64K)
    hfree(ptr);
+   ptr = NULL;
 # else
    free(ptr);
+   ptr = NULL;
 # endif
 #endif
 }
@@ -341,7 +468,7 @@ png_memcpy_check (png_structp png_ptr, png_voidp s1, png_voidp s2,
    size = (png_size_t)length;
    if ((png_uint_32)size != length)
       png_error(png_ptr,"Overflow in png_memcpy_check.");
-  
+
    return(png_memcpy (s1, s2, size));
 }
 
@@ -358,3 +485,27 @@ png_memset_check (png_structp png_ptr, png_voidp s1, int value,
    return (png_memset (s1, value, size));
 
 }
+
+#ifdef PNG_USER_MEM_SUPPORTED
+/* This function is called when the application wants to use another method
+ * of allocating and freeing memory.
+ */
+void
+png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr
+  malloc_fn, png_free_ptr free_fn)
+{
+   png_ptr->mem_ptr = mem_ptr;
+   png_ptr->malloc_fn = malloc_fn;
+   png_ptr->free_fn = free_fn;
+}
+
+/* This function returns a pointer to the mem_ptr associated with the user
+ * functions.  The application should free any memory associated with this
+ * pointer before png_write_destroy and png_read_destroy are called.
+ */
+png_voidp
+png_get_mem_ptr(png_structp png_ptr)
+{
+   return ((png_voidp)png_ptr->mem_ptr);
+}
+#endif /* PNG_USER_MEM_SUPPORTED */
index 897140d9dc63fd8d70a605c5f11c914aca35ab8b..b44651801d1a2ca4b8ea32bdd1deae3195413b7b 100644 (file)
@@ -1,16 +1,15 @@
 
 /* pngpread.c - read a png file in push mode
  *
- * libpng 1.0.1
+ * libpng 1.0.3 - January 14, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, Glenn Randers-Pehrson
- * March 15, 1998
+ * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
  */
 
 #define PNG_INTERNAL
-#include "../png/png.h"
+#include "png.h"
 
 #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
 
@@ -78,8 +77,9 @@ png_process_some_data(png_structp png_ptr, png_infop info_ptr)
 
 /* Read any remaining signature bytes from the stream and compare them with
  * the correct PNG signature.  It is possible that this routine is called
- * with bytes already read from the signature, whether because they have been
- * checked by the calling application, or from multiple calls to this routine.
+ * with bytes already read from the signature, either because they have been
+ * checked by the calling application, or because of multiple calls to this
+ * routine.
  */
 void
 png_push_read_sig(png_structp png_ptr, png_infop info_ptr)
@@ -92,7 +92,7 @@ png_push_read_sig(png_structp png_ptr, png_infop info_ptr)
       num_to_check = png_ptr->buffer_size;
    }
 
-   png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]), 
+   png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]),
       num_to_check);
    png_ptr->sig_bytes += num_to_check;
 
@@ -446,13 +446,13 @@ png_push_save_buffer(png_structp png_ptr)
    {
       if (png_ptr->save_buffer_ptr != png_ptr->save_buffer)
       {
-         png_size_t i;
+         png_size_t i,istop;
          png_bytep sp;
          png_bytep dp;
 
+         istop = png_ptr->save_buffer_size;
          for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer;
-            i < png_ptr->save_buffer_size;
-            i++, sp++, dp++)
+            i < istop; i++, sp++, dp++)
          {
             *dp = *sp;
          }
@@ -466,7 +466,7 @@ png_push_save_buffer(png_structp png_ptr)
 
       new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256;
       old_buffer = png_ptr->save_buffer;
-      png_ptr->save_buffer = (png_bytep)png_malloc(png_ptr, 
+      png_ptr->save_buffer = (png_bytep)png_malloc(png_ptr,
          (png_uint_32)new_max);
       png_memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
       png_free(png_ptr, old_buffer);
@@ -630,7 +630,7 @@ png_push_process_row(png_structp png_ptr)
    png_ptr->row_info.channels = png_ptr->channels;
    png_ptr->row_info.bit_depth = png_ptr->bit_depth;
    png_ptr->row_info.pixel_depth = png_ptr->pixel_depth;
-   
+
    png_ptr->row_info.rowbytes = ((png_ptr->row_info.width *
       (png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3);
 
@@ -781,6 +781,7 @@ png_read_push_finish_row(png_structp png_ptr)
          png_ptr->pass++;
          if (png_ptr->pass >= 7)
             break;
+
          png_ptr->iwidth = (png_ptr->width +
             png_pass_inc[png_ptr->pass] - 1 -
             png_pass_start[png_ptr->pass]) /
@@ -789,18 +790,15 @@ png_read_push_finish_row(png_structp png_ptr)
          png_ptr->irowbytes = ((png_ptr->iwidth *
             png_ptr->pixel_depth + 7) >> 3) + 1;
 
-         if (!(png_ptr->transformations & PNG_INTERLACE))
-         {
-            png_ptr->num_rows = (png_ptr->height +
-               png_pass_yinc[png_ptr->pass] - 1 -
-               png_pass_ystart[png_ptr->pass]) /
-               png_pass_yinc[png_ptr->pass];
-            if (!(png_ptr->num_rows))
-               continue;
-         }
          if (png_ptr->transformations & PNG_INTERLACE)
             break;
-      } while (png_ptr->iwidth == 0);
+
+         png_ptr->num_rows = (png_ptr->height +
+            png_pass_yinc[png_ptr->pass] - 1 -
+            png_pass_ystart[png_ptr->pass]) /
+            png_pass_yinc[png_ptr->pass];
+
+      } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0);
    }
 }
 
@@ -826,7 +824,7 @@ png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length
    }
 #endif
 
-   png_ptr->current_text = (png_charp)png_malloc(png_ptr, 
+   png_ptr->current_text = (png_charp)png_malloc(png_ptr,
          (png_uint_32)(length+1));
    png_ptr->current_text[length] = '\0';
    png_ptr->current_text_ptr = png_ptr->current_text;
@@ -1070,7 +1068,7 @@ png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr)
 #endif
 
 /* This function is called when we haven't found a handler for this
- * chunk.  In the future we will have code here which can handle
+ * chunk.  In the future we will have code here that can handle
  * user-defined callback functions for unknown chunks before they are
  * ignored or cause an error.  If there isn't a problem with the
  * chunk itself (ie a bad chunk name or a critical chunk), the chunk
@@ -1117,7 +1115,7 @@ void
 png_progressive_combine_row (png_structp png_ptr,
    png_bytep old_row, png_bytep new_row)
 {
-   if (new_row != NULL)
+   if (new_row != NULL)    /* new_row must == png_ptr->row_buf here. */
       png_combine_row(png_ptr, old_row, png_pass_dsp_mask[png_ptr->pass]);
 }
 
index 714f5f14299cf459d6cc80a3e52cca0d52c2f7bb..01613b1641b13e5d08b0ee67a0984677a14a3fd4 100644 (file)
@@ -1,31 +1,49 @@
 
 /* pngread.c - read a PNG file
  *
- * libpng 1.0.1
+ * libpng 1.0.3 - January 14, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, Glenn Randers-Pehrson
- * March 15, 1998
+ * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
  *
  * This file contains routines that an application calls directly to
  * read a PNG file or stream.
  */
 
 #define PNG_INTERNAL
-#include "../png/png.h"
+#include "png.h"
 
 /* Create a PNG structure for reading, and allocate any memory needed. */
 png_structp
-png_create_read_struct(png_const_charp user_png_ver, voidp error_ptr,
+png_create_read_struct(png_const_charp user_png_ver, png_voidp error_ptr,
    png_error_ptr error_fn, png_error_ptr warn_fn)
 {
+
+#ifdef PNG_USER_MEM_SUPPORTED
+   return (png_create_read_struct_2(user_png_ver, error_ptr, error_fn,
+      warn_fn, NULL, NULL, NULL));
+}
+
+/* Alternate create PNG structure for reading, and allocate any memory needed. */
+png_structp
+png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
+   png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
+   png_malloc_ptr malloc_fn, png_free_ptr free_fn)
+{
+#endif /* PNG_USER_MEM_SUPPORTED */
+
    png_structp png_ptr;
 #ifdef USE_FAR_KEYWORD
    jmp_buf jmpbuf;
 #endif
    png_debug(1, "in png_create_read_struct\n");
+#ifdef PNG_USER_MEM_SUPPORTED
+   if ((png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,
+      (png_malloc_ptr)malloc_fn)) == NULL)
+#else
    if ((png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG)) == NULL)
+#endif
    {
       return (png_structp)NULL;
    }
@@ -42,6 +60,11 @@ png_create_read_struct(png_const_charp user_png_ver, voidp error_ptr,
 #ifdef USE_FAR_KEYWORD
    png_memcpy(png_ptr->jmpbuf,jmpbuf,sizeof(jmp_buf));
 #endif
+
+#ifdef PNG_USER_MEM_SUPPORTED
+   png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn);
+#endif /* PNG_USER_MEM_SUPPORTED */
+
    png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
 
    /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
@@ -82,7 +105,7 @@ png_create_read_struct(png_const_charp user_png_ver, voidp error_ptr,
 }
 
 /* Initialize PNG structure for reading, and allocate any memory needed.
-   This interface is depreciated in favour of the png_create_read_struct(),
+   This interface is deprecated in favour of the png_create_read_struct(),
    and it will eventually disappear. */
 void
 png_read_init(png_structp png_ptr)
@@ -125,7 +148,7 @@ png_read_init(png_structp png_ptr)
 /* Read the information before the actual image data.  This has been
  * changed in v0.90 to allow reading a file that already has the magic
  * bytes read from the stream.  You can tell libpng how many bytes have
- * been read from the beginning of the stream (up to the maxumum of 8)
+ * been read from the beginning of the stream (up to the maximum of 8)
  * via png_set_sig_bytes(), and we will only check the remaining bytes
  * here.  The application can then have access to the signature bytes we
  * read if it is determined that this isn't a valid PNG file.
@@ -258,7 +281,7 @@ png_read_update_info(png_structp png_ptr, png_infop info_ptr)
 
 /* Initialize palette, background, etc, after transformations
  * are set, but before any reading takes place.  This allows
- * the user to obtail a gamma corrected palette, for example.
+ * the user to obtain a gamma-corrected palette, for example.
  * If the user doesn't call this, we will do it ourselves.
  */
 void
@@ -279,6 +302,38 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
    /* save jump buffer and error functions */
    if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
       png_read_start_row(png_ptr);
+   if (png_ptr->row_number == 0 && png_ptr->pass == 0)
+   {
+   /* check for transforms that have been set but were defined out */
+#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED)
+   if (png_ptr->transformations & PNG_INVERT_MONO)
+      png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined.");
+#endif
+#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED)
+   if (png_ptr->transformations & PNG_FILLER)
+      png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined.");
+#endif
+#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && !defined(PNG_READ_PACKSWAP_SUPPORTED)
+   if (png_ptr->transformations & PNG_PACKSWAP)
+      png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined.");
+#endif
+#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED)
+   if (png_ptr->transformations & PNG_PACK)
+      png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined.");
+#endif
+#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED)
+   if (png_ptr->transformations & PNG_SHIFT)
+      png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined.");
+#endif
+#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED)
+   if (png_ptr->transformations & PNG_BGR)
+      png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined.");
+#endif
+#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED)
+   if (png_ptr->transformations & PNG_SWAP_BYTES)
+      png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined.");
+#endif
+   }
 
 #if defined(PNG_READ_INTERLACING_SUPPORTED)
    /* if interlaced and we do not need a new row, combine row and return */
@@ -457,10 +512,10 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
 /* Read one or more rows of image data.  If the image is interlaced,
  * and png_set_interlace_handling() has been called, the rows need to
  * contain the contents of the rows from the previous pass.  If the
- * image has alpha or transparency, and png_handle_alpha() has been
+ * image has alpha or transparency, and png_handle_alpha()[*] has been
  * called, the rows contents must be initialized to the contents of the
  * screen.
- * 
+ *
  * "row" holds the actual image, and pixels are placed in it
  * as they arrive.  If the image is displayed after each pass, it will
  * appear to "sparkle" in.  "display_row" can be used to display a
@@ -474,6 +529,8 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
  * also, but you may.  If the image is not interlaced, or if you have
  * not called png_set_interlace_handling(), the display_row buffer will
  * be ignored, so pass NULL to it.
+ *
+ * [*] png_handle_alpha() does not exist yet, as of libpng version 1.0.3.
  */
 
 void
@@ -488,29 +545,32 @@ png_read_rows(png_structp png_ptr, png_bytepp row,
    /* save jump buffer and error functions */
    rp = row;
    dp = display_row;
-   for (i = 0; i < num_rows; i++)
-   {
-      png_bytep rptr;
-      png_bytep dptr;
+   if (rp != NULL && dp != NULL)
+      for (i = 0; i < num_rows; i++)
+      {
+         png_bytep rptr = *rp++;
+         png_bytep dptr = *dp++;
 
-      if (rp != NULL)
-         rptr = *rp;
-      else
-         rptr = NULL;
-      if (dp != NULL)
-         dptr = *dp;
-      else
-         dptr = NULL;
-      png_read_row(png_ptr, rptr, dptr);
-      if (row != NULL)
+         png_read_row(png_ptr, rptr, dptr);
+      }
+   else if(rp != NULL)
+      for (i = 0; i < num_rows; i++)
+      {
+         png_bytep rptr = *rp;
+         png_read_row(png_ptr, rptr, NULL);
          rp++;
-      if (display_row != NULL)
+      }
+   else if(dp != NULL)
+      for (i = 0; i < num_rows; i++)
+      {
+         png_bytep dptr = *dp;
+         png_read_row(png_ptr, NULL, dptr);
          dp++;
-   }
+      }
 }
 
 /* Read the entire image.  If the image has an alpha channel or a tRNS
- * chunk, and you have called png_handle_alpha(), you will need to
+ * chunk, and you have called png_handle_alpha()[*], you will need to
  * initialize the image to the current image that PNG will be overlaying.
  * We set the num_rows again here, in case it was incorrectly set in
  * png_read_start_row() by a call to png_read_update_info() or
@@ -518,11 +578,13 @@ png_read_rows(png_structp png_ptr, png_bytepp row,
  * prior to either of these functions like it should have been.  You can
  * only call this function once.  If you desire to have an image for
  * each pass of a interlaced image, use png_read_rows() instead.
+ *
+ * [*] png_handle_alpha() does not exist yet, as of libpng version 1.0.3.
  */
 void
 png_read_image(png_structp png_ptr, png_bytepp image)
 {
-   png_uint_32 i;
+   png_uint_32 i,image_height;
    int pass, j;
    png_bytepp rp;
 
@@ -530,12 +592,13 @@ png_read_image(png_structp png_ptr, png_bytepp image)
    /* save jump buffer and error functions */
    pass = png_set_interlace_handling(png_ptr);
 
-   png_ptr->num_rows = png_ptr->height; /* Make sure this is set correctly */
+   image_height=png_ptr->height;
+   png_ptr->num_rows = image_height; /* Make sure this is set correctly */
 
    for (j = 0; j < pass; j++)
    {
       rp = image;
-      for (i = 0; i < png_ptr->height; i++)
+      for (i = 0; i < image_height; i++)
       {
          png_read_row(png_ptr, *rp, NULL);
          rp++;
@@ -647,6 +710,9 @@ png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,
 {
    png_structp png_ptr = NULL;
    png_infop info_ptr = NULL, end_info_ptr = NULL;
+#ifdef PNG_USER_MEM_SUPPORTED
+   png_free_ptr free_fn = NULL;
+#endif /* PNG_USER_MEM_SUPPORTED */
 
    png_debug(1, "in png_destroy_read_struct\n");
    /* save jump buffer and error functions */
@@ -659,6 +725,10 @@ png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,
    if (end_info_ptr_ptr != NULL)
       end_info_ptr = *end_info_ptr_ptr;
 
+#ifdef PNG_USER_MEM_SUPPORTED
+   free_fn = png_ptr->free_fn;
+#endif
+
    png_read_destroy(png_ptr, info_ptr, end_info_ptr);
 
    if (info_ptr != NULL)
@@ -666,7 +736,12 @@ png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,
 #if defined(PNG_READ_tEXt_SUPPORTED) || defined(PNG_READ_zTXt_SUPPORTED)
       png_free(png_ptr, info_ptr->text);
 #endif
+
+#ifdef PNG_USER_MEM_SUPPORTED
+      png_destroy_struct_2((png_voidp)info_ptr, free_fn);
+#else
       png_destroy_struct((png_voidp)info_ptr);
+#endif
       *info_ptr_ptr = (png_infop)NULL;
    }
 
@@ -675,13 +750,21 @@ png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,
 #if defined(PNG_READ_tEXt_SUPPORTED) || defined(PNG_READ_zTXt_SUPPORTED)
       png_free(png_ptr, end_info_ptr->text);
 #endif
+#ifdef PNG_USER_MEM_SUPPORTED
+      png_destroy_struct_2((png_voidp)end_info_ptr, free_fn);
+#else
       png_destroy_struct((png_voidp)end_info_ptr);
+#endif
       *end_info_ptr_ptr = (png_infop)NULL;
    }
 
    if (png_ptr != NULL)
    {
+#ifdef PNG_USER_MEM_SUPPORTED
+      png_destroy_struct_2((png_voidp)png_ptr, free_fn);
+#else
       png_destroy_struct((png_voidp)png_ptr);
+#endif
       *png_ptr_ptr = (png_structp)NULL;
    }
 }
@@ -694,6 +777,9 @@ png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr
    png_error_ptr error_fn;
    png_error_ptr warning_fn;
    png_voidp error_ptr;
+#ifdef PNG_USER_MEM_SUPPORTED
+   png_free_ptr free_fn;
+#endif
 
    png_debug(1, "in png_read_destroy\n");
    /* save jump buffer and error functions */
@@ -729,33 +815,39 @@ png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr
    if (png_ptr->gamma_16_table != NULL)
    {
       int i;
-      for (i = 0; i < (1 << (8 - png_ptr->gamma_shift)); i++)
+      int istop = (1 << (8 - png_ptr->gamma_shift));
+      for (i = 0; i < istop; i++)
       {
          png_free(png_ptr, png_ptr->gamma_16_table[i]);
       }
+   png_free(png_ptr, png_ptr->gamma_16_table);
    }
-#endif
 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
-   png_free(png_ptr, png_ptr->gamma_16_table);
    if (png_ptr->gamma_16_from_1 != NULL)
    {
       int i;
-      for (i = 0; i < (1 << (8 - png_ptr->gamma_shift)); i++)
+      int istop = (1 << (8 - png_ptr->gamma_shift));
+      for (i = 0; i < istop; i++)
       {
          png_free(png_ptr, png_ptr->gamma_16_from_1[i]);
       }
-   }
    png_free(png_ptr, png_ptr->gamma_16_from_1);
+   }
    if (png_ptr->gamma_16_to_1 != NULL)
    {
       int i;
-      for (i = 0; i < (1 << (8 - png_ptr->gamma_shift)); i++)
+      int istop = (1 << (8 - png_ptr->gamma_shift));
+      for (i = 0; i < istop; i++)
       {
          png_free(png_ptr, png_ptr->gamma_16_to_1[i]);
       }
-   }
    png_free(png_ptr, png_ptr->gamma_16_to_1);
+   }
 #endif
+#endif
+#if defined(PNG_TIME_RFC1123_SUPPORTED)
+   png_free(png_ptr, png_ptr->time_buffer);
+#endif /* PNG_TIME_RFC1123_SUPPORTED */
 
    inflateEnd(&png_ptr->zstream);
 #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
@@ -770,12 +862,18 @@ png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr
    error_fn = png_ptr->error_fn;
    warning_fn = png_ptr->warning_fn;
    error_ptr = png_ptr->error_ptr;
+#ifdef PNG_USER_MEM_SUPPORTED
+   free_fn = png_ptr->free_fn;
+#endif
 
    png_memset(png_ptr, 0, sizeof (png_struct));
 
    png_ptr->error_fn = error_fn;
    png_ptr->warning_fn = warning_fn;
    png_ptr->error_ptr = error_ptr;
+#ifdef PNG_USER_MEM_SUPPORTED
+   png_ptr->free_fn = free_fn;
+#endif
 
    png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
 }
index 6c6710a46f660cafe98d34960605e8f01acac244..23bbb2b6603512a7765355c312a0e202748222bc 100644 (file)
@@ -1,23 +1,22 @@
 
 /* pngrio.c - functions for data input
  *
- * libpng 1.0.1
+ * libpng 1.0.3 - January 14, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, Glenn Randers-Pehrson
- * March 15, 1998
+ * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
  *
- * This file provides a location for all input.  Users which need
- * special handling are expected to write a function which has the same
- * arguments as this, and perform a similar function, but possibly has
- * a different input method.  Note that you shouldn't change this
+ * This file provides a location for all input.  Users who need
+ * special handling are expected to write a function that has the same
+ * arguments as this and performs a similar function, but that possibly
+ * has a different input method.  Note that you shouldn't change this
  * function, but rather write a replacement function and then make
  * libpng use it at run time with png_set_read_fn(...).
  */
 
 #define PNG_INTERNAL
-#include "../png/png.h"
+#include "png.h"
 
 /* Read the data from whatever input you are using.  The default routine
    reads from a file pointer.  Note that this routine sometimes gets called
@@ -35,7 +34,7 @@ png_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
 }
 
 #if !defined(PNG_NO_STDIO)
-/* This is the function which does the actual reading of data.  If you are
+/* This is the function that 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. */
@@ -61,10 +60,10 @@ png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
    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)
 {
@@ -114,10 +113,10 @@ png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
    png_ptr      - pointer to a png input data structure
    io_ptr       - pointer to user supplied structure containing info about
                   the input functions.  May be NULL.
-   read_data_fn - pointer to a new input function which takes as it's
+   read_data_fn - pointer to a new input function that takes as its
                   arguments a pointer to a png_struct, a pointer to
                   a location where input data can be stored, and a 32-bit
-                  unsigned int which is the number of bytes to be read.
+                  unsigned int that is the number of bytes to be read.
                   To exit and output any fatal error messages the new write
                   function should call png_error(png_ptr, "Error msg"). */
 void
@@ -136,7 +135,14 @@ png_set_read_fn(png_structp png_ptr, png_voidp io_ptr,
 #endif
 
    /* It is an error to write to a read device */
-   png_ptr->write_data_fn = NULL;
+   if (png_ptr->write_data_fn != NULL)
+   {
+      png_ptr->write_data_fn = NULL;
+      png_warning(png_ptr,
+         "It's an error to set both read_data_fn and write_data_fn in the ");
+      png_warning(png_ptr,
+         "same structure.  Resetting write_data_fn to NULL.");
+   }
 
 #if defined(PNG_WRITE_FLUSH_SUPPORTED)
    png_ptr->output_flush_fn = NULL;
index 684bf5f2537d0374629bd23877b66387513f2779..ce486bd06d604c63a6d14f945fc3f7b8f53c6a18 100644 (file)
@@ -1,61 +1,20 @@
 
 /* pngrtran.c - transforms the data in a row for PNG readers
  *
- * libpng 1.0.1
+ * libpng 1.0.3 - January 14, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, Glenn Randers-Pehrson
- * March 15, 1998
+ * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
  *
- * This file contains functions optionally called by an application 
+ * This file contains functions optionally called by an application
  * in order to tell libpng how to handle data when reading a PNG.
- * Transformations which are used in both reading and writing are
+ * Transformations that are used in both reading and writing are
  * in pngtrans.c.
  */
 
 #define PNG_INTERNAL
-#include "../png/png.h"
-
-#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED
-/* With these routines, we avoid an integer divide, which will be slower on
- * many machines.  However, it does take more operations than the corresponding
- * divide method, so it may be slower on some RISC systems.  There are two
- * shifts (by 8 or 16 bits) and an addition, versus a single integer divide.
- *
- * Note that the rounding factors are NOT supposed to be the same!  128 and
- * 32768 are correct for the NODIV code; 127 and 32767 are correct for the
- * standard method.
- *
- * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ]
- */
-
-   /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */
-#  define png_composite(composite, fg, alpha, bg) \
-     { png_uint_16 temp = ((png_uint_16)(fg) * (png_uint_16)(alpha) + \
-                        (png_uint_16)(bg)*(png_uint_16)(255 - \
-                        (png_uint_16)(alpha)) + (png_uint_16)128); \
-       (composite) = (png_byte)((temp + (temp >> 8)) >> 8); }
-#  define png_composite_16(composite, fg, alpha, bg) \
-     { png_uint_32 temp = ((png_uint_32)(fg) * (png_uint_32)(alpha) + \
-                        (png_uint_32)(bg)*(png_uint_32)(65535L - \
-                        (png_uint_32)(alpha)) + (png_uint_32)32768L); \
-       (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); }
-
-#else  /* standard method using integer division */
-
-   /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */
-#  define png_composite(composite, fg, alpha, bg) \
-     (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \
-       (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \
-       (png_uint_16)127) / 255)
-#  define png_composite_16(composite, fg, alpha, bg) \
-     (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \
-       (png_uint_32)(bg)*(png_uint_32)(65535L - (png_uint_32)(alpha)) + \
-       (png_uint_32)32767) / (png_uint_32)65535L)
-
-#endif /* ?PNG_READ_COMPOSITE_NODIV_SUPPORTED */
-
+#include "png.h"
 
 /* Set the action on getting a CRC error for an ancillary or critical chunk. */
 void
@@ -125,11 +84,21 @@ png_set_background(png_structp png_ptr,
    }
 
    png_ptr->transformations |= PNG_BACKGROUND;
-   png_memcpy(&(png_ptr->background), background_color,
-      sizeof(png_color_16));
+   png_memcpy(&(png_ptr->background), background_color, sizeof(png_color_16));
    png_ptr->background_gamma = (float)background_gamma;
    png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
    png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0);
+
+   /* Note:  if need_expand is set and color_type is either RGB or RGB_ALPHA
+    * (in which case need_expand is superfluous anyway), the background color
+    * might actually be gray yet not be flagged as such. This is not a problem
+    * for the current code, which uses PNG_FLAG_BACKGROUND_IS_GRAY only to
+    * decide when to do the png_do_gray_to_rgb() transformation.
+    */
+   if ((need_expand && !(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) ||
+       (!need_expand && background_color->red == background_color->green &&
+        background_color->red == background_color->blue))
+      png_ptr->flags |= PNG_FLAG_BACKGROUND_IS_GRAY;
 }
 #endif
 
@@ -238,11 +207,11 @@ png_set_dither(png_structp png_ptr, png_colorp palette,
          /* swap the palette around, and set up a table, if necessary */
          if (full_dither)
          {
-            int j;
+            int j = num_palette;
 
             /* put all the useful colors within the max, but don't
                move the others */
-            for (i = 0, j = num_palette; i < maximum_colors; i++)
+            for (i = 0; i < maximum_colors; i++)
             {
                if ((int)sort[i] >= maximum_colors)
                {
@@ -255,11 +224,11 @@ png_set_dither(png_structp png_ptr, png_colorp palette,
          }
          else
          {
-            int j;
+            int j = num_palette;
 
             /* move all the used colors inside the max limit, and
                develop a translation table */
-            for (i = 0, j = num_palette; i < maximum_colors; i++)
+            for (i = 0; i < maximum_colors; i++)
             {
                /* only move the colors we need to */
                if ((int)sort[i] >= maximum_colors)
@@ -315,8 +284,8 @@ png_set_dither(png_structp png_ptr, png_colorp palette,
             don't always behave themselves with only a few colors
             as input.  So we will just find the closest two colors,
             and throw out one of them (chosen somewhat randomly).
-            [I don't understand this at all, so if someone wants to
-             work on improving it, be my guest - AED]
+            [We don't understand this at all, so if someone wants to
+             work on improving it, be our guest - AED, GRP]
             */
          int i;
          int max_d;
@@ -340,7 +309,7 @@ png_set_dither(png_structp png_ptr, png_colorp palette,
             palette_to_index[i] = (png_byte)i;
          }
 
-         hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 * 
+         hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 *
             sizeof (png_dsortp)));
          for (i = 0; i < 769; i++)
             hash[i] = NULL;
@@ -447,9 +416,7 @@ png_set_dither(png_structp png_ptr, png_colorp palette,
             {
                if (hash[i] != NULL)
                {
-                  png_dsortp p;
-
-                  p = hash[i];
+                  png_dsortp p = hash[i];
                   while (p)
                   {
                      png_dsortp t;
@@ -478,17 +445,13 @@ png_set_dither(png_structp png_ptr, png_colorp palette,
    if (full_dither)
    {
       int i;
-      int total_bits, num_red, num_green, num_blue;
-      png_size_t num_entries;
       png_bytep distance;
-
-      total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS +
+      int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS +
          PNG_DITHER_BLUE_BITS;
-
-      num_red = (1 << PNG_DITHER_RED_BITS);
-      num_green = (1 << PNG_DITHER_GREEN_BITS);
-      num_blue = (1 << PNG_DITHER_BLUE_BITS);
-      num_entries = ((png_size_t)1 << total_bits);
+      int num_red = (1 << PNG_DITHER_RED_BITS);
+      int num_green = (1 << PNG_DITHER_GREEN_BITS);
+      int num_blue = (1 << PNG_DITHER_BLUE_BITS);
+      png_size_t num_entries = ((png_size_t)1 << total_bits);
 
       png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr,
          (png_uint_32)(num_entries * sizeof (png_byte)));
@@ -502,34 +465,29 @@ png_set_dither(png_structp png_ptr, png_colorp palette,
 
       for (i = 0; i < num_palette; i++)
       {
-         int r, g, b, ir, ig, ib;
-
-         r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS));
-         g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS));
-         b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS));
+         int ir, ig, ib;
+         int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS));
+         int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS));
+         int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS));
 
          for (ir = 0; ir < num_red; ir++)
          {
-            int dr, index_r;
+            int dr = abs(ir - r);
+            int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS));
 
-            dr = abs(ir - r);
-            index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS));
             for (ig = 0; ig < num_green; ig++)
             {
-               int dg, dt, dm, index_g;
+               int dg = abs(ig - g);
+               int dt = dr + dg;
+               int dm = ((dr > dg) ? dr : dg);
+               int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS);
 
-               dg = abs(ig - g);
-               dt = dr + dg;
-               dm = ((dr > dg) ? dr : dg);
-               index_g = index_r | (ig << PNG_DITHER_BLUE_BITS);
                for (ib = 0; ib < num_blue; ib++)
                {
-                  int d_index, db, dmax, d;
-
-                  d_index = index_g | ib;
-                  db = abs(ib - b);
-                  dmax = ((dm > db) ? dm : db);
-                  d = dmax + dt + db;
+                  int d_index = index_g | ib;
+                  int db = abs(ib - b);
+                  int dmax = ((dm > db) ? dm : db);
+                  int d = dmax + dt + db;
 
                   if (d < (int)distance[d_index])
                   {
@@ -565,7 +523,7 @@ png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
 
 #if defined(PNG_READ_EXPAND_SUPPORTED)
 /* Expand paletted images to rgb, expand grayscale images of
- * less then 8 bit depth to 8 bit depth, and expand tRNS chunks
+ * less than 8 bit depth to 8 bit depth, and expand tRNS chunks
  * to alpha channels.
  */
 void
@@ -586,17 +544,49 @@ png_set_gray_to_rgb(png_structp png_ptr)
 #endif
 
 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
-/* Convert a RGB image to a grayscale of the given width.  This would
- * allow us, for example, to convert a 24 bpp RGB image into an 8 or
- * 16 bpp grayscale image. (Not yet implemented.)
+/* Convert a RGB image to a grayscale of the same width.  This allows us,
+ * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
  */
 void
-png_set_rgb_to_gray(png_structp png_ptr, int gray_bits)
+png_set_rgb_to_gray(png_structp png_ptr, int error_action, float red,
+  float green)
 {
    png_debug(1, "in png_set_rgb_to_gray\n");
-   png_ptr->transformations |= PNG_RGB_TO_GRAY;
-   /* Need to do something with gray_bits here. */
-   png_warning(png_ptr, "RGB to GRAY transformation is not yet implemented.");
+   switch(error_action)
+   {
+      case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY;
+              break;
+      case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
+              break;
+      case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
+   }
+   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+#if defined(PNG_READ_EXPAND_SUPPORTED)
+      png_ptr->transformations |= PNG_EXPAND;
+#else
+   {
+      png_warning(png_ptr, "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED.");
+      png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
+   }
+#endif
+   {
+      png_byte red_byte = (png_byte)(red*255.0 + 0.5);
+      png_byte green_byte = (png_byte)(green*255.0 + 0.5);
+      if(red < 0.0 || green < 0.0)
+      {
+         red_byte = 54;
+         green_byte = 183;
+      }
+      else if(red_byte + green_byte > 255)
+      {
+         png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
+         red_byte = 54;
+         green_byte = 183;
+      }
+      png_ptr->rgb_to_gray_red_coeff   = red_byte;
+      png_ptr->rgb_to_gray_green_coeff = green_byte;
+      png_ptr->rgb_to_gray_blue_coeff  = 255 - red_byte - green_byte;
+   }
 }
 #endif
 
@@ -617,15 +607,20 @@ png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
 void
 png_init_read_transformations(png_structp png_ptr)
 {
-   int color_type;
-
    png_debug(1, "in png_init_read_transformations\n");
-   color_type = png_ptr->color_type;
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   if(png_ptr != NULL)
+#endif
+  {
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \
+ || defined(PNG_READ_GAMMA_SUPPORTED)
+   int color_type = png_ptr->color_type;
+#endif
 
 #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
    if (png_ptr->transformations & PNG_BACKGROUND_EXPAND)
    {
-      if (color_type == PNG_COLOR_TYPE_GRAY)
+      if (!(color_type & PNG_COLOR_MASK_COLOR))  /* i.e., GRAY or GRAY_ALPHA */
       {
          /* expand background chunk. */
          switch (png_ptr->bit_depth)
@@ -668,10 +663,11 @@ png_init_read_transformations(png_structp png_ptr)
            if (!(png_ptr->transformations & PNG_EXPAND))
 #endif
            {
-           /* invert the alpha channel (in tRNS) unless the pixels are 
+           /* invert the alpha channel (in tRNS) unless the pixels are
               going to be expanded, in which case leave it for later */
-              int i;
-              for (i=0; i<(int)png_ptr->num_trans; i++)
+              int i,istop;
+              istop=(int)png_ptr->num_trans;
+              for (i=0; i<istop; i++)
                  png_ptr->trans[i] = 255 - png_ptr->trans[i];
            }
         }
@@ -685,7 +681,7 @@ png_init_read_transformations(png_structp png_ptr)
    png_ptr->background_1 = png_ptr->background;
 #endif
 #if defined(PNG_READ_GAMMA_SUPPORTED)
-   if (png_ptr->transformations & PNG_GAMMA)
+   if (png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY))
    {
       png_build_gamma_table(png_ptr);
 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
@@ -693,12 +689,10 @@ png_init_read_transformations(png_structp png_ptr)
       {
          if (color_type == PNG_COLOR_TYPE_PALETTE)
          {
-            int num_palette, i;
             png_color back, back_1;
-            png_colorp palette;
-
-            palette = png_ptr->palette;
-            num_palette = png_ptr->num_palette;
+            png_colorp palette = png_ptr->palette;
+            int num_palette = png_ptr->num_palette;
+            int i;
 
             if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
             {
@@ -795,11 +789,9 @@ png_init_read_transformations(png_structp png_ptr)
          else
          /* color_type != PNG_COLOR_TYPE_PALETTE */
          {
-            double g, gs, m;
-
-            m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1);
-            g = 1.0;
-            gs = 1.0;
+            double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1);
+            double g = 1.0;
+            double gs = 1.0;
 
             switch (png_ptr->background_gamma_type)
             {
@@ -849,11 +841,9 @@ png_init_read_transformations(png_structp png_ptr)
 #endif
       if (color_type == PNG_COLOR_TYPE_PALETTE)
       {
-         int num_palette, i;
-         png_colorp palette;
-
-         palette = png_ptr->palette;
-         num_palette = png_ptr->num_palette;
+         png_colorp palette = png_ptr->palette;
+         int num_palette = png_ptr->num_palette;
+         int i;
 
          for (i = 0; i < num_palette; i++)
          {
@@ -873,15 +863,15 @@ png_init_read_transformations(png_structp png_ptr)
        color_type == PNG_COLOR_TYPE_PALETTE)
    {
       int i;
+      int istop = (int)png_ptr->num_trans;
       png_color back;
-      png_colorp palette;
+      png_colorp palette = png_ptr->palette;
 
-      palette = png_ptr->palette;
       back.red   = (png_byte)png_ptr->background.red;
       back.green = (png_byte)png_ptr->background.green;
       back.blue  = (png_byte)png_ptr->background.blue;
 
-      for (i = 0; i < (int)png_ptr->num_trans; i++)
+      for (i = 0; i < istop; i++)
       {
          if (png_ptr->trans[i] == 0)
          {
@@ -889,6 +879,7 @@ png_init_read_transformations(png_structp png_ptr)
          }
          else if (png_ptr->trans[i] != 0xff)
          {
+            /* The png_composite() macro is defined in png.h */
             png_composite(palette[i].red, palette[i].red,
                png_ptr->trans[i], back.red);
             png_composite(palette[i].green, palette[i].green,
@@ -905,18 +896,18 @@ png_init_read_transformations(png_structp png_ptr)
       color_type == PNG_COLOR_TYPE_PALETTE)
    {
       png_uint_16 i;
-      int sr, sg, sb;
+      png_uint_16 istop = png_ptr->num_palette;
+      int sr = 8 - png_ptr->sig_bit.red;
+      int sg = 8 - png_ptr->sig_bit.green;
+      int sb = 8 - png_ptr->sig_bit.blue;
 
-      sr = 8 - png_ptr->sig_bit.red;
       if (sr < 0 || sr > 8)
          sr = 0;
-      sg = 8 - png_ptr->sig_bit.green;
       if (sg < 0 || sg > 8)
          sg = 0;
-      sb = 8 - png_ptr->sig_bit.blue;
       if (sb < 0 || sb > 8)
          sb = 0;
-      for (i = 0; i < png_ptr->num_palette; i++)
+      for (i = 0; i < istop; i++)
       {
          png_ptr->palette[i].red >>= sr;
          png_ptr->palette[i].green >>= sg;
@@ -924,6 +915,7 @@ png_init_read_transformations(png_structp png_ptr)
       }
    }
 #endif
+ }
 }
 
 /* Modify the info structure to reflect the transformations.  The
@@ -966,6 +958,11 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
    }
 #endif
 
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+   if (png_ptr->transformations & PNG_GAMMA)
+      info_ptr->gamma = png_ptr->gamma;
+#endif
+
 #if defined(PNG_READ_16_TO_8_SUPPORTED)
    if ((png_ptr->transformations & PNG_16_TO_8) && info_ptr->bit_depth == 16)
       info_ptr->bit_depth = 8;
@@ -993,6 +990,11 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
       info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
 #endif
 
+#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+   if (png_ptr->transformations & PNG_RGB_TO_GRAY)
+      info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR;
+#endif
+
    if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
       info_ptr->channels = 1;
    else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
@@ -1005,20 +1007,19 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
       info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
 #endif
 
+   if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
+      info_ptr->channels++;
+
 #if defined(PNG_READ_FILLER_SUPPORTED)
-   if ((png_ptr->transformations & PNG_FILLER) &&
-       info_ptr->color_type & PNG_COLOR_TYPE_RGB &&
-       info_ptr->channels == 3)
-   {
-      info_ptr->channels = 4;
-   }
+   /* STRIP_ALPHA and FILLER allowed:  MASK_ALPHA bit stripped above */
+   if (png_ptr->transformations & PNG_FILLER &&
+       (info_ptr->color_type == PNG_COLOR_TYPE_RGB ||
+        info_ptr->color_type == PNG_COLOR_TYPE_GRAY))
+      ++info_ptr->channels;
 #endif
 
-   if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
-      info_ptr->channels++;
    info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
       info_ptr->bit_depth);
-
    info_ptr->rowbytes = ((info_ptr->width * info_ptr->pixel_depth + 7) >> 3);
 }
 
@@ -1053,7 +1054,7 @@ png_do_read_transformations(png_structp png_ptr)
          png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
             png_ptr->palette, png_ptr->trans, png_ptr->num_trans);
       }
-      else if (png_ptr->transformations & PNG_EXPAND)
+      else
       {
          if (png_ptr->num_trans)
             png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
@@ -1071,6 +1072,60 @@ png_do_read_transformations(png_structp png_ptr)
          PNG_FLAG_FILLER_AFTER);
 #endif
 
+#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+   if (png_ptr->transformations & PNG_RGB_TO_GRAY)
+   {
+      int rgb_error =
+         png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1);
+      if(rgb_error)
+      {
+         png_ptr->rgb_to_gray_status=1;
+         if(png_ptr->transformations == PNG_RGB_TO_GRAY_WARN)
+            png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
+         if(png_ptr->transformations == PNG_RGB_TO_GRAY_ERR)
+            png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
+      }
+   }
+#endif
+
+/*
+From Andreas Dilger e-mail to png-implement, 26 March 1998:
+
+  In most cases, the "simple transparency" should be done prior to doing
+  gray-to-RGB, or you will have to test 3x as many bytes to check if a
+  pixel is transparent.  You would also need to make sure that the
+  transparency information is upgraded to RGB.
+
+  To summarize, the current flow is:
+  - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
+                                  with background "in place" if transparent,
+                                  convert to RGB if necessary
+  - Gray + alpha -> composite with gray background and remove alpha bytes,
+                                  convert to RGB if necessary
+
+  To support RGB backgrounds for gray images we need:
+  - Gray + simple transparency -> convert to RGB + simple transparency, compare
+                                  3 or 6 bytes and composite with background
+                                  "in place" if transparent (3x compare/pixel
+                                  compared to doing composite with gray bkgrnd)
+  - Gray + alpha -> convert to RGB + alpha, composite with background and
+                                  remove alpha bytes (3x float operations/pixel
+                                  compared with composite on gray background)
+
+  Greg's change will do this.  The reason it wasn't done before is for
+  performance, as this increases the per-pixel operations.  If we would check
+  in advance if the background was gray or RGB, and position the gray-to-RGB
+  transform appropriately, then it would save a lot of work/time.
+ */
+
+#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
+   /* if gray -> RGB, do so now only if background is non-gray; else do later
+    * for performance reasons */
+   if (png_ptr->transformations & PNG_GRAY_TO_RGB &&
+       !(png_ptr->flags & PNG_FLAG_BACKGROUND_IS_GRAY))
+      png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+
 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
    if ((png_ptr->transformations & PNG_BACKGROUND) &&
       ((png_ptr->num_trans != 0 ) ||
@@ -1086,18 +1141,17 @@ png_do_read_transformations(png_structp png_ptr)
 
 #if defined(PNG_READ_GAMMA_SUPPORTED)
    if ((png_ptr->transformations & PNG_GAMMA) &&
-      !(png_ptr->transformations & PNG_BACKGROUND) &&
+#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+      !((png_ptr->transformations & PNG_BACKGROUND) &&
+      ((png_ptr->num_trans != 0) ||
+      (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
+#endif
       (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
       png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1,
          png_ptr->gamma_table, png_ptr->gamma_16_table,
          png_ptr->gamma_shift);
 #endif
 
-#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
-   if (png_ptr->transformations & PNG_RGB_TO_GRAY)
-      png_do_rgb_to_gray(&(png_ptr->row_info), png_ptr->row_buf + 1);
-#endif
-
 #if defined(PNG_READ_16_TO_8_SUPPORTED)
    if (png_ptr->transformations & PNG_16_TO_8)
       png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
@@ -1140,7 +1194,9 @@ png_do_read_transformations(png_structp png_ptr)
 #endif
 
 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
-   if (png_ptr->transformations & PNG_GRAY_TO_RGB)
+   /* if gray -> RGB, do so now only if we did not do so above */
+   if (png_ptr->transformations & PNG_GRAY_TO_RGB &&
+       png_ptr->flags & PNG_FLAG_BACKGROUND_IS_GRAY)
       png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
 #endif
 
@@ -1199,17 +1255,17 @@ png_do_unpack(png_row_infop row_info, png_bytep row)
    if (row_info->bit_depth < 8)
 #endif
    {
-      png_uint_32 shift, i;
-      png_bytep sp, dp;
+      png_uint_32 i;
+      png_uint_32 row_width=row_info->width;
 
       switch (row_info->bit_depth)
       {
          case 1:
          {
-            sp = row + (png_size_t)((row_info->width - 1) >> 3);
-            dp = row + (png_size_t)row_info->width - 1;
-            shift = 7 - (int)((row_info->width + 7) & 7);
-            for (i = 0; i < row_info->width; i++)
+            png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
+            png_bytep dp = row + (png_size_t)row_width - 1;
+            png_uint_32 shift = 7 - (int)((row_width + 7) & 7);
+            for (i = 0; i < row_width; i++)
             {
                *dp = (png_byte)((*sp >> shift) & 0x1);
                if (shift == 7)
@@ -1227,10 +1283,10 @@ png_do_unpack(png_row_infop row_info, png_bytep row)
          case 2:
          {
 
-            sp = row + (png_size_t)((row_info->width - 1) >> 2);
-            dp = row + (png_size_t)row_info->width - 1;
-            shift = (int)((3 - ((row_info->width + 3) & 3)) << 1);
-            for (i = 0; i < row_info->width; i++)
+            png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
+            png_bytep dp = row + (png_size_t)row_width - 1;
+            png_uint_32 shift = (int)((3 - ((row_width + 3) & 3)) << 1);
+            for (i = 0; i < row_width; i++)
             {
                *dp = (png_byte)((*sp >> shift) & 0x3);
                if (shift == 6)
@@ -1247,10 +1303,10 @@ png_do_unpack(png_row_infop row_info, png_bytep row)
          }
          case 4:
          {
-            sp = row + (png_size_t)((row_info->width - 1) >> 1);
-            dp = row + (png_size_t)row_info->width - 1;
-            shift = (int)((1 - ((row_info->width + 1) & 1)) << 2);
-            for (i = 0; i < row_info->width; i++)
+            png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
+            png_bytep dp = row + (png_size_t)row_width - 1;
+            png_uint_32 shift = (int)((1 - ((row_width + 1) & 1)) << 2);
+            for (i = 0; i < row_width; i++)
             {
                *dp = (png_byte)((*sp >> shift) & 0xf);
                if (shift == 4)
@@ -1268,7 +1324,7 @@ png_do_unpack(png_row_infop row_info, png_bytep row)
       }
       row_info->bit_depth = 8;
       row_info->pixel_depth = (png_byte)(8 * row_info->channels);
-      row_info->rowbytes = row_info->width * row_info->channels;
+      row_info->rowbytes = row_width * row_info->channels;
    }
 }
 #endif
@@ -1290,10 +1346,11 @@ png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
        row_info->color_type != PNG_COLOR_TYPE_PALETTE)
    {
       int shift[4];
-      int channels, c;
-      png_uint_16 value;
+      int channels = 0;
+      int c;
+      png_uint_16 value = 0;
+      png_uint_32 row_width = row_info->width;
 
-      channels = 0;
       if (row_info->color_type & PNG_COLOR_MASK_COLOR)
       {
          shift[channels++] = row_info->bit_depth - sig_bits->red;
@@ -1309,8 +1366,6 @@ png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
          shift[channels++] = row_info->bit_depth - sig_bits->alpha;
       }
 
-      value = 0;
-
       for (c = 0; c < channels; c++)
       {
          if (shift[c] <= 0)
@@ -1328,57 +1383,54 @@ png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
          {
             png_bytep bp;
             png_uint_32 i;
+            png_uint_32 istop = row_info->rowbytes;
 
-            for (bp = row, i = 0; i < row_info->rowbytes; i++, bp++)
+            for (bp = row, i = 0; i < istop; i++)
             {
                *bp >>= 1;
-               *bp &= 0x55;
+               *bp++ &= 0x55;
             }
             break;
          }
          case 4:
          {
-            png_bytep bp;
-            png_byte mask;
+            png_bytep bp = row;
             png_uint_32 i;
-
-            mask = (png_byte)(((int)0xf0 >> shift[0]) & (int)0xf0) |
+            png_uint_32 istop = row_info->rowbytes;
+            png_byte mask = (png_byte)(((int)0xf0 >> shift[0]) & (int)0xf0) |
                (png_byte)((int)0xf >> shift[0]);
-            for (bp = row, i = 0; i < row_info->rowbytes; i++, bp++)
+
+            for (i = 0; i < istop; i++)
             {
                *bp >>= shift[0];
-               *bp &= mask;
+               *bp++ &= mask;
             }
             break;
          }
          case 8:
          {
-            png_bytep bp;
+            png_bytep bp = row;
             png_uint_32 i;
+            png_uint_32 istop = row_width * channels;
 
-            for (bp = row, i = 0; i < row_info->width; i++)
+            for (i = 0; i < istop; i++)
             {
-               for (c = 0; c < (int)row_info->channels; c++, bp++)
-               {
-                  *bp >>= shift[c];
-               }
+               *bp++ >>= shift[i%channels];
             }
             break;
          }
          case 16:
          {
-            png_bytep bp;
-            png_size_t i;
+            png_bytep bp = row;
+            png_uint_32 i;
+            png_uint_32 istop = channels * row_width;
 
-            for (bp = row, i = 0; i < row_info->width; i++)
+            for (i = 0; i < istop; i++)
             {
-               for (c = 0; c < (int)row_info->channels; c++, bp += 2)
-               {
-                  value = (png_uint_16)((*bp << 8) + *(bp + 1));
-                  value >>= shift[c];
-                  *bp = (png_byte)(value >> 8);
-                  *(bp + 1) = (png_byte)(value & 0xff);
-               }
+               value = (png_uint_16)((*bp << 8) + *(bp + 1));
+               value >>= shift[i%channels];
+               *bp++ = (png_byte)(value >> 8);
+               *bp++ = (png_byte)(value & 0xff);
             }
             break;
          }
@@ -1399,38 +1451,39 @@ png_do_chop(png_row_infop row_info, png_bytep row)
    if (row_info->bit_depth == 16)
 #endif
    {
-      png_bytep sp, dp;
+      png_bytep sp = row;
+      png_bytep dp = row;
       png_uint_32 i;
+      png_uint_32 istop = row_info->width * row_info->channels;
 
-      sp = row;
-      dp = row;
-      for (i = 0; i < row_info->width * row_info->channels; i++, sp += 2, dp++)
+      for (i = 0; i<istop; i++, sp += 2, dp++)
       {
 #if defined(PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED)
-         /* This does a more accurate scaling of the 16-bit color
-          * value, rather than a simple low-byte truncation.
-          *
-          * What the ideal calculation should be:
-         *dp = (((((png_uint_32)(*sp) << 8) |
-                   (png_uint_32)(*(sp + 1))) * 255 + 127) / (png_uint_32)65535L;
-
-
-          * GRR: no, I think this is what it really should be:
-         *dp = (((((png_uint_32)(*sp) << 8) |
-                   (png_uint_32)(*(sp + 1))) + 128L) / (png_uint_32)257L;
+      /* This does a more accurate scaling of the 16-bit color
+       * value, rather than a simple low-byte truncation.
+       *
+       * What the ideal calculation should be:
+       *   *dp = (((((png_uint_32)(*sp) << 8) |
+       *          (png_uint_32)(*(sp + 1))) * 255 + 127) / (png_uint_32)65535L;
+       *
+       * GRR: no, I think this is what it really should be:
+       *   *dp = (((((png_uint_32)(*sp) << 8) |
+       *           (png_uint_32)(*(sp + 1))) + 128L) / (png_uint_32)257L;
+       *
+       * GRR: here's the exact calculation with shifts:
+       *   temp = (((png_uint_32)(*sp) << 8) | (png_uint_32)(*(sp + 1))) + 128L;
+       *   *dp = (temp - (temp >> 8)) >> 8;
+       *
+       * Approximate calculation with shift/add instead of multiply/divide:
+       *   *dp = ((((png_uint_32)(*sp) << 8) |
+       *          (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8;
+       *
+       * What we actually do to avoid extra shifting and conversion:
+       */
 
-          * GRR: here's the exact calculation with shifts:
-         temp = (((png_uint_32)(*sp) << 8) | (png_uint_32)(*(sp + 1))) + 128L;
-         *dp = (temp - (temp >> 8)) >> 8;
-
-
-          * Approximate calculation with shift/add instead of multiply/divide:
-         *dp = ((((png_uint_32)(*sp) << 8) |
-                  (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8;
-
-          * What we actually do to avoid extra shifting and conversion: */
          *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0);
 #else
+       /* Simply discard the low order byte */
          *dp = *sp;
 #endif
       }
@@ -1450,17 +1503,18 @@ png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
    if (row != NULL && row_info != NULL)
 #endif
    {
+      png_uint_32 row_width = row_info->width;
       if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
       {
          /* This converts from RGBA to ARGB */
          if (row_info->bit_depth == 8)
          {
-            png_bytep sp, dp;
+            png_bytep sp = row + row_info->rowbytes;
+            png_bytep dp = sp;
             png_byte save;
             png_uint_32 i;
 
-            for (i = 0, sp = dp = row + row_info->rowbytes;
-               i < row_info->width; i++)
+            for (i = 0; i < row_width; i++)
             {
                save = *(--sp);
                *(--dp) = *(--sp);
@@ -1472,12 +1526,12 @@ png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
          /* This converts from RRGGBBAA to AARRGGBB */
          else
          {
-            png_bytep sp, dp;
+            png_bytep sp = row + row_info->rowbytes;
+            png_bytep dp = sp;
             png_byte save[2];
             png_uint_32 i;
 
-            for (i = 0, sp = dp = row + row_info->rowbytes;
-               i < row_info->width; i++)
+            for (i = 0; i < row_width; i++)
             {
                save[0] = *(--sp);
                save[1] = *(--sp);
@@ -1497,12 +1551,12 @@ png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
          /* This converts from GA to AG */
          if (row_info->bit_depth == 8)
          {
-            png_bytep sp, dp;
+            png_bytep sp = row + row_info->rowbytes;
+            png_bytep dp = sp;
             png_byte save;
             png_uint_32 i;
 
-            for (i = 0, sp = dp = row + row_info->rowbytes;
-               i < row_info->width; i++)
+            for (i = 0; i < row_width; i++)
             {
                save = *(--sp);
                *(--dp) = *(--sp);
@@ -1512,12 +1566,12 @@ png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
          /* This converts from GGAA to AAGG */
          else
          {
-            png_bytep sp, dp;
+            png_bytep sp = row + row_info->rowbytes;
+            png_bytep dp = sp;
             png_byte save[2];
             png_uint_32 i;
 
-            for (i = 0, sp = dp = row + row_info->rowbytes;
-               i < row_info->width; i++)
+            for (i = 0; i < row_width; i++)
             {
                save[0] = *(--sp);
                save[1] = *(--sp);
@@ -1541,16 +1595,17 @@ png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
    if (row != NULL && row_info != NULL)
 #endif
    {
+      png_uint_32 row_width = row_info->width;
       if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
       {
          /* This inverts the alpha channel in RGBA */
          if (row_info->bit_depth == 8)
          {
-            png_bytep sp, dp;
+            png_bytep sp = row + row_info->rowbytes;
+            png_bytep dp = sp;
             png_uint_32 i;
 
-            for (i = 0, sp = dp = row + row_info->rowbytes;
-               i < row_info->width; i++)
+            for (i = 0; i < row_width; i++)
             {
                *(--dp) = 255 - *(--sp);
                *(--dp) = *(--sp);
@@ -1561,11 +1616,11 @@ png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
          /* This inverts the alpha channel in RRGGBBAA */
          else
          {
-            png_bytep sp, dp;
+            png_bytep sp = row + row_info->rowbytes;
+            png_bytep dp = sp;
             png_uint_32 i;
 
-            for (i = 0, sp = dp = row + row_info->rowbytes;
-               i < row_info->width; i++)
+            for (i = 0; i < row_width; i++)
             {
                *(--dp) = 255 - *(--sp);
                *(--dp) = 255 - *(--sp);
@@ -1583,11 +1638,11 @@ png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
          /* This inverts the alpha channel in GA */
          if (row_info->bit_depth == 8)
          {
-            png_bytep sp, dp;
+            png_bytep sp = row + row_info->rowbytes;
+            png_bytep dp = sp;
             png_uint_32 i;
 
-            for (i = 0, sp = dp = row + row_info->rowbytes;
-               i < row_info->width; i++)
+            for (i = 0; i < row_width; i++)
             {
                *(--dp) = 255 - *(--sp);
                *(--dp) = *(--sp);
@@ -1596,11 +1651,11 @@ png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
          /* This inverts the alpha channel in GGAA */
          else
          {
-            png_bytep sp, dp;
+            png_bytep sp  = row + row_info->rowbytes;
+            png_bytep dp = sp;
             png_uint_32 i;
 
-            for (i = 0, sp = dp = row + row_info->rowbytes;
-               i < row_info->width; i++)
+            for (i = 0; i < row_width; i++)
             {
                *(--dp) = 255 - *(--sp);
                *(--dp) = 255 - *(--sp);
@@ -1619,52 +1674,173 @@ void
 png_do_read_filler(png_row_infop row_info, png_bytep row,
    png_uint_32 filler, png_uint_32 flags)
 {
-   png_bytep sp, dp;
    png_uint_32 i;
+   png_uint_32 row_width = row_info->width;
+
+   png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
+   png_byte lo_filler = (png_byte)(filler & 0xff);
 
    png_debug(1, "in png_do_read_filler\n");
    if (
 #if defined(PNG_USELESS_TESTS_SUPPORTED)
        row != NULL  && row_info != NULL &&
 #endif
-       row_info->color_type == PNG_COLOR_TYPE_RGB && row_info->bit_depth == 8)
+       row_info->color_type == PNG_COLOR_TYPE_GRAY)
    {
-      /* This changes the data from RGB to RGBX */
-      if (flags & PNG_FLAG_FILLER_AFTER)
+      if(row_info->bit_depth == 8)
       {
-         for (i = 1, sp = row + (png_size_t)row_info->width * 3,
-            dp = row + (png_size_t)row_info->width * 4;
-            i < row_info->width;
-            i++)
+         /* This changes the data from G to GX */
+         if (flags & PNG_FLAG_FILLER_AFTER)
          {
-            *(--dp) = (png_byte)filler;
-            *(--dp) = *(--sp);
-            *(--dp) = *(--sp);
-            *(--dp) = *(--sp);
+            png_bytep sp = row + (png_size_t)row_width;
+            png_bytep dp =  sp + (png_size_t)row_width;
+            for (i = 1; i < row_width; i++)
+            {
+               *(--dp) = lo_filler;
+               *(--dp) = *(--sp);
+            }
+            *(--dp) = lo_filler;
+            row_info->channels = 2;
+            row_info->pixel_depth = 16;
+            row_info->rowbytes = row_width * 2;
+         }
+      /* This changes the data from G to XG */
+         else
+         {
+            png_bytep sp = row + (png_size_t)row_width;
+            png_bytep dp = sp  + (png_size_t)row_width;
+            for (i = 0; i < row_width; i++)
+            {
+               *(--dp) = *(--sp);
+               *(--dp) = lo_filler;
+            }
+            row_info->channels = 2;
+            row_info->pixel_depth = 16;
+            row_info->rowbytes = row_width * 2;
          }
-         *(--dp) = (png_byte)filler;
-         row_info->channels = 4;
-         row_info->pixel_depth = 32;
-         row_info->rowbytes = row_info->width * 4;
       }
+      else if(row_info->bit_depth == 16)
+      {
+         /* This changes the data from GG to GGXX */
+         if (flags & PNG_FLAG_FILLER_AFTER)
+         {
+            png_bytep sp = row + (png_size_t)row_width;
+            png_bytep dp = sp  + (png_size_t)row_width;
+            for (i = 1; i < row_width; i++)
+            {
+               *(--dp) = hi_filler;
+               *(--dp) = lo_filler;
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+            }
+            *(--dp) = hi_filler;
+            *(--dp) = lo_filler;
+            row_info->channels = 2;
+            row_info->pixel_depth = 32;
+            row_info->rowbytes = row_width * 2;
+         }
+         /* This changes the data from GG to XXGG */
+         else
+         {
+            png_bytep sp = row + (png_size_t)row_width;
+            png_bytep dp = sp  + (png_size_t)row_width;
+            for (i = 0; i < row_width; i++)
+            {
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = hi_filler;
+               *(--dp) = lo_filler;
+            }
+            row_info->channels = 2;
+            row_info->pixel_depth = 16;
+            row_info->rowbytes = row_width * 2;
+         }
+      }
+   } /* COLOR_TYPE == GRAY */
+   else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+   {
+      if(row_info->bit_depth == 8)
+      {
+         /* This changes the data from RGB to RGBX */
+         if (flags & PNG_FLAG_FILLER_AFTER)
+         {
+            png_bytep sp = row + (png_size_t)row_width * 3;
+            png_bytep dp = sp  + (png_size_t)row_width;
+            for (i = 1; i < row_width; i++)
+            {
+               *(--dp) = lo_filler;
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+            }
+            *(--dp) = lo_filler;
+            row_info->channels = 4;
+            row_info->pixel_depth = 32;
+            row_info->rowbytes = row_width * 4;
+         }
       /* This changes the data from RGB to XRGB */
-      else
+         else
+         {
+            png_bytep sp = row + (png_size_t)row_width * 3;
+            png_bytep dp = sp + (png_size_t)row_width;
+            for (i = 0; i < row_width; i++)
+            {
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = lo_filler;
+            }
+            row_info->channels = 4;
+            row_info->pixel_depth = 32;
+            row_info->rowbytes = row_width * 4;
+         }
+      }
+      else if(row_info->bit_depth == 16)
       {
-         for (i = 0, sp = row + (png_size_t)row_info->width * 3,
-            dp = row + (png_size_t)row_info->width * 4;
-            i < row_info->width;
-            i++)
+         /* This changes the data from RRGGBB to RRGGBBXX */
+         if (flags & PNG_FLAG_FILLER_AFTER)
          {
-            *(--dp) = *(--sp);
-            *(--dp) = *(--sp);
-            *(--dp) = *(--sp);
-            *(--dp) = (png_byte)filler;
+            png_bytep sp = row + (png_size_t)row_width * 3;
+            png_bytep dp = sp  + (png_size_t)row_width;
+            for (i = 1; i < row_width; i++)
+            {
+               *(--dp) = hi_filler;
+               *(--dp) = lo_filler;
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+            }
+            *(--dp) = hi_filler;
+            *(--dp) = lo_filler;
+            row_info->channels = 4;
+            row_info->pixel_depth = 64;
+            row_info->rowbytes = row_width * 4;
+         }
+         /* This changes the data from RRGGBB to XXRRGGBB */
+         else
+         {
+            png_bytep sp = row + (png_size_t)row_width * 3;
+            png_bytep dp = sp  + (png_size_t)row_width;
+            for (i = 0; i < row_width; i++)
+            {
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = hi_filler;
+               *(--dp) = lo_filler;
+            }
+            row_info->channels = 4;
+            row_info->pixel_depth = 64;
+            row_info->rowbytes = row_width * 4;
          }
-         row_info->channels = 4;
-         row_info->pixel_depth = 32;
-         row_info->rowbytes = row_info->width * 4;
       }
-   }
+   } /* COLOR_TYPE == RGB */
 }
 #endif
 
@@ -1673,8 +1849,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
 void
 png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
 {
-   png_bytep sp, dp;
    png_uint_32 i;
+   png_uint_32 row_width = row_info->width;
 
    png_debug(1, "in png_do_gray_to_rgb\n");
    if (row_info->bit_depth >= 8 &&
@@ -1687,10 +1863,9 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
       {
          if (row_info->bit_depth == 8)
          {
-            for (i = 0, sp = row + (png_size_t)row_info->width - 1,
-               dp = row + (png_size_t)row_info->width * 3 - 1;
-               i < row_info->width;
-               i++)
+            png_bytep sp = row + (png_size_t)row_width - 1;
+            png_bytep dp = sp  + (png_size_t)row_width * 2;
+            for (i = 0; i < row_width; i++)
             {
                *(dp--) = *sp;
                *(dp--) = *sp;
@@ -1700,10 +1875,9 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
          }
          else
          {
-            for (i = 0, sp = row + (png_size_t)row_info->width * 2 - 1,
-               dp = row + (png_size_t)row_info->width * 6 - 1;
-               i < row_info->width;
-               i++)
+            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
+            png_bytep dp = sp  + (png_size_t)row_width * 4;
+            for (i = 0; i < row_width; i++)
             {
                *(dp--) = *sp;
                *(dp--) = *(sp - 1);
@@ -1720,10 +1894,9 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
       {
          if (row_info->bit_depth == 8)
          {
-            for (i = 0, sp = row + (png_size_t)row_info->width * 2 - 1,
-               dp = row + (png_size_t)row_info->width * 4 - 1;
-               i < row_info->width;
-               i++)
+            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
+            png_bytep dp = sp  + (png_size_t)row_width * 2;
+            for (i = 0; i < row_width; i++)
             {
                *(dp--) = *(sp--);
                *(dp--) = *sp;
@@ -1734,10 +1907,9 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
          }
          else
          {
-            for (i = 0, sp = row + (png_size_t)row_info->width * 4 - 1,
-               dp = row + (png_size_t)row_info->width * 8 - 1;
-               i < row_info->width;
-               i++)
+            png_bytep sp = row + (png_size_t)row_width * 4 - 1;
+            png_bytep dp = sp  + (png_size_t)row_width * 4;
+            for (i = 0; i < row_width; i++)
             {
                *(dp--) = *(sp--);
                *(dp--) = *(sp--);
@@ -1756,12 +1928,267 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
       row_info->color_type |= PNG_COLOR_MASK_COLOR;
       row_info->pixel_depth = (png_byte)(row_info->channels *
          row_info->bit_depth);
-      row_info->rowbytes = ((row_info->width *
+      row_info->rowbytes = ((row_width *
          row_info->pixel_depth + 7) >> 3);
    }
 }
 #endif
 
+#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+/* reduce RGB files to grayscale, with or without alpha 
+ * using the equation given in Poynton's ColorFAQ at
+ * <http://www.inforamp.net/~poynton/>
+ * Copyright (c) 1998-01-04 Charles Poynton poynton@inforamp.net
+ *
+ *     Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
+ *
+ *  We approximate this with
+ * 
+ *     Y = 0.211 * R    + 0.715 * G    + 0.074 * B
+ *
+ *  which can be expressed with integers as
+ *
+ *     Y = (54 * R + 183 * G + 19 * B)/256
+ *
+ *  The calculation is to be done in a linear colorspace.
+ *
+ *  Other integer coefficents can be used via png_set_rgb_to_gray().
+ */
+int
+png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
+
+{
+   png_uint_32 i;
+
+   png_uint_32 row_width = row_info->width;
+   int rgb_error = 0;
+
+   png_debug(1, "in png_do_rgb_to_gray\n");
+   if (
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+       row != NULL && row_info != NULL &&
+#endif
+      (row_info->color_type & PNG_COLOR_MASK_COLOR))
+   {
+      png_byte rc = png_ptr->rgb_to_gray_red_coeff;
+      png_byte gc = png_ptr->rgb_to_gray_green_coeff;
+      png_byte bc = png_ptr->rgb_to_gray_blue_coeff;
+
+      if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+      {
+         if (row_info->bit_depth == 8)
+         {
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+            if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
+            {
+               png_bytep sp = row;
+               png_bytep dp = row;
+
+               for (i = 0; i < row_width; i++)
+               {
+                  png_byte red   = png_ptr->gamma_to_1[*(sp++)];
+                  png_byte green = png_ptr->gamma_to_1[*(sp++)];
+                  png_byte blue  = png_ptr->gamma_to_1[*(sp++)];
+                  if(red != green || red != blue)
+                  {
+                     rgb_error |= 1;
+                     *(dp++) = png_ptr->gamma_from_1[
+                       (rc*red+gc*green+bc*blue)>>8];
+                  }
+                  else
+                     *(dp++) = *(sp-1);
+               }
+            }
+            else
+#endif
+            {
+               png_bytep sp = row;
+               png_bytep dp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  png_byte red   = *(sp++);
+                  png_byte green = *(sp++);
+                  png_byte blue  = *(sp++);
+                  if(red != green || red != blue)
+                  {
+                     rgb_error |= 1;
+                     *(dp++) = (rc*red+gc*green+bc*blue)>>8;
+                  }
+                  else
+                     *(dp++) = *(sp-1);
+               }
+            }
+         }
+         else /* RGB bit_depth == 16 */
+         {
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+            if (png_ptr->gamma_16_to_1 != NULL &&
+                png_ptr->gamma_16_from_1 != NULL)
+            {
+               png_bytep sp = row;
+               png_bytep dp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  png_uint_16 red, green, blue, w;
+
+                  red   = ((*(sp))<<8) | *(sp+1); sp+=2;
+                  green = ((*(sp))<<8) | *(sp+1); sp+=2;
+                  blue  = ((*(sp))<<8) | *(sp+1); sp+=2;
+
+                  if(red == green && red == blue)
+                     w = red;
+                  else
+                  {
+                     png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red&0xff) >>
+                                  png_ptr->gamma_shift][red>>8];
+                     png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
+                                  png_ptr->gamma_shift][green>>8];
+                     png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue&0xff) >> 
+                                  png_ptr->gamma_shift][blue>>8];
+                     png_uint_16 gray16  =  (rc * red_1 + gc * green_1
+                                  + bc * blue_1)>>8;
+                     w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
+                         png_ptr->gamma_shift][gray16 >> 8];
+                     rgb_error |= 1;
+                  }
+                  
+                  *(dp++) = (w>>8) & 0xff;
+                  *(dp++) = w & 0xff;
+               }
+            }
+            else
+#endif
+            {
+               png_bytep sp = row;
+               png_bytep dp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  png_uint_16 red, green, blue, gray16;
+
+                  red   = ((*(sp))<<8) | *(sp+1); sp+=2;
+                  green = ((*(sp))<<8) | *(sp+1); sp+=2;
+                  blue  = ((*(sp))<<8) | *(sp+1); sp+=2;
+
+                  if(red != green || red != blue)
+                     rgb_error |= 1;
+                  gray16  =  (rc * red + gc * green + bc * blue)>>8;
+                  *(dp++) = (gray16>>8) & 0xff;
+                  *(dp++) = gray16 & 0xff;
+               }
+            }
+         }
+      }
+      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+      {
+         if (row_info->bit_depth == 8)
+         {
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+            if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
+            {
+               png_bytep sp = row;
+               png_bytep dp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  png_byte red   = png_ptr->gamma_to_1[*(sp++)];
+                  png_byte green = png_ptr->gamma_to_1[*(sp++)];
+                  png_byte blue  = png_ptr->gamma_to_1[*(sp++)];
+                  if(red != green || red != blue)
+                     rgb_error |= 1;
+                  *(dp++) =  png_ptr->gamma_from_1
+                             [(rc*red + gc*green + bc*blue)>>8];
+                  *(dp++) = *(sp++);  /* alpha */
+               }
+            }
+            else
+#endif
+            {
+               png_bytep sp = row;
+               png_bytep dp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  png_byte red   = *(sp++);
+                  png_byte green = *(sp++);
+                  png_byte blue  = *(sp++);
+                  if(red != green || red != blue)
+                     rgb_error |= 1;
+                  *(dp++) =  (gc*red + gc*green + bc*blue)>>8;
+                  *(dp++) = *(sp++);  /* alpha */
+               }
+            }
+         }
+         else /* RGBA bit_depth == 16 */
+         {
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+            if (png_ptr->gamma_16_to_1 != NULL &&
+                png_ptr->gamma_16_from_1 != NULL)
+            {
+               png_bytep sp = row;
+               png_bytep dp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  png_uint_16 red, green, blue, w;
+
+                  red   = ((*(sp))<<8) | *(sp+1); sp+=2;
+                  green = ((*(sp))<<8) | *(sp+1); sp+=2;
+                  blue  = ((*(sp))<<8) | *(sp+1); sp+=2;
+
+                  if(red == green && red == blue)
+                     w = red;
+                  else
+                  {
+                     png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red&0xff) >>
+                                  png_ptr->gamma_shift][red>>8];
+                     png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
+                                  png_ptr->gamma_shift][green>>8];
+                     png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue&0xff) >> 
+                                  png_ptr->gamma_shift][blue>>8];
+                     png_uint_16 gray16  =  (rc * red_1 + gc * green_1
+                                  + bc * blue_1)>>8;
+                     w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
+                         png_ptr->gamma_shift][gray16 >> 8];
+                     rgb_error |= 1;
+                  }
+                  
+                  *(dp++) = (w>>8) & 0xff;
+                  *(dp++) = w & 0xff;
+                  *(dp++) = *(sp++);  /* alpha */
+                  *(dp++) = *(sp++);
+               }
+            }
+            else
+#endif
+            {
+               png_bytep sp = row;
+               png_bytep dp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  png_uint_16 red, green, blue, gray16;
+                  red   = (*(sp)<<8) | *(sp+1); sp+=2;
+                  green = (*(sp)<<8) | *(sp+1); sp+=2;
+                  blue  = (*(sp)<<8) | *(sp+1); sp+=2;
+                  if(red != green || red != blue)
+                     rgb_error |= 1;
+                  gray16  =  (rc * red + gc * green + bc * blue)>>8;
+                  *(dp++) = (gray16>>8) & 0xff;
+                  *(dp++) = gray16 & 0xff;
+                  *(dp++) = *(sp++);  /* alpha */
+                  *(dp++) = *(sp++);
+               }
+            }
+         }
+      }
+   row_info->channels -= (png_byte)2;
+      row_info->color_type &= ~PNG_COLOR_MASK_COLOR;
+      row_info->pixel_depth = (png_byte)(row_info->channels *
+         row_info->bit_depth);
+      row_info->rowbytes = ((row_width *
+         row_info->pixel_depth + 7) >> 3);
+   }
+   return rgb_error;
+}
+#endif
+
 /* Build a grayscale palette.  Palette is assumed to be 1 << bit_depth
  * large of png_color.  This lets grayscale images be treated as
  * paletted.  Most useful for gamma correction and simplification
@@ -1819,8 +2246,7 @@ png_correct_palette(png_structp png_ptr, png_colorp palette,
 {
    png_debug(1, "in png_correct_palette\n");
 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
-   if ((png_ptr->transformations & (PNG_GAMMA)) &&
-      (png_ptr->transformations & (PNG_BACKGROUND)))
+   if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND))
    {
       png_color back, back_1;
 
@@ -2008,6 +2434,7 @@ png_do_background(png_row_infop row_info, png_bytep row,
 {
    png_bytep sp, dp;
    png_uint_32 i;
+   png_uint_32 row_width=row_info->width;
    int shift;
 
    png_debug(1, "in png_do_background\n");
@@ -2028,7 +2455,7 @@ png_do_background(png_row_infop row_info, png_bytep row,
                {
                   sp = row;
                   shift = 7;
-                  for (i = 0; i < row_info->width; i++)
+                  for (i = 0; i < row_width; i++)
                   {
                      if ((png_uint_16)((*sp >> shift) & 0x1)
                         == trans_values->gray)
@@ -2048,45 +2475,112 @@ png_do_background(png_row_infop row_info, png_bytep row,
                }
                case 2:
                {
-                  sp = row;
-                  shift = 6;
-                  for (i = 0; i < row_info->width; i++)
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+                  if (gamma_table != NULL)
                   {
-                     if ((png_uint_16)((*sp >> shift) & 0x3)
-                         == trans_values->gray)
+                     sp = row;
+                     shift = 6;
+                     for (i = 0; i < row_width; i++)
                      {
-                        *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
-                        *sp |= (png_byte)(background->gray << shift);
+                        if ((png_uint_16)((*sp >> shift) & 0x3)
+                            == trans_values->gray)
+                        {
+                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
+                           *sp |= (png_byte)(background->gray << shift);
+                        }
+                        else
+                        {
+                           png_byte p = (*sp >> shift) & 0x3;
+                           png_byte g = (gamma_table [p | (p << 2) | (p << 4) |
+                               (p << 6)] >> 6) & 0x3;
+                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
+                           *sp |= (png_byte)(g << shift);
+                        }
+                        if (!shift)
+                        {
+                           shift = 6;
+                           sp++;
+                        }
+                        else
+                           shift -= 2;
                      }
-                     if (!shift)
+                  }
+                  else
+#endif
+                  {
+                     sp = row;
+                     shift = 6;
+                     for (i = 0; i < row_width; i++)
                      {
-                        shift = 6;
-                        sp++;
+                        if ((png_uint_16)((*sp >> shift) & 0x3)
+                            == trans_values->gray)
+                        {
+                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
+                           *sp |= (png_byte)(background->gray << shift);
+                        }
+                        if (!shift)
+                        {
+                           shift = 6;
+                           sp++;
+                        }
+                        else
+                           shift -= 2;
                      }
-                     else
-                        shift -= 2;
                   }
                   break;
                }
                case 4:
                {
-                  sp = row;
-                  shift = 4;
-                  for (i = 0; i < row_info->width; i++)
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+                  if (gamma_table != NULL)
                   {
-                     if ((png_uint_16)((*sp >> shift) & 0xf)
-                         == trans_values->gray)
+                     sp = row;
+                     shift = 4;
+                     for (i = 0; i < row_width; i++)
                      {
-                        *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
-                        *sp |= (png_byte)(background->gray << shift);
+                        if ((png_uint_16)((*sp >> shift) & 0xf)
+                            == trans_values->gray)
+                        {
+                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
+                           *sp |= (png_byte)(background->gray << shift);
+                        }
+                        else
+                        {
+                           png_byte p = (*sp >> shift) & 0xf;
+                           png_byte g = (gamma_table[p | (p << 4)] >> 4) & 0xf;
+                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
+                           *sp |= (png_byte)(g << shift);
+                        }
+                        if (!shift)
+                        {
+                           shift = 4;
+                           sp++;
+                        }
+                        else
+                           shift -= 4;
                      }
-                     if (!shift)
+                  }
+                  else
+#endif
+                  {
+                     sp = row;
+                     shift = 4;
+                     for (i = 0; i < row_width; i++)
                      {
-                        shift = 4;
-                        sp++;
+                        if ((png_uint_16)((*sp >> shift) & 0xf)
+                            == trans_values->gray)
+                        {
+                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
+                           *sp |= (png_byte)(background->gray << shift);
+                        }
+                        if (!shift)
+                        {
+                           shift = 4;
+                           sp++;
+                        }
+                        else
+                           shift -= 4;
                      }
-                     else
-                        shift -= 4;
                   }
                   break;
                }
@@ -2095,7 +2589,8 @@ png_do_background(png_row_infop row_info, png_bytep row,
 #if defined(PNG_READ_GAMMA_SUPPORTED)
                   if (gamma_table != NULL)
                   {
-                     for (i = 0, sp = row; i < row_info->width; i++, sp++)
+                     sp = row;
+                     for (i = 0; i < row_width; i++, sp++)
                      {
                         if (*sp == trans_values->gray)
                         {
@@ -2110,7 +2605,8 @@ png_do_background(png_row_infop row_info, png_bytep row,
                   else
 #endif
                   {
-                     for (i = 0, sp = row; i < row_info->width; i++, sp++)
+                     sp = row;
+                     for (i = 0; i < row_width; i++, sp++)
                      {
                         if (*sp == trans_values->gray)
                         {
@@ -2125,7 +2621,8 @@ png_do_background(png_row_infop row_info, png_bytep row,
 #if defined(PNG_READ_GAMMA_SUPPORTED)
                   if (gamma_16 != NULL)
                   {
-                     for (i = 0, sp = row; i < row_info->width; i++, sp += 2)
+                     sp = row;
+                     for (i = 0; i < row_width; i++, sp += 2)
                      {
                         png_uint_16 v;
 
@@ -2147,7 +2644,8 @@ png_do_background(png_row_infop row_info, png_bytep row,
                   else
 #endif
                   {
-                     for (i = 0, sp = row; i < row_info->width; i++, sp += 2)
+                     sp = row;
+                     for (i = 0; i < row_width; i++, sp += 2)
                      {
                         png_uint_16 v;
 
@@ -2171,7 +2669,8 @@ png_do_background(png_row_infop row_info, png_bytep row,
 #if defined(PNG_READ_GAMMA_SUPPORTED)
                if (gamma_table != NULL)
                {
-                  for (i = 0, sp = row; i < row_info->width; i++, sp += 3)
+                  sp = row;
+                  for (i = 0; i < row_width; i++, sp += 3)
                   {
                      if (*sp == trans_values->red &&
                         *(sp + 1) == trans_values->green &&
@@ -2192,7 +2691,8 @@ png_do_background(png_row_infop row_info, png_bytep row,
                else
 #endif
                {
-                  for (i = 0, sp = row; i < row_info->width; i++, sp += 3)
+                  sp = row;
+                  for (i = 0; i < row_width; i++, sp += 3)
                   {
                      if (*sp == trans_values->red &&
                         *(sp + 1) == trans_values->green &&
@@ -2210,13 +2710,12 @@ png_do_background(png_row_infop row_info, png_bytep row,
 #if defined(PNG_READ_GAMMA_SUPPORTED)
                if (gamma_16 != NULL)
                {
-                  for (i = 0, sp = row; i < row_info->width; i++, sp += 6)
+                  sp = row;
+                  for (i = 0; i < row_width; i++, sp += 6)
                   {
-                     png_uint_16 r, g, b;
-
-                     r = ((png_uint_16)(*sp) << 8) + *(sp + 1);
-                     g = ((png_uint_16)(*(sp + 2)) << 8) + *(sp + 3);
-                     b = ((png_uint_16)(*(sp + 4)) << 8) + *(sp + 5);
+                     png_uint_16 r = ((png_uint_16)(*sp) << 8) + *(sp + 1);
+                     png_uint_16 g = ((png_uint_16)(*(sp + 2)) << 8) + *(sp + 3);
+                     png_uint_16 b = ((png_uint_16)(*(sp + 4)) << 8) + *(sp + 5);
                      if (r == trans_values->red && g == trans_values->green &&
                         b == trans_values->blue)
                      {
@@ -2230,8 +2729,7 @@ png_do_background(png_row_infop row_info, png_bytep row,
                      }
                      else
                      {
-                        png_uint_16 v;
-                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
+                        png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
                         *sp = (png_byte)((v >> 8) & 0xff);
                         *(sp + 1) = (png_byte)(v & 0xff);
                         v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
@@ -2246,13 +2744,13 @@ png_do_background(png_row_infop row_info, png_bytep row,
                else
 #endif
                {
-                  for (i = 0, sp = row; i < row_info->width; i++, sp += 6)
+                  sp = row;
+                  for (i = 0; i < row_width; i++, sp += 6)
                   {
-                     png_uint_16 r, g, b;
+                     png_uint_16 r = ((png_uint_16)(*sp) << 8) + *(sp + 1);
+                     png_uint_16 g = ((png_uint_16)(*(sp + 2)) << 8) + *(sp + 3);
+                     png_uint_16 b = ((png_uint_16)(*(sp + 4)) << 8) + *(sp + 5);
 
-                     r = ((png_uint_16)(*sp) << 8) + *(sp + 1);
-                     g = ((png_uint_16)(*(sp + 2)) << 8) + *(sp + 3);
-                     b = ((png_uint_16)(*(sp + 4)) << 8) + *(sp + 5);
                      if (r == trans_values->red && g == trans_values->green &&
                         b == trans_values->blue)
                      {
@@ -2276,12 +2774,12 @@ png_do_background(png_row_infop row_info, png_bytep row,
                if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
                    gamma_table != NULL)
                {
-                  for (i = 0, sp = row, dp = row;
-                     i < row_info->width; i++, sp += 2, dp++)
+                  sp = row;
+                  dp = row;
+                  for (i = 0; i < row_width; i++, sp += 2, dp++)
                   {
-                     png_uint_16 a;
+                     png_uint_16 a = *(sp + 1);
 
-                     a = *(sp + 1);
                      if (a == 0xff)
                      {
                         *dp = gamma_table[*sp];
@@ -2304,12 +2802,12 @@ png_do_background(png_row_infop row_info, png_bytep row,
                else
 #endif
                {
-                  for (i = 0, sp = row, dp = row;
-                     i < row_info->width; i++, sp += 2, dp++)
+                  sp = row;
+                  dp = row;
+                  for (i = 0; i < row_width; i++, sp += 2, dp++)
                   {
-                     png_byte a;
+                     png_byte a = *(sp + 1);
 
-                     a = *(sp + 1);
                      if (a == 0xff)
                      {
                         *dp = *sp;
@@ -2331,12 +2829,12 @@ png_do_background(png_row_infop row_info, png_bytep row,
                if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
                    gamma_16_to_1 != NULL)
                {
-                  for (i = 0, sp = row, dp = row;
-                     i < row_info->width; i++, sp += 4, dp += 2)
+                  sp = row;
+                  dp = row;
+                  for (i = 0; i < row_width; i++, sp += 4, dp += 2)
                   {
-                     png_uint_16 a;
+                     png_uint_16 a = ((png_uint_16)(*(sp + 2)) << 8) + *(sp + 3);
 
-                     a = ((png_uint_16)(*(sp + 2)) << 8) + *(sp + 3);
                      if (a == (png_uint_16)0xffff)
                      {
                         png_uint_16 v;
@@ -2366,12 +2864,11 @@ png_do_background(png_row_infop row_info, png_bytep row,
                else
 #endif
                {
-                  for (i = 0, sp = row, dp = row;
-                     i < row_info->width; i++, sp += 4, dp += 2)
+                  sp = row;
+                  dp = row;
+                  for (i = 0; i < row_width; i++, sp += 4, dp += 2)
                   {
-                     png_uint_16 a;
-
-                     a = ((png_uint_16)(*(sp + 2)) << 8) + *(sp + 3);
+                     png_uint_16 a = ((png_uint_16)(*(sp + 2)) << 8) + *(sp + 3);
                      if (a == (png_uint_16)0xffff)
                      {
                         png_memcpy(dp, sp, 2);
@@ -2403,12 +2900,12 @@ png_do_background(png_row_infop row_info, png_bytep row,
                if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
                    gamma_table != NULL)
                {
-                  for (i = 0, sp = row, dp = row;
-                     i < row_info->width; i++, sp += 4, dp += 3)
+                  sp = row;
+                  dp = row;
+                  for (i = 0; i < row_width; i++, sp += 4, dp += 3)
                   {
-                     png_byte a;
+                     png_byte a = *(sp + 3);
 
-                     a = *(sp + 3);
                      if (a == 0xff)
                      {
                         *dp = gamma_table[*sp];
@@ -2441,12 +2938,12 @@ png_do_background(png_row_infop row_info, png_bytep row,
                else
 #endif
                {
-                  for (i = 0, sp = row, dp = row;
-                     i < row_info->width; i++, sp += 4, dp += 3)
+                  sp = row;
+                  dp = row;
+                  for (i = 0; i < row_width; i++, sp += 4, dp += 3)
                   {
-                     png_byte a;
+                     png_byte a = *(sp + 3);
 
-                     a = *(sp + 3);
                      if (a == 0xff)
                      {
                         *dp = *sp;
@@ -2476,13 +2973,12 @@ png_do_background(png_row_infop row_info, png_bytep row,
                if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
                    gamma_16_to_1 != NULL)
                {
-                  for (i = 0, sp = row, dp = row;
-                     i < row_info->width; i++, sp += 8, dp += 6)
+                  sp = row;
+                  dp = row;
+                  for (i = 0; i < row_width; i++, sp += 8, dp += 6)
                   {
-                     png_uint_16 a;
-
-                     a = (png_uint_16)(((png_uint_16)(*(sp + 6)) << 8) +
-                         (png_uint_16)(*(sp + 7)));
+                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
+                         << 8) + (png_uint_16)(*(sp + 7)));
                      if (a == (png_uint_16)0xffff)
                      {
                         png_uint_16 v;
@@ -2532,13 +3028,12 @@ png_do_background(png_row_infop row_info, png_bytep row,
                else
 #endif
                {
-                  for (i = 0, sp = row, dp = row;
-                     i < row_info->width; i++, sp += 8, dp += 6)
+                  sp = row;
+                  dp = row;
+                  for (i = 0; i < row_width; i++, sp += 8, dp += 6)
                   {
-                     png_uint_16 a;
-
-                     a = (png_uint_16)(((png_uint_16)(*(sp + 6)) << 8) +
-                        (png_uint_16)(*(sp + 7)));
+                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
+                        << 8) + (png_uint_16)(*(sp + 7)));
                      if (a == (png_uint_16)0xffff)
                      {
                         png_memcpy(dp, sp, 6);
@@ -2554,11 +3049,13 @@ png_do_background(png_row_infop row_info, png_bytep row,
                      }
                      else
                      {
-                        png_uint_16 r, g, b, v;
+                        png_uint_16 v;
 
-                        r = ((png_uint_16)(*sp) << 8) + *(sp + 1);
-                        g = ((png_uint_16)(*(sp + 2)) << 8) + *(sp + 3);
-                        b = ((png_uint_16)(*(sp + 4)) << 8) + *(sp + 5);
+                        png_uint_16 r = ((png_uint_16)(*sp) << 8) + *(sp + 1);
+                        png_uint_16 g = ((png_uint_16)(*(sp + 2)) << 8)
+                            + *(sp + 3);
+                        png_uint_16 b = ((png_uint_16)(*(sp + 4)) << 8)
+                            + *(sp + 5);
 
                         png_composite_16(v, r, a, background->red);
                         *dp = (png_byte)((v >> 8) & 0xff);
@@ -2583,7 +3080,7 @@ png_do_background(png_row_infop row_info, png_bytep row,
          row_info->channels--;
          row_info->pixel_depth = (png_byte)(row_info->channels *
             row_info->bit_depth);
-         row_info->rowbytes = ((row_info->width *
+         row_info->rowbytes = ((row_width *
             row_info->pixel_depth + 7) >> 3);
       }
    }
@@ -2592,7 +3089,7 @@ png_do_background(png_row_infop row_info, png_bytep row,
 
 #if defined(PNG_READ_GAMMA_SUPPORTED)
 /* Gamma correct the image, avoiding the alpha channel.  Make sure
- * you do this after you deal with the trasparency issue on grayscale
+ * you do this after you deal with the transparency issue on grayscale
  * or rgb images. If your bit depth is 8, use gamma_table, if it
  * is 16, use gamma_16_table and gamma_shift.  Build these with
  * build_gamma_table().
@@ -2604,6 +3101,7 @@ png_do_gamma(png_row_infop row_info, png_bytep row,
 {
    png_bytep sp;
    png_uint_32 i;
+   png_uint_32 row_width=row_info->width;
 
    png_debug(1, "in png_do_gamma\n");
    if (
@@ -2619,7 +3117,8 @@ png_do_gamma(png_row_infop row_info, png_bytep row,
          {
             if (row_info->bit_depth == 8)
             {
-               for (i = 0, sp = row; i < row_info->width; i++)
+               sp = row;
+               for (i = 0; i < row_width; i++)
                {
                   *sp = gamma_table[*sp];
                   sp++;
@@ -2631,7 +3130,8 @@ png_do_gamma(png_row_infop row_info, png_bytep row,
             }
             else /* if (row_info->bit_depth == 16) */
             {
-               for (i = 0, sp = row; i < row_info->width; i++)
+               sp = row;
+               for (i = 0; i < row_width; i++)
                {
                   png_uint_16 v;
 
@@ -2655,8 +3155,8 @@ png_do_gamma(png_row_infop row_info, png_bytep row,
          {
             if (row_info->bit_depth == 8)
             {
-               for (i = 0, sp = row;
-                  i < row_info->width; i++)
+               sp = row;
+               for (i = 0; i < row_width; i++)
                {
                   *sp = gamma_table[*sp];
                   sp++;
@@ -2669,12 +3169,10 @@ png_do_gamma(png_row_infop row_info, png_bytep row,
             }
             else /* if (row_info->bit_depth == 16) */
             {
-               for (i = 0, sp = row;
-                  i < row_info->width; i++)
+               sp = row;
+               for (i = 0; i < row_width; i++)
                {
-                  png_uint_16 v;
-
-                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
+                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
                   *sp = (png_byte)((v >> 8) & 0xff);
                   *(sp + 1) = (png_byte)(v & 0xff);
                   sp += 2;
@@ -2694,8 +3192,8 @@ png_do_gamma(png_row_infop row_info, png_bytep row,
          {
             if (row_info->bit_depth == 8)
             {
-               for (i = 0, sp = row;
-                  i < row_info->width; i++)
+               sp = row;
+               for (i = 0; i < row_width; i++)
                {
                   *sp = gamma_table[*sp];
                   sp += 2;
@@ -2703,12 +3201,10 @@ png_do_gamma(png_row_infop row_info, png_bytep row,
             }
             else /* if (row_info->bit_depth == 16) */
             {
-               for (i = 0, sp = row;
-                  i < row_info->width; i++)
+               sp = row;
+               for (i = 0; i < row_width; i++)
                {
-                  png_uint_16 v;
-
-                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
+                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
                   *sp = (png_byte)((v >> 8) & 0xff);
                   *(sp + 1) = (png_byte)(v & 0xff);
                   sp += 4;
@@ -2720,7 +3216,8 @@ png_do_gamma(png_row_infop row_info, png_bytep row,
          {
             if (row_info->bit_depth == 2)
             {
-               for (i = 0, sp = row; i < row_info->width; i += 4)
+               sp = row;
+               for (i = 0; i < row_width; i += 4)
                {
                   int a = *sp & 0xc0;
                   int b = *sp & 0x30;
@@ -2736,7 +3233,8 @@ png_do_gamma(png_row_infop row_info, png_bytep row,
             }
             if (row_info->bit_depth == 4)
             {
-               for (i = 0, sp = row; i < row_info->width; i += 2)
+               sp = row;
+               for (i = 0; i < row_width; i += 2)
                {
                   int msb = *sp & 0xf0;
                   int lsb = *sp & 0x0f;
@@ -2748,7 +3246,8 @@ png_do_gamma(png_row_infop row_info, png_bytep row,
             }
             else if (row_info->bit_depth == 8)
             {
-               for (i = 0, sp = row; i < row_info->width; i++)
+               sp = row;
+               for (i = 0; i < row_width; i++)
                {
                   *sp = gamma_table[*sp];
                   sp++;
@@ -2756,11 +3255,10 @@ png_do_gamma(png_row_infop row_info, png_bytep row,
             }
             else if (row_info->bit_depth == 16)
             {
-               for (i = 0, sp = row; i < row_info->width; i++)
+               sp = row;
+               for (i = 0; i < row_width; i++)
                {
-                  png_uint_16 v;
-
-                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
+                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
                   *sp = (png_byte)((v >> 8) & 0xff);
                   *(sp + 1) = (png_byte)(v & 0xff);
                   sp += 2;
@@ -2784,6 +3282,7 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row,
    int shift, value;
    png_bytep sp, dp;
    png_uint_32 i;
+   png_uint_32 row_width=row_info->width;
 
    png_debug(1, "in png_do_expand_palette\n");
    if (
@@ -2798,10 +3297,10 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row,
          {
             case 1:
             {
-               sp = row + (png_size_t)((row_info->width - 1) >> 3);
-               dp = row + (png_size_t)row_info->width - 1;
-               shift = 7 - (int)((row_info->width + 7) & 7);
-               for (i = 0; i < row_info->width; i++)
+               sp = row + (png_size_t)((row_width - 1) >> 3);
+               dp = row + (png_size_t)row_width - 1;
+               shift = 7 - (int)((row_width + 7) & 7);
+               for (i = 0; i < row_width; i++)
                {
                   if ((*sp >> shift) & 0x1)
                      *dp = 1;
@@ -2821,10 +3320,10 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row,
             }
             case 2:
             {
-               sp = row + (png_size_t)((row_info->width - 1) >> 2);
-               dp = row + (png_size_t)row_info->width - 1;
-               shift = (int)((3 - ((row_info->width + 3) & 3)) << 1);
-               for (i = 0; i < row_info->width; i++)
+               sp = row + (png_size_t)((row_width - 1) >> 2);
+               dp = row + (png_size_t)row_width - 1;
+               shift = (int)((3 - ((row_width + 3) & 3)) << 1);
+               for (i = 0; i < row_width; i++)
                {
                   value = (*sp >> shift) & 0x3;
                   *dp = (png_byte)value;
@@ -2842,10 +3341,10 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row,
             }
             case 4:
             {
-               sp = row + (png_size_t)((row_info->width - 1) >> 1);
-               dp = row + (png_size_t)row_info->width - 1;
-               shift = (int)((row_info->width & 1) << 2);
-               for (i = 0; i < row_info->width; i++)
+               sp = row + (png_size_t)((row_width - 1) >> 1);
+               dp = row + (png_size_t)row_width - 1;
+               shift = (int)((row_width & 1) << 2);
+               for (i = 0; i < row_width; i++)
                {
                   value = (*sp >> shift) & 0xf;
                   *dp = (png_byte)value;
@@ -2864,7 +3363,7 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row,
          }
          row_info->bit_depth = 8;
          row_info->pixel_depth = 8;
-         row_info->rowbytes = row_info->width;
+         row_info->rowbytes = row_width;
       }
       switch (row_info->bit_depth)
       {
@@ -2872,10 +3371,10 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row,
          {
             if (trans != NULL)
             {
-               sp = row + (png_size_t)row_info->width - 1;
-               dp = row + (png_size_t)(row_info->width << 2) - 1;
+               sp = row + (png_size_t)row_width - 1;
+               dp = row + (png_size_t)(row_width << 2) - 1;
 
-               for (i = 0; i < row_info->width; i++)
+               for (i = 0; i < row_width; i++)
                {
                   if ((int)(*sp) >= num_trans)
                      *dp-- = 0xff;
@@ -2888,16 +3387,16 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row,
                }
                row_info->bit_depth = 8;
                row_info->pixel_depth = 32;
-               row_info->rowbytes = row_info->width * 4;
+               row_info->rowbytes = row_width * 4;
                row_info->color_type = 6;
                row_info->channels = 4;
             }
             else
             {
-               sp = row + (png_size_t)row_info->width - 1;
-               dp = row + (png_size_t)(row_info->width * 3) - 1;
+               sp = row + (png_size_t)row_width - 1;
+               dp = row + (png_size_t)(row_width * 3) - 1;
 
-               for (i = 0; i < row_info->width; i++)
+               for (i = 0; i < row_width; i++)
                {
                   *dp-- = palette[*sp].blue;
                   *dp-- = palette[*sp].green;
@@ -2906,7 +3405,7 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row,
                }
                row_info->bit_depth = 8;
                row_info->pixel_depth = 24;
-               row_info->rowbytes = row_info->width * 3;
+               row_info->rowbytes = row_width * 3;
                row_info->color_type = 2;
                row_info->channels = 3;
             }
@@ -2926,6 +3425,7 @@ png_do_expand(png_row_infop row_info, png_bytep row,
    int shift, value;
    png_bytep sp, dp;
    png_uint_32 i;
+   png_uint_32 row_width=row_info->width;
 
    png_debug(1, "in png_do_expand\n");
 #if defined(PNG_USELESS_TESTS_SUPPORTED)
@@ -2943,10 +3443,10 @@ png_do_expand(png_row_infop row_info, png_bytep row,
                case 1:
                {
                   gray *= 0xff;
-                  sp = row + (png_size_t)((row_info->width - 1) >> 3);
-                  dp = row + (png_size_t)row_info->width - 1;
-                  shift = 7 - (int)((row_info->width + 7) & 7);
-                  for (i = 0; i < row_info->width; i++)
+                  sp = row + (png_size_t)((row_width - 1) >> 3);
+                  dp = row + (png_size_t)row_width - 1;
+                  shift = 7 - (int)((row_width + 7) & 7);
+                  for (i = 0; i < row_width; i++)
                   {
                      if ((*sp >> shift) & 0x1)
                         *dp = 0xff;
@@ -2967,10 +3467,10 @@ png_do_expand(png_row_infop row_info, png_bytep row,
                case 2:
                {
                   gray *= 0x55;
-                  sp = row + (png_size_t)((row_info->width - 1) >> 2);
-                  dp = row + (png_size_t)row_info->width - 1;
-                  shift = (int)((3 - ((row_info->width + 3) & 3)) << 1);
-                  for (i = 0; i < row_info->width; i++)
+                  sp = row + (png_size_t)((row_width - 1) >> 2);
+                  dp = row + (png_size_t)row_width - 1;
+                  shift = (int)((3 - ((row_width + 3) & 3)) << 1);
+                  for (i = 0; i < row_width; i++)
                   {
                      value = (*sp >> shift) & 0x3;
                      *dp = (png_byte)(value | (value << 2) | (value << 4) |
@@ -2990,10 +3490,10 @@ png_do_expand(png_row_infop row_info, png_bytep row,
                case 4:
                {
                   gray *= 0x11;
-                  sp = row + (png_size_t)((row_info->width - 1) >> 1);
-                  dp = row + (png_size_t)row_info->width - 1;
-                  shift = (int)((1 - ((row_info->width + 1) & 1)) << 2);
-                  for (i = 0; i < row_info->width; i++)
+                  sp = row + (png_size_t)((row_width - 1) >> 1);
+                  dp = row + (png_size_t)row_width - 1;
+                  shift = (int)((1 - ((row_width + 1) & 1)) << 2);
+                  for (i = 0; i < row_width; i++)
                   {
                      value = (*sp >> shift) & 0xf;
                      *dp = (png_byte)(value | (value << 4));
@@ -3012,16 +3512,16 @@ png_do_expand(png_row_infop row_info, png_bytep row,
             }
             row_info->bit_depth = 8;
             row_info->pixel_depth = 8;
-            row_info->rowbytes = row_info->width;
+            row_info->rowbytes = row_width;
          }
 
          if (trans_value != NULL)
          {
             if (row_info->bit_depth == 8)
             {
-               sp = row + (png_size_t)row_info->width - 1;
-               dp = row + (png_size_t)(row_info->width << 1) - 1;
-               for (i = 0; i < row_info->width; i++)
+               sp = row + (png_size_t)row_width - 1;
+               dp = row + (png_size_t)(row_width << 1) - 1;
+               for (i = 0; i < row_width; i++)
                {
                   if (*sp == gray)
                      *dp-- = 0;
@@ -3034,7 +3534,7 @@ png_do_expand(png_row_infop row_info, png_bytep row,
             {
                sp = row + row_info->rowbytes - 1;
                dp = row + (row_info->rowbytes << 1) - 1;
-               for (i = 0; i < row_info->width; i++)
+               for (i = 0; i < row_width; i++)
                {
                   if (((png_uint_16)*(sp) |
                      ((png_uint_16)*(sp - 1) << 8)) == gray)
@@ -3055,7 +3555,7 @@ png_do_expand(png_row_infop row_info, png_bytep row,
             row_info->channels = 2;
             row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
             row_info->rowbytes =
-               ((row_info->width * row_info->pixel_depth) >> 3);
+               ((row_width * row_info->pixel_depth) >> 3);
          }
       }
       else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value)
@@ -3063,8 +3563,8 @@ png_do_expand(png_row_infop row_info, png_bytep row,
          if (row_info->bit_depth == 8)
          {
             sp = row + (png_size_t)row_info->rowbytes - 1;
-            dp = row + (png_size_t)(row_info->width << 2) - 1;
-            for (i = 0; i < row_info->width; i++)
+            dp = row + (png_size_t)(row_width << 2) - 1;
+            for (i = 0; i < row_width; i++)
             {
                if (*(sp - 2) == trans_value->red &&
                   *(sp - 1) == trans_value->green &&
@@ -3080,8 +3580,8 @@ png_do_expand(png_row_infop row_info, png_bytep row,
          else if (row_info->bit_depth == 16)
          {
             sp = row + row_info->rowbytes - 1;
-            dp = row + (png_size_t)(row_info->width << 3) - 1;
-            for (i = 0; i < row_info->width; i++)
+            dp = row + (png_size_t)(row_width << 3) - 1;
+            for (i = 0; i < row_width; i++)
             {
                if ((((png_uint_16)*(sp - 4) |
                   ((png_uint_16)*(sp - 5) << 8)) == trans_value->red) &&
@@ -3110,7 +3610,7 @@ png_do_expand(png_row_infop row_info, png_bytep row,
          row_info->channels = 4;
          row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
          row_info->rowbytes =
-            ((row_info->width * row_info->pixel_depth) >> 3);
+            ((row_width * row_info->pixel_depth) >> 3);
       }
    }
 }
@@ -3123,6 +3623,7 @@ png_do_dither(png_row_infop row_info, png_bytep row,
 {
    png_bytep sp, dp;
    png_uint_32 i;
+   png_uint_32 row_width=row_info->width;
 
    png_debug(1, "in png_do_dither\n");
 #if defined(PNG_USELESS_TESTS_SUPPORTED)
@@ -3135,7 +3636,7 @@ png_do_dither(png_row_infop row_info, png_bytep row,
          int r, g, b, p;
          sp = row;
          dp = row;
-         for (i = 0; i < row_info->width; i++)
+         for (i = 0; i < row_width; i++)
          {
             r = *sp++;
             g = *sp++;
@@ -3163,7 +3664,7 @@ png_do_dither(png_row_infop row_info, png_bytep row,
          row_info->channels = 1;
          row_info->pixel_depth = row_info->bit_depth;
          row_info->rowbytes =
-             ((row_info->width * row_info->pixel_depth + 7) >> 3);
+             ((row_width * row_info->pixel_depth + 7) >> 3);
       }
       else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
          palette_lookup != NULL && row_info->bit_depth == 8)
@@ -3171,7 +3672,7 @@ png_do_dither(png_row_infop row_info, png_bytep row,
          int r, g, b, p;
          sp = row;
          dp = row;
-         for (i = 0; i < row_info->width; i++)
+         for (i = 0; i < row_width; i++)
          {
             r = *sp++;
             g = *sp++;
@@ -3193,13 +3694,13 @@ png_do_dither(png_row_infop row_info, png_bytep row,
          row_info->channels = 1;
          row_info->pixel_depth = row_info->bit_depth;
          row_info->rowbytes =
-            ((row_info->width * row_info->pixel_depth + 7) >> 3);
+            ((row_width * row_info->pixel_depth + 7) >> 3);
       }
       else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
          dither_lookup && row_info->bit_depth == 8)
       {
          sp = row;
-         for (i = 0; i < row_info->width; i++, sp++)
+         for (i = 0; i < row_width; i++, sp++)
          {
             *sp = dither_lookup[*sp];
          }
@@ -3220,13 +3721,18 @@ static int png_gamma_shift[] =
 void
 png_build_gamma_table(png_structp png_ptr)
 {
-   png_debug(1, "in png_build_gamma_table\n");
+  png_debug(1, "in png_build_gamma_table\n");
+  if(png_ptr->gamma != 0.0)
+  {
    if (png_ptr->bit_depth <= 8)
    {
       int i;
       double g;
 
-      g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
+      if (png_ptr->screen_gamma > .000001)
+         g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
+      else
+         g = 1.0;
 
       png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr,
          (png_uint_32)256);
@@ -3237,9 +3743,11 @@ png_build_gamma_table(png_structp png_ptr)
             g) * 255.0 + .5);
       }
 
-#if defined(PNG_READ_BACKGROUND_SUPPORTED)
-      if (png_ptr->transformations & PNG_BACKGROUND)
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
+    defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+      if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY))
       {
+
          g = 1.0 / (png_ptr->gamma);
 
          png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr,
@@ -3251,18 +3759,23 @@ png_build_gamma_table(png_structp png_ptr)
                g) * 255.0 + .5);
          }
 
-         g = 1.0 / (png_ptr->screen_gamma);
-
+         
          png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr,
             (png_uint_32)256);
 
+         if(png_ptr->screen_gamma > 0.000001)
+            g = 1.0 / png_ptr->screen_gamma;
+         else
+            g = png_ptr->gamma;   /* probably doing rgb_to_gray */
+
          for (i = 0; i < 256; i++)
          {
             png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0,
                g) * 255.0 + .5);
+
          }
       }
-#endif /* PNG_BACKGROUND_SUPPORTED */
+#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
    }
    else
    {
@@ -3304,13 +3817,15 @@ png_build_gamma_table(png_structp png_ptr)
 
       num = (1 << (8 - shift));
 
-      g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
+      if (png_ptr->screen_gamma > .000001)
+         g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
+      else
+         g = 1.0;
 
       png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr,
          (png_uint_32)(num * sizeof (png_uint_16p)));
 
-      if ((png_ptr->transformations & PNG_16_TO_8) &&
-         !(png_ptr->transformations & PNG_BACKGROUND))
+      if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND))
       {
          double fin, fout;
          png_uint_32 last, max;
@@ -3360,9 +3875,11 @@ png_build_gamma_table(png_structp png_ptr)
          }
       }
 
-#if defined(PNG_READ_BACKGROUND_SUPPORTED)
-      if (png_ptr->transformations & PNG_BACKGROUND)
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
+    defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+      if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY))
       {
+
          g = 1.0 / (png_ptr->gamma);
 
          png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr,
@@ -3382,7 +3899,11 @@ png_build_gamma_table(png_structp png_ptr)
                      65535.0, g) * 65535.0 + .5);
             }
          }
-         g = 1.0 / (png_ptr->screen_gamma);
+
+         if(png_ptr->screen_gamma > 0.000001)
+            g = 1.0 / png_ptr->screen_gamma;
+         else
+            g = png_ptr->gamma;   /* probably doing rgb_to_gray */
 
          png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr,
             (png_uint_32)(num * sizeof (png_uint_16p)));
@@ -3402,8 +3923,9 @@ png_build_gamma_table(png_structp png_ptr)
             }
          }
       }
-#endif /* PNG_BACKGROUND_SUPPORTED */
+#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
    }
+ }
 }
 #endif
 
index e127c87995bc8da6699f36cc54500e4a505b1911..9320a7107c76a375cfced7c35742afb9795a43b1 100644 (file)
@@ -1,28 +1,25 @@
 
 /* pngrutil.c - utilities to read a PNG file
  *
- * libpng 1.0.1
+ * libpng 1.0.3 - January 14, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, Glenn Randers-Pehrson
- * March 15, 1998
+ * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
  *
- * This file contains routines which are only called from within
+ * This file contains routines that are only called from within
  * libpng itself during the course of reading an image.
  */
 
 #define PNG_INTERNAL
-#include "../png/png.h"
+#include "png.h"
 
 #ifndef PNG_READ_BIG_ENDIAN_SUPPORTED
-/* Grab an unsigned 32-bit integer from a buffer in big endian format. */
+/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
 png_uint_32
 png_get_uint_32(png_bytep buf)
 {
-   png_uint_32 i;
-
-   i = ((png_uint_32)(*buf) << 24) +
+   png_uint_32 i = ((png_uint_32)(*buf) << 24) +
       ((png_uint_32)(*(buf + 1)) << 16) +
       ((png_uint_32)(*(buf + 2)) << 8) +
       (png_uint_32)(*(buf + 3));
@@ -31,15 +28,13 @@ png_get_uint_32(png_bytep buf)
 }
 
 #if defined(PNG_READ_pCAL_SUPPORTED)
-/* Grab a signed 32-bit integer from a buffer in big endian format.  The
+/* Grab a signed 32-bit integer from a buffer in big-endian format.  The
  * data is stored in the PNG file in two's complement format, and it is
  * assumed that the machine format for signed integers is the same. */
 png_int_32
 png_get_int_32(png_bytep buf)
 {
-   png_int_32 i;
-
-   i = ((png_int_32)(*buf) << 24) +
+   png_int_32 i = ((png_int_32)(*buf) << 24) +
       ((png_int_32)(*(buf + 1)) << 16) +
       ((png_int_32)(*(buf + 2)) << 8) +
       (png_int_32)(*(buf + 3));
@@ -48,13 +43,11 @@ png_get_int_32(png_bytep buf)
 }
 #endif /* PNG_READ_pCAL_SUPPORTED */
 
-/* Grab an unsigned 16-bit integer from a buffer in big endian format. */
+/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
 png_uint_16
 png_get_uint_16(png_bytep buf)
 {
-   png_uint_16 i;
-
-   i = (png_uint_16)(((png_uint_16)(*buf) << 8) +
+   png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) +
       (png_uint_16)(*(buf + 1)));
 
    return (i);
@@ -76,15 +69,16 @@ png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
 int
 png_crc_finish(png_structp png_ptr, png_uint_32 skip)
 {
-   png_uint_32 i;
+   png_size_t i;
+   png_size_t istop = png_ptr->zbuf_size;
 
-   for (i = skip; i > (png_uint_32)png_ptr->zbuf_size; i -= png_ptr->zbuf_size)
+   for (i = (png_size_t)skip; i > istop; i -= istop)
    {
       png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
    }
    if (i)
    {
-      png_crc_read(png_ptr, png_ptr->zbuf, (png_size_t)i);
+      png_crc_read(png_ptr, png_ptr->zbuf, i);
    }
 
    if (png_crc_error(png_ptr))
@@ -258,20 +252,6 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 
    png_ptr->mode |= PNG_HAVE_PLTE;
 
-#if defined (PNG_READ_tRNS_SUPPORTED)
-   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
-   {
-      if (info_ptr != NULL && info_ptr->valid & PNG_INFO_tRNS)
-      {
-         if (png_ptr->num_trans > png_ptr->num_palette)
-         {
-            png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
-            png_ptr->num_trans = png_ptr->num_palette;
-         }
-      }
-   }
-#endif
-
 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
    if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
    {
@@ -349,6 +329,21 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    png_ptr->palette = palette;
    png_ptr->num_palette = (png_uint_16)num;
    png_set_PLTE(png_ptr, info_ptr, palette, num);
+
+#if defined (PNG_READ_tRNS_SUPPORTED)
+   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+   {
+      if (info_ptr != NULL && info_ptr->valid & PNG_INFO_tRNS)
+      {
+         if (png_ptr->num_trans > png_ptr->num_palette)
+         {
+            png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
+            png_ptr->num_trans = png_ptr->num_palette;
+         }
+      }
+   }
+#endif
+
 }
 
 void
@@ -429,7 +424,7 @@ png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
       {
          png_warning(png_ptr,
            "Ignoring incorrect gAMA value when sRGB is also present");
-#ifndef PNG_NO_STDIO
+#ifndef PNG_NO_CONSOLE_IO
          fprintf(stderr, "igamma = %lu\n", igamma);
 #endif
          return;
@@ -501,6 +496,9 @@ png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    else
    {
       png_ptr->sig_bit.gray = buf[0];
+      png_ptr->sig_bit.red = buf[0];
+      png_ptr->sig_bit.green = buf[0];
+      png_ptr->sig_bit.blue = buf[0];
       png_ptr->sig_bit.alpha = buf[1];
    }
    png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
@@ -629,7 +627,7 @@ png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 
             png_warning(png_ptr,
               "Ignoring incorrect cHRM value when sRGB is also present");
-#ifndef PNG_NO_STDIO
+#ifndef PNG_NO_CONSOLE_IO
             fprintf(stderr,"wx=%f, wy=%f, rx=%f, ry=%f\n",
                white_x, white_y, red_x, red_y);
             fprintf(stderr,"gx=%f, gy=%f, bx=%f, by=%f\n",
@@ -698,7 +696,7 @@ png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
       {
          png_warning(png_ptr,
            "Ignoring incorrect gAMA value when sRGB is also present");
-#ifndef PNG_NO_STDIO
+#ifndef PNG_NO_CONSOLE_IO
            fprintf(stderr,"gamma=%f\n",png_ptr->gamma);
 #endif
       }
@@ -758,6 +756,12 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
          png_crc_finish(png_ptr, length);
          return;
       }
+      if (length == 0)
+      {
+         png_warning(png_ptr, "Zero length tRNS chunk");
+         png_crc_finish(png_ptr, length);
+         return;
+      }
 
       png_ptr->trans = (png_bytep)png_malloc(png_ptr, length);
       png_ptr->flags |= PNG_FLAG_FREE_TRANS;
@@ -1075,7 +1079,7 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    purpose[slength] = 0x00; /* null terminate the last string */
 
    png_debug(3, "Finding end of pCAL purpose string\n");
-   for (buf = purpose; *buf != '\0'; buf++)
+   for (buf = purpose; *buf; buf++)
       /* empty loop */ ;
 
    endptr = purpose + slength;
@@ -1113,7 +1117,7 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
       png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
    }
 
-   for (buf = units; *buf != 0x00; buf++)
+   for (buf = units; *buf; buf++)
       /* Empty loop to move past the units string. */ ;
 
    png_debug(3, "Allocating pCAL parameters array\n");
@@ -1465,13 +1469,13 @@ png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
    }
 }
 
-/* Combines the row recently read in with the previous row.
-   This routine takes care of alpha and transparency if requested.
+/* Combines the row recently read in with the existing pixels in the
+   row.  This routine takes care of alpha and transparency if requested.
    This routine also handles the two methods of progressive display
    of interlaced images, depending on the mask value.
    The mask value describes which pixels are to be combined with
    the row.  The pattern always repeats every 8 pixels, so just 8
-   bits are needed.  A one indicates the pixels is to be combined,
+   bits are needed.  A one indicates the pixel is to be combined,
    a zero indicates the pixel is to be skipped.  This is in addition
    to any alpha or transparency value associated with the pixel.  If
    you want all pixels to be combined, pass 0xff (255) in mask.  */
@@ -1492,16 +1496,14 @@ png_combine_row(png_structp png_ptr, png_bytep row,
       {
          case 1:
          {
-            png_bytep sp;
-            png_bytep dp;
+            png_bytep sp = png_ptr->row_buf + 1;
+            png_bytep dp = row;
             int s_inc, s_start, s_end;
-            int m;
+            int m = 0x80;
             int shift;
             png_uint_32 i;
+            png_uint_32 row_width = png_ptr->width;
 
-            sp = png_ptr->row_buf + 1;
-            dp = row;
-            m = 0x80;
 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
             if (png_ptr->transformations & PNG_PACKSWAP)
             {
@@ -1519,7 +1521,7 @@ png_combine_row(png_structp png_ptr, png_bytep row,
 
             shift = s_start;
 
-            for (i = 0; i < png_ptr->width; i++)
+            for (i = 0; i < row_width; i++)
             {
                if (m & mask)
                {
@@ -1548,17 +1550,15 @@ png_combine_row(png_structp png_ptr, png_bytep row,
          }
          case 2:
          {
-            png_bytep sp;
-            png_bytep dp;
+            png_bytep sp = png_ptr->row_buf + 1;
+            png_bytep dp = row;
             int s_start, s_end, s_inc;
-            int m;
+            int m = 0x80;
             int shift;
             png_uint_32 i;
+            png_uint_32 row_width = png_ptr->width;
             int value;
 
-            sp = png_ptr->row_buf + 1;
-            dp = row;
-            m = 0x80;
 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
             if (png_ptr->transformations & PNG_PACKSWAP)
             {
@@ -1576,7 +1576,7 @@ png_combine_row(png_structp png_ptr, png_bytep row,
 
             shift = s_start;
 
-            for (i = 0; i < png_ptr->width; i++)
+            for (i = 0; i < row_width; i++)
             {
                if (m & mask)
                {
@@ -1602,17 +1602,15 @@ png_combine_row(png_structp png_ptr, png_bytep row,
          }
          case 4:
          {
-            png_bytep sp;
-            png_bytep dp;
+            png_bytep sp = png_ptr->row_buf + 1;
+            png_bytep dp = row;
             int s_start, s_end, s_inc;
-            int m;
+            int m = 0x80;
             int shift;
             png_uint_32 i;
+            png_uint_32 row_width = png_ptr->width;
             int value;
 
-            sp = png_ptr->row_buf + 1;
-            dp = row;
-            m = 0x80;
 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
             if (png_ptr->transformations & PNG_PACKSWAP)
             {
@@ -1629,7 +1627,7 @@ png_combine_row(png_structp png_ptr, png_bytep row,
             }
             shift = s_start;
 
-            for (i = 0; i < png_ptr->width; i++)
+            for (i = 0; i < row_width; i++)
             {
                if (m & mask)
                {
@@ -1655,18 +1653,15 @@ png_combine_row(png_structp png_ptr, png_bytep row,
          }
          default:
          {
-            png_bytep sp;
-            png_bytep dp;
-            png_size_t pixel_bytes;
+            png_bytep sp = png_ptr->row_buf + 1;
+            png_bytep dp = row;
+            png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
             png_uint_32 i;
-            png_byte m;
+            png_uint_32 row_width = png_ptr->width;
+            png_byte m = 0x80;
 
-            pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
 
-            sp = png_ptr->row_buf + 1;
-            dp = row;
-            m = 0x80;
-            for (i = 0; i < png_ptr->width; i++)
+            for (i = 0; i < row_width; i++)
             {
                if (m & mask)
                {
@@ -1703,15 +1698,15 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
       {
          case 1:
          {
-            png_bytep sp, dp;
+            png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
+            png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
             int sshift, dshift;
             int s_start, s_end, s_inc;
+            int jstop = png_pass_inc[pass];
             png_byte v;
             png_uint_32 i;
             int j;
 
-            sp = row + (png_size_t)((row_info->width - 1) >> 3);
-            dp = row + (png_size_t)((final_width - 1) >> 3);
 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
             if (transformations & PNG_PACKSWAP)
             {
@@ -1731,10 +1726,10 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
                 s_inc = 1;
             }
 
-            for (i = row_info->width; i; i--)
+            for (i = 0; i < row_info->width; i++)
             {
                v = (png_byte)((*sp >> sshift) & 0x1);
-               for (j = 0; j < png_pass_inc[pass]; j++)
+               for (j = 0; j < jstop; j++)
                {
                   *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
                   *dp |= (png_byte)(v << dshift);
@@ -1758,13 +1753,13 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
          }
          case 2:
          {
-            png_bytep sp, dp;
+            png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
+            png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
             int sshift, dshift;
             int s_start, s_end, s_inc;
+            int jstop = png_pass_inc[pass];
             png_uint_32 i;
 
-            sp = row + (png_uint_32)((row_info->width - 1) >> 2);
-            dp = row + (png_uint_32)((final_width - 1) >> 2);
 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
             if (transformations & PNG_PACKSWAP)
             {
@@ -1784,13 +1779,13 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
                s_inc = 2;
             }
 
-            for (i = row_info->width; i; i--)
+            for (i = 0; i < row_info->width; i++)
             {
                png_byte v;
                int j;
 
                v = (png_byte)((*sp >> sshift) & 0x3);
-               for (j = 0; j < png_pass_inc[pass]; j++)
+               for (j = 0; j < jstop; j++)
                {
                   *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
                   *dp |= (png_byte)(v << dshift);
@@ -1814,13 +1809,13 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
          }
          case 4:
          {
-            png_bytep sp, dp;
+            png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
+            png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
             int sshift, dshift;
             int s_start, s_end, s_inc;
             png_uint_32 i;
+            int jstop = png_pass_inc[pass];
 
-            sp = row + (png_size_t)((row_info->width - 1) >> 1);
-            dp = row + (png_size_t)((final_width - 1) >> 1);
 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
             if (transformations & PNG_PACKSWAP)
             {
@@ -1840,13 +1835,12 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
                s_inc = 4;
             }
 
-            for (i = row_info->width; i; i--)
+            for (i = 0; i < row_info->width; i++)
             {
-               png_byte v;
+               png_byte v = (png_byte)((*sp >> sshift) & 0xf);
                int j;
 
-               v = (png_byte)((*sp >> sshift) & 0xf);
-               for (j = 0; j < png_pass_inc[pass]; j++)
+               for (j = 0; j < jstop; j++)
                {
                   *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
                   *dp |= (png_byte)(v << dshift);
@@ -1870,21 +1864,19 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
          }
          default:
          {
-            png_bytep sp, dp;
+            png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
+            png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes;
+            png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
+            int jstop = png_pass_inc[pass];
             png_uint_32 i;
-            png_size_t pixel_bytes;
 
-            pixel_bytes = (row_info->pixel_depth >> 3);
-
-            sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes;
-            dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
-            for (i = row_info->width; i; i--)
+            for (i = 0; i < row_info->width; i++)
             {
                png_byte v[8];
                int j;
 
                png_memcpy(v, sp, pixel_bytes);
-               for (j = 0; j < png_pass_inc[pass]; j++)
+               for (j = 0; j < jstop; j++)
                {
                   png_memcpy(dp, v, pixel_bytes);
                   dp -= pixel_bytes;
@@ -1916,97 +1908,112 @@ png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
       case PNG_FILTER_VALUE_SUB:
       {
          png_uint_32 i;
-         int bpp;
-         png_bytep rp;
-         png_bytep lp;
+         png_uint_32 istop = row_info->rowbytes;
+         png_uint_32 bpp = (row_info->pixel_depth + 7) / 8;
+         png_bytep rp = row + bpp;
+         png_bytep lp = row;
 
-         bpp = (row_info->pixel_depth + 7) / 8;
-         for (i = (png_uint_32)bpp, rp = row + bpp, lp = row;
-            i < row_info->rowbytes; i++, rp++, lp++)
+         for (i = bpp; i < istop; i++)
          {
-            *rp = (png_byte)(((int)(*rp) + (int)(*lp)) & 0xff);
+            *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
+            rp++;
          }
          break;
       }
       case PNG_FILTER_VALUE_UP:
       {
          png_uint_32 i;
-         png_bytep rp;
-         png_bytep pp;
+         png_uint_32 istop = row_info->rowbytes;
+         png_bytep rp = row;
+         png_bytep pp = prev_row;
 
-         for (i = 0, rp = row, pp = prev_row;
-            i < row_info->rowbytes; i++, rp++, pp++)
+         for (i = 0; i < istop; i++)
          {
-            *rp = (png_byte)(((int)(*rp) + (int)(*pp)) & 0xff);
+            *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
+            rp++;
          }
          break;
       }
       case PNG_FILTER_VALUE_AVG:
       {
          png_uint_32 i;
-         int bpp;
-         png_bytep rp;
-         png_bytep pp;
-         png_bytep lp;
-
-         bpp = (row_info->pixel_depth + 7) / 8;
-         for (i = 0, rp = row, pp = prev_row;
-            i < (png_uint_32)bpp; i++, rp++, pp++)
+         png_bytep rp = row;
+         png_bytep pp = prev_row;
+         png_bytep lp = row;
+         png_uint_32 bpp = (row_info->pixel_depth + 7) / 8;
+         png_uint_32 istop = row_info->rowbytes - bpp;
+
+         for (i = 0; i < bpp; i++)
          {
             *rp = (png_byte)(((int)(*rp) +
-               ((int)(*pp) / 2)) & 0xff);
+               ((int)(*pp++) / 2)) & 0xff);
+            rp++;
          }
-         for (lp = row; i < row_info->rowbytes; i++, rp++, lp++, pp++)
+
+         for (i = 0; i < istop; i++)
          {
             *rp = (png_byte)(((int)(*rp) +
-               (int)(*pp + *lp) / 2) & 0xff);
+               (int)(*pp++ + *lp++) / 2) & 0xff);
+            rp++;
          }
          break;
       }
       case PNG_FILTER_VALUE_PAETH:
       {
-         int bpp;
          png_uint_32 i;
-         png_bytep rp;
-         png_bytep pp;
-         png_bytep lp;
-         png_bytep cp;
-
-         bpp = (row_info->pixel_depth + 7) / 8;
-         for (i = 0, rp = row, pp = prev_row,
-            lp = row - bpp, cp = prev_row - bpp;
-            i < row_info->rowbytes; i++, rp++, pp++, lp++, cp++)
+         png_bytep rp = row;
+         png_bytep pp = prev_row;
+         png_bytep lp = row;
+         png_bytep cp = prev_row;
+         png_uint_32 bpp = (row_info->pixel_depth + 7) / 8;
+         png_uint_32 istop=row_info->rowbytes - bpp;
+
+         for (i = 0; i < bpp; i++)
+         {
+            *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
+            rp++;
+         }
+
+         for (i = 0; i < istop; i++)   /* use leftover rp,pp */
          {
             int a, b, c, pa, pb, pc, p;
 
-            b = *pp;
-            if (i >= (png_uint_32)bpp)
-            {
-               c = *cp;
-               a = *lp;
-            }
-            else
-            {
-               a = c = 0;
-            }
-            p = a + b - c;
-            pa = abs(p - a);
-            pb = abs(p - b);
-            pc = abs(p - c);
-
-            if (pa <= pb && pa <= pc)
-               p = a;
-            else if (pb <= pc)
-               p = b;
-            else
-               p = c;
+            a = *lp++;
+            b = *pp++;
+            c = *cp++;
+
+            p = b - c;
+            pc = a - c;
+
+#ifdef PNG_USE_ABS
+            pa = abs(p);
+            pb = abs(pc);
+            pc = abs(p + pc);
+#else
+            pa = p < 0 ? -p : p;
+            pb = pc < 0 ? -pc : pc;
+            pc = (p + pc) < 0 ? -(p + pc) : p + pc;
+#endif
+
+            /*
+               if (pa <= pb && pa <= pc)
+                  p = a;
+               else if (pb <= pc)
+                  p = b;
+               else
+                  p = c;
+             */
+
+            p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
 
             *rp = (png_byte)(((int)(*rp) + p) & 0xff);
+            rp++;
          }
          break;
       }
       default:
-         png_error(png_ptr, "Bad adaptive filter type");
+         png_warning(png_ptr, "Ignoring bad adaptive filter type");
+         *row=0;
          break;
    }
 }
@@ -2044,7 +2051,7 @@ png_read_finish_row(png_structp png_ptr)
             if (!(png_ptr->num_rows))
                continue;
          }
-         if (png_ptr->transformations & PNG_INTERLACE)
+         else  /* if (png_ptr->transformations & PNG_INTERLACE) */
             break;
       } while (png_ptr->iwidth == 0);
 
@@ -2118,7 +2125,7 @@ void
 png_read_start_row(png_structp png_ptr)
 {
    int max_pixel_depth;
-   png_uint_32 rowbytes;
+   png_uint_32 row_bytes;
 
    png_debug(1, "in png_read_start_row\n");
    png_ptr->zstream.avail_in = 0;
@@ -2136,10 +2143,10 @@ png_read_start_row(png_structp png_ptr)
          png_pass_start[png_ptr->pass]) /
          png_pass_inc[png_ptr->pass];
 
-         rowbytes = ((png_ptr->iwidth *
+         row_bytes = ((png_ptr->iwidth *
             (png_uint_32)png_ptr->pixel_depth + 7) >> 3) +1;
-         png_ptr->irowbytes = (png_size_t)rowbytes;
-         if((png_uint_32)png_ptr->irowbytes != rowbytes)
+         png_ptr->irowbytes = (png_size_t)row_bytes;
+         if((png_uint_32)png_ptr->irowbytes != row_bytes)
             png_error(png_ptr, "Rowbytes overflow in png_read_start_row");
    }
    else
@@ -2186,27 +2193,47 @@ png_read_start_row(png_structp png_ptr)
 #if defined(PNG_READ_FILLER_SUPPORTED)
    if (png_ptr->transformations & (PNG_FILLER))
    {
-      if (max_pixel_depth < 32)
+      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
          max_pixel_depth = 32;
+      else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
+      {
+         if (max_pixel_depth <= 8)
+            max_pixel_depth = 16;
+         else
+            max_pixel_depth = 32;
+      }
+      else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
+      {
+         if (max_pixel_depth <= 32)
+            max_pixel_depth = 32;
+         else
+            max_pixel_depth = 64;
+      }
    }
 #endif
 
 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
    if (png_ptr->transformations & PNG_GRAY_TO_RGB)
    {
-      if ((png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
-         png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+      if (
+#if defined(PNG_READ_EXPAND_SUPPORTED)
+        (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
+#endif
+#if defined(PNG_READ_FILLER_SUPPORTED)
+        (png_ptr->transformations & (PNG_FILLER)) ||
+#endif
+        png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
       {
          if (max_pixel_depth <= 16)
             max_pixel_depth = 32;
-         else if (max_pixel_depth <= 32)
+         else
             max_pixel_depth = 64;
       }
       else
       {
          if (max_pixel_depth <= 8)
             max_pixel_depth = 24;
-         else if (max_pixel_depth <= 16)
+         else
             max_pixel_depth = 48;
       }
    }
@@ -2214,16 +2241,16 @@ png_read_start_row(png_structp png_ptr)
 
    /* align the width on the next larger 8 pixels.  Mainly used
       for interlacing */
-   rowbytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
+   row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
    /* calculate the maximum bytes needed, adding a byte and a pixel
-      for safety sake */
-   rowbytes = ((rowbytes * (png_uint_32)max_pixel_depth + 7) >> 3) +
+      for safety's sake */
+   row_bytes = ((row_bytes * (png_uint_32)max_pixel_depth + 7) >> 3) +
       1 + ((max_pixel_depth + 7) >> 3);
 #ifdef PNG_MAX_MALLOC_64K
-   if (rowbytes > (png_uint_32)65536L)
+   if (row_bytes > (png_uint_32)65536L)
       png_error(png_ptr, "This image requires a row greater than 64KB");
 #endif
-   png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, rowbytes);
+   png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, row_bytes);
 
 #ifdef PNG_MAX_MALLOC_64K
    if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L)
index cb3fbe27b6d507646615419ac3bc1128f3c2debd..320083638cff4fb762918be2476034d8014cdf37 100644 (file)
@@ -1,12 +1,11 @@
 
 /* pngset.c - storage of image information into info struct
  *
- * libpng 1.0.1
+ * libpng 1.0.3 - January 14, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, Glenn Randers-Pehrson
- * March 15, 1998
+ * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
  *
  * The functions here are used during reads to store data from the file
  * into the info struct, and during writes to store application data
@@ -15,7 +14,7 @@
  */
 
 #define PNG_INTERNAL
-#include "../png/png.h"
+#include "png.h"
 
 #if defined(PNG_READ_bKGD_SUPPORTED) || defined(PNG_WRITE_bKGD_SUPPORTED)
 void
@@ -108,13 +107,14 @@ png_set_IHDR(png_structp png_ptr, png_infop info_ptr,
 
    /* check for overflow */
    rowbytes_per_pixel = (info_ptr->pixel_depth + 7) >> 3;
-   info_ptr->rowbytes = info_ptr->width * rowbytes_per_pixel;
    if (( width > (png_uint_32)2147483647L/rowbytes_per_pixel))
    {
       png_warning(png_ptr,
          "Width too large to process image data; rowbytes will overflow.");
       info_ptr->rowbytes = (png_size_t)0;
    }
+   else
+      info_ptr->rowbytes = (info_ptr->width * info_ptr->pixel_depth + 7) >> 3;
 }
 
 #if defined(PNG_READ_oFFs_SUPPORTED) || defined(PNG_WRITE_oFFs_SUPPORTED)
index 9eae4795ea910e7d0d1960535ea6adad1f5ebd01..a1ba8ec2eafd13cb8a7a04c7465fcb2b59bf0c96 100644 (file)
@@ -1,12 +1,11 @@
 
 /* pngtest.c - a simple test program to test libpng
  *
- * libpng 1.0.1
+ * libpng 1.0.3 -January 14, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, Glenn Randers-Pehrson
- * March 15, 1998
+ * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
  *
  * This program reads in a PNG image, writes it out again, and then
  * compares the two files.  If the files are identical, this shows that
@@ -14,9 +13,9 @@
  * properly.  It does not currently test all of the transforms, although
  * it probably should.
  *
- * The program will fail in certain legitimate cases:
+ * The program will report "FAIL" in certain legitimate cases:
  * 1) when the compression level or filter selection method is changed.
- * 2) when the chunk size is smaller than 8K.
+ * 2) when the chunk size is not 8K.
  * 3) unknown ancillary chunks exist in the input file.
  * 4) others not listed here...
  * In these cases, it is best to check with another tool such as "pngcheck"
@@ -24,7 +23,8 @@
  *
  * If a filename is given on the command-line, then this file is used
  * for the input, rather than the default "pngtest.png".  This allows
- * testing a wide variety of files easily.
+ * testing a wide variety of files easily.  You can also test a number
+ * of files at once by typing "pngtest -m file1.png file2.png ..."
  */
 
 #include <stdio.h>
 #define PNG_DEBUG 0
 #endif
 
-#include "../png/png.h"
+#include "png.h"
+
+#if defined(PNG_TIME_RFC1123_SUPPORTED)
+static int tIME_chunk_present=0;
+static char tIME_string[30] = "no tIME chunk present in file";
+#endif /* PNG_TIME_RFC1123_SUPPORTED */
 
 int test_one_file PNGARG((PNG_CONST char *inname, PNG_CONST char *outname));
 
@@ -81,15 +86,15 @@ write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass)
 
 #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
 /* example of using user transform callback (we don't transform anything,
-   but merely count the black pixels) */
+   but merely count the zero samples) */
 
-static png_uint_32 black_pixels;
+static png_uint_32 zero_samples;
 
 void
-count_black_pixels(png_structp png_ptr, png_row_infop row_info, png_bytep data)
+count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data)
 {
    png_bytep dp = data;
-   if(png_ptr == NULL)return; 
+   if(png_ptr == NULL)return;
 
    /* contents of row_info:
     *  png_uint_32 width      width of row
@@ -100,60 +105,66 @@ count_black_pixels(png_structp png_ptr, png_row_infop row_info, png_bytep data)
     *  png_byte pixel_depth   bits per pixel (depth*channels)
     */
 
-    /* counts the number of black pixels (or zero pixels if color_type is 3 */
+    /* counts the number of zero samples (or zero pixels if color_type is 3 */
 
     if(row_info->color_type == 0 || row_info->color_type == 3)
     {
        int pos=0;
-       png_uint_32 n;
-       for (n=0; n<row_info->width; n++)
+       png_uint_32 n, nstop;
+       for (n=0, nstop=row_info->width; n<nstop; n++)
        {
           if(row_info->bit_depth == 1)
-             if(((*dp << pos++ )& 0x80) == 0) black_pixels++;
+          {
+             if(((*dp << pos++ )& 0x80) == 0) zero_samples++;
              if(pos == 8)
              {
-                pos=0;
+                pos = 0;
                 dp++;
              }
+          }
           if(row_info->bit_depth == 2)
-             if(((*dp << (pos+=2))& 0xc0) == 0) black_pixels++;
+          {
+             if(((*dp << (pos+=2))& 0xc0) == 0) zero_samples++;
              if(pos == 8)
              {
-                pos=0;
+                pos = 0;
                 dp++;
              }
+          }
           if(row_info->bit_depth == 4)
-             if(((*dp << (pos+=4))& 0xf0) == 0) black_pixels++;
+          {
+             if(((*dp << (pos+=4))& 0xf0) == 0) zero_samples++;
              if(pos == 8)
              {
-                pos=0;
+                pos = 0;
                 dp++;
              }
+          }
           if(row_info->bit_depth == 8)
-             if(*dp++ == 0) black_pixels++;
+             if(*dp++ == 0) zero_samples++;
           if(row_info->bit_depth == 16)
           {
-             if((*dp | *(dp+1)) == 0) black_pixels++;
+             if((*dp | *(dp+1)) == 0) zero_samples++;
              dp+=2;
           }
        }
     }
     else /* other color types */
     {
-       png_uint_32 n;
+       png_uint_32 n, nstop;
        int channel;
        int color_channels = row_info->channels;
        if(row_info->color_type > 3)color_channels--;
 
-       for (n=0; n<row_info->width; n++)
+       for (n=0, nstop=row_info->width; n<nstop; n++)
        {
           for (channel = 0; channel < color_channels; channel++)
           {
              if(row_info->bit_depth == 8)
-                if(*dp++ == 0) black_pixels++;
+                if(*dp++ == 0) zero_samples++;
              if(row_info->bit_depth == 16)
              {
-                if((*dp | *(dp+1)) == 0) black_pixels++;
+                if((*dp | *(dp+1)) == 0) zero_samples++;
                 dp+=2;
              }
           }
@@ -174,7 +185,7 @@ static int wrote_question = 0;
 /* 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. */
-/* This is the function which does the actual reading of data.  If you are
+/* This is the function that 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. */
@@ -200,10 +211,10 @@ png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
    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)
 {
@@ -256,7 +267,7 @@ png_default_flush(png_structp png_ptr)
 }
 #endif
 
-/* This is the function which does the actual writing of data.  If you are
+/* This is the function that 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. */
@@ -346,18 +357,14 @@ 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. */
+   /* We can return because png_error calls the default handler, which is
+    * actually OK in this case. */
 }
 #endif /* PNG_NO_STDIO */
 /* END of code to validate stdio-free compilation */
 
 /* START of code to validate memory allocation and deallocation */
-#ifdef PNGTEST_MEMORY_DEBUG
-/* Borland DOS special memory handler */
-#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
-ERROR - memory debugging is not supported on this platform
-#else
+#ifdef PNG_USER_MEM_SUPPORTED
 
 /* Allocate memory.  For reasonable files, size should never exceed
    64K.  However, zlib may allocate more then 64K if you don't tell
@@ -369,7 +376,7 @@ ERROR - memory debugging is not supported on this platform
    by setting MAXSEG_64K in zlib zconf.h *or* PNG_MAX_MALLOC_64K. */
 typedef struct memory_information {
    png_uint_32                    size;
-   png_voidp                      pointer;
+   png_voidp                 pointer;
    struct memory_information FAR *next;
 } memory_information;
 typedef memory_information FAR *memory_infop;
@@ -384,23 +391,23 @@ extern PNG_EXPORT(void,png_debug_free) PNGARG((png_structp png_ptr,
    png_voidp ptr));
 
 png_voidp
-png_malloc(png_structp png_ptr, png_uint_32 size) {
-   if (png_ptr == NULL) {
-      fprintf(STDERR, "NULL pointer to memory allocator\n");
-      return (NULL);
-   }
+png_debug_malloc(png_structp png_ptr, png_uint_32 size) {
+
+   /* png_malloc has already tested for NULL; png_create_struct calls
+      png_debug_malloc directly, with png_ptr == NULL which is OK */
+
    if (size == 0)
       return (png_voidp)(NULL);
 
    /* This calls the library allocator twice, once to get the requested
       buffer and once to get a new free list entry. */
    {
-      memory_infop pinfo = png_debug_malloc(png_ptr, sizeof *pinfo);
+      memory_infop pinfo = png_malloc_default(png_ptr, sizeof *pinfo);
       pinfo->size = size;
       current_allocation += size;
       if (current_allocation > maximum_allocation)
          maximum_allocation = current_allocation;
-      pinfo->pointer = png_debug_malloc(png_ptr, size);
+      pinfo->pointer = png_malloc_default(png_ptr, size);
       pinfo->next = pinformation;
       pinformation = pinfo;
       /* Make sure the caller isn't assuming zeroed memory. */
@@ -411,10 +418,10 @@ png_malloc(png_structp png_ptr, png_uint_32 size) {
 
 /* Free a pointer.  It is removed from the list at the same time. */
 void
-png_free(png_structp png_ptr, png_voidp ptr)
+png_debug_free(png_structp png_ptr, png_voidp ptr)
 {
    if (png_ptr == NULL)
-      fprintf(STDERR, "NULL pointer to memory allocator\n");
+      fprintf(STDERR, "NULL pointer to png_debug_free.\n");
    if (ptr == 0) {
 #if 0 /* This happens all the time. */
       fprintf(STDERR, "WARNING: freeing NULL pointer\n");
@@ -433,9 +440,9 @@ png_free(png_structp png_ptr, png_voidp ptr)
             if (current_allocation < 0)
                fprintf(STDERR, "Duplicate free of memory\n");
             /* We must free the list element too, but first kill
-               the memory which is to be freed. */
+               the memory that is to be freed. */
             memset(ptr, 0x55, pinfo->size);
-            png_debug_free(png_ptr, pinfo);
+            png_free_default(png_ptr, pinfo);
             break;
          }
          if (pinfo->next == NULL) {
@@ -447,10 +454,9 @@ png_free(png_structp png_ptr, png_voidp ptr)
    }
 
    /* Finally free the data. */
-   png_debug_free(png_ptr, ptr);
+   png_free_default(png_ptr, ptr);
 }
-#endif /* Not Borland DOS special memory handler */
-#endif
+#endif /* PNG_USER_MEM_SUPPORTED */
 /* END of code to test memory allocation/deallocation */
 
 /* Test one file */
@@ -468,7 +474,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
 #ifdef USE_FAR_KEYWORD
    jmp_buf jmpbuf;
 #endif   
-   
+
    char inbuf[256], outbuf[256];
 
    row_buf = (png_bytep)NULL;
@@ -487,14 +493,26 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
    }
 
    png_debug(0, "Allocating read and write structures\n");
+#ifdef PNG_USER_MEM_SUPPORTED
+   read_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
+      (png_error_ptr)NULL, (png_error_ptr)NULL, (png_voidp)NULL,
+      (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free);
+#else
    read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
       (png_error_ptr)NULL, (png_error_ptr)NULL);
+#endif
 #if defined(PNG_NO_STDIO)
    png_set_error_fn(read_ptr, (png_voidp)inname, png_default_error,
        png_default_warning);
 #endif
+#ifdef PNG_USER_MEM_SUPPORTED
+   write_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
+      (png_error_ptr)NULL, (png_error_ptr)NULL, (png_voidp)NULL,
+      (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free);
+#else
    write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
       (png_error_ptr)NULL, (png_error_ptr)NULL);
+#endif
 #if defined(PNG_NO_STDIO)
    png_set_error_fn(write_ptr, (png_voidp)inname, png_default_error,
        png_default_warning);
@@ -503,6 +521,8 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
    read_info_ptr = png_create_info_struct(read_ptr);
    write_info_ptr = png_create_info_struct(write_ptr);
    end_info_ptr = png_create_info_struct(read_ptr);
+#ifdef PNG_USER_MEM_SUPPORTED
+#endif
 
    png_debug(0, "Setting jmpbuf for read struct\n");
 #ifdef USE_FAR_KEYWORD
@@ -518,10 +538,12 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
       fclose(fpout);
       return (1);
    }
+#ifdef USE_FAR_KEYWORD
+   png_memcpy(read_ptr->jmpbuf,jmpbuf,sizeof(jmp_buf));
+#endif
 
    png_debug(0, "Setting jmpbuf for write struct\n");
 #ifdef USE_FAR_KEYWORD
-   png_memcpy(read_ptr->jmpbuf,jmpbuf,sizeof(jmp_buf));
    if (setjmp(jmpbuf))
 #else
    if (setjmp(write_ptr->jmpbuf))
@@ -534,10 +556,10 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
       fclose(fpout);
       return (1);
    }
-
 #ifdef USE_FAR_KEYWORD
    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);
@@ -563,8 +585,8 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
    }
 
 #  if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
-     black_pixels=0;
-     png_set_write_user_transform_fn(write_ptr, count_black_pixels);
+     zero_samples=0;
+     png_set_write_user_transform_fn(write_ptr, count_zero_samples);
 #  endif
 
    png_debug(0, "Reading info struct\n");
@@ -713,6 +735,13 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
       if (png_get_tIME(read_ptr, read_info_ptr, &mod_time))
       {
          png_set_tIME(write_ptr, write_info_ptr, mod_time);
+#if defined(PNG_TIME_RFC1123_SUPPORTED)
+         /* we have to use png_strcpy instead of "=" because the string
+            pointed to by png_convert_to_rfc1123() gets free'ed before
+            we use it */
+         png_strcpy(tIME_string,png_convert_to_rfc1123(read_ptr, mod_time));
+         tIME_chunk_present++;
+#endif /* PNG_TIME_RFC1123_SUPPORTED */
       }
    }
 #endif
@@ -735,7 +764,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
    png_write_info(write_ptr, write_info_ptr);
 
    png_debug(0, "\nAllocating row buffer \n");
-   row_buf = (png_bytep)png_malloc(read_ptr, 
+   row_buf = (png_bytep)png_malloc(read_ptr,
       png_get_rowbytes(read_ptr, read_info_ptr));
    if (row_buf == NULL)
    {
@@ -764,7 +793,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
    png_debug(0, "Reading and writing end_info data\n");
    png_read_end(read_ptr, end_info_ptr);
    png_write_end(write_ptr, end_info_ptr);
+
 #ifdef PNG_EASY_ACCESS_SUPPORTED
    if(verbose)
    {
@@ -871,6 +900,7 @@ main(int argc, char *argv[])
 
    fprintf(STDERR, "Testing libpng version %s\n", PNG_LIBPNG_VER_STRING);
    fprintf(STDERR, "   with zlib   version %s\n", ZLIB_VERSION);
+   fprintf(STDERR,"%s",png_get_copyright(NULL));
 
    /* Do some consistency checking on the memory allocation settings, I'm
       not sure this matters, but it is nice to know, the first of these
@@ -938,7 +968,7 @@ main(int argc, char *argv[])
    if (multiple)
    {
       int i;
-#ifdef PNGTEST_MEMORY_DEBUG
+#ifdef PNG_USER_MEM_SUPPORTED
       int allocation_now = current_allocation;
 #endif
       for (i=2; i<argc; ++i)
@@ -946,17 +976,25 @@ main(int argc, char *argv[])
          int kerror;
          fprintf(STDERR, "Testing %s:",argv[i]);
          kerror = test_one_file(argv[i], outname);
-         if (kerror == 0) 
+         if (kerror == 0)
+         {
 #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
-            fprintf(STDERR, " PASS (%lu black pixels)\n",black_pixels);
+            fprintf(STDERR, " PASS (%lu zero samples)\n",zero_samples);
 #else
             fprintf(STDERR, " PASS\n");
 #endif
-         else {
+#if defined(PNG_TIME_RFC1123_SUPPORTED)
+         if(tIME_chunk_present != 0)
+            fprintf(STDERR, " tIME = %s\n",tIME_string);
+         tIME_chunk_present = 0;
+#endif /* PNG_TIME_RFC1123_SUPPORTED */
+         }
+         else
+         {
             fprintf(STDERR, " FAIL\n");
             ierror += kerror;
-            }
-#ifdef PNGTEST_MEMORY_DEBUG
+         }
+#ifdef PNG_USER_MEM_SUPPORTED
          if (allocation_now != current_allocation)
             fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n",
                current_allocation-allocation_now);
@@ -972,7 +1010,7 @@ main(int argc, char *argv[])
          }
 #endif
       }
-#ifdef PNGTEST_MEMORY_DEBUG
+#ifdef PNG_USER_MEM_SUPPORTED
          fprintf(STDERR, "Maximum memory allocation: %d bytes\n",
             maximum_allocation);
 #endif
@@ -982,7 +1020,7 @@ main(int argc, char *argv[])
       int i;
       for (i=0; i<3; ++i) {
          int kerror;
-#ifdef PNGTEST_MEMORY_DEBUG
+#ifdef PNG_USER_MEM_SUPPORTED
          int allocation_now = current_allocation;
 #endif
          if (i == 1) status_dots_requested = 1;
@@ -993,11 +1031,17 @@ main(int argc, char *argv[])
          if(kerror == 0)
          {
             if(verbose == 1 || i == 2)
+            {
 #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
-                fprintf(STDERR, " PASS (%lu black pixels)\n",black_pixels);
+                fprintf(STDERR, " PASS (%lu zero samples)\n",zero_samples);
 #else
                 fprintf(STDERR, " PASS\n");
 #endif
+#if defined(PNG_TIME_RFC1123_SUPPORTED)
+         if(tIME_chunk_present != 0)
+            fprintf(STDERR, " tIME = %s\n",tIME_string);
+#endif /* PNG_TIME_RFC1123_SUPPORTED */
+            }
          }
          else
          {
@@ -1006,13 +1050,13 @@ main(int argc, char *argv[])
             fprintf(STDERR, " FAIL\n");
             ierror += kerror;
          }
-#ifdef PNGTEST_MEMORY_DEBUG
+#ifdef PNG_USER_MEM_SUPPORTED
          if (allocation_now != current_allocation)
              fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n",
                current_allocation-allocation_now);
          if (current_allocation != 0) {
              memory_infop pinfo = pinformation;
-   
+
              fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n",
                 current_allocation);
              while (pinfo != NULL) {
@@ -1022,7 +1066,7 @@ main(int argc, char *argv[])
           }
 #endif
        }
-#ifdef PNGTEST_MEMORY_DEBUG
+#ifdef PNG_USER_MEM_SUPPORTED
        fprintf(STDERR, "Maximum memory allocation: %d bytes\n",
           maximum_allocation);
 #endif
@@ -1034,3 +1078,4 @@ main(int argc, char *argv[])
       fprintf(STDERR, "libpng FAILS test\n");
    return (int)(ierror != 0);
 }
+
index b28464acb264593caae8bf72aa816143e79afa93..397c988f071312bef06316530c5c90742d171cdf 100644 (file)
@@ -1,16 +1,15 @@
 
 /* pngtrans.c - transforms the data in a row (used by both readers and writers)
  *
- * libpng 1.0.1
+ * libpng 1.0.3 - January 14, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, Glenn Randers-Pehrson
- * March 15, 1998
+ * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
  */
 
 #define PNG_INTERNAL
-#include "../png/png.h"
+#include "png.h"
 
 #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
 /* turn on bgr to rgb mapping */
@@ -87,8 +86,8 @@ png_set_interlace_handling(png_structp png_ptr)
 #if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
 /* Add a filler byte on read, or remove a filler or alpha byte on write.
  * The filler type has changed in v0.95 to allow future 2-byte fillers
- * for 48-bit input data, as well as avoiding problems with some compilers
- * which don't like bytes as parameters.
+ * for 48-bit input data, as well as to avoid problems with some compilers
+ * that don't like bytes as parameters.
  */
 void
 png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc)
@@ -101,11 +100,23 @@ png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc)
    else
       png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
 
-   /* This should probably go in the "do_filler" routine */
-   if (png_ptr->color_type == PNG_COLOR_TYPE_RGB && png_ptr->bit_depth == 8)
+   /* This should probably go in the "do_filler" routine.
+    * I attempted to do that in libpng-1.0.1a but that caused problems
+    * so I restored it in libpng-1.0.2a
+   */
+
+   if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
    {
       png_ptr->usr_channels = 4;
    }
+
+   /* Also I added this in libpng-1.0.2a (what happens when we expand
+    * a less-than-8-bit grayscale to GA? */
+
+   if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY && png_ptr->bit_depth >= 8)
+   {
+      png_ptr->usr_channels = 2;
+   }
 }
 #endif
 
@@ -137,7 +148,7 @@ png_set_invert_mono(png_structp png_ptr)
    png_ptr->transformations |= PNG_INVERT_MONO;
 }
 
-/* invert monocrome grayscale data */
+/* invert monochrome grayscale data */
 void
 png_do_invert(png_row_infop row_info, png_bytep row)
 {
@@ -148,12 +159,14 @@ png_do_invert(png_row_infop row_info, png_bytep row)
 #endif
        row_info->color_type == PNG_COLOR_TYPE_GRAY)
    {
-      png_bytep rp;
+      png_bytep rp = row;
       png_uint_32 i;
+      png_uint_32 istop = row_info->rowbytes;
 
-      for (i = 0, rp = row; i < row_info->rowbytes; i++, rp++)
+      for (i = 0; i < istop; i++)
       {
          *rp = (png_byte)(~(*rp));
+         rp++;
       }
    }
 }
@@ -171,15 +184,13 @@ png_do_swap(png_row_infop row_info, png_bytep row)
 #endif
        row_info->bit_depth == 16)
    {
-      png_bytep rp;
-      png_byte t;
+      png_bytep rp = row;
       png_uint_32 i;
+      png_uint_32 istop= row_info->width * row_info->channels;
 
-      for (i = 0, rp = row;
-         i < row_info->width * row_info->channels;
-         i++, rp += 2)
+      for (i = 0; i < istop; i++, rp += 2)
       {
-         t = *rp;
+         png_byte t = *rp;
          *rp = *(rp + 1);
          *(rp + 1) = t;
       }
@@ -338,6 +349,11 @@ png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
       if (row_info->color_type == PNG_COLOR_TYPE_RGB ||
           row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
 */
+      png_bytep sp=row;
+      png_bytep dp=row;
+      png_uint_32 row_width=row_info->width;
+      png_uint_32 i;
+
       if (row_info->channels == 4)
       {
          if (row_info->bit_depth == 8)
@@ -345,10 +361,8 @@ png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
             /* This converts from RGBX or RGBA to RGB */
             if (flags & PNG_FLAG_FILLER_AFTER)
             {
-               png_bytep sp, dp;
-               png_uint_32 i;
-
-               for (i = 1, sp = row + 4, dp = row + 3; i < row_info->width; i++)
+               dp+=3; sp+=4;
+               for (i = 1; i < row_width; i++)
                {
                   *dp++ = *sp++;
                   *dp++ = *sp++;
@@ -359,10 +373,7 @@ png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
             /* This converts from XRGB or ARGB to RGB */
             else
             {
-               png_bytep sp, dp;
-               png_uint_32 i;
-
-               for (i = 0, sp = row, dp = row; i < row_info->width; i++)
+               for (i = 0; i < row_width; i++)
                {
                   sp++;
                   *dp++ = *sp++;
@@ -371,17 +382,15 @@ png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
                }
             }
             row_info->pixel_depth = 24;
-            row_info->rowbytes = row_info->width * 3;
+            row_info->rowbytes = row_width * 3;
          }
          else /* if (row_info->bit_depth == 16) */
          {
             if (flags & PNG_FLAG_FILLER_AFTER)
             {
-               png_bytep sp, dp;
-               png_uint_32 i;
-
                /* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */
-               for (i = 1, sp = row + 8, dp = row + 6; i < row_info->width; i++)
+               sp += 8; dp += 6;
+               for (i = 1; i < row_width; i++)
                {
                   /* This could be (although memcpy is probably slower):
                   png_memcpy(dp, sp, 6);
@@ -399,17 +408,15 @@ png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
             }
             else
             {
-               png_bytep sp, dp;
-               png_uint_32 i;
-
                /* This converts from XXRRGGBB or AARRGGBB to RRGGBB */
-               for (i = 0, sp = row + 2, dp = row; i < row_info->width; i++)
+               for (i = 0; i < row_width; i++)
                {
                   /* This could be (although memcpy is probably slower):
                   png_memcpy(dp, sp, 6);
                   sp += 8;
                   dp += 6;
                   */
+                  sp+=2;
                   *dp++ = *sp++;
                   *dp++ = *sp++;
                   *dp++ = *sp++;
@@ -419,9 +426,10 @@ png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
                }
             }
             row_info->pixel_depth = 48;
-            row_info->rowbytes = row_info->width * 6;
+            row_info->rowbytes = row_width * 6;
          }
          row_info->channels = 3;
+         row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
       }
 /*
       else if (row_info->color_type == PNG_COLOR_TYPE_GRAY ||
@@ -434,10 +442,7 @@ png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
             /* This converts from GX or GA to G */
             if (flags & PNG_FLAG_FILLER_AFTER)
             {
-               png_bytep sp, dp;
-               png_uint_32 i;
-
-               for (i = 1, sp = row + 2, dp = row + 1; i < row_info->width; i++)
+               for (i = 0; i < row_width; i++)
                {
                   *dp++ = *sp++;
                   sp++;
@@ -446,27 +451,22 @@ png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
             /* This converts from XG or AG to G */
             else
             {
-               png_bytep sp, dp;
-               png_uint_32 i;
-
-               for (i = 0, sp = row, dp = row; i < row_info->width; i++)
+               for (i = 0; i < row_width; i++)
                {
                   sp++;
                   *dp++ = *sp++;
                }
             }
             row_info->pixel_depth = 8;
-            row_info->rowbytes = row_info->width;
+            row_info->rowbytes = row_width;
          }
          else /* if (row_info->bit_depth == 16) */
          {
             if (flags & PNG_FLAG_FILLER_AFTER)
             {
-               png_bytep sp, dp;
-               png_uint_32 i;
-
                /* This converts from GGXX or GGAA to GG */
-               for (i = 1, sp = row + 4, dp = row + 2; i < row_info->width; i++)
+               sp += 4; dp += 2;
+               for (i = 1; i < row_width; i++)
                {
                   *dp++ = *sp++;
                   *dp++ = *sp++;
@@ -475,11 +475,8 @@ png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
             }
             else
             {
-               png_bytep sp, dp;
-               png_uint_32 i;
-
                /* This converts from XXGG or AAGG to GG */
-               for (i = 0, sp = row, dp = row; i < row_info->width; i++)
+               for (i = 0; i < row_width; i++)
                {
                   sp += 2;
                   *dp++ = *sp++;
@@ -487,9 +484,10 @@ png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
                }
             }
             row_info->pixel_depth = 16;
-            row_info->rowbytes = row_info->width * 2;
+            row_info->rowbytes = row_width * 2;
          }
          row_info->channels = 1;
+         row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
       }
    }
 }
@@ -507,17 +505,17 @@ png_do_bgr(png_row_infop row_info, png_bytep row)
 #endif
        (row_info->color_type & PNG_COLOR_MASK_COLOR))
    {
+      png_uint_32 row_width = row_info->width;
       if (row_info->bit_depth == 8)
       {
          if (row_info->color_type == PNG_COLOR_TYPE_RGB)
          {
             png_bytep rp;
-            png_byte save;
             png_uint_32 i;
 
-            for (i = 0, rp = row; i < row_info->width; i++, rp += 3)
+            for (i = 0, rp = row; i < row_width; i++, rp += 3)
             {
-               save = *rp;
+               png_byte save = *rp;
                *rp = *(rp + 2);
                *(rp + 2) = save;
             }
@@ -525,12 +523,11 @@ png_do_bgr(png_row_infop row_info, png_bytep row)
          else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
          {
             png_bytep rp;
-            png_byte save;
             png_uint_32 i;
 
-            for (i = 0, rp = row; i < row_info->width; i++, rp += 4)
+            for (i = 0, rp = row; i < row_width; i++, rp += 4)
             {
-               save = *rp;
+               png_byte save = *rp;
                *rp = *(rp + 2);
                *(rp + 2) = save;
             }
@@ -541,33 +538,31 @@ png_do_bgr(png_row_infop row_info, png_bytep row)
          if (row_info->color_type == PNG_COLOR_TYPE_RGB)
          {
             png_bytep rp;
-            png_byte save[2];
             png_uint_32 i;
 
-            for (i = 0, rp = row; i < row_info->width; i++, rp += 6)
+            for (i = 0, rp = row; i < row_width; i++, rp += 6)
             {
-               save[0] = *rp;
-               save[1] = *(rp + 1);
+               png_byte save = *rp;
                *rp = *(rp + 4);
+               *(rp + 4) = save;
+               save = *(rp + 1);
                *(rp + 1) = *(rp + 5);
-               *(rp + 4) = save[0];
-               *(rp + 5) = save[1];
+               *(rp + 5) = save;
             }
          }
          else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
          {
             png_bytep rp;
-            png_byte save[2];
             png_uint_32 i;
 
-            for (i = 0, rp = row; i < row_info->width; i++, rp += 8)
+            for (i = 0, rp = row; i < row_width; i++, rp += 8)
             {
-               save[0] = *rp;
-               save[1] = *(rp + 1);
+               png_byte save = *rp;
                *rp = *(rp + 4);
+               *(rp + 4) = save;
+               save = *(rp + 1);
                *(rp + 1) = *(rp + 5);
-               *(rp + 4) = save[0];
-               *(rp + 5) = save[1];
+               *(rp + 5) = save;
             }
          }
       }
index 69825046917a684b23cfa9cef54e4834482586c4..84b5b2869d8053e2e864b4ffd1696d595732fa99 100644 (file)
@@ -1,29 +1,28 @@
 
 /* pngwio.c - functions for data output
  *
- * libpng 1.0.1
+ * libpng 1.0.3 - January 14, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, Glenn Randers-Pehrson
- * March 15, 1998
+ * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
  *
- * This file provides a location for all output.  Users which need
- * special handling are expected to write functions which have the same
- * arguments as these, and perform similar functions, but possibly use
- * different output methods.  Note that you shouldn't change these
+ * This file provides a location for all output.  Users who need
+ * special handling are expected to write functions that have the same
+ * arguments as these and perform similar functions, but that possibly
+ * use different output methods.  Note that you shouldn't change these
  * functions, but rather write replacement functions and then change
  * them at run time with png_set_write_fn(...).
  */
 
 #define PNG_INTERNAL
-#include "../png/png.h"
+#include "png.h"
 
 /* Write the data to whatever output you are using.  The default routine
    writes to a file pointer.  Note that this routine sometimes gets called
    with very small lengths, so you should implement some kind of simple
    buffering if you are using unbuffered writes.  This should never be asked
-   to write more then 64K on a 16 bit machine.  */
+   to write more than 64K on a 16 bit machine.  */
 
 void
 png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
@@ -35,7 +34,7 @@ png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
 }
 
 #if !defined(PNG_NO_STDIO)
-/* This is the function which does the actual writing of data.  If you are
+/* This is the function that 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. */
@@ -133,13 +132,13 @@ png_default_flush(png_structp png_ptr)
    png_ptr       - pointer to a png output data structure
    io_ptr        - pointer to user supplied structure containing info about
                    the output functions.  May be NULL.
-   write_data_fn - pointer to a new output function which takes as its
+   write_data_fn - pointer to a new output function that takes as its
                    arguments a pointer to a png_struct, a pointer to
-                   data to be written, and a 32-bit unsigned int which is
+                   data to be written, and a 32-bit unsigned int that is
                    the number of bytes to be written.  The new write
                    function should call png_error(png_ptr, "Error msg")
                    to exit and output any fatal error messages.
-   flush_data_fn - pointer to a new flush function which takes as its
+   flush_data_fn - pointer to a new flush function that takes as its
                    arguments a pointer to a png_struct.  After a call to
                    the flush function, there should be no data in any buffers
                    or pending transmission.  If the output method doesn't do
@@ -175,14 +174,21 @@ png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
 #endif /* PNG_WRITE_FLUSH_SUPPORTED */
 
    /* It is an error to read while writing a png file */
-   png_ptr->read_data_fn = NULL;
+   if (png_ptr->read_data_fn != NULL)
+   {
+      png_ptr->read_data_fn = NULL;
+      png_warning(png_ptr,
+         "Attempted to set both read_data_fn and write_data_fn in");
+      png_warning(png_ptr,
+         "the same structure.  Resetting read_data_fn to NULL.");
+   }
 }
 
-#if defined(USE_FAR_KEYWORD) 
-#if defined(_MSC_VER)   
+#if defined(USE_FAR_KEYWORD)
+#if defined(_MSC_VER)
 void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check)
 {
-   void *near_ptr;   
+   void *near_ptr;
    void FAR *far_ptr;
    FP_OFF(near_ptr) = FP_OFF(ptr);
    far_ptr = (void FAR *)near_ptr;
@@ -194,7 +200,7 @@ void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check)
 #  else
 void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check)
 {
-   void *near_ptr;   
+   void *near_ptr;
    void FAR *far_ptr;
    near_ptr = (void FAR *)ptr;
    far_ptr = (void FAR *)near_ptr;
index 699207c04a8596485fc17a743af019fe3504bc1f..3b533e58c23d7870fed1b5acab7a33b4fa27dce4 100644 (file)
@@ -1,22 +1,21 @@
-   
+
 /* pngwrite.c - general routines to write a PNG file
  *
- * libpng 1.0.1
+ * libpng 1.0.3 - January 14, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, Glenn Randers-Pehrson
- * March 15, 1998
+ * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
  */
 
 /* get internal access to png.h */
 #define PNG_INTERNAL
-#include "../png/png.h"
+#include "png.h"
 
 /* Writes all the PNG information.  This is the suggested way to use the
  * library.  If you have a new chunk to add, make a function to write it,
  * and put it in the correct location here.  If you want the chunk written
- * after the image data, put it in png_write_end().  I strongly encurage
+ * after the image data, put it in png_write_end().  I strongly encourage
  * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing
  * the chunk, as that will keep the code from breaking if you want to just
  * write a plain PNG file.  If you have long comments, I suggest writing
@@ -218,43 +217,6 @@ png_write_end(png_structp png_ptr, png_infop info_ptr)
    png_write_IEND(png_ptr);
 }
 
-#if defined(PNG_TIME_RFC1123_SUPPORTED)
-/* Convert the supplied time into an RFC 1123 string suitable for use in
- * a "Creation Time" or other text-based time string.
- */
-png_charp
-png_convert_to_rfc1123(png_structp png_ptr, png_timep ptime)
-{
-   static PNG_CONST char short_months[12][4] =
-       {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
-        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
-
-   if (png_ptr->time_buffer == NULL)
-   {
-      png_ptr->time_buffer = (png_charp)png_malloc(png_ptr, (png_uint_32)(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 - 1],
-               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 - 1],
-               ptime->year, ptime->hour % 24, ptime->minute % 60,
-               ptime->second % 61);
-#endif
-   return ((png_charp)png_ptr->time_buffer);
-}
-#endif /* PNG_TIME_RFC1123_SUPPORTED */
-
 #if defined(PNG_WRITE_tIME_SUPPORTED)
 void
 png_convert_from_struct_tm(png_timep ptime, struct tm FAR * ttime)
@@ -281,15 +243,32 @@ png_convert_from_time_t(png_timep ptime, time_t ttime)
 
 /* Initialize png_ptr structure, and allocate any memory needed */
 png_structp
-png_create_write_struct(png_const_charp user_png_ver, voidp error_ptr,
+png_create_write_struct(png_const_charp user_png_ver, png_voidp error_ptr,
    png_error_ptr error_fn, png_error_ptr warn_fn)
 {
+#ifdef PNG_USER_MEM_SUPPORTED
+   return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn,
+      warn_fn, NULL, NULL, NULL));
+}
+
+/* Alternate initialize png_ptr structure, and allocate any memory needed */
+png_structp
+png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
+   png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
+   png_malloc_ptr malloc_fn, png_free_ptr free_fn)
+{
+#endif /* PNG_USER_MEM_SUPPORTED */
    png_structp png_ptr;
 #ifdef USE_FAR_KEYWORD
    jmp_buf jmpbuf;
 #endif
    png_debug(1, "in png_create_write_struct\n");
+#ifdef PNG_USER_MEM_SUPPORTED
+   if ((png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,
+      (png_malloc_ptr)malloc_fn)) == NULL)
+#else
    if ((png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG)) == NULL)
+#endif /* PNG_USER_MEM_SUPPORTED */
    {
       return ((png_structp)NULL);
    }
@@ -306,6 +285,9 @@ png_create_write_struct(png_const_charp user_png_ver, voidp error_ptr,
 #ifdef USE_FAR_KEYWORD
    png_memcpy(png_ptr->jmpbuf,jmpbuf,sizeof(jmp_buf));
 #endif
+#ifdef PNG_USER_MEM_SUPPORTED
+   png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn);
+#endif /* PNG_USER_MEM_SUPPORTED */
    png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
 
    /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
@@ -335,7 +317,6 @@ png_create_write_struct(png_const_charp user_png_ver, voidp error_ptr,
    return ((png_structp)png_ptr);
 }
 
-
 /* Initialize png_ptr structure, and allocate any memory needed */
 void
 png_write_init(png_structp png_ptr)
@@ -422,6 +403,36 @@ png_write_row(png_structp png_ptr, png_bytep row)
    /* initialize transformations and other stuff if first time */
    if (png_ptr->row_number == 0 && png_ptr->pass == 0)
    {
+   /* check for transforms that have been set but were defined out */
+#if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED)
+   if (png_ptr->transformations & PNG_INVERT_MONO)
+      png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined.");
+#endif
+#if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED)
+   if (png_ptr->transformations & PNG_FILLER)
+      png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined.");
+#endif
+#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && defined(PNG_READ_PACKSWAP_SUPPORTED)
+   if (png_ptr->transformations & PNG_PACKSWAP)
+      png_warning(png_ptr, "PNG_WRITE_PACKSWAP_SUPPORTED is not defined.");
+#endif
+#if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED)
+   if (png_ptr->transformations & PNG_PACK)
+      png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined.");
+#endif
+#if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED)
+   if (png_ptr->transformations & PNG_SHIFT)
+      png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined.");
+#endif
+#if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED)
+   if (png_ptr->transformations & PNG_BGR)
+      png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined.");
+#endif
+#if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED)
+   if (png_ptr->transformations & PNG_SWAP_BYTES)
+      png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined.");
+#endif
+
       png_write_start_row(png_ptr);
    }
 
@@ -601,10 +612,18 @@ png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
 {
    png_structp png_ptr = NULL;
    png_infop info_ptr = NULL;
+#ifdef PNG_USER_MEM_SUPPORTED
+   png_free_ptr free_fn = NULL;
+#endif
 
    png_debug(1, "in png_destroy_write_struct\n");
    if (png_ptr_ptr != NULL)
+   {
       png_ptr = *png_ptr_ptr;
+#ifdef PNG_USER_MEM_SUPPORTED
+      free_fn = png_ptr->free_fn;
+#endif
+   }
 
    if (info_ptr_ptr != NULL)
       info_ptr = *info_ptr_ptr;
@@ -627,14 +646,22 @@ png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
          png_free(png_ptr, info_ptr->pcal_params);
       }
 #endif
+#ifdef PNG_USER_MEM_SUPPORTED
+      png_destroy_struct_2((png_voidp)info_ptr, free_fn);
+#else
       png_destroy_struct((png_voidp)info_ptr);
+#endif
       *info_ptr_ptr = (png_infop)NULL;
    }
 
    if (png_ptr != NULL)
    {
       png_write_destroy(png_ptr);
+#ifdef PNG_USER_MEM_SUPPORTED
+      png_destroy_struct_2((png_voidp)png_ptr, free_fn);
+#else
       png_destroy_struct((png_voidp)png_ptr);
+#endif
       *png_ptr_ptr = (png_structp)NULL;
    }
 }
@@ -648,6 +675,9 @@ png_write_destroy(png_structp png_ptr)
    png_error_ptr error_fn;
    png_error_ptr warning_fn;
    png_voidp error_ptr;
+#ifdef PNG_USER_MEM_SUPPORTED
+   png_free_ptr free_fn;
+#endif
 
    png_debug(1, "in png_write_destroy\n");
    /* free any memory zlib uses */
@@ -678,12 +708,18 @@ png_write_destroy(png_structp png_ptr)
    error_fn = png_ptr->error_fn;
    warning_fn = png_ptr->warning_fn;
    error_ptr = png_ptr->error_ptr;
+#ifdef PNG_USER_MEM_SUPPORTED
+   free_fn = png_ptr->free_fn;
+#endif
 
    png_memset(png_ptr, 0, sizeof (png_struct));
 
    png_ptr->error_fn = error_fn;
    png_ptr->warning_fn = warning_fn;
    png_ptr->error_ptr = error_ptr;
+#ifdef PNG_USER_MEM_SUPPORTED
+   png_ptr->free_fn = free_fn;
+#endif
 
    png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
 }
@@ -794,9 +830,7 @@ 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)
index df224c88eebc6fcd66108d0ce3ff9a3a52be72a6..76cf3a3e5d9f638ee8ce253a5f579ebf50146036 100644 (file)
@@ -1,18 +1,17 @@
 
 /* pngwtran.c - transforms the data in a row for PNG writers
  *
- * libpng 1.0.1
+ * libpng 1.0.3 - January 14, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, Glenn Randers-Pehrson
- * March 15, 1998
+ * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
  */
 
 #define PNG_INTERNAL
-#include "../png/png.h"
+#include "png.h"
 
-/* Transform the data according to the users wishes.  The order of
+/* Transform the data according to the user's wishes.  The order of
  * transformations is significant.
  */
 void
@@ -48,15 +47,15 @@ png_do_write_transformations(png_structp png_ptr)
       png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1,
          (png_uint_32)png_ptr->bit_depth);
 #endif
+#if defined(PNG_WRITE_SWAP_SUPPORTED)
+   if (png_ptr->transformations & PNG_SWAP_BYTES)
+      png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
 #if defined(PNG_WRITE_SHIFT_SUPPORTED)
    if (png_ptr->transformations & PNG_SHIFT)
       png_do_shift(&(png_ptr->row_info), png_ptr->row_buf + 1,
          &(png_ptr->shift));
 #endif
-#if defined(PNG_WRITE_SWAP_SUPPORTED)
-   if (png_ptr->transformations & PNG_SWAP_BYTES)
-      png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
-#endif
 #if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
    if (png_ptr->transformations & PNG_INVERT_ALPHA)
       png_do_write_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
@@ -97,12 +96,14 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
             png_bytep sp, dp;
             int mask, v;
             png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
 
             sp = row;
             dp = row;
             mask = 0x80;
             v = 0;
-            for (i = 0; i < row_info->width; i++)
+
+            for (i = 0; i < row_width; i++)
             {
                if (*sp != 0)
                   v |= mask;
@@ -126,12 +127,13 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
             png_bytep sp, dp;
             int shift, v;
             png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
 
             sp = row;
             dp = row;
             shift = 6;
             v = 0;
-            for (i = 0; i < row_info->width; i++)
+            for (i = 0; i < row_width; i++)
             {
                png_byte value;
 
@@ -157,12 +159,13 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
             png_bytep sp, dp;
             int shift, v;
             png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
 
             sp = row;
             dp = row;
             shift = 4;
             v = 0;
-            for (i = 0; i < row_info->width; i++)
+            for (i = 0; i < row_width; i++)
             {
                png_byte value;
 
@@ -214,9 +217,8 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
       row_info->color_type != PNG_COLOR_TYPE_PALETTE)
    {
       int shift_start[4], shift_dec[4];
-      png_uint_32 channels;
+      int channels = 0;
 
-      channels = 0;
       if (row_info->color_type & PNG_COLOR_MASK_COLOR)
       {
          shift_start[channels] = row_info->bit_depth - bit_depth->red;
@@ -245,9 +247,10 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
       /* with low row depths, could only be grayscale, so one channel */
       if (row_info->bit_depth < 8)
       {
-         png_bytep bp;
+         png_bytep bp = row;
          png_uint_32 i;
          png_byte mask;
+         png_uint_32 row_bytes = row_info->rowbytes;
 
          if (bit_depth->gray == 1 && row_info->bit_depth == 2)
             mask = 0x55;
@@ -256,7 +259,7 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
          else
             mask = 0xff;
 
-         for (bp = row, i = 0; i < row_info->rowbytes; i++, bp++)
+         for (i = 0; i < row_bytes; i++, bp++)
          {
             png_uint_16 v;
             int j;
@@ -274,27 +277,25 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
       }
       else if (row_info->bit_depth == 8)
       {
-         png_bytep bp;
+         png_bytep bp = row;
          png_uint_32 i;
+         png_uint_32 istop = channels * row_info->width;
 
-         for (bp = row, i = 0; i < row_info->width; i++)
+         for (i = 0; i < istop; i++, bp++)
          {
-            png_uint_32 c;
 
-            for (c = 0; c < channels; c++, bp++)
-            {
-               png_uint_16 v;
-               int j;
+            png_uint_16 v;
+            int j;
+            int c = (int)(i%channels);
 
-               v = *bp;
-               *bp = 0;
-               for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
-               {
-                  if (j > 0)
-                     *bp |= (png_byte)((v << j) & 0xff);
-                  else
-                     *bp |= (png_byte)((v >> (-j)) & 0xff);
-               }
+            v = *bp;
+            *bp = 0;
+            for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
+            {
+               if (j > 0)
+                  *bp |= (png_byte)((v << j) & 0xff);
+               else
+                  *bp |= (png_byte)((v >> (-j)) & 0xff);
             }
          }
       }
@@ -302,28 +303,25 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
       {
          png_bytep bp;
          png_uint_32 i;
+         png_uint_32 istop = channels * row_info->width;
 
-         for (bp = row, i = 0; i < row_info->width * row_info->channels; i++)
+         for (bp = row, i = 0; i < istop; i++)
          {
-            png_uint_32 c;
+            int c = (int)(i%channels);
+            png_uint_16 value, v;
+            int j;
 
-            for (c = 0; c < channels; c++, bp += 2)
+            v = ((png_uint_16)(*bp) << 8) + *(bp + 1);
+            value = 0;
+            for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
             {
-               png_uint_16 value, v;
-               int j;
-
-               v = ((png_uint_16)(*bp) << 8) + *(bp + 1);
-               value = 0;
-               for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
-               {
-                  if (j > 0)
-                     value |= (png_uint_16)((v << j) & (png_uint_16)0xffff);
-                  else
-                     value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff);
-               }
-               *bp = (png_byte)(value >> 8);
-               *(bp + 1) = (png_byte)(value & 0xff);
+               if (j > 0)
+                  value |= (png_uint_16)((v << j) & (png_uint_16)0xffff);
+               else
+                  value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff);
             }
+            *bp++ = (png_byte)(value >> 8);
+            *bp++ = (png_byte)(value & 0xff);
          }
       }
    }
@@ -345,12 +343,11 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
          if (row_info->bit_depth == 8)
          {
             png_bytep sp, dp;
-            png_byte save;
             png_uint_32 i;
-
-            for (i = 0, sp = dp = row; i < row_info->width; i++)
+            png_uint_32 row_width = row_info->width;
+            for (i = 0, sp = dp = row; i < row_width; i++)
             {
-               save = *(sp++);
+               png_byte save = *(sp++);
                *(dp++) = *(sp++);
                *(dp++) = *(sp++);
                *(dp++) = *(sp++);
@@ -361,11 +358,12 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
          else
          {
             png_bytep sp, dp;
-            png_byte save[2];
             png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
 
-            for (i = 0, sp = dp = row; i < row_info->width; i++)
+            for (i = 0, sp = dp = row; i < row_width; i++)
             {
+               png_byte save[2];
                save[0] = *(sp++);
                save[1] = *(sp++);
                *(dp++) = *(sp++);
@@ -385,12 +383,12 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
          if (row_info->bit_depth == 8)
          {
             png_bytep sp, dp;
-            png_byte save;
             png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
 
-            for (i = 0, sp = dp = row; i < row_info->width; i++)
+            for (i = 0, sp = dp = row; i < row_width; i++)
             {
-               save = *(sp++);
+               png_byte save = *(sp++);
                *(dp++) = *(sp++);
                *(dp++) = save;
             }
@@ -399,11 +397,12 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
          else
          {
             png_bytep sp, dp;
-            png_byte save[2];
             png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
 
-            for (i = 0, sp = dp = row; i < row_info->width; i++)
+            for (i = 0, sp = dp = row; i < row_width; i++)
             {
+               png_byte save[2];
                save[0] = *(sp++);
                save[1] = *(sp++);
                *(dp++) = *(sp++);
@@ -433,8 +432,8 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
          {
             png_bytep sp, dp;
             png_uint_32 i;
-
-            for (i = 0, sp = dp = row; i < row_info->width; i++)
+            png_uint_32 row_width = row_info->width;
+            for (i = 0, sp = dp = row; i < row_width; i++)
             {
                *(dp++) = *(sp++);
                *(dp++) = *(sp++);
@@ -447,8 +446,9 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
          {
             png_bytep sp, dp;
             png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
 
-            for (i = 0, sp = dp = row; i < row_info->width; i++)
+            for (i = 0, sp = dp = row; i < row_width; i++)
             {
                *(dp++) = *(sp++);
                *(dp++) = *(sp++);
@@ -468,8 +468,9 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
          {
             png_bytep sp, dp;
             png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
 
-            for (i = 0, sp = dp = row; i < row_info->width; i++)
+            for (i = 0, sp = dp = row; i < row_width; i++)
             {
                *(dp++) = *(sp++);
                *(dp++) = 255 - *(sp++);
@@ -480,8 +481,9 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
          {
             png_bytep sp, dp;
             png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
 
-            for (i = 0, sp = dp = row; i < row_info->width; i++)
+            for (i = 0, sp = dp = row; i < row_width; i++)
             {
                *(dp++) = *(sp++);
                *(dp++) = *(sp++);
index c6ae1a677e46a739ece9afea05af22bb753d9f5d..4736361d2eb39a54cb8266749810d831cab0d35f 100644 (file)
@@ -1,16 +1,15 @@
 
 /* pngwutil.c - utilities to write a PNG file
  *
- * libpng 1.0.1
+ * libpng 1.0.3 - January 14, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, Glenn Randers-Pehrson
- * March 15, 1998
+ * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
  */
 
 #define PNG_INTERNAL
-#include "../png/png.h"
+#include "png.h"
 
 /* Place a 32-bit number into a buffer in PNG byte order.  We work
  * with unsigned numbers for convenience, although one supported
@@ -274,7 +273,7 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
 }
 
 /* write the palette.  We are careful not to trust png_color to be in the
- * correct order for PNG, so people can redefine it to any convient
+ * correct order for PNG, so people can redefine it to any convenient
  * structure.
  */
 void
@@ -377,9 +376,9 @@ png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type)
    {
       png_byte maxbits;
 
-      maxbits = color_type==PNG_COLOR_TYPE_PALETTE ? 8:png_ptr->usr_bit_depth;
-      if (sbit->red == 0 || sbit->red > maxbits || 
-          sbit->green == 0 || sbit->green > maxbits || 
+      maxbits = color_type==PNG_COLOR_TYPE_PALETTE ? 8 : png_ptr->usr_bit_depth;
+      if (sbit->red == 0 || sbit->red > maxbits ||
+          sbit->green == 0 || sbit->green > maxbits ||
           sbit->blue == 0 || sbit->blue > maxbits)
       {
          png_warning(png_ptr, "Invalid sBIT depth specified");
@@ -575,7 +574,8 @@ png_write_hIST(png_structp png_ptr, png_uint_16p hist, int num_hist)
 }
 #endif
 
-#if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
+#if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED) || \
+    defined(PNG_WRITE_pCAL_SUPPORTED)
 /* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
  * and if invalid, correct the keyword rather than discarding the entire
  * chunk.  The PNG 1.0 specification requires keywords 1-79 characters in
@@ -766,7 +766,7 @@ png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text,
    }
 
    /* We can't write the chunk until we find out how much data we have,
-    * which means we need to run the compressor first, and save the
+    * which means we need to run the compressor first and save the
     * output.  This shouldn't be a problem, as the vast majority of
     * comments should be reasonable, but we will set up an array of
     * malloc'd pointers to be sure.
@@ -835,7 +835,7 @@ png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text,
          png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
          png_ptr->zstream.next_out = png_ptr->zbuf;
       }
-   /* continue until we don't have anymore to compress */
+   /* continue until we don't have any more to compress */
    } while (png_ptr->zstream.avail_in);
 
    /* finish the compression */
@@ -952,7 +952,7 @@ void
 png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
    png_int_32 X1, int type, int nparams, png_charp units, png_charpp params)
 {
-   png_size_t purpose_len, units_len, total_len; 
+   png_size_t purpose_len, units_len, total_len;
    png_uint_32p params_len;
    png_byte buf[10];
    png_charp new_purpose;
@@ -1180,7 +1180,7 @@ png_write_finish_row(png_structp png_ptr)
       if (png_ptr->pass < 7)
       {
          if (png_ptr->prev_row != NULL)
-            png_memset(png_ptr->prev_row, 0, 
+            png_memset(png_ptr->prev_row, 0,
                (png_size_t) (((png_uint_32)png_ptr->usr_channels *
                (png_uint_32)png_ptr->usr_bit_depth *
                png_ptr->width + 7) >> 3) + 1);
@@ -1241,7 +1241,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
    if (pass < 6)
 #endif
    {
-      /* each pixel depth is handled seperately */
+      /* each pixel depth is handled separately */
       switch (row_info->pixel_depth)
       {
          case 1:
@@ -1252,11 +1252,12 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
             int d;
             int value;
             png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
 
             dp = row;
             d = 0;
             shift = 7;
-            for (i = png_pass_start[pass]; i < row_info->width;
+            for (i = png_pass_start[pass]; i < row_width;
                i += png_pass_inc[pass])
             {
                sp = row + (png_size_t)(i >> 3);
@@ -1285,11 +1286,12 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
             int d;
             int value;
             png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
 
             dp = row;
             shift = 6;
             d = 0;
-            for (i = png_pass_start[pass]; i < row_info->width;
+            for (i = png_pass_start[pass]; i < row_width;
                i += png_pass_inc[pass])
             {
                sp = row + (png_size_t)(i >> 2);
@@ -1317,11 +1319,12 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
             int d;
             int value;
             png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
 
             dp = row;
             shift = 4;
             d = 0;
-            for (i = png_pass_start[pass]; i < row_info->width;
+            for (i = png_pass_start[pass]; i < row_width;
                i += png_pass_inc[pass])
             {
                sp = row + (png_size_t)(i >> 1);
@@ -1346,6 +1349,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
             png_bytep sp;
             png_bytep dp;
             png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
             png_size_t pixel_bytes;
 
             /* start at the beginning */
@@ -1354,7 +1358,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
             pixel_bytes = (row_info->pixel_depth >> 3);
             /* loop through the row, only looking at the pixels that
                matter */
-            for (i = png_pass_start[pass]; i < row_info->width;
+            for (i = png_pass_start[pass]; i < row_width;
                i += png_pass_inc[pass])
             {
                /* find out where the original pixel is */
@@ -1392,6 +1396,11 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
 {
    png_bytep prev_row, best_row, row_buf;
    png_uint_32 mins, bpp;
+   png_byte filter_to_do = png_ptr->do_filter;
+   png_uint_32 row_bytes = row_info->rowbytes;
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+   int num_p_filters = (int)png_ptr->num_prev_filters;
+#endif
 
    png_debug(1, "in png_write_find_filter\n");
    /* find out how many bytes offset each pixel is */
@@ -1403,28 +1412,38 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
 
    /* The prediction method we use is to find which method provides the
     * smallest value when summing the absolute values of the distances
-    * from zero using anything >= 128 as negative numbers.  This is known
+    * from zero, using anything >= 128 as negative numbers.  This is known
     * as the "minimum sum of absolute differences" heuristic.  Other
-    * heuristics are the "weighted minumum sum of absolute differences"
+    * heuristics are the "weighted minimum sum of absolute differences"
     * (experimental and can in theory improve compression), and the "zlib
-    * predictive" method (not implemented in libpng 0.95), which does test
-    * compressions of lines using different filter methods, and then chooses
-    * the (series of) filter(s) which give minimum compressed data size (VERY
+    * predictive" method (not implemented yet), which does test compressions
+    * of lines using different filter methods, and then chooses the
+    * (series of) filter(s) that give minimum compressed data size (VERY
     * computationally expensive).
+    *
+    * GRR 980525:  consider also
+    *   (1) minimum sum of absolute differences from running average (i.e.,
+    *       keep running sum of non-absolute differences & count of bytes)
+    *       [track dispersion, too?  restart average if dispersion too large?]
+    *  (1b) minimum sum of absolute differences from sliding average, probably
+    *       with window size <= deflate window (usually 32K)
+    *   (2) minimum sum of squared differences from zero or running average
+    *       (i.e., ~ root-mean-square approach)
     */
 
+
    /* We don't need to test the 'no filter' case if this is the only filter
     * that has been chosen, as it doesn't actually do anything to the data.
     */
-   if (png_ptr->do_filter & PNG_FILTER_NONE &&
-       png_ptr->do_filter != PNG_FILTER_NONE)
+   if (filter_to_do & PNG_FILTER_NONE &&
+       filter_to_do != PNG_FILTER_NONE)
    {
       png_bytep rp;
       png_uint_32 sum = 0;
       png_uint_32 i;
       int v;
 
-      for (i = 0, rp = row_buf + 1; i < row_info->rowbytes; i++, rp++)
+      for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++)
       {
          v = *rp;
          sum += (v < 128) ? v : 256 - v;
@@ -1434,17 +1453,18 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
       {
          png_uint_32 sumhi, sumlo;
+         int j;
          sumlo = sum & PNG_LOMASK;
          sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */
 
          /* Reduce the sum if we match any of the previous rows */
-         for (i = 0; i < (png_uint_32)png_ptr->num_prev_filters; i++)
+         for (j = 0; j < num_p_filters; j++)
          {
-            if (png_ptr->prev_filters[i] == PNG_FILTER_NONE)
+            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
             {
-               sumlo = (sumlo * png_ptr->filter_weights[i]) >>
+               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
                   PNG_WEIGHT_SHIFT;
-               sumhi = (sumhi * png_ptr->filter_weights[i]) >>
+               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
                   PNG_WEIGHT_SHIFT;
             }
          }
@@ -1468,7 +1488,25 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
    }
 
    /* sub filter */
-   if (png_ptr->do_filter & PNG_FILTER_SUB)
+   if (filter_to_do == PNG_FILTER_SUB)
+   /* it's the only filter so no testing is needed */
+   {
+      png_bytep rp, lp, dp;
+      png_uint_32 i;
+      for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
+           i++, rp++, dp++)
+      {
+         *dp = *rp;
+      }
+      for (lp = row_buf + 1; i < row_bytes;
+         i++, rp++, lp++, dp++)
+      {
+         *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
+      }
+      best_row = png_ptr->sub_row;
+   }
+
+   else if (filter_to_do & PNG_FILTER_SUB)
    {
       png_bytep rp, dp, lp;
       png_uint_32 sum = 0, lmins = mins;
@@ -1476,23 +1514,24 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
       int v;
 
 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
-      /* We temporarily increase the "minumum sum" by the factor we
+      /* We temporarily increase the "minimum sum" by the factor we
        * would reduce the sum of this filter, so that we can do the
        * early exit comparison without scaling the sum each time.
        */
       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
       {
+         int j;
          png_uint_32 lmhi, lmlo;
          lmlo = lmins & PNG_LOMASK;
          lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
 
-         for (i = 0; i < (png_uint_32)png_ptr->num_prev_filters; i++)
+         for (j = 0; j < num_p_filters; j++)
          {
-            if (png_ptr->prev_filters[i] == PNG_FILTER_VALUE_SUB)
+            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
             {
-               lmlo = (lmlo * png_ptr->inv_filter_weights[i]) >>
+               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
                   PNG_WEIGHT_SHIFT;
-               lmhi = (lmhi * png_ptr->inv_filter_weights[i]) >>
+               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
                   PNG_WEIGHT_SHIFT;
             }
          }
@@ -1530,17 +1569,18 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
       {
+         int j;
          png_uint_32 sumhi, sumlo;
          sumlo = sum & PNG_LOMASK;
          sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
 
-         for (i = 0; i < (png_uint_32)png_ptr->num_prev_filters; i++)
+         for (j = 0; j < num_p_filters; j++)
          {
-            if (png_ptr->prev_filters[i] == PNG_FILTER_VALUE_SUB)
+            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
             {
-               sumlo = (sumlo * png_ptr->inv_filter_weights[i]) >>
+               sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >>
                   PNG_WEIGHT_SHIFT;
-               sumhi = (sumhi * png_ptr->inv_filter_weights[i]) >>
+               sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >>
                   PNG_WEIGHT_SHIFT;
             }
          }
@@ -1565,27 +1605,43 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
    }
 
    /* up filter */
-   if (png_ptr->do_filter & PNG_FILTER_UP)
+   if (filter_to_do == PNG_FILTER_UP)
+   {
+      png_bytep rp, dp, pp;
+      png_uint_32 i;
+
+      for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
+           pp = prev_row + 1; i < row_bytes;
+           i++, rp++, pp++, dp++)
+      {
+         *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
+      }
+      best_row = png_ptr->up_row;
+   }
+
+   else if (filter_to_do & PNG_FILTER_UP)
    {
       png_bytep rp, dp, pp;
       png_uint_32 sum = 0, lmins = mins;
       png_uint_32 i;
       int v;
 
+
 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
       {
+         int j;
          png_uint_32 lmhi, lmlo;
          lmlo = lmins & PNG_LOMASK;
          lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
 
-         for (i = 0; i < (png_uint_32)png_ptr->num_prev_filters; i++)
+         for (j = 0; j < num_p_filters; j++)
          {
-            if (png_ptr->prev_filters[i] == PNG_FILTER_VALUE_UP)
+            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
             {
-               lmlo = (lmlo * png_ptr->inv_filter_weights[i]) >>
+               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
                   PNG_WEIGHT_SHIFT;
-               lmhi = (lmhi * png_ptr->inv_filter_weights[i]) >>
+               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
                   PNG_WEIGHT_SHIFT;
             }
          }
@@ -1603,10 +1659,9 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
 #endif
 
       for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
-           pp = prev_row + 1; i < row_info->rowbytes;
-           i++, rp++, pp++, dp++)
+           pp = prev_row + 1; i < row_bytes; i++)
       {
-         v = *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
+         v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
 
          sum += (v < 128) ? v : 256 - v;
 
@@ -1617,17 +1672,18 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
       {
+         int j;
          png_uint_32 sumhi, sumlo;
          sumlo = sum & PNG_LOMASK;
          sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
 
-         for (i = 0; i < (png_uint_32)png_ptr->num_prev_filters; i++)
+         for (j = 0; j < num_p_filters; j++)
          {
-            if (png_ptr->prev_filters[i] == PNG_FILTER_UP)
+            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
             {
-               sumlo = (sumlo * png_ptr->filter_weights[i]) >>
+               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
                   PNG_WEIGHT_SHIFT;
-               sumhi = (sumhi * png_ptr->filter_weights[i]) >>
+               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
                   PNG_WEIGHT_SHIFT;
             }
          }
@@ -1652,7 +1708,24 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
    }
 
    /* avg filter */
-   if (png_ptr->do_filter & PNG_FILTER_AVG)
+   if (filter_to_do == PNG_FILTER_AVG)
+   {
+      png_bytep rp, dp, pp, lp;
+      png_uint_32 i;
+      for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
+           pp = prev_row + 1; i < bpp; i++)
+      {
+         *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
+      }
+      for (lp = row_buf + 1; i < row_bytes; i++)
+      {
+         *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2))
+                 & 0xff);
+      }
+      best_row = png_ptr->avg_row;
+   }
+
+   else if (filter_to_do & PNG_FILTER_AVG)
    {
       png_bytep rp, dp, pp, lp;
       png_uint_32 sum = 0, lmins = mins;
@@ -1662,17 +1735,18 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
       {
+         int j;
          png_uint_32 lmhi, lmlo;
          lmlo = lmins & PNG_LOMASK;
          lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
 
-         for (i = 0; i < (png_uint_32)png_ptr->num_prev_filters; i++)
+         for (j = 0; j < num_p_filters; j++)
          {
-            if (png_ptr->prev_filters[i] == PNG_FILTER_VALUE_AVG)
+            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG)
             {
-               lmlo = (lmlo * png_ptr->inv_filter_weights[i]) >>
+               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
                   PNG_WEIGHT_SHIFT;
-               lmhi = (lmhi * png_ptr->inv_filter_weights[i]) >>
+               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
                   PNG_WEIGHT_SHIFT;
             }
          }
@@ -1690,16 +1764,16 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
 #endif
 
       for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
-           pp = prev_row + 1; i < bpp; i++, rp++, pp++, dp++)
+           pp = prev_row + 1; i < bpp; i++)
       {
-         v = *dp = (png_byte)(((int)*rp - ((int)*pp / 2)) & 0xff);
+         v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
 
          sum += (v < 128) ? v : 256 - v;
       }
-      for (lp = row_buf + 1; i < row_info->rowbytes;
-           i++, rp++, pp++, lp++, dp++)
+      for (lp = row_buf + 1; i < row_bytes; i++)
       {
-         v = *dp = (png_byte)(((int)*rp - (((int)*pp + (int)*lp) / 2)) & 0xff);
+         v = *dp++ =
+          (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff);
 
          sum += (v < 128) ? v : 256 - v;
 
@@ -1710,17 +1784,18 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
       {
+         int j;
          png_uint_32 sumhi, sumlo;
          sumlo = sum & PNG_LOMASK;
          sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
 
-         for (i = 0; i < png_ptr->num_prev_filters; i++)
+         for (j = 0; j < num_p_filters; j++)
          {
-            if (png_ptr->prev_filters[i] == PNG_FILTER_NONE)
+            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
             {
-               sumlo = (sumlo * png_ptr->filter_weights[i]) >>
+               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
                   PNG_WEIGHT_SHIFT;
-               sumhi = (sumhi * png_ptr->filter_weights[i]) >>
+               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
                   PNG_WEIGHT_SHIFT;
             }
          }
@@ -1745,7 +1820,45 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
    }
 
    /* Paeth filter */
-   if (png_ptr->do_filter & PNG_FILTER_PAETH)
+   if (filter_to_do == PNG_FILTER_PAETH)
+   {
+      png_bytep rp, dp, pp, cp, lp;
+      png_uint_32 i;
+      for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
+           pp = prev_row + 1; i < bpp; i++)
+      {
+         *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
+      }
+
+      for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
+      {
+         int a, b, c, pa, pb, pc, p;
+
+         b = *pp++;
+         c = *cp++;
+         a = *lp++;
+
+         p = b - c;
+         pc = a - c;
+
+#ifdef PNG_USE_ABS
+         pa = abs(p);
+         pb = abs(pc);
+         pc = abs(p + pc);
+#else
+         pa = p < 0 ? -p : p;
+         pb = pc < 0 ? -pc : pc;
+         pc = (p + pc) < 0 ? -(p + pc) : p + pc;
+#endif
+
+         p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
+
+         *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
+      }
+      best_row = png_ptr->paeth_row;
+   }
+
+   else if (filter_to_do & PNG_FILTER_PAETH)
    {
       png_bytep rp, dp, pp, cp, lp;
       png_uint_32 sum = 0, lmins = mins;
@@ -1755,17 +1868,18 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
       {
+         int j;
          png_uint_32 lmhi, lmlo;
          lmlo = lmins & PNG_LOMASK;
          lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
 
-         for (i = 0; i < png_ptr->num_prev_filters; i++)
+         for (j = 0; j < num_p_filters; j++)
          {
-            if (png_ptr->prev_filters[i] == PNG_FILTER_VALUE_PAETH)
+            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
             {
-               lmlo = (lmlo * png_ptr->inv_filter_weights[i]) >>
+               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
                   PNG_WEIGHT_SHIFT;
-               lmhi = (lmhi * png_ptr->inv_filter_weights[i]) >>
+               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
                   PNG_WEIGHT_SHIFT;
             }
          }
@@ -1783,34 +1897,48 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
 #endif
 
       for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
-           pp = prev_row + 1; (unsigned)i < bpp; i++, rp++, pp++, dp++)
+           pp = prev_row + 1; i < bpp; i++)
       {
-         v = *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
+         v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
 
          sum += (v < 128) ? v : 256 - v;
       }
-      for (lp = row_buf + 1, cp = prev_row + 1; i < row_info->rowbytes;
-           i++, rp++, pp++, lp++, dp++, cp++)
+
+      for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
       {
          int a, b, c, pa, pb, pc, p;
 
-         b = *pp;
-         c = *cp;
-         a = *lp;
-
+         b = *pp++;
+         c = *cp++;
+         a = *lp++;
+
+#ifndef PNG_SLOW_PAETH
+         p = b - c;
+         pc = a - c;
+#ifdef PNG_USE_ABS
+         pa = abs(p);
+         pb = abs(pc);
+         pc = abs(p + pc);
+#else
+         pa = p < 0 ? -p : p;
+         pb = pc < 0 ? -pc : pc;
+         pc = (p + pc) < 0 ? -(p + pc) : p + pc;
+#endif
+         p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
+#else /* PNG_SLOW_PAETH */
          p = a + b - c;
          pa = abs(p - a);
          pb = abs(p - b);
          pc = abs(p - c);
-
          if (pa <= pb && pa <= pc)
             p = a;
          else if (pb <= pc)
             p = b;
          else
             p = c;
+#endif /* PNG_SLOW_PAETH */
 
-         v = *dp = (png_byte)(((int)*rp - p) & 0xff);
+         v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
 
          sum += (v < 128) ? v : 256 - v;
 
@@ -1821,17 +1949,18 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
       {
+         int j;
          png_uint_32 sumhi, sumlo;
          sumlo = sum & PNG_LOMASK;
          sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
 
-         for (i = 0; i < png_ptr->num_prev_filters; i++)
+         for (j = 0; j < num_p_filters; j++)
          {
-            if (png_ptr->prev_filters[i] == PNG_FILTER_PAETH)
+            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
             {
-               sumlo = (sumlo * png_ptr->filter_weights[i]) >>
+               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
                   PNG_WEIGHT_SHIFT;
-               sumhi = (sumhi * png_ptr->filter_weights[i]) >>
+               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
                   PNG_WEIGHT_SHIFT;
             }
          }
@@ -1855,19 +1984,19 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
    }
 
    /* Do the actual writing of the filtered row data from the chosen filter. */
+
    png_write_filtered_row(png_ptr, best_row);
 
 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
    /* Save the type of filter we picked this time for future calculations */
    if (png_ptr->num_prev_filters > 0)
    {
-      int i;
-
-      for (i = 1; i < (int)png_ptr->num_prev_filters; i++)
+      int j;
+      for (j = 1; j < num_p_filters; j++)
       {
-         png_ptr->prev_filters[i] = png_ptr->prev_filters[i - 1];
+         png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1];
       }
-      png_ptr->prev_filters[i] = best_row[0];
+      png_ptr->prev_filters[j] = best_row[0];
    }
 #endif
 }