[devel]
  Fixed point APIs are now supported throughout (no missing APIs).
  Internal fixed point arithmetic support exists for all internal floating
    point operations.
  sCAL validates the floating point strings it is passed.
  Safe, albeit rudimentary, Watcom support is provided by PNG_API_RULE==2
  Two new APIs exist to get the number of passes without turning on the
    PNG_INTERLACE transform and to get the number of rows in the current
    pass.
  A new test program, pngvalid.c, validates the gamma code.
  Errors in the 16 bit gamma correction (overflows) have been corrected.
  cHRM chunk testing is done consistently (previously the floating point
    API bypassed it, because the test really didn't work on FP, now the test
    is performed on the actual values to be stored in the PNG file so it
    works in the FP case too.)
  Most floating point APIs now simply call the fixed point APIs after
    converting the values to the fixed point form used in the PNG file.
  The standard headers no longer include zlib.h, which is currently only
    required for pngstruct.h and can therefore be internal.
  (Patches by John Bowler)
diff --git a/ANNOUNCE b/ANNOUNCE
index 875d58e..dc5d535 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,5 +1,5 @@
 
-Libpng 1.5.0beta36 - July 24, 2010
+Libpng 1.5.0beta36 - July 29, 2010
 
 This is not intended to be a public release.  It will be replaced
 within a few weeks by a public version or by another test version.
@@ -226,7 +226,7 @@
     offset of the png_ptr->rowbuf pointer into png_ptr->big_row_buf.
   Added more blank lines for readability.
 
-version 1.5.0beta25 [July 24, 2010]
+version 1.5.0beta25 [July 29, 2010]
   In pngpread.c: png_push_have_row() add check for new_row > height
   Removed the now-redundant check for out-of-bounds new_row from example.c
 
@@ -287,7 +287,27 @@
   Moved the definition of png_snprintf() outside of the enclosing
     #ifdef blocks in pngconf.h
 
-version 1.5.0beta36 [July 24, 2010]
+version 1.5.0beta36 [July 29, 2010]
+  Patches by John Bowler:
+  Fixed point APIs are now supported throughout (no missing APIs).
+  Internal fixed point arithmetic support exists for all internal floating
+    point operations.
+  sCAL validates the floating point strings it is passed.
+  Safe, albeit rudimentary, Watcom support is provided by PNG_API_RULE==2
+  Two new APIs exist to get the number of passes without turning on the
+    PNG_INTERLACE transform and to get the number of rows in the current
+    pass.
+  A new test program, pngvalid.c, validates the gamma code.
+  Errors in the 16 bit gamma correction (overflows) have been corrected.
+  Gamma handling arithmetic is in a new file, pngarith.c
+  cHRM chunk testing is done consistently (previously the floating point
+    API bypassed it, because the test really didn't work on FP, now the test
+    is performed on the actual values to be stored in the PNG file so it
+    works in the FP case too.)
+  Most floating point APIs now simply call the fixed point APIs after
+    converting the values to the fixed point form used in the PNG file.
+  The standard headers no longer include zlib.h, which is currently only
+    required for pngstruct.h and can therefore be internal.
 
 Send comments/corrections/commendations to png-mng-implement at lists.sf.net:
 (subscription required; visit
diff --git a/CHANGES b/CHANGES
index 9f86b8b..6a0c01b 100644
--- a/CHANGES
+++ b/CHANGES
@@ -2769,7 +2769,27 @@
   Moved the definition of png_snprintf() outside of the enclosing
     #ifdef blocks in pngconf.h
 
-version 1.5.0beta36 [July 24, 2010]
+version 1.5.0beta36 [July 29, 2010]
+  Patches by John Bowler:
+  Fixed point APIs are now supported throughout (no missing APIs).
+  Internal fixed point arithmetic support exists for all internal floating
+    point operations.
+  sCAL validates the floating point strings it is passed.
+  Safe, albeit rudimentary, Watcom support is provided by PNG_API_RULE==2
+  Two new APIs exist to get the number of passes without turning on the
+    PNG_INTERLACE transform and to get the number of rows in the current
+    pass.
+  A new test program, pngvalid.c, validates the gamma code.
+  Errors in the 16 bit gamma correction (overflows) have been corrected.
+  Gamma handling arithmetic is in a new file, pngarith.c
+  cHRM chunk testing is done consistently (previously the floating point
+    API bypassed it, because the test really didn't work on FP, now the test
+    is performed on the actual values to be stored in the PNG file so it
+    works in the FP case too.)
+  Most floating point APIs now simply call the fixed point APIs after
+    converting the values to the fixed point form used in the PNG file.
+  The standard headers no longer include zlib.h, which is currently only
+    required for pngstruct.h and can therefore be internal.
 
 Send comments/corrections/commendations to png-mng-implement at lists.sf.net
 (subscription required; visit
diff --git a/Makefile.am b/Makefile.am
index 61f3521..bfdb970 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -8,10 +8,12 @@
 AUTOMAKE_OPTIONS = foreign color-tests
 
 # test programs - run on make check, make distcheck
-check_PROGRAMS= pngtest
+check_PROGRAMS= pngtest pngvalid
 pngtest_SOURCES = pngtest.c
 pngtest_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
-TESTS = test-pngtest.sh
+pngvalid_SOURCES = pngvalid.c
+pngvalid_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
+TESTS = test-pngtest.sh pngvalid
 TESTS_ENVIRONMENT= srcdir=$(srcdir) 
 
 # man pages
@@ -25,11 +27,10 @@
 # rules to build libpng, only build the old library on request
 lib_LTLIBRARIES=libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
 # EXTRA_LTLIBRARIES= libpng.la
-libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = png.c pngset.c pngget.c pngrutil.c \
-	pngtrans.c pngwutil.c \
-	pngread.c pngrio.c pngwio.c pngwrite.c pngrtran.c \
-	pngwtran.c pngmem.c pngerror.c pngpread.c \
-	png.h pngconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h
+libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = png.c pngarith.c pngerror.c\
+	pngget.c pngmem.c pngpread.c pngread.c pngrio.c pngrtran.c pngrutil.c\
+	pngset.c pngtrans.c pngwio.c pngwrite.c pngwtran.c pngwutil.c\
+	png.h pngconf.h pngdebug.h pnginfo.h pngpriv.h pngstruct.h
 
 nodist_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = pnglibconf.h
 
diff --git a/Makefile.in b/Makefile.in
index ec0442f..a08fb73 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -40,7 +40,8 @@
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
-check_PROGRAMS = pngtest$(EXEEXT)
+check_PROGRAMS = pngtest$(EXEEXT) pngvalid$(EXEEXT)
+TESTS = test-pngtest.sh pngvalid$(EXEEXT)
 @HAVE_LD_VERSION_SCRIPT_TRUE@am__append_1 = -Wl,--version-script=libpng.vers
 @HAVE_LD_VERSION_SCRIPT_FALSE@am__append_2 = -export-symbols libpng.sym
 subdir = .
@@ -89,20 +90,21 @@
 libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LIBADD =
 am_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS =  \
 	libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-png.lo \
-	libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngset.lo \
+	libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngarith.lo \
+	libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngerror.lo \
 	libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngget.lo \
-	libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrutil.lo \
-	libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngtrans.lo \
-	libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwutil.lo \
+	libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngmem.lo \
+	libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngpread.lo \
 	libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngread.lo \
 	libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrio.lo \
+	libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrtran.lo \
+	libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrutil.lo \
+	libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngset.lo \
+	libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngtrans.lo \
 	libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwio.lo \
 	libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwrite.lo \
-	libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrtran.lo \
 	libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwtran.lo \
-	libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngmem.lo \
-	libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngerror.lo \
-	libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngpread.lo
+	libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwutil.lo
 nodist_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS =
 libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS =  \
 	$(am_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS) \
@@ -115,6 +117,9 @@
 am_pngtest_OBJECTS = pngtest.$(OBJEXT)
 pngtest_OBJECTS = $(am_pngtest_OBJECTS)
 pngtest_DEPENDENCIES = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
+am_pngvalid_OBJECTS = pngvalid.$(OBJEXT)
+pngvalid_OBJECTS = $(am_pngvalid_OBJECTS)
+pngvalid_DEPENDENCIES = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
 SCRIPTS = $(bin_SCRIPTS)
 DEFAULT_INCLUDES = -I.@am__isrc@
 depcomp = $(SHELL) $(top_srcdir)/depcomp
@@ -131,9 +136,9 @@
 	$(LDFLAGS) -o $@
 SOURCES = $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES) \
 	$(nodist_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES) \
-	$(pngtest_SOURCES)
+	$(pngtest_SOURCES) $(pngvalid_SOURCES)
 DIST_SOURCES = $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES) \
-	$(pngtest_SOURCES)
+	$(pngtest_SOURCES) $(pngvalid_SOURCES)
 man3dir = $(mandir)/man3
 man5dir = $(mandir)/man5
 NROFF = nroff
@@ -305,7 +310,8 @@
 AUTOMAKE_OPTIONS = foreign color-tests
 pngtest_SOURCES = pngtest.c
 pngtest_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
-TESTS = test-pngtest.sh
+pngvalid_SOURCES = pngvalid.c
+pngvalid_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
 TESTS_ENVIRONMENT = srcdir=$(srcdir) 
 
 # man pages
@@ -316,11 +322,10 @@
 # rules to build libpng, only build the old library on request
 lib_LTLIBRARIES = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
 # EXTRA_LTLIBRARIES= libpng.la
-libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = png.c pngset.c pngget.c pngrutil.c \
-	pngtrans.c pngwutil.c \
-	pngread.c pngrio.c pngwio.c pngwrite.c pngrtran.c \
-	pngwtran.c pngmem.c pngerror.c pngpread.c \
-	png.h pngconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h
+libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = png.c pngarith.c pngerror.c\
+	pngget.c pngmem.c pngpread.c pngread.c pngrio.c pngrtran.c pngrutil.c\
+	pngset.c pngtrans.c pngwio.c pngwrite.c pngwtran.c pngwutil.c\
+	png.h pngconf.h pngdebug.h pnginfo.h pngpriv.h pngstruct.h
 
 nodist_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = pnglibconf.h
 libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS = @LIBPNG_DEFINES@
@@ -461,6 +466,9 @@
 pngtest$(EXEEXT): $(pngtest_OBJECTS) $(pngtest_DEPENDENCIES) 
 	@rm -f pngtest$(EXEEXT)
 	$(LINK) $(pngtest_OBJECTS) $(pngtest_LDADD) $(LIBS)
+pngvalid$(EXEEXT): $(pngvalid_OBJECTS) $(pngvalid_DEPENDENCIES) 
+	@rm -f pngvalid$(EXEEXT)
+	$(LINK) $(pngvalid_OBJECTS) $(pngvalid_LDADD) $(LIBS)
 install-binSCRIPTS: $(bin_SCRIPTS)
 	@$(NORMAL_INSTALL)
 	test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
@@ -503,6 +511,7 @@
 	-rm -f *.tab.c
 
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-png.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngarith.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngerror.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngget.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngmem.Plo@am__quote@
@@ -518,6 +527,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwtran.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwutil.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pngtest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pngvalid.Po@am__quote@
 
 .c.o:
 @am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@@ -547,12 +557,19 @@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-png.lo `test -f 'png.c' || echo '$(srcdir)/'`png.c
 
-libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngset.lo: pngset.c
-@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngset.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngset.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngset.lo `test -f 'pngset.c' || echo '$(srcdir)/'`pngset.c
-@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngset.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngset.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='pngset.c' object='libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngset.lo' libtool=yes @AMDEPBACKSLASH@
+libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngarith.lo: pngarith.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngarith.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngarith.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngarith.lo `test -f 'pngarith.c' || echo '$(srcdir)/'`pngarith.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngarith.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngarith.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='pngarith.c' object='libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngarith.lo' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngset.lo `test -f 'pngset.c' || echo '$(srcdir)/'`pngset.c
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngarith.lo `test -f 'pngarith.c' || echo '$(srcdir)/'`pngarith.c
+
+libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngerror.lo: pngerror.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngerror.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngerror.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngerror.lo `test -f 'pngerror.c' || echo '$(srcdir)/'`pngerror.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngerror.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngerror.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='pngerror.c' object='libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngerror.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngerror.lo `test -f 'pngerror.c' || echo '$(srcdir)/'`pngerror.c
 
 libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngget.lo: pngget.c
 @am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngget.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngget.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngget.lo `test -f 'pngget.c' || echo '$(srcdir)/'`pngget.c
@@ -561,26 +578,19 @@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngget.lo `test -f 'pngget.c' || echo '$(srcdir)/'`pngget.c
 
-libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrutil.lo: pngrutil.c
-@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrutil.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrutil.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrutil.lo `test -f 'pngrutil.c' || echo '$(srcdir)/'`pngrutil.c
-@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrutil.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrutil.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='pngrutil.c' object='libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrutil.lo' libtool=yes @AMDEPBACKSLASH@
+libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngmem.lo: pngmem.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngmem.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngmem.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngmem.lo `test -f 'pngmem.c' || echo '$(srcdir)/'`pngmem.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngmem.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngmem.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='pngmem.c' object='libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngmem.lo' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrutil.lo `test -f 'pngrutil.c' || echo '$(srcdir)/'`pngrutil.c
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngmem.lo `test -f 'pngmem.c' || echo '$(srcdir)/'`pngmem.c
 
-libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngtrans.lo: pngtrans.c
-@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngtrans.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngtrans.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngtrans.lo `test -f 'pngtrans.c' || echo '$(srcdir)/'`pngtrans.c
-@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngtrans.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngtrans.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='pngtrans.c' object='libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngtrans.lo' libtool=yes @AMDEPBACKSLASH@
+libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngpread.lo: pngpread.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngpread.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngpread.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngpread.lo `test -f 'pngpread.c' || echo '$(srcdir)/'`pngpread.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngpread.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngpread.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='pngpread.c' object='libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngpread.lo' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngtrans.lo `test -f 'pngtrans.c' || echo '$(srcdir)/'`pngtrans.c
-
-libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwutil.lo: pngwutil.c
-@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwutil.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwutil.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwutil.lo `test -f 'pngwutil.c' || echo '$(srcdir)/'`pngwutil.c
-@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwutil.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwutil.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='pngwutil.c' object='libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwutil.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwutil.lo `test -f 'pngwutil.c' || echo '$(srcdir)/'`pngwutil.c
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngpread.lo `test -f 'pngpread.c' || echo '$(srcdir)/'`pngpread.c
 
 libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngread.lo: pngread.c
 @am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngread.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngread.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngread.lo `test -f 'pngread.c' || echo '$(srcdir)/'`pngread.c
@@ -596,6 +606,34 @@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrio.lo `test -f 'pngrio.c' || echo '$(srcdir)/'`pngrio.c
 
+libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrtran.lo: pngrtran.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrtran.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrtran.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrtran.lo `test -f 'pngrtran.c' || echo '$(srcdir)/'`pngrtran.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrtran.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrtran.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='pngrtran.c' object='libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrtran.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrtran.lo `test -f 'pngrtran.c' || echo '$(srcdir)/'`pngrtran.c
+
+libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrutil.lo: pngrutil.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrutil.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrutil.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrutil.lo `test -f 'pngrutil.c' || echo '$(srcdir)/'`pngrutil.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrutil.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrutil.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='pngrutil.c' object='libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrutil.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrutil.lo `test -f 'pngrutil.c' || echo '$(srcdir)/'`pngrutil.c
+
+libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngset.lo: pngset.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngset.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngset.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngset.lo `test -f 'pngset.c' || echo '$(srcdir)/'`pngset.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngset.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngset.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='pngset.c' object='libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngset.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngset.lo `test -f 'pngset.c' || echo '$(srcdir)/'`pngset.c
+
+libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngtrans.lo: pngtrans.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngtrans.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngtrans.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngtrans.lo `test -f 'pngtrans.c' || echo '$(srcdir)/'`pngtrans.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngtrans.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngtrans.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='pngtrans.c' object='libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngtrans.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngtrans.lo `test -f 'pngtrans.c' || echo '$(srcdir)/'`pngtrans.c
+
 libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwio.lo: pngwio.c
 @am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwio.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwio.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwio.lo `test -f 'pngwio.c' || echo '$(srcdir)/'`pngwio.c
 @am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwio.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwio.Plo
@@ -610,13 +648,6 @@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwrite.lo `test -f 'pngwrite.c' || echo '$(srcdir)/'`pngwrite.c
 
-libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrtran.lo: pngrtran.c
-@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrtran.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrtran.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrtran.lo `test -f 'pngrtran.c' || echo '$(srcdir)/'`pngrtran.c
-@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrtran.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrtran.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='pngrtran.c' object='libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrtran.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrtran.lo `test -f 'pngrtran.c' || echo '$(srcdir)/'`pngrtran.c
-
 libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwtran.lo: pngwtran.c
 @am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwtran.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwtran.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwtran.lo `test -f 'pngwtran.c' || echo '$(srcdir)/'`pngwtran.c
 @am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwtran.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwtran.Plo
@@ -624,26 +655,12 @@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwtran.lo `test -f 'pngwtran.c' || echo '$(srcdir)/'`pngwtran.c
 
-libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngmem.lo: pngmem.c
-@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngmem.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngmem.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngmem.lo `test -f 'pngmem.c' || echo '$(srcdir)/'`pngmem.c
-@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngmem.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngmem.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='pngmem.c' object='libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngmem.lo' libtool=yes @AMDEPBACKSLASH@
+libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwutil.lo: pngwutil.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwutil.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwutil.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwutil.lo `test -f 'pngwutil.c' || echo '$(srcdir)/'`pngwutil.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwutil.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwutil.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='pngwutil.c' object='libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwutil.lo' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngmem.lo `test -f 'pngmem.c' || echo '$(srcdir)/'`pngmem.c
-
-libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngerror.lo: pngerror.c
-@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngerror.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngerror.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngerror.lo `test -f 'pngerror.c' || echo '$(srcdir)/'`pngerror.c
-@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngerror.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngerror.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='pngerror.c' object='libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngerror.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngerror.lo `test -f 'pngerror.c' || echo '$(srcdir)/'`pngerror.c
-
-libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngpread.lo: pngpread.c
-@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngpread.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngpread.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngpread.lo `test -f 'pngpread.c' || echo '$(srcdir)/'`pngpread.c
-@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngpread.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngpread.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='pngpread.c' object='libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngpread.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngpread.lo `test -f 'pngpread.c' || echo '$(srcdir)/'`pngpread.c
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwutil.lo `test -f 'pngwutil.c' || echo '$(srcdir)/'`pngwutil.c
 
 mostlyclean-libtool:
 	-rm -f *.lo
@@ -983,7 +1000,8 @@
 	  top_distdir="$(top_distdir)" distdir="$(distdir)" \
 	  dist-hook
 	-test -n "$(am__skip_mode_fix)" \
-	|| find "$(distdir)" -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
+	|| find "$(distdir)" -type d ! -perm -755 \
+		-exec chmod u+rwx,go+rx {} \; -o \
 	  ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
 	  ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
 	  ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
@@ -1027,17 +1045,17 @@
 distcheck: dist
 	case '$(DIST_ARCHIVES)' in \
 	*.tar.gz*) \
-	  GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
+	  GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
 	*.tar.bz2*) \
-	  bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
+	  bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
 	*.tar.lzma*) \
-	  unlzma -c $(distdir).tar.lzma | $(am__untar) ;;\
+	  lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\
 	*.tar.xz*) \
 	  xz -dc $(distdir).tar.xz | $(am__untar) ;;\
 	*.tar.Z*) \
 	  uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
 	*.shar.gz*) \
-	  GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
+	  GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\
 	*.zip*) \
 	  unzip $(distdir).zip ;;\
 	esac
diff --git a/contrib/gregbook/readpng2.c b/contrib/gregbook/readpng2.c
index 4644b09..2414f90 100644
--- a/contrib/gregbook/readpng2.c
+++ b/contrib/gregbook/readpng2.c
@@ -55,8 +55,10 @@
 
 
 #include <stdlib.h>     /* for exit() prototype */
+#include <setjmp.h>
 
-#include "png.h"        /* libpng header; includes zlib.h and setjmp.h */
+#include <zlib.h>
+#include "png.h"        /* libpng header from the local directory */
 #include "readpng2.h"   /* typedefs, common macros, public prototypes */
 
 
@@ -216,7 +218,11 @@
     mainprog_info  *mainprog_ptr;
     int  color_type, bit_depth;
     png_uint_32 width, height;
+#ifdef PNG_FLOATING_POINT_SUPPORTED
     double  gamma;
+#else
+    png_fixed_point gamma;
+#endif
 
 
     /* setjmp() doesn't make sense here, because we'd either have to exit(),
@@ -327,11 +333,19 @@
      * "gamma" value for the entire display system, i.e., the product of
      * LUT_exponent and CRT_exponent. */
 
+#ifdef PNG_FLOATING_POINT_SUPPORTED
     if (png_get_gAMA(png_ptr, info_ptr, &gamma))
         png_set_gamma(png_ptr, mainprog_ptr->display_exponent, gamma);
     else
         png_set_gamma(png_ptr, mainprog_ptr->display_exponent, 0.45455);
-
+#else
+    if (png_get_gAMA_fixed(png_ptr, info_ptr, &gamma))
+        png_set_gamma_fixed(png_ptr,
+	    (png_fixed_point)(100000*mainprog_ptr->display_exponent+.5), gamma);
+    else
+        png_set_gamma_fixed(png_ptr,
+	    (png_fixed_point)(100000*mainprog_ptr->display_exponent+.5), 45455);
+#endif
 
     /* we'll let libpng expand interlaced images, too */
 
diff --git a/contrib/gregbook/rpng2-x.c b/contrib/gregbook/rpng2-x.c
index 2c24734..80d4c45 100644
--- a/contrib/gregbook/rpng2-x.c
+++ b/contrib/gregbook/rpng2-x.c
@@ -485,9 +485,6 @@
           "\nPress Q, Esc or mouse button 1 (within image window, after image\n"
           "is displayed) to quit.\n"
           "\n", PROGNAME,
-#if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__))
-          (int)strlen(PROGNAME), " ",
-#endif
           (int)strlen(PROGNAME), " ", default_display_exponent, num_bgpat-1);
         exit(1);
     }
diff --git a/contrib/pngminim/preader/makefile b/contrib/pngminim/preader/makefile
index 282709e..44bab95 100644
--- a/contrib/pngminim/preader/makefile
+++ b/contrib/pngminim/preader/makefile
@@ -64,7 +64,7 @@
 	 zutil$(O)
 
 # libpng
-PNGSRCS=png$(C) pngerror$(C) pngget$(C) pngmem$(C) \
+PNGSRCS=png$(C) pngarith$(C) pngerror$(C) pngget$(C) pngmem$(C) \
 	pngpread$(C) pngread$(C) pngrio$(C) pngrtran$(C) pngrutil$(C) \
 	pngset$(C) pngtrans$(C)
 
@@ -80,7 +80,7 @@
 # Headers the PNG library uses
 PNGHDRS=$(PNGH) $(PNGCONF) pngusr.h
 
-PNGOBJS=png$(O) pngerror$(O) pngget$(O) pngmem$(O) \
+PNGOBJS=png$(O) pngarith$(O) pngerror$(O) pngget$(O) pngmem$(O) \
 	pngpread$(O) pngread$(O) pngrio$(O) pngrtran$(O) pngrutil$(O) \
 	pngset$(O) pngtrans$(O)
 
diff --git a/contrib/pngminim/preader/pngusr.dfa b/contrib/pngminim/preader/pngusr.dfa
index 27b2b09..31e83a5 100644
--- a/contrib/pngminim/preader/pngusr.dfa
+++ b/contrib/pngminim/preader/pngusr.dfa
@@ -12,9 +12,14 @@
 # Just switch on the progressive read code
 option PROGRESSIVE_READ on
 
-# You must choose fixed or floating point arithmetic:
-option FLOATING_POINT on
-# option FIXED_POINT on
+# You may choose fixed or floating point APIs:
+# option FLOATING_POINT on
+option FIXED_POINT on
+# You must chose the internal fixed point implementation or to
+# use the system floating point.  The latter is considerably
+# smaller (by about 1kbyte on an x86 system):
+option FLOATING_ARITHMETIC on
+# option FLOATING_ARITHMETIC off
 
 # Your program will probably need other options.  The example
 # program here, rpng2-x, requires the following.  Take a look
diff --git a/example.c b/example.c
index ec63290..bd229a6 100644
--- a/example.c
+++ b/example.c
@@ -2,7 +2,7 @@
 #if 0 /* in case someone actually tries to compile this */
 
 /* example.c - an example of using libpng
- * Last changed in libpng 1.5.0 [July 24, 2010]
+ * Last changed in libpng 1.5.0 [July 29, 2010]
  * This file has been placed in the public domain by the authors.
  * Maintained 1998-2010 Glenn Randers-Pehrson
  * Maintained 1996, 1997 Andreas Dilger)
diff --git a/png.c b/png.c
index 66c6907..8993842 100644
--- a/png.c
+++ b/png.c
@@ -1,7 +1,7 @@
 
 /* png.c - location for general purpose libpng functions
  *
- * Last changed in libpng 1.5.0 [July 24, 2010]
+ * Last changed in libpng 1.5.0 [July 29, 2010]
  * Copyright (c) 1998-2010 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -560,13 +560,13 @@
 #else
 #  ifdef __STDC__
    return ((png_charp) PNG_STRING_NEWLINE \
-     "libpng version 1.5.0beta36 - July 24, 2010" PNG_STRING_NEWLINE \
+     "libpng version 1.5.0beta36 - July 29, 2010" PNG_STRING_NEWLINE \
      "Copyright (c) 1998-2010 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \
      "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
      "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
      PNG_STRING_NEWLINE);
 #  else
-      return ((png_charp) "libpng version 1.5.0beta36 - July 24, 2010\
+      return ((png_charp) "libpng version 1.5.0beta36 - July 29, 2010\
       Copyright (c) 1998-2010 Glenn Randers-Pehrson\
       Copyright (c) 1996-1997 Andreas Dilger\
       Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.");
@@ -616,7 +616,7 @@
 #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
 #  ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
 int PNGAPI
-png_handle_as_unknown(png_structp png_ptr, png_bytep chunk_name)
+png_handle_as_unknown(png_structp png_ptr, png_const_bytep chunk_name)
 {
    /* Check chunk_name and return "keep" value if it's on the list, else 0 */
    int i;
@@ -670,48 +670,7 @@
 #  endif /* PNG_SIZE_T */
 
 /* Added at libpng version 1.2.34 and 1.4.0 (moved from pngset.c) */
-#  ifdef PNG_cHRM_SUPPORTED
-#    ifdef PNG_CHECK_cHRM_SUPPORTED
-
-/*
- *    Multiply two 32-bit numbers, V1 and V2, using 32-bit
- *    arithmetic, to produce a 64 bit result in the HI/LO words.
- *
- *                  A B
- *                x C D
- *               ------
- *              AD || BD
- *        AC || CB || 0
- *
- *    where A and B are the high and low 16-bit words of V1,
- *    C and D are the 16-bit words of V2, AD is the product of
- *    A and D, and X || Y is (X << 16) + Y.
-*/
-
-void /* PRIVATE */
-png_64bit_product (long v1, long v2, unsigned long *hi_product,
-   unsigned long *lo_product)
-{
-   int a, b, c, d;
-   long lo, hi, x, y;
-
-   a = (v1 >> 16) & 0xffff;
-   b = v1 & 0xffff;
-   c = (v2 >> 16) & 0xffff;
-   d = v2 & 0xffff;
-
-   lo = b * d;                   /* BD */
-   x = a * d + c * b;            /* AD + CB */
-   y = ((lo >> 16) & 0xffff) + x;
-
-   lo = (lo & 0xffff) | ((y & 0xffff) << 16);
-   hi = (y >> 16) & 0xffff;
-
-   hi += a * c;                  /* AC */
-
-   *hi_product = (unsigned long)hi;
-   *lo_product = (unsigned long)lo;
-}
+#  ifdef PNG_CHECK_cHRM_SUPPORTED
 
 int /* PRIVATE */
 png_check_cHRM_fixed(png_structp png_ptr,
@@ -785,8 +744,7 @@
 
    return ret;
 }
-#    endif /* PNG_CHECK_cHRM_SUPPORTED */
-#  endif /* PNG_cHRM_SUPPORTED */
+#  endif /* PNG_CHECK_cHRM_SUPPORTED */
 
 void /* PRIVATE */
 png_check_IHDR(png_structp png_ptr,
@@ -931,3 +889,1273 @@
       png_error(png_ptr, "Invalid IHDR data");
 }
 #endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
+
+#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED)
+/* ASCII to fp functions */
+/* Check an ASCII formated floating point value, see the more detailed
+ * comments in pngpriv.h
+ */
+/* The following is used internally to preserve the 'valid' flag */
+#define png_fp_add(state, flags) ((state) |= (flags))
+#define png_fp_set(state, value)\
+   ((state) = (value) | ((state) & PNG_FP_WAS_VALID))
+
+/* Internal type codes: bits above the base state! */
+#define PNG_FP_SIGN   0  /* [+-] */
+#define PNG_FP_DOT    4  /* . */
+#define PNG_FP_DIGIT  8  /* [0123456789] */
+#define PNG_FP_E     12  /* [Ee] */
+
+int /* PRIVATE */
+png_check_fp_number(png_charp string, png_size_t size, int *statep,
+   png_size_tp whereami)
+{
+   int state = *statep;
+   png_size_t i = *whereami;
+
+   while (i < size)
+   {
+      int type;
+      /* First find the type of the next character */
+      {
+	 char ch = string[i];
+	 if (ch >= 48 && ch <= 57)
+	    type = PNG_FP_DIGIT;
+	 else switch (ch)
+	 {
+	 case 43: case 45:  type = PNG_FP_SIGN;  break;
+	 case 46:           type = PNG_FP_DOT;   break;
+	 case 69: case 101: type = PNG_FP_E;     break;
+	 default:           goto PNG_FP_End;
+	 }
+      }
+
+      /* Now deal with this type according to the current
+       * state, the type is arranged to not overlap the
+       * bits of the PNG_FP_STATE.
+       */
+      switch ((state & PNG_FP_STATE) + type)
+      {
+      case PNG_FP_INTEGER + PNG_FP_SIGN:
+	 if (state & PNG_FP_SAW_ANY)
+	    goto PNG_FP_End; /* not a part of the number */
+	 png_fp_add(state, PNG_FP_SAW_SIGN);
+	 break;
+      case PNG_FP_INTEGER + PNG_FP_DOT:
+	 /* Ok as trailer, ok as lead of fraction. */
+	 if (state & PNG_FP_SAW_DOT) /* two dots */
+	    goto PNG_FP_End;
+	 else if (state & PNG_FP_SAW_DIGIT) /* trailing dot? */
+	    png_fp_add(state, PNG_FP_SAW_DOT);
+	 else
+	    png_fp_set(state, PNG_FP_FRACTION | PNG_FP_SAW_DOT);
+	 break;
+      case PNG_FP_INTEGER + PNG_FP_DIGIT:
+	 if (state & PNG_FP_SAW_DOT) /* delayed fraction */
+	    png_fp_set(state, PNG_FP_FRACTION | PNG_FP_SAW_DOT);
+	 png_fp_add(state, PNG_FP_SAW_DIGIT + PNG_FP_WAS_VALID);
+	 break;
+      case PNG_FP_INTEGER + PNG_FP_E:
+	 if ((state & PNG_FP_SAW_DIGIT) == 0)
+	    goto PNG_FP_End;
+	 png_fp_set(state, PNG_FP_EXPONENT);
+	 break;
+   /* case PNG_FP_FRACTION + PNG_FP_SIGN:
+	 goto PNG_FP_End; ** no sign in exponent */
+   /* case PNG_FP_FRACTION + PNG_FP_DOT:
+	 goto PNG_FP_End; ** Because SAW_DOT is always set */
+      case PNG_FP_FRACTION + PNG_FP_DIGIT:
+	 png_fp_add(state, PNG_FP_SAW_DIGIT + PNG_FP_WAS_VALID);
+	 break;
+      case PNG_FP_FRACTION + PNG_FP_E:
+	 /* This is correct because the trailing '.' on an
+	  * integer is handled above - so we can only get here
+	  * with the sequence ".E" (with no preceding digits).
+	  */
+	 if ((state & PNG_FP_SAW_DIGIT) == 0)
+	    goto PNG_FP_End;
+	 png_fp_set(state, PNG_FP_EXPONENT);
+	 break;
+      case PNG_FP_EXPONENT + PNG_FP_SIGN:
+	 if (state & PNG_FP_SAW_ANY)
+	    goto PNG_FP_End; /* not a part of the number */
+	 png_fp_add(state, PNG_FP_SAW_SIGN);
+	 break;
+   /* case PNG_FP_EXPONENT + PNG_FP_DOT:
+	 goto PNG_FP_End; */
+      case PNG_FP_EXPONENT + PNG_FP_DIGIT:
+	 png_fp_add(state, PNG_FP_SAW_DIGIT + PNG_FP_WAS_VALID);
+	 break;
+   /* case PNG_FP_EXPONEXT + PNG_FP_E:
+	 goto PNG_FP_End; */
+      default: goto PNG_FP_End; /* I.e. break 2 */
+      }
+
+      /* The character seems ok, continue. */
+      ++i;
+   }
+
+PNG_FP_End:
+   /* Here at the end, update the state and return the correct
+    * return code.
+    */
+   *statep = state;
+   *whereami = i;
+
+   return (state & PNG_FP_SAW_DIGIT) != 0;
+}
+
+
+/* The same but for a complete string. */
+int
+png_check_fp_string(png_charp string, png_size_t size)
+{
+   int        state=0;
+   png_size_t index=0;
+
+   return png_check_fp_number(string, size, &state, &index) &&
+      (index == size || string[index] == 0);
+}
+#endif /* pCAL or sCAL */
+
+#ifdef PNG_READ_sCAL_SUPPORTED
+#  ifdef PNG_FLOATING_POINT_SUPPORTED
+/* Utility used below - a simple accurate power of ten from an integral
+ * exponent.
+ */
+static double
+png_pow10(int power)
+{
+   int recip = 0;
+   double d = 1;
+   /* Handle negative exponent with a reciprocal at the end because
+    * 10 is exact whereas .1 is inexact in base 2
+    */
+   if (power < 0)
+      recip = 1, power = -power;
+   if (power > 0)
+   {
+      /* Decompose power bitwise. */
+      double mult = 10;
+      do
+      {
+         if (power & 1) d *= mult;
+	 mult *= mult;
+	 power >>= 1;
+      }
+      while (power > 0);
+
+      if (recip) d = 1/d;
+   }
+   /* else power is 0 and d is 1 */
+
+   return d;
+}
+
+/* Function to format a floating point value in ASCII with a given
+ * precision.
+ */
+void /* PRIVATE */
+png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
+    double fp, unsigned precision)
+{
+   /* We use standard functions from math.h, but not printf because
+    * that would require stdio.  The caller must supply a buffer of
+    * sufficient size or we will png_error.  The tests on size and
+    * the space in ascii[] consumed are indicated below.
+    */
+   if (precision < 1)
+      precision = DBL_DIG;
+
+   /* Enforce the limit of the implementation precision too. */
+   if (precision > DBL_DIG+1)
+      precision = DBL_DIG+1;
+
+   /* Basic sanity checks */
+   if (size >= precision+5) /* See the requirements below. */
+   {
+      if (fp < 0)
+      {
+         fp = -fp;
+	 *ascii++ = 45; /* '-'  PLUS 1 TOTAL 1*/
+	 --size;
+      }
+
+      if (fp >= DBL_MIN && fp <= DBL_MAX)
+      {
+	 int exp;       /* A base 10 exponent */
+	 double base;   /* 10^exp */
+
+	 /* First extract a base 10 exponent of the number,
+	  * the calculation below rounds down when converting
+	  * from base 2 to base 10 (multiply by log10(2) -
+	  * 0.3010, but 77/256 is 0.3008, so exp needs to
+	  * be increased.  Note that the arithmetic shift
+	  * performs a floor() unlike C arithmetic - using a
+	  * C multiply would break the following for negative
+	  * exponents.
+	  */
+	 (void)frexp(fp, &exp); /* exponent to base 2 */
+	 exp = (exp * 77) >> 8; /* <= exponent to base 10 */
+	 /* Avoid underflow here. */
+	 base = png_pow10(exp); /* May underflow */
+	 while (base < DBL_MIN || base < fp)
+	 {
+	    /* And this may overflow. */
+	    double test = png_pow10(exp+1);
+	    if (test <= DBL_MAX)
+	       ++exp, base = test;
+	    else
+	       break;
+	 }
+
+	 /* Normalize fp and correct exp, after this fp is in the
+	  * range [.1,1) and exp is both the exponent and the digit
+	  * *before* which the decimal point should be inserted
+	  * (starting with 0 for the first digit).  Note that this
+	  * works even if 10^exp is out of range because of the
+	  * test on DBL_MAX above.
+	  */
+	 fp /= base;
+	 while (fp >= 1) fp /= 10, ++exp;
+
+	 /* Because of the code above fp may, at this point, be
+	  * less than .1, this is ok because the code below can
+	  * handle the leading zeros this generates, so no attempt
+	  * is made to correct that here.
+	  */
+
+	 {
+	    int czero, clead, cdigits;
+	    char exponent[10];
+
+	    /* Allow up to two leading zeros - this will not lengthen
+	     * the number compared to using E-n.
+	     */
+	    if (exp < 0 && exp > -3) /* PLUS 3 TOTAL 4 */
+	    {
+	       czero = -exp; /* PLUS 2 digits: TOTAL 3 */
+	       exp = 0;      /* Dot added below before first output. */
+	    }
+	    else
+	       czero = 0;    /* No zeros to add */
+
+	    /* Generate the digit list, stripping trailing zeros and
+	     * inserting a '.' before a digit if the exponent is 0.
+	     */
+	    clead = czero; /* Count of leading zeros */
+	    cdigits = 0;   /* Count of digits in list. */
+	    do
+	    {
+	       double d;
+
+	       fp *= 10;
+	       /* Use modf here, not floor and subtract, so that
+		* the separation is done in one step.  At the end
+		* of the loop don't break the number into parts so
+		* that the final digit is rounded.
+		*/
+	       if (cdigits+czero-clead+1 < (int)precision)
+		  fp = modf(fp, &d);
+	       else
+	       {
+		  /* End of loop - round the whole number. */
+		  d = floor(fp + .5);
+
+		  if (d > 9)
+		  {
+		     /* Rounding up to 10, handle that here. */
+		     if (czero > 0)
+		     {
+		        --czero, d = 1;
+			if (cdigits == 0) --clead;
+                     }
+		     else
+		     {
+			while (cdigits > 0 && d > 9)
+			{
+			   int ch = *--ascii;
+			   if (exp != (-1))
+			      ++exp;
+			   else if (ch == 46)
+			   {
+			      ch = *--ascii, ++size;
+			      /* Advance exp to '1', so that the
+			       * decimal point happens after the
+			       * previous digit.
+			       */
+			      exp = 1;
+			   }
+
+			   --cdigits;
+			   d = ch - 47;  /* I.e. 1+(ch-48) */
+			}
+
+			/* Did we reach the beginning? If so adjust the
+			 * exponent but take into account the leading
+			 * decimal point.
+			 */
+			if (d > 9)  /* cdigits == 0 */
+			{
+			   if (exp == (-1))
+			   {
+			      /* Leading decimal point (plus zeros?), if
+			       * we lose the decimal point here it must
+			       * be reentered below.
+			       */
+			      int ch = *--ascii;
+			      if (ch == 46)
+			         ++size, exp = 1;
+			      /* Else lost a leading zero, so 'exp' is
+			       * still ok at (-1)
+			       */
+			   }
+			   else
+			      ++exp;
+
+			   /* In all cases we output a '1' */
+			   d = 1;
+			}
+		     }
+		  }
+		  fp = 0; /* Guarantees termination below. */
+	       }
+
+	       if (d == 0)
+	       {
+		  ++czero;
+		  if (cdigits == 0) ++clead;
+	       }
+	       else
+	       {
+		  /* Included embedded zeros in the digit count. */
+		  cdigits += czero - clead;
+		  clead = 0;
+
+		  while (czero > 0)
+		  {
+		     /* exp == (-1) means we just output the decimal
+		      * place - after the DP don't adjust 'exp' any
+		      * more!
+		      */
+		     if (exp != (-1)) 
+		     {
+		        if (exp == 0) *ascii++ = 46, --size;
+		        /* PLUS 1: TOTAL 4 */
+			--exp;
+		     }
+		     *ascii++ = 48, --czero;
+		  }
+
+		  if (exp != (-1))
+		  {
+		     if (exp == 0) *ascii++ = 46, --size; /* counted above */
+		     --exp;
+		  }
+		  *ascii++ = 48 + (int)d, ++cdigits;
+	       }
+	    }
+	    while (cdigits+czero-clead < (int)precision && fp > DBL_MIN);
+
+	    /* The total output count (max) is now 4+precision */
+
+	    /* Check for an exponent, if we don't need one we are
+	     * done and just need to terminate the string.  At
+	     * this point exp==(-1) is effectively if flag - it got
+	     * to '-1' because of the decrement after outputing
+	     * the decimal point above (the exponent required is
+	     * *not* -1!)
+	     */
+	    if (exp >= (-1) && exp <= 2)
+	    {
+	       /* The following only happens if we didn't output the
+		* leading zeros above for negative exponent, so this
+		* doest add to the digit requirement.  Note that the
+		* two zeros here can only be output if the two leading
+		* zeros were *not* output, so this doesn't increase
+		* the output count.
+		*/
+	       while (--exp >= 0) *ascii++ = 48;
+	       *ascii = 0;
+	       /* Total buffer requirement (including the '\0') is
+		* 5+precision - see check at the start.
+		*/
+	       return;
+	    }
+
+	    /* Here if an exponent is required, adjust size for
+	     * the digits we output but did not count.  The total
+	     * digit output here so far is at most 1+precision - no
+	     * decimal point and no leading or trailing zeros have
+	     * been output.
+	     */
+	    size -= cdigits;
+
+	    *ascii++ = 69, --size;    /* 'E': PLUS 1 TOTAL 2+precision*/
+	    if (exp < 0)
+	    {
+	       *ascii++ = 45, --size; /* '-': PLUS 1 TOTAL 3+precision */
+	       exp = -exp;
+	    }
+
+	    cdigits = 0;
+	    while (exp > 0)
+	    {
+	       exponent[cdigits++] = 48 + exp % 10;
+	       exp /= 10;
+	    }
+
+	    /* Need another size check here for the exponent digits, so
+	     * this need not be considered above.
+	     */
+	    if ((int)size > cdigits)
+	    {
+	       while (cdigits > 0) *ascii++ = exponent[--cdigits];
+	       *ascii = 0;
+	       return;
+	    }
+	 }
+      }
+      else if (!(fp >= DBL_MIN))
+      {
+         *ascii++ = 48; /* '0' */
+	 *ascii = 0;
+	 return;
+      }
+      else
+      {
+         *ascii++ = 105; /* 'i' */
+	 *ascii++ = 110; /* 'n' */
+	 *ascii++ = 102; /* 'f' */
+	 *ascii = 0;
+	 return;
+      }
+   }
+
+   /* Here on buffer too small. */
+   png_error(png_ptr, "ASCII convertion buffer too small");
+}
+
+#  endif /* FLOATING_POINT */
+#endif /* READ_SCAL */
+
+#if defined(PNG_FLOATING_POINT_SUPPORTED) &&\
+   !defined(PNG_FIXED_POINT_MACRO_SUPPORTED)
+png_fixed_point
+png_fixed(png_structp png_ptr, double fp, png_const_charp text)
+{
+   double r = floor(100000 * fp + .5);
+   if (r <= 2147483647. && r >= -2147483648.)
+      return (png_fixed_point)r;
+
+   png_fixed_error(png_ptr, text, fp);
+   return 0;
+}
+#endif
+
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED)
+/* muldiv functions */
+/* This API takes signed arguments and rounds the result to the nearest
+ * integer (or, for a fixed point number - the standard argument - to
+ * the nearest .00001).  Overflow and divide by zero are signalled in
+ * the result, a boolean - true on success, false on overflow.
+ */
+int
+png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times,
+   png_int_32 div)
+{
+   /* Return a * times / div, rounded. */
+   if (div != 0)
+   {
+      if (a == 0 || times == 0)
+      {
+	 *res = 0;
+         return 1;
+      }
+      else
+      {
+#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
+	 double r = a;
+	 r *= times;
+	 r /= div;
+	 r = floor(r+.5);
+	 /* A png_fixed_point is a 32 bit integer. */
+	 if (r <= 2147483647. && r >= -2147483648.)
+	 {
+	    *res = (png_fixed_point)r;
+	    return 1;
+	 }
+#else
+	 int negative = 0;
+	 png_uint_32 A, T, D;
+	 if (a < 0) negative = 1, A = -a; else A = a;
+	 if (times < 0) negative = !negative, T = -times; else T = times;
+	 if (div < 0) negative = !negative, D = -div; else D = div;
+
+	 /* Following can't overflow because the arguments only
+	  * have 31 bits each, however the result may be 32 bits.
+	  */
+	 png_uint_32 s16 = (A >> 16) * (T & 0xffff) +
+			   (A & 0xffff) * (T >> 16);
+	 /* Can't overflow because the a*times bit is only 30
+	  * bits at most.
+	  */
+	 png_uint_32 s32 = (A >> 16) * (T >> 16) + (s16 >> 16);
+	 png_uint_32 s00 = (A & 0xffff) * (T & 0xffff);
+
+	 s16 = (s16 & 0xffff) << 16;
+	 s00 += s16;
+	 if (s00 < s16) ++s32; /* carry */
+
+	 if (s32 < D) /* else overflow */
+	 {
+	    /* s32.s00 is now the 64 bit product, do a standard
+	     * division, we know that s32 < D, so the maximum
+	     * required shift is 31.
+	     */
+	    int bitshift = 32;
+	    png_fixed_point result = 0; /* NOTE: signed */
+
+	    while (--bitshift >= 0)
+	    {
+	       png_uint_32 d32, d00;
+	       if (bitshift > 0)
+	          d32 = D >> (32-bitshift), d00 = D << bitshift;
+	       else
+	          d32 = 0, d00 = D;
+
+	       if (s32 > d32)
+	       {
+		  if (s00 < d00) --s32; /* carry */
+	          s32 -= d32, s00 -= d00, result += 1<<bitshift;
+	       }
+	       else if (s32 == d32 && s00 >= d00)
+	          s32 = 0, s00 -= d00, result += 1<<bitshift;
+	    }
+
+	    /* Handle the rounding. */
+	    if (s00 >= (D >> 1)) ++result;
+
+	    if (negative) result = -result;
+
+	    /* Check for overflow. */
+	    if (negative && result <= 0 || !negative && result >= 0)
+	    {
+	       *res = result;
+	       return 1;
+	    }
+	 }
+#endif
+      }
+   }
+
+   return 0;
+}
+#endif /* READ_GAMMA || INCH_CONVERSIONS */
+
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED)
+/* The following is for when the caller doesn't much care about the
+ * result.
+ */
+png_fixed_point
+png_muldiv_warn(png_structp png_ptr, png_fixed_point a, png_int_32 times,
+   png_int_32 div)
+{
+   png_fixed_point result;
+   if (png_muldiv(&result, a, times, div))
+      return result;
+
+   png_warning(png_ptr, "fixed point overflow ignored");
+   return 0;
+}
+#endif
+
+#ifdef PNG_READ_GAMMA_SUPPORTED /* more fixed point functions for gammma */
+/* Calculate a reciprocal, return 0 on div-by-zero or overflow. */
+png_fixed_point
+png_reciprocal(png_fixed_point a)
+{
+#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
+   double r = floor(1E10/a+.5);
+   if (r <= 2147483647. && r >= -2147483648.)
+      return (png_fixed_point)r;
+#else
+   png_fixed_point res;
+   if (png_muldiv(&res, 100000, 100000, a))
+      return res;
+#endif
+
+   return 0; /* error/overflow */
+}
+
+/* A local convenience routine. */
+static png_fixed_point
+png_product2(png_fixed_point a, png_fixed_point b)
+{
+   /* The required result is 1/a * 1/b, the following preserves accuracy. */
+#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
+   double r = a * 1E-5;
+   r *= b;
+   r = floor(r+.5);
+   if (r <= 2147483647. && r >= -2147483648.)
+      return (png_fixed_point)r;
+#else
+   png_fixed_point res;
+   if (png_muldiv(&res, a, b, 100000))
+      return res;
+#endif
+
+   return 0; /* overflow */
+}
+
+/* The inverse of the above. */
+png_fixed_point
+png_reciprocal2(png_fixed_point a, png_fixed_point b)
+{
+   /* The required result is 1/a * 1/b, the following preserves accuracy. */
+#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
+   double r = 1E15/a;
+   r /= b;
+   r = floor(r+.5);
+   if (r <= 2147483647. && r >= -2147483648.)
+      return (png_fixed_point)r;
+#else
+   /* This may overflow because the range of png_fixed_point isn't symmetric,
+    * but this API is only used for the product of file and screen gamma so it
+    * doesn't matter that the smallest number it can produce is 1/21474, not
+    * 1/100000
+    */
+   png_fixed_point res = png_product2(a, b);
+   if (res != 0)
+      return png_reciprocal(res);
+#endif
+
+   return 0; /* overflow */
+}
+#endif /* READ_GAMMA */
+
+#ifdef PNG_CHECK_cHRM_SUPPORTED
+/* Added at libpng version 1.2.34 (Dec 8, 2008) and 1.4.0 (Jan 2,
+ * 2010: moved from pngset.c) */
+/*
+ *    Multiply two 32-bit numbers, V1 and V2, using 32-bit
+ *    arithmetic, to produce a 64 bit result in the HI/LO words.
+ *
+ *                  A B
+ *                x C D
+ *               ------
+ *              AD || BD
+ *        AC || CB || 0
+ *
+ *    where A and B are the high and low 16-bit words of V1,
+ *    C and D are the 16-bit words of V2, AD is the product of
+ *    A and D, and X || Y is (X << 16) + Y.
+*/
+
+void /* PRIVATE */
+png_64bit_product (long v1, long v2, unsigned long *hi_product,
+   unsigned long *lo_product)
+{
+   int a, b, c, d;
+   long lo, hi, x, y;
+
+   a = (v1 >> 16) & 0xffff;
+   b = v1 & 0xffff;
+   c = (v2 >> 16) & 0xffff;
+   d = v2 & 0xffff;
+
+   lo = b * d;                   /* BD */
+   x = a * d + c * b;            /* AD + CB */
+   y = ((lo >> 16) & 0xffff) + x;
+
+   lo = (lo & 0xffff) | ((y & 0xffff) << 16);
+   hi = (y >> 16) & 0xffff;
+
+   hi += a * c;                  /* AC */
+
+   *hi_product = (unsigned long)hi;
+   *lo_product = (unsigned long)lo;
+}
+#endif /* CHECK_cHRM */
+
+#ifdef PNG_READ_GAMMA_SUPPORTED /* gamma table code */
+#ifndef PNG_FLOATING_ARITHMETIC_SUPPORTED
+/* Fixed point gamma.
+ *
+ * To calculate gamma this code implements fast log() and exp() calls using only
+ * fixed point arithmetic.  This code has sufficient precision for either 8 or
+ * 16 bit sample values.
+ *
+ * The tables used here were calculated using simple 'bc' programs, but C double
+ * precision floating point arithmetic would work fine.  The programs are given
+ * at the head of each table.
+ *
+ * 8 bit log table
+ *   This is a table of -log(value/255)/log(2) for 'value' in the range 128 to
+ *   255, so it's the base 2 logarithm of a normalized 8 bit floating point
+ *   mantissa.  The numbers are 32 bit fractions.
+ */
+static png_uint_32
+png_8bit_l2[128] =
+{
+#  if PNG_DO_BC
+      for (i=128;i<256;++i) { .5 - l(i/255)/l(2)*65536*65536; }
+#  endif
+   4270715492U, 4222494797U, 4174646467U, 4127164793U, 4080044201U, 4033279239U,
+   3986864580U, 3940795015U, 3895065449U, 3849670902U, 3804606499U, 3759867474U,
+   3715449162U, 3671346997U, 3627556511U, 3584073329U, 3540893168U, 3498011834U,
+   3455425220U, 3413129301U, 3371120137U, 3329393864U, 3287946700U, 3246774933U,
+   3205874930U, 3165243125U, 3124876025U, 3084770202U, 3044922296U, 3005329011U,
+   2965987113U, 2926893432U, 2888044853U, 2849438323U, 2811070844U, 2772939474U,
+   2735041326U, 2697373562U, 2659933400U, 2622718104U, 2585724991U, 2548951424U,
+   2512394810U, 2476052606U, 2439922311U, 2404001468U, 2368287663U, 2332778523U,
+   2297471715U, 2262364947U, 2227455964U, 2192742551U, 2158222529U, 2123893754U,
+   2089754119U, 2055801552U, 2022034013U, 1988449497U, 1955046031U, 1921821672U,
+   1888774511U, 1855902668U, 1823204291U, 1790677560U, 1758320682U, 1726131893U,
+   1694109454U, 1662251657U, 1630556815U, 1599023271U, 1567649391U, 1536433567U,
+   1505374214U, 1474469770U, 1443718700U, 1413119487U, 1382670639U, 1352370686U,
+   1322218179U, 1292211689U, 1262349810U, 1232631153U, 1203054352U, 1173618059U,
+   1144320946U, 1115161701U, 1086139034U, 1057251672U, 1028498358U, 999877854U,
+   971388940U, 943030410U, 914801076U, 886699767U, 858725327U, 830876614U,
+   803152505U, 775551890U, 748073672U, 720716771U, 693480120U, 666362667U,
+   639363374U, 612481215U, 585715177U, 559064263U, 532527486U, 506103872U,
+   479792461U, 453592303U, 427502463U, 401522014U, 375650043U, 349885648U,
+   324227938U, 298676034U, 273229066U, 247886176U, 222646516U, 197509248U,
+   172473545U, 147538590U, 122703574U, 97967701U, 73330182U, 48790236U,
+   24347096U, 0U
+#if 0
+   /* The following are the values for 16 bit tables - these work fine for the 8
+    * bit convertions but produce very slightly larger errors in the 16 bit log
+    * (about 1.2 as opposed to 0.7 absolute error in the final value).  To use
+    * these all the shifts below must be adjusted appropriately.
+    */
+   65166, 64430, 63700, 62976, 62257, 61543, 60835, 60132, 59434, 58741, 58054,
+   57371, 56693, 56020, 55352, 54689, 54030, 53375, 52726, 52080, 51439, 50803,
+   50170, 49542, 48918, 48298, 47682, 47070, 46462, 45858, 45257, 44661, 44068,
+   43479, 42894, 42312, 41733, 41159, 40587, 40020, 39455, 38894, 38336, 37782,
+   37230, 36682, 36137, 35595, 35057, 34521, 33988, 33459, 32932, 32408, 31887,
+   31369, 30854, 30341, 29832, 29325, 28820, 28319, 27820, 27324, 26830, 26339,
+   25850, 25364, 24880, 24399, 23920, 23444, 22970, 22499, 22029, 21562, 21098,
+   20636, 20175, 19718, 19262, 18808, 18357, 17908, 17461, 17016, 16573, 16132,
+   15694, 15257, 14822, 14390, 13959, 13530, 13103, 12678, 12255, 11834, 11415,
+   10997, 10582, 10168, 9756, 9346, 8937, 8531, 8126, 7723, 7321, 6921, 6523,
+   6127, 5732, 5339, 4947, 4557, 4169, 3782, 3397, 3014, 2632, 2251, 1872, 1495,
+   1119, 744, 372
+#endif
+};
+
+static png_uint_32
+png_log8bit(unsigned x)
+{
+   unsigned log = 0;
+   /* Each time 'x' is multiplied by 2, 1 must be subtracted off the final log,
+    * because the log is actually negate that means adding 1.  The final
+    * returned value thus has the range 0 (for 255 input) to 7.994 (for 1
+    * input), return 7.99998 for the overflow (log 0) case - so the result is
+    * always at most 19 bits.
+    */
+   if ((x &= 0xff) == 0) return 0xffffffff; 
+   if ((x & 0xf0) == 0) log  = 4, x <<= 4;
+   if ((x & 0xc0) == 0) log += 2, x <<= 2;
+   if ((x & 0x80) == 0) log += 1, x <<= 1;
+   return (log << 16) + ((png_8bit_l2[x-128]+32768)>>16);
+}
+
+/* The above gives exact (to 16 binary places) log2 values for 8 bit images,
+ * for 16 bit images we use the most significant 8 bits of the 16 bit value to
+ * get an approximation then multiply the approximation by a correction factor
+ * determined by the remaining up to 8 bits.  This requires an additional step
+ * in the 16 bit case.
+ *
+ * We want log2(value/65535), we have log2(v'/255), where:
+ *
+ *    value = v' * 256 + v''
+ *          = v' * f
+ *
+ * So f is value/v', which is equal to (256+v''/v') since v' is in the range 128
+ * to 255 and v'' is in the range 0 to 255 f will be in the range 256 to less
+ * than 258.  The final factor also needs to correct for the fact that our 8 bit
+ * value is scaled by 255, whereas the 16 bit values must be scaled by 65535.
+ *
+ * This gives a final formula using a calculated value 'x' which is value/v' and
+ * scaling by 65536 to match the above table:
+ *
+ *   log2(x/257) * 65536
+ *
+ * Since these numbers are so close to '1' we can use simple linear
+ * interpolation between the two end values 256/257 (result -368.61) and 258/257
+ * (result 367.179).  The values used below are scaled by a further 64 to give
+ * 16 bit precision in the interpolation:
+ *
+ * Start (256): -23591
+ * Zero  (257):      0
+ * End   (258):  23499
+ */
+static png_uint_32
+png_log16bit(png_uint_32 x)
+{
+   unsigned log = 0;
+
+   /* As above, but now the input has 16 bits. */
+   if ((x &= 0xffff) == 0) return 0xffffffff;
+   if ((x & 0xff00) == 0) log  = 8, x <<= 8;
+   if ((x & 0xf000) == 0) log += 4, x <<= 4;
+   if ((x & 0xc000) == 0) log += 2, x <<= 2;
+   if ((x & 0x8000) == 0) log += 1, x <<= 1;
+
+   /* Calculate the base logarithm from the top 8 bits as a 28 bit fractional
+    * value.
+    */
+   log <<= 28;
+   log += (png_8bit_l2[(x>>8)-128]+8) >> 4;
+
+   /* Now we need to interpolate the factor, this requires a division by the top
+    * 8 bits.  Do this with maximum precision.
+    */
+   x = ((x << 16) + (x >> 9)) / (x >> 8);
+
+   /* Since we divided by the top 8 bits of 'x' there will be a '1' at 1<<24,
+    * the value at 1<<16 (ignoring this) will be 0 or 1; this gives us exactly
+    * 16 bits to interpolate to get the low bits of the result.  Round the
+    * answer.  Note that the end point values are scaled by 64 to retain overall
+    * precision and that 'log' is current scaled by an extra 12 bits, so adjust
+    * the overall scaling by 6-12.  Round at every step.
+    */
+   x -= 1U << 24;
+   if (x <= 65536U) /* <= '257' */
+      log += ((23591U * (65536U-x)) + (1U << (16+6-12-1))) >> (16+6-12);
+   else
+      log -= ((23499U * (x-65536U)) + (1U << (16+6-12-1))) >> (16+6-12);
+
+   return (log + 2048) >> 12;
+}
+
+/* The 'exp()' case must invert the above, taking a 20 bit fixed point
+ * logarithmic value and returning a 16 or 8 bit number as appropriate.  In
+ * each case only the low 16 bits are relevant - the fraction - since the
+ * integer bits (the top 4) simply determine a shift.
+ *
+ * The worst case is the 16 bit distinction between 65535 and 65534, this
+ * requires perhaps spurious accuracty in the decoding of the logarithm to
+ * distinguish log2(65535/65534.5) - 10^-5 or 17 bits.  There is little chance
+ * of getting this accuracy in practice.
+ *
+ * To deal with this the following exp() function works out the exponent of the
+ * frational part of the logarithm by using an accurate 32 bit value from the
+ * top four fractional bits then multiplying in the remaining bits.
+ */
+static png_uint_32
+png_32bit_exp[16] =
+{
+#  if PNG_DO_BC
+      for (i=0;i<16;++i) { .5 + e(-i/16*l(2))*2^32; }
+#  endif
+   /* NOTE: the first entry is deliberately set to the maximum 32 bit value. */
+   4294967295U, 4112874773U, 3938502376U, 3771522796U, 3611622603U, 3458501653U,
+   3311872529U, 3171459999U, 3037000500U, 2908241642U, 2784941738U, 2666869345U,
+   2553802834U, 2445529972U, 2341847524U, 2242560872U
+};
+
+/* Adjustment table; provided to explain the numbers in the code below. */
+#if PNG_DO_BC
+for (i=11;i>=0;--i){ print i, " ", (1 - e(-(2^i)/65536*l(2))) * 2^(32-i), "\n"}
+   11 44937.64284865548751208448
+   10 45180.98734845585101160448
+    9 45303.31936980687359311872
+    8 45364.65110595323018870784
+    7 45395.35850361789624614912
+    6 45410.72259715102037508096
+    5 45418.40724413220722311168
+    4 45422.25021786898173001728
+    3 45424.17186732298419044352
+    2 45425.13273269940811464704
+    1 45425.61317555035558641664
+    0 45425.85339951654943850496
+#endif
+
+static png_uint_32
+png_exp(png_uint_32 x)
+{
+   if (x <= 0xfffff) /* Else zero */
+   {
+      /* Obtain a 4 bit approximation */
+      png_uint_32 e = png_32bit_exp[(x >> 12) & 0xf];
+
+      /* Incorporate the low 12 bits - these decrease the returned value by
+       * multiplying by a number less than 1 if the bit is set.  The multiplier
+       * is determined by the above table and the shift, notice that the values
+       * converge on 45426 and this is used to allow linear interpolation of the
+       * low bits.
+       */
+      if (x & 0x800) e -= (((e >> 16) * 44938U) +  16U) >> 5;
+      if (x & 0x400) e -= (((e >> 16) * 45181U) +  32U) >> 6;
+      if (x & 0x200) e -= (((e >> 16) * 45303U) +  64U) >> 7;
+      if (x & 0x100) e -= (((e >> 16) * 45365U) + 128U) >> 8;
+      if (x & 0x080) e -= (((e >> 16) * 45395U) + 256U) >> 9;
+      if (x & 0x040) e -= (((e >> 16) * 45410U) + 512U) >> 10;
+
+      /* And handle the low 6 bits in a single block. */
+      e -= (((e >> 16) * 355U * (x & 0x3fU)) + 256U) >> 9;
+
+      /* Handle the upper bits of x. */
+      e >>= x >> 16;
+      return e;
+   }
+
+   return 0;
+}
+
+static png_byte
+png_exp8bit(png_uint_32 log)
+{
+   /* Get a 32 bit value: */
+   png_uint_32 x = png_exp(log);
+
+   /* Convert the 32 bit value to 0..255 by multiplying by 256-1, note that the
+    * second, rounding, step can't overflow because of the first, subtraction,
+    * step.
+    */
+   x -= x >> 8;
+   return (x + 0x7fffffU) >> 24;
+}
+
+static png_uint_16
+png_exp16bit(png_uint_32 log)
+{
+   /* Get a 32 bit value: */
+   png_uint_32 x = png_exp(log);
+
+   /* Convert the 32 bit value to 0..65535 by multiplying by 65536-1: */
+   x -= x >> 16;
+   return (x + 32767U) >> 16;
+}
+#endif /* FLOATING_ARITHMETIC */
+
+png_byte
+png_gamma_8bit_correct(unsigned value, png_fixed_point gamma)
+{
+   if (value > 0 && value < 255)
+   {
+#     ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
+	 return (png_byte)floor(255*pow(value/255.,gamma*.00001)+.5);
+#     else
+	 png_uint_32 log = png_log8bit(value);
+	 png_fixed_point res;
+	 if (png_muldiv(&res, gamma, log, PNG_FP_1))
+	    return png_exp8bit(res);
+#     endif
+
+      /* Overflow. */
+      value = 0;
+   }
+
+   return value;
+}
+
+png_uint_16
+png_gamma_16bit_correct(unsigned value, png_fixed_point gamma)
+{
+   if (value > 0 && value < 65535)
+   {
+#     ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
+	 return (png_uint_16)floor(65535*pow(value/65535.,gamma*.00001)+.5);
+#     else
+	 png_uint_32 log = png_log16bit(value);
+	 png_fixed_point res;
+	 if (png_muldiv(&res, gamma, log, PNG_FP_1))
+	    return png_exp16bit(res);
+#     endif
+
+      /* Overflow. */
+      value = 0;
+   }
+
+   return value;
+}
+
+/* This does the right thing based on the bit_depth field of the
+ * png_struct, interpreting values as 8 or 16 bit.  While the result
+ * is nominally a 16 bit value if bit depth is 8 then the result is
+ * 8 bit (as are the arguments.)
+ */
+png_uint_16 /* PRIVATE */
+png_gamma_correct(png_structp png_ptr, unsigned value, png_fixed_point gamma)
+{
+   if (png_ptr->bit_depth == 8)
+      return png_gamma_8bit_correct(value, gamma);
+   else
+      return png_gamma_16bit_correct(value, gamma);
+}
+
+/* This is the shared test on whether a gamma value is 'significant' - whether
+ * it is worth doing gamma correction.
+ */
+int /* PRIVATE */
+png_gamma_significant(png_fixed_point gamma)
+{
+   return gamma < PNG_FP_1-PNG_GAMMA_THRESHOLD_FIXED ||
+      gamma > PNG_FP_1+PNG_GAMMA_THRESHOLD_FIXED;
+}
+
+/* Internal function to build a single 16 bit table - the table consists of
+ * 'num' 256 entry subtables, where 'num' is determined by 'shift' - the amount
+ * to shift the input values right (or 16-number_of_signifiant_bits).
+ *
+ * The caller is respoonsible for ensuring that the table gets cleaned up on
+ * png_error (i.e. if one of the mallocs below fails) - i.e. the *table argument
+ * should be somewhere that will be cleaned.
+ */
+static void
+png_build_16bit_table(png_structp png_ptr, png_uint_16pp *ptable,
+   PNG_CONST unsigned shift, PNG_CONST png_fixed_point gamma)
+{
+   /* Various values derived from 'shift': */
+   PNG_CONST unsigned num = 1U << (8U - shift);
+   PNG_CONST unsigned max = (1U << (16U - shift))-1U;
+   PNG_CONST unsigned max_by_2 = 1U << (15U-shift);
+   unsigned i;
+
+   png_uint_16pp table = *ptable =
+      (png_uint_16pp)png_calloc(png_ptr, num * png_sizeof(png_uint_16p));
+
+   for (i = 0; i < num; i++)
+   {
+      png_uint_16p sub_table = table[i] =
+         (png_uint_16p)png_malloc(png_ptr, 256 * png_sizeof(png_uint_16));
+
+      /* The 'threshold' test is repeated here because it can arise for one of
+       * the 16 bit tables even if the others don't hit it.
+       */
+      if (png_gamma_significant(gamma))
+      {
+	 /* The old code would overflow at the end and this would cause the
+	  * 'pow' function to return a result >1, resulting in an
+	  * arithmetic error.  This code follows the spec exactly; ig is
+	  * the recovered input sample, it always has 8-16 bits.
+	  *
+	  * We want input * 65535/max, rounded, the arithmetic fits in 32
+	  * bits (unsigned) so long as max <= 32767.
+	  */
+	 unsigned j;
+	 for (j = 0; j < 256; j++)
+	 {
+	    png_uint_16 ig = (j << (8-shift)) + i;
+#           ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
+	       /* Inline the 'max' scaling operation: */
+	       sub_table[j] = (png_uint_16)floor(65535*pow(ig/(double)max,
+	          gamma*.00001)+.5);
+#           else
+	       if (shift)
+		  ig = (ig * 65535U + max_by_2)/max;
+	       sub_table[j] = png_gamma_16bit_correct(ig, gamma);
+#           endif
+	 }
+      }
+      else
+      {
+         /* We must still build a table, but do it the fast way. */
+	 unsigned j;
+	 for (j = 0; j < 256; j++)
+	 {
+	    png_uint_32 ig = (j << (8-shift)) + i;
+	    if (shift)
+	       ig = (ig * 65535U + max_by_2)/max;
+	    sub_table[j] = ig;
+	 }
+      }
+   }
+}
+
+/* NOTE: this function expects the *inverse* of the overall gamma transformation
+ * required.
+ */
+static void
+png_build_16to8_table(png_structp png_ptr, png_uint_16pp *ptable,
+   PNG_CONST unsigned shift, PNG_CONST png_fixed_point gamma)
+{
+   PNG_CONST unsigned num = 1U << (8U - shift);
+   PNG_CONST unsigned max = (1U << (16U - shift))-1U;
+   unsigned i;
+   png_uint_32 last;
+
+   png_uint_16pp table = *ptable =
+      (png_uint_16pp)png_calloc(png_ptr, num * png_sizeof(png_uint_16p));
+
+   /* 'num' is the number of tables and also the number of low bits of low
+    * bits of the input 16 bit value used to select a table.  Each table is
+    * itself index by the high 8 bits of the value.
+    */
+   for (i = 0; i < num; i++)
+      table[i] = (png_uint_16p)png_malloc(png_ptr,
+         256 * png_sizeof(png_uint_16));
+
+   /* 'gamma' is set to the reciprocal of the value calculated above, so
+    * pow(out,g) is an *input* value.  'last' is the last input value set.
+    *
+    * In the loop 'i' is used to find output values.  Since the output is 8
+    * bit there are only 256 possible values.  The tables are set up to
+    * select the closest possible output value for each input by finding
+    * the input value at the boundary between each pair of output values
+    * and filling the table up to that boundary with the lower output
+    * value.
+    *
+    * The boundary values are 0.5,1.5..253.5,254.5.  Since these are 9 bit
+    * values the code below uses a 16 bit value in i; the values start at
+    * 128.5 (for 0.5) and step by 257, for a total of 254 values (the last
+    * entries are filled with 255).  Start i at 128 and fill all 'last'
+    * table entries <= 'max'
+    */
+   last = 0;
+   for (i = 0; i < 255; ++i) /* 8 bit output value */
+   {
+      /* Find the corresponding maximum input value */
+      png_uint_16 out = i * 257U; /* 16 bit output value */
+      /* Find the boundary value in 16 bits: */
+      png_uint_16 bound = png_gamma_16bit_correct(out+128U, gamma);
+      /* Adjust (round) to (16-shift) bits: */
+      bound = (bound * max + 32768)/65535;
+
+      while (last <= bound)
+      {
+	 table[last & (0xffU >> shift)][last >> (8U - shift)] = out;
+	 last++;
+      }
+   }
+
+   /* And fill in the final entries. */
+   while (last < (num << 8))
+   {
+      table[last & (0xff >> shift)][last >> (8U - shift)] = 65535U;
+      last++;
+   }
+}
+
+/* Build a single 8 bit table: same as the 16 bit case but much simpler (and
+ * typically much faster).  Note that libpng currently does no sBIT processing
+ * (apparently contrary to the spec) so a 256 entry table is always generated.
+ */
+static void
+png_build_8bit_table(png_structp png_ptr, png_bytepp ptable,
+   PNG_CONST png_fixed_point gamma)
+{
+   unsigned i;
+   png_bytep table = *ptable = (png_bytep)png_malloc(png_ptr, 256);
+
+   if (png_gamma_significant(gamma)) for (i=0; i<256; i++)
+      table[i] = png_gamma_8bit_correct(i, gamma);
+   else for (i=0; i<245; ++i)
+      table[i] = i;
+}
+
+/* We build the 8- or 16-bit gamma tables here.  Note that for 16-bit
+ * tables, we don't make a full table if we are reducing to 8-bit in
+ * the future.  Note also how the gamma_16 tables are segmented so that
+ * we don't need to allocate > 64K chunks for a full 16-bit table.
+ */
+void /* PRIVATE */
+png_build_gamma_table(png_structp png_ptr, png_byte bit_depth)
+{
+  png_debug(1, "in png_build_gamma_table");
+
+  if (bit_depth <= 8)
+  {
+     png_build_8bit_table(png_ptr, &png_ptr->gamma_table,
+        png_ptr->screen_gamma > 0 ?  png_reciprocal2(png_ptr->gamma,
+	   png_ptr->screen_gamma) : PNG_FP_1);
+
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
+   defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+     if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY))
+     {
+        png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1,
+	   png_reciprocal(png_ptr->gamma));
+
+        png_build_8bit_table(png_ptr, &png_ptr->gamma_from_1,
+           png_ptr->screen_gamma > 0 ?  png_reciprocal(png_ptr->screen_gamma) :
+	      png_ptr->gamma/* Probably doing rgb_to_gray */);
+     }
+#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
+  }
+  else
+  {
+     png_byte shift, sig_bit;
+
+     if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
+     {
+        sig_bit = png_ptr->sig_bit.red;
+
+        if (png_ptr->sig_bit.green > sig_bit)
+           sig_bit = png_ptr->sig_bit.green;
+
+        if (png_ptr->sig_bit.blue > sig_bit)
+           sig_bit = png_ptr->sig_bit.blue;
+     }
+     else
+        sig_bit = png_ptr->sig_bit.gray;
+
+     /* 16 bit gamma code uses this equation:
+      *
+      *   ov = table[(iv & 0xff) >> gamma_shift][iv >> 8]
+      *
+      * Where 'iv' is the input color value and 'ov' is the output value -
+      * pow(iv, gamma).
+      *
+      * Thus the gamma table consists of up to 256 256 entry tables.  The table
+      * is selected by the (8-gamma_shift) most significant of the low 8 bits of
+      * the color value then indexed by the upper 8 bits:
+      *
+      *   table[low bits][high 8 bits]
+      *
+      * So the table 'n' corresponds to all those 'iv' of:
+      *
+      *   <all high 8 bit values><n << gamma_shift>..<(n+1 << gamma_shift)-1>
+      *
+      */
+     if (sig_bit > 0)
+        shift = 16U - sig_bit; /* shift == insignificant bits */
+     else
+        shift = 0; /* keep all 16 bits */
+
+     if (png_ptr->transformations & PNG_16_TO_8)
+     {
+	/* PNG_MAX_GAMMA_8 is the number of bits to keep - effectively
+	 * the significant bits in the *input* when the output will
+	 * eventually be 8 bits.  By default it is 11.
+	 */
+        if (shift < (16U - PNG_MAX_GAMMA_8))
+           shift = (16U - PNG_MAX_GAMMA_8);
+     }
+
+     if (shift > 8U)
+        shift = 8U; /* Guarantees at least one table! */
+
+     png_ptr->gamma_shift = shift;
+
+     if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND))
+	png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift,
+	   png_ptr->screen_gamma > 0 ? png_product2(png_ptr->gamma,
+	      png_ptr->screen_gamma) : PNG_FP_1);
+     else
+	png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift,
+	   png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->gamma,
+	      png_ptr->screen_gamma) : PNG_FP_1);
+
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
+   defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+     if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY))
+     {
+	png_build_16bit_table(png_ptr, &png_ptr->gamma_16_to_1, shift,
+	   png_reciprocal(png_ptr->gamma));
+
+	/* Notice that the '16 from 1' table should be full precision, however
+	 * the lookup on this table still uses gamma_shift, os it can't be.
+	 * TODO: fix this.
+	 */
+        png_build_16bit_table(png_ptr, &png_ptr->gamma_16_from_1, shift,
+           png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) :
+           png_ptr->gamma/* Probably doing rgb_to_gray */);
+     }
+#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
+  }
+}
+#endif /* READ_GAMMA */
diff --git a/png.h b/png.h
index 398b879..ccc9e99 100644
--- a/png.h
+++ b/png.h
@@ -1,7 +1,7 @@
 
 /* png.h - header file for PNG reference library
  *
- * libpng version 1.5.0beta36 - July 24, 2010
+ * libpng version 1.5.0beta36 - July 29, 2010
  * Copyright (c) 1998-2010 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -11,7 +11,7 @@
  * Authors and maintainers:
  *   libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
  *   libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger
- *   libpng versions 0.97, January 1998, through 1.5.0beta36 - July 24, 2010: Glenn
+ *   libpng versions 0.97, January 1998, through 1.5.0beta36 - July 29, 2010: Glenn
  *   See also "Contributing Authors", below.
  *
  * Note about libpng version numbers:
@@ -172,7 +172,7 @@
  *
  * This code is released under the libpng license.
  *
- * libpng versions 1.2.6, August 15, 2004, through 1.5.0beta36, July 24, 2010, are
+ * libpng versions 1.2.6, August 15, 2004, through 1.5.0beta36, July 29, 2010, are
  * Copyright (c) 2004, 2006-2010 Glenn Randers-Pehrson, and are
  * distributed according to the same disclaimer and license as libpng-1.2.5
  * with the following individual added to the list of Contributing Authors:
@@ -284,14 +284,14 @@
  * Y2K compliance in libpng:
  * =========================
  *
- *    July 24, 2010
+ *    July 29, 2010
  *
  *    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.71 and
- *    upward through 1.5.0beta36 are Y2K compliant.  It is my belief that earlier
- *    versions were also Y2K compliant.
+ *    upward through 1.5.0beta36 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
@@ -348,7 +348,7 @@
 /* Version information for png.h - this should match the version in png.c */
 #define PNG_LIBPNG_VER_STRING "1.5.0beta36"
 #define PNG_HEADER_VERSION_STRING \
-     " libpng version 1.5.0beta36 - July 24, 2010\n"
+     " libpng version 1.5.0beta36 - July 29, 2010\n"
 
 #define PNG_LIBPNG_VER_SONUM   15
 #define PNG_LIBPNG_VER_DLLNUM  15
@@ -397,15 +397,17 @@
 
 #ifndef PNG_VERSION_INFO_ONLY
 /* Standard header files (not needed for the version info) */
-#  ifdef PNG_STDIO_SUPPORTED
-#    include <stdio.h>
-#  endif
 #  ifdef PNG_SETJMP_SUPPORTED
 #    include <setjmp.h>
 #  endif
 
-/* Include the compression library's header */
-#  include "zlib.h"
+/* Need the time information for converting tIME chunks, it
+ * defines struct tm:
+ */
+#ifdef PNG_CONVERT_tIME_SUPPORTED
+   /* "time.h" functions are not supported on all operating systems */
+#  include <time.h>
+#endif
 
 /* Machine specific configuration. */
 #  include "pngconf.h"
@@ -647,6 +649,12 @@
 #define PNG_UINT_32_MAX ((png_uint_32)(-1))
 #define PNG_SIZE_MAX ((png_size_t)(-1))
 
+/* These are constants for fixed point values encoded in the
+ * PNG specification manner (x100000)
+ */
+#define PNG_FP_1    100000
+#define PNG_FP_HALF  50000
+
 /* These describe the color_type field in png_info. */
 /* color type masks */
 #define PNG_COLOR_MASK_PALETTE    1
@@ -794,6 +802,17 @@
 /* This must match the function definition in <setjmp.h>, and the
  * application must include this before png.h to obtain the definition
  * of jmp_buf.  The function is required to be PNG_NORETURN.
+ *
+ * If you get a type warning from the compiler when linking against this line
+ * then your compiler has 'longjmp' that does not match the requirements of the
+ * compiler that built libpng.  You will have to write a wrapper function for
+ * your compiler's longjmp and call png_set_longjmp_fn directly (not via the
+ * png_jmpbuf macro.)
+ *
+ * If you get a warning here while building the library you will need to make
+ * changes to ensure that pnglibconf.h records the calling convention used by
+ * your compiler.  This may be very difficult - try using a different compiler
+ * to build the library!
  */
 typedef void (PNGCAPI *png_longjmp_ptr) PNGARG((jmp_buf, int)) PNG_NORETURN;
 #endif
@@ -853,8 +872,7 @@
 /* Tell lib we have already handled the first <num_bytes> magic bytes.
  * Handling more than 8 bytes from the beginning of the file is an error.
  */
-PNG_EXPORT(void,png_set_sig_bytes,(png_structp png_ptr,
-    int num_bytes),,2);
+PNG_EXPORT(void,png_set_sig_bytes,(png_structp png_ptr, int num_bytes),,2);
 
 /* Check sig[start] through sig[start + num_to_check - 1] to see if it's a
  * PNG file.  Returns zero if the supplied bytes match the 8-byte PNG
@@ -870,17 +888,16 @@
 #define png_check_sig(sig,n) !png_sig_cmp((sig), 0, (n))
 
 /* Allocate and initialize png_ptr struct for reading, and any other memory. */
-PNG_EXPORT(png_structp,png_create_read_struct,
-    (png_const_charp user_png_ver, png_voidp error_ptr,
-    png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED,4);
+PNG_EXPORT(png_structp,png_create_read_struct,(png_const_charp user_png_ver,
+    png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn),
+    PNG_ALLOCATED,4);
 
 /* Allocate and initialize png_ptr struct for writing, and any other memory */
-PNG_EXPORT(png_structp,png_create_write_struct,
-    (png_const_charp user_png_ver, png_voidp error_ptr,
-    png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED,5);
+PNG_EXPORT(png_structp,png_create_write_struct,(png_const_charp user_png_ver,
+    png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn),
+    PNG_ALLOCATED,5);
 
-PNG_EXPORT(png_size_t,png_get_compression_buffer_size,(png_structp
-    png_ptr),,6);
+PNG_EXPORT(png_size_t,png_get_compression_buffer_size,(png_structp png_ptr),,6);
 
 PNG_EXPORT(void,png_set_compression_buffer_size,(png_structp png_ptr,
     png_size_t size),,7);
@@ -896,7 +913,7 @@
  * allocated by the library - the call will return NULL on a mismatch
  * indicating an ABI mismatch.
  */
-PNG_EXPORT(jmp_buf*, png_set_longjmp_fn, (png_structp png_ptr,
+PNG_EXPORT(jmp_buf*,png_set_longjmp_fn,(png_structp png_ptr,
     png_longjmp_ptr longjmp_fn, size_t jmp_buf_size),,8);
 #  define png_jmpbuf(png_ptr) \
       (*png_set_longjmp_fn((png_ptr), longjmp, sizeof (jmp_buf)))
@@ -909,8 +926,7 @@
  * will use it; otherwise it will call PNG_ABORT().  This function was
  * added in libpng-1.5.0.
  */
-PNG_EXPORT(void, png_longjmp, (png_structp png_ptr, int val),
-    PNG_NORETURN,9);
+PNG_EXPORT(void,png_longjmp,(png_structp png_ptr, int val),PNG_NORETURN,9);
 
 #ifdef PNG_READ_SUPPORTED
 /* Reset the compression stream */
@@ -919,30 +935,30 @@
 
 /* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */
 #ifdef PNG_USER_MEM_SUPPORTED
-PNG_EXPORT(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_ALLOCATED,11);
-PNG_EXPORT(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),PNG_ALLOCATED,12);
+PNG_EXPORT(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_ALLOCATED,11);
+PNG_EXPORT(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),
+    PNG_ALLOCATED,12);
 #endif
 
 /* Write the PNG file signature. */
 PNG_EXPORT(void,png_write_sig,(png_structp png_ptr),,13);
 
 /* Write a PNG chunk - size, type, (optional) data, CRC. */
-PNG_EXPORT(void,png_write_chunk,(png_structp png_ptr,
-    png_bytep chunk_name, png_bytep data, png_size_t length),,14);
+PNG_EXPORT(void,png_write_chunk,(png_structp png_ptr, png_bytep chunk_name,
+    png_bytep data, png_size_t length),,14);
 
 /* Write the start of a PNG chunk - length and chunk name. */
 PNG_EXPORT(void,png_write_chunk_start,(png_structp png_ptr,
     png_bytep chunk_name, png_uint_32 length),,15);
 
 /* Write the data of a PNG chunk started with png_write_chunk_start(). */
-PNG_EXPORT(void,png_write_chunk_data,(png_structp png_ptr,
-    png_bytep data, png_size_t length),,16);
+PNG_EXPORT(void,png_write_chunk_data,(png_structp png_ptr, png_bytep data,
+    png_size_t length),,16);
 
 /* Finish a chunk started with png_write_chunk_start() (includes CRC). */
 PNG_EXPORT(void,png_write_chunk_end,(png_structp png_ptr),,17);
@@ -957,13 +973,11 @@
 /* Writes all the PNG information before the image. */
 PNG_EXPORT(void,png_write_info_before_PLTE,(png_structp png_ptr,
     png_infop info_ptr),,20);
-PNG_EXPORT(void,png_write_info,(png_structp png_ptr,
-    png_infop info_ptr),,21);
+PNG_EXPORT(void,png_write_info,(png_structp png_ptr, png_infop info_ptr),,21);
 
 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED
 /* Read the information before the actual image data. */
-PNG_EXPORT(void,png_read_info,(png_structp png_ptr,
-    png_infop info_ptr),,22);
+PNG_EXPORT(void,png_read_info,(png_structp png_ptr, png_infop info_ptr),,22);
 #endif
 
 #ifdef PNG_TIME_RFC1123_SUPPORTED
@@ -977,15 +991,13 @@
     struct tm FAR * ttime),,24);
 
 /* Convert from time_t to png_time.  Uses gmtime() */
-PNG_EXPORT(void,png_convert_from_time_t,(png_timep ptime,
-    time_t ttime),,25);
+PNG_EXPORT(void,png_convert_from_time_t,(png_timep ptime, time_t ttime),,25);
 #endif /* PNG_CONVERT_tIME_SUPPORTED */
 
 #ifdef PNG_READ_EXPAND_SUPPORTED
 /* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */
 PNG_EXPORT(void,png_set_expand,(png_structp png_ptr),,26);
-PNG_EXPORT(void,png_set_expand_gray_1_2_4_to_8,(png_structp png_ptr),,
-    27);
+PNG_EXPORT(void,png_set_expand_gray_1_2_4_to_8,(png_structp png_ptr),,27);
 PNG_EXPORT(void,png_set_palette_to_rgb,(png_structp png_ptr),,28);
 PNG_EXPORT(void,png_set_tRNS_to_alpha,(png_structp png_ptr),,29);
 #endif
@@ -1000,17 +1012,12 @@
 PNG_EXPORT(void,png_set_gray_to_rgb,(png_structp png_ptr),,31);
 
 /* Reduce RGB to grayscale. */
-#  ifdef PNG_FLOATING_POINT_SUPPORTED
-PNG_EXPORT(void,png_set_rgb_to_gray,(png_structp png_ptr,
-    int error_action, double red, double green ),,32);
-#  endif
-#  ifdef PNG_FIXED_POINT_SUPPORTED
-PNG_EXPORT(void,png_set_rgb_to_gray_fixed,(png_structp png_ptr,
+PNG_FP_EXPORT(void,png_set_rgb_to_gray,(png_structp png_ptr, int error_action,
+    double red, double green ),,32);
+PNG_FIXED_EXPORT(void,png_set_rgb_to_gray_fixed,(png_structp png_ptr,
     int error_action, png_fixed_point red, png_fixed_point green),,33);
-#  endif
 
-PNG_EXPORT(png_byte,png_get_rgb_to_gray_status,(png_structp png_ptr),,
-    34);
+PNG_EXPORT(png_byte,png_get_rgb_to_gray_status,(png_structp png_ptr),,34);
 #endif
 
 PNG_EXPORT(void,png_build_grayscale_palette,(int bit_depth,
@@ -1032,14 +1039,14 @@
 
 #if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
 /* Add a filler byte to 8-bit Gray or 24-bit RGB images. */
-PNG_EXPORT(void,png_set_filler,(png_structp png_ptr,
-    png_uint_32 filler, int flags),,39);
+PNG_EXPORT(void,png_set_filler,(png_structp png_ptr, png_uint_32 filler,
+    int flags),,39);
 /* The values of the PNG_FILLER_ defines should NOT be changed */
 #  define PNG_FILLER_BEFORE 0
 #  define PNG_FILLER_AFTER 1
 /* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */
-PNG_EXPORT(void,png_set_add_alpha,(png_structp png_ptr,
-    png_uint_32 filler, int flags),,40);
+PNG_EXPORT(void,png_set_add_alpha,(png_structp png_ptr, png_uint_32 filler,
+    int flags),,40);
 #endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */
 
 #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
@@ -1060,16 +1067,33 @@
 
 #if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
 /* Converts files to legal bit depths. */
-PNG_EXPORT(void,png_set_shift,(png_structp png_ptr,
-    png_color_8p true_bits),,44);
+PNG_EXPORT(void,png_set_shift,(png_structp png_ptr, png_color_8p true_bits),,
+    44);
 #endif
 
 #if defined(PNG_READ_INTERLACING_SUPPORTED) || \
     defined(PNG_WRITE_INTERLACING_SUPPORTED)
-/* Have the code handle the interlacing.  Returns the number of passes. */
+/* Have the code handle the interlacing.  Returns the number of passes.
+ * MUST be called before png_read_update_info or png_start_read_image, otherwise
+ * it will not have the desired effect.  Note that it is still necessary to call
+ * png_read_row or png_read_rows png_get_image_height times for each pass.
+ */
 PNG_EXPORT(int,png_set_interlace_handling,(png_structp png_ptr),,45);
 #endif
 
+#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
+/* Alternatively call this to get the number of rows in the current pass.  Call
+ * this after png_read_update_info or png_start_read_image; if you call it
+ * before it will just return the image height (which is also what it returns
+ * for a non-interlaced image!).
+ *
+ * NOTE: you need to call these to find out how many times to call png_read_row
+ * if you handle your own de-interlacing.
+ */
+PNG_EXPORT(int,png_get_num_passes,(png_structp png_ptr),,215);
+PNG_EXPORT(png_uint_32,png_get_num_rows,(png_structp png_ptr),,216);
+#endif
+
 #if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
 /* Invert monochrome files */
 PNG_EXPORT(void,png_set_invert_mono,(png_structp png_ptr),,46);
@@ -1077,12 +1101,14 @@
 
 #ifdef PNG_READ_BACKGROUND_SUPPORTED
 /* Handle alpha and tRNS by replacing with a background color. */
-#  ifdef PNG_FLOATING_POINT_SUPPORTED
-PNG_EXPORT(void,png_set_background,(png_structp png_ptr,
-    png_color_16p background_color, int background_gamma_code,
-    int need_expand, double background_gamma),,47);
-#  endif
-/* TODO: png_set_background_fixed */
+PNG_FP_EXPORT(void,png_set_background,(png_structp png_ptr,
+    png_color_16p background_color, int background_gamma_code, int need_expand,
+    double background_gamma),,47);
+PNG_FIXED_EXPORT(void,png_set_background_fixed,(png_structp png_ptr,
+    png_color_16p background_color, int background_gamma_code, int need_expand,
+    png_fixed_point background_gamma),,217);
+#endif
+#ifdef PNG_READ_BACKGROUND_SUPPORTED
 #  define PNG_BACKGROUND_GAMMA_UNKNOWN 0
 #  define PNG_BACKGROUND_GAMMA_SCREEN  1
 #  define PNG_BACKGROUND_GAMMA_FILE    2
@@ -1098,18 +1124,22 @@
 /* Turn on quantizing, and reduce the palette to the number of colors
  * available.
  */
-PNG_EXPORT(void,png_set_quantize,(png_structp png_ptr,
-    png_colorp palette, int num_palette, int maximum_colors,
-    png_uint_16p histogram, int full_quantize),,49);
+PNG_EXPORT(void,png_set_quantize,(png_structp png_ptr, png_colorp palette,
+    int num_palette, int maximum_colors, png_uint_16p histogram,
+    int full_quantize),,49);
 #endif
 
 #ifdef PNG_READ_GAMMA_SUPPORTED
+/* The threshold on gamma processing is configurable but hard-wired into the
+ * library.  The following is the floating point variant.
+ */
+#define PNG_GAMMA_THRESHOLD (PNG_GAMMA_THRESHOLD_FIXED*.00001)
+
 /* Handle gamma correction. Screen_gamma=(display_exponent) */
-#  ifdef PNG_FLOATING_POINT_SUPPORTED
-PNG_EXPORT(void,png_set_gamma,(png_structp png_ptr,
-    double screen_gamma, double default_file_gamma),,50);
-#  endif
-/* TODO: png_set_gamma_fixed */
+PNG_FP_EXPORT(void,png_set_gamma,(png_structp png_ptr, double screen_gamma,
+    double default_file_gamma),,50);
+PNG_FIXED_EXPORT(void,png_set_gamma_fixed,(png_structp png_ptr,
+    png_fixed_point screen_gamma, png_fixed_point default_file_gamma),,208);
 #endif
 
 
@@ -1124,8 +1154,8 @@
 PNG_EXPORT(void,png_start_read_image,(png_structp png_ptr),,53);
 
 /* Optional call to update the users info structure */
-PNG_EXPORT(void,png_read_update_info,(png_structp png_ptr,
-    png_infop info_ptr),,54);
+PNG_EXPORT(void,png_read_update_info,(png_structp png_ptr, png_infop info_ptr),,
+    54);
 
 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED
 /* Read one or more rows of image data. */
@@ -1141,29 +1171,25 @@
 
 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED
 /* Read the whole image into memory at once. */
-PNG_EXPORT(void,png_read_image,(png_structp png_ptr,
-    png_bytepp image),,57);
+PNG_EXPORT(void,png_read_image,(png_structp png_ptr, png_bytepp image),,57);
 #endif
 
 /* Write a row of image data */
 PNG_EXPORT(void,png_write_row,(png_structp png_ptr, png_bytep row),,58);
 
 /* Write a few rows of image data */
-PNG_EXPORT(void,png_write_rows,(png_structp png_ptr,
-    png_bytepp row, png_uint_32 num_rows),,59);
+PNG_EXPORT(void,png_write_rows,(png_structp png_ptr, png_bytepp row,
+    png_uint_32 num_rows),,59);
 
 /* Write the image data */
-PNG_EXPORT(void,png_write_image,(png_structp png_ptr,
-    png_bytepp image),,60);
+PNG_EXPORT(void,png_write_image,(png_structp png_ptr, png_bytepp image),,60);
 
 /* Write the end of the PNG file. */
-PNG_EXPORT(void,png_write_end,(png_structp png_ptr,
-    png_infop info_ptr),,61);
+PNG_EXPORT(void,png_write_end,(png_structp png_ptr, png_infop info_ptr),,61);
 
 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED
 /* Read the end of the PNG file. */
-PNG_EXPORT(void,png_read_end,(png_structp png_ptr,
-    png_infop info_ptr),,62);
+PNG_EXPORT(void,png_read_end,(png_structp png_ptr, png_infop info_ptr),,62);
 #endif
 
 /* Free any memory associated with the png_info_struct */
@@ -1179,8 +1205,8 @@
     png_infopp info_ptr_ptr),,65);
 
 /* Set the libpng method of handling chunk CRC errors */
-PNG_EXPORT(void,png_set_crc_action,(png_structp png_ptr,
-    int crit_action, int ancil_action),,66);
+PNG_EXPORT(void,png_set_crc_action,(png_structp png_ptr, int crit_action,
+    int ancil_action),,66);
 
 /* Values for png_set_crc_action() to say how to handle CRC errors in
  * ancillary and critical chunks, and whether to use the data contained
@@ -1209,8 +1235,8 @@
 /* Set the filtering method(s) used by libpng.  Currently, the only valid
  * value for "method" is 0.
  */
-PNG_EXPORT(void,png_set_filter,(png_structp png_ptr, int method,
-    int filters),,67);
+PNG_EXPORT(void,png_set_filter,(png_structp png_ptr, int method, int filters),,
+    67);
 
 /* Flags for png_set_filter() to say which filters to use.  The flags
  * are chosen so that they don't conflict with real filter types
@@ -1265,12 +1291,12 @@
  * the weights and costs are set to 1.0, this degenerates the WEIGHTED method
  * to the UNWEIGHTED method, but with added encoding time/computation.
  */
-#  ifdef PNG_FLOATING_POINT_SUPPORTED
-PNG_EXPORT(void,png_set_filter_heuristics,(png_structp png_ptr,
+PNG_FP_EXPORT(void,png_set_filter_heuristics,(png_structp png_ptr,
     int heuristic_method, int num_weights, png_doublep filter_weights,
     png_doublep filter_costs),,68);
-#  endif
-/* TODO: png_set_filter_heuristics_fixed */
+PNG_FIXED_EXPORT(void,png_set_filter_heuristics_fixed,(png_structp png_ptr,
+    int heuristic_method, int num_weights, png_fixed_point_p filter_weights,
+    png_fixed_point_p filter_costs),,209);
 #endif /*  PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */
 
 /* Heuristic used for row filter selection.  These defines should NOT be
@@ -1288,8 +1314,7 @@
  * for PNG images, and do considerably fewer caclulations.  In the future,
  * these values may not correspond directly to the zlib compression levels.
  */
-PNG_EXPORT(void,png_set_compression_level,(png_structp png_ptr,
-    int level),,69);
+PNG_EXPORT(void,png_set_compression_level,(png_structp png_ptr, int level),,69);
 
 PNG_EXPORT(void,png_set_compression_mem_level,(png_structp png_ptr,
     int mem_level),,70);
@@ -1300,8 +1325,8 @@
 PNG_EXPORT(void,png_set_compression_window_bits,(png_structp png_ptr,
     int window_bits),,72);
 
-PNG_EXPORT(void,png_set_compression_method,(png_structp png_ptr,
-    int method),,73);
+PNG_EXPORT(void,png_set_compression_method,(png_structp png_ptr, int method),,
+    73);
 
 /* These next functions are called for input/output, memory, and error
  * handling.  They are in the file pngrio.c, pngwio.c, and pngerror.c,
@@ -1325,9 +1350,8 @@
  * default function will be used.
  */
 
-PNG_EXPORT(void,png_set_error_fn,(png_structp png_ptr,
-    png_voidp error_ptr, png_error_ptr error_fn,
-    png_error_ptr warning_fn),,75);
+PNG_EXPORT(void,png_set_error_fn,(png_structp png_ptr, png_voidp error_ptr,
+    png_error_ptr error_fn, png_error_ptr warning_fn),,75);
 
 /* Return the user pointer associated with the error functions */
 PNG_EXPORT(png_voidp,png_get_error_ptr,(png_structp png_ptr),,76);
@@ -1342,13 +1366,12 @@
  * default flush function, which uses the standard *FILE structure, will
  * be used.
  */
-PNG_EXPORT(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),,77);
+PNG_EXPORT(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),,77);
 
 /* Replace the default data input function with a user supplied one. */
-PNG_EXPORT(void,png_set_read_fn,(png_structp png_ptr,
-    png_voidp io_ptr, png_rw_ptr read_data_fn),,78);
+PNG_EXPORT(void,png_set_read_fn,(png_structp png_ptr, png_voidp io_ptr,
+    png_rw_ptr read_data_fn),,78);
 
 /* Return the user pointer associated with the I/O functions */
 PNG_EXPORT(png_voidp,png_get_io_ptr,(png_structp png_ptr),,79);
@@ -1361,8 +1384,8 @@
 
 #ifdef PNG_USER_MEM_SUPPORTED
 /* Replace the default memory allocation functions with user supplied one(s). */
-PNG_EXPORT(void,png_set_mem_fn,(png_structp png_ptr,
-    png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn),,82);
+PNG_EXPORT(void,png_set_mem_fn,(png_structp png_ptr, png_voidp mem_ptr,
+    png_malloc_ptr malloc_fn, png_free_ptr free_fn),,82);
 /* Return the user pointer associated with the memory functions */
 PNG_EXPORT(png_voidp,png_get_mem_ptr,(png_structp png_ptr),,83);
 #endif
@@ -1383,8 +1406,7 @@
     png_voidp user_transform_ptr, int user_transform_depth,
     int user_transform_channels),,86);
 /* Return the user pointer associated with the user transform functions */
-PNG_EXPORT(png_voidp,png_get_user_transform_ptr,
-    (png_structp png_ptr),,87);
+PNG_EXPORT(png_voidp,png_get_user_transform_ptr,(png_structp png_ptr),,87);
 #endif
 
 #ifdef PNG_USER_CHUNKS_SUPPORTED
@@ -1405,8 +1427,8 @@
 PNG_EXPORT(png_voidp,png_get_progressive_ptr,(png_structp png_ptr),,91);
 
 /* Function to be called when data becomes available */
-PNG_EXPORT(void,png_process_data,(png_structp png_ptr,
-    png_infop info_ptr, png_bytep buffer, png_size_t buffer_size),,92);
+PNG_EXPORT(void,png_process_data,(png_structp png_ptr, png_infop info_ptr,
+    png_bytep buffer, png_size_t buffer_size),,92);
 
 /* Function that combines rows.  Not very much different than the
  * png_combine_row() call.  Is this even used?????
@@ -1415,11 +1437,11 @@
     png_bytep old_row, png_bytep new_row),,93);
 #endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
 
-PNG_EXPORT(png_voidp,png_malloc,(png_structp png_ptr,
-    png_alloc_size_t size),PNG_ALLOCATED,94);
+PNG_EXPORT(png_voidp,png_malloc,(png_structp png_ptr, png_alloc_size_t size),
+    PNG_ALLOCATED,94);
 /* Added at libpng version 1.4.0 */
-PNG_EXPORT(png_voidp,png_calloc,(png_structp png_ptr,
-    png_alloc_size_t size),PNG_ALLOCATED,95);
+PNG_EXPORT(png_voidp,png_calloc,(png_structp png_ptr, png_alloc_size_t size),
+    PNG_ALLOCATED,95);
 
 /* Added at libpng version 1.2.4 */
 PNG_EXPORT(png_voidp,png_malloc_warn,(png_structp png_ptr,
@@ -1457,14 +1479,13 @@
 #ifdef PNG_USER_MEM_SUPPORTED
 PNG_EXPORT(png_voidp,png_malloc_default,(png_structp png_ptr,
     png_alloc_size_t size),PNG_ALLOCATED,100);
-PNG_EXPORT(void,png_free_default,(png_structp png_ptr,
-    png_voidp ptr),,101);
+PNG_EXPORT(void,png_free_default,(png_structp png_ptr, png_voidp ptr),,101);
 #endif
 
 #ifdef PNG_ERROR_TEXT_SUPPORTED
 /* Fatal error in PNG image of libpng - can't continue */
-PNG_EXPORT(void,png_error,(png_structp png_ptr,
-    png_const_charp error_message),PNG_NORETURN,102);
+PNG_EXPORT(void,png_error,(png_structp png_ptr, png_const_charp error_message),
+    PNG_NORETURN,102);
 
 /* The same, but the chunk name is prepended to the error string. */
 PNG_EXPORT(void,png_chunk_error,(png_structp png_ptr,
@@ -1495,8 +1516,7 @@
 PNG_EXPORT(void,png_chunk_benign_error,(png_structp png_ptr,
     png_const_charp warning_message),,108);
 
-PNG_EXPORT(void,png_set_benign_errors,(png_structp png_ptr,
-    int allowed),,109);
+PNG_EXPORT(void,png_set_benign_errors,(png_structp png_ptr, int allowed),,109);
 #else
 #  ifdef PNG_ALLOW_BENIGN_ERRORS
 #    define png_benign_error png_warning
@@ -1520,8 +1540,8 @@
  * png_info_struct.
  */
 /* Returns "flag" if chunk data is valid in info_ptr. */
-PNG_EXPORT(png_uint_32,png_get_valid,(png_structp png_ptr,
-    png_infop info_ptr, png_uint_32 flag),,110);
+PNG_EXPORT(png_uint_32,png_get_valid,(png_structp png_ptr, png_infop info_ptr,
+    png_uint_32 flag),,110);
 
 /* Returns number of bytes needed to hold a transformed row. */
 PNG_EXPORT(png_size_t,png_get_rowbytes,(png_structp png_ptr,
@@ -1531,8 +1551,8 @@
 /* Returns row_pointers, which is an array of pointers to scanlines that was
  * returned from png_read_png().
  */
-PNG_EXPORT(png_bytepp,png_get_rows,(png_structp png_ptr,
-    png_infop info_ptr),,112);
+PNG_EXPORT(png_bytepp,png_get_rows,(png_structp png_ptr, png_infop info_ptr),,
+    112);
 /* Set row_pointers, which is an array of pointers to scanlines for use
  * by png_write_png().
  */
@@ -1541,62 +1561,61 @@
 #endif
 
 /* Returns number of color channels in image. */
-PNG_EXPORT(png_byte,png_get_channels,(png_structp png_ptr,
-    png_infop info_ptr),,114);
+PNG_EXPORT(png_byte,png_get_channels,(png_structp png_ptr, png_infop info_ptr),,
+    114);
 
 #ifdef PNG_EASY_ACCESS_SUPPORTED
 /* Returns image width in pixels. */
-PNG_EXPORT(png_uint_32, png_get_image_width,(png_structp png_ptr,
+PNG_EXPORT(png_uint_32,png_get_image_width,(png_structp png_ptr,
     png_infop info_ptr),,115);
 
 /* Returns image height in pixels. */
-PNG_EXPORT(png_uint_32, png_get_image_height,(png_structp png_ptr,
+PNG_EXPORT(png_uint_32,png_get_image_height,(png_structp png_ptr,
     png_infop info_ptr),,116);
 
 /* Returns image bit_depth. */
-PNG_EXPORT(png_byte, png_get_bit_depth,(png_structp png_ptr,
-    png_infop info_ptr),,117);
+PNG_EXPORT(png_byte,png_get_bit_depth,(png_structp png_ptr, png_infop info_ptr),
+    ,117);
 
 /* Returns image color_type. */
-PNG_EXPORT(png_byte, png_get_color_type,(png_structp png_ptr,
+PNG_EXPORT(png_byte,png_get_color_type,(png_structp png_ptr,
     png_infop info_ptr),,118);
 
 /* Returns image filter_type. */
-PNG_EXPORT(png_byte, png_get_filter_type,(png_structp png_ptr,
+PNG_EXPORT(png_byte,png_get_filter_type,(png_structp png_ptr,
     png_infop info_ptr),,119);
 
 /* Returns image interlace_type. */
-PNG_EXPORT(png_byte, png_get_interlace_type,(png_structp png_ptr,
+PNG_EXPORT(png_byte,png_get_interlace_type,(png_structp png_ptr,
     png_infop info_ptr),,120);
 
 /* Returns image compression_type. */
-PNG_EXPORT(png_byte, png_get_compression_type,(png_structp png_ptr,
+PNG_EXPORT(png_byte,png_get_compression_type,(png_structp png_ptr,
     png_infop info_ptr),,121);
 
 /* Returns image resolution in pixels per meter, from pHYs chunk data. */
-PNG_EXPORT(png_uint_32, png_get_pixels_per_meter,(png_structp png_ptr,
+PNG_EXPORT(png_uint_32,png_get_pixels_per_meter,(png_structp png_ptr,
     png_infop info_ptr),,122);
-PNG_EXPORT(png_uint_32, png_get_x_pixels_per_meter,
-    (png_structp png_ptr, png_infop info_ptr),,123);
-PNG_EXPORT(png_uint_32, png_get_y_pixels_per_meter,
-    (png_structp png_ptr, png_infop info_ptr),,124);
+PNG_EXPORT(png_uint_32,png_get_x_pixels_per_meter,(png_structp png_ptr,
+    png_infop info_ptr),,123);
+PNG_EXPORT(png_uint_32,png_get_y_pixels_per_meter,(png_structp png_ptr,
+    png_infop info_ptr),,124);
 
 /* Returns pixel aspect ratio, computed from pHYs chunk data.  */
-#  ifdef PNG_FLOATING_POINT_SUPPORTED
-PNG_EXPORT(float, png_get_pixel_aspect_ratio,
-    (png_structp png_ptr, png_infop info_ptr),,125);
-#  endif
-/* TODO: png_get_pixel_aspect_ratio_fixed */
+PNG_FP_EXPORT(float,png_get_pixel_aspect_ratio,(png_structp png_ptr,
+    png_infop info_ptr),,125);
+PNG_FIXED_EXPORT(png_fixed_point,png_get_pixel_aspect_ratio_fixed,
+    (png_structp png_ptr, png_infop info_ptr),,210);
 
 /* Returns image x, y offset in pixels or microns, from oFFs chunk data. */
-PNG_EXPORT(png_int_32, png_get_x_offset_pixels,
-    (png_structp png_ptr, png_infop info_ptr),,126);
-PNG_EXPORT(png_int_32, png_get_y_offset_pixels,
-    (png_structp png_ptr, png_infop info_ptr),,127);
-PNG_EXPORT(png_int_32, png_get_x_offset_microns,
-    (png_structp png_ptr, png_infop info_ptr),,128);
-PNG_EXPORT(png_int_32, png_get_y_offset_microns,
-    (png_structp png_ptr, png_infop info_ptr),,129);
+PNG_EXPORT(png_int_32,png_get_x_offset_pixels,(png_structp png_ptr,
+    png_infop info_ptr),,126);
+PNG_EXPORT(png_int_32,png_get_y_offset_pixels,(png_structp png_ptr,
+    png_infop info_ptr),,127);
+PNG_EXPORT(png_int_32,png_get_x_offset_microns,(png_structp png_ptr,
+    png_infop info_ptr),,128);
+PNG_EXPORT(png_int_32, png_get_y_offset_microns,(png_structp png_ptr,
+    png_infop info_ptr),,129);
 
 #endif /* PNG_EASY_ACCESS_SUPPORTED */
 
@@ -1605,183 +1624,160 @@
     png_infop info_ptr),,130);
 
 #ifdef PNG_bKGD_SUPPORTED
-PNG_EXPORT(png_uint_32,png_get_bKGD,(png_structp png_ptr,
-    png_infop info_ptr, png_color_16p *background),,131);
+PNG_EXPORT(png_uint_32,png_get_bKGD,(png_structp png_ptr, png_infop info_ptr,
+    png_color_16p *background),,131);
 #endif
 
 #ifdef PNG_bKGD_SUPPORTED
-PNG_EXPORT(void,png_set_bKGD,(png_structp png_ptr,
-    png_infop info_ptr, png_color_16p background),,132);
+PNG_EXPORT(void,png_set_bKGD,(png_structp png_ptr, png_infop info_ptr,
+    png_color_16p background),,132);
 #endif
 
 #ifdef PNG_cHRM_SUPPORTED
-#  ifdef PNG_FLOATING_POINT_SUPPORTED
-PNG_EXPORT(png_uint_32,png_get_cHRM,(png_structp png_ptr,
-    png_infop info_ptr, double *white_x, double *white_y,
-    double *red_x, double *red_y, double *green_x, double *green_y,
-    double *blue_x, double *blue_y),,133);
-#  endif
-#  ifdef PNG_FIXED_POINT_SUPPORTED
-PNG_EXPORT(png_uint_32,png_get_cHRM_fixed,(png_structp png_ptr,
-    png_infop info_ptr,
-    png_fixed_point *int_white_x, png_fixed_point *int_white_y,
-    png_fixed_point *int_red_x, png_fixed_point *int_red_y,
-    png_fixed_point *int_green_x, png_fixed_point *int_green_y,
-    png_fixed_point *int_blue_x, png_fixed_point *int_blue_y),,134);
-#  endif
+PNG_FP_EXPORT(png_uint_32,png_get_cHRM,(png_structp png_ptr,
+    png_infop info_ptr, double *white_x, double *white_y, double *red_x,
+    double *red_y, double *green_x, double *green_y, double *blue_x,
+    double *blue_y),,133);
+#ifdef PNG_FIXED_POINT_SUPPORTED /* Otherwise not implemented */
+PNG_FIXED_EXPORT(png_uint_32,png_get_cHRM_fixed,(png_structp png_ptr,
+    png_infop info_ptr, png_fixed_point *int_white_x,
+    png_fixed_point *int_white_y, png_fixed_point *int_red_x,
+    png_fixed_point *int_red_y, png_fixed_point *int_green_x,
+    png_fixed_point *int_green_y, png_fixed_point *int_blue_x,
+    png_fixed_point *int_blue_y),,134);
+#endif
 #endif
 
 #ifdef PNG_cHRM_SUPPORTED
-#  ifdef PNG_FLOATING_POINT_SUPPORTED
-PNG_EXPORT(void,png_set_cHRM,(png_structp png_ptr,
-    png_infop info_ptr, double white_x, double white_y,
-    double red_x, double red_y, double green_x, double green_y,
-    double blue_x, double blue_y),,135);
-#  endif
-#  ifdef PNG_FIXED_POINT_SUPPORTED
-PNG_EXPORT(void,png_set_cHRM_fixed,(png_structp png_ptr,
-    png_infop info_ptr,
-    png_fixed_point int_white_x, png_fixed_point int_white_y,
-    png_fixed_point int_red_x, png_fixed_point int_red_y,
-    png_fixed_point int_green_x, png_fixed_point int_green_y,
-    png_fixed_point int_blue_x, png_fixed_point int_blue_y),,136);
-#  endif
+PNG_FP_EXPORT(void,png_set_cHRM,(png_structp png_ptr, png_infop info_ptr,
+    double white_x, double white_y, double red_x, double red_y, double green_x,
+    double green_y, double blue_x, double blue_y),,135);
+PNG_FIXED_EXPORT(void,png_set_cHRM_fixed,(png_structp png_ptr,
+    png_infop info_ptr, png_fixed_point int_white_x,
+    png_fixed_point int_white_y, png_fixed_point int_red_x,
+    png_fixed_point int_red_y, png_fixed_point int_green_x,
+    png_fixed_point int_green_y, png_fixed_point int_blue_x,
+    png_fixed_point int_blue_y),,136);
 #endif
 
 #ifdef PNG_gAMA_SUPPORTED
-#  ifdef PNG_FLOATING_POINT_SUPPORTED
-PNG_EXPORT(png_uint_32,png_get_gAMA,(png_structp png_ptr,
-    png_infop info_ptr, double *file_gamma),,137);
-#  endif
-#  ifdef PNG_FIXED_POINT_SUPPORTED
-PNG_EXPORT(png_uint_32,png_get_gAMA_fixed,(png_structp png_ptr,
+PNG_FP_EXPORT(png_uint_32,png_get_gAMA,(png_structp png_ptr, png_infop info_ptr,
+    double *file_gamma),,137);
+PNG_FIXED_EXPORT(png_uint_32,png_get_gAMA_fixed,(png_structp png_ptr,
     png_infop info_ptr, png_fixed_point *int_file_gamma),,138);
-#  endif
 #endif
 
 #ifdef PNG_gAMA_SUPPORTED
-#  ifdef PNG_FLOATING_POINT_SUPPORTED
-PNG_EXPORT(void,png_set_gAMA,(png_structp png_ptr,
-    png_infop info_ptr, double file_gamma),,139);
-#  endif
-#  ifdef PNG_FIXED_POINT_SUPPORTED
-PNG_EXPORT(void,png_set_gAMA_fixed,(png_structp png_ptr,
+PNG_FP_EXPORT(void,png_set_gAMA,(png_structp png_ptr, png_infop info_ptr,
+    double file_gamma),,139);
+PNG_FIXED_EXPORT(void,png_set_gAMA_fixed,(png_structp png_ptr,
     png_infop info_ptr, png_fixed_point int_file_gamma),,140);
-#  endif
 #endif
 
 #ifdef PNG_hIST_SUPPORTED
-PNG_EXPORT(png_uint_32,png_get_hIST,(png_structp png_ptr,
-    png_infop info_ptr, png_uint_16p *hist),,141);
+PNG_EXPORT(png_uint_32,png_get_hIST,(png_structp png_ptr, png_infop info_ptr,
+    png_uint_16p *hist),,141);
 #endif
 
 #ifdef PNG_hIST_SUPPORTED
-PNG_EXPORT(void,png_set_hIST,(png_structp png_ptr,
-    png_infop info_ptr, png_uint_16p hist),,142);
+PNG_EXPORT(void,png_set_hIST,(png_structp png_ptr, png_infop info_ptr,
+    png_uint_16p hist),,142);
 #endif
 
-PNG_EXPORT(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_method,
-    int *compression_method, int *filter_method),,143);
+PNG_EXPORT(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_method, int *compression_method, int *filter_method),,143);
 
-PNG_EXPORT(void,png_set_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_method, int compression_method,
-    int filter_method),,144);
+PNG_EXPORT(void,png_set_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_method, int compression_method, int filter_method),,144);
 
 #ifdef PNG_oFFs_SUPPORTED
-PNG_EXPORT(png_uint_32,png_get_oFFs,(png_structp png_ptr,
-    png_infop info_ptr, png_int_32 *offset_x, png_int_32 *offset_y,
-    int *unit_type),,145);
+PNG_EXPORT(png_uint_32,png_get_oFFs,(png_structp png_ptr, png_infop info_ptr,
+    png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type),,145);
 #endif
 
 #ifdef PNG_oFFs_SUPPORTED
-PNG_EXPORT(void,png_set_oFFs,(png_structp png_ptr,
-    png_infop info_ptr, png_int_32 offset_x, png_int_32 offset_y,
-    int unit_type),,146);
+PNG_EXPORT(void,png_set_oFFs,(png_structp png_ptr, png_infop info_ptr,
+    png_int_32 offset_x, png_int_32 offset_y, int unit_type),,146);
 #endif
 
 #ifdef PNG_pCAL_SUPPORTED
-PNG_EXPORT(png_uint_32,png_get_pCAL,(png_structp png_ptr,
-    png_infop info_ptr, png_charp *purpose, png_int_32 *X0, png_int_32 *X1,
-    int *type, int *nparams, png_charp *units, png_charpp *params),,147);
+PNG_EXPORT(png_uint_32,png_get_pCAL,(png_structp png_ptr, png_infop info_ptr,
+    png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type, int *nparams,
+    png_charp *units, png_charpp *params),,147);
 #endif
 
 #ifdef PNG_pCAL_SUPPORTED
-PNG_EXPORT(void,png_set_pCAL,(png_structp png_ptr,
-    png_infop info_ptr, png_charp purpose, png_int_32 X0, png_int_32 X1,
-    int type, int nparams, png_charp units, png_charpp params),,148);
+PNG_EXPORT(void,png_set_pCAL,(png_structp png_ptr, png_infop info_ptr,
+    png_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams,
+    png_charp units, png_charpp params),,148);
 #endif
 
 #ifdef PNG_pHYs_SUPPORTED
-PNG_EXPORT(png_uint_32,png_get_pHYs,(png_structp png_ptr,
-    png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y,
-    int *unit_type),,149);
+PNG_EXPORT(png_uint_32,png_get_pHYs,(png_structp png_ptr, png_infop info_ptr,
+    png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type),,149);
 #endif
 
 #ifdef PNG_pHYs_SUPPORTED
-PNG_EXPORT(void,png_set_pHYs,(png_structp png_ptr,
-    png_infop info_ptr, png_uint_32 res_x, png_uint_32 res_y,
-    int unit_type),,150);
+PNG_EXPORT(void,png_set_pHYs,(png_structp png_ptr, png_infop info_ptr,
+    png_uint_32 res_x, png_uint_32 res_y, int unit_type),,150);
 #endif
 
-PNG_EXPORT(png_uint_32,png_get_PLTE,(png_structp png_ptr,
-    png_infop info_ptr, png_colorp *palette, int *num_palette),,151);
+PNG_EXPORT(png_uint_32,png_get_PLTE,(png_structp png_ptr, png_infop info_ptr,
+    png_colorp *palette, int *num_palette),,151);
 
-PNG_EXPORT(void,png_set_PLTE,(png_structp png_ptr,
-    png_infop info_ptr, png_colorp palette, int num_palette),,152);
+PNG_EXPORT(void,png_set_PLTE,(png_structp png_ptr, png_infop info_ptr,
+    png_colorp palette, int num_palette),,152);
 
 #ifdef PNG_sBIT_SUPPORTED
-PNG_EXPORT(png_uint_32,png_get_sBIT,(png_structp png_ptr,
-    png_infop info_ptr, png_color_8p *sig_bit),,153);
+PNG_EXPORT(png_uint_32,png_get_sBIT,(png_structp png_ptr, png_infop info_ptr,
+    png_color_8p *sig_bit),,153);
 #endif
 
 #ifdef PNG_sBIT_SUPPORTED
-PNG_EXPORT(void,png_set_sBIT,(png_structp png_ptr,
-    png_infop info_ptr, png_color_8p sig_bit),,154);
+PNG_EXPORT(void,png_set_sBIT,(png_structp png_ptr, png_infop info_ptr,
+    png_color_8p sig_bit),,154);
 #endif
 
 #ifdef PNG_sRGB_SUPPORTED
-PNG_EXPORT(png_uint_32,png_get_sRGB,(png_structp png_ptr,
-    png_infop info_ptr, int *intent),,155);
+PNG_EXPORT(png_uint_32,png_get_sRGB,(png_structp png_ptr, png_infop info_ptr,
+    int *intent),,155);
 #endif
 
 #ifdef PNG_sRGB_SUPPORTED
-PNG_EXPORT(void,png_set_sRGB,(png_structp png_ptr,
-    png_infop info_ptr, int intent),,156);
+PNG_EXPORT(void,png_set_sRGB,(png_structp png_ptr, png_infop info_ptr,
+    int intent),,156);
 PNG_EXPORT(void,png_set_sRGB_gAMA_and_cHRM,(png_structp png_ptr,
     png_infop info_ptr, int intent),,157);
 #endif
 
 #ifdef PNG_iCCP_SUPPORTED
-PNG_EXPORT(png_uint_32,png_get_iCCP,(png_structp png_ptr,
-    png_infop info_ptr, png_charpp name, int *compression_type,
-    png_charpp profile, png_uint_32 *proflen),,158);
-    /* Note to maintainer: profile should be png_bytepp */
+PNG_EXPORT(png_uint_32,png_get_iCCP,(png_structp png_ptr, png_infop info_ptr,
+    png_charpp name, int *compression_type, png_bytepp profile,
+    png_uint_32 *proflen),,158);
 #endif
 
 #ifdef PNG_iCCP_SUPPORTED
-PNG_EXPORT(void,png_set_iCCP,(png_structp png_ptr,
-    png_infop info_ptr, png_charp name, int compression_type,
-    png_charp profile, png_uint_32 proflen),,159);
-    /* Note to maintainer: profile should be png_bytep */
+PNG_EXPORT(void,png_set_iCCP,(png_structp png_ptr, png_infop info_ptr,
+    png_charp name, int compression_type, png_bytep profile,
+    png_uint_32 proflen),,159);
 #endif
 
 #ifdef PNG_sPLT_SUPPORTED
-PNG_EXPORT(png_uint_32,png_get_sPLT,(png_structp png_ptr,
-    png_infop info_ptr, png_sPLT_tpp entries),,160);
+PNG_EXPORT(png_uint_32,png_get_sPLT,(png_structp png_ptr, png_infop info_ptr,
+    png_sPLT_tpp entries),,160);
 #endif
 
 #ifdef PNG_sPLT_SUPPORTED
-PNG_EXPORT(void,png_set_sPLT,(png_structp png_ptr,
-    png_infop info_ptr, png_sPLT_tp entries, int nentries),,161);
+PNG_EXPORT(void,png_set_sPLT,(png_structp png_ptr, png_infop info_ptr,
+    png_sPLT_tp entries, int nentries),,161);
 #endif
 
 #ifdef PNG_TEXT_SUPPORTED
 /* png_get_text also returns the number of text chunks in *num_text */
-PNG_EXPORT(png_uint_32,png_get_text,(png_structp png_ptr,
-    png_infop info_ptr, png_textp *text_ptr, int *num_text),,162);
+PNG_EXPORT(png_uint_32,png_get_text,(png_structp png_ptr, png_infop info_ptr,
+    png_textp *text_ptr, int *num_text),,162);
 #endif
 
 /* Note while png_set_text() will accept a structure whose text,
@@ -1792,55 +1788,47 @@
  */
 
 #ifdef PNG_TEXT_SUPPORTED
-PNG_EXPORT(void,png_set_text,(png_structp png_ptr,
-    png_infop info_ptr, png_textp text_ptr, int num_text),,163);
+PNG_EXPORT(void,png_set_text,(png_structp png_ptr, png_infop info_ptr,
+    png_textp text_ptr, int num_text),,163);
 #endif
 
 #ifdef PNG_tIME_SUPPORTED
-PNG_EXPORT(png_uint_32,png_get_tIME,(png_structp png_ptr,
-    png_infop info_ptr, png_timep *mod_time),,164);
+PNG_EXPORT(png_uint_32,png_get_tIME,(png_structp png_ptr, png_infop info_ptr,
+    png_timep *mod_time),,164);
 #endif
 
 #ifdef PNG_tIME_SUPPORTED
-PNG_EXPORT(void,png_set_tIME,(png_structp png_ptr,
-    png_infop info_ptr, png_timep mod_time),,165);
+PNG_EXPORT(void,png_set_tIME,(png_structp png_ptr, png_infop info_ptr,
+    png_timep mod_time),,165);
 #endif
 
 #ifdef PNG_tRNS_SUPPORTED
-PNG_EXPORT(png_uint_32,png_get_tRNS,(png_structp png_ptr,
-    png_infop info_ptr, png_bytep *trans_alpha, int *num_trans,
-    png_color_16p *trans_color),,166);
+PNG_EXPORT(png_uint_32,png_get_tRNS,(png_structp png_ptr, png_infop info_ptr,
+    png_bytep *trans_alpha, int *num_trans, png_color_16p *trans_color),,166);
 #endif
 
 #ifdef PNG_tRNS_SUPPORTED
-PNG_EXPORT(void,png_set_tRNS,(png_structp png_ptr,
-    png_infop info_ptr, png_bytep trans_alpha, int num_trans,
-    png_color_16p trans_color),,167);
+PNG_EXPORT(void,png_set_tRNS,(png_structp png_ptr, png_infop info_ptr,
+    png_bytep trans_alpha, int num_trans, png_color_16p trans_color),,167);
 #endif
 
 #ifdef PNG_sCAL_SUPPORTED
-#  ifdef PNG_FLOATING_POINT_SUPPORTED
-PNG_EXPORT(png_uint_32,png_get_sCAL,(png_structp png_ptr,
-    png_infop info_ptr, int *unit, double *width, double *height),,168);
-#  endif
-#  ifdef PNG_FIXED_POINT_SUPPORTED
+PNG_FP_EXPORT(png_uint_32,png_get_sCAL,(png_structp png_ptr, png_infop info_ptr,
+    int *unit, double *width, double *height),,168);
+PNG_FIXED_EXPORT(png_uint_32,png_get_sCAL_fixed,(png_structp png_ptr,
+    png_infop info_ptr, int *unit, png_fixed_point *width,
+    png_fixed_point *height),,214);
 PNG_EXPORT(png_uint_32,png_get_sCAL_s,(png_structp png_ptr,
-    png_infop info_ptr, int *unit, png_charpp swidth,
-    png_charpp sheight),,169);
-#  endif
-#endif /* PNG_sCAL_SUPPORTED */
+    png_infop info_ptr, int *unit, png_charpp swidth, png_charpp sheight),,169);
 
-#ifdef PNG_sCAL_SUPPORTED
-#  ifdef PNG_FLOATING_POINT_SUPPORTED
-PNG_EXPORT(void,png_set_sCAL,(png_structp png_ptr,
-    png_infop info_ptr, int unit, double width, double height),,170);
-#  endif
-#  ifdef PNG_FIXED_POINT_SUPPORTED
-PNG_EXPORT(void,png_set_sCAL_s,(png_structp png_ptr,
-    png_infop info_ptr, int unit, png_charp swidth,
-    png_charp sheight),,171);
-#  endif
-#endif /* PNG_sCAL_SUPPORTED || PNG_WRITE_sCAL_SUPPORTED */
+PNG_FP_EXPORT(void,png_set_sCAL,(png_structp png_ptr, png_infop info_ptr,
+    int unit, double width, double height),,170);
+PNG_FIXED_EXPORT(void,png_set_sCAL_fixed,(png_structp png_ptr,
+   png_infop info_ptr, int unit, png_fixed_point width,
+   png_fixed_point height), ,213);
+PNG_EXPORT(void,png_set_sCAL_s,(png_structp png_ptr, png_infop info_ptr,
+    int unit, png_charp swidth, png_charp sheight),,171);
+#endif /* PNG_sCAL_SUPPORTED */
 
 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
 /* Provide a list of chunks and how they are to be handled, if the built-in
@@ -1852,18 +1840,16 @@
            = 2: keep only if safe-to-copy
            = 3: keep even if unsafe-to-copy
 */
-PNG_EXPORT(void, png_set_keep_unknown_chunks,(png_structp png_ptr,
-    int keep, png_bytep chunk_list, int num_chunks),,172);
+PNG_EXPORT(void, png_set_keep_unknown_chunks,(png_structp png_ptr, int keep,
+    png_bytep chunk_list, int num_chunks),,172);
 PNG_EXPORT(int,png_handle_as_unknown,(png_structp png_ptr,
-    png_bytep chunk_name),,173);
+    png_const_bytep chunk_name),,173);
 #endif
 #ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
 PNG_EXPORT(void, png_set_unknown_chunks,(png_structp png_ptr,
-    png_infop info_ptr, png_unknown_chunkp unknowns,
-    int num_unknowns),,174);
-PNG_EXPORT(void, png_set_unknown_chunk_location,
-    (png_structp png_ptr, png_infop info_ptr, int chunk,
-    int location),,175);
+    png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns),,174);
+PNG_EXPORT(void, png_set_unknown_chunk_location, (png_structp png_ptr,
+    png_infop info_ptr, int chunk, int location),,175);
 PNG_EXPORT(png_uint_32,png_get_unknown_chunks,(png_structp png_ptr,
     png_infop info_ptr, png_unknown_chunkpp entries),,176);
 #endif
@@ -1872,15 +1858,15 @@
  * If you need to turn it off for a chunk that your application has freed,
  * you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK);
  */
-PNG_EXPORT(void, png_set_invalid,(png_structp png_ptr,
-    png_infop info_ptr, int mask),,177);
+PNG_EXPORT(void, png_set_invalid,(png_structp png_ptr, png_infop info_ptr,
+    int mask),,177);
 
 #ifdef PNG_INFO_IMAGE_SUPPORTED
 /* The "params" pointer is currently not used and is for future expansion. */
-PNG_EXPORT(void, png_read_png,(png_structp png_ptr,
-    png_infop info_ptr, int transforms, png_voidp params),,178);
-PNG_EXPORT(void, png_write_png,(png_structp png_ptr,
-    png_infop info_ptr, int transforms, png_voidp params),,179);
+PNG_EXPORT(void, png_read_png,(png_structp png_ptr, png_infop info_ptr,
+    int transforms, png_voidp params),,178);
+PNG_EXPORT(void, png_write_png,(png_structp png_ptr, png_infop info_ptr,
+    int transforms, png_voidp params),,179);
 #endif
 
 PNG_EXPORT(png_charp,png_get_copyright,(png_structp png_ptr),,180);
@@ -1911,23 +1897,20 @@
 #ifdef PNG_SET_USER_LIMITS_SUPPORTED
 PNG_EXPORT(void,png_set_user_limits,(png_structp png_ptr,
     png_uint_32 user_width_max, png_uint_32 user_height_max),,186);
-PNG_EXPORT(png_uint_32,png_get_user_width_max,
-    (png_structp png_ptr),,187);
-PNG_EXPORT(png_uint_32,png_get_user_height_max,
-    (png_structp png_ptr),,188);
+PNG_EXPORT(png_uint_32,png_get_user_width_max,(png_structp png_ptr),,187);
+PNG_EXPORT(png_uint_32,png_get_user_height_max,(png_structp png_ptr),,188);
 /* Added in libpng-1.4.0 */
 PNG_EXPORT(void,png_set_chunk_cache_max,(png_structp png_ptr,
     png_uint_32 user_chunk_cache_max),,189);
-PNG_EXPORT(png_uint_32,png_get_chunk_cache_max,
-    (png_structp png_ptr),,190);
+PNG_EXPORT(png_uint_32,png_get_chunk_cache_max,(png_structp png_ptr),,190);
 /* Added in libpng-1.4.1 */
 PNG_EXPORT(void,png_set_chunk_malloc_max,(png_structp png_ptr,
     png_alloc_size_t user_chunk_cache_max),,191);
-PNG_EXPORT(png_alloc_size_t,png_get_chunk_malloc_max,
-    (png_structp png_ptr),,192);
+PNG_EXPORT(png_alloc_size_t,png_get_chunk_malloc_max,(png_structp png_ptr),,
+    192);
 #endif
 
-#if defined(PNG_INCH_CONVERSIONS_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
+#if defined(PNG_INCH_CONVERSIONS_SUPPORTED)
 PNG_EXPORT(png_uint_32,png_get_pixels_per_inch,(png_structp png_ptr,
     png_infop info_ptr),,193);
 
@@ -1937,18 +1920,26 @@
 PNG_EXPORT(png_uint_32,png_get_y_pixels_per_inch,(png_structp png_ptr,
     png_infop info_ptr),,195);
 
-PNG_EXPORT(float,png_get_x_offset_inches,(png_structp png_ptr,
+PNG_FP_EXPORT(float,png_get_x_offset_inches,(png_structp png_ptr,
     png_infop info_ptr),,196);
+#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */
+PNG_FIXED_EXPORT(png_fixed_point,png_get_x_offset_inches_fixed,
+    (png_structp png_ptr, png_infop info_ptr),,211);
+#endif
 
-PNG_EXPORT(float,png_get_y_offset_inches,(png_structp png_ptr,
+PNG_FP_EXPORT(float,png_get_y_offset_inches,(png_structp png_ptr,
     png_infop info_ptr),,197);
+#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */
+PNG_FIXED_EXPORT(png_fixed_point,png_get_y_offset_inches_fixed,
+    (png_structp png_ptr, png_infop info_ptr),,212);
+#endif
 
 #  ifdef PNG_pHYs_SUPPORTED
 PNG_EXPORT(png_uint_32,png_get_pHYs_dpi,(png_structp png_ptr,
-    png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y,
-    int *unit_type),,198);
+    png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type),
+    ,198);
 #  endif /* PNG_pHYs_SUPPORTED */
-#endif  /* PNG_INCH_CONVERSIONS_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */
+#endif  /* PNG_INCH_CONVERSIONS_SUPPORTED */
 
 /* Added in libpng-1.4.0 */
 #ifdef PNG_IO_STATE_SUPPORTED
@@ -1968,10 +1959,6 @@
 #  define PNG_IO_MASK_LOC    0x00f0   /* current location: sig/hdr/data/crc */
 #endif /* ?PNG_IO_STATE_SUPPORTED */
 
-/* Maintainer: Put new public prototypes here ^, in libpng.3, and project
- * defs
- */
-
 #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
@@ -2027,25 +2014,20 @@
 #  define png_get_uint_16(buf) \
      (((png_uint_32)(*(buf)) << 8) + \
       ((png_uint_32)(*((buf) + 1))))
-#  ifdef PNG_GET_INT_32_SUPPORTED
-#    define png_get_int_32(buf) \
-     (((png_int_32)(*(buf)) << 24) + \
-      ((png_int_32)(*((buf) + 1)) << 16) + \
-      ((png_int_32)(*((buf) + 2)) << 8) + \
-      ((png_int_32)(*((buf) + 3))))
-#  endif
+#  define png_get_int_32(buf) \
+     ((png_int_32)((*(buf) & 0x80) \
+      ? -((png_get_uint_32(buf) ^ 0xffffffff)+1) \
+      : png_get_uint_32(buf)))
 #endif
 
 #ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED
 PNG_EXPORT(png_uint_32,png_get_uint_32,(png_bytep buf),,201);
 PNG_EXPORT(png_uint_16,png_get_uint_16,(png_bytep buf),,202);
-#endif
-#ifdef PNG_GET_INT_32_SUPPORTED
 PNG_EXPORT(png_int_32,png_get_int_32,(png_bytep buf),,203);
 #endif
 
-PNG_EXPORT(png_uint_32,png_get_uint_31,(png_structp png_ptr,
-    png_bytep buf),,204);
+PNG_EXPORT(png_uint_32,png_get_uint_31,(png_structp png_ptr, png_bytep buf),,
+    204);
 /* No png_get_int_16 -- may be added if there's a real need for it. */
 
 /* Place a 32-bit number into a buffer in PNG byte order (big-endian). */
@@ -2065,11 +2047,15 @@
 /* No png_save_int_16 -- may be added if there's a real need for it. */
 #endif
 
+/* Maintainer: Put new public prototypes here ^, in libpng.3, and project
+ * defs
+ */
+
 /* The last ordinal number (this is the *last* one, the next one to
  * use is one more than this.)
  */
 #ifdef PNG_EXPORT_LAST_ORDINAL
-  PNG_EXPORT_LAST_ORDINAL(207);
+  PNG_EXPORT_LAST_ORDINAL(217);
 #endif
 
 #ifdef __cplusplus
diff --git a/pngconf.h b/pngconf.h
index b8fea48..744e6af 100644
--- a/pngconf.h
+++ b/pngconf.h
@@ -1,7 +1,7 @@
 
 /* pngconf.h - machine configurable file for libpng
  *
- * libpng version 1.5.0beta36 - July 24, 2010
+ * libpng version 1.5.0beta36 - July 29, 2010
  *
  * Copyright (c) 1998-2010 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
@@ -22,14 +22,6 @@
 #ifndef PNGCONF_H
 #define PNGCONF_H
 
-/* Need the time information for converting tIME chunks, it
- * defines struct tm:
- */
-#ifdef PNG_CONVERT_tIME_SUPPORTED
-  /* "time.h" functions are not supported on WindowsCE */
-#  include <time.h>
-#endif
-
 /* PNG_NO_LIMITS_H may be used to turn off the use of the standard C
  * definition file for  machine specific limits, this may impact the
  * correctness of the definitons below (see uses of INT_MAX).
@@ -38,6 +30,23 @@
 #  include <limits.h>
 #endif
 
+/* For the memory copy APIs (i.e. the standard definitions of these),
+ * because this file defines png_memcpy and so on the base APIs must
+ * be defined here.
+ */
+#ifdef BSD
+#  include <strings.h>
+#else
+#  include <string.h>
+#endif
+
+/* For png_FILE_p - this provides the standard definition of a
+ * FILE
+ */
+#ifdef PNG_STDIO_SUPPORTED
+#  include <stdio.h>
+#endif
+
 /* This controls optimization of the reading of 16 and 32 bit values
  * from PNG files.  It can be set on a per-app-file basis - it
  * just changes whether a macro is used to the function is called.
@@ -171,9 +180,20 @@
       defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) ) &&\
     ( defined(_X86_) || defined(_X64_) || defined(_M_IX86) ||\
       defined(_M_X64) || defined(_M_IA64) )
-  /* Windows system (DOS doesn't support DLLs) running on x86/x64.
-   * Includes builds under Cygwin or MinGW.
+  /* Windows system (DOS doesn't support DLLs) running on x86/x64.  Includes
+   * builds under Cygwin or MinGW.  Also includes Watcom builds but these need
+   * special treatment because they are not compatible with GCC or Visual C
+   * because of different calling conventions.
    */
+#  if PNG_API_RULE == 2
+    /* If this line results in an error, either because __watcall is not
+     * understood or because of a redefine just below you cannot use *this*
+     * build of the library with the compiler you are using.  *This* build was
+     * build using Watcom and applications must also be built using Watcom!
+     */
+#    define PNGCAPI __watcall
+#  endif
+
 #  if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800))
 #    define PNGCAPI __cdecl
 #    if PNG_API_RULE == 1
@@ -266,7 +286,7 @@
 #endif
 #ifndef PNG_EXPORT
 #  define PNG_EXPORT(type, name, args, attributes, ordinal)\
-     PNG_EXPORT_TYPE(type) (PNGAPI name) PNGARG(args) attributes
+     extern PNG_EXPORT_TYPE(type) (PNGAPI name) PNGARG(args) attributes
 #endif
 
 /* Use PNG_REMOVED to comment out a removed interface. */
@@ -351,6 +371,22 @@
 #ifndef PNG_PRIVATE
 #  define PNG_PRIVATE     /* This is a private libpng function */
 #endif
+#ifndef PNG_FP_EXPORT     /* A floating point API. */
+#  ifdef PNG_FLOATING_POINT_SUPPORTED
+#    define PNG_FP_EXPORT(type, name, args, attributes, ordinal)\
+	PNG_EXPORT(type, name, args, attributes, ordinal)
+#  else                   /* No floating point APIs */
+#    define PNG_FP_EXPORT(type, name, args, attributes, ordinal)
+#  endif
+#endif
+#ifndef PNG_FIXED_EXPORT  /* A fixed point API. */
+#  ifdef PNG_FIXED_POINT_SUPPORTED
+#    define PNG_FIXED_EXPORT(type, name, args, attributes, ordinal)\
+	PNG_EXPORT(type, name, args, attributes, ordinal)
+#  else                   /* No fixed point APIs */
+#    define PNG_FIXED_EXPORT(type, name, args, attributes, ordinal)
+#  endif
+#endif
 
 /* The following uses const char * instead of char * for error
  * and warning message functions, so some compilers won't complain.
@@ -454,20 +490,22 @@
 #endif
 
 /* Typedef for floating-point numbers that are converted
- * to fixed-point with a multiple of 100,000, e.g., int_gamma
+ * to fixed-point with a multiple of 100,000, e.g., gamma
  */
 typedef png_int_32 png_fixed_point;
 
 /* Add typedefs for pointers */
-typedef void            FAR * png_voidp;
-typedef png_byte        FAR * png_bytep;
-typedef png_uint_32     FAR * png_uint_32p;
-typedef png_int_32      FAR * png_int_32p;
-typedef png_uint_16     FAR * png_uint_16p;
-typedef png_int_16      FAR * png_int_16p;
-typedef PNG_CONST char  FAR * png_const_charp;
-typedef char            FAR * png_charp;
-typedef png_fixed_point FAR * png_fixed_point_p;
+typedef void               FAR * png_voidp;
+typedef png_byte           FAR * png_bytep;
+typedef PNG_CONST png_byte FAR * png_const_bytep;
+typedef png_uint_32        FAR * png_uint_32p;
+typedef png_int_32         FAR * png_int_32p;
+typedef png_uint_16        FAR * png_uint_16p;
+typedef png_int_16         FAR * png_int_16p;
+typedef PNG_CONST char     FAR * png_const_charp;
+typedef char               FAR * png_charp;
+typedef png_fixed_point    FAR * png_fixed_point_p;
+typedef png_size_t         FAR * png_size_tp;
 
 #ifdef PNG_STDIO_SUPPORTED
 typedef FILE            * png_FILE_p;
@@ -493,81 +531,6 @@
 /* Pointers to pointers to pointers; i.e., pointer to array */
 typedef char            FAR * FAR * FAR * png_charppp;
 
-#define PNG_USE_LOCAL_ARRAYS /* Not used in libpng, defined for legacy apps */
-
-/* Users may want to use these so they are not private.  Any library
- * functions that are passed far data must be model-independent.
- */
-
-/* Memory model/platform independent fns */
-#ifndef PNG_ABORT
-#  ifdef _WINDOWS_
-#    define PNG_ABORT() ExitProcess(0)
-#  else
-#    define PNG_ABORT() abort()
-#  endif
-#endif
-
-#ifdef USE_FAR_KEYWORD
-/* Use this to make far-to-near assignments */
-#  define CHECK   1
-#  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_strncpy _fstrncpy   /* Added to v 1.2.6 */
-#  define png_strlen  _fstrlen
-#  define png_memcmp  _fmemcmp    /* SJT: added */
-#  define png_memcpy  _fmemcpy
-#  define png_memset  _fmemset
-#  define png_sprintf sprintf
-#else
-#  ifdef _WINDOWS_  /* Favor Windows over C runtime fns */
-#    define CVT_PTR(ptr)         (ptr)
-#    define CVT_PTR_NOCHECK(ptr) (ptr)
-#    define png_strcpy  lstrcpyA
-#    define png_strncpy lstrcpynA
-#    define png_strlen  lstrlenA
-#    define png_memcmp  memcmp
-#    define png_memcpy  CopyMemory
-#    define png_memset  memset
-#    define png_sprintf wsprintfA
-#  else
-#    define CVT_PTR(ptr)         (ptr)
-#    define CVT_PTR_NOCHECK(ptr) (ptr)
-#    define png_strcpy  strcpy
-#    define png_strncpy strncpy     /* Added to v 1.2.6 */
-#    define png_strlen  strlen
-#    define png_memcmp  memcmp      /* SJT: added */
-#    define png_memcpy  memcpy
-#    define png_memset  memset
-#    define png_sprintf sprintf
-#  endif
-#endif
-
-#ifndef PNG_NO_SNPRINTF
-#  ifdef _MSC_VER
-#    define png_snprintf _snprintf   /* Added to v 1.2.19 */
-#    define png_snprintf2 _snprintf
-#    define png_snprintf6 _snprintf
-#  else
-#    define png_snprintf snprintf   /* Added to v 1.2.19 */
-#    define png_snprintf2 snprintf
-#    define png_snprintf6 snprintf
-#  endif
-#else
-  /* You don't have or don't want to use snprintf().  Caution: Using
-   * sprintf instead of snprintf exposes your application to accidental
-   * or malevolent buffer overflows.  If you don't have snprintf()
-   * as a general rule you should provide one (you can get one from
-   * Portable OpenSSH).
-   */
-#  define png_snprintf(s1,n,fmt,x1) png_sprintf(s1,fmt,x1)
-#  define png_snprintf2(s1,n,fmt,x1,x2) png_sprintf(s1,fmt,x1,x2)
-#  define png_snprintf6(s1,n,fmt,x1,x2,x3,x4,x5,x6) \
-      png_sprintf(s1,fmt,x1,x2,x3,x4,x5,x6)
-#endif
-
 /* png_alloc_size_t is guaranteed to be no smaller than png_size_t,
  * and no smaller than png_uint_32.  Casts from png_size_t or png_uint_32
  * to png_alloc_size_t are not necessary; in fact, it is recommended
@@ -598,6 +561,5 @@
 #    endif
 #  endif
 #endif
-/* End of memory model/platform independent support */
 
 #endif /* PNGCONF_H */
diff --git a/pngdebug.h b/pngdebug.h
index e3f415d..123113e 100644
--- a/pngdebug.h
+++ b/pngdebug.h
@@ -5,7 +5,7 @@
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
- * Last changed in libpng version 1.5.0 - July 24, 2010
+ * Last changed in libpng version 1.5.0 - July 29, 2010
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
diff --git a/pngerror.c b/pngerror.c
index 635680e..7f1f7b1 100644
--- a/pngerror.c
+++ b/pngerror.c
@@ -1,7 +1,7 @@
 
 /* pngerror.c - stub functions for i/o and memory allocation
  *
- * Last changed in libpng 1.5.0 [July 24, 2010]
+ * Last changed in libpng 1.5.0 [July 29, 2010]
  * Copyright (c) 1998-2010 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -237,6 +237,30 @@
 #endif
 #endif /* PNG_READ_SUPPORTED */
 
+#ifdef PNG_ERROR_TEXT_SUPPORTED
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+void
+png_fixed_error(png_structp png_ptr, png_const_charp name, double value)
+{
+#  define fixed_message "fixed point overflow in "
+#  define fixed_message_ln ((sizeof fixed_message)-1)
+   int  iin;
+   char msg[fixed_message_ln+PNG_MAX_ERROR_TEXT];
+   png_memcpy(msg, fixed_message, fixed_message_ln);
+   iin = 0;
+   if (name != NULL) while (iin < (PNG_MAX_ERROR_TEXT-1) && name[iin] != 0)
+   {
+      msg[fixed_message_ln + iin] = name[iin];
+      ++iin;
+   }
+   msg[fixed_message_ln + iin] = 0;
+   /* To discover 'value' put a breakpoint here: */
+   png_error(png_ptr, msg);
+   value = value; png_ptr = png_ptr; /* Quiet the compiler */
+}
+#endif
+#endif
+
 #ifdef PNG_SETJMP_SUPPORTED
 /* This API only exists if ANSI-C style error handling is used,
  * otherwise it is necessary for png_default_error to be overridden.
diff --git a/pngget.c b/pngget.c
index 1854988..31804f0 100644
--- a/pngget.c
+++ b/pngget.c
@@ -1,7 +1,7 @@
 
 /* pngget.c - retrieval of values from info struct
  *
- * Last changed in libpng 1.4.1 [July 24, 2010]
+ * Last changed in libpng 1.4.1 [July 29, 2010]
  * Copyright (c) 1998-2010 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -254,7 +254,7 @@
 #ifdef PNG_oFFs_SUPPORTED
    if (info_ptr->valid & PNG_INFO_oFFs)
    {
-      png_debug1(1, "in %s retrieval function", "png_get_x_offset_microns");
+      png_debug1(1, "in %s retrieval function", "png_get_x_offset_pixels");
 
       if (info_ptr->offset_unit_type != PNG_OFFSET_PIXEL)
          return (0);
@@ -276,7 +276,7 @@
 #ifdef PNG_oFFs_SUPPORTED
    if (info_ptr->valid & PNG_INFO_oFFs)
    {
-      png_debug1(1, "in %s retrieval function", "png_get_y_offset_microns");
+      png_debug1(1, "in %s retrieval function", "png_get_y_offset_pixels");
 
       if (info_ptr->offset_unit_type != PNG_OFFSET_PIXEL)
          return (0);
@@ -290,42 +290,106 @@
    return (0);
 }
 
-#if defined(PNG_INCH_CONVERSIONS_SUPPORTED) && \
-    defined(PNG_FLOATING_POINT_SUPPORTED)
+#ifdef PNG_INCH_CONVERSIONS_SUPPORTED
+static png_uint_32
+ppi_from_ppm(png_uint_32 ppm)
+{
+#if 0
+   /* The convertion is *(2.54/100), in binary (32 digits):
+    * .00000110100000001001110101001001
+    */
+   png_uint_32 t1001, t1101;
+   ppm >>= 1;                  /* .1 */
+   t1001 = ppm + (ppm >> 3);   /* .1001 */
+   t1101 = t1001 + (ppm >> 1); /* .1101 */
+   ppm >>= 20;                 /* .000000000000000000001 */
+   t1101 += t1101 >> 15;       /* .1101000000000001101 */
+   t1001 >>= 11;               /* .000000000001001 */
+   t1001 += t1001 >> 12;       /* .000000000001001000000001001 */
+   ppm += t1001;               /* .000000000001001000001001001 */
+   ppm += t1101;               /* .110100000001001110101001001 */
+   return (ppm + 16) >> 5;/* .00000110100000001001110101001001 */
+#else
+   /* The argument is a PNG unsigned integer, so it is not permitted
+    * to be bigger than 2^31.
+    */
+   png_fixed_point result;
+   if (ppm <= PNG_UINT_31_MAX && png_muldiv(&result, ppm, 127, 5000))
+      return result;
+
+   /* Overflow. */
+   return 0;
+#endif
+}
+
 png_uint_32 PNGAPI
 png_get_pixels_per_inch(png_structp png_ptr, png_infop info_ptr)
 {
-   return ((png_uint_32)((float)png_get_pixels_per_meter(png_ptr, info_ptr)
-       *.0254 +.5));
+   return ppi_from_ppm(png_get_pixels_per_meter(png_ptr, info_ptr));
 }
 
 png_uint_32 PNGAPI
 png_get_x_pixels_per_inch(png_structp png_ptr, png_infop info_ptr)
 {
-   return ((png_uint_32)((float)png_get_x_pixels_per_meter(png_ptr, info_ptr)
-       *.0254 +.5));
+   return ppi_from_ppm(png_get_x_pixels_per_meter(png_ptr, info_ptr));
 }
 
 png_uint_32 PNGAPI
 png_get_y_pixels_per_inch(png_structp png_ptr, png_infop info_ptr)
 {
-   return ((png_uint_32)((float)png_get_y_pixels_per_meter(png_ptr, info_ptr)
-       *.0254 +.5));
+   return ppi_from_ppm(png_get_y_pixels_per_meter(png_ptr, info_ptr));
 }
 
+#ifdef PNG_FIXED_POINT_SUPPORTED
+static png_fixed_point
+png_fixed_inches_from_microns(png_structp png_ptr, png_int_32 microns)
+{
+   /* Convert from metres * 1,000,000 to inches * 100,000, meters to
+    * inches is simply *(100/2.54), so we want *(10/2.54) == 1000/254.
+    * Notice that this can overflow - a warning is output and 0 is
+    * returned.
+    */
+   return png_muldiv_warn(png_ptr, microns, 500, 127);
+}
+
+png_fixed_point PNGAPI
+png_get_x_offset_inches_fixed(png_structp png_ptr, png_infop info_ptr)
+{
+   return png_fixed_inches_from_microns(png_ptr,
+      png_get_x_offset_microns(png_ptr, info_ptr));
+}
+#endif
+
+#ifdef PNG_FIXED_POINT_SUPPORTED
+png_fixed_point PNGAPI
+png_get_y_offset_inches_fixed(png_structp png_ptr, png_infop info_ptr)
+{
+   return png_fixed_inches_from_microns(png_ptr,
+      png_get_y_offset_microns(png_ptr, info_ptr));
+}
+#endif
+
+#ifdef PNG_FLOATING_POINT_SUPPORTED
 float PNGAPI
 png_get_x_offset_inches(png_structp png_ptr, png_infop info_ptr)
 {
-   return ((float)png_get_x_offset_microns(png_ptr, info_ptr)
-       *.00003937);
+   /* To avoid the overflow do the conversion directly in floating
+    * point.
+    */
+   return png_get_x_offset_microns(png_ptr, info_ptr) * .00003937f;
 }
+#endif
 
+#ifdef PNG_FLOATING_POINT_SUPPORTED
 float PNGAPI
 png_get_y_offset_inches(png_structp png_ptr, png_infop info_ptr)
 {
-   return ((float)png_get_y_offset_microns(png_ptr, info_ptr)
-       *.00003937);
+   /* To avoid the overflow do the conversion directly in floating
+    * point.
+    */
+   return png_get_y_offset_microns(png_ptr, info_ptr) * .00003937f;
 }
+#endif
 
 #ifdef PNG_pHYs_SUPPORTED
 png_uint_32 PNGAPI
@@ -364,7 +428,7 @@
    return (retval);
 }
 #endif /* PNG_pHYs_SUPPORTED */
-#endif  /* PNG_INCH_CONVERSIONS_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */
+#endif  /* PNG_INCH_CONVERSIONS_SUPPORTED */
 
 /* png_get_channels really belongs in here, too, but it's been around longer */
 
@@ -419,26 +483,27 @@
       png_debug1(1, "in %s retrieval function", "cHRM");
 
       if (white_x != NULL)
-         *white_x = (double)info_ptr->x_white;
+         *white_x = png_float(png_ptr, info_ptr->x_white, "cHRM white X");
       if (white_y != NULL)
-         *white_y = (double)info_ptr->y_white;
+         *white_y = png_float(png_ptr, info_ptr->y_white, "cHRM white Y");
       if (red_x != NULL)
-         *red_x = (double)info_ptr->x_red;
+         *red_x = png_float(png_ptr, info_ptr->x_red, "cHRM red X");
       if (red_y != NULL)
-         *red_y = (double)info_ptr->y_red;
+         *red_y = png_float(png_ptr, info_ptr->y_red, "cHRM red Y");
       if (green_x != NULL)
-         *green_x = (double)info_ptr->x_green;
+         *green_x = png_float(png_ptr, info_ptr->x_green, "cHRM green X");
       if (green_y != NULL)
-         *green_y = (double)info_ptr->y_green;
+         *green_y = png_float(png_ptr, info_ptr->y_green, "cHRM green Y");
       if (blue_x != NULL)
-         *blue_x = (double)info_ptr->x_blue;
+         *blue_x = png_float(png_ptr, info_ptr->x_blue, "cHRM blue X");
       if (blue_y != NULL)
-         *blue_y = (double)info_ptr->y_blue;
+         *blue_y = png_float(png_ptr, info_ptr->y_blue, "cHRM blue Y");
       return (PNG_INFO_cHRM);
    }
    return (0);
 }
 #endif
+
 #ifdef PNG_FIXED_POINT_SUPPORTED
 png_uint_32 PNGAPI
 png_get_cHRM_fixed(png_structp png_ptr, png_infop info_ptr,
@@ -451,21 +516,21 @@
    if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
    {
       if (white_x != NULL)
-         *white_x = info_ptr->int_x_white;
+         *white_x = info_ptr->x_white;
       if (white_y != NULL)
-         *white_y = info_ptr->int_y_white;
+         *white_y = info_ptr->y_white;
       if (red_x != NULL)
-         *red_x = info_ptr->int_x_red;
+         *red_x = info_ptr->x_red;
       if (red_y != NULL)
-         *red_y = info_ptr->int_y_red;
+         *red_y = info_ptr->y_red;
       if (green_x != NULL)
-         *green_x = info_ptr->int_x_green;
+         *green_x = info_ptr->x_green;
       if (green_y != NULL)
-         *green_y = info_ptr->int_y_green;
+         *green_y = info_ptr->y_green;
       if (blue_x != NULL)
-         *blue_x = info_ptr->int_x_blue;
+         *blue_x = info_ptr->x_blue;
       if (blue_y != NULL)
-         *blue_y = info_ptr->int_y_blue;
+         *blue_y = info_ptr->y_blue;
       return (PNG_INFO_cHRM);
    }
    return (0);
@@ -474,36 +539,30 @@
 #endif
 
 #ifdef PNG_gAMA_SUPPORTED
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-png_uint_32 PNGAPI
-png_get_gAMA(png_structp png_ptr, png_infop info_ptr, double *file_gamma)
+png_uint_32 PNGFAPI
+png_get_gAMA_fixed(png_structp png_ptr, png_infop info_ptr,
+    png_fixed_point *file_gamma)
 {
    png_debug1(1, "in %s retrieval function", "gAMA");
 
    if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
        && file_gamma != NULL)
    {
-      *file_gamma = (double)info_ptr->gamma;
+      *file_gamma = info_ptr->gamma;
       return (PNG_INFO_gAMA);
    }
+
    return (0);
 }
-#endif
-#ifdef PNG_FIXED_POINT_SUPPORTED
+#ifdef PNG_FLOATING_POINT_SUPPORTED
 png_uint_32 PNGAPI
-png_get_gAMA_fixed(png_structp png_ptr, png_infop info_ptr,
-    png_fixed_point *int_file_gamma)
+png_get_gAMA(png_structp png_ptr, png_infop info_ptr, double *file_gamma)
 {
-   png_debug1(1, "in %s retrieval function", "gAMA");
-
-   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
-       && int_file_gamma != NULL)
-   {
-      *int_file_gamma = info_ptr->int_gamma;
-      return (PNG_INFO_gAMA);
-   }
-
-   return (0);
+   png_fixed_point igamma;
+   png_uint_32 ok = png_get_gAMA_fixed(png_ptr, info_ptr, &igamma);
+   if (ok)
+      *file_gamma = png_float(png_ptr, igamma, "png_get_gAMA");
+   return ok;
 }
 #endif
 #endif
@@ -529,7 +588,7 @@
 png_uint_32 PNGAPI
 png_get_iCCP(png_structp png_ptr, png_infop info_ptr,
     png_charpp name, int *compression_type,
-    png_charpp profile, png_uint_32 *proflen)
+    png_bytepp profile, png_uint_32 *proflen)
 {
    png_debug1(1, "in %s retrieval function", "iCCP");
 
@@ -668,6 +727,25 @@
 #endif
 
 #ifdef PNG_sCAL_SUPPORTED
+#ifdef PNG_FIXED_POINT_SUPPORTED
+png_uint_32 PNGAPI
+png_get_sCAL_fixed(png_structp png_ptr, png_infop info_ptr,
+    int *unit, png_fixed_point *width, png_fixed_point *height)
+{
+   if (png_ptr != NULL && info_ptr != NULL &&
+       (info_ptr->valid & PNG_INFO_sCAL))
+   {
+      *unit = info_ptr->scal_unit;
+      /*TODO: make this work */
+      *width = png_fixed(png_ptr, atof(info_ptr->scal_s_width), "sCAL width");
+      *height = png_fixed(png_ptr, atof(info_ptr->scal_s_height),
+         "sCAL height");
+      return (PNG_INFO_sCAL);
+   }
+
+   return(0);
+}
+#endif
 #ifdef PNG_FLOATING_POINT_SUPPORTED
 png_uint_32 PNGAPI
 png_get_sCAL(png_structp png_ptr, png_infop info_ptr,
@@ -677,15 +755,14 @@
        (info_ptr->valid & PNG_INFO_sCAL))
    {
       *unit = info_ptr->scal_unit;
-      *width = info_ptr->scal_pixel_width;
-      *height = info_ptr->scal_pixel_height;
+      *width = atof(info_ptr->scal_s_width);
+      *height = atof(info_ptr->scal_s_height);
       return (PNG_INFO_sCAL);
    }
 
    return(0);
 }
 #endif
-#ifdef PNG_FIXED_POINT_SUPPORTED
 png_uint_32 PNGAPI
 png_get_sCAL_s(png_structp png_ptr, png_infop info_ptr,
              int *unit, png_charpp width, png_charpp height)
@@ -702,7 +779,6 @@
    return(0);
 }
 #endif
-#endif
 
 #ifdef PNG_pHYs_SUPPORTED
 png_uint_32 PNGAPI
diff --git a/pnginfo.h b/pnginfo.h
index a5d02f4..d929ede 100644
--- a/pnginfo.h
+++ b/pnginfo.h
@@ -5,7 +5,7 @@
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
- * Last changed in libpng version 1.5.0 - July 24, 2010
+ * Last changed in libpng version 1.5.0 - July 29, 2010
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
@@ -82,12 +82,12 @@
     * and initialize the appropriate fields below.
     */
 
-#if defined(PNG_gAMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
+#if defined(PNG_gAMA_SUPPORTED)
    /* The gAMA chunk describes the gamma characteristics of the system
     * on which the image was created, normally in the range [1.0, 2.5].
     * Data is valid if (valid & PNG_INFO_gAMA) is non-zero.
     */
-   float gamma; /* gamma value of image, if (valid & PNG_INFO_gAMA) */
+   png_fixed_point gamma;
 #endif
 
 #ifdef PNG_sRGB_SUPPORTED
@@ -191,16 +191,14 @@
     * colors in the image as the creator.  Values are in the range
     * [0.0, 0.8].  Data valid if (valid & PNG_INFO_cHRM) non-zero.
     */
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-   float x_white;
-   float y_white;
-   float x_red;
-   float y_red;
-   float x_green;
-   float y_green;
-   float x_blue;
-   float y_blue;
-#endif
+   png_fixed_point x_white;
+   png_fixed_point y_white;
+   png_fixed_point x_red;
+   png_fixed_point y_red;
+   png_fixed_point x_green;
+   png_fixed_point y_green;
+   png_fixed_point x_blue;
+   png_fixed_point y_blue;
 #endif
 
 #ifdef PNG_pCAL_SUPPORTED
@@ -237,8 +235,7 @@
 #ifdef PNG_iCCP_SUPPORTED
    /* iCCP chunk data. */
    png_charp iccp_name;     /* profile name */
-   png_charp iccp_profile;  /* International Color Consortium profile data */
-                            /* Note to maintainer: should be png_bytep */
+   png_bytep iccp_profile;  /* International Color Consortium profile data */
    png_uint_32 iccp_proflen;  /* ICC profile data length */
    png_byte iccp_compression; /* Always zero */
 #endif
@@ -254,19 +251,13 @@
     * subject matter of the graphic.  The chunk contains a unit specification
     * a byte value, and two ASCII strings representing floating-point
     * values.  The values are width and height corresponsing to one pixel
-    * in the image.  This external representation is converted to double
-    * here.  Data values are valid if (valid & PNG_INFO_sCAL) is non-zero.
+    * in the image.  Data values are valid if (valid & PNG_INFO_sCAL) is
+    * non-zero.
     */
    png_byte scal_unit;         /* unit of physical scale */
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-   double scal_pixel_width;    /* width of one pixel */
-   double scal_pixel_height;   /* height of one pixel */
-#endif
-#ifdef PNG_FIXED_POINT_SUPPORTED
    png_charp scal_s_width;     /* string containing height */
    png_charp scal_s_height;    /* string containing width */
 #endif
-#endif
 
 #ifdef PNG_INFO_IMAGE_SUPPORTED
    /* Memory has been allocated if (valid & PNG_ALLOCATED_INFO_ROWS)
@@ -275,20 +266,5 @@
    png_bytepp row_pointers;        /* the image bits */
 #endif
 
-#if defined(PNG_FIXED_POINT_SUPPORTED) && defined(PNG_gAMA_SUPPORTED)
-   png_fixed_point int_gamma; /* gamma of image, if (valid & PNG_INFO_gAMA) */
-#endif
-
-#if defined(PNG_cHRM_SUPPORTED) && defined(PNG_FIXED_POINT_SUPPORTED)
-   png_fixed_point int_x_white;
-   png_fixed_point int_y_white;
-   png_fixed_point int_x_red;
-   png_fixed_point int_y_red;
-   png_fixed_point int_x_green;
-   png_fixed_point int_y_green;
-   png_fixed_point int_x_blue;
-   png_fixed_point int_y_blue;
-#endif
-
 };
 #endif /* PNGINFO_H */
diff --git a/pngmem.c b/pngmem.c
index 94a573a..dde1d34 100644
--- a/pngmem.c
+++ b/pngmem.c
@@ -1,7 +1,7 @@
 
 /* pngmem.c - stub functions for memory allocation
  *
- * Last changed in libpng 1.5.0 [July 24, 2010]
+ * Last changed in libpng 1.5.0 [July 29, 2010]
  * Copyright (c) 1998-2010 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
diff --git a/pngpread.c b/pngpread.c
index 63eac4c..936b2f1 100644
--- a/pngpread.c
+++ b/pngpread.c
@@ -1,7 +1,7 @@
 
 /* pngpread.c - read a png file in push mode
  *
- * Last changed in libpng 1.5.0 [July 24, 2010]
+ * Last changed in libpng 1.5.0 [July 29, 2010]
  * Copyright (c) 1998-2010 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
diff --git a/pngpriv.h b/pngpriv.h
index a00f2c1..68f031b 100644
--- a/pngpriv.h
+++ b/pngpriv.h
@@ -1,7 +1,7 @@
 
 /* pngpriv.h - private declarations for use inside libpng
  *
- * libpng version 1.5.0beta36 - July 24, 2010
+ * libpng version 1.5.0beta36 - July 29, 2010
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1998-2010 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
@@ -32,12 +32,10 @@
 #include "pnginfo.h"
 #include "pngstruct.h"
 
+/* This is required for the definition of abort(), used as a last ditch
+ * error handler when all else fails.
+ */
 #include <stdlib.h>
-#ifdef BSD
-#  include <strings.h>
-#else
-#  include <string.h>
-#endif
 
 /* Added at libpng-1.2.9 */
 /* Moved to pngpriv.h at libpng-1.5.0 */
@@ -53,6 +51,9 @@
 #endif
 
 /* Moved to pngpriv.h at libpng-1.5.0 */
+/* NOTE: some of these may be used in external applications as these definitions
+ * were exposed in pngconf.h prior to 1.5.
+ */
 /* If you are running on a machine where you cannot allocate more
  * than 64K of memory at once, uncomment this.  While libpng will not
  * normally need that much memory in a chunk (unless you load up a very
@@ -68,16 +69,12 @@
 #  define PNG_MAX_MALLOC_64K
 #endif
 
-/* Moved to pngpriv.h at libpng-1.5.0 */
-/* Feature support: in 1.4 this was in pngconf.h, but these
- * features have no affect on the libpng API.  Add library
- * only features to the end of this list.  Add features that
- * affect the API to scipts/config.dfn using png_on or png_off
- * as determined by the default and update scripts/config.std
+/* Just a little check that someone hasn't tried to define something
+ * contradictory.
  */
-/* Added at libpng version 1.4.0 */
-#if !defined(PNG_NO_WARNINGS) && !defined(PNG_WARNINGS_SUPPORTED)
-#  define PNG_WARNINGS_SUPPORTED
+#if (PNG_ZBUF_SIZE > 65536L) && defined(PNG_MAX_MALLOC_64K)
+#  undef PNG_ZBUF_SIZE
+#  define PNG_ZBUF_SIZE 65536L
 #endif
 
 /* If warnings or errors are turned off the code is disabled
@@ -90,57 +87,7 @@
 #ifndef PNG_ERROR_TEXT_SUPPORTED
 #  define png_error(s1,s2) png_err(s1)
 #  define png_chunk_error(s1,s2) png_err(s1)
-#endif
-
-/* Added at libpng version 1.4.0 */
-#if !defined(PNG_NO_CHECK_cHRM) && !defined(PNG_CHECK_cHRM_SUPPORTED)
-#  define PNG_CHECK_cHRM_SUPPORTED
-#endif
-
-/* Added at libpng version 1.4.0 */
-#if !defined(PNG_NO_ALIGNED_MEMORY) && !defined(PNG_ALIGNED_MEMORY_SUPPORTED)
-#  define PNG_ALIGNED_MEMORY_SUPPORTED
-#endif
-
-/* Buggy compilers (e.g., gcc 2.7.2.2) need PNG_NO_POINTER_INDEXING
- * See png[wr]util.c
- */
-#if !defined(PNG_NO_POINTER_INDEXING) && \
-    !defined(PNG_POINTER_INDEXING_SUPPORTED)
-#  define PNG_POINTER_INDEXING_SUPPORTED
-#endif
-
-/* Other defines for things like memory and the like can go here.  */
-
-/* This controls how fine the quantizing gets.  As this allocates
- * a largish chunk of memory (32K), those who are not as concerned
- * with quantizing quality can decrease some or all of these.
- */
-#ifndef PNG_QUANTIZE_RED_BITS
-#  define PNG_QUANTIZE_RED_BITS 5
-#endif
-#ifndef PNG_QUANTIZE_GREEN_BITS
-#  define PNG_QUANTIZE_GREEN_BITS 5
-#endif
-#ifndef PNG_QUANTIZE_BLUE_BITS
-#  define PNG_QUANTIZE_BLUE_BITS 5
-#endif
-
-/* This controls how fine the gamma correction becomes when you
- * are only interested in 8 bits anyway.  Increasing this value
- * results in more memory being used, and more pow() functions
- * being called to fill in the gamma tables.  Don't set this value
- * less then 8, and even that may not work (I haven't tested it).
- */
-#ifndef PNG_MAX_GAMMA_8
-#  define PNG_MAX_GAMMA_8 11
-#endif
-
-/* This controls how much a difference in gamma we can tolerate before
- * we actually start doing gamma conversion.
- */
-#ifndef PNG_GAMMA_THRESHOLD
-#  define PNG_GAMMA_THRESHOLD 0.05
+#  define png_fixed_error(s1,s2,s3) png_err(s1)
 #endif
 
 #ifndef PNG_EXTERN
@@ -154,11 +101,30 @@
 #  define PNG_EXTERN
 #endif
 
+/* Some fixed point APIs are still required even if not exported because
+ * they get used by the corresponding floating point APIs.  This magic
+ * deals with this:
+ */
+#ifdef PNG_FIXED_POINT_SUPPORTED
+#  define PNGFAPI PNGAPI
+#else
+#  define PNGFAPI /* PRIVATE */
+#endif
+
 /* Other defines specific to compilers can go here.  Try to keep
  * them inside an appropriate ifdef/endif pair for portability.
  */
+#if defined(PNG_FLOATING_POINT_SUPPORTED) ||\
+    defined(PNG_FLOATING_ARITHMETIC_SUPPORTED)
+   /* pngarith.c requires the following ANSI-C constants if the convertion of
+    * floating point to ASCII is implemented therein:
+    * 
+    *  DBL_DIG  Maximum number of decimal digits (can be set to any constant)
+    *  DBL_MIN  Smalles normalized fp number (can be set to an arbitrary value)
+    *  DBL_MAX  Maximum floating point number (can be set to an arbitrary value)
+    */
+#  include <float.h>
 
-#ifdef PNG_FLOATING_POINT_SUPPORTED
 #  if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \
     defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC)
      /* We need to check that <math.h> hasn't already been included earlier
@@ -194,31 +160,85 @@
 #  endif
 #endif
 
-/* 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
- * is full, it writes the data to the disk, and does some other
- * calculations.  Making this an extremely small size will slow
- * the library down, but you may want to experiment to determine
- * where it becomes significant, if you are concerned with memory
- * usage.  Note that zlib allocates at least 32Kb also.  For readers,
- * this describes the size of the buffer available to read the data in.
- * Unless this gets smaller than the size of a row (compressed),
- * it should not make much difference how big this is.
+/* Moved here around 1.5.0beta36 from pngconf.h */
+/* Users may want to use these so they are not private.  Any library
+ * functions that are passed far data must be model-independent.
  */
 
-#ifndef PNG_ZBUF_SIZE
-#  define PNG_ZBUF_SIZE 8192
+/* Memory model/platform independent fns */
+#ifndef PNG_ABORT
+#  ifdef _WINDOWS_
+#    define PNG_ABORT() ExitProcess(0)
+#  else
+#    define PNG_ABORT() abort()
+#  endif
 #endif
 
-/* Just a little check that someone hasn't tried to define something
- * contradictory.
+#ifdef USE_FAR_KEYWORD
+/* Use this to make far-to-near assignments */
+#  define CHECK   1
+#  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_strncpy _fstrncpy   /* Added to v 1.2.6 */
+#  define png_strlen  _fstrlen
+#  define png_memcmp  _fmemcmp    /* SJT: added */
+#  define png_memcpy  _fmemcpy
+#  define png_memset  _fmemset
+#  define png_sprintf sprintf
+#else
+#  ifdef _WINDOWS_  /* Favor Windows over C runtime fns */
+#    define CVT_PTR(ptr)         (ptr)
+#    define CVT_PTR_NOCHECK(ptr) (ptr)
+#    define png_strcpy  lstrcpyA
+#    define png_strncpy lstrcpynA
+#    define png_strlen  lstrlenA
+#    define png_memcmp  memcmp
+#    define png_memcpy  CopyMemory
+#    define png_memset  memset
+#    define png_sprintf wsprintfA
+#  else
+#    define CVT_PTR(ptr)         (ptr)
+#    define CVT_PTR_NOCHECK(ptr) (ptr)
+#    define png_strcpy  strcpy
+#    define png_strncpy strncpy     /* Added to v 1.2.6 */
+#    define png_strlen  strlen
+#    define png_memcmp  memcmp      /* SJT: added */
+#    define png_memcpy  memcpy
+#    define png_memset  memset
+#    define png_sprintf sprintf
+#  endif
+#endif
+/* End of memory model/platform independent support */
+
+#ifndef PNG_NO_SNPRINTF
+#  ifdef _MSC_VER
+#    define png_snprintf _snprintf   /* Added to v 1.2.19 */
+#    define png_snprintf2 _snprintf
+#    define png_snprintf6 _snprintf
+#  else
+#    define png_snprintf snprintf   /* Added to v 1.2.19 */
+#    define png_snprintf2 snprintf
+#    define png_snprintf6 snprintf
+#  endif
+#else
+  /* You don't have or don't want to use snprintf().  Caution: Using
+   * sprintf instead of snprintf exposes your application to accidental
+   * or malevolent buffer overflows.  If you don't have snprintf()
+   * as a general rule you should provide one (you can get one from
+   * Portable OpenSSH).
+   */
+#  define png_snprintf(s1,n,fmt,x1) png_sprintf(s1,fmt,x1)
+#  define png_snprintf2(s1,n,fmt,x1,x2) png_sprintf(s1,fmt,x1,x2)
+#  define png_snprintf6(s1,n,fmt,x1,x2,x3,x4,x5,x6) \
+      png_sprintf(s1,fmt,x1,x2,x3,x4,x5,x6)
+#endif
+/* End of 1.5.0beta36 move from pngconf.h */
+
+/* CONSTANTS and UTILITY MACROS
+ * These are used internally by libpng and not exposed in the API
  */
-#if (PNG_ZBUF_SIZE > 65536L) && defined(PNG_MAX_MALLOC_64K)
-#  undef PNG_ZBUF_SIZE
-#  define PNG_ZBUF_SIZE 65536L
-#endif
-
 /* Various modes of operation.  Note that after an init, mode is set to
  * zero automatically when the structure is created.
  */
@@ -276,9 +296,7 @@
 #define PNG_STRUCT_INFO  0x0002
 
 /* Scaling factor for filter heuristic weighting calculations */
-#define PNG_WEIGHT_SHIFT 8
 #define PNG_WEIGHT_FACTOR (1<<(PNG_WEIGHT_SHIFT))
-#define PNG_COST_SHIFT 3
 #define PNG_COST_FACTOR (1<<(PNG_COST_SHIFT))
 
 /* Flags for the png_ptr->flags rather than declaring a byte for each one */
@@ -343,6 +361,44 @@
 #define PNG_OUT_OF_RANGE(value, ideal, delta) \
    ( (value) < (ideal)-(delta) || (value) > (ideal)+(delta) )
 
+/* Convertions between fixed and floating point, only defined if
+ * required (to make sure the code doesn't accidentally use float
+ * when it is supposedly disabled.)
+ */
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+/* The floating point convertion can't overflow, though it can and
+ * does lose accuracy relative to the original fixed point value.
+ * In practice this doesn't matter because png_fixed_point only
+ * stores numbers with very low precision.  The png_ptr and s
+ * arguments are unused by default but are there in case error
+ * checking becomes a requirement.
+ */
+#define png_float(png_ptr, fixed, s) (.00001 * (fixed))
+
+/* The fixed point convertion performs range checking and evaluates
+ * its argument multiple times, so must be used with care.  The
+ * range checking uses the PNG specification values for a signed
+ * 32 bit fixed point value except that the values are deliberately
+ * rounded-to-zero to an integral value - 21474.  's' is a string
+ * that describes the value being converted.
+ *
+ * NOTE: this macro will raise a png_error if the range check fails,
+ * therefore it is normally only appropriate to use this on values
+ * that come from API calls or other sources where an out of range
+ * error indicates a programming error, not a data error!
+ *
+ * NOTE: by default this is off - the macro is not used - because the
+ * function call saves a lot of code.
+ */
+#ifdef PNG_FIXED_POINT_MACRO_SUPPORTED
+#define png_fixed(png_ptr, fp, s) ((fp) <= 21474 && (fp) >= -21474 ?\
+    ((png_fixed_point)(100000 * (fp))) : (png_fixed_error(png_ptr, s, fp),0))
+#else
+PNG_EXTERN png_fixed_point png_fixed PNGARG((png_structp png_ptr, double fp,
+   png_const_charp text));
+#endif
+#endif
+
 /* Constant strings for known chunk types.  If you need to add a chunk,
  * define the name here, and add an invocation of the macro wherever it's
  * needed.
@@ -404,8 +460,8 @@
 PNG_EXTERN void png_zfree PNGARG((voidpf png_ptr, voidpf ptr));
 
 /* Next four functions are used internally as callbacks.  PNGCBAPI is required
- * but not PNG_EXPORT.  PNGAPI added at libpng version 1.2.3, changed to PNGCBAPI
- * at 1.5.0
+ * but not PNG_EXPORT.  PNGAPI added at libpng version 1.2.3, changed to
+ * PNGCBAPI at 1.5.0
  */
 
 PNG_EXTERN void PNGCBAPI png_default_read_data PNGARG((png_structp png_ptr,
@@ -597,15 +653,8 @@
 #endif
 
 #ifdef PNG_WRITE_sCAL_SUPPORTED
-#  if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
-PNG_EXTERN void png_write_sCAL PNGARG((png_structp png_ptr,
-    int unit, double width, double height));
-#  else
-#    ifdef PNG_FIXED_POINT_SUPPORTED
 PNG_EXTERN void png_write_sCAL_s PNGARG((png_structp png_ptr,
     int unit, png_charp width, png_charp height));
-#    endif
-#  endif
 #endif
 
 /* Called when finished processing a row of data */
@@ -945,7 +994,7 @@
 #endif
 
 /* Added at libpng version 1.4.0 */
-#ifdef PNG_cHRM_SUPPORTED
+#ifdef PNG_CHECK_cHRM_SUPPORTED
 PNG_EXTERN int png_check_cHRM_fixed PNGARG((png_structp png_ptr,
     png_fixed_point int_white_x, png_fixed_point int_white_y,
     png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point
@@ -953,12 +1002,11 @@
     png_fixed_point int_blue_y));
 #endif
 
-#ifdef PNG_cHRM_SUPPORTED
-#  ifdef PNG_CHECK_cHRM_SUPPORTED
+#ifdef PNG_CHECK_cHRM_SUPPORTED
 /* Added at libpng version 1.2.34 and 1.4.0 */
+/* Currently only used by png_check_cHRM_fixed */
 PNG_EXTERN void png_64bit_product PNGARG((long v1, long v2,
     unsigned long *hi_product, unsigned long *lo_product));
-#  endif
 #endif
 
 /* Added at libpng version 1.4.0 */
@@ -968,21 +1016,165 @@
     int filter_type));
 
 /* Free all memory used by the read (old method - NOT DLL EXPORTED) */
-PNG_EXTERN void png_read_destroy PNGARG((png_structp png_ptr, png_infop info_ptr,
-    png_infop end_info_ptr));
+PNG_EXTERN void png_read_destroy PNGARG((png_structp png_ptr,
+    png_infop info_ptr, png_infop end_info_ptr));
 
 /* Free any memory used in png_ptr struct (old method - NOT DLL EXPORTED) */
 PNG_EXTERN void png_write_destroy PNGARG((png_structp png_ptr));
 
 #ifdef USE_FAR_KEYWORD  /* memory model conversion function */
-PNG_EXTERN void *png_far_to_near PNGARG((png_structp png_ptr,png_voidp ptr,
+PNG_EXTERN void *png_far_to_near PNGARG((png_structp png_ptr, png_voidp ptr,
     int check));
 #endif /* USE_FAR_KEYWORD */
 
-#include "pngdebug.h"
+#if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED)
+PNG_EXTERN void png_fixed_error PNGARG((png_structp png_ptr,
+    png_const_charp name, double value));
+#endif
+
+/* ASCII to FP interfaces, currently only implemented if sCAL
+ * support is required.
+ */
+#if defined(PNG_READ_sCAL_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
+/* MAX_DIGITS is actually the maximum number of characters in an sCAL
+ * width or height, derived from the precision (number of significant
+ * digits - a build time settable option) and assumpitions about the
+ * maximum ridiculous exponent.
+ */
+#define PNG_sCAL_MAX_DIGITS (PNG_sCAL_PRECISION+1/*.*/+1/*E*/+10/*exponent*/)
+PNG_EXTERN void png_ascii_from_fp(png_structp png_ptr, png_charp ascii,
+    png_size_t size, double fp, unsigned precision);
+#endif /* READ_sCAL && FLOATING_POINT */
+
+#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED)
+/* An internal API to validate the format of a floating point number.
+ * The result is the index of the next character.  If the number is
+ * not valid it will be the index of a character in the supposed number.
+ *
+ * The format of a number is defined in the PNG extensions specification
+ * and this API is strictly conformant to that spec, not anyone elses!
+ *
+ * The format as a regular expression is:
+ *
+ * [+-]?[0-9]+.?([Ee][+-]?[0-9]+)?
+ *
+ * or:
+ *
+ * [+-]?.[0-9]+(.[0-9]+)?([Ee][+-]?[0-9]+)?
+ *
+ * The complexity is that either integer or fraction must be present and the
+ * fraction is permitted to have no digits only if the integer is present.
+ *
+ * NOTE: The dangling E problem.
+ *   There is a PNG valid floating point number in the following:
+ *
+ *       PNG floating point numb1.ers are not greedy.
+ *
+ *   Working this out requires *TWO* character lookahead (because of the
+ *   sign), the parser does not do this - it will fail at the 'r' - this
+ *   doesn't matter for PNG sCAL chunk values, but it requires more care
+ *   if the value were ever to be embedded in something more complex.  Use
+ *   ANSI-C strtod if you need the lookahead.
+ */
+/* State table for the parser. */
+#define PNG_FP_INTEGER    0  /* before or in integer */
+#define PNG_FP_FRACTION   1  /* before or in fraction */
+#define PNG_FP_EXPONENT   2  /* before or in exponent */
+#define PNG_FP_STATE      3  /* mask for the above */
+#define PNG_FP_SAW_SIGN   4  /* Saw +/- in current state */
+#define PNG_FP_SAW_DIGIT  8  /* Saw a digit in current state */
+#define PNG_FP_SAW_DOT   16  /* Saw a dot in current state */
+#define PNG_FP_SAW_E     32  /* Saw an E (or e) in current state */
+#define PNG_FP_SAW_ANY   60  /* Saw any of the above 4 */
+#define PNG_FP_WAS_VALID 64  /* Preceding substring is a valid fp number */
+#define PNG_FP_INVALID  128  /* Available for callers as a distinct value */
+
+/* Result codes for the parser (boolean - true meants ok, false means
+ * not ok yet.)
+ */
+#define PNG_FP_MAYBE      0  /* The number may be valid in the future */
+#define PNG_FP_OK         1  /* The number is valid */
+
+/* The actual parser.  This can be called repeatedly, it updates
+ * the index into the string and the state variable (which must
+ * be initialzed to 0).  It returns a result code, as above.  There
+ * is no point calling the parser any more if it fails to advance to
+ * the end of the string - it is stuck on an invalid character (or
+ * terminated by '\0').
+ *
+ * Note that the pointer will consume an E or even an E+ then leave
+ * a 'maybe' state even though a preceding integer.fraction is valid.
+ * The PNG_FP_WAS_VALID flag indicates that a preceding substring was
+ * a valid number.  It's possible to recover from this by calling
+ * the parser again (from the start, with state 0) but with a string
+ * that omits the last character (i.e. set the size to the index of
+ * the problem character.)  This has not been tested within libpng.
+ */
+PNG_EXTERN int png_check_fp_number(png_charp string, png_size_t size,
+    int *statep, png_size_tp whereami);
+
+/* This is the same but it checks a complete string and returns true
+ * only if it just contains a floating point number.
+ */
+PNG_EXTERN int png_check_fp_string(png_charp string, png_size_t size);
+#endif /* pCAL || sCAL */
+
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED)
+/* Added at libpng version 1.5.0 */
+/* This is a utility to provide a*times/div (rounded) and indicate
+ * if there is an overflow.  The result is a boolean - false (0)
+ * for overflow, true (1) if no overflow, in which case *res
+ * holds the result.
+ */
+PNG_EXTERN int png_muldiv PNGARG((png_fixed_point_p res, png_fixed_point a,
+    png_int_32 times, png_int_32 div));
+#endif
+
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED)
+/* Same deal, but issue a warning on overflow and return 0. */
+PNG_EXTERN png_fixed_point png_muldiv_warn PNGARG((png_structp png_ptr,
+    png_fixed_point a, png_int_32 times, png_int_32 div));
+#endif
+
+#ifdef PNG_READ_GAMMA_SUPPORTED
+/* Calculate a reciprocal - used for gamma values.  This returns
+ * 0 if the argument is 0 in order to maintain an undefined value,
+ * there are no warnings.
+ */
+PNG_EXTERN png_fixed_point png_reciprocal PNGARG((png_fixed_point a));
+
+/* The same but gives a reciprocal of the product of two fixed point
+ * values.  Accuracy is suitable for gamma calculations but this is
+ * not exact - use png_muldiv for that.
+ */
+PNG_EXTERN png_fixed_point png_reciprocal2 PNGARG((png_fixed_point a,
+    png_fixed_point b));
+#endif
+
+#ifdef PNG_READ_GAMMA_SUPPORTED
+/* Internal fixed point gamma correction.  These APIs are called as
+ * required to convert single values - they don't need to be fast,
+ * they are not used when processing image pixel values.
+ *
+ * While the input is an 'unsigned' value it must actually be the
+ * correct bit value - 0..255 or 0..65535 as required.
+ */
+PNG_EXTERN png_uint_16 png_gamma_correct PNGARG((png_structp png_ptr,
+    unsigned value, png_fixed_point gamma));
+PNG_EXTERN int png_gamma_significant PNGARG((png_fixed_point gamma));
+PNG_EXTERN png_uint_16 png_gamma_16bit_correct PNGARG((unsigned value,
+    png_fixed_point gamma));
+PNG_EXTERN png_byte png_gamma_8bit_correct PNGARG((unsigned value,
+    png_fixed_point gamma));
+PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr,
+    png_byte bit_depth));
+#endif
 
 /* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */
 
+
+#include "pngdebug.h"
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/pngread.c b/pngread.c
index 6fbd687..2e18f4f 100644
--- a/pngread.c
+++ b/pngread.c
@@ -1,7 +1,7 @@
 
 /* pngread.c - read a PNG file
  *
- * Last changed in libpng 1.5.0 [July 24, 2010]
+ * Last changed in libpng 1.5.0 [July 29, 2010]
  * Copyright (c) 1998-2010 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -500,6 +500,10 @@
 
    if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
       png_read_start_row(png_ptr);
+   else
+      png_warning(png_ptr,
+          "Ignoring extra png_start_read_image() call;"
+          " row buffer not reallocated");
 }
 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
 
@@ -852,7 +856,31 @@
       return;
 
 #ifdef PNG_READ_INTERLACING_SUPPORTED
-   pass = png_set_interlace_handling(png_ptr);
+   if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
+   {
+      pass = png_set_interlace_handling(png_ptr);
+      /* And make sure transforms are initialized. */
+      png_start_read_image(png_ptr);
+   }
+   else
+   {
+      if (!(png_ptr->transformations & PNG_INTERLACE))
+      {
+	 /* Caller called png_start_read_image or png_read_update_info without
+	  * first turning on the PNG_INTERLACE transform.  We can fix this here,
+	  * but the caller should do it!
+	  */
+	 png_warning(png_ptr, "Interlace handling should be turned on when "
+	    "using png_read_image");
+	 /* Make sure this is set correctly */
+	 png_ptr->num_rows = png_ptr->height;
+      }
+
+      /* Obtain the pass number, which also turns on the PNG_INTERLACE flag in
+       * the above error case.
+       */
+      pass = png_set_interlace_handling(png_ptr);
+   }
 #else
    if (png_ptr->interlaced)
       png_error(png_ptr,
@@ -861,9 +889,7 @@
    pass = 1;
 #endif
 
-
    image_height=png_ptr->height;
-   png_ptr->num_rows = image_height; /* Make sure this is set correctly */
 
    for (j = 0; j < pass; j++)
    {
diff --git a/pngrio.c b/pngrio.c
index d14e188..d3f6ec7 100644
--- a/pngrio.c
+++ b/pngrio.c
@@ -1,7 +1,7 @@
 
 /* pngrio.c - functions for data input
  *
- * Last changed in libpng 1.5.0 [July 24, 2010]
+ * Last changed in libpng 1.5.0 [July 29, 2010]
  * Copyright (c) 1998-2010 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
diff --git a/pngrtran.c b/pngrtran.c
index 061713d..f9b506e 100644
--- a/pngrtran.c
+++ b/pngrtran.c
@@ -1,7 +1,7 @@
 
 /* pngrtran.c - transforms the data in a row for PNG readers
  *
- * Last changed in libpng 1.5.0 [July 24, 2010]
+ * Last changed in libpng 1.5.0 [July 29, 2010]
  * Copyright (c) 1998-2010 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -88,15 +88,14 @@
    }
 }
 
-#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
-    defined(PNG_FLOATING_POINT_SUPPORTED)
+#ifdef PNG_READ_BACKGROUND_SUPPORTED
 /* Handle alpha and tRNS via a background color */
-void PNGAPI
-png_set_background(png_structp png_ptr,
+void PNGFAPI
+png_set_background_fixed(png_structp png_ptr,
     png_color_16p background_color, int background_gamma_code,
-    int need_expand, double background_gamma)
+    int need_expand, png_fixed_point background_gamma)
 {
-   png_debug(1, "in png_set_background");
+   png_debug(1, "in png_set_background_fixed");
 
    if (png_ptr == NULL)
       return;
@@ -110,11 +109,22 @@
    png_ptr->transformations |= PNG_BACKGROUND;
    png_memcpy(&(png_ptr->background), background_color,
       png_sizeof(png_color_16));
-   png_ptr->background_gamma = (float)background_gamma;
+   png_ptr->background_gamma = background_gamma;
    png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
    png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0);
 }
-#endif
+
+#  ifdef PNG_FLOATING_POINT_SUPPORTED
+void PNGAPI
+png_set_background(png_structp png_ptr,
+    png_color_16p background_color, int background_gamma_code,
+    int need_expand, double background_gamma)
+{
+   png_set_background_fixed(png_ptr, background_color, background_gamma_code,
+      need_expand, png_fixed(png_ptr, background_gamma, "png_set_background"));
+}
+#  endif  /* FLOATING_POINT */
+#endif /* READ_BACKGROUND */
 
 #ifdef PNG_READ_16_TO_8_SUPPORTED
 /* Strip 16 bit depth files to 8 bit depth */
@@ -549,7 +559,7 @@
 }
 #endif /* PNG_READ_QUANTIZE_SUPPORTED */
 
-#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
 /* Transform the image from the file_gamma to the screen_gamma.  We
  * only do transformations on images where the file_gamma and screen_gamma
  * are not close reciprocals, otherwise it slows things down slightly, and
@@ -559,22 +569,48 @@
  * are present in the tRNS array for palette images.  We can't do it here
  * because we don't necessarily have the tRNS chunk yet.
  */
-void PNGAPI
-png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
+static int /* PRIVATE */
+png_gamma_threshold(png_fixed_point scrn_gamma, png_fixed_point file_gamma)
 {
-   png_debug(1, "in png_set_gamma");
+   /* PNG_GAMMA_THRESHOLD is the threshold for performing gamma
+    * correction as a difference of the overall transform from 1.0
+    *
+    * We want to compare the threshold with s*f - 1, if we get
+    * overflow here it is because of wacky gamma values so we
+    * turn on processing anyway.
+    */
+   png_fixed_point gtest;
+   return !png_muldiv(&gtest, scrn_gamma, file_gamma, PNG_FP_1) ||
+       png_gamma_significant(gtest);
+}
+
+void PNGFAPI
+png_set_gamma_fixed(png_structp png_ptr, png_fixed_point scrn_gamma,
+   png_fixed_point file_gamma)
+{
+   png_debug(1, "in png_set_gamma_fixed");
 
    if (png_ptr == NULL)
       return;
 
-   if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) ||
-       (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) ||
-       (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
+   if ((png_ptr->color_type & PNG_COLOR_MASK_ALPHA) ||
+       (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ||
+       png_gamma_threshold(scrn_gamma, file_gamma))
       png_ptr->transformations |= PNG_GAMMA;
-   png_ptr->gamma = (float)file_gamma;
-   png_ptr->screen_gamma = (float)scrn_gamma;
+   png_ptr->gamma = file_gamma;
+   png_ptr->screen_gamma = scrn_gamma;
 }
-#endif
+
+#  ifdef PNG_FLOATING_POINT_SUPPORTED
+void PNGAPI
+png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
+{
+   png_set_gamma_fixed(png_ptr,
+      png_fixed(png_ptr, scrn_gamma, "png_set_gamma screen gamma"),
+      png_fixed(png_ptr, file_gamma, "png_set_gamma file gamma"));
+}
+#  endif /* FLOATING_POINT_SUPPORTED */
+#endif /* READ_GAMMA */
 
 #ifdef PNG_READ_EXPAND_SUPPORTED
 /* Expand paletted images to RGB, expand grayscale images of
@@ -662,12 +698,7 @@
 #endif
 
 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
-void
-#ifdef PNG_FIXED_POINT_SUPPORTED
-    PNGAPI
-#else
-    /* PRIVATE */
-#endif
+void PNGFAPI
 png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
     png_fixed_point red, png_fixed_point green)
 {
@@ -735,15 +766,14 @@
 
 void PNGAPI
 png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
-    double green)
+   double green)
 {
-   int red_fixed = (int)((float)red*100000.0 + 0.5);
-   int green_fixed = (int)((float)green*100000.0 + 0.5);
-
    if (png_ptr == NULL)
       return;
 
-   png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed);
+   png_set_rgb_to_gray_fixed(png_ptr, error_action,
+      png_fixed(png_ptr, red, "rgb to gray red coefficient"),
+      png_fixed(png_ptr, green, "rgb to gray green coefficient"));
 }
 #endif /* FLOATING POINT */
 
@@ -886,7 +916,8 @@
               int i, istop;
               istop=(int)png_ptr->num_trans;
               for (i=0; i<istop; i++)
-                 png_ptr->trans_alpha[i] = (png_byte)(255 - png_ptr->trans_alpha[i]);
+                 png_ptr->trans_alpha[i] = (png_byte)(255 -
+		    png_ptr->trans_alpha[i]);
            }
         }
 #endif
@@ -898,11 +929,10 @@
 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
    png_ptr->background_1 = png_ptr->background;
 #endif
-#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
 
    if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0)
-       && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0)
-       < PNG_GAMMA_THRESHOLD))
+       && png_gamma_threshold(png_ptr->screen_gamma, png_ptr->gamma))
    {
       int i, k;
       k=0;
@@ -916,7 +946,7 @@
    }
 
    if ((png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY)) &&
-       png_ptr->gamma != 0.0)
+       png_ptr->gamma != 0)
    {
       png_build_gamma_table(png_ptr, png_ptr->bit_depth);
 
@@ -932,6 +962,7 @@
             int i;
             if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
             {
+
                back.red = png_ptr->gamma_table[png_ptr->background.red];
                back.green = png_ptr->gamma_table[png_ptr->background.green];
                back.blue = png_ptr->gamma_table[png_ptr->background.blue];
@@ -942,31 +973,33 @@
             }
             else
             {
-               double g, gs;
+               png_fixed_point g, gs;
 
                switch (png_ptr->background_gamma_type)
                {
                   case PNG_BACKGROUND_GAMMA_SCREEN:
                      g = (png_ptr->screen_gamma);
-                     gs = 1.0;
+                     gs = PNG_FP_1;
                      break;
 
                   case PNG_BACKGROUND_GAMMA_FILE:
-                     g = 1.0 / (png_ptr->gamma);
-                     gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
+                     g = png_reciprocal(png_ptr->gamma);
+                     gs = png_reciprocal2(png_ptr->gamma,
+		        png_ptr->screen_gamma);
                      break;
 
                   case PNG_BACKGROUND_GAMMA_UNIQUE:
-                     g = 1.0 / (png_ptr->background_gamma);
-                     gs = 1.0 / (png_ptr->background_gamma *
-                                 png_ptr->screen_gamma);
+                     g = png_reciprocal(png_ptr->background_gamma);
+                     gs = png_reciprocal2(png_ptr->background_gamma,
+		        png_ptr->screen_gamma);
                      break;
                   default:
-                     g = 1.0;    /* back_1 */
-                     gs = 1.0;   /* back */
+                     g = PNG_FP_1;    /* back_1 */
+                     gs = PNG_FP_1;   /* back */
+		     break;
                }
 
-               if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD)
+	       if ( png_gamma_significant(gs) )
                {
                   back.red   = (png_byte)png_ptr->background.red;
                   back.green = (png_byte)png_ptr->background.green;
@@ -975,24 +1008,18 @@
 
                else
                {
-                  back.red = (png_byte)(pow(
-                      (double)png_ptr->background.red/255.0, gs) * 255.0 + .5);
-                  back.green = (png_byte)(pow(
-                      (double)png_ptr->background.green/255.0, gs) * 255.0
-                      + .5);
-                  back.blue = (png_byte)(pow(
-                      (double)png_ptr->background.blue/255.0, gs) * 255.0
-                      + .5);
+                  back.red = png_gamma_8bit_correct(png_ptr->background.red,
+                      gs);
+                  back.green = png_gamma_8bit_correct(png_ptr->background.green,
+                      gs);
+                  back.blue = png_gamma_8bit_correct(png_ptr->background.blue,
+                      gs);
                }
-
-               back_1.red = (png_byte)(pow(
-                   (double)png_ptr->background.red/255.0, g) * 255.0 + .5);
-
-               back_1.green = (png_byte)(pow(
-                   (double)png_ptr->background.green/255.0, g) * 255.0 + .5);
-
-               back_1.blue = (png_byte)(pow(
-                   (double)png_ptr->background.blue/255.0, g) * 255.0 + .5);
+               back_1.red = png_gamma_8bit_correct(png_ptr->background.red, g);
+               back_1.green = png_gamma_8bit_correct(png_ptr->background.green,
+                   g);
+               back_1.blue = png_gamma_8bit_correct(png_ptr->background.blue,
+                   g);
             }
             for (i = 0; i < num_palette; i++)
             {
@@ -1040,57 +1067,56 @@
          else
          /* color_type != PNG_COLOR_TYPE_PALETTE */
          {
-            double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1);
-            double g = 1.0;
-            double gs = 1.0;
+	    png_fixed_point g = PNG_FP_1;
+	    png_fixed_point gs = PNG_FP_1;
 
             switch (png_ptr->background_gamma_type)
             {
                case PNG_BACKGROUND_GAMMA_SCREEN:
-                  g = (png_ptr->screen_gamma);
-                  gs = 1.0;
+                  g = png_ptr->screen_gamma;
+                  /* gs = PNG_FP_1; */
                   break;
 
                case PNG_BACKGROUND_GAMMA_FILE:
-                  g = 1.0 / (png_ptr->gamma);
-                  gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
+                  g = png_reciprocal(png_ptr->gamma);
+                  gs = png_reciprocal2(png_ptr->gamma, png_ptr->screen_gamma);
                   break;
 
                case PNG_BACKGROUND_GAMMA_UNIQUE:
-                  g = 1.0 / (png_ptr->background_gamma);
-                  gs = 1.0 / (png_ptr->background_gamma *
-                     png_ptr->screen_gamma);
+                  g = png_reciprocal(png_ptr->background_gamma);
+                  gs = png_reciprocal2(png_ptr->background_gamma,
+		      png_ptr->screen_gamma);
                   break;
             }
 
-            png_ptr->background_1.gray = (png_uint_16)(pow(
-                (double)png_ptr->background.gray / m, g) * m + .5);
+            png_ptr->background_1.gray = png_gamma_correct(png_ptr,
+	        png_ptr->background.gray, g);
 
-            png_ptr->background.gray = (png_uint_16)(pow(
-                (double)png_ptr->background.gray / m, gs) * m + .5);
+            png_ptr->background.gray = png_gamma_correct(png_ptr,
+                png_ptr->background.gray, gs);
 
             if ((png_ptr->background.red != png_ptr->background.green) ||
                 (png_ptr->background.red != png_ptr->background.blue) ||
                 (png_ptr->background.red != png_ptr->background.gray))
             {
                /* RGB or RGBA with color background */
-               png_ptr->background_1.red = (png_uint_16)(pow(
-                   (double)png_ptr->background.red / m, g) * m + .5);
+               png_ptr->background_1.red = png_gamma_correct(png_ptr,
+                   png_ptr->background.red, g);
 
-               png_ptr->background_1.green = (png_uint_16)(pow(
-                   (double)png_ptr->background.green / m, g) * m + .5);
+               png_ptr->background_1.green = png_gamma_correct(png_ptr,
+                   png_ptr->background.green, g);
 
-               png_ptr->background_1.blue = (png_uint_16)(pow(
-                   (double)png_ptr->background.blue / m, g) * m + .5);
+               png_ptr->background_1.blue = png_gamma_correct(png_ptr,
+                   png_ptr->background.blue, g);
 
-               png_ptr->background.red = (png_uint_16)(pow(
-                   (double)png_ptr->background.red / m, gs) * m + .5);
+               png_ptr->background.red = png_gamma_correct(png_ptr,
+                   png_ptr->background.red, gs);
 
-               png_ptr->background.green = (png_uint_16)(pow(
-                   (double)png_ptr->background.green / m, gs) * m + .5);
+               png_ptr->background.green = png_gamma_correct(png_ptr,
+                   png_ptr->background.green, gs);
 
-               png_ptr->background.blue = (png_uint_16)(pow(
-                   (double)png_ptr->background.blue / m, gs) * m + .5);
+               png_ptr->background.blue = png_gamma_correct(png_ptr,
+                   png_ptr->background.blue, gs);
             }
 
             else
@@ -1127,7 +1153,7 @@
 #ifdef PNG_READ_BACKGROUND_SUPPORTED
    else
 #endif
-#endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */
+#endif /* PNG_READ_GAMMA_SUPPORTED */
 #ifdef PNG_READ_BACKGROUND_SUPPORTED
    /* No GAMMA transformation */
    if ((png_ptr->transformations & PNG_BACKGROUND) &&
@@ -1255,12 +1281,7 @@
 #ifdef PNG_READ_GAMMA_SUPPORTED
    if (png_ptr->transformations & PNG_GAMMA)
    {
-#ifdef PNG_FLOATING_POINT_SUPPORTED
       info_ptr->gamma = png_ptr->gamma;
-#endif
-#ifdef PNG_FIXED_POINT_SUPPORTED
-      info_ptr->int_gamma = png_ptr->int_gamma;
-#endif
    }
 #endif
 
@@ -4066,267 +4087,6 @@
 }
 #endif /* PNG_READ_QUANTIZE_SUPPORTED */
 
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-#ifdef PNG_READ_GAMMA_SUPPORTED
-static PNG_CONST int png_gamma_shift[] =
-   {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0, 0x00};
-
-/* We build the 8- or 16-bit gamma tables here.  Note that for 16-bit
- * tables, we don't make a full table if we are reducing to 8-bit in
- * the future.  Note also how the gamma_16 tables are segmented so that
- * we don't need to allocate > 64K chunks for a full 16-bit table.
- *
- * See the PNG extensions document for an integer algorithm for creating
- * the gamma tables.  Maybe we will implement that here someday.
- *
- * We should only reach this point if
- *
- *      the file_gamma is known (i.e., the gAMA or sRGB chunk is present,
- *      or the application has provided a file_gamma)
- *
- *   AND
- *      {
- *         the screen_gamma is known
- *
- *      OR
- *
- *         RGB_to_gray transformation is being performed
- *      }
- *
- *   AND
- *      {
- *         the screen_gamma is different from the reciprocal of the
- *         file_gamma by more than the specified threshold
- *
- *      OR
- *
- *         a background color has been specified and the file_gamma
- *         and screen_gamma are not 1.0, within the specified threshold.
- *      }
- */
-
-void /* PRIVATE */
-png_build_gamma_table(png_structp png_ptr, png_byte bit_depth)
-{
-  png_debug(1, "in png_build_gamma_table");
-
-  if (bit_depth <= 8)
-  {
-     int i;
-     double g;
-
-     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);
-
-     for (i = 0; i < 256; i++)
-     {
-        png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0,
-            g) * 255.0 + .5);
-     }
-
-#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,
-            (png_uint_32)256);
-
-        for (i = 0; i < 256; i++)
-        {
-           png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0,
-               g) * 255.0 + .5);
-        }
-
-        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_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
-  }
-  else
-  {
-     double g;
-     int i, j, shift, num;
-     int sig_bit;
-     png_uint_32 ig;
-
-     if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
-     {
-        sig_bit = (int)png_ptr->sig_bit.red;
-
-        if ((int)png_ptr->sig_bit.green > sig_bit)
-           sig_bit = png_ptr->sig_bit.green;
-
-        if ((int)png_ptr->sig_bit.blue > sig_bit)
-           sig_bit = png_ptr->sig_bit.blue;
-     }
-     else
-     {
-        sig_bit = (int)png_ptr->sig_bit.gray;
-     }
-
-     if (sig_bit > 0)
-        shift = 16 - sig_bit;
-
-     else
-        shift = 0;
-
-     if (png_ptr->transformations & PNG_16_TO_8)
-     {
-        if (shift < (16 - PNG_MAX_GAMMA_8))
-           shift = (16 - PNG_MAX_GAMMA_8);
-     }
-
-     if (shift > 8)
-        shift = 8;
-
-     if (shift < 0)
-        shift = 0;
-
-     png_ptr->gamma_shift = (png_byte)shift;
-
-     num = (1 << (8 - shift));
-
-     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_calloc(png_ptr,
-         (png_uint_32)(num * png_sizeof(png_uint_16p)));
-
-     if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND))
-     {
-        double fin, fout;
-        png_uint_32 last, max;
-
-        for (i = 0; i < num; i++)
-        {
-           png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
-               (png_uint_32)(256 * png_sizeof(png_uint_16)));
-        }
-
-        g = 1.0 / g;
-        last = 0;
-        for (i = 0; i < 256; i++)
-        {
-           fout = ((double)i + 0.5) / 256.0;
-           fin = pow(fout, g);
-           max = (png_uint_32)(fin * (double)((png_uint_32)num << 8));
-           while (last <= max)
-           {
-              png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
-                  [(int)(last >> (8 - shift))] = (png_uint_16)(
-                  (png_uint_16)i | ((png_uint_16)i << 8));
-              last++;
-           }
-        }
-
-        while (last < ((png_uint_32)num << 8))
-        {
-           png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
-               [(int)(last >> (8 - shift))] = (png_uint_16)65535L;
-           last++;
-        }
-     }
-     else
-     {
-        for (i = 0; i < num; i++)
-        {
-           png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
-               (png_uint_32)(256 * png_sizeof(png_uint_16)));
-
-           ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4);
-
-           for (j = 0; j < 256; j++)
-           {
-              png_ptr->gamma_16_table[i][j] =
-                  (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
-                  65535.0, g) * 65535.0 + .5);
-           }
-        }
-     }
-
-#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_calloc(png_ptr,
-            (png_uint_32)(num * png_sizeof(png_uint_16p )));
-
-        for (i = 0; i < num; i++)
-        {
-           png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr,
-               (png_uint_32)(256 * png_sizeof(png_uint_16)));
-
-           ig = (((png_uint_32)i *
-               (png_uint_32)png_gamma_shift[shift]) >> 4);
-
-           for (j = 0; j < 256; j++)
-           {
-              png_ptr->gamma_16_to_1[i][j] =
-                  (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
-                  65535.0, g) * 65535.0 + .5);
-           }
-        }
-
-        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_calloc(png_ptr,
-            (png_uint_32)(num * png_sizeof(png_uint_16p)));
-
-        for (i = 0; i < num; i++)
-        {
-           png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr,
-               (png_uint_32)(256 * png_sizeof(png_uint_16)));
-
-           ig = (((png_uint_32)i *
-               (png_uint_32)png_gamma_shift[shift]) >> 4);
-
-           for (j = 0; j < 256; j++)
-           {
-              png_ptr->gamma_16_from_1[i][j] =
-                  (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
-                  65535.0, g) * 65535.0 + .5);
-           }
-        }
-     }
-#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
-  }
-}
-#endif
-/* To do: install integer version of png_build_gamma_table here */
-#endif
-
 #ifdef PNG_MNG_FEATURES_SUPPORTED
 /* Undoes intrapixel differencing  */
 void /* PRIVATE */
diff --git a/pngrutil.c b/pngrutil.c
index 867f512..85ad575 100644
--- a/pngrutil.c
+++ b/pngrutil.c
@@ -1,7 +1,7 @@
 
 /* pngrutil.c - utilities to read a PNG file
  *
- * Last changed in libpng 1.4.1 [July 24, 2010]
+ * Last changed in libpng 1.4.1 [July 29, 2010]
  * Copyright (c) 1998-2010 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -27,6 +27,29 @@
       png_error(png_ptr, "PNG unsigned integer out of range");
    return (i);
 }
+
+#if defined(PNG_READ_gAMA_SUPPORTED) || defined(PNG_READ_cHRM_SUPPORTED)
+/* The following is a variation on the above for use with the fixed
+ * point values used for gAMA and cHRM.  Instead of png_error it
+ * issues a warning and returns (-1) - an invalid value because both
+ * gAMA and cHRM use *unsigned* integers for fixed point values.
+ */
+#define PNG_FIXED_ERROR (-1)
+
+png_fixed_point /* PRIVATE */
+png_get_fixed_point(png_structp png_ptr, png_bytep buf)
+{
+   png_uint_32 u = png_get_uint_32(buf);
+   if (u <= PNG_UINT_31_MAX)
+      return (png_fixed_point)u; /* known to be in range */
+
+   /* The caller can turn off the warning by passing NULL. */
+   if (png_ptr != NULL)
+      png_warning(png_ptr, "PNG fixed point integer out of range");
+   return PNG_FIXED_ERROR;
+}
+#endif
+
 #ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED
 /* NOTE: the read macros will obscure these definitions, so that if
  * PNG_USE_READ_MACROS is set the library will not use them internally,
@@ -46,22 +69,20 @@
 }
 
 /* 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.
- * Only used internally in this file.
+ * data is stored in the PNG file in two's complement format and there
+ * is no guarantee that a 'png_int_32' is exactly 32 bits, therefore
+ * the following code does a two's complement to native convertion.
  */
-#if defined(PNG_GET_INT_32_SUPPORTED)
 png_int_32 (PNGAPI
 png_get_int_32)(png_bytep buf)
 {
-   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));
+   png_uint_32 u = png_get_uint_32(buf);
+   if ((u & 0x80000000) == 0) /* negative */
+      return u;
 
-   return (i);
+   u = (u ^ 0xffffffff) + 1;  /* 2's complement: -x = ~x+1 */
+   return -u;
 }
-#endif
 
 /* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
 png_uint_16 (PNGAPI
@@ -677,9 +698,6 @@
 png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
    png_fixed_point igamma;
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-   float file_gamma;
-#endif
    png_byte buf[4];
 
    png_debug(1, "in png_handle_gAMA");
@@ -718,12 +736,12 @@
    if (png_crc_finish(png_ptr, 0))
       return;
 
-   igamma = (png_fixed_point)png_get_uint_32(buf);
-   /* Check for zero gamma */
-   if (igamma == 0)
+   igamma = png_get_fixed_point(NULL, buf);
+   /* Check for zero gamma or an error. */
+   if (igamma <= 0)
    {
       png_warning(png_ptr,
-          "Ignoring gAMA chunk with gamma=0");
+          "Ignoring gAMA chunk with out of range gamma");
       return;
    }
 
@@ -740,16 +758,12 @@
       }
 #endif /* PNG_READ_sRGB_SUPPORTED */
 
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-   file_gamma = (float)igamma / (float)100000.0;
 #  ifdef PNG_READ_GAMMA_SUPPORTED
-   png_ptr->gamma = file_gamma;
+   /* Gamma correction on read is supported. */
+   png_ptr->gamma = igamma;
 #  endif
-   png_set_gAMA(png_ptr, info_ptr, file_gamma);
-#else
-   /* Fixed point must be set! */
+   /* And set the 'info' structure members. */
    png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
-#endif
 }
 #endif
 
@@ -831,13 +845,8 @@
 png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
    png_byte buf[32];
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-   float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
-#endif
-   png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
-       int_y_green, int_x_blue, int_y_blue;
-
-   png_uint_32 uint_x, uint_y;
+   png_fixed_point x_white, y_white, x_red, y_red, x_green, y_green, x_blue,
+      y_blue;
 
    png_debug(1, "in png_handle_cHRM");
 
@@ -877,80 +886,54 @@
    if (png_crc_finish(png_ptr, 0))
       return;
 
-   uint_x = png_get_uint_32(buf);
-   uint_y = png_get_uint_32(buf + 4);
-   int_x_white = (png_fixed_point)uint_x;
-   int_y_white = (png_fixed_point)uint_y;
-
-   uint_x = png_get_uint_32(buf + 8);
-   uint_y = png_get_uint_32(buf + 12);
-   int_x_red = (png_fixed_point)uint_x;
-   int_y_red = (png_fixed_point)uint_y;
-
-   uint_x = png_get_uint_32(buf + 16);
-   uint_y = png_get_uint_32(buf + 20);
-   int_x_green = (png_fixed_point)uint_x;
-   int_y_green = (png_fixed_point)uint_y;
-
-   uint_x = png_get_uint_32(buf + 24);
-   uint_y = png_get_uint_32(buf + 28);
-   int_x_blue = (png_fixed_point)uint_x;
-   int_y_blue = (png_fixed_point)uint_y;
-
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-   white_x = (float)int_x_white / (float)100000.0;
-   white_y = (float)int_y_white / (float)100000.0;
-   red_x   = (float)int_x_red   / (float)100000.0;
-   red_y   = (float)int_y_red   / (float)100000.0;
-   green_x = (float)int_x_green / (float)100000.0;
-   green_y = (float)int_y_green / (float)100000.0;
-   blue_x  = (float)int_x_blue  / (float)100000.0;
-   blue_y  = (float)int_y_blue  / (float)100000.0;
-#endif
+   x_white = png_get_fixed_point(NULL, buf);
+   y_white = png_get_fixed_point(NULL, buf + 4);
+   x_red   = png_get_fixed_point(NULL, buf + 8);
+   y_red   = png_get_fixed_point(NULL, buf + 12);
+   x_green = png_get_fixed_point(NULL, buf + 16);
+   y_green = png_get_fixed_point(NULL, buf + 20);
+   x_blue  = png_get_fixed_point(NULL, buf + 24);
+   y_blue  = png_get_fixed_point(NULL, buf + 28);
+   if (x_white == PNG_FIXED_ERROR ||
+       y_white == PNG_FIXED_ERROR ||
+       x_red   == PNG_FIXED_ERROR ||
+       y_red   == PNG_FIXED_ERROR ||
+       x_green == PNG_FIXED_ERROR ||
+       y_green == PNG_FIXED_ERROR ||
+       x_blue  == PNG_FIXED_ERROR ||
+       y_blue  == PNG_FIXED_ERROR)
+   {
+      png_warning(png_ptr, "Ignoring cHRM chunk with negative chromaticities");
+      return;
+   }
 
 #ifdef PNG_READ_sRGB_SUPPORTED
    if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB))
    {
-      if (PNG_OUT_OF_RANGE(int_x_white, 31270,  1000) ||
-          PNG_OUT_OF_RANGE(int_y_white, 32900,  1000) ||
-          PNG_OUT_OF_RANGE(int_x_red,   64000L, 1000) ||
-          PNG_OUT_OF_RANGE(int_y_red,   33000,  1000) ||
-          PNG_OUT_OF_RANGE(int_x_green, 30000,  1000) ||
-          PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) ||
-          PNG_OUT_OF_RANGE(int_x_blue,  15000,  1000) ||
-          PNG_OUT_OF_RANGE(int_y_blue,   6000,  1000))
+      if (PNG_OUT_OF_RANGE(x_white, 31270,  1000) ||
+          PNG_OUT_OF_RANGE(y_white, 32900,  1000) ||
+          PNG_OUT_OF_RANGE(x_red,   64000L, 1000) ||
+          PNG_OUT_OF_RANGE(y_red,   33000,  1000) ||
+          PNG_OUT_OF_RANGE(x_green, 30000,  1000) ||
+          PNG_OUT_OF_RANGE(y_green, 60000L, 1000) ||
+          PNG_OUT_OF_RANGE(x_blue,  15000,  1000) ||
+          PNG_OUT_OF_RANGE(y_blue,   6000,  1000))
       {
          png_warning(png_ptr,
              "Ignoring incorrect cHRM value when sRGB is also present");
 #ifdef PNG_CONSOLE_IO_SUPPORTED
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-         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",
-             green_x, green_y, blue_x, blue_y);
-#else
-         fprintf(stderr, "wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
-             (long)int_x_white, (long)int_y_white,
-             (long)int_x_red, (long)int_y_red);
-         fprintf(stderr, "gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
-             (long)int_x_green, (long)int_y_green,
-             (long)int_x_blue, (long)int_y_blue);
-#endif
+         fprintf(stderr, "wx=%d, wy=%d, rx=%d, ry=%d\n",
+             x_white, y_white, x_red, y_red);
+         fprintf(stderr, "gx=%d, gy=%d, bx=%d, by=%d\n",
+             x_green, y_green, x_blue, y_blue);
 #endif /* PNG_CONSOLE_IO_SUPPORTED */
       }
       return;
    }
 #endif /* PNG_READ_sRGB_SUPPORTED */
 
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-   png_set_cHRM(png_ptr, info_ptr,
-       white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
-#endif
-#ifdef PNG_FIXED_POINT_SUPPORTED
-   png_set_cHRM_fixed(png_ptr, info_ptr,
-       int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
-       int_y_green, int_x_blue, int_y_blue);
-#endif
+   png_set_cHRM_fixed(png_ptr, info_ptr, x_white, y_white, x_red, y_red,
+      x_green, y_green, x_blue, y_blue);
 }
 #endif
 
@@ -1007,48 +990,31 @@
 #if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
    if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA))
    {
-   png_fixed_point igamma;
-#ifdef PNG_FIXED_POINT_SUPPORTED
-      igamma=info_ptr->int_gamma;
-#else
-#  ifdef PNG_FLOATING_POINT_SUPPORTED
-      igamma=(png_fixed_point)(info_ptr->gamma * 100000.);
-#  endif
-#endif
-      if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
+      if (PNG_OUT_OF_RANGE(info_ptr->gamma, 45500L, 500))
       {
-         png_warning(png_ptr,
-             "Ignoring incorrect gAMA value when sRGB is also present");
+	 png_warning(png_ptr,
+	     "Ignoring incorrect gAMA value when sRGB is also present");
 #ifdef PNG_CONSOLE_IO_SUPPORTED
-#  ifdef PNG_FIXED_POINT_SUPPORTED
-         fprintf(stderr, "incorrect gamma=(%d/100000)\n",
-             (int)png_ptr->int_gamma);
-#  else
-#    ifdef PNG_FLOATING_POINT_SUPPORTED
-         fprintf(stderr, "incorrect gamma=%f\n", png_ptr->gamma);
-#    endif
-#  endif
+	 fprintf(stderr, "incorrect gamma=(%d/100000)\n", info_ptr->gamma);
 #endif
       }
    }
 #endif /* PNG_READ_gAMA_SUPPORTED */
 
 #ifdef PNG_READ_cHRM_SUPPORTED
-#ifdef PNG_FIXED_POINT_SUPPORTED
    if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
-      if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270,  1000) ||
-          PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900,  1000) ||
-          PNG_OUT_OF_RANGE(info_ptr->int_x_red,   64000L, 1000) ||
-          PNG_OUT_OF_RANGE(info_ptr->int_y_red,   33000,  1000) ||
-          PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000,  1000) ||
-          PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) ||
-          PNG_OUT_OF_RANGE(info_ptr->int_x_blue,  15000,  1000) ||
-          PNG_OUT_OF_RANGE(info_ptr->int_y_blue,   6000,  1000))
+      if (PNG_OUT_OF_RANGE(info_ptr->x_white, 31270,  1000) ||
+          PNG_OUT_OF_RANGE(info_ptr->y_white, 32900,  1000) ||
+          PNG_OUT_OF_RANGE(info_ptr->x_red,   64000L, 1000) ||
+          PNG_OUT_OF_RANGE(info_ptr->y_red,   33000,  1000) ||
+          PNG_OUT_OF_RANGE(info_ptr->x_green, 30000,  1000) ||
+          PNG_OUT_OF_RANGE(info_ptr->y_green, 60000L, 1000) ||
+          PNG_OUT_OF_RANGE(info_ptr->x_blue,  15000,  1000) ||
+          PNG_OUT_OF_RANGE(info_ptr->y_blue,   6000,  1000))
       {
          png_warning(png_ptr,
              "Ignoring incorrect cHRM value when sRGB is also present");
       }
-#endif /* PNG_FIXED_POINT_SUPPORTED */
 #endif /* PNG_READ_cHRM_SUPPORTED */
 
    png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
@@ -1144,7 +1110,7 @@
 
    profile_length = data_length - prefix_length;
 
-   if ( prefix_length > data_length || profile_length < 4)
+   if (prefix_length > data_length || profile_length < 4)
    {
       png_free(png_ptr, png_ptr->chunkdata);
       png_ptr->chunkdata = NULL;
@@ -1167,22 +1133,24 @@
       png_free(png_ptr, png_ptr->chunkdata);
       png_ptr->chunkdata = NULL;
 #ifdef PNG_STDIO_SUPPORTED
- {
-    char umsg[80];
+      {
+         char umsg[80];
 
-    png_snprintf2(umsg, 80,
-        "Ignoring iCCP chunk with declared size = %lu "
-         "and actual length = %lu",
-        (unsigned long)profile_size,
-        (unsigned long)profile_length);
-    png_warning(png_ptr, umsg);
- }
+         png_snprintf2(umsg, 80,
+             "Ignoring iCCP chunk with declared size = %u "
+              "and actual length = %u", profile_size, profile_length);
+         png_warning(png_ptr, umsg);
+      }
+#else
+      png_warning(png_ptr,
+         "Ignoring iCCP chunk with uncompressed size mismatch");
 #endif
       return;
    }
 
    png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata,
-       compression_type, png_ptr->chunkdata + prefix_length, profile_length);
+       compression_type, (png_bytep)png_ptr->chunkdata + prefix_length,
+       profile_length);
    png_free(png_ptr, png_ptr->chunkdata);
    png_ptr->chunkdata = NULL;
 }
@@ -1854,16 +1822,8 @@
 void /* PRIVATE */
 png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
-   png_charp ep;
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-   double width, height;
-   png_charp vp;
-#else
-#ifdef PNG_FIXED_POINT_SUPPORTED
-   png_charp swidth, sheight;
-#endif
-#endif
-   png_size_t slength;
+   png_size_t slength, index;
+   int state;
 
    png_debug(1, "in png_handle_sCAL");
 
@@ -1897,6 +1857,7 @@
 
    slength = (png_size_t)length;
    png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
+   png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
 
    if (png_crc_finish(png_ptr, 0))
    {
@@ -1905,115 +1866,40 @@
       return;
    }
 
-   png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
-
-   ep = png_ptr->chunkdata + 1;        /* Skip unit byte */
-
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-   width = png_strtod(png_ptr, ep, &vp);
-   if (*vp)
+   /* Validate the unit. */
+   if (png_ptr->chunkdata[0] != 1 && png_ptr->chunkdata[0] != 2)
    {
-      png_warning(png_ptr, "malformed width string in sCAL chunk");
-      png_free(png_ptr, png_ptr->chunkdata);
-      png_ptr->chunkdata = NULL;
-      return;
-   }
-#else
-#ifdef PNG_FIXED_POINT_SUPPORTED
-   swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
-
-   if (swidth == NULL)
-   {
-      png_warning(png_ptr, "Out of memory while processing sCAL chunk width");
+      png_warning(png_ptr, "Invalid sCAL ignored: invalid unit");
       png_free(png_ptr, png_ptr->chunkdata);
       png_ptr->chunkdata = NULL;
       return;
    }
 
-   png_memcpy(swidth, ep, png_strlen(ep));
-#endif
-#endif
-
-   for (ep = png_ptr->chunkdata; *ep; ep++)
-      /* Empty loop */ ;
-
-   ep++;
-
-   if (png_ptr->chunkdata + slength < ep)
+   /* Validate the ASCII numbers, need two ASCII numbers separated by
+    * a '\0' and they need to fit exactly in the chunk data.
+    */
+   index = 0;
+   state = 0;
+   if (png_ptr->chunkdata[1] == 45 /* negative width */ ||
+       !png_check_fp_number(png_ptr->chunkdata, slength, &state, &index) ||
+       index >= slength || png_ptr->chunkdata[index++] != 0)
+      png_warning(png_ptr, "Invalid sCAL chunk ignored: bad width format");
+   else
    {
-      png_warning(png_ptr, "Truncated sCAL chunk");
-#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
-      png_free(png_ptr, swidth);
-#endif
-      png_free(png_ptr, png_ptr->chunkdata);
-      png_ptr->chunkdata = NULL;
-      return;
+      png_size_t heighti = index;
+      if (png_ptr->chunkdata[index] == 45 /* negative height */ ||
+          !png_check_fp_number(png_ptr->chunkdata, slength, &state, &index) ||
+	  index != slength)
+	 png_warning(png_ptr, "Invalid sCAL chunk ignored: bad height format");
+      else
+	 /* This is the (only) success case. */
+	 png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0],
+	    png_ptr->chunkdata+1, png_ptr->chunkdata+heighti);
    }
 
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-   height = png_strtod(png_ptr, ep, &vp);
-
-   if (*vp)
-   {
-      png_warning(png_ptr, "malformed height string in sCAL chunk");
-      png_free(png_ptr, png_ptr->chunkdata);
-      png_ptr->chunkdata = NULL;
-#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
-      png_free(png_ptr, swidth);
-#endif
-      return;
-   }
-
-#else
-#ifdef PNG_FIXED_POINT_SUPPORTED
-   sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
-
-   if (sheight == NULL)
-   {
-      png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
-      png_free(png_ptr, png_ptr->chunkdata);
-      png_ptr->chunkdata = NULL;
-#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
-      png_free(png_ptr, swidth);
-#endif
-      return;
-   }
-
-   png_memcpy(sheight, ep, png_strlen(ep));
-#endif
-#endif
-
-   if (png_ptr->chunkdata + slength < ep
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-       || width <= 0. || height <= 0.
-#endif
-       )
-   {
-      png_warning(png_ptr, "Invalid sCAL data");
-      png_free(png_ptr, png_ptr->chunkdata);
-      png_ptr->chunkdata = NULL;
-#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
-      png_free(png_ptr, swidth);
-      png_free(png_ptr, sheight);
-#endif
-      return;
-   }
-
-
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-   png_set_sCAL(png_ptr, info_ptr, png_ptr->chunkdata[0], width, height);
-#else
-#ifdef PNG_FIXED_POINT_SUPPORTED
-   png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], swidth, sheight);
-#endif
-#endif
-
+   /* Clean up - just free the temporarily allocated buffer. */
    png_free(png_ptr, png_ptr->chunkdata);
    png_ptr->chunkdata = NULL;
-#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
-   png_free(png_ptr, swidth);
-   png_free(png_ptr, sheight);
-#endif
 }
 #endif
 
@@ -3567,4 +3453,37 @@
 
    png_ptr->flags |= PNG_FLAG_ROW_INIT;
 }
+
+#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
+int PNGAPI
+png_get_num_passes(png_structp png_ptr)
+{
+   if (png_ptr != NULL)
+   {
+      if (png_ptr->interlaced)
+         return 7;
+      else
+         return 1;
+   }
+
+   /* Here on error */
+   return 0;
+}
+
+png_uint_32 PNGAPI
+png_get_num_rows(png_structp png_ptr)
+{
+   if (png_ptr != NULL)
+   {
+      if (png_ptr->flags & PNG_FLAG_ROW_INIT)
+	 return png_ptr->num_rows;
+      else
+	 png_error(png_ptr, "Call png_start_read_image or png_read_update_info "
+	    "before png_get_num_rows");
+   }
+
+   /* Here on error */
+   return 0;
+}
+#endif /* SEQUENTIAL READ */
 #endif /* PNG_READ_SUPPORTED */
diff --git a/pngset.c b/pngset.c
index 67cd1a5..e68ffe5 100644
--- a/pngset.c
+++ b/pngset.c
@@ -1,7 +1,7 @@
 
 /* pngset.c - storage of image information into info struct
  *
- * Last changed in libpng 1.5.0 [July 24, 2010]
+ * Last changed in libpng 1.5.0 [July 29, 2010]
  * Copyright (c) 1998-2010 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -35,42 +35,7 @@
 #endif
 
 #ifdef PNG_cHRM_SUPPORTED
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-void PNGAPI
-png_set_cHRM(png_structp png_ptr, png_infop info_ptr,
-    double white_x, double white_y, double red_x, double red_y,
-    double green_x, double green_y, double blue_x, double blue_y)
-{
-   png_debug1(1, "in %s storage function", "cHRM");
-
-   if (png_ptr == NULL || info_ptr == NULL)
-      return;
-
-   /* TODO: call png_check_cHRM_fixed */
-   info_ptr->x_white = (float)white_x;
-   info_ptr->y_white = (float)white_y;
-   info_ptr->x_red   = (float)red_x;
-   info_ptr->y_red   = (float)red_y;
-   info_ptr->x_green = (float)green_x;
-   info_ptr->y_green = (float)green_y;
-   info_ptr->x_blue  = (float)blue_x;
-   info_ptr->y_blue  = (float)blue_y;
-#ifdef PNG_FIXED_POINT_SUPPORTED
-   info_ptr->int_x_white = (png_fixed_point)(white_x*100000. + 0.5);
-   info_ptr->int_y_white = (png_fixed_point)(white_y*100000. + 0.5);
-   info_ptr->int_x_red   = (png_fixed_point)(  red_x*100000. + 0.5);
-   info_ptr->int_y_red   = (png_fixed_point)(  red_y*100000. + 0.5);
-   info_ptr->int_x_green = (png_fixed_point)(green_x*100000. + 0.5);
-   info_ptr->int_y_green = (png_fixed_point)(green_y*100000. + 0.5);
-   info_ptr->int_x_blue  = (png_fixed_point)( blue_x*100000. + 0.5);
-   info_ptr->int_y_blue  = (png_fixed_point)( blue_y*100000. + 0.5);
-#endif
-   info_ptr->valid |= PNG_INFO_cHRM;
-}
-#endif /* PNG_FLOATING_POINT_SUPPORTED */
-
-#ifdef PNG_FIXED_POINT_SUPPORTED
-void PNGAPI
+void PNGFAPI
 png_set_cHRM_fixed(png_structp png_ptr, png_infop info_ptr,
     png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x,
     png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y,
@@ -86,99 +51,71 @@
        white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y))
 #endif
    {
-      info_ptr->int_x_white = white_x;
-      info_ptr->int_y_white = white_y;
-      info_ptr->int_x_red   = red_x;
-      info_ptr->int_y_red   = red_y;
-      info_ptr->int_x_green = green_x;
-      info_ptr->int_y_green = green_y;
-      info_ptr->int_x_blue  = blue_x;
-      info_ptr->int_y_blue  = blue_y;
-#ifdef  PNG_FLOATING_POINT_SUPPORTED
-      info_ptr->x_white = (float)(white_x/100000.);
-      info_ptr->y_white = (float)(white_y/100000.);
-      info_ptr->x_red   = (float)(  red_x/100000.);
-      info_ptr->y_red   = (float)(  red_y/100000.);
-      info_ptr->x_green = (float)(green_x/100000.);
-      info_ptr->y_green = (float)(green_y/100000.);
-      info_ptr->x_blue  = (float)( blue_x/100000.);
-      info_ptr->y_blue  = (float)( blue_y/100000.);
-#endif
+      info_ptr->x_white = white_x;
+      info_ptr->y_white = white_y;
+      info_ptr->x_red   = red_x;
+      info_ptr->y_red   = red_y;
+      info_ptr->x_green = green_x;
+      info_ptr->y_green = green_y;
+      info_ptr->x_blue  = blue_x;
+      info_ptr->y_blue  = blue_y;
       info_ptr->valid |= PNG_INFO_cHRM;
    }
 }
-#endif /* PNG_FIXED_POINT_SUPPORTED */
+
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+void PNGAPI
+png_set_cHRM(png_structp png_ptr, png_infop info_ptr,
+    double white_x, double white_y, double red_x, double red_y,
+    double green_x, double green_y, double blue_x, double blue_y)
+{
+   png_set_cHRM_fixed(png_ptr, info_ptr,
+      png_fixed(png_ptr, white_x, "cHRM White X"),
+      png_fixed(png_ptr, white_y, "cHRM White Y"),
+      png_fixed(png_ptr, red_x, "cHRM Red X"),
+      png_fixed(png_ptr, red_y, "cHRM Red Y"),
+      png_fixed(png_ptr, green_x, "cHRM Green X"),
+      png_fixed(png_ptr, green_y, "cHRM Green Y"),
+      png_fixed(png_ptr, blue_x, "cHRM Blue X"),
+      png_fixed(png_ptr, blue_y, "cHRM Blue Y"));
+}
+#endif /* PNG_FLOATING_POINT_SUPPORTED */
+
 #endif /* PNG_cHRM_SUPPORTED */
 
 #ifdef PNG_gAMA_SUPPORTED
+void PNGFAPI
+png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point
+    gamma)
+{
+   png_debug1(1, "in %s storage function", "gAMA");
+
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   /* Previously these values were limited, however they must be
+    * wrong, therfore storing them (and setting PNG_INFO_gAMA)
+    * must be wrong too.
+    */
+   if (gamma > (png_fixed_point)PNG_UINT_31_MAX)
+      png_warning(png_ptr, "Gamma too large, ignored");
+
+   else if (gamma <= 0)
+      png_warning(png_ptr, "Negative gamma ignored");
+
+   else
+   {
+      info_ptr->gamma = gamma;
+      info_ptr->valid |= PNG_INFO_gAMA;
+   }
+}
+
 #ifdef PNG_FLOATING_POINT_SUPPORTED
 void PNGAPI
 png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma)
 {
-   double png_gamma;
-
-   png_debug1(1, "in %s storage function", "gAMA");
-
-   if (png_ptr == NULL || info_ptr == NULL)
-      return;
-
-   /* Check for overflow */
-   if (file_gamma > 21474.83)
-   {
-      png_warning(png_ptr, "Limiting gamma to 21474.83");
-      png_gamma = 21474.83;
-   }
-
-   else
-      png_gamma = file_gamma;
-
-   info_ptr->gamma = (float)png_gamma;
-#ifdef PNG_FIXED_POINT_SUPPORTED
-   info_ptr->int_gamma = (int)(png_gamma*100000.+.5);
-#endif
-   info_ptr->valid |= PNG_INFO_gAMA;
-
-   if (png_gamma == 0.0)
-      png_warning(png_ptr, "Setting gamma = 0");
-}
-#endif
-#ifdef PNG_FIXED_POINT_SUPPORTED
-void PNGAPI
-png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point
-    int_gamma)
-{
-   png_fixed_point png_gamma;
-
-   png_debug1(1, "in %s storage function", "gAMA");
-
-   if (png_ptr == NULL || info_ptr == NULL)
-      return;
-
-   if (int_gamma > (png_fixed_point)PNG_UINT_31_MAX)
-   {
-      png_warning(png_ptr, "Limiting gamma to 21474.83");
-      png_gamma = PNG_UINT_31_MAX;
-   }
-
-   else
-   {
-      if (int_gamma < 0)
-      {
-         png_warning(png_ptr, "Setting negative gamma to zero");
-         png_gamma = 0;
-      }
-
-      else
-         png_gamma = int_gamma;
-   }
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-   info_ptr->gamma = (float)(png_gamma/100000.);
-#endif
-   info_ptr->int_gamma = png_gamma;
-   info_ptr->valid |= PNG_INFO_gAMA;
-
-   if (png_gamma == 0)
-      png_warning(png_ptr, "Setting gamma = 0");
+   png_set_gAMA_fixed(png_ptr, info_ptr, png_fixed(png_ptr, file_gamma,
+      "png_set_gAMA"));
 }
 #endif
 #endif
@@ -309,6 +246,17 @@
    png_debug1(3, "allocating purpose for info (%lu bytes)",
        (unsigned long)length);
 
+   /* TODO: validate format of calibration name and unit name */
+
+   /* Check that the type matches the specification. */
+   if (type < 0 || type > 3)
+      png_error(png_ptr, "Invalid pCAL equation type");
+
+   /* Validate params[nparams] */
+   for (i=0; i<nparams; ++i)
+      if (!png_check_fp_string(params[i], png_strlen(params[i])))
+         png_error(png_ptr, "Invalid format for pCAL parameter");
+
    info_ptr->pcal_purpose = (png_charp)png_malloc_warn(png_ptr, length);
    if (info_ptr->pcal_purpose == NULL)
    {
@@ -370,75 +318,94 @@
 #endif
 
 #ifdef PNG_sCAL_SUPPORTED
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-void PNGAPI
-png_set_sCAL(png_structp png_ptr, png_infop info_ptr,
-    int unit, double width, double height)
-{
-   png_debug1(1, "in %s storage function", "sCAL");
-
-   if (png_ptr == NULL || info_ptr == NULL)
-      return;
-
-   info_ptr->scal_unit = (png_byte)unit;
-   info_ptr->scal_pixel_width = width;
-   info_ptr->scal_pixel_height = height;
-
-   info_ptr->valid |= PNG_INFO_sCAL;
-}
-#endif
-#ifdef PNG_FIXED_POINT_SUPPORTED
-void PNGAPI
+void PNGFAPI
 png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr,
     int unit, png_charp swidth, png_charp sheight)
 {
-   png_size_t length;
+   png_size_t lengthw, lengthh;
 
    png_debug1(1, "in %s storage function", "sCAL");
 
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
+   /* Double check the unit (should never get here with an invalid
+    * unit unless this is an API call.)
+    */
+   if (unit != 1 && unit != 2)
+      png_error(png_ptr, "Invalid sCAL unit");
+
+   if (swidth == NULL || (lengthw = png_strlen(swidth)) <= 0 ||
+       swidth[0] == 45 /*'-'*/ || !png_check_fp_string(swidth, lengthw))
+      png_error(png_ptr, "Invalid sCAL width");
+
+   if (sheight == NULL || (lengthh = png_strlen(sheight)) <= 0 ||
+       sheight[0] == 45 /*'-'*/ || !png_check_fp_string(sheight, lengthh))
+      png_error(png_ptr, "Invalid sCAL height");
+
    info_ptr->scal_unit = (png_byte)unit;
 
-   length = png_strlen(swidth) + 1;
+   ++lengthw;
 
-   png_debug1(3, "allocating unit for info (%u bytes)",
-       (unsigned int)length);
+   png_debug1(3, "allocating unit for info (%u bytes)", lengthw);
 
-   info_ptr->scal_s_width = (png_charp)png_malloc_warn(png_ptr, length);
+   info_ptr->scal_s_width = (png_charp)png_malloc_warn(png_ptr, lengthw);
 
    if (info_ptr->scal_s_width == NULL)
    {
-      png_warning(png_ptr,
-         "Memory allocation failed while processing sCAL");
+      png_warning(png_ptr, "Memory allocation failed while processing sCAL");
       return;
    }
 
-   png_memcpy(info_ptr->scal_s_width, swidth, length);
+   png_memcpy(info_ptr->scal_s_width, swidth, lengthw);
 
-   length = png_strlen(sheight) + 1;
+   ++lengthh;
 
-   png_debug1(3, "allocating unit for info (%u bytes)",
-      (unsigned int)length);
+   png_debug1(3, "allocating unit for info (%u bytes)", lengthh);
 
-   info_ptr->scal_s_height = (png_charp)png_malloc_warn(png_ptr, length);
+   info_ptr->scal_s_height = (png_charp)png_malloc_warn(png_ptr, lengthh);
 
    if (info_ptr->scal_s_height == NULL)
    {
       png_free (png_ptr, info_ptr->scal_s_width);
       info_ptr->scal_s_width = NULL;
 
-      png_warning(png_ptr,
-         "Memory allocation failed while processing sCAL");
-
+      png_warning(png_ptr, "Memory allocation failed while processing sCAL");
       return;
    }
 
-   png_memcpy(info_ptr->scal_s_height, sheight, length);
+   png_memcpy(info_ptr->scal_s_height, sheight, lengthh);
+
    info_ptr->valid |= PNG_INFO_sCAL;
    info_ptr->free_me |= PNG_FREE_SCAL;
 }
+
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+void PNGAPI
+png_set_sCAL(png_structp png_ptr, png_infop info_ptr, int unit, double width,
+   double height)
+{
+   png_debug1(1, "in %s storage function", "sCAL");
+
+   /* Check the arguments. */
+   if (width <= 0)
+      png_warning(png_ptr, "Invalid sCAL width ignored");
+   else if (height <= 0)
+      png_warning(png_ptr, "Invalid sCAL height ignored");
+   else
+   {
+      /* Convert 'width' and 'height' to ASCII. */
+      char swidth[PNG_sCAL_MAX_DIGITS+1];
+      char sheight[PNG_sCAL_MAX_DIGITS+1];
+
+      png_ascii_from_fp(png_ptr, swidth, sizeof swidth, width,
+         PNG_sCAL_PRECISION);
+      png_ascii_from_fp(png_ptr, sheight, sizeof sheight, height,
+         PNG_sCAL_PRECISION);
+
+      png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight);
+   }
+}
 #endif
 #endif
 
@@ -543,16 +510,10 @@
    png_set_sRGB(png_ptr, info_ptr, intent);
 
 #ifdef PNG_gAMA_SUPPORTED
-#ifdef PNG_FIXED_POINT_SUPPORTED
    png_set_gAMA_fixed(png_ptr, info_ptr, 45455L);
-#else
-   /* Floating point must be set! */
-   png_set_gAMA(png_ptr, info_ptr, .45455);
-#endif
 #endif
 
 #ifdef PNG_cHRM_SUPPORTED
-#ifdef PNG_FIXED_POINT_SUPPORTED
    png_set_cHRM_fixed(png_ptr, info_ptr,
       /* color      x       y */
       /* white */ 31270L, 32900L,
@@ -560,16 +521,6 @@
       /* green */ 30000L, 60000L,
       /* blue  */ 15000L,  6000L
    );
-#else
-   /* Floating point must be supported! */
-   png_set_cHRM(png_ptr, info_ptr,
-      /* color      x      y */
-      /* while */ .3127, .3290,
-      /* red   */ .64,   .33,
-      /* green */ .30,   .60,
-      /* blue  */ .15,   .06
-   );
-#endif
 #endif /* cHRM */
 }
 #endif /* sRGB */
@@ -579,10 +530,10 @@
 void PNGAPI
 png_set_iCCP(png_structp png_ptr, png_infop info_ptr,
     png_charp name, int compression_type,
-    png_charp profile, png_uint_32 proflen)
+    png_bytep profile, png_uint_32 proflen)
 {
    png_charp new_iccp_name;
-   png_charp new_iccp_profile;
+   png_bytep new_iccp_profile;
    png_uint_32 length;
 
    png_debug1(1, "in %s storage function", "iCCP");
@@ -598,7 +549,7 @@
       return;
    }
    png_memcpy(new_iccp_name, name, length);
-   new_iccp_profile = (png_charp)png_malloc_warn(png_ptr, proflen);
+   new_iccp_profile = (png_bytep)png_malloc_warn(png_ptr, proflen);
 
    if (new_iccp_profile == NULL)
    {
@@ -844,8 +795,8 @@
        png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
 
        /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */
-       png_ptr->trans_alpha = info_ptr->trans_alpha = (png_bytep)png_malloc(png_ptr,
-           (png_size_t)PNG_MAX_PALETTE_LENGTH);
+       png_ptr->trans_alpha = info_ptr->trans_alpha =
+          (png_bytep)png_malloc(png_ptr, (png_size_t)PNG_MAX_PALETTE_LENGTH);
 
        if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH)
           png_memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans);
@@ -864,7 +815,8 @@
          png_warning(png_ptr,
             "tRNS chunk has out-of-range samples for bit_depth");
 
-      png_memcpy(&(info_ptr->trans_color), trans_color, png_sizeof(png_color_16));
+      png_memcpy(&(info_ptr->trans_color), trans_color,
+         png_sizeof(png_color_16));
 
       if (num_trans == 0)
          num_trans = 1;
diff --git a/pngstruct.h b/pngstruct.h
index d0d7ae6..a9d6c90 100644
--- a/pngstruct.h
+++ b/pngstruct.h
@@ -5,7 +5,7 @@
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
- * Last changed in libpng version 1.5.0 - July 24, 2010
+ * Last changed in libpng version 1.5.0 - July 29, 2010
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
@@ -20,6 +20,12 @@
 
 #ifndef PNGSTRUCT_H
 #define PNGSTRUCT_H
+/* zlib.h defines the structure z_stream, an instance of which is included
+ * in this structure and is required for decompressing the LZ compressed
+ * data in PNG files.
+ */
+#include "zlib.h"
+
 struct png_struct_def
 {
 #ifdef PNG_SETJMP_SUPPORTED
@@ -104,9 +110,7 @@
 
 #ifdef PNG_bKGD_SUPPORTED
    png_byte background_gamma_type;
-#  ifdef PNG_FLOATING_POINT_SUPPORTED
-   float background_gamma;
-#  endif
+   png_fixed_point background_gamma;
    png_color_16 background;   /* background color in screen gamma space */
 #ifdef PNG_READ_GAMMA_SUPPORTED
    png_color_16 background_1; /* background normalized to gamma 1.0 */
@@ -121,10 +125,8 @@
 
 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
    int gamma_shift;      /* number of "insignificant" bits in 16-bit gamma */
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-   float gamma;          /* file gamma value */
-   float screen_gamma;   /* screen gamma value (display_exponent) */
-#endif
+   png_fixed_point gamma;        /* file gamma value */
+   png_fixed_point screen_gamma; /* screen gamma value (display_exponent) */
 #endif
 
 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
@@ -154,7 +156,7 @@
    png_write_status_ptr write_row_fn; /* called after each row is encoded */
 #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
    png_progressive_info_ptr info_fn; /* called after header data fully read */
-   png_progressive_row_ptr row_fn;   /* called after each prog. row is decoded */
+   png_progressive_row_ptr row_fn;   /* called after a prog. row is decoded */
    png_progressive_end_ptr end_fn;   /* called after image is complete */
    png_bytep save_buffer_ptr;        /* current location in save_buffer */
    png_bytep save_buffer;            /* buffer for previously read data */
@@ -241,11 +243,6 @@
    png_uint_32 mng_features_permitted;
 #endif
 
-/* New member added in libpng-1.0.7 */
-#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
-   png_fixed_point int_gamma;
-#endif
-
 /* New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 */
 #ifdef PNG_MNG_FEATURES_SUPPORTED
    png_byte filter_type;
diff --git a/pngtest.c b/pngtest.c
index 4323f95..07dc466 100644
--- a/pngtest.c
+++ b/pngtest.c
@@ -1,7 +1,7 @@
 
 /* pngtest.c - a simple test program to test libpng
  *
- * Last changed in libpng 1.5.0 [July 24, 2010]
+ * Last changed in libpng 1.5.0 [July 29, 2010]
  * Copyright (c) 1998-2010 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -31,6 +31,7 @@
  * of files at once by typing "pngtest -m file1.png file2.png ..."
  */
 
+#include "zlib.h"
 #include "png.h"
 /* Copied from pngpriv.h but only used in error messages below. */
 #ifndef PNG_ZBUF_SIZE
@@ -64,6 +65,17 @@
 #  define SINGLE_ROWBUF_ALLOC  /* Makes buffer overruns easier to nail */
 #endif
 
+/* The code uses memcmp and memcpy on large objects (typically row pointers) so
+ * it is necessary to do soemthing special on certain architectures, note that
+ * the actual support for this was effectively removed in 1.4, so only the
+ * memory remains in this program:
+ */
+#define CVT_PTR(ptr)         (ptr)
+#define CVT_PTR_NOCHECK(ptr) (ptr)
+#define png_memcmp  memcmp
+#define png_memcpy  memcpy
+#define png_memset  memset
+
 /* Turn on CPU timing
 #define PNGTEST_TIMING
 */
@@ -957,7 +969,7 @@
 #ifdef PNG_iCCP_SUPPORTED
    {
       png_charp name;
-      png_charp profile;
+      png_bytep profile;
       png_uint_32 proflen;
       int compression_type;
 
diff --git a/pngtrans.c b/pngtrans.c
index ff851ba..d48ab36 100644
--- a/pngtrans.c
+++ b/pngtrans.c
@@ -1,7 +1,7 @@
 
 /* pngtrans.c - transforms the data in a row (used by both readers and writers)
  *
- * Last changed in libpng 1.5.0 [July 24, 2010]
+ * Last changed in libpng 1.5.0 [July 29, 2010]
  * Copyright (c) 1998-2010 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
diff --git a/pngvalid.c b/pngvalid.c
new file mode 100644
index 0000000..5070e0a
--- /dev/null
+++ b/pngvalid.c
@@ -0,0 +1,2075 @@
+
+/* pngvalid.c - validate libpng by constructing then reading png files.
+ *
+ * Last changed in libpng 1.5.0 [July 5, 2010]
+ * Copyright (c) 2010-2010 Glenn Randers-Pehrson
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
+ * NOTES:
+ *   This is a C program that is intended to be linked against libpng.  It
+ *   generates bitmaps internally, stores them as PNG files (using the
+ *   sequential write code) then reads them back (using the sequential
+ *   read code) and validates that the result has the correct data.
+ *
+ *   The program can be modified and extended to test the correctness of
+ *   transformations performed by libpng.
+ */
+
+#include "png.h"
+#include "zlib.h"   /* For crc32 */
+
+#include <stdlib.h> /* For malloc */
+#include <string.h> /* For memcpy, memset */
+#include <setjmp.h> /* For jmp_buf, setjmp, longjmp */
+#include <math.h>   /* For floor */
+
+/******************************* ERROR UTILITIES ******************************/
+static size_t safecat(char *buffer, size_t bufsize, size_t pos, const char *cat)
+{
+   while (pos < bufsize && cat != NULL && *cat != 0) buffer[pos++] = *cat++;
+   if (pos >= bufsize) pos = bufsize-1;
+   buffer[pos] = 0;
+   return pos;
+}
+
+static size_t safecatn(char *buffer, size_t bufsize, size_t pos, int n)
+{
+   char number[64];
+   sprintf(number, "%d", n);
+   return safecat(buffer, bufsize, pos, number);
+}
+
+static size_t safecatd(char *buffer, size_t bufsize, size_t pos, double d,
+   int precision)
+{
+   char number[64];
+   sprintf(number, "%.*f", precision, d);
+   return safecat(buffer, bufsize, pos, number);
+}
+
+static const char invalid[] = "invalid";
+static const char sep[] = ": ";
+
+/* NOTE: this is indexed by ln2(bit_depth)! */
+static const char *bit_depths[8] =
+{
+   "1", "2", "4", "8", "16", invalid, invalid, invalid
+};
+
+static const char *colour_types[8] =
+{
+   "greyscale", invalid, "truecolour", "indexed-colour",
+   "greyscale with alpha", invalid, "truecolour with alpha", invalid
+};
+
+/* Convenience API to list valid formats: */
+static int
+next_format(png_bytep colour_type, png_bytep bit_depth)
+{
+   if (*bit_depth == 0)
+   {
+      *colour_type = 0, *bit_depth = 1;
+      return 1;
+   }
+   else switch (*colour_type)
+   {
+   case 0:
+      *bit_depth <<= 1;
+      if (*bit_depth <= 16) return 1;
+      *colour_type = 2;
+      *bit_depth = 8;
+      return 1;
+   case 2:
+      *bit_depth <<= 1;
+      if (*bit_depth <= 16) return 1;
+      *colour_type = 3;
+      *bit_depth = 1;
+      return 1;
+   case 3:
+      *bit_depth <<= 1;
+      if (*bit_depth <= 8) return 1;
+      *colour_type = 4;
+      *bit_depth = 8;
+      return 1;
+   case 4:
+      *bit_depth <<= 1;
+      if (*bit_depth <= 16) return 1;
+      *colour_type = 6;
+      *bit_depth = 8;
+      return 1;
+   case 6:
+      *bit_depth <<= 1;
+      if (*bit_depth <= 16) return 1;
+      break;
+   }
+
+   /* Here at the end. */
+   return 0;
+}
+
+static inline unsigned
+sample(png_byte *row, png_byte colour_type, png_byte bit_depth, png_uint_32 x,
+   unsigned sample)
+{
+   png_uint_32 index, result;
+   
+   /* Find a sample index for the desired sample: */
+   x *= bit_depth;
+   index = x;
+   if ((colour_type & 1) == 0) /* !palette */
+   {
+      if (colour_type & 2)
+         index *= 3, index += sample; /* Colour channels; select one */
+      if (colour_type & 4) index += x; /* Alpha channel */
+   }
+
+   /* Return the sample from the row as an integer. */
+   row += index >> 3;
+   result = *row;
+   if (bit_depth == 8)
+      return result;
+   else if (bit_depth > 8)
+      return (result << 8) + *++row;
+   /* Less than 8 bits per sample. */
+   index &= 7;
+   return (result >> (8-index-bit_depth)) & ((1U<<bit_depth)-1);
+}
+
+/*************************** BASIC PNG FILE WRITING ***************************/
+/* A png_sucker takes data from the sequential writer or provides data
+ * to the sequential reader.  It can also store the result of a PNG
+ * write for later retrieval.
+ */
+#define SUCKER_BUFFER_SIZE 500 /* arbitrary */
+typedef struct png_sucker_buffer
+{
+   struct png_sucker_buffer* prev;    /* NOTE: stored in reverse order */
+   png_byte                  buffer[SUCKER_BUFFER_SIZE];
+} png_sucker_buffer;
+
+typedef struct png_sucker_file
+{
+   struct png_sucker_file* next;      /* as many as you like... */
+   char                    name[64];  /* textual name */
+   png_uint_32             id;        /* as a convenience to users */
+   png_size_t              datacount; /* In this (the last) buffer */
+   png_sucker_buffer       data;      /* Last buffer in file */
+} png_sucker_file;
+
+#define SUCKER_ERROR 0x345
+typedef struct png_sucker
+{
+   jmp_buf            jmpbuf;
+   int                verbose;
+   int                nerrors;
+   int                nwarnings;
+   int                treat_warnings_as_errors;
+   char               test[64]; /* Name of test */
+   char               error[128];
+   /* Read fields */
+   png_structp        pread;    /* Used to read a saved file */
+   png_infop          piread;
+   png_sucker_file*   current;  /* Set when reading */
+   png_sucker_buffer* next;     /* Set when reading */
+   png_size_t         readpos;  /* Position in *next */
+   /* Write fields */
+   png_sucker_file*   saved;
+   png_structp        pwrite;   /* Used when writing a new file */
+   png_infop          piwrite;
+   png_size_t         writepos; /* Position in .new */
+   char               wname[64];/* Name of file being written */
+   png_sucker_buffer  new;      /* The end of the new PNG file being written. */
+} png_sucker;
+
+/* Initialization and cleanup */
+static void
+sucker_init(png_sucker* ps)
+{
+   memset(ps, 0, sizeof *ps);
+   ps->verbose = 0;
+   ps->nerrors = ps->nwarnings = 0;
+   ps->treat_warnings_as_errors = 0;
+   ps->pread = NULL;
+   ps->piread = NULL;
+   ps->saved = ps->current = NULL;
+   ps->next = NULL;
+   ps->readpos = 0;
+   ps->pwrite = NULL;
+   ps->piwrite = NULL;
+   ps->writepos = 0;
+   ps->new.prev = NULL;
+}
+
+static void
+sucker_freebuffer(png_sucker_buffer* psb)
+{
+   if (psb->prev)
+   {
+      sucker_freebuffer(psb->prev);
+      free(psb->prev);
+      psb->prev = NULL;
+   }
+}
+
+static void
+sucker_freenew(png_sucker *ps)
+{
+   sucker_freebuffer(&ps->new);
+   ps->writepos = 0;
+}
+
+static void
+sucker_storenew(png_sucker *ps)
+{
+   png_sucker_buffer *pb;
+   if (ps->writepos != SUCKER_BUFFER_SIZE)
+      png_error(ps->pwrite, "invalid store call");
+   pb = malloc(sizeof *pb);
+   if (pb == NULL)
+      png_error(ps->pwrite, "store new: OOM");
+   *pb = ps->new;
+   ps->new.prev = pb;
+   ps->writepos = 0;
+}
+
+static void
+sucker_freefile(png_sucker_file *pf)
+{
+   if (pf->next)
+      sucker_freefile(pf->next);
+   pf->next = NULL;
+   sucker_freebuffer(&pf->data);
+   pf->datacount = 0;
+   free(pf);
+}
+
+/* Main interface to file storeage, after writing a new PNG file (see the API
+ * below) call sucker_storefile to store the result with the given name and id.
+ */
+static void
+sucker_storefile(png_sucker *ps, png_uint_32 id)
+{
+   png_sucker_file *pf = malloc(sizeof *pf);
+   if (pf == NULL)
+      png_error(ps->pwrite, "storefile: OOM");
+   safecat(pf->name, sizeof pf->name, 0, ps->wname);
+   pf->id = id;
+   pf->data = ps->new;
+   pf->datacount = ps->writepos;
+   ps->new.prev = NULL;
+   ps->writepos = 0;
+
+   /* And save it. */
+   pf->next = ps->saved;
+   ps->saved = pf;
+}
+
+/* Generate an error message (in the given buffer) */
+static size_t
+sucker_message(png_structp pp, char *buffer, size_t bufsize, const char *msg)
+{
+   size_t pos = 0;
+   png_sucker *ps = png_get_error_ptr(pp);
+
+   if (pp == ps->pread)
+   {
+      /* Reading a file */
+      pos = safecat(buffer, bufsize, pos, "read: ");
+      if (ps->current != NULL)
+      {
+         pos = safecat(buffer, bufsize, pos, ps->current->name);
+	 pos = safecat(buffer, bufsize, pos, sep);
+      }
+   }
+   else if (pp == ps->pwrite)
+   {
+      /* Writing a file */
+      pos = safecat(buffer, bufsize, pos, "write: ");
+      pos = safecat(buffer, bufsize, pos, ps->wname);
+   }
+   else
+   {
+      /* Neither reading nor writing */
+      pos = safecat(buffer, bufsize, pos, "pngvalid: ");
+   }
+
+   pos = safecat(buffer, bufsize, pos, ps->test);
+   pos = safecat(buffer, bufsize, pos, " ");
+   pos = safecat(buffer, bufsize, pos, msg);
+   return pos;
+}
+
+/* Functions to use as PNG callbacks. */
+static void
+sucker_error(png_structp pp, png_const_charp message) /* PNG_NORETURN */
+{
+   png_sucker *ps = png_get_error_ptr(pp);
+   char buffer[256];
+
+   sucker_message(pp, buffer, sizeof buffer, message);
+
+   if (ps->nerrors++ == 0)
+      safecat(ps->error, sizeof ps->error, 0, buffer);
+
+   if (ps->verbose)
+      fprintf(stderr, "error: %s\n", buffer);
+
+   /* The longjmp argument is because, by UTSL, libpng calls longjmp with 1, and
+    * libpng is *not* expected to ever call longjmp, so this is a sanity
+    * check.  The code below ensures that libpng gets a copy of our jmp_buf.
+    */
+   longjmp(ps->jmpbuf, SUCKER_ERROR);
+}
+
+static void
+sucker_warning(png_structp pp, png_const_charp message)
+{
+   png_sucker *ps = png_get_error_ptr(pp);
+   char buffer[256];
+
+   sucker_message(pp, buffer, sizeof buffer, message);
+
+   if (ps->nwarnings++ == 0 && ps->nerrors == 0)
+      safecat(ps->error, sizeof ps->error, 0, buffer);
+
+   if (ps->verbose)
+      fprintf(stderr, "warning: %s\n", buffer);
+}
+
+static void
+sucker_write(png_structp pp, png_bytep pb, png_size_t st)
+{
+   png_sucker *ps = png_get_io_ptr(pp);
+   if (ps->pwrite != pp)
+      png_error(pp, "sucker state damaged");
+   while (st > 0)
+   {
+      size_t cb;
+
+      if (ps->writepos >= SUCKER_BUFFER_SIZE)
+         sucker_storenew(ps);
+
+      cb = st;
+      if (cb > SUCKER_BUFFER_SIZE - ps->writepos)
+         cb = SUCKER_BUFFER_SIZE - ps->writepos;
+      memcpy(ps->new.buffer + ps->writepos, pb, cb);
+      pb += cb;
+      st -= cb;
+      ps->writepos += cb;
+   }
+}
+
+static void
+sucker_flush(png_structp pp)
+{
+   /*DOES NOTHING*/
+}
+
+static size_t
+sucker_read_buffer_size(png_sucker *ps)
+{
+   /* Return the bytes available for read in the current buffer. */
+   if (ps->next != &ps->current->data)
+      return SUCKER_BUFFER_SIZE;
+
+   return ps->current->datacount;
+}
+
+static int
+sucker_read_buffer_next(png_sucker *ps)
+{
+   png_sucker_buffer *pbOld = ps->next;
+   png_sucker_buffer *pbNew = &ps->current->data;
+   if (pbOld != pbNew)
+   {
+      while (pbNew != NULL && pbNew->prev != pbOld)
+         pbNew = pbNew->prev;
+      if (pbNew != NULL)
+      {
+         ps->next = pbNew;
+	 ps->readpos = 0;
+	 return 1;
+      }
+
+      png_error(ps->pread, "buffer lost");
+   }
+
+   return 0; /* EOF or error */
+}
+
+static void
+sucker_read(png_structp pp, png_bytep pb, png_size_t st)
+{
+   png_sucker *ps = png_get_io_ptr(pp);
+   if (ps->pread != pp || ps->current == NULL || ps->next == NULL)
+      png_error(pp, "sucker state damaged");
+   while (st > 0)
+   {
+      size_t cbAvail = sucker_read_buffer_size(ps) - ps->readpos;
+
+      if (cbAvail > 0)
+      {
+         if (cbAvail > st) cbAvail = st;
+	 memcpy(pb, ps->next->buffer + ps->readpos, cbAvail);
+	 st -= cbAvail;
+	 pb += cbAvail;
+	 ps->readpos += cbAvail;
+      }
+      else if (!sucker_read_buffer_next(ps))
+         png_error(pp, "read beyond end of file");
+   }
+}
+
+/* Setup functions. */
+/* Cleanup when aborting a write or after storing the new file. */
+static void
+sucker_write_reset(png_sucker *ps)
+{
+   if (ps->pwrite != NULL)
+   {
+      png_destroy_write_struct(&ps->pwrite, &ps->piwrite);
+      ps->pwrite = NULL;
+      ps->piwrite = NULL;
+   }
+   
+   sucker_freenew(ps);
+}
+
+/* The following is the main write function, it returns a png_struct and,
+ * optionally, a png)info suitable for writiing a new PNG file.  Use
+ * sucker_storefile above to record this file after it has been written.  The
+ * returned libpng structures as destroyed by sucker_write_reset above.
+ */
+static png_structp
+set_sucker_for_write(png_sucker *ps, png_infopp ppi, const char name[64])
+{
+   if (setjmp(ps->jmpbuf) != 0)
+      return NULL;
+
+   if (ps->pwrite != NULL)
+      png_error(ps->pwrite, "sucker already in use");
+
+   sucker_write_reset(ps);
+   safecat(ps->wname, sizeof ps->wname, 0, name);
+
+   ps->pwrite = png_create_write_struct(PNG_LIBPNG_VER_STRING, ps, sucker_error,
+      sucker_warning);
+   png_set_write_fn(ps->pwrite, ps, sucker_write, sucker_flush);
+
+   if (ppi != NULL)
+      *ppi = ps->piwrite = png_create_info_struct(ps->pwrite);
+
+   return ps->pwrite;
+}
+
+/* Cleanup when finished reading (either due to error or in the success case. )
+ */
+static void
+sucker_read_reset(png_sucker *ps)
+{
+   if (ps->pread != NULL)
+   {
+      png_destroy_read_struct(&ps->pread, &ps->piread, NULL);
+      ps->pread = NULL;
+      ps->piread = NULL;
+   }
+
+   ps->current = NULL;
+   ps->next = NULL;
+   ps->readpos = 0;
+}
+
+static void
+sucker_read_set(png_sucker *ps, png_uint_32 id)
+{
+   png_sucker_file *pf = ps->saved;
+
+   while (pf != NULL)
+   {
+      if (pf->id == id)
+      {
+         ps->current = pf;
+	 ps->next = NULL;
+	 sucker_read_buffer_next(ps);
+	 return;
+      }
+
+      pf = pf->next;
+   }
+
+   png_error(ps->pread, "unable to find file to read");
+}
+
+/* The main interface for reading a saved file - pass the id number of the file
+ * to retrieve.  Ids must be unique or the earlier file will be hidden.  The API
+ * returns a png_struct and, optionally, a png_info.  Both of these will be
+ * destroyed by sucker_read_reset above.
+ */
+static png_structp
+set_sucker_for_read(png_sucker *ps, png_infopp ppi, png_uint_32 id,
+   const char *name)
+{
+   safecat(ps->test, sizeof ps->test, 0, name);
+
+   if (setjmp(ps->jmpbuf) != 0)
+      return NULL;
+
+   if (ps->pread != NULL)
+      png_error(ps->pread, "sucker already in use");
+
+   sucker_read_reset(ps);
+
+   ps->pread = png_create_read_struct(PNG_LIBPNG_VER_STRING, ps, sucker_error,
+      sucker_warning);
+   sucker_read_set(ps, id);
+   png_set_read_fn(ps->pread, ps, sucker_read);
+
+   if (ppi != NULL)
+      *ppi = ps->piread = png_create_info_struct(ps->pread);
+
+   return ps->pread;
+}
+
+/*********************** PNG FILE MODIFICATION ON READ ************************/
+/* Files may be modified on read.  The following structure contains a complete
+ * png_sucker together with extra members to handle modification and a special
+ * read callback for libpng.  To use this the 'modifications' field must be set
+ * to a list of png_modification structures that actually perform the
+ * modification, otherwise a png_modifier is functionally equivalent to a
+ * png_sucker.  There is a special read function, set_modifier_for_read, which
+ * replaces set_sucker_for_read.
+ */
+typedef struct png_modifier
+{
+   png_sucker               this;            /* I am a png_sucker */
+   struct png_modification *modifications;   /* Changes to make */
+   enum modifier_state
+   {
+      modifier_start,                        /* Initial value */
+      modifier_signature,                    /* Have a signature */
+      modifier_IHDR                          /* Have an IHDR */
+   }                        state;           /* My state */
+
+   /* Information from IHDR: */
+   png_byte                 bit_depth;       /* From IHDR */
+   png_byte                 colour_type;     /* From IHDR */
+
+   /* While handling PLTE, IDAT and IEND these chunks may be pended to allow
+    * other chunks to be inserted.
+    */
+   png_uint_32              pending_len;
+   png_uint_32              pending_chunk;
+
+   /* Test values */
+   double                  *gammas;
+   unsigned                 ngammas;
+
+   /* Lowest sbit to test (libpng fails for sbit < 8) */
+   unsigned                 sbitlow;
+
+   /* Error control - these are the limits on errors accepted by the gamma tests
+    * below.
+    */
+   double                   maxout8;  /* Maximum output value error */
+   double                   maxabs8;  /* Abosulte sample error 0..1 */
+   double                   maxpc8;   /* Percentage sample error 0..100% */
+   double                   maxout16; /* Maximum output value error */
+   double                   maxabs16; /* Absolute sample error 0..1 */
+   double                   maxpc16;  /* Percentage sample error 0..100% */
+
+   /* Logged 8 and 16 bit errors ('output' values): */
+   double                   error_gray_2;
+   double                   error_gray_4;
+   double                   error_gray_8;
+   double                   error_gray_16;
+   double                   error_color_8;
+   double                   error_color_16;
+
+   /* Flags: */
+   /* When to use the use_input_precision option: */
+   int                      use_input_precision :1;
+   int                      use_input_precision_sbit :1;
+   int                      use_input_precision_16to8 :1;
+   int                      log :1;   /* Log max error */
+
+   /* Buffer information, the buffer size limits the size of the chunks that can
+    * be modified - they must fit (including header and CRC) into the buffer!
+    */
+   size_t                   flush;           /* Count of bytes to flush */
+   size_t                   buffer_count;    /* Bytes in buffer */
+   size_t                   buffer_position; /* Position in buffer */
+   png_byte                 buffer[1024];
+} png_modifier;
+
+static double abserr(png_modifier *pm, png_byte bit_depth)
+{
+   return bit_depth == 16 ? pm->maxabs16 : pm->maxabs8;
+}
+
+static double pcerr(png_modifier *pm, png_byte bit_depth)
+{
+   return (bit_depth == 16 ? pm->maxpc16 : pm->maxpc8) * .01;
+}
+
+static double outerr(png_modifier *pm, png_byte bit_depth)
+{
+   /* There is a serious error in the 2 and 4 bit grayscale transform because
+    * the gamma table value (8 bits) is simply shifted, not rouned, so the
+    * error in 4 bit greyscale gamma is up to the value below.  This is a hack
+    * to allow pngvalid to succeed:
+    */
+   if (bit_depth == 2)  return .73182-.5;
+   if (bit_depth == 4)  return .90644-.5;
+   if (bit_depth == 16) return pm->maxout16;
+   return pm->maxout8;
+}
+
+/* This returns true if the test should be stopped now because it has already
+ * failed and it is running silently.
+ */
+static int fail(png_modifier *pm)
+{
+   return !pm->log && !pm->this.verbose && (pm->this.nerrors > 0 ||
+      pm->this.treat_warnings_as_errors && pm->this.nwarnings > 0);
+}
+
+static void
+modifier_init(png_modifier *pm)
+{
+   memset(pm, 0, sizeof *pm);
+   sucker_init(&pm->this);
+   pm->modifications = NULL;
+   pm->state = modifier_start;
+   pm->sbitlow = 1;
+   pm->maxout8 = pm->maxpc8 = pm->maxabs8 = 0;
+   pm->maxout16 = pm->maxpc16 = pm->maxabs16 = 0;
+   pm->error_gray_2 = pm->error_gray_4 = pm->error_gray_8 = 0;
+   pm->error_gray_16 = pm->error_color_8 = pm->error_color_16 = 0;
+   pm->use_input_precision = 0;
+   pm->use_input_precision_sbit = 0;
+   pm->use_input_precision_16to8 = 0;
+   pm->log = 0;
+
+   /* Rely on the memset for all the other fields - there are no pointers */
+}
+
+/* One modification strucutre must be provided for each chunk to be modified (in
+ * fact more than one can be provided if multiple separate changes are desired
+ * for a single chunk.)  Modifications include adding a new chunk when a
+ * suitable chunk does not exist.
+ *
+ * The caller of modify_fn will reset the CRC of the chunk and record 'modified'
+ * or 'added' as appropriate if the modify_fn returns 1 (true).  If the
+ * modify_fn is NULL the chunk is simply removed.
+ */
+typedef struct png_modification
+{
+   struct png_modification *next;
+   png_uint_32              chunk;
+   /* If the following is NULL all matching chunks will be removed: */
+   int                    (*modify_fn)(png_structp pp, struct png_modifier *pm,
+                                       struct png_modification *me, int add);
+   /* If the following is set to PLTE, IDAT or IEND and the chunk has not been
+    * found and modified (and there is a modify_fn) the modify_fn will be called
+    * to add the chunk before the relevant chunk.
+    */
+   png_uint_32              add;
+   int                      modified :1;     /* Chunk was modified */
+   int                      added    :1;     /* Chunk was added */
+   int                      removed  :1;     /* Chunk was removed */
+} png_modification;
+
+static void modification_reset(png_modification *pmm)
+{
+   if (pmm != NULL)
+   {
+      pmm->modified = 0;
+      pmm->added = 0;
+      pmm->removed = 0;
+      modification_reset(pmm->next);
+   }
+}
+
+static void
+modification_init(png_modification *pmm)
+{
+   memset(pmm, 0, sizeof *pmm);
+   pmm->next = NULL;
+   pmm->chunk = 0;
+   pmm->modify_fn = NULL;
+   pmm->add = 0;
+   modification_reset(pmm);
+}
+
+static void
+modifier_reset(png_modifier *pm)
+{
+   sucker_read_reset(&pm->this);
+   pm->modifications = NULL;
+   pm->state = modifier_start;
+   pm->bit_depth = pm->colour_type = 0;
+   pm->pending_len = pm->pending_chunk = 0;
+   pm->flush = pm->buffer_count = pm->buffer_position = 0;
+}
+
+/* Convenience macros. */
+#define CHUNK(a,b,c,d) (((a)<<24)+((b)<<16)+((c)<<8)+(d))
+#define CHUNK_IHDR CHUNK(73,72,68,82)
+#define CHUNK_PLTE CHUNK(80,76,84,69)
+#define CHUNK_IDAT CHUNK(73,68,65,84)
+#define CHUNK_IEND CHUNK(73,69,78,68)
+#define CHUNK_cHRM CHUNK(99,72,82,77)
+#define CHUNK_gAMA CHUNK(103,65,77,65)
+#define CHUNK_sBIT CHUNK(115,66,73,84)
+#define CHUNK_sRGB CHUNK(115,82,71,66)
+
+/* The guts of modification are performed during a read. */
+static void
+modifier_crc(png_bytep buffer)
+{
+   /* Recalculate the chunk CRC - a complete chunk must be in
+    * the buffer, at the start.
+    */
+   uInt datalen = png_get_uint_32(buffer);
+   png_save_uint_32(buffer+datalen+8, crc32(0L, buffer+4, datalen+4));
+}
+
+static void
+modifier_setbuffer(png_modifier *pm)
+{
+   modifier_crc(pm->buffer);
+   pm->buffer_count = png_get_uint_32(pm->buffer)+12;
+   pm->buffer_position = 0;
+}
+
+static void
+modifier_read(png_structp pp, png_bytep pb, png_size_t st)
+{
+   png_modifier *pm = png_get_io_ptr(pp);
+
+   while (st > 0)
+   {
+      size_t cb;
+      png_uint_32 len, chunk;
+      png_modification *mod;
+
+      if (pm->buffer_position >= pm->buffer_count) switch (pm->state)
+      {
+      static png_byte sign[8] = { 137, 80, 78, 71, 13, 10, 26, 10 };
+      case modifier_start:
+         sucker_read(pp, pm->buffer, 8); /* size of signature. */
+	 pm->buffer_count = 8;
+	 pm->buffer_position = 0;
+
+	 if (memcmp(pm->buffer, sign, 8) != 0)
+	    png_error(pp, "invalid PNG file signature");
+	 pm->state = modifier_signature;
+	 break;
+
+      case modifier_signature:
+	 sucker_read(pp, pm->buffer, 13+12); /* size of IHDR */
+	 pm->buffer_count = 13+12;
+	 pm->buffer_position = 0;
+
+	 if (png_get_uint_32(pm->buffer) != 13 ||
+	     png_get_uint_32(pm->buffer+4) != CHUNK_IHDR)
+	    png_error(pp, "invalid IHDR");
+
+	 /* Check the list of modifiers for modifications to the IHDR. */
+         mod = pm->modifications;
+	 while (mod != NULL)
+	 {
+	    if (mod->chunk == CHUNK_IHDR && mod->modify_fn &&
+	        (*mod->modify_fn)(pp, pm, mod, 0))
+	       {
+	       mod->modified = 1;
+	       modifier_setbuffer(pm);
+	       }
+
+	    /* Ignore removal or add if IHDR! */
+	    mod = mod->next;
+	 }
+
+	 /* Cache information from the IHDR (the modified one.) */
+	 pm->bit_depth = pm->buffer[8+8];
+	 pm->colour_type = pm->buffer[8+8+1];
+
+	 pm->state = modifier_IHDR;
+	 pm->flush = 0;
+	 break;
+
+      default:
+         /* Read a new chunk and process it until we see PLTE, IDAT or
+	  * IEND.  'flush' indicates that there is still some data to
+	  * output from the preceding chunk.
+	  */
+	 if ((cb = pm->flush) > 0)
+	 {
+	    if (cb > st) cb = st;
+	    pm->flush -= cb;
+	    sucker_read(pp, pb, cb);
+	    pb += cb;
+	    st -= cb;
+	    if (st <= 0) return;
+	 }
+
+	 /* No more bytes to flush, read a header, or handle a pending
+	  * chunk.
+	  */
+	 if (pm->pending_chunk != 0)
+	 {
+	    png_save_uint_32(pm->buffer, pm->pending_len);
+	    png_save_uint_32(pm->buffer+4, pm->pending_chunk);
+	    pm->pending_len = 0;
+	    pm->pending_chunk = 0;
+	 }
+         else
+	    sucker_read(pp, pm->buffer, 8);
+
+	 pm->buffer_count = 8;
+	 pm->buffer_position = 0;
+
+	 /* Check for something to modify or a terminator chunk. */
+	 len = png_get_uint_32(pm->buffer);
+	 chunk = png_get_uint_32(pm->buffer+4);
+
+	 /* Terminators first, they may have to be delayed for added
+	  * chunks
+	  */
+	 if (chunk == CHUNK_PLTE || chunk == CHUNK_IDAT || chunk == CHUNK_IEND)
+	 {
+	    mod = pm->modifications;
+
+	    while (mod != NULL)
+	    {
+	       if ((mod->add == chunk ||
+	           mod->add == CHUNK_PLTE && chunk == CHUNK_IDAT) &&
+		   mod->modify_fn != NULL && !mod->modified && !mod->added)
+	       {
+		  /* Regardless of what the modify function does do not run this
+		   * again.
+		   */
+		  mod->added = 1;
+
+		  if ((*mod->modify_fn)(pp, pm, mod, 1/*add*/))
+		  {
+		     /* Reset the CRC on a new chunk */
+		     if (pm->buffer_count > 0)
+			modifier_setbuffer(pm);
+		     else
+		        {
+			pm->buffer_position = 0;
+			mod->removed = 1;
+			}
+
+		     /* The buffer has been filled with something (we assume) so
+		      * output this.  Pend the current chunk.
+		      */
+		     pm->pending_len = len;
+		     pm->pending_chunk = chunk;
+		     break; /* out of while */
+		  }
+	       }
+
+	       mod = mod->next;
+	    }
+
+	    /* Don't do any further processing if the buffer was modified -
+	     * otherwise the code will end up modifying a chunk that was just
+	     * added.
+	     */
+	    if (mod != NULL)
+	       break; /* out of switch */
+	 }
+
+	 /* If we get to here then this chunk may need to be modified.  To do
+	  * this is must be less than 1024 bytes in total size, otherwise
+	  * it just gets flushed.
+	  */
+	 if (len+12 <= sizeof pm->buffer)
+	 {
+	    sucker_read(pp, pm->buffer+pm->buffer_count,
+	       len+12-pm->buffer_count);
+	    pm->buffer_count = len+12;
+
+	    /* Check for a modification, else leave it be. */
+	    mod = pm->modifications;
+	    while (mod != NULL)
+	    {
+	       if (mod->chunk == chunk)
+	       {
+	          if (mod->modify_fn == NULL)
+		  {
+		     /* Remove this chunk */
+		     pm->buffer_count = pm->buffer_position = 0;
+		     mod->removed = 1;
+		     break; /* Terminate the while loop */
+		  }
+		  else if ((*mod->modify_fn)(pp, pm, mod, 0))
+		  {
+		     mod->modified = 1;
+		     /* The chunk may have been removed: */
+		     if (pm->buffer_count == 0)
+		     {
+		        pm->buffer_position = 0;
+			break;
+		     }
+		     modifier_setbuffer(pm);
+		  }
+	       }
+
+	       mod = mod->next;
+	    }
+	 }
+	 else
+	    pm->flush = len+12 - pm->buffer_count; /* data + crc */
+
+	 /* Take the data from the buffer (if there is any). */
+	 break;
+      }
+
+      /* Here to read from the modifier buffer (not directly from
+       * the sucker, as in the flush case above.)
+       */
+      cb = pm->buffer_count - pm->buffer_position;
+      if (cb > st) cb = st;
+      memcpy(pb, pm->buffer + pm->buffer_position, cb);
+      st -= cb;
+      pb += cb;
+      pm->buffer_position += cb;
+   }
+}
+
+/* Set up a modifier. */
+static png_structp
+set_modifier_for_read(png_modifier *pm, png_infopp ppi, png_uint_32 id,
+   const char *name)
+{
+   png_structp pp = set_sucker_for_read(&pm->this, ppi, id, name);
+
+   if (pp != NULL)
+   {
+      if (setjmp(pm->this.jmpbuf) == 0)
+      {
+	 png_set_read_fn(pp, pm, modifier_read);
+
+	 pm->state = modifier_start;
+	 pm->bit_depth = 0;
+	 pm->colour_type = 255;
+
+	 pm->pending_len = 0;
+	 pm->pending_chunk = 0;
+	 pm->flush = 0;
+	 pm->buffer_count = 0;
+	 pm->buffer_position = 0;
+      }
+      else
+      {
+	 sucker_read_reset(&pm->this);
+	 pp = NULL;
+      }
+   }
+
+   return pp;
+}
+
+/***************************** STANDARD PNG FILES *****************************/
+/* Standard files - write and save standard files. */
+/* The standard files are constructed with rows which fit into a 1024 byte row
+ * buffer.  This makes allocation easier below.  Further regardless of the file
+ * format every file has 128 pixels (giving 1024 bytes for 64bpp formats).
+ *
+ * Files are stored with no gAMA or sBIT chunks, with a PLTE only when needed
+ * and with an ID derived from the colour type and bit depth as follows:
+ */
+#define FILEID(col, depth) ((png_uint_32)((col) + ((depth)<<3)))
+#define COL_FROM_ID(id) ((id)& 0x7)
+#define DEPTH_FROM_ID(id) (((id) >> 3) & 0x1f)
+
+#define STD_WIDTH  128
+#define STD_ROWMAX (STD_WIDTH*8)
+
+static unsigned
+bit_size(png_structp pp, png_byte colour_type, png_byte bit_depth)
+{
+   switch (colour_type)
+   {
+   case 0:  return bit_depth;
+   case 2:  return 3*bit_depth;
+   case 3:  return bit_depth;
+   case 4:  return 2*bit_depth;
+   case 6:  return 4*bit_depth;
+   default: png_error(pp, "invalid color type");
+   }
+}
+
+static size_t
+standard_rowsize(png_structp pp, png_byte colour_type, png_byte bit_depth)
+{
+   return (STD_WIDTH * bit_size(pp, colour_type, bit_depth)) / 8;
+}
+
+static png_uint_32
+standard_width(png_structp pp, png_byte colour_type, png_byte bit_depth)
+{
+   return STD_WIDTH;
+}
+
+static png_uint_32
+standard_height(png_structp pp, png_byte colour_type, png_byte bit_depth)
+{
+   switch (bit_size(pp, colour_type, bit_depth))
+   {
+   case 1:
+   case 2:
+   case 4:
+      return 1;   /* Total of 128 pixels */
+   case 8:
+      return 2;   /* Total of 256 pixels/bytes */
+   case 16:
+      return 512; /* Total of 65536 pixels */
+   case 24:
+   case 32:
+      return 512; /* 65536 pixels */
+   case 48:
+   case 64:
+      return 2048;/* 4 x 65536 pixels. */
+   }
+}
+
+static void
+standard_row(png_structp pp, png_byte buffer[STD_ROWMAX], png_byte colour_type,
+   png_byte bit_depth, png_uint_32 y)
+{
+   png_uint_32 v = y << 7;
+   png_uint_32 i = 0;
+
+   switch (bit_size(pp, colour_type, bit_depth))
+   {
+   case 1:
+      while (i<128/8) buffer[i] = v & 0xff, v += 17, ++i;
+      return;
+   case 2:
+      while (i<128/4) buffer[i] = v & 0xff, v += 33, ++i;
+      return;
+   case 4:
+      while (i<128/2) buffer[i] = v & 0xff, v += 65, ++i;
+      return;
+   case 8:
+      /* 256 bytes total, 128 bytes in each row set as follows: */
+      while (i<128) buffer[i] = v & 0xff, ++v, ++i;
+      return;
+   case 16:
+      /* Generate all 65536 pixel values in order, this includes the 8 bit GA
+       * case as we as the 16 bit G case.
+       */
+      while (i<128)
+         buffer[2*i] = (v>>8) & 0xff, buffer[2*i+1] = v & 0xff, ++v, ++i;
+      return;
+   case 24:
+      /* 65535 pixels, but rotate the values. */
+      while (i<128)
+      {
+	 /* Three bytes per pixel, r, g, b, make b by r^g */
+	 buffer[3*i+0] = (v >> 8) & 0xff;
+	 buffer[3*i+1] = v & 0xff;
+	 buffer[3*i+2] = ((v >> 8) ^ v) & 0xff;
+	 ++v;
+         ++i;
+      }
+      return;
+   case 32:
+      /* 65535 pixels, r, g, b, a; just replicate */
+      while (i<128)
+      {
+	 buffer[4*i+0] = (v >> 8) & 0xff;
+	 buffer[4*i+1] = v & 0xff;
+	 buffer[4*i+2] = (v >> 8) & 0xff;
+	 buffer[4*i+3] = v & 0xff;
+	 ++v;
+         ++i;
+      }
+      return;
+   case 48:
+      /* y is maximum 2047, giving 4x65536 pixels, make 'r' increase by 1 at
+       * each pixel, g increase by 257 (0x101) and 'b' by 0x1111:
+       */
+      while (i<128)
+      {
+	 png_uint_32 t = v++;
+	 buffer[6*i+0] = (t >> 8) & 0xff;
+	 buffer[6*i+1] = t & 0xff;
+	 t *= 257;
+	 buffer[6*i+2] = (t >> 8) & 0xff;
+	 buffer[6*i+3] = t & 0xff;
+	 t *= 17;
+	 buffer[6*i+4] = (t >> 8) & 0xff;
+	 buffer[6*i+5] = t & 0xff;
+         ++i;
+      }
+      return;
+   case 64:
+      /* As above in the 32 bit case. */
+      while (i<128)
+      {
+	 png_uint_32 t = v++;
+	 buffer[8*i+0] = (t >> 8) & 0xff;
+	 buffer[8*i+1] = t & 0xff;
+	 buffer[8*i+4] = (t >> 8) & 0xff;
+	 buffer[8*i+5] = t & 0xff;
+	 t *= 257;
+	 buffer[8*i+2] = (t >> 8) & 0xff;
+	 buffer[8*i+3] = t & 0xff;
+	 buffer[8*i+6] = (t >> 8) & 0xff;
+	 buffer[8*i+7] = t & 0xff;
+         ++i;
+      }
+      return;
+   }
+
+   png_error(pp, "internal error");
+}
+
+static void
+make_standard(png_sucker* ps, png_byte colour_type, int bdlo, int bdhi)
+{
+   for (; bdlo <= bdhi; ++bdlo)
+   {
+      png_byte bit_depth = 1U << bdlo;
+      png_uint_32 h, y;
+      png_structp pp;
+      png_infop pi;
+
+      {
+	 size_t pos;
+	 char name[64];  /* Same size as the buffer in a file. */
+
+	 /* Build a name */
+	 pos = safecat(name, sizeof name, 0, bit_depths[bdlo]);
+	 pos = safecat(name, sizeof name, pos, "bit ");
+	 pos = safecat(name, sizeof name, pos, colour_types[colour_type]);
+
+	 /* Get a png_struct for writing the image. */
+	 pp = set_sucker_for_write(ps, &pi, name);
+      }
+      if (pp == NULL) return;
+
+      /* Do the honourable write stuff, protected by a local setjmp */
+      if (setjmp(ps->jmpbuf) != 0)
+      {
+         sucker_write_reset(ps);
+	 continue;
+      }
+
+      h = standard_height(pp, colour_type, bit_depth),
+      png_set_IHDR(pp, pi, standard_width(pp, colour_type, bit_depth), h,
+         bit_depth, colour_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
+	 PNG_FILTER_TYPE_BASE);
+
+      if (colour_type == 3) /* palette */
+      {
+	 int i;
+         png_color pal[256];
+	 for (i=0; i<256; ++i) pal[i].red = pal[i].green = pal[i].blue = i;
+         png_set_PLTE(pp, pi, pal, 256);
+      }
+
+      png_write_info(pp, pi);
+
+      if (png_get_rowbytes(pp, pi) !=
+          standard_rowsize(pp, colour_type, bit_depth))
+         png_error(pp, "row size incorrect");
+
+      else for (y=0; y<h; ++y)
+      {
+         png_byte buffer[STD_ROWMAX];
+	 standard_row(pp, buffer, colour_type, bit_depth, y);
+         png_write_row(pp, buffer);
+      }
+
+      png_write_end(pp, pi);
+
+      /* And store this under the appropriate id, then clean up. */
+      sucker_storefile(ps, FILEID(colour_type, bit_depth));
+
+      sucker_write_reset(ps);
+   }
+}
+
+static void
+make_standard_images(png_sucker *ps)
+{
+   /* Arguments are colour_type, low bit depth, high bit depth */
+   make_standard(ps, 0, 0, 4);
+   make_standard(ps, 2, 3, 4);
+   make_standard(ps, 3, 0, 3);
+   make_standard(ps, 4, 3, 4);
+   make_standard(ps, 6, 3, 4);
+}
+
+/* Tests - individual test cases */
+static void
+test_standard(png_sucker* ps, png_byte colour_type, int bdlo, int bdhi)
+{
+   for (; bdlo <= bdhi; ++bdlo)
+   {
+      png_byte bit_depth = 1U << bdlo;
+      png_uint_32 h, y;
+      size_t cb;
+      png_structp pp;
+      png_infop pi;
+
+      /* Get a png_struct for writing the image. */
+      pp = set_sucker_for_read(ps, &pi, FILEID(colour_type, bit_depth),
+         "standard");
+      if (pp == NULL) return;
+
+      /* Do the honourable write stuff, protected by a local setjmp */
+      if (setjmp(ps->jmpbuf) != 0)
+      {
+         sucker_read_reset(ps);
+	 continue;
+      }
+
+      h = standard_height(pp, colour_type, bit_depth);
+
+      /* Check the header values: */
+      png_read_info(pp, pi);
+
+      if (png_get_image_width(pp, pi) !=
+          standard_width(pp, colour_type, bit_depth))
+         png_error(pp, "validate: image width changed");
+      if (png_get_image_height(pp, pi) != h)
+         png_error(pp, "validate: image height changed");
+      if (png_get_bit_depth(pp, pi) != bit_depth)
+         png_error(pp, "validate: bit depth changed");
+      if (png_get_color_type(pp, pi) != colour_type)
+         png_error(pp, "validate: color type changed");
+      if (png_get_filter_type(pp, pi) != PNG_FILTER_TYPE_BASE)
+         png_error(pp, "validate: filter type changed");
+      if (png_get_interlace_type(pp, pi) != PNG_INTERLACE_NONE)
+         png_error(pp, "validate: interlacing changed");
+      if (png_get_compression_type(pp, pi) != PNG_COMPRESSION_TYPE_BASE)
+         png_error(pp, "validate: compression type changed");
+      if (png_set_interlace_handling(pp) != 1)
+         png_error(pp, "validate: interlacing unexpected");
+
+      if (colour_type == 3) /* palette */
+      {
+	 png_colorp pal;
+	 int num;
+	 if (png_get_PLTE(pp, pi, &pal, &num) & PNG_INFO_PLTE)
+	 {
+	    int i;
+	    if (num != 256)
+	       png_error(pp, "validate: color type 3 PLTE chunk size changed");
+	    for (i=0; i<num; ++i)
+	       if (pal[i].red != i || pal[i].green != i || pal[i].blue != i)
+	          png_error(pp, "validate: color type 3 PLTE chunk changed");
+	 }
+	 else
+	    png_error(pp, "validate: missing PLTE with color type 3");
+      }
+
+      cb = standard_rowsize(pp, colour_type, bit_depth);
+      png_start_read_image(pp);
+
+      if (png_get_rowbytes(pp, pi) != cb)
+         png_error(pp, "validate: row size changed");
+
+      else for (y=0; y<h; ++y)
+      {
+         png_byte std[STD_ROWMAX];
+	 png_byte read[STD_ROWMAX];
+	 png_byte display[STD_ROWMAX];
+
+	 standard_row(pp, std, colour_type, bit_depth, y);
+         png_read_row(pp, read, display);
+
+         if (memcmp(std, read, cb) != 0)
+	 {
+	    char msg[64];
+	    sprintf(msg, "validate: PNG image row %d (of %d) changed", y,
+	       h);
+	    png_error(pp, msg);
+	 }
+         if (memcmp(std, display, cb) != 0)
+	 {
+	    char msg[64];
+	    sprintf(msg, "validate: transformed row %d (of %d) changed", y, h);
+	    png_error(pp, msg);
+         }
+      }
+
+      png_read_end(pp, pi);
+
+      sucker_read_reset(ps);
+   }
+}
+
+static void
+perform_standard_test(png_modifier *pm)
+{
+   test_standard(&pm->this, 0, 0, 4);
+   if (fail(pm)) return;
+   test_standard(&pm->this, 2, 3, 4);
+   if (fail(pm)) return;
+   test_standard(&pm->this, 3, 0, 3);
+   if (fail(pm)) return;
+   test_standard(&pm->this, 4, 3, 4);
+   if (fail(pm)) return;
+   test_standard(&pm->this, 6, 3, 4);
+}
+
+
+/********************************* GAMMA TESTS ********************************/
+/* Gamma test images. */
+static void
+make_gamma_images(png_sucker *ps)
+{
+   /* Do nothing - the standard greyscale images are used. */
+}
+
+typedef struct gamma_modification
+{
+   png_modification this;
+   png_fixed_point  gamma;
+}
+gamma_modification;
+
+static int
+gamma_modify(png_structp pp, png_modifier *pm, png_modification *me, int add)
+{
+   /* This simply dumps the given gamma value into the buffer. */
+   png_save_uint_32(pm->buffer, 4);
+   png_save_uint_32(pm->buffer+4, CHUNK_gAMA);
+   png_save_uint_32(pm->buffer+8, ((gamma_modification*)me)->gamma);
+   return 1;
+}
+
+static void
+gamma_modification_init(gamma_modification *me, png_modifier *pm, double gamma)
+{
+   modification_init(&me->this);
+   me->this.chunk = CHUNK_gAMA;
+   me->this.modify_fn = gamma_modify;
+   me->this.add = CHUNK_PLTE;
+   me->gamma = floor(gamma * 100000 + .5);
+   me->this.next = pm->modifications;
+   pm->modifications = &me->this;
+}
+
+typedef struct srgb_modification
+{
+   png_modification this;
+   png_byte         intent;
+}
+srgb_modification;
+
+static int
+srgb_modify(png_structp pp, png_modifier *pm, png_modification *me, int add)
+{
+   /* As above, ignore add and just make a new chunk */
+   png_save_uint_32(pm->buffer, 1);
+   png_save_uint_32(pm->buffer+4, CHUNK_sRGB);
+   pm->buffer[8] = ((srgb_modification*)me)->intent;
+   return 1;
+}
+
+static void
+srgb_modification_init(srgb_modification *me, png_modifier *pm, png_byte intent)
+{
+   modification_init(&me->this);
+   me->this.chunk = CHUNK_sBIT;
+   if (intent <= 3) /* if valid, else *delete* sRGB chunks */
+   {
+      me->this.modify_fn = srgb_modify;
+      me->this.add = CHUNK_PLTE;
+      me->intent = intent;
+   }
+   else
+   {
+      me->this.modify_fn = 0;
+      me->this.add = 0;
+      me->intent = 0;
+   }
+   me->this.next = pm->modifications;
+   pm->modifications = &me->this;
+}
+
+typedef struct sbit_modification
+{
+   png_modification this;
+   png_byte         sbit;
+}
+sbit_modification;
+
+static int
+sbit_modify(png_structp pp, png_modifier *pm, png_modification *me, int add)
+{
+   png_byte sbit = ((sbit_modification*)me)->sbit;
+   if (pm->bit_depth > sbit)
+   {
+      int cb = 0;
+      switch (pm->colour_type)
+      {
+      case 0: cb = 1; break;
+      case 2:
+      case 3: cb = 3; break;
+      case 4: cb = 2; break;
+      case 6: cb = 4; break;
+      default:
+	 png_error(pp, "unexpected colour type in sBIT modification");
+      }
+
+      png_save_uint_32(pm->buffer, cb);
+      png_save_uint_32(pm->buffer+4, CHUNK_sBIT);
+      while (cb > 0)
+	 (pm->buffer+8)[--cb] = sbit;
+
+      return 1;
+   }
+   else if (!add)
+   {
+      /* Remove the sBIT chunk */
+      pm->buffer_count = pm->buffer_position = 0;
+      return 1;
+   }
+   else
+      return 0; /* do nothing */
+}
+
+static void
+sbit_modification_init(sbit_modification *me, png_modifier *pm, png_byte sbit)
+{
+   modification_init(&me->this);
+   me->this.chunk = CHUNK_sBIT;
+   me->this.modify_fn = sbit_modify;
+   me->this.add = CHUNK_PLTE;
+   me->sbit = sbit;
+   me->this.next = pm->modifications;
+   pm->modifications = &me->this;
+}
+
+/* maxabs: maximum absolute error as a fraction
+ * maxout: maximum output error in the output units
+ * maxpc:  maximum percentage error (as a percentage)
+ */
+static void
+gamma_test(png_modifier *pm, const png_byte colour_type,
+   const png_byte bit_depth, const double file_gamma, const double screen_gamma,
+   const png_byte sbit, const int threshold_test, const char *name,
+   const int speed, const int use_input_precision, const int strip16)
+{
+   png_structp pp;
+   png_infop pi;
+   double maxerrout = 0, maxerrpc = 0, maxerrabs = 0;
+
+   gamma_modification gamma_mod;
+   srgb_modification srgb_mod;
+   sbit_modification sbit_mod;
+
+   /* Make an appropriate modifier to set the PNG file gamma to the
+    * given gamma value and the sBIT chunk to the given precision.
+    */
+   pm->modifications = NULL;
+   gamma_modification_init(&gamma_mod, pm, file_gamma);
+   srgb_modification_init(&srgb_mod, pm, 127/*delete*/);
+   sbit_modification_init(&sbit_mod, pm, sbit);
+
+   modification_reset(pm->modifications);
+
+   /* Get a png_struct for writing the image. */
+   pp = set_modifier_for_read(pm, &pi, FILEID(colour_type, bit_depth), name);
+   if (pp == NULL) return;
+
+   /* Do the honourable write stuff, protected by a local setjmp */
+   if (setjmp(pm->this.jmpbuf) != 0)
+   {
+      modifier_reset(pm);
+      return;
+   }
+
+   /* Set up gamma processing. */
+   png_set_gamma(pp, screen_gamma, file_gamma);
+
+   /* Check the header values: */
+   png_read_info(pp, pi);
+
+   /* If requested strip 16 to 8 bits - this is handled automagically below
+    * because the output bit depth is read from the library.  Note that there
+    * are interactions with sBIT but, internally, libpng makes sbit at most
+    * PNG_MAX_GAMMA_8 when doing the following.
+    */
+   if (strip16)
+      png_set_strip_16(pp);
+
+   if (png_set_interlace_handling(pp) != 1)
+      png_error(pp, "gamma: interlaced images not supported");
+
+   png_read_update_info(pp, pi);
+
+   {
+      const png_byte out_ct = png_get_color_type(pp, pi);
+      const png_byte out_bd = png_get_bit_depth(pp, pi);
+      const unsigned outmax = (1U<<out_bd)-1;
+      const png_uint_32 w = png_get_image_width(pp, pi);
+      const png_uint_32 h = png_get_image_height(pp, pi);
+      const size_t cb = png_get_rowbytes(pp, pi); /* For the memcmp below. */
+      const double maxabs = abserr(pm, out_bd);
+      const double maxout = outerr(pm, out_bd);
+      const double maxpc = pcerr(pm, out_bd);
+      png_uint_32 y;
+
+      /* There are three sources of error, firstly the quantization in the file
+       * encoding, determined by sbit and/or the file depth, secondly the output
+       * (screen) gamma and thirdly the output file encoding.  Since this API
+       * receives the screen and file gamma in double precision it is possible
+       * to calculate an exact answer given an input pixel value.  Therefore we
+       * assume that the *input* value is exact - sample/maxsample - calculate
+       * the corresponding gamma corrected output to the limits of double
+       * precision arithmetic and compare with what libpng returns.
+       *
+       * Since the library must quantise the output to 8 or 16 bits there is a
+       * fundamental limit on the accuracy of the output of +/-.5 - this
+       * quantisation limit is included in addition to the other limits
+       * specified by the paramaters to the API.  (Effectively, add .5
+       * everywhere.)
+       *
+       * The behavior of the 'sbit' paramter is defined by section 12.5 (sample
+       * depth scaling) of the PNG spec.  That section forces the decoder to
+       * assume that the PNG values have been scaled if sBIT is presence:
+       *
+       *     png-sample = floor( input-sample * (max-out/max-in) + .5 );
+       *
+       * This means that only a subset of the possible PNG values should appear
+       * in the input, however the spec allows the encoder to use a variety of
+       * approximations to the above and doesn't require any restriction of the
+       * values produced.
+       *
+       * Nevertheless the spec requires that the upper 'sBIT' bits of the value
+       * stored in a PNG file be the original sample bits.  Consequently the
+       * code below simply scales the top sbit bits by (1<<sbit)-1 to obtain an
+       * original sample value.
+       *
+       * Because there is limited precision in the input it is arguable that an
+       * acceptable result is any valid result from input-.5 to input+.5.  The
+       * basic tests below do not do this, however if 'use_input_precision' is
+       * set a subsequent test is performed below.
+       */
+      const int processing = (fabs(screen_gamma*file_gamma-1) >=
+         PNG_GAMMA_THRESHOLD && !threshold_test && !speed && colour_type != 3)
+	 || bit_depth != out_bd;
+      const int samples_per_pixel = (out_ct & 2) ? 3 : 1;
+      const double gamma = 1/(file_gamma*screen_gamma); /* Overall correction */
+
+      for (y=0; y<h; ++y) /* just one pass - no interlacing */
+      {
+	 unsigned s, x;
+	 png_byte std[STD_ROWMAX];
+	 png_byte display[STD_ROWMAX];
+
+	 standard_row(pp, std, colour_type, bit_depth, y);
+	 png_read_row(pp, NULL, display);
+
+	 if (processing) for (x=0; x<w; ++x) for (s=0; s<samples_per_pixel; ++s)
+	 {
+	    /* Input sample values: */
+	    const unsigned id = sample(std, colour_type, bit_depth, x, s);
+	    const unsigned od = sample(display, out_ct, out_bd, x, s);
+	    const unsigned isbit = id >> (bit_depth-sbit);
+	    double i, sample, encoded_sample, output, encoded_error, error;
+	    double es_lo, es_hi;
+
+	    /* First check on the 'perfect' result obtained from the digitized
+	     * input value, id, and compare this against the actual digitized
+	     * result, 'od'.  'i' is the input result in the range 0..1:
+	     *
+	     * NOTE: sbit should be taken into account here but isn't, as
+	     * described above.
+	     */
+	    i = isbit; i /= (1U<<sbit)-1;
+
+	    /* Then get the gamma corrected version of 'i' and compare to 'od',
+	     * any error less than .5 is insignificant - just quantization of
+	     * the output value to the nearest digital value (neverthelss the
+	     * error is still recorded - it's interesting ;-)
+	     */
+	    encoded_sample = pow(i, gamma) * outmax;
+	    encoded_error = fabs(od-encoded_sample);
+
+	    if (encoded_error > maxerrout)
+	       maxerrout = encoded_error;
+
+	    if (encoded_error < .5+maxout)
+	       continue;
+
+	    /* There may be an error, calculate the actual sample values -
+	     * unencoded light intensity values.  Note that in practice these
+	     * are not unencoded because they include a 'viewing correction' to
+	     * decrease or (normally) increase the perceptual contrast of the
+	     * image.  There's nothing we can do about this - we don't know what
+	     * it is - so assume the unencoded value is perceptually linear.
+	     */
+	    sample = pow(i, 1/file_gamma); /* In range 0..1 */
+	    output = od;
+	    output /= outmax;
+	    output = pow(output, screen_gamma);
+
+	    /* Now we have the numbers for real errors, both absolute values as
+	     * as a percentage of the correct value (output):
+	     */
+	    error = fabs(sample-output);
+	    if (error > maxerrabs)
+	       maxerrabs = error;
+	    /* The following is an attempt to ignore the tendency of
+	     * quantization to dominate the percentage errors for low output
+	     * sample values:
+	     */
+	    if (sample*maxpc > .5+maxabs)
+	    {
+	       double pcerr = error/sample;
+	       if (pcerr > maxerrpc) maxerrpc = pcerr;
+	    }
+
+	    /* Now calculate the digitization limits for 'encoded_sample' using
+	     * the 'max' values.  Note that maxout is in the encoded space but
+	     * maxpc and maxabs are in linear light space.
+	     *
+	     * First find the maximum error in linear light space, range 0..1:
+	     */
+	    {
+	       double tmp = sample * maxpc;
+	       if (tmp < maxabs) tmp = maxabs;
+
+	       /* Low bound - the minimum of the three: */
+	       es_lo = encoded_sample - maxout;
+	       if (es_lo > 0 && sample-tmp > 0)
+	       {
+		  double l = outmax * pow(sample-tmp, 1/screen_gamma);
+		  if (l < es_lo) es_lo = l;
+	       }
+	       else
+	          es_lo = 0;
+
+	       es_hi = encoded_sample + maxout;
+	       if (es_hi < outmax && sample+tmp < 1)
+	       {
+		  double h = outmax * pow(sample+tmp, 1/screen_gamma);
+		  if (h > es_hi) es_hi = h;
+	       }
+	       else
+	          es_hi = outmax;
+	    }
+
+	    /* The primary test is that the final encoded value returned by the
+	     * library should be between the two limits (inclusive) that were
+	     * calculated above.  At this point quantization of the output must
+	     * be taken into account.
+	     */
+	    if (od+.5 < es_lo || od-.5 > es_hi)
+	    {
+	       /* Thee has been an error in processing. */
+	       double is_lo, is_hi;
+
+	       if (use_input_precision)
+	       {
+		  /* Ok, something is wrong - this actually happens in current
+		   * libpng sbit processing.  Assume that the input value (id,
+		   * adjusted for sbit) can be anywhere between value-.5 and
+		   * value+.5 - quite a large range if sbit is low.
+		   */
+		  double tmp = (isbit - .5)/((1U<<sbit)-1);
+		  if (tmp > 0)
+		  {
+		     is_lo = outmax * pow(tmp, gamma) - maxout;
+		     if (is_lo < 0) is_lo = 0;
+		  }
+		  else
+		     is_lo = 0;
+
+		  tmp = (isbit + .5)/((1U<<sbit)-1);
+		  if (tmp < 1)
+		  {
+		     is_hi = outmax * pow(tmp, gamma) + maxout;
+		     if (is_hi > outmax) is_hi = outmax;
+		  }
+		  else
+		     is_hi = outmax;
+
+		  if (!(od+.5 < is_lo || od-.5 > is_hi))
+		     continue;
+	       }
+
+	       {
+		  char msg[256];
+	          sprintf(msg,
+		     "error: %.3f; %u{%u;%u} -> %u not %.2f (%.1f-%.1f)",
+		     od-encoded_sample, id, sbit, isbit, od, encoded_sample,
+		     use_input_precision ? is_lo : es_lo,
+		     use_input_precision ? is_hi : es_hi);
+	          png_warning(pp, msg);
+	       }
+	    }
+	 }
+	 else if (!speed && memcmp(std, display, cb) != 0)
+	 {
+	    char msg[64];
+	    /* No transform is expected on the threshold tests. */
+	    sprintf(msg, "gamma: below threshold row %d (of %d) changed", y, h);
+	    png_error(pp, msg);
+	 }
+      }
+   }
+
+   png_read_end(pp, pi);
+   modifier_reset(pm);
+
+   if (pm->log && !threshold_test && !speed)
+      fprintf(stderr, "%d bit %s %s: max error %f (%.2g, %2g%%)\n", bit_depth,
+         colour_types[colour_type], name, maxerrout, maxerrabs, 100*maxerrpc);
+
+   /* Log the summary values too. */
+   if (colour_type == 0 || colour_type == 4) switch (bit_depth)
+   {
+   case 2:
+      if (maxerrout > pm->error_gray_2) pm->error_gray_2 = maxerrout; break;
+   case 4:
+      if (maxerrout > pm->error_gray_4) pm->error_gray_4 = maxerrout; break;
+   case 8:
+      if (maxerrout > pm->error_gray_8) pm->error_gray_8 = maxerrout; break;
+   case 16:
+      if (maxerrout > pm->error_gray_16) pm->error_gray_16 = maxerrout; break;
+   }
+   else if (colour_type == 2 || colour_type == 6) switch (bit_depth)
+   {
+   case 8:
+      if (maxerrout > pm->error_color_8) pm->error_color_8 = maxerrout; break;
+   case 16:
+      if (maxerrout > pm->error_color_16) pm->error_color_16 = maxerrout; break;
+   }
+}
+
+static void gamma_threshold_test(png_modifier *pm, png_byte colour_type,
+   png_byte bit_depth, double file_gamma, double screen_gamma)
+{
+   size_t pos = 0;
+   char name[64];
+   pos = safecat(name, sizeof name, pos, "threshold ");
+   pos = safecatd(name, sizeof name, pos, file_gamma, 3);
+   pos = safecat(name, sizeof name, pos, "/");
+   pos = safecatd(name, sizeof name, pos, screen_gamma, 3);
+
+   (void)gamma_test(pm, colour_type, bit_depth, file_gamma, screen_gamma,
+      bit_depth, 1, name, 0/*speed*/, 0/*no input precision*/, 0/*no strip16*/);
+}
+
+static void
+perform_gamma_threshold_tests(png_modifier *pm)
+{
+   png_byte colour_type = 0;
+   png_byte bit_depth = 0;
+
+   while (next_format(&colour_type, &bit_depth))
+   {
+      double gamma = 1.0;
+      while (gamma >= .4)
+      {
+	 gamma_threshold_test(pm, colour_type, bit_depth, gamma, 1/gamma);
+	 gamma *= .95;
+      }
+
+      /* And a special test for sRGB */
+      gamma_threshold_test(pm, colour_type, bit_depth, .45455, 2.2);
+      if (fail(pm)) return;
+   }
+}
+
+static void gamma_transform_test(png_modifier *pm, const png_byte colour_type,
+   const png_byte bit_depth, const double file_gamma, const double screen_gamma,
+   const png_byte sbit, const int speed, const int use_input_precision,
+   const int strip16)
+{
+   size_t pos = 0;
+   char name[64];
+   if (sbit != bit_depth)
+   {
+      pos = safecat(name, sizeof name, pos, "sbit(");
+      pos = safecatn(name, sizeof name, pos, sbit);
+      pos = safecat(name, sizeof name, pos, ") ");
+   }
+   else
+      pos = safecat(name, sizeof name, pos, "gamma ");
+   if (strip16)
+      pos = safecat(name, sizeof name, pos, "16to8 ");
+   pos = safecatd(name, sizeof name, pos, file_gamma, 3);
+   pos = safecat(name, sizeof name, pos, "->");
+   pos = safecatd(name, sizeof name, pos, screen_gamma, 3);
+
+   gamma_test(pm, colour_type, bit_depth, file_gamma, screen_gamma, sbit, 0,
+      name, speed, use_input_precision, strip16);
+}
+
+static void perform_gamma_transform_tests(png_modifier *pm, int speed)
+{
+   png_byte colour_type = 0;
+   png_byte bit_depth = 0;
+
+   /* Ignore palette images - the gamma correction happens on the palette entry,
+    * haven't got the tests for this yet.
+    */
+   while (next_format(&colour_type, &bit_depth)) if (colour_type != 3)
+   {
+      int i, j;
+
+      for (i=0; i<pm->ngammas; ++i) for (j=0; j<pm->ngammas; ++j) if (i != j)
+      {
+	 gamma_transform_test(pm, colour_type, bit_depth, 1/pm->gammas[i],
+	    pm->gammas[j], bit_depth, speed, pm->use_input_precision,
+	    0/*do not strip16*/);
+         if (fail(pm)) return;
+      }
+   }
+}
+
+static void perform_gamma_sbit_tests(png_modifier *pm, int speed)
+{
+   png_byte sbit;
+
+   /* The only interesting cases are colour and grayscale, alpha is ignored here
+    * for overall speed.  Only bit depths 8 and 16 are tested.
+    */
+   for (sbit=pm->sbitlow; sbit<16; ++sbit)
+   {
+      int i, j;
+      for (i=0; i<pm->ngammas; ++i) for (j=0; j<pm->ngammas; ++j)
+         if (i != j)
+      {
+	 if (sbit < 8)
+	 {
+	    gamma_transform_test(pm, 0, 8, 1/pm->gammas[i], pm->gammas[j], sbit,
+	       speed, pm->use_input_precision_sbit, 0/*strip16*/);
+	    if (fail(pm)) return;
+	    gamma_transform_test(pm, 2, 8, 1/pm->gammas[i], pm->gammas[j], sbit,
+	       speed, pm->use_input_precision_sbit, 0/*strip16*/);
+	    if (fail(pm)) return;
+	 }
+	 gamma_transform_test(pm, 0, 16, 1/pm->gammas[i], pm->gammas[j], sbit,
+	    speed, pm->use_input_precision_sbit, 0/*strip16*/);
+         if (fail(pm)) return;
+	 gamma_transform_test(pm, 2, 16, 1/pm->gammas[i], pm->gammas[j], sbit,
+	    speed, pm->use_input_precision_sbit, 0/*strip16*/);
+         if (fail(pm)) return;
+      }
+   }
+}
+
+static void perform_gamma_strip16_tests(png_modifier *pm, int speed)
+{
+#  ifndef PNG_MAX_GAMMA_8
+#     define PNG_MAX_GAMMA_8 11
+#  endif
+   /* Include the alpha cases here, not that sbit matches the internal value
+    * used by the library - otherwise we will get spurious errors from the
+    * internal sbit style approximation.
+    *
+    * The threshold test is here because otherwise the 16 to 8 convertion will
+    * proceed *without* gamma correction, and the tests above will fail (but not
+    * by much) - this could be fixed, it only appears with the -g option.
+    */
+   int i, j;
+   for (i=0; i<pm->ngammas; ++i) for (j=0; j<pm->ngammas; ++j)
+      if (i != j && fabs(pm->gammas[j]/pm->gammas[i]-1) >= PNG_GAMMA_THRESHOLD)
+   {
+      gamma_transform_test(pm, 0, 16, 1/pm->gammas[i], pm->gammas[j],
+         PNG_MAX_GAMMA_8, speed, pm->use_input_precision_16to8, 1/*strip16*/);
+      if (fail(pm)) return;
+      gamma_transform_test(pm, 2, 16, 1/pm->gammas[i], pm->gammas[j],
+         PNG_MAX_GAMMA_8, speed, pm->use_input_precision_16to8, 1/*strip16*/);
+      if (fail(pm)) return;
+      gamma_transform_test(pm, 4, 16, 1/pm->gammas[i], pm->gammas[j],
+         PNG_MAX_GAMMA_8, speed, pm->use_input_precision_16to8, 1/*strip16*/);
+      if (fail(pm)) return;
+      gamma_transform_test(pm, 6, 16, 1/pm->gammas[i], pm->gammas[j],
+         PNG_MAX_GAMMA_8, speed, pm->use_input_precision_16to8, 1/*strip16*/);
+      if (fail(pm)) return;
+   }
+}
+
+static void
+perform_gamma_test(png_modifier *pm, int speed, int summary)
+{
+   /* First some arbitrary no-transform tests: */
+   if (!speed)
+   {
+      perform_gamma_threshold_tests(pm);
+      if (fail(pm)) return;
+   }
+
+   /* Now some real transforms. */
+   perform_gamma_transform_tests(pm, speed);
+   if (summary)
+   {
+      printf("Gamma correction error summary (output value error):\n");
+      printf("  2 bit gray:  %.5f\n", pm->error_gray_2);
+      printf("  4 bit gray:  %.5f\n", pm->error_gray_4);
+      printf("  8 bit gray:  %.5f\n", pm->error_gray_8);
+      printf(" 16 bit gray:  %.5f\n", pm->error_gray_16);
+      printf("  8 bit color: %.5f\n", pm->error_color_8);
+      printf(" 16 bit color: %.5f\n", pm->error_color_16);
+   }
+
+   /* The sbit tests produce much larger errors: */
+   pm->error_gray_2 = pm->error_gray_4 = pm->error_gray_8 = pm->error_gray_16 =
+   pm->error_color_8 = pm->error_color_16 = 0;
+   perform_gamma_sbit_tests(pm, speed);
+   if (summary)
+   {
+      printf("Gamma correction with sBIT:\n");
+      if (pm->sbitlow < 8)
+      {
+	 printf("  2 bit gray:  %.5f\n", pm->error_gray_2);
+	 printf("  4 bit gray:  %.5f\n", pm->error_gray_4);
+	 printf("  8 bit gray:  %.5f\n", pm->error_gray_8);
+      }
+      printf(" 16 bit gray:  %.5f\n", pm->error_gray_16);
+      if (pm->sbitlow < 8)
+	 printf("  8 bit color: %.5f\n", pm->error_color_8);
+      printf(" 16 bit color: %.5f\n", pm->error_color_16);
+   }
+
+   /* The 16 to 8 bit strip operations: */
+   pm->error_gray_2 = pm->error_gray_4 = pm->error_gray_8 = pm->error_gray_16 =
+   pm->error_color_8 = pm->error_color_16 = 0;
+   perform_gamma_strip16_tests(pm, speed);
+   if (summary)
+   {
+      printf("Gamma correction with 16 to 8 bit reduction:\n");
+      printf(" 16 bit gray:  %.5f\n", pm->error_gray_16);
+      printf(" 16 bit color: %.5f\n", pm->error_color_16);
+   }
+}
+
+/* main program */
+int main(int argc, const char **argv)
+{
+   int summary = 1; /* Print the error sumamry at the end */
+   int speed = 0;   /* Speed test only (for gamma stuff) */
+
+   /* This is an array of standard gamma values (believe it or not I've seen
+    * every one of these mentioned somewhere.)
+    *
+    * In the following list the most useful values are first!
+    */
+   static double gammas[]={2.2, 1.0, 2.2/1.45, 1.8, 1.5, 2.4, 2.5, 2.62, 2.9};
+
+   png_modifier pm;
+   modifier_init(&pm);
+
+   /* Default to error on warning: */
+   pm.this.treat_warnings_as_errors = 1;
+
+   /* Store the test gammas */
+   pm.gammas = gammas;
+   pm.ngammas = 3; /* for speed */
+   pm.sbitlow = 8; /* because libpng doesn't do sbit below 8! */
+   pm.use_input_precision_16to8 = 1; /* Because of the way libpng does it */
+
+   /* Some default values (set the behavior for 'make check' here) */
+   pm.maxout8 = .1;     /* Arithmetic error in *encoded* value */
+   pm.maxabs8 = .00005; /* 1/20000 */
+   pm.maxpc8 = .499;    /* I.e. .499% fractional error */
+   pm.maxout16 = .499;  /* Error in *encoded* value */
+   pm.maxabs16 = .00005;/* 1/20000 */
+   /* NOTE: this is a reasonable perceptual limit, we assume that humans can
+    * perceive light level differences of 1% over a 100:1 range, so we need to
+    * maintain 1 in 10000 accuracy (in linear light space), this is what the
+    * following guarantees.  It also allows significantly higher errors at
+    * higher 16 bit values, which is important for performance.  The actual
+    * maximum 16 bit error is about +/-1.9 in the fixed point implementation but
+    * this is only allowed for values >38149 by the following:
+    */
+   pm.maxpc16 = .005;   /* I.e. 1/200% - 1/20000 */
+
+   /* Now parse the command line options. */
+   while (--argc >= 1)
+      if (strcmp(*++argv, "-v") == 0)
+         pm.this.verbose = 1;
+      else if (strcmp(*argv, "-l") == 0)
+         pm.log = 1;
+      else if (strcmp(*argv, "-q") == 0)
+         pm.this.verbose = pm.log = summary = 0;
+      else if (strcmp(*argv, "-g") == 0)
+	 pm.ngammas = (sizeof gammas)/(sizeof gammas[0]);
+      else if (strcmp(*argv, "-w") == 0)
+         pm.this.treat_warnings_as_errors = 0;
+      else if (strcmp(*argv, "-speed") == 0)
+         speed = 1, pm.ngammas = (sizeof gammas)/(sizeof gammas[0]);
+      else if (argc >= 1 && strcmp(*argv, "-sbitlow") == 0)
+         --argc, pm.sbitlow = atol(*++argv);
+      else if (argc >= 1 && strncmp(*argv, "-max", 4) == 0)
+      {
+         --argc;
+         if (strcmp(4+*argv, "abs8") == 0)
+	    pm.maxabs8 = atof(*++argv);
+	 else if (strcmp(4+*argv, "abs16") == 0)
+	    pm.maxabs16 = atof(*++argv);
+	 else if (strcmp(4+*argv, "out8") == 0)
+	    pm.maxout8 = atof(*++argv);
+	 else if (strcmp(4+*argv, "out16") == 0)
+	    pm.maxout16 = atof(*++argv);
+	 else if (strcmp(4+*argv, "pc8") == 0)
+	    pm.maxpc8 = atof(*++argv);
+	 else if (strcmp(4+*argv, "pc16") == 0)
+	    pm.maxpc16 = atof(*++argv);
+	 else
+	 {
+	    fprintf(stderr, "pngvalid: %s: unknown 'max' option\n", *argv);
+	    exit(1);
+	 }
+      }
+      else
+      {
+         fprintf(stderr, "pngvalid: %s: unknown argument\n", *argv);
+	 exit(1);
+      }
+
+   /* Make useful base images */
+   make_standard_images(&pm.this);
+   make_gamma_images(&pm.this);
+
+   /* Perform the standard and gamma tests. */
+   if (!speed)
+      perform_standard_test(&pm);
+   perform_gamma_test(&pm, speed, summary && !speed);
+   if (summary && !speed)
+      printf("Results using %s point arithmetic %s\n",
+#if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || PNG_LIBPNG_VER < 10500
+         "floating",
+#else
+         "fixed",
+#endif
+	 (pm.this.nerrors || pm.this.treat_warnings_as_errors &&
+	    pm.this.nwarnings) ? "(errors)" : (pm.this.nwarnings ?
+	       "(warnings)" : "(no errors or warnings)")
+      );
+
+   /* Error exit if there are any errors, and maybe if there are any
+    * warnings.
+    */
+   if (pm.this.nerrors || pm.this.treat_warnings_as_errors && pm.this.nwarnings)
+   {
+      if (!pm.this.verbose)
+         fprintf(stderr, "pngvalid: %s\n", pm.this.error);
+      fprintf(stderr, "pngvalid: %d errors, %d warnings\n", pm.this.nerrors,
+         pm.this.nwarnings);
+      exit(1);
+   }
+
+   return 0;
+}
+
+/* vim: set sw=3 ts=8 tw=80: */
diff --git a/pngwio.c b/pngwio.c
index 795e2f7..20955af 100644
--- a/pngwio.c
+++ b/pngwio.c
@@ -1,7 +1,7 @@
 
 /* pngwio.c - functions for data output
  *
- * Last changed in libpng 1.5.0 [July 24, 2010]
+ * Last changed in libpng 1.5.0 [July 29, 2010]
  * Copyright (c) 1998-2010 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
diff --git a/pngwrite.c b/pngwrite.c
index b7564ba..15d7f6e 100644
--- a/pngwrite.c
+++ b/pngwrite.c
@@ -1,7 +1,7 @@
 
 /* pngwrite.c - general routines to write a PNG file
  *
- * Last changed in libpng 1.5.0 [July 24, 2010]
+ * Last changed in libpng 1.5.0 [July 29, 2010]
  * Copyright (c) 1998-2010 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -60,15 +60,7 @@
     */
 #ifdef PNG_WRITE_gAMA_SUPPORTED
    if (info_ptr->valid & PNG_INFO_gAMA)
-   {
-#  ifdef PNG_FLOATING_POINT_SUPPORTED
-      png_write_gAMA(png_ptr, info_ptr->gamma);
-#else
-#ifdef PNG_FIXED_POINT_SUPPORTED
-      png_write_gAMA_fixed(png_ptr, info_ptr->int_gamma);
-#  endif
-#endif
-   }
+      png_write_gAMA_fixed(png_ptr, info_ptr->gamma);
 #endif
 #ifdef PNG_WRITE_sRGB_SUPPORTED
    if (info_ptr->valid & PNG_INFO_sRGB)
@@ -78,32 +70,19 @@
 #ifdef PNG_WRITE_iCCP_SUPPORTED
    if (info_ptr->valid & PNG_INFO_iCCP)
       png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_COMPRESSION_TYPE_BASE,
-                     info_ptr->iccp_profile, (int)info_ptr->iccp_proflen);
+          (png_charp)info_ptr->iccp_profile, (int)info_ptr->iccp_proflen);
 #endif
 #ifdef PNG_WRITE_sBIT_SUPPORTED
    if (info_ptr->valid & PNG_INFO_sBIT)
       png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type);
 #endif
-
 #ifdef PNG_WRITE_cHRM_SUPPORTED
    if (info_ptr->valid & PNG_INFO_cHRM)
-   {
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-      png_write_cHRM(png_ptr,
+      png_write_cHRM_fixed(png_ptr,
           info_ptr->x_white, info_ptr->y_white,
           info_ptr->x_red, info_ptr->y_red,
           info_ptr->x_green, info_ptr->y_green,
           info_ptr->x_blue, info_ptr->y_blue);
-#else
-#  ifdef PNG_FIXED_POINT_SUPPORTED
-      png_write_cHRM_fixed(png_ptr,
-          info_ptr->int_x_white, info_ptr->int_y_white,
-          info_ptr->int_x_red, info_ptr->int_y_red,
-          info_ptr->int_x_green, info_ptr->int_y_green,
-          info_ptr->int_x_blue, info_ptr->int_y_blue);
-#  endif
-#endif
-   }
 #endif
 
 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
@@ -168,7 +147,8 @@
       {
          int j;
          for (j = 0; j<(int)info_ptr->num_trans; j++)
-            info_ptr->trans_alpha[j] = (png_byte)(255 - info_ptr->trans_alpha[j]);
+            info_ptr->trans_alpha[j] =
+	       (png_byte)(255 - info_ptr->trans_alpha[j]);
       }
 #endif
       png_write_tRNS(png_ptr, info_ptr->trans_alpha, &(info_ptr->trans_color),
@@ -198,25 +178,10 @@
           info_ptr->pcal_units, info_ptr->pcal_params);
 #endif
 
-#ifdef PNG_sCAL_SUPPORTED
-   if (info_ptr->valid & PNG_INFO_sCAL)
 #ifdef PNG_WRITE_sCAL_SUPPORTED
-
-#if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
-      png_write_sCAL(png_ptr, (int)info_ptr->scal_unit,
-          info_ptr->scal_pixel_width, info_ptr->scal_pixel_height);
-#else /* !FLOATING_POINT */
-
-#ifdef PNG_FIXED_POINT_SUPPORTED
+   if (info_ptr->valid & PNG_INFO_sCAL)
       png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit,
           info_ptr->scal_s_width, info_ptr->scal_s_height);
-#endif /* FIXED_POINT */
-
-#endif /* FLOATING_POINT */
-#else  /* !WRITE_sCAL */
-      png_warning(png_ptr,
-          "png_write_sCAL not supported; sCAL chunk not written");
-#endif /* WRITE_sCAL */
 #endif /* sCAL */
 
 #ifdef PNG_WRITE_pHYs_SUPPORTED
diff --git a/pngwtran.c b/pngwtran.c
index d150420..dff6585 100644
--- a/pngwtran.c
+++ b/pngwtran.c
@@ -1,7 +1,7 @@
 
 /* pngwtran.c - transforms the data in a row for PNG writers
  *
- * Last changed in libpng 1.5.0 [July 24, 2010]
+ * Last changed in libpng 1.5.0 [July 29, 2010]
  * Copyright (c) 1998-2010 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
diff --git a/pngwutil.c b/pngwutil.c
index e3e96fb..ced9f0f 100644
--- a/pngwutil.c
+++ b/pngwutil.c
@@ -1,7 +1,7 @@
 
 /* pngwutil.c - utilities to write a PNG file
  *
- * Last changed in libpng 1.5.0 [July 24, 2010]
+ * Last changed in libpng 1.5.0 [July 29, 2010]
  * Copyright (c) 1998-2010 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -32,7 +32,9 @@
 #ifdef PNG_SAVE_INT_32_SUPPORTED
 /* The png_save_int_32 function assumes integers are stored in two's
  * complement format.  If this isn't the case, then this routine needs to
- * be modified to write data in two's complement format.
+ * be modified to write data in two's complement format.  Note that,
+ * the following works correctly even if png_int_32 has more than 32 bits
+ * (compare the more complex code required on read for sign extention.)
  */
 void PNGAPI
 png_save_int_32(png_bytep buf, png_int_32 i)
@@ -770,23 +772,6 @@
 
 #ifdef PNG_WRITE_gAMA_SUPPORTED
 /* Write a gAMA chunk */
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-void /* PRIVATE */
-png_write_gAMA(png_structp png_ptr, double file_gamma)
-{
-   PNG_gAMA;
-   png_uint_32 igamma;
-   png_byte buf[4];
-
-   png_debug(1, "in png_write_gAMA");
-
-   /* file_gamma is saved in 1/100,000ths */
-   igamma = (png_uint_32)(file_gamma * 100000.0 + 0.5);
-   png_save_uint_32(buf, igamma);
-   png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4);
-}
-#endif
-#ifdef PNG_FIXED_POINT_SUPPORTED
 void /* PRIVATE */
 png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma)
 {
@@ -800,7 +785,6 @@
    png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4);
 }
 #endif
-#endif
 
 #ifdef PNG_WRITE_sRGB_SUPPORTED
 /* Write a sRGB chunk */
@@ -1044,53 +1028,6 @@
 
 #ifdef PNG_WRITE_cHRM_SUPPORTED
 /* Write the cHRM chunk */
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-void /* PRIVATE */
-png_write_cHRM(png_structp png_ptr, double white_x, double white_y,
-    double red_x, double red_y, double green_x, double green_y,
-    double blue_x, double blue_y)
-{
-   PNG_cHRM;
-   png_byte buf[32];
-
-   png_fixed_point int_white_x, int_white_y, int_red_x, int_red_y,
-      int_green_x, int_green_y, int_blue_x, int_blue_y;
-
-   png_debug(1, "in png_write_cHRM");
-
-   int_white_x = (png_uint_32)(white_x * 100000.0 + 0.5);
-   int_white_y = (png_uint_32)(white_y * 100000.0 + 0.5);
-   int_red_x   = (png_uint_32)(red_x   * 100000.0 + 0.5);
-   int_red_y   = (png_uint_32)(red_y   * 100000.0 + 0.5);
-   int_green_x = (png_uint_32)(green_x * 100000.0 + 0.5);
-   int_green_y = (png_uint_32)(green_y * 100000.0 + 0.5);
-   int_blue_x  = (png_uint_32)(blue_x  * 100000.0 + 0.5);
-   int_blue_y  = (png_uint_32)(blue_y  * 100000.0 + 0.5);
-
-#ifdef PNG_CHECK_cHRM_SUPPORTED
-   if (png_check_cHRM_fixed(png_ptr, int_white_x, int_white_y,
-      int_red_x, int_red_y, int_green_x, int_green_y, int_blue_x, int_blue_y))
-#endif
-   {
-      /* Each value is saved in 1/100,000ths */
-
-      png_save_uint_32(buf, int_white_x);
-      png_save_uint_32(buf + 4, int_white_y);
-
-      png_save_uint_32(buf + 8, int_red_x);
-      png_save_uint_32(buf + 12, int_red_y);
-
-      png_save_uint_32(buf + 16, int_green_x);
-      png_save_uint_32(buf + 20, int_green_y);
-
-      png_save_uint_32(buf + 24, int_blue_x);
-      png_save_uint_32(buf + 28, int_blue_y);
-
-      png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32);
-   }
-}
-#endif
-#ifdef PNG_FIXED_POINT_SUPPORTED
 void /* PRIVATE */
 png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x,
     png_fixed_point white_y, png_fixed_point red_x, png_fixed_point red_y,
@@ -1124,7 +1061,6 @@
    }
 }
 #endif
-#endif
 
 #ifdef PNG_WRITE_tRNS_SUPPORTED
 /* Write the tRNS chunk */
@@ -1691,27 +1627,6 @@
 
 #ifdef PNG_WRITE_sCAL_SUPPORTED
 /* Write the sCAL chunk */
-#if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
-void /* PRIVATE */
-png_write_sCAL(png_structp png_ptr, int unit, double width, double height)
-{
-   PNG_sCAL;
-   char buf[64];
-   png_size_t total_len;
-
-   png_debug(1, "in png_write_sCAL");
-
-   buf[0] = (char)unit;
-   png_snprintf(buf + 1, 63, "%12.12e", width);
-   total_len = 1 + png_strlen(buf + 1) + 1;
-   png_snprintf(buf + total_len, 64 - total_len, "%12.12e", height);
-   total_len += png_strlen(buf + total_len);
-
-   png_debug1(3, "sCAL total length = %u", (unsigned int)total_len);
-   png_write_chunk(png_ptr, (png_bytep)png_sCAL, (png_bytep)buf, total_len);
-}
-#else
-#ifdef PNG_FIXED_POINT_SUPPORTED
 void /* PRIVATE */
 png_write_sCAL_s(png_structp png_ptr, int unit, png_charp width,
     png_charp height)
@@ -1740,8 +1655,6 @@
    png_write_chunk(png_ptr, (png_bytep)png_sCAL, buf, total_len);
 }
 #endif
-#endif
-#endif
 
 #ifdef PNG_WRITE_pHYs_SUPPORTED
 /* Write the pHYs chunk */
diff --git a/scripts/README.txt b/scripts/README.txt
index af6a570..7109ef9 100644
--- a/scripts/README.txt
+++ b/scripts/README.txt
@@ -1,5 +1,5 @@
 
-Makefiles for  libpng version 1.5.0beta36 - July 24, 2010
+Makefiles for  libpng version 1.5.0beta36 - July 29, 2010
 
 pnglibconf.h       =>  Stores configuration settings
  makefile.linux    =>  Linux/ELF makefile
diff --git a/scripts/makefile.dj2 b/scripts/makefile.dj2
index 1163043..c821cba 100644
--- a/scripts/makefile.dj2
+++ b/scripts/makefile.dj2
@@ -1,5 +1,5 @@
 # DJGPP (DOS gcc) makefile for libpng
-# Copyright (C) 2002, 2006, 2009 Glenn Randers-Pehrson
+# Copyright (C) 2002, 2006, 2009-2010 Glenn Randers-Pehrson
 # Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc.
 #
 # This code is released under the libpng license.
diff --git a/scripts/makefile.watcom b/scripts/makefile.watcom
index 4f9c7a1..aa1cf5b 100644
--- a/scripts/makefile.watcom
+++ b/scripts/makefile.watcom
@@ -50,8 +50,14 @@
 all: test
 
 # see scripts/pnglibconf.mak for more options
+# to support watcom calling conventions it is necessary to set PNG_API_RULE to 2
+# in pnglibconf.h - copy scripts/pnglibconf.h, delete the first line and change
+# the definition of PNG_API_RULE from 0 to 2.
+#
+# If you know how to do this with the Watcom build system please supply a patch
+# for this makefile to the PNG implementation list.
 pnglibconf.h: scripts/pnglibconf.h
-	cp scripts/pnglibconf.h $@
+	@echo please copy scripts/pnglibconf.h and change PNG_API_RULE to 2
 
 png$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h
 	$(CC) $(CFLAGS) $*.c $(ERRFILE)
diff --git a/scripts/options.awk b/scripts/options.awk
index e58fe4b..67b4626 100755
--- a/scripts/options.awk
+++ b/scripts/options.awk
@@ -1,7 +1,7 @@
 #!/bin/awk -f
 # scripts/options.awk - library build configuration control
 #
-# last changed in libpng version 1.5.0 - July 24, 2010
+# last changed in libpng version 1.5.0 - July 29, 2010
 #
 # Copyright (c) 1998-2010 Glenn Randers-Pehrson
 #
diff --git a/scripts/pnglibconf.dfa b/scripts/pnglibconf.dfa
index d057838..6e8e8b4 100644
--- a/scripts/pnglibconf.dfa
+++ b/scripts/pnglibconf.dfa
@@ -6,7 +6,7 @@
 #
 com pnglibconf.h - library build configuration
 com
-com libpng version PNGLIB_VERSION - last changed on July 24, 2010
+com libpng version PNGLIB_VERSION - last changed on July 29, 2010
 com
 com Copyright (c) 1998-2010 Glenn Randers-Pehrson
 com
@@ -134,6 +134,17 @@
 @#  include "pngusr.h"
 @#endif
 
+# This is a special fixup for the Watcom C compiler on Windows, which has
+# multiple procedure call standards.  Unless PNG_API_RULE is set explicitly
+# (i.e. if it is not defined at this point) it will be forced to '2' here when
+# using Watcom.  This indicates to the other header files that Watcom behaviour
+# is required where appropriate.
+@#ifdef __WATCOMC__
+@#  ifndef PNG_API_RULE
+@#     define PNG_API_RULE 2 /* Use Watcom calling conventions */
+@#  endif
+@#endif
+
 # Note that PNG_USR_CONFIG only has an effect when building
 # pnglibconf.h
 setting USER_CONFIG requires USER_PRIVATEBUILD USER_DLLFNAME_POSTFIX
@@ -166,8 +177,14 @@
 option WRITE enables WRITE_INT_FUNCTIONS
 
 # Generic options - affect both read and write.
+option WARNINGS
 option BENIGN_ERRORS
 option MNG_FEATURES
+
+# Arithmetic options, the first is the big switch that chooses between internal
+# floating and fixed point arithmetic implementations - it does not affect any
+# APIs.  The second two (the _POINT settings) switch off individual APIs.
+option FLOATING_ARITHMETIC
 option FLOATING_POINT enables ok_math
 option FIXED_POINT enables ok_math
 
@@ -287,8 +304,8 @@
 option READ_COMPOSITE_NODIV requires READ
 = NO_READ_COMPOSITE_NODIV PNG_NO_READ_COMPOSITED_NODIV
 
-# Inch conversions: not switched on by default
-option INCH_CONVERSIONS requires FLOATING_POINT
+# Inch conversions
+option INCH_CONVERSIONS
 = INCH_CONVERSIONS PNG_INCH_CONVERSIONS
 
 # IN DEVELOPMENT
@@ -319,6 +336,8 @@
 # trouble if left undefined
 option WRITE_INTERLACING requires WRITE
 
+# The following depends, internally, on WEIGHT_SHIFT and COST_SHIFT
+# where are set below.
 option WRITE_WEIGHTED_FILTER requires WRITE FLOATING_POINT
 
 option WRITE_FLUSH requires WRITE
@@ -349,6 +368,81 @@
 option READ_TEXT requires READ_ANCILLARY_CHUNKS enables TEXT
 option WRITE_TEXT requires WRITE_ANCILLARY_CHUNKS enables TEXT
 
+# Moved to pnglibconf.h at libpng-1.5.0
+# Feature support: in 1.4 this was in pngconf.h, but the following
+# features have no affect on the libpng API.  Add library
+# only features to the end of this list.  Add features that
+# affect the API above.  (Note: the list of chunks follows
+# the library-only settings.)
+#
+# BUILD TIME ONLY OPTIONS
+#   These options do not affect the API but rather alter how the
+#   API is implemented, they get recorded in pnglibconf.h, but
+#   can't be changed by the application.
+
+# Check the correctness of cHRM chunks
+option CHECK_cHRM requires cHRM
+#
+# Artificially align memory - the code typically aligns to 8 byte
+# boundaries if this is switched on, it's a small waste of space
+# but can help (in theory) on some architectures.  Only affects
+# internal structures.  Added at libpng 1.4.0
+option ALIGN_MEMORY
+
+# Buggy compilers (e.g., gcc 2.7.2.2) need PNG_NO_POINTER_INDEXING
+# See png[wr]util.c, normally this should always be *on*
+option POINTER_INDEXING
+
+# Other defines for things like memory and the like can go here.
+
+# BUILD TIME SETTINGS
+# Like build time options these do not affect the API, but they
+# may be useful to applications because they record details of
+# how the API will behave particularly with regard to overall
+# accuracy.
+
+# This controls how fine the quantizing gets.  As this allocates
+# a largish chunk of memory (32K), those who are not as concerned
+# with quantizing quality can decrease some or all of these.
+setting QUANTIZE_RED_BITS default 5
+setting QUANTIZE_GREEN_BITS default 5
+setting QUANTIZE_BLUE_BITS default 5
+
+# This controls how fine the gamma correction becomes when you
+# are only interested in 8 bits anyway.  Increasing this value
+# results in more memory being used, and more pow() functions
+# being called to fill in the gamma tables.  Don't set this value
+# less then 8, and even that may not work (I haven't tested it).
+setting MAX_GAMMA_8 default 11
+
+# This controls how much a difference in gamma we can tolerate before
+# we actually start doing gamma conversion, it's a fixed point value,
+# so the default below is 0.05, meaning libpng ignores corrections in
+# the range 0.95 to 1.05
+setting GAMMA_THRESHOLD_FIXED default 5000
+
+# Scaling factor for filter heuristic weighting calculations
+setting WEIGHT_SHIFT default 8
+setting COST_SHIFT default 3
+
+# Precision to use when converting a floating point value to a PNG
+# extension format string in an sCAL chunk (only relevant if the
+# floating point API is enabled)
+setting sCAL_PRECISION default 5
+
+# 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
+# is full, it writes the data to the disk, and does some other
+# calculations.  Making this an extremely small size may slow
+# the library down, but you may want to experiment to determine
+# where it becomes significant, if you are concerned with memory
+# usage.  Note that zlib allocates at least 32Kb also.  For readers,
+# this describes the size of the buffer available to read the data in.
+# Unless this gets smaller than the size of a row (compressed),
+# it should not make much difference how big this is.
+setting ZBUF_SIZE default 8192
+
 # Ancillary chunks
 chunk bKGD
 chunk cHRM
@@ -389,13 +483,8 @@
 
 option HANDLE_AS_UNKNOWN
 
-option GET_INT_32 requires READ
-# png_get_int_32 is required by the ancillary chunks oFFs and pCAL
-option READ_oFFs enables GET_INT_32
-option READ_pCAL enables GET_INT_32
-
 option SAVE_INT_32 requires WRITE
-# Likewise for png_save_int_32
+# png_save_int_32 is required by the ancillary chunks oFFs and pCAL
 option WRITE_oFFs enables SAVE_INT_32
 option WRITE_pCAL enables SAVE_INT_32
 
diff --git a/scripts/pnglibconf.h b/scripts/pnglibconf.h
index 783c438..4469b0f 100644
--- a/scripts/pnglibconf.h
+++ b/scripts/pnglibconf.h
@@ -1,7 +1,7 @@
 /* libpng-1.5.0beta36 STANDARD API DEFINITION */
 /* pnglibconf.h - library build configuration */
 
-/* last changed in libpng version 1.5.0 - July 24, 2010 */
+/* last changed in libpng version 1.5.0 - July 29, 2010 */
 
 /* Copyright (c) 1998-2010 Glenn Randers-Pehrson */
 
@@ -15,20 +15,33 @@
 #ifndef PNGLCONF_H
 #define PNGLCONF_H
 /* settings */
+#define PNG_MAX_GAMMA_8 11
 #define PNG_CALLOC_SUPPORTED
+#define PNG_QUANTIZE_RED_BITS 5
 #define PNG_USER_WIDTH_MAX 1000000L
+#define PNG_QUANTIZE_GREEN_BITS 5
 #define PNG_API_RULE 0
+#define PNG_QUANTIZE_BLUE_BITS 5
 #define PNG_USER_CHUNK_CACHE_MAX 0
 #define PNG_USER_HEIGHT_MAX 1000000L
+#define PNG_sCAL_PRECISION 5
+#define PNG_COST_SHIFT 3
+#define PNG_WEIGHT_SHIFT 8
 #define PNG_USER_CHUNK_MALLOC_MAX 0
 #define PNG_DEFAULT_READ_MACROS 1
+#define PNG_ZBUF_SIZE 8192
+#define PNG_GAMMA_THRESHOLD_FIXED 5000
 /* end of settings */
 /* options */
 #define PNG_INFO_IMAGE_SUPPORTED
 #define PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+#define PNG_POINTER_INDEXING_SUPPORTED
+#define PNG_WARNINGS_SUPPORTED
+#define PNG_FLOATING_ARITHMETIC_SUPPORTED
 #define PNG_WRITE_SUPPORTED
 #define PNG_WRITE_INTERLACING_SUPPORTED
 #define PNG_EASY_ACCESS_SUPPORTED
+#define PNG_ALIGN_MEMORY_SUPPORTED
 #define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
 #define PNG_USER_LIMITS_SUPPORTED
 #define PNG_FIXED_POINT_SUPPORTED
@@ -112,7 +125,6 @@
 #define PNG_WRITE_BGR_SUPPORTED
 #define PNG_USER_CHUNKS_SUPPORTED
 #define PNG_CONSOLE_IO_SUPPORTED
-#define PNG_GET_INT_32_SUPPORTED
 #define PNG_WRITE_PACK_SUPPORTED
 #define PNG_READ_FILLER_SUPPORTED
 #define PNG_WRITE_bKGD_SUPPORTED
@@ -144,6 +156,7 @@
 #define PNG_READ_zTXt_SUPPORTED
 #define PNG_gAMA_SUPPORTED
 #define PNG_pCAL_SUPPORTED
+#define PNG_CHECK_cHRM_SUPPORTED
 #define PNG_tIME_SUPPORTED
 #define PNG_pHYs_SUPPORTED
 #define PNG_READ_iTXt_SUPPORTED
diff --git a/scripts/pngwin.def b/scripts/pngwin.def
index 69450a4..020d69b 100644
--- a/scripts/pngwin.def
+++ b/scripts/pngwin.def
@@ -217,3 +217,13 @@
  png_save_uint_32 @205
  png_save_int_32 @206
  png_save_uint_16 @207
+ png_set_gamma_fixed @208
+ png_set_filter_heuristics_fixed @209
+ png_get_pixel_aspect_ratio_fixed @210
+ png_get_x_offset_inches_fixed @211
+ png_get_y_offset_inches_fixed @212
+ png_set_sCAL_fixed @213
+ png_get_sCAL_fixed @214
+ png_get_num_passes @215
+ png_get_num_rows @216
+ png_set_background_fixed @217
diff --git a/scripts/pngwin.dfn b/scripts/pngwin.dfn
index 0e50f98..9fd159f 100644
--- a/scripts/pngwin.dfn
+++ b/scripts/pngwin.dfn
@@ -1,7 +1,7 @@
 
 /* pngwin.dfn - define format of pngwin.def
  *
- * Last changed in libpng version 1.5.0 [July 24, 2010]
+ * Last changed in libpng version 1.5.0 [July 29, 2010]
  * Copyright (c) 1998-2010 Glenn Randers-Pehrson
  *
  * This code is released under the libpng license.
diff --git a/scripts/sym.dfn b/scripts/sym.dfn
index db0de67..42a802d 100644
--- a/scripts/sym.dfn
+++ b/scripts/sym.dfn
@@ -1,7 +1,7 @@
 
 /* sym.dfn - define format of libpng.sym
  *
- * Last changed in libpng version 1.5.0 [July 24, 2010]
+ * Last changed in libpng version 1.5.0 [July 29, 2010]
  * Copyright (c) 1998-2010 Glenn Randers-Pehrson
  *
  * This code is released under the libpng license.
diff --git a/scripts/symbols.def b/scripts/symbols.def
index f29a740..c449c3b 100644
--- a/scripts/symbols.def
+++ b/scripts/symbols.def
@@ -213,3 +213,13 @@
  png_save_uint_32 @205
  png_save_int_32 @206
  png_save_uint_16 @207
+ png_set_gamma_fixed @208
+ png_set_filter_heuristics_fixed @209
+ png_get_pixel_aspect_ratio_fixed @210
+ png_get_x_offset_inches_fixed @211
+ png_get_y_offset_inches_fixed @212
+ png_set_sCAL_fixed @213
+ png_get_sCAL_fixed @214
+ png_get_num_passes @215
+ png_get_num_rows @216
+ png_set_background_fixed @217
diff --git a/scripts/symbols.dfn b/scripts/symbols.dfn
index 30c10a6..fd2fce2 100644
--- a/scripts/symbols.dfn
+++ b/scripts/symbols.dfn
@@ -1,7 +1,7 @@
 
 /* symbols.dfn - find all exported symbols
  *
- * Last changed in libpng version 1.5.0 [July 24, 2010]
+ * Last changed in libpng version 1.5.0 [July 29, 2010]
  * Copyright (c) 1998-2010 Glenn Randers-Pehrson
  *
  * This code is released under the libpng license.
diff --git a/scripts/vers.dfn b/scripts/vers.dfn
index 79c6781..2ef4c20 100644
--- a/scripts/vers.dfn
+++ b/scripts/vers.dfn
@@ -1,7 +1,7 @@
 
 /* vers.dfn - define format of libpng.vers
  *
- * Last changed in libpng version 1.5.0 [July 24, 2010]
+ * Last changed in libpng version 1.5.0 [July 29, 2010]
  * Copyright (c) 1998-2010 Glenn Randers-Pehrson
  *
  * This code is released under the libpng license.