Imported from libpng-1.0.5q.tar
diff --git a/ANNOUNCE b/ANNOUNCE
index 6b07d33..45bf9b1 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,5 +1,5 @@
 
-Libpng 1.0.5h - December 10, 1999
+Libpng 1.0.5q - February 5, 2000
 
 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.
@@ -73,13 +73,72 @@
   Moved PNG_CHNK string macro definitions outside of PNG_NO_EXTERN block
   Added "translated_key" to png_text structure and png_write_iTXt().
   Added code in pngwrite.c to work around a newly discovered zlib bug.
-version 1.0.5h [December 10, 1999]
-  NOTE: regarding the not for version 1.0.5e, the following must also
+version libpng-1.0.5h December 10, 1999
+  NOTE: regarding the note for version 1.0.5e, the following must also
     be included in your code:
         png_text[i].translated_key = NULL;
   Unknown chunk handling is now supported.
   Option to eliminate all floating point support was added.  Some new
     fixed-point functions such as png_set_gAMA_fixed() were added.
+version libpng-1.0.5i December 13, 1999
+  Added some type casts to silence compiler warnings.
+  Renamed "png_free_spalette" to "png_free_spalettes" for consistency.
+  Removed leading blanks from a #define in pngvcrd.c
+  Added some parameters to the new png_set_keep_unknown_chunks() function,
+    and relocated it in pngset.c
+  Added a test for up->location != 0 in the first instance of writing
+    unknown chunks in pngwrite.c
+  Changed "num" to "i" in png_free_spalettes() and png_free_unknowns() to
+    prevent recursion.
+  Added png_free_hIST() function.
+  Various patches to fix bugs in the sCAL and integer cHRM processing,
+    and to add some convenience macros for use with sCAL.
+version libpng-1.0.5j December 21, 1999
+  Changed "unit" parameter of png_write_sCAL from png_byte to int, to work
+    around buggy compilers.
+  Added new type "png_fixed_point" for integers that hold float*100000 values
+  Restored backward compatibility of tEXt/zTXt chunk processing:
+    Added members "lang_key" and "itxt_length" to png_text struct.  Set
+    text_length=0 when "text" contains iTXt data.  Use the "compression"
+    member to distinguish among tEXt/zTXt/iTXt types.  Restored the first
+    four members of png_text to the same order as v.1.0.5d.  The "Note" above,
+    about backward incompatibility of libpng-1.0.5e, no longer applies.
+  Added PNG_ITXT_COMPRESSION_NONE (1) and PNG_ITXT_COMPRESSION_zTXt(2) macros.
+  Fixed png_read|write_iTXt() to read|write parameters in the right order.
+    and to write the iTXt chunk after IDAT if it appears in the end_ptr.
+  Added pnggccrd.c, version of pngvcrd.c Intel assembler for gcc (Greg Roelofs)
+  Reversed the order of trying to write floating-point and fixed-point gAMA.
+version libpng-1.0.5k December 27, 1999
+  Added many parentheses, e.g., "if (a && b & c)" becomes "if (a && (b & c))"
+  Added png_handle_as_unknown()
+  Added png_free_chunk_list() function and chunk_list and num_chunk_list members
+    of png_ptr.
+  Eliminated erroneous warnings about multiple sPLT chunks and sPLT-after-PLTE.
+  Fixed a libpng-1.0.5h bug in pngrutil.c that was issuing erroneous warnings
+    about ignoring incorrect gAMA with sRGB (gAMA was in fact not ignored)
+  Added png_free_tRNS(); png_set_tRNS() now malloc's its own trans array (ESR).
+  Define png_get_int_32 when oFFs chunk is supported as well as when pCAL is.
+  Changed type of proflen from png_int_32 to png_uint_32 in png_get_iCCP().
+version libpng-1.0.5l January 1, 2000
+  Added functions png_set_read_user_chunk_fn() and png_get_user_chunk_ptr()
+    for setting a callback function to handle unknown chunks and for
+    retrieving the associated user pointer (Glenn).
+version 1.0.5m [January 7, 2000]
+  Added high-level functions png_read_png(), png_write_png(), png_free_pixels().
+version 1.0.5n [January 9, 2000]
+  Added png_free_PLTE() function, and modified png_set_PLTE() to malloc its
+    own memory for info_ptr->palette.  This makes it safe for the calling
+    application to free its copy of the palette any time after it calls
+    png_set_PLTE().
+version 1.0.5o [January 20, 2000]
+  Cosmetic changes only (removed some trailing blanks and TABs)
+version 1.0.5p [January 31, 2000]
+  Renamed pngdll.mak to makefile.bd32
+  Cosmetic changes in pngtest.c
+version 1.0.5q [February 5, 2000]
+  Relocated the makefile.solaris warning about PATH problems.
+  Fixed pngvcrd.c bug by pushing/popping registers in mmxsupport (Bruce Oberg)
+  Revised makefile.gcmmx
 
 Send comments/corrections/commendations to
 png-implement@ccrc.wustl.edu or to randeg@alum.rpi.edu
diff --git a/CHANGES b/CHANGES
index fef0473..5f2de77 100644
--- a/CHANGES
+++ b/CHANGES
@@ -517,7 +517,7 @@
     with trailing compressed parts easier in the future, and added new functions
     png_free_iCCP, png_free_pCAL, png_free_sPLT, png_free_text, png_get_iCCP,
     png_get_spalettes, png_set_iCCP, png_set_spalettes (Eric S. Raymond).
-  NOTE: Applications that write text chunks MUST define png_text->lang and
+  NOTE: Applications that write text chunks MUST define png_text->lang
     before calling png_set_text(). It must be set to NULL if you want to
     write tEXt or zTXt chunks.  If you want your application to be able to
     run with older versions of libpng, use
@@ -544,9 +544,70 @@
   Added "translated_key" to png_text structure and png_write_iTXt().
   Added code in pngwrite.c to work around a newly discovered zlib bug.
 version 1.0.5h [December 10, 1999]
-  NOTE: regarding the not for version 1.0.5e, the following must also
+  NOTE: regarding the note for version 1.0.5e, the following must also
     be included in your code:
         png_text[i].translated_key = NULL;
   Unknown chunk handling is now supported.
   Option to eliminate all floating point support was added.  Some new
     fixed-point functions such as png_set_gAMA_fixed() were added.
+  Expanded tabs and removed trailing blanks in source files.
+version 1.0.5i [December 13, 1999]
+  Added some type casts to silence compiler warnings.
+  Renamed "png_free_spalette" to "png_free_spalettes" for consistency.
+  Removed leading blanks from a #define in pngvcrd.c
+  Added some parameters to the new png_set_keep_unknown_chunks() function.
+  Added a test for up->location != 0 in the first instance of writing
+    unknown chunks in pngwrite.c
+  Changed "num" to "i" in png_free_spalettes() and png_free_unknowns() to
+    prevent recursion.
+  Added png_free_hIST() function.
+  Various patches to fix bugs in the sCAL and integer cHRM processing,
+    and to add some convenience macros for use with sCAL.
+version 1.0.5j [December 21, 1999]
+  Changed "unit" parameter of png_write_sCAL from png_byte to int, to work
+    around buggy compilers.
+  Added new type "png_fixed_point" for integers that hold float*100000 values
+  Restored backward compatibility of tEXt/zTXt chunk processing:
+    Restored the first four members of png_text to the same order as v.1.0.5d.
+    Added members "lang_key" and "itxt_length" to png_text struct.  Set
+    text_length=0 when "text" contains iTXt data.  Use the "compression"
+    member to distinguish among tEXt/zTXt/iTXt types.  Added
+    PNG_ITXT_COMPRESSION_NONE (1) and PNG_ITXT_COMPRESSION_zTXt(2) macros.
+    The "Note" above, about backward incompatibility of libpng-1.0.5e, no
+    longer applies.
+  Fixed png_read|write_iTXt() to read|write parameters in the right order,
+    and to write the iTXt chunk after IDAT if it appears in the end_ptr.
+  Added pnggccrd.c, version of pngvcrd.c Intel assembler for gcc (Greg Roelofs)
+  Reversed the order of trying to write floating-point and fixed-point gAMA.
+version 1.0.5k [December 27, 1999]
+  Added many parentheses, e.g., "if (a && b & c)" becomes "if (a && (b & c))"
+  Added png_handle_as_unknown() function (Glenn)
+  Added png_free_chunk_list() function and chunk_list and num_chunk_list members
+    of png_ptr.
+  Eliminated erroneous warnings about multiple sPLT chunks and sPLT-after-PLTE.
+  Fixed a libpng-1.0.5h bug in pngrutil.c that was issuing erroneous warnings
+    about ignoring incorrect gAMA with sRGB (gAMA was in fact not ignored)
+  Added png_free_tRNS(); png_set_tRNS() now malloc's its own trans array (ESR).
+  Define png_get_int_32 when oFFs chunk is supported as well as when pCAL is.
+  Changed type of proflen from png_int_32 to png_uint_32 in png_get_iCCP().
+version 1.0.5l [January 1, 2000]
+  Added functions png_set_read_user_chunk_fn() and png_get_user_chunk_ptr()
+    for setting a callback function to handle unknown chunks and for
+    retrieving the associated user pointer (Glenn).
+version 1.0.5m [January 7, 2000]
+  Added high-level functions png_read_png(), png_write_png(), png_free_pixels().
+version 1.0.5n [January 9, 2000]
+  Added png_free_PLTE() function, and modified png_set_PLTE() to malloc its
+    own memory for info_ptr->palette.  This makes it safe for the calling
+    application to free its copy of the palette any time after it calls
+    png_set_PLTE().
+version 1.0.5o [January 20, 2000]
+  Cosmetic changes only (removed some trailing blanks and TABs)
+version 1.0.5p [January 31, 2000]
+  Renamed pngdll.mak to makefile.bd32
+  Cosmetic changes in pngtest.c
+version 1.0.5q [February 5, 2000]
+  Relocated the makefile.solaris warning about PATH problems.
+  Fixed pngvcrd.c bug by pushing/popping registers in mmxsupport (Bruce Oberg)
+  Revised makefile.gcmmx
+  Added PNG_SETJMP_SUPPORTED, PNG_SETJMP_NOT_SUPPORTED, and PNG_ABORT() macros
diff --git a/INSTALL b/INSTALL
index 73fac6c..114bc33 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,5 +1,5 @@
 
-Installing libpng version 1.0.5h - December 10, 1999
+Installing libpng version 1.0.5q - February 5, 2000
 
 Before installing libpng, you must first install zlib.  zlib
 can usually be found wherever you got libpng.  zlib can be
@@ -10,7 +10,7 @@
 version of zlib that's installed.
 
 You can rename the directories that you downloaded (they
-might be called "libpng-1.0.5h" or "lpng103" and "zlib-1.1.3"
+might be called "libpng-1.0.5q" or "lpng103" and "zlib-1.1.3"
 or "zlib113") so that you have directories called "zlib" and "libpng".
 
 Your directory structure should look like this:
@@ -36,6 +36,10 @@
           contrib
           etc.
 
+If the line endings in the files look funny, you may wish to get the other
+distribution of libpng.  It is available in both tar.gz (UNIX style line
+endings) and zip (DOS style line endings) formats.
+
 First enter the zlib directory and follow the instructions
 in zlib/README.  Then come back here and choose the
 appropriate makefile.sys in the scripts directory.
@@ -51,8 +55,10 @@
  makefile.hpux     =>  HPUX (10.20 and 11.00) makefile
  makefile.sgi      =>  Silicon Graphics IRIX makefile
  makefile.sunos    =>  Sun makefile
- makefile.solaris  =>  Solaris 2.X makefile (gcc, creates libpng.so.2.1.0.5h)
- makefile.linux    =>  Linux/ELF makefile (gcc, creates libpng.so.2.1.0.5h)
+ makefile.solaris  =>  Solaris 2.X makefile (gcc, creates libpng.so.2.1.0.5q)
+ makefile.linux    =>  Linux/ELF makefile (gcc, creates libpng.so.2.1.0.5q)
+ makefile.gcmmx    =>  Linux/ELF makefile (gcc, creates libpng.so.2.1.0.5q,
+                       uses assembler code tuned for Intel MMX platform)
  makefile.sco      =>  For SCO OSr5  ELF and Unixware 7 with Native cc
  makefile.mips     =>  MIPS makefile
  makefile.acorn    =>  Acorn makefile
@@ -61,20 +67,20 @@
                        (Requires SCOPTIONS, copied from scripts/SCOPTIONS.ppc)
  makefile.atari    =>  Atari makefile
  makefile.beos     =>  BEOS makefile for X86
- makefile.borland  =>  Borland makefile
+ makefile.borland  =>  Borland makefile (uses bcc)
+ makefile.bd32     =>  To make a png32bd.dll with Borland C++ 4.5
+ makefile.turboc3  =>  Turbo C 3.0 makefile
  build.bat         =>  MS-DOS batch file for Borland compiler
  makefile.dj2      =>  DJGPP 2 makefile
  makefile.msc      =>  Microsoft C makefile
  makefile.vcawin32 =>  makefile for Microsoft Visual C++ 5.0 and later (uses
-                       assembler code)
+                       assembler code tuned for Intel MMX platform)
  makefile.vcwin32  =>  makefile for Microsoft Visual C++ 4.0 and later (does
                        not use assembler code)
- makefile.turboc3  =>  Turbo C 3.0 makefile
  makefile.os2      =>  OS/2 Makefile (gcc and emx, requires pngos2.def)
  pngos2.def        =>  OS/2 module definition file used by makefile.os2
  makefile.watcom   =>  Watcom 10a+ Makefile, 32-bit flat memory model
  makevms.com       =>  VMS build script
- pngdll.mak        =>  To make a png32bd.dll with Borland C++ 4.5
  pngdef.pas        =>  Defines for a png32bd.dll with Borland C++ 4.5
  SCOPTIONS.ppc     =>  Used with smakefile.ppc
 
diff --git a/KNOWNBUG b/KNOWNBUG
index 7dc036d..527da8c 100644
--- a/KNOWNBUG
+++ b/KNOWNBUG
@@ -38,6 +38,9 @@
    for the png_set_gAMA(), png_set_cHRM(), and corresponding png_get_()
    functions will be needed.
 
+   Much of this was completed in libpng-1.0.5h, but gamma compensation
+   is not yet done in fixed-point arithmetic.
+
 4. October 1999 -- BUG
 
    pngvcrd.c is failing for interlaced PNGs that have empty passes.
@@ -64,4 +67,10 @@
    is not backward compatible (the lang member was added, and the
    translated_key member was added to libpng-1.0.5g)
 
-   STATUS: Will be fixed before the next public release.
+   STATUS: Fixed in libpng-1.0.5j/1.1.0
+
+7. December 1999 -- BUG
+
+   The new pnggccrd.c has syntax errors when compiled with gcc.
+
+   STATUS: Under investigation.
diff --git a/LICENSE b/LICENSE
index d6cc5ec..5f2d9dd 100644
--- a/LICENSE
+++ b/LICENSE
@@ -4,8 +4,8 @@
 (libpng versions 0.5, May 1995, through 0.89c, May 1996)
 Copyright (c) 1996, 1997 Andreas Dilger
 (libpng versions 0.90, December 1996, through 0.96, May 1997)
-Copyright (c) 1998, 1999 Glenn Randers-Pehrson
-(libpng versions 0.97, January 1998, through 1.0.5h, December 10, 1999)
+Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson
+(libpng versions 0.97, January 1998, through 1.0.5q, February 5, 2000)
 
 For the purposes of this copyright and license, "Contributing Authors"
 is defined as the following set of individuals:
@@ -63,9 +63,9 @@
 Also, the PNG logo (in PNG format, of course) is supplied in the
 file "pngnow.png".
 
-Libpng is OSI Certified Open Source Software.  OSI Certified is a
+Libpng is OSI Certified Open Source Software.  OSI Certified Open Source is a
 certification mark of the Open Source Initiative.
 
 Glenn Randers-Pehrson
 randeg@alum.rpi.edu
-December 10, 1999
+February 5, 2000
diff --git a/README b/README
index be96b14..9e40a7e 100644
--- a/README
+++ b/README
@@ -1,8 +1,12 @@
-README for libpng 1.0.5h - December 10, 1999 (shared library 2.1)
+README for libpng 1.0.5q - February 5, 2000 (shared library 2.1)
 See the note about version numbers near the top of png.h
 
 See INSTALL for instructions on how to install libpng.
 
+Libpng comes in two distribution formats.  Get libpng-*.tar.gz if you
+want UNIX-style line endings in the text files, or lpng*.zip if you want
+DOS-style line endings.
+
 Version 0.89 was the first official release of libpng.  Don't let the
 fact that it's the first release fool you.  The libpng library has been in
 extensive use and testing since mid-1995.  By late 1997 it had
@@ -171,9 +175,12 @@
        makefile.sgi     =>  Silicon Graphics IRIX makefile
        makefile.sunos   =>  Sun makefile
        makefile.solaris =>  Solaris 2.X makefile
-                            (gcc, creates libpng.so.2.1.0.5h)
+                            (gcc, creates libpng.so.2.1.0.5q)
        makefile.linux   =>  Linux/ELF makefile
-                            (gcc, creates libpng.so.2.1.0.5h)
+                            (gcc, creates libpng.so.2.1.0.5q)
+       makefile.gcmmx   =>  Linux/ELF makefile (gcc, creates
+                            libpng.so.2.1.0.5q, uses assembler code
+                            tuned for Intel MMX platform)
        makefile.sco     =>  For SCO OSr5  ELF and Unixware 7 with Native cc
        makefile.mips    =>  MIPS makefile
        makefile.acorn   =>  Acorn makefile
@@ -183,20 +190,21 @@
                             scripts/SCOPTIONS.ppc)
        makefile.atari   =>  Atari makefile
        makefile.beos    =>  BEOS makefile for X86
-       makefile.borland =>  Borland makefile
+       makefile.borland =>  Borland makefile (uses bcc)
+       makefile.bd32    =>  To make a png32bd.dll with Borland C++ 4.5
+       makefile.turboc3 =>  Turbo C 3.0 makefile
        build.bat        =>  MS-DOS batch file for Borland compiler
        makefile.dj2     =>  DJGPP 2 makefile
        makefile.msc     =>  Microsoft C makefile
        makefile.vcawin32 => makefile for Microsoft Visual C++ 5.0 and
-                            later (uses assembler code)
+                            later (uses assembler code tuned for Intel MMX
+                            platform)
        makefile.vcwin32 =>  makefile for Microsoft Visual C++ 4.0 and
                             later (does not use assembler code)
-       makefile.turboc3 =>  Turbo C 3.0 makefile
        makefile.os2     =>  OS/2 Makefile (gcc and emx, requires pngos2.def)
        pngos2.def       =>  OS/2 module definition file used by makefile.os2
        makefile.watcom  =>  Watcom 10a+ Makefile, 32-bit flat memory model
        makevms.com      =>  VMS build script
-       pngdll.mak       =>  To make a png32bd.dll with Borland C++ 4.5
        pngdef.pas       =>  Defines for a png32bd.dll with Borland C++ 4.5
        SCOPTIONS.ppc    =>  Used with smakefile.ppc
 
diff --git a/TODO b/TODO
index b0cff06..58c11e7 100644
--- a/TODO
+++ b/TODO
@@ -1,13 +1,11 @@
 TODO - list of things to do for libpng:
 
 Final bug fixes.
-Fix problem with C++ and EXTERN "C".
+Finish work on the no-floating-point version (including gamma compensation)
 Better C++ wrapper/full C++ implementation?
-Keep up with public chunks.
+Fix problem with C++ and EXTERN "C".
 cHRM transformation.
-Support for application-defined chunk handlers.
 Improve setjmp/longjmp usage or remove it in favor of returning error codes.
-High-level API for reading images.
 Add "grayscale->palette" transformation and "palette->grayscale" detection.
 Improved dithering.
 Multi-lingual error and warning message support.
@@ -19,4 +17,3 @@
 Histogram creation.
 Text conversion between different code pages (Latin-1 -> Mac and DOS).
 Improve API by hiding the info_ptr.
-Make a no-floating-point version.
diff --git a/Y2KINFO b/Y2KINFO
index 20554fe..1fb61c4 100644
--- a/Y2KINFO
+++ b/Y2KINFO
@@ -1,29 +1,29 @@
    Y2K compliance in libpng:
    =========================
-      
-      December 10, 1999
-      
+
+      February 5, 2000
+
       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.0.5h are Y2K compliant.  It is my belief that earlier
+      upward through 1.0.5q are Y2K compliant.  It is my belief that earlier
       versions were also Y2K compliant.
-      
+
       Libpng only has three year fields.  One is a 2-byte unsigned integer
       that will hold years up to 65535.  The other two hold the date in text
       format, and will hold years up to 9999.
-      
+
       The integer is
           "png_uint_16 year" in png_time_struct.
-      
+
       The strings are
           "png_charp time_buffer" in png_struct and
           "near_time_buffer", which is a local character string in png.c.
-      
+
       There are seven time-related functions:
 
-          png_convert_to_rfc_1123() in png.c 
+          png_convert_to_rfc_1123() in png.c
             (formerly png_convert_to_rfc_1152() in error)
           png_convert_from_struct_tm() in pngwrite.c, called in pngwrite.c
           png_convert_from_time_t() in pngwrite.c
@@ -31,8 +31,8 @@
           png_handle_tIME() in pngrutil.c, called in pngread.c
           png_set_tIME() in pngset.c
           png_write_tIME() in pngwutil.c, called in pngwrite.c
-      
-      All appear to handle dates properly in a Y2K environment.  The 
+
+      All appear to handle dates properly in a Y2K environment.  The
       png_convert_from_time_t() function calls gmtime() to convert from system
       clock time, which returns (year - 1900), which we properly convert to
       the full 4-digit year.  There is a possibility that applications using
@@ -42,14 +42,14 @@
       but this is not under our control.  The libpng documentation has always
       stated that it works with 4-digit years, and the APIs have been
       documented as such.
-      
+
       The tIME chunk itself is also Y2K compliant.  It uses a 2-byte unsigned
       integer to hold the year, and can hold years as large as 65535.
 
       zlib, upon which libpng depends, is also Y2K compliant.  It contains
       no date-related code.
-      
-      
+
+
          Glenn Randers-Pehrson
          libpng maintainer
          PNG Development Group
diff --git a/contrib/pngminus/makefile b/contrib/pngminus/makefile
new file mode 100644
index 0000000..3ccbc8f
--- /dev/null
+++ b/contrib/pngminus/makefile
@@ -0,0 +1,52 @@
+# Makefile for PngMinus (png2pnm and pnm2png)
+# Linux / Unix
+
+CC=cc -O -n32
+LD=cc -O -n32
+#CC=gcc -O
+#LD=gcc -O
+LB=ar
+RM=rm
+CP=cp
+
+PNGPATH = /usr/local
+PNGINC = $(PNGPATH)/include
+PNGLIB = $(PNGPATH)/lib -lpng
+# PNGLIB = $(PNGPATH)/libpng.a
+
+ZPATH = /usr/local
+ZINC = $(ZPATH)/include
+ZLIB = $(ZPATH)/lib -lz
+# ZLIB = $(ZPATH)/libz.a
+
+CCFLAGS=-I$(PNGINC) -I$(ZINC)
+LDFLAGS=-L$(PNGLIB) -L$(ZLIB) -lm
+C=.c
+O=.o
+L=.a
+E=
+
+# dependencies
+
+all: png2pnm$(E) pnm2png$(E)
+
+png2pnm$(O): png2pnm$(C)
+	$(CC) -c $(CCFLAGS) png2pnm$(C)
+
+png2pnm$(E): png2pnm$(O)
+	$(LD) -o png2pnm$(E) png2pnm$(O) $(LDFLAGS)
+
+pnm2png$(O): pnm2png$(C)
+	$(CC) -c $(CCFLAGS) pnm2png$(C)
+
+pnm2png$(E): pnm2png$(O)
+	$(LD) -o pnm2png$(E) pnm2png$(O) $(LDFLAGS)
+
+clean:
+	$(RM) png2pnm$(O)
+	$(RM) pnm2png$(O)
+	$(RM) png2pnm$(E)
+	$(RM) pnm2png$(E)
+
+# End of makefile for png2pnm / pnm2png
+
diff --git a/contrib/pngminus/pnm2png.c b/contrib/pngminus/pnm2png.c
index 67796dd..996f544 100644
--- a/contrib/pngminus/pnm2png.c
+++ b/contrib/pngminus/pnm2png.c
@@ -77,7 +77,8 @@
           if ((fp_al = fopen (argv[argi], "rb")) == NULL)
           {
             fprintf (stderr, "PNM2PNG\n");
-            fprintf (stderr, "Error:  alpha-channel file %s does not exist\n", argv[argi]);
+            fprintf (stderr, "Error:  alpha-channel file %s does not exist\n",
+               argv[argi]);
             exit (1);
           }
           break;
@@ -511,8 +512,8 @@
     for (i = 0; i < depth; i++)
       mask = (mask << 1) | 0x01;
 
-  get_token (pnm_file, token);
-  sscanf (token, "%lu", &ret_value);
+  get_token (pnm_file, (char *) token);
+  sscanf ((const char *) token, "%lu", &ret_value);
 
   ret_value &= mask;
 
diff --git a/example.c b/example.c
index 50a285f..691e5d1 100644
--- a/example.c
+++ b/example.c
@@ -136,6 +136,19 @@
    /* If we have already read some of the signature */
    png_set_sig_bytes(png_ptr, sig_read);
 
+#ifdef hilevel
+   /*
+    * If you have enough memory to read in the entire image at once,
+    * and you need to specify only transforms that can be controlled
+    * with one of the PNG_TRANSFORM_* bits (this presently excludes
+    * dithering, filling, setting background, and doing gamma
+    * adjustment), then you can read the entire image (including
+    * pixels) into the info structure with this call:
+    */
+   png_read_png(png_ptr, info_ptr, png_transforms, NULL);
+#else
+   /* OK, you're doing it the hard way, with the lower-level functions */
+
    /* The call to png_read_info() gives us all of the information from the
     * PNG file before the first IDAT (image data chunk).  REQUIRED
     */
@@ -275,7 +288,7 @@
     */
    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT))
    {
-      png_color8p sig_bit;
+      png_color_8p sig_bit;
 
       png_get_sBIT(png_ptr, info_ptr, &sig_bit);
       png_set_shift(png_ptr, sig_bit);
@@ -350,6 +363,9 @@
 
    /* read rest of file, and get additional chunks in info_ptr - REQUIRED */
    png_read_end(png_ptr, info_ptr);
+#endif hilevel
+
+   /* At this point you have read the entire image */
 
    /* clean up after the read, and free any memory allocated - REQUIRED */
    png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
@@ -530,7 +546,7 @@
    }
 
    /* Set error handling.  REQUIRED if you aren't supplying your own
-    * error hadnling functions in the png_create_write_struct() call.
+    * error handling functions in the png_create_write_struct() call.
     */
    if (setjmp(png_ptr->jmpbuf))
    {
@@ -552,6 +568,15 @@
    /* where user_io_ptr is a structure you want available to the callbacks */
 #endif no_streams /* only use one initialization method */
 
+#ifdef hilevel
+   /* This is the easy way.  Use it if you already have all the
+    * image info living info in the structure.  You could "|" many
+    * PNG_TRANSFORM flags into the png_transforms integer here.
+    */
+   png_write_png(png_ptr, info_ptr, png_transforms, NULL);
+#else
+   /* This is the hard way */
+
    /* Set the image information here.  Width and height are up to 2^31,
     * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
     * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
@@ -567,6 +592,11 @@
    palette = (png_colorp)png_malloc(png_ptr, 256 * sizeof (png_color));
    /* ... set palette colors ... */
    png_set_PLTE(png_ptr, info_ptr, palette, 256);
+   /* You can free the palette here if you like, since libpng has made its
+      own copy.  In versions of libpng earlier than version 1.0.5n, it was
+      necessary to keep the palette until after png_write_end(), because
+      libpng was using the caller's copy. */
+   free(palette);
 
    /* optional significant bit chunk */
    /* if we are dealing with a grayscale image then */
@@ -615,6 +645,9 @@
     *   png_write_info_before_PLTE(write_ptr, write_info_ptr);
     *   write_my_chunk();
     *   png_write_info(png_ptr, info_ptr);
+    *
+    * However, given the level of known- and unknown-chunk support in 1.1.0
+    * and up, this should no longer be necessary.
     */
 
    /* Once we write out the header, the compression type on the text
@@ -695,14 +728,20 @@
 #endif no_entire /* use only one output method */
 
    /* You can write optional chunks like tEXt, zTXt, and tIME at the end
-    * as well.
+    * as well.  Shouldn't be necessary in 1.1.0 and up as all the public
+    * chunks are supported and you can use png_set_unknown_chunks() to
+    * register unknown chunks into the info structure to be written out.
     */
 
    /* It is REQUIRED to call this to finish writing the rest of the file */
    png_write_end(png_ptr, info_ptr);
+#endif hilevel
 
-   /* if you malloced the palette, free it here */
-   free(info_ptr->palette);
+   /* if you malloced a palette and have not already freed it, free it
+      here (do *not* free libpng's copy of the palette in info_ptr->palette,
+      as recommended in versions 1.0.5m and earlier of this example; libpng
+      now takes care of that automatically). */
+   free(palette);
 
    /* clean up after the write, and free any memory allocated */
    png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
diff --git a/libpng.3 b/libpng.3
index 599dcb0..6be60ed 100644
--- a/libpng.3
+++ b/libpng.3
@@ -1,6 +1,6 @@
-.TH LIBPNG 3 "December 10, 1999"
+.TH LIBPNG 3 "February 5, 2000"
 .SH NAME
-libpng \- Portable Network Graphics (PNG) Reference Library 1.0.5h
+libpng \- Portable Network Graphics (PNG) Reference Library 1.0.5q
 .SH SYNOPSIS
 \fI\fB
 
@@ -84,10 +84,18 @@
 
 \fI\fB
 
+\fBvoid png_free_chunk_list (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
 \fBvoid png_free_default(png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fIptr\fP\fB);\fP
 
 \fI\fB
 
+\fBvoid png_free_hIST (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fI\fP\fB);\fP
+
+\fI\fB
+
 \fBvoid png_free_iCCP (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fI\fP\fB);\fP
 
 \fI\fB
@@ -96,11 +104,19 @@
 
 \fI\fB
 
+\fBvoid png_free_pixels (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_free_PLTE (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
 \fBvoid png_free_sCAL (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
 
 \fI\fB
 
-\fBvoid png_free_spalette (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fInum_text\fP\fB);\fP
+\fBvoid png_free_spalettes (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fInum_text\fP\fB);\fP
 
 \fI\fB
 
@@ -112,6 +128,14 @@
 
 \fI\fB
 
+\fBvoid png_free_tRNS (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_free_unknown_chunks (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fInum_unknowns\fP\fB);\fP
+
+\fI\fB
+
 \fBpng_byte png_get_bit_depth (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
 
 \fI\fB
@@ -172,7 +196,7 @@
 
 \fI\fB
 
-\fBpng_uint_32 png_get_iCCP (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_charpp \fP\fIname\fP\fB, int \fP\fI*compression_type\fP\fB, png_charpp \fP\fIprofile\fP\fB, int \fI*proflen\fP\fB);\fP
+\fBpng_uint_32 png_get_iCCP (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_charpp \fP\fIname\fP\fB, int \fP\fI*compression_type\fP\fB, png_charpp \fP\fIprofile\fP\fB, png_uint_32 \fI*proflen\fP\fB);\fP
 
 \fI\fB
 
@@ -270,6 +294,10 @@
 
 \fI\fB
 
+\fBpng_voidp png_get_user_chunk_ptr (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
 \fBpng_voidp png_get_user_transform_ptr (png_structp \fIpng_ptr\fP\fB);\fP
 
 \fI\fB
@@ -362,6 +390,10 @@
 
 \fI\fB
 
+\fBvoid png_read_png (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fItransforms\fP\fB, voidp \fIparams\fP\fB);\fP
+
+\fI\fB
+
 \fBvoid png_read_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIrow\fP\fB, png_bytep \fIdisplay_row\fP\fB);\fP
 
 \fI\fB
@@ -470,7 +502,7 @@
 
 \fI\fB
 
-\fBvoid png_set_iCCP (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_charp \fP\fIname\fP\fB, int \fP\fIcompression_type\fP\fB, png_charp \fP\fIprofile\fP\fB, int \fIproflen\fP\fB);\fP
+\fBvoid png_set_iCCP (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_charp \fP\fIname\fP\fB, int \fP\fIcompression_type\fP\fB, png_charp \fP\fIprofile\fP\fB, png_uint_32 \fIproflen\fP\fB);\fP
 
 \fI\fB
 
@@ -490,7 +522,7 @@
 
 \fI\fB
 
-\fBvoid png_set_keep_unknown_chunks (png_structp \fIpng_ptr\fP\fB);\fP
+\fBvoid png_set_keep_unknown_chunks (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIkeep\fP\fB, png_bytep \fP\fIchunk_list\fP\fB, int \fInum_chunks\fP\fB);\fP
 
 \fI\fB
 
@@ -606,7 +638,11 @@
 
 \fI\fB
 
-\fBpng_uint_32 png_set_unknown_chunks (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_unknown_chunkp \fP\fIunknowns\fP\fB, int \fInum\fP\fB);\fP
+\fBpng_uint_32 png_set_unknown_chunks (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_unknown_chunkp \fP\fIunknowns\fP\fB, int \fP\fInum\fP\fB, int \fIlocation\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_read_user_chunk_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIuser_chunk_ptr\fP\fB, png_user_chunk_ptr \fIread_user_chunk_fn\fP\fB);\fP
 
 \fI\fB
 
@@ -682,6 +718,10 @@
 
 \fI\fB
 
+\fBvoid png_write_png (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fItransforms\fP\fB, voidp \fIparams\fP\fB);\fP
+
+\fI\fB
+
 \fBvoid png_write_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIrow\fP\fB);\fP
 
 \fI\fB
@@ -701,10 +741,10 @@
 .SH LIBPNG.TXT
 libpng.txt - A description on how to use and modify libpng
 
- libpng version 1.0.5h - December 10, 1999
+ libpng version 1.0.5q - February 5, 2000
  Updated and distributed by Glenn Randers-Pehrson
  <randeg@alum.rpi.edu>
- Copyright (c) 1998, 1999 Glenn Randers-Pehrson
+ Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson
  For conditions of distribution and use, see copyright
  notice in png.h.
 
@@ -720,10 +760,9 @@
  Schalnat, Group 42, Inc.
 
  Updated/rewritten per request in the libpng FAQ
- Copyright (c) 1995 Frank J. T. Wojcik
- December 18, 1995 && January 20, 1996
+ Copyright (c) 1995, 1996 Frank J. T. Wojcik
+ December 18, 1995 & January 20, 1996
 
- *
 .SH I. Introduction
 
 This file describes how to use and modify the PNG reference library
@@ -803,13 +842,14 @@
 
 .SH III. Reading
 
-Reading PNG files:
-
 We'll now walk you through the possible functions to call when reading
-in a PNG file, briefly explaining the syntax and purpose of each one.
-See example.c and png.h for more detail.  While Progressive reading
-is covered in the next section, you will still need some of the
-functions discussed in this section to read a PNG file.
+in a PNG file sequentially, briefly explaining the syntax and purpose
+of each one.  See example.c and png.h for more detail.  While
+progressive reading is covered in the next section, you will still
+need some of the functions discussed in this section to read a PNG
+file.
+
+.SS Setup
 
 You will want to do the I/O initialization(*) before you get into libpng,
 so if it doesn't work, you don't have much to undo.  Of course, you
@@ -909,6 +949,10 @@
         return;
     }
 
+If you would rather avoid the complexity of setjmp/longjmp issues,
+you can compile libpng with PNG_SETJMP_NOT_SUPPORTED, in which case
+errors will result in a call to PNG_ABORT() which defaults to abort().
+
 Now you need to set up the input code.  The default for libpng is to
 use the C function fread().  If you use this, you will need to pass a
 valid FILE * in the function png_init_io().  Be sure that the file is
@@ -925,6 +969,42 @@
 
     png_set_sig_bytes(png_ptr, number);
 
+.SS Setting up callback code
+
+You can set up a callback function to handle any unknown chunks in the
+input stream. You must supply the function
+
+    read_chunk_callback(png_ptr ptr,
+         png_unknown_chunkp chunk);
+    {
+       /* The unknown chunk structure contains your
+          chunk data: */
+           png_byte name[5];
+           png_byte *data;
+           png_size_t size;
+       /* Note that libpng has already taken care of the
+          CRC handling */
+
+       /* put your code here.  Return one of the following: */
+
+       return (-n); /* chunk had an error */
+       return (0); /* did not recognize */
+       return (n); /* success */
+    }
+
+(You can give your function another name that you like instead of
+"read_chunk_callback")
+
+To inform libpng about your function, use
+
+    png_set_read_user_chunk_fn(png_ptr, user_chunk_ptr,
+        read_chunk_callback);
+
+This names not only the callback function, but also a user pointer that
+you can retrieve with
+
+    png_get_user_chunk_ptr(png_ptr);
+
 At this point, you can set up a callback function that will be
 called after each row has been read, which you can use to control
 a progress meter or the like.  It's demonstrated in pngtest.c.
@@ -941,19 +1021,6 @@
 
     png_set_read_status_fn(png_ptr, read_row_callback);
 
-In PNG files, the alpha channel in an image is the level of opacity.
-If you need the alpha channel in an image to be the level of transparency
-instead of opacity, you can invert the alpha channel (or the tRNS chunk
-data) after it's read, so that 0 is fully opaque and 255 (in 8-bit or
-paletted images) or 65535 (in 16-bit images) is fully transparent, with
-
-    png_set_invert_alpha(png_ptr);
-
-This has to appear here rather than later with the other transformations
-because the tRNS chunk data must be modified in the case of paletted images.
-If your image is not a paletted image, the tRNS data (which in such cases
-represents a single color to be rendered as transparent) won't be changed.
-
 Finally, you can write your own transformation function if none of
 the existing ones meets your needs.  This is done by setting a callback
 with
@@ -977,6 +1044,8 @@
     png_set_user_transform_info(png_ptr, user_ptr,
        user_depth, user_channels);
 
+The user's application, not libpng, is responsible for allocating and
+freeing any memory required for the user structure.
 
 You can retrieve the pointer via the function
 png_get_user_transform_ptr().  For example:
@@ -984,23 +1053,100 @@
     voidp read_user_transform_ptr =
        png_get_user_transform_ptr(png_ptr);
 
-You are now ready to read all the file information up to the actual
-image data.  You do this with a call to png_read_info().
+.SS Unknown-chunk handling
+
+Now you get to set the way the library processes unknown chunks in the
+input PNG stream. Both known and unknown chunks will be read.  Normal
+behavior is that known chunks will be parsed into information in
+various info_ptr members; unknown chunks will be discarded. To change
+this, you can call:
+
+    png_set_keep_unknown_chunks(png_ptr, info_ptr, keep,
+        chunk_list, num_chunks);
+    keep       - 0: do not keep
+                 1: keep only if safe-to-copy
+                 2: keep even if unsafe-to-copy
+    chunk_list - list of chunks affected (a byte string,
+                 five bytes per chunk, NULL or '\0' if
+                 num_chunks is 0)
+    num_chunks - number of chunks affected; if 0, all
+                 unknown chunks are affected
+
+Unknown chunks declared in this way will be saved as raw data onto a
+list of png_unknown_chunk structures.  If a chunk that is normally
+known to libpng is named in the list, it will be handled as unknown,
+according to the "keep" directive.  If a chunk is named in successive
+instances of png_set_keep_unknown_chunks(), the final instance will
+take precedence.
+
+.SS The high-level read interface
+
+At this point there are two ways to proceed; through the high-level
+read interface, or through a sequence of low-level read operations.
+You can use the high-level interface if (a) you are willing to read
+the entire image into memory, and (b) the input transformations
+you want to do are limited to the following set:
+
+    PNG_TRANSFORM_IDENTITY      No transformation
+    PNG_TRANSFORM_STRIP_16      Strip 16-bit samples to 8 bits
+    PNG_TRANSFORM_STRIP_ALPHA   Discard the alpha channel
+    PNG_TRANSFORM_PACKING       Expand 1, 2 and 4-bit samples to bytes
+    PNG_TRANSFORM_PACKSWAP      Change order of packed pixels to LSB first
+    PNG_TRANSFORM_EXPAND        Perform set_expand()
+    PNG_TRANSFORM_INVERT_MONO   Invert monochrome images
+    PNG_TRANSFORM_SHIFT         Normalize pixels to the sBIT depth
+    PNG_TRANSFORM_BGR           Flip RGB to BGR, RGBA to BGRA
+    PNG_TRANSFORM_SWAP_ALPHA    Flip RGBA to ARGB or GA to AG
+    PNG_TRANSFORM_INVERT_ALPHA  Change alpha from opacity to transparency
+    PNG_TRANSFORM_SWAP_ENDIAN   Byte-swap 16-bit samples
+
+(This excludes setting a background color, doing gamma transformation,
+dithering, and setting filler.)  If this is the case, simply do this:
+
+    png_read_png(png_ptr, info_ptr, png_transforms, NULL)
+
+where png_transforms is an integer containing the logical-or of some set of
+transformation flags.  This call is equivalent to png_read_info(),
+followed the set of transformations indicated by the transform mask,
+followed by png_update_info(), followed by a read of the image bytes
+to the info member `rowpointers', followed by png_read_end().
+
+(The final parameter of this call is not yet used.  Someday it
+will point to transformation parameters.)
+
+.SS The low-level read interface
+
+If you are going the low-level route, you are now ready to read all
+the file information up to the actual image data.  You do this with a
+call to png_read_info().
 
     png_read_info(png_ptr, info_ptr);
 
-This will read all chunks up to but not including the image data.
-Both known and unknown chunks will be read.  Known chunks will be
-parsed into information in various info_ptr members; unknown chunks
-will be discarded, unless you previously called
+This will process all chunks up to but not including the image data.
 
-    png_set_keep_unknown_chunks();
+There is one transformation you may need to set up before doing
+png_read_info(), however.  In PNG files, the alpha channel in an image
+is the level of opacity.  If you need the alpha channel in an image to
+be the level of transparency instead of opacity, you can invert the
+alpha channel (or the tRNS chunk data) after it's read, so that 0 is
+fully opaque and 255 (in 8-bit or paletted images) or 65535 (in 16-bit
+images) is fully transparent, with
 
-in which case they will be saved as raw data onto a list of
-png_unknown_chunk structures (and written out if you subsequently
-call png_write_info and friends).
+    png_set_invert_alpha(png_ptr);
 
-Functions are used to get the information from the info_ptr:
+This must appear before png_write_info() instead of later with the
+other transformations because in the case of paletted images the tRNS
+chunk data has to be inverted before the tRNS chunk is written.
+If your image is not a paletted image, the tRNS data (which in such cases
+represents a single color to be rendered as transparent) won't need to
+be changed, and you can safely do this transformation after your
+png_read_info() call.
+
+.SS Querying the info structure
+
+Functions are used to get the information from the info_ptr once it
+has been read.  Note that these fields may not be completely filled
+in until png_read_end() has read the chunk data following the image.
 
     png_get_IHDR(png_ptr, info_ptr, &width, &height,
        &bit_depth, &color_type, &interlace_type,
@@ -1140,20 +1286,28 @@
 
     png_get_bKGD(png_ptr, info_ptr, &background);
     background     - background color (PNG_VALID_bKGD)
+                     valid 16-bit red, green and blue
+                     values, regardless of color_type
 
     num_text = png_get_text(png_ptr, info_ptr, &text_ptr);
     text_ptr       - array of png_text holding image
                      comments
-    text_ptr[i]->lang  - language of comment (NULL for unknown).
+    text_ptr[i]->compression - type of compression used
+                 on "text" PNG_TEXT_COMPRESSION_NONE
+                           PNG_TEXT_COMPRESSION_zTXt
+                           PNG_ITXT_COMPRESSION_NONE
+                           PNG_ITXT_COMPRESSION_zTXt
     text_ptr[i]->key   - keyword for comment.
-    text_ptr[i]->translated_keyword  - keyword in UTF-8 (NULL for unknown).
     text_ptr[i]->text  - text comments for current
                          keyword.
-    text_ptr[i]->compression - type of compression used
-                     on "text" PNG_TEXT_COMPRESSION_NONE
-                     or PNG_TEXT_COMPRESSION_zTXt
+    text_ptr[i]->text_length - length of text string,
+                 after decompression, 0 for iTXt
+    text_ptr[i]->itxt_length - length of itxt string,
+                 after decompression, 0 for tEXt/zTXt
+    text_ptr[i]->lang  - language of comment (NULL for unknown).
+    text_ptr[i]->translated_keyword  - keyword in UTF-8 (NULL
+                         for unknown).
     num_text       - number of comments
-
     num_spalettes = png_get_spalettes(png_ptr, info_ptr, &palette_ptr);
     palette_ptr    - array of png_spalette structures holding contents
                      of one or more sPLT chunks read.
@@ -1188,6 +1342,7 @@
     unknowns[i].name  - name of unknown chunk
     unknowns[i].data  - data of unknown chunk
     unknowns[i].size  - size of unknown chunk
+    unknowns[i].location - position of chunk in file
 
 The data from the pHYs chunk can be retrieved in several convenient
 forms:
@@ -1232,6 +1387,8 @@
 until after you read the stuff after the image.  This will be
 mentioned again below in the discussion that goes with png_read_end().
 
+.SS Input transformations
+
 After you've read the header information, you can set up the library
 to handle any special transformations of the image data.  The various
 ways to transform the data will be described in the order that they
@@ -1566,6 +1723,8 @@
 array of pointers to each row, as it will be needed for some
 of the functions below.
 
+.SS Reading image data
+
 After you've allocated memory, you can read the image data.
 The simplest way to do this is in one function call.  If you are
 allocating enough memory to hold the whole image, you can just
@@ -1674,12 +1833,14 @@
     png_read_rows(png_ptr, NULL, row_pointers,
        number_of_rows);
 
-After you are finished reading the image, you can finish reading
-the file.  If you are interested in comments or time, which may be
-stored either before or after the image data, you should pass the
-separate png_info struct if you want to keep the comments from
-before and after the image separate.  If you are not interested, you
-can pass NULL.
+.SS Finishing a sequential read
+
+After you are finished reading the image through either the high- or
+low-level interfaces, you can finish reading the file.  If you are
+interested in comments or time, which may be stored either before or
+after the image data, you should pass the separate png_info struct if
+you want to keep the comments from before and after the image
+separate.  If you are not interested, you can pass NULL.
 
    png_read_end(png_ptr, end_info);
 
@@ -1694,16 +1855,20 @@
     png_free_text(png_ptr, info_ptr, num)
     num          - number of text item to be freed (-1 for all items)
 
+    png_free_hIST(png_ptr, info_ptr)
+
     png_free_iCCP(png_ptr, info_ptr)
 
     png_free_pCAL(png_ptr, info_ptr)
 
     png_free_sCAL(png_ptr, info_ptr)
 
-    png_free_spalette(png_ptr, info_ptr, num)
+    png_free_spalettes(png_ptr, info_ptr, num)
     num          - number of suggested-paletted entry to be freed
                    (-1 for all suggested palettes)
 
+    png_free_pixels(png_ptr, info_ptr)
+
     png_free_unknown_chunk(png_ptr, info_ptr, num)
     num          - number of unknown chunk to be freed
                    (-1 for all suggested palettes)
@@ -1714,8 +1879,7 @@
 
 For a more compact example of reading a PNG image, see the file example.c.
 
-
-Reading PNG files progressively:
+.SS Reading PNG files progressively
 
 The progressive reader is slightly different then the non-progressive
 reader.  Instead of calling png_read_info(), png_read_rows(), and
@@ -1892,6 +2056,8 @@
 importance is repeated here, so you won't have to constantly look
 back up in the reading section to understand writing.
 
+.SS Setup
+
 You will want to do the I/O initialization before you get into libpng,
 so if it doesn't work, you don't have anything to undo. If you are not
 using the standard I/O functions, you will need to replace them with
@@ -1954,6 +2120,10 @@
     ...
     return;
 
+If you would rather avoid the complexity of setjmp/longjmp issues,
+you can compile libpng with PNG_SETJMP_NOT_SUPPORTED, in which case
+errors will result in a call to PNG_ABORT() which defaults to abort().
+
 Now you need to set up the output code.  The default for libpng is to
 use the C function fwrite().  If you use this, you will need to pass a
 valid FILE * in the function png_init_io().  Be sure that the file is
@@ -1963,6 +2133,8 @@
 
     png_init_io(png_ptr, fp);
 
+.SS Write callbacks
+
 At this point, you can set up a callback function that will be
 called after each row has been written, which you can use to control
 a progress meter or the like.  It's demonstrated in pngtest.c.
@@ -2017,6 +2189,8 @@
     png_set_compression_window_bits(png_ptr, 15);
     png_set_compression_method(png_ptr, 8);
 
+.SS Setting the contents of info for output
+
 You now need to fill in the png_info structure with all the data you
 wish to write before the actual image.  Note that the only thing you
 are allowed to write after the image is the text chunks and the time
@@ -2146,15 +2320,22 @@
     png_set_text(png_ptr, info_ptr, text_ptr, num_text);
     text_ptr       - array of png_text holding image
                      comments
-    text_ptr[i]->lang  - language of comment (NULL for unknown).
+    text_ptr[i]->compression - type of compression used
+                 on "text" PNG_TEXT_COMPRESSION_NONE
+                           PNG_TEXT_COMPRESSION_zTXt
+                           PNG_ITXT_COMPRESSION_NONE
+                           PNG_ITXT_COMPRESSION_zTXt
     text_ptr[i]->key   - keyword for comment.
-    text_ptr[i]->translated_keyword  - keyword in UTF-8 (NULL for unknown).
     text_ptr[i]->text  - text comments for current
                          keyword.
-    text_ptr[i]->compression - type of compression used
-         on "text" PNG_TEXT_COMPRESSION_NONE or
-         PNG_TEXT_COMPRESSION_zTXt
-    num_text    - number of comments in text_ptr
+    text_ptr[i]->text_length - length of text string,
+                 after decompression, 0 for iTXt
+    text_ptr[i]->itxt_length - length of itxt string,
+                 after decompression, 0 for tEXt/zTXt
+    text_ptr[i]->lang  - language of comment (NULL for unknown).
+    text_ptr[i]->translated_keyword  - keyword in UTF-8 (NULL
+                         for unknown).
+    num_text       - number of comments
 
     png_set_spalettes(png_ptr, info_ptr, &palette_ptr, num_spalettes);
     palette_ptr    - array of png_spalette structures to be added to
@@ -2189,20 +2370,15 @@
     unknowns[i].name  - name of unknown chunk
     unknowns[i].data  - data of unknown chunk
     unknowns[i].size  - size of unknown chunk
-
-In PNG files, the alpha channel in an image is the level of opacity.
-If your data is supplied as a level of transparency, you can invert the
-alpha channel before you write it, so that 0 is fully transparent and 255
-(in 8-bit or paletted images) or 65535 (in 16-bit images) is fully opaque,
-with
-
-    png_set_invert_alpha(png_ptr);
-
-This must appear here instead of later with the other transformations
-because in the case of paletted images the tRNS chunk data has to
-be inverted before the tRNS chunk is written.  If your image is not a
-paletted image, the tRNS data (which in such cases represents a single
-color to be rendered as transparent) won't be changed.
+    unknowns[i].location - position to write chunk in file
+                           0: do not write chunk
+                           PNG_HAVE_IHDR: before PLTE
+                           PNG_HAVE_PLTE: before IDAT
+                           PNG_AFTER_IDAT: after IDAT
+    The "location" member is set automatically according to
+    what part of the output file has already been written.
+    You can change its value after calling png_set_unknown_chunks()
+    as demonstrated in pngtest.c.
 
 A quick word about text and num_text.  text is an array of png_text
 structures.  num_text is the number of valid structures in the array.
@@ -2284,6 +2460,8 @@
 png_convert_to_rfc1123(png_timep) is provided to convert from PNG
 time to an RFC 1123 format string.
 
+.SS Writing unknown chunks
+
 You can use the png_set_unknown_chunks function to queue up chunks
 for writing.  You give it a chunk name, raw data, and a size; that's
 all there is to it.  The chunks will be written by the next following
@@ -2292,11 +2470,63 @@
 list will also be written out in a sequence that satisfies the PNG
 specification's ordering rules.
 
-You are now ready to write all the file information up to the actual
-image data.  You do this with a call to png_write_info().
+.SS The high-level write interface
+
+At this point there are two ways to proceed; through the high-level
+write interface, or through a sequence of low-level write operations.
+You can use the high-level interface if your image data is present
+on the rowpointers member of the info structure.  All defined output
+transformations are pernmitted, enabled by the following masks.
+
+    PNG_TRANSFORM_IDENTITY      No transformation
+    PNG_TRANSFORM_PACKING       Pack 1, 2 and 4-bit samples
+    PNG_TRANSFORM_PACKSWAP      Change order of packed pixels to LSB first
+    PNG_TRANSFORM_INVERT_MONO   Invert monochrome images
+    PNG_TRANSFORM_SHIFT         Normalize pixels to the sBIT depth
+    PNG_TRANSFORM_BGR           Flip RGB to BGR, RGBA to BGRA
+    PNG_TRANSFORM_SWAP_ALPHA    Flip RGBA to ARGB or GA to AG
+    PNG_TRANSFORM_INVERT_ALPHA  Change alpha from opacity to transparency
+    PNG_TRANSFORM_SWAP_ENDIAN   Byte-swap 16-bit samples
+    PNG_TRANSFORM_STRIP_FILLER  Strip out filler bytes.
+
+If you have valid image data on the rowpointers member, simply do this:
+
+    png_write_png(png_ptr, info_ptr, png_transforms, NULL)
+
+where png_transforms is an integer containing the logical-or of some set of
+transformation flags.  This call is equivalent to png_write_info(),
+followed by the set of transformations indicated by the transform
+mask, followed by followed by a write of the image bytes to the info
+member `rowpointers', followed by png_write_end().
+
+(The final parameter of this call is not yet used.  Someday it
+may point to output transformation parameters.)
+
+.SS The low-level write interface
+
+If you are going the low-level route instead, you are now ready to
+write all the file information up to the actual image data.  You do
+this with a call to png_write_info().
 
     png_write_info(png_ptr, info_ptr);
 
+Note that there is one transformation you may need to do before
+png_write_info().  In PNG files, the alpha channel in an image is the
+level of opacity.  If your data is supplied as a level of
+transparency, you can invert the alpha channel before you write it, so
+that 0 is fully transparent and 255 (in 8-bit or paletted images) or
+65535 (in 16-bit images) is fully opaque, with
+
+    png_set_invert_alpha(png_ptr);
+
+This must appear before png_write_info() instead of later with the
+other transformations because in the case of paletted images the tRNS
+chunk data has to be inverted before the tRNS chunk is written.  If
+your image is not a paletted image, the tRNS data (which in such cases
+represents a single color to be rendered as transparent) won't need to
+be changed, and you can safely do this transformation after your
+png_write_info() call.
+
 If you need to write a private chunk that you want to appear before
 the PLTE chunk when PLTE is present, you can write the PNG info in
 two steps, and insert code to write your own chunk between them:
@@ -2437,6 +2667,8 @@
 only degrade the compression performance by a few percent over images
 that do not use flushing.
 
+.SS Writing the image data
+
 That's it for the transformations.  Now you can write the image data.
 The simplest way to do this is in one function call.  If have the
 whole image in memory, you can just call png_write_image() and libpng
@@ -2470,7 +2702,7 @@
     png_write_row(png_ptr, &row_pointer);
 
 When the file is interlaced, things can get a good deal more
-complicated.  The only currently (as of August 1999 -- PNG Specification
+complicated.  The only currently (as of January 2000 -- PNG Specification
 version 1.2, dated July 1999) defined interlacing scheme for PNG files
 is the "Adam7" interlace scheme, that breaks down an
 image into seven smaller images of varying size.  libpng will build
@@ -2500,6 +2732,8 @@
 you may want to read about interlacing in the PNG specification,
 and only update the rows that are actually used.
 
+.SS Finishing a sequential write
+
 After you are finished writing the image, you should finish writing
 the file.  If you are interested in writing comments or time, you should
 pass an appropriately filled png_info pointer.  If you are not interested,
@@ -2517,16 +2751,20 @@
     png_free_text(png_ptr, info_ptr, num)
     num          - number of text item to be freed (-1 for all items)
 
+    png_free_hIST(png_ptr, info_ptr)
+
     png_free_iCCP(png_ptr, info_ptr)
 
     png_free_pCAL(png_ptr, info_ptr)
 
     png_free_sCAL(png_ptr, info_ptr)
 
-    png_free_spalette(png_ptr, info_ptr, num)
+    png_free_spalettes(png_ptr, info_ptr, num)
     num          - number of suggested-paletted entry to be freed
                    (-1 for all suggested palettes)
 
+    png_free_pixels(png_ptr, info_ptr)
+
     png_free_unknown_chunk(png_ptr, info_ptr, num)
     num          - number of unknown chunk entry to be freed
                    (-1 for all suggested palettes)
@@ -2535,8 +2773,7 @@
 already been freed, or has not yet been allocated, and will in that
 case do nothing.
 
-You must free any data you allocated for info_ptr, such as comments,
-palette, or histogram, before the call to png_destroy_write_struct();
+If you allocated palette data, you must free it before the call to png_destroy_write_struct();
 
 For a more compact example of writing a PNG image, see the file example.c.
 
@@ -2596,8 +2833,11 @@
 Error handling in libpng is done through png_error() and png_warning().
 Errors handled through png_error() are fatal, meaning that png_error()
 should never return to its caller.  Currently, this is handled via
-setjmp() and longjmp(), but you could change this to do things like
-exit() if you should wish.  On non-fatal errors, png_warning() is called
+setjmp() and longjmp() (unless you have compiled libpng with
+PNG_SETJMP_NOT_SUPPORTED, in which case it is handled via PNG_ABORT()),
+but you could change this to do things like exit() if you should wish.
+
+On non-fatal errors, png_warning() is called
 to print a warning message, and then control returns to the calling code.
 By default png_error() and png_warning() print a message on stderr via
 fprintf() unless the library is compiled with PNG_NO_STDIO defined.  If
@@ -2630,16 +2870,25 @@
 setjmp returns non-zero besides returning itself.  Consult your compiler
 documentation for more details.
 
-If you need to read or write custom chunks, you will need to get deeper
-into the libpng code, as a mechanism has not yet been supplied for user
-callbacks with custom chunks.  First, read the PNG specification, and have
-a first level of understanding of how it works.  Pay particular attention
-to the sections that describe chunk names, and look at how other chunks
-were designed, so you can do things similarly.  Second, check out the
-sections of libpng that read and write chunks.  Try to find a chunk that
-is similar to yours and use it as a template.  More details can be found in the
-comments inside the code.  A way of handling unknown chunks in a generic
-method, potentially via callback functions, would be best.
+.SS Custom chunks
+
+If you need to read or write custom chunks, you may need to get deeper
+into the libpng code.  The library now has mechanisms for storing
+and writing chunks of unknown type; you can even declare callbacks
+for custom chunks.  Hoewver, this may not be good enough if the
+library code itself needs to know about interactions between your
+chunk and existing `intrinsic' chunks.
+
+If you need to write a new intrinsic chunk, first read the PNG
+specification. Acquire a first level of
+understanding of how it works.  Pay particular attention to the
+sections that describe chunk names, and look at how other chunks were
+designed, so you can do things similarly.  Second, check out the
+sections of libpng that read and write chunks.  Try to find a chunk
+that is similar to yours and use it as a template.  More details can
+be found in the comments inside the code.  It is best to handle unknown
+chunks in a generic method, via callback functions, instead of by
+modifying libpng functions.
 
 If you wish to write your own transformation for the data, look through
 the part of the code that does the transformations, and check out some of
@@ -2647,7 +2896,7 @@
 transformation to the one you want to add and copy off of it.  More details
 can be found in the comments inside the code itself.
 
-Configuring for 16 bit platforms:
+.SS Configuring for 16 bit platforms
 
 You may need to change the png_large_malloc() and png_large_free()
 routines in pngmem.c, as these are required to allocate 64K, although
@@ -2656,13 +2905,13 @@
 it cannot allocate more then 64K at a time.  Even if you can, the memory
 won't be accessible.  So limit zlib and libpng to 64K by defining MAXSEG_64K.
 
-Configuring for DOS:
+.SS Configuring for DOS
 
 For DOS users who only have access to the lower 640K, you will
 have to limit zlib's memory usage via a png_set_compression_mem_level()
 call.  See zlib.h or zconf.h in the zlib library for more information.
 
-Configuring for Medium Model:
+.SS Configuring for Medium Model
 
 Libpng's support for medium model has been tested on most of the popular
 compilers.  Make sure MAXSEG_64K gets defined, USE_FAR_KEYWORD gets
@@ -2670,10 +2919,10 @@
 all set.  Everything in the library (except for zlib's structure) is
 expecting far data.  You must use the typedefs with the p or pp on
 the end for pointers (or at least look at them and be careful).  Make
-note that the row's of data are defined as png_bytepp, which is an
+note that the rows of data are defined as png_bytepp, which is an
 unsigned char far * far *.
 
-Configuring for gui/windowing platforms:
+.SS Configuring for gui/windowing platforms:
 
 You will need to write new error and warning functions that use the GUI
 interface, as described previously, and set them to be the error and
@@ -2682,7 +2931,7 @@
 They can be changed later via png_set_error_fn().  On some compilers,
 you may also have to change the memory allocators (png_malloc, etc.).
 
-Configuring for compiler xxx:
+.SS Configuring for compiler xxx:
 
 All includes for libpng are in pngconf.h.  If you need to add/change/delete
 an include, this is the place to do it.  The includes that are not
@@ -2690,7 +2939,7 @@
 which is only defined for those routines inside libpng itself.  The
 files in libpng proper only include png.h, which includes pngconf.h.
 
-Configuring zlib:
+.SS Configuring zlib:
 
 There are special functions to configure the compression.  Perhaps the
 most useful one changes the compression level, which currently uses
@@ -2722,7 +2971,7 @@
         window_bits);
     png_set_compression_method(png_ptr, method);
 
-Controlling row filtering:
+.SS Controlling row filtering
 
 If you want to control whether libpng uses filtering or not, which
 filters are used, and how it goes about picking row filters, you
@@ -2788,7 +3037,7 @@
 are given only to help explain the function usage.  Little testing has
 been done to find optimum values for either the costs or the weights.
 
-Removing unwanted object code:
+.SS Removing unwanted object code
 
 There are a bunch of #define's in pngconf.h that control what parts of
 libpng are compiled.  All the defines end in _SUPPORTED.  If you are
@@ -2826,7 +3075,7 @@
 The size of the library itself should not be an issue, because only
 those sections that are actually used will be loaded into memory.
 
-Requesting debug printout:
+.SS Requesting debug printout
 
 The macro definition PNG_DEBUG can be used to request debugging
 printout.  Set it to an integer value in the range 0 to 3.  Higher
@@ -2898,13 +3147,13 @@
 
 .SH VII. Y2K Compliance in libpng
 
-December 10, 1999
+February 5, 2000
 
 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.0.5h are Y2K compliant.  It is my belief that earlier
+upward through 1.0.5q 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
@@ -3030,7 +3279,7 @@
 
 Thanks to Frank J. T. Wojcik for helping with the documentation.
 
-Libpng version 1.0.5h - December 10, 1999:
+Libpng version 1.0.5q - February 5, 2000:
 Initially created in 1995 by Guy Eric Schalnat, then of Group 42, Inc.
 Currently maintained by Glenn Randers-Pehrson (randeg@alum.rpi.edu).
 
@@ -3044,8 +3293,8 @@
 (libpng versions 0.5, May 1995, through 0.89c, May 1996)
 Copyright (c) 1996, 1997 Andreas Dilger
 (libpng versions 0.90, December 1996, through 0.96, May 1997)
-Copyright (c) 1998, 1999 Glenn Randers-Pehrson
-(libpng versions 0.97, January 1998, through 1.0.5h, December 10, 1999)
+Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson
+(libpng versions 0.97, January 1998, through 1.0.5q, February 5, 2000)
 
 For the purposes of this copyright and license, "Contributing Authors"
 is defined as the following set of individuals:
@@ -3058,6 +3307,7 @@
    Tom Lane
    Dave Martindale
    Glenn Randers-Pehrson
+   Eric S. Raymond
    Greg Roelofs
    Guy Eric Schalnat
    Paul Schmidt
diff --git a/libpng.txt b/libpng.txt
index 43b8f53..d688eac 100644
--- a/libpng.txt
+++ b/libpng.txt
@@ -1,9 +1,9 @@
 libpng.txt - A description on how to use and modify libpng
 
- libpng version 1.0.5h - December 10, 1999
+ libpng version 1.0.5q - February 5, 2000
  Updated and distributed by Glenn Randers-Pehrson
  <randeg@alum.rpi.edu>
- Copyright (c) 1998, 1999 Glenn Randers-Pehrson
+ Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson
  For conditions of distribution and use, see copyright
  notice in png.h.
 
@@ -19,10 +19,9 @@
  Schalnat, Group 42, Inc.
 
  Updated/rewritten per request in the libpng FAQ
- Copyright (c) 1995 Frank J. T. Wojcik
- December 18, 1995 && January 20, 1996
+ Copyright (c) 1995, 1996 Frank J. T. Wojcik
+ December 18, 1995 & January 20, 1996
 
- *
 I. Introduction
 
 This file describes how to use and modify the PNG reference library
@@ -102,13 +101,14 @@
 
 III. Reading
 
-Reading PNG files:
-
 We'll now walk you through the possible functions to call when reading
-in a PNG file, briefly explaining the syntax and purpose of each one.
-See example.c and png.h for more detail.  While Progressive reading
-is covered in the next section, you will still need some of the
-functions discussed in this section to read a PNG file.
+in a PNG file sequentially, briefly explaining the syntax and purpose
+of each one.  See example.c and png.h for more detail.  While
+progressive reading is covered in the next section, you will still
+need some of the functions discussed in this section to read a PNG
+file.
+
+Setup
 
 You will want to do the I/O initialization(*) before you get into libpng,
 so if it doesn't work, you don't have much to undo.  Of course, you
@@ -208,6 +208,10 @@
         return;
     }
 
+If you would rather avoid the complexity of setjmp/longjmp issues,
+you can compile libpng with PNG_SETJMP_NOT_SUPPORTED, in which case
+errors will result in a call to PNG_ABORT() which defaults to abort().
+
 Now you need to set up the input code.  The default for libpng is to
 use the C function fread().  If you use this, you will need to pass a
 valid FILE * in the function png_init_io().  Be sure that the file is
@@ -224,6 +228,42 @@
 
     png_set_sig_bytes(png_ptr, number);
 
+Setting up callback code
+
+You can set up a callback function to handle any unknown chunks in the
+input stream. You must supply the function
+
+    read_chunk_callback(png_ptr ptr,
+         png_unknown_chunkp chunk);
+    {
+       /* The unknown chunk structure contains your
+          chunk data: */
+           png_byte name[5];
+           png_byte *data;
+           png_size_t size;
+       /* Note that libpng has already taken care of the
+          CRC handling */
+
+       /* put your code here.  Return one of the following: */
+
+       return (-n); /* chunk had an error */
+       return (0); /* did not recognize */
+       return (n); /* success */
+    }
+
+(You can give your function another name that you like instead of
+"read_chunk_callback")
+
+To inform libpng about your function, use
+
+    png_set_read_user_chunk_fn(png_ptr, user_chunk_ptr,
+        read_chunk_callback);
+
+This names not only the callback function, but also a user pointer that
+you can retrieve with
+
+    png_get_user_chunk_ptr(png_ptr);
+
 At this point, you can set up a callback function that will be
 called after each row has been read, which you can use to control
 a progress meter or the like.  It's demonstrated in pngtest.c.
@@ -240,19 +280,6 @@
 
     png_set_read_status_fn(png_ptr, read_row_callback);
 
-In PNG files, the alpha channel in an image is the level of opacity.
-If you need the alpha channel in an image to be the level of transparency
-instead of opacity, you can invert the alpha channel (or the tRNS chunk
-data) after it's read, so that 0 is fully opaque and 255 (in 8-bit or
-paletted images) or 65535 (in 16-bit images) is fully transparent, with
-
-    png_set_invert_alpha(png_ptr);
-
-This has to appear here rather than later with the other transformations
-because the tRNS chunk data must be modified in the case of paletted images.
-If your image is not a paletted image, the tRNS data (which in such cases
-represents a single color to be rendered as transparent) won't be changed.
-
 Finally, you can write your own transformation function if none of
 the existing ones meets your needs.  This is done by setting a callback
 with
@@ -276,6 +303,8 @@
     png_set_user_transform_info(png_ptr, user_ptr,
        user_depth, user_channels);
 
+The user's application, not libpng, is responsible for allocating and
+freeing any memory required for the user structure.
 
 You can retrieve the pointer via the function
 png_get_user_transform_ptr().  For example:
@@ -283,23 +312,100 @@
     voidp read_user_transform_ptr =
        png_get_user_transform_ptr(png_ptr);
 
-You are now ready to read all the file information up to the actual
-image data.  You do this with a call to png_read_info().
+Unknown-chunk handling
+
+Now you get to set the way the library processes unknown chunks in the
+input PNG stream. Both known and unknown chunks will be read.  Normal
+behavior is that known chunks will be parsed into information in
+various info_ptr members; unknown chunks will be discarded. To change
+this, you can call:
+
+    png_set_keep_unknown_chunks(png_ptr, info_ptr, keep,
+        chunk_list, num_chunks);
+    keep       - 0: do not keep
+                 1: keep only if safe-to-copy
+                 2: keep even if unsafe-to-copy
+    chunk_list - list of chunks affected (a byte string,
+                 five bytes per chunk, NULL or '\0' if
+                 num_chunks is 0)
+    num_chunks - number of chunks affected; if 0, all
+                 unknown chunks are affected
+
+Unknown chunks declared in this way will be saved as raw data onto a
+list of png_unknown_chunk structures.  If a chunk that is normally
+known to libpng is named in the list, it will be handled as unknown,
+according to the "keep" directive.  If a chunk is named in successive
+instances of png_set_keep_unknown_chunks(), the final instance will
+take precedence.
+
+The high-level read interface
+
+At this point there are two ways to proceed; through the high-level
+read interface, or through a sequence of low-level read operations.
+You can use the high-level interface if (a) you are willing to read
+the entire image into memory, and (b) the input transformations
+you want to do are limited to the following set:
+
+    PNG_TRANSFORM_IDENTITY      No transformation
+    PNG_TRANSFORM_STRIP_16      Strip 16-bit samples to 8 bits
+    PNG_TRANSFORM_STRIP_ALPHA   Discard the alpha channel
+    PNG_TRANSFORM_PACKING       Expand 1, 2 and 4-bit samples to bytes
+    PNG_TRANSFORM_PACKSWAP      Change order of packed pixels to LSB first
+    PNG_TRANSFORM_EXPAND        Perform set_expand()
+    PNG_TRANSFORM_INVERT_MONO   Invert monochrome images
+    PNG_TRANSFORM_SHIFT         Normalize pixels to the sBIT depth
+    PNG_TRANSFORM_BGR           Flip RGB to BGR, RGBA to BGRA
+    PNG_TRANSFORM_SWAP_ALPHA    Flip RGBA to ARGB or GA to AG
+    PNG_TRANSFORM_INVERT_ALPHA  Change alpha from opacity to transparency
+    PNG_TRANSFORM_SWAP_ENDIAN   Byte-swap 16-bit samples
+
+(This excludes setting a background color, doing gamma transformation,
+dithering, and setting filler.)  If this is the case, simply do this:
+
+    png_read_png(png_ptr, info_ptr, png_transforms, NULL)
+
+where png_transforms is an integer containing the logical-or of some set of
+transformation flags.  This call is equivalent to png_read_info(),
+followed the set of transformations indicated by the transform mask,
+followed by png_update_info(), followed by a read of the image bytes
+to the info member `rowpointers', followed by png_read_end().
+
+(The final parameter of this call is not yet used.  Someday it
+will point to transformation parameters.)
+
+The low-level read interface
+
+If you are going the low-level route, you are now ready to read all
+the file information up to the actual image data.  You do this with a
+call to png_read_info().
 
     png_read_info(png_ptr, info_ptr);
 
-This will read all chunks up to but not including the image data.
-Both known and unknown chunks will be read.  Known chunks will be
-parsed into information in various info_ptr members; unknown chunks
-will be discarded, unless you previously called
+This will process all chunks up to but not including the image data.
 
-    png_set_keep_unknown_chunks();
+There is one transformation you may need to set up before doing
+png_read_info(), however.  In PNG files, the alpha channel in an image
+is the level of opacity.  If you need the alpha channel in an image to
+be the level of transparency instead of opacity, you can invert the
+alpha channel (or the tRNS chunk data) after it's read, so that 0 is
+fully opaque and 255 (in 8-bit or paletted images) or 65535 (in 16-bit
+images) is fully transparent, with
 
-in which case they will be saved as raw data onto a list of
-png_unknown_chunk structures (and written out if you subsequently
-call png_write_info and friends).
+    png_set_invert_alpha(png_ptr);
 
-Functions are used to get the information from the info_ptr:
+This must appear before png_write_info() instead of later with the
+other transformations because in the case of paletted images the tRNS
+chunk data has to be inverted before the tRNS chunk is written.
+If your image is not a paletted image, the tRNS data (which in such cases
+represents a single color to be rendered as transparent) won't need to
+be changed, and you can safely do this transformation after your
+png_read_info() call.
+
+Querying the info structure
+
+Functions are used to get the information from the info_ptr once it
+has been read.  Note that these fields may not be completely filled
+in until png_read_end() has read the chunk data following the image.
 
     png_get_IHDR(png_ptr, info_ptr, &width, &height,
        &bit_depth, &color_type, &interlace_type,
@@ -439,20 +545,28 @@
 
     png_get_bKGD(png_ptr, info_ptr, &background);
     background     - background color (PNG_VALID_bKGD)
+                     valid 16-bit red, green and blue
+                     values, regardless of color_type
 
     num_text = png_get_text(png_ptr, info_ptr, &text_ptr);
     text_ptr       - array of png_text holding image
                      comments
-    text_ptr[i]->lang  - language of comment (NULL for unknown).
+    text_ptr[i]->compression - type of compression used
+                 on "text" PNG_TEXT_COMPRESSION_NONE
+                           PNG_TEXT_COMPRESSION_zTXt
+                           PNG_ITXT_COMPRESSION_NONE
+                           PNG_ITXT_COMPRESSION_zTXt
     text_ptr[i]->key   - keyword for comment.
-    text_ptr[i]->translated_keyword  - keyword in UTF-8 (NULL for unknown).
     text_ptr[i]->text  - text comments for current
                          keyword.
-    text_ptr[i]->compression - type of compression used
-                     on "text" PNG_TEXT_COMPRESSION_NONE
-                     or PNG_TEXT_COMPRESSION_zTXt
+    text_ptr[i]->text_length - length of text string,
+                 after decompression, 0 for iTXt
+    text_ptr[i]->itxt_length - length of itxt string,
+                 after decompression, 0 for tEXt/zTXt
+    text_ptr[i]->lang  - language of comment (NULL for unknown).
+    text_ptr[i]->translated_keyword  - keyword in UTF-8 (NULL
+                         for unknown).
     num_text       - number of comments
-
     num_spalettes = png_get_spalettes(png_ptr, info_ptr, &palette_ptr);
     palette_ptr    - array of png_spalette structures holding contents
                      of one or more sPLT chunks read.
@@ -487,6 +601,7 @@
     unknowns[i].name  - name of unknown chunk
     unknowns[i].data  - data of unknown chunk
     unknowns[i].size  - size of unknown chunk
+    unknowns[i].location - position of chunk in file
 
 The data from the pHYs chunk can be retrieved in several convenient
 forms:
@@ -531,6 +646,8 @@
 until after you read the stuff after the image.  This will be
 mentioned again below in the discussion that goes with png_read_end().
 
+Input transformations
+
 After you've read the header information, you can set up the library
 to handle any special transformations of the image data.  The various
 ways to transform the data will be described in the order that they
@@ -865,6 +982,8 @@
 array of pointers to each row, as it will be needed for some
 of the functions below.
 
+Reading image data
+
 After you've allocated memory, you can read the image data.
 The simplest way to do this is in one function call.  If you are
 allocating enough memory to hold the whole image, you can just
@@ -973,12 +1092,14 @@
     png_read_rows(png_ptr, NULL, row_pointers,
        number_of_rows);
 
-After you are finished reading the image, you can finish reading
-the file.  If you are interested in comments or time, which may be
-stored either before or after the image data, you should pass the
-separate png_info struct if you want to keep the comments from
-before and after the image separate.  If you are not interested, you
-can pass NULL.
+Finishing a sequential read
+
+After you are finished reading the image through either the high- or
+low-level interfaces, you can finish reading the file.  If you are
+interested in comments or time, which may be stored either before or
+after the image data, you should pass the separate png_info struct if
+you want to keep the comments from before and after the image
+separate.  If you are not interested, you can pass NULL.
 
    png_read_end(png_ptr, end_info);
 
@@ -993,16 +1114,20 @@
     png_free_text(png_ptr, info_ptr, num)
     num          - number of text item to be freed (-1 for all items)
 
+    png_free_hIST(png_ptr, info_ptr)
+
     png_free_iCCP(png_ptr, info_ptr)
 
     png_free_pCAL(png_ptr, info_ptr)
 
     png_free_sCAL(png_ptr, info_ptr)
 
-    png_free_spalette(png_ptr, info_ptr, num)
+    png_free_spalettes(png_ptr, info_ptr, num)
     num          - number of suggested-paletted entry to be freed
                    (-1 for all suggested palettes)
 
+    png_free_pixels(png_ptr, info_ptr)
+
     png_free_unknown_chunk(png_ptr, info_ptr, num)
     num          - number of unknown chunk to be freed
                    (-1 for all suggested palettes)
@@ -1013,8 +1138,7 @@
 
 For a more compact example of reading a PNG image, see the file example.c.
 
-
-Reading PNG files progressively:
+Reading PNG files progressively
 
 The progressive reader is slightly different then the non-progressive
 reader.  Instead of calling png_read_info(), png_read_rows(), and
@@ -1191,6 +1315,8 @@
 importance is repeated here, so you won't have to constantly look
 back up in the reading section to understand writing.
 
+Setup
+
 You will want to do the I/O initialization before you get into libpng,
 so if it doesn't work, you don't have anything to undo. If you are not
 using the standard I/O functions, you will need to replace them with
@@ -1253,6 +1379,10 @@
     ...
     return;
 
+If you would rather avoid the complexity of setjmp/longjmp issues,
+you can compile libpng with PNG_SETJMP_NOT_SUPPORTED, in which case
+errors will result in a call to PNG_ABORT() which defaults to abort().
+
 Now you need to set up the output code.  The default for libpng is to
 use the C function fwrite().  If you use this, you will need to pass a
 valid FILE * in the function png_init_io().  Be sure that the file is
@@ -1262,6 +1392,8 @@
 
     png_init_io(png_ptr, fp);
 
+Write callbacks
+
 At this point, you can set up a callback function that will be
 called after each row has been written, which you can use to control
 a progress meter or the like.  It's demonstrated in pngtest.c.
@@ -1316,6 +1448,8 @@
     png_set_compression_window_bits(png_ptr, 15);
     png_set_compression_method(png_ptr, 8);
 
+Setting the contents of info for output
+
 You now need to fill in the png_info structure with all the data you
 wish to write before the actual image.  Note that the only thing you
 are allowed to write after the image is the text chunks and the time
@@ -1445,15 +1579,22 @@
     png_set_text(png_ptr, info_ptr, text_ptr, num_text);
     text_ptr       - array of png_text holding image
                      comments
-    text_ptr[i]->lang  - language of comment (NULL for unknown).
+    text_ptr[i]->compression - type of compression used
+                 on "text" PNG_TEXT_COMPRESSION_NONE
+                           PNG_TEXT_COMPRESSION_zTXt
+                           PNG_ITXT_COMPRESSION_NONE
+                           PNG_ITXT_COMPRESSION_zTXt
     text_ptr[i]->key   - keyword for comment.
-    text_ptr[i]->translated_keyword  - keyword in UTF-8 (NULL for unknown).
     text_ptr[i]->text  - text comments for current
                          keyword.
-    text_ptr[i]->compression - type of compression used
-         on "text" PNG_TEXT_COMPRESSION_NONE or
-         PNG_TEXT_COMPRESSION_zTXt
-    num_text    - number of comments in text_ptr
+    text_ptr[i]->text_length - length of text string,
+                 after decompression, 0 for iTXt
+    text_ptr[i]->itxt_length - length of itxt string,
+                 after decompression, 0 for tEXt/zTXt
+    text_ptr[i]->lang  - language of comment (NULL for unknown).
+    text_ptr[i]->translated_keyword  - keyword in UTF-8 (NULL
+                         for unknown).
+    num_text       - number of comments
 
     png_set_spalettes(png_ptr, info_ptr, &palette_ptr, num_spalettes);
     palette_ptr    - array of png_spalette structures to be added to
@@ -1488,20 +1629,15 @@
     unknowns[i].name  - name of unknown chunk
     unknowns[i].data  - data of unknown chunk
     unknowns[i].size  - size of unknown chunk
-
-In PNG files, the alpha channel in an image is the level of opacity.
-If your data is supplied as a level of transparency, you can invert the
-alpha channel before you write it, so that 0 is fully transparent and 255
-(in 8-bit or paletted images) or 65535 (in 16-bit images) is fully opaque,
-with
-
-    png_set_invert_alpha(png_ptr);
-
-This must appear here instead of later with the other transformations
-because in the case of paletted images the tRNS chunk data has to
-be inverted before the tRNS chunk is written.  If your image is not a
-paletted image, the tRNS data (which in such cases represents a single
-color to be rendered as transparent) won't be changed.
+    unknowns[i].location - position to write chunk in file
+                           0: do not write chunk
+                           PNG_HAVE_IHDR: before PLTE
+                           PNG_HAVE_PLTE: before IDAT
+                           PNG_AFTER_IDAT: after IDAT
+    The "location" member is set automatically according to
+    what part of the output file has already been written.
+    You can change its value after calling png_set_unknown_chunks()
+    as demonstrated in pngtest.c.
 
 A quick word about text and num_text.  text is an array of png_text
 structures.  num_text is the number of valid structures in the array.
@@ -1583,6 +1719,8 @@
 png_convert_to_rfc1123(png_timep) is provided to convert from PNG
 time to an RFC 1123 format string.
 
+Writing unknown chunks
+
 You can use the png_set_unknown_chunks function to queue up chunks
 for writing.  You give it a chunk name, raw data, and a size; that's
 all there is to it.  The chunks will be written by the next following
@@ -1591,11 +1729,63 @@
 list will also be written out in a sequence that satisfies the PNG
 specification's ordering rules.
 
-You are now ready to write all the file information up to the actual
-image data.  You do this with a call to png_write_info().
+The high-level write interface
+
+At this point there are two ways to proceed; through the high-level
+write interface, or through a sequence of low-level write operations.
+You can use the high-level interface if your image data is present
+on the rowpointers member of the info structure.  All defined output
+transformations are pernmitted, enabled by the following masks.
+
+    PNG_TRANSFORM_IDENTITY      No transformation
+    PNG_TRANSFORM_PACKING       Pack 1, 2 and 4-bit samples
+    PNG_TRANSFORM_PACKSWAP      Change order of packed pixels to LSB first
+    PNG_TRANSFORM_INVERT_MONO   Invert monochrome images
+    PNG_TRANSFORM_SHIFT         Normalize pixels to the sBIT depth
+    PNG_TRANSFORM_BGR           Flip RGB to BGR, RGBA to BGRA
+    PNG_TRANSFORM_SWAP_ALPHA    Flip RGBA to ARGB or GA to AG
+    PNG_TRANSFORM_INVERT_ALPHA  Change alpha from opacity to transparency
+    PNG_TRANSFORM_SWAP_ENDIAN   Byte-swap 16-bit samples
+    PNG_TRANSFORM_STRIP_FILLER  Strip out filler bytes.
+
+If you have valid image data on the rowpointers member, simply do this:
+
+    png_write_png(png_ptr, info_ptr, png_transforms, NULL)
+
+where png_transforms is an integer containing the logical-or of some set of
+transformation flags.  This call is equivalent to png_write_info(),
+followed by the set of transformations indicated by the transform
+mask, followed by followed by a write of the image bytes to the info
+member `rowpointers', followed by png_write_end().
+
+(The final parameter of this call is not yet used.  Someday it
+may point to output transformation parameters.)
+
+The low-level write interface
+
+If you are going the low-level route instead, you are now ready to
+write all the file information up to the actual image data.  You do
+this with a call to png_write_info().
 
     png_write_info(png_ptr, info_ptr);
 
+Note that there is one transformation you may need to do before
+png_write_info().  In PNG files, the alpha channel in an image is the
+level of opacity.  If your data is supplied as a level of
+transparency, you can invert the alpha channel before you write it, so
+that 0 is fully transparent and 255 (in 8-bit or paletted images) or
+65535 (in 16-bit images) is fully opaque, with
+
+    png_set_invert_alpha(png_ptr);
+
+This must appear before png_write_info() instead of later with the
+other transformations because in the case of paletted images the tRNS
+chunk data has to be inverted before the tRNS chunk is written.  If
+your image is not a paletted image, the tRNS data (which in such cases
+represents a single color to be rendered as transparent) won't need to
+be changed, and you can safely do this transformation after your
+png_write_info() call.
+
 If you need to write a private chunk that you want to appear before
 the PLTE chunk when PLTE is present, you can write the PNG info in
 two steps, and insert code to write your own chunk between them:
@@ -1736,6 +1926,8 @@
 only degrade the compression performance by a few percent over images
 that do not use flushing.
 
+Writing the image data
+
 That's it for the transformations.  Now you can write the image data.
 The simplest way to do this is in one function call.  If have the
 whole image in memory, you can just call png_write_image() and libpng
@@ -1769,7 +1961,7 @@
     png_write_row(png_ptr, &row_pointer);
 
 When the file is interlaced, things can get a good deal more
-complicated.  The only currently (as of August 1999 -- PNG Specification
+complicated.  The only currently (as of January 2000 -- PNG Specification
 version 1.2, dated July 1999) defined interlacing scheme for PNG files
 is the "Adam7" interlace scheme, that breaks down an
 image into seven smaller images of varying size.  libpng will build
@@ -1799,6 +1991,8 @@
 you may want to read about interlacing in the PNG specification,
 and only update the rows that are actually used.
 
+Finishing a sequential write
+
 After you are finished writing the image, you should finish writing
 the file.  If you are interested in writing comments or time, you should
 pass an appropriately filled png_info pointer.  If you are not interested,
@@ -1816,16 +2010,20 @@
     png_free_text(png_ptr, info_ptr, num)
     num          - number of text item to be freed (-1 for all items)
 
+    png_free_hIST(png_ptr, info_ptr)
+
     png_free_iCCP(png_ptr, info_ptr)
 
     png_free_pCAL(png_ptr, info_ptr)
 
     png_free_sCAL(png_ptr, info_ptr)
 
-    png_free_spalette(png_ptr, info_ptr, num)
+    png_free_spalettes(png_ptr, info_ptr, num)
     num          - number of suggested-paletted entry to be freed
                    (-1 for all suggested palettes)
 
+    png_free_pixels(png_ptr, info_ptr)
+
     png_free_unknown_chunk(png_ptr, info_ptr, num)
     num          - number of unknown chunk entry to be freed
                    (-1 for all suggested palettes)
@@ -1834,8 +2032,7 @@
 already been freed, or has not yet been allocated, and will in that
 case do nothing.
 
-You must free any data you allocated for info_ptr, such as comments,
-palette, or histogram, before the call to png_destroy_write_struct();
+If you allocated palette data, you must free it before the call to png_destroy_write_struct();
 
 For a more compact example of writing a PNG image, see the file example.c.
 
@@ -1895,8 +2092,11 @@
 Error handling in libpng is done through png_error() and png_warning().
 Errors handled through png_error() are fatal, meaning that png_error()
 should never return to its caller.  Currently, this is handled via
-setjmp() and longjmp(), but you could change this to do things like
-exit() if you should wish.  On non-fatal errors, png_warning() is called
+setjmp() and longjmp() (unless you have compiled libpng with
+PNG_SETJMP_NOT_SUPPORTED, in which case it is handled via PNG_ABORT()),
+but you could change this to do things like exit() if you should wish.
+
+On non-fatal errors, png_warning() is called
 to print a warning message, and then control returns to the calling code.
 By default png_error() and png_warning() print a message on stderr via
 fprintf() unless the library is compiled with PNG_NO_STDIO defined.  If
@@ -1929,16 +2129,25 @@
 setjmp returns non-zero besides returning itself.  Consult your compiler
 documentation for more details.
 
-If you need to read or write custom chunks, you will need to get deeper
-into the libpng code, as a mechanism has not yet been supplied for user
-callbacks with custom chunks.  First, read the PNG specification, and have
-a first level of understanding of how it works.  Pay particular attention
-to the sections that describe chunk names, and look at how other chunks
-were designed, so you can do things similarly.  Second, check out the
-sections of libpng that read and write chunks.  Try to find a chunk that
-is similar to yours and use it as a template.  More details can be found in the
-comments inside the code.  A way of handling unknown chunks in a generic
-method, potentially via callback functions, would be best.
+Custom chunks
+
+If you need to read or write custom chunks, you may need to get deeper
+into the libpng code.  The library now has mechanisms for storing
+and writing chunks of unknown type; you can even declare callbacks
+for custom chunks.  Hoewver, this may not be good enough if the
+library code itself needs to know about interactions between your
+chunk and existing `intrinsic' chunks.
+
+If you need to write a new intrinsic chunk, first read the PNG
+specification. Acquire a first level of
+understanding of how it works.  Pay particular attention to the
+sections that describe chunk names, and look at how other chunks were
+designed, so you can do things similarly.  Second, check out the
+sections of libpng that read and write chunks.  Try to find a chunk
+that is similar to yours and use it as a template.  More details can
+be found in the comments inside the code.  It is best to handle unknown
+chunks in a generic method, via callback functions, instead of by
+modifying libpng functions.
 
 If you wish to write your own transformation for the data, look through
 the part of the code that does the transformations, and check out some of
@@ -1946,7 +2155,7 @@
 transformation to the one you want to add and copy off of it.  More details
 can be found in the comments inside the code itself.
 
-Configuring for 16 bit platforms:
+Configuring for 16 bit platforms
 
 You may need to change the png_large_malloc() and png_large_free()
 routines in pngmem.c, as these are required to allocate 64K, although
@@ -1955,13 +2164,13 @@
 it cannot allocate more then 64K at a time.  Even if you can, the memory
 won't be accessible.  So limit zlib and libpng to 64K by defining MAXSEG_64K.
 
-Configuring for DOS:
+Configuring for DOS
 
 For DOS users who only have access to the lower 640K, you will
 have to limit zlib's memory usage via a png_set_compression_mem_level()
 call.  See zlib.h or zconf.h in the zlib library for more information.
 
-Configuring for Medium Model:
+Configuring for Medium Model
 
 Libpng's support for medium model has been tested on most of the popular
 compilers.  Make sure MAXSEG_64K gets defined, USE_FAR_KEYWORD gets
@@ -1969,7 +2178,7 @@
 all set.  Everything in the library (except for zlib's structure) is
 expecting far data.  You must use the typedefs with the p or pp on
 the end for pointers (or at least look at them and be careful).  Make
-note that the row's of data are defined as png_bytepp, which is an
+note that the rows of data are defined as png_bytepp, which is an
 unsigned char far * far *.
 
 Configuring for gui/windowing platforms:
@@ -2021,7 +2230,7 @@
         window_bits);
     png_set_compression_method(png_ptr, method);
 
-Controlling row filtering:
+Controlling row filtering
 
 If you want to control whether libpng uses filtering or not, which
 filters are used, and how it goes about picking row filters, you
@@ -2087,7 +2296,7 @@
 are given only to help explain the function usage.  Little testing has
 been done to find optimum values for either the costs or the weights.
 
-Removing unwanted object code:
+Removing unwanted object code
 
 There are a bunch of #define's in pngconf.h that control what parts of
 libpng are compiled.  All the defines end in _SUPPORTED.  If you are
@@ -2125,7 +2334,7 @@
 The size of the library itself should not be an issue, because only
 those sections that are actually used will be loaded into memory.
 
-Requesting debug printout:
+Requesting debug printout
 
 The macro definition PNG_DEBUG can be used to request debugging
 printout.  Set it to an integer value in the range 0 to 3.  Higher
@@ -2197,13 +2406,13 @@
 
 VII. Y2K Compliance in libpng
 
-December 10, 1999
+February 5, 2000
 
 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.0.5h are Y2K compliant.  It is my belief that earlier
+upward through 1.0.5q 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
diff --git a/libpngpf.3 b/libpngpf.3
index cdea799..f1ed3c1 100644
--- a/libpngpf.3
+++ b/libpngpf.3
@@ -1,6 +1,6 @@
-.TH LIBPNGPF 3 December 10, 1999
+.TH LIBPNGPF 3 February 5, 2000
 .SH NAME
-libpng \- Portable Network Graphics (PNG) Reference Library 1.0.5h
+libpng \- Portable Network Graphics (PNG) Reference Library 1.0.5q
 (private functions)
 .SH SYNOPSIS
 \fB#include <png.h>\fP
@@ -187,6 +187,10 @@
 
 \fI\fB
 
+\fBint png_handle_as_unknown (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIchunk_name\fP\fB);\fP
+
+\fI\fB
+
 \fBvoid png_handle_bKGD (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
 
 \fI\fB
@@ -505,9 +509,7 @@
 
 \fI\fB
 
-\fBvoid png_write_sPLT (png_structp \fP\fIpng_ptr\fP\fB, \fIpng_spalette_p
-
-\fI\fBpalette\fP\fB);\fP
+\fBvoid png_write_sPLT (png_structp \fP\fIpng_ptr\fP\fB, png_spalette_p \fIpalette\fP\fB);\fP
 
 \fI\fB
 
diff --git a/png.5 b/png.5
index c911a3d..0932db8 100644
--- a/png.5
+++ b/png.5
@@ -1,4 +1,4 @@
-.TH PNG 5 "December 10, 1999"
+.TH PNG 5 "February 5, 2000"
 .SH NAME
 png \- Portable Network Graphics (PNG) format
 .SH DESCRIPTION
@@ -20,7 +20,7 @@
 .SH "SEE ALSO"
 .IR libpng(3), zlib(3), deflate(5), and zlib(5)
 .LP
-PNG 1.1 specification, January 1999:
+PNG 1.2 specification, July 1999:
 .IP
 .br
 http://www.cdrom.com/pub/png
diff --git a/png.c b/png.c
index 4e4b13e..f062252 100644
--- a/png.c
+++ b/png.c
@@ -1,15 +1,16 @@
 
 /* png.c - location for general purpose libpng functions
  *
- * libpng version 1.0.5h - December 10, 1999
+ * libpng version 1.0.5q - February 5, 2000
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
+ * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson
  *
  */
 
 #define PNG_INTERNAL
 #define PNG_NO_EXTERN
+#include <assert.h>
 #include "png.h"
 
 /* Version information for C files.  This had better match the version
@@ -18,7 +19,7 @@
 
 #ifdef PNG_USE_GLOBAL_ARRAYS
 /* png_libpng_ver was changed to a function in version 1.0.5c */
-char png_libpng_ver[12] = "1.0.5h";
+char png_libpng_ver[12] = "1.0.5q";
 
 /* png_sig was changed to a function in version 1.0.5c */
 /* Place to hold the signature string for a PNG file. */
@@ -263,27 +264,43 @@
 void
 png_free_text(png_structp png_ptr, png_infop info_ptr, int num)
 {
-    if (num != -1)
-    {
-    if (info_ptr->text[num].key)
-    {
-        png_free(png_ptr, info_ptr->text[num].key);
-        info_ptr->text[num].key = NULL;
-    }
-    if (info_ptr->text[num].lang)
-    {
-        png_free(png_ptr, info_ptr->text[num].lang);
-        info_ptr->text[num].lang = NULL;
-    }
-    }
-    else if (info_ptr->text != NULL)
-    {
-    int i;
-    for (i = 0; i < info_ptr->num_text; i++)
-        png_free_text(png_ptr, info_ptr, i);
-    png_free(png_ptr, info_ptr->text);
-    info_ptr->text = NULL;
-    }
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+   if (num != -1)
+   {
+     if (info_ptr->text[num].key)
+     {
+         png_free(png_ptr, info_ptr->text[num].key);
+         info_ptr->text[num].key = NULL;
+     }
+   }
+   else if (info_ptr->text != NULL)
+   {
+     int i;
+     if(info_ptr->text != NULL)
+     {
+       for (i = 0; i < info_ptr->num_text; i++)
+           png_free_text(png_ptr, info_ptr, i);
+       png_free(png_ptr, info_ptr->text);
+       info_ptr->text = NULL;
+     }
+     info_ptr->num_text=0;
+   }
+}
+#endif
+
+#if defined(PNG_tRNS_SUPPORTED)
+/* free any tRNS entry */
+void
+png_free_tRNS(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr == NULL || info_ptr == NULL)
+       return;
+   if (info_ptr->valid & PNG_INFO_tRNS)
+   {
+       png_free(png_ptr, info_ptr->trans);
+       info_ptr->valid &= ~PNG_INFO_tRNS;
+   }
 }
 #endif
 
@@ -292,14 +309,18 @@
 void
 png_free_sCAL(png_structp png_ptr, png_infop info_ptr)
 {
+   if (png_ptr == NULL || info_ptr == NULL)
+       return;
    if (info_ptr->valid & PNG_INFO_sCAL)
    {
-       png_free(png_ptr, info_ptr->scal_unit);
-#ifdef PNG_FIXED_POINT_SUPPORTED
+#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
        png_free(png_ptr, info_ptr->scal_s_width);
        png_free(png_ptr, info_ptr->scal_s_height);
+#else
+       if(png_ptr != NULL)
+          /* silence a compiler warning */ ;
 #endif
-       info_ptr->valid &= ~PNG_INFO_sCAL;
+          info_ptr->valid &= ~PNG_INFO_sCAL;
    }
 }
 #endif
@@ -309,6 +330,8 @@
 void
 png_free_pCAL(png_structp png_ptr, png_infop info_ptr)
 {
+   if (png_ptr == NULL || info_ptr == NULL)
+       return;
    if (info_ptr->valid & PNG_INFO_pCAL)
    {
        png_free(png_ptr, info_ptr->pcal_purpose);
@@ -317,9 +340,9 @@
        {
            int i;
            for (i = 0; i < (int)info_ptr->pcal_nparams; i++)
-           {
-               png_free(png_ptr, info_ptr->pcal_params[i]);
-           }
+             {
+             png_free(png_ptr, info_ptr->pcal_params[i]);
+             }
            png_free(png_ptr, info_ptr->pcal_params);
        }
        info_ptr->valid &= ~PNG_INFO_pCAL;
@@ -328,10 +351,12 @@
 #endif
 
 #if defined(PNG_iCCP_SUPPORTED)
-/* free any pCAL entry */
+/* free any iCCP entry */
 void
 png_free_iCCP(png_structp png_ptr, png_infop info_ptr)
 {
+   if (png_ptr == NULL || info_ptr == NULL)
+       return;
    if (info_ptr->valid & PNG_INFO_iCCP)
    {
        png_free(png_ptr, info_ptr->iccp_name);
@@ -344,19 +369,25 @@
 #if defined(PNG_sPLT_SUPPORTED)
 /* free a given sPLT entry, or (if num == -1) all sPLT entries */
 void
-png_free_spalette(png_structp png_ptr, png_infop info_ptr, int num)
+png_free_spalettes(png_structp png_ptr, png_infop info_ptr, int num)
 {
+   if (png_ptr == NULL || info_ptr == NULL)
+       return;
    if (num != -1)
    {
        png_free(png_ptr, info_ptr->splt_palettes[num].name);
        png_free(png_ptr, info_ptr->splt_palettes[num].entries);
+       info_ptr->valid &= ~PNG_INFO_sPLT;
    }
    else
    {
-       png_uint_32 i;
+       int i;
 
-       for (i = 0; i < info_ptr->splt_palettes_num; i++)
-          png_free_spalette(png_ptr, info_ptr, num);
+       if(info_ptr->splt_palettes_num == 0)
+          return;
+
+       for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
+          png_free_spalettes(png_ptr, info_ptr, i);
 
        png_free(png_ptr, info_ptr->splt_palettes);
        info_ptr->splt_palettes_num = 0;
@@ -366,8 +397,10 @@
 
 #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
 void
-png_free_unknown_chunk(png_structp png_ptr, png_infop info_ptr, int num)
+png_free_unknown_chunks(png_structp png_ptr, png_infop info_ptr, int num)
 {
+   if (png_ptr == NULL || info_ptr == NULL)
+       return;
    if (num != -1)
    {
        png_free(png_ptr, info_ptr->unknown_chunks[num].data);
@@ -375,15 +408,78 @@
    }
    else
    {
-       png_uint_32 i;
+       int i;
 
-       for (i = 0; i < info_ptr->unknown_chunks_num; i++)
-          png_free_unknown_chunk(png_ptr, info_ptr, num);
+       if(info_ptr->unknown_chunks_num == 0)
+          return;
+
+       for (i = 0; i < (int)info_ptr->unknown_chunks_num; i++)
+          png_free_unknown_chunks(png_ptr, info_ptr, i);
 
        png_free(png_ptr, info_ptr->unknown_chunks);
        info_ptr->unknown_chunks_num = 0;
    }
 }
+void
+png_free_chunk_list(png_structp png_ptr)
+{
+   if (png_ptr == NULL)
+       return;
+   if (png_ptr->num_chunk_list)
+   {
+       png_free(png_ptr, png_ptr->chunk_list);
+       png_ptr->num_chunk_list=0;
+   }
+}
+#endif
+
+#if defined(PNG_hIST_SUPPORTED)
+/* free any hIST entry */
+void
+png_free_hIST(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr == NULL || info_ptr == NULL)
+       return;
+   if (info_ptr->valid & PNG_INFO_hIST)
+   {
+       png_free(png_ptr, info_ptr->hist);
+       info_ptr->valid &= ~PNG_INFO_hIST;
+   }
+}
+#endif
+
+/* free any PLTE entry that was internally allocated */
+void
+png_free_PLTE(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr == NULL || info_ptr == NULL)
+       return;
+   if (info_ptr->valid & PNG_INFO_PLTE)
+   {
+       if (info_ptr->valid & PNG_ALLOCATED_INFO_PLTE)
+          png_zfree(png_ptr, info_ptr->palette);
+       info_ptr->valid &= ~(PNG_INFO_PLTE|PNG_ALLOCATED_INFO_PLTE);
+       info_ptr->num_palette = 0;
+   }
+}
+
+#if defined(PNG_INFO_IMAGE_SUPPORTED)
+/* free any image bits attached to the info structure */
+void
+png_free_pixels(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr == NULL || info_ptr == NULL)
+       return;
+   if (info_ptr->valid & PNG_INFO_IDAT)
+   {
+       int row;
+
+       for (row = 0; row < (int)info_ptr->height; row++)
+          png_free(png_ptr, info_ptr->row_pointers[row]);
+       png_free(png_ptr, info_ptr->row_pointers);
+       info_ptr->valid &= ~PNG_INFO_IDAT;
+   }
+}
 #endif
 
 /* This is an internal routine to free any memory that the info struct is
@@ -397,6 +493,9 @@
 #if defined(PNG_READ_TEXT_SUPPORTED)
    png_free_text(png_ptr, info_ptr, -1);
 #endif
+#if defined(PNG_READ_tRNS_SUPPORTED)
+   png_free_tRNS(png_ptr, info_ptr);
+#endif
 #if defined(PNG_READ_sCAL_SUPPORTED)
    png_free_sCAL(png_ptr, info_ptr);
 #endif
@@ -407,10 +506,18 @@
    png_free_iCCP(png_ptr, info_ptr);
 #endif
 #if defined(PNG_READ_sPLT_SUPPORTED)
-   png_free_spalette(png_ptr, info_ptr, -1);
+   png_free_spalettes(png_ptr, info_ptr, -1);
 #endif
 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
-   png_free_unknown_chunk(png_ptr, info_ptr, -1);
+   png_free_unknown_chunks(png_ptr, info_ptr, -1);
+   png_free_chunk_list(png_ptr);
+#endif
+#if defined(PNG_hIST_SUPPORTED)
+   png_free_hIST(png_ptr, info_ptr);
+#endif
+   png_free_PLTE(png_ptr, info_ptr);
+#if defined(PNG_INFO_IMAGE_SUPPORTED)
+   png_free_pixels(png_ptr, info_ptr);
 #endif
    png_info_init(info_ptr);
 }
@@ -489,10 +596,10 @@
 png_get_copyright(png_structp png_ptr)
 {
    if (png_ptr != NULL || png_ptr == NULL)  /* silence compiler warning */
-   return ("\n libpng version 1.0.5h - December 10, 1999\n\
+   return ("\n libpng version 1.0.5q - February 5, 2000\n\
    Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.\n\
    Copyright (c) 1996, 1997 Andreas Dilger\n\
-   Copyright (c) 1998, 1999 Glenn Randers-Pehrson\n");
+   Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson\n");
    return ("");
 }
 
@@ -507,8 +614,8 @@
 {
    /* Version of *.c files used when building libpng */
    if(png_ptr != NULL) /* silence compiler warning about unused png_ptr */
-      return("1.0.5h");
-   return("1.0.5h");
+      return("1.0.5q");
+   return("1.0.5q");
 }
 
 png_charp
@@ -532,8 +639,25 @@
 /* Generate a compiler error if there is an old png.h in the search path. */
 void
 png_check_version
-   (version_1_0_5h png_h_is_not_version_1_0_5h)
+   (version_1_0_5q png_h_is_not_version_1_0_5q)
 {
-   if(png_h_is_not_version_1_0_5h == NULL)
+   if(png_h_is_not_version_1_0_5q == NULL)
      return;
 }
+
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+int
+png_handle_as_unknown(png_structp png_ptr, png_bytep chunk_name)
+{
+   /* check chunk_name and return "keep" value if it's on the list, else 0 */
+   int i;
+   png_bytep p;
+   if((png_ptr == NULL && chunk_name == NULL) || png_ptr->num_chunk_list<=0)
+      return 0;
+   p=png_ptr->chunk_list+png_ptr->num_chunk_list*5-5;
+   for (i = png_ptr->num_chunk_list; i; i--, p-=5)
+      if (!png_memcmp(chunk_name, p, 4))
+        return ((int)*(p+4));
+   return 0;
+}
+#endif
diff --git a/png.h b/png.h
index 1757add..a6d58ba 100644
--- a/png.h
+++ b/png.h
@@ -1,27 +1,27 @@
 
 /* png.h - header file for PNG reference library
  *
- * libpng version 1.0.5h - December 10, 1999
+ * libpng version 1.0.5q - February 5, 2000
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
+ * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson
  *
  * Authors and maintainers:
  *  libpng versions 0.71, May 1995, through 0.89c, May 1996: Guy Schalnat
  *  libpng versions 0.90, December 1996, through 0.96, May 1997: Andreas Dilger
- *  libpng versions 0.97, January 1998, through 1.0.5h - December 10, 1999: Glenn
+ *  libpng versions 0.97, January 1998, through 1.0.5q - February 5, 2000: Glenn
  *  See also "Contributing Authors", below.
  *
  * Y2K compliance in libpng:
  * =========================
  *
- *    December 10, 1999
+ *    February 5, 2000
  *
  *    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.0.5h are Y2K compliant.  It is my belief that earlier
+ *    upward through 1.0.5q 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
@@ -98,8 +98,8 @@
  *    1.0.4a-f                 1.0.4a-f 10005  2.1.0.4a-f
  *    1.0.5                    1.0.5    10005  2.1.0.5
  *    1.0.5a-d                 1.0.5a-d 10006  2.1.0.5a-d
- *    1.0.5e-h                 1.0.5e-h 10100  2.1.0.5e-h
- *    1.1.0                    1.1.0    10100  3.1.0.0
+ *    1.0.5e-p                 1.0.5e-p 10100  2.1.0.5e-p
+ *    1.1.0                    1.1.0    10100  3.1.1.0
  *
  *    Henceforth the source version will match the shared-library minor
  *    and patch numbers; the shared-library major version number will be
@@ -122,8 +122,8 @@
  * (libpng versions 0.5, May 1995, through 0.89c, May 1996)
  * Copyright (c) 1996, 1997 Andreas Dilger
  * (libpng versions 0.90, December 1996, through 0.96, May 1997)
- * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
- * (libpng versions 0.97, January 1998, through 1.0.5h, December 10, 1999)
+ * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson
+ * (libpng versions 0.97, January 1998, through 1.0.5q, February 5, 2000)
  *
  * For the purposes of this copyright and license, "Contributing Authors"
  * is defined as the following set of individuals:
@@ -224,7 +224,7 @@
  */
 
 /* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.0.5h"
+#define PNG_LIBPNG_VER_STRING "1.0.5q"
 
 /* Careful here.  At one time, Guy wanted to use 082, but that would be octal.
  * We must not include leading zeros.
@@ -324,18 +324,23 @@
 typedef png_spalette FAR * FAR * png_spalette_pp;
 
 #ifdef PNG_TEXT_SUPPORTED
-/* png_text holds the contents of a text chunk in a PNG file, and whether
- * that contents is compressed or not.  The "keyword" field points to a
- * regular C string.  */
+/* png_text holds the contents of a text/ztxt/itxt chunk in a PNG file,
+ * and whether that contents is compressed or not.  The "key" field
+ * points to a regular C string.  */
 typedef struct png_text_struct
 {
-   int compression;        /* compression value, see PNG_TEXT_COMPRESSION_ */
+   int  compression; /* compression value:
+                       -1: tEXt, none
+                        0: zTXt, deflate
+                        1: iTXt, none
+                        2: iTXt, deflate  */
    png_charp key;          /* keyword, 1-79 character description of "text" */
-   png_charp lang;         /* language code, 1-79 characters */
-   png_charp translated_key; /* translated keyword, 1-79 characters */
    png_charp text;         /* comment, may be an empty string (ie "") */
-   /* text_length is no longer used, and now present for compatibility only */
-   png_size_t text_length; /* length of "text" field (not used any more) */
+   png_size_t text_length; /* length of the text string */
+   png_size_t itxt_length; /* length of the itxt string */
+   png_charp lang;         /* language code, 1-79 characters */
+   png_charp lang_key;     /* keyword translated UTF-8 string, 0 or more
+                              chars */
 } png_text;
 typedef png_text FAR * png_textp;
 typedef png_text FAR * FAR * png_textpp;
@@ -347,7 +352,9 @@
 #define PNG_TEXT_COMPRESSION_zTXt_WR -2
 #define PNG_TEXT_COMPRESSION_NONE    -1
 #define PNG_TEXT_COMPRESSION_zTXt     0
-#define PNG_TEXT_COMPRESSION_LAST     1  /* Not a valid value */
+#define PNG_ITXT_COMPRESSION_NONE     1
+#define PNG_ITXT_COMPRESSION_zTXt     2
+#define PNG_TEXT_COMPRESSION_LAST     3  /* Not a valid value */
 
 /* png_time is a way to hold the time in an machine independent way.
  * Two conversions are provided, both from time_t and struct tm.  There
@@ -379,8 +386,7 @@
     png_byte *data;
     png_size_t size;
 
-    /* libpng-using applications should NOT modify this byte.  Applications
-       that are inserting a new unknown chunk can set it to 0. */
+    /* libpng-using applications should NOT directly modify this byte. */
     png_byte location; /* mode of operation at read time */
 }
 png_unknown_chunk;
@@ -410,11 +416,10 @@
  * that use the old direct-access method with png_info_struct.
  *
  * The following members may have allocated storage attached that should be
- * cleaned up before the structure is discarded: palette, text, pcal_purpose,
- * pcal_units, pcal_params, iccp_name, iccp_profile, splt_palettes, and
- * scal_unit.  Of these, the text, pcal_*, iccp_*, splt_*, and scal_unit
- * members are automatically freed when the info structure is deallocated.
- * The palette member is not.
+ * cleaned up before the structure is discarded: palette, trans, text,
+ * pcal_purpose, pcal_units, pcal_params, hist, iccp_name, iccp_profile,
+ * splt_palettes, scal_unit, and row_pointers.   These are automatically
+ * freed when the info structure is deallocated.
  *
  * More allocation details: all the chunk-reading functions that change these
  * members go through the corresponding png_set_* functions.  Functions to
@@ -460,9 +465,7 @@
 #ifdef PNG_FLOATING_POINT_SUPPORTED
    float gamma; /* gamma value of image, if (valid & PNG_INFO_gAMA) */
 #endif
-#ifdef PNG_FIXED_POINT_SUPPORTED
-   png_uint_32 int_gamma; /* gamma value of image, if (valid & PNG_INFO_gAMA) */
-#endif
+   png_fixed_point int_gamma; /* gamma value of image, if (valid & PNG_INFO_gAMA) */
 #endif
 
 #if defined(PNG_sRGB_SUPPORTED)
@@ -483,6 +486,9 @@
    int num_text; /* number of comments read/to write */
    int max_text; /* current size of text array */
    png_textp text; /* array of comments read/to write */
+   int num_text_old; /* number of comments read/to write */
+   png_textp text_old; /* array of comments read/to write, backward
+                          compatible  with libpng-1.0.5 and earlier */
 #endif /* PNG_TEXT_SUPPORTED */
 
 #if defined(PNG_tIME_SUPPORTED)
@@ -576,14 +582,14 @@
    float y_blue;
 #endif
 #ifdef PNG_FIXED_POINT_SUPPORTED
-   png_uint_32 int_x_white;
-   png_uint_32 int_y_white;
-   png_uint_32 int_x_red;
-   png_uint_32 int_y_red;
-   png_uint_32 int_x_green;
-   png_uint_32 int_y_green;
-   png_uint_32 int_x_blue;
-   png_uint_32 int_y_blue;
+   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
 
@@ -626,17 +632,20 @@
 #if defined(PNG_sCAL_SUPPORTED)
    /* The sCAL chunk describes the actual physical dimensions of the
     * subject matter of the graphic.  The chunk contains a unit specification
-    * (an ASCII string), and two ASCII strings representing floating-point
+    * 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.
     */
-   png_charp scal_unit;        /* unit of physical scale */
-   png_charp scal_s_width;     /* string containing height */
-   png_charp scal_s_height;    /* string containing width */
+   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 */
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   png_charp scal_s_width;     /* string containing height */
+   png_charp scal_s_height;    /* string containing width */
+#endif
 #endif
 #endif
 
@@ -645,6 +654,11 @@
    png_unknown_chunkp unknown_chunks;
    png_size_t unknown_chunks_num;
 #endif
+
+#if defined(PNG_INFO_IMAGE_SUPPORTED)
+   /* Data valid if (valid & PNG_INFO_IDAT) non-zero */
+   png_bytepp row_pointers;        /* the image bits */
+#endif
 } png_info;
 
 typedef png_info FAR * png_infop;
@@ -691,6 +705,12 @@
 #define PNG_EQUATION_HYPERBOLIC   3 /* Hyperbolic sine transformation */
 #define PNG_EQUATION_LAST         4 /* Not a valid value */
 
+/* These are for the sCAL chunk.  These values should NOT be changed. */
+#define PNG_SCALE_UNKNOWN         0 /* unknown unit (image scale) */
+#define PNG_SCALE_METER           1 /* meters per pixel */
+#define PNG_SCALE_RADIAN          2 /* radians per pixel */
+#define PNG_SCALE_LAST            3 /* Not a valid value */
+
 /* These are for the pHYs chunk.  These values should NOT be changed. */
 #define PNG_RESOLUTION_UNKNOWN    0 /* pixels/unknown unit (aspect ratio) */
 #define PNG_RESOLUTION_METER      1 /* pixels/meter */
@@ -727,6 +747,8 @@
 #define PNG_INFO_iCCP 0x1000   /* ESR, 1.0.6 */
 #define PNG_INFO_sPLT 0x2000   /* ESR, 1.0.6 */
 #define PNG_INFO_sCAL 0x4000   /* ESR, 1.0.6 */
+#define PNG_INFO_IDAT 0x8000   /* ESR, 1.0.6 */
+#define PNG_ALLOCATED_INFO_PLTE  0x10000L  /* GR-P, 1.0.6 */
 
 /* This is used for the transformation routines, as some of them
  * change these values for the row.  It also should enable using
@@ -773,6 +795,28 @@
     png_row_infop, png_bytep));
 #endif
 
+#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
+typedef int (*png_user_chunk_ptr) PNGARG((png_structp, png_unknown_chunkp));
+#endif
+#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
+typedef void (*png_unknown_chunk_ptr) PNGARG((png_structp));
+#endif
+
+/* Transform masks for the high-level interface */
+#define PNG_TRANSFORM_IDENTITY        0x0000    /* read and write */
+#define PNG_TRANSFORM_STRIP_16        0x0001  /* read only */
+#define PNG_TRANSFORM_STRIP_ALPHA    0x0002    /* read only */
+#define PNG_TRANSFORM_PACKING        0x0004    /* read and write */
+#define PNG_TRANSFORM_PACKSWAP        0x0008    /* read and write */
+#define PNG_TRANSFORM_EXPAND        0x0010    /* read only */
+#define PNG_TRANSFORM_INVERT_MONO    0x0020    /* read and write */
+#define PNG_TRANSFORM_SHIFT        0x0040    /* read and write */
+#define PNG_TRANSFORM_BGR        0x0080    /* read and write */
+#define PNG_TRANSFORM_SWAP_ALPHA    0x0100    /* read and write */
+#define PNG_TRANSFORM_SWAP_ENDIAN    0x0200    /* read and write */
+#define PNG_TRANSFORM_INVERT_ALPHA    0x0200    /* read and write */
+#define PNG_TRANSFORM_STRIP_FILLER    0x0800    /* WRITE only */
+
 typedef png_voidp (*png_malloc_ptr) PNGARG((png_structp, png_size_t));
 typedef void (*png_free_ptr) PNGARG((png_structp, png_voidp));
 
@@ -785,8 +829,9 @@
 
 struct png_struct_def
 {
+#ifdef PNG_SETJMP_SUPPORTED
    jmp_buf jmpbuf;            /* used in png_error */
-
+#endif
    png_error_ptr error_fn;    /* function for printing errors and aborting */
    png_error_ptr warning_fn;  /* function for printing warnings */
    png_voidp error_ptr;       /* user supplied struct for error functions */
@@ -809,6 +854,11 @@
    png_byte user_transform_channels; /* channels in user transformed pixels */
 #endif
 
+#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
+   png_voidp user_chunk_ptr;
+   png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */
+#endif
+
    png_uint_32 mode;          /* tells us where we are in the PNG file */
    png_uint_32 flags;         /* flags indicating various things to libpng */
    png_uint_32 transformations; /* which transformations to perform */
@@ -884,9 +934,7 @@
    float gamma;          /* file gamma value */
    float screen_gamma;   /* screen gamma value (display_exponent) */
 #endif
-#ifdef PNG_FIXED_POINT_SUPPORTED
-   png_uint_32 int_gamma;
-#endif
+   png_fixed_point int_gamma;
 #endif
 
 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
@@ -989,19 +1037,24 @@
     defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED)
    png_byte empty_plte_permitted;
 #endif
+
+#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+   int num_chunk_list;
+   png_bytep chunk_list;
+#endif
 };
 
 /* This prevents a compiler error in png_get_copyright() in png.c if png.c
-and png.h are both at * version 1.0.5h
+and png.h are both at * version 1.0.5q
  */
-typedef png_structp version_1_0_5h;
+typedef png_structp version_1_0_5q;
 
 typedef png_struct FAR * FAR * png_structpp;
 
 /* Here are the function definitions most commonly used.  This is not
  * the place to find out how to use libpng.  See libpng.txt for the
  * full explanation, see example.c for the summary.  This just provides
- * a simple one line of the use of each function.
+ * a simple one line description of the use of each function.
  */
 
 /* Tell lib we have already handled the first <num_bytes> magic bytes.
@@ -1487,6 +1540,13 @@
    PNGARG((png_structp png_ptr));
 #endif
 
+#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
+extern PNG_EXPORT(void,png_set_read_user_chunk_fn) PNGARG((png_structp png_ptr,
+   png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn));
+extern PNG_EXPORT(png_voidp,png_get_user_chunk_ptr) PNGARG((png_structp
+   png_ptr));
+#endif
+
 #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
 /* Sets the function callbacks for the push reader, and a pointer to a
  * user-defined structure available to the callback functions.
@@ -1653,10 +1713,10 @@
 #endif
 #ifdef PNG_FIXED_POINT_SUPPORTED
 extern PNG_EXPORT(png_uint_32,png_get_cHRM_fixed) PNGARG((png_structp png_ptr,
-   png_infop info_ptr, png_uint_32 *int_white_x, png_uint_32 *int_white_y,
-   png_uint_32 *int_red_x, png_uint_32 *int_red_y, png_uint_32 *int_green_x,
-   png_uint_32 *int_green_y, png_uint_32 *int_blue_x,
-   png_uint_32 *int_blue_y));
+   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));
 #endif
 #endif
 
@@ -1668,9 +1728,10 @@
 #endif
 #ifdef PNG_FIXED_POINT_SUPPORTED
 extern PNG_EXPORT(void,png_set_cHRM_fixed) PNGARG((png_structp png_ptr,
-   png_infop info_ptr, png_uint_32 int_white_x, png_uint_32 int_white_y,
-   png_uint_32 int_red_x, png_uint_32 int_red_y, png_uint_32 int_green_x,
-   png_uint_32 int_green_y, png_uint_32 int_blue_x, png_uint_32 int_blue_y));
+   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));
 #endif
 #endif
 
@@ -1679,10 +1740,8 @@
 extern PNG_EXPORT(png_uint_32,png_get_gAMA) PNGARG((png_structp png_ptr,
    png_infop info_ptr, double *file_gamma));
 #endif
-#ifdef PNG_FIXED_POINT_SUPPORTED
 extern PNG_EXPORT(png_uint_32,png_get_gAMA_fixed) PNGARG((png_structp png_ptr,
-   png_infop info_ptr, png_uint_32 *int_file_gamma));
-#endif
+   png_infop info_ptr, png_fixed_point *int_file_gamma));
 #endif
 
 #if defined(PNG_gAMA_SUPPORTED)
@@ -1690,10 +1749,8 @@
 extern PNG_EXPORT(void,png_set_gAMA) PNGARG((png_structp png_ptr,
    png_infop info_ptr, double file_gamma));
 #endif
-#ifdef PNG_FIXED_POINT_SUPPORTED
 extern PNG_EXPORT(void,png_set_gAMA_fixed) PNGARG((png_structp png_ptr,
-   png_infop info_ptr, png_uint_32 int_file_gamma));
-#endif
+   png_infop info_ptr, png_fixed_point int_file_gamma));
 #endif
 
 #if defined(PNG_READ_hIST_SUPPORTED)
@@ -1785,13 +1842,13 @@
 #if defined(PNG_READ_iCCP_SUPPORTED)
 extern PNG_EXPORT(png_uint_32,png_get_iCCP) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_charpp name, int *compression_type,
-   png_charpp profile, png_int_32 *proflen));
+   png_charpp profile, png_uint_32 *proflen));
 #endif
 
 #if defined(PNG_iCCP_SUPPORTED)
 extern PNG_EXPORT(void,png_set_iCCP) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_charp name, int compression_type,
-   png_charp profile, int proflen));
+   png_charp profile, png_uint_32 proflen));
 extern PNG_EXPORT(void,png_free_iCCP) PNGARG((png_structp png_ptr,
    png_infop info_ptr));
 #endif
@@ -1804,11 +1861,23 @@
 #if defined(PNG_sPLT_SUPPORTED)
 extern PNG_EXPORT(void,png_set_spalettes) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_spalette_p entries, int nentries));
-extern PNG_EXPORT(void,png_free_spalette) PNGARG((png_structp png_ptr,
+extern PNG_EXPORT(void,png_free_spalettes) PNGARG((png_structp png_ptr,
    png_infop info_ptr, int num));
 #endif
 
+#if defined(PNG_READ_iTXt_SUPPORTED)
+/* png_get_itxt also returns the number of text chunks in *num_text */
+extern PNG_EXPORT(png_uint_32,png_get_itxt) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_textp *text_ptr, int *num_text));
+#endif
+
+#if defined(PNG_TEXT_SUPPORTED)
+extern PNG_EXPORT(void,png_set_itxt) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_textp text_ptr, int num_text));
+#endif
+
 #if defined(PNG_READ_TEXT_SUPPORTED)
+/* Old interface; apps should use png_get_itxt instead */
 /* png_get_text also returns the number of text chunks in *num_text */
 extern PNG_EXPORT(png_uint_32,png_get_text) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_textp *text_ptr, int *num_text));
@@ -1818,7 +1887,7 @@
 extern PNG_EXPORT(void,png_set_text) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_textp text_ptr, int num_text));
 extern PNG_EXPORT(void,png_free_text) PNGARG((png_structp png_ptr,
-   png_infop info_ptr, int num_text));
+   png_infop info_ptr, int num_text_old));
 #endif
 
 #if defined(PNG_READ_tIME_SUPPORTED)
@@ -1843,22 +1912,32 @@
    png_color_16p trans_values));
 #endif
 
+#if defined(PNG_tRNS_SUPPORTED)
+extern PNG_EXPORT(void,png_free_tRNS) PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+#endif
+
 #if defined(PNG_READ_sCAL_SUPPORTED)
 #ifdef PNG_FLOATING_POINT_SUPPORTED
 extern PNG_EXPORT(png_uint_32,png_get_sCAL) PNGARG((png_structp png_ptr,
-   png_infop info_ptr, png_charpp unit, double *width, double *height));
-#endif
+   png_infop info_ptr, int *unit, double *width, double *height));
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
 extern PNG_EXPORT(png_uint_32,png_get_sCAL_s) PNGARG((png_structp png_ptr,
-   png_infop info_ptr, png_charpp unit, png_charpp swidth, png_charpp sheight));
+   png_infop info_ptr, int *unit, png_charpp swidth, png_charpp sheight));
+#endif
+#endif
 #endif /* PNG_READ_sCAL_SUPPORTED */
 
-#if defined(PNG_READ_sCAL_SUPPORTED) || defined(PNG_WRITE_sCAL_SUPPORTED)
+#if defined(PNG_sCAL_SUPPORTED)
 #ifdef PNG_FLOATING_POINT_SUPPORTED
 extern PNG_EXPORT(void,png_set_sCAL) PNGARG((png_structp png_ptr,
-   png_infop info_ptr, png_charp unit, double width, double height));
+   png_infop info_ptr, int unit, double width, double height));
 #endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
 extern PNG_EXPORT(void,png_set_sCAL_s) PNGARG((png_structp png_ptr,
-   png_infop info_ptr, png_charp unit, png_charp swidth, png_charp sheight));
+   png_infop info_ptr, int unit, png_charp swidth, png_charp sheight));
+#endif
 #endif /* PNG_READ_sCAL_SUPPORTED || PNG_WRITE_sCAL_SUPPORTED */
 
 #if defined(PNG_READ_sCAL_SUPPORTED) || defined(PNG_WRITE_sCAL_SUPPORTED)
@@ -1867,13 +1946,37 @@
 #endif /* PNG_READ_sCAL_SUPPORTED || PNG_WRITE_sCAL_SUPPORTED */
 
 #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
-extern PNG_EXPORT(void, png_set_keep_unknown_chunks) PNGARG((png_structp png_ptr));
+/* provide a list of chunks and how they are to be handled, if the built-in
+   handling or default unknown chunk handling is not desired.  Any chunks not
+   listed will be handled in the default manner.  The IHDR and IEND chunks
+   must not be listed.
+      keep = 0: follow default behavour
+           = 1: do not keep
+           = 2: keep only if safe-to-copy
+           = 3: keep even if unsafe-to-copy
+*/
+extern PNG_EXPORT(void, png_set_keep_unknown_chunks) PNGARG((png_structp
+   png_ptr, int keep, png_bytep chunk_list, int num_chunks));
 extern PNG_EXPORT(void, png_set_unknown_chunks) PNGARG((png_structp png_ptr,
-   png_infop info_ptr, png_unknown_chunkp unknowns, int nunknowns));
-extern PNG_EXPORT(void,png_free_unknown_chunk) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns));
+extern PNG_EXPORT(void,png_free_unknown_chunks) PNGARG((png_structp png_ptr,
    png_infop info_ptr, int num));
-extern PNG_EXPORT(png_uint_32,png_get_unknown_chunks) PNGARG((png_structp png_ptr,
-   png_infop info_ptr, png_unknown_chunkpp entries));
+extern PNG_EXPORT(png_uint_32,png_get_unknown_chunks) PNGARG((png_structp
+   png_ptr, png_infop info_ptr, png_unknown_chunkpp entries));
+extern PNG_EXPORT(void,png_free_chunk_list) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_INFO_IMAGE_SUPPORTED)
+extern PNG_EXPORT(void, png_read_png) PNGARG((png_structp png_ptr,
+                        png_infop info_ptr,
+                        int transforms,
+                        voidp params));
+extern PNG_EXPORT(void, png_write_png) PNGARG((png_structp png_ptr,
+                        png_infop info_ptr,
+                        int transforms,
+                        voidp params));
+extern PNG_EXPORT(void, png_free_pixels) PNGARG((png_structp png_ptr,
+                        png_infop info_ptr));
 #endif
 
 /* Define PNG_DEBUG at compile time for debugging information.  Higher
@@ -1915,7 +2018,8 @@
 extern PNG_EXPORT(png_charp,png_get_header_version) PNGARG((png_structp png_ptr));
 extern PNG_EXPORT(png_charp,png_get_libpng_ver) PNGARG((png_structp png_ptr));
 
-#define PNG_HEADER_VERSION_STRING " libpng version 1.0.5h - December 10, 1999 (header)\n"
+#define PNG_HEADER_VERSION_STRING \
+   " libpng version 1.0.5q - February 5, 2000 (header)\n"
 
 #ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED
 /* With these routines we avoid an integer divide, which will be slower on
@@ -1999,7 +2103,7 @@
 #define PNG_EXPAND             0x1000
 #define PNG_GAMMA              0x2000
 #define PNG_GRAY_TO_RGB        0x4000
-#define PNG_FILLER             0x8000
+#define PNG_FILLER             0x8000L
 #define PNG_PACKSWAP          0x10000L
 #define PNG_SWAP_ALPHA        0x20000L
 #define PNG_STRIP_ALPHA       0x40000L
@@ -2035,8 +2139,14 @@
 #define PNG_FLAG_FREE_PALETTE             0x1000
 #define PNG_FLAG_FREE_TRANS               0x2000
 #define PNG_FLAG_FREE_HIST                0x4000
-#define PNG_FLAG_KEEP_UNKNOWN_CHUNKS      0x8000
+#define PNG_FLAG_KEEP_UNKNOWN_CHUNKS      0x8000L
+#define PNG_FLAG_KEEP_UNSAFE_CHUNKS      0x10000L
 
+/* For use in png_set_keep_unknown, png_handle_as_unknown */
+#define HANDLE_CHUNK_AS_DEFAULT   0
+#define HANDLE_CHUNK_NEVER        1
+#define HANDLE_CHUNK_IF_SAFE      2
+#define HANDLE_CHUNK_ALWAYS       3
 
 #define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \
                                      PNG_FLAG_CRC_ANCILLARY_NOWARN)
@@ -2122,18 +2232,18 @@
  * values, which is almost certainly true.
  */
 #if defined(PNG_READ_BIG_ENDIAN_SUPPORTED)
-#if defined(PNG_READ_pCAL_SUPPORTED)
-#define png_get_int_32(buf) ( *((png_int_32p) (buf)))
-#endif /* PNG_READ_pCAL_SUPPORTED */
-#define png_get_uint_32(buf) ( *((png_uint_32p) (buf)))
-#define png_get_uint_16(buf) ( *((png_uint_16p) (buf)))
+#  if defined(PNG_READ_pCAL_SUPPORTED) || defined(PNG_READ_oFFs_SUPPORTED)
+#    define png_get_int_32(buf) ( *((png_int_32p) (buf)))
+#  endif
+#  define png_get_uint_32(buf) ( *((png_uint_32p) (buf)))
+#  define png_get_uint_16(buf) ( *((png_uint_16p) (buf)))
 #else
-#if defined(PNG_READ_pCAL_SUPPORTED)
+#  if defined(PNG_READ_pCAL_SUPPORTED) || defined(PNG_READ_oFFs_SUPPORTED)
 PNG_EXTERN png_int_32 png_get_int_32 PNGARG((png_bytep buf));
-#endif /* PNG_READ_pCAL_SUPPORTED */
+#  endif
 PNG_EXTERN png_uint_32 png_get_uint_32 PNGARG((png_bytep buf));
 PNG_EXTERN png_uint_16 png_get_uint_16 PNGARG((png_bytep buf));
-#endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */
+#endif /* !PNG_READ_BIG_ENDIAN_SUPPORTED */
 
 /* Initialize png_ptr struct for reading, and allocate any other memory.
  * (old interface - NOT DLL EXPORTED).
@@ -2248,7 +2358,7 @@
 PNG_EXTERN void png_write_gAMA PNGARG((png_structp png_ptr, double file_gamma));
 #endif
 #ifdef PNG_FIXED_POINT_SUPPORTED
-PNG_EXTERN void png_write_gAMA_fixed PNGARG((png_structp png_ptr, png_uint_32
+PNG_EXTERN void png_write_gAMA_fixed PNGARG((png_structp png_ptr, png_fixed_point
     file_gamma));
 #endif
 #endif
@@ -2267,9 +2377,10 @@
 #endif
 #ifdef PNG_FIXED_POINT_SUPPORTED
 PNG_EXTERN void png_write_cHRM_fixed PNGARG((png_structp png_ptr,
-   png_uint_32 int_white_x, png_uint_32 int_white_y,
-   png_uint_32 int_red_x, png_uint_32 int_red_y, png_uint_32 int_green_x,
-   png_uint_32 int_green_y, png_uint_32 int_blue_x, png_uint_32 int_blue_y));
+   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));
 #endif
 #endif
 
@@ -2304,6 +2415,14 @@
    int num_hist));
 #endif
 
+#if defined(PNG_hIST_SUPPORTED)
+extern PNG_EXPORT(void,png_free_hIST) PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+#endif
+
+extern PNG_EXPORT(void,png_free_PLTE) PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+
 #if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \
     defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
 PNG_EXTERN png_size_t png_check_keyword PNGARG((png_structp png_ptr,
@@ -2322,7 +2441,7 @@
 
 #if defined(PNG_WRITE_iTXt_SUPPORTED)
 PNG_EXTERN void png_write_iTXt PNGARG((png_structp png_ptr,
-   int compression, png_charp key, png_charp lang, png_charp translated_key,
+   int compression, png_charp key, png_charp lang, png_charp lang_key,
    png_charp text));
 #endif
 
@@ -2351,10 +2470,13 @@
 #if defined(PNG_WRITE_sCAL_SUPPORTED)
 #ifdef PNG_FLOATING_POINT_SUPPORTED
 PNG_EXTERN void png_write_sCAL PNGARG((png_structp png_ptr,
-   png_charp unit, double width, double height));
-#endif
+   int unit, double width, double height));
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
 PNG_EXTERN void png_write_sCAL_s PNGARG((png_structp png_ptr,
-   png_charp unit, png_charp width, png_charp height));
+   int unit, png_charp width, png_charp height));
+#endif
+#endif
 #endif
 
 /* Called when finished processing a row of data */
@@ -2528,13 +2650,8 @@
 PNG_EXTERN void png_handle_IEND PNGARG((png_structp png_ptr, png_infop info_ptr,
    png_uint_32 length));
 
-#if defined(PNG_READ_gAMA_SUPPORTED)
-PNG_EXTERN void png_handle_gAMA PNGARG((png_structp png_ptr, png_infop info_ptr,
-   png_uint_32 length));
-#endif
-
-#if defined(PNG_READ_sBIT_SUPPORTED)
-PNG_EXTERN void png_handle_sBIT PNGARG((png_structp png_ptr, png_infop info_ptr,
+#if defined(PNG_READ_bKGD_SUPPORTED)
+PNG_EXTERN void png_handle_bKGD PNGARG((png_structp png_ptr, png_infop info_ptr,
    png_uint_32 length));
 #endif
 
@@ -2543,8 +2660,13 @@
    png_uint_32 length));
 #endif
 
-#if defined(PNG_READ_sRGB_SUPPORTED)
-PNG_EXTERN void png_handle_sRGB PNGARG((png_structp png_ptr, png_infop info_ptr,
+#if defined(PNG_READ_gAMA_SUPPORTED)
+PNG_EXTERN void png_handle_gAMA PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 length));
+#endif
+
+#if defined(PNG_READ_hIST_SUPPORTED)
+PNG_EXTERN void png_handle_hIST PNGARG((png_structp png_ptr, png_infop info_ptr,
    png_uint_32 length));
 #endif
 
@@ -2553,23 +2675,8 @@
    png_uint_32 length));
 #endif /* PNG_READ_iCCP_SUPPORTED */
 
-#if defined(PNG_READ_sPLT_SUPPORTED)
-extern void png_handle_sPLT PNGARG((png_structp png_ptr, png_infop info_ptr,
-   png_uint_32 length));
-#endif /* PNG_READ_sPLT_SUPPORTED */
-
-#if defined(PNG_READ_tRNS_SUPPORTED)
-PNG_EXTERN void png_handle_tRNS PNGARG((png_structp png_ptr, png_infop info_ptr,
-   png_uint_32 length));
-#endif
-
-#if defined(PNG_READ_bKGD_SUPPORTED)
-PNG_EXTERN void png_handle_bKGD PNGARG((png_structp png_ptr, png_infop info_ptr,
-   png_uint_32 length));
-#endif
-
-#if defined(PNG_READ_hIST_SUPPORTED)
-PNG_EXTERN void png_handle_hIST PNGARG((png_structp png_ptr, png_infop info_ptr,
+#if defined(PNG_READ_iTXt_SUPPORTED)
+PNG_EXTERN void png_handle_iTXt PNGARG((png_structp png_ptr, png_infop info_ptr,
    png_uint_32 length));
 #endif
 
@@ -2583,18 +2690,28 @@
    png_uint_32 length));
 #endif
 
-#if defined(PNG_READ_sCAL_SUPPORTED)
-PNG_EXTERN void png_handle_sCAL PNGARG((png_structp png_ptr, png_infop info_ptr,
-   png_uint_32 length));
-#endif
-
 #if defined(PNG_READ_pHYs_SUPPORTED)
 PNG_EXTERN void png_handle_pHYs PNGARG((png_structp png_ptr, png_infop info_ptr,
    png_uint_32 length));
 #endif
 
-#if defined(PNG_READ_tIME_SUPPORTED)
-PNG_EXTERN void png_handle_tIME PNGARG((png_structp png_ptr, png_infop info_ptr,
+#if defined(PNG_READ_sBIT_SUPPORTED)
+PNG_EXTERN void png_handle_sBIT PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 length));
+#endif
+
+#if defined(PNG_READ_sCAL_SUPPORTED)
+PNG_EXTERN void png_handle_sCAL PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 length));
+#endif
+
+#if defined(PNG_READ_sPLT_SUPPORTED)
+extern void png_handle_sPLT PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 length));
+#endif /* PNG_READ_sPLT_SUPPORTED */
+
+#if defined(PNG_READ_sRGB_SUPPORTED)
+PNG_EXTERN void png_handle_sRGB PNGARG((png_structp png_ptr, png_infop info_ptr,
    png_uint_32 length));
 #endif
 
@@ -2603,14 +2720,24 @@
    png_uint_32 length));
 #endif
 
+#if defined(PNG_READ_tIME_SUPPORTED)
+PNG_EXTERN void png_handle_tIME PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 length));
+#endif
+
+#if defined(PNG_READ_tRNS_SUPPORTED)
+PNG_EXTERN void png_handle_tRNS PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 length));
+#endif
+
 #if defined(PNG_READ_zTXt_SUPPORTED)
 PNG_EXTERN void png_handle_zTXt PNGARG((png_structp png_ptr, png_infop info_ptr,
    png_uint_32 length));
 #endif
 
-#if defined(PNG_READ_iTXt_SUPPORTED)
-PNG_EXTERN void png_handle_iTXt PNGARG((png_structp png_ptr, png_infop info_ptr,
-   png_uint_32 length));
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+PNG_EXTERN int png_handle_as_unknown PNGARG((png_structp png_ptr, png_bytep
+   chunk_name));
 #endif
 
 PNG_EXTERN void png_handle_unknown PNGARG((png_structp png_ptr,
diff --git a/pngasmrd.h b/pngasmrd.h
index 520dbb3..876f819 100644
--- a/pngasmrd.h
+++ b/pngasmrd.h
@@ -1,8 +1,8 @@
 /* pngasmrd.h - assembler version of utilities to read a PNG file
  *
- * libpng 1.0.5h - December 10, 1999
+ * libpng 1.0.5q - February 5, 2000
  * For conditions of distribution and use, see copyright notice in png.h
- * Copyright (c) 1999 Glenn Randers-Pehrson
+ * Copyright (c) 1999, 2000 Glenn Randers-Pehrson
  *
  */
 
@@ -21,7 +21,7 @@
 /* Set this in the makefile for gcc on Pentium, not in pngconf.h */
 #ifdef PNG_USE_PNGGCCRD
 /* Platform must be Pentium.  Makefile must assemble and load pnggccrd.c
- * (not available in libpng 1.0.5h).
+ * (not available in libpng 1.0.5q).
  * MMX will be detected at run time and used if present.
  */
 #define PNG_HAVE_ASSEMBLER_COMBINE_ROW
diff --git a/pngconf.h b/pngconf.h
index bbfd23a..16e1e77 100644
--- a/pngconf.h
+++ b/pngconf.h
@@ -1,11 +1,11 @@
 
 /* pngconf.h - machine configurable file for libpng
  *
- * libpng 1.0.5h - December 10, 1999
+ * libpng 1.0.5q - February 5, 2000
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
+ * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson
  */
 
 /* Any machine specific code is near the front of this file, so if you
@@ -111,29 +111,35 @@
 #include <sys/types.h>
 #endif
 
+#ifndef PNG_SETJMP_NOT_SUPPORTED
+#  define PNG_SETJMP_SUPPORTED
+#endif
+
+#ifdef PNG_SETJMP_SUPPORTED
 /* This is an attempt to force a single setjmp behaviour on Linux.  If
  * the X config stuff didn't define _BSD_SOURCE we wouldn't need this.
  */
-#ifdef __linux__
-#ifdef _BSD_SOURCE
-#define _PNG_SAVE_BSD_SOURCE
-#undef _BSD_SOURCE
-#endif
-#ifdef _SETJMP_H
-__png.h__ already includes setjmp.h
-__dont__ include it again
-#endif
+#  ifdef __linux__
+#    ifdef _BSD_SOURCE
+#      define _PNG_SAVE_BSD_SOURCE
+#      undef _BSD_SOURCE
+#    endif
+#    ifdef _SETJMP_H
+      __png.h__ already includes setjmp.h
+      __dont__ include it again
+#    endif
 #endif /* __linux__ */
 
 /* include setjmp.h for error handling */
 #include <setjmp.h>
 
-#ifdef __linux__
-#ifdef _PNG_SAVE_BSD_SOURCE
-#define _BSD_SOURCE
-#undef _PNG_SAVE_BSD_SOURCE
-#endif
-#endif /* __linux__ */
+#  ifdef __linux__
+#    ifdef _PNG_SAVE_BSD_SOURCE
+#      define _BSD_SOURCE
+#      undef _PNG_SAVE_BSD_SOURCE
+#    endif
+#  endif /* __linux__ */
+#endif /* PNG_SETJMP_SUPPORTED */
 
 #ifdef BSD
 #include <strings.h>
@@ -158,6 +164,7 @@
  * them inside an appropriate ifdef/endif pair for portability.
  */
 
+#if !defined(PNG_NO_FLOATING_POINT_SUPPORTED)
 #if defined(MACOS)
 /* We need to check that <math.h> hasn't already been included earlier
  * as it seems it doesn't agree with <fp.h>, yet we should really use
@@ -169,6 +176,7 @@
 #else
 #include <math.h>
 #endif
+#endif
 
 /* Codewarrior on NT has linking problems without this. */
 #if (defined(__MWERKS__) && defined(WIN32)) || defined(__STDC__)
@@ -473,209 +481,246 @@
 #endif
 
 #ifdef PNG_READ_ANCILLARY_CHUNKS_SUPPORTED
+
+#ifdef PNG_NO_READ_TEXT
+#  define PNG_NO_READ_iTXt
+#  define PNG_NO_READ_tEXt
+#  define PNG_NO_READ_zTXt
+#endif
 #ifndef PNG_NO_READ_bKGD
-#define PNG_READ_bKGD_SUPPORTED
-#define PNG_bKGD_SUPPORTED
+#  define PNG_READ_bKGD_SUPPORTED
+#  define PNG_bKGD_SUPPORTED
 #endif
 #ifndef PNG_NO_READ_cHRM
-#define PNG_READ_cHRM_SUPPORTED
-#define PNG_cHRM_SUPPORTED
+#  define PNG_READ_cHRM_SUPPORTED
+#  define PNG_cHRM_SUPPORTED
 #endif
 #ifndef PNG_NO_READ_gAMA
-#define PNG_READ_gAMA_SUPPORTED
-#define PNG_gAMA_SUPPORTED
+#  define PNG_READ_gAMA_SUPPORTED
+#  define PNG_gAMA_SUPPORTED
 #endif
 #ifndef PNG_NO_READ_hIST
-#define PNG_READ_hIST_SUPPORTED
-#define PNG_hIST_SUPPORTED
+#  define PNG_READ_hIST_SUPPORTED
+#  define PNG_hIST_SUPPORTED
 #endif
 #ifndef PNG_NO_READ_iCCP
-#define PNG_READ_iCCP_SUPPORTED
-#define PNG_iCCP_SUPPORTED
+#  define PNG_READ_iCCP_SUPPORTED
+#  define PNG_iCCP_SUPPORTED
 #endif
 #ifndef PNG_NO_READ_iTXt
-#define PNG_READ_iTXt_SUPPORTED
-#define PNG_iTXt_SUPPORTED
+#  define PNG_READ_iTXt_SUPPORTED
+#  define PNG_iTXt_SUPPORTED
 #endif
 #ifndef PNG_NO_READ_oFFs
-#define PNG_READ_oFFs_SUPPORTED
-#define PNG_oFFs_SUPPORTED
+#  define PNG_READ_oFFs_SUPPORTED
+#  define PNG_oFFs_SUPPORTED
 #endif
 #ifndef PNG_NO_READ_pCAL
-#define PNG_READ_pCAL_SUPPORTED
-#define PNG_pCAL_SUPPORTED
+#  define PNG_READ_pCAL_SUPPORTED
+#  define PNG_pCAL_SUPPORTED
 #endif
 #ifndef PNG_NO_READ_sCAL
-#define PNG_READ_sCAL_SUPPORTED
-#define PNG_sCAL_SUPPORTED
+#  define PNG_READ_sCAL_SUPPORTED
+#  define PNG_sCAL_SUPPORTED
 #endif
 #ifndef PNG_NO_READ_pHYs
-#define PNG_READ_pHYs_SUPPORTED
-#define PNG_pHYs_SUPPORTED
+#  define PNG_READ_pHYs_SUPPORTED
+#  define PNG_pHYs_SUPPORTED
 #endif
 #ifndef PNG_NO_READ_sBIT
-#define PNG_READ_sBIT_SUPPORTED
-#define PNG_sBIT_SUPPORTED
+#  define PNG_READ_sBIT_SUPPORTED
+#  define PNG_sBIT_SUPPORTED
 #endif
 #ifndef PNG_NO_READ_sPLT
-#define PNG_READ_sPLT_SUPPORTED
-#define PNG_sPLT_SUPPORTED
+#  define PNG_READ_sPLT_SUPPORTED
+#  define PNG_sPLT_SUPPORTED
 #endif
 #ifndef PNG_NO_READ_sRGB
-#define PNG_READ_sRGB_SUPPORTED
-#define PNG_sRGB_SUPPORTED
+#  define PNG_READ_sRGB_SUPPORTED
+#  define PNG_sRGB_SUPPORTED
 #endif
 #ifndef PNG_NO_READ_tEXt
-#define PNG_READ_tEXt_SUPPORTED
-#define PNG_tEXt_SUPPORTED
+#  define PNG_READ_tEXt_SUPPORTED
+#  define PNG_tEXt_SUPPORTED
 #endif
 #ifndef PNG_NO_READ_tIME
-#define PNG_READ_tIME_SUPPORTED
-#define PNG_tIME_SUPPORTED
+#  define PNG_READ_tIME_SUPPORTED
+#  define PNG_tIME_SUPPORTED
 #endif
 #ifndef PNG_NO_READ_tRNS
-#define PNG_READ_tRNS_SUPPORTED
-#define PNG_tRNS_SUPPORTED
+#  define PNG_READ_tRNS_SUPPORTED
+#  define PNG_tRNS_SUPPORTED
 #endif
 #ifndef PNG_NO_READ_zTXt
-#define PNG_READ_zTXt_SUPPORTED
-#define PNG_zTXt_SUPPORTED
+#  define PNG_READ_zTXt_SUPPORTED
+#  define PNG_zTXt_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_USER_CHUNKS
+#  define PNG_READ_USER_CHUNKS_SUPPORTED
+#  define PNG_USER_CHUNKS_SUPPORTED
+#  ifdef PNG_NO_READ_UNKNOWN_CHUNKS
+#    undef PNG_NO_READ_UNKNOWN_CHUNKS
+#  endif
+#  ifdef PNG_NO_HANDLE_AS_UNKNOWN
+#    undef PNG_NO_HANDLE_AS_UNKNOWN
+#  endif
 #endif
 #ifndef PNG_NO_READ_UNKNOWN_CHUNKS
-#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
-#define PNG_UNKNOWN_CHUNKS_SUPPORTED
+#  define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
+#  define PNG_UNKNOWN_CHUNKS_SUPPORTED
+#  ifndef PNG_NO_HANDLE_AS_UNKNOWN
+#    define PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+#  endif
 #endif
 #ifndef PNG_NO_READ_OPT_PLTE
-#define PNG_READ_OPT_PLTE_SUPPORTED /* only affects support of the optional */
-#endif                              /* PLTE chunk in RGB and RGBA images */
+#  define PNG_READ_OPT_PLTE_SUPPORTED /* only affects support of the */
+#endif                      /* optional PLTE chunk in RGB and RGBA images */
 #if defined(PNG_READ_iTXt_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) || \
   defined(PNG_READ_zTXt_SUPPORTED)
-#define PNG_READ_TEXT_SUPPORTED
-#define PNG_TEXT_SUPPORTED
+#  define PNG_READ_TEXT_SUPPORTED
+#  define PNG_TEXT_SUPPORTED
 #endif
 #endif /* PNG_READ_ANCILLARY_CHUNKS_SUPPORTED */
 
 #ifdef PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED
-#ifndef PNG_NO_WRITE_bKGD
-#define PNG_WRITE_bKGD_SUPPORTED
-#ifndef PNG_bKGD_SUPPORTED
-#  define PNG_bKGD_SUPPORTED
+#ifdef PNG_NO_WRITE_TEXT
+#  define PNG_NO_WRITE_iTXt
+#  define PNG_NO_WRITE_tEXt
+#  define PNG_NO_WRITE_zTXt
 #endif
+#ifndef PNG_NO_WRITE_bKGD
+#  define PNG_WRITE_bKGD_SUPPORTED
+#  ifndef PNG_bKGD_SUPPORTED
+#    define PNG_bKGD_SUPPORTED
+#  endif
 #endif
 #ifndef PNG_NO_WRITE_cHRM
-#define PNG_WRITE_cHRM_SUPPORTED
-#ifndef PNG_cHRM_SUPPORTED
-#  define PNG_cHRM_SUPPORTED
-#endif
+#  define PNG_WRITE_cHRM_SUPPORTED
+#  ifndef PNG_cHRM_SUPPORTED
+#    define PNG_cHRM_SUPPORTED
+#  endif
 #endif
 #ifndef PNG_NO_WRITE_gAMA
-#define PNG_WRITE_gAMA_SUPPORTED
-#ifndef PNG_gAMA_SUPPORTED
-#  define PNG_gAMA_SUPPORTED
-#endif
+#  define PNG_WRITE_gAMA_SUPPORTED
+#  ifndef PNG_gAMA_SUPPORTED
+#    define PNG_gAMA_SUPPORTED
+#  endif
 #endif
 #ifndef PNG_NO_WRITE_hIST
-#define PNG_WRITE_hIST_SUPPORTED
-#ifndef PNG_hIST_SUPPORTED
-#  define PNG_hIST_SUPPORTED
-#endif
+#  define PNG_WRITE_hIST_SUPPORTED
+#  ifndef PNG_hIST_SUPPORTED
+#    define PNG_hIST_SUPPORTED
+#  endif
 #endif
 #ifndef PNG_NO_WRITE_iCCP
-#define PNG_WRITE_iCCP_SUPPORTED
-#ifndef PNG_iCCP_SUPPORTED
-#  define PNG_iCCP_SUPPORTED
-#endif
+#  define PNG_WRITE_iCCP_SUPPORTED
+#  ifndef PNG_iCCP_SUPPORTED
+#    define PNG_iCCP_SUPPORTED
+#  endif
 #endif
 #ifndef PNG_NO_WRITE_iTXt
-#define PNG_WRITE_iTXt_SUPPORTED
-#ifndef PNG_iTXt_SUPPORTED
-#  define PNG_iTXt_SUPPORTED
-#endif
+#  define PNG_WRITE_iTXt_SUPPORTED
+#  ifndef PNG_iTXt_SUPPORTED
+#    define PNG_iTXt_SUPPORTED
+#  endif
 #endif
 #ifndef PNG_NO_WRITE_oFFs
-#define PNG_WRITE_oFFs_SUPPORTED
-#ifndef PNG_oFFs_SUPPORTED
-#  define PNG_oFFs_SUPPORTED
-#endif
+#  define PNG_WRITE_oFFs_SUPPORTED
+#  ifndef PNG_oFFs_SUPPORTED
+#    define PNG_oFFs_SUPPORTED
+#  endif
 #endif
 #ifndef PNG_NO_WRITE_pCAL
-#define PNG_WRITE_pCAL_SUPPORTED
-#ifndef PNG_pCAL_SUPPORTED
-#  define PNG_pCAL_SUPPORTED
-#endif
+#  define PNG_WRITE_pCAL_SUPPORTED
+#  ifndef PNG_pCAL_SUPPORTED
+#    define PNG_pCAL_SUPPORTED
+#  endif
 #endif
 #ifndef PNG_NO_WRITE_sCAL
-#define PNG_WRITE_sCAL_SUPPORTED
-#ifndef PNG_sCAL_SUPPORTED
-#  define PNG_sCAL_SUPPORTED
-#endif
+#  define PNG_WRITE_sCAL_SUPPORTED
+#  ifndef PNG_sCAL_SUPPORTED
+#    define PNG_sCAL_SUPPORTED
+#  endif
 #endif
 #ifndef PNG_NO_WRITE_pHYs
-#define PNG_WRITE_pHYs_SUPPORTED
-#ifndef PNG_pHYs_SUPPORTED
-#  define PNG_pHYs_SUPPORTED
-#endif
+#  define PNG_WRITE_pHYs_SUPPORTED
+#  ifndef PNG_pHYs_SUPPORTED
+#    define PNG_pHYs_SUPPORTED
+#  endif
 #endif
 #ifndef PNG_NO_WRITE_sBIT
-#define PNG_WRITE_sBIT_SUPPORTED
-#ifndef PNG_sBIT_SUPPORTED
-#  define PNG_sBIT_SUPPORTED
-#endif
+#  define PNG_WRITE_sBIT_SUPPORTED
+#  ifndef PNG_sBIT_SUPPORTED
+#    define PNG_sBIT_SUPPORTED
+#  endif
 #endif
 #ifndef PNG_NO_WRITE_sPLT
-#define PNG_WRITE_sPLT_SUPPORTED
-#ifndef PNG_sPLT_SUPPORTED
-#  define PNG_sPLT_SUPPORTED
-#endif
+#  define PNG_WRITE_sPLT_SUPPORTED
+#  ifndef PNG_sPLT_SUPPORTED
+#    define PNG_sPLT_SUPPORTED
+#  endif
 #endif
 #ifndef PNG_NO_WRITE_sRGB
-#define PNG_WRITE_sRGB_SUPPORTED
-#ifndef PNG_sRGB_SUPPORTED
-#  define PNG_sRGB_SUPPORTED
-#endif
+#  define PNG_WRITE_sRGB_SUPPORTED
+#  ifndef PNG_sRGB_SUPPORTED
+#    define PNG_sRGB_SUPPORTED
+#  endif
 #endif
 #ifndef PNG_NO_WRITE_tEXt
-#define PNG_WRITE_tEXt_SUPPORTED
-#ifndef PNG_tEXt_SUPPORTED
-#  define PNG_tEXt_SUPPORTED
-#endif
+#  define PNG_WRITE_tEXt_SUPPORTED
+#  ifndef PNG_tEXt_SUPPORTED
+#    define PNG_tEXt_SUPPORTED
+#  endif
 #endif
 #ifndef PNG_NO_WRITE_tIME
-#define PNG_WRITE_tIME_SUPPORTED
-#ifndef PNG_tIME_SUPPORTED
-#  define PNG_tIME_SUPPORTED
-#endif
+#  define PNG_WRITE_tIME_SUPPORTED
+#  ifndef PNG_tIME_SUPPORTED
+#    define PNG_tIME_SUPPORTED
+#  endif
 #endif
 #ifndef PNG_NO_WRITE_tRNS
-#define PNG_WRITE_tRNS_SUPPORTED
-#ifndef PNG_tRNS_SUPPORTED
-#  define PNG_tRNS_SUPPORTED
-#endif
+#  define PNG_WRITE_tRNS_SUPPORTED
+#  ifndef PNG_tRNS_SUPPORTED
+#    define PNG_tRNS_SUPPORTED
+#  endif
 #endif
 #ifndef PNG_NO_WRITE_zTXt
-#define PNG_WRITE_zTXt_SUPPORTED
-#ifndef PNG_zTXt_SUPPORTED
-#  define PNG_zTXt_SUPPORTED
-#endif
+#  define PNG_WRITE_zTXt_SUPPORTED
+#  ifndef PNG_zTXt_SUPPORTED
+#    define PNG_zTXt_SUPPORTED
+#  endif
 #endif
 #ifndef PNG_NO_WRITE_UNKNOWN_CHUNKS
-#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
-#ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED
-#  define PNG_UNKNOWN_CHUNKS_SUPPORTED
-#endif
+#  define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
+#  ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED
+#    define PNG_UNKNOWN_CHUNKS_SUPPORTED
+#  endif
+#  ifndef PNG_NO_HANDLE_AS_UNKNOWN
+#     ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+#       define PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+#     endif
+#  endif
 #endif
 #if defined(PNG_WRITE_iTXt_SUPPORTED) || defined(PNG_WRITE_tEXt_SUPPORTED) || \
   defined(PNG_WRITE_zTXt_SUPPORTED)
-#define PNG_WRITE_TEXT_SUPPORTED
-#ifndef PNG_TEXT_SUPPORTED
-#  define PNG_TEXT_SUPPORTED
-#endif
+#  define PNG_WRITE_TEXT_SUPPORTED
+#  ifndef PNG_TEXT_SUPPORTED
+#    define PNG_TEXT_SUPPORTED
+#  endif
 #endif
 #endif /* PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED */
 
+/* Turn this off to disable png_read_png() and
+ * png_write_png() and leave the image_bits member
+ * out of the info structure.
+ */
+#ifndef PNG_NO_INFO_IMAGE
+#  define PNG_INFO_IMAGE_SUPPORTED
+#endif
+
 /* need the time information for reading tIME chunks */
-#if defined(PNG_READ_tIME_SUPPORTED) || defined(PNG_WRITE_tIME_SUPPORTED)
-#include <time.h>
+#if defined(PNG_tIME_SUPPORTED)
+#  include <time.h>
 #endif
 
 /* Some typedefs to get us started.  These should be safe on most of the
@@ -758,6 +803,10 @@
 #define FARDATA
 #endif
 
+/* Typedef for floating-point numbers that are converted
+   to fixed-point with a multiple of 100,000, e.g., int_gamma */
+typedef png_int_32 png_fixed_point;
+
 /* Add typedefs for pointers */
 typedef void            FAR * png_voidp;
 typedef png_byte        FAR * png_bytep;
@@ -767,6 +816,7 @@
 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;
 #ifdef PNG_FLOATING_POINT_SUPPORTED
 typedef double          FAR * png_doublep;
 #endif
@@ -779,6 +829,7 @@
 typedef png_int_16      FAR * FAR * png_int_16pp;
 typedef PNG_CONST char  FAR * FAR * png_const_charpp;
 typedef char            FAR * FAR * png_charpp;
+typedef png_fixed_point FAR * FAR * png_fixed_point_pp;
 #ifdef PNG_FLOATING_POINT_SUPPORTED
 typedef double          FAR * FAR * png_doublepp;
 #endif
@@ -848,6 +899,10 @@
  * that are passed far data must be model independent.
  */
 
+#ifndef PNG_ABORT
+#   define PNG_ABORT() abort()
+#endif
+
 #if defined(USE_FAR_KEYWORD)  /* memory model independent fns */
 /* use this to make far-to-near assignments */
 #   define CHECK   1
diff --git a/pngerror.c b/pngerror.c
index af09771..3ef74ff 100644
--- a/pngerror.c
+++ b/pngerror.c
@@ -1,11 +1,11 @@
 
 /* pngerror.c - stub functions for i/o and memory allocation
  *
- * libpng 1.0.5h - December 10, 1999
+ * libpng 1.0.5q - February 5, 2000
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
+ * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson
  *
  * This file provides a location for all error handling.  Users who
  * need special error handling are expected to write replacement functions
@@ -67,21 +67,26 @@
 {
    int iout = 0, iin = 0;
 
-   while (iin < 4) {
+   while (iin < 4)
+   {
       int c = png_ptr->chunk_name[iin++];
-      if (isnonalpha(c)) {
+      if (isnonalpha(c))
+      {
          buffer[iout++] = '[';
          buffer[iout++] = png_digit[(c & 0xf0) >> 4];
-         buffer[iout++] = png_digit[c & 0xf];
+         buffer[iout++] = png_digit[c & 0x0f];
          buffer[iout++] = ']';
-      } else {
+      }
+      else
+      {
          buffer[iout++] = (png_byte)c;
       }
    }
 
    if (message == NULL)
       buffer[iout] = 0;
-   else {
+   else
+   {
       buffer[iout++] = ':';
       buffer[iout++] = ' ';
       png_memcpy(buffer+iout, message, 64);
@@ -117,14 +122,18 @@
    fprintf(stderr, "libpng error: %s\n", message);
 #endif
 
-#ifdef USE_FAR_KEYWORD
+#ifdef PNG_SETJMP_SUPPORTED
+#  ifdef USE_FAR_KEYWORD
    {
       jmp_buf jmpbuf;
       png_memcpy(jmpbuf,png_ptr->jmpbuf,sizeof(jmp_buf));
       longjmp(jmpbuf, 1);
    }
-#else
+#  else
    longjmp(png_ptr->jmpbuf, 1);
+# endif
+#else
+   PNG_ABORT();
 #endif
 }
 
diff --git a/pnggccrd.c b/pnggccrd.c
new file mode 100644
index 0000000..f73b1ff
--- /dev/null
+++ b/pnggccrd.c
@@ -0,0 +1,4633 @@
+/* pnggccrd.c - mixed C/assembler version of utilities to read a PNG file
+ *
+ * For Intel x86 CPU (Pentium-MMX or later) and GNU C compiler.
+ *
+ *     See http://www.intel.com/drg/pentiumII/appnotes/916/916.htm
+ *     and http://www.intel.com/drg/pentiumII/appnotes/923/923.htm
+ *     for Intel's performance analysis of the MMX vs. non-MMX code.
+ *
+ * libpng 1.0.5q - February 5, 2000
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998, Intel Corporation
+ * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson
+ *
+ * Based on MSVC code contributed by Nirav Chhatrapati, Intel Corp., 1998.
+ * Interface to libpng contributed by Gilles Vollant, 1999.
+ * GNU C port by Greg Roelofs, 1999.
+ *
+ * Lines 2350-4300 converted in place with intel2gas 1.3.1:
+ *
+ *   intel2gas -mdI pnggccrd.c.partially-msvc -o pnggccrd.c
+ *
+ * and then cleaned up by hand.  See http://hermes.terminal.at/intel2gas/ .
+ *
+ * NOTE:  A sufficiently recent version of GNU as (or as.exe under DOS/Windows)
+ *        is required to assemble the newer MMX instructions such as movq.
+ *        For djgpp, see
+ *
+ *           ftp://ftp.cdrom.com/pub/simtelnet/gnu/djgpp/v2gnu/bnu281b.zip
+ *
+ *        (or a later version in the same directory).  For Linux, check your
+ *        distribution's web site(s) or try these links:
+ *
+ *           http://rufus.w3.org/linux/RPM/binutils.html
+ *           http://www.debian.org/Packages/stable/devel/binutils.html
+ *           ftp://ftp.cdrom.com/pub/linux/slackware/slakware/d1/binutils.tgz
+ *
+ *        For other platforms, see the main GNU site:
+ *
+ *           ftp://ftp.gnu.org/pub/gnu/binutils/
+ *
+ *        Version 2.5.2l.15 is definitely too old...
+ */
+#if 0
+// GRR NOTES
+//
+// 19991006:
+//  - fixed sign error in post-MMX cleanup code (16- & 32-bit cases)
+//
+// 19991007:
+//  - additional optimizations (possible or definite):
+//     x [DONE] write MMX code for 64-bit case (pixel_bytes == 8) [not tested]
+//     - write MMX code for 48-bit case (pixel_bytes == 6)
+//     - figure out what's up with 24-bit case (pixel_bytes == 3):
+//        why subtract 8 from width_mmx in the pass 4/5 case?
+//        (only width_mmx case)
+//     x [DONE] replace pixel_bytes within each block with the true
+//        constant value (or are compilers smart enough to do that?)
+//     - rewrite all MMX interlacing code so it's aligned with
+//        the *beginning* of the row buffer, not the end.  This
+//        would not only allow one to eliminate half of the memory
+//        writes for odd passes (i.e., pass == odd), it may also
+//        eliminate some unaligned-data-access exceptions (assuming
+//        there's a penalty for not aligning 64-bit accesses on
+//        64-bit boundaries).  The only catch is that the "leftover"
+//        pixel(s) at the end of the row would have to be saved,
+//        but there are enough unused MMX registers in every case,
+//        so this is not a problem.  A further benefit is that the
+//        post-MMX cleanup code (C code) in at least some of the
+//        cases could be done within the assembler block.
+//  x [DONE] the "v3 v2 v1 v0 v7 v6 v5 v4" comments are confusing,
+//     inconsistent, and don't match the MMX Programmer's Reference
+//     Manual conventions anyway.  They should be changed to
+//     "b7 b6 b5 b4 b3 b2 b1 b0," where b0 indicates the byte that
+//     was lowest in memory (e.g., corresponding to a left pixel)
+//     and b7 is the byte that was highest (e.g., a right pixel).
+//
+// 19991016:
+//  - Brennan's Guide notwithstanding, gcc under Linux does *not*
+//     want globals prefixed by underscores when referencing them--
+//     i.e., if the variable is const4, then refer to it as const4,
+//     not _const4.  This seems to be a djgpp-specific requirement.
+//     Also, such variables apparently *must* be declared outside
+//     of functions; neither static nor automatic variables work if
+//     defined within the scope of a single function, but both
+//     static and truly global (multi-module) variables work fine.
+//
+// 19991023:
+//  - fixed png_combine_row() non-MMX replication bug (odd passes only?)
+//  - switched from string-concatenation-with-macros to cleaner method of
+//     renaming global variables for djgpp--i.e., always use prefixes in
+//     inlined assembler code (== strings) and conditionally rename the
+//     variables, not the other way around.  Hence _const4, _mask8_0, etc.
+//
+// 19991024:
+//  - fixed mmxsupport()/png_do_interlace() first-row bug
+//     This one was severely weird:  even though mmxsupport() doesn't touch
+//     ebx (where "row" pointer was stored), it nevertheless managed to zero
+//     the register (even in static/non-fPIC code--see below), which in turn
+//     caused png_do_interlace() to return prematurely on the first row of
+//     interlaced images (i.e., without expanding the interlaced pixels).
+//     Inspection of the generated assembly code didn't turn up any clues,
+//     although it did point at a minor optimization (i.e., get rid of
+//     mmx_supported_local variable and just use eax).  Possibly the CPUID
+//     instruction is more destructive than it looks?  (Not yet checked.)
+//  - "info gcc" was next to useless, so compared fPIC and non-fPIC assembly
+//     listings...  Apparently register spillage has to do with ebx, since
+//     it's used to index the global offset table.  Commenting it out of the
+//     input-reg lists in png_combine_row() eliminated compiler barfage, so
+//     ifdef'd with __PIC__ macro:  if defined, use a global for unmask
+//
+// 19991107:
+//  - verified CPUID clobberage:  12-char string constant ("GenuineIntel",
+//     "AuthenticAMD", etc.) placed in EBX:ECX:EDX.  Still need to polish.
+//
+// 19991120:
+//  - made "diff" variable (now "_dif") global to simplify conversion of
+//     filtering routines (running out of regs, sigh).  "diff" is still used
+//     in interlacing routines, however.
+//  - fixed up both versions of mmxsupport() (ORIG_THAT_USED_TO_CLOBBER_EBX
+//     macro determines which is used); original not yet tested.
+#endif
+
+#define PNG_INTERNAL
+#include "png.h"
+
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) && defined(PNG_USE_PNGGCCRD)
+
+int mmxsupport(void);
+
+static int mmx_supported = 2;
+
+// djgpp adds its own underscores to global variables, so define them without:
+#ifdef __DJGPP__
+#  define _unmask      unmask
+#  define _const4      const4
+#  define _const6      const6
+#  define _mask8_0     mask8_0  
+#  define _mask16_1    mask16_1 
+#  define _mask16_0    mask16_0 
+#  define _mask24_2    mask24_2 
+#  define _mask24_1    mask24_1 
+#  define _mask24_0    mask24_0 
+#  define _mask32_3    mask32_3 
+#  define _mask32_2    mask32_2 
+#  define _mask32_1    mask32_1 
+#  define _mask32_0    mask32_0 
+#  define _mask48_5    mask48_5 
+#  define _mask48_4    mask48_4 
+#  define _mask48_3    mask48_3 
+#  define _mask48_2    mask48_2 
+#  define _mask48_1    mask48_1 
+#  define _mask48_0    mask48_0 
+#  define _FullLength  FullLength
+#  define _MMXLength   MMXLength
+#  define _dif         dif
+#endif
+
+/* These constants are used in the inlined MMX assembly code.
+   Ignore gcc's "At top level: defined but not used" warnings. */
+
+#ifdef __PIC__
+static int _unmask;     // not enough regs when compiling with -fPIC, so...
+#endif
+
+static unsigned long long _mask8_0  = 0x0102040810204080LL;
+
+static unsigned long long _mask16_1 = 0x0101020204040808LL;
+static unsigned long long _mask16_0 = 0x1010202040408080LL;
+
+static unsigned long long _mask24_2 = 0x0101010202020404LL;
+static unsigned long long _mask24_1 = 0x0408080810101020LL;
+static unsigned long long _mask24_0 = 0x2020404040808080LL;
+
+static unsigned long long _mask32_3 = 0x0101010102020202LL;
+static unsigned long long _mask32_2 = 0x0404040408080808LL;
+static unsigned long long _mask32_1 = 0x1010101020202020LL;
+static unsigned long long _mask32_0 = 0x4040404080808080LL;
+
+static unsigned long long _mask48_5 = 0x0101010101010202LL;
+static unsigned long long _mask48_4 = 0x0202020204040404LL;
+static unsigned long long _mask48_3 = 0x0404080808080808LL;
+static unsigned long long _mask48_2 = 0x1010101010102020LL;
+static unsigned long long _mask48_1 = 0x2020202040404040LL;
+static unsigned long long _mask48_0 = 0x4040808080808080LL;
+
+static unsigned long long _const4   = 0x0000000000FFFFFFLL;
+//static unsigned long long _const5 = 0x000000FFFFFF0000LL;     // NOT USED
+static unsigned long long _const6   = 0x00000000000000FFLL;
+
+// These are used in the row-filter routines and should/would be local
+//  variables if not for gcc addressing limitations.
+
+static png_uint_32  _FullLength;
+static png_uint_32  _MMXLength;
+static int          _dif;
+
+
+void
+png_read_filter_row_c(png_structp png_ptr, png_row_infop row_info,
+   png_bytep row, png_bytep prev_row, int filter);
+
+
+#if defined(PNG_HAVE_ASSEMBLER_COMBINE_ROW)
+
+/* Combines the row recently read in with the previous row.
+   This routine takes care of alpha and transparency if requested.
+   This routine also handles the two methods of progressive display
+   of interlaced images, depending on the mask value.
+   The mask value describes which pixels are to be combined with
+   the row.  The pattern always repeats every 8 pixels, so just 8
+   bits are needed.  A one indicates the pixel is to be combined; a
+   zero indicates the pixel is to be skipped.  This is in addition
+   to any alpha or transparency value associated with the pixel.
+   If you want all pixels to be combined, pass 0xff (255) in mask. */
+
+/* Use this routine for the x86 platform - it uses a faster MMX routine
+   if the machine supports MMX. */
+
+void
+png_combine_row(png_structp png_ptr, png_bytep row, int mask)
+{
+   png_debug(1,"in png_combine_row_asm\n");
+
+   if (mmx_supported == 2)
+       mmx_supported = mmxsupport();
+
+/*
+fprintf(stderr, "GRR DEBUG:  png_combine_row() pixel_depth = %d, mask = 0x%02x, unmask = 0x%02x\n", png_ptr->row_info.pixel_depth, mask, ~mask);
+fflush(stderr);
+ */
+   if (mask == 0xff)
+   {
+      png_memcpy(row, png_ptr->row_buf + 1,
+       (png_size_t)((png_ptr->width * png_ptr->row_info.pixel_depth + 7) >> 3));
+   }
+   /* GRR:  add "else if (mask == 0)" case?
+    *       or does png_combine_row() not even get called in that case? */
+   else
+   {
+      switch (png_ptr->row_info.pixel_depth)
+      {
+         case 1:        // png_ptr->row_info.pixel_depth
+         {
+            png_bytep sp;
+            png_bytep dp;
+            int s_inc, s_start, s_end;
+            int m;
+            int shift;
+            png_uint_32 i;
+
+            sp = png_ptr->row_buf + 1;
+            dp = row;
+            m = 0x80;
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+            if (png_ptr->transformations & PNG_PACKSWAP)
+            {
+                s_start = 0;
+                s_end = 7;
+                s_inc = 1;
+            }
+            else
+#endif
+            {
+                s_start = 7;
+                s_end = 0;
+                s_inc = -1;
+            }
+
+            shift = s_start;
+
+            for (i = 0; i < png_ptr->width; i++)
+            {
+               if (m & mask)
+               {
+                  int value;
+
+                  value = (*sp >> shift) & 0x1;
+                  *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
+                  *dp |= (png_byte)(value << shift);
+               }
+
+               if (shift == s_end)
+               {
+                  shift = s_start;
+                  sp++;
+                  dp++;
+               }
+               else
+                  shift += s_inc;
+
+               if (m == 1)
+                  m = 0x80;
+               else
+                  m >>= 1;
+            }
+            break;
+         }
+
+         case 2:        // png_ptr->row_info.pixel_depth
+         {
+            png_bytep sp;
+            png_bytep dp;
+            int s_start, s_end, s_inc;
+            int m;
+            int shift;
+            png_uint_32 i;
+            int value;
+
+            sp = png_ptr->row_buf + 1;
+            dp = row;
+            m = 0x80;
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+            if (png_ptr->transformations & PNG_PACKSWAP)
+            {
+               s_start = 0;
+               s_end = 6;
+               s_inc = 2;
+            }
+            else
+#endif
+            {
+               s_start = 6;
+               s_end = 0;
+               s_inc = -2;
+            }
+
+            shift = s_start;
+
+            for (i = 0; i < png_ptr->width; i++)
+            {
+               if (m & mask)
+               {
+                  value = (*sp >> shift) & 0x3;
+                  *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
+                  *dp |= (png_byte)(value << shift);
+               }
+
+               if (shift == s_end)
+               {
+                  shift = s_start;
+                  sp++;
+                  dp++;
+               }
+               else
+                  shift += s_inc;
+               if (m == 1)
+                  m = 0x80;
+               else
+                  m >>= 1;
+            }
+            break;
+         }
+
+         case 4:        // png_ptr->row_info.pixel_depth
+         {
+            png_bytep sp;
+            png_bytep dp;
+            int s_start, s_end, s_inc;
+            int m;
+            int shift;
+            png_uint_32 i;
+            int value;
+
+            sp = png_ptr->row_buf + 1;
+            dp = row;
+            m = 0x80;
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+            if (png_ptr->transformations & PNG_PACKSWAP)
+            {
+               s_start = 0;
+               s_end = 4;
+               s_inc = 4;
+            }
+            else
+#endif
+            {
+               s_start = 4;
+               s_end = 0;
+               s_inc = -4;
+            }
+            shift = s_start;
+
+            for (i = 0; i < png_ptr->width; i++)
+            {
+               if (m & mask)
+               {
+                  value = (*sp >> shift) & 0xf;
+                  *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
+                  *dp |= (png_byte)(value << shift);
+               }
+
+               if (shift == s_end)
+               {
+                  shift = s_start;
+                  sp++;
+                  dp++;
+               }
+               else
+                  shift += s_inc;
+               if (m == 1)
+                  m = 0x80;
+               else
+                  m >>= 1;
+            }
+            break;
+         }
+
+         case 8:        // png_ptr->row_info.pixel_depth
+         {
+            png_bytep srcptr;
+            png_bytep dstptr;
+
+            if (mmx_supported)
+            {
+               png_uint_32 len;
+               int diff;
+#ifndef __PIC__
+               int unmask = ~mask;
+#else
+               _unmask = ~mask;            // global variable for -fPIC version
+#endif
+               srcptr = png_ptr->row_buf + 1;
+               dstptr = row;
+               len  = png_ptr->width &~7;  // reduce to multiple of 8
+               diff = png_ptr->width & 7;  // amount lost
+
+               __asm__ (
+#ifdef __PIC__
+                  "movd      _unmask, %%mm7  \n\t" // load bit pattern
+#else
+// preload        "movd      unmask, %%mm7   \n\t" // (unmask is in ebx)
+                  "movd      %%ebx, %%mm7    \n\t" // load bit pattern (unmask)
+#endif
+                  "psubb     %%mm6, %%mm6    \n\t" // zero mm6
+                  "punpcklbw %%mm7, %%mm7    \n\t"
+                  "punpcklwd %%mm7, %%mm7    \n\t"
+                  "punpckldq %%mm7, %%mm7    \n\t" // fill reg with 8 masks
+
+                  "movq      _mask8_0, %%mm0 \n\t"
+                  "pand      %%mm7, %%mm0    \n\t" // nonzero if keep byte
+                  "pcmpeqb   %%mm6, %%mm0    \n\t" // zeros->1s, v versa
+
+// preload        "movl      len, %%ecx      \n\t" // load length of line
+// preload        "movl      srcptr, %%esi   \n\t" // load source
+// preload        "movl      dstptr, %%edi   \n\t" // load dest
+
+                  "cmpl      $0, %%ecx       \n\t" // len == 0 ?
+                  "je        mainloop8end    \n\t"
+
+                "mainloop8:                  \n\t"
+                  "movq      (%%esi), %%mm4  \n\t" // *srcptr
+                  "pand      %%mm0, %%mm4    \n\t"
+                  "movq      %%mm0, %%mm6    \n\t"
+                  "pandn     (%%edi), %%mm6  \n\t" // *dstptr
+                  "por       %%mm6, %%mm4    \n\t"
+                  "movq      %%mm4, (%%edi)  \n\t"
+                  "addl      $8, %%esi       \n\t" // inc by 8 bytes processed
+                  "addl      $8, %%edi       \n\t"
+                  "subl      $8, %%ecx       \n\t" // dec by 8 pixels processed
+                  "ja        mainloop8       \n\t"
+
+                "mainloop8end:               \n\t"
+// preload        "movl      diff, %%ecx     \n\t" // (diff is in eax)
+                  "movl      %%eax, %%ecx    \n\t"
+                  "cmpl      $0, %%ecx       \n\t"
+                  "jz        end8            \n\t"
+// preload        "movl      mask, %%edx     \n\t"
+                  "sall      $24, %%edx      \n\t" // make low byte, high byte
+
+                "secondloop8:                \n\t"
+                  "sall      %%edx           \n\t" // move high bit to CF
+                  "jnc       skip8           \n\t" // if CF = 0
+                  "movb      (%%esi), %%al   \n\t"
+                  "movb      %%al, (%%edi)   \n\t"
+
+                "skip8:                      \n\t"
+                  "incl      %%esi           \n\t"
+                  "incl      %%edi           \n\t"
+                  "decl      %%ecx           \n\t"
+                  "jnz       secondloop8     \n\t"
+
+                "end8:                       \n\t"
+                  "EMMS                      \n\t"  // DONE
+
+                  :                                 // output regs (none)
+
+                  : "S" (srcptr),      // esi       // input regs
+                    "D" (dstptr),      // edi
+                    "a" (diff),        // eax
+#ifndef __PIC__
+                    "b" (unmask),      // ebx       // Global Offset Table idx
+#endif
+                    "c" (len),         // ecx
+                    "d" (mask)         // edx
+
+                  : "%esi", "%edi", "%eax",         // clobber list
+                    "%ecx", "%edx"
+#if 0  /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */
+                  , "%mm0", "%mm4", "%mm6", "%mm7"
+#endif
+               );
+            }
+            else /* mmx _not supported - Use modified C routine */
+            {
+               register png_uint_32 i;
+               png_uint_32 initial_val = png_pass_start[png_ptr->pass];
+                 // png.c:  png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
+               register int stride = png_pass_inc[png_ptr->pass];
+                 // png.c:  png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
+               register int rep_bytes = png_pass_width[png_ptr->pass];
+                 // png.c:  png_pass_width[] = {8, 4, 4, 2, 2, 1, 1};
+               register png_uint_32 final_val = png_ptr->width;
+
+               srcptr = png_ptr->row_buf + 1 + initial_val;
+               dstptr = row + initial_val;
+
+               for (i = initial_val; i < final_val; i += stride)
+               {
+                  png_memcpy(dstptr, srcptr, rep_bytes);
+                  srcptr += stride;
+                  dstptr += stride;
+               } 
+            } /* end of else */
+
+            break;
+         }       // end 8 bpp
+
+         case 16:       // png_ptr->row_info.pixel_depth
+         {
+            png_bytep srcptr;
+            png_bytep dstptr;
+
+            if (mmx_supported)
+            {
+               png_uint_32 len;
+               int diff;
+#ifndef __PIC__
+               int unmask = ~mask;
+#else
+               _unmask = ~mask;            // global variable for -fPIC version
+#endif
+               srcptr = png_ptr->row_buf + 1;
+               dstptr = row;
+               len  = png_ptr->width &~7;  // reduce to multiple of 8
+               diff = png_ptr->width & 7;  // amount lost
+
+               __asm__ (
+#ifdef __PIC__
+                  "movd      _unmask, %%mm7   \n\t" // load bit pattern
+#else
+// preload        "movd      unmask, %%mm7    \n\t" // (unmask is in ebx)
+                  "movd      %%ebx, %%mm7     \n\t" // load bit pattern (unmask)
+#endif
+                  "psubb     %%mm6, %%mm6     \n\t" // zero mm6
+                  "punpcklbw %%mm7, %%mm7     \n\t"
+                  "punpcklwd %%mm7, %%mm7     \n\t"
+                  "punpckldq %%mm7, %%mm7     \n\t" // fill reg with 8 masks
+
+                  "movq      _mask16_0, %%mm0 \n\t"
+                  "movq      _mask16_1, %%mm1 \n\t"
+
+                  "pand      %%mm7, %%mm0     \n\t"
+                  "pand      %%mm7, %%mm1     \n\t"
+
+                  "pcmpeqb   %%mm6, %%mm0     \n\t"
+                  "pcmpeqb   %%mm6, %%mm1     \n\t"
+
+// preload        "movl      len, %%ecx       \n\t" // load length of line
+// preload        "movl      srcptr, %%esi    \n\t" // load source
+// preload        "movl      dstptr, %%edi    \n\t" // load dest
+
+                  "cmpl      $0, %%ecx        \n\t"
+                  "jz        mainloop16end    \n\t"
+
+                "mainloop16:                  \n\t"
+                  "movq      (%%esi), %%mm4   \n\t"
+                  "pand      %%mm0, %%mm4     \n\t"
+                  "movq      %%mm0, %%mm6     \n\t"
+                  "movq      (%%edi), %%mm7   \n\t"
+                  "pandn     %%mm7, %%mm6     \n\t"
+                  "por       %%mm6, %%mm4     \n\t"
+                  "movq      %%mm4, (%%edi)   \n\t"
+
+                  "movq      8(%%esi), %%mm5  \n\t"
+                  "pand      %%mm1, %%mm5     \n\t"
+                  "movq      %%mm1, %%mm7     \n\t"
+                  "movq      8(%%edi), %%mm6  \n\t"
+                  "pandn     %%mm6, %%mm7     \n\t"
+                  "por       %%mm7, %%mm5     \n\t"
+                  "movq      %%mm5, 8(%%edi)  \n\t"
+
+                  "addl      $16, %%esi       \n\t" // inc by 16 bytes processed
+                  "addl      $16, %%edi       \n\t"
+                  "subl      $8, %%ecx        \n\t" // dec by 8 pixels processed
+                  "ja        mainloop16       \n\t"
+
+                "mainloop16end:               \n\t"
+// preload        "movl      diff, %%ecx      \n\t" // (diff is in eax)
+                  "movl      %%eax, %%ecx     \n\t"
+                  "cmpl      $0, %%ecx        \n\t"
+                  "jz        end16            \n\t"
+// preload        "movl      mask, %%edx      \n\t"
+                  "sall      $24, %%edx       \n\t" // make low byte, high byte
+
+                "secondloop16:                \n\t"
+                  "sall      %%edx            \n\t" // move high bit to CF
+                  "jnc       skip16           \n\t" // if CF = 0
+                  "movw      (%%esi), %%ax    \n\t"
+                  "movw      %%ax, (%%edi)    \n\t"
+
+                "skip16:                      \n\t"
+                  "addl      $2, %%esi        \n\t"
+                  "addl      $2, %%edi        \n\t"
+                  "decl      %%ecx            \n\t"
+                  "jnz       secondloop16     \n\t"
+
+                "end16:                       \n\t"
+                  "EMMS                       \n\t" // DONE
+
+                  :                                 // output regs (none)
+
+                  : "S" (srcptr),      // esi       // input regs
+                    "D" (dstptr),      // edi
+                    "a" (diff),        // eax
+#ifndef __PIC__
+                    "b" (unmask),      // ebx       // Global Offset Table idx
+#endif
+                    "c" (len),         // ecx
+                    "d" (mask)         // edx
+
+                  : "%esi", "%edi", "%eax",         // clobber list
+                    "%ecx", "%edx"
+#if 0  /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */
+                  , "%mm0", "%mm1",
+                    "%mm4", "%mm5", "%mm6", "%mm7"
+#endif
+               );
+            }
+            else /* mmx _not supported - Use modified C routine */
+            {
+               register png_uint_32 i;
+               png_uint_32 initial_val = 2 * png_pass_start[png_ptr->pass];
+                 // png.c:  png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
+               register int stride = 2 * png_pass_inc[png_ptr->pass];
+                 // png.c:  png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
+               register int rep_bytes = 2 * png_pass_width[png_ptr->pass];
+                 // png.c:  png_pass_width[] = {8, 4, 4, 2, 2, 1, 1};
+               register png_uint_32 final_val = 2 * png_ptr->width;
+
+               srcptr = png_ptr->row_buf + 1 + initial_val;
+               dstptr = row + initial_val;
+
+               for (i = initial_val; i < final_val; i += stride)
+               {
+                  png_memcpy(dstptr, srcptr, rep_bytes);
+                  srcptr += stride;
+                  dstptr += stride;
+               } 
+            } /* end of else */
+
+            break;
+         }       // end 16 bpp
+
+         case 24:       // png_ptr->row_info.pixel_depth
+         {
+            png_bytep srcptr;
+            png_bytep dstptr;
+
+            if (mmx_supported)
+            {
+               png_uint_32 len;
+               int diff;
+#ifndef __PIC__
+               int unmask = ~mask;
+#else
+               _unmask = ~mask;            // global variable for -fPIC version
+#endif
+               srcptr = png_ptr->row_buf + 1;
+               dstptr = row;
+               len  = png_ptr->width &~7;  // reduce to multiple of 8
+               diff = png_ptr->width & 7;  // amount lost
+
+               __asm__ (
+#ifdef __PIC__
+                  "movd      _unmask, %%mm7   \n\t" // load bit pattern
+#else
+// preload        "movd      unmask, %%mm7    \n\t" // (unmask is in ebx)
+                  "movd      %%ebx, %%mm7     \n\t" // load bit pattern (unmask)
+#endif
+                  "psubb     %%mm6, %%mm6     \n\t" // zero mm6
+                  "punpcklbw %%mm7, %%mm7     \n\t"
+                  "punpcklwd %%mm7, %%mm7     \n\t"
+                  "punpckldq %%mm7, %%mm7     \n\t" // fill reg with 8 masks
+
+                  "movq      _mask24_0, %%mm0 \n\t"
+                  "movq      _mask24_1, %%mm1 \n\t"
+                  "movq      _mask24_2, %%mm2 \n\t"
+
+                  "pand      %%mm7, %%mm0     \n\t"
+                  "pand      %%mm7, %%mm1     \n\t"
+                  "pand      %%mm7, %%mm2     \n\t"
+
+                  "pcmpeqb   %%mm6, %%mm0     \n\t"
+                  "pcmpeqb   %%mm6, %%mm1     \n\t"
+                  "pcmpeqb   %%mm6, %%mm2     \n\t"
+
+// preload        "movl      len, %%ecx       \n\t" // load length of line
+// preload        "movl      srcptr, %%esi    \n\t" // load source
+// preload        "movl      dstptr, %%edi    \n\t" // load dest
+
+                  "cmpl      $0, %%ecx        \n\t"
+                  "jz        mainloop24end    \n\t"
+
+                "mainloop24:                  \n\t"
+                  "movq      (%%esi), %%mm4   \n\t"
+                  "pand      %%mm0, %%mm4     \n\t"
+                  "movq      %%mm0, %%mm6     \n\t"
+                  "movq      (%%edi), %%mm7   \n\t"
+                  "pandn     %%mm7, %%mm6     \n\t"
+                  "por       %%mm6, %%mm4     \n\t"
+                  "movq      %%mm4, (%%edi)   \n\t"
+
+                  "movq      8(%%esi), %%mm5  \n\t"
+                  "pand      %%mm1, %%mm5     \n\t"
+                  "movq      %%mm1, %%mm7     \n\t"
+                  "movq      8(%%edi), %%mm6  \n\t"
+                  "pandn     %%mm6, %%mm7     \n\t"
+                  "por       %%mm7, %%mm5     \n\t"
+                  "movq      %%mm5, 8(%%edi)  \n\t"
+
+                  "movq      16(%%esi), %%mm6 \n\t"
+                  "pand      %%mm2, %%mm6     \n\t"
+                  "movq      %%mm2, %%mm4     \n\t"
+                  "movq      16(%%edi), %%mm7 \n\t"
+                  "pandn     %%mm7, %%mm4     \n\t"
+                  "por       %%mm4, %%mm6     \n\t"
+                  "movq      %%mm6, 16(%%edi) \n\t"
+
+                  "addl      $24, %%esi       \n\t" // inc by 24 bytes processed
+                  "addl      $24, %%edi       \n\t"
+                  "subl      $8, %%ecx        \n\t" // dec by 8 pixels processed
+
+                  "ja        mainloop24       \n\t"
+
+                "mainloop24end:               \n\t"
+// preload        "movl      diff, %%ecx      \n\t" // (diff is in eax)
+                  "movl      %%eax, %%ecx     \n\t"
+                  "cmpl      $0, %%ecx        \n\t"
+                  "jz        end24            \n\t"
+// preload        "movl      mask, %%edx      \n\t"
+                  "sall      $24, %%edx       \n\t" // make low byte, high byte
+
+                "secondloop24:                \n\t"
+                  "sall      %%edx            \n\t" // move high bit to CF
+                  "jnc       skip24           \n\t" // if CF = 0
+                  "movw      (%%esi), %%ax    \n\t"
+                  "movw      %%ax, (%%edi)    \n\t"
+                  "xorl      %%eax, %%eax     \n\t"
+                  "movb      2(%%esi), %%al   \n\t"
+                  "movb      %%al, 2(%%edi)   \n\t"
+
+                "skip24:                      \n\t"
+                  "addl      $3, %%esi        \n\t"
+                  "addl      $3, %%edi        \n\t"
+                  "decl      %%ecx            \n\t"
+                  "jnz       secondloop24     \n\t"
+
+                "end24:                       \n\t"
+                  "EMMS                       \n\t" // DONE
+
+                  :                                 // output regs (none)
+
+                  : "S" (srcptr),      // esi       // input regs
+                    "D" (dstptr),      // edi
+                    "a" (diff),        // eax
+#ifndef __PIC__
+                    "b" (unmask),      // ebx       // Global Offset Table idx
+#endif
+                    "c" (len),         // ecx
+                    "d" (mask)         // edx
+
+                  : "%esi", "%edi", "%eax",         // clobber list
+                    "%ecx", "%edx"
+#if 0  /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */
+                  , "%mm0", "%mm1", "%mm2",
+                    "%mm4", "%mm5", "%mm6", "%mm7"
+#endif
+               );
+            }
+            else /* mmx _not supported - Use modified C routine */
+            {
+               register png_uint_32 i;
+               png_uint_32 initial_val = 3 * png_pass_start[png_ptr->pass];
+                 // png.c:  png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
+               register int stride = 3 * png_pass_inc[png_ptr->pass];
+                 // png.c:  png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
+               register int rep_bytes = 3 * png_pass_width[png_ptr->pass];
+                 // png.c:  png_pass_width[] = {8, 4, 4, 2, 2, 1, 1};
+               register png_uint_32 final_val = 3 * png_ptr->width;
+
+               srcptr = png_ptr->row_buf + 1 + initial_val;
+               dstptr = row + initial_val;
+
+               for (i = initial_val; i < final_val; i += stride)
+               {
+                  png_memcpy(dstptr, srcptr, rep_bytes);
+                  srcptr += stride;
+                  dstptr += stride;
+               } 
+            } /* end of else */
+
+            break;
+         }       // end 24 bpp
+
+         case 32:       // png_ptr->row_info.pixel_depth
+         {
+            png_bytep srcptr;
+            png_bytep dstptr;
+
+            if (mmx_supported)
+            {
+               png_uint_32 len;
+               int diff;
+#ifndef __PIC__
+               int unmask = ~mask;
+#else
+               _unmask = ~mask;            // global variable for -fPIC version
+#endif
+               srcptr = png_ptr->row_buf + 1;
+               dstptr = row;
+               len  = png_ptr->width &~7;  // reduce to multiple of 8
+               diff = png_ptr->width & 7;  // amount lost
+
+               __asm__ (
+#ifdef __PIC__
+                  "movd      _unmask, %%mm7   \n\t" // load bit pattern
+#else
+// preload        "movd      unmask, %%mm7    \n\t" // (unmask is in ebx)
+                  "movd      %%ebx, %%mm7     \n\t" // load bit pattern (unmask)
+#endif
+                  "psubb     %%mm6, %%mm6     \n\t" // zero mm6
+                  "punpcklbw %%mm7, %%mm7     \n\t"
+                  "punpcklwd %%mm7, %%mm7     \n\t"
+                  "punpckldq %%mm7, %%mm7     \n\t" // fill reg with 8 masks
+
+                  "movq      _mask32_0, %%mm0 \n\t"
+                  "movq      _mask32_1, %%mm1 \n\t"
+                  "movq      _mask32_2, %%mm2 \n\t"
+                  "movq      _mask32_3, %%mm3 \n\t"
+
+                  "pand      %%mm7, %%mm0     \n\t"
+                  "pand      %%mm7, %%mm1     \n\t"
+                  "pand      %%mm7, %%mm2     \n\t"
+                  "pand      %%mm7, %%mm3     \n\t"
+
+                  "pcmpeqb   %%mm6, %%mm0     \n\t"
+                  "pcmpeqb   %%mm6, %%mm1     \n\t"
+                  "pcmpeqb   %%mm6, %%mm2     \n\t"
+                  "pcmpeqb   %%mm6, %%mm3     \n\t"
+
+// preload        "movl      len, %%ecx       \n\t" // load length of line
+// preload        "movl      srcptr, %%esi    \n\t" // load source
+// preload        "movl      dstptr, %%edi    \n\t" // load dest
+
+                  "cmpl      $0, %%ecx        \n\t" // lcr
+                  "jz        mainloop32end    \n\t"
+
+                "mainloop32:                  \n\t"
+                  "movq      (%%esi), %%mm4   \n\t"
+                  "pand      %%mm0, %%mm4     \n\t"
+                  "movq      %%mm0, %%mm6     \n\t"
+                  "movq      (%%edi), %%mm7   \n\t"
+                  "pandn     %%mm7, %%mm6     \n\t"
+                  "por       %%mm6, %%mm4     \n\t"
+                  "movq      %%mm4, (%%edi)   \n\t"
+
+                  "movq      8(%%esi), %%mm5  \n\t"
+                  "pand      %%mm1, %%mm5     \n\t"
+                  "movq      %%mm1, %%mm7     \n\t"
+                  "movq      8(%%edi), %%mm6  \n\t"
+                  "pandn     %%mm6, %%mm7     \n\t"
+                  "por       %%mm7, %%mm5     \n\t"
+                  "movq      %%mm5, 8(%%edi)  \n\t"
+
+                  "movq      16(%%esi), %%mm6 \n\t"
+                  "pand      %%mm2, %%mm6     \n\t"
+                  "movq      %%mm2, %%mm4     \n\t"
+                  "movq      16(%%edi), %%mm7 \n\t"
+                  "pandn     %%mm7, %%mm4     \n\t"
+                  "por       %%mm4, %%mm6     \n\t"
+                  "movq      %%mm6, 16(%%edi) \n\t"
+
+                  "movq      24(%%esi), %%mm7 \n\t"
+                  "pand      %%mm3, %%mm7     \n\t"
+                  "movq      %%mm3, %%mm5     \n\t"
+                  "movq      24(%%edi), %%mm4 \n\t"
+                  "pandn     %%mm4, %%mm5     \n\t"
+                  "por       %%mm5, %%mm7     \n\t"
+                  "movq      %%mm7, 24(%%edi) \n\t"
+
+                  "addl      $32, %%esi       \n\t" // inc by 32 bytes processed
+                  "addl      $32, %%edi       \n\t"
+                  "subl      $8, %%ecx        \n\t" // dec by 8 pixels processed
+                  "ja        mainloop32       \n\t"
+
+                "mainloop32end:               \n\t"
+// preload        "movl      diff, %%ecx      \n\t" // (diff is in eax)
+                  "movl      %%eax, %%ecx     \n\t"
+                  "cmpl      $0, %%ecx        \n\t"
+                  "jz        end32            \n\t"
+// preload        "movl      mask, %%edx      \n\t"
+                  "sall      $24, %%edx       \n\t" // low byte => high byte
+
+                "secondloop32:                \n\t"
+                  "sall      %%edx            \n\t" // move high bit to CF
+                  "jnc       skip32           \n\t" // if CF = 0
+                  "movl      (%%esi), %%eax   \n\t"
+                  "movl      %%eax, (%%edi)   \n\t"
+
+                "skip32:                      \n\t"
+                  "addl      $4, %%esi        \n\t"
+                  "addl      $4, %%edi        \n\t"
+                  "decl      %%ecx            \n\t"
+                  "jnz       secondloop32     \n\t"
+
+                "end32:                       \n\t"
+                  "EMMS                       \n\t" // DONE
+
+                  :                                 // output regs (none)
+
+                  : "S" (srcptr),      // esi       // input regs
+                    "D" (dstptr),      // edi
+                    "a" (diff),        // eax
+#ifndef __PIC__
+                    "b" (unmask),      // ebx       // Global Offset Table idx
+#endif
+                    "c" (len),         // ecx
+                    "d" (mask)         // edx
+
+                  : "%esi", "%edi", "%eax",         // clobber list
+                    "%ecx", "%edx"
+#if 0  /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */
+                  , "%mm0", "%mm1", "%mm2", "%mm3",
+                    "%mm4", "%mm5", "%mm6", "%mm7"
+#endif
+               );
+            }
+            else /* mmx _not supported - Use modified C routine */
+            {
+               register png_uint_32 i;
+               png_uint_32 initial_val = 4 * png_pass_start[png_ptr->pass];
+                 // png.c:  png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
+               register int stride = 4 * png_pass_inc[png_ptr->pass];
+                 // png.c:  png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
+               register int rep_bytes = 4 * png_pass_width[png_ptr->pass];
+                 // png.c:  png_pass_width[] = {8, 4, 4, 2, 2, 1, 1};
+               register png_uint_32 final_val = 4 * png_ptr->width;
+
+               srcptr = png_ptr->row_buf + 1 + initial_val;
+               dstptr = row + initial_val;
+
+               for (i = initial_val; i < final_val; i += stride)
+               {
+                  png_memcpy(dstptr, srcptr, rep_bytes);
+                  srcptr += stride;
+                  dstptr += stride;
+               }
+            } /* end of else */
+
+            break;
+         }       // end 32 bpp
+
+         case 48:       // png_ptr->row_info.pixel_depth
+         {
+            png_bytep srcptr;
+            png_bytep dstptr;
+
+            if (mmx_supported)
+            {
+               png_uint_32 len;
+               int diff;
+#ifndef __PIC__
+               int unmask = ~mask;
+#else
+               _unmask = ~mask;            // global variable for -fPIC version
+#endif
+               srcptr = png_ptr->row_buf + 1;
+               dstptr = row;
+               len  = png_ptr->width &~7;  // reduce to multiple of 8
+               diff = png_ptr->width & 7;  // amount lost
+
+               __asm__ (
+#ifdef __PIC__
+                  "movd      _unmask, %%mm7   \n\t" // load bit pattern
+#else
+// preload        "movd      unmask, %%mm7    \n\t" // (unmask is in ebx)
+                  "movd      %%ebx, %%mm7     \n\t" // load bit pattern (unmask)
+#endif
+                  "psubb     %%mm6, %%mm6     \n\t" // zero mm6
+                  "punpcklbw %%mm7, %%mm7     \n\t"
+                  "punpcklwd %%mm7, %%mm7     \n\t"
+                  "punpckldq %%mm7, %%mm7     \n\t" // fill reg with 8 masks
+
+                  "movq      _mask48_0, %%mm0 \n\t"
+                  "movq      _mask48_1, %%mm1 \n\t"
+                  "movq      _mask48_2, %%mm2 \n\t"
+                  "movq      _mask48_3, %%mm3 \n\t"
+                  "movq      _mask48_4, %%mm4 \n\t"
+                  "movq      _mask48_5, %%mm5 \n\t"
+
+                  "pand      %%mm7, %%mm0     \n\t"
+                  "pand      %%mm7, %%mm1     \n\t"
+                  "pand      %%mm7, %%mm2     \n\t"
+                  "pand      %%mm7, %%mm3     \n\t"
+                  "pand      %%mm7, %%mm4     \n\t"
+                  "pand      %%mm7, %%mm5     \n\t"
+
+                  "pcmpeqb   %%mm6, %%mm0     \n\t"
+                  "pcmpeqb   %%mm6, %%mm1     \n\t"
+                  "pcmpeqb   %%mm6, %%mm2     \n\t"
+                  "pcmpeqb   %%mm6, %%mm3     \n\t"
+                  "pcmpeqb   %%mm6, %%mm4     \n\t"
+                  "pcmpeqb   %%mm6, %%mm5     \n\t"
+
+// preload        "movl      len, %%ecx       \n\t" // load length of line
+// preload        "movl      srcptr, %%esi    \n\t" // load source
+// preload        "movl      dstptr, %%edi    \n\t" // load dest
+
+                  "cmpl      $0, %%ecx        \n\t"
+                  "jz        mainloop48end    \n\t"
+
+                "mainloop48:                  \n\t"
+                  "movq      (%%esi), %%mm7   \n\t"
+                  "pand      %%mm0, %%mm7     \n\t"
+                  "movq      %%mm0, %%mm6     \n\t"
+                  "pandn     (%%edi), %%mm6   \n\t"
+                  "por       %%mm6, %%mm7     \n\t"
+                  "movq      %%mm7, (%%edi)   \n\t"
+
+                  "movq      8(%%esi), %%mm6  \n\t"
+                  "pand      %%mm1, %%mm6     \n\t"
+                  "movq      %%mm1, %%mm7     \n\t"
+                  "pandn     8(%%edi), %%mm7  \n\t"
+                  "por       %%mm7, %%mm6     \n\t"
+                  "movq      %%mm6, 8(%%edi)  \n\t"
+
+                  "movq      16(%%esi), %%mm6 \n\t"
+                  "pand      %%mm2, %%mm6     \n\t"
+                  "movq      %%mm2, %%mm7     \n\t"
+                  "pandn     16(%%edi), %%mm7 \n\t"
+                  "por       %%mm7, %%mm6     \n\t"
+                  "movq      %%mm6, 16(%%edi) \n\t"
+
+                  "movq      24(%%esi), %%mm7 \n\t"
+                  "pand      %%mm3, %%mm7     \n\t"
+                  "movq      %%mm3, %%mm6     \n\t"
+                  "pandn     24(%%edi), %%mm6 \n\t"
+                  "por       %%mm6, %%mm7     \n\t"
+                  "movq      %%mm7, 24(%%edi) \n\t"
+
+                  "movq      32(%%esi), %%mm6 \n\t"
+                  "pand      %%mm4, %%mm6     \n\t"
+                  "movq      %%mm4, %%mm7     \n\t"
+                  "pandn     32(%%edi), %%mm7 \n\t"
+                  "por       %%mm7, %%mm6     \n\t"
+                  "movq      %%mm6, 32(%%edi) \n\t"
+
+                  "movq      40(%%esi), %%mm7 \n\t"
+                  "pand      %%mm5, %%mm7     \n\t"
+                  "movq      %%mm5, %%mm6     \n\t"
+                  "pandn     40(%%edi), %%mm6 \n\t"
+                  "por       %%mm6, %%mm7     \n\t"
+                  "movq      %%mm7, 40(%%edi) \n\t"
+
+                  "addl      $48, %%esi       \n\t" // inc by 48 bytes processed
+                  "addl      $48, %%edi       \n\t"
+                  "subl      $8, %%ecx        \n\t" // dec by 8 pixels processed
+
+                  "ja        mainloop48       \n\t"
+
+                "mainloop48end:               \n\t"
+// preload        "movl      diff, %%ecx      \n\t" // (diff is in eax)
+                  "movl      %%eax, %%ecx     \n\t"
+                  "cmpl      $0, %%ecx        \n\t"
+                  "jz        end48            \n\t"
+// preload        "movl      mask, %%edx      \n\t"
+                  "sall      $24, %%edx       \n\t" // make low byte, high byte
+
+                "secondloop48:                \n\t"
+                  "sall      %%edx            \n\t" // move high bit to CF
+                  "jnc       skip48           \n\t" // if CF = 0
+                  "movl      (%%esi), %%eax   \n\t"
+                  "movl      %%eax, (%%edi)   \n\t"
+
+                "skip48:                      \n\t"
+                  "addl      $4, %%esi        \n\t"
+                  "addl      $4, %%edi        \n\t"
+                  "decl      %%ecx            \n\t"
+                  "jnz       secondloop48     \n\t"
+
+                "end48:                       \n\t"
+                  "EMMS                       \n\t" // DONE
+
+                  :                                 // output regs (none)
+
+                  : "S" (srcptr),      // esi       // input regs
+                    "D" (dstptr),      // edi
+                    "a" (diff),        // eax
+#ifndef __PIC__
+                    "b" (unmask),      // ebx       // Global Offset Table idx
+#endif
+                    "c" (len),         // ecx
+                    "d" (mask)         // edx
+
+                  : "%esi", "%edi", "%eax",         // clobber list
+                    "%ecx", "%edx"
+#if 0  /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */
+                  , "%mm0", "%mm1", "%mm2", "%mm3",
+                    "%mm4", "%mm5", "%mm6", "%mm7"
+#endif
+               );
+            }
+            else /* mmx _not supported - Use modified C routine */
+            {
+               register png_uint_32 i;
+               png_uint_32 initial_val = 6 * png_pass_start[png_ptr->pass];
+                 // png.c:  png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
+               register int stride = 6 * png_pass_inc[png_ptr->pass];
+                 // png.c:  png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
+               register int rep_bytes = 6 * png_pass_width[png_ptr->pass];
+                 // png.c:  png_pass_width[] = {8, 4, 4, 2, 2, 1, 1};
+               register png_uint_32 final_val = 6 * png_ptr->width;
+
+               srcptr = png_ptr->row_buf + 1 + initial_val;
+               dstptr = row + initial_val;
+
+               for (i = initial_val; i < final_val; i += stride)
+               {
+                  png_memcpy(dstptr, srcptr, rep_bytes);
+                  srcptr += stride;
+                  dstptr += stride;
+               } 
+            } /* end of else */
+
+            break;
+         }       // end 48 bpp
+
+         case 64:       // png_ptr->row_info.pixel_depth
+         {
+            png_bytep srcptr;
+            png_bytep dstptr;
+            register png_uint_32 i;
+            png_uint_32 initial_val = 8 * png_pass_start[png_ptr->pass];
+              // png.c:  png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
+            register int stride = 8 * png_pass_inc[png_ptr->pass];
+              // png.c:  png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
+            register int rep_bytes = 8 * png_pass_width[png_ptr->pass];
+              // png.c:  png_pass_width[] = {8, 4, 4, 2, 2, 1, 1};
+            register png_uint_32 final_val = 8 * png_ptr->width;
+
+            srcptr = png_ptr->row_buf + 1 + initial_val;
+            dstptr = row + initial_val;
+
+            for (i = initial_val; i < final_val; i += stride)
+            {
+               png_memcpy(dstptr, srcptr, rep_bytes);
+               srcptr += stride;
+               dstptr += stride;
+            } 
+            break;
+         }       // end 64 bpp
+
+         default:   // png_ptr->row_info.pixel_depth != 1,2,4,8,16,24,32,48,64
+         {
+            // this should never happen
+            fprintf(stderr,
+              "libpng internal error:  png_ptr->row_info.pixel_depth = %d\n",
+              png_ptr->row_info.pixel_depth);
+            fflush(stderr);
+            break;
+         }
+      } /* end switch (png_ptr->row_info.pixel_depth) */
+
+   } /* end if (non-trivial mask) */
+
+} /* end png_combine_row() */
+
+#endif /* PNG_HAVE_ASSEMBLER_COMBINE_ROW */
+
+
+
+#if defined(PNG_READ_INTERLACING_SUPPORTED)
+#if defined(PNG_HAVE_ASSEMBLER_READ_INTERLACE)
+
+/* png_do_read_interlace() is called after any 16-bit to 8-bit conversion
+ * has taken place.  [GRR: what other steps come before and/or after?]
+ */
+
+void
+png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
+   png_uint_32 transformations)
+{
+/*
+fprintf(stderr, "GRR DEBUG:  entering png_do_read_interlace()\n");
+if (row == NULL) fprintf(stderr, "GRR DEBUG:  row == NULL\n");
+if (row_info == NULL) fprintf(stderr, "GRR DEBUG:  row_info == NULL\n");
+fflush(stderr);
+ */
+   png_debug(1,"in png_do_read_interlace\n");
+
+   if (mmx_supported == 2)
+       mmx_supported = mmxsupport();
+/*
+{
+fprintf(stderr, "GRR DEBUG:  calling mmxsupport()\n");
+fprintf(stderr, "GRR DEBUG:  done with mmxsupport() (mmx_supported = %d)\n", mmx_supported);
+}
+ */
+
+/*
+this one happened on first row due to weirdness with mmxsupport():
+if (row == NULL) fprintf(stderr, "GRR DEBUG:  now row == NULL!!!\n");
+  row was in ebx, and even though nothing touched ebx, it still got wiped...
+  [weird side effect of CPUID instruction?]
+if (row_info == NULL) fprintf(stderr, "GRR DEBUG:  now row_info == NULL!!!\n");
+ */
+   if (row != NULL && row_info != NULL)
+   {
+      png_uint_32 final_width;
+
+      final_width = row_info->width * png_pass_inc[pass];
+
+/*
+fprintf(stderr, "GRR DEBUG:  png_do_read_interlace() row_info->width = %d, final_width = %d\n", row_info->width, final_width);
+fprintf(stderr, "GRR DEBUG:  png_do_read_interlace() pixel_depth = %d\n", row_info->pixel_depth);
+fflush(stderr);
+ */
+      switch (row_info->pixel_depth)
+      {
+         case 1:
+         {
+            png_bytep sp, dp;
+            int sshift, dshift;
+            int s_start, s_end, s_inc;
+            png_byte v;
+            png_uint_32 i;
+            int j;
+
+            sp = row + (png_size_t)((row_info->width - 1) >> 3);
+            dp = row + (png_size_t)((final_width - 1) >> 3);
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+            if (transformations & PNG_PACKSWAP)
+            {
+               sshift = (int)((row_info->width + 7) & 7);
+               dshift = (int)((final_width + 7) & 7);
+               s_start = 7;
+               s_end = 0;
+               s_inc = -1;
+            }
+            else
+#endif
+            {
+               sshift = 7 - (int)((row_info->width + 7) & 7);
+               dshift = 7 - (int)((final_width + 7) & 7);
+               s_start = 0;
+               s_end = 7;
+               s_inc = 1;
+            }
+
+            for (i = row_info->width; i; i--)
+            {
+               v = (png_byte)((*sp >> sshift) & 0x1);
+               for (j = 0; j < png_pass_inc[pass]; j++)
+               {
+                  *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
+                  *dp |= (png_byte)(v << dshift);
+                  if (dshift == s_end)
+                  {
+                     dshift = s_start;
+                     dp--;
+                  }
+                  else
+                     dshift += s_inc;
+               }
+               if (sshift == s_end)
+               {
+                  sshift = s_start;
+                  sp--;
+               }
+               else
+                  sshift += s_inc;
+            }
+            break;
+         }
+
+         case 2:
+         {
+            png_bytep sp, dp;
+            int sshift, dshift;
+            int s_start, s_end, s_inc;
+            png_uint_32 i;
+
+            sp = row + (png_size_t)((row_info->width - 1) >> 2);
+            dp = row + (png_size_t)((final_width - 1) >> 2);
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+            if (transformations & PNG_PACKSWAP)
+            {
+               sshift = (png_size_t)(((row_info->width + 3) & 3) << 1);
+               dshift = (png_size_t)(((final_width + 3) & 3) << 1);
+               s_start = 6;
+               s_end = 0;
+               s_inc = -2;
+            }
+            else
+#endif
+            {
+               sshift = (png_size_t)((3 - ((row_info->width + 3) & 3)) << 1);
+               dshift = (png_size_t)((3 - ((final_width + 3) & 3)) << 1);
+               s_start = 0;
+               s_end = 6;
+               s_inc = 2;
+            }
+
+            for (i = row_info->width; i; i--)
+            {
+               png_byte v;
+               int j;
+
+               v = (png_byte)((*sp >> sshift) & 0x3);
+               for (j = 0; j < png_pass_inc[pass]; j++)
+               {
+                  *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
+                  *dp |= (png_byte)(v << dshift);
+                  if (dshift == s_end)
+                  {
+                     dshift = s_start;
+                     dp--;
+                  }
+                  else
+                     dshift += s_inc;
+               }
+               if (sshift == s_end)
+               {
+                  sshift = s_start;
+                  sp--;
+               }
+               else
+                  sshift += s_inc;
+            }
+            break;
+         }
+
+         case 4:
+         {
+            png_bytep sp, dp;
+            int sshift, dshift;
+            int s_start, s_end, s_inc;
+            png_uint_32 i;
+
+            sp = row + (png_size_t)((row_info->width - 1) >> 1);
+            dp = row + (png_size_t)((final_width - 1) >> 1);
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+            if (transformations & PNG_PACKSWAP)
+            {
+               sshift = (png_size_t)(((row_info->width + 1) & 1) << 2);
+               dshift = (png_size_t)(((final_width + 1) & 1) << 2);
+               s_start = 4;
+               s_end = 0;
+               s_inc = -4;
+            }
+            else
+#endif
+            {
+               sshift = (png_size_t)((1 - ((row_info->width + 1) & 1)) << 2);
+               dshift = (png_size_t)((1 - ((final_width + 1) & 1)) << 2);
+               s_start = 0;
+               s_end = 4;
+               s_inc = 4;
+            }
+
+            for (i = row_info->width; i; i--)
+            {
+               png_byte v;
+               int j;
+
+               v = (png_byte)((*sp >> sshift) & 0xf);
+               for (j = 0; j < png_pass_inc[pass]; j++)
+               {
+                  *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
+                  *dp |= (png_byte)(v << dshift);
+                  if (dshift == s_end)
+                  {
+                     dshift = s_start;
+                     dp--;
+                  }
+                  else
+                     dshift += s_inc;
+               }
+               if (sshift == s_end)
+               {
+                  sshift = s_start;
+                  sp--;
+               }
+               else
+                  sshift += s_inc;
+            }
+            break;
+         }
+
+         //====================================================================
+
+         default:  // 8-bit or larger (this is where the routine is modified)
+         {
+//          static unsigned long long _const4 = 0x0000000000FFFFFFLL;  no good
+//          static unsigned long long const4 = 0x0000000000FFFFFFLL;   no good
+//          unsigned long long _const4 = 0x0000000000FFFFFFLL;         no good
+//          unsigned long long const4 = 0x0000000000FFFFFFLL;          no good
+            png_bytep sptr, dp;
+            png_uint_32 i;
+            png_size_t pixel_bytes;
+            int width = row_info->width;
+
+            pixel_bytes = (row_info->pixel_depth >> 3);
+
+            // point sptr at the last pixel in the pre-expanded row:
+            sptr = row + (width - 1) * pixel_bytes;
+
+            // point dp at the last pixel position in the expanded row:
+            dp = row + (final_width - 1) * pixel_bytes;
+
+            // New code by Nirav Chhatrapati - Intel Corporation
+
+            if (mmx_supported)  // use MMX code if machine supports it
+            {
+               //--------------------------------------------------------------
+               if (pixel_bytes == 3)
+               {
+                  if (((pass == 0) || (pass == 1)) && width)
+                  {
+                     __asm__ (
+                        "subl $21, %%edi         \n\t"
+                                     // (png_pass_inc[pass] - 1)*pixel_bytes
+
+                     ".loop3_pass0:              \n\t"
+                        "movd (%%esi), %%mm0     \n\t" // x x x x x 2 1 0
+                        "pand _const4, %%mm0     \n\t" // z z z z z 2 1 0
+                        "movq %%mm0, %%mm1       \n\t" // z z z z z 2 1 0
+                        "psllq $16, %%mm0        \n\t" // z z z 2 1 0 z z
+                        "movq %%mm0, %%mm2       \n\t" // z z z 2 1 0 z z
+                        "psllq $24, %%mm0        \n\t" // 2 1 0 z z z z z
+                        "psrlq $8, %%mm1         \n\t" // z z z z z z 2 1
+                        "por %%mm2, %%mm0        \n\t" // 2 1 0 2 1 0 z z
+                        "por %%mm1, %%mm0        \n\t" // 2 1 0 2 1 0 2 1
+                        "movq %%mm0, %%mm3       \n\t" // 2 1 0 2 1 0 2 1
+                        "psllq $16, %%mm0        \n\t" // 0 2 1 0 2 1 z z
+                        "movq %%mm3, %%mm4       \n\t" // 2 1 0 2 1 0 2 1
+                        "punpckhdq %%mm0, %%mm3  \n\t" // 0 2 1 0 2 1 0 2
+                        "movq %%mm4, 16(%%edi)   \n\t"
+                        "psrlq $32, %%mm0        \n\t" // z z z z 0 2 1 0
+                        "movq %%mm3, 8(%%edi)    \n\t"
+                        "punpckldq %%mm4, %%mm0  \n\t" // 1 0 2 1 0 2 1 0
+                        "subl $3, %%esi          \n\t"
+                        "movq %%mm0, (%%edi)     \n\t"
+                        "subl $24, %%edi         \n\t"
+                        "decl %%ecx              \n\t"
+                        "jnz .loop3_pass0        \n\t"
+                        "EMMS                    \n\t" // DONE
+
+                        :                              // output regs (none)
+
+                        : "S" (sptr),      // esi      // input regs
+                          "D" (dp),        // edi
+                          "c" (width)      // ecx
+// doesn't work           "i" (0x0000000000FFFFFFLL)   // %1 (a.k.a. _const4)
+
+                        : "%esi", "%edi", "%ecx"       // clobber list
+#if 0  /* %mm0, ..., %mm4 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                        , "%mm0", "%mm1", "%mm2", "%mm3", "%mm4"
+#endif
+                     );
+                  }
+                  else if (((pass == 2) || (pass == 3)) && width)
+                  {
+                     __asm__ (
+                        "subl $9, %%edi          \n\t"
+                                     // (png_pass_inc[pass] - 1)*pixel_bytes
+
+                     ".loop3_pass2:              \n\t"
+                        "movd (%%esi), %%mm0     \n\t" // x x x x x 2 1 0
+                        "pand _const4, %%mm0     \n\t" // z z z z z 2 1 0
+                        "movq %%mm0, %%mm1       \n\t" // z z z z z 2 1 0
+                        "psllq $16, %%mm0        \n\t" // z z z 2 1 0 z z
+                        "movq %%mm0, %%mm2       \n\t" // z z z 2 1 0 z z
+                        "psllq $24, %%mm0        \n\t" // 2 1 0 z z z z z
+                        "psrlq $8, %%mm1         \n\t" // z z z z z z 2 1
+                        "por %%mm2, %%mm0        \n\t" // 2 1 0 2 1 0 z z
+                        "por %%mm1, %%mm0        \n\t" // 2 1 0 2 1 0 2 1
+                        "movq %%mm0, 4(%%edi)    \n\t"
+                        "psrlq $16, %%mm0        \n\t" // z z 2 1 0 2 1 0
+                        "subl $3, %%esi          \n\t"
+                        "movd %%mm0, (%%edi)     \n\t"
+                        "subl $12, %%edi         \n\t"
+                        "decl %%ecx              \n\t"
+                        "jnz .loop3_pass2        \n\t"
+                        "EMMS                    \n\t" // DONE
+
+                        :                              // output regs (none)
+
+                        : "S" (sptr),      // esi      // input regs
+                          "D" (dp),        // edi
+                          "c" (width)      // ecx
+
+                        : "%esi", "%edi", "%ecx"       // clobber list
+#if 0  /* %mm0, ..., %mm2 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                        , "%mm0", "%mm1", "%mm2"
+#endif
+                     );
+                  }
+                  else if (width) /* && ((pass == 4) || (pass == 5)) */
+                  {
+                     int width_mmx = ((width >> 1) << 1) - 8;   // GRR:  huh?
+                     if (width_mmx < 0)
+                         width_mmx = 0;
+                     width -= width_mmx;        // 8 or 9 pix, 24 or 27 bytes
+                     if (width_mmx)
+                     {
+                        __asm__ (
+                           "subl $3, %%esi          \n\t"
+                           "subl $9, %%edi          \n\t"
+                                        // (png_pass_inc[pass] - 1)*pixel_bytes
+
+                        ".loop3_pass4:              \n\t"
+                           "movq (%%esi), %%mm0     \n\t" // x x 5 4 3 2 1 0
+                           "movq %%mm0, %%mm1       \n\t" // x x 5 4 3 2 1 0
+                           "movq %%mm0, %%mm2       \n\t" // x x 5 4 3 2 1 0
+                           "psllq $24, %%mm0        \n\t" // 4 3 2 1 0 z z z
+                           "pand _const4, %%mm0     \n\t" // z z z z z 2 1 0
+                           "psrlq $24, %%mm2        \n\t" // z z z x x 5 4 3
+                           "por %%mm1, %%mm0        \n\t" // 4 3 2 1 0 2 1 0
+                           "movq %%mm2, %%mm3       \n\t" // z z z x x 5 4 3
+                           "psllq $8, %%mm2         \n\t" // z z x x 5 4 3 z
+                           "movq %%mm0, (%%edi)     \n\t"
+                           "psrlq $16, %%mm3        \n\t" // z z z z z x x 5
+                           "pand _const6, %%mm3     \n\t" // z z z z z z z 5
+                           "por %%mm3, %%mm2        \n\t" // z z x x 5 4 3 5
+                           "subl $6, %%esi          \n\t"
+                           "movd %%mm2, 8(%%edi)    \n\t"
+                           "subl $12, %%edi         \n\t"
+                           "subl $2, %%ecx          \n\t"
+                           "jnz .loop3_pass4        \n\t"
+                           "EMMS                    \n\t" // DONE
+
+                           :                              // output regs (none)
+
+                           : "S" (sptr),      // esi      // input regs
+                             "D" (dp),        // edi
+                             "c" (width_mmx)  // ecx
+
+                           : "%esi", "%edi", "%ecx"       // clobber list
+#if 0  /* %mm0, ..., %mm3 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           , "%mm0", "%mm1", "%mm2", "%mm3"
+#endif
+                        );
+                     }
+
+                     sptr -= width_mmx*3;
+                     dp -= width_mmx*6;
+                     for (i = width; i; i--)
+                     {
+                        png_byte v[8];
+                        int j;
+
+                        png_memcpy(v, sptr, 3);
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                        {
+                           png_memcpy(dp, v, 3);
+                           dp -= 3;
+                        }
+                        sptr -= 3;
+                     }
+                  }
+               } /* end of pixel_bytes == 3 */
+
+               //--------------------------------------------------------------
+               else if (pixel_bytes == 1)
+               {
+                  if (((pass == 0) || (pass == 1)) && width)
+                  {
+                     int width_mmx = ((width >> 2) << 2);
+                     width -= width_mmx;        // 0-3 pixels => 0-3 bytes
+                     if (width_mmx)
+                     {
+                        __asm__ (
+                           "subl $3, %%esi          \n\t"
+                           "subl $31, %%edi         \n\t"
+
+                        ".loop1_pass0:              \n\t"
+                           "movd (%%esi), %%mm0     \n\t" // x x x x 3 2 1 0
+                           "movq %%mm0, %%mm1       \n\t" // x x x x 3 2 1 0
+                           "punpcklbw %%mm0, %%mm0  \n\t" // 3 3 2 2 1 1 0 0
+                           "movq %%mm0, %%mm2       \n\t" // 3 3 2 2 1 1 0 0
+                           "punpcklwd %%mm0, %%mm0  \n\t" // 1 1 1 1 0 0 0 0
+                           "movq %%mm0, %%mm3       \n\t" // 1 1 1 1 0 0 0 0
+                           "punpckldq %%mm0, %%mm0  \n\t" // 0 0 0 0 0 0 0 0
+                           "punpckhdq %%mm3, %%mm3  \n\t" // 1 1 1 1 1 1 1 1
+                           "movq %%mm0, (%%edi)     \n\t"
+                           "punpckhwd %%mm2, %%mm2  \n\t" // 3 3 3 3 2 2 2 2
+                           "movq %%mm3, 8(%%edi)    \n\t"
+                           "movq %%mm2, %%mm4       \n\t" // 3 3 3 3 2 2 2 2
+                           "punpckldq %%mm2, %%mm2  \n\t" // 2 2 2 2 2 2 2 2
+                           "punpckhdq %%mm4, %%mm4  \n\t" // 3 3 3 3 3 3 3 3
+                           "movq %%mm2, 16(%%edi)   \n\t"
+                           "subl $4, %%esi          \n\t"
+                           "movq %%mm4, 24(%%edi)   \n\t"
+                           "subl $32, %%edi         \n\t"
+                           "subl $4, %%ecx          \n\t"
+                           "jnz .loop1_pass0        \n\t"
+                           "EMMS                    \n\t" // DONE
+
+                           :                              // output regs (none)
+
+                           : "S" (sptr),      // esi      // input regs
+                             "D" (dp),        // edi
+                             "c" (width_mmx)  // ecx
+
+                           : "%esi", "%edi", "%ecx"       // clobber list
+#if 0  /* %mm0, ..., %mm4 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           , "%mm0", "%mm1", "%mm2", "%mm3", "%mm4"
+#endif
+                        );
+                     }
+
+                     sptr -= width_mmx;
+                     dp -= width_mmx*8;
+                     for (i = width; i; i--)
+                     {
+                        int j;
+
+                       /* I simplified this part in version 1.0.4e
+                        * here and in several other instances where
+                        * pixel_bytes == 1  -- GR-P
+                        *
+                        * Original code:
+                        *
+                        * png_byte v[8];
+                        * png_memcpy(v, sptr, pixel_bytes);
+                        * for (j = 0; j < png_pass_inc[pass]; j++)
+                        * {
+                        *    png_memcpy(dp, v, pixel_bytes);
+                        *    dp -= pixel_bytes;
+                        * }
+                        * sptr -= pixel_bytes;
+                        *
+                        * Replacement code is in the next three lines:
+                        */
+
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                           *dp-- = *sptr;
+                        --sptr;
+                     }
+                  }
+                  else if (((pass == 2) || (pass == 3)) && width)
+                  {
+                     int width_mmx = ((width >> 2) << 2);
+                     width -= width_mmx;        // 0-3 pixels => 0-3 bytes
+                     if (width_mmx)
+                     {
+                        __asm__ (
+                           "subl $3, %%esi          \n\t"
+                           "subl $15, %%edi         \n\t"
+
+                        ".loop1_pass2:              \n\t"
+                           "movd (%%esi), %%mm0     \n\t" // x x x x 3 2 1 0
+                           "punpcklbw %%mm0, %%mm0  \n\t" // 3 3 2 2 1 1 0 0
+                           "movq %%mm0, %%mm1       \n\t" // 3 3 2 2 1 1 0 0
+                           "punpcklwd %%mm0, %%mm0  \n\t" // 1 1 1 1 0 0 0 0
+                           "punpckhwd %%mm1, %%mm1  \n\t" // 3 3 3 3 2 2 2 2
+                           "movq %%mm0, (%%edi)     \n\t"
+                           "subl $4, %%esi          \n\t"
+                           "movq %%mm1, 8(%%edi)    \n\t"
+                           "subl $16, %%edi         \n\t"
+                           "subl $4, %%ecx          \n\t"
+                           "jnz .loop1_pass2        \n\t"
+                           "EMMS                    \n\t" // DONE
+
+                           :                              // output regs (none)
+
+                           : "S" (sptr),      // esi      // input regs
+                             "D" (dp),        // edi
+                             "c" (width_mmx)  // ecx
+
+                           : "%esi", "%edi", "%ecx"       // clobber list
+#if 0  /* %mm0, %mm1 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           , "%mm0", "%mm1"
+#endif
+                        );
+                     }
+
+                     sptr -= width_mmx;
+                     dp -= width_mmx*4;
+                     for (i = width; i; i--)
+                     {
+                        int j;
+
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                           *dp-- = *sptr;
+                        --sptr;
+                     }
+                  }
+                  else if (width)  /* && ((pass == 4) || (pass == 5)) */
+                  {
+                     int width_mmx = ((width >> 3) << 3);
+                     width -= width_mmx;        // 0-3 pixels => 0-3 bytes
+                     if (width_mmx)
+                     {
+                        __asm__ (
+                           "subl $7, %%esi          \n\t"
+                           "subl $15, %%edi         \n\t"
+
+                        ".loop1_pass4:              \n\t"
+                           "movq (%%esi), %%mm0     \n\t" // 7 6 5 4 3 2 1 0
+                           "movq %%mm0, %%mm1       \n\t" // 7 6 5 4 3 2 1 0
+                           "punpcklbw %%mm0, %%mm0  \n\t" // 3 3 2 2 1 1 0 0
+                           "punpckhbw %%mm1, %%mm1  \n\t" // 7 7 6 6 5 5 4 4
+                           "movq %%mm1, 8(%%edi)    \n\t"
+                           "subl $8, %%esi          \n\t"
+                           "movq %%mm0, (%%edi)     \n\t"
+                           "subl $16, %%edi         \n\t"
+                           "subl $8, %%ecx          \n\t"
+                           "jnz .loop1_pass4        \n\t"
+                           "EMMS                    \n\t" // DONE
+
+                           :                              // output regs (none)
+
+                           : "S" (sptr),      // esi      // input regs
+                             "D" (dp),        // edi
+                             "c" (width_mmx)  // ecx
+
+                           : "%esi", "%edi", "%ecx"       // clobber list
+#if 0  /* %mm0, %mm1 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           , "%mm0", "%mm1"
+#endif
+                        );
+                     }
+
+                     sptr -= width_mmx;
+                     dp -= width_mmx*2;
+                     for (i = width; i; i--)
+                     {
+                        int j;
+
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                           *dp-- = *sptr;
+                        --sptr;
+                     }
+                  }
+               } /* end of pixel_bytes == 1 */
+
+               //--------------------------------------------------------------
+               else if (pixel_bytes == 2)
+               {
+                  if (((pass == 0) || (pass == 1)) && width)
+                  {
+                     int width_mmx = ((width >> 1) << 1);
+                     width -= width_mmx;        // 0,1 pixels => 0,2 bytes
+                     if (width_mmx)
+                     {
+                        __asm__ (
+                           "subl $2, %%esi          \n\t"
+                           "subl $30, %%edi         \n\t"
+
+                        ".loop2_pass0:              \n\t"
+                           "movd (%%esi), %%mm0     \n\t" // x x x x 3 2 1 0
+                           "punpcklwd %%mm0, %%mm0  \n\t" // 3 2 3 2 1 0 1 0
+                           "movq %%mm0, %%mm1       \n\t" // 3 2 3 2 1 0 1 0
+                           "punpckldq %%mm0, %%mm0  \n\t" // 1 0 1 0 1 0 1 0
+                           "punpckhdq %%mm1, %%mm1  \n\t" // 3 2 3 2 3 2 3 2
+                           "movq %%mm0, (%%edi)     \n\t"
+                           "movq %%mm0, 8(%%edi)    \n\t"
+                           "movq %%mm1, 16(%%edi)   \n\t"
+                           "subl $4, %%esi          \n\t"
+                           "movq %%mm1, 24(%%edi)   \n\t"
+                           "subl $32, %%edi         \n\t"
+                           "subl $2, %%ecx          \n\t"
+                           "jnz .loop2_pass0        \n\t"
+                           "EMMS                    \n\t" // DONE
+
+                           :                              // output regs (none)
+
+                           : "S" (sptr),      // esi      // input regs
+                             "D" (dp),        // edi
+                             "c" (width_mmx)  // ecx
+
+                           : "%esi", "%edi", "%ecx"       // clobber list
+#if 0  /* %mm0, %mm1 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           , "%mm0", "%mm1"
+#endif
+                        );
+                     }
+
+                     sptr -= (width_mmx*2 - 2); // sign fixed
+                     dp -= (width_mmx*16 - 2);  // sign fixed
+                     for (i = width; i; i--)
+                     {
+                        png_byte v[8];
+                        int j;
+                        sptr -= 2;
+                        png_memcpy(v, sptr, 2);
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                        {
+                           dp -= 2;
+                           png_memcpy(dp, v, 2);
+                        }
+                     }
+                  }
+                  else if (((pass == 2) || (pass == 3)) && width)
+                  {
+                     int width_mmx = ((width >> 1) << 1) ;
+                     width -= width_mmx;        // 0,1 pixels => 0,2 bytes
+                     if (width_mmx)
+                     {
+                        __asm__ (
+                           "subl $2, %%esi          \n\t"
+                           "subl $14, %%edi         \n\t"
+
+                        ".loop2_pass2:              \n\t"
+                           "movd (%%esi), %%mm0     \n\t" // x x x x 3 2 1 0
+                           "punpcklwd %%mm0, %%mm0  \n\t" // 3 2 3 2 1 0 1 0
+                           "movq %%mm0, %%mm1       \n\t" // 3 2 3 2 1 0 1 0
+                           "punpckldq %%mm0, %%mm0  \n\t" // 1 0 1 0 1 0 1 0
+                           "punpckhdq %%mm1, %%mm1  \n\t" // 3 2 3 2 3 2 3 2
+                           "movq %%mm0, (%%edi)     \n\t"
+                           "subl $4, %%esi          \n\t"
+                           "movq %%mm1, 8(%%edi)    \n\t"
+                           "subl $16, %%edi         \n\t"
+                           "subl $2, %%ecx          \n\t"
+                           "jnz .loop2_pass2        \n\t"
+                           "EMMS                    \n\t" // DONE
+
+                           :                              // output regs (none)
+
+                           : "S" (sptr),      // esi      // input regs
+                             "D" (dp),        // edi
+                             "c" (width_mmx)  // ecx
+
+                           : "%esi", "%edi", "%ecx"       // clobber list
+#if 0  /* %mm0, %mm1 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           , "%mm0", "%mm1"
+#endif
+                        );
+                     }
+
+                     sptr -= (width_mmx*2 - 2); // sign fixed
+                     dp -= (width_mmx*8 - 2);   // sign fixed
+                     for (i = width; i; i--)
+                     {
+                        png_byte v[8];
+                        int j;
+                        sptr -= 2;
+                        png_memcpy(v, sptr, 2);
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                        {
+                           dp -= 2;
+                           png_memcpy(dp, v, 2);
+                        }
+                     }
+                  }
+                  else if (width)  // pass == 4 or 5
+                  {
+                     int width_mmx = ((width >> 1) << 1) ;
+                     width -= width_mmx;        // 0,1 pixels => 0,2 bytes
+                     if (width_mmx)
+                     {
+                        __asm__ (
+                           "subl $2, %%esi          \n\t"
+                           "subl $6, %%edi          \n\t"
+
+                        ".loop2_pass4:              \n\t"
+                           "movd (%%esi), %%mm0     \n\t" // x x x x 3 2 1 0
+                           "punpcklwd %%mm0, %%mm0  \n\t" // 3 2 3 2 1 0 1 0
+                           "subl $4, %%esi          \n\t"
+                           "movq %%mm0, (%%edi)     \n\t"
+                           "subl $8, %%edi          \n\t"
+                           "subl $2, %%ecx          \n\t"
+                           "jnz .loop2_pass4        \n\t"
+                           "EMMS                    \n\t" // DONE
+
+                           :                              // output regs (none)
+
+                           : "S" (sptr),      // esi      // input regs
+                             "D" (dp),        // edi
+                             "c" (width_mmx)  // ecx
+
+                           : "%esi", "%edi", "%ecx"       // clobber list
+#if 0  /* %mm0 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           , "%mm0"
+#endif
+                        );
+                     }
+
+                     sptr -= (width_mmx*2 - 2); // sign fixed
+                     dp -= (width_mmx*4 - 2);   // sign fixed
+                     for (i = width; i; i--)
+                     {
+                        png_byte v[8];
+                        int j;
+                        sptr -= 2;
+                        png_memcpy(v, sptr, 2);
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                        {
+                           dp -= 2;
+                           png_memcpy(dp, v, 2);
+                        }
+                     }
+                  }
+               } /* end of pixel_bytes == 2 */
+
+               //--------------------------------------------------------------
+               else if (pixel_bytes == 4)
+               {
+                  if (((pass == 0) || (pass == 1)) && width)
+                  {
+                     int width_mmx = ((width >> 1) << 1);
+                     width -= width_mmx;        // 0,1 pixels => 0,4 bytes
+/*
+fprintf(stderr, "GRR DEBUG:  png_do_read_interlace() pass = %d, width_mmx = %d, width = %d\n", pass, width_mmx, width);
+fprintf(stderr, "            sptr = 0x%08lx, dp = 0x%08lx\n", (unsigned long)sptr, (unsigned long)dp);
+fflush(stderr);
+ */
+                     if (width_mmx)
+                     {
+#ifdef GRR_DEBUG
+                        FILE *junk = fopen("junk.4bytes", "wb");
+                        if (junk)
+                           fclose(junk);
+#endif /* GRR_DEBUG */
+                        __asm__ (
+                           "subl $4, %%esi          \n\t"
+                           "subl $60, %%edi         \n\t"
+
+                        ".loop4_pass0:              \n\t"
+                           "movq (%%esi), %%mm0     \n\t" // 7 6 5 4 3 2 1 0
+                           "movq %%mm0, %%mm1       \n\t" // 7 6 5 4 3 2 1 0
+                           "punpckldq %%mm0, %%mm0  \n\t" // 3 2 1 0 3 2 1 0
+                           "punpckhdq %%mm1, %%mm1  \n\t" // 7 6 5 4 7 6 5 4
+                           "movq %%mm0, (%%edi)     \n\t"
+                           "movq %%mm0, 8(%%edi)    \n\t"
+                           "movq %%mm0, 16(%%edi)   \n\t"
+                           "movq %%mm0, 24(%%edi)   \n\t"
+                           "movq %%mm1, 32(%%edi)   \n\t"
+                           "movq %%mm1, 40(%%edi)   \n\t"
+                           "movq %%mm1, 48(%%edi)   \n\t"
+                           "subl $8, %%esi          \n\t"
+                           "movq %%mm1, 56(%%edi)   \n\t"
+                           "subl $64, %%edi         \n\t"
+                           "subl $2, %%ecx          \n\t"
+                           "jnz .loop4_pass0        \n\t"
+                           "EMMS                    \n\t" // DONE
+
+                           :                              // output regs (none)
+
+                           : "S" (sptr),      // esi      // input regs
+                             "D" (dp),        // edi
+                             "c" (width_mmx)  // ecx
+
+                           : "%esi", "%edi", "%ecx"       // clobber list
+#if 0  /* %mm0, %mm1 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           , "%mm0", "%mm1"
+#endif
+                        );
+                     }
+
+                     sptr -= (width_mmx*4 - 4); // sign fixed
+                     dp -= (width_mmx*32 - 4);  // sign fixed
+                     for (i = width; i; i--)
+                     {
+                        png_byte v[8];
+                        int j;
+                        sptr -= 4;
+                        png_memcpy(v, sptr, 4);
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                        {
+                           dp -= 4;
+                           png_memcpy(dp, v, 4);
+                        }
+                     }
+                  }
+                  else if (((pass == 2) || (pass == 3)) && width)
+                  {
+                     int width_mmx = ((width >> 1) << 1);
+                     width -= width_mmx;        // 0,1 pixels => 0,4 bytes
+                     if (width_mmx)
+                     {
+                        __asm__ (
+                           "subl $4, %%esi          \n\t"
+                           "subl $28, %%edi         \n\t"
+
+                        ".loop4_pass2:              \n\t"
+                           "movq (%%esi), %%mm0     \n\t" // 7 6 5 4 3 2 1 0
+                           "movq %%mm0, %%mm1       \n\t" // 7 6 5 4 3 2 1 0
+                           "punpckldq %%mm0, %%mm0  \n\t" // 3 2 1 0 3 2 1 0
+                           "punpckhdq %%mm1, %%mm1  \n\t" // 7 6 5 4 7 6 5 4
+                           "movq %%mm0, (%%edi)     \n\t"
+                           "movq %%mm0, 8(%%edi)    \n\t"
+                           "movq %%mm1, 16(%%edi)   \n\t"
+                           "movq %%mm1, 24(%%edi)   \n\t"
+                           "subl $8, %%esi          \n\t"
+                           "subl $32, %%edi         \n\t"
+                           "subl $2, %%ecx          \n\t"
+                           "jnz .loop4_pass2        \n\t"
+                           "EMMS                    \n\t" // DONE
+
+                           :                              // output regs (none)
+
+                           : "S" (sptr),      // esi      // input regs
+                             "D" (dp),        // edi
+                             "c" (width_mmx)  // ecx
+
+                           : "%esi", "%edi", "%ecx"       // clobber list
+#if 0  /* %mm0, %mm1 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           , "%mm0", "%mm1"
+#endif
+                        );
+                     }
+
+                     sptr -= (width_mmx*4 - 4); // sign fixed
+                     dp -= (width_mmx*16 - 4);  // sign fixed
+                     for (i = width; i; i--)
+                     {
+                        png_byte v[8];
+                        int j;
+                        sptr -= 4;
+                        png_memcpy(v, sptr, 4);
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                        {
+                           dp -= 4;
+                           png_memcpy(dp, v, 4);
+                        }
+                     }
+                  }
+                  else if (width)  // pass == 4 or 5
+                  {
+                     int width_mmx = ((width >> 1) << 1) ;
+                     width -= width_mmx;        // 0,1 pixels => 0,4 bytes
+                     if (width_mmx)
+                     {
+                        __asm__ (
+                           "subl $4, %%esi          \n\t"
+                           "subl $12, %%edi         \n\t"
+
+                        ".loop4_pass4:              \n\t"
+                           "movq (%%esi), %%mm0     \n\t" // 7 6 5 4 3 2 1 0
+                           "movq %%mm0, %%mm1       \n\t" // 7 6 5 4 3 2 1 0
+                           "punpckldq %%mm0, %%mm0  \n\t" // 3 2 1 0 3 2 1 0
+                           "punpckhdq %%mm1, %%mm1  \n\t" // 7 6 5 4 7 6 5 4
+                           "movq %%mm0, (%%edi)     \n\t"
+                           "subl $8, %%esi          \n\t"
+                           "movq %%mm1, 8(%%edi)    \n\t"
+                           "subl $16, %%edi         \n\t"
+                           "subl $2, %%ecx          \n\t"
+                           "jnz .loop4_pass4        \n\t"
+                           "EMMS                    \n\t" // DONE
+
+                           :                              // output regs (none)
+
+                           : "S" (sptr),      // esi      // input regs
+                             "D" (dp),        // edi
+                             "c" (width_mmx)  // ecx
+
+                           : "%esi", "%edi", "%ecx"       // clobber list
+#if 0  /* %mm0, %mm1 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           , "%mm0", "%mm1"
+#endif
+                        );
+                     }
+
+                     sptr -= (width_mmx*4 - 4); // sign fixed
+                     dp -= (width_mmx*8 - 4);   // sign fixed
+                     for (i = width; i; i--)
+                     {
+                        png_byte v[8];
+                        int j;
+                        sptr -= 4;
+                        png_memcpy(v, sptr, 4);
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                        {
+                           dp -= 4;
+                           png_memcpy(dp, v, 4);
+                        }
+                     }
+                  }
+               } /* end of pixel_bytes == 4 */
+
+#define STILL_WORKING_ON_THIS
+#ifdef STILL_WORKING_ON_THIS  // GRR: should work, but needs testing
+                              //      (special 64-bit version of rpng2)
+
+               //--------------------------------------------------------------
+               else if (pixel_bytes == 8)
+               {
+                  // GRR NOTE:  no need to combine passes here!
+                  if (((pass == 0) || (pass == 1)) && width)
+                  {
+                     // source is 8-byte RRGGBBAA
+                     // dest is 64-byte RRGGBBAA RRGGBBAA RRGGBBAA RRGGBBAA ...
+#ifdef GRR_DEBUG
+                        FILE *junk = fopen("junk.8bytes", "wb");
+                        if (junk)
+                            fclose(junk);
+#endif /* GRR_DEBUG */
+                        __asm__ (
+                           "subl $56, %%edi         \n\t" // start of last block
+
+                        ".loop8_pass0:              \n\t"
+                           "movq (%%esi), %%mm0     \n\t" // 7 6 5 4 3 2 1 0
+                           "movq %%mm0, (%%edi)     \n\t"
+                           "movq %%mm0, 8(%%edi)    \n\t"
+                           "movq %%mm0, 16(%%edi)   \n\t"
+                           "movq %%mm0, 24(%%edi)   \n\t"
+                           "movq %%mm0, 32(%%edi)   \n\t"
+                           "movq %%mm0, 40(%%edi)   \n\t"
+                           "movq %%mm0, 48(%%edi)   \n\t"
+                           "subl $8, %%esi          \n\t"
+                           "movq %%mm0, 56(%%edi)   \n\t"
+                           "subl $64, %%edi         \n\t"
+                           "decl %%ecx              \n\t"
+                           "jnz .loop8_pass0        \n\t"
+                           "EMMS                    \n\t" // DONE
+
+                           :                              // output regs (none)
+
+                           : "S" (sptr),      // esi      // input regs
+                             "D" (dp),        // edi
+                             "c" (width)      // ecx
+
+                           : "%esi", "%edi", "%ecx"       // clobber list
+#if 0  /* %mm0 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           , "%mm0"
+#endif
+                        );
+                  }
+                  else if (((pass == 2) || (pass == 3)) && width)
+                  {
+                     // source is 8-byte RRGGBBAA
+                     // dest is 32-byte RRGGBBAA RRGGBBAA RRGGBBAA RRGGBBAA
+                     int width_mmx = ((width >> 1) << 1) ;
+                     width -= width_mmx;
+                     if (width_mmx)
+                     {
+                        __asm__ (
+                           "subl $24, %%edi         \n\t" // start of last block
+
+                        ".loop8_pass2:              \n\t"
+                           "movq (%%esi), %%mm0     \n\t" // 7 6 5 4 3 2 1 0
+                           "movq %%mm0, (%%edi)     \n\t"
+                           "movq %%mm0, 8(%%edi)    \n\t"
+                           "movq %%mm0, 16(%%edi)   \n\t"
+                           "subl $8, %%esi          \n\t"
+                           "movq %%mm0, 24(%%edi)   \n\t"
+                           "subl $32, %%edi         \n\t"
+                           "decl %%ecx              \n\t"
+                           "jnz .loop8_pass2        \n\t"
+                           "EMMS                    \n\t" // DONE
+
+                           :                              // output regs (none)
+
+                           : "S" (sptr),      // esi      // input regs
+                             "D" (dp),        // edi
+                             "c" (width)      // ecx
+
+                           : "%esi", "%edi", "%ecx"       // clobber list
+#if 0  /* %mm0 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           , "%mm0"
+#endif
+                        );
+                     }
+                  }
+                  else if (width)  // pass == 4 or 5
+                  {
+                     // source is 8-byte RRGGBBAA
+                     // dest is 16-byte RRGGBBAA RRGGBBAA
+                     int width_mmx = ((width >> 1) << 1) ;
+                     width -= width_mmx;
+                     if (width_mmx)
+                     {
+                        __asm__ (
+                           "subl $8, %%edi          \n\t" // start of last block
+
+                        ".loop8_pass4:              \n\t"
+                           "movq (%%esi), %%mm0     \n\t" // 7 6 5 4 3 2 1 0
+                           "movq %%mm0, (%%edi)     \n\t"
+                           "subl $8, %%esi          \n\t"
+                           "movq %%mm0, 8(%%edi)    \n\t"
+                           "subl $16, %%edi         \n\t"
+                           "decl %%ecx              \n\t"
+                           "jnz .loop8_pass4        \n\t"
+                           "EMMS                    \n\t" // DONE
+
+                           :                              // output regs (none)
+
+                           : "S" (sptr),      // esi      // input regs
+                             "D" (dp),        // edi
+                             "c" (width)      // ecx
+
+                           : "%esi", "%edi", "%ecx"       // clobber list
+#if 0  /* %mm0 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           , "%mm0"
+#endif
+                        );
+                     }
+                  }
+
+               } /* end of pixel_bytes == 8 */
+
+#endif /* STILL_WORKING_ON_THIS */
+
+               //--------------------------------------------------------------
+               else if (pixel_bytes == 6)
+               {
+                  for (i = width; i; i--)
+                  {
+                     png_byte v[8];
+                     int j;
+                     png_memcpy(v, sptr, 6);
+                     for (j = 0; j < png_pass_inc[pass]; j++)
+                     {
+                        png_memcpy(dp, v, 6);
+                        dp -= 6;
+                     }
+                     sptr -= 6;
+                  }
+               } /* end of pixel_bytes == 6 */
+
+               //--------------------------------------------------------------
+               else
+               {
+                  for (i = width; i; i--)
+                  {
+                     png_byte v[8];
+                     int j;
+                     png_memcpy(v, sptr, pixel_bytes);
+                     for (j = 0; j < png_pass_inc[pass]; j++)
+                     {
+                        png_memcpy(dp, v, pixel_bytes);
+                        dp -= pixel_bytes;
+                     }
+                     sptr-= pixel_bytes;
+                  }
+               }
+            } // end of mmx_supported =========================================
+
+            else /* MMX not supported:  use modified C code - takes advantage
+                  *   of inlining of memcpy for a constant */
+                 /* GRR 19991007:  does it?  or should pixel_bytes in each
+                  *   block be replaced with immediate value (e.g., 1)? */
+                 /* GRR 19991017:  replaced with constants in each case */
+            {
+               if (pixel_bytes == 1)
+               {
+                  for (i = width; i; i--)
+                  {
+                     int j;
+                     for (j = 0; j < png_pass_inc[pass]; j++)
+                        *dp-- = *sptr;
+                     --sptr;
+                  }
+               }
+               else if (pixel_bytes == 3)
+               {
+                  for (i = width; i; i--)
+                  {
+                     png_byte v[8];
+                     int j;
+                     png_memcpy(v, sptr, 3);
+                     for (j = 0; j < png_pass_inc[pass]; j++)
+                     {
+                        png_memcpy(dp, v, 3);
+                        dp -= 3;
+                     }
+                     sptr -= 3;
+                  }
+               }
+               else if (pixel_bytes == 2)
+               {
+                  for (i = width; i; i--)
+                  {
+                     png_byte v[8];
+                     int j;
+                     png_memcpy(v, sptr, 2);
+                     for (j = 0; j < png_pass_inc[pass]; j++)
+                     {
+                        png_memcpy(dp, v, 2);
+                        dp -= 2;
+                     }
+                     sptr -= 2;
+                  }
+               }
+               else if (pixel_bytes == 4)
+               {
+                  for (i = width; i; i--)
+                  {
+                     png_byte v[8];
+                     int j;
+                     png_memcpy(v, sptr, 4);
+                     for (j = 0; j < png_pass_inc[pass]; j++)
+                     {
+                        png_memcpy(dp, v, 4);
+                        dp -= 4;
+                     }
+                     sptr -= 4;
+                  }
+               }
+               else if (pixel_bytes == 6)
+               {
+                  for (i = width; i; i--)
+                  {
+                     png_byte v[8];
+                     int j;
+                     png_memcpy(v, sptr, 6);
+                     for (j = 0; j < png_pass_inc[pass]; j++)
+                     {
+                        png_memcpy(dp, v, 6);
+                        dp -= 6;
+                     }
+                     sptr -= 6;
+                  }
+               }
+               else if (pixel_bytes == 8)
+               {
+                  for (i = width; i; i--)
+                  {
+                     png_byte v[8];
+                     int j;
+                     png_memcpy(v, sptr, 8);
+                     for (j = 0; j < png_pass_inc[pass]; j++)
+                     {
+                        png_memcpy(dp, v, 8);
+                        dp -= 8;
+                     }
+                     sptr -= 8;
+                  }
+               }
+               else     // GRR:  should never be reached
+               {
+                  for (i = width; i; i--)
+                  {
+                     png_byte v[8];
+                     int j;
+                     png_memcpy(v, sptr, pixel_bytes);
+                     for (j = 0; j < png_pass_inc[pass]; j++)
+                     {
+                        png_memcpy(dp, v, pixel_bytes);
+                        dp -= pixel_bytes;
+                     }
+                     sptr -= pixel_bytes;
+                  }
+               }
+
+            } /* end if (MMX not supported) */
+            break;
+         }
+      } /* end switch (row_info->pixel_depth) */
+
+      row_info->width = final_width;
+      row_info->rowbytes = ((final_width *
+         (png_uint_32)row_info->pixel_depth + 7) >> 3);
+   }
+
+} /* end png_do_read_interlace() */
+
+#endif /* PNG_HAVE_ASSEMBLER_READ_INTERLACE */
+#endif /* PNG_READ_INTERLACING_SUPPORTED */
+
+
+// These variables are utilized in the functions below.  They are declared
+// globally here to ensure alignment on 8-byte boundaries.
+
+union uAll {
+   long long use;
+   double  align;
+} LBCarryMask = {0x0101010101010101LL},
+  HBClearMask = {0x7f7f7f7f7f7f7f7fLL},
+  ActiveMask, ActiveMask2, ActiveMaskEnd, ShiftBpp, ShiftRem;
+
+
+// Optimized code for PNG Average filter decoder
+void
+png_read_filter_row_mmx_avg(png_row_infop row_info, png_bytep row,
+                            png_bytep prev_row)
+{
+   int bpp;
+// int diff;  GRR: global now (shortened to dif/_dif)
+
+   bpp = (row_info->pixel_depth + 7) >> 3;  // Get # bytes per pixel
+   _FullLength  = row_info->rowbytes;        // # of bytes to filter
+   __asm__ (
+      // Init address pointers and offset
+//GRR "movl row, %%edi             \n\t" // edi ==> Avg(x)
+      "xorl %%ebx, %%ebx           \n\t" // ebx ==> x
+      "movl %%edi, %%edx           \n\t"
+//GRR "movl prev_row, %%esi        \n\t" // esi ==> Prior(x)
+//GRR "subl bpp, %%edx             \n\t" // (bpp is preloaded into ecx)
+      "subl %%ecx, %%edx           \n\t" // edx ==> Raw(x-bpp)
+
+      "xorl %%eax,%%eax            \n\t"
+
+      // Compute the Raw value for the first bpp bytes
+      //    Raw(x) = Avg(x) + (Prior(x)/2)
+   "avg_rlp:                       \n\t"
+      "movb (%%esi,%%ebx,),%%al    \n\t" // Load al with Prior(x)
+      "incl %%ebx                  \n\t"
+      "shrb %%al                   \n\t" // divide by 2
+      "addb -1(%%edi,%%ebx,),%%al  \n\t" // add Avg(x); -1 to offset inc ebx
+//GRR "cmpl bpp, %%ebx             \n\t" // (bpp is preloaded into ecx)
+      "cmpl %%ecx, %%ebx           \n\t"
+      "movb %%al,-1(%%edi,%%ebx,)  \n\t" // write Raw(x); -1 to offset inc ebx
+      "jb avg_rlp                  \n\t" // mov does not affect flags
+
+      // get # of bytes to alignment
+      "movl %%edi, _dif            \n\t" // take start of row
+      "addl %%ebx, _dif            \n\t" // add bpp
+      "addl $0xf, _dif             \n\t" // add 7+8 to incr past alignment bdry
+      "andl $0xfffffff8, _dif      \n\t" // mask to alignment boundary
+      "subl %%edi, _dif            \n\t" // subtract from start => value ebx at alignment
+      "jz avg_go                   \n\t"
+
+      // fix alignment
+      // Compute the Raw value for the bytes up to the alignment boundary
+      //    Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2)
+      "xorl %%ecx, %%ecx           \n\t"
+   "avg_lp1:                       \n\t"
+      "xorl %%eax, %%eax           \n\t"
+      "movb (%%esi,%%ebx,), %%cl   \n\t" // load cl with Prior(x)
+      "movb (%%edx,%%ebx,), %%al   \n\t" // load al with Raw(x-bpp)
+      "addw %%cx, %%ax             \n\t"
+      "incl %%ebx                  \n\t"
+      "shrw %%ax                   \n\t" // divide by 2
+      "addb -1(%%edi,%%ebx,), %%al \n\t" // add Avg(x); -1 to offset inc ebx
+      "cmpl _dif, %%ebx            \n\t" // check if at alignment boundary
+      "movb %%al, -1(%%edi,%%ebx,) \n\t" // write Raw(x); -1 to offset inc ebx
+      "jb avg_lp1                  \n\t" // repeat until at alignment boundary
+
+   "avg_go:                        \n\t"
+      "movl _FullLength, %%eax     \n\t"
+      "movl %%eax, %%ecx           \n\t"
+      "subl %%ebx, %%eax           \n\t" // subtract alignment fix
+      "andl $0x00000007, %%eax     \n\t" // calc bytes over mult of 8
+      "subl %%eax, %%ecx           \n\t" // drop over bytes from original length
+      "movl %%ecx, _MMXLength      \n\t"
+
+      : // output regs/vars here, e.g., "=m" (_MMXLength) instead of final instr
+
+      : "S" (prev_row),  // esi          // input regs
+        "D" (row),       // edi
+        "c" (bpp)        // ecx
+
+      : "%eax", "%ebx", "%ecx",          // clobber list
+        "%edx", "%edi", "%esi"
+// GRR: INCLUDE "memory" as clobbered? (_dif, _MMXLength)     PROBABLY
+   );
+
+#ifdef GRR_GCC_MMX_CONVERTED
+   // Now do the math for the rest of the row
+   switch ( bpp )
+   {
+      case 3:
+      {
+         ActiveMask.use  = 0x0000000000ffffff;
+         ShiftBpp.use = 24;    // == 3 * 8
+         ShiftRem.use = 40;    // == 64 - 24
+         __asm__ (
+            // Re-init address pointers and offset
+            "movq $ActiveMask, %%mm7     \n\t"
+            "movl _dif, %%ebx            \n\t" // ebx ==> x = offset to alignment boundary
+            "movq $LBCarryMask, %%mm5    \n\t"
+            "movl row, %%edi             \n\t" // edi ==> Avg(x)
+            "movq $HBClearMask, %%mm4    \n\t"
+            "movl prev_row, %%esi        \n\t" // esi ==> Prior(x)
+            // PRIME the pump (load the first Raw(x-bpp) data set)
+            "movq -8(%%edi,%%ebx,), %%mm2 \n\t" // Load previous aligned 8 bytes
+                                          // (we correct position in loop below)
+         "avg_3lp:                       \n\t"
+            "movq (%%edi,%%ebx,), %%mm0  \n\t" // Load mm0 with Avg(x)
+            // Add (Prev_row/2) to Average
+            "movq %%mm5, %%mm3           \n\t"
+            "psrlq $ShiftRem, %%mm2      \n\t" // Correct position Raw(x-bpp) data
+            "movq (%%esi,%%ebx,), %%mm1  \n\t" // Load mm1 with Prior(x)
+            "movq %%mm7, %%mm6           \n\t"
+            "pand %%mm1, %%mm3           \n\t" // get lsb for each prev_row byte
+            "psrlq $1, %%mm1             \n\t" // divide prev_row bytes by 2
+            "pand  %%mm4, %%mm1          \n\t" // clear invalid bit 7 of each byte
+            "paddb %%mm1, %%mm0          \n\t" // add (Prev_row/2) to Avg for each byte
+            // Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry
+            "movq %%mm3, %%mm1           \n\t" // now use mm1 for getting LBCarrys
+            "pand %%mm2, %%mm1           \n\t" // get LBCarrys for each byte where both
+                               // lsb's were == 1 (Only valid for active group)
+            "psrlq $1, %%mm2             \n\t" // divide raw bytes by 2
+            "pand  %%mm4, %%mm2          \n\t" // clear invalid bit 7 of each byte
+            "paddb %%mm1, %%mm2          \n\t" // add LBCarrys to (Raw(x-bpp)/2) for each byte
+            "pand %%mm6, %%mm2           \n\t" // Leave only Active Group 1 bytes to add to Avg
+            "paddb %%mm2, %%mm0          \n\t" // add (Raw/2) + LBCarrys to Avg for each Active
+                               //  byte
+            // Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry
+            "psllq $ShiftBpp, %%mm6      \n\t" // shift the mm6 mask to cover bytes 3-5
+            "movq %%mm0, %%mm2           \n\t" // mov updated Raws to mm2
+            "psllq $ShiftBpp, %%mm2      \n\t" // shift data to position correctly
+            "movq %%mm3, %%mm1           \n\t" // now use mm1 for getting LBCarrys
+            "pand %%mm2, %%mm1           \n\t" // get LBCarrys for each byte where both
+                               // lsb's were == 1 (Only valid for active group)
+            "psrlq $1, %%mm2             \n\t" // divide raw bytes by 2
+            "pand  %%mm4, %%mm2          \n\t" // clear invalid bit 7 of each byte
+            "paddb %%mm1, %%mm2          \n\t" // add LBCarrys to (Raw(x-bpp)/2) for each byte
+            "pand %%mm6, %%mm2           \n\t" // Leave only Active Group 2 bytes to add to Avg
+            "paddb %%mm2, %%mm0          \n\t" // add (Raw/2) + LBCarrys to Avg for each Active
+                               //  byte
+
+            // Add 3rd active group (Raw(x-bpp)/2) to Average with LBCarry
+            "psllq $ShiftBpp, %%mm6      \n\t" // shift the mm6 mask to cover the last two
+                                 // bytes
+            "movq %%mm0, %%mm2           \n\t" // mov updated Raws to mm2
+            "psllq $ShiftBpp, %%mm2      \n\t" // shift data to position correctly
+                              // Data only needs to be shifted once here to
+                              // get the correct x-bpp offset.
+            "movq %%mm3, %%mm1           \n\t" // now use mm1 for getting LBCarrys
+            "pand %%mm2, %%mm1           \n\t" // get LBCarrys for each byte where both
+                              // lsb's were == 1 (Only valid for active group)
+            "psrlq $1, %%mm2             \n\t" // divide raw bytes by 2
+            "pand  %%mm4, %%mm2          \n\t" // clear invalid bit 7 of each byte
+            "paddb %%mm1, %%mm2          \n\t" // add LBCarrys to (Raw(x-bpp)/2) for each byte
+            "pand %%mm6, %%mm2           \n\t" // Leave only Active Group 2 bytes to add to Avg
+            "addl $8, %%ebx              \n\t"
+            "paddb %%mm2, %%mm0          \n\t" // add (Raw/2) + LBCarrys to Avg for each Active
+                                               // byte
+            // Now ready to write back to memory
+            "movq %%mm0, -8(%%edi,%%ebx,) \n\t"
+            // Move updated Raw(x) to use as Raw(x-bpp) for next loop
+            "cmpl _MMXLength, %%ebx      \n\t"
+            "movq %%mm0, %%mm2           \n\t" // mov updated Raw(x) to mm2
+            "jb avg_3lp                  \n\t"
+
+            : // output regs/vars go here, e.g.:  "=m" (memory_var)
+
+            : "S" (prev_row),  // esi          // input regs
+              "D" (row)        // edi
+
+            : "%ebx", "%edi", "%esi"           // clobber list
+//            GRR: INCLUDE "memory" as clobbered? (_dif, _MMXLength)   PROBABLY
+//          , "%mm0", "%mm1", "%mm2", "%mm3",
+//            "%mm4", "%mm5", "%mm6", "%mm7"
+         );
+      }
+      break;  // end 3 bpp
+
+      case 6:
+      case 4:
+      //case 7:   // who wrote this?  PNG doesn't support 5 or 7 bytes/pixel
+      //case 5:
+      {
+         ActiveMask.use  = 0xffffffffffffffff;  // use shift below to clear
+                                                // appropriate inactive bytes
+         ShiftBpp.use = bpp << 3;
+         ShiftRem.use = 64 - ShiftBpp.use;
+         __asm__ (
+            "movq $HBClearMask, %%mm4    \n\t"
+
+            // Re-init address pointers and offset
+            "movl _dif, %%ebx            \n\t" // ebx ==> x = offset to alignment boundary
+
+            // Load ActiveMask and clear all bytes except for 1st active group
+            "movq $ActiveMask, %%mm7     \n\t"
+            "movl row, %%edi             \n\t" // edi ==> Avg(x)
+            "psrlq $ShiftRem, %%mm7      \n\t"
+            "movl prev_row, %%esi        \n\t" // esi ==> Prior(x)
+            "movq %%mm7, %%mm6           \n\t"
+            "movq $LBCarryMask, %%mm5    \n\t"
+            "psllq $ShiftBpp, %%mm6      \n\t" // Create mask for 2nd active group
+
+            // PRIME the pump (load the first Raw(x-bpp) data set
+            "movq -8(%%edi,%%ebx,), %%mm2 \n\t" // Load previous aligned 8 bytes
+                                          // (we correct position in loop below)
+         "avg_4lp:                       \n\t"
+            "movq (%%edi,%%ebx,), %%mm0  \n\t"
+            "psrlq $ShiftRem, %%mm2      \n\t" // shift data to position correctly
+            "movq (%%esi,%%ebx,), %%mm1  \n\t"
+            // Add (Prev_row/2) to Average
+            "movq %%mm5, %%mm3           \n\t"
+            "pand %%mm1, %%mm3           \n\t" // get lsb for each prev_row byte
+            "psrlq $1, %%mm1             \n\t" // divide prev_row bytes by 2
+            "pand  %%mm4, %%mm1          \n\t" // clear invalid bit 7 of each byte
+            "paddb %%mm1, %%mm0          \n\t" // add (Prev_row/2) to Avg for each byte
+            // Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry
+            "movq %%mm3, %%mm1           \n\t" // now use mm1 for getting LBCarrys
+            "pand %%mm2, %%mm1           \n\t" // get LBCarrys for each byte where both
+                              // lsb's were == 1 (Only valid for active group)
+            "psrlq $1, %%mm2             \n\t" // divide raw bytes by 2
+            "pand  %%mm4, %%mm2          \n\t" // clear invalid bit 7 of each byte
+            "paddb %%mm1, %%mm2          \n\t" // add LBCarrys to (Raw(x-bpp)/2) for each byte
+            "pand %%mm7, %%mm2           \n\t" // Leave only Active Group 1 bytes to add to Avg
+            "paddb %%mm2, %%mm0          \n\t" // add (Raw/2) + LBCarrys to Avg for each Active
+                              // byte
+            // Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry
+            "movq %%mm0, %%mm2           \n\t" // mov updated Raws to mm2
+            "psllq $ShiftBpp, %%mm2      \n\t" // shift data to position correctly
+            "addl $8, %%ebx              \n\t"
+            "movq %%mm3, %%mm1           \n\t" // now use mm1 for getting LBCarrys
+            "pand %%mm2, %%mm1           \n\t" // get LBCarrys for each byte where both
+                              // lsb's were == 1 (Only valid for active group)
+            "psrlq $1, %%mm2             \n\t" // divide raw bytes by 2
+            "pand  %%mm4, %%mm2          \n\t" // clear invalid bit 7 of each byte
+            "paddb %%mm1, %%mm2          \n\t" // add LBCarrys to (Raw(x-bpp)/2) for each byte
+            "pand %%mm6, %%mm2           \n\t" // Leave only Active Group 2 bytes to add to Avg
+            "paddb %%mm2, %%mm0          \n\t" // add (Raw/2) + LBCarrys to Avg for each Active
+                              // byte
+            "cmpl _MMXLength, %%ebx      \n\t"
+            // Now ready to write back to memory
+            "movq %%mm0, -8(%%edi,%%ebx,) \n\t"
+            // Prep Raw(x-bpp) for next loop
+            "movq %%mm0, %%mm2           \n\t" // mov updated Raws to mm2
+            "jb avg_4lp                  \n\t"
+
+            : // FIXASM: output regs/vars go here, e.g.:  "=m" (memory_var)
+
+            : // FIXASM: input regs, e.g.:  "c" (count), "S" (src), "D" (dest)
+
+            : "%ebx", "%edi", "%esi", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7" // CHECKASM: clobber list
+         );
+      }
+      break;  // end 4,6 bpp
+
+      case 2:
+      {
+         ActiveMask.use  = 0x000000000000ffff;
+         ShiftBpp.use = 24;   // == 3 * 8
+         ShiftRem.use = 40;   // == 64 - 24
+         __asm__ (
+            // Load ActiveMask
+            "movq $ActiveMask, %%mm7     \n\t"
+            // Re-init address pointers and offset
+            "movl _dif, %%ebx            \n\t" // ebx ==> x = offset to alignment boundary
+            "movq $LBCarryMask, %%mm5    \n\t"
+            "movl row, %%edi             \n\t" // edi ==> Avg(x)
+            "movq $HBClearMask, %%mm4    \n\t"
+            "movl prev_row, %%esi        \n\t" // esi ==> Prior(x)
+            // PRIME the pump (load the first Raw(x-bpp) data set
+            "movq -8(%%edi,%%ebx,), %%mm2 \n\t" // Load previous aligned 8 bytes
+                              // (we correct position in loop below)
+         "avg_2lp:                       \n\t"
+            "movq (%%edi,%%ebx,), %%mm0  \n\t"
+            "psllq $ShiftRem, %%mm2      \n\t" // shift data to position correctly
+            "movq (%%esi,%%ebx,), %%mm1  \n\t"
+            // Add (Prev_row/2) to Average
+            "movq %%mm5, %%mm3           \n\t"
+            "pand %%mm1, %%mm3           \n\t" // get lsb for each prev_row byte
+            "psrlq $1, %%mm1             \n\t" // divide prev_row bytes by 2
+            "pand  %%mm4, %%mm1          \n\t" // clear invalid bit 7 of each byte
+            "movq %%mm7, %%mm6           \n\t"
+            "paddb %%mm1, %%mm0          \n\t" // add (Prev_row/2) to Avg for each byte
+            // Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry
+            "movq %%mm3, %%mm1           \n\t" // now use mm1 for getting LBCarrys
+            "pand %%mm2, %%mm1           \n\t" // get LBCarrys for each byte where both
+                              // lsb's were == 1 (Only valid for active group)
+            "psrlq $1, %%mm2             \n\t" // divide raw bytes by 2
+            "pand  %%mm4, %%mm2          \n\t" // clear invalid bit 7 of each byte
+            "paddb %%mm1, %%mm2          \n\t" // add LBCarrys to (Raw(x-bpp)/2) for each byte
+            "pand %%mm6, %%mm2           \n\t" // Leave only Active Group 1 bytes to add to Avg
+            "paddb %%mm2, %%mm0          \n\t" // add (Raw/2) + LBCarrys to Avg for each Active byte
+            // Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry
+            "psllq $ShiftBpp, %%mm6      \n\t" // shift the mm6 mask to cover bytes 2 & 3
+            "movq %%mm0, %%mm2           \n\t" // mov updated Raws to mm2
+            "psllq $ShiftBpp, %%mm2      \n\t" // shift data to position correctly
+            "movq %%mm3, %%mm1           \n\t" // now use mm1 for getting LBCarrys
+            "pand %%mm2, %%mm1           \n\t" // get LBCarrys for each byte where both
+                                // lsb's were == 1 (Only valid for active group)
+            "psrlq $1, %%mm2             \n\t" // divide raw bytes by 2
+            "pand  %%mm4, %%mm2          \n\t" // clear invalid bit 7 of each byte
+            "paddb %%mm1, %%mm2          \n\t" // add LBCarrys to (Raw(x-bpp)/2) for each byte
+            "pand %%mm6, %%mm2           \n\t" // Leave only Active Group 2 bytes to add to Avg
+            "paddb %%mm2, %%mm0          \n\t" // add (Raw/2) + LBCarrys to Avg for each Active byte
+
+            // Add rdd active group (Raw(x-bpp)/2) to Average with LBCarry
+            "psllq $ShiftBpp, %%mm6      \n\t" // shift the mm6 mask to cover bytes 4 & 5
+            "movq %%mm0, %%mm2           \n\t" // mov updated Raws to mm2
+            "psllq $ShiftBpp, %%mm2      \n\t" // shift data to position correctly
+                                // Data only needs to be shifted once here to
+                                // get the correct x-bpp offset.
+            "movq %%mm3, %%mm1           \n\t" // now use mm1 for getting LBCarrys
+            "pand %%mm2, %%mm1           \n\t" // get LBCarrys for each byte where both
+                                // lsb's were == 1 (Only valid for active group)
+            "psrlq $1, %%mm2             \n\t" // divide raw bytes by 2
+            "pand  %%mm4, %%mm2          \n\t" // clear invalid bit 7 of each byte
+            "paddb %%mm1, %%mm2          \n\t" // add LBCarrys to (Raw(x-bpp)/2) for each byte
+            "pand %%mm6, %%mm2           \n\t" // Leave only Active Group 2 bytes to add to Avg
+            "paddb %%mm2, %%mm0          \n\t" // add (Raw/2) + LBCarrys to Avg for each Active byte
+
+            // Add 4th active group (Raw(x-bpp)/2) to Average with LBCarry
+            "psllq $ShiftBpp, %%mm6      \n\t" // shift the mm6 mask to cover bytes 6 & 7
+            "movq %%mm0, %%mm2           \n\t" // mov updated Raws to mm2
+            "psllq $ShiftBpp, %%mm2      \n\t" // shift data to position correctly
+                                 // Data only needs to be shifted once here to
+                                 // get the correct x-bpp offset.
+            "addl $8, %%ebx              \n\t"
+            "movq %%mm3, %%mm1           \n\t" // now use mm1 for getting LBCarrys
+            "pand %%mm2, %%mm1           \n\t" // get LBCarrys for each byte where both
+                             // lsb's were == 1 (Only valid for active group)
+            "psrlq $1, %%mm2             \n\t" // divide raw bytes by 2
+            "pand  %%mm4, %%mm2          \n\t" // clear invalid bit 7 of each byte
+            "paddb %%mm1, %%mm2          \n\t" // add LBCarrys to (Raw(x-bpp)/2) for each byte
+            "pand %%mm6, %%mm2           \n\t" // Leave only Active Group 2 bytes to add to Avg
+            "paddb %%mm2, %%mm0          \n\t" // add (Raw/2) + LBCarrys to Avg for each Active byte
+
+            "cmpl _MMXLength, %%ebx      \n\t"
+            // Now ready to write back to memory
+            "movq %%mm0, -8(%%edi,%%ebx,) \n\t"
+            // Prep Raw(x-bpp) for next loop
+            "movq %%mm0, %%mm2           \n\t" // mov updated Raws to mm2
+            "jb avg_2lp                  \n\t"
+
+            : // FIXASM: output regs/vars go here, e.g.:  "=m" (memory_var)
+
+            : // FIXASM: input regs, e.g.:  "c" (count), "S" (src), "D" (dest)
+
+            : "%ebx", "%edi", "%esi", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7" // CHECKASM: clobber list
+         );
+      }
+      break;  // end 2 bpp
+
+      case 1:
+      {
+         __asm__ (
+            // Re-init address pointers and offset
+            "movl _dif, %%ebx            \n\t" // ebx ==> x = offset to alignment boundary
+            "movl row, %%edi             \n\t" // edi ==> Avg(x)
+            "cmpl _FullLength, %%ebx     \n\t" // Test if offset at end of array
+            "jnb avg_1end                \n\t"
+            // Do Paeth decode for remaining bytes
+            "movl prev_row, %%esi        \n\t" // esi ==> Prior(x)
+            "movl %%edi, %%edx           \n\t"
+            "xorl %%ecx, %%ecx           \n\t" // zero ecx before using cl & cx in loop below
+            "subl bpp, %%edx             \n\t" // edx ==> Raw(x-bpp)
+         "avg_1lp:                       \n\t"
+            // Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2)
+            "xorl %%eax, %%eax           \n\t"
+            "movb (%%esi,%%ebx,), %%cl   \n\t" // load cl with Prior(x)
+            "movb (%%edx,%%ebx,), %%al   \n\t" // load al with Raw(x-bpp)
+            "addw %%cx, %%ax             \n\t"
+            "incl %%ebx                  \n\t"
+            "shrw %%ax                   \n\t" // divide by 2
+            "addb -1(%%edi,%%ebx,), %%al \n\t" // Add Avg(x); -1 to offset inc ebx
+            "cmpl _FullLength, %%ebx     \n\t" // Check if at end of array
+            "movb %%al, -1(%%edi,%%ebx,) \n\t" // Write back Raw(x);
+                         // mov does not affect flags; -1 to offset inc ebx
+            "jb avg_1lp                  \n\t"
+         "avg_1end:                      \n\t"
+
+            : // FIXASM: output regs/vars go here, e.g.:  "=m" (memory_var)
+
+            : // FIXASM: input regs, e.g.:  "c" (count), "S" (src), "D" (dest)
+
+            : "%eax", "%ebx", "%ecx", "%edx", "%edi", "%esi" // CHECKASM: clobber list
+         );
+      }
+      return;  // end 1 bpp
+
+      case 8:
+      {
+         __asm__ (
+            // Re-init address pointers and offset
+            "movl _dif, %%ebx            \n\t" // ebx ==> x = offset to alignment boundary
+            "movq $LBCarryMask, %%mm5    \n\t"
+            "movl row, %%edi             \n\t" // edi ==> Avg(x)
+            "movq $HBClearMask, %%mm4    \n\t"
+            "movl prev_row, %%esi        \n\t" // esi ==> Prior(x)
+            // PRIME the pump (load the first Raw(x-bpp) data set
+            "movq -8(%%edi,%%ebx,), %%mm2 \n\t" // Load previous aligned 8 bytes
+                                // (NO NEED to correct position in loop below)
+         "avg_8lp:                       \n\t"
+            "movq (%%edi,%%ebx,), %%mm0  \n\t"
+            "movq %%mm5, %%mm3           \n\t"
+            "movq (%%esi,%%ebx,), %%mm1  \n\t"
+            "addl $8, %%ebx              \n\t"
+            "pand %%mm1, %%mm3           \n\t" // get lsb for each prev_row byte
+            "psrlq $1, %%mm1             \n\t" // divide prev_row bytes by 2
+            "pand %%mm2, %%mm3           \n\t" // get LBCarrys for each byte where both
+                                // lsb's were == 1
+            "psrlq $1, %%mm2             \n\t" // divide raw bytes by 2
+            "pand  %%mm4, %%mm1          \n\t" // clear invalid bit 7 of each byte
+            "paddb %%mm3, %%mm0          \n\t" // add LBCarrys to Avg for each byte
+            "pand  %%mm4, %%mm2          \n\t" // clear invalid bit 7 of each byte
+            "paddb %%mm1, %%mm0          \n\t" // add (Prev_row/2) to Avg for each byte
+            "paddb %%mm2, %%mm0          \n\t" // add (Raw/2) to Avg for each byte
+            "cmpl _MMXLength, %%ebx      \n\t"
+            "movq %%mm0, -8(%%edi,%%ebx,) \n\t"
+            "movq %%mm0, %%mm2           \n\t" // reuse as Raw(x-bpp)
+            "jb avg_8lp                  \n\t"
+
+            : // FIXASM: output regs/vars go here, e.g.:  "=m" (memory_var)
+
+            : // FIXASM: input regs, e.g.:  "c" (count), "S" (src), "D" (dest)
+
+            : "%ebx", "%edi", "%esi", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5" // CHECKASM: clobber list
+         );
+      }
+      break;  // end 8 bpp
+
+      default:                  // bpp greater than 8 (!= 1,2,3,4,6,8)
+      {
+
+      GRR:  PRINT ERROR HERE:  SHOULD NEVER BE REACHED (unless smaller than 1?)
+
+        __asm__ (
+            "movq $LBCarryMask, %%mm5    \n\t"
+            // Re-init address pointers and offset
+            "movl _dif, %%ebx            \n\t" // ebx ==> x = offset to alignment boundary
+            "movl row, %%edi             \n\t" // edi ==> Avg(x)
+            "movq $HBClearMask, %%mm4    \n\t"
+            "movl %%edi, %%edx           \n\t"
+            "movl prev_row, %%esi        \n\t" // esi ==> Prior(x)
+            "subl bpp, %%edx             \n\t" // edx ==> Raw(x-bpp)
+         "avg_Alp:                       \n\t"
+            "movq (%%edi,%%ebx,), %%mm0  \n\t"
+            "movq %%mm5, %%mm3           \n\t"
+            "movq (%%esi,%%ebx,), %%mm1  \n\t"
+            "pand %%mm1, %%mm3           \n\t" // get lsb for each prev_row byte
+            "movq (%%edx,%%ebx,), %%mm2  \n\t"
+            "psrlq $1, %%mm1             \n\t" // divide prev_row bytes by 2
+            "pand %%mm2, %%mm3           \n\t" // get LBCarrys for each byte where both
+                                // lsb's were == 1
+            "psrlq $1, %%mm2             \n\t" // divide raw bytes by 2
+            "pand  %%mm4, %%mm1          \n\t" // clear invalid bit 7 of each byte
+            "paddb %%mm3, %%mm0          \n\t" // add LBCarrys to Avg for each byte
+            "pand  %%mm4, %%mm2          \n\t" // clear invalid bit 7 of each byte
+            "paddb %%mm1, %%mm0          \n\t" // add (Prev_row/2) to Avg for each byte
+            "addl $8, %%ebx              \n\t"
+            "paddb %%mm2, %%mm0          \n\t" // add (Raw/2) to Avg for each byte
+            "cmpl _MMXLength, %%ebx      \n\t"
+            "movq %%mm0, -8(%%edi,%%ebx,) \n\t"
+            "jb avg_Alp                  \n\t"
+
+            : // FIXASM: output regs/vars go here, e.g.:  "=m" (memory_var)
+
+            : // FIXASM: input regs, e.g.:  "c" (count), "S" (src), "D" (dest)
+
+            : "%ebx", "%edx", "%edi", "%esi", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5" // CHECKASM: clobber list
+         );
+      }
+      break;
+   }                         // end switch ( bpp )
+
+   __asm__ (
+      // MMX acceleration complete now do clean-up
+      // Check if any remaining bytes left to decode
+      "movl _MMXLength, %%ebx      \n\t" // ebx ==> x = offset bytes remaining after MMX
+      "movl row, %%edi             \n\t" // edi ==> Avg(x)
+      "cmpl _FullLength, %%ebx     \n\t" // Test if offset at end of array
+      "jnb avg_end                 \n\t"
+      // Do Paeth decode for remaining bytes
+      "movl prev_row, %%esi        \n\t" // esi ==> Prior(x)
+      "movl %%edi, %%edx           \n\t"
+      "xorl %%ecx, %%ecx           \n\t" // zero ecx before using cl & cx in loop below
+      "subl bpp, %%edx             \n\t" // edx ==> Raw(x-bpp)
+   "avg_lp2:                       \n\t"
+      // Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2)
+      "xorl %%eax, %%eax           \n\t"
+      "movb (%%esi,%%ebx,), %%cl   \n\t" // load cl with Prior(x)
+      "movb (%%edx,%%ebx,), %%al   \n\t" // load al with Raw(x-bpp)
+      "addw %%cx, %%ax             \n\t"
+      "incl %%ebx                  \n\t"
+      "shrw %%ax                   \n\t" // divide by 2
+      "addb -1(%%edi,%%ebx,), %%al \n\t" // Add Avg(x); -1 to offset inc ebx
+      "cmpl _FullLength, %%ebx     \n\t" // Check if at end of array
+      "movb %%al, -1(%%edi,%%ebx,) \n\t" // Write back Raw(x);
+                       // mov does not affect flags; -1 to offset inc ebx
+      "jb avg_lp2                  \n\t"
+   "avg_end:                       \n\t"
+      "emms                        \n\t" // End MMX instructions; prep for possible FP instrs.
+
+      : // FIXASM: output regs/vars go here, e.g.:  "=m" (memory_var)
+
+      : // FIXASM: input regs, e.g.:  "c" (count), "S" (src), "D" (dest)
+
+      : "%eax", "%ebx", "%ecx", "%edx", "%edi", "%esi" // CHECKASM: clobber list
+   );
+#endif /* GRR_GCC_MMX_CONVERTED */
+}
+
+// Optimized code for PNG Paeth filter decoder
+void
+png_read_filter_row_mmx_paeth(png_row_infop row_info, png_bytep row,
+                              png_bytep prev_row)
+{
+#ifdef GRR_GCC_MMX_CONVERTED
+   int bpp;
+   int patemp, pbtemp, pctemp;
+
+   bpp = (row_info->pixel_depth + 7) >> 3; // Get # bytes per pixel
+   _FullLength  = row_info->rowbytes; // # of bytes to filter
+   __asm__ (
+      "xorl %%ebx, %%ebx           \n\t" // ebx ==> x offset
+      "movl row, %%edi             \n\t"
+      "xorl %%edx, %%edx           \n\t" // edx ==> x-bpp offset
+      "movl prev_row, %%esi        \n\t"
+      "xorl %%eax, %%eax           \n\t"
+
+      // Compute the Raw value for the first bpp bytes
+      // Note: the formula works out to be always
+      //   Paeth(x) = Raw(x) + Prior(x)      where x < bpp
+   "paeth_rlp:                     \n\t"
+      "movb (%%edi,%%ebx,), %%al   \n\t"
+      "addb (%%esi,%%ebx,), %%al   \n\t"
+      "incl %%ebx                  \n\t"
+      "cmpl bpp, %%ebx             \n\t"
+      "movb %%al, -1(%%edi,%%ebx,) \n\t"
+      "jb paeth_rlp                \n\t"
+      // get # of bytes to alignment
+      "movl %%edi, _dif            \n\t" // take start of row
+      "addl %%ebx, _dif            \n\t" // add bpp
+      "xorl %%ecx, %%ecx           \n\t"
+      "addl $0xf, _dif             \n\t" // add 7 + 8 to incr past alignment boundary
+      "andl $0xfffffff8, _dif      \n\t" // mask to alignment boundary
+      "subl %%edi, _dif            \n\t" // subtract from start ==> value ebx at alignment
+      "jz paeth_go                 \n\t"
+      // fix alignment
+   "paeth_lp1:                     \n\t"
+      "xorl %%eax, %%eax           \n\t"
+      // pav = p - a = (a + b - c) - a = b - c
+      "movb (%%esi,%%ebx,), %%al   \n\t" // load Prior(x) into al
+      "movb (%%esi,%%edx,), %%cl   \n\t" // load Prior(x-bpp) into cl
+      "subl %%ecx, %%eax           \n\t" // subtract Prior(x-bpp)
+      "movl %%eax, patemp          \n\t" // Save pav for later use
+      "xorl %%eax, %%eax           \n\t"
+      // pbv = p - b = (a + b - c) - b = a - c
+      "movb (%%edi,%%edx,), %%al   \n\t" // load Raw(x-bpp) into al
+      "subl %%ecx, %%eax           \n\t" // subtract Prior(x-bpp)
+      "movl %%eax, %%ecx           \n\t"
+      // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+      "addl patemp, %%eax          \n\t" // pcv = pav + pbv
+      // pc = abs(pcv)
+      "testl $0x80000000, %%eax    \n\t"
+      "jz paeth_pca                \n\t"
+      "negl %%eax                  \n\t" // reverse sign of neg values
+   "paeth_pca:                     \n\t"
+      "movl %%eax, pctemp          \n\t" // save pc for later use
+      // pb = abs(pbv)
+      "testl $0x80000000, %%ecx    \n\t"
+      "jz paeth_pba                \n\t"
+      "negl %%ecx                  \n\t" // reverse sign of neg values
+   "paeth_pba:                     \n\t"
+      "movl %%ecx, pbtemp          \n\t" // save pb for later use
+      // pa = abs(pav)
+      "movl patemp, %%eax          \n\t"
+      "testl $0x80000000, %%eax    \n\t"
+      "jz paeth_paa                \n\t"
+      "negl %%eax                  \n\t" // reverse sign of neg values
+   "paeth_paa:                     \n\t"
+      "movl %%eax, patemp          \n\t" // save pa for later use
+      // test if pa <= pb
+      "cmpl %%ecx, %%eax           \n\t"
+      "jna paeth_abb               \n\t"
+      // pa > pb; now test if pb <= pc
+      "cmpl pctemp, %%ecx          \n\t"
+      "jna paeth_bbc               \n\t"
+      // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
+      "movb (%%esi,%%edx,), %%cl   \n\t" // load Prior(x-bpp) into cl
+      "jmp paeth_paeth             \n\t"
+   "paeth_bbc:                     \n\t"
+      // pb <= pc; Raw(x) = Paeth(x) + Prior(x)
+      "movb (%%esi,%%ebx,), %%cl   \n\t" // load Prior(x) into cl
+      "jmp paeth_paeth             \n\t"
+   "paeth_abb:                     \n\t"
+      // pa <= pb; now test if pa <= pc
+      "cmpl pctemp, %%eax          \n\t"
+      "jna paeth_abc               \n\t"
+      // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
+      "movb (%%esi,%%edx,), %%cl   \n\t" // load Prior(x-bpp) into cl
+      "jmp paeth_paeth             \n\t"
+   "paeth_abc:                     \n\t"
+      // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp)
+      "movb (%%edi,%%edx,), %%cl   \n\t" // load Raw(x-bpp) into cl
+   "paeth_paeth:                   \n\t"
+      "incl %%ebx                  \n\t"
+      "incl %%edx                  \n\t"
+      // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256
+      "addb %%cl, -1(%%edi,%%ebx,) \n\t"
+      "cmpl _dif, %%ebx            \n\t"
+      "jb paeth_lp1                \n\t"
+   "paeth_go:                      \n\t"
+      "movl _FullLength, %%ecx     \n\t"
+      "movl %%ecx, %%eax           \n\t"
+      "subl %%ebx, %%eax           \n\t" // subtract alignment fix
+      "andl $0x00000007, %%eax     \n\t" // calc bytes over mult of 8
+      "subl %%eax, %%ecx           \n\t" // drop over bytes from original length
+      "movl %%ecx, _MMXLength      \n\t"
+
+      : // FIXASM: output regs/vars go here, e.g.:  "=m" (memory_var)
+
+      : // FIXASM: input regs, e.g.:  "c" (count), "S" (src), "D" (dest)
+
+      : "%eax", "%ebx", "%ecx", "%edx", "%edi", "%esi" // CHECKASM: clobber list
+   );
+
+   // Now do the math for the rest of the row
+   switch ( bpp )
+   {
+      case 3:
+      {
+         ActiveMask.use = 0x0000000000ffffff;
+         ActiveMaskEnd.use = 0xffff000000000000;
+         ShiftBpp.use = 24;    // == bpp(3) * 8
+         ShiftRem.use = 40;    // == 64 - 24
+         __asm__ (
+            "movl _dif, %%ebx            \n\t"
+            "movl row, %%edi             \n\t"
+            "movl prev_row, %%esi        \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            // PRIME the pump (load the first Raw(x-bpp) data set
+            "movq -8(%%edi,%%ebx,), %%mm1 \n\t"
+         "paeth_3lp:                     \n\t"
+            "psrlq $ShiftRem, %%mm1      \n\t" // shift last 3 bytes to 1st 3 bytes
+            "movq (%%esi,%%ebx,), %%mm2  \n\t" // load b=Prior(x)
+            "punpcklbw %%mm0, %%mm1      \n\t" // Unpack High bytes of a
+            "movq -8(%%esi,%%ebx,), %%mm3 \n\t" // Prep c=Prior(x-bpp) bytes
+            "punpcklbw %%mm0, %%mm2      \n\t" // Unpack High bytes of b
+            "psrlq $ShiftRem, %%mm3      \n\t" // shift last 3 bytes to 1st 3 bytes
+            // pav = p - a = (a + b - c) - a = b - c
+            "movq %%mm2, %%mm4           \n\t"
+            "punpcklbw %%mm0, %%mm3      \n\t" // Unpack High bytes of c
+            // pbv = p - b = (a + b - c) - b = a - c
+            "movq %%mm1, %%mm5           \n\t"
+            "psubw %%mm3, %%mm4          \n\t"
+            "pxor %%mm7, %%mm7           \n\t"
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            "movq %%mm4, %%mm6           \n\t"
+            "psubw %%mm3, %%mm5          \n\t"
+
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            "pcmpgtw %%mm4, %%mm0        \n\t" // Create mask pav bytes < 0
+            "paddw %%mm5, %%mm6          \n\t"
+            "pand %%mm4, %%mm0           \n\t" // Only pav bytes < 0 in mm7
+            "pcmpgtw %%mm5, %%mm7        \n\t" // Create mask pbv bytes < 0
+            "psubw %%mm0, %%mm4          \n\t"
+            "pand %%mm5, %%mm7           \n\t" // Only pbv bytes < 0 in mm0
+            "psubw %%mm0, %%mm4          \n\t"
+            "psubw %%mm7, %%mm5          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            "pcmpgtw %%mm6, %%mm0        \n\t" // Create mask pcv bytes < 0
+            "pand %%mm6, %%mm0           \n\t" // Only pav bytes < 0 in mm7
+            "psubw %%mm7, %%mm5          \n\t"
+            "psubw %%mm0, %%mm6          \n\t"
+            //  test pa <= pb
+            "movq %%mm4, %%mm7           \n\t"
+            "psubw %%mm0, %%mm6          \n\t"
+            "pcmpgtw %%mm5, %%mm7        \n\t" // pa > pb?
+            "movq %%mm7, %%mm0           \n\t"
+            // use mm7 mask to merge pa & pb
+            "pand %%mm7, %%mm5           \n\t"
+            // use mm0 mask copy to merge a & b
+            "pand %%mm0, %%mm2           \n\t"
+            "pandn %%mm4, %%mm7          \n\t"
+            "pandn %%mm1, %%mm0          \n\t"
+            "paddw %%mm5, %%mm7          \n\t"
+            "paddw %%mm2, %%mm0          \n\t"
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            "pcmpgtw %%mm6, %%mm7        \n\t" // pab > pc?
+            "pxor %%mm1, %%mm1           \n\t"
+            "pand %%mm7, %%mm3           \n\t"
+            "pandn %%mm0, %%mm7          \n\t"
+            "paddw %%mm3, %%mm7          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            "packuswb %%mm1, %%mm7       \n\t"
+            "movq (%%esi,%%ebx,), %%mm3  \n\t" // load c=Prior(x-bpp)
+            "pand $ActiveMask, %%mm7     \n\t"
+            "movq %%mm3, %%mm2           \n\t" // load b=Prior(x) step 1
+            "paddb (%%edi,%%ebx,), %%mm7 \n\t" // add Paeth predictor with Raw(x)
+            "punpcklbw %%mm0, %%mm3      \n\t" // Unpack High bytes of c
+            "movq %%mm7, (%%edi,%%ebx,)  \n\t" // write back updated value
+            "movq %%mm7, %%mm1           \n\t" // Now mm1 will be used as Raw(x-bpp)
+            // Now do Paeth for 2nd set of bytes (3-5)
+            "psrlq $ShiftBpp, %%mm2      \n\t" // load b=Prior(x) step 2
+            "punpcklbw %%mm0, %%mm1      \n\t" // Unpack High bytes of a
+            "pxor %%mm7, %%mm7           \n\t"
+            "punpcklbw %%mm0, %%mm2      \n\t" // Unpack High bytes of b
+            // pbv = p - b = (a + b - c) - b = a - c
+            "movq %%mm1, %%mm5           \n\t"
+            // pav = p - a = (a + b - c) - a = b - c
+            "movq %%mm2, %%mm4           \n\t"
+            "psubw %%mm3, %%mm5          \n\t"
+            "psubw %%mm3, %%mm4          \n\t"
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) =
+            //       pav + pbv = pbv + pav
+            "movq %%mm5, %%mm6           \n\t"
+            "paddw %%mm4, %%mm6          \n\t"
+
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            "pcmpgtw %%mm5, %%mm0        \n\t" // Create mask pbv bytes < 0
+            "pcmpgtw %%mm4, %%mm7        \n\t" // Create mask pav bytes < 0
+            "pand %%mm5, %%mm0           \n\t" // Only pbv bytes < 0 in mm0
+            "pand %%mm4, %%mm7           \n\t" // Only pav bytes < 0 in mm7
+            "psubw %%mm0, %%mm5          \n\t"
+            "psubw %%mm7, %%mm4          \n\t"
+            "psubw %%mm0, %%mm5          \n\t"
+            "psubw %%mm7, %%mm4          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            "pcmpgtw %%mm6, %%mm0        \n\t" // Create mask pcv bytes < 0
+            "pand %%mm6, %%mm0           \n\t" // Only pav bytes < 0 in mm7
+            "psubw %%mm0, %%mm6          \n\t"
+            //  test pa <= pb
+            "movq %%mm4, %%mm7           \n\t"
+            "psubw %%mm0, %%mm6          \n\t"
+            "pcmpgtw %%mm5, %%mm7        \n\t" // pa > pb?
+            "movq %%mm7, %%mm0           \n\t"
+            // use mm7 mask to merge pa & pb
+            "pand %%mm7, %%mm5           \n\t"
+            // use mm0 mask copy to merge a & b
+            "pand %%mm0, %%mm2           \n\t"
+            "pandn %%mm4, %%mm7          \n\t"
+            "pandn %%mm1, %%mm0          \n\t"
+            "paddw %%mm5, %%mm7          \n\t"
+            "paddw %%mm2, %%mm0          \n\t"
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            "pcmpgtw %%mm6, %%mm7        \n\t" // pab > pc?
+            "movq (%%esi,%%ebx,), %%mm2  \n\t" // load b=Prior(x)
+            "pand %%mm7, %%mm3           \n\t"
+            "pandn %%mm0, %%mm7          \n\t"
+            "pxor %%mm1, %%mm1           \n\t"
+            "paddw %%mm3, %%mm7          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            "packuswb %%mm1, %%mm7       \n\t"
+            "movq %%mm2, %%mm3           \n\t" // load c=Prior(x-bpp) step 1
+            "pand $ActiveMask, %%mm7     \n\t"
+            "punpckhbw %%mm0, %%mm2      \n\t" // Unpack High bytes of b
+            "psllq $ShiftBpp, %%mm7      \n\t" // Shift bytes to 2nd group of 3 bytes
+             // pav = p - a = (a + b - c) - a = b - c
+            "movq %%mm2, %%mm4           \n\t"
+            "paddb (%%edi,%%ebx,), %%mm7 \n\t" // add Paeth predictor with Raw(x)
+            "psllq $ShiftBpp, %%mm3      \n\t" // load c=Prior(x-bpp) step 2
+            "movq %%mm7, (%%edi,%%ebx,)  \n\t" // write back updated value
+            "movq %%mm7, %%mm1           \n\t"
+            "punpckhbw %%mm0, %%mm3      \n\t" // Unpack High bytes of c
+            "psllq $ShiftBpp, %%mm1      \n\t" // Shift bytes
+                                    // Now mm1 will be used as Raw(x-bpp)
+            // Now do Paeth for 3rd, and final, set of bytes (6-7)
+            "pxor %%mm7, %%mm7           \n\t"
+            "punpckhbw %%mm0, %%mm1      \n\t" // Unpack High bytes of a
+            "psubw %%mm3, %%mm4          \n\t"
+            // pbv = p - b = (a + b - c) - b = a - c
+            "movq %%mm1, %%mm5           \n\t"
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            "movq %%mm4, %%mm6           \n\t"
+            "psubw %%mm3, %%mm5          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            "paddw %%mm5, %%mm6          \n\t"
+
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            "pcmpgtw %%mm4, %%mm0        \n\t" // Create mask pav bytes < 0
+            "pcmpgtw %%mm5, %%mm7        \n\t" // Create mask pbv bytes < 0
+            "pand %%mm4, %%mm0           \n\t" // Only pav bytes < 0 in mm7
+            "pand %%mm5, %%mm7           \n\t" // Only pbv bytes < 0 in mm0
+            "psubw %%mm0, %%mm4          \n\t"
+            "psubw %%mm7, %%mm5          \n\t"
+            "psubw %%mm0, %%mm4          \n\t"
+            "psubw %%mm7, %%mm5          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            "pcmpgtw %%mm6, %%mm0        \n\t" // Create mask pcv bytes < 0
+            "pand %%mm6, %%mm0           \n\t" // Only pav bytes < 0 in mm7
+            "psubw %%mm0, %%mm6          \n\t"
+            //  test pa <= pb
+            "movq %%mm4, %%mm7           \n\t"
+            "psubw %%mm0, %%mm6          \n\t"
+            "pcmpgtw %%mm5, %%mm7        \n\t" // pa > pb?
+            "movq %%mm7, %%mm0           \n\t"
+            // use mm0 mask copy to merge a & b
+            "pand %%mm0, %%mm2           \n\t"
+            // use mm7 mask to merge pa & pb
+            "pand %%mm7, %%mm5           \n\t"
+            "pandn %%mm1, %%mm0          \n\t"
+            "pandn %%mm4, %%mm7          \n\t"
+            "paddw %%mm2, %%mm0          \n\t"
+            "paddw %%mm5, %%mm7          \n\t"
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            "pcmpgtw %%mm6, %%mm7        \n\t" // pab > pc?
+            "pand %%mm7, %%mm3           \n\t"
+            "pandn %%mm0, %%mm7          \n\t"
+            "paddw %%mm3, %%mm7          \n\t"
+            "pxor %%mm1, %%mm1           \n\t"
+            "packuswb %%mm7, %%mm1       \n\t"
+            // Step ebx to next set of 8 bytes and repeat loop til done
+            "addl $8, %%ebx              \n\t"
+            "pand $ActiveMaskEnd, %%mm1  \n\t"
+            "paddb -8(%%edi,%%ebx,), %%mm1 \n\t" // add Paeth predictor with Raw(x)
+
+            "cmpl _MMXLength, %%ebx      \n\t"
+            "pxor %%mm0, %%mm0           \n\t" // pxor does not affect flags
+            "movq %%mm1, -8(%%edi,%%ebx,) \n\t" // write back updated value
+                                 // mm1 will be used as Raw(x-bpp) next loop
+                           // mm3 ready to be used as Prior(x-bpp) next loop
+            "jb paeth_3lp                \n\t"
+
+            : // FIXASM: output regs/vars go here, e.g.:  "=m" (memory_var)
+
+            : // FIXASM: input regs, e.g.:  "c" (count), "S" (src), "D" (dest)
+
+            : "%ebx", "%edi", "%esi", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7" // CHECKASM: clobber list
+         );
+      }
+      break;
+
+      case 6:
+      //case 7:   // GRR BOGUS
+      //case 5:   // GRR BOGUS
+      {
+         ActiveMask.use  = 0x00000000ffffffff;
+         ActiveMask2.use = 0xffffffff00000000;
+         ShiftBpp.use = bpp << 3;    // == bpp * 8
+         ShiftRem.use = 64 - ShiftBpp.use;
+         __asm__ (
+            "movl _dif, %%ebx            \n\t"
+            "movl row, %%edi             \n\t"
+            "movl prev_row, %%esi        \n\t"
+            // PRIME the pump (load the first Raw(x-bpp) data set
+            "movq -8(%%edi,%%ebx,), %%mm1 \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+         "paeth_6lp:                     \n\t"
+            // Must shift to position Raw(x-bpp) data
+            "psrlq $ShiftRem, %%mm1      \n\t"
+            // Do first set of 4 bytes
+            "movq -8(%%esi,%%ebx,), %%mm3 \n\t" // read c=Prior(x-bpp) bytes
+            "punpcklbw %%mm0, %%mm1      \n\t" // Unpack Low bytes of a
+            "movq (%%esi,%%ebx,), %%mm2  \n\t" // load b=Prior(x)
+            "punpcklbw %%mm0, %%mm2      \n\t" // Unpack Low bytes of b
+            // Must shift to position Prior(x-bpp) data
+            "psrlq $ShiftRem, %%mm3      \n\t"
+            // pav = p - a = (a + b - c) - a = b - c
+            "movq %%mm2, %%mm4           \n\t"
+            "punpcklbw %%mm0, %%mm3      \n\t" // Unpack Low bytes of c
+            // pbv = p - b = (a + b - c) - b = a - c
+            "movq %%mm1, %%mm5           \n\t"
+            "psubw %%mm3, %%mm4          \n\t"
+            "pxor %%mm7, %%mm7           \n\t"
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            "movq %%mm4, %%mm6           \n\t"
+            "psubw %%mm3, %%mm5          \n\t"
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            "pcmpgtw %%mm4, %%mm0        \n\t" // Create mask pav bytes < 0
+            "paddw %%mm5, %%mm6          \n\t"
+            "pand %%mm4, %%mm0           \n\t" // Only pav bytes < 0 in mm7
+            "pcmpgtw %%mm5, %%mm7        \n\t" // Create mask pbv bytes < 0
+            "psubw %%mm0, %%mm4          \n\t"
+            "pand %%mm5, %%mm7           \n\t" // Only pbv bytes < 0 in mm0
+            "psubw %%mm0, %%mm4          \n\t"
+            "psubw %%mm7, %%mm5          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            "pcmpgtw %%mm6, %%mm0        \n\t" // Create mask pcv bytes < 0
+            "pand %%mm6, %%mm0           \n\t" // Only pav bytes < 0 in mm7
+            "psubw %%mm7, %%mm5          \n\t"
+            "psubw %%mm0, %%mm6          \n\t"
+            //  test pa <= pb
+            "movq %%mm4, %%mm7           \n\t"
+            "psubw %%mm0, %%mm6          \n\t"
+            "pcmpgtw %%mm5, %%mm7        \n\t" // pa > pb?
+            "movq %%mm7, %%mm0           \n\t"
+            // use mm7 mask to merge pa & pb
+            "pand %%mm7, %%mm5           \n\t"
+            // use mm0 mask copy to merge a & b
+            "pand %%mm0, %%mm2           \n\t"
+            "pandn %%mm4, %%mm7          \n\t"
+            "pandn %%mm1, %%mm0          \n\t"
+            "paddw %%mm5, %%mm7          \n\t"
+            "paddw %%mm2, %%mm0          \n\t"
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            "pcmpgtw %%mm6, %%mm7        \n\t" // pab > pc?
+            "pxor %%mm1, %%mm1           \n\t"
+            "pand %%mm7, %%mm3           \n\t"
+            "pandn %%mm0, %%mm7          \n\t"
+            "paddw %%mm3, %%mm7          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            "packuswb %%mm1, %%mm7       \n\t"
+            "movq -8(%%esi,%%ebx,), %%mm3 \n\t" // load c=Prior(x-bpp)
+            "pand $ActiveMask, %%mm7     \n\t"
+            "psrlq $ShiftRem, %%mm3      \n\t"
+            "movq (%%esi,%%ebx,), %%mm2  \n\t" // load b=Prior(x) step 1
+            "paddb (%%edi,%%ebx,), %%mm7 \n\t" // add Paeth predictor with Raw(x)
+            "movq %%mm2, %%mm6           \n\t"
+            "movq %%mm7, (%%edi,%%ebx,)  \n\t" // write back updated value
+            "movq -8(%%edi,%%ebx,), %%mm1 \n\t"
+            "psllq $ShiftBpp, %%mm6      \n\t"
+            "movq %%mm7, %%mm5           \n\t"
+            "psrlq $ShiftRem, %%mm1      \n\t"
+            "por %%mm6, %%mm3            \n\t"
+            "psllq $ShiftBpp, %%mm5      \n\t"
+            "punpckhbw %%mm0, %%mm3      \n\t" // Unpack High bytes of c
+            "por %%mm5, %%mm1            \n\t"
+            // Do second set of 4 bytes
+            "punpckhbw %%mm0, %%mm2      \n\t" // Unpack High bytes of b
+            "punpckhbw %%mm0, %%mm1      \n\t" // Unpack High bytes of a
+            // pav = p - a = (a + b - c) - a = b - c
+            "movq %%mm2, %%mm4           \n\t"
+            // pbv = p - b = (a + b - c) - b = a - c
+            "movq %%mm1, %%mm5           \n\t"
+            "psubw %%mm3, %%mm4          \n\t"
+            "pxor %%mm7, %%mm7           \n\t"
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            "movq %%mm4, %%mm6           \n\t"
+            "psubw %%mm3, %%mm5          \n\t"
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            "pcmpgtw %%mm4, %%mm0        \n\t" // Create mask pav bytes < 0
+            "paddw %%mm5, %%mm6          \n\t"
+            "pand %%mm4, %%mm0           \n\t" // Only pav bytes < 0 in mm7
+            "pcmpgtw %%mm5, %%mm7        \n\t" // Create mask pbv bytes < 0
+            "psubw %%mm0, %%mm4          \n\t"
+            "pand %%mm5, %%mm7           \n\t" // Only pbv bytes < 0 in mm0
+            "psubw %%mm0, %%mm4          \n\t"
+            "psubw %%mm7, %%mm5          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            "pcmpgtw %%mm6, %%mm0        \n\t" // Create mask pcv bytes < 0
+            "pand %%mm6, %%mm0           \n\t" // Only pav bytes < 0 in mm7
+            "psubw %%mm7, %%mm5          \n\t"
+            "psubw %%mm0, %%mm6          \n\t"
+            //  test pa <= pb
+            "movq %%mm4, %%mm7           \n\t"
+            "psubw %%mm0, %%mm6          \n\t"
+            "pcmpgtw %%mm5, %%mm7        \n\t" // pa > pb?
+            "movq %%mm7, %%mm0           \n\t"
+            // use mm7 mask to merge pa & pb
+            "pand %%mm7, %%mm5           \n\t"
+            // use mm0 mask copy to merge a & b
+            "pand %%mm0, %%mm2           \n\t"
+            "pandn %%mm4, %%mm7          \n\t"
+            "pandn %%mm1, %%mm0          \n\t"
+            "paddw %%mm5, %%mm7          \n\t"
+            "paddw %%mm2, %%mm0          \n\t"
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            "pcmpgtw %%mm6, %%mm7        \n\t" // pab > pc?
+            "pxor %%mm1, %%mm1           \n\t"
+            "pand %%mm7, %%mm3           \n\t"
+            "pandn %%mm0, %%mm7          \n\t"
+            "pxor %%mm1, %%mm1           \n\t"
+            "paddw %%mm3, %%mm7          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            // Step ex to next set of 8 bytes and repeat loop til done
+            "addl $8, %%ebx              \n\t"
+            "packuswb %%mm7, %%mm1       \n\t"
+            "paddb -8(%%edi,%%ebx,), %%mm1 \n\t" // add Paeth predictor with Raw(x)
+            "cmpl _MMXLength, %%ebx      \n\t"
+            "movq %%mm1, -8(%%edi,%%ebx,) \n\t" // write back updated value
+                                // mm1 will be used as Raw(x-bpp) next loop
+            "jb paeth_6lp                \n\t"
+
+            : // FIXASM: output regs/vars go here, e.g.:  "=m" (memory_var)
+
+            : // FIXASM: input regs, e.g.:  "c" (count), "S" (src), "D" (dest)
+
+            : "%ebx", "%edi", "%esi", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7" // CHECKASM: clobber list
+         );
+      }
+      break;
+
+      case 4:
+      {
+         ActiveMask.use  = 0x00000000ffffffff;
+         __asm__ (
+            "movl _dif, %%ebx            \n\t"
+            "movl row, %%edi             \n\t"
+            "movl prev_row, %%esi        \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            // PRIME the pump (load the first Raw(x-bpp) data set
+            "movq -8(%%edi,%%ebx,), %%mm1 \n\t" // Only time should need to read
+                                     //  a=Raw(x-bpp) bytes
+         "paeth_4lp:                     \n\t"
+            // Do first set of 4 bytes
+            "movq -8(%%esi,%%ebx,), %%mm3 \n\t" // read c=Prior(x-bpp) bytes
+            "punpckhbw %%mm0, %%mm1      \n\t" // Unpack Low bytes of a
+            "movq (%%esi,%%ebx,), %%mm2  \n\t" // load b=Prior(x)
+            "punpcklbw %%mm0, %%mm2      \n\t" // Unpack High bytes of b
+            // pav = p - a = (a + b - c) - a = b - c
+            "movq %%mm2, %%mm4           \n\t"
+            "punpckhbw %%mm0, %%mm3      \n\t" // Unpack High bytes of c
+            // pbv = p - b = (a + b - c) - b = a - c
+            "movq %%mm1, %%mm5           \n\t"
+            "psubw %%mm3, %%mm4          \n\t"
+            "pxor %%mm7, %%mm7           \n\t"
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            "movq %%mm4, %%mm6           \n\t"
+            "psubw %%mm3, %%mm5          \n\t"
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            "pcmpgtw %%mm4, %%mm0        \n\t" // Create mask pav bytes < 0
+            "paddw %%mm5, %%mm6          \n\t"
+            "pand %%mm4, %%mm0           \n\t" // Only pav bytes < 0 in mm7
+            "pcmpgtw %%mm5, %%mm7        \n\t" // Create mask pbv bytes < 0
+            "psubw %%mm0, %%mm4          \n\t"
+            "pand %%mm5, %%mm7           \n\t" // Only pbv bytes < 0 in mm0
+            "psubw %%mm0, %%mm4          \n\t"
+            "psubw %%mm7, %%mm5          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            "pcmpgtw %%mm6, %%mm0        \n\t" // Create mask pcv bytes < 0
+            "pand %%mm6, %%mm0           \n\t" // Only pav bytes < 0 in mm7
+            "psubw %%mm7, %%mm5          \n\t"
+            "psubw %%mm0, %%mm6          \n\t"
+            //  test pa <= pb
+            "movq %%mm4, %%mm7           \n\t"
+            "psubw %%mm0, %%mm6          \n\t"
+            "pcmpgtw %%mm5, %%mm7        \n\t" // pa > pb?
+            "movq %%mm7, %%mm0           \n\t"
+            // use mm7 mask to merge pa & pb
+            "pand %%mm7, %%mm5           \n\t"
+            // use mm0 mask copy to merge a & b
+            "pand %%mm0, %%mm2           \n\t"
+            "pandn %%mm4, %%mm7          \n\t"
+            "pandn %%mm1, %%mm0          \n\t"
+            "paddw %%mm5, %%mm7          \n\t"
+            "paddw %%mm2, %%mm0          \n\t"
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            "pcmpgtw %%mm6, %%mm7        \n\t" // pab > pc?
+            "pxor %%mm1, %%mm1           \n\t"
+            "pand %%mm7, %%mm3           \n\t"
+            "pandn %%mm0, %%mm7          \n\t"
+            "paddw %%mm3, %%mm7          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            "packuswb %%mm1, %%mm7       \n\t"
+            "movq (%%esi,%%ebx,), %%mm3  \n\t" // load c=Prior(x-bpp)
+            "pand $ActiveMask, %%mm7     \n\t"
+            "movq %%mm3, %%mm2           \n\t" // load b=Prior(x) step 1
+            "paddb (%%edi,%%ebx,), %%mm7 \n\t" // add Paeth predictor with Raw(x)
+            "punpcklbw %%mm0, %%mm3      \n\t" // Unpack High bytes of c
+            "movq %%mm7, (%%edi,%%ebx,)  \n\t" // write back updated value
+            "movq %%mm7, %%mm1           \n\t" // Now mm1 will be used as Raw(x-bpp)
+            // Do second set of 4 bytes
+            "punpckhbw %%mm0, %%mm2      \n\t" // Unpack Low bytes of b
+            "punpcklbw %%mm0, %%mm1      \n\t" // Unpack Low bytes of a
+            // pav = p - a = (a + b - c) - a = b - c
+            "movq %%mm2, %%mm4           \n\t"
+            // pbv = p - b = (a + b - c) - b = a - c
+            "movq %%mm1, %%mm5           \n\t"
+            "psubw %%mm3, %%mm4          \n\t"
+            "pxor %%mm7, %%mm7           \n\t"
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            "movq %%mm4, %%mm6           \n\t"
+            "psubw %%mm3, %%mm5          \n\t"
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            "pcmpgtw %%mm4, %%mm0        \n\t" // Create mask pav bytes < 0
+            "paddw %%mm5, %%mm6          \n\t"
+            "pand %%mm4, %%mm0           \n\t" // Only pav bytes < 0 in mm7
+            "pcmpgtw %%mm5, %%mm7        \n\t" // Create mask pbv bytes < 0
+            "psubw %%mm0, %%mm4          \n\t"
+            "pand %%mm5, %%mm7           \n\t" // Only pbv bytes < 0 in mm0
+            "psubw %%mm0, %%mm4          \n\t"
+            "psubw %%mm7, %%mm5          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            "pcmpgtw %%mm6, %%mm0        \n\t" // Create mask pcv bytes < 0
+            "pand %%mm6, %%mm0           \n\t" // Only pav bytes < 0 in mm7
+            "psubw %%mm7, %%mm5          \n\t"
+            "psubw %%mm0, %%mm6          \n\t"
+            //  test pa <= pb
+            "movq %%mm4, %%mm7           \n\t"
+            "psubw %%mm0, %%mm6          \n\t"
+            "pcmpgtw %%mm5, %%mm7        \n\t" // pa > pb?
+            "movq %%mm7, %%mm0           \n\t"
+            // use mm7 mask to merge pa & pb
+            "pand %%mm7, %%mm5           \n\t"
+            // use mm0 mask copy to merge a & b
+            "pand %%mm0, %%mm2           \n\t"
+            "pandn %%mm4, %%mm7          \n\t"
+            "pandn %%mm1, %%mm0          \n\t"
+            "paddw %%mm5, %%mm7          \n\t"
+            "paddw %%mm2, %%mm0          \n\t"
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            "pcmpgtw %%mm6, %%mm7        \n\t" // pab > pc?
+            "pxor %%mm1, %%mm1           \n\t"
+            "pand %%mm7, %%mm3           \n\t"
+            "pandn %%mm0, %%mm7          \n\t"
+            "pxor %%mm1, %%mm1           \n\t"
+            "paddw %%mm3, %%mm7          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            // Step ex to next set of 8 bytes and repeat loop til done
+            "addl $8, %%ebx              \n\t"
+            "packuswb %%mm7, %%mm1       \n\t"
+            "paddb -8(%%edi,%%ebx,), %%mm1 \n\t" // add Paeth predictor with Raw(x)
+            "cmpl _MMXLength, %%ebx      \n\t"
+            "movq %%mm1, -8(%%edi,%%ebx,) \n\t" // write back updated value
+                                // mm1 will be used as Raw(x-bpp) next loop
+            "jb paeth_4lp                \n\t"
+
+            : // FIXASM: output regs/vars go here, e.g.:  "=m" (memory_var)
+
+            : // FIXASM: input regs, e.g.:  "c" (count), "S" (src), "D" (dest)
+
+            : "%ebx", "%edi", "%esi", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7" // CHECKASM: clobber list
+         );
+      }
+      break;
+      case 8:                          // bpp == 8
+      {
+         ActiveMask.use  = 0x00000000ffffffff;
+         __asm__ (
+            "movl _dif, %%ebx            \n\t"
+            "movl row, %%edi             \n\t"
+            "movl prev_row, %%esi        \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            // PRIME the pump (load the first Raw(x-bpp) data set
+            "movq -8(%%edi,%%ebx,), %%mm1 \n\t" // Only time should need to read
+                                       //  a=Raw(x-bpp) bytes
+         "paeth_8lp:                     \n\t"
+            // Do first set of 4 bytes
+            "movq -8(%%esi,%%ebx,), %%mm3 \n\t" // read c=Prior(x-bpp) bytes
+            "punpcklbw %%mm0, %%mm1      \n\t" // Unpack Low bytes of a
+            "movq (%%esi,%%ebx,), %%mm2  \n\t" // load b=Prior(x)
+            "punpcklbw %%mm0, %%mm2      \n\t" // Unpack Low bytes of b
+            // pav = p - a = (a + b - c) - a = b - c
+            "movq %%mm2, %%mm4           \n\t"
+            "punpcklbw %%mm0, %%mm3      \n\t" // Unpack Low bytes of c
+            // pbv = p - b = (a + b - c) - b = a - c
+            "movq %%mm1, %%mm5           \n\t"
+            "psubw %%mm3, %%mm4          \n\t"
+            "pxor %%mm7, %%mm7           \n\t"
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            "movq %%mm4, %%mm6           \n\t"
+            "psubw %%mm3, %%mm5          \n\t"
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            "pcmpgtw %%mm4, %%mm0        \n\t" // Create mask pav bytes < 0
+            "paddw %%mm5, %%mm6          \n\t"
+            "pand %%mm4, %%mm0           \n\t" // Only pav bytes < 0 in mm7
+            "pcmpgtw %%mm5, %%mm7        \n\t" // Create mask pbv bytes < 0
+            "psubw %%mm0, %%mm4          \n\t"
+            "pand %%mm5, %%mm7           \n\t" // Only pbv bytes < 0 in mm0
+            "psubw %%mm0, %%mm4          \n\t"
+            "psubw %%mm7, %%mm5          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            "pcmpgtw %%mm6, %%mm0        \n\t" // Create mask pcv bytes < 0
+            "pand %%mm6, %%mm0           \n\t" // Only pav bytes < 0 in mm7
+            "psubw %%mm7, %%mm5          \n\t"
+            "psubw %%mm0, %%mm6          \n\t"
+            //  test pa <= pb
+            "movq %%mm4, %%mm7           \n\t"
+            "psubw %%mm0, %%mm6          \n\t"
+            "pcmpgtw %%mm5, %%mm7        \n\t" // pa > pb?
+            "movq %%mm7, %%mm0           \n\t"
+            // use mm7 mask to merge pa & pb
+            "pand %%mm7, %%mm5           \n\t"
+            // use mm0 mask copy to merge a & b
+            "pand %%mm0, %%mm2           \n\t"
+            "pandn %%mm4, %%mm7          \n\t"
+            "pandn %%mm1, %%mm0          \n\t"
+            "paddw %%mm5, %%mm7          \n\t"
+            "paddw %%mm2, %%mm0          \n\t"
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            "pcmpgtw %%mm6, %%mm7        \n\t" // pab > pc?
+            "pxor %%mm1, %%mm1           \n\t"
+            "pand %%mm7, %%mm3           \n\t"
+            "pandn %%mm0, %%mm7          \n\t"
+            "paddw %%mm3, %%mm7          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            "packuswb %%mm1, %%mm7       \n\t"
+            "movq -8(%%esi,%%ebx,), %%mm3 \n\t" // read c=Prior(x-bpp) bytes
+            "pand $ActiveMask, %%mm7     \n\t"
+            "movq (%%esi,%%ebx,), %%mm2  \n\t" // load b=Prior(x)
+            "paddb (%%edi,%%ebx,), %%mm7 \n\t" // add Paeth predictor with Raw(x)
+            "punpckhbw %%mm0, %%mm3      \n\t" // Unpack High bytes of c
+            "movq %%mm7, (%%edi,%%ebx,)  \n\t" // write back updated value
+            "movq -8(%%edi,%%ebx,), %%mm1 \n\t" // read a=Raw(x-bpp) bytes
+
+            // Do second set of 4 bytes
+            "punpckhbw %%mm0, %%mm2      \n\t" // Unpack High bytes of b
+            "punpckhbw %%mm0, %%mm1      \n\t" // Unpack High bytes of a
+            // pav = p - a = (a + b - c) - a = b - c
+            "movq %%mm2, %%mm4           \n\t"
+            // pbv = p - b = (a + b - c) - b = a - c
+            "movq %%mm1, %%mm5           \n\t"
+            "psubw %%mm3, %%mm4          \n\t"
+            "pxor %%mm7, %%mm7           \n\t"
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            "movq %%mm4, %%mm6           \n\t"
+            "psubw %%mm3, %%mm5          \n\t"
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            "pcmpgtw %%mm4, %%mm0        \n\t" // Create mask pav bytes < 0
+            "paddw %%mm5, %%mm6          \n\t"
+            "pand %%mm4, %%mm0           \n\t" // Only pav bytes < 0 in mm7
+            "pcmpgtw %%mm5, %%mm7        \n\t" // Create mask pbv bytes < 0
+            "psubw %%mm0, %%mm4          \n\t"
+            "pand %%mm5, %%mm7           \n\t" // Only pbv bytes < 0 in mm0
+            "psubw %%mm0, %%mm4          \n\t"
+            "psubw %%mm7, %%mm5          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            "pcmpgtw %%mm6, %%mm0        \n\t" // Create mask pcv bytes < 0
+            "pand %%mm6, %%mm0           \n\t" // Only pav bytes < 0 in mm7
+            "psubw %%mm7, %%mm5          \n\t"
+            "psubw %%mm0, %%mm6          \n\t"
+            //  test pa <= pb
+            "movq %%mm4, %%mm7           \n\t"
+            "psubw %%mm0, %%mm6          \n\t"
+            "pcmpgtw %%mm5, %%mm7        \n\t" // pa > pb?
+            "movq %%mm7, %%mm0           \n\t"
+            // use mm7 mask to merge pa & pb
+            "pand %%mm7, %%mm5           \n\t"
+            // use mm0 mask copy to merge a & b
+            "pand %%mm0, %%mm2           \n\t"
+            "pandn %%mm4, %%mm7          \n\t"
+            "pandn %%mm1, %%mm0          \n\t"
+            "paddw %%mm5, %%mm7          \n\t"
+            "paddw %%mm2, %%mm0          \n\t"
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            "pcmpgtw %%mm6, %%mm7        \n\t" // pab > pc?
+            "pxor %%mm1, %%mm1           \n\t"
+            "pand %%mm7, %%mm3           \n\t"
+            "pandn %%mm0, %%mm7          \n\t"
+            "pxor %%mm1, %%mm1           \n\t"
+            "paddw %%mm3, %%mm7          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            // Step ex to next set of 8 bytes and repeat loop til done
+            "addl $8, %%ebx              \n\t"
+            "packuswb %%mm7, %%mm1       \n\t"
+            "paddb -8(%%edi,%%ebx,), %%mm1 \n\t" // add Paeth predictor with Raw(x)
+            "cmpl _MMXLength, %%ebx      \n\t"
+            "movq %%mm1, -8(%%edi,%%ebx,) \n\t" // write back updated value
+                            // mm1 will be used as Raw(x-bpp) next loop
+            "jb paeth_8lp                \n\t"
+
+            : // FIXASM: output regs/vars go here, e.g.:  "=m" (memory_var)
+
+            : // FIXASM: input regs, e.g.:  "c" (count), "S" (src), "D" (dest)
+
+            : "%ebx", "%edi", "%esi", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7" // CHECKASM: clobber list
+         );
+      }
+      break;
+
+      case 1:                // bpp = 1
+      case 2:                // bpp = 2
+      default:               // bpp > 8
+      {
+         __asm__ (
+            "movl _dif, %%ebx            \n\t"
+            "cmpl _FullLength, %%ebx     \n\t"
+            "jnb paeth_dend              \n\t"
+            "movl row, %%edi             \n\t"
+            "movl prev_row, %%esi        \n\t"
+            // Do Paeth decode for remaining bytes
+            "movl %%ebx, %%edx           \n\t"
+            "xorl %%ecx, %%ecx           \n\t" // zero ecx before using cl & cx in loop below
+            "subl bpp, %%edx             \n\t" // Set edx = ebx - bpp
+         "paeth_dlp:                     \n\t"
+            "xorl %%eax, %%eax           \n\t"
+            // pav = p - a = (a + b - c) - a = b - c
+            "movb (%%esi,%%ebx,), %%al   \n\t" // load Prior(x) into al
+            "movb (%%esi,%%edx,), %%cl   \n\t" // load Prior(x-bpp) into cl
+            "subl %%ecx, %%eax           \n\t" // subtract Prior(x-bpp)
+            "movl %%eax, patemp          \n\t" // Save pav for later use
+            "xorl %%eax, %%eax           \n\t"
+            // pbv = p - b = (a + b - c) - b = a - c
+            "movb (%%edi,%%edx,), %%al   \n\t" // load Raw(x-bpp) into al
+            "subl %%ecx, %%eax           \n\t" // subtract Prior(x-bpp)
+            "movl %%eax, %%ecx           \n\t"
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            "addl patemp, %%eax          \n\t" // pcv = pav + pbv
+            // pc = abs(pcv)
+            "testl $0x80000000, %%eax    \n\t"
+            "jz paeth_dpca               \n\t"
+            "negl %%eax                  \n\t" // reverse sign of neg values
+         "paeth_dpca:                    \n\t"
+            "movl %%eax, pctemp          \n\t" // save pc for later use
+            // pb = abs(pbv)
+            "testl $0x80000000, %%ecx    \n\t"
+            "jz paeth_dpba               \n\t"
+            "negl %%ecx                  \n\t" // reverse sign of neg values
+         "paeth_dpba:                    \n\t"
+            "movl %%ecx, pbtemp          \n\t" // save pb for later use
+            // pa = abs(pav)
+            "movl patemp, %%eax          \n\t"
+            "testl $0x80000000, %%eax    \n\t"
+            "jz paeth_dpaa               \n\t"
+            "negl %%eax                  \n\t" // reverse sign of neg values
+         "paeth_dpaa:                    \n\t"
+            "movl %%eax, patemp          \n\t" // save pa for later use
+            // test if pa <= pb
+            "cmpl %%ecx, %%eax           \n\t"
+            "jna paeth_dabb              \n\t"
+            // pa > pb; now test if pb <= pc
+            "cmpl pctemp, %%ecx          \n\t"
+            "jna paeth_dbbc              \n\t"
+            // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
+            "movb (%%esi,%%edx,), %%cl   \n\t" // load Prior(x-bpp) into cl
+            "jmp paeth_dpaeth            \n\t"
+         "paeth_dbbc:                    \n\t"
+            // pb <= pc; Raw(x) = Paeth(x) + Prior(x)
+            "movb (%%esi,%%ebx,), %%cl   \n\t" // load Prior(x) into cl
+            "jmp paeth_dpaeth            \n\t"
+         "paeth_dabb:                    \n\t"
+            // pa <= pb; now test if pa <= pc
+            "cmpl pctemp, %%eax          \n\t"
+            "jna paeth_dabc              \n\t"
+            // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
+            "movb (%%esi,%%edx,), %%cl   \n\t" // load Prior(x-bpp) into cl
+            "jmp paeth_dpaeth            \n\t"
+         "paeth_dabc:                    \n\t"
+            // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp)
+            "movb (%%edi,%%edx,), %%cl   \n\t" // load Raw(x-bpp) into cl
+         "paeth_dpaeth:                  \n\t"
+            "incl %%ebx                  \n\t"
+            "incl %%edx                  \n\t"
+            // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256
+            "addb %%cl, -1(%%edi,%%ebx,) \n\t"
+            "cmpl _FullLength, %%ebx     \n\t"
+            "jb paeth_dlp                \n\t"
+         "paeth_dend:                    \n\t"
+
+            : // FIXASM: output regs/vars go here, e.g.:  "=m" (memory_var)
+
+            : // FIXASM: input regs, e.g.:  "c" (count), "S" (src), "D" (dest)
+
+            : "%eax", "%ebx", "%ecx", "%edx", "%edi", "%esi" // CHECKASM: clobber list
+         );
+      }
+      return;                   // No need to go further with this one
+   }                         // end switch ( bpp )
+   __asm__ (
+      // MMX acceleration complete now do clean-up
+      // Check if any remaining bytes left to decode
+      "movl _MMXLength, %%ebx      \n\t"
+      "cmpl _FullLength, %%ebx     \n\t"
+      "jnb paeth_end               \n\t"
+      "movl row, %%edi             \n\t"
+      "movl prev_row, %%esi        \n\t"
+      // Do Paeth decode for remaining bytes
+      "movl %%ebx, %%edx           \n\t"
+      "xorl %%ecx, %%ecx           \n\t" // zero ecx before using cl & cx in loop below
+      "subl bpp, %%edx             \n\t" // Set edx = ebx - bpp
+   "paeth_lp2:                     \n\t"
+      "xorl %%eax, %%eax           \n\t"
+      // pav = p - a = (a + b - c) - a = b - c
+      "movb (%%esi,%%ebx,), %%al   \n\t" // load Prior(x) into al
+      "movb (%%esi,%%edx,), %%cl   \n\t" // load Prior(x-bpp) into cl
+      "subl %%ecx, %%eax           \n\t" // subtract Prior(x-bpp)
+      "movl %%eax, patemp          \n\t" // Save pav for later use
+      "xorl %%eax, %%eax           \n\t"
+      // pbv = p - b = (a + b - c) - b = a - c
+      "movb (%%edi,%%edx,), %%al   \n\t" // load Raw(x-bpp) into al
+      "subl %%ecx, %%eax           \n\t" // subtract Prior(x-bpp)
+      "movl %%eax, %%ecx           \n\t"
+      // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+      "addl patemp, %%eax          \n\t" // pcv = pav + pbv
+      // pc = abs(pcv)
+      "testl $0x80000000, %%eax    \n\t"
+      "jz paeth_pca2               \n\t"
+      "negl %%eax                  \n\t" // reverse sign of neg values
+   "paeth_pca2:                    \n\t"
+      "movl %%eax, pctemp          \n\t" // save pc for later use
+      // pb = abs(pbv)
+      "testl $0x80000000, %%ecx    \n\t"
+      "jz paeth_pba2               \n\t"
+      "negl %%ecx                  \n\t" // reverse sign of neg values
+   "paeth_pba2:                    \n\t"
+      "movl %%ecx, pbtemp          \n\t" // save pb for later use
+      // pa = abs(pav)
+      "movl patemp, %%eax          \n\t"
+      "testl $0x80000000, %%eax    \n\t"
+      "jz paeth_paa2               \n\t"
+      "negl %%eax                  \n\t" // reverse sign of neg values
+   "paeth_paa2:                    \n\t"
+      "movl %%eax, patemp          \n\t" // save pa for later use
+      // test if pa <= pb
+      "cmpl %%ecx, %%eax           \n\t"
+      "jna paeth_abb2              \n\t"
+      // pa > pb; now test if pb <= pc
+      "cmpl pctemp, %%ecx          \n\t"
+      "jna paeth_bbc2              \n\t"
+      // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
+      "movb (%%esi,%%edx,), %%cl   \n\t" // load Prior(x-bpp) into cl
+      "jmp paeth_paeth2            \n\t"
+   "paeth_bbc2:                    \n\t"
+      // pb <= pc; Raw(x) = Paeth(x) + Prior(x)
+      "movb (%%esi,%%ebx,), %%cl   \n\t" // load Prior(x) into cl
+      "jmp paeth_paeth2            \n\t"
+   "paeth_abb2:                    \n\t"
+      // pa <= pb; now test if pa <= pc
+      "cmpl pctemp, %%eax          \n\t"
+      "jna paeth_abc2              \n\t"
+      // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
+      "movb (%%esi,%%edx,), %%cl   \n\t" // load Prior(x-bpp) into cl
+      "jmp paeth_paeth2            \n\t"
+   "paeth_abc2:                    \n\t"
+      // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp)
+      "movb (%%edi,%%edx,), %%cl   \n\t" // load Raw(x-bpp) into cl
+   "paeth_paeth2:                  \n\t"
+      "incl %%ebx                  \n\t"
+      "incl %%edx                  \n\t"
+      // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256
+      "addb %%cl, -1(%%edi,%%ebx,) \n\t"
+      "cmpl _FullLength, %%ebx     \n\t"
+      "jb paeth_lp2                \n\t"
+   "paeth_end:                     \n\t"
+      "emms                        \n\t" // End MMX instructions; prep for possible FP instrs.
+
+      : // FIXASM: output regs/vars go here, e.g.:  "=m" (memory_var)
+
+      : // FIXASM: input regs, e.g.:  "c" (count), "S" (src), "D" (dest)
+
+      : "%eax", "%ebx", "%ecx", "%edx", "%edi", "%esi" // CHECKASM: clobber list
+   );
+#endif /* GRR_GCC_MMX_CONVERTED */
+}
+
+// Optimized code for PNG Sub filter decoder
+void
+png_read_filter_row_mmx_sub(png_row_infop row_info, png_bytep row)
+{
+#ifdef GRR_GCC_MMX_CONVERTED
+   int bpp;
+
+   bpp = (row_info->pixel_depth + 7) >> 3; // Get # bytes per pixel
+   _FullLength  = row_info->rowbytes - bpp; // # of bytes to filter
+   __asm__ (
+      "movl row, %%edi             \n\t"
+      "movl %%edi, %%esi           \n\t" // lp = row
+      "addl bpp, %%edi             \n\t" // rp = row + bpp
+      "xorl %%eax, %%eax           \n\t"
+      // get # of bytes to alignment
+      "movl %%edi, _dif            \n\t" // take start of row
+      "addl $0xf, _dif             \n\t" // add 7 + 8 to incr past
+                                         // alignment boundary
+      "xorl %%ebx, %%ebx           \n\t"
+      "andl $0xfffffff8, _dif      \n\t" // mask to alignment boundary
+      "subl %%edi, _dif            \n\t" // subtract from start ==> value
+                                         //  ebx at alignment
+      "jz sub_go                   \n\t"
+      // fix alignment
+   "sub_lp1:                       \n\t"
+      "movb (%%esi,%%ebx,), %%al   \n\t"
+      "addb %%al, (%%edi,%%ebx,)   \n\t"
+      "incl %%ebx                  \n\t"
+      "cmpl _dif, %%ebx            \n\t"
+      "jb sub_lp1                  \n\t"
+   "sub_go:                        \n\t"
+      "movl _FullLength, %%ecx     \n\t"
+      "movl %%ecx, %%edx           \n\t"
+      "subl %%ebx, %%edx           \n\t" // subtract alignment fix
+      "andl $0x00000007, %%edx     \n\t" // calc bytes over mult of 8
+      "subl %%edx, %%ecx           \n\t" // drop over bytes from length
+      "movl %%ecx, _MMXLength      \n\t"
+
+      : // FIXASM: output regs/vars go here, e.g.:  "=m" (memory_var)
+
+      : // FIXASM: input regs, e.g.:  "c" (count), "S" (src), "D" (dest)
+
+      : "%eax", "%ebx", "%ecx", "%edx", "%edi", "%esi" // CHECKASM: clobber list
+   );
+
+   // Now do the math for the rest of the row
+   switch ( bpp )
+   {
+        case 3:
+        {
+         ActiveMask.use  = 0x0000ffffff000000;
+         ShiftBpp.use = 24;       // == 3 * 8
+         ShiftRem.use  = 40;      // == 64 - 24
+         __asm__ (
+            "movl row, %%edi             \n\t"
+            "movq $ActiveMask, %%mm7     \n\t" // Load ActiveMask for 2nd active byte group
+            "movl %%edi, %%esi           \n\t" // lp = row
+            "addl bpp, %%edi             \n\t" // rp = row + bpp
+            "movq %%mm7, %%mm6           \n\t"
+            "movl _dif, %%ebx            \n\t"
+            "psllq $ShiftBpp, %%mm6      \n\t" // Move mask in mm6 to cover 3rd active
+                                  // byte group
+            // PRIME the pump (load the first Raw(x-bpp) data set
+            "movq -8(%%edi,%%ebx,), %%mm1 \n\t"
+         "sub_3lp:                       \n\t"
+            "psrlq $ShiftRem, %%mm1      \n\t" // Shift data for adding 1st bpp bytes
+                          // no need for mask; shift clears inactive bytes
+            // Add 1st active group
+            "movq (%%edi,%%ebx,), %%mm0  \n\t"
+            "paddb %%mm1, %%mm0          \n\t"
+            // Add 2nd active group
+            "movq %%mm0, %%mm1           \n\t" // mov updated Raws to mm1
+            "psllq $ShiftBpp, %%mm1      \n\t" // shift data to position correctly
+            "pand %%mm7, %%mm1           \n\t" // mask to use only 2nd active group
+            "paddb %%mm1, %%mm0          \n\t"
+            // Add 3rd active group
+            "movq %%mm0, %%mm1           \n\t" // mov updated Raws to mm1
+            "psllq $ShiftBpp, %%mm1      \n\t" // shift data to position correctly
+            "pand %%mm6, %%mm1           \n\t" // mask to use only 3rd active group
+            "addl $8, %%ebx              \n\t"
+            "paddb %%mm1, %%mm0          \n\t"
+            "cmpl _MMXLength, %%ebx      \n\t"
+            "movq %%mm0, -8(%%edi,%%ebx,) \n\t" // Write updated Raws back to array
+            // Prep for doing 1st add at top of loop
+            "movq %%mm0, %%mm1           \n\t"
+            "jb sub_3lp                  \n\t"
+
+            : // FIXASM: output regs/vars go here, e.g.:  "=m" (memory_var)
+
+            : // FIXASM: input regs, e.g.:  "c" (count), "S" (src), "D" (dest)
+
+            : "%ebx", "%edi", "%esi", "%mm0", "%mm1", "%mm6", "%mm7" // CHECKASM: clobber list
+         );
+      }
+      break;
+
+      case 1:
+      {
+         // Placed here just in case this is a duplicate of the
+         // non-MMX code for the SUB filter in png_read_filter_row above
+         //
+         //         png_bytep rp;
+         //         png_bytep lp;
+         //         png_uint_32 i;
+         //         bpp = (row_info->pixel_depth + 7) >> 3;
+         //         for (i = (png_uint_32)bpp, rp = row + bpp, lp = row;
+         //            i < row_info->rowbytes; i++, rp++, lp++)
+         //      {
+         //            *rp = (png_byte)(((int)(*rp) + (int)(*lp)) & 0xff);
+         //      }
+         __asm__ (
+            "movl _dif, %%ebx            \n\t"
+            "movl row, %%edi             \n\t"
+            "cmpl _FullLength, %%ebx     \n\t"
+            "jnb sub_1end                \n\t"
+            "movl %%edi, %%esi           \n\t" // lp = row
+            "xorl %%eax, %%eax           \n\t"
+            "addl bpp, %%edi             \n\t" // rp = row + bpp
+         "sub_1lp:                       \n\t"
+            "movb (%%esi,%%ebx,), %%al   \n\t"
+            "addb %%al, (%%edi,%%ebx,)   \n\t"
+            "incl %%ebx                  \n\t"
+            "cmpl _FullLength, %%ebx     \n\t"
+            "jb sub_1lp                  \n\t"
+         "sub_1end:                      \n\t"
+
+            : // FIXASM: output regs/vars go here, e.g.:  "=m" (memory_var)
+
+            : // FIXASM: input regs, e.g.:  "c" (count), "S" (src), "D" (dest)
+
+            : "%eax", "%ebx", "%edi", "%esi" // CHECKASM: clobber list
+         );
+      }
+      return;
+
+      case 6:
+      case 7:
+      case 4:
+      case 5:
+      {
+         ShiftBpp.use = bpp << 3;
+         ShiftRem.use = 64 - ShiftBpp.use;
+         __asm__ (
+            "movl row, %%edi             \n\t"
+            "movl _dif, %%ebx            \n\t"
+            "movl %%edi, %%esi           \n\t" // lp = row
+            "addl bpp, %%edi             \n\t" // rp = row + bpp
+            // PRIME the pump (load the first Raw(x-bpp) data set
+            "movq -8(%%edi,%%ebx,), %%mm1 \n\t"
+         "sub_4lp:                       \n\t"
+            "psrlq $ShiftRem, %%mm1      \n\t" // Shift data for adding 1st bpp bytes
+                          // no need for mask; shift clears inactive bytes
+            "movq (%%edi,%%ebx,), %%mm0  \n\t"
+            "paddb %%mm1, %%mm0          \n\t"
+            // Add 2nd active group
+            "movq %%mm0, %%mm1           \n\t" // mov updated Raws to mm1
+            "psllq $ShiftBpp, %%mm1      \n\t" // shift data to position correctly
+                                   // there is no need for any mask
+                                   // since shift clears inactive bits/bytes
+            "addl $8, %%ebx              \n\t"
+            "paddb %%mm1, %%mm0          \n\t"
+            "cmpl _MMXLength, %%ebx      \n\t"
+            "movq %%mm0, -8(%%edi,%%ebx,) \n\t"
+            "movq %%mm0, %%mm1           \n\t" // Prep for doing 1st add at top of loop
+            "jb sub_4lp                  \n\t"
+
+            : // FIXASM: output regs/vars go here, e.g.:  "=m" (memory_var)
+
+            : // FIXASM: input regs, e.g.:  "c" (count), "S" (src), "D" (dest)
+
+            : "%ebx", "%edi", "%esi", "%mm0", "%mm1" // CHECKASM: clobber list
+         );
+      }
+      break;
+
+      case 2:
+      {
+         ActiveMask.use  = 0x00000000ffff0000;
+         ShiftBpp.use = 16;       // == 2 * 8
+         ShiftRem.use = 48;       // == 64 - 16
+         __asm__ (
+            "movq $ActiveMask, %%mm7     \n\t" // Load ActiveMask for 2nd active byte group
+            "movl _dif, %%ebx            \n\t"
+            "movq %%mm7, %%mm6           \n\t"
+            "movl row, %%edi             \n\t"
+            "psllq $ShiftBpp, %%mm6      \n\t" // Move mask in mm6 to cover 3rd active
+                                    //  byte group
+            "movl %%edi, %%esi           \n\t" // lp = row
+            "movq %%mm6, %%mm5           \n\t"
+            "addl bpp, %%edi             \n\t" // rp = row + bpp
+            "psllq $ShiftBpp, %%mm5      \n\t" // Move mask in mm5 to cover 4th active
+                                    //  byte group
+            // PRIME the pump (load the first Raw(x-bpp) data set
+            "movq -8(%%edi,%%ebx,), %%mm1 \n\t"
+         "sub_2lp:                       \n\t"
+            // Add 1st active group
+            "psrlq $ShiftRem, %%mm1      \n\t" // Shift data for adding 1st bpp bytes
+                                    // no need for mask; shift clears inactive
+                                    //  bytes
+            "movq (%%edi,%%ebx,), %%mm0  \n\t"
+            "paddb %%mm1, %%mm0          \n\t"
+            // Add 2nd active group
+            "movq %%mm0, %%mm1           \n\t" // mov updated Raws to mm1
+            "psllq $ShiftBpp, %%mm1      \n\t" // shift data to position correctly
+            "pand %%mm7, %%mm1           \n\t" // mask to use only 2nd active group
+            "paddb %%mm1, %%mm0          \n\t"
+            // Add 3rd active group
+            "movq %%mm0, %%mm1           \n\t" // mov updated Raws to mm1
+            "psllq $ShiftBpp, %%mm1      \n\t" // shift data to position correctly
+            "pand %%mm6, %%mm1           \n\t" // mask to use only 3rd active group
+            "paddb %%mm1, %%mm0          \n\t"
+            // Add 4th active group
+            "movq %%mm0, %%mm1           \n\t" // mov updated Raws to mm1
+            "psllq $ShiftBpp, %%mm1      \n\t" // shift data to position correctly
+            "pand %%mm5, %%mm1           \n\t" // mask to use only 4th active group
+            "addl $8, %%ebx              \n\t"
+            "paddb %%mm1, %%mm0          \n\t"
+            "cmpl _MMXLength, %%ebx      \n\t"
+            "movq %%mm0, -8(%%edi,%%ebx,) \n\t" // Write updated Raws back to array
+            "movq %%mm0, %%mm1           \n\t" // Prep for doing 1st add at top of loop
+            "jb sub_2lp                  \n\t"
+
+            : // FIXASM: output regs/vars go here, e.g.:  "=m" (memory_var)
+
+            : // FIXASM: input regs, e.g.:  "c" (count), "S" (src), "D" (dest)
+
+            : "%ebx", "%edi", "%esi", "%mm0", "%mm1", "%mm5", "%mm6", "%mm7" // CHECKASM: clobber list
+         );
+      }
+      break;
+      case 8:
+      {
+         __asm__ (
+            "movl row, %%edi             \n\t"
+            "movl _dif, %%ebx            \n\t"
+            "movl %%edi, %%esi           \n\t" // lp = row
+            "addl bpp, %%edi             \n\t" // rp = row + bpp
+            "movl _MMXLength, %%ecx      \n\t"
+            "movq -8(%%edi,%%ebx,), %%mm7 \n\t" // PRIME the pump (load the first
+                                    // Raw(x-bpp) data set
+            "andl $0x0000003f, %%ecx     \n\t" // calc bytes over mult of 64
+         "sub_8lp:                       \n\t"
+            "movq (%%edi,%%ebx,), %%mm0  \n\t" // Load Sub(x) for 1st 8 bytes
+            "paddb %%mm7, %%mm0          \n\t"
+            "movq 8(%%edi,%%ebx,), %%mm1 \n\t" // Load Sub(x) for 2nd 8 bytes
+            "movq %%mm0, (%%edi,%%ebx,)  \n\t" // Write Raw(x) for 1st 8 bytes
+                                   // Now mm0 will be used as Raw(x-bpp) for
+                                   // the 2nd group of 8 bytes.  This will be
+                                   // repeated for each group of 8 bytes with
+                                   // the 8th group being used as the Raw(x-bpp)
+                                   // for the 1st group of the next loop.
+            "paddb %%mm0, %%mm1          \n\t"
+            "movq 16(%%edi,%%ebx,), %%mm2 \n\t" // Load Sub(x) for 3rd 8 bytes
+            "movq %%mm1, 8(%%edi,%%ebx,) \n\t" // Write Raw(x) for 2nd 8 bytes
+            "paddb %%mm1, %%mm2          \n\t"
+            "movq 24(%%edi,%%ebx,), %%mm3 \n\t" // Load Sub(x) for 4th 8 bytes
+            "movq %%mm2, 16(%%edi,%%ebx,) \n\t" // Write Raw(x) for 3rd 8 bytes
+            "paddb %%mm2, %%mm3          \n\t"
+            "movq 32(%%edi,%%ebx,), %%mm4 \n\t" // Load Sub(x) for 5th 8 bytes
+            "movq %%mm3, 24(%%edi,%%ebx,) \n\t" // Write Raw(x) for 4th 8 bytes
+            "paddb %%mm3, %%mm4          \n\t"
+            "movq 40(%%edi,%%ebx,), %%mm5 \n\t" // Load Sub(x) for 6th 8 bytes
+            "movq %%mm4, 32(%%edi,%%ebx,) \n\t" // Write Raw(x) for 5th 8 bytes
+            "paddb %%mm4, %%mm5          \n\t"
+            "movq 48(%%edi,%%ebx,), %%mm6 \n\t" // Load Sub(x) for 7th 8 bytes
+            "movq %%mm5, 40(%%edi,%%ebx,) \n\t" // Write Raw(x) for 6th 8 bytes
+            "paddb %%mm5, %%mm6          \n\t"
+            "movq 56(%%edi,%%ebx,), %%mm7 \n\t" // Load Sub(x) for 8th 8 bytes
+            "movq %%mm6, 48(%%edi,%%ebx,) \n\t" // Write Raw(x) for 7th 8 bytes
+            "addl $64, %%ebx             \n\t"
+            "paddb %%mm6, %%mm7          \n\t"
+            "cmpl %%ecx, %%ebx           \n\t"
+            "movq %%mm7, -8(%%edi,%%ebx,) \n\t" // Write Raw(x) for 8th 8 bytes
+            "jb sub_8lp                  \n\t"
+            "cmpl _MMXLength, %%ebx      \n\t"
+            "jnb sub_8lt8                \n\t"
+         "sub_8lpA:                      \n\t"
+            "movq (%%edi,%%ebx,), %%mm0  \n\t"
+            "addl $8, %%ebx              \n\t"
+            "paddb %%mm7, %%mm0          \n\t"
+            "cmpl _MMXLength, %%ebx      \n\t"
+            "movq %%mm0, -8(%%edi,%%ebx,) \n\t" // use -8 to offset early add to ebx
+            "movq %%mm0, %%mm7           \n\t" // Move calculated Raw(x) data to mm1 to
+                                    // be the new Raw(x-bpp) for the next loop
+            "jb sub_8lpA                 \n\t"
+         "sub_8lt8:                      \n\t"
+
+            : // FIXASM: output regs/vars go here, e.g.:  "=m" (memory_var)
+
+            : // FIXASM: input regs, e.g.:  "c" (count), "S" (src), "D" (dest)
+
+            : "%ebx", "%ecx", "%edi", "%esi", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7" // CHECKASM: clobber list
+         );
+      }
+      break;
+
+      default:                // bpp greater than 8 bytes
+      {
+         __asm__ (
+            "movl _dif, %%ebx            \n\t"
+            "movl row, %%edi             \n\t"
+            "movl %%edi, %%esi           \n\t" // lp = row
+            "addl bpp, %%edi             \n\t" // rp = row + bpp
+         "sub_Alp:                       \n\t"
+            "movq (%%edi,%%ebx,), %%mm0  \n\t"
+            "movq (%%esi,%%ebx,), %%mm1  \n\t"
+            "addl $8, %%ebx              \n\t"
+            "paddb %%mm1, %%mm0          \n\t"
+            "cmpl _MMXLength, %%ebx      \n\t"
+            "movq %%mm0, -8(%%edi,%%ebx,) \n\t" // mov does not affect flags; -8 to offset
+                                   //  add ebx
+            "jb sub_Alp                  \n\t"
+
+            : // FIXASM: output regs/vars go here, e.g.:  "=m" (memory_var)
+
+            : // FIXASM: input regs, e.g.:  "c" (count), "S" (src), "D" (dest)
+
+            : "%ebx", "%edi", "%esi", "%mm0", "%mm1" // CHECKASM: clobber list
+         );
+      }
+      break;
+
+   } // end switch ( bpp )
+
+   __asm__ (
+      "movl _MMXLength, %%ebx      \n\t"
+      "movl row, %%edi             \n\t"
+      "cmpl _FullLength, %%ebx     \n\t"
+      "jnb sub_end                 \n\t"
+      "movl %%edi, %%esi           \n\t" // lp = row
+      "xorl %%eax, %%eax           \n\t"
+      "addl bpp, %%edi             \n\t" // rp = row + bpp
+   "sub_lp2:                       \n\t"
+      "movb (%%esi,%%ebx,), %%al   \n\t"
+      "addb %%al, (%%edi,%%ebx,)   \n\t"
+      "incl %%ebx                  \n\t"
+      "cmpl _FullLength, %%ebx     \n\t"
+      "jb sub_lp2                  \n\t"
+   "sub_end:                       \n\t"
+      "emms                        \n\t" // end MMX instructions
+
+      : // FIXASM: output regs/vars go here, e.g.:  "=m" (memory_var)
+
+      : // FIXASM: input regs, e.g.:  "c" (count), "S" (src), "D" (dest)
+
+      : "%eax", "%ebx", "%edi", "%esi" // CHECKASM: clobber list
+   );
+#endif /* GRR_GCC_MMX_CONVERTED */
+}
+
+// Optimized code for PNG Up filter decoder
+void
+png_read_filter_row_mmx_up(png_row_infop row_info, png_bytep row,
+                           png_bytep prev_row)
+{
+#ifdef GRR_GCC_MMX_CONVERTED
+   png_uint_32 len;
+
+   len = row_info->rowbytes;       // # of bytes to filter
+   __asm__ (
+      "movl row, %%edi             \n\t"
+      // get # of bytes to alignment
+      "movl %%edi, %%ecx           \n\t"
+      "xorl %%ebx, %%ebx           \n\t"
+      "addl $0x7, %%ecx            \n\t"
+      "xorl %%eax, %%eax           \n\t"
+      "andl $0xfffffff8, %%ecx     \n\t"
+      "movl prev_row, %%esi        \n\t"
+      "subl %%edi, %%ecx           \n\t"
+      "jz up_go                    \n\t"
+      // fix alignment
+   "up_lp1:                        \n\t"
+      "movb (%%edi,%%ebx,), %%al   \n\t"
+      "addb (%%esi,%%ebx,), %%al   \n\t"
+      "incl %%ebx                  \n\t"
+      "cmpl %%ecx, %%ebx           \n\t"
+      "movb %%al, -1(%%edi,%%ebx,) \n\t" // mov does not affect flags; -1 to offset inc ebx
+      "jb up_lp1                   \n\t"
+   "up_go:                         \n\t"
+      "movl len, %%ecx             \n\t"
+      "movl %%ecx, %%edx           \n\t"
+      "subl %%ebx, %%edx           \n\t" // subtract alignment fix
+      "andl $0x0000003f, %%edx     \n\t" // calc bytes over mult of 64
+      "subl %%edx, %%ecx           \n\t" // drop over bytes from length
+      // Unrolled loop - use all MMX registers and interleave to reduce
+      // number of branch instructions (loops) and reduce partial stalls
+   "up_loop:                       \n\t"
+      "movq (%%esi,%%ebx,), %%mm1  \n\t"
+      "movq (%%edi,%%ebx,), %%mm0  \n\t"
+      "movq 8(%%esi,%%ebx,), %%mm3 \n\t"
+      "paddb %%mm1, %%mm0          \n\t"
+      "movq 8(%%edi,%%ebx,), %%mm2 \n\t"
+      "movq %%mm0, (%%edi,%%ebx,)  \n\t"
+      "paddb %%mm3, %%mm2          \n\t"
+      "movq 16(%%esi,%%ebx,), %%mm5 \n\t"
+      "movq %%mm2, 8(%%edi,%%ebx,) \n\t"
+      "movq 16(%%edi,%%ebx,), %%mm4 \n\t"
+      "movq 24(%%esi,%%ebx,), %%mm7 \n\t"
+      "paddb %%mm5, %%mm4          \n\t"
+      "movq 24(%%edi,%%ebx,), %%mm6 \n\t"
+      "movq %%mm4, 16(%%edi,%%ebx,) \n\t"
+      "paddb %%mm7, %%mm6          \n\t"
+      "movq 32(%%esi,%%ebx,), %%mm1 \n\t"
+      "movq %%mm6, 24(%%edi,%%ebx,) \n\t"
+      "movq 32(%%edi,%%ebx,), %%mm0 \n\t"
+      "movq 40(%%esi,%%ebx,), %%mm3 \n\t"
+      "paddb %%mm1, %%mm0          \n\t"
+      "movq 40(%%edi,%%ebx,), %%mm2 \n\t"
+      "movq %%mm0, 32(%%edi,%%ebx,) \n\t"
+      "paddb %%mm3, %%mm2          \n\t"
+      "movq 48(%%esi,%%ebx,), %%mm5 \n\t"
+      "movq %%mm2, 40(%%edi,%%ebx,) \n\t"
+      "movq 48(%%edi,%%ebx,), %%mm4 \n\t"
+      "movq 56(%%esi,%%ebx,), %%mm7 \n\t"
+      "paddb %%mm5, %%mm4          \n\t"
+      "movq 56(%%edi,%%ebx,), %%mm6 \n\t"
+      "movq %%mm4, 48(%%edi,%%ebx,) \n\t"
+      "addl $64, %%ebx             \n\t"
+      "paddb %%mm7, %%mm6          \n\t"
+      "cmpl %%ecx, %%ebx           \n\t"
+      "movq %%mm6, -8(%%edi,%%ebx,) \n\t" // (+56)movq does not affect flags;
+                                     // -8 to offset add ebx
+      "jb up_loop                  \n\t"
+
+      "cmpl $0, %%edx              \n\t" // Test for bytes over mult of 64
+      "jz up_end                   \n\t"
+
+
+      // 2 lines added by lcreeve@netins.net
+      // (mail 11 Jul 98 in png-implement list)
+      "cmpl $8, %%edx              \n\t" //test for less than 8 bytes
+      "jb up_lt8                   \n\t"
+
+
+      "addl %%edx, %%ecx           \n\t"
+      "andl $0x00000007, %%edx     \n\t" // calc bytes over mult of 8
+      "subl %%edx, %%ecx           \n\t" // drop over bytes from length
+      "jz up_lt8                   \n\t"
+      // Loop using MMX registers mm0 & mm1 to update 8 bytes simultaneously
+   "up_lpA:                        \n\t"
+      "movq (%%esi,%%ebx,), %%mm1  \n\t"
+      "movq (%%edi,%%ebx,), %%mm0  \n\t"
+      "addl $8, %%ebx              \n\t"
+      "paddb %%mm1, %%mm0          \n\t"
+      "cmpl %%ecx, %%ebx           \n\t"
+      "movq %%mm0, -8(%%edi,%%ebx,) \n\t" // movq does not affect flags; -8 to offset add ebx
+      "jb up_lpA                   \n\t"
+      "cmpl $0, %%edx              \n\t" // Test for bytes over mult of 8
+      "jz up_end                   \n\t"
+   "up_lt8:                        \n\t"
+      "xorl %%eax, %%eax           \n\t"
+      "addl %%edx, %%ecx           \n\t" // move over byte count into counter
+      // Loop using x86 registers to update remaining bytes
+   "up_lp2:                        \n\t"
+      "movb (%%edi,%%ebx,), %%al   \n\t"
+      "addb (%%esi,%%ebx,), %%al   \n\t"
+      "incl %%ebx                  \n\t"
+      "cmpl %%ecx, %%ebx           \n\t"
+      "movb %%al, -1(%%edi,%%ebx,) \n\t" // mov does not affect flags; -1 to offset inc ebx
+      "jb up_lp2                   \n\t"
+   "up_end:                        \n\t"
+      // Conversion of filtered row completed
+      "emms                        \n\t" // End MMX instructions; prep for possible FP instrs.
+
+      : // FIXASM: output regs/vars go here, e.g.:  "=m" (memory_var)
+
+      : // FIXASM: input regs, e.g.:  "c" (count), "S" (src), "D" (dest)
+
+      : "%eax", "%ebx", "%ecx", "%edx", "%edi", "%esi", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7" // CHECKASM: clobber list
+   );
+#endif /* GRR_GCC_MMX_CONVERTED */
+}
+
+
+#if defined(PNG_HAVE_ASSEMBLER_READ_FILTER_ROW)
+
+// Optimized png_read_filter_row routines
+
+void
+png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep
+   row, png_bytep prev_row, int filter)
+{
+#ifdef PNG_DEBUG
+   char filnm[6];
+#endif
+   #define UseMMX 1
+
+   if (mmx_supported == 2)
+       mmx_supported = mmxsupport();
+
+#ifdef GRR_GCC_MMX_CONVERTED
+   if (!mmx_supported)
+#endif
+   {
+       png_read_filter_row_c(png_ptr, row_info, row, prev_row, filter);
+       return ;
+   }
+
+#ifdef PNG_DEBUG
+   png_debug(1, "in png_read_filter_row\n");
+#if (UseMMX == 1)
+   png_debug1(0,"%s, ", "MMX");
+#else
+   png_debug1(0,"%s, ", "x86");
+#endif
+   switch (filter)
+   {
+      case 0: sprintf(filnm, "None ");
+         break;
+      case 1: sprintf(filnm, "Sub  ");
+         break;
+      case 2: sprintf(filnm, "Up   ");
+         break;
+      case 3: sprintf(filnm, "Avg  ");
+         break;
+      case 4: sprintf(filnm, "Paeth");
+         break;
+      default: sprintf(filnm, "Unknw");
+         break;
+   }
+   png_debug2(0,"row=%5d, %s, ", png_ptr->row_number, filnm);
+   png_debug2(0, "pd=%2d, b=%d, ", (int)row_info->pixel_depth,
+      (int)((row_info->pixel_depth + 7) >> 3));
+   png_debug1(0,"len=%8d, ", row_info->rowbytes);
+#endif
+
+   switch (filter)
+   {
+      case PNG_FILTER_VALUE_NONE:
+         break;
+
+      case PNG_FILTER_VALUE_SUB:
+#if (UseMMX == 1)
+         if ((row_info->pixel_depth > 8) && (row_info->rowbytes >= 128))
+         {
+            png_read_filter_row_mmx_sub(row_info, row);
+         }
+         else
+#endif
+         {
+            png_uint_32 i;
+            png_uint_32 istop = row_info->rowbytes;
+            png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
+            png_bytep rp = row + bpp;
+            png_bytep lp = row;
+
+            for (i = bpp; i < istop; i++)
+            {
+               *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
+               rp++;
+            }
+         }  //end !UseMMX
+         break;
+
+      case PNG_FILTER_VALUE_UP:
+#if (UseMMX == 1)
+         if ((row_info->pixel_depth > 8) && (row_info->rowbytes >= 128))
+         {
+            png_read_filter_row_mmx_up(row_info, row, prev_row);
+         }
+         else
+#endif
+         {
+            png_bytep rp;
+            png_bytep pp;
+            png_uint_32 i;
+            for (i = 0, rp = row, pp = prev_row;
+               i < row_info->rowbytes; i++, rp++, pp++)
+            {
+                  *rp = (png_byte)(((int)(*rp) + (int)(*pp)) & 0xff);
+            }
+         }  //end !UseMMX
+         break;
+
+      case PNG_FILTER_VALUE_AVG:
+#if (UseMMX == 1)
+         if ((row_info->pixel_depth > 8) && (row_info->rowbytes >= 128))
+         {
+            png_read_filter_row_mmx_avg(row_info, row, prev_row);
+         }
+         else
+#endif
+         {
+            png_uint_32 i;
+            png_bytep rp = row;
+            png_bytep pp = prev_row;
+            png_bytep lp = row;
+            png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
+            png_uint_32 istop = row_info->rowbytes - bpp;
+
+            for (i = 0; i < bpp; i++)
+            {
+               *rp = (png_byte)(((int)(*rp) +
+                  ((int)(*pp++) >> 1)) & 0xff);
+               rp++;
+            }
+
+            for (i = 0; i < istop; i++)
+            {
+               *rp = (png_byte)(((int)(*rp) +
+                  ((int)(*pp++ + *lp++) >> 1)) & 0xff);
+               rp++;
+            }
+         }  //end !UseMMX
+         break;
+
+      case PNG_FILTER_VALUE_PAETH:
+#if (UseMMX == 1)
+         if ((row_info->pixel_depth > 8) && (row_info->rowbytes >= 128))
+         {
+            png_read_filter_row_mmx_paeth(row_info, row, prev_row);
+         }
+         else
+#endif
+         {
+            png_uint_32 i;
+            png_bytep rp = row;
+            png_bytep pp = prev_row;
+            png_bytep lp = row;
+            png_bytep cp = prev_row;
+            png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
+            png_uint_32 istop=row_info->rowbytes - bpp;
+
+            for (i = 0; i < bpp; i++)
+            {
+               *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
+               rp++;
+            }
+
+            for (i = 0; i < istop; i++)   // use leftover rp,pp
+            {
+               int a, b, c, pa, pb, pc, p;
+
+               a = *lp++;
+               b = *pp++;
+               c = *cp++;
+
+               p = b - c;
+               pc = a - c;
+
+#ifdef PNG_USE_ABS
+               pa = abs(p);
+               pb = abs(pc);
+               pc = abs(p + pc);
+#else
+               pa = p < 0 ? -p : p;
+               pb = pc < 0 ? -pc : pc;
+               pc = (p + pc) < 0 ? -(p + pc) : p + pc;
+#endif
+
+               /*
+                  if (pa <= pb && pa <= pc)
+                     p = a;
+                  else if (pb <= pc)
+                     p = b;
+                  else
+                     p = c;
+                */
+
+               p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
+
+               *rp = (png_byte)(((int)(*rp) + p) & 0xff);
+               rp++;
+            }
+         }  //end !UseMMX
+         break;
+
+      default:
+         png_error(png_ptr, "Bad adaptive filter type");
+         break;
+   }
+}
+
+#endif /* PNG_HAVE_ASSEMBLER_READ_FILTER_ROW */
+
+
+// GRR NOTES:  (1) the following code assumes 386 or better (pushfl/popfl)
+//             (2) all instructions compile with gcc 2.7.2.3 and later
+//             (3) the function is moved down here to prevent gcc from
+//                  inlining it in multiple places and then barfing be-
+//                  cause the ".NOT_SUPPORTED" label is multiply defined
+//             [is there a way to signal that a *single* function should
+//              not be inlined?  is there a way to modify the label for
+//              each inlined instance, e.g., by appending _1, _2, etc.?
+//              maybe if don't use leading "." in label name? (not tested)]
+
+#ifdef ORIG_THAT_USED_TO_CLOBBER_EBX
+
+int mmxsupport(void)
+{
+    int mmx_supported_local = 0;
+
+    __asm__ (
+//      ".byte  0x66          \n\t"  // convert 16-bit pushf to 32-bit pushfd
+//      "pushf                \n\t"  // save Eflag to stack
+        "pushfl               \n\t"  // save Eflag to stack
+        "popl %%eax           \n\t"  // get Eflag from stack into eax
+        "movl %%eax, %%ecx    \n\t"  // make another copy of Eflag in ecx
+        "xorl $0x200000, %%eax \n\t" // toggle ID bit in Eflag (i.e., bit 21)
+        "pushl %%eax          \n\t"  // save modified Eflag back to stack
+//      ".byte  0x66          \n\t"  // convert 16-bit popf to 32-bit popfd
+//      "popf                 \n\t"  // restore modified value to Eflag reg
+        "popfl                \n\t"  // restore modified value to Eflag reg
+        "pushfl               \n\t"  // save Eflag to stack
+        "popl %%eax           \n\t"  // get Eflag from stack
+        "xorl %%ecx, %%eax    \n\t"  // compare new Eflag with original Eflag
+        "jz .NOT_SUPPORTED    \n\t"  // if same, CPUID instr. is not supported
+
+        "xorl %%eax, %%eax    \n\t"  // set eax to zero
+//      ".byte  0x0f, 0xa2    \n\t"  // CPUID instruction (two-byte opcode)
+        "cpuid                \n\t"  // get the CPU identification info
+        "cmpl $1, %%eax       \n\t"  // make sure eax return non-zero value
+        "jl .NOT_SUPPORTED    \n\t"  // if eax is zero, MMX is not supported
+
+        "xorl %%eax, %%eax    \n\t"  // set eax to zero and...
+        "incl %%eax           \n\t"  // ...increment eax to 1.  This pair is
+                                     // faster than the instruction "mov eax, 1"
+        "cpuid                \n\t"  // get the CPU identification info again
+        "andl $0x800000, %%edx \n\t" // mask out all bits but MMX bit (23)
+        "cmpl $0, %%edx       \n\t"  // 0 = MMX not supported
+        "jz .NOT_SUPPORTED    \n\t"  // non-zero = yes, MMX IS supported
+
+        "movl $1, %0          \n\t"  // set return value to 1 and fall through
+
+    ".NOT_SUPPORTED:          \n\t"  // target label for jump instructions
+        "movl %0, %%eax       \n\t"  // move return value to eax
+                                     // DONE
+
+        : "=m" (mmx_supported_local) // %0 (output list:  memory only)
+
+        :                            // any variables used on input (none)
+
+        : "%eax", "%ebx",            // clobber list
+          "%ecx", "%edx"
+//      , "memory"   // if write to a variable gcc thought was in a reg
+//      , "cc"       // "condition codes" (flag bits)
+    );
+
+    //mmx_supported_local=0; // test code for force don't support MMX
+    //printf("MMX : %u (1=MMX supported)\n",mmx_supported_local);
+
+    return mmx_supported_local;
+}
+
+#else /* !ORIG_THAT_USED_TO_CLOBBER_EBX */
+
+int mmxsupport(void)
+{
+    __asm__ (
+        "pushl %%ebx          \n\t"  // ebx gets clobbered by CPUID instruction
+        "pushl %%ecx          \n\t"  // so does ecx...
+        "pushl %%edx          \n\t"  // ...and edx (but ecx & edx safe on Linux)
+//      ".byte  0x66          \n\t"  // convert 16-bit pushf to 32-bit pushfd
+//      "pushf                \n\t"  // save Eflag to stack
+        "pushfl               \n\t"  // save Eflag to stack
+        "popl %%eax           \n\t"  // get Eflag from stack into eax
+        "movl %%eax, %%ecx    \n\t"  // make another copy of Eflag in ecx
+        "xorl $0x200000, %%eax \n\t" // toggle ID bit in Eflag (i.e., bit 21)
+        "pushl %%eax          \n\t"  // save modified Eflag back to stack
+//      ".byte  0x66          \n\t"  // convert 16-bit popf to 32-bit popfd
+//      "popf                 \n\t"  // restore modified value to Eflag reg
+        "popfl                \n\t"  // restore modified value to Eflag reg
+        "pushfl               \n\t"  // save Eflag to stack
+        "popl %%eax           \n\t"  // get Eflag from stack
+        "xorl %%ecx, %%eax    \n\t"  // compare new Eflag with original Eflag
+        "jz .NOT_SUPPORTED    \n\t"  // if same, CPUID instr. is not supported
+
+        "xorl %%eax, %%eax    \n\t"  // set eax to zero
+//      ".byte  0x0f, 0xa2    \n\t"  // CPUID instruction (two-byte opcode)
+        "cpuid                \n\t"  // get the CPU identification info
+        "cmpl $1, %%eax       \n\t"  // make sure eax return non-zero value
+        "jl .NOT_SUPPORTED    \n\t"  // if eax is zero, MMX is not supported
+
+        "xorl %%eax, %%eax    \n\t"  // set eax to zero and...
+        "incl %%eax           \n\t"  // ...increment eax to 1.  This pair is
+                                     // faster than the instruction "mov eax, 1"
+        "cpuid                \n\t"  // get the CPU identification info again
+        "andl $0x800000, %%edx \n\t" // mask out all bits but MMX bit (23)
+        "cmpl $0, %%edx       \n\t"  // 0 = MMX not supported
+        "jz .NOT_SUPPORTED    \n\t"  // non-zero = yes, MMX IS supported
+
+        "movl $1, %%eax       \n\t"  // set return value to 1
+        "popl %%edx           \n\t"  // restore edx
+        "popl %%ecx           \n\t"  // restore ecx
+        "popl %%ebx           \n\t"  // restore ebx ("row" in png_do_interlace)
+        "ret                  \n\t"  // DONE:  have MMX support
+
+    ".NOT_SUPPORTED:          \n\t"  // target label for jump instructions
+        "movl $0, %%eax       \n\t"  // set return value to 0
+        "popl %%edx           \n\t"  // restore edx
+        "popl %%ecx           \n\t"  // restore ecx
+        "popl %%ebx           \n\t"  // restore ebx ("row" in png_do_interlace)
+//      "ret                  \n\t"  // DONE:  no MMX support
+                                     // (fall through to standard C "ret")
+
+        : // "=m" (mmx_supported_local) // %0 (output list:  memory only)
+
+        :                            // any variables used on input (none)
+
+        : "%eax"                     // clobber list
+//      , "%ebx", "%ecx", "%edx"     // GRR:  we handle these manually
+//      , "memory"   // if write to a variable gcc thought was in a reg
+//      , "cc"       // "condition codes" (flag bits)
+    );
+
+    //mmx_supported_local=0; // test code for force don't support MMX
+    //printf("MMX : %u (1=MMX supported)\n",mmx_supported_local);
+
+    //return mmx_supported_local;
+}
+
+#endif /* ?ORIG_THAT_USED_TO_CLOBBER_EBX */
+
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED && PNG_USE_PNGGCCRD */
+
+
diff --git a/pngget.c b/pngget.c
index 9bedfc6..c474a4f 100644
--- a/pngget.c
+++ b/pngget.c
@@ -1,11 +1,11 @@
 
 /* pngget.c - retrieval of values from info struct
  *
- * libpng 1.0.5h - December 10, 1999
+ * libpng 1.0.5q - February 5, 2000
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
+ * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson
  */
 
 #define PNG_INTERNAL
@@ -277,7 +277,7 @@
 {
    png_uint_32 retval = 0;
 
-   if (png_ptr != NULL && info_ptr != NULL && info_ptr->valid & PNG_INFO_pHYs)
+   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
    {
       png_debug1(1, "in %s retrieval function\n", "pHYs");
       if (res_x != NULL)
@@ -304,7 +304,7 @@
    return (retval);
 }
 #endif /* PNG_READ_pHYs_SUPPORTED */
-#endif  /* PNG_INCH_CONVERSIONS $$ PNG_FLOATING_POINT_SUPPORTED */
+#endif  /* PNG_INCH_CONVERSIONS && PNG_FLOATING_POINT_SUPPORTED */
 
 /* png_get_channels really belongs in here, too, but it's been around longer */
 
@@ -378,9 +378,9 @@
 #ifdef PNG_FIXED_POINT_SUPPORTED
 png_uint_32
 png_get_cHRM_fixed(png_structp png_ptr, png_infop info_ptr,
-   png_uint_32 *white_x, png_uint_32 *white_y, png_uint_32 *red_x,
-   png_uint_32 *red_y, png_uint_32 *green_x, png_uint_32 *green_y,
-   png_uint_32 *blue_x, png_uint_32 *blue_y)
+   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,
+   png_fixed_point *blue_x, png_fixed_point *blue_y)
 {
    if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
    {
@@ -423,10 +423,9 @@
    return (0);
 }
 #endif
-#ifdef PNG_FIXED_POINT_SUPPORTED
 png_uint_32
 png_get_gAMA_fixed(png_structp png_ptr, png_infop info_ptr,
-    png_uint_32 *int_file_gamma)
+    png_fixed_point *int_file_gamma)
 {
    if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
       && int_file_gamma != NULL)
@@ -438,7 +437,6 @@
    return (0);
 }
 #endif
-#endif
 
 #if defined(PNG_READ_sRGB_SUPPORTED)
 png_uint_32
@@ -459,7 +457,7 @@
 png_uint_32
 png_get_iCCP(png_structp png_ptr, png_infop info_ptr,
              png_charpp name, int *compression_type,
-             png_charpp profile, png_int_32 *proflen)
+             png_charpp profile, png_uint_32 *proflen)
 {
    if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP)
       && name != NULL && profile != NULL && proflen != NULL)
@@ -477,7 +475,7 @@
 }
 #endif
 
-#if defined(PNG_READ_sPLT_SUPPORTED) || defined(PNG_READ_zTXt_SUPPORTED)
+#if defined(PNG_READ_sPLT_SUPPORTED)
 png_uint_32
 png_get_spalettes(png_structp png_ptr, png_infop info_ptr,
              png_spalette_pp spalettes)
@@ -573,8 +571,8 @@
    png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type, int *nparams,
    png_charp *units, png_charpp *params)
 {
-   if (png_ptr != NULL && info_ptr != NULL && info_ptr->valid & PNG_INFO_pCAL &&
-      purpose != NULL && X0 != NULL && X1 != NULL && type != NULL &&
+   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL)
+      && purpose != NULL && X0 != NULL && X1 != NULL && type != NULL &&
       nparams != NULL && units != NULL && params != NULL)
    {
       png_debug1(1, "in %s retrieval function\n", "pCAL");
@@ -595,9 +593,10 @@
 #ifdef PNG_FLOATING_POINT_SUPPORTED
 png_uint_32
 png_get_sCAL(png_structp png_ptr, png_infop info_ptr,
-             png_charpp unit, double *width, double *height)
+             int *unit, double *width, double *height)
 {
-    if (png_ptr != NULL && info_ptr != NULL && info_ptr->valid & PNG_INFO_sCAL)
+    if (png_ptr != NULL && info_ptr != NULL &&
+       (info_ptr->valid & PNG_INFO_sCAL))
     {
         *unit = info_ptr->scal_unit;
         *width = info_ptr->scal_pixel_width;
@@ -606,12 +605,14 @@
     }
     return(0);
 }
-#endif
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
 png_uint_32
 png_get_sCAL_s(png_structp png_ptr, png_infop info_ptr,
-             png_charpp unit, png_charpp width, png_charpp height)
+             int *unit, png_charpp width, png_charpp height)
 {
-    if (png_ptr != NULL && info_ptr != NULL && info_ptr->valid & PNG_INFO_sCAL)
+    if (png_ptr != NULL && info_ptr != NULL &&
+       (info_ptr->valid & PNG_INFO_sCAL))
     {
         *unit = info_ptr->scal_unit;
         *width = info_ptr->scal_s_width;
@@ -621,6 +622,8 @@
     return(0);
 }
 #endif
+#endif
+#endif
 
 #if defined(PNG_READ_pHYs_SUPPORTED)
 png_uint_32
@@ -629,7 +632,8 @@
 {
    png_uint_32 retval = 0;
 
-   if (png_ptr != NULL && info_ptr != NULL && info_ptr->valid & PNG_INFO_pHYs)
+   if (png_ptr != NULL && info_ptr != NULL &&
+      (info_ptr->valid & PNG_INFO_pHYs))
    {
       png_debug1(1, "in %s retrieval function\n", "pHYs");
       if (res_x != NULL)
@@ -656,8 +660,8 @@
 png_get_PLTE(png_structp png_ptr, png_infop info_ptr, png_colorp *palette,
    int *num_palette)
 {
-   if (png_ptr != NULL && info_ptr != NULL && info_ptr->valid & PNG_INFO_PLTE &&
-       palette != NULL)
+   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_PLTE)
+       && palette != NULL)
    {
       png_debug1(1, "in %s retrieval function\n", "PLTE");
       *palette = info_ptr->palette;
@@ -672,8 +676,8 @@
 png_uint_32
 png_get_sBIT(png_structp png_ptr, png_infop info_ptr, png_color_8p *sig_bit)
 {
-   if (png_ptr != NULL && info_ptr != NULL && info_ptr->valid & PNG_INFO_sBIT &&
-       sig_bit != NULL)
+   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT)
+      && sig_bit != NULL)
    {
       png_debug1(1, "in %s retrieval function\n", "sBIT");
       *sig_bit = &(info_ptr->sig_bit);
@@ -707,8 +711,8 @@
 png_uint_32
 png_get_tIME(png_structp png_ptr, png_infop info_ptr, png_timep *mod_time)
 {
-   if (png_ptr != NULL && info_ptr != NULL && info_ptr->valid & PNG_INFO_tIME &&
-       mod_time != NULL)
+   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME)
+       && mod_time != NULL)
    {
       png_debug1(1, "in %s retrieval function\n", "tIME");
       *mod_time = &(info_ptr->mod_time);
@@ -724,7 +728,7 @@
    png_bytep *trans, int *num_trans, png_color_16p *trans_values)
 {
    png_uint_32 retval = 0;
-   if (png_ptr != NULL && info_ptr != NULL && info_ptr->valid & PNG_INFO_tRNS)
+   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
    {
       png_debug1(1, "in %s retrieval function\n", "tRNS");
       if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
@@ -775,3 +779,12 @@
    return png_ptr->rgb_to_gray_status;
 }
 #endif
+
+#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
+png_voidp
+png_get_user_chunk_ptr(png_structp png_ptr)
+{
+   return (png_ptr->user_chunk_ptr);
+}
+#endif
+
diff --git a/pngmem.c b/pngmem.c
index f042ae9..840ea0c 100644
--- a/pngmem.c
+++ b/pngmem.c
@@ -1,11 +1,11 @@
 
 /* pngmem.c - stub functions for memory allocation
  *
- * libpng 1.0.5h - December 10, 1999
+ * libpng 1.0.5q - February 5, 2000
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
+ * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson
  *
  * This file provides a location for all memory allocation.  Users who
  * need special memory handling are expected to supply replacement
diff --git a/pngnow.png b/pngnow.png
index 6a1f497..174b5fa 100644
--- a/pngnow.png
+++ b/pngnow.png
Binary files differ
diff --git a/pngpread.c b/pngpread.c
index 9fa4720..d789308 100644
--- a/pngpread.c
+++ b/pngpread.c
@@ -1,11 +1,11 @@
 
 /* pngpread.c - read a png file in push mode
  *
- * libpng 1.0.5h - December 10, 1999
+ * libpng 1.0.5q - February 5, 2000
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
+ * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson
  */
 
 #define PNG_INTERNAL
@@ -151,27 +151,30 @@
 #if defined(PNG_READ_hIST_SUPPORTED)
       PNG_hIST;
 #endif
+#if defined(PNG_READ_iCCP_SUPPORTED)
+      PNG_iCCP;
+#endif
+#if defined(PNG_READ_iTXt_SUPPORTED)
+      PNG_iTXt;
+#endif
 #if defined(PNG_READ_oFFs_SUPPORTED)
       PNG_oFFs;
 #endif
 #if defined(PNG_READ_pCAL_SUPPORTED)
       PNG_pCAL;
 #endif
-#if defined(PNG_READ_sCAL_SUPPORTED)
-      PNG_sCAL;
-#endif
 #if defined(PNG_READ_pHYs_SUPPORTED)
       PNG_pHYs;
 #endif
 #if defined(PNG_READ_sBIT_SUPPORTED)
       PNG_sBIT;
 #endif
+#if defined(PNG_READ_sCAL_SUPPORTED)
+      PNG_sCAL;
+#endif
 #if defined(PNG_READ_sRGB_SUPPORTED)
       PNG_sRGB;
 #endif
-#if defined(PNG_READ_iCCP_SUPPORTED)
-      PNG_iCCP;
-#endif
 #if defined(PNG_READ_sPLT_SUPPORTED)
       PNG_sPLT;
 #endif
@@ -447,7 +450,7 @@
    }
 #endif
 #if defined(PNG_READ_iTXt_SUPPORTED)
-   else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))
+   else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4))
    {
       png_push_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
    }
@@ -1023,6 +1026,7 @@
       text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
       text_ptr->lang = (char *)NULL;
       text_ptr->key = key;
+      text_ptr->lang_key = (char *)NULL;
       text_ptr->text = text;
 
       png_set_text(png_ptr, info_ptr, text_ptr, 1);
@@ -1201,8 +1205,9 @@
 
       text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
       text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt;
-      text_ptr->lang = (char *)NULL;
       text_ptr->key = key;
+      text_ptr->lang = (char *)NULL;
+      text_ptr->lang_key = (char *)NULL;
       text_ptr->text = text;
 
       png_set_text(png_ptr, info_ptr, text_ptr, 1);
@@ -1246,6 +1251,7 @@
 void
 png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr)
 {
+
    if (png_ptr->buffer_size && png_ptr->current_text_left)
    {
       png_size_t text_size;
@@ -1261,9 +1267,11 @@
    if (!(png_ptr->current_text_left))
    {
       png_textp text_ptr;
-      png_charp text;
-      png_charp lang;
       png_charp key;
+      int comp_flag = 0;
+      png_charp lang;
+      png_charp lang_key;
+      png_charp text;
 
       if (png_ptr->buffer_size < 4)
       {
@@ -1278,26 +1286,36 @@
          return;
 #endif
 
-      lang = png_ptr->current_text;
+      key = png_ptr->current_text;
       png_ptr->current_text = 0;
 
-      for (key = lang; *key; key++)
+      for (lang = key; *lang; lang++)
          /* empty loop */ ;
 
-      if (key != lang + png_ptr->current_text_size)
-         key++;
+      if (lang != key + png_ptr->current_text_size)
+         lang++;
 
-      for (text = key; *text; text++)
+      comp_flag = *lang++;
+      lang++;     /* skip comp_type, always zero */
+
+      for (lang_key = lang; *lang_key; lang_key++)
+         /* empty loop */ ;
+      lang_key++;        /* skip NUL separator */
+
+      for (text = lang_key; *text; text++)
          /* empty loop */ ;
 
       if (text != key + png_ptr->current_text_size)
          text++;
 
       text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
-      text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
-      text_ptr->lang = lang;
+      text_ptr->compression = comp_flag + 2;
       text_ptr->key = key;
+      text_ptr->lang = lang;
+      text_ptr->lang_key = lang_key;
       text_ptr->text = text;
+      text_ptr->text_length = 0;
+      text_ptr->itxt_length = png_strlen(text);
 
       png_set_text(png_ptr, info_ptr, text_ptr, 1);
 
@@ -1307,25 +1325,70 @@
 #endif
 
 /* This function is called when we haven't found a handler for this
- * chunk.  In the future we will have code here that can handle
- * user-defined callback functions for unknown chunks before they are
- * ignored or cause an error.  If there isn't a problem with the
- * chunk itself (ie a bad chunk name or a critical chunk), the chunk
- * is (currently) silently ignored.
+ * chunk.  If there isn't a problem with the chunk itself (ie a bad chunk
+ * name or a critical chunk), the chunk is (currently) silently ignored.
  */
 void
 png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
+   png_uint_32 skip=0;
    png_check_chunk_name(png_ptr, png_ptr->chunk_name);
 
    if (!(png_ptr->chunk_name[0] & 0x20))
    {
-      png_chunk_error(png_ptr, "unknown critical chunk");
-      /* to quiet some compiler warnings */
-      if(info_ptr == NULL) return;
+      if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
+           HANDLE_CHUNK_ALWAYS
+#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
+           && png_ptr->read_user_chunk_fn == (png_user_chunk_ptr)NULL
+#endif
+         )
+         png_chunk_error(png_ptr, "unknown critical chunk");
+
+      /* to quiet compiler warnings about unused info_ptr */
+      if (info_ptr == NULL)
+         return;
    }
 
-   png_push_crc_skip(png_ptr, length);
+#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
+   if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
+   {
+       png_unknown_chunk chunk;
+
+#ifdef PNG_MAX_MALLOC_64K
+       if (length > (png_uint_32)65535L)
+       {
+           png_warning(png_ptr, "unknown chunk too large to fit in memory");
+           skip = length - (png_uint_32)65535L;
+           length = (png_uint_32)65535L;
+       }
+#endif
+
+       strcpy((png_charp)chunk.name, (png_charp)png_ptr->chunk_name);
+       chunk.data = (png_bytep)png_malloc(png_ptr, length);
+       png_crc_read(png_ptr, chunk.data, length);
+       chunk.size = length;
+#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
+       if(png_ptr->read_user_chunk_fn != (png_user_chunk_ptr)NULL)
+       {
+          /* callback to user unknown chunk handler */
+          if ((*(png_ptr->read_user_chunk_fn)) (png_ptr, &chunk) <= 0)
+          {
+             if (!(png_ptr->chunk_name[0] & 0x20))
+                if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
+                     HANDLE_CHUNK_ALWAYS)
+                   png_chunk_error(png_ptr, "unknown critical chunk");
+          }
+             png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
+       }
+       else
+#endif
+          png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
+       png_free(png_ptr, chunk.data);
+   }
+   else
+#endif
+      skip=length;
+   png_push_crc_skip(png_ptr, skip);
 }
 
 void
diff --git a/pngread.c b/pngread.c
index cdfc018..ba356dc 100644
--- a/pngread.c
+++ b/pngread.c
@@ -1,11 +1,11 @@
 
 /* pngread.c - read a PNG file
  *
- * libpng 1.0.5h - December 10, 1999
+ * libpng 1.0.5q - February 5, 2000
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
+ * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson
  *
  * This file contains routines that an application calls directly to
  * read a PNG file or stream.
@@ -34,9 +34,13 @@
 #endif /* PNG_USER_MEM_SUPPORTED */
 
    png_structp png_ptr;
+
+#ifdef PNG_SETJMP_SUPPORTED
 #ifdef USE_FAR_KEYWORD
    jmp_buf jmpbuf;
 #endif
+#endif
+
    png_debug(1, "in png_create_read_struct\n");
 #ifdef PNG_USER_MEM_SUPPORTED
    if ((png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,
@@ -47,6 +51,8 @@
    {
       return (png_structp)NULL;
    }
+
+#ifdef PNG_SETJMP_SUPPORTED
 #ifdef USE_FAR_KEYWORD
    if (setjmp(jmpbuf))
 #else
@@ -60,6 +66,7 @@
 #ifdef USE_FAR_KEYWORD
    png_memcpy(png_ptr->jmpbuf,jmpbuf,sizeof(jmp_buf));
 #endif
+#endif
 
 #ifdef PNG_USER_MEM_SUPPORTED
    png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn);
@@ -110,17 +117,24 @@
 void
 png_read_init(png_structp png_ptr)
 {
+#ifdef PNG_SETJMP_SUPPORTED
    jmp_buf tmp_jmp;  /* to save current jump buffer */
+#endif
 
    png_debug(1, "in png_read_init\n");
+
+#ifdef PNG_SETJMP_SUPPORTED
    /* save jump buffer and error functions */
    png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
+#endif
 
    /* reset all variables to 0 */
    png_memset(png_ptr, 0, sizeof (png_struct));
 
+#ifdef PNG_SETJMP_SUPPORTED
    /* restore jump buffer */
    png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
+#endif
 
    /* initialize zbuf - compression buffer */
    png_ptr->zbuf_size = PNG_ZBUF_SIZE;
@@ -214,7 +228,7 @@
 #if defined(PNG_READ_sBIT_SUPPORTED)
       PNG_sBIT;
 #endif
-#if defined(PNG_READ_pCAL_SUPPORTED)
+#if defined(PNG_READ_sCAL_SUPPORTED)
       PNG_sCAL;
 #endif
 #if defined(PNG_READ_sPLT_SUPPORTED)
@@ -253,10 +267,29 @@
        */
       if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4))
          png_handle_IHDR(png_ptr, info_ptr, length);
-      else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
-         png_handle_PLTE(png_ptr, info_ptr, length);
       else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
          png_handle_IEND(png_ptr, info_ptr, length);
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+      else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name))
+      {
+         if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
+            png_ptr->mode |= PNG_HAVE_IDAT;
+         png_handle_unknown(png_ptr, info_ptr, length);
+         if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
+            png_ptr->mode |= PNG_HAVE_PLTE;
+         else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
+         {
+            if (!(png_ptr->mode & PNG_HAVE_IHDR))
+               png_error(png_ptr, "Missing IHDR before IDAT");
+            else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
+                     !(png_ptr->mode & PNG_HAVE_PLTE))
+               png_error(png_ptr, "Missing PLTE before IDAT");
+            break;
+         }
+      }
+#endif
+      else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
+         png_handle_PLTE(png_ptr, info_ptr, length);
       else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
       {
          if (!(png_ptr->mode & PNG_HAVE_IHDR))
@@ -421,7 +454,7 @@
       switch (png_ptr->pass)
       {
          case 0:
-            if (png_ptr->row_number & 7)
+            if (png_ptr->row_number & 0x07)
             {
                if (dsp_row != NULL)
                   png_combine_row(png_ptr, dsp_row,
@@ -431,7 +464,7 @@
             }
             break;
          case 1:
-            if ((png_ptr->row_number & 7) || png_ptr->width < 5)
+            if ((png_ptr->row_number & 0x07) || png_ptr->width < 5)
             {
                if (dsp_row != NULL)
                   png_combine_row(png_ptr, dsp_row,
@@ -441,7 +474,7 @@
             }
             break;
          case 2:
-            if ((png_ptr->row_number & 7) != 4)
+            if ((png_ptr->row_number & 0x07) != 4)
             {
                if (dsp_row != NULL && (png_ptr->row_number & 4))
                   png_combine_row(png_ptr, dsp_row,
@@ -546,6 +579,7 @@
    png_ptr->row_info.rowbytes = ((png_ptr->row_info.width *
       (png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3);
 
+   if(png_ptr->row_buf[0])
    png_read_filter_row(png_ptr, &(png_ptr->row_info),
       png_ptr->row_buf + 1, png_ptr->prev_row + 1,
       (int)(png_ptr->row_buf[0]));
@@ -607,7 +641,7 @@
  * not called png_set_interlace_handling(), the display_row buffer will
  * be ignored, so pass NULL to it.
  *
- * [*] png_handle_alpha() does not exist yet, as of libpng version 1.0.5h.
+ * [*] png_handle_alpha() does not exist yet, as of libpng version 1.0.5q.
  */
 
 void
@@ -656,7 +690,7 @@
  * only call this function once.  If you desire to have an image for
  * each pass of a interlaced image, use png_read_rows() instead.
  *
- * [*] png_handle_alpha() does not exist yet, as of libpng version 1.0.5h.
+ * [*] png_handle_alpha() does not exist yet, as of libpng version 1.0.5q.
  */
 void
 png_read_image(png_structp png_ptr, png_bytepp image)
@@ -743,7 +777,7 @@
 #if defined(PNG_READ_sBIT_SUPPORTED)
       PNG_sBIT;
 #endif
-#if defined(PNG_READ_pCAL_SUPPORTED)
+#if defined(PNG_READ_sCAL_SUPPORTED)
       PNG_sCAL;
 #endif
 #if defined(PNG_READ_sPLT_SUPPORTED)
@@ -776,6 +810,23 @@
 
       if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4))
          png_handle_IHDR(png_ptr, info_ptr, length);
+      else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
+         png_handle_IEND(png_ptr, info_ptr, length);
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+      else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name))
+      {
+         if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
+         {
+            if (length > 0 || png_ptr->mode & PNG_AFTER_IDAT)
+               png_error(png_ptr, "Too many IDAT's found");
+         }
+         else
+            png_ptr->mode |= PNG_AFTER_IDAT;
+         png_handle_unknown(png_ptr, info_ptr, length);
+         if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
+            png_ptr->mode |= PNG_HAVE_PLTE;
+      }
+#endif
       else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
       {
          /* Zero length IDATs are legal after the last IDAT has been
@@ -788,8 +839,6 @@
       }
       else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
          png_handle_PLTE(png_ptr, info_ptr, length);
-      else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
-         png_handle_IEND(png_ptr, info_ptr, length);
 #if defined(PNG_READ_bKGD_SUPPORTED)
       else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4))
          png_handle_bKGD(png_ptr, info_ptr, length);
@@ -933,7 +982,9 @@
 void
 png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr)
 {
+#ifdef PNG_SETJMP_SUPPORTED
    jmp_buf tmp_jmp;
+#endif
    png_error_ptr error_fn;
    png_error_ptr warning_fn;
    png_voidp error_ptr;
@@ -1020,7 +1071,9 @@
    /* Save the important info out of the png_struct, in case it is
     * being used again.
     */
+#ifdef PNG_SETJMP_SUPPORTED
    png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
+#endif
 
    error_fn = png_ptr->error_fn;
    warning_fn = png_ptr->warning_fn;
@@ -1038,7 +1091,10 @@
    png_ptr->free_fn = free_fn;
 #endif
 
+#ifdef PNG_SETJMP_SUPPORTED
    png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
+#endif
+
 }
 
 void
@@ -1046,3 +1102,131 @@
 {
    png_ptr->read_row_fn = read_row_fn;
 }
+
+#if defined(PNG_INFO_IMAGE_SUPPORTED)
+void png_read_png(png_structp png_ptr, png_infop info_ptr,
+                           int transforms,
+                           voidp params)
+{
+   int row;
+
+   if(transforms == 0 || params == (voidp)NULL)
+      /* quiet compiler warnings */ ;
+
+#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
+   /* invert the alpha channel from opacity to transparency */
+   if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
+       png_set_invert_alpha(png_ptr);
+#endif
+
+   /* The call to png_read_info() gives us all of the information from the
+    * PNG file before the first IDAT (image data chunk).
+    */
+   png_read_info(png_ptr, info_ptr);
+
+   /* -------------- image transformations start here ------------------- */
+
+#if defined(PNG_READ_16_TO_8_SUPPORTED)
+   /* tell libpng to strip 16 bit/color files down to 8 bits/color */
+   if (transforms & PNG_TRANSFORM_STRIP_16)
+       png_set_strip_16(png_ptr);
+#endif
+
+#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
+   /* Strip alpha bytes from the input data without combining with the
+    * background (not recommended).
+    */
+   if (transforms & PNG_TRANSFORM_STRIP_ALPHA)
+       png_set_strip_alpha(png_ptr);
+#endif
+
+#if defined(PNG_READ_PACK_SUPPORTED)
+   /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single
+    * byte into separate bytes (useful for paletted and grayscale images).
+    */
+   if (transforms & PNG_TRANSFORM_PACKING)
+       png_set_packing(png_ptr);
+#endif
+
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+   /* Change the order of packed pixels to least significant bit first
+    * (not useful if you are using png_set_packing). */
+   if (transforms & PNG_TRANSFORM_PACKSWAP)
+       png_set_packswap(png_ptr);
+#endif
+
+#if defined(PNG_READ_EXPAND_SUPPORTED)
+   /* Expand paletted colors into true RGB triplets
+    * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel
+    * Expand paletted or RGB images with transparency to full alpha
+    * channels so the data will be available as RGBA quartets.
+    */
+   if (transforms & PNG_TRANSFORM_EXPAND)
+       if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
+           png_set_expand(png_ptr);
+#endif
+
+   /* We don't handle background color or gamma transformation or dithering. */
+
+#if defined(PNG_READ_INVERT_SUPPORTED)
+   /* invert monochrome files to have 0 as white and 1 as black */
+   if (transforms & PNG_TRANSFORM_INVERT_MONO)
+       png_set_invert_mono(png_ptr);
+#endif
+
+#if defined(PNG_READ_SHIFT_SUPPORTED)
+   /* If you want to shift the pixel values from the range [0,255] or
+    * [0,65535] to the original [0,7] or [0,31], or whatever range the
+    * colors were originally in:
+    */
+   if ((transforms & PNG_TRANSFORM_SHIFT)
+       && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT))
+   {
+      png_color_8p sig_bit;
+
+      png_get_sBIT(png_ptr, info_ptr, &sig_bit);
+      png_set_shift(png_ptr, sig_bit);
+   }
+#endif
+
+#if defined(PNG_READ_BGR_SUPPORTED)
+   /* flip the RGB pixels to BGR (or RGBA to BGRA) */
+   if (transforms & PNG_TRANSFORM_BGR)
+       png_set_bgr(png_ptr);
+#endif
+
+#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
+   /* swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */
+   if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
+       png_set_swap_alpha(png_ptr);
+#endif
+
+#if defined(PNG_READ_SWAP_SUPPORTED)
+   /* swap bytes of 16 bit files to least significant byte first */
+   if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
+       png_set_swap(png_ptr);
+#endif
+
+   /* We don't handle adding filler bytes */
+
+   /* Optional call to gamma correct and add the background to the palette
+    * and update info structure.  REQUIRED if you are expecting libpng to
+    * update the palette for you (ie you selected such a transform above).
+    */
+   png_read_update_info(png_ptr, info_ptr);
+
+   /* -------------- image transformations end here ------------------- */
+
+   info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr,
+                                         info_ptr->height * sizeof(png_bytep));
+   for (row = 0; row < (int)info_ptr->height; row++)
+       info_ptr->row_pointers[row] = png_malloc(png_ptr,
+                                      png_get_rowbytes(png_ptr, info_ptr));
+
+   png_read_image(png_ptr, info_ptr->row_pointers);
+   info_ptr->valid |= PNG_INFO_IDAT;
+
+   /* read rest of file, and get additional chunks in info_ptr - REQUIRED */
+   png_read_end(png_ptr, info_ptr);
+}
+#endif
diff --git a/pngrio.c b/pngrio.c
index b5e9fc4..92d9d50 100644
--- a/pngrio.c
+++ b/pngrio.c
@@ -1,11 +1,11 @@
 
 /* pngrio.c - functions for data input
  *
- * libpng 1.0.5h - December 10, 1999
+ * libpng 1.0.5q - February 5, 2000
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
+ * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson
  *
  * This file provides a location for all input.  Users who need
  * special handling are expected to write a function that has the same
diff --git a/pngrtran.c b/pngrtran.c
index 894139b..a76a548 100644
--- a/pngrtran.c
+++ b/pngrtran.c
@@ -1,11 +1,11 @@
 
 /* pngrtran.c - transforms the data in a row for PNG readers
  *
- * libpng 1.0.5h - December 10, 1999
+ * libpng 1.0.5q - February 5, 2000
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
+ * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson
  *
  * This file contains functions optionally called by an application
  * in order to tell libpng how to handle data when reading a PNG.
@@ -367,7 +367,7 @@
                      {
                         int j, next_j;
 
-                        if (num_new_palette & 1)
+                        if (num_new_palette & 0x01)
                         {
                            j = p->left;
                            next_j = p->right;
@@ -897,8 +897,8 @@
 #endif
 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
    /* No GAMMA transformation */
-   if (png_ptr->transformations & PNG_BACKGROUND &&
-       color_type == PNG_COLOR_TYPE_PALETTE)
+   if ((png_ptr->transformations & PNG_BACKGROUND) &&
+       (color_type == PNG_COLOR_TYPE_PALETTE))
    {
       int i;
       int istop = (int)png_ptr->num_trans;
@@ -931,7 +931,7 @@
 
 #if defined(PNG_READ_SHIFT_SUPPORTED)
    if ((png_ptr->transformations & PNG_SHIFT) &&
-      color_type == PNG_COLOR_TYPE_PALETTE)
+      (color_type == PNG_COLOR_TYPE_PALETTE))
    {
       png_uint_16 i;
       png_uint_16 istop = png_ptr->num_palette;
@@ -1009,7 +1009,7 @@
 #endif
 
 #if defined(PNG_READ_16_TO_8_SUPPORTED)
-   if ((png_ptr->transformations & PNG_16_TO_8) && info_ptr->bit_depth == 16)
+   if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16))
       info_ptr->bit_depth = 8;
 #endif
 
@@ -1026,7 +1026,7 @@
 #endif
 
 #if defined(PNG_READ_PACK_SUPPORTED)
-   if ((png_ptr->transformations & PNG_PACK) && info_ptr->bit_depth < 8)
+   if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
       info_ptr->bit_depth = 8;
 #endif
 
@@ -1057,9 +1057,9 @@
 
 #if defined(PNG_READ_FILLER_SUPPORTED)
    /* STRIP_ALPHA and FILLER allowed:  MASK_ALPHA bit stripped above */
-   if (png_ptr->transformations & PNG_FILLER &&
-       (info_ptr->color_type == PNG_COLOR_TYPE_RGB ||
-        info_ptr->color_type == PNG_COLOR_TYPE_GRAY))
+   if ((png_ptr->transformations & PNG_FILLER) &&
+       ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
+       (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
       info_ptr->channels++;
 #endif
 
@@ -1177,7 +1177,7 @@
 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
    /* if gray -> RGB, do so now only if background is non-gray; else do later
     * for performance reasons */
-   if (png_ptr->transformations & PNG_GRAY_TO_RGB &&
+   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
        !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
       png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
 #endif
@@ -1251,8 +1251,8 @@
 
 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
    /* if gray -> RGB, do so now only if we did not do so above */
-   if (png_ptr->transformations & PNG_GRAY_TO_RGB &&
-       png_ptr->mode & PNG_BACKGROUND_IS_GRAY)
+   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
+       (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
       png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
 #endif
 
@@ -1330,10 +1330,10 @@
          {
             png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
             png_bytep dp = row + (png_size_t)row_width - 1;
-            png_uint_32 shift = 7 - (int)((row_width + 7) & 7);
+            png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
             for (i = 0; i < row_width; i++)
             {
-               *dp = (png_byte)((*sp >> shift) & 0x1);
+               *dp = (png_byte)((*sp >> shift) & 0x01);
                if (shift == 7)
                {
                   shift = 0;
@@ -1351,10 +1351,10 @@
 
             png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
             png_bytep dp = row + (png_size_t)row_width - 1;
-            png_uint_32 shift = (int)((3 - ((row_width + 3) & 3)) << 1);
+            png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
             for (i = 0; i < row_width; i++)
             {
-               *dp = (png_byte)((*sp >> shift) & 0x3);
+               *dp = (png_byte)((*sp >> shift) & 0x03);
                if (shift == 6)
                {
                   shift = 0;
@@ -1371,10 +1371,10 @@
          {
             png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
             png_bytep dp = row + (png_size_t)row_width - 1;
-            png_uint_32 shift = (int)((1 - ((row_width + 1) & 1)) << 2);
+            png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
             for (i = 0; i < row_width; i++)
             {
-               *dp = (png_byte)((*sp >> shift) & 0xf);
+               *dp = (png_byte)((*sp >> shift) & 0x0f);
                if (shift == 4)
                {
                   shift = 0;
@@ -1674,9 +1674,15 @@
             for (i = 0; i < row_width; i++)
             {
                *(--dp) = (png_byte)(255 - *(--sp));
+
+/*             This does nothing:
                *(--dp) = *(--sp);
                *(--dp) = *(--sp);
                *(--dp) = *(--sp);
+               We can replace it with:
+*/
+               sp-=3;
+               dp=sp;
             }
          }
          /* This inverts the alpha channel in RRGGBBAA */
@@ -1690,12 +1696,18 @@
             {
                *(--dp) = (png_byte)(255 - *(--sp));
                *(--dp) = (png_byte)(255 - *(--sp));
+
+/*             This does nothing:
                *(--dp) = *(--sp);
                *(--dp) = *(--sp);
                *(--dp) = *(--sp);
                *(--dp) = *(--sp);
                *(--dp) = *(--sp);
                *(--dp) = *(--sp);
+               We can replace it with:
+*/
+               sp-=6;
+               dp=sp;
             }
          }
       }
@@ -1725,8 +1737,12 @@
             {
                *(--dp) = (png_byte)(255 - *(--sp));
                *(--dp) = (png_byte)(255 - *(--sp));
+/*
                *(--dp) = *(--sp);
                *(--dp) = *(--sp);
+*/
+               sp-=2;
+               dp=sp;
             }
          }
       }
@@ -2518,7 +2534,7 @@
                   shift = 7;
                   for (i = 0; i < row_width; i++)
                   {
-                     if ((png_uint_16)((*sp >> shift) & 0x1)
+                     if ((png_uint_16)((*sp >> shift) & 0x01)
                         == trans_values->gray)
                      {
                         *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
@@ -2543,7 +2559,7 @@
                      shift = 6;
                      for (i = 0; i < row_width; i++)
                      {
-                        if ((png_uint_16)((*sp >> shift) & 0x3)
+                        if ((png_uint_16)((*sp >> shift) & 0x03)
                             == trans_values->gray)
                         {
                            *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
@@ -2551,9 +2567,9 @@
                         }
                         else
                         {
-                           png_byte p = (png_byte)((*sp >> shift) & 0x3);
+                           png_byte p = (png_byte)((*sp >> shift) & 0x03);
                            png_byte g = (png_byte)((gamma_table [p | (p << 2) |
-                               (p << 4) | (p << 6)] >> 6) & 0x3);
+                               (p << 4) | (p << 6)] >> 6) & 0x03);
                            *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
                            *sp |= (png_byte)(g << shift);
                         }
@@ -2573,7 +2589,7 @@
                      shift = 6;
                      for (i = 0; i < row_width; i++)
                      {
-                        if ((png_uint_16)((*sp >> shift) & 0x3)
+                        if ((png_uint_16)((*sp >> shift) & 0x03)
                             == trans_values->gray)
                         {
                            *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
@@ -2599,7 +2615,7 @@
                      shift = 4;
                      for (i = 0; i < row_width; i++)
                      {
-                        if ((png_uint_16)((*sp >> shift) & 0xf)
+                        if ((png_uint_16)((*sp >> shift) & 0x0f)
                             == trans_values->gray)
                         {
                            *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
@@ -2607,9 +2623,9 @@
                         }
                         else
                         {
-                           png_byte p = (png_byte)((*sp >> shift) & 0xf);
+                           png_byte p = (png_byte)((*sp >> shift) & 0x0f);
                            png_byte g = (png_byte)((gamma_table[p |
-                             (p << 4)] >> 4) & 0xf);
+                             (p << 4)] >> 4) & 0x0f);
                            *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
                            *sp |= (png_byte)(g << shift);
                         }
@@ -2629,7 +2645,7 @@
                      shift = 4;
                      for (i = 0; i < row_width; i++)
                      {
-                        if ((png_uint_16)((*sp >> shift) & 0xf)
+                        if ((png_uint_16)((*sp >> shift) & 0x0f)
                             == trans_values->gray)
                         {
                            *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
@@ -3362,10 +3378,10 @@
             {
                sp = row + (png_size_t)((row_width - 1) >> 3);
                dp = row + (png_size_t)row_width - 1;
-               shift = 7 - (int)((row_width + 7) & 7);
+               shift = 7 - (int)((row_width + 7) & 0x07);
                for (i = 0; i < row_width; i++)
                {
-                  if ((*sp >> shift) & 0x1)
+                  if ((*sp >> shift) & 0x01)
                      *dp = 1;
                   else
                      *dp = 0;
@@ -3385,10 +3401,10 @@
             {
                sp = row + (png_size_t)((row_width - 1) >> 2);
                dp = row + (png_size_t)row_width - 1;
-               shift = (int)((3 - ((row_width + 3) & 3)) << 1);
+               shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
                for (i = 0; i < row_width; i++)
                {
-                  value = (*sp >> shift) & 0x3;
+                  value = (*sp >> shift) & 0x03;
                   *dp = (png_byte)value;
                   if (shift == 6)
                   {
@@ -3406,10 +3422,10 @@
             {
                sp = row + (png_size_t)((row_width - 1) >> 1);
                dp = row + (png_size_t)row_width - 1;
-               shift = (int)((row_width & 1) << 2);
+               shift = (int)((row_width & 0x01) << 2);
                for (i = 0; i < row_width; i++)
                {
-                  value = (*sp >> shift) & 0xf;
+                  value = (*sp >> shift) & 0x0f;
                   *dp = (png_byte)value;
                   if (shift == 4)
                   {
@@ -3508,10 +3524,10 @@
                   gray = (png_uint_16)(gray*0xff);
                   sp = row + (png_size_t)((row_width - 1) >> 3);
                   dp = row + (png_size_t)row_width - 1;
-                  shift = 7 - (int)((row_width + 7) & 7);
+                  shift = 7 - (int)((row_width + 7) & 0x07);
                   for (i = 0; i < row_width; i++)
                   {
-                     if ((*sp >> shift) & 0x1)
+                     if ((*sp >> shift) & 0x01)
                         *dp = 0xff;
                      else
                         *dp = 0;
@@ -3532,10 +3548,10 @@
                   gray = (png_uint_16)(gray*0x55);
                   sp = row + (png_size_t)((row_width - 1) >> 2);
                   dp = row + (png_size_t)row_width - 1;
-                  shift = (int)((3 - ((row_width + 3) & 3)) << 1);
+                  shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
                   for (i = 0; i < row_width; i++)
                   {
-                     value = (*sp >> shift) & 0x3;
+                     value = (*sp >> shift) & 0x03;
                      *dp = (png_byte)(value | (value << 2) | (value << 4) |
                         (value << 6));
                      if (shift == 6)
@@ -3555,10 +3571,10 @@
                   gray = (png_uint_16)(gray*0x11);
                   sp = row + (png_size_t)((row_width - 1) >> 1);
                   dp = row + (png_size_t)row_width - 1;
-                  shift = (int)((1 - ((row_width + 1) & 1)) << 2);
+                  shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
                   for (i = 0; i < row_width; i++)
                   {
-                     value = (*sp >> shift) & 0xf;
+                     value = (*sp >> shift) & 0x0f;
                      *dp = (png_byte)(value | (value << 4));
                      if (shift == 4)
                      {
@@ -3809,7 +3825,7 @@
 
 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
     defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
-      if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY))
+      if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY))
       {
 
          g = 1.0 / (png_ptr->gamma);
diff --git a/pngrutil.c b/pngrutil.c
index 3a69a48..4947dd2 100644
--- a/pngrutil.c
+++ b/pngrutil.c
@@ -1,11 +1,11 @@
 
 /* pngrutil.c - utilities to read a PNG file
  *
- * libpng 1.0.5h - December 10, 1999
+ * libpng 1.0.5q - February 5, 2000
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
+ * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson
  *
  * This file contains routines that are only called from within
  * libpng itself during the course of reading an image.
@@ -31,7 +31,7 @@
    return (i);
 }
 
-#if defined(PNG_READ_pCAL_SUPPORTED)
+#if defined(PNG_READ_pCAL_SUPPORTED) || defined(PNG_READ_oFFs_SUPPORTED)
 /* 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. */
@@ -87,10 +87,10 @@
 
    if (png_crc_error(png_ptr))
    {
-      if ((png_ptr->chunk_name[0] & 0x20 &&                /* Ancillary */
+      if (((png_ptr->chunk_name[0] & 0x20) &&                /* Ancillary */
            !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
           (!(png_ptr->chunk_name[0] & 0x20) &&             /* Critical  */
-           png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE))
+          (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)))
       {
          png_chunk_warning(png_ptr, "CRC error");
       }
@@ -455,7 +455,7 @@
 #if defined (PNG_READ_tRNS_SUPPORTED)
    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
    {
-      if (info_ptr != NULL && info_ptr->valid & PNG_INFO_tRNS)
+      if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
       {
          if (png_ptr->num_trans > png_ptr->num_palette)
          {
@@ -482,7 +482,7 @@
          return;
    }
 
-   png_ptr->mode |= PNG_AFTER_IDAT | PNG_HAVE_IEND;
+   png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
 
    if (length != 0)
    {
@@ -495,7 +495,7 @@
 void
 png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
-   png_uint_32 igamma;
+   png_fixed_point igamma;
 #ifdef PNG_FLOATING_POINT_SUPPORTED
    float file_gamma;
 #endif
@@ -515,7 +515,7 @@
       /* Should be an error, but we can cope with it */
       png_warning(png_ptr, "Out of place gAMA chunk");
 
-   else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_gAMA
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
 #if defined(PNG_READ_sRGB_SUPPORTED)
       && !(info_ptr->valid & PNG_INFO_sRGB)
 #endif
@@ -537,7 +537,7 @@
    if (png_crc_finish(png_ptr, 0))
       return;
 
-   igamma = png_get_uint_32(buf);
+   igamma = (png_fixed_point)png_get_uint_32(buf);
    /* check for zero gamma */
    if (igamma == 0)
       return;
@@ -549,7 +549,7 @@
          png_warning(png_ptr,
            "Ignoring incorrect gAMA value when sRGB is also present");
 #ifndef PNG_NO_CONSOLE_IO
-         fprintf(stderr, "igamma = %lu\n", igamma);
+         fprintf(stderr, "gamma = (%d/100000)\n", (int)igamma);
 #endif
          return;
       }
@@ -557,10 +557,10 @@
 
 #ifdef PNG_FLOATING_POINT_SUPPORTED
    file_gamma = (float)igamma / (float)100000.0;
-#ifdef PNG_READ_GAMMA_SUPPORTED
-   png_ptr->gamma = file_gamma;
-#endif
-   png_set_gAMA(png_ptr, info_ptr, file_gamma);
+#  ifdef PNG_READ_GAMMA_SUPPORTED
+     png_ptr->gamma = file_gamma;
+#  endif
+     png_set_gAMA(png_ptr, info_ptr, file_gamma);
 #endif
 #ifdef PNG_FIXED_POINT_SUPPORTED
    png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
@@ -592,7 +592,7 @@
       /* Should be an error, but we can cope with it */
       png_warning(png_ptr, "Out of place sBIT chunk");
    }
-   else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_sBIT)
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
    {
       png_warning(png_ptr, "Duplicate sBIT chunk");
       png_crc_finish(png_ptr, length);
@@ -642,13 +642,13 @@
 #ifdef PNG_FLOATING_POINT_SUPPORTED
    float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
 #endif
-   png_uint_32 int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
+   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_debug(1, "in png_handle_cHRM\n");
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
-      png_error(png_ptr, "Missing IHDR before sBIT");
+      png_error(png_ptr, "Missing IHDR before cHRM");
    else if (png_ptr->mode & PNG_HAVE_IDAT)
    {
       png_warning(png_ptr, "Invalid cHRM after IDAT");
@@ -659,7 +659,7 @@
       /* Should be an error, but we can cope with it */
       png_warning(png_ptr, "Missing PLTE before cHRM");
 
-   else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_cHRM
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
 #if defined(PNG_READ_sRGB_SUPPORTED)
       && !(info_ptr->valid & PNG_INFO_sRGB)
 #endif
@@ -678,10 +678,10 @@
    }
 
    png_crc_read(png_ptr, buf, 4);
-   int_x_white = png_get_uint_32(buf);
+   int_x_white = (png_fixed_point)png_get_uint_32(buf);
 
    png_crc_read(png_ptr, buf, 4);
-   int_y_white = png_get_uint_32(buf);
+   int_y_white = (png_fixed_point)png_get_uint_32(buf);
 
    if (int_x_white > 80000L || int_y_white > 80000L ||
       int_x_white + int_y_white > 100000L)
@@ -692,10 +692,10 @@
    }
 
    png_crc_read(png_ptr, buf, 4);
-   int_x_red = png_get_uint_32(buf);
+   int_x_red = (png_fixed_point)png_get_uint_32(buf);
 
    png_crc_read(png_ptr, buf, 4);
-   int_y_red = png_get_uint_32(buf);
+   int_y_red = (png_fixed_point)png_get_uint_32(buf);
 
    if (int_x_red > 80000L || int_y_red > 80000L ||
       int_x_red + int_y_red > 100000L)
@@ -706,10 +706,10 @@
    }
 
    png_crc_read(png_ptr, buf, 4);
-   int_x_green = png_get_uint_32(buf);
+   int_x_green = (png_fixed_point)png_get_uint_32(buf);
 
    png_crc_read(png_ptr, buf, 4);
-   int_y_green = png_get_uint_32(buf);
+   int_y_green = (png_fixed_point)png_get_uint_32(buf);
 
    if (int_x_green > 80000L || int_y_green > 80000L ||
       int_x_green + int_y_green > 100000L)
@@ -720,10 +720,10 @@
    }
 
    png_crc_read(png_ptr, buf, 4);
-   int_x_blue = png_get_uint_32(buf);
+   int_x_blue = (png_fixed_point)png_get_uint_32(buf);
 
    png_crc_read(png_ptr, buf, 4);
-   int_y_blue = png_get_uint_32(buf);
+   int_y_blue = (png_fixed_point)png_get_uint_32(buf);
 
    if (int_x_blue > 80000L || int_y_blue > 80000L ||
       int_x_blue + int_y_blue > 100000L)
@@ -743,20 +743,17 @@
    blue_y  = (float)int_y_blue  / (float)100000.0;
 #endif
 
-   if (png_crc_finish(png_ptr, 0))
-      return;
-
 #if defined(PNG_READ_sRGB_SUPPORTED)
    if (info_ptr->valid & PNG_INFO_sRGB)
       {
-      if (abs((int)int_x_white - 31270L) > 1000 ||
-          abs((int)int_y_white - 32900L) > 1000 ||
-          abs((int)  int_x_red - 64000L) > 1000 ||
-          abs((int)  int_y_red - 33000L) > 1000 ||
-          abs((int)int_x_green - 30000L) > 1000 ||
-          abs((int)int_y_green - 60000L) > 1000 ||
-          abs((int) int_x_blue - 15000L) > 1000 ||
-          abs((int) int_y_blue -  6000L) > 1000)
+      if (abs(int_x_white - 31270L) > 1000 ||
+          abs(int_y_white - 32900L) > 1000 ||
+          abs(  int_x_red - 64000L) > 1000 ||
+          abs(  int_y_red - 33000L) > 1000 ||
+          abs(int_x_green - 30000L) > 1000 ||
+          abs(int_y_green - 60000L) > 1000 ||
+          abs( int_x_blue - 15000L) > 1000 ||
+          abs( int_y_blue -  6000L) > 1000)
          {
 
             png_warning(png_ptr,
@@ -768,13 +765,14 @@
             fprintf(stderr,"gx=%f, gy=%f, bx=%f, by=%f\n",
                green_x, green_y, blue_x, blue_y);
 #else
-            fprintf(stderr,"wx=%d, wy=%d, rx=%d, ry=%d\n",
+            fprintf(stderr,"wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
                int_x_white, int_y_white, int_x_red, int_y_red);
-            fprintf(stderr,"gx=%d, gy=%d, bx=%d, by=%d\n",
+            fprintf(stderr,"gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
                int_x_green, int_y_green, int_x_blue, int_y_blue);
 #endif
 #endif /* PNG_NO_CONSOLE_IO */
          }
+         png_crc_finish(png_ptr, 0);
          return;
       }
 #endif /* PNG_READ_sRGB_SUPPORTED */
@@ -788,6 +786,8 @@
       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
+   if (png_crc_finish(png_ptr, 0))
+      return;
 }
 #endif
 
@@ -796,7 +796,6 @@
 png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
    int intent;
-   int igamma;
    png_byte buf[1];
 
    png_debug(1, "in png_handle_sRGB\n");
@@ -813,7 +812,7 @@
       /* Should be an error, but we can cope with it */
       png_warning(png_ptr, "Out of place sRGB chunk");
 
-   else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_sRGB)
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
    {
       png_warning(png_ptr, "Duplicate sRGB chunk");
       png_crc_finish(png_ptr, length);
@@ -840,38 +839,43 @@
    }
 
 #if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-   igamma=png_ptr->gamma * 100000.;
+   if ((info_ptr->valid & PNG_INFO_gAMA))
+   {
+   int igamma;
+#ifdef PNG_FIXED_POINT_SUPPORTED
+      igamma=(int)info_ptr->int_gamma;
 #else
-#  ifdef PNG_FIXED_POINT_SUPPORTED
-   igamma=(int)png_ptr->int_gamma;
+#  ifdef PNG_FLOATING_POINT_SUPPORTED
+      igamma=info_ptr->gamma * 100000.;
 #  endif
 #endif
-   if ((info_ptr->valid & PNG_INFO_gAMA))
       if(igamma < 45000L || igamma > 46000L)
       {
          png_warning(png_ptr,
            "Ignoring incorrect gAMA value when sRGB is also present");
 #ifndef PNG_NO_CONSOLE_IO
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-           fprintf(stderr,"gamma=%f\n",png_ptr->gamma);
-#else
-           fprintf(stderr,"gamma=%d\n",png_ptr->int_gamma);
-#endif
+#  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
 #endif
       }
+   }
 #endif /* PNG_READ_gAMA_SUPPORTED */
 
 #ifdef PNG_READ_cHRM_SUPPORTED
    if (info_ptr->valid & PNG_INFO_cHRM)
-      if (abs((int)info_ptr->int_x_white - 31270L) > 1000 ||
-          abs((int)info_ptr->int_y_white - 32900L) > 1000 ||
-          abs((int)  info_ptr->int_x_red - 64000L) > 1000 ||
-          abs((int)  info_ptr->int_y_red - 33000L) > 1000 ||
-          abs((int)info_ptr->int_x_green - 30000L) > 1000 ||
-          abs((int)info_ptr->int_y_green - 60000L) > 1000 ||
-          abs((int) info_ptr->int_x_blue - 15000L) > 1000 ||
-          abs((int) info_ptr->int_y_blue -  6000L) > 1000)
+      if (abs(info_ptr->int_x_white - 31270L) > 1000 ||
+          abs(info_ptr->int_y_white - 32900L) > 1000 ||
+          abs(  info_ptr->int_x_red - 64000L) > 1000 ||
+          abs(  info_ptr->int_y_red - 33000L) > 1000 ||
+          abs(info_ptr->int_x_green - 30000L) > 1000 ||
+          abs(info_ptr->int_y_green - 60000L) > 1000 ||
+          abs( info_ptr->int_x_blue - 15000L) > 1000 ||
+          abs( info_ptr->int_y_blue -  6000L) > 1000)
          {
             png_warning(png_ptr,
               "Ignoring incorrect cHRM value when sRGB is also present");
@@ -907,7 +911,7 @@
       /* Should be an error, but we can cope with it */
       png_warning(png_ptr, "Out of place iCCP chunk");
 
-   else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_iCCP)
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
    {
       png_warning(png_ptr, "Duplicate iCCP chunk");
       png_crc_finish(png_ptr, length);
@@ -982,16 +986,6 @@
       png_crc_finish(png_ptr, length);
       return;
    }
-   else if (png_ptr->mode & PNG_HAVE_PLTE)
-      /* Should be an error, but we can cope with it */
-      png_warning(png_ptr, "Out of place sPLT chunk");
-
-   else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_sPLT)
-   {
-      png_warning(png_ptr, "Duplicate sPLT chunk");
-      png_crc_finish(png_ptr, length);
-      return;
-   }
 
 #ifdef PNG_MAX_MALLOC_64K
    if (length > (png_uint_32)65535L)
@@ -1085,7 +1079,7 @@
       png_crc_finish(png_ptr, length);
       return;
    }
-   else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_tRNS)
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
    {
       png_warning(png_ptr, "Duplicate tRNS chunk");
       png_crc_finish(png_ptr, length);
@@ -1188,7 +1182,7 @@
       png_crc_finish(png_ptr, length);
       return;
    }
-   else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_bKGD)
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
    {
       png_warning(png_ptr, "Duplicate bKGD chunk");
       png_crc_finish(png_ptr, length);
@@ -1276,7 +1270,7 @@
       png_crc_finish(png_ptr, length);
       return;
    }
-   else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_hIST)
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
    {
       png_warning(png_ptr, "Duplicate hIST chunk");
       png_crc_finish(png_ptr, length);
@@ -1327,7 +1321,7 @@
       png_crc_finish(png_ptr, length);
       return;
    }
-   else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_pHYs)
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
    {
       png_warning(png_ptr, "Duplicate pHYS chunk");
       png_crc_finish(png_ptr, length);
@@ -1370,7 +1364,7 @@
       png_crc_finish(png_ptr, length);
       return;
    }
-   else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_oFFs)
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
    {
       png_warning(png_ptr, "Duplicate oFFs chunk");
       png_crc_finish(png_ptr, length);
@@ -1418,7 +1412,7 @@
       png_crc_finish(png_ptr, length);
       return;
    }
-   else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_pCAL)
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
    {
       png_warning(png_ptr, "Duplicate pCAL chunk");
       png_crc_finish(png_ptr, length);
@@ -1517,10 +1511,14 @@
 void
 png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
-   png_charp unit, swidth, sheight, ep;
+   png_charp buffer, ep;
 #ifdef PNG_FLOATING_POINT_SUPPORTED
    double width=0., height=0.;
    png_charp vp;
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   png_charp swidth, sheight;
+#endif
 #endif
    png_size_t slength;
 
@@ -1534,7 +1532,7 @@
       png_crc_finish(png_ptr, length);
       return;
    }
-   else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_sCAL)
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
    {
       png_warning(png_ptr, "Duplicate sCAL chunk");
       png_crc_finish(png_ptr, length);
@@ -1543,32 +1541,32 @@
 
    png_debug1(2, "Allocating and reading sCAL chunk data (%d bytes)\n",
       length + 1);
-   unit = (png_charp)png_malloc(png_ptr, length + 1);
+   buffer = (png_charp)png_malloc(png_ptr, length + 1);
    slength = (png_size_t)length;
-   png_crc_read(png_ptr, (png_bytep)unit, slength);
+   png_crc_read(png_ptr, (png_bytep)buffer, slength);
 
    if (png_crc_finish(png_ptr, 0))
    {
-      png_free(png_ptr, unit);
+      png_free(png_ptr, buffer);
       return;
    }
 
-   unit[slength] = 0x00; /* null terminate the last string */
+   buffer[slength] = 0x00; /* null terminate the last string */
 
-   png_debug(3, "Finding end of sCAL unit string\n");
-   for (ep = unit; *ep; ep++)
-      /* empty loop */ ;
-   ep++;
+   ep = buffer + 1;        /* skip unit byte */
 
 #ifdef PNG_FLOATING_POINT_SUPPORTED
    width = strtod(ep, &vp);
    if (*vp)
        png_error(png_ptr, "malformed width string in sCAL chunk");
-#endif
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
    swidth = (png_charp)png_malloc(png_ptr, strlen(ep) + 1);
    png_memcpy(swidth, ep, (png_size_t)strlen(ep));
+#endif
+#endif
 
-   for (ep = unit; *ep; ep++)
+   for (ep = buffer; *ep; ep++)
       /* empty loop */ ;
    ep++;
 
@@ -1576,32 +1574,42 @@
    height = strtod(ep, &vp);
    if (*vp)
        png_error(png_ptr, "malformed height string in sCAL chunk");
-#endif
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
    sheight = (png_charp)png_malloc(png_ptr, strlen(ep) + 1);
    png_memcpy(sheight, ep, (png_size_t)strlen(ep));
+#endif
+#endif
 
-   if (unit + slength < ep
+   if (buffer + slength < ep
 #ifdef PNG_FLOATING_POINT_SUPPORTED
       || width <= 0. || height <= 0.
 #endif
       )
    {
       png_warning(png_ptr, "Invalid sCAL data");
-      png_free(png_ptr, unit);
+      png_free(png_ptr, buffer);
+#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, unit, width, height);
-#endif
+   png_set_sCAL(png_ptr, info_ptr, buffer[0], width, height);
+#else
 #ifdef PNG_FIXED_POINT_SUPPORTED
-   png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight);
+   png_set_sCAL_s(png_ptr, info_ptr, buffer[0], swidth, sheight);
+#endif
 #endif
 
-   png_free(png_ptr, unit);
+   png_free(png_ptr, buffer);
+#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
+   png_free(png_ptr, swidth);
+   png_free(png_ptr, sheight);
+#endif
 }
 #endif
 
@@ -1616,7 +1624,7 @@
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Out of place tIME chunk");
-   else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_tIME)
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
    {
       png_warning(png_ptr, "Duplicate tIME chunk");
       png_crc_finish(png_ptr, length);
@@ -1696,9 +1704,12 @@
 
    text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
    text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
-   text_ptr->lang = NULL;
    text_ptr->key = key;
+   text_ptr->lang = NULL;
+   text_ptr->lang_key = NULL;
    text_ptr->text = text;
+   text_ptr->text_length = png_strlen(text);
+   text_ptr->itxt_length = 0;
 
    png_set_text(png_ptr, info_ptr, text_ptr, 1);
 
@@ -1759,7 +1770,7 @@
    else
    {
        comp_type = *(++text);
-       text++;        /* skip the compression byte */
+       text++;        /* skip the compression_method byte */
    }
    prefix_len = text - chunkdata;
 
@@ -1770,7 +1781,10 @@
    text_ptr->compression = comp_type;
    text_ptr->lang = NULL;
    text_ptr->key = chunkdata;
+   text_ptr->lang_key = NULL;
    text_ptr->text = chunkdata + prefix_len;
+   text_ptr->text_length = png_strlen(text);
+   text_ptr->itxt_length = 0;
 
    png_set_text(png_ptr, info_ptr, text_ptr, 1);
 
@@ -1786,9 +1800,9 @@
 {
    png_textp text_ptr;
    png_charp chunkdata;
-   png_charp lang, text;
-   int comp_type = PNG_TEXT_COMPRESSION_NONE;
-   int comp_flag = 0;
+   png_charp key, lang, text, lang_key;
+   int comp_flag = PNG_TEXT_COMPRESSION_NONE;
+   int comp_type = 0;
    png_size_t slength, prefix_len;
 
    png_debug(1, "in png_handle_iTXt\n");
@@ -1825,10 +1839,13 @@
       /* empty loop */ ;
    lang++;        /* skip NUL separator */
 
-   /* iTXt must have a language tag and some text after the keyword */
+   /* iTXt must have a language tag (possibly empty), two compression bytes,
+      translated keyword (possibly empty), and possibly some text after the
+      keyword */
+
    if (lang >= chunkdata + slength)
    {
-      comp_type = PNG_TEXT_COMPRESSION_NONE;
+      comp_flag = PNG_TEXT_COMPRESSION_NONE;
       png_warning(png_ptr, "Zero length iTXt chunk");
    }
    else
@@ -1837,38 +1854,36 @@
        comp_type = *lang++;
    }
 
-   for (text = lang; *text; text++)
+   for (lang_key = lang; *lang_key; lang_key++)
+      /* empty loop */ ;
+   lang_key++;        /* skip NUL separator */
+
+   for (text = lang_key; *text; text++)
       /* empty loop */ ;
    text++;        /* skip NUL separator */
 
    prefix_len = text - chunkdata;
 
+   key=chunkdata;
    if (comp_flag)
        chunkdata = png_decompress_chunk(png_ptr, comp_type, chunkdata,
-                                        (size_t)length, prefix_len);
-
+          (size_t)length, prefix_len);
    text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
-   text_ptr->compression = (png_byte)comp_type;
-   text_ptr->lang = NULL;
+   text_ptr->compression = (int)comp_flag + 1;
+   text_ptr->lang_key = chunkdata+(lang_key-key);
+   text_ptr->lang = chunkdata+(lang-key);
    text_ptr->key = chunkdata;
    text_ptr->text = chunkdata + prefix_len;
+   text_ptr->text_length = 0;
+   text_ptr->itxt_length = png_strlen(text_ptr->text);
 
    png_set_text(png_ptr, info_ptr, text_ptr, 1);
 
-   png_free(png_ptr, text_ptr->key);
    png_free(png_ptr, text_ptr);
    png_free(png_ptr, chunkdata);
 }
 #endif
 
-#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
-void
-png_set_keep_unknown_chunks(png_structp png_ptr)
-{
-    png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
-}
-#endif
-
 /* This function is called when we haven't found a handler for a
    chunk.  If there isn't a problem with the chunk itself (ie bad
    chunk name, CRC, or a critical chunk), the chunk is silently ignored
@@ -1882,21 +1897,25 @@
    png_debug(1, "in png_handle_unknown\n");
 
    if (png_ptr->mode & PNG_HAVE_IDAT)
-      png_ptr->mode |= PNG_AFTER_IDAT;
+   {
+#ifdef PNG_USE_LOCAL_ARRAYS
+      PNG_IDAT;
+#endif
+      if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))  /* not an IDAT */
+         png_ptr->mode |= PNG_AFTER_IDAT;
+   }
 
-   /* In the future we can have code here that calls user-supplied
-    * callback functions for unknown chunks before they are ignored or
-    * cause an error.
-    */
    png_check_chunk_name(png_ptr, png_ptr->chunk_name);
 
    if (!(png_ptr->chunk_name[0] & 0x20))
    {
-      png_chunk_error(png_ptr, "unknown critical chunk");
-
-      /* to quiet compiler warnings about unused info_ptr */
-      if (info_ptr == NULL)
-         return;
+      if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
+           HANDLE_CHUNK_ALWAYS
+#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
+           && png_ptr->read_user_chunk_fn == (png_user_chunk_ptr)NULL
+#endif
+        )
+          png_chunk_error(png_ptr, "unknown critical chunk");
    }
 
 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
@@ -1912,19 +1931,38 @@
            length = (png_uint_32)65535L;
        }
 #endif
-
-       strcpy(chunk.name, png_ptr->chunk_name);
+       strcpy((png_charp)chunk.name, (png_charp)png_ptr->chunk_name);
        chunk.data = (png_bytep)png_malloc(png_ptr, length);
        png_crc_read(png_ptr, chunk.data, length);
        chunk.size = length;
-       png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
+#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
+       if(png_ptr->read_user_chunk_fn != (png_user_chunk_ptr)NULL)
+       {
+          /* callback to user unknown chunk handler */
+          if ((*(png_ptr->read_user_chunk_fn)) (png_ptr, &chunk) <= 0)
+          {
+             if (!(png_ptr->chunk_name[0] & 0x20))
+                if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
+                     HANDLE_CHUNK_ALWAYS)
+                   png_chunk_error(png_ptr, "unknown critical chunk");
+             png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
+          }
+       }
+       else
+#endif
+          png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
        png_free(png_ptr, chunk.data);
    }
    else
 #endif
-       skip = length;
+      skip = length;
 
    png_crc_finish(png_ptr, skip);
+
+#if !defined(PNG_READ_USER_CHUNKS_SUPPORTED)
+   if (info_ptr == NULL)
+     /* quiet compiler warnings about unused info_ptr */ ;
+#endif
 }
 
 /* This function is called to verify that a chunk name is valid.
@@ -2008,7 +2046,7 @@
                {
                   int value;
 
-                  value = (*sp >> shift) & 0x1;
+                  value = (*sp >> shift) & 0x01;
                   *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
                   *dp |= (png_byte)(value << shift);
                }
@@ -2061,7 +2099,7 @@
             {
                if (m & mask)
                {
-                  value = (*sp >> shift) & 0x3;
+                  value = (*sp >> shift) & 0x03;
                   *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
                   *dp |= (png_byte)(value << shift);
                }
@@ -2203,8 +2241,8 @@
 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
             if (transformations & PNG_PACKSWAP)
             {
-                sshift = (int)((row_info->width + 7) & 7);
-                dshift = (int)((final_width + 7) & 7);
+                sshift = (int)((row_info->width + 7) & 0x07);
+                dshift = (int)((final_width + 7) & 0x07);
                 s_start = 7;
                 s_end = 0;
                 s_inc = -1;
@@ -2212,8 +2250,8 @@
             else
 #endif
             {
-                sshift = 7 - (int)((row_info->width + 7) & 7);
-                dshift = 7 - (int)((final_width + 7) & 7);
+                sshift = 7 - (int)((row_info->width + 7) & 0x07);
+                dshift = 7 - (int)((final_width + 7) & 0x07);
                 s_start = 0;
                 s_end = 7;
                 s_inc = 1;
@@ -2221,7 +2259,7 @@
 
             for (i = 0; i < row_info->width; i++)
             {
-               v = (png_byte)((*sp >> sshift) & 0x1);
+               v = (png_byte)((*sp >> sshift) & 0x01);
                for (j = 0; j < jstop; j++)
                {
                   *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
@@ -2256,8 +2294,8 @@
 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
             if (transformations & PNG_PACKSWAP)
             {
-               sshift = (int)(((row_info->width + 3) & 3) << 1);
-               dshift = (int)(((final_width + 3) & 3) << 1);
+               sshift = (int)(((row_info->width + 3) & 0x03) << 1);
+               dshift = (int)(((final_width + 3) & 0x03) << 1);
                s_start = 6;
                s_end = 0;
                s_inc = -2;
@@ -2265,8 +2303,8 @@
             else
 #endif
             {
-               sshift = (int)((3 - ((row_info->width + 3) & 3)) << 1);
-               dshift = (int)((3 - ((final_width + 3) & 3)) << 1);
+               sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
+               dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
                s_start = 0;
                s_end = 6;
                s_inc = 2;
@@ -2277,7 +2315,7 @@
                png_byte v;
                int j;
 
-               v = (png_byte)((*sp >> sshift) & 0x3);
+               v = (png_byte)((*sp >> sshift) & 0x03);
                for (j = 0; j < jstop; j++)
                {
                   *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
@@ -2312,8 +2350,8 @@
 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
             if (transformations & PNG_PACKSWAP)
             {
-               sshift = (int)(((row_info->width + 1) & 1) << 2);
-               dshift = (int)(((final_width + 1) & 1) << 2);
+               sshift = (int)(((row_info->width + 1) & 0x01) << 2);
+               dshift = (int)(((final_width + 1) & 0x01) << 2);
                s_start = 4;
                s_end = 0;
                s_inc = -4;
@@ -2321,8 +2359,8 @@
             else
 #endif
             {
-               sshift = (int)((1 - ((row_info->width + 1) & 1)) << 2);
-               dshift = (int)((1 - ((final_width + 1) & 1)) << 2);
+               sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
+               dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
                s_start = 0;
                s_end = 4;
                s_inc = 4;
diff --git a/pngset.c b/pngset.c
index 6e7420a..011f459 100644
--- a/pngset.c
+++ b/pngset.c
@@ -1,11 +1,11 @@
 
 /* pngset.c - storage of image information into info struct
  *
- * libpng 1.0.5h - December 10, 1999
+ * libpng 1.0.5q - February 5, 2000
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
+ * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson
  *
  * The functions here are used during reads to store data from the file
  * into the info struct, and during writes to store application data
@@ -48,15 +48,25 @@
    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
 #ifdef PNG_FIXED_POINT_SUPPORTED
 void
 png_set_cHRM_fixed(png_structp png_ptr, png_infop info_ptr,
-   png_uint_32 white_x, png_uint_32 white_y, png_uint_32 red_x,
-   png_uint_32 red_y, png_uint_32 green_x, png_uint_32 green_y,
-   png_uint_32 blue_x, png_uint_32 blue_y)
+   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,
+   png_fixed_point blue_x, png_fixed_point blue_y)
 {
    png_debug1(1, "in %s storage function\n", "cHRM");
    if (png_ptr == NULL || info_ptr == NULL)
@@ -70,6 +80,16 @@
    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->valid |= PNG_INFO_cHRM;
 }
 #endif
@@ -92,21 +112,20 @@
 }
 #endif
 #endif
-#ifdef PNG_FIXED_POINT_SUPPORTED
 void
-png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_uint_32 int_gamma)
+png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point
+   int_gamma)
 {
    png_debug1(1, "in %s storage function\n", "gAMA");
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
 #ifdef PNG_FLOATING_POINT_SUPPORTED
-   info_ptr->gamma = (float)int_gamma/100000.;
+   info_ptr->gamma = (float)(int_gamma/100000.);
 #endif
    info_ptr->int_gamma = int_gamma;
    info_ptr->valid |= PNG_INFO_gAMA;
 }
-#endif
 
 #if defined(PNG_hIST_SUPPORTED)
 void
@@ -116,7 +135,9 @@
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
-   info_ptr->hist = hist;
+   info_ptr->hist = png_malloc(png_ptr, sizeof(png_uint_16) *
+      info_ptr->num_palette);
+   png_memcpy(info_ptr->hist, hist, sizeof(png_uint_16) * info_ptr->num_palette);
    info_ptr->valid |= PNG_INFO_hIST;
 }
 #endif
@@ -226,27 +247,23 @@
 #ifdef PNG_FLOATING_POINT_SUPPORTED
 void
 png_set_sCAL(png_structp png_ptr, png_infop info_ptr,
-             png_charp unit, double width, double height)
+             int unit, double width, double height)
 {
-   png_uint_32 length;
-
    png_debug1(1, "in %s storage function\n", "sCAL");
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
-   length = png_strlen(unit) + 1;
-   png_debug1(3, "allocating unit for info (%d bytes)\n", length);
-   info_ptr->scal_unit = (png_charp)png_malloc(png_ptr, length);
-   png_memcpy(info_ptr->scal_unit, unit, (png_size_t)length);
+   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
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
 void
 png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr,
-             png_charp unit, png_charp swidth, png_charp sheight)
+             int unit, png_charp swidth, png_charp sheight)
 {
    png_uint_32 length;
 
@@ -254,10 +271,7 @@
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
-   length = png_strlen(unit) + 1;
-   png_debug1(3, "allocating unit for info (%d bytes)\n", length);
-   info_ptr->scal_unit = (png_charp)png_malloc(png_ptr, length);
-   png_memcpy(info_ptr->scal_unit, unit, (png_size_t)length);
+   info_ptr->scal_unit = (png_byte)unit;
 
    length = png_strlen(swidth) + 1;
    png_debug1(3, "allocating unit for info (%d bytes)\n", length);
@@ -272,6 +286,8 @@
    info_ptr->valid |= PNG_INFO_sCAL;
 }
 #endif
+#endif
+#endif
 
 #if defined(PNG_pHYs_SUPPORTED)
 void
@@ -293,13 +309,21 @@
 png_set_PLTE(png_structp png_ptr, png_infop info_ptr,
    png_colorp palette, int num_palette)
 {
+   png_size_t length = (png_size_t)(3*num_palette);
+
    png_debug1(1, "in %s storage function\n", "PLTE");
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
-   info_ptr->palette = palette;
+   png_debug1(3, "allocating PLTE for info (%d bytes)\n", length);
+
+   info_ptr->palette = (png_colorp)png_zalloc(png_ptr, (uInt)num_palette,
+      sizeof (png_color));
+
+   png_memcpy(info_ptr->palette, palette, length);
+
    info_ptr->num_palette = (png_uint_16)num_palette;
-   info_ptr->valid |= PNG_INFO_PLTE;
+   info_ptr->valid |= (PNG_INFO_PLTE|PNG_ALLOCATED_INFO_PLTE);
 }
 
 #if defined(PNG_sBIT_SUPPORTED)
@@ -337,7 +361,7 @@
    float file_gamma;
 #endif
 #ifdef PNG_FIXED_POINT_SUPPORTED
-   png_uint_32 int_file_gamma;
+   png_fixed_point int_file_gamma;
 #endif
 #endif
 #if defined(PNG_cHRM_SUPPORTED)
@@ -345,7 +369,7 @@
    float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
 #endif
 #ifdef PNG_FIXED_POINT_SUPPORTED
-   png_uint_32 int_white_x, int_white_y, int_red_x, int_red_y, int_green_x,
+   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;
 #endif
 #endif
@@ -403,7 +427,7 @@
 void
 png_set_iCCP(png_structp png_ptr, png_infop info_ptr,
              png_charp name, int compression_type,
-             png_charp profile, int proflen)
+             png_charp profile, png_uint_32 proflen)
 {
    png_debug1(1, "in %s storage function\n", "iCCP");
    if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL)
@@ -412,8 +436,8 @@
    info_ptr->iccp_name = png_malloc(png_ptr, png_strlen(name)+1);
    strcpy(info_ptr->iccp_name, name);
    info_ptr->iccp_profile = png_malloc(png_ptr, proflen);
-   memcpy(info_ptr->iccp_profile, profile, proflen);
-   info_ptr->iccp_proflen = (png_uint_32)proflen;
+   png_memcpy(info_ptr->iccp_profile, profile, (png_size_t)proflen);
+   info_ptr->iccp_proflen = proflen;
    /* Compression is always zero but is here so the API and info structure
     * does not have to change * if we introduce multiple compression types */
    info_ptr->iccp_compression = (png_byte)compression_type;
@@ -466,54 +490,87 @@
 
    for (i = 0; i < num_text; i++)
    {
+      png_size_t text_length,key_len,lang_len,lang_key_len;
       png_textp textp = &(info_ptr->text[info_ptr->num_text]);
-      png_charp key,text;
 
       if (text_ptr[i].key == (png_charp)NULL)
           continue;
 
-#ifdef PNG_iTXt_SUPPORTED
-      textp->lang = text_ptr[i].lang;
-      textp->translated_key = text_ptr[i].translated_key;
-#else
-      textp->lang = NULL;
-      textp->translated_key = NULL;
-#endif
+      key_len = png_strlen(text_ptr[i].key);
+
+      if(text_ptr[i].compression > 0)
+      {
+        /* set iTXt data */
+        lang_len = png_strlen(text_ptr[i].lang);
+        lang_key_len = png_strlen(text_ptr[i].lang_key);
+      }
+      else
+      {
+        lang_len = 0;
+        lang_key_len = 0;
+      }
 
       if (text_ptr[i].text[0] == '\0')
       {
-         textp->text_length = 0;
-         textp->compression = PNG_TEXT_COMPRESSION_NONE;
+         text_length = 0;
+         if(text_ptr[i].compression > 0)
+            textp->compression = PNG_ITXT_COMPRESSION_NONE;
+         else
+            textp->compression = PNG_TEXT_COMPRESSION_NONE;
       }
       else
       {
-         textp->text_length = png_strlen(text_ptr[i].text);
+         text_length = png_strlen(text_ptr[i].text);
          textp->compression = text_ptr[i].compression;
       }
-      key=text_ptr[i].key;
-      for (text = key; *text++;)
-        /* empty loop to find the byte after the zero byte after the
-           end of key */ ;
 
       textp->key = (png_charp)png_malloc(png_ptr,
-         (png_uint_32)(text+textp->text_length - key)+1);
+         (png_uint_32)(key_len + lang_len + lang_key_len + text_length + 4));
       /* Caution: the calling program, not libpng, is responsible for
          freeing this, if libpng wasn't the caller. */
       png_debug2(2, "Allocated %d bytes at %x in png_set_text\n",
-         text+textp->text_length-key+1, textp->key);
+         key_len + lang_len + lang_key_len + text_length + 4, textp->key);
 
       png_memcpy(textp->key, text_ptr[i].key,
-         (png_size_t)(text - key));  /* includes the zero-byte separator */
+         (png_size_t)(key_len));
+      *(textp->key+key_len) = '\0';
+      if (text_ptr[i].compression > 0)
+      {
+         textp->lang=textp->key + key_len + 1;
+         png_memcpy(textp->lang, text_ptr[i].lang, lang_len);
+         *(textp->lang+lang_len) = '\0';
+         textp->lang_key=textp->lang + lang_len + 1;
+         png_memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len);
+         *(textp->lang_key+lang_key_len) = '\0';
+         textp->text=textp->lang_key + lang_key_len + 1;
+      }
+      else
+      {
+         textp->lang=NULL;
+         textp->lang_key=NULL;
+         textp->text=textp->key + key_len + 1;
+      }
 
-      textp->text = textp->key + (text-key);
-      if(textp->text_length)
+      if(text_length)
       {
          png_memcpy(textp->text, text_ptr[i].text,
-            (png_size_t)(textp->text_length));
-         *(textp->text+textp->text_length) = '\0';
+            (png_size_t)(text_length));
+         *(textp->text+text_length) = '\0';
       }
       else
          textp->text--;
+
+      if(textp->compression > 0)
+      {
+         textp->text_length = 0;
+         textp->itxt_length = text_length;
+      }
+      else
+      {
+         textp->text_length = text_length;
+         textp->itxt_length = 0;
+      }
+
       info_ptr->text[info_ptr->num_text]= *textp;
       info_ptr->num_text++;
       png_debug1(3, "transferred text chunk %d\n", info_ptr->num_text);
@@ -546,7 +603,8 @@
 
    if (trans != NULL)
    {
-      info_ptr->trans = trans;
+      info_ptr->trans = png_malloc(png_ptr, num_trans);
+      png_memcpy(info_ptr->trans, trans, num_trans);
    }
 
    if (trans_values != NULL)
@@ -572,7 +630,7 @@
     np = (png_spalette_p)png_malloc(png_ptr,
         (info_ptr->splt_palettes_num + nentries) * sizeof(png_spalette));
 
-    memcpy(np, info_ptr->splt_palettes,
+    png_memcpy(np, info_ptr->splt_palettes,
            info_ptr->splt_palettes_num * sizeof(png_spalette));
     png_free(png_ptr, info_ptr->splt_palettes);
 
@@ -586,46 +644,53 @@
         png_strcpy(to->name, from->name);
         to->entries = (png_spalette_entryp)png_malloc(png_ptr,
                                  from->nentries * sizeof(png_spalette));
-        memcpy(to->entries, from->entries,
+        png_memcpy(to->entries, from->entries,
                from->nentries * sizeof(png_spalette));
+        to->nentries = from->nentries;
+        to->depth = from->depth;
     }
 
     info_ptr->splt_palettes = np;
     info_ptr->splt_palettes_num += nentries;
+    info_ptr->valid |= PNG_INFO_sPLT;
 }
 #endif /* PNG_sPLT_SUPPORTED */
 
 #if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
 void
 png_set_unknown_chunks(png_structp png_ptr,
-   png_infop info_ptr, png_unknown_chunkp unknowns, int nunknowns)
+   png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns)
 {
     png_unknown_chunkp np;
     int i;
 
-    np = (png_unknown_chunkp)png_malloc(png_ptr,
-        (info_ptr->unknown_chunks_num + nunknowns) * sizeof(png_unknown_chunk));
+    if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0)
+        return;
 
-    memcpy(np, info_ptr->unknown_chunks,
+    np = (png_unknown_chunkp)png_malloc(png_ptr,
+        (info_ptr->unknown_chunks_num + num_unknowns) *
+        sizeof(png_unknown_chunk));
+
+    png_memcpy(np, info_ptr->unknown_chunks,
            info_ptr->unknown_chunks_num * sizeof(png_unknown_chunk));
     png_free(png_ptr, info_ptr->unknown_chunks);
 
-    for (i = 0; i < nunknowns; i++)
+    for (i = 0; i < num_unknowns; i++)
     {
         png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i;
         png_unknown_chunkp from = unknowns + i;
 
-        png_strcpy(to->name, from->name);
+        png_strcpy((png_charp)to->name, (png_charp)from->name);
         to->data = (png_bytep)png_malloc(png_ptr, from->size);
-        memcpy(to->data, from->data, from->size);
+        png_memcpy(to->data, from->data, from->size);
         to->size = from->size;
 
         /* note our location in the read or write sequence */
-        to->location = png_ptr->mode;
+        to->location = (png_byte)(png_ptr->mode & 0xff);
     }
 
     info_ptr->unknown_chunks = np;
-    info_ptr->unknown_chunks_num += nunknowns;
+    info_ptr->unknown_chunks_num += num_unknowns;
 }
 #endif
 
@@ -640,9 +705,51 @@
 }
 #endif
 
+#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+void
+png_set_keep_unknown_chunks(png_structp png_ptr, int keep, png_bytep
+   chunk_list, int num_chunks)
+{
+    png_bytep new_list, p;
+    int i, old_num_chunks;
+    if (num_chunks == 0)
+    {
+      if(keep == HANDLE_CHUNK_ALWAYS || keep == HANDLE_CHUNK_IF_SAFE)
+        png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
+      else
+        png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
 
+      if(keep == HANDLE_CHUNK_ALWAYS)
+        png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS;
+      else
+        png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS;
+      return;
+    }
+    if (chunk_list == NULL)
+      return;
+    old_num_chunks=png_ptr->num_chunk_list;
+    new_list=png_malloc(png_ptr,5*(num_chunks+old_num_chunks));
+    if(png_ptr->chunk_list != (png_bytep)NULL)
+    {
+       png_memcpy(new_list, png_ptr->chunk_list, 5*old_num_chunks);
+       png_free_chunk_list(png_ptr);
+    }
+    png_memcpy(new_list+5*old_num_chunks, chunk_list, 5*num_chunks);
+    for (p=new_list+5*old_num_chunks+4, i=0; i<num_chunks; i++, p+=5)
+       *p=(png_byte)keep;
+    png_ptr->num_chunk_list=old_num_chunks+num_chunks;
+    png_ptr->chunk_list=new_list;
+}
+#endif
 
-
-
-
+#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
+void
+png_set_read_user_chunk_fn(png_structp png_ptr, png_voidp user_chunk_ptr,
+   png_user_chunk_ptr read_user_chunk_fn)
+{
+   png_debug(1, "in png_set_read_user_chunk_fn\n");
+   png_ptr->read_user_chunk_fn = read_user_chunk_fn;
+   png_ptr->user_chunk_ptr = user_chunk_ptr;
+}
+#endif
 
diff --git a/pngtest.c b/pngtest.c
index a1e4531..a29619d 100644
--- a/pngtest.c
+++ b/pngtest.c
@@ -1,11 +1,11 @@
 
 /* pngtest.c - a simple test program to test libpng
  *
- * libpng 1.0.5h - December 10, 1999
+ * libpng 1.0.5q - February 5, 2000
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
+ * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson
  *
  * This program reads in a PNG image, writes it out again, and then
  * compares the two files.  If the files are identical, this shows that
@@ -15,11 +15,11 @@
  *
  * The program will report "FAIL" in certain legitimate cases:
  * 1) when the compression level or filter selection method is changed.
- * 2) when the chunk size is not 8K.
+ * 2) when the maximum IDAT size (PNG_ZBUF_SIZE in pngconf.h) is not 8192.
  * 3) unknown ancillary chunks exist in the input file.
  * 4) others not listed here...
  * In these cases, it is best to check with another tool such as "pngcheck"
- * to see what the differences between the two images are.
+ * to see what the differences between the two files are.
  *
  * If a filename is given on the command-line, then this file is used
  * for the input, rather than the default "pngtest.png".  This allows
@@ -29,6 +29,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <assert.h>
 
 /* Makes pngtest verbose so we can find problems (needs to be before png.h) */
 #ifndef PNG_DEBUG
@@ -151,7 +152,7 @@
        {
           if(row_info->bit_depth == 1)
           {
-             if(((*dp << pos++ )& 0x80) == 0) zero_samples++;
+             if(((*dp << pos++ ) & 0x80) == 0) zero_samples++;
              if(pos == 8)
              {
                 pos = 0;
@@ -160,7 +161,7 @@
           }
           if(row_info->bit_depth == 2)
           {
-             if(((*dp << (pos+=2))& 0xc0) == 0) zero_samples++;
+             if(((*dp << (pos+=2)) & 0xc0) == 0) zero_samples++;
              if(pos == 8)
              {
                 pos = 0;
@@ -169,7 +170,7 @@
           }
           if(row_info->bit_depth == 4)
           {
-             if(((*dp << (pos+=4))& 0xf0) == 0) zero_samples++;
+             if(((*dp << (pos+=4)) & 0xf0) == 0) zero_samples++;
              if(pos == 8)
              {
                 pos = 0;
@@ -409,7 +410,8 @@
 
    This piece of code can be compiled to validate max 64K allocations
    by setting MAXSEG_64K in zlib zconf.h *or* PNG_MAX_MALLOC_64K. */
-typedef struct memory_information {
+typedef struct memory_information
+{
    png_uint_32                    size;
    png_voidp                 pointer;
    struct memory_information FAR *next;
@@ -426,7 +428,8 @@
    png_voidp ptr));
 
 png_voidp
-png_debug_malloc(png_structp png_ptr, png_uint_32 size) {
+png_debug_malloc(png_structp png_ptr, png_uint_32 size)
+{
 
    /* png_malloc has already tested for NULL; png_create_struct calls
       png_debug_malloc directly, with png_ptr == NULL which is OK */
@@ -451,6 +454,7 @@
       if(verbose)
          printf("png_malloc %d bytes at %x\n",size,pinfo->pointer);
 #endif
+      assert(pinfo->size != 12345);
       return (png_voidp)(pinfo->pointer);
    }
 }
@@ -461,7 +465,8 @@
 {
    if (png_ptr == NULL)
       fprintf(STDERR, "NULL pointer to png_debug_free.\n");
-   if (ptr == 0) {
+   if (ptr == 0)
+   {
 #if 0 /* This happens all the time. */
       fprintf(STDERR, "WARNING: freeing NULL pointer\n");
 #endif
@@ -471,9 +476,11 @@
    /* Unlink the element from the list. */
    {
       memory_infop FAR *ppinfo = &pinformation;
-      for (;;) {
+      for (;;)
+      {
          memory_infop pinfo = *ppinfo;
-         if (pinfo->pointer == ptr) {
+         if (pinfo->pointer == ptr)
+         {
             *ppinfo = pinfo->next;
             current_allocation -= pinfo->size;
             if (current_allocation < 0)
@@ -484,7 +491,8 @@
             png_free_default(png_ptr, pinfo);
             break;
          }
-         if (pinfo->next == NULL) {
+         if (pinfo->next == NULL)
+         {
             fprintf(STDERR, "Pointer %x not found\n", ptr);
             break;
          }
@@ -514,9 +522,11 @@
    png_uint_32 width, height;
    int num_pass, pass;
    int bit_depth, color_type;
+#ifdef PNG_SETJMP_SUPPORTED
 #ifdef USE_FAR_KEYWORD
    jmp_buf jmpbuf;
 #endif
+#endif
 
    char inbuf[256], outbuf[256];
 
@@ -568,6 +578,7 @@
 #ifdef PNG_USER_MEM_SUPPORTED
 #endif
 
+#ifdef PNG_SETJMP_SUPPORTED
    png_debug(0, "Setting jmpbuf for read struct\n");
 #ifdef USE_FAR_KEYWORD
    if (setjmp(jmpbuf))
@@ -605,6 +616,7 @@
 #ifdef USE_FAR_KEYWORD
    png_memcpy(write_ptr->jmpbuf,jmpbuf,sizeof(jmp_buf));
 #endif
+#endif
 
    png_debug(0, "Initializing input and output streams\n");
 #if !defined(PNG_NO_STDIO)
@@ -643,6 +655,15 @@
    png_set_write_user_transform_fn(write_ptr, count_zero_samples);
 #endif
 
+#define HANDLE_CHUNK_IF_SAFE      2
+#define HANDLE_CHUNK_ALWAYS       3
+#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
+   png_set_keep_unknown_chunks(read_ptr, HANDLE_CHUNK_ALWAYS, NULL, 0);
+#endif
+#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
+   png_set_keep_unknown_chunks(write_ptr, HANDLE_CHUNK_IF_SAFE, NULL, 0);
+#endif
+
    png_debug(0, "Reading info struct\n");
    png_read_info(read_ptr, read_info_ptr);
 
@@ -663,7 +684,7 @@
    }
 #if defined(PNG_cHRM_SUPPORTED)
    {
-      png_uint_32 white_x, white_y, red_x, red_y, green_x, green_y, blue_x,
+      png_fixed_point white_x, white_y, red_x, red_y, green_x, green_y, blue_x,
          blue_y;
 
       if (png_get_cHRM_fixed(read_ptr, read_info_ptr, &white_x, &white_y, &red_x,
@@ -676,7 +697,7 @@
 #endif
 #if defined(PNG_gAMA_SUPPORTED)
    {
-      png_uint_32 gamma;
+      png_fixed_point gamma;
 
       if (png_get_gAMA_fixed(read_ptr, read_info_ptr, &gamma))
       {
@@ -688,7 +709,7 @@
    {
       png_charp name;
       png_charp profile;
-      png_int_32 proflen;
+      png_uint_32 proflen;
       int compression_type;
 
       if (png_get_iCCP(read_ptr, read_info_ptr, &name, &compression_type,
@@ -740,7 +761,7 @@
 #endif
 #if defined(PNG_oFFs_SUPPORTED)
    {
-      long offset_x, offset_y;
+      png_int_32 offset_x, offset_y;
       int unit_type;
 
       if (png_get_oFFs(read_ptr, read_info_ptr,&offset_x,&offset_y,&unit_type))
@@ -788,7 +809,7 @@
 #if defined(PNG_sCAL_SUPPORTED)
 #ifdef PNG_FLOATING_POINT_SUPPORTED
    {
-      png_charp unit;
+      int unit;
       double width, height;
 
       if (png_get_sCAL(read_ptr, read_info_ptr, &unit, &width, &height))
@@ -797,9 +818,10 @@
       }
    }
 #else
-#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
    {
-      png_charp unit, width, height;
+      int unit;
+      png_charp width, height;
 
       if (png_get_sCAL_s(read_ptr, read_info_ptr, &unit, &width, &height))
       {
@@ -807,6 +829,8 @@
       }
    }
 #endif
+#endif
+#endif
 #if defined(PNG_TEXT_SUPPORTED)
    {
       png_textp text_ptr;
@@ -850,6 +874,24 @@
       }
    }
 #endif
+#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
+   {
+      png_unknown_chunkp unknowns;
+      int num_unknowns = (int)png_get_unknown_chunks(read_ptr, read_info_ptr,
+         &unknowns);
+      if (num_unknowns)
+      {
+         png_size_t i;
+         png_set_unknown_chunks(write_ptr, write_info_ptr, unknowns,
+           num_unknowns);
+         /* copy the locations from the read_info_ptr.  The automatically
+            generated locations in write_info_ptr are wrong because we
+            haven't written anything yet */
+         for (i = 0; i < (png_size_t)num_unknowns; i++)
+           write_info_ptr->unknown_chunks[i].location = unknowns[i].location;
+      }
+   }
+#endif
 
    png_debug(0, "\nWriting info struct\n");
 
@@ -906,7 +948,15 @@
       }
    }
 
+#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
+   png_free_unknown_chunks(read_ptr, end_info_ptr, -1);
+#endif
+#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
+   png_free_unknown_chunks(write_ptr, write_info_ptr, -1);
+#endif
+
    png_debug(0, "Reading and writing end_info data\n");
+
    png_read_end(read_ptr, end_info_ptr);
 #if defined(PNG_TEXT_SUPPORTED)
    {
@@ -937,6 +987,26 @@
       }
    }
 #endif
+#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
+   {
+      png_unknown_chunkp unknowns;
+      int num_unknowns;
+      num_unknowns = (int)png_get_unknown_chunks(read_ptr, end_info_ptr,
+         &unknowns);
+      if (num_unknowns)
+      {
+         png_size_t i;
+         png_set_unknown_chunks(write_ptr, write_end_info_ptr, unknowns,
+           num_unknowns);
+         /* copy the locations from the read_info_ptr.  The automatically
+            generated locations in write_end_info_ptr are wrong because we
+            haven't written the end_info yet */
+         for (i = 0; i < (png_size_t)num_unknowns; i++)
+           write_end_info_ptr->unknown_chunks[i].location =
+              unknowns[i].location;
+      }
+   }
+#endif
    png_write_end(write_ptr, write_end_info_ptr);
 
 #ifdef PNG_EASY_ACCESS_SUPPORTED
@@ -982,16 +1052,17 @@
 
       if (num_in != num_out)
       {
-         fprintf(STDERR, "Files %s and %s are of a different size\n",
+         fprintf(STDERR, "\nFiles %s and %s are of a different size\n",
                  inname, outname);
          if(wrote_question == 0)
          {
             fprintf(STDERR,
-              "   Was %s written with the same chunk size (8k),",inname);
+         "   Was %s written with the same maximum IDAT chunk size (%d bytes),",
+              inname,PNG_ZBUF_SIZE);
             fprintf(STDERR,
-              " filtering\n   heuristic (libpng default), compression");
+              "\n   filtering heuristic (libpng default), compression");
             fprintf(STDERR,
-              " level (zlib default)\n   and zlib version (%s)?\n\n",
+              " level (zlib default),\n   and zlib version (%s)?\n\n",
               ZLIB_VERSION);
             wrote_question=1;
          }
@@ -1009,11 +1080,12 @@
          if(wrote_question == 0)
          {
             fprintf(STDERR,
-              "   Was %s written with the same chunk size (8k),",inname);
+         "   Was %s written with the same maximum IDAT chunk size (%d bytes),",
+                 inname,PNG_ZBUF_SIZE);
             fprintf(STDERR,
-              " filtering\n   heuristic (libpng default), compression");
+              "\n   filtering heuristic (libpng default), compression");
             fprintf(STDERR,
-              " level (zlib default)\n   and zlib version (%s)?\n\n",
+              " level (zlib default),\n   and zlib version (%s)?\n\n",
               ZLIB_VERSION);
             wrote_question=1;
          }
@@ -1154,15 +1226,17 @@
          if (allocation_now != current_allocation)
             fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n",
                current_allocation-allocation_now);
-         if (current_allocation != 0) {
+         if (current_allocation != 0)
+         {
             memory_infop pinfo = pinformation;
 
             fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n",
                current_allocation);
-            while (pinfo != NULL) {
+            while (pinfo != NULL)
+            {
                fprintf(STDERR, " %d bytes at %x\n", pinfo->size, pinfo->pointer);
                pinfo = pinfo->next;
-               }
+            }
          }
 #endif
       }
@@ -1176,7 +1250,8 @@
    else
    {
       int i;
-      for (i=0; i<3; ++i) {
+      for (i=0; i<3; ++i)
+      {
          int kerror;
 #ifdef PNG_USER_MEM_SUPPORTED
          int allocation_now = current_allocation;
@@ -1219,13 +1294,16 @@
          if (allocation_now != current_allocation)
              fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n",
                current_allocation-allocation_now);
-         if (current_allocation != 0) {
+         if (current_allocation != 0)
+         {
              memory_infop pinfo = pinformation;
 
              fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n",
                 current_allocation);
-             while (pinfo != NULL) {
-                fprintf(STDERR, " %d bytes at %x\n", pinfo->size, pinfo->pointer);
+             while (pinfo != NULL)
+             {
+                fprintf(STDERR," %d bytes at %x\n",
+                   pinfo->size, pinfo->pointer);
                 pinfo = pinfo->next;
              }
           }
@@ -1263,7 +1341,7 @@
 /* Generate a compiler error if there is an old png.h in the search path. */
 void
 png_check_pngtest_version
-   (version_1_0_5h png_h_is_not_version_1_0_5h)
+   (version_1_0_5q png_h_is_not_version_1_0_5q)
 {
-   if(png_h_is_not_version_1_0_5h == NULL) return;
+   if(png_h_is_not_version_1_0_5q == NULL) return;
 }
diff --git a/pngtrans.c b/pngtrans.c
index 11bb38e..631ffc3 100644
--- a/pngtrans.c
+++ b/pngtrans.c
@@ -1,11 +1,11 @@
 
 /* pngtrans.c - transforms the data in a row (used by both readers and writers)
  *
- * libpng 1.0.5h - December 10, 1999
+ * libpng 1.0.5q - February 5, 2000
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
+ * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson
  */
 
 #define PNG_INTERNAL
diff --git a/pngtypes.h b/pngtypes.h
index ab192b6..5db1e8d 100644
--- a/pngtypes.h
+++ b/pngtypes.h
@@ -1,10 +1,10 @@
 /* pngtypes.h - array of chunk-types for libpng
  *
- * libpng 1.0.5h - December 10, 1999
+ * libpng 1.0.5q - February 5, 2000
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
+ * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson
  */
 
 /* Constant strings for known chunk types.  If you need to add a chunk,
@@ -25,6 +25,7 @@
 PNG_pCAL;
 PNG_pHYs;
 PNG_sBIT;
+PNG_sCAL;
 PNG_sPLT;
 PNG_sRGB;
 PNG_tEXt;
diff --git a/pngvcrd.c b/pngvcrd.c
index 069f003..ab238a5 100644
--- a/pngvcrd.c
+++ b/pngvcrd.c
@@ -2,10 +2,10 @@
  *
  * For Intel x86 CPU and Microsoft Visual C++ compiler
  *
- * libpng 1.0.5h - December 10, 1999
+ * libpng 1.0.5q - February 5, 2000
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1998, Intel Corporation
- * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
+ * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson
  *
  * Contributed by Nirav Chhatrapati, Intel Corporation, 1998
  * Interface to libpng contributed by Gilles Vollant, 1999
@@ -33,6 +33,9 @@
 {
   int mmx_supported_local = 0;
   _asm {
+    push ebx          //CPUID will trash these
+    push ecx
+    push edx
     pushfd            //Save Eflag to stack
     pop eax           //Get Eflag from stack into eax
     mov ecx, eax      //Make another copy of Eflag in ecx
@@ -70,7 +73,9 @@
 
 NOT_SUPPORTED:
     mov  eax, mmx_supported_local  //move return value to eax
-
+    pop edx          //CPUID trashed these
+    pop ecx
+    pop ebx
   }
 
   //mmx_supported_local=0; // test code for force don't support MMX
@@ -3653,7 +3658,7 @@
 #ifdef PNG_DEBUG
    char filnm[6];
 #endif
-   #define UseMMX 1
+#define UseMMX 1
 
    if (mmx_supported == 2)
        mmx_supported = mmxsupport();
diff --git a/pngwio.c b/pngwio.c
index faf2e77..efeb913 100644
--- a/pngwio.c
+++ b/pngwio.c
@@ -1,11 +1,11 @@
 
 /* pngwio.c - functions for data output
  *
- * libpng 1.0.5h - December 10, 1999
+ * libpng 1.0.5q - February 5, 2000
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
+ * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson
  *
  * This file provides a location for all output.  Users who need
  * special handling are expected to write functions that have the same
diff --git a/pngwrite.c b/pngwrite.c
index 19773ab..e3bd282 100644
--- a/pngwrite.c
+++ b/pngwrite.c
@@ -1,11 +1,11 @@
 
 /* pngwrite.c - general routines to write a PNG file
  *
- * libpng 1.0.5h - December 10, 1999
+ * libpng 1.0.5q - February 5, 2000
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
+ * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson
  */
 
 /* get internal access to png.h */
@@ -24,9 +24,6 @@
 void
 png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr)
 {
-#if defined(PNG_WRITE_sPLT_SUPPORTED)
-   int i;
-#endif
    png_debug(1, "in png_write_info_before_PLTE\n");
    if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE))
    {
@@ -45,11 +42,11 @@
 #if defined(PNG_WRITE_gAMA_SUPPORTED)
    if (info_ptr->valid & PNG_INFO_gAMA)
    {
-#ifdef PNG_FIXED_POINT_SUPPORTED
-      png_write_gAMA_fixed(png_ptr, info_ptr->int_gamma);
-#else
 #  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
    }
@@ -63,11 +60,6 @@
       png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_TEXT_COMPRESSION_NONE,
                      info_ptr->iccp_profile, (int)info_ptr->iccp_proflen);
 #endif
-#if defined(PNG_WRITE_sPLT_SUPPORTED)
-   if (info_ptr->valid & PNG_INFO_sPLT)
-     for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
-       png_write_sPLT(png_ptr, info_ptr->splt_palettes + i);
-#endif
 #if defined(PNG_WRITE_sBIT_SUPPORTED)
    if (info_ptr->valid & PNG_INFO_sBIT)
       png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type);
@@ -75,19 +67,19 @@
 #if defined(PNG_WRITE_cHRM_SUPPORTED)
    if (info_ptr->valid & PNG_INFO_cHRM)
    {
-#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);
-#else
-#  ifdef PNG_FLOATING_POINT_SUPPORTED
+#ifdef PNG_FLOATING_POINT_SUPPORTED
       png_write_cHRM(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
    }
@@ -102,8 +94,16 @@
        for (up = info_ptr->unknown_chunks;
             up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
             up++)
-         if (!(up->location & PNG_HAVE_PLTE))
+       {
+         int keep=png_handle_as_unknown(png_ptr, up->name);
+         if (keep != HANDLE_CHUNK_NEVER &&
+            up->location && (!(up->location & PNG_HAVE_PLTE)) &&
+            ((up->name[3] & 0x20) || keep == HANDLE_CHUNK_ALWAYS ||
+            (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
+         {
             png_write_chunk(png_ptr, up->name, up->data, up->size);
+         }
+       }
    }
 #endif
       png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE;
@@ -113,7 +113,7 @@
 void
 png_write_info(png_structp png_ptr, png_infop info_ptr)
 {
-#if defined(PNG_WRITE_TEXT_SUPPORTED)
+#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
    int i;
 #endif
 
@@ -132,7 +132,7 @@
       {
 #if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
          /* invert the alpha channel (in tRNS) */
-         if (png_ptr->transformations & PNG_INVERT_ALPHA &&
+         if ((png_ptr->transformations & PNG_INVERT_ALPHA) &&
             info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
          {
             int j;
@@ -165,9 +165,16 @@
 #endif
 #if defined(PNG_WRITE_sCAL_SUPPORTED)
    if (info_ptr->valid & PNG_INFO_sCAL)
-      png_write_sCAL_s(png_ptr, info_ptr->scal_unit,
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+      png_write_sCAL(png_ptr, (int)info_ptr->scal_unit,
+          info_ptr->scal_pixel_width, info_ptr->scal_pixel_height);
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+      png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit,
           info_ptr->scal_s_width, info_ptr->scal_s_height);
 #endif
+#endif
+#endif
 #if defined(PNG_WRITE_pHYs_SUPPORTED)
    if (info_ptr->valid & PNG_INFO_pHYs)
       png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit,
@@ -180,6 +187,11 @@
       png_ptr->mode |= PNG_WROTE_tIME;
    }
 #endif
+#if defined(PNG_WRITE_sPLT_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_sPLT)
+     for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
+       png_write_sPLT(png_ptr, info_ptr->splt_palettes + i);
+#endif
 #if defined(PNG_WRITE_TEXT_SUPPORTED)
    /* Check to see if we need to write text chunks */
    for (i = 0; i < info_ptr->num_text; i++)
@@ -187,15 +199,15 @@
       png_debug2(2, "Writing header text chunk %d, type %d\n", i,
          info_ptr->text[i].compression);
       /* an internationalized chunk? */
-      if (info_ptr->text[i].lang)
+      if (info_ptr->text[i].compression > 0)
       {
 #if defined(PNG_WRITE_iTXt_SUPPORTED)
           /* write international chunk */
           png_write_iTXt(png_ptr,
                          info_ptr->text[i].compression,
-                         info_ptr->text[i].lang,
                          info_ptr->text[i].key,
-                         info_ptr->text[i].translated_key,
+                         info_ptr->text[i].lang,
+                         info_ptr->text[i].lang_key,
                          info_ptr->text[i].text);
 #else
           png_warning(png_ptr, "Unable to write international text\n");
@@ -204,12 +216,12 @@
           info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
       }
       /* If we want a compressed text chunk */
-      else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt)
+      else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt)
       {
 #if defined(PNG_WRITE_zTXt_SUPPORTED)
          /* write compressed chunk */
          png_write_zTXt(png_ptr, info_ptr->text[i].key,
-            info_ptr->text[i].text, info_ptr->text[i].text_length,
+            info_ptr->text[i].text, 0,
             info_ptr->text[i].compression);
 #else
          png_warning(png_ptr, "Unable to write compressed text\n");
@@ -223,7 +235,7 @@
          /* write uncompressed chunk */
          png_write_tEXt(png_ptr, info_ptr->text[i].key,
                          info_ptr->text[i].text,
-                         info_ptr->text[i].text_length);
+                         0);
 #else
          png_warning(png_ptr, "Unable to write uncompressed text\n");
 #endif
@@ -242,8 +254,17 @@
        for (up = info_ptr->unknown_chunks;
             up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
             up++)
-         if ((up->location& PNG_HAVE_PLTE) && !(up->location& PNG_HAVE_IDAT))
-       png_write_chunk(png_ptr, up->name, up->data, up->size);
+       {
+         int keep=png_handle_as_unknown(png_ptr, up->name);
+         if (keep != HANDLE_CHUNK_NEVER &&
+            up->location && (up->location & PNG_HAVE_PLTE) &&
+            !(up->location & PNG_HAVE_IDAT) &&
+            ((up->name[3] & 0x20) || keep == HANDLE_CHUNK_ALWAYS ||
+            (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
+         {
+            png_write_chunk(png_ptr, up->name, up->data, up->size);
+         }
+       }
    }
 #endif
 }
@@ -268,7 +289,7 @@
 #endif
 #if defined(PNG_WRITE_tIME_SUPPORTED)
       /* check to see if user has supplied a time chunk */
-      if (info_ptr->valid & PNG_INFO_tIME &&
+      if ((info_ptr->valid & PNG_INFO_tIME) &&
          !(png_ptr->mode & PNG_WROTE_tIME))
          png_write_tIME(png_ptr, &(info_ptr->mod_time));
 #endif
@@ -278,12 +299,29 @@
       {
          png_debug2(2, "Writing trailer text chunk %d, type %d\n", i,
             info_ptr->text[i].compression);
-         if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt)
+         /* an internationalized chunk? */
+         if (info_ptr->text[i].compression > 0)
+         {
+#if defined(PNG_WRITE_iTXt_SUPPORTED)
+             /* write international chunk */
+             png_write_iTXt(png_ptr,
+                         info_ptr->text[i].compression,
+                         info_ptr->text[i].key,
+                         info_ptr->text[i].lang,
+                         info_ptr->text[i].lang_key,
+                         info_ptr->text[i].text);
+#else
+             png_warning(png_ptr, "Unable to write international text\n");
+#endif
+             /* Mark this chunk as written */
+             info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
+         }
+         else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt)
          {
 #if defined(PNG_WRITE_zTXt_SUPPORTED)
             /* write compressed chunk */
             png_write_zTXt(png_ptr, info_ptr->text[i].key,
-               info_ptr->text[i].text, info_ptr->text[i].text_length,
+               info_ptr->text[i].text, 0,
                info_ptr->text[i].compression);
 #else
             png_warning(png_ptr, "Unable to write compressed text\n");
@@ -296,7 +334,7 @@
 #if defined(PNG_WRITE_tEXt_SUPPORTED)
             /* write uncompressed chunk */
             png_write_tEXt(png_ptr, info_ptr->text[i].key,
-               info_ptr->text[i].text, info_ptr->text[i].text_length);
+               info_ptr->text[i].text, 0);
 #else
             png_warning(png_ptr, "Unable to write uncompressed text\n");
 #endif
@@ -316,8 +354,16 @@
        for (up = info_ptr->unknown_chunks;
             up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
             up++)
-         if (up->location & PNG_HAVE_IDAT)
+       {
+         int keep=png_handle_as_unknown(png_ptr, up->name);
+         if (keep != HANDLE_CHUNK_NEVER &&
+            up->location && (up->location & PNG_AFTER_IDAT) &&
+            ((up->name[3] & 0x20) || keep == HANDLE_CHUNK_ALWAYS ||
+            (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
+         {
             png_write_chunk(png_ptr, up->name, up->data, up->size);
+         }
+       }
    }
 #endif
    }
@@ -370,9 +416,11 @@
 {
 #endif /* PNG_USER_MEM_SUPPORTED */
    png_structp png_ptr;
+#ifdef PNG_SETJMP_SUPPORTED
 #ifdef USE_FAR_KEYWORD
    jmp_buf jmpbuf;
 #endif
+#endif
    png_debug(1, "in png_create_write_struct\n");
 #ifdef PNG_USER_MEM_SUPPORTED
    if ((png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,
@@ -383,6 +431,8 @@
    {
       return ((png_structp)NULL);
    }
+
+#ifdef PNG_SETJMP_SUPPORTED
 #ifdef USE_FAR_KEYWORD
    if (setjmp(jmpbuf))
 #else
@@ -396,6 +446,8 @@
 #ifdef USE_FAR_KEYWORD
    png_memcpy(png_ptr->jmpbuf,jmpbuf,sizeof(jmp_buf));
 #endif
+#endif
+
 #ifdef PNG_USER_MEM_SUPPORTED
    png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn);
 #endif /* PNG_USER_MEM_SUPPORTED */
@@ -432,17 +484,23 @@
 void
 png_write_init(png_structp png_ptr)
 {
+#ifdef PNG_SETJMP_SUPPORTED
    jmp_buf tmp_jmp; /* to save current jump buffer */
+#endif
 
    png_debug(1, "in png_write_init\n");
+#ifdef PNG_SETJMP_SUPPORTED
    /* save jump buffer and error functions */
    png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
+#endif
 
    /* reset all variables to 0 */
    png_memset(png_ptr, 0, sizeof (png_struct));
 
+#ifdef PNG_SETJMP_SUPPORTED
    /* restore jump buffer */
    png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
+#endif
 
    /* initialize zbuf - compression buffer */
    png_ptr->zbuf_size = PNG_ZBUF_SIZE;
@@ -554,49 +612,49 @@
       switch (png_ptr->pass)
       {
          case 0:
-            if (png_ptr->row_number & 7)
+            if (png_ptr->row_number & 0x07)
             {
                png_write_finish_row(png_ptr);
                return;
             }
             break;
          case 1:
-            if ((png_ptr->row_number & 7) || png_ptr->width < 5)
+            if ((png_ptr->row_number & 0x07) || png_ptr->width < 5)
             {
                png_write_finish_row(png_ptr);
                return;
             }
             break;
          case 2:
-            if ((png_ptr->row_number & 7) != 4)
+            if ((png_ptr->row_number & 0x07) != 4)
             {
                png_write_finish_row(png_ptr);
                return;
             }
             break;
          case 3:
-            if ((png_ptr->row_number & 3) || png_ptr->width < 3)
+            if ((png_ptr->row_number & 0x03) || png_ptr->width < 3)
             {
                png_write_finish_row(png_ptr);
                return;
             }
             break;
          case 4:
-            if ((png_ptr->row_number & 3) != 2)
+            if ((png_ptr->row_number & 0x03) != 2)
             {
                png_write_finish_row(png_ptr);
                return;
             }
             break;
          case 5:
-            if ((png_ptr->row_number & 1) || png_ptr->width < 2)
+            if ((png_ptr->row_number & 0x01) || png_ptr->width < 2)
             {
                png_write_finish_row(png_ptr);
                return;
             }
             break;
          case 6:
-            if (!(png_ptr->row_number & 1))
+            if (!(png_ptr->row_number & 0x01))
             {
                png_write_finish_row(png_ptr);
                return;
@@ -744,6 +802,9 @@
 #if defined(PNG_WRITE_TEXT_SUPPORTED)
       png_free_text(png_ptr, info_ptr, -1);
 #endif
+#if defined(PNG_WRITE_tRNS_SUPPORTED)
+   png_free_tRNS(png_ptr, info_ptr);
+#endif
 #if defined(PNG_WRITE_sCAL_SUPPORTED)
       png_free_sCAL(png_ptr, info_ptr);
 #endif
@@ -754,10 +815,18 @@
       png_free_iCCP(png_ptr, info_ptr);
 #endif
 #if defined(PNG_WRITE_sPLT_SUPPORTED)
-      png_free_spalette(png_ptr, info_ptr, -1);
+      png_free_spalettes(png_ptr, info_ptr, -1);
 #endif
-#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
-      png_free_unknown_chunk(png_ptr, info_ptr, -1);
+#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
+      png_free_unknown_chunks(png_ptr, info_ptr, -1);
+      png_free_chunk_list(png_ptr);
+#endif
+#if defined(PNG_hIST_SUPPORTED)
+      png_free_hIST(png_ptr, info_ptr);
+#endif
+      png_free_PLTE(png_ptr, info_ptr);
+#if defined(PNG_INFO_IMAGE_SUPPORTED)
+   png_free_pixels(png_ptr, info_ptr);
 #endif
 
 #ifdef PNG_USER_MEM_SUPPORTED
@@ -785,7 +854,9 @@
 void
 png_write_destroy(png_structp png_ptr)
 {
+#ifdef PNG_SETJMP_SUPPORTED
    jmp_buf tmp_jmp; /* save jump buffer */
+#endif
    png_error_ptr error_fn;
    png_error_ptr warning_fn;
    png_voidp error_ptr;
@@ -818,8 +889,10 @@
    png_free(png_ptr, png_ptr->inv_filter_costs);
 #endif
 
+#ifdef PNG_SETJMP_SUPPORTED
    /* reset structure */
    png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
+#endif
 
    error_fn = png_ptr->error_fn;
    warning_fn = png_ptr->warning_fn;
@@ -837,7 +910,9 @@
    png_ptr->free_fn = free_fn;
 #endif
 
+#ifdef PNG_SETJMP_SUPPORTED
    png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
+#endif
 }
 
 /* Allow the application to select one or more row filters to use. */
@@ -872,14 +947,14 @@
        */
       if (png_ptr->row_buf != NULL)
       {
-         if (png_ptr->do_filter & PNG_FILTER_SUB && png_ptr->sub_row == NULL)
+         if ((png_ptr->do_filter & PNG_FILTER_SUB) && png_ptr->sub_row == NULL)
          {
             png_ptr->sub_row = (png_bytep)png_malloc(png_ptr,
               (png_ptr->rowbytes + 1));
             png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
          }
 
-         if (png_ptr->do_filter & PNG_FILTER_UP && png_ptr->up_row == NULL)
+         if ((png_ptr->do_filter & PNG_FILTER_UP) && png_ptr->up_row == NULL)
          {
             if (png_ptr->prev_row == NULL)
             {
@@ -894,7 +969,7 @@
             }
          }
 
-         if (png_ptr->do_filter & PNG_FILTER_AVG && png_ptr->avg_row == NULL)
+         if ((png_ptr->do_filter & PNG_FILTER_AVG) && png_ptr->avg_row == NULL)
          {
             if (png_ptr->prev_row == NULL)
             {
@@ -909,7 +984,7 @@
             }
          }
 
-         if (png_ptr->do_filter & PNG_FILTER_PAETH &&
+         if ((png_ptr->do_filter & PNG_FILTER_PAETH) &&
              png_ptr->paeth_row == NULL)
          {
             if (png_ptr->prev_row == NULL)
@@ -1127,3 +1202,87 @@
    png_ptr->write_user_transform_fn = write_user_transform_fn;
 }
 #endif
+
+
+#if defined(PNG_INFO_IMAGE_SUPPORTED)
+void png_write_png(png_structp png_ptr, png_infop info_ptr,
+                           int transforms,
+                           voidp params)
+{
+   if(transforms == 0 || params == (voidp)NULL)
+      /* quiet compiler warnings */ ;
+
+#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
+   /* invert the alpha channel from opacity to transparency */
+   if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
+       png_set_invert_alpha(png_ptr);
+#endif
+
+   /* Write the file header information. */
+   png_write_info(png_ptr, info_ptr);
+
+   /* ------ these transformations don't touch the info structure ------- */
+
+#if defined(PNG_WRITE_INVERT_SUPPORTED)
+   /* invert monochrome pixels */
+   if (transforms & PNG_TRANSFORM_INVERT_MONO)
+       png_set_invert_mono(png_ptr);
+#endif
+
+#if defined(PNG_WRITE_SHIFT_SUPPORTED)
+   /* Shift the pixels up to a legal bit depth and fill in
+    * as appropriate to correctly scale the image.
+    */
+   if ((transforms & PNG_TRANSFORM_SHIFT)
+               && (info_ptr->valid & PNG_INFO_sBIT))
+       png_set_shift(png_ptr, &info_ptr->sig_bit);
+#endif
+
+#if defined(PNG_WRITE_PACK_SUPPORTED)
+   /* pack pixels into bytes */
+   if (transforms & PNG_TRANSFORM_PACKING)
+       png_set_packing(png_ptr);
+#endif
+
+#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
+   /* swap location of alpha bytes from ARGB to RGBA */
+   if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
+       png_set_swap_alpha(png_ptr);
+#endif
+
+#if defined(PNG_WRITE_FILLER_SUPPORTED)
+   /* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into
+    * RGB (4 channels -> 3 channels). The second parameter is not used.
+    */
+   if (transforms & PNG_TRANSFORM_STRIP_FILLER)
+       png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
+#endif
+
+#if defined(PNG_WRITE_BGR_SUPPORTED)
+   /* flip BGR pixels to RGB */
+   if (transforms & PNG_TRANSFORM_BGR)
+       png_set_bgr(png_ptr);
+#endif
+
+#if defined(PNG_WRITE_SWAP_SUPPORTED)
+   /* swap bytes of 16-bit files to most significant byte first */
+   if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
+       png_set_swap(png_ptr);
+#endif
+
+#if defined(PNG_WRITE_PACKSWAP_SUPPORTED)
+   /* swap bits of 1, 2, 4 bit packed pixel formats */
+   if (transforms & PNG_TRANSFORM_PACKSWAP)
+       png_set_packswap(png_ptr);
+#endif
+
+   /* ----------------------- end of transformations ------------------- */
+
+   /* write the bits */
+   if (info_ptr->valid & PNG_INFO_IDAT)
+       png_write_image(png_ptr, info_ptr->row_pointers);
+
+   /* It is REQUIRED to call this to finish writing the rest of the file */
+   png_write_end(png_ptr, info_ptr);
+}
+#endif
diff --git a/pngwtran.c b/pngwtran.c
index 7647c4d..ed7f22f 100644
--- a/pngwtran.c
+++ b/pngwtran.c
@@ -1,11 +1,11 @@
 
 /* pngwtran.c - transforms the data in a row for PNG writers
  *
- * libpng 1.0.5h - December 10, 1999
+ * libpng 1.0.5q - February 5, 2000
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
+ * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson
  */
 
 #define PNG_INTERNAL
@@ -140,7 +140,7 @@
             {
                png_byte value;
 
-               value = (png_byte)(*sp & 0x3);
+               value = (png_byte)(*sp & 0x03);
                v |= (value << shift);
                if (shift == 0)
                {
@@ -172,7 +172,7 @@
             {
                png_byte value;
 
-               value = (png_byte)(*sp & 0xf);
+               value = (png_byte)(*sp & 0x0f);
                v |= (value << shift);
 
                if (shift == 0)
diff --git a/pngwutil.c b/pngwutil.c
index 2ac3332..3ddecbc 100644
--- a/pngwutil.c
+++ b/pngwutil.c
@@ -1,11 +1,11 @@
 
 /* pngwutil.c - utilities to write a PNG file
  *
- * libpng 1.0.5h - December 10, 1999
+ * libpng 1.0.5q - February 5, 2000
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
+ * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson
  */
 
 #define PNG_INTERNAL
@@ -133,7 +133,7 @@
       (png_size_t)8 - png_ptr->sig_bytes);
 }
 
-#if defined(PNG_WRITE_TEXT_SUPPORTED)
+#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_iCCP_SUPPORTED)
 /*
  * This pair of functions encapsulates the operation of (a) compressing a
  * text string, and (b) issuing it later as a series of chunk data writes.
@@ -334,7 +334,8 @@
    /* write saved output buffers, if any */
    for (i = 0; i < comp->num_output_ptr; i++)
    {
-      png_write_chunk_data(png_ptr,(png_bytep)comp->output_ptr[i],png_ptr->zbuf_size);
+      png_write_chunk_data(png_ptr,(png_bytep)comp->output_ptr[i],
+         png_ptr->zbuf_size);
       png_free(png_ptr, comp->output_ptr[i]);
    }
    if (comp->max_output_ptr != 0)
@@ -577,15 +578,15 @@
    png_byte buf[4];
 
    png_debug(1, "in png_write_gAMA\n");
-   /* file_gamma is saved in 1/1000000ths */
+   /* 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
-void
 #ifdef PNG_FIXED_POINT_SUPPORTED
-png_write_gAMA_fixed(png_structp png_ptr, png_uint_32 file_gamma)
+void
+png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma)
 {
 #ifdef PNG_USE_LOCAL_ARRAYS
    PNG_gAMA;
@@ -593,7 +594,7 @@
    png_byte buf[4];
 
    png_debug(1, "in png_write_gAMA\n");
-   /* file_gamma is saved in 1/1000000ths */
+   /* file_gamma is saved in 1/100,000ths */
    png_save_uint_32(buf, file_gamma);
    png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4);
 }
@@ -687,8 +688,9 @@
 
    /* make sure we include the NULL after the name */
    png_write_chunk_start(png_ptr, (png_bytep) png_sPLT,
-          (png_uint_32)(name_len + 1 + palette_size));
+          (png_uint_32)(name_len + 2 + palette_size));
    png_write_chunk_data(png_ptr, (png_bytep)new_name, name_len + 1);
+   png_write_chunk_data(png_ptr, (png_bytep)&spalette->depth, 1);
 
    /* loop through each palette entry, writing appropriately */
    for (ep = spalette->entries; ep<spalette->entries+spalette->nentries; ep++)
@@ -784,15 +786,16 @@
 #ifdef PNG_USE_LOCAL_ARRAYS
    PNG_cHRM;
 #endif
-   png_uint_32 itemp;
    png_byte buf[32];
+   png_uint_32 itemp;
 
    png_debug(1, "in png_write_cHRM\n");
-   /* each value is saved in 1/1000000ths */
+   /* each value is saved in 1/100,000ths */
    if (white_x < 0 || white_x > 0.8 || white_y < 0 || white_y > 0.8 ||
        white_x + white_y > 1.0)
    {
       png_warning(png_ptr, "Invalid cHRM white point specified");
+      printf("white_x=%f, white_y=%f\n",white_x, white_y);
       return;
    }
    itemp = (png_uint_32)(white_x * 100000.0 + 0.5);
@@ -838,22 +841,22 @@
 #endif
 #ifdef PNG_FIXED_POINT_SUPPORTED
 void
-png_write_cHRM_fixed(png_structp png_ptr, png_uint_32 white_x,
-   png_uint_32 white_y, png_uint_32 red_x, png_uint_32 red_y,
-   png_uint_32 green_x, png_uint_32 green_y, png_uint_32 blue_x,
-   png_uint_32 blue_y)
+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,
+   png_fixed_point green_x, png_fixed_point green_y, png_fixed_point blue_x,
+   png_fixed_point blue_y)
 {
 #ifdef PNG_USE_LOCAL_ARRAYS
    PNG_cHRM;
 #endif
-   png_uint_32 itemp;
    png_byte buf[32];
 
    png_debug(1, "in png_write_cHRM\n");
-   /* each value is saved int 1/1000000ths */
+   /* each value is saved in 1/100,000ths */
    if (white_x > 80000L || white_y > 80000L || white_x + white_y > 100000L)
    {
-      png_warning(png_ptr, "Invalid cHRM white point specified");
+      png_warning(png_ptr, "Invalid fixed cHRM white point specified");
+      printf("white_x=%ld, white_y=%ld\n",white_x, white_y);
       return;
    }
    png_save_uint_32(buf, white_x);
@@ -861,7 +864,7 @@
 
    if (red_x > 80000L || red_y > 80000L || red_x + red_y > 100000L)
    {
-      png_warning(png_ptr, "Invalid cHRM red point specified");
+      png_warning(png_ptr, "Invalid cHRM fixed red point specified");
       return;
    }
    png_save_uint_32(buf + 8, red_x);
@@ -869,7 +872,7 @@
 
    if (green_x > 80000L || green_y > 80000L || green_x + green_y > 100000L)
    {
-      png_warning(png_ptr, "Invalid cHRM green point specified");
+      png_warning(png_ptr, "Invalid fixed cHRM green point specified");
       return;
    }
    png_save_uint_32(buf + 16, green_x);
@@ -877,7 +880,7 @@
 
    if (blue_x > 80000L || blue_y > 80000L || blue_x + blue_y > 100000L)
    {
-      png_warning(png_ptr, "Invalid cHRM blue point specified");
+      png_warning(png_ptr, "Invalid fixed cHRM blue point specified");
       return;
    }
    png_save_uint_32(buf + 24, blue_x);
@@ -1108,7 +1111,7 @@
    {
       png_free(png_ptr, *new_key);
       *new_key=NULL;
-      png_chunk_warning(png_ptr, "zero length keyword");
+      png_chunk_warning(png_ptr, "Zero length keyword");
    }
 
    if (key_len > 79)
@@ -1143,6 +1146,8 @@
 
    if (text == NULL || *text == '\0')
       text_len = 0;
+   else
+      text_len = png_strlen(text);
 
    /* make sure we include the 0 after the key */
    png_write_chunk_start(png_ptr, (png_bytep)png_tEXt, (png_uint_32)key_len+text_len+1);
@@ -1190,6 +1195,8 @@
       return;
    }
 
+   text_len = png_strlen(text);
+
    png_free(png_ptr, new_key);
 
    /* compute the compressed data; do it now for the length */
@@ -1215,57 +1222,48 @@
 /* write an iTXt chunk */
 void
 png_write_iTXt(png_structp png_ptr, int compression, png_charp key,
-    png_charp lang, png_charp translated_key, png_charp text)
+    png_charp lang, png_charp lang_key, png_charp text)
 {
 #ifdef PNG_USE_LOCAL_ARRAYS
    PNG_iTXt;
 #endif
-   png_size_t lang_len, key_len, translated_key_len, text_len;
+   png_size_t lang_len, key_len, lang_key_len, text_len;
    png_charp new_lang, new_key;
    png_byte cbuf[2];
    compression_state comp;
 
    png_debug(1, "in png_write_iTXt\n");
 
-   translated_key_len = png_strlen(translated_key);
-   text_len = png_strlen(text);
-
+   if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0)
+   {
+      png_warning(png_ptr, "Empty keyword in iTXt chunk");
+      return;
+   }
    if (lang == NULL || (lang_len = png_check_keyword(png_ptr, lang,
       &new_lang))==0)
    {
       png_warning(png_ptr, "Empty language field in iTXt chunk");
       return;
    }
-   if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0)
-   {
-      png_warning(png_ptr, "Empty keyword in iTXt chunk");
-      return;
-   }
+   lang_key_len = png_strlen(lang_key);
+   text_len = png_strlen(text);
 
    if (text == NULL || *text == '\0')
       text_len = 0;
 
    /* compute the compressed data; do it now for the length */
-   text_len = png_text_compress(png_ptr, text, text_len, compression, &comp);
+   text_len = png_text_compress(png_ptr, text, text_len, compression-2, &comp);
 
    /* make sure we include the compression flag, the compression byte,
-    * and the NULs after the key, lang, and translated_key parts */
-   png_write_chunk_start(png_ptr, (png_bytep)png_iTXt,
-          (png_uint_32)(2 + lang_len+1 + key_len+1 + translated_key_len +
-          text_len));
+    * and the NULs after the key, lang, and lang_key parts */
 
-   /* set the compression bits */
-   if (compression == PNG_TEXT_COMPRESSION_NONE)
-   {
-       cbuf[0] = 0;
-       cbuf[1] = 0;
-   }
-   else /* compression == PNG_TEXT_COMPRESSION_zTXt */
-   {
-       cbuf[0] = 1;
-       cbuf[1] = 0;
-   }
-   png_write_chunk_data(png_ptr, cbuf, 2);
+   png_write_chunk_start(png_ptr, (png_bytep)png_iTXt,
+          (png_uint_32)(
+        5 /* comp byte, comp flag, terminators for key, lang and lang_key */
+        + key_len
+        + lang_len
+        + lang_key_len
+        + text_len));
 
    /*
     * We leave it to the application to meet PNG-1.0 requirements on the
@@ -1274,9 +1272,19 @@
     * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
     */
    png_write_chunk_data(png_ptr, (png_bytep)new_key, key_len + 1);
+
+   /* set the compression flag */
+   if (compression == PNG_ITXT_COMPRESSION_NONE || \
+       compression == PNG_TEXT_COMPRESSION_NONE)
+       cbuf[0] = 0;
+   else /* compression == PNG_ITXT_COMPRESSION_zTXt */
+       cbuf[0] = 1;
+   /* set the compression method */
+   cbuf[1] = 0;
+   png_write_chunk_data(png_ptr, cbuf, 2);
+
    png_write_chunk_data(png_ptr, (png_bytep)new_lang, lang_len + 1);
-   png_write_chunk_data(png_ptr, (png_bytep)translated_key,
-       translated_key_len);
+   png_write_chunk_data(png_ptr, (png_bytep)lang_key, lang_key_len+1);
    png_write_chunk_data(png_ptr, '\0', 1);
 
    png_write_compressed_data_out(png_ptr, &comp);
@@ -1375,7 +1383,7 @@
 /* write the sCAL chunk */
 #ifdef PNG_FLOATING_POINT_SUPPORTED
 void
-png_write_sCAL(png_structp png_ptr, png_charp unit, double width,double height)
+png_write_sCAL(png_structp png_ptr, int unit, double width,double height)
 {
 #ifdef PNG_USE_LOCAL_ARRAYS
    PNG_sCAL;
@@ -1387,19 +1395,20 @@
 
    sprintf(wbuf, "%12.12e", width);
    sprintf(hbuf, "%12.12e", height);
-   total_len = png_strlen(unit)+1 + png_strlen(wbuf)+1 + png_strlen(hbuf);
+   total_len = 1 + png_strlen(wbuf)+1 + png_strlen(hbuf);
 
    png_debug1(3, "sCAL total length = %d\n", total_len);
    png_write_chunk_start(png_ptr, (png_bytep)png_sCAL, (png_uint_32)total_len);
-   png_write_chunk_data(png_ptr, (png_bytep)unit, png_strlen(unit)+1);
+   png_write_chunk_data(png_ptr, (png_bytep)&unit, 1);
    png_write_chunk_data(png_ptr, (png_bytep)wbuf, strlen(wbuf)+1);
    png_write_chunk_data(png_ptr, (png_bytep)hbuf, strlen(hbuf));
 
    png_write_chunk_end(png_ptr);
 }
-#endif
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
 void
-png_write_sCAL_s(png_structp png_ptr, png_charp unit, png_charp width,
+png_write_sCAL_s(png_structp png_ptr, int unit, png_charp width,
    png_charp height)
 {
 #ifdef PNG_USE_LOCAL_ARRAYS
@@ -1412,17 +1421,19 @@
 
    sprintf(wbuf, "%s", width);
    sprintf(hbuf, "%s", height);
-   total_len = png_strlen(unit)+1 + png_strlen(wbuf)+1 + png_strlen(hbuf);
+   total_len = 1 + png_strlen(wbuf)+1 + png_strlen(hbuf);
 
    png_debug1(3, "sCAL total length = %d\n", total_len);
    png_write_chunk_start(png_ptr, (png_bytep)png_sCAL, (png_uint_32)total_len);
-   png_write_chunk_data(png_ptr, (png_bytep)unit, png_strlen(unit)+1);
+   png_write_chunk_data(png_ptr, (png_bytep)&unit, 1);
    png_write_chunk_data(png_ptr, (png_bytep)wbuf, strlen(wbuf)+1);
    png_write_chunk_data(png_ptr, (png_bytep)hbuf, strlen(hbuf));
 
    png_write_chunk_end(png_ptr);
 }
 #endif
+#endif
+#endif
 
 #if defined(PNG_WRITE_pHYs_SUPPORTED)
 /* write the pHYs chunk */
@@ -1730,7 +1741,7 @@
                i += png_pass_inc[pass])
             {
                sp = row + (png_size_t)(i >> 3);
-               value = (int)(*sp >> (7 - (int)(i & 7))) & 0x1;
+               value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01;
                d |= (value << shift);
 
                if (shift == 0)
@@ -1764,7 +1775,7 @@
                i += png_pass_inc[pass])
             {
                sp = row + (png_size_t)(i >> 2);
-               value = (*sp >> ((3 - (int)(i & 3)) << 1)) & 0x3;
+               value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03;
                d |= (value << shift);
 
                if (shift == 0)
@@ -1797,7 +1808,7 @@
                i += png_pass_inc[pass])
             {
                sp = row + (png_size_t)(i >> 1);
-               value = (*sp >> ((1 - (int)(i & 1)) << 2)) & 0xf;
+               value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f;
                d |= (value << shift);
 
                if (shift == 0)
@@ -1904,7 +1915,7 @@
    /* We don't need to test the 'no filter' case if this is the only filter
     * that has been chosen, as it doesn't actually do anything to the data.
     */
-   if (filter_to_do & PNG_FILTER_NONE &&
+   if ((filter_to_do & PNG_FILTER_NONE) &&
        filter_to_do != PNG_FILTER_NONE)
    {
       png_bytep rp;
diff --git a/scripts/pngdll.mak b/scripts/makefile.bd32
similarity index 100%
rename from scripts/pngdll.mak
rename to scripts/makefile.bd32
diff --git a/scripts/makefile.beos b/scripts/makefile.beos
index b764fcc..b863706 100644
--- a/scripts/makefile.beos
+++ b/scripts/makefile.beos
@@ -31,7 +31,7 @@
 # read libpng.txt or png.h to see why PNGMAJ is 2.  You should not
 # have to change it.
 PNGMAJ = 2
-PNGMIN = 1.0.5h
+PNGMIN = 1.0.5q
 PNGVER = $(PNGMAJ).$(PNGMIN)
 
 # where make install puts libpng.a, libpng.so*, and png.h
diff --git a/scripts/makefile.dec b/scripts/makefile.dec
index 0e14dfe..7a00e47 100644
--- a/scripts/makefile.dec
+++ b/scripts/makefile.dec
@@ -14,7 +14,7 @@
 # read libpng.txt or png.h to see why PNGMAJ is 2.  You should not
 # have to change it.
 PNGMAJ = 2
-PNGMIN = 1.0.5h
+PNGMIN = 1.0.5q
 PNGVER = $(PNGMAJ).$(PNGMIN)
 
 CC=cc
diff --git a/scripts/makefile.gcmmx b/scripts/makefile.gcmmx
new file mode 100644
index 0000000..4f17231
--- /dev/null
+++ b/scripts/makefile.gcmmx
@@ -0,0 +1,112 @@
+# makefile for libpng on Linux ELF with gcc using MMX assembler code
+# Copyright (C) 1996, 1997 Andreas Dilger
+# Copyright (C) 1998, 1999, 2000 Greg Roelofs
+# For conditions of distribution and use, see copyright notice in png.h
+
+CC=gcc
+
+# where "make install" puts libpng.a, libpng.so*, png.h and pngconf.h
+prefix=/usr/local
+
+# Where the zlib library and include files are located
+#ZLIBLIB=/usr/local/lib
+#ZLIBINC=/usr/local/include
+ZLIBLIB=../zlib
+ZLIBINC=../zlib
+
+ALIGN=
+# for i386:
+#ALIGN=-malign-loops=2 -malign-functions=2
+
+WARNMORE=-Wwrite-strings -Wpointer-arith -Wshadow \
+	-Wmissing-declarations -Wtraditional -Wcast-align \
+	-Wstrict-prototypes -Wmissing-prototypes #-Wconversion
+
+# for pgcc version 2.95.1, -O3 is buggy; don't use it.
+
+CFLAGS=-DPNG_USE_PNGGCCRD -I$(ZLIBINC) -Wall -O3 $(ALIGN) \
+	-funroll-loops -fomit-frame-pointer	# $(WARNMORE) -g -DPNG_DEBUG=5
+LDFLAGS=-L. -Wl,-rpath,. -L$(ZLIBLIB) -Wl,-rpath,$(ZLIBLIB) -lpng -lz -lm
+
+RANLIB=ranlib
+#RANLIB=echo
+
+# read libpng.txt or png.h to see why PNGMAJ is 2.  You should not
+# have to change it.
+PNGMAJ = 2
+PNGMIN = 1.0.5q
+PNGVER = $(PNGMAJ).$(PNGMIN)
+
+INCPATH=$(prefix)/include
+LIBPATH=$(prefix)/lib
+
+OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \
+	pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \
+	pngwtran.o pngmem.o pngerror.o pngpread.o pnggccrd.o
+
+OBJSDLL = $(OBJS:.o=.pic.o)
+
+.SUFFIXES:      .c .o .pic.o
+
+.c.pic.o:
+	$(CC) -c $(CFLAGS) -fPIC -o $@ $*.c
+
+all: libpng.a libpng.so pngtest
+
+libpng.a: $(OBJS)
+	ar rc $@ $(OBJS)
+	$(RANLIB) $@
+
+libpng.so: libpng.so.$(PNGMAJ)
+	ln -sf libpng.so.$(PNGMAJ) libpng.so
+
+libpng.so.$(PNGMAJ): libpng.so.$(PNGVER)
+	ln -sf libpng.so.$(PNGVER) libpng.so.$(PNGMAJ)
+
+libpng.so.$(PNGVER): $(OBJSDLL)
+	$(CC) -shared -Wl,-soname,libpng.so.$(PNGMAJ) -o libpng.so.$(PNGVER) \
+	 $(OBJSDLL) -L$(ZLIBLIB) -lz -lm -lc
+
+pngtest: pngtest.o libpng.so
+	$(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS)
+
+test: pngtest
+	./pngtest
+
+install: libpng.a libpng.so.$(PNGVER)
+	-@mkdir $(INCPATH) $(LIBPATH)
+	cp png.h pngconf.h $(INCPATH)
+	chmod 644 $(INCPATH)/png.h $(INCPATH)/pngconf.h
+	cp libpng.a libpng.so.$(PNGVER) $(LIBPATH)
+	chmod 755 $(LIBPATH)/libpng.so.$(PNGVER)
+	-@/bin/rm -f $(LIBPATH)/libpng.so.$(PNGMAJ) $(LIBPATH)/libpng.so
+	(cd $(LIBPATH); ln -sf libpng.so.$(PNGVER) libpng.so.$(PNGMAJ); \
+	 ln -sf libpng.so.$(PNGMAJ) libpng.so)
+
+clean:
+	/bin/rm -f *.o libpng.a libpng.so* pngtest pngout.png
+
+DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO
+writelock:
+	chmod a-w *.[ch35] $(DOCS) scripts/*
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
+
+png.o png.pic.o: png.h pngconf.h
+pngerror.o pngerror.pic.o: png.h pngconf.h
+pngrio.o pngrio.pic.o: png.h pngconf.h
+pngwio.o pngwio.pic.o: png.h pngconf.h
+pngmem.o pngmem.pic.o: png.h pngconf.h
+pngset.o pngset.pic.o: png.h pngconf.h
+pngget.o pngget.pic.o: png.h pngconf.h
+pngread.o pngread.pic.o: png.h pngconf.h
+pngrtran.o pngrtran.pic.o: png.h pngconf.h
+pngrutil.o pngrutil.pic.o: png.h pngconf.h
+pngtrans.o pngtrans.pic.o: png.h pngconf.h
+pngwrite.o pngwrite.pic.o: png.h pngconf.h
+pngwtran.o pngwtran.pic.o: png.h pngconf.h
+pngwutil.o pngwutil.pic.o: png.h pngconf.h
+pngpread.o pngpread.pic.o: png.h pngconf.h
+pnggccrd.o pnggccrd.pic.o: png.h pngconf.h
+
+pngtest.o: png.h pngconf.h
diff --git a/scripts/makefile.linux b/scripts/makefile.linux
index 0ea7d3e..8796904 100644
--- a/scripts/makefile.linux
+++ b/scripts/makefile.linux
@@ -34,7 +34,7 @@
 # read libpng.txt or png.h to see why PNGMAJ is 2.  You should not
 # have to change it.
 PNGMAJ = 2
-PNGMIN = 1.0.5h
+PNGMIN = 1.0.5q
 PNGVER = $(PNGMAJ).$(PNGMIN)
 
 INCPATH=$(prefix)/include
diff --git a/scripts/makefile.sco b/scripts/makefile.sco
index 176a536..4e94029 100644
--- a/scripts/makefile.sco
+++ b/scripts/makefile.sco
@@ -25,7 +25,7 @@
 # read libpng.txt or png.h to see why PNGMAJ is 2.  You should not
 # have to change it.
 PNGMAJ = 2
-PNGMIN = 1.0.5h
+PNGMIN = 1.0.5q
 PNGVER = $(PNGMAJ).$(PNGMIN)
 
 INCPATH=$(prefix)/include
diff --git a/scripts/makefile.solaris b/scripts/makefile.solaris
index b796907..922b6af 100644
--- a/scripts/makefile.solaris
+++ b/scripts/makefile.solaris
@@ -6,17 +6,6 @@
 
 CC=gcc
 
-case "`type ld`" in *ucb*) echo "
-# WARNING:
-# The commands "CC" and "LD" must NOT refer to /usr/ucb/cc and
-# /usr/ucb/ld.  If they do, you need to adjust your PATH environment
-# variable to put /usr/ccs/bin ahead of /usr/ucb.  The environment
-# variable LD_LIBRARY_PATH should not be set at all.  If it is,
-# things are likely to break because of the libucb dependency that
-# is created.
-" ;;
-esac
-
 # Where make install puts libpng.a, libpng.so*, and png.h
 prefix=/usr/local
 
@@ -42,7 +31,7 @@
 # read libpng.txt or png.h to see why PNGMAJ is 2.  You should not
 # have to change it.
 PNGMAJ = 2
-PNGMIN = 1.0.5h
+PNGMIN = 1.0.5q
 PNGVER = $(PNGMAJ).$(PNGMIN)
 
 INCPATH=$(prefix)/include
@@ -72,6 +61,18 @@
 	ln -f -s libpng.so.$(PNGVER) libpng.so.$(PNGMAJ)
 
 libpng.so.$(PNGVER): $(OBJSDLL)
+	@case "`type ld`" in *ucb*) \
+	echo; \
+	echo '## WARNING:'; \
+	echo '## The commands "CC" and "LD" must NOT refer to /usr/ucb/cc'; \
+	echo '## and /usr/ucb/ld.  If they do, you need to adjust your PATH'; \
+	echo '## environment variable to put /usr/ccs/bin ahead of /usr/ucb.'; \
+	echo '## The environment variable LD_LIBRARY_PATH should not be set'; \
+	echo '## at all.  If it is, things are likely to break because of'; \
+	echo '## the libucb dependency that is created.'; \
+	echo; \
+	;; \
+	esac
 	$(LD) -G -L$(ZLIBLIB) -R$(ZLIBLIB) -h libpng.so.$(PNGMAJ) \
 	 -o libpng.so.$(PNGVER) $(OBJSDLL) -lz
 
diff --git a/scripts/makefile.vcawin32 b/scripts/makefile.vcawin32
index be7fcc8..aef0a6e 100644
--- a/scripts/makefile.vcawin32
+++ b/scripts/makefile.vcawin32
@@ -81,6 +81,7 @@
 	$(CC) -c $(CFLAGS) $*.c $(ERRFILE)
 
 libpng.lib: $(OBJS1) $(OBJS2) $(OBJS3)
+	echo something to del > libpng.lib
 	del libpng.lib
 	lib /OUT:libpng.lib $(OBJS1) $(OBJS2) $(OBJS3)
 
diff --git a/scripts/makefile.vcwin32 b/scripts/makefile.vcwin32
index 5b62fc3..593137d 100644
--- a/scripts/makefile.vcwin32
+++ b/scripts/makefile.vcwin32
@@ -74,6 +74,7 @@
 	$(CC) -c $(CFLAGS) $*.c $(ERRFILE)
 
 libpng.lib: $(OBJS1) $(OBJS2) $(OBJS3)
+	echo something to del > libpng.lib
 	del libpng.lib
 	lib /OUT:libpng.lib $(OBJS1) $(OBJS2) $(OBJS3)
 
diff --git a/scripts/pngdef.pas b/scripts/pngdef.pas
index 81f0406..832b7f3 100644
--- a/scripts/pngdef.pas
+++ b/scripts/pngdef.pas
@@ -3,7 +3,7 @@
 interface
 
 const
-  PNG_LIBPNG_VER_STRING = '1.0.5h';
+  PNG_LIBPNG_VER_STRING = '1.0.5n';
   PNG_LIBPNG_VER        =  10006;
 
 type
@@ -56,6 +56,9 @@
   png_write_status_ptr = procedure(png_ptr: Pointer;
                            row_number: png_uint_32; pass: int);
              stdcall;
+  png_user_chunk_ptr = procedure(png_ptr: Pointer;
+                             data: png_unknown_chunkp);
+             stdcall;
   png_user_transform_ptr = procedure(png_ptr: Pointer;
                              row_info: Pointer; data: png_bytep);
              stdcall;
@@ -380,6 +383,9 @@
              var text_ptr: png_textp; var num_text: int):
              png_uint_32;
              stdcall;
+function png_get_user_chunk_ptr(png_ptr: png_structp):
+             png_voidp;
+             stdcall;
 function png_get_valid(png_ptr: png_structp; info_ptr: png_infop;
              flag: png_uint_32): png_uint_32;
              stdcall;
@@ -525,6 +531,9 @@
 procedure png_set_read_status_fn(png_ptr: png_structp;
              read_row_fn: png_read_status_ptr);
              stdcall;
+procedure png_set_read_user_chunk_fn(png_ptr: png_structp;
+             read_user_chunk_fn: png_user_chunk_ptr);
+             stdcall;
 procedure png_set_read_user_transform_fn(png_ptr: png_structp;
              read_user_transform_fn: png_user_transform_ptr);
              stdcall;
@@ -613,14 +622,22 @@
              stdcall;
 procedure png_free_pCAL(png_ptr: png_structp; info_ptr: png_infop);
              stdcall;
+procedure png_free_sCAL(png_ptr: png_structp; info_ptr: png_infop);
+             stdcall;
 procedure png_set_iCCP(png_ptr: png_structp; info_ptr: png_infop;
              name: png_charp; compression_type: int; profile: png_charp;
              proflen: int);
              stdcall;
+procedure png_free_hIST(png_ptr: png_structp; info_ptr: png_infop);
+             stdcall;
 procedure png_free_iCCP(png_ptr: png_structp; info_ptr: png_infop);
              stdcall;
+procedure png_free_PLTE(png_ptr: png_structp; info_ptr: png_infop);
+             stdcall;
 procedure png_free_text(png_ptr: png_structp; info_ptr: png_infop);
              stdcall;
+procedure png_free_tRNS(png_ptr: png_structp; info_ptr: png_infop);
+             stdcall;
 procedure png_set_spalettes(png_ptr: png_structp; info_ptr: png_infop;
              entries: png_spalette_p; nentries: int);
              stdcall;
@@ -673,6 +690,7 @@
 function png_get_tIME; external pngDLL;
 function png_get_tRNS; external pngDLL;
 function png_get_text; external pngDLL;
+function png_get_user_chunk_ptr; external pngDLL;
 function png_get_valid; external pngDLL;
 function png_get_x_offset_microns; external pngDLL;
 function png_get_x_offset_pixels; external pngDLL;
@@ -735,6 +753,7 @@
 procedure png_set_tIME; external pngDLL;
 procedure png_set_tRNS; external pngDLL;
 procedure png_set_text; external pngDLL;
+procedure png_set_user_chunk_fn; external pngDLL;
 procedure png_set_write_fn; external pngDLL;
 procedure png_set_write_status_fn; external pngDLL;
 procedure png_set_write_user_transform_fn; external pngDLL;
@@ -755,8 +774,12 @@
 procedure png_get_spalettes; external pngDLL;
 procedure png_free_pCAL; external pngDLL;
 procedure png_set_iCCP; external pngDLL;
+procedure png_free_hIST; external pngDLL;
 procedure png_free_iCCP; external pngDLL;
+procedure png_free_PLTE; external pngDLL;
+procedure png_free_sCAL; external pngDLL;
 procedure png_free_text; external pngDLL;
+procedure png_free_tRNS; external pngDLL;
 procedure png_set_spalettes; external pngDLL;
 procedure png_free_sPLT; external pngDLL;
 
diff --git a/scripts/pngos2.def b/scripts/pngos2.def
index 9edb8bf..ce5735f 100644
--- a/scripts/pngos2.def
+++ b/scripts/pngos2.def
@@ -47,6 +47,7 @@
   png_set_dither
   png_set_gamma
   png_set_flush
+  png_set_user_chunk_fn
   png_write_flush
   png_start_read_image
   png_read_update_info
@@ -79,6 +80,7 @@
   png_get_header_ver
   png_get_header_version
   png_get_libpng_ver
+  png_get_user_chunk_ptr
 ; png_get_mem_fn
 ; png_set_mem_fn
   png_set_write_fn
@@ -177,20 +179,24 @@
   png_write_PLTE
   png_write_IDAT
   png_write_IEND
-  png_write_gAMA
-  png_write_sBIT
-  png_write_cHRM
-  png_write_sRGB
-  png_write_tRNS
   png_write_bKGD
+  png_write_cHRM
+  png_write_gAMA
   png_write_hIST
-  png_check_keyword
-  png_write_tEXt
-  png_write_zTXt
+  png_write_iCCP
+  png_write_iTXt
   png_write_oFFs
   png_write_pCAL
   png_write_pHYs
+  png_write_sBIT
+  png_write_sCAL
+  png_write_sPLT
+  png_write_sRGB
+  png_check_keyword
+  png_write_tEXt
   png_write_tIME
+  png_write_tRNS
+  png_write_zTXt
   png_write_finish_row
   png_write_start_row
   png_build_gamma_table
@@ -229,18 +235,22 @@
   png_handle_IHDR
   png_handle_PLTE
   png_handle_IEND
-  png_handle_gAMA
-  png_handle_sBIT
-  png_handle_cHRM
-  png_handle_sRGB
-  png_handle_tRNS
   png_handle_bKGD
+  png_handle_cHRM
+  png_handle_gAMA
   png_handle_hIST
+  png_handle_iCCP
+  png_handle_iTXt
   png_handle_oFFs
   png_handle_pCAL
   png_handle_pHYs
-  png_handle_tIME
+  png_handle_sBIT
+  png_handle_sCAL
+  png_handle_sPLT
+  png_handle_sRGB
   png_handle_tEXt
+  png_handle_tIME
+  png_handle_tRNS
   png_handle_zTXt
   png_handle_unknown
   png_check_chunk_name
@@ -282,13 +292,16 @@
   png_get_iCCP 
   png_get_sCAL
   png_get_spalettes 
-  png_free_pCAL 
   png_set_iCCP 
-  png_free_iCCP 
-  png_free_text 
-  png_free_sCAL
   png_set_spalettes 
+  png_free_hIST 
+  png_free_iCCP 
+  png_free_pCAL 
+  png_free_PLTE 
+  png_free_sCAL
   png_free_sPLT 
+  png_free_text 
+  png_free_tRNS 
 
   png_IHDR
   png_IDAT