From e2edf4e270cb1a250f8f0ddac03b3ca3c93b34e6 Mon Sep 17 00:00:00 2001
From: Romain Garrigues <romain.garrigues@c-s.fr>
Date: Tue, 30 May 2006 06:57:01 +0000
Subject: [PATCH] =?UTF-8?q?Ajout=20du=20r=C3=A9pertoire=20ITK=20dans=20Uti?=
 =?UTF-8?q?lities?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 Utilities/ITK/Utilities/CMakeLists.txt        |   72 +
 .../ITK/Utilities/openjpeg/.NoDartCoverage    |    0
 .../ITK/Utilities/openjpeg/CMakeLists.txt     |   42 +
 .../ITK/Utilities/openjpeg/README.ITK.txt     |   31 +
 Utilities/ITK/Utilities/openjpeg/bio.c        |  186 +
 Utilities/ITK/Utilities/openjpeg/bio.h        |  124 +
 Utilities/ITK/Utilities/openjpeg/cio.c        |  189 +
 Utilities/ITK/Utilities/openjpeg/cio.h        |   85 +
 Utilities/ITK/Utilities/openjpeg/dwt.c        |  610 ++
 Utilities/ITK/Utilities/openjpeg/dwt.h        |  112 +
 Utilities/ITK/Utilities/openjpeg/event.c      |  181 +
 Utilities/ITK/Utilities/openjpeg/event.h      |   58 +
 Utilities/ITK/Utilities/openjpeg/fix.h        |   62 +
 Utilities/ITK/Utilities/openjpeg/image.c      |   87 +
 Utilities/ITK/Utilities/openjpeg/image.h      |   48 +
 Utilities/ITK/Utilities/openjpeg/int.h        |  118 +
 Utilities/ITK/Utilities/openjpeg/j2k.c        | 1924 ++++++
 Utilities/ITK/Utilities/openjpeg/j2k.h        |  429 ++
 Utilities/ITK/Utilities/openjpeg/j2k_lib.c    |   76 +
 Utilities/ITK/Utilities/openjpeg/j2k_lib.h    |   75 +
 Utilities/ITK/Utilities/openjpeg/jp2.c        |  704 +++
 Utilities/ITK/Utilities/openjpeg/jp2.h        |  162 +
 Utilities/ITK/Utilities/openjpeg/jpt.c        |  154 +
 Utilities/ITK/Utilities/openjpeg/jpt.h        |   74 +
 Utilities/ITK/Utilities/openjpeg/mct.c        |  131 +
 Utilities/ITK/Utilities/openjpeg/mct.h        |   97 +
 Utilities/ITK/Utilities/openjpeg/mqc.c        |  541 ++
 Utilities/ITK/Utilities/openjpeg/mqc.h        |  196 +
 Utilities/ITK/Utilities/openjpeg/openjpeg.c   |  264 +
 Utilities/ITK/Utilities/openjpeg/openjpeg.h   |  628 ++
 .../ITK/Utilities/openjpeg/opj_includes.h     |   97 +
 Utilities/ITK/Utilities/openjpeg/pi.c         |  554 ++
 Utilities/ITK/Utilities/openjpeg/pi.h         |  130 +
 Utilities/ITK/Utilities/openjpeg/raw.c        |   86 +
 Utilities/ITK/Utilities/openjpeg/raw.h        |   99 +
 Utilities/ITK/Utilities/openjpeg/t1.c         | 1095 ++++
 Utilities/ITK/Utilities/openjpeg/t1.h         |  150 +
 Utilities/ITK/Utilities/openjpeg/t2.c         |  672 +++
 Utilities/ITK/Utilities/openjpeg/t2.h         |   99 +
 Utilities/ITK/Utilities/openjpeg/tcd.c        | 1417 +++++
 Utilities/ITK/Utilities/openjpeg/tcd.h        |  266 +
 Utilities/ITK/Utilities/openjpeg/tgt.c        |  212 +
 Utilities/ITK/Utilities/openjpeg/tgt.h        |  113 +
 Utilities/ITK/Utilities/png/.NoDartCoverage   |    0
 Utilities/ITK/Utilities/png/CMakeLists.txt    |   38 +
 Utilities/ITK/Utilities/png/itk_png_mangle.h  |  349 ++
 Utilities/ITK/Utilities/png/png.c             |  729 +++
 Utilities/ITK/Utilities/png/png.h             | 3097 ++++++++++
 Utilities/ITK/Utilities/png/pngDllConfig.h.in |   11 +
 Utilities/ITK/Utilities/png/pngasmrd.h        |   11 +
 Utilities/ITK/Utilities/png/pngconf.h         | 1341 +++++
 Utilities/ITK/Utilities/png/pngerror.c        |  290 +
 Utilities/ITK/Utilities/png/pnggccrd.c        | 5208 +++++++++++++++++
 Utilities/ITK/Utilities/png/pngget.c          |  829 +++
 Utilities/ITK/Utilities/png/pngmem.c          |  531 ++
 Utilities/ITK/Utilities/png/pngpread.c        | 1504 +++++
 Utilities/ITK/Utilities/png/pngread.c         | 1424 +++++
 Utilities/ITK/Utilities/png/pngrio.c          |  162 +
 Utilities/ITK/Utilities/png/pngrtran.c        | 4115 +++++++++++++
 Utilities/ITK/Utilities/png/pngrutil.c        | 3000 ++++++++++
 Utilities/ITK/Utilities/png/pngset.c          |  972 +++
 Utilities/ITK/Utilities/png/pngtest.c         | 1514 +++++
 Utilities/ITK/Utilities/png/pngtrans.c        |  611 ++
 Utilities/ITK/Utilities/png/pngvcrd.c         | 3836 ++++++++++++
 Utilities/ITK/Utilities/png/pngwio.c          |  228 +
 Utilities/ITK/Utilities/png/pngwrite.c        | 1447 +++++
 Utilities/ITK/Utilities/png/pngwtran.c        |  563 ++
 Utilities/ITK/Utilities/png/pngwutil.c        | 2646 +++++++++
 Utilities/ITK/Utilities/tiff/.NoDartCoverage  |    0
 Utilities/ITK/Utilities/tiff/CMakeLists.txt   |  153 +
 Utilities/ITK/Utilities/tiff/COPYRIGHT        |   21 +
 Utilities/ITK/Utilities/tiff/README           |   59 +
 Utilities/ITK/Utilities/tiff/RELEASE-DATE     |    1 +
 Utilities/ITK/Utilities/tiff/VERSION          |    1 +
 Utilities/ITK/Utilities/tiff/dist/newalpha    |    8 +
 Utilities/ITK/Utilities/tiff/dist/newversion  |   31 +
 Utilities/ITK/Utilities/tiff/dist/tiff.alpha  |    1 +
 Utilities/ITK/Utilities/tiff/dist/tiff.spec   |   68 +
 .../ITK/Utilities/tiff/dist/tiff.version      |    1 +
 Utilities/ITK/Utilities/tiff/fax3sm_winnt.c   | 1047 ++++
 .../ITK/Utilities/tiff/itk_tiff_mangle.h      |  260 +
 Utilities/ITK/Utilities/tiff/itktiff.def      |   88 +
 Utilities/ITK/Utilities/tiff/mkg3states.c     |  439 ++
 Utilities/ITK/Utilities/tiff/mkspans.c        |   72 +
 Utilities/ITK/Utilities/tiff/mkversion.c      |  175 +
 Utilities/ITK/Utilities/tiff/port.h           |   36 +
 Utilities/ITK/Utilities/tiff/t4.h             |  285 +
 Utilities/ITK/Utilities/tiff/tconf.h          |   59 +
 Utilities/ITK/Utilities/tiff/tif_acorn.c      |  519 ++
 Utilities/ITK/Utilities/tiff/tif_apple.c      |  274 +
 Utilities/ITK/Utilities/tiff/tif_atari.c      |  243 +
 Utilities/ITK/Utilities/tiff/tif_aux.c        |  264 +
 Utilities/ITK/Utilities/tiff/tif_close.c      |  119 +
 Utilities/ITK/Utilities/tiff/tif_codec.c      |  150 +
 Utilities/ITK/Utilities/tiff/tif_color.c      |  267 +
 Utilities/ITK/Utilities/tiff/tif_compress.c   |  283 +
 Utilities/ITK/Utilities/tiff/tif_config.h.in  |  253 +
 Utilities/ITK/Utilities/tiff/tif_dir.c        | 1478 +++++
 Utilities/ITK/Utilities/tiff/tif_dir.h        |  265 +
 Utilities/ITK/Utilities/tiff/tif_dirinfo.c    |  535 ++
 Utilities/ITK/Utilities/tiff/tif_dirread.c    | 1611 +++++
 Utilities/ITK/Utilities/tiff/tif_dirwrite.c   | 1237 ++++
 Utilities/ITK/Utilities/tiff/tif_dumpmode.c   |  117 +
 Utilities/ITK/Utilities/tiff/tif_error.c      |   49 +
 Utilities/ITK/Utilities/tiff/tif_extension.c  |  111 +
 Utilities/ITK/Utilities/tiff/tif_fax3.c       | 1556 +++++
 Utilities/ITK/Utilities/tiff/tif_fax3.h       |  526 ++
 Utilities/ITK/Utilities/tiff/tif_fax3sm.c     | 1253 ++++
 Utilities/ITK/Utilities/tiff/tif_flush.c      |   67 +
 Utilities/ITK/Utilities/tiff/tif_getimage.c   | 2596 ++++++++
 Utilities/ITK/Utilities/tiff/tif_jpeg.c       | 1754 ++++++
 Utilities/ITK/Utilities/tiff/tif_luv.c        | 1601 +++++
 Utilities/ITK/Utilities/tiff/tif_lzw.c        | 1078 ++++
 Utilities/ITK/Utilities/tiff/tif_msdos.c      |  179 +
 Utilities/ITK/Utilities/tiff/tif_next.c       |  143 +
 Utilities/ITK/Utilities/tiff/tif_ojpeg.c      | 2640 +++++++++
 Utilities/ITK/Utilities/tiff/tif_open.c       |  642 ++
 Utilities/ITK/Utilities/tiff/tif_packbits.c   |  292 +
 Utilities/ITK/Utilities/tiff/tif_pixarlog.c   | 1333 +++++
 Utilities/ITK/Utilities/tiff/tif_predict.c    |  463 ++
 Utilities/ITK/Utilities/tiff/tif_predict.h    |   61 +
 Utilities/ITK/Utilities/tiff/tif_print.c      |  618 ++
 Utilities/ITK/Utilities/tiff/tif_read.c       |  641 ++
 Utilities/ITK/Utilities/tiff/tif_stream.cxx   |  289 +
 Utilities/ITK/Utilities/tiff/tif_strip.c      |  261 +
 Utilities/ITK/Utilities/tiff/tif_swab.c       |  218 +
 Utilities/ITK/Utilities/tiff/tif_thunder.c    |  157 +
 Utilities/ITK/Utilities/tiff/tif_tile.c       |  264 +
 Utilities/ITK/Utilities/tiff/tif_unix.c       |  291 +
 Utilities/ITK/Utilities/tiff/tif_version.c    |   33 +
 Utilities/ITK/Utilities/tiff/tif_vms.c        |  588 ++
 Utilities/ITK/Utilities/tiff/tif_warning.c    |   49 +
 Utilities/ITK/Utilities/tiff/tif_win3.c       |  225 +
 Utilities/ITK/Utilities/tiff/tif_win32.c      |  389 ++
 Utilities/ITK/Utilities/tiff/tif_write.c      |  716 +++
 Utilities/ITK/Utilities/tiff/tif_zip.c        |  368 ++
 Utilities/ITK/Utilities/tiff/tiff.h           |  568 ++
 .../ITK/Utilities/tiff/tiffDllConfig.h.in     |    7 +
 Utilities/ITK/Utilities/tiff/tiffcomp.h       |  214 +
 Utilities/ITK/Utilities/tiff/tiffconf.h       |   80 +
 Utilities/ITK/Utilities/tiff/tiffio.h         |  501 ++
 Utilities/ITK/Utilities/tiff/tiffio.hxx       |   42 +
 Utilities/ITK/Utilities/tiff/tiffiop.h        |  306 +
 Utilities/ITK/Utilities/tiff/tiffvers.h       |    9 +
 Utilities/ITK/Utilities/tiff/uvcode.h         |  173 +
 Utilities/ITK/Utilities/zlib/.NoDartCoverage  |    0
 Utilities/ITK/Utilities/zlib/CMakeLists.txt   |   41 +
 Utilities/ITK/Utilities/zlib/adler32.c        |   48 +
 Utilities/ITK/Utilities/zlib/compress.c       |   68 +
 Utilities/ITK/Utilities/zlib/crc32.c          |  162 +
 Utilities/ITK/Utilities/zlib/deflate.c        | 1350 +++++
 Utilities/ITK/Utilities/zlib/deflate.h        |  318 +
 Utilities/ITK/Utilities/zlib/example.c        |  556 ++
 Utilities/ITK/Utilities/zlib/gzio.c           |  875 +++
 Utilities/ITK/Utilities/zlib/infblock.c       |  398 ++
 Utilities/ITK/Utilities/zlib/infblock.h       |   39 +
 Utilities/ITK/Utilities/zlib/infcodes.c       |  257 +
 Utilities/ITK/Utilities/zlib/infcodes.h       |   27 +
 Utilities/ITK/Utilities/zlib/inffast.c        |  170 +
 Utilities/ITK/Utilities/zlib/inffast.h        |   17 +
 Utilities/ITK/Utilities/zlib/inffixed.h       |  151 +
 Utilities/ITK/Utilities/zlib/inflate.c        |  366 ++
 Utilities/ITK/Utilities/zlib/inftrees.c       |  456 ++
 Utilities/ITK/Utilities/zlib/inftrees.h       |   58 +
 Utilities/ITK/Utilities/zlib/infutil.c        |   87 +
 Utilities/ITK/Utilities/zlib/infutil.h        |   98 +
 .../ITK/Utilities/zlib/itk_zlib_mangle.h      |   86 +
 Utilities/ITK/Utilities/zlib/maketree.c       |   86 +
 Utilities/ITK/Utilities/zlib/minigzip.c       |  320 +
 Utilities/ITK/Utilities/zlib/trees.c          | 1214 ++++
 Utilities/ITK/Utilities/zlib/trees.h          |  128 +
 Utilities/ITK/Utilities/zlib/uncompr.c        |   58 +
 Utilities/ITK/Utilities/zlib/zconf.h          |  290 +
 Utilities/ITK/Utilities/zlib/zlib.def         |   50 +
 Utilities/ITK/Utilities/zlib/zlib.h           |  893 +++
 Utilities/ITK/Utilities/zlib/zlib.rc          |   32 +
 .../ITK/Utilities/zlib/zlibDllConfig.h.in     |    6 +
 Utilities/ITK/Utilities/zlib/zutil.c          |  225 +
 Utilities/ITK/Utilities/zlib/zutil.h          |  220 +
 179 files changed, 89827 insertions(+)
 create mode 100644 Utilities/ITK/Utilities/CMakeLists.txt
 create mode 100644 Utilities/ITK/Utilities/openjpeg/.NoDartCoverage
 create mode 100644 Utilities/ITK/Utilities/openjpeg/CMakeLists.txt
 create mode 100644 Utilities/ITK/Utilities/openjpeg/README.ITK.txt
 create mode 100644 Utilities/ITK/Utilities/openjpeg/bio.c
 create mode 100644 Utilities/ITK/Utilities/openjpeg/bio.h
 create mode 100644 Utilities/ITK/Utilities/openjpeg/cio.c
 create mode 100644 Utilities/ITK/Utilities/openjpeg/cio.h
 create mode 100644 Utilities/ITK/Utilities/openjpeg/dwt.c
 create mode 100644 Utilities/ITK/Utilities/openjpeg/dwt.h
 create mode 100644 Utilities/ITK/Utilities/openjpeg/event.c
 create mode 100644 Utilities/ITK/Utilities/openjpeg/event.h
 create mode 100644 Utilities/ITK/Utilities/openjpeg/fix.h
 create mode 100644 Utilities/ITK/Utilities/openjpeg/image.c
 create mode 100644 Utilities/ITK/Utilities/openjpeg/image.h
 create mode 100644 Utilities/ITK/Utilities/openjpeg/int.h
 create mode 100644 Utilities/ITK/Utilities/openjpeg/j2k.c
 create mode 100644 Utilities/ITK/Utilities/openjpeg/j2k.h
 create mode 100644 Utilities/ITK/Utilities/openjpeg/j2k_lib.c
 create mode 100644 Utilities/ITK/Utilities/openjpeg/j2k_lib.h
 create mode 100644 Utilities/ITK/Utilities/openjpeg/jp2.c
 create mode 100644 Utilities/ITK/Utilities/openjpeg/jp2.h
 create mode 100644 Utilities/ITK/Utilities/openjpeg/jpt.c
 create mode 100644 Utilities/ITK/Utilities/openjpeg/jpt.h
 create mode 100644 Utilities/ITK/Utilities/openjpeg/mct.c
 create mode 100644 Utilities/ITK/Utilities/openjpeg/mct.h
 create mode 100644 Utilities/ITK/Utilities/openjpeg/mqc.c
 create mode 100644 Utilities/ITK/Utilities/openjpeg/mqc.h
 create mode 100644 Utilities/ITK/Utilities/openjpeg/openjpeg.c
 create mode 100644 Utilities/ITK/Utilities/openjpeg/openjpeg.h
 create mode 100644 Utilities/ITK/Utilities/openjpeg/opj_includes.h
 create mode 100644 Utilities/ITK/Utilities/openjpeg/pi.c
 create mode 100644 Utilities/ITK/Utilities/openjpeg/pi.h
 create mode 100644 Utilities/ITK/Utilities/openjpeg/raw.c
 create mode 100644 Utilities/ITK/Utilities/openjpeg/raw.h
 create mode 100644 Utilities/ITK/Utilities/openjpeg/t1.c
 create mode 100644 Utilities/ITK/Utilities/openjpeg/t1.h
 create mode 100644 Utilities/ITK/Utilities/openjpeg/t2.c
 create mode 100644 Utilities/ITK/Utilities/openjpeg/t2.h
 create mode 100644 Utilities/ITK/Utilities/openjpeg/tcd.c
 create mode 100644 Utilities/ITK/Utilities/openjpeg/tcd.h
 create mode 100644 Utilities/ITK/Utilities/openjpeg/tgt.c
 create mode 100644 Utilities/ITK/Utilities/openjpeg/tgt.h
 create mode 100644 Utilities/ITK/Utilities/png/.NoDartCoverage
 create mode 100644 Utilities/ITK/Utilities/png/CMakeLists.txt
 create mode 100644 Utilities/ITK/Utilities/png/itk_png_mangle.h
 create mode 100644 Utilities/ITK/Utilities/png/png.c
 create mode 100644 Utilities/ITK/Utilities/png/png.h
 create mode 100644 Utilities/ITK/Utilities/png/pngDllConfig.h.in
 create mode 100644 Utilities/ITK/Utilities/png/pngasmrd.h
 create mode 100644 Utilities/ITK/Utilities/png/pngconf.h
 create mode 100644 Utilities/ITK/Utilities/png/pngerror.c
 create mode 100644 Utilities/ITK/Utilities/png/pnggccrd.c
 create mode 100644 Utilities/ITK/Utilities/png/pngget.c
 create mode 100644 Utilities/ITK/Utilities/png/pngmem.c
 create mode 100644 Utilities/ITK/Utilities/png/pngpread.c
 create mode 100644 Utilities/ITK/Utilities/png/pngread.c
 create mode 100644 Utilities/ITK/Utilities/png/pngrio.c
 create mode 100644 Utilities/ITK/Utilities/png/pngrtran.c
 create mode 100644 Utilities/ITK/Utilities/png/pngrutil.c
 create mode 100644 Utilities/ITK/Utilities/png/pngset.c
 create mode 100644 Utilities/ITK/Utilities/png/pngtest.c
 create mode 100644 Utilities/ITK/Utilities/png/pngtrans.c
 create mode 100644 Utilities/ITK/Utilities/png/pngvcrd.c
 create mode 100644 Utilities/ITK/Utilities/png/pngwio.c
 create mode 100644 Utilities/ITK/Utilities/png/pngwrite.c
 create mode 100644 Utilities/ITK/Utilities/png/pngwtran.c
 create mode 100644 Utilities/ITK/Utilities/png/pngwutil.c
 create mode 100644 Utilities/ITK/Utilities/tiff/.NoDartCoverage
 create mode 100644 Utilities/ITK/Utilities/tiff/CMakeLists.txt
 create mode 100644 Utilities/ITK/Utilities/tiff/COPYRIGHT
 create mode 100644 Utilities/ITK/Utilities/tiff/README
 create mode 100644 Utilities/ITK/Utilities/tiff/RELEASE-DATE
 create mode 100644 Utilities/ITK/Utilities/tiff/VERSION
 create mode 100644 Utilities/ITK/Utilities/tiff/dist/newalpha
 create mode 100644 Utilities/ITK/Utilities/tiff/dist/newversion
 create mode 100644 Utilities/ITK/Utilities/tiff/dist/tiff.alpha
 create mode 100644 Utilities/ITK/Utilities/tiff/dist/tiff.spec
 create mode 100644 Utilities/ITK/Utilities/tiff/dist/tiff.version
 create mode 100644 Utilities/ITK/Utilities/tiff/fax3sm_winnt.c
 create mode 100644 Utilities/ITK/Utilities/tiff/itk_tiff_mangle.h
 create mode 100644 Utilities/ITK/Utilities/tiff/itktiff.def
 create mode 100644 Utilities/ITK/Utilities/tiff/mkg3states.c
 create mode 100644 Utilities/ITK/Utilities/tiff/mkspans.c
 create mode 100644 Utilities/ITK/Utilities/tiff/mkversion.c
 create mode 100644 Utilities/ITK/Utilities/tiff/port.h
 create mode 100644 Utilities/ITK/Utilities/tiff/t4.h
 create mode 100644 Utilities/ITK/Utilities/tiff/tconf.h
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_acorn.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_apple.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_atari.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_aux.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_close.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_codec.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_color.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_compress.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_config.h.in
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_dir.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_dir.h
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_dirinfo.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_dirread.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_dirwrite.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_dumpmode.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_error.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_extension.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_fax3.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_fax3.h
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_fax3sm.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_flush.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_getimage.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_jpeg.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_luv.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_lzw.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_msdos.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_next.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_ojpeg.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_open.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_packbits.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_pixarlog.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_predict.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_predict.h
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_print.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_read.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_stream.cxx
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_strip.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_swab.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_thunder.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_tile.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_unix.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_version.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_vms.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_warning.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_win3.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_win32.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_write.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tif_zip.c
 create mode 100644 Utilities/ITK/Utilities/tiff/tiff.h
 create mode 100644 Utilities/ITK/Utilities/tiff/tiffDllConfig.h.in
 create mode 100644 Utilities/ITK/Utilities/tiff/tiffcomp.h
 create mode 100644 Utilities/ITK/Utilities/tiff/tiffconf.h
 create mode 100644 Utilities/ITK/Utilities/tiff/tiffio.h
 create mode 100644 Utilities/ITK/Utilities/tiff/tiffio.hxx
 create mode 100644 Utilities/ITK/Utilities/tiff/tiffiop.h
 create mode 100644 Utilities/ITK/Utilities/tiff/tiffvers.h
 create mode 100644 Utilities/ITK/Utilities/tiff/uvcode.h
 create mode 100644 Utilities/ITK/Utilities/zlib/.NoDartCoverage
 create mode 100644 Utilities/ITK/Utilities/zlib/CMakeLists.txt
 create mode 100644 Utilities/ITK/Utilities/zlib/adler32.c
 create mode 100644 Utilities/ITK/Utilities/zlib/compress.c
 create mode 100644 Utilities/ITK/Utilities/zlib/crc32.c
 create mode 100644 Utilities/ITK/Utilities/zlib/deflate.c
 create mode 100644 Utilities/ITK/Utilities/zlib/deflate.h
 create mode 100644 Utilities/ITK/Utilities/zlib/example.c
 create mode 100644 Utilities/ITK/Utilities/zlib/gzio.c
 create mode 100644 Utilities/ITK/Utilities/zlib/infblock.c
 create mode 100644 Utilities/ITK/Utilities/zlib/infblock.h
 create mode 100644 Utilities/ITK/Utilities/zlib/infcodes.c
 create mode 100644 Utilities/ITK/Utilities/zlib/infcodes.h
 create mode 100644 Utilities/ITK/Utilities/zlib/inffast.c
 create mode 100644 Utilities/ITK/Utilities/zlib/inffast.h
 create mode 100644 Utilities/ITK/Utilities/zlib/inffixed.h
 create mode 100644 Utilities/ITK/Utilities/zlib/inflate.c
 create mode 100644 Utilities/ITK/Utilities/zlib/inftrees.c
 create mode 100644 Utilities/ITK/Utilities/zlib/inftrees.h
 create mode 100644 Utilities/ITK/Utilities/zlib/infutil.c
 create mode 100644 Utilities/ITK/Utilities/zlib/infutil.h
 create mode 100644 Utilities/ITK/Utilities/zlib/itk_zlib_mangle.h
 create mode 100644 Utilities/ITK/Utilities/zlib/maketree.c
 create mode 100644 Utilities/ITK/Utilities/zlib/minigzip.c
 create mode 100644 Utilities/ITK/Utilities/zlib/trees.c
 create mode 100644 Utilities/ITK/Utilities/zlib/trees.h
 create mode 100644 Utilities/ITK/Utilities/zlib/uncompr.c
 create mode 100644 Utilities/ITK/Utilities/zlib/zconf.h
 create mode 100644 Utilities/ITK/Utilities/zlib/zlib.def
 create mode 100644 Utilities/ITK/Utilities/zlib/zlib.h
 create mode 100644 Utilities/ITK/Utilities/zlib/zlib.rc
 create mode 100644 Utilities/ITK/Utilities/zlib/zlibDllConfig.h.in
 create mode 100644 Utilities/ITK/Utilities/zlib/zutil.c
 create mode 100644 Utilities/ITK/Utilities/zlib/zutil.h

diff --git a/Utilities/ITK/Utilities/CMakeLists.txt b/Utilities/ITK/Utilities/CMakeLists.txt
new file mode 100644
index 0000000000..6390abdf87
--- /dev/null
+++ b/Utilities/ITK/Utilities/CMakeLists.txt
@@ -0,0 +1,72 @@
+# If any utility projects have their own testing targets,
+# tell Dart.cmake to generate the Experimental test target with the
+# project name.  This avoids the conflict in msdev between the
+# Experimental testing targets for main ITK and nested projects.
+SET(DART_EXPERIMENTAL_USE_PROJECT_NAME 1)
+
+# Build jpeg first because tiff needs it
+SUBDIRS(itkjpeg)
+
+#------------------------------------------------------------------------------
+# Build third-party utilities.
+ITK_THIRD_PARTY_SUBDIR(ZLIB zlib)
+ITK_THIRD_PARTY_SUBDIR(PNG  png)
+ITK_THIRD_PARTY_SUBDIR(TIFF tiff)
+SET(OPJ_PREFIX "itk")
+ITK_THIRD_PARTY_SUBDIR(OpenJPEG openjpeg)
+#------------------------------------------------------------------------------
+# Other utilities libraries
+SUBDIRS(MetaIO)
+SUBDIRS(NrrdIO)
+SUBDIRS(expat)
+SUBDIRS(gdcm)
+SUBDIRS(nifti)
+
+#------------------------------------------------------------------------------
+# Create the DICOMParse library for ITK
+SET(DICOMPARSER_NAMESPACE itkdicomparser)
+SET(DICOMPARSER_LIBRARY ITKDICOMParser)
+SET(DICOMPARSER_STANDALONE 0)
+SUBDIRS(DICOMParser)
+
+IF(ITK_DISABLE_CXX_TESTING)
+  SET(BUILD_TESTING OFF)
+ENDIF(ITK_DISABLE_CXX_TESTING)
+
+#------------------------------------------------------------------------------
+# Configure vxl/vnl as needed
+IF(NOT ITK_USE_SYSTEM_VXL)
+  SUBDIRS(vxl)
+ENDIF(NOT ITK_USE_SYSTEM_VXL)
+
+#------------------------------------------------------------------------------
+# Build testing as needed
+IF (BUILD_TESTING)
+  SUBDIRS(Dart)
+ENDIF (BUILD_TESTING)
+
+#-----------------------------------------------------------------------------
+# Create the kwsys library for ITK.
+SET(KWSYS_NAMESPACE itksys)
+SET(KWSYS_USE_SystemTools 1)
+SET(KWSYS_USE_RegularExpression 1)
+SET(KWSYS_USE_Directory 1)
+SET(KWSYS_USE_Base64 1)
+SET(KWSYS_USE_FundamentalType 1)
+SET(KWSYS_USE_CommandLineArguments 1)
+SET(KWSYS_HEADER_ROOT ${ITK_BINARY_DIR}/Utilities)
+SET(KWSYS_LIBRARY_INSTALL_DIR /lib/InsightToolkit)
+SET(KWSYS_HEADER_INSTALL_DIR /include/InsightToolkit/Utilities)
+SUBDIRS(kwsys)
+
+#-----------------------------------------------------------------------------
+# Build CableSwig if necessary.
+IF(ITK_BUILD_CABLESWIG)
+  SUBDIRS(CableSwig)
+ENDIF(ITK_BUILD_CABLESWIG)
+
+
+#-----------------------------------------------------------------------------
+# Install the UseITK.cmake file configured from the top-level.
+INSTALL_FILES(/lib/InsightToolkit ".cmake" "ITKConfig")
+
diff --git a/Utilities/ITK/Utilities/openjpeg/.NoDartCoverage b/Utilities/ITK/Utilities/openjpeg/.NoDartCoverage
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/Utilities/ITK/Utilities/openjpeg/CMakeLists.txt b/Utilities/ITK/Utilities/openjpeg/CMakeLists.txt
new file mode 100644
index 0000000000..d1a6b1ea47
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/CMakeLists.txt
@@ -0,0 +1,42 @@
+PROJECT(ITKOpenJPEG C)
+INCLUDE_REGULAR_EXPRESSION("^.*$")
+# Defines the source code for the library
+SET(OpenJPEG_SRCS
+  bio.c
+  cio.c
+  dwt.c
+  event.c
+  image.c
+  j2k.c
+  j2k_lib.c
+  jp2.c
+  jpt.c
+  mct.c
+  mqc.c
+  openjpeg.c
+  pi.c
+  raw.c
+  t1.c
+  t2.c
+  tcd.c
+  tgt.c
+)
+
+CONFIGURE_FILE(${ITKOpenJPEG_SOURCE_DIR}/.NoDartCoverage
+               ${ITKOpenJPEG_BINARY_DIR}/.NoDartCoverage)
+
+# Pass proper definition to preprocessor to generate shared lib
+IF (WIN32)
+  IF (BUILD_SHARED_LIBS)
+    ADD_DEFINITIONS(-DOPJ_EXPORTS)
+  ELSE (BUILD_SHARED_LIBS)
+    ADD_DEFINITIONS(-DOPJ_STATIC)
+  ENDIF (BUILD_SHARED_LIBS)
+ENDIF (WIN32)
+
+# Create the library
+ADD_LIBRARY(${OPJ_PREFIX}openjpeg ${OpenJPEG_SRCS})
+
+# Install library
+INSTALL_TARGETS(/lib/InsightToolkit ${OPJ_PREFIX}openjpeg)
+
diff --git a/Utilities/ITK/Utilities/openjpeg/README.ITK.txt b/Utilities/ITK/Utilities/openjpeg/README.ITK.txt
new file mode 100644
index 0000000000..455174163a
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/README.ITK.txt
@@ -0,0 +1,31 @@
+This directory contains a subset of the OpenJPEG project (http://www.openjpeg.org/)
+The OpenJPEG library is an open-source JPEG 2000 codec written in C language. It
+has been developed in order to promote the use of JPEG 2000, the new still-image
+compression standard from the Joint Photographic Experts Group (JPEG). In
+addition to the basic codec, various other features are under development, among
+them the  JP2 and MJ2 (Motion JPEG 2000) file formats, an indexing tool useful
+for the JPIP  protocol, JPWL-tools for error-resilience, a Java-viewer for
+j2k-images, ...
+
+The library is developed by the Communications and Remote Sensing Lab  (TELE),
+in the Universit� Catholique de Louvain (UCL).
+
+The OpenJPEG library is released under the BSD license (see BSDlicense.txt for
+details). Or online at:
+http://www.tele.ucl.ac.be/PROJECTS/OPENJPEG/BSDlicense.txt
+
+We only include enough of distribution to build libopenjpeg. For instance we do not
+include the codec subdirs.
+Furthermore, the standard OpenJPEG build process is replaced with a CMake build
+process.
+
+We'd like to thank the OpenJPEG project for releasing an open source
+implementation of the JPEG2000 codec. In particular, thanks to Antonin Descampe
+for fixing the 'well known' 16bits j2k issue.
+
+Modifications
+-------------
+
+- modification were made so that compilation with gcc -Wall flags passes without warnings
+- remove all explicit tabs and replace by proper amount of spaces (2)
+- remove all Makefile, *.dsp files...
diff --git a/Utilities/ITK/Utilities/openjpeg/bio.c b/Utilities/ITK/Utilities/openjpeg/bio.c
new file mode 100644
index 0000000000..3dfd7cf7ac
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/bio.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opj_includes.h"
+
+/** @defgroup BIO BIO - Individual bit input-output stream */
+/*@{*/
+
+/** @name Local static functions */
+/*@{*/
+
+/**
+Write a bit
+@param bio BIO handle
+@param b Bit to write (0 or 1)
+*/
+static void bio_putbit(opj_bio_t *bio, int b);
+/**
+Read a bit
+@param bio BIO handle
+@return Returns the read bit
+*/
+static int bio_getbit(opj_bio_t *bio);
+/**
+Write a byte
+@param bio BIO handle
+@return Returns 0 if successful, returns 1 otherwise
+*/
+static int bio_byteout(opj_bio_t *bio);
+/**
+Read a byte
+@param bio BIO handle
+@return Returns 0 if successful, returns 1 otherwise
+*/
+static int bio_bytein(opj_bio_t *bio);
+
+/*@}*/
+
+/*@}*/
+
+/* 
+==========================================================
+   local functions
+==========================================================
+*/
+
+static int bio_byteout(opj_bio_t *bio) {
+  bio->buf = (bio->buf << 8) & 0xffff;
+  bio->ct = bio->buf == 0xff00 ? 7 : 8;
+  if (bio->bp >= bio->end) {
+    return 1;
+  }
+  *bio->bp++ = bio->buf >> 8;
+  return 0;
+}
+
+static int bio_bytein(opj_bio_t *bio) {
+  bio->buf = (bio->buf << 8) & 0xffff;
+  bio->ct = bio->buf == 0xff00 ? 7 : 8;
+  if (bio->bp >= bio->end) {
+    return 1;
+  }
+  bio->buf |= *bio->bp++;
+  return 0;
+}
+
+static void bio_putbit(opj_bio_t *bio, int b) {
+  if (bio->ct == 0) {
+    bio_byteout(bio);
+  }
+  bio->ct--;
+  bio->buf |= b << bio->ct;
+}
+
+static int bio_getbit(opj_bio_t *bio) {
+  if (bio->ct == 0) {
+    bio_bytein(bio);
+  }
+  bio->ct--;
+  return (bio->buf >> bio->ct) & 1;
+}
+
+/* 
+==========================================================
+   Bit Input/Output interface
+==========================================================
+*/
+
+opj_bio_t* bio_create() {
+  opj_bio_t *bio = (opj_bio_t*)opj_malloc(sizeof(opj_bio_t));
+  return bio;
+}
+
+void bio_destroy(opj_bio_t *bio) {
+  if(bio) {
+    opj_free(bio);
+  }
+}
+
+int bio_numbytes(opj_bio_t *bio) {
+  return (bio->bp - bio->start);
+}
+
+void bio_init_enc(opj_bio_t *bio, unsigned char *bp, int len) {
+  bio->start = bp;
+  bio->end = bp + len;
+  bio->bp = bp;
+  bio->buf = 0;
+  bio->ct = 8;
+}
+
+void bio_init_dec(opj_bio_t *bio, unsigned char *bp, int len) {
+  bio->start = bp;
+  bio->end = bp + len;
+  bio->bp = bp;
+  bio->buf = 0;
+  bio->ct = 0;
+}
+
+void bio_write(opj_bio_t *bio, int v, int n) {
+  int i;
+  for (i = n - 1; i >= 0; i--) {
+    bio_putbit(bio, (v >> i) & 1);
+  }
+}
+
+int bio_read(opj_bio_t *bio, int n) {
+  int i, v;
+  v = 0;
+  for (i = n - 1; i >= 0; i--) {
+    v += bio_getbit(bio) << i;
+  }
+  return v;
+}
+
+int bio_flush(opj_bio_t *bio) {
+  bio->ct = 0;
+  if (bio_byteout(bio)) {
+    return 1;
+  }
+  if (bio->ct == 7) {
+    bio->ct = 0;
+    if (bio_byteout(bio)) {
+      return 1;
+    }
+  }
+  return 0;
+}
+
+int bio_inalign(opj_bio_t *bio) {
+  bio->ct = 0;
+  if ((bio->buf & 0xff) == 0xff) {
+    if (bio_bytein(bio)) {
+      return 1;
+    }
+    bio->ct = 0;
+  }
+  return 0;
+}
diff --git a/Utilities/ITK/Utilities/openjpeg/bio.h b/Utilities/ITK/Utilities/openjpeg/bio.h
new file mode 100644
index 0000000000..e64bf06234
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/bio.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BIO_H
+#define __BIO_H
+/** 
+@file bio.h
+@brief Implementation of an individual bit input-output (BIO)
+
+The functions in BIO.C have for goal to realize an individual bit input - output.
+*/
+
+/** @defgroup BIO BIO - Individual bit input-output stream */
+/*@{*/
+
+/**
+Individual bit input-output stream (BIO)
+*/
+typedef struct opj_bio {
+  /** pointer to the start of the buffer */
+  unsigned char *start;
+  /** pointer to the end of the buffer */
+  unsigned char *end;
+  /** pointer to the present position in the buffer */
+  unsigned char *bp;
+  /** temporary place where each byte is read or written */
+  unsigned int buf;
+  /** coder : number of bits free to write. decoder : number of bits read */
+  int ct;
+} opj_bio_t;
+
+/** @name Exported functions */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+/**
+Create a new BIO handle 
+@return Returns a new BIO handle if successful, returns NULL otherwise
+*/
+opj_bio_t* bio_create();
+/**
+Destroy a previously created BIO handle
+@param bio BIO handle to destroy
+*/
+void bio_destroy(opj_bio_t *bio);
+/**
+Number of bytes written.
+@param bio BIO handle
+@return Returns the number of bytes written
+*/
+int bio_numbytes(opj_bio_t *bio);
+/**
+Init encoder
+@param bio BIO handle
+@param bp Output buffer
+@param len Output buffer length 
+*/
+void bio_init_enc(opj_bio_t *bio, unsigned char *bp, int len);
+/**
+Init decoder
+@param bio BIO handle
+@param bp Input buffer
+@param len Input buffer length 
+*/
+void bio_init_dec(opj_bio_t *bio, unsigned char *bp, int len);
+/**
+Write bits
+@param bio BIO handle
+@param v Value of bits
+@param n Number of bits to write
+*/
+void bio_write(opj_bio_t *bio, int v, int n);
+/**
+Read bits
+@param bio BIO handle
+@param n Number of bits to read 
+@return Returns the corresponding read number
+*/
+int bio_read(opj_bio_t *bio, int n);
+/**
+Flush bits
+@param bio BIO handle
+@return Returns 1 if successful, returns 0 otherwise
+*/
+int bio_flush(opj_bio_t *bio);
+/**
+Passes the ending bits (coming from flushing)
+@param bio BIO handle
+@return Returns 1 if successful, returns 0 otherwise
+*/
+int bio_inalign(opj_bio_t *bio);
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __BIO_H */
+
diff --git a/Utilities/ITK/Utilities/openjpeg/cio.c b/Utilities/ITK/Utilities/openjpeg/cio.c
new file mode 100644
index 0000000000..146c5d3d46
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/cio.c
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opj_includes.h"
+
+/* ----------------------------------------------------------------------- */
+
+opj_cio_t* OPJ_CALLCONV opj_cio_open(opj_common_ptr cinfo, unsigned char *buffer, int length) {
+  opj_cp_t *cp = NULL;
+  opj_cio_t *cio = (opj_cio_t*)opj_malloc(sizeof(opj_cio_t));
+  if(!cio) return NULL;
+  cio->cinfo = cinfo;
+  if(buffer && length) {
+    /* wrap a user buffer containing the encoded image */
+    cio->openmode = OPJ_STREAM_READ;
+    cio->buffer = buffer;
+    cio->length = length;
+  }
+  else if(!buffer && !length && cinfo) {
+    /* allocate a buffer for the encoded image */
+    cio->openmode = OPJ_STREAM_WRITE;
+    switch(cinfo->codec_format) {
+      case CODEC_J2K:
+        cp = ((opj_j2k_t*)cinfo->j2k_handle)->cp;
+        break;
+      case CODEC_JP2:
+        cp = ((opj_jp2_t*)cinfo->jp2_handle)->j2k->cp;
+        break;
+      default:
+        opj_free(cio);
+        return NULL;
+    }
+    cio->length = cp->tdx * cp->tdy * cp->tw * cp->th * 4;
+    cio->buffer = (unsigned char *)opj_malloc(cio->length);
+    if(!cio->buffer) {
+      opj_free(cio);
+      return NULL;
+    }
+  }
+  else {
+    opj_free(cio);
+    return NULL;
+  }
+
+  /* Initialize byte IO */
+  cio->start = cio->buffer;
+  cio->end = cio->buffer + cio->length;
+  cio->bp = cio->buffer;
+
+  return cio;
+}
+
+void OPJ_CALLCONV opj_cio_close(opj_cio_t *cio) {
+  if(cio) {
+    if(cio->openmode == OPJ_STREAM_WRITE) {
+      /* destroy the allocated buffer */
+      opj_free(cio->buffer);
+    }
+    /* destroy the cio */
+    opj_free(cio);
+  }
+}
+
+
+/* ----------------------------------------------------------------------- */
+
+/*
+ * Get position in byte stream.
+ */
+int OPJ_CALLCONV cio_tell(opj_cio_t *cio) {
+  return cio->bp - cio->start;
+}
+
+/*
+ * Set position in byte stream.
+ *
+ * pos : position, in number of bytes, from the beginning of the stream
+ */
+void OPJ_CALLCONV cio_seek(opj_cio_t *cio, int pos) {
+  cio->bp = cio->start + pos;
+}
+
+/*
+ * Number of bytes left before the end of the stream.
+ */
+int cio_numbytesleft(opj_cio_t *cio) {
+  return cio->end - cio->bp;
+}
+
+/*
+ * Get pointer to the current position in the stream.
+ */
+unsigned char *cio_getbp(opj_cio_t *cio) {
+  return cio->bp;
+}
+
+/*
+ * Write a byte.
+ */
+bool cio_byteout(opj_cio_t *cio, unsigned char v) {
+  if (cio->bp >= cio->end) {
+    opj_event_msg(cio->cinfo, EVT_ERROR, "write error\n");
+    return false;
+  }
+  *cio->bp++ = v;
+  return true;
+}
+
+/*
+ * Read a byte.
+ */
+unsigned char cio_bytein(opj_cio_t *cio) {
+  if (cio->bp >= cio->end) {
+    opj_event_msg(cio->cinfo, EVT_ERROR, "read error\n");
+    return 0;
+  }
+  return *cio->bp++;
+}
+
+/*
+ * Write some bytes.
+ *
+ * v : value to write
+ * n : number of bytes to write
+ */
+unsigned int cio_write(opj_cio_t *cio, unsigned int v, int n) {
+  int i;
+  for (i = n - 1; i >= 0; i--) {
+    if( !cio_byteout(cio, (unsigned char) ((v >> (i << 3)) & 0xff)) )
+      return 0;
+  }
+  return n;
+}
+
+/*
+ * Read some bytes.
+ *
+ * n : number of bytes to read
+ *
+ * return : value of the n bytes read
+ */
+unsigned int cio_read(opj_cio_t *cio, int n) {
+  int i;
+  unsigned int v;
+  v = 0;
+  for (i = n - 1; i >= 0; i--) {
+    v += cio_bytein(cio) << (i << 3);
+  }
+  return v;
+}
+
+/* 
+ * Skip some bytes.
+ *
+ * n : number of bytes to skip
+ */
+void cio_skip(opj_cio_t *cio, int n) {
+  cio->bp += n;
+}
+
+
+
diff --git a/Utilities/ITK/Utilities/openjpeg/cio.h b/Utilities/ITK/Utilities/openjpeg/cio.h
new file mode 100644
index 0000000000..0f4048b74c
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/cio.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __CIO_H
+#define __CIO_H
+/**
+@file cio.h
+@brief Implementation of a byte input-output process (CIO)
+
+The functions in CIO.C have for goal to realize a byte input / output process.
+*/
+
+/** @defgroup CIO CIO - byte input-output stream */
+/*@{*/
+
+/** @name Exported functions (see also openjpeg.h) */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+/**
+Number of bytes left before the end of the stream
+@param cio CIO handle
+@return Returns the number of bytes before the end of the stream
+*/
+int cio_numbytesleft(opj_cio_t *cio);
+/**
+Get pointer to the current position in the stream
+@param cio CIO handle
+@return Returns a pointer to the current position
+*/
+unsigned char *cio_getbp(opj_cio_t *cio);
+/**
+Write some bytes
+@param cio CIO handle
+@param v Value to write
+@param n Number of bytes to write
+@return Returns the number of bytes written or 0 if an error occured
+*/
+unsigned int cio_write(opj_cio_t *cio, unsigned int v, int n);
+/**
+Read some bytes
+@param cio CIO handle
+@param n Number of bytes to read
+@return Returns the value of the n bytes read
+*/
+unsigned int cio_read(opj_cio_t *cio, int n);
+/**
+Skip some bytes
+@param cio CIO handle
+@param n Number of bytes to skip
+*/
+void cio_skip(opj_cio_t *cio, int n);
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __CIO_H */
+
diff --git a/Utilities/ITK/Utilities/openjpeg/dwt.c b/Utilities/ITK/Utilities/openjpeg/dwt.c
new file mode 100644
index 0000000000..53c4a5e3f0
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/dwt.c
@@ -0,0 +1,610 @@
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ *  NOTE:
+ *  This is a modified version of the openjpeg dwt.c file.
+ *  Average speed improvement compared to the original file (measured on
+ *  my own machine, a P4 running at 3.0 GHz):
+ *  5x3 wavelets about 2 times faster
+ *  9x7 wavelets about 3 times faster
+ *  for both, encoding and decoding.
+ *
+ *  The better performance is caused by doing the 1-dimensional DWT
+ *  within a temporary buffer where the data can be accessed sequential
+ *  for both directions, horizontal and vertical. The 2d vertical DWT was
+ *  the major bottleneck in the former version.
+ *
+ *  I have also removed the "Add Patrick" part because it is not longer
+ *  needed.  
+ *
+ *  6/6/2005
+ *  -Ive (aka Reiner Wahler)
+ *  mail: ive@lilysoft.com
+ */
+
+#include "opj_includes.h"
+
+/** @defgroup DWT DWT - Implementation of a discrete wavelet transform */
+/*@{*/
+
+/** @name Local static functions */
+/*@{*/
+
+/**
+Forward lazy transform (horizontal)
+*/
+static void dwt_deinterleave_h(int *a, int *b, int dn, int sn, int cas);
+/**
+Forward lazy transform (vertical)
+*/
+static void dwt_deinterleave_v(int *a, int *b, int dn, int sn, int x, int cas);
+/**
+Inverse lazy transform (horizontal)
+*/
+static void dwt_interleave_h(int *a, int *b, int dn, int sn, int cas);
+/**
+Inverse lazy transform (vertical)
+*/
+static void dwt_interleave_v(int *a, int *b, int dn, int sn, int x, int cas);
+/**
+Forward 5-3 wavelet tranform in 1-D
+*/
+static void dwt_encode_1(int *a, int dn, int sn, int cas);
+/**
+Inverse 5-3 wavelet tranform in 1-D
+*/
+static void dwt_decode_1(int *a, int dn, int sn, int cas);
+/**
+Forward 9-7 wavelet transform in 1-D
+*/
+static void dwt_encode_1_real(int *a, int dn, int sn, int cas);
+/**
+Inverse 9-7 wavelet transform in 1-D
+*/
+static void dwt_decode_1_real(int *a, int dn, int sn, int cas);
+/**
+FIXME : comment ???
+*/
+static void dwt_encode_stepsize(int stepsize, int numbps, opj_stepsize_t *bandno_stepsize);
+
+/*@}*/
+
+/*@}*/
+
+#define S(i) a[(i)*2]
+#define D(i) a[(1+(i)*2)]
+#define S_(i) ((i)<0?S(0):((i)>=sn?S(sn-1):S(i)))
+#define D_(i) ((i)<0?D(0):((i)>=dn?D(dn-1):D(i)))
+/* new */
+#define SS_(i) ((i)<0?S(0):((i)>=dn?S(dn-1):S(i)))
+#define DD_(i) ((i)<0?D(0):((i)>=sn?D(sn-1):D(i)))
+
+/* <summary>                                                              */
+/* This table contains the norms of the 5-3 wavelets for different bands. */
+/* </summary>                                                             */
+static const double dwt_norms[4][10] = {
+  {1.000, 1.500, 2.750, 5.375, 10.68, 21.34, 42.67, 85.33, 170.7, 341.3},
+  {1.038, 1.592, 2.919, 5.703, 11.33, 22.64, 45.25, 90.48, 180.9},
+  {1.038, 1.592, 2.919, 5.703, 11.33, 22.64, 45.25, 90.48, 180.9},
+  {.7186, .9218, 1.586, 3.043, 6.019, 12.01, 24.00, 47.97, 95.93}
+};
+
+/* <summary>                                                              */
+/* This table contains the norms of the 9-7 wavelets for different bands. */
+/* </summary>                                                             */
+static const double dwt_norms_real[4][10] = {
+  {1.000, 1.965, 4.177, 8.403, 16.90, 33.84, 67.69, 135.3, 270.6, 540.9},
+  {2.022, 3.989, 8.355, 17.04, 34.27, 68.63, 137.3, 274.6, 549.0},
+  {2.022, 3.989, 8.355, 17.04, 34.27, 68.63, 137.3, 274.6, 549.0},
+  {2.080, 3.865, 8.307, 17.18, 34.71, 69.59, 139.3, 278.6, 557.2}
+};
+
+/* 
+==========================================================
+   local functions
+==========================================================
+*/
+
+/* <summary>                       */
+/* Forward lazy transform (horizontal).  */
+/* </summary>                            */ 
+static void dwt_deinterleave_h(int *a, int *b, int dn, int sn, int cas) {
+  int i;
+    for (i=0; i<sn; i++) b[i]=a[2*i+cas];
+    for (i=0; i<dn; i++) b[sn+i]=a[(2*i+1-cas)];
+}
+
+/* <summary>                             */  
+/* Forward lazy transform (vertical).    */
+/* </summary>                            */ 
+static void dwt_deinterleave_v(int *a, int *b, int dn, int sn, int x, int cas) {
+    int i;
+    for (i=0; i<sn; i++) b[i*x]=a[2*i+cas];
+    for (i=0; i<dn; i++) b[(sn+i)*x]=a[(2*i+1-cas)];
+}
+
+/* <summary>                             */
+/* Inverse lazy transform (horizontal).  */
+/* </summary>                            */
+static void dwt_interleave_h(int *a, int *b, int dn, int sn, int cas) {
+    int i;
+    int *ai = NULL;
+    int *bi = NULL;
+    ai = a;
+    bi = b + cas;
+    for (i = 0; i < sn; i++) {
+      *bi = *ai;  
+    bi += 2;  
+    ai++;
+    }
+    ai = a + sn;
+    bi = b + 1 - cas;
+    for (i = 0; i < dn; i++) {
+      *bi = *ai;
+    bi += 2;
+    ai++;
+    }
+}
+
+/* <summary>                             */  
+/* Inverse lazy transform (vertical).    */
+/* </summary>                            */ 
+static void dwt_interleave_v(int *a, int *b, int dn, int sn, int x, int cas) {
+    int i;
+    int *ai = NULL;
+    int *bi = NULL;
+    ai = a;
+    bi = b + cas;
+    for (i = 0; i < sn; i++) {
+      *bi = *ai;
+    bi += 2;
+    ai += x;
+    }
+    ai = a + (sn * x);
+    bi = b + 1 - cas;
+    for (i = 0; i < dn; i++) {
+      *bi = *ai;
+    bi += 2;  
+    ai += x;
+    }
+}
+
+
+/* <summary>                            */
+/* Forward 5-3 wavelet tranform in 1-D. */
+/* </summary>                           */
+static void dwt_encode_1(int *a, int dn, int sn, int cas) {
+  int i;
+  
+  if (!cas) {
+    if ((dn > 0) || (sn > 1)) {  /* NEW :  CASE ONE ELEMENT */
+      for (i = 0; i < dn; i++) D(i) -= (S_(i) + S_(i + 1)) >> 1;
+      for (i = 0; i < sn; i++) S(i) += (D_(i - 1) + D_(i) + 2) >> 2;
+    }
+  } else {
+    if (!sn && dn == 1)        /* NEW :  CASE ONE ELEMENT */
+      S(0) *= 2;
+    else {
+      for (i = 0; i < dn; i++) S(i) -= (DD_(i) + DD_(i - 1)) >> 1;
+      for (i = 0; i < sn; i++) D(i) += (SS_(i) + SS_(i + 1) + 2) >> 2;
+    }
+  }
+}
+
+/* <summary>                            */
+/* Inverse 5-3 wavelet tranform in 1-D. */
+/* </summary>                           */ 
+static void dwt_decode_1(int *a, int dn, int sn, int cas) {
+  int i;
+  
+  if (!cas) {
+    if ((dn > 0) || (sn > 1)) { /* NEW :  CASE ONE ELEMENT */
+      for (i = 0; i < sn; i++) S(i) -= (D_(i - 1) + D_(i) + 2) >> 2;
+      for (i = 0; i < dn; i++) D(i) += (S_(i) + S_(i + 1)) >> 1;
+    }
+  } else {
+    if (!sn  && dn == 1)          /* NEW :  CASE ONE ELEMENT */
+      S(0) /= 2;
+    else {
+      for (i = 0; i < sn; i++) D(i) -= (SS_(i) + SS_(i + 1) + 2) >> 2;
+      for (i = 0; i < dn; i++) S(i) += (DD_(i) + DD_(i - 1)) >> 1;
+    }
+  }
+}
+
+/* <summary>                             */
+/* Forward 9-7 wavelet transform in 1-D. */
+/* </summary>                            */
+static void dwt_encode_1_real(int *a, int dn, int sn, int cas) {
+  int i;
+  if (!cas) {
+    if ((dn > 0) || (sn > 1)) {  /* NEW :  CASE ONE ELEMENT */
+      for (i = 0; i < dn; i++)
+        D(i) -= fix_mul(S_(i) + S_(i + 1), 12993);
+      for (i = 0; i < sn; i++)
+        S(i) -= fix_mul(D_(i - 1) + D_(i), 434);
+      for (i = 0; i < dn; i++)
+        D(i) += fix_mul(S_(i) + S_(i + 1), 7233);
+      for (i = 0; i < sn; i++)
+        S(i) += fix_mul(D_(i - 1) + D_(i), 3633);
+      for (i = 0; i < dn; i++)
+        D(i) = fix_mul(D(i), 5038);  /*5038 */
+      for (i = 0; i < sn; i++)
+        S(i) = fix_mul(S(i), 6659);  /*6660 */
+    }
+  } else {
+    if ((sn > 0) || (dn > 1)) {  /* NEW :  CASE ONE ELEMENT */
+      for (i = 0; i < dn; i++)
+        S(i) -= fix_mul(DD_(i) + DD_(i - 1), 12993);
+      for (i = 0; i < sn; i++)
+        D(i) -= fix_mul(SS_(i) + SS_(i + 1), 434);
+      for (i = 0; i < dn; i++)
+        S(i) += fix_mul(DD_(i) + DD_(i - 1), 7233);
+      for (i = 0; i < sn; i++)
+        D(i) += fix_mul(SS_(i) + SS_(i + 1), 3633);
+      for (i = 0; i < dn; i++)
+        S(i) = fix_mul(S(i), 5038);  /*5038 */
+      for (i = 0; i < sn; i++)
+        D(i) = fix_mul(D(i), 6659);  /*6660 */
+    }
+  }
+}
+
+/* <summary>                             */
+/* Inverse 9-7 wavelet transform in 1-D. */
+/* </summary>                            */
+static void dwt_decode_1_real(int *a, int dn, int sn, int cas) {
+  int i;
+  if (!cas) {
+    if ((dn > 0) || (sn > 1)) {  /* NEW :  CASE ONE ELEMENT */
+      for (i = 0; i < sn; i++)
+        S(i) = fix_mul(S(i), 10078);  /* 10076 */
+      for (i = 0; i < dn; i++)
+        D(i) = fix_mul(D(i), 13318);  /* 13320 */
+      for (i = 0; i < sn; i++)
+        S(i) -= fix_mul(D_(i - 1) + D_(i), 3633);
+      for (i = 0; i < dn; i++)
+        D(i) -= fix_mul(S_(i) + S_(i + 1), 7233);
+      for (i = 0; i < sn; i++)
+        S(i) += fix_mul(D_(i - 1) + D_(i), 434);
+      for (i = 0; i < dn; i++)
+        D(i) += fix_mul(S_(i) + S_(i + 1), 12994);  /* 12993 */
+    }
+  } else {
+    if ((sn > 0) || (dn > 1)) {  /* NEW :  CASE ONE ELEMENT */
+      for (i = 0; i < sn; i++)
+        D(i) = fix_mul(D(i), 10078);  /* 10076 */
+      for (i = 0; i < dn; i++)
+        S(i) = fix_mul(S(i), 13318);  /* 13320 */
+      for (i = 0; i < sn; i++)
+        D(i) -= fix_mul(SS_(i) + SS_(i + 1), 3633);
+      for (i = 0; i < dn; i++)
+        S(i) -= fix_mul(DD_(i) + DD_(i - 1), 7233);
+      for (i = 0; i < sn; i++)
+        D(i) += fix_mul(SS_(i) + SS_(i + 1), 434);
+      for (i = 0; i < dn; i++)
+        S(i) += fix_mul(DD_(i) + DD_(i - 1), 12994);  /* 12993 */
+    }
+  }
+}
+
+static void dwt_encode_stepsize(int stepsize, int numbps, opj_stepsize_t *bandno_stepsize) {
+  int p, n;
+  p = int_floorlog2(stepsize) - 13;
+  n = 11 - int_floorlog2(stepsize);
+  bandno_stepsize->mant = (n < 0 ? stepsize >> -n : stepsize << n) & 0x7ff;
+  bandno_stepsize->expn = numbps - p;
+}
+
+/* 
+==========================================================
+   DWT interface
+==========================================================
+*/
+
+/* <summary>                            */
+/* Forward 5-3 wavelet tranform in 2-D. */
+/* </summary>                           */
+void dwt_encode(opj_tcd_tilecomp_t * tilec) {
+  int i, j, k;
+  int *a = NULL;
+  int *aj = NULL;
+  int *bj = NULL;
+  int w, l;
+  
+  w = tilec->x1-tilec->x0;
+  l = tilec->numresolutions-1;
+  a = tilec->data;
+  
+  for (i = 0; i < l; i++) {
+    int rw;      /* width of the resolution level computed                                                           */
+    int rh;      /* heigth of the resolution level computed                                                          */
+    int rw1;    /* width of the resolution level once lower than computed one                                       */
+    int rh1;    /* height of the resolution level once lower than computed one                                      */
+    int cas_col;  /* 0 = non inversion on horizontal filtering 1 = inversion between low-pass and high-pass filtering */
+    int cas_row;  /* 0 = non inversion on vertical filtering 1 = inversion between low-pass and high-pass filtering   */
+    int dn, sn;
+    
+    rw = tilec->resolutions[l - i].x1 - tilec->resolutions[l - i].x0;
+    rh = tilec->resolutions[l - i].y1 - tilec->resolutions[l - i].y0;
+    rw1= tilec->resolutions[l - i - 1].x1 - tilec->resolutions[l - i - 1].x0;
+    rh1= tilec->resolutions[l - i - 1].y1 - tilec->resolutions[l - i - 1].y0;
+    
+    cas_row = tilec->resolutions[l - i].x0 % 2;
+    cas_col = tilec->resolutions[l - i].y0 % 2;
+        
+    sn = rh1;
+    dn = rh - rh1;
+    bj = (int*)opj_malloc(rh * sizeof(int));
+    for (j = 0; j < rw; j++) {
+      aj = a + j;
+      for (k = 0; k < rh; k++)  bj[k] = aj[k*w];
+      dwt_encode_1(bj, dn, sn, cas_col);
+      dwt_deinterleave_v(bj, aj, dn, sn, w, cas_col);
+    }
+    opj_free(bj);
+    
+    sn = rw1;
+    dn = rw - rw1;
+    bj = (int*)opj_malloc(rw * sizeof(int));
+    for (j = 0; j < rh; j++) {
+      aj = a + j * w;
+      for (k = 0; k < rw; k++)  bj[k] = aj[k];
+      dwt_encode_1(bj, dn, sn, cas_row);
+      dwt_deinterleave_h(bj, aj, dn, sn, cas_row);
+    }
+    opj_free(bj);
+  }
+}
+
+
+/* <summary>                            */
+/* Inverse 5-3 wavelet tranform in 2-D. */
+/* </summary>                           */
+void dwt_decode(opj_tcd_tilecomp_t * tilec, int stop) {
+  int i, j, k;
+  int *a = NULL;
+  int *aj = NULL;
+  int *bj = NULL;
+  int w, l;
+  
+  w = tilec->x1-tilec->x0;
+  l = tilec->numresolutions-1;
+  a = tilec->data;
+  
+  for (i = l - 1; i >= stop; i--) {
+    int rw;      /* width of the resolution level computed                                                           */
+    int rh;      /* heigth of the resolution level computed                                                          */
+    int rw1;    /* width of the resolution level once lower than computed one                                       */
+    int rh1;    /* height of the resolution level once lower than computed one                                      */
+    int cas_col;  /* 0 = non inversion on horizontal filtering 1 = inversion between low-pass and high-pass filtering */
+    int cas_row;  /* 0 = non inversion on vertical filtering 1 = inversion between low-pass and high-pass filtering   */
+    int dn, sn;
+    
+    rw = tilec->resolutions[l - i].x1 - tilec->resolutions[l - i].x0;
+    rh = tilec->resolutions[l - i].y1 - tilec->resolutions[l - i].y0;
+    rw1= tilec->resolutions[l - i - 1].x1 - tilec->resolutions[l - i - 1].x0;
+    rh1= tilec->resolutions[l - i - 1].y1 - tilec->resolutions[l - i - 1].y0;
+    
+    cas_row = tilec->resolutions[l - i].x0 % 2;
+    cas_col = tilec->resolutions[l - i].y0 % 2;
+    
+    sn = rw1;
+    dn = rw - rw1;
+    bj = (int*)opj_malloc(rw * sizeof(int));
+    for (j = 0; j < rh; j++) {
+      aj = a + j*w;
+      dwt_interleave_h(aj, bj, dn, sn, cas_row);
+      dwt_decode_1(bj, dn, sn, cas_row);
+      for (k = 0; k < rw; k++)  aj[k] = bj[k];
+    }
+    opj_free(bj);
+    
+    sn = rh1;
+    dn = rh - rh1;
+    bj = (int*)opj_malloc(rh * sizeof(int));
+    for (j = 0; j < rw; j++) {
+      aj = a + j;
+      dwt_interleave_v(aj, bj, dn, sn, w, cas_col);
+      dwt_decode_1(bj, dn, sn, cas_col);
+      for (k = 0; k < rh; k++)  aj[k * w] = bj[k];
+    }
+    opj_free(bj);
+  }
+}
+
+
+/* <summary>                          */
+/* Get gain of 5-3 wavelet transform. */
+/* </summary>                         */
+int dwt_getgain(int orient) {
+  if (orient == 0)
+    return 0;
+  if (orient == 1 || orient == 2)
+    return 1;
+  return 2;
+}
+
+/* <summary>                */
+/* Get norm of 5-3 wavelet. */
+/* </summary>               */
+double dwt_getnorm(int level, int orient) {
+  return dwt_norms[orient][level];
+}
+
+/* <summary>                             */
+/* Forward 9-7 wavelet transform in 2-D. */
+/* </summary>                            */
+
+void dwt_encode_real(opj_tcd_tilecomp_t * tilec) {
+  int i, j, k;
+  int *a = NULL;
+  int *aj = NULL;
+  int *bj = NULL;
+  int w, l;
+  
+  w = tilec->x1-tilec->x0;
+  l = tilec->numresolutions-1;
+  a = tilec->data;
+  
+  for (i = 0; i < l; i++) {
+    int rw;      /* width of the resolution level computed                                                     */
+    int rh;      /* heigth of the resolution level computed                                                    */
+    int rw1;    /* width of the resolution level once lower than computed one                                 */
+    int rh1;    /* height of the resolution level once lower than computed one                                */
+    int cas_col;  /* 0 = non inversion on horizontal filtering 1 = inversion between low-pass and high-pass filtering */
+    int cas_row;  /* 0 = non inversion on vertical filtering 1 = inversion between low-pass and high-pass filtering   */
+    int dn, sn;
+    
+    rw = tilec->resolutions[l - i].x1 - tilec->resolutions[l - i].x0;
+    rh = tilec->resolutions[l - i].y1 - tilec->resolutions[l - i].y0;
+    rw1= tilec->resolutions[l - i - 1].x1 - tilec->resolutions[l - i - 1].x0;
+    rh1= tilec->resolutions[l - i - 1].y1 - tilec->resolutions[l - i - 1].y0;
+    
+    cas_row = tilec->resolutions[l - i].x0 % 2;
+    cas_col = tilec->resolutions[l - i].y0 % 2;
+    
+    sn = rh1;
+    dn = rh - rh1;
+    bj = (int*)opj_malloc(rh * sizeof(int));
+    for (j = 0; j < rw; j++) {
+      aj = a + j;
+      for (k = 0; k < rh; k++)  bj[k] = aj[k*w];
+      dwt_encode_1_real(bj, dn, sn, cas_col);
+      dwt_deinterleave_v(bj, aj, dn, sn, w, cas_col);
+    }
+    opj_free(bj);
+    
+    sn = rw1;
+    dn = rw - rw1;
+    bj = (int*)opj_malloc(rw * sizeof(int));
+    for (j = 0; j < rh; j++) {
+      aj = a + j * w;
+      for (k = 0; k < rw; k++)  bj[k] = aj[k];
+      dwt_encode_1_real(bj, dn, sn, cas_row);
+      dwt_deinterleave_h(bj, aj, dn, sn, cas_row);
+    }
+    opj_free(bj);
+  }
+}
+
+
+/* <summary>                             */
+/* Inverse 9-7 wavelet transform in 2-D. */
+/* </summary>                            */
+void dwt_decode_real(opj_tcd_tilecomp_t * tilec, int stop) {
+  int i, j, k;
+  int *a = NULL;
+  int *aj = NULL;
+  int *bj = NULL;
+  int w, l;
+  
+  w = tilec->x1-tilec->x0;
+  l = tilec->numresolutions-1;
+  a = tilec->data;
+  
+  for (i = l-1; i >= stop; i--) {
+    int rw;      /* width of the resolution level computed                       */
+    int rh;      /* heigth of the resolution level computed                      */
+    int rw1;    /* width of the resolution level once lower than computed one   */
+    int rh1;    /* height of the resolution level once lower than computed one  */
+    int cas_col;  /* 0 = non inversion on horizontal filtering 1 = inversion between low-pass and high-pass filtering */
+    int cas_row;  /* 0 = non inversion on vertical filtering 1 = inversion between low-pass and high-pass filtering   */
+    int dn, sn;
+    
+    rw = tilec->resolutions[l - i].x1 - tilec->resolutions[l - i].x0;
+    rh = tilec->resolutions[l - i].y1 - tilec->resolutions[l - i].y0;
+    rw1= tilec->resolutions[l - i - 1].x1 - tilec->resolutions[l - i - 1].x0;
+    rh1= tilec->resolutions[l - i - 1].y1 - tilec->resolutions[l - i - 1].y0;
+    
+    cas_col = tilec->resolutions[l - i].x0 % 2; /* 0 = non inversion on horizontal filtering 1 = inversion between low-pass and high-pass filtering */
+    cas_row = tilec->resolutions[l - i].y0 % 2; /* 0 = non inversion on vertical filtering 1 = inversion between low-pass and high-pass filtering   */
+        
+    sn = rw1;
+    dn = rw-rw1;
+    bj = (int*)opj_malloc(rw * sizeof(int));
+    for (j = 0; j < rh; j++) {
+      aj = a + j * w;
+      dwt_interleave_h(aj, bj, dn, sn, cas_col);
+      dwt_decode_1_real(bj, dn, sn, cas_col);
+      for (k = 0; k < rw; k++)  aj[k] = bj[k];
+    }
+    opj_free(bj);
+    
+    sn = rh1;
+    dn = rh-rh1;
+    bj = (int*)opj_malloc(rh * sizeof(int));
+    for (j = 0; j < rw; j++) {
+      aj = a + j;
+      dwt_interleave_v(aj, bj, dn, sn, w, cas_row);
+      dwt_decode_1_real(bj, dn, sn, cas_row);
+      for (k = 0; k < rh; k++)  aj[k * w] = bj[k];
+    }
+    opj_free(bj);
+  }
+}
+
+
+/* <summary>                          */
+/* Get gain of 9-7 wavelet transform. */
+/* </summary>                         */
+int dwt_getgain_real(int orient) {
+  (void)orient;
+  return 0;
+}
+
+/* <summary>                */
+/* Get norm of 9-7 wavelet. */
+/* </summary>               */
+double dwt_getnorm_real(int level, int orient) {
+  return dwt_norms_real[orient][level];
+}
+
+void dwt_calc_explicit_stepsizes(opj_tccp_t * tccp, int prec) {
+  int numbands, bandno;
+  numbands = 3 * tccp->numresolutions - 2;
+  for (bandno = 0; bandno < numbands; bandno++) {
+    double stepsize;
+    int resno, level, orient, gain;
+
+    resno = (bandno == 0) ? 0 : ((bandno - 1) / 3 + 1);
+    orient = (bandno == 0) ? 0 : ((bandno - 1) % 3 + 1);
+    level = tccp->numresolutions - 1 - resno;
+    gain = (tccp->qmfbid == 0) ? 0 : ((orient == 0) ? 0 : (((orient == 1) || (orient == 2)) ? 1 : 2));
+    if (tccp->qntsty == J2K_CCP_QNTSTY_NOQNT) {
+      stepsize = 1.0;
+    } else {
+      double norm = dwt_norms_real[orient][level];
+      stepsize = (1 << (gain + 1)) / norm;
+    }
+    dwt_encode_stepsize((int) floor(stepsize * 8192.0), prec + gain, &tccp->stepsizes[bandno]);
+  }
+}
diff --git a/Utilities/ITK/Utilities/openjpeg/dwt.h b/Utilities/ITK/Utilities/openjpeg/dwt.h
new file mode 100644
index 0000000000..3ee99a37aa
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/dwt.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __DWT_H
+#define __DWT_H
+/**
+@file dwt.h
+@brief Implementation of a discrete wavelet transform (DWT)
+
+The functions in DWT.C have for goal to realize forward and inverse discret wavelet
+transform with filter 5-3 (reversible) and filter 9-7 (irreversible). The functions in
+DWT.C are used by some function in TCD.C.
+*/
+
+/** @defgroup DWT DWT - Implementation of a discrete wavelet transform */
+/*@{*/
+
+
+/** @name Exported functions */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+/**
+Forward 5-3 wavelet tranform in 2-D. 
+Apply a reversible DWT transform to a component of an image.
+@param tilec Tile component information (current tile)
+*/
+void dwt_encode(opj_tcd_tilecomp_t * tilec);
+/**
+Inverse 5-3 wavelet tranform in 2-D.
+Apply a reversible inverse DWT transform to a component of an image.
+@param tilec Tile component information (current tile)
+@param stop FIXME Number of decoded resolution levels ?
+*/
+void dwt_decode(opj_tcd_tilecomp_t * tilec, int stop);
+/**
+Get the gain of a subband for the reversible 5-3 DWT.
+@param orient Number that identifies the subband (0->LL, 1->HL, 2->LH, 3->HH)
+@return Returns 0 if orient = 0, returns 1 if orient = 1 or 2, returns 2 otherwise
+*/
+int dwt_getgain(int orient);
+/**
+Get the norm of a wavelet function of a subband at a specified level for the reversible 5-3 DWT.
+@param level Level of the wavelet function
+@param orient Band of the wavelet function
+@return Returns the norm of the wavelet function
+*/
+double dwt_getnorm(int level, int orient);
+/**
+Forward 9-7 wavelet transform in 2-D. 
+Apply an irreversible DWT transform to a component of an image.
+@param tilec Tile component information (current tile)
+*/
+void dwt_encode_real(opj_tcd_tilecomp_t * tilec);
+/**
+Inverse 9-7 wavelet transform in 2-D. 
+Apply an irreversible inverse DWT transform to a component of an image.
+@param tilec Tile component information (current tile)
+@param stop FIXME Number of decoded resolution levels ?
+*/
+void dwt_decode_real(opj_tcd_tilecomp_t * tilec, int stop);
+/**
+Get the gain of a subband for the irreversible 9-7 DWT.
+@param orient Number that identifies the subband (0->LL, 1->HL, 2->LH, 3->HH)
+@return Returns the gain of the 9-7 wavelet transform
+*/
+int dwt_getgain_real(int orient);
+/**
+Get the norm of a wavelet function of a subband at a specified level for the irreversible 9-7 DWT
+@param level Level of the wavelet function
+@param orient Band of the wavelet function
+@return Returns the norm of the 9-7 wavelet
+*/
+double dwt_getnorm_real(int level, int orient);
+/**
+FIXME : comment ???
+@param tccp
+@param prec
+*/
+void dwt_calc_explicit_stepsizes(opj_tccp_t * tccp, int prec);
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __DWT_H */
diff --git a/Utilities/ITK/Utilities/openjpeg/event.c b/Utilities/ITK/Utilities/openjpeg/event.c
new file mode 100644
index 0000000000..57e1e3b6c1
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/event.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opj_includes.h"
+
+/* ==========================================================
+     Utility functions
+   ==========================================================*/
+
+#if !defined(_MSC_VER) && !defined(__MINGW32__)
+static char*
+i2a(unsigned i, char *a, unsigned r) {
+  if (i/r > 0) a = i2a(i/r,a,r);
+  *a = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i%r];
+  return a+1;
+}
+
+/** 
+ Transforms integer i into an ascii string and stores the result in a; 
+ string is encoded in the base indicated by r.
+ @param i Number to be converted
+ @param a String result
+ @param r Base of value; must be in the range 2 - 36
+ @return Returns a
+*/
+static char *
+_itoa(int i, char *a, int r) {
+  r = ((r < 2) || (r > 36)) ? 10 : r;
+  if(i < 0) {
+    *a = '-';
+    *i2a(-i, a+1, r) = 0;
+  }
+  else *i2a(i, a, r) = 0;
+  return a;
+}
+
+#endif /* !WIN32 */
+
+/* ----------------------------------------------------------------------- */
+
+opj_event_mgr_t* OPJ_CALLCONV opj_set_event_mgr(opj_common_ptr cinfo, opj_event_mgr_t *event_mgr, void *context) {
+  if(cinfo) {
+    opj_event_mgr_t *previous = cinfo->event_mgr;
+    cinfo->event_mgr = event_mgr;
+    cinfo->client_data = context;
+    return previous;
+  }
+
+  return NULL;
+}
+
+bool opj_event_msg(opj_common_ptr cinfo, int event_type, const char *fmt, ...) {
+#define MSG_SIZE 512 /* 512 bytes should be more than enough for a short message */
+  opj_msg_callback msg_handler = NULL;
+
+  opj_event_mgr_t *event_mgr = cinfo->event_mgr;
+  if(event_mgr != NULL) {
+    switch(event_type) {
+      case EVT_ERROR:
+        msg_handler = event_mgr->error_handler;
+        break;
+      case EVT_WARNING:
+        msg_handler = event_mgr->warning_handler;
+        break;
+      case EVT_INFO:
+        msg_handler = event_mgr->info_handler;
+        break;
+      default:
+        break;
+    }
+    if(msg_handler == NULL) {
+      return false;
+    }
+  } else {
+    return false;
+  }
+
+  if ((fmt != NULL) && (event_mgr != NULL)) {
+    va_list arg;
+    int str_length, i, j;
+    char message[MSG_SIZE];
+    memset(message, 0, MSG_SIZE);
+    /* initialize the optional parameter list */
+    va_start(arg, fmt);
+    /* check the length of the format string */
+    str_length = (strlen(fmt) > MSG_SIZE) ? MSG_SIZE : strlen(fmt);
+    /* parse the format string and put the result in 'message' */
+    for (i = 0, j = 0; i < str_length; ++i) {
+      if (fmt[i] == '%') {
+        if (i + 1 < str_length) {
+          switch(tolower(fmt[i + 1])) {
+            case '%' :
+              message[j++] = '%';
+              break;
+            case 'o' : /* octal numbers */
+            {
+              char tmp[16];
+              _itoa(va_arg(arg, int), tmp, 8);
+              strcat(message, tmp);
+              j += strlen(tmp);
+              ++i;
+              break;
+            }
+            case 'i' : /* decimal numbers */
+            case 'd' :
+            {
+              char tmp[16];
+              _itoa(va_arg(arg, int), tmp, 10);
+              strcat(message, tmp);
+              j += strlen(tmp);
+              ++i;
+              break;
+            }
+            case 'x' : /* hexadecimal numbers */
+            {
+              char tmp[16];
+              _itoa(va_arg(arg, int), tmp, 16);
+              strcat(message, tmp);
+              j += strlen(tmp);
+              ++i;
+              break;
+            }
+            case 's' : /* strings */
+            {
+              char *tmp = va_arg(arg, char*);
+              strcat(message, tmp);
+              j += strlen(tmp);
+              ++i;
+              break;
+            }
+            case 'f' :  /* floats */
+            {
+              char tmp[16];
+              double value = va_arg(arg, double);
+              sprintf(tmp, "%f", value);
+              strcat(message, tmp);
+              j += strlen(tmp);
+              ++i;
+              break;
+            }
+          };
+        } else {
+          message[j++] = fmt[i];
+        }
+      } else {
+        message[j++] = fmt[i];
+      };
+    }
+    /* deinitialize the optional parameter list */
+    va_end(arg);
+
+    /* output the message to the user program */
+    msg_handler(message, cinfo->client_data);
+  }
+
+  return true;
+}
+
diff --git a/Utilities/ITK/Utilities/openjpeg/event.h b/Utilities/ITK/Utilities/openjpeg/event.h
new file mode 100644
index 0000000000..75c504d86b
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/event.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __EVENT_H
+#define __EVENT_H
+/**
+@file event.h
+@brief Implementation of a event callback system
+
+The functions in EVENT.C have for goal to send output messages (errors, warnings, debug) to the user.
+*/
+
+#define EVT_ERROR  1  /**< Error event type */
+#define EVT_WARNING  2  /**< Warning event type */
+#define EVT_INFO  4  /**< Debug event type */
+
+/** @defgroup EVENT EVENT - Implementation of a event callback system */
+/*@{*/
+
+/** @name Exported functions (see also openjpeg.h) */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+/**
+Write formatted data to a string and send the string to a user callback. 
+@param cinfo Codec context info
+@param event_type Event type or callback to use to send the message
+@param fmt Format-control string (plus optionnal arguments)
+@return Returns true if successful, returns false otherwise
+*/
+bool opj_event_msg(opj_common_ptr cinfo, int event_type, const char *fmt, ...);
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __EVENT_H */
diff --git a/Utilities/ITK/Utilities/openjpeg/fix.h b/Utilities/ITK/Utilities/openjpeg/fix.h
new file mode 100644
index 0000000000..85575cbcee
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/fix.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __FIX_H
+#define __FIX_H
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+#define int64 __int64
+#else
+#define int64 long long
+#endif
+
+/**
+@file fix.h
+@brief Implementation of operations of specific multiplication (FIX)
+
+The functions in FIX.H have for goal to realize specific multiplication.
+*/
+
+/** @defgroup FIX FIX - Implementation of operations of specific multiplication */
+/*@{*/
+
+/**
+Multiply two fixed-precision rational numbers.
+@param a
+@param b
+@return Returns a * b
+*/
+static INLINE int fix_mul(int a, int b) {
+    int64 temp = (int64) a * (int64) b >> 12;
+    return (int) ((temp >> 1) + (temp & 1)) ;
+}
+
+/*@}*/
+
+#endif /* __FIX_H */
diff --git a/Utilities/ITK/Utilities/openjpeg/image.c b/Utilities/ITK/Utilities/openjpeg/image.c
new file mode 100644
index 0000000000..69267eed3c
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/image.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opj_includes.h"
+
+opj_image_t* opj_image_create0() {
+  opj_image_t *image = (opj_image_t*)opj_malloc(sizeof(opj_image_t));
+  return image;
+}
+
+opj_image_t* OPJ_CALLCONV opj_image_create(int numcmpts, opj_image_cmptparm_t *cmptparms, OPJ_COLOR_SPACE clrspc) {
+  int compno;
+  opj_image_t *image = NULL;
+
+  image = (opj_image_t*)opj_malloc(sizeof(opj_image_t));
+  if(image) {
+    image->color_space = clrspc;
+    image->numcomps = numcmpts;
+    /* allocate memory for the per-component information */
+    image->comps = (opj_image_comp_t*)opj_malloc(image->numcomps * sizeof(opj_image_comp_t));
+    if(!image->comps) {
+      opj_image_destroy(image);
+      return NULL;
+    }
+    /* create the individual image components */
+    for(compno = 0; compno < numcmpts; compno++) {
+      opj_image_comp_t *comp = &image->comps[compno];
+      comp->dx = cmptparms[compno].dx;
+      comp->dy = cmptparms[compno].dy;
+      comp->w = cmptparms[compno].w;
+      comp->h = cmptparms[compno].h;
+      comp->x0 = cmptparms[compno].x0;
+      comp->y0 = cmptparms[compno].y0;
+      comp->prec = cmptparms[compno].prec;
+      comp->bpp = cmptparms[compno].bpp;
+      comp->sgnd = cmptparms[compno].sgnd;
+      comp->data = (int*)opj_malloc(comp->w * comp->h * sizeof(int));
+      if(!comp->data) {
+        opj_image_destroy(image);
+        return NULL;
+      }
+    }
+  }
+
+  return image;
+}
+
+void OPJ_CALLCONV opj_image_destroy(opj_image_t *image) {
+  int i;
+  if(image) {
+    if(image->comps) {
+      /* image components */
+      for(i = 0; i < image->numcomps; i++) {
+        opj_image_comp_t *image_comp = &image->comps[i];
+        if(image_comp->data) {
+          opj_free(image_comp->data);
+        }
+      }
+      opj_free(image->comps);
+    }
+    opj_free(image);
+  }
+}
+
diff --git a/Utilities/ITK/Utilities/openjpeg/image.h b/Utilities/ITK/Utilities/openjpeg/image.h
new file mode 100644
index 0000000000..b56de4acb3
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/image.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __IMAGE_H
+#define __IMAGE_H
+/**
+@file image.h
+@brief Implementation of operations on images (IMAGE)
+
+The functions in IMAGE.C have for goal to realize operations on images.
+*/
+
+/** @defgroup IMAGE IMAGE - Implementation of operations on images */
+/*@{*/
+
+/**
+Create an empty image
+@todo this function should be removed
+@return returns an empty image if successful, returns NULL otherwise
+*/
+opj_image_t* opj_image_create0();
+
+/*@}*/
+
+#endif /* __IMAGE_H */
+
diff --git a/Utilities/ITK/Utilities/openjpeg/int.h b/Utilities/ITK/Utilities/openjpeg/int.h
new file mode 100644
index 0000000000..3195cccc44
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/int.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __INT_H
+#define __INT_H
+/**
+@file int.h
+@brief Implementation of operations on integers (INT)
+
+The functions in INT.H have for goal to realize operations on integers.
+*/
+
+/** @defgroup INT INT - Implementation of operations on integers */
+/*@{*/
+
+/** @name Exported functions (see also openjpeg.h) */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+/**
+Get the minimum of two integers
+@return Returns a if a < b else b
+*/
+static INLINE int int_min(int a, int b) {
+  return a < b ? a : b;
+}
+/**
+Get the maximum of two integers
+@return Returns a if a > b else b
+*/
+static INLINE int int_max(int a, int b) {
+  return (a > b) ? a : b;
+}
+/**
+Clamp an integer inside an interval
+@return
+<ul>
+<li>Returns a if (min < a < max)
+<li>Returns max if (a > max)
+<li>Returns min if (a < min) 
+</ul>
+*/
+static INLINE int int_clamp(int a, int min, int max) {
+  if (a < min)
+    return min;
+  if (a > max)
+    return max;
+  return a;
+}
+/**
+@return Get absolute value of integer
+*/
+static INLINE int int_abs(int a) {
+  return a < 0 ? -a : a;
+}
+/**
+Divide an integer and round upwards
+@return Returns a divided by b
+*/
+static INLINE int int_ceildiv(int a, int b) {
+  return (a + b - 1) / b;
+}
+/**
+Divide an integer by a power of 2 and round upwards
+@return Returns a divided by 2^b
+*/
+static INLINE int int_ceildivpow2(int a, int b) {
+  return (a + (1 << b) - 1) >> b;
+}
+/**
+Divide an integer by a power of 2 and round downwards
+@return Returns a divided by 2^b
+*/
+static INLINE int int_floordivpow2(int a, int b) {
+  return a >> b;
+}
+/**
+Get logarithm of an integer and round downwards
+@return Returns log2(a)
+*/
+static INLINE int int_floorlog2(int a) {
+  int l;
+  for (l = 0; a > 1; l++) {
+    a >>= 1;
+  }
+  return l;
+}
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif
diff --git a/Utilities/ITK/Utilities/openjpeg/j2k.c b/Utilities/ITK/Utilities/openjpeg/j2k.c
new file mode 100644
index 0000000000..7481dfd6e3
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/j2k.c
@@ -0,0 +1,1924 @@
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opj_includes.h"
+
+/** @defgroup J2K J2K - JPEG-2000 codestream reader/writer */
+/*@{*/
+
+/** @name Local static functions */
+/*@{*/
+
+/**
+Write the SOC marker (Start Of Codestream)
+@param j2k J2K handle
+*/
+static void j2k_write_soc(opj_j2k_t *j2k);
+/**
+Read the SOC marker (Start of Codestream)
+@param j2k J2K handle
+*/
+static void j2k_read_soc(opj_j2k_t *j2k);
+/**
+Write the SIZ marker (image and tile size)
+@param j2k J2K handle
+*/
+static void j2k_write_siz(opj_j2k_t *j2k);
+/**
+Read the SIZ marker (image and tile size)
+@param j2k J2K handle
+*/
+static void j2k_read_siz(opj_j2k_t *j2k);
+/**
+Write the COM marker (comment)
+@param j2k J2K handle
+*/
+static void j2k_write_com(opj_j2k_t *j2k);
+/**
+Read the COM marker (comment)
+@param j2k J2K handle
+*/
+static void j2k_read_com(opj_j2k_t *j2k);
+/**
+Write the value concerning the specified component in the marker COD and COC
+@param j2k J2K handle
+@param compno Number of the component concerned by the information written
+*/
+static void j2k_write_cox(opj_j2k_t *j2k, int compno);
+/**
+Read the value concerning the specified component in the marker COD and COC
+@param j2k J2K handle
+@param compno Number of the component concerned by the information read
+*/
+static void j2k_read_cox(opj_j2k_t *j2k, int compno);
+/**
+Write the COD marker (coding style default)
+@param j2k J2K handle
+*/
+static void j2k_write_cod(opj_j2k_t *j2k);
+/**
+Read the COD marker (coding style default)
+@param j2k J2K handle
+*/
+static void j2k_read_cod(opj_j2k_t *j2k);
+/**
+Write the COC marker (coding style component)
+@param j2k J2K handle
+@param compno Number of the component concerned by the information written
+*/
+static void j2k_write_coc(opj_j2k_t *j2k, int compno);
+/**
+Read the COC marker (coding style component)
+@param j2k J2K handle
+*/
+static void j2k_read_coc(opj_j2k_t *j2k);
+/**
+Write the value concerning the specified component in the marker QCD and QCC
+@param j2k J2K handle
+@param compno Number of the component concerned by the information written
+*/
+static void j2k_write_qcx(opj_j2k_t *j2k, int compno);
+/**
+Read the value concerning the specified component in the marker QCD and QCC
+@param j2k J2K handle
+@param compno Number of the component concern by the information read
+@param len Length of the information in the QCX part of the marker QCD/QCC
+*/
+static void j2k_read_qcx(opj_j2k_t *j2k, int compno, int len);
+/**
+Write the QCD marker (quantization default)
+@param j2k J2K handle
+*/
+static void j2k_write_qcd(opj_j2k_t *j2k);
+/**
+Read the QCD marker (quantization default)
+@param j2k J2K handle
+*/
+static void j2k_read_qcd(opj_j2k_t *j2k);
+/**
+Write the QCC marker (quantization component)
+@param j2k J2K handle
+@param compno Number of the component concerned by the information written
+*/
+static void j2k_write_qcc(opj_j2k_t *j2k, int compno);
+/**
+Read the QCC marker (quantization component)
+@param j2k J2K handle
+*/
+static void j2k_read_qcc(opj_j2k_t *j2k);
+/**
+Write the POC marker (progression order change)
+@param j2k J2K handle
+*/
+static void j2k_write_poc(opj_j2k_t *j2k);
+/**
+Read the POC marker (progression order change)
+@param j2k J2K handle
+*/
+static void j2k_read_poc(opj_j2k_t *j2k);
+/**
+Read the CRG marker (component registration)
+@param j2k J2K handle
+*/
+static void j2k_read_crg(opj_j2k_t *j2k);
+/**
+Read the TLM marker (tile-part lengths)
+@param j2k J2K handle
+*/
+static void j2k_read_tlm(opj_j2k_t *j2k);
+/**
+Read the PLM marker (packet length, main header)
+@param j2k J2K handle
+*/
+static void j2k_read_plm(opj_j2k_t *j2k);
+/**
+Read the PLT marker (packet length, tile-part header)
+@param j2k J2K handle
+*/
+static void j2k_read_plt(opj_j2k_t *j2k);
+/**
+Read the PPM marker (packet packet headers, main header)
+@param j2k J2K handle
+*/
+static void j2k_read_ppm(opj_j2k_t *j2k);
+/**
+Read the PPT marker (packet packet headers, tile-part header)
+@param j2k J2K handle
+*/
+static void j2k_read_ppt(opj_j2k_t *j2k);
+/**
+Write the SOT marker (start of tile-part)
+@param j2k J2K handle
+*/
+static void j2k_write_sot(opj_j2k_t *j2k);
+/**
+Read the SOT marker (start of tile-part)
+@param j2k J2K handle
+*/
+static void j2k_read_sot(opj_j2k_t *j2k);
+/**
+Write the SOD marker (start of data)
+@param j2k J2K handle
+@param tile_coder Pointer to a TCD handle
+*/
+static void j2k_write_sod(opj_j2k_t *j2k, void *tile_coder);
+/**
+Read the SOD marker (start of data)
+@param j2k J2K handle
+*/
+static void j2k_read_sod(opj_j2k_t *j2k);
+/**
+Write the RGN marker (region-of-interest)
+@param j2k J2K handle
+@param compno Number of the component concerned by the information written
+@param tileno Number of the tile concerned by the information written
+*/
+static void j2k_write_rgn(opj_j2k_t *j2k, int compno, int tileno);
+/**
+Read the RGN marker (region-of-interest)
+@param j2k J2K handle
+*/
+static void j2k_read_rgn(opj_j2k_t *j2k);
+/**
+Write the EOC marker (end of codestream)
+@param j2k J2K handle
+*/
+static void j2k_write_eoc(opj_j2k_t *j2k);
+/**
+Read the EOC marker (end of codestream)
+@param j2k J2K handle
+*/
+static void j2k_read_eoc(opj_j2k_t *j2k);
+/**
+Read an unknown marker
+@param j2k J2K handle
+*/
+static void j2k_read_unk(opj_j2k_t *j2k);
+
+/*@}*/
+
+/*@}*/
+
+/* ----------------------------------------------------------------------- */
+
+void j2k_dump_image(FILE *fd, opj_image_t * img) {
+  int compno;
+  fprintf(fd, "image {\n");
+  fprintf(fd, "  x0=%d, y0=%d, x1=%d, y1=%d\n", img->x0, img->y0, img->x1, img->y1);
+  fprintf(fd, "  numcomps=%d\n", img->numcomps);
+  for (compno = 0; compno < img->numcomps; compno++) {
+    opj_image_comp_t *comp = &img->comps[compno];
+    fprintf(fd, "  comp %d {\n", compno);
+    fprintf(fd, "    dx=%d, dy=%d\n", comp->dx, comp->dy);
+    fprintf(fd, "    prec=%d\n", comp->prec);
+    fprintf(fd, "    sgnd=%d\n", comp->sgnd);
+    fprintf(fd, "  }\n");
+  }
+  fprintf(fd, "}\n");
+}
+
+void j2k_dump_cp(FILE *fd, opj_image_t * img, opj_cp_t * cp) {
+  int tileno, compno, layno, bandno, resno, numbands;
+  fprintf(fd, "coding parameters {\n");
+  fprintf(fd, "  tx0=%d, ty0=%d\n", cp->tx0, cp->ty0);
+  fprintf(fd, "  tdx=%d, tdy=%d\n", cp->tdx, cp->tdy);
+  fprintf(fd, "  tw=%d, th=%d\n", cp->tw, cp->th);
+  for (tileno = 0; tileno < cp->tw * cp->th; tileno++) {
+    opj_tcp_t *tcp = &cp->tcps[tileno];
+    fprintf(fd, "  tile %d {\n", tileno);
+    fprintf(fd, "    csty=%x\n", tcp->csty);
+    fprintf(fd, "    prg=%d\n", tcp->prg);
+    fprintf(fd, "    numlayers=%d\n", tcp->numlayers);
+    fprintf(fd, "    mct=%d\n", tcp->mct);
+    fprintf(fd, "    rates=");
+    for (layno = 0; layno < tcp->numlayers; layno++) {
+      fprintf(fd, "%d ", tcp->rates[layno]);
+    }
+    fprintf(fd, "\n");
+    for (compno = 0; compno < img->numcomps; compno++) {
+      opj_tccp_t *tccp = &tcp->tccps[compno];
+      fprintf(fd, "    comp %d {\n", compno);
+      fprintf(fd, "      csty=%x\n", tccp->csty);
+      fprintf(fd, "      numresolutions=%d\n", tccp->numresolutions);
+      fprintf(fd, "      cblkw=%d\n", tccp->cblkw);
+      fprintf(fd, "      cblkh=%d\n", tccp->cblkh);
+      fprintf(fd, "      cblksty=%x\n", tccp->cblksty);
+      fprintf(fd, "      qmfbid=%d\n", tccp->qmfbid);
+      fprintf(fd, "      qntsty=%d\n", tccp->qntsty);
+      fprintf(fd, "      numgbits=%d\n", tccp->numgbits);
+      fprintf(fd, "      roishift=%d\n", tccp->roishift);
+      fprintf(fd, "      stepsizes=");
+      numbands = tccp->qntsty == J2K_CCP_QNTSTY_SIQNT ? 1 : tccp->numresolutions * 3 - 2;
+      for (bandno = 0; bandno < numbands; bandno++) {
+        fprintf(fd, "(%d,%d) ", tccp->stepsizes[bandno].mant,
+          tccp->stepsizes[bandno].expn);
+      }
+      fprintf(fd, "\n");
+      
+      if (tccp->csty & J2K_CCP_CSTY_PRT) {
+        fprintf(fd, "      prcw=");
+        for (resno = 0; resno < tccp->numresolutions; resno++) {
+          fprintf(fd, "%d ", tccp->prcw[resno]);
+        }
+        fprintf(fd, "\n");
+        fprintf(fd, "      prch=");
+        for (resno = 0; resno < tccp->numresolutions; resno++) {
+          fprintf(fd, "%d ", tccp->prch[resno]);
+        }
+        fprintf(fd, "\n");
+      }
+      fprintf(fd, "    }\n");
+    }
+    fprintf(fd, "  }\n");
+  }
+  fprintf(fd, "}\n");
+}
+
+/* ----------------------------------------------------------------------- */
+
+static void j2k_write_soc(opj_j2k_t *j2k) {
+  opj_cio_t *cio = j2k->cio;
+  cio_write(cio, J2K_MS_SOC, 2);
+}
+
+static void j2k_read_soc(opj_j2k_t *j2k) {
+  j2k->state = J2K_STATE_MHSIZ;
+}
+
+static void j2k_write_siz(opj_j2k_t *j2k) {
+  int i;
+  int lenp, len;
+
+  opj_cio_t *cio = j2k->cio;
+  opj_image_t *image = j2k->image;
+  opj_cp_t *cp = j2k->cp;
+  
+  cio_write(cio, J2K_MS_SIZ, 2);  /* SIZ */
+  lenp = cio_tell(cio);
+  cio_skip(cio, 2);
+  cio_write(cio, 0, 2);      /* Rsiz (capabilities) */
+  cio_write(cio, image->x1, 4);  /* Xsiz */
+  cio_write(cio, image->y1, 4);  /* Ysiz */
+  cio_write(cio, image->x0, 4);  /* X0siz */
+  cio_write(cio, image->y0, 4);  /* Y0siz */
+  cio_write(cio, cp->tdx, 4);    /* XTsiz */
+  cio_write(cio, cp->tdy, 4);    /* YTsiz */
+  cio_write(cio, cp->tx0, 4);    /* XT0siz */
+  cio_write(cio, cp->ty0, 4);    /* YT0siz */
+  cio_write(cio, image->numcomps, 2);  /* Csiz */
+  for (i = 0; i < image->numcomps; i++) {
+    cio_write(cio, image->comps[i].prec - 1 + (image->comps[i].sgnd << 7), 1);  /* Ssiz_i */
+    cio_write(cio, image->comps[i].dx, 1);  /* XRsiz_i */
+    cio_write(cio, image->comps[i].dy, 1);  /* YRsiz_i */
+  }
+  len = cio_tell(cio) - lenp;
+  cio_seek(cio, lenp);
+  cio_write(cio, len, 2);    /* Lsiz */
+  cio_seek(cio, lenp + len);
+}
+
+static void j2k_read_siz(opj_j2k_t *j2k) {
+  int len, i;
+  
+  opj_cio_t *cio = j2k->cio;
+  opj_image_t *image = j2k->image;
+  opj_cp_t *cp = j2k->cp;
+  
+  len = cio_read(cio, 2);      /* Lsiz */
+  cio_read(cio, 2);        /* Rsiz (capabilities) */
+  image->x1 = cio_read(cio, 4);  /* Xsiz */
+  image->y1 = cio_read(cio, 4);  /* Ysiz */
+  image->x0 = cio_read(cio, 4);  /* X0siz */
+  image->y0 = cio_read(cio, 4);  /* Y0siz */
+  cp->tdx = cio_read(cio, 4);    /* XTsiz */
+  cp->tdy = cio_read(cio, 4);    /* YTsiz */
+  cp->tx0 = cio_read(cio, 4);    /* XT0siz */
+  cp->ty0 = cio_read(cio, 4);    /* YT0siz */
+  
+  image->numcomps = cio_read(cio, 2);  /* Csiz */
+  image->comps = (opj_image_comp_t *) opj_malloc(image->numcomps * sizeof(opj_image_comp_t));
+  for (i = 0; i < image->numcomps; i++) {
+    int tmp, w, h;
+    tmp = cio_read(cio, 1);    /* Ssiz_i */
+    image->comps[i].prec = (tmp & 0x7f) + 1;
+    image->comps[i].sgnd = tmp >> 7;
+    image->comps[i].dx = cio_read(cio, 1);  /* XRsiz_i */
+    image->comps[i].dy = cio_read(cio, 1);  /* YRsiz_i */
+    
+    /* TODO: unused ? */
+    w = int_ceildiv(image->x1 - image->x0, image->comps[i].dx);
+    h = int_ceildiv(image->y1 - image->y0, image->comps[i].dy);
+
+    image->comps[i].resno_decoded = 0;  /* number of resolution decoded */
+    image->comps[i].factor = 0;      /* reducing factor per component */
+  }
+  
+  cp->tw = int_ceildiv(image->x1 - cp->tx0, cp->tdx);
+  cp->th = int_ceildiv(image->y1 - cp->ty0, cp->tdy);
+  cp->tcps = (opj_tcp_t *) opj_malloc(cp->tw * cp->th * sizeof(opj_tcp_t));
+  cp->tileno = (int *) opj_malloc(cp->tw * cp->th * sizeof(int));
+  cp->tileno_size = 0;
+  
+  for (i = 0; i < cp->tw * cp->th; i++) {
+    cp->tcps[i].POC = 0;
+    cp->tcps[i].numpocs = 0;
+    cp->tcps[i].first = 1;
+  }
+  
+  /* Initialization for PPM marker */
+  cp->ppm = 0;
+  cp->ppm_data = NULL;
+  cp->ppm_data_first = NULL;
+  cp->ppm_previous = 0;
+  cp->ppm_store = 0;
+  
+  j2k->default_tcp->tccps = (opj_tccp_t *) opj_malloc(sizeof(opj_tccp_t) * image->numcomps);
+  for (i = 0; i < cp->tw * cp->th; i++) {
+    cp->tcps[i].tccps = (opj_tccp_t *) opj_malloc(sizeof(opj_tccp_t) * image->numcomps);
+  }
+  j2k->tile_data = (unsigned char **) opj_malloc(cp->tw * cp->th * sizeof(unsigned char *));
+  j2k->tile_len = (int *) opj_malloc(cp->tw * cp->th * sizeof(int));
+  j2k->state = J2K_STATE_MH;
+}
+
+static void j2k_write_com(opj_j2k_t *j2k) {
+  unsigned int i;
+  int lenp, len;
+
+  if(j2k->cp->comment) {
+    opj_cio_t *cio = j2k->cio;
+    char *comment = j2k->cp->comment;
+
+    cio_write(cio, J2K_MS_COM, 2);
+    lenp = cio_tell(cio);
+    cio_skip(cio, 2);
+    cio_write(cio, 0, 2);
+    for (i = 0; i < strlen(comment); i++) {
+      cio_write(cio, comment[i], 1);
+    }
+    len = cio_tell(cio) - lenp;
+    cio_seek(cio, lenp);
+    cio_write(cio, len, 2);
+    cio_seek(cio, lenp + len);
+  }
+}
+
+static void j2k_read_com(opj_j2k_t *j2k) {
+  int len;
+  
+  opj_cio_t *cio = j2k->cio;
+
+  len = cio_read(cio, 2);
+  cio_skip(cio, len - 2);  
+}
+
+static void j2k_write_cox(opj_j2k_t *j2k, int compno) {
+  int i;
+
+  opj_cp_t *cp = j2k->cp;
+  opj_tcp_t *tcp = &cp->tcps[j2k->curtileno];
+  opj_tccp_t *tccp = &tcp->tccps[compno];
+  opj_cio_t *cio = j2k->cio;
+  
+  cio_write(cio, tccp->numresolutions - 1, 1);  /* SPcox (D) */
+  cio_write(cio, tccp->cblkw - 2, 1);        /* SPcox (E) */
+  cio_write(cio, tccp->cblkh - 2, 1);        /* SPcox (F) */
+  cio_write(cio, tccp->cblksty, 1);        /* SPcox (G) */
+  cio_write(cio, tccp->qmfbid, 1);        /* SPcox (H) */
+  
+  if (tccp->csty & J2K_CCP_CSTY_PRT) {
+    for (i = 0; i < tccp->numresolutions; i++) {
+      cio_write(cio, tccp->prcw[i] + (tccp->prch[i] << 4), 1);  /* SPcox (I_i) */
+    }
+  }
+}
+
+static void j2k_read_cox(opj_j2k_t *j2k, int compno) {
+  int i;
+
+  opj_cp_t *cp = j2k->cp;
+  opj_tcp_t *tcp = j2k->state == J2K_STATE_TPH ? &cp->tcps[j2k->curtileno] : j2k->default_tcp;
+  opj_tccp_t *tccp = &tcp->tccps[compno];
+  opj_cio_t *cio = j2k->cio;
+
+  tccp->numresolutions = cio_read(cio, 1) + 1;  /* SPcox (D) */
+
+  /* check the reduce value */
+  cp->reduce = int_min((tccp->numresolutions)-1, cp->reduce);
+  tccp->cblkw = cio_read(cio, 1) + 2;  /* SPcox (E) */
+  tccp->cblkh = cio_read(cio, 1) + 2;  /* SPcox (F) */
+  tccp->cblksty = cio_read(cio, 1);  /* SPcox (G) */
+  tccp->qmfbid = cio_read(cio, 1);  /* SPcox (H) */
+  if (tccp->csty & J2K_CP_CSTY_PRT) {
+    for (i = 0; i < tccp->numresolutions; i++) {
+      int tmp = cio_read(cio, 1);  /* SPcox (I_i) */
+      tccp->prcw[i] = tmp & 0xf;
+      tccp->prch[i] = tmp >> 4;
+    }
+  }
+}
+
+static void j2k_write_cod(opj_j2k_t *j2k) {
+  opj_cp_t *cp = NULL;
+  opj_tcp_t *tcp = NULL;
+  int lenp, len;
+
+  opj_cio_t *cio = j2k->cio;
+  
+  cio_write(cio, J2K_MS_COD, 2);  /* COD */
+  
+  lenp = cio_tell(cio);
+  cio_skip(cio, 2);
+  
+  cp = j2k->cp;
+  tcp = &cp->tcps[j2k->curtileno];
+
+  cio_write(cio, tcp->csty, 1);    /* Scod */
+  cio_write(cio, tcp->prg, 1);    /* SGcod (A) */
+  cio_write(cio, tcp->numlayers, 2);  /* SGcod (B) */
+  cio_write(cio, tcp->mct, 1);    /* SGcod (C) */
+  
+  j2k_write_cox(j2k, 0);
+  len = cio_tell(cio) - lenp;
+  cio_seek(cio, lenp);
+  cio_write(cio, len, 2);    /* Lcod */
+  cio_seek(cio, lenp + len);
+}
+
+static void j2k_read_cod(opj_j2k_t *j2k) {
+  int len, i, pos;
+  
+  opj_cio_t *cio = j2k->cio;
+  opj_cp_t *cp = j2k->cp;
+  opj_tcp_t *tcp = j2k->state == J2K_STATE_TPH ? &cp->tcps[j2k->curtileno] : j2k->default_tcp;
+  opj_image_t *image = j2k->image;
+  
+  len = cio_read(cio, 2);        /* Lcod */
+  tcp->csty = cio_read(cio, 1);    /* Scod */
+  tcp->prg = (OPJ_PROG_ORDER)cio_read(cio, 1);    /* SGcod (A) */
+  tcp->numlayers = cio_read(cio, 2);  /* SGcod (B) */
+  tcp->mct = cio_read(cio, 1);    /* SGcod (C) */
+  
+  pos = cio_tell(cio);
+  for (i = 0; i < image->numcomps; i++) {
+    tcp->tccps[i].csty = tcp->csty & J2K_CP_CSTY_PRT;
+    cio_seek(cio, pos);
+    j2k_read_cox(j2k, i);
+  }
+}
+
+static void j2k_write_coc(opj_j2k_t *j2k, int compno) {
+  int lenp, len;
+
+  opj_cp_t *cp = j2k->cp;
+  opj_tcp_t *tcp = &cp->tcps[j2k->curtileno];
+  opj_image_t *image = j2k->image;
+  opj_cio_t *cio = j2k->cio;
+  
+  cio_write(cio, J2K_MS_COC, 2);  /* COC */
+  lenp = cio_tell(cio);
+  cio_skip(cio, 2);
+  cio_write(cio, compno, image->numcomps <= 256 ? 1 : 2);  /* Ccoc */
+  cio_write(cio, tcp->tccps[compno].csty, 1);  /* Scoc */
+  j2k_write_cox(j2k, compno);
+  len = cio_tell(cio) - lenp;
+  cio_seek(cio, lenp);
+  cio_write(cio, len, 2);      /* Lcoc */
+  cio_seek(cio, lenp + len);
+}
+
+static void j2k_read_coc(opj_j2k_t *j2k) {
+  int len, compno;
+
+  opj_cp_t *cp = j2k->cp;
+  opj_tcp_t *tcp = j2k->state == J2K_STATE_TPH ? &cp->tcps[j2k->curtileno] : j2k->default_tcp;
+  opj_image_t *image = j2k->image;
+  opj_cio_t *cio = j2k->cio;
+  
+  len = cio_read(cio, 2);    /* Lcoc */
+  compno = cio_read(cio, image->numcomps <= 256 ? 1 : 2);  /* Ccoc */
+  tcp->tccps[compno].csty = cio_read(cio, 1);  /* Scoc */
+  j2k_read_cox(j2k, compno);
+}
+
+static void j2k_write_qcx(opj_j2k_t *j2k, int compno) {
+  int bandno, numbands;
+  int expn, mant;
+  
+  opj_cp_t *cp = j2k->cp;
+  opj_tcp_t *tcp = &cp->tcps[j2k->curtileno];
+  opj_tccp_t *tccp = &tcp->tccps[compno];
+  opj_cio_t *cio = j2k->cio;
+  
+  cio_write(cio, tccp->qntsty + (tccp->numgbits << 5), 1);  /* Sqcx */
+  numbands = tccp->qntsty == J2K_CCP_QNTSTY_SIQNT ? 1 : tccp->numresolutions * 3 - 2;
+  
+  for (bandno = 0; bandno < numbands; bandno++) {
+    expn = tccp->stepsizes[bandno].expn;
+    mant = tccp->stepsizes[bandno].mant;
+    
+    if (tccp->qntsty == J2K_CCP_QNTSTY_NOQNT) {
+      cio_write(cio, expn << 3, 1);  /* SPqcx_i */
+    } else {
+      cio_write(cio, (expn << 11) + mant, 2);  /* SPqcx_i */
+    }
+  }
+}
+
+static void j2k_read_qcx(opj_j2k_t *j2k, int compno, int len) {
+  int tmp;
+  int bandno, numbands;
+
+  opj_cp_t *cp = j2k->cp;
+  opj_tcp_t *tcp = j2k->state == J2K_STATE_TPH ? &cp->tcps[j2k->curtileno] : j2k->default_tcp;
+  opj_tccp_t *tccp = &tcp->tccps[compno];
+  opj_cio_t *cio = j2k->cio;
+
+  tmp = cio_read(cio, 1);    /* Sqcx */
+  tccp->qntsty = tmp & 0x1f;
+  tccp->numgbits = tmp >> 5;
+  numbands = (tccp->qntsty == J2K_CCP_QNTSTY_SIQNT) ? 
+    1 : ((tccp->qntsty == J2K_CCP_QNTSTY_NOQNT) ? len - 1 : (len - 1) / 2);
+  for (bandno = 0; bandno < numbands; bandno++) {
+    int expn, mant;
+    if (tccp->qntsty == J2K_CCP_QNTSTY_NOQNT) {
+      expn = cio_read(cio, 1) >> 3;  /* SPqcx_i */
+      mant = 0;
+    } else {
+      tmp = cio_read(cio, 2);  /* SPqcx_i */
+      expn = tmp >> 11;
+      mant = tmp & 0x7ff;
+    }
+    tccp->stepsizes[bandno].expn = expn;
+    tccp->stepsizes[bandno].mant = mant;
+  }
+  
+  /* Add Antonin : if scalar_derived -> compute other stepsizes */
+  if (tccp->qntsty == J2K_CCP_QNTSTY_SIQNT) {
+    for (bandno = 1; bandno < J2K_MAXBANDS; bandno++) {
+      tccp->stepsizes[bandno].expn = 
+        ((tccp->stepsizes[0].expn) - ((bandno - 1) / 3) > 0) ? 
+          (tccp->stepsizes[0].expn) - ((bandno - 1) / 3) : 0;
+      tccp->stepsizes[bandno].mant = tccp->stepsizes[0].mant;
+    }
+  }
+  /* ddA */
+}
+
+static void j2k_write_qcd(opj_j2k_t *j2k) {
+  int lenp, len;
+
+  opj_cio_t *cio = j2k->cio;
+  
+  cio_write(cio, J2K_MS_QCD, 2);  /* QCD */
+  lenp = cio_tell(cio);
+  cio_skip(cio, 2);
+  j2k_write_qcx(j2k, 0);
+  len = cio_tell(cio) - lenp;
+  cio_seek(cio, lenp);
+  cio_write(cio, len, 2);      /* Lqcd */
+  cio_seek(cio, lenp + len);
+}
+
+static void j2k_read_qcd(opj_j2k_t *j2k) {
+  int len, i, pos;
+
+  opj_cio_t *cio = j2k->cio;
+  opj_image_t *image = j2k->image;
+  
+  len = cio_read(cio, 2);    /* Lqcd */
+  pos = cio_tell(cio);
+  for (i = 0; i < image->numcomps; i++) {
+    cio_seek(cio, pos);
+    j2k_read_qcx(j2k, i, len - 2);
+  }
+}
+
+static void j2k_write_qcc(opj_j2k_t *j2k, int compno) {
+  int lenp, len;
+
+  opj_cio_t *cio = j2k->cio;
+  
+  cio_write(cio, J2K_MS_QCC, 2);  /* QCC */
+  lenp = cio_tell(cio);
+  cio_skip(cio, 2);
+  cio_write(cio, compno, j2k->image->numcomps <= 256 ? 1 : 2);  /* Cqcc */
+  j2k_write_qcx(j2k, compno);
+  len = cio_tell(cio) - lenp;
+  cio_seek(cio, lenp);
+  cio_write(cio, len, 2);      /* Lqcc */
+  cio_seek(cio, lenp + len);
+}
+
+static void j2k_read_qcc(opj_j2k_t *j2k) {
+  int len, compno;
+  int numcomp = j2k->image->numcomps;
+  opj_cio_t *cio = j2k->cio;
+  
+  len = cio_read(cio, 2);  /* Lqcc */
+  compno = cio_read(cio, numcomp <= 256 ? 1 : 2);  /* Cqcc */
+  j2k_read_qcx(j2k, compno, len - 2 - (numcomp <= 256 ? 1 : 2));
+}
+
+static void j2k_write_poc(opj_j2k_t *j2k) {
+  int len, numpchgs, i;
+
+  int numcomps = j2k->image->numcomps;
+  
+  opj_cp_t *cp = j2k->cp;
+  opj_tcp_t *tcp = &cp->tcps[j2k->curtileno];
+  opj_tccp_t *tccp = &tcp->tccps[0];
+  opj_cio_t *cio = j2k->cio;
+
+  numpchgs = tcp->numpocs;
+  cio_write(cio, J2K_MS_POC, 2);  /* POC  */
+  len = 2 + (5 + 2 * (numcomps <= 256 ? 1 : 2)) * numpchgs;
+  cio_write(cio, len, 2);    /* Lpoc */
+  for (i = 0; i < numpchgs; i++) {
+    opj_poc_t *poc = &tcp->pocs[i];
+    cio_write(cio, poc->resno0, 1);  /* RSpoc_i */
+    cio_write(cio, poc->compno0, (numcomps <= 256 ? 1 : 2));  /* CSpoc_i */
+    cio_write(cio, poc->layno1, 2);  /* LYEpoc_i */
+    poc->layno1 = int_min(poc->layno1, tcp->numlayers);
+    cio_write(cio, poc->resno1, 1);  /* REpoc_i */
+    poc->resno1 = int_min(poc->resno1, tccp->numresolutions);
+    cio_write(cio, poc->compno1, (numcomps <= 256 ? 1 : 2));  /* CEpoc_i */
+    poc->compno1 = int_min(poc->compno1, numcomps);
+    cio_write(cio, poc->prg, 1);  /* Ppoc_i */
+  }
+}
+
+static void j2k_read_poc(opj_j2k_t *j2k) {
+  int len, numpchgs, i, old_poc;
+
+  int numcomps = j2k->image->numcomps;
+  
+  opj_cp_t *cp = j2k->cp;
+  opj_tcp_t *tcp = j2k->state == J2K_STATE_TPH ? &cp->tcps[j2k->curtileno] : j2k->default_tcp;
+  opj_tccp_t *tccp = &tcp->tccps[0];
+  opj_cio_t *cio = j2k->cio;
+  
+  old_poc = tcp->POC ? tcp->numpocs + 1 : 0;
+  tcp->POC = 1;
+  len = cio_read(cio, 2);    /* Lpoc */
+  numpchgs = (len - 2) / (5 + 2 * (numcomps <= 256 ? 1 : 2));
+  
+  for (i = old_poc; i < numpchgs + old_poc; i++) {
+    opj_poc_t *poc;
+    poc = &tcp->pocs[i];
+    poc->resno0 = cio_read(cio, 1);  /* RSpoc_i */
+    poc->compno0 = cio_read(cio, numcomps <= 256 ? 1 : 2);  /* CSpoc_i */
+    poc->layno1 = int_min(cio_read(cio, 2), (unsigned int) tcp->numlayers);  /* LYEpoc_i */
+    poc->resno1 = int_min(cio_read(cio, 1), (unsigned int) tccp->numresolutions);  /* REpoc_i */
+    poc->compno1 = int_min(
+      cio_read(cio, numcomps <= 256 ? 1 : 2), (unsigned int) numcomps);  /* CEpoc_i */
+    poc->prg = (OPJ_PROG_ORDER)cio_read(cio, 1);  /* Ppoc_i */
+  }
+  
+  tcp->numpocs = numpchgs + old_poc - 1;
+}
+
+static void j2k_read_crg(opj_j2k_t *j2k) {
+  int len, i, Xcrg_i, Ycrg_i;
+  
+  opj_cio_t *cio = j2k->cio;
+  int numcomps = j2k->image->numcomps;
+  
+  len = cio_read(cio, 2);      /* Lcrg */
+  for (i = 0; i < numcomps; i++) {
+    Xcrg_i = cio_read(cio, 2);  /* Xcrg_i */
+    Ycrg_i = cio_read(cio, 2);  /* Ycrg_i */
+  }
+}
+
+static void j2k_read_tlm(opj_j2k_t *j2k) {
+  int len, Ztlm, Stlm, ST, SP, tile_tlm, i;
+  long int Ttlm_i, Ptlm_i;
+
+  opj_cio_t *cio = j2k->cio;
+  
+  len = cio_read(cio, 2);    /* Ltlm */
+  Ztlm = cio_read(cio, 1);  /* Ztlm */
+  Stlm = cio_read(cio, 1);  /* Stlm */
+  ST = ((Stlm >> 4) & 0x01) + ((Stlm >> 4) & 0x02);
+  SP = (Stlm >> 6) & 0x01;
+  tile_tlm = (len - 4) / ((SP + 1) * 2 + ST);
+  for (i = 0; i < tile_tlm; i++) {
+    Ttlm_i = cio_read(cio, ST);  /* Ttlm_i */
+    Ptlm_i = cio_read(cio, SP ? 4 : 2);  /* Ptlm_i */
+  }
+}
+
+static void j2k_read_plm(opj_j2k_t *j2k) {
+  int len, i, Zplm, Nplm, add, packet_len = 0;
+  
+  opj_cio_t *cio = j2k->cio;
+
+  len = cio_read(cio, 2);    /* Lplm */
+  Zplm = cio_read(cio, 1);  /* Zplm */
+  len -= 3;
+  while (len > 0) {
+    Nplm = cio_read(cio, 4);    /* Nplm */
+    len -= 4;
+    for (i = Nplm; i > 0; i--) {
+      add = cio_read(cio, 1);
+      len--;
+      packet_len = (packet_len << 7) + add;  /* Iplm_ij */
+      if ((add & 0x80) == 0) {
+        /* New packet */
+        packet_len = 0;
+      }
+      if (len <= 0)
+        break;
+    }
+  }
+}
+
+static void j2k_read_plt(opj_j2k_t *j2k) {
+  int len, i, Zplt, packet_len = 0, add;
+  
+  opj_cio_t *cio = j2k->cio;
+  
+  len = cio_read(cio, 2);    /* Lplt */
+  Zplt = cio_read(cio, 1);  /* Zplt */
+  for (i = len - 3; i > 0; i--) {
+    add = cio_read(cio, 1);
+    packet_len = (packet_len << 7) + add;  /* Iplt_i */
+    if ((add & 0x80) == 0) {
+      /* New packet */
+      packet_len = 0;
+    }
+  }
+}
+
+static void j2k_read_ppm(opj_j2k_t *j2k) {
+  int len, Z_ppm, i, j;
+  int N_ppm;
+
+  opj_cp_t *cp = j2k->cp;
+  opj_cio_t *cio = j2k->cio;
+  
+  len = cio_read(cio, 2);
+  cp->ppm = 1;
+  
+  Z_ppm = cio_read(cio, 1);  /* Z_ppm */
+  len -= 3;
+  while (len > 0) {
+    if (cp->ppm_previous == 0) {
+      N_ppm = cio_read(cio, 4);  /* N_ppm */
+      len -= 4;
+    } else {
+      N_ppm = cp->ppm_previous;
+    }
+    j = cp->ppm_store;
+    if (Z_ppm == 0) {  /* First PPM marker */
+      cp->ppm_data = (unsigned char *) opj_malloc(N_ppm * sizeof(unsigned char));
+      cp->ppm_data_first = cp->ppm_data;
+      cp->ppm_len = N_ppm;
+    } else {      /* NON-first PPM marker */
+      cp->ppm_data = (unsigned char *) opj_realloc(cp->ppm_data, (N_ppm +  cp->ppm_store) * sizeof(unsigned char));
+      cp->ppm_data_first = cp->ppm_data;
+      cp->ppm_len = N_ppm + cp->ppm_store;
+    }
+    for (i = N_ppm; i > 0; i--) {  /* Read packet header */
+      cp->ppm_data[j] = cio_read(cio, 1);
+      j++;
+      len--;
+      if (len == 0)
+        break;      /* Case of non-finished packet header in present marker but finished in next one */
+    }
+    cp->ppm_previous = i - 1;
+    cp->ppm_store = j;
+  }
+}
+
+static void j2k_read_ppt(opj_j2k_t *j2k) {
+  int len, Z_ppt, i, j = 0;
+
+  opj_cp_t *cp = j2k->cp;
+  opj_tcp_t *tcp = cp->tcps + j2k->curtileno;
+  opj_cio_t *cio = j2k->cio;
+
+  len = cio_read(cio, 2);
+  Z_ppt = cio_read(cio, 1);
+  tcp->ppt = 1;
+  if (Z_ppt == 0) {    /* First PPT marker */
+    tcp->ppt_data = (unsigned char *) opj_malloc((len - 3) * sizeof(unsigned char));
+    tcp->ppt_data_first = tcp->ppt_data;
+    tcp->ppt_store = 0;
+    tcp->ppt_len = len - 3;
+  } else {      /* NON-first PPT marker */
+    tcp->ppt_data =  (unsigned char *) opj_realloc(tcp->ppt_data, (len - 3 + tcp->ppt_store) * sizeof(unsigned char));
+    tcp->ppt_data_first = tcp->ppt_data;
+    tcp->ppt_len = len - 3 + tcp->ppt_store;
+  }
+  j = tcp->ppt_store;
+  for (i = len - 3; i > 0; i--) {
+    tcp->ppt_data[j] = cio_read(cio, 1);
+    j++;
+  }
+  tcp->ppt_store = j;
+}
+
+static void j2k_write_sot(opj_j2k_t *j2k) {
+  int lenp, len;
+
+  opj_cio_t *cio = j2k->cio;
+
+  j2k->sot_start = cio_tell(cio);
+  cio_write(cio, J2K_MS_SOT, 2);    /* SOT */
+  lenp = cio_tell(cio);
+  cio_skip(cio, 2);          /* Lsot (further) */
+  cio_write(cio, j2k->curtileno, 2);  /* Isot */
+  cio_skip(cio, 4);          /* Psot (further in j2k_write_sod) */
+  cio_write(cio, 0, 1);        /* TPsot */
+  cio_write(cio, 1, 1);        /* TNsot */
+  len = cio_tell(cio) - lenp;
+  cio_seek(cio, lenp);
+  cio_write(cio, len, 2);        /* Lsot */
+  cio_seek(cio, lenp + len);
+}
+
+static void j2k_read_sot(opj_j2k_t *j2k) {
+  int len, tileno, totlen, partno, numparts, i;
+  opj_tcp_t *tcp = NULL;
+  char status = 0;
+
+  opj_cp_t *cp = j2k->cp;
+  opj_cio_t *cio = j2k->cio;
+  
+  len = cio_read(cio, 2);
+  tileno = cio_read(cio, 2);
+  
+  if (cp->tileno_size == 0) {
+    cp->tileno[cp->tileno_size] = tileno;
+    cp->tileno_size++;
+  } else {
+    i = 0;
+    while (i < cp->tileno_size && status == 0) {
+      status = cp->tileno[i] == tileno ? 1 : 0;
+      i++;
+    }
+    if (status == 0) {
+      cp->tileno[cp->tileno_size] = tileno;
+      cp->tileno_size++;
+    }
+  }
+  
+  totlen = cio_read(cio, 4);
+  if (!totlen)
+    totlen = cio_numbytesleft(cio) + 8;
+  
+  partno = cio_read(cio, 1);
+  numparts = cio_read(cio, 1);
+  
+  j2k->curtileno = tileno;
+  j2k->eot = cio_getbp(cio) - 12 + totlen;
+  j2k->state = J2K_STATE_TPH;
+  tcp = &cp->tcps[j2k->curtileno];
+  
+  if (tcp->first == 1) {
+    
+    /* Initialization PPT */
+    opj_tccp_t *tmp = tcp->tccps;
+    memcpy(tcp, j2k->default_tcp, sizeof(opj_tcp_t));
+    tcp->ppt = 0;
+    tcp->ppt_data = NULL;
+    tcp->ppt_data_first = NULL;
+    tcp->tccps = tmp;
+
+    for (i = 0; i < j2k->image->numcomps; i++) {
+      tcp->tccps[i] = j2k->default_tcp->tccps[i];
+    }
+    cp->tcps[j2k->curtileno].first = 0;
+  }
+}
+
+static void j2k_write_sod(opj_j2k_t *j2k, void *tile_coder) {
+  int l, layno;
+  int totlen;
+  opj_tcp_t *tcp = NULL;
+  opj_image_info_t *image_info = NULL;
+  
+  opj_tcd_t *tcd = (opj_tcd_t*)tile_coder;  /* cast is needed because of conflicts in header inclusions */
+  opj_cp_t *cp = j2k->cp;
+  opj_cio_t *cio = j2k->cio;
+  
+  cio_write(cio, J2K_MS_SOD, 2);
+  if (j2k->curtileno == 0) {
+    j2k->sod_start = cio_tell(cio) + j2k->pos_correction;
+  }
+  
+  /* INDEX >> */
+  image_info = j2k->image_info;
+  if (image_info && image_info->index_on) {
+    image_info->tile[j2k->curtileno].end_header = cio_tell(cio) + j2k->pos_correction - 1;
+  }
+  /* << INDEX */
+  
+  tcp = &cp->tcps[j2k->curtileno];
+  for (layno = 0; layno < tcp->numlayers; layno++) {
+    tcp->rates[layno] -= tcp->rates[layno] ? (j2k->sod_start / (cp->th * cp->tw)) : 0;
+  }
+  if(image_info) {
+    image_info->num = 0;
+  }
+  
+  l = tcd_encode_tile(tcd, j2k->curtileno, cio_getbp(cio), cio_numbytesleft(cio) - 2, image_info);
+  
+  /* Writing Psot in SOT marker */
+  totlen = cio_tell(cio) + l - j2k->sot_start;
+  cio_seek(cio, j2k->sot_start + 6);
+  cio_write(cio, totlen, 4);
+  cio_seek(cio, j2k->sot_start + totlen);
+}
+
+static void j2k_read_sod(opj_j2k_t *j2k) {
+  int len, truncate = 0, i;
+  unsigned char *data = NULL, *data_ptr = NULL;
+
+  opj_cio_t *cio = j2k->cio;
+  int curtileno = j2k->curtileno;
+  
+  len = int_min(j2k->eot - cio_getbp(cio), cio_numbytesleft(cio) + 1);
+  
+  if (len == cio_numbytesleft(cio) + 1) {
+    truncate = 1;    /* Case of a truncate codestream */
+  }
+  
+  data = (unsigned char *) opj_malloc((j2k->tile_len[curtileno] + len) * sizeof(unsigned char));
+
+  for (i = 0; i < j2k->tile_len[curtileno]; i++) {
+    data[i] = j2k->tile_data[curtileno][i];
+  }
+
+  data_ptr = data + j2k->tile_len[curtileno];
+  for (i = 0; i < len; i++) {
+    data_ptr[i] = cio_read(cio, 1);
+  }
+  
+  j2k->tile_len[curtileno] += len;
+  opj_free(j2k->tile_data[curtileno]);
+  j2k->tile_data[curtileno] = data;
+  
+  if (!truncate) {
+    j2k->state = J2K_STATE_TPHSOT;
+  } else {
+    j2k->state = J2K_STATE_NEOC;  /* RAJOUTE !! */
+  }
+}
+
+static void j2k_write_rgn(opj_j2k_t *j2k, int compno, int tileno) {
+  
+  opj_cp_t *cp = j2k->cp;
+  opj_tcp_t *tcp = &cp->tcps[tileno];
+  opj_cio_t *cio = j2k->cio;
+  int numcomps = j2k->image->numcomps;
+  
+  cio_write(cio, J2K_MS_RGN, 2);            /* RGN  */
+  cio_write(cio, numcomps <= 256 ? 5 : 6, 2);      /* Lrgn */
+  cio_write(cio, compno, numcomps <= 256 ? 1 : 2);  /* Crgn */
+  cio_write(cio, 0, 1);                /* Srgn */
+  cio_write(cio, tcp->tccps[compno].roishift, 1);    /* SPrgn */
+}
+
+static void j2k_read_rgn(opj_j2k_t *j2k) {
+  int len, compno, roisty;
+
+  opj_cp_t *cp = j2k->cp;
+  opj_tcp_t *tcp = j2k->state == J2K_STATE_TPH ? &cp->tcps[j2k->curtileno] : j2k->default_tcp;
+  opj_cio_t *cio = j2k->cio;
+  int numcomps = j2k->image->numcomps;
+
+  len = cio_read(cio, 2);                    /* Lrgn */
+  compno = cio_read(cio, numcomps <= 256 ? 1 : 2);      /* Crgn */
+  roisty = cio_read(cio, 1);                  /* Srgn */
+  tcp->tccps[compno].roishift = cio_read(cio, 1);        /* SPrgn */
+}
+
+static void j2k_write_eoc(opj_j2k_t *j2k) {
+  opj_cio_t *cio = j2k->cio;
+  /* opj_event_msg(j2k->cinfo, "%.8x: EOC\n", cio_tell(cio) + j2k->pos_correction); */
+  cio_write(cio, J2K_MS_EOC, 2);
+}
+
+static void j2k_read_eoc(opj_j2k_t *j2k) {
+  int i, tileno;
+
+#ifndef NO_PACKETS_DECODING  
+  opj_tcd_t *tcd = tcd_create(j2k->cinfo);
+  tcd_malloc_decode(tcd, j2k->image, j2k->cp);
+  for (i = 0; i < j2k->cp->tileno_size; i++) {
+    tileno = j2k->cp->tileno[i];
+    tcd_decode_tile(tcd, j2k->tile_data[tileno], j2k->tile_len[tileno], tileno);
+    opj_free(j2k->tile_data[tileno]);
+    j2k->tile_data[tileno] = NULL;
+  }
+  tcd_free_decode(tcd);
+  tcd_destroy(tcd);
+#else 
+  for (i = 0; i < j2k->cp->tileno_size; i++) {
+    tileno = j2k->cp->tileno[i];
+    opj_free(j2k->tile_data[tileno]);
+    j2k->tile_data[tileno] = NULL;
+  }
+#endif
+  
+  j2k->state = J2K_STATE_MT;
+}
+
+static void j2k_read_unk(opj_j2k_t *j2k) {
+  opj_event_msg(j2k->cinfo, EVT_WARNING, "Unknown marker\n");
+}
+
+typedef struct opj_dec_mstabent {
+  /** marker value */
+  int id;
+  /** value of the state when the marker can appear */
+  int states;
+  /** action linked to the marker */
+  void (*handler) (opj_j2k_t *j2k);
+} opj_dec_mstabent_t;
+
+opj_dec_mstabent_t j2k_dec_mstab[] = {
+  {J2K_MS_SOC, J2K_STATE_MHSOC, j2k_read_soc},
+  {J2K_MS_SOT, J2K_STATE_MH | J2K_STATE_TPHSOT, j2k_read_sot},
+  {J2K_MS_SOD, J2K_STATE_TPH, j2k_read_sod},
+  {J2K_MS_EOC, J2K_STATE_TPHSOT, j2k_read_eoc},
+  {J2K_MS_SIZ, J2K_STATE_MHSIZ, j2k_read_siz},
+  {J2K_MS_COD, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_cod},
+  {J2K_MS_COC, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_coc},
+  {J2K_MS_RGN, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_rgn},
+  {J2K_MS_QCD, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_qcd},
+  {J2K_MS_QCC, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_qcc},
+  {J2K_MS_POC, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_poc},
+  {J2K_MS_TLM, J2K_STATE_MH, j2k_read_tlm},
+  {J2K_MS_PLM, J2K_STATE_MH, j2k_read_plm},
+  {J2K_MS_PLT, J2K_STATE_TPH, j2k_read_plt},
+  {J2K_MS_PPM, J2K_STATE_MH, j2k_read_ppm},
+  {J2K_MS_PPT, J2K_STATE_TPH, j2k_read_ppt},
+  {J2K_MS_SOP, 0, 0},
+  {J2K_MS_CRG, J2K_STATE_MH, j2k_read_crg},
+  {J2K_MS_COM, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_com},
+  {0, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_unk}
+};
+
+/**
+Read the lookup table containing all the marker, status and action
+@param id Marker value
+*/
+static opj_dec_mstabent_t *j2k_dec_mstab_lookup(int id) {
+  opj_dec_mstabent_t *e;
+  for (e = j2k_dec_mstab; e->id != 0; e++) {
+    if (e->id == id) {
+      break;
+    }
+  }
+  return e;
+}
+
+/* ----------------------------------------------------------------------- */
+/* J2K / JPT decoder interface                                             */
+/* ----------------------------------------------------------------------- */
+
+opj_j2k_t* j2k_create_decompress(opj_common_ptr cinfo) {
+  opj_j2k_t *j2k = (opj_j2k_t*)opj_malloc(sizeof(opj_j2k_t));
+  if(j2k) {
+    j2k->cinfo = cinfo;
+    j2k->default_tcp = (opj_tcp_t*)opj_malloc(sizeof(opj_tcp_t));
+    if(!j2k->default_tcp) {
+      opj_free(j2k);
+      return NULL;
+    }
+  }
+  return j2k;
+}
+
+void j2k_destroy_decompress(opj_j2k_t *j2k) {
+  int i = 0;
+
+  if(j2k->tile_len != NULL) {
+    opj_free(j2k->tile_len);
+  }
+  if(j2k->tile_data != NULL) {
+    opj_free(j2k->tile_data);
+  }
+  if(j2k->default_tcp != NULL) {
+    opj_tcp_t *default_tcp = j2k->default_tcp;
+    if(default_tcp->ppt_data_first != NULL) {
+      opj_free(default_tcp->ppt_data_first);
+    }
+    if(j2k->default_tcp->tccps != NULL) {
+      opj_free(j2k->default_tcp->tccps);
+    }
+    opj_free(j2k->default_tcp);
+  }
+  if(j2k->cp != NULL) {
+    opj_cp_t *cp = j2k->cp;
+    if(cp->tcps != NULL) {
+      for(i = 0; i < cp->tw * cp->th; i++) {
+        if(cp->tcps[i].ppt_data_first != NULL) {
+          opj_free(cp->tcps[i].ppt_data_first);
+        }
+        if(cp->tcps[i].tccps != NULL) {
+          opj_free(cp->tcps[i].tccps);
+        }
+      }
+      opj_free(cp->tcps);
+    }
+    if(cp->ppm_data_first != NULL) {
+      opj_free(cp->ppm_data_first);
+    }
+    if(cp->tileno != NULL) {
+      opj_free(cp->tileno);  
+    }
+    if(cp->comment != NULL) {
+      opj_free(cp->comment);
+    }
+
+    opj_free(cp);
+  }
+
+  opj_free(j2k);
+}
+
+void j2k_setup_decoder(opj_j2k_t *j2k, opj_dparameters_t *parameters) {
+  if(j2k && parameters) {
+    /* create and initialize the coding parameters structure */
+    opj_cp_t *cp = (opj_cp_t*)opj_malloc(sizeof(opj_cp_t));
+    cp->reduce = parameters->cp_reduce;  
+    cp->layer = parameters->cp_layer;
+
+    /* keep a link to cp so that we can destroy it later in j2k_destroy_decompress */
+    j2k->cp = cp;
+  }
+}
+
+opj_image_t* j2k_decode(opj_j2k_t *j2k, opj_cio_t *cio) {
+  opj_image_t *image = NULL;
+
+  opj_common_ptr cinfo = j2k->cinfo;
+
+  j2k->cio = cio;
+
+  /* create an empty image */
+  image = opj_image_create0();
+  j2k->image = image;
+
+  j2k->state = J2K_STATE_MHSOC;
+
+  for (;;) {
+    opj_dec_mstabent_t *e;
+    int id = cio_read(cio, 2);
+    if (id >> 8 != 0xff) {
+      opj_image_destroy(image);
+      opj_event_msg(cinfo, EVT_ERROR, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id);
+      return 0;
+    }
+    e = j2k_dec_mstab_lookup(id);
+    if (!(j2k->state & e->states)) {
+      opj_image_destroy(image);
+      opj_event_msg(cinfo, EVT_ERROR, "%.8x: unexpected marker %x\n", cio_tell(cio) - 2, id);
+      return 0;
+    }
+    if (e->handler) {
+      (*e->handler)(j2k);
+    }
+    if (j2k->state == J2K_STATE_MT) {
+      break;
+    }
+    if (j2k->state == J2K_STATE_NEOC) {
+      break;
+    }
+  }
+  if (j2k->state == J2K_STATE_NEOC) {
+    j2k_read_eoc(j2k);
+  }
+
+  if (j2k->state != J2K_STATE_MT) {
+    opj_event_msg(cinfo, EVT_WARNING, "Incomplete bitstream\n");
+  }
+
+  return image;
+}
+
+/*
+* Read a JPT-stream and decode file
+*
+*/
+opj_image_t* j2k_decode_jpt_stream(opj_j2k_t *j2k, opj_cio_t *cio) {
+  opj_image_t *image = NULL;
+  opj_jpt_msg_header_t header;
+  int position;
+
+  opj_common_ptr cinfo = j2k->cinfo;
+  
+  j2k->cio = cio;
+
+  /* create an empty image */
+  image = opj_image_create0();
+
+  j2k->state = J2K_STATE_MHSOC;
+  
+  /* Initialize the header */
+  jpt_init_msg_header(&header);
+  /* Read the first header of the message */
+  jpt_read_msg_header(cinfo, cio, &header);
+  
+  position = cio_tell(cio);
+  if (header.Class_Id != 6) {  /* 6 : Main header data-bin message */
+    opj_image_destroy(image);
+    opj_event_msg(cinfo, EVT_ERROR, "[JPT-stream] : Expecting Main header first [class_Id %d] !\n", header.Class_Id);
+    return 0;
+  }
+  
+  for (;;) {
+    opj_dec_mstabent_t *e = NULL;
+    int id;
+    
+    if (!cio_numbytesleft(cio)) {
+      j2k_read_eoc(j2k);
+      return image;
+    }
+    /* data-bin read -> need to read a new header */
+    if ((unsigned int) (cio_tell(cio) - position) == header.Msg_length) {
+      jpt_read_msg_header(cinfo, cio, &header);
+      position = cio_tell(cio);
+      if (header.Class_Id != 4) {  /* 4 : Tile data-bin message */
+        opj_image_destroy(image);
+        opj_event_msg(cinfo, EVT_ERROR, "[JPT-stream] : Expecting Tile info !\n");
+        return 0;
+      }
+    }
+    
+    id = cio_read(cio, 2);
+    if (id >> 8 != 0xff) {
+      opj_image_destroy(image);
+      opj_event_msg(cinfo, EVT_ERROR, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id);
+      return 0;
+    }
+    e = j2k_dec_mstab_lookup(id);
+    if (!(j2k->state & e->states)) {
+      opj_image_destroy(image);
+      opj_event_msg(cinfo, EVT_ERROR, "%.8x: unexpected marker %x\n", cio_tell(cio) - 2, id);
+      return 0;
+    }
+    if (e->handler) {
+      (*e->handler)(j2k);
+    }
+    if (j2k->state == J2K_STATE_MT) {
+      break;
+    }
+    if (j2k->state == J2K_STATE_NEOC) {
+      break;
+    }
+  }
+  if (j2k->state == J2K_STATE_NEOC) {
+    j2k_read_eoc(j2k);
+  }
+  
+  if (j2k->state != J2K_STATE_MT) {
+    opj_event_msg(cinfo, EVT_WARNING, "Incomplete bitstream\n");
+  }
+
+  return image;
+}
+
+/* ----------------------------------------------------------------------- */
+/* J2K encoder interface                                                       */
+/* ----------------------------------------------------------------------- */
+
+opj_j2k_t* j2k_create_compress(opj_common_ptr cinfo) {
+  opj_j2k_t *j2k = (opj_j2k_t*)opj_malloc(sizeof(opj_j2k_t));
+  if(j2k) {
+    j2k->cinfo = cinfo;
+  }
+  return j2k;
+}
+
+void j2k_destroy_compress(opj_j2k_t *j2k) {
+  int tileno;
+
+  if(!j2k) return;
+
+  if(j2k->image_info != NULL) {
+    opj_image_info_t *image_info = j2k->image_info;
+    if (image_info->index_on && j2k->cp) {
+      opj_cp_t *cp = j2k->cp;
+      for (tileno = 0; tileno < cp->tw * cp->th; tileno++) {
+        opj_tile_info_t *tile_info = &image_info->tile[tileno];
+        opj_free(tile_info->thresh);
+        opj_free(tile_info->packet);
+      }
+      opj_free(image_info->tile);
+    }
+    opj_free(image_info);
+  }
+  if(j2k->cp != NULL) {
+    opj_cp_t *cp = j2k->cp;
+
+    if(cp->comment) {
+      opj_free(cp->comment);
+    }
+    if(cp->matrice) {
+      opj_free(cp->matrice);
+    }
+    for (tileno = 0; tileno < cp->tw * cp->th; tileno++) {
+      opj_free(cp->tcps[tileno].tccps);
+    }
+    opj_free(cp->tcps);
+    opj_free(cp);
+  }
+
+  opj_free(j2k);
+}
+
+void j2k_setup_encoder(opj_j2k_t *j2k, opj_cparameters_t *parameters, opj_image_t *image) {
+  int i, j, tileno, numpocs_tile;
+  opj_cp_t *cp = NULL;
+
+  if(!j2k || !parameters || ! image) {
+    return;
+  }
+
+  /* create and initialize the coding parameters structure */
+  cp = (opj_cp_t*)opj_malloc(sizeof(opj_cp_t));
+
+  /* keep a link to cp so that we can destroy it later in j2k_destroy_compress */
+  j2k->cp = cp;
+
+  /* set default values for cp */
+  cp->tw = 1;
+  cp->th = 1;
+
+  /* 
+  copy user encoding parameters 
+  */
+
+  cp->disto_alloc = parameters->cp_disto_alloc;
+  cp->fixed_alloc = parameters->cp_fixed_alloc;
+  cp->fixed_quality = parameters->cp_fixed_quality;
+
+  /* mod fixed_quality */
+  if(parameters->cp_matrice) {
+    size_t array_size = parameters->tcp_numlayers * parameters->numresolution * 3 * sizeof(int);
+    cp->matrice = (int *) opj_malloc(array_size);
+    memcpy(cp->matrice, parameters->cp_matrice, array_size);
+  }
+
+  /* creation of an index file ? */
+  cp->index_on = parameters->index_on;
+  if(cp->index_on) {
+    j2k->image_info = (opj_image_info_t*)opj_malloc(sizeof(opj_image_info_t));
+  }
+
+  /* tiles */
+  cp->tdx = parameters->cp_tdx;
+  cp->tdy = parameters->cp_tdy;
+
+  /* tile offset */
+  cp->tx0 = parameters->cp_tx0;
+  cp->ty0 = parameters->cp_ty0;
+
+  /* comment string */
+  if(parameters->cp_comment) {
+    cp->comment = (char*)opj_malloc(strlen(parameters->cp_comment) + 1);
+    if(cp->comment) {
+      strcpy(cp->comment, parameters->cp_comment);
+    }
+  }
+
+  /*
+  calculate other encoding parameters
+  */
+
+  if (parameters->tile_size_on) {
+    cp->tw = int_ceildiv(image->x1 - cp->tx0, cp->tdx);
+    cp->th = int_ceildiv(image->y1 - cp->ty0, cp->tdy);
+  } else {
+    cp->tdx = image->x1 - cp->tx0;
+    cp->tdy = image->y1 - cp->ty0;
+  }
+
+  /* initialize the mutiple tiles */
+  /* ---------------------------- */
+  cp->tcps = (opj_tcp_t *) opj_malloc(cp->tw * cp->th * sizeof(opj_tcp_t));
+
+  for (tileno = 0; tileno < cp->tw * cp->th; tileno++) {
+    opj_tcp_t *tcp = &cp->tcps[tileno];
+    tcp->numlayers = parameters->tcp_numlayers;
+    for (j = 0; j < tcp->numlayers; j++) {
+      if (cp->fixed_quality) {  /* add fixed_quality */
+        tcp->distoratio[j] = parameters->tcp_distoratio[j];
+      } else {
+        tcp->rates[j] = parameters->tcp_rates[j];
+      }
+    }
+    tcp->csty = parameters->csty;
+    tcp->prg = parameters->prog_order;
+    tcp->mct = image->numcomps == 3 ? 1 : 0;
+
+    numpocs_tile = 0;
+    tcp->POC = 0;
+    if (parameters->numpocs) {
+      /* initialisation of POC */
+      tcp->POC = 1;
+      for (i = 0; i < parameters->numpocs; i++) {
+        if((tileno == parameters->POC[i].tile - 1) || (parameters->POC[i].tile == -1)) {
+          opj_poc_t *tcp_poc = &tcp->pocs[numpocs_tile];
+          tcp_poc->resno0    = parameters->POC[numpocs_tile].resno0;
+          tcp_poc->compno0  = parameters->POC[numpocs_tile].compno0;
+          tcp_poc->layno1    = parameters->POC[numpocs_tile].layno1;
+          tcp_poc->resno1    = parameters->POC[numpocs_tile].resno1;
+          tcp_poc->compno1  = parameters->POC[numpocs_tile].compno1;
+          tcp_poc->prg    = parameters->POC[numpocs_tile].prg;
+          tcp_poc->tile    = parameters->POC[numpocs_tile].tile;
+          numpocs_tile++;
+        }
+      }
+    }
+    tcp->numpocs = numpocs_tile;
+
+    tcp->tccps = (opj_tccp_t *) opj_malloc(image->numcomps * sizeof(opj_tccp_t));
+    
+    for (i = 0; i < image->numcomps; i++) {
+      opj_tccp_t *tccp = &tcp->tccps[i];
+      tccp->csty = parameters->csty & 0x01;  /* 0 => one precinct || 1 => custom precinct  */
+      tccp->numresolutions = parameters->numresolution;
+      tccp->cblkw = int_floorlog2(parameters->cblockw_init);
+      tccp->cblkh = int_floorlog2(parameters->cblockh_init);
+      tccp->cblksty = parameters->mode;
+      tccp->qmfbid = parameters->irreversible ? 0 : 1;
+      tccp->qntsty = parameters->irreversible ? J2K_CCP_QNTSTY_SEQNT : J2K_CCP_QNTSTY_NOQNT;
+      tccp->numgbits = 2;
+      if (i == parameters->roi_compno) {
+        tccp->roishift = parameters->roi_shift;
+      } else {
+        tccp->roishift = 0;
+      }
+      if (parameters->csty & J2K_CCP_CSTY_PRT) {
+        int p = 0;
+        for (j = tccp->numresolutions - 1; j >= 0; j--) {
+          if (p < parameters->res_spec) {
+            if (parameters->prcw_init[p] < 1) {
+              tccp->prcw[j] = 1;
+            } else {
+              tccp->prcw[j] = int_floorlog2(parameters->prcw_init[p]);
+            }
+            if (parameters->prch_init[p] < 1) {
+              tccp->prch[j] = 1;
+            } else {
+              tccp->prch[j] = int_floorlog2(parameters->prch_init[p]);
+            }
+          } else {
+            int res_spec = parameters->res_spec;
+            int size_prcw = parameters->prcw_init[res_spec - 1] >> (p - (res_spec - 1));
+            int size_prch = parameters->prch_init[res_spec - 1] >> (p - (res_spec - 1));
+            if (size_prcw < 1) {
+              tccp->prcw[j] = 1;
+            } else {
+              tccp->prcw[j] = int_floorlog2(size_prcw);
+            }
+            if (size_prch < 1) {
+              tccp->prch[j] = 1;
+            } else {
+              tccp->prch[j] = int_floorlog2(size_prch);
+            }
+          }
+          p++;
+          /*printf("\nsize precinct for level %d : %d,%d\n", j,tccp->prcw[j], tccp->prch[j]); */
+        }
+      } else {
+        for (j = 0; j < tccp->numresolutions; j++) {
+          tccp->prcw[j] = 15;
+          tccp->prch[j] = 15;
+        }
+      }
+
+      dwt_calc_explicit_stepsizes(tccp, image->comps[i].prec);
+    }
+  }
+}
+
+/**
+Create an index file
+@param j2k
+@param cio
+@param image_info
+@param index Index filename
+@return Returns 1 if successful, returns 0 otherwise
+*/
+static int j2k_create_index(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_info_t *image_info, char *index) {
+  int tileno, compno, layno, resno, precno, pack_nb, x, y;
+  FILE *stream = NULL;
+  double total_disto = 0;
+
+  image_info->codestream_size = cio_tell(cio) + j2k->pos_correction;  /* Correction 14/4/03 suite rmq de Patrick */
+
+  stream = fopen(index, "w");
+  if (!stream) {
+    opj_event_msg(j2k->cinfo, EVT_ERROR, "failed to open %s for writing\n", index);
+    return 0;
+  }
+  
+  fprintf(stream, "%d %d\n", image_info->image_w, image_info->image_h);
+  fprintf(stream, "%d\n", image_info->prog);
+  fprintf(stream, "%d %d\n", image_info->tile_x, image_info->tile_y);
+  fprintf(stream, "%d %d\n", image_info->tw, image_info->th);
+  fprintf(stream, "%d\n", image_info->comp);
+  fprintf(stream, "%d\n", image_info->layer);
+  fprintf(stream, "%d\n", image_info->decomposition);
+  
+  for (resno = image_info->decomposition; resno >= 0; resno--) {
+    fprintf(stream, "[%d,%d] ", 
+      (1 << image_info->tile[0].pdx[resno]), (1 << image_info->tile[0].pdx[resno]));  /* based on tile 0 */
+  }
+  fprintf(stream, "\n");
+  fprintf(stream, "%d\n", image_info->main_head_end);
+  fprintf(stream, "%d\n", image_info->codestream_size);
+  
+  for (tileno = 0; tileno < image_info->tw * image_info->th; tileno++) {
+    fprintf(stream, "%4d %9d %9d %9d %9e %9d %9e\n",
+      image_info->tile[tileno].num_tile,
+      image_info->tile[tileno].start_pos,
+      image_info->tile[tileno].end_header,
+      image_info->tile[tileno].end_pos,
+      image_info->tile[tileno].distotile, image_info->tile[tileno].nbpix,
+      image_info->tile[tileno].distotile / image_info->tile[tileno].nbpix);
+  }
+  
+  for (tileno = 0; tileno < image_info->tw * image_info->th; tileno++) {
+    int start_pos, end_pos;
+    double disto = 0;
+    pack_nb = 0;
+    
+    /*
+    fprintf(stream, "pkno tileno layerno resno compno precno start_pos   end_pos       deltaSE        \n");
+    */
+    
+    if (image_info->prog == LRCP) {  /* LRCP */
+      /*
+      fprintf(stream, "pack_nb tileno layno resno compno precno start_pos  end_pos   disto");
+      */
+      for (layno = 0; layno < image_info->layer; layno++) {
+        for (resno = 0; resno < image_info->decomposition + 1; resno++) {
+          for (compno = 0; compno < image_info->comp; compno++) {
+            int prec_max = image_info->tile[tileno].pw[resno] * image_info->tile[tileno].ph[resno];
+            for (precno = 0; precno < prec_max; precno++) {
+              start_pos = image_info->tile[tileno].packet[pack_nb].start_pos;
+              end_pos = image_info->tile[tileno].packet[pack_nb].end_pos;
+              disto = image_info->tile[tileno].packet[pack_nb].disto;
+              fprintf(stream, "%4d %6d %7d %5d %6d %6d %9d %9d %8e\n",
+                pack_nb, tileno, layno, resno, compno, precno, start_pos, end_pos, disto);
+              total_disto += disto;
+              pack_nb++;
+            }
+          }
+        }
+      }
+    } /* LRCP */
+    else if (image_info->prog == RLCP) {  /* RLCP */
+      /*
+      fprintf(stream, "pack_nb tileno resno layno compno precno start_pos  end_pos   disto");
+      */
+      for (resno = 0; resno < image_info->decomposition + 1; resno++) {
+        for (layno = 0; layno < image_info->layer; layno++) {
+          for (compno = 0; compno < image_info->comp; compno++) {
+            int prec_max = image_info->tile[tileno].pw[resno] * image_info->tile[tileno].ph[resno];
+            for (precno = 0; precno < prec_max; precno++) {
+              start_pos = image_info->tile[tileno].packet[pack_nb].start_pos;
+              end_pos = image_info->tile[tileno].packet[pack_nb].end_pos;
+              disto = image_info->tile[tileno].packet[pack_nb].disto;
+              fprintf(stream, "%4d %6d %5d %7d %6d %6d %9d %9d %8e\n",
+                pack_nb, tileno, resno, layno, compno, precno, start_pos, end_pos, disto);
+              total_disto += disto;
+              pack_nb++;
+            }
+          }
+        }
+      }
+    } /* RLCP */
+    else if (image_info->prog == RPCL) {  /* RPCL */
+      /*
+      fprintf(stream, "\npack_nb tileno resno precno compno layno start_pos  end_pos   disto\n"); 
+      */
+      for (resno = 0; resno < image_info->decomposition + 1; resno++) {
+        /* I suppose components have same XRsiz, YRsiz */
+        int x0 = image_info->tile_Ox + tileno - (int)floor( (float)tileno/(float)image_info->tw ) * image_info->tw * image_info->tile_x;
+        int y0 = image_info->tile_Ox + (int)floor( (float)tileno/(float)image_info->tw ) * image_info->tile_y;
+        int x1 = x0 + image_info->tile_x;
+        int y1 = y0 + image_info->tile_y;
+        for(y = y0; y < y1; y++) {
+          for(x = x0; x < x1; x++) {
+            for (compno = 0; compno < image_info->comp; compno++) {
+              int prec_max = image_info->tile[tileno].pw[resno] * image_info->tile[tileno].ph[resno];
+              for (precno = 0; precno < prec_max; precno++) {
+                int pcnx = image_info->tile[tileno].pw[resno];
+                int pcx = (int) pow( 2, image_info->tile[tileno].pdx[resno] + image_info->decomposition - resno );
+                int pcy = (int) pow( 2, image_info->tile[tileno].pdy[resno] + image_info->decomposition - resno );
+                int precno_x = precno - (int) floor( (float)precno/(float)pcnx ) * pcnx;
+                int precno_y = (int) floor( (float)precno/(float)pcnx );
+                if (precno_y*pcy == y ) {
+                  if (precno_x*pcx == x ) {
+                    for (layno = 0; layno < image_info->layer; layno++) {
+                      start_pos = image_info->tile[tileno].packet[pack_nb].start_pos;
+                      end_pos = image_info->tile[tileno].packet[pack_nb].end_pos;
+                      disto = image_info->tile[tileno].packet[pack_nb].disto;
+                      fprintf(stream, "%4d %6d %5d %6d %6d %7d %9d %9d %8e\n",
+                        pack_nb, tileno, resno, precno, compno, layno, start_pos, end_pos, disto); 
+                      total_disto += disto;
+                      pack_nb++; 
+                    }
+                  }
+                }
+              } /* precno */
+            } /* compno */
+          } /* x = x0..x1 */
+        } /* y = y0..y1 */
+      } /* resno */
+    } /* RPCL */
+    else if (image_info->prog == PCRL) {  /* PCRL */
+      /* I suppose components have same XRsiz, YRsiz */
+      int x0 = image_info->tile_Ox + tileno - (int)floor( (float)tileno/(float)image_info->tw ) * image_info->tw * image_info->tile_x;
+      int y0 = image_info->tile_Ox + (int)floor( (float)tileno/(float)image_info->tw ) * image_info->tile_y;
+      int x1 = x0 + image_info->tile_x;
+      int y1 = y0 + image_info->tile_y;
+      /*
+      fprintf(stream, "\npack_nb tileno precno compno resno layno start_pos  end_pos   disto\n"); 
+      */
+      for(y = y0; y < y1; y++) {
+        for(x = x0; x < x1; x++) {
+          for (compno = 0; compno < image_info->comp; compno++) {
+            for (resno = 0; resno < image_info->decomposition + 1; resno++) {
+              int prec_max = image_info->tile[tileno].pw[resno] * image_info->tile[tileno].ph[resno];
+              for (precno = 0; precno < prec_max; precno++) {
+                int pcnx = image_info->tile[tileno].pw[resno];
+                int pcx = (int) pow( 2, image_info->tile[tileno].pdx[resno] + image_info->decomposition - resno );
+                int pcy = (int) pow( 2, image_info->tile[tileno].pdy[resno] + image_info->decomposition - resno );
+                int precno_x = precno - (int) floor( (float)precno/(float)pcnx ) * pcnx;
+                int precno_y = (int) floor( (float)precno/(float)pcnx );
+                if (precno_y*pcy == y ) {
+                  if (precno_x*pcx == x ) {
+                    for (layno = 0; layno < image_info->layer; layno++) {
+                      start_pos = image_info->tile[tileno].packet[pack_nb].start_pos;
+                      end_pos = image_info->tile[tileno].packet[pack_nb].end_pos;
+                      disto = image_info->tile[tileno].packet[pack_nb].disto;
+                      fprintf(stream, "%4d %6d %6d %6d %5d %7d %9d %9d %8e\n",
+                        pack_nb, tileno, precno, compno, resno, layno, start_pos, end_pos, disto); 
+                      total_disto += disto;
+                      pack_nb++; 
+                    }
+                  }
+                }
+              } /* precno */
+            } /* resno */
+          } /* compno */
+        } /* x = x0..x1 */
+      } /* y = y0..y1 */
+    } /* PCRL */
+    else {  /* CPRL */
+      /*
+      fprintf(stream, "\npack_nb tileno compno precno resno layno start_pos  end_pos   disto\n"); 
+      */
+      for (compno = 0; compno < image_info->comp; compno++) {
+        /* I suppose components have same XRsiz, YRsiz */
+        int x0 = image_info->tile_Ox + tileno - (int)floor( (float)tileno/(float)image_info->tw ) * image_info->tw * image_info->tile_x;
+        int y0 = image_info->tile_Ox + (int)floor( (float)tileno/(float)image_info->tw ) * image_info->tile_y;
+        int x1 = x0 + image_info->tile_x;
+        int y1 = y0 + image_info->tile_y;
+        for(y = y0; y < y1; y++) {
+          for(x = x0; x < x1; x++) {
+            for (resno = 0; resno < image_info->decomposition + 1; resno++) {
+              int prec_max = image_info->tile[tileno].pw[resno] * image_info->tile[tileno].ph[resno];
+              for (precno = 0; precno < prec_max; precno++) {
+                int pcnx = image_info->tile[tileno].pw[resno];
+                int pcx = (int) pow( 2, image_info->tile[tileno].pdx[resno] + image_info->decomposition - resno );
+                int pcy = (int) pow( 2, image_info->tile[tileno].pdy[resno] + image_info->decomposition - resno );
+                int precno_x = precno - (int) floor( (float)precno/(float)pcnx ) * pcnx;
+                int precno_y = (int) floor( (float)precno/(float)pcnx );
+                if (precno_y*pcy == y ) {
+                  if (precno_x*pcx == x ) {
+                    for (layno = 0; layno < image_info->layer; layno++) {
+                      start_pos = image_info->tile[tileno].packet[pack_nb].start_pos;
+                      end_pos = image_info->tile[tileno].packet[pack_nb].end_pos;
+                      disto = image_info->tile[tileno].packet[pack_nb].disto;
+                      fprintf(stream, "%4d %6d %6d %6d %5d %7d %9d %9d %8e\n",
+                        pack_nb, tileno, compno, precno, resno, layno, start_pos, end_pos, disto); 
+                      total_disto += disto;
+                      pack_nb++; 
+                    }
+                  }
+                }
+              } /* precno */
+            } /* resno */
+          } /* x = x0..x1 */
+        } /* y = y0..y1 */
+      } /* comno */
+    } /* CPRL */   
+  } /* tileno */
+  
+  fprintf(stream, "%8e\n", image_info->D_max); /* SE max */
+  fprintf(stream, "%.8e\n", total_disto);  /* SE totale */
+  fclose(stream);
+
+  return 1;
+}
+
+bool j2k_encode(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image, char *index) {
+  int tileno, compno;
+  opj_image_info_t *image_info = NULL;
+  opj_cp_t *cp = NULL;
+
+  opj_tcd_t *tcd = NULL;  /* TCD component */
+
+  j2k->cio = cio;  
+  j2k->image = image;
+
+  cp = j2k->cp;
+
+  /* j2k_dump_cp(stdout, image, cp); */
+
+  /* INDEX >> */
+  image_info = j2k->image_info;
+  if (image_info && cp->index_on) {
+    image_info->index_on = cp->index_on;
+    image_info->tile = (opj_tile_info_t *) opj_malloc(cp->tw * cp->th * sizeof(opj_tile_info_t));
+    image_info->image_w = image->x1 - image->x0;
+    image_info->image_h = image->y1 - image->y0;
+    image_info->prog = (&cp->tcps[0])->prg;
+    image_info->tw = cp->tw;
+    image_info->th = cp->th;
+    image_info->tile_x = cp->tdx;  /* new version parser */
+    image_info->tile_y = cp->tdy;  /* new version parser */
+    image_info->tile_Ox = cp->tx0;  /* new version parser */
+    image_info->tile_Oy = cp->ty0;  /* new version parser */
+    image_info->comp = image->numcomps;
+    image_info->layer = (&cp->tcps[0])->numlayers;
+    image_info->decomposition = (&cp->tcps[0])->tccps->numresolutions - 1;
+    image_info->D_max = 0;    /* ADD Marcela */
+  }
+  /* << INDEX */
+  
+  j2k_write_soc(j2k);
+  j2k_write_siz(j2k);
+  j2k_write_cod(j2k);
+  j2k_write_qcd(j2k);
+  for (compno = 0; compno < image->numcomps; compno++) {
+    opj_tcp_t *tcp = &cp->tcps[0];
+    if (tcp->tccps[compno].roishift)
+      j2k_write_rgn(j2k, compno, 0);
+  }
+  if (cp->comment != NULL) {
+    j2k_write_com(j2k);
+  }
+  /* INDEX >> */
+  if(image_info && image_info->index_on) {
+    image_info->main_head_end = cio_tell(cio) - 1;
+  }
+  /* << INDEX */
+
+  /* create the tile encoder */
+  tcd = tcd_create(j2k->cinfo);
+
+  /* encode each tile */
+
+  for (tileno = 0; tileno < cp->tw * cp->th; tileno++) {
+    opj_event_msg(j2k->cinfo, EVT_INFO, "tile number %d / %d\n", tileno + 1, cp->tw * cp->th);
+    
+    j2k->curtileno = tileno;
+
+    /* initialisation before tile encoding  */
+    if (tileno == 0) {
+      tcd_malloc_encode(tcd, image, cp, j2k->curtileno);
+    } else {
+      tcd_init_encode(tcd, image, cp, j2k->curtileno);
+    }
+    
+    /* INDEX >> */
+    if(image_info && image_info->index_on) {
+      image_info->tile[j2k->curtileno].num_tile = j2k->curtileno;
+      image_info->tile[j2k->curtileno].start_pos = cio_tell(cio) + j2k->pos_correction;
+    }
+    /* << INDEX */
+
+    j2k_write_sot(j2k);
+    
+    for (compno = 1; compno < image->numcomps; compno++) {
+      j2k_write_coc(j2k, compno);
+      j2k_write_qcc(j2k, compno);
+    }
+    if (cp->tcps[tileno].numpocs) {
+      j2k_write_poc(j2k);
+    }
+
+    j2k_write_sod(j2k, tcd);
+    
+    /* INDEX >> */
+    if(image_info && image_info->index_on) {
+      image_info->tile[j2k->curtileno].end_pos = cio_tell(cio) + j2k->pos_correction - 1;
+    }
+    /* << INDEX */
+    
+    
+    /*
+    if (tile->PPT) { // BAD PPT !!! 
+      FILE *PPT_file;
+      int i;
+      PPT_file=fopen("PPT","rb");
+      fprintf(stderr,"%c%c%c%c",255,97,tile->len_ppt/256,tile->len_ppt%256);
+      for (i=0;i<tile->len_ppt;i++) {
+        unsigned char elmt;
+        fread(&elmt, 1, 1, PPT_file);
+        fwrite(&elmt,1,1,f);
+      }
+      fclose(PPT_file);
+      unlink("PPT");
+    }
+    */
+    
+  }
+  
+  /* destroy the tile encoder */
+  tcd_free_encode(tcd);
+  tcd_destroy(tcd);
+
+  j2k_write_eoc(j2k);
+  
+  /* Creation of the index file */
+  if(image_info && image_info->index_on) {
+    if(!j2k_create_index(j2k, cio, image_info, index)) {
+      opj_event_msg(j2k->cinfo, EVT_ERROR, "failed to create index file %s\n", index);
+      return false;
+    }
+  }
+    
+  return true;
+}
+
diff --git a/Utilities/ITK/Utilities/openjpeg/j2k.h b/Utilities/ITK/Utilities/openjpeg/j2k.h
new file mode 100644
index 0000000000..225c3cd3ca
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/j2k.h
@@ -0,0 +1,429 @@
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __J2K_H
+#define __J2K_H
+/**
+@file j2k.h
+@brief The JPEG-2000 Codestream Reader/Writer (J2K)
+
+The functions in J2K.C have for goal to read/write the several parts of the codestream: markers and data.
+*/
+
+/** @defgroup J2K J2K - JPEG-2000 codestream reader/writer */
+/*@{*/
+
+#define J2K_CP_CSTY_PRT 0x01
+#define J2K_CP_CSTY_SOP 0x02
+#define J2K_CP_CSTY_EPH 0x04
+#define J2K_CCP_CSTY_PRT 0x01
+#define J2K_CCP_CBLKSTY_LAZY 0x01
+#define J2K_CCP_CBLKSTY_RESET 0x02
+#define J2K_CCP_CBLKSTY_TERMALL 0x04
+#define J2K_CCP_CBLKSTY_VSC 0x08
+#define J2K_CCP_CBLKSTY_PTERM 0x10
+#define J2K_CCP_CBLKSTY_SEGSYM 0x20
+#define J2K_CCP_QNTSTY_NOQNT 0
+#define J2K_CCP_QNTSTY_SIQNT 1
+#define J2K_CCP_QNTSTY_SEQNT 2
+
+/* ----------------------------------------------------------------------- */
+
+#define J2K_MS_SOC 0xff4f  /**< SOC marker value */
+#define J2K_MS_SOT 0xff90  /**< SOT marker value */
+#define J2K_MS_SOD 0xff93  /**< SOD marker value */
+#define J2K_MS_EOC 0xffd9  /**< EOC marker value */
+#define J2K_MS_SIZ 0xff51  /**< SIZ marker value */
+#define J2K_MS_COD 0xff52  /**< COD marker value */
+#define J2K_MS_COC 0xff53  /**< COC marker value */
+#define J2K_MS_RGN 0xff5e  /**< RGN marker value */
+#define J2K_MS_QCD 0xff5c  /**< QCD marker value */
+#define J2K_MS_QCC 0xff5d  /**< QCC marker value */
+#define J2K_MS_POC 0xff5f  /**< POC marker value */
+#define J2K_MS_TLM 0xff55  /**< TLM marker value */
+#define J2K_MS_PLM 0xff57  /**< PLM marker value */
+#define J2K_MS_PLT 0xff58  /**< PLT marker value */
+#define J2K_MS_PPM 0xff60  /**< PPM marker value */
+#define J2K_MS_PPT 0xff61  /**< PPT marker value */
+#define J2K_MS_SOP 0xff91  /**< SOP marker value */
+#define J2K_MS_EPH 0xff92  /**< EPH marker value */
+#define J2K_MS_CRG 0xff63  /**< CRG marker value */
+#define J2K_MS_COM 0xff64  /**< COM marker value */
+
+/* ----------------------------------------------------------------------- */
+
+/**
+Values that specify the status of the decoding process when decoding the main header. 
+These values may be combined with a | operator. 
+*/
+typedef enum J2K_STATUS {
+  J2K_STATE_MHSOC  = 0x0001, /**< a SOC marker is expected */
+  J2K_STATE_MHSIZ  = 0x0002, /**< a SIZ marker is expected */
+  J2K_STATE_MH     = 0x0004, /**< the decoding process is in the main header */
+  J2K_STATE_TPHSOT = 0x0008, /**< the decoding process is in a tile part header and expects a SOT marker */
+  J2K_STATE_TPH    = 0x0010, /**< the decoding process is in a tile part header */
+  J2K_STATE_MT     = 0x0020, /**< the EOC marker has just been read */
+  J2K_STATE_NEOC   = 0x0040  /**< the decoding process must not expect a EOC marker because the codestream is truncated */
+} J2K_STATUS;
+
+/* ----------------------------------------------------------------------- */
+
+/**
+Quantization stepsize
+*/
+typedef struct opj_stepsize {
+  /** exponent */
+  int expn;
+  /** mantissa */
+  int mant;
+} opj_stepsize_t;
+
+/**
+Tile-component coding parameters
+*/
+typedef struct opj_tccp {
+  /** coding style */
+  int csty;
+  /** number of resolutions */
+  int numresolutions;
+  /** code-blocks width */
+  int cblkw;
+  /** code-blocks height */
+  int cblkh;
+  /** code-block coding style */
+  int cblksty;
+  /** discrete wavelet transform identifier */
+  int qmfbid;
+  /** quantisation style */
+  int qntsty;
+  /** stepsizes used for quantization */
+  opj_stepsize_t stepsizes[J2K_MAXBANDS];
+  /** number of guard bits */
+  int numgbits;
+  /** Region Of Interest shift */
+  int roishift;
+  /** precinct width */
+  int prcw[J2K_MAXRLVLS];
+  /** precinct height */
+  int prch[J2K_MAXRLVLS];  
+} opj_tccp_t;
+
+/**
+Tile coding parameters : 
+this structure is used to store coding/decoding parameters common to all
+tiles (information like COD, COC in main header)
+*/
+typedef struct opj_tcp {
+  /** 1 : first part-tile of a tile */
+  int first;
+  /** coding style */
+  int csty;
+  /** progression order */
+  OPJ_PROG_ORDER prg;
+  /** number of layers */
+  int numlayers;
+  /** multi-component transform identifier */
+  int mct;
+  /** rates of layers */
+  int rates[100];
+  /** number of progression order changes */
+  int numpocs;
+  /** indicates if a POC marker has been used O:NO, 1:YES */
+  int POC;
+  /** progression order changes */
+  opj_poc_t pocs[32];
+  /** packet header store there for futur use in t2_decode_packet */
+  unsigned char *ppt_data;
+  /** pointer remaining on the first byte of the first header if ppt is used */
+  unsigned char *ppt_data_first;
+  /** If ppt == 1 --> there was a PPT marker for the present tile */
+  int ppt;
+  /** used in case of multiple marker PPT (number of info already stored) */
+  int ppt_store;
+  /** ppmbug1 */
+  int ppt_len;
+  /** add fixed_quality */
+  float distoratio[100];
+  /** tile-component coding parameters */
+  opj_tccp_t *tccps;
+} opj_tcp_t;
+
+/**
+Coding parameters
+*/
+typedef struct opj_cp {
+  /** allocation by rate/distortion */
+  int disto_alloc;
+  /** allocation by fixed layer */
+  int fixed_alloc;
+  /** add fixed_quality */
+  int fixed_quality;
+  /** if != 0, then original dimension divided by 2^(reduce); if == 0 or not used, image is decoded to the full resolution */
+  int reduce;
+  /** if != 0, then only the first "layer" layers are decoded; if == 0 or not used, all the quality layers are decoded */
+  int layer;
+  /** 0 = no index || 1 = index */
+  int index_on;
+  /** XTOsiz */
+  int tx0;
+  /** YTOsiz */
+  int ty0;
+  /** XTsiz */
+  int tdx;
+  /** YTsiz */
+  int tdy;
+  /** comment for coding */
+  char *comment;
+  /** number of tiles in width */
+  int tw;
+  /** number of tiles in heigth */
+  int th;
+  /** ID number of the tiles present in the codestream */
+  int *tileno;
+  /** size of the vector tileno */
+  int tileno_size;
+  /** packet header store there for futur use in t2_decode_packet */
+  unsigned char *ppm_data;
+  /** pointer remaining on the first byte of the first header if ppm is used */
+  unsigned char *ppm_data_first;
+  /** if ppm == 1 --> there was a PPM marker for the present tile */
+  int ppm;
+  /** use in case of multiple marker PPM (number of info already store) */
+  int ppm_store;
+  /** use in case of multiple marker PPM (case on non-finished previous info) */
+  int ppm_previous;
+  /** ppmbug1 */
+  int ppm_len;
+  /** tile coding parameters */
+  opj_tcp_t *tcps;
+  /** fixed layer */
+  int *matrice;
+} opj_cp_t;
+
+/**
+Information concerning a packet inside tile
+*/
+typedef struct opj_packet_info {
+  /** start position */
+  int start_pos;
+  /** end position */
+  int end_pos;
+  /** ADD for Marcela */
+  double disto;
+} opj_packet_info_t;
+
+/**
+Index structure : information regarding tiles inside image
+*/
+typedef struct opj_tile_info {
+  /** value of thresh for each layer by tile cfr. Marcela   */
+  double *thresh;
+  /** number of tile */
+  int num_tile;
+  /** start position */
+  int start_pos;
+  /** end position of the header */
+  int end_header;
+  /** end position */
+  int end_pos;
+  /** precinct number for each resolution level (width) */
+  int pw[33];
+  /** precinct number for each resolution level (height) */
+  int ph[33];
+  /** precinct size (in power of 2), in X for each resolution level */
+  int pdx[33];
+  /** precinct size (in power of 2), in Y for each resolution level */
+  int pdy[33];
+  /** information concerning packets inside tile */
+  opj_packet_info_t *packet;
+  /** add fixed_quality */
+  int nbpix;
+  /** add fixed_quality */
+  double distotile;
+} opj_tile_info_t;
+
+/**
+Index structure
+*/
+typedef struct opj_image_info {
+  /** 0 = no index || 1 = index */
+  int index_on;
+  /** maximum distortion reduction on the whole image (add for Marcela) */
+  double D_max;
+  /** packet number */
+  int num;
+  /** writing the packet in the index with t2_encode_packets */
+  int index_write;
+  /** image width */
+  int image_w;
+  /** image height */
+  int image_h;
+  /** progression order */
+  OPJ_PROG_ORDER prog;
+  /** tile size in x */
+  int tile_x;
+  /** tile size in y */
+  int tile_y;
+  /** */
+  int tile_Ox;
+  /** */
+  int tile_Oy;
+  /** number of tiles in X */
+  int tw;
+  /** number of tiles in Y */
+  int th;
+  /** component numbers */
+  int comp;
+  /** number of layer */
+  int layer;
+  /** number of decomposition */
+  int decomposition;
+  /** main header position */
+  int main_head_end;
+  /** codestream's size */
+  int codestream_size;
+  /** information regarding tiles inside image */
+  opj_tile_info_t *tile;
+} opj_image_info_t;
+
+/**
+JPEG-2000 codestream reader/writer
+*/
+typedef struct opj_j2k {
+  /** codec context */
+  opj_common_ptr cinfo;
+
+  /** locate in which part of the codestream the decoder is (main header, tile header, end) */
+  int state;
+  /** number of the tile curently concern by coding/decoding */
+  int curtileno;
+  /** 
+  locate the position of the end of the tile in the codestream, 
+  used to detect a truncated codestream (in j2k_read_sod)
+  */
+  unsigned char *eot;
+  /**
+  locate the start position of the SOT marker of the current coded tile:  
+  after encoding the tile, a jump (in j2k_write_sod) is done to the SOT marker to store the value of its length. 
+  */
+  int sot_start;
+  int sod_start;
+  /**
+  as the J2K-file is written in several parts during encoding, 
+  it enables to make the right correction in position return by cio_tell
+  */
+  int pos_correction;
+  /** array used to store the data of each tile */
+  unsigned char **tile_data;
+  /** array used to store the length of each tile */
+  int *tile_len;
+  /** 
+  decompression only : 
+  store decoding parameters common to all tiles (information like COD, COC in main header)
+  */
+  opj_tcp_t *default_tcp;
+  /** pointer to the encoded / decoded image */
+  opj_image_t *image;
+  /** pointer to the coding parameters */
+  opj_cp_t *cp;
+  /** helper used to write the index file */
+  opj_image_info_t *image_info;
+  /** pointer to the byte i/o stream */
+  opj_cio_t *cio;
+} opj_j2k_t;
+
+/** @name Exported functions */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+/**
+Creates a J2K decompression structure
+@param cinfo Codec context info
+@return Returns a handle to a J2K decompressor if successful, returns NULL otherwise
+*/
+opj_j2k_t* j2k_create_decompress(opj_common_ptr cinfo);
+/**
+Destroy a J2K decompressor handle
+@param j2k J2K decompressor handle to destroy
+*/
+void j2k_destroy_decompress(opj_j2k_t *j2k);
+/**
+Setup the decoder decoding parameters using user parameters.
+Decoding parameters are returned in j2k->cp. 
+@param j2k J2K decompressor handle
+@param parameters decompression parameters
+*/
+void j2k_setup_decoder(opj_j2k_t *j2k, opj_dparameters_t *parameters);
+/**
+Decode an image from a JPEG-2000 codestream
+@param j2k J2K decompressor handle
+@param cio Input buffer stream
+@return Returns a decoded image if successful, returns NULL otherwise
+*/
+opj_image_t* j2k_decode(opj_j2k_t *j2k, opj_cio_t *cio);
+/**
+Decode an image form a JPT-stream (JPEG 2000, JPIP)
+@param j2k J2K decompressor handle
+@param cio Input buffer stream
+@return Returns a decoded image if successful, returns NULL otherwise
+*/
+opj_image_t* j2k_decode_jpt_stream(opj_j2k_t *j2k, opj_cio_t *cio);
+/**
+Creates a J2K compression structure
+@param cinfo Codec context info
+@return Returns a handle to a J2K compressor if successful, returns NULL otherwise
+*/
+opj_j2k_t* j2k_create_compress(opj_common_ptr cinfo);
+/**
+Destroy a J2K compressor handle
+@param j2k J2K compressor handle to destroy
+*/
+void j2k_destroy_compress(opj_j2k_t *j2k);
+/**
+Setup the encoder parameters using the current image and using user parameters. 
+Coding parameters are returned in j2k->cp. 
+@param j2k J2K compressor handle
+@param parameters compression parameters
+@param image input filled image
+*/
+void j2k_setup_encoder(opj_j2k_t *j2k, opj_cparameters_t *parameters, opj_image_t *image);
+/**
+Encode an image into a JPEG-2000 codestream
+@param j2k J2K compressor handle
+@param cio Output buffer stream
+@param image Image to encode
+@param index Name of the index file if required, NULL otherwise
+@return Returns true if successful, returns false otherwise
+*/
+bool j2k_encode(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image, char *index);
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __J2K_H */
diff --git a/Utilities/ITK/Utilities/openjpeg/j2k_lib.c b/Utilities/ITK/Utilities/openjpeg/j2k_lib.c
new file mode 100644
index 0000000000..230be80c28
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/j2k_lib.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#else
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/times.h>
+#endif /* WIN32 */
+#include "opj_includes.h"
+
+double opj_clock() {
+#ifdef WIN32
+  /* WIN32: use QueryPerformance (very accurate) */
+    LARGE_INTEGER freq , t ;
+    /* freq is the clock speed of the CPU */
+    QueryPerformanceFrequency(&freq) ;
+  /* cout << "freq = " << ((double) freq.QuadPart) << endl; */
+    /* t is the high resolution performance counter (see MSDN) */
+    QueryPerformanceCounter ( & t ) ;
+    return ( t.QuadPart /(double) freq.QuadPart ) ;
+#else
+  /* Unix or Linux: use resource usage */
+    struct rusage t;
+    double procTime;
+    /* (1) Get the rusage data structure at this moment (man getrusage) */
+    getrusage(0,&t);
+    /* (2) What is the elapsed time ? - CPU time = User time + System time */
+  /* (2a) Get the seconds */
+    procTime = t.ru_utime.tv_sec + t.ru_stime.tv_sec;
+    /* (2b) More precisely! Get the microseconds part ! */
+    return ( procTime + (t.ru_utime.tv_usec + t.ru_stime.tv_usec) * 1e-6 ) ;
+#endif
+}
+
+void* opj_malloc( size_t size ) {
+  void *memblock = malloc(size);
+  if(memblock) {
+    memset(memblock, 0, size);
+  }
+  return memblock;
+}
+
+void* opj_realloc( void *memblock, size_t size ) {
+  return realloc(memblock, size);
+}
+
+void opj_free( void *memblock ) {
+  free(memblock);
+}
+
+
diff --git a/Utilities/ITK/Utilities/openjpeg/j2k_lib.h b/Utilities/ITK/Utilities/openjpeg/j2k_lib.h
new file mode 100644
index 0000000000..3d1b53c93b
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/j2k_lib.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __J2K_LIB_H
+#define __J2K_LIB_H
+/**
+@file j2k_lib.h
+@brief Internal functions
+
+The functions in J2K_LIB.C are internal utilities mainly used for memory management.
+*/
+
+/** @defgroup MISC MISC - Miscellaneous internal functions */
+/*@{*/
+
+/** @name Exported functions */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+
+/**
+Difference in successive opj_clock() calls tells you the elapsed time
+@return Returns time in seconds
+*/
+double opj_clock();
+
+/**
+Allocate a memory block with elements initialized to 0
+@param size Bytes to allocate
+@return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available
+*/
+void* opj_malloc( size_t size );
+
+/**
+Reallocate memory blocks.
+@param memblock Pointer to previously allocated memory block
+@param size New size in bytes
+@return Returns a void pointer to the reallocated (and possibly moved) memory block
+*/
+void* opj_realloc( void *memblock, size_t size );
+
+/**
+Deallocates or frees a memory block.
+@param memblock Previously allocated memory block to be freed
+*/
+void opj_free( void *memblock );
+
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __J2K_LIB_H */
+
diff --git a/Utilities/ITK/Utilities/openjpeg/jp2.c b/Utilities/ITK/Utilities/openjpeg/jp2.c
new file mode 100644
index 0000000000..7f6988d33a
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/jp2.c
@@ -0,0 +1,704 @@
+/*
+ * Copyright (c) 2004, Yannick Verschueren
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opj_includes.h"
+
+/** @defgroup JP2 JP2 - JPEG-2000 file format reader/writer */
+/*@{*/
+
+/** @name Local static functions */
+/*@{*/
+
+/**
+Read box headers
+@param cinfo Codec context info
+@param cio Input stream
+@param box
+@return Returns true if successful, returns false otherwise
+*/
+static bool jp2_read_boxhdr(opj_common_ptr cinfo, opj_cio_t *cio, opj_jp2_box_t *box);
+/*static void jp2_write_url(opj_cio_t *cio, char *Idx_file);*/
+/**
+Read the IHDR box - Image Header box
+@param jp2 JP2 handle
+@param cio Input buffer stream
+@return Returns true if successful, returns false otherwise
+*/
+static bool jp2_read_ihdr(opj_jp2_t *jp2, opj_cio_t *cio);
+static void jp2_write_ihdr(opj_jp2_t *jp2, opj_cio_t *cio);
+static void jp2_write_bpcc(opj_jp2_t *jp2, opj_cio_t *cio);
+static bool jp2_read_bpcc(opj_jp2_t *jp2, opj_cio_t *cio);
+static void jp2_write_colr(opj_jp2_t *jp2, opj_cio_t *cio);
+static bool jp2_read_colr(opj_jp2_t *jp2, opj_cio_t *cio);
+/**
+Write the JP2H box - JP2 Header box
+@param jp2 JP2 handle
+@param cio Output buffer stream
+*/
+static void jp2_write_jp2h(opj_jp2_t *jp2, opj_cio_t *cio);
+/**
+Read the JP2H box - JP2 Header box
+@param jp2 JP2 handle
+@param cio Input buffer stream
+@return Returns true if successful, returns false otherwise
+*/
+static bool jp2_read_jp2h(opj_jp2_t *jp2, opj_cio_t *cio);
+/**
+Write the FTYP box - File type box
+@param jp2 JP2 handle
+@param cio Output buffer stream
+*/
+static void jp2_write_ftyp(opj_jp2_t *jp2, opj_cio_t *cio);
+/**
+Read the FTYP box - File type box
+@param jp2 JP2 handle
+@param cio Input buffer stream
+@return Returns true if successful, returns false otherwise
+*/
+static bool jp2_read_ftyp(opj_jp2_t *jp2, opj_cio_t *cio);
+static int jp2_write_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, char *index);
+static bool jp2_read_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, unsigned int *j2k_codestream_length, unsigned int *j2k_codestream_offset);
+static void jp2_write_jp(opj_cio_t *cio);
+/**
+Read the JP box - JPEG 2000 signature
+@param jp2 JP2 handle
+@param cio Input buffer stream
+@return Returns true if successful, returns false otherwise
+*/
+static bool jp2_read_jp(opj_jp2_t *jp2, opj_cio_t *cio);
+/**
+Decode the structure of a JP2 file
+@param jp2 JP2 handle
+@param cio Input buffer stream
+@return Returns true if successful, returns false otherwise
+*/
+static bool jp2_read_struct(opj_jp2_t *jp2, opj_cio_t *cio);
+
+/*@}*/
+
+/*@}*/
+
+/* ----------------------------------------------------------------------- */
+
+static bool jp2_read_boxhdr(opj_common_ptr cinfo, opj_cio_t *cio, opj_jp2_box_t *box) {
+  box->init_pos = cio_tell(cio);
+  box->length = cio_read(cio, 4);
+  box->type = cio_read(cio, 4);
+  if (box->length == 1) {
+    if (cio_read(cio, 4) != 0) {
+      opj_event_msg(cinfo, EVT_ERROR, "Cannot handle box sizes higher than 2^32\n");
+      return false;
+    }
+    box->length = cio_read(cio, 4);
+    if (box->length == 0) 
+      box->length = cio_numbytesleft(cio) + 12;
+  }
+  else if (box->length == 0) {
+    box->length = cio_numbytesleft(cio) + 8;
+  }
+  
+  return true;
+}
+
+#if 0
+static void jp2_write_url(opj_cio_t *cio, char *Idx_file) {
+  unsigned int i;
+  opj_jp2_box_t box;
+
+  box.init_pos = cio_tell(cio);
+  cio_skip(cio, 4);
+  cio_write(cio, JP2_URL, 4);  /* DBTL */
+  cio_write(cio, 0, 1);    /* VERS */
+  cio_write(cio, 0, 3);    /* FLAG */
+
+  if(Idx_file) {
+    for (i = 0; i < strlen(Idx_file); i++) {
+      cio_write(cio, Idx_file[i], 1);
+    }
+  }
+
+  box.length = cio_tell(cio) - box.init_pos;
+  cio_seek(cio, box.init_pos);
+  cio_write(cio, box.length, 4);  /* L */
+  cio_seek(cio, box.init_pos + box.length);
+}
+#endif
+
+static bool jp2_read_ihdr(opj_jp2_t *jp2, opj_cio_t *cio) {
+  opj_jp2_box_t box;
+
+  opj_common_ptr cinfo = jp2->cinfo;
+
+  jp2_read_boxhdr(cinfo, cio, &box);
+  if (JP2_IHDR != box.type) {
+    opj_event_msg(cinfo, EVT_ERROR, "Expected IHDR Marker\n");
+    return false;
+  }
+
+  jp2->h = cio_read(cio, 4);      /* HEIGHT */
+  jp2->w = cio_read(cio, 4);      /* WIDTH */
+  jp2->numcomps = cio_read(cio, 2);  /* NC */
+  jp2->comps = (opj_jp2_comps_t*) opj_malloc(jp2->numcomps * sizeof(opj_jp2_comps_t));
+
+  jp2->bpc = cio_read(cio, 1);    /* BPC */
+
+  jp2->C = cio_read(cio, 1);      /* C */
+  jp2->UnkC = cio_read(cio, 1);    /* UnkC */
+  jp2->IPR = cio_read(cio, 1);    /* IPR */
+
+  if (cio_tell(cio) - box.init_pos != box.length) {
+    opj_event_msg(cinfo, EVT_ERROR, "Error with IHDR Box\n");
+    return false;
+  }
+
+  return true;
+}
+
+static void jp2_write_ihdr(opj_jp2_t *jp2, opj_cio_t *cio) {
+  opj_jp2_box_t box;
+
+  box.init_pos = cio_tell(cio);
+  cio_skip(cio, 4);
+  cio_write(cio, JP2_IHDR, 4);    /* IHDR */
+
+  cio_write(cio, jp2->h, 4);      /* HEIGHT */
+  cio_write(cio, jp2->w, 4);      /* WIDTH */
+  cio_write(cio, jp2->numcomps, 2);  /* NC */
+
+  cio_write(cio, jp2->bpc, 1);    /* BPC */
+
+  cio_write(cio, jp2->C, 1);      /* C : Always 7 */
+  cio_write(cio, jp2->UnkC, 1);    /* UnkC, colorspace unknown */
+  cio_write(cio, jp2->IPR, 1);    /* IPR, no intellectual property */
+
+  box.length = cio_tell(cio) - box.init_pos;
+  cio_seek(cio, box.init_pos);
+  cio_write(cio, box.length, 4);  /* L */
+  cio_seek(cio, box.init_pos + box.length);
+}
+
+static void jp2_write_bpcc(opj_jp2_t *jp2, opj_cio_t *cio) {
+  unsigned int i;
+  opj_jp2_box_t box;
+
+  box.init_pos = cio_tell(cio);
+  cio_skip(cio, 4);
+  cio_write(cio, JP2_BPCC, 4);  /* BPCC */
+
+  for (i = 0; i < jp2->numcomps; i++) {
+    cio_write(cio, jp2->comps[i].bpcc, 1);
+  }
+
+  box.length = cio_tell(cio) - box.init_pos;
+  cio_seek(cio, box.init_pos);
+  cio_write(cio, box.length, 4);  /* L */
+  cio_seek(cio, box.init_pos + box.length);
+}
+
+
+static bool jp2_read_bpcc(opj_jp2_t *jp2, opj_cio_t *cio) {
+  unsigned int i;
+  opj_jp2_box_t box;
+
+  opj_common_ptr cinfo = jp2->cinfo;
+
+  jp2_read_boxhdr(cinfo, cio, &box);
+  if (JP2_BPCC != box.type) {
+    opj_event_msg(cinfo, EVT_ERROR, "Expected BPCC Marker\n");
+    return false;
+  }
+
+  for (i = 0; i < jp2->numcomps; i++) {
+    jp2->comps[i].bpcc = cio_read(cio, 1);
+  }
+
+  if (cio_tell(cio) - box.init_pos != box.length) {
+    opj_event_msg(cinfo, EVT_ERROR, "Error with BPCC Box\n");
+    return false;
+  }
+
+  return true;
+}
+
+static void jp2_write_colr(opj_jp2_t *jp2, opj_cio_t *cio) {
+  opj_jp2_box_t box;
+
+  box.init_pos = cio_tell(cio);
+  cio_skip(cio, 4);
+  cio_write(cio, JP2_COLR, 4);    /* COLR */
+
+  cio_write(cio, jp2->meth, 1);    /* METH */
+  cio_write(cio, jp2->precedence, 1);  /* PRECEDENCE */
+  cio_write(cio, jp2->approx, 1);    /* APPROX */
+
+  if (jp2->meth == 1) {
+    cio_write(cio, jp2->enumcs, 4);  /* EnumCS */
+  } else {
+    cio_write(cio, 0, 1);      /* PROFILE (??) */
+  }
+
+  box.length = cio_tell(cio) - box.init_pos;
+  cio_seek(cio, box.init_pos);
+  cio_write(cio, box.length, 4);  /* L */
+  cio_seek(cio, box.init_pos + box.length);
+}
+
+static bool jp2_read_colr(opj_jp2_t *jp2, opj_cio_t *cio) {
+  opj_jp2_box_t box;
+  int skip_len;
+
+  opj_common_ptr cinfo = jp2->cinfo;
+
+  jp2_read_boxhdr(cinfo, cio, &box);
+  do {
+    if (JP2_COLR != box.type) {
+      cio_skip(cio, box.length - 8);
+      jp2_read_boxhdr(cinfo, cio, &box);
+    }
+  } while(JP2_COLR != box.type);
+
+  jp2->meth = cio_read(cio, 1);    /* METH */
+  jp2->precedence = cio_read(cio, 1);  /* PRECEDENCE */
+  jp2->approx = cio_read(cio, 1);    /* APPROX */
+
+  if (jp2->meth == 1) {
+    jp2->enumcs = cio_read(cio, 4);  /* EnumCS */
+  } else {
+    /* skip PROFILE */
+    skip_len = box.init_pos + box.length - cio_tell(cio);
+    if (skip_len < 0) {
+      opj_event_msg(cinfo, EVT_ERROR, "Error with JP2H box size\n");
+      return false;
+    }
+    cio_skip(cio, box.init_pos + box.length - cio_tell(cio));
+  }
+
+  if (cio_tell(cio) - box.init_pos != box.length) {
+    opj_event_msg(cinfo, EVT_ERROR, "Error with BPCC Box\n");
+    return false;
+  }
+  return true;
+}
+
+static void jp2_write_jp2h(opj_jp2_t *jp2, opj_cio_t *cio) {
+  opj_jp2_box_t box;
+
+  box.init_pos = cio_tell(cio);
+  cio_skip(cio, 4);
+  cio_write(cio, JP2_JP2H, 4);  /* JP2H */
+
+  jp2_write_ihdr(jp2, cio);
+
+  if (jp2->bpc == 255) {
+    jp2_write_bpcc(jp2, cio);
+  }
+  jp2_write_colr(jp2, cio);
+
+  box.length = cio_tell(cio) - box.init_pos;
+  cio_seek(cio, box.init_pos);
+  cio_write(cio, box.length, 4);  /* L */
+  cio_seek(cio, box.init_pos + box.length);
+}
+
+static bool jp2_read_jp2h(opj_jp2_t *jp2, opj_cio_t *cio) {
+  opj_jp2_box_t box;
+  int skip_len;
+
+  opj_common_ptr cinfo = jp2->cinfo;
+
+  jp2_read_boxhdr(cinfo, cio, &box);
+  do {
+    if (JP2_JP2H != box.type) {
+      if (box.type == JP2_JP2C) {
+        opj_event_msg(cinfo, EVT_ERROR, "Expected JP2H Marker\n");
+        return false;
+      }
+      cio_skip(cio, box.length - 8);
+      jp2_read_boxhdr(cinfo, cio, &box);
+    }
+  } while(JP2_JP2H != box.type);
+
+  if (!jp2_read_ihdr(jp2, cio))
+    return false;
+
+  if (jp2->bpc == 255) {
+    if (!jp2_read_bpcc(jp2, cio))
+      return false;
+  }
+  if (!jp2_read_colr(jp2, cio))
+    return false;
+
+  skip_len = box.init_pos + box.length - cio_tell(cio);
+  if (skip_len < 0) {
+    opj_event_msg(cinfo, EVT_ERROR, "Error with JP2H Box\n");
+    return false;
+  }
+  cio_skip(cio, box.init_pos + box.length - cio_tell(cio));
+
+  return true;
+}
+
+static void jp2_write_ftyp(opj_jp2_t *jp2, opj_cio_t *cio) {
+  unsigned int i;
+  opj_jp2_box_t box;
+
+  box.init_pos = cio_tell(cio);
+  cio_skip(cio, 4);
+  cio_write(cio, JP2_FTYP, 4);    /* FTYP */
+
+  cio_write(cio, jp2->brand, 4);    /* BR */
+  cio_write(cio, jp2->minversion, 4);  /* MinV */
+
+  for (i = 0; i < jp2->numcl; i++) {
+    cio_write(cio, jp2->cl[i], 4);  /* CL */
+  }
+
+  box.length = cio_tell(cio) - box.init_pos;
+  cio_seek(cio, box.init_pos);
+  cio_write(cio, box.length, 4);  /* L */
+  cio_seek(cio, box.init_pos + box.length);
+}
+
+static bool jp2_read_ftyp(opj_jp2_t *jp2, opj_cio_t *cio) {
+  int i;
+  opj_jp2_box_t box;
+
+  opj_common_ptr cinfo = jp2->cinfo;
+
+  jp2_read_boxhdr(cinfo, cio, &box);
+
+  if (JP2_FTYP != box.type) {
+    opj_event_msg(cinfo, EVT_ERROR, "Expected FTYP Marker\n");
+    return false;
+  }
+
+  jp2->brand = cio_read(cio, 4);    /* BR */
+  jp2->minversion = cio_read(cio, 4);  /* MinV */
+  jp2->numcl = (box.length - 16) / 4;
+  jp2->cl = (unsigned int *) opj_malloc(jp2->numcl * sizeof(unsigned int));
+
+  for (i = 0; i < (int)jp2->numcl; i++) {
+    jp2->cl[i] = cio_read(cio, 4);  /* CLi */
+  }
+
+  if (cio_tell(cio) - box.init_pos != box.length) {
+    opj_event_msg(cinfo, EVT_ERROR, "Error with FTYP Box\n");
+    return false;
+  }
+
+  return true;
+}
+
+static int jp2_write_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, char *index) {
+  unsigned int j2k_codestream_offset, j2k_codestream_length;
+  opj_jp2_box_t box;
+
+  opj_j2k_t *j2k = jp2->j2k;
+
+  box.init_pos = cio_tell(cio);
+  cio_skip(cio, 4);
+  cio_write(cio, JP2_JP2C, 4);  /* JP2C */
+
+  /* J2K encoding */
+  j2k_codestream_offset = cio_tell(cio);
+  if(!j2k_encode(j2k, cio, image, index)) {
+    opj_event_msg(j2k->cinfo, EVT_ERROR, "Failed to encode image\n");
+    return 0;
+  }
+  j2k_codestream_length = cio_tell(cio) - j2k_codestream_offset;
+
+  jp2->j2k_codestream_offset = j2k_codestream_offset;
+  jp2->j2k_codestream_length = j2k_codestream_length;
+
+  box.length = 8 + jp2->j2k_codestream_length;
+  cio_seek(cio, box.init_pos);
+  cio_write(cio, box.length, 4);  /* L */
+  cio_seek(cio, box.init_pos + box.length);
+
+  return box.length;
+}
+
+static bool jp2_read_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, unsigned int *j2k_codestream_length, unsigned int *j2k_codestream_offset) {
+  opj_jp2_box_t box;
+
+  opj_common_ptr cinfo = jp2->cinfo;
+
+  jp2_read_boxhdr(cinfo, cio, &box);
+  do {
+    if(JP2_JP2C != box.type) {
+      cio_skip(cio, box.length - 8);
+      jp2_read_boxhdr(cinfo, cio, &box);
+    }
+  } while(JP2_JP2C != box.type);
+
+  *j2k_codestream_offset = cio_tell(cio);
+  *j2k_codestream_length = box.length - 8;
+
+  return true;
+}
+
+static void jp2_write_jp(opj_cio_t *cio) {
+  opj_jp2_box_t box;
+
+  box.init_pos = cio_tell(cio);
+  cio_skip(cio, 4);
+  cio_write(cio, JP2_JP, 4);    /* JP2 signature */
+  cio_write(cio, 0x0d0a870a, 4);
+
+  box.length = cio_tell(cio) - box.init_pos;
+  cio_seek(cio, box.init_pos);
+  cio_write(cio, box.length, 4);  /* L */
+  cio_seek(cio, box.init_pos + box.length);
+}
+
+static bool jp2_read_jp(opj_jp2_t *jp2, opj_cio_t *cio) {
+  opj_jp2_box_t box;
+
+  opj_common_ptr cinfo = jp2->cinfo;
+
+  jp2_read_boxhdr(cinfo, cio, &box);
+  if (JP2_JP != box.type) {
+    opj_event_msg(cinfo, EVT_ERROR, "Expected JP Marker\n");
+    return false;
+  }
+  if (0x0d0a870a != cio_read(cio, 4)) {
+    opj_event_msg(cinfo, EVT_ERROR, "Error with JP Marker\n");
+    return false;
+  }
+  if (cio_tell(cio) - box.init_pos != box.length) {
+    opj_event_msg(cinfo, EVT_ERROR, "Error with JP Box size\n");
+    return false;
+  }
+
+  return true;
+}
+
+
+static bool jp2_read_struct(opj_jp2_t *jp2, opj_cio_t *cio) {
+  if (!jp2_read_jp(jp2, cio))
+    return false;
+  if (!jp2_read_ftyp(jp2, cio))
+    return false;
+  if (!jp2_read_jp2h(jp2, cio))
+    return false;
+  if (!jp2_read_jp2c(jp2, cio, &jp2->j2k_codestream_length, &jp2->j2k_codestream_offset))
+    return false;
+  
+  return true;
+}
+
+/* ----------------------------------------------------------------------- */
+/* JP2 decoder interface                                             */
+/* ----------------------------------------------------------------------- */
+
+opj_jp2_t* jp2_create_decompress(opj_common_ptr cinfo) {
+  opj_jp2_t *jp2 = (opj_jp2_t*)opj_malloc(sizeof(opj_jp2_t));
+  if(jp2) {
+    jp2->cinfo = cinfo;
+    /* create the J2K codec */
+    jp2->j2k = j2k_create_decompress(cinfo);
+    if(jp2->j2k == NULL) {
+      jp2_destroy_decompress(jp2);
+      return NULL;
+    }
+  }
+  return jp2;
+}
+
+void jp2_destroy_decompress(opj_jp2_t *jp2) {
+  if(jp2) {
+    /* destroy the J2K codec */
+    j2k_destroy_decompress(jp2->j2k);
+
+    if(jp2->comps) {
+      opj_free(jp2->comps);
+    }
+    if(jp2->cl) {
+      opj_free(jp2->cl);
+    }
+    opj_free(jp2);
+  }
+}
+
+void jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters) {
+  /* setup the J2K codec */
+  j2k_setup_decoder(jp2->j2k, parameters);
+  /* further JP2 initializations go here */
+}
+
+opj_image_t* jp2_decode(opj_jp2_t *jp2, opj_cio_t *cio) {
+  opj_common_ptr cinfo;
+  opj_image_t *image = NULL;
+
+  if(!jp2 || !cio) {
+    return NULL;
+  }
+
+  cinfo = jp2->cinfo;
+
+  /* JP2 decoding */
+  if(!jp2_read_struct(jp2, cio)) {
+    opj_event_msg(cinfo, EVT_ERROR, "Failed to decode jp2 structure\n");
+    return NULL;
+  }
+
+  /* J2K decoding */
+  image = j2k_decode(jp2->j2k, cio);
+  if(!image) {
+    opj_event_msg(cinfo, EVT_ERROR, "Failed to decode J2K image\n");
+  }
+
+  return image;
+}
+
+/* ----------------------------------------------------------------------- */
+/* JP2 encoder interface                                             */
+/* ----------------------------------------------------------------------- */
+
+opj_jp2_t* jp2_create_compress(opj_common_ptr cinfo) {
+  opj_jp2_t *jp2 = (opj_jp2_t*)opj_malloc(sizeof(opj_jp2_t));
+  if(jp2) {
+    jp2->cinfo = cinfo;
+    /* create the J2K codec */
+    jp2->j2k = j2k_create_compress(cinfo);
+    if(jp2->j2k == NULL) {
+      jp2_destroy_compress(jp2);
+      return NULL;
+    }
+  }
+  return jp2;
+}
+
+void jp2_destroy_compress(opj_jp2_t *jp2) {
+  if(jp2) {
+    /* destroy the J2K codec */
+    j2k_destroy_compress(jp2->j2k);
+
+    if(jp2->comps) {
+      opj_free(jp2->comps);
+    }
+    if(jp2->cl) {
+      opj_free(jp2->cl);
+    }
+    opj_free(jp2);
+  }
+}
+
+void jp2_setup_encoder(opj_jp2_t *jp2, opj_cparameters_t *parameters, opj_image_t *image) {
+  int i;
+  int depth_0, sign;
+
+  if(!jp2 || !parameters || !image)
+    return;
+
+  /* setup the J2K codec */
+  /* ------------------- */
+
+  j2k_setup_encoder(jp2->j2k, parameters, image);
+
+  /* setup the JP2 codec */
+  /* ------------------- */
+  
+  /* Profile box */
+
+  jp2->brand = JP2_JP2;  /* BR */
+  jp2->minversion = 0;  /* MinV */
+  jp2->numcl = 1;
+  jp2->cl = (unsigned int*) opj_malloc(jp2->numcl * sizeof(unsigned int));
+  jp2->cl[0] = JP2_JP2;  /* CL0 : JP2 */
+
+  /* Image Header box */
+
+  jp2->numcomps = image->numcomps;  /* NC */
+  jp2->comps = (opj_jp2_comps_t*) opj_malloc(jp2->numcomps * sizeof(opj_jp2_comps_t));
+  jp2->h = image->y1 - image->y0;    /* HEIGHT */
+  jp2->w = image->x1 - image->x0;    /* WIDTH */
+  /* BPC */
+  depth_0 = image->comps[0].prec - 1;
+  sign = image->comps[0].sgnd;
+  jp2->bpc = depth_0 + (sign << 7);
+  for (i = 1; i < image->numcomps; i++) {
+    int depth = image->comps[i].prec - 1;
+    sign = image->comps[i].sgnd;
+    if (depth_0 != depth)
+      jp2->bpc = 255;
+  }
+  jp2->C = 7;      /* C : Always 7 */
+  jp2->UnkC = 0;    /* UnkC, colorspace specified in colr box */
+  jp2->IPR = 0;    /* IPR, no intellectual property */
+  
+  /* BitsPerComponent box */
+
+  for (i = 0; i < image->numcomps; i++) {
+    jp2->comps[i].bpcc = image->comps[i].prec - 1 + (image->comps[i].sgnd << 7);
+  }
+
+  /* Colour Specification box */
+
+  if ((image->numcomps == 1 || image->numcomps == 3) && (jp2->bpc != 255)) {
+    jp2->meth = 1;  /* METH: Enumerated colourspace */
+  } else {
+    jp2->meth = 2;  /* METH: Restricted ICC profile */
+  }
+  if (jp2->meth == 1) {
+    if (image->color_space == 1)
+      jp2->enumcs = 16;  /* sRGB as defined by IEC 61966�2�1 */
+    else if (image->color_space == 2)
+      jp2->enumcs = 17;  /* greyscale */
+    else if (image->color_space == 3)
+      jp2->enumcs = 18;  /* YUV */
+  } else {
+    jp2->enumcs = 0;    /* PROFILE (??) */
+  }
+  jp2->precedence = 0;  /* PRECEDENCE */
+  jp2->approx = 0;    /* APPROX */
+
+}
+
+bool jp2_encode(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, char *index) {
+
+  /* JP2 encoding */
+
+  /* JPEG 2000 Signature box */
+  jp2_write_jp(cio);
+  /* File Type box */
+  jp2_write_ftyp(jp2, cio);
+  /* JP2 Header box */
+  jp2_write_jp2h(jp2, cio);
+
+  /* J2K encoding */
+
+  if(!jp2_write_jp2c(jp2, cio, image, index)) {
+    opj_event_msg(jp2->cinfo, EVT_ERROR, "Failed to encode image\n");
+    return false;
+  }
+
+  return true;
+}
+
+
diff --git a/Utilities/ITK/Utilities/openjpeg/jp2.h b/Utilities/ITK/Utilities/openjpeg/jp2.h
new file mode 100644
index 0000000000..12ac455f96
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/jp2.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2004, Yannick Verschueren
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __JP2_H
+#define __JP2_H
+/**
+@file jp2.h
+@brief The JPEG-2000 file format Reader/Writer (JP2)
+
+*/
+
+/** @defgroup JP2 JP2 - JPEG-2000 file format reader/writer */
+/*@{*/
+
+#define JPIP_JPIP 0x6a706970
+
+#define JP2_JP   0x6a502020    /**< JPEG 2000 signature box */
+#define JP2_FTYP 0x66747970    /**< File type box */
+#define JP2_JP2H 0x6a703268    /**< JP2 header box */
+#define JP2_IHDR 0x69686472    /**< Image header box */
+#define JP2_COLR 0x636f6c72    /**< Colour specification box */
+#define JP2_JP2C 0x6a703263    /**< Contiguous codestream box */
+#define JP2_URL  0x75726c20    /**< URL box */
+#define JP2_DBTL 0x6474626c    /**< ??? */
+#define JP2_BPCC 0x62706363    /**< Bits per component box */
+#define JP2_JP2  0x6a703220    /**< File type fields */
+
+/* ----------------------------------------------------------------------- */
+
+/** 
+JP2 component
+*/
+typedef struct opj_jp2_comps {
+  int depth;      
+  int sgnd;       
+  int bpcc;
+} opj_jp2_comps_t;
+
+/**
+JPEG-2000 file format reader/writer
+*/
+typedef struct opj_jp2 {
+  /** codec context */
+  opj_common_ptr cinfo;
+  /** handle to the J2K codec  */
+  opj_j2k_t *j2k;
+  unsigned int w;
+  unsigned int h;
+  unsigned int numcomps;
+  unsigned int bpc;
+  unsigned int C;
+  unsigned int UnkC;
+  unsigned int IPR;
+  unsigned int meth;
+  unsigned int approx;
+  unsigned int enumcs;
+  unsigned int precedence;
+  unsigned int brand;
+  unsigned int minversion;
+  unsigned int numcl;
+  unsigned int *cl;
+  opj_jp2_comps_t *comps;
+  unsigned int j2k_codestream_offset;
+  unsigned int j2k_codestream_length;
+} opj_jp2_t;
+
+/**
+JP2 Box
+*/
+typedef struct opj_jp2_box {
+  int length;
+  int type;
+  int init_pos;
+} opj_jp2_box_t;
+
+/** @name Exported functions */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+/**
+Creates a JP2 decompression structure
+@param cinfo Codec context info
+@return Returns a handle to a JP2 decompressor if successful, returns NULL otherwise
+*/
+opj_jp2_t* jp2_create_decompress(opj_common_ptr cinfo);
+/**
+Destroy a JP2 decompressor handle
+@param jp2 JP2 decompressor handle to destroy
+*/
+void jp2_destroy_decompress(opj_jp2_t *jp2);
+/**
+Setup the decoder decoding parameters using user parameters.
+Decoding parameters are returned in jp2->j2k->cp. 
+@param jp2 JP2 decompressor handle
+@param parameters decompression parameters
+*/
+void jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters);
+/**
+Decode an image from a JPEG-2000 file stream
+@param jp2 JP2 decompressor handle
+@param cio Input buffer stream
+@return Returns a decoded image if successful, returns NULL otherwise
+*/
+opj_image_t* jp2_decode(opj_jp2_t *jp2, opj_cio_t *cio);
+/**
+Creates a JP2 compression structure
+@param cinfo Codec context info
+@return Returns a handle to a JP2 compressor if successful, returns NULL otherwise
+*/
+opj_jp2_t* jp2_create_compress(opj_common_ptr cinfo);
+/**
+Destroy a JP2 compressor handle
+@param jp2 JP2 compressor handle to destroy
+*/
+void jp2_destroy_compress(opj_jp2_t *jp2);
+/**
+Setup the encoder parameters using the current image and using user parameters. 
+Coding parameters are returned in jp2->j2k->cp. 
+@param jp2 JP2 compressor handle
+@param parameters compression parameters
+@param image input filled image
+*/
+void jp2_setup_encoder(opj_jp2_t *jp2, opj_cparameters_t *parameters, opj_image_t *image);
+/**
+Encode an image into a JPEG-2000 file stream
+@param jp2 JP2 compressor handle
+@param cio Output buffer stream
+@param image Image to encode
+@param index Name of the index file if required, NULL otherwise
+@return Returns true if successful, returns false otherwise
+*/
+bool jp2_encode(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, char *index);
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __JP2_H */
+
diff --git a/Utilities/ITK/Utilities/openjpeg/jpt.c b/Utilities/ITK/Utilities/openjpeg/jpt.c
new file mode 100644
index 0000000000..9b75994b06
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/jpt.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2004, Yannick Verschueren
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opj_includes.h"
+
+/*
+ * Read the information contains in VBAS [JPP/JPT stream message header]
+ * Store information (7 bits) in value
+ *
+ */
+unsigned int jpt_read_VBAS_info(opj_cio_t *cio, unsigned int value) {
+  unsigned char elmt;
+
+  elmt = cio_read(cio, 1);
+  while ((elmt >> 7) == 1) {
+    value = (value << 7);
+    value |= (elmt & 0x7f);
+    elmt = cio_read(cio, 1);
+  }
+  value = (value << 7);
+  value |= (elmt & 0x7f);
+
+  return value;
+}
+
+/*
+ * Initialize the value of the message header structure 
+ *
+ */
+void jpt_init_msg_header(opj_jpt_msg_header_t * header) {
+  header->Id = 0;    /* In-class Identifier    */
+  header->last_byte = 0;  /* Last byte information  */
+  header->Class_Id = 0;    /* Class Identifier       */
+  header->CSn_Id = 0;    /* CSn : index identifier */
+  header->Msg_offset = 0;  /* Message offset         */
+  header->Msg_length = 0;  /* Message length         */
+  header->Layer_nb = 0;    /* Auxiliary for JPP case */
+}
+
+/*
+ * Re-initialize the value of the message header structure
+ *
+ * Only parameters always present in message header
+ *
+ */
+void jpt_reinit_msg_header(opj_jpt_msg_header_t * header) {
+  header->Id = 0;    /* In-class Identifier    */
+  header->last_byte = 0;  /* Last byte information  */
+  header->Msg_offset = 0;  /* Message offset         */
+  header->Msg_length = 0;  /* Message length         */
+}
+
+/*
+ * Read the message header for a JPP/JPT - stream
+ *
+ */
+void jpt_read_msg_header(opj_common_ptr cinfo, opj_cio_t *cio, opj_jpt_msg_header_t *header) {
+  unsigned char elmt, Class = 0, CSn = 0;
+  jpt_reinit_msg_header(header);
+
+  /* ------------- */
+  /* VBAS : Bin-ID */
+  /* ------------- */
+  elmt = cio_read(cio, 1);
+
+  /* See for Class and CSn */
+  switch ((elmt >> 5) & 0x03) {
+    case 0:
+      opj_event_msg(cinfo, EVT_ERROR, "Forbidden value encounter in message header !!\n");
+      break;
+    case 1:
+      Class = 0;
+      CSn = 0;
+      break;
+    case 2:
+      Class = 1;
+      CSn = 0;
+      break;
+    case 3:
+      Class = 1;
+      CSn = 1;
+      break;
+    default:
+      break;
+  }
+
+  /* see information on bits 'c' [p 10 : A.2.1 general, ISO/IEC FCD 15444-9] */
+  if (((elmt >> 4) & 0x01) == 1)
+    header->last_byte = 1;
+
+  /* In-class identifier */
+  header->Id |= (elmt & 0x0f);
+  if ((elmt >> 7) == 1)
+    header->Id = jpt_read_VBAS_info(cio, header->Id);
+
+  /* ------------ */
+  /* VBAS : Class */
+  /* ------------ */
+  if (Class == 1) {
+    header->Class_Id = 0;
+    header->Class_Id = jpt_read_VBAS_info(cio, header->Class_Id);
+  }
+
+  /* ---------- */
+  /* VBAS : CSn */
+  /* ---------- */
+  if (CSn == 1) {
+    header->CSn_Id = 0;
+    header->CSn_Id = jpt_read_VBAS_info(cio, header->CSn_Id);
+  }
+
+  /* ----------------- */
+  /* VBAS : Msg_offset */
+  /* ----------------- */
+  header->Msg_offset = jpt_read_VBAS_info(cio, header->Msg_offset);
+
+  /* ----------------- */
+  /* VBAS : Msg_length */
+  /* ----------------- */
+  header->Msg_length = jpt_read_VBAS_info(cio, header->Msg_length);
+
+  /* ---------- */
+  /* VBAS : Aux */
+  /* ---------- */
+  if ((header->Class_Id & 0x01) == 1) {
+    header->Layer_nb = 0;
+    header->Layer_nb = jpt_read_VBAS_info(cio, header->Layer_nb);
+  }
+}
diff --git a/Utilities/ITK/Utilities/openjpeg/jpt.h b/Utilities/ITK/Utilities/openjpeg/jpt.h
new file mode 100644
index 0000000000..f6250f54a1
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/jpt.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2004, Yannick Verschueren
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __JPT_H
+#define __JPT_H
+/**
+@file jpt.h
+@brief JPT-stream reader (JPEG 2000, JPIP)
+
+JPT-stream functions are implemented in J2K.C. 
+*/
+
+/**
+Message Header JPT stream structure
+*/
+typedef struct opj_jpt_msg_header {
+  /** In-class Identifier */
+  unsigned int Id;
+  /** Last byte information */
+  unsigned int last_byte;  
+  /** Class Identifier */
+  unsigned int Class_Id;  
+  /** CSn : index identifier */
+  unsigned int CSn_Id;
+  /** Message offset */
+  unsigned int Msg_offset;
+  /** Message length */
+  unsigned int Msg_length;
+  /** Auxiliary for JPP case */
+  unsigned int Layer_nb;
+} opj_jpt_msg_header_t;
+
+/* ----------------------------------------------------------------------- */
+
+/**
+Initialize the value of the message header structure 
+@param header Message header structure
+*/
+void jpt_init_msg_header(opj_jpt_msg_header_t * header);
+
+/**
+Read the message header for a JPP/JPT - stream
+@param cinfo Codec context info
+@param cio CIO handle
+@param header Message header structure
+*/
+void jpt_read_msg_header(opj_common_ptr cinfo, opj_cio_t *cio, opj_jpt_msg_header_t *header);
+
+#endif
diff --git a/Utilities/ITK/Utilities/openjpeg/mct.c b/Utilities/ITK/Utilities/openjpeg/mct.c
new file mode 100644
index 0000000000..b6e3c96eb2
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/mct.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opj_includes.h"
+
+/* <summary> */
+/* This table contains the norms of the basis function of the reversible MCT. */
+/* </summary> */
+static const double mct_norms[3] = { 1.732, .8292, .8292 };
+
+/* <summary> */
+/* This table contains the norms of the basis function of the irreversible MCT. */
+/* </summary> */
+static const double mct_norms_real[3] = { 1.732, 1.805, 1.573 };
+
+/* <summary> */
+/* Foward reversible MCT. */
+/* </summary> */
+void mct_encode(int *c0, int *c1, int *c2, int n) {
+  int i;
+  for (i = 0; i < n; i++) {
+    int r, g, b, y, u, v;
+    r = c0[i];
+    g = c1[i];
+    b = c2[i];
+    y = (r + (g << 1) + b) >> 2;
+    u = b - g;
+    v = r - g;
+    c0[i] = y;
+    c1[i] = u;
+    c2[i] = v;
+  }
+}
+
+/* <summary> */
+/* Inverse reversible MCT. */
+/* </summary> */
+void mct_decode(int *c0, int *c1, int *c2, int n) {
+  int i;
+  for (i = 0; i < n; i++) {
+    int y, u, v, r, g, b;
+    y = c0[i];
+    u = c1[i];
+    v = c2[i];
+    g = y - ((u + v) >> 2);
+    r = v + g;
+    b = u + g;
+    c0[i] = r;
+    c1[i] = g;
+    c2[i] = b;
+  }
+}
+
+/* <summary> */
+/* Get norm of basis function of reversible MCT. */
+/* </summary> */
+double mct_getnorm(int compno) {
+  return mct_norms[compno];
+}
+
+/* <summary> */
+/* Foward irreversible MCT. */
+/* </summary> */
+void mct_encode_real(int *c0, int *c1, int *c2, int n) {
+  int i;
+  for (i = 0; i < n; i++) {
+    int r, g, b, y, u, v;
+    r = c0[i];
+    g = c1[i];
+    b = c2[i];
+    y = fix_mul(r, 2449) + fix_mul(g, 4809) + fix_mul(b, 934);
+    u = -fix_mul(r, 1382) - fix_mul(g, 2714) + fix_mul(b, 4096);
+    v = fix_mul(r, 4096) - fix_mul(g, 3430) - fix_mul(b, 666);
+    c0[i] = y;
+    c1[i] = u;
+    c2[i] = v;
+  }
+}
+
+/* <summary> */
+/* Inverse irreversible MCT. */
+/* </summary> */
+void mct_decode_real(int *c0, int *c1, int *c2, int n) {
+  int i;
+  for (i = 0; i < n; i++) {
+    int y, u, v, r, g, b;
+    y = c0[i];
+    u = c1[i];
+    v = c2[i];
+    r = y + fix_mul(v, 11485);
+    g = y - fix_mul(u, 2819) - fix_mul(v, 5850);
+    b = y + fix_mul(u, 14516);
+    c0[i] = r;
+    c1[i] = g;
+    c2[i] = b;
+  }
+}
+
+/* <summary> */
+/* Get norm of basis function of irreversible MCT. */
+/* </summary> */
+double mct_getnorm_real(int compno) {
+  return mct_norms_real[compno];
+}
diff --git a/Utilities/ITK/Utilities/openjpeg/mct.h b/Utilities/ITK/Utilities/openjpeg/mct.h
new file mode 100644
index 0000000000..906d0db89e
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/mct.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MCT_H
+#define __MCT_H
+/**
+@file mct.h
+@brief Implementation of a multi-component transforms (MCT)
+
+The functions in MCT.C have for goal to realize reversible and irreversible multicomponent
+transform. The functions in MCT.C are used by some function in TCD.C.
+*/
+
+/** @defgroup MCT MCT - Implementation of a multi-component transform */
+/*@{*/
+
+/** @name Exported functions */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+/**
+Apply a reversible multi-component transform to an image
+@param c0 Samples for red component
+@param c1 Samples for green component
+@param c2 Samples blue component
+@param n Number of samples for each component
+*/
+void mct_encode(int *c0, int *c1, int *c2, int n);
+/**
+Apply a reversible multi-component inverse transform to an image
+@param c0 Samples for luminance component
+@param c1 Samples for red chrominance component
+@param c2 Samples for blue chrominance component
+@param n Number of samples for each component
+*/
+void mct_decode(int *c0, int *c1, int *c2, int n);
+/**
+Get norm of the basis function used for the reversible multi-component transform
+@param compno Number of the component (0->Y, 1->U, 2->V)
+@return 
+*/
+double mct_getnorm(int compno);
+
+/**
+Apply an irreversible multi-component transform to an image
+@param c0 Samples for red component
+@param c1 Samples for green component
+@param c2 Samples blue component
+@param n Number of samples for each component
+*/
+void mct_encode_real(int *c0, int *c1, int *c2, int n);
+/**
+Apply an irreversible multi-component inverse transform to an image
+@param c0 Samples for luminance component
+@param c1 Samples for red chrominance component
+@param c2 Samples for blue chrominance component
+@param n Number of samples for each component
+*/
+void mct_decode_real(int *c0, int *c1, int *c2, int n);
+/**
+Get norm of the basis function used for the irreversible multi-component transform
+@param compno Number of the component (0->Y, 1->U, 2->V)
+@return 
+*/
+double mct_getnorm_real(int compno);
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __MCT_H */
diff --git a/Utilities/ITK/Utilities/openjpeg/mqc.c b/Utilities/ITK/Utilities/openjpeg/mqc.c
new file mode 100644
index 0000000000..f06751af08
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/mqc.c
@@ -0,0 +1,541 @@
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opj_includes.h"
+
+/** @defgroup MQC MQC - Implementation of an MQ-Coder */
+/*@{*/
+
+/** @name Local static functions */
+/*@{*/
+
+/**
+Output a byte, doing bit-stuffing if necessary.
+After a 0xff byte, the next byte must be smaller than 0x90.
+@param mqc MQC handle
+*/
+static void mqc_byteout(opj_mqc_t *mqc);
+/**
+Renormalize mqc->a and mqc->c while encoding, so that mqc->a stays between 0x8000 and 0x10000
+@param mqc MQC handle
+*/
+static void mqc_renorme(opj_mqc_t *mqc);
+/**
+Encode the most probable symbol
+@param mqc MQC handle
+*/
+static void mqc_codemps(opj_mqc_t *mqc);
+/**
+Encode the most least symbol
+@param mqc MQC handle
+*/
+static void mqc_codelps(opj_mqc_t *mqc);
+/**
+Fill mqc->c with 1's for flushing
+@param mqc MQC handle
+*/
+static void mqc_setbits(opj_mqc_t *mqc);
+/**
+FIXME: documentation ???
+@param mqc MQC handle
+@return 
+*/
+static int mqc_mpsexchange(opj_mqc_t *mqc);
+/**
+FIXME: documentation ???
+@param mqc MQC handle
+@return 
+*/
+static int mqc_lpsexchange(opj_mqc_t *mqc);
+/**
+Input a byte
+@param mqc MQC handle
+*/
+static void mqc_bytein(opj_mqc_t *mqc);
+/**
+Renormalize mqc->a and mqc->c while decoding
+@param mqc MQC handle
+*/
+static void mqc_renormd(opj_mqc_t *mqc);
+
+/*@}*/
+
+/*@}*/
+
+/* <summary> */
+/* This array defines all the possible states for a context. */
+/* </summary> */
+static opj_mqc_state_t mqc_states[47 * 2] = {
+  {0x5601, 0, &mqc_states[2], &mqc_states[3]},
+  {0x5601, 1, &mqc_states[3], &mqc_states[2]},
+  {0x3401, 0, &mqc_states[4], &mqc_states[12]},
+  {0x3401, 1, &mqc_states[5], &mqc_states[13]},
+  {0x1801, 0, &mqc_states[6], &mqc_states[18]},
+  {0x1801, 1, &mqc_states[7], &mqc_states[19]},
+  {0x0ac1, 0, &mqc_states[8], &mqc_states[24]},
+  {0x0ac1, 1, &mqc_states[9], &mqc_states[25]},
+  {0x0521, 0, &mqc_states[10], &mqc_states[58]},
+  {0x0521, 1, &mqc_states[11], &mqc_states[59]},
+  {0x0221, 0, &mqc_states[76], &mqc_states[66]},
+  {0x0221, 1, &mqc_states[77], &mqc_states[67]},
+  {0x5601, 0, &mqc_states[14], &mqc_states[13]},
+  {0x5601, 1, &mqc_states[15], &mqc_states[12]},
+  {0x5401, 0, &mqc_states[16], &mqc_states[28]},
+  {0x5401, 1, &mqc_states[17], &mqc_states[29]},
+  {0x4801, 0, &mqc_states[18], &mqc_states[28]},
+  {0x4801, 1, &mqc_states[19], &mqc_states[29]},
+  {0x3801, 0, &mqc_states[20], &mqc_states[28]},
+  {0x3801, 1, &mqc_states[21], &mqc_states[29]},
+  {0x3001, 0, &mqc_states[22], &mqc_states[34]},
+  {0x3001, 1, &mqc_states[23], &mqc_states[35]},
+  {0x2401, 0, &mqc_states[24], &mqc_states[36]},
+  {0x2401, 1, &mqc_states[25], &mqc_states[37]},
+  {0x1c01, 0, &mqc_states[26], &mqc_states[40]},
+  {0x1c01, 1, &mqc_states[27], &mqc_states[41]},
+  {0x1601, 0, &mqc_states[58], &mqc_states[42]},
+  {0x1601, 1, &mqc_states[59], &mqc_states[43]},
+  {0x5601, 0, &mqc_states[30], &mqc_states[29]},
+  {0x5601, 1, &mqc_states[31], &mqc_states[28]},
+  {0x5401, 0, &mqc_states[32], &mqc_states[28]},
+  {0x5401, 1, &mqc_states[33], &mqc_states[29]},
+  {0x5101, 0, &mqc_states[34], &mqc_states[30]},
+  {0x5101, 1, &mqc_states[35], &mqc_states[31]},
+  {0x4801, 0, &mqc_states[36], &mqc_states[32]},
+  {0x4801, 1, &mqc_states[37], &mqc_states[33]},
+  {0x3801, 0, &mqc_states[38], &mqc_states[34]},
+  {0x3801, 1, &mqc_states[39], &mqc_states[35]},
+  {0x3401, 0, &mqc_states[40], &mqc_states[36]},
+  {0x3401, 1, &mqc_states[41], &mqc_states[37]},
+  {0x3001, 0, &mqc_states[42], &mqc_states[38]},
+  {0x3001, 1, &mqc_states[43], &mqc_states[39]},
+  {0x2801, 0, &mqc_states[44], &mqc_states[38]},
+  {0x2801, 1, &mqc_states[45], &mqc_states[39]},
+  {0x2401, 0, &mqc_states[46], &mqc_states[40]},
+  {0x2401, 1, &mqc_states[47], &mqc_states[41]},
+  {0x2201, 0, &mqc_states[48], &mqc_states[42]},
+  {0x2201, 1, &mqc_states[49], &mqc_states[43]},
+  {0x1c01, 0, &mqc_states[50], &mqc_states[44]},
+  {0x1c01, 1, &mqc_states[51], &mqc_states[45]},
+  {0x1801, 0, &mqc_states[52], &mqc_states[46]},
+  {0x1801, 1, &mqc_states[53], &mqc_states[47]},
+  {0x1601, 0, &mqc_states[54], &mqc_states[48]},
+  {0x1601, 1, &mqc_states[55], &mqc_states[49]},
+  {0x1401, 0, &mqc_states[56], &mqc_states[50]},
+  {0x1401, 1, &mqc_states[57], &mqc_states[51]},
+  {0x1201, 0, &mqc_states[58], &mqc_states[52]},
+  {0x1201, 1, &mqc_states[59], &mqc_states[53]},
+  {0x1101, 0, &mqc_states[60], &mqc_states[54]},
+  {0x1101, 1, &mqc_states[61], &mqc_states[55]},
+  {0x0ac1, 0, &mqc_states[62], &mqc_states[56]},
+  {0x0ac1, 1, &mqc_states[63], &mqc_states[57]},
+  {0x09c1, 0, &mqc_states[64], &mqc_states[58]},
+  {0x09c1, 1, &mqc_states[65], &mqc_states[59]},
+  {0x08a1, 0, &mqc_states[66], &mqc_states[60]},
+  {0x08a1, 1, &mqc_states[67], &mqc_states[61]},
+  {0x0521, 0, &mqc_states[68], &mqc_states[62]},
+  {0x0521, 1, &mqc_states[69], &mqc_states[63]},
+  {0x0441, 0, &mqc_states[70], &mqc_states[64]},
+  {0x0441, 1, &mqc_states[71], &mqc_states[65]},
+  {0x02a1, 0, &mqc_states[72], &mqc_states[66]},
+  {0x02a1, 1, &mqc_states[73], &mqc_states[67]},
+  {0x0221, 0, &mqc_states[74], &mqc_states[68]},
+  {0x0221, 1, &mqc_states[75], &mqc_states[69]},
+  {0x0141, 0, &mqc_states[76], &mqc_states[70]},
+  {0x0141, 1, &mqc_states[77], &mqc_states[71]},
+  {0x0111, 0, &mqc_states[78], &mqc_states[72]},
+  {0x0111, 1, &mqc_states[79], &mqc_states[73]},
+  {0x0085, 0, &mqc_states[80], &mqc_states[74]},
+  {0x0085, 1, &mqc_states[81], &mqc_states[75]},
+  {0x0049, 0, &mqc_states[82], &mqc_states[76]},
+  {0x0049, 1, &mqc_states[83], &mqc_states[77]},
+  {0x0025, 0, &mqc_states[84], &mqc_states[78]},
+  {0x0025, 1, &mqc_states[85], &mqc_states[79]},
+  {0x0015, 0, &mqc_states[86], &mqc_states[80]},
+  {0x0015, 1, &mqc_states[87], &mqc_states[81]},
+  {0x0009, 0, &mqc_states[88], &mqc_states[82]},
+  {0x0009, 1, &mqc_states[89], &mqc_states[83]},
+  {0x0005, 0, &mqc_states[90], &mqc_states[84]},
+  {0x0005, 1, &mqc_states[91], &mqc_states[85]},
+  {0x0001, 0, &mqc_states[90], &mqc_states[86]},
+  {0x0001, 1, &mqc_states[91], &mqc_states[87]},
+  {0x5601, 0, &mqc_states[92], &mqc_states[92]},
+  {0x5601, 1, &mqc_states[93], &mqc_states[93]},
+};
+
+/* 
+==========================================================
+   local functions
+==========================================================
+*/
+
+static void mqc_byteout(opj_mqc_t *mqc) {
+  if (*mqc->bp == 0xff) {
+    mqc->bp++;
+    *mqc->bp = mqc->c >> 20;
+    mqc->c &= 0xfffff;
+    mqc->ct = 7;
+  } else {
+    if ((mqc->c & 0x8000000) == 0) {  /* ((mqc->c&0x8000000)==0) CHANGE */
+      mqc->bp++;
+      *mqc->bp = mqc->c >> 19;
+      mqc->c &= 0x7ffff;
+      mqc->ct = 8;
+    } else {
+      (*mqc->bp)++;
+      if (*mqc->bp == 0xff) {
+        mqc->c &= 0x7ffffff;
+        mqc->bp++;
+        *mqc->bp = mqc->c >> 20;
+        mqc->c &= 0xfffff;
+        mqc->ct = 7;
+      } else {
+        mqc->bp++;
+        *mqc->bp = mqc->c >> 19;
+        mqc->c &= 0x7ffff;
+        mqc->ct = 8;
+      }
+    }
+  }
+}
+
+static void mqc_renorme(opj_mqc_t *mqc) {
+  do {
+    mqc->a <<= 1;
+    mqc->c <<= 1;
+    mqc->ct--;
+    if (mqc->ct == 0) {
+      mqc_byteout(mqc);
+    }
+  } while ((mqc->a & 0x8000) == 0);
+}
+
+static void mqc_codemps(opj_mqc_t *mqc) {
+  mqc->a -= (*mqc->curctx)->qeval;
+  if ((mqc->a & 0x8000) == 0) {
+    if (mqc->a < (*mqc->curctx)->qeval) {
+      mqc->a = (*mqc->curctx)->qeval;
+    } else {
+      mqc->c += (*mqc->curctx)->qeval;
+    }
+    *mqc->curctx = (*mqc->curctx)->nmps;
+    mqc_renorme(mqc);
+  } else {
+    mqc->c += (*mqc->curctx)->qeval;
+  }
+}
+
+static void mqc_codelps(opj_mqc_t *mqc) {
+  mqc->a -= (*mqc->curctx)->qeval;
+  if (mqc->a < (*mqc->curctx)->qeval) {
+    mqc->c += (*mqc->curctx)->qeval;
+  } else {
+    mqc->a = (*mqc->curctx)->qeval;
+  }
+  *mqc->curctx = (*mqc->curctx)->nlps;
+  mqc_renorme(mqc);
+}
+
+static void mqc_setbits(opj_mqc_t *mqc) {
+  unsigned int tempc = mqc->c + mqc->a;
+  mqc->c |= 0xffff;
+  if (mqc->c >= tempc) {
+    mqc->c -= 0x8000;
+  }
+}
+
+static int mqc_mpsexchange(opj_mqc_t *mqc) {
+  int d;
+  if (mqc->a < (*mqc->curctx)->qeval) {
+    d = 1 - (*mqc->curctx)->mps;
+    *mqc->curctx = (*mqc->curctx)->nlps;
+  } else {
+    d = (*mqc->curctx)->mps;
+    *mqc->curctx = (*mqc->curctx)->nmps;
+  }
+  
+  return d;
+}
+
+static int mqc_lpsexchange(opj_mqc_t *mqc) {
+  int d;
+  if (mqc->a < (*mqc->curctx)->qeval) {
+    mqc->a = (*mqc->curctx)->qeval;
+    d = (*mqc->curctx)->mps;
+    *mqc->curctx = (*mqc->curctx)->nmps;
+  } else {
+    mqc->a = (*mqc->curctx)->qeval;
+    d = 1 - (*mqc->curctx)->mps;
+    *mqc->curctx = (*mqc->curctx)->nlps;
+  }
+  
+  return d;
+}
+
+static void mqc_bytein(opj_mqc_t *mqc) {
+  if (mqc->bp != mqc->end) {
+    unsigned int c;
+    if (mqc->bp + 1 != mqc->end) {
+      c = *(mqc->bp + 1);
+    } else {
+      c = 0xff;
+    }
+    if (*mqc->bp == 0xff) {
+      if (c > 0x8f) {
+        mqc->c += 0xff00;
+        mqc->ct = 8;
+      } else {
+        mqc->bp++;
+        mqc->c += c << 9;
+        mqc->ct = 7;
+      }
+    } else {
+      mqc->bp++;
+      mqc->c += c << 8;
+      mqc->ct = 8;
+    }
+  } else {
+    mqc->c += 0xff00;
+    mqc->ct = 8;
+  }
+}
+
+static void mqc_renormd(opj_mqc_t *mqc) {
+  do {
+    if (mqc->ct == 0) {
+      mqc_bytein(mqc);
+    }
+    mqc->a <<= 1;
+    mqc->c <<= 1;
+    mqc->ct--;
+  } while (mqc->a < 0x8000);
+}
+
+/* 
+==========================================================
+   MQ-Coder interface
+==========================================================
+*/
+
+opj_mqc_t* mqc_create() {
+  opj_mqc_t *mqc = (opj_mqc_t*)opj_malloc(sizeof(opj_mqc_t));
+  return mqc;
+}
+
+void mqc_destroy(opj_mqc_t *mqc) {
+  if(mqc) {
+    opj_free(mqc);
+  }
+}
+
+int mqc_numbytes(opj_mqc_t *mqc) {
+  return mqc->bp - mqc->start;
+}
+
+void mqc_init_enc(opj_mqc_t *mqc, unsigned char *bp) {
+  mqc_setcurctx(mqc, 0);
+  mqc->a = 0x8000;
+  mqc->c = 0;
+  mqc->bp = bp - 1;
+  mqc->ct = 12;
+  if (*mqc->bp == 0xff) {
+    mqc->ct = 13;
+  }
+  mqc->start = bp;
+}
+
+void mqc_setcurctx(opj_mqc_t *mqc, int ctxno) {
+  mqc->curctx = &mqc->ctxs[ctxno];
+}
+
+void mqc_encode(opj_mqc_t *mqc, int d) {
+  if ((*mqc->curctx)->mps == d) {
+    mqc_codemps(mqc);
+  } else {
+    mqc_codelps(mqc);
+  }
+}
+
+void mqc_flush(opj_mqc_t *mqc) {
+  mqc_setbits(mqc);
+  mqc->c <<= mqc->ct;
+  mqc_byteout(mqc);
+  mqc->c <<= mqc->ct;
+  mqc_byteout(mqc);
+  
+  if (*mqc->bp != 0xff) {
+    mqc->bp++;
+  }
+}
+
+void mqc_bypass_init_enc(opj_mqc_t *mqc) {
+  mqc->c = 0;
+  mqc->ct = 8;
+  /*if (*mqc->bp == 0xff) {
+  mqc->ct = 7;
+     } */
+}
+
+void mqc_bypass_enc(opj_mqc_t *mqc, int d) {
+  mqc->ct--;
+  mqc->c = mqc->c + (d << mqc->ct);
+  if (mqc->ct == 0) {
+    mqc->bp++;
+    *mqc->bp = mqc->c;
+    mqc->ct = 8;
+    if (*mqc->bp == 0xff) {
+      mqc->ct = 7;
+    }
+    mqc->c = 0;
+  }
+}
+
+int mqc_bypass_flush_enc(opj_mqc_t *mqc) {
+  unsigned char bit_padding;
+  
+  bit_padding = 0;
+  
+  if (mqc->ct != 0) {
+    while (mqc->ct > 0) {
+      mqc->ct--;
+      mqc->c += bit_padding << mqc->ct;
+      bit_padding = (bit_padding + 1) & 0x01;
+    }
+    mqc->bp++;
+    *mqc->bp = mqc->c;
+    mqc->ct = 8;
+    mqc->c = 0;
+  }
+  
+  return 1;
+}
+
+void mqc_reset_enc(opj_mqc_t *mqc) {
+  mqc_resetstates(mqc);
+  mqc_setstate(mqc, 18, 0, 46);
+  mqc_setstate(mqc, 0, 0, 3);
+  mqc_setstate(mqc, 1, 0, 4);
+}
+
+int mqc_restart_enc(opj_mqc_t *mqc) {
+  int correction = 1;
+  
+  /* <flush part> */
+  int n = 27 - 15 - mqc->ct;
+  mqc->c <<= mqc->ct;
+  while (n > 0) {
+    mqc_byteout(mqc);
+    n -= mqc->ct;
+    mqc->c <<= mqc->ct;
+  }
+  mqc_byteout(mqc);
+  
+  return correction;
+}
+
+void mqc_restart_init_enc(opj_mqc_t *mqc) {
+  /* <Re-init part> */
+  mqc_setcurctx(mqc, 0);
+  mqc->a = 0x8000;
+  mqc->c = 0;
+  mqc->ct = 12;
+  mqc->bp--;
+  if (*mqc->bp == 0xff) {
+    mqc->ct = 13;
+  }
+}
+
+void mqc_erterm_enc(opj_mqc_t *mqc) {
+  int k = 11 - mqc->ct + 1;
+  
+  while (k > 0) {
+    mqc->c <<= mqc->ct;
+    mqc->ct = 0;
+    mqc_byteout(mqc);
+    k -= mqc->ct;
+  }
+  
+  if (*mqc->bp != 0xff) {
+    mqc_byteout(mqc);
+  }
+}
+
+void mqc_segmark_enc(opj_mqc_t *mqc) {
+  int i;
+  mqc_setcurctx(mqc, 18);
+  
+  for (i = 1; i < 5; i++) {
+    mqc_encode(mqc, i % 2);
+  }
+}
+
+void mqc_init_dec(opj_mqc_t *mqc, unsigned char *bp, int len) {
+  mqc_setcurctx(mqc, 0);
+  mqc->start = bp;
+  mqc->end = bp + len;
+  mqc->bp = bp;
+  if (len==0) mqc->c = 0xff << 16;
+  else mqc->c = *mqc->bp << 16;
+  mqc_bytein(mqc);
+  mqc->c <<= 7;
+  mqc->ct -= 7;
+  mqc->a = 0x8000;
+}
+
+int mqc_decode(opj_mqc_t *mqc) {
+  int d;
+  mqc->a -= (*mqc->curctx)->qeval;
+  if ((mqc->c >> 16) < (*mqc->curctx)->qeval) {
+    d = mqc_lpsexchange(mqc);
+    mqc_renormd(mqc);
+  } else {
+    mqc->c -= (*mqc->curctx)->qeval << 16;
+    if ((mqc->a & 0x8000) == 0) {
+      d = mqc_mpsexchange(mqc);
+      mqc_renormd(mqc);
+    } else {
+      d = (*mqc->curctx)->mps;
+    }
+  }
+
+  return d;
+}
+
+void mqc_resetstates(opj_mqc_t *mqc) {
+  int i;
+  for (i = 0; i < MQC_NUMCTXS; i++) {
+    mqc->ctxs[i] = mqc_states;
+  }
+}
+
+void mqc_setstate(opj_mqc_t *mqc, int ctxno, int msb, int prob) {
+  mqc->ctxs[ctxno] = &mqc_states[msb + (prob << 1)];
+}
+
+
diff --git a/Utilities/ITK/Utilities/openjpeg/mqc.h b/Utilities/ITK/Utilities/openjpeg/mqc.h
new file mode 100644
index 0000000000..0104048d0f
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/mqc.h
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MQC_H
+#define __MQC_H
+/**
+@file mqc.h
+@brief Implementation of an MQ-Coder (MQC)
+
+The functions in MQC.C have for goal to realize the MQ-coder operations. The functions
+in MQC.C are used by some function in T1.C.
+*/
+
+/** @defgroup MQC MQC - Implementation of an MQ-Coder */
+/*@{*/
+
+/**
+This struct defines the state of a context.
+*/
+typedef struct opj_mqc_state {
+  /** the probability of the Least Probable Symbol (0.75->0x8000, 1.5->0xffff) */
+  unsigned int qeval;
+  /** the Most Probable Symbol (0 or 1) */
+  int mps;
+  /** next state if the next encoded symbol is the MPS */
+  struct opj_mqc_state *nmps;
+  /** next state if the next encoded symbol is the LPS */
+  struct opj_mqc_state *nlps;
+} opj_mqc_state_t;
+
+#define MQC_NUMCTXS 32
+
+/**
+MQ coder
+*/
+typedef struct opj_mqc {
+  unsigned int c;
+  unsigned int a;
+  unsigned int ct;
+  unsigned char *bp;
+  unsigned char *start;
+  unsigned char *end;
+  opj_mqc_state_t *ctxs[MQC_NUMCTXS];
+  opj_mqc_state_t **curctx;
+} opj_mqc_t;
+
+/** @name Exported functions */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+/**
+Create a new MQC handle 
+@return Returns a new MQC handle if successful, returns NULL otherwise
+*/
+opj_mqc_t* mqc_create();
+/**
+Destroy a previously created MQC handle
+@param mqc MQC handle to destroy
+*/
+void mqc_destroy(opj_mqc_t *mqc);
+/**
+Return the number of bytes written/read since initialisation
+@param mqc MQC handle
+@return Returns the number of bytes already encoded
+*/
+int mqc_numbytes(opj_mqc_t *mqc);
+/**
+Reset the states of all the context of the coder/decoder 
+(each context is set to a state where 0 and 1 are more or less equiprobable)
+@param mqc MQC handle
+*/
+void mqc_resetstates(opj_mqc_t *mqc);
+/**
+Set the state of a particular context
+@param mqc MQC handle
+@param ctxno Number that identifies the context
+@param msb The MSB of the new state of the context
+@param prob Number that identifies the probability of the symbols for the new state of the context
+*/
+void mqc_setstate(opj_mqc_t *mqc, int ctxno, int msb, int prob);
+/**
+Initialize the encoder
+@param mqc MQC handle
+@param bp Pointer to the start of the buffer where the bytes will be written
+*/
+void mqc_init_enc(opj_mqc_t *mqc, unsigned char *bp);
+/**
+Set the current context used for coding/decoding
+@param mqc MQC handle
+@param ctxno Number that identifies the context
+*/
+void mqc_setcurctx(opj_mqc_t *mqc, int ctxno);
+/**
+Encode a symbol using the MQ-coder
+@param mqc MQC handle
+@param d The symbol to be encoded (0 or 1)
+*/
+void mqc_encode(opj_mqc_t *mqc, int d);
+/**
+Flush the encoder, so that all remaining data is written
+@param mqc MQC handle
+*/
+void mqc_flush(opj_mqc_t *mqc);
+/**
+BYPASS mode switch, initialization operation. 
+JPEG 2000 p 505. 
+<h2>Not fully implemented and tested !!</h2>
+@param mqc MQC handle
+*/
+void mqc_bypass_init_enc(opj_mqc_t *mqc);
+/**
+BYPASS mode switch, coding operation. 
+JPEG 2000 p 505. 
+<h2>Not fully implemented and tested !!</h2>
+@param mqc MQC handle
+@param d The symbol to be encoded (0 or 1)
+*/
+void mqc_bypass_enc(opj_mqc_t *mqc, int d);
+/**
+BYPASS mode switch, flush operation
+<h2>Not fully implemented and tested !!</h2>
+@param mqc MQC handle
+@return Returns 1 (always)
+*/
+int mqc_bypass_flush_enc(opj_mqc_t *mqc);
+/**
+RESET mode switch
+@param mqc MQC handle
+*/
+void mqc_reset_enc(opj_mqc_t *mqc);
+/**
+RESTART mode switch (TERMALL)
+@param mqc MQC handle
+@return Returns 1 (always)
+*/
+int mqc_restart_enc(opj_mqc_t *mqc);
+/**
+RESTART mode switch (TERMALL) reinitialisation
+@param mqc MQC handle
+*/
+void mqc_restart_init_enc(opj_mqc_t *mqc);
+/**
+ERTERM mode switch (PTERM)
+@param mqc MQC handle
+*/
+void mqc_erterm_enc(opj_mqc_t *mqc);
+/**
+SEGMARK mode switch (SEGSYM)
+@param mqc MQC handle
+*/
+void mqc_segmark_enc(opj_mqc_t *mqc);
+/**
+Initialize the decoder
+@param mqc MQC handle
+@param bp Pointer to the start of the buffer from which the bytes will be read
+@param len Length of the input buffer
+*/
+void mqc_init_dec(opj_mqc_t *mqc, unsigned char *bp, int len);
+/**
+Decode a symbol
+@param mqc MQC handle
+@return Returns the decoded symbol (0 or 1)
+*/
+int mqc_decode(opj_mqc_t *mqc);
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __MQC_H */
diff --git a/Utilities/ITK/Utilities/openjpeg/openjpeg.c b/Utilities/ITK/Utilities/openjpeg/openjpeg.c
new file mode 100644
index 0000000000..6097cdbafd
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/openjpeg.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif /* WIN32 */
+
+#include "opj_includes.h"
+
+/* ---------------------------------------------------------------------- */
+#ifdef WIN32
+#ifndef OPJ_STATIC
+BOOL APIENTRY
+DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
+  switch (ul_reason_for_call) {
+    case DLL_PROCESS_ATTACH :
+      break;
+    case DLL_PROCESS_DETACH :
+      break;
+    case DLL_THREAD_ATTACH :
+    case DLL_THREAD_DETACH :
+      break;
+    }
+
+    return TRUE;
+}
+#endif /* OPJ_STATIC */
+#endif /* WIN32 */
+
+/* ---------------------------------------------------------------------- */
+
+
+const char* OPJ_CALLCONV opj_version() {
+    return OPENJPEG_VERSION;
+}
+
+opj_dinfo_t* OPJ_CALLCONV opj_create_decompress(OPJ_CODEC_FORMAT format) {
+  opj_dinfo_t *dinfo = (opj_dinfo_t*)opj_malloc(sizeof(opj_dinfo_t));
+  if(!dinfo) return NULL;
+  dinfo->is_decompressor = true;
+  switch(format) {
+    case CODEC_J2K:
+    case CODEC_JPT:
+      /* get a J2K decoder handle */
+      dinfo->j2k_handle = (void*)j2k_create_decompress((opj_common_ptr)dinfo);
+      if(!dinfo->j2k_handle) {
+        opj_free(dinfo);
+        return NULL;
+      }
+      break;
+    case CODEC_JP2:
+      /* get a JP2 decoder handle */
+      dinfo->jp2_handle = (void*)jp2_create_decompress((opj_common_ptr)dinfo);
+      if(!dinfo->jp2_handle) {
+        opj_free(dinfo);
+        return NULL;
+      }
+      break;
+    case CODEC_UNKNOWN:
+    default:
+      opj_free(dinfo);
+      return NULL;
+  }
+
+  dinfo->codec_format = format;
+
+  return dinfo;
+}
+
+void OPJ_CALLCONV opj_destroy_decompress(opj_dinfo_t *dinfo) {
+  if(dinfo) {
+    /* destroy the codec */
+    switch(dinfo->codec_format) {
+      case CODEC_J2K:
+      case CODEC_JPT:
+        j2k_destroy_decompress((opj_j2k_t*)dinfo->j2k_handle);
+        break;
+      case CODEC_JP2:
+        jp2_destroy_decompress((opj_jp2_t*)dinfo->jp2_handle);
+        break;
+      case CODEC_UNKNOWN:
+      default:
+        break;
+    }
+    /* destroy the decompressor */
+    opj_free(dinfo);
+  }
+}
+
+void OPJ_CALLCONV opj_set_default_decoder_parameters(opj_dparameters_t *parameters) {
+  if(parameters) {
+    memset(parameters, 0, sizeof(opj_dparameters_t));
+    /* default decoding parameters */
+    parameters->cp_layer = 0;
+    parameters->cp_reduce = 0;
+
+    parameters->decod_format = -1;
+    parameters->cod_format = -1;
+  }
+}
+
+void OPJ_CALLCONV opj_setup_decoder(opj_dinfo_t *dinfo, opj_dparameters_t *parameters) {
+  if(dinfo && parameters) {
+    switch(dinfo->codec_format) {
+      case CODEC_J2K:
+      case CODEC_JPT:
+        j2k_setup_decoder((opj_j2k_t*)dinfo->j2k_handle, parameters);
+        break;
+      case CODEC_JP2:
+        jp2_setup_decoder((opj_jp2_t*)dinfo->jp2_handle, parameters);
+        break;
+      case CODEC_UNKNOWN:
+      default:
+        break;
+    }
+  }
+}
+
+opj_image_t* OPJ_CALLCONV opj_decode(opj_dinfo_t *dinfo, opj_cio_t *cio) {
+  if(dinfo && cio) {
+    switch(dinfo->codec_format) {
+      case CODEC_J2K:
+        return j2k_decode((opj_j2k_t*)dinfo->j2k_handle, cio);
+      case CODEC_JPT:
+        return j2k_decode_jpt_stream((opj_j2k_t*)dinfo->j2k_handle, cio);
+      case CODEC_JP2:
+        return jp2_decode((opj_jp2_t*)dinfo->jp2_handle, cio);
+      case CODEC_UNKNOWN:
+      default:
+        break;
+    }
+  }
+
+  return NULL;
+}
+
+opj_cinfo_t* OPJ_CALLCONV opj_create_compress(OPJ_CODEC_FORMAT format) {
+  opj_cinfo_t *cinfo = (opj_cinfo_t*)opj_malloc(sizeof(opj_cinfo_t));
+  if(!cinfo) return NULL;
+  cinfo->is_decompressor = false;
+  switch(format) {
+    case CODEC_J2K:
+      /* get a J2K coder handle */
+      cinfo->j2k_handle = (void*)j2k_create_compress((opj_common_ptr)cinfo);
+      if(!cinfo->j2k_handle) {
+        opj_free(cinfo);
+        return NULL;
+      }
+      break;
+    case CODEC_JP2:
+      /* get a JP2 coder handle */
+      cinfo->jp2_handle = (void*)jp2_create_compress((opj_common_ptr)cinfo);
+      if(!cinfo->jp2_handle) {
+        opj_free(cinfo);
+        return NULL;
+      }
+      break;
+    case CODEC_JPT:
+    case CODEC_UNKNOWN:
+    default:
+      opj_free(cinfo);
+      return NULL;
+  }
+
+  cinfo->codec_format = format;
+
+  return cinfo;
+}
+
+void OPJ_CALLCONV opj_destroy_compress(opj_cinfo_t *cinfo) {
+  if(cinfo) {
+    /* destroy the codec */
+    switch(cinfo->codec_format) {
+      case CODEC_J2K:
+        j2k_destroy_decompress((opj_j2k_t*)cinfo->j2k_handle);
+        break;
+      case CODEC_JP2:
+        jp2_destroy_decompress((opj_jp2_t*)cinfo->jp2_handle);
+        break;
+      case CODEC_JPT:
+      case CODEC_UNKNOWN:
+      default:
+        break;
+    }
+    /* destroy the decompressor */
+    opj_free(cinfo);
+  }
+}
+
+void OPJ_CALLCONV opj_set_default_encoder_parameters(opj_cparameters_t *parameters) {
+  if(parameters) {
+    memset(parameters, 0, sizeof(opj_cparameters_t));
+    /* default coding parameters */
+    parameters->numresolution = 6;
+    parameters->cblockw_init = 64;
+    parameters->cblockh_init = 64;
+    parameters->prog_order = LRCP;
+    parameters->roi_compno = -1;    /* no ROI */
+    parameters->subsampling_dx = 1;
+    parameters->subsampling_dy = 1;
+
+    parameters->decod_format = -1;
+    parameters->cod_format = -1;
+  }
+}
+
+void OPJ_CALLCONV opj_setup_encoder(opj_cinfo_t *cinfo, opj_cparameters_t *parameters, opj_image_t *image) {
+  if(cinfo && parameters && image) {
+    switch(cinfo->codec_format) {
+      case CODEC_J2K:
+        j2k_setup_encoder((opj_j2k_t*)cinfo->j2k_handle, parameters, image);
+        break;
+      case CODEC_JP2:
+        jp2_setup_encoder((opj_jp2_t*)cinfo->jp2_handle, parameters, image);
+        break;
+      case CODEC_JPT:
+      case CODEC_UNKNOWN:
+      default:
+        break;
+    }
+  }
+}
+
+bool OPJ_CALLCONV opj_encode(opj_cinfo_t *cinfo, opj_cio_t *cio, opj_image_t *image, char *index) {
+  if(cinfo && cio && image) {
+    switch(cinfo->codec_format) {
+      case CODEC_J2K:
+        return j2k_encode((opj_j2k_t*)cinfo->j2k_handle, cio, image, index);
+      case CODEC_JP2:
+        return jp2_encode((opj_jp2_t*)cinfo->jp2_handle, cio, image, index);
+      case CODEC_JPT:
+      case CODEC_UNKNOWN:
+      default:
+        break;
+    }
+  }
+
+  return false;
+}
+
+
diff --git a/Utilities/ITK/Utilities/openjpeg/openjpeg.h b/Utilities/ITK/Utilities/openjpeg/openjpeg.h
new file mode 100644
index 0000000000..641b3d6f33
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/openjpeg.h
@@ -0,0 +1,628 @@
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef OPENJPEG_H
+#define OPENJPEG_H
+
+#define OPENJPEG_VERSION "1.0.0"
+
+/* 
+==========================================================
+   Compiler directives
+==========================================================
+*/
+
+#if defined(OPJ_STATIC) || !(defined(WIN32) || defined(__WIN32__))
+#define OPJ_API
+#define OPJ_CALLCONV
+#else
+#define OPJ_CALLCONV __stdcall
+/*
+The following ifdef block is the standard way of creating macros which make exporting 
+from a DLL simpler. All files within this DLL are compiled with the OPJ_EXPORTS
+symbol defined on the command line. this symbol should not be defined on any project
+that uses this DLL. This way any other project whose source files include this file see 
+OPJ_API functions as being imported from a DLL, wheras this DLL sees symbols
+defined with this macro as being exported.
+*/
+#ifdef OPJ_EXPORTS
+#define OPJ_API __declspec(dllexport)
+#else
+#define OPJ_API __declspec(dllimport)
+#endif /* OPJ_EXPORTS */
+#endif /* !OPJ_STATIC || !WIN32 */
+
+#ifndef __cplusplus
+#if defined(HAVE_STDBOOL_H)
+/*
+The C language implementation does correctly provide the standard header
+file "stdbool.h".
+ */
+#include <stdbool.h>
+#else
+/*
+The C language implementation does not provide the standard header file
+"stdbool.h" as required by ISO/IEC 9899:1999.  Try to compensate for this
+braindamage below.
+*/
+#if !defined(bool)
+#define  bool  int
+#endif
+#if !defined(true)
+#define true  1
+#endif
+#if !defined(false)
+#define  false  0
+#endif
+#endif
+#endif /* __cplusplus */
+
+/* 
+==========================================================
+   Useful constant definitions
+==========================================================
+*/
+
+#ifndef MAX_PATH
+#define MAX_PATH 260  /**< Maximum allowed size for filenames */
+#endif /* MAX_PATH */
+
+#define J2K_MAXRLVLS 33          /**< Number of maximum resolution level authorized */
+#define J2K_MAXBANDS (3*J2K_MAXRLVLS-2)  /**< Number of maximum sub-band linked to number of resolution level */
+
+/* 
+==========================================================
+   enum definitions
+==========================================================
+*/
+
+/** Progression order */
+typedef enum PROG_ORDER {
+  PROG_UNKNOWN = -1,  /**< place-holder */
+  LRCP = 0,    /**< layer-resolution-component-precinct order */
+  RLCP = 1,    /**< resolution-layer-component-precinct order */
+  RPCL = 2,    /**< resolution-precinct-component-layer order */
+  PCRL = 3,    /**< precinct-component-resolution-layer order */
+  CPRL = 4    /**< component-precinct-resolution-layer order */
+} OPJ_PROG_ORDER;
+
+/**
+Supported image color spaces
+*/
+typedef enum COLOR_SPACE {
+  CLRSPC_UNKNOWN = -1,  /**< place-holder */
+  CLRSPC_SRGB = 1,    /**< sRGB */
+  CLRSPC_GRAY = 2,    /**< grayscale */
+  CLRSPC_SYCC = 3      /**< YUV */
+} OPJ_COLOR_SPACE;
+
+/**
+Supported codec
+*/
+typedef enum CODEC_FORMAT {
+  CODEC_UNKNOWN = -1,  /**< place-holder */
+  CODEC_J2K = 0,    /**< JPEG-2000 codestream : read/write */
+  CODEC_JPT = 1,    /**< JPT-stream (JPEG 2000, JPIP) : read only */
+  CODEC_JP2 = 2    /**< JPEG-2000 file format : read/write */
+} OPJ_CODEC_FORMAT;
+
+/* 
+==========================================================
+   event manager typedef definitions
+==========================================================
+*/
+
+/**
+Callback function prototype for events
+@param msg Event message
+@param client_data 
+*/
+typedef void (*opj_msg_callback) (const char *msg, void *client_data);
+
+/**
+Message handler object
+used for 
+<ul>
+<li>Error messages
+<li>Warning messages
+<li>Debugging messages
+</ul>
+*/
+typedef struct opj_event_mgr {
+  /** Error message callback if available, NULL otherwise */
+  opj_msg_callback error_handler;
+  /** Warning message callback if available, NULL otherwise */
+  opj_msg_callback warning_handler;
+  /** Debug message callback if available, NULL otherwise */
+  opj_msg_callback info_handler;
+} opj_event_mgr_t;
+
+
+/* 
+==========================================================
+   codec typedef definitions
+==========================================================
+*/
+
+/**
+Progression order changes
+*/
+typedef struct opj_poc {
+  int resno0, compno0;
+  int layno1, resno1, compno1;
+  OPJ_PROG_ORDER prg;
+  int tile;
+  char progorder[4];
+} opj_poc_t;
+
+/**
+Compression parameters
+*/
+typedef struct opj_cparameters {
+  /** size of tile: tile_size_on = false (not in argument) or = true (in argument) */
+  bool tile_size_on;
+  /** XTOsiz */
+  int cp_tx0;
+  /** YTOsiz */
+  int cp_ty0;
+  /** XTsiz */
+  int cp_tdx;
+  /** YTsiz */
+  int cp_tdy;
+  /** allocation by rate/distortion */
+  int cp_disto_alloc;
+  /** allocation by fixed layer */
+  int cp_fixed_alloc;
+  /** add fixed_quality */
+  int cp_fixed_quality;
+  /** fixed layer */
+  int *cp_matrice;
+  /** comment for coding */
+  char *cp_comment;
+  /** csty : coding style */
+  int csty;
+  /** progression order (default LRCP) */
+  OPJ_PROG_ORDER prog_order;
+  /** progression order changes */
+  opj_poc_t POC[32];
+  /** number of progression order changes (POC), default to 0 */
+  int numpocs;
+  /** number of layers */
+  int tcp_numlayers;
+  /** rates of layers */
+  int tcp_rates[100];
+  /** different psnr for successive layers */
+  float tcp_distoratio[100];
+  /** number of resolutions */
+  int numresolution;
+  /** initial code block width, default to 64 */
+   int cblockw_init;
+  /** initial code block height, default to 64 */
+  int cblockh_init;
+  /** mode switch (cblk_style) */
+  int mode;
+  /** 1 : use the irreversible DWT 9-7, 0 : use lossless compression (default) */
+  int irreversible;
+  /** region of interest: affected component in [0..3], -1 means no ROI */
+  int roi_compno;
+  /** region of interest: upshift value */
+  int roi_shift;
+  /* number of precinct size specifications */
+  int res_spec;
+  /** initial precinct width */
+  int prcw_init[J2K_MAXRLVLS];
+  /** initial precinct height */
+  int prch_init[J2K_MAXRLVLS];
+
+  /**@name command line encoder parameters (not used inside the library) */
+  /*@{*/
+  /** input file name */
+  char infile[MAX_PATH];
+  /** output file name */
+  char outfile[MAX_PATH];
+  /** creation of an index file, default to 0 (false) */
+  int index_on;
+  /** index file name */
+  char index[MAX_PATH];
+  /** subimage encoding: origin image offset in x direction */
+  int image_offset_x0;
+  /** subimage encoding: origin image offset in y direction */
+  int image_offset_y0;
+  /** subsampling value for dx */
+  int subsampling_dx;
+  /** subsampling value for dy */
+  int subsampling_dy;
+  /** input file format 0: PGX, 1: PxM, 2: BMP */
+  int decod_format;
+  /** output file format 0: J2K, 1: JP2, 2: JPT */
+  int cod_format;
+  /*@}*/
+} opj_cparameters_t;
+
+/**
+Decompression parameters
+*/
+typedef struct opj_dparameters {
+  /** 
+  Set the number of highest resolution levels to be discarded. 
+  The image resolution is effectively divided by 2 to the power of the number of discarded levels. 
+  The reduce factor is limited by the smallest total number of decomposition levels among tiles.
+  if != 0, then original dimension divided by 2^(reduce); 
+  if == 0 or not used, image is decoded to the full resolution 
+  */
+  int cp_reduce;
+  /** 
+  Set the maximum number of quality layers to decode. 
+  If there are less quality layers than the specified number, all the quality layers are decoded.
+  if != 0, then only the first "layer" layers are decoded; 
+  if == 0 or not used, all the quality layers are decoded 
+  */
+  int cp_layer;
+
+  /**@name command line encoder parameters (not used inside the library) */
+  /*@{*/
+  /** input file name */
+  char infile[MAX_PATH];
+  /** output file name */
+  char outfile[MAX_PATH];
+  /** input file format 0: J2K, 1: JP2, 2: JPT */
+  int decod_format;
+  /** output file format 0: PGX, 1: PxM, 2: BMP */
+  int cod_format;
+  /*@}*/
+} opj_dparameters_t;
+
+/** Common fields between JPEG-2000 compression and decompression master structs. */
+
+#define opj_common_fields \
+  opj_event_mgr_t *event_mgr;  /**< pointer to the event manager */\
+  void * client_data;      /**< Available for use by application */\
+  bool is_decompressor;    /**< So common code can tell which is which */\
+  OPJ_CODEC_FORMAT codec_format;  /**< selected codec */\
+  void *j2k_handle;      /**< pointer to the J2K codec */\
+  void *jp2_handle      /**< pointer to the JP2 codec */
+  
+/* Routines that are to be used by both halves of the library are declared
+ * to receive a pointer to this structure.  There are no actual instances of
+ * opj_common_struct_t, only of opj_cinfo_t and opj_dinfo_t.
+ */
+typedef struct opj_common_struct {
+  opj_common_fields;    /* Fields common to both master struct types */
+  /* Additional fields follow in an actual opj_cinfo_t or
+   * opj_dinfo_t.  All three structs must agree on these
+   * initial fields!  (This would be a lot cleaner in C++.)
+   */
+} opj_common_struct_t;
+
+typedef opj_common_struct_t * opj_common_ptr;
+
+/**
+Compression context info
+*/
+typedef struct opj_cinfo {
+  /** Fields shared with opj_dinfo_t */
+  opj_common_fields;  
+  /* other specific fields go here */
+} opj_cinfo_t;
+
+/**
+Decompression context info
+*/
+typedef struct opj_dinfo {
+  /** Fields shared with opj_cinfo_t */
+  opj_common_fields;  
+  /* other specific fields go here */
+} opj_dinfo_t;
+
+/* 
+==========================================================
+   I/O stream typedef definitions
+==========================================================
+*/
+
+/*
+ * Stream open flags.
+ */
+/** The stream was opened for reading. */
+#define OPJ_STREAM_READ  0x0001
+/** The stream was opened for writing. */
+#define OPJ_STREAM_WRITE 0x0002
+
+/**
+Byte input-output stream (CIO)
+*/
+typedef struct opj_cio {
+  /** codec context */
+  opj_common_ptr cinfo;
+
+  /** open mode (read/write) either OPJ_STREAM_READ or OPJ_STREAM_WRITE */
+  int openmode;
+  /** pointer to the start of the buffer */
+  unsigned char *buffer;
+  /** buffer size in bytes */
+  int length;
+
+  /** pointer to the start of the stream */
+  unsigned char *start;
+  /** pointer to the end of the stream */
+  unsigned char *end;
+  /** pointer to the current position */
+  unsigned char *bp;
+} opj_cio_t;
+
+/* 
+==========================================================
+   image typedef definitions
+==========================================================
+*/
+
+/**
+Defines a single image component
+*/
+typedef struct opj_image_comp {
+  /** XRsiz: horizontal separation of a sample of ith component with respect to the reference grid */
+  int dx;
+  /** YRsiz: vertical separation of a sample of ith component with respect to the reference grid */
+  int dy;
+  /** data width */
+  int w;
+  /** data height */
+  int h;
+  /** x component offset compared to the whole image */
+  int x0;
+  /** y component offset compared to the whole image */
+  int y0;
+  /** precision */
+  int prec;
+  /** image depth in bits */
+  int bpp;
+  /** signed (1) / unsigned (0) */
+  int sgnd;
+  /** number of decoded resolution */
+  int resno_decoded;
+  /** number of division by 2 of the out image compared to the original size of image */
+  int factor;
+  /** image component data */
+  int *data;
+} opj_image_comp_t;
+
+/** 
+Defines image data and characteristics
+*/
+typedef struct opj_image {
+  /** XOsiz: horizontal offset from the origin of the reference grid to the left side of the image area */
+  int x0;
+  /** YOsiz: vertical offset from the origin of the reference grid to the top side of the image area */
+  int y0;
+  /** Xsiz: width of the reference grid */
+  int x1;
+  /** Ysiz: height of the reference grid */
+  int y1;
+  /** number of components in the image */
+  int numcomps;
+  /** color space: sRGB, Greyscale or YUV */
+  OPJ_COLOR_SPACE color_space;
+  /** image components */
+  opj_image_comp_t *comps;
+} opj_image_t;
+
+/**
+Component parameters structure used by the opj_image_create function
+*/
+typedef struct opj_image_comptparm {
+  /** XRsiz: horizontal separation of a sample of ith component with respect to the reference grid */
+  int dx;
+  /** YRsiz: vertical separation of a sample of ith component with respect to the reference grid */
+  int dy;
+  /** data width */
+  int w;
+  /** data height */
+  int h;
+  /** x component offset compared to the whole image */
+  int x0;
+  /** y component offset compared to the whole image */
+  int y0;
+  /** precision */
+  int prec;
+  /** image depth in bits */
+  int bpp;
+  /** signed (1) / unsigned (0) */
+  int sgnd;
+} opj_image_cmptparm_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* 
+==========================================================
+   openjpeg version
+==========================================================
+*/
+
+OPJ_API const char * OPJ_CALLCONV opj_version();
+
+/* 
+==========================================================
+   image functions definitions
+==========================================================
+*/
+
+/**
+Create an image
+@param numcmpts number of components
+@param cmptparms components parameters
+@param clrspc image color space
+@return returns a new image structure if successful, returns NULL otherwise
+*/
+OPJ_API opj_image_t* OPJ_CALLCONV opj_image_create(int numcmpts, opj_image_cmptparm_t *cmptparms, OPJ_COLOR_SPACE clrspc);
+
+/**
+Deallocate any resources associated with an image
+@param image image to be destroyed
+*/
+OPJ_API void OPJ_CALLCONV opj_image_destroy(opj_image_t *image);
+
+/* 
+==========================================================
+   stream functions definitions
+==========================================================
+*/
+
+/**
+Open and allocate a memory stream for read / write. 
+On reading, the user must provide a buffer containing encoded data. The buffer will be 
+wrapped by the returned CIO handle. 
+On writing, buffer parameters must be set to 0: a buffer will be allocated by the library 
+to contain encoded data. 
+@param cinfo Codec context info
+@param buffer Reading: buffer address. Writing: NULL
+@param length Reading: buffer length. Writing: 0
+@return Returns a CIO handle if successful, returns NULL otherwise
+*/
+OPJ_API opj_cio_t* OPJ_CALLCONV opj_cio_open(opj_common_ptr cinfo, unsigned char *buffer, int length);
+
+/**
+Close and free a CIO handle
+@param cio CIO handle to free
+*/
+OPJ_API void OPJ_CALLCONV opj_cio_close(opj_cio_t *cio);
+
+/**
+Get position in byte stream
+@param cio CIO handle
+@return Returns the position in bytes
+*/
+OPJ_API int OPJ_CALLCONV cio_tell(opj_cio_t *cio);
+/**
+Set position in byte stream
+@param cio CIO handle
+@param pos Position, in number of bytes, from the beginning of the stream
+*/
+OPJ_API void OPJ_CALLCONV cio_seek(opj_cio_t *cio, int pos);
+
+/* 
+==========================================================
+   event manager functions definitions
+==========================================================
+*/
+
+OPJ_API opj_event_mgr_t* OPJ_CALLCONV opj_set_event_mgr(opj_common_ptr cinfo, opj_event_mgr_t *event_mgr, void *context);
+
+/* 
+==========================================================
+   codec functions definitions
+==========================================================
+*/
+/**
+Creates a J2K/JPT/JP2 decompression structure
+@param format Decoder to select
+@return Returns a handle to a decompressor if successful, returns NULL otherwise
+*/
+OPJ_API opj_dinfo_t* OPJ_CALLCONV opj_create_decompress(OPJ_CODEC_FORMAT format);
+/**
+Destroy a decompressor handle
+@param dinfo decompressor handle to destroy
+*/
+OPJ_API void OPJ_CALLCONV opj_destroy_decompress(opj_dinfo_t *dinfo);
+/**
+Set decoding parameters to default values
+@param parameters Decompression parameters
+*/
+OPJ_API void OPJ_CALLCONV opj_set_default_decoder_parameters(opj_dparameters_t *parameters);
+/**
+Setup the decoder decoding parameters using user parameters.
+Decoding parameters are returned in j2k->cp. 
+@param dinfo decompressor handle
+@param parameters decompression parameters
+*/
+OPJ_API void OPJ_CALLCONV opj_setup_decoder(opj_dinfo_t *dinfo, opj_dparameters_t *parameters);
+/**
+Decode an image from a JPEG-2000 codestream
+@param dinfo decompressor handle
+@param cio Input buffer stream
+@return Returns a decoded image if successful, returns NULL otherwise
+*/
+OPJ_API opj_image_t* OPJ_CALLCONV opj_decode(opj_dinfo_t *dinfo, opj_cio_t *cio);
+/**
+Creates a J2K/JP2 compression structure
+@param format Coder to select
+@return Returns a handle to a compressor if successful, returns NULL otherwise
+*/
+OPJ_API opj_cinfo_t* OPJ_CALLCONV opj_create_compress(OPJ_CODEC_FORMAT format);
+/**
+Destroy a compressor handle
+@param cinfo compressor handle to destroy
+*/
+OPJ_API void OPJ_CALLCONV opj_destroy_compress(opj_cinfo_t *cinfo);
+/**
+Set encoding parameters to default values, that means : 
+<ul>
+<li>Lossless
+<li>1 tile
+<li>Size of precinct : 2^15 x 2^15 (means 1 precinct)
+<li>Size of code-block : 64 x 64
+<li>Number of resolutions: 6
+<li>No SOP marker in the codestream
+<li>No EPH marker in the codestream
+<li>No sub-sampling in x or y direction
+<li>No mode switch activated
+<li>Progression order: LRCP
+<li>No index file
+<li>No ROI upshifted
+<li>No offset of the origin of the image
+<li>No offset of the origin of the tiles
+<li>Reversible DWT 5-3
+</ul>
+@param parameters Compression parameters
+*/
+OPJ_API void OPJ_CALLCONV opj_set_default_encoder_parameters(opj_cparameters_t *parameters);
+/**
+Setup the encoder parameters using the current image and using user parameters. 
+@param cinfo compressor handle
+@param parameters compression parameters
+@param image input filled image
+*/
+OPJ_API void OPJ_CALLCONV opj_setup_encoder(opj_cinfo_t *cinfo, opj_cparameters_t *parameters, opj_image_t *image);
+/**
+Encode an image into a JPEG-2000 codestream
+@param cinfo compressor handle
+@param cio Output buffer stream
+@param image Image to encode
+@param index Name of the index file if required, NULL otherwise
+@return Returns true if successful, returns false otherwise
+*/
+OPJ_API bool OPJ_CALLCONV opj_encode(opj_cinfo_t *cinfo, opj_cio_t *cio, opj_image_t *image, char *index);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OPENJPEG_H */
diff --git a/Utilities/ITK/Utilities/openjpeg/opj_includes.h b/Utilities/ITK/Utilities/openjpeg/opj_includes.h
new file mode 100644
index 0000000000..13240323cc
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/opj_includes.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef OPJ_INCLUDES_H
+#define OPJ_INCLUDES_H
+
+/*
+ ==========================================================
+   Standard includes used by the library
+ ==========================================================
+*/
+#include <memory.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+#include <time.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <ctype.h>
+
+/*
+ ==========================================================
+   OpenJPEG interface
+ ==========================================================
+ */
+#include "openjpeg.h"
+
+/*
+ ==========================================================
+   OpenJPEG modules
+ ==========================================================
+*/
+
+/*
+The inline keyword is supported by C99 but not by C90. 
+Most compilers implement their own version of this keyword ... 
+*/
+#ifndef INLINE
+  #if defined(_MSC_VER)
+    #define INLINE __inline
+  #elif defined(__GNUC__)
+    #define INLINE __inline__
+  #elif defined(__MWERKS__)
+    #define INLINE inline
+  #else 
+    /* add other compilers here ... */
+    #define INLINE 
+  #endif /* defined(<Compiler>) */
+#endif /* INLINE */
+
+#include "j2k_lib.h"
+#include "event.h"
+#include "cio.h"
+
+#include "image.h"
+#include "j2k.h"
+#include "jp2.h"
+#include "jpt.h"
+
+#include "mqc.h"
+#include "raw.h"
+#include "bio.h"
+#include "tgt.h"
+#include "tcd.h"
+#include "t1.h"
+#include "dwt.h"
+#include "pi.h"
+#include "t2.h"
+#include "mct.h"
+#include "int.h"
+#include "fix.h"
+
+
+#endif /* OPJ_INCLUDES_H */
diff --git a/Utilities/ITK/Utilities/openjpeg/pi.c b/Utilities/ITK/Utilities/openjpeg/pi.c
new file mode 100644
index 0000000000..589124474d
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/pi.c
@@ -0,0 +1,554 @@
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opj_includes.h"
+
+/** @defgroup PI PI - Implementation of a packet iterator */
+/*@{*/
+
+/** @name Local static functions */
+/*@{*/
+
+/**
+Get next packet in layer-resolution-component-precinct order.
+@param pi packet iterator to modify
+@return returns false if pi pointed to the last packet or else returns true 
+*/
+static bool pi_next_lrcp(opj_pi_iterator_t * pi);
+/**
+Get next packet in resolution-layer-component-precinct order.
+@param pi packet iterator to modify
+@return returns false if pi pointed to the last packet or else returns true 
+*/
+static bool pi_next_rlcp(opj_pi_iterator_t * pi);
+/**
+Get next packet in resolution-precinct-component-layer order.
+@param pi packet iterator to modify
+@return returns false if pi pointed to the last packet or else returns true 
+*/
+static bool pi_next_rpcl(opj_pi_iterator_t * pi);
+/**
+Get next packet in precinct-component-resolution-layer order.
+@param pi packet iterator to modify
+@return returns false if pi pointed to the last packet or else returns true 
+*/
+static bool pi_next_pcrl(opj_pi_iterator_t * pi);
+/**
+Get next packet in component-precinct-resolution-layer order.
+@param pi packet iterator to modify
+@return returns false if pi pointed to the last packet or else returns true 
+*/
+static bool pi_next_cprl(opj_pi_iterator_t * pi);
+
+/*@}*/
+
+/*@}*/
+
+/* 
+==========================================================
+   local functions
+==========================================================
+*/
+
+static bool pi_next_lrcp(opj_pi_iterator_t * pi) {
+  opj_pi_comp_t *comp = NULL;
+  opj_pi_resolution_t *res = NULL;
+  long index = 0;
+  
+  if (!pi->first) {
+    comp = &pi->comps[pi->compno];
+    res = &comp->resolutions[pi->resno];
+    goto LABEL_SKIP;
+  } else {
+    pi->first = 0;
+  }
+
+  for (pi->layno = 0; pi->layno < pi->poc.layno1; pi->layno++) {
+    for (pi->resno = pi->poc.resno0; pi->resno < pi->poc.resno1;
+    pi->resno++) {
+      for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) {
+        comp = &pi->comps[pi->compno];
+        if (pi->resno >= comp->numresolutions) {
+          continue;
+        }
+        res = &comp->resolutions[pi->resno];
+        for (pi->precno = 0; pi->precno < res->pw * res->ph; pi->precno++) {
+          index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p;
+          if (!pi->include[index]) {
+            pi->include[index] = 1;
+            return true;
+          }
+LABEL_SKIP:;
+        }
+      }
+    }
+  }
+  
+  return false;
+}
+
+static bool pi_next_rlcp(opj_pi_iterator_t * pi) {
+  opj_pi_comp_t *comp = NULL;
+  opj_pi_resolution_t *res = NULL;
+  long index = 0;
+
+  if (!pi->first) {
+    comp = &pi->comps[pi->compno];
+    res = &comp->resolutions[pi->resno];
+    goto LABEL_SKIP;
+  } else {
+    pi->first = 0;
+  }
+
+  for (pi->resno = pi->poc.resno0; pi->resno < pi->poc.resno1; pi->resno++) {
+    for (pi->layno = 0; pi->layno < pi->poc.layno1; pi->layno++) {
+      for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) {
+        comp = &pi->comps[pi->compno];
+        if (pi->resno >= comp->numresolutions) {
+          continue;
+        }
+        res = &comp->resolutions[pi->resno];
+        for (pi->precno = 0; pi->precno < res->pw * res->ph; pi->precno++) {
+          index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p;
+          if (!pi->include[index]) {
+            pi->include[index] = 1;
+            return true;
+          }
+LABEL_SKIP:;
+        }
+      }
+    }
+  }
+  
+  return false;
+}
+
+static bool pi_next_rpcl(opj_pi_iterator_t * pi) {
+  opj_pi_comp_t *comp = NULL;
+  opj_pi_resolution_t *res = NULL;
+  long index = 0;
+
+  if (!pi->first) {
+    goto LABEL_SKIP;
+  } else {
+    int compno, resno;
+    pi->first = 0;
+    pi->dx = 0;
+    pi->dy = 0;
+    for (compno = 0; compno < pi->numcomps; compno++) {
+      comp = &pi->comps[compno];
+      for (resno = 0; resno < comp->numresolutions; resno++) {
+        int dx, dy;
+        res = &comp->resolutions[resno];
+        dx = comp->dx * (1 << (res->pdx + comp->numresolutions - 1 - resno));
+        dy = comp->dy * (1 << (res->pdy + comp->numresolutions - 1 - resno));
+        pi->dx = !pi->dx ? dx : int_min(pi->dx, dx);
+        pi->dy = !pi->dy ? dy : int_min(pi->dy, dy);
+      }
+    }
+  }
+
+  for (pi->resno = pi->poc.resno0; pi->resno < pi->poc.resno1; pi->resno++) {
+    for (pi->y = pi->ty0; pi->y < pi->ty1; pi->y += pi->dy - (pi->y % pi->dy)) {
+      for (pi->x = pi->tx0; pi->x < pi->tx1; pi->x += pi->dx - (pi->x % pi->dx)) {
+        for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) {
+          int levelno;
+          int trx0, try0;
+          int trx1, try1;
+          int rpx, rpy;
+          int prci, prcj;
+          comp = &pi->comps[pi->compno];
+          if (pi->resno >= comp->numresolutions) {
+            continue;
+          }
+          res = &comp->resolutions[pi->resno];
+          levelno = comp->numresolutions - 1 - pi->resno;
+          trx0 = int_ceildiv(pi->tx0, comp->dx << levelno);
+          try0 = int_ceildiv(pi->ty0, comp->dy << levelno);
+          trx1 = int_ceildiv(pi->tx1, comp->dx << levelno);
+          try1 = int_ceildiv(pi->ty1, comp->dy << levelno);
+          rpx = res->pdx + levelno;
+          rpy = res->pdy + levelno;
+          if ((!(pi->x % (comp->dx << rpx) == 0) || (pi->x == pi->tx0 && (trx0 << levelno) % (1 << rpx)))) {
+            continue;
+          }
+          if ((!(pi->y % (comp->dy << rpy) == 0) || (pi->y == pi->ty0 && (try0 << levelno) % (1 << rpx)))) {
+            continue;
+          }
+          
+          if ((res->pw==0)||(res->pw==0)) continue;
+          
+          if ((trx0==trx1)||(try0==try1)) continue;
+          
+          prci = int_floordivpow2(int_ceildiv(pi->x, comp->dx << levelno), res->pdx) 
+             - int_floordivpow2(trx0, res->pdx);
+          prcj = int_floordivpow2(int_ceildiv(pi->y, comp->dy << levelno), res->pdy) 
+             - int_floordivpow2(try0, res->pdy);
+          pi->precno = prci + prcj * res->pw;
+          for (pi->layno = 0; pi->layno < pi->poc.layno1; pi->layno++) {
+            index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p;
+            if (!pi->include[index]) {
+              pi->include[index] = 1;
+              return true;
+            }
+LABEL_SKIP:;
+          }
+        }
+      }
+    }
+  }
+  
+  return false;
+}
+
+static bool pi_next_pcrl(opj_pi_iterator_t * pi) {
+  opj_pi_comp_t *comp = NULL;
+  opj_pi_resolution_t *res = NULL;
+  long index = 0;
+
+  if (!pi->first) {
+    comp = &pi->comps[pi->compno];
+    goto LABEL_SKIP;
+  } else {
+    int compno, resno;
+    pi->first = 0;
+    pi->dx = 0;
+    pi->dy = 0;
+    for (compno = 0; compno < pi->numcomps; compno++) {
+      comp = &pi->comps[compno];
+      for (resno = 0; resno < comp->numresolutions; resno++) {
+        int dx, dy;
+        res = &comp->resolutions[resno];
+        dx = comp->dx * (1 << (res->pdx + comp->numresolutions - 1 - resno));
+        dy = comp->dy * (1 << (res->pdy + comp->numresolutions - 1 - resno));
+        pi->dx = !pi->dx ? dx : int_min(pi->dx, dx);
+        pi->dy = !pi->dy ? dy : int_min(pi->dy, dy);
+      }
+    }
+  }
+
+  for (pi->y = pi->ty0; pi->y < pi->ty1; pi->y += pi->dy - (pi->y % pi->dy)) {
+    for (pi->x = pi->tx0; pi->x < pi->tx1; pi->x += pi->dx - (pi->x % pi->dx)) {
+      for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) {
+        comp = &pi->comps[pi->compno];
+        for (pi->resno = pi->poc.resno0; pi->resno < int_min(pi->poc.resno1, comp->numresolutions); pi->resno++) {
+          int levelno;
+          int trx0, try0;
+          int trx1, try1;
+          int rpx, rpy;
+          int prci, prcj;
+          res = &comp->resolutions[pi->resno];
+          levelno = comp->numresolutions - 1 - pi->resno;
+          trx0 = int_ceildiv(pi->tx0, comp->dx << levelno);
+          try0 = int_ceildiv(pi->ty0, comp->dy << levelno);
+          trx1 = int_ceildiv(pi->tx1, comp->dx << levelno);
+          try1 = int_ceildiv(pi->ty1, comp->dy << levelno);
+          rpx = res->pdx + levelno;
+          rpy = res->pdy + levelno;
+          if ((!(pi->x % (comp->dx << rpx) == 0) || (pi->x == pi->tx0 && (trx0 << levelno) % (1 << rpx)))) {
+            continue;
+          }
+          if ((!(pi->y % (comp->dy << rpy) == 0) || (pi->y == pi->ty0 && (try0 << levelno) % (1 << rpx)))) {
+            continue;
+          }
+          
+          if ((res->pw==0)||(res->pw==0)) continue;
+          
+          if ((trx0==trx1)||(try0==try1)) continue;
+          
+          prci = int_floordivpow2(int_ceildiv(pi->x, comp->dx << levelno), res->pdx) 
+             - int_floordivpow2(trx0, res->pdx);
+          prcj = int_floordivpow2(int_ceildiv(pi->y, comp->dy << levelno), res->pdy) 
+             - int_floordivpow2(try0, res->pdy);
+          pi->precno = prci + prcj * res->pw;
+          for (pi->layno = 0; pi->layno < pi->poc.layno1; pi->layno++) {
+            index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p;
+            if (!pi->include[index]) {
+              pi->include[index] = 1;
+              return true;
+            }  
+LABEL_SKIP:;
+          }
+        }
+      }
+    }
+  }
+  
+  return false;
+}
+
+static bool pi_next_cprl(opj_pi_iterator_t * pi) {
+  opj_pi_comp_t *comp = NULL;
+  opj_pi_resolution_t *res = NULL;
+  long index = 0;
+
+  if (!pi->first) {
+    comp = &pi->comps[pi->compno];
+    goto LABEL_SKIP;
+  } else {
+    pi->first = 0;
+  }
+
+  for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) {
+    int resno;
+    comp = &pi->comps[pi->compno];
+    pi->dx = 0;
+    pi->dy = 0;
+    for (resno = 0; resno < comp->numresolutions; resno++) {
+      int dx, dy;
+      res = &comp->resolutions[resno];
+      dx = comp->dx * (1 << (res->pdx + comp->numresolutions - 1 - resno));
+      dy = comp->dy * (1 << (res->pdy + comp->numresolutions - 1 - resno));
+      pi->dx = !pi->dx ? dx : int_min(pi->dx, dx);
+      pi->dy = !pi->dy ? dy : int_min(pi->dy, dy);
+    }
+    for (pi->y = pi->ty0; pi->y < pi->ty1; pi->y += pi->dy - (pi->y % pi->dy)) {
+      for (pi->x = pi->tx0; pi->x < pi->tx1; pi->x += pi->dx - (pi->x % pi->dx)) {
+        for (pi->resno = pi->poc.resno0; pi->resno < int_min(pi->poc.resno1, comp->numresolutions); pi->resno++) {
+          int levelno;
+          int trx0, try0;
+          int trx1, try1;
+          int rpx, rpy;
+          int prci, prcj;
+          res = &comp->resolutions[pi->resno];
+          levelno = comp->numresolutions - 1 - pi->resno;
+          trx0 = int_ceildiv(pi->tx0, comp->dx << levelno);
+          try0 = int_ceildiv(pi->ty0, comp->dy << levelno);
+          trx1 = int_ceildiv(pi->tx1, comp->dx << levelno);
+          try1 = int_ceildiv(pi->ty1, comp->dy << levelno);
+          rpx = res->pdx + levelno;
+          rpy = res->pdy + levelno;
+          if ((!(pi->x % (comp->dx << rpx) == 0) || (pi->x == pi->tx0 && (trx0 << levelno) % (1 << rpx)))) {
+            continue;
+          }
+          if ((!(pi->y % (comp->dy << rpy) == 0) || (pi->y == pi->ty0 && (try0 << levelno) % (1 << rpx)))) {
+            continue;
+          }
+          
+          if ((res->pw==0)||(res->pw==0)) continue;
+          
+          if ((trx0==trx1)||(try0==try1)) continue;
+          
+          prci = int_floordivpow2(int_ceildiv(pi->x, comp->dx << levelno), res->pdx) 
+             - int_floordivpow2(trx0, res->pdx);
+          prcj = int_floordivpow2(int_ceildiv(pi->y, comp->dy << levelno), res->pdy) 
+             - int_floordivpow2(try0, res->pdy);
+          pi->precno = prci + prcj * res->pw;
+          for (pi->layno = 0; pi->layno < pi->poc.layno1; pi->layno++) {
+            index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p;
+            if (!pi->include[index]) {
+              pi->include[index] = 1;
+              return true;
+            }
+LABEL_SKIP:;
+          }
+        }
+      }
+    }
+  }
+  
+  return false;
+}
+
+/* 
+==========================================================
+   Packet iterator interface
+==========================================================
+*/
+
+opj_pi_iterator_t *pi_create(opj_image_t *image, opj_cp_t *cp, int tileno) {
+  int p, q;
+  int compno, resno, pino;
+  int maxres = 0;
+  opj_pi_iterator_t *pi = NULL;
+  opj_tcp_t *tcp = NULL;
+  opj_tccp_t *tccp = NULL;
+  size_t array_size;
+  
+  tcp = &cp->tcps[tileno];
+
+  array_size = (tcp->numpocs + 1) * sizeof(opj_pi_iterator_t);
+  pi = (opj_pi_iterator_t *) opj_malloc(array_size);
+  if(!pi) {
+    /* TODO: throw an error */
+    return NULL;
+  }
+  
+  for (pino = 0; pino < tcp->numpocs + 1; pino++) {  /* change */
+    p = tileno % cp->tw;
+    q = tileno / cp->tw;
+
+    pi[pino].tx0 = int_max(cp->tx0 + p * cp->tdx, image->x0);
+    pi[pino].ty0 = int_max(cp->ty0 + q * cp->tdy, image->y0);
+    pi[pino].tx1 = int_min(cp->tx0 + (p + 1) * cp->tdx, image->x1);
+    pi[pino].ty1 = int_min(cp->ty0 + (q + 1) * cp->tdy, image->y1);
+    pi[pino].numcomps = image->numcomps;
+
+    array_size = image->numcomps * sizeof(opj_pi_comp_t);
+    pi[pino].comps = (opj_pi_comp_t *) opj_malloc(array_size);
+    if(!pi[pino].comps) {
+      /* TODO: throw an error */
+      pi_destroy(pi, cp, tileno);
+      return NULL;
+    }
+    memset(pi[pino].comps, 0, array_size);
+    
+    for (compno = 0; compno < pi->numcomps; compno++) {
+      int tcx0, tcy0, tcx1, tcy1;
+      opj_pi_comp_t *comp = &pi[pino].comps[compno];
+      tccp = &tcp->tccps[compno];
+      comp->dx = image->comps[compno].dx;
+      comp->dy = image->comps[compno].dy;
+      comp->numresolutions = tccp->numresolutions;
+
+      array_size = comp->numresolutions * sizeof(opj_pi_resolution_t);
+      comp->resolutions =  (opj_pi_resolution_t *) opj_malloc(array_size);
+      if(!comp->resolutions) {
+        /* TODO: throw an error */
+        pi_destroy(pi, cp, tileno);
+        return NULL;
+      }
+
+      tcx0 = int_ceildiv(pi->tx0, comp->dx);
+      tcy0 = int_ceildiv(pi->ty0, comp->dy);
+      tcx1 = int_ceildiv(pi->tx1, comp->dx);
+      tcy1 = int_ceildiv(pi->ty1, comp->dy);
+      if (comp->numresolutions > maxres) {
+        maxres = comp->numresolutions;
+      }
+
+      for (resno = 0; resno < comp->numresolutions; resno++) {
+        int levelno;
+        int rx0, ry0, rx1, ry1;
+        int px0, py0, px1, py1;
+        opj_pi_resolution_t *res = &comp->resolutions[resno];
+        if (tccp->csty & J2K_CCP_CSTY_PRT) {
+          res->pdx = tccp->prcw[resno];
+          res->pdy = tccp->prch[resno];
+        } else {
+          res->pdx = 15;
+          res->pdy = 15;
+        }
+        levelno = comp->numresolutions - 1 - resno;
+        rx0 = int_ceildivpow2(tcx0, levelno);
+        ry0 = int_ceildivpow2(tcy0, levelno);
+        rx1 = int_ceildivpow2(tcx1, levelno);
+        ry1 = int_ceildivpow2(tcy1, levelno);
+        px0 = int_floordivpow2(rx0, res->pdx) << res->pdx;
+        py0 = int_floordivpow2(ry0, res->pdy) << res->pdy;
+        px1 = int_ceildivpow2(rx1, res->pdx) << res->pdx;
+        py1 = int_ceildivpow2(ry1, res->pdy) << res->pdy;
+        res->pw = (rx0==rx1)?0:((px1 - px0) >> res->pdx);
+        res->ph = (ry0==ry1)?0:((py1 - py0) >> res->pdy);
+      }
+    }
+    
+    tccp = &tcp->tccps[0];
+    pi[pino].step_p = 1;
+    pi[pino].step_c = 100 * pi[pino].step_p;
+    pi[pino].step_r = image->numcomps * pi[pino].step_c;
+    pi[pino].step_l = maxres * pi[pino].step_r;
+    
+    if (pino == 0) {
+      array_size = image->numcomps * maxres * tcp->numlayers * 100 * sizeof(short int);
+      pi[pino].include = (short int *) opj_malloc(array_size);
+      if(!pi[pino].include) {
+        /* TODO: throw an error */
+        pi_destroy(pi, cp, tileno);
+        return NULL;
+      }
+    }
+    else {
+      pi[pino].include = pi[pino - 1].include;
+    }
+    
+    if (tcp->POC == 0) {
+      pi[pino].first = 1;
+      pi[pino].poc.resno0 = 0;
+      pi[pino].poc.compno0 = 0;
+      pi[pino].poc.layno1 = tcp->numlayers;
+      pi[pino].poc.resno1 = maxres;
+      pi[pino].poc.compno1 = image->numcomps;
+      pi[pino].poc.prg = tcp->prg;
+    } else {
+      pi[pino].first = 1;
+      pi[pino].poc.resno0 = tcp->pocs[pino].resno0;
+      pi[pino].poc.compno0 = tcp->pocs[pino].compno0;
+      pi[pino].poc.layno1 = tcp->pocs[pino].layno1;
+      pi[pino].poc.resno1 = tcp->pocs[pino].resno1;
+      pi[pino].poc.compno1 = tcp->pocs[pino].compno1;
+      pi[pino].poc.prg = tcp->pocs[pino].prg;
+    }
+  }
+  
+  return pi;
+}
+
+void pi_destroy(opj_pi_iterator_t *pi, opj_cp_t *cp, int tileno) {
+  int compno, pino;
+  opj_tcp_t *tcp = &cp->tcps[tileno];
+  if(pi) {
+    for (pino = 0; pino < tcp->numpocs + 1; pino++) {  
+      if(pi[pino].comps) {
+        for (compno = 0; compno < pi->numcomps; compno++) {
+          opj_pi_comp_t *comp = &pi[pino].comps[compno];
+          if(comp->resolutions) {
+            opj_free(comp->resolutions);
+          }
+        }
+        opj_free(pi[pino].comps);
+      }
+    }
+    if(pi->include) {
+      opj_free(pi->include);
+    }
+    opj_free(pi);
+  }
+}
+
+bool pi_next(opj_pi_iterator_t * pi) {
+  switch (pi->poc.prg) {
+    case LRCP:
+      return pi_next_lrcp(pi);
+    case RLCP:
+      return pi_next_rlcp(pi);
+    case RPCL:
+      return pi_next_rpcl(pi);
+    case PCRL:
+      return pi_next_pcrl(pi);
+    case CPRL:
+      return pi_next_cprl(pi);
+    case PROG_UNKNOWN:
+      return false;
+  }
+  
+  return false;
+}
+
diff --git a/Utilities/ITK/Utilities/openjpeg/pi.h b/Utilities/ITK/Utilities/openjpeg/pi.h
new file mode 100644
index 0000000000..509fdd6b1c
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/pi.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PI_H
+#define __PI_H
+/**
+@file pi.h
+@brief Implementation of a packet iterator (PI)
+
+The functions in PI.C have for goal to realize a packet iterator that permits to get the next
+packet following the progression order and change of it. The functions in PI.C are used
+by some function in T2.C.
+*/
+
+/** @defgroup PI PI - Implementation of a packet iterator */
+/*@{*/
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_pi_resolution {
+  int pdx, pdy;
+  int pw, ph;
+} opj_pi_resolution_t;
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_pi_comp {
+  int dx, dy;
+  /** number of resolution levels */
+  int numresolutions;
+  opj_pi_resolution_t *resolutions;
+} opj_pi_comp_t;
+
+/** 
+Packet iterator 
+*/
+typedef struct opj_pi_iterator {
+  /** precise if the packet has been already used (usefull for progression order change) */
+  short int *include;
+  /** layer step used to localize the packet in the include vector */
+  int step_l;
+  /** resolution step used to localize the packet in the include vector */
+  int step_r;  
+  /** component step used to localize the packet in the include vector */
+  int step_c;  
+  /** precinct step used to localize the packet in the include vector */
+  int step_p;  
+  /** component that identify the packet */
+  int compno;
+  /** resolution that identify the packet */
+  int resno;
+  /** precinct that identify the packet */
+  int precno;
+  /** layer that identify the packet */
+  int layno;   
+  /** 0 if the first packet */
+  int first;
+  /** progression order change information */
+  opj_poc_t poc;
+  /** */
+  int numcomps;
+  /** */
+  opj_pi_comp_t *comps;
+  int tx0, ty0, tx1, ty1;
+  int x, y, dx, dy;
+} opj_pi_iterator_t;
+
+/** @name Exported functions */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+/**
+Create a packet iterator
+@param image Raw image for which the packets will be listed
+@param cp Coding parameters
+@param tileno Number that identifies the tile for which to list the packets
+@return Returns a packet iterator that points to the first packet of the tile
+@see pi_destroy
+*/
+opj_pi_iterator_t *pi_create(opj_image_t * image, opj_cp_t * cp, int tileno);
+
+/**
+Destroy a packet iterator
+@param pi Previously created packet iterator
+@param cp Coding parameters
+@param tileno Number that identifies the tile for which the packets were listed
+@see pi_create
+*/
+void pi_destroy(opj_pi_iterator_t *pi, opj_cp_t *cp, int tileno);
+
+/**
+Modify the packet iterator to point to the next packet
+@param pi Packet iterator to modify
+@return Returns false if pi pointed to the last packet or else returns true 
+*/
+bool pi_next(opj_pi_iterator_t * pi);
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __PI_H */
diff --git a/Utilities/ITK/Utilities/openjpeg/raw.c b/Utilities/ITK/Utilities/openjpeg/raw.c
new file mode 100644
index 0000000000..49c38fd22e
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/raw.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opj_includes.h"
+
+/* 
+==========================================================
+   local functions
+==========================================================
+*/
+
+
+/* 
+==========================================================
+   RAW encoding interface
+==========================================================
+*/
+
+opj_raw_t* raw_create() {
+  opj_raw_t *raw = (opj_raw_t*)opj_malloc(sizeof(opj_raw_t));
+  return raw;
+}
+
+void raw_destroy(opj_raw_t *raw) {
+  if(raw) {
+    opj_free(raw);
+  }
+}
+
+int raw_numbytes(opj_raw_t *raw) {
+  return raw->bp - raw->start;
+}
+
+void raw_init_dec(opj_raw_t *raw, unsigned char *bp, int len) {
+  raw->start = bp;
+  raw->lenmax = len;
+  raw->len = 0;
+  raw->c = 0;
+  raw->ct = 0;
+}
+
+int raw_decode(opj_raw_t *raw) {
+  int d;
+  if (raw->ct == 0) {
+    raw->ct = 8;
+    if (raw->len == raw->lenmax) {
+      raw->c = 0xff;
+    } else {
+      if (raw->c == 0xff) {
+        raw->ct = 7;
+      }
+      raw->c = *(raw->start + raw->len);
+      raw->len++;
+    }
+  }
+  raw->ct--;
+  d = (raw->c >> raw->ct) & 0x01;
+  
+  return d;
+}
+
diff --git a/Utilities/ITK/Utilities/openjpeg/raw.h b/Utilities/ITK/Utilities/openjpeg/raw.h
new file mode 100644
index 0000000000..5158610503
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/raw.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __RAW_H
+#define __RAW_H
+/**
+@file raw.h
+@brief Implementation of operations for raw encoding (RAW)
+
+The functions in RAW.C have for goal to realize the operation of raw encoding linked
+with the corresponding mode switch.
+*/
+
+/** @defgroup RAW RAW - Implementation of operations for raw encoding */
+/*@{*/
+
+/**
+RAW encoding operations
+*/
+typedef struct opj_raw {
+  /** temporary buffer where bits are coded or decoded */
+  unsigned char c;
+  /** number of bits already read or free to write */
+  unsigned int ct;
+  /** maximum length to decode */
+  unsigned int lenmax;
+  /** length decoded */
+  unsigned int len;
+  /** pointer to the current position in the buffer */
+  unsigned char *bp;
+  /** pointer to the start of the buffer */
+  unsigned char *start;
+  /** pointer to the end of the buffer */
+  unsigned char *end;
+} opj_raw_t;
+
+/** @name Exported functions */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+/**
+Create a new RAW handle 
+@return Returns a new RAW handle if successful, returns NULL otherwise
+*/
+opj_raw_t* raw_create();
+/**
+Destroy a previously created RAW handle
+@param raw RAW handle to destroy
+*/
+void raw_destroy(opj_raw_t *raw);
+/**
+Return the number of bytes written/read since initialisation
+@param raw RAW handle to destroy
+@return Returns the number of bytes already encoded
+*/
+int raw_numbytes(opj_raw_t *raw);
+/**
+Initialize the decoder
+@param raw RAW handle
+@param bp Pointer to the start of the buffer from which the bytes will be read
+@param len Length of the input buffer
+*/
+void raw_init_dec(opj_raw_t *raw, unsigned char *bp, int len);
+/**
+Decode a symbol using raw-decoder. Cfr p.506 TAUBMAN
+@param raw RAW handle
+@return Returns the decoded symbol (0 or 1)
+*/
+int raw_decode(opj_raw_t *raw);
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __RAW_H */
diff --git a/Utilities/ITK/Utilities/openjpeg/t1.c b/Utilities/ITK/Utilities/openjpeg/t1.c
new file mode 100644
index 0000000000..49651fe9bf
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/t1.c
@@ -0,0 +1,1095 @@
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opj_includes.h"
+
+/** @defgroup T1 T1 - Implementation of the tier-1 coding */
+/*@{*/
+
+/** @name Local static functions */
+/*@{*/
+
+static int t1_getctxno_zc(opj_t1_t *t1, int f, int orient);
+static int t1_getctxno_sc(opj_t1_t *t1, int f);
+static int t1_getctxno_mag(opj_t1_t *t1, int f);
+static int t1_getspb(opj_t1_t *t1, int f);
+static int t1_getnmsedec_sig(opj_t1_t *t1, int x, int bitpos);
+static int t1_getnmsedec_ref(opj_t1_t *t1, int x, int bitpos);
+static void t1_updateflags(int *fp, int s);
+/**
+Encode significant pass
+*/
+static void t1_enc_sigpass_step(opj_t1_t *t1, int *fp, int *dp, int orient, int bpno, int one, int *nmsedec, char type, int vsc);
+/**
+Decode significant pass
+*/
+static void t1_dec_sigpass_step(opj_t1_t *t1, int *fp, int *dp, int orient, int oneplushalf, char type, int vsc);
+/**
+Encode significant pass
+*/
+static void t1_enc_sigpass(opj_t1_t *t1, int w, int h, int bpno, int orient, int *nmsedec, char type, int cblksty);
+/**
+Decode significant pass
+*/
+static void t1_dec_sigpass(opj_t1_t *t1, int w, int h, int bpno, int orient, char type, int cblksty);
+/**
+Encode refinement pass
+*/
+static void t1_enc_refpass_step(opj_t1_t *t1, int *fp, int *dp, int bpno, int one, int *nmsedec, char type, int vsc);
+/**
+Decode refinement pass
+*/
+static void t1_dec_refpass_step(opj_t1_t *t1, int *fp, int *dp, int poshalf, int neghalf, char type, int vsc);
+/**
+Encode refinement pass
+*/
+static void t1_enc_refpass(opj_t1_t *t1, int w, int h, int bpno, int *nmsedec, char type, int cblksty);
+/**
+Decode refinement pass
+*/
+static void t1_dec_refpass(opj_t1_t *t1, int w, int h, int bpno, char type, int cblksty);
+/**
+Encode clean-up pass
+*/
+static void t1_enc_clnpass_step(opj_t1_t *t1, int *fp, int *dp, int orient, int bpno, int one, int *nmsedec, int partial, int vsc);
+/**
+Decode clean-up pass
+*/
+static void t1_dec_clnpass_step(opj_t1_t *t1, int *fp, int *dp, int orient, int oneplushalf, int partial, int vsc);
+/**
+Encode clean-up pass
+*/
+static void t1_enc_clnpass(opj_t1_t *t1, int w, int h, int bpno, int orient, int *nmsedec, int cblksty);
+/**
+Decode clean-up pass
+*/
+static void t1_dec_clnpass(opj_t1_t *t1, int w, int h, int bpno, int orient, int cblksty);
+static double t1_getwmsedec(int nmsedec, int compno, int level, int orient, int bpno, int qmfbid, double stepsize, int numcomps);
+/**
+Encode 1 code-block
+@param t1 T1 handle
+@param cblk Code-block coding parameters
+@param orient
+@param compno Component number
+@param level
+@param qmfbid
+@param stepsize
+@param cblksty Code-block style
+@param numcomps
+@param tile
+*/
+static void t1_encode_cblk(opj_t1_t *t1, opj_tcd_cblk_t * cblk, int orient, int compno, int level, int qmfbid, double stepsize, int cblksty, int numcomps, opj_tcd_tile_t * tile);
+/**
+Decode 1 code-block
+@param t1 T1 handle
+@param cblk Code-block coding parameters
+@param orient
+@param roishift Region of interest shifting value
+@param cblksty Code-block style
+*/
+static void t1_decode_cblk(opj_t1_t *t1, opj_tcd_cblk_t * cblk, int orient, int roishift, int cblksty);
+static int t1_init_ctxno_zc(int f, int orient);
+static int t1_init_ctxno_sc(int f);
+static int t1_init_ctxno_mag(int f);
+static int t1_init_spb(int f);
+/**
+Initialize the look-up tables of the Tier-1 coder/decoder
+@param t1 T1 handle
+*/
+static void t1_init_luts(opj_t1_t *t1);
+
+/*@}*/
+
+/*@}*/
+
+/* ----------------------------------------------------------------------- */
+
+static int t1_getctxno_zc(opj_t1_t *t1, int f, int orient) {
+  return t1->lut_ctxno_zc[(orient << 8) | (f & T1_SIG_OTH)];
+}
+
+static int t1_getctxno_sc(opj_t1_t *t1, int f) {
+  return t1->lut_ctxno_sc[(f & (T1_SIG_PRIM | T1_SGN)) >> 4];
+}
+
+static int t1_getctxno_mag(opj_t1_t *t1, int f) {
+  return t1->lut_ctxno_mag[(f & T1_SIG_OTH) | (((f & T1_REFINE) != 0) << 11)];
+}
+
+static int t1_getspb(opj_t1_t *t1, int f) {
+  return t1->lut_spb[(f & (T1_SIG_PRIM | T1_SGN)) >> 4];
+}
+
+static int t1_getnmsedec_sig(opj_t1_t *t1, int x, int bitpos) {
+  if (bitpos > T1_NMSEDEC_FRACBITS) {
+    return t1->lut_nmsedec_sig[(x >> (bitpos - T1_NMSEDEC_FRACBITS)) & ((1 << T1_NMSEDEC_BITS) - 1)];
+  }
+  
+  return t1->lut_nmsedec_sig0[x & ((1 << T1_NMSEDEC_BITS) - 1)];
+}
+
+static int t1_getnmsedec_ref(opj_t1_t *t1, int x, int bitpos) {
+  if (bitpos > T1_NMSEDEC_FRACBITS) {
+    return t1->lut_nmsedec_ref[(x >> (bitpos - T1_NMSEDEC_FRACBITS)) & ((1 << T1_NMSEDEC_BITS) - 1)];
+  }
+
+    return t1->lut_nmsedec_ref0[x & ((1 << T1_NMSEDEC_BITS) - 1)];
+}
+
+static void t1_updateflags(int *fp, int s) {
+  int *np = fp - (T1_MAXCBLKW + 2);
+  int *sp = fp + (T1_MAXCBLKW + 2);
+  np[-1] |= T1_SIG_SE;
+  np[1] |= T1_SIG_SW;
+  sp[-1] |= T1_SIG_NE;
+  sp[1] |= T1_SIG_NW;
+  *np |= T1_SIG_S;
+  *sp |= T1_SIG_N;
+  fp[-1] |= T1_SIG_E;
+  fp[1] |= T1_SIG_W;
+  if (s) {
+    *np |= T1_SGN_S;
+    *sp |= T1_SGN_N;
+    fp[-1] |= T1_SGN_E;
+    fp[1] |= T1_SGN_W;
+  }
+}
+
+static void t1_enc_sigpass_step(opj_t1_t *t1, int *fp, int *dp, int orient, int bpno, int one, int *nmsedec, char type, int vsc) {
+  int v, flag;
+  
+  opj_mqc_t *mqc = t1->mqc;  /* MQC component */
+  
+  flag = vsc ? ((*fp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*fp);
+  if ((flag & T1_SIG_OTH) && !(flag & (T1_SIG | T1_VISIT))) {
+    v = int_abs(*dp) & one ? 1 : 0;
+    if (type == T1_TYPE_RAW) {  /* BYPASS/LAZY MODE */
+      mqc_setcurctx(mqc, t1_getctxno_zc(t1, flag, orient));  /* ESSAI */
+      mqc_bypass_enc(mqc, v);
+    } else {
+      mqc_setcurctx(mqc, t1_getctxno_zc(t1, flag, orient));
+      mqc_encode(mqc, v);
+    }
+    if (v) {
+      v = *dp < 0 ? 1 : 0;
+      *nmsedec +=  t1_getnmsedec_sig(t1, int_abs(*dp), bpno + T1_NMSEDEC_FRACBITS);
+      if (type == T1_TYPE_RAW) {  /* BYPASS/LAZY MODE */
+        mqc_setcurctx(mqc, t1_getctxno_sc(t1, flag));  /* ESSAI */
+        mqc_bypass_enc(mqc, v);
+      } else {
+        mqc_setcurctx(mqc, t1_getctxno_sc(t1, flag));
+        mqc_encode(mqc, v ^ t1_getspb(t1, flag));
+      }
+      t1_updateflags(fp, v);
+      *fp |= T1_SIG;
+    }
+    *fp |= T1_VISIT;
+  }
+}
+
+static void t1_dec_sigpass_step(opj_t1_t *t1, int *fp, int *dp, int orient, int oneplushalf, char type, int vsc) {
+  int v, flag;
+  
+  opj_raw_t *raw = t1->raw;  /* RAW component */
+  opj_mqc_t *mqc = t1->mqc;  /* MQC component */
+  
+  flag = vsc ? ((*fp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*fp);
+  if ((flag & T1_SIG_OTH) && !(flag & (T1_SIG | T1_VISIT))) {
+    if (type == T1_TYPE_RAW) {
+      if (raw_decode(raw)) {
+        v = raw_decode(raw);  /* ESSAI */
+        *dp = v ? -oneplushalf : oneplushalf;
+        t1_updateflags(fp, v);
+        *fp |= T1_SIG;
+      }
+    } else {
+      mqc_setcurctx(mqc, t1_getctxno_zc(t1, flag, orient));
+      if (mqc_decode(mqc)) {
+        mqc_setcurctx(mqc, t1_getctxno_sc(t1, flag));
+        v = mqc_decode(mqc) ^ t1_getspb(t1, flag);
+        *dp = v ? -oneplushalf : oneplushalf;
+        t1_updateflags(fp, v);
+        *fp |= T1_SIG;
+      }
+    }
+    *fp |= T1_VISIT;
+  }
+}        /* VSC and  BYPASS by Antonin */
+
+static void t1_enc_sigpass(opj_t1_t *t1, int w, int h, int bpno, int orient, int *nmsedec, char type, int cblksty) {
+  int i, j, k, one, vsc;
+  *nmsedec = 0;
+  one = 1 << (bpno + T1_NMSEDEC_FRACBITS);
+  for (k = 0; k < h; k += 4) {
+    for (i = 0; i < w; i++) {
+      for (j = k; j < k + 4 && j < h; j++) {
+        vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == h - 1)) ? 1 : 0;
+        t1_enc_sigpass_step(t1, &t1->flags[1 + j][1 + i], &t1->data[j][i], orient, bpno, one, nmsedec, type, vsc);
+      }
+    }
+  }
+}
+
+static void t1_dec_sigpass(opj_t1_t *t1, int w, int h, int bpno, int orient, char type, int cblksty) {
+  int i, j, k, one, half, oneplushalf, vsc;
+  one = 1 << bpno;
+  half = one >> 1;
+  oneplushalf = one | half;
+  for (k = 0; k < h; k += 4) {
+    for (i = 0; i < w; i++) {
+      for (j = k; j < k + 4 && j < h; j++) {
+        vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == h - 1)) ? 1 : 0;
+        t1_dec_sigpass_step(t1, &t1->flags[1 + j][1 + i], &t1->data[j][i], orient, oneplushalf, type, vsc);
+      }
+    }
+  }
+}        /* VSC and  BYPASS by Antonin */
+
+static void t1_enc_refpass_step(opj_t1_t *t1, int *fp, int *dp, int bpno, int one, int *nmsedec, char type, int vsc) {
+  int v, flag;
+  
+  opj_mqc_t *mqc = t1->mqc;  /* MQC component */
+  
+  flag = vsc ? ((*fp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*fp);
+  if ((flag & (T1_SIG | T1_VISIT)) == T1_SIG) {
+    *nmsedec += t1_getnmsedec_ref(t1, int_abs(*dp), bpno + T1_NMSEDEC_FRACBITS);
+    v = int_abs(*dp) & one ? 1 : 0;
+    if (type == T1_TYPE_RAW) {  /* BYPASS/LAZY MODE */
+      mqc_setcurctx(mqc, t1_getctxno_mag(t1, flag));  /* ESSAI */
+      mqc_bypass_enc(mqc, v);
+    } else {
+      mqc_setcurctx(mqc, t1_getctxno_mag(t1, flag));
+      mqc_encode(mqc, v);
+    }
+    *fp |= T1_REFINE;
+  }
+}
+
+static void t1_dec_refpass_step(opj_t1_t *t1, int *fp, int *dp, int poshalf, int neghalf, char type, int vsc) {
+  int v, t, flag;
+  
+  opj_mqc_t *mqc = t1->mqc;  /* MQC component */
+  opj_raw_t *raw = t1->raw;  /* RAW component */
+  
+  flag = vsc ? ((*fp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*fp);
+  if ((flag & (T1_SIG | T1_VISIT)) == T1_SIG) {
+    if (type == T1_TYPE_RAW) {
+      mqc_setcurctx(mqc, t1_getctxno_mag(t1, flag));  /* ESSAI */
+      v = raw_decode(raw);
+    } else {
+      mqc_setcurctx(mqc, t1_getctxno_mag(t1, flag));
+      v = mqc_decode(mqc);
+    }
+    t = v ? poshalf : neghalf;
+    *dp += *dp < 0 ? -t : t;
+    *fp |= T1_REFINE;
+  }
+}        /* VSC and  BYPASS by Antonin  */
+
+static void t1_enc_refpass(opj_t1_t *t1, int w, int h, int bpno, int *nmsedec, char type, int cblksty) {
+  int i, j, k, one, vsc;
+  *nmsedec = 0;
+  one = 1 << (bpno + T1_NMSEDEC_FRACBITS);
+  for (k = 0; k < h; k += 4) {
+    for (i = 0; i < w; i++) {
+      for (j = k; j < k + 4 && j < h; j++) {
+        vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == h - 1)) ? 1 : 0;
+        t1_enc_refpass_step(t1, &t1->flags[1 + j][1 + i], &t1->data[j][i], bpno, one, nmsedec, type, vsc);
+      }
+    }
+  }
+}
+
+static void t1_dec_refpass(opj_t1_t *t1, int w, int h, int bpno, char type, int cblksty) {
+  int i, j, k, one, poshalf, neghalf;
+  int vsc;
+  one = 1 << bpno;
+  poshalf = one >> 1;
+  neghalf = bpno > 0 ? -poshalf : -1;
+  for (k = 0; k < h; k += 4) {
+    for (i = 0; i < w; i++) {
+      for (j = k; j < k + 4 && j < h; j++) {
+        vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == h - 1)) ? 1 : 0;
+        t1_dec_refpass_step(t1, &t1->flags[1 + j][1 + i], &t1->data[j][i], poshalf, neghalf, type, vsc);
+      }
+    }
+  }
+}        /* VSC and  BYPASS by Antonin */
+
+static void t1_enc_clnpass_step(opj_t1_t *t1, int *fp, int *dp, int orient, int bpno, int one, int *nmsedec, int partial, int vsc) {
+  int v, flag;
+  
+  opj_mqc_t *mqc = t1->mqc;  /* MQC component */
+  
+  flag = vsc ? ((*fp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*fp);
+  if (partial) {
+    goto LABEL_PARTIAL;
+  }
+  if (!(*fp & (T1_SIG | T1_VISIT))) {
+    mqc_setcurctx(mqc, t1_getctxno_zc(t1, flag, orient));
+    v = int_abs(*dp) & one ? 1 : 0;
+    mqc_encode(mqc, v);
+    if (v) {
+LABEL_PARTIAL:
+      *nmsedec += t1_getnmsedec_sig(t1, int_abs(*dp), bpno + T1_NMSEDEC_FRACBITS);
+      mqc_setcurctx(mqc, t1_getctxno_sc(t1, flag));
+      v = *dp < 0 ? 1 : 0;
+      mqc_encode(mqc, v ^ t1_getspb(t1, flag));
+      t1_updateflags(fp, v);
+      *fp |= T1_SIG;
+    }
+  }
+  *fp &= ~T1_VISIT;
+}
+
+static void t1_dec_clnpass_step(opj_t1_t *t1, int *fp, int *dp, int orient, int oneplushalf, int partial, int vsc) {
+  int v, flag;
+  
+  opj_mqc_t *mqc = t1->mqc;  /* MQC component */
+  
+  flag = vsc ? ((*fp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*fp);
+  if (partial) {
+    goto LABEL_PARTIAL;
+  }
+  if (!(flag & (T1_SIG | T1_VISIT))) {
+    mqc_setcurctx(mqc, t1_getctxno_zc(t1, flag, orient));
+    if (mqc_decode(mqc)) {
+LABEL_PARTIAL:
+      mqc_setcurctx(mqc, t1_getctxno_sc(t1, flag));
+      v = mqc_decode(mqc) ^ t1_getspb(t1, flag);
+      *dp = v ? -oneplushalf : oneplushalf;
+      t1_updateflags(fp, v);
+      *fp |= T1_SIG;
+    }
+  }
+  *fp &= ~T1_VISIT;
+}        /* VSC and  BYPASS by Antonin */
+
+static void t1_enc_clnpass(opj_t1_t *t1, int w, int h, int bpno, int orient, int *nmsedec, int cblksty) {
+  int i, j, k, one, agg, runlen, vsc;
+  
+  opj_mqc_t *mqc = t1->mqc;  /* MQC component */
+  
+  *nmsedec = 0;
+  one = 1 << (bpno + T1_NMSEDEC_FRACBITS);
+  for (k = 0; k < h; k += 4) {
+    for (i = 0; i < w; i++) {
+      if (k + 3 < h) {
+        if (cblksty & J2K_CCP_CBLKSTY_VSC) {
+          agg = !(t1->flags[1 + k][1 + i] & (T1_SIG | T1_VISIT | T1_SIG_OTH)
+            || t1->flags[1 + k + 1][1 + i] & (T1_SIG | T1_VISIT | T1_SIG_OTH)
+            || t1->flags[1 + k + 2][1 + i] & (T1_SIG | T1_VISIT | T1_SIG_OTH)
+            || (t1->flags[1 + k + 3][1 + i] 
+            & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW |  T1_SGN_S))) & (T1_SIG | T1_VISIT | T1_SIG_OTH));
+        } else {
+          agg = !(t1->flags[1 + k][1 + i] & (T1_SIG | T1_VISIT | T1_SIG_OTH)
+            || t1->flags[1 + k + 1][1 + i] & (T1_SIG | T1_VISIT | T1_SIG_OTH)
+            || t1->flags[1 + k + 2][1 + i] & (T1_SIG | T1_VISIT | T1_SIG_OTH)
+            || t1->flags[1 + k + 3][1 + i] & (T1_SIG | T1_VISIT | T1_SIG_OTH));
+        }
+      } else {
+        agg = 0;
+      }
+      if (agg) {
+        for (runlen = 0; runlen < 4; runlen++) {
+          if (int_abs(t1->data[k + runlen][i]) & one)
+            break;
+        }
+        mqc_setcurctx(mqc, T1_CTXNO_AGG);
+        mqc_encode(mqc, runlen != 4);
+        if (runlen == 4) {
+          continue;
+        }
+        mqc_setcurctx(mqc, T1_CTXNO_UNI);
+        mqc_encode(mqc, runlen >> 1);
+        mqc_encode(mqc, runlen & 1);
+      } else {
+        runlen = 0;
+      }
+      for (j = k + runlen; j < k + 4 && j < h; j++) {
+        vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == h - 1)) ? 1 : 0;
+        t1_enc_clnpass_step(t1, &t1->flags[1 + j][1 + i], &t1->data[j][i], orient, bpno, one, nmsedec, agg && (j == k + runlen), vsc);
+      }
+    }
+  }
+}
+
+static void t1_dec_clnpass(opj_t1_t *t1, int w, int h, int bpno, int orient, int cblksty) {
+  int i, j, k, one, half, oneplushalf, agg, runlen, vsc;
+  int segsym = cblksty & J2K_CCP_CBLKSTY_SEGSYM;
+  
+  opj_mqc_t *mqc = t1->mqc;  /* MQC component */
+  
+  one = 1 << bpno;
+  half = one >> 1;
+  oneplushalf = one | half;
+  for (k = 0; k < h; k += 4) {
+    for (i = 0; i < w; i++) {
+      if (k + 3 < h) {
+        if (cblksty & J2K_CCP_CBLKSTY_VSC) {
+          agg = !(t1->flags[1 + k][1 + i] & (T1_SIG | T1_VISIT | T1_SIG_OTH)
+            || t1->flags[1 + k + 1][1 + i] & (T1_SIG | T1_VISIT | T1_SIG_OTH)
+            || t1->flags[1 + k + 2][1 + i] & (T1_SIG | T1_VISIT | T1_SIG_OTH)
+            || (t1->flags[1 + k + 3][1 + i] 
+            & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW |  T1_SGN_S))) & (T1_SIG | T1_VISIT | T1_SIG_OTH));
+        } else {
+          agg = !(t1->flags[1 + k][1 + i] & (T1_SIG | T1_VISIT | T1_SIG_OTH)
+            || t1->flags[1 + k + 1][1 + i] & (T1_SIG | T1_VISIT | T1_SIG_OTH)
+            || t1->flags[1 + k + 2][1 + i] & (T1_SIG | T1_VISIT | T1_SIG_OTH)
+            || t1->flags[1 + k + 3][1 + i] & (T1_SIG | T1_VISIT | T1_SIG_OTH));
+        }
+      } else {
+        agg = 0;
+      }
+      if (agg) {
+        mqc_setcurctx(mqc, T1_CTXNO_AGG);
+        if (!mqc_decode(mqc)) {
+          continue;
+        }
+        mqc_setcurctx(mqc, T1_CTXNO_UNI);
+        runlen = mqc_decode(mqc);
+        runlen = (runlen << 1) | mqc_decode(mqc);
+      } else {
+        runlen = 0;
+      }
+      for (j = k + runlen; j < k + 4 && j < h; j++) {
+        vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == h - 1)) ? 1 : 0;
+        t1_dec_clnpass_step(t1, &t1->flags[1 + j][1 + i], &t1->data[j][i], orient, oneplushalf, agg && (j == k + runlen), vsc);
+      }
+    }
+  }
+  if (segsym) {
+    int v = 0;
+    mqc_setcurctx(mqc, T1_CTXNO_UNI);
+    v = mqc_decode(mqc);
+    v = (v << 1) | mqc_decode(mqc);
+    v = (v << 1) | mqc_decode(mqc);
+    v = (v << 1) | mqc_decode(mqc);
+    /*
+    if (v!=0xa) {
+      opj_event_msg(t1->cinfo, EVT_WARNING, "Bad segmentation symbol %x\n", v);
+    } 
+    */
+  }
+}        /* VSC and  BYPASS by Antonin */
+
+
+/** mod fixed_quality */
+static double t1_getwmsedec(int nmsedec, int compno, int level, int orient, int bpno, int qmfbid, double stepsize, int numcomps)  {
+  double w1, w2, wmsedec;
+  if (qmfbid == 1) {
+    w1 = (numcomps > 1) ? mct_getnorm(compno) : 1;
+    w2 = dwt_getnorm(level, orient);
+  } else {      /* if (qmfbid == 0) */
+    w1 = (numcomps > 1) ? mct_getnorm_real(compno) : 1;
+    w2 = dwt_getnorm_real(level, orient);
+  }
+  wmsedec = w1 * w2 * stepsize * (1 << bpno);
+  wmsedec *= wmsedec * nmsedec / 8192.0;
+  
+  return wmsedec;
+}
+
+/** mod fixed_quality */
+static void t1_encode_cblk(opj_t1_t *t1, opj_tcd_cblk_t * cblk, int orient, int compno, int level, int qmfbid, double stepsize, int cblksty, int numcomps, opj_tcd_tile_t * tile) {
+  int i, j;
+  int w, h;
+  int passno;
+  int bpno, passtype;
+  int max;
+  int nmsedec = 0;
+  double cumwmsedec = 0;
+  char type = T1_TYPE_MQ;
+  
+  opj_mqc_t *mqc = t1->mqc;  /* MQC component */
+  
+  w = cblk->x1 - cblk->x0;
+  h = cblk->y1 - cblk->y0;
+  
+  max = 0;
+  for (j = 0; j < h; j++) {
+    for (i = 0; i < w; i++) {
+      max = int_max(max, int_abs(t1->data[j][i]));
+    }
+  }
+  
+  cblk->numbps = max ? (int_floorlog2(max) + 1) - T1_NMSEDEC_FRACBITS : 0;
+  
+  /* Changed by Dmitry Kolyadin */
+  for (i = 0; i <= w; i++) {
+    for (j = 0; j <= h; j++) {
+      t1->flags[j][i] = 0;
+    }
+  }
+  
+  bpno = cblk->numbps - 1;
+  passtype = 2;
+  
+  mqc_resetstates(mqc);
+  mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46);
+  mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3);
+  mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4);
+  mqc_init_enc(mqc, cblk->data);
+  
+  for (passno = 0; bpno >= 0; passno++) {
+    opj_tcd_pass_t *pass = &cblk->passes[passno];
+    int correction = 3;
+    type = ((bpno < (cblk->numbps - 4)) && (passtype < 2) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ;
+    
+    switch (passtype) {
+      case 0:
+        t1_enc_sigpass(t1, w, h, bpno, orient, &nmsedec, type, cblksty);
+        break;
+      case 1:
+        t1_enc_refpass(t1, w, h, bpno, &nmsedec, type, cblksty);
+        break;
+      case 2:
+        t1_enc_clnpass(t1, w, h, bpno, orient, &nmsedec, cblksty);
+        /* code switch SEGMARK (i.e. SEGSYM) */
+        if (cblksty & J2K_CCP_CBLKSTY_SEGSYM)
+          mqc_segmark_enc(mqc);
+        break;
+    }
+    
+    /* fixed_quality */
+    cumwmsedec += t1_getwmsedec(nmsedec, compno, level, orient, bpno, qmfbid, stepsize, numcomps);
+    tile->distotile += t1_getwmsedec(nmsedec, compno, level, orient, bpno, qmfbid, stepsize, numcomps);
+    
+    /* Code switch "RESTART" (i.e. TERMALL) */
+    if ((cblksty & J2K_CCP_CBLKSTY_TERMALL)  && !((passtype == 2) && (bpno - 1 < 0))) {
+      if (type == T1_TYPE_RAW) {
+        mqc_flush(mqc);
+        correction = 1;
+        /* correction = mqc_bypass_flush_enc(); */
+      } else {      /* correction = mqc_restart_enc(); */
+        mqc_flush(mqc);
+        correction = 1;
+      }
+      pass->term = 1;
+    } else {
+      if (((bpno < (cblk->numbps - 4) && (passtype > 0)) 
+        || ((bpno == (cblk->numbps - 4)) && (passtype == 2))) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) {
+        if (type == T1_TYPE_RAW) {
+          mqc_flush(mqc);
+          correction = 1;
+          /* correction = mqc_bypass_flush_enc(); */
+        } else {    /* correction = mqc_restart_enc(); */
+          mqc_flush(mqc);
+          correction = 1;
+        }
+        pass->term = 1;
+      } else {
+        pass->term = 0;
+      }
+    }
+    
+    if (++passtype == 3) {
+      passtype = 0;
+      bpno--;
+    }
+    
+    if (pass->term && bpno > 0) {
+      type = ((bpno < (cblk->numbps - 4)) && (passtype < 2) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ;
+      if (type == T1_TYPE_RAW)
+        mqc_bypass_init_enc(mqc);
+      else
+        mqc_restart_init_enc(mqc);
+    }
+    
+    pass->distortiondec = cumwmsedec;
+    pass->rate = mqc_numbytes(mqc) + correction;  /* FIXME */
+    pass->len = pass->rate - (passno == 0 ? 0 : cblk->passes[passno - 1].rate);
+    
+    /* Code-switch "RESET" */
+    if (cblksty & J2K_CCP_CBLKSTY_RESET)
+      mqc_reset_enc(mqc);
+  }
+  
+  /* Code switch "ERTERM" (i.e. PTERM) */
+  if (cblksty & J2K_CCP_CBLKSTY_PTERM)
+    mqc_erterm_enc(mqc);
+  else /* Default coding */ if (!(cblksty & J2K_CCP_CBLKSTY_LAZY))
+    mqc_flush(mqc);
+  
+  cblk->totalpasses = passno;
+}
+
+static void t1_decode_cblk(opj_t1_t *t1, opj_tcd_cblk_t * cblk, int orient, int roishift, int cblksty) {
+  int i, j, w, h;
+  int bpno, passtype;
+  int segno, passno;
+  char type = T1_TYPE_MQ; /* BYPASS mode */
+  
+  opj_raw_t *raw = t1->raw;  /* RAW component */
+  opj_mqc_t *mqc = t1->mqc;  /* MQC component */
+  
+  w = cblk->x1 - cblk->x0;
+  h = cblk->y1 - cblk->y0;
+  
+  /* Changed by Dmitry Kolyadin */
+  for (j = 0; j <= h; j++) {
+    for (i = 0; i <= w; i++) {
+      t1->flags[j][i] = 0;
+    }
+  }
+  
+  /* Changed by Dmitry Kolyadin */
+  for (i = 0; i < w; i++) {
+    for (j = 0; j < h; j++){
+      t1->data[j][i] = 0;
+    }
+  }
+  
+  bpno = roishift + cblk->numbps - 1;
+  passtype = 2;
+  
+  mqc_resetstates(mqc);
+  mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46);
+  mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3);
+  mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4);
+  
+  for (segno = 0; segno < cblk->numsegs; segno++) {
+    opj_tcd_seg_t *seg = &cblk->segs[segno];
+    
+    /* BYPASS mode */
+    type = ((bpno <= (cblk->numbps - 1) - 4) && (passtype < 2) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ;
+    if (type == T1_TYPE_RAW) {
+      raw_init_dec(raw, seg->data, seg->len);
+    } else {
+      mqc_init_dec(mqc, seg->data, seg->len);
+    }
+    
+    for (passno = 0; passno < seg->numpasses; passno++) {
+      switch (passtype) {
+        case 0:
+          t1_dec_sigpass(t1, w, h, bpno+1, orient, type, cblksty);
+          break;
+        case 1:
+          t1_dec_refpass(t1, w, h, bpno+1, type, cblksty);
+          break;
+        case 2:
+          t1_dec_clnpass(t1, w, h, bpno+1, orient, cblksty);
+          break;
+      }
+      
+      if ((cblksty & J2K_CCP_CBLKSTY_RESET) && type == T1_TYPE_MQ) {
+        mqc_resetstates(mqc);
+        mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46);        
+        mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3);
+        mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4);
+      }
+      if (++passtype == 3) {
+        passtype = 0;
+        bpno--;
+      }
+    }
+  }
+}
+
+static int t1_init_ctxno_zc(int f, int orient) {
+  int h, v, d, n, t, hv;
+  n = 0;
+  h = ((f & T1_SIG_W) != 0) + ((f & T1_SIG_E) != 0);
+  v = ((f & T1_SIG_N) != 0) + ((f & T1_SIG_S) != 0);
+  d = ((f & T1_SIG_NW) != 0) + ((f & T1_SIG_NE) != 0) + ((f & T1_SIG_SE) != 0) + ((f & T1_SIG_SW) != 0);
+  
+  switch (orient) {
+    case 2:
+      t = h;
+      h = v;
+      v = t;
+    case 0:
+    case 1:
+      if (!h) {
+        if (!v) {
+          if (!d)
+            n = 0;
+          else if (d == 1)
+            n = 1;
+          else
+            n = 2;
+        } else if (v == 1) {
+          n = 3;
+        } else {
+          n = 4;
+        }
+      } else if (h == 1) {
+        if (!v) {
+          if (!d)
+            n = 5;
+          else
+            n = 6;
+        } else {
+          n = 7;
+        }
+      } else
+        n = 8;
+      break;
+    case 3:
+      hv = h + v;
+      if (!d) {
+        if (!hv) {
+          n = 0;
+        } else if (hv == 1) {
+          n = 1;
+        } else {
+          n = 2;
+        }
+      } else if (d == 1) {
+        if (!hv) {
+          n = 3;
+        } else if (hv == 1) {
+          n = 4;
+        } else {
+          n = 5;
+        }
+      } else if (d == 2) {
+        if (!hv) {
+          n = 6;
+        } else {
+          n = 7;
+        }
+      } else {
+        n = 8;
+      }
+      break;
+  }
+  
+  return (T1_CTXNO_ZC + n);
+}
+
+static int t1_init_ctxno_sc(int f) {
+  int hc, vc, n;
+  n = 0;
+
+  hc = int_min(((f & (T1_SIG_E | T1_SGN_E)) ==
+    T1_SIG_E) + ((f & (T1_SIG_W | T1_SGN_W)) == T1_SIG_W),
+         1) - int_min(((f & (T1_SIG_E | T1_SGN_E)) ==
+       (T1_SIG_E | T1_SGN_E)) +
+       ((f & (T1_SIG_W | T1_SGN_W)) ==
+       (T1_SIG_W | T1_SGN_W)), 1);
+  
+  vc = int_min(((f & (T1_SIG_N | T1_SGN_N)) ==
+    T1_SIG_N) + ((f & (T1_SIG_S | T1_SGN_S)) == T1_SIG_S),
+         1) - int_min(((f & (T1_SIG_N | T1_SGN_N)) ==
+       (T1_SIG_N | T1_SGN_N)) +
+       ((f & (T1_SIG_S | T1_SGN_S)) ==
+       (T1_SIG_S | T1_SGN_S)), 1);
+  
+  if (hc < 0) {
+    hc = -hc;
+    vc = -vc;
+  }
+  if (!hc) {
+    if (vc == -1)
+      n = 1;
+    else if (!vc)
+      n = 0;
+    else
+      n = 1;
+  } else if (hc == 1) {
+    if (vc == -1)
+      n = 2;
+    else if (!vc)
+      n = 3;
+    else
+      n = 4;
+  }
+  
+  return (T1_CTXNO_SC + n);
+}
+
+static int t1_init_ctxno_mag(int f) {
+  int n;
+  if (!(f & T1_REFINE))
+    n = (f & (T1_SIG_OTH)) ? 1 : 0;
+  else
+    n = 2;
+  
+  return (T1_CTXNO_MAG + n);
+}
+
+static int t1_init_spb(int f) {
+  int hc, vc, n;
+  
+  hc = int_min(((f & (T1_SIG_E | T1_SGN_E)) ==
+    T1_SIG_E) + ((f & (T1_SIG_W | T1_SGN_W)) == T1_SIG_W),
+         1) - int_min(((f & (T1_SIG_E | T1_SGN_E)) ==
+       (T1_SIG_E | T1_SGN_E)) +
+       ((f & (T1_SIG_W | T1_SGN_W)) ==
+       (T1_SIG_W | T1_SGN_W)), 1);
+  
+  vc = int_min(((f & (T1_SIG_N | T1_SGN_N)) ==
+    T1_SIG_N) + ((f & (T1_SIG_S | T1_SGN_S)) == T1_SIG_S),
+         1) - int_min(((f & (T1_SIG_N | T1_SGN_N)) ==
+       (T1_SIG_N | T1_SGN_N)) +
+       ((f & (T1_SIG_S | T1_SGN_S)) ==
+       (T1_SIG_S | T1_SGN_S)), 1);
+  
+  if (!hc && !vc)
+    n = 0;
+  else
+    n = (!(hc > 0 || (!hc && vc > 0)));
+  
+  return n;
+}
+
+static void t1_init_luts(opj_t1_t *t1) {
+  int i, j;
+  double u, v, t;
+  for (j = 0; j < 4; j++) {
+    for (i = 0; i < 256; ++i) {
+      t1->lut_ctxno_zc[(j << 8) | i] = t1_init_ctxno_zc(i, j);
+    }
+  }
+  for (i = 0; i < 256; i++) {
+    t1->lut_ctxno_sc[i] = t1_init_ctxno_sc(i << 4);
+  }
+  for (j = 0; j < 2; j++) {
+    for (i = 0; i < 2048; ++i) {
+      t1->lut_ctxno_mag[(j << 11) + i] = t1_init_ctxno_mag((j ? T1_REFINE : 0) | i);
+    }
+  }
+  for (i = 0; i < 256; ++i) {
+    t1->lut_spb[i] = t1_init_spb(i << 4);
+  }
+  /* FIXME FIXME FIXME */
+  /* fprintf(stdout,"nmsedec luts:\n"); */
+  for (i = 0; i < (1 << T1_NMSEDEC_BITS); i++) {
+    t = i / pow(2, T1_NMSEDEC_FRACBITS);
+    u = t;
+    v = t - 1.5;
+    t1->lut_nmsedec_sig[i] = 
+      int_max(0, 
+      (int) (floor((u * u - v * v) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, T1_NMSEDEC_FRACBITS) * 8192.0));
+    t1->lut_nmsedec_sig0[i] =
+      int_max(0,
+      (int) (floor((u * u) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, T1_NMSEDEC_FRACBITS) * 8192.0));
+    u = t - 1.0;
+    if (i & (1 << (T1_NMSEDEC_BITS - 1))) {
+      v = t - 1.5;
+    } else {
+      v = t - 0.5;
+    }
+    t1->lut_nmsedec_ref[i] =
+      int_max(0,
+      (int) (floor((u * u - v * v) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, T1_NMSEDEC_FRACBITS) * 8192.0));
+    t1->lut_nmsedec_ref0[i] =
+      int_max(0,
+      (int) (floor((u * u) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, T1_NMSEDEC_FRACBITS) * 8192.0));
+  }
+}
+
+/* ----------------------------------------------------------------------- */
+
+opj_t1_t* t1_create(opj_common_ptr cinfo) {
+  opj_t1_t *t1 = (opj_t1_t*)opj_malloc(sizeof(opj_t1_t));
+  if(t1) {
+    t1->cinfo = cinfo;
+    /* create MQC and RAW handles */
+    t1->mqc = mqc_create();
+    t1->raw = raw_create();
+    /* initialize the look-up tables of the Tier-1 coder/decoder */
+    t1_init_luts(t1);
+  }
+  return t1;
+}
+
+void t1_destroy(opj_t1_t *t1) {
+  if(t1) {
+    /* destroy MQC and RAW handles */
+    mqc_destroy(t1->mqc);
+    raw_destroy(t1->raw);
+    opj_free(t1);
+  }
+}
+
+void t1_encode_cblks(opj_t1_t *t1, opj_tcd_tile_t *tile, opj_tcp_t *tcp) {
+  int compno, resno, bandno, precno, cblkno;
+  int x, y, i, j, orient;
+  
+  tile->distotile = 0;    /* fixed_quality */
+
+  for (compno = 0; compno < tile->numcomps; compno++) {
+    opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
+
+    for (resno = 0; resno < tilec->numresolutions; resno++) {
+      opj_tcd_resolution_t *res = &tilec->resolutions[resno];
+
+      for (bandno = 0; bandno < res->numbands; bandno++) {
+        opj_tcd_band_t *band = &res->bands[bandno];
+
+        for (precno = 0; precno < res->pw * res->ph; precno++) {
+          opj_tcd_precinct_t *prc = &band->precincts[precno];
+
+          for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+            opj_tcd_cblk_t *cblk = &prc->cblks[cblkno];
+
+            if (band->bandno == 0) {
+              x = cblk->x0 - band->x0;
+              y = cblk->y0 - band->y0;
+            } else if (band->bandno == 1) {
+              opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1];
+              x = pres->x1 - pres->x0 + cblk->x0 - band->x0;
+              y = cblk->y0 - band->y0;
+            } else if (band->bandno == 2) {
+              opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1];
+              x = cblk->x0 - band->x0;
+              y = pres->y1 - pres->y0 + cblk->y0 - band->y0;
+            } else {    /* if (band->bandno == 3) */
+              opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1];
+              x = pres->x1 - pres->x0 + cblk->x0 - band->x0;
+              y = pres->y1 - pres->y0 + cblk->y0 - band->y0;
+            }
+            
+            if (tcp->tccps[compno].qmfbid == 1) {
+              for (j = 0; j < cblk->y1 - cblk->y0; j++) {
+                for (i = 0; i < cblk->x1 - cblk->x0; i++) {
+                  t1->data[j][i] = 
+                    tilec->data[(x + i) + (y + j) * (tilec->x1 - tilec->x0)] << T1_NMSEDEC_FRACBITS;
+                }
+              }
+            } else if (tcp->tccps[compno].qmfbid == 0) {
+              for (j = 0; j < cblk->y1 - cblk->y0; j++) {
+                for (i = 0; i < cblk->x1 - cblk->x0; i++) {
+                  t1->data[j][i] = 
+                    fix_mul(
+                    tilec->data[x + i + (y + j) * (tilec->x1 - tilec->x0)], 
+                    8192 * 8192 / ((int) floor(band->stepsize * 8192))) >> (13 - T1_NMSEDEC_FRACBITS);
+                }
+              }
+            }
+            orient = band->bandno;  /* FIXME */
+            if (orient == 2) {
+              orient = 1;
+            } else if (orient == 1) {
+              orient = 2;
+            }
+
+            t1_encode_cblk(t1, cblk, orient, compno, tilec->numresolutions - 1 - resno, tcp->tccps[compno].qmfbid, band->stepsize, tcp->tccps[compno].cblksty, tile->numcomps, tile);
+
+          } /* cblkno */
+        } /* precno */
+      } /* bandno */
+    } /* resno  */
+  } /* compno  */
+}
+
+void t1_decode_cblks(opj_t1_t *t1, opj_tcd_tile_t *tile, opj_tcp_t *tcp) {
+  int compno, resno, bandno, precno, cblkno;
+  
+  for (compno = 0; compno < tile->numcomps; compno++) {
+    opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
+
+    for (resno = 0; resno < tilec->numresolutions; resno++) {
+      opj_tcd_resolution_t *res = &tilec->resolutions[resno];
+
+      for (bandno = 0; bandno < res->numbands; bandno++) {
+        opj_tcd_band_t *band = &res->bands[bandno];
+
+        for (precno = 0; precno < res->pw * res->ph; precno++) {
+          opj_tcd_precinct_t *prc = &band->precincts[precno];
+
+          for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+            int x, y, i, j, orient;
+            opj_tcd_cblk_t *cblk = &prc->cblks[cblkno];
+
+            orient = band->bandno;  /* FIXME */
+            if (orient == 2) {
+              orient = 1;
+            } else if (orient == 1) {
+              orient = 2;
+            }
+            
+            t1_decode_cblk(t1, cblk, orient, tcp->tccps[compno].roishift, tcp->tccps[compno].cblksty);
+
+            if (band->bandno == 0) {
+              x = cblk->x0 - band->x0;
+              y = cblk->y0 - band->y0;
+            } else if (band->bandno == 1) {
+              opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1];
+              x = pres->x1 - pres->x0 + cblk->x0 - band->x0;
+              y = cblk->y0 - band->y0;
+            } else if (band->bandno == 2) {
+              opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1];
+              x = cblk->x0 - band->x0;
+              y = pres->y1 - pres->y0 + cblk->y0 - band->y0;
+            } else {    /* if (band->bandno == 3) */
+              opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1];
+              x = pres->x1 - pres->x0 + cblk->x0 - band->x0;
+              y = pres->y1 - pres->y0 + cblk->y0 - band->y0;
+            }
+            
+            if (tcp->tccps[compno].roishift) {
+              int thresh, val, mag;
+              thresh = 1 << tcp->tccps[compno].roishift;
+              for (j = 0; j < cblk->y1 - cblk->y0; j++) {
+                for (i = 0; i < cblk->x1 - cblk->x0; i++) {
+                  val = t1->data[j][i];
+                  mag = int_abs(val);
+                  if (mag >= thresh) {
+                    mag >>= tcp->tccps[compno].roishift;
+                    t1->data[j][i] = val < 0 ? -mag : mag;
+                  }
+                }
+              }
+            }
+            
+            if (tcp->tccps[compno].qmfbid == 1) {
+              for (j = 0; j < cblk->y1 - cblk->y0; j++) {
+                for (i = 0; i < cblk->x1 - cblk->x0; i++) {
+                  int tmp = t1->data[j][i];
+                  if(tmp >> 1 == 0) {
+                    tilec->data[x + i + (y + j) * (tilec->x1 - tilec->x0)] = 0;
+                  } else {
+                    tilec->data[x + i + (y + j) * (tilec->x1 - tilec->x0)] = tmp<0?(tmp>>1)+1:(tmp>>1);
+                  }
+                }
+              }
+            } else {    /* if (tcp->tccps[compno].qmfbid == 0) */
+              for (j = 0; j < cblk->y1 - cblk->y0; j++) {
+                for (i = 0; i < cblk->x1 - cblk->x0; i++) {
+                  double tmp = (double)(t1->data[j][i] * band->stepsize * 4096.0);
+                  if (t1->data[j][i] >> 1 == 0) {
+                    tilec->data[x + i + (y + j) * (tilec->x1 - tilec->x0)] = 0;
+                  } else {
+                    int tmp2 = ((int) (floor(fabs(tmp)))) + ((int) floor(fabs(tmp*2))%2);
+                    tilec->data[x + i + (y + j) * (tilec->x1 - tilec->x0)] = ((tmp<0)?-tmp2:tmp2);
+                  }
+                }
+              }
+            }
+          } /* cblkno */
+        } /* precno */
+      } /* bandno */
+    } /* resno */
+  } /* compno */
+}
+
diff --git a/Utilities/ITK/Utilities/openjpeg/t1.h b/Utilities/ITK/Utilities/openjpeg/t1.h
new file mode 100644
index 0000000000..98ea2c0187
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/t1.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __T1_H
+#define __T1_H
+/**
+@file t1.h
+@brief Implementation of the tier-1 coding (coding of code-block coefficients) (T1)
+
+The functions in T1.C have for goal to realize the tier-1 coding operation. The functions
+in T1.C are used by some function in TCD.C.
+*/
+
+/** @defgroup T1 T1 - Implementation of the tier-1 coding */
+/*@{*/
+
+/* ----------------------------------------------------------------------- */
+#define T1_NMSEDEC_BITS 7
+
+#define T1_MAXCBLKW 1024  /**< Maximum size of code-block (width) */
+#define T1_MAXCBLKH 1024  /**< Maximum size of code-block (heigth) */
+
+#define T1_SIG_NE 0x0001  /**< Context orientation : North-East direction */
+#define T1_SIG_SE 0x0002  /**< Context orientation : South-East direction */
+#define T1_SIG_SW 0x0004  /**< Context orientation : South-West direction */
+#define T1_SIG_NW 0x0008  /**< Context orientation : North-West direction */
+#define T1_SIG_N 0x0010    /**< Context orientation : North direction */
+#define T1_SIG_E 0x0020    /**< Context orientation : East direction */
+#define T1_SIG_S 0x0040    /**< Context orientation : South direction */
+#define T1_SIG_W 0x0080    /**< Context orientation : West direction */
+#define T1_SIG_OTH (T1_SIG_N|T1_SIG_NE|T1_SIG_E|T1_SIG_SE|T1_SIG_S|T1_SIG_SW|T1_SIG_W|T1_SIG_NW)
+#define T1_SIG_PRIM (T1_SIG_N|T1_SIG_E|T1_SIG_S|T1_SIG_W)
+
+#define T1_SGN_N 0x0100
+#define T1_SGN_E 0x0200
+#define T1_SGN_S 0x0400
+#define T1_SGN_W 0x0800
+#define T1_SGN (T1_SGN_N|T1_SGN_E|T1_SGN_S|T1_SGN_W)
+
+#define T1_SIG 0x1000
+#define T1_REFINE 0x2000
+#define T1_VISIT 0x4000
+
+#define T1_NUMCTXS_AGG 1
+#define T1_NUMCTXS_ZC 9
+#define T1_NUMCTXS_MAG 3
+#define T1_NUMCTXS_SC 5
+#define T1_NUMCTXS_UNI 1
+
+#define T1_CTXNO_AGG 0
+#define T1_CTXNO_ZC (T1_CTXNO_AGG+T1_NUMCTXS_AGG)
+#define T1_CTXNO_MAG (T1_CTXNO_ZC+T1_NUMCTXS_ZC)
+#define T1_CTXNO_SC (T1_CTXNO_MAG+T1_NUMCTXS_MAG)
+#define T1_CTXNO_UNI (T1_CTXNO_SC+T1_NUMCTXS_SC)
+#define T1_NUMCTXS (T1_CTXNO_UNI+T1_NUMCTXS_UNI)
+
+#define T1_NMSEDEC_FRACBITS (T1_NMSEDEC_BITS-1)
+
+#define T1_TYPE_MQ 0  /**< Normal coding using entropy coder */
+#define T1_TYPE_RAW 1  /**< No encoding the information is store under raw format in codestream (mode switch RAW)*/
+
+/* ----------------------------------------------------------------------- */
+
+/**
+Tier-1 coding (coding of code-block coefficients)
+*/
+typedef struct opj_t1 {
+  /** codec context */
+  opj_common_ptr cinfo;
+
+  /** MQC component */
+  opj_mqc_t *mqc;
+  /** RAW component */
+  opj_raw_t *raw;
+
+  int lut_ctxno_zc[1024];
+  int lut_ctxno_sc[256];
+  int lut_ctxno_mag[4096];
+  int lut_spb[256];
+  int lut_nmsedec_sig[1 << T1_NMSEDEC_BITS];
+  int lut_nmsedec_sig0[1 << T1_NMSEDEC_BITS];
+  int lut_nmsedec_ref[1 << T1_NMSEDEC_BITS];
+  int lut_nmsedec_ref0[1 << T1_NMSEDEC_BITS];
+
+  int data[T1_MAXCBLKH][T1_MAXCBLKW];
+  int flags[T1_MAXCBLKH + 2][T1_MAXCBLKH + 2];
+
+} opj_t1_t;
+
+/** @name Exported functions */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+/**
+Create a new T1 handle 
+and initialize the look-up tables of the Tier-1 coder/decoder
+@return Returns a new T1 handle if successful, returns NULL otherwise
+@see t1_init_luts
+*/
+opj_t1_t* t1_create(opj_common_ptr cinfo);
+/**
+Destroy a previously created T1 handle
+@param t1 T1 handle to destroy
+*/
+void t1_destroy(opj_t1_t *t1);
+/**
+Encode the code-blocks of a tile
+@param t1 T1 handle
+@param tile The tile to encode
+@param tcp Tile coding parameters
+*/
+void t1_encode_cblks(opj_t1_t *t1, opj_tcd_tile_t *tile, opj_tcp_t *tcp);
+/**
+Decode the code-blocks of a tile
+@param t1 T1 handle
+@param tile The tile to decode
+@param tcp Tile coding parameters
+*/
+void t1_decode_cblks(opj_t1_t *t1, opj_tcd_tile_t *tile, opj_tcp_t *tcp);
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __T1_H */
diff --git a/Utilities/ITK/Utilities/openjpeg/t2.c b/Utilities/ITK/Utilities/openjpeg/t2.c
new file mode 100644
index 0000000000..fc30aa8f66
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/t2.c
@@ -0,0 +1,672 @@
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opj_includes.h"
+
+/** @defgroup T2 T2 - Implementation of a tier-2 coding */
+/*@{*/
+
+/** @name Local static functions */
+/*@{*/
+
+static void t2_putcommacode(opj_bio_t *bio, int n);
+static int t2_getcommacode(opj_bio_t *bio);
+/**
+Variable length code for signalling delta Zil (truncation point)
+@param bio Bit Input/Output component
+@param n delta Zil
+*/
+static void t2_putnumpasses(opj_bio_t *bio, int n);
+static int t2_getnumpasses(opj_bio_t *bio);
+/**
+Encode a packet of a tile to a destination buffer
+@param tile Tile for which to write the packets
+@param tcp Tile coding parameters
+@param pi Packet identity
+@param dest Destination buffer
+@param len Length of the destination buffer
+@param image_info Structure to create an index file
+@param tileno Number of the tile encoded
+@return 
+*/
+static int t2_encode_packet(opj_tcd_tile_t *tile, opj_tcp_t *tcp, opj_pi_iterator_t *pi, unsigned char *dest, int len, opj_image_info_t *image_info, int tileno);
+/**
+@param seg
+@param cblksty
+@param first
+*/
+static void t2_init_seg(opj_tcd_seg_t *seg, int cblksty, int first);
+/**
+Decode a packet of a tile from a source buffer
+@param t2 T2 handle
+@param src Source buffer
+@param len Length of the source buffer
+@param tile Tile for which to write the packets
+@param tcp Tile coding parameters
+@param pi Packet identity
+@return 
+*/
+static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_tile_t *tile, opj_tcp_t *tcp, opj_pi_iterator_t *pi);
+
+/*@}*/
+
+/*@}*/
+
+/* ----------------------------------------------------------------------- */
+
+/* #define RESTART 0x04 */
+
+static void t2_putcommacode(opj_bio_t *bio, int n) {
+  while (--n >= 0) {
+    bio_write(bio, 1, 1);
+  }
+  bio_write(bio, 0, 1);
+}
+
+static int t2_getcommacode(opj_bio_t *bio) {
+  int n;
+  for (n = 0; bio_read(bio, 1); n++) {
+    ;
+  }
+  return n;
+}
+
+static void t2_putnumpasses(opj_bio_t *bio, int n) {
+  if (n == 1) {
+    bio_write(bio, 0, 1);
+  } else if (n == 2) {
+    bio_write(bio, 2, 2);
+  } else if (n <= 5) {
+    bio_write(bio, 0xc | (n - 3), 4);
+  } else if (n <= 36) {
+    bio_write(bio, 0x1e0 | (n - 6), 9);
+  } else if (n <= 164) {
+    bio_write(bio, 0xff80 | (n - 37), 16);
+  }
+}
+
+static int t2_getnumpasses(opj_bio_t *bio) {
+  int n;
+  if (!bio_read(bio, 1))
+    return 1;
+  if (!bio_read(bio, 1))
+    return 2;
+  if ((n = bio_read(bio, 2)) != 3)
+    return (3 + n);
+  if ((n = bio_read(bio, 5)) != 31)
+    return (6 + n);
+  return (37 + bio_read(bio, 7));
+}
+
+static int t2_encode_packet(opj_tcd_tile_t * tile, opj_tcp_t * tcp, opj_pi_iterator_t *pi, unsigned char *dest, int len, opj_image_info_t * image_info, int tileno) {
+  int bandno, cblkno;
+  unsigned char *sop = 0, *eph = 0;
+  unsigned char *c = dest;
+
+  int compno = pi->compno;  /* component value */
+  int resno  = pi->resno;    /* resolution level value */
+  int precno = pi->precno;  /* precinct value */
+  int layno  = pi->layno;    /* quality layer value */
+
+  opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
+  opj_tcd_resolution_t *res = &tilec->resolutions[resno];
+  
+  opj_bio_t *bio = NULL;  /* BIO component */
+  
+  /* <SOP 0xff91> */
+  if (tcp->csty & J2K_CP_CSTY_SOP) {
+    sop = (unsigned char *) opj_malloc(6 * sizeof(unsigned char));
+    sop[0] = 255;
+    sop[1] = 145;
+    sop[2] = 0;
+    sop[3] = 4;
+    sop[4] = (image_info->num % 65536) / 256;
+    sop[5] = (image_info->num % 65536) % 256;
+    memcpy(c, sop, 6);
+    opj_free(sop);
+    c += 6;
+  }
+  /* </SOP> */
+  
+  if (!layno) {
+    for (bandno = 0; bandno < res->numbands; bandno++) {
+      opj_tcd_band_t *band = &res->bands[bandno];
+      opj_tcd_precinct_t *prc = &band->precincts[precno];
+      tgt_reset(prc->incltree);
+      tgt_reset(prc->imsbtree);
+      for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+        opj_tcd_cblk_t *cblk = &prc->cblks[cblkno];
+        cblk->numpasses = 0;
+        tgt_setvalue(prc->imsbtree, cblkno, band->numbps - cblk->numbps);
+      }
+    }
+  }
+  
+  bio = bio_create();
+  bio_init_enc(bio, c, len);
+  bio_write(bio, 1, 1);    /* Empty header bit */
+  
+  /* Writing Packet header */
+  for (bandno = 0; bandno < res->numbands; bandno++) {
+    opj_tcd_band_t *band = &res->bands[bandno];
+    opj_tcd_precinct_t *prc = &band->precincts[precno];
+    for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+      opj_tcd_cblk_t *cblk = &prc->cblks[cblkno];
+      opj_tcd_layer_t *layer = &cblk->layers[layno];
+      if (!cblk->numpasses && layer->numpasses) {
+        tgt_setvalue(prc->incltree, cblkno, layno);
+      }
+    }
+    for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+      opj_tcd_cblk_t *cblk = &prc->cblks[cblkno];
+      opj_tcd_layer_t *layer = &cblk->layers[layno];
+      int increment = 0;
+      int nump = 0;
+      int len = 0, passno;
+      /* cblk inclusion bits */
+      if (!cblk->numpasses) {
+        tgt_encode(bio, prc->incltree, cblkno, layno + 1);
+      } else {
+        bio_write(bio, layer->numpasses != 0, 1);
+      }
+      /* if cblk not included, go to the next cblk  */
+      if (!layer->numpasses) {
+        continue;
+      }
+      /* if first instance of cblk --> zero bit-planes information */
+      if (!cblk->numpasses) {
+        cblk->numlenbits = 3;
+        tgt_encode(bio, prc->imsbtree, cblkno, 999);
+      }
+      /* number of coding passes included */
+      t2_putnumpasses(bio, layer->numpasses);
+      
+      /* computation of the increase of the length indicator and insertion in the header     */
+      for (passno = cblk->numpasses; passno < cblk->numpasses + layer->numpasses; passno++) {
+        opj_tcd_pass_t *pass = &cblk->passes[passno];
+        nump++;
+        len += pass->len;
+        if (pass->term || passno == (cblk->numpasses + layer->numpasses) - 1) {
+          increment = int_max(increment, int_floorlog2(len) + 1 - (cblk->numlenbits + int_floorlog2(nump)));
+          len = 0;
+          nump = 0;
+        }
+      }
+      t2_putcommacode(bio, increment);
+
+      /* computation of the new Length indicator */
+      cblk->numlenbits += increment;
+
+      /* insertion of the codeword segment length */
+      for (passno = cblk->numpasses; passno < cblk->numpasses + layer->numpasses; passno++) {
+        opj_tcd_pass_t *pass = &cblk->passes[passno];
+        nump++;
+        len += pass->len;
+        if (pass->term || passno == (cblk->numpasses + layer->numpasses) - 1) {
+          bio_write(bio, len, cblk->numlenbits + int_floorlog2(nump));
+          len = 0;
+          nump = 0;
+        }
+      }
+    }
+  }
+  
+  if (bio_flush(bio)) {
+    return -999;    /* modified to eliminate longjmp !! */
+  }
+  
+  c += bio_numbytes(bio);
+
+  bio_destroy(bio);
+  
+  /* <EPH 0xff92> */
+  if (tcp->csty & J2K_CP_CSTY_EPH) {
+    eph = (unsigned char *) opj_malloc(2 * sizeof(unsigned char));
+    eph[0] = 255;
+    eph[1] = 146;
+    memcpy(c, eph, 2);
+    opj_free(eph);
+    c += 2;
+  }
+  /* </EPH> */
+  
+  /* Writing the packet body */
+  
+  for (bandno = 0; bandno < res->numbands; bandno++) {
+    opj_tcd_band_t *band = &res->bands[bandno];
+    opj_tcd_precinct_t *prc = &band->precincts[precno];
+    for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+      opj_tcd_cblk_t *cblk = &prc->cblks[cblkno];
+      opj_tcd_layer_t *layer = &cblk->layers[layno];
+      if (!layer->numpasses) {
+        continue;
+      }
+      if (c + layer->len > dest + len) {
+        return -999;
+      }
+      
+      memcpy(c, layer->data, layer->len);
+      cblk->numpasses += layer->numpasses;
+      c += layer->len;
+      /* ADD for index Cfr. Marcela --> delta disto by packet */
+      if(image_info && image_info->index_write && image_info->index_on) {
+        opj_tile_info_t *info_TL = &image_info->tile[tileno];
+        opj_packet_info_t *info_PK = &info_TL->packet[image_info->num];
+        info_PK->disto += layer->disto;
+        if (image_info->D_max < info_PK->disto) {
+          image_info->D_max = info_PK->disto;
+        }
+      }
+      /* </ADD> */
+    }
+  }
+  
+  return (c - dest);
+}
+
+static void t2_init_seg(opj_tcd_seg_t * seg, int cblksty, int first) {
+  seg->numpasses = 0;
+  seg->len = 0;
+  if (cblksty & J2K_CCP_CBLKSTY_TERMALL) {
+    seg->maxpasses = 1;
+  }
+  else if (cblksty & J2K_CCP_CBLKSTY_LAZY) {
+    if (first) {
+      seg->maxpasses = 10;
+    } else {
+      seg->maxpasses = (((seg - 1)->maxpasses == 1) || ((seg - 1)->maxpasses == 10)) ? 2 : 1;
+    }
+  } else {
+    seg->maxpasses = 109;
+  }
+}
+
+static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_tile_t *tile, opj_tcp_t *tcp, opj_pi_iterator_t *pi) {
+  int bandno, cblkno;
+  unsigned char *c = src;
+
+  opj_cp_t *cp = t2->cp;
+
+  int compno = pi->compno;  /* component value */
+  int resno  = pi->resno;    /* resolution level value */
+  int precno = pi->precno;  /* precinct value */
+  int layno  = pi->layno;    /* quality layer value */
+
+  opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
+  opj_tcd_resolution_t *res = &tilec->resolutions[resno];
+  
+  unsigned char *hd = NULL;
+  int present;
+  
+  opj_bio_t *bio = NULL;  /* BIO component */
+  
+  if (layno == 0) {
+    for (bandno = 0; bandno < res->numbands; bandno++) {
+      opj_tcd_band_t *band = &res->bands[bandno];
+      opj_tcd_precinct_t *prc = &band->precincts[precno];
+      
+      if ((band->x1-band->x0 == 0)||(band->y1-band->y0 == 0)) continue;
+      
+      tgt_reset(prc->incltree);
+      tgt_reset(prc->imsbtree);
+      for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+        opj_tcd_cblk_t *cblk = &prc->cblks[cblkno];
+        cblk->numsegs = 0;
+      }
+    }
+  }
+  
+  /* SOP markers */
+  
+  if (tcp->csty & J2K_CP_CSTY_SOP) {
+    if ((*c) != 0xff || (*(c + 1) != 0x91)) {
+      opj_event_msg(t2->cinfo, EVT_WARNING, "Expected SOP marker\n");
+    } else {
+      c += 6;
+    }
+    
+    /** TODO : check the Nsop value */
+  }
+  
+  /* 
+  When the marker PPT/PPM is used the packet header are store in PPT/PPM marker
+  This part deal with this caracteristic
+  step 1: Read packet header in the saved structure
+  step 2: Return to codestream for decoding 
+  */
+
+  bio = bio_create();
+  
+  if (cp->ppm == 1) {    /* PPM */
+    hd = cp->ppm_data;
+    bio_init_dec(bio, hd, cp->ppm_len);
+  } else if (tcp->ppt == 1) {  /* PPT */
+    hd = tcp->ppt_data;
+    bio_init_dec(bio, hd, tcp->ppt_len);
+  } else {      /* Normal Case */
+    hd = c;
+    bio_init_dec(bio, hd, src+len-hd);
+  }
+  
+  present = bio_read(bio, 1);
+  
+  if (!present) {
+    bio_inalign(bio);
+    hd += bio_numbytes(bio);
+    bio_destroy(bio);
+    
+    /* EPH markers */
+    
+    if (tcp->csty & J2K_CP_CSTY_EPH) {
+      if ((*hd) != 0xff || (*(hd + 1) != 0x92)) {
+        printf("Error : expected EPH marker\n");
+      } else {
+        hd += 2;
+      }
+    }
+    
+    if (cp->ppm == 1) {    /* PPM case */
+      cp->ppm_len += cp->ppm_data-hd;
+      cp->ppm_data = hd;
+      return (c - src);
+    }
+    if (tcp->ppt == 1) {  /* PPT case */
+      tcp->ppt_len+=tcp->ppt_data-hd;
+      tcp->ppt_data = hd;
+      return (c - src);
+    }
+    
+    return (hd - src);
+  }
+  
+  for (bandno = 0; bandno < res->numbands; bandno++) {
+    opj_tcd_band_t *band = &res->bands[bandno];
+    opj_tcd_precinct_t *prc = &band->precincts[precno];
+    
+    if ((band->x1-band->x0 == 0)||(band->y1-band->y0 == 0)) continue;
+    
+    for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+      int included, increment, n;
+      opj_tcd_cblk_t *cblk = &prc->cblks[cblkno];
+      opj_tcd_seg_t *seg = NULL;
+      /* if cblk not yet included before --> inclusion tagtree */
+      if (!cblk->numsegs) {
+        included = tgt_decode(bio, prc->incltree, cblkno, layno + 1);
+        /* else one bit */
+      } else {
+        included = bio_read(bio, 1);
+      }
+      /* if cblk not included */
+      if (!included) {
+        cblk->numnewpasses = 0;
+        continue;
+      }
+      /* if cblk not yet included --> zero-bitplane tagtree */
+      if (!cblk->numsegs) {
+        int i, numimsbs;
+        for (i = 0; !tgt_decode(bio, prc->imsbtree, cblkno, i); i++) {
+          ;
+        }
+        numimsbs = i - 1;
+        cblk->numbps = band->numbps - numimsbs;
+        cblk->numlenbits = 3;
+      }
+      /* number of coding passes */
+      cblk->numnewpasses = t2_getnumpasses(bio);
+      increment = t2_getcommacode(bio);
+      /* length indicator increment */
+      cblk->numlenbits += increment;
+      if (!cblk->numsegs) {
+        seg = &cblk->segs[0];
+        t2_init_seg(seg, tcp->tccps[compno].cblksty, 1);
+      } else {
+        seg = &cblk->segs[cblk->numsegs - 1];
+        if (seg->numpasses == seg->maxpasses) {
+          t2_init_seg(++seg, tcp->tccps[compno].cblksty, 0);
+        }
+      }
+      n = cblk->numnewpasses;
+      
+      do {
+        seg->numnewpasses = int_min(seg->maxpasses - seg->numpasses, n);
+        seg->newlen = bio_read(bio, cblk->numlenbits + int_floorlog2(seg->numnewpasses));
+        n -= seg->numnewpasses;
+        if (n > 0) {
+          t2_init_seg(++seg, tcp->tccps[compno].cblksty, 0);
+        }
+      } while (n > 0);
+    }
+  }
+  
+  if (bio_inalign(bio)) {
+    bio_destroy(bio);
+    return -999;
+  }
+  
+  hd += bio_numbytes(bio);
+  bio_destroy(bio);
+  
+  /* EPH markers */
+  if (tcp->csty & J2K_CP_CSTY_EPH) {
+    if ((*hd) != 0xff || (*(hd + 1) != 0x92)) {
+      opj_event_msg(t2->cinfo, EVT_ERROR, "Expected EPH marker\n");
+    } else {
+      hd += 2;
+    }
+  }
+  
+  if (cp->ppm==1) {
+    cp->ppm_len+=cp->ppm_data-hd;
+    cp->ppm_data = hd;
+  } else if (tcp->ppt == 1) {
+    tcp->ppt_len+=tcp->ppt_data-hd;
+    tcp->ppt_data = hd;
+  } else {
+    c=hd;
+  }
+  
+  for (bandno = 0; bandno < res->numbands; bandno++) {
+    opj_tcd_band_t *band = &res->bands[bandno];
+    opj_tcd_precinct_t *prc = &band->precincts[precno];
+    
+    if ((band->x1-band->x0 == 0)||(band->y1-band->y0 == 0)) continue;
+    
+    for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+      opj_tcd_cblk_t *cblk = &prc->cblks[cblkno];
+      opj_tcd_seg_t *seg = NULL;
+      if (!cblk->numnewpasses)
+        continue;
+      if (!cblk->numsegs) {
+        seg = &cblk->segs[0];
+        cblk->numsegs++;
+        cblk->len = 0;
+      } else {
+        seg = &cblk->segs[cblk->numsegs - 1];
+        if (seg->numpasses == seg->maxpasses) {
+          seg++;
+          cblk->numsegs++;
+        }
+      }
+      
+      do {
+        if (c + seg->newlen > src + len) {
+          return -999;
+        }
+        
+        memcpy(cblk->data + cblk->len, c, seg->newlen);
+        if (seg->numpasses == 0) {
+          seg->data = cblk->data + cblk->len;
+        }
+        c += seg->newlen;
+        cblk->len += seg->newlen;
+        seg->len += seg->newlen;
+        seg->numpasses += seg->numnewpasses;
+        cblk->numnewpasses -= seg->numnewpasses;
+        if (cblk->numnewpasses > 0) {
+          seg++;
+          cblk->numsegs++;
+        }
+      } while (cblk->numnewpasses > 0);
+    }
+  }
+  
+  return (c - src);
+}
+
+/* ----------------------------------------------------------------------- */
+
+int t2_encode_packets(opj_t2_t* t2, int tileno, opj_tcd_tile_t *tile, int maxlayers, unsigned char *dest, int len, opj_image_info_t *image_info) {
+  unsigned char *c = dest;
+  int e = 0;
+  opj_pi_iterator_t *pi = NULL;
+  int pino;
+
+  opj_image_t *image = t2->image;
+  opj_cp_t *cp = t2->cp;
+  
+  /* create a packet iterator */
+  pi = pi_create(image, cp, tileno);
+  if(!pi) {
+    /* TODO: throw an error */
+    return -999;
+  }
+  
+  if(image_info) {
+    image_info->num = 0;
+  }
+  
+  for (pino = 0; pino <= cp->tcps[tileno].numpocs; pino++) {
+    while (pi_next(&pi[pino])) {
+      if (pi[pino].layno < maxlayers) {
+        e = t2_encode_packet(tile, &cp->tcps[tileno], &pi[pino], c, dest + len - c, image_info, tileno);
+        if (e == -999) {
+          break;
+        } else {
+          c += e;
+        }
+        
+        /* INDEX >> */
+        if(image_info && image_info->index_on) {
+          if(image_info->index_write) {
+            opj_tile_info_t *info_TL = &image_info->tile[tileno];
+            opj_packet_info_t *info_PK = &info_TL->packet[image_info->num];
+            if (!image_info->num) {
+              info_PK->start_pos = info_TL->end_header + 1;
+            } else {
+              info_PK->start_pos = info_TL->packet[image_info->num - 1].end_pos + 1;
+            }
+            info_PK->end_pos = info_PK->start_pos + e - 1;
+          }
+
+          image_info->num++;
+        }
+        /* << INDEX */
+      }
+    }
+  }
+
+  /* don't forget to release pi */
+  pi_destroy(pi, cp, tileno);
+  
+  if (e == -999) {
+    return e;
+  }
+
+    return (c - dest);
+}
+
+int t2_decode_packets(opj_t2_t *t2, unsigned char *src, int len, int tileno, opj_tcd_tile_t *tile) {
+  unsigned char *c = src;
+  opj_pi_iterator_t *pi;
+  int pino, e = 0;
+  int n = 0;
+
+  opj_image_t *image = t2->image;
+  opj_cp_t *cp = t2->cp;
+  
+  /* create a packet iterator */
+  pi = pi_create(image, cp, tileno);
+  if(!pi) {
+    /* TODO: throw an error */
+    return -999;
+  }
+  
+  for (pino = 0; pino <= cp->tcps[tileno].numpocs; pino++) {
+    while (pi_next(&pi[pino])) {
+      if ((cp->layer==0) || (cp->layer>=((pi[pino].layno)+1))) {
+        e = t2_decode_packet(t2, c, src + len - c, tile, &cp->tcps[tileno], &pi[pino]);
+      } else {
+        e = 0;
+      }
+      
+      /* progression in resolution */
+      image->comps[pi[pino].compno].resno_decoded =  
+        (e > 0) ? 
+        int_max(pi[pino].resno, image->comps[pi[pino].compno].resno_decoded) 
+        : image->comps[pi[pino].compno].resno_decoded;
+      n++;
+      
+      if (e == -999) {    /* ADD */
+        break;
+      } else {
+        c += e;
+      }
+    }
+  }
+
+  /* don't forget to release pi */
+  pi_destroy(pi, cp, tileno);
+  
+  if (e == -999) {
+    return e;
+  }
+  
+    return (c - src);
+}
+
+/* ----------------------------------------------------------------------- */
+
+opj_t2_t* t2_create(opj_common_ptr cinfo, opj_image_t *image, opj_cp_t *cp) {
+  /* create the tcd structure */
+  opj_t2_t *t2 = (opj_t2_t*)opj_malloc(sizeof(opj_t2_t));
+  if(!t2) return NULL;
+  t2->cinfo = cinfo;
+  t2->image = image;
+  t2->cp = cp;
+
+  return t2;
+}
+
+void t2_destroy(opj_t2_t *t2) {
+  if(t2) {
+    opj_free(t2);
+  }
+}
+
diff --git a/Utilities/ITK/Utilities/openjpeg/t2.h b/Utilities/ITK/Utilities/openjpeg/t2.h
new file mode 100644
index 0000000000..d1d4d90808
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/t2.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __T2_H
+#define __T2_H
+/**
+@file t2.h
+@brief Implementation of a tier-2 coding (packetization of code-block data) (T2)
+
+*/
+
+/** @defgroup T2 T2 - Implementation of a tier-2 coding */
+/*@{*/
+
+/**
+Tier-2 coding
+*/
+typedef struct opj_t2 {
+  /** codec context */
+  opj_common_ptr cinfo;
+
+  /** Encoding: pointer to the src image. Decoding: pointer to the dst image. */
+  opj_image_t *image;
+  /** pointer to the image coding parameters */
+  opj_cp_t *cp;
+} opj_t2_t;
+
+/** @name Exported functions */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+
+/**
+Encode the packets of a tile to a destination buffer
+@param t2 T2 handle
+@param tileno number of the tile encoded
+@param tile the tile for which to write the packets
+@param maxlayers maximum number of layers
+@param dest the destination buffer
+@param len the length of the destination buffer
+@param image_info structure to create an index file
+*/
+int t2_encode_packets(opj_t2_t* t2, int tileno, opj_tcd_tile_t *tile, int maxlayers, unsigned char *dest, int len, opj_image_info_t *image_info);
+
+/**
+Decode the packets of a tile from a source buffer
+@param t2 T2 handle
+@param src the source buffer
+@param len length of the source buffer
+@param tileno number that identifies the tile for which to decode the packets
+@param tile tile for which to decode the packets
+ */
+int t2_decode_packets(opj_t2_t *t2, unsigned char *src, int len, int tileno, opj_tcd_tile_t *tile);
+
+/**
+Create a T2 handle
+@param cinfo Codec context info
+@param image Source or destination image
+@param cp Image coding parameters
+@return Returns a new T2 handle if successful, returns NULL otherwise
+*/
+opj_t2_t* t2_create(opj_common_ptr cinfo, opj_image_t *image, opj_cp_t *cp);
+/**
+Destroy a T2 handle
+@param t2 T2 handle to destroy
+*/
+void t2_destroy(opj_t2_t *t2);
+
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __T2_H */
diff --git a/Utilities/ITK/Utilities/openjpeg/tcd.c b/Utilities/ITK/Utilities/openjpeg/tcd.c
new file mode 100644
index 0000000000..abd0d620d8
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/tcd.c
@@ -0,0 +1,1417 @@
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opj_includes.h"
+
+void tcd_dump(FILE *fd, opj_tcd_t *tcd, opj_tcd_image_t * img) {
+  int tileno, compno, resno, bandno, precno, cblkno;
+
+  fprintf(fd, "image {\n");
+  fprintf(fd, "  tw=%d, th=%d x0=%d x1=%d y0=%d y1=%d\n", 
+    img->tw, img->th, tcd->image->x0, tcd->image->x1, tcd->image->y0, tcd->image->y1);
+
+  for (tileno = 0; tileno < img->th * img->tw; tileno++) {
+    opj_tcd_tile_t *tile = &tcd->tcd_image->tiles[tileno];
+    fprintf(fd, "  tile {\n");
+    fprintf(fd, "    x0=%d, y0=%d, x1=%d, y1=%d, numcomps=%d\n",
+      tile->x0, tile->y0, tile->x1, tile->y1, tile->numcomps);
+    for (compno = 0; compno < tile->numcomps; compno++) {
+      opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
+      fprintf(fd, "    tilec {\n");
+      fprintf(fd,
+        "      x0=%d, y0=%d, x1=%d, y1=%d, numresolutions=%d\n",
+        tilec->x0, tilec->y0, tilec->x1, tilec->y1, tilec->numresolutions);
+      for (resno = 0; resno < tilec->numresolutions; resno++) {
+        opj_tcd_resolution_t *res = &tilec->resolutions[resno];
+        fprintf(fd, "\n   res {\n");
+        fprintf(fd,
+          "          x0=%d, y0=%d, x1=%d, y1=%d, pw=%d, ph=%d, numbands=%d\n",
+          res->x0, res->y0, res->x1, res->y1, res->pw, res->ph, res->numbands);
+        for (bandno = 0; bandno < res->numbands; bandno++) {
+          opj_tcd_band_t *band = &res->bands[bandno];
+          fprintf(fd, "        band {\n");
+          fprintf(fd,
+            "          x0=%d, y0=%d, x1=%d, y1=%d, stepsize=%f, numbps=%d\n",
+            band->x0, band->y0, band->x1, band->y1, band->stepsize, band->numbps);
+          for (precno = 0; precno < res->pw * res->ph; precno++) {
+            opj_tcd_precinct_t *prec = &band->precincts[precno];
+            fprintf(fd, "          prec {\n");
+            fprintf(fd,
+              "            x0=%d, y0=%d, x1=%d, y1=%d, cw=%d, ch=%d\n",
+              prec->x0, prec->y0, prec->x1, prec->y1, prec->cw, prec->ch);
+            for (cblkno = 0; cblkno < prec->cw * prec->ch; cblkno++) {
+              opj_tcd_cblk_t *cblk = &prec->cblks[cblkno];
+              fprintf(fd, "            cblk {\n");
+              fprintf(fd,
+                "              x0=%d, y0=%d, x1=%d, y1=%d\n",
+                cblk->x0, cblk->y0, cblk->x1, cblk->y1);
+              fprintf(fd, "            }\n");
+            }
+            fprintf(fd, "          }\n");
+          }
+          fprintf(fd, "        }\n");
+        }
+        fprintf(fd, "      }\n");
+      }
+      fprintf(fd, "    }\n");
+    }
+    fprintf(fd, "  }\n");
+  }
+  fprintf(fd, "}\n");
+}
+
+/* ----------------------------------------------------------------------- */
+
+/**
+Create a new TCD handle
+*/
+opj_tcd_t* tcd_create(opj_common_ptr cinfo) {
+  /* create the tcd structure */
+  opj_tcd_t *tcd = (opj_tcd_t*)opj_malloc(sizeof(opj_tcd_t));
+  if(!tcd) return NULL;
+  tcd->cinfo = cinfo;
+  tcd->tcd_image = (opj_tcd_image_t*)opj_malloc(sizeof(opj_tcd_image_t));
+  if(!tcd->tcd_image) {
+    opj_free(tcd);
+    return NULL;
+  }
+
+  return tcd;
+}
+
+/**
+Destroy a previously created TCD handle
+*/
+void tcd_destroy(opj_tcd_t *tcd) {
+  if(tcd) {
+    opj_free(tcd->tcd_image);
+    opj_free(tcd);
+  }
+}
+
+/* ----------------------------------------------------------------------- */
+
+void tcd_malloc_encode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, int curtileno) {
+  int tileno, compno, resno, bandno, precno, cblkno;
+
+  opj_tcd_tile_t *tile = NULL;    /* pointer to tcd->tile */
+  opj_tcd_tilecomp_t *tilec = NULL;  /* pointer to tcd->tilec */
+  opj_tcd_resolution_t *res = NULL;  /* pointer to tcd->res */
+  opj_tcd_band_t *band = NULL;    /* pointer to tcd->band */
+  opj_tcd_precinct_t *prc = NULL;    /* pointer to tcd->prc */
+  opj_tcd_cblk_t *cblk = NULL;    /* pointer to tcd->cblk */
+
+  tcd->image = image;
+  tcd->cp = cp;
+  tcd->tcd_image->tw = cp->tw;
+  tcd->tcd_image->th = cp->th;
+  tcd->tcd_image->tiles = (opj_tcd_tile_t *) opj_malloc(sizeof(opj_tcd_tile_t));
+  
+  for (tileno = 0; tileno < 1; tileno++) {
+    opj_tcp_t *tcp = &cp->tcps[curtileno];
+    int j;
+
+    /* cfr p59 ISO/IEC FDIS15444-1 : 2000 (18 august 2000) */
+    int p = curtileno % cp->tw;  /* si numerotation matricielle .. */
+    int q = curtileno / cp->tw;  /* .. coordonnees de la tile (q,p) q pour ligne et p pour colonne */
+
+    /* opj_tcd_tile_t *tile=&tcd->tcd_image->tiles[tileno]; */
+    tcd->tile = tcd->tcd_image->tiles;
+    tile = tcd->tile;
+
+    /* 4 borders of the tile rescale on the image if necessary */
+    tile->x0 = int_max(cp->tx0 + p * cp->tdx, image->x0);
+    tile->y0 = int_max(cp->ty0 + q * cp->tdy, image->y0);
+    tile->x1 = int_min(cp->tx0 + (p + 1) * cp->tdx, image->x1);
+    tile->y1 = int_min(cp->ty0 + (q + 1) * cp->tdy, image->y1);
+    tile->numcomps = image->numcomps;
+    /* tile->PPT=image->PPT;  */
+
+    /* Modification of the RATE >> */
+    for (j = 0; j < tcp->numlayers; j++) {
+      tcp->rates[j] = tcp->rates[j] ? 
+        int_ceildiv(tile->numcomps 
+          * (tile->x1 - tile->x0) 
+          * (tile->y1 - tile->y0) 
+          * image->comps[0].prec, 
+          (tcp->rates[j] * 8 * image->comps[0].dx * image->comps[0].dy)) 
+          : 0;
+
+      if (tcp->rates[j]) {
+        if (j && tcp->rates[j] < tcp->rates[j - 1] + 10) {
+          tcp->rates[j] = tcp->rates[j - 1] + 20;
+        } else {
+          if (!j && tcp->rates[j] < 30)
+            tcp->rates[j] = 30;
+        }
+      }
+    }
+    /* << Modification of the RATE */
+    
+    tile->comps = (opj_tcd_tilecomp_t *) opj_malloc(image->numcomps * sizeof(opj_tcd_tilecomp_t));
+    for (compno = 0; compno < tile->numcomps; compno++) {
+      opj_tccp_t *tccp = &tcp->tccps[compno];
+
+      /* opj_tcd_tilecomp_t *tilec=&tile->comps[compno]; */
+      tcd->tilec = &tile->comps[compno];
+      tilec = tcd->tilec;
+
+      /* border of each tile component (global) */
+      tilec->x0 = int_ceildiv(tile->x0, image->comps[compno].dx);
+      tilec->y0 = int_ceildiv(tile->y0, image->comps[compno].dy);
+      tilec->x1 = int_ceildiv(tile->x1, image->comps[compno].dx);
+      tilec->y1 = int_ceildiv(tile->y1, image->comps[compno].dy);
+      
+      tilec->data = (int *) opj_malloc((tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0) * sizeof(int));
+      tilec->numresolutions = tccp->numresolutions;
+
+      tilec->resolutions = (opj_tcd_resolution_t *) opj_malloc(tilec->numresolutions * sizeof(opj_tcd_resolution_t));
+      
+      for (resno = 0; resno < tilec->numresolutions; resno++) {
+        int pdx, pdy;
+        int levelno = tilec->numresolutions - 1 - resno;
+        int tlprcxstart, tlprcystart, brprcxend, brprcyend;
+        int tlcbgxstart, tlcbgystart, brcbgxend, brcbgyend;
+        int cbgwidthexpn, cbgheightexpn;
+        int cblkwidthexpn, cblkheightexpn;
+
+        /* opj_tcd_resolution_t *res=&tilec->resolutions[resno]; */
+        tcd->res = &tilec->resolutions[resno];
+        res = tcd->res;
+        
+        /* border for each resolution level (global) */
+        res->x0 = int_ceildivpow2(tilec->x0, levelno);
+        res->y0 = int_ceildivpow2(tilec->y0, levelno);
+        res->x1 = int_ceildivpow2(tilec->x1, levelno);
+        res->y1 = int_ceildivpow2(tilec->y1, levelno);
+        
+        res->numbands = resno == 0 ? 1 : 3;
+        /* p. 35, table A-23, ISO/IEC FDIS154444-1 : 2000 (18 august 2000) */
+        if (tccp->csty & J2K_CCP_CSTY_PRT) {
+          pdx = tccp->prcw[resno];
+          pdy = tccp->prch[resno];
+        } else {
+          pdx = 15;
+          pdy = 15;
+        }
+        /* p. 64, B.6, ISO/IEC FDIS15444-1 : 2000 (18 august 2000)  */
+        tlprcxstart = int_floordivpow2(res->x0, pdx) << pdx;
+        tlprcystart = int_floordivpow2(res->y0, pdy) << pdy;
+        
+        brprcxend = int_ceildivpow2(res->x1, pdx) << pdx;
+        brprcyend = int_ceildivpow2(res->y1, pdy) << pdy;
+        
+        res->pw = (brprcxend - tlprcxstart) >> pdx;
+        res->ph = (brprcyend - tlprcystart) >> pdy;
+        
+        if (resno == 0) {
+          tlcbgxstart = tlprcxstart;
+          tlcbgystart = tlprcystart;
+          brcbgxend = brprcxend;
+          brcbgyend = brprcyend;
+          cbgwidthexpn = pdx;
+          cbgheightexpn = pdy;
+        } else {
+          tlcbgxstart = int_ceildivpow2(tlprcxstart, 1);
+          tlcbgystart = int_ceildivpow2(tlprcystart, 1);
+          brcbgxend = int_ceildivpow2(brprcxend, 1);
+          brcbgyend = int_ceildivpow2(brprcyend, 1);
+          cbgwidthexpn = pdx - 1;
+          cbgheightexpn = pdy - 1;
+        }
+        
+        cblkwidthexpn = int_min(tccp->cblkw, cbgwidthexpn);
+        cblkheightexpn = int_min(tccp->cblkh, cbgheightexpn);
+        
+        for (bandno = 0; bandno < res->numbands; bandno++) {
+          int x0b, y0b, i;
+          int gain, numbps;
+          opj_stepsize_t *ss = NULL;
+
+          tcd->band = &res->bands[bandno];
+          band = tcd->band;
+
+          band->bandno = resno == 0 ? 0 : bandno + 1;
+          x0b = (band->bandno == 1) || (band->bandno == 3) ? 1 : 0;
+          y0b = (band->bandno == 2) || (band->bandno == 3) ? 1 : 0;
+          
+          if (band->bandno == 0) {
+            /* band border (global) */
+            band->x0 = int_ceildivpow2(tilec->x0, levelno);
+            band->y0 = int_ceildivpow2(tilec->y0, levelno);
+            band->x1 = int_ceildivpow2(tilec->x1, levelno);
+            band->y1 = int_ceildivpow2(tilec->y1, levelno);
+          } else {
+            /* band border (global) */
+            band->x0 = int_ceildivpow2(tilec->x0 - (1 << levelno) * x0b, levelno + 1);
+            band->y0 = int_ceildivpow2(tilec->y0 - (1 << levelno) * y0b, levelno + 1);
+            band->x1 = int_ceildivpow2(tilec->x1 - (1 << levelno) * x0b, levelno + 1);
+            band->y1 = int_ceildivpow2(tilec->y1 - (1 << levelno) * y0b, levelno + 1);
+          }
+          
+          ss = &tccp->stepsizes[resno == 0 ? 0 : 3 * (resno - 1) + bandno + 1];
+          gain = tccp->qmfbid == 0 ? dwt_getgain_real(band->bandno) : dwt_getgain(band->bandno);          
+          numbps = image->comps[compno].prec + gain;
+          
+          band->stepsize = (float)((1.0 + ss->mant / 2048.0) * pow(2.0, numbps - ss->expn));
+          band->numbps = ss->expn + tccp->numgbits - 1;  /* WHY -1 ? */
+          
+          band->precincts = (opj_tcd_precinct_t *) opj_malloc(3 * res->pw * res->ph * sizeof(opj_tcd_precinct_t));
+          
+          for (i = 0; i < res->pw * res->ph * 3; i++) {
+            band->precincts[i].imsbtree = NULL;
+            band->precincts[i].incltree = NULL;
+          }
+          
+          for (precno = 0; precno < res->pw * res->ph; precno++) {
+            int tlcblkxstart, tlcblkystart, brcblkxend, brcblkyend;
+
+            int cbgxstart = tlcbgxstart + (precno % res->pw) * (1 << cbgwidthexpn);
+            int cbgystart = tlcbgystart + (precno / res->pw) * (1 << cbgheightexpn);
+            int cbgxend = cbgxstart + (1 << cbgwidthexpn);
+            int cbgyend = cbgystart + (1 << cbgheightexpn);
+
+            /* opj_tcd_precinct_t *prc=&band->precincts[precno]; */
+            tcd->prc = &band->precincts[precno];
+            prc = tcd->prc;
+
+            /* precinct size (global) */
+            prc->x0 = int_max(cbgxstart, band->x0);
+            prc->y0 = int_max(cbgystart, band->y0);
+            prc->x1 = int_min(cbgxend, band->x1);
+            prc->y1 = int_min(cbgyend, band->y1);
+
+            tlcblkxstart = int_floordivpow2(prc->x0, cblkwidthexpn) << cblkwidthexpn;
+            tlcblkystart = int_floordivpow2(prc->y0, cblkheightexpn) << cblkheightexpn;
+            brcblkxend = int_ceildivpow2(prc->x1, cblkwidthexpn) << cblkwidthexpn;
+            brcblkyend = int_ceildivpow2(prc->y1, cblkheightexpn) << cblkheightexpn;
+            prc->cw = (brcblkxend - tlcblkxstart) >> cblkwidthexpn;
+            prc->ch = (brcblkyend - tlcblkystart) >> cblkheightexpn;
+
+            prc->cblks = (opj_tcd_cblk_t *) opj_malloc((prc->cw * prc->ch) * sizeof(opj_tcd_cblk_t));
+            prc->incltree = tgt_create(prc->cw, prc->ch);
+            prc->imsbtree = tgt_create(prc->cw, prc->ch);
+            
+            for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+              int cblkxstart = tlcblkxstart + (cblkno % prc->cw) * (1 << cblkwidthexpn);
+              int cblkystart = tlcblkystart + (cblkno / prc->cw) * (1 << cblkheightexpn);
+              int cblkxend = cblkxstart + (1 << cblkwidthexpn);
+              int cblkyend = cblkystart + (1 << cblkheightexpn);
+              
+              tcd->cblk = &prc->cblks[cblkno];
+              cblk = tcd->cblk;
+
+              /* code-block size (global) */
+              cblk->x0 = int_max(cblkxstart, prc->x0);
+              cblk->y0 = int_max(cblkystart, prc->y0);
+              cblk->x1 = int_min(cblkxend, prc->x1);
+              cblk->y1 = int_min(cblkyend, prc->y1);
+            }
+          }
+        }
+      }
+    }
+  }
+  
+  /* tcd_dump(stdout, tcd, &tcd->tcd_image); */
+}
+
+void tcd_free_encode(opj_tcd_t *tcd) {
+  int tileno, compno, resno, bandno, precno;
+
+  opj_tcd_tile_t *tile = NULL;    /* pointer to tcd->tile    */
+  opj_tcd_tilecomp_t *tilec = NULL;  /* pointer to tcd->tilec  */
+  opj_tcd_resolution_t *res = NULL;  /* pointer to tcd->res    */
+  opj_tcd_band_t *band = NULL;    /* pointer to tcd->band    */
+  opj_tcd_precinct_t *prc = NULL;    /* pointer to tcd->prc    */
+
+  for (tileno = 0; tileno < 1; tileno++) {
+    tcd->tile = tcd->tcd_image->tiles;
+    tile = tcd->tile;
+
+    for (compno = 0; compno < tile->numcomps; compno++) {
+      tcd->tilec = &tile->comps[compno];
+      tilec = tcd->tilec;
+
+      for (resno = 0; resno < tilec->numresolutions; resno++) {
+        tcd->res = &tilec->resolutions[resno];
+        res = tcd->res;
+
+        for (bandno = 0; bandno < res->numbands; bandno++) {
+          tcd->band = &res->bands[bandno];
+          band = tcd->band;
+
+          for (precno = 0; precno < res->pw * res->ph; precno++) {
+            tcd->prc = &band->precincts[precno];
+            prc = tcd->prc;
+
+            if (prc->incltree != NULL) {
+              tgt_destroy(prc->incltree);
+              prc->incltree = NULL;
+            }
+            if (prc->imsbtree != NULL) {
+              tgt_destroy(prc->imsbtree);  
+              prc->imsbtree = NULL;
+            }
+            opj_free(prc->cblks);
+            prc->cblks = NULL;
+          } /* for (precno */
+          opj_free(band->precincts);
+          band->precincts = NULL;
+        } /* for (bandno */
+      } /* for (resno */
+      opj_free(tilec->resolutions);
+      tilec->resolutions = NULL;
+    } /* for (compno */
+    opj_free(tile->comps);
+    tile->comps = NULL;
+  } /* for (tileno */
+  opj_free(tcd->tcd_image->tiles);
+  tcd->tcd_image->tiles = NULL;
+}
+
+void tcd_init_encode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, int curtileno) {
+  int tileno, compno, resno, bandno, precno, cblkno;
+
+  opj_tcd_tile_t *tile = NULL;    /* pointer to tcd->tile */
+  opj_tcd_tilecomp_t *tilec = NULL;  /* pointer to tcd->tilec */
+  opj_tcd_resolution_t *res = NULL;  /* pointer to tcd->res */
+  opj_tcd_band_t *band = NULL;    /* pointer to tcd->band */
+  opj_tcd_precinct_t *prc = NULL;    /* pointer to tcd->prc */
+  opj_tcd_cblk_t *cblk = NULL;    /* pointer to tcd->cblk */
+
+  for (tileno = 0; tileno < 1; tileno++) {
+    opj_tcp_t *tcp = &cp->tcps[curtileno];
+    int j;
+    /* cfr p59 ISO/IEC FDIS15444-1 : 2000 (18 august 2000) */
+    int p = curtileno % cp->tw;
+    int q = curtileno / cp->tw;
+
+    tcd->tile = tcd->tcd_image->tiles;
+    tile = tcd->tile;
+    
+    /* 4 borders of the tile rescale on the image if necessary */
+    tile->x0 = int_max(cp->tx0 + p * cp->tdx, image->x0);
+    tile->y0 = int_max(cp->ty0 + q * cp->tdy, image->y0);
+    tile->x1 = int_min(cp->tx0 + (p + 1) * cp->tdx, image->x1);
+    tile->y1 = int_min(cp->ty0 + (q + 1) * cp->tdy, image->y1);
+    
+    tile->numcomps = image->numcomps;
+    /* tile->PPT=image->PPT; */
+
+    /* Modification of the RATE >> */
+    for (j = 0; j < tcp->numlayers; j++) {
+      tcp->rates[j] = tcp->rates[j] ? 
+        int_ceildiv(tile->numcomps 
+        * (tile->x1 - tile->x0) 
+        * (tile->y1 - tile->y0) 
+        * image->comps[0].prec, 
+        (tcp->rates[j] * 8 * image->comps[0].dx * image->comps[0].dy)) 
+        : 0;
+
+      if (tcp->rates[j]) {
+        if (j && tcp->rates[j] < tcp->rates[j - 1] + 10) {
+          tcp->rates[j] = tcp->rates[j - 1] + 20;
+        } else {
+          if (!j && tcp->rates[j] < 30)
+            tcp->rates[j] = 30;
+        }
+      }
+    }
+    /* << Modification of the RATE */
+
+    /* tile->comps=(opj_tcd_tilecomp_t*)opj_realloc(tile->comps,image->numcomps*sizeof(opj_tcd_tilecomp_t)); */
+    for (compno = 0; compno < tile->numcomps; compno++) {
+      opj_tccp_t *tccp = &tcp->tccps[compno];
+      
+      tcd->tilec = &tile->comps[compno];
+      tilec = tcd->tilec;
+
+      /* border of each tile component (global) */
+      tilec->x0 = int_ceildiv(tile->x0, image->comps[compno].dx);
+      tilec->y0 = int_ceildiv(tile->y0, image->comps[compno].dy);
+      tilec->x1 = int_ceildiv(tile->x1, image->comps[compno].dx);
+      tilec->y1 = int_ceildiv(tile->y1, image->comps[compno].dy);
+      
+      tilec->data = (int *) opj_malloc((tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0) * sizeof(int));
+      tilec->numresolutions = tccp->numresolutions;
+      /* tilec->resolutions=(opj_tcd_resolution_t*)opj_realloc(tilec->resolutions,tilec->numresolutions*sizeof(opj_tcd_resolution_t)); */
+      for (resno = 0; resno < tilec->numresolutions; resno++) {
+        int pdx, pdy;
+
+        int levelno = tilec->numresolutions - 1 - resno;
+        int tlprcxstart, tlprcystart, brprcxend, brprcyend;
+        int tlcbgxstart, tlcbgystart, brcbgxend, brcbgyend;
+        int cbgwidthexpn, cbgheightexpn;
+        int cblkwidthexpn, cblkheightexpn;
+        
+        tcd->res = &tilec->resolutions[resno];
+        res = tcd->res;
+
+        /* border for each resolution level (global) */
+        res->x0 = int_ceildivpow2(tilec->x0, levelno);
+        res->y0 = int_ceildivpow2(tilec->y0, levelno);
+        res->x1 = int_ceildivpow2(tilec->x1, levelno);
+        res->y1 = int_ceildivpow2(tilec->y1, levelno);  
+        res->numbands = resno == 0 ? 1 : 3;
+
+        /* p. 35, table A-23, ISO/IEC FDIS154444-1 : 2000 (18 august 2000) */
+        if (tccp->csty & J2K_CCP_CSTY_PRT) {
+          pdx = tccp->prcw[resno];
+          pdy = tccp->prch[resno];
+        } else {
+          pdx = 15;
+          pdy = 15;
+        }
+        /* p. 64, B.6, ISO/IEC FDIS15444-1 : 2000 (18 august 2000)  */
+        tlprcxstart = int_floordivpow2(res->x0, pdx) << pdx;
+        tlprcystart = int_floordivpow2(res->y0, pdy) << pdy;
+        brprcxend = int_ceildivpow2(res->x1, pdx) << pdx;
+        brprcyend = int_ceildivpow2(res->y1, pdy) << pdy;
+        
+        res->pw = (brprcxend - tlprcxstart) >> pdx;
+        res->ph = (brprcyend - tlprcystart) >> pdy;
+        
+        if (resno == 0) {
+          tlcbgxstart = tlprcxstart;
+          tlcbgystart = tlprcystart;
+          brcbgxend = brprcxend;
+          brcbgyend = brprcyend;
+          cbgwidthexpn = pdx;
+          cbgheightexpn = pdy;
+        } else {
+          tlcbgxstart = int_ceildivpow2(tlprcxstart, 1);
+          tlcbgystart = int_ceildivpow2(tlprcystart, 1);
+          brcbgxend = int_ceildivpow2(brprcxend, 1);
+          brcbgyend = int_ceildivpow2(brprcyend, 1);
+          cbgwidthexpn = pdx - 1;
+          cbgheightexpn = pdy - 1;
+        }
+        
+        cblkwidthexpn = int_min(tccp->cblkw, cbgwidthexpn);
+        cblkheightexpn = int_min(tccp->cblkh, cbgheightexpn);
+        
+        for (bandno = 0; bandno < res->numbands; bandno++) {
+          int x0b, y0b;
+          int gain, numbps;
+          opj_stepsize_t *ss = NULL;
+
+          tcd->band = &res->bands[bandno];
+          band = tcd->band;
+
+          band->bandno = resno == 0 ? 0 : bandno + 1;
+          x0b = (band->bandno == 1) || (band->bandno == 3) ? 1 : 0;
+          y0b = (band->bandno == 2) || (band->bandno == 3) ? 1 : 0;
+          
+          if (band->bandno == 0) {
+            /* band border */
+            band->x0 = int_ceildivpow2(tilec->x0, levelno);
+            band->y0 = int_ceildivpow2(tilec->y0, levelno);
+            band->x1 = int_ceildivpow2(tilec->x1, levelno);
+            band->y1 = int_ceildivpow2(tilec->y1, levelno);
+          } else {
+            band->x0 = int_ceildivpow2(tilec->x0 - (1 << levelno) * x0b, levelno + 1);
+            band->y0 = int_ceildivpow2(tilec->y0 - (1 << levelno) * y0b, levelno + 1);
+            band->x1 = int_ceildivpow2(tilec->x1 - (1 << levelno) * x0b, levelno + 1);
+            band->y1 = int_ceildivpow2(tilec->y1 - (1 << levelno) * y0b, levelno + 1);
+          }
+          
+          ss = &tccp->stepsizes[resno == 0 ? 0 : 3 * (resno - 1) + bandno + 1];
+          gain = tccp->qmfbid == 0 ? dwt_getgain_real(band->bandno) : dwt_getgain(band->bandno);
+          numbps = image->comps[compno].prec + gain;
+          band->stepsize = (float)((1.0 + ss->mant / 2048.0) * pow(2.0, numbps - ss->expn));
+          band->numbps = ss->expn + tccp->numgbits - 1;  /* WHY -1 ? */
+          
+          for (precno = 0; precno < res->pw * res->ph; precno++) {
+            int tlcblkxstart, tlcblkystart, brcblkxend, brcblkyend;
+
+            int cbgxstart = tlcbgxstart + (precno % res->pw) * (1 << cbgwidthexpn);
+            int cbgystart = tlcbgystart + (precno / res->pw) * (1 << cbgheightexpn);
+            int cbgxend = cbgxstart + (1 << cbgwidthexpn);
+            int cbgyend = cbgystart + (1 << cbgheightexpn);
+            
+            tcd->prc = &band->precincts[precno];
+            prc = tcd->prc;
+
+            /* precinct size (global) */
+            prc->x0 = int_max(cbgxstart, band->x0);
+            prc->y0 = int_max(cbgystart, band->y0);
+            prc->x1 = int_min(cbgxend, band->x1);
+            prc->y1 = int_min(cbgyend, band->y1);
+
+            tlcblkxstart = int_floordivpow2(prc->x0, cblkwidthexpn) << cblkwidthexpn;
+            tlcblkystart = int_floordivpow2(prc->y0, cblkheightexpn) << cblkheightexpn;
+            brcblkxend = int_ceildivpow2(prc->x1, cblkwidthexpn) << cblkwidthexpn;
+            brcblkyend = int_ceildivpow2(prc->y1, cblkheightexpn) << cblkheightexpn;
+            prc->cw = (brcblkxend - tlcblkxstart) >> cblkwidthexpn;
+            prc->ch = (brcblkyend - tlcblkystart) >> cblkheightexpn;
+
+            opj_free(prc->cblks);
+            prc->cblks = (opj_tcd_cblk_t *) opj_malloc(prc->cw * prc->ch * sizeof(opj_tcd_cblk_t));
+
+            if (prc->incltree != NULL) {
+              tgt_destroy(prc->incltree);
+            }
+            if (prc->imsbtree != NULL) {
+              tgt_destroy(prc->imsbtree);
+            }
+            
+            prc->incltree = tgt_create(prc->cw, prc->ch);
+            prc->imsbtree = tgt_create(prc->cw, prc->ch);
+
+            for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+              int cblkxstart = tlcblkxstart + (cblkno % prc->cw) * (1 << cblkwidthexpn);
+              int cblkystart = tlcblkystart + (cblkno / prc->cw) * (1 << cblkheightexpn);
+              int cblkxend = cblkxstart + (1 << cblkwidthexpn);
+              int cblkyend = cblkystart + (1 << cblkheightexpn);
+
+              tcd->cblk = &prc->cblks[cblkno];
+              cblk = tcd->cblk;
+              
+              /* code-block size (global) */
+              cblk->x0 = int_max(cblkxstart, prc->x0);
+              cblk->y0 = int_max(cblkystart, prc->y0);
+              cblk->x1 = int_min(cblkxend, prc->x1);
+              cblk->y1 = int_min(cblkyend, prc->y1);
+            }
+          } /* precno */
+        } /* bandno */
+      } /* resno */
+    } /* compno */
+  } /* tileno */
+
+  /* tcd_dump(stdout, tcd, &tcd->tcd_image); */
+}
+
+void tcd_malloc_decode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp) {
+  int tileno, compno, resno, bandno, precno, cblkno, i, j, p, q;
+  unsigned int x0 = 0, y0 = 0, x1 = 0, y1 = 0, w, h;
+
+  tcd->image = image;
+  tcd->cp = cp;
+  tcd->tcd_image->tw = cp->tw;
+  tcd->tcd_image->th = cp->th;
+  tcd->tcd_image->tiles = (opj_tcd_tile_t *) opj_malloc(cp->tw * cp->th * sizeof(opj_tcd_tile_t));
+  
+  for (i = 0; i < cp->tileno_size; i++) {
+    opj_tcp_t *tcp = &(cp->tcps[cp->tileno[i]]);
+    opj_tcd_tile_t *tile = &(tcd->tcd_image->tiles[cp->tileno[i]]);
+  
+    /* cfr p59 ISO/IEC FDIS15444-1 : 2000 (18 august 2000) */
+    tileno = cp->tileno[i];
+    p = tileno % cp->tw;  /* si numerotation matricielle .. */
+    q = tileno / cp->tw;  /* .. coordonnees de la tile (q,p) q pour ligne et p pour colonne */
+
+    /* 4 borders of the tile rescale on the image if necessary */
+    tile->x0 = int_max(cp->tx0 + p * cp->tdx, image->x0);
+    tile->y0 = int_max(cp->ty0 + q * cp->tdy, image->y0);
+    tile->x1 = int_min(cp->tx0 + (p + 1) * cp->tdx, image->x1);
+    tile->y1 = int_min(cp->ty0 + (q + 1) * cp->tdy, image->y1);
+    
+    tile->numcomps = image->numcomps;
+    tile->comps = (opj_tcd_tilecomp_t *) opj_malloc(image->numcomps * sizeof(opj_tcd_tilecomp_t));
+    for (compno = 0; compno < tile->numcomps; compno++) {
+      opj_tccp_t *tccp = &tcp->tccps[compno];
+      opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
+
+      /* border of each tile component (global) */
+      tilec->x0 = int_ceildiv(tile->x0, image->comps[compno].dx);
+      tilec->y0 = int_ceildiv(tile->y0, image->comps[compno].dy);
+      tilec->x1 = int_ceildiv(tile->x1, image->comps[compno].dx);
+      tilec->y1 = int_ceildiv(tile->y1, image->comps[compno].dy);
+      
+      tilec->data = (int *) opj_malloc((tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0) * sizeof(int));
+      tilec->numresolutions = tccp->numresolutions;
+      tilec->resolutions = (opj_tcd_resolution_t *) opj_malloc(tilec->numresolutions * sizeof(opj_tcd_resolution_t));
+
+      for (resno = 0; resno < tilec->numresolutions; resno++) {
+        int pdx, pdy;
+        int levelno = tilec->numresolutions - 1 - resno;
+        int tlprcxstart, tlprcystart, brprcxend, brprcyend;
+        int tlcbgxstart, tlcbgystart, brcbgxend, brcbgyend;
+        int cbgwidthexpn, cbgheightexpn;
+        int cblkwidthexpn, cblkheightexpn;
+
+        opj_tcd_resolution_t *res = &tilec->resolutions[resno];
+        
+        /* border for each resolution level (global) */
+        res->x0 = int_ceildivpow2(tilec->x0, levelno);
+        res->y0 = int_ceildivpow2(tilec->y0, levelno);
+        res->x1 = int_ceildivpow2(tilec->x1, levelno);
+        res->y1 = int_ceildivpow2(tilec->y1, levelno);
+        res->numbands = resno == 0 ? 1 : 3;
+        
+        /* p. 35, table A-23, ISO/IEC FDIS154444-1 : 2000 (18 august 2000) */
+        if (tccp->csty & J2K_CCP_CSTY_PRT) {
+          pdx = tccp->prcw[resno];
+          pdy = tccp->prch[resno];
+        } else {
+          pdx = 15;
+          pdy = 15;
+        }
+        
+        /* p. 64, B.6, ISO/IEC FDIS15444-1 : 2000 (18 august 2000)  */
+        tlprcxstart = int_floordivpow2(res->x0, pdx) << pdx;
+        tlprcystart = int_floordivpow2(res->y0, pdy) << pdy;
+        brprcxend = int_ceildivpow2(res->x1, pdx) << pdx;
+        brprcyend = int_ceildivpow2(res->y1, pdy) << pdy;
+
+        res->pw = (res->x0 == res->x1) ? 0 : ((brprcxend - tlprcxstart) >> pdx);
+        res->ph = (res->y0 == res->y1) ? 0 : ((brprcyend - tlprcystart) >> pdy);
+        
+        if (resno == 0) {
+          tlcbgxstart = tlprcxstart;
+          tlcbgystart = tlprcystart;
+          brcbgxend = brprcxend;
+          brcbgyend = brprcyend;
+          cbgwidthexpn = pdx;
+          cbgheightexpn = pdy;
+        } else {
+          tlcbgxstart = int_ceildivpow2(tlprcxstart, 1);
+          tlcbgystart = int_ceildivpow2(tlprcystart, 1);
+          brcbgxend = int_ceildivpow2(brprcxend, 1);
+          brcbgyend = int_ceildivpow2(brprcyend, 1);
+          cbgwidthexpn = pdx - 1;
+          cbgheightexpn = pdy - 1;
+        }
+        
+        cblkwidthexpn = int_min(tccp->cblkw, cbgwidthexpn);
+        cblkheightexpn = int_min(tccp->cblkh, cbgheightexpn);
+        
+        for (bandno = 0; bandno < res->numbands; bandno++) {
+          int x0b, y0b;
+          int gain, numbps;
+          opj_stepsize_t *ss = NULL;
+
+          opj_tcd_band_t *band = &res->bands[bandno];
+          band->bandno = resno == 0 ? 0 : bandno + 1;
+          x0b = (band->bandno == 1) || (band->bandno == 3) ? 1 : 0;
+          y0b = (band->bandno == 2) || (band->bandno == 3) ? 1 : 0;
+          
+          if (band->bandno == 0) {
+            /* band border (global) */
+            band->x0 = int_ceildivpow2(tilec->x0, levelno);
+            band->y0 = int_ceildivpow2(tilec->y0, levelno);
+            band->x1 = int_ceildivpow2(tilec->x1, levelno);
+            band->y1 = int_ceildivpow2(tilec->y1, levelno);
+          } else {
+            /* band border (global) */
+            band->x0 = int_ceildivpow2(tilec->x0 - (1 << levelno) * x0b, levelno + 1);
+            band->y0 = int_ceildivpow2(tilec->y0 - (1 << levelno) * y0b, levelno + 1);
+            band->x1 = int_ceildivpow2(tilec->x1 - (1 << levelno) * x0b, levelno + 1);
+            band->y1 = int_ceildivpow2(tilec->y1 - (1 << levelno) * y0b, levelno + 1);
+          }
+          
+          ss = &tccp->stepsizes[resno == 0 ? 0 : 3 * (resno - 1) + bandno + 1];
+          gain = tccp->qmfbid == 0 ? dwt_getgain_real(band->bandno) : dwt_getgain(band->bandno);
+          numbps = image->comps[compno].prec + gain;
+          band->stepsize = (float)((1.0 + ss->mant / 2048.0) * pow(2.0, numbps - ss->expn));
+          band->numbps = ss->expn + tccp->numgbits - 1;  /* WHY -1 ? */
+          
+          band->precincts = (opj_tcd_precinct_t *) opj_malloc(res->pw * res->ph * sizeof(opj_tcd_precinct_t));
+          
+          for (precno = 0; precno < res->pw * res->ph; precno++) {
+            int tlcblkxstart, tlcblkystart, brcblkxend, brcblkyend;
+            int cbgxstart = tlcbgxstart + (precno % res->pw) * (1 << cbgwidthexpn);
+            int cbgystart = tlcbgystart + (precno / res->pw) * (1 << cbgheightexpn);
+            int cbgxend = cbgxstart + (1 << cbgwidthexpn);
+            int cbgyend = cbgystart + (1 << cbgheightexpn);
+
+            opj_tcd_precinct_t *prc = &band->precincts[precno];
+            /* precinct size (global) */
+            prc->x0 = int_max(cbgxstart, band->x0);
+            prc->y0 = int_max(cbgystart, band->y0);
+            prc->x1 = int_min(cbgxend, band->x1);
+            prc->y1 = int_min(cbgyend, band->y1);
+            
+            tlcblkxstart = int_floordivpow2(prc->x0, cblkwidthexpn) << cblkwidthexpn;
+            tlcblkystart = int_floordivpow2(prc->y0, cblkheightexpn) << cblkheightexpn;
+            brcblkxend = int_ceildivpow2(prc->x1, cblkwidthexpn) << cblkwidthexpn;
+            brcblkyend = int_ceildivpow2(prc->y1, cblkheightexpn) << cblkheightexpn;
+            prc->cw = (brcblkxend - tlcblkxstart) >> cblkwidthexpn;
+            prc->ch = (brcblkyend - tlcblkystart) >> cblkheightexpn;
+            
+            prc->cblks = (opj_tcd_cblk_t *) opj_malloc(prc->cw * prc->ch * sizeof(opj_tcd_cblk_t));
+            
+            prc->incltree = tgt_create(prc->cw, prc->ch);
+            prc->imsbtree = tgt_create(prc->cw, prc->ch);
+            
+            for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+              int cblkxstart = tlcblkxstart + (cblkno % prc->cw) * (1 << cblkwidthexpn);
+              int cblkystart = tlcblkystart + (cblkno / prc->cw) * (1 << cblkheightexpn);
+              int cblkxend = cblkxstart + (1 << cblkwidthexpn);
+              int cblkyend = cblkystart + (1 << cblkheightexpn);          
+              
+              /* code-block size (global) */
+              opj_tcd_cblk_t *cblk = &prc->cblks[cblkno];
+              cblk->x0 = int_max(cblkxstart, prc->x0);
+              cblk->y0 = int_max(cblkystart, prc->y0);
+              cblk->x1 = int_min(cblkxend, prc->x1);
+              cblk->y1 = int_min(cblkyend, prc->y1);
+            }
+          } /* precno */
+        } /* bandno */
+      } /* resno */
+    } /* compno */
+  } /* i = 0..cp->tileno_size */
+
+  /* tcd_dump(stdout, tcd, &tcd->tcd_image); */
+
+  /* 
+  Allocate place to store the decoded data = final image
+  Place limited by the tile really present in the codestream 
+  */
+  
+  for (i = 0; i < image->numcomps; i++) {
+    for (j = 0; j < cp->tileno_size; j++) {
+      tileno = cp->tileno[j];
+      x0 = j == 0 ? tcd->tcd_image->tiles[tileno].comps[i].x0 : int_min(x0,
+        (unsigned int) tcd->tcd_image->tiles[tileno].comps[i].x0);
+      y0 = j == 0 ? tcd->tcd_image->tiles[tileno].comps[i].y0 : int_min(y0,
+        (unsigned int) tcd->tcd_image->tiles[tileno].comps[i].y0);
+      x1 = j == 0 ? tcd->tcd_image->tiles[tileno].comps[i].x1 : int_max(x1,
+        (unsigned int) tcd->tcd_image->tiles[tileno].comps[i].x1);
+      y1 = j == 0 ? tcd->tcd_image->tiles[tileno].comps[i].y1 : int_max(y1, 
+        (unsigned int) tcd->tcd_image->tiles[tileno].comps[i].y1);
+    }
+    
+    w = x1 - x0;
+    h = y1 - y0;
+    
+    image->comps[i].data = (int *) opj_malloc(w * h * sizeof(int));
+    image->comps[i].w = w;
+    image->comps[i].h = h;
+    image->comps[i].x0 = x0;
+    image->comps[i].y0 = y0;
+  }
+}
+
+void tcd_makelayer_fixed(opj_tcd_t *tcd, int layno, int final) {
+  int compno, resno, bandno, precno, cblkno;
+  int value;      /*, matrice[tcd_tcp->numlayers][tcd_tile->comps[0].numresolutions][3]; */
+  int matrice[10][10][3];
+  int i, j, k;
+
+  opj_cp_t *cp = tcd->cp;
+  opj_tcd_tile_t *tcd_tile = tcd->tcd_tile;
+  opj_tcp_t *tcd_tcp = tcd->tcp;
+
+  /*matrice=(int*)opj_malloc(tcd_tcp->numlayers*tcd_tile->comps[0].numresolutions*3*sizeof(int)); */
+  
+  for (compno = 0; compno < tcd_tile->numcomps; compno++) {
+    opj_tcd_tilecomp_t *tilec = &tcd_tile->comps[compno];
+    for (i = 0; i < tcd_tcp->numlayers; i++) {
+      for (j = 0; j < tilec->numresolutions; j++) {
+        for (k = 0; k < 3; k++) {
+          matrice[i][j][k] =
+            (int) (cp->matrice[i * tilec->numresolutions * 3 + j * 3 + k] 
+            * (float) (tcd->image->comps[compno].prec / 16.0));
+        }
+      }
+    }
+        
+    for (resno = 0; resno < tilec->numresolutions; resno++) {
+      opj_tcd_resolution_t *res = &tilec->resolutions[resno];
+      for (bandno = 0; bandno < res->numbands; bandno++) {
+        opj_tcd_band_t *band = &res->bands[bandno];
+        for (precno = 0; precno < res->pw * res->ph; precno++) {
+          opj_tcd_precinct_t *prc = &band->precincts[precno];
+          for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+            opj_tcd_cblk_t *cblk = &prc->cblks[cblkno];
+            opj_tcd_layer_t *layer = &cblk->layers[layno];
+            int n;
+            int imsb = tcd->image->comps[compno].prec - cblk->numbps;  /* number of bit-plan equal to zero */
+            /* Correction of the matrix of coefficient to include the IMSB information */
+            if (layno == 0) {
+              value = matrice[layno][resno][bandno];
+              if (imsb >= value) {
+                value = 0;
+              } else {
+                value -= imsb;
+              }
+            } else {
+              value =  matrice[layno][resno][bandno] -  matrice[layno - 1][resno][bandno];
+              if (imsb >= matrice[layno - 1][resno][bandno]) {
+                value -= (imsb - matrice[layno - 1][resno][bandno]);
+                if (value < 0) {
+                  value = 0;
+                }
+              }
+            }
+            
+            if (layno == 0) {
+              cblk->numpassesinlayers = 0;
+            }
+            
+            n = cblk->numpassesinlayers;
+            if (cblk->numpassesinlayers == 0) {
+              if (value != 0) {
+                n = 3 * value - 2 + cblk->numpassesinlayers;
+              } else {
+                n = cblk->numpassesinlayers;
+              }
+            } else {
+              n = 3 * value + cblk->numpassesinlayers;
+            }
+            
+            layer->numpasses = n - cblk->numpassesinlayers;
+            
+            if (!layer->numpasses)
+              continue;
+            
+            if (cblk->numpassesinlayers == 0) {
+              layer->len = cblk->passes[n - 1].rate;
+              layer->data = cblk->data;
+            } else {
+              layer->len = cblk->passes[n - 1].rate - cblk->passes[cblk->numpassesinlayers - 1].rate;
+              layer->data = cblk->data + cblk->passes[cblk->numpassesinlayers - 1].rate;
+            }
+            if (final)
+              cblk->numpassesinlayers = n;
+          }
+        }
+      }
+    }
+  }
+}
+
+void tcd_rateallocate_fixed(opj_tcd_t *tcd) {
+  int layno;
+  for (layno = 0; layno < tcd->tcp->numlayers; layno++) {
+    tcd_makelayer_fixed(tcd, layno, 1);
+  }
+}
+
+void tcd_makelayer(opj_tcd_t *tcd, int layno, double thresh, int final) {
+  int compno, resno, bandno, precno, cblkno, passno;
+  
+  opj_tcd_tile_t *tcd_tile = tcd->tcd_tile;
+
+  tcd_tile->distolayer[layno] = 0;  /* fixed_quality */
+  
+  for (compno = 0; compno < tcd_tile->numcomps; compno++) {
+    opj_tcd_tilecomp_t *tilec = &tcd_tile->comps[compno];
+    for (resno = 0; resno < tilec->numresolutions; resno++) {
+      opj_tcd_resolution_t *res = &tilec->resolutions[resno];
+      for (bandno = 0; bandno < res->numbands; bandno++) {
+        opj_tcd_band_t *band = &res->bands[bandno];
+        for (precno = 0; precno < res->pw * res->ph; precno++) {
+          opj_tcd_precinct_t *prc = &band->precincts[precno];
+          for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+            opj_tcd_cblk_t *cblk = &prc->cblks[cblkno];
+            opj_tcd_layer_t *layer = &cblk->layers[layno];
+            
+            int n;
+            if (layno == 0) {
+              cblk->numpassesinlayers = 0;
+            }
+            n = cblk->numpassesinlayers;
+            for (passno = cblk->numpassesinlayers; passno < cblk->totalpasses; passno++) {
+              int dr;
+              double dd;
+              opj_tcd_pass_t *pass = &cblk->passes[passno];
+              if (n == 0) {
+                dr = pass->rate;
+                dd = pass->distortiondec;
+              } else {
+                dr = pass->rate - cblk->passes[n - 1].rate;
+                dd = pass->distortiondec - cblk->passes[n - 1].distortiondec;
+              }
+              if (!dr) {
+                if (dd != 0)
+                  n = passno + 1;
+                continue;
+              }
+              if (dd / dr >= thresh)
+                n = passno + 1;
+            }
+            layer->numpasses = n - cblk->numpassesinlayers;
+            
+            if (!layer->numpasses) {
+              layer->disto = 0;
+              continue;
+            }
+            if (cblk->numpassesinlayers == 0) {
+              layer->len = cblk->passes[n - 1].rate;
+              layer->data = cblk->data;
+              layer->disto = cblk->passes[n - 1].distortiondec;
+            } else {
+              layer->len = cblk->passes[n - 1].rate -  cblk->passes[cblk->numpassesinlayers - 1].rate;
+              layer->data = cblk->data + cblk->passes[cblk->numpassesinlayers - 1].rate;
+              layer->disto = cblk->passes[n - 1].distortiondec - cblk->passes[cblk->numpassesinlayers - 1].distortiondec;
+            }
+            
+            tcd_tile->distolayer[layno] += layer->disto;  /* fixed_quality */
+            
+            if (final)
+              cblk->numpassesinlayers = n;
+          }
+        }
+      }
+    }
+  }
+}
+
+bool tcd_rateallocate(opj_tcd_t *tcd, unsigned char *dest, int len, opj_image_info_t * image_info) {
+  int compno, resno, bandno, precno, cblkno, passno, layno;
+  double min, max;
+  double cumdisto[100];  /* fixed_quality */
+  const double K = 1;    /* 1.1; // fixed_quality */
+  double maxSE = 0;
+
+  opj_cp_t *cp = tcd->cp;
+  opj_tcd_tile_t *tcd_tile = tcd->tcd_tile;
+  opj_tcp_t *tcd_tcp = tcd->tcp;
+
+  min = DBL_MAX;
+  max = 0;
+  
+  tcd_tile->nbpix = 0;    /* fixed_quality */
+  
+  for (compno = 0; compno < tcd_tile->numcomps; compno++) {
+    opj_tcd_tilecomp_t *tilec = &tcd_tile->comps[compno];
+    tilec->nbpix = 0;
+    for (resno = 0; resno < tilec->numresolutions; resno++) {
+      opj_tcd_resolution_t *res = &tilec->resolutions[resno];
+      for (bandno = 0; bandno < res->numbands; bandno++) {
+        opj_tcd_band_t *band = &res->bands[bandno];
+        for (precno = 0; precno < res->pw * res->ph; precno++) {
+          opj_tcd_precinct_t *prc = &band->precincts[precno];
+          for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+            opj_tcd_cblk_t *cblk = &prc->cblks[cblkno];
+            for (passno = 0; passno < cblk->totalpasses; passno++) {
+              opj_tcd_pass_t *pass = &cblk->passes[passno];
+              int dr;
+              double dd, rdslope;
+              if (passno == 0) {
+                dr = pass->rate;
+                dd = pass->distortiondec;
+              } else {
+                dr = pass->rate - cblk->passes[passno - 1].rate;
+                dd = pass->distortiondec - cblk->passes[passno - 1].distortiondec;
+              }
+              if (dr == 0) {
+                continue;
+              }
+              rdslope = dd / dr;
+              if (rdslope < min) {
+                min = rdslope;
+              }
+              if (rdslope > max) {
+                max = rdslope;
+              }
+            } /* passno */
+            
+            /* fixed_quality */
+            tcd_tile->nbpix += ((cblk->x1 - cblk->x0) * (cblk->y1 - cblk->y0));
+            tilec->nbpix += ((cblk->x1 - cblk->x0) * (cblk->y1 - cblk->y0));
+          } /* cbklno */
+        } /* precno */
+      } /* bandno */
+    } /* resno */
+    
+    maxSE += (((double)(1 << tcd->image->comps[compno].prec) - 1.0) 
+      * ((double)(1 << tcd->image->comps[compno].prec) -1.0)) 
+      * ((double)(tilec->nbpix));
+  } /* compno */
+  
+  /* add antonin index */
+  if(image_info && image_info->index_on) {
+    opj_tile_info_t *info_TL = &image_info->tile[tcd->tcd_tileno];
+    info_TL->nbpix = tcd_tile->nbpix;
+    info_TL->distotile = tcd_tile->distotile;
+    info_TL->thresh = (double *) opj_malloc(tcd_tcp->numlayers * sizeof(double));
+  }
+  /* dda */
+  
+  for (layno = 0; layno < tcd_tcp->numlayers; layno++) {
+    double lo = min;
+    double hi = max;
+    int success = 0;
+    int maxlen = tcd_tcp->rates[layno] ? int_min(tcd_tcp->rates[layno], len) : len;
+    double goodthresh = 0;
+    int i;
+    double distotarget;    /* fixed_quality */
+    
+    /* fixed_quality */
+    distotarget = tcd_tile->distotile - ((K * maxSE) / pow((float)10, tcd_tcp->distoratio[layno] / 10));
+        
+    if ((tcd_tcp->rates[layno]) || (cp->disto_alloc==0)) {
+      opj_t2_t *t2 = t2_create(tcd->cinfo, tcd->image, cp);
+
+      for (i = 0; i < 32; i++) {
+        double thresh = (lo + hi) / 2;
+        int l = 0;
+        double distoachieved = 0;  /* fixed_quality */
+        
+        tcd_makelayer(tcd, layno, thresh, 0);
+        
+        if (cp->fixed_quality) {  /* fixed_quality */
+          distoachieved =  layno == 0 ? 
+            tcd_tile->distolayer[0]  : cumdisto[layno - 1] + tcd_tile->distolayer[layno];
+          if (distoachieved < distotarget) {
+            hi = thresh;
+            continue;
+          }
+          lo = thresh;
+        } else {
+          l = t2_encode_packets(t2, tcd->tcd_tileno, tcd_tile, layno + 1, dest, maxlen, image_info);
+          /* opj_event_msg(tcd->cinfo, EVT_INFO, "rate alloc: len=%d, max=%d\n", l, maxlen); */
+          if (l == -999) {
+            lo = thresh;
+            continue;
+          }
+          hi = thresh;
+        }
+        
+        success = 1;
+        goodthresh = thresh;
+      }
+      t2_destroy(t2);
+    } else {
+      success = 1;
+      goodthresh = min;
+    }
+    
+    if (!success) {
+      return false;
+    }
+    
+    if(image_info && image_info->index_on) {  /* Threshold for Marcela Index */
+      image_info->tile[tcd->tcd_tileno].thresh[layno] = goodthresh;
+    }
+    tcd_makelayer(tcd, layno, goodthresh, 1);
+        
+    /* fixed_quality */
+    cumdisto[layno] = layno == 0 ? tcd_tile->distolayer[0] : cumdisto[layno - 1] + tcd_tile->distolayer[layno];  
+  }
+
+  return true;
+}
+
+int tcd_encode_tile(opj_tcd_t *tcd, int tileno, unsigned char *dest, int len, opj_image_info_t * image_info) {
+  int compno;
+  int l, i, npck = 0;
+  double encoding_time;
+  opj_tcd_tile_t *tile = NULL;
+  opj_tcp_t *tcd_tcp = NULL;
+  opj_cp_t *cp = NULL;
+
+  opj_tcp_t *tcp = &tcd->cp->tcps[0];
+  opj_tccp_t *tccp = &tcp->tccps[0];
+  opj_image_t *image = tcd->image;
+  
+  opj_t1_t *t1 = NULL;    /* T1 component */
+  opj_t2_t *t2 = NULL;    /* T2 component */
+
+  tcd->tcd_tileno = tileno;
+  tcd->tcd_tile = tcd->tcd_image->tiles;
+  tcd->tcp = &tcd->cp->tcps[tileno];
+
+  tile = tcd->tcd_tile;
+  tcd_tcp = tcd->tcp;
+  cp = tcd->cp;
+
+  /* INDEX >> "Precinct_nb_X et Precinct_nb_Y" */
+  if(image_info && image_info->index_on) {
+    opj_tcd_tilecomp_t *tilec_idx = &tile->comps[0];  /* based on component 0 */
+    for (i = 0; i < tilec_idx->numresolutions; i++) {
+      opj_tcd_resolution_t *res_idx = &tilec_idx->resolutions[i];
+
+      image_info->tile[tileno].pw[i] = res_idx->pw;
+      image_info->tile[tileno].ph[i] = res_idx->ph;
+
+      npck += res_idx->pw * res_idx->ph;
+
+      image_info->tile[tileno].pdx[i] = tccp->prcw[i];
+      image_info->tile[tileno].pdy[i] = tccp->prch[i];
+    }
+    image_info->tile[tileno].packet = (opj_packet_info_t *) opj_malloc(image_info->comp * image_info->layer * npck * sizeof(opj_packet_info_t));
+  }
+  /* << INDEX */
+  
+  /*---------------TILE-------------------*/
+  encoding_time = opj_clock();  /* time needed to encode a tile */
+  
+  for (compno = 0; compno < tile->numcomps; compno++) {
+    int x, y;
+
+    int adjust = image->comps[compno].sgnd ? 0 : 1 << (image->comps[compno].prec - 1);
+    int offset_x = int_ceildiv(image->x0, image->comps[compno].dx);
+    int offset_y = int_ceildiv(image->y0, image->comps[compno].dy);
+    
+    opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
+    int tw = tilec->x1 - tilec->x0;
+    int w = int_ceildiv(image->x1 - image->x0, image->comps[compno].dx);
+
+    /* extract tile data */
+
+    if (tcd_tcp->tccps[compno].qmfbid == 1) {
+      for (y = tilec->y0; y < tilec->y1; y++) {
+        /* start of the src tile scanline */
+        int *data = &image->comps[compno].data[(tilec->x0 - offset_x) + (y - offset_y) * w];
+        /* start of the dst tile scanline */
+        int *tile_data = &tilec->data[(y - tilec->y0) * tw];
+        for (x = tilec->x0; x < tilec->x1; x++) {
+          *tile_data++ = *data++ - adjust;
+        }
+      }
+    } else if (tcd_tcp->tccps[compno].qmfbid == 0) {
+      for (y = tilec->y0; y < tilec->y1; y++) {
+        /* start of the src tile scanline */
+        int *data = &image->comps[compno].data[(tilec->x0 - offset_x) + (y - offset_y) * w];
+        /* start of the dst tile scanline */
+        int *tile_data = &tilec->data[(y - tilec->y0) * tw];
+        for (x = tilec->x0; x < tilec->x1; x++) {
+          *tile_data++ = (*data++ - adjust) << 13;
+        }
+      }
+    }
+  }
+  
+  /*----------------MCT-------------------*/
+  if (tcd_tcp->mct) {
+    int samples = (tile->comps[0].x1 - tile->comps[0].x0) * (tile->comps[0].y1 - tile->comps[0].y0);
+    if (tcd_tcp->tccps[0].qmfbid == 0) {
+      mct_encode_real(tile->comps[0].data, tile->comps[1].data, tile->comps[2].data, samples);
+    } else {
+      mct_encode(tile->comps[0].data, tile->comps[1].data, tile->comps[2].data, samples);
+    }
+  }
+  
+  /*----------------DWT---------------------*/
+
+  for (compno = 0; compno < tile->numcomps; compno++) {
+    opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
+    if (tcd_tcp->tccps[compno].qmfbid == 1) {
+      dwt_encode(tilec);
+    } else if (tcd_tcp->tccps[compno].qmfbid == 0) {
+      dwt_encode_real(tilec);
+    }
+  }
+
+  /*------------------TIER1-----------------*/
+  t1 = t1_create(tcd->cinfo);
+  t1_encode_cblks(t1, tile, tcd_tcp);
+  t1_destroy(t1);
+  
+  /*-----------RATE-ALLOCATE------------------*/
+
+  /* INDEX */
+  if(image_info) {
+    image_info->index_write = 0;
+  }
+  if (cp->disto_alloc || cp->fixed_quality) {  /* fixed_quality */
+    /* Normal Rate/distortion allocation */
+    tcd_rateallocate(tcd, dest, len, image_info);
+  } else {
+    /* Fixed layer allocation */
+    tcd_rateallocate_fixed(tcd);
+  }
+  
+  /*--------------TIER2------------------*/
+
+  /* INDEX */
+  if(image_info) {
+    image_info->index_write = 1;
+  }
+
+  t2 = t2_create(tcd->cinfo, image, cp);
+  l = t2_encode_packets(t2, tileno, tile, tcd_tcp->numlayers, dest, len, image_info);
+  t2_destroy(t2);
+  
+  /*---------------CLEAN-------------------*/
+
+  encoding_time = opj_clock() - encoding_time;
+  opj_event_msg(tcd->cinfo, EVT_INFO, "- tile encoded in %f s\n", encoding_time);
+  
+  /* cleaning memory */
+  for (compno = 0; compno < tile->numcomps; compno++) {
+    tcd->tilec = &tile->comps[compno];
+    opj_free(tcd->tilec->data);
+  }
+  
+  return l;
+}
+
+bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno) {
+  int l;
+  int compno;
+  int eof = 0;
+  double tile_time, t1_time, dwt_time;
+  opj_tcd_tile_t *tile = NULL;
+
+  opj_t1_t *t1 = NULL;    /* T1 component */
+  opj_t2_t *t2 = NULL;    /* T2 component */
+  
+  tcd->tcd_tileno = tileno;
+  tcd->tcd_tile = &(tcd->tcd_image->tiles[tileno]);
+  tcd->tcp = &(tcd->cp->tcps[tileno]);
+  tile = tcd->tcd_tile;
+  
+  tile_time = opj_clock();  /* time needed to decode a tile */
+  opj_event_msg(tcd->cinfo, EVT_INFO, "tile %d of %d\n", tileno + 1, tcd->cp->tw * tcd->cp->th);
+  
+  /*--------------TIER2------------------*/
+  
+  t2 = t2_create(tcd->cinfo, tcd->image, tcd->cp);
+  l = t2_decode_packets(t2, src, len, tileno, tile);
+  t2_destroy(t2);
+
+  if (l == -999) {
+    eof = 1;
+    opj_event_msg(tcd->cinfo, EVT_ERROR, "tcd_decode: incomplete bistream\n");
+  }
+  
+  /*------------------TIER1-----------------*/
+  
+  t1_time = opj_clock();  /* time needed to decode a tile */
+  t1 = t1_create(tcd->cinfo);
+  t1_decode_cblks(t1, tile, tcd->tcp);
+  t1_destroy(t1);
+  t1_time = opj_clock() - t1_time;
+  opj_event_msg(tcd->cinfo, EVT_INFO, "- tiers-1 took %f s\n", t1_time);
+  
+  /*----------------DWT---------------------*/
+
+  dwt_time = opj_clock();  /* time needed to decode a tile */
+  for (compno = 0; compno < tile->numcomps; compno++) {
+    opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
+    if (tcd->cp->reduce != 0) {
+      tcd->image->comps[compno].resno_decoded =
+        tile->comps[compno].numresolutions - tcd->cp->reduce - 1;
+    }
+        
+    if (tcd->tcp->tccps[compno].qmfbid == 1) {
+      dwt_decode(tilec, tilec->numresolutions - 1 - tcd->image->comps[compno].resno_decoded);
+    } else {
+      dwt_decode_real(tilec, tilec->numresolutions - 1 - tcd->image->comps[compno].resno_decoded);
+    }
+
+    if (tile->comps[compno].numresolutions > 0) {
+      tcd->image->comps[compno].factor = tile->comps[compno].numresolutions - (tcd->image->comps[compno].resno_decoded + 1);
+    }
+  }
+  dwt_time = opj_clock() - dwt_time;
+  opj_event_msg(tcd->cinfo, EVT_INFO, "- dwt took %f s\n", dwt_time);
+  
+  /*----------------MCT-------------------*/
+  
+  if (tcd->tcp->mct) {
+    if (tcd->tcp->tccps[0].qmfbid == 1) {
+      mct_decode(tile->comps[0].data, tile->comps[1].data, tile->comps[2].data, 
+        (tile->comps[0].x1 - tile->comps[0].x0) * (tile->comps[0].y1 - tile->comps[0].y0));
+    } else {
+      mct_decode_real(tile->comps[0].data, tile->comps[1].data, tile->comps[2].data, 
+        (tile->comps[0].x1 - tile->comps[0].x0) * (tile->comps[0].y1 - tile->comps[0].y0));
+    }
+  }
+  
+  /*---------------TILE-------------------*/
+  
+  for (compno = 0; compno < tile->numcomps; compno++) {
+    opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
+    opj_tcd_resolution_t *res =  &tilec->resolutions[tcd->image->comps[compno].resno_decoded];
+    int adjust = tcd->image->comps[compno].sgnd ? 0 : 1 << (tcd->image->comps[compno].prec - 1);
+    int min = tcd->image->comps[compno].sgnd ? 
+      -(1 << (tcd->image->comps[compno].prec - 1)) : 0;
+    int max = tcd->image->comps[compno].sgnd ? 
+      (1 << (tcd->image->comps[compno].prec - 1)) - 1 : (1 << tcd->image->comps[compno].prec) - 1;
+    
+    int tw = tilec->x1 - tilec->x0;
+    int w = tcd->image->comps[compno].w;
+    
+    int i, j;
+    int offset_x = int_ceildivpow2(tcd->image->comps[compno].x0, tcd->image->comps[compno].factor);
+    int offset_y = int_ceildivpow2(tcd->image->comps[compno].y0, tcd->image->comps[compno].factor);
+    
+    for (j = res->y0; j < res->y1; j++) {
+      for (i = res->x0; i < res->x1; i++) {
+        int v;
+        float tmp = (float)((tilec->data[i - res->x0 + (j - res->y0) * tw]) / 8192.0);
+
+        if (tcd->tcp->tccps[compno].qmfbid == 1) {
+          v = tilec->data[i - res->x0 + (j - res->y0) * tw];
+        } else {
+          int tmp2 = ((int) (floor(fabs(tmp)))) + ((int) floor(fabs(tmp*2))%2);
+          v = ((tmp < 0) ? -tmp2:tmp2);
+        }
+        v += adjust;
+        
+        tcd->image->comps[compno].data[(i - offset_x) + (j - offset_y) * w] = int_clamp(v, min, max);
+      }
+    }
+  }
+  
+  tile_time = opj_clock() - tile_time;  /* time needed to decode a tile */
+  opj_event_msg(tcd->cinfo, EVT_INFO, "- tile decoded in %f s\n", tile_time);
+    
+  for (compno = 0; compno < tile->numcomps; compno++) {
+    opj_free(tcd->tcd_image->tiles[tileno].comps[compno].data);
+    tcd->tcd_image->tiles[tileno].comps[compno].data = NULL;
+  }
+  
+  if (eof) {
+    return false;
+  }
+  
+  return true;
+}
+
+void tcd_free_decode(opj_tcd_t *tcd) {
+  int tileno,compno,resno,bandno,precno;
+
+  opj_tcd_image_t *tcd_image = tcd->tcd_image;
+  
+  for (tileno = 0; tileno < tcd_image->tw * tcd_image->th; tileno++) {
+    opj_tcd_tile_t *tile = &tcd_image->tiles[tileno];
+    for (compno = 0; compno < tile->numcomps; compno++) {
+      opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
+      for (resno = 0; resno < tilec->numresolutions; resno++) {
+        opj_tcd_resolution_t *res = &tilec->resolutions[resno];
+        for (bandno = 0; bandno < res->numbands; bandno++) {
+          opj_tcd_band_t *band = &res->bands[bandno];
+          for (precno = 0; precno < res->ph * res->pw; precno++) {
+            opj_tcd_precinct_t *prec = &band->precincts[precno];
+            if (prec->cblks != NULL) opj_free(prec->cblks);
+            if (prec->imsbtree != NULL) tgt_destroy(prec->imsbtree);
+            if (prec->incltree != NULL) tgt_destroy(prec->incltree);
+          }
+          if (band->precincts != NULL) opj_free(band->precincts);
+        }
+      }
+      if (tilec->resolutions != NULL) opj_free(tilec->resolutions);
+    }
+    if (tile->comps != NULL) opj_free(tile->comps);
+  }
+
+  if (tcd_image->tiles != NULL) opj_free(tcd_image->tiles);
+}
+
diff --git a/Utilities/ITK/Utilities/openjpeg/tcd.h b/Utilities/ITK/Utilities/openjpeg/tcd.h
new file mode 100644
index 0000000000..dfa7b15a79
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/tcd.h
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __TCD_H
+#define __TCD_H
+/**
+@file tcd.h
+@brief Implementation of a tile coder/decoder (TCD)
+
+The functions in TCD.C have for goal to encode or decode each tile independently from
+each other. The functions in TCD.C are used by some function in J2K.C.
+*/
+
+/** @defgroup TCD TCD - Implementation of a tile coder/decoder */
+/*@{*/
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_tcd_seg {
+  int numpasses;
+  int len;
+  unsigned char *data;
+  int maxpasses;
+  int numnewpasses;
+  int newlen;
+} opj_tcd_seg_t;
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_tcd_pass {
+  int rate;
+  double distortiondec;
+  int term, len;
+} opj_tcd_pass_t;
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_tcd_layer {
+  int numpasses;    /* Number of passes in the layer */
+  int len;      /* len of information */
+  double disto;      /* add for index (Cfr. Marcela) */
+  unsigned char *data;    /* data */
+} opj_tcd_layer_t;
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_tcd_cblk {
+  int x0, y0, x1, y1;    /* dimension of the code-blocks : left upper corner (x0, y0) right low corner (x1,y1) */
+  int numbps;
+  int numlenbits;
+  int len;      /* length */
+  int numpasses;    /* number of pass already done for the code-blocks */
+  int numnewpasses;    /* number of pass added to the code-blocks */
+  int numsegs;      /* number of segments */
+  opj_tcd_seg_t segs[100];    /* segments informations */
+  unsigned char data[8192];  /* Data */
+  int numpassesinlayers;  /* number of passes in the layer */
+  opj_tcd_layer_t layers[100];  /* layer information */
+  int totalpasses;    /* total number of passes */
+  opj_tcd_pass_t passes[100];  /* information about the passes */
+} opj_tcd_cblk_t;
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_tcd_precinct {
+  int x0, y0, x1, y1;    /* dimension of the precinct : left upper corner (x0, y0) right low corner (x1,y1) */
+  int cw, ch;      /* number of precinct in width and heigth */
+  opj_tcd_cblk_t *cblks;    /* code-blocks informations */
+  opj_tgt_tree_t *incltree;    /* inclusion tree */
+  opj_tgt_tree_t *imsbtree;    /* IMSB tree */
+} opj_tcd_precinct_t;
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_tcd_band {
+  int x0, y0, x1, y1;    /* dimension of the subband : left upper corner (x0, y0) right low corner (x1,y1) */
+  int bandno;
+  opj_tcd_precinct_t *precincts;  /* precinct information */
+  int numbps;
+  float stepsize;
+} opj_tcd_band_t;
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_tcd_resolution {
+  int x0, y0, x1, y1;    /* dimension of the resolution level : left upper corner (x0, y0) right low corner (x1,y1) */
+  int pw, ph;
+  int numbands;      /* number sub-band for the resolution level */
+  opj_tcd_band_t bands[3];    /* subband information */
+} opj_tcd_resolution_t;
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_tcd_tilecomp {
+  int x0, y0, x1, y1;    /* dimension of component : left upper corner (x0, y0) right low corner (x1,y1) */
+  int numresolutions;    /* number of resolutions level */
+  opj_tcd_resolution_t *resolutions;  /* resolutions information */
+  int *data;      /* data of the component */
+  int nbpix;      /* add fixed_quality */
+} opj_tcd_tilecomp_t;
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_tcd_tile {
+  int x0, y0, x1, y1;    /* dimension of the tile : left upper corner (x0, y0) right low corner (x1,y1) */
+  int numcomps;      /* number of components in tile */
+  opj_tcd_tilecomp_t *comps;  /* Components information */
+  int nbpix;      /* add fixed_quality */
+  double distotile;    /* add fixed_quality */
+  double distolayer[100];  /* add fixed_quality */
+} opj_tcd_tile_t;
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_tcd_image {
+  int tw, th;      /* number of tiles in width and heigth */
+  opj_tcd_tile_t *tiles;    /* Tiles information */
+} opj_tcd_image_t;
+
+/**
+Tile coder/decoder
+*/
+typedef struct opj_tcd {
+  /** codec context */
+  opj_common_ptr cinfo;
+
+  /** info on each image tile */
+  opj_tcd_image_t *tcd_image;
+  /** image */
+  opj_image_t *image;
+  /** coding parameters */
+  opj_cp_t *cp;
+  /** pointer to the current encoded/decoded tile */
+  opj_tcd_tile_t *tcd_tile;
+  /** coding/decoding parameters common to all tiles */
+  opj_tcp_t *tcp;
+  /** current encoded/decoded tile */
+  int tcd_tileno;
+  /**@name working variables */
+  /*@{*/
+  opj_tcd_tile_t *tile;
+  opj_tcd_tilecomp_t *tilec;
+  opj_tcd_resolution_t *res;
+  opj_tcd_band_t *band;
+  opj_tcd_precinct_t *prc;
+  opj_tcd_cblk_t *cblk;
+  /*@}*/
+} opj_tcd_t;
+
+/** @name Exported functions */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+
+/**
+Dump the content of a tcd structure
+*/
+void tcd_dump(FILE *fd, opj_tcd_t *tcd, opj_tcd_image_t *img);
+/**
+Create a new TCD handle
+@param cinfo Codec context info
+@return Returns a new TCD handle if successful returns NULL otherwise
+*/
+opj_tcd_t* tcd_create(opj_common_ptr cinfo);
+/**
+Destroy a previously created TCD handle
+@param tcd TCD handle to destroy
+*/
+void tcd_destroy(opj_tcd_t *tcd);
+/**
+Initialize the tile coder (allocate the memory)
+@param tcd TCD handle
+@param image Raw image
+@param cp Coding parameters
+@param curtileno Number that identifies the tile that will be encoded
+*/
+void tcd_malloc_encode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, int curtileno);
+/**
+Free the memory allocated for encoding
+@param tcd TCD handle
+*/
+void tcd_free_encode(opj_tcd_t *tcd);
+/**
+Initialize the tile coder (reuses the memory allocated by tcd_malloc_encode)
+@param tcd TCD handle
+@param image Raw image
+@param cp Coding parameters
+@param curtileno Number that identifies the tile that will be encoded
+*/
+void tcd_init_encode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, int curtileno);
+/**
+Initialize the tile decoder
+@param tcd TCD handle
+@param image Raw image
+@param cp Coding parameters
+*/
+void tcd_malloc_decode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp);
+void tcd_makelayer_fixed(opj_tcd_t *tcd, int layno, int final);
+void tcd_rateallocate_fixed(opj_tcd_t *tcd);
+void tcd_makelayer(opj_tcd_t *tcd, int layno, double thresh, int final);
+bool tcd_rateallocate(opj_tcd_t *tcd, unsigned char *dest, int len, opj_image_info_t * image_info);
+/**
+Encode a tile from the raw image into a buffer
+@param tcd TCD handle
+@param tileno Number that identifies one of the tiles to be encoded
+@param dest Destination buffer
+@param len Length of destination buffer
+@param image_info Creation of index file
+@return 
+*/
+int tcd_encode_tile(opj_tcd_t *tcd, int tileno, unsigned char *dest, int len, opj_image_info_t * image_info);
+/**
+Decode a tile from a buffer into a raw image
+@param tcd TCD handle
+@param src Source buffer
+@param len Length of source buffer
+@param tileno Number that identifies one of the tiles to be decoded
+*/
+bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno);
+/**
+Free the memory allocated for decoding
+@param tcd TCD handle
+*/
+void tcd_free_decode(opj_tcd_t *tcd);
+
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __TCD_H */
diff --git a/Utilities/ITK/Utilities/openjpeg/tgt.c b/Utilities/ITK/Utilities/openjpeg/tgt.c
new file mode 100644
index 0000000000..aaaa09b962
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/tgt.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opj_includes.h"
+
+/* 
+==========================================================
+   Tag-tree coder interface
+==========================================================
+*/
+
+opj_tgt_tree_t *tgt_create(int numleafsh, int numleafsv) {
+  int nplh[32];
+  int nplv[32];
+  opj_tgt_node_t *node = NULL;
+  opj_tgt_node_t *parentnode = NULL;
+  opj_tgt_node_t *parentnode0 = NULL;
+  opj_tgt_tree_t *tree = NULL;
+  int i, j, k;
+  int numlvls;
+  int n;
+
+  tree = (opj_tgt_tree_t *) opj_malloc(sizeof(opj_tgt_tree_t));
+  if(!tree) return NULL;
+  tree->numleafsh = numleafsh;
+  tree->numleafsv = numleafsv;
+
+  numlvls = 0;
+  nplh[0] = numleafsh;
+  nplv[0] = numleafsv;
+  tree->numnodes = 0;
+  do {
+    n = nplh[numlvls] * nplv[numlvls];
+    nplh[numlvls + 1] = (nplh[numlvls] + 1) / 2;
+    nplv[numlvls + 1] = (nplv[numlvls] + 1) / 2;
+    tree->numnodes += n;
+    ++numlvls;
+  } while (n > 1);
+  
+  /* ADD */
+  if (tree->numnodes == 0) {
+    opj_free(tree);
+    return NULL;
+  }
+
+  tree->nodes = (opj_tgt_node_t *) opj_malloc(tree->numnodes * sizeof(opj_tgt_node_t));
+  if(!tree->nodes) {
+    opj_free(tree);
+    return NULL;
+  }
+
+  node = tree->nodes;
+  parentnode = &tree->nodes[tree->numleafsh * tree->numleafsv];
+  parentnode0 = parentnode;
+  
+  for (i = 0; i < numlvls - 1; ++i) {
+    for (j = 0; j < nplv[i]; ++j) {
+      k = nplh[i];
+      while (--k >= 0) {
+        node->parent = parentnode;
+        ++node;
+        if (--k >= 0) {
+          node->parent = parentnode;
+          ++node;
+        }
+        ++parentnode;
+      }
+      if ((j & 1) || j == nplv[i] - 1) {
+        parentnode0 = parentnode;
+      } else {
+        parentnode = parentnode0;
+        parentnode0 += nplh[i];
+      }
+    }
+  }
+  node->parent = 0;
+  
+  tgt_reset(tree);
+  
+  return tree;
+}
+
+void tgt_destroy(opj_tgt_tree_t *tree) {
+  opj_free(tree->nodes);
+  opj_free(tree);
+}
+
+void tgt_reset(opj_tgt_tree_t *tree) {
+  int i;
+
+  if (NULL == tree)
+    return;
+  
+  for (i = 0; i < tree->numnodes; i++) {
+    tree->nodes[i].value = 999;
+    tree->nodes[i].low = 0;
+    tree->nodes[i].known = 0;
+  }
+}
+
+void tgt_setvalue(opj_tgt_tree_t *tree, int leafno, int value) {
+  opj_tgt_node_t *node;
+  node = &tree->nodes[leafno];
+  while (node && node->value > value) {
+    node->value = value;
+    node = node->parent;
+  }
+}
+
+void tgt_encode(opj_bio_t *bio, opj_tgt_tree_t *tree, int leafno, int threshold) {
+  opj_tgt_node_t *stk[31];
+  opj_tgt_node_t **stkptr;
+  opj_tgt_node_t *node;
+  int low;
+
+  stkptr = stk;
+  node = &tree->nodes[leafno];
+  while (node->parent) {
+    *stkptr++ = node;
+    node = node->parent;
+  }
+  
+  low = 0;
+  for (;;) {
+    if (low > node->low) {
+      node->low = low;
+    } else {
+      low = node->low;
+    }
+    
+    while (low < threshold) {
+      if (low >= node->value) {
+        if (!node->known) {
+          bio_write(bio, 1, 1);
+          node->known = 1;
+        }
+        break;
+      }
+      bio_write(bio, 0, 1);
+      ++low;
+    }
+    
+    node->low = low;
+    if (stkptr == stk)
+      break;
+    node = *--stkptr;
+  }
+}
+
+int tgt_decode(opj_bio_t *bio, opj_tgt_tree_t *tree, int leafno, int threshold) {
+  opj_tgt_node_t *stk[31];
+  opj_tgt_node_t **stkptr;
+  opj_tgt_node_t *node;
+  int low;
+
+  stkptr = stk;
+  node = &tree->nodes[leafno];
+  while (node->parent) {
+    *stkptr++ = node;
+    node = node->parent;
+  }
+  
+  low = 0;
+  for (;;) {
+    if (low > node->low) {
+      node->low = low;
+    } else {
+      low = node->low;
+    }
+    while (low < threshold && low < node->value) {
+      if (bio_read(bio, 1)) {
+        node->value = low;
+      } else {
+        ++low;
+      }
+    }
+    node->low = low;
+    if (stkptr == stk) {
+      break;
+    }
+    node = *--stkptr;
+  }
+  
+  return (node->value < threshold) ? 1 : 0;
+}
diff --git a/Utilities/ITK/Utilities/openjpeg/tgt.h b/Utilities/ITK/Utilities/openjpeg/tgt.h
new file mode 100644
index 0000000000..481f678adb
--- /dev/null
+++ b/Utilities/ITK/Utilities/openjpeg/tgt.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TGT_H
+#define __TGT_H
+/**
+@file tgt.h
+@brief Implementation of a tag-tree coder (TGT)
+
+The functions in TGT.C have for goal to realize a tag-tree coder. The functions in TGT.C
+are used by some function in T2.C.
+*/
+
+/** @defgroup TGT TGT - Implementation of a tag-tree coder */
+/*@{*/
+
+/**
+Tag node
+*/
+typedef struct opj_tgt_node {
+  struct opj_tgt_node *parent;
+  int value;
+  int low;
+  int known;
+} opj_tgt_node_t;
+
+/**
+Tag tree
+*/
+typedef struct opj_tgt_tree {
+  int numleafsh;
+  int numleafsv;
+  int numnodes;
+  opj_tgt_node_t *nodes;
+} opj_tgt_tree_t;
+
+/** @name Exported functions */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+/**
+Create a tag-tree
+@param numleafsh Width of the array of leafs of the tree
+@param numleafsv Height of the array of leafs of the tree
+@return Returns a new tag-tree if successful, returns NULL otherwise
+*/
+opj_tgt_tree_t *tgt_create(int numleafsh, int numleafsv);
+/**
+Destroy a tag-tree, liberating memory
+@param tree Tag-tree to destroy
+*/
+void tgt_destroy(opj_tgt_tree_t *tree);
+/**
+Reset a tag-tree (set all leaves to 0)
+@param tree Tag-tree to reset
+*/
+void tgt_reset(opj_tgt_tree_t *tree);
+/**
+Set the value of a leaf of a tag-tree
+@param tree Tag-tree to modify
+@param leafno Number that identifies the leaf to modify
+@param value New value of the leaf
+*/
+void tgt_setvalue(opj_tgt_tree_t *tree, int leafno, int value);
+/**
+Encode the value of a leaf of the tag-tree up to a given threshold
+@param bio Pointer to a BIO handle
+@param tree Tag-tree to modify
+@param leafno Number that identifies the leaf to encode
+@param threshold Threshold to use when encoding value of the leaf
+*/
+void tgt_encode(opj_bio_t *bio, opj_tgt_tree_t *tree, int leafno, int threshold);
+/**
+Decode the value of a leaf of the tag-tree up to a given threshold
+@param bio Pointer to a BIO handle
+@param tree Tag-tree to decode
+@param leafno Number that identifies the leaf to decode
+@param threshold Threshold to use when decoding value of the leaf
+@return Returns 1 if the node's value < threshold, returns 0 otherwise
+*/
+int tgt_decode(opj_bio_t *bio, opj_tgt_tree_t *tree, int leafno, int threshold);
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __TGT_H */
diff --git a/Utilities/ITK/Utilities/png/.NoDartCoverage b/Utilities/ITK/Utilities/png/.NoDartCoverage
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/Utilities/ITK/Utilities/png/CMakeLists.txt b/Utilities/ITK/Utilities/png/CMakeLists.txt
new file mode 100644
index 0000000000..2d6de4354f
--- /dev/null
+++ b/Utilities/ITK/Utilities/png/CMakeLists.txt
@@ -0,0 +1,38 @@
+PROJECT(ITKPNG)
+INCLUDE_REGULAR_EXPRESSION("^(itk_png_mangle|png).*$")
+
+INCLUDE_DIRECTORIES(BEFORE ${ITKPNG_SOURCE_DIR})
+INCLUDE_DIRECTORIES(BEFORE ${ITKPNG_BINARY_DIR})
+
+# source files for png
+SET(PNG_SRCS
+pngget.c    pngrio.c    pngwrite.c
+png.c       pngmem.c    pngrtran.c  pngtrans.c  pngwtran.c
+pngerror.c  pngpread.c  pngrutil.c  pngvcrd.c   pngwutil.c
+pnggccrd.c  pngread.c   pngset.c   pngwio.c
+)
+
+IF(WIN32)
+  IF(BUILD_SHARED_LIBS)
+    ADD_DEFINITIONS(-DPNG_BUILD_DLL)
+    SET(PNG_NO_MODULEDEF 1)
+  ELSE(BUILD_SHARED_LIBS)
+    SET(PNG_STATIC 1)
+  ENDIF(BUILD_SHARED_LIBS)
+ENDIF(WIN32)
+
+CONFIGURE_FILE(${ITKPNG_SOURCE_DIR}/.NoDartCoverage
+               ${ITKPNG_BINARY_DIR}/.NoDartCoverage)
+CONFIGURE_FILE(${ITKPNG_SOURCE_DIR}/pngDllConfig.h.in
+               ${ITKPNG_BINARY_DIR}/pngDllConfig.h)
+
+ADD_LIBRARY(itkpng ${PNG_SRCS})
+
+
+IF(UNIX)
+TARGET_LINK_LIBRARIES(itkpng ${ITK_ZLIB_LIBRARIES} -lm)
+ELSE(UNIX)
+TARGET_LINK_LIBRARIES(itkpng ${ITK_ZLIB_LIBRARIES})
+ENDIF(UNIX)
+
+INSTALL_TARGETS(/lib/InsightToolkit itkpng)
diff --git a/Utilities/ITK/Utilities/png/itk_png_mangle.h b/Utilities/ITK/Utilities/png/itk_png_mangle.h
new file mode 100644
index 0000000000..cbaa4385c9
--- /dev/null
+++ b/Utilities/ITK/Utilities/png/itk_png_mangle.h
@@ -0,0 +1,349 @@
+#ifndef itk_png_mangle_h
+#define itk_png_mangle_h
+
+/*
+
+This header file mangles all symbols exported from the png library.
+It is included in all files while building the png library.  Due to
+namespace pollution, no png headers should be included in .h files in
+ITK.
+
+The following command was used to obtain the symbol list:
+
+nm libitkpng.a |grep " T "
+
+*/
+
+#define png_access_version_number itk_png_access_version_number
+#define png_build_gamma_table itk_png_build_gamma_table
+#define png_build_grayscale_palette itk_png_build_grayscale_palette
+#define png_calculate_crc itk_png_calculate_crc
+#define png_check_chunk_name itk_png_check_chunk_name
+#define png_check_keyword itk_png_check_keyword
+#define png_check_sig itk_png_check_sig
+#define png_chunk_error itk_png_chunk_error
+#define png_chunk_warning itk_png_chunk_warning
+#define png_combine_row itk_png_combine_row
+#define png_convert_from_struct_tm itk_png_convert_from_struct_tm
+#define png_convert_from_time_t itk_png_convert_from_time_t
+#define png_convert_to_rfc1123 itk_png_convert_to_rfc1123
+#define png_crc_error itk_png_crc_error
+#define png_crc_finish itk_png_crc_finish
+#define png_crc_read itk_png_crc_read
+#define png_create_info_struct itk_png_create_info_struct
+#define png_create_read_struct itk_png_create_read_struct
+#define png_create_struct itk_png_create_struct
+#define png_create_write_struct itk_png_create_write_struct
+#define png_data_freer itk_png_data_freer
+#define png_decompress_chunk itk_png_decompress_chunk
+#define png_destroy_info_struct itk_png_destroy_info_struct
+#define png_destroy_read_struct itk_png_destroy_read_struct
+#define png_destroy_struct itk_png_destroy_struct
+#define png_destroy_write_struct itk_png_destroy_write_struct
+#define png_do_background itk_png_do_background
+#define png_do_bgr itk_png_do_bgr
+#define png_do_chop itk_png_do_chop
+#define png_do_dither itk_png_do_dither
+#define png_do_expand itk_png_do_expand
+#define png_do_expand_palette itk_png_do_expand_palette
+#define png_do_gamma itk_png_do_gamma
+#define png_do_gray_to_rgb itk_png_do_gray_to_rgb
+#define png_do_invert itk_png_do_invert
+#define png_do_pack itk_png_do_pack
+#define png_do_packswap itk_png_do_packswap
+#define png_do_read_filler itk_png_do_read_filler
+#define png_do_read_interlace itk_png_do_read_interlace
+#define png_do_read_invert_alpha itk_png_do_read_invert_alpha
+#define png_do_read_swap_alpha itk_png_do_read_swap_alpha
+#define png_do_read_transformations itk_png_do_read_transformations
+#define png_do_rgb_to_gray itk_png_do_rgb_to_gray
+#define png_do_shift itk_png_do_shift
+#define png_do_strip_filler itk_png_do_strip_filler
+#define png_do_swap itk_png_do_swap
+#define png_do_unpack itk_png_do_unpack
+#define png_do_unshift itk_png_do_unshift
+#define png_do_write_interlace itk_png_do_write_interlace
+#define png_do_write_invert_alpha itk_png_do_write_invert_alpha
+#define png_do_write_swap_alpha itk_png_do_write_swap_alpha
+#define png_do_write_transformations itk_png_do_write_transformations
+#define png_error itk_png_error
+#define png_flush itk_png_flush
+#define png_free itk_png_free
+#define png_free_data itk_png_free_data
+#define png_get_IHDR itk_png_get_IHDR
+#define png_get_PLTE itk_png_get_PLTE
+#define png_get_bKGD itk_png_get_bKGD
+#define png_get_bit_depth itk_png_get_bit_depth
+#define png_get_cHRM itk_png_get_cHRM
+#define png_get_cHRM_fixed itk_png_get_cHRM_fixed
+#define png_get_channels itk_png_get_channels
+#define png_get_color_type itk_png_get_color_type
+#define png_get_compression_buffer_size itk_png_get_compression_buffer_size
+#define png_get_compression_type itk_png_get_compression_type
+#define png_get_copyright itk_png_get_copyright
+#define png_get_error_ptr itk_png_get_error_ptr
+#define png_get_filter_type itk_png_get_filter_type
+#define png_get_gAMA itk_png_get_gAMA
+#define png_get_gAMA_fixed itk_png_get_gAMA_fixed
+#define png_get_hIST itk_png_get_hIST
+#define png_get_header_ver itk_png_get_header_ver
+#define png_get_header_version itk_png_get_header_version
+#define png_get_iCCP itk_png_get_iCCP
+#define png_get_image_height itk_png_get_image_height
+#define png_get_image_width itk_png_get_image_width
+#define png_get_int_32 itk_png_get_int_32
+#define png_get_interlace_type itk_png_get_interlace_type
+#define png_get_io_ptr itk_png_get_io_ptr
+#define png_get_libpng_ver itk_png_get_libpng_ver
+#define png_get_oFFs itk_png_get_oFFs
+#define png_get_pCAL itk_png_get_pCAL
+#define png_get_pHYs itk_png_get_pHYs
+#define png_get_pixel_aspect_ratio itk_png_get_pixel_aspect_ratio
+#define png_get_pixels_per_meter itk_png_get_pixels_per_meter
+#define png_get_progressive_ptr itk_png_get_progressive_ptr
+#define png_get_rgb_to_gray_status itk_png_get_rgb_to_gray_status
+#define png_get_rowbytes itk_png_get_rowbytes
+#define png_get_rows itk_png_get_rows
+#define png_get_sBIT itk_png_get_sBIT
+#define png_get_sCAL itk_png_get_sCAL
+#define png_get_sPLT itk_png_get_sPLT
+#define png_get_sRGB itk_png_get_sRGB
+#define png_get_signature itk_png_get_signature
+#define png_get_tIME itk_png_get_tIME
+#define png_get_tRNS itk_png_get_tRNS
+#define png_get_text itk_png_get_text
+#define png_get_uint_16 itk_png_get_uint_16
+#define png_get_uint_32 itk_png_get_uint_32
+#define png_get_unknown_chunks itk_png_get_unknown_chunks
+#define png_get_user_chunk_ptr itk_png_get_user_chunk_ptr
+#define png_get_user_transform_ptr itk_png_get_user_transform_ptr
+#define png_get_valid itk_png_get_valid
+#define png_get_x_offset_microns itk_png_get_x_offset_microns
+#define png_get_x_offset_pixels itk_png_get_x_offset_pixels
+#define png_get_x_pixels_per_meter itk_png_get_x_pixels_per_meter
+#define png_get_y_offset_microns itk_png_get_y_offset_microns
+#define png_get_y_offset_pixels itk_png_get_y_offset_pixels
+#define png_get_y_pixels_per_meter itk_png_get_y_pixels_per_meter
+#define png_handle_IEND itk_png_handle_IEND
+#define png_handle_IHDR itk_png_handle_IHDR
+#define png_handle_PLTE itk_png_handle_PLTE
+#define png_handle_as_unknown itk_png_handle_as_unknown
+#define png_handle_bKGD itk_png_handle_bKGD
+#define png_handle_cHRM itk_png_handle_cHRM
+#define png_handle_gAMA itk_png_handle_gAMA
+#define png_handle_hIST itk_png_handle_hIST
+#define png_handle_iCCP itk_png_handle_iCCP
+#define png_handle_oFFs itk_png_handle_oFFs
+#define png_handle_pCAL itk_png_handle_pCAL
+#define png_handle_pHYs itk_png_handle_pHYs
+#define png_handle_sBIT itk_png_handle_sBIT
+#define png_handle_sCAL itk_png_handle_sCAL
+#define png_handle_sPLT itk_png_handle_sPLT
+#define png_handle_sRGB itk_png_handle_sRGB
+#define png_handle_tEXt itk_png_handle_tEXt
+#define png_handle_tIME itk_png_handle_tIME
+#define png_handle_tRNS itk_png_handle_tRNS
+#define png_handle_unknown itk_png_handle_unknown
+#define png_handle_zTXt itk_png_handle_zTXt
+#define png_info_destroy itk_png_info_destroy
+#define png_info_init itk_png_info_init
+#define png_info_init_3 itk_png_info_init_3
+#define png_init_io itk_png_init_io
+#define png_init_read_transformations itk_png_init_read_transformations
+#define png_libpng_ver itk_png_libpng_ver
+#define png_malloc itk_png_malloc
+#define png_memcpy_check itk_png_memcpy_check
+#define png_memset_check itk_png_memset_check
+#define png_mmx_support itk_png_mmx_support
+#define png_pass_dsp_mask itk_png_pass_dsp_mask
+#define png_pass_mask itk_png_pass_mask
+#define png_pass_yinc itk_png_pass_yinc
+#define png_pass_ystart itk_png_pass_ystart
+#define png_pass_inc itk_png_pass_inc
+#define png_pass_start itk_png_pass_start
+#define png_permit_empty_plte itk_png_permit_empty_plte
+#define png_process_IDAT_data itk_png_process_IDAT_data
+#define png_process_data itk_png_process_data
+#define png_process_some_data itk_png_process_some_data
+#define png_progressive_combine_row itk_png_progressive_combine_row
+#define png_push_crc_finish itk_png_push_crc_finish
+#define png_push_crc_skip itk_png_push_crc_skip
+#define png_push_fill_buffer itk_png_push_fill_buffer
+#define png_push_handle_tEXt itk_png_push_handle_tEXt
+#define png_push_handle_unknown itk_png_push_handle_unknown
+#define png_push_handle_zTXt itk_png_push_handle_zTXt
+#define png_push_have_end itk_png_push_have_end
+#define png_push_have_info itk_png_push_have_info
+#define png_push_have_row itk_png_push_have_row
+#define png_push_process_row itk_png_push_process_row
+#define png_push_read_IDAT itk_png_push_read_IDAT
+#define png_push_read_chunk itk_png_push_read_chunk
+#define png_push_read_sig itk_png_push_read_sig
+#define png_push_read_tEXt itk_png_push_read_tEXt
+#define png_push_read_zTXt itk_png_push_read_zTXt
+#define png_push_restore_buffer itk_png_push_restore_buffer
+#define png_push_save_buffer itk_png_push_save_buffer
+#define png_read_data itk_png_read_data
+#define png_read_destroy itk_png_read_destroy
+#define png_read_end itk_png_read_end
+#define png_read_filter_row itk_png_read_filter_row
+#define png_read_finish_row itk_png_read_finish_row
+#define png_read_image itk_png_read_image
+#define png_read_info itk_png_read_info
+#define png_read_init itk_png_read_init
+#define png_read_init_2 itk_png_read_init_2
+#define png_read_init_3 itk_png_read_init_3
+#define png_read_png itk_png_read_png
+#define png_read_push_finish_row itk_png_read_push_finish_row
+#define png_read_row itk_png_read_row
+#define png_read_rows itk_png_read_rows
+#define png_read_start_row itk_png_read_start_row
+#define png_read_transform_info itk_png_read_transform_info
+#define png_read_update_info itk_png_read_update_info
+#define png_reset_crc itk_png_reset_crc
+#define png_reset_zstream itk_png_reset_zstream
+#define png_save_int_32 itk_png_save_int_32
+#define png_save_uint_16 itk_png_save_uint_16
+#define png_save_uint_32 itk_png_save_uint_32
+#define png_set_IHDR itk_png_set_IHDR
+#define png_set_PLTE itk_png_set_PLTE
+#define png_set_bKGD itk_png_set_bKGD
+#define png_set_background itk_png_set_background
+#define png_set_bgr itk_png_set_bgr
+#define png_set_cHRM itk_png_set_cHRM
+#define png_set_cHRM_fixed itk_png_set_cHRM_fixed
+#define png_set_compression_buffer_size itk_png_set_compression_buffer_size
+#define png_set_compression_level itk_png_set_compression_level
+#define png_set_compression_mem_level itk_png_set_compression_mem_level
+#define png_set_compression_method itk_png_set_compression_method
+#define png_set_compression_strategy itk_png_set_compression_strategy
+#define png_set_compression_window_bits itk_png_set_compression_window_bits
+#define png_set_crc_action itk_png_set_crc_action
+#define png_set_dither itk_png_set_dither
+#define png_set_error_fn itk_png_set_error_fn
+#define png_set_expand itk_png_set_expand
+#define png_set_filler itk_png_set_filler
+#define png_set_filter itk_png_set_filter
+#define png_set_filter_heuristics itk_png_set_filter_heuristics
+#define png_set_flush itk_png_set_flush
+#define png_set_gAMA itk_png_set_gAMA
+#define png_set_gAMA_fixed itk_png_set_gAMA_fixed
+#define png_set_gamma itk_png_set_gamma
+#define png_set_gray_1_2_4_to_8 itk_png_set_gray_1_2_4_to_8
+#define png_set_gray_to_rgb itk_png_set_gray_to_rgb
+#define png_set_hIST itk_png_set_hIST
+#define png_set_iCCP itk_png_set_iCCP
+#define png_set_interlace_handling itk_png_set_interlace_handling
+#define png_set_invalid itk_png_set_invalid
+#define png_set_invert_alpha itk_png_set_invert_alpha
+#define png_set_invert_mono itk_png_set_invert_mono
+#define png_set_keep_unknown_chunks itk_png_set_keep_unknown_chunks
+#define png_set_oFFs itk_png_set_oFFs
+#define png_set_pCAL itk_png_set_pCAL
+#define png_set_pHYs itk_png_set_pHYs
+#define png_set_packing itk_png_set_packing
+#define png_set_packswap itk_png_set_packswap
+#define png_set_palette_to_rgb itk_png_set_palette_to_rgb
+#define png_set_progressive_read_fn itk_png_set_progressive_read_fn
+#define png_set_read_fn itk_png_set_read_fn
+#define png_set_read_status_fn itk_png_set_read_status_fn
+#define png_set_read_user_chunk_fn itk_png_set_read_user_chunk_fn
+#define png_set_read_user_transform_fn itk_png_set_read_user_transform_fn
+#define png_set_rgb_to_gray itk_png_set_rgb_to_gray
+#define png_set_rgb_to_gray_fixed itk_png_set_rgb_to_gray_fixed
+#define png_set_rows itk_png_set_rows
+#define png_set_sBIT itk_png_set_sBIT
+#define png_set_sCAL itk_png_set_sCAL
+#define png_set_sPLT itk_png_set_sPLT
+#define png_set_sRGB itk_png_set_sRGB
+#define png_set_sRGB_gAMA_and_cHRM itk_png_set_sRGB_gAMA_and_cHRM
+#define png_set_shift itk_png_set_shift
+#define png_set_sig_bytes itk_png_set_sig_bytes
+#define png_set_strip_16 itk_png_set_strip_16
+#define png_set_strip_alpha itk_png_set_strip_alpha
+#define png_set_swap itk_png_set_swap
+#define png_set_swap_alpha itk_png_set_swap_alpha
+#define png_set_tIME itk_png_set_tIME
+#define png_set_tRNS itk_png_set_tRNS
+#define png_set_tRNS_to_alpha itk_png_set_tRNS_to_alpha
+#define png_set_text itk_png_set_text
+#define png_set_unknown_chunk_location itk_png_set_unknown_chunk_location
+#define png_set_unknown_chunks itk_png_set_unknown_chunks
+#define png_set_user_transform_info itk_png_set_user_transform_info
+#define png_set_write_fn itk_png_set_write_fn
+#define png_set_write_status_fn itk_png_set_write_status_fn
+#define png_set_write_user_transform_fn itk_png_set_write_user_transform_fn
+#define png_sig_cmp itk_png_sig_cmp
+#define png_start_read_image itk_png_start_read_image
+#define png_warning itk_png_warning
+#define png_write_IDAT itk_png_write_IDAT
+#define png_write_IEND itk_png_write_IEND
+#define png_write_IHDR itk_png_write_IHDR
+#define png_write_PLTE itk_png_write_PLTE
+#define png_write_bKGD itk_png_write_bKGD
+#define png_write_cHRM itk_png_write_cHRM
+#define png_write_cHRM_fixed itk_png_write_cHRM_fixed
+#define png_write_chunk itk_png_write_chunk
+#define png_write_chunk_data itk_png_write_chunk_data
+#define png_write_chunk_end itk_png_write_chunk_end
+#define png_write_chunk_start itk_png_write_chunk_start
+#define png_write_data itk_png_write_data
+#define png_write_destroy itk_png_write_destroy
+#define png_write_end itk_png_write_end
+#define png_write_filtered_row itk_png_write_filtered_row
+#define png_write_find_filter itk_png_write_find_filter
+#define png_write_finish_row itk_png_write_finish_row
+#define png_write_flush itk_png_write_flush
+#define png_write_gAMA itk_png_write_gAMA
+#define png_write_gAMA_fixed itk_png_write_gAMA_fixed
+#define png_write_hIST itk_png_write_hIST
+#define png_write_iCCP itk_png_write_iCCP
+#define png_write_image itk_png_write_image
+#define png_write_info itk_png_write_info
+#define png_write_info_before_PLTE itk_png_write_info_before_PLTE
+#define png_write_init itk_png_write_init
+#define png_write_init_2 itk_png_write_init_2
+#define png_write_init_3 itk_png_write_init_3
+#define png_write_oFFs itk_png_write_oFFs
+#define png_write_pCAL itk_png_write_pCAL
+#define png_write_pHYs itk_png_write_pHYs
+#define png_write_png itk_png_write_png
+#define png_write_row itk_png_write_row
+#define png_write_rows itk_png_write_rows
+#define png_write_sBIT itk_png_write_sBIT
+#define png_write_sCAL itk_png_write_sCAL
+#define png_write_sPLT itk_png_write_sPLT
+#define png_write_sRGB itk_png_write_sRGB
+#define png_write_sig itk_png_write_sig
+#define png_write_start_row itk_png_write_start_row
+#define png_write_tEXt itk_png_write_tEXt
+#define png_write_tIME itk_png_write_tIME
+#define png_write_tRNS itk_png_write_tRNS
+#define png_write_zTXt itk_png_write_zTXt
+#define png_zalloc itk_png_zalloc
+#define png_zfree itk_png_zfree
+
+#define png_zTXt itk_png_zTXt
+#define png_tRNS itk_png_tRNS
+#define png_tIME itk_png_tIME
+#define png_tEXt itk_png_tEXt
+#define png_sRGB itk_png_sRGB
+#define png_sPLT itk_png_sPLT
+#define png_sBIT itk_png_sBIT
+#define png_pHYs itk_png_pHYs
+#define png_sCAL itk_png_sCAL
+#define png_pCAL itk_png_pCAL
+#define png_oFFs itk_png_oFFs
+#define png_iTXt itk_png_iTXt
+#define png_iCCP itk_png_iCCP
+#define png_hIST itk_png_hIST
+#define png_gAMA itk_png_gAMA
+#define png_cHRM itk_png_cHRM
+#define png_bKGD itk_png_bKGD
+#define png_PLTE itk_png_PLTE
+#define png_IEND itk_png_IEND
+#define png_IDAT itk_png_IDAT
+#define png_IHDR itk_png_IHDR
+#define png_sig  itk_png_sig 
+
+#endif
diff --git a/Utilities/ITK/Utilities/png/png.c b/Utilities/ITK/Utilities/png/png.c
new file mode 100644
index 0000000000..c29be5bef3
--- /dev/null
+++ b/Utilities/ITK/Utilities/png/png.c
@@ -0,0 +1,729 @@
+
+/* png.c - location for general purpose libpng functions
+ *
+ * libpng version 1.0.12 - June 8, 2001
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ */
+
+#define PNG_INTERNAL
+#define PNG_NO_EXTERN
+#include "png.h"
+
+/* Generate a compiler error if there is an old png.h in the search path. */
+typedef version_1_0_12 Your_png_h_is_not_version_1_0_12;
+
+/* Version information for C files.  This had better match the version
+ * string defined in png.h.  */
+
+#ifdef PNG_USE_GLOBAL_ARRAYS
+/* png_libpng_ver was changed to a function in version 1.0.5c */
+const char png_libpng_ver[18] = "1.0.12";
+
+/* png_sig was changed to a function in version 1.0.5c */
+/* Place to hold the signature string for a PNG file. */
+const png_byte FARDATA png_sig[8] = {137, 80, 78, 71, 13, 10, 26, 10};
+
+/* Invoke global declarations for constant strings for known chunk types */
+PNG_IHDR;
+PNG_IDAT;
+PNG_IEND;
+PNG_PLTE;
+PNG_bKGD;
+PNG_cHRM;
+PNG_gAMA;
+PNG_hIST;
+PNG_iCCP;
+PNG_iTXt;
+PNG_oFFs;
+PNG_pCAL;
+PNG_sCAL;
+PNG_pHYs;
+PNG_sBIT;
+PNG_sPLT;
+PNG_sRGB;
+PNG_tEXt;
+PNG_tIME;
+PNG_tRNS;
+PNG_zTXt;
+
+/* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+
+/* start of interlace block */
+const int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
+
+/* offset to next interlace block */
+const int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
+
+/* start of interlace block in the y direction */
+const int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
+
+/* offset to next interlace block in the y direction */
+const int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
+
+/* width of interlace block (used in assembler routines only) */
+#ifdef PNG_HAVE_ASSEMBLER_COMBINE_ROW
+const int FARDATA png_pass_width[] = {8, 4, 4, 2, 2, 1, 1};
+#endif
+
+/* Height of interlace block.  This is not currently used - if you need
+ * it, uncomment it here and in png.h
+const int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
+*/
+
+/* Mask to determine which pixels are valid in a pass */
+const int FARDATA png_pass_mask[] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff};
+
+/* Mask to determine which pixels to overwrite while displaying */
+const int FARDATA png_pass_dsp_mask[]
+   = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff};
+
+#endif
+
+/* Tells libpng that we have already handled the first "num_bytes" bytes
+ * of the PNG file signature.  If the PNG data is embedded into another
+ * stream we can set num_bytes = 8 so that libpng will not attempt to read
+ * or write any of the magic bytes before it starts on the IHDR.
+ */
+
+void PNGAPI
+png_set_sig_bytes(png_structp png_ptr, int num_bytes)
+{
+   png_debug(1, "in png_set_sig_bytes\n");
+   if (num_bytes > 8)
+      png_error(png_ptr, "Too many bytes for PNG signature.");
+
+   png_ptr->sig_bytes = (png_byte)(num_bytes < 0 ? 0 : num_bytes);
+}
+
+/* Checks whether the supplied bytes match the PNG signature.  We allow
+ * checking less than the full 8-byte signature so that those apps that
+ * already read the first few bytes of a file to determine the file type
+ * can simply check the remaining bytes for extra assurance.  Returns
+ * an integer less than, equal to, or greater than zero if sig is found,
+ * respectively, to be less than, to match, or be greater than the correct
+ * PNG signature (this is the same behaviour as strcmp, memcmp, etc).
+ */
+int PNGAPI
+png_sig_cmp(png_bytep sig, png_size_t start, png_size_t num_to_check)
+{
+   png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
+   if (num_to_check > 8)
+      num_to_check = 8;
+   else if (num_to_check < 1)
+      return (0);
+
+   if (start > 7)
+      return (0);
+
+   if (start + num_to_check > 8)
+      num_to_check = 8 - start;
+
+   return ((int)(png_memcmp(&sig[start], &png_signature[start], num_to_check)));
+}
+
+/* (Obsolete) function to check signature bytes.  It does not allow one
+ * to check a partial signature.  This function might be removed in the
+ * future - use png_sig_cmp().  Returns true (nonzero) if the file is a PNG.
+ */
+int PNGAPI
+png_check_sig(png_bytep sig, int num)
+{
+  return ((int)!png_sig_cmp(sig, (png_size_t)0, (png_size_t)num));
+}
+
+/* Function to allocate memory for zlib and clear it to 0. */
+voidpf /* PRIVATE */
+png_zalloc(voidpf png_ptr, uInt items, uInt size)
+{
+   png_uint_32 num_bytes = (png_uint_32)items * size;
+   png_voidp ptr = (png_voidp)png_malloc((png_structp)png_ptr, num_bytes);
+
+#ifndef PNG_NO_ZALLOC_ZERO
+   if (num_bytes > (png_uint_32)0x8000L)
+   {
+      png_memset(ptr, 0, (png_size_t)0x8000L);
+      png_memset((png_bytep)ptr + (png_size_t)0x8000L, 0,
+         (png_size_t)(num_bytes - (png_uint_32)0x8000L));
+   }
+   else
+   {
+      png_memset(ptr, 0, (png_size_t)num_bytes);
+   }
+#endif
+   return ((voidpf)ptr);
+}
+
+/* function to free memory for zlib */
+void /* PRIVATE */
+png_zfree(voidpf png_ptr, voidpf ptr)
+{
+   png_free((png_structp)png_ptr, (png_voidp)ptr);
+}
+
+/* Reset the CRC variable to 32 bits of 1's.  Care must be taken
+ * in case CRC is > 32 bits to leave the top bits 0.
+ */
+void /* PRIVATE */
+png_reset_crc(png_structp png_ptr)
+{
+   png_ptr->crc = crc32(0, Z_NULL, 0);
+}
+
+/* Calculate the CRC over a section of data.  We can only pass as
+ * much data to this routine as the largest single buffer size.  We
+ * also check that this data will actually be used before going to the
+ * trouble of calculating it.
+ */
+void /* PRIVATE */
+png_calculate_crc(png_structp png_ptr, png_bytep ptr, png_size_t length)
+{
+   int need_crc = 1;
+
+   if (png_ptr->chunk_name[0] & 0x20)                     /* ancillary */
+   {
+      if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
+          (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
+         need_crc = 0;
+   }
+   else                                                    /* critical */
+   {
+      if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
+         need_crc = 0;
+   }
+
+   if (need_crc)
+      png_ptr->crc = crc32(png_ptr->crc, ptr, (uInt)length);
+}
+
+/* Allocate the memory for an info_struct for the application.  We don't
+ * really need the png_ptr, but it could potentially be useful in the
+ * future.  This should be used in favour of malloc(sizeof(png_info))
+ * and png_info_init() so that applications that want to use a shared
+ * libpng don't have to be recompiled if png_info changes size.
+ */
+png_infop PNGAPI
+png_create_info_struct(png_structp png_ptr)
+{
+   png_infop info_ptr;
+
+   png_debug(1, "in png_create_info_struct\n");
+   if(png_ptr == NULL) return (NULL);
+#ifdef PNG_USER_MEM_SUPPORTED
+   if ((info_ptr = (png_infop)png_create_struct_2(PNG_STRUCT_INFO,
+      png_ptr->malloc_fn, png_ptr->mem_ptr)) != NULL)
+#else
+   if ((info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO)) != NULL)
+#endif
+   {
+      png_info_init_3(&info_ptr, sizeof(png_info));
+   }
+
+   return (info_ptr);
+}
+
+/* This function frees the memory associated with a single info struct.
+ * Normally, one would use either png_destroy_read_struct() or
+ * png_destroy_write_struct() to free an info struct, but this may be
+ * useful for some applications.
+ */
+void PNGAPI
+png_destroy_info_struct(png_structp png_ptr, png_infopp info_ptr_ptr)
+{
+   png_infop info_ptr = NULL;
+
+   png_debug(1, "in png_destroy_info_struct\n");
+   if (info_ptr_ptr != NULL)
+      info_ptr = *info_ptr_ptr;
+
+   if (info_ptr != NULL)
+   {
+      png_info_destroy(png_ptr, info_ptr);
+
+#ifdef PNG_USER_MEM_SUPPORTED
+      png_destroy_struct_2((png_voidp)info_ptr, png_ptr->free_fn,
+          png_ptr->mem_ptr);
+#else
+      png_destroy_struct((png_voidp)info_ptr);
+#endif
+      *info_ptr_ptr = (png_infop)NULL;
+   }
+}
+
+/* Initialize the info structure.  This is now an internal function (0.89)
+ * and applications using it are urged to use png_create_info_struct()
+ * instead.
+ */
+#undef png_info_init
+void PNGAPI
+itk_png_info_init(png_infop info_ptr)
+{
+   /* We only come here via pre-1.0.12-compiled applications */
+   png_info_init_3(&info_ptr, 0);
+}
+
+void PNGAPI
+png_info_init_3(png_infopp ptr_ptr, png_size_t png_info_struct_size)
+{
+   png_infop info_ptr = *ptr_ptr;
+
+   png_debug(1, "in png_info_init_3\n");
+
+   if(sizeof(png_info) > png_info_struct_size)
+     {
+       png_destroy_struct(info_ptr);
+       info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO);
+       *ptr_ptr = info_ptr;
+     }
+
+   /* set everything to 0 */
+   png_memset(info_ptr, 0, sizeof (png_info));
+}
+
+#ifdef PNG_FREE_ME_SUPPORTED
+void PNGAPI
+png_data_freer(png_structp png_ptr, png_infop info_ptr,
+   int freer, png_uint_32 mask)
+{
+   png_debug(1, "in png_data_freer\n");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+   if(freer == PNG_DESTROY_WILL_FREE_DATA)
+      info_ptr->free_me |= mask;
+   else if(freer == PNG_USER_WILL_FREE_DATA)
+      info_ptr->free_me &= ~mask;
+   else
+      png_warning(png_ptr,
+         "Unknown freer parameter in png_data_freer.");
+}
+#endif
+
+void PNGAPI
+png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask,
+   int num)
+{
+   png_debug(1, "in png_free_data\n");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+#if defined(PNG_TEXT_SUPPORTED)
+/* free text item num or (if num == -1) all text items */
+#ifdef PNG_FREE_ME_SUPPORTED
+if ((mask & PNG_FREE_TEXT) & info_ptr->free_me)
+#else
+if (mask & PNG_FREE_TEXT)
+#endif
+{
+   if (num != -1)
+   {
+     if (info_ptr->text && info_ptr->text[num].key)
+     {
+         png_free(png_ptr, info_ptr->text[num].key);
+         info_ptr->text[num].key = NULL;
+     }
+   }
+   else
+   {
+       int i;
+       for (i = 0; i < info_ptr->num_text; i++)
+           png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, 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 */
+#ifdef PNG_FREE_ME_SUPPORTED
+if ((mask & PNG_FREE_TRNS) & info_ptr->free_me)
+#else
+if ((mask & PNG_FREE_TRNS) && (png_ptr->flags & PNG_FLAG_FREE_TRNS))
+#endif
+{
+    png_free(png_ptr, info_ptr->trans);
+    info_ptr->valid &= ~PNG_INFO_tRNS;
+    info_ptr->trans = NULL;
+}
+#endif
+
+#if defined(PNG_sCAL_SUPPORTED)
+/* free any sCAL entry */
+#ifdef PNG_FREE_ME_SUPPORTED
+if ((mask & PNG_FREE_SCAL) & info_ptr->free_me)
+#else
+if (mask & PNG_FREE_SCAL)
+#endif
+{
+#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);
+    info_ptr->scal_s_width = NULL;
+    info_ptr->scal_s_height = NULL;
+#endif
+    info_ptr->valid &= ~PNG_INFO_sCAL;
+}
+#endif
+
+#if defined(PNG_pCAL_SUPPORTED)
+/* free any pCAL entry */
+#ifdef PNG_FREE_ME_SUPPORTED
+if ((mask & PNG_FREE_PCAL) & info_ptr->free_me)
+#else
+if (mask & PNG_FREE_PCAL)
+#endif
+{
+    png_free(png_ptr, info_ptr->pcal_purpose);
+    png_free(png_ptr, info_ptr->pcal_units);
+    info_ptr->pcal_purpose = NULL;
+    info_ptr->pcal_units = NULL;
+    if (info_ptr->pcal_params != NULL)
+    {
+        int i;
+        for (i = 0; i < (int)info_ptr->pcal_nparams; i++)
+        {
+          png_free(png_ptr, info_ptr->pcal_params[i]);
+          info_ptr->pcal_params[i]=NULL;
+        }
+        png_free(png_ptr, info_ptr->pcal_params);
+        info_ptr->pcal_params = NULL;
+    }
+    info_ptr->valid &= ~PNG_INFO_pCAL;
+}
+#endif
+
+#if defined(PNG_iCCP_SUPPORTED)
+/* free any iCCP entry */
+#ifdef PNG_FREE_ME_SUPPORTED
+if ((mask & PNG_FREE_ICCP) & info_ptr->free_me)
+#else
+if (mask & PNG_FREE_ICCP)
+#endif
+{
+    png_free(png_ptr, info_ptr->iccp_name);
+    png_free(png_ptr, info_ptr->iccp_profile);
+    info_ptr->iccp_name = NULL;
+    info_ptr->iccp_profile = NULL;
+    info_ptr->valid &= ~PNG_INFO_iCCP;
+}
+#endif
+
+#if defined(PNG_sPLT_SUPPORTED)
+/* free a given sPLT entry, or (if num == -1) all sPLT entries */
+#ifdef PNG_FREE_ME_SUPPORTED
+if ((mask & PNG_FREE_SPLT) & info_ptr->free_me)
+#else
+if (mask & PNG_FREE_SPLT)
+#endif
+{
+   if (num != -1)
+   {
+      if(info_ptr->splt_palettes)
+      {
+          png_free(png_ptr, info_ptr->splt_palettes[num].name);
+          png_free(png_ptr, info_ptr->splt_palettes[num].entries);
+          info_ptr->splt_palettes[num].name = NULL;
+          info_ptr->splt_palettes[num].entries = NULL;
+      }
+   }
+   else
+   {
+       if(info_ptr->splt_palettes_num)
+       {
+         int i;
+         for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
+            png_free_data(png_ptr, info_ptr, PNG_FREE_SPLT, i);
+
+         png_free(png_ptr, info_ptr->splt_palettes);
+         info_ptr->splt_palettes = NULL;
+         info_ptr->splt_palettes_num = 0;
+       }
+       info_ptr->valid &= ~PNG_INFO_sPLT;
+   }
+}
+#endif
+
+#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+#ifdef PNG_FREE_ME_SUPPORTED
+if ((mask & PNG_FREE_UNKN) & info_ptr->free_me)
+#else
+if (mask & PNG_FREE_UNKN)
+#endif
+{
+   if (num != -1)
+   {
+       if(info_ptr->unknown_chunks)
+       {
+          png_free(png_ptr, info_ptr->unknown_chunks[num].data);
+          info_ptr->unknown_chunks[num].data = NULL;
+       }
+   }
+   else
+   {
+       int i;
+
+       if(info_ptr->unknown_chunks_num)
+       {
+         for (i = 0; i < (int)info_ptr->unknown_chunks_num; i++)
+            png_free_data(png_ptr, info_ptr, PNG_FREE_UNKN, i);
+
+         png_free(png_ptr, info_ptr->unknown_chunks);
+         info_ptr->unknown_chunks = NULL;
+         info_ptr->unknown_chunks_num = 0;
+       }
+   }
+}
+#endif
+
+#if defined(PNG_hIST_SUPPORTED)
+/* free any hIST entry */
+#ifdef PNG_FREE_ME_SUPPORTED
+if ((mask & PNG_FREE_HIST)  & info_ptr->free_me)
+#else
+if ((mask & PNG_FREE_HIST) && (png_ptr->flags & PNG_FLAG_FREE_HIST))
+#endif
+{
+    png_free(png_ptr, info_ptr->hist);
+    info_ptr->hist = NULL;
+    info_ptr->valid &= ~PNG_INFO_hIST;
+}
+#endif
+
+/* free any PLTE entry that was internally allocated */
+#ifdef PNG_FREE_ME_SUPPORTED
+if ((mask & PNG_FREE_PLTE) & info_ptr->free_me)
+#else
+if ((mask & PNG_FREE_PLTE) && (png_ptr->flags & PNG_FLAG_FREE_PLTE))
+#endif
+{
+    png_zfree(png_ptr, info_ptr->palette);
+    info_ptr->palette = NULL;
+    info_ptr->valid &= ~PNG_INFO_PLTE;
+    info_ptr->num_palette = 0;
+}
+
+#if defined(PNG_INFO_IMAGE_SUPPORTED)
+/* free any image bits attached to the info structure */
+#ifdef PNG_FREE_ME_SUPPORTED
+if ((mask & PNG_FREE_ROWS) & info_ptr->free_me)
+#else
+if (mask & PNG_FREE_ROWS)
+#endif
+{
+    if(info_ptr->row_pointers)
+    {
+       int row;
+       for (row = 0; row < (int)info_ptr->height; row++)
+       {
+          png_free(png_ptr, info_ptr->row_pointers[row]);
+          info_ptr->row_pointers[row]=NULL;
+       }
+       png_free(png_ptr, info_ptr->row_pointers);
+       info_ptr->row_pointers=NULL;
+    }
+    info_ptr->valid &= ~PNG_INFO_IDAT;
+}
+#endif
+
+#ifdef PNG_FREE_ME_SUPPORTED
+   if(num == -1)
+     info_ptr->free_me &= ~mask;
+   else
+     info_ptr->free_me &= ~(mask & ~PNG_FREE_MUL);
+#endif
+}
+
+/* This is an internal routine to free any memory that the info struct is
+ * pointing to before re-using it or freeing the struct itself.  Recall
+ * that png_free() checks for NULL pointers for us.
+ */
+void /* PRIVATE */
+png_info_destroy(png_structp png_ptr, png_infop info_ptr)
+{
+   png_debug(1, "in png_info_destroy\n");
+
+   png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
+
+#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+   if (png_ptr->num_chunk_list)
+   {
+       png_free(png_ptr, png_ptr->chunk_list);
+       png_ptr->chunk_list=NULL;
+       png_ptr->num_chunk_list=0;
+   }
+#endif
+
+   png_info_init_3(&info_ptr, sizeof(png_info));
+}
+
+/* This function returns a pointer to the io_ptr associated with the user
+ * functions.  The application should free any memory associated with this
+ * pointer before png_write_destroy() or png_read_destroy() are called.
+ */
+png_voidp PNGAPI
+png_get_io_ptr(png_structp png_ptr)
+{
+   return (png_ptr->io_ptr);
+}
+
+#if !defined(PNG_NO_STDIO)
+/* Initialize the default input/output functions for the PNG file.  If you
+ * use your own read or write routines, you can call either png_set_read_fn()
+ * or png_set_write_fn() instead of png_init_io().  If you have defined
+ * PNG_NO_STDIO, you must use a function of your own because "FILE *" isn't
+ * necessarily available.
+ */
+void PNGAPI
+png_init_io(png_structp png_ptr, png_FILE_p fp)
+{
+   png_debug(1, "in png_init_io\n");
+   png_ptr->io_ptr = (png_voidp)fp;
+}
+#endif
+
+#if defined(PNG_TIME_RFC1123_SUPPORTED)
+/* Convert the supplied time into an RFC 1123 string suitable for use in
+ * a "Creation Time" or other text-based time string.
+ */
+png_charp PNGAPI
+png_convert_to_rfc1123(png_structp png_ptr, png_timep ptime)
+{
+   static PNG_CONST char short_months[12][4] =
+        {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+
+   if (png_ptr->time_buffer == NULL)
+   {
+      png_ptr->time_buffer = (png_charp)png_malloc(png_ptr, (png_uint_32)(29*
+         sizeof(char)));
+   }
+
+#if defined(_WIN32_WCE)
+   {
+      wchar_t time_buf[29];
+      wsprintf(time_buf, TEXT("%d %S %d %02d:%02d:%02d +0000"),
+          ptime->day % 32, short_months[(ptime->month - 1) % 12],
+        ptime->year, ptime->hour % 24, ptime->minute % 60,
+          ptime->second % 61);
+      WideCharToMultiByte(CP_ACP, 0, time_buf, -1, png_ptr->time_buffer, 29,
+          NULL, NULL);
+   }
+#else
+#ifdef USE_FAR_KEYWORD
+   {
+      char near_time_buf[29];
+      sprintf(near_time_buf, "%d %s %d %02d:%02d:%02d +0000",
+          ptime->day % 32, short_months[(ptime->month - 1) % 12],
+          ptime->year, ptime->hour % 24, ptime->minute % 60,
+          ptime->second % 61);
+      png_memcpy(png_ptr->time_buffer, near_time_buf,
+          29*sizeof(char));
+   }
+#else
+   sprintf(png_ptr->time_buffer, "%d %s %d %02d:%02d:%02d +0000",
+       ptime->day % 32, short_months[(ptime->month - 1) % 12],
+       ptime->year, ptime->hour % 24, ptime->minute % 60,
+       ptime->second % 61);
+#endif
+#endif /* _WIN32_WCE */
+   return ((png_charp)png_ptr->time_buffer);
+}
+#endif /* PNG_TIME_RFC1123_SUPPORTED */
+
+#if 0
+/* Signature string for a PNG file. */
+png_bytep PNGAPI
+png_sig_bytes(void)
+{
+   return ((png_bytep)"\211\120\116\107\015\012\032\012");
+}
+#endif
+
+png_charp PNGAPI
+png_get_copyright(png_structp png_ptr)
+{
+   if (png_ptr != NULL || png_ptr == NULL)  /* silence compiler warning */
+   return ((png_charp) "\n libpng version 1.0.12 - June 8, 2001\n\
+   Copyright (c) 1998-2001 Glenn Randers-Pehrson\n\
+   Copyright (c) 1996, 1997 Andreas Dilger\n\
+   Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.\n");
+   return ((png_charp) "");
+}
+
+/* The following return the library version as a short string in the
+ * format 1.0.0 through 99.99.99zz.  To get the version of *.h files used
+ * with your application, print out PNG_LIBPNG_VER_STRING, which is defined
+ * in png.h.
+ */
+
+png_charp PNGAPI
+png_get_libpng_ver(png_structp png_ptr)
+{
+   /* Version of *.c files used when building libpng */
+   if(png_ptr != NULL) /* silence compiler warning about unused png_ptr */
+      return((png_charp) "1.0.12");
+   return((png_charp) "1.0.12");
+}
+
+png_charp PNGAPI
+png_get_header_ver(png_structp png_ptr)
+{
+   /* Version of *.h files used when building libpng */
+   if(png_ptr != NULL) /* silence compiler warning about unused png_ptr */
+      return((png_charp) PNG_LIBPNG_VER_STRING);
+   return((png_charp) PNG_LIBPNG_VER_STRING);
+}
+
+png_charp PNGAPI
+png_get_header_version(png_structp png_ptr)
+{
+   /* Returns longer string containing both version and date */
+   if(png_ptr != NULL) /* silence compiler warning about unused png_ptr */
+      return((png_charp) PNG_HEADER_VERSION_STRING);
+   return((png_charp) PNG_HEADER_VERSION_STRING);
+}
+
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+int /* PRIVATE */
+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
+
+/* This function, added to libpng-1.0.6g, is untested. */
+int PNGAPI
+png_reset_zstream(png_structp png_ptr)
+{
+   return (inflateReset(&png_ptr->zstream));
+}
+
+/* This function was added to libpng-1.0.7 */
+png_uint_32 PNGAPI
+png_access_version_number(void)
+{
+   /* Version of *.c files used when building libpng */
+   return((png_uint_32) 10012L);
+}
+
+/* this function was added to libpng 1.2.0 */
+#if !defined(PNG_USE_PNGGCCRD) && \
+    !(defined(PNG_ASSEMBLER_CODE_SUPPORTED) && defined(PNG_USE_PNGVCRD))
+int PNGAPI
+png_mmx_support(void)
+{
+    return -1;
+}
+#endif
diff --git a/Utilities/ITK/Utilities/png/png.h b/Utilities/ITK/Utilities/png/png.h
new file mode 100644
index 0000000000..d1b342d333
--- /dev/null
+++ b/Utilities/ITK/Utilities/png/png.h
@@ -0,0 +1,3097 @@
+
+/* png.h - header file for PNG reference library
+ *
+ * libpng version 1.0.12 - June 8, 2001
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * Authors and maintainers:
+ *  libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
+ *  libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger
+ *  libpng versions 0.97, January 1998, through 1.0.12 - June 8, 2001: Glenn
+ *  See also "Contributing Authors", below.
+ *
+ * Note about libpng version numbers:
+ *
+ *    Due to various miscommunications, unforeseen code incompatibilities
+ *    and occasional factors outside the authors' control, version numbering
+ *    on the library has not always been consistent and straightforward.
+ *    The following table summarizes matters since version 0.89c, which was
+ *    the first widely used release:
+ *
+ *    source                 png.h  png.h  shared-lib
+ *    version                string   int  version
+ *    -------                ------ -----  ----------
+ *    0.89c "1.0 beta 3"     0.89      89  1.0.89
+ *    0.90  "1.0 beta 4"     0.90      90  0.90  [should have been 2.0.90]
+ *    0.95  "1.0 beta 5"     0.95      95  0.95  [should have been 2.0.95]
+ *    0.96  "1.0 beta 6"     0.96      96  0.96  [should have been 2.0.96]
+ *    0.97b "1.00.97 beta 7" 1.00.97   97  1.0.1 [should have been 2.0.97]
+ *    0.97c                  0.97      97  2.0.97
+ *    0.98                   0.98      98  2.0.98
+ *    0.99                   0.99      98  2.0.99
+ *    0.99a-m                0.99      99  2.0.99
+ *    1.00                   1.00     100  2.1.0 [100 should be 10000]
+ *    1.0.0      (from here on, the   100  2.1.0 [100 should be 10000]
+ *    1.0.1       png.h string is   10001  2.1.0
+ *    1.0.1a-e    identical to the  10002  from here on, the shared library
+ *    1.0.2       source version)   10002  is 2.V where V is the source code
+ *    1.0.2a-b                      10003  version, except as noted.
+ *    1.0.3                         10003
+ *    1.0.3a-d                      10004
+ *    1.0.4                         10004
+ *    1.0.4a-f                      10005
+ *    1.0.5 (+ 2 patches)           10005
+ *    1.0.5a-d                      10006
+ *    1.0.5e-r                      10100 (not source compatible)
+ *    1.0.5s-v                      10006 (not binary compatible)
+ *    1.0.6 (+ 3 patches)           10006 (still binary incompatible)
+ *    1.0.6d-f                      10007 (still binary incompatible)
+ *    1.0.6g                        10007
+ *    1.0.6h                        10007  10.6h (testing xy.z so-numbering)
+ *    1.0.6i                        10007  10.6i
+ *    1.0.6j                        10007  2.1.0.6j (incompatible with 1.0.0)
+ *    1.0.7beta11-14        DLLNUM  10007  2.1.0.7beta11-14 (binary compatible)
+ *    1.0.7beta15-18           1    10007  2.1.0.7beta15-18 (binary compatible)
+ *    1.0.7rc1-2               1    10007  2.1.0.7rc1-2 (binary compatible)
+ *    1.0.7                    1    10007  (still compatible)
+ *    1.0.8beta1-4             1    10008  2.1.0.8beta1-4
+ *    1.0.8rc1                 1    10008  2.1.0.8rc1
+ *    1.0.8                    1    10008  2.1.0.8
+ *    1.0.9beta1-6             1    10009  2.1.0.9beta1-6
+ *    1.0.9rc1                 1    10009  2.1.0.9rc1
+ *    1.0.9beta7-10            1    10009  2.1.0.9beta7-10
+ *    1.0.9rc2                 1    10009  2.1.0.9rc2
+ *    1.0.9                    1    10009  2.1.0.9
+ *    1.0.10beta1              1    10010  2.1.0.10beta1
+ *    1.0.10rc1                1    10010  2.1.0.10rc1
+ *    1.0.10                   1    10010  2.1.0.10
+ *    1.0.11beta1-3            1    10011  2.1.0.11beta1-3
+ *    1.0.11rc1                1    10011  2.1.0.11rc1
+ *    1.0.11                   1    10011  2.1.0.11
+ *    1.0.12beta1-2            2    10012  2.1.0.11beta1-2
+ *
+ *    Henceforth the source version will match the shared-library major
+ *    and minor numbers; the shared-library major version number will be
+ *    used for changes in backward compatibility, as it is intended.  The
+ *    PNG_LIBPNG_VER macro, which is not used within libpng but is available
+ *    for applications, is an unsigned integer of the form xyyzz corresponding
+ *    to the source version x.y.z (leading zeros in y and z).  Beta versions
+ *    were given the previous public release number plus a letter, until
+ *    version 1.0.6j; from then on they were given the upcoming public
+ *    release number plus "betaNN" or "rcN".
+ *
+ *    Binary incompatibility exists only when applications make direct access
+ *    to the info_ptr or png_ptr members through png.h, and the compiled
+ *    application is loaded with a different version of the library.
+ *
+ *    DLLNUM will change each time there are forward or backward changes
+ *    in binary compatibility (e.g., when a new feature is added).
+ *
+ * See libpng.txt or libpng.3 for more information.  The PNG specification
+ * is available as RFC 2083 <ftp://ftp.uu.net/graphics/png/documents/>
+ * and as a W3C Recommendation <http://www.w3.org/TR/REC.png.html>
+ */
+
+/*
+ * COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
+ *
+ * If you modify libpng you may insert additional notices immediately following
+ * this sentence.
+ *
+ * libpng versions 1.0.7, July 1, 2000, through  1.0.12, June 8, 2001, are
+ * Copyright (c) 2000, 2001 Glenn Randers-Pehrson, and are
+ * distributed according to the same disclaimer and license as libpng-1.0.6
+ * with the following individuals added to the list of Contributing Authors
+ *
+ *    Simon-Pierre Cadieux
+ *    Eric S. Raymond
+ *    Gilles Vollant
+ *
+ * and with the following additions to the disclaimer:
+ *
+ *    There is no warranty against interference with your enjoyment of the
+ *    library or against infringement.  There is no warranty that our
+ *    efforts or the library will fulfill any of your particular purposes
+ *    or needs.  This library is provided with all faults, and the entire
+ *    risk of satisfactory quality, performance, accuracy, and effort is with
+ *    the user.
+ *
+ * libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
+ * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson
+ * Distributed according to the same disclaimer and license as libpng-0.96,
+ * with the following individuals added to the list of Contributing Authors:
+ *
+ *    Tom Lane
+ *    Glenn Randers-Pehrson
+ *    Willem van Schaik
+ *
+ * libpng versions 0.89, June 1996, through 0.96, May 1997, are
+ * Copyright (c) 1996, 1997 Andreas Dilger
+ * Distributed according to the same disclaimer and license as libpng-0.88,
+ * with the following individuals added to the list of Contributing Authors:
+ *
+ *    John Bowler
+ *    Kevin Bracey
+ *    Sam Bushell
+ *    Magnus Holmgren
+ *    Greg Roelofs
+ *    Tom Tanner
+ *
+ * libpng versions 0.5, May 1995, through 0.88, January 1996, are
+ * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
+ *
+ * For the purposes of this copyright and license, "Contributing Authors"
+ * is defined as the following set of individuals:
+ *
+ *    Andreas Dilger
+ *    Dave Martindale
+ *    Guy Eric Schalnat
+ *    Paul Schmidt
+ *    Tim Wegner
+ *
+ * The PNG Reference Library is supplied "AS IS".  The Contributing Authors
+ * and Group 42, Inc. disclaim all warranties, expressed or implied,
+ * including, without limitation, the warranties of merchantability and of
+ * fitness for any purpose.  The Contributing Authors and Group 42, Inc.
+ * assume no liability for direct, indirect, incidental, special, exemplary,
+ * or consequential damages, which may result from the use of the PNG
+ * Reference Library, even if advised of the possibility of such damage.
+ *
+ * Permission is hereby granted to use, copy, modify, and distribute this
+ * source code, or portions hereof, for any purpose, without fee, subject
+ * to the following restrictions:
+ *
+ * 1. The origin of this source code must not be misrepresented.
+ *
+ * 2. Altered versions must be plainly marked as such and
+ * must not be misrepresented as being the original source.
+ *
+ * 3. This Copyright notice may not be removed or altered from
+ *    any source or altered source distribution.
+ *
+ * The Contributing Authors and Group 42, Inc. specifically permit, without
+ * fee, and encourage the use of this source code as a component to
+ * supporting the PNG file format in commercial products.  If you use this
+ * source code in a product, acknowledgment is not required but would be
+ * appreciated.
+ */
+
+/*
+ * A "png_get_copyright" function is available, for convenient use in "about"
+ * boxes and the like:
+ *
+ * printf("%s",png_get_copyright(NULL));
+ *
+ * Also, the PNG logo (in PNG format, of course) is supplied in the
+ * files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31).
+ */
+
+/*
+ * Libpng is OSI Certified Open Source Software.  OSI Certified is a
+ * certification mark of the Open Source Initiative.
+ */
+
+/*
+ * The contributing authors would like to thank all those who helped
+ * with testing, bug fixes, and patience.  This wouldn't have been
+ * possible without all of you.
+ *
+ * Thanks to Frank J. T. Wojcik for helping with the documentation.
+ */
+
+/*
+ * Y2K compliance in libpng:
+ * =========================
+ *
+ *    June 8, 2001
+ *
+ *    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.12 are Y2K compliant.  It is my belief that earlier
+ *    versions were also Y2K compliant.
+ *
+ *    Libpng only has three year fields.  One is a 2-byte unsigned integer
+ *    that will hold years up to 65535.  The other two hold the date in text
+ *    format, and will hold years up to 9999.
+ *
+ *    The integer is
+ *        "png_uint_16 year" in png_time_struct.
+ *
+ *    The strings are
+ *        "png_charp time_buffer" in png_struct and
+ *        "near_time_buffer", which is a local character string in png.c.
+ *
+ *    There are seven time-related functions:
+ *        png.c: png_convert_to_rfc_1123() in png.c
+ *          (formerly png_convert_to_rfc_1152() in error)
+ *        png_convert_from_struct_tm() in pngwrite.c, called in pngwrite.c
+ *        png_convert_from_time_t() in pngwrite.c
+ *        png_get_tIME() in pngget.c
+ *        png_handle_tIME() in pngrutil.c, called in pngread.c
+ *        png_set_tIME() in pngset.c
+ *        png_write_tIME() in pngwutil.c, called in pngwrite.c
+ *
+ *    All handle dates properly in a Y2K environment.  The
+ *    png_convert_from_time_t() function calls gmtime() to convert from system
+ *    clock time, which returns (year - 1900), which we properly convert to
+ *    the full 4-digit year.  There is a possibility that applications using
+ *    libpng are not passing 4-digit years into the png_convert_to_rfc_1123()
+ *    function, or that they are incorrectly passing only a 2-digit year
+ *    instead of "year - 1900" into the png_convert_from_struct_tm() function,
+ *    but this is not under our control.  The libpng documentation has always
+ *    stated that it works with 4-digit years, and the APIs have been
+ *    documented as such.
+ *
+ *    The tIME chunk itself is also Y2K compliant.  It uses a 2-byte unsigned
+ *    integer to hold the year, and can hold years as large as 65535.
+ *
+ *    zlib, upon which libpng depends, is also Y2K compliant.  It contains
+ *    no date-related code.
+ *
+ *       Glenn Randers-Pehrson
+ *       libpng maintainer
+ *       PNG Development Group
+ */
+
+#ifndef PNG_H
+#define PNG_H
+
+/* This is not the place to learn how to use libpng.  The file libpng.txt
+ * describes how to use libpng, and the file example.c summarizes it
+ * with some code on which to build.  This file is useful for looking
+ * at the actual function definitions and structure components.
+ */
+
+/* Version information for png.h - this should match the version in png.c */
+#define PNG_LIBPNG_VER_STRING "1.0.12"
+
+#define PNG_LIBPNG_VER_SONUM   2
+#define PNG_LIBPNG_VER_DLLNUM  %DLLNUM%
+
+/* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
+#define PNG_LIBPNG_VER_MAJOR   1
+#define PNG_LIBPNG_VER_MINOR   0
+#define PNG_LIBPNG_VER_RELEASE 12
+/* This should match the numeric part of the final component of
+ * PNG_LIBPNG_VER_STRING, omitting any leading zero: */
+
+#define PNG_LIBPNG_VER_BUILD  0
+
+#define PNG_LIBPNG_BUILD_ALPHA    1
+#define PNG_LIBPNG_BUILD_BETA     2
+#define PNG_LIBPNG_BUILD_RC       3
+#define PNG_LIBPNG_BUILD_STABLE   4
+#define PNG_LIBPNG_BUILD_TYPEMASK 7
+#define PNG_LIBPNG_BUILD_PATCH    8 /* Can be OR'ed with STABLE only */
+#define PNG_LIBPNG_BUILD_TYPE 4
+
+/* Careful here.  At one time, Guy wanted to use 082, but that would be octal.
+ * We must not include leading zeros.
+ * Versions 0.7 through 1.0.0 were in the range 0 to 100 here (only
+ * version 1.0.0 was mis-numbered 100 instead of 10000).  From
+ * version 1.0.1 it's    xxyyzz, where x=major, y=minor, z=release */
+#define PNG_LIBPNG_VER 10012 /* 1.0.12 */
+
+#ifndef PNG_VERSION_INFO_ONLY
+
+/* include the compression library's header */
+#include "zlib.h"
+
+/* include all user configurable info, including optional assembler routines */
+#include "pngconf.h"
+
+/* Inhibit C++ name-mangling for libpng functions but not for system calls. */
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* This file is arranged in several sections.  The first section contains
+ * structure and type definitions.  The second section contains the external
+ * library functions, while the third has the internal library functions,
+ * which applications aren't expected to use directly.
+ */
+
+/* variables declared in png.c - only it needs to define PNG_NO_EXTERN */
+#if !defined(PNG_NO_EXTERN) || defined(PNG_ALWAYS_EXTERN)
+/* Version information for C files, stored in png.c.  This had better match
+ * the version above.
+ */
+#ifdef PNG_USE_GLOBAL_ARRAYS
+PNG_EXPORT_VAR (const char) png_libpng_ver[18];
+  /* need room for 99.99.99beta99z*/
+#else
+#ifdef png_libpng_ver
+#undef png_libpng_ver
+#endif
+#define png_libpng_ver png_get_header_ver(NULL)
+#endif
+
+#ifdef PNG_USE_GLOBAL_ARRAYS
+/* This was removed in version 1.0.5c */
+/* Structures to facilitate easy interlacing.  See png.c for more details */
+PNG_EXPORT_VAR (const int FARDATA) png_pass_start[7];
+PNG_EXPORT_VAR (const int FARDATA) png_pass_inc[7];
+PNG_EXPORT_VAR (const int FARDATA) png_pass_ystart[7];
+PNG_EXPORT_VAR (const int FARDATA) png_pass_yinc[7];
+PNG_EXPORT_VAR (const int FARDATA) png_pass_mask[7];
+PNG_EXPORT_VAR (const int FARDATA) png_pass_dsp_mask[7];
+#ifdef PNG_HAVE_ASSEMBLER_COMBINE_ROW
+PNG_EXPORT_VAR (const int FARDATA) png_pass_width[7];
+#endif
+/* This isn't currently used.  If you need it, see png.c for more details.
+PNG_EXPORT_VAR (const int FARDATA) png_pass_height[7];
+*/
+#endif
+
+#endif /* PNG_NO_EXTERN */
+
+/* Three color definitions.  The order of the red, green, and blue, (and the
+ * exact size) is not important, although the size of the fields need to
+ * be png_byte or png_uint_16 (as defined below).
+ */
+typedef struct png_color_struct
+{
+   png_byte red;
+   png_byte green;
+   png_byte blue;
+} png_color;
+typedef png_color FAR * png_colorp;
+typedef png_color FAR * FAR * png_colorpp;
+
+typedef struct png_color_16_struct
+{
+   png_byte index;    /* used for palette files */
+   png_uint_16 red;   /* for use in red green blue files */
+   png_uint_16 green;
+   png_uint_16 blue;
+   png_uint_16 gray;  /* for use in grayscale files */
+} png_color_16;
+typedef png_color_16 FAR * png_color_16p;
+typedef png_color_16 FAR * FAR * png_color_16pp;
+
+typedef struct png_color_8_struct
+{
+   png_byte red;   /* for use in red green blue files */
+   png_byte green;
+   png_byte blue;
+   png_byte gray;  /* for use in grayscale files */
+   png_byte alpha; /* for alpha channel files */
+} png_color_8;
+typedef png_color_8 FAR * png_color_8p;
+typedef png_color_8 FAR * FAR * png_color_8pp;
+
+/*
+ * The following two structures are used for the in-core representation
+ * of sPLT chunks.
+ */
+typedef struct png_sPLT_entry_struct
+{
+   png_uint_16 red;
+   png_uint_16 green;
+   png_uint_16 blue;
+   png_uint_16 alpha;
+   png_uint_16 frequency;
+} png_sPLT_entry;
+typedef png_sPLT_entry FAR * png_sPLT_entryp;
+typedef png_sPLT_entry FAR * FAR * png_sPLT_entrypp;
+
+/*  When the depth of the sPLT palette is 8 bits, the color and alpha samples
+ *  occupy the LSB of their respective members, and the MSB of each member
+ *  is zero-filled.  The frequency member always occupies the full 16 bits.
+ */
+
+typedef struct png_sPLT_struct
+{
+   png_charp name;           /* palette name */
+   png_byte depth;           /* depth of palette samples */
+   png_sPLT_entryp entries;  /* palette entries */
+   png_int_32 nentries;      /* number of palette entries */
+} png_sPLT_t;
+typedef png_sPLT_t FAR * png_sPLT_tp;
+typedef png_sPLT_t FAR * FAR * png_sPLT_tpp;
+
+#ifdef PNG_TEXT_SUPPORTED
+/* 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 zero-terminated C string.  The "text", "lang", and
+ * "lang_key" fields can be regular C strings, empty strings, or NULL pointers.
+ * However, the * structure returned by png_get_text() will always contain
+ * regular zero-terminated C strings (possibly empty), never NULL pointers,
+ * so they can be safely used in printf() and other string-handling functions.
+ */
+typedef struct png_text_struct
+{
+   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 text;         /* comment, may be an empty string (ie "")
+                              or a NULL pointer */
+   png_size_t text_length; /* length of the text string */
+#ifdef PNG_iTXt_SUPPORTED
+   png_size_t itxt_length; /* length of the itxt string */
+   png_charp lang;         /* language code, 0-79 characters
+                              or a NULL pointer */
+   png_charp lang_key;     /* keyword translated UTF-8 string, 0 or more
+                              chars or a NULL pointer */
+#endif
+} png_text;
+typedef png_text FAR * png_textp;
+typedef png_text FAR * FAR * png_textpp;
+#endif
+
+/* Supported compression types for text in PNG files (tEXt, and zTXt).
+ * The values of the PNG_TEXT_COMPRESSION_ defines should NOT be changed. */
+#define PNG_TEXT_COMPRESSION_NONE_WR -3
+#define PNG_TEXT_COMPRESSION_zTXt_WR -2
+#define PNG_TEXT_COMPRESSION_NONE    -1
+#define PNG_TEXT_COMPRESSION_zTXt     0
+#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
+ * is no portable way to convert to either of these structures, as far
+ * as I know.  If you know of a portable way, send it to me.  As a side
+ * note - PNG has always been Year 2000 compliant!
+ */
+typedef struct png_time_struct
+{
+   png_uint_16 year; /* full year, as in, 1995 */
+   png_byte month;   /* month of year, 1 - 12 */
+   png_byte day;     /* day of month, 1 - 31 */
+   png_byte hour;    /* hour of day, 0 - 23 */
+   png_byte minute;  /* minute of hour, 0 - 59 */
+   png_byte second;  /* second of minute, 0 - 60 (for leap seconds) */
+} png_time;
+typedef png_time FAR * png_timep;
+typedef png_time FAR * FAR * png_timepp;
+
+#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+/* png_unknown_chunk is a structure to hold queued chunks for which there is
+ * no specific support.  The idea is that we can use this to queue
+ * up private chunks for output even though the library doesn't actually
+ * know about their semantics.
+ */
+typedef struct png_unknown_chunk_t
+{
+    png_byte name[5];
+    png_byte *data;
+    png_size_t size;
+
+    /* libpng-using applications should NOT directly modify this byte. */
+    png_byte location; /* mode of operation at read time */
+}
+png_unknown_chunk;
+typedef png_unknown_chunk FAR * png_unknown_chunkp;
+typedef png_unknown_chunk FAR * FAR * png_unknown_chunkpp;
+#endif
+
+/* png_info is a structure that holds the information in a PNG file so
+ * that the application can find out the characteristics of the image.
+ * If you are reading the file, this structure will tell you what is
+ * in the PNG file.  If you are writing the file, fill in the information
+ * you want to put into the PNG file, then call png_write_info().
+ * The names chosen should be very close to the PNG specification, so
+ * consult that document for information about the meaning of each field.
+ *
+ * With libpng < 0.95, it was only possible to directly set and read the
+ * the values in the png_info_struct, which meant that the contents and
+ * order of the values had to remain fixed.  With libpng 0.95 and later,
+ * however, there are now functions that abstract the contents of
+ * png_info_struct from the application, so this makes it easier to use
+ * libpng with dynamic libraries, and even makes it possible to use
+ * libraries that don't have all of the libpng ancillary chunk-handing
+ * functionality.
+ *
+ * In any case, the order of the parameters in png_info_struct should NOT
+ * be changed for as long as possible to keep compatibility with applications
+ * 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, trans, text,
+ * pcal_purpose, pcal_units, pcal_params, hist, iccp_name, iccp_profile,
+ * splt_palettes, scal_unit, row_pointers, and unknowns.   By default, these
+ * are automatically freed when the info structure is deallocated, if they were
+ * allocated internally by libpng.  This behavior can be changed by means
+ * of the png_data_freer() function.
+ *
+ * More allocation details: all the chunk-reading functions that
+ * change these members go through the corresponding png_set_*
+ * functions.  A function to clear these members is available: see
+ * png_free_data().  The png_set_* functions do not depend on being
+ * able to point info structure members to any of the storage they are
+ * passed (they make their own copies), EXCEPT that the png_set_text
+ * functions use the same storage passed to them in the text_ptr or
+ * itxt_ptr structure argument, and the png_set_rows and png_set_unknowns
+ * functions do not make their own copies.
+ */
+typedef struct png_info_struct
+{
+   /* the following are necessary for every PNG file */
+   png_uint_32 width;       /* width of image in pixels (from IHDR) */
+   png_uint_32 height;      /* height of image in pixels (from IHDR) */
+   png_uint_32 valid;       /* valid chunk data (see PNG_INFO_ below) */
+   png_uint_32 rowbytes;    /* bytes needed to hold an untransformed row */
+   png_colorp palette;      /* array of color values (valid & PNG_INFO_PLTE) */
+   png_uint_16 num_palette; /* number of color entries in "palette" (PLTE) */
+   png_uint_16 num_trans;   /* number of transparent palette color (tRNS) */
+   png_byte bit_depth;      /* 1, 2, 4, 8, or 16 bits/channel (from IHDR) */
+   png_byte color_type;     /* see PNG_COLOR_TYPE_ below (from IHDR) */
+   /* The following three should have been named *_method not *_type */
+   png_byte compression_type; /* must be PNG_COMPRESSION_TYPE_BASE (IHDR) */
+   png_byte filter_type;    /* must be PNG_FILTER_TYPE_BASE (from IHDR) */
+   png_byte interlace_type; /* One of PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */
+
+   /* The following is informational only on read, and not used on writes. */
+   png_byte channels;       /* number of data channels per pixel (1, 2, 3, 4)*/
+   png_byte pixel_depth;    /* number of bits per pixel */
+   png_byte spare_byte;     /* to align the data, and for future use */
+   png_byte signature[8];   /* magic bytes read by libpng from start of file */
+
+   /* The rest of the data is optional.  If you are reading, check the
+    * valid field to see if the information in these are valid.  If you
+    * are writing, set the valid field to those chunks you want written,
+    * and initialize the appropriate fields below.
+    */
+
+#if defined(PNG_gAMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
+   /* The gAMA chunk describes the gamma characteristics of the system
+    * on which the image was created, normally in the range [1.0, 2.5].
+    * Data is valid if (valid & PNG_INFO_gAMA) is non-zero.
+    */
+   float gamma; /* gamma value of image, if (valid & PNG_INFO_gAMA) */
+#endif
+
+#if defined(PNG_sRGB_SUPPORTED)
+    /* GR-P, 0.96a */
+    /* Data valid if (valid & PNG_INFO_sRGB) non-zero. */
+   png_byte srgb_intent; /* sRGB rendering intent [0, 1, 2, or 3] */
+#endif
+
+#if defined(PNG_TEXT_SUPPORTED)
+   /* The tEXt, and zTXt chunks contain human-readable textual data in
+    * uncompressed, compressed, and optionally compressed forms, respectively.
+    * The data in "text" is an array of pointers to uncompressed,
+    * null-terminated C strings. Each chunk has a keyword that describes the
+    * textual data contained in that chunk.  Keywords are not required to be
+    * unique, and the text string may be empty.  Any number of text chunks may
+    * be in an image.
+    */
+   int num_text; /* number of comments read/to write */
+   int max_text; /* current size of text array */
+   png_textp text; /* array of comments read/to write */
+#endif /* PNG_TEXT_SUPPORTED */
+
+#if defined(PNG_tIME_SUPPORTED)
+   /* The tIME chunk holds the last time the displayed image data was
+    * modified.  See the png_time struct for the contents of this struct.
+    */
+   png_time mod_time;
+#endif
+
+#if defined(PNG_sBIT_SUPPORTED)
+   /* The sBIT chunk specifies the number of significant high-order bits
+    * in the pixel data.  Values are in the range [1, bit_depth], and are
+    * only specified for the channels in the pixel data.  The contents of
+    * the low-order bits is not specified.  Data is valid if
+    * (valid & PNG_INFO_sBIT) is non-zero.
+    */
+   png_color_8 sig_bit; /* significant bits in color channels */
+#endif
+
+#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_EXPAND_SUPPORTED) || \
+defined(PNG_READ_BACKGROUND_SUPPORTED)
+   /* The tRNS chunk supplies transparency data for paletted images and
+    * other image types that don't need a full alpha channel.  There are
+    * "num_trans" transparency values for a paletted image, stored in the
+    * same order as the palette colors, starting from index 0.  Values
+    * for the data are in the range [0, 255], ranging from fully transparent
+    * to fully opaque, respectively.  For non-paletted images, there is a
+    * single color specified that should be treated as fully transparent.
+    * Data is valid if (valid & PNG_INFO_tRNS) is non-zero.
+    */
+   png_bytep trans; /* transparent values for paletted image */
+   png_color_16 trans_values; /* transparent color for non-palette image */
+#endif
+
+#if defined(PNG_bKGD_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+   /* The bKGD chunk gives the suggested image background color if the
+    * display program does not have its own background color and the image
+    * is needs to composited onto a background before display.  The colors
+    * in "background" are normally in the same color space/depth as the
+    * pixel data.  Data is valid if (valid & PNG_INFO_bKGD) is non-zero.
+    */
+   png_color_16 background;
+#endif
+
+#if defined(PNG_oFFs_SUPPORTED)
+   /* The oFFs chunk gives the offset in "offset_unit_type" units rightwards
+    * and downwards from the top-left corner of the display, page, or other
+    * application-specific co-ordinate space.  See the PNG_OFFSET_ defines
+    * below for the unit types.  Valid if (valid & PNG_INFO_oFFs) non-zero.
+    */
+   png_int_32 x_offset; /* x offset on page */
+   png_int_32 y_offset; /* y offset on page */
+   png_byte offset_unit_type; /* offset units type */
+#endif
+
+#if defined(PNG_pHYs_SUPPORTED)
+   /* The pHYs chunk gives the physical pixel density of the image for
+    * display or printing in "phys_unit_type" units (see PNG_RESOLUTION_
+    * defines below).  Data is valid if (valid & PNG_INFO_pHYs) is non-zero.
+    */
+   png_uint_32 x_pixels_per_unit; /* horizontal pixel density */
+   png_uint_32 y_pixels_per_unit; /* vertical pixel density */
+   png_byte phys_unit_type; /* resolution type (see PNG_RESOLUTION_ below) */
+#endif
+
+#if defined(PNG_hIST_SUPPORTED)
+   /* The hIST chunk contains the relative frequency or importance of the
+    * various palette entries, so that a viewer can intelligently select a
+    * reduced-color palette, if required.  Data is an array of "num_palette"
+    * values in the range [0,65535]. Data valid if (valid & PNG_INFO_hIST)
+    * is non-zero.
+    */
+   png_uint_16p hist;
+#endif
+
+#ifdef PNG_cHRM_SUPPORTED
+   /* The cHRM chunk describes the CIE color characteristics of the monitor
+    * on which the PNG was created.  This data allows the viewer to do gamut
+    * mapping of the input image to ensure that the viewer sees the same
+    * colors in the image as the creator.  Values are in the range
+    * [0.0, 0.8].  Data valid if (valid & PNG_INFO_cHRM) non-zero.
+    */
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   float x_white;
+   float y_white;
+   float x_red;
+   float y_red;
+   float x_green;
+   float y_green;
+   float x_blue;
+   float y_blue;
+#endif
+#endif
+
+#if defined(PNG_pCAL_SUPPORTED)
+   /* The pCAL chunk describes a transformation between the stored pixel
+    * values and original physical data values used to create the image.
+    * The integer range [0, 2^bit_depth - 1] maps to the floating-point
+    * range given by [pcal_X0, pcal_X1], and are further transformed by a
+    * (possibly non-linear) transformation function given by "pcal_type"
+    * and "pcal_params" into "pcal_units".  Please see the PNG_EQUATION_
+    * defines below, and the PNG-Group's PNG extensions document for a
+    * complete description of the transformations and how they should be
+    * implemented, and for a description of the ASCII parameter strings.
+    * Data values are valid if (valid & PNG_INFO_pCAL) non-zero.
+    */
+   png_charp pcal_purpose;  /* pCAL chunk description string */
+   png_int_32 pcal_X0;      /* minimum value */
+   png_int_32 pcal_X1;      /* maximum value */
+   png_charp pcal_units;    /* Latin-1 string giving physical units */
+   png_charpp pcal_params;  /* ASCII strings containing parameter values */
+   png_byte pcal_type;      /* equation type (see PNG_EQUATION_ below) */
+   png_byte pcal_nparams;   /* number of parameters given in pcal_params */
+#endif
+
+/* New members added in libpng-1.0.6 */
+#ifdef PNG_FREE_ME_SUPPORTED
+   png_uint_32 free_me;     /* flags items libpng is responsible for freeing */
+#endif
+
+#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+   /* storage for unknown chunks that the library doesn't recognize. */
+   png_unknown_chunkp unknown_chunks;
+   png_size_t unknown_chunks_num;
+#endif
+
+#if defined(PNG_iCCP_SUPPORTED)
+   /* iCCP chunk data. */
+   png_charp iccp_name;     /* profile name */
+   png_charp iccp_profile;  /* International Color Consortium profile data */
+                            /* Note to maintainer: should be png_bytep */
+   png_uint_32 iccp_proflen;  /* ICC profile data length */
+   png_byte iccp_compression; /* Always zero */
+#endif
+
+#if defined(PNG_sPLT_SUPPORTED)
+   /* data on sPLT chunks (there may be more than one). */
+   png_sPLT_tp splt_palettes;
+   png_uint_32 splt_palettes_num;
+#endif
+
+#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
+    * 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_byte scal_unit;         /* unit of physical scale */
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   double scal_pixel_width;    /* width of one pixel */
+   double scal_pixel_height;   /* height of one pixel */
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   png_charp scal_s_width;     /* string containing height */
+   png_charp scal_s_height;    /* string containing width */
+#endif
+#endif
+
+#if defined(PNG_INFO_IMAGE_SUPPORTED)
+   /* Memory has been allocated if (valid & PNG_ALLOCATED_INFO_ROWS) non-zero */
+   /* Data valid if (valid & PNG_INFO_IDAT) non-zero */
+   png_bytepp row_pointers;        /* the image bits */
+#endif
+
+#if defined(PNG_FIXED_POINT_SUPPORTED) && defined(PNG_gAMA_SUPPORTED)
+   png_fixed_point int_gamma; /* gamma of image, if (valid & PNG_INFO_gAMA) */
+#endif
+
+#if defined(PNG_cHRM_SUPPORTED) && defined(PNG_FIXED_POINT_SUPPORTED)
+   png_fixed_point int_x_white;
+   png_fixed_point int_y_white;
+   png_fixed_point int_x_red;
+   png_fixed_point int_y_red;
+   png_fixed_point int_x_green;
+   png_fixed_point int_y_green;
+   png_fixed_point int_x_blue;
+   png_fixed_point int_y_blue;
+#endif
+
+} png_info;
+
+typedef png_info FAR * png_infop;
+typedef png_info FAR * FAR * png_infopp;
+
+/* Maximum positive integer used in PNG is (2^31)-1 */
+#define PNG_MAX_UINT ((png_uint_32)0x7fffffffL)
+
+/* These describe the color_type field in png_info. */
+/* color type masks */
+#define PNG_COLOR_MASK_PALETTE    1
+#define PNG_COLOR_MASK_COLOR      2
+#define PNG_COLOR_MASK_ALPHA      4
+
+/* color types.  Note that not all combinations are legal */
+#define PNG_COLOR_TYPE_GRAY 0
+#define PNG_COLOR_TYPE_PALETTE  (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE)
+#define PNG_COLOR_TYPE_RGB        (PNG_COLOR_MASK_COLOR)
+#define PNG_COLOR_TYPE_RGB_ALPHA  (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA)
+#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA)
+/* aliases */
+#define PNG_COLOR_TYPE_RGBA  PNG_COLOR_TYPE_RGB_ALPHA
+#define PNG_COLOR_TYPE_GA  PNG_COLOR_TYPE_GRAY_ALPHA
+
+/* This is for compression type. PNG 1.0-1.2 only define the single type. */
+#define PNG_COMPRESSION_TYPE_BASE 0 /* Deflate method 8, 32K window */
+#define PNG_COMPRESSION_TYPE_DEFAULT PNG_COMPRESSION_TYPE_BASE
+
+/* This is for filter type. PNG 1.0-1.2 only define the single type. */
+#define PNG_FILTER_TYPE_BASE      0 /* Single row per-byte filtering */
+#define PNG_INTRAPIXEL_DIFFERENCING 64 /* Used only in MNG datastreams */
+#define PNG_FILTER_TYPE_DEFAULT   PNG_FILTER_TYPE_BASE
+
+/* These are for the interlacing type.  These values should NOT be changed. */
+#define PNG_INTERLACE_NONE        0 /* Non-interlaced image */
+#define PNG_INTERLACE_ADAM7       1 /* Adam7 interlacing */
+#define PNG_INTERLACE_LAST        2 /* Not a valid value */
+
+/* These are for the oFFs chunk.  These values should NOT be changed. */
+#define PNG_OFFSET_PIXEL          0 /* Offset in pixels */
+#define PNG_OFFSET_MICROMETER     1 /* Offset in micrometers (1/10^6 meter) */
+#define PNG_OFFSET_LAST           2 /* Not a valid value */
+
+/* These are for the pCAL chunk.  These values should NOT be changed. */
+#define PNG_EQUATION_LINEAR       0 /* Linear transformation */
+#define PNG_EQUATION_BASE_E       1 /* Exponential base e transform */
+#define PNG_EQUATION_ARBITRARY    2 /* Arbitrary base exponential transform */
+#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 */
+#define PNG_RESOLUTION_LAST       2 /* Not a valid value */
+
+/* These are for the sRGB chunk.  These values should NOT be changed. */
+#define PNG_sRGB_INTENT_PERCEPTUAL 0
+#define PNG_sRGB_INTENT_RELATIVE   1
+#define PNG_sRGB_INTENT_SATURATION 2
+#define PNG_sRGB_INTENT_ABSOLUTE   3
+#define PNG_sRGB_INTENT_LAST       4 /* Not a valid value */
+
+/* This is for text chunks */
+#define PNG_KEYWORD_MAX_LENGTH     79
+
+/* Maximum number of entries in PLTE/sPLT/tRNS arrays */
+#define PNG_MAX_PALETTE_LENGTH     256
+
+/* These determine if an ancillary chunk's data has been successfully read
+ * from the PNG header, or if the application has filled in the corresponding
+ * data in the info_struct to be written into the output file.  The values
+ * of the PNG_INFO_<chunk> defines should NOT be changed.
+ */
+#define PNG_INFO_gAMA 0x0001
+#define PNG_INFO_sBIT 0x0002
+#define PNG_INFO_cHRM 0x0004
+#define PNG_INFO_PLTE 0x0008
+#define PNG_INFO_tRNS 0x0010
+#define PNG_INFO_bKGD 0x0020
+#define PNG_INFO_hIST 0x0040
+#define PNG_INFO_pHYs 0x0080
+#define PNG_INFO_oFFs 0x0100
+#define PNG_INFO_tIME 0x0200
+#define PNG_INFO_pCAL 0x0400
+#define PNG_INFO_sRGB 0x0800   /* GR-P, 0.96a */
+#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 0x8000L  /* ESR, 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
+ * the routines for other purposes.
+ */
+typedef struct png_row_info_struct
+{
+   png_uint_32 width; /* width of row */
+   png_uint_32 rowbytes; /* number of bytes in row */
+   png_byte color_type; /* color type of row */
+   png_byte bit_depth; /* bit depth of row */
+   png_byte channels; /* number of channels (1, 2, 3, or 4) */
+   png_byte pixel_depth; /* bits per pixel (depth * channels) */
+} png_row_info;
+
+typedef png_row_info FAR * png_row_infop;
+typedef png_row_info FAR * FAR * png_row_infopp;
+
+/* These are the function types for the I/O functions and for the functions
+ * that allow the user to override the default I/O functions with his or her
+ * own.  The png_error_ptr type should match that of user-supplied warning
+ * and error functions, while the png_rw_ptr type should match that of the
+ * user read/write data functions.
+ */
+typedef struct png_struct_def png_struct;
+typedef png_struct FAR * png_structp;
+
+typedef void (PNGAPI *png_error_ptr) PNGARG((png_structp, png_const_charp));
+typedef void (PNGAPI *png_rw_ptr) PNGARG((png_structp, png_bytep, png_size_t));
+typedef void (PNGAPI *png_flush_ptr) PNGARG((png_structp));
+typedef void (PNGAPI *png_read_status_ptr) PNGARG((png_structp, png_uint_32,
+   int));
+typedef void (PNGAPI *png_write_status_ptr) PNGARG((png_structp, png_uint_32,
+   int));
+
+#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
+typedef void (PNGAPI *png_progressive_info_ptr) PNGARG((png_structp, png_infop));
+typedef void (PNGAPI *png_progressive_end_ptr) PNGARG((png_structp, png_infop));
+typedef void (PNGAPI *png_progressive_row_ptr) PNGARG((png_structp, png_bytep,
+   png_uint_32, int));
+#endif
+
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
+    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
+    defined(PNG_LEGACY_SUPPORTED)
+typedef void (PNGAPI *png_user_transform_ptr) PNGARG((png_structp,
+    png_row_infop, png_bytep));
+#endif
+
+#if defined(PNG_USER_CHUNKS_SUPPORTED)
+typedef int (PNGAPI *png_user_chunk_ptr) PNGARG((png_structp, png_unknown_chunkp));
+#endif
+#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+typedef void (PNGAPI *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   0x0400    /* read and write */
+#define PNG_TRANSFORM_STRIP_FILLER   0x0800    /* WRITE only */
+
+/* Flags for MNG supported features */
+#define PNG_FLAG_MNG_EMPTY_PLTE     0x01
+#define PNG_FLAG_MNG_FILTER_64      0x04
+#define PNG_ALL_MNG_FEATURES        0x05
+
+typedef png_voidp (*png_malloc_ptr) PNGARG((png_structp, png_size_t));
+typedef void (*png_free_ptr) PNGARG((png_structp, png_voidp));
+
+/* The structure that holds the information to read and write PNG files.
+ * The only people who need to care about what is inside of this are the
+ * people who will be modifying the library for their own special needs.
+ * It should NOT be accessed directly by an application, except to store
+ * the jmp_buf.
+ */
+
+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 */
+   png_rw_ptr write_data_fn;  /* function for writing output data */
+   png_rw_ptr read_data_fn;   /* function for reading input data */
+   png_voidp io_ptr;          /* ptr to application struct for I/O functions*/
+
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
+   png_user_transform_ptr read_user_transform_fn; /* user read transform */
+#endif
+
+#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
+   png_user_transform_ptr write_user_transform_fn; /* user write transform */
+#endif
+
+/* These were added in libpng-1.0.2 */
+#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
+    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
+   png_voidp user_transform_ptr; /* user supplied struct for user transform */
+   png_byte user_transform_depth;    /* bit depth of user transformed pixels */
+   png_byte user_transform_channels; /* channels in user transformed pixels */
+#endif
+#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 */
+
+   z_stream zstream;          /* pointer to decompression structure (below) */
+   png_bytep zbuf;            /* buffer for zlib */
+   png_size_t zbuf_size;      /* size of zbuf */
+   int zlib_level;            /* holds zlib compression level */
+   int zlib_method;           /* holds zlib compression method */
+   int zlib_window_bits;      /* holds zlib compression window bits */
+   int zlib_mem_level;        /* holds zlib compression memory level */
+   int zlib_strategy;         /* holds zlib compression strategy */
+
+   png_uint_32 width;         /* width of image in pixels */
+   png_uint_32 height;        /* height of image in pixels */
+   png_uint_32 num_rows;      /* number of rows in current pass */
+   png_uint_32 usr_width;     /* width of row at start of write */
+   png_uint_32 rowbytes;      /* size of row in bytes */
+   png_uint_32 irowbytes;     /* size of current interlaced row in bytes */
+   png_uint_32 iwidth;        /* width of current interlaced row in pixels */
+   png_uint_32 row_number;    /* current row in interlace pass */
+   png_bytep prev_row;        /* buffer to save previous (unfiltered) row */
+   png_bytep row_buf;         /* buffer to save current (unfiltered) row */
+   png_bytep sub_row;         /* buffer to save "sub" row when filtering */
+   png_bytep up_row;          /* buffer to save "up" row when filtering */
+   png_bytep avg_row;         /* buffer to save "avg" row when filtering */
+   png_bytep paeth_row;       /* buffer to save "Paeth" row when filtering */
+   png_row_info row_info;     /* used for transformation routines */
+
+   png_uint_32 idat_size;     /* current IDAT size for read */
+   png_uint_32 crc;           /* current chunk CRC value */
+   png_colorp palette;        /* palette from the input file */
+   png_uint_16 num_palette;   /* number of color entries in palette */
+   png_uint_16 num_trans;     /* number of transparency values */
+   png_byte chunk_name[5];    /* null-terminated name of current chunk */
+   png_byte compression;      /* file compression type (always 0) */
+   png_byte filter;           /* file filter type (always 0) */
+   png_byte interlaced;       /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */
+   png_byte pass;             /* current interlace pass (0 - 6) */
+   png_byte do_filter;        /* row filter flags (see PNG_FILTER_ below ) */
+   png_byte color_type;       /* color type of file */
+   png_byte bit_depth;        /* bit depth of file */
+   png_byte usr_bit_depth;    /* bit depth of users row */
+   png_byte pixel_depth;      /* number of bits per pixel */
+   png_byte channels;         /* number of channels in file */
+   png_byte usr_channels;     /* channels at start of write */
+   png_byte sig_bytes;        /* magic bytes read/written from start of file */
+
+#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
+#ifdef PNG_LEGACY_SUPPORTED
+   png_byte filler;           /* filler byte for pixel expansion */
+#else
+   png_uint_16 filler;           /* filler bytes for pixel expansion */
+#endif
+#endif
+
+#if defined(PNG_bKGD_SUPPORTED)
+   png_byte background_gamma_type;
+#  ifdef PNG_FLOATING_POINT_SUPPORTED
+   float background_gamma;
+#  endif
+   png_color_16 background;   /* background color in screen gamma space */
+#  if defined(PNG_READ_GAMMA_SUPPORTED)
+     png_color_16 background_1; /* background normalized to gamma 1.0 */
+#  endif /* PNG_READ_GAMMA && PNG_bKGD_SUPPORTED */
+#endif /* PNG_bKGD_SUPPORTED */
+
+#if defined(PNG_WRITE_FLUSH_SUPPORTED)
+   png_flush_ptr output_flush_fn;/* Function for flushing output */
+   png_uint_32 flush_dist;    /* how many rows apart to flush, 0 - no flush */
+   png_uint_32 flush_rows;    /* number of rows written since last flush */
+#endif
+
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+   int gamma_shift;      /* number of "insignificant" bits 16-bit gamma */
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   float gamma;          /* file gamma value */
+   float screen_gamma;   /* screen gamma value (display_exponent) */
+#endif
+#endif
+
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+   png_bytep gamma_table;     /* gamma table for 8-bit depth files */
+   png_bytep gamma_from_1;    /* converts from 1.0 to screen */
+   png_bytep gamma_to_1;      /* converts from file to 1.0 */
+   png_uint_16pp gamma_16_table; /* gamma table for 16-bit depth files */
+   png_uint_16pp gamma_16_from_1; /* converts from 1.0 to screen */
+   png_uint_16pp gamma_16_to_1; /* converts from file to 1.0 */
+#endif
+
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED)
+   png_color_8 sig_bit;       /* significant bits in each available channel */
+#endif
+
+#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
+   png_color_8 shift;         /* shift for significant bit tranformation */
+#endif
+
+#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \
+ || defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+   png_bytep trans;           /* transparency values for paletted files */
+   png_color_16 trans_values; /* transparency values for non-paletted files */
+#endif
+
+   png_read_status_ptr read_row_fn;   /* called after each row is decoded */
+   png_write_status_ptr write_row_fn; /* called after each row is encoded */
+#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
+   png_progressive_info_ptr info_fn; /* called after header data fully read */
+   png_progressive_row_ptr row_fn;   /* called after each prog. row is decoded */
+   png_progressive_end_ptr end_fn;   /* called after image is complete */
+   png_bytep save_buffer_ptr;        /* current location in save_buffer */
+   png_bytep save_buffer;            /* buffer for previously read data */
+   png_bytep current_buffer_ptr;     /* current location in current_buffer */
+   png_bytep current_buffer;         /* buffer for recently used data */
+   png_uint_32 push_length;          /* size of current input chunk */
+   png_uint_32 skip_length;          /* bytes to skip in input data */
+   png_size_t save_buffer_size;      /* amount of data now in save_buffer */
+   png_size_t save_buffer_max;       /* total size of save_buffer */
+   png_size_t buffer_size;           /* total amount of available input data */
+   png_size_t current_buffer_size;   /* amount of data now in current_buffer */
+   int process_mode;                 /* what push library is currently doing */
+   int cur_palette;                  /* current push library palette index */
+
+#  if defined(PNG_TEXT_SUPPORTED)
+     png_size_t current_text_size;   /* current size of text input data */
+     png_size_t current_text_left;   /* how much text left to read in input */
+     png_charp current_text;         /* current text chunk buffer */
+     png_charp current_text_ptr;     /* current location in current_text */
+#  endif /* PNG_PROGRESSIVE_READ_SUPPORTED && PNG_TEXT_SUPPORTED */
+
+#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
+
+#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
+/* for the Borland special 64K segment handler */
+   png_bytepp offset_table_ptr;
+   png_bytep offset_table;
+   png_uint_16 offset_table_number;
+   png_uint_16 offset_table_count;
+   png_uint_16 offset_table_count_free;
+#endif
+
+#if defined(PNG_READ_DITHER_SUPPORTED)
+   png_bytep palette_lookup;         /* lookup table for dithering */
+   png_bytep dither_index;           /* index translation for palette files */
+#endif
+
+#if defined(PNG_READ_DITHER_SUPPORTED) || defined(PNG_hIST_SUPPORTED)
+   png_uint_16p hist;                /* histogram */
+#endif
+
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+   png_byte heuristic_method;        /* heuristic for row filter selection */
+   png_byte num_prev_filters;        /* number of weights for previous rows */
+   png_bytep prev_filters;           /* filter type(s) of previous row(s) */
+   png_uint_16p filter_weights;      /* weight(s) for previous line(s) */
+   png_uint_16p inv_filter_weights;  /* 1/weight(s) for previous line(s) */
+   png_uint_16p filter_costs;        /* relative filter calculation cost */
+   png_uint_16p inv_filter_costs;    /* 1/relative filter calculation cost */
+#endif
+
+#if defined(PNG_TIME_RFC1123_SUPPORTED)
+   png_charp time_buffer;            /* String to hold RFC 1123 time text */
+#endif
+
+/* New members added in libpng-1.0.6 */
+
+#ifdef PNG_FREE_ME_SUPPORTED
+   png_uint_32 free_me;       /* flags items libpng is responsible for freeing */
+#endif
+
+#if defined(PNG_USER_CHUNKS_SUPPORTED)
+   png_voidp user_chunk_ptr;
+   png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */
+#endif
+
+#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+   int num_chunk_list;
+   png_bytep chunk_list;
+#endif
+
+/* New members added in libpng-1.0.3 */
+#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+   png_byte rgb_to_gray_status;
+   /* These were changed from png_byte in libpng-1.0.6 */
+   png_uint_16 rgb_to_gray_red_coeff;
+   png_uint_16 rgb_to_gray_green_coeff;
+   png_uint_16 rgb_to_gray_blue_coeff;
+#endif
+
+/* New member added in libpng-1.0.4 (renamed in 1.0.9) */
+#if defined(PNG_MNG_FEATURES_SUPPORTED) || \
+    defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \
+    defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED)
+/* changed from png_byte to png_uint_32 at version 1.2.0 */
+   png_byte mng_features_permitted;
+#endif
+
+/* New member added in libpng-1.0.7 */
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+   png_fixed_point int_gamma;
+#endif
+
+/* New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 */
+#if defined(PNG_MNG_FEATURES_SUPPORTED)
+   png_byte filter_type;
+#endif
+
+#if defined(PNG_DEBUG) && defined(PNG_USE_PNGGCCRD)
+/* New member added in libpng-1.0.10, ifdef'ed out in 1.2.0 */
+   png_uint_32 row_buf_size;
+#endif
+
+/* New members added in libpng-1.2.0 */
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED)
+   png_byte     mmx_bitdepth_threshold;
+   png_uint_32  mmx_rowbytes_threshold;
+   png_uint_32  asm_flags;
+#endif
+
+/* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */
+#ifdef PNG_USER_MEM_SUPPORTED
+   png_voidp mem_ptr;                /* user supplied struct for mem functions */
+   png_malloc_ptr malloc_fn;         /* function for allocating memory */
+   png_free_ptr free_fn;             /* function for freeing memory */
+#endif
+
+};
+
+
+/* This prevents a compiler error in png_get_copyright() in png.c if png.c
+   and png.h are both at version 1.0.12
+ */
+typedef png_structp version_1_0_12;
+
+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 description of the use of each function.
+ */
+
+/* Returns the version number of the library */
+extern PNG_EXPORT(png_uint_32,png_access_version_number) PNGARG((void));
+
+/* Tell lib we have already handled the first <num_bytes> magic bytes.
+ * Handling more than 8 bytes from the beginning of the file is an error.
+ */
+extern PNG_EXPORT(void,png_set_sig_bytes) PNGARG((png_structp png_ptr,
+   int num_bytes));
+
+/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a
+ * PNG file.  Returns zero if the supplied bytes match the 8-byte PNG
+ * signature, and non-zero otherwise.  Having num_to_check == 0 or
+ * start > 7 will always fail (ie return non-zero).
+ */
+extern PNG_EXPORT(int,png_sig_cmp) PNGARG((png_bytep sig, png_size_t start,
+   png_size_t num_to_check));
+
+/* Simple signature checking function.  This is the same as calling
+ * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n).
+ */
+extern PNG_EXPORT(int,png_check_sig) PNGARG((png_bytep sig, int num));
+
+/* Allocate and initialize png_ptr struct for reading, and any other memory. */
+extern PNG_EXPORT(png_structp,png_create_read_struct)
+   PNGARG((png_const_charp user_png_ver, png_voidp error_ptr,
+   png_error_ptr error_fn, png_error_ptr warn_fn));
+
+/* Allocate and initialize png_ptr struct for writing, and any other memory */
+extern PNG_EXPORT(png_structp,png_create_write_struct)
+   PNGARG((png_const_charp user_png_ver, png_voidp error_ptr,
+   png_error_ptr error_fn, png_error_ptr warn_fn));
+
+extern PNG_EXPORT(png_uint_32,png_get_compression_buffer_size)
+   PNGARG((png_structp png_ptr));
+
+extern PNG_EXPORT(void,png_set_compression_buffer_size)
+   PNGARG((png_structp png_ptr, png_uint_32 size));
+
+/* Reset the compression stream */
+extern PNG_EXPORT(int,png_reset_zstream) PNGARG((png_structp png_ptr));
+
+/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */
+#ifdef PNG_USER_MEM_SUPPORTED
+extern PNG_EXPORT(png_structp,png_create_read_struct_2)
+   PNGARG((png_const_charp user_png_ver, png_voidp error_ptr,
+   png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
+   png_malloc_ptr malloc_fn, png_free_ptr free_fn));
+extern PNG_EXPORT(png_structp,png_create_write_struct_2)
+   PNGARG((png_const_charp user_png_ver, png_voidp error_ptr,
+   png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
+   png_malloc_ptr malloc_fn, png_free_ptr free_fn));
+#endif
+
+/* Write a PNG chunk - size, type, (optional) data, CRC. */
+extern PNG_EXPORT(void,png_write_chunk) PNGARG((png_structp png_ptr,
+   png_bytep chunk_name, png_bytep data, png_size_t length));
+
+/* Write the start of a PNG chunk - length and chunk name. */
+extern PNG_EXPORT(void,png_write_chunk_start) PNGARG((png_structp png_ptr,
+   png_bytep chunk_name, png_uint_32 length));
+
+/* Write the data of a PNG chunk started with png_write_chunk_start(). */
+extern PNG_EXPORT(void,png_write_chunk_data) PNGARG((png_structp png_ptr,
+   png_bytep data, png_size_t length));
+
+/* Finish a chunk started with png_write_chunk_start() (includes CRC). */
+extern PNG_EXPORT(void,png_write_chunk_end) PNGARG((png_structp png_ptr));
+
+/* Allocate and initialize the info structure */
+extern PNG_EXPORT(png_infop,png_create_info_struct)
+   PNGARG((png_structp png_ptr));
+
+/* Initialize the info structure (old interface - DEPRECATED) */
+extern PNG_EXPORT(void,png_info_init) PNGARG((png_infop info_ptr));
+#undef png_info_init
+#define png_info_init(info_ptr) png_info_init_3(&info_ptr, sizeof(png_info));
+extern PNG_EXPORT(void,png_info_init_3) PNGARG((png_infopp info_ptr,
+    png_size_t png_info_struct_size));
+
+/* Writes all the PNG information before the image. */
+extern PNG_EXPORT(void,png_write_info_before_PLTE) PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+extern PNG_EXPORT(void,png_write_info) PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+
+/* read the information before the actual image data. */
+extern PNG_EXPORT(void,png_read_info) PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+
+#if defined(PNG_TIME_RFC1123_SUPPORTED)
+extern PNG_EXPORT(png_charp,png_convert_to_rfc1123)
+   PNGARG((png_structp png_ptr, png_timep ptime));
+#endif
+
+#if !defined(_WIN32_WCE)
+/* "time.h" functions are not supported on WindowsCE */
+#if defined(PNG_WRITE_tIME_SUPPORTED)
+/* convert from a struct tm to png_time */
+extern PNG_EXPORT(void,png_convert_from_struct_tm) PNGARG((png_timep ptime,
+   struct tm FAR * ttime));
+
+/* convert from time_t to png_time.  Uses gmtime() */
+extern PNG_EXPORT(void,png_convert_from_time_t) PNGARG((png_timep ptime,
+   time_t ttime));
+#endif /* PNG_WRITE_tIME_SUPPORTED */
+#endif /* _WIN32_WCE */
+
+#if defined(PNG_READ_EXPAND_SUPPORTED)
+/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */
+extern PNG_EXPORT(void,png_set_expand) PNGARG((png_structp png_ptr));
+extern PNG_EXPORT(void,png_set_gray_1_2_4_to_8) PNGARG((png_structp png_ptr));
+extern PNG_EXPORT(void,png_set_palette_to_rgb) PNGARG((png_structp png_ptr));
+extern PNG_EXPORT(void,png_set_tRNS_to_alpha) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
+/* Use blue, green, red order for pixels. */
+extern PNG_EXPORT(void,png_set_bgr) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
+/* Expand the grayscale to 24-bit RGB if necessary. */
+extern PNG_EXPORT(void,png_set_gray_to_rgb) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+/* Reduce RGB to grayscale. */
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+extern PNG_EXPORT(void,png_set_rgb_to_gray) PNGARG((png_structp png_ptr,
+   int error_action, double red, double green ));
+#endif
+extern PNG_EXPORT(void,png_set_rgb_to_gray_fixed) PNGARG((png_structp png_ptr,
+   int error_action, png_fixed_point red, png_fixed_point green ));
+extern PNG_EXPORT(png_byte,png_get_rgb_to_gray_status) PNGARG((png_structp
+   png_ptr));
+#endif
+
+extern PNG_EXPORT(void,png_build_grayscale_palette) PNGARG((int bit_depth,
+   png_colorp palette));
+
+#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
+extern PNG_EXPORT(void,png_set_strip_alpha) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
+    defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
+extern PNG_EXPORT(void,png_set_swap_alpha) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
+    defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
+extern PNG_EXPORT(void,png_set_invert_alpha) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
+/* Add a filler byte to 24-bit RGB images. */
+extern PNG_EXPORT(void,png_set_filler) PNGARG((png_structp png_ptr,
+   png_uint_32 filler, int flags));
+/* The values of the PNG_FILLER_ defines should NOT be changed */
+#define PNG_FILLER_BEFORE 0
+#define PNG_FILLER_AFTER 1
+#endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */
+
+#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
+/* Swap bytes in 16-bit depth files. */
+extern PNG_EXPORT(void,png_set_swap) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
+/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */
+extern PNG_EXPORT(void,png_set_packing) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_PACKSWAP_SUPPORTED) || defined(PNG_WRITE_PACKSWAP_SUPPORTED)
+/* Swap packing order of pixels in bytes. */
+extern PNG_EXPORT(void,png_set_packswap) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
+/* Converts files to legal bit depths. */
+extern PNG_EXPORT(void,png_set_shift) PNGARG((png_structp png_ptr,
+   png_color_8p true_bits));
+#endif
+
+#if defined(PNG_READ_INTERLACING_SUPPORTED) || \
+    defined(PNG_WRITE_INTERLACING_SUPPORTED)
+/* Have the code handle the interlacing.  Returns the number of passes. */
+extern PNG_EXPORT(int,png_set_interlace_handling) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
+/* Invert monochrome files */
+extern PNG_EXPORT(void,png_set_invert_mono) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+/* Handle alpha and tRNS by replacing with a background color. */
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+extern PNG_EXPORT(void,png_set_background) PNGARG((png_structp png_ptr,
+   png_color_16p background_color, int background_gamma_code,
+   int need_expand, double background_gamma));
+#endif
+#define PNG_BACKGROUND_GAMMA_UNKNOWN 0
+#define PNG_BACKGROUND_GAMMA_SCREEN  1
+#define PNG_BACKGROUND_GAMMA_FILE    2
+#define PNG_BACKGROUND_GAMMA_UNIQUE  3
+#endif
+
+#if defined(PNG_READ_16_TO_8_SUPPORTED)
+/* strip the second byte of information from a 16-bit depth file. */
+extern PNG_EXPORT(void,png_set_strip_16) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_DITHER_SUPPORTED)
+/* Turn on dithering, and reduce the palette to the number of colors available. */
+extern PNG_EXPORT(void,png_set_dither) PNGARG((png_structp png_ptr,
+   png_colorp palette, int num_palette, int maximum_colors,
+   png_uint_16p histogram, int full_dither));
+#endif
+
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+/* Handle gamma correction. Screen_gamma=(display_exponent) */
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+extern PNG_EXPORT(void,png_set_gamma) PNGARG((png_structp png_ptr,
+   double screen_gamma, double default_file_gamma));
+#endif
+#endif
+
+#if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \
+    defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED)
+/* Permit or disallow empty PLTE (0: not permitted, 1: permitted) */
+/* Deprecated and will be removed.  Use png_permit_mng_features() instead. */
+extern PNG_EXPORT(void,png_permit_empty_plte) PNGARG((png_structp png_ptr,
+   int empty_plte_permitted));
+#endif
+
+#if defined(PNG_WRITE_FLUSH_SUPPORTED)
+/* Set how many lines between output flushes - 0 for no flushing */
+extern PNG_EXPORT(void,png_set_flush) PNGARG((png_structp png_ptr, int nrows));
+/* Flush the current PNG output buffer */
+extern PNG_EXPORT(void,png_write_flush) PNGARG((png_structp png_ptr));
+#endif
+
+/* optional update palette with requested transformations */
+extern PNG_EXPORT(void,png_start_read_image) PNGARG((png_structp png_ptr));
+
+/* optional call to update the users info structure */
+extern PNG_EXPORT(void,png_read_update_info) PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+
+/* read a one or more rows of image data.*/
+extern PNG_EXPORT(void,png_read_rows) PNGARG((png_structp png_ptr,
+   png_bytepp row, png_bytepp display_row, png_uint_32 num_rows));
+
+/* read a row of data.*/
+extern PNG_EXPORT(void,png_read_row) PNGARG((png_structp png_ptr,
+   png_bytep row,
+   png_bytep display_row));
+
+/* read the whole image into memory at once. */
+extern PNG_EXPORT(void,png_read_image) PNGARG((png_structp png_ptr,
+   png_bytepp image));
+
+/* write a row of image data */
+extern PNG_EXPORT(void,png_write_row) PNGARG((png_structp png_ptr,
+   png_bytep row));
+
+/* write a few rows of image data */
+extern PNG_EXPORT(void,png_write_rows) PNGARG((png_structp png_ptr,
+   png_bytepp row, png_uint_32 num_rows));
+
+/* write the image data */
+extern PNG_EXPORT(void,png_write_image) PNGARG((png_structp png_ptr,
+   png_bytepp image));
+
+/* writes the end of the PNG file. */
+extern PNG_EXPORT(void,png_write_end) PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+
+/* read the end of the PNG file. */
+extern PNG_EXPORT(void,png_read_end) PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+
+/* free any memory associated with the png_info_struct */
+extern PNG_EXPORT(void,png_destroy_info_struct) PNGARG((png_structp png_ptr,
+   png_infopp info_ptr_ptr));
+
+/* free any memory associated with the png_struct and the png_info_structs */
+extern PNG_EXPORT(void,png_destroy_read_struct) PNGARG((png_structpp
+   png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr));
+
+/* free all memory used by the read (old method - NOT DLL EXPORTED) */
+extern void png_read_destroy PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_infop end_info_ptr));
+
+/* free any memory associated with the png_struct and the png_info_structs */
+extern PNG_EXPORT(void,png_destroy_write_struct)
+   PNGARG((png_structpp png_ptr_ptr, png_infopp info_ptr_ptr));
+
+/* free any memory used in info_ptr struct (old method - NOT DLL EXPORTED) */
+extern void png_write_destroy_info PNGARG((png_infop info_ptr));
+
+/* free any memory used in png_ptr struct (old method - NOT DLL EXPORTED) */
+extern void png_write_destroy PNGARG((png_structp png_ptr));
+
+/* set the libpng method of handling chunk CRC errors */
+extern PNG_EXPORT(void,png_set_crc_action) PNGARG((png_structp png_ptr,
+   int crit_action, int ancil_action));
+
+/* Values for png_set_crc_action() to say how to handle CRC errors in
+ * ancillary and critical chunks, and whether to use the data contained
+ * therein.  Note that it is impossible to "discard" data in a critical
+ * chunk.  For versions prior to 0.90, the action was always error/quit,
+ * whereas in version 0.90 and later, the action for CRC errors in ancillary
+ * chunks is warn/discard.  These values should NOT be changed.
+ *
+ *      value                       action:critical     action:ancillary
+ */
+#define PNG_CRC_DEFAULT       0  /* error/quit          warn/discard data */
+#define PNG_CRC_ERROR_QUIT    1  /* error/quit          error/quit        */
+#define PNG_CRC_WARN_DISCARD  2  /* (INVALID)           warn/discard data */
+#define PNG_CRC_WARN_USE      3  /* warn/use data       warn/use data     */
+#define PNG_CRC_QUIET_USE     4  /* quiet/use data      quiet/use data    */
+#define PNG_CRC_NO_CHANGE     5  /* use current value   use current value */
+
+/* These functions give the user control over the scan-line filtering in
+ * libpng and the compression methods used by zlib.  These functions are
+ * mainly useful for testing, as the defaults should work with most users.
+ * Those users who are tight on memory or want faster performance at the
+ * expense of compression can modify them.  See the compression library
+ * header file (zlib.h) for an explination of the compression functions.
+ */
+
+/* set the filtering method(s) used by libpng.  Currently, the only valid
+ * value for "method" is 0.
+ */
+extern PNG_EXPORT(void,png_set_filter) PNGARG((png_structp png_ptr, int method,
+   int filters));
+
+/* Flags for png_set_filter() to say which filters to use.  The flags
+ * are chosen so that they don't conflict with real filter types
+ * below, in case they are supplied instead of the #defined constants.
+ * These values should NOT be changed.
+ */
+#define PNG_NO_FILTERS     0x00
+#define PNG_FILTER_NONE    0x08
+#define PNG_FILTER_SUB     0x10
+#define PNG_FILTER_UP      0x20
+#define PNG_FILTER_AVG     0x40
+#define PNG_FILTER_PAETH   0x80
+#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \
+                         PNG_FILTER_AVG | PNG_FILTER_PAETH)
+
+/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now.
+ * These defines should NOT be changed.
+ */
+#define PNG_FILTER_VALUE_NONE  0
+#define PNG_FILTER_VALUE_SUB   1
+#define PNG_FILTER_VALUE_UP    2
+#define PNG_FILTER_VALUE_AVG   3
+#define PNG_FILTER_VALUE_PAETH 4
+#define PNG_FILTER_VALUE_LAST  5
+
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) /* EXPERIMENTAL */
+/* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_
+ * defines, either the default (minimum-sum-of-absolute-differences), or
+ * the experimental method (weighted-minimum-sum-of-absolute-differences).
+ *
+ * Weights are factors >= 1.0, indicating how important it is to keep the
+ * filter type consistent between rows.  Larger numbers mean the current
+ * filter is that many times as likely to be the same as the "num_weights"
+ * previous filters.  This is cumulative for each previous row with a weight.
+ * There needs to be "num_weights" values in "filter_weights", or it can be
+ * NULL if the weights aren't being specified.  Weights have no influence on
+ * the selection of the first row filter.  Well chosen weights can (in theory)
+ * improve the compression for a given image.
+ *
+ * Costs are factors >= 1.0 indicating the relative decoding costs of a
+ * filter type.  Higher costs indicate more decoding expense, and are
+ * therefore less likely to be selected over a filter with lower computational
+ * costs.  There needs to be a value in "filter_costs" for each valid filter
+ * type (given by PNG_FILTER_VALUE_LAST), or it can be NULL if you aren't
+ * setting the costs.  Costs try to improve the speed of decompression without
+ * unduly increasing the compressed image size.
+ *
+ * A negative weight or cost indicates the default value is to be used, and
+ * values in the range [0.0, 1.0) indicate the value is to remain unchanged.
+ * The default values for both weights and costs are currently 1.0, but may
+ * change if good general weighting/cost heuristics can be found.  If both
+ * the weights and costs are set to 1.0, this degenerates the WEIGHTED method
+ * to the UNWEIGHTED method, but with added encoding time/computation.
+ */
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+extern PNG_EXPORT(void,png_set_filter_heuristics) PNGARG((png_structp png_ptr,
+   int heuristic_method, int num_weights, png_doublep filter_weights,
+   png_doublep filter_costs));
+#endif
+#endif /*  PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */
+
+/* Heuristic used for row filter selection.  These defines should NOT be
+ * changed.
+ */
+#define PNG_FILTER_HEURISTIC_DEFAULT    0  /* Currently "UNWEIGHTED" */
+#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1  /* Used by libpng < 0.95 */
+#define PNG_FILTER_HEURISTIC_WEIGHTED   2  /* Experimental feature */
+#define PNG_FILTER_HEURISTIC_LAST       3  /* Not a valid value */
+
+/* Set the library compression level.  Currently, valid values range from
+ * 0 - 9, corresponding directly to the zlib compression levels 0 - 9
+ * (0 - no compression, 9 - "maximal" compression).  Note that tests have
+ * shown that zlib compression levels 3-6 usually perform as well as level 9
+ * for PNG images, and do considerably fewer caclulations.  In the future,
+ * these values may not correspond directly to the zlib compression levels.
+ */
+extern PNG_EXPORT(void,png_set_compression_level) PNGARG((png_structp png_ptr,
+   int level));
+
+extern PNG_EXPORT(void,png_set_compression_mem_level)
+   PNGARG((png_structp png_ptr, int mem_level));
+
+extern PNG_EXPORT(void,png_set_compression_strategy)
+   PNGARG((png_structp png_ptr, int strategy));
+
+extern PNG_EXPORT(void,png_set_compression_window_bits)
+   PNGARG((png_structp png_ptr, int window_bits));
+
+extern PNG_EXPORT(void,png_set_compression_method) PNGARG((png_structp png_ptr,
+   int method));
+
+/* These next functions are called for input/output, memory, and error
+ * handling.  They are in the file pngrio.c, pngwio.c, and pngerror.c,
+ * and call standard C I/O routines such as fread(), fwrite(), and
+ * fprintf().  These functions can be made to use other I/O routines
+ * at run time for those applications that need to handle I/O in a
+ * different manner by calling png_set_???_fn().  See libpng.txt for
+ * more information.
+ */
+
+#if !defined(PNG_NO_STDIO)
+/* Initialize the input/output for the PNG file to the default functions. */
+extern PNG_EXPORT(void,png_init_io) PNGARG((png_structp png_ptr, png_FILE_p fp));
+#endif
+
+/* Replace the (error and abort), and warning functions with user
+ * supplied functions.  If no messages are to be printed you must still
+ * write and use replacement functions. The replacement error_fn should
+ * still do a longjmp to the last setjmp location if you are using this
+ * method of error handling.  If error_fn or warning_fn is NULL, the
+ * default function will be used.
+ */
+
+extern PNG_EXPORT(void,png_set_error_fn) PNGARG((png_structp png_ptr,
+   png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn));
+
+/* Return the user pointer associated with the error functions */
+extern PNG_EXPORT(png_voidp,png_get_error_ptr) PNGARG((png_structp png_ptr));
+
+/* Replace the default data output functions with a user supplied one(s).
+ * If buffered output is not used, then output_flush_fn can be set to NULL.
+ * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time
+ * output_flush_fn will be ignored (and thus can be NULL).
+ */
+extern PNG_EXPORT(void,png_set_write_fn) PNGARG((png_structp png_ptr,
+   png_voidp io_ptr, png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn));
+
+/* Replace the default data input function with a user supplied one. */
+extern PNG_EXPORT(void,png_set_read_fn) PNGARG((png_structp png_ptr,
+   png_voidp io_ptr, png_rw_ptr read_data_fn));
+
+/* Return the user pointer associated with the I/O functions */
+extern PNG_EXPORT(png_voidp,png_get_io_ptr) PNGARG((png_structp png_ptr));
+
+extern PNG_EXPORT(void,png_set_read_status_fn) PNGARG((png_structp png_ptr,
+   png_read_status_ptr read_row_fn));
+
+extern PNG_EXPORT(void,png_set_write_status_fn) PNGARG((png_structp png_ptr,
+   png_write_status_ptr write_row_fn));
+
+#ifdef PNG_USER_MEM_SUPPORTED
+/* Replace the default memory allocation functions with user supplied one(s). */
+extern PNG_EXPORT(void,png_set_mem_fn) PNGARG((png_structp png_ptr,
+   png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn));
+/* Return the user pointer associated with the memory functions */
+extern PNG_EXPORT(png_voidp,png_get_mem_ptr) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
+    defined(PNG_LEGACY_SUPPORTED)
+extern PNG_EXPORT(void,png_set_read_user_transform_fn) PNGARG((png_structp
+   png_ptr, png_user_transform_ptr read_user_transform_fn));
+#endif
+
+#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
+    defined(PNG_LEGACY_SUPPORTED)
+extern PNG_EXPORT(void,png_set_write_user_transform_fn) PNGARG((png_structp
+   png_ptr, png_user_transform_ptr write_user_transform_fn));
+#endif
+
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
+    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
+    defined(PNG_LEGACY_SUPPORTED)
+extern PNG_EXPORT(void,png_set_user_transform_info) PNGARG((png_structp
+   png_ptr, png_voidp user_transform_ptr, int user_transform_depth,
+   int user_transform_channels));
+/* Return the user pointer associated with the user transform functions */
+extern PNG_EXPORT(png_voidp,png_get_user_transform_ptr)
+   PNGARG((png_structp png_ptr));
+#endif
+
+#ifdef PNG_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.
+ */
+extern PNG_EXPORT(void,png_set_progressive_read_fn) PNGARG((png_structp png_ptr,
+   png_voidp progressive_ptr,
+   png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,
+   png_progressive_end_ptr end_fn));
+
+/* returns the user pointer associated with the push read functions */
+extern PNG_EXPORT(png_voidp,png_get_progressive_ptr)
+   PNGARG((png_structp png_ptr));
+
+/* function to be called when data becomes available */
+extern PNG_EXPORT(void,png_process_data) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_bytep buffer, png_size_t buffer_size));
+
+/* function that combines rows.  Not very much different than the
+ * png_combine_row() call.  Is this even used?????
+ */
+extern PNG_EXPORT(void,png_progressive_combine_row) PNGARG((png_structp png_ptr,
+   png_bytep old_row, png_bytep new_row));
+#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
+
+extern PNG_EXPORT(png_voidp,png_malloc) PNGARG((png_structp png_ptr,
+   png_uint_32 size));
+
+/* frees a pointer allocated by png_malloc() */
+extern PNG_EXPORT(void,png_free) PNGARG((png_structp png_ptr, png_voidp ptr));
+
+/* Free data that was allocated internally */
+extern PNG_EXPORT(void,png_free_data) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_uint_32 free_me, int num));
+#ifdef PNG_FREE_ME_SUPPORTED
+/* Reassign responsibility for freeing existing data, whether allocated
+ * by libpng or by the application */
+extern PNG_EXPORT(void,png_data_freer) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, int freer, png_uint_32 mask));
+#endif
+/* assignments for png_data_freer */
+#define PNG_DESTROY_WILL_FREE_DATA 1
+#define PNG_SET_WILL_FREE_DATA 1
+#define PNG_USER_WILL_FREE_DATA 2
+/* Flags for png_ptr->free_me and info_ptr->free_me */
+#define PNG_FREE_HIST 0x0008
+#define PNG_FREE_ICCP 0x0010
+#define PNG_FREE_SPLT 0x0020
+#define PNG_FREE_ROWS 0x0040
+#define PNG_FREE_PCAL 0x0080
+#define PNG_FREE_SCAL 0x0100
+#define PNG_FREE_UNKN 0x0200
+#define PNG_FREE_LIST 0x0400
+#define PNG_FREE_PLTE 0x1000
+#define PNG_FREE_TRNS 0x2000
+#define PNG_FREE_TEXT 0x4000
+#define PNG_FREE_ALL  0x7fff
+#define PNG_FREE_MUL  0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */
+
+#ifdef PNG_USER_MEM_SUPPORTED
+extern PNG_EXPORT(png_voidp,png_malloc_default) PNGARG((png_structp png_ptr,
+   png_uint_32 size));
+extern PNG_EXPORT(void,png_free_default) PNGARG((png_structp png_ptr,
+   png_voidp ptr));
+#endif
+
+extern PNG_EXPORT(png_voidp,png_memcpy_check) PNGARG((png_structp png_ptr,
+   png_voidp s1, png_voidp s2, png_uint_32 size));
+
+extern PNG_EXPORT(png_voidp,png_memset_check) PNGARG((png_structp png_ptr,
+   png_voidp s1, int value, png_uint_32 size));
+
+#if defined(USE_FAR_KEYWORD)  /* memory model conversion function */
+extern void *png_far_to_near PNGARG((png_structp png_ptr,png_voidp ptr,
+   int check));
+#endif /* USE_FAR_KEYWORD */
+
+/* Fatal error in PNG image of libpng - can't continue */
+extern PNG_EXPORT(void,png_error) PNGARG((png_structp png_ptr,
+   png_const_charp error));
+
+/* The same, but the chunk name is prepended to the error string. */
+extern PNG_EXPORT(void,png_chunk_error) PNGARG((png_structp png_ptr,
+   png_const_charp error));
+
+/* Non-fatal error in libpng.  Can continue, but may have a problem. */
+extern PNG_EXPORT(void,png_warning) PNGARG((png_structp png_ptr,
+   png_const_charp message));
+
+/* Non-fatal error in libpng, chunk name is prepended to message. */
+extern PNG_EXPORT(void,png_chunk_warning) PNGARG((png_structp png_ptr,
+   png_const_charp message));
+
+/* The png_set_<chunk> functions are for storing values in the png_info_struct.
+ * Similarly, the png_get_<chunk> calls are used to read values from the
+ * png_info_struct, either storing the parameters in the passed variables, or
+ * setting pointers into the png_info_struct where the data is stored.  The
+ * png_get_<chunk> functions return a non-zero value if the data was available
+ * in info_ptr, or return zero and do not change any of the parameters if the
+ * data was not available.
+ *
+ * These functions should be used instead of directly accessing png_info
+ * to avoid problems with future changes in the size and internal layout of
+ * png_info_struct.
+ */
+/* Returns "flag" if chunk data is valid in info_ptr. */
+extern PNG_EXPORT(png_uint_32,png_get_valid) PNGARG((png_structp png_ptr,
+png_infop info_ptr, png_uint_32 flag));
+
+/* Returns number of bytes needed to hold a transformed row. */
+extern PNG_EXPORT(png_uint_32,png_get_rowbytes) PNGARG((png_structp png_ptr,
+png_infop info_ptr));
+
+#if defined(PNG_INFO_IMAGE_SUPPORTED)
+/* Returns row_pointers, which is an array of pointers to scanlines that was
+returned from png_read_png(). */
+extern PNG_EXPORT(png_bytepp,png_get_rows) PNGARG((png_structp png_ptr,
+png_infop info_ptr));
+/* Set row_pointers, which is an array of pointers to scanlines for use
+by png_write_png(). */
+extern PNG_EXPORT(void,png_set_rows) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_bytepp row_pointers));
+#endif
+
+/* Returns number of color channels in image. */
+extern PNG_EXPORT(png_byte,png_get_channels) PNGARG((png_structp png_ptr,
+png_infop info_ptr));
+
+#ifdef PNG_EASY_ACCESS_SUPPORTED
+/* Returns image width in pixels. */
+extern PNG_EXPORT(png_uint_32, png_get_image_width) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+
+/* Returns image height in pixels. */
+extern PNG_EXPORT(png_uint_32, png_get_image_height) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+
+/* Returns image bit_depth. */
+extern PNG_EXPORT(png_byte, png_get_bit_depth) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+
+/* Returns image color_type. */
+extern PNG_EXPORT(png_byte, png_get_color_type) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+
+/* Returns image filter_type. */
+extern PNG_EXPORT(png_byte, png_get_filter_type) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+
+/* Returns image interlace_type. */
+extern PNG_EXPORT(png_byte, png_get_interlace_type) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+
+/* Returns image compression_type. */
+extern PNG_EXPORT(png_byte, png_get_compression_type) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+
+/* Returns image resolution in pixels per meter, from pHYs chunk data. */
+extern PNG_EXPORT(png_uint_32, png_get_pixels_per_meter) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+extern PNG_EXPORT(png_uint_32, png_get_x_pixels_per_meter) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+extern PNG_EXPORT(png_uint_32, png_get_y_pixels_per_meter) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+
+/* Returns pixel aspect ratio, computed from pHYs chunk data.  */
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+extern PNG_EXPORT(float, png_get_pixel_aspect_ratio) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+#endif
+
+/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */
+extern PNG_EXPORT(png_int_32, png_get_x_offset_pixels) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+extern PNG_EXPORT(png_int_32, png_get_y_offset_pixels) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+extern PNG_EXPORT(png_int_32, png_get_x_offset_microns) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+extern PNG_EXPORT(png_int_32, png_get_y_offset_microns) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+
+#endif /* PNG_EASY_ACCESS_SUPPORTED */
+
+/* Returns pointer to signature string read from PNG header */
+extern PNG_EXPORT(png_bytep,png_get_signature) PNGARG((png_structp png_ptr,
+png_infop info_ptr));
+
+#if defined(PNG_bKGD_SUPPORTED)
+extern PNG_EXPORT(png_uint_32,png_get_bKGD) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_color_16p *background));
+#endif
+
+#if defined(PNG_bKGD_SUPPORTED)
+extern PNG_EXPORT(void,png_set_bKGD) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_color_16p background));
+#endif
+
+#if defined(PNG_cHRM_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+extern PNG_EXPORT(png_uint_32,png_get_cHRM) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, double *white_x, double *white_y, double *red_x,
+   double *red_y, double *green_x, double *green_y, double *blue_x,
+   double *blue_y));
+#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_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
+
+#if defined(PNG_cHRM_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+extern PNG_EXPORT(void,png_set_cHRM) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, double white_x, double white_y, double red_x,
+   double red_y, double green_x, double green_y, double blue_x, double blue_y));
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+extern PNG_EXPORT(void,png_set_cHRM_fixed) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_fixed_point int_white_x, png_fixed_point int_white_y,
+   png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point
+   int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x,
+   png_fixed_point int_blue_y));
+#endif
+#endif
+
+#if defined(PNG_gAMA_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+extern PNG_EXPORT(png_uint_32,png_get_gAMA) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, double *file_gamma));
+#endif
+extern PNG_EXPORT(png_uint_32,png_get_gAMA_fixed) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_fixed_point *int_file_gamma));
+#endif
+
+#if defined(PNG_gAMA_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+extern PNG_EXPORT(void,png_set_gAMA) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, double file_gamma));
+#endif
+extern PNG_EXPORT(void,png_set_gAMA_fixed) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_fixed_point int_file_gamma));
+#endif
+
+#if defined(PNG_hIST_SUPPORTED)
+extern PNG_EXPORT(png_uint_32,png_get_hIST) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_uint_16p *hist));
+#endif
+
+#if defined(PNG_hIST_SUPPORTED)
+extern PNG_EXPORT(void,png_set_hIST) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_uint_16p hist));
+#endif
+
+extern PNG_EXPORT(png_uint_32,png_get_IHDR) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_uint_32 *width, png_uint_32 *height,
+   int *bit_depth, int *color_type, int *interlace_method,
+   int *compression_method, int *filter_method));
+
+extern PNG_EXPORT(void,png_set_IHDR) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth,
+   int color_type, int interlace_method, int compression_method,
+   int filter_method));
+
+#if defined(PNG_oFFs_SUPPORTED)
+extern PNG_EXPORT(png_uint_32,png_get_oFFs) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_int_32 *offset_x, png_int_32 *offset_y,
+   int *unit_type));
+#endif
+
+#if defined(PNG_oFFs_SUPPORTED)
+extern PNG_EXPORT(void,png_set_oFFs) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_int_32 offset_x, png_int_32 offset_y,
+   int unit_type));
+#endif
+
+#if defined(PNG_pCAL_SUPPORTED)
+extern PNG_EXPORT(png_uint_32,png_get_pCAL) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_charp *purpose, png_int_32 *X0, png_int_32 *X1,
+   int *type, int *nparams, png_charp *units, png_charpp *params));
+#endif
+
+#if defined(PNG_pCAL_SUPPORTED)
+extern PNG_EXPORT(void,png_set_pCAL) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_charp purpose, png_int_32 X0, png_int_32 X1,
+   int type, int nparams, png_charp units, png_charpp params));
+#endif
+
+#if defined(PNG_pHYs_SUPPORTED)
+extern PNG_EXPORT(png_uint_32,png_get_pHYs) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type));
+#endif
+
+#if defined(PNG_pHYs_SUPPORTED)
+extern PNG_EXPORT(void,png_set_pHYs) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type));
+#endif
+
+extern PNG_EXPORT(png_uint_32,png_get_PLTE) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_colorp *palette, int *num_palette));
+
+extern PNG_EXPORT(void,png_set_PLTE) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_colorp palette, int num_palette));
+
+#if defined(PNG_sBIT_SUPPORTED)
+extern PNG_EXPORT(png_uint_32,png_get_sBIT) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_color_8p *sig_bit));
+#endif
+
+#if defined(PNG_sBIT_SUPPORTED)
+extern PNG_EXPORT(void,png_set_sBIT) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_color_8p sig_bit));
+#endif
+
+#if defined(PNG_sRGB_SUPPORTED)
+extern PNG_EXPORT(png_uint_32,png_get_sRGB) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, int *intent));
+#endif
+
+#if defined(PNG_sRGB_SUPPORTED)
+extern PNG_EXPORT(void,png_set_sRGB) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, int intent));
+extern PNG_EXPORT(void,png_set_sRGB_gAMA_and_cHRM) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, int intent));
+#endif
+
+#if defined(PNG_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_uint_32 *proflen));
+   /* Note to maintainer: profile should be png_bytepp */
+#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, png_uint_32 proflen));
+   /* Note to maintainer: profile should be png_bytep */
+#endif
+
+#if defined(PNG_sPLT_SUPPORTED)
+extern PNG_EXPORT(png_uint_32,png_get_sPLT) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_sPLT_tpp entries));
+#endif
+
+#if defined(PNG_sPLT_SUPPORTED)
+extern PNG_EXPORT(void,png_set_sPLT) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_sPLT_tp entries, int nentries));
+#endif
+
+#if defined(PNG_TEXT_SUPPORTED)
+/* 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));
+#endif
+
+/*
+ *  Note while png_set_text() will accept a structure whose text,
+ *  language, and  translated keywords are NULL pointers, the structure
+ *  returned by png_get_text will always contain regular
+ *  zero-terminated C strings.  They might be empty strings but
+ *  they will never be NULL pointers.
+ */
+
+#if defined(PNG_TEXT_SUPPORTED)
+extern PNG_EXPORT(void,png_set_text) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_textp text_ptr, int num_text));
+#endif
+
+#if defined(PNG_tIME_SUPPORTED)
+extern PNG_EXPORT(png_uint_32,png_get_tIME) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_timep *mod_time));
+#endif
+
+#if defined(PNG_tIME_SUPPORTED)
+extern PNG_EXPORT(void,png_set_tIME) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_timep mod_time));
+#endif
+
+#if defined(PNG_tRNS_SUPPORTED)
+extern PNG_EXPORT(png_uint_32,png_get_tRNS) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_bytep *trans, int *num_trans,
+   png_color_16p *trans_values));
+#endif
+
+#if defined(PNG_tRNS_SUPPORTED)
+extern PNG_EXPORT(void,png_set_tRNS) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_bytep trans, int num_trans,
+   png_color_16p trans_values));
+#endif
+
+#if defined(PNG_tRNS_SUPPORTED)
+#endif
+
+#if defined(PNG_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, 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, int *unit, png_charpp swidth, png_charpp sheight));
+#endif
+#endif
+#endif /* PNG_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, 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, int unit, png_charp swidth, png_charp sheight));
+#endif
+#endif /* PNG_sCAL_SUPPORTED || PNG_WRITE_sCAL_SUPPORTED */
+
+#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+/* 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 num_unknowns));
+extern PNG_EXPORT(void, png_set_unknown_chunk_location)
+   PNGARG((png_structp png_ptr, png_infop info_ptr, int chunk, int location));
+extern PNG_EXPORT(png_uint_32,png_get_unknown_chunks) PNGARG((png_structp
+   png_ptr, png_infop info_ptr, png_unknown_chunkpp entries));
+#endif
+
+/* Png_free_data() will turn off the "valid" flag for anything it frees.
+   If you need to turn it off for a chunk that your application has freed,
+   you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); */
+extern PNG_EXPORT(void, png_set_invalid) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, int mask));
+
+#if defined(PNG_INFO_IMAGE_SUPPORTED)
+/* The "params" pointer is currently not used and is for future expansion. */
+extern PNG_EXPORT(void, png_read_png) PNGARG((png_structp png_ptr,
+                        png_infop info_ptr,
+                        int transforms,
+                        png_voidp params));
+extern PNG_EXPORT(void, png_write_png) PNGARG((png_structp png_ptr,
+                        png_infop info_ptr,
+                        int transforms,
+                        png_voidp params));
+#endif
+
+/* Define PNG_DEBUG at compile time for debugging information.  Higher
+ * numbers for PNG_DEBUG mean more debugging information.  This has
+ * only been added since version 0.95 so it is not implemented throughout
+ * libpng yet, but more support will be added as needed.
+ */
+#ifdef PNG_DEBUG
+#if (PNG_DEBUG > 0)
+#if !defined(PNG_DEBUG_FILE) && defined(_MSC_VER)
+#include <crtdbg.h>
+#if (PNG_DEBUG > 1)
+#define png_debug(l,m)  _RPT0(_CRT_WARN,m)
+#define png_debug1(l,m,p1)  _RPT1(_CRT_WARN,m,p1)
+#define png_debug2(l,m,p1,p2) _RPT2(_CRT_WARN,m,p1,p2)
+#endif
+#else /* PNG_DEBUG_FILE || !_MSC_VER */
+#ifndef PNG_DEBUG_FILE
+#define PNG_DEBUG_FILE stderr
+#endif /* PNG_DEBUG_FILE */
+#if (PNG_DEBUG > 1)
+#define png_debug(l,m) \
+{ \
+     int num_tabs=l; \
+     fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \
+       (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":"")))); \
+}
+#define png_debug1(l,m,p1) \
+{ \
+     int num_tabs=l; \
+     fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \
+       (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1); \
+}
+#define png_debug2(l,m,p1,p2) \
+{ \
+     int num_tabs=l; \
+     fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \
+       (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1,p2); \
+}
+#endif /* (PNG_DEBUG > 1) */
+#endif /* _MSC_VER */
+#endif /* (PNG_DEBUG > 0) */
+#endif /* PNG_DEBUG */
+#ifndef png_debug
+#define png_debug(l, m)
+#endif
+#ifndef png_debug1
+#define png_debug1(l, m, p1)
+#endif
+#ifndef png_debug2
+#define png_debug2(l, m, p1, p2)
+#endif
+
+extern PNG_EXPORT(png_bytep,png_sig_bytes) PNGARG((void));
+
+extern PNG_EXPORT(png_charp,png_get_copyright) PNGARG((png_structp png_ptr));
+extern PNG_EXPORT(png_charp,png_get_header_ver) PNGARG((png_structp png_ptr));
+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));
+
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+extern PNG_EXPORT(png_uint_32,png_permit_mng_features) PNGARG((png_structp
+   png_ptr, png_uint_32 mng_features_permitted));
+#endif
+
+/* png_mmx_support will be included unconditionally starting in version 1.2.0 */
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) || defined(PNG_USE_PNGGCCRD)
+/* png.c, pnggccrd.c, or pngvcrd.c */
+extern PNG_EXPORT(int,png_mmx_support) PNGARG((void));
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */
+
+/* Strip the prepended error numbers ("#nnn ") from error and warning
+ * messages before passing them to the error or warning handler. */
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+extern PNG_EXPORT(void,png_set_strip_error_numbers) PNGARG((png_structp
+   png_ptr, png_uint_32 strip_mode));
+#endif
+
+/* Maintainer: Put new public prototypes here ^, in libpng.3, and project defs */
+
+#define PNG_HEADER_VERSION_STRING \
+   " libpng version 1.0.12 - June 8, 2001 (header)\n"
+
+#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED
+/* With these routines we avoid an integer divide, which will be slower on
+ * most machines.  However, it does take more operations than the corresponding
+ * divide method, so it may be slower on a few RISC systems.  There are two
+ * shifts (by 8 or 16 bits) and an addition, versus a single integer divide.
+ *
+ * Note that the rounding factors are NOT supposed to be the same!  128 and
+ * 32768 are correct for the NODIV code; 127 and 32767 are correct for the
+ * standard method.
+ *
+ * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ]
+ */
+
+ /* fg and bg should be in `gamma 1.0' space; alpha is the opacity          */
+
+#  define png_composite(composite, fg, alpha, bg)                            \
+     { png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) * (png_uint_16)(alpha) \
+                        +        (png_uint_16)(bg)*(png_uint_16)(255 -       \
+                        (png_uint_16)(alpha)) + (png_uint_16)128);           \
+       (composite) = (png_byte)((temp + (temp >> 8)) >> 8); }
+
+#  define png_composite_16(composite, fg, alpha, bg)                         \
+     { png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) * (png_uint_32)(alpha) \
+                        + (png_uint_32)(bg)*(png_uint_32)(65535L -           \
+                        (png_uint_32)(alpha)) + (png_uint_32)32768L);        \
+       (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); }
+
+#else  /* standard method using integer division */
+
+#  define png_composite(composite, fg, alpha, bg)                            \
+     (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) +    \
+       (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) +       \
+       (png_uint_16)127) / 255)
+
+#  define png_composite_16(composite, fg, alpha, bg)                         \
+     (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \
+       (png_uint_32)(bg)*(png_uint_32)(65535L - (png_uint_32)(alpha)) +      \
+       (png_uint_32)32767) / (png_uint_32)65535L)
+
+#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */
+
+/* These next functions are used internally in the code.  They generally
+ * shouldn't be used unless you are writing code to add or replace some
+ * functionality in libpng.  More information about most functions can
+ * be found in the files where the functions are located.
+ */
+
+#if defined(PNG_INTERNAL)
+
+/* Various modes of operation.  Note that after an init, mode is set to
+ * zero automatically when the structure is created.
+ */
+#define PNG_HAVE_IHDR               0x01
+#define PNG_HAVE_PLTE               0x02
+#define PNG_HAVE_IDAT               0x04
+#define PNG_AFTER_IDAT              0x08
+#define PNG_HAVE_IEND               0x10
+#define PNG_HAVE_gAMA               0x20
+#define PNG_HAVE_cHRM               0x40
+#define PNG_HAVE_sRGB               0x80
+#define PNG_HAVE_CHUNK_HEADER      0x100
+#define PNG_WROTE_tIME             0x200
+#define PNG_WROTE_INFO_BEFORE_PLTE 0x400
+#define PNG_BACKGROUND_IS_GRAY     0x800
+#define PNG_HAVE_PNG_SIGNATURE    0x1000
+
+/* flags for the transformations the PNG library does on the image data */
+#define PNG_BGR                0x0001
+#define PNG_INTERLACE          0x0002
+#define PNG_PACK               0x0004
+#define PNG_SHIFT              0x0008
+#define PNG_SWAP_BYTES         0x0010
+#define PNG_INVERT_MONO        0x0020
+#define PNG_DITHER             0x0040
+#define PNG_BACKGROUND         0x0080
+#define PNG_BACKGROUND_EXPAND  0x0100
+                          /*   0x0200 unused */
+#define PNG_16_TO_8            0x0400
+#define PNG_RGBA               0x0800
+#define PNG_EXPAND             0x1000
+#define PNG_GAMMA              0x2000
+#define PNG_GRAY_TO_RGB        0x4000
+#define PNG_FILLER             0x8000L
+#define PNG_PACKSWAP          0x10000L
+#define PNG_SWAP_ALPHA        0x20000L
+#define PNG_STRIP_ALPHA       0x40000L
+#define PNG_INVERT_ALPHA      0x80000L
+#define PNG_USER_TRANSFORM   0x100000L
+#define PNG_RGB_TO_GRAY_ERR  0x200000L
+#define PNG_RGB_TO_GRAY_WARN 0x400000L
+#define PNG_RGB_TO_GRAY      0x600000L  /* two bits, RGB_TO_GRAY_ERR|WARN */
+
+/* flags for png_create_struct */
+#define PNG_STRUCT_PNG   0x0001
+#define PNG_STRUCT_INFO  0x0002
+
+/* Scaling factor for filter heuristic weighting calculations */
+#define PNG_WEIGHT_SHIFT 8
+#define PNG_WEIGHT_FACTOR (1<<(PNG_WEIGHT_SHIFT))
+#define PNG_COST_SHIFT 3
+#define PNG_COST_FACTOR (1<<(PNG_COST_SHIFT))
+
+/* flags for the png_ptr->flags rather than declaring a byte for each one */
+#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY     0x0001
+#define PNG_FLAG_ZLIB_CUSTOM_LEVEL        0x0002
+#define PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL    0x0004
+#define PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS  0x0008
+#define PNG_FLAG_ZLIB_CUSTOM_METHOD       0x0010
+#define PNG_FLAG_ZLIB_FINISHED            0x0020
+#define PNG_FLAG_ROW_INIT                 0x0040
+#define PNG_FLAG_FILLER_AFTER             0x0080
+#define PNG_FLAG_CRC_ANCILLARY_USE        0x0100
+#define PNG_FLAG_CRC_ANCILLARY_NOWARN     0x0200
+#define PNG_FLAG_CRC_CRITICAL_USE         0x0400
+#define PNG_FLAG_CRC_CRITICAL_IGNORE      0x0800
+#define PNG_FLAG_FREE_PLTE                0x1000
+#define PNG_FLAG_FREE_TRNS                0x2000
+#define PNG_FLAG_FREE_HIST                0x4000
+#define PNG_FLAG_KEEP_UNKNOWN_CHUNKS      0x8000L
+#define PNG_FLAG_KEEP_UNSAFE_CHUNKS       0x10000L
+#define PNG_FLAG_LIBRARY_MISMATCH         0x20000L
+#define PNG_FLAG_STRIP_ERROR_NUMBERS      0x40000L
+#define PNG_FLAG_STRIP_ERROR_TEXT         0x80000L
+
+/* 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)
+
+#define PNG_FLAG_CRC_CRITICAL_MASK  (PNG_FLAG_CRC_CRITICAL_USE | \
+                                     PNG_FLAG_CRC_CRITICAL_IGNORE)
+
+#define PNG_FLAG_CRC_MASK           (PNG_FLAG_CRC_ANCILLARY_MASK | \
+                                     PNG_FLAG_CRC_CRITICAL_MASK)
+
+/* save typing and make code easier to understand */
+#define PNG_COLOR_DIST(c1, c2) (abs((int)((c1).red) - (int)((c2).red)) + \
+   abs((int)((c1).green) - (int)((c2).green)) + \
+   abs((int)((c1).blue) - (int)((c2).blue)))
+
+/* variables declared in png.c - only it needs to define PNG_NO_EXTERN */
+#if !defined(PNG_NO_EXTERN) || defined(PNG_ALWAYS_EXTERN)
+/* place to hold the signature string for a PNG file. */
+#ifdef PNG_USE_GLOBAL_ARRAYS
+   PNG_EXPORT_VAR (const png_byte FARDATA) png_sig[8];
+#else
+#ifdef png_sig
+#undef png_sig
+#endif
+#define png_sig png_sig_bytes(NULL)
+#endif
+#endif /* PNG_NO_EXTERN */
+
+/* Constant strings for known chunk types.  If you need to add a chunk,
+ * define the name here, and add an invocation of the macro in png.c and
+ * wherever it's needed.
+ */
+#define PNG_IHDR const png_byte png_IHDR[5] = { 73,  72,  68,  82, '\0'}
+#define PNG_IDAT const png_byte png_IDAT[5] = { 73,  68,  65,  84, '\0'}
+#define PNG_IEND const png_byte png_IEND[5] = { 73,  69,  78,  68, '\0'}
+#define PNG_PLTE const png_byte png_PLTE[5] = { 80,  76,  84,  69, '\0'}
+#define PNG_bKGD const png_byte png_bKGD[5] = { 98,  75,  71,  68, '\0'}
+#define PNG_cHRM const png_byte png_cHRM[5] = { 99,  72,  82,  77, '\0'}
+#define PNG_gAMA const png_byte png_gAMA[5] = {103,  65,  77,  65, '\0'}
+#define PNG_hIST const png_byte png_hIST[5] = {104,  73,  83,  84, '\0'}
+#define PNG_iCCP const png_byte png_iCCP[5] = {105,  67,  67,  80, '\0'}
+#define PNG_iTXt const png_byte png_iTXt[5] = {105,  84,  88, 116, '\0'}
+#define PNG_oFFs const png_byte png_oFFs[5] = {111,  70,  70, 115, '\0'}
+#define PNG_pCAL const png_byte png_pCAL[5] = {112,  67,  65,  76, '\0'}
+#define PNG_sCAL const png_byte png_sCAL[5] = {115,  67,  65,  76, '\0'}
+#define PNG_pHYs const png_byte png_pHYs[5] = {112,  72,  89, 115, '\0'}
+#define PNG_sBIT const png_byte png_sBIT[5] = {115,  66,  73,  84, '\0'}
+#define PNG_sPLT const png_byte png_sPLT[5] = {115,  80,  76,  84, '\0'}
+#define PNG_sRGB const png_byte png_sRGB[5] = {115,  82,  71,  66, '\0'}
+#define PNG_tEXt const png_byte png_tEXt[5] = {116,  69,  88, 116, '\0'}
+#define PNG_tIME const png_byte png_tIME[5] = {116,  73,  77,  69, '\0'}
+#define PNG_tRNS const png_byte png_tRNS[5] = {116,  82,  78,  83, '\0'}
+#define PNG_zTXt const png_byte png_zTXt[5] = {122,  84,  88, 116, '\0'}
+
+#ifdef PNG_USE_GLOBAL_ARRAYS
+PNG_EXPORT_VAR (const png_byte FARDATA) png_IHDR[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_IDAT[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_IEND[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_PLTE[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_bKGD[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_cHRM[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_gAMA[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_hIST[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_iCCP[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_iTXt[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_oFFs[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_pCAL[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_sCAL[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_pHYs[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_sBIT[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_sPLT[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_sRGB[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_tEXt[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_tIME[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_tRNS[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_zTXt[5];
+#endif /* PNG_USE_GLOBAL_ARRAYS */
+
+
+/* Inline macros to do direct reads of bytes from the input buffer.  These
+ * require that you are using an architecture that uses PNG byte ordering
+ * (MSB first) and supports unaligned data storage.  I think that PowerPC
+ * in big-endian mode and 680x0 are the only ones that will support this.
+ * The x86 line of processors definitely do not.  The png_get_int_32()
+ * routine also assumes we are using two's complement format for negative
+ * values, which is almost certainly true.
+ */
+#if defined(PNG_READ_BIG_ENDIAN_SUPPORTED)
+#  if defined(PNG_pCAL_SUPPORTED) || defined(PNG_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_pCAL_SUPPORTED) || defined(PNG_oFFs_SUPPORTED)
+PNG_EXTERN png_int_32 png_get_int_32 PNGARG((png_bytep buf));
+#  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 */
+
+/* Initialize png_ptr struct for reading, and allocate any other memory.
+ * (old interface - DEPRECATED - use png_create_read_struct instead).
+ */
+extern PNG_EXPORT(void,png_read_init) PNGARG((png_structp png_ptr));
+#undef png_read_init
+#define png_read_init(png_ptr) png_read_init_3(&png_ptr, \
+    PNG_LIBPNG_VER_STRING,  sizeof(png_struct));
+extern PNG_EXPORT(void,png_read_init_3) PNGARG((png_structpp ptr_ptr,
+    png_const_charp user_png_ver, png_size_t png_struct_size));
+extern PNG_EXPORT(void,png_read_init_2) PNGARG((png_structp png_ptr,
+    png_const_charp user_png_ver, png_size_t png_struct_size, png_size_t
+    png_info_size));
+
+/* Initialize png_ptr struct for writing, and allocate any other memory.
+ * (old interface - DEPRECATED - use png_create_write_struct instead).
+ */
+extern PNG_EXPORT(void,png_write_init) PNGARG((png_structp png_ptr));
+#undef png_write_init
+#define png_write_init(png_ptr) png_write_init_3(&png_ptr, \
+    PNG_LIBPNG_VER_STRING, sizeof(png_struct));
+extern PNG_EXPORT(void,png_write_init_3) PNGARG((png_structpp ptr_ptr,
+    png_const_charp user_png_ver, png_size_t png_struct_size));
+extern PNG_EXPORT(void,png_write_init_2) PNGARG((png_structp png_ptr,
+    png_const_charp user_png_ver, png_size_t png_struct_size, png_size_t
+    png_info_size));
+
+/* Allocate memory for an internal libpng struct */
+PNG_EXTERN png_voidp png_create_struct PNGARG((int type));
+
+/* Free memory from internal libpng struct */
+PNG_EXTERN void png_destroy_struct PNGARG((png_voidp struct_ptr));
+
+PNG_EXTERN png_voidp png_create_struct_2 PNGARG((int type, png_malloc_ptr
+  malloc_fn, png_voidp mem_ptr));
+PNG_EXTERN void png_destroy_struct_2 PNGARG((png_voidp struct_ptr,
+   png_free_ptr free_fn, png_voidp mem_ptr));
+
+/* Free any memory that info_ptr points to and reset struct. */
+PNG_EXTERN void png_info_destroy PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+
+/* Function to allocate memory for zlib. */
+PNG_EXTERN voidpf png_zalloc PNGARG((voidpf png_ptr, uInt items, uInt size));
+
+/* Function to free memory for zlib */
+PNG_EXTERN void png_zfree PNGARG((voidpf png_ptr, voidpf ptr));
+
+/* Reset the CRC variable */
+PNG_EXTERN void png_reset_crc PNGARG((png_structp png_ptr));
+
+/* Write the "data" buffer to whatever output you are using. */
+PNG_EXTERN void png_write_data PNGARG((png_structp png_ptr, png_bytep data,
+   png_size_t length));
+
+/* Read data from whatever input you are using into the "data" buffer */
+PNG_EXTERN void png_read_data PNGARG((png_structp png_ptr, png_bytep data,
+   png_size_t length));
+
+/* Read bytes into buf, and update png_ptr->crc */
+PNG_EXTERN void png_crc_read PNGARG((png_structp png_ptr, png_bytep buf,
+   png_size_t length));
+
+/* Decompress data in a chunk that uses compression */
+#if defined(PNG_zTXt_SUPPORTED) || defined(PNG_iTXt_SUPPORTED) || \
+    defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED)
+PNG_EXTERN png_charp png_decompress_chunk PNGARG((png_structp png_ptr,
+   int comp_type, png_charp chunkdata, png_size_t chunklength,
+   png_size_t prefix_length, png_size_t *data_length));
+#endif
+
+/* Read "skip" bytes, read the file crc, and (optionally) verify png_ptr->crc */
+PNG_EXTERN int png_crc_finish PNGARG((png_structp png_ptr, png_uint_32 skip));
+
+/* Read the CRC from the file and compare it to the libpng calculated CRC */
+PNG_EXTERN int png_crc_error PNGARG((png_structp png_ptr));
+
+/* Calculate the CRC over a section of data.  Note that we are only
+ * passing a maximum of 64K on systems that have this as a memory limit,
+ * since this is the maximum buffer size we can specify.
+ */
+PNG_EXTERN void png_calculate_crc PNGARG((png_structp png_ptr, png_bytep ptr,
+   png_size_t length));
+
+#if defined(PNG_WRITE_FLUSH_SUPPORTED)
+PNG_EXTERN void png_flush PNGARG((png_structp png_ptr));
+#endif
+
+/* Place a 32-bit number into a buffer in PNG byte order (big-endian).
+ * The only currently known PNG chunks that use signed numbers are
+ * the ancillary extension chunks, oFFs and pCAL.
+ */
+PNG_EXTERN void png_save_uint_32 PNGARG((png_bytep buf, png_uint_32 i));
+
+#if defined(PNG_WRITE_pCAL_SUPPORTED)
+PNG_EXTERN void png_save_int_32 PNGARG((png_bytep buf, png_int_32 i));
+#endif
+
+/* Place a 16-bit number into a buffer in PNG byte order.
+ * The parameter is declared unsigned int, not png_uint_16,
+ * just to avoid potential problems on pre-ANSI C compilers.
+ */
+PNG_EXTERN void png_save_uint_16 PNGARG((png_bytep buf, unsigned int i));
+
+/* simple function to write the signature */
+PNG_EXTERN void png_write_sig PNGARG((png_structp png_ptr));
+
+/* write various chunks */
+
+/* Write the IHDR chunk, and update the png_struct with the necessary
+ * information.
+ */
+PNG_EXTERN void png_write_IHDR PNGARG((png_structp png_ptr, png_uint_32 width,
+   png_uint_32 height,
+   int bit_depth, int color_type, int compression_method, int filter_method,
+   int interlace_method));
+
+PNG_EXTERN void png_write_PLTE PNGARG((png_structp png_ptr, png_colorp palette,
+   png_uint_32 num_pal));
+
+PNG_EXTERN void png_write_IDAT PNGARG((png_structp png_ptr, png_bytep data,
+   png_size_t length));
+
+PNG_EXTERN void png_write_IEND PNGARG((png_structp png_ptr));
+
+#if defined(PNG_WRITE_gAMA_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+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_fixed_point
+    file_gamma));
+#endif
+#endif
+
+#if defined(PNG_WRITE_sBIT_SUPPORTED)
+PNG_EXTERN void png_write_sBIT PNGARG((png_structp png_ptr, png_color_8p sbit,
+   int color_type));
+#endif
+
+#if defined(PNG_WRITE_cHRM_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+PNG_EXTERN void png_write_cHRM PNGARG((png_structp png_ptr,
+   double white_x, double white_y,
+   double red_x, double red_y, double green_x, double green_y,
+   double blue_x, double blue_y));
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+PNG_EXTERN void png_write_cHRM_fixed PNGARG((png_structp png_ptr,
+   png_fixed_point int_white_x, png_fixed_point int_white_y,
+   png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point
+   int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x,
+   png_fixed_point int_blue_y));
+#endif
+#endif
+
+#if defined(PNG_WRITE_sRGB_SUPPORTED)
+PNG_EXTERN void png_write_sRGB PNGARG((png_structp png_ptr,
+   int intent));
+#endif
+
+#if defined(PNG_WRITE_iCCP_SUPPORTED)
+PNG_EXTERN void png_write_iCCP PNGARG((png_structp png_ptr,
+   png_charp name, int compression_type,
+   png_charp profile, int proflen));
+   /* Note to maintainer: profile should be png_bytep */
+#endif
+
+#if defined(PNG_WRITE_sPLT_SUPPORTED)
+PNG_EXTERN void png_write_sPLT PNGARG((png_structp png_ptr,
+   png_sPLT_tp palette));
+#endif
+
+#if defined(PNG_WRITE_tRNS_SUPPORTED)
+PNG_EXTERN void png_write_tRNS PNGARG((png_structp png_ptr, png_bytep trans,
+   png_color_16p values, int number, int color_type));
+#endif
+
+#if defined(PNG_WRITE_bKGD_SUPPORTED)
+PNG_EXTERN void png_write_bKGD PNGARG((png_structp png_ptr,
+   png_color_16p values, int color_type));
+#endif
+
+#if defined(PNG_WRITE_hIST_SUPPORTED)
+PNG_EXTERN void png_write_hIST PNGARG((png_structp png_ptr, png_uint_16p hist,
+   int num_hist));
+#endif
+
+#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_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,
+   png_charp key, png_charpp new_key));
+#endif
+
+#if defined(PNG_WRITE_tEXt_SUPPORTED)
+PNG_EXTERN void png_write_tEXt PNGARG((png_structp png_ptr, png_charp key,
+   png_charp text, png_size_t text_len));
+#endif
+
+#if defined(PNG_WRITE_zTXt_SUPPORTED)
+PNG_EXTERN void png_write_zTXt PNGARG((png_structp png_ptr, png_charp key,
+   png_charp text, png_size_t text_len, int compression));
+#endif
+
+#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 lang_key,
+   png_charp text));
+#endif
+
+#if defined(PNG_WRITE_oFFs_SUPPORTED)
+PNG_EXTERN void png_write_oFFs PNGARG((png_structp png_ptr,
+   png_uint_32 x_offset, png_uint_32 y_offset, int unit_type));
+#endif
+
+#if defined(PNG_WRITE_pCAL_SUPPORTED)
+PNG_EXTERN void png_write_pCAL PNGARG((png_structp png_ptr, png_charp purpose,
+   png_int_32 X0, png_int_32 X1, int type, int nparams,
+   png_charp units, png_charpp params));
+#endif
+
+#if defined(PNG_WRITE_pHYs_SUPPORTED)
+PNG_EXTERN void png_write_pHYs PNGARG((png_structp png_ptr,
+   png_uint_32 x_pixels_per_unit, png_uint_32 y_pixels_per_unit,
+   int unit_type));
+#endif
+
+#if defined(PNG_WRITE_tIME_SUPPORTED)
+PNG_EXTERN void png_write_tIME PNGARG((png_structp png_ptr,
+   png_timep mod_time));
+#endif
+
+#if defined(PNG_WRITE_sCAL_SUPPORTED)
+#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO)
+PNG_EXTERN void png_write_sCAL PNGARG((png_structp png_ptr,
+   int unit, double width, double height));
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+PNG_EXTERN void png_write_sCAL_s PNGARG((png_structp png_ptr,
+   int unit, png_charp width, png_charp height));
+#endif
+#endif
+#endif
+
+/* Called when finished processing a row of data */
+PNG_EXTERN void png_write_finish_row PNGARG((png_structp png_ptr));
+
+/* Internal use only.   Called before first row of data */
+PNG_EXTERN void png_write_start_row PNGARG((png_structp png_ptr));
+
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr));
+#endif
+
+/* combine a row of data, dealing with alpha, etc. if requested */
+PNG_EXTERN void png_combine_row PNGARG((png_structp png_ptr, png_bytep row,
+   int mask));
+
+#if defined(PNG_READ_INTERLACING_SUPPORTED)
+/* expand an interlaced row */
+/* OLD pre-1.0.9 interface:
+PNG_EXTERN void png_do_read_interlace PNGARG((png_row_infop row_info,
+   png_bytep row, int pass, png_uint_32 transformations));
+ */
+PNG_EXTERN void png_do_read_interlace PNGARG((png_structp png_ptr));
+#endif
+
+/* GRR TO DO (2.0 or whenever):  simplify other internal calling interfaces */
+
+#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
+/* grab pixels out of a row for an interlaced pass */
+PNG_EXTERN void png_do_write_interlace PNGARG((png_row_infop row_info,
+   png_bytep row, int pass));
+#endif
+
+/* unfilter a row */
+PNG_EXTERN void png_read_filter_row PNGARG((png_structp png_ptr,
+   png_row_infop row_info, png_bytep row, png_bytep prev_row, int filter));
+
+/* Choose the best filter to use and filter the row data */
+PNG_EXTERN void png_write_find_filter PNGARG((png_structp png_ptr,
+   png_row_infop row_info));
+
+/* Write out the filtered row. */
+PNG_EXTERN void png_write_filtered_row PNGARG((png_structp png_ptr,
+   png_bytep filtered_row));
+/* finish a row while reading, dealing with interlacing passes, etc. */
+PNG_EXTERN void png_read_finish_row PNGARG((png_structp png_ptr));
+
+/* initialize the row buffers, etc. */
+PNG_EXTERN void png_read_start_row PNGARG((png_structp png_ptr));
+/* optional call to update the users info structure */
+PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+
+/* these are the functions that do the transformations */
+#if defined(PNG_READ_FILLER_SUPPORTED)
+PNG_EXTERN void png_do_read_filler PNGARG((png_row_infop row_info,
+   png_bytep row, png_uint_32 filler, png_uint_32 flags));
+#endif
+
+#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
+PNG_EXTERN void png_do_read_swap_alpha PNGARG((png_row_infop row_info,
+   png_bytep row));
+#endif
+
+#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
+PNG_EXTERN void png_do_write_swap_alpha PNGARG((png_row_infop row_info,
+   png_bytep row));
+#endif
+
+#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
+PNG_EXTERN void png_do_read_invert_alpha PNGARG((png_row_infop row_info,
+   png_bytep row));
+#endif
+
+#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
+PNG_EXTERN void png_do_write_invert_alpha PNGARG((png_row_infop row_info,
+   png_bytep row));
+#endif
+
+#if defined(PNG_WRITE_FILLER_SUPPORTED) || \
+    defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
+PNG_EXTERN void png_do_strip_filler PNGARG((png_row_infop row_info,
+   png_bytep row, png_uint_32 flags));
+#endif
+
+#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
+PNG_EXTERN void png_do_swap PNGARG((png_row_infop row_info, png_bytep row));
+#endif
+
+#if defined(PNG_READ_PACKSWAP_SUPPORTED) || defined(PNG_WRITE_PACKSWAP_SUPPORTED)
+PNG_EXTERN void png_do_packswap PNGARG((png_row_infop row_info, png_bytep row));
+#endif
+
+#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+PNG_EXTERN int png_do_rgb_to_gray PNGARG((png_structp png_ptr, png_row_infop
+   row_info, png_bytep row));
+#endif
+
+#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
+PNG_EXTERN void png_do_gray_to_rgb PNGARG((png_row_infop row_info,
+   png_bytep row));
+#endif
+
+#if defined(PNG_READ_PACK_SUPPORTED)
+PNG_EXTERN void png_do_unpack PNGARG((png_row_infop row_info, png_bytep row));
+#endif
+
+#if defined(PNG_READ_SHIFT_SUPPORTED)
+PNG_EXTERN void png_do_unshift PNGARG((png_row_infop row_info, png_bytep row,
+   png_color_8p sig_bits));
+#endif
+
+#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
+PNG_EXTERN void png_do_invert PNGARG((png_row_infop row_info, png_bytep row));
+#endif
+
+#if defined(PNG_READ_16_TO_8_SUPPORTED)
+PNG_EXTERN void png_do_chop PNGARG((png_row_infop row_info, png_bytep row));
+#endif
+
+#if defined(PNG_READ_DITHER_SUPPORTED)
+PNG_EXTERN void png_do_dither PNGARG((png_row_infop row_info,
+   png_bytep row, png_bytep palette_lookup, png_bytep dither_lookup));
+
+#  if defined(PNG_CORRECT_PALETTE_SUPPORTED)
+PNG_EXTERN void png_correct_palette PNGARG((png_structp png_ptr,
+   png_colorp palette, int num_palette));
+#  endif
+#endif
+
+#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
+PNG_EXTERN void png_do_bgr PNGARG((png_row_infop row_info, png_bytep row));
+#endif
+
+#if defined(PNG_WRITE_PACK_SUPPORTED)
+PNG_EXTERN void png_do_pack PNGARG((png_row_infop row_info,
+   png_bytep row, png_uint_32 bit_depth));
+#endif
+
+#if defined(PNG_WRITE_SHIFT_SUPPORTED)
+PNG_EXTERN void png_do_shift PNGARG((png_row_infop row_info, png_bytep row,
+   png_color_8p bit_depth));
+#endif
+
+#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, png_bytep row,
+   png_color_16p trans_values, png_color_16p background,
+   png_color_16p background_1,
+   png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
+   png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
+   png_uint_16pp gamma_16_to_1, int gamma_shift));
+#endif
+
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+PNG_EXTERN void png_do_gamma PNGARG((png_row_infop row_info, png_bytep row,
+   png_bytep gamma_table, png_uint_16pp gamma_16_table,
+   int gamma_shift));
+#endif
+
+#if defined(PNG_READ_EXPAND_SUPPORTED)
+PNG_EXTERN void png_do_expand_palette PNGARG((png_row_infop row_info,
+   png_bytep row, png_colorp palette, png_bytep trans, int num_trans));
+PNG_EXTERN void png_do_expand PNGARG((png_row_infop row_info,
+   png_bytep row, png_color_16p trans_value));
+#endif
+
+/* The following decodes the appropriate chunks, and does error correction,
+ * then calls the appropriate callback for the chunk if it is valid.
+ */
+
+/* decode the IHDR chunk */
+PNG_EXTERN void png_handle_IHDR PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 length));
+PNG_EXTERN void png_handle_PLTE PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 length));
+PNG_EXTERN void png_handle_IEND PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 length));
+
+#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_cHRM_SUPPORTED)
+PNG_EXTERN void png_handle_cHRM PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 length));
+#endif
+
+#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
+
+#if defined(PNG_READ_iCCP_SUPPORTED)
+extern void png_handle_iCCP PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 length));
+#endif /* PNG_READ_iCCP_SUPPORTED */
+
+#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
+
+#if defined(PNG_READ_oFFs_SUPPORTED)
+PNG_EXTERN void png_handle_oFFs PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 length));
+#endif
+
+#if defined(PNG_READ_pCAL_SUPPORTED)
+PNG_EXTERN void png_handle_pCAL 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_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
+
+#if defined(PNG_READ_tEXt_SUPPORTED)
+PNG_EXTERN void png_handle_tEXt 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,
+   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
+
+#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,
+   png_infop info_ptr, png_uint_32 length));
+
+PNG_EXTERN void png_check_chunk_name PNGARG((png_structp png_ptr,
+   png_bytep chunk_name));
+
+/* handle the transformations for reading and writing */
+PNG_EXTERN void png_do_read_transformations PNGARG((png_structp png_ptr));
+PNG_EXTERN void png_do_write_transformations PNGARG((png_structp png_ptr));
+
+PNG_EXTERN void png_init_read_transformations PNGARG((png_structp png_ptr));
+
+#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
+PNG_EXTERN void png_push_read_chunk PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+PNG_EXTERN void png_push_read_sig PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+PNG_EXTERN void png_push_check_crc PNGARG((png_structp png_ptr));
+PNG_EXTERN void png_push_crc_skip PNGARG((png_structp png_ptr,
+   png_uint_32 length));
+PNG_EXTERN void png_push_crc_finish PNGARG((png_structp png_ptr));
+PNG_EXTERN void png_push_fill_buffer PNGARG((png_structp png_ptr,
+   png_bytep buffer, png_size_t length));
+PNG_EXTERN void png_push_save_buffer PNGARG((png_structp png_ptr));
+PNG_EXTERN void png_push_restore_buffer PNGARG((png_structp png_ptr,
+   png_bytep buffer, png_size_t buffer_length));
+PNG_EXTERN void png_push_read_IDAT PNGARG((png_structp png_ptr));
+PNG_EXTERN void png_process_IDAT_data PNGARG((png_structp png_ptr,
+   png_bytep buffer, png_size_t buffer_length));
+PNG_EXTERN void png_push_process_row PNGARG((png_structp png_ptr));
+PNG_EXTERN void png_push_handle_unknown PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_uint_32 length));
+PNG_EXTERN void png_push_have_info PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+PNG_EXTERN void png_push_have_end PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+PNG_EXTERN void png_push_have_row PNGARG((png_structp png_ptr, png_bytep row));
+PNG_EXTERN void png_push_read_end PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+PNG_EXTERN void png_process_some_data PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+PNG_EXTERN void png_read_push_finish_row PNGARG((png_structp png_ptr));
+#if defined(PNG_READ_tEXt_SUPPORTED)
+PNG_EXTERN void png_push_handle_tEXt PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_uint_32 length));
+PNG_EXTERN void png_push_read_tEXt PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+#endif
+#if defined(PNG_READ_zTXt_SUPPORTED)
+PNG_EXTERN void png_push_handle_zTXt PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_uint_32 length));
+PNG_EXTERN void png_push_read_zTXt PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+#endif
+#if defined(PNG_READ_iTXt_SUPPORTED)
+PNG_EXTERN void png_push_handle_iTXt PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_uint_32 length));
+PNG_EXTERN void png_push_read_iTXt PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+#endif
+
+#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
+
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+PNG_EXTERN void png_do_read_intrapixel PNGARG((png_row_infop row_info,
+   png_bytep row));
+PNG_EXTERN void png_do_write_intrapixel PNGARG((png_row_infop row_info,
+   png_bytep row));
+#endif
+
+/* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */
+
+#endif /* PNG_INTERNAL */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PNG_VERSION_INFO_ONLY */
+/* do not put anything past this line */
+#endif /* PNG_H */
diff --git a/Utilities/ITK/Utilities/png/pngDllConfig.h.in b/Utilities/ITK/Utilities/png/pngDllConfig.h.in
new file mode 100644
index 0000000000..40b05b3938
--- /dev/null
+++ b/Utilities/ITK/Utilities/png/pngDllConfig.h.in
@@ -0,0 +1,11 @@
+#ifndef _pngDllConfig_h
+#define _pngDllConfig_h
+
+#cmakedefine PNG_STATIC
+#cmakedefine PNG_NO_MODULEDEF
+
+#if defined(_WIN32) && !defined(PNG_STATIC) && !defined(PNG_BUILD_DLL)
+#  define PNG_USE_DLL
+#endif
+
+#endif
diff --git a/Utilities/ITK/Utilities/png/pngasmrd.h b/Utilities/ITK/Utilities/png/pngasmrd.h
new file mode 100644
index 0000000000..2db18524df
--- /dev/null
+++ b/Utilities/ITK/Utilities/png/pngasmrd.h
@@ -0,0 +1,11 @@
+/* pngasmrd.h - assembler version of utilities to read a PNG file
+ *
+ * libpng 1.0.12 - June 8, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 2001 Glenn Randers-Pehrson
+ *
+ */
+
+/* This file is obsolete in libpng-1.0.9 and later; its contents now appear
+ * at the end of pngconf.h.
+ */
diff --git a/Utilities/ITK/Utilities/png/pngconf.h b/Utilities/ITK/Utilities/png/pngconf.h
new file mode 100644
index 0000000000..e188fa5e66
--- /dev/null
+++ b/Utilities/ITK/Utilities/png/pngconf.h
@@ -0,0 +1,1341 @@
+#include "itk_png_mangle.h"
+/* pngconf.h - machine configurable file for libpng
+ *
+ * libpng 1.0.12 - June 8, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ */
+
+/* Any machine specific code is near the front of this file, so if you
+ * are configuring libpng for a machine, you may want to read the section
+ * starting here down to where it starts to typedef png_color, png_text,
+ * and png_info.
+ */
+
+#ifndef PNGCONF_H
+#define PNGCONF_H
+
+#include "pngDllConfig.h"
+
+/* This is the size of the compression buffer, and thus the size of
+ * an IDAT chunk.  Make this whatever size you feel is best for your
+ * machine.  One of these will be allocated per png_struct.  When this
+ * is full, it writes the data to the disk, and does some other
+ * calculations.  Making this an extremely small size will slow
+ * the library down, but you may want to experiment to determine
+ * where it becomes significant, if you are concerned with memory
+ * usage.  Note that zlib allocates at least 32Kb also.  For readers,
+ * this describes the size of the buffer available to read the data in.
+ * Unless this gets smaller than the size of a row (compressed),
+ * it should not make much difference how big this is.
+ */
+
+#ifndef PNG_ZBUF_SIZE
+#  define PNG_ZBUF_SIZE 8192
+#endif
+
+/* Enable if you want a write-only libpng */
+
+#ifndef PNG_NO_READ_SUPPORTED
+#  define PNG_READ_SUPPORTED
+#endif
+
+/* Enable if you want a read-only libpng */
+
+#ifndef PNG_NO_WRITE_SUPPORTED
+#  define PNG_WRITE_SUPPORTED
+#endif
+
+/* Enabled by default in 1.2.0.  You can disable this if you don't need to
+   support PNGs that are embedded in MNG datastreams */
+/*
+#ifndef PNG_NO_MNG_FEATURES
+#  ifndef PNG_MNG_FEATURES_SUPPORTED
+#    define PNG_MNG_FEATURES_SUPPORTED
+#  endif
+#endif
+*/
+
+#ifndef PNG_NO_FLOATING_POINT_SUPPORTED
+#  ifndef PNG_FLOATING_POINT_SUPPORTED
+#    define PNG_FLOATING_POINT_SUPPORTED
+#  endif
+#endif
+
+/* If you are running on a machine where you cannot allocate more
+ * than 64K of memory at once, uncomment this.  While libpng will not
+ * normally need that much memory in a chunk (unless you load up a very
+ * large file), zlib needs to know how big of a chunk it can use, and
+ * libpng thus makes sure to check any memory allocation to verify it
+ * will fit into memory.
+#define PNG_MAX_MALLOC_64K
+ */
+#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K)
+#  define PNG_MAX_MALLOC_64K
+#endif
+
+/* Special munging to support doing things the 'cygwin' way:
+ * 'Normal' png-on-win32 defines/defaults:
+ *   PNG_BUILD_DLL -- building dll
+ *   PNG_USE_DLL   -- building an application, linking to dll
+ *   (no define)   -- building static library, or building an
+ *                    application and linking to the static lib
+ * 'Cygwin' defines/defaults:
+ *   PNG_BUILD_DLL -- building the dll
+ *   (no define)   -- building an application, linking to the dll
+ *   PNG_STATIC    -- building the static lib, or building an application
+ *                    that links to the static lib.
+ *   ALL_STATIC    -- building various static libs, or building an application
+ *                    that links to the static libs.
+ * Thus,
+ * a cygwin user should define either PNG_BUILD_DLL or PNG_STATIC, and
+ * this bit of #ifdefs will define the 'correct' config variables based on
+ * that. If a cygwin user *wants* to define 'PNG_USE_DLL' that's okay, but
+ * unnecessary.
+ *
+ * Also, the precedence order is:
+ *   ALL_STATIC (since we can't #undef something outside our namespace)
+ *   PNG_BUILD_DLL
+ *   PNG_STATIC
+ *   (nothing) == PNG_USE_DLL 
+ */
+#if defined(__CYGWIN__)
+#  if defined(ALL_STATIC)
+#    if defined(PNG_BUILD_DLL)
+#      undef PNG_BUILD_DLL
+#    endif
+#    if defined(PNG_USE_DLL)
+#      undef PNG_USE_DLL
+#    endif
+#    if defined(PNG_DLL)
+#      undef PNG_DLL
+#    endif
+#    if !defined(PNG_STATIC)
+#      define PNG_STATIC
+#    endif
+#  else
+#    if defined (PNG_BUILD_DLL)
+#      if defined(PNG_STATIC)
+#        undef PNG_STATIC
+#      endif
+#      if defined(PNG_USE_DLL)
+#        undef PNG_USE_DLL
+#      endif
+#      if !defined(PNG_DLL)
+#        define PNG_DLL
+#      endif
+#    else
+#      if defined(PNG_STATIC)
+#        if defined(PNG_USE_DLL)
+#          undef PNG_USE_DLL
+#        endif
+#        if defined(PNG_DLL)
+#          undef PNG_DLL
+#        endif
+#      else
+#        if !defined(PNG_USE_DLL)
+#          define PNG_USE_DLL
+#        endif
+#        if !defined(PNG_DLL)
+#          define PNG_DLL
+#        endif
+#      endif  
+#    endif  
+#  endif
+#endif
+
+/* This protects us against compilers that run on a windowing system
+ * and thus don't have or would rather us not use the stdio types:
+ * stdin, stdout, and stderr.  The only one currently used is stderr
+ * in png_error() and png_warning().  #defining PNG_NO_CONSOLE_IO will
+ * prevent these from being compiled and used. #defining PNG_NO_STDIO
+ * will also prevent these, plus will prevent the entire set of stdio
+ * macros and functions (FILE *, printf, etc.) from being compiled and used,
+ * unless (PNG_DEBUG > 0) has been #defined.
+ *
+ * #define PNG_NO_CONSOLE_IO
+ * #define PNG_NO_STDIO
+ */
+
+#if defined(_WIN32_WCE)
+#  include <windows.h>
+   /* Console I/O functions are not supported on WindowsCE */
+#  define PNG_NO_CONSOLE_IO
+#  ifdef PNG_DEBUG
+#    undef PNG_DEBUG
+#  endif
+#endif
+
+#ifdef PNG_BUILD_DLL
+#  ifndef PNG_CONSOLE_IO_SUPPORTED
+#    ifndef PNG_NO_CONSOLE_IO
+#      define PNG_NO_CONSOLE_IO
+#    endif
+#  endif
+#endif
+
+#  ifdef PNG_NO_STDIO
+#    ifndef PNG_NO_CONSOLE_IO
+#      define PNG_NO_CONSOLE_IO
+#    endif
+#    ifdef PNG_DEBUG
+#      if (PNG_DEBUG > 0)
+#        include <stdio.h>
+#      endif
+#    endif
+#  else
+#    if !defined(_WIN32_WCE)
+/* "stdio.h" functions are not supported on WindowsCE */
+#      include <stdio.h>
+#    endif
+#  endif
+
+/* This macro protects us against machines that don't have function
+ * prototypes (ie K&R style headers).  If your compiler does not handle
+ * function prototypes, define this macro and use the included ansi2knr.
+ * I've always been able to use _NO_PROTO as the indicator, but you may
+ * need to drag the empty declaration out in front of here, or change the
+ * ifdef to suit your own needs.
+ */
+#ifndef PNGARG
+
+#ifdef OF /* zlib prototype munger */
+#  define PNGARG(arglist) OF(arglist)
+#else
+
+#ifdef _NO_PROTO
+#  define PNGARG(arglist) ()
+#else
+#  define PNGARG(arglist) arglist
+#endif /* _NO_PROTO */
+
+#endif /* OF */
+
+#endif /* PNGARG */
+
+/* Try to determine if we are compiling on a Mac.  Note that testing for
+ * just __MWERKS__ is not good enough, because the Codewarrior is now used
+ * on non-Mac platforms.
+ */
+#ifndef MACOS
+#  if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \
+      defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC)
+#    define MACOS
+#  endif
+#endif
+
+/* enough people need this for various reasons to include it here */
+#if !defined(MACOS) && !defined(RISCOS) && !defined(_WIN32_WCE)
+#  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
+#  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__ */
+#endif /* PNG_SETJMP_SUPPORTED */
+
+#ifdef BSD
+#  include <strings.h>
+#else
+#  include <string.h>
+#endif
+
+/* Other defines for things like memory and the like can go here.  */
+#ifdef PNG_INTERNAL
+
+#include <stdlib.h>
+
+/* The functions exported by PNG_EXTERN are PNG_INTERNAL functions, which
+ * aren't usually used outside the library (as far as I know), so it is
+ * debatable if they should be exported at all.  In the future, when it is
+ * possible to have run-time registry of chunk-handling functions, some of
+ * these will be made available again.
+#define PNG_EXTERN extern
+ */
+#define PNG_EXTERN
+
+/* Other defines specific to compilers can go here.  Try to keep
+ * them inside an appropriate ifdef/endif pair for portability.
+ */
+
+#if defined(PNG_FLOATING_POINT_SUPPORTED)
+#  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
+      * <fp.h> if possible.
+      */
+#    if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__)
+#      include <fp.h>
+#    endif
+#  else
+#    include <math.h>
+#  endif
+#  if defined(_AMIGA) && defined(__SASC) && defined(_M68881)
+     /* Amiga SAS/C: We must include builtin FPU functions when compiling using
+      * MATH=68881
+      */
+#    include <m68881.h>
+#  endif
+#endif
+
+/* Codewarrior on NT has linking problems without this. */
+#if (defined(__MWERKS__) && defined(WIN32)) || defined(__STDC__)
+#  define PNG_ALWAYS_EXTERN
+#endif
+
+/* For some reason, Borland C++ defines memcmp, etc. in mem.h, not
+ * stdlib.h like it should (I think).  Or perhaps this is a C++
+ * "feature"?
+ */
+#if 0
+#ifdef __TURBOC__
+#  include <mem.h>
+#  include "alloc.h"
+#endif
+#endif
+
+#if defined(_MSC_VER) && (defined(WIN32) || defined(_Windows) || \
+    defined(_WINDOWS) || defined(_WIN32) || defined(__WIN32__))
+#  include <malloc.h>
+#endif
+
+/* This controls how fine the dithering gets.  As this allocates
+ * a largish chunk of memory (32K), those who are not as concerned
+ * with dithering quality can decrease some or all of these.
+ */
+#ifndef PNG_DITHER_RED_BITS
+#  define PNG_DITHER_RED_BITS 5
+#endif
+#ifndef PNG_DITHER_GREEN_BITS
+#  define PNG_DITHER_GREEN_BITS 5
+#endif
+#ifndef PNG_DITHER_BLUE_BITS
+#  define PNG_DITHER_BLUE_BITS 5
+#endif
+
+/* This controls how fine the gamma correction becomes when you
+ * are only interested in 8 bits anyway.  Increasing this value
+ * results in more memory being used, and more pow() functions
+ * being called to fill in the gamma tables.  Don't set this value
+ * less then 8, and even that may not work (I haven't tested it).
+ */
+
+#ifndef PNG_MAX_GAMMA_8
+#  define PNG_MAX_GAMMA_8 11
+#endif
+
+/* This controls how much a difference in gamma we can tolerate before
+ * we actually start doing gamma conversion.
+ */
+#ifndef PNG_GAMMA_THRESHOLD
+#  define PNG_GAMMA_THRESHOLD 0.05
+#endif
+
+#endif /* PNG_INTERNAL */
+
+/* The following uses const char * instead of char * for error
+ * and warning message functions, so some compilers won't complain.
+ * If you do not want to use const, define PNG_NO_CONST here.
+ */
+
+#ifndef PNG_NO_CONST
+#  define PNG_CONST const
+#else
+#  define PNG_CONST
+#endif
+
+/* The following defines give you the ability to remove code from the
+ * library that you will not be using.  I wish I could figure out how to
+ * automate this, but I can't do that without making it seriously hard
+ * on the users.  So if you are not using an ability, change the #define
+ * to and #undef, and that part of the library will not be compiled.  If
+ * your linker can't find a function, you may want to make sure the
+ * ability is defined here.  Some of these depend upon some others being
+ * defined.  I haven't figured out all the interactions here, so you may
+ * have to experiment awhile to get everything to compile.  If you are
+ * creating or using a shared library, you probably shouldn't touch this,
+ * as it will affect the size of the structures, and this will cause bad
+ * things to happen if the library and/or application ever change.
+ */
+
+/* Any features you will not be using can be undef'ed here */
+
+/* GR-P, 0.96a: Set "*TRANSFORMS_SUPPORTED as default but allow user
+ * to turn it off with "*TRANSFORMS_NOT_SUPPORTED" or *PNG_NO_*_TRANSFORMS
+ * on the compile line, then pick and choose which ones to define without
+ * having to edit this file. It is safe to use the *TRANSFORMS_NOT_SUPPORTED
+ * if you only want to have a png-compliant reader/writer but don't need
+ * any of the extra transformations.  This saves about 80 kbytes in a
+ * typical installation of the library. (PNG_NO_* form added in version
+ * 1.0.1c, for consistency)
+ */
+
+/* The size of the png_text structure changed in libpng-1.0.6 when
+ * iTXt is supported.  It is turned off by default, to support old apps
+ * that malloc the png_text structure instead of calling png_set_text()
+ * and letting libpng malloc it.  It will be turned on by default in
+ * libpng-1.3.0.
+ */
+
+#ifndef PNG_iTXt_SUPPORTED
+#  ifndef PNG_READ_iTXt_SUPPORTED
+#    define PNG_NO_READ_iTXt
+#  endif
+#  ifndef PNG_WRITE_iTXt_SUPPORTED
+#    define PNG_NO_WRITE_iTXt
+#  endif
+#endif
+
+/* The following support, added after version 1.0.0, can be turned off here en
+ * masse by defining PNG_LEGACY_SUPPORTED in case you need binary compatibility
+ * with old applications that require the length of png_struct and png_info
+ * to remain unchanged.
+ */
+
+#ifdef PNG_LEGACY_SUPPORTED
+#  define PNG_NO_FREE_ME
+#  define PNG_NO_READ_UNKNOWN_CHUNKS
+#  define PNG_NO_WRITE_UNKNOWN_CHUNKS
+#  define PNG_NO_READ_USER_CHUNKS
+#  define PNG_NO_READ_iCCP
+#  define PNG_NO_WRITE_iCCP
+#  define PNG_NO_READ_iTXt
+#  define PNG_NO_WRITE_iTXt
+#  define PNG_NO_READ_sCAL
+#  define PNG_NO_WRITE_sCAL
+#  define PNG_NO_READ_sPLT
+#  define PNG_NO_WRITE_sPLT
+#  define PNG_NO_INFO_IMAGE
+#  define PNG_NO_READ_RGB_TO_GRAY
+#  define PNG_NO_READ_USER_TRANSFORM
+#  define PNG_NO_WRITE_USER_TRANSFORM
+#  define PNG_NO_USER_MEM
+#  define PNG_NO_READ_EMPTY_PLTE
+#  define PNG_NO_MNG_FEATURES
+#  define PNG_NO_FIXED_POINT_SUPPORTED
+#endif
+
+/* Ignore attempt to turn off both floating and fixed point support */
+#if !defined(PNG_FLOATING_POINT_SUPPORTED) || \
+    !defined(PNG_NO_FIXED_POINT_SUPPORTED)
+#  define PNG_FIXED_POINT_SUPPORTED
+#endif
+
+#ifndef PNG_NO_FREE_ME
+#  define PNG_FREE_ME_SUPPORTED
+#endif
+
+#if defined(PNG_READ_SUPPORTED)
+
+#if !defined(PNG_READ_TRANSFORMS_NOT_SUPPORTED) && \
+      !defined(PNG_NO_READ_TRANSFORMS)
+#  define PNG_READ_TRANSFORMS_SUPPORTED
+#endif
+
+#ifdef PNG_READ_TRANSFORMS_SUPPORTED
+#  ifndef PNG_NO_READ_EXPAND
+#    define PNG_READ_EXPAND_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_SHIFT
+#    define PNG_READ_SHIFT_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_PACK
+#    define PNG_READ_PACK_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_BGR
+#    define PNG_READ_BGR_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_SWAP
+#    define PNG_READ_SWAP_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_PACKSWAP
+#    define PNG_READ_PACKSWAP_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_INVERT
+#    define PNG_READ_INVERT_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_DITHER
+#    define PNG_READ_DITHER_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_BACKGROUND
+#    define PNG_READ_BACKGROUND_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_16_TO_8
+#    define PNG_READ_16_TO_8_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_FILLER
+#    define PNG_READ_FILLER_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_GAMMA
+#    define PNG_READ_GAMMA_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_GRAY_TO_RGB
+#    define PNG_READ_GRAY_TO_RGB_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_SWAP_ALPHA
+#    define PNG_READ_SWAP_ALPHA_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_INVERT_ALPHA
+#    define PNG_READ_INVERT_ALPHA_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_STRIP_ALPHA
+#    define PNG_READ_STRIP_ALPHA_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_USER_TRANSFORM
+#    define PNG_READ_USER_TRANSFORM_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_RGB_TO_GRAY
+#    define PNG_READ_RGB_TO_GRAY_SUPPORTED
+#  endif
+#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
+
+#if !defined(PNG_NO_PROGRESSIVE_READ) && \
+ !defined(PNG_PROGRESSIVE_READ_NOT_SUPPORTED)  /* if you don't do progressive */
+#  define PNG_PROGRESSIVE_READ_SUPPORTED     /* reading.  This is not talking */
+#endif                               /* about interlacing capability!  You'll */
+              /* still have interlacing unless you change the following line: */
+
+#define PNG_READ_INTERLACING_SUPPORTED /* required for PNG-compliant decoders */
+
+#ifndef PNG_NO_READ_COMPOSITE_NODIV
+#  ifndef PNG_NO_READ_COMPOSITED_NODIV  /* libpng-1.0.x misspelling */
+#    define PNG_READ_COMPOSITE_NODIV_SUPPORTED   /* well tested on Intel, SGI */
+#  endif
+#endif
+
+/* Deprecated, will be removed from version 2.0.0.
+   Use PNG_MNG_FEATURES_SUPPORTED instead. */
+#ifndef PNG_NO_READ_EMPTY_PLTE
+#  define PNG_READ_EMPTY_PLTE_SUPPORTED
+#endif
+
+#endif /* PNG_READ_SUPPORTED */
+
+#if defined(PNG_WRITE_SUPPORTED)
+
+# if !defined(PNG_WRITE_TRANSFORMS_NOT_SUPPORTED) && \
+    !defined(PNG_NO_WRITE_TRANSFORMS)
+#  define PNG_WRITE_TRANSFORMS_SUPPORTED
+#endif
+
+#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
+#  ifndef PNG_NO_WRITE_SHIFT
+#    define PNG_WRITE_SHIFT_SUPPORTED
+#  endif
+#  ifndef PNG_NO_WRITE_PACK
+#    define PNG_WRITE_PACK_SUPPORTED
+#  endif
+#  ifndef PNG_NO_WRITE_BGR
+#    define PNG_WRITE_BGR_SUPPORTED
+#  endif
+#  ifndef PNG_NO_WRITE_SWAP
+#    define PNG_WRITE_SWAP_SUPPORTED
+#  endif
+#  ifndef PNG_NO_WRITE_PACKSWAP
+#    define PNG_WRITE_PACKSWAP_SUPPORTED
+#  endif
+#  ifndef PNG_NO_WRITE_INVERT
+#    define PNG_WRITE_INVERT_SUPPORTED
+#  endif
+#  ifndef PNG_NO_WRITE_FILLER
+#    define PNG_WRITE_FILLER_SUPPORTED   /* same as WRITE_STRIP_ALPHA */
+#  endif
+#  ifndef PNG_NO_WRITE_SWAP_ALPHA
+#    define PNG_WRITE_SWAP_ALPHA_SUPPORTED
+#  endif
+#  ifndef PNG_NO_WRITE_INVERT_ALPHA
+#    define PNG_WRITE_INVERT_ALPHA_SUPPORTED
+#  endif
+#  ifndef PNG_NO_WRITE_USER_TRANSFORM
+#    define PNG_WRITE_USER_TRANSFORM_SUPPORTED
+#  endif
+#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */
+
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
+    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
+#  ifndef PNG_NO_USER_TRANSFORM_PTR
+#    define PNG_USER_TRANSFORM_PTR_SUPPORTED
+#  endif
+#endif
+
+#define PNG_WRITE_INTERLACING_SUPPORTED  /* not required for PNG-compliant
+                                            encoders, but can cause trouble
+                                            if left undefined */
+
+#if !defined(PNG_NO_WRITE_WEIGHTED_FILTER) && \
+     defined(PNG_FLOATING_POINT_SUPPORTED)
+#  define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
+#endif
+
+/* Will be enabled in libpng-1.2.0 */
+/*
+#ifndef PNG_NO_ERROR_NUMBERS
+#define PNG_ERROR_NUMBERS_SUPPORTED
+#endif
+*/
+
+#ifndef PNG_NO_WRITE_FLUSH
+#  define PNG_WRITE_FLUSH_SUPPORTED
+#endif
+
+/* Deprecated, see PNG_MNG_FEATURES_SUPPORTED, above */
+#ifndef PNG_NO_WRITE_EMPTY_PLTE
+#  define PNG_WRITE_EMPTY_PLTE_SUPPORTED
+#endif
+
+#endif /* PNG_WRITE_SUPPORTED */
+
+#ifndef PNG_NO_STDIO
+#  define PNG_TIME_RFC1123_SUPPORTED
+#endif
+
+/* This adds extra functions in pngget.c for accessing data from the
+ * info pointer (added in version 0.99)
+ * png_get_image_width()
+ * png_get_image_height()
+ * png_get_bit_depth()
+ * png_get_color_type()
+ * png_get_compression_type()
+ * png_get_filter_type()
+ * png_get_interlace_type()
+ * png_get_pixel_aspect_ratio()
+ * png_get_pixels_per_meter()
+ * png_get_x_offset_pixels()
+ * png_get_y_offset_pixels()
+ * png_get_x_offset_microns()
+ * png_get_y_offset_microns()
+ */
+#if !defined(PNG_NO_EASY_ACCESS) && !defined(PNG_EASY_ACCESS_SUPPORTED)
+#  define PNG_EASY_ACCESS_SUPPORTED
+#endif
+
+/* PNG_ASSEMBLER_CODE was enabled by default in version 1.2.0 
+   even when PNG_USE_PNGVCRD or PNG_USE_PNGGCCRD is not defined */
+/*
+#if defined(PNG_READ_SUPPORTED) && !defined(PNG_NO_ASSEMBLER_CODE)
+#  ifndef PNG_ASSEMBLER_CODE_SUPPORTED
+#    define PNG_ASSEMBLER_CODE_SUPPORTED
+#  endif
+#  if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE)
+#    define PNG_MMX_CODE_SUPPORTED
+#  endif
+#endif
+*/
+#if defined(PNG_READ_SUPPORTED) && !defined(PNG_NO_ASSEMBLER_CODE)
+#  if defined(PNG_USE_PNGVCRD) || defined(PNG_USE_PNGGCCRD)
+#    ifndef PNG_ASSEMBLER_CODE_SUPPORTED
+#      define PNG_ASSEMBLER_CODE_SUPPORTED
+#    endif
+#    if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE)
+#      define PNG_MMX_CODE_SUPPORTED
+#    endif
+#  endif
+#endif
+
+/* This will be enabled by default in libpng-1.2.0 */
+/*
+#if !defined(PNG_NO_USER_MEM) && !defined(PNG_USER_MEM_SUPPORTED)
+#  define PNG_USER_MEM_SUPPORTED
+#endif
+*/
+
+/* These are currently experimental features, define them if you want */
+
+/* very little testing */
+/*
+#ifdef PNG_READ_SUPPORTED
+#  ifndef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED
+#    define PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED
+#  endif
+#endif
+*/
+
+/* This is only for PowerPC big-endian and 680x0 systems */
+/* some testing */
+/*
+#ifdef PNG_READ_SUPPORTED
+#  ifndef PNG_PNG_READ_BIG_ENDIAN_SUPPORTED
+#    define PNG_READ_BIG_ENDIAN_SUPPORTED
+#  endif
+#endif
+*/
+
+/* Buggy compilers (e.g., gcc 2.7.2.2) need this */
+/*
+#define PNG_NO_POINTER_INDEXING
+*/
+
+/* These functions are turned off by default, as they will be phased out. */
+/*
+#define  PNG_USELESS_TESTS_SUPPORTED
+#define  PNG_CORRECT_PALETTE_SUPPORTED
+*/
+
+/* Any chunks you are not interested in, you can undef here.  The
+ * ones that allocate memory may be expecially important (hIST,
+ * tEXt, zTXt, tRNS, pCAL).  Others will just save time and make png_info
+ * a bit smaller.
+ */
+
+#if defined(PNG_READ_SUPPORTED) && \
+    !defined(PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \
+    !defined(PNG_NO_READ_ANCILLARY_CHUNKS)
+#  define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED
+#endif
+
+#if defined(PNG_WRITE_SUPPORTED) && \
+    !defined(PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \
+    !defined(PNG_NO_WRITE_ANCILLARY_CHUNKS)
+#  define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED
+#endif
+
+#ifdef PNG_READ_ANCILLARY_CHUNKS_SUPPORTED
+
+#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
+#endif
+#ifndef PNG_NO_READ_cHRM
+#  define PNG_READ_cHRM_SUPPORTED
+#  define PNG_cHRM_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_gAMA
+#  define PNG_READ_gAMA_SUPPORTED
+#  define PNG_gAMA_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_hIST
+#  define PNG_READ_hIST_SUPPORTED
+#  define PNG_hIST_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_iCCP
+#  define PNG_READ_iCCP_SUPPORTED
+#  define PNG_iCCP_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_iTXt
+#  define PNG_READ_iTXt_SUPPORTED
+#  define PNG_iTXt_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_oFFs
+#  define PNG_READ_oFFs_SUPPORTED
+#  define PNG_oFFs_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_pCAL
+#  define PNG_READ_pCAL_SUPPORTED
+#  define PNG_pCAL_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_sCAL
+#  define PNG_READ_sCAL_SUPPORTED
+#  define PNG_sCAL_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_pHYs
+#  define PNG_READ_pHYs_SUPPORTED
+#  define PNG_pHYs_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_sBIT
+#  define PNG_READ_sBIT_SUPPORTED
+#  define PNG_sBIT_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_sPLT
+#  define PNG_READ_sPLT_SUPPORTED
+#  define PNG_sPLT_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_sRGB
+#  define PNG_READ_sRGB_SUPPORTED
+#  define PNG_sRGB_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_tEXt
+#  define PNG_READ_tEXt_SUPPORTED
+#  define PNG_tEXt_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_tIME
+#  define PNG_READ_tIME_SUPPORTED
+#  define PNG_tIME_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_tRNS
+#  define PNG_READ_tRNS_SUPPORTED
+#  define PNG_tRNS_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_zTXt
+#  define PNG_READ_zTXt_SUPPORTED
+#  define PNG_zTXt_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_UNKNOWN_CHUNKS
+#  define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
+#  ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED
+#    define PNG_UNKNOWN_CHUNKS_SUPPORTED
+#  endif
+#  ifndef PNG_NO_HANDLE_AS_UNKNOWN
+#    define PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+#  endif
+#endif
+#if !defined(PNG_NO_READ_USER_CHUNKS) && \
+     defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
+#  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_OPT_PLTE
+#  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
+#endif
+
+#endif /* PNG_READ_ANCILLARY_CHUNKS_SUPPORTED */
+
+#ifdef PNG_WRITE_ANCILLARY_CHUNKS_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
+#endif
+#ifndef PNG_NO_WRITE_gAMA
+#  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
+#endif
+#ifndef PNG_NO_WRITE_iCCP
+#  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
+#endif
+#ifndef PNG_NO_WRITE_oFFs
+#  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
+#endif
+#ifndef PNG_NO_WRITE_sCAL
+#  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
+#endif
+#ifndef PNG_NO_WRITE_sBIT
+#  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
+#endif
+#ifndef PNG_NO_WRITE_sRGB
+#  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
+#endif
+#ifndef PNG_NO_WRITE_tIME
+#  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
+#endif
+#ifndef PNG_NO_WRITE_zTXt
+#  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
+#  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
+#endif
+
+#endif /* PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED */
+
+/* Turn this off to disable png_read_png() and
+ * png_write_png() and leave the row_pointers 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_tIME_SUPPORTED)
+#  if !defined(_WIN32_WCE)
+     /* "time.h" functions are not supported on WindowsCE */
+#    include <time.h>
+#  endif
+#endif
+
+/* Some typedefs to get us started.  These should be safe on most of the
+ * common platforms.  The typedefs should be at least as large as the
+ * numbers suggest (a png_uint_32 must be at least 32 bits long), but they
+ * don't have to be exactly that size.  Some compilers dislike passing
+ * unsigned shorts as function parameters, so you may be better off using
+ * unsigned int for png_uint_16.  Likewise, for 64-bit systems, you may
+ * want to have unsigned int for png_uint_32 instead of unsigned long.
+ */
+
+typedef unsigned long png_uint_32;
+typedef long png_int_32;
+typedef unsigned short png_uint_16;
+typedef short png_int_16;
+typedef unsigned char png_byte;
+
+/* This is usually size_t.  It is typedef'ed just in case you need it to
+   change (I'm not sure if you will or not, so I thought I'd be safe) */
+typedef size_t png_size_t;
+
+/* The following is needed for medium model support.  It cannot be in the
+ * PNG_INTERNAL section.  Needs modification for other compilers besides
+ * MSC.  Model independent support declares all arrays and pointers to be
+ * large using the far keyword.  The zlib version used must also support
+ * model independent data.  As of version zlib 1.0.4, the necessary changes
+ * have been made in zlib.  The USE_FAR_KEYWORD define triggers other
+ * changes that are needed. (Tim Wegner)
+ */
+
+/* Separate compiler dependencies (problem here is that zlib.h always
+   defines FAR. (SJT) */
+#ifdef __BORLANDC__
+#  if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__)
+#    define LDATA 1
+#  else
+#    define LDATA 0
+#  endif
+   /* GRR:  why is Cygwin in here?  Cygwin is not Borland C... */
+#  if !defined(__WIN32__) && !defined(__FLAT__) && !defined(__CYGWIN__)
+#    define PNG_MAX_MALLOC_64K
+#    if (LDATA != 1)
+#      ifndef FAR
+#        define FAR __far
+#      endif
+#      define USE_FAR_KEYWORD
+#    endif   /* LDATA != 1 */
+     /* Possibly useful for moving data out of default segment.
+      * Uncomment it if you want. Could also define FARDATA as
+      * const if your compiler supports it. (SJT)
+#    define FARDATA FAR
+      */
+#  endif  /* __WIN32__, __FLAT__, __CYGWIN__ */
+#endif   /* __BORLANDC__ */
+
+
+/* Suggest testing for specific compiler first before testing for
+ * FAR.  The Watcom compiler defines both __MEDIUM__ and M_I86MM,
+ * making reliance oncertain keywords suspect. (SJT)
+ */
+
+/* MSC Medium model */
+#if defined(FAR)
+#  if defined(M_I86MM)
+#    define USE_FAR_KEYWORD
+#    define FARDATA FAR
+#    include <dos.h>
+#  endif
+#endif
+
+/* SJT: default case */
+#ifndef FAR
+#  define FAR
+#endif
+
+/* At this point FAR is always defined */
+#ifndef FARDATA
+#  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;
+typedef png_uint_32     FAR * png_uint_32p;
+typedef png_int_32      FAR * png_int_32p;
+typedef png_uint_16     FAR * png_uint_16p;
+typedef png_int_16      FAR * png_int_16p;
+typedef PNG_CONST char  FAR * png_const_charp;
+typedef char            FAR * png_charp;
+typedef png_fixed_point FAR * png_fixed_point_p;
+
+#ifndef PNG_NO_STDIO
+#if defined(_WIN32_WCE)
+typedef HANDLE                png_FILE_p;
+#else
+typedef FILE                * png_FILE_p;
+#endif
+#endif
+
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+typedef double          FAR * png_doublep;
+#endif
+
+/* Pointers to pointers; i.e. arrays */
+typedef png_byte        FAR * FAR * png_bytepp;
+typedef png_uint_32     FAR * FAR * png_uint_32pp;
+typedef png_int_32      FAR * FAR * png_int_32pp;
+typedef png_uint_16     FAR * FAR * png_uint_16pp;
+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
+
+/* Pointers to pointers to pointers; i.e., pointer to array */
+typedef char            FAR * FAR * FAR * png_charppp;
+
+/* libpng typedefs for types in zlib. If zlib changes
+ * or another compression library is used, then change these.
+ * Eliminates need to change all the source files.
+ */
+typedef charf *         png_zcharp;
+typedef charf * FAR *   png_zcharpp;
+typedef z_stream FAR *  png_zstreamp;
+
+/*
+ * Define PNG_BUILD_DLL if the module being built is a Windows
+ * LIBPNG DLL.
+ *
+ * Define PNG_USE_DLL if you want to *link* to the Windows LIBPNG DLL.
+ * It is equivalent to Microsoft predefined macro _DLL that is
+ * automatically defined when you compile using the share
+ * version of the CRT (C Run-Time library)
+ *
+ * The cygwin mods make this behavior a little different:
+ * Define PNG_BUILD_DLL if you are building a dll for use with cygwin
+ * Define PNG_STATIC if you are building a static library for use with cygwin,
+ *   -or- if you are building an application that you want to link to the
+ *   static library.
+ * PNG_USE_DLL is defined by default (no user action needed) unless one of
+ *   the other flags is defined.
+ */
+
+#if !defined(PNG_DLL) && (defined(PNG_BUILD_DLL) || defined(PNG_USE_DLL))
+#  define PNG_DLL
+#endif
+/* If CYGWIN, then disallow GLOBAL ARRAYS unless building a static lib.
+ * When building a static lib, default to no GLOBAL ARRAYS, but allow
+ * command-line override
+ */
+#if defined(__CYGWIN__)
+#  if !defined(PNG_STATIC)
+#    if defined(PNG_USE_GLOBAL_ARRAYS)
+#      undef PNG_USE_GLOBAL_ARRAYS
+#    endif
+#    if !defined(PNG_USE_LOCAL_ARRAYS)
+#      define PNG_USE_LOCAL_ARRAYS
+#    endif
+#  else
+#    if defined(PNG_USE_LOCAL_ARRAYS) || defined(PNG_NO_GLOBAL_ARRAYS)
+#      if defined(PNG_USE_GLOBAL_ARRAYS)
+#        undef PNG_USE_GLOBAL_ARRAYS
+#      endif
+#    endif
+#  endif
+#  if !defined(PNG_USE_LOCAL_ARRAYS) && !defined(PNG_USE_GLOBAL_ARRAYS)
+#    define PNG_USE_LOCAL_ARRAYS
+#  endif
+#endif
+
+/* Do not use global arrays (helps with building DLL's)
+ * They are no longer used in libpng itself, since version 1.0.5c,
+ * but might be required for some pre-1.0.5c applications.
+ */
+#if !defined(PNG_USE_LOCAL_ARRAYS) && !defined(PNG_USE_GLOBAL_ARRAYS)
+#  if defined(PNG_NO_GLOBAL_ARRAYS) || (defined(__GNUC__) && defined(PNG_DLL))
+#    define PNG_USE_LOCAL_ARRAYS
+#  else
+#    define PNG_USE_GLOBAL_ARRAYS
+#  endif
+#endif
+
+
+#ifndef PNGAPI
+
+#if defined(__MINGW32__) || defined(__CYGWIN__) && !defined(PNG_MODULEDEF)
+#  ifndef PNG_NO_MODULEDEF
+#    define PNG_NO_MODULEDEF
+#  endif
+#endif
+
+#if !defined(PNG_IMPEXP) && defined(PNG_BUILD_DLL) && !defined(PNG_NO_MODULEDEF)
+#  define PNG_IMPEXP
+#endif
+
+#if defined(PNG_DLL) || defined(_DLL) || defined(__DLL__ ) || \
+    (( defined(_Windows) || defined(_WINDOWS) || \
+       defined(WIN32) || defined(_WIN32) || defined(__WIN32__) \
+          ) && !defined(__CYGWIN__))
+
+#  if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800))
+#    define PNGAPI __cdecl
+#  else
+#    define PNGAPI _cdecl
+#  endif
+
+#  if !defined(PNG_IMPEXP) && (!defined(PNG_DLL) || \
+       0 /* WINCOMPILER_WITH_NO_SUPPORT_FOR_DECLIMPEXP */)
+#     define PNG_IMPEXP
+#  endif
+
+#  if !defined(PNG_IMPEXP)
+
+#     define PNG_EXPORT_TYPE1(type,symbol)  PNG_IMPEXP type PNGAPI symbol
+#     define PNG_EXPORT_TYPE2(type,symbol)  type PNG_IMPEXP PNGAPI symbol
+
+      /* Borland/Microsoft */
+#     if defined(_MSC_VER) || defined(__BORLANDC__)
+#        if (_MSC_VER >= 800) || (__BORLANDC__ >= 0x500)
+#           define PNG_EXPORT PNG_EXPORT_TYPE1
+#        else
+#           define PNG_EXPORT PNG_EXPORT_TYPE2
+#           if defined(PNG_BUILD_DLL)
+#              define PNG_IMPEXP __export
+#           else
+#              define PNG_IMPEXP /*__import*/ /* doesn't exist AFAIK in
+                                                 VC++*/
+#           endif                             /* Exists in Borland C++ for
+                                                 C++ classes (== huge) */
+#        endif
+#     endif
+
+#     if !defined(PNG_IMPEXP)
+#        if defined(PNG_BUILD_DLL)
+#           define PNG_IMPEXP __declspec(dllexport)
+#        else
+#           define PNG_IMPEXP __declspec(dllimport)
+#        endif
+#     endif
+#  endif  /* PNG_IMPEXP */
+#else /* !(DLL || non-cygwin WINDOWS) */
+#  if defined(__CYGWIN__) && !defined(PNG_DLL)
+#    if !defined(PNG_IMPEXP)
+#      define PNG_IMPEXP
+#    endif
+#    define PNGAPI __cdecl
+#  else
+#    if (defined(__IBMC__) || defined(IBMCPP__)) && defined(__OS2__)
+#      define PNGAPI _System
+#      define PNG_IMPEXP
+#    else
+#      if 0 /* ... other platforms, with other meanings */
+#      else
+#        define PNGAPI
+#        define PNG_IMPEXP
+#      endif
+#    endif
+#  endif
+#endif
+#endif
+
+#ifndef PNGAPI
+#  define PNGAPI
+#endif
+#ifndef PNG_IMPEXP
+#  define PNG_IMPEXP
+#endif
+
+#ifndef PNG_EXPORT
+#  define PNG_EXPORT(type,symbol) PNG_IMPEXP type PNGAPI symbol
+#endif
+
+#ifdef PNG_USE_GLOBAL_ARRAYS
+#  ifndef PNG_EXPORT_VAR
+#    define PNG_EXPORT_VAR(type) extern PNG_IMPEXP type
+#  endif
+#endif
+
+/* User may want to use these so they are not in PNG_INTERNAL. Any library
+ * functions that are passed far data must be model independent.
+ */
+
+#ifndef PNG_ABORT
+#  define PNG_ABORT() abort()
+#endif
+
+#ifdef PNG_SETJMP_SUPPORTED
+#  define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
+#else
+#  define png_jmpbuf(png_ptr) \
+   (LIBPNG_WAS_COMPILED_WITH__PNG_SETJMP_NOT_SUPPORTED)
+#endif
+
+#if defined(USE_FAR_KEYWORD)  /* memory model independent fns */
+/* use this to make far-to-near assignments */
+#  define CHECK   1
+#  define NOCHECK 0
+#  define CVT_PTR(ptr) (png_far_to_near(png_ptr,ptr,CHECK))
+#  define CVT_PTR_NOCHECK(ptr) (png_far_to_near(png_ptr,ptr,NOCHECK))
+#  define png_strcpy _fstrcpy
+#  define png_strlen _fstrlen
+#  define png_memcmp _fmemcmp      /* SJT: added */
+#  define png_memcpy _fmemcpy
+#  define png_memset _fmemset
+#else /* use the usual functions */
+#  define CVT_PTR(ptr)         (ptr)
+#  define CVT_PTR_NOCHECK(ptr) (ptr)
+#  define png_strcpy strcpy
+#  define png_strlen strlen
+#  define png_memcmp memcmp     /* SJT: added */
+#  define png_memcpy memcpy
+#  define png_memset memset
+#endif
+/* End of memory model independent support */
+
+/* Just a little check that someone hasn't tried to define something
+ * contradictory.
+ */
+#if (PNG_ZBUF_SIZE > 65536) && defined(PNG_MAX_MALLOC_64K)
+#  undef PNG_ZBUF_SIZE
+#  define PNG_ZBUF_SIZE 65536
+#endif
+
+#ifdef PNG_READ_SUPPORTED
+/* Prior to libpng-1.0.9, this block was in pngasmrd.h */
+#if defined(PNG_INTERNAL)
+
+/* These are the default thresholds before the MMX code kicks in; if either
+ * rowbytes or bitdepth is below the threshold, plain C code is used.  These
+ * can be overridden at runtime via the png_set_mmx_thresholds() call in
+ * libpng 1.2.0 and later.  The values below were chosen by Intel.
+ */
+
+#ifndef PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT
+#  define PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT  128  /*  >=  */
+#endif
+#ifndef PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT
+#  define PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT  9    /*  >=  */   
+#endif
+
+/* Set this in the makefile for VC++ on Pentium, not here. */
+/* Platform must be Pentium.  Makefile must assemble and load pngvcrd.c .
+ * MMX will be detected at run time and used if present.
+ */
+#ifdef PNG_USE_PNGVCRD
+#  define PNG_HAVE_ASSEMBLER_COMBINE_ROW
+#  define PNG_HAVE_ASSEMBLER_READ_INTERLACE
+#  define PNG_HAVE_ASSEMBLER_READ_FILTER_ROW
+#endif
+
+/* Set this in the makefile for gcc/as on Pentium, not here. */
+/* Platform must be Pentium.  Makefile must assemble and load pnggccrd.c .
+ * MMX will be detected at run time and used if present.
+ */
+#ifdef PNG_USE_PNGGCCRD
+#  define PNG_HAVE_ASSEMBLER_COMBINE_ROW
+#  define PNG_HAVE_ASSEMBLER_READ_INTERLACE
+#  define PNG_HAVE_ASSEMBLER_READ_FILTER_ROW
+#endif
+/* - see pnggccrd.c for info about what is currently enabled */
+
+#endif /* PNG_INTERNAL */
+#endif /* PNG_READ_SUPPORTED */
+
+#endif /* PNGCONF_H */
+
diff --git a/Utilities/ITK/Utilities/png/pngerror.c b/Utilities/ITK/Utilities/png/pngerror.c
new file mode 100644
index 0000000000..c2285ff6d9
--- /dev/null
+++ b/Utilities/ITK/Utilities/png/pngerror.c
@@ -0,0 +1,290 @@
+
+/* pngerror.c - stub functions for i/o and memory allocation
+ *
+ * libpng 1.0.12 - June 8, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This file provides a location for all error handling.  Users who
+ * need special error handling are expected to write replacement functions
+ * and use png_set_error_fn() to use those functions.  See the instructions
+ * at each function.
+ */
+
+#define PNG_INTERNAL
+#include "png.h"
+
+static void /* PRIVATE */
+png_default_error PNGARG((png_structp png_ptr,
+                                      png_const_charp message));
+static void /* PRIVATE */
+png_default_warning PNGARG((png_structp png_ptr,
+                                        png_const_charp message));
+
+/* This function is called whenever there is a fatal error.  This function
+ * should not be changed.  If there is a need to handle errors differently,
+ * you should supply a replacement error function and use png_set_error_fn()
+ * to replace the error function at run-time.
+ */
+void PNGAPI
+png_error(png_structp png_ptr, png_const_charp message)
+{
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+   char msg[16];
+   if (png_ptr->flags&(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))
+   {
+     int offset = 0;
+     if (*message == '#')
+     {
+         for (offset=1; offset<15; offset++)
+            if (*(message+offset) == ' ')
+                break;
+         if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT)
+         {
+            int i;
+            for (i=0; i<offset-1; i++)
+               msg[i]=message[i+1];
+            msg[i]='\0';
+            message=msg;
+         }
+         else
+            message+=offset;
+     }
+     else
+     {
+         if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT)
+         {
+            msg[0]='0';        
+            msg[1]='\0';
+            message=msg;
+         }
+     }
+   }
+#endif
+   if (png_ptr->error_fn != NULL)
+      (*(png_ptr->error_fn))(png_ptr, message);
+
+   /* if the following returns or doesn't exist, use the default function,
+      which will not return */
+   png_default_error(png_ptr, message);
+}
+
+/* This function is called whenever there is a non-fatal error.  This function
+ * should not be changed.  If there is a need to handle warnings differently,
+ * you should supply a replacement warning function and use
+ * png_set_error_fn() to replace the warning function at run-time.
+ */
+void PNGAPI
+png_warning(png_structp png_ptr, png_const_charp message)
+{
+     int offset = 0;
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+   if (png_ptr->flags&(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))
+#endif
+   {
+     if (*message == '#')
+     {
+         for (offset=1; offset<15; offset++)
+            if (*(message+offset) == ' ')
+                break;
+     }
+   }
+   if (png_ptr->warning_fn != NULL)
+      (*(png_ptr->warning_fn))(png_ptr, (png_const_charp)(message+offset));
+   else
+      png_default_warning(png_ptr, (png_const_charp)(message+offset));
+}
+
+/* These utilities are used internally to build an error message that relates
+ * to the current chunk.  The chunk name comes from png_ptr->chunk_name,
+ * this is used to prefix the message.  The message is limited in length
+ * to 63 bytes, the name characters are output as hex digits wrapped in []
+ * if the character is invalid.
+ */
+#define isnonalpha(c) ((c) < 41 || (c) > 122 || ((c) > 90 && (c) < 97))
+static PNG_CONST char png_digit[16] = {
+   '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
+   'F' };
+
+static void /* PRIVATE */
+png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp
+   message)
+{
+   int iout = 0, iin = 0;
+
+   while (iin < 4)
+   {
+      int c = png_ptr->chunk_name[iin++];
+      if (isnonalpha(c))
+      {
+         buffer[iout++] = '[';
+         buffer[iout++] = png_digit[(c & 0xf0) >> 4];
+         buffer[iout++] = png_digit[c & 0x0f];
+         buffer[iout++] = ']';
+      }
+      else
+      {
+         buffer[iout++] = (png_byte)c;
+      }
+   }
+
+   if (message == NULL)
+      buffer[iout] = 0;
+   else
+   {
+      buffer[iout++] = ':';
+      buffer[iout++] = ' ';
+      png_memcpy(buffer+iout, message, 64);
+      buffer[iout+63] = 0;
+   }
+}
+
+void PNGAPI
+png_chunk_error(png_structp png_ptr, png_const_charp message)
+{
+   char msg[18+64];
+   png_format_buffer(png_ptr, msg, message);
+   png_error(png_ptr, msg);
+}
+
+void PNGAPI
+png_chunk_warning(png_structp png_ptr, png_const_charp message)
+{
+   char msg[18+64];
+   png_format_buffer(png_ptr, msg, message);
+   png_warning(png_ptr, msg);
+}
+
+/* This is the default error handling function.  Note that replacements for
+ * this function MUST NOT RETURN, or the program will likely crash.  This
+ * function is used by default, or if the program supplies NULL for the
+ * error function pointer in png_set_error_fn().
+ */
+static void /* PRIVATE */
+png_default_error(png_structp png_ptr, png_const_charp message)
+{
+#ifndef PNG_NO_CONSOLE_IO
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+   if (*message == '#')
+   {
+     int offset;
+     char error_number[16];
+     for (offset=0; offset<15; offset++)
+     {
+         error_number[offset] = *(message+offset+1);
+         if (*(message+offset) == ' ')
+             break;
+     }
+     if((offset > 1) && (offset < 15))
+     {
+       error_number[offset-1]='\0';
+       fprintf(stderr, "libpng error no. %s: %s\n", error_number, message+offset);
+     }
+     else
+       fprintf(stderr, "libpng error: %s, offset=%d\n", message,offset);
+   }
+   else
+#endif
+   fprintf(stderr, "libpng error: %s\n", message);
+#else
+   if (message)
+     /* make compiler happy */ ;
+#endif
+
+#ifdef PNG_SETJMP_SUPPORTED
+#  ifdef USE_FAR_KEYWORD
+   {
+      jmp_buf jmpbuf;
+      png_memcpy(jmpbuf,png_ptr->jmpbuf,sizeof(jmp_buf));
+      longjmp(jmpbuf, 1);
+   }
+#  else
+   longjmp(png_ptr->jmpbuf, 1);
+# endif
+#else
+   if (png_ptr)
+     /* make compiler happy */ ;
+   PNG_ABORT();
+#endif
+}
+
+/* This function is called when there is a warning, but the library thinks
+ * it can continue anyway.  Replacement functions don't have to do anything
+ * here if you don't want them to.  In the default configuration, png_ptr is
+ * not used, but it is passed in case it may be useful.
+ */
+static void /* PRIVATE */
+png_default_warning(png_structp png_ptr, png_const_charp message)
+{
+#ifndef PNG_NO_CONSOLE_IO
+#  ifdef PNG_ERROR_NUMBERS_SUPPORTED
+   if (*message == '#')
+   {
+     int offset;
+     char warning_number[16];
+     for (offset=0; offset<15; offset++)
+     {
+        warning_number[offset]=*(message+offset+1);
+        if (*(message+offset) == ' ')
+            break;
+     }
+     if((offset > 1) && (offset < 15))
+     {
+       warning_number[offset-1]='\0';
+       fprintf(stderr, "libpng warning no. %s: %s\n", warning_number,
+          message+offset);
+     }
+     else
+       fprintf(stderr, "libpng warning: %s\n", message);
+   }
+   else
+#  endif
+     fprintf(stderr, "libpng warning: %s\n", message);
+#else
+   if (message)
+     /* appease compiler */ ;
+#endif
+   if (png_ptr)
+      return;
+}
+
+/* This function is called when the application wants to use another method
+ * of handling errors and warnings.  Note that the error function MUST NOT
+ * return to the calling routine or serious problems will occur.  The return
+ * method used in the default routine calls longjmp(png_ptr->jmpbuf, 1)
+ */
+void PNGAPI
+png_set_error_fn(png_structp png_ptr, png_voidp error_ptr,
+   png_error_ptr error_fn, png_error_ptr warning_fn)
+{
+   png_ptr->error_ptr = error_ptr;
+   png_ptr->error_fn = error_fn;
+   png_ptr->warning_fn = warning_fn;
+}
+
+
+/* This function returns a pointer to the error_ptr associated with the user
+ * functions.  The application should free any memory associated with this
+ * pointer before png_write_destroy and png_read_destroy are called.
+ */
+png_voidp PNGAPI
+png_get_error_ptr(png_structp png_ptr)
+{
+   return ((png_voidp)png_ptr->error_ptr);
+}
+
+
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+void
+png_set_strip_error_numbers(png_structp png_ptr, png_uint_32 strip_mode)
+{
+   if(png_ptr != NULL)
+   {
+     png_ptr->flags &=
+       ((~(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode);
+   }
+}
+#endif
+
diff --git a/Utilities/ITK/Utilities/png/pnggccrd.c b/Utilities/ITK/Utilities/png/pnggccrd.c
new file mode 100644
index 0000000000..62ea6905b7
--- /dev/null
+++ b/Utilities/ITK/Utilities/png/pnggccrd.c
@@ -0,0 +1,5208 @@
+/* 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 version 1.0.12 - June 8, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * Copyright (c) 1998, Intel Corporation
+ *
+ * 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-2001.
+ *
+ * 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.simtel.net/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.slackware.com/pub/linux/slackware/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...
+ */
+
+/*
+ * TEMPORARY PORTING NOTES AND CHANGELOG (mostly by Greg Roelofs)
+ * =====================================
+ *
+ * 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) (near line 1606)
+ *     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 (that is, 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_read_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_read_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.
+ *
+ * 20000213:
+ *  - when compiling with gcc, be sure to use  -fomit-frame-pointer
+ *
+ * 20000319:
+ *  - fixed a register-name typo in png_do_read_interlace(), default (MMX) case,
+ *     pass == 4 or 5, that caused visible corruption of interlaced images
+ *
+ * 20000623:
+ *  - Various problems were reported with gcc 2.95.2 in the Cygwin environment,
+ *     many of the form "forbidden register 0 (ax) was spilled for class AREG."
+ *     This is explained at http://gcc.gnu.org/fom_serv/cache/23.html, and
+ *     Chuck Wilson supplied a patch involving dummy output registers.  See
+ *     http://sourceforge.net/bugs/?func=detailbug&bug_id=108741&group_id=5624
+ *     for the original (anonymous) SourceForge bug report.
+ *
+ * 20000706:
+ *  - Chuck Wilson passed along these remaining gcc 2.95.2 errors:
+ *       pnggccrd.c: In function `png_combine_row':
+ *       pnggccrd.c:525: more than 10 operands in `asm'
+ *       pnggccrd.c:669: more than 10 operands in `asm'
+ *       pnggccrd.c:828: more than 10 operands in `asm'
+ *       pnggccrd.c:994: more than 10 operands in `asm'
+ *       pnggccrd.c:1177: more than 10 operands in `asm'
+ *     They are all the same problem and can be worked around by using the
+ *     global _unmask variable unconditionally, not just in the -fPIC case.
+ *     Reportedly earlier versions of gcc also have the problem with more than
+ *     10 operands; they just don't report it.  Much strangeness ensues, etc.
+ *
+ * 20000729:
+ *  - enabled png_read_filter_row_mmx_up() (shortest remaining unconverted
+ *     MMX routine); began converting png_read_filter_row_mmx_sub()
+ *  - to finish remaining sections:
+ *     - clean up indentation and comments
+ *     - preload local variables
+ *     - add output and input regs (order of former determines numerical
+ *        mapping of latter)
+ *     - avoid all usage of ebx (including bx, bh, bl) register [20000823]
+ *     - remove "$" from addressing of Shift and Mask variables [20000823]
+ *
+ * 20000731:
+ *  - global union vars causing segfaults in png_read_filter_row_mmx_sub()?
+ *
+ * 20000822:
+ *  - ARGH, stupid png_read_filter_row_mmx_sub() segfault only happens with
+ *     shared-library (-fPIC) version!  Code works just fine as part of static
+ *     library.  Damn damn damn damn damn, should have tested that sooner.
+ *     ebx is getting clobbered again (explicitly this time); need to save it
+ *     on stack or rewrite asm code to avoid using it altogether.  Blargh!
+ *
+ * 20000823:
+ *  - first section was trickiest; all remaining sections have ebx -> edx now.
+ *     (-fPIC works again.)  Also added missing underscores to various Shift*
+ *     and *Mask* globals and got rid of leading "$" signs.
+ *
+ * 20000826:
+ *  - added visual separators to help navigate microscopic printed copies
+ *     (http://pobox.com/~newt/code/gpr-latest.zip, mode 10); started working
+ *     on png_read_filter_row_mmx_avg()
+ *
+ * 20000828:
+ *  - finished png_read_filter_row_mmx_avg():  only Paeth left! (930 lines...)
+ *     What the hell, did png_read_filter_row_mmx_paeth(), too.  Comments not
+ *     cleaned up/shortened in either routine, but functionality is complete
+ *     and seems to be working fine.
+ *
+ * 20000829:
+ *  - ahhh, figured out last(?) bit of gcc/gas asm-fu:  if register is listed
+ *     as an input reg (with dummy output variables, etc.), then it *cannot*
+ *     also appear in the clobber list or gcc 2.95.2 will barf.  The solution
+ *     is simple enough...
+ *
+ * 20000914:
+ *  - bug in png_read_filter_row_mmx_avg():  16-bit grayscale not handled
+ *     correctly (but 48-bit RGB just fine)
+ *
+ * 20000916:
+ *  - fixed bug in png_read_filter_row_mmx_avg(), bpp == 2 case; three errors:
+ *     - "_ShiftBpp.use = 24;"      should have been   "_ShiftBpp.use = 16;"
+ *     - "_ShiftRem.use = 40;"      should have been   "_ShiftRem.use = 48;"
+ *     - "psllq _ShiftRem, %%mm2"   should have been   "psrlq _ShiftRem, %%mm2"
+ *
+ * 20010103:
+ *  - renamed mmxsupport() to png_mmx_support(), with auto-set of mmx_supported,
+ *     and made it public
+ *
+ * 20010104:
+ *  - removed dependency on png_read_filter_row_c() (C code already duplicated
+ *     within MMX version of png_read_filter_row()) so no longer necessary to
+ *     compile it into pngrutil.o
+ *
+ * 20010310:
+ *  - fixed buffer-overrun bug in png_combine_row() C code (non-MMX)
+ *
+ * STILL TO DO:
+ *     - test png_do_read_interlace() 64-bit case (pixel_bytes == 8)
+ *     - 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) (near line 1606)
+ *     - rewrite all MMX interlacing code so it's aligned with beginning
+ *        of the row buffer, not the end (see 19991007 for details)
+ *     x pick one version of mmxsupport() and get rid of the other
+ *     - add error messages to any remaining bogus default cases
+ *     - enable pixel_depth == 8 cases in png_read_filter_row()? (test speed)
+ *     - add support for runtime enable/disable/query of various MMX routines
+ */
+
+/*
+#ifndef PNG_DEBUG
+#  define PNG_DEBUG 0
+#endif
+*/
+
+#define PNG_INTERNAL
+#include "png.h"
+
+#if defined(PNG_USE_PNGGCCRD)
+
+int PNGAPI png_mmx_support(void);
+
+#ifdef PNG_USE_LOCAL_ARRAYS
+static const int FARDATA png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+static const int FARDATA png_pass_inc[7]   = {8, 8, 4, 4, 2, 2, 1};
+static const int FARDATA png_pass_width[7] = {8, 4, 4, 2, 2, 1, 1};
+#endif
+
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED)
+/* djgpp, Win32, and Cygwin add their own underscores to global variables,
+ * so define them without: */
+#if defined(__DJGPP__) || defined(WIN32) || defined(__CYGWIN__)
+#  define _mmx_supported  mmx_supported
+#  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
+#  define _LBCarryMask    LBCarryMask
+#  define _HBClearMask    HBClearMask
+#  define _ActiveMask     ActiveMask
+#  define _ActiveMask2    ActiveMask2
+#  define _ActiveMaskEnd  ActiveMaskEnd
+#  define _ShiftBpp       ShiftBpp
+#  define _ShiftRem       ShiftRem
+#  define _patemp         patemp
+#  define _pbtemp         pbtemp
+#  define _pctemp         pctemp
+#endif
+
+
+/* These constants are used in the inlined MMX assembly code.
+   Ignore gcc's "At top level: defined but not used" warnings. */
+
+/* GRR 20000706:  originally _unmask was needed only when compiling with -fPIC,
+ *  since that case uses the %ebx register for indexing the Global Offset Table
+ *  and there were no other registers available.  But gcc 2.95 and later emit
+ *  "more than 10 operands in `asm'" errors when %ebx is used to preload unmask
+ *  in the non-PIC case, so we'll just use the global unconditionally now.
+ */
+static int _unmask;
+
+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;
+static int          _patemp;	// temp variables for Paeth routine
+static int          _pbtemp;
+static int          _pctemp;
+
+static void /* PRIVATE */
+png_squelch_warnings(void)
+{
+   _dif = _dif;
+   _patemp = _patemp;
+   _pbtemp = _pbtemp;
+   _pctemp = _pctemp;
+   _const4  = _const4;
+   _const6  = _const6;
+   _MMXLength = _MMXLength;
+   _mask8_0  = _mask8_0;
+   _mask16_1 = _mask16_1;
+   _mask16_0 = _mask16_0;
+   _mask24_2 = _mask24_2;
+   _mask24_1 = _mask24_1;
+   _mask24_0 = _mask24_0;
+   _mask32_3 = _mask32_3;
+   _mask32_2 = _mask32_2;
+   _mask32_1 = _mask32_1;
+   _mask32_0 = _mask32_0;
+   _mask48_5 = _mask48_5;
+   _mask48_4 = _mask48_4;
+   _mask48_3 = _mask48_3;
+   _mask48_2 = _mask48_2;
+   _mask48_1 = _mask48_1;
+   _mask48_0 = _mask48_0;
+}
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */
+
+static int _mmx_supported = 2;
+
+/*===========================================================================*/
+/*                                                                           */
+/*                       P N G _ C O M B I N E _ R O W                       */
+/*                                                                           */
+/*===========================================================================*/
+
+#if defined(PNG_HAVE_ASSEMBLER_COMBINE_ROW)
+
+#define BPP2  2
+#define BPP3  3		/* bytes per pixel (a.k.a. pixel_bytes) */
+#define BPP4  4
+#define BPP6  6		/* (defined only to help avoid cut-and-paste errors) */
+#define BPP8  8
+
+/* 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 /* PRIVATE */
+png_combine_row(png_structp png_ptr, png_bytep row, int mask)
+{
+   png_debug(1, "in png_combine_row (pnggccrd.c)\n");
+
+   if (_mmx_supported == 2) {
+       png_mmx_support();
+   }
+
+   if (mask == 0xff)
+   {
+      png_debug(2,"mask == 0xff:  doing single png_memcpy()\n");
+      png_memcpy(row, png_ptr->row_buf + 1,
+       (png_size_t)((png_ptr->width * png_ptr->row_info.pixel_depth + 7) >> 3));
+   }
+   else   /* (png_combine_row() is never called with mask == 0) */
+   {
+      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 defined(PNG_ASSEMBLER_CODE_SUPPORTED)
+            if ( _mmx_supported  )
+            {
+               png_uint_32 len;
+               int diff;
+               int dummy_value_a;   // fix 'forbidden register spilled' error
+               int dummy_value_d;
+               int dummy_value_c;
+               int dummy_value_S;
+               int dummy_value_D;
+               _unmask = ~mask;            // global variable for -fPIC version
+               srcptr = png_ptr->row_buf + 1;
+               dstptr = row;
+               len  = png_ptr->width &~7;  // reduce to multiple of 8
+               diff = (int) (png_ptr->width & 7);  // amount lost
+
+               __asm__ __volatile__ (
+                  "movd      _unmask, %%mm7  \n\t" // load bit pattern
+                  "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
+
+                  : "=a" (dummy_value_a),           // output regs (dummy)
+                    "=d" (dummy_value_d),
+                    "=c" (dummy_value_c),
+                    "=S" (dummy_value_S),
+                    "=D" (dummy_value_D)
+
+                  : "3" (srcptr),      // esi       // input regs
+                    "4" (dstptr),      // edi
+                    "0" (diff),        // eax
+// was (unmask)     "b"    RESERVED    // ebx       // Global Offset Table idx
+                    "2" (len),         // ecx
+                    "1" (mask)         // edx
+
+#if 0  /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */
+                  : "%mm0", "%mm4", "%mm6", "%mm7"  // clobber list
+#endif
+               );
+            }
+            else /* mmx _not supported - Use modified C routine */
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */
+            {
+               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}; */
+               png_uint_32 len = png_ptr->width &~7;  /* reduce to mult. of 8 */
+               int diff = (int) (png_ptr->width & 7); /* amount lost */
+               register png_uint_32 final_val = len;  /* GRR bugfix */
+
+               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;
+               }
+               if (diff)  /* number of leftover pixels:  3 for pngtest */
+               {
+                  final_val+=diff /* *BPP1 */ ;
+                  for (; i < final_val; i += stride)
+                  {
+                     if (rep_bytes > (int)(final_val-i))
+                        rep_bytes = (int)(final_val-i);
+                     png_memcpy(dstptr, srcptr, rep_bytes);
+                     srcptr += stride;
+                     dstptr += stride;
+                  }
+               }
+
+            } /* end of else (_mmx_supported) */
+
+            break;
+         }       /* end 8 bpp */
+
+         case 16:       /* png_ptr->row_info.pixel_depth */
+         {
+            png_bytep srcptr;
+            png_bytep dstptr;
+
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED)
+            if ( _mmx_supported )
+            {
+               png_uint_32 len;
+               int diff;
+               int dummy_value_a;   // fix 'forbidden register spilled' error
+               int dummy_value_d;
+               int dummy_value_c;
+               int dummy_value_S;
+               int dummy_value_D;
+               _unmask = ~mask;            // global variable for -fPIC version
+               srcptr = png_ptr->row_buf + 1;
+               dstptr = row;
+               len  = png_ptr->width &~7;  // reduce to multiple of 8
+               diff = (int) (png_ptr->width & 7); // amount lost //
+
+               __asm__ __volatile__ (
+                  "movd      _unmask, %%mm7   \n\t" // load bit pattern
+                  "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
+
+                  : "=a" (dummy_value_a),           // output regs (dummy)
+                    "=c" (dummy_value_c),
+                    "=d" (dummy_value_d),
+                    "=S" (dummy_value_S),
+                    "=D" (dummy_value_D)
+
+                  : "0" (diff),        // eax       // input regs
+// was (unmask)     " "    RESERVED    // ebx       // Global Offset Table idx
+                    "1" (len),         // ecx
+                    "2" (mask),        // edx
+                    "3" (srcptr),      // esi
+                    "4" (dstptr)       // edi
+
+#if 0  /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */
+                  : "%mm0", "%mm1", "%mm4"          // clobber list
+                  , "%mm5", "%mm6", "%mm7"
+#endif
+               );
+            }
+            else /* mmx _not supported - Use modified C routine */
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */
+            {
+               register png_uint_32 i;
+               png_uint_32 initial_val = BPP2 * png_pass_start[png_ptr->pass];
+                 /* png.c:  png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; */
+               register int stride = BPP2 * png_pass_inc[png_ptr->pass];
+                 /* png.c:  png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; */
+               register int rep_bytes = BPP2 * png_pass_width[png_ptr->pass];
+                 /* png.c:  png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; */
+               png_uint_32 len = png_ptr->width &~7;  /* reduce to mult. of 8 */
+               int diff = (int) (png_ptr->width & 7); /* amount lost */
+               register png_uint_32 final_val = BPP2 * len;   /* GRR bugfix */
+
+               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;
+               }
+               if (diff)  /* number of leftover pixels:  3 for pngtest */
+               {
+                  final_val+=diff*BPP2;
+                  for (; i < final_val; i += stride)
+                  {
+                     if (rep_bytes > (int)(final_val-i))
+                        rep_bytes = (int)(final_val-i);
+                     png_memcpy(dstptr, srcptr, rep_bytes);
+                     srcptr += stride;
+                     dstptr += stride;
+                  }
+               }
+            } /* end of else (_mmx_supported) */
+
+            break;
+         }       /* end 16 bpp */
+
+         case 24:       /* png_ptr->row_info.pixel_depth */
+         {
+            png_bytep srcptr;
+            png_bytep dstptr;
+
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED)
+            if ( _mmx_supported )
+            {
+               png_uint_32 len;
+               int diff;
+               int dummy_value_a;   // fix 'forbidden register spilled' error
+               int dummy_value_d;
+               int dummy_value_c;
+               int dummy_value_S;
+               int dummy_value_D;
+               _unmask = ~mask;            // global variable for -fPIC version
+               srcptr = png_ptr->row_buf + 1;
+               dstptr = row;
+               len  = png_ptr->width &~7;  // reduce to multiple of 8
+               diff = (int) (png_ptr->width & 7); // amount lost //
+
+               __asm__ __volatile__ (
+                  "movd      _unmask, %%mm7   \n\t" // load bit pattern
+                  "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
+
+                  : "=a" (dummy_value_a),           // output regs (dummy)
+                    "=d" (dummy_value_d),
+                    "=c" (dummy_value_c),
+                    "=S" (dummy_value_S),
+                    "=D" (dummy_value_D)
+
+                  : "3" (srcptr),      // esi       // input regs
+                    "4" (dstptr),      // edi
+                    "0" (diff),        // eax
+// was (unmask)     "b"    RESERVED    // ebx       // Global Offset Table idx
+                    "2" (len),         // ecx
+                    "1" (mask)         // edx
+
+#if 0  /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */
+                  : "%mm0", "%mm1", "%mm2"          // clobber list
+                  , "%mm4", "%mm5", "%mm6", "%mm7"
+#endif
+               );
+            }
+            else /* mmx _not supported - Use modified C routine */
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */
+            {
+               register png_uint_32 i;
+               png_uint_32 initial_val = BPP3 * png_pass_start[png_ptr->pass];
+                 /* png.c:  png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; */
+               register int stride = BPP3 * png_pass_inc[png_ptr->pass];
+                 /* png.c:  png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; */
+               register int rep_bytes = BPP3 * png_pass_width[png_ptr->pass];
+                 /* png.c:  png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; */
+               png_uint_32 len = png_ptr->width &~7;  /* reduce to mult. of 8 */
+               int diff = (int) (png_ptr->width & 7); /* amount lost */
+               register png_uint_32 final_val = BPP3 * len;   /* GRR bugfix */
+
+               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;
+               }
+               if (diff)  /* number of leftover pixels:  3 for pngtest */
+               {
+                  final_val+=diff*BPP3;
+                  for (; i < final_val; i += stride)
+                  {
+                     if (rep_bytes > (int)(final_val-i))
+                        rep_bytes = (int)(final_val-i);
+                     png_memcpy(dstptr, srcptr, rep_bytes);
+                     srcptr += stride;
+                     dstptr += stride;
+                  }
+               }
+            } /* end of else (_mmx_supported) */
+
+            break;
+         }       /* end 24 bpp */
+
+         case 32:       /* png_ptr->row_info.pixel_depth */
+         {
+            png_bytep srcptr;
+            png_bytep dstptr;
+
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED)
+            if ( _mmx_supported )
+            {
+               png_uint_32 len;
+               int diff;
+               int dummy_value_a;   // fix 'forbidden register spilled' error
+               int dummy_value_d;
+               int dummy_value_c;
+               int dummy_value_S;
+               int dummy_value_D;
+               _unmask = ~mask;            // global variable for -fPIC version
+               srcptr = png_ptr->row_buf + 1;
+               dstptr = row;
+               len  = png_ptr->width &~7;  // reduce to multiple of 8
+               diff = (int) (png_ptr->width & 7); // amount lost //
+
+               __asm__ __volatile__ (
+                  "movd      _unmask, %%mm7   \n\t" // load bit pattern
+                  "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
+
+                  : "=a" (dummy_value_a),           // output regs (dummy)
+                    "=d" (dummy_value_d),
+                    "=c" (dummy_value_c),
+                    "=S" (dummy_value_S),
+                    "=D" (dummy_value_D)
+
+                  : "3" (srcptr),      // esi       // input regs
+                    "4" (dstptr),      // edi
+                    "0" (diff),        // eax
+// was (unmask)     "b"    RESERVED    // ebx       // Global Offset Table idx
+                    "2" (len),         // ecx
+                    "1" (mask)         // edx
+
+#if 0  /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */
+                  : "%mm0", "%mm1", "%mm2", "%mm3"  // clobber list
+                  , "%mm4", "%mm5", "%mm6", "%mm7"
+#endif
+               );
+            }
+            else /* mmx _not supported - Use modified C routine */
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */
+            {
+               register png_uint_32 i;
+               png_uint_32 initial_val = BPP4 * png_pass_start[png_ptr->pass];
+                 /* png.c:  png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; */
+               register int stride = BPP4 * png_pass_inc[png_ptr->pass];
+                 /* png.c:  png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; */
+               register int rep_bytes = BPP4 * png_pass_width[png_ptr->pass];
+                 /* png.c:  png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; */
+               png_uint_32 len = png_ptr->width &~7;  /* reduce to mult. of 8 */
+               int diff = (int) (png_ptr->width & 7); /* amount lost */
+               register png_uint_32 final_val = BPP4 * len;   /* GRR bugfix */
+
+               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;
+               }
+               if (diff)  /* number of leftover pixels:  3 for pngtest */
+               {
+                  final_val+=diff*BPP4;
+                  for (; i < final_val; i += stride)
+                  {
+                     if (rep_bytes > (int)(final_val-i))
+                        rep_bytes = (int)(final_val-i);
+                     png_memcpy(dstptr, srcptr, rep_bytes);
+                     srcptr += stride;
+                     dstptr += stride;
+                  }
+               }
+            } /* end of else (_mmx_supported) */
+
+            break;
+         }       /* end 32 bpp */
+
+         case 48:       /* png_ptr->row_info.pixel_depth */
+         {
+            png_bytep srcptr;
+            png_bytep dstptr;
+
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED)
+            if ( _mmx_supported )
+            {
+               png_uint_32 len;
+               int diff;
+               int dummy_value_a;   // fix 'forbidden register spilled' error
+               int dummy_value_d;
+               int dummy_value_c;
+               int dummy_value_S;
+               int dummy_value_D;
+               _unmask = ~mask;            // global variable for -fPIC version
+               srcptr = png_ptr->row_buf + 1;
+               dstptr = row;
+               len  = png_ptr->width &~7;  // reduce to multiple of 8
+               diff = (int) (png_ptr->width & 7); // amount lost //
+
+               __asm__ __volatile__ (
+                  "movd      _unmask, %%mm7   \n\t" // load bit pattern
+                  "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
+
+                  : "=a" (dummy_value_a),           // output regs (dummy)
+                    "=d" (dummy_value_d),
+                    "=c" (dummy_value_c),
+                    "=S" (dummy_value_S),
+                    "=D" (dummy_value_D)
+
+                  : "3" (srcptr),      // esi       // input regs
+                    "4" (dstptr),      // edi
+                    "0" (diff),        // eax
+// was (unmask)     "b"    RESERVED    // ebx       // Global Offset Table idx
+                    "2" (len),         // ecx
+                    "1" (mask)         // edx
+
+#if 0  /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */
+                  : "%mm0", "%mm1", "%mm2", "%mm3"  // clobber list
+                  , "%mm4", "%mm5", "%mm6", "%mm7"
+#endif
+               );
+            }
+            else /* mmx _not supported - Use modified C routine */
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */
+            {
+               register png_uint_32 i;
+               png_uint_32 initial_val = BPP6 * png_pass_start[png_ptr->pass];
+                 /* png.c:  png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; */
+               register int stride = BPP6 * png_pass_inc[png_ptr->pass];
+                 /* png.c:  png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; */
+               register int rep_bytes = BPP6 * png_pass_width[png_ptr->pass];
+                 /* png.c:  png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; */
+               png_uint_32 len = png_ptr->width &~7;  /* reduce to mult. of 8 */
+               int diff = (int) (png_ptr->width & 7); /* amount lost */
+               register png_uint_32 final_val = BPP6 * len;   /* GRR bugfix */
+
+               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;
+               }
+               if (diff)  /* number of leftover pixels:  3 for pngtest */
+               {
+                  final_val+=diff*BPP6;
+                  for (; i < final_val; i += stride)
+                  {
+                     if (rep_bytes > (int)(final_val-i))
+                        rep_bytes = (int)(final_val-i);
+                     png_memcpy(dstptr, srcptr, rep_bytes);
+                     srcptr += stride;
+                     dstptr += stride;
+                  }
+               }
+            } /* end of else (_mmx_supported) */
+
+            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 = BPP8 * png_pass_start[png_ptr->pass];
+              /* png.c:  png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; */
+            register int stride = BPP8 * png_pass_inc[png_ptr->pass];
+              /* png.c:  png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; */
+            register int rep_bytes = BPP8 * png_pass_width[png_ptr->pass];
+              /* png.c:  png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; */
+            png_uint_32 len = png_ptr->width &~7;  /* reduce to mult. of 8 */
+            int diff = (int) (png_ptr->width & 7); /* amount lost */
+            register png_uint_32 final_val = BPP8 * len;   /* GRR bugfix */
+
+            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;
+            }
+            if (diff)  /* number of leftover pixels:  3 for pngtest */
+            {
+               final_val+=diff*BPP8;
+               for (; i < final_val; i += stride)
+               {
+                  if (rep_bytes > (int)(final_val-i))
+                     rep_bytes = (int)(final_val-i);
+                  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 */
+
+
+
+
+/*===========================================================================*/
+/*                                                                           */
+/*                 P N G _ D O _ R E A D _ I N T E R L A C E                 */
+/*                                                                           */
+/*===========================================================================*/
+
+#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 /* PRIVATE */
+png_do_read_interlace(png_structp png_ptr)
+{
+   png_row_infop row_info = &(png_ptr->row_info);
+   png_bytep row = png_ptr->row_buf + 1;
+   int pass = png_ptr->pass;
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+   png_uint_32 transformations = png_ptr->transformations;
+#endif
+
+   png_debug(1, "in png_do_read_interlace (pnggccrd.c)\n");
+
+   if (_mmx_supported == 2) {
+       png_mmx_support();
+   }
+
+   if (row != NULL && row_info != NULL)
+   {
+      png_uint_32 final_width;
+
+      final_width = row_info->width * png_pass_inc[pass];
+
+      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) */
+         {
+#if 0
+//          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
+#endif
+            png_bytep sptr, dp;
+            png_uint_32 i;
+            png_size_t pixel_bytes;
+            int width = (int)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 defined(PNG_ASSEMBLER_CODE_SUPPORTED)
+            if ( _mmx_supported )
+            {
+               //--------------------------------------------------------------
+               if (pixel_bytes == 3)
+               {
+                  if (((pass == 0) || (pass == 1)) && width)
+                  {
+                     int dummy_value_c;   // fix 'forbidden register spilled'
+                     int dummy_value_S;
+                     int dummy_value_D;
+
+                     __asm__ __volatile__ (
+                        "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
+
+                        : "=c" (dummy_value_c),        // output regs (dummy)
+                          "=S" (dummy_value_S),
+                          "=D" (dummy_value_D)
+
+                        : "1" (sptr),      // esi      // input regs
+                          "2" (dp),        // edi
+                          "0" (width)      // ecx
+// doesn't work           "i" (0x0000000000FFFFFFLL)   // %1 (a.k.a. _const4)
+
+#if 0  /* %mm0, ..., %mm4 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                        : "%mm0", "%mm1", "%mm2"       // clobber list
+                        , "%mm3", "%mm4"
+#endif
+                     );
+                  }
+                  else if (((pass == 2) || (pass == 3)) && width)
+                  {
+                     int dummy_value_c;   // fix 'forbidden register spilled'
+                     int dummy_value_S;
+                     int dummy_value_D;
+
+                     __asm__ __volatile__ (
+                        "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
+
+                        : "=c" (dummy_value_c),        // output regs (dummy)
+                          "=S" (dummy_value_S),
+                          "=D" (dummy_value_D)
+
+                        : "1" (sptr),      // esi      // input regs
+                          "2" (dp),        // edi
+                          "0" (width)      // ecx
+
+#if 0  /* %mm0, ..., %mm2 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                        : "%mm0", "%mm1", "%mm2"       // clobber list
+#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)
+                     {
+                        // png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
+                        // sptr points at last pixel in pre-expanded row
+                        // dp points at last pixel position in expanded row
+                        int dummy_value_c;  // fix 'forbidden register spilled'
+                        int dummy_value_S;
+                        int dummy_value_D;
+
+                        __asm__ __volatile__ (
+                           "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, %%mm1     \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
+
+                           : "=c" (dummy_value_c),        // output regs (dummy)
+                             "=S" (dummy_value_S),
+                             "=D" (dummy_value_D)
+
+                           : "1" (sptr),      // esi      // input regs
+                             "2" (dp),        // edi
+                             "0" (width_mmx)  // ecx
+
+#if 0  /* %mm0, ..., %mm3 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           : "%mm0", "%mm1"               // clobber list
+                           , "%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)
+                     {
+                        int dummy_value_c;  // fix 'forbidden register spilled'
+                        int dummy_value_S;
+                        int dummy_value_D;
+
+                        __asm__ __volatile__ (
+                           "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
+
+                           : "=c" (dummy_value_c),        // output regs (dummy)
+                             "=S" (dummy_value_S),
+                             "=D" (dummy_value_D)
+
+                           : "1" (sptr),      // esi      // input regs
+                             "2" (dp),        // edi
+                             "0" (width_mmx)  // ecx
+
+#if 0  /* %mm0, ..., %mm4 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           : "%mm0", "%mm1", "%mm2"       // clobber list
+                           , "%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)
+                     {
+                        int dummy_value_c;  // fix 'forbidden register spilled'
+                        int dummy_value_S;
+                        int dummy_value_D;
+
+                        __asm__ __volatile__ (
+                           "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
+
+                           : "=c" (dummy_value_c),        // output regs (dummy)
+                             "=S" (dummy_value_S),
+                             "=D" (dummy_value_D)
+
+                           : "1" (sptr),      // esi      // input regs
+                             "2" (dp),        // edi
+                             "0" (width_mmx)  // ecx
+
+#if 0  /* %mm0, %mm1 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           : "%mm0", "%mm1"               // clobber list
+#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)
+                     {
+                        int dummy_value_c;  // fix 'forbidden register spilled'
+                        int dummy_value_S;
+                        int dummy_value_D;
+
+                        __asm__ __volatile__ (
+                           "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
+
+                           : "=c" (dummy_value_c),        // output regs (none)
+                             "=S" (dummy_value_S),
+                             "=D" (dummy_value_D)
+
+                           : "1" (sptr),      // esi      // input regs
+                             "2" (dp),        // edi
+                             "0" (width_mmx)  // ecx
+
+#if 0  /* %mm0, %mm1 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           : "%mm0", "%mm1"               // clobber list
+#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)
+                     {
+                        int dummy_value_c;  // fix 'forbidden register spilled'
+                        int dummy_value_S;
+                        int dummy_value_D;
+
+                        __asm__ __volatile__ (
+                           "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
+
+                           : "=c" (dummy_value_c),        // output regs (dummy)
+                             "=S" (dummy_value_S),
+                             "=D" (dummy_value_D)
+
+                           : "1" (sptr),      // esi      // input regs
+                             "2" (dp),        // edi
+                             "0" (width_mmx)  // ecx
+
+#if 0  /* %mm0, %mm1 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           : "%mm0", "%mm1"               // clobber list
+#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)
+                     {
+                        int dummy_value_c;  // fix 'forbidden register spilled'
+                        int dummy_value_S;
+                        int dummy_value_D;
+
+                        __asm__ __volatile__ (
+                           "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
+
+                           : "=c" (dummy_value_c),        // output regs (dummy)
+                             "=S" (dummy_value_S),
+                             "=D" (dummy_value_D)
+
+                           : "1" (sptr),      // esi      // input regs
+                             "2" (dp),        // edi
+                             "0" (width_mmx)  // ecx
+
+#if 0  /* %mm0, %mm1 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           : "%mm0", "%mm1"               // clobber list
+#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)
+                     {
+                        int dummy_value_c;  // fix 'forbidden register spilled'
+                        int dummy_value_S;
+                        int dummy_value_D;
+
+                        __asm__ __volatile__ (
+                           "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
+
+                           : "=c" (dummy_value_c),        // output regs (dummy)
+                             "=S" (dummy_value_S),
+                             "=D" (dummy_value_D)
+
+                           : "1" (sptr),      // esi      // input regs
+                             "2" (dp),        // edi
+                             "0" (width_mmx)  // ecx
+
+#if 0  /* %mm0 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           : "%mm0"                       // clobber list
+#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
+                     if (width_mmx)
+                     {
+                        int dummy_value_c;  // fix 'forbidden register spilled'
+                        int dummy_value_S;
+                        int dummy_value_D;
+
+                        __asm__ __volatile__ (
+                           "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
+
+                           : "=c" (dummy_value_c),        // output regs (dummy)
+                             "=S" (dummy_value_S),
+                             "=D" (dummy_value_D)
+
+                           : "1" (sptr),      // esi      // input regs
+                             "2" (dp),        // edi
+                             "0" (width_mmx)  // ecx
+
+#if 0  /* %mm0, %mm1 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           : "%mm0", "%mm1"               // clobber list
+#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)
+                     {
+                        int dummy_value_c;  // fix 'forbidden register spilled'
+                        int dummy_value_S;
+                        int dummy_value_D;
+
+                        __asm__ __volatile__ (
+                           "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
+
+                           : "=c" (dummy_value_c),        // output regs (dummy)
+                             "=S" (dummy_value_S),
+                             "=D" (dummy_value_D)
+
+                           : "1" (sptr),      // esi      // input regs
+                             "2" (dp),        // edi
+                             "0" (width_mmx)  // ecx
+
+#if 0  /* %mm0, %mm1 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           : "%mm0", "%mm1"               // clobber list
+#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)
+                     {
+                        int dummy_value_c;  // fix 'forbidden register spilled'
+                        int dummy_value_S;
+                        int dummy_value_D;
+
+                        __asm__ __volatile__ (
+                           "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
+
+                           : "=c" (dummy_value_c),        // output regs (dummy)
+                             "=S" (dummy_value_S),
+                             "=D" (dummy_value_D)
+
+                           : "1" (sptr),      // esi      // input regs
+                             "2" (dp),        // edi
+                             "0" (width_mmx)  // ecx
+
+#if 0  /* %mm0, %mm1 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           : "%mm0", "%mm1"               // clobber list
+#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 */
+
+               //--------------------------------------------------------------
+               else if (pixel_bytes == 8)
+               {
+// GRR TEST:  should work, but needs testing (special 64-bit version of rpng2?)
+                  // GRR NOTE:  no need to combine passes here!
+                  if (((pass == 0) || (pass == 1)) && width)
+                  {
+                     int dummy_value_c;  // fix 'forbidden register spilled'
+                     int dummy_value_S;
+                     int dummy_value_D;
+
+                     // source is 8-byte RRGGBBAA
+                     // dest is 64-byte RRGGBBAA RRGGBBAA RRGGBBAA RRGGBBAA ...
+                     __asm__ __volatile__ (
+                        "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
+
+                        : "=c" (dummy_value_c),        // output regs (dummy)
+                          "=S" (dummy_value_S),
+                          "=D" (dummy_value_D)
+
+                        : "1" (sptr),      // esi      // input regs
+                          "2" (dp),        // edi
+                          "0" (width)      // ecx
+
+#if 0  /* %mm0 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                        : "%mm0"                       // clobber list
+#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)
+                     {
+                        int dummy_value_c;  // fix 'forbidden register spilled'
+                        int dummy_value_S;
+                        int dummy_value_D;
+
+                        __asm__ __volatile__ (
+                           "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
+
+                           : "=c" (dummy_value_c),        // output regs (dummy)
+                             "=S" (dummy_value_S),
+                             "=D" (dummy_value_D)
+
+                           : "1" (sptr),      // esi      // input regs
+                             "2" (dp),        // edi
+                             "0" (width)      // ecx
+
+#if 0  /* %mm0 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           : "%mm0"                       // clobber list
+#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)
+                     {
+                        int dummy_value_c;  // fix 'forbidden register spilled'
+                        int dummy_value_S;
+                        int dummy_value_D;
+
+                        __asm__ __volatile__ (
+                           "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
+
+                           : "=c" (dummy_value_c),        // output regs (dummy)
+                             "=S" (dummy_value_S),
+                             "=D" (dummy_value_D)
+
+                           : "1" (sptr),      // esi      // input regs
+                             "2" (dp),        // edi
+                             "0" (width)      // ecx
+
+#if 0  /* %mm0 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           : "%mm0"                       // clobber list
+#endif
+                        );
+                     }
+                  }
+
+               } /* end of pixel_bytes == 8 */
+
+               //--------------------------------------------------------------
+               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 png_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 */
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */
+            {
+               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++)
+                     {
+#ifdef PNG_DEBUG
+               if (dp < row || dp+3 > row+png_ptr->row_buf_size)
+                 {
+                  printf("dp out of bounds: row=%d, dp=%d, rp=%d\n",row, dp,
+                    row+png_ptr->row_buf_size);
+                  printf("row_buf=%d\n",png_ptr->row_buf_size);
+                 }
+#endif
+                        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 */
+
+
+
+
+#if defined(PNG_ASSEMBLER_CODE_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;
+
+
+
+//===========================================================================//
+//                                                                           //
+//           P N G _ R E A D _ F I L T E R _ R O W _ M M X _ A V G           //
+//                                                                           //
+//===========================================================================//
+
+// Optimized code for PNG Average filter decoder
+
+static void /* PRIVATE */
+png_read_filter_row_mmx_avg(png_row_infop row_info, png_bytep row,
+                            png_bytep prev_row)
+{
+   int bpp;
+   int dummy_value_c;   // fix 'forbidden register 2 (cx) was spilled' error
+   int dummy_value_S;
+   int dummy_value_D;
+
+   bpp = (row_info->pixel_depth + 7) >> 3;  // get # bytes per pixel
+   _FullLength  = row_info->rowbytes;       // # of bytes to filter
+
+   __asm__ __volatile__ (
+      // initialize address pointers and offset
+#ifdef __PIC__
+      "pushl %%ebx                 \n\t" // save index to Global Offset Table
+#endif
+//pre "movl row, %%edi             \n\t" // edi:  Avg(x)
+      "xorl %%ebx, %%ebx           \n\t" // ebx:  x
+      "movl %%edi, %%edx           \n\t"
+//pre "movl prev_row, %%esi        \n\t" // esi:  Prior(x)
+//pre "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
+//pre "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
+      "jz avg_go                   \n\t" //  alignment
+
+      // 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"
+#ifdef __PIC__
+      "popl %%ebx                  \n\t" // restore index to Global Offset Table
+#endif
+
+      : "=c" (dummy_value_c),            // output regs (dummy)
+        "=S" (dummy_value_S),
+        "=D" (dummy_value_D)
+
+      : "0" (bpp),       // ecx          // input regs
+        "1" (prev_row),  // esi
+        "2" (row)        // edi
+
+      : "%eax", "%edx"                   // clobber list
+#ifndef __PIC__
+      , "%ebx"
+#endif
+      // GRR: INCLUDE "memory" as clobbered? (_dif, _MMXLength)
+      // (seems to work fine without...)
+   );
+
+   // now do the math for the rest of the row
+   switch (bpp)
+   {
+      case 3:
+      {
+         _ActiveMask.use  = 0x0000000000ffffffLL;
+         _ShiftBpp.use = 24;    // == 3 * 8
+         _ShiftRem.use = 40;    // == 64 - 24
+
+         __asm__ __volatile__ (
+            // re-init address pointers and offset
+            "movq _ActiveMask, %%mm7      \n\t"
+            "movl _dif, %%ecx             \n\t" // ecx:  x = offset to
+            "movq _LBCarryMask, %%mm5     \n\t" //  alignment boundary
+// preload  "movl row, %%edi              \n\t" // edi:  Avg(x)
+            "movq _HBClearMask, %%mm4     \n\t"
+// preload  "movl prev_row, %%esi         \n\t" // esi:  Prior(x)
+
+            // prime the pump:  load the first Raw(x-bpp) data set
+            "movq -8(%%edi,%%ecx,), %%mm2 \n\t" // load previous aligned 8 bytes
+                                                // (correct pos. in loop below)
+         "avg_3lp:                        \n\t"
+            "movq (%%edi,%%ecx,), %%mm0   \n\t" // load mm0 with Avg(x)
+            "movq %%mm5, %%mm3            \n\t"
+            "psrlq _ShiftRem, %%mm2       \n\t" // correct position Raw(x-bpp) data
+            "movq (%%esi,%%ecx,), %%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 pos. 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 mm6 mask to cover last two
+                                 // bytes
+            "movq %%mm0, %%mm2            \n\t" // mov updated Raws to mm2
+            "psllq _ShiftBpp, %%mm2       \n\t" // shift data to pos. 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, %%ecx               \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,%%ecx,) \n\t"
+            // move updated Raw(x) to use as Raw(x-bpp) for next loop
+            "cmpl _MMXLength, %%ecx       \n\t"
+            "movq %%mm0, %%mm2            \n\t" // mov updated Raw(x) to mm2
+            "jb avg_3lp                   \n\t"
+
+            : "=S" (dummy_value_S),             // output regs (dummy)
+              "=D" (dummy_value_D)
+
+            : "0" (prev_row),  // esi           // input regs
+              "1" (row)        // edi
+
+            : "%ecx"                            // clobber list
+#if 0  /* %mm0, ..., %mm7 not supported by gcc 2.7.2.3 or egcs 1.1 */
+            , "%mm0", "%mm1", "%mm2", "%mm3"
+            , "%mm4", "%mm5", "%mm6", "%mm7"
+#endif
+         );
+      }
+      break;  // end 3 bpp
+
+      case 6:
+      case 4:
+      //case 7:   // who wrote this?  PNG doesn't support 5 or 7 bytes/pixel
+      //case 5:   // GRR BOGUS
+      {
+         _ActiveMask.use  = 0xffffffffffffffffLL; // use shift below to clear
+                                                  // appropriate inactive bytes
+         _ShiftBpp.use = bpp << 3;
+         _ShiftRem.use = 64 - _ShiftBpp.use;
+
+         __asm__ __volatile__ (
+            "movq _HBClearMask, %%mm4    \n\t"
+
+            // re-init address pointers and offset
+            "movl _dif, %%ecx            \n\t" // ecx:  x = offset to alignment boundary
+
+            // load _ActiveMask and clear all bytes except for 1st active group
+            "movq _ActiveMask, %%mm7     \n\t"
+// preload  "movl row, %%edi             \n\t" // edi:  Avg(x)
+            "psrlq _ShiftRem, %%mm7      \n\t"
+// preload  "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,%%ecx,), %%mm2 \n\t" // load previous aligned 8 bytes
+                                          // (we correct pos. in loop below)
+         "avg_4lp:                       \n\t"
+            "movq (%%edi,%%ecx,), %%mm0  \n\t"
+            "psrlq _ShiftRem, %%mm2      \n\t" // shift data to pos. correctly
+            "movq (%%esi,%%ecx,), %%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 pos. correctly
+            "addl $8, %%ecx              \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, %%ecx      \n\t"
+            // now ready to write back to memory
+            "movq %%mm0, -8(%%edi,%%ecx,) \n\t"
+            // prep Raw(x-bpp) for next loop
+            "movq %%mm0, %%mm2           \n\t" // mov updated Raws to mm2
+            "jb avg_4lp                  \n\t"
+
+            : "=S" (dummy_value_S),            // output regs (dummy)
+              "=D" (dummy_value_D)
+
+            : "0" (prev_row),  // esi          // input regs
+              "1" (row)        // edi
+
+            : "%ecx"                           // clobber list
+#if 0  /* %mm0, ..., %mm7 not supported by gcc 2.7.2.3 or egcs 1.1 */
+            , "%mm0", "%mm1", "%mm2", "%mm3"
+            , "%mm4", "%mm5", "%mm6", "%mm7"
+#endif
+         );
+      }
+      break;  // end 4,6 bpp
+
+      case 2:
+      {
+         _ActiveMask.use  = 0x000000000000ffffLL;
+         _ShiftBpp.use = 16;   // == 2 * 8
+         _ShiftRem.use = 48;   // == 64 - 16
+
+         __asm__ __volatile__ (
+            // load _ActiveMask
+            "movq _ActiveMask, %%mm7     \n\t"
+            // re-init address pointers and offset
+            "movl _dif, %%ecx            \n\t" // ecx:  x = offset to alignment boundary
+            "movq _LBCarryMask, %%mm5    \n\t"
+// preload  "movl row, %%edi             \n\t" // edi:  Avg(x)
+            "movq _HBClearMask, %%mm4    \n\t"
+// preload  "movl prev_row, %%esi        \n\t" // esi:  Prior(x)
+
+            // prime the pump:  load the first Raw(x-bpp) data set
+            "movq -8(%%edi,%%ecx,), %%mm2 \n\t" // load previous aligned 8 bytes
+                              // (we correct pos. in loop below)
+         "avg_2lp:                       \n\t"
+            "movq (%%edi,%%ecx,), %%mm0  \n\t"
+            "psrlq _ShiftRem, %%mm2      \n\t" // shift data to pos. correctly
+            "movq (%%esi,%%ecx,), %%mm1  \n\t" //  (GRR BUGFIX:  was psllq)
+            // 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 pos. 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 bytes 4 & 5
+            "movq %%mm0, %%mm2           \n\t" // mov updated Raws to mm2
+            "psllq _ShiftBpp, %%mm2      \n\t" // shift data to pos. 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 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 pos. correctly
+            "addl $8, %%ecx              \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, %%ecx      \n\t"
+            // now ready to write back to memory
+            "movq %%mm0, -8(%%edi,%%ecx,) \n\t"
+            // prep Raw(x-bpp) for next loop
+            "movq %%mm0, %%mm2           \n\t" // mov updated Raws to mm2
+            "jb avg_2lp                  \n\t"
+
+            : "=S" (dummy_value_S),            // output regs (dummy)
+              "=D" (dummy_value_D)
+
+            : "0" (prev_row),  // esi          // input regs
+              "1" (row)        // edi
+
+            : "%ecx"                           // clobber list
+#if 0  /* %mm0, ..., %mm7 not supported by gcc 2.7.2.3 or egcs 1.1 */
+            , "%mm0", "%mm1", "%mm2", "%mm3"
+            , "%mm4", "%mm5", "%mm6", "%mm7"
+#endif
+         );
+      }
+      break;  // end 2 bpp
+
+      case 1:
+      {
+         __asm__ __volatile__ (
+            // re-init address pointers and offset
+#ifdef __PIC__
+            "pushl %%ebx                 \n\t" // save Global Offset Table index
+#endif
+            "movl _dif, %%ebx            \n\t" // ebx:  x = offset to alignment boundary
+// preload  "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
+// preload  "movl prev_row, %%esi        \n\t" // esi:  Prior(x)
+            "movl %%edi, %%edx           \n\t"
+// preload  "subl bpp, %%edx             \n\t" // (bpp is preloaded into ecx)
+            "subl %%ecx, %%edx           \n\t" // edx:  Raw(x-bpp)
+            "xorl %%ecx, %%ecx           \n\t" // zero ecx before using cl & cx
+                                               //  in loop below
+         "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"
+#ifdef __PIC__
+            "popl %%ebx                  \n\t" // Global Offset Table index
+#endif
+
+            : "=c" (dummy_value_c),            // output regs (dummy)
+              "=S" (dummy_value_S),
+              "=D" (dummy_value_D)
+
+            : "0" (bpp),       // ecx          // input regs
+              "1" (prev_row),  // esi
+              "2" (row)        // edi
+
+            : "%eax", "%edx"                   // clobber list
+#ifndef __PIC__
+            , "%ebx"
+#endif
+         );
+      }
+      return;  // end 1 bpp
+
+      case 8:
+      {
+         __asm__ __volatile__ (
+            // re-init address pointers and offset
+            "movl _dif, %%ecx            \n\t" // ecx:  x == offset to alignment
+            "movq _LBCarryMask, %%mm5    \n\t" //            boundary
+// preload  "movl row, %%edi             \n\t" // edi:  Avg(x)
+            "movq _HBClearMask, %%mm4    \n\t"
+// preload  "movl prev_row, %%esi        \n\t" // esi:  Prior(x)
+
+            // prime the pump:  load the first Raw(x-bpp) data set
+            "movq -8(%%edi,%%ecx,), %%mm2 \n\t" // load previous aligned 8 bytes
+                                      // (NO NEED to correct pos. in loop below)
+
+         "avg_8lp:                       \n\t"
+            "movq (%%edi,%%ecx,), %%mm0  \n\t"
+            "movq %%mm5, %%mm3           \n\t"
+            "movq (%%esi,%%ecx,), %%mm1  \n\t"
+            "addl $8, %%ecx              \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, each byte
+            "paddb %%mm3, %%mm0          \n\t" // add LBCarrys to Avg, each byte
+            "pand  %%mm4, %%mm2          \n\t" // clear invalid bit 7, each byte
+            "paddb %%mm1, %%mm0          \n\t" // add (Prev_row/2) to Avg, each
+            "paddb %%mm2, %%mm0          \n\t" // add (Raw/2) to Avg for each
+            "cmpl _MMXLength, %%ecx      \n\t"
+            "movq %%mm0, -8(%%edi,%%ecx,) \n\t"
+            "movq %%mm0, %%mm2           \n\t" // reuse as Raw(x-bpp)
+            "jb avg_8lp                  \n\t"
+
+            : "=S" (dummy_value_S),            // output regs (dummy)
+              "=D" (dummy_value_D)
+
+            : "0" (prev_row),  // esi          // input regs
+              "1" (row)        // edi
+
+            : "%ecx"                           // clobber list
+#if 0  /* %mm0, ..., %mm5 not supported by gcc 2.7.2.3 or egcs 1.1 */
+            , "%mm0", "%mm1", "%mm2"
+            , "%mm3", "%mm4", "%mm5"
+#endif
+         );
+      }
+      break;  // end 8 bpp
+
+      default:                  // bpp greater than 8 (!= 1,2,3,4,[5],6,[7],8)
+      {
+
+         // GRR:  PRINT ERROR HERE:  SHOULD NEVER BE REACHED
+         fprintf(stderr,
+           "libpng:  internal logic error (png_read_filter_row_mmx_avg())\n");
+
+#if 0
+        __asm__ __volatile__ (
+            "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" // CHECKASM: clobber list
+         );
+#endif /* 0 - NEVER REACHED */
+      }
+      break;
+
+   } // end switch (bpp)
+
+   __asm__ __volatile__ (
+      // MMX acceleration complete; now do clean-up
+      // check if any remaining bytes left to decode
+#ifdef __PIC__
+      "pushl %%ebx                 \n\t" // save index to Global Offset Table
+#endif
+      "movl _MMXLength, %%ebx      \n\t" // ebx:  x == offset bytes after MMX
+//pre "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 Avg decode for remaining bytes
+//pre "movl prev_row, %%esi        \n\t" // esi:  Prior(x)
+      "movl %%edi, %%edx           \n\t"
+//pre "subl bpp, %%edx             \n\t" // (bpp is preloaded into ecx)
+      "subl %%ecx, %%edx           \n\t" // edx:  Raw(x-bpp)
+      "xorl %%ecx, %%ecx           \n\t" // zero ecx before using cl & cx below
+
+   "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
+      "jb avg_lp2                  \n\t" //  affect flags; -1 to offset inc ebx]
+
+   "avg_end:                       \n\t"
+      "EMMS                        \n\t" // end MMX; prep for poss. FP instrs.
+#ifdef __PIC__
+      "popl %%ebx                  \n\t" // restore index to Global Offset Table
+#endif
+
+      : "=c" (dummy_value_c),            // output regs (dummy)
+        "=S" (dummy_value_S),
+        "=D" (dummy_value_D)
+
+      : "0" (bpp),       // ecx          // input regs
+        "1" (prev_row),  // esi
+        "2" (row)        // edi
+
+      : "%eax", "%edx"                   // clobber list
+#ifndef __PIC__
+      , "%ebx"
+#endif
+   );
+
+} /* end png_read_filter_row_mmx_avg() */
+
+
+
+
+//===========================================================================//
+//                                                                           //
+//         P N G _ R E A D _ F I L T E R _ R O W _ M M X _ P A E T H         //
+//                                                                           //
+//===========================================================================//
+
+// Optimized code for PNG Paeth filter decoder
+
+static void /* PRIVATE */
+png_read_filter_row_mmx_paeth(png_row_infop row_info, png_bytep row,
+                              png_bytep prev_row)
+{
+   int bpp;
+   int dummy_value_c;   // fix 'forbidden register 2 (cx) was spilled' error
+   int dummy_value_S;
+   int dummy_value_D;
+
+   bpp = (row_info->pixel_depth + 7) >> 3; // Get # bytes per pixel
+   _FullLength  = row_info->rowbytes; // # of bytes to filter
+
+   __asm__ __volatile__ (
+#ifdef __PIC__
+      "pushl %%ebx                 \n\t" // save index to Global Offset Table
+#endif
+      "xorl %%ebx, %%ebx           \n\t" // ebx:  x offset
+//pre "movl row, %%edi             \n\t"
+      "xorl %%edx, %%edx           \n\t" // edx:  x-bpp offset
+//pre "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"
+//pre "cmpl bpp, %%ebx             \n\t" (bpp is preloaded into ecx)
+      "cmpl %%ecx, %%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"
+#ifdef __PIC__
+      "popl %%ebx                  \n\t" // restore index to Global Offset Table
+#endif
+
+      : "=c" (dummy_value_c),            // output regs (dummy)
+        "=S" (dummy_value_S),
+        "=D" (dummy_value_D)
+
+      : "0" (bpp),       // ecx          // input regs
+        "1" (prev_row),  // esi
+        "2" (row)        // edi
+
+      : "%eax", "%edx"                   // clobber list
+#ifndef __PIC__
+      , "%ebx"
+#endif
+   );
+
+   // now do the math for the rest of the row
+   switch (bpp)
+   {
+      case 3:
+      {
+         _ActiveMask.use = 0x0000000000ffffffLL;
+         _ActiveMaskEnd.use = 0xffff000000000000LL;
+         _ShiftBpp.use = 24;    // == bpp(3) * 8
+         _ShiftRem.use = 40;    // == 64 - 24
+
+         __asm__ __volatile__ (
+            "movl _dif, %%ecx            \n\t"
+// preload  "movl row, %%edi             \n\t"
+// preload  "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,%%ecx,), %%mm1 \n\t"
+         "paeth_3lp:                     \n\t"
+            "psrlq _ShiftRem, %%mm1      \n\t" // shift last 3 bytes to 1st 3 bytes
+            "movq (%%esi,%%ecx,), %%mm2  \n\t" // load b=Prior(x)
+            "punpcklbw %%mm0, %%mm1      \n\t" // unpack High bytes of a
+            "movq -8(%%esi,%%ecx,), %%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,%%ecx,), %%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,%%ecx,), %%mm7 \n\t" // add Paeth predictor with Raw(x)
+            "punpcklbw %%mm0, %%mm3      \n\t" // unpack High bytes of c
+            "movq %%mm7, (%%edi,%%ecx,)  \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,%%ecx,), %%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,%%ecx,), %%mm7 \n\t" // add Paeth predictor with Raw(x)
+            "psllq _ShiftBpp, %%mm3      \n\t" // load c=Prior(x-bpp) step 2
+            "movq %%mm7, (%%edi,%%ecx,)  \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 ecx to next set of 8 bytes and repeat loop til done
+            "addl $8, %%ecx              \n\t"
+            "pand _ActiveMaskEnd, %%mm1  \n\t"
+            "paddb -8(%%edi,%%ecx,), %%mm1 \n\t" // add Paeth predictor with Raw(x)
+
+            "cmpl _MMXLength, %%ecx      \n\t"
+            "pxor %%mm0, %%mm0           \n\t" // pxor does not affect flags
+            "movq %%mm1, -8(%%edi,%%ecx,) \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"
+
+            : "=S" (dummy_value_S),             // output regs (dummy)
+              "=D" (dummy_value_D)
+
+            : "0" (prev_row),  // esi           // input regs
+              "1" (row)        // edi
+
+            : "%ecx"                            // clobber list
+#if 0  /* %mm0, ..., %mm7 not supported by gcc 2.7.2.3 or egcs 1.1 */
+            , "%mm0", "%mm1", "%mm2", "%mm3"
+            , "%mm4", "%mm5", "%mm6", "%mm7"
+#endif
+         );
+      }
+      break;  // end 3 bpp
+
+      case 6:
+      //case 7:   // GRR BOGUS
+      //case 5:   // GRR BOGUS
+      {
+         _ActiveMask.use  = 0x00000000ffffffffLL;
+         _ActiveMask2.use = 0xffffffff00000000LL;
+         _ShiftBpp.use = bpp << 3;    // == bpp * 8
+         _ShiftRem.use = 64 - _ShiftBpp.use;
+
+         __asm__ __volatile__ (
+            "movl _dif, %%ecx            \n\t"
+// preload  "movl row, %%edi             \n\t"
+// preload  "movl prev_row, %%esi        \n\t"
+            // prime the pump:  load the first Raw(x-bpp) data set
+            "movq -8(%%edi,%%ecx,), %%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,%%ecx,), %%mm3 \n\t" // read c=Prior(x-bpp) bytes
+            "punpcklbw %%mm0, %%mm1      \n\t" // unpack Low bytes of a
+            "movq (%%esi,%%ecx,), %%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,%%ecx,), %%mm3 \n\t" // load c=Prior(x-bpp)
+            "pand _ActiveMask, %%mm7     \n\t"
+            "psrlq _ShiftRem, %%mm3      \n\t"
+            "movq (%%esi,%%ecx,), %%mm2  \n\t" // load b=Prior(x) step 1
+            "paddb (%%edi,%%ecx,), %%mm7 \n\t" // add Paeth predictor and Raw(x)
+            "movq %%mm2, %%mm6           \n\t"
+            "movq %%mm7, (%%edi,%%ecx,)  \n\t" // write back updated value
+            "movq -8(%%edi,%%ecx,), %%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 ecx to next set of 8 bytes and repeat loop til done
+            "addl $8, %%ecx              \n\t"
+            "packuswb %%mm7, %%mm1       \n\t"
+            "paddb -8(%%edi,%%ecx,), %%mm1 \n\t" // add Paeth predictor with Raw(x)
+            "cmpl _MMXLength, %%ecx      \n\t"
+            "movq %%mm1, -8(%%edi,%%ecx,) \n\t" // write back updated value
+                                // mm1 will be used as Raw(x-bpp) next loop
+            "jb paeth_6lp                \n\t"
+
+            : "=S" (dummy_value_S),             // output regs (dummy)
+              "=D" (dummy_value_D)
+
+            : "0" (prev_row),  // esi           // input regs
+              "1" (row)        // edi
+
+            : "%ecx"                            // clobber list
+#if 0  /* %mm0, ..., %mm7 not supported by gcc 2.7.2.3 or egcs 1.1 */
+            , "%mm0", "%mm1", "%mm2", "%mm3"
+            , "%mm4", "%mm5", "%mm6", "%mm7"
+#endif
+         );
+      }
+      break;  // end 6 bpp
+
+      case 4:
+      {
+         _ActiveMask.use  = 0x00000000ffffffffLL;
+
+         __asm__ __volatile__ (
+            "movl _dif, %%ecx            \n\t"
+// preload  "movl row, %%edi             \n\t"
+// preload  "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,%%ecx,), %%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,%%ecx,), %%mm3 \n\t" // read c=Prior(x-bpp) bytes
+            "punpckhbw %%mm0, %%mm1      \n\t" // unpack Low bytes of a
+            "movq (%%esi,%%ecx,), %%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,%%ecx,), %%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,%%ecx,), %%mm7 \n\t" // add Paeth predictor with Raw(x)
+            "punpcklbw %%mm0, %%mm3      \n\t" // unpack High bytes of c
+            "movq %%mm7, (%%edi,%%ecx,)  \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 ecx to next set of 8 bytes and repeat loop til done
+            "addl $8, %%ecx              \n\t"
+            "packuswb %%mm7, %%mm1       \n\t"
+            "paddb -8(%%edi,%%ecx,), %%mm1 \n\t" // add predictor with Raw(x)
+            "cmpl _MMXLength, %%ecx      \n\t"
+            "movq %%mm1, -8(%%edi,%%ecx,) \n\t" // write back updated value
+                                // mm1 will be used as Raw(x-bpp) next loop
+            "jb paeth_4lp                \n\t"
+
+            : "=S" (dummy_value_S),             // output regs (dummy)
+              "=D" (dummy_value_D)
+
+            : "0" (prev_row),  // esi           // input regs
+              "1" (row)        // edi
+
+            : "%ecx"                            // clobber list
+#if 0  /* %mm0, ..., %mm7 not supported by gcc 2.7.2.3 or egcs 1.1 */
+            , "%mm0", "%mm1", "%mm2", "%mm3"
+            , "%mm4", "%mm5", "%mm6", "%mm7"
+#endif
+         );
+      }
+      break;  // end 4 bpp
+
+      case 8:                          // bpp == 8
+      {
+         _ActiveMask.use  = 0x00000000ffffffffLL;
+
+         __asm__ __volatile__ (
+            "movl _dif, %%ecx            \n\t"
+// preload  "movl row, %%edi             \n\t"
+// preload  "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,%%ecx,), %%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,%%ecx,), %%mm3 \n\t" // read c=Prior(x-bpp) bytes
+            "punpcklbw %%mm0, %%mm1      \n\t" // unpack Low bytes of a
+            "movq (%%esi,%%ecx,), %%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,%%ecx,), %%mm3 \n\t" // read c=Prior(x-bpp) bytes
+            "pand _ActiveMask, %%mm7     \n\t"
+            "movq (%%esi,%%ecx,), %%mm2  \n\t" // load b=Prior(x)
+            "paddb (%%edi,%%ecx,), %%mm7 \n\t" // add Paeth predictor with Raw(x)
+            "punpckhbw %%mm0, %%mm3      \n\t" // unpack High bytes of c
+            "movq %%mm7, (%%edi,%%ecx,)  \n\t" // write back updated value
+            "movq -8(%%edi,%%ecx,), %%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 ecx to next set of 8 bytes and repeat loop til done
+            "addl $8, %%ecx              \n\t"
+            "packuswb %%mm7, %%mm1       \n\t"
+            "paddb -8(%%edi,%%ecx,), %%mm1 \n\t" // add Paeth predictor with Raw(x)
+            "cmpl _MMXLength, %%ecx      \n\t"
+            "movq %%mm1, -8(%%edi,%%ecx,) \n\t" // write back updated value
+                            // mm1 will be used as Raw(x-bpp) next loop
+            "jb paeth_8lp                \n\t"
+
+            : "=S" (dummy_value_S),             // output regs (dummy)
+              "=D" (dummy_value_D)
+
+            : "0" (prev_row),  // esi           // input regs
+              "1" (row)        // edi
+
+            : "%ecx"                            // clobber list
+#if 0  /* %mm0, ..., %mm7 not supported by gcc 2.7.2.3 or egcs 1.1 */
+            , "%mm0", "%mm1", "%mm2", "%mm3"
+            , "%mm4", "%mm5", "%mm6", "%mm7"
+#endif
+         );
+      }
+      break;  // end 8 bpp
+
+      case 1:                // bpp = 1
+      case 2:                // bpp = 2
+      default:               // bpp > 8
+      {
+         __asm__ __volatile__ (
+#ifdef __PIC__
+            "pushl %%ebx                 \n\t" // save Global Offset Table index
+#endif
+            "movl _dif, %%ebx            \n\t"
+            "cmpl _FullLength, %%ebx     \n\t"
+            "jnb paeth_dend              \n\t"
+
+// preload  "movl row, %%edi             \n\t"
+// preload  "movl prev_row, %%esi        \n\t"
+            // do Paeth decode for remaining bytes
+            "movl %%ebx, %%edx           \n\t"
+// preload  "subl bpp, %%edx             \n\t" // (bpp is preloaded into ecx)
+            "subl %%ecx, %%edx           \n\t" // edx = ebx - bpp
+            "xorl %%ecx, %%ecx           \n\t" // zero ecx before using cl & cx
+
+         "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"
+#ifdef __PIC__
+            "popl %%ebx                  \n\t" // index to Global Offset Table
+#endif
+
+            : "=c" (dummy_value_c),            // output regs (dummy)
+              "=S" (dummy_value_S),
+              "=D" (dummy_value_D)
+
+            : "0" (bpp),       // ecx          // input regs
+              "1" (prev_row),  // esi
+              "2" (row)        // edi
+
+            : "%eax", "%edx"                   // clobber list
+#ifndef __PIC__
+            , "%ebx"
+#endif
+         );
+      }
+      return;                   // No need to go further with this one
+
+   } // end switch (bpp)
+
+   __asm__ __volatile__ (
+      // MMX acceleration complete; now do clean-up
+      // check if any remaining bytes left to decode
+#ifdef __PIC__
+      "pushl %%ebx                 \n\t" // save index to Global Offset Table
+#endif
+      "movl _MMXLength, %%ebx      \n\t"
+      "cmpl _FullLength, %%ebx     \n\t"
+      "jnb paeth_end               \n\t"
+//pre "movl row, %%edi             \n\t"
+//pre "movl prev_row, %%esi        \n\t"
+      // do Paeth decode for remaining bytes
+      "movl %%ebx, %%edx           \n\t"
+//pre "subl bpp, %%edx             \n\t" // (bpp is preloaded into ecx)
+      "subl %%ecx, %%edx           \n\t" // edx = ebx - bpp
+      "xorl %%ecx, %%ecx           \n\t" // zero ecx before using cl & cx below
+
+   "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; prep for poss. FP instrs.
+#ifdef __PIC__
+      "popl %%ebx                  \n\t" // restore index to Global Offset Table
+#endif
+
+      : "=c" (dummy_value_c),            // output regs (dummy)
+        "=S" (dummy_value_S),
+        "=D" (dummy_value_D)
+
+      : "0" (bpp),       // ecx          // input regs
+        "1" (prev_row),  // esi
+        "2" (row)        // edi
+
+      : "%eax", "%edx"                   // clobber list (no input regs!)
+#ifndef __PIC__
+      , "%ebx"
+#endif
+   );
+
+} /* end png_read_filter_row_mmx_paeth() */
+
+
+
+
+//===========================================================================//
+//                                                                           //
+//           P N G _ R E A D _ F I L T E R _ R O W _ M M X _ S U B           //
+//                                                                           //
+//===========================================================================//
+
+// Optimized code for PNG Sub filter decoder
+
+static void /* PRIVATE */
+png_read_filter_row_mmx_sub(png_row_infop row_info, png_bytep row)
+{
+   int bpp;
+   int dummy_value_a;
+   int dummy_value_D;
+
+   bpp = (row_info->pixel_depth + 7) >> 3;   // calc number of bytes per pixel
+   _FullLength = row_info->rowbytes - bpp;   // number of bytes to filter
+
+   __asm__ __volatile__ (
+//pre "movl row, %%edi             \n\t"
+      "movl %%edi, %%esi           \n\t" // lp = row
+//pre "movl bpp, %%eax             \n\t"
+      "addl %%eax, %%edi           \n\t" // rp = row + bpp
+//irr "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 %%ecx, %%ecx           \n\t"
+      "andl $0xfffffff8, _dif      \n\t" // mask to alignment boundary
+      "subl %%edi, _dif            \n\t" // subtract from start ==> value
+      "jz sub_go                   \n\t" //  ecx at alignment
+
+   "sub_lp1:                       \n\t" // fix alignment
+      "movb (%%esi,%%ecx,), %%al   \n\t"
+      "addb %%al, (%%edi,%%ecx,)   \n\t"
+      "incl %%ecx                  \n\t"
+      "cmpl _dif, %%ecx            \n\t"
+      "jb sub_lp1                  \n\t"
+
+   "sub_go:                        \n\t"
+      "movl _FullLength, %%eax     \n\t"
+      "movl %%eax, %%edx           \n\t"
+      "subl %%ecx, %%edx           \n\t" // subtract alignment fix
+      "andl $0x00000007, %%edx     \n\t" // calc bytes over mult of 8
+      "subl %%edx, %%eax           \n\t" // drop over bytes from length
+      "movl %%eax, _MMXLength      \n\t"
+
+      : "=a" (dummy_value_a),   // 0      // output regs (dummy)
+        "=D" (dummy_value_D)    // 1
+
+      : "0" (bpp),              // eax    // input regs
+        "1" (row)               // edi
+
+      : "%ebx", "%ecx", "%edx"            // clobber list
+      , "%esi"
+
+#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
+   );
+
+   // now do the math for the rest of the row
+   switch (bpp)
+   {
+      case 3:
+      {
+         _ActiveMask.use  = 0x0000ffffff000000LL;
+         _ShiftBpp.use = 24;       // == 3 * 8
+         _ShiftRem.use  = 40;      // == 64 - 24
+
+         __asm__ __volatile__ (
+// preload  "movl row, %%edi              \n\t"
+            "movq _ActiveMask, %%mm7       \n\t" // load _ActiveMask for 2nd
+                                                //  active byte group
+            "movl %%edi, %%esi            \n\t" // lp = row
+// preload  "movl bpp, %%eax              \n\t"
+            "addl %%eax, %%edi            \n\t" // rp = row + bpp
+            "movq %%mm7, %%mm6            \n\t"
+            "movl _dif, %%edx             \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,%%edx,), %%mm1 \n\t"
+
+         "sub_3lp:                        \n\t" // shift data for adding first
+            "psrlq _ShiftRem, %%mm1       \n\t" //  bpp bytes (no need for mask;
+                                                //  shift clears inactive bytes)
+            // add 1st active group
+            "movq (%%edi,%%edx,), %%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 pos. correctly
+            "pand %%mm7, %%mm1            \n\t" // mask to use 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 pos. correctly
+            "pand %%mm6, %%mm1            \n\t" // mask to use 3rd active group
+            "addl $8, %%edx               \n\t"
+            "paddb %%mm1, %%mm0           \n\t"
+
+            "cmpl _MMXLength, %%edx       \n\t"
+            "movq %%mm0, -8(%%edi,%%edx,) \n\t" // write updated Raws to array
+            "movq %%mm0, %%mm1            \n\t" // prep 1st add at top of loop
+            "jb sub_3lp                   \n\t"
+
+            : "=a" (dummy_value_a),   // 0      // output regs (dummy)
+              "=D" (dummy_value_D)    // 1
+
+            : "0" (bpp),              // eax    // input regs
+              "1" (row)               // edi
+
+            : "%edx", "%esi"                    // clobber list
+#if 0  /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */
+            , "%mm0", "%mm1", "%mm6", "%mm7"
+#endif
+         );
+      }
+      break;
+
+      case 1:
+      {
+         __asm__ __volatile__ (
+            "movl _dif, %%edx            \n\t"
+// preload  "movl row, %%edi             \n\t"
+            "cmpl _FullLength, %%edx     \n\t"
+            "jnb sub_1end                \n\t"
+            "movl %%edi, %%esi           \n\t" // lp = row
+            "xorl %%eax, %%eax           \n\t"
+// preload  "movl bpp, %%eax             \n\t"
+            "addl %%eax, %%edi           \n\t" // rp = row + bpp
+
+         "sub_1lp:                       \n\t"
+            "movb (%%esi,%%edx,), %%al   \n\t"
+            "addb %%al, (%%edi,%%edx,)   \n\t"
+            "incl %%edx                  \n\t"
+            "cmpl _FullLength, %%edx     \n\t"
+            "jb sub_1lp                  \n\t"
+
+         "sub_1end:                      \n\t"
+
+            : "=a" (dummy_value_a),   // 0      // output regs (dummy)
+              "=D" (dummy_value_D)    // 1
+
+            : "0" (bpp),              // eax    // input regs
+              "1" (row)               // edi
+
+            : "%edx", "%esi"                    // clobber list
+         );
+      }
+      return;
+
+      case 6:
+      case 4:
+      //case 7:   // GRR BOGUS
+      //case 5:   // GRR BOGUS
+      {
+         _ShiftBpp.use = bpp << 3;
+         _ShiftRem.use = 64 - _ShiftBpp.use;
+
+         __asm__ __volatile__ (
+// preload  "movl row, %%edi              \n\t"
+            "movl _dif, %%edx             \n\t"
+            "movl %%edi, %%esi            \n\t" // lp = row
+// preload  "movl bpp, %%eax              \n\t"
+            "addl %%eax, %%edi            \n\t" // rp = row + bpp
+
+            // prime the pump:  load the first Raw(x-bpp) data set
+            "movq -8(%%edi,%%edx,), %%mm1 \n\t"
+
+         "sub_4lp:                        \n\t" // shift data for adding first
+            "psrlq _ShiftRem, %%mm1       \n\t" //  bpp bytes (no need for mask;
+                                                //  shift clears inactive bytes)
+            "movq (%%edi,%%edx,), %%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 pos. correctly
+            "addl $8, %%edx               \n\t"
+            "paddb %%mm1, %%mm0           \n\t"
+
+            "cmpl _MMXLength, %%edx       \n\t"
+            "movq %%mm0, -8(%%edi,%%edx,) \n\t"
+            "movq %%mm0, %%mm1            \n\t" // prep 1st add at top of loop
+            "jb sub_4lp                   \n\t"
+
+            : "=a" (dummy_value_a),   // 0      // output regs (dummy)
+              "=D" (dummy_value_D)    // 1
+
+            : "0" (bpp),              // eax    // input regs
+              "1" (row)               // edi
+
+            : "%edx", "%esi"                    // clobber list
+#if 0  /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */
+            , "%mm0", "%mm1"
+#endif
+         );
+      }
+      break;
+
+      case 2:
+      {
+         _ActiveMask.use = 0x00000000ffff0000LL;
+         _ShiftBpp.use = 16;       // == 2 * 8
+         _ShiftRem.use = 48;       // == 64 - 16
+
+         __asm__ __volatile__ (
+            "movq _ActiveMask, %%mm7      \n\t" // load _ActiveMask for 2nd
+                                                //  active byte group
+            "movl _dif, %%edx             \n\t"
+            "movq %%mm7, %%mm6            \n\t"
+// preload  "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"
+// preload  "movl bpp, %%eax              \n\t"
+            "addl %%eax, %%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,%%edx,), %%mm1 \n\t"
+
+         "sub_2lp:                        \n\t" // shift data for adding first
+            "psrlq _ShiftRem, %%mm1       \n\t" //  bpp bytes (no need for mask;
+                                                //  shift clears inactive bytes)
+            // add 1st active group
+            "movq (%%edi,%%edx,), %%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 pos. correctly
+            "pand %%mm7, %%mm1            \n\t" // mask to use 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 pos. correctly
+            "pand %%mm6, %%mm1            \n\t" // mask to use 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 pos. correctly
+            "pand %%mm5, %%mm1            \n\t" // mask to use 4th active group
+            "addl $8, %%edx               \n\t"
+            "paddb %%mm1, %%mm0           \n\t"
+            "cmpl _MMXLength, %%edx       \n\t"
+            "movq %%mm0, -8(%%edi,%%edx,) \n\t" // write updated Raws to array
+            "movq %%mm0, %%mm1            \n\t" // prep 1st add at top of loop
+            "jb sub_2lp                   \n\t"
+
+            : "=a" (dummy_value_a),   // 0      // output regs (dummy)
+              "=D" (dummy_value_D)    // 1
+
+            : "0" (bpp),              // eax    // input regs
+              "1" (row)               // edi
+
+            : "%edx", "%esi"                    // clobber list
+#if 0  /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */
+            , "%mm0", "%mm1", "%mm5", "%mm6", "%mm7"
+#endif
+         );
+      }
+      break;
+
+      case 8:
+      {
+         __asm__ __volatile__ (
+// preload  "movl row, %%edi              \n\t"
+            "movl _dif, %%edx             \n\t"
+            "movl %%edi, %%esi            \n\t" // lp = row
+// preload  "movl bpp, %%eax              \n\t"
+            "addl %%eax, %%edi            \n\t" // rp = row + bpp
+            "movl _MMXLength, %%ecx       \n\t"
+
+            // prime the pump:  load the first Raw(x-bpp) data set
+            "movq -8(%%edi,%%edx,), %%mm7 \n\t"
+            "andl $0x0000003f, %%ecx      \n\t" // calc bytes over mult of 64
+
+         "sub_8lp:                        \n\t"
+            "movq (%%edi,%%edx,), %%mm0   \n\t" // load Sub(x) for 1st 8 bytes
+            "paddb %%mm7, %%mm0           \n\t"
+            "movq 8(%%edi,%%edx,), %%mm1  \n\t" // load Sub(x) for 2nd 8 bytes
+            "movq %%mm0, (%%edi,%%edx,)   \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,%%edx,), %%mm2 \n\t" // load Sub(x) for 3rd 8 bytes
+            "movq %%mm1, 8(%%edi,%%edx,)  \n\t" // write Raw(x) for 2nd 8 bytes
+            "paddb %%mm1, %%mm2           \n\t"
+            "movq 24(%%edi,%%edx,), %%mm3 \n\t" // load Sub(x) for 4th 8 bytes
+            "movq %%mm2, 16(%%edi,%%edx,) \n\t" // write Raw(x) for 3rd 8 bytes
+            "paddb %%mm2, %%mm3           \n\t"
+            "movq 32(%%edi,%%edx,), %%mm4 \n\t" // load Sub(x) for 5th 8 bytes
+            "movq %%mm3, 24(%%edi,%%edx,) \n\t" // write Raw(x) for 4th 8 bytes
+            "paddb %%mm3, %%mm4           \n\t"
+            "movq 40(%%edi,%%edx,), %%mm5 \n\t" // load Sub(x) for 6th 8 bytes
+            "movq %%mm4, 32(%%edi,%%edx,) \n\t" // write Raw(x) for 5th 8 bytes
+            "paddb %%mm4, %%mm5           \n\t"
+            "movq 48(%%edi,%%edx,), %%mm6 \n\t" // load Sub(x) for 7th 8 bytes
+            "movq %%mm5, 40(%%edi,%%edx,) \n\t" // write Raw(x) for 6th 8 bytes
+            "paddb %%mm5, %%mm6           \n\t"
+            "movq 56(%%edi,%%edx,), %%mm7 \n\t" // load Sub(x) for 8th 8 bytes
+            "movq %%mm6, 48(%%edi,%%edx,) \n\t" // write Raw(x) for 7th 8 bytes
+            "addl $64, %%edx              \n\t"
+            "paddb %%mm6, %%mm7           \n\t"
+            "cmpl %%ecx, %%edx            \n\t"
+            "movq %%mm7, -8(%%edi,%%edx,) \n\t" // write Raw(x) for 8th 8 bytes
+            "jb sub_8lp                   \n\t"
+
+            "cmpl _MMXLength, %%edx       \n\t"
+            "jnb sub_8lt8                 \n\t"
+
+         "sub_8lpA:                       \n\t"
+            "movq (%%edi,%%edx,), %%mm0   \n\t"
+            "addl $8, %%edx               \n\t"
+            "paddb %%mm7, %%mm0           \n\t"
+            "cmpl _MMXLength, %%edx       \n\t"
+            "movq %%mm0, -8(%%edi,%%edx,) \n\t" // -8 to offset early addl edx
+            "movq %%mm0, %%mm7            \n\t" // move calculated Raw(x) data
+                                                //  to mm1 to be new Raw(x-bpp)
+                                                //  for next loop
+            "jb sub_8lpA                  \n\t"
+
+         "sub_8lt8:                       \n\t"
+
+            : "=a" (dummy_value_a),   // 0      // output regs (dummy)
+              "=D" (dummy_value_D)    // 1
+
+            : "0" (bpp),              // eax    // input regs
+              "1" (row)               // edi
+
+            : "%ecx", "%edx", "%esi"            // clobber list
+#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
+         );
+      }
+      break;
+
+      default:                // bpp greater than 8 bytes	GRR BOGUS
+      {
+         __asm__ __volatile__ (
+            "movl _dif, %%edx             \n\t"
+// preload  "movl row, %%edi              \n\t"
+            "movl %%edi, %%esi            \n\t" // lp = row
+// preload  "movl bpp, %%eax              \n\t"
+            "addl %%eax, %%edi            \n\t" // rp = row + bpp
+
+         "sub_Alp:                        \n\t"
+            "movq (%%edi,%%edx,), %%mm0   \n\t"
+            "movq (%%esi,%%edx,), %%mm1   \n\t"
+            "addl $8, %%edx               \n\t"
+            "paddb %%mm1, %%mm0           \n\t"
+            "cmpl _MMXLength, %%edx       \n\t"
+            "movq %%mm0, -8(%%edi,%%edx,) \n\t" // mov does not affect flags;
+                                                //  -8 to offset addl edx
+            "jb sub_Alp                   \n\t"
+
+            : "=a" (dummy_value_a),   // 0      // output regs (dummy)
+              "=D" (dummy_value_D)    // 1
+
+            : "0" (bpp),              // eax    // input regs
+              "1" (row)               // edi
+
+            : "%edx", "%esi"                    // clobber list
+#if 0  /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */
+            , "%mm0", "%mm1"
+#endif
+         );
+      }
+      break;
+
+   } // end switch (bpp)
+
+   __asm__ __volatile__ (
+      "movl _MMXLength, %%edx       \n\t"
+//pre "movl row, %%edi              \n\t"
+      "cmpl _FullLength, %%edx      \n\t"
+      "jnb sub_end                  \n\t"
+
+      "movl %%edi, %%esi            \n\t" // lp = row
+//pre "movl bpp, %%eax              \n\t"
+      "addl %%eax, %%edi            \n\t" // rp = row + bpp
+      "xorl %%eax, %%eax            \n\t"
+
+   "sub_lp2:                        \n\t"
+      "movb (%%esi,%%edx,), %%al    \n\t"
+      "addb %%al, (%%edi,%%edx,)    \n\t"
+      "incl %%edx                   \n\t"
+      "cmpl _FullLength, %%edx      \n\t"
+      "jb sub_lp2                   \n\t"
+
+   "sub_end:                        \n\t"
+      "EMMS                         \n\t" // end MMX instructions
+
+      : "=a" (dummy_value_a),   // 0      // output regs (dummy)
+        "=D" (dummy_value_D)    // 1
+
+      : "0" (bpp),              // eax    // input regs
+        "1" (row)               // edi
+
+      : "%edx", "%esi"                    // clobber list
+   );
+
+} // end of png_read_filter_row_mmx_sub()
+
+
+
+
+//===========================================================================//
+//                                                                           //
+//            P N G _ R E A D _ F I L T E R _ R O W _ M M X _ U P            //
+//                                                                           //
+//===========================================================================//
+
+// Optimized code for PNG Up filter decoder
+
+static void /* PRIVATE */
+png_read_filter_row_mmx_up(png_row_infop row_info, png_bytep row,
+                           png_bytep prev_row)
+{
+   png_uint_32 len;
+   int dummy_value_d;   // fix 'forbidden register 3 (dx) was spilled' error
+   int dummy_value_S;
+   int dummy_value_D;
+
+   len = row_info->rowbytes;              // number of bytes to filter
+
+   __asm__ __volatile__ (
+//pre "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"
+//pre "movl prev_row, %%esi         \n\t"
+      "subl %%edi, %%ecx            \n\t"
+      "jz up_go                     \n\t"
+
+   "up_lp1:                         \n\t" // fix alignment
+      "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
+      "jb up_lp1                    \n\t" //  offset incl ebx
+
+   "up_go:                          \n\t"
+//pre "movl len, %%edx              \n\t"
+      "movl %%edx, %%ecx            \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;
+      "jb up_loop                   \n\t" //  -8 to offset addl ebx
+
+      "cmpl $0, %%edx               \n\t" // test for bytes over mult of 64
+      "jz up_end                    \n\t"
+
+      "cmpl $8, %%edx               \n\t" // test for less than 8 bytes
+      "jb up_lt8                    \n\t" //  [added by lcreeve@netins.net]
+
+      "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"
+
+   "up_lpA:                         \n\t" // use MMX regs to update 8 bytes sim.
+      "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
+      "jb up_lpA                    \n\t" //  offset add ebx
+      "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
+
+   "up_lp2:                         \n\t" // use x86 regs for remaining bytes
+      "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
+      "jb up_lp2                    \n\t" //  offset inc ebx
+
+   "up_end:                         \n\t"
+      "EMMS                         \n\t" // conversion of filtered row complete
+
+      : "=d" (dummy_value_d),   // 0      // output regs (dummy)
+        "=S" (dummy_value_S),   // 1
+        "=D" (dummy_value_D)    // 2
+
+      : "0" (len),              // edx    // input regs
+        "1" (prev_row),         // esi
+        "2" (row)               // edi
+
+      : "%eax", "%ebx", "%ecx"            // clobber list (no input regs!)
+
+#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
+   );
+
+} // end of png_read_filter_row_mmx_up()
+
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */
+
+
+
+
+/*===========================================================================*/
+/*                                                                           */
+/*                   P N G _ R E A D _ F I L T E R _ R O W                   */
+/*                                                                           */
+/*===========================================================================*/
+
+#if defined(PNG_HAVE_ASSEMBLER_READ_FILTER_ROW)
+
+/* Optimized png_read_filter_row routines */
+
+void /* PRIVATE */
+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[10];
+#endif
+
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED)
+/* GRR:  these are superseded by png_ptr->asm_flags: */
+#define UseMMX_sub    1   // GRR:  converted 20000730
+#define UseMMX_up     1   // GRR:  converted 20000729
+#define UseMMX_avg    1   // GRR:  converted 20000828 (+ 16-bit bugfix 20000916)
+#define UseMMX_paeth  1   // GRR:  converted 20000828
+
+   if (_mmx_supported == 2) {
+       png_mmx_support();
+   }
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */
+
+#ifdef PNG_DEBUG
+   png_debug(1, "in png_read_filter_row (pnggccrd.c)\n");
+   switch (filter)
+   {
+      case 0: sprintf(filnm, "none");
+         break;
+      case 1: sprintf(filnm, "sub-%s", "MMX");
+         break;
+      case 2: sprintf(filnm, "up-%s", "MMX");
+         break;
+      case 3: sprintf(filnm, "avg-%s", "MMX");
+         break;
+      case 4: sprintf(filnm, "Paeth-%s", "MMX");
+         break;
+      default: sprintf(filnm, "unknw");
+         break;
+   }
+   png_debug2(0, "row_number=%5ld, %5s, ", png_ptr->row_number, filnm);
+   png_debug1(0, "row=0x%08lx, ", (unsigned long)row);
+   png_debug2(0, "pixdepth=%2d, bytes=%d, ", (int)row_info->pixel_depth,
+      (int)((row_info->pixel_depth + 7) >> 3));
+   png_debug1(0,"rowbytes=%8ld\n", row_info->rowbytes);
+#endif /* PNG_DEBUG */
+
+   switch (filter)
+   {
+      case PNG_FILTER_VALUE_NONE:
+         break;
+
+      case PNG_FILTER_VALUE_SUB:
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED)
+         if ( _mmx_supported &&
+             (row_info->pixel_depth >= PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT) &&
+             (row_info->rowbytes >= PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT))
+         {
+            png_read_filter_row_mmx_sub(row_info, row);
+         }
+         else
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */
+         {
+            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_sub */
+         break;
+
+      case PNG_FILTER_VALUE_UP:
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED)
+         if ( _mmx_supported &&
+             (row_info->pixel_depth >= PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT) &&
+             (row_info->rowbytes >= PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT))
+         {
+            png_read_filter_row_mmx_up(row_info, row, prev_row);
+         }
+          else
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */
+         {
+            png_uint_32 i;
+            png_uint_32 istop = row_info->rowbytes;
+            png_bytep rp = row;
+            png_bytep pp = prev_row;
+
+            for (i = 0; i < istop; ++i)
+            {
+               *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
+               rp++;
+            }
+         }  /* end !UseMMX_up */
+         break;
+
+      case PNG_FILTER_VALUE_AVG:
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED)
+         if ( _mmx_supported &&
+             (row_info->pixel_depth >= PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT) &&
+             (row_info->rowbytes >= PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT))
+         {
+            png_read_filter_row_mmx_avg(row_info, row, prev_row);
+         }
+         else
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */
+         {
+            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_avg */
+         break;
+
+      case PNG_FILTER_VALUE_PAETH:
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED)
+         if ( _mmx_supported &&
+             (row_info->pixel_depth >= PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT) &&
+             (row_info->rowbytes >= PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT))
+         {
+            png_read_filter_row_mmx_paeth(row_info, row, prev_row);
+         }
+         else
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */
+         {
+            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_paeth */
+         break;
+
+      default:
+         png_warning(png_ptr, "Ignoring bad row-filter type");
+         *row=0;
+         break;
+   }
+}
+
+#endif /* PNG_HAVE_ASSEMBLER_READ_FILTER_ROW */
+
+
+/*===========================================================================*/
+/*                                                                           */
+/*                      P N G _ M M X _ S U P P O R T                        */
+/*                                                                           */
+/*===========================================================================*/
+
+/* 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? (nope...sigh)]
+ */
+
+int PNGAPI
+png_mmx_support(void)
+{
+#if defined(PNG_MMX_CODE_SUPPORTED)
+    __asm__ __volatile__ (
+        "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"  // 16-bit pushf
+        "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"  // 16-bit popf
+        "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
+        "jmp  .RETURN         \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
+    ".RETURN:          \n\t"  // target label for jump instructions
+        "movl %%eax, _mmx_supported \n\t" // save in global static variable, too
+        "popl %%edx           \n\t"  // restore edx
+        "popl %%ecx           \n\t"  // restore ecx
+        "popl %%ebx           \n\t"  // restore ebx
+
+//      "ret                  \n\t"  // DONE:  no MMX support
+                                     // (fall through to standard C "ret")
+
+        :                            // output list (none)
+
+        :                            // 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)
+    );
+#else     
+    _mmx_supported = 0;
+#endif /* PNG_MMX_CODE_SUPPORTED */
+
+    return _mmx_supported;
+}
+
+#endif /* PNG_USE_PNGGCCRD */
diff --git a/Utilities/ITK/Utilities/png/pngget.c b/Utilities/ITK/Utilities/png/pngget.c
new file mode 100644
index 0000000000..208918f0c6
--- /dev/null
+++ b/Utilities/ITK/Utilities/png/pngget.c
@@ -0,0 +1,829 @@
+
+/* pngget.c - retrieval of values from info struct
+ *
+ * libpng 1.0.12 - June 8, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ */
+
+#define PNG_INTERNAL
+#include "png.h"
+
+png_uint_32 PNGAPI
+png_get_valid(png_structp png_ptr, png_infop info_ptr, png_uint_32 flag)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+      return(info_ptr->valid & flag);
+   else
+      return(0);
+}
+
+png_uint_32 PNGAPI
+png_get_rowbytes(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+      return(info_ptr->rowbytes);
+   else
+      return(0);
+}
+
+#if defined(PNG_INFO_IMAGE_SUPPORTED)
+png_bytepp PNGAPI
+png_get_rows(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+      return(info_ptr->row_pointers);
+   else
+      return(0);
+}
+#endif
+
+#ifdef PNG_EASY_ACCESS_SUPPORTED
+/* easy access to info, added in libpng-0.99 */
+png_uint_32 PNGAPI
+png_get_image_width(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+   {
+      return info_ptr->width;
+   }
+   return (0);
+}
+
+png_uint_32 PNGAPI
+png_get_image_height(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+   {
+      return info_ptr->height;
+   }
+   return (0);
+}
+
+png_byte PNGAPI
+png_get_bit_depth(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+   {
+      return info_ptr->bit_depth;
+   }
+   return (0);
+}
+
+png_byte PNGAPI
+png_get_color_type(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+   {
+      return info_ptr->color_type;
+   }
+   return (0);
+}
+
+png_byte PNGAPI
+png_get_filter_type(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+   {
+      return info_ptr->filter_type;
+   }
+   return (0);
+}
+
+png_byte PNGAPI
+png_get_interlace_type(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+   {
+      return info_ptr->interlace_type;
+   }
+   return (0);
+}
+
+png_byte PNGAPI
+png_get_compression_type(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+   {
+      return info_ptr->compression_type;
+   }
+   return (0);
+}
+
+png_uint_32 PNGAPI
+png_get_x_pixels_per_meter(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+#if defined(PNG_pHYs_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_pHYs)
+   {
+      png_debug1(1, "in %s retrieval function\n", "png_get_x_pixels_per_meter");
+      if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER)
+          return (0);
+      else return (info_ptr->x_pixels_per_unit);
+   }
+#else
+   return (0);
+#endif
+   return (0);
+}
+
+png_uint_32 PNGAPI
+png_get_y_pixels_per_meter(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+#if defined(PNG_pHYs_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_pHYs)
+   {
+      png_debug1(1, "in %s retrieval function\n", "png_get_y_pixels_per_meter");
+      if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER)
+          return (0);
+      else return (info_ptr->y_pixels_per_unit);
+   }
+#else
+   return (0);
+#endif
+   return (0);
+}
+
+png_uint_32 PNGAPI
+png_get_pixels_per_meter(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+#if defined(PNG_pHYs_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_pHYs)
+   {
+      png_debug1(1, "in %s retrieval function\n", "png_get_pixels_per_meter");
+      if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER ||
+         info_ptr->x_pixels_per_unit != info_ptr->y_pixels_per_unit)
+          return (0);
+      else return (info_ptr->x_pixels_per_unit);
+   }
+#else
+   return (0);
+#endif
+   return (0);
+}
+
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+float PNGAPI
+png_get_pixel_aspect_ratio(png_structp png_ptr, png_infop info_ptr)
+   {
+   if (png_ptr != NULL && info_ptr != NULL)
+#if defined(PNG_pHYs_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_pHYs)
+   {
+      png_debug1(1, "in %s retrieval function\n", "png_get_aspect_ratio");
+      if (info_ptr->x_pixels_per_unit == 0)
+         return ((float)0.0);
+      else
+         return ((float)((float)info_ptr->y_pixels_per_unit
+            /(float)info_ptr->x_pixels_per_unit));
+   }
+#else
+   return (0.0);
+#endif
+   return ((float)0.0);
+}
+#endif
+
+png_int_32 PNGAPI
+png_get_x_offset_microns(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+#if defined(PNG_oFFs_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_oFFs)
+   {
+      png_debug1(1, "in %s retrieval function\n", "png_get_x_offset_microns");
+      if(info_ptr->offset_unit_type != PNG_OFFSET_MICROMETER)
+          return (0);
+      else return (info_ptr->x_offset);
+   }
+#else
+   return (0);
+#endif
+   return (0);
+}
+
+png_int_32 PNGAPI
+png_get_y_offset_microns(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+#if defined(PNG_oFFs_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_oFFs)
+   {
+      png_debug1(1, "in %s retrieval function\n", "png_get_y_offset_microns");
+      if(info_ptr->offset_unit_type != PNG_OFFSET_MICROMETER)
+          return (0);
+      else return (info_ptr->y_offset);
+   }
+#else
+   return (0);
+#endif
+   return (0);
+}
+
+png_int_32 PNGAPI
+png_get_x_offset_pixels(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+#if defined(PNG_oFFs_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_oFFs)
+   {
+      png_debug1(1, "in %s retrieval function\n", "png_get_x_offset_microns");
+      if(info_ptr->offset_unit_type != PNG_OFFSET_PIXEL)
+          return (0);
+      else return (info_ptr->x_offset);
+   }
+#else
+   return (0);
+#endif
+   return (0);
+}
+
+png_int_32 PNGAPI
+png_get_y_offset_pixels(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+#if defined(PNG_oFFs_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_oFFs)
+   {
+      png_debug1(1, "in %s retrieval function\n", "png_get_y_offset_microns");
+      if(info_ptr->offset_unit_type != PNG_OFFSET_PIXEL)
+          return (0);
+      else return (info_ptr->y_offset);
+   }
+#else
+   return (0);
+#endif
+   return (0);
+}
+
+#if defined(PNG_INCH_CONVERSIONS) && defined(PNG_FLOATING_POINT_SUPPORTED)
+png_uint_32 PNGAPI
+png_get_pixels_per_inch(png_structp png_ptr, png_infop info_ptr)
+{
+   return ((png_uint_32)((float)png_get_pixels_per_meter(png_ptr, info_ptr)
+     *.0254 +.5));
+}
+
+png_uint_32 PNGAPI
+png_get_x_pixels_per_inch(png_structp png_ptr, png_infop info_ptr)
+{
+   return ((png_uint_32)((float)png_get_x_pixels_per_meter(png_ptr, info_ptr)
+     *.0254 +.5));
+}
+
+png_uint_32 PNGAPI
+png_get_y_pixels_per_inch(png_structp png_ptr, png_infop info_ptr)
+{
+   return ((png_uint_32)((float)png_get_y_pixels_per_meter(png_ptr, info_ptr)
+     *.0254 +.5));
+}
+
+float PNGAPI
+png_get_x_offset_inches(png_structp png_ptr, png_infop info_ptr)
+{
+   return ((float)png_get_x_offset_microns(png_ptr, info_ptr)
+     *.00003937);
+}
+
+float PNGAPI
+png_get_y_offset_inches(png_structp png_ptr, png_infop info_ptr)
+{
+   return ((float)png_get_y_offset_microns(png_ptr, info_ptr)
+     *.00003937);
+}
+
+#if defined(PNG_pHYs_SUPPORTED)
+png_uint_32 PNGAPI
+png_get_pHYs_dpi(png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)
+{
+   png_uint_32 retval = 0;
+
+   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)
+      {
+         *res_x = info_ptr->x_pixels_per_unit;
+         retval |= PNG_INFO_pHYs;
+      }
+      if (res_y != NULL)
+      {
+         *res_y = info_ptr->y_pixels_per_unit;
+         retval |= PNG_INFO_pHYs;
+      }
+      if (unit_type != NULL)
+      {
+         *unit_type = (int)info_ptr->phys_unit_type;
+         retval |= PNG_INFO_pHYs;
+         if(*unit_type == 1)
+         {
+            if (res_x != NULL) *res_x = (png_uint_32)(*res_x * .0254 + .50);
+            if (res_y != NULL) *res_y = (png_uint_32)(*res_y * .0254 + .50);
+         }
+      }
+   }
+   return (retval);
+}
+#endif /* PNG_pHYs_SUPPORTED */
+#endif  /* PNG_INCH_CONVERSIONS && PNG_FLOATING_POINT_SUPPORTED */
+
+/* png_get_channels really belongs in here, too, but it's been around longer */
+
+#endif  /* PNG_EASY_ACCESS_SUPPORTED */
+
+png_byte PNGAPI
+png_get_channels(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+      return(info_ptr->channels);
+   else
+      return (0);
+}
+
+png_bytep PNGAPI
+png_get_signature(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+      return(info_ptr->signature);
+   else
+      return (NULL);
+}
+
+#if defined(PNG_bKGD_SUPPORTED)
+png_uint_32 PNGAPI
+png_get_bKGD(png_structp png_ptr, png_infop info_ptr,
+   png_color_16p *background)
+{
+   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD)
+      && background != NULL)
+   {
+      png_debug1(1, "in %s retrieval function\n", "bKGD");
+      *background = &(info_ptr->background);
+      return (PNG_INFO_bKGD);
+   }
+   return (0);
+}
+#endif
+
+#if defined(PNG_cHRM_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+png_uint_32 PNGAPI
+png_get_cHRM(png_structp png_ptr, png_infop info_ptr,
+   double *white_x, double *white_y, double *red_x, double *red_y,
+   double *green_x, double *green_y, double *blue_x, double *blue_y)
+{
+   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
+   {
+      png_debug1(1, "in %s retrieval function\n", "cHRM");
+      if (white_x != NULL)
+         *white_x = (double)info_ptr->x_white;
+      if (white_y != NULL)
+         *white_y = (double)info_ptr->y_white;
+      if (red_x != NULL)
+         *red_x = (double)info_ptr->x_red;
+      if (red_y != NULL)
+         *red_y = (double)info_ptr->y_red;
+      if (green_x != NULL)
+         *green_x = (double)info_ptr->x_green;
+      if (green_y != NULL)
+         *green_y = (double)info_ptr->y_green;
+      if (blue_x != NULL)
+         *blue_x = (double)info_ptr->x_blue;
+      if (blue_y != NULL)
+         *blue_y = (double)info_ptr->y_blue;
+      return (PNG_INFO_cHRM);
+   }
+   return (0);
+}
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+png_uint_32 PNGAPI
+png_get_cHRM_fixed(png_structp png_ptr, png_infop info_ptr,
+   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))
+   {
+      png_debug1(1, "in %s retrieval function\n", "cHRM");
+      if (white_x != NULL)
+         *white_x = info_ptr->int_x_white;
+      if (white_y != NULL)
+         *white_y = info_ptr->int_y_white;
+      if (red_x != NULL)
+         *red_x = info_ptr->int_x_red;
+      if (red_y != NULL)
+         *red_y = info_ptr->int_y_red;
+      if (green_x != NULL)
+         *green_x = info_ptr->int_x_green;
+      if (green_y != NULL)
+         *green_y = info_ptr->int_y_green;
+      if (blue_x != NULL)
+         *blue_x = info_ptr->int_x_blue;
+      if (blue_y != NULL)
+         *blue_y = info_ptr->int_y_blue;
+      return (PNG_INFO_cHRM);
+   }
+   return (0);
+}
+#endif
+#endif
+
+#if defined(PNG_gAMA_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+png_uint_32 PNGAPI
+png_get_gAMA(png_structp png_ptr, png_infop info_ptr, double *file_gamma)
+{
+   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
+      && file_gamma != NULL)
+   {
+      png_debug1(1, "in %s retrieval function\n", "gAMA");
+      *file_gamma = (double)info_ptr->gamma;
+      return (PNG_INFO_gAMA);
+   }
+   return (0);
+}
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+png_uint_32 PNGAPI
+png_get_gAMA_fixed(png_structp png_ptr, png_infop info_ptr,
+    png_fixed_point *int_file_gamma)
+{
+   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
+      && int_file_gamma != NULL)
+   {
+      png_debug1(1, "in %s retrieval function\n", "gAMA");
+      *int_file_gamma = info_ptr->int_gamma;
+      return (PNG_INFO_gAMA);
+   }
+   return (0);
+}
+#endif
+#endif
+
+#if defined(PNG_sRGB_SUPPORTED)
+png_uint_32 PNGAPI
+png_get_sRGB(png_structp png_ptr, png_infop info_ptr, int *file_srgb_intent)
+{
+   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)
+      && file_srgb_intent != NULL)
+   {
+      png_debug1(1, "in %s retrieval function\n", "sRGB");
+      *file_srgb_intent = (int)info_ptr->srgb_intent;
+      return (PNG_INFO_sRGB);
+   }
+   return (0);
+}
+#endif
+
+#if defined(PNG_iCCP_SUPPORTED)
+png_uint_32 PNGAPI
+png_get_iCCP(png_structp png_ptr, png_infop info_ptr,
+             png_charpp name, int *compression_type,
+             png_charpp profile, png_uint_32 *proflen)
+{
+   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP)
+      && name != NULL && profile != NULL && proflen != NULL)
+   {
+      png_debug1(1, "in %s retrieval function\n", "iCCP");
+      *name = info_ptr->iccp_name;
+      *profile = info_ptr->iccp_profile;
+      /* compression_type is a dummy so the API won't have to change
+         if we introduce multiple compression types later. */
+      *proflen = (int)info_ptr->iccp_proflen;
+      *compression_type = (int)info_ptr->iccp_compression;
+      return (PNG_INFO_iCCP);
+   }
+   return (0);
+}
+#endif
+
+#if defined(PNG_sPLT_SUPPORTED)
+png_uint_32 PNGAPI
+png_get_sPLT(png_structp png_ptr, png_infop info_ptr,
+             png_sPLT_tpp spalettes)
+{
+   if (png_ptr != NULL && info_ptr != NULL && spalettes != NULL)
+     *spalettes = info_ptr->splt_palettes;
+   return ((png_uint_32)info_ptr->splt_palettes_num);
+}
+#endif
+
+#if defined(PNG_hIST_SUPPORTED)
+png_uint_32 PNGAPI
+png_get_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p *hist)
+{
+   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST)
+      && hist != NULL)
+   {
+      png_debug1(1, "in %s retrieval function\n", "hIST");
+      *hist = info_ptr->hist;
+      return (PNG_INFO_hIST);
+   }
+   return (0);
+}
+#endif
+
+png_uint_32 PNGAPI
+png_get_IHDR(png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 *width, png_uint_32 *height, int *bit_depth,
+   int *color_type, int *interlace_type, int *compression_type,
+   int *filter_type)
+
+{
+   if (png_ptr != NULL && info_ptr != NULL && width != NULL && height != NULL &&
+      bit_depth != NULL && color_type != NULL)
+   {
+      int pixel_depth, channels;
+      png_uint_32 rowbytes_per_pixel;
+
+      png_debug1(1, "in %s retrieval function\n", "IHDR");
+      *width = info_ptr->width;
+      *height = info_ptr->height;
+      *bit_depth = info_ptr->bit_depth;
+      *color_type = info_ptr->color_type;
+      if (compression_type != NULL)
+         *compression_type = info_ptr->compression_type;
+      if (filter_type != NULL)
+         *filter_type = info_ptr->filter_type;
+      if (interlace_type != NULL)
+         *interlace_type = info_ptr->interlace_type;
+
+      /* check for potential overflow of rowbytes */
+      if (*color_type == PNG_COLOR_TYPE_PALETTE)
+         channels = 1;
+      else if (*color_type & PNG_COLOR_MASK_COLOR)
+         channels = 3;
+      else
+         channels = 1;
+      if (*color_type & PNG_COLOR_MASK_ALPHA)
+         channels++;
+      pixel_depth = *bit_depth * channels;
+      rowbytes_per_pixel = (pixel_depth + 7) >> 3;
+      if ((*width > PNG_MAX_UINT/rowbytes_per_pixel))
+      {
+         png_warning(png_ptr,
+            "Width too large for libpng to process image data.");
+      }
+      return (1);
+   }
+   return (0);
+}
+
+#if defined(PNG_oFFs_SUPPORTED)
+png_uint_32 PNGAPI
+png_get_oFFs(png_structp png_ptr, png_infop info_ptr,
+   png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type)
+{
+   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)
+      && offset_x != NULL && offset_y != NULL && unit_type != NULL)
+   {
+      png_debug1(1, "in %s retrieval function\n", "oFFs");
+      *offset_x = info_ptr->x_offset;
+      *offset_y = info_ptr->y_offset;
+      *unit_type = (int)info_ptr->offset_unit_type;
+      return (PNG_INFO_oFFs);
+   }
+   return (0);
+}
+#endif
+
+#if defined(PNG_pCAL_SUPPORTED)
+png_uint_32 PNGAPI
+png_get_pCAL(png_structp png_ptr, png_infop info_ptr,
+   png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type, int *nparams,
+   png_charp *units, png_charpp *params)
+{
+   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");
+      *purpose = info_ptr->pcal_purpose;
+      *X0 = info_ptr->pcal_X0;
+      *X1 = info_ptr->pcal_X1;
+      *type = (int)info_ptr->pcal_type;
+      *nparams = (int)info_ptr->pcal_nparams;
+      *units = info_ptr->pcal_units;
+      *params = info_ptr->pcal_params;
+      return (PNG_INFO_pCAL);
+   }
+   return (0);
+}
+#endif
+
+#if defined(PNG_sCAL_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+png_uint_32 PNGAPI
+png_get_sCAL(png_structp png_ptr, png_infop info_ptr,
+             int *unit, double *width, double *height)
+{
+    if (png_ptr != NULL && info_ptr != NULL &&
+       (info_ptr->valid & PNG_INFO_sCAL))
+    {
+        *unit = info_ptr->scal_unit;
+        *width = info_ptr->scal_pixel_width;
+        *height = info_ptr->scal_pixel_height;
+        return (PNG_INFO_sCAL);
+    }
+    return(0);
+}
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+png_uint_32 PNGAPI
+png_get_sCAL_s(png_structp png_ptr, png_infop info_ptr,
+             int *unit, png_charpp width, png_charpp height)
+{
+    if (png_ptr != NULL && info_ptr != NULL &&
+       (info_ptr->valid & PNG_INFO_sCAL))
+    {
+        *unit = info_ptr->scal_unit;
+        *width = info_ptr->scal_s_width;
+        *height = info_ptr->scal_s_height;
+        return (PNG_INFO_sCAL);
+    }
+    return(0);
+}
+#endif
+#endif
+#endif
+
+#if defined(PNG_pHYs_SUPPORTED)
+png_uint_32 PNGAPI
+png_get_pHYs(png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)
+{
+   png_uint_32 retval = 0;
+
+   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)
+      {
+         *res_x = info_ptr->x_pixels_per_unit;
+         retval |= PNG_INFO_pHYs;
+      }
+      if (res_y != NULL)
+      {
+         *res_y = info_ptr->y_pixels_per_unit;
+         retval |= PNG_INFO_pHYs;
+      }
+      if (unit_type != NULL)
+      {
+         *unit_type = (int)info_ptr->phys_unit_type;
+         retval |= PNG_INFO_pHYs;
+      }
+   }
+   return (retval);
+}
+#endif
+
+png_uint_32 PNGAPI
+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)
+   {
+      png_debug1(1, "in %s retrieval function\n", "PLTE");
+      *palette = info_ptr->palette;
+      *num_palette = info_ptr->num_palette;
+      png_debug1(3, "num_palette = %d\n", *num_palette);
+      return (PNG_INFO_PLTE);
+   }
+   return (0);
+}
+
+#if defined(PNG_sBIT_SUPPORTED)
+png_uint_32 PNGAPI
+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)
+   {
+      png_debug1(1, "in %s retrieval function\n", "sBIT");
+      *sig_bit = &(info_ptr->sig_bit);
+      return (PNG_INFO_sBIT);
+   }
+   return (0);
+}
+#endif
+
+#if defined(PNG_TEXT_SUPPORTED)
+png_uint_32 PNGAPI
+png_get_text(png_structp png_ptr, png_infop info_ptr, png_textp *text_ptr,
+   int *num_text)
+{
+   if (png_ptr != NULL && info_ptr != NULL && info_ptr->num_text > 0)
+   {
+      png_debug1(1, "in %s retrieval function\n",
+         (png_ptr->chunk_name[0] == '\0' ? "text"
+             : (png_const_charp)png_ptr->chunk_name));
+      if (text_ptr != NULL)
+         *text_ptr = info_ptr->text;
+      if (num_text != NULL)
+         *num_text = info_ptr->num_text;
+      return ((png_uint_32)info_ptr->num_text);
+   }
+   if (num_text != NULL)
+     *num_text = 0;
+   return(0);
+}
+#endif
+
+#if defined(PNG_tIME_SUPPORTED)
+png_uint_32 PNGAPI
+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)
+   {
+      png_debug1(1, "in %s retrieval function\n", "tIME");
+      *mod_time = &(info_ptr->mod_time);
+      return (PNG_INFO_tIME);
+   }
+   return (0);
+}
+#endif
+
+#if defined(PNG_tRNS_SUPPORTED)
+png_uint_32 PNGAPI
+png_get_tRNS(png_structp png_ptr, png_infop info_ptr,
+   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))
+   {
+      png_debug1(1, "in %s retrieval function\n", "tRNS");
+      if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+      {
+          if (trans != NULL)
+          {
+             *trans = info_ptr->trans;
+             retval |= PNG_INFO_tRNS;
+          }
+          if (trans_values != NULL)
+             *trans_values = &(info_ptr->trans_values);
+      }
+      else /* if (info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) */
+      {
+          if (trans_values != NULL)
+          {
+             *trans_values = &(info_ptr->trans_values);
+             retval |= PNG_INFO_tRNS;
+          }
+          if(trans != NULL)
+             *trans = NULL;
+      }
+      if(num_trans != NULL)
+      {
+         *num_trans = info_ptr->num_trans;
+         retval |= PNG_INFO_tRNS;
+      }
+   }
+   return (retval);
+}
+#endif
+
+#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+png_uint_32 PNGAPI
+png_get_unknown_chunks(png_structp png_ptr, png_infop info_ptr,
+             png_unknown_chunkpp unknowns)
+{
+   if (png_ptr != NULL && info_ptr != NULL && unknowns != NULL)
+     *unknowns = info_ptr->unknown_chunks;
+   return ((png_uint_32)info_ptr->unknown_chunks_num);
+}
+#endif
+
+#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+png_byte PNGAPI
+png_get_rgb_to_gray_status (png_structp png_ptr)
+{
+   return (png_byte)(png_ptr? png_ptr->rgb_to_gray_status : 0);
+}
+#endif
+
+#if defined(PNG_USER_CHUNKS_SUPPORTED)
+png_voidp PNGAPI
+png_get_user_chunk_ptr(png_structp png_ptr)
+{
+   return (png_ptr? png_ptr->user_chunk_ptr : NULL);
+}
+#endif
+
+
+png_uint_32 PNGAPI
+png_get_compression_buffer_size(png_structp png_ptr)
+{
+   return (png_uint_32)(png_ptr? png_ptr->zbuf_size : 0L);
+}
+
+
diff --git a/Utilities/ITK/Utilities/png/pngmem.c b/Utilities/ITK/Utilities/png/pngmem.c
new file mode 100644
index 0000000000..dd74715eb3
--- /dev/null
+++ b/Utilities/ITK/Utilities/png/pngmem.c
@@ -0,0 +1,531 @@
+
+/* pngmem.c - stub functions for memory allocation
+ *
+ * libpng 1.0.12 - June 8, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This file provides a location for all memory allocation.  Users who
+ * need special memory handling are expected to supply replacement
+ * functions for png_malloc() and png_free(), and to use
+ * png_create_read_struct_2() and png_create_write_struct_2() to
+ * identify the replacement functions.
+ */
+
+#define PNG_INTERNAL
+#include "png.h"
+
+/* Borland DOS special memory handler */
+#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
+/* if you change this, be sure to change the one in png.h also */
+
+/* Allocate memory for a png_struct.  The malloc and memset can be replaced
+   by a single call to calloc() if this is thought to improve performance. */
+png_voidp /* PRIVATE */
+png_create_struct(int type)
+{
+#ifdef PNG_USER_MEM_SUPPORTED
+   return (png_create_struct_2(type, NULL, NULL));
+}
+
+/* Alternate version of png_create_struct, for use with user-defined malloc. */
+png_voidp /* PRIVATE */
+png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr)
+{
+#endif /* PNG_USER_MEM_SUPPORTED */
+   png_size_t size;
+   png_voidp struct_ptr;
+
+   if (type == PNG_STRUCT_INFO)
+     size = sizeof(png_info);
+   else if (type == PNG_STRUCT_PNG)
+     size = sizeof(png_struct);
+   else
+     return ((png_voidp)NULL);
+
+#ifdef PNG_USER_MEM_SUPPORTED
+   if(malloc_fn != NULL)
+   {
+      if (mem_ptr != NULL)
+      {
+         png_struct dummy_struct;
+         png_structp png_ptr = &dummy_struct;
+         png_ptr->mem_ptr=mem_ptr;
+         struct_ptr = (*(malloc_fn))(png_ptr, size);
+      }
+      else
+         struct_ptr = (*(malloc_fn))(NULL, size);
+      if (struct_ptr != NULL)
+         png_memset(struct_ptr, 0, size);
+      return (struct_ptr);
+   }
+#endif /* PNG_USER_MEM_SUPPORTED */
+   if ((struct_ptr = (png_voidp)farmalloc(size)) != NULL)
+   {
+      png_memset(struct_ptr, 0, size);
+   }
+   return (struct_ptr);
+}
+
+
+/* Free memory allocated by a png_create_struct() call */
+void /* PRIVATE */
+png_destroy_struct(png_voidp struct_ptr)
+{
+#ifdef PNG_USER_MEM_SUPPORTED
+   png_destroy_struct_2(struct_ptr, (png_free_ptr)NULL, (png_voidp)NULL);
+}
+
+/* Free memory allocated by a png_create_struct() call */
+void /* PRIVATE */
+png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
+    png_voidp mem_ptr)
+{
+#endif
+   if (struct_ptr != NULL)
+   {
+#ifdef PNG_USER_MEM_SUPPORTED
+      if(free_fn != NULL)
+      {
+         png_struct dummy_struct;
+         png_structp png_ptr = &dummy_struct;
+         png_ptr->mem_ptr=mem_ptr;
+         (*(free_fn))(png_ptr, struct_ptr);
+         return;
+      }
+#endif /* PNG_USER_MEM_SUPPORTED */
+      farfree (struct_ptr);
+   }
+}
+
+/* Allocate memory.  For reasonable files, size should never exceed
+ * 64K.  However, zlib may allocate more then 64K if you don't tell
+ * it not to.  See zconf.h and png.h for more information. zlib does
+ * need to allocate exactly 64K, so whatever you call here must
+ * have the ability to do that.
+ *
+ * Borland seems to have a problem in DOS mode for exactly 64K.
+ * It gives you a segment with an offset of 8 (perhaps to store its
+ * memory stuff).  zlib doesn't like this at all, so we have to
+ * detect and deal with it.  This code should not be needed in
+ * Windows or OS/2 modes, and only in 16 bit mode.  This code has
+ * been updated by Alexander Lehmann for version 0.89 to waste less
+ * memory.
+ *
+ * Note that we can't use png_size_t for the "size" declaration,
+ * since on some systems a png_size_t is a 16-bit quantity, and as a
+ * result, we would be truncating potentially larger memory requests
+ * (which should cause a fatal error) and introducing major problems.
+ */
+png_voidp PNGAPI
+png_malloc(png_structp png_ptr, png_uint_32 size)
+{
+#ifndef PNG_USER_MEM_SUPPORTED
+   png_voidp ret;
+#endif
+   if (png_ptr == NULL || size == 0)
+      return ((png_voidp)NULL);
+
+#ifdef PNG_USER_MEM_SUPPORTED
+   if(png_ptr->malloc_fn != NULL)
+   {
+       ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, size));
+       if (ret == NULL)
+          png_error(png_ptr, "Out of memory!");
+       return (ret);
+   }
+   else
+       return png_malloc_default(png_ptr, size);
+}
+
+png_voidp PNGAPI
+png_malloc_default(png_structp png_ptr, png_uint_32 size)
+{
+   png_voidp ret;
+#endif /* PNG_USER_MEM_SUPPORTED */
+
+#ifdef PNG_MAX_MALLOC_64K
+   if (size > (png_uint_32)65536L)
+      png_error(png_ptr, "Cannot Allocate > 64K");
+#endif
+
+   if (size == (png_uint_32)65536L)
+   {
+      if (png_ptr->offset_table == NULL)
+      {
+         /* try to see if we need to do any of this fancy stuff */
+         ret = farmalloc(size);
+         if (ret == NULL || ((png_size_t)ret & 0xffff))
+         {
+            int num_blocks;
+            png_uint_32 total_size;
+            png_bytep table;
+            int i;
+            png_byte huge * hptr;
+
+            if (ret != NULL)
+            {
+               farfree(ret);
+               ret = NULL;
+            }
+
+            if(png_ptr->zlib_window_bits > 14)
+               num_blocks = (int)(1 << (png_ptr->zlib_window_bits - 14));
+            else
+               num_blocks = 1;
+            if (png_ptr->zlib_mem_level >= 7)
+               num_blocks += (int)(1 << (png_ptr->zlib_mem_level - 7));
+            else
+               num_blocks++;
+
+            total_size = ((png_uint_32)65536L) * (png_uint_32)num_blocks+16;
+
+            table = farmalloc(total_size);
+
+            if (table == NULL)
+            {
+               png_error(png_ptr, "Out Of Memory."); /* Note "O" and "M" */
+            }
+
+            if ((png_size_t)table & 0xfff0)
+            {
+               png_error(png_ptr, "Farmalloc didn't return normalized pointer");
+            }
+
+            png_ptr->offset_table = table;
+            png_ptr->offset_table_ptr = farmalloc(num_blocks *
+               sizeof (png_bytep));
+
+            if (png_ptr->offset_table_ptr == NULL)
+            {
+               png_error(png_ptr, "Out Of memory.");
+            }
+
+            hptr = (png_byte huge *)table;
+            if ((png_size_t)hptr & 0xf)
+            {
+               hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L);
+               hptr = hptr + 16L;  /* "hptr += 16L" fails on Turbo C++ 3.0 */
+            }
+            for (i = 0; i < num_blocks; i++)
+            {
+               png_ptr->offset_table_ptr[i] = (png_bytep)hptr;
+               hptr = hptr + (png_uint_32)65536L;  /* "+=" fails on TC++3.0 */
+            }
+
+            png_ptr->offset_table_number = num_blocks;
+            png_ptr->offset_table_count = 0;
+            png_ptr->offset_table_count_free = 0;
+         }
+      }
+
+      if (png_ptr->offset_table_count >= png_ptr->offset_table_number)
+         png_error(png_ptr, "Out of Memory.");
+
+      ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++];
+   }
+   else
+      ret = farmalloc(size);
+
+   if (ret == NULL)
+   {
+      png_error(png_ptr, "Out of memory."); /* Note "o" and "m" */
+   }
+
+   return (ret);
+}
+
+/* free a pointer allocated by png_malloc().  In the default
+   configuration, png_ptr is not used, but is passed in case it
+   is needed.  If ptr is NULL, return without taking any action. */
+void PNGAPI
+png_free(png_structp png_ptr, png_voidp ptr)
+{
+   if (png_ptr == NULL || ptr == NULL)
+      return;
+
+#ifdef PNG_USER_MEM_SUPPORTED
+   if (png_ptr->free_fn != NULL)
+   {
+      (*(png_ptr->free_fn))(png_ptr, ptr);
+      return;
+   }
+   else png_free_default(png_ptr, ptr);
+}
+
+void PNGAPI
+png_free_default(png_structp png_ptr, png_voidp ptr)
+{
+#endif /* PNG_USER_MEM_SUPPORTED */
+
+   if (png_ptr->offset_table != NULL)
+   {
+      int i;
+
+      for (i = 0; i < png_ptr->offset_table_count; i++)
+      {
+         if (ptr == png_ptr->offset_table_ptr[i])
+         {
+            ptr = NULL;
+            png_ptr->offset_table_count_free++;
+            break;
+         }
+      }
+      if (png_ptr->offset_table_count_free == png_ptr->offset_table_count)
+      {
+         farfree(png_ptr->offset_table);
+         farfree(png_ptr->offset_table_ptr);
+         png_ptr->offset_table = NULL;
+         png_ptr->offset_table_ptr = NULL;
+      }
+   }
+
+   if (ptr != NULL)
+   {
+      farfree(ptr);
+   }
+}
+
+#else /* Not the Borland DOS special memory handler */
+
+/* Allocate memory for a png_struct or a png_info.  The malloc and
+   memset can be replaced by a single call to calloc() if this is thought
+   to improve performance noticably.*/
+png_voidp /* PRIVATE */
+png_create_struct(int type)
+{
+#ifdef PNG_USER_MEM_SUPPORTED
+   return (png_create_struct_2(type, NULL, NULL));
+}
+
+/* Allocate memory for a png_struct or a png_info.  The malloc and
+   memset can be replaced by a single call to calloc() if this is thought
+   to improve performance noticably.*/
+png_voidp /* PRIVATE */
+png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr)
+{
+#endif /* PNG_USER_MEM_SUPPORTED */
+   png_size_t size;
+   png_voidp struct_ptr;
+
+   if (type == PNG_STRUCT_INFO)
+      size = sizeof(png_info);
+   else if (type == PNG_STRUCT_PNG)
+      size = sizeof(png_struct);
+   else
+      return ((png_voidp)NULL);
+
+#ifdef PNG_USER_MEM_SUPPORTED
+   if(malloc_fn != NULL)
+   {
+      if (mem_ptr != NULL)
+      {
+         png_struct dummy_struct;
+         png_structp png_ptr = &dummy_struct;
+         png_ptr->mem_ptr=mem_ptr;
+         struct_ptr = (*(malloc_fn))(png_ptr, size);
+      }
+      else
+         struct_ptr = (*(malloc_fn))(NULL, size);
+      if (struct_ptr != NULL)
+         png_memset(struct_ptr, 0, size);
+      return (struct_ptr);
+   }
+#endif /* PNG_USER_MEM_SUPPORTED */
+
+#if defined(__TURBOC__) && !defined(__FLAT__)
+   if ((struct_ptr = (png_voidp)farmalloc(size)) != NULL)
+#else
+# if defined(_MSC_VER) && defined(MAXSEG_64K)
+   if ((struct_ptr = (png_voidp)halloc(size,1)) != NULL)
+# else
+   if ((struct_ptr = (png_voidp)malloc(size)) != NULL)
+# endif
+#endif
+   {
+      png_memset(struct_ptr, 0, size);
+   }
+
+   return (struct_ptr);
+}
+
+
+/* Free memory allocated by a png_create_struct() call */
+void /* PRIVATE */
+png_destroy_struct(png_voidp struct_ptr)
+{
+#ifdef PNG_USER_MEM_SUPPORTED
+   png_destroy_struct_2(struct_ptr, (png_free_ptr)NULL, (png_voidp)NULL);
+}
+
+/* Free memory allocated by a png_create_struct() call */
+void /* PRIVATE */
+png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
+    png_voidp mem_ptr)
+{
+#endif /* PNG_USER_MEM_SUPPORTED */
+   if (struct_ptr != NULL)
+   {
+#ifdef PNG_USER_MEM_SUPPORTED
+      if(free_fn != NULL)
+      {
+         png_struct dummy_struct;
+         png_structp png_ptr = &dummy_struct;
+         png_ptr->mem_ptr=mem_ptr;
+         (*(free_fn))(png_ptr, struct_ptr);
+         return;
+      }
+#endif /* PNG_USER_MEM_SUPPORTED */
+#if defined(__TURBOC__) && !defined(__FLAT__)
+      farfree(struct_ptr);
+#else
+# if defined(_MSC_VER) && defined(MAXSEG_64K)
+      hfree(struct_ptr);
+# else
+      free(struct_ptr);
+# endif
+#endif
+   }
+}
+
+
+/* Allocate memory.  For reasonable files, size should never exceed
+   64K.  However, zlib may allocate more then 64K if you don't tell
+   it not to.  See zconf.h and png.h for more information.  zlib does
+   need to allocate exactly 64K, so whatever you call here must
+   have the ability to do that. */
+
+png_voidp PNGAPI
+png_malloc(png_structp png_ptr, png_uint_32 size)
+{
+   png_voidp ret;
+   if (png_ptr == NULL || size == 0)
+      return ((png_voidp)NULL);
+
+#ifdef PNG_USER_MEM_SUPPORTED
+   if(png_ptr->malloc_fn != NULL)
+   {
+       ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, size));
+       if (ret == NULL)
+          png_error(png_ptr, "Out of Memory!");
+       return (ret);
+   }
+   else
+       return (png_malloc_default(png_ptr, size));
+}
+png_voidp /* PRIVATE */
+png_malloc_default(png_structp png_ptr, png_uint_32 size)
+{
+   png_voidp ret;
+#endif /* PNG_USER_MEM_SUPPORTED */
+
+#ifdef PNG_MAX_MALLOC_64K
+   if (size > (png_uint_32)65536L)
+      png_error(png_ptr, "Cannot Allocate > 64K");
+#endif
+
+#if defined(__TURBOC__) && !defined(__FLAT__)
+   ret = farmalloc(size);
+#else
+# if defined(_MSC_VER) && defined(MAXSEG_64K)
+   ret = halloc(size, 1);
+# else
+   ret = malloc((size_t)size);
+# endif
+#endif
+
+   if (ret == NULL)
+      png_error(png_ptr, "Out of Memory");
+
+   return (ret);
+}
+
+/* Free a pointer allocated by png_malloc().  If ptr is NULL, return
+   without taking any action. */
+void PNGAPI
+png_free(png_structp png_ptr, png_voidp ptr)
+{
+   if (png_ptr == NULL || ptr == NULL)
+      return;
+
+#ifdef PNG_USER_MEM_SUPPORTED
+   if (png_ptr->free_fn != NULL)
+   {
+      (*(png_ptr->free_fn))(png_ptr, ptr);
+      return;
+   }
+   else png_free_default(png_ptr, ptr);
+}
+void /* PRIVATE */
+png_free_default(png_structp png_ptr, png_voidp ptr)
+{
+   if (png_ptr == NULL || ptr == NULL)
+      return;
+
+#endif /* PNG_USER_MEM_SUPPORTED */
+
+#if defined(__TURBOC__) && !defined(__FLAT__)
+   farfree(ptr);
+#else
+# if defined(_MSC_VER) && defined(MAXSEG_64K)
+   hfree(ptr);
+# else
+   free(ptr);
+# endif
+#endif
+}
+
+#endif /* Not Borland DOS special memory handler */
+
+png_voidp /* PRIVATE */
+png_memcpy_check (png_structp png_ptr, png_voidp s1, png_voidp s2,
+   png_uint_32 length)
+{
+   png_size_t size;
+
+   size = (png_size_t)length;
+   if ((png_uint_32)size != length)
+      png_error(png_ptr,"Overflow in png_memcpy_check.");
+
+   return(png_memcpy (s1, s2, size));
+}
+
+png_voidp /* PRIVATE */
+png_memset_check (png_structp png_ptr, png_voidp s1, int value,
+   png_uint_32 length)
+{
+   png_size_t size;
+
+   size = (png_size_t)length;
+   if ((png_uint_32)size != length)
+      png_error(png_ptr,"Overflow in png_memset_check.");
+
+   return (png_memset (s1, value, size));
+
+}
+
+#ifdef PNG_USER_MEM_SUPPORTED
+/* This function is called when the application wants to use another method
+ * of allocating and freeing memory.
+ */
+void PNGAPI
+png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr
+  malloc_fn, png_free_ptr free_fn)
+{
+   png_ptr->mem_ptr = mem_ptr;
+   png_ptr->malloc_fn = malloc_fn;
+   png_ptr->free_fn = free_fn;
+}
+
+/* This function returns a pointer to the mem_ptr associated with the user
+ * functions.  The application should free any memory associated with this
+ * pointer before png_write_destroy and png_read_destroy are called.
+ */
+png_voidp PNGAPI
+png_get_mem_ptr(png_structp png_ptr)
+{
+   return ((png_voidp)png_ptr->mem_ptr);
+}
+#endif /* PNG_USER_MEM_SUPPORTED */
diff --git a/Utilities/ITK/Utilities/png/pngpread.c b/Utilities/ITK/Utilities/png/pngpread.c
new file mode 100644
index 0000000000..9b4b77a931
--- /dev/null
+++ b/Utilities/ITK/Utilities/png/pngpread.c
@@ -0,0 +1,1504 @@
+
+/* pngpread.c - read a png file in push mode
+ *
+ * libpng 1.0.12 - June 8, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ */
+
+#define PNG_INTERNAL
+#include "png.h"
+
+#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
+
+/* push model modes */
+#define PNG_READ_SIG_MODE   0
+#define PNG_READ_CHUNK_MODE 1
+#define PNG_READ_IDAT_MODE  2
+#define PNG_SKIP_MODE       3
+#define PNG_READ_tEXt_MODE  4
+#define PNG_READ_zTXt_MODE  5
+#define PNG_READ_DONE_MODE  6
+#define PNG_READ_iTXt_MODE  7
+#define PNG_ERROR_MODE      8
+
+void PNGAPI
+png_process_data(png_structp png_ptr, png_infop info_ptr,
+   png_bytep buffer, png_size_t buffer_size)
+{
+   png_push_restore_buffer(png_ptr, buffer, buffer_size);
+
+   while (png_ptr->buffer_size)
+   {
+      png_process_some_data(png_ptr, info_ptr);
+   }
+}
+
+/* What we do with the incoming data depends on what we were previously
+ * doing before we ran out of data...
+ */
+void /* PRIVATE */
+png_process_some_data(png_structp png_ptr, png_infop info_ptr)
+{
+   switch (png_ptr->process_mode)
+   {
+      case PNG_READ_SIG_MODE:
+      {
+         png_push_read_sig(png_ptr, info_ptr);
+         break;
+      }
+      case PNG_READ_CHUNK_MODE:
+      {
+         png_push_read_chunk(png_ptr, info_ptr);
+         break;
+      }
+      case PNG_READ_IDAT_MODE:
+      {
+         png_push_read_IDAT(png_ptr);
+         break;
+      }
+#if defined(PNG_READ_tEXt_SUPPORTED)
+      case PNG_READ_tEXt_MODE:
+      {
+         png_push_read_tEXt(png_ptr, info_ptr);
+         break;
+      }
+#endif
+#if defined(PNG_READ_zTXt_SUPPORTED)
+      case PNG_READ_zTXt_MODE:
+      {
+         png_push_read_zTXt(png_ptr, info_ptr);
+         break;
+      }
+#endif
+#if defined(PNG_READ_iTXt_SUPPORTED)
+      case PNG_READ_iTXt_MODE:
+      {
+         png_push_read_iTXt(png_ptr, info_ptr);
+         break;
+      }
+#endif
+      case PNG_SKIP_MODE:
+      {
+         png_push_crc_finish(png_ptr);
+         break;
+      }
+      default:
+      {
+         png_ptr->buffer_size = 0;
+         break;
+      }
+   }
+}
+
+/* Read any remaining signature bytes from the stream and compare them with
+ * the correct PNG signature.  It is possible that this routine is called
+ * with bytes already read from the signature, either because they have been
+ * checked by the calling application, or because of multiple calls to this
+ * routine.
+ */
+void /* PRIVATE */
+png_push_read_sig(png_structp png_ptr, png_infop info_ptr)
+{
+   png_size_t num_checked = png_ptr->sig_bytes,
+             num_to_check = 8 - num_checked;
+
+   if (png_ptr->buffer_size < num_to_check)
+   {
+      num_to_check = png_ptr->buffer_size;
+   }
+
+   png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]),
+      num_to_check);
+   png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes+num_to_check);
+
+   if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
+   {
+      if (num_checked < 4 &&
+          png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
+         png_error(png_ptr, "Not a PNG file");
+      else
+         png_error(png_ptr, "PNG file corrupted by ASCII conversion");
+   }
+   else
+   {
+      if (png_ptr->sig_bytes >= 8)
+      {
+         png_ptr->process_mode = PNG_READ_CHUNK_MODE;
+      }
+   }
+}
+
+void /* PRIVATE */
+png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+      PNG_IHDR;
+      PNG_IDAT;
+      PNG_IEND;
+      PNG_PLTE;
+#if defined(PNG_READ_bKGD_SUPPORTED)
+      PNG_bKGD;
+#endif
+#if defined(PNG_READ_cHRM_SUPPORTED)
+      PNG_cHRM;
+#endif
+#if defined(PNG_READ_gAMA_SUPPORTED)
+      PNG_gAMA;
+#endif
+#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_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_sPLT_SUPPORTED)
+      PNG_sPLT;
+#endif
+#if defined(PNG_READ_tEXt_SUPPORTED)
+      PNG_tEXt;
+#endif
+#if defined(PNG_READ_tIME_SUPPORTED)
+      PNG_tIME;
+#endif
+#if defined(PNG_READ_tRNS_SUPPORTED)
+      PNG_tRNS;
+#endif
+#if defined(PNG_READ_zTXt_SUPPORTED)
+      PNG_zTXt;
+#endif
+#endif /* PNG_USE_LOCAL_ARRAYS */
+   /* First we make sure we have enough data for the 4 byte chunk name
+    * and the 4 byte chunk length before proceeding with decoding the
+    * chunk data.  To fully decode each of these chunks, we also make
+    * sure we have enough data in the buffer for the 4 byte CRC at the
+    * end of every chunk (except IDAT, which is handled separately).
+    */
+   if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER))
+   {
+      png_byte chunk_length[4];
+
+      if (png_ptr->buffer_size < 8)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_push_fill_buffer(png_ptr, chunk_length, 4);
+      png_ptr->push_length = png_get_uint_32(chunk_length);
+      png_reset_crc(png_ptr);
+      png_crc_read(png_ptr, png_ptr->chunk_name, 4);
+      png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
+   }
+
+   if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length);
+   }
+   else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length);
+   }
+   else if (!png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4))
+   {
+      /* If we reach an IDAT chunk, this means we have read all of the
+       * header chunks, and we can start reading the image (or if this
+       * is called after the image has been read - we have an error).
+       */
+      if (png_ptr->mode & PNG_HAVE_IDAT)
+      {
+         if (png_ptr->push_length == 0)
+            return;
+
+         if (png_ptr->mode & PNG_AFTER_IDAT)
+            png_error(png_ptr, "Too many IDAT's found");
+      }
+
+      png_ptr->idat_size = png_ptr->push_length;
+      png_ptr->mode |= PNG_HAVE_IDAT;
+      png_ptr->process_mode = PNG_READ_IDAT_MODE;
+      png_push_have_info(png_ptr, info_ptr);
+      png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;
+      png_ptr->zstream.next_out = png_ptr->row_buf;
+      return;
+   }
+   else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length);
+      png_ptr->process_mode = PNG_READ_DONE_MODE;
+      png_push_have_end(png_ptr, info_ptr);
+   }
+#if defined(PNG_READ_gAMA_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+#if defined(PNG_READ_sBIT_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+#if defined(PNG_READ_cHRM_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+#if defined(PNG_READ_sRGB_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+#if defined(PNG_READ_iCCP_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+#if defined(PNG_READ_sPLT_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+#if defined(PNG_READ_tRNS_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+#if defined(PNG_READ_bKGD_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+#if defined(PNG_READ_hIST_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+#if defined(PNG_READ_pHYs_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+#if defined(PNG_READ_oFFs_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+#if defined(PNG_READ_pCAL_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+#if defined(PNG_READ_sCAL_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+#if defined(PNG_READ_tIME_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+#if defined(PNG_READ_tEXt_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4))
+   {
+      png_push_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+#if defined(PNG_READ_zTXt_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))
+   {
+      png_push_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+#if defined(PNG_READ_iTXt_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4))
+   {
+      png_push_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+   else
+   {
+      png_push_handle_unknown(png_ptr, info_ptr, png_ptr->push_length);
+   }
+
+   png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
+}
+
+void /* PRIVATE */
+png_push_crc_skip(png_structp png_ptr, png_uint_32 skip)
+{
+   png_ptr->process_mode = PNG_SKIP_MODE;
+   png_ptr->skip_length = skip;
+}
+
+void /* PRIVATE */
+png_push_crc_finish(png_structp png_ptr)
+{
+   if (png_ptr->skip_length && png_ptr->save_buffer_size)
+   {
+      png_size_t save_size;
+
+      if (png_ptr->skip_length < (png_uint_32)png_ptr->save_buffer_size)
+         save_size = (png_size_t)png_ptr->skip_length;
+      else
+         save_size = png_ptr->save_buffer_size;
+
+      png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
+
+      png_ptr->skip_length -= save_size;
+      png_ptr->buffer_size -= save_size;
+      png_ptr->save_buffer_size -= save_size;
+      png_ptr->save_buffer_ptr += save_size;
+   }
+   if (png_ptr->skip_length && png_ptr->current_buffer_size)
+   {
+      png_size_t save_size;
+
+      if (png_ptr->skip_length < (png_uint_32)png_ptr->current_buffer_size)
+         save_size = (png_size_t)png_ptr->skip_length;
+      else
+         save_size = png_ptr->current_buffer_size;
+
+      png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
+
+      png_ptr->skip_length -= save_size;
+      png_ptr->buffer_size -= save_size;
+      png_ptr->current_buffer_size -= save_size;
+      png_ptr->current_buffer_ptr += save_size;
+   }
+   if (!png_ptr->skip_length)
+   {
+      if (png_ptr->buffer_size < 4)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_crc_finish(png_ptr, 0);
+      png_ptr->process_mode = PNG_READ_CHUNK_MODE;
+   }
+}
+
+void /* PRIVATE */
+png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
+{
+   png_bytep ptr;
+
+   ptr = buffer;
+   if (png_ptr->save_buffer_size)
+   {
+      png_size_t save_size;
+
+      if (length < png_ptr->save_buffer_size)
+         save_size = length;
+      else
+         save_size = png_ptr->save_buffer_size;
+
+      png_memcpy(ptr, png_ptr->save_buffer_ptr, save_size);
+      length -= save_size;
+      ptr += save_size;
+      png_ptr->buffer_size -= save_size;
+      png_ptr->save_buffer_size -= save_size;
+      png_ptr->save_buffer_ptr += save_size;
+   }
+   if (length && png_ptr->current_buffer_size)
+   {
+      png_size_t save_size;
+
+      if (length < png_ptr->current_buffer_size)
+         save_size = length;
+      else
+         save_size = png_ptr->current_buffer_size;
+
+      png_memcpy(ptr, png_ptr->current_buffer_ptr, save_size);
+      png_ptr->buffer_size -= save_size;
+      png_ptr->current_buffer_size -= save_size;
+      png_ptr->current_buffer_ptr += save_size;
+   }
+}
+
+void /* PRIVATE */
+png_push_save_buffer(png_structp png_ptr)
+{
+   if (png_ptr->save_buffer_size)
+   {
+      if (png_ptr->save_buffer_ptr != png_ptr->save_buffer)
+      {
+         png_size_t i,istop;
+         png_bytep sp;
+         png_bytep dp;
+
+         istop = png_ptr->save_buffer_size;
+         for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer;
+            i < istop; i++, sp++, dp++)
+         {
+            *dp = *sp;
+         }
+      }
+   }
+   if (png_ptr->save_buffer_size + png_ptr->current_buffer_size >
+      png_ptr->save_buffer_max)
+   {
+      png_size_t new_max;
+      png_bytep old_buffer;
+
+      new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256;
+      old_buffer = png_ptr->save_buffer;
+      png_ptr->save_buffer = (png_bytep)png_malloc(png_ptr,
+         (png_uint_32)new_max);
+      png_memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
+      png_free(png_ptr, old_buffer);
+      png_ptr->save_buffer_max = new_max;
+   }
+   if (png_ptr->current_buffer_size)
+   {
+      png_memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size,
+         png_ptr->current_buffer_ptr, png_ptr->current_buffer_size);
+      png_ptr->save_buffer_size += png_ptr->current_buffer_size;
+      png_ptr->current_buffer_size = 0;
+   }
+   png_ptr->save_buffer_ptr = png_ptr->save_buffer;
+   png_ptr->buffer_size = 0;
+}
+
+void /* PRIVATE */
+png_push_restore_buffer(png_structp png_ptr, png_bytep buffer,
+   png_size_t buffer_length)
+{
+   png_ptr->current_buffer = buffer;
+   png_ptr->current_buffer_size = buffer_length;
+   png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size;
+   png_ptr->current_buffer_ptr = png_ptr->current_buffer;
+}
+
+void /* PRIVATE */
+png_push_read_IDAT(png_structp png_ptr)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_IDAT;
+#endif
+   if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER))
+   {
+      png_byte chunk_length[4];
+
+      if (png_ptr->buffer_size < 8)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_push_fill_buffer(png_ptr, chunk_length, 4);
+      png_ptr->push_length = png_get_uint_32(chunk_length);
+
+      png_reset_crc(png_ptr);
+      png_crc_read(png_ptr, png_ptr->chunk_name, 4);
+      png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
+
+      if (png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4))
+      {
+         png_ptr->process_mode = PNG_READ_CHUNK_MODE;
+         if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
+            png_error(png_ptr, "Not enough compressed data");
+         return;
+      }
+
+      png_ptr->idat_size = png_ptr->push_length;
+   }
+   if (png_ptr->idat_size && png_ptr->save_buffer_size)
+   {
+      png_size_t save_size;
+
+      if (png_ptr->idat_size < (png_uint_32)png_ptr->save_buffer_size)
+      {
+         save_size = (png_size_t)png_ptr->idat_size;
+         /* check for overflow */
+         if((png_uint_32)save_size != png_ptr->idat_size)
+            png_error(png_ptr, "save_size overflowed in pngpread");
+      }
+      else
+         save_size = png_ptr->save_buffer_size;
+
+      png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
+      png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size);
+
+      png_ptr->idat_size -= save_size;
+      png_ptr->buffer_size -= save_size;
+      png_ptr->save_buffer_size -= save_size;
+      png_ptr->save_buffer_ptr += save_size;
+   }
+   if (png_ptr->idat_size && png_ptr->current_buffer_size)
+   {
+      png_size_t save_size;
+
+      if (png_ptr->idat_size < (png_uint_32)png_ptr->current_buffer_size)
+      {
+         save_size = (png_size_t)png_ptr->idat_size;
+         /* check for overflow */
+         if((png_uint_32)save_size != png_ptr->idat_size)
+            png_error(png_ptr, "save_size overflowed in pngpread");
+      }
+      else
+         save_size = png_ptr->current_buffer_size;
+
+      png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
+      png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size);
+
+      png_ptr->idat_size -= save_size;
+      png_ptr->buffer_size -= save_size;
+      png_ptr->current_buffer_size -= save_size;
+      png_ptr->current_buffer_ptr += save_size;
+   }
+   if (!png_ptr->idat_size)
+   {
+      if (png_ptr->buffer_size < 4)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_crc_finish(png_ptr, 0);
+      png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
+   }
+}
+
+void /* PRIVATE */
+png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
+   png_size_t buffer_length)
+{
+   int ret;
+
+   if ((png_ptr->flags & PNG_FLAG_ZLIB_FINISHED) && buffer_length)
+      png_error(png_ptr, "Extra compression data");
+
+   png_ptr->zstream.next_in = buffer;
+   png_ptr->zstream.avail_in = (uInt)buffer_length;
+   for(;;)
+   {
+      ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
+      if (ret != Z_OK)
+      {
+         if (ret == Z_STREAM_END)
+         {
+            if (png_ptr->zstream.avail_in)
+               png_error(png_ptr, "Extra compressed data");
+            if (!(png_ptr->zstream.avail_out))
+            {
+               png_push_process_row(png_ptr);
+            }
+
+            png_ptr->mode |= PNG_AFTER_IDAT;
+            png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
+            break;
+         }
+         else if (ret == Z_BUF_ERROR)
+            break;
+         else
+            png_error(png_ptr, "Decompression Error");
+      }
+      if (!(png_ptr->zstream.avail_out))
+      {
+         png_push_process_row(png_ptr);
+         png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;
+         png_ptr->zstream.next_out = png_ptr->row_buf;
+      }
+      else
+         break;
+   }
+}
+
+void /* PRIVATE */
+png_push_process_row(png_structp png_ptr)
+{
+   png_ptr->row_info.color_type = png_ptr->color_type;
+   png_ptr->row_info.width = png_ptr->iwidth;
+   png_ptr->row_info.channels = png_ptr->channels;
+   png_ptr->row_info.bit_depth = png_ptr->bit_depth;
+   png_ptr->row_info.pixel_depth = png_ptr->pixel_depth;
+
+   png_ptr->row_info.rowbytes = ((png_ptr->row_info.width *
+      (png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3);
+
+   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]));
+
+   png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf,
+      png_ptr->rowbytes + 1);
+
+   if (png_ptr->transformations)
+      png_do_read_transformations(png_ptr);
+
+#if defined(PNG_READ_INTERLACING_SUPPORTED)
+   /* blow up interlaced rows to full size */
+   if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
+   {
+      if (png_ptr->pass < 6)
+/*       old interface (pre-1.0.9):
+         png_do_read_interlace(&(png_ptr->row_info),
+            png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations);
+ */
+         png_do_read_interlace(png_ptr);
+
+    switch (png_ptr->pass)
+    {
+         case 0:
+         {
+            int i;
+            for (i = 0; i < 8 && png_ptr->pass == 0; i++)
+            {
+               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
+               png_read_push_finish_row(png_ptr); /* updates png_ptr->pass */
+            }
+            if (png_ptr->pass == 2) /* pass 1 might be empty */
+            {
+               for (i = 0; i < 4 && png_ptr->pass == 2; i++)
+               {
+                  png_push_have_row(png_ptr, NULL);
+                  png_read_push_finish_row(png_ptr);
+               }
+            }
+	    if (png_ptr->pass == 4 && png_ptr->height <= 4)
+	    {
+	        for (i = 0; i < 2 && png_ptr->pass == 4; i++)
+                {
+                   png_push_have_row(png_ptr, NULL);
+                   png_read_push_finish_row(png_ptr);
+                }
+            }
+            if (png_ptr->pass == 6 && png_ptr->height <= 4)
+            {
+                png_push_have_row(png_ptr, NULL);
+                png_read_push_finish_row(png_ptr);
+            }
+            break;
+         }
+         case 1:
+         {
+            int i;
+            for (i = 0; i < 8 && png_ptr->pass == 1; i++)
+            {
+               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
+               png_read_push_finish_row(png_ptr);
+            }
+            if (png_ptr->pass == 2) /* skip top 4 generated rows */
+            {
+               for (i = 0; i < 4 && png_ptr->pass == 2; i++)
+               {
+                  png_push_have_row(png_ptr, NULL);
+                  png_read_push_finish_row(png_ptr);
+               }
+            }
+            break;
+         }
+         case 2:
+         {
+            int i;
+            for (i = 0; i < 4 && png_ptr->pass == 2; i++)
+            {
+               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
+               png_read_push_finish_row(png_ptr);
+            }
+            for (i = 0; i < 4 && png_ptr->pass == 2; i++)
+            {
+               png_push_have_row(png_ptr, NULL);
+               png_read_push_finish_row(png_ptr);
+            }
+            if (png_ptr->pass == 4) /* pass 3 might be empty */
+            {
+               for (i = 0; i < 2 && png_ptr->pass == 4; i++)
+               {
+                  png_push_have_row(png_ptr, NULL);
+                  png_read_push_finish_row(png_ptr);
+               }
+            }
+            break;
+         }
+         case 3:
+         {
+            int i;
+            for (i = 0; i < 4 && png_ptr->pass == 3; i++)
+            {
+               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
+               png_read_push_finish_row(png_ptr);
+            }
+            if (png_ptr->pass == 4) /* skip top two generated rows */
+            {
+               for (i = 0; i < 2 && png_ptr->pass == 4; i++)
+               {
+                  png_push_have_row(png_ptr, NULL);
+                  png_read_push_finish_row(png_ptr);
+               }
+            }
+            break;
+         }
+         case 4:
+         {
+            int i;
+            for (i = 0; i < 2 && png_ptr->pass == 4; i++)
+            {
+               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
+               png_read_push_finish_row(png_ptr);
+            }
+            for (i = 0; i < 2 && png_ptr->pass == 4; i++)
+            {
+               png_push_have_row(png_ptr, NULL);
+               png_read_push_finish_row(png_ptr);
+            }
+            if (png_ptr->pass == 6) /* pass 5 might be empty */
+            {
+               png_push_have_row(png_ptr, NULL);
+               png_read_push_finish_row(png_ptr);
+            }
+            break;
+         }
+         case 5:
+         {
+            int i;
+            for (i = 0; i < 2 && png_ptr->pass == 5; i++)
+            {
+               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
+               png_read_push_finish_row(png_ptr);
+            }
+            if (png_ptr->pass == 6) /* skip top generated row */
+            {
+               png_push_have_row(png_ptr, NULL);
+               png_read_push_finish_row(png_ptr);
+            }
+            break;
+         }
+         case 6:
+         {
+            png_push_have_row(png_ptr, png_ptr->row_buf + 1);
+            png_read_push_finish_row(png_ptr);
+            if (png_ptr->pass != 6)
+               break;
+            png_push_have_row(png_ptr, NULL);
+            png_read_push_finish_row(png_ptr);
+         }
+      }
+   }
+   else
+#endif
+   {
+      png_push_have_row(png_ptr, png_ptr->row_buf + 1);
+      png_read_push_finish_row(png_ptr);
+   }
+}
+
+void /* PRIVATE */
+png_read_push_finish_row(png_structp png_ptr)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+
+   /* start of interlace block */
+   const int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
+
+   /* offset to next interlace block */
+   const int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
+
+   /* start of interlace block in the y direction */
+   const int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
+
+   /* offset to next interlace block in the y direction */
+   const int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
+
+   /* Width of interlace block.  This is not currently used - if you need
+    * it, uncomment it here and in png.h
+   const int FARDATA png_pass_width[] = {8, 4, 4, 2, 2, 1, 1};
+   */
+
+   /* Height of interlace block.  This is not currently used - if you need
+    * it, uncomment it here and in png.h
+   const int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
+   */
+#endif
+
+   png_ptr->row_number++;
+   if (png_ptr->row_number < png_ptr->num_rows)
+      return;
+
+   if (png_ptr->interlaced)
+   {
+      png_ptr->row_number = 0;
+      png_memset_check(png_ptr, png_ptr->prev_row, 0,
+         png_ptr->rowbytes + 1);
+      do
+      {
+         png_ptr->pass++;
+         if ((png_ptr->pass == 1 && png_ptr->width < 5) ||
+             (png_ptr->pass == 3 && png_ptr->width < 3) ||
+             (png_ptr->pass == 5 && png_ptr->width < 2))
+           png_ptr->pass++;
+
+         if (png_ptr->pass >= 7)
+            break;
+
+         png_ptr->iwidth = (png_ptr->width +
+            png_pass_inc[png_ptr->pass] - 1 -
+            png_pass_start[png_ptr->pass]) /
+            png_pass_inc[png_ptr->pass];
+
+         png_ptr->irowbytes = ((png_ptr->iwidth *
+            png_ptr->pixel_depth + 7) >> 3) + 1;
+
+         if (png_ptr->transformations & PNG_INTERLACE)
+            break;
+
+         png_ptr->num_rows = (png_ptr->height +
+            png_pass_yinc[png_ptr->pass] - 1 -
+            png_pass_ystart[png_ptr->pass]) /
+            png_pass_yinc[png_ptr->pass];
+
+      } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0);
+   }
+}
+
+#if defined(PNG_READ_tEXt_SUPPORTED)
+void /* PRIVATE */
+png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32
+   length)
+{
+   if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))
+      {
+         png_error(png_ptr, "Out of place tEXt");
+         /* to quiet some compiler warnings */
+         if(info_ptr == NULL) return;
+      }
+
+#ifdef PNG_MAX_MALLOC_64K
+   png_ptr->skip_length = 0;  /* This may not be necessary */
+
+   if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */
+   {
+      png_warning(png_ptr, "tEXt chunk too large to fit in memory");
+      png_ptr->skip_length = length - (png_uint_32)65535L;
+      length = (png_uint_32)65535L;
+   }
+#endif
+
+   png_ptr->current_text = (png_charp)png_malloc(png_ptr,
+         (png_uint_32)(length+1));
+   png_ptr->current_text[length] = '\0';
+   png_ptr->current_text_ptr = png_ptr->current_text;
+   png_ptr->current_text_size = (png_size_t)length;
+   png_ptr->current_text_left = (png_size_t)length;
+   png_ptr->process_mode = PNG_READ_tEXt_MODE;
+}
+
+void /* PRIVATE */
+png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr->buffer_size && png_ptr->current_text_left)
+   {
+      png_size_t text_size;
+
+      if (png_ptr->buffer_size < png_ptr->current_text_left)
+         text_size = png_ptr->buffer_size;
+      else
+         text_size = png_ptr->current_text_left;
+      png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
+      png_ptr->current_text_left -= text_size;
+      png_ptr->current_text_ptr += text_size;
+   }
+   if (!(png_ptr->current_text_left))
+   {
+      png_textp text_ptr;
+      png_charp text;
+      png_charp key;
+
+      if (png_ptr->buffer_size < 4)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_push_crc_finish(png_ptr);
+
+#if defined(PNG_MAX_MALLOC_64K)
+      if (png_ptr->skip_length)
+         return;
+#endif
+
+      key = png_ptr->current_text;
+      png_ptr->current_text = 0;
+
+      for (text = 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->key = key;
+#ifdef PNG_iTXt_SUPPORTED
+      text_ptr->lang = (char *)NULL;
+      text_ptr->lang_key = (char *)NULL;
+#endif
+      text_ptr->text = text;
+
+      png_set_text(png_ptr, info_ptr, text_ptr, 1);
+
+      png_free(png_ptr, key);
+      png_free(png_ptr, text_ptr);
+   }
+}
+#endif
+
+#if defined(PNG_READ_zTXt_SUPPORTED)
+void /* PRIVATE */
+png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32
+   length)
+{
+   if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))
+      {
+         png_error(png_ptr, "Out of place zTXt");
+         /* to quiet some compiler warnings */
+         if(info_ptr == NULL) return;
+      }
+
+#ifdef PNG_MAX_MALLOC_64K
+   /* We can't handle zTXt chunks > 64K, since we don't have enough space
+    * to be able to store the uncompressed data.  Actually, the threshold
+    * is probably around 32K, but it isn't as definite as 64K is.
+    */
+   if (length > (png_uint_32)65535L)
+   {
+      png_warning(png_ptr, "zTXt chunk too large to fit in memory");
+      png_push_crc_skip(png_ptr, length);
+      return;
+   }
+#endif
+
+   png_ptr->current_text = (png_charp)png_malloc(png_ptr,
+       (png_uint_32)(length+1));
+   png_ptr->current_text[length] = '\0';
+   png_ptr->current_text_ptr = png_ptr->current_text;
+   png_ptr->current_text_size = (png_size_t)length;
+   png_ptr->current_text_left = (png_size_t)length;
+   png_ptr->process_mode = PNG_READ_zTXt_MODE;
+}
+
+void /* PRIVATE */
+png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr->buffer_size && png_ptr->current_text_left)
+   {
+      png_size_t text_size;
+
+      if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left)
+         text_size = png_ptr->buffer_size;
+      else
+         text_size = png_ptr->current_text_left;
+      png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
+      png_ptr->current_text_left -= text_size;
+      png_ptr->current_text_ptr += text_size;
+   }
+   if (!(png_ptr->current_text_left))
+   {
+      png_textp text_ptr;
+      png_charp text;
+      png_charp key;
+      int ret;
+      png_size_t text_size, key_size;
+
+      if (png_ptr->buffer_size < 4)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_push_crc_finish(png_ptr);
+
+      key = png_ptr->current_text;
+      png_ptr->current_text = 0;
+
+      for (text = key; *text; text++)
+         /* empty loop */ ;
+
+      /* zTXt can't have zero text */
+      if (text == key + png_ptr->current_text_size)
+      {
+         png_free(png_ptr, key);
+         return;
+      }
+
+      text++;
+
+      if (*text != PNG_TEXT_COMPRESSION_zTXt) /* check compression byte */
+      {
+         png_free(png_ptr, key);
+         return;
+      }
+
+      text++;
+
+      png_ptr->zstream.next_in = (png_bytep )text;
+      png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size -
+         (text - key));
+      png_ptr->zstream.next_out = png_ptr->zbuf;
+      png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+
+      key_size = text - key;
+      text_size = 0;
+      text = NULL;
+      ret = Z_STREAM_END;
+
+      while (png_ptr->zstream.avail_in)
+      {
+         ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
+         if (ret != Z_OK && ret != Z_STREAM_END)
+         {
+            inflateReset(&png_ptr->zstream);
+            png_ptr->zstream.avail_in = 0;
+            png_free(png_ptr, key);
+            png_free(png_ptr, text);
+            return;
+         }
+         if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END)
+         {
+            if (text == NULL)
+            {
+               text = (png_charp)png_malloc(png_ptr,
+                  (png_uint_32)(png_ptr->zbuf_size - png_ptr->zstream.avail_out
+                     + key_size + 1));
+               png_memcpy(text + key_size, png_ptr->zbuf,
+                  png_ptr->zbuf_size - png_ptr->zstream.avail_out);
+               png_memcpy(text, key, key_size);
+               text_size = key_size + png_ptr->zbuf_size -
+                  png_ptr->zstream.avail_out;
+               *(text + text_size) = '\0';
+            }
+            else
+            {
+               png_charp tmp;
+
+               tmp = text;
+               text = (png_charp)png_malloc(png_ptr, text_size +
+                  (png_uint_32)(png_ptr->zbuf_size - png_ptr->zstream.avail_out
+                   + 1));
+               png_memcpy(text, tmp, text_size);
+               png_free(png_ptr, tmp);
+               png_memcpy(text + text_size, png_ptr->zbuf,
+                  png_ptr->zbuf_size - png_ptr->zstream.avail_out);
+               text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
+               *(text + text_size) = '\0';
+            }
+            if (ret != Z_STREAM_END)
+            {
+               png_ptr->zstream.next_out = png_ptr->zbuf;
+               png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+            }
+         }
+         else
+         {
+            break;
+         }
+
+         if (ret == Z_STREAM_END)
+            break;
+      }
+
+      inflateReset(&png_ptr->zstream);
+      png_ptr->zstream.avail_in = 0;
+
+      if (ret != Z_STREAM_END)
+      {
+         png_free(png_ptr, key);
+         png_free(png_ptr, text);
+         return;
+      }
+
+      png_free(png_ptr, key);
+      key = text;
+      text += key_size;
+
+      text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
+      text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt;
+      text_ptr->key = key;
+#ifdef PNG_iTXt_SUPPORTED
+      text_ptr->lang = (char *)NULL;
+      text_ptr->lang_key = (char *)NULL;
+#endif
+      text_ptr->text = text;
+
+      png_set_text(png_ptr, info_ptr, text_ptr, 1);
+
+      png_free(png_ptr, key);
+      png_free(png_ptr, text_ptr);
+   }
+}
+#endif
+
+#if defined(PNG_READ_iTXt_SUPPORTED)
+void /* PRIVATE */
+png_push_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32
+   length)
+{
+   if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))
+      {
+         png_error(png_ptr, "Out of place iTXt");
+         /* to quiet some compiler warnings */
+         if(info_ptr == NULL) return;
+      }
+
+#ifdef PNG_MAX_MALLOC_64K
+   png_ptr->skip_length = 0;  /* This may not be necessary */
+
+   if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */
+   {
+      png_warning(png_ptr, "iTXt chunk too large to fit in memory");
+      png_ptr->skip_length = length - (png_uint_32)65535L;
+      length = (png_uint_32)65535L;
+   }
+#endif
+
+   png_ptr->current_text = (png_charp)png_malloc(png_ptr,
+         (png_uint_32)(length+1));
+   png_ptr->current_text[length] = '\0';
+   png_ptr->current_text_ptr = png_ptr->current_text;
+   png_ptr->current_text_size = (png_size_t)length;
+   png_ptr->current_text_left = (png_size_t)length;
+   png_ptr->process_mode = PNG_READ_iTXt_MODE;
+}
+
+void /* PRIVATE */
+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;
+
+      if (png_ptr->buffer_size < png_ptr->current_text_left)
+         text_size = png_ptr->buffer_size;
+      else
+         text_size = png_ptr->current_text_left;
+      png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
+      png_ptr->current_text_left -= text_size;
+      png_ptr->current_text_ptr += text_size;
+   }
+   if (!(png_ptr->current_text_left))
+   {
+      png_textp text_ptr;
+      png_charp key;
+      int comp_flag;
+      png_charp lang;
+      png_charp lang_key;
+      png_charp text;
+
+      if (png_ptr->buffer_size < 4)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_push_crc_finish(png_ptr);
+
+#if defined(PNG_MAX_MALLOC_64K)
+      if (png_ptr->skip_length)
+         return;
+#endif
+
+      key = png_ptr->current_text;
+      png_ptr->current_text = 0;
+
+      for (lang = key; *lang; lang++)
+         /* empty loop */ ;
+
+      if (lang != key + png_ptr->current_text_size)
+         lang++;
+
+      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 = 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);
+
+      png_free(png_ptr, text_ptr);
+   }
+}
+#endif
+
+/* This function is called when we haven't found a handler for this
+ * 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 /* PRIVATE */
+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))
+   {
+#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
+      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 == NULL
+#endif
+         )
+#endif
+         png_chunk_error(png_ptr, "unknown critical chunk");
+
+      /* to quiet compiler warnings about unused info_ptr */
+      if (info_ptr == NULL)
+         return;
+   }
+
+#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
+
+       png_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 != 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 /* PRIVATE */
+png_push_have_info(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr->info_fn != NULL)
+      (*(png_ptr->info_fn))(png_ptr, info_ptr);
+}
+
+void /* PRIVATE */
+png_push_have_end(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr->end_fn != NULL)
+      (*(png_ptr->end_fn))(png_ptr, info_ptr);
+}
+
+void /* PRIVATE */
+png_push_have_row(png_structp png_ptr, png_bytep row)
+{
+   if (png_ptr->row_fn != NULL)
+      (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number,
+         (int)png_ptr->pass);
+}
+
+void PNGAPI
+png_progressive_combine_row (png_structp png_ptr,
+   png_bytep old_row, png_bytep new_row)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   const int FARDATA png_pass_dsp_mask[7] =
+      {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff};
+#endif
+   if (new_row != NULL)    /* new_row must == png_ptr->row_buf here. */
+      png_combine_row(png_ptr, old_row, png_pass_dsp_mask[png_ptr->pass]);
+}
+
+void PNGAPI
+png_set_progressive_read_fn(png_structp png_ptr, png_voidp progressive_ptr,
+   png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,
+   png_progressive_end_ptr end_fn)
+{
+   png_ptr->info_fn = info_fn;
+   png_ptr->row_fn = row_fn;
+   png_ptr->end_fn = end_fn;
+
+   png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
+}
+
+png_voidp PNGAPI
+png_get_progressive_ptr(png_structp png_ptr)
+{
+   return png_ptr->io_ptr;
+}
+
+#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
+
diff --git a/Utilities/ITK/Utilities/png/pngread.c b/Utilities/ITK/Utilities/png/pngread.c
new file mode 100644
index 0000000000..06783ff6b9
--- /dev/null
+++ b/Utilities/ITK/Utilities/png/pngread.c
@@ -0,0 +1,1424 @@
+
+/* pngread.c - read a PNG file
+ *
+ * libpng 1.0.12 - June 8, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This file contains routines that an application calls directly to
+ * read a PNG file or stream.
+ */
+
+#define PNG_INTERNAL
+#include "png.h"
+
+/* Create a PNG structure for reading, and allocate any memory needed. */
+png_structp PNGAPI
+png_create_read_struct(png_const_charp user_png_ver, png_voidp error_ptr,
+   png_error_ptr error_fn, png_error_ptr warn_fn)
+{
+
+#ifdef PNG_USER_MEM_SUPPORTED
+   return (png_create_read_struct_2(user_png_ver, error_ptr, error_fn,
+      warn_fn, NULL, NULL, NULL));
+}
+
+/* Alternate create PNG structure for reading, and allocate any memory needed. */
+png_structp PNGAPI
+png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
+   png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
+   png_malloc_ptr malloc_fn, png_free_ptr free_fn)
+{
+#endif /* PNG_USER_MEM_SUPPORTED */
+
+   png_structp png_ptr;
+
+#ifdef PNG_SETJMP_SUPPORTED
+#ifdef USE_FAR_KEYWORD
+   jmp_buf jmpbuf;
+#endif
+#endif
+
+   int i;
+
+   png_debug(1, "in png_create_read_struct\n");
+#ifdef PNG_USER_MEM_SUPPORTED
+   if ((png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,
+      (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr)) == NULL)
+#else
+   if ((png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG)) == NULL)
+#endif
+   {
+      return (png_structp)NULL;
+   }
+
+#ifdef PNG_SETJMP_SUPPORTED
+#ifdef USE_FAR_KEYWORD
+   if (setjmp(jmpbuf))
+#else
+   if (setjmp(png_ptr->jmpbuf))
+#endif
+   {
+      png_free(png_ptr, png_ptr->zbuf);
+      png_ptr->zbuf=NULL;
+      png_destroy_struct(png_ptr);
+      return (png_structp)NULL;
+   }
+#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_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
+
+   i=0;
+   do
+   {
+     if(user_png_ver[i] != png_libpng_ver[i])
+        png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
+   } while (png_libpng_ver[i++]);
+
+   if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH)
+   {
+     /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
+      * we must recompile any applications that use any older library version.
+      * For versions after libpng 1.0, we will be compatible, so we need
+      * only check the first digit.
+      */
+     if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] ||
+         (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) ||
+         (user_png_ver[0] == '0' && user_png_ver[2] < '9'))
+     {
+#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
+        char msg[80];
+        if (user_png_ver)
+        {
+          sprintf(msg, "Application was compiled with png.h from libpng-%.20s",
+             user_png_ver);
+          png_warning(png_ptr, msg);
+        }
+        sprintf(msg, "Application  is running with png.c from libpng-%.20s",
+           png_libpng_ver);
+        png_warning(png_ptr, msg);
+#endif
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+        png_ptr->flags=0;
+#endif
+        png_error(png_ptr,
+           "Incompatible libpng version in application and library");
+     }
+
+     /* Libpng 1.0.6 was not binary compatible, due to insertion of the
+        info_ptr->free_me member.  Libpng-1.0.1 and earlier were not
+        compatible due to insertion of the user transform function. Note
+        to maintainer: this test can be removed from version 1.2.0 and
+        beyond because the previous test would have already rejected it. */
+
+     if (user_png_ver[0] == '1' && user_png_ver[2] == '0' &&
+         (user_png_ver[4] <  '2' || user_png_ver[4] == '6') &&
+         user_png_ver[5] == '\0')
+     {
+#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
+        char msg[80];
+        if (user_png_ver)
+        {
+          sprintf(msg, "Application was compiled with png.h from libpng-%.20s",
+             user_png_ver);
+          png_warning(png_ptr, msg);
+        }
+        sprintf(msg, "Application  is running with png.c from libpng-%.20s",
+           png_libpng_ver);
+        png_warning(png_ptr, msg);
+#endif
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+        png_ptr->flags=0;
+#endif
+        png_error(png_ptr,
+        "Application must be recompiled; versions <= 1.0.6 were incompatible");
+     }
+   }
+
+   /* initialize zbuf - compression buffer */
+   png_ptr->zbuf_size = PNG_ZBUF_SIZE;
+   png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
+     (png_uint_32)png_ptr->zbuf_size);
+   png_ptr->zstream.zalloc = png_zalloc;
+   png_ptr->zstream.zfree = png_zfree;
+   png_ptr->zstream.opaque = (voidpf)png_ptr;
+
+   switch (inflateInit(&png_ptr->zstream))
+   {
+     case Z_OK: /* Do nothing */ break;
+     case Z_MEM_ERROR:
+     case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory error"); break;
+     case Z_VERSION_ERROR: png_error(png_ptr, "zlib version error"); break;
+     default: png_error(png_ptr, "Unknown zlib error");
+   }
+
+   png_ptr->zstream.next_out = png_ptr->zbuf;
+   png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+
+   png_set_read_fn(png_ptr, NULL, NULL);
+
+   return (png_ptr);
+}
+
+/* Initialize PNG structure for reading, and allocate any memory needed.
+   This interface is deprecated in favour of the png_create_read_struct(),
+   and it will eventually disappear. */
+#undef png_read_init
+void PNGAPI
+itk_png_read_init(png_structp png_ptr)
+{
+   /* We only come here via pre-1.0.7-compiled applications */
+   png_read_init_2(png_ptr, "1.0.6 or earlier", 0, 0);
+}
+
+void PNGAPI
+png_read_init_2(png_structp png_ptr, png_const_charp user_png_ver,
+   png_size_t png_struct_size, png_size_t png_info_size)
+{
+   /* We only come here via pre-1.0.12-compiled applications */
+#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
+   if(sizeof(png_struct) > png_struct_size || sizeof(png_info) > png_info_size)
+   {
+      char msg[80];
+      png_ptr->warning_fn=(png_error_ptr)NULL;
+      if (user_png_ver)
+      {
+        sprintf(msg, "Application was compiled with png.h from libpng-%.20s",
+           user_png_ver);
+        png_warning(png_ptr, msg);
+      }
+      sprintf(msg, "Application  is running with png.c from libpng-%.20s",
+         png_libpng_ver);
+      png_warning(png_ptr, msg);
+   }
+#endif
+   if(sizeof(png_struct) > png_struct_size)
+     {
+       png_ptr->error_fn=(png_error_ptr)NULL;
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+       png_ptr->flags=0;
+#endif
+       png_error(png_ptr,
+       "The png struct allocated by the application for reading is too small.");
+     }
+   if(sizeof(png_info) > png_info_size)
+     {
+       png_ptr->error_fn=(png_error_ptr)NULL;
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+       png_ptr->flags=0;
+#endif
+       png_error(png_ptr,
+         "The info struct allocated by application for reading is too small.");
+     }
+   png_read_init_3(&png_ptr, user_png_ver, png_struct_size);
+}
+
+void PNGAPI
+png_read_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver,
+   png_size_t png_struct_size)
+{
+#ifdef PNG_SETJMP_SUPPORTED
+   jmp_buf tmp_jmp;  /* to save current jump buffer */
+#endif
+
+   int i=0;
+
+   png_structp png_ptr=*ptr_ptr;
+
+   do
+   {
+     if(user_png_ver[i] != png_libpng_ver[i])
+     {
+#ifdef PNG_LEGACY_SUPPORTED
+       png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
+#else
+       png_ptr->warning_fn=(png_error_ptr)NULL;
+       png_warning(png_ptr,
+        "Application uses deprecated png_read_init() and should be recompiled.");
+       break;
+#endif
+     }
+   } while (png_libpng_ver[i++]);
+
+   png_debug(1, "in png_read_init_3\n");
+
+#ifdef PNG_SETJMP_SUPPORTED
+   /* save jump buffer and error functions */
+   png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
+#endif
+
+   if(sizeof(png_struct) > png_struct_size)
+     {
+       png_destroy_struct(png_ptr);
+       *ptr_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
+       png_ptr = *ptr_ptr;
+     }
+
+   /* 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;
+   png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
+     (png_uint_32)png_ptr->zbuf_size);
+   png_ptr->zstream.zalloc = png_zalloc;
+   png_ptr->zstream.zfree = png_zfree;
+   png_ptr->zstream.opaque = (voidpf)png_ptr;
+
+   switch (inflateInit(&png_ptr->zstream))
+   {
+     case Z_OK: /* Do nothing */ break;
+     case Z_MEM_ERROR:
+     case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory"); break;
+     case Z_VERSION_ERROR: png_error(png_ptr, "zlib version"); break;
+     default: png_error(png_ptr, "Unknown zlib error");
+   }
+
+   png_ptr->zstream.next_out = png_ptr->zbuf;
+   png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+
+   png_set_read_fn(png_ptr, NULL, NULL);
+}
+
+/* Read the information before the actual image data.  This has been
+ * changed in v0.90 to allow reading a file that already has the magic
+ * bytes read from the stream.  You can tell libpng how many bytes have
+ * been read from the beginning of the stream (up to the maximum of 8)
+ * via png_set_sig_bytes(), and we will only check the remaining bytes
+ * here.  The application can then have access to the signature bytes we
+ * read if it is determined that this isn't a valid PNG file.
+ */
+void PNGAPI
+png_read_info(png_structp png_ptr, png_infop info_ptr)
+{
+   png_debug(1, "in png_read_info\n");
+   /* save jump buffer and error functions */
+   /* If we haven't checked all of the PNG signature bytes, do so now. */
+   if (png_ptr->sig_bytes < 8)
+   {
+      png_size_t num_checked = png_ptr->sig_bytes,
+                 num_to_check = 8 - num_checked;
+
+      png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check);
+      png_ptr->sig_bytes = 8;
+
+      if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
+      {
+         if (num_checked < 4 &&
+             png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
+            png_error(png_ptr, "Not a PNG file");
+         else
+            png_error(png_ptr, "PNG file corrupted by ASCII conversion");
+      }
+      if (num_checked < 3)
+         png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE;
+   }
+
+   for(;;)
+   {
+#ifdef PNG_USE_LOCAL_ARRAYS
+      PNG_IHDR;
+      PNG_IDAT;
+      PNG_IEND;
+      PNG_PLTE;
+#if defined(PNG_READ_bKGD_SUPPORTED)
+      PNG_bKGD;
+#endif
+#if defined(PNG_READ_cHRM_SUPPORTED)
+      PNG_cHRM;
+#endif
+#if defined(PNG_READ_gAMA_SUPPORTED)
+      PNG_gAMA;
+#endif
+#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_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_sPLT_SUPPORTED)
+      PNG_sPLT;
+#endif
+#if defined(PNG_READ_sRGB_SUPPORTED)
+      PNG_sRGB;
+#endif
+#if defined(PNG_READ_tEXt_SUPPORTED)
+      PNG_tEXt;
+#endif
+#if defined(PNG_READ_tIME_SUPPORTED)
+      PNG_tIME;
+#endif
+#if defined(PNG_READ_tRNS_SUPPORTED)
+      PNG_tRNS;
+#endif
+#if defined(PNG_READ_zTXt_SUPPORTED)
+      PNG_zTXt;
+#endif
+#endif /* PNG_GLOBAL_ARRAYS */
+      png_byte chunk_length[4];
+      png_uint_32 length;
+
+      png_read_data(png_ptr, chunk_length, 4);
+      length = png_get_uint_32(chunk_length);
+
+      png_reset_crc(png_ptr);
+      png_crc_read(png_ptr, png_ptr->chunk_name, 4);
+
+      png_debug2(0, "Reading %s chunk, length=%lu.\n", png_ptr->chunk_name,
+         length);
+
+      /* This should be a binary subdivision search or a hash for
+       * matching the chunk name rather than a linear search.
+       */
+      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))
+            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))
+            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");
+
+         png_ptr->idat_size = length;
+         png_ptr->mode |= PNG_HAVE_IDAT;
+         break;
+      }
+#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);
+#endif
+#if defined(PNG_READ_cHRM_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))
+         png_handle_cHRM(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_gAMA_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
+         png_handle_gAMA(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_hIST_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))
+         png_handle_hIST(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_oFFs_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))
+         png_handle_oFFs(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_pCAL_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4))
+         png_handle_pCAL(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_sCAL_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4))
+         png_handle_sCAL(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_pHYs_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))
+         png_handle_pHYs(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_sBIT_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))
+         png_handle_sBIT(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_sRGB_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4))
+         png_handle_sRGB(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_iCCP_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4))
+         png_handle_iCCP(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_sPLT_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4))
+         png_handle_sPLT(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_tEXt_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4))
+         png_handle_tEXt(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_tIME_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
+         png_handle_tIME(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_tRNS_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
+         png_handle_tRNS(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_zTXt_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))
+         png_handle_zTXt(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_iTXt_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4))
+         png_handle_iTXt(png_ptr, info_ptr, length);
+#endif
+      else
+         png_handle_unknown(png_ptr, info_ptr, length);
+   }
+}
+
+/* optional call to update the users info_ptr structure */
+void PNGAPI
+png_read_update_info(png_structp png_ptr, png_infop info_ptr)
+{
+   png_debug(1, "in png_read_update_info\n");
+   /* save jump buffer and error functions */
+   if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
+      png_read_start_row(png_ptr);
+   else
+      png_warning(png_ptr,
+      "Ignoring extra png_read_update_info() call; row buffer not reallocated");
+   png_read_transform_info(png_ptr, info_ptr);
+}
+
+/* Initialize palette, background, etc, after transformations
+ * are set, but before any reading takes place.  This allows
+ * the user to obtain a gamma-corrected palette, for example.
+ * If the user doesn't call this, we will do it ourselves.
+ */
+void PNGAPI
+png_start_read_image(png_structp png_ptr)
+{
+   png_debug(1, "in png_start_read_image\n");
+   /* save jump buffer and error functions */
+   if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
+      png_read_start_row(png_ptr);
+}
+
+void PNGAPI
+png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_IDAT;
+   const int png_pass_dsp_mask[7] = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff};
+   const int png_pass_mask[7] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff};
+#endif
+   int ret;
+   png_debug2(1, "in png_read_row (row %lu, pass %d)\n",
+      png_ptr->row_number, png_ptr->pass);
+   /* save jump buffer and error functions */
+   if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
+      png_read_start_row(png_ptr);
+   if (png_ptr->row_number == 0 && png_ptr->pass == 0)
+   {
+   /* check for transforms that have been set but were defined out */
+#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED)
+   if (png_ptr->transformations & PNG_INVERT_MONO)
+      png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined.");
+#endif
+#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED)
+   if (png_ptr->transformations & PNG_FILLER)
+      png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined.");
+#endif
+#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && !defined(PNG_READ_PACKSWAP_SUPPORTED)
+   if (png_ptr->transformations & PNG_PACKSWAP)
+      png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined.");
+#endif
+#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED)
+   if (png_ptr->transformations & PNG_PACK)
+      png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined.");
+#endif
+#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED)
+   if (png_ptr->transformations & PNG_SHIFT)
+      png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined.");
+#endif
+#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED)
+   if (png_ptr->transformations & PNG_BGR)
+      png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined.");
+#endif
+#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED)
+   if (png_ptr->transformations & PNG_SWAP_BYTES)
+      png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined.");
+#endif
+   }
+
+#if defined(PNG_READ_INTERLACING_SUPPORTED)
+   /* if interlaced and we do not need a new row, combine row and return */
+   if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
+   {
+      switch (png_ptr->pass)
+      {
+         case 0:
+            if (png_ptr->row_number & 0x07)
+            {
+               if (dsp_row != NULL)
+                  png_combine_row(png_ptr, dsp_row,
+                     png_pass_dsp_mask[png_ptr->pass]);
+               png_read_finish_row(png_ptr);
+               return;
+            }
+            break;
+         case 1:
+            if ((png_ptr->row_number & 0x07) || png_ptr->width < 5)
+            {
+               if (dsp_row != NULL)
+                  png_combine_row(png_ptr, dsp_row,
+                     png_pass_dsp_mask[png_ptr->pass]);
+               png_read_finish_row(png_ptr);
+               return;
+            }
+            break;
+         case 2:
+            if ((png_ptr->row_number & 0x07) != 4)
+            {
+               if (dsp_row != NULL && (png_ptr->row_number & 4))
+                  png_combine_row(png_ptr, dsp_row,
+                     png_pass_dsp_mask[png_ptr->pass]);
+               png_read_finish_row(png_ptr);
+               return;
+            }
+            break;
+         case 3:
+            if ((png_ptr->row_number & 3) || png_ptr->width < 3)
+            {
+               if (dsp_row != NULL)
+                  png_combine_row(png_ptr, dsp_row,
+                     png_pass_dsp_mask[png_ptr->pass]);
+               png_read_finish_row(png_ptr);
+               return;
+            }
+            break;
+         case 4:
+            if ((png_ptr->row_number & 3) != 2)
+            {
+               if (dsp_row != NULL && (png_ptr->row_number & 2))
+                  png_combine_row(png_ptr, dsp_row,
+                     png_pass_dsp_mask[png_ptr->pass]);
+               png_read_finish_row(png_ptr);
+               return;
+            }
+            break;
+         case 5:
+            if ((png_ptr->row_number & 1) || png_ptr->width < 2)
+            {
+               if (dsp_row != NULL)
+                  png_combine_row(png_ptr, dsp_row,
+                     png_pass_dsp_mask[png_ptr->pass]);
+               png_read_finish_row(png_ptr);
+               return;
+            }
+            break;
+         case 6:
+            if (!(png_ptr->row_number & 1))
+            {
+               png_read_finish_row(png_ptr);
+               return;
+            }
+            break;
+      }
+   }
+#endif
+
+   if (!(png_ptr->mode & PNG_HAVE_IDAT))
+      png_error(png_ptr, "Invalid attempt to read row data");
+
+   png_ptr->zstream.next_out = png_ptr->row_buf;
+   png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;
+   do
+   {
+      if (!(png_ptr->zstream.avail_in))
+      {
+         while (!png_ptr->idat_size)
+         {
+            png_byte chunk_length[4];
+
+            png_crc_finish(png_ptr, 0);
+
+            png_read_data(png_ptr, chunk_length, 4);
+            png_ptr->idat_size = png_get_uint_32(chunk_length);
+
+            png_reset_crc(png_ptr);
+            png_crc_read(png_ptr, png_ptr->chunk_name, 4);
+            if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
+               png_error(png_ptr, "Not enough image data");
+         }
+         png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
+         png_ptr->zstream.next_in = png_ptr->zbuf;
+         if (png_ptr->zbuf_size > png_ptr->idat_size)
+            png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
+         png_crc_read(png_ptr, png_ptr->zbuf,
+            (png_size_t)png_ptr->zstream.avail_in);
+         png_ptr->idat_size -= png_ptr->zstream.avail_in;
+      }
+      ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
+      if (ret == Z_STREAM_END)
+      {
+         if (png_ptr->zstream.avail_out || png_ptr->zstream.avail_in ||
+            png_ptr->idat_size)
+            png_error(png_ptr, "Extra compressed data");
+         png_ptr->mode |= PNG_AFTER_IDAT;
+         png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
+         break;
+      }
+      if (ret != Z_OK)
+         png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
+                   "Decompression error");
+
+   } while (png_ptr->zstream.avail_out);
+
+   png_ptr->row_info.color_type = png_ptr->color_type;
+   png_ptr->row_info.width = png_ptr->iwidth;
+   png_ptr->row_info.channels = png_ptr->channels;
+   png_ptr->row_info.bit_depth = png_ptr->bit_depth;
+   png_ptr->row_info.pixel_depth = png_ptr->pixel_depth;
+   png_ptr->row_info.rowbytes = ((png_ptr->row_info.width *
+      (png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3);
+
+   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]));
+
+   png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf,
+      png_ptr->rowbytes + 1);
+   
+#if defined(PNG_MNG_FEATURES_SUPPORTED)
+   if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
+      (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))
+   {
+      /* Intrapixel differencing */
+      png_do_read_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1);
+   }
+#endif
+
+   if (png_ptr->transformations)
+      png_do_read_transformations(png_ptr);
+
+#if defined(PNG_READ_INTERLACING_SUPPORTED)
+   /* blow up interlaced rows to full size */
+   if (png_ptr->interlaced &&
+      (png_ptr->transformations & PNG_INTERLACE))
+   {
+      if (png_ptr->pass < 6)
+/*       old interface (pre-1.0.9):
+         png_do_read_interlace(&(png_ptr->row_info),
+            png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations);
+ */
+         png_do_read_interlace(png_ptr);
+
+      if (dsp_row != NULL)
+         png_combine_row(png_ptr, dsp_row,
+            png_pass_dsp_mask[png_ptr->pass]);
+      if (row != NULL)
+         png_combine_row(png_ptr, row,
+            png_pass_mask[png_ptr->pass]);
+   }
+   else
+#endif
+   {
+      if (row != NULL)
+         png_combine_row(png_ptr, row, 0xff);
+      if (dsp_row != NULL)
+         png_combine_row(png_ptr, dsp_row, 0xff);
+   }
+   png_read_finish_row(png_ptr);
+
+   if (png_ptr->read_row_fn != NULL)
+      (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
+}
+
+/* Read one or more rows of image data.  If the image is interlaced,
+ * and png_set_interlace_handling() has been called, the rows need to
+ * contain the contents of the rows from the previous pass.  If the
+ * image has alpha or transparency, and png_handle_alpha()[*] has been
+ * called, the rows contents must be initialized to the contents of the
+ * screen.
+ *
+ * "row" holds the actual image, and pixels are placed in it
+ * as they arrive.  If the image is displayed after each pass, it will
+ * appear to "sparkle" in.  "display_row" can be used to display a
+ * "chunky" progressive image, with finer detail added as it becomes
+ * available.  If you do not want this "chunky" display, you may pass
+ * NULL for display_row.  If you do not want the sparkle display, and
+ * you have not called png_handle_alpha(), you may pass NULL for rows.
+ * If you have called png_handle_alpha(), and the image has either an
+ * alpha channel or a transparency chunk, you must provide a buffer for
+ * rows.  In this case, you do not have to provide a display_row buffer
+ * also, but you may.  If the image is not interlaced, or if you have
+ * not called png_set_interlace_handling(), the display_row buffer will
+ * be ignored, so pass NULL to it.
+ *
+ * [*] png_handle_alpha() does not exist yet, as of libpng version 1.0.12
+ */
+
+void PNGAPI
+png_read_rows(png_structp png_ptr, png_bytepp row,
+   png_bytepp display_row, png_uint_32 num_rows)
+{
+   png_uint_32 i;
+   png_bytepp rp;
+   png_bytepp dp;
+
+   png_debug(1, "in png_read_rows\n");
+   /* save jump buffer and error functions */
+   rp = row;
+   dp = display_row;
+   if (rp != NULL && dp != NULL)
+      for (i = 0; i < num_rows; i++)
+      {
+         png_bytep rptr = *rp++;
+         png_bytep dptr = *dp++;
+
+         png_read_row(png_ptr, rptr, dptr);
+      }
+   else if(rp != NULL)
+      for (i = 0; i < num_rows; i++)
+      {
+         png_bytep rptr = *rp;
+         png_read_row(png_ptr, rptr, NULL);
+         rp++;
+      }
+   else if(dp != NULL)
+      for (i = 0; i < num_rows; i++)
+      {
+         png_bytep dptr = *dp;
+         png_read_row(png_ptr, NULL, dptr);
+         dp++;
+      }
+}
+
+/* Read the entire image.  If the image has an alpha channel or a tRNS
+ * chunk, and you have called png_handle_alpha()[*], you will need to
+ * initialize the image to the current image that PNG will be overlaying.
+ * We set the num_rows again here, in case it was incorrectly set in
+ * png_read_start_row() by a call to png_read_update_info() or
+ * png_start_read_image() if png_set_interlace_handling() wasn't called
+ * prior to either of these functions like it should have been.  You can
+ * only call this function once.  If you desire to have an image for
+ * each pass of a interlaced image, use png_read_rows() instead.
+ *
+ * [*] png_handle_alpha() does not exist yet, as of libpng version 1.0.12
+ */
+void PNGAPI
+png_read_image(png_structp png_ptr, png_bytepp image)
+{
+   png_uint_32 i,image_height;
+   int pass, j;
+   png_bytepp rp;
+
+   png_debug(1, "in png_read_image\n");
+   /* save jump buffer and error functions */
+
+#ifdef PNG_READ_INTERLACING_SUPPORTED
+   pass = png_set_interlace_handling(png_ptr);
+#else
+   if (png_ptr->interlaced)
+      png_error(png_ptr,
+        "Cannot read interlaced image -- interlace handler disabled.");
+   pass = 1;
+#endif
+
+
+   image_height=png_ptr->height;
+   png_ptr->num_rows = image_height; /* Make sure this is set correctly */
+
+   for (j = 0; j < pass; j++)
+   {
+      rp = image;
+      for (i = 0; i < image_height; i++)
+      {
+         png_read_row(png_ptr, *rp, NULL);
+         rp++;
+      }
+   }
+}
+
+/* Read the end of the PNG file.  Will not read past the end of the
+ * file, will verify the end is accurate, and will read any comments
+ * or time information at the end of the file, if info is not NULL.
+ */
+void PNGAPI
+png_read_end(png_structp png_ptr, png_infop info_ptr)
+{
+   png_byte chunk_length[4];
+   png_uint_32 length;
+
+   png_debug(1, "in png_read_end\n");
+   /* save jump buffer and error functions */
+   png_crc_finish(png_ptr, 0); /* Finish off CRC from last IDAT chunk */
+
+   do
+   {
+#ifdef PNG_USE_LOCAL_ARRAYS
+      PNG_IHDR;
+      PNG_IDAT;
+      PNG_IEND;
+      PNG_PLTE;
+#if defined(PNG_READ_bKGD_SUPPORTED)
+      PNG_bKGD;
+#endif
+#if defined(PNG_READ_cHRM_SUPPORTED)
+      PNG_cHRM;
+#endif
+#if defined(PNG_READ_gAMA_SUPPORTED)
+      PNG_gAMA;
+#endif
+#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_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_sPLT_SUPPORTED)
+      PNG_sPLT;
+#endif
+#if defined(PNG_READ_sRGB_SUPPORTED)
+      PNG_sRGB;
+#endif
+#if defined(PNG_READ_tEXt_SUPPORTED)
+      PNG_tEXt;
+#endif
+#if defined(PNG_READ_tIME_SUPPORTED)
+      PNG_tIME;
+#endif
+#if defined(PNG_READ_tRNS_SUPPORTED)
+      PNG_tRNS;
+#endif
+#if defined(PNG_READ_zTXt_SUPPORTED)
+      PNG_zTXt;
+#endif
+#endif /* PNG_GLOBAL_ARRAYS */
+
+      png_read_data(png_ptr, chunk_length, 4);
+      length = png_get_uint_32(chunk_length);
+
+      png_reset_crc(png_ptr);
+      png_crc_read(png_ptr, png_ptr->chunk_name, 4);
+
+      png_debug1(0, "Reading %s chunk.\n", png_ptr->chunk_name);
+
+      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
+          * read, but not after other chunks have been read.
+          */
+         if (length > 0 || png_ptr->mode & PNG_AFTER_IDAT)
+            png_error(png_ptr, "Too many IDAT's found");
+         png_crc_finish(png_ptr, length);
+      }
+      else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
+         png_handle_PLTE(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);
+#endif
+#if defined(PNG_READ_cHRM_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))
+         png_handle_cHRM(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_gAMA_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
+         png_handle_gAMA(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_hIST_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))
+         png_handle_hIST(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_oFFs_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))
+         png_handle_oFFs(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_pCAL_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4))
+         png_handle_pCAL(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_sCAL_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4))
+         png_handle_sCAL(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_pHYs_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))
+         png_handle_pHYs(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_sBIT_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))
+         png_handle_sBIT(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_sRGB_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4))
+         png_handle_sRGB(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_iCCP_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4))
+         png_handle_iCCP(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_sPLT_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4))
+         png_handle_sPLT(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_tEXt_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4))
+         png_handle_tEXt(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_tIME_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
+         png_handle_tIME(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_tRNS_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
+         png_handle_tRNS(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_zTXt_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))
+         png_handle_zTXt(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_iTXt_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4))
+         png_handle_iTXt(png_ptr, info_ptr, length);
+#endif
+      else
+         png_handle_unknown(png_ptr, info_ptr, length);
+   } while (!(png_ptr->mode & PNG_HAVE_IEND));
+}
+
+/* free all memory used by the read */
+void PNGAPI
+png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,
+   png_infopp end_info_ptr_ptr)
+{
+   png_structp png_ptr = NULL;
+   png_infop info_ptr = NULL, end_info_ptr = NULL;
+#ifdef PNG_USER_MEM_SUPPORTED
+   png_free_ptr free_fn = NULL;
+   png_voidp mem_ptr = NULL;
+#endif
+
+   png_debug(1, "in png_destroy_read_struct\n");
+   /* save jump buffer and error functions */
+   if (png_ptr_ptr != NULL)
+      png_ptr = *png_ptr_ptr;
+
+   if (info_ptr_ptr != NULL)
+      info_ptr = *info_ptr_ptr;
+
+   if (end_info_ptr_ptr != NULL)
+      end_info_ptr = *end_info_ptr_ptr;
+
+#ifdef PNG_USER_MEM_SUPPORTED
+   free_fn = png_ptr->free_fn;
+   mem_ptr = png_ptr->mem_ptr;
+#endif
+
+   png_read_destroy(png_ptr, info_ptr, end_info_ptr);
+
+   if (info_ptr != NULL)
+   {
+#if defined(PNG_TEXT_SUPPORTED)
+      png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, -1);
+#endif
+
+#ifdef PNG_USER_MEM_SUPPORTED
+      png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn,
+          (png_voidp)mem_ptr);
+#else
+      png_destroy_struct((png_voidp)info_ptr);
+#endif
+      *info_ptr_ptr = (png_infop)NULL;
+   }
+
+   if (end_info_ptr != NULL)
+   {
+#if defined(PNG_READ_TEXT_SUPPORTED)
+      png_free_data(png_ptr, end_info_ptr, PNG_FREE_TEXT, -1);
+#endif
+#ifdef PNG_USER_MEM_SUPPORTED
+      png_destroy_struct_2((png_voidp)end_info_ptr, (png_free_ptr)free_fn,
+         (png_voidp)mem_ptr);
+#else
+      png_destroy_struct((png_voidp)end_info_ptr);
+#endif
+      *end_info_ptr_ptr = (png_infop)NULL;
+   }
+
+   if (png_ptr != NULL)
+   {
+#ifdef PNG_USER_MEM_SUPPORTED
+      png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn,
+          (png_voidp)mem_ptr);
+#else
+      png_destroy_struct((png_voidp)png_ptr);
+#endif
+      *png_ptr_ptr = (png_structp)NULL;
+   }
+}
+
+/* free all memory used by the read (old method) */
+void /* PRIVATE */
+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;
+#ifdef PNG_USER_MEM_SUPPORTED
+   png_free_ptr free_fn;
+#endif
+
+   png_debug(1, "in png_read_destroy\n");
+   /* save jump buffer and error functions */
+   if (info_ptr != NULL)
+      png_info_destroy(png_ptr, info_ptr);
+
+   if (end_info_ptr != NULL)
+      png_info_destroy(png_ptr, end_info_ptr);
+
+   png_free(png_ptr, png_ptr->zbuf);
+   png_free(png_ptr, png_ptr->row_buf);
+   png_free(png_ptr, png_ptr->prev_row);
+#if defined(PNG_READ_DITHER_SUPPORTED)
+   png_free(png_ptr, png_ptr->palette_lookup);
+   png_free(png_ptr, png_ptr->dither_index);
+#endif
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+   png_free(png_ptr, png_ptr->gamma_table);
+#endif
+#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+   png_free(png_ptr, png_ptr->gamma_from_1);
+   png_free(png_ptr, png_ptr->gamma_to_1);
+#endif
+#ifdef PNG_FREE_ME_SUPPORTED
+   if (png_ptr->free_me & PNG_FREE_PLTE)
+      png_zfree(png_ptr, png_ptr->palette);
+   png_ptr->free_me &= ~PNG_FREE_PLTE;
+#else
+   if (png_ptr->flags & PNG_FLAG_FREE_PLTE)
+      png_zfree(png_ptr, png_ptr->palette);
+   png_ptr->flags &= ~PNG_FLAG_FREE_PLTE;
+#endif
+#if defined(PNG_tRNS_SUPPORTED) || \
+    defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+#ifdef PNG_FREE_ME_SUPPORTED
+   if (png_ptr->free_me & PNG_FREE_TRNS)
+      png_free(png_ptr, png_ptr->trans);
+   png_ptr->free_me &= ~PNG_FREE_TRNS;
+#else
+   if (png_ptr->flags & PNG_FLAG_FREE_TRNS)
+      png_free(png_ptr, png_ptr->trans);
+   png_ptr->flags &= ~PNG_FLAG_FREE_TRNS;
+#endif
+#endif
+#if defined(PNG_READ_hIST_SUPPORTED)
+#ifdef PNG_FREE_ME_SUPPORTED
+   if (png_ptr->free_me & PNG_FREE_HIST)
+      png_free(png_ptr, png_ptr->hist);
+   png_ptr->free_me &= ~PNG_FREE_HIST;
+#else
+   if (png_ptr->flags & PNG_FLAG_FREE_HIST)
+      png_free(png_ptr, png_ptr->hist);
+   png_ptr->flags &= ~PNG_FLAG_FREE_HIST;
+#endif
+#endif
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+   if (png_ptr->gamma_16_table != NULL)
+   {
+      int i;
+      int istop = (1 << (8 - png_ptr->gamma_shift));
+      for (i = 0; i < istop; i++)
+      {
+         png_free(png_ptr, png_ptr->gamma_16_table[i]);
+      }
+   png_free(png_ptr, png_ptr->gamma_16_table);
+   }
+#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+   if (png_ptr->gamma_16_from_1 != NULL)
+   {
+      int i;
+      int istop = (1 << (8 - png_ptr->gamma_shift));
+      for (i = 0; i < istop; i++)
+      {
+         png_free(png_ptr, png_ptr->gamma_16_from_1[i]);
+      }
+   png_free(png_ptr, png_ptr->gamma_16_from_1);
+   }
+   if (png_ptr->gamma_16_to_1 != NULL)
+   {
+      int i;
+      int istop = (1 << (8 - png_ptr->gamma_shift));
+      for (i = 0; i < istop; i++)
+      {
+         png_free(png_ptr, png_ptr->gamma_16_to_1[i]);
+      }
+   png_free(png_ptr, png_ptr->gamma_16_to_1);
+   }
+#endif
+#endif
+#if defined(PNG_TIME_RFC1123_SUPPORTED)
+   png_free(png_ptr, png_ptr->time_buffer);
+#endif
+
+   inflateEnd(&png_ptr->zstream);
+#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
+   png_free(png_ptr, png_ptr->save_buffer);
+#endif
+
+   /* 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;
+   error_ptr = png_ptr->error_ptr;
+#ifdef PNG_USER_MEM_SUPPORTED
+   free_fn = png_ptr->free_fn;
+#endif
+
+   png_memset(png_ptr, 0, sizeof (png_struct));
+
+   png_ptr->error_fn = error_fn;
+   png_ptr->warning_fn = warning_fn;
+   png_ptr->error_ptr = error_ptr;
+#ifdef PNG_USER_MEM_SUPPORTED
+   png_ptr->free_fn = free_fn;
+#endif
+
+#ifdef PNG_SETJMP_SUPPORTED
+   png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
+#endif
+
+}
+
+void PNGAPI
+png_set_read_status_fn(png_structp png_ptr, png_read_status_ptr read_row_fn)
+{
+   png_ptr->read_row_fn = read_row_fn;
+}
+
+#if defined(PNG_INFO_IMAGE_SUPPORTED)
+void PNGAPI
+png_read_png(png_structp png_ptr, png_infop info_ptr,
+                           int transforms,
+                           voidp params)
+{
+   int row;
+
+#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) && !defined(PNG_READ_EXPAND_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_ptr->bit_depth < 8) ||
+           (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ||
+           (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 (i.e., you selected such a transform above).
+    */
+   png_read_update_info(png_ptr, info_ptr);
+
+   /* -------------- image transformations end here ------------------- */
+
+#ifdef PNG_FREE_ME_SUPPORTED
+   png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
+#endif
+   if(info_ptr->row_pointers == NULL)
+   {
+      info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr,
+         info_ptr->height * sizeof(png_bytep));
+#ifdef PNG_FREE_ME_SUPPORTED
+      info_ptr->free_me |= PNG_FREE_ROWS;
+#endif
+      for (row = 0; row < (int)info_ptr->height; row++)
+      {
+         info_ptr->row_pointers[row] = (png_bytep)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);
+
+   if(transforms == 0 || params == NULL)
+      /* quiet compiler warnings */ return;
+
+}
+#endif
diff --git a/Utilities/ITK/Utilities/png/pngrio.c b/Utilities/ITK/Utilities/png/pngrio.c
new file mode 100644
index 0000000000..707a139d40
--- /dev/null
+++ b/Utilities/ITK/Utilities/png/pngrio.c
@@ -0,0 +1,162 @@
+
+/* pngrio.c - functions for data input
+ *
+ * libpng 1.0.12 - June 8, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This file provides a location for all input.  Users who need
+ * special handling are expected to write a function that has the same
+ * arguments as this and performs a similar function, but that possibly
+ * has a different input method.  Note that you shouldn't change this
+ * function, but rather write a replacement function and then make
+ * libpng use it at run time with png_set_read_fn(...).
+ */
+
+#define PNG_INTERNAL
+#include "png.h"
+
+/* Read the data from whatever input you are using.  The default routine
+   reads from a file pointer.  Note that this routine sometimes gets called
+   with very small lengths, so you should implement some kind of simple
+   buffering if you are using unbuffered reads.  This should never be asked
+   to read more then 64K on a 16 bit machine. */
+void /* PRIVATE */
+png_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+   png_debug1(4,"reading %d bytes\n", (int)length);
+   if (png_ptr->read_data_fn != NULL)
+      (*(png_ptr->read_data_fn))(png_ptr, data, length);
+   else
+      png_error(png_ptr, "Call to NULL read function");
+}
+
+#if !defined(PNG_NO_STDIO)
+/* This is the function that does the actual reading of data.  If you are
+   not reading from a standard C stream, you should create a replacement
+   read_data function and use it at run time with png_set_read_fn(), rather
+   than changing the library. */
+#ifndef USE_FAR_KEYWORD
+static void /* PRIVATE */
+png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+   png_size_t check;
+
+   /* fread() returns 0 on error, so it is OK to store this in a png_size_t
+    * instead of an int, which is what fread() actually returns.
+    */
+#if defined(_WIN32_WCE)
+   if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) )
+      check = 0;
+#else
+   check = (png_size_t)fread(data, (png_size_t)1, length,
+      (png_FILE_p)png_ptr->io_ptr);
+#endif
+
+   if (check != length)
+      png_error(png_ptr, "Read Error");
+}
+#else
+/* this is the model-independent version. Since the standard I/O library
+   can't handle far buffers in the medium and small models, we have to copy
+   the data.
+*/
+
+#define NEAR_BUF_SIZE 1024
+#define MIN(a,b) (a <= b ? a : b)
+
+static void /* PRIVATE */
+png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+   int check;
+   png_byte *n_data;
+   png_FILE_p io_ptr;
+
+   /* Check if data really is near. If so, use usual code. */
+   n_data = (png_byte *)CVT_PTR_NOCHECK(data);
+   io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
+   if ((png_bytep)n_data == data)
+   {
+#if defined(_WIN32_WCE)
+      if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) )
+         check = 0;
+#else
+      check = fread(n_data, 1, length, io_ptr);
+#endif
+   }
+   else
+   {
+      png_byte buf[NEAR_BUF_SIZE];
+      png_size_t read, remaining, err;
+      check = 0;
+      remaining = length;
+      do
+      {
+         read = MIN(NEAR_BUF_SIZE, remaining);
+#if defined(_WIN32_WCE)
+         if ( !ReadFile((HANDLE)(io_ptr), buf, read, &err, NULL) )
+            err = 0;
+#else
+         err = fread(buf, (png_size_t)1, read, io_ptr);
+#endif
+         png_memcpy(data, buf, read); /* copy far buffer to near buffer */
+         if(err != read)
+            break;
+         else
+            check += err;
+         data += read;
+         remaining -= read;
+      }
+      while (remaining != 0);
+   }
+   if ((png_uint_32)check != (png_uint_32)length)
+      png_error(png_ptr, "read Error");
+}
+#endif
+#endif
+
+/* This function allows the application to supply a new input function
+   for libpng if standard C streams aren't being used.
+
+   This function takes as its arguments:
+   png_ptr      - pointer to a png input data structure
+   io_ptr       - pointer to user supplied structure containing info about
+                  the input functions.  May be NULL.
+   read_data_fn - pointer to a new input function that takes as its
+                  arguments a pointer to a png_struct, a pointer to
+                  a location where input data can be stored, and a 32-bit
+                  unsigned int that is the number of bytes to be read.
+                  To exit and output any fatal error messages the new write
+                  function should call png_error(png_ptr, "Error msg"). */
+void PNGAPI
+png_set_read_fn(png_structp png_ptr, png_voidp io_ptr,
+   png_rw_ptr read_data_fn)
+{
+   png_ptr->io_ptr = io_ptr;
+
+#if !defined(PNG_NO_STDIO)
+   if (read_data_fn != NULL)
+      png_ptr->read_data_fn = read_data_fn;
+   else
+      png_ptr->read_data_fn = png_default_read_data;
+#else
+   png_ptr->read_data_fn = read_data_fn;
+#endif
+
+   /* It is an error to write to a read device */
+   if (png_ptr->write_data_fn != NULL)
+   {
+      png_ptr->write_data_fn = NULL;
+      png_warning(png_ptr,
+         "It's an error to set both read_data_fn and write_data_fn in the ");
+      png_warning(png_ptr,
+         "same structure.  Resetting write_data_fn to NULL.");
+   }
+
+#if defined(PNG_WRITE_FLUSH_SUPPORTED)
+   png_ptr->output_flush_fn = NULL;
+#endif
+}
+
diff --git a/Utilities/ITK/Utilities/png/pngrtran.c b/Utilities/ITK/Utilities/png/pngrtran.c
new file mode 100644
index 0000000000..ef070c88ed
--- /dev/null
+++ b/Utilities/ITK/Utilities/png/pngrtran.c
@@ -0,0 +1,4115 @@
+
+/* pngrtran.c - transforms the data in a row for PNG readers
+ *
+ * libpng 1.0.12 - June 8, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This file contains functions optionally called by an application
+ * in order to tell libpng how to handle data when reading a PNG.
+ * Transformations that are used in both reading and writing are
+ * in pngtrans.c.
+ */
+
+#define PNG_INTERNAL
+#include "png.h"
+
+/* Set the action on getting a CRC error for an ancillary or critical chunk. */
+void PNGAPI
+png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action)
+{
+   png_debug(1, "in png_set_crc_action\n");
+   /* Tell libpng how we react to CRC errors in critical chunks */
+   switch (crit_action)
+   {
+      case PNG_CRC_NO_CHANGE:                        /* leave setting as is */
+         break;
+      case PNG_CRC_WARN_USE:                               /* warn/use data */
+         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
+         png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;
+         break;
+      case PNG_CRC_QUIET_USE:                             /* quiet/use data */
+         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
+         png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE |
+                           PNG_FLAG_CRC_CRITICAL_IGNORE;
+         break;
+      case PNG_CRC_WARN_DISCARD:    /* not a valid action for critical data */
+         png_warning(png_ptr, "Can't discard critical data on CRC error.");
+      case PNG_CRC_ERROR_QUIT:                                /* error/quit */
+      case PNG_CRC_DEFAULT:
+      default:
+         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
+         break;
+   }
+
+   switch (ancil_action)
+   {
+      case PNG_CRC_NO_CHANGE:                       /* leave setting as is */
+         break;
+      case PNG_CRC_WARN_USE:                              /* warn/use data */
+         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
+         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE;
+         break;
+      case PNG_CRC_QUIET_USE:                            /* quiet/use data */
+         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
+         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE |
+                           PNG_FLAG_CRC_ANCILLARY_NOWARN;
+         break;
+      case PNG_CRC_ERROR_QUIT:                               /* error/quit */
+         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
+         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN;
+         break;
+      case PNG_CRC_WARN_DISCARD:                      /* warn/discard data */
+      case PNG_CRC_DEFAULT:
+      default:
+         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
+         break;
+   }
+}
+
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
+    defined(PNG_FLOATING_POINT_SUPPORTED)
+/* handle alpha and tRNS via a background color */
+void PNGAPI
+png_set_background(png_structp png_ptr,
+   png_color_16p background_color, int background_gamma_code,
+   int need_expand, double background_gamma)
+{
+   png_debug(1, "in png_set_background\n");
+   if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
+   {
+      png_warning(png_ptr, "Application must supply a known background gamma");
+      return;
+   }
+
+   png_ptr->transformations |= PNG_BACKGROUND;
+   png_memcpy(&(png_ptr->background), background_color, sizeof(png_color_16));
+   png_ptr->background_gamma = (float)background_gamma;
+   png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
+   png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0);
+
+   /* Note:  if need_expand is set and color_type is either RGB or RGB_ALPHA
+    * (in which case need_expand is superfluous anyway), the background color
+    * might actually be gray yet not be flagged as such. This is not a problem
+    * for the current code, which uses PNG_BACKGROUND_IS_GRAY only to
+    * decide when to do the png_do_gray_to_rgb() transformation.
+    */
+   if ((need_expand && !(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) ||
+       (!need_expand && background_color->red == background_color->green &&
+        background_color->red == background_color->blue))
+      png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
+}
+#endif
+
+#if defined(PNG_READ_16_TO_8_SUPPORTED)
+/* strip 16 bit depth files to 8 bit depth */
+void PNGAPI
+png_set_strip_16(png_structp png_ptr)
+{
+   png_debug(1, "in png_set_strip_16\n");
+   png_ptr->transformations |= PNG_16_TO_8;
+}
+#endif
+
+#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
+void PNGAPI
+png_set_strip_alpha(png_structp png_ptr)
+{
+   png_debug(1, "in png_set_strip_alpha\n");
+   png_ptr->transformations |= PNG_STRIP_ALPHA;
+}
+#endif
+
+#if defined(PNG_READ_DITHER_SUPPORTED)
+/* Dither file to 8 bit.  Supply a palette, the current number
+ * of elements in the palette, the maximum number of elements
+ * allowed, and a histogram if possible.  If the current number
+ * of colors is greater then the maximum number, the palette will be
+ * modified to fit in the maximum number.  "full_dither" indicates
+ * whether we need a dithering cube set up for RGB images, or if we
+ * simply are reducing the number of colors in a paletted image.
+ */
+
+typedef struct png_dsort_struct
+{
+   struct png_dsort_struct FAR * next;
+   png_byte left;
+   png_byte right;
+} png_dsort;
+typedef png_dsort FAR *       png_dsortp;
+typedef png_dsort FAR * FAR * png_dsortpp;
+
+void PNGAPI
+png_set_dither(png_structp png_ptr, png_colorp palette,
+   int num_palette, int maximum_colors, png_uint_16p histogram,
+   int full_dither)
+{
+   png_debug(1, "in png_set_dither\n");
+   png_ptr->transformations |= PNG_DITHER;
+
+   if (!full_dither)
+   {
+      int i;
+
+      png_ptr->dither_index = (png_bytep)png_malloc(png_ptr,
+         (png_uint_32)(num_palette * sizeof (png_byte)));
+      for (i = 0; i < num_palette; i++)
+         png_ptr->dither_index[i] = (png_byte)i;
+   }
+
+   if (num_palette > maximum_colors)
+   {
+      if (histogram != NULL)
+      {
+         /* This is easy enough, just throw out the least used colors.
+            Perhaps not the best solution, but good enough. */
+
+         int i;
+         png_bytep sort;
+
+         /* initialize an array to sort colors */
+         sort = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_palette
+            * sizeof (png_byte)));
+
+         /* initialize the sort array */
+         for (i = 0; i < num_palette; i++)
+            sort[i] = (png_byte)i;
+
+         /* Find the least used palette entries by starting a
+            bubble sort, and running it until we have sorted
+            out enough colors.  Note that we don't care about
+            sorting all the colors, just finding which are
+            least used. */
+
+         for (i = num_palette - 1; i >= maximum_colors; i--)
+         {
+            int done; /* to stop early if the list is pre-sorted */
+            int j;
+
+            done = 1;
+            for (j = 0; j < i; j++)
+            {
+               if (histogram[sort[j]] < histogram[sort[j + 1]])
+               {
+                  png_byte t;
+
+                  t = sort[j];
+                  sort[j] = sort[j + 1];
+                  sort[j + 1] = t;
+                  done = 0;
+               }
+            }
+            if (done)
+               break;
+         }
+
+         /* swap the palette around, and set up a table, if necessary */
+         if (full_dither)
+         {
+            int j = num_palette;
+
+            /* put all the useful colors within the max, but don't
+               move the others */
+            for (i = 0; i < maximum_colors; i++)
+            {
+               if ((int)sort[i] >= maximum_colors)
+               {
+                  do
+                     j--;
+                  while ((int)sort[j] >= maximum_colors);
+                  palette[i] = palette[j];
+               }
+            }
+         }
+         else
+         {
+            int j = num_palette;
+
+            /* move all the used colors inside the max limit, and
+               develop a translation table */
+            for (i = 0; i < maximum_colors; i++)
+            {
+               /* only move the colors we need to */
+               if ((int)sort[i] >= maximum_colors)
+               {
+                  png_color tmp_color;
+
+                  do
+                     j--;
+                  while ((int)sort[j] >= maximum_colors);
+
+                  tmp_color = palette[j];
+                  palette[j] = palette[i];
+                  palette[i] = tmp_color;
+                  /* indicate where the color went */
+                  png_ptr->dither_index[j] = (png_byte)i;
+                  png_ptr->dither_index[i] = (png_byte)j;
+               }
+            }
+
+            /* find closest color for those colors we are not using */
+            for (i = 0; i < num_palette; i++)
+            {
+               if ((int)png_ptr->dither_index[i] >= maximum_colors)
+               {
+                  int min_d, k, min_k, d_index;
+
+                  /* find the closest color to one we threw out */
+                  d_index = png_ptr->dither_index[i];
+                  min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
+                  for (k = 1, min_k = 0; k < maximum_colors; k++)
+                  {
+                     int d;
+
+                     d = PNG_COLOR_DIST(palette[d_index], palette[k]);
+
+                     if (d < min_d)
+                     {
+                        min_d = d;
+                        min_k = k;
+                     }
+                  }
+                  /* point to closest color */
+                  png_ptr->dither_index[i] = (png_byte)min_k;
+               }
+            }
+         }
+         png_free(png_ptr, sort);
+      }
+      else
+      {
+         /* This is much harder to do simply (and quickly).  Perhaps
+            we need to go through a median cut routine, but those
+            don't always behave themselves with only a few colors
+            as input.  So we will just find the closest two colors,
+            and throw out one of them (chosen somewhat randomly).
+            [We don't understand this at all, so if someone wants to
+             work on improving it, be our guest - AED, GRP]
+            */
+         int i;
+         int max_d;
+         int num_new_palette;
+         png_dsortpp hash;
+         png_bytep index_to_palette;
+            /* where the original index currently is in the palette */
+         png_bytep palette_to_index;
+            /* which original index points to this palette color */
+
+         /* initialize palette index arrays */
+         index_to_palette = (png_bytep)png_malloc(png_ptr,
+            (png_uint_32)(num_palette * sizeof (png_byte)));
+         palette_to_index = (png_bytep)png_malloc(png_ptr,
+            (png_uint_32)(num_palette * sizeof (png_byte)));
+
+         /* initialize the sort array */
+         for (i = 0; i < num_palette; i++)
+         {
+            index_to_palette[i] = (png_byte)i;
+            palette_to_index[i] = (png_byte)i;
+         }
+
+         hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 *
+            sizeof (png_dsortp)));
+         for (i = 0; i < 769; i++)
+            hash[i] = NULL;
+/*         png_memset(hash, 0, 769 * sizeof (png_dsortp)); */
+
+         num_new_palette = num_palette;
+
+         /* initial wild guess at how far apart the farthest pixel
+            pair we will be eliminating will be.  Larger
+            numbers mean more areas will be allocated, Smaller
+            numbers run the risk of not saving enough data, and
+            having to do this all over again.
+
+            I have not done extensive checking on this number.
+            */
+         max_d = 96;
+
+         while (num_new_palette > maximum_colors)
+         {
+            for (i = 0; i < num_new_palette - 1; i++)
+            {
+               int j;
+
+               for (j = i + 1; j < num_new_palette; j++)
+               {
+                  int d;
+
+                  d = PNG_COLOR_DIST(palette[i], palette[j]);
+
+                  if (d <= max_d)
+                  {
+                     png_dsortp t;
+
+                     t = (png_dsortp)png_malloc(png_ptr, (png_uint_32)(sizeof
+                         (png_dsort)));
+                     t->next = hash[d];
+                     t->left = (png_byte)i;
+                     t->right = (png_byte)j;
+                     hash[d] = t;
+                  }
+               }
+            }
+
+            for (i = 0; i <= max_d; i++)
+            {
+               if (hash[i] != NULL)
+               {
+                  png_dsortp p;
+
+                  for (p = hash[i]; p; p = p->next)
+                  {
+                     if ((int)index_to_palette[p->left] < num_new_palette &&
+                        (int)index_to_palette[p->right] < num_new_palette)
+                     {
+                        int j, next_j;
+
+                        if (num_new_palette & 0x01)
+                        {
+                           j = p->left;
+                           next_j = p->right;
+                        }
+                        else
+                        {
+                           j = p->right;
+                           next_j = p->left;
+                        }
+
+                        num_new_palette--;
+                        palette[index_to_palette[j]] = palette[num_new_palette];
+                        if (!full_dither)
+                        {
+                           int k;
+
+                           for (k = 0; k < num_palette; k++)
+                           {
+                              if (png_ptr->dither_index[k] ==
+                                 index_to_palette[j])
+                                 png_ptr->dither_index[k] =
+                                    index_to_palette[next_j];
+                              if ((int)png_ptr->dither_index[k] ==
+                                 num_new_palette)
+                                 png_ptr->dither_index[k] =
+                                    index_to_palette[j];
+                           }
+                        }
+
+                        index_to_palette[palette_to_index[num_new_palette]] =
+                           index_to_palette[j];
+                        palette_to_index[index_to_palette[j]] =
+                           palette_to_index[num_new_palette];
+
+                        index_to_palette[j] = (png_byte)num_new_palette;
+                        palette_to_index[num_new_palette] = (png_byte)j;
+                     }
+                     if (num_new_palette <= maximum_colors)
+                        break;
+                  }
+                  if (num_new_palette <= maximum_colors)
+                     break;
+               }
+            }
+
+            for (i = 0; i < 769; i++)
+            {
+               if (hash[i] != NULL)
+               {
+                  png_dsortp p = hash[i];
+                  while (p)
+                  {
+                     png_dsortp t;
+
+                     t = p->next;
+                     png_free(png_ptr, p);
+                     p = t;
+                  }
+               }
+               hash[i] = 0;
+            }
+            max_d += 96;
+         }
+         png_free(png_ptr, hash);
+         png_free(png_ptr, palette_to_index);
+         png_free(png_ptr, index_to_palette);
+      }
+      num_palette = maximum_colors;
+   }
+   if (png_ptr->palette == NULL)
+   {
+      png_ptr->palette = palette;
+   }
+   png_ptr->num_palette = (png_uint_16)num_palette;
+
+   if (full_dither)
+   {
+      int i;
+      png_bytep distance;
+      int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS +
+         PNG_DITHER_BLUE_BITS;
+      int num_red = (1 << PNG_DITHER_RED_BITS);
+      int num_green = (1 << PNG_DITHER_GREEN_BITS);
+      int num_blue = (1 << PNG_DITHER_BLUE_BITS);
+      png_size_t num_entries = ((png_size_t)1 << total_bits);
+
+      png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr,
+         (png_uint_32)(num_entries * sizeof (png_byte)));
+
+      png_memset(png_ptr->palette_lookup, 0, num_entries * sizeof (png_byte));
+
+      distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
+         sizeof(png_byte)));
+
+      png_memset(distance, 0xff, num_entries * sizeof(png_byte));
+
+      for (i = 0; i < num_palette; i++)
+      {
+         int ir, ig, ib;
+         int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS));
+         int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS));
+         int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS));
+
+         for (ir = 0; ir < num_red; ir++)
+         {
+            int dr = abs(ir - r);
+            int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS));
+
+            for (ig = 0; ig < num_green; ig++)
+            {
+               int dg = abs(ig - g);
+               int dt = dr + dg;
+               int dm = ((dr > dg) ? dr : dg);
+               int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS);
+
+               for (ib = 0; ib < num_blue; ib++)
+               {
+                  int d_index = index_g | ib;
+                  int db = abs(ib - b);
+                  int dmax = ((dm > db) ? dm : db);
+                  int d = dmax + dt + db;
+
+                  if (d < (int)distance[d_index])
+                  {
+                     distance[d_index] = (png_byte)d;
+                     png_ptr->palette_lookup[d_index] = (png_byte)i;
+                  }
+               }
+            }
+         }
+      }
+
+      png_free(png_ptr, distance);
+   }
+}
+#endif
+
+#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
+/* Transform the image from the file_gamma to the screen_gamma.  We
+ * only do transformations on images where the file_gamma and screen_gamma
+ * are not close reciprocals, otherwise it slows things down slightly, and
+ * also needlessly introduces small errors.
+ */
+void PNGAPI
+png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
+{
+   png_debug(1, "in png_set_gamma\n");
+   if (fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD)
+      png_ptr->transformations |= PNG_GAMMA;
+   png_ptr->gamma = (float)file_gamma;
+   png_ptr->screen_gamma = (float)scrn_gamma;
+}
+#endif
+
+#if defined(PNG_READ_EXPAND_SUPPORTED)
+/* Expand paletted images to RGB, expand grayscale images of
+ * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
+ * to alpha channels.
+ */
+void PNGAPI
+png_set_expand(png_structp png_ptr)
+{
+   png_debug(1, "in png_set_expand\n");
+   png_ptr->transformations |= PNG_EXPAND;
+}
+
+/* GRR 19990627:  the following three functions currently are identical
+ *  to png_set_expand().  However, it is entirely reasonable that someone
+ *  might wish to expand an indexed image to RGB but *not* expand a single,
+ *  fully transparent palette entry to a full alpha channel--perhaps instead
+ *  convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
+ *  the transparent color with a particular RGB value, or drop tRNS entirely.
+ *  IOW, a future version of the library may make the transformations flag
+ *  a bit more fine-grained, with separate bits for each of these three
+ *  functions.
+ *
+ *  More to the point, these functions make it obvious what libpng will be
+ *  doing, whereas "expand" can (and does) mean any number of things.
+ */
+
+/* Expand paletted images to RGB. */
+void PNGAPI
+png_set_palette_to_rgb(png_structp png_ptr)
+{
+   png_debug(1, "in png_set_expand\n");
+   png_ptr->transformations |= PNG_EXPAND;
+}
+
+/* Expand grayscale images of less than 8-bit depth to 8 bits. */
+void PNGAPI
+png_set_gray_1_2_4_to_8(png_structp png_ptr)
+{
+   png_debug(1, "in png_set_expand\n");
+   png_ptr->transformations |= PNG_EXPAND;
+}
+
+/* Expand tRNS chunks to alpha channels. */
+void PNGAPI
+png_set_tRNS_to_alpha(png_structp png_ptr)
+{
+   png_debug(1, "in png_set_expand\n");
+   png_ptr->transformations |= PNG_EXPAND;
+}
+#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
+
+#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
+void PNGAPI
+png_set_gray_to_rgb(png_structp png_ptr)
+{
+   png_debug(1, "in png_set_gray_to_rgb\n");
+   png_ptr->transformations |= PNG_GRAY_TO_RGB;
+}
+#endif
+
+#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+#if defined(PNG_FLOATING_POINT_SUPPORTED)
+/* Convert a RGB image to a grayscale of the same width.  This allows us,
+ * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
+ */
+
+void PNGAPI
+png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
+   double green)
+{
+      int red_fixed = (int)((float)red*100000.0 + 0.5);
+      int green_fixed = (int)((float)green*100000.0 + 0.5);
+      png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed);
+}
+#endif
+
+void PNGAPI
+png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
+   png_fixed_point red, png_fixed_point green)
+{
+   png_debug(1, "in png_set_rgb_to_gray\n");
+   switch(error_action)
+   {
+      case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY;
+              break;
+      case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
+              break;
+      case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
+   }
+   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+#if defined(PNG_READ_EXPAND_SUPPORTED)
+      png_ptr->transformations |= PNG_EXPAND;
+#else
+   {
+      png_warning(png_ptr, "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED.");
+      png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
+   }
+#endif
+   {
+      png_uint_16 red_int, green_int;
+      if(red < 0 || green < 0)
+      {
+         red_int   =  6968; /* .212671 * 32768 + .5 */
+         green_int = 23434; /* .715160 * 32768 + .5 */
+      }
+      else if(red + green < 100000L)
+      {
+        red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L);
+        green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L);
+      }
+      else
+      {
+         png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
+         red_int   =  6968;
+         green_int = 23434;
+      }
+      png_ptr->rgb_to_gray_red_coeff   = red_int;
+      png_ptr->rgb_to_gray_green_coeff = green_int;
+      png_ptr->rgb_to_gray_blue_coeff  = (png_uint_16)(32768-red_int-green_int);
+   }
+}
+#endif
+
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
+    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
+    defined(PNG_LEGACY_SUPPORTED)
+void PNGAPI
+png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
+   read_user_transform_fn)
+{
+   png_debug(1, "in png_set_read_user_transform_fn\n");
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
+   png_ptr->transformations |= PNG_USER_TRANSFORM;
+   png_ptr->read_user_transform_fn = read_user_transform_fn;
+#endif
+#ifdef PNG_LEGACY_SUPPORTED
+   if(read_user_transform_fn)
+      png_warning(png_ptr,
+        "This version of libpng does not support user transforms");
+#endif
+}
+#endif
+
+/* Initialize everything needed for the read.  This includes modifying
+ * the palette.
+ */
+void /* PRIVATE */
+png_init_read_transformations(png_structp png_ptr)
+{
+   png_debug(1, "in png_init_read_transformations\n");
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   if(png_ptr != NULL)
+#endif
+  {
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \
+ || defined(PNG_READ_GAMMA_SUPPORTED)
+   int color_type = png_ptr->color_type;
+#endif
+
+#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
+   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
+       (png_ptr->transformations & PNG_EXPAND))
+   {
+      if (!(color_type & PNG_COLOR_MASK_COLOR))  /* i.e., GRAY or GRAY_ALPHA */
+      {
+         /* expand background chunk. */
+         switch (png_ptr->bit_depth)
+         {
+            case 1:
+               png_ptr->background.gray *= (png_uint_16)0xff;
+               png_ptr->background.red = png_ptr->background.green =
+               png_ptr->background.blue = png_ptr->background.gray;
+               break;
+            case 2:
+               png_ptr->background.gray *= (png_uint_16)0x55;
+               png_ptr->background.red = png_ptr->background.green =
+               png_ptr->background.blue = png_ptr->background.gray;
+               break;
+            case 4:
+               png_ptr->background.gray *= (png_uint_16)0x11;
+               png_ptr->background.red = png_ptr->background.green =
+               png_ptr->background.blue = png_ptr->background.gray;
+               break;
+            case 8:
+            case 16:
+               png_ptr->background.red = png_ptr->background.green =
+               png_ptr->background.blue = png_ptr->background.gray;
+               break;
+         }
+      }
+      else if (color_type == PNG_COLOR_TYPE_PALETTE)
+      {
+         png_ptr->background.red   =
+            png_ptr->palette[png_ptr->background.index].red;
+         png_ptr->background.green =
+            png_ptr->palette[png_ptr->background.index].green;
+         png_ptr->background.blue  =
+            png_ptr->palette[png_ptr->background.index].blue;
+
+#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
+        if (png_ptr->transformations & PNG_INVERT_ALPHA)
+        {
+#if defined(PNG_READ_EXPAND_SUPPORTED)
+           if (!(png_ptr->transformations & PNG_EXPAND))
+#endif
+           {
+           /* invert the alpha channel (in tRNS) unless the pixels are
+              going to be expanded, in which case leave it for later */
+              int i,istop;
+              istop=(int)png_ptr->num_trans;
+              for (i=0; i<istop; i++)
+                 png_ptr->trans[i] = (png_byte)(255 - png_ptr->trans[i]);
+           }
+        }
+#endif
+
+      }
+   }
+#endif
+
+#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+   png_ptr->background_1 = png_ptr->background;
+#endif
+#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
+   if (png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY))
+   {
+      png_build_gamma_table(png_ptr);
+#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+      if (png_ptr->transformations & PNG_BACKGROUND)
+      {
+         if (color_type == PNG_COLOR_TYPE_PALETTE)
+         {
+            png_color back, back_1;
+            png_colorp palette = png_ptr->palette;
+            int num_palette = png_ptr->num_palette;
+            int i;
+            if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
+            {
+               back.red = png_ptr->gamma_table[png_ptr->background.red];
+               back.green = png_ptr->gamma_table[png_ptr->background.green];
+               back.blue = png_ptr->gamma_table[png_ptr->background.blue];
+
+               back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
+               back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
+               back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
+            }
+            else
+            {
+               double g, gs;
+
+               switch (png_ptr->background_gamma_type)
+               {
+                  case PNG_BACKGROUND_GAMMA_SCREEN:
+                     g = (png_ptr->screen_gamma);
+                     gs = 1.0;
+                     break;
+                  case PNG_BACKGROUND_GAMMA_FILE:
+                     g = 1.0 / (png_ptr->gamma);
+                     gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
+                     break;
+                  case PNG_BACKGROUND_GAMMA_UNIQUE:
+                     g = 1.0 / (png_ptr->background_gamma);
+                     gs = 1.0 / (png_ptr->background_gamma *
+                                 png_ptr->screen_gamma);
+                     break;
+                  default:
+                     g = 1.0;    /* back_1 */
+                     gs = 1.0;   /* back */
+               }
+
+               if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD)
+               {
+                  back.red   = (png_byte)png_ptr->background.red;
+                  back.green = (png_byte)png_ptr->background.green;
+                  back.blue  = (png_byte)png_ptr->background.blue;
+               }
+               else
+               {
+                  back.red = (png_byte)(pow(
+                     (double)png_ptr->background.red/255, gs) * 255.0 + .5);
+                  back.green = (png_byte)(pow(
+                     (double)png_ptr->background.green/255, gs) * 255.0 + .5);
+                  back.blue = (png_byte)(pow(
+                     (double)png_ptr->background.blue/255, gs) * 255.0 + .5);
+               }
+
+               back_1.red = (png_byte)(pow(
+                  (double)png_ptr->background.red/255, g) * 255.0 + .5);
+               back_1.green = (png_byte)(pow(
+                  (double)png_ptr->background.green/255, g) * 255.0 + .5);
+               back_1.blue = (png_byte)(pow(
+                  (double)png_ptr->background.blue/255, g) * 255.0 + .5);
+            }
+            for (i = 0; i < num_palette; i++)
+            {
+               if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff)
+               {
+                  if (png_ptr->trans[i] == 0)
+                  {
+                     palette[i] = back;
+                  }
+                  else /* if (png_ptr->trans[i] != 0xff) */
+                  {
+                     png_byte v, w;
+
+                     v = png_ptr->gamma_to_1[palette[i].red];
+                     png_composite(w, v, png_ptr->trans[i], back_1.red);
+                     palette[i].red = png_ptr->gamma_from_1[w];
+
+                     v = png_ptr->gamma_to_1[palette[i].green];
+                     png_composite(w, v, png_ptr->trans[i], back_1.green);
+                     palette[i].green = png_ptr->gamma_from_1[w];
+
+                     v = png_ptr->gamma_to_1[palette[i].blue];
+                     png_composite(w, v, png_ptr->trans[i], back_1.blue);
+                     palette[i].blue = png_ptr->gamma_from_1[w];
+                  }
+               }
+               else
+               {
+                  palette[i].red = png_ptr->gamma_table[palette[i].red];
+                  palette[i].green = png_ptr->gamma_table[palette[i].green];
+                  palette[i].blue = png_ptr->gamma_table[palette[i].blue];
+               }
+            }
+         }
+         /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN)*/
+         else
+         /* color_type != PNG_COLOR_TYPE_PALETTE */
+         {
+            double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1);
+            double g = 1.0;
+            double gs = 1.0;
+
+            switch (png_ptr->background_gamma_type)
+            {
+               case PNG_BACKGROUND_GAMMA_SCREEN:
+                  g = (png_ptr->screen_gamma);
+                  gs = 1.0;
+                  break;
+               case PNG_BACKGROUND_GAMMA_FILE:
+                  g = 1.0 / (png_ptr->gamma);
+                  gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
+                  break;
+               case PNG_BACKGROUND_GAMMA_UNIQUE:
+                  g = 1.0 / (png_ptr->background_gamma);
+                  gs = 1.0 / (png_ptr->background_gamma *
+                     png_ptr->screen_gamma);
+                  break;
+            }
+
+            if (color_type & PNG_COLOR_MASK_COLOR)
+            {
+               /* RGB or RGBA */
+               png_ptr->background_1.red = (png_uint_16)(pow(
+                  (double)png_ptr->background.red / m, g) * m + .5);
+               png_ptr->background_1.green = (png_uint_16)(pow(
+                  (double)png_ptr->background.green / m, g) * m + .5);
+               png_ptr->background_1.blue = (png_uint_16)(pow(
+                  (double)png_ptr->background.blue / m, g) * m + .5);
+               png_ptr->background.red = (png_uint_16)(pow(
+                  (double)png_ptr->background.red / m, gs) * m + .5);
+               png_ptr->background.green = (png_uint_16)(pow(
+                  (double)png_ptr->background.green / m, gs) * m + .5);
+               png_ptr->background.blue = (png_uint_16)(pow(
+                  (double)png_ptr->background.blue / m, gs) * m + .5);
+            }
+            else
+            {
+               /* GRAY or GRAY ALPHA */
+               png_ptr->background_1.gray = (png_uint_16)(pow(
+                  (double)png_ptr->background.gray / m, g) * m + .5);
+               png_ptr->background.gray = (png_uint_16)(pow(
+                  (double)png_ptr->background.gray / m, gs) * m + .5);
+            }
+         }
+      }
+      else
+      /* transformation does not include PNG_BACKGROUND */
+#endif
+      if (color_type == PNG_COLOR_TYPE_PALETTE)
+      {
+         png_colorp palette = png_ptr->palette;
+         int num_palette = png_ptr->num_palette;
+         int i;
+
+         for (i = 0; i < num_palette; i++)
+         {
+            palette[i].red = png_ptr->gamma_table[palette[i].red];
+            palette[i].green = png_ptr->gamma_table[palette[i].green];
+            palette[i].blue = png_ptr->gamma_table[palette[i].blue];
+         }
+      }
+   }
+#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+   else
+#endif
+#endif
+#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+   /* No GAMMA transformation */
+   if ((png_ptr->transformations & PNG_BACKGROUND) &&
+       (color_type == PNG_COLOR_TYPE_PALETTE))
+   {
+      int i;
+      int istop = (int)png_ptr->num_trans;
+      png_color back;
+      png_colorp palette = png_ptr->palette;
+
+      back.red   = (png_byte)png_ptr->background.red;
+      back.green = (png_byte)png_ptr->background.green;
+      back.blue  = (png_byte)png_ptr->background.blue;
+
+      for (i = 0; i < istop; i++)
+      {
+         if (png_ptr->trans[i] == 0)
+         {
+            palette[i] = back;
+         }
+         else if (png_ptr->trans[i] != 0xff)
+         {
+            /* The png_composite() macro is defined in png.h */
+            png_composite(palette[i].red, palette[i].red,
+               png_ptr->trans[i], back.red);
+            png_composite(palette[i].green, palette[i].green,
+               png_ptr->trans[i], back.green);
+            png_composite(palette[i].blue, palette[i].blue,
+               png_ptr->trans[i], back.blue);
+         }
+      }
+   }
+#endif
+
+#if defined(PNG_READ_SHIFT_SUPPORTED)
+   if ((png_ptr->transformations & PNG_SHIFT) &&
+      (color_type == PNG_COLOR_TYPE_PALETTE))
+   {
+      png_uint_16 i;
+      png_uint_16 istop = png_ptr->num_palette;
+      int sr = 8 - png_ptr->sig_bit.red;
+      int sg = 8 - png_ptr->sig_bit.green;
+      int sb = 8 - png_ptr->sig_bit.blue;
+
+      if (sr < 0 || sr > 8)
+         sr = 0;
+      if (sg < 0 || sg > 8)
+         sg = 0;
+      if (sb < 0 || sb > 8)
+         sb = 0;
+      for (i = 0; i < istop; i++)
+      {
+         png_ptr->palette[i].red >>= sr;
+         png_ptr->palette[i].green >>= sg;
+         png_ptr->palette[i].blue >>= sb;
+      }
+   }
+#endif
+ }
+#if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \
+ && !defined(PNG_READ_BACKGROUND_SUPPORTED)
+   if(png_ptr)
+      return;
+#endif
+}
+
+/* Modify the info structure to reflect the transformations.  The
+ * info should be updated so a PNG file could be written with it,
+ * assuming the transformations result in valid PNG data.
+ */
+void /* PRIVATE */
+png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
+{
+   png_debug(1, "in png_read_transform_info\n");
+#if defined(PNG_READ_EXPAND_SUPPORTED)
+   if (png_ptr->transformations & PNG_EXPAND)
+   {
+      if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+      {
+         if (png_ptr->num_trans)
+            info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+         else
+            info_ptr->color_type = PNG_COLOR_TYPE_RGB;
+         info_ptr->bit_depth = 8;
+         info_ptr->num_trans = 0;
+      }
+      else
+      {
+         if (png_ptr->num_trans)
+            info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
+         if (info_ptr->bit_depth < 8)
+            info_ptr->bit_depth = 8;
+         info_ptr->num_trans = 0;
+      }
+   }
+#endif
+
+#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+   if (png_ptr->transformations & PNG_BACKGROUND)
+   {
+      info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
+      info_ptr->num_trans = 0;
+      info_ptr->background = png_ptr->background;
+   }
+#endif
+
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+   if (png_ptr->transformations & PNG_GAMMA)
+   {
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+      info_ptr->gamma = png_ptr->gamma;
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+      info_ptr->int_gamma = png_ptr->int_gamma;
+#endif
+   }
+#endif
+
+#if defined(PNG_READ_16_TO_8_SUPPORTED)
+   if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16))
+      info_ptr->bit_depth = 8;
+#endif
+
+#if defined(PNG_READ_DITHER_SUPPORTED)
+   if (png_ptr->transformations & PNG_DITHER)
+   {
+      if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
+         (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
+         png_ptr->palette_lookup && info_ptr->bit_depth == 8)
+      {
+         info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
+      }
+   }
+#endif
+
+#if defined(PNG_READ_PACK_SUPPORTED)
+   if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
+      info_ptr->bit_depth = 8;
+#endif
+
+#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
+   if (png_ptr->transformations & PNG_GRAY_TO_RGB)
+      info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
+#endif
+
+#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+   if (png_ptr->transformations & PNG_RGB_TO_GRAY)
+      info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR;
+#endif
+
+   if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+      info_ptr->channels = 1;
+   else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
+      info_ptr->channels = 3;
+   else
+      info_ptr->channels = 1;
+
+#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
+   if (png_ptr->transformations & PNG_STRIP_ALPHA)
+      info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
+#endif
+
+   if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
+      info_ptr->channels++;
+
+#if defined(PNG_READ_FILLER_SUPPORTED)
+   /* STRIP_ALPHA and FILLER allowed:  MASK_ALPHA bit stripped above */
+   if ((png_ptr->transformations & PNG_FILLER) &&
+       ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
+       (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
+   {
+      info_ptr->channels++;
+#if 0 /* if adding a true alpha channel not just filler */
+      info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
+#endif
+   }
+#endif
+
+#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
+defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
+   if(png_ptr->transformations & PNG_USER_TRANSFORM)
+     {
+       if(info_ptr->bit_depth < png_ptr->user_transform_depth)
+         info_ptr->bit_depth = png_ptr->user_transform_depth;
+       if(info_ptr->channels < png_ptr->user_transform_channels)
+         info_ptr->channels = png_ptr->user_transform_channels;
+     }
+#endif
+
+   info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
+      info_ptr->bit_depth);
+   info_ptr->rowbytes = ((info_ptr->width * info_ptr->pixel_depth + 7) >> 3);
+
+#if !defined(PNG_READ_EXPAND_SUPPORTED)
+   if(png_ptr)
+      return;
+#endif
+}
+
+/* Transform the row.  The order of transformations is significant,
+ * and is very touchy.  If you add a transformation, take care to
+ * decide how it fits in with the other transformations here.
+ */
+void /* PRIVATE */
+png_do_read_transformations(png_structp png_ptr)
+{
+   png_debug(1, "in png_do_read_transformations\n");
+#if !defined(PNG_USELESS_TESTS_SUPPORTED)
+   if (png_ptr->row_buf == NULL)
+   {
+#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
+      char msg[50];
+
+      sprintf(msg, "NULL row buffer for row %ld, pass %d", png_ptr->row_number,
+         png_ptr->pass);
+      png_error(png_ptr, msg);
+#else
+      png_error(png_ptr, "NULL row buffer");
+#endif
+   }
+#endif
+
+#if defined(PNG_READ_EXPAND_SUPPORTED)
+   if (png_ptr->transformations & PNG_EXPAND)
+   {
+      if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
+      {
+         png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
+            png_ptr->palette, png_ptr->trans, png_ptr->num_trans);
+      }
+      else
+      {
+         if (png_ptr->num_trans)
+            png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
+               &(png_ptr->trans_values));
+         else
+            png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
+               NULL);
+      }
+   }
+#endif
+
+#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
+   if (png_ptr->transformations & PNG_STRIP_ALPHA)
+      png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
+         PNG_FLAG_FILLER_AFTER);
+#endif
+
+#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+   if (png_ptr->transformations & PNG_RGB_TO_GRAY)
+   {
+      int rgb_error =
+         png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1);
+      if(rgb_error)
+      {
+         png_ptr->rgb_to_gray_status=1;
+         if(png_ptr->transformations == PNG_RGB_TO_GRAY_WARN)
+            png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
+         if(png_ptr->transformations == PNG_RGB_TO_GRAY_ERR)
+            png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
+      }
+   }
+#endif
+
+/*
+From Andreas Dilger e-mail to png-implement, 26 March 1998:
+
+  In most cases, the "simple transparency" should be done prior to doing
+  gray-to-RGB, or you will have to test 3x as many bytes to check if a
+  pixel is transparent.  You would also need to make sure that the
+  transparency information is upgraded to RGB.
+
+  To summarize, the current flow is:
+  - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
+                                  with background "in place" if transparent,
+                                  convert to RGB if necessary
+  - Gray + alpha -> composite with gray background and remove alpha bytes,
+                                  convert to RGB if necessary
+
+  To support RGB backgrounds for gray images we need:
+  - Gray + simple transparency -> convert to RGB + simple transparency, compare
+                                  3 or 6 bytes and composite with background
+                                  "in place" if transparent (3x compare/pixel
+                                  compared to doing composite with gray bkgrnd)
+  - Gray + alpha -> convert to RGB + alpha, composite with background and
+                                  remove alpha bytes (3x float operations/pixel
+                                  compared with composite on gray background)
+
+  Greg's change will do this.  The reason it wasn't done before is for
+  performance, as this increases the per-pixel operations.  If we would check
+  in advance if the background was gray or RGB, and position the gray-to-RGB
+  transform appropriately, then it would save a lot of work/time.
+ */
+
+#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
+   /* if gray -> RGB, do so now only if background is non-gray; else do later
+    * for performance reasons */
+   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
+       !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
+      png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+
+#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+   if ((png_ptr->transformations & PNG_BACKGROUND) &&
+      ((png_ptr->num_trans != 0 ) ||
+      (png_ptr->color_type & PNG_COLOR_MASK_ALPHA)))
+      png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1,
+         &(png_ptr->trans_values), &(png_ptr->background),
+         &(png_ptr->background_1),
+         png_ptr->gamma_table, png_ptr->gamma_from_1,
+         png_ptr->gamma_to_1, png_ptr->gamma_16_table,
+         png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1,
+         png_ptr->gamma_shift);
+#endif
+
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+   if ((png_ptr->transformations & PNG_GAMMA) &&
+#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+      !((png_ptr->transformations & PNG_BACKGROUND) &&
+      ((png_ptr->num_trans != 0) ||
+      (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
+#endif
+      (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
+      png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1,
+         png_ptr->gamma_table, png_ptr->gamma_16_table,
+         png_ptr->gamma_shift);
+#endif
+
+#if defined(PNG_READ_16_TO_8_SUPPORTED)
+   if (png_ptr->transformations & PNG_16_TO_8)
+      png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+
+#if defined(PNG_READ_DITHER_SUPPORTED)
+   if (png_ptr->transformations & PNG_DITHER)
+   {
+      png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1,
+         png_ptr->palette_lookup, png_ptr->dither_index);
+      if(png_ptr->row_info.rowbytes == (png_uint_32)0)
+         png_error(png_ptr, "png_do_dither returned rowbytes=0");
+   }
+#endif
+
+#if defined(PNG_READ_INVERT_SUPPORTED)
+   if (png_ptr->transformations & PNG_INVERT_MONO)
+      png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+
+#if defined(PNG_READ_SHIFT_SUPPORTED)
+   if (png_ptr->transformations & PNG_SHIFT)
+      png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1,
+         &(png_ptr->shift));
+#endif
+
+#if defined(PNG_READ_PACK_SUPPORTED)
+   if (png_ptr->transformations & PNG_PACK)
+      png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+
+#if defined(PNG_READ_BGR_SUPPORTED)
+   if (png_ptr->transformations & PNG_BGR)
+      png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+   if (png_ptr->transformations & PNG_PACKSWAP)
+      png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+
+#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))
+      png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+
+#if defined(PNG_READ_FILLER_SUPPORTED)
+   if (png_ptr->transformations & PNG_FILLER)
+      png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
+         (png_uint_32)png_ptr->filler, png_ptr->flags);
+#endif
+
+#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
+   if (png_ptr->transformations & PNG_INVERT_ALPHA)
+      png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+
+#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
+   if (png_ptr->transformations & PNG_SWAP_ALPHA)
+      png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+
+#if defined(PNG_READ_SWAP_SUPPORTED)
+   if (png_ptr->transformations & PNG_SWAP_BYTES)
+      png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
+   if (png_ptr->transformations & PNG_USER_TRANSFORM)
+    {
+      if(png_ptr->read_user_transform_fn != NULL)
+        (*(png_ptr->read_user_transform_fn)) /* user read transform function */
+          (png_ptr,                    /* png_ptr */
+           &(png_ptr->row_info),       /* row_info:     */
+             /*  png_uint_32 width;          width of row */
+             /*  png_uint_32 rowbytes;       number of bytes in row */
+             /*  png_byte color_type;        color type of pixels */
+             /*  png_byte bit_depth;         bit depth of samples */
+             /*  png_byte channels;          number of channels (1-4) */
+             /*  png_byte pixel_depth;       bits per pixel (depth*channels) */
+           png_ptr->row_buf + 1);      /* start of pixel data for row */
+#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
+      if(png_ptr->user_transform_depth)
+         png_ptr->row_info.bit_depth = png_ptr->user_transform_depth;
+      if(png_ptr->user_transform_channels)
+         png_ptr->row_info.channels = png_ptr->user_transform_channels;
+#endif
+      png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
+         png_ptr->row_info.channels);
+      png_ptr->row_info.rowbytes = (png_ptr->row_info.width *
+         png_ptr->row_info.pixel_depth+7)>>3;
+   }
+#endif
+
+}
+
+#if defined(PNG_READ_PACK_SUPPORTED)
+/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
+ * without changing the actual values.  Thus, if you had a row with
+ * a bit depth of 1, you would end up with bytes that only contained
+ * the numbers 0 or 1.  If you would rather they contain 0 and 255, use
+ * png_do_shift() after this.
+ */
+void /* PRIVATE */
+png_do_unpack(png_row_infop row_info, png_bytep row)
+{
+   png_debug(1, "in png_do_unpack\n");
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   if (row != NULL && row_info != NULL && row_info->bit_depth < 8)
+#else
+   if (row_info->bit_depth < 8)
+#endif
+   {
+      png_uint_32 i;
+      png_uint_32 row_width=row_info->width;
+
+      switch (row_info->bit_depth)
+      {
+         case 1:
+         {
+            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) & 0x07);
+            for (i = 0; i < row_width; i++)
+            {
+               *dp = (png_byte)((*sp >> shift) & 0x01);
+               if (shift == 7)
+               {
+                  shift = 0;
+                  sp--;
+               }
+               else
+                  shift++;
+
+               dp--;
+            }
+            break;
+         }
+         case 2:
+         {
+
+            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) & 0x03)) << 1);
+            for (i = 0; i < row_width; i++)
+            {
+               *dp = (png_byte)((*sp >> shift) & 0x03);
+               if (shift == 6)
+               {
+                  shift = 0;
+                  sp--;
+               }
+               else
+                  shift += 2;
+
+               dp--;
+            }
+            break;
+         }
+         case 4:
+         {
+            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) & 0x01)) << 2);
+            for (i = 0; i < row_width; i++)
+            {
+               *dp = (png_byte)((*sp >> shift) & 0x0f);
+               if (shift == 4)
+               {
+                  shift = 0;
+                  sp--;
+               }
+               else
+                  shift = 4;
+
+               dp--;
+            }
+            break;
+         }
+      }
+      row_info->bit_depth = 8;
+      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
+      row_info->rowbytes = row_width * row_info->channels;
+   }
+}
+#endif
+
+#if defined(PNG_READ_SHIFT_SUPPORTED)
+/* Reverse the effects of png_do_shift.  This routine merely shifts the
+ * pixels back to their significant bits values.  Thus, if you have
+ * a row of bit depth 8, but only 5 are significant, this will shift
+ * the values back to 0 through 31.
+ */
+void /* PRIVATE */
+png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
+{
+   png_debug(1, "in png_do_unshift\n");
+   if (
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+       row != NULL && row_info != NULL && sig_bits != NULL &&
+#endif
+       row_info->color_type != PNG_COLOR_TYPE_PALETTE)
+   {
+      int shift[4];
+      int channels = 0;
+      int c;
+      png_uint_16 value = 0;
+      png_uint_32 row_width = row_info->width;
+
+      if (row_info->color_type & PNG_COLOR_MASK_COLOR)
+      {
+         shift[channels++] = row_info->bit_depth - sig_bits->red;
+         shift[channels++] = row_info->bit_depth - sig_bits->green;
+         shift[channels++] = row_info->bit_depth - sig_bits->blue;
+      }
+      else
+      {
+         shift[channels++] = row_info->bit_depth - sig_bits->gray;
+      }
+      if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
+      {
+         shift[channels++] = row_info->bit_depth - sig_bits->alpha;
+      }
+
+      for (c = 0; c < channels; c++)
+      {
+         if (shift[c] <= 0)
+            shift[c] = 0;
+         else
+            value = 1;
+      }
+
+      if (!value)
+         return;
+
+      switch (row_info->bit_depth)
+      {
+         case 2:
+         {
+            png_bytep bp;
+            png_uint_32 i;
+            png_uint_32 istop = row_info->rowbytes;
+
+            for (bp = row, i = 0; i < istop; i++)
+            {
+               *bp >>= 1;
+               *bp++ &= 0x55;
+            }
+            break;
+         }
+         case 4:
+         {
+            png_bytep bp = row;
+            png_uint_32 i;
+            png_uint_32 istop = row_info->rowbytes;
+            png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) |
+               (png_byte)((int)0xf >> shift[0]));
+
+            for (i = 0; i < istop; i++)
+            {
+               *bp >>= shift[0];
+               *bp++ &= mask;
+            }
+            break;
+         }
+         case 8:
+         {
+            png_bytep bp = row;
+            png_uint_32 i;
+            png_uint_32 istop = row_width * channels;
+
+            for (i = 0; i < istop; i++)
+            {
+               *bp++ >>= shift[i%channels];
+            }
+            break;
+         }
+         case 16:
+         {
+            png_bytep bp = row;
+            png_uint_32 i;
+            png_uint_32 istop = channels * row_width;
+
+            for (i = 0; i < istop; i++)
+            {
+               value = (png_uint_16)((*bp << 8) + *(bp + 1));
+               value >>= shift[i%channels];
+               *bp++ = (png_byte)(value >> 8);
+               *bp++ = (png_byte)(value & 0xff);
+            }
+            break;
+         }
+      }
+   }
+}
+#endif
+
+#if defined(PNG_READ_16_TO_8_SUPPORTED)
+/* chop rows of bit depth 16 down to 8 */
+void /* PRIVATE */
+png_do_chop(png_row_infop row_info, png_bytep row)
+{
+   png_debug(1, "in png_do_chop\n");
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   if (row != NULL && row_info != NULL && row_info->bit_depth == 16)
+#else
+   if (row_info->bit_depth == 16)
+#endif
+   {
+      png_bytep sp = row;
+      png_bytep dp = row;
+      png_uint_32 i;
+      png_uint_32 istop = row_info->width * row_info->channels;
+
+      for (i = 0; i<istop; i++, sp += 2, dp++)
+      {
+#if defined(PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED)
+      /* This does a more accurate scaling of the 16-bit color
+       * value, rather than a simple low-byte truncation.
+       *
+       * What the ideal calculation should be:
+       *   *dp = (((((png_uint_32)(*sp) << 8) |
+       *          (png_uint_32)(*(sp + 1))) * 255 + 127) / (png_uint_32)65535L;
+       *
+       * GRR: no, I think this is what it really should be:
+       *   *dp = (((((png_uint_32)(*sp) << 8) |
+       *           (png_uint_32)(*(sp + 1))) + 128L) / (png_uint_32)257L;
+       *
+       * GRR: here's the exact calculation with shifts:
+       *   temp = (((png_uint_32)(*sp) << 8) | (png_uint_32)(*(sp + 1))) + 128L;
+       *   *dp = (temp - (temp >> 8)) >> 8;
+       *
+       * Approximate calculation with shift/add instead of multiply/divide:
+       *   *dp = ((((png_uint_32)(*sp) << 8) |
+       *          (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8;
+       *
+       * What we actually do to avoid extra shifting and conversion:
+       */
+
+         *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0);
+#else
+       /* Simply discard the low order byte */
+         *dp = *sp;
+#endif
+      }
+      row_info->bit_depth = 8;
+      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
+      row_info->rowbytes = row_info->width * row_info->channels;
+   }
+}
+#endif
+
+#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
+void /* PRIVATE */
+png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
+{
+   png_debug(1, "in png_do_read_swap_alpha\n");
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   if (row != NULL && row_info != NULL)
+#endif
+   {
+      png_uint_32 row_width = row_info->width;
+      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+      {
+         /* This converts from RGBA to ARGB */
+         if (row_info->bit_depth == 8)
+         {
+            png_bytep sp = row + row_info->rowbytes;
+            png_bytep dp = sp;
+            png_byte save;
+            png_uint_32 i;
+
+            for (i = 0; i < row_width; i++)
+            {
+               save = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = save;
+            }
+         }
+         /* This converts from RRGGBBAA to AARRGGBB */
+         else
+         {
+            png_bytep sp = row + row_info->rowbytes;
+            png_bytep dp = sp;
+            png_byte save[2];
+            png_uint_32 i;
+
+            for (i = 0; i < row_width; i++)
+            {
+               save[0] = *(--sp);
+               save[1] = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = save[0];
+               *(--dp) = save[1];
+            }
+         }
+      }
+      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+      {
+         /* This converts from GA to AG */
+         if (row_info->bit_depth == 8)
+         {
+            png_bytep sp = row + row_info->rowbytes;
+            png_bytep dp = sp;
+            png_byte save;
+            png_uint_32 i;
+
+            for (i = 0; i < row_width; i++)
+            {
+               save = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = save;
+            }
+         }
+         /* This converts from GGAA to AAGG */
+         else
+         {
+            png_bytep sp = row + row_info->rowbytes;
+            png_bytep dp = sp;
+            png_byte save[2];
+            png_uint_32 i;
+
+            for (i = 0; i < row_width; i++)
+            {
+               save[0] = *(--sp);
+               save[1] = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = save[0];
+               *(--dp) = save[1];
+            }
+         }
+      }
+   }
+}
+#endif
+
+#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
+void /* PRIVATE */
+png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
+{
+   png_debug(1, "in png_do_read_invert_alpha\n");
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   if (row != NULL && row_info != NULL)
+#endif
+   {
+      png_uint_32 row_width = row_info->width;
+      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+      {
+         /* This inverts the alpha channel in RGBA */
+         if (row_info->bit_depth == 8)
+         {
+            png_bytep sp = row + row_info->rowbytes;
+            png_bytep dp = sp;
+            png_uint_32 i;
+
+            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 */
+         else
+         {
+            png_bytep sp = row + row_info->rowbytes;
+            png_bytep dp = sp;
+            png_uint_32 i;
+
+            for (i = 0; i < row_width; i++)
+            {
+               *(--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;
+            }
+         }
+      }
+      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+      {
+         /* This inverts the alpha channel in GA */
+         if (row_info->bit_depth == 8)
+         {
+            png_bytep sp = row + row_info->rowbytes;
+            png_bytep dp = sp;
+            png_uint_32 i;
+
+            for (i = 0; i < row_width; i++)
+            {
+               *(--dp) = (png_byte)(255 - *(--sp));
+               *(--dp) = *(--sp);
+            }
+         }
+         /* This inverts the alpha channel in GGAA */
+         else
+         {
+            png_bytep sp  = row + row_info->rowbytes;
+            png_bytep dp = sp;
+            png_uint_32 i;
+
+            for (i = 0; i < row_width; i++)
+            {
+               *(--dp) = (png_byte)(255 - *(--sp));
+               *(--dp) = (png_byte)(255 - *(--sp));
+/*
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+*/
+               sp-=2;
+               dp=sp;
+            }
+         }
+      }
+   }
+}
+#endif
+
+#if defined(PNG_READ_FILLER_SUPPORTED)
+/* Add filler channel if we have RGB color */
+void /* PRIVATE */
+png_do_read_filler(png_row_infop row_info, png_bytep row,
+   png_uint_32 filler, png_uint_32 flags)
+{
+   png_uint_32 i;
+   png_uint_32 row_width = row_info->width;
+
+   png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
+   png_byte lo_filler = (png_byte)(filler & 0xff);
+
+   png_debug(1, "in png_do_read_filler\n");
+   if (
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+       row != NULL  && row_info != NULL &&
+#endif
+       row_info->color_type == PNG_COLOR_TYPE_GRAY)
+   {
+      if(row_info->bit_depth == 8)
+      {
+         /* This changes the data from G to GX */
+         if (flags & PNG_FLAG_FILLER_AFTER)
+         {
+            png_bytep sp = row + (png_size_t)row_width;
+            png_bytep dp =  sp + (png_size_t)row_width;
+            for (i = 1; i < row_width; i++)
+            {
+               *(--dp) = lo_filler;
+               *(--dp) = *(--sp);
+            }
+            *(--dp) = lo_filler;
+            row_info->channels = 2;
+            row_info->pixel_depth = 16;
+            row_info->rowbytes = row_width * 2;
+         }
+      /* This changes the data from G to XG */
+         else
+         {
+            png_bytep sp = row + (png_size_t)row_width;
+            png_bytep dp = sp  + (png_size_t)row_width;
+            for (i = 0; i < row_width; i++)
+            {
+               *(--dp) = *(--sp);
+               *(--dp) = lo_filler;
+            }
+            row_info->channels = 2;
+            row_info->pixel_depth = 16;
+            row_info->rowbytes = row_width * 2;
+         }
+      }
+      else if(row_info->bit_depth == 16)
+      {
+         /* This changes the data from GG to GGXX */
+         if (flags & PNG_FLAG_FILLER_AFTER)
+         {
+            png_bytep sp = row + (png_size_t)row_width;
+            png_bytep dp = sp  + (png_size_t)row_width;
+            for (i = 1; i < row_width; i++)
+            {
+               *(--dp) = hi_filler;
+               *(--dp) = lo_filler;
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+            }
+            *(--dp) = hi_filler;
+            *(--dp) = lo_filler;
+            row_info->channels = 2;
+            row_info->pixel_depth = 32;
+            row_info->rowbytes = row_width * 4;
+         }
+         /* This changes the data from GG to XXGG */
+         else
+         {
+            png_bytep sp = row + (png_size_t)row_width;
+            png_bytep dp = sp  + (png_size_t)row_width;
+            for (i = 0; i < row_width; i++)
+            {
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = hi_filler;
+               *(--dp) = lo_filler;
+            }
+            row_info->channels = 2;
+            row_info->pixel_depth = 32;
+            row_info->rowbytes = row_width * 4;
+         }
+      }
+   } /* COLOR_TYPE == GRAY */
+   else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+   {
+      if(row_info->bit_depth == 8)
+      {
+         /* This changes the data from RGB to RGBX */
+         if (flags & PNG_FLAG_FILLER_AFTER)
+         {
+            png_bytep sp = row + (png_size_t)row_width * 3;
+            png_bytep dp = sp  + (png_size_t)row_width;
+            for (i = 1; i < row_width; i++)
+            {
+               *(--dp) = lo_filler;
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+            }
+            *(--dp) = lo_filler;
+            row_info->channels = 4;
+            row_info->pixel_depth = 32;
+            row_info->rowbytes = row_width * 4;
+         }
+      /* This changes the data from RGB to XRGB */
+         else
+         {
+            png_bytep sp = row + (png_size_t)row_width * 3;
+            png_bytep dp = sp + (png_size_t)row_width;
+            for (i = 0; i < row_width; i++)
+            {
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = lo_filler;
+            }
+            row_info->channels = 4;
+            row_info->pixel_depth = 32;
+            row_info->rowbytes = row_width * 4;
+         }
+      }
+      else if(row_info->bit_depth == 16)
+      {
+         /* This changes the data from RRGGBB to RRGGBBXX */
+         if (flags & PNG_FLAG_FILLER_AFTER)
+         {
+            png_bytep sp = row + (png_size_t)row_width * 3;
+            png_bytep dp = sp  + (png_size_t)row_width;
+            for (i = 1; i < row_width; i++)
+            {
+               *(--dp) = hi_filler;
+               *(--dp) = lo_filler;
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+            }
+            *(--dp) = hi_filler;
+            *(--dp) = lo_filler;
+            row_info->channels = 4;
+            row_info->pixel_depth = 64;
+            row_info->rowbytes = row_width * 8;
+         }
+         /* This changes the data from RRGGBB to XXRRGGBB */
+         else
+         {
+            png_bytep sp = row + (png_size_t)row_width * 3;
+            png_bytep dp = sp  + (png_size_t)row_width;
+            for (i = 0; i < row_width; i++)
+            {
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = hi_filler;
+               *(--dp) = lo_filler;
+            }
+            row_info->channels = 4;
+            row_info->pixel_depth = 64;
+            row_info->rowbytes = row_width * 8;
+         }
+      }
+   } /* COLOR_TYPE == RGB */
+}
+#endif
+
+#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
+/* expand grayscale files to RGB, with or without alpha */
+void /* PRIVATE */
+png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
+{
+   png_uint_32 i;
+   png_uint_32 row_width = row_info->width;
+
+   png_debug(1, "in png_do_gray_to_rgb\n");
+   if (row_info->bit_depth >= 8 &&
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+       row != NULL && row_info != NULL &&
+#endif
+      !(row_info->color_type & PNG_COLOR_MASK_COLOR))
+   {
+      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
+      {
+         if (row_info->bit_depth == 8)
+         {
+            png_bytep sp = row + (png_size_t)row_width - 1;
+            png_bytep dp = sp  + (png_size_t)row_width * 2;
+            for (i = 0; i < row_width; i++)
+            {
+               *(dp--) = *sp;
+               *(dp--) = *sp;
+               *(dp--) = *(sp--);
+            }
+         }
+         else
+         {
+            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
+            png_bytep dp = sp  + (png_size_t)row_width * 4;
+            for (i = 0; i < row_width; i++)
+            {
+               *(dp--) = *sp;
+               *(dp--) = *(sp - 1);
+               *(dp--) = *sp;
+               *(dp--) = *(sp - 1);
+               *(dp--) = *(sp--);
+               *(dp--) = *(sp--);
+            }
+         }
+      }
+      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+      {
+         if (row_info->bit_depth == 8)
+         {
+            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
+            png_bytep dp = sp  + (png_size_t)row_width * 2;
+            for (i = 0; i < row_width; i++)
+            {
+               *(dp--) = *(sp--);
+               *(dp--) = *sp;
+               *(dp--) = *sp;
+               *(dp--) = *(sp--);
+            }
+         }
+         else
+         {
+            png_bytep sp = row + (png_size_t)row_width * 4 - 1;
+            png_bytep dp = sp  + (png_size_t)row_width * 4;
+            for (i = 0; i < row_width; i++)
+            {
+               *(dp--) = *(sp--);
+               *(dp--) = *(sp--);
+               *(dp--) = *sp;
+               *(dp--) = *(sp - 1);
+               *(dp--) = *sp;
+               *(dp--) = *(sp - 1);
+               *(dp--) = *(sp--);
+               *(dp--) = *(sp--);
+            }
+         }
+      }
+      row_info->channels += (png_byte)2;
+      row_info->color_type |= PNG_COLOR_MASK_COLOR;
+      row_info->pixel_depth = (png_byte)(row_info->channels *
+         row_info->bit_depth);
+      row_info->rowbytes = ((row_width *
+         row_info->pixel_depth + 7) >> 3);
+   }
+}
+#endif
+
+#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+/* reduce RGB files to grayscale, with or without alpha
+ * using the equation given in Poynton's ColorFAQ at
+ * <http://www.inforamp.net/~poynton/>
+ * Copyright (c) 1998-01-04 Charles Poynton poynton@inforamp.net
+ *
+ *     Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
+ *
+ *  We approximate this with
+ *
+ *     Y = 0.21268 * R    + 0.7151 * G    + 0.07217 * B
+ *
+ *  which can be expressed with integers as
+ *
+ *     Y = (6969 * R + 23434 * G + 2365 * B)/32768
+ *
+ *  The calculation is to be done in a linear colorspace.
+ *
+ *  Other integer coefficents can be used via png_set_rgb_to_gray().
+ */
+int /* PRIVATE */
+png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
+
+{
+   png_uint_32 i;
+
+   png_uint_32 row_width = row_info->width;
+   int rgb_error = 0;
+
+   png_debug(1, "in png_do_rgb_to_gray\n");
+   if (
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+       row != NULL && row_info != NULL &&
+#endif
+      (row_info->color_type & PNG_COLOR_MASK_COLOR))
+   {
+      png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
+      png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
+      png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff;
+
+      if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+      {
+         if (row_info->bit_depth == 8)
+         {
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+            if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
+            {
+               png_bytep sp = row;
+               png_bytep dp = row;
+
+               for (i = 0; i < row_width; i++)
+               {
+                  png_byte red   = png_ptr->gamma_to_1[*(sp++)];
+                  png_byte green = png_ptr->gamma_to_1[*(sp++)];
+                  png_byte blue  = png_ptr->gamma_to_1[*(sp++)];
+                  if(red != green || red != blue)
+                  {
+                     rgb_error |= 1;
+                     *(dp++) = png_ptr->gamma_from_1[
+                       (rc*red+gc*green+bc*blue)>>15];
+                  }
+                  else
+                     *(dp++) = *(sp-1);
+               }
+            }
+            else
+#endif
+            {
+               png_bytep sp = row;
+               png_bytep dp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  png_byte red   = *(sp++);
+                  png_byte green = *(sp++);
+                  png_byte blue  = *(sp++);
+                  if(red != green || red != blue)
+                  {
+                     rgb_error |= 1;
+                     *(dp++) = (png_byte)((rc*red+gc*green+bc*blue)>>15);
+                  }
+                  else
+                     *(dp++) = *(sp-1);
+               }
+            }
+         }
+
+         else /* RGB bit_depth == 16 */
+         {
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+            if (png_ptr->gamma_16_to_1 != NULL &&
+                png_ptr->gamma_16_from_1 != NULL)
+            {
+               png_bytep sp = row;
+               png_bytep dp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  png_uint_16 red, green, blue, w;
+
+                  red   = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
+                  green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
+                  blue  = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
+
+                  if(red == green && red == blue)
+                     w = red;
+                  else
+                  {
+                     png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red&0xff) >>
+                                  png_ptr->gamma_shift][red>>8];
+                     png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
+                                  png_ptr->gamma_shift][green>>8];
+                     png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue&0xff) >>
+                                  png_ptr->gamma_shift][blue>>8];
+                     png_uint_16 gray16  = (png_uint_16)((rc*red_1 + gc*green_1
+                                  + bc*blue_1)>>15);
+                     w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
+                         png_ptr->gamma_shift][gray16 >> 8];
+                     rgb_error |= 1;
+                  }
+
+                  *(dp++) = (png_byte)((w>>8) & 0xff);
+                  *(dp++) = (png_byte)(w & 0xff);
+               }
+            }
+            else
+#endif
+            {
+               png_bytep sp = row;
+               png_bytep dp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  png_uint_16 red, green, blue, gray16;
+
+                  red   = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
+                  green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
+                  blue  = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
+
+                  if(red != green || red != blue)
+                     rgb_error |= 1;
+                  gray16  = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
+                  *(dp++) = (png_byte)((gray16>>8) & 0xff);
+                  *(dp++) = (png_byte)(gray16 & 0xff);
+               }
+            }
+         }
+      }
+      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+      {
+         if (row_info->bit_depth == 8)
+         {
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+            if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
+            {
+               png_bytep sp = row;
+               png_bytep dp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  png_byte red   = png_ptr->gamma_to_1[*(sp++)];
+                  png_byte green = png_ptr->gamma_to_1[*(sp++)];
+                  png_byte blue  = png_ptr->gamma_to_1[*(sp++)];
+                  if(red != green || red != blue)
+                     rgb_error |= 1;
+                  *(dp++) =  png_ptr->gamma_from_1
+                             [(rc*red + gc*green + bc*blue)>>15];
+                  *(dp++) = *(sp++);  /* alpha */
+               }
+            }
+            else
+#endif
+            {
+               png_bytep sp = row;
+               png_bytep dp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  png_byte red   = *(sp++);
+                  png_byte green = *(sp++);
+                  png_byte blue  = *(sp++);
+                  if(red != green || red != blue)
+                     rgb_error |= 1;
+                  *(dp++) =  (png_byte)((gc*red + gc*green + bc*blue)>>8);
+                  *(dp++) = *(sp++);  /* alpha */
+               }
+            }
+         }
+         else /* RGBA bit_depth == 16 */
+         {
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+            if (png_ptr->gamma_16_to_1 != NULL &&
+                png_ptr->gamma_16_from_1 != NULL)
+            {
+               png_bytep sp = row;
+               png_bytep dp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  png_uint_16 red, green, blue, w;
+
+                  red   = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
+                  green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
+                  blue  = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
+
+                  if(red == green && red == blue)
+                     w = red;
+                  else
+                  {
+                     png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red&0xff) >>
+                                  png_ptr->gamma_shift][red>>8];
+                     png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
+                                  png_ptr->gamma_shift][green>>8];
+                     png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue&0xff) >>
+                                  png_ptr->gamma_shift][blue>>8];
+                     png_uint_16 gray16  = (png_uint_16)((rc * red_1
+                                  + gc * green_1 + bc * blue_1)>>15);
+                     w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
+                         png_ptr->gamma_shift][gray16 >> 8];
+                     rgb_error |= 1;
+                  }
+
+                  *(dp++) = (png_byte)((w>>8) & 0xff);
+                  *(dp++) = (png_byte)(w & 0xff);
+                  *(dp++) = *(sp++);  /* alpha */
+                  *(dp++) = *(sp++);
+               }
+            }
+            else
+#endif
+            {
+               png_bytep sp = row;
+               png_bytep dp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  png_uint_16 red, green, blue, gray16;
+                  red   = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
+                  green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
+                  blue  = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
+                  if(red != green || red != blue)
+                     rgb_error |= 1;
+                  gray16  = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
+                  *(dp++) = (png_byte)((gray16>>8) & 0xff);
+                  *(dp++) = (png_byte)(gray16 & 0xff);
+                  *(dp++) = *(sp++);  /* alpha */
+                  *(dp++) = *(sp++);
+               }
+            }
+         }
+      }
+   row_info->channels -= (png_byte)2;
+      row_info->color_type &= ~PNG_COLOR_MASK_COLOR;
+      row_info->pixel_depth = (png_byte)(row_info->channels *
+         row_info->bit_depth);
+      row_info->rowbytes = ((row_width *
+         row_info->pixel_depth + 7) >> 3);
+   }
+   return rgb_error;
+}
+#endif
+
+/* Build a grayscale palette.  Palette is assumed to be 1 << bit_depth
+ * large of png_color.  This lets grayscale images be treated as
+ * paletted.  Most useful for gamma correction and simplification
+ * of code.
+ */
+void /* PRIVATE */
+png_build_grayscale_palette(int bit_depth, png_colorp palette)
+{
+   int num_palette;
+   int color_inc;
+   int i;
+   int v;
+
+   png_debug(1, "in png_do_build_grayscale_palette\n");
+   if (palette == NULL)
+      return;
+
+   switch (bit_depth)
+   {
+      case 1:
+         num_palette = 2;
+         color_inc = 0xff;
+         break;
+      case 2:
+         num_palette = 4;
+         color_inc = 0x55;
+         break;
+      case 4:
+         num_palette = 16;
+         color_inc = 0x11;
+         break;
+      case 8:
+         num_palette = 256;
+         color_inc = 1;
+         break;
+      default:
+         num_palette = 0;
+         color_inc = 0;
+         break;
+   }
+
+   for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
+   {
+      palette[i].red = (png_byte)v;
+      palette[i].green = (png_byte)v;
+      palette[i].blue = (png_byte)v;
+   }
+}
+
+/* This function is currently unused.  Do we really need it? */
+#if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED)
+void /* PRIVATE */
+png_correct_palette(png_structp png_ptr, png_colorp palette,
+   int num_palette)
+{
+   png_debug(1, "in png_correct_palette\n");
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
+    defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
+   if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND))
+   {
+      png_color back, back_1;
+
+      if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
+      {
+         back.red = png_ptr->gamma_table[png_ptr->background.red];
+         back.green = png_ptr->gamma_table[png_ptr->background.green];
+         back.blue = png_ptr->gamma_table[png_ptr->background.blue];
+
+         back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
+         back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
+         back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
+      }
+      else
+      {
+         double g;
+
+         g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma);
+
+         if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN ||
+             fabs(g - 1.0) < PNG_GAMMA_THRESHOLD)
+         {
+            back.red = png_ptr->background.red;
+            back.green = png_ptr->background.green;
+            back.blue = png_ptr->background.blue;
+         }
+         else
+         {
+            back.red =
+               (png_byte)(pow((double)png_ptr->background.red/255, g) *
+                255.0 + 0.5);
+            back.green =
+               (png_byte)(pow((double)png_ptr->background.green/255, g) *
+                255.0 + 0.5);
+            back.blue =
+               (png_byte)(pow((double)png_ptr->background.blue/255, g) *
+                255.0 + 0.5);
+         }
+
+         g = 1.0 / png_ptr->background_gamma;
+
+         back_1.red =
+            (png_byte)(pow((double)png_ptr->background.red/255, g) *
+             255.0 + 0.5);
+         back_1.green =
+            (png_byte)(pow((double)png_ptr->background.green/255, g) *
+             255.0 + 0.5);
+         back_1.blue =
+            (png_byte)(pow((double)png_ptr->background.blue/255, g) *
+             255.0 + 0.5);
+      }
+
+      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+      {
+         png_uint_32 i;
+
+         for (i = 0; i < (png_uint_32)num_palette; i++)
+         {
+            if (i < png_ptr->num_trans && png_ptr->trans[i] == 0)
+            {
+               palette[i] = back;
+            }
+            else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff)
+            {
+               png_byte v, w;
+
+               v = png_ptr->gamma_to_1[png_ptr->palette[i].red];
+               png_composite(w, v, png_ptr->trans[i], back_1.red);
+               palette[i].red = png_ptr->gamma_from_1[w];
+
+               v = png_ptr->gamma_to_1[png_ptr->palette[i].green];
+               png_composite(w, v, png_ptr->trans[i], back_1.green);
+               palette[i].green = png_ptr->gamma_from_1[w];
+
+               v = png_ptr->gamma_to_1[png_ptr->palette[i].blue];
+               png_composite(w, v, png_ptr->trans[i], back_1.blue);
+               palette[i].blue = png_ptr->gamma_from_1[w];
+            }
+            else
+            {
+               palette[i].red = png_ptr->gamma_table[palette[i].red];
+               palette[i].green = png_ptr->gamma_table[palette[i].green];
+               palette[i].blue = png_ptr->gamma_table[palette[i].blue];
+            }
+         }
+      }
+      else
+      {
+         int i;
+
+         for (i = 0; i < num_palette; i++)
+         {
+            if (palette[i].red == (png_byte)png_ptr->trans_values.gray)
+            {
+               palette[i] = back;
+            }
+            else
+            {
+               palette[i].red = png_ptr->gamma_table[palette[i].red];
+               palette[i].green = png_ptr->gamma_table[palette[i].green];
+               palette[i].blue = png_ptr->gamma_table[palette[i].blue];
+            }
+         }
+      }
+   }
+   else
+#endif
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+   if (png_ptr->transformations & PNG_GAMMA)
+   {
+      int i;
+
+      for (i = 0; i < num_palette; i++)
+      {
+         palette[i].red = png_ptr->gamma_table[palette[i].red];
+         palette[i].green = png_ptr->gamma_table[palette[i].green];
+         palette[i].blue = png_ptr->gamma_table[palette[i].blue];
+      }
+   }
+#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+   else
+#endif
+#endif
+#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+   if (png_ptr->transformations & PNG_BACKGROUND)
+   {
+      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+      {
+         png_color back;
+
+         back.red   = (png_byte)png_ptr->background.red;
+         back.green = (png_byte)png_ptr->background.green;
+         back.blue  = (png_byte)png_ptr->background.blue;
+
+         for (i = 0; i < (int)png_ptr->num_trans; i++)
+         {
+            if (png_ptr->trans[i] == 0)
+            {
+               palette[i].red = back.red;
+               palette[i].green = back.green;
+               palette[i].blue = back.blue;
+            }
+            else if (png_ptr->trans[i] != 0xff)
+            {
+               png_composite(palette[i].red, png_ptr->palette[i].red,
+                  png_ptr->trans[i], back.red);
+               png_composite(palette[i].green, png_ptr->palette[i].green,
+                  png_ptr->trans[i], back.green);
+               png_composite(palette[i].blue, png_ptr->palette[i].blue,
+                  png_ptr->trans[i], back.blue);
+            }
+         }
+      }
+      else /* assume grayscale palette (what else could it be?) */
+      {
+         int i;
+
+         for (i = 0; i < num_palette; i++)
+         {
+            if (i == (png_byte)png_ptr->trans_values.gray)
+            {
+               palette[i].red = (png_byte)png_ptr->background.red;
+               palette[i].green = (png_byte)png_ptr->background.green;
+               palette[i].blue = (png_byte)png_ptr->background.blue;
+            }
+         }
+      }
+   }
+#endif
+}
+#endif
+
+#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+/* Replace any alpha or transparency with the supplied background color.
+ * "background" is already in the screen gamma, while "background_1" is
+ * at a gamma of 1.0.  Paletted files have already been taken care of.
+ */
+void /* PRIVATE */
+png_do_background(png_row_infop row_info, png_bytep row,
+   png_color_16p trans_values, png_color_16p background,
+   png_color_16p background_1,
+   png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
+   png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
+   png_uint_16pp gamma_16_to_1, int gamma_shift)
+{
+   png_bytep sp, dp;
+   png_uint_32 i;
+   png_uint_32 row_width=row_info->width;
+   int shift;
+
+   png_debug(1, "in png_do_background\n");
+   if (background != NULL &&
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+       row != NULL && row_info != NULL &&
+#endif
+      (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) ||
+      (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values)))
+   {
+      switch (row_info->color_type)
+      {
+         case PNG_COLOR_TYPE_GRAY:
+         {
+            switch (row_info->bit_depth)
+            {
+               case 1:
+               {
+                  sp = row;
+                  shift = 7;
+                  for (i = 0; i < row_width; i++)
+                  {
+                     if ((png_uint_16)((*sp >> shift) & 0x01)
+                        == trans_values->gray)
+                     {
+                        *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
+                        *sp |= (png_byte)(background->gray << shift);
+                     }
+                     if (!shift)
+                     {
+                        shift = 7;
+                        sp++;
+                     }
+                     else
+                        shift--;
+                  }
+                  break;
+               }
+               case 2:
+               {
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+                  if (gamma_table != NULL)
+                  {
+                     sp = row;
+                     shift = 6;
+                     for (i = 0; i < row_width; i++)
+                     {
+                        if ((png_uint_16)((*sp >> shift) & 0x03)
+                            == trans_values->gray)
+                        {
+                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
+                           *sp |= (png_byte)(background->gray << shift);
+                        }
+                        else
+                        {
+                           png_byte p = (png_byte)((*sp >> shift) & 0x03);
+                           png_byte g = (png_byte)((gamma_table [p | (p << 2) |
+                               (p << 4) | (p << 6)] >> 6) & 0x03);
+                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
+                           *sp |= (png_byte)(g << shift);
+                        }
+                        if (!shift)
+                        {
+                           shift = 6;
+                           sp++;
+                        }
+                        else
+                           shift -= 2;
+                     }
+                  }
+                  else
+#endif
+                  {
+                     sp = row;
+                     shift = 6;
+                     for (i = 0; i < row_width; i++)
+                     {
+                        if ((png_uint_16)((*sp >> shift) & 0x03)
+                            == trans_values->gray)
+                        {
+                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
+                           *sp |= (png_byte)(background->gray << shift);
+                        }
+                        if (!shift)
+                        {
+                           shift = 6;
+                           sp++;
+                        }
+                        else
+                           shift -= 2;
+                     }
+                  }
+                  break;
+               }
+               case 4:
+               {
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+                  if (gamma_table != NULL)
+                  {
+                     sp = row;
+                     shift = 4;
+                     for (i = 0; i < row_width; i++)
+                     {
+                        if ((png_uint_16)((*sp >> shift) & 0x0f)
+                            == trans_values->gray)
+                        {
+                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
+                           *sp |= (png_byte)(background->gray << shift);
+                        }
+                        else
+                        {
+                           png_byte p = (png_byte)((*sp >> shift) & 0x0f);
+                           png_byte g = (png_byte)((gamma_table[p |
+                             (p << 4)] >> 4) & 0x0f);
+                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
+                           *sp |= (png_byte)(g << shift);
+                        }
+                        if (!shift)
+                        {
+                           shift = 4;
+                           sp++;
+                        }
+                        else
+                           shift -= 4;
+                     }
+                  }
+                  else
+#endif
+                  {
+                     sp = row;
+                     shift = 4;
+                     for (i = 0; i < row_width; i++)
+                     {
+                        if ((png_uint_16)((*sp >> shift) & 0x0f)
+                            == trans_values->gray)
+                        {
+                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
+                           *sp |= (png_byte)(background->gray << shift);
+                        }
+                        if (!shift)
+                        {
+                           shift = 4;
+                           sp++;
+                        }
+                        else
+                           shift -= 4;
+                     }
+                  }
+                  break;
+               }
+               case 8:
+               {
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+                  if (gamma_table != NULL)
+                  {
+                     sp = row;
+                     for (i = 0; i < row_width; i++, sp++)
+                     {
+                        if (*sp == trans_values->gray)
+                        {
+                           *sp = (png_byte)background->gray;
+                        }
+                        else
+                        {
+                           *sp = gamma_table[*sp];
+                        }
+                     }
+                  }
+                  else
+#endif
+                  {
+                     sp = row;
+                     for (i = 0; i < row_width; i++, sp++)
+                     {
+                        if (*sp == trans_values->gray)
+                        {
+                           *sp = (png_byte)background->gray;
+                        }
+                     }
+                  }
+                  break;
+               }
+               case 16:
+               {
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+                  if (gamma_16 != NULL)
+                  {
+                     sp = row;
+                     for (i = 0; i < row_width; i++, sp += 2)
+                     {
+                        png_uint_16 v;
+
+                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
+                        if (v == trans_values->gray)
+                        {
+                           /* background is already in screen gamma */
+                           *sp = (png_byte)((background->gray >> 8) & 0xff);
+                           *(sp + 1) = (png_byte)(background->gray & 0xff);
+                        }
+                        else
+                        {
+                           v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
+                           *sp = (png_byte)((v >> 8) & 0xff);
+                           *(sp + 1) = (png_byte)(v & 0xff);
+                        }
+                     }
+                  }
+                  else
+#endif
+                  {
+                     sp = row;
+                     for (i = 0; i < row_width; i++, sp += 2)
+                     {
+                        png_uint_16 v;
+
+                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
+                        if (v == trans_values->gray)
+                        {
+                           *sp = (png_byte)((background->gray >> 8) & 0xff);
+                           *(sp + 1) = (png_byte)(background->gray & 0xff);
+                        }
+                     }
+                  }
+                  break;
+               }
+            }
+            break;
+         }
+         case PNG_COLOR_TYPE_RGB:
+         {
+            if (row_info->bit_depth == 8)
+            {
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+               if (gamma_table != NULL)
+               {
+                  sp = row;
+                  for (i = 0; i < row_width; i++, sp += 3)
+                  {
+                     if (*sp == trans_values->red &&
+                        *(sp + 1) == trans_values->green &&
+                        *(sp + 2) == trans_values->blue)
+                     {
+                        *sp = (png_byte)background->red;
+                        *(sp + 1) = (png_byte)background->green;
+                        *(sp + 2) = (png_byte)background->blue;
+                     }
+                     else
+                     {
+                        *sp = gamma_table[*sp];
+                        *(sp + 1) = gamma_table[*(sp + 1)];
+                        *(sp + 2) = gamma_table[*(sp + 2)];
+                     }
+                  }
+               }
+               else
+#endif
+               {
+                  sp = row;
+                  for (i = 0; i < row_width; i++, sp += 3)
+                  {
+                     if (*sp == trans_values->red &&
+                        *(sp + 1) == trans_values->green &&
+                        *(sp + 2) == trans_values->blue)
+                     {
+                        *sp = (png_byte)background->red;
+                        *(sp + 1) = (png_byte)background->green;
+                        *(sp + 2) = (png_byte)background->blue;
+                     }
+                  }
+               }
+            }
+            else /* if (row_info->bit_depth == 16) */
+            {
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+               if (gamma_16 != NULL)
+               {
+                  sp = row;
+                  for (i = 0; i < row_width; i++, sp += 6)
+                  {
+                     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
+                     png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
+                     png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
+                     if (r == trans_values->red && g == trans_values->green &&
+                        b == trans_values->blue)
+                     {
+                        /* background is already in screen gamma */
+                        *sp = (png_byte)((background->red >> 8) & 0xff);
+                        *(sp + 1) = (png_byte)(background->red & 0xff);
+                        *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
+                        *(sp + 3) = (png_byte)(background->green & 0xff);
+                        *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
+                        *(sp + 5) = (png_byte)(background->blue & 0xff);
+                     }
+                     else
+                     {
+                        png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
+                        *sp = (png_byte)((v >> 8) & 0xff);
+                        *(sp + 1) = (png_byte)(v & 0xff);
+                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
+                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
+                        *(sp + 3) = (png_byte)(v & 0xff);
+                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
+                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
+                        *(sp + 5) = (png_byte)(v & 0xff);
+                     }
+                  }
+               }
+               else
+#endif
+               {
+                  sp = row;
+                  for (i = 0; i < row_width; i++, sp += 6)
+                  {
+                     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1));
+                     png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
+                     png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
+
+                     if (r == trans_values->red && g == trans_values->green &&
+                        b == trans_values->blue)
+                     {
+                        *sp = (png_byte)((background->red >> 8) & 0xff);
+                        *(sp + 1) = (png_byte)(background->red & 0xff);
+                        *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
+                        *(sp + 3) = (png_byte)(background->green & 0xff);
+                        *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
+                        *(sp + 5) = (png_byte)(background->blue & 0xff);
+                     }
+                  }
+               }
+            }
+            break;
+         }
+         case PNG_COLOR_TYPE_GRAY_ALPHA:
+         {
+            if (row_info->bit_depth == 8)
+            {
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
+                   gamma_table != NULL)
+               {
+                  sp = row;
+                  dp = row;
+                  for (i = 0; i < row_width; i++, sp += 2, dp++)
+                  {
+                     png_uint_16 a = *(sp + 1);
+
+                     if (a == 0xff)
+                     {
+                        *dp = gamma_table[*sp];
+                     }
+                     else if (a == 0)
+                     {
+                        /* background is already in screen gamma */
+                        *dp = (png_byte)background->gray;
+                     }
+                     else
+                     {
+                        png_byte v, w;
+
+                        v = gamma_to_1[*sp];
+                        png_composite(w, v, a, background_1->gray);
+                        *dp = gamma_from_1[w];
+                     }
+                  }
+               }
+               else
+#endif
+               {
+                  sp = row;
+                  dp = row;
+                  for (i = 0; i < row_width; i++, sp += 2, dp++)
+                  {
+                     png_byte a = *(sp + 1);
+
+                     if (a == 0xff)
+                     {
+                        *dp = *sp;
+                     }
+                     else if (a == 0)
+                     {
+                        *dp = (png_byte)background->gray;
+                     }
+                     else
+                     {
+                        png_composite(*dp, *sp, a, background_1->gray);
+                     }
+                  }
+               }
+            }
+            else /* if (png_ptr->bit_depth == 16) */
+            {
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+               if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
+                   gamma_16_to_1 != NULL)
+               {
+                  sp = row;
+                  dp = row;
+                  for (i = 0; i < row_width; i++, sp += 4, dp += 2)
+                  {
+                     png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
+
+                     if (a == (png_uint_16)0xffff)
+                     {
+                        png_uint_16 v;
+
+                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
+                        *dp = (png_byte)((v >> 8) & 0xff);
+                        *(dp + 1) = (png_byte)(v & 0xff);
+                     }
+                     else if (a == 0)
+                     {
+                        /* background is already in screen gamma */
+                        *dp = (png_byte)((background->gray >> 8) & 0xff);
+                        *(dp + 1) = (png_byte)(background->gray & 0xff);
+                     }
+                     else
+                     {
+                        png_uint_16 g, v, w;
+
+                        g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
+                        png_composite_16(v, g, a, background_1->gray);
+                        w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
+                        *dp = (png_byte)((w >> 8) & 0xff);
+                        *(dp + 1) = (png_byte)(w & 0xff);
+                     }
+                  }
+               }
+               else
+#endif
+               {
+                  sp = row;
+                  dp = row;
+                  for (i = 0; i < row_width; i++, sp += 4, dp += 2)
+                  {
+                     png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
+                     if (a == (png_uint_16)0xffff)
+                     {
+                        png_memcpy(dp, sp, 2);
+                     }
+                     else if (a == 0)
+                     {
+                        *dp = (png_byte)((background->gray >> 8) & 0xff);
+                        *(dp + 1) = (png_byte)(background->gray & 0xff);
+                     }
+                     else
+                     {
+                        png_uint_16 g, v;
+
+                        g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
+                        png_composite_16(v, g, a, background_1->gray);
+                        *dp = (png_byte)((v >> 8) & 0xff);
+                        *(dp + 1) = (png_byte)(v & 0xff);
+                     }
+                  }
+               }
+            }
+            break;
+         }
+         case PNG_COLOR_TYPE_RGB_ALPHA:
+         {
+            if (row_info->bit_depth == 8)
+            {
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
+                   gamma_table != NULL)
+               {
+                  sp = row;
+                  dp = row;
+                  for (i = 0; i < row_width; i++, sp += 4, dp += 3)
+                  {
+                     png_byte a = *(sp + 3);
+
+                     if (a == 0xff)
+                     {
+                        *dp = gamma_table[*sp];
+                        *(dp + 1) = gamma_table[*(sp + 1)];
+                        *(dp + 2) = gamma_table[*(sp + 2)];
+                     }
+                     else if (a == 0)
+                     {
+                        /* background is already in screen gamma */
+                        *dp = (png_byte)background->red;
+                        *(dp + 1) = (png_byte)background->green;
+                        *(dp + 2) = (png_byte)background->blue;
+                     }
+                     else
+                     {
+                        png_byte v, w;
+
+                        v = gamma_to_1[*sp];
+                        png_composite(w, v, a, background_1->red);
+                        *dp = gamma_from_1[w];
+                        v = gamma_to_1[*(sp + 1)];
+                        png_composite(w, v, a, background_1->green);
+                        *(dp + 1) = gamma_from_1[w];
+                        v = gamma_to_1[*(sp + 2)];
+                        png_composite(w, v, a, background_1->blue);
+                        *(dp + 2) = gamma_from_1[w];
+                     }
+                  }
+               }
+               else
+#endif
+               {
+                  sp = row;
+                  dp = row;
+                  for (i = 0; i < row_width; i++, sp += 4, dp += 3)
+                  {
+                     png_byte a = *(sp + 3);
+
+                     if (a == 0xff)
+                     {
+                        *dp = *sp;
+                        *(dp + 1) = *(sp + 1);
+                        *(dp + 2) = *(sp + 2);
+                     }
+                     else if (a == 0)
+                     {
+                        *dp = (png_byte)background->red;
+                        *(dp + 1) = (png_byte)background->green;
+                        *(dp + 2) = (png_byte)background->blue;
+                     }
+                     else
+                     {
+                        png_composite(*dp, *sp, a, background->red);
+                        png_composite(*(dp + 1), *(sp + 1), a,
+                           background->green);
+                        png_composite(*(dp + 2), *(sp + 2), a,
+                           background->blue);
+                     }
+                  }
+               }
+            }
+            else /* if (row_info->bit_depth == 16) */
+            {
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+               if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
+                   gamma_16_to_1 != NULL)
+               {
+                  sp = row;
+                  dp = row;
+                  for (i = 0; i < row_width; i++, sp += 8, dp += 6)
+                  {
+                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
+                         << 8) + (png_uint_16)(*(sp + 7)));
+                     if (a == (png_uint_16)0xffff)
+                     {
+                        png_uint_16 v;
+
+                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
+                        *dp = (png_byte)((v >> 8) & 0xff);
+                        *(dp + 1) = (png_byte)(v & 0xff);
+                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
+                        *(dp + 2) = (png_byte)((v >> 8) & 0xff);
+                        *(dp + 3) = (png_byte)(v & 0xff);
+                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
+                        *(dp + 4) = (png_byte)((v >> 8) & 0xff);
+                        *(dp + 5) = (png_byte)(v & 0xff);
+                     }
+                     else if (a == 0)
+                     {
+                        /* background is already in screen gamma */
+                        *dp = (png_byte)((background->red >> 8) & 0xff);
+                        *(dp + 1) = (png_byte)(background->red & 0xff);
+                        *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
+                        *(dp + 3) = (png_byte)(background->green & 0xff);
+                        *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
+                        *(dp + 5) = (png_byte)(background->blue & 0xff);
+                     }
+                     else
+                     {
+                        png_uint_16 v, w, x;
+
+                        v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
+                        png_composite_16(w, v, a, background->red);
+                        x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
+                        *dp = (png_byte)((x >> 8) & 0xff);
+                        *(dp + 1) = (png_byte)(x & 0xff);
+                        v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
+                        png_composite_16(w, v, a, background->green);
+                        x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
+                        *(dp + 2) = (png_byte)((x >> 8) & 0xff);
+                        *(dp + 3) = (png_byte)(x & 0xff);
+                        v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
+                        png_composite_16(w, v, a, background->blue);
+                        x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8];
+                        *(dp + 4) = (png_byte)((x >> 8) & 0xff);
+                        *(dp + 5) = (png_byte)(x & 0xff);
+                     }
+                  }
+               }
+               else
+#endif
+               {
+                  sp = row;
+                  dp = row;
+                  for (i = 0; i < row_width; i++, sp += 8, dp += 6)
+                  {
+                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
+                        << 8) + (png_uint_16)(*(sp + 7)));
+                     if (a == (png_uint_16)0xffff)
+                     {
+                        png_memcpy(dp, sp, 6);
+                     }
+                     else if (a == 0)
+                     {
+                        *dp = (png_byte)((background->red >> 8) & 0xff);
+                        *(dp + 1) = (png_byte)(background->red & 0xff);
+                        *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
+                        *(dp + 3) = (png_byte)(background->green & 0xff);
+                        *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
+                        *(dp + 5) = (png_byte)(background->blue & 0xff);
+                     }
+                     else
+                     {
+                        png_uint_16 v;
+
+                        png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
+                        png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
+                            + *(sp + 3));
+                        png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
+                            + *(sp + 5));
+
+                        png_composite_16(v, r, a, background->red);
+                        *dp = (png_byte)((v >> 8) & 0xff);
+                        *(dp + 1) = (png_byte)(v & 0xff);
+                        png_composite_16(v, g, a, background->green);
+                        *(dp + 2) = (png_byte)((v >> 8) & 0xff);
+                        *(dp + 3) = (png_byte)(v & 0xff);
+                        png_composite_16(v, b, a, background->blue);
+                        *(dp + 4) = (png_byte)((v >> 8) & 0xff);
+                        *(dp + 5) = (png_byte)(v & 0xff);
+                     }
+                  }
+               }
+            }
+            break;
+         }
+      }
+
+      if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
+      {
+         row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
+         row_info->channels--;
+         row_info->pixel_depth = (png_byte)(row_info->channels *
+            row_info->bit_depth);
+         row_info->rowbytes = ((row_width *
+            row_info->pixel_depth + 7) >> 3);
+      }
+   }
+}
+#endif
+
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+/* Gamma correct the image, avoiding the alpha channel.  Make sure
+ * you do this after you deal with the transparency issue on grayscale
+ * or RGB images. If your bit depth is 8, use gamma_table, if it
+ * is 16, use gamma_16_table and gamma_shift.  Build these with
+ * build_gamma_table().
+ */
+void /* PRIVATE */
+png_do_gamma(png_row_infop row_info, png_bytep row,
+   png_bytep gamma_table, png_uint_16pp gamma_16_table,
+   int gamma_shift)
+{
+   png_bytep sp;
+   png_uint_32 i;
+   png_uint_32 row_width=row_info->width;
+
+   png_debug(1, "in png_do_gamma\n");
+   if (
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+       row != NULL && row_info != NULL &&
+#endif
+       ((row_info->bit_depth <= 8 && gamma_table != NULL) ||
+        (row_info->bit_depth == 16 && gamma_16_table != NULL)))
+   {
+      switch (row_info->color_type)
+      {
+         case PNG_COLOR_TYPE_RGB:
+         {
+            if (row_info->bit_depth == 8)
+            {
+               sp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  *sp = gamma_table[*sp];
+                  sp++;
+                  *sp = gamma_table[*sp];
+                  sp++;
+                  *sp = gamma_table[*sp];
+                  sp++;
+               }
+            }
+            else /* if (row_info->bit_depth == 16) */
+            {
+               sp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  png_uint_16 v;
+
+                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
+                  *sp = (png_byte)((v >> 8) & 0xff);
+                  *(sp + 1) = (png_byte)(v & 0xff);
+                  sp += 2;
+                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
+                  *sp = (png_byte)((v >> 8) & 0xff);
+                  *(sp + 1) = (png_byte)(v & 0xff);
+                  sp += 2;
+                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
+                  *sp = (png_byte)((v >> 8) & 0xff);
+                  *(sp + 1) = (png_byte)(v & 0xff);
+                  sp += 2;
+               }
+            }
+            break;
+         }
+         case PNG_COLOR_TYPE_RGB_ALPHA:
+         {
+            if (row_info->bit_depth == 8)
+            {
+               sp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  *sp = gamma_table[*sp];
+                  sp++;
+                  *sp = gamma_table[*sp];
+                  sp++;
+                  *sp = gamma_table[*sp];
+                  sp++;
+                  sp++;
+               }
+            }
+            else /* if (row_info->bit_depth == 16) */
+            {
+               sp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
+                  *sp = (png_byte)((v >> 8) & 0xff);
+                  *(sp + 1) = (png_byte)(v & 0xff);
+                  sp += 2;
+                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
+                  *sp = (png_byte)((v >> 8) & 0xff);
+                  *(sp + 1) = (png_byte)(v & 0xff);
+                  sp += 2;
+                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
+                  *sp = (png_byte)((v >> 8) & 0xff);
+                  *(sp + 1) = (png_byte)(v & 0xff);
+                  sp += 4;
+               }
+            }
+            break;
+         }
+         case PNG_COLOR_TYPE_GRAY_ALPHA:
+         {
+            if (row_info->bit_depth == 8)
+            {
+               sp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  *sp = gamma_table[*sp];
+                  sp += 2;
+               }
+            }
+            else /* if (row_info->bit_depth == 16) */
+            {
+               sp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
+                  *sp = (png_byte)((v >> 8) & 0xff);
+                  *(sp + 1) = (png_byte)(v & 0xff);
+                  sp += 4;
+               }
+            }
+            break;
+         }
+         case PNG_COLOR_TYPE_GRAY:
+         {
+            if (row_info->bit_depth == 2)
+            {
+               sp = row;
+               for (i = 0; i < row_width; i += 4)
+               {
+                  int a = *sp & 0xc0;
+                  int b = *sp & 0x30;
+                  int c = *sp & 0x0c;
+                  int d = *sp & 0x03;
+
+                  *sp = (png_byte)(
+                        ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)])   ) & 0xc0)|
+                        ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
+                        ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
+                        ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
+                  sp++;
+               }
+            }
+            if (row_info->bit_depth == 4)
+            {
+               sp = row;
+               for (i = 0; i < row_width; i += 2)
+               {
+                  int msb = *sp & 0xf0;
+                  int lsb = *sp & 0x0f;
+
+                  *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
+                          | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
+                  sp++;
+               }
+            }
+            else if (row_info->bit_depth == 8)
+            {
+               sp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  *sp = gamma_table[*sp];
+                  sp++;
+               }
+            }
+            else if (row_info->bit_depth == 16)
+            {
+               sp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
+                  *sp = (png_byte)((v >> 8) & 0xff);
+                  *(sp + 1) = (png_byte)(v & 0xff);
+                  sp += 2;
+               }
+            }
+            break;
+         }
+      }
+   }
+}
+#endif
+
+#if defined(PNG_READ_EXPAND_SUPPORTED)
+/* Expands a palette row to an RGB or RGBA row depending
+ * upon whether you supply trans and num_trans.
+ */
+void /* PRIVATE */
+png_do_expand_palette(png_row_infop row_info, png_bytep row,
+   png_colorp palette, png_bytep trans, int num_trans)
+{
+   int shift, value;
+   png_bytep sp, dp;
+   png_uint_32 i;
+   png_uint_32 row_width=row_info->width;
+
+   png_debug(1, "in png_do_expand_palette\n");
+   if (
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+       row != NULL && row_info != NULL &&
+#endif
+       row_info->color_type == PNG_COLOR_TYPE_PALETTE)
+   {
+      if (row_info->bit_depth < 8)
+      {
+         switch (row_info->bit_depth)
+         {
+            case 1:
+            {
+               sp = row + (png_size_t)((row_width - 1) >> 3);
+               dp = row + (png_size_t)row_width - 1;
+               shift = 7 - (int)((row_width + 7) & 0x07);
+               for (i = 0; i < row_width; i++)
+               {
+                  if ((*sp >> shift) & 0x01)
+                     *dp = 1;
+                  else
+                     *dp = 0;
+                  if (shift == 7)
+                  {
+                     shift = 0;
+                     sp--;
+                  }
+                  else
+                     shift++;
+
+                  dp--;
+               }
+               break;
+            }
+            case 2:
+            {
+               sp = row + (png_size_t)((row_width - 1) >> 2);
+               dp = row + (png_size_t)row_width - 1;
+               shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
+               for (i = 0; i < row_width; i++)
+               {
+                  value = (*sp >> shift) & 0x03;
+                  *dp = (png_byte)value;
+                  if (shift == 6)
+                  {
+                     shift = 0;
+                     sp--;
+                  }
+                  else
+                     shift += 2;
+
+                  dp--;
+               }
+               break;
+            }
+            case 4:
+            {
+               sp = row + (png_size_t)((row_width - 1) >> 1);
+               dp = row + (png_size_t)row_width - 1;
+               shift = (int)((row_width & 0x01) << 2);
+               for (i = 0; i < row_width; i++)
+               {
+                  value = (*sp >> shift) & 0x0f;
+                  *dp = (png_byte)value;
+                  if (shift == 4)
+                  {
+                     shift = 0;
+                     sp--;
+                  }
+                  else
+                     shift += 4;
+
+                  dp--;
+               }
+               break;
+            }
+         }
+         row_info->bit_depth = 8;
+         row_info->pixel_depth = 8;
+         row_info->rowbytes = row_width;
+      }
+      switch (row_info->bit_depth)
+      {
+         case 8:
+         {
+            if (trans != NULL)
+            {
+               sp = row + (png_size_t)row_width - 1;
+               dp = row + (png_size_t)(row_width << 2) - 1;
+
+               for (i = 0; i < row_width; i++)
+               {
+                  if ((int)(*sp) >= num_trans)
+                     *dp-- = 0xff;
+                  else
+                     *dp-- = trans[*sp];
+                  *dp-- = palette[*sp].blue;
+                  *dp-- = palette[*sp].green;
+                  *dp-- = palette[*sp].red;
+                  sp--;
+               }
+               row_info->bit_depth = 8;
+               row_info->pixel_depth = 32;
+               row_info->rowbytes = row_width * 4;
+               row_info->color_type = 6;
+               row_info->channels = 4;
+            }
+            else
+            {
+               sp = row + (png_size_t)row_width - 1;
+               dp = row + (png_size_t)(row_width * 3) - 1;
+
+               for (i = 0; i < row_width; i++)
+               {
+                  *dp-- = palette[*sp].blue;
+                  *dp-- = palette[*sp].green;
+                  *dp-- = palette[*sp].red;
+                  sp--;
+               }
+               row_info->bit_depth = 8;
+               row_info->pixel_depth = 24;
+               row_info->rowbytes = row_width * 3;
+               row_info->color_type = 2;
+               row_info->channels = 3;
+            }
+            break;
+         }
+      }
+   }
+}
+
+/* If the bit depth < 8, it is expanded to 8.  Also, if the
+ * transparency value is supplied, an alpha channel is built.
+ */
+void /* PRIVATE */
+png_do_expand(png_row_infop row_info, png_bytep row,
+   png_color_16p trans_value)
+{
+   int shift, value;
+   png_bytep sp, dp;
+   png_uint_32 i;
+   png_uint_32 row_width=row_info->width;
+
+   png_debug(1, "in png_do_expand\n");
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   if (row != NULL && row_info != NULL)
+#endif
+   {
+      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
+      {
+         png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0);
+
+         if (row_info->bit_depth < 8)
+         {
+            switch (row_info->bit_depth)
+            {
+               case 1:
+               {
+                  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) & 0x07);
+                  for (i = 0; i < row_width; i++)
+                  {
+                     if ((*sp >> shift) & 0x01)
+                        *dp = 0xff;
+                     else
+                        *dp = 0;
+                     if (shift == 7)
+                     {
+                        shift = 0;
+                        sp--;
+                     }
+                     else
+                        shift++;
+
+                     dp--;
+                  }
+                  break;
+               }
+               case 2:
+               {
+                  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) & 0x03)) << 1);
+                  for (i = 0; i < row_width; i++)
+                  {
+                     value = (*sp >> shift) & 0x03;
+                     *dp = (png_byte)(value | (value << 2) | (value << 4) |
+                        (value << 6));
+                     if (shift == 6)
+                     {
+                        shift = 0;
+                        sp--;
+                     }
+                     else
+                        shift += 2;
+
+                     dp--;
+                  }
+                  break;
+               }
+               case 4:
+               {
+                  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) & 0x01)) << 2);
+                  for (i = 0; i < row_width; i++)
+                  {
+                     value = (*sp >> shift) & 0x0f;
+                     *dp = (png_byte)(value | (value << 4));
+                     if (shift == 4)
+                     {
+                        shift = 0;
+                        sp--;
+                     }
+                     else
+                        shift = 4;
+
+                     dp--;
+                  }
+                  break;
+               }
+            }
+            row_info->bit_depth = 8;
+            row_info->pixel_depth = 8;
+            row_info->rowbytes = row_width;
+         }
+
+         if (trans_value != NULL)
+         {
+            if (row_info->bit_depth == 8)
+            {
+               sp = row + (png_size_t)row_width - 1;
+               dp = row + (png_size_t)(row_width << 1) - 1;
+               for (i = 0; i < row_width; i++)
+               {
+                  if (*sp == gray)
+                     *dp-- = 0;
+                  else
+                     *dp-- = 0xff;
+                  *dp-- = *sp--;
+               }
+            }
+            else if (row_info->bit_depth == 16)
+            {
+               sp = row + row_info->rowbytes - 1;
+               dp = row + (row_info->rowbytes << 1) - 1;
+               for (i = 0; i < row_width; i++)
+               {
+                  if (((png_uint_16)*(sp) |
+                     ((png_uint_16)*(sp - 1) << 8)) == gray)
+                  {
+                     *dp-- = 0;
+                     *dp-- = 0;
+                  }
+                  else
+                  {
+                     *dp-- = 0xff;
+                     *dp-- = 0xff;
+                  }
+                  *dp-- = *sp--;
+                  *dp-- = *sp--;
+               }
+            }
+            row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
+            row_info->channels = 2;
+            row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
+            row_info->rowbytes =
+               ((row_width * row_info->pixel_depth) >> 3);
+         }
+      }
+      else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value)
+      {
+         if (row_info->bit_depth == 8)
+         {
+            sp = row + (png_size_t)row_info->rowbytes - 1;
+            dp = row + (png_size_t)(row_width << 2) - 1;
+            for (i = 0; i < row_width; i++)
+            {
+               if (*(sp - 2) == trans_value->red &&
+                  *(sp - 1) == trans_value->green &&
+                  *(sp - 0) == trans_value->blue)
+                  *dp-- = 0;
+               else
+                  *dp-- = 0xff;
+               *dp-- = *sp--;
+               *dp-- = *sp--;
+               *dp-- = *sp--;
+            }
+         }
+         else if (row_info->bit_depth == 16)
+         {
+            sp = row + row_info->rowbytes - 1;
+            dp = row + (png_size_t)(row_width << 3) - 1;
+            for (i = 0; i < row_width; i++)
+            {
+               if ((((png_uint_16)*(sp - 4) |
+                  ((png_uint_16)*(sp - 5) << 8)) == trans_value->red) &&
+                  (((png_uint_16)*(sp - 2) |
+                  ((png_uint_16)*(sp - 3) << 8)) == trans_value->green) &&
+                  (((png_uint_16)*(sp - 0) |
+                  ((png_uint_16)*(sp - 1) << 8)) == trans_value->blue))
+               {
+                  *dp-- = 0;
+                  *dp-- = 0;
+               }
+               else
+               {
+                  *dp-- = 0xff;
+                  *dp-- = 0xff;
+               }
+               *dp-- = *sp--;
+               *dp-- = *sp--;
+               *dp-- = *sp--;
+               *dp-- = *sp--;
+               *dp-- = *sp--;
+               *dp-- = *sp--;
+            }
+         }
+         row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+         row_info->channels = 4;
+         row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
+         row_info->rowbytes =
+            ((row_width * row_info->pixel_depth) >> 3);
+      }
+   }
+}
+#endif
+
+#if defined(PNG_READ_DITHER_SUPPORTED)
+void /* PRIVATE */
+png_do_dither(png_row_infop row_info, png_bytep row,
+    png_bytep palette_lookup, png_bytep dither_lookup)
+{
+   png_bytep sp, dp;
+   png_uint_32 i;
+   png_uint_32 row_width=row_info->width;
+
+   png_debug(1, "in png_do_dither\n");
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   if (row != NULL && row_info != NULL)
+#endif
+   {
+      if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
+         palette_lookup && row_info->bit_depth == 8)
+      {
+         int r, g, b, p;
+         sp = row;
+         dp = row;
+         for (i = 0; i < row_width; i++)
+         {
+            r = *sp++;
+            g = *sp++;
+            b = *sp++;
+
+            /* this looks real messy, but the compiler will reduce
+               it down to a reasonable formula.  For example, with
+               5 bits per color, we get:
+               p = (((r >> 3) & 0x1f) << 10) |
+                  (((g >> 3) & 0x1f) << 5) |
+                  ((b >> 3) & 0x1f);
+               */
+            p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
+               ((1 << PNG_DITHER_RED_BITS) - 1)) <<
+               (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
+               (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
+               ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
+               (PNG_DITHER_BLUE_BITS)) |
+               ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
+               ((1 << PNG_DITHER_BLUE_BITS) - 1));
+
+            *dp++ = palette_lookup[p];
+         }
+         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
+         row_info->channels = 1;
+         row_info->pixel_depth = row_info->bit_depth;
+         row_info->rowbytes =
+             ((row_width * row_info->pixel_depth + 7) >> 3);
+      }
+      else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
+         palette_lookup != NULL && row_info->bit_depth == 8)
+      {
+         int r, g, b, p;
+         sp = row;
+         dp = row;
+         for (i = 0; i < row_width; i++)
+         {
+            r = *sp++;
+            g = *sp++;
+            b = *sp++;
+            sp++;
+
+            p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
+               ((1 << PNG_DITHER_RED_BITS) - 1)) <<
+               (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
+               (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
+               ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
+               (PNG_DITHER_BLUE_BITS)) |
+               ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
+               ((1 << PNG_DITHER_BLUE_BITS) - 1));
+
+            *dp++ = palette_lookup[p];
+         }
+         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
+         row_info->channels = 1;
+         row_info->pixel_depth = row_info->bit_depth;
+         row_info->rowbytes =
+            ((row_width * row_info->pixel_depth + 7) >> 3);
+      }
+      else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
+         dither_lookup && row_info->bit_depth == 8)
+      {
+         sp = row;
+         for (i = 0; i < row_width; i++, sp++)
+         {
+            *sp = dither_lookup[*sp];
+         }
+      }
+   }
+}
+#endif
+
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+static int png_gamma_shift[] =
+   {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0};
+
+/* We build the 8- or 16-bit gamma tables here.  Note that for 16-bit
+ * tables, we don't make a full table if we are reducing to 8-bit in
+ * the future.  Note also how the gamma_16 tables are segmented so that
+ * we don't need to allocate > 64K chunks for a full 16-bit table.
+ */
+void /* PRIVATE */
+png_build_gamma_table(png_structp png_ptr)
+{
+  png_debug(1, "in png_build_gamma_table\n");
+  if(png_ptr->gamma != 0.0)
+  {
+   if (png_ptr->bit_depth <= 8)
+   {
+      int i;
+      double g;
+
+      if (png_ptr->screen_gamma > .000001)
+         g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
+      else
+         g = 1.0;
+
+      png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr,
+         (png_uint_32)256);
+
+      for (i = 0; i < 256; i++)
+      {
+         png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0,
+            g) * 255.0 + .5);
+      }
+
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
+    defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+      if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY))
+      {
+
+         g = 1.0 / (png_ptr->gamma);
+
+         png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr,
+            (png_uint_32)256);
+
+         for (i = 0; i < 256; i++)
+         {
+            png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0,
+               g) * 255.0 + .5);
+         }
+
+
+         png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr,
+            (png_uint_32)256);
+
+         if(png_ptr->screen_gamma > 0.000001)
+            g = 1.0 / png_ptr->screen_gamma;
+         else
+            g = png_ptr->gamma;   /* probably doing rgb_to_gray */
+
+         for (i = 0; i < 256; i++)
+         {
+            png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0,
+               g) * 255.0 + .5);
+
+         }
+      }
+#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
+   }
+   else
+   {
+      double g;
+      int i, j, shift, num;
+      int sig_bit;
+      png_uint_32 ig;
+
+      if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
+      {
+         sig_bit = (int)png_ptr->sig_bit.red;
+         if ((int)png_ptr->sig_bit.green > sig_bit)
+            sig_bit = png_ptr->sig_bit.green;
+         if ((int)png_ptr->sig_bit.blue > sig_bit)
+            sig_bit = png_ptr->sig_bit.blue;
+      }
+      else
+      {
+         sig_bit = (int)png_ptr->sig_bit.gray;
+      }
+
+      if (sig_bit > 0)
+         shift = 16 - sig_bit;
+      else
+         shift = 0;
+
+      if (png_ptr->transformations & PNG_16_TO_8)
+      {
+         if (shift < (16 - PNG_MAX_GAMMA_8))
+            shift = (16 - PNG_MAX_GAMMA_8);
+      }
+
+      if (shift > 8)
+         shift = 8;
+      if (shift < 0)
+         shift = 0;
+
+      png_ptr->gamma_shift = (png_byte)shift;
+
+      num = (1 << (8 - shift));
+
+      if (png_ptr->screen_gamma > .000001)
+         g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
+      else
+         g = 1.0;
+
+      png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr,
+         (png_uint_32)(num * sizeof (png_uint_16p)));
+
+      if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND))
+      {
+         double fin, fout;
+         png_uint_32 last, max;
+
+         for (i = 0; i < num; i++)
+         {
+            png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
+               (png_uint_32)(256 * sizeof (png_uint_16)));
+         }
+
+         g = 1.0 / g;
+         last = 0;
+         for (i = 0; i < 256; i++)
+         {
+            fout = ((double)i + 0.5) / 256.0;
+            fin = pow(fout, g);
+            max = (png_uint_32)(fin * (double)((png_uint_32)num << 8));
+            while (last <= max)
+            {
+               png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
+                  [(int)(last >> (8 - shift))] = (png_uint_16)(
+                  (png_uint_16)i | ((png_uint_16)i << 8));
+               last++;
+            }
+         }
+         while (last < ((png_uint_32)num << 8))
+         {
+            png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
+               [(int)(last >> (8 - shift))] = (png_uint_16)65535L;
+            last++;
+         }
+      }
+      else
+      {
+         for (i = 0; i < num; i++)
+         {
+            png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
+               (png_uint_32)(256 * sizeof (png_uint_16)));
+
+            ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4);
+            for (j = 0; j < 256; j++)
+            {
+               png_ptr->gamma_16_table[i][j] =
+                  (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
+                     65535.0, g) * 65535.0 + .5);
+            }
+         }
+      }
+
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
+    defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+      if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY))
+      {
+
+         g = 1.0 / (png_ptr->gamma);
+
+         png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr,
+            (png_uint_32)(num * sizeof (png_uint_16p )));
+
+         for (i = 0; i < num; i++)
+         {
+            png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr,
+               (png_uint_32)(256 * sizeof (png_uint_16)));
+
+            ig = (((png_uint_32)i *
+               (png_uint_32)png_gamma_shift[shift]) >> 4);
+            for (j = 0; j < 256; j++)
+            {
+               png_ptr->gamma_16_to_1[i][j] =
+                  (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
+                     65535.0, g) * 65535.0 + .5);
+            }
+         }
+
+         if(png_ptr->screen_gamma > 0.000001)
+            g = 1.0 / png_ptr->screen_gamma;
+         else
+            g = png_ptr->gamma;   /* probably doing rgb_to_gray */
+
+         png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr,
+            (png_uint_32)(num * sizeof (png_uint_16p)));
+
+         for (i = 0; i < num; i++)
+         {
+            png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr,
+               (png_uint_32)(256 * sizeof (png_uint_16)));
+
+            ig = (((png_uint_32)i *
+               (png_uint_32)png_gamma_shift[shift]) >> 4);
+            for (j = 0; j < 256; j++)
+            {
+               png_ptr->gamma_16_from_1[i][j] =
+                  (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
+                     65535.0, g) * 65535.0 + .5);
+            }
+         }
+      }
+#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
+   }
+ }
+}
+#endif
+/* To do: install integer version of png_build_gamma_table here */
+#endif
+
+#if defined(PNG_MNG_FEATURES_SUPPORTED)
+/* undoes intrapixel differencing  */
+void /* PRIVATE */
+png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
+{
+   png_debug(1, "in png_do_read_intrapixel\n");
+   if (
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+       row != NULL && row_info != NULL &&
+#endif
+       (row_info->color_type & PNG_COLOR_MASK_COLOR))
+   {
+      int bytes_per_pixel;
+      png_uint_32 row_width = row_info->width;
+      if (row_info->bit_depth == 8)
+      {
+         png_bytep rp;
+         png_uint_32 i;
+
+         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+            bytes_per_pixel = 3;
+         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+            bytes_per_pixel = 4;
+         else
+            return;
+
+         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
+         {
+            *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff);
+            *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff);
+         }
+      }
+      else if (row_info->bit_depth == 16)
+      {
+         png_bytep rp;
+         png_uint_32 i;
+
+         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+            bytes_per_pixel = 6;
+         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+            bytes_per_pixel = 8;
+         else
+            return;
+
+         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
+         {
+            png_uint_32 s0=*(rp  )<<8 | *(rp+1);
+            png_uint_32 s1=*(rp+2)<<8 | *(rp+3);
+            png_uint_32 s2=*(rp+4)<<8 | *(rp+5);
+            png_uint_32 red=(65536+s0+s1)&0xffff;
+            png_uint_32 blue=(65536+s2+s1)&0xffff;
+            *(rp  ) = (png_byte)((red>>8)&0xff);
+            *(rp+1) = (png_byte)(red&0xff);
+            *(rp+4) = (png_byte)((blue>>8)&0xff);
+            *(rp+5) = (png_byte)(blue&0xff);
+         }
+      }
+   }
+}
+#endif /* PNG_MNG_FEATURES_SUPPORTED */
diff --git a/Utilities/ITK/Utilities/png/pngrutil.c b/Utilities/ITK/Utilities/png/pngrutil.c
new file mode 100644
index 0000000000..ec970ce417
--- /dev/null
+++ b/Utilities/ITK/Utilities/png/pngrutil.c
@@ -0,0 +1,3000 @@
+
+/* pngrutil.c - utilities to read a PNG file
+ *
+ * libpng 1.0.12 - June 8, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This file contains routines that are only called from within
+ * libpng itself during the course of reading an image.
+ */
+
+#define PNG_INTERNAL
+#include "png.h"
+
+#if defined(_WIN32_WCE)
+/* strtod() function is not supported on WindowsCE */
+#  ifdef PNG_FLOATING_POINT_SUPPORTED
+__inline double strtod(const char *nptr, char **endptr)
+{
+   double result = 0;
+   int len;
+   wchar_t *str, *end;
+
+   len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0);
+   str = (wchar_t *)malloc(len * sizeof(wchar_t));
+   if ( NULL != str )
+   {
+      MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len);
+      result = wcstod(str, &end);
+      len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL);
+      *endptr = (char *)nptr + (png_strlen(nptr) - len + 1);
+      free(str);
+   }
+   return result;
+}
+#  endif
+#endif
+
+#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED
+/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
+png_uint_32 /* PRIVATE */
+png_get_uint_32(png_bytep buf)
+{
+   png_uint_32 i = ((png_uint_32)(*buf) << 24) +
+      ((png_uint_32)(*(buf + 1)) << 16) +
+      ((png_uint_32)(*(buf + 2)) << 8) +
+      (png_uint_32)(*(buf + 3));
+
+   return (i);
+}
+
+#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. */
+png_int_32 /* PRIVATE */
+png_get_int_32(png_bytep buf)
+{
+   png_int_32 i = ((png_int_32)(*buf) << 24) +
+      ((png_int_32)(*(buf + 1)) << 16) +
+      ((png_int_32)(*(buf + 2)) << 8) +
+      (png_int_32)(*(buf + 3));
+
+   return (i);
+}
+#endif /* PNG_READ_pCAL_SUPPORTED */
+
+/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
+png_uint_16 /* PRIVATE */
+png_get_uint_16(png_bytep buf)
+{
+   png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) +
+      (png_uint_16)(*(buf + 1)));
+
+   return (i);
+}
+#endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */
+
+/* Read data, and (optionally) run it through the CRC. */
+void /* PRIVATE */
+png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
+{
+   png_read_data(png_ptr, buf, length);
+   png_calculate_crc(png_ptr, buf, length);
+}
+
+/* Optionally skip data and then check the CRC.  Depending on whether we
+   are reading a ancillary or critical chunk, and how the program has set
+   things up, we may calculate the CRC on the data and print a message.
+   Returns '1' if there was a CRC error, '0' otherwise. */
+int /* PRIVATE */
+png_crc_finish(png_structp png_ptr, png_uint_32 skip)
+{
+   png_size_t i;
+   png_size_t istop = png_ptr->zbuf_size;
+
+   for (i = (png_size_t)skip; i > istop; i -= istop)
+   {
+      png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
+   }
+   if (i)
+   {
+      png_crc_read(png_ptr, png_ptr->zbuf, i);
+   }
+
+   if (png_crc_error(png_ptr))
+   {
+      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_chunk_warning(png_ptr, "CRC error");
+      }
+      else
+      {
+         png_chunk_error(png_ptr, "CRC error");
+      }
+      return (1);
+   }
+
+   return (0);
+}
+
+/* Compare the CRC stored in the PNG file with that calculated by libpng from
+   the data it has read thus far. */
+int /* PRIVATE */
+png_crc_error(png_structp png_ptr)
+{
+   png_byte crc_bytes[4];
+   png_uint_32 crc;
+   int need_crc = 1;
+
+   if (png_ptr->chunk_name[0] & 0x20)                     /* ancillary */
+   {
+      if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
+          (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
+         need_crc = 0;
+   }
+   else                                                    /* critical */
+   {
+      if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
+         need_crc = 0;
+   }
+
+   png_read_data(png_ptr, crc_bytes, 4);
+
+   if (need_crc)
+   {
+      crc = png_get_uint_32(crc_bytes);
+      return ((int)(crc != png_ptr->crc));
+   }
+   else
+      return (0);
+}
+
+#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \
+    defined(PNG_READ_iCCP_SUPPORTED)
+/*
+ * Decompress trailing data in a chunk.  The assumption is that chunkdata
+ * points at an allocated area holding the contents of a chunk with a
+ * trailing compressed part.  What we get back is an allocated area
+ * holding the original prefix part and an uncompressed version of the
+ * trailing part (the malloc area passed in is freed).
+ */
+png_charp /* PRIVATE */
+png_decompress_chunk(png_structp png_ptr, int comp_type,
+                              png_charp chunkdata, png_size_t chunklength,
+                              png_size_t prefix_size, png_size_t *newlength)
+{
+   static char msg[] = "Error decoding compressed text";
+   png_charp text = NULL;
+   png_size_t text_size;
+
+   if (comp_type == PNG_COMPRESSION_TYPE_BASE)
+   {
+      int ret = Z_OK;
+      png_ptr->zstream.next_in = (png_bytep)(chunkdata + prefix_size);
+      png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size);
+      png_ptr->zstream.next_out = png_ptr->zbuf;
+      png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+
+      text_size = 0;
+      text = NULL;
+
+      while (png_ptr->zstream.avail_in)
+      {
+         ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
+         if (ret != Z_OK && ret != Z_STREAM_END)
+         {
+            if (png_ptr->zstream.msg != NULL)
+               png_warning(png_ptr, png_ptr->zstream.msg);
+            else
+               png_warning(png_ptr, msg);
+            inflateReset(&png_ptr->zstream);
+            png_ptr->zstream.avail_in = 0;
+
+            if (text ==  NULL)
+            {
+               text_size = prefix_size + sizeof(msg) + 1;
+               text = (png_charp)png_malloc(png_ptr, text_size);
+               png_memcpy(text, chunkdata, prefix_size);
+            }
+
+            text[text_size - 1] = 0x00;
+
+            /* Copy what we can of the error message into the text chunk */
+            text_size = (png_size_t)(chunklength - (text - chunkdata) - 1);
+            text_size = sizeof(msg) > text_size ? text_size : sizeof(msg);
+            png_memcpy(text + prefix_size, msg, text_size + 1);
+            break;
+         }
+         if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END)
+         {
+            if (text == NULL)
+            {
+               text_size = prefix_size +
+                   png_ptr->zbuf_size - png_ptr->zstream.avail_out;
+               text = (png_charp)png_malloc(png_ptr, text_size + 1);
+               png_memcpy(text + prefix_size, png_ptr->zbuf,
+                    text_size - prefix_size);
+               png_memcpy(text, chunkdata, prefix_size);
+               *(text + text_size) = 0x00;
+            }
+            else
+            {
+               png_charp tmp;
+
+               tmp = text;
+               text = (png_charp)png_malloc(png_ptr, (png_uint_32)(text_size +
+                  png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1));
+               png_memcpy(text, tmp, text_size);
+               png_free(png_ptr, tmp);
+               png_memcpy(text + text_size, png_ptr->zbuf,
+                  (png_ptr->zbuf_size - png_ptr->zstream.avail_out));
+               text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
+               *(text + text_size) = 0x00;
+            }
+            if (ret == Z_STREAM_END)
+               break;
+            else
+            {
+               png_ptr->zstream.next_out = png_ptr->zbuf;
+               png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+            }
+         }
+      }
+      if (ret != Z_STREAM_END)
+      {
+#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
+         char umsg[50];
+
+         if (ret == Z_BUF_ERROR)
+            sprintf(umsg,"Buffer error in compressed datastream in %s chunk",
+                png_ptr->chunk_name);
+         else if (ret == Z_DATA_ERROR)
+            sprintf(umsg,"Data error in compressed datastream in %s chunk",
+                png_ptr->chunk_name);
+         else
+            sprintf(umsg,"Incomplete compressed datastream in %s chunk",
+                png_ptr->chunk_name);
+         png_warning(png_ptr, umsg);
+#else
+         png_warning(png_ptr,
+            "Incomplete compressed datastream in chunk other than IDAT");
+#endif
+         text_size=prefix_size;
+         if (text ==  NULL)
+         {
+            text = (png_charp)png_malloc(png_ptr, text_size+1);
+            png_memcpy(text, chunkdata, prefix_size);
+         }
+         *(text + text_size) = 0x00;
+      }
+
+      inflateReset(&png_ptr->zstream);
+      png_ptr->zstream.avail_in = 0;
+
+      png_free(png_ptr, chunkdata);
+      chunkdata = text;
+      *newlength=text_size;
+   }
+   else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
+   {
+#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
+      char umsg[50];
+
+      sprintf(umsg, "Unknown zTXt compression type %d", comp_type);
+      png_warning(png_ptr, umsg);
+#else
+      png_warning(png_ptr, "Unknown zTXt compression type");
+#endif
+
+      *(chunkdata + prefix_size) = 0x00;
+      *newlength=prefix_size;
+   }
+
+   return chunkdata;
+}
+#endif
+
+/* read and check the IDHR chunk */
+void /* PRIVATE */
+png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_byte buf[13];
+   png_uint_32 width, height;
+   int bit_depth, color_type, compression_type, filter_type;
+   int interlace_type;
+
+   png_debug(1, "in png_handle_IHDR\n");
+
+   if (png_ptr->mode & PNG_HAVE_IHDR)
+      png_error(png_ptr, "Out of place IHDR");
+
+   /* check the length */
+   if (length != 13)
+      png_error(png_ptr, "Invalid IHDR chunk");
+
+   png_ptr->mode |= PNG_HAVE_IHDR;
+
+   png_crc_read(png_ptr, buf, 13);
+   png_crc_finish(png_ptr, 0);
+
+   width = png_get_uint_32(buf);
+   height = png_get_uint_32(buf + 4);
+   bit_depth = buf[8];
+   color_type = buf[9];
+   compression_type = buf[10];
+   filter_type = buf[11];
+   interlace_type = buf[12];
+
+
+   /* set internal variables */
+   png_ptr->width = width;
+   png_ptr->height = height;
+   png_ptr->bit_depth = (png_byte)bit_depth;
+   png_ptr->interlaced = (png_byte)interlace_type;
+   png_ptr->color_type = (png_byte)color_type;
+#if defined(PNG_MNG_FEATURES_SUPPORTED)
+   png_ptr->filter_type = (png_byte)filter_type;
+#endif
+
+   /* find number of channels */
+   switch (png_ptr->color_type)
+   {
+      case PNG_COLOR_TYPE_GRAY:
+      case PNG_COLOR_TYPE_PALETTE:
+         png_ptr->channels = 1;
+         break;
+      case PNG_COLOR_TYPE_RGB:
+         png_ptr->channels = 3;
+         break;
+      case PNG_COLOR_TYPE_GRAY_ALPHA:
+         png_ptr->channels = 2;
+         break;
+      case PNG_COLOR_TYPE_RGB_ALPHA:
+         png_ptr->channels = 4;
+         break;
+   }
+
+   /* set up other useful info */
+   png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
+   png_ptr->channels);
+   png_ptr->rowbytes = ((png_ptr->width *
+      (png_uint_32)png_ptr->pixel_depth + 7) >> 3);
+   png_debug1(3,"bit_depth = %d\n", png_ptr->bit_depth);
+   png_debug1(3,"channels = %d\n", png_ptr->channels);
+   png_debug1(3,"rowbytes = %lu\n", png_ptr->rowbytes);
+   png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
+      color_type, interlace_type, compression_type, filter_type);
+}
+
+/* read and check the palette */
+void /* PRIVATE */
+png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_color palette[PNG_MAX_PALETTE_LENGTH];
+   int num, i;
+#ifndef PNG_NO_POINTER_INDEXING
+   png_colorp pal_ptr;
+#endif
+
+   png_debug(1, "in png_handle_PLTE\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before PLTE");
+   else if (png_ptr->mode & PNG_HAVE_IDAT)
+   {
+      png_warning(png_ptr, "Invalid PLTE after IDAT");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+   else if (png_ptr->mode & PNG_HAVE_PLTE)
+      png_error(png_ptr, "Duplicate PLTE chunk");
+
+   png_ptr->mode |= PNG_HAVE_PLTE;
+
+   if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
+   {
+      png_warning(png_ptr,
+        "Ignoring PLTE chunk in grayscale PNG");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
+   if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
+   {
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+#endif
+
+   if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
+   {
+      if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
+      {
+         png_warning(png_ptr, "Invalid palette chunk");
+         png_crc_finish(png_ptr, length);
+         return;
+      }
+      else
+      {
+         png_error(png_ptr, "Invalid palette chunk");
+      }
+   }
+
+   num = (int)length / 3;
+
+#ifndef PNG_NO_POINTER_INDEXING
+   for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
+   {
+      png_byte buf[3];
+
+      png_crc_read(png_ptr, buf, 3);
+      pal_ptr->red = buf[0];
+      pal_ptr->green = buf[1];
+      pal_ptr->blue = buf[2];
+   }
+#else
+   for (i = 0; i < num; i++)
+   {
+      png_byte buf[3];
+
+      png_crc_read(png_ptr, buf, 3);
+      /* don't depend upon png_color being any order */
+      palette[i].red = buf[0];
+      palette[i].green = buf[1];
+      palette[i].blue = buf[2];
+   }
+#endif
+
+   /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
+      whatever the normal CRC configuration tells us.  However, if we
+      have an RGB image, the PLTE can be considered ancillary, so
+      we will act as though it is. */
+#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
+   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+#endif
+   {
+      png_crc_finish(png_ptr, 0);
+   }
+#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
+   else if (png_crc_error(png_ptr))  /* Only if we have a CRC error */
+   {
+      /* If we don't want to use the data from an ancillary chunk,
+         we have two options: an error abort, or a warning and we
+         ignore the data in this chunk (which should be OK, since
+         it's considered ancillary for a RGB or RGBA image). */
+      if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
+      {
+         if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
+         {
+            png_chunk_error(png_ptr, "CRC error");
+         }
+         else
+         {
+            png_chunk_warning(png_ptr, "CRC error");
+            return;
+         }
+      }
+      /* Otherwise, we (optionally) emit a warning and use the chunk. */
+      else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
+      {
+         png_chunk_warning(png_ptr, "CRC error");
+      }
+   }
+#endif
+
+   png_set_PLTE(png_ptr, info_ptr, palette, num);
+
+#if defined(PNG_READ_tRNS_SUPPORTED)
+   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+   {
+      if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
+      {
+         if (png_ptr->num_trans > (png_uint_16)num)
+         {
+            png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
+            png_ptr->num_trans = (png_uint_16)num;
+         }
+         if (info_ptr->num_trans > (png_uint_16)num)
+         {
+            png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
+            info_ptr->num_trans = (png_uint_16)num;
+         }
+      }
+   }
+#endif
+
+}
+
+void /* PRIVATE */
+png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_debug(1, "in png_handle_IEND\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
+   {
+      png_error(png_ptr, "No image in file");
+
+      info_ptr = info_ptr; /* quiet compiler warnings about unused info_ptr */
+   }
+
+   png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
+
+   if (length != 0)
+   {
+      png_warning(png_ptr, "Incorrect IEND chunk length");
+   }
+   png_crc_finish(png_ptr, length);
+}
+
+#if defined(PNG_READ_gAMA_SUPPORTED)
+void /* PRIVATE */
+png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_fixed_point igamma;
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   float file_gamma;
+#endif
+   png_byte buf[4];
+
+   png_debug(1, "in png_handle_gAMA\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before gAMA");
+   else if (png_ptr->mode & PNG_HAVE_IDAT)
+   {
+      png_warning(png_ptr, "Invalid gAMA after IDAT");
+      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 gAMA chunk");
+
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
+#if defined(PNG_READ_sRGB_SUPPORTED)
+      && !(info_ptr->valid & PNG_INFO_sRGB)
+#endif
+      )
+   {
+      png_warning(png_ptr, "Duplicate gAMA chunk");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   if (length != 4)
+   {
+      png_warning(png_ptr, "Incorrect gAMA chunk length");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   png_crc_read(png_ptr, buf, 4);
+   if (png_crc_finish(png_ptr, 0))
+      return;
+
+   igamma = (png_fixed_point)png_get_uint_32(buf);
+   /* check for zero gamma */
+   if (igamma == 0)
+      {
+         png_warning(png_ptr,
+           "Ignoring gAMA chunk with gamma=0");
+         return;
+      }
+
+#if defined(PNG_READ_sRGB_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_sRGB)
+      if(igamma < 45000L || igamma > 46000L)
+      {
+         png_warning(png_ptr,
+           "Ignoring incorrect gAMA value when sRGB is also present");
+#ifndef PNG_NO_CONSOLE_IO
+         fprintf(stderr, "gamma = (%d/100000)\n", (int)igamma);
+#endif
+         return;
+      }
+#endif /* PNG_READ_sRGB_SUPPORTED */
+
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   file_gamma = (float)igamma / (float)100000.0;
+#  ifdef PNG_READ_GAMMA_SUPPORTED
+     png_ptr->gamma = file_gamma;
+#  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);
+#endif
+}
+#endif
+
+#if defined(PNG_READ_sBIT_SUPPORTED)
+void /* PRIVATE */
+png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_size_t truelen;
+   png_byte buf[4];
+
+   png_debug(1, "in png_handle_sBIT\n");
+
+   buf[0] = buf[1] = buf[2] = buf[3] = 0;
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before sBIT");
+   else if (png_ptr->mode & PNG_HAVE_IDAT)
+   {
+      png_warning(png_ptr, "Invalid sBIT after IDAT");
+      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 sBIT chunk");
+   }
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
+   {
+      png_warning(png_ptr, "Duplicate sBIT chunk");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+      truelen = 3;
+   else
+      truelen = (png_size_t)png_ptr->channels;
+
+   if (length != truelen)
+   {
+      png_warning(png_ptr, "Incorrect sBIT chunk length");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   png_crc_read(png_ptr, buf, truelen);
+   if (png_crc_finish(png_ptr, 0))
+      return;
+
+   if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
+   {
+      png_ptr->sig_bit.red = buf[0];
+      png_ptr->sig_bit.green = buf[1];
+      png_ptr->sig_bit.blue = buf[2];
+      png_ptr->sig_bit.alpha = buf[3];
+   }
+   else
+   {
+      png_ptr->sig_bit.gray = buf[0];
+      png_ptr->sig_bit.red = buf[0];
+      png_ptr->sig_bit.green = buf[0];
+      png_ptr->sig_bit.blue = buf[0];
+      png_ptr->sig_bit.alpha = buf[1];
+   }
+   png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
+}
+#endif
+
+#if defined(PNG_READ_cHRM_SUPPORTED)
+void /* PRIVATE */
+png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_byte buf[4];
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
+#endif
+   png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
+      int_y_green, int_x_blue, int_y_blue;
+
+   png_debug(1, "in png_handle_cHRM\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before cHRM");
+   else if (png_ptr->mode & PNG_HAVE_IDAT)
+   {
+      png_warning(png_ptr, "Invalid cHRM after IDAT");
+      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, "Missing PLTE before 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
+      )
+   {
+      png_warning(png_ptr, "Duplicate cHRM chunk");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   if (length != 32)
+   {
+      png_warning(png_ptr, "Incorrect cHRM chunk length");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   png_crc_read(png_ptr, buf, 4);
+   int_x_white = (png_fixed_point)png_get_uint_32(buf);
+
+   png_crc_read(png_ptr, buf, 4);
+   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)
+   {
+      png_warning(png_ptr, "Invalid cHRM white point");
+      png_crc_finish(png_ptr, 24);
+      return;
+   }
+
+   png_crc_read(png_ptr, buf, 4);
+   int_x_red = (png_fixed_point)png_get_uint_32(buf);
+
+   png_crc_read(png_ptr, buf, 4);
+   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)
+   {
+      png_warning(png_ptr, "Invalid cHRM red point");
+      png_crc_finish(png_ptr, 16);
+      return;
+   }
+
+   png_crc_read(png_ptr, buf, 4);
+   int_x_green = (png_fixed_point)png_get_uint_32(buf);
+
+   png_crc_read(png_ptr, buf, 4);
+   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)
+   {
+      png_warning(png_ptr, "Invalid cHRM green point");
+      png_crc_finish(png_ptr, 8);
+      return;
+   }
+
+   png_crc_read(png_ptr, buf, 4);
+   int_x_blue = (png_fixed_point)png_get_uint_32(buf);
+
+   png_crc_read(png_ptr, buf, 4);
+   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)
+   {
+      png_warning(png_ptr, "Invalid cHRM blue point");
+      png_crc_finish(png_ptr, 0);
+      return;
+   }
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   white_x = (float)int_x_white / (float)100000.0;
+   white_y = (float)int_y_white / (float)100000.0;
+   red_x   = (float)int_x_red   / (float)100000.0;
+   red_y   = (float)int_y_red   / (float)100000.0;
+   green_x = (float)int_x_green / (float)100000.0;
+   green_y = (float)int_y_green / (float)100000.0;
+   blue_x  = (float)int_x_blue  / (float)100000.0;
+   blue_y  = (float)int_y_blue  / (float)100000.0;
+#endif
+
+#if defined(PNG_READ_sRGB_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_sRGB)
+      {
+      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,
+              "Ignoring incorrect cHRM value when sRGB is also present");
+#ifndef PNG_NO_CONSOLE_IO
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+            fprintf(stderr,"wx=%f, wy=%f, rx=%f, ry=%f\n",
+               white_x, white_y, red_x, red_y);
+            fprintf(stderr,"gx=%f, gy=%f, bx=%f, by=%f\n",
+               green_x, green_y, blue_x, blue_y);
+#else
+            fprintf(stderr,"wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
+               int_x_white, int_y_white, int_x_red, int_y_red);
+            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 */
+
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   png_set_cHRM(png_ptr, info_ptr,
+      white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   png_set_cHRM_fixed(png_ptr, info_ptr,
+      int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
+      int_y_green, int_x_blue, int_y_blue);
+#endif
+   if (png_crc_finish(png_ptr, 0))
+      return;
+}
+#endif
+
+#if defined(PNG_READ_sRGB_SUPPORTED)
+void /* PRIVATE */
+png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   int intent;
+   png_byte buf[1];
+
+   png_debug(1, "in png_handle_sRGB\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before sRGB");
+   else if (png_ptr->mode & PNG_HAVE_IDAT)
+   {
+      png_warning(png_ptr, "Invalid sRGB after IDAT");
+      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 sRGB chunk");
+
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
+   {
+      png_warning(png_ptr, "Duplicate sRGB chunk");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   if (length != 1)
+   {
+      png_warning(png_ptr, "Incorrect sRGB chunk length");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   png_crc_read(png_ptr, buf, 1);
+   if (png_crc_finish(png_ptr, 0))
+      return;
+
+   intent = buf[0];
+   /* check for bad intent */
+   if (intent >= PNG_sRGB_INTENT_LAST)
+   {
+      png_warning(png_ptr, "Unknown sRGB intent");
+      return;
+   }
+
+#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
+   if ((info_ptr->valid & PNG_INFO_gAMA))
+   {
+   int igamma;
+#ifdef PNG_FIXED_POINT_SUPPORTED
+      igamma=(int)info_ptr->int_gamma;
+#else
+#  ifdef PNG_FLOATING_POINT_SUPPORTED
+      igamma=(int)(info_ptr->gamma * 100000.);
+#  endif
+#endif
+#if 0 && defined(PNG_cHRM_SUPPORTED) && !defined(PNG_FIXED_POINT_SUPPORTED)
+/* We need to define these here because they aren't in png.h */
+   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
+      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_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
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   if (info_ptr->valid & PNG_INFO_cHRM)
+      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");
+         }
+#endif /* PNG_FIXED_POINT_SUPPORTED */
+#endif /* PNG_READ_cHRM_SUPPORTED */
+
+   png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
+}
+#endif /* PNG_READ_sRGB_SUPPORTED */
+
+#if defined(PNG_READ_iCCP_SUPPORTED)
+void /* PRIVATE */
+png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+/* Note: this does not properly handle chunks that are > 64K under DOS */
+{
+   png_charp chunkdata;
+   png_byte compression_type;
+   png_charp profile;
+   png_uint_32 skip = 0;
+   png_uint_32 profile_size = 0;
+   png_uint_32 profile_length = 0;
+   png_size_t slength, prefix_length, data_length;
+
+   png_debug(1, "in png_handle_iCCP\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before iCCP");
+   else if (png_ptr->mode & PNG_HAVE_IDAT)
+   {
+      png_warning(png_ptr, "Invalid iCCP after IDAT");
+      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 iCCP chunk");
+
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
+   {
+      png_warning(png_ptr, "Duplicate iCCP chunk");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+#ifdef PNG_MAX_MALLOC_64K
+   if (length > (png_uint_32)65535L)
+   {
+      png_warning(png_ptr, "iCCP chunk too large to fit in memory");
+      skip = length - (png_uint_32)65535L;
+      length = (png_uint_32)65535L;
+   }
+#endif
+
+   chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
+   slength = (png_size_t)length;
+   png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
+
+   if (png_crc_finish(png_ptr, skip))
+   {
+      png_free(png_ptr, chunkdata);
+      return;
+   }
+
+   chunkdata[slength] = 0x00;
+
+   for (profile = chunkdata; *profile; profile++)
+      /* empty loop to find end of name */ ;
+
+   ++profile;
+
+   /* there should be at least one zero (the compression type byte)
+      following the separator, and we should be on it  */
+   if ( profile >= chunkdata + slength)
+   {
+      png_free(png_ptr, chunkdata);
+      png_warning(png_ptr, "Malformed iCCP chunk");
+      return;
+   }
+
+   /* compression_type should always be zero */
+   compression_type = *profile++;
+   if (compression_type)
+   {
+      png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
+      compression_type=0x00;  /* Reset it to zero (libpng-1.0.6 through 1.0.8
+                                 wrote nonzero) */
+   }
+
+   prefix_length = profile - chunkdata;
+   chunkdata = png_decompress_chunk(png_ptr, compression_type, chunkdata,
+                                    slength, prefix_length, &data_length);
+
+   profile_length = data_length - prefix_length;
+
+   if ( profile_length < 4)
+   {
+      png_free(png_ptr, chunkdata);
+      png_warning(png_ptr, "Profile size field missing from iCCP chunk");
+      return;
+   }
+
+   /* Check the profile_size recorded in the first 32 bits of the ICC profile */
+   profile_size = ((*(chunkdata+prefix_length))<<24) |
+                  ((*(chunkdata+prefix_length+1))<<16) |
+                  ((*(chunkdata+prefix_length+2))<< 8) |
+                  ((*(chunkdata+prefix_length+3))    );
+
+   if(profile_size < profile_length)
+      profile_length = profile_size;
+
+   if(profile_size > profile_length)
+   {
+      png_free(png_ptr, chunkdata);
+      png_warning(png_ptr, "Ignoring truncated iCCP profile.\n");
+      return;
+   }
+
+   png_set_iCCP(png_ptr, info_ptr, chunkdata, compression_type,
+                chunkdata + prefix_length, profile_length);
+   png_free(png_ptr, chunkdata);
+}
+#endif /* PNG_READ_iCCP_SUPPORTED */
+
+#if defined(PNG_READ_sPLT_SUPPORTED)
+void /* PRIVATE */
+png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+/* Note: this does not properly handle chunks that are > 64K under DOS */
+{
+   png_bytep chunkdata;
+   png_bytep entry_start;
+   png_sPLT_t new_palette;
+#ifdef PNG_NO_POINTER_INDEXING
+   png_sPLT_entryp pp;
+#endif
+   int data_length, entry_size, i;
+   png_uint_32 skip = 0;
+   png_size_t slength;
+
+   png_debug(1, "in png_handle_sPLT\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before sPLT");
+   else if (png_ptr->mode & PNG_HAVE_IDAT)
+   {
+      png_warning(png_ptr, "Invalid sPLT after IDAT");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+#ifdef PNG_MAX_MALLOC_64K
+   if (length > (png_uint_32)65535L)
+   {
+      png_warning(png_ptr, "sPLT chunk too large to fit in memory");
+      skip = length - (png_uint_32)65535L;
+      length = (png_uint_32)65535L;
+   }
+#endif
+
+   chunkdata = (png_bytep)png_malloc(png_ptr, length + 1);
+   slength = (png_size_t)length;
+   png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
+
+   if (png_crc_finish(png_ptr, skip))
+   {
+      png_free(png_ptr, chunkdata);
+      return;
+   }
+
+   chunkdata[slength] = 0x00;
+
+   for (entry_start = chunkdata; *entry_start; entry_start++)
+      /* empty loop to find end of name */ ;
+   ++entry_start;
+
+   /* a sample depth should follow the separator, and we should be on it  */
+   if (entry_start > chunkdata + slength)
+   {
+      png_free(png_ptr, chunkdata);
+      png_warning(png_ptr, "malformed sPLT chunk");
+      return;
+   }
+
+   new_palette.depth = *entry_start++;
+   entry_size = (new_palette.depth == 8 ? 6 : 10);
+   data_length = (slength - (entry_start - chunkdata));
+
+   /* integrity-check the data length */
+   if (data_length % entry_size)
+   {
+      png_free(png_ptr, chunkdata);
+      png_warning(png_ptr, "sPLT chunk has bad length");
+      return;
+   }
+
+   new_palette.nentries = data_length / entry_size;
+   new_palette.entries = (png_sPLT_entryp)png_malloc(
+       png_ptr, new_palette.nentries * sizeof(png_sPLT_entry));
+
+#ifndef PNG_NO_POINTER_INDEXING
+   for (i = 0; i < new_palette.nentries; i++)
+   {
+      png_sPLT_entryp pp = new_palette.entries + i;
+
+      if (new_palette.depth == 8)
+      {
+          pp->red = *entry_start++;
+          pp->green = *entry_start++;
+          pp->blue = *entry_start++;
+          pp->alpha = *entry_start++;
+      }
+      else
+      {
+          pp->red   = png_get_uint_16(entry_start); entry_start += 2;
+          pp->green = png_get_uint_16(entry_start); entry_start += 2;
+          pp->blue  = png_get_uint_16(entry_start); entry_start += 2;
+          pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
+      }
+      pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
+   }
+#else
+   pp = new_palette.entries;
+   for (i = 0; i < new_palette.nentries; i++)
+   {
+
+      if (new_palette.depth == 8)
+      {
+          pp[i].red   = *entry_start++;
+          pp[i].green = *entry_start++;
+          pp[i].blue  = *entry_start++;
+          pp[i].alpha = *entry_start++;
+      }
+      else
+      {
+          pp[i].red   = png_get_uint_16(entry_start); entry_start += 2;
+          pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
+          pp[i].blue  = png_get_uint_16(entry_start); entry_start += 2;
+          pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
+      }
+      pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
+   }
+#endif
+
+   /* discard all chunk data except the name and stash that */
+   new_palette.name = (png_charp)chunkdata;
+
+   png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
+
+   png_free(png_ptr, chunkdata);
+   png_free(png_ptr, new_palette.entries);
+}
+#endif /* PNG_READ_sPLT_SUPPORTED */
+
+#if defined(PNG_READ_tRNS_SUPPORTED)
+void /* PRIVATE */
+png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_byte	readbuf[PNG_MAX_PALETTE_LENGTH];
+
+   png_debug(1, "in png_handle_tRNS\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before tRNS");
+   else if (png_ptr->mode & PNG_HAVE_IDAT)
+   {
+      png_warning(png_ptr, "Invalid tRNS after IDAT");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
+   {
+      png_warning(png_ptr, "Duplicate tRNS chunk");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+   {
+      if (!(png_ptr->mode & PNG_HAVE_PLTE))
+      {
+         /* Should be an error, but we can cope with it */
+         png_warning(png_ptr, "Missing PLTE before tRNS");
+      }
+      else if (length > (png_uint_32)png_ptr->num_palette)
+      {
+         png_warning(png_ptr, "Incorrect tRNS chunk length");
+         png_crc_finish(png_ptr, length);
+         return;
+      }
+      if (length == 0)
+      {
+         png_warning(png_ptr, "Zero length tRNS chunk");
+         png_crc_finish(png_ptr, length);
+         return;
+      }
+
+      png_crc_read(png_ptr, readbuf, (png_size_t)length);
+      png_ptr->num_trans = (png_uint_16)length;
+   }
+   else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
+   {
+      png_byte buf[6];
+
+      if (length != 6)
+      {
+         png_warning(png_ptr, "Incorrect tRNS chunk length");
+         png_crc_finish(png_ptr, length);
+         return;
+      }
+
+      png_crc_read(png_ptr, buf, (png_size_t)length);
+      png_ptr->num_trans = 1;
+      png_ptr->trans_values.red = png_get_uint_16(buf);
+      png_ptr->trans_values.green = png_get_uint_16(buf + 2);
+      png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
+   }
+   else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
+   {
+      png_byte buf[6];
+
+      if (length != 2)
+      {
+         png_warning(png_ptr, "Incorrect tRNS chunk length");
+         png_crc_finish(png_ptr, length);
+         return;
+      }
+
+      png_crc_read(png_ptr, buf, 2);
+      png_ptr->num_trans = 1;
+      png_ptr->trans_values.gray = png_get_uint_16(buf);
+   }
+   else
+   {
+      png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   if (png_crc_finish(png_ptr, 0))
+      return;
+
+   png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
+      &(png_ptr->trans_values));
+}
+#endif
+
+#if defined(PNG_READ_bKGD_SUPPORTED)
+void /* PRIVATE */
+png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_size_t truelen;
+   png_byte buf[6];
+
+   png_debug(1, "in png_handle_bKGD\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before bKGD");
+   else if (png_ptr->mode & PNG_HAVE_IDAT)
+   {
+      png_warning(png_ptr, "Invalid bKGD after IDAT");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+   else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
+            !(png_ptr->mode & PNG_HAVE_PLTE))
+   {
+      png_warning(png_ptr, "Missing PLTE before bKGD");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
+   {
+      png_warning(png_ptr, "Duplicate bKGD chunk");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+      truelen = 1;
+   else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
+      truelen = 6;
+   else
+      truelen = 2;
+
+   if (length != truelen)
+   {
+      png_warning(png_ptr, "Incorrect bKGD chunk length");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   png_crc_read(png_ptr, buf, truelen);
+   if (png_crc_finish(png_ptr, 0))
+      return;
+
+   /* We convert the index value into RGB components so that we can allow
+    * arbitrary RGB values for background when we have transparency, and
+    * so it is easy to determine the RGB values of the background color
+    * from the info_ptr struct. */
+   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+   {
+      png_ptr->background.index = buf[0];
+      if(info_ptr->num_palette)
+      {
+          if(buf[0] > info_ptr->num_palette)
+          {
+             png_warning(png_ptr, "Incorrect bKGD chunk index value");
+             return;
+          }
+          png_ptr->background.red =
+             (png_uint_16)png_ptr->palette[buf[0]].red;
+          png_ptr->background.green =
+             (png_uint_16)png_ptr->palette[buf[0]].green;
+          png_ptr->background.blue =
+             (png_uint_16)png_ptr->palette[buf[0]].blue;
+      }
+   }
+   else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
+   {
+      png_ptr->background.red =
+      png_ptr->background.green =
+      png_ptr->background.blue =
+      png_ptr->background.gray = png_get_uint_16(buf);
+   }
+   else
+   {
+      png_ptr->background.red = png_get_uint_16(buf);
+      png_ptr->background.green = png_get_uint_16(buf + 2);
+      png_ptr->background.blue = png_get_uint_16(buf + 4);
+   }
+
+   png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
+}
+#endif
+
+#if defined(PNG_READ_hIST_SUPPORTED)
+void /* PRIVATE */
+png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   int num, i;
+   png_uint_16	readbuf[PNG_MAX_PALETTE_LENGTH];
+
+   png_debug(1, "in png_handle_hIST\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before hIST");
+   else if (png_ptr->mode & PNG_HAVE_IDAT)
+   {
+      png_warning(png_ptr, "Invalid hIST after IDAT");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+   else if (!(png_ptr->mode & PNG_HAVE_PLTE))
+   {
+      png_warning(png_ptr, "Missing PLTE before hIST");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
+   {
+      png_warning(png_ptr, "Duplicate hIST chunk");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   num = (int)length / 2 ;
+   if (num != png_ptr->num_palette)
+   {
+      png_warning(png_ptr, "Incorrect hIST chunk length");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   for (i = 0; i < num; i++)
+   {
+      png_byte buf[2];
+
+      png_crc_read(png_ptr, buf, 2);
+      readbuf[i] = png_get_uint_16(buf);
+   }
+
+   if (png_crc_finish(png_ptr, 0))
+      return;
+
+   png_set_hIST(png_ptr, info_ptr, readbuf);
+}
+#endif
+
+#if defined(PNG_READ_pHYs_SUPPORTED)
+void /* PRIVATE */
+png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_byte buf[9];
+   png_uint_32 res_x, res_y;
+   int unit_type;
+
+   png_debug(1, "in png_handle_pHYs\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before pHYs");
+   else if (png_ptr->mode & PNG_HAVE_IDAT)
+   {
+      png_warning(png_ptr, "Invalid pHYs after IDAT");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
+   {
+      png_warning(png_ptr, "Duplicate pHYs chunk");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   if (length != 9)
+   {
+      png_warning(png_ptr, "Incorrect pHYs chunk length");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   png_crc_read(png_ptr, buf, 9);
+   if (png_crc_finish(png_ptr, 0))
+      return;
+
+   res_x = png_get_uint_32(buf);
+   res_y = png_get_uint_32(buf + 4);
+   unit_type = buf[8];
+   png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
+}
+#endif
+
+#if defined(PNG_READ_oFFs_SUPPORTED)
+void /* PRIVATE */
+png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_byte buf[9];
+   png_int_32 offset_x, offset_y;
+   int unit_type;
+
+   png_debug(1, "in png_handle_oFFs\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before oFFs");
+   else if (png_ptr->mode & PNG_HAVE_IDAT)
+   {
+      png_warning(png_ptr, "Invalid oFFs after IDAT");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
+   {
+      png_warning(png_ptr, "Duplicate oFFs chunk");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   if (length != 9)
+   {
+      png_warning(png_ptr, "Incorrect oFFs chunk length");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   png_crc_read(png_ptr, buf, 9);
+   if (png_crc_finish(png_ptr, 0))
+      return;
+
+   offset_x = png_get_int_32(buf);
+   offset_y = png_get_int_32(buf + 4);
+   unit_type = buf[8];
+   png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
+}
+#endif
+
+#if defined(PNG_READ_pCAL_SUPPORTED)
+/* read the pCAL chunk (described in the PNG Extensions document) */
+void /* PRIVATE */
+png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_charp purpose;
+   png_int_32 X0, X1;
+   png_byte type, nparams;
+   png_charp buf, units, endptr;
+   png_charpp params;
+   png_size_t slength;
+   int i;
+
+   png_debug(1, "in png_handle_pCAL\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before pCAL");
+   else if (png_ptr->mode & PNG_HAVE_IDAT)
+   {
+      png_warning(png_ptr, "Invalid pCAL after IDAT");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
+   {
+      png_warning(png_ptr, "Duplicate pCAL chunk");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)\n",
+      length + 1);
+   purpose = (png_charp)png_malloc(png_ptr, length + 1);
+   slength = (png_size_t)length;
+   png_crc_read(png_ptr, (png_bytep)purpose, slength);
+
+   if (png_crc_finish(png_ptr, 0))
+   {
+      png_free(png_ptr, purpose);
+      return;
+   }
+
+   purpose[slength] = 0x00; /* null terminate the last string */
+
+   png_debug(3, "Finding end of pCAL purpose string\n");
+   for (buf = purpose; *buf; buf++)
+      /* empty loop */ ;
+
+   endptr = purpose + slength;
+
+   /* We need to have at least 12 bytes after the purpose string
+      in order to get the parameter information. */
+   if (endptr <= buf + 12)
+   {
+      png_warning(png_ptr, "Invalid pCAL data");
+      png_free(png_ptr, purpose);
+      return;
+   }
+
+   png_debug(3, "Reading pCAL X0, X1, type, nparams, and units\n");
+   X0 = png_get_int_32((png_bytep)buf+1);
+   X1 = png_get_int_32((png_bytep)buf+5);
+   type = buf[9];
+   nparams = buf[10];
+   units = buf + 11;
+
+   png_debug(3, "Checking pCAL equation type and number of parameters\n");
+   /* Check that we have the right number of parameters for known
+      equation types. */
+   if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
+       (type == PNG_EQUATION_BASE_E && nparams != 3) ||
+       (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
+       (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
+   {
+      png_warning(png_ptr, "Invalid pCAL parameters for equation type");
+      png_free(png_ptr, purpose);
+      return;
+   }
+   else if (type >= PNG_EQUATION_LAST)
+   {
+      png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
+   }
+
+   for (buf = units; *buf; buf++)
+      /* Empty loop to move past the units string. */ ;
+
+   png_debug(3, "Allocating pCAL parameters array\n");
+   params = (png_charpp)png_malloc(png_ptr, (png_uint_32)(nparams
+      *sizeof(png_charp))) ;
+
+   /* Get pointers to the start of each parameter string. */
+   for (i = 0; i < (int)nparams; i++)
+   {
+      buf++; /* Skip the null string terminator from previous parameter. */
+
+      png_debug1(3, "Reading pCAL parameter %d\n", i);
+      for (params[i] = buf; *buf != 0x00 && buf <= endptr; buf++)
+         /* Empty loop to move past each parameter string */ ;
+
+      /* Make sure we haven't run out of data yet */
+      if (buf > endptr)
+      {
+         png_warning(png_ptr, "Invalid pCAL data");
+         png_free(png_ptr, purpose);
+         png_free(png_ptr, params);
+         return;
+      }
+   }
+
+   png_set_pCAL(png_ptr, info_ptr, purpose, X0, X1, type, nparams,
+      units, params);
+
+   png_free(png_ptr, purpose);
+   png_free(png_ptr, params);
+}
+#endif
+
+#if defined(PNG_READ_sCAL_SUPPORTED)
+/* read the sCAL chunk */
+void /* PRIVATE */
+png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_charp buffer, ep;
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   double width, height;
+   png_charp vp;
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   png_charp swidth, sheight;
+#endif
+#endif
+   png_size_t slength;
+
+   png_debug(1, "in png_handle_sCAL\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before sCAL");
+   else if (png_ptr->mode & PNG_HAVE_IDAT)
+   {
+      png_warning(png_ptr, "Invalid sCAL after IDAT");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
+   {
+      png_warning(png_ptr, "Duplicate sCAL chunk");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)\n",
+      length + 1);
+   buffer = (png_charp)png_malloc(png_ptr, length + 1);
+   slength = (png_size_t)length;
+   png_crc_read(png_ptr, (png_bytep)buffer, slength);
+
+   if (png_crc_finish(png_ptr, 0))
+   {
+      png_free(png_ptr, buffer);
+      return;
+   }
+
+   buffer[slength] = 0x00; /* null terminate the last string */
+
+   ep = buffer + 1;        /* skip unit byte */
+
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   width = strtod(ep, &vp);
+   if (*vp)
+   {
+       png_warning(png_ptr, "malformed width string in sCAL chunk");
+       return;
+   }
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   swidth = (png_charp)png_malloc(png_ptr, png_strlen(ep) + 1);
+   png_memcpy(swidth, ep, (png_size_t)png_strlen(ep));
+#endif
+#endif
+
+   for (ep = buffer; *ep; ep++)
+      /* empty loop */ ;
+   ep++;
+
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   height = strtod(ep, &vp);
+   if (*vp)
+   {
+       png_warning(png_ptr, "malformed height string in sCAL chunk");
+       return;
+   }
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   sheight = (png_charp)png_malloc(png_ptr, png_strlen(ep) + 1);
+   png_memcpy(sheight, ep, (png_size_t)png_strlen(ep));
+#endif
+#endif
+
+   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, 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, buffer[0], width, height);
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   png_set_sCAL_s(png_ptr, info_ptr, buffer[0], swidth, sheight);
+#endif
+#endif
+
+   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
+
+#if defined(PNG_READ_tIME_SUPPORTED)
+void /* PRIVATE */
+png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_byte buf[7];
+   png_time mod_time;
+
+   png_debug(1, "in png_handle_tIME\n");
+
+   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))
+   {
+      png_warning(png_ptr, "Duplicate tIME chunk");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   if (png_ptr->mode & PNG_HAVE_IDAT)
+      png_ptr->mode |= PNG_AFTER_IDAT;
+
+   if (length != 7)
+   {
+      png_warning(png_ptr, "Incorrect tIME chunk length");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   png_crc_read(png_ptr, buf, 7);
+   if (png_crc_finish(png_ptr, 0))
+      return;
+
+   mod_time.second = buf[6];
+   mod_time.minute = buf[5];
+   mod_time.hour = buf[4];
+   mod_time.day = buf[3];
+   mod_time.month = buf[2];
+   mod_time.year = png_get_uint_16(buf);
+
+   png_set_tIME(png_ptr, info_ptr, &mod_time);
+}
+#endif
+
+#if defined(PNG_READ_tEXt_SUPPORTED)
+/* Note: this does not properly handle chunks that are > 64K under DOS */
+void /* PRIVATE */
+png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_textp text_ptr;
+   png_charp key;
+   png_charp text;
+   png_uint_32 skip = 0;
+   png_size_t slength;
+
+   png_debug(1, "in png_handle_tEXt\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before tEXt");
+
+   if (png_ptr->mode & PNG_HAVE_IDAT)
+      png_ptr->mode |= PNG_AFTER_IDAT;
+
+#ifdef PNG_MAX_MALLOC_64K
+   if (length > (png_uint_32)65535L)
+   {
+      png_warning(png_ptr, "tEXt chunk too large to fit in memory");
+      skip = length - (png_uint_32)65535L;
+      length = (png_uint_32)65535L;
+   }
+#endif
+
+   key = (png_charp)png_malloc(png_ptr, length + 1);
+   slength = (png_size_t)length;
+   png_crc_read(png_ptr, (png_bytep)key, slength);
+
+   if (png_crc_finish(png_ptr, skip))
+   {
+      png_free(png_ptr, key);
+      return;
+   }
+
+   key[slength] = 0x00;
+
+   for (text = key; *text; text++)
+      /* empty loop to find end of key */ ;
+
+   if (text != key + slength)
+      text++;
+
+   text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
+   text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
+   text_ptr->key = key;
+#ifdef PNG_iTXt_SUPPORTED
+   text_ptr->lang = NULL;
+   text_ptr->lang_key = NULL;
+   text_ptr->itxt_length = 0;
+#endif
+   text_ptr->text = text;
+   text_ptr->text_length = png_strlen(text);
+
+   png_set_text(png_ptr, info_ptr, text_ptr, 1);
+
+   png_free(png_ptr, key);
+   png_free(png_ptr, text_ptr);
+}
+#endif
+
+#if defined(PNG_READ_zTXt_SUPPORTED)
+/* note: this does not correctly handle chunks that are > 64K under DOS */
+void /* PRIVATE */
+png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_textp text_ptr;
+   png_charp chunkdata;
+   png_charp text;
+   int comp_type;
+   png_size_t slength, prefix_len, data_len;
+
+   png_debug(1, "in png_handle_zTXt\n");
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before zTXt");
+
+   if (png_ptr->mode & PNG_HAVE_IDAT)
+      png_ptr->mode |= PNG_AFTER_IDAT;
+
+#ifdef PNG_MAX_MALLOC_64K
+   /* We will no doubt have problems with chunks even half this size, but
+      there is no hard and fast rule to tell us where to stop. */
+   if (length > (png_uint_32)65535L)
+   {
+     png_warning(png_ptr,"zTXt chunk too large to fit in memory");
+     png_crc_finish(png_ptr, length);
+     return;
+   }
+#endif
+
+   chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
+     slength = (png_size_t)length;
+   png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
+   if (png_crc_finish(png_ptr, 0))
+   {
+      png_free(png_ptr, chunkdata);
+      return;
+   }
+
+   chunkdata[slength] = 0x00;
+
+   for (text = chunkdata; *text; text++)
+      /* empty loop */ ;
+
+   /* zTXt must have some text after the chunkdataword */
+   if (text == chunkdata + slength)
+   {
+      comp_type = PNG_TEXT_COMPRESSION_NONE;
+      png_warning(png_ptr, "Zero length zTXt chunk");
+   }
+   else
+   {
+       comp_type = *(++text);
+       if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
+       {
+          png_warning(png_ptr, "Unknown compression type in zTXt chunk");
+          comp_type = PNG_TEXT_COMPRESSION_zTXt;
+       }
+       text++;        /* skip the compression_method byte */
+   }
+   prefix_len = text - chunkdata;
+
+   chunkdata = (png_charp)png_decompress_chunk(png_ptr, comp_type, chunkdata,
+                                    (png_size_t)length, prefix_len, &data_len);
+
+   text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
+   text_ptr->compression = comp_type;
+   text_ptr->key = chunkdata;
+#ifdef PNG_iTXt_SUPPORTED
+   text_ptr->lang = NULL;
+   text_ptr->lang_key = NULL;
+   text_ptr->itxt_length = 0;
+#endif
+   text_ptr->text = chunkdata + prefix_len;
+   text_ptr->text_length = data_len;
+
+   png_set_text(png_ptr, info_ptr, text_ptr, 1);
+
+   png_free(png_ptr, text_ptr);
+   png_free(png_ptr, chunkdata);
+}
+#endif
+
+#if defined(PNG_READ_iTXt_SUPPORTED)
+/* note: this does not correctly handle chunks that are > 64K under DOS */
+void /* PRIVATE */
+png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_textp text_ptr;
+   png_charp chunkdata;
+   png_charp key, lang, text, lang_key;
+   int comp_flag;
+   int comp_type = 0;
+   png_size_t slength, prefix_len, data_len;
+
+   png_debug(1, "in png_handle_iTXt\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before iTXt");
+
+   if (png_ptr->mode & PNG_HAVE_IDAT)
+      png_ptr->mode |= PNG_AFTER_IDAT;
+
+#ifdef PNG_MAX_MALLOC_64K
+   /* We will no doubt have problems with chunks even half this size, but
+      there is no hard and fast rule to tell us where to stop. */
+   if (length > (png_uint_32)65535L)
+   {
+     png_warning(png_ptr,"iTXt chunk too large to fit in memory");
+     png_crc_finish(png_ptr, length);
+     return;
+   }
+#endif
+
+   chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
+   slength = (png_size_t)length;
+   png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
+   if (png_crc_finish(png_ptr, 0))
+   {
+      png_free(png_ptr, chunkdata);
+      return;
+   }
+
+   chunkdata[slength] = 0x00;
+
+   for (lang = chunkdata; *lang; lang++)
+      /* empty loop */ ;
+   lang++;        /* skip NUL separator */
+
+   /* 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_flag = PNG_TEXT_COMPRESSION_NONE;
+      png_warning(png_ptr, "Zero length iTXt chunk");
+   }
+   else
+   {
+       comp_flag = *lang++;
+       comp_type = *lang++;
+   }
+
+   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, &data_len);
+   else
+       data_len=png_strlen(chunkdata + prefix_len);
+   text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
+   text_ptr->compression = (int)comp_flag + 1;
+   text_ptr->lang_key = chunkdata+(lang_key-key);
+   text_ptr->lang = chunkdata+(lang-key);
+   text_ptr->itxt_length = data_len;
+   text_ptr->text_length = 0;
+   text_ptr->key = chunkdata;
+   text_ptr->text = chunkdata + prefix_len;
+
+   png_set_text(png_ptr, info_ptr, text_ptr, 1);
+
+   png_free(png_ptr, text_ptr);
+   png_free(png_ptr, chunkdata);
+}
+#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
+   -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
+   case it will be saved away to be written out later. */
+void /* PRIVATE */
+png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_uint_32 skip = 0;
+
+   png_debug(1, "in png_handle_unknown\n");
+
+   if (png_ptr->mode & PNG_HAVE_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;
+   }
+
+   png_check_chunk_name(png_ptr, png_ptr->chunk_name);
+
+   if (!(png_ptr->chunk_name[0] & 0x20))
+   {
+#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
+      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 == NULL
+#endif
+        )
+#endif
+          png_chunk_error(png_ptr, "unknown critical chunk");
+   }
+
+#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
+       png_strcpy((png_charp)chunk.name, (png_charp)png_ptr->chunk_name);
+       chunk.data = (png_bytep)png_malloc(png_ptr, length);
+       chunk.size = (png_size_t)length;
+       png_crc_read(png_ptr, (png_bytep)chunk.data, length);
+#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
+       if(png_ptr->read_user_chunk_fn != 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_crc_finish(png_ptr, skip);
+
+#if !defined(PNG_READ_USER_CHUNKS_SUPPORTED)
+   info_ptr = info_ptr; /* quiet compiler warnings about unused info_ptr */
+#endif
+}
+
+/* This function is called to verify that a chunk name is valid.
+   This function can't have the "critical chunk check" incorporated
+   into it, since in the future we will need to be able to call user
+   functions to handle unknown critical chunks after we check that
+   the chunk name itself is valid. */
+
+#define isnonalpha(c) ((c) < 41 || (c) > 122 || ((c) > 90 && (c) < 97))
+
+void /* PRIVATE */
+png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
+{
+   png_debug(1, "in png_check_chunk_name\n");
+   if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
+       isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
+   {
+      png_chunk_error(png_ptr, "invalid chunk type");
+   }
+}
+
+/* Combines the row recently read in with the existing pixels in the
+   row.  This routine takes care of alpha and transparency if requested.
+   This routine also handles the two methods of progressive display
+   of interlaced images, depending on the mask value.
+   The mask value describes which pixels are to be combined with
+   the row.  The pattern always repeats every 8 pixels, so just 8
+   bits are needed.  A one indicates the 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.  */
+#ifndef PNG_HAVE_ASSEMBLER_COMBINE_ROW
+void /* PRIVATE */
+png_combine_row(png_structp png_ptr, png_bytep row, int mask)
+{
+   png_debug(1,"in png_combine_row\n");
+   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));
+   }
+   else
+   {
+      switch (png_ptr->row_info.pixel_depth)
+      {
+         case 1:
+         {
+            png_bytep sp = png_ptr->row_buf + 1;
+            png_bytep dp = row;
+            int s_inc, s_start, s_end;
+            int m = 0x80;
+            int shift;
+            png_uint_32 i;
+            png_uint_32 row_width = png_ptr->width;
+
+#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 < row_width; i++)
+            {
+               if (m & mask)
+               {
+                  int value;
+
+                  value = (*sp >> shift) & 0x01;
+                  *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_bytep sp = png_ptr->row_buf + 1;
+            png_bytep dp = row;
+            int s_start, s_end, s_inc;
+            int m = 0x80;
+            int shift;
+            png_uint_32 i;
+            png_uint_32 row_width = png_ptr->width;
+            int value;
+
+#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 < row_width; i++)
+            {
+               if (m & mask)
+               {
+                  value = (*sp >> shift) & 0x03;
+                  *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_bytep sp = png_ptr->row_buf + 1;
+            png_bytep dp = row;
+            int s_start, s_end, s_inc;
+            int m = 0x80;
+            int shift;
+            png_uint_32 i;
+            png_uint_32 row_width = png_ptr->width;
+            int value;
+
+#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 < row_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;
+         }
+         default:
+         {
+            png_bytep sp = png_ptr->row_buf + 1;
+            png_bytep dp = row;
+            png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
+            png_uint_32 i;
+            png_uint_32 row_width = png_ptr->width;
+            png_byte m = 0x80;
+
+
+            for (i = 0; i < row_width; i++)
+            {
+               if (m & mask)
+               {
+                  png_memcpy(dp, sp, pixel_bytes);
+               }
+
+               sp += pixel_bytes;
+               dp += pixel_bytes;
+
+               if (m == 1)
+                  m = 0x80;
+               else
+                  m >>= 1;
+            }
+            break;
+         }
+      }
+   }
+}
+#endif /* !PNG_HAVE_ASSEMBLER_COMBINE_ROW */
+
+#ifdef PNG_READ_INTERLACING_SUPPORTED
+#ifndef PNG_HAVE_ASSEMBLER_READ_INTERLACE   /* else in pngvcrd.c, pnggccrd.c */
+/* OLD pre-1.0.9 interface:
+void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
+   png_uint_32 transformations)
+ */
+void /* PRIVATE */
+png_do_read_interlace(png_structp png_ptr)
+{
+   png_row_infop row_info = &(png_ptr->row_info);
+   png_bytep row = png_ptr->row_buf + 1;
+   int pass = png_ptr->pass;
+   png_uint_32 transformations = png_ptr->transformations;
+#ifdef PNG_USE_LOCAL_ARRAYS
+   /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+   /* offset to next interlace block */
+   const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+#endif
+
+   png_debug(1,"in png_do_read_interlace (stock C version)\n");
+   if (row != NULL && row_info != NULL)
+   {
+      png_uint_32 final_width;
+
+      final_width = row_info->width * png_pass_inc[pass];
+
+      switch (row_info->pixel_depth)
+      {
+         case 1:
+         {
+            png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
+            png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
+            int sshift, dshift;
+            int s_start, s_end, s_inc;
+            int jstop = png_pass_inc[pass];
+            png_byte v;
+            png_uint_32 i;
+            int j;
+
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+            if (transformations & PNG_PACKSWAP)
+            {
+                sshift = (int)((row_info->width + 7) & 0x07);
+                dshift = (int)((final_width + 7) & 0x07);
+                s_start = 7;
+                s_end = 0;
+                s_inc = -1;
+            }
+            else
+#endif
+            {
+                sshift = 7 - (int)((row_info->width + 7) & 0x07);
+                dshift = 7 - (int)((final_width + 7) & 0x07);
+                s_start = 0;
+                s_end = 7;
+                s_inc = 1;
+            }
+
+            for (i = 0; i < row_info->width; i++)
+            {
+               v = (png_byte)((*sp >> sshift) & 0x01);
+               for (j = 0; j < jstop; 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 = row + (png_uint_32)((row_info->width - 1) >> 2);
+            png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
+            int sshift, dshift;
+            int s_start, s_end, s_inc;
+            int jstop = png_pass_inc[pass];
+            png_uint_32 i;
+
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+            if (transformations & PNG_PACKSWAP)
+            {
+               sshift = (int)(((row_info->width + 3) & 0x03) << 1);
+               dshift = (int)(((final_width + 3) & 0x03) << 1);
+               s_start = 6;
+               s_end = 0;
+               s_inc = -2;
+            }
+            else
+#endif
+            {
+               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;
+            }
+
+            for (i = 0; i < row_info->width; i++)
+            {
+               png_byte v;
+               int j;
+
+               v = (png_byte)((*sp >> sshift) & 0x03);
+               for (j = 0; j < jstop; 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 = row + (png_size_t)((row_info->width - 1) >> 1);
+            png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
+            int sshift, dshift;
+            int s_start, s_end, s_inc;
+            png_uint_32 i;
+            int jstop = png_pass_inc[pass];
+
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+            if (transformations & PNG_PACKSWAP)
+            {
+               sshift = (int)(((row_info->width + 1) & 0x01) << 2);
+               dshift = (int)(((final_width + 1) & 0x01) << 2);
+               s_start = 4;
+               s_end = 0;
+               s_inc = -4;
+            }
+            else
+#endif
+            {
+               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;
+            }
+
+            for (i = 0; i < row_info->width; i++)
+            {
+               png_byte v = (png_byte)((*sp >> sshift) & 0xf);
+               int j;
+
+               for (j = 0; j < jstop; 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:
+         {
+            png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
+            png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes;
+            png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
+
+            int jstop = png_pass_inc[pass];
+            png_uint_32 i;
+
+            for (i = 0; i < row_info->width; i++)
+            {
+               png_byte v[8];
+               int j;
+
+               png_memcpy(v, sp, pixel_bytes);
+               for (j = 0; j < jstop; j++)
+               {
+                  png_memcpy(dp, v, pixel_bytes);
+                  dp -= pixel_bytes;
+               }
+               sp -= pixel_bytes;
+            }
+            break;
+         }
+      }
+      row_info->width = final_width;
+      row_info->rowbytes = ((final_width *
+         (png_uint_32)row_info->pixel_depth + 7) >> 3);
+   }
+#if !defined(PNG_READ_PACKSWAP_SUPPORTED)
+   transformations = transformations; /* silence compiler warning */
+#endif
+}
+#endif /* !PNG_HAVE_ASSEMBLER_READ_INTERLACE */
+#endif /* PNG_READ_INTERLACING_SUPPORTED */
+
+#ifndef PNG_HAVE_ASSEMBLER_READ_FILTER_ROW
+void /* PRIVATE */
+png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
+   png_bytep prev_row, int filter)
+{
+   png_debug(1, "in png_read_filter_row\n");
+   png_debug2(2,"row = %lu, filter = %d\n", png_ptr->row_number, filter);
+   switch (filter)
+   {
+      case PNG_FILTER_VALUE_NONE:
+         break;
+      case PNG_FILTER_VALUE_SUB:
+      {
+         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++;
+         }
+         break;
+      }
+      case PNG_FILTER_VALUE_UP:
+      {
+         png_uint_32 i;
+         png_uint_32 istop = row_info->rowbytes;
+         png_bytep rp = row;
+         png_bytep pp = prev_row;
+
+         for (i = 0; i < istop; i++)
+         {
+            *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
+            rp++;
+         }
+         break;
+      }
+      case PNG_FILTER_VALUE_AVG:
+      {
+         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++) / 2 )) & 0xff);
+            rp++;
+         }
+
+         for (i = 0; i < istop; i++)
+         {
+            *rp = (png_byte)(((int)(*rp) +
+               (int)(*pp++ + *lp++) / 2 ) & 0xff);
+            rp++;
+         }
+         break;
+      }
+      case PNG_FILTER_VALUE_PAETH:
+      {
+         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++;
+         }
+         break;
+      }
+      default:
+         png_warning(png_ptr, "Ignoring bad adaptive filter type");
+         *row=0;
+         break;
+   }
+}
+#endif /* !PNG_HAVE_ASSEMBLER_READ_FILTER_ROW */
+
+void /* PRIVATE */
+png_read_finish_row(png_structp png_ptr)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+
+   /* start of interlace block */
+   const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+
+   /* offset to next interlace block */
+   const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+
+   /* start of interlace block in the y direction */
+   const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
+
+   /* offset to next interlace block in the y direction */
+   const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
+#endif
+
+   png_debug(1, "in png_read_finish_row\n");
+   png_ptr->row_number++;
+   if (png_ptr->row_number < png_ptr->num_rows)
+      return;
+
+   if (png_ptr->interlaced)
+   {
+      png_ptr->row_number = 0;
+      png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
+      do
+      {
+         png_ptr->pass++;
+         if (png_ptr->pass >= 7)
+            break;
+         png_ptr->iwidth = (png_ptr->width +
+            png_pass_inc[png_ptr->pass] - 1 -
+            png_pass_start[png_ptr->pass]) /
+            png_pass_inc[png_ptr->pass];
+            png_ptr->irowbytes = ((png_ptr->iwidth *
+               (png_uint_32)png_ptr->pixel_depth + 7) >> 3) +1;
+
+         if (!(png_ptr->transformations & PNG_INTERLACE))
+         {
+            png_ptr->num_rows = (png_ptr->height +
+               png_pass_yinc[png_ptr->pass] - 1 -
+               png_pass_ystart[png_ptr->pass]) /
+               png_pass_yinc[png_ptr->pass];
+            if (!(png_ptr->num_rows))
+               continue;
+         }
+         else  /* if (png_ptr->transformations & PNG_INTERLACE) */
+            break;
+      } while (png_ptr->iwidth == 0);
+
+      if (png_ptr->pass < 7)
+         return;
+   }
+
+   if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
+   {
+#ifdef PNG_USE_LOCAL_ARRAYS
+      PNG_IDAT;
+#endif
+      char extra;
+      int ret;
+
+      png_ptr->zstream.next_out = (Byte *)&extra;
+      png_ptr->zstream.avail_out = (uInt)1;
+      for(;;)
+      {
+         if (!(png_ptr->zstream.avail_in))
+         {
+            while (!png_ptr->idat_size)
+            {
+               png_byte chunk_length[4];
+
+               png_crc_finish(png_ptr, 0);
+
+               png_read_data(png_ptr, chunk_length, 4);
+               png_ptr->idat_size = png_get_uint_32(chunk_length);
+
+               png_reset_crc(png_ptr);
+               png_crc_read(png_ptr, png_ptr->chunk_name, 4);
+               if (png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4))
+                  png_error(png_ptr, "Not enough image data");
+
+            }
+            png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
+            png_ptr->zstream.next_in = png_ptr->zbuf;
+            if (png_ptr->zbuf_size > png_ptr->idat_size)
+               png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
+            png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
+            png_ptr->idat_size -= png_ptr->zstream.avail_in;
+         }
+         ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
+         if (ret == Z_STREAM_END)
+         {
+            if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
+               png_ptr->idat_size)
+               png_error(png_ptr, "Extra compressed data");
+            png_ptr->mode |= PNG_AFTER_IDAT;
+            png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
+            break;
+         }
+         if (ret != Z_OK)
+            png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
+                      "Decompression Error");
+
+         if (!(png_ptr->zstream.avail_out))
+            png_error(png_ptr, "Extra compressed data");
+
+      }
+      png_ptr->zstream.avail_out = 0;
+   }
+
+   if (png_ptr->idat_size || png_ptr->zstream.avail_in)
+      png_error(png_ptr, "Extra compression data");
+
+   inflateReset(&png_ptr->zstream);
+
+   png_ptr->mode |= PNG_AFTER_IDAT;
+}
+
+void /* PRIVATE */
+png_read_start_row(png_structp png_ptr)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+
+   /* start of interlace block */
+   const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+
+   /* offset to next interlace block */
+   const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+
+   /* start of interlace block in the y direction */
+   const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
+
+   /* offset to next interlace block in the y direction */
+   const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
+#endif
+
+   int max_pixel_depth;
+   png_uint_32 row_bytes;
+
+   png_debug(1, "in png_read_start_row\n");
+   png_ptr->zstream.avail_in = 0;
+   png_init_read_transformations(png_ptr);
+   if (png_ptr->interlaced)
+   {
+      if (!(png_ptr->transformations & PNG_INTERLACE))
+         png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
+            png_pass_ystart[0]) / png_pass_yinc[0];
+      else
+         png_ptr->num_rows = png_ptr->height;
+
+      png_ptr->iwidth = (png_ptr->width +
+         png_pass_inc[png_ptr->pass] - 1 -
+         png_pass_start[png_ptr->pass]) /
+         png_pass_inc[png_ptr->pass];
+
+         row_bytes = ((png_ptr->iwidth *
+            (png_uint_32)png_ptr->pixel_depth + 7) >> 3) +1;
+         png_ptr->irowbytes = (png_size_t)row_bytes;
+         if((png_uint_32)png_ptr->irowbytes != row_bytes)
+            png_error(png_ptr, "Rowbytes overflow in png_read_start_row");
+   }
+   else
+   {
+      png_ptr->num_rows = png_ptr->height;
+      png_ptr->iwidth = png_ptr->width;
+      png_ptr->irowbytes = png_ptr->rowbytes + 1;
+   }
+   max_pixel_depth = png_ptr->pixel_depth;
+
+#if defined(PNG_READ_PACK_SUPPORTED)
+   if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
+      max_pixel_depth = 8;
+#endif
+
+#if defined(PNG_READ_EXPAND_SUPPORTED)
+   if (png_ptr->transformations & PNG_EXPAND)
+   {
+      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+      {
+         if (png_ptr->num_trans)
+            max_pixel_depth = 32;
+         else
+            max_pixel_depth = 24;
+      }
+      else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
+      {
+         if (max_pixel_depth < 8)
+            max_pixel_depth = 8;
+         if (png_ptr->num_trans)
+            max_pixel_depth *= 2;
+      }
+      else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
+      {
+         if (png_ptr->num_trans)
+         {
+            max_pixel_depth *= 4;
+            max_pixel_depth /= 3;
+         }
+      }
+   }
+#endif
+
+#if defined(PNG_READ_FILLER_SUPPORTED)
+   if (png_ptr->transformations & (PNG_FILLER))
+   {
+      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+         max_pixel_depth = 32;
+      else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
+      {
+         if (max_pixel_depth <= 8)
+            max_pixel_depth = 16;
+         else
+            max_pixel_depth = 32;
+      }
+      else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
+      {
+         if (max_pixel_depth <= 32)
+            max_pixel_depth = 32;
+         else
+            max_pixel_depth = 64;
+      }
+   }
+#endif
+
+#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
+   if (png_ptr->transformations & PNG_GRAY_TO_RGB)
+   {
+      if (
+#if defined(PNG_READ_EXPAND_SUPPORTED)
+        (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
+#endif
+#if defined(PNG_READ_FILLER_SUPPORTED)
+        (png_ptr->transformations & (PNG_FILLER)) ||
+#endif
+        png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+      {
+         if (max_pixel_depth <= 16)
+            max_pixel_depth = 32;
+         else
+            max_pixel_depth = 64;
+      }
+      else
+      {
+         if (max_pixel_depth <= 8)
+           {
+             if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+               max_pixel_depth = 32;
+             else
+               max_pixel_depth = 24;
+           }
+         else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+            max_pixel_depth = 64;
+         else
+            max_pixel_depth = 48;
+      }
+   }
+#endif
+
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
+defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
+   if(png_ptr->transformations & PNG_USER_TRANSFORM)
+     {
+       int user_pixel_depth=png_ptr->user_transform_depth*
+         png_ptr->user_transform_channels;
+       if(user_pixel_depth > max_pixel_depth)
+         max_pixel_depth=user_pixel_depth;
+     }
+#endif
+
+   /* align the width on the next larger 8 pixels.  Mainly used
+      for interlacing */
+   row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
+   /* calculate the maximum bytes needed, adding a byte and a pixel
+      for safety's sake */
+   row_bytes = ((row_bytes * (png_uint_32)max_pixel_depth + 7) >> 3) +
+      1 + ((max_pixel_depth + 7) >> 3);
+#ifdef PNG_MAX_MALLOC_64K
+   if (row_bytes > (png_uint_32)65536L)
+      png_error(png_ptr, "This image requires a row greater than 64KB");
+#endif
+   png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, row_bytes);
+#if defined(PNG_DEBUG) && defined(PNG_USE_PNGGCCRD)
+   png_ptr->row_buf_size = row_bytes;
+#endif
+
+#ifdef PNG_MAX_MALLOC_64K
+   if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L)
+      png_error(png_ptr, "This image requires a row greater than 64KB");
+#endif
+   png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
+      png_ptr->rowbytes + 1));
+
+   png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
+
+   png_debug1(3, "width = %lu,\n", png_ptr->width);
+   png_debug1(3, "height = %lu,\n", png_ptr->height);
+   png_debug1(3, "iwidth = %lu,\n", png_ptr->iwidth);
+   png_debug1(3, "num_rows = %lu\n", png_ptr->num_rows);
+   png_debug1(3, "rowbytes = %lu,\n", png_ptr->rowbytes);
+   png_debug1(3, "irowbytes = %lu,\n", png_ptr->irowbytes);
+
+   png_ptr->flags |= PNG_FLAG_ROW_INIT;
+}
diff --git a/Utilities/ITK/Utilities/png/pngset.c b/Utilities/ITK/Utilities/png/pngset.c
new file mode 100644
index 0000000000..ddc4d0cb7e
--- /dev/null
+++ b/Utilities/ITK/Utilities/png/pngset.c
@@ -0,0 +1,972 @@
+
+/* pngset.c - storage of image information into info struct
+ *
+ * libpng 1.0.12 - June 8, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * The functions here are used during reads to store data from the file
+ * into the info struct, and during writes to store application data
+ * into the info struct for writing into the file.  This abstracts the
+ * info struct and allows us to change the structure in the future.
+ */
+
+#define PNG_INTERNAL
+#include "png.h"
+
+#if defined(PNG_bKGD_SUPPORTED)
+void PNGAPI
+png_set_bKGD(png_structp png_ptr, png_infop info_ptr, png_color_16p background)
+{
+   png_debug1(1, "in %s storage function\n", "bKGD");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   png_memcpy(&(info_ptr->background), background, sizeof(png_color_16));
+   info_ptr->valid |= PNG_INFO_bKGD;
+}
+#endif
+
+#if defined(PNG_cHRM_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+void PNGAPI
+png_set_cHRM(png_structp png_ptr, png_infop info_ptr,
+   double white_x, double white_y, double red_x, double red_y,
+   double green_x, double green_y, double blue_x, double blue_y)
+{
+   png_debug1(1, "in %s storage function\n", "cHRM");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   info_ptr->x_white = (float)white_x;
+   info_ptr->y_white = (float)white_y;
+   info_ptr->x_red   = (float)red_x;
+   info_ptr->y_red   = (float)red_y;
+   info_ptr->x_green = (float)green_x;
+   info_ptr->y_green = (float)green_y;
+   info_ptr->x_blue  = (float)blue_x;
+   info_ptr->y_blue  = (float)blue_y;
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   info_ptr->int_x_white = (png_fixed_point)(white_x*100000.+0.5);
+   info_ptr->int_y_white = (png_fixed_point)(white_y*100000.+0.5);
+   info_ptr->int_x_red   = (png_fixed_point)(red_x*100000.+0.5);
+   info_ptr->int_y_red   = (png_fixed_point)(red_y*100000.+0.5);
+   info_ptr->int_x_green = (png_fixed_point)(green_x*100000.+0.5);
+   info_ptr->int_y_green = (png_fixed_point)(green_y*100000.+0.5);
+   info_ptr->int_x_blue  = (png_fixed_point)(blue_x*100000.+0.5);
+   info_ptr->int_y_blue  = (png_fixed_point)(blue_y*100000.+0.5);
+#endif
+   info_ptr->valid |= PNG_INFO_cHRM;
+}
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+void PNGAPI
+png_set_cHRM_fixed(png_structp png_ptr, png_infop info_ptr,
+   png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x,
+   png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y,
+   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)
+      return;
+
+   info_ptr->int_x_white = white_x;
+   info_ptr->int_y_white = white_y;
+   info_ptr->int_x_red   = red_x;
+   info_ptr->int_y_red   = red_y;
+   info_ptr->int_x_green = green_x;
+   info_ptr->int_y_green = green_y;
+   info_ptr->int_x_blue  = blue_x;
+   info_ptr->int_y_blue  = blue_y;
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   info_ptr->x_white = (float)(white_x/100000.);
+   info_ptr->y_white = (float)(white_y/100000.);
+   info_ptr->x_red   = (float)(red_x/100000.);
+   info_ptr->y_red   = (float)(red_y/100000.);
+   info_ptr->x_green = (float)(green_x/100000.);
+   info_ptr->y_green = (float)(green_y/100000.);
+   info_ptr->x_blue  = (float)(blue_x/100000.);
+   info_ptr->y_blue  = (float)(blue_y/100000.);
+#endif
+   info_ptr->valid |= PNG_INFO_cHRM;
+}
+#endif
+#endif
+
+#if defined(PNG_gAMA_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+void PNGAPI
+png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma)
+{
+   png_debug1(1, "in %s storage function\n", "gAMA");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   info_ptr->gamma = (float)file_gamma;
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   info_ptr->int_gamma = (int)(file_gamma*100000.+.5);
+#endif
+   info_ptr->valid |= PNG_INFO_gAMA;
+   if(file_gamma == 0.0)
+      png_warning(png_ptr, "Setting gamma=0");
+}
+#endif
+void PNGAPI
+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.);
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   info_ptr->int_gamma = int_gamma;
+#endif
+   info_ptr->valid |= PNG_INFO_gAMA;
+   if(int_gamma == 0)
+      png_warning(png_ptr, "Setting gamma=0");
+}
+#endif
+
+#if defined(PNG_hIST_SUPPORTED)
+void PNGAPI
+png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p hist)
+{
+   int	i;
+
+   png_debug1(1, "in %s storage function\n", "hIST");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+   if (info_ptr->num_palette == 0)
+   {
+       png_warning(png_ptr,
+          "Palette size 0, hIST allocation skipped.");
+       return;
+   }
+
+#ifdef PNG_FREE_ME_SUPPORTED
+   png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0);
+#endif
+   png_ptr->hist = (png_uint_16p)png_malloc(png_ptr,
+      (png_uint_32)(info_ptr->num_palette * sizeof (png_uint_16)));
+
+   for (i = 0; i < info_ptr->num_palette; i++)
+       png_ptr->hist[i] = hist[i];
+   info_ptr->hist = png_ptr->hist;
+   info_ptr->valid |= PNG_INFO_hIST;
+
+#ifdef PNG_FREE_ME_SUPPORTED
+   info_ptr->free_me |= PNG_FREE_HIST;
+#else
+   png_ptr->flags |= PNG_FLAG_FREE_HIST;
+#endif
+}
+#endif
+
+void PNGAPI
+png_set_IHDR(png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 width, png_uint_32 height, int bit_depth,
+   int color_type, int interlace_type, int compression_type,
+   int filter_type)
+{
+   int rowbytes_per_pixel;
+   png_debug1(1, "in %s storage function\n", "IHDR");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   /* check for width and height valid values */
+   if (width == 0 || height == 0)
+      png_error(png_ptr, "Image width or height is zero in IHDR");
+   if (width > PNG_MAX_UINT || height > PNG_MAX_UINT)
+      png_error(png_ptr, "Invalid image size in IHDR");
+
+   /* check other values */
+   if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 &&
+      bit_depth != 8 && bit_depth != 16)
+      png_error(png_ptr, "Invalid bit depth in IHDR");
+
+   if (color_type < 0 || color_type == 1 ||
+      color_type == 5 || color_type > 6)
+      png_error(png_ptr, "Invalid color type in IHDR");
+
+   if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) ||
+       ((color_type == PNG_COLOR_TYPE_RGB ||
+         color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
+         color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8))
+      png_error(png_ptr, "Invalid color type/bit depth combination in IHDR");
+
+   if (interlace_type >= PNG_INTERLACE_LAST)
+      png_error(png_ptr, "Unknown interlace method in IHDR");
+
+   if (compression_type != PNG_COMPRESSION_TYPE_BASE)
+      png_error(png_ptr, "Unknown compression method in IHDR");
+
+#if defined(PNG_MNG_FEATURES_SUPPORTED)
+   /* Accept filter_method 64 (intrapixel differencing) only if
+    * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
+    * 2. Libpng did not read a PNG signature (this filter_method is only
+    *    used in PNG datastreams that are embedded in MNG datastreams) and
+    * 3. The application called png_permit_mng_features with a mask that
+    *    included PNG_FLAG_MNG_FILTER_64 and
+    * 4. The filter_method is 64 and
+    * 5. The color_type is RGB or RGBA
+    */
+   if((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&png_ptr->mng_features_permitted)
+      png_warning(png_ptr,"MNG features are not allowed in a PNG datastream\n");
+   if(filter_type != PNG_FILTER_TYPE_BASE)
+   {
+     if(!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
+        (filter_type == PNG_INTRAPIXEL_DIFFERENCING) &&
+        ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&
+        (color_type == PNG_COLOR_TYPE_RGB || 
+         color_type == PNG_COLOR_TYPE_RGB_ALPHA)))
+        png_error(png_ptr, "Unknown filter method in IHDR");
+     if(png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)
+        png_warning(png_ptr, "Invalid filter method in IHDR");
+   }
+#else
+   if(filter_type != PNG_FILTER_TYPE_BASE)
+      png_error(png_ptr, "Unknown filter method in IHDR");
+#endif
+
+   info_ptr->width = width;
+   info_ptr->height = height;
+   info_ptr->bit_depth = (png_byte)bit_depth;
+   info_ptr->color_type =(png_byte) color_type;
+   info_ptr->compression_type = (png_byte)compression_type;
+   info_ptr->filter_type = (png_byte)filter_type;
+   info_ptr->interlace_type = (png_byte)interlace_type;
+   if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+      info_ptr->channels = 1;
+   else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
+      info_ptr->channels = 3;
+   else
+      info_ptr->channels = 1;
+   if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
+      info_ptr->channels++;
+   info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth);
+
+   /* check for overflow */
+   rowbytes_per_pixel = (info_ptr->pixel_depth + 7) >> 3;
+   if (( width > PNG_MAX_UINT/rowbytes_per_pixel))
+   {
+      png_warning(png_ptr,
+         "Width too large to process image data; rowbytes will overflow.");
+      info_ptr->rowbytes = (png_size_t)0;
+   }
+   else
+      info_ptr->rowbytes = (info_ptr->width * info_ptr->pixel_depth + 7) >> 3;
+}
+
+#if defined(PNG_oFFs_SUPPORTED)
+void PNGAPI
+png_set_oFFs(png_structp png_ptr, png_infop info_ptr,
+   png_int_32 offset_x, png_int_32 offset_y, int unit_type)
+{
+   png_debug1(1, "in %s storage function\n", "oFFs");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   info_ptr->x_offset = offset_x;
+   info_ptr->y_offset = offset_y;
+   info_ptr->offset_unit_type = (png_byte)unit_type;
+   info_ptr->valid |= PNG_INFO_oFFs;
+}
+#endif
+
+#if defined(PNG_pCAL_SUPPORTED)
+void PNGAPI
+png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
+   png_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams,
+   png_charp units, png_charpp params)
+{
+   png_uint_32 length;
+   int i;
+
+   png_debug1(1, "in %s storage function\n", "pCAL");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   length = png_strlen(purpose) + 1;
+   png_debug1(3, "allocating purpose for info (%lu bytes)\n", length);
+   info_ptr->pcal_purpose = (png_charp)png_malloc(png_ptr, length);
+   png_memcpy(info_ptr->pcal_purpose, purpose, (png_size_t)length);
+
+   png_debug(3, "storing X0, X1, type, and nparams in info\n");
+   info_ptr->pcal_X0 = X0;
+   info_ptr->pcal_X1 = X1;
+   info_ptr->pcal_type = (png_byte)type;
+   info_ptr->pcal_nparams = (png_byte)nparams;
+
+   length = png_strlen(units) + 1;
+   png_debug1(3, "allocating units for info (%lu bytes)\n", length);
+   info_ptr->pcal_units = (png_charp)png_malloc(png_ptr, length);
+   png_memcpy(info_ptr->pcal_units, units, (png_size_t)length);
+
+   info_ptr->pcal_params = (png_charpp)png_malloc(png_ptr,
+      (png_uint_32)((nparams + 1) * sizeof(png_charp)));
+
+   info_ptr->pcal_params[nparams] = NULL;
+
+   for (i = 0; i < nparams; i++)
+   {
+      length = png_strlen(params[i]) + 1;
+      png_debug2(3, "allocating parameter %d for info (%lu bytes)\n", i, length);
+      info_ptr->pcal_params[i] = (png_charp)png_malloc(png_ptr, length);
+      png_memcpy(info_ptr->pcal_params[i], params[i], (png_size_t)length);
+   }
+
+   info_ptr->valid |= PNG_INFO_pCAL;
+#ifdef PNG_FREE_ME_SUPPORTED
+   info_ptr->free_me |= PNG_FREE_PCAL;
+#endif
+}
+#endif
+
+#if defined(PNG_READ_sCAL_SUPPORTED) || defined(PNG_WRITE_sCAL_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+void PNGAPI
+png_set_sCAL(png_structp png_ptr, png_infop info_ptr,
+             int unit, double width, double height)
+{
+   png_debug1(1, "in %s storage function\n", "sCAL");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   info_ptr->scal_unit = (png_byte)unit;
+   info_ptr->scal_pixel_width = width;
+   info_ptr->scal_pixel_height = height;
+
+   info_ptr->valid |= PNG_INFO_sCAL;
+}
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+void PNGAPI
+png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr,
+             int unit, png_charp swidth, png_charp sheight)
+{
+   png_uint_32 length;
+
+   png_debug1(1, "in %s storage function\n", "sCAL");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   info_ptr->scal_unit = (png_byte)unit;
+
+   length = png_strlen(swidth) + 1;
+   png_debug1(3, "allocating unit for info (%d bytes)\n", length);
+   info_ptr->scal_s_width = (png_charp)png_malloc(png_ptr, length);
+   png_memcpy(info_ptr->scal_s_width, swidth, (png_size_t)length);
+
+   length = png_strlen(sheight) + 1;
+   png_debug1(3, "allocating unit for info (%d bytes)\n", length);
+   info_ptr->scal_s_height = (png_charp)png_malloc(png_ptr, length);
+   png_memcpy(info_ptr->scal_s_height, sheight, (png_size_t)length);
+
+   info_ptr->valid |= PNG_INFO_sCAL;
+#ifdef PNG_FREE_ME_SUPPORTED
+   info_ptr->free_me |= PNG_FREE_SCAL;
+#endif
+}
+#endif
+#endif
+#endif
+
+#if defined(PNG_pHYs_SUPPORTED)
+void PNGAPI
+png_set_pHYs(png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 res_x, png_uint_32 res_y, int unit_type)
+{
+   png_debug1(1, "in %s storage function\n", "pHYs");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   info_ptr->x_pixels_per_unit = res_x;
+   info_ptr->y_pixels_per_unit = res_y;
+   info_ptr->phys_unit_type = (png_byte)unit_type;
+   info_ptr->valid |= PNG_INFO_pHYs;
+}
+#endif
+
+void PNGAPI
+png_set_PLTE(png_structp png_ptr, png_infop info_ptr,
+   png_colorp palette, int num_palette)
+{
+
+   png_debug1(1, "in %s storage function\n", "PLTE");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   /*
+    * It may not actually be necessary to set png_ptr->palette here;
+    * we do it for backward compatibility with the way the png_handle_tRNS
+    * function used to do the allocation.
+    */
+#ifdef PNG_FREE_ME_SUPPORTED
+   png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0);
+#endif
+   png_ptr->palette = (png_colorp)png_zalloc(png_ptr, (uInt)num_palette,
+      sizeof (png_color));
+   png_memcpy(png_ptr->palette, palette, num_palette * sizeof (png_color));
+   info_ptr->palette = png_ptr->palette;
+   info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette;
+
+#ifdef PNG_FREE_ME_SUPPORTED
+   info_ptr->free_me |= PNG_FREE_PLTE;
+#else
+   png_ptr->flags |= PNG_FLAG_FREE_PLTE;
+#endif
+
+   info_ptr->valid |= PNG_INFO_PLTE;
+}
+
+#if defined(PNG_sBIT_SUPPORTED)
+void PNGAPI
+png_set_sBIT(png_structp png_ptr, png_infop info_ptr,
+   png_color_8p sig_bit)
+{
+   png_debug1(1, "in %s storage function\n", "sBIT");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   png_memcpy(&(info_ptr->sig_bit), sig_bit, sizeof (png_color_8));
+   info_ptr->valid |= PNG_INFO_sBIT;
+}
+#endif
+
+#if defined(PNG_sRGB_SUPPORTED)
+void PNGAPI
+png_set_sRGB(png_structp png_ptr, png_infop info_ptr, int intent)
+{
+   png_debug1(1, "in %s storage function\n", "sRGB");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   info_ptr->srgb_intent = (png_byte)intent;
+   info_ptr->valid |= PNG_INFO_sRGB;
+}
+
+void PNGAPI
+png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr,
+   int intent)
+{
+#if defined(PNG_gAMA_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   float file_gamma;
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   png_fixed_point int_file_gamma;
+#endif
+#endif
+#if defined(PNG_cHRM_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   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
+   png_debug1(1, "in %s storage function\n", "sRGB_gAMA_and_cHRM");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   png_set_sRGB(png_ptr, info_ptr, intent);
+
+#if defined(PNG_gAMA_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   file_gamma = (float).45455;
+   png_set_gAMA(png_ptr, info_ptr, file_gamma);
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   int_file_gamma = 45455L;
+   png_set_gAMA_fixed(png_ptr, info_ptr, int_file_gamma);
+#endif
+#endif
+
+#if defined(PNG_cHRM_SUPPORTED)
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   int_white_x = 31270L;
+   int_white_y = 32900L;
+   int_red_x   = 64000L;
+   int_red_y   = 33000L;
+   int_green_x = 30000L;
+   int_green_y = 60000L;
+   int_blue_x  = 15000L;
+   int_blue_y  =  6000L;
+
+   png_set_cHRM_fixed(png_ptr, info_ptr,
+      int_white_x, int_white_y, int_red_x, int_red_y, int_green_x, int_green_y,
+      int_blue_x, int_blue_y);
+#endif
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   white_x = (float).3127;
+   white_y = (float).3290;
+   red_x   = (float).64;
+   red_y   = (float).33;
+   green_x = (float).30;
+   green_y = (float).60;
+   blue_x  = (float).15;
+   blue_y  = (float).06;
+
+   png_set_cHRM(png_ptr, info_ptr,
+      white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
+#endif
+#endif
+}
+#endif
+
+
+#if defined(PNG_iCCP_SUPPORTED)
+void PNGAPI
+png_set_iCCP(png_structp png_ptr, png_infop info_ptr,
+             png_charp name, int compression_type,
+             png_charp profile, png_uint_32 proflen)
+{
+   png_charp new_iccp_name;
+   png_charp new_iccp_profile;
+
+   png_debug1(1, "in %s storage function\n", "iCCP");
+   if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL)
+      return;
+
+   new_iccp_name = (png_charp)png_malloc(png_ptr, png_strlen(name)+1);
+   png_strcpy(new_iccp_name, name);
+   new_iccp_profile = (png_charp)png_malloc(png_ptr, proflen);
+   png_memcpy(new_iccp_profile, profile, (png_size_t)proflen);
+
+   png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0);
+
+   info_ptr->iccp_proflen = proflen;
+   info_ptr->iccp_name = new_iccp_name;
+   info_ptr->iccp_profile = new_iccp_profile;
+   /* 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;
+#ifdef PNG_FREE_ME_SUPPORTED
+   info_ptr->free_me |= PNG_FREE_ICCP;
+#endif
+   info_ptr->valid |= PNG_INFO_iCCP;
+}
+#endif
+
+#if defined(PNG_TEXT_SUPPORTED)
+void PNGAPI
+png_set_text(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr,
+   int num_text)
+{
+   int i;
+
+   png_debug1(1, "in %s storage function\n", (png_ptr->chunk_name[0] == '\0' ?
+      "text" : (png_const_charp)png_ptr->chunk_name));
+
+   if (png_ptr == NULL || info_ptr == NULL || num_text == 0)
+      return;
+
+   /* Make sure we have enough space in the "text" array in info_struct
+    * to hold all of the incoming text_ptr objects.
+    */
+   if (info_ptr->num_text + num_text > info_ptr->max_text)
+   {
+      if (info_ptr->text != NULL)
+      {
+         png_textp old_text;
+         int old_max;
+
+         old_max = info_ptr->max_text;
+         info_ptr->max_text = info_ptr->num_text + num_text + 8;
+         old_text = info_ptr->text;
+         info_ptr->text = (png_textp)png_malloc(png_ptr,
+            (png_uint_32)(info_ptr->max_text * sizeof (png_text)));
+         png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max *
+            sizeof(png_text)));
+         png_free(png_ptr, old_text);
+      }
+      else
+      {
+         info_ptr->max_text = num_text + 8;
+         info_ptr->num_text = 0;
+         info_ptr->text = (png_textp)png_malloc(png_ptr,
+            (png_uint_32)(info_ptr->max_text * sizeof (png_text)));
+#ifdef PNG_FREE_ME_SUPPORTED
+         info_ptr->free_me |= PNG_FREE_TEXT;
+#endif
+      }
+      png_debug1(3, "allocated %d entries for info_ptr->text\n",
+         info_ptr->max_text);
+   }
+   for (i = 0; i < num_text; i++)
+   {
+      png_size_t text_length,key_len;
+      png_size_t lang_len,lang_key_len;
+      png_textp textp = &(info_ptr->text[info_ptr->num_text]);
+
+      if (text_ptr[i].key == NULL)
+          continue;
+
+      key_len = png_strlen(text_ptr[i].key);
+
+      if(text_ptr[i].compression <= 0)
+      {
+        lang_len = 0;
+        lang_key_len = 0;
+      }
+      else
+#ifdef PNG_iTXt_SUPPORTED
+      {
+        /* set iTXt data */
+        if (text_ptr[i].key != NULL)
+          lang_len = png_strlen(text_ptr[i].lang);
+        else
+          lang_len = 0;
+        if (text_ptr[i].lang_key != NULL)
+          lang_key_len = png_strlen(text_ptr[i].lang_key);
+        else
+          lang_key_len = 0;
+      }
+#else
+      {
+        png_warning(png_ptr, "iTXt chunk not supported.");
+        continue;
+      }
+#endif
+
+      if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0')
+      {
+         text_length = 0;
+#ifdef PNG_iTXt_SUPPORTED
+         if(text_ptr[i].compression > 0)
+            textp->compression = PNG_ITXT_COMPRESSION_NONE;
+         else
+#endif
+            textp->compression = PNG_TEXT_COMPRESSION_NONE;
+      }
+      else
+      {
+         text_length = png_strlen(text_ptr[i].text);
+         textp->compression = text_ptr[i].compression;
+      }
+
+      textp->key = (png_charp)png_malloc(png_ptr,
+         (png_uint_32)(key_len + text_length + lang_len + lang_key_len + 4));
+      png_debug2(2, "Allocated %lu bytes at %x in png_set_text\n",
+         (png_uint_32)(key_len + lang_len + lang_key_len + text_length + 4),
+         (int)textp->key);
+
+      png_memcpy(textp->key, text_ptr[i].key,
+         (png_size_t)(key_len));
+      *(textp->key+key_len) = '\0';
+#ifdef PNG_iTXt_SUPPORTED
+      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
+#endif
+      {
+#ifdef PNG_iTXt_SUPPORTED
+         textp->lang=(png_charp)NULL;
+         textp->lang_key=(png_charp)NULL;
+#endif
+         textp->text=textp->key + key_len + 1;
+      }
+      if(text_length)
+         png_memcpy(textp->text, text_ptr[i].text,
+            (png_size_t)(text_length));
+      *(textp->text+text_length) = '\0';
+
+#ifdef PNG_iTXt_SUPPORTED
+      if(textp->compression > 0)
+      {
+         textp->text_length = 0;
+         textp->itxt_length = text_length;
+      }
+      else
+#endif
+      {
+         textp->text_length = text_length;
+#ifdef PNG_iTXt_SUPPORTED
+         textp->itxt_length = 0;
+#endif
+      }
+      info_ptr->text[info_ptr->num_text]= *textp;
+      info_ptr->num_text++;
+      png_debug1(3, "transferred text chunk %d\n", info_ptr->num_text);
+   }
+}
+#endif
+
+#if defined(PNG_tIME_SUPPORTED)
+void PNGAPI
+png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_timep mod_time)
+{
+   png_debug1(1, "in %s storage function\n", "tIME");
+   if (png_ptr == NULL || info_ptr == NULL ||
+       (png_ptr->mode & PNG_WROTE_tIME))
+      return;
+
+   png_memcpy(&(info_ptr->mod_time), mod_time, sizeof (png_time));
+   info_ptr->valid |= PNG_INFO_tIME;
+}
+#endif
+
+#if defined(PNG_tRNS_SUPPORTED)
+void PNGAPI
+png_set_tRNS(png_structp png_ptr, png_infop info_ptr,
+   png_bytep trans, int num_trans, png_color_16p trans_values)
+{
+   png_debug1(1, "in %s storage function\n", "tRNS");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   if (trans != NULL)
+   {
+       /*
+	* It may not actually be necessary to set png_ptr->trans here;
+	* we do it for backward compatibility with the way the png_handle_tRNS
+	* function used to do the allocation.
+	*/
+#ifdef PNG_FREE_ME_SUPPORTED
+       png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
+#endif
+       png_ptr->trans = info_ptr->trans = (png_bytep)png_malloc(png_ptr,
+           num_trans);
+       png_memcpy(info_ptr->trans, trans, num_trans);
+#ifdef PNG_FREE_ME_SUPPORTED
+       info_ptr->free_me |= PNG_FREE_TRNS;
+#else
+       png_ptr->flags |= PNG_FLAG_FREE_TRNS;
+#endif
+   }
+
+   if (trans_values != NULL)
+   {
+      png_memcpy(&(info_ptr->trans_values), trans_values,
+         sizeof(png_color_16));
+      if (num_trans == 0)
+        num_trans = 1;
+   }
+   info_ptr->num_trans = (png_uint_16)num_trans;
+   info_ptr->valid |= PNG_INFO_tRNS;
+}
+#endif
+
+#if defined(PNG_sPLT_SUPPORTED)
+void PNGAPI
+png_set_sPLT(png_structp png_ptr,
+             png_infop info_ptr, png_sPLT_tp entries, int nentries)
+{
+    png_sPLT_tp np;
+    int i;
+
+    np = (png_sPLT_tp)png_malloc(png_ptr,
+        (info_ptr->splt_palettes_num + nentries) * sizeof(png_sPLT_t));
+
+    png_memcpy(np, info_ptr->splt_palettes,
+           info_ptr->splt_palettes_num * sizeof(png_sPLT_t));
+    png_free(png_ptr, info_ptr->splt_palettes);
+    info_ptr->splt_palettes=NULL;
+
+    for (i = 0; i < nentries; i++)
+    {
+        png_sPLT_tp to = np + info_ptr->splt_palettes_num + i;
+        png_sPLT_tp from = entries + i;
+
+        to->name = (png_charp)png_malloc(png_ptr,
+            png_strlen(from->name) + 1);
+        png_strcpy(to->name, from->name);
+        to->entries = (png_sPLT_entryp)png_malloc(png_ptr,
+            from->nentries * sizeof(png_sPLT_t));
+        png_memcpy(to->entries, from->entries,
+            from->nentries * sizeof(png_sPLT_t));
+        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;
+#ifdef PNG_FREE_ME_SUPPORTED
+    info_ptr->free_me |= PNG_FREE_SPLT;
+#endif
+}
+#endif /* PNG_sPLT_SUPPORTED */
+
+#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+void PNGAPI
+png_set_unknown_chunks(png_structp png_ptr,
+   png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns)
+{
+    png_unknown_chunkp np;
+    int i;
+
+    if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0)
+        return;
+
+    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);
+    info_ptr->unknown_chunks=NULL;
+
+    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((png_charp)to->name, (png_charp)from->name);
+        to->data = (png_bytep)png_malloc(png_ptr, 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_byte)(png_ptr->mode & 0xff);
+    }
+
+    info_ptr->unknown_chunks = np;
+    info_ptr->unknown_chunks_num += num_unknowns;
+#ifdef PNG_FREE_ME_SUPPORTED
+    info_ptr->free_me |= PNG_FREE_UNKN;
+#endif
+}
+void PNGAPI
+png_set_unknown_chunk_location(png_structp png_ptr, png_infop info_ptr,
+   int chunk, int location)
+{
+   if(png_ptr != NULL && info_ptr != NULL && chunk >= 0 && chunk <
+         (int)info_ptr->unknown_chunks_num)
+      info_ptr->unknown_chunks[chunk].location = (png_byte)location;
+}
+#endif
+
+#if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \
+    defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED)
+void PNGAPI
+png_permit_empty_plte (png_structp png_ptr, int empty_plte_permitted)
+{
+   /* This function is deprecated in favor of png_permit_mng_features()
+      and will be removed from libpng-2.0.0 */
+   png_debug(1, "in png_permit_empty_plte, DEPRECATED.\n");
+   if (png_ptr == NULL)
+      return;
+   png_ptr->mng_features_permitted = (png_byte)
+     ((png_ptr->mng_features_permitted & (~(PNG_FLAG_MNG_EMPTY_PLTE))) |
+     ((empty_plte_permitted & PNG_FLAG_MNG_EMPTY_PLTE)));
+}
+#endif
+
+#if defined(PNG_MNG_FEATURES_SUPPORTED)
+png_uint_32 PNGAPI
+png_permit_mng_features (png_structp png_ptr, png_uint_32 mng_features)
+{
+   png_debug(1, "in png_permit_mng_features\n");
+   if (png_ptr == NULL)
+      return (png_uint_32)0;
+   png_ptr->mng_features_permitted =
+     (png_byte)(mng_features & PNG_ALL_MNG_FEATURES);
+   return (png_uint_32)png_ptr->mng_features_permitted;
+}
+#endif
+
+#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+void PNGAPI
+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_bytep)png_malloc(png_ptr,5*(num_chunks+old_num_chunks));
+    if(png_ptr->chunk_list != NULL)
+    {
+       png_memcpy(new_list, png_ptr->chunk_list, 5*old_num_chunks);
+       png_free(png_ptr, png_ptr->chunk_list);
+       png_ptr->chunk_list=NULL;
+    }
+    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;
+#ifdef PNG_FREE_ME_SUPPORTED
+    png_ptr->free_me |= PNG_FREE_LIST;
+#endif
+}
+#endif
+
+#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
+void PNGAPI
+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
+
+#if defined(PNG_INFO_IMAGE_SUPPORTED)
+void PNGAPI
+png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers)
+{
+   png_debug1(1, "in %s storage function\n", "rows");
+
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   if(info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers))
+      png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
+   info_ptr->row_pointers = row_pointers;
+   if(row_pointers)
+      info_ptr->valid |= PNG_INFO_IDAT;
+}
+#endif
+
+void PNGAPI
+png_set_compression_buffer_size(png_structp png_ptr, png_uint_32 size)
+{
+    if(png_ptr->zbuf)
+       png_free(png_ptr, png_ptr->zbuf);
+    png_ptr->zbuf_size = (png_size_t)size;
+    png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, size);
+    png_ptr->zstream.next_out = png_ptr->zbuf;
+    png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+}
+
+void PNGAPI
+png_set_invalid(png_structp png_ptr, png_infop info_ptr, int mask)
+{
+   if (png_ptr && info_ptr)
+      info_ptr->valid &= ~(mask);
+}
+
+
diff --git a/Utilities/ITK/Utilities/png/pngtest.c b/Utilities/ITK/Utilities/png/pngtest.c
new file mode 100644
index 0000000000..9b954b33f7
--- /dev/null
+++ b/Utilities/ITK/Utilities/png/pngtest.c
@@ -0,0 +1,1514 @@
+
+/* pngtest.c - a simple test program to test libpng
+ *
+ * libpng 1.0.12 - June 8, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * 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
+ * the basic chunk handling, filtering, and (de)compression code is working
+ * properly.  It does not currently test all of the transforms, although
+ * it probably should.
+ *
+ * The program will report "FAIL" in certain legitimate cases:
+ * 1) when the compression level or filter selection method is changed.
+ * 2) when the maximum IDAT size (PNG_ZBUF_SIZE in pngconf.h) is not 8192.
+ * 3) unknown unsafe-to-copy ancillary chunks or unknown critical 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 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
+ * testing a wide variety of files easily.  You can also test a number
+ * of files at once by typing "pngtest -m file1.png file2.png ..."
+ */
+
+#if defined(_WIN32_WCE)
+#  if _WIN32_WCE < 211
+     __error__ (f|w)printf functions are not supported on old WindowsCE.;
+#  endif
+#  include <windows.h>
+#  include <stdlib.h>
+#  define READFILE(file, data, length, check) \
+     if (ReadFile(file, data, length, &check,NULL)) check = 0
+#  define WRITEFILE(file, data, length, check)) \
+     if (WriteFile(file, data, length, &check, NULL)) check = 0
+#  define FCLOSE(file) CloseHandle(file)
+#else
+#  include <stdio.h>
+#  include <stdlib.h>
+#  include <assert.h>
+#  define READFILE(file, data, length, check) \
+     check=(png_size_t)fread(data,(png_size_t)1,length,file)
+#  define WRITEFILE(file, data, length, check) \
+     check=(png_size_t)fwrite(data,(png_size_t)1, length, file)
+#  define FCLOSE(file) fclose(file)
+#endif
+
+#if defined(PNG_NO_STDIO)
+#  if defined(_WIN32_WCE)
+     typedef HANDLE                png_FILE_p;
+#  else
+     typedef FILE                * png_FILE_p;
+#  endif
+#endif
+
+/* Makes pngtest verbose so we can find problems (needs to be before png.h) */
+#ifndef PNG_DEBUG
+#  define PNG_DEBUG 0
+#endif
+
+#if !PNG_DEBUG
+#  define SINGLE_ROWBUF_ALLOC	/* makes buffer overruns easier to nail */
+#endif
+
+/* Turn on CPU timing
+#define PNGTEST_TIMING
+*/
+
+#ifdef PNG_NO_FLOATING_POINT_SUPPORTED
+#undef PNGTEST_TIMING
+#endif
+
+#ifdef PNGTEST_TIMING
+static float t_start, t_stop, t_decode, t_encode, t_misc;
+#include <time.h>
+#endif
+
+#include "png.h"
+
+/* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */
+#ifndef png_jmpbuf
+#  define png_jmpbuf(png_ptr) png_ptr->jmpbuf
+#endif
+
+#ifdef PNGTEST_TIMING
+static float t_start, t_stop, t_decode, t_encode, t_misc;
+#if !defined(PNG_tIME_SUPPORTED)
+#include <time.h>
+#endif
+#endif
+
+#if defined(PNG_TIME_RFC1123_SUPPORTED)
+static int tIME_chunk_present=0;
+static char tIME_string[30] = "no tIME chunk present in file";
+#endif
+
+static int verbose = 0;
+
+int test_one_file PNGARG((PNG_CONST char *inname, PNG_CONST char *outname));
+
+#ifdef __TURBOC__
+#include <mem.h>
+#endif
+
+/* defined so I can write to a file on gui/windowing platforms */
+/*  #define STDERR stderr  */
+#define STDERR stdout   /* for DOS */
+
+/* example of using row callbacks to make a simple progress meter */
+static int status_pass=1;
+static int status_dots_requested=0;
+static int status_dots=1;
+
+void
+read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass);
+void
+read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass)
+{
+    if(png_ptr == NULL || row_number > PNG_MAX_UINT) return;
+    if(status_pass != pass)
+    {
+       fprintf(stdout,"\n Pass %d: ",pass);
+       status_pass = pass;
+       status_dots = 31;
+    }
+    status_dots--;
+    if(status_dots == 0)
+    {
+       fprintf(stdout, "\n         ");
+       status_dots=30;
+    }
+    fprintf(stdout, "r");
+}
+
+void
+write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass);
+void
+write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass)
+{
+    if(png_ptr == NULL || row_number > PNG_MAX_UINT || pass > 7) return;
+    fprintf(stdout, "w");
+}
+
+
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
+/* Example of using user transform callback (we don't transform anything,
+   but merely examine the row filters.  We set this to 256 rather than
+   5 in case illegal filter values are present.) */
+static png_uint_32 filters_used[256];
+void
+count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data);
+void
+count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data)
+{
+    if(png_ptr != NULL && row_info != NULL)
+      ++filters_used[*(data-1)];
+}
+#endif
+
+#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
+/* example of using user transform callback (we don't transform anything,
+   but merely count the zero samples) */
+
+static png_uint_32 zero_samples;
+
+void
+count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data);
+void
+count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data)
+{
+   png_bytep dp = data;
+   if(png_ptr == NULL)return;
+
+   /* contents of row_info:
+    *  png_uint_32 width      width of row
+    *  png_uint_32 rowbytes   number of bytes in row
+    *  png_byte color_type    color type of pixels
+    *  png_byte bit_depth     bit depth of samples
+    *  png_byte channels      number of channels (1-4)
+    *  png_byte pixel_depth   bits per pixel (depth*channels)
+    */
+
+
+    /* counts the number of zero samples (or zero pixels if color_type is 3 */
+
+    if(row_info->color_type == 0 || row_info->color_type == 3)
+    {
+       int pos=0;
+       png_uint_32 n, nstop;
+       for (n=0, nstop=row_info->width; n<nstop; n++)
+       {
+          if(row_info->bit_depth == 1)
+          {
+             if(((*dp << pos++ ) & 0x80) == 0) zero_samples++;
+             if(pos == 8)
+             {
+                pos = 0;
+                dp++;
+             }
+          }
+          if(row_info->bit_depth == 2)
+          {
+             if(((*dp << (pos+=2)) & 0xc0) == 0) zero_samples++;
+             if(pos == 8)
+             {
+                pos = 0;
+                dp++;
+             }
+          }
+          if(row_info->bit_depth == 4)
+          {
+             if(((*dp << (pos+=4)) & 0xf0) == 0) zero_samples++;
+             if(pos == 8)
+             {
+                pos = 0;
+                dp++;
+             }
+          }
+          if(row_info->bit_depth == 8)
+             if(*dp++ == 0) zero_samples++;
+          if(row_info->bit_depth == 16)
+          {
+             if((*dp | *(dp+1)) == 0) zero_samples++;
+             dp+=2;
+          }
+       }
+    }
+    else /* other color types */
+    {
+       png_uint_32 n, nstop;
+       int channel;
+       int color_channels = row_info->channels;
+       if(row_info->color_type > 3)color_channels--;
+
+       for (n=0, nstop=row_info->width; n<nstop; n++)
+       {
+          for (channel = 0; channel < color_channels; channel++)
+          {
+             if(row_info->bit_depth == 8)
+                if(*dp++ == 0) zero_samples++;
+             if(row_info->bit_depth == 16)
+             {
+                if((*dp | *(dp+1)) == 0) zero_samples++;
+                dp+=2;
+             }
+          }
+          if(row_info->color_type > 3)
+          {
+             dp++;
+             if(row_info->bit_depth == 16)dp++;
+          }
+       }
+    }
+}
+#endif /* PNG_WRITE_USER_TRANSFORM_SUPPORTED */
+
+static int wrote_question = 0;
+
+#if defined(PNG_NO_STDIO)
+/* START of code to validate stdio-free compilation */
+/* These copies of the default read/write functions come from pngrio.c and */
+/* pngwio.c.  They allow "don't include stdio" testing of the library. */
+/* This is the function that does the actual reading of data.  If you are
+   not reading from a standard C stream, you should create a replacement
+   read_data function and use it at run time with png_set_read_fn(), rather
+   than changing the library. */
+
+#ifndef USE_FAR_KEYWORD
+static void
+pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+   png_size_t check;
+
+   /* fread() returns 0 on error, so it is OK to store this in a png_size_t
+    * instead of an int, which is what fread() actually returns.
+    */
+   READFILE((png_FILE_p)png_ptr->io_ptr, data, length, check);
+
+   if (check != length)
+   {
+      png_error(png_ptr, "Read Error!");
+   }
+}
+#else
+/* this is the model-independent version. Since the standard I/O library
+   can't handle far buffers in the medium and small models, we have to copy
+   the data.
+*/
+
+#define NEAR_BUF_SIZE 1024
+#define MIN(a,b) (a <= b ? a : b)
+
+static void
+pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+   int check;
+   png_byte *n_data;
+   png_FILE_p io_ptr;
+
+   /* Check if data really is near. If so, use usual code. */
+   n_data = (png_byte *)CVT_PTR_NOCHECK(data);
+   io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
+   if ((png_bytep)n_data == data)
+   {
+      READFILE(io_ptr, n_data, length, check);
+   }
+   else
+   {
+      png_byte buf[NEAR_BUF_SIZE];
+      png_size_t read, remaining, err;
+      check = 0;
+      remaining = length;
+      do
+      {
+         read = MIN(NEAR_BUF_SIZE, remaining);
+         READFILE(io_ptr, buf, 1, err);
+         png_memcpy(data, buf, read); /* copy far buffer to near buffer */
+         if(err != read)
+            break;
+         else
+            check += err;
+         data += read;
+         remaining -= read;
+      }
+      while (remaining != 0);
+   }
+   if (check != length)
+   {
+      png_error(png_ptr, "read Error");
+   }
+}
+#endif /* USE_FAR_KEYWORD */
+
+#if defined(PNG_WRITE_FLUSH_SUPPORTED)
+static void
+pngtest_flush(png_structp png_ptr)
+{
+#if !defined(_WIN32_WCE)
+   png_FILE_p io_ptr;
+   io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr));
+   if (io_ptr != NULL)
+      fflush(io_ptr);
+#endif
+}
+#endif
+
+/* This is the function that does the actual writing of data.  If you are
+   not writing to a standard C stream, you should create a replacement
+   write_data function and use it at run time with png_set_write_fn(), rather
+   than changing the library. */
+#ifndef USE_FAR_KEYWORD
+static void
+pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+   png_uint_32 check;
+
+   WRITEFILE((png_FILE_p)png_ptr->io_ptr,  data, length, check);
+   if (check != length)
+   {
+      png_error(png_ptr, "Write Error");
+   }
+}
+#else
+/* this is the model-independent version. Since the standard I/O library
+   can't handle far buffers in the medium and small models, we have to copy
+   the data.
+*/
+
+#define NEAR_BUF_SIZE 1024
+#define MIN(a,b) (a <= b ? a : b)
+
+static void
+pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+   png_uint_32 check;
+   png_byte *near_data;  /* Needs to be "png_byte *" instead of "png_bytep" */
+   png_FILE_p io_ptr;
+
+   /* Check if data really is near. If so, use usual code. */
+   near_data = (png_byte *)CVT_PTR_NOCHECK(data);
+   io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
+   if ((png_bytep)near_data == data)
+   {
+      WRITEFILE(io_ptr, near_data, length, check);
+   }
+   else
+   {
+      png_byte buf[NEAR_BUF_SIZE];
+      png_size_t written, remaining, err;
+      check = 0;
+      remaining = length;
+      do
+      {
+         written = MIN(NEAR_BUF_SIZE, remaining);
+         png_memcpy(buf, data, written); /* copy far buffer to near buffer */
+         WRITEFILE(io_ptr, buf, written, err);
+         if (err != written)
+            break;
+         else
+            check += err;
+         data += written;
+         remaining -= written;
+      }
+      while (remaining != 0);
+   }
+   if (check != length)
+   {
+      png_error(png_ptr, "Write Error");
+   }
+}
+
+#endif /* USE_FAR_KEYWORD */
+
+/* This function is called when there is a warning, but the library thinks
+ * it can continue anyway.  Replacement functions don't have to do anything
+ * here if you don't want to.  In the default configuration, png_ptr is
+ * not used, but it is passed in case it may be useful.
+ */
+static void
+pngtest_warning(png_structp png_ptr, png_const_charp message)
+{
+   PNG_CONST char *name = "UNKNOWN (ERROR!)";
+   if (png_ptr != NULL && png_ptr->error_ptr != NULL)
+      name = png_ptr->error_ptr;
+   fprintf(STDERR, "%s: libpng warning: %s\n", name, message);
+}
+
+/* This is the default error handling function.  Note that replacements for
+ * this function MUST NOT RETURN, or the program will likely crash.  This
+ * function is used by default, or if the program supplies NULL for the
+ * error function pointer in png_set_error_fn().
+ */
+static void
+pngtest_error(png_structp png_ptr, png_const_charp message)
+{
+   pngtest_warning(png_ptr, message);
+   /* We can return because png_error calls the default handler, which is
+    * actually OK in this case. */
+}
+#endif /* PNG_NO_STDIO */
+/* END of code to validate stdio-free compilation */
+
+/* START of code to validate memory allocation and deallocation */
+#ifdef PNG_USER_MEM_SUPPORTED
+
+/* Allocate memory.  For reasonable files, size should never exceed
+   64K.  However, zlib may allocate more then 64K if you don't tell
+   it not to.  See zconf.h and png.h for more information.  zlib does
+   need to allocate exactly 64K, so whatever you call here must
+   have the ability to do that.
+
+   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
+{
+   png_uint_32               size;
+   png_voidp                 pointer;
+   struct memory_information FAR *next;
+} memory_information;
+typedef memory_information FAR *memory_infop;
+
+static memory_infop pinformation = NULL;
+static int current_allocation = 0;
+static int maximum_allocation = 0;
+static int total_allocation = 0;
+static int num_allocations = 0;
+
+extern PNG_EXPORT(png_voidp,png_debug_malloc) PNGARG((png_structp png_ptr,
+   png_uint_32 size));
+extern PNG_EXPORT(void,png_debug_free) PNGARG((png_structp png_ptr,
+   png_voidp ptr));
+
+png_voidp
+png_debug_malloc(png_structp png_ptr, png_uint_32 size)
+{
+
+   /* png_malloc has already tested for NULL; png_create_struct calls
+      png_debug_malloc directly, with png_ptr == NULL which is OK */
+
+   if (size == 0)
+      return (png_voidp)(NULL);
+
+   /* This calls the library allocator twice, once to get the requested
+      buffer and once to get a new free list entry. */
+   {
+      memory_infop pinfo = (memory_infop)png_malloc_default(png_ptr,
+         sizeof *pinfo);
+      pinfo->size = size;
+      current_allocation += size;
+      total_allocation += size;
+      num_allocations ++;
+      if (current_allocation > maximum_allocation)
+         maximum_allocation = current_allocation;
+      pinfo->pointer = (png_voidp)png_malloc_default(png_ptr, size);
+      pinfo->next = pinformation;
+      pinformation = pinfo;
+      /* Make sure the caller isn't assuming zeroed memory. */
+      png_memset(pinfo->pointer, 0xdd, pinfo->size);
+#if PNG_DEBUG
+      if(verbose)
+         printf("png_malloc %d bytes at %x\n",size,pinfo->pointer);
+#endif
+      assert(pinfo->size != 12345678);
+      return (png_voidp)(pinfo->pointer);
+   }
+}
+
+/* Free a pointer.  It is removed from the list at the same time. */
+void
+png_debug_free(png_structp png_ptr, png_voidp ptr)
+{
+   if (png_ptr == NULL)
+      fprintf(STDERR, "NULL pointer to png_debug_free.\n");
+   if (ptr == 0)
+   {
+#if 0 /* This happens all the time. */
+      fprintf(STDERR, "WARNING: freeing NULL pointer\n");
+#endif
+      return;
+   }
+
+   /* Unlink the element from the list. */
+   {
+      memory_infop FAR *ppinfo = &pinformation;
+      for (;;)
+      {
+         memory_infop pinfo = *ppinfo;
+         if (pinfo->pointer == ptr)
+         {
+            *ppinfo = pinfo->next;
+            current_allocation -= pinfo->size;
+            if (current_allocation < 0)
+               fprintf(STDERR, "Duplicate free of memory\n");
+            /* We must free the list element too, but first kill
+               the memory that is to be freed. */
+            png_memset(ptr, 0x55, pinfo->size);
+            png_free_default(png_ptr, pinfo);
+            pinfo=NULL;
+            break;
+         }
+         if (pinfo->next == NULL)
+         {
+            fprintf(STDERR, "Pointer %x not found\n", ptr);
+            break;
+         }
+         ppinfo = &pinfo->next;
+      }
+   }
+
+   /* Finally free the data. */
+#if PNG_DEBUG
+   if(verbose)
+      printf("Freeing %x\n",ptr);
+#endif
+   png_free_default(png_ptr, ptr);
+   ptr=NULL;
+}
+#endif /* PNG_USER_MEM_SUPPORTED */
+/* END of code to test memory allocation/deallocation */
+
+/* Test one file */
+int
+test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
+{
+   static png_FILE_p fpin;
+   static png_FILE_p fpout;  /* "static" prevents setjmp corruption */
+   png_structp read_ptr;
+   png_infop read_info_ptr, end_info_ptr;
+#ifdef PNG_WRITE_SUPPORTED
+   png_structp write_ptr;
+   png_infop write_info_ptr;
+   png_infop write_end_info_ptr;
+#else
+   png_structp write_ptr = NULL;
+   png_infop write_info_ptr = NULL;
+   png_infop write_end_info_ptr = NULL;
+#endif
+   png_bytep row_buf;
+   png_uint_32 y;
+   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
+
+#if defined(_WIN32_WCE)
+   TCHAR path[MAX_PATH];
+#endif
+   char inbuf[256], outbuf[256];
+
+   row_buf = (png_bytep)NULL;
+
+#if defined(_WIN32_WCE)
+   MultiByteToWideChar(CP_ACP, 0, inname, -1, path, MAX_PATH);
+   if ((fpin = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
+#else
+   if ((fpin = fopen(inname, "rb")) == NULL)
+#endif
+   {
+      fprintf(STDERR, "Could not find input file %s\n", inname);
+      return (1);
+   }
+
+#if defined(_WIN32_WCE)
+   MultiByteToWideChar(CP_ACP, 0, outname, -1, path, MAX_PATH);
+   if ((fpout = CreateFile(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL)) == INVALID_HANDLE_VALUE)
+#else
+   if ((fpout = fopen(outname, "wb")) == NULL)
+#endif
+   {
+      fprintf(STDERR, "Could not open output file %s\n", outname);
+      FCLOSE(fpin);
+      return (1);
+   }
+
+   png_debug(0, "Allocating read and write structures\n");
+#ifdef PNG_USER_MEM_SUPPORTED
+   read_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
+      (png_error_ptr)NULL, (png_error_ptr)NULL, (png_voidp)NULL,
+      (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free);
+#else
+   read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
+      (png_error_ptr)NULL, (png_error_ptr)NULL);
+#endif
+#if defined(PNG_NO_STDIO)
+   png_set_error_fn(read_ptr, (png_voidp)inname, pngtest_error,
+       pngtest_warning);
+#endif
+#ifdef PNG_WRITE_SUPPORTED
+#ifdef PNG_USER_MEM_SUPPORTED
+   write_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
+      (png_error_ptr)NULL, (png_error_ptr)NULL, (png_voidp)NULL,
+      (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free);
+#else
+   write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
+      (png_error_ptr)NULL, (png_error_ptr)NULL);
+#endif
+#if defined(PNG_NO_STDIO)
+   png_set_error_fn(write_ptr, (png_voidp)inname, pngtest_error,
+       pngtest_warning);
+#endif
+#endif
+   png_debug(0, "Allocating read_info, write_info and end_info structures\n");
+   read_info_ptr = png_create_info_struct(read_ptr);
+   end_info_ptr = png_create_info_struct(read_ptr);
+#ifdef PNG_WRITE_SUPPORTED
+   write_info_ptr = png_create_info_struct(write_ptr);
+   write_end_info_ptr = png_create_info_struct(write_ptr);
+#endif
+
+#ifdef PNG_SETJMP_SUPPORTED
+   png_debug(0, "Setting jmpbuf for read struct\n");
+#ifdef USE_FAR_KEYWORD
+   if (setjmp(jmpbuf))
+#else
+   if (setjmp(png_jmpbuf(read_ptr)))
+#endif
+   {
+      fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname);
+      png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
+#ifdef PNG_WRITE_SUPPORTED
+      png_destroy_info_struct(write_ptr, &write_end_info_ptr);
+      png_destroy_write_struct(&write_ptr, &write_info_ptr);
+#endif
+      FCLOSE(fpin);
+      FCLOSE(fpout);
+      return (1);
+   }
+#ifdef USE_FAR_KEYWORD
+   png_memcpy(png_jmpbuf(read_ptr),jmpbuf,sizeof(jmp_buf));
+#endif
+
+#ifdef PNG_WRITE_SUPPORTED
+   png_debug(0, "Setting jmpbuf for write struct\n");
+#ifdef USE_FAR_KEYWORD
+   if (setjmp(jmpbuf))
+#else
+   if (setjmp(png_jmpbuf(write_ptr)))
+#endif
+   {
+      fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname);
+      png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
+      png_destroy_info_struct(write_ptr, &write_end_info_ptr);
+#ifdef PNG_WRITE_SUPPORTED
+      png_destroy_write_struct(&write_ptr, &write_info_ptr);
+#endif
+      FCLOSE(fpin);
+      FCLOSE(fpout);
+      return (1);
+   }
+#ifdef USE_FAR_KEYWORD
+   png_memcpy(png_jmpbuf(write_ptr),jmpbuf,sizeof(jmp_buf));
+#endif
+#endif
+#endif
+
+   png_debug(0, "Initializing input and output streams\n");
+#if !defined(PNG_NO_STDIO)
+   png_init_io(read_ptr, fpin);
+#  ifdef PNG_WRITE_SUPPORTED
+   png_init_io(write_ptr, fpout);
+#  endif
+#else
+   png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data);
+#  ifdef PNG_WRITE_SUPPORTED
+   png_set_write_fn(write_ptr, (png_voidp)fpout,  pngtest_write_data,
+#    if defined(PNG_WRITE_FLUSH_SUPPORTED)
+      pngtest_flush);
+#    else
+      NULL);
+#    endif
+#  endif
+#endif
+   if(status_dots_requested == 1)
+   {
+#ifdef PNG_WRITE_SUPPORTED
+      png_set_write_status_fn(write_ptr, write_row_callback);
+#endif
+      png_set_read_status_fn(read_ptr, read_row_callback);
+   }
+   else
+   {
+#ifdef PNG_WRITE_SUPPORTED
+      png_set_write_status_fn(write_ptr, NULL);
+#endif
+      png_set_read_status_fn(read_ptr, NULL);
+   }
+
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
+   {
+     int i;
+     for(i=0; i<256; i++)
+        filters_used[i]=0;
+     png_set_read_user_transform_fn(read_ptr, count_filters);
+   }
+#endif
+#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
+   zero_samples=0;
+   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);
+
+   png_debug(0, "Transferring info struct\n");
+   {
+      int interlace_type, compression_type, filter_type;
+
+      if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth,
+          &color_type, &interlace_type, &compression_type, &filter_type))
+      {
+         png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth,
+#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
+            color_type, interlace_type, compression_type, filter_type);
+#else
+            color_type, PNG_INTERLACE_NONE, compression_type, filter_type);
+#endif
+      }
+   }
+#if defined(PNG_FIXED_POINT_SUPPORTED)
+#if defined(PNG_cHRM_SUPPORTED)
+   {
+      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,
+         &red_y, &green_x, &green_y, &blue_x, &blue_y))
+      {
+         png_set_cHRM_fixed(write_ptr, write_info_ptr, white_x, white_y, red_x,
+            red_y, green_x, green_y, blue_x, blue_y);
+      }
+   }
+#endif
+#if defined(PNG_gAMA_SUPPORTED)
+   {
+      png_fixed_point gamma;
+
+      if (png_get_gAMA_fixed(read_ptr, read_info_ptr, &gamma))
+      {
+         png_set_gAMA_fixed(write_ptr, write_info_ptr, gamma);
+      }
+   }
+#endif
+#else /* Use floating point versions */
+#if defined(PNG_FLOATING_POINT_SUPPORTED)
+#if defined(PNG_cHRM_SUPPORTED)
+   {
+      double white_x, white_y, red_x, red_y, green_x, green_y, blue_x,
+         blue_y;
+      if (png_get_cHRM(read_ptr, read_info_ptr, &white_x, &white_y, &red_x,
+         &red_y, &green_x, &green_y, &blue_x, &blue_y))
+      {
+         png_set_cHRM(write_ptr, write_info_ptr, white_x, white_y, red_x,
+            red_y, green_x, green_y, blue_x, blue_y);
+      }
+   }
+#endif
+#if defined(PNG_gAMA_SUPPORTED)
+   {
+      double gamma;
+
+      if (png_get_gAMA(read_ptr, read_info_ptr, &gamma))
+      {
+         png_set_gAMA(write_ptr, write_info_ptr, gamma);
+      }
+   }
+#endif
+#endif /* floating point */
+#endif /* fixed point */
+#if defined(PNG_iCCP_SUPPORTED)
+   {
+      png_charp name;
+      png_charp profile;
+      png_uint_32 proflen;
+      int compression_type;
+
+      if (png_get_iCCP(read_ptr, read_info_ptr, &name, &compression_type,
+                      &profile, &proflen))
+      {
+         png_set_iCCP(write_ptr, write_info_ptr, name, compression_type,
+                      profile, proflen);
+      }
+   }
+#endif
+#if defined(PNG_sRGB_SUPPORTED)
+   {
+      int intent;
+
+      if (png_get_sRGB(read_ptr, read_info_ptr, &intent))
+      {
+         png_set_sRGB(write_ptr, write_info_ptr, intent);
+      }
+   }
+#endif
+   {
+      png_colorp palette;
+      int num_palette;
+
+      if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette))
+      {
+         png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette);
+      }
+   }
+#if defined(PNG_bKGD_SUPPORTED)
+   {
+      png_color_16p background;
+
+      if (png_get_bKGD(read_ptr, read_info_ptr, &background))
+      {
+         png_set_bKGD(write_ptr, write_info_ptr, background);
+      }
+   }
+#endif
+#if defined(PNG_hIST_SUPPORTED)
+   {
+      png_uint_16p hist;
+
+      if (png_get_hIST(read_ptr, read_info_ptr, &hist))
+      {
+         png_set_hIST(write_ptr, write_info_ptr, hist);
+      }
+   }
+#endif
+#if defined(PNG_oFFs_SUPPORTED)
+   {
+      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))
+      {
+         png_set_oFFs(write_ptr, write_info_ptr, offset_x, offset_y, unit_type);
+      }
+   }
+#endif
+#if defined(PNG_pCAL_SUPPORTED)
+   {
+      png_charp purpose, units;
+      png_charpp params;
+      png_int_32 X0, X1;
+      int type, nparams;
+
+      if (png_get_pCAL(read_ptr, read_info_ptr, &purpose, &X0, &X1, &type,
+         &nparams, &units, &params))
+      {
+         png_set_pCAL(write_ptr, write_info_ptr, purpose, X0, X1, type,
+            nparams, units, params);
+      }
+   }
+#endif
+#if defined(PNG_pHYs_SUPPORTED)
+   {
+      png_uint_32 res_x, res_y;
+      int unit_type;
+
+      if (png_get_pHYs(read_ptr, read_info_ptr, &res_x, &res_y, &unit_type))
+      {
+         png_set_pHYs(write_ptr, write_info_ptr, res_x, res_y, unit_type);
+      }
+   }
+#endif
+#if defined(PNG_sBIT_SUPPORTED)
+   {
+      png_color_8p sig_bit;
+
+      if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit))
+      {
+         png_set_sBIT(write_ptr, write_info_ptr, sig_bit);
+      }
+   }
+#endif
+#if defined(PNG_sCAL_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   {
+      int unit;
+      double scal_width, scal_height;
+
+      if (png_get_sCAL(read_ptr, read_info_ptr, &unit, &scal_width,
+         &scal_height))
+      {
+         png_set_sCAL(write_ptr, write_info_ptr, unit, scal_width, scal_height);
+      }
+   }
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   {
+      int unit;
+      png_charp scal_width, scal_height;
+
+      if (png_get_sCAL_s(read_ptr, read_info_ptr, &unit, &scal_width,
+          &scal_height))
+      {
+         png_set_sCAL_s(write_ptr, write_info_ptr, unit, scal_width, scal_height);
+      }
+   }
+#endif
+#endif
+#endif
+#if defined(PNG_TEXT_SUPPORTED)
+   {
+      png_textp text_ptr;
+      int num_text;
+
+      if (png_get_text(read_ptr, read_info_ptr, &text_ptr, &num_text) > 0)
+      {
+         png_debug1(0, "Handling %d iTXt/tEXt/zTXt chunks\n", num_text);
+         png_set_text(write_ptr, write_info_ptr, text_ptr, num_text);
+      }
+   }
+#endif
+#if defined(PNG_tIME_SUPPORTED)
+   {
+      png_timep mod_time;
+
+      if (png_get_tIME(read_ptr, read_info_ptr, &mod_time))
+      {
+         png_set_tIME(write_ptr, write_info_ptr, mod_time);
+#if defined(PNG_TIME_RFC1123_SUPPORTED)
+         /* we have to use png_strcpy instead of "=" because the string
+            pointed to by png_convert_to_rfc1123() gets free'ed before
+            we use it */
+         png_strcpy(tIME_string,png_convert_to_rfc1123(read_ptr, mod_time));
+         tIME_chunk_present++;
+#endif /* PNG_TIME_RFC1123_SUPPORTED */
+      }
+   }
+#endif
+#if defined(PNG_tRNS_SUPPORTED)
+   {
+      png_bytep trans;
+      int num_trans;
+      png_color_16p trans_values;
+
+      if (png_get_tRNS(read_ptr, read_info_ptr, &trans, &num_trans,
+         &trans_values))
+      {
+         png_set_tRNS(write_ptr, write_info_ptr, trans, num_trans,
+            trans_values);
+      }
+   }
+#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++)
+           png_set_unknown_chunk_location(write_ptr, write_info_ptr, i,
+             unknowns[i].location);
+      }
+   }
+#endif
+
+#ifdef PNG_WRITE_SUPPORTED
+   png_debug(0, "\nWriting info struct\n");
+
+/* If we wanted, we could write info in two steps:
+   png_write_info_before_PLTE(write_ptr, write_info_ptr);
+ */
+   png_write_info(write_ptr, write_info_ptr);
+#endif
+
+#ifdef SINGLE_ROWBUF_ALLOC
+   png_debug(0, "\nAllocating row buffer...");
+   row_buf = (png_bytep)png_malloc(read_ptr,
+      png_get_rowbytes(read_ptr, read_info_ptr));
+   png_debug1(0, "0x%08lx\n\n", (unsigned long)row_buf);
+#endif /* SINGLE_ROWBUF_ALLOC */
+   png_debug(0, "Writing row data\n");
+
+#if defined(PNG_READ_INTERLACING_SUPPORTED) || \
+  defined(PNG_WRITE_INTERLACING_SUPPORTED)
+   num_pass = png_set_interlace_handling(read_ptr);
+#  ifdef PNG_WRITE_SUPPORTED
+   png_set_interlace_handling(write_ptr);
+#  endif
+#else
+   num_pass=1;
+#endif
+
+#ifdef PNGTEST_TIMING
+   t_stop = (float)clock();
+   t_misc += (t_stop - t_start);
+   t_start = t_stop;
+#endif
+   for (pass = 0; pass < num_pass; pass++)
+   {
+      png_debug1(0, "Writing row data for pass %d\n",pass);
+      for (y = 0; y < height; y++)
+      {
+#ifndef SINGLE_ROWBUF_ALLOC
+         png_debug2(0, "\nAllocating row buffer (pass %d, y = %ld)...", pass,y);
+         row_buf = (png_bytep)png_malloc(read_ptr,
+            png_get_rowbytes(read_ptr, read_info_ptr));
+         png_debug2(0, "0x%08lx (%ld bytes)\n", (unsigned long)row_buf,
+            png_get_rowbytes(read_ptr, read_info_ptr));
+#endif /* !SINGLE_ROWBUF_ALLOC */
+         png_read_rows(read_ptr, (png_bytepp)&row_buf, (png_bytepp)NULL, 1);
+
+#ifdef PNG_WRITE_SUPPORTED
+#ifdef PNGTEST_TIMING
+         t_stop = (float)clock();
+         t_decode += (t_stop - t_start);
+         t_start = t_stop;
+#endif
+         png_write_rows(write_ptr, (png_bytepp)&row_buf, 1);
+#ifdef PNGTEST_TIMING
+         t_stop = (float)clock();
+         t_encode += (t_stop - t_start);
+         t_start = t_stop;
+#endif
+#endif /* PNG_WRITE_SUPPORTED */
+
+#ifndef SINGLE_ROWBUF_ALLOC
+         png_debug2(0, "Freeing row buffer (pass %d, y = %ld)\n\n", pass, y);
+         png_free(read_ptr, row_buf);
+#endif /* !SINGLE_ROWBUF_ALLOC */
+      }
+   }
+
+#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
+   png_free_data(read_ptr, read_info_ptr, PNG_FREE_UNKN, -1);
+#endif
+#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
+   png_free_data(write_ptr, write_info_ptr, PNG_FREE_UNKN, -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)
+   {
+      png_textp text_ptr;
+      int num_text;
+
+      if (png_get_text(read_ptr, end_info_ptr, &text_ptr, &num_text) > 0)
+      {
+         png_debug1(0, "Handling %d iTXt/tEXt/zTXt chunks\n", num_text);
+         png_set_text(write_ptr, write_end_info_ptr, text_ptr, num_text);
+      }
+   }
+#endif
+#if defined(PNG_tIME_SUPPORTED)
+   {
+      png_timep mod_time;
+
+      if (png_get_tIME(read_ptr, end_info_ptr, &mod_time))
+      {
+         png_set_tIME(write_ptr, write_end_info_ptr, mod_time);
+#if defined(PNG_TIME_RFC1123_SUPPORTED)
+         /* we have to use png_strcpy instead of "=" because the string
+            pointed to by png_convert_to_rfc1123() gets free'ed before
+            we use it */
+         png_strcpy(tIME_string,png_convert_to_rfc1123(read_ptr, mod_time));
+         tIME_chunk_present++;
+#endif /* PNG_TIME_RFC1123_SUPPORTED */
+      }
+   }
+#endif
+#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++)
+           png_set_unknown_chunk_location(write_ptr, write_end_info_ptr, i,
+             unknowns[i].location);
+      }
+   }
+#endif
+#ifdef PNG_WRITE_SUPPORTED
+   png_write_end(write_ptr, write_end_info_ptr);
+#endif
+
+#ifdef PNG_EASY_ACCESS_SUPPORTED
+   if(verbose)
+   {
+      png_uint_32 iwidth, iheight;
+      iwidth = png_get_image_width(write_ptr, write_info_ptr);
+      iheight = png_get_image_height(write_ptr, write_info_ptr);
+      fprintf(STDERR, "Image width = %lu, height = %lu\n",
+         iwidth, iheight);
+   }
+#endif
+
+   png_debug(0, "Destroying data structs\n");
+#ifdef SINGLE_ROWBUF_ALLOC
+   png_debug(1, "destroying row_buf for read_ptr\n");
+   png_free(read_ptr, row_buf);
+   row_buf=NULL;
+#endif /* SINGLE_ROWBUF_ALLOC */
+   png_debug(1, "destroying read_ptr, read_info_ptr, end_info_ptr\n");
+   png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
+#ifdef PNG_WRITE_SUPPORTED
+   png_debug(1, "destroying write_end_info_ptr\n");
+   png_destroy_info_struct(write_ptr, &write_end_info_ptr);
+   png_debug(1, "destroying write_ptr, write_info_ptr\n");
+   png_destroy_write_struct(&write_ptr, &write_info_ptr);
+#endif
+   png_debug(0, "Destruction complete.\n");
+
+   FCLOSE(fpin);
+   FCLOSE(fpout);
+
+   png_debug(0, "Opening files for comparison\n");
+#if defined(_WIN32_WCE)
+   MultiByteToWideChar(CP_ACP, 0, inname, -1, path, MAX_PATH);
+   if ((fpin = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
+#else
+   if ((fpin = fopen(inname, "rb")) == NULL)
+#endif
+   {
+      fprintf(STDERR, "Could not find file %s\n", inname);
+      return (1);
+   }
+
+#if defined(_WIN32_WCE)
+   MultiByteToWideChar(CP_ACP, 0, outname, -1, path, MAX_PATH);
+   if ((fpout = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
+#else
+   if ((fpout = fopen(outname, "rb")) == NULL)
+#endif
+   {
+      fprintf(STDERR, "Could not find file %s\n", outname);
+      FCLOSE(fpin);
+      return (1);
+   }
+
+   for(;;)
+   {
+      png_size_t num_in, num_out;
+
+      READFILE(fpin, inbuf, 1, num_in);
+      READFILE(fpout, outbuf, 1, num_out);
+
+      if (num_in != num_out)
+      {
+         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 maximum IDAT chunk size (%d bytes),",
+              inname,PNG_ZBUF_SIZE);
+            fprintf(STDERR,
+              "\n   filtering heuristic (libpng default), compression");
+            fprintf(STDERR,
+              " level (zlib default),\n   and zlib version (%s)?\n\n",
+              ZLIB_VERSION);
+            wrote_question=1;
+         }
+         FCLOSE(fpin);
+         FCLOSE(fpout);
+         return (0);
+      }
+
+      if (!num_in)
+         break;
+
+      if (png_memcmp(inbuf, outbuf, num_in))
+      {
+         fprintf(STDERR, "\nFiles %s and %s are different\n", inname, outname);
+         if(wrote_question == 0)
+         {
+            fprintf(STDERR,
+         "   Was %s written with the same maximum IDAT chunk size (%d bytes),",
+                 inname,PNG_ZBUF_SIZE);
+            fprintf(STDERR,
+              "\n   filtering heuristic (libpng default), compression");
+            fprintf(STDERR,
+              " level (zlib default),\n   and zlib version (%s)?\n\n",
+              ZLIB_VERSION);
+            wrote_question=1;
+         }
+         FCLOSE(fpin);
+         FCLOSE(fpout);
+         return (0);
+      }
+   }
+
+   FCLOSE(fpin);
+   FCLOSE(fpout);
+
+   return (0);
+}
+
+/* input and output filenames */
+#ifdef RISCOS
+static PNG_CONST char *inname = "pngtest/png";
+static PNG_CONST char *outname = "pngout/png";
+#else
+static PNG_CONST char *inname = "pngtest.png";
+static PNG_CONST char *outname = "pngout.png";
+#endif
+
+int
+main(int argc, char *argv[])
+{
+   int multiple = 0;
+   int ierror = 0;
+
+   fprintf(STDERR, "Testing libpng version %s\n", PNG_LIBPNG_VER_STRING);
+   fprintf(STDERR, "   with zlib   version %s\n", ZLIB_VERSION);
+   fprintf(STDERR,"%s",png_get_copyright(NULL));
+   /* Show the version of libpng used in building the library */
+   fprintf(STDERR," library (%lu):%s", png_access_version_number(),
+      png_get_header_version(NULL));
+   /* Show the version of libpng used in building the application */
+   fprintf(STDERR," pngtest (%lu):%s", (unsigned long)PNG_LIBPNG_VER,
+      PNG_HEADER_VERSION_STRING);
+   fprintf(STDERR," sizeof(png_struct)=%d, sizeof(png_info)=%d\n",
+                    sizeof(png_struct), sizeof(png_info));
+
+   /* Do some consistency checking on the memory allocation settings, I'm
+      not sure this matters, but it is nice to know, the first of these
+      tests should be impossible because of the way the macros are set
+      in pngconf.h */
+#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K)
+      fprintf(STDERR, " NOTE: Zlib compiled for max 64k, libpng not\n");
+#endif
+   /* I think the following can happen. */
+#if !defined(MAXSEG_64K) && defined(PNG_MAX_MALLOC_64K)
+      fprintf(STDERR, " NOTE: libpng compiled for max 64k, zlib not\n");
+#endif
+
+   if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING))
+   {
+      fprintf(STDERR,
+         "Warning: versions are different between png.h and png.c\n");
+      fprintf(STDERR, "  png.h version: %s\n", PNG_LIBPNG_VER_STRING);
+      fprintf(STDERR, "  png.c version: %s\n\n", png_libpng_ver);
+      ++ierror;
+   }
+
+   if (argc > 1)
+   {
+      if (strcmp(argv[1], "-m") == 0)
+      {
+         multiple = 1;
+         status_dots_requested = 0;
+      }
+      else if (strcmp(argv[1], "-mv") == 0 ||
+               strcmp(argv[1], "-vm") == 0 )
+      {
+         multiple = 1;
+         verbose = 1;
+         status_dots_requested = 1;
+      }
+      else if (strcmp(argv[1], "-v") == 0)
+      {
+         verbose = 1;
+         status_dots_requested = 1;
+         inname = argv[2];
+      }
+      else
+      {
+         inname = argv[1];
+         status_dots_requested = 0;
+      }
+   }
+
+   if (!multiple && argc == 3+verbose)
+     outname = argv[2+verbose];
+
+   if ((!multiple && argc > 3+verbose) || (multiple && argc < 2))
+   {
+     fprintf(STDERR,
+       "usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n",
+        argv[0], argv[0]);
+     fprintf(STDERR,
+       "  reads/writes one PNG file (without -m) or multiple files (-m)\n");
+     fprintf(STDERR,
+       "  with -m %s is used as a temporary file\n", outname);
+     exit(1);
+   }
+
+   if (multiple)
+   {
+      int i;
+#ifdef PNG_USER_MEM_SUPPORTED
+      int allocation_now = current_allocation;
+#endif
+      for (i=2; i<argc; ++i)
+      {
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
+         int k;
+#endif
+         int kerror;
+         fprintf(STDERR, "Testing %s:",argv[i]);
+         kerror = test_one_file(argv[i], outname);
+         if (kerror == 0)
+         {
+#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
+            fprintf(STDERR, "\n PASS (%lu zero samples)\n",zero_samples);
+#else
+            fprintf(STDERR, " PASS\n");
+#endif
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
+            for (k=0; k<256; k++)
+               if(filters_used[k])
+                  fprintf(STDERR, " Filter %d was used %lu times\n",
+                     k,filters_used[k]);
+#endif
+#if defined(PNG_TIME_RFC1123_SUPPORTED)
+         if(tIME_chunk_present != 0)
+            fprintf(STDERR, " tIME = %s\n",tIME_string);
+         tIME_chunk_present = 0;
+#endif /* PNG_TIME_RFC1123_SUPPORTED */
+         }
+         else
+         {
+            fprintf(STDERR, " FAIL\n");
+            ierror += kerror;
+         }
+#ifdef PNG_USER_MEM_SUPPORTED
+         if (allocation_now != current_allocation)
+            fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n",
+               current_allocation-allocation_now);
+         if (current_allocation != 0)
+         {
+            memory_infop pinfo = pinformation;
+
+            fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n",
+               current_allocation);
+            while (pinfo != NULL)
+            {
+               fprintf(STDERR, " %d bytes at %x\n", pinfo->size, pinfo->pointer);
+               pinfo = pinfo->next;
+            }
+         }
+#endif
+      }
+#ifdef PNG_USER_MEM_SUPPORTED
+         fprintf(STDERR, " Current memory allocation: %10d bytes\n",
+            current_allocation);
+         fprintf(STDERR, " Maximum memory allocation: %10d bytes\n",
+            maximum_allocation);
+         fprintf(STDERR, " Total   memory allocation: %10d bytes\n",
+            total_allocation);
+         fprintf(STDERR, "     Number of allocations: %10d\n",
+            num_allocations);
+#endif
+   }
+   else
+   {
+      int i;
+      for (i=0; i<3; ++i)
+      {
+         int kerror;
+#ifdef PNG_USER_MEM_SUPPORTED
+         int allocation_now = current_allocation;
+#endif
+         if (i == 1) status_dots_requested = 1;
+         else if(verbose == 0)status_dots_requested = 0;
+         if (i == 0 || verbose == 1 || ierror != 0)
+            fprintf(STDERR, "Testing %s:",inname);
+         kerror = test_one_file(inname, outname);
+         if(kerror == 0)
+         {
+            if(verbose == 1 || i == 2)
+            {
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
+                int k;
+#endif
+#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
+                fprintf(STDERR, "\n PASS (%lu zero samples)\n",zero_samples);
+#else
+                fprintf(STDERR, " PASS\n");
+#endif
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
+                for (k=0; k<256; k++)
+                   if(filters_used[k])
+                      fprintf(STDERR, " Filter %d was used %lu times\n",
+                         k,filters_used[k]);
+#endif
+#if defined(PNG_TIME_RFC1123_SUPPORTED)
+             if(tIME_chunk_present != 0)
+                fprintf(STDERR, " tIME = %s\n",tIME_string);
+#endif /* PNG_TIME_RFC1123_SUPPORTED */
+            }
+         }
+         else
+         {
+            if(verbose == 0 && i != 2)
+               fprintf(STDERR, "Testing %s:",inname);
+            fprintf(STDERR, " FAIL\n");
+            ierror += kerror;
+         }
+#ifdef PNG_USER_MEM_SUPPORTED
+         if (allocation_now != current_allocation)
+             fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n",
+               current_allocation-allocation_now);
+         if (current_allocation != 0)
+         {
+             memory_infop pinfo = pinformation;
+
+             fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n",
+                current_allocation);
+             while (pinfo != NULL)
+             {
+                fprintf(STDERR," %d bytes at %x\n",
+                   pinfo->size, pinfo->pointer);
+                pinfo = pinfo->next;
+             }
+          }
+#endif
+       }
+#ifdef PNG_USER_MEM_SUPPORTED
+       fprintf(STDERR, " Current memory allocation: %10d bytes\n",
+          current_allocation);
+       fprintf(STDERR, " Maximum memory allocation: %10d bytes\n",
+          maximum_allocation);
+       fprintf(STDERR, " Total   memory allocation: %10d bytes\n",
+          total_allocation);
+       fprintf(STDERR, "     Number of allocations: %10d\n",
+            num_allocations);
+#endif
+   }
+
+#ifdef PNGTEST_TIMING
+   t_stop = (float)clock();
+   t_misc += (t_stop - t_start);
+   t_start = t_stop;
+   fprintf(STDERR," CPU time used = %.3f seconds",
+      (t_misc+t_decode+t_encode)/(float)CLOCKS_PER_SEC);
+   fprintf(STDERR," (decoding %.3f,\n",
+      t_decode/(float)CLOCKS_PER_SEC);
+   fprintf(STDERR,"        encoding %.3f ,",
+      t_encode/(float)CLOCKS_PER_SEC);
+   fprintf(STDERR," other %.3f seconds)\n\n",
+      t_misc/(float)CLOCKS_PER_SEC);
+#endif
+
+   if (ierror == 0)
+      fprintf(STDERR, "libpng passes test\n");
+   else
+      fprintf(STDERR, "libpng FAILS test\n");
+   return (int)(ierror != 0);
+}
+
+/* Generate a compiler error if there is an old png.h in the search path. */
+typedef version_1_0_12 your_png_h_is_not_version_1_0_12;
diff --git a/Utilities/ITK/Utilities/png/pngtrans.c b/Utilities/ITK/Utilities/png/pngtrans.c
new file mode 100644
index 0000000000..3e757c171c
--- /dev/null
+++ b/Utilities/ITK/Utilities/png/pngtrans.c
@@ -0,0 +1,611 @@
+
+/* pngtrans.c - transforms the data in a row (used by both readers and writers)
+ *
+ * libpng 1.0.12 - June 8, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ */
+
+#define PNG_INTERNAL
+#include "png.h"
+
+#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
+/* turn on BGR-to-RGB mapping */
+void PNGAPI
+png_set_bgr(png_structp png_ptr)
+{
+   png_debug(1, "in png_set_bgr\n");
+   png_ptr->transformations |= PNG_BGR;
+}
+#endif
+
+#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
+/* turn on 16 bit byte swapping */
+void PNGAPI
+png_set_swap(png_structp png_ptr)
+{
+   png_debug(1, "in png_set_swap\n");
+   if (png_ptr->bit_depth == 16)
+      png_ptr->transformations |= PNG_SWAP_BYTES;
+}
+#endif
+
+#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
+/* turn on pixel packing */
+void PNGAPI
+png_set_packing(png_structp png_ptr)
+{
+   png_debug(1, "in png_set_packing\n");
+   if (png_ptr->bit_depth < 8)
+   {
+      png_ptr->transformations |= PNG_PACK;
+      png_ptr->usr_bit_depth = 8;
+   }
+}
+#endif
+
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
+/* turn on packed pixel swapping */
+void PNGAPI
+png_set_packswap(png_structp png_ptr)
+{
+   png_debug(1, "in png_set_packswap\n");
+   if (png_ptr->bit_depth < 8)
+      png_ptr->transformations |= PNG_PACKSWAP;
+}
+#endif
+
+#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
+void PNGAPI
+png_set_shift(png_structp png_ptr, png_color_8p true_bits)
+{
+   png_debug(1, "in png_set_shift\n");
+   png_ptr->transformations |= PNG_SHIFT;
+   png_ptr->shift = *true_bits;
+}
+#endif
+
+#if defined(PNG_READ_INTERLACING_SUPPORTED) || \
+    defined(PNG_WRITE_INTERLACING_SUPPORTED)
+int PNGAPI
+png_set_interlace_handling(png_structp png_ptr)
+{
+   png_debug(1, "in png_set_interlace handling\n");
+   if (png_ptr->interlaced)
+   {
+      png_ptr->transformations |= PNG_INTERLACE;
+      return (7);
+   }
+
+   return (1);
+}
+#endif
+
+#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
+/* Add a filler byte on read, or remove a filler or alpha byte on write.
+ * The filler type has changed in v0.95 to allow future 2-byte fillers
+ * for 48-bit input data, as well as to avoid problems with some compilers
+ * that don't like bytes as parameters.
+ */
+void PNGAPI
+png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc)
+{
+   png_debug(1, "in png_set_filler\n");
+   png_ptr->transformations |= PNG_FILLER;
+   png_ptr->filler = (png_byte)filler;
+   if (filler_loc == PNG_FILLER_AFTER)
+      png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
+   else
+      png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
+
+   /* This should probably go in the "do_filler" routine.
+    * I attempted to do that in libpng-1.0.1a but that caused problems
+    * so I restored it in libpng-1.0.2a
+   */
+
+   if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
+   {
+      png_ptr->usr_channels = 4;
+   }
+
+   /* Also I added this in libpng-1.0.2a (what happens when we expand
+    * a less-than-8-bit grayscale to GA? */
+
+   if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY && png_ptr->bit_depth >= 8)
+   {
+      png_ptr->usr_channels = 2;
+   }
+}
+#endif
+
+#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
+    defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
+void PNGAPI
+png_set_swap_alpha(png_structp png_ptr)
+{
+   png_debug(1, "in png_set_swap_alpha\n");
+   png_ptr->transformations |= PNG_SWAP_ALPHA;
+}
+#endif
+
+#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
+    defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
+void PNGAPI
+png_set_invert_alpha(png_structp png_ptr)
+{
+   png_debug(1, "in png_set_invert_alpha\n");
+   png_ptr->transformations |= PNG_INVERT_ALPHA;
+}
+#endif
+
+#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
+void PNGAPI
+png_set_invert_mono(png_structp png_ptr)
+{
+   png_debug(1, "in png_set_invert_mono\n");
+   png_ptr->transformations |= PNG_INVERT_MONO;
+}
+
+/* invert monochrome grayscale data */
+void /* PRIVATE */
+png_do_invert(png_row_infop row_info, png_bytep row)
+{
+   png_debug(1, "in png_do_invert\n");
+   if (row_info->bit_depth == 1 &&
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+       row != NULL && row_info != NULL &&
+#endif
+       row_info->color_type == PNG_COLOR_TYPE_GRAY)
+   {
+      png_bytep rp = row;
+      png_uint_32 i;
+      png_uint_32 istop = row_info->rowbytes;
+
+      for (i = 0; i < istop; i++)
+      {
+         *rp = (png_byte)(~(*rp));
+         rp++;
+      }
+   }
+}
+#endif
+
+#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
+/* swaps byte order on 16 bit depth images */
+void /* PRIVATE */
+png_do_swap(png_row_infop row_info, png_bytep row)
+{
+   png_debug(1, "in png_do_swap\n");
+   if (
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+       row != NULL && row_info != NULL &&
+#endif
+       row_info->bit_depth == 16)
+   {
+      png_bytep rp = row;
+      png_uint_32 i;
+      png_uint_32 istop= row_info->width * row_info->channels;
+
+      for (i = 0; i < istop; i++, rp += 2)
+      {
+         png_byte t = *rp;
+         *rp = *(rp + 1);
+         *(rp + 1) = t;
+      }
+   }
+}
+#endif
+
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
+static png_byte onebppswaptable[256] = {
+   0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
+   0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
+   0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
+   0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
+   0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
+   0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
+   0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
+   0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
+   0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
+   0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
+   0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
+   0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
+   0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
+   0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
+   0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
+   0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
+   0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
+   0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
+   0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
+   0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
+   0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
+   0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
+   0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
+   0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
+   0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
+   0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
+   0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
+   0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
+   0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
+   0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
+   0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
+   0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
+};
+
+static png_byte twobppswaptable[256] = {
+   0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0,
+   0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0,
+   0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4,
+   0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4,
+   0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8,
+   0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8,
+   0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC,
+   0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC,
+   0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1,
+   0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1,
+   0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5,
+   0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5,
+   0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9,
+   0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9,
+   0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD,
+   0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD,
+   0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2,
+   0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2,
+   0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6,
+   0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6,
+   0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA,
+   0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA,
+   0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE,
+   0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE,
+   0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3,
+   0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3,
+   0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7,
+   0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7,
+   0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB,
+   0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB,
+   0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF,
+   0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF
+};
+
+static png_byte fourbppswaptable[256] = {
+   0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
+   0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
+   0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
+   0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
+   0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,
+   0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2,
+   0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73,
+   0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3,
+   0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74,
+   0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4,
+   0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75,
+   0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5,
+   0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76,
+   0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6,
+   0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77,
+   0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7,
+   0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78,
+   0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8,
+   0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79,
+   0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9,
+   0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A,
+   0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA,
+   0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B,
+   0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB,
+   0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C,
+   0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC,
+   0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D,
+   0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD,
+   0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E,
+   0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE,
+   0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F,
+   0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF
+};
+
+/* swaps pixel packing order within bytes */
+void /* PRIVATE */
+png_do_packswap(png_row_infop row_info, png_bytep row)
+{
+   png_debug(1, "in png_do_packswap\n");
+   if (
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+       row != NULL && row_info != NULL &&
+#endif
+       row_info->bit_depth < 8)
+   {
+      png_bytep rp, end, table;
+
+      end = row + row_info->rowbytes;
+
+      if (row_info->bit_depth == 1)
+         table = onebppswaptable;
+      else if (row_info->bit_depth == 2)
+         table = twobppswaptable;
+      else if (row_info->bit_depth == 4)
+         table = fourbppswaptable;
+      else
+         return;
+
+      for (rp = row; rp < end; rp++)
+         *rp = table[*rp];
+   }
+}
+#endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */
+
+#if defined(PNG_WRITE_FILLER_SUPPORTED) || \
+    defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
+/* remove filler or alpha byte(s) */
+void /* PRIVATE */
+png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
+{
+   png_debug(1, "in png_do_strip_filler\n");
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   if (row != NULL && row_info != NULL)
+#endif
+   {
+/*
+      if (row_info->color_type == PNG_COLOR_TYPE_RGB ||
+          row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+*/
+      png_bytep sp=row;
+      png_bytep dp=row;
+      png_uint_32 row_width=row_info->width;
+      png_uint_32 i;
+
+      if (row_info->channels == 4)
+      {
+         if (row_info->bit_depth == 8)
+         {
+            /* This converts from RGBX or RGBA to RGB */
+            if (flags & PNG_FLAG_FILLER_AFTER)
+            {
+               dp+=3; sp+=4;
+               for (i = 1; i < row_width; i++)
+               {
+                  *dp++ = *sp++;
+                  *dp++ = *sp++;
+                  *dp++ = *sp++;
+                  sp++;
+               }
+            }
+            /* This converts from XRGB or ARGB to RGB */
+            else
+            {
+               for (i = 0; i < row_width; i++)
+               {
+                  sp++;
+                  *dp++ = *sp++;
+                  *dp++ = *sp++;
+                  *dp++ = *sp++;
+               }
+            }
+            row_info->pixel_depth = 24;
+            row_info->rowbytes = row_width * 3;
+         }
+         else /* if (row_info->bit_depth == 16) */
+         {
+            if (flags & PNG_FLAG_FILLER_AFTER)
+            {
+               /* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */
+               sp += 8; dp += 6;
+               for (i = 1; i < row_width; i++)
+               {
+                  /* This could be (although png_memcpy is probably slower):
+                  png_memcpy(dp, sp, 6);
+                  sp += 8;
+                  dp += 6;
+                  */
+
+                  *dp++ = *sp++;
+                  *dp++ = *sp++;
+                  *dp++ = *sp++;
+                  *dp++ = *sp++;
+                  *dp++ = *sp++;
+                  *dp++ = *sp++;
+                  sp += 2;
+               }
+            }
+            else
+            {
+               /* This converts from XXRRGGBB or AARRGGBB to RRGGBB */
+               for (i = 0; i < row_width; i++)
+               {
+                  /* This could be (although png_memcpy is probably slower):
+                  png_memcpy(dp, sp, 6);
+                  sp += 8;
+                  dp += 6;
+                  */
+
+                  sp+=2;
+                  *dp++ = *sp++;
+                  *dp++ = *sp++;
+                  *dp++ = *sp++;
+                  *dp++ = *sp++;
+                  *dp++ = *sp++;
+                  *dp++ = *sp++;
+               }
+            }
+            row_info->pixel_depth = 48;
+            row_info->rowbytes = row_width * 6;
+         }
+         row_info->channels = 3;
+         row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
+      }
+/*
+      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY ||
+               row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+*/
+      else if (row_info->channels == 2)
+      {
+         if (row_info->bit_depth == 8)
+         {
+            /* This converts from GX or GA to G */
+            if (flags & PNG_FLAG_FILLER_AFTER)
+            {
+               for (i = 0; i < row_width; i++)
+               {
+                  *dp++ = *sp++;
+                  sp++;
+               }
+            }
+            /* This converts from XG or AG to G */
+            else
+            {
+               for (i = 0; i < row_width; i++)
+               {
+                  sp++;
+                  *dp++ = *sp++;
+               }
+            }
+            row_info->pixel_depth = 8;
+            row_info->rowbytes = row_width;
+         }
+         else /* if (row_info->bit_depth == 16) */
+         {
+            if (flags & PNG_FLAG_FILLER_AFTER)
+            {
+               /* This converts from GGXX or GGAA to GG */
+               sp += 4; dp += 2;
+               for (i = 1; i < row_width; i++)
+               {
+                  *dp++ = *sp++;
+                  *dp++ = *sp++;
+                  sp += 2;
+               }
+            }
+            else
+            {
+               /* This converts from XXGG or AAGG to GG */
+               for (i = 0; i < row_width; i++)
+               {
+                  sp += 2;
+                  *dp++ = *sp++;
+                  *dp++ = *sp++;
+               }
+            }
+            row_info->pixel_depth = 16;
+            row_info->rowbytes = row_width * 2;
+         }
+         row_info->channels = 1;
+         row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
+      }
+   }
+}
+#endif
+
+#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
+/* swaps red and blue bytes within a pixel */
+void /* PRIVATE */
+png_do_bgr(png_row_infop row_info, png_bytep row)
+{
+   png_debug(1, "in png_do_bgr\n");
+   if (
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+       row != NULL && row_info != NULL &&
+#endif
+       (row_info->color_type & PNG_COLOR_MASK_COLOR))
+   {
+      png_uint_32 row_width = row_info->width;
+      if (row_info->bit_depth == 8)
+      {
+         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+         {
+            png_bytep rp;
+            png_uint_32 i;
+
+            for (i = 0, rp = row; i < row_width; i++, rp += 3)
+            {
+               png_byte save = *rp;
+               *rp = *(rp + 2);
+               *(rp + 2) = save;
+            }
+         }
+         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+         {
+            png_bytep rp;
+            png_uint_32 i;
+
+            for (i = 0, rp = row; i < row_width; i++, rp += 4)
+            {
+               png_byte save = *rp;
+               *rp = *(rp + 2);
+               *(rp + 2) = save;
+            }
+         }
+      }
+      else if (row_info->bit_depth == 16)
+      {
+         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+         {
+            png_bytep rp;
+            png_uint_32 i;
+
+            for (i = 0, rp = row; i < row_width; i++, rp += 6)
+            {
+               png_byte save = *rp;
+               *rp = *(rp + 4);
+               *(rp + 4) = save;
+               save = *(rp + 1);
+               *(rp + 1) = *(rp + 5);
+               *(rp + 5) = save;
+            }
+         }
+         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+         {
+            png_bytep rp;
+            png_uint_32 i;
+
+            for (i = 0, rp = row; i < row_width; i++, rp += 8)
+            {
+               png_byte save = *rp;
+               *rp = *(rp + 4);
+               *(rp + 4) = save;
+               save = *(rp + 1);
+               *(rp + 1) = *(rp + 5);
+               *(rp + 5) = save;
+            }
+         }
+      }
+   }
+}
+#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */
+
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
+    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
+    defined(PNG_LEGACY_SUPPORTED)
+void PNGAPI
+png_set_user_transform_info(png_structp png_ptr, png_voidp
+   user_transform_ptr, int user_transform_depth, int user_transform_channels)
+{
+   png_debug(1, "in png_set_user_transform_info\n");
+#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
+   png_ptr->user_transform_ptr = user_transform_ptr;
+   png_ptr->user_transform_depth = (png_byte)user_transform_depth;
+   png_ptr->user_transform_channels = (png_byte)user_transform_channels;
+#else
+   if(user_transform_ptr || user_transform_depth || user_transform_channels)
+      png_warning(png_ptr,
+        "This version of libpng does not support user transform info");
+#endif
+}
+#endif
+
+/* This function returns a pointer to the user_transform_ptr associated with
+ * the user transform functions.  The application should free any memory
+ * associated with this pointer before png_write_destroy and png_read_destroy
+ * are called.
+ */
+png_voidp PNGAPI
+png_get_user_transform_ptr(png_structp png_ptr)
+{
+#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
+   return ((png_voidp)png_ptr->user_transform_ptr);
+#else
+   if(png_ptr)
+     return (NULL);
+   return (NULL);
+#endif
+}
+
diff --git a/Utilities/ITK/Utilities/png/pngvcrd.c b/Utilities/ITK/Utilities/png/pngvcrd.c
new file mode 100644
index 0000000000..f464f34cb8
--- /dev/null
+++ b/Utilities/ITK/Utilities/png/pngvcrd.c
@@ -0,0 +1,3836 @@
+/* pngvcrd.c - mixed C/assembler version of utilities to read a PNG file
+ *
+ * For Intel x86 CPU and Microsoft Visual C++ compiler
+ *
+ * libpng 1.0.12 - June 8, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * Copyright (c) 1998, Intel Corporation
+ *
+ * Contributed by Nirav Chhatrapati, Intel Corporation, 1998
+ * Interface to libpng contributed by Gilles Vollant, 1999
+ * Debugging and cleanup by Greg Roelofs, 2000, 2001
+ *
+ * In png_do_read_interlace() in libpng versions 1.0.3a through 1.0.4d,
+ * a sign error in the post-MMX cleanup code for each pixel_depth resulted
+ * in bad pixels at the beginning of some rows of some images, and also
+ * (due to out-of-range memory reads and writes) caused heap corruption
+ * when compiled with MSVC 6.0.  The error was fixed in version 1.0.4e.
+ *
+ * [png_read_filter_row_mmx_avg() bpp == 2 bugfix, GRR 20000916]
+ *
+ */
+
+#define PNG_INTERNAL
+#include "png.h"
+
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) && defined(PNG_USE_PNGVCRD)
+
+static int mmx_supported=2;
+
+
+int PNGAPI
+png_mmx_support(void)
+{
+  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
+    xor eax, 0x200000 //Toggle ID bit in Eflag [i.e. bit(21)]
+    push eax          //Save modified Eflag back to stack
+
+    popfd             //Restored modified value back to Eflag reg
+    pushfd            //Save Eflag to stack
+    pop eax           //Get Eflag from stack
+    xor eax, ecx      //Compare the new Eflag with the original Eflag
+    jz NOT_SUPPORTED  //If the same, CPUID instruction is not supported,
+                      //skip following instructions and jump to
+                      //NOT_SUPPORTED label
+
+    xor eax, eax      //Set eax to zero
+
+    _asm _emit 0x0f   //CPUID instruction  (two bytes opcode)
+    _asm _emit 0xa2
+
+    cmp eax, 1        //make sure eax return non-zero value
+    jl NOT_SUPPORTED  //If eax is zero, mmx not supported
+
+    xor eax, eax      //set eax to zero
+    inc eax           //Now increment eax to 1.  This instruction is
+                      //faster than the instruction "mov eax, 1"
+
+    _asm _emit 0x0f   //CPUID instruction
+    _asm _emit 0xa2
+
+    and edx, 0x00800000  //mask out all bits but mmx bit(24)
+    cmp edx, 0        // 0 = mmx not supported
+    jz  NOT_SUPPORTED // non-zero = Yes, mmx IS supported
+
+    mov  mmx_supported_local, 1  //set return value to 1
+
+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
+  //printf("MMX : %u (1=MMX supported)\n",mmx_supported_local);
+
+  mmx_supported = mmx_supported_local;
+  return mmx_supported_local;
+}
+
+/* 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 x86 platform - uses faster MMX routine if machine
+   supports MMX */
+
+void /* PRIVATE */
+png_combine_row(png_structp png_ptr, png_bytep row, int mask)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+#endif
+
+   png_debug(1,"in png_combine_row_asm\n");
+
+   if (mmx_supported == 2) {
+       png_mmx_support();
+   }
+
+   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_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_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_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_bytep srcptr;
+            png_bytep dstptr;
+            png_uint_32 len;
+            int m;
+            int diff, unmask;
+
+            __int64 mask0=0x0102040810204080;
+
+            if ( mmx_supported )
+            {
+               srcptr = png_ptr->row_buf + 1;
+               dstptr = row;
+               m = 0x80;
+               unmask = ~mask;
+               len  = png_ptr->width &~7;  //reduce to multiple of 8
+               diff = png_ptr->width & 7;  //amount lost
+
+               _asm
+               {
+                  movd       mm7, unmask   //load bit pattern
+                  psubb      mm6,mm6       //zero mm6
+                  punpcklbw  mm7,mm7
+                  punpcklwd  mm7,mm7
+                  punpckldq  mm7,mm7       //fill register with 8 masks
+
+                  movq       mm0,mask0
+
+                  pand       mm0,mm7       //nonzero if keep byte
+                  pcmpeqb    mm0,mm6       //zeros->1s, v versa
+
+                  mov        ecx,len       //load length of line (pixels)
+                  mov        esi,srcptr    //load source
+                  mov        ebx,dstptr    //load dest
+                  cmp        ecx,0         //lcr
+                  je         mainloop8end
+
+mainloop8:
+                  movq       mm4,[esi]
+                  pand       mm4,mm0
+                  movq       mm6,mm0
+                  pandn      mm6,[ebx]
+                  por        mm4,mm6
+                  movq       [ebx],mm4
+
+                  add        esi,8         //inc by 8 bytes processed
+                  add        ebx,8
+                  sub        ecx,8         //dec by 8 pixels processed
+
+                  ja         mainloop8
+mainloop8end:
+
+                  mov        ecx,diff
+                  cmp        ecx,0
+                  jz         end8
+
+                  mov        edx,mask
+                  sal        edx,24        //make low byte the high byte
+
+secondloop8:
+                  sal        edx,1         //move high bit to CF
+                  jnc        skip8         //if CF = 0
+                  mov        al,[esi]
+                  mov        [ebx],al
+skip8:
+                  inc        esi
+                  inc        ebx
+
+                  dec        ecx
+                  jnz        secondloop8
+end8:
+                  emms
+               }
+            }
+            else /* mmx not supported - use modified C routine */
+            {
+               register unsigned int incr1, initial_val, final_val;
+               png_size_t pixel_bytes;
+               png_uint_32 i;
+               register int disp = png_pass_inc[png_ptr->pass];
+               int offset_table[7] = {0, 4, 0, 2, 0, 1, 0};
+
+               pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
+               srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]*
+                  pixel_bytes;
+               dstptr = row + offset_table[png_ptr->pass]*pixel_bytes;
+               initial_val = offset_table[png_ptr->pass]*pixel_bytes;
+               final_val = png_ptr->width*pixel_bytes;
+               incr1 = (disp)*pixel_bytes;
+               for (i = initial_val; i < final_val; i += incr1)
+               {
+                  if (pixel_bytes > (png_size_t)(final_val-i))
+                    pixel_bytes = (png_size_t)(final_val-i);
+                  png_memcpy(dstptr, srcptr, pixel_bytes);
+                  srcptr += incr1;
+                  dstptr += incr1;
+               }
+            } /* end of else */
+
+            break;
+         }       // end 8 bpp
+
+         case 16:
+         {
+            png_bytep srcptr;
+            png_bytep dstptr;
+            png_uint_32 len;
+            int unmask, diff;
+            __int64 mask1=0x0101020204040808,
+                    mask0=0x1010202040408080;
+
+            if ( mmx_supported )
+            {
+               srcptr = png_ptr->row_buf + 1;
+               dstptr = row;
+
+               unmask = ~mask;
+               len     = (png_ptr->width)&~7;
+               diff = (png_ptr->width)&7;
+               _asm
+               {
+                  movd       mm7, unmask       //load bit pattern
+                  psubb      mm6,mm6           //zero mm6
+                  punpcklbw  mm7,mm7
+                  punpcklwd  mm7,mm7
+                  punpckldq  mm7,mm7           //fill register with 8 masks
+
+                  movq       mm0,mask0
+                  movq       mm1,mask1
+
+                  pand       mm0,mm7
+                  pand       mm1,mm7
+
+                  pcmpeqb    mm0,mm6
+                  pcmpeqb    mm1,mm6
+
+                  mov        ecx,len           //load length of line
+                  mov        esi,srcptr        //load source
+                  mov        ebx,dstptr        //load dest
+                  cmp        ecx,0             //lcr
+                  jz         mainloop16end
+
+mainloop16:
+                  movq       mm4,[esi]
+                  pand       mm4,mm0
+                  movq       mm6,mm0
+                  movq       mm7,[ebx]
+                  pandn      mm6,mm7
+                  por        mm4,mm6
+                  movq       [ebx],mm4
+
+                  movq       mm5,[esi+8]
+                  pand       mm5,mm1
+                  movq       mm7,mm1
+                  movq       mm6,[ebx+8]
+                  pandn      mm7,mm6
+                  por        mm5,mm7
+                  movq       [ebx+8],mm5
+
+                  add        esi,16            //inc by 16 bytes processed
+                  add        ebx,16
+                  sub        ecx,8             //dec by 8 pixels processed
+
+                  ja         mainloop16
+
+mainloop16end:
+                  mov        ecx,diff
+                  cmp        ecx,0
+                  jz         end16
+
+                  mov        edx,mask
+                  sal        edx,24            //make low byte the high byte
+secondloop16:
+                  sal        edx,1             //move high bit to CF
+                  jnc        skip16            //if CF = 0
+                  mov        ax,[esi]
+                  mov        [ebx],ax
+skip16:
+                  add        esi,2
+                  add        ebx,2
+
+                  dec        ecx
+                  jnz        secondloop16
+end16:
+                  emms
+               }
+            }
+            else /* mmx not supported - use modified C routine */
+            {
+               register unsigned int incr1, initial_val, final_val;
+               png_size_t pixel_bytes;
+               png_uint_32 i;
+               register int disp = png_pass_inc[png_ptr->pass];
+               int offset_table[7] = {0, 4, 0, 2, 0, 1, 0};
+
+               pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
+               srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]*
+                  pixel_bytes;
+               dstptr = row + offset_table[png_ptr->pass]*pixel_bytes;
+               initial_val = offset_table[png_ptr->pass]*pixel_bytes;
+               final_val = png_ptr->width*pixel_bytes;
+               incr1 = (disp)*pixel_bytes;
+               for (i = initial_val; i < final_val; i += incr1)
+               {
+                  if (pixel_bytes > (png_size_t)(final_val-i))
+                    pixel_bytes = (png_size_t)(final_val-i);
+                  png_memcpy(dstptr, srcptr, pixel_bytes);
+                  srcptr += incr1;
+                  dstptr += incr1;
+               }
+            } /* end of else */
+
+            break;
+         }       // end 16 bpp
+
+         case 24:
+         {
+            png_bytep srcptr;
+            png_bytep dstptr;
+            png_uint_32 len;
+            int unmask, diff;
+
+            __int64 mask2=0x0101010202020404,  //24bpp
+                    mask1=0x0408080810101020,
+                    mask0=0x2020404040808080;
+
+            srcptr = png_ptr->row_buf + 1;
+            dstptr = row;
+
+            unmask = ~mask;
+            len     = (png_ptr->width)&~7;
+            diff = (png_ptr->width)&7;
+
+            if ( mmx_supported )
+            {
+               _asm
+               {
+                  movd       mm7, unmask       //load bit pattern
+                  psubb      mm6,mm6           //zero mm6
+                  punpcklbw  mm7,mm7
+                  punpcklwd  mm7,mm7
+                  punpckldq  mm7,mm7           //fill register with 8 masks
+
+                  movq       mm0,mask0
+                  movq       mm1,mask1
+                  movq       mm2,mask2
+
+                  pand       mm0,mm7
+                  pand       mm1,mm7
+                  pand       mm2,mm7
+
+                  pcmpeqb    mm0,mm6
+                  pcmpeqb    mm1,mm6
+                  pcmpeqb    mm2,mm6
+
+                  mov        ecx,len           //load length of line
+                  mov        esi,srcptr        //load source
+                  mov        ebx,dstptr        //load dest
+                  cmp        ecx,0
+                  jz         mainloop24end
+
+mainloop24:
+                  movq       mm4,[esi]
+                  pand       mm4,mm0
+                  movq       mm6,mm0
+                  movq       mm7,[ebx]
+                  pandn      mm6,mm7
+                  por        mm4,mm6
+                  movq       [ebx],mm4
+
+
+                  movq       mm5,[esi+8]
+                  pand       mm5,mm1
+                  movq       mm7,mm1
+                  movq       mm6,[ebx+8]
+                  pandn      mm7,mm6
+                  por        mm5,mm7
+                  movq       [ebx+8],mm5
+
+                  movq       mm6,[esi+16]
+                  pand       mm6,mm2
+                  movq       mm4,mm2
+                  movq       mm7,[ebx+16]
+                  pandn      mm4,mm7
+                  por        mm6,mm4
+                  movq       [ebx+16],mm6
+
+                  add        esi,24            //inc by 24 bytes processed
+                  add        ebx,24
+                  sub        ecx,8             //dec by 8 pixels processed
+
+                  ja         mainloop24
+
+mainloop24end:
+                  mov        ecx,diff
+                  cmp        ecx,0
+                  jz         end24
+
+                  mov        edx,mask
+                  sal        edx,24            //make low byte the high byte
+secondloop24:
+                  sal        edx,1             //move high bit to CF
+                  jnc        skip24            //if CF = 0
+                  mov        ax,[esi]
+                  mov        [ebx],ax
+                  xor        eax,eax
+                  mov        al,[esi+2]
+                  mov        [ebx+2],al
+skip24:
+                  add        esi,3
+                  add        ebx,3
+
+                  dec        ecx
+                  jnz        secondloop24
+
+end24:
+                  emms
+               }
+            }
+            else /* mmx not supported - use modified C routine */
+            {
+               register unsigned int incr1, initial_val, final_val;
+               png_size_t pixel_bytes;
+               png_uint_32 i;
+               register int disp = png_pass_inc[png_ptr->pass];
+               int offset_table[7] = {0, 4, 0, 2, 0, 1, 0};
+
+               pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
+               srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]*
+                  pixel_bytes;
+               dstptr = row + offset_table[png_ptr->pass]*pixel_bytes;
+               initial_val = offset_table[png_ptr->pass]*pixel_bytes;
+               final_val = png_ptr->width*pixel_bytes;
+               incr1 = (disp)*pixel_bytes;
+               for (i = initial_val; i < final_val; i += incr1)
+               {
+                  if (pixel_bytes > (png_size_t)(final_val-i))
+                    pixel_bytes = (png_size_t)(final_val-i);
+                  png_memcpy(dstptr, srcptr, pixel_bytes);
+                  srcptr += incr1;
+                  dstptr += incr1;
+               }
+            } /* end of else */
+
+            break;
+         }       // end 24 bpp
+
+         case 32:
+         {
+            png_bytep srcptr;
+            png_bytep dstptr;
+            png_uint_32 len;
+            int unmask, diff;
+
+            __int64 mask3=0x0101010102020202,  //32bpp
+                    mask2=0x0404040408080808,
+                    mask1=0x1010101020202020,
+                    mask0=0x4040404080808080;
+
+            srcptr = png_ptr->row_buf + 1;
+            dstptr = row;
+
+            unmask = ~mask;
+            len     = (png_ptr->width)&~7;
+            diff = (png_ptr->width)&7;
+
+            if ( mmx_supported )
+            {
+               _asm
+               {
+                  movd       mm7, unmask       //load bit pattern
+                  psubb      mm6,mm6           //zero mm6
+                  punpcklbw  mm7,mm7
+                  punpcklwd  mm7,mm7
+                  punpckldq  mm7,mm7           //fill register with 8 masks
+
+                  movq       mm0,mask0
+                  movq       mm1,mask1
+                  movq       mm2,mask2
+                  movq       mm3,mask3
+
+                  pand       mm0,mm7
+                  pand       mm1,mm7
+                  pand       mm2,mm7
+                  pand       mm3,mm7
+
+                  pcmpeqb    mm0,mm6
+                  pcmpeqb    mm1,mm6
+                  pcmpeqb    mm2,mm6
+                  pcmpeqb    mm3,mm6
+
+                  mov        ecx,len           //load length of line
+                  mov        esi,srcptr        //load source
+                  mov        ebx,dstptr        //load dest
+
+                  cmp        ecx,0             //lcr
+                  jz         mainloop32end
+
+mainloop32:
+                  movq       mm4,[esi]
+                  pand       mm4,mm0
+                  movq       mm6,mm0
+                  movq       mm7,[ebx]
+                  pandn      mm6,mm7
+                  por        mm4,mm6
+                  movq       [ebx],mm4
+
+                  movq       mm5,[esi+8]
+                  pand       mm5,mm1
+                  movq       mm7,mm1
+                  movq       mm6,[ebx+8]
+                  pandn      mm7,mm6
+                  por        mm5,mm7
+                  movq       [ebx+8],mm5
+
+                  movq       mm6,[esi+16]
+                  pand       mm6,mm2
+                  movq       mm4,mm2
+                  movq       mm7,[ebx+16]
+                  pandn      mm4,mm7
+                  por        mm6,mm4
+                  movq       [ebx+16],mm6
+
+                  movq       mm7,[esi+24]
+                  pand       mm7,mm3
+                  movq       mm5,mm3
+                  movq       mm4,[ebx+24]
+                  pandn      mm5,mm4
+                  por        mm7,mm5
+                  movq       [ebx+24],mm7
+
+                  add        esi,32            //inc by 32 bytes processed
+                  add        ebx,32
+                  sub        ecx,8             //dec by 8 pixels processed
+
+                  ja         mainloop32
+
+mainloop32end:
+                  mov        ecx,diff
+                  cmp        ecx,0
+                  jz         end32
+
+                  mov        edx,mask
+                  sal        edx,24            //make low byte the high byte
+secondloop32:
+                  sal        edx,1             //move high bit to CF
+                  jnc        skip32            //if CF = 0
+                  mov        eax,[esi]
+                  mov        [ebx],eax
+skip32:
+                  add        esi,4
+                  add        ebx,4
+
+                  dec        ecx
+                  jnz        secondloop32
+
+end32:
+                  emms
+               }
+            }
+            else /* mmx _not supported - Use modified C routine */
+            {
+               register unsigned int incr1, initial_val, final_val;
+               png_size_t pixel_bytes;
+               png_uint_32 i;
+               register int disp = png_pass_inc[png_ptr->pass];
+               int offset_table[7] = {0, 4, 0, 2, 0, 1, 0};
+
+               pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
+               srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]*
+                  pixel_bytes;
+               dstptr = row + offset_table[png_ptr->pass]*pixel_bytes;
+               initial_val = offset_table[png_ptr->pass]*pixel_bytes;
+               final_val = png_ptr->width*pixel_bytes;
+               incr1 = (disp)*pixel_bytes;
+               for (i = initial_val; i < final_val; i += incr1)
+               {
+                  if (pixel_bytes > (png_size_t)(final_val-i))
+                    pixel_bytes = (png_size_t)(final_val-i);
+                  png_memcpy(dstptr, srcptr, pixel_bytes);
+                  srcptr += incr1;
+                  dstptr += incr1;
+               }
+            } /* end of else */
+
+            break;
+         }       // end 32 bpp
+
+         case 48:
+         {
+            png_bytep srcptr;
+            png_bytep dstptr;
+            png_uint_32 len;
+            int unmask, diff;
+
+            __int64 mask5=0x0101010101010202,
+                    mask4=0x0202020204040404,
+                    mask3=0x0404080808080808,
+                    mask2=0x1010101010102020,
+                    mask1=0x2020202040404040,
+                    mask0=0x4040808080808080;
+
+            if ( mmx_supported )
+            {
+               srcptr = png_ptr->row_buf + 1;
+               dstptr = row;
+
+               unmask = ~mask;
+               len     = (png_ptr->width)&~7;
+               diff = (png_ptr->width)&7;
+               _asm
+               {
+                  movd       mm7, unmask       //load bit pattern
+                  psubb      mm6,mm6           //zero mm6
+                  punpcklbw  mm7,mm7
+                  punpcklwd  mm7,mm7
+                  punpckldq  mm7,mm7           //fill register with 8 masks
+
+                  movq       mm0,mask0
+                  movq       mm1,mask1
+                  movq       mm2,mask2
+                  movq       mm3,mask3
+                  movq       mm4,mask4
+                  movq       mm5,mask5
+
+                  pand       mm0,mm7
+                  pand       mm1,mm7
+                  pand       mm2,mm7
+                  pand       mm3,mm7
+                  pand       mm4,mm7
+                  pand       mm5,mm7
+
+                  pcmpeqb    mm0,mm6
+                  pcmpeqb    mm1,mm6
+                  pcmpeqb    mm2,mm6
+                  pcmpeqb    mm3,mm6
+                  pcmpeqb    mm4,mm6
+                  pcmpeqb    mm5,mm6
+
+                  mov        ecx,len           //load length of line
+                  mov        esi,srcptr        //load source
+                  mov        ebx,dstptr        //load dest
+
+                  cmp        ecx,0
+                  jz         mainloop48end
+
+mainloop48:
+                  movq       mm7,[esi]
+                  pand       mm7,mm0
+                  movq       mm6,mm0
+                  pandn      mm6,[ebx]
+                  por        mm7,mm6
+                  movq       [ebx],mm7
+
+                  movq       mm6,[esi+8]
+                  pand       mm6,mm1
+                  movq       mm7,mm1
+                  pandn      mm7,[ebx+8]
+                  por        mm6,mm7
+                  movq       [ebx+8],mm6
+
+                  movq       mm6,[esi+16]
+                  pand       mm6,mm2
+                  movq       mm7,mm2
+                  pandn      mm7,[ebx+16]
+                  por        mm6,mm7
+                  movq       [ebx+16],mm6
+
+                  movq       mm7,[esi+24]
+                  pand       mm7,mm3
+                  movq       mm6,mm3
+                  pandn      mm6,[ebx+24]
+                  por        mm7,mm6
+                  movq       [ebx+24],mm7
+
+                  movq       mm6,[esi+32]
+                  pand       mm6,mm4
+                  movq       mm7,mm4
+                  pandn      mm7,[ebx+32]
+                  por        mm6,mm7
+                  movq       [ebx+32],mm6
+
+                  movq       mm7,[esi+40]
+                  pand       mm7,mm5
+                  movq       mm6,mm5
+                  pandn      mm6,[ebx+40]
+                  por        mm7,mm6
+                  movq       [ebx+40],mm7
+
+                  add        esi,48            //inc by 32 bytes processed
+                  add        ebx,48
+                  sub        ecx,8             //dec by 8 pixels processed
+
+                  ja         mainloop48
+mainloop48end:
+
+                  mov        ecx,diff
+                  cmp        ecx,0
+                  jz         end48
+
+                  mov        edx,mask
+                  sal        edx,24            //make low byte the high byte
+
+secondloop48:
+                  sal        edx,1             //move high bit to CF
+                  jnc        skip48            //if CF = 0
+                  mov        eax,[esi]
+                  mov        [ebx],eax
+skip48:
+                  add        esi,4
+                  add        ebx,4
+
+                  dec        ecx
+                  jnz        secondloop48
+
+end48:
+                  emms
+               }
+            }
+            else /* mmx _not supported - Use modified C routine */
+            {
+               register unsigned int incr1, initial_val, final_val;
+               png_size_t pixel_bytes;
+               png_uint_32 i;
+               register int disp = png_pass_inc[png_ptr->pass];
+               int offset_table[7] = {0, 4, 0, 2, 0, 1, 0};
+
+               pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
+               srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]*
+                  pixel_bytes;
+               dstptr = row + offset_table[png_ptr->pass]*pixel_bytes;
+               initial_val = offset_table[png_ptr->pass]*pixel_bytes;
+               final_val = png_ptr->width*pixel_bytes;
+               incr1 = (disp)*pixel_bytes;
+               for (i = initial_val; i < final_val; i += incr1)
+               {
+                  if (pixel_bytes > (png_size_t)(final_val-i))
+                    pixel_bytes = (png_size_t)(final_val-i);
+                  png_memcpy(dstptr, srcptr, pixel_bytes);
+                  srcptr += incr1;
+                  dstptr += incr1;
+               }
+            } /* end of else */
+
+            break;
+         }       // end 48 bpp
+
+         default:
+         {
+            png_bytep sptr;
+            png_bytep dp;
+            png_size_t pixel_bytes;
+            int offset_table[7] = {0, 4, 0, 2, 0, 1, 0};
+            unsigned int i;
+            register int disp = png_pass_inc[png_ptr->pass];  // get the offset
+            register unsigned int incr1, initial_val, final_val;
+
+            pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
+            sptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]*
+               pixel_bytes;
+            dp = row + offset_table[png_ptr->pass]*pixel_bytes;
+            initial_val = offset_table[png_ptr->pass]*pixel_bytes;
+            final_val = png_ptr->width*pixel_bytes;
+            incr1 = (disp)*pixel_bytes;
+            for (i = initial_val; i < final_val; i += incr1)
+            {
+               if (pixel_bytes > (png_size_t)(final_val-i))
+                 pixel_bytes = (png_size_t)(final_val-i);
+               png_memcpy(dp, sptr, pixel_bytes);
+               sptr += incr1;
+               dp += incr1;
+            }
+            break;
+         }
+      } /* end switch (png_ptr->row_info.pixel_depth) */
+   } /* end if (non-trivial mask) */
+
+} /* end png_combine_row() */
+
+
+#if defined(PNG_READ_INTERLACING_SUPPORTED)
+
+void /* PRIVATE */
+png_do_read_interlace(png_structp png_ptr)
+{
+   png_row_infop row_info = &(png_ptr->row_info);
+   png_bytep row = png_ptr->row_buf + 1;
+   int pass = png_ptr->pass;
+   png_uint_32 transformations = png_ptr->transformations;
+#ifdef PNG_USE_LOCAL_ARRAYS
+   const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+#endif
+
+   png_debug(1,"in png_do_read_interlace\n");
+
+   if (mmx_supported == 2) {
+       png_mmx_support();
+   }
+
+   if (row != NULL && row_info != NULL)
+   {
+      png_uint_32 final_width;
+
+      final_width = row_info->width * png_pass_inc[pass];
+
+      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:         // This is the place where the routine is modified
+         {
+            __int64 const4 = 0x0000000000FFFFFF;
+            // __int64 const5 = 0x000000FFFFFF0000;  // unused...
+            __int64 const6 = 0x00000000000000FF;
+            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);
+
+            sptr = row + (width - 1) * pixel_bytes;
+            dp = row + (final_width - 1) * pixel_bytes;
+            // New code by Nirav Chhatrapati - Intel Corporation
+            // sign fix by GRR
+            // NOTE:  there is NO MMX code for 48-bit and 64-bit images
+
+            // use MMX routine if machine supports it
+            if ( mmx_supported )
+            {
+               if (pixel_bytes == 3)
+               {
+                  if (((pass == 0) || (pass == 1)) && width)
+                  {
+                     _asm
+                     {
+                        mov esi, sptr
+                        mov edi, dp
+                        mov ecx, width
+                        sub edi, 21   // (png_pass_inc[pass] - 1)*pixel_bytes
+loop_pass0:
+                        movd mm0, [esi]     ; X X X X X v2 v1 v0
+                        pand mm0, const4    ; 0 0 0 0 0 v2 v1 v0
+                        movq mm1, mm0       ; 0 0 0 0 0 v2 v1 v0
+                        psllq mm0, 16       ; 0 0 0 v2 v1 v0 0 0
+                        movq mm2, mm0       ; 0 0 0 v2 v1 v0 0 0
+                        psllq mm0, 24       ; v2 v1 v0 0 0 0 0 0
+                        psrlq mm1, 8        ; 0 0 0 0 0 0 v2 v1
+                        por mm0, mm2        ; v2 v1 v0 v2 v1 v0 0 0
+                        por mm0, mm1        ; v2 v1 v0 v2 v1 v0 v2 v1
+                        movq mm3, mm0       ; v2 v1 v0 v2 v1 v0 v2 v1
+                        psllq mm0, 16       ; v0 v2 v1 v0 v2 v1 0 0
+                        movq mm4, mm3       ; v2 v1 v0 v2 v1 v0 v2 v1
+                        punpckhdq mm3, mm0  ; v0 v2 v1 v0 v2 v1 v0 v2
+                        movq [edi+16] , mm4
+                        psrlq mm0, 32       ; 0 0 0 0 v0 v2 v1 v0
+                        movq [edi+8] , mm3
+                        punpckldq mm0, mm4  ; v1 v0 v2 v1 v0 v2 v1 v0
+                        sub esi, 3
+                        movq [edi], mm0
+                        sub edi, 24
+                        //sub esi, 3
+                        dec ecx
+                        jnz loop_pass0
+                        EMMS
+                     }
+                  }
+                  else if (((pass == 2) || (pass == 3)) && width)
+                  {
+                     _asm
+                     {
+                        mov esi, sptr
+                        mov edi, dp
+                        mov ecx, width
+                        sub edi, 9   // (png_pass_inc[pass] - 1)*pixel_bytes
+loop_pass2:
+                        movd mm0, [esi]     ; X X X X X v2 v1 v0
+                        pand mm0, const4    ; 0 0 0 0 0 v2 v1 v0
+                        movq mm1, mm0       ; 0 0 0 0 0 v2 v1 v0
+                        psllq mm0, 16       ; 0 0 0 v2 v1 v0 0 0
+                        movq mm2, mm0       ; 0 0 0 v2 v1 v0 0 0
+                        psllq mm0, 24       ; v2 v1 v0 0 0 0 0 0
+                        psrlq mm1, 8        ; 0 0 0 0 0 0 v2 v1
+                        por mm0, mm2        ; v2 v1 v0 v2 v1 v0 0 0
+                        por mm0, mm1        ; v2 v1 v0 v2 v1 v0 v2 v1
+                        movq [edi+4], mm0   ; move to memory
+                        psrlq mm0, 16       ; 0 0 v2 v1 v0 v2 v1 v0
+                        movd [edi], mm0     ; move to memory
+                        sub esi, 3
+                        sub edi, 12
+                        dec ecx
+                        jnz loop_pass2
+                        EMMS
+                     }
+                  }
+                  else if (width) /* && ((pass == 4) || (pass == 5)) */
+                  {
+                     int width_mmx = ((width >> 1) << 1) - 8;
+                     if (width_mmx < 0)
+                         width_mmx = 0;
+                     width -= width_mmx;        // 8 or 9 pix, 24 or 27 bytes
+                     if (width_mmx)
+                     {
+                        _asm
+                        {
+                           mov esi, sptr
+                           mov edi, dp
+                           mov ecx, width_mmx
+                           sub esi, 3
+                           sub edi, 9
+loop_pass4:
+                           movq mm0, [esi]     ; X X v2 v1 v0 v5 v4 v3
+                           movq mm7, mm0       ; X X v2 v1 v0 v5 v4 v3
+                           movq mm6, mm0       ; X X v2 v1 v0 v5 v4 v3
+                           psllq mm0, 24       ; v1 v0 v5 v4 v3 0 0 0
+                           pand mm7, const4    ; 0 0 0 0 0 v5 v4 v3
+                           psrlq mm6, 24       ; 0 0 0 X X v2 v1 v0
+                           por mm0, mm7        ; v1 v0 v5 v4 v3 v5 v4 v3
+                           movq mm5, mm6       ; 0 0 0 X X v2 v1 v0
+                           psllq mm6, 8        ; 0 0 X X v2 v1 v0 0
+                           movq [edi], mm0     ; move quad to memory
+                           psrlq mm5, 16       ; 0 0 0 0 0 X X v2
+                           pand mm5, const6    ; 0 0 0 0 0 0 0 v2
+                           por mm6, mm5        ; 0 0 X X v2 v1 v0 v2
+                           movd [edi+8], mm6   ; move double to memory
+                           sub esi, 6
+                           sub edi, 12
+                           sub ecx, 2
+                           jnz loop_pass4
+                           EMMS
+                        }
+                     }
+
+                     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;
+                     if (width_mmx)
+                     {
+                        _asm
+                        {
+                           mov esi, sptr
+                           mov edi, dp
+                           mov ecx, width_mmx
+                           sub edi, 31
+                           sub esi, 3
+loop1_pass0:
+                           movd mm0, [esi]     ; X X X X v0 v1 v2 v3
+                           movq mm1, mm0       ; X X X X v0 v1 v2 v3
+                           punpcklbw mm0, mm0  ; v0 v0 v1 v1 v2 v2 v3 v3
+                           movq mm2, mm0       ; v0 v0 v1 v1 v2 v2 v3 v3
+                           punpcklwd mm0, mm0  ; v2 v2 v2 v2 v3 v3 v3 v3
+                           movq mm3, mm0       ; v2 v2 v2 v2 v3 v3 v3 v3
+                           punpckldq mm0, mm0  ; v3 v3 v3 v3 v3 v3 v3 v3
+                           punpckhdq mm3, mm3  ; v2 v2 v2 v2 v2 v2 v2 v2
+                           movq [edi], mm0     ; move to memory v3
+                           punpckhwd mm2, mm2  ; v0 v0 v0 v0 v1 v1 v1 v1
+                           movq [edi+8], mm3   ; move to memory v2
+                           movq mm4, mm2       ; v0 v0 v0 v0 v1 v1 v1 v1
+                           punpckldq mm2, mm2  ; v1 v1 v1 v1 v1 v1 v1 v1
+                           punpckhdq mm4, mm4  ; v0 v0 v0 v0 v0 v0 v0 v0
+                           movq [edi+16], mm2  ; move to memory v1
+                           movq [edi+24], mm4  ; move to memory v0
+                           sub esi, 4
+                           sub edi, 32
+                           sub ecx, 4
+                           jnz loop1_pass0
+                           EMMS
+                        }
+                     }
+
+                     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;
+                     if (width_mmx)
+                     {
+                        _asm
+                        {
+                           mov esi, sptr
+                           mov edi, dp
+                           mov ecx, width_mmx
+                           sub edi, 15
+                           sub esi, 3
+loop1_pass2:
+                           movd mm0, [esi]     ; X X X X v0 v1 v2 v3
+                           punpcklbw mm0, mm0  ; v0 v0 v1 v1 v2 v2 v3 v3
+                           movq mm1, mm0       ; v0 v0 v1 v1 v2 v2 v3 v3
+                           punpcklwd mm0, mm0  ; v2 v2 v2 v2 v3 v3 v3 v3
+                           punpckhwd mm1, mm1  ; v0 v0 v0 v0 v1 v1 v1 v1
+                           movq [edi], mm0     ; move to memory v2 and v3
+                           sub esi, 4
+                           movq [edi+8], mm1   ; move to memory v1     and v0
+                           sub edi, 16
+                           sub ecx, 4
+                           jnz loop1_pass2
+                           EMMS
+                        }
+                     }
+
+                     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;
+                     if (width_mmx)
+                     {
+                        _asm
+                        {
+                           mov esi, sptr
+                           mov edi, dp
+                           mov ecx, width_mmx
+                           sub edi, 15
+                           sub esi, 7
+loop1_pass4:
+                           movq mm0, [esi]     ; v0 v1 v2 v3 v4 v5 v6 v7
+                           movq mm1, mm0       ; v0 v1 v2 v3 v4 v5 v6 v7
+                           punpcklbw mm0, mm0  ; v4 v4 v5 v5 v6 v6 v7 v7
+                           //movq mm1, mm0     ; v0 v0 v1 v1 v2 v2 v3 v3
+                           punpckhbw mm1, mm1  ;v0 v0 v1 v1 v2 v2 v3 v3
+                           movq [edi+8], mm1   ; move to memory v0 v1 v2 and v3
+                           sub esi, 8
+                           movq [edi], mm0     ; move to memory v4 v5 v6 and v7
+                           //sub esi, 4
+                           sub edi, 16
+                           sub ecx, 8
+                           jnz loop1_pass4
+                           EMMS
+                        }
+                     }
+
+                     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;
+                     if (width_mmx)
+                     {
+                        _asm
+                        {
+                           mov esi, sptr
+                           mov edi, dp
+                           mov ecx, width_mmx
+                           sub esi, 2
+                           sub edi, 30
+loop2_pass0:
+                           movd mm0, [esi]        ; X X X X v1 v0 v3 v2
+                           punpcklwd mm0, mm0     ; v1 v0 v1 v0 v3 v2 v3 v2
+                           movq mm1, mm0          ; v1 v0 v1 v0 v3 v2 v3 v2
+                           punpckldq mm0, mm0     ; v3 v2 v3 v2 v3 v2 v3 v2
+                           punpckhdq mm1, mm1     ; v1 v0 v1 v0 v1 v0 v1 v0
+                           movq [edi], mm0
+                           movq [edi + 8], mm0
+                           movq [edi + 16], mm1
+                           movq [edi + 24], mm1
+                           sub esi, 4
+                           sub edi, 32
+                           sub ecx, 2
+                           jnz loop2_pass0
+                           EMMS
+                        }
+                     }
+
+                     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;
+                     if (width_mmx)
+                     {
+                        _asm
+                        {
+                           mov esi, sptr
+                           mov edi, dp
+                           mov ecx, width_mmx
+                           sub esi, 2
+                           sub edi, 14
+loop2_pass2:
+                           movd mm0, [esi]        ; X X X X v1 v0 v3 v2
+                           punpcklwd mm0, mm0     ; v1 v0 v1 v0 v3 v2 v3 v2
+                           movq mm1, mm0          ; v1 v0 v1 v0 v3 v2 v3 v2
+                           punpckldq mm0, mm0     ; v3 v2 v3 v2 v3 v2 v3 v2
+                           punpckhdq mm1, mm1     ; v1 v0 v1 v0 v1 v0 v1 v0
+                           movq [edi], mm0
+                           sub esi, 4
+                           movq [edi + 8], mm1
+                           //sub esi, 4
+                           sub edi, 16
+                           sub ecx, 2
+                           jnz loop2_pass2
+                           EMMS
+                        }
+                     }
+
+                     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;
+                     if (width_mmx)
+                     {
+                        _asm
+                        {
+                           mov esi, sptr
+                           mov edi, dp
+                           mov ecx, width_mmx
+                           sub esi, 2
+                           sub edi, 6
+loop2_pass4:
+                           movd mm0, [esi]        ; X X X X v1 v0 v3 v2
+                           punpcklwd mm0, mm0     ; v1 v0 v1 v0 v3 v2 v3 v2
+                           sub esi, 4
+                           movq [edi], mm0
+                           sub edi, 8
+                           sub ecx, 2
+                           jnz loop2_pass4
+                           EMMS
+                        }
+                     }
+
+                     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;
+                     if (width_mmx)
+                     {
+                        _asm
+                        {
+                           mov esi, sptr
+                           mov edi, dp
+                           mov ecx, width_mmx
+                           sub esi, 4
+                           sub edi, 60
+loop4_pass0:
+                           movq mm0, [esi]        ; v3 v2 v1 v0 v7 v6 v5 v4
+                           movq mm1, mm0          ; v3 v2 v1 v0 v7 v6 v5 v4
+                           punpckldq mm0, mm0     ; v7 v6 v5 v4 v7 v6 v5 v4
+                           punpckhdq mm1, mm1     ; v3 v2 v1 v0 v3 v2 v1 v0
+                           movq [edi], mm0
+                           movq [edi + 8], mm0
+                           movq [edi + 16], mm0
+                           movq [edi + 24], mm0
+                           movq [edi+32], mm1
+                           movq [edi + 40], mm1
+                           movq [edi+ 48], mm1
+                           sub esi, 8
+                           movq [edi + 56], mm1
+                           sub edi, 64
+                           sub ecx, 2
+                           jnz loop4_pass0
+                           EMMS
+                        }
+                     }
+
+                     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;
+                     if (width_mmx)
+                     {
+                        _asm
+                        {
+                           mov esi, sptr
+                           mov edi, dp
+                           mov ecx, width_mmx
+                           sub esi, 4
+                           sub edi, 28
+loop4_pass2:
+                           movq mm0, [esi]      ; v3 v2 v1 v0 v7 v6 v5 v4
+                           movq mm1, mm0        ; v3 v2 v1 v0 v7 v6 v5 v4
+                           punpckldq mm0, mm0   ; v7 v6 v5 v4 v7 v6 v5 v4
+                           punpckhdq mm1, mm1   ; v3 v2 v1 v0 v3 v2 v1 v0
+                           movq [edi], mm0
+                           movq [edi + 8], mm0
+                           movq [edi+16], mm1
+                           movq [edi + 24], mm1
+                           sub esi, 8
+                           sub edi, 32
+                           sub ecx, 2
+                           jnz loop4_pass2
+                           EMMS
+                        }
+                     }
+
+                     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;
+                     if (width_mmx)
+                     {
+                        _asm
+                        {
+                           mov esi, sptr
+                           mov edi, dp
+                           mov ecx, width_mmx
+                           sub esi, 4
+                           sub edi, 12
+loop4_pass4:
+                           movq mm0, [esi]      ; v3 v2 v1 v0 v7 v6 v5 v4
+                           movq mm1, mm0        ; v3 v2 v1 v0 v7 v6 v5 v4
+                           punpckldq mm0, mm0   ; v7 v6 v5 v4 v7 v6 v5 v4
+                           punpckhdq mm1, mm1   ; v3 v2 v1 v0 v3 v2 v1 v0
+                           movq [edi], mm0
+                           sub esi, 8
+                           movq [edi + 8], mm1
+                           sub edi, 16
+                           sub ecx, 2
+                           jnz loop4_pass4
+                           EMMS
+                        }
+                     }
+
+                     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 */
+
+               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 png_memcpy for a constant */
+            {
+               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, pixel_bytes);
+                     for (j = 0; j < png_pass_inc[pass]; j++)
+                     {
+                        png_memcpy(dp, v, pixel_bytes);
+                        dp -= pixel_bytes;
+                     }
+                     sptr -= pixel_bytes;
+                  }
+               }
+               else if (pixel_bytes == 2)
+               {
+                  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;
+                  }
+               }
+               else if (pixel_bytes == 4)
+               {
+                  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;
+                  }
+               }
+               else if (pixel_bytes == 6)
+               {
+                  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;
+                  }
+               }
+               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 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);
+   }
+
+}
+
+#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 {
+   __int64 use;
+   double  align;
+} LBCarryMask = {0x0101010101010101},
+  HBClearMask = {0x7f7f7f7f7f7f7f7f},
+  ActiveMask, ActiveMask2, ActiveMaskEnd, ShiftBpp, ShiftRem;
+
+
+// Optimized code for PNG Average filter decoder
+void /* PRIVATE */
+png_read_filter_row_mmx_avg(png_row_infop row_info, png_bytep row
+                            , png_bytep prev_row)
+{
+   int bpp;
+   png_uint_32 FullLength;
+   png_uint_32 MMXLength;
+   //png_uint_32 len;
+   int diff;
+
+   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
+         mov edi, row          // edi ==> Avg(x)
+         xor ebx, ebx          // ebx ==> x
+         mov edx, edi
+         mov esi, prev_row           // esi ==> Prior(x)
+         sub edx, bpp          // edx ==> Raw(x-bpp)
+
+         xor eax, eax
+         // Compute the Raw value for the first bpp bytes
+         //    Raw(x) = Avg(x) + (Prior(x)/2)
+davgrlp:
+         mov al, [esi + ebx]   // Load al with Prior(x)
+         inc ebx
+         shr al, 1             // divide by 2
+         add al, [edi+ebx-1]   // Add Avg(x); -1 to offset inc ebx
+         cmp ebx, bpp
+         mov [edi+ebx-1], al    // Write back Raw(x);
+                            // mov does not affect flags; -1 to offset inc ebx
+         jb davgrlp
+         // get # of bytes to alignment
+         mov diff, edi         // take start of row
+         add diff, ebx         // add bpp
+         add diff, 0xf         // add 7 + 8 to incr past alignment boundary
+         and diff, 0xfffffff8  // mask to alignment boundary
+         sub diff, edi         // subtract from start ==> value ebx at alignment
+         jz davggo
+         // fix alignment
+         // Compute the Raw value for the bytes upto the alignment boundary
+         //    Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2)
+         xor ecx, ecx
+davglp1:
+         xor eax, eax
+         mov cl, [esi + ebx]        // load cl with Prior(x)
+         mov al, [edx + ebx]  // load al with Raw(x-bpp)
+         add ax, cx
+         inc ebx
+         shr ax, 1            // divide by 2
+         add al, [edi+ebx-1]  // Add Avg(x); -1 to offset inc ebx
+         cmp ebx, diff              // Check if at alignment boundary
+         mov [edi+ebx-1], al        // Write back Raw(x);
+                            // mov does not affect flags; -1 to offset inc ebx
+         jb davglp1               // Repeat until at alignment boundary
+davggo:
+         mov eax, FullLength
+         mov ecx, eax
+         sub eax, ebx          // subtract alignment fix
+         and eax, 0x00000007   // calc bytes over mult of 8
+         sub ecx, eax          // drop over bytes from original length
+         mov MMXLength, ecx
+   } // end _asm block
+   // 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 mm7, ActiveMask
+            mov ebx, diff      // ebx ==> x = offset to alignment boundary
+            movq mm5, LBCarryMask
+            mov edi, row       // edi ==> Avg(x)
+            movq mm4, HBClearMask
+            mov esi, prev_row        // esi ==> Prior(x)
+            // PRIME the pump (load the first Raw(x-bpp) data set
+            movq mm2, [edi + ebx - 8]  // Load previous aligned 8 bytes
+                               // (we correct position in loop below)
+davg3lp:
+            movq mm0, [edi + ebx]      // Load mm0 with Avg(x)
+            // Add (Prev_row/2) to Average
+            movq mm3, mm5
+            psrlq mm2, ShiftRem      // Correct position Raw(x-bpp) data
+            movq mm1, [esi + ebx]    // Load mm1 with Prior(x)
+            movq mm6, mm7
+            pand mm3, mm1      // get lsb for each prev_row byte
+            psrlq mm1, 1       // divide prev_row bytes by 2
+            pand  mm1, mm4     // clear invalid bit 7 of each byte
+            paddb mm0, mm1     // add (Prev_row/2) to Avg for each byte
+            // Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry
+            movq mm1, mm3      // now use mm1 for getting LBCarrys
+            pand mm1, mm2      // get LBCarrys for each byte where both
+                               // lsb's were == 1 (Only valid for active group)
+            psrlq mm2, 1       // divide raw bytes by 2
+            pand  mm2, mm4     // clear invalid bit 7 of each byte
+            paddb mm2, mm1     // add LBCarrys to (Raw(x-bpp)/2) for each byte
+            pand mm2, mm6      // Leave only Active Group 1 bytes to add to Avg
+            paddb mm0, mm2     // add (Raw/2) + LBCarrys to Avg for each Active
+                               //  byte
+            // Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry
+            psllq mm6, ShiftBpp  // shift the mm6 mask to cover bytes 3-5
+            movq mm2, mm0        // mov updated Raws to mm2
+            psllq mm2, ShiftBpp  // shift data to position correctly
+            movq mm1, mm3        // now use mm1 for getting LBCarrys
+            pand mm1, mm2      // get LBCarrys for each byte where both
+                               // lsb's were == 1 (Only valid for active group)
+            psrlq mm2, 1       // divide raw bytes by 2
+            pand  mm2, mm4     // clear invalid bit 7 of each byte
+            paddb mm2, mm1     // add LBCarrys to (Raw(x-bpp)/2) for each byte
+            pand mm2, mm6      // Leave only Active Group 2 bytes to add to Avg
+            paddb mm0, mm2     // add (Raw/2) + LBCarrys to Avg for each Active
+                               //  byte
+
+            // Add 3rd active group (Raw(x-bpp)/2) to Average with LBCarry
+            psllq mm6, ShiftBpp  // shift the mm6 mask to cover the last two
+                                 // bytes
+            movq mm2, mm0        // mov updated Raws to mm2
+            psllq mm2, ShiftBpp  // shift data to position correctly
+                              // Data only needs to be shifted once here to
+                              // get the correct x-bpp offset.
+            movq mm1, mm3     // now use mm1 for getting LBCarrys
+            pand mm1, mm2     // get LBCarrys for each byte where both
+                              // lsb's were == 1 (Only valid for active group)
+            psrlq mm2, 1      // divide raw bytes by 2
+            pand  mm2, mm4    // clear invalid bit 7 of each byte
+            paddb mm2, mm1    // add LBCarrys to (Raw(x-bpp)/2) for each byte
+            pand mm2, mm6     // Leave only Active Group 2 bytes to add to Avg
+            add ebx, 8
+            paddb mm0, mm2    // add (Raw/2) + LBCarrys to Avg for each Active
+                              // byte
+
+            // Now ready to write back to memory
+            movq [edi + ebx - 8], mm0
+            // Move updated Raw(x) to use as Raw(x-bpp) for next loop
+            cmp ebx, MMXLength
+            movq mm2, mm0     // mov updated Raw(x) to mm2
+            jb davg3lp
+         } // end _asm block
+      }
+      break;
+
+      case 6:
+      case 4:
+      case 7:
+      case 5:
+      {
+         ActiveMask.use  = 0xffffffffffffffff;  // use shift below to clear
+                                                // appropriate inactive bytes
+         ShiftBpp.use = bpp << 3;
+         ShiftRem.use = 64 - ShiftBpp.use;
+         _asm {
+            movq mm4, HBClearMask
+            // Re-init address pointers and offset
+            mov ebx, diff       // ebx ==> x = offset to alignment boundary
+            // Load ActiveMask and clear all bytes except for 1st active group
+            movq mm7, ActiveMask
+            mov edi, row         // edi ==> Avg(x)
+            psrlq mm7, ShiftRem
+            mov esi, prev_row    // esi ==> Prior(x)
+            movq mm6, mm7
+            movq mm5, LBCarryMask
+            psllq mm6, ShiftBpp  // Create mask for 2nd active group
+            // PRIME the pump (load the first Raw(x-bpp) data set
+            movq mm2, [edi + ebx - 8]  // Load previous aligned 8 bytes
+                                 // (we correct position in loop below)
+davg4lp:
+            movq mm0, [edi + ebx]
+            psrlq mm2, ShiftRem  // shift data to position correctly
+            movq mm1, [esi + ebx]
+            // Add (Prev_row/2) to Average
+            movq mm3, mm5
+            pand mm3, mm1     // get lsb for each prev_row byte
+            psrlq mm1, 1      // divide prev_row bytes by 2
+            pand  mm1, mm4    // clear invalid bit 7 of each byte
+            paddb mm0, mm1    // add (Prev_row/2) to Avg for each byte
+            // Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry
+            movq mm1, mm3     // now use mm1 for getting LBCarrys
+            pand mm1, mm2     // get LBCarrys for each byte where both
+                              // lsb's were == 1 (Only valid for active group)
+            psrlq mm2, 1      // divide raw bytes by 2
+            pand  mm2, mm4    // clear invalid bit 7 of each byte
+            paddb mm2, mm1    // add LBCarrys to (Raw(x-bpp)/2) for each byte
+            pand mm2, mm7     // Leave only Active Group 1 bytes to add to Avg
+            paddb mm0, mm2    // add (Raw/2) + LBCarrys to Avg for each Active
+                              // byte
+            // Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry
+            movq mm2, mm0     // mov updated Raws to mm2
+            psllq mm2, ShiftBpp // shift data to position correctly
+            add ebx, 8
+            movq mm1, mm3     // now use mm1 for getting LBCarrys
+            pand mm1, mm2     // get LBCarrys for each byte where both
+                              // lsb's were == 1 (Only valid for active group)
+            psrlq mm2, 1      // divide raw bytes by 2
+            pand  mm2, mm4    // clear invalid bit 7 of each byte
+            paddb mm2, mm1    // add LBCarrys to (Raw(x-bpp)/2) for each byte
+            pand mm2, mm6     // Leave only Active Group 2 bytes to add to Avg
+            paddb mm0, mm2    // add (Raw/2) + LBCarrys to Avg for each Active
+                              // byte
+            cmp ebx, MMXLength
+            // Now ready to write back to memory
+            movq [edi + ebx - 8], mm0
+            // Prep Raw(x-bpp) for next loop
+            movq mm2, mm0     // mov updated Raws to mm2
+            jb davg4lp
+         } // end _asm block
+      }
+      break;
+      case 2:
+      {
+         ActiveMask.use  = 0x000000000000ffff;
+         ShiftBpp.use = 16;   // == 2 * 8     [BUGFIX]
+         ShiftRem.use = 48;   // == 64 - 16   [BUGFIX]
+         _asm {
+            // Load ActiveMask
+            movq mm7, ActiveMask
+            // Re-init address pointers and offset
+            mov ebx, diff     // ebx ==> x = offset to alignment boundary
+            movq mm5, LBCarryMask
+            mov edi, row      // edi ==> Avg(x)
+            movq mm4, HBClearMask
+            mov esi, prev_row  // esi ==> Prior(x)
+            // PRIME the pump (load the first Raw(x-bpp) data set
+            movq mm2, [edi + ebx - 8]  // Load previous aligned 8 bytes
+                              // (we correct position in loop below)
+davg2lp:
+            movq mm0, [edi + ebx]
+            psrlq mm2, ShiftRem  // shift data to position correctly   [BUGFIX]
+            movq mm1, [esi + ebx]
+            // Add (Prev_row/2) to Average
+            movq mm3, mm5
+            pand mm3, mm1     // get lsb for each prev_row byte
+            psrlq mm1, 1      // divide prev_row bytes by 2
+            pand  mm1, mm4    // clear invalid bit 7 of each byte
+            movq mm6, mm7
+            paddb mm0, mm1    // add (Prev_row/2) to Avg for each byte
+            // Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry
+            movq mm1, mm3     // now use mm1 for getting LBCarrys
+            pand mm1, mm2     // get LBCarrys for each byte where both
+                              // lsb's were == 1 (Only valid for active group)
+            psrlq mm2, 1      // divide raw bytes by 2
+            pand  mm2, mm4    // clear invalid bit 7 of each byte
+            paddb mm2, mm1    // add LBCarrys to (Raw(x-bpp)/2) for each byte
+            pand mm2, mm6     // Leave only Active Group 1 bytes to add to Avg
+            paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active byte
+            // Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry
+            psllq mm6, ShiftBpp // shift the mm6 mask to cover bytes 2 & 3
+            movq mm2, mm0       // mov updated Raws to mm2
+            psllq mm2, ShiftBpp // shift data to position correctly
+            movq mm1, mm3       // now use mm1 for getting LBCarrys
+            pand mm1, mm2       // get LBCarrys for each byte where both
+                                // lsb's were == 1 (Only valid for active group)
+            psrlq mm2, 1        // divide raw bytes by 2
+            pand  mm2, mm4      // clear invalid bit 7 of each byte
+            paddb mm2, mm1      // add LBCarrys to (Raw(x-bpp)/2) for each byte
+            pand mm2, mm6       // Leave only Active Group 2 bytes to add to Avg
+            paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active byte
+
+            // Add rdd active group (Raw(x-bpp)/2) to Average with LBCarry
+            psllq mm6, ShiftBpp // shift the mm6 mask to cover bytes 4 & 5
+            movq mm2, mm0       // mov updated Raws to mm2
+            psllq mm2, ShiftBpp // shift data to position correctly
+                                // Data only needs to be shifted once here to
+                                // get the correct x-bpp offset.
+            movq mm1, mm3       // now use mm1 for getting LBCarrys
+            pand mm1, mm2       // get LBCarrys for each byte where both
+                                // lsb's were == 1 (Only valid for active group)
+            psrlq mm2, 1        // divide raw bytes by 2
+            pand  mm2, mm4      // clear invalid bit 7 of each byte
+            paddb mm2, mm1      // add LBCarrys to (Raw(x-bpp)/2) for each byte
+            pand mm2, mm6       // Leave only Active Group 2 bytes to add to Avg
+            paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active byte
+
+            // Add 4th active group (Raw(x-bpp)/2) to Average with LBCarry
+            psllq mm6, ShiftBpp  // shift the mm6 mask to cover bytes 6 & 7
+            movq mm2, mm0        // mov updated Raws to mm2
+            psllq mm2, ShiftBpp  // shift data to position correctly
+                                 // Data only needs to be shifted once here to
+                                 // get the correct x-bpp offset.
+            add ebx, 8
+            movq mm1, mm3    // now use mm1 for getting LBCarrys
+            pand mm1, mm2    // get LBCarrys for each byte where both
+                             // lsb's were == 1 (Only valid for active group)
+            psrlq mm2, 1     // divide raw bytes by 2
+            pand  mm2, mm4   // clear invalid bit 7 of each byte
+            paddb mm2, mm1   // add LBCarrys to (Raw(x-bpp)/2) for each byte
+            pand mm2, mm6    // Leave only Active Group 2 bytes to add to Avg
+            paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active byte
+
+            cmp ebx, MMXLength
+            // Now ready to write back to memory
+            movq [edi + ebx - 8], mm0
+            // Prep Raw(x-bpp) for next loop
+            movq mm2, mm0    // mov updated Raws to mm2
+            jb davg2lp
+        } // end _asm block
+      }
+      break;
+
+      case 1:                 // bpp == 1
+      {
+         _asm {
+            // Re-init address pointers and offset
+            mov ebx, diff     // ebx ==> x = offset to alignment boundary
+            mov edi, row      // edi ==> Avg(x)
+            cmp ebx, FullLength  // Test if offset at end of array
+            jnb davg1end
+            // Do Paeth decode for remaining bytes
+            mov esi, prev_row    // esi ==> Prior(x)
+            mov edx, edi
+            xor ecx, ecx         // zero ecx before using cl & cx in loop below
+            sub edx, bpp         // edx ==> Raw(x-bpp)
+davg1lp:
+            // Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2)
+            xor eax, eax
+            mov cl, [esi + ebx]  // load cl with Prior(x)
+            mov al, [edx + ebx]  // load al with Raw(x-bpp)
+            add ax, cx
+            inc ebx
+            shr ax, 1            // divide by 2
+            add al, [edi+ebx-1]  // Add Avg(x); -1 to offset inc ebx
+            cmp ebx, FullLength  // Check if at end of array
+            mov [edi+ebx-1], al  // Write back Raw(x);
+                         // mov does not affect flags; -1 to offset inc ebx
+            jb davg1lp
+davg1end:
+         } // end _asm block
+      }
+      return;
+
+      case 8:             // bpp == 8
+      {
+         _asm {
+            // Re-init address pointers and offset
+            mov ebx, diff           // ebx ==> x = offset to alignment boundary
+            movq mm5, LBCarryMask
+            mov edi, row            // edi ==> Avg(x)
+            movq mm4, HBClearMask
+            mov esi, prev_row       // esi ==> Prior(x)
+            // PRIME the pump (load the first Raw(x-bpp) data set
+            movq mm2, [edi + ebx - 8]  // Load previous aligned 8 bytes
+                                // (NO NEED to correct position in loop below)
+davg8lp:
+            movq mm0, [edi + ebx]
+            movq mm3, mm5
+            movq mm1, [esi + ebx]
+            add ebx, 8
+            pand mm3, mm1       // get lsb for each prev_row byte
+            psrlq mm1, 1        // divide prev_row bytes by 2
+            pand mm3, mm2       // get LBCarrys for each byte where both
+                                // lsb's were == 1
+            psrlq mm2, 1        // divide raw bytes by 2
+            pand  mm1, mm4      // clear invalid bit 7 of each byte
+            paddb mm0, mm3      // add LBCarrys to Avg for each byte
+            pand  mm2, mm4      // clear invalid bit 7 of each byte
+            paddb mm0, mm1      // add (Prev_row/2) to Avg for each byte
+            paddb mm0, mm2      // add (Raw/2) to Avg for each byte
+            cmp ebx, MMXLength
+            movq [edi + ebx - 8], mm0
+            movq mm2, mm0       // reuse as Raw(x-bpp)
+            jb davg8lp
+        } // end _asm block
+      }
+      break;
+      default:                  // bpp greater than 8
+      {
+        _asm {
+            movq mm5, LBCarryMask
+            // Re-init address pointers and offset
+            mov ebx, diff       // ebx ==> x = offset to alignment boundary
+            mov edi, row        // edi ==> Avg(x)
+            movq mm4, HBClearMask
+            mov edx, edi
+            mov esi, prev_row   // esi ==> Prior(x)
+            sub edx, bpp        // edx ==> Raw(x-bpp)
+davgAlp:
+            movq mm0, [edi + ebx]
+            movq mm3, mm5
+            movq mm1, [esi + ebx]
+            pand mm3, mm1       // get lsb for each prev_row byte
+            movq mm2, [edx + ebx]
+            psrlq mm1, 1        // divide prev_row bytes by 2
+            pand mm3, mm2       // get LBCarrys for each byte where both
+                                // lsb's were == 1
+            psrlq mm2, 1        // divide raw bytes by 2
+            pand  mm1, mm4      // clear invalid bit 7 of each byte
+            paddb mm0, mm3      // add LBCarrys to Avg for each byte
+            pand  mm2, mm4      // clear invalid bit 7 of each byte
+            paddb mm0, mm1      // add (Prev_row/2) to Avg for each byte
+            add ebx, 8
+            paddb mm0, mm2      // add (Raw/2) to Avg for each byte
+            cmp ebx, MMXLength
+            movq [edi + ebx - 8], mm0
+            jb davgAlp
+        } // end _asm block
+      }
+      break;
+   }                         // end switch ( bpp )
+
+   _asm {
+         // MMX acceleration complete now do clean-up
+         // Check if any remaining bytes left to decode
+         mov ebx, MMXLength    // ebx ==> x = offset bytes remaining after MMX
+         mov edi, row          // edi ==> Avg(x)
+         cmp ebx, FullLength   // Test if offset at end of array
+         jnb davgend
+         // Do Paeth decode for remaining bytes
+         mov esi, prev_row     // esi ==> Prior(x)
+         mov edx, edi
+         xor ecx, ecx          // zero ecx before using cl & cx in loop below
+         sub edx, bpp          // edx ==> Raw(x-bpp)
+davglp2:
+         // Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2)
+         xor eax, eax
+         mov cl, [esi + ebx]   // load cl with Prior(x)
+         mov al, [edx + ebx]   // load al with Raw(x-bpp)
+         add ax, cx
+         inc ebx
+         shr ax, 1              // divide by 2
+         add al, [edi+ebx-1]    // Add Avg(x); -1 to offset inc ebx
+         cmp ebx, FullLength    // Check if at end of array
+         mov [edi+ebx-1], al    // Write back Raw(x);
+                          // mov does not affect flags; -1 to offset inc ebx
+         jb davglp2
+davgend:
+         emms             // End MMX instructions; prep for possible FP instrs.
+   } // end _asm block
+}
+
+// Optimized code for PNG Paeth filter decoder
+void /* PRIVATE */
+png_read_filter_row_mmx_paeth(png_row_infop row_info, png_bytep row,
+                              png_bytep prev_row)
+{
+   png_uint_32 FullLength;
+   png_uint_32 MMXLength;
+   //png_uint_32 len;
+   int bpp;
+   int diff;
+   //int ptemp;
+   int patemp, pbtemp, pctemp;
+
+   bpp = (row_info->pixel_depth + 7) >> 3; // Get # bytes per pixel
+   FullLength  = row_info->rowbytes; // # of bytes to filter
+   _asm
+   {
+         xor ebx, ebx        // ebx ==> x offset
+         mov edi, row
+         xor edx, edx        // edx ==> x-bpp offset
+         mov esi, prev_row
+         xor eax, eax
+
+         // 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
+dpthrlp:
+         mov al, [edi + ebx]
+         add al, [esi + ebx]
+         inc ebx
+         cmp ebx, bpp
+         mov [edi + ebx - 1], al
+         jb dpthrlp
+         // get # of bytes to alignment
+         mov diff, edi         // take start of row
+         add diff, ebx         // add bpp
+         xor ecx, ecx
+         add diff, 0xf         // add 7 + 8 to incr past alignment boundary
+         and diff, 0xfffffff8  // mask to alignment boundary
+         sub diff, edi         // subtract from start ==> value ebx at alignment
+         jz dpthgo
+         // fix alignment
+dpthlp1:
+         xor eax, eax
+         // pav = p - a = (a + b - c) - a = b - c
+         mov al, [esi + ebx]   // load Prior(x) into al
+         mov cl, [esi + edx]   // load Prior(x-bpp) into cl
+         sub eax, ecx          // subtract Prior(x-bpp)
+         mov patemp, eax       // Save pav for later use
+         xor eax, eax
+         // pbv = p - b = (a + b - c) - b = a - c
+         mov al, [edi + edx]   // load Raw(x-bpp) into al
+         sub eax, ecx          // subtract Prior(x-bpp)
+         mov ecx, eax
+         // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+         add eax, patemp       // pcv = pav + pbv
+         // pc = abs(pcv)
+         test eax, 0x80000000
+         jz dpthpca
+         neg eax               // reverse sign of neg values
+dpthpca:
+         mov pctemp, eax       // save pc for later use
+         // pb = abs(pbv)
+         test ecx, 0x80000000
+         jz dpthpba
+         neg ecx               // reverse sign of neg values
+dpthpba:
+         mov pbtemp, ecx       // save pb for later use
+         // pa = abs(pav)
+         mov eax, patemp
+         test eax, 0x80000000
+         jz dpthpaa
+         neg eax               // reverse sign of neg values
+dpthpaa:
+         mov patemp, eax       // save pa for later use
+         // test if pa <= pb
+         cmp eax, ecx
+         jna dpthabb
+         // pa > pb; now test if pb <= pc
+         cmp ecx, pctemp
+         jna dpthbbc
+         // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
+         mov cl, [esi + edx]  // load Prior(x-bpp) into cl
+         jmp dpthpaeth
+dpthbbc:
+         // pb <= pc; Raw(x) = Paeth(x) + Prior(x)
+         mov cl, [esi + ebx]   // load Prior(x) into cl
+         jmp dpthpaeth
+dpthabb:
+         // pa <= pb; now test if pa <= pc
+         cmp eax, pctemp
+         jna dpthabc
+         // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
+         mov cl, [esi + edx]  // load Prior(x-bpp) into cl
+         jmp dpthpaeth
+dpthabc:
+         // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp)
+         mov cl, [edi + edx]  // load Raw(x-bpp) into cl
+dpthpaeth:
+         inc ebx
+         inc edx
+         // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256
+         add [edi + ebx - 1], cl
+         cmp ebx, diff
+         jb dpthlp1
+dpthgo:
+         mov ecx, FullLength
+         mov eax, ecx
+         sub eax, ebx          // subtract alignment fix
+         and eax, 0x00000007   // calc bytes over mult of 8
+         sub ecx, eax          // drop over bytes from original length
+         mov MMXLength, ecx
+   } // end _asm block
+   // 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
+         {
+            mov ebx, diff
+            mov edi, row
+            mov esi, prev_row
+            pxor mm0, mm0
+            // PRIME the pump (load the first Raw(x-bpp) data set
+            movq mm1, [edi+ebx-8]
+dpth3lp:
+            psrlq mm1, ShiftRem     // shift last 3 bytes to 1st 3 bytes
+            movq mm2, [esi + ebx]   // load b=Prior(x)
+            punpcklbw mm1, mm0      // Unpack High bytes of a
+            movq mm3, [esi+ebx-8]   // Prep c=Prior(x-bpp) bytes
+            punpcklbw mm2, mm0      // Unpack High bytes of b
+            psrlq mm3, ShiftRem     // shift last 3 bytes to 1st 3 bytes
+            // pav = p - a = (a + b - c) - a = b - c
+            movq mm4, mm2
+            punpcklbw mm3, mm0      // Unpack High bytes of c
+            // pbv = p - b = (a + b - c) - b = a - c
+            movq mm5, mm1
+            psubw mm4, mm3
+            pxor mm7, mm7
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            movq mm6, mm4
+            psubw mm5, mm3
+
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            pcmpgtw mm0, mm4    // Create mask pav bytes < 0
+            paddw mm6, mm5
+            pand mm0, mm4       // Only pav bytes < 0 in mm7
+            pcmpgtw mm7, mm5    // Create mask pbv bytes < 0
+            psubw mm4, mm0
+            pand mm7, mm5       // Only pbv bytes < 0 in mm0
+            psubw mm4, mm0
+            psubw mm5, mm7
+            pxor mm0, mm0
+            pcmpgtw mm0, mm6    // Create mask pcv bytes < 0
+            pand mm0, mm6       // Only pav bytes < 0 in mm7
+            psubw mm5, mm7
+            psubw mm6, mm0
+            //  test pa <= pb
+            movq mm7, mm4
+            psubw mm6, mm0
+            pcmpgtw mm7, mm5    // pa > pb?
+            movq mm0, mm7
+            // use mm7 mask to merge pa & pb
+            pand mm5, mm7
+            // use mm0 mask copy to merge a & b
+            pand mm2, mm0
+            pandn mm7, mm4
+            pandn mm0, mm1
+            paddw mm7, mm5
+            paddw mm0, mm2
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            pcmpgtw mm7, mm6       // pab > pc?
+            pxor mm1, mm1
+            pand mm3, mm7
+            pandn mm7, mm0
+            paddw mm7, mm3
+            pxor mm0, mm0
+            packuswb mm7, mm1
+            movq mm3, [esi + ebx]   // load c=Prior(x-bpp)
+            pand mm7, ActiveMask
+            movq mm2, mm3           // load b=Prior(x) step 1
+            paddb mm7, [edi + ebx]  // add Paeth predictor with Raw(x)
+            punpcklbw mm3, mm0      // Unpack High bytes of c
+            movq [edi + ebx], mm7   // write back updated value
+            movq mm1, mm7           // Now mm1 will be used as Raw(x-bpp)
+            // Now do Paeth for 2nd set of bytes (3-5)
+            psrlq mm2, ShiftBpp     // load b=Prior(x) step 2
+            punpcklbw mm1, mm0      // Unpack High bytes of a
+            pxor mm7, mm7
+            punpcklbw mm2, mm0      // Unpack High bytes of b
+            // pbv = p - b = (a + b - c) - b = a - c
+            movq mm5, mm1
+            // pav = p - a = (a + b - c) - a = b - c
+            movq mm4, mm2
+            psubw mm5, mm3
+            psubw mm4, mm3
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) =
+            //       pav + pbv = pbv + pav
+            movq mm6, mm5
+            paddw mm6, mm4
+
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            pcmpgtw mm0, mm5       // Create mask pbv bytes < 0
+            pcmpgtw mm7, mm4       // Create mask pav bytes < 0
+            pand mm0, mm5          // Only pbv bytes < 0 in mm0
+            pand mm7, mm4          // Only pav bytes < 0 in mm7
+            psubw mm5, mm0
+            psubw mm4, mm7
+            psubw mm5, mm0
+            psubw mm4, mm7
+            pxor mm0, mm0
+            pcmpgtw mm0, mm6       // Create mask pcv bytes < 0
+            pand mm0, mm6          // Only pav bytes < 0 in mm7
+            psubw mm6, mm0
+            //  test pa <= pb
+            movq mm7, mm4
+            psubw mm6, mm0
+            pcmpgtw mm7, mm5       // pa > pb?
+            movq mm0, mm7
+            // use mm7 mask to merge pa & pb
+            pand mm5, mm7
+            // use mm0 mask copy to merge a & b
+            pand mm2, mm0
+            pandn mm7, mm4
+            pandn mm0, mm1
+            paddw mm7, mm5
+            paddw mm0, mm2
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            pcmpgtw mm7, mm6       // pab > pc?
+            movq mm2, [esi + ebx]  // load b=Prior(x)
+            pand mm3, mm7
+            pandn mm7, mm0
+            pxor mm1, mm1
+            paddw mm7, mm3
+            pxor mm0, mm0
+            packuswb mm7, mm1
+            movq mm3, mm2           // load c=Prior(x-bpp) step 1
+            pand mm7, ActiveMask
+            punpckhbw mm2, mm0      // Unpack High bytes of b
+            psllq mm7, ShiftBpp     // Shift bytes to 2nd group of 3 bytes
+             // pav = p - a = (a + b - c) - a = b - c
+            movq mm4, mm2
+            paddb mm7, [edi + ebx]  // add Paeth predictor with Raw(x)
+            psllq mm3, ShiftBpp     // load c=Prior(x-bpp) step 2
+            movq [edi + ebx], mm7   // write back updated value
+            movq mm1, mm7
+            punpckhbw mm3, mm0      // Unpack High bytes of c
+            psllq mm1, ShiftBpp     // 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
+            punpckhbw mm1, mm0      // Unpack High bytes of a
+            psubw mm4, mm3
+            // pbv = p - b = (a + b - c) - b = a - c
+            movq mm5, mm1
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            movq mm6, mm4
+            psubw mm5, mm3
+            pxor mm0, mm0
+            paddw mm6, mm5
+
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            pcmpgtw mm0, mm4    // Create mask pav bytes < 0
+            pcmpgtw mm7, mm5    // Create mask pbv bytes < 0
+            pand mm0, mm4       // Only pav bytes < 0 in mm7
+            pand mm7, mm5       // Only pbv bytes < 0 in mm0
+            psubw mm4, mm0
+            psubw mm5, mm7
+            psubw mm4, mm0
+            psubw mm5, mm7
+            pxor mm0, mm0
+            pcmpgtw mm0, mm6    // Create mask pcv bytes < 0
+            pand mm0, mm6       // Only pav bytes < 0 in mm7
+            psubw mm6, mm0
+            //  test pa <= pb
+            movq mm7, mm4
+            psubw mm6, mm0
+            pcmpgtw mm7, mm5    // pa > pb?
+            movq mm0, mm7
+            // use mm0 mask copy to merge a & b
+            pand mm2, mm0
+            // use mm7 mask to merge pa & pb
+            pand mm5, mm7
+            pandn mm0, mm1
+            pandn mm7, mm4
+            paddw mm0, mm2
+            paddw mm7, mm5
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            pcmpgtw mm7, mm6    // pab > pc?
+            pand mm3, mm7
+            pandn mm7, mm0
+            paddw mm7, mm3
+            pxor mm1, mm1
+            packuswb mm1, mm7
+            // Step ebx to next set of 8 bytes and repeat loop til done
+            add ebx, 8
+            pand mm1, ActiveMaskEnd
+            paddb mm1, [edi + ebx - 8] // add Paeth predictor with Raw(x)
+
+            cmp ebx, MMXLength
+            pxor mm0, mm0              // pxor does not affect flags
+            movq [edi + ebx - 8], mm1  // 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 dpth3lp
+         } // end _asm block
+      }
+      break;
+
+      case 6:
+      case 7:
+      case 5:
+      {
+         ActiveMask.use  = 0x00000000ffffffff;
+         ActiveMask2.use = 0xffffffff00000000;
+         ShiftBpp.use = bpp << 3;    // == bpp * 8
+         ShiftRem.use = 64 - ShiftBpp.use;
+         _asm
+         {
+            mov ebx, diff
+            mov edi, row
+            mov esi, prev_row
+            // PRIME the pump (load the first Raw(x-bpp) data set
+            movq mm1, [edi+ebx-8]
+            pxor mm0, mm0
+dpth6lp:
+            // Must shift to position Raw(x-bpp) data
+            psrlq mm1, ShiftRem
+            // Do first set of 4 bytes
+            movq mm3, [esi+ebx-8]      // read c=Prior(x-bpp) bytes
+            punpcklbw mm1, mm0      // Unpack Low bytes of a
+            movq mm2, [esi + ebx]   // load b=Prior(x)
+            punpcklbw mm2, mm0      // Unpack Low bytes of b
+            // Must shift to position Prior(x-bpp) data
+            psrlq mm3, ShiftRem
+            // pav = p - a = (a + b - c) - a = b - c
+            movq mm4, mm2
+            punpcklbw mm3, mm0      // Unpack Low bytes of c
+            // pbv = p - b = (a + b - c) - b = a - c
+            movq mm5, mm1
+            psubw mm4, mm3
+            pxor mm7, mm7
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            movq mm6, mm4
+            psubw mm5, mm3
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            pcmpgtw mm0, mm4    // Create mask pav bytes < 0
+            paddw mm6, mm5
+            pand mm0, mm4       // Only pav bytes < 0 in mm7
+            pcmpgtw mm7, mm5    // Create mask pbv bytes < 0
+            psubw mm4, mm0
+            pand mm7, mm5       // Only pbv bytes < 0 in mm0
+            psubw mm4, mm0
+            psubw mm5, mm7
+            pxor mm0, mm0
+            pcmpgtw mm0, mm6    // Create mask pcv bytes < 0
+            pand mm0, mm6       // Only pav bytes < 0 in mm7
+            psubw mm5, mm7
+            psubw mm6, mm0
+            //  test pa <= pb
+            movq mm7, mm4
+            psubw mm6, mm0
+            pcmpgtw mm7, mm5    // pa > pb?
+            movq mm0, mm7
+            // use mm7 mask to merge pa & pb
+            pand mm5, mm7
+            // use mm0 mask copy to merge a & b
+            pand mm2, mm0
+            pandn mm7, mm4
+            pandn mm0, mm1
+            paddw mm7, mm5
+            paddw mm0, mm2
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            pcmpgtw mm7, mm6    // pab > pc?
+            pxor mm1, mm1
+            pand mm3, mm7
+            pandn mm7, mm0
+            paddw mm7, mm3
+            pxor mm0, mm0
+            packuswb mm7, mm1
+            movq mm3, [esi + ebx - 8]  // load c=Prior(x-bpp)
+            pand mm7, ActiveMask
+            psrlq mm3, ShiftRem
+            movq mm2, [esi + ebx]      // load b=Prior(x) step 1
+            paddb mm7, [edi + ebx]     // add Paeth predictor with Raw(x)
+            movq mm6, mm2
+            movq [edi + ebx], mm7      // write back updated value
+            movq mm1, [edi+ebx-8]
+            psllq mm6, ShiftBpp
+            movq mm5, mm7
+            psrlq mm1, ShiftRem
+            por mm3, mm6
+            psllq mm5, ShiftBpp
+            punpckhbw mm3, mm0         // Unpack High bytes of c
+            por mm1, mm5
+            // Do second set of 4 bytes
+            punpckhbw mm2, mm0         // Unpack High bytes of b
+            punpckhbw mm1, mm0         // Unpack High bytes of a
+            // pav = p - a = (a + b - c) - a = b - c
+            movq mm4, mm2
+            // pbv = p - b = (a + b - c) - b = a - c
+            movq mm5, mm1
+            psubw mm4, mm3
+            pxor mm7, mm7
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            movq mm6, mm4
+            psubw mm5, mm3
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            pcmpgtw mm0, mm4       // Create mask pav bytes < 0
+            paddw mm6, mm5
+            pand mm0, mm4          // Only pav bytes < 0 in mm7
+            pcmpgtw mm7, mm5       // Create mask pbv bytes < 0
+            psubw mm4, mm0
+            pand mm7, mm5          // Only pbv bytes < 0 in mm0
+            psubw mm4, mm0
+            psubw mm5, mm7
+            pxor mm0, mm0
+            pcmpgtw mm0, mm6       // Create mask pcv bytes < 0
+            pand mm0, mm6          // Only pav bytes < 0 in mm7
+            psubw mm5, mm7
+            psubw mm6, mm0
+            //  test pa <= pb
+            movq mm7, mm4
+            psubw mm6, mm0
+            pcmpgtw mm7, mm5       // pa > pb?
+            movq mm0, mm7
+            // use mm7 mask to merge pa & pb
+            pand mm5, mm7
+            // use mm0 mask copy to merge a & b
+            pand mm2, mm0
+            pandn mm7, mm4
+            pandn mm0, mm1
+            paddw mm7, mm5
+            paddw mm0, mm2
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            pcmpgtw mm7, mm6           // pab > pc?
+            pxor mm1, mm1
+            pand mm3, mm7
+            pandn mm7, mm0
+            pxor mm1, mm1
+            paddw mm7, mm3
+            pxor mm0, mm0
+            // Step ex to next set of 8 bytes and repeat loop til done
+            add ebx, 8
+            packuswb mm1, mm7
+            paddb mm1, [edi + ebx - 8]     // add Paeth predictor with Raw(x)
+            cmp ebx, MMXLength
+            movq [edi + ebx - 8], mm1      // write back updated value
+                                // mm1 will be used as Raw(x-bpp) next loop
+            jb dpth6lp
+         } // end _asm block
+      }
+      break;
+
+      case 4:
+      {
+         ActiveMask.use  = 0x00000000ffffffff;
+         _asm {
+            mov ebx, diff
+            mov edi, row
+            mov esi, prev_row
+            pxor mm0, mm0
+            // PRIME the pump (load the first Raw(x-bpp) data set
+            movq mm1, [edi+ebx-8]    // Only time should need to read
+                                     //  a=Raw(x-bpp) bytes
+dpth4lp:
+            // Do first set of 4 bytes
+            movq mm3, [esi+ebx-8]    // read c=Prior(x-bpp) bytes
+            punpckhbw mm1, mm0       // Unpack Low bytes of a
+            movq mm2, [esi + ebx]    // load b=Prior(x)
+            punpcklbw mm2, mm0       // Unpack High bytes of b
+            // pav = p - a = (a + b - c) - a = b - c
+            movq mm4, mm2
+            punpckhbw mm3, mm0       // Unpack High bytes of c
+            // pbv = p - b = (a + b - c) - b = a - c
+            movq mm5, mm1
+            psubw mm4, mm3
+            pxor mm7, mm7
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            movq mm6, mm4
+            psubw mm5, mm3
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            pcmpgtw mm0, mm4       // Create mask pav bytes < 0
+            paddw mm6, mm5
+            pand mm0, mm4          // Only pav bytes < 0 in mm7
+            pcmpgtw mm7, mm5       // Create mask pbv bytes < 0
+            psubw mm4, mm0
+            pand mm7, mm5          // Only pbv bytes < 0 in mm0
+            psubw mm4, mm0
+            psubw mm5, mm7
+            pxor mm0, mm0
+            pcmpgtw mm0, mm6       // Create mask pcv bytes < 0
+            pand mm0, mm6          // Only pav bytes < 0 in mm7
+            psubw mm5, mm7
+            psubw mm6, mm0
+            //  test pa <= pb
+            movq mm7, mm4
+            psubw mm6, mm0
+            pcmpgtw mm7, mm5       // pa > pb?
+            movq mm0, mm7
+            // use mm7 mask to merge pa & pb
+            pand mm5, mm7
+            // use mm0 mask copy to merge a & b
+            pand mm2, mm0
+            pandn mm7, mm4
+            pandn mm0, mm1
+            paddw mm7, mm5
+            paddw mm0, mm2
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            pcmpgtw mm7, mm6       // pab > pc?
+            pxor mm1, mm1
+            pand mm3, mm7
+            pandn mm7, mm0
+            paddw mm7, mm3
+            pxor mm0, mm0
+            packuswb mm7, mm1
+            movq mm3, [esi + ebx]      // load c=Prior(x-bpp)
+            pand mm7, ActiveMask
+            movq mm2, mm3              // load b=Prior(x) step 1
+            paddb mm7, [edi + ebx]     // add Paeth predictor with Raw(x)
+            punpcklbw mm3, mm0         // Unpack High bytes of c
+            movq [edi + ebx], mm7      // write back updated value
+            movq mm1, mm7              // Now mm1 will be used as Raw(x-bpp)
+            // Do second set of 4 bytes
+            punpckhbw mm2, mm0         // Unpack Low bytes of b
+            punpcklbw mm1, mm0         // Unpack Low bytes of a
+            // pav = p - a = (a + b - c) - a = b - c
+            movq mm4, mm2
+            // pbv = p - b = (a + b - c) - b = a - c
+            movq mm5, mm1
+            psubw mm4, mm3
+            pxor mm7, mm7
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            movq mm6, mm4
+            psubw mm5, mm3
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            pcmpgtw mm0, mm4       // Create mask pav bytes < 0
+            paddw mm6, mm5
+            pand mm0, mm4          // Only pav bytes < 0 in mm7
+            pcmpgtw mm7, mm5       // Create mask pbv bytes < 0
+            psubw mm4, mm0
+            pand mm7, mm5          // Only pbv bytes < 0 in mm0
+            psubw mm4, mm0
+            psubw mm5, mm7
+            pxor mm0, mm0
+            pcmpgtw mm0, mm6       // Create mask pcv bytes < 0
+            pand mm0, mm6          // Only pav bytes < 0 in mm7
+            psubw mm5, mm7
+            psubw mm6, mm0
+            //  test pa <= pb
+            movq mm7, mm4
+            psubw mm6, mm0
+            pcmpgtw mm7, mm5       // pa > pb?
+            movq mm0, mm7
+            // use mm7 mask to merge pa & pb
+            pand mm5, mm7
+            // use mm0 mask copy to merge a & b
+            pand mm2, mm0
+            pandn mm7, mm4
+            pandn mm0, mm1
+            paddw mm7, mm5
+            paddw mm0, mm2
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            pcmpgtw mm7, mm6       // pab > pc?
+            pxor mm1, mm1
+            pand mm3, mm7
+            pandn mm7, mm0
+            pxor mm1, mm1
+            paddw mm7, mm3
+            pxor mm0, mm0
+            // Step ex to next set of 8 bytes and repeat loop til done
+            add ebx, 8
+            packuswb mm1, mm7
+            paddb mm1, [edi + ebx - 8]     // add Paeth predictor with Raw(x)
+            cmp ebx, MMXLength
+            movq [edi + ebx - 8], mm1      // write back updated value
+                                // mm1 will be used as Raw(x-bpp) next loop
+            jb dpth4lp
+         } // end _asm block
+      }
+      break;
+      case 8:                          // bpp == 8
+      {
+         ActiveMask.use  = 0x00000000ffffffff;
+         _asm {
+            mov ebx, diff
+            mov edi, row
+            mov esi, prev_row
+            pxor mm0, mm0
+            // PRIME the pump (load the first Raw(x-bpp) data set
+            movq mm1, [edi+ebx-8]      // Only time should need to read
+                                       //  a=Raw(x-bpp) bytes
+dpth8lp:
+            // Do first set of 4 bytes
+            movq mm3, [esi+ebx-8]      // read c=Prior(x-bpp) bytes
+            punpcklbw mm1, mm0         // Unpack Low bytes of a
+            movq mm2, [esi + ebx]      // load b=Prior(x)
+            punpcklbw mm2, mm0         // Unpack Low bytes of b
+            // pav = p - a = (a + b - c) - a = b - c
+            movq mm4, mm2
+            punpcklbw mm3, mm0         // Unpack Low bytes of c
+            // pbv = p - b = (a + b - c) - b = a - c
+            movq mm5, mm1
+            psubw mm4, mm3
+            pxor mm7, mm7
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            movq mm6, mm4
+            psubw mm5, mm3
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            pcmpgtw mm0, mm4       // Create mask pav bytes < 0
+            paddw mm6, mm5
+            pand mm0, mm4          // Only pav bytes < 0 in mm7
+            pcmpgtw mm7, mm5       // Create mask pbv bytes < 0
+            psubw mm4, mm0
+            pand mm7, mm5          // Only pbv bytes < 0 in mm0
+            psubw mm4, mm0
+            psubw mm5, mm7
+            pxor mm0, mm0
+            pcmpgtw mm0, mm6       // Create mask pcv bytes < 0
+            pand mm0, mm6          // Only pav bytes < 0 in mm7
+            psubw mm5, mm7
+            psubw mm6, mm0
+            //  test pa <= pb
+            movq mm7, mm4
+            psubw mm6, mm0
+            pcmpgtw mm7, mm5       // pa > pb?
+            movq mm0, mm7
+            // use mm7 mask to merge pa & pb
+            pand mm5, mm7
+            // use mm0 mask copy to merge a & b
+            pand mm2, mm0
+            pandn mm7, mm4
+            pandn mm0, mm1
+            paddw mm7, mm5
+            paddw mm0, mm2
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            pcmpgtw mm7, mm6       // pab > pc?
+            pxor mm1, mm1
+            pand mm3, mm7
+            pandn mm7, mm0
+            paddw mm7, mm3
+            pxor mm0, mm0
+            packuswb mm7, mm1
+            movq mm3, [esi+ebx-8]    // read c=Prior(x-bpp) bytes
+            pand mm7, ActiveMask
+            movq mm2, [esi + ebx]    // load b=Prior(x)
+            paddb mm7, [edi + ebx]   // add Paeth predictor with Raw(x)
+            punpckhbw mm3, mm0       // Unpack High bytes of c
+            movq [edi + ebx], mm7    // write back updated value
+            movq mm1, [edi+ebx-8]    // read a=Raw(x-bpp) bytes
+
+            // Do second set of 4 bytes
+            punpckhbw mm2, mm0       // Unpack High bytes of b
+            punpckhbw mm1, mm0       // Unpack High bytes of a
+            // pav = p - a = (a + b - c) - a = b - c
+            movq mm4, mm2
+            // pbv = p - b = (a + b - c) - b = a - c
+            movq mm5, mm1
+            psubw mm4, mm3
+            pxor mm7, mm7
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            movq mm6, mm4
+            psubw mm5, mm3
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            pcmpgtw mm0, mm4       // Create mask pav bytes < 0
+            paddw mm6, mm5
+            pand mm0, mm4          // Only pav bytes < 0 in mm7
+            pcmpgtw mm7, mm5       // Create mask pbv bytes < 0
+            psubw mm4, mm0
+            pand mm7, mm5          // Only pbv bytes < 0 in mm0
+            psubw mm4, mm0
+            psubw mm5, mm7
+            pxor mm0, mm0
+            pcmpgtw mm0, mm6       // Create mask pcv bytes < 0
+            pand mm0, mm6          // Only pav bytes < 0 in mm7
+            psubw mm5, mm7
+            psubw mm6, mm0
+            //  test pa <= pb
+            movq mm7, mm4
+            psubw mm6, mm0
+            pcmpgtw mm7, mm5       // pa > pb?
+            movq mm0, mm7
+            // use mm7 mask to merge pa & pb
+            pand mm5, mm7
+            // use mm0 mask copy to merge a & b
+            pand mm2, mm0
+            pandn mm7, mm4
+            pandn mm0, mm1
+            paddw mm7, mm5
+            paddw mm0, mm2
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            pcmpgtw mm7, mm6       // pab > pc?
+            pxor mm1, mm1
+            pand mm3, mm7
+            pandn mm7, mm0
+            pxor mm1, mm1
+            paddw mm7, mm3
+            pxor mm0, mm0
+            // Step ex to next set of 8 bytes and repeat loop til done
+            add ebx, 8
+            packuswb mm1, mm7
+            paddb mm1, [edi + ebx - 8]     // add Paeth predictor with Raw(x)
+            cmp ebx, MMXLength
+            movq [edi + ebx - 8], mm1      // write back updated value
+                            // mm1 will be used as Raw(x-bpp) next loop
+            jb dpth8lp
+         } // end _asm block
+      }
+      break;
+
+      case 1:                // bpp = 1
+      case 2:                // bpp = 2
+      default:               // bpp > 8
+      {
+         _asm {
+            mov ebx, diff
+            cmp ebx, FullLength
+            jnb dpthdend
+            mov edi, row
+            mov esi, prev_row
+            // Do Paeth decode for remaining bytes
+            mov edx, ebx
+            xor ecx, ecx        // zero ecx before using cl & cx in loop below
+            sub edx, bpp        // Set edx = ebx - bpp
+dpthdlp:
+            xor eax, eax
+            // pav = p - a = (a + b - c) - a = b - c
+            mov al, [esi + ebx]        // load Prior(x) into al
+            mov cl, [esi + edx]        // load Prior(x-bpp) into cl
+            sub eax, ecx                 // subtract Prior(x-bpp)
+            mov patemp, eax                 // Save pav for later use
+            xor eax, eax
+            // pbv = p - b = (a + b - c) - b = a - c
+            mov al, [edi + edx]        // load Raw(x-bpp) into al
+            sub eax, ecx                 // subtract Prior(x-bpp)
+            mov ecx, eax
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            add eax, patemp                 // pcv = pav + pbv
+            // pc = abs(pcv)
+            test eax, 0x80000000
+            jz dpthdpca
+            neg eax                     // reverse sign of neg values
+dpthdpca:
+            mov pctemp, eax             // save pc for later use
+            // pb = abs(pbv)
+            test ecx, 0x80000000
+            jz dpthdpba
+            neg ecx                     // reverse sign of neg values
+dpthdpba:
+            mov pbtemp, ecx             // save pb for later use
+            // pa = abs(pav)
+            mov eax, patemp
+            test eax, 0x80000000
+            jz dpthdpaa
+            neg eax                     // reverse sign of neg values
+dpthdpaa:
+            mov patemp, eax             // save pa for later use
+            // test if pa <= pb
+            cmp eax, ecx
+            jna dpthdabb
+            // pa > pb; now test if pb <= pc
+            cmp ecx, pctemp
+            jna dpthdbbc
+            // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
+            mov cl, [esi + edx]  // load Prior(x-bpp) into cl
+            jmp dpthdpaeth
+dpthdbbc:
+            // pb <= pc; Raw(x) = Paeth(x) + Prior(x)
+            mov cl, [esi + ebx]        // load Prior(x) into cl
+            jmp dpthdpaeth
+dpthdabb:
+            // pa <= pb; now test if pa <= pc
+            cmp eax, pctemp
+            jna dpthdabc
+            // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
+            mov cl, [esi + edx]  // load Prior(x-bpp) into cl
+            jmp dpthdpaeth
+dpthdabc:
+            // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp)
+            mov cl, [edi + edx]  // load Raw(x-bpp) into cl
+dpthdpaeth:
+            inc ebx
+            inc edx
+            // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256
+            add [edi + ebx - 1], cl
+            cmp ebx, FullLength
+            jb dpthdlp
+dpthdend:
+         } // end _asm block
+      }
+      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
+         mov ebx, MMXLength
+         cmp ebx, FullLength
+         jnb dpthend
+         mov edi, row
+         mov esi, prev_row
+         // Do Paeth decode for remaining bytes
+         mov edx, ebx
+         xor ecx, ecx         // zero ecx before using cl & cx in loop below
+         sub edx, bpp         // Set edx = ebx - bpp
+dpthlp2:
+         xor eax, eax
+         // pav = p - a = (a + b - c) - a = b - c
+         mov al, [esi + ebx]  // load Prior(x) into al
+         mov cl, [esi + edx]  // load Prior(x-bpp) into cl
+         sub eax, ecx         // subtract Prior(x-bpp)
+         mov patemp, eax      // Save pav for later use
+         xor eax, eax
+         // pbv = p - b = (a + b - c) - b = a - c
+         mov al, [edi + edx]  // load Raw(x-bpp) into al
+         sub eax, ecx         // subtract Prior(x-bpp)
+         mov ecx, eax
+         // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+         add eax, patemp      // pcv = pav + pbv
+         // pc = abs(pcv)
+         test eax, 0x80000000
+         jz dpthpca2
+         neg eax              // reverse sign of neg values
+dpthpca2:
+         mov pctemp, eax      // save pc for later use
+         // pb = abs(pbv)
+         test ecx, 0x80000000
+         jz dpthpba2
+         neg ecx              // reverse sign of neg values
+dpthpba2:
+         mov pbtemp, ecx      // save pb for later use
+         // pa = abs(pav)
+         mov eax, patemp
+         test eax, 0x80000000
+         jz dpthpaa2
+         neg eax              // reverse sign of neg values
+dpthpaa2:
+         mov patemp, eax      // save pa for later use
+         // test if pa <= pb
+         cmp eax, ecx
+         jna dpthabb2
+         // pa > pb; now test if pb <= pc
+         cmp ecx, pctemp
+         jna dpthbbc2
+         // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
+         mov cl, [esi + edx]  // load Prior(x-bpp) into cl
+         jmp dpthpaeth2
+dpthbbc2:
+         // pb <= pc; Raw(x) = Paeth(x) + Prior(x)
+         mov cl, [esi + ebx]        // load Prior(x) into cl
+         jmp dpthpaeth2
+dpthabb2:
+         // pa <= pb; now test if pa <= pc
+         cmp eax, pctemp
+         jna dpthabc2
+         // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
+         mov cl, [esi + edx]  // load Prior(x-bpp) into cl
+         jmp dpthpaeth2
+dpthabc2:
+         // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp)
+         mov cl, [edi + edx]  // load Raw(x-bpp) into cl
+dpthpaeth2:
+         inc ebx
+         inc edx
+         // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256
+         add [edi + ebx - 1], cl
+         cmp ebx, FullLength
+         jb dpthlp2
+dpthend:
+         emms             // End MMX instructions; prep for possible FP instrs.
+   } // end _asm block
+}
+
+// Optimized code for PNG Sub filter decoder
+void /* PRIVATE */
+png_read_filter_row_mmx_sub(png_row_infop row_info, png_bytep row)
+{
+   //int test;
+   int bpp;
+   png_uint_32 FullLength;
+   png_uint_32 MMXLength;
+   int diff;
+
+   bpp = (row_info->pixel_depth + 7) >> 3; // Get # bytes per pixel
+   FullLength  = row_info->rowbytes - bpp; // # of bytes to filter
+   _asm {
+        mov edi, row
+        mov esi, edi               // lp = row
+        add edi, bpp               // rp = row + bpp
+        xor eax, eax
+        // get # of bytes to alignment
+        mov diff, edi               // take start of row
+        add diff, 0xf               // add 7 + 8 to incr past
+                                        // alignment boundary
+        xor ebx, ebx
+        and diff, 0xfffffff8        // mask to alignment boundary
+        sub diff, edi               // subtract from start ==> value
+                                        //  ebx at alignment
+        jz dsubgo
+        // fix alignment
+dsublp1:
+        mov al, [esi+ebx]
+        add [edi+ebx], al
+        inc ebx
+        cmp ebx, diff
+        jb dsublp1
+dsubgo:
+        mov ecx, FullLength
+        mov edx, ecx
+        sub edx, ebx                  // subtract alignment fix
+        and edx, 0x00000007           // calc bytes over mult of 8
+        sub ecx, edx                  // drop over bytes from length
+        mov MMXLength, ecx
+   } // end _asm block
+
+   // 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 {
+            mov edi, row
+            movq mm7, ActiveMask  // Load ActiveMask for 2nd active byte group
+            mov esi, edi              // lp = row
+            add edi, bpp          // rp = row + bpp
+            movq mm6, mm7
+            mov ebx, diff
+            psllq mm6, ShiftBpp   // Move mask in mm6 to cover 3rd active
+                                  // byte group
+            // PRIME the pump (load the first Raw(x-bpp) data set
+            movq mm1, [edi+ebx-8]
+dsub3lp:
+            psrlq mm1, ShiftRem   // Shift data for adding 1st bpp bytes
+                          // no need for mask; shift clears inactive bytes
+            // Add 1st active group
+            movq mm0, [edi+ebx]
+            paddb mm0, mm1
+            // Add 2nd active group
+            movq mm1, mm0         // mov updated Raws to mm1
+            psllq mm1, ShiftBpp   // shift data to position correctly
+            pand mm1, mm7         // mask to use only 2nd active group
+            paddb mm0, mm1
+            // Add 3rd active group
+            movq mm1, mm0         // mov updated Raws to mm1
+            psllq mm1, ShiftBpp   // shift data to position correctly
+            pand mm1, mm6         // mask to use only 3rd active group
+            add ebx, 8
+            paddb mm0, mm1
+            cmp ebx, MMXLength
+            movq [edi+ebx-8], mm0     // Write updated Raws back to array
+            // Prep for doing 1st add at top of loop
+            movq mm1, mm0
+            jb dsub3lp
+         } // end _asm block
+      }
+      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 below
+         //
+         //         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 {
+            mov ebx, diff
+            mov edi, row
+            cmp ebx, FullLength
+            jnb dsub1end
+            mov esi, edi          // lp = row
+            xor eax, eax
+            add edi, bpp      // rp = row + bpp
+dsub1lp:
+            mov al, [esi+ebx]
+            add [edi+ebx], al
+            inc ebx
+            cmp ebx, FullLength
+            jb dsub1lp
+dsub1end:
+         } // end _asm block
+      }
+      return;
+
+      case 6:
+      case 7:
+      case 4:
+      case 5:
+      {
+         ShiftBpp.use = bpp << 3;
+         ShiftRem.use = 64 - ShiftBpp.use;
+         _asm {
+            mov edi, row
+            mov ebx, diff
+            mov esi, edi               // lp = row
+            add edi, bpp           // rp = row + bpp
+            // PRIME the pump (load the first Raw(x-bpp) data set
+            movq mm1, [edi+ebx-8]
+dsub4lp:
+            psrlq mm1, ShiftRem // Shift data for adding 1st bpp bytes
+                          // no need for mask; shift clears inactive bytes
+            movq mm0, [edi+ebx]
+            paddb mm0, mm1
+            // Add 2nd active group
+            movq mm1, mm0          // mov updated Raws to mm1
+            psllq mm1, ShiftBpp    // shift data to position correctly
+                                   // there is no need for any mask
+                                   // since shift clears inactive bits/bytes
+            add ebx, 8
+            paddb mm0, mm1
+            cmp ebx, MMXLength
+            movq [edi+ebx-8], mm0
+            movq mm1, mm0          // Prep for doing 1st add at top of loop
+            jb dsub4lp
+         } // end _asm block
+      }
+      break;
+
+      case 2:
+      {
+         ActiveMask.use  = 0x00000000ffff0000;
+         ShiftBpp.use = 16;       // == 2 * 8
+         ShiftRem.use = 48;       // == 64 - 16
+         _asm {
+            movq mm7, ActiveMask  // Load ActiveMask for 2nd active byte group
+            mov ebx, diff
+            movq mm6, mm7
+            mov edi, row
+            psllq mm6, ShiftBpp     // Move mask in mm6 to cover 3rd active
+                                    //  byte group
+            mov esi, edi            // lp = row
+            movq mm5, mm6
+            add edi, bpp            // rp = row + bpp
+            psllq mm5, ShiftBpp     // Move mask in mm5 to cover 4th active
+                                    //  byte group
+            // PRIME the pump (load the first Raw(x-bpp) data set
+            movq mm1, [edi+ebx-8]
+dsub2lp:
+            // Add 1st active group
+            psrlq mm1, ShiftRem     // Shift data for adding 1st bpp bytes
+                                    // no need for mask; shift clears inactive
+                                    //  bytes
+            movq mm0, [edi+ebx]
+            paddb mm0, mm1
+            // Add 2nd active group
+            movq mm1, mm0           // mov updated Raws to mm1
+            psllq mm1, ShiftBpp     // shift data to position correctly
+            pand mm1, mm7           // mask to use only 2nd active group
+            paddb mm0, mm1
+            // Add 3rd active group
+            movq mm1, mm0           // mov updated Raws to mm1
+            psllq mm1, ShiftBpp     // shift data to position correctly
+            pand mm1, mm6           // mask to use only 3rd active group
+            paddb mm0, mm1
+            // Add 4th active group
+            movq mm1, mm0           // mov updated Raws to mm1
+            psllq mm1, ShiftBpp     // shift data to position correctly
+            pand mm1, mm5           // mask to use only 4th active group
+            add ebx, 8
+            paddb mm0, mm1
+            cmp ebx, MMXLength
+            movq [edi+ebx-8], mm0   // Write updated Raws back to array
+            movq mm1, mm0           // Prep for doing 1st add at top of loop
+            jb dsub2lp
+         } // end _asm block
+      }
+      break;
+      case 8:
+      {
+         _asm {
+            mov edi, row
+            mov ebx, diff
+            mov esi, edi            // lp = row
+            add edi, bpp            // rp = row + bpp
+            mov ecx, MMXLength
+            movq mm7, [edi+ebx-8]   // PRIME the pump (load the first
+                                    // Raw(x-bpp) data set
+            and ecx, 0x0000003f     // calc bytes over mult of 64
+dsub8lp:
+            movq mm0, [edi+ebx]     // Load Sub(x) for 1st 8 bytes
+            paddb mm0, mm7
+            movq mm1, [edi+ebx+8]   // Load Sub(x) for 2nd 8 bytes
+            movq [edi+ebx], mm0    // 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 mm1, mm0
+            movq mm2, [edi+ebx+16]  // Load Sub(x) for 3rd 8 bytes
+            movq [edi+ebx+8], mm1   // Write Raw(x) for 2nd 8 bytes
+            paddb mm2, mm1
+            movq mm3, [edi+ebx+24]  // Load Sub(x) for 4th 8 bytes
+            movq [edi+ebx+16], mm2  // Write Raw(x) for 3rd 8 bytes
+            paddb mm3, mm2
+            movq mm4, [edi+ebx+32]  // Load Sub(x) for 5th 8 bytes
+            movq [edi+ebx+24], mm3  // Write Raw(x) for 4th 8 bytes
+            paddb mm4, mm3
+            movq mm5, [edi+ebx+40]  // Load Sub(x) for 6th 8 bytes
+            movq [edi+ebx+32], mm4  // Write Raw(x) for 5th 8 bytes
+            paddb mm5, mm4
+            movq mm6, [edi+ebx+48]  // Load Sub(x) for 7th 8 bytes
+            movq [edi+ebx+40], mm5  // Write Raw(x) for 6th 8 bytes
+            paddb mm6, mm5
+            movq mm7, [edi+ebx+56]  // Load Sub(x) for 8th 8 bytes
+            movq [edi+ebx+48], mm6  // Write Raw(x) for 7th 8 bytes
+            add ebx, 64
+            paddb mm7, mm6
+            cmp ebx, ecx
+            movq [edi+ebx-8], mm7   // Write Raw(x) for 8th 8 bytes
+            jb dsub8lp
+            cmp ebx, MMXLength
+            jnb dsub8lt8
+dsub8lpA:
+            movq mm0, [edi+ebx]
+            add ebx, 8
+            paddb mm0, mm7
+            cmp ebx, MMXLength
+            movq [edi+ebx-8], mm0   // use -8 to offset early add to ebx
+            movq mm7, mm0           // Move calculated Raw(x) data to mm1 to
+                                    // be the new Raw(x-bpp) for the next loop
+            jb dsub8lpA
+dsub8lt8:
+         } // end _asm block
+      }
+      break;
+
+      default:                // bpp greater than 8 bytes
+      {
+         _asm {
+            mov ebx, diff
+            mov edi, row
+            mov esi, edi           // lp = row
+            add edi, bpp           // rp = row + bpp
+dsubAlp:
+            movq mm0, [edi+ebx]
+            movq mm1, [esi+ebx]
+            add ebx, 8
+            paddb mm0, mm1
+            cmp ebx, MMXLength
+            movq [edi+ebx-8], mm0  // mov does not affect flags; -8 to offset
+                                   //  add ebx
+            jb dsubAlp
+         } // end _asm block
+      }
+      break;
+
+   } // end switch ( bpp )
+
+   _asm {
+        mov ebx, MMXLength
+        mov edi, row
+        cmp ebx, FullLength
+        jnb dsubend
+        mov esi, edi               // lp = row
+        xor eax, eax
+        add edi, bpp               // rp = row + bpp
+dsublp2:
+        mov al, [esi+ebx]
+        add [edi+ebx], al
+        inc ebx
+        cmp ebx, FullLength
+        jb dsublp2
+dsubend:
+        emms             // End MMX instructions; prep for possible FP instrs.
+   } // end _asm block
+}
+
+// Optimized code for PNG Up filter decoder
+void /* PRIVATE */
+png_read_filter_row_mmx_up(png_row_infop row_info, png_bytep row,
+   png_bytep prev_row)
+{
+   png_uint_32 len;
+   len  = row_info->rowbytes;       // # of bytes to filter
+   _asm {
+      mov edi, row
+      // get # of bytes to alignment
+      mov ecx, edi
+      xor ebx, ebx
+      add ecx, 0x7
+      xor eax, eax
+      and ecx, 0xfffffff8
+      mov esi, prev_row
+      sub ecx, edi
+      jz dupgo
+      // fix alignment
+duplp1:
+      mov al, [edi+ebx]
+      add al, [esi+ebx]
+      inc ebx
+      cmp ebx, ecx
+      mov [edi + ebx-1], al  // mov does not affect flags; -1 to offset inc ebx
+      jb duplp1
+dupgo:
+      mov ecx, len
+      mov edx, ecx
+      sub edx, ebx                  // subtract alignment fix
+      and edx, 0x0000003f           // calc bytes over mult of 64
+      sub ecx, edx                  // drop over bytes from length
+      // Unrolled loop - use all MMX registers and interleave to reduce
+      // number of branch instructions (loops) and reduce partial stalls
+duploop:
+      movq mm1, [esi+ebx]
+      movq mm0, [edi+ebx]
+      movq mm3, [esi+ebx+8]
+      paddb mm0, mm1
+      movq mm2, [edi+ebx+8]
+      movq [edi+ebx], mm0
+      paddb mm2, mm3
+      movq mm5, [esi+ebx+16]
+      movq [edi+ebx+8], mm2
+      movq mm4, [edi+ebx+16]
+      movq mm7, [esi+ebx+24]
+      paddb mm4, mm5
+      movq mm6, [edi+ebx+24]
+      movq [edi+ebx+16], mm4
+      paddb mm6, mm7
+      movq mm1, [esi+ebx+32]
+      movq [edi+ebx+24], mm6
+      movq mm0, [edi+ebx+32]
+      movq mm3, [esi+ebx+40]
+      paddb mm0, mm1
+      movq mm2, [edi+ebx+40]
+      movq [edi+ebx+32], mm0
+      paddb mm2, mm3
+      movq mm5, [esi+ebx+48]
+      movq [edi+ebx+40], mm2
+      movq mm4, [edi+ebx+48]
+      movq mm7, [esi+ebx+56]
+      paddb mm4, mm5
+      movq mm6, [edi+ebx+56]
+      movq [edi+ebx+48], mm4
+      add ebx, 64
+      paddb mm6, mm7
+      cmp ebx, ecx
+      movq [edi+ebx-8], mm6 // (+56)movq does not affect flags;
+                                     // -8 to offset add ebx
+      jb duploop
+
+      cmp edx, 0                     // Test for bytes over mult of 64
+      jz dupend
+
+
+      // 2 lines added by lcreeve@netins.net
+      // (mail 11 Jul 98 in png-implement list)
+      cmp edx, 8 //test for less than 8 bytes
+      jb duplt8
+
+
+      add ecx, edx
+      and edx, 0x00000007           // calc bytes over mult of 8
+      sub ecx, edx                  // drop over bytes from length
+      jz duplt8
+      // Loop using MMX registers mm0 & mm1 to update 8 bytes simultaneously
+duplpA:
+      movq mm1, [esi+ebx]
+      movq mm0, [edi+ebx]
+      add ebx, 8
+      paddb mm0, mm1
+      cmp ebx, ecx
+      movq [edi+ebx-8], mm0 // movq does not affect flags; -8 to offset add ebx
+      jb duplpA
+      cmp edx, 0            // Test for bytes over mult of 8
+      jz dupend
+duplt8:
+      xor eax, eax
+      add ecx, edx          // move over byte count into counter
+      // Loop using x86 registers to update remaining bytes
+duplp2:
+      mov al, [edi + ebx]
+      add al, [esi + ebx]
+      inc ebx
+      cmp ebx, ecx
+      mov [edi + ebx-1], al // mov does not affect flags; -1 to offset inc ebx
+      jb duplp2
+dupend:
+      // Conversion of filtered row completed
+      emms          // End MMX instructions; prep for possible FP instrs.
+   } // end _asm block
+}
+
+
+// Optimized png_read_filter_row routines
+void /* PRIVATE */
+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[10];
+#endif
+
+   if (mmx_supported == 2) {
+       png_mmx_support();
+   }
+
+#ifdef PNG_DEBUG
+   png_debug(1, "in png_read_filter_row\n");
+   switch (filter)
+   {
+      case 0: sprintf(filnm, "none");
+         break;
+      case 1: sprintf(filnm, "sub-%s", "MMX");
+         break;
+      case 2: sprintf(filnm, "up-%s", "MMX");
+         break;
+      case 3: sprintf(filnm, "avg-%s", "MMX");
+         break;
+      case 4: sprintf(filnm, "Paeth-%s", "MMX");
+         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 /* PNG_DEBUG */
+
+   switch (filter)
+   {
+      case PNG_FILTER_VALUE_NONE:
+         break;
+
+      case PNG_FILTER_VALUE_SUB:
+      {
+         if (
+             (row_info->pixel_depth >= PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT) &&
+             (row_info->rowbytes >= PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT))
+         {
+            png_read_filter_row_mmx_sub(row_info, row);
+         }
+         else
+         {
+            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++;
+            }
+         }
+         break;
+      }
+
+      case PNG_FILTER_VALUE_UP:
+      {
+         if (
+             (row_info->pixel_depth >= PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT) &&
+             (row_info->rowbytes >= PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT))
+         {
+            png_read_filter_row_mmx_up(row_info, row, prev_row);
+         }
+         else
+         {
+            png_uint_32 i;
+            png_uint_32 istop = row_info->rowbytes;
+            png_bytep rp = row;
+            png_bytep pp = prev_row;
+
+            for (i = 0; i < istop; ++i)
+            {
+               *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
+               rp++;
+            }
+         }
+         break;
+      }
+
+      case PNG_FILTER_VALUE_AVG:
+      {
+         if (
+             (row_info->pixel_depth >= PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT) &&
+             (row_info->rowbytes >= PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT))
+         {
+            png_read_filter_row_mmx_avg(row_info, row, prev_row);
+         }
+         else
+         {
+            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++;
+            }
+         }
+         break;
+      }
+
+      case PNG_FILTER_VALUE_PAETH:
+      {
+         if (
+             (row_info->pixel_depth >= PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT) &&
+             (row_info->rowbytes >= PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT))
+         {
+            png_read_filter_row_mmx_paeth(row_info, row, prev_row);
+         }
+         else
+         {
+            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++;
+            }
+         }
+         break;
+      }
+
+      default:
+         png_warning(png_ptr, "Ignoring bad row filter type");
+         *row=0;
+         break;
+   }
+}
+
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED && PNG_USE_PNGVCRD */
diff --git a/Utilities/ITK/Utilities/png/pngwio.c b/Utilities/ITK/Utilities/png/pngwio.c
new file mode 100644
index 0000000000..23f881e98e
--- /dev/null
+++ b/Utilities/ITK/Utilities/png/pngwio.c
@@ -0,0 +1,228 @@
+
+/* pngwio.c - functions for data output
+ *
+ * libpng 1.0.12 - June 8, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This file provides a location for all output.  Users who need
+ * special handling are expected to write functions that have the same
+ * arguments as these and perform similar functions, but that possibly
+ * use different output methods.  Note that you shouldn't change these
+ * functions, but rather write replacement functions and then change
+ * them at run time with png_set_write_fn(...).
+ */
+
+#define PNG_INTERNAL
+#include "png.h"
+#ifdef PNG_WRITE_SUPPORTED
+
+/* Write the data to whatever output you are using.  The default routine
+   writes to a file pointer.  Note that this routine sometimes gets called
+   with very small lengths, so you should implement some kind of simple
+   buffering if you are using unbuffered writes.  This should never be asked
+   to write more than 64K on a 16 bit machine.  */
+
+void /* PRIVATE */
+png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+   if (png_ptr->write_data_fn != NULL )
+      (*(png_ptr->write_data_fn))(png_ptr, data, length);
+   else
+      png_error(png_ptr, "Call to NULL write function");
+}
+
+#if !defined(PNG_NO_STDIO)
+/* This is the function that does the actual writing of data.  If you are
+   not writing to a standard C stream, you should create a replacement
+   write_data function and use it at run time with png_set_write_fn(), rather
+   than changing the library. */
+#ifndef USE_FAR_KEYWORD
+static void /* PRIVATE */
+png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+   png_uint_32 check;
+
+#if defined(_WIN32_WCE)
+   if ( !WriteFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) )
+      check = 0;
+#else
+   check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr));
+#endif
+   if (check != length)
+      png_error(png_ptr, "Write Error");
+}
+#else
+/* this is the model-independent version. Since the standard I/O library
+   can't handle far buffers in the medium and small models, we have to copy
+   the data.
+*/
+
+#define NEAR_BUF_SIZE 1024
+#define MIN(a,b) (a <= b ? a : b)
+
+static void /* PRIVATE */
+png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+   png_uint_32 check;
+   png_byte *near_data;  /* Needs to be "png_byte *" instead of "png_bytep" */
+   png_FILE_p io_ptr;
+
+   /* Check if data really is near. If so, use usual code. */
+   near_data = (png_byte *)CVT_PTR_NOCHECK(data);
+   io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
+   if ((png_bytep)near_data == data)
+   {
+#if defined(_WIN32_WCE)
+      if ( !WriteFile(io_ptr, near_data, length, &check, NULL) )
+         check = 0;
+#else
+      check = fwrite(near_data, 1, length, io_ptr);
+#endif
+   }
+   else
+   {
+      png_byte buf[NEAR_BUF_SIZE];
+      png_size_t written, remaining, err;
+      check = 0;
+      remaining = length;
+      do
+      {
+         written = MIN(NEAR_BUF_SIZE, remaining);
+         png_memcpy(buf, data, written); /* copy far buffer to near buffer */
+#if defined(_WIN32_WCE)
+         if ( !WriteFile(io_ptr, buf, written, &err, NULL) )
+            err = 0;
+#else
+         err = fwrite(buf, 1, written, io_ptr);
+#endif
+         if (err != written)
+            break;
+         else
+            check += err;
+         data += written;
+         remaining -= written;
+      }
+      while (remaining != 0);
+   }
+   if (check != length)
+      png_error(png_ptr, "Write Error");
+}
+
+#endif
+#endif
+
+/* This function is called to output any data pending writing (normally
+   to disk).  After png_flush is called, there should be no data pending
+   writing in any buffers. */
+#if defined(PNG_WRITE_FLUSH_SUPPORTED)
+void /* PRIVATE */
+png_flush(png_structp png_ptr)
+{
+   if (png_ptr->output_flush_fn != NULL)
+      (*(png_ptr->output_flush_fn))(png_ptr);
+}
+
+#if !defined(PNG_NO_STDIO)
+static void /* PRIVATE */
+png_default_flush(png_structp png_ptr)
+{
+#if !defined(_WIN32_WCE)
+   png_FILE_p io_ptr;
+   io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr));
+   if (io_ptr != NULL)
+      fflush(io_ptr);
+#endif
+}
+#endif
+#endif
+
+/* This function allows the application to supply new output functions for
+   libpng if standard C streams aren't being used.
+
+   This function takes as its arguments:
+   png_ptr       - pointer to a png output data structure
+   io_ptr        - pointer to user supplied structure containing info about
+                   the output functions.  May be NULL.
+   write_data_fn - pointer to a new output function that takes as its
+                   arguments a pointer to a png_struct, a pointer to
+                   data to be written, and a 32-bit unsigned int that is
+                   the number of bytes to be written.  The new write
+                   function should call png_error(png_ptr, "Error msg")
+                   to exit and output any fatal error messages.
+   flush_data_fn - pointer to a new flush function that takes as its
+                   arguments a pointer to a png_struct.  After a call to
+                   the flush function, there should be no data in any buffers
+                   or pending transmission.  If the output method doesn't do
+                   any buffering of ouput, a function prototype must still be
+                   supplied although it doesn't have to do anything.  If
+                   PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile
+                   time, output_flush_fn will be ignored, although it must be
+                   supplied for compatibility. */
+void PNGAPI
+png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
+   png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)
+{
+   png_ptr->io_ptr = io_ptr;
+
+#if !defined(PNG_NO_STDIO)
+   if (write_data_fn != NULL)
+      png_ptr->write_data_fn = write_data_fn;
+   else
+      png_ptr->write_data_fn = png_default_write_data;
+#else
+   png_ptr->write_data_fn = write_data_fn;
+#endif
+
+#if defined(PNG_WRITE_FLUSH_SUPPORTED)
+#if !defined(PNG_NO_STDIO)
+   if (output_flush_fn != NULL)
+      png_ptr->output_flush_fn = output_flush_fn;
+   else
+      png_ptr->output_flush_fn = png_default_flush;
+#else
+   png_ptr->output_flush_fn = output_flush_fn;
+#endif
+#endif /* PNG_WRITE_FLUSH_SUPPORTED */
+
+   /* It is an error to read while writing a png file */
+   if (png_ptr->read_data_fn != NULL)
+   {
+      png_ptr->read_data_fn = NULL;
+      png_warning(png_ptr,
+         "Attempted to set both read_data_fn and write_data_fn in");
+      png_warning(png_ptr,
+         "the same structure.  Resetting read_data_fn to NULL.");
+   }
+}
+
+#if defined(USE_FAR_KEYWORD)
+#if defined(_MSC_VER)
+void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check)
+{
+   void *near_ptr;
+   void FAR *far_ptr;
+   FP_OFF(near_ptr) = FP_OFF(ptr);
+   far_ptr = (void FAR *)near_ptr;
+   if(check != 0)
+      if(FP_SEG(ptr) != FP_SEG(far_ptr))
+         png_error(png_ptr,"segment lost in conversion");
+   return(near_ptr);
+}
+#  else
+void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check)
+{
+   void *near_ptr;
+   void FAR *far_ptr;
+   near_ptr = (void FAR *)ptr;
+   far_ptr = (void FAR *)near_ptr;
+   if(check != 0)
+      if(far_ptr != ptr)
+         png_error(png_ptr,"segment lost in conversion");
+   return(near_ptr);
+}
+#   endif
+#   endif
+#endif /* PNG_WRITE_SUPPORTED */
diff --git a/Utilities/ITK/Utilities/png/pngwrite.c b/Utilities/ITK/Utilities/png/pngwrite.c
new file mode 100644
index 0000000000..8350861a46
--- /dev/null
+++ b/Utilities/ITK/Utilities/png/pngwrite.c
@@ -0,0 +1,1447 @@
+
+/* pngwrite.c - general routines to write a PNG file
+ *
+ * libpng 1.0.12 - June 8, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ */
+
+/* get internal access to png.h */
+#define PNG_INTERNAL
+#include "png.h"
+#ifdef PNG_WRITE_SUPPORTED
+
+/* Writes all the PNG information.  This is the suggested way to use the
+ * library.  If you have a new chunk to add, make a function to write it,
+ * and put it in the correct location here.  If you want the chunk written
+ * after the image data, put it in png_write_end().  I strongly encourage
+ * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing
+ * the chunk, as that will keep the code from breaking if you want to just
+ * write a plain PNG file.  If you have long comments, I suggest writing
+ * them in png_write_end(), and compressing them.
+ */
+void PNGAPI
+png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr)
+{
+   png_debug(1, "in png_write_info_before_PLTE\n");
+   if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE))
+   {
+   png_write_sig(png_ptr); /* write PNG signature */
+#if defined(PNG_MNG_FEATURES_SUPPORTED)
+   if((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&(png_ptr->mng_features_permitted))
+   {
+      png_warning(png_ptr,"MNG features are not allowed in a PNG datastream\n");
+      png_ptr->mng_features_permitted=0;
+   }
+#endif
+   /* write IHDR information. */
+   png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height,
+      info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type,
+      info_ptr->filter_type,
+#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
+      info_ptr->interlace_type);
+#else
+      0);
+#endif
+   /* the rest of these check to see if the valid field has the appropriate
+      flag set, and if it does, writes the chunk. */
+#if defined(PNG_WRITE_gAMA_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_gAMA)
+   {
+#  ifdef PNG_FLOATING_POINT_SUPPORTED
+      png_write_gAMA(png_ptr, info_ptr->gamma);
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+      png_write_gAMA_fixed(png_ptr, info_ptr->int_gamma);
+#  endif
+#endif
+   }
+#endif
+#if defined(PNG_WRITE_sRGB_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_sRGB)
+      png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent);
+#endif
+#if defined(PNG_WRITE_iCCP_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_iCCP)
+      png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_COMPRESSION_TYPE_BASE,
+                     info_ptr->iccp_profile, (int)info_ptr->iccp_proflen);
+#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);
+#endif
+#if defined(PNG_WRITE_cHRM_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_cHRM)
+   {
+#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
+   }
+#endif
+#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
+   if (info_ptr->unknown_chunks_num)
+   {
+       png_unknown_chunk *up;
+
+       png_debug(5, "writing extra chunks\n");
+
+       for (up = info_ptr->unknown_chunks;
+            up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
+            up++)
+       {
+         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;
+   }
+}
+
+void PNGAPI
+png_write_info(png_structp png_ptr, png_infop info_ptr)
+{
+#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
+   int i;
+#endif
+
+   png_debug(1, "in png_write_info\n");
+
+   png_write_info_before_PLTE(png_ptr, info_ptr);
+
+   if (info_ptr->valid & PNG_INFO_PLTE)
+      png_write_PLTE(png_ptr, info_ptr->palette,
+         (png_uint_32)info_ptr->num_palette);
+   else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+      png_error(png_ptr, "Valid palette required for paletted images\n");
+
+#if defined(PNG_WRITE_tRNS_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_tRNS)
+      {
+#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
+         /* invert the alpha channel (in tRNS) */
+         if ((png_ptr->transformations & PNG_INVERT_ALPHA) &&
+            info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+         {
+            int j;
+            for (j=0; j<(int)info_ptr->num_trans; j++)
+               info_ptr->trans[j] = (png_byte)(255 - info_ptr->trans[j]);
+         }
+#endif
+      png_write_tRNS(png_ptr, info_ptr->trans, &(info_ptr->trans_values),
+         info_ptr->num_trans, info_ptr->color_type);
+      }
+#endif
+#if defined(PNG_WRITE_bKGD_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_bKGD)
+      png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type);
+#endif
+#if defined(PNG_WRITE_hIST_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_hIST)
+      png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette);
+#endif
+#if defined(PNG_WRITE_oFFs_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_oFFs)
+      png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset,
+         info_ptr->offset_unit_type);
+#endif
+#if defined(PNG_WRITE_pCAL_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_pCAL)
+      png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0,
+         info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams,
+         info_ptr->pcal_units, info_ptr->pcal_params);
+#endif
+#if defined(PNG_WRITE_sCAL_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_sCAL)
+#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO)
+      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);
+#else
+      png_warning(png_ptr,
+          "png_write_sCAL not supported; sCAL chunk not written.\n");
+#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,
+         info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type);
+#endif
+#if defined(PNG_WRITE_tIME_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_tIME)
+   {
+      png_write_tIME(png_ptr, &(info_ptr->mod_time));
+      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++)
+   {
+      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].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;
+      }
+      /* If we want a compressed text chunk */
+      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, 0,
+            info_ptr->text[i].compression);
+#else
+         png_warning(png_ptr, "Unable to write compressed text\n");
+#endif
+         /* Mark this chunk as written */
+         info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
+      }
+      else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
+      {
+#if defined(PNG_WRITE_tEXt_SUPPORTED)
+         /* write uncompressed chunk */
+         png_write_tEXt(png_ptr, info_ptr->text[i].key,
+                         info_ptr->text[i].text,
+                         0);
+#else
+         png_warning(png_ptr, "Unable to write uncompressed text\n");
+#endif
+         /* Mark this chunk as written */
+         info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
+      }
+   }
+#endif
+#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
+   if (info_ptr->unknown_chunks_num)
+   {
+       png_unknown_chunk *up;
+
+       png_debug(5, "writing extra chunks\n");
+
+       for (up = info_ptr->unknown_chunks;
+            up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
+            up++)
+       {
+         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
+}
+
+/* Writes the end of the PNG file.  If you don't want to write comments or
+ * time information, you can pass NULL for info.  If you already wrote these
+ * in png_write_info(), do not write them again here.  If you have long
+ * comments, I suggest writing them here, and compressing them.
+ */
+void PNGAPI
+png_write_end(png_structp png_ptr, png_infop info_ptr)
+{
+   png_debug(1, "in png_write_end\n");
+   if (!(png_ptr->mode & PNG_HAVE_IDAT))
+      png_error(png_ptr, "No IDATs written into file");
+
+   /* see if user wants us to write information chunks */
+   if (info_ptr != NULL)
+   {
+#if defined(PNG_WRITE_TEXT_SUPPORTED)
+      int i; /* local index variable */
+#endif
+#if defined(PNG_WRITE_tIME_SUPPORTED)
+      /* check to see if user has supplied a time chunk */
+      if ((info_ptr->valid & PNG_INFO_tIME) &&
+         !(png_ptr->mode & PNG_WROTE_tIME))
+         png_write_tIME(png_ptr, &(info_ptr->mod_time));
+#endif
+#if defined(PNG_WRITE_TEXT_SUPPORTED)
+      /* loop through comment chunks */
+      for (i = 0; i < info_ptr->num_text; i++)
+      {
+         png_debug2(2, "Writing trailer text chunk %d, type %d\n", i,
+            info_ptr->text[i].compression);
+         /* 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, 0,
+               info_ptr->text[i].compression);
+#else
+            png_warning(png_ptr, "Unable to write compressed text\n");
+#endif
+            /* Mark this chunk as written */
+            info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
+         }
+         else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
+         {
+#if defined(PNG_WRITE_tEXt_SUPPORTED)
+            /* write uncompressed chunk */
+            png_write_tEXt(png_ptr, info_ptr->text[i].key,
+               info_ptr->text[i].text, 0);
+#else
+            png_warning(png_ptr, "Unable to write uncompressed text\n");
+#endif
+
+            /* Mark this chunk as written */
+            info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
+         }
+      }
+#endif
+#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
+   if (info_ptr->unknown_chunks_num)
+   {
+       png_unknown_chunk *up;
+
+       png_debug(5, "writing extra chunks\n");
+
+       for (up = info_ptr->unknown_chunks;
+            up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
+            up++)
+       {
+         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
+   }
+
+   png_ptr->mode |= PNG_AFTER_IDAT;
+
+   /* write end of PNG file */
+   png_write_IEND(png_ptr);
+#if 0
+/* This flush, added in libpng-1.0.8,  causes some applications to crash
+   because they do not set png_ptr->output_flush_fn */
+   png_flush(png_ptr);
+#endif
+}
+
+#if defined(PNG_WRITE_tIME_SUPPORTED)
+#if !defined(_WIN32_WCE)
+/* "time.h" functions are not supported on WindowsCE */
+void PNGAPI
+png_convert_from_struct_tm(png_timep ptime, struct tm FAR * ttime)
+{
+   png_debug(1, "in png_convert_from_struct_tm\n");
+   ptime->year = (png_uint_16)(1900 + ttime->tm_year);
+   ptime->month = (png_byte)(ttime->tm_mon + 1);
+   ptime->day = (png_byte)ttime->tm_mday;
+   ptime->hour = (png_byte)ttime->tm_hour;
+   ptime->minute = (png_byte)ttime->tm_min;
+   ptime->second = (png_byte)ttime->tm_sec;
+}
+
+void PNGAPI
+png_convert_from_time_t(png_timep ptime, time_t ttime)
+{
+   struct tm *tbuf;
+
+   png_debug(1, "in png_convert_from_time_t\n");
+   tbuf = gmtime(&ttime);
+   png_convert_from_struct_tm(ptime, tbuf);
+}
+#endif
+#endif
+
+/* Initialize png_ptr structure, and allocate any memory needed */
+png_structp PNGAPI
+png_create_write_struct(png_const_charp user_png_ver, png_voidp error_ptr,
+   png_error_ptr error_fn, png_error_ptr warn_fn)
+{
+#ifdef PNG_USER_MEM_SUPPORTED
+   return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn,
+      warn_fn, NULL, NULL, NULL));
+}
+
+/* Alternate initialize png_ptr structure, and allocate any memory needed */
+png_structp PNGAPI
+png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
+   png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
+   png_malloc_ptr malloc_fn, png_free_ptr free_fn)
+{
+#endif /* PNG_USER_MEM_SUPPORTED */
+   png_structp png_ptr;
+#ifdef PNG_SETJMP_SUPPORTED
+#ifdef USE_FAR_KEYWORD
+   jmp_buf jmpbuf;
+#endif
+#endif
+   int i;
+   png_debug(1, "in png_create_write_struct\n");
+#ifdef PNG_USER_MEM_SUPPORTED
+   if ((png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,
+      (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr)) == NULL)
+#else
+   if ((png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG)) == NULL)
+#endif /* PNG_USER_MEM_SUPPORTED */
+   {
+      return ((png_structp)NULL);
+   }
+
+#ifdef PNG_SETJMP_SUPPORTED
+#ifdef USE_FAR_KEYWORD
+   if (setjmp(jmpbuf))
+#else
+   if (setjmp(png_ptr->jmpbuf))
+#endif
+   {
+      png_free(png_ptr, png_ptr->zbuf);
+      png_ptr->zbuf=NULL;
+      png_destroy_struct(png_ptr);
+      return ((png_structp)NULL);
+   }
+#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 */
+   png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
+
+   i=0;
+   do
+   {
+     if(user_png_ver[i] != png_libpng_ver[i])
+        png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
+   } while (png_libpng_ver[i++]);
+
+   if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH)
+   {
+     /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
+      * we must recompile any applications that use any older library version.
+      * For versions after libpng 1.0, we will be compatible, so we need
+      * only check the first digit.
+      */
+     if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] ||
+         (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) ||
+         (user_png_ver[0] == '0' && user_png_ver[2] < '9'))
+     {
+#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
+        char msg[80];
+        if (user_png_ver)
+        {
+          sprintf(msg, "Application was compiled with png.h from libpng-%.20s",
+             user_png_ver);
+          png_warning(png_ptr, msg);
+        }
+        sprintf(msg, "Application  is running with png.c from libpng-%.20s",
+           png_libpng_ver);
+        png_warning(png_ptr, msg);
+#endif
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+        png_ptr->flags=0;
+#endif
+        png_error(png_ptr,
+           "Incompatible libpng version in application and library");
+     }
+
+     /* Libpng 1.0.6 was not binary compatible, due to insertion of the
+        info_ptr->free_me member.  Libpng-1.0.1 and earlier were not
+        compatible due to insertion of the user transform function. Note
+        to maintainer: this test can be removed from version 1.2.0 and
+        beyond because the previous test would have already rejected it. */
+
+     if (user_png_ver[0] == '1' && user_png_ver[2] == '0' &&
+         (user_png_ver[4] <  '2' || user_png_ver[4] == '6') &&
+         user_png_ver[5] == '\0')
+     {
+#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
+        char msg[80];
+        if (user_png_ver)
+        {
+          sprintf(msg, "Application was compiled with png.h from libpng-%.20s",
+             user_png_ver);
+          png_warning(png_ptr, msg);
+        }
+        sprintf(msg, "Application  is running with png.c from libpng-%.20s",
+           png_libpng_ver);
+        png_warning(png_ptr, msg);
+#endif
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+        png_ptr->flags=0;
+#endif
+        png_error(png_ptr,
+        "Application must be recompiled; versions <= 1.0.6 were incompatible");
+     }
+   }
+
+   /* initialize zbuf - compression buffer */
+   png_ptr->zbuf_size = PNG_ZBUF_SIZE;
+   png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
+      (png_uint_32)png_ptr->zbuf_size);
+
+   png_set_write_fn(png_ptr, NULL, NULL, NULL);
+
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+   png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT,
+      1, NULL, NULL);
+#endif
+
+   return ((png_structp)png_ptr);
+}
+
+/* Initialize png_ptr structure, and allocate any memory needed */
+#undef png_write_init
+void PNGAPI
+itk_png_write_init(png_structp png_ptr)
+{
+   /* We only come here via pre-1.0.7-compiled applications */
+   png_write_init_2(png_ptr, "1.0.6 or earlier", 0, 0);
+}
+
+void PNGAPI
+png_write_init_2(png_structp png_ptr, png_const_charp user_png_ver,
+   png_size_t png_struct_size, png_size_t png_info_size)
+{
+   /* We only come here via pre-1.0.12-compiled applications */
+#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
+   if(sizeof(png_struct) > png_struct_size || sizeof(png_info) > png_info_size)
+   {
+      char msg[80];
+      png_ptr->warning_fn=(png_error_ptr)NULL;
+      if (user_png_ver)
+      {
+        sprintf(msg, "Application was compiled with png.h from libpng-%.20s",
+           user_png_ver);
+        png_warning(png_ptr, msg);
+      }
+      sprintf(msg, "Application  is running with png.c from libpng-%.20s",
+         png_libpng_ver);
+      png_warning(png_ptr, msg);
+   }
+#endif
+   if(sizeof(png_struct) > png_struct_size)
+     {
+       png_ptr->error_fn=(png_error_ptr)NULL;
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+       png_ptr->flags=0;
+#endif
+       png_error(png_ptr,
+       "The png struct allocated by the application for writing is too small.");
+     }
+   if(sizeof(png_info) > png_info_size)
+     {
+       png_ptr->error_fn=(png_error_ptr)NULL;
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+       png_ptr->flags=0;
+#endif
+       png_error(png_ptr,
+       "The info struct allocated by the application for writing is too small.");
+     }
+   png_write_init_3(&png_ptr, user_png_ver, png_struct_size);
+}
+
+
+void PNGAPI
+png_write_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver,
+   png_size_t png_struct_size)
+{
+   png_structp png_ptr=*ptr_ptr;
+#ifdef PNG_SETJMP_SUPPORTED
+   jmp_buf tmp_jmp; /* to save current jump buffer */
+#endif
+   int i = 0;
+   do
+   {
+     if (user_png_ver[i] != png_libpng_ver[i])
+     {
+#ifdef PNG_LEGACY_SUPPORTED
+       png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
+#else
+       png_ptr->warning_fn=(png_error_ptr)NULL;
+       png_warning(png_ptr,
+     "Application uses deprecated png_write_init() and should be recompiled.");
+       break;
+#endif
+     }
+   } while (png_libpng_ver[i++]);
+
+   png_debug(1, "in png_write_init_3\n");
+
+#ifdef PNG_SETJMP_SUPPORTED
+   /* save jump buffer and error functions */
+   png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
+#endif
+
+   if (sizeof(png_struct) > png_struct_size)
+     {
+       png_destroy_struct(png_ptr);
+       png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
+       *ptr_ptr = png_ptr;
+     }
+
+   /* 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
+
+   png_set_write_fn(png_ptr, NULL, NULL, NULL);
+
+   /* initialize zbuf - compression buffer */
+   png_ptr->zbuf_size = PNG_ZBUF_SIZE;
+   png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
+      (png_uint_32)png_ptr->zbuf_size);
+
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+   png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT,
+      1, NULL, NULL);
+#endif
+}
+
+/* Write a few rows of image data.  If the image is interlaced,
+ * either you will have to write the 7 sub images, or, if you
+ * have called png_set_interlace_handling(), you will have to
+ * "write" the image seven times.
+ */
+void PNGAPI
+png_write_rows(png_structp png_ptr, png_bytepp row,
+   png_uint_32 num_rows)
+{
+   png_uint_32 i; /* row counter */
+   png_bytepp rp; /* row pointer */
+
+   png_debug(1, "in png_write_rows\n");
+   /* loop through the rows */
+   for (i = 0, rp = row; i < num_rows; i++, rp++)
+   {
+      png_write_row(png_ptr, *rp);
+   }
+}
+
+/* Write the image.  You only need to call this function once, even
+ * if you are writing an interlaced image.
+ */
+void PNGAPI
+png_write_image(png_structp png_ptr, png_bytepp image)
+{
+   png_uint_32 i; /* row index */
+   int pass, num_pass; /* pass variables */
+   png_bytepp rp; /* points to current row */
+
+   png_debug(1, "in png_write_image\n");
+#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
+   /* intialize interlace handling.  If image is not interlaced,
+      this will set pass to 1 */
+   num_pass = png_set_interlace_handling(png_ptr);
+#else
+   num_pass = 1;
+#endif
+   /* loop through passes */
+   for (pass = 0; pass < num_pass; pass++)
+   {
+      /* loop through image */
+      for (i = 0, rp = image; i < png_ptr->height; i++, rp++)
+      {
+         png_write_row(png_ptr, *rp);
+      }
+   }
+}
+
+/* called by user to write a row of image data */
+void PNGAPI
+png_write_row(png_structp png_ptr, png_bytep row)
+{
+   png_debug2(1, "in png_write_row (row %ld, pass %d)\n",
+      png_ptr->row_number, png_ptr->pass);
+   /* initialize transformations and other stuff if first time */
+   if (png_ptr->row_number == 0 && png_ptr->pass == 0)
+   {
+   /* check for transforms that have been set but were defined out */
+#if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED)
+   if (png_ptr->transformations & PNG_INVERT_MONO)
+      png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined.");
+#endif
+#if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED)
+   if (png_ptr->transformations & PNG_FILLER)
+      png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined.");
+#endif
+#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && defined(PNG_READ_PACKSWAP_SUPPORTED)
+   if (png_ptr->transformations & PNG_PACKSWAP)
+      png_warning(png_ptr, "PNG_WRITE_PACKSWAP_SUPPORTED is not defined.");
+#endif
+#if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED)
+   if (png_ptr->transformations & PNG_PACK)
+      png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined.");
+#endif
+#if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED)
+   if (png_ptr->transformations & PNG_SHIFT)
+      png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined.");
+#endif
+#if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED)
+   if (png_ptr->transformations & PNG_BGR)
+      png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined.");
+#endif
+#if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED)
+   if (png_ptr->transformations & PNG_SWAP_BYTES)
+      png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined.");
+#endif
+
+      png_write_start_row(png_ptr);
+   }
+
+#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
+   /* if interlaced and not interested in row, return */
+   if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
+   {
+      switch (png_ptr->pass)
+      {
+         case 0:
+            if (png_ptr->row_number & 0x07)
+            {
+               png_write_finish_row(png_ptr);
+               return;
+            }
+            break;
+         case 1:
+            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 & 0x07) != 4)
+            {
+               png_write_finish_row(png_ptr);
+               return;
+            }
+            break;
+         case 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 & 0x03) != 2)
+            {
+               png_write_finish_row(png_ptr);
+               return;
+            }
+            break;
+         case 5:
+            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 & 0x01))
+            {
+               png_write_finish_row(png_ptr);
+               return;
+            }
+            break;
+      }
+   }
+#endif
+
+   /* set up row info for transformations */
+   png_ptr->row_info.color_type = png_ptr->color_type;
+   png_ptr->row_info.width = png_ptr->usr_width;
+   png_ptr->row_info.channels = png_ptr->usr_channels;
+   png_ptr->row_info.bit_depth = png_ptr->usr_bit_depth;
+   png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
+      png_ptr->row_info.channels);
+
+   png_ptr->row_info.rowbytes = ((png_ptr->row_info.width *
+      (png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3);
+
+   png_debug1(3, "row_info->color_type = %d\n", png_ptr->row_info.color_type);
+   png_debug1(3, "row_info->width = %lu\n", png_ptr->row_info.width);
+   png_debug1(3, "row_info->channels = %d\n", png_ptr->row_info.channels);
+   png_debug1(3, "row_info->bit_depth = %d\n", png_ptr->row_info.bit_depth);
+   png_debug1(3, "row_info->pixel_depth = %d\n", png_ptr->row_info.pixel_depth);
+   png_debug1(3, "row_info->rowbytes = %lu\n", png_ptr->row_info.rowbytes);
+
+   /* Copy user's row into buffer, leaving room for filter byte. */
+   png_memcpy_check(png_ptr, png_ptr->row_buf + 1, row,
+      png_ptr->row_info.rowbytes);
+
+#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
+   /* handle interlacing */
+   if (png_ptr->interlaced && png_ptr->pass < 6 &&
+      (png_ptr->transformations & PNG_INTERLACE))
+   {
+      png_do_write_interlace(&(png_ptr->row_info),
+         png_ptr->row_buf + 1, png_ptr->pass);
+      /* this should always get caught above, but still ... */
+      if (!(png_ptr->row_info.width))
+      {
+         png_write_finish_row(png_ptr);
+         return;
+      }
+   }
+#endif
+
+   /* handle other transformations */
+   if (png_ptr->transformations)
+      png_do_write_transformations(png_ptr);
+
+#if defined(PNG_MNG_FEATURES_SUPPORTED)
+   /* Write filter_method 64 (intrapixel differencing) only if
+    * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
+    * 2. Libpng did not write a PNG signature (this filter_method is only
+    *    used in PNG datastreams that are embedded in MNG datastreams) and
+    * 3. The application called png_permit_mng_features with a mask that
+    *    included PNG_FLAG_MNG_FILTER_64 and
+    * 4. The filter_method is 64 and
+    * 5. The color_type is RGB or RGBA
+    */
+   if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
+      (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))
+   {
+      /* Intrapixel differencing */
+      png_do_write_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1);
+   }
+#endif
+
+   /* Find a filter if necessary, filter the row and write it out. */
+   png_write_find_filter(png_ptr, &(png_ptr->row_info));
+
+   if (png_ptr->write_row_fn != NULL)
+      (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
+}
+
+#if defined(PNG_WRITE_FLUSH_SUPPORTED)
+/* Set the automatic flush interval or 0 to turn flushing off */
+void PNGAPI
+png_set_flush(png_structp png_ptr, int nrows)
+{
+   png_debug(1, "in png_set_flush\n");
+   png_ptr->flush_dist = (nrows < 0 ? 0 : nrows);
+}
+
+/* flush the current output buffers now */
+void PNGAPI
+png_write_flush(png_structp png_ptr)
+{
+   int wrote_IDAT;
+
+   png_debug(1, "in png_write_flush\n");
+   /* We have already written out all of the data */
+   if (png_ptr->row_number >= png_ptr->num_rows)
+     return;
+
+   do
+   {
+      int ret;
+
+      /* compress the data */
+      ret = deflate(&png_ptr->zstream, Z_SYNC_FLUSH);
+      wrote_IDAT = 0;
+
+      /* check for compression errors */
+      if (ret != Z_OK)
+      {
+         if (png_ptr->zstream.msg != NULL)
+            png_error(png_ptr, png_ptr->zstream.msg);
+         else
+            png_error(png_ptr, "zlib error");
+      }
+
+      if (!(png_ptr->zstream.avail_out))
+      {
+         /* write the IDAT and reset the zlib output buffer */
+         png_write_IDAT(png_ptr, png_ptr->zbuf,
+                        png_ptr->zbuf_size);
+         png_ptr->zstream.next_out = png_ptr->zbuf;
+         png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+         wrote_IDAT = 1;
+      }
+   } while(wrote_IDAT == 1);
+
+   /* If there is any data left to be output, write it into a new IDAT */
+   if (png_ptr->zbuf_size != png_ptr->zstream.avail_out)
+   {
+      /* write the IDAT and reset the zlib output buffer */
+      png_write_IDAT(png_ptr, png_ptr->zbuf,
+                     png_ptr->zbuf_size - png_ptr->zstream.avail_out);
+      png_ptr->zstream.next_out = png_ptr->zbuf;
+      png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+   }
+   png_ptr->flush_rows = 0;
+   png_flush(png_ptr);
+}
+#endif /* PNG_WRITE_FLUSH_SUPPORTED */
+
+/* free all memory used by the write */
+void PNGAPI
+png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
+{
+   png_structp png_ptr = NULL;
+   png_infop info_ptr = NULL;
+#ifdef PNG_USER_MEM_SUPPORTED
+   png_free_ptr free_fn = NULL;
+   png_voidp mem_ptr = NULL;
+#endif
+
+   png_debug(1, "in png_destroy_write_struct\n");
+   if (png_ptr_ptr != NULL)
+   {
+      png_ptr = *png_ptr_ptr;
+#ifdef PNG_USER_MEM_SUPPORTED
+      free_fn = png_ptr->free_fn;
+#endif
+   }
+
+   if (info_ptr_ptr != NULL)
+      info_ptr = *info_ptr_ptr;
+
+   if (info_ptr != NULL)
+   {
+      png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
+
+#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+      if (png_ptr->num_chunk_list)
+      {
+         png_free(png_ptr, png_ptr->chunk_list);
+         png_ptr->chunk_list=NULL;
+         png_ptr->num_chunk_list=0;
+      }
+#endif
+
+#ifdef PNG_USER_MEM_SUPPORTED
+      png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn,
+         (png_voidp)mem_ptr);
+#else
+      png_destroy_struct((png_voidp)info_ptr);
+#endif
+      *info_ptr_ptr = (png_infop)NULL;
+   }
+
+   if (png_ptr != NULL)
+   {
+      png_write_destroy(png_ptr);
+#ifdef PNG_USER_MEM_SUPPORTED
+      png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn,
+         (png_voidp)mem_ptr);
+#else
+      png_destroy_struct((png_voidp)png_ptr);
+#endif
+      *png_ptr_ptr = (png_structp)NULL;
+   }
+}
+
+
+/* Free any memory used in png_ptr struct (old method) */
+void /* PRIVATE */
+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;
+#ifdef PNG_USER_MEM_SUPPORTED
+   png_free_ptr free_fn;
+#endif
+
+   png_debug(1, "in png_write_destroy\n");
+   /* free any memory zlib uses */
+   deflateEnd(&png_ptr->zstream);
+
+   /* free our memory.  png_free checks NULL for us. */
+   png_free(png_ptr, png_ptr->zbuf);
+   png_free(png_ptr, png_ptr->row_buf);
+   png_free(png_ptr, png_ptr->prev_row);
+   png_free(png_ptr, png_ptr->sub_row);
+   png_free(png_ptr, png_ptr->up_row);
+   png_free(png_ptr, png_ptr->avg_row);
+   png_free(png_ptr, png_ptr->paeth_row);
+
+#if defined(PNG_TIME_RFC1123_SUPPORTED)
+   png_free(png_ptr, png_ptr->time_buffer);
+#endif
+
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+   png_free(png_ptr, png_ptr->prev_filters);
+   png_free(png_ptr, png_ptr->filter_weights);
+   png_free(png_ptr, png_ptr->inv_filter_weights);
+   png_free(png_ptr, png_ptr->filter_costs);
+   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;
+   error_ptr = png_ptr->error_ptr;
+#ifdef PNG_USER_MEM_SUPPORTED
+   free_fn = png_ptr->free_fn;
+#endif
+
+   png_memset(png_ptr, 0, sizeof (png_struct));
+
+   png_ptr->error_fn = error_fn;
+   png_ptr->warning_fn = warning_fn;
+   png_ptr->error_ptr = error_ptr;
+#ifdef PNG_USER_MEM_SUPPORTED
+   png_ptr->free_fn = free_fn;
+#endif
+
+#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. */
+void PNGAPI
+png_set_filter(png_structp png_ptr, int method, int filters)
+{
+   png_debug(1, "in png_set_filter\n");
+#if defined(PNG_MNG_FEATURES_SUPPORTED)
+   if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
+      (method == PNG_INTRAPIXEL_DIFFERENCING))
+         method = PNG_FILTER_TYPE_BASE;
+#endif
+   if (method == PNG_FILTER_TYPE_BASE)
+   {
+      switch (filters & (PNG_ALL_FILTERS | 0x07))
+      {
+         case 5:
+         case 6:
+         case 7: png_warning(png_ptr, "Unknown row filter for method 0");
+         case PNG_FILTER_VALUE_NONE:  png_ptr->do_filter=PNG_FILTER_NONE; break;
+         case PNG_FILTER_VALUE_SUB:   png_ptr->do_filter=PNG_FILTER_SUB;  break;
+         case PNG_FILTER_VALUE_UP:    png_ptr->do_filter=PNG_FILTER_UP;   break;
+         case PNG_FILTER_VALUE_AVG:   png_ptr->do_filter=PNG_FILTER_AVG;  break;
+         case PNG_FILTER_VALUE_PAETH: png_ptr->do_filter=PNG_FILTER_PAETH;break;
+         default: png_ptr->do_filter = (png_byte)filters; break;
+      }
+
+      /* If we have allocated the row_buf, this means we have already started
+       * with the image and we should have allocated all of the filter buffers
+       * that have been selected.  If prev_row isn't already allocated, then
+       * it is too late to start using the filters that need it, since we
+       * will be missing the data in the previous row.  If an application
+       * wants to start and stop using particular filters during compression,
+       * it should start out with all of the filters, and then add and
+       * remove them after the start of compression.
+       */
+      if (png_ptr->row_buf != 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->prev_row == NULL)
+            {
+               png_warning(png_ptr, "Can't add Up filter after starting");
+               png_ptr->do_filter &= ~PNG_FILTER_UP;
+            }
+            else
+            {
+               png_ptr->up_row = (png_bytep)png_malloc(png_ptr,
+                  (png_ptr->rowbytes + 1));
+               png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
+            }
+         }
+
+         if ((png_ptr->do_filter & PNG_FILTER_AVG) && png_ptr->avg_row == NULL)
+         {
+            if (png_ptr->prev_row == NULL)
+            {
+               png_warning(png_ptr, "Can't add Average filter after starting");
+               png_ptr->do_filter &= ~PNG_FILTER_AVG;
+            }
+            else
+            {
+               png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
+                  (png_ptr->rowbytes + 1));
+               png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
+            }
+         }
+
+         if ((png_ptr->do_filter & PNG_FILTER_PAETH) &&
+             png_ptr->paeth_row == NULL)
+         {
+            if (png_ptr->prev_row == NULL)
+            {
+               png_warning(png_ptr, "Can't add Paeth filter after starting");
+               png_ptr->do_filter &= (png_byte)(~PNG_FILTER_PAETH);
+            }
+            else
+            {
+               png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr,
+                  (png_ptr->rowbytes + 1));
+               png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
+            }
+         }
+
+         if (png_ptr->do_filter == PNG_NO_FILTERS)
+            png_ptr->do_filter = PNG_FILTER_NONE;
+      }
+   }
+   else
+      png_error(png_ptr, "Unknown custom filter method");
+}
+
+/* This allows us to influence the way in which libpng chooses the "best"
+ * filter for the current scanline.  While the "minimum-sum-of-absolute-
+ * differences metric is relatively fast and effective, there is some
+ * question as to whether it can be improved upon by trying to keep the
+ * filtered data going to zlib more consistent, hopefully resulting in
+ * better compression.
+ */
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)      /* GRR 970116 */
+void PNGAPI
+png_set_filter_heuristics(png_structp png_ptr, int heuristic_method,
+   int num_weights, png_doublep filter_weights,
+   png_doublep filter_costs)
+{
+   int i;
+
+   png_debug(1, "in png_set_filter_heuristics\n");
+   if (heuristic_method >= PNG_FILTER_HEURISTIC_LAST)
+   {
+      png_warning(png_ptr, "Unknown filter heuristic method");
+      return;
+   }
+
+   if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT)
+   {
+      heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED;
+   }
+
+   if (num_weights < 0 || filter_weights == NULL ||
+      heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED)
+   {
+      num_weights = 0;
+   }
+
+   png_ptr->num_prev_filters = (png_byte)num_weights;
+   png_ptr->heuristic_method = (png_byte)heuristic_method;
+
+   if (num_weights > 0)
+   {
+      if (png_ptr->prev_filters == NULL)
+      {
+         png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr,
+            (png_uint_32)(sizeof(png_byte) * num_weights));
+
+         /* To make sure that the weighting starts out fairly */
+         for (i = 0; i < num_weights; i++)
+         {
+            png_ptr->prev_filters[i] = 255;
+         }
+      }
+
+      if (png_ptr->filter_weights == NULL)
+      {
+         png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr,
+            (png_uint_32)(sizeof(png_uint_16) * num_weights));
+
+         png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr,
+            (png_uint_32)(sizeof(png_uint_16) * num_weights));
+         for (i = 0; i < num_weights; i++)
+         {
+            png_ptr->inv_filter_weights[i] =
+            png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR;
+         }
+      }
+
+      for (i = 0; i < num_weights; i++)
+      {
+         if (filter_weights[i] < 0.0)
+         {
+            png_ptr->inv_filter_weights[i] =
+            png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR;
+         }
+         else
+         {
+            png_ptr->inv_filter_weights[i] =
+               (png_uint_16)((double)PNG_WEIGHT_FACTOR*filter_weights[i]+0.5);
+            png_ptr->filter_weights[i] =
+               (png_uint_16)((double)PNG_WEIGHT_FACTOR/filter_weights[i]+0.5);
+         }
+      }
+   }
+
+   /* If, in the future, there are other filter methods, this would
+    * need to be based on png_ptr->filter.
+    */
+   if (png_ptr->filter_costs == NULL)
+   {
+      png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr,
+         (png_uint_32)(sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST));
+
+      png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr,
+         (png_uint_32)(sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST));
+
+      for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
+      {
+         png_ptr->inv_filter_costs[i] =
+         png_ptr->filter_costs[i] = PNG_COST_FACTOR;
+      }
+   }
+
+   /* Here is where we set the relative costs of the different filters.  We
+    * should take the desired compression level into account when setting
+    * the costs, so that Paeth, for instance, has a high relative cost at low
+    * compression levels, while it has a lower relative cost at higher
+    * compression settings.  The filter types are in order of increasing
+    * relative cost, so it would be possible to do this with an algorithm.
+    */
+   for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
+   {
+      if (filter_costs == NULL || filter_costs[i] < 0.0)
+      {
+         png_ptr->inv_filter_costs[i] =
+         png_ptr->filter_costs[i] = PNG_COST_FACTOR;
+      }
+      else if (filter_costs[i] >= 1.0)
+      {
+         png_ptr->inv_filter_costs[i] =
+            (png_uint_16)((double)PNG_COST_FACTOR / filter_costs[i] + 0.5);
+         png_ptr->filter_costs[i] =
+            (png_uint_16)((double)PNG_COST_FACTOR * filter_costs[i] + 0.5);
+      }
+   }
+}
+#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */
+
+void PNGAPI
+png_set_compression_level(png_structp png_ptr, int level)
+{
+   png_debug(1, "in png_set_compression_level\n");
+   png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL;
+   png_ptr->zlib_level = level;
+}
+
+void PNGAPI
+png_set_compression_mem_level(png_structp png_ptr, int mem_level)
+{
+   png_debug(1, "in png_set_compression_mem_level\n");
+   png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL;
+   png_ptr->zlib_mem_level = mem_level;
+}
+
+void PNGAPI
+png_set_compression_strategy(png_structp png_ptr, int strategy)
+{
+   png_debug(1, "in png_set_compression_strategy\n");
+   png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY;
+   png_ptr->zlib_strategy = strategy;
+}
+
+void PNGAPI
+png_set_compression_window_bits(png_structp png_ptr, int window_bits)
+{
+   if (window_bits > 15)
+      png_warning(png_ptr, "Only compression windows <= 32k supported by PNG");
+   else if (window_bits < 8)
+      png_warning(png_ptr, "Only compression windows >= 256 supported by PNG");
+#ifndef WBITS_8_OK
+   /* avoid libpng bug with 256-byte windows */
+   if (window_bits == 8)
+     {
+       png_warning(png_ptr, "Compression window is being reset to 512");
+       window_bits=9;
+     }
+#endif
+   png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS;
+   png_ptr->zlib_window_bits = window_bits;
+}
+
+void PNGAPI
+png_set_compression_method(png_structp png_ptr, int method)
+{
+   png_debug(1, "in png_set_compression_method\n");
+   if (method != 8)
+      png_warning(png_ptr, "Only compression method 8 is supported by PNG");
+   png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_METHOD;
+   png_ptr->zlib_method = method;
+}
+
+void PNGAPI
+png_set_write_status_fn(png_structp png_ptr, png_write_status_ptr write_row_fn)
+{
+   png_ptr->write_row_fn = write_row_fn;
+}
+
+#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
+void PNGAPI
+png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
+   write_user_transform_fn)
+{
+   png_debug(1, "in png_set_write_user_transform_fn\n");
+   png_ptr->transformations |= PNG_USER_TRANSFORM;
+   png_ptr->write_user_transform_fn = write_user_transform_fn;
+}
+#endif
+
+
+#if defined(PNG_INFO_IMAGE_SUPPORTED)
+void PNGAPI
+png_write_png(png_structp png_ptr, png_infop info_ptr,
+              int transforms, voidp params)
+{
+#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);
+
+   if(transforms == 0 || params == NULL)
+      /* quiet compiler warnings */ return;
+}
+#endif
+#endif /* PNG_WRITE_SUPPORTED */
diff --git a/Utilities/ITK/Utilities/png/pngwtran.c b/Utilities/ITK/Utilities/png/pngwtran.c
new file mode 100644
index 0000000000..3cc60672ac
--- /dev/null
+++ b/Utilities/ITK/Utilities/png/pngwtran.c
@@ -0,0 +1,563 @@
+
+/* pngwtran.c - transforms the data in a row for PNG writers
+ *
+ * libpng 1.0.12 - June 8, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ */
+
+#define PNG_INTERNAL
+#include "png.h"
+#ifdef PNG_WRITE_SUPPORTED
+
+/* Transform the data according to the user's wishes.  The order of
+ * transformations is significant.
+ */
+void /* PRIVATE */
+png_do_write_transformations(png_structp png_ptr)
+{
+   png_debug(1, "in png_do_write_transformations\n");
+
+   if (png_ptr == NULL)
+      return;
+
+#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
+   if (png_ptr->transformations & PNG_USER_TRANSFORM)
+      if(png_ptr->write_user_transform_fn != NULL)
+        (*(png_ptr->write_user_transform_fn)) /* user write transform function */
+          (png_ptr,                    /* png_ptr */
+           &(png_ptr->row_info),       /* row_info:     */
+             /*  png_uint_32 width;          width of row */
+             /*  png_uint_32 rowbytes;       number of bytes in row */
+             /*  png_byte color_type;        color type of pixels */
+             /*  png_byte bit_depth;         bit depth of samples */
+             /*  png_byte channels;          number of channels (1-4) */
+             /*  png_byte pixel_depth;       bits per pixel (depth*channels) */
+           png_ptr->row_buf + 1);      /* start of pixel data for row */
+#endif
+#if defined(PNG_WRITE_FILLER_SUPPORTED)
+   if (png_ptr->transformations & PNG_FILLER)
+      png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
+         png_ptr->flags);
+#endif
+#if defined(PNG_WRITE_PACKSWAP_SUPPORTED)
+   if (png_ptr->transformations & PNG_PACKSWAP)
+      png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+#if defined(PNG_WRITE_PACK_SUPPORTED)
+   if (png_ptr->transformations & PNG_PACK)
+      png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1,
+         (png_uint_32)png_ptr->bit_depth);
+#endif
+#if defined(PNG_WRITE_SWAP_SUPPORTED)
+   if (png_ptr->transformations & PNG_SWAP_BYTES)
+      png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+#if defined(PNG_WRITE_SHIFT_SUPPORTED)
+   if (png_ptr->transformations & PNG_SHIFT)
+      png_do_shift(&(png_ptr->row_info), png_ptr->row_buf + 1,
+         &(png_ptr->shift));
+#endif
+#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
+   if (png_ptr->transformations & PNG_INVERT_ALPHA)
+      png_do_write_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
+   if (png_ptr->transformations & PNG_SWAP_ALPHA)
+      png_do_write_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+#if defined(PNG_WRITE_BGR_SUPPORTED)
+   if (png_ptr->transformations & PNG_BGR)
+      png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+#if defined(PNG_WRITE_INVERT_SUPPORTED)
+   if (png_ptr->transformations & PNG_INVERT_MONO)
+      png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+}
+
+#if defined(PNG_WRITE_PACK_SUPPORTED)
+/* Pack pixels into bytes.  Pass the true bit depth in bit_depth.  The
+ * row_info bit depth should be 8 (one pixel per byte).  The channels
+ * should be 1 (this only happens on grayscale and paletted images).
+ */
+void /* PRIVATE */
+png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
+{
+   png_debug(1, "in png_do_pack\n");
+   if (row_info->bit_depth == 8 &&
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+       row != NULL && row_info != NULL &&
+#endif
+      row_info->channels == 1)
+   {
+      switch ((int)bit_depth)
+      {
+         case 1:
+         {
+            png_bytep sp, dp;
+            int mask, v;
+            png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
+
+            sp = row;
+            dp = row;
+            mask = 0x80;
+            v = 0;
+
+            for (i = 0; i < row_width; i++)
+            {
+               if (*sp != 0)
+                  v |= mask;
+               sp++;
+               if (mask > 1)
+                  mask >>= 1;
+               else
+               {
+                  mask = 0x80;
+                  *dp = (png_byte)v;
+                  dp++;
+                  v = 0;
+               }
+            }
+            if (mask != 0x80)
+               *dp = (png_byte)v;
+            break;
+         }
+         case 2:
+         {
+            png_bytep sp, dp;
+            int shift, v;
+            png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
+
+            sp = row;
+            dp = row;
+            shift = 6;
+            v = 0;
+            for (i = 0; i < row_width; i++)
+            {
+               png_byte value;
+
+               value = (png_byte)(*sp & 0x03);
+               v |= (value << shift);
+               if (shift == 0)
+               {
+                  shift = 6;
+                  *dp = (png_byte)v;
+                  dp++;
+                  v = 0;
+               }
+               else
+                  shift -= 2;
+               sp++;
+            }
+            if (shift != 6)
+               *dp = (png_byte)v;
+            break;
+         }
+         case 4:
+         {
+            png_bytep sp, dp;
+            int shift, v;
+            png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
+
+            sp = row;
+            dp = row;
+            shift = 4;
+            v = 0;
+            for (i = 0; i < row_width; i++)
+            {
+               png_byte value;
+
+               value = (png_byte)(*sp & 0x0f);
+               v |= (value << shift);
+
+               if (shift == 0)
+               {
+                  shift = 4;
+                  *dp = (png_byte)v;
+                  dp++;
+                  v = 0;
+               }
+               else
+                  shift -= 4;
+
+               sp++;
+            }
+            if (shift != 4)
+               *dp = (png_byte)v;
+            break;
+         }
+      }
+      row_info->bit_depth = (png_byte)bit_depth;
+      row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels);
+      row_info->rowbytes =
+         ((row_info->width * row_info->pixel_depth + 7) >> 3);
+   }
+}
+#endif
+
+#if defined(PNG_WRITE_SHIFT_SUPPORTED)
+/* Shift pixel values to take advantage of whole range.  Pass the
+ * true number of bits in bit_depth.  The row should be packed
+ * according to row_info->bit_depth.  Thus, if you had a row of
+ * bit depth 4, but the pixels only had values from 0 to 7, you
+ * would pass 3 as bit_depth, and this routine would translate the
+ * data to 0 to 15.
+ */
+void /* PRIVATE */
+png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
+{
+   png_debug(1, "in png_do_shift\n");
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   if (row != NULL && row_info != NULL &&
+#else
+   if (
+#endif
+      row_info->color_type != PNG_COLOR_TYPE_PALETTE)
+   {
+      int shift_start[4], shift_dec[4];
+      int channels = 0;
+
+      if (row_info->color_type & PNG_COLOR_MASK_COLOR)
+      {
+         shift_start[channels] = row_info->bit_depth - bit_depth->red;
+         shift_dec[channels] = bit_depth->red;
+         channels++;
+         shift_start[channels] = row_info->bit_depth - bit_depth->green;
+         shift_dec[channels] = bit_depth->green;
+         channels++;
+         shift_start[channels] = row_info->bit_depth - bit_depth->blue;
+         shift_dec[channels] = bit_depth->blue;
+         channels++;
+      }
+      else
+      {
+         shift_start[channels] = row_info->bit_depth - bit_depth->gray;
+         shift_dec[channels] = bit_depth->gray;
+         channels++;
+      }
+      if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
+      {
+         shift_start[channels] = row_info->bit_depth - bit_depth->alpha;
+         shift_dec[channels] = bit_depth->alpha;
+         channels++;
+      }
+
+      /* with low row depths, could only be grayscale, so one channel */
+      if (row_info->bit_depth < 8)
+      {
+         png_bytep bp = row;
+         png_uint_32 i;
+         png_byte mask;
+         png_uint_32 row_bytes = row_info->rowbytes;
+
+         if (bit_depth->gray == 1 && row_info->bit_depth == 2)
+            mask = 0x55;
+         else if (row_info->bit_depth == 4 && bit_depth->gray == 3)
+            mask = 0x11;
+         else
+            mask = 0xff;
+
+         for (i = 0; i < row_bytes; i++, bp++)
+         {
+            png_uint_16 v;
+            int j;
+
+            v = *bp;
+            *bp = 0;
+            for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0])
+            {
+               if (j > 0)
+                  *bp |= (png_byte)((v << j) & 0xff);
+               else
+                  *bp |= (png_byte)((v >> (-j)) & mask);
+            }
+         }
+      }
+      else if (row_info->bit_depth == 8)
+      {
+         png_bytep bp = row;
+         png_uint_32 i;
+         png_uint_32 istop = channels * row_info->width;
+
+         for (i = 0; i < istop; i++, bp++)
+         {
+
+            png_uint_16 v;
+            int j;
+            int c = (int)(i%channels);
+
+            v = *bp;
+            *bp = 0;
+            for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
+            {
+               if (j > 0)
+                  *bp |= (png_byte)((v << j) & 0xff);
+               else
+                  *bp |= (png_byte)((v >> (-j)) & 0xff);
+            }
+         }
+      }
+      else
+      {
+         png_bytep bp;
+         png_uint_32 i;
+         png_uint_32 istop = channels * row_info->width;
+
+         for (bp = row, i = 0; i < istop; i++)
+         {
+            int c = (int)(i%channels);
+            png_uint_16 value, v;
+            int j;
+
+            v = (png_uint_16)(((png_uint_16)(*bp) << 8) + *(bp + 1));
+            value = 0;
+            for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
+            {
+               if (j > 0)
+                  value |= (png_uint_16)((v << j) & (png_uint_16)0xffff);
+               else
+                  value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff);
+            }
+            *bp++ = (png_byte)(value >> 8);
+            *bp++ = (png_byte)(value & 0xff);
+         }
+      }
+   }
+}
+#endif
+
+#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
+void /* PRIVATE */
+png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
+{
+   png_debug(1, "in png_do_write_swap_alpha\n");
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   if (row != NULL && row_info != NULL)
+#endif
+   {
+      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+      {
+         /* This converts from ARGB to RGBA */
+         if (row_info->bit_depth == 8)
+         {
+            png_bytep sp, dp;
+            png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
+            for (i = 0, sp = dp = row; i < row_width; i++)
+            {
+               png_byte save = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = save;
+            }
+         }
+         /* This converts from AARRGGBB to RRGGBBAA */
+         else
+         {
+            png_bytep sp, dp;
+            png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
+
+            for (i = 0, sp = dp = row; i < row_width; i++)
+            {
+               png_byte save[2];
+               save[0] = *(sp++);
+               save[1] = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = save[0];
+               *(dp++) = save[1];
+            }
+         }
+      }
+      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+      {
+         /* This converts from AG to GA */
+         if (row_info->bit_depth == 8)
+         {
+            png_bytep sp, dp;
+            png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
+
+            for (i = 0, sp = dp = row; i < row_width; i++)
+            {
+               png_byte save = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = save;
+            }
+         }
+         /* This converts from AAGG to GGAA */
+         else
+         {
+            png_bytep sp, dp;
+            png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
+
+            for (i = 0, sp = dp = row; i < row_width; i++)
+            {
+               png_byte save[2];
+               save[0] = *(sp++);
+               save[1] = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = save[0];
+               *(dp++) = save[1];
+            }
+         }
+      }
+   }
+}
+#endif
+
+#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
+void /* PRIVATE */
+png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
+{
+   png_debug(1, "in png_do_write_invert_alpha\n");
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   if (row != NULL && row_info != NULL)
+#endif
+   {
+      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+      {
+         /* This inverts the alpha channel in RGBA */
+         if (row_info->bit_depth == 8)
+         {
+            png_bytep sp, dp;
+            png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
+            for (i = 0, sp = dp = row; i < row_width; i++)
+            {
+               *(dp++) = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = (png_byte)(255 - *(sp++));
+            }
+         }
+         /* This inverts the alpha channel in RRGGBBAA */
+         else
+         {
+            png_bytep sp, dp;
+            png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
+
+            for (i = 0, sp = dp = row; i < row_width; i++)
+            {
+               *(dp++) = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = (png_byte)(255 - *(sp++));
+               *(dp++) = (png_byte)(255 - *(sp++));
+            }
+         }
+      }
+      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+      {
+         /* This inverts the alpha channel in GA */
+         if (row_info->bit_depth == 8)
+         {
+            png_bytep sp, dp;
+            png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
+
+            for (i = 0, sp = dp = row; i < row_width; i++)
+            {
+               *(dp++) = *(sp++);
+               *(dp++) = (png_byte)(255 - *(sp++));
+            }
+         }
+         /* This inverts the alpha channel in GGAA */
+         else
+         {
+            png_bytep sp, dp;
+            png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
+
+            for (i = 0, sp = dp = row; i < row_width; i++)
+            {
+               *(dp++) = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = (png_byte)(255 - *(sp++));
+               *(dp++) = (png_byte)(255 - *(sp++));
+            }
+         }
+      }
+   }
+}
+#endif
+
+#if defined(PNG_MNG_FEATURES_SUPPORTED)
+/* undoes intrapixel differencing  */
+void /* PRIVATE */
+png_do_write_intrapixel(png_row_infop row_info, png_bytep row)
+{
+   png_debug(1, "in png_do_write_intrapixel\n");
+   if (
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+       row != NULL && row_info != NULL &&
+#endif
+       (row_info->color_type & PNG_COLOR_MASK_COLOR))
+   {
+      int bytes_per_pixel;
+      png_uint_32 row_width = row_info->width;
+      if (row_info->bit_depth == 8)
+      {
+         png_bytep rp;
+         png_uint_32 i;
+
+         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+            bytes_per_pixel = 3;
+         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+            bytes_per_pixel = 4;
+         else
+            return;
+
+         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
+         {
+            *(rp)   = (png_byte)((*rp     - *(rp+1))&0xff);
+            *(rp+2) = (png_byte)((*(rp+2) - *(rp+1))&0xff);
+         }
+      }
+      else if (row_info->bit_depth == 16)
+      {
+         png_bytep rp;
+         png_uint_32 i;
+
+         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+            bytes_per_pixel = 6;
+         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+            bytes_per_pixel = 8;
+         else
+            return;
+
+         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
+         {
+            png_uint_32 s0=*(rp  )<<8 | *(rp+1);
+            png_uint_32 s1=*(rp+2)<<8 | *(rp+3);
+            png_uint_32 s2=*(rp+4)<<8 | *(rp+5);
+            png_uint_32 red=(s0-s1)&0xffff;
+            png_uint_32 blue=(s2-s1)&0xffff;
+            *(rp  ) = (png_byte)((red>>8)&0xff);
+            *(rp+1) = (png_byte)(red&0xff);
+            *(rp+4) = (png_byte)((blue>>8)&0xff);
+            *(rp+5) = (png_byte)(blue&0xff);
+         }
+      }
+   }
+}
+#endif /* PNG_MNG_FEATURES_SUPPORTED */
+#endif /* PNG_WRITE_SUPPORTED */
diff --git a/Utilities/ITK/Utilities/png/pngwutil.c b/Utilities/ITK/Utilities/png/pngwutil.c
new file mode 100644
index 0000000000..a1db9c2913
--- /dev/null
+++ b/Utilities/ITK/Utilities/png/pngwutil.c
@@ -0,0 +1,2646 @@
+
+/* pngwutil.c - utilities to write a PNG file
+ *
+ * libpng 1.0.12 - June 8, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ */
+
+#define PNG_INTERNAL
+#include "png.h"
+#ifdef PNG_WRITE_SUPPORTED
+
+/* Place a 32-bit number into a buffer in PNG byte order.  We work
+ * with unsigned numbers for convenience, although one supported
+ * ancillary chunk uses signed (two's complement) numbers.
+ */
+void /* PRIVATE */
+png_save_uint_32(png_bytep buf, png_uint_32 i)
+{
+   buf[0] = (png_byte)((i >> 24) & 0xff);
+   buf[1] = (png_byte)((i >> 16) & 0xff);
+   buf[2] = (png_byte)((i >> 8) & 0xff);
+   buf[3] = (png_byte)(i & 0xff);
+}
+
+#if defined(PNG_WRITE_pCAL_SUPPORTED)
+/* The png_save_int_32 function assumes integers are stored in two's
+ * complement format.  If this isn't the case, then this routine needs to
+ * be modified to write data in two's complement format.
+ */
+void /* PRIVATE */
+png_save_int_32(png_bytep buf, png_int_32 i)
+{
+   buf[0] = (png_byte)((i >> 24) & 0xff);
+   buf[1] = (png_byte)((i >> 16) & 0xff);
+   buf[2] = (png_byte)((i >> 8) & 0xff);
+   buf[3] = (png_byte)(i & 0xff);
+}
+#endif
+
+/* Place a 16-bit number into a buffer in PNG byte order.
+ * The parameter is declared unsigned int, not png_uint_16,
+ * just to avoid potential problems on pre-ANSI C compilers.
+ */
+void /* PRIVATE */
+png_save_uint_16(png_bytep buf, unsigned int i)
+{
+   buf[0] = (png_byte)((i >> 8) & 0xff);
+   buf[1] = (png_byte)(i & 0xff);
+}
+
+/* Write a PNG chunk all at once.  The type is an array of ASCII characters
+ * representing the chunk name.  The array must be at least 4 bytes in
+ * length, and does not need to be null terminated.  To be safe, pass the
+ * pre-defined chunk names here, and if you need a new one, define it
+ * where the others are defined.  The length is the length of the data.
+ * All the data must be present.  If that is not possible, use the
+ * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end()
+ * functions instead.
+ */
+void PNGAPI
+png_write_chunk(png_structp png_ptr, png_bytep chunk_name,
+   png_bytep data, png_size_t length)
+{
+   png_write_chunk_start(png_ptr, chunk_name, (png_uint_32)length);
+   png_write_chunk_data(png_ptr, data, length);
+   png_write_chunk_end(png_ptr);
+}
+
+/* Write the start of a PNG chunk.  The type is the chunk type.
+ * The total_length is the sum of the lengths of all the data you will be
+ * passing in png_write_chunk_data().
+ */
+void PNGAPI
+png_write_chunk_start(png_structp png_ptr, png_bytep chunk_name,
+   png_uint_32 length)
+{
+   png_byte buf[4];
+   png_debug2(0, "Writing %s chunk (%lu bytes)\n", chunk_name, length);
+
+   /* write the length */
+   png_save_uint_32(buf, length);
+   png_write_data(png_ptr, buf, (png_size_t)4);
+
+   /* write the chunk name */
+   png_write_data(png_ptr, chunk_name, (png_size_t)4);
+   /* reset the crc and run it over the chunk name */
+   png_reset_crc(png_ptr);
+   png_calculate_crc(png_ptr, chunk_name, (png_size_t)4);
+}
+
+/* Write the data of a PNG chunk started with png_write_chunk_start().
+ * Note that multiple calls to this function are allowed, and that the
+ * sum of the lengths from these calls *must* add up to the total_length
+ * given to png_write_chunk_start().
+ */
+void PNGAPI
+png_write_chunk_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+   /* write the data, and run the CRC over it */
+   if (data != NULL && length > 0)
+   {
+      png_calculate_crc(png_ptr, data, length);
+      png_write_data(png_ptr, data, length);
+   }
+}
+
+/* Finish a chunk started with png_write_chunk_start(). */
+void PNGAPI
+png_write_chunk_end(png_structp png_ptr)
+{
+   png_byte buf[4];
+
+   /* write the crc */
+   png_save_uint_32(buf, png_ptr->crc);
+
+   png_write_data(png_ptr, buf, (png_size_t)4);
+}
+
+/* Simple function to write the signature.  If we have already written
+ * the magic bytes of the signature, or more likely, the PNG stream is
+ * being embedded into another stream and doesn't need its own signature,
+ * we should call png_set_sig_bytes() to tell libpng how many of the
+ * bytes have already been written.
+ */
+void /* PRIVATE */
+png_write_sig(png_structp png_ptr)
+{
+   png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
+   /* write the rest of the 8 byte signature */
+   png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes],
+      (png_size_t)8 - png_ptr->sig_bytes);
+   if(png_ptr->sig_bytes < 3)
+      png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE;
+}
+
+#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.
+ * The compression_state structure is shared context for these functions
+ * set up by the caller in order to make the whole mess thread-safe.
+ */
+
+typedef struct
+{
+    char *input;   /* the uncompressed input data */
+    int input_len;   /* its length */
+    int num_output_ptr; /* number of output pointers used */
+    int max_output_ptr; /* size of output_ptr */
+    png_charpp output_ptr; /* array of pointers to output */
+} compression_state;
+
+/* compress given text into storage in the png_ptr structure */
+static int /* PRIVATE */
+png_text_compress(png_structp png_ptr,
+        png_charp text, png_size_t text_len, int compression,
+        compression_state *comp)
+{
+   int ret;
+
+   comp->num_output_ptr = comp->max_output_ptr = 0;
+   comp->output_ptr = NULL;
+   comp->input = NULL;
+
+   /* we may just want to pass the text right through */
+   if (compression == PNG_TEXT_COMPRESSION_NONE)
+   {
+       comp->input = text;
+       comp->input_len = text_len;
+       return((int)text_len);
+   }
+
+   if (compression >= PNG_TEXT_COMPRESSION_LAST)
+   {
+#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
+      char msg[50];
+      sprintf(msg, "Unknown compression type %d", compression);
+      png_warning(png_ptr, msg);
+#else
+      png_warning(png_ptr, "Unknown compression type");
+#endif
+   }
+
+   /* We can't write the chunk until we find out how much data we have,
+    * which means we need to run the compressor first and save the
+    * output.  This shouldn't be a problem, as the vast majority of
+    * comments should be reasonable, but we will set up an array of
+    * malloc'd pointers to be sure.
+    *
+    * If we knew the application was well behaved, we could simplify this
+    * greatly by assuming we can always malloc an output buffer large
+    * enough to hold the compressed text ((1001 * text_len / 1000) + 12)
+    * and malloc this directly.  The only time this would be a bad idea is
+    * if we can't malloc more than 64K and we have 64K of random input
+    * data, or if the input string is incredibly large (although this
+    * wouldn't cause a failure, just a slowdown due to swapping).
+    */
+
+   /* set up the compression buffers */
+   png_ptr->zstream.avail_in = (uInt)text_len;
+   png_ptr->zstream.next_in = (Bytef *)text;
+   png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+   png_ptr->zstream.next_out = (Bytef *)png_ptr->zbuf;
+
+   /* this is the same compression loop as in png_write_row() */
+   do
+   {
+      /* compress the data */
+      ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
+      if (ret != Z_OK)
+      {
+         /* error */
+         if (png_ptr->zstream.msg != NULL)
+            png_error(png_ptr, png_ptr->zstream.msg);
+         else
+            png_error(png_ptr, "zlib error");
+      }
+      /* check to see if we need more room */
+      if (!png_ptr->zstream.avail_out && png_ptr->zstream.avail_in)
+      {
+         /* make sure the output array has room */
+         if (comp->num_output_ptr >= comp->max_output_ptr)
+         {
+            int old_max;
+
+            old_max = comp->max_output_ptr;
+            comp->max_output_ptr = comp->num_output_ptr + 4;
+            if (comp->output_ptr != NULL)
+            {
+               png_charpp old_ptr;
+
+               old_ptr = comp->output_ptr;
+               comp->output_ptr = (png_charpp)png_malloc(png_ptr,
+                  (png_uint_32)(comp->max_output_ptr * sizeof (png_charpp)));
+               png_memcpy(comp->output_ptr, old_ptr, old_max
+                  * sizeof (png_charp));
+               png_free(png_ptr, old_ptr);
+            }
+            else
+               comp->output_ptr = (png_charpp)png_malloc(png_ptr,
+                  (png_uint_32)(comp->max_output_ptr * sizeof (png_charp)));
+         }
+
+         /* save the data */
+         comp->output_ptr[comp->num_output_ptr] = (png_charp)png_malloc(png_ptr,
+            (png_uint_32)png_ptr->zbuf_size);
+         png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
+            png_ptr->zbuf_size);
+         comp->num_output_ptr++;
+
+         /* and reset the buffer */
+         png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+         png_ptr->zstream.next_out = png_ptr->zbuf;
+      }
+   /* continue until we don't have any more to compress */
+   } while (png_ptr->zstream.avail_in);
+
+   /* finish the compression */
+   do
+   {
+      /* tell zlib we are finished */
+      ret = deflate(&png_ptr->zstream, Z_FINISH);
+
+      if (ret == Z_OK)
+      {
+         /* check to see if we need more room */
+         if (!(png_ptr->zstream.avail_out))
+         {
+            /* check to make sure our output array has room */
+            if (comp->num_output_ptr >= comp->max_output_ptr)
+            {
+               int old_max;
+
+               old_max = comp->max_output_ptr;
+               comp->max_output_ptr = comp->num_output_ptr + 4;
+               if (comp->output_ptr != NULL)
+               {
+                  png_charpp old_ptr;
+
+                  old_ptr = comp->output_ptr;
+                  /* This could be optimized to realloc() */
+                  comp->output_ptr = (png_charpp)png_malloc(png_ptr,
+                     (png_uint_32)(comp->max_output_ptr * sizeof (png_charpp)));
+                  png_memcpy(comp->output_ptr, old_ptr,
+                     old_max * sizeof (png_charp));
+                  png_free(png_ptr, old_ptr);
+               }
+               else
+                  comp->output_ptr = (png_charpp)png_malloc(png_ptr,
+                     (png_uint_32)(comp->max_output_ptr * sizeof (png_charp)));
+            }
+
+            /* save off the data */
+            comp->output_ptr[comp->num_output_ptr] =
+               (png_charp)png_malloc(png_ptr, (png_uint_32)png_ptr->zbuf_size);
+            png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
+               png_ptr->zbuf_size);
+            comp->num_output_ptr++;
+
+            /* and reset the buffer pointers */
+            png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+            png_ptr->zstream.next_out = png_ptr->zbuf;
+         }
+      }
+      else if (ret != Z_STREAM_END)
+      {
+         /* we got an error */
+         if (png_ptr->zstream.msg != NULL)
+            png_error(png_ptr, png_ptr->zstream.msg);
+         else
+            png_error(png_ptr, "zlib error");
+      }
+   } while (ret != Z_STREAM_END);
+
+   /* text length is number of buffers plus last buffer */
+   text_len = png_ptr->zbuf_size * comp->num_output_ptr;
+   if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
+      text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out;
+
+   return((int)text_len);
+}
+
+/* ship the compressed text out via chunk writes */
+static void /* PRIVATE */
+png_write_compressed_data_out(png_structp png_ptr, compression_state *comp)
+{
+   int i;
+
+   /* handle the no-compression case */
+   if (comp->input)
+   {
+       png_write_chunk_data(png_ptr, (png_bytep)comp->input, comp->input_len);
+       return;
+   }
+
+   /* 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_free(png_ptr, comp->output_ptr[i]);
+      comp->output_ptr[i]=NULL;
+   }
+   if (comp->max_output_ptr != 0)
+      png_free(png_ptr, comp->output_ptr);
+      comp->output_ptr=NULL;
+   /* write anything left in zbuf */
+   if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size)
+      png_write_chunk_data(png_ptr, png_ptr->zbuf,
+         png_ptr->zbuf_size - png_ptr->zstream.avail_out);
+
+   /* reset zlib for another zTXt/iTXt or the image data */
+   deflateReset(&png_ptr->zstream);
+
+}
+#endif
+
+/* Write the IHDR chunk, and update the png_struct with the necessary
+ * information.  Note that the rest of this code depends upon this
+ * information being correct.
+ */
+void /* PRIVATE */
+png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
+   int bit_depth, int color_type, int compression_type, int filter_type,
+   int interlace_type)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_IHDR;
+#endif
+   png_byte buf[13]; /* buffer to store the IHDR info */
+
+   png_debug(1, "in png_write_IHDR\n");
+   /* Check that we have valid input data from the application info */
+   switch (color_type)
+   {
+      case PNG_COLOR_TYPE_GRAY:
+         switch (bit_depth)
+         {
+            case 1:
+            case 2:
+            case 4:
+            case 8:
+            case 16: png_ptr->channels = 1; break;
+            default: png_error(png_ptr,"Invalid bit depth for grayscale image");
+         }
+         break;
+      case PNG_COLOR_TYPE_RGB:
+         if (bit_depth != 8 && bit_depth != 16)
+            png_error(png_ptr, "Invalid bit depth for RGB image");
+         png_ptr->channels = 3;
+         break;
+      case PNG_COLOR_TYPE_PALETTE:
+         switch (bit_depth)
+         {
+            case 1:
+            case 2:
+            case 4:
+            case 8: png_ptr->channels = 1; break;
+            default: png_error(png_ptr, "Invalid bit depth for paletted image");
+         }
+         break;
+      case PNG_COLOR_TYPE_GRAY_ALPHA:
+         if (bit_depth != 8 && bit_depth != 16)
+            png_error(png_ptr, "Invalid bit depth for grayscale+alpha image");
+         png_ptr->channels = 2;
+         break;
+      case PNG_COLOR_TYPE_RGB_ALPHA:
+         if (bit_depth != 8 && bit_depth != 16)
+            png_error(png_ptr, "Invalid bit depth for RGBA image");
+         png_ptr->channels = 4;
+         break;
+      default:
+         png_error(png_ptr, "Invalid image color type specified");
+   }
+
+   if (compression_type != PNG_COMPRESSION_TYPE_BASE)
+   {
+      png_warning(png_ptr, "Invalid compression type specified");
+      compression_type = PNG_COMPRESSION_TYPE_BASE;
+   }
+
+   /* Write filter_method 64 (intrapixel differencing) only if
+    * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
+    * 2. Libpng did not write a PNG signature (this filter_method is only
+    *    used in PNG datastreams that are embedded in MNG datastreams) and
+    * 3. The application called png_permit_mng_features with a mask that
+    *    included PNG_FLAG_MNG_FILTER_64 and
+    * 4. The filter_method is 64 and
+    * 5. The color_type is RGB or RGBA
+    */
+   if (
+#if defined(PNG_MNG_FEATURES_SUPPORTED)
+      !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
+      ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&
+      (color_type == PNG_COLOR_TYPE_RGB ||
+       color_type == PNG_COLOR_TYPE_RGB_ALPHA) &&
+      (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) &&
+#endif
+      filter_type != PNG_FILTER_TYPE_BASE)
+   {
+      png_warning(png_ptr, "Invalid filter type specified");
+      filter_type = PNG_FILTER_TYPE_BASE;
+   }
+
+#ifdef PNG_WRITE_INTERLACING_SUPPORTED
+   if (interlace_type != PNG_INTERLACE_NONE &&
+      interlace_type != PNG_INTERLACE_ADAM7)
+   {
+      png_warning(png_ptr, "Invalid interlace type specified");
+      interlace_type = PNG_INTERLACE_ADAM7;
+   }
+#else
+   interlace_type=PNG_INTERLACE_NONE;
+#endif
+
+   /* save off the relevent information */
+   png_ptr->bit_depth = (png_byte)bit_depth;
+   png_ptr->color_type = (png_byte)color_type;
+   png_ptr->interlaced = (png_byte)interlace_type;
+#if defined(PNG_MNG_FEATURES_SUPPORTED)
+   png_ptr->filter_type = (png_byte)filter_type;
+#endif
+   png_ptr->width = width;
+   png_ptr->height = height;
+
+   png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels);
+   png_ptr->rowbytes = ((width * (png_size_t)png_ptr->pixel_depth + 7) >> 3);
+   /* set the usr info, so any transformations can modify it */
+   png_ptr->usr_width = png_ptr->width;
+   png_ptr->usr_bit_depth = png_ptr->bit_depth;
+   png_ptr->usr_channels = png_ptr->channels;
+
+   /* pack the header information into the buffer */
+   png_save_uint_32(buf, width);
+   png_save_uint_32(buf + 4, height);
+   buf[8] = (png_byte)bit_depth;
+   buf[9] = (png_byte)color_type;
+   buf[10] = (png_byte)compression_type;
+   buf[11] = (png_byte)filter_type;
+   buf[12] = (png_byte)interlace_type;
+
+   /* write the chunk */
+   png_write_chunk(png_ptr, (png_bytep)png_IHDR, buf, (png_size_t)13);
+
+   /* initialize zlib with PNG info */
+   png_ptr->zstream.zalloc = png_zalloc;
+   png_ptr->zstream.zfree = png_zfree;
+   png_ptr->zstream.opaque = (voidpf)png_ptr;
+   if (!(png_ptr->do_filter))
+   {
+      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
+         png_ptr->bit_depth < 8)
+         png_ptr->do_filter = PNG_FILTER_NONE;
+      else
+         png_ptr->do_filter = PNG_ALL_FILTERS;
+   }
+   if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY))
+   {
+      if (png_ptr->do_filter != PNG_FILTER_NONE)
+         png_ptr->zlib_strategy = Z_FILTERED;
+      else
+         png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY;
+   }
+   if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL))
+      png_ptr->zlib_level = Z_DEFAULT_COMPRESSION;
+   if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL))
+      png_ptr->zlib_mem_level = 8;
+   if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS))
+      png_ptr->zlib_window_bits = 15;
+   if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD))
+      png_ptr->zlib_method = 8;
+   deflateInit2(&png_ptr->zstream, png_ptr->zlib_level,
+      png_ptr->zlib_method, png_ptr->zlib_window_bits,
+      png_ptr->zlib_mem_level, png_ptr->zlib_strategy);
+   png_ptr->zstream.next_out = png_ptr->zbuf;
+   png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+
+   png_ptr->mode = PNG_HAVE_IHDR;
+}
+
+/* write the palette.  We are careful not to trust png_color to be in the
+ * correct order for PNG, so people can redefine it to any convenient
+ * structure.
+ */
+void /* PRIVATE */
+png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_PLTE;
+#endif
+   png_uint_32 i;
+   png_colorp pal_ptr;
+   png_byte buf[3];
+
+   png_debug(1, "in png_write_PLTE\n");
+   if ((
+#if defined(PNG_MNG_FEATURES_SUPPORTED) || \
+    defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED)
+        !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) &&
+#endif
+        num_pal == 0) || num_pal > 256)
+   {
+     if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+     {
+        png_error(png_ptr, "Invalid number of colors in palette");
+     }
+     else
+     {
+        png_warning(png_ptr, "Invalid number of colors in palette");
+        return;
+     }
+   }
+
+   if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
+   {
+      png_warning(png_ptr,
+        "Ignoring request to write a PLTE chunk in grayscale PNG");
+      return;
+   }
+
+   png_ptr->num_palette = (png_uint_16)num_pal;
+   png_debug1(3, "num_palette = %d\n", png_ptr->num_palette);
+
+   png_write_chunk_start(png_ptr, (png_bytep)png_PLTE, num_pal * 3);
+#ifndef PNG_NO_POINTER_INDEXING
+   for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++)
+   {
+      buf[0] = pal_ptr->red;
+      buf[1] = pal_ptr->green;
+      buf[2] = pal_ptr->blue;
+      png_write_chunk_data(png_ptr, buf, (png_size_t)3);
+   }
+#else
+   /* This is a little slower but some buggy compilers need to do this instead */
+   pal_ptr=palette;
+   for (i = 0; i < num_pal; i++)
+   {
+      buf[0] = pal_ptr[i].red;
+      buf[1] = pal_ptr[i].green;
+      buf[2] = pal_ptr[i].blue;
+      png_write_chunk_data(png_ptr, buf, (png_size_t)3);
+   }
+#endif
+   png_write_chunk_end(png_ptr);
+   png_ptr->mode |= PNG_HAVE_PLTE;
+}
+
+/* write an IDAT chunk */
+void /* PRIVATE */
+png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_IDAT;
+#endif
+   png_debug(1, "in png_write_IDAT\n");
+   png_write_chunk(png_ptr, (png_bytep)png_IDAT, data, length);
+   png_ptr->mode |= PNG_HAVE_IDAT;
+}
+
+/* write an IEND chunk */
+void /* PRIVATE */
+png_write_IEND(png_structp png_ptr)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_IEND;
+#endif
+   png_debug(1, "in png_write_IEND\n");
+   png_write_chunk(png_ptr, (png_bytep)png_IEND, NULL, (png_size_t)0);
+   png_ptr->mode |= PNG_HAVE_IEND;
+}
+
+#if defined(PNG_WRITE_gAMA_SUPPORTED)
+/* write a gAMA chunk */
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+void /* PRIVATE */
+png_write_gAMA(png_structp png_ptr, double file_gamma)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_gAMA;
+#endif
+   png_uint_32 igamma;
+   png_byte buf[4];
+
+   png_debug(1, "in png_write_gAMA\n");
+   /* file_gamma is saved in 1/100,000ths */
+   igamma = (png_uint_32)(file_gamma * 100000.0 + 0.5);
+   png_save_uint_32(buf, igamma);
+   png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4);
+}
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+void /* PRIVATE */
+png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_gAMA;
+#endif
+   png_byte buf[4];
+
+   png_debug(1, "in png_write_gAMA\n");
+   /* 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);
+}
+#endif
+#endif
+
+#if defined(PNG_WRITE_sRGB_SUPPORTED)
+/* write a sRGB chunk */
+void /* PRIVATE */
+png_write_sRGB(png_structp png_ptr, int srgb_intent)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_sRGB;
+#endif
+   png_byte buf[1];
+
+   png_debug(1, "in png_write_sRGB\n");
+   if(srgb_intent >= PNG_sRGB_INTENT_LAST)
+         png_warning(png_ptr,
+            "Invalid sRGB rendering intent specified");
+   buf[0]=(png_byte)srgb_intent;
+   png_write_chunk(png_ptr, (png_bytep)png_sRGB, buf, (png_size_t)1);
+}
+#endif
+
+#if defined(PNG_WRITE_iCCP_SUPPORTED)
+/* write an iCCP chunk */
+void /* PRIVATE */
+png_write_iCCP(png_structp png_ptr, png_charp name, int compression_type,
+   png_charp profile, int profile_len)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_iCCP;
+#endif
+   png_size_t name_len;
+   png_charp new_name;
+   compression_state comp;
+
+   png_debug(1, "in png_write_iCCP\n");
+   if (name == NULL || (name_len = png_check_keyword(png_ptr, name,
+      &new_name)) == 0)
+   {
+      png_warning(png_ptr, "Empty keyword in iCCP chunk");
+      return;
+   }
+
+   if (compression_type != PNG_COMPRESSION_TYPE_BASE)
+      png_warning(png_ptr, "Unknown compression type in iCCP chunk");
+
+   if (profile == NULL)
+      profile_len = 0;
+
+   if (profile_len)
+       profile_len = png_text_compress(png_ptr, profile, (png_size_t)profile_len,
+          PNG_COMPRESSION_TYPE_BASE, &comp);
+
+   /* make sure we include the NULL after the name and the compression type */
+   png_write_chunk_start(png_ptr, (png_bytep)png_iCCP,
+          (png_uint_32)name_len+profile_len+2);
+   new_name[name_len+1]=0x00;
+   png_write_chunk_data(png_ptr, (png_bytep)new_name, name_len + 2);
+
+   if (profile_len)
+      png_write_compressed_data_out(png_ptr, &comp);
+
+   png_write_chunk_end(png_ptr);
+   png_free(png_ptr, new_name);
+}
+#endif
+
+#if defined(PNG_WRITE_sPLT_SUPPORTED)
+/* write a sPLT chunk */
+void /* PRIVATE */
+png_write_sPLT(png_structp png_ptr, png_sPLT_tp spalette)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_sPLT;
+#endif
+   png_size_t name_len;
+   png_charp new_name;
+   png_byte entrybuf[10];
+   int entry_size = (spalette->depth == 8 ? 6 : 10);
+   int palette_size = entry_size * spalette->nentries;
+   png_sPLT_entryp ep;
+#ifdef PNG_NO_POINTER_INDEXING
+   int i;
+#endif
+
+   png_debug(1, "in png_write_sPLT\n");
+   if (spalette->name == NULL || (name_len = png_check_keyword(png_ptr,
+      spalette->name, &new_name))==0)
+   {
+      png_warning(png_ptr, "Empty keyword in sPLT chunk");
+      return;
+   }
+
+   /* make sure we include the NULL after the name */
+   png_write_chunk_start(png_ptr, (png_bytep)png_sPLT,
+          (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 */
+#ifndef PNG_NO_POINTER_INDEXING
+   for (ep = spalette->entries; ep<spalette->entries+spalette->nentries; ep++)
+   {
+       if (spalette->depth == 8)
+       {
+           entrybuf[0] = (png_byte)ep->red;
+           entrybuf[1] = (png_byte)ep->green;
+           entrybuf[2] = (png_byte)ep->blue;
+           entrybuf[3] = (png_byte)ep->alpha;
+           png_save_uint_16(entrybuf + 4, ep->frequency);
+       }
+       else
+       {
+           png_save_uint_16(entrybuf + 0, ep->red);
+           png_save_uint_16(entrybuf + 2, ep->green);
+           png_save_uint_16(entrybuf + 4, ep->blue);
+           png_save_uint_16(entrybuf + 6, ep->alpha);
+           png_save_uint_16(entrybuf + 8, ep->frequency);
+       }
+       png_write_chunk_data(png_ptr, entrybuf, entry_size);
+   }
+#else
+   ep=spalette->entries;
+   for (i=0; i>spalette->nentries; i++)
+   {
+       if (spalette->depth == 8)
+       {
+           entrybuf[0] = (png_byte)ep[i].red;
+           entrybuf[1] = (png_byte)ep[i].green;
+           entrybuf[2] = (png_byte)ep[i].blue;
+           entrybuf[3] = (png_byte)ep[i].alpha;
+           png_save_uint_16(entrybuf + 4, ep[i].frequency);
+       }
+       else
+       {
+           png_save_uint_16(entrybuf + 0, ep[i].red);
+           png_save_uint_16(entrybuf + 2, ep[i].green);
+           png_save_uint_16(entrybuf + 4, ep[i].blue);
+           png_save_uint_16(entrybuf + 6, ep[i].alpha);
+           png_save_uint_16(entrybuf + 8, ep[i].frequency);
+       }
+       png_write_chunk_data(png_ptr, entrybuf, entry_size);
+   }
+#endif
+
+   png_write_chunk_end(png_ptr);
+   png_free(png_ptr, new_name);
+}
+#endif
+
+#if defined(PNG_WRITE_sBIT_SUPPORTED)
+/* write the sBIT chunk */
+void /* PRIVATE */
+png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_sBIT;
+#endif
+   png_byte buf[4];
+   png_size_t size;
+
+   png_debug(1, "in png_write_sBIT\n");
+   /* make sure we don't depend upon the order of PNG_COLOR_8 */
+   if (color_type & PNG_COLOR_MASK_COLOR)
+   {
+      png_byte maxbits;
+
+      maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 :
+                png_ptr->usr_bit_depth);
+      if (sbit->red == 0 || sbit->red > maxbits ||
+          sbit->green == 0 || sbit->green > maxbits ||
+          sbit->blue == 0 || sbit->blue > maxbits)
+      {
+         png_warning(png_ptr, "Invalid sBIT depth specified");
+         return;
+      }
+      buf[0] = sbit->red;
+      buf[1] = sbit->green;
+      buf[2] = sbit->blue;
+      size = 3;
+   }
+   else
+   {
+      if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth)
+      {
+         png_warning(png_ptr, "Invalid sBIT depth specified");
+         return;
+      }
+      buf[0] = sbit->gray;
+      size = 1;
+   }
+
+   if (color_type & PNG_COLOR_MASK_ALPHA)
+   {
+      if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth)
+      {
+         png_warning(png_ptr, "Invalid sBIT depth specified");
+         return;
+      }
+      buf[size++] = sbit->alpha;
+   }
+
+   png_write_chunk(png_ptr, (png_bytep)png_sBIT, buf, size);
+}
+#endif
+
+#if defined(PNG_WRITE_cHRM_SUPPORTED)
+/* write the cHRM chunk */
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+void /* PRIVATE */
+png_write_cHRM(png_structp png_ptr, double white_x, double white_y,
+   double red_x, double red_y, double green_x, double green_y,
+   double blue_x, double blue_y)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_cHRM;
+#endif
+   png_byte buf[32];
+   png_uint_32 itemp;
+
+   png_debug(1, "in png_write_cHRM\n");
+   /* 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");
+#if !defined(PNG_NO_CONSOLE_IO)
+      fprintf(stderr,"white_x=%f, white_y=%f\n",white_x, white_y);
+#endif
+      return;
+   }
+   itemp = (png_uint_32)(white_x * 100000.0 + 0.5);
+   png_save_uint_32(buf, itemp);
+   itemp = (png_uint_32)(white_y * 100000.0 + 0.5);
+   png_save_uint_32(buf + 4, itemp);
+
+   if (red_x < 0 || red_x > 0.8 || red_y < 0 || red_y > 0.8 ||
+       red_x + red_y > 1.0)
+   {
+      png_warning(png_ptr, "Invalid cHRM red point specified");
+      return;
+   }
+   itemp = (png_uint_32)(red_x * 100000.0 + 0.5);
+   png_save_uint_32(buf + 8, itemp);
+   itemp = (png_uint_32)(red_y * 100000.0 + 0.5);
+   png_save_uint_32(buf + 12, itemp);
+
+   if (green_x < 0 || green_x > 0.8 || green_y < 0 || green_y > 0.8 ||
+       green_x + green_y > 1.0)
+   {
+      png_warning(png_ptr, "Invalid cHRM green point specified");
+      return;
+   }
+   itemp = (png_uint_32)(green_x * 100000.0 + 0.5);
+   png_save_uint_32(buf + 16, itemp);
+   itemp = (png_uint_32)(green_y * 100000.0 + 0.5);
+   png_save_uint_32(buf + 20, itemp);
+
+   if (blue_x < 0 || blue_x > 0.8 || blue_y < 0 || blue_y > 0.8 ||
+       blue_x + blue_y > 1.0)
+   {
+      png_warning(png_ptr, "Invalid cHRM blue point specified");
+      return;
+   }
+   itemp = (png_uint_32)(blue_x * 100000.0 + 0.5);
+   png_save_uint_32(buf + 24, itemp);
+   itemp = (png_uint_32)(blue_y * 100000.0 + 0.5);
+   png_save_uint_32(buf + 28, itemp);
+
+   png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32);
+}
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+void /* PRIVATE */
+png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x,
+   png_fixed_point white_y, png_fixed_point red_x, png_fixed_point red_y,
+   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_byte buf[32];
+
+   png_debug(1, "in png_write_cHRM\n");
+   /* 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 fixed cHRM white point specified");
+#if !defined(PNG_NO_CONSOLE_IO)
+      fprintf(stderr,"white_x=%ld, white_y=%ld\n",white_x, white_y);
+#endif
+      return;
+   }
+   png_save_uint_32(buf, white_x);
+   png_save_uint_32(buf + 4, white_y);
+
+   if (red_x > 80000L || red_y > 80000L || red_x + red_y > 100000L)
+   {
+      png_warning(png_ptr, "Invalid cHRM fixed red point specified");
+      return;
+   }
+   png_save_uint_32(buf + 8, red_x);
+   png_save_uint_32(buf + 12, red_y);
+
+   if (green_x > 80000L || green_y > 80000L || green_x + green_y > 100000L)
+   {
+      png_warning(png_ptr, "Invalid fixed cHRM green point specified");
+      return;
+   }
+   png_save_uint_32(buf + 16, green_x);
+   png_save_uint_32(buf + 20, green_y);
+
+   if (blue_x > 80000L || blue_y > 80000L || blue_x + blue_y > 100000L)
+   {
+      png_warning(png_ptr, "Invalid fixed cHRM blue point specified");
+      return;
+   }
+   png_save_uint_32(buf + 24, blue_x);
+   png_save_uint_32(buf + 28, blue_y);
+
+   png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32);
+}
+#endif
+#endif
+
+#if defined(PNG_WRITE_tRNS_SUPPORTED)
+/* write the tRNS chunk */
+void /* PRIVATE */
+png_write_tRNS(png_structp png_ptr, png_bytep trans, png_color_16p tran,
+   int num_trans, int color_type)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_tRNS;
+#endif
+   png_byte buf[6];
+
+   png_debug(1, "in png_write_tRNS\n");
+   if (color_type == PNG_COLOR_TYPE_PALETTE)
+   {
+      if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette)
+      {
+         png_warning(png_ptr,"Invalid number of transparent colors specified");
+         return;
+      }
+      /* write the chunk out as it is */
+      png_write_chunk(png_ptr, (png_bytep)png_tRNS, trans, (png_size_t)num_trans);
+   }
+   else if (color_type == PNG_COLOR_TYPE_GRAY)
+   {
+      /* one 16 bit value */
+      png_save_uint_16(buf, tran->gray);
+      png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)2);
+   }
+   else if (color_type == PNG_COLOR_TYPE_RGB)
+   {
+      /* three 16 bit values */
+      png_save_uint_16(buf, tran->red);
+      png_save_uint_16(buf + 2, tran->green);
+      png_save_uint_16(buf + 4, tran->blue);
+      png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)6);
+   }
+   else
+   {
+      png_warning(png_ptr, "Can't write tRNS with an alpha channel");
+   }
+}
+#endif
+
+#if defined(PNG_WRITE_bKGD_SUPPORTED)
+/* write the background chunk */
+void /* PRIVATE */
+png_write_bKGD(png_structp png_ptr, png_color_16p back, int color_type)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_bKGD;
+#endif
+   png_byte buf[6];
+
+   png_debug(1, "in png_write_bKGD\n");
+   if (color_type == PNG_COLOR_TYPE_PALETTE)
+   {
+      if (
+#if defined(PNG_MNG_FEATURES_SUPPORTED) || \
+    defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED)
+          (png_ptr->num_palette ||
+          (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) &&
+#endif
+         back->index > png_ptr->num_palette)
+      {
+         png_warning(png_ptr, "Invalid background palette index");
+         return;
+      }
+      buf[0] = back->index;
+      png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)1);
+   }
+   else if (color_type & PNG_COLOR_MASK_COLOR)
+   {
+      png_save_uint_16(buf, back->red);
+      png_save_uint_16(buf + 2, back->green);
+      png_save_uint_16(buf + 4, back->blue);
+      png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)6);
+   }
+   else
+   {
+      png_save_uint_16(buf, back->gray);
+      png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)2);
+   }
+}
+#endif
+
+#if defined(PNG_WRITE_hIST_SUPPORTED)
+/* write the histogram */
+void /* PRIVATE */
+png_write_hIST(png_structp png_ptr, png_uint_16p hist, int num_hist)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_hIST;
+#endif
+   int i;
+   png_byte buf[3];
+
+   png_debug(1, "in png_write_hIST\n");
+   if (num_hist > (int)png_ptr->num_palette)
+   {
+      png_debug2(3, "num_hist = %d, num_palette = %d\n", num_hist,
+         png_ptr->num_palette);
+      png_warning(png_ptr, "Invalid number of histogram entries specified");
+      return;
+   }
+
+   png_write_chunk_start(png_ptr, (png_bytep)png_hIST, (png_uint_32)(num_hist * 2));
+   for (i = 0; i < num_hist; i++)
+   {
+      png_save_uint_16(buf, hist[i]);
+      png_write_chunk_data(png_ptr, buf, (png_size_t)2);
+   }
+   png_write_chunk_end(png_ptr);
+}
+#endif
+
+#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \
+    defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
+/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
+ * and if invalid, correct the keyword rather than discarding the entire
+ * chunk.  The PNG 1.0 specification requires keywords 1-79 characters in
+ * length, forbids leading or trailing whitespace, multiple internal spaces,
+ * and the non-break space (0x80) from ISO 8859-1.  Returns keyword length.
+ *
+ * The new_key is allocated to hold the corrected keyword and must be freed
+ * by the calling routine.  This avoids problems with trying to write to
+ * static keywords without having to have duplicate copies of the strings.
+ */
+png_size_t /* PRIVATE */
+png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key)
+{
+   png_size_t key_len;
+   png_charp kp, dp;
+   int kflag;
+   int kwarn=0;
+
+   png_debug(1, "in png_check_keyword\n");
+   *new_key = NULL;
+
+   if (key == NULL || (key_len = png_strlen(key)) == 0)
+   {
+      png_warning(png_ptr, "zero length keyword");
+      return ((png_size_t)0);
+   }
+
+   png_debug1(2, "Keyword to be checked is '%s'\n", key);
+
+   *new_key = (png_charp)png_malloc(png_ptr, (png_uint_32)(key_len + 2));
+
+   /* Replace non-printing characters with a blank and print a warning */
+   for (kp = key, dp = *new_key; *kp != '\0'; kp++, dp++)
+   {
+      if (*kp < 0x20 || (*kp > 0x7E && (png_byte)*kp < 0xA1))
+      {
+#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
+         char msg[40];
+
+         sprintf(msg, "invalid keyword character 0x%02X", *kp);
+         png_warning(png_ptr, msg);
+#else
+         png_warning(png_ptr, "invalid character in keyword");
+#endif
+         *dp = ' ';
+      }
+      else
+      {
+         *dp = *kp;
+      }
+   }
+   *dp = '\0';
+
+   /* Remove any trailing white space. */
+   kp = *new_key + key_len - 1;
+   if (*kp == ' ')
+   {
+      png_warning(png_ptr, "trailing spaces removed from keyword");
+
+      while (*kp == ' ')
+      {
+        *(kp--) = '\0';
+        key_len--;
+      }
+   }
+
+   /* Remove any leading white space. */
+   kp = *new_key;
+   if (*kp == ' ')
+   {
+      png_warning(png_ptr, "leading spaces removed from keyword");
+
+      while (*kp == ' ')
+      {
+        kp++;
+        key_len--;
+      }
+   }
+
+   png_debug1(2, "Checking for multiple internal spaces in '%s'\n", kp);
+
+   /* Remove multiple internal spaces. */
+   for (kflag = 0, dp = *new_key; *kp != '\0'; kp++)
+   {
+      if (*kp == ' ' && kflag == 0)
+      {
+         *(dp++) = *kp;
+         kflag = 1;
+      }
+      else if (*kp == ' ')
+      {
+         key_len--;
+         kwarn=1;
+      }
+      else
+      {
+         *(dp++) = *kp;
+         kflag = 0;
+      }
+   }
+   *dp = '\0';
+   if(kwarn)
+      png_warning(png_ptr, "extra interior spaces removed from keyword");
+
+   if (key_len == 0)
+   {
+      png_free(png_ptr, *new_key);
+      *new_key=NULL;
+      png_warning(png_ptr, "Zero length keyword");
+   }
+
+   if (key_len > 79)
+   {
+      png_warning(png_ptr, "keyword length must be 1 - 79 characters");
+      new_key[79] = '\0';
+      key_len = 79;
+   }
+
+   return (key_len);
+}
+#endif
+
+#if defined(PNG_WRITE_tEXt_SUPPORTED)
+/* write a tEXt chunk */
+void /* PRIVATE */
+png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text,
+   png_size_t text_len)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_tEXt;
+#endif
+   png_size_t key_len;
+   png_charp new_key;
+
+   png_debug(1, "in png_write_tEXt\n");
+   if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0)
+   {
+      png_warning(png_ptr, "Empty keyword in tEXt chunk");
+      return;
+   }
+
+   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);
+   /*
+    * We leave it to the application to meet PNG-1.0 requirements on the
+    * contents of the text.  PNG-1.0 through PNG-1.2 discourage the use of
+    * any non-Latin-1 characters except for NEWLINE.  ISO PNG will forbid them.
+    * 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);
+   if (text_len)
+      png_write_chunk_data(png_ptr, (png_bytep)text, text_len);
+
+   png_write_chunk_end(png_ptr);
+   png_free(png_ptr, new_key);
+}
+#endif
+
+#if defined(PNG_WRITE_zTXt_SUPPORTED)
+/* write a compressed text chunk */
+void /* PRIVATE */
+png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text,
+   png_size_t text_len, int compression)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_zTXt;
+#endif
+   png_size_t key_len;
+   char buf[1];
+   png_charp new_key;
+   compression_state comp;
+
+   png_debug(1, "in png_write_zTXt\n");
+
+   if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0)
+   {
+      png_warning(png_ptr, "Empty keyword in zTXt chunk");
+      return;
+   }
+
+   if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE)
+   {
+      png_write_tEXt(png_ptr, new_key, text, (png_size_t)0);
+      png_free(png_ptr, new_key);
+      return;
+   }
+
+   text_len = png_strlen(text);
+
+   png_free(png_ptr, new_key);
+
+   /* compute the compressed data; do it now for the length */
+   text_len = png_text_compress(png_ptr, text, text_len, compression,
+       &comp);
+
+   /* write start of chunk */
+   png_write_chunk_start(png_ptr, (png_bytep)png_zTXt, (png_uint_32)
+      (key_len+text_len+2));
+   /* write key */
+   png_write_chunk_data(png_ptr, (png_bytep)key, key_len + 1);
+   buf[0] = (png_byte)compression;
+   /* write compression */
+   png_write_chunk_data(png_ptr, (png_bytep)buf, (png_size_t)1);
+   /* write the compressed data */
+   png_write_compressed_data_out(png_ptr, &comp);
+
+   /* close the chunk */
+   png_write_chunk_end(png_ptr);
+}
+#endif
+
+#if defined(PNG_WRITE_iTXt_SUPPORTED)
+/* write an iTXt chunk */
+void /* PRIVATE */
+png_write_iTXt(png_structp png_ptr, int compression, png_charp key,
+    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, 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");
+
+   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;
+   }
+   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-2,
+      &comp);
+
+   /* make sure we include the compression flag, the compression byte,
+    * and the NULs after the key, lang, and lang_key parts */
+
+   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
+    * contents of the text.  PNG-1.0 through PNG-1.2 discourage the use of
+    * any non-Latin-1 characters except for NEWLINE.  ISO PNG will forbid them.
+    * 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)lang_key, lang_key_len+1);
+   png_write_chunk_data(png_ptr, '\0', 1);
+
+   png_write_compressed_data_out(png_ptr, &comp);
+
+   png_write_chunk_end(png_ptr);
+   png_free(png_ptr, new_key);
+   png_free(png_ptr, new_lang);
+}
+#endif
+
+#if defined(PNG_WRITE_oFFs_SUPPORTED)
+/* write the oFFs chunk */
+void /* PRIVATE */
+png_write_oFFs(png_structp png_ptr, png_uint_32 x_offset,
+   png_uint_32 y_offset,
+   int unit_type)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_oFFs;
+#endif
+   png_byte buf[9];
+
+   png_debug(1, "in png_write_oFFs\n");
+   if (unit_type >= PNG_OFFSET_LAST)
+      png_warning(png_ptr, "Unrecognized unit type for oFFs chunk");
+
+   png_save_uint_32(buf, x_offset);
+   png_save_uint_32(buf + 4, y_offset);
+   buf[8] = (png_byte)unit_type;
+
+   png_write_chunk(png_ptr, (png_bytep)png_oFFs, buf, (png_size_t)9);
+}
+#endif
+
+#if defined(PNG_WRITE_pCAL_SUPPORTED)
+/* write the pCAL chunk (described in the PNG extensions document) */
+void /* PRIVATE */
+png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
+   png_int_32 X1, int type, int nparams, png_charp units, png_charpp params)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_pCAL;
+#endif
+   png_size_t purpose_len, units_len, total_len;
+   png_uint_32p params_len;
+   png_byte buf[10];
+   png_charp new_purpose;
+   int i;
+
+   png_debug1(1, "in png_write_pCAL (%d parameters)\n", nparams);
+   if (type >= PNG_EQUATION_LAST)
+      png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
+
+   purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1;
+   png_debug1(3, "pCAL purpose length = %d\n", (int)purpose_len);
+   units_len = png_strlen(units) + (nparams == 0 ? 0 : 1);
+   png_debug1(3, "pCAL units length = %d\n", (int)units_len);
+   total_len = purpose_len + units_len + 10;
+
+   params_len = (png_uint_32p)png_malloc(png_ptr, (png_uint_32)(nparams
+      *sizeof(png_uint_32)));
+
+   /* Find the length of each parameter, making sure we don't count the
+      null terminator for the last parameter. */
+   for (i = 0; i < nparams; i++)
+   {
+      params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1);
+      png_debug2(3, "pCAL parameter %d length = %lu\n", i, params_len[i]);
+      total_len += (png_size_t)params_len[i];
+   }
+
+   png_debug1(3, "pCAL total length = %d\n", (int)total_len);
+   png_write_chunk_start(png_ptr, (png_bytep)png_pCAL, (png_uint_32)total_len);
+   png_write_chunk_data(png_ptr, (png_bytep)new_purpose, purpose_len);
+   png_save_int_32(buf, X0);
+   png_save_int_32(buf + 4, X1);
+   buf[8] = (png_byte)type;
+   buf[9] = (png_byte)nparams;
+   png_write_chunk_data(png_ptr, buf, (png_size_t)10);
+   png_write_chunk_data(png_ptr, (png_bytep)units, (png_size_t)units_len);
+
+   png_free(png_ptr, new_purpose);
+
+   for (i = 0; i < nparams; i++)
+   {
+      png_write_chunk_data(png_ptr, (png_bytep)params[i],
+         (png_size_t)params_len[i]);
+   }
+
+   png_free(png_ptr, params_len);
+   png_write_chunk_end(png_ptr);
+}
+#endif
+
+#if defined(PNG_WRITE_sCAL_SUPPORTED)
+/* write the sCAL chunk */
+#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO)
+void /* PRIVATE */
+png_write_sCAL(png_structp png_ptr, int unit, double width,double height)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_sCAL;
+#endif
+   png_size_t total_len;
+   char wbuf[32], hbuf[32];
+
+   png_debug(1, "in png_write_sCAL\n");
+
+#if defined(_WIN32_WCE)
+/* sprintf() function is not supported on WindowsCE */
+   {
+      wchar_t wc_buf[32];
+      swprintf(wc_buf, TEXT("%12.12e"), width);
+      WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, wbuf, 32, NULL, NULL);
+      swprintf(wc_buf, TEXT("%12.12e"), height);
+      WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, hbuf, 32, NULL, NULL);
+   }
+#else
+   sprintf(wbuf, "%12.12e", width);
+   sprintf(hbuf, "%12.12e", height);
+#endif
+   total_len = 1 + png_strlen(wbuf)+1 + png_strlen(hbuf);
+
+   png_debug1(3, "sCAL total length = %d\n", (int)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, 1);
+   png_write_chunk_data(png_ptr, (png_bytep)wbuf, png_strlen(wbuf)+1);
+   png_write_chunk_data(png_ptr, (png_bytep)hbuf, png_strlen(hbuf));
+
+   png_write_chunk_end(png_ptr);
+}
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+void /* PRIVATE */
+png_write_sCAL_s(png_structp png_ptr, int unit, png_charp width,
+   png_charp height)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_sCAL;
+#endif
+   png_size_t total_len;
+   char wbuf[32], hbuf[32];
+
+   png_debug(1, "in png_write_sCAL_s\n");
+
+   png_strcpy(wbuf,(const char *)width);
+   png_strcpy(hbuf,(const char *)height);
+   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, 1);
+   png_write_chunk_data(png_ptr, (png_bytep)wbuf, png_strlen(wbuf)+1);
+   png_write_chunk_data(png_ptr, (png_bytep)hbuf, png_strlen(hbuf));
+
+   png_write_chunk_end(png_ptr);
+}
+#endif
+#endif
+#endif
+
+#if defined(PNG_WRITE_pHYs_SUPPORTED)
+/* write the pHYs chunk */
+void /* PRIVATE */
+png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit,
+   png_uint_32 y_pixels_per_unit,
+   int unit_type)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_pHYs;
+#endif
+   png_byte buf[9];
+
+   png_debug(1, "in png_write_pHYs\n");
+   if (unit_type >= PNG_RESOLUTION_LAST)
+      png_warning(png_ptr, "Unrecognized unit type for pHYs chunk");
+
+   png_save_uint_32(buf, x_pixels_per_unit);
+   png_save_uint_32(buf + 4, y_pixels_per_unit);
+   buf[8] = (png_byte)unit_type;
+
+   png_write_chunk(png_ptr, (png_bytep)png_pHYs, buf, (png_size_t)9);
+}
+#endif
+
+#if defined(PNG_WRITE_tIME_SUPPORTED)
+/* Write the tIME chunk.  Use either png_convert_from_struct_tm()
+ * or png_convert_from_time_t(), or fill in the structure yourself.
+ */
+void /* PRIVATE */
+png_write_tIME(png_structp png_ptr, png_timep mod_time)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_tIME;
+#endif
+   png_byte buf[7];
+
+   png_debug(1, "in png_write_tIME\n");
+   if (mod_time->month  > 12 || mod_time->month  < 1 ||
+       mod_time->day    > 31 || mod_time->day    < 1 ||
+       mod_time->hour   > 23 || mod_time->second > 60)
+   {
+      png_warning(png_ptr, "Invalid time specified for tIME chunk");
+      return;
+   }
+
+   png_save_uint_16(buf, mod_time->year);
+   buf[2] = mod_time->month;
+   buf[3] = mod_time->day;
+   buf[4] = mod_time->hour;
+   buf[5] = mod_time->minute;
+   buf[6] = mod_time->second;
+
+   png_write_chunk(png_ptr, (png_bytep)png_tIME, buf, (png_size_t)7);
+}
+#endif
+
+/* initializes the row writing capability of libpng */
+void /* PRIVATE */
+png_write_start_row(png_structp png_ptr)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+
+   /* start of interlace block */
+   int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+
+   /* offset to next interlace block */
+   int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+
+   /* start of interlace block in the y direction */
+   int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
+
+   /* offset to next interlace block in the y direction */
+   int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
+#endif
+
+   png_size_t buf_size;
+
+   png_debug(1, "in png_write_start_row\n");
+   buf_size = (png_size_t)(((png_ptr->width * png_ptr->usr_channels *
+                            png_ptr->usr_bit_depth + 7) >> 3) + 1);
+
+   /* set up row buffer */
+   png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, (png_uint_32)buf_size);
+   png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE;
+
+   /* set up filtering buffer, if using this filter */
+   if (png_ptr->do_filter & PNG_FILTER_SUB)
+   {
+      png_ptr->sub_row = (png_bytep)png_malloc(png_ptr,
+         (png_ptr->rowbytes + 1));
+      png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
+   }
+
+   /* We only need to keep the previous row if we are using one of these. */
+   if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH))
+   {
+     /* set up previous row buffer */
+      png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)buf_size);
+      png_memset(png_ptr->prev_row, 0, buf_size);
+
+      if (png_ptr->do_filter & PNG_FILTER_UP)
+      {
+         png_ptr->up_row = (png_bytep )png_malloc(png_ptr,
+            (png_ptr->rowbytes + 1));
+         png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
+      }
+
+      if (png_ptr->do_filter & PNG_FILTER_AVG)
+      {
+         png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
+            (png_ptr->rowbytes + 1));
+         png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
+      }
+
+      if (png_ptr->do_filter & PNG_FILTER_PAETH)
+      {
+         png_ptr->paeth_row = (png_bytep )png_malloc(png_ptr,
+            (png_ptr->rowbytes + 1));
+         png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
+      }
+   }
+
+#ifdef PNG_WRITE_INTERLACING_SUPPORTED
+   /* if interlaced, we need to set up width and height of pass */
+   if (png_ptr->interlaced)
+   {
+      if (!(png_ptr->transformations & PNG_INTERLACE))
+      {
+         png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
+            png_pass_ystart[0]) / png_pass_yinc[0];
+         png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 -
+            png_pass_start[0]) / png_pass_inc[0];
+      }
+      else
+      {
+         png_ptr->num_rows = png_ptr->height;
+         png_ptr->usr_width = png_ptr->width;
+      }
+   }
+   else
+#endif
+   {
+      png_ptr->num_rows = png_ptr->height;
+      png_ptr->usr_width = png_ptr->width;
+   }
+   png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+   png_ptr->zstream.next_out = png_ptr->zbuf;
+}
+
+/* Internal use only.  Called when finished processing a row of data. */
+void /* PRIVATE */
+png_write_finish_row(png_structp png_ptr)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+
+   /* start of interlace block */
+   int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+
+   /* offset to next interlace block */
+   int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+
+   /* start of interlace block in the y direction */
+   int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
+
+   /* offset to next interlace block in the y direction */
+   int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
+#endif
+
+   int ret;
+
+   png_debug(1, "in png_write_finish_row\n");
+   /* next row */
+   png_ptr->row_number++;
+
+   /* see if we are done */
+   if (png_ptr->row_number < png_ptr->num_rows)
+      return;
+
+#ifdef PNG_WRITE_INTERLACING_SUPPORTED
+   /* if interlaced, go to next pass */
+   if (png_ptr->interlaced)
+   {
+      png_ptr->row_number = 0;
+      if (png_ptr->transformations & PNG_INTERLACE)
+      {
+         png_ptr->pass++;
+      }
+      else
+      {
+         /* loop until we find a non-zero width or height pass */
+         do
+         {
+            png_ptr->pass++;
+            if (png_ptr->pass >= 7)
+               break;
+            png_ptr->usr_width = (png_ptr->width +
+               png_pass_inc[png_ptr->pass] - 1 -
+               png_pass_start[png_ptr->pass]) /
+               png_pass_inc[png_ptr->pass];
+            png_ptr->num_rows = (png_ptr->height +
+               png_pass_yinc[png_ptr->pass] - 1 -
+               png_pass_ystart[png_ptr->pass]) /
+               png_pass_yinc[png_ptr->pass];
+            if (png_ptr->transformations & PNG_INTERLACE)
+               break;
+         } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0);
+
+      }
+
+      /* reset the row above the image for the next pass */
+      if (png_ptr->pass < 7)
+      {
+         if (png_ptr->prev_row != NULL)
+            png_memset(png_ptr->prev_row, 0,
+               (png_size_t) (((png_uint_32)png_ptr->usr_channels *
+               (png_uint_32)png_ptr->usr_bit_depth *
+               png_ptr->width + 7) >> 3) + 1);
+         return;
+      }
+   }
+#endif
+
+   /* if we get here, we've just written the last row, so we need
+      to flush the compressor */
+   do
+   {
+      /* tell the compressor we are done */
+      ret = deflate(&png_ptr->zstream, Z_FINISH);
+      /* check for an error */
+      if (ret == Z_OK)
+      {
+         /* check to see if we need more room */
+         if (!(png_ptr->zstream.avail_out))
+         {
+            png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
+            png_ptr->zstream.next_out = png_ptr->zbuf;
+            png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+         }
+      }
+      else if (ret != Z_STREAM_END)
+      {
+         if (png_ptr->zstream.msg != NULL)
+            png_error(png_ptr, png_ptr->zstream.msg);
+         else
+            png_error(png_ptr, "zlib error");
+      }
+   } while (ret != Z_STREAM_END);
+
+   /* write any extra space */
+   if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
+   {
+      png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size -
+         png_ptr->zstream.avail_out);
+   }
+
+   deflateReset(&png_ptr->zstream);
+}
+
+#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
+/* Pick out the correct pixels for the interlace pass.
+ * The basic idea here is to go through the row with a source
+ * pointer and a destination pointer (sp and dp), and copy the
+ * correct pixels for the pass.  As the row gets compacted,
+ * sp will always be >= dp, so we should never overwrite anything.
+ * See the default: case for the easiest code to understand.
+ */
+void /* PRIVATE */
+png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+
+   /* start of interlace block */
+   int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+
+   /* offset to next interlace block */
+   int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+#endif
+
+   png_debug(1, "in png_do_write_interlace\n");
+   /* we don't have to do anything on the last pass (6) */
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   if (row != NULL && row_info != NULL && pass < 6)
+#else
+   if (pass < 6)
+#endif
+   {
+      /* each pixel depth is handled separately */
+      switch (row_info->pixel_depth)
+      {
+         case 1:
+         {
+            png_bytep sp;
+            png_bytep dp;
+            int shift;
+            int d;
+            int value;
+            png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
+
+            dp = row;
+            d = 0;
+            shift = 7;
+            for (i = png_pass_start[pass]; i < row_width;
+               i += png_pass_inc[pass])
+            {
+               sp = row + (png_size_t)(i >> 3);
+               value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01;
+               d |= (value << shift);
+
+               if (shift == 0)
+               {
+                  shift = 7;
+                  *dp++ = (png_byte)d;
+                  d = 0;
+               }
+               else
+                  shift--;
+
+            }
+            if (shift != 7)
+               *dp = (png_byte)d;
+            break;
+         }
+         case 2:
+         {
+            png_bytep sp;
+            png_bytep dp;
+            int shift;
+            int d;
+            int value;
+            png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
+
+            dp = row;
+            shift = 6;
+            d = 0;
+            for (i = png_pass_start[pass]; i < row_width;
+               i += png_pass_inc[pass])
+            {
+               sp = row + (png_size_t)(i >> 2);
+               value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03;
+               d |= (value << shift);
+
+               if (shift == 0)
+               {
+                  shift = 6;
+                  *dp++ = (png_byte)d;
+                  d = 0;
+               }
+               else
+                  shift -= 2;
+            }
+            if (shift != 6)
+                   *dp = (png_byte)d;
+            break;
+         }
+         case 4:
+         {
+            png_bytep sp;
+            png_bytep dp;
+            int shift;
+            int d;
+            int value;
+            png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
+
+            dp = row;
+            shift = 4;
+            d = 0;
+            for (i = png_pass_start[pass]; i < row_width;
+               i += png_pass_inc[pass])
+            {
+               sp = row + (png_size_t)(i >> 1);
+               value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f;
+               d |= (value << shift);
+
+               if (shift == 0)
+               {
+                  shift = 4;
+                  *dp++ = (png_byte)d;
+                  d = 0;
+               }
+               else
+                  shift -= 4;
+            }
+            if (shift != 4)
+               *dp = (png_byte)d;
+            break;
+         }
+         default:
+         {
+            png_bytep sp;
+            png_bytep dp;
+            png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
+            png_size_t pixel_bytes;
+
+            /* start at the beginning */
+            dp = row;
+            /* find out how many bytes each pixel takes up */
+            pixel_bytes = (row_info->pixel_depth >> 3);
+            /* loop through the row, only looking at the pixels that
+               matter */
+            for (i = png_pass_start[pass]; i < row_width;
+               i += png_pass_inc[pass])
+            {
+               /* find out where the original pixel is */
+               sp = row + (png_size_t)i * pixel_bytes;
+               /* move the pixel */
+               if (dp != sp)
+                  png_memcpy(dp, sp, pixel_bytes);
+               /* next pixel */
+               dp += pixel_bytes;
+            }
+            break;
+         }
+      }
+      /* set new row width */
+      row_info->width = (row_info->width +
+         png_pass_inc[pass] - 1 -
+         png_pass_start[pass]) /
+         png_pass_inc[pass];
+         row_info->rowbytes = ((row_info->width *
+            row_info->pixel_depth + 7) >> 3);
+   }
+}
+#endif
+
+/* This filters the row, chooses which filter to use, if it has not already
+ * been specified by the application, and then writes the row out with the
+ * chosen filter.
+ */
+#define PNG_MAXSUM (~((png_uint_32)0) >> 1)
+#define PNG_HISHIFT 10
+#define PNG_LOMASK ((png_uint_32)0xffffL)
+#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT))
+void /* PRIVATE */
+png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
+{
+   png_bytep prev_row, best_row, row_buf;
+   png_uint_32 mins, bpp;
+   png_byte filter_to_do = png_ptr->do_filter;
+   png_uint_32 row_bytes = row_info->rowbytes;
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+   int num_p_filters = (int)png_ptr->num_prev_filters;
+#endif
+
+   png_debug(1, "in png_write_find_filter\n");
+   /* find out how many bytes offset each pixel is */
+   bpp = (row_info->pixel_depth + 7) / 8;
+
+   prev_row = png_ptr->prev_row;
+   best_row = row_buf = png_ptr->row_buf;
+   mins = PNG_MAXSUM;
+
+   /* The prediction method we use is to find which method provides the
+    * smallest value when summing the absolute values of the distances
+    * from zero, using anything >= 128 as negative numbers.  This is known
+    * as the "minimum sum of absolute differences" heuristic.  Other
+    * heuristics are the "weighted minimum sum of absolute differences"
+    * (experimental and can in theory improve compression), and the "zlib
+    * predictive" method (not implemented yet), which does test compressions
+    * of lines using different filter methods, and then chooses the
+    * (series of) filter(s) that give minimum compressed data size (VERY
+    * computationally expensive).
+    *
+    * GRR 980525:  consider also
+    *   (1) minimum sum of absolute differences from running average (i.e.,
+    *       keep running sum of non-absolute differences & count of bytes)
+    *       [track dispersion, too?  restart average if dispersion too large?]
+    *  (1b) minimum sum of absolute differences from sliding average, probably
+    *       with window size <= deflate window (usually 32K)
+    *   (2) minimum sum of squared differences from zero or running average
+    *       (i.e., ~ root-mean-square approach)
+    */
+
+
+   /* We don't need to test the 'no filter' case if this is the only filter
+    * that has been chosen, as it doesn't actually do anything to the data.
+    */
+   if ((filter_to_do & PNG_FILTER_NONE) &&
+       filter_to_do != PNG_FILTER_NONE)
+   {
+      png_bytep rp;
+      png_uint_32 sum = 0;
+      png_uint_32 i;
+      int v;
+
+      for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++)
+      {
+         v = *rp;
+         sum += (v < 128) ? v : 256 - v;
+      }
+
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
+      {
+         png_uint_32 sumhi, sumlo;
+         int j;
+         sumlo = sum & PNG_LOMASK;
+         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */
+
+         /* Reduce the sum if we match any of the previous rows */
+         for (j = 0; j < num_p_filters; j++)
+         {
+            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
+            {
+               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+            }
+         }
+
+         /* Factor in the cost of this filter (this is here for completeness,
+          * but it makes no sense to have a "cost" for the NONE filter, as
+          * it has the minimum possible computational cost - none).
+          */
+         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
+            PNG_COST_SHIFT;
+         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
+            PNG_COST_SHIFT;
+
+         if (sumhi > PNG_HIMASK)
+            sum = PNG_MAXSUM;
+         else
+            sum = (sumhi << PNG_HISHIFT) + sumlo;
+      }
+#endif
+      mins = sum;
+   }
+
+   /* sub filter */
+   if (filter_to_do == PNG_FILTER_SUB)
+   /* it's the only filter so no testing is needed */
+   {
+      png_bytep rp, lp, dp;
+      png_uint_32 i;
+      for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
+           i++, rp++, dp++)
+      {
+         *dp = *rp;
+      }
+      for (lp = row_buf + 1; i < row_bytes;
+         i++, rp++, lp++, dp++)
+      {
+         *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
+      }
+      best_row = png_ptr->sub_row;
+   }
+
+   else if (filter_to_do & PNG_FILTER_SUB)
+   {
+      png_bytep rp, dp, lp;
+      png_uint_32 sum = 0, lmins = mins;
+      png_uint_32 i;
+      int v;
+
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+      /* We temporarily increase the "minimum sum" by the factor we
+       * would reduce the sum of this filter, so that we can do the
+       * early exit comparison without scaling the sum each time.
+       */
+      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
+      {
+         int j;
+         png_uint_32 lmhi, lmlo;
+         lmlo = lmins & PNG_LOMASK;
+         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
+
+         for (j = 0; j < num_p_filters; j++)
+         {
+            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
+            {
+               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+            }
+         }
+
+         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
+            PNG_COST_SHIFT;
+         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
+            PNG_COST_SHIFT;
+
+         if (lmhi > PNG_HIMASK)
+            lmins = PNG_MAXSUM;
+         else
+            lmins = (lmhi << PNG_HISHIFT) + lmlo;
+      }
+#endif
+
+      for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
+           i++, rp++, dp++)
+      {
+         v = *dp = *rp;
+
+         sum += (v < 128) ? v : 256 - v;
+      }
+      for (lp = row_buf + 1; i < row_info->rowbytes;
+         i++, rp++, lp++, dp++)
+      {
+         v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
+
+         sum += (v < 128) ? v : 256 - v;
+
+         if (sum > lmins)  /* We are already worse, don't continue. */
+            break;
+      }
+
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
+      {
+         int j;
+         png_uint_32 sumhi, sumlo;
+         sumlo = sum & PNG_LOMASK;
+         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
+
+         for (j = 0; j < num_p_filters; j++)
+         {
+            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
+            {
+               sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+               sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+            }
+         }
+
+         sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
+            PNG_COST_SHIFT;
+         sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
+            PNG_COST_SHIFT;
+
+         if (sumhi > PNG_HIMASK)
+            sum = PNG_MAXSUM;
+         else
+            sum = (sumhi << PNG_HISHIFT) + sumlo;
+      }
+#endif
+
+      if (sum < mins)
+      {
+         mins = sum;
+         best_row = png_ptr->sub_row;
+      }
+   }
+
+   /* up filter */
+   if (filter_to_do == PNG_FILTER_UP)
+   {
+      png_bytep rp, dp, pp;
+      png_uint_32 i;
+
+      for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
+           pp = prev_row + 1; i < row_bytes;
+           i++, rp++, pp++, dp++)
+      {
+         *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
+      }
+      best_row = png_ptr->up_row;
+   }
+
+   else if (filter_to_do & PNG_FILTER_UP)
+   {
+      png_bytep rp, dp, pp;
+      png_uint_32 sum = 0, lmins = mins;
+      png_uint_32 i;
+      int v;
+
+
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
+      {
+         int j;
+         png_uint_32 lmhi, lmlo;
+         lmlo = lmins & PNG_LOMASK;
+         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
+
+         for (j = 0; j < num_p_filters; j++)
+         {
+            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
+            {
+               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+            }
+         }
+
+         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
+            PNG_COST_SHIFT;
+         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
+            PNG_COST_SHIFT;
+
+         if (lmhi > PNG_HIMASK)
+            lmins = PNG_MAXSUM;
+         else
+            lmins = (lmhi << PNG_HISHIFT) + lmlo;
+      }
+#endif
+
+      for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
+           pp = prev_row + 1; i < row_bytes; i++)
+      {
+         v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
+
+         sum += (v < 128) ? v : 256 - v;
+
+         if (sum > lmins)  /* We are already worse, don't continue. */
+            break;
+      }
+
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
+      {
+         int j;
+         png_uint_32 sumhi, sumlo;
+         sumlo = sum & PNG_LOMASK;
+         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
+
+         for (j = 0; j < num_p_filters; j++)
+         {
+            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
+            {
+               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+            }
+         }
+
+         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
+            PNG_COST_SHIFT;
+         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
+            PNG_COST_SHIFT;
+
+         if (sumhi > PNG_HIMASK)
+            sum = PNG_MAXSUM;
+         else
+            sum = (sumhi << PNG_HISHIFT) + sumlo;
+      }
+#endif
+
+      if (sum < mins)
+      {
+         mins = sum;
+         best_row = png_ptr->up_row;
+      }
+   }
+
+   /* avg filter */
+   if (filter_to_do == PNG_FILTER_AVG)
+   {
+      png_bytep rp, dp, pp, lp;
+      png_uint_32 i;
+      for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
+           pp = prev_row + 1; i < bpp; i++)
+      {
+         *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
+      }
+      for (lp = row_buf + 1; i < row_bytes; i++)
+      {
+         *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2))
+                 & 0xff);
+      }
+      best_row = png_ptr->avg_row;
+   }
+
+   else if (filter_to_do & PNG_FILTER_AVG)
+   {
+      png_bytep rp, dp, pp, lp;
+      png_uint_32 sum = 0, lmins = mins;
+      png_uint_32 i;
+      int v;
+
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
+      {
+         int j;
+         png_uint_32 lmhi, lmlo;
+         lmlo = lmins & PNG_LOMASK;
+         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
+
+         for (j = 0; j < num_p_filters; j++)
+         {
+            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG)
+            {
+               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+            }
+         }
+
+         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
+            PNG_COST_SHIFT;
+         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
+            PNG_COST_SHIFT;
+
+         if (lmhi > PNG_HIMASK)
+            lmins = PNG_MAXSUM;
+         else
+            lmins = (lmhi << PNG_HISHIFT) + lmlo;
+      }
+#endif
+
+      for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
+           pp = prev_row + 1; i < bpp; i++)
+      {
+         v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
+
+         sum += (v < 128) ? v : 256 - v;
+      }
+      for (lp = row_buf + 1; i < row_bytes; i++)
+      {
+         v = *dp++ =
+          (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff);
+
+         sum += (v < 128) ? v : 256 - v;
+
+         if (sum > lmins)  /* We are already worse, don't continue. */
+            break;
+      }
+
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
+      {
+         int j;
+         png_uint_32 sumhi, sumlo;
+         sumlo = sum & PNG_LOMASK;
+         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
+
+         for (j = 0; j < num_p_filters; j++)
+         {
+            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
+            {
+               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+            }
+         }
+
+         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
+            PNG_COST_SHIFT;
+         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
+            PNG_COST_SHIFT;
+
+         if (sumhi > PNG_HIMASK)
+            sum = PNG_MAXSUM;
+         else
+            sum = (sumhi << PNG_HISHIFT) + sumlo;
+      }
+#endif
+
+      if (sum < mins)
+      {
+         mins = sum;
+         best_row = png_ptr->avg_row;
+      }
+   }
+
+   /* Paeth filter */
+   if (filter_to_do == PNG_FILTER_PAETH)
+   {
+      png_bytep rp, dp, pp, cp, lp;
+      png_uint_32 i;
+      for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
+           pp = prev_row + 1; i < bpp; i++)
+      {
+         *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
+      }
+
+      for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
+      {
+         int a, b, c, pa, pb, pc, p;
+
+         b = *pp++;
+         c = *cp++;
+         a = *lp++;
+
+         p = b - c;
+         pc = a - c;
+
+#ifdef PNG_USE_ABS
+         pa = abs(p);
+         pb = abs(pc);
+         pc = abs(p + pc);
+#else
+         pa = p < 0 ? -p : p;
+         pb = pc < 0 ? -pc : pc;
+         pc = (p + pc) < 0 ? -(p + pc) : p + pc;
+#endif
+
+         p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
+
+         *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
+      }
+      best_row = png_ptr->paeth_row;
+   }
+
+   else if (filter_to_do & PNG_FILTER_PAETH)
+   {
+      png_bytep rp, dp, pp, cp, lp;
+      png_uint_32 sum = 0, lmins = mins;
+      png_uint_32 i;
+      int v;
+
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
+      {
+         int j;
+         png_uint_32 lmhi, lmlo;
+         lmlo = lmins & PNG_LOMASK;
+         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
+
+         for (j = 0; j < num_p_filters; j++)
+         {
+            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
+            {
+               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+            }
+         }
+
+         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
+            PNG_COST_SHIFT;
+         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
+            PNG_COST_SHIFT;
+
+         if (lmhi > PNG_HIMASK)
+            lmins = PNG_MAXSUM;
+         else
+            lmins = (lmhi << PNG_HISHIFT) + lmlo;
+      }
+#endif
+
+      for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
+           pp = prev_row + 1; i < bpp; i++)
+      {
+         v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
+
+         sum += (v < 128) ? v : 256 - v;
+      }
+
+      for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
+      {
+         int a, b, c, pa, pb, pc, p;
+
+         b = *pp++;
+         c = *cp++;
+         a = *lp++;
+
+#ifndef PNG_SLOW_PAETH
+         p = b - c;
+         pc = a - c;
+#ifdef PNG_USE_ABS
+         pa = abs(p);
+         pb = abs(pc);
+         pc = abs(p + pc);
+#else
+         pa = p < 0 ? -p : p;
+         pb = pc < 0 ? -pc : pc;
+         pc = (p + pc) < 0 ? -(p + pc) : p + pc;
+#endif
+         p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
+#else /* PNG_SLOW_PAETH */
+         p = a + b - c;
+         pa = abs(p - a);
+         pb = abs(p - b);
+         pc = abs(p - c);
+         if (pa <= pb && pa <= pc)
+            p = a;
+         else if (pb <= pc)
+            p = b;
+         else
+            p = c;
+#endif /* PNG_SLOW_PAETH */
+
+         v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
+
+         sum += (v < 128) ? v : 256 - v;
+
+         if (sum > lmins)  /* We are already worse, don't continue. */
+            break;
+      }
+
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
+      {
+         int j;
+         png_uint_32 sumhi, sumlo;
+         sumlo = sum & PNG_LOMASK;
+         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
+
+         for (j = 0; j < num_p_filters; j++)
+         {
+            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
+            {
+               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+            }
+         }
+
+         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
+            PNG_COST_SHIFT;
+         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
+            PNG_COST_SHIFT;
+
+         if (sumhi > PNG_HIMASK)
+            sum = PNG_MAXSUM;
+         else
+            sum = (sumhi << PNG_HISHIFT) + sumlo;
+      }
+#endif
+
+      if (sum < mins)
+      {
+         best_row = png_ptr->paeth_row;
+      }
+   }
+
+   /* Do the actual writing of the filtered row data from the chosen filter. */
+
+   png_write_filtered_row(png_ptr, best_row);
+
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+   /* Save the type of filter we picked this time for future calculations */
+   if (png_ptr->num_prev_filters > 0)
+   {
+      int j;
+      for (j = 1; j < num_p_filters; j++)
+      {
+         png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1];
+      }
+      png_ptr->prev_filters[j] = best_row[0];
+   }
+#endif
+}
+
+
+/* Do the actual writing of a previously filtered row. */
+void /* PRIVATE */
+png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row)
+{
+   png_debug(1, "in png_write_filtered_row\n");
+   png_debug1(2, "filter = %d\n", filtered_row[0]);
+   /* set up the zlib input buffer */
+
+   png_ptr->zstream.next_in = filtered_row;
+   png_ptr->zstream.avail_in = (uInt)png_ptr->row_info.rowbytes + 1;
+   /* repeat until we have compressed all the data */
+   do
+   {
+      int ret; /* return of zlib */
+
+      /* compress the data */
+      ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
+      /* check for compression errors */
+      if (ret != Z_OK)
+      {
+         if (png_ptr->zstream.msg != NULL)
+            png_error(png_ptr, png_ptr->zstream.msg);
+         else
+            png_error(png_ptr, "zlib error");
+      }
+
+      /* see if it is time to write another IDAT */
+      if (!(png_ptr->zstream.avail_out))
+      {
+         /* write the IDAT and reset the zlib output buffer */
+         png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
+         png_ptr->zstream.next_out = png_ptr->zbuf;
+         png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+      }
+   /* repeat until all data has been compressed */
+   } while (png_ptr->zstream.avail_in);
+
+   /* swap the current and previous rows */
+   if (png_ptr->prev_row != NULL)
+   {
+      png_bytep tptr;
+
+      tptr = png_ptr->prev_row;
+      png_ptr->prev_row = png_ptr->row_buf;
+      png_ptr->row_buf = tptr;
+   }
+
+   /* finish row - updates counters and flushes zlib if last row */
+   png_write_finish_row(png_ptr);
+
+#if defined(PNG_WRITE_FLUSH_SUPPORTED)
+   png_ptr->flush_rows++;
+
+   if (png_ptr->flush_dist > 0 &&
+       png_ptr->flush_rows >= png_ptr->flush_dist)
+   {
+      png_write_flush(png_ptr);
+   }
+#endif
+}
+#endif /* PNG_WRITE_SUPPORTED */
diff --git a/Utilities/ITK/Utilities/tiff/.NoDartCoverage b/Utilities/ITK/Utilities/tiff/.NoDartCoverage
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/Utilities/ITK/Utilities/tiff/CMakeLists.txt b/Utilities/ITK/Utilities/tiff/CMakeLists.txt
new file mode 100644
index 0000000000..8e0074db1b
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/CMakeLists.txt
@@ -0,0 +1,153 @@
+PROJECT(ITKTIFF)
+INCLUDE_REGULAR_EXPRESSION("^(itk_tiff_mangle|tif|fax|port|uv|tconf|t4|mk|itkjpeg|jpeg|mangle|jconfig|jmorecfg).*$")
+
+INCLUDE_DIRECTORIES(BEFORE ${ITKTIFF_SOURCE_DIR})
+INCLUDE_DIRECTORIES(BEFORE ${ITKTIFF_BINARY_DIR})
+
+INCLUDE_DIRECTORIES(${ITK_SOURCE_DIR}/Utilities/itkjpeg)
+INCLUDE_DIRECTORIES(${ITK_BINARY_DIR}/Utilities/itkjpeg/8)
+
+# library object files common to compression and decompression
+SET(common_SRCS
+tif_aux.c 
+tif_close.c 
+tif_codec.c 
+tif_compress.c
+tif_color.c
+tif_dir.c 
+tif_dirinfo.c 
+tif_dirread.c
+tif_dirwrite.c 
+tif_dumpmode.c 
+tif_error.c 
+tif_extension.c
+tif_fax3.c 
+tif_flush.c
+tif_getimage.c  
+tif_luv.c 
+tif_lzw.c 
+tif_next.c
+tif_ojpeg.c 
+tif_open.c 
+tif_packbits.c 
+tif_pixarlog.c 
+tif_predict.c
+tif_print.c 
+tif_read.c 
+tif_strip.c 
+tif_swab.c 
+tif_thunder.c 
+tif_tile.c
+tif_version.c 
+tif_warning.c
+tif_write.c 
+tif_zip.c
+tif_jpeg.c)
+
+ADD_DEFINITIONS(-DJPEG_SUPPORT  -DZIP_SUPPORT -D_HPUX_SOURCE)
+
+IF(WIN32)
+  IF(BUILD_SHARED_LIBS)
+    SET(TIFFDLL 1)
+  ELSE(BUILD_SHARED_LIBS)
+    SET(TIFFSTATIC 1)
+  ENDIF(BUILD_SHARED_LIBS)
+ENDIF(WIN32)
+
+IF(NOT UNIX)
+    ADD_DEFINITIONS( -DTIF_PLATFORM_CONSOLE )
+    SET(common_SRCS ${common_SRCS} tif_win32.c tif_fax3sm.c)
+    IF (NOT BORLAND)
+      IF(NOT MINGW)
+        SET(common_SRCS ${common_SRCS} itktiff.def)
+      ENDIF(NOT MINGW) 
+   ENDIF(NOT BORLAND)
+ELSE (NOT UNIX)
+  IF (CMAKE_MAJOR_VERSION MATCHES [1-9][0-9]*)
+    IF (CMAKE_MINOR_VERSION MATCHES [2-9][0-9]*)
+      SET(TIFF_RIGHT_VERSION 1)
+    ENDIF (CMAKE_MINOR_VERSION MATCHES [2-9][0-9]*)
+  ENDIF (CMAKE_MAJOR_VERSION MATCHES [1-9][0-9]*)
+
+  IF(TIFF_RIGHT_VERSION)
+    SET(common_SRCS ${common_SRCS} tif_unix.c tif_fax3sm.c)
+    SET_SOURCE_FILES_PROPERTIES(tif_fax3sm.c GENERATED)
+    ADD_EXECUTABLE(mkg3states mkg3states.c)    
+    IF(CYGWIN)
+      SET(EXE_EXTENSION .exe)
+    ENDIF(CYGWIN) 
+    ADD_CUSTOM_COMMAND(
+      OUTPUT ${ITKTIFF_BINARY_DIR}/tif_fax3sm.c
+      COMMAND ${EXECUTABLE_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/mkg3states${EXE_EXTENSION}
+      ARGS -c const ${ITKTIFF_BINARY_DIR}/tif_fax3sm.c
+      DEPENDS mkg3states
+    )
+  ELSE(TIFF_RIGHT_VERSION)
+      MESSAGE("The new TIFF reader requires CMake 1.2 or newer. Please get the new version of CMake from www.cmake.org.")
+  ENDIF(TIFF_RIGHT_VERSION)
+ENDIF (NOT UNIX)
+
+INCLUDE (${CMAKE_ROOT}/Modules/CheckIncludeFiles.cmake)
+INCLUDE(${CMAKE_ROOT}/Modules/CheckSymbolExists.cmake)
+INCLUDE(${CMAKE_ROOT}/Modules/CheckFunctionExists.cmake)
+
+# Check if header file exists and add it to the list.
+CHECK_INCLUDE_FILES("assert.h" HAVE_ASSERT_H)
+CHECK_INCLUDE_FILES("dlfcn.h" HAVE_DLFCN_H)
+CHECK_INCLUDE_FILES("fcntl.h" HAVE_FCNTL_H)
+CHECK_INCLUDE_FILES("inttypes.h" HAVE_INTTYPES_H)
+CHECK_INCLUDE_FILES("limits.h" HAVE_LIMITS_H)
+CHECK_INCLUDE_FILES("malloc.h" HAVE_MALLOC_H)
+CHECK_INCLUDE_FILES("memory.h" HAVE_MEMORY_H)
+CHECK_INCLUDE_FILES("stdint.h" HAVE_STDINT_H)
+CHECK_INCLUDE_FILES("stdlib.h" HAVE_STDLIB_H)
+CHECK_INCLUDE_FILES("string.h" HAVE_STRING_H)
+CHECK_INCLUDE_FILES("strings.h" HAVE_STRINGS_H)
+CHECK_INCLUDE_FILES("sys/stat.h" HAVE_SYS_STAT_H)
+CHECK_INCLUDE_FILES("sys/time.h" HAVE_SYS_TIME_H)
+CHECK_INCLUDE_FILES("sys/types.h" HAVE_SYS_TYPES_H)
+CHECK_INCLUDE_FILES("unistd.h" HAVE_UNISTD_H)
+CHECK_INCLUDE_FILES("windows.h" HAVE_WINDOWS_H)
+CHECK_INCLUDE_FILES("strings.h" HAVE_STRINGS_H)
+CHECK_INCLUDE_FILES("ieeefp.h" HAVE_IEEEFP_H)
+
+CHECK_FUNCTION_EXISTS(floor HAVE_FLOOR)
+CHECK_FUNCTION_EXISTS(getopt HAVE_GETOPT)
+CHECK_FUNCTION_EXISTS(isascii HAVE_ISASCII)
+CHECK_FUNCTION_EXISTS(memmove HAVE_MEMMOVE)
+CHECK_FUNCTION_EXISTS(memset HAVE_MEMSET)
+CHECK_FUNCTION_EXISTS(mmap HAVE_MMAP)
+CHECK_FUNCTION_EXISTS(pow HAVE_POW)
+CHECK_FUNCTION_EXISTS(sqrt HAVE_SQRT)
+CHECK_FUNCTION_EXISTS(strcasecmp HAVE_STRCASECMP)
+CHECK_FUNCTION_EXISTS(strchr HAVE_STRCHR)
+CHECK_FUNCTION_EXISTS(strrchr HAVE_STRRCHR)
+CHECK_FUNCTION_EXISTS(strstr HAVE_STRSTR)
+CHECK_FUNCTION_EXISTS(strtol HAVE_STRTOL)
+CHECK_FUNCTION_EXISTS(areroul HAVE_STRTOUL)
+
+
+IF("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.0)
+ELSE("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.0)
+INCLUDE(CheckTypeSize)
+ENDIF("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.0)
+
+CHECK_TYPE_SIZE("int" SIZEOF_INT)
+CHECK_TYPE_SIZE("long" SIZEOF_LONG)
+
+
+CONFIGURE_FILE(${ITKTIFF_SOURCE_DIR}/.NoDartCoverage
+               ${ITKTIFF_BINARY_DIR}/.NoDartCoverage)
+CONFIGURE_FILE(${ITKTIFF_SOURCE_DIR}/tiffDllConfig.h.in
+               ${ITKTIFF_BINARY_DIR}/tiffDllConfig.h)
+CONFIGURE_FILE(${ITKTIFF_SOURCE_DIR}/tif_config.h.in
+               ${ITKTIFF_BINARY_DIR}/tif_config.h)
+
+ADD_LIBRARY(itktiff ${common_SRCS})
+TARGET_LINK_LIBRARIES( itktiff ${ITK_ZLIB_LIBRARIES} itkjpeg8)
+
+IF(UNIX)
+TARGET_LINK_LIBRARIES(itktiff -lm)
+ENDIF(UNIX)
+
+INSTALL_TARGETS(/lib/InsightToolkit itktiff)
diff --git a/Utilities/ITK/Utilities/tiff/COPYRIGHT b/Utilities/ITK/Utilities/tiff/COPYRIGHT
new file mode 100644
index 0000000000..8282186151
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/COPYRIGHT
@@ -0,0 +1,21 @@
+Copyright (c) 1988-1997 Sam Leffler
+Copyright (c) 1991-1997 Silicon Graphics, Inc.
+
+Permission to use, copy, modify, distribute, and sell this software and 
+its documentation for any purpose is hereby granted without fee, provided
+that (i) the above copyright notices and this permission notice appear in
+all copies of the software and related documentation, and (ii) the names of
+Sam Leffler and Silicon Graphics may not be used in any advertising or
+publicity relating to the software without the specific, prior written
+permission of Sam Leffler and Silicon Graphics.
+
+THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+
+IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+OF THIS SOFTWARE.
diff --git a/Utilities/ITK/Utilities/tiff/README b/Utilities/ITK/Utilities/tiff/README
new file mode 100644
index 0000000000..cacaf55ab0
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/README
@@ -0,0 +1,59 @@
+$Header: /cvsroot/Insight/Insight/Utilities/tiff/README,v 1.2 2005/09/16 19:53:39 jjomier Exp $
+
+
+TIFF Software Distribution
+--------------------------
+This file is just a placeholder; all the documentation is now in
+HTML in the html directory.  To view the documentation point your
+favorite WWW viewer at html/index.html; e.g.
+
+    netscape html/index.html
+
+If you don't have an HTML viewer then you can read the HTML source
+or fetch a PostScript version of this documentation from the directory
+
+    ftp://ftp.remotesensing.org/pub/libtiff/
+
+If you can't hack either of these options then basically what you
+want to do is:
+
+    % ./configure
+    % make
+    % su
+    # make install
+
+More information, email contacts, and mailing list information can be 
+found online at http://www.remotesensing.org/libtiff/.
+
+
+Use and Copyright
+-----------------
+Silicon Graphics has seen fit to allow us to give this work away.  It
+is free.  There is no support or guarantee of any sort as to its
+operations, correctness, or whatever.  If you do anything useful with
+all or parts of it you need to honor the copyright notices.   I would
+also be interested in knowing about it and, hopefully, be acknowledged.
+
+The legal way of saying that is:
+
+Copyright (c) 1988-1997 Sam Leffler
+Copyright (c) 1991-1997 Silicon Graphics, Inc.
+
+Permission to use, copy, modify, distribute, and sell this software and 
+its documentation for any purpose is hereby granted without fee, provided
+that (i) the above copyright notices and this permission notice appear in
+all copies of the software and related documentation, and (ii) the names of
+Sam Leffler and Silicon Graphics may not be used in any advertising or
+publicity relating to the software without the specific, prior written
+permission of Sam Leffler and Silicon Graphics.
+
+THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+
+IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+OF THIS SOFTWARE.
diff --git a/Utilities/ITK/Utilities/tiff/RELEASE-DATE b/Utilities/ITK/Utilities/tiff/RELEASE-DATE
new file mode 100644
index 0000000000..4ba9f1d8cf
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/RELEASE-DATE
@@ -0,0 +1 @@
+20050315
diff --git a/Utilities/ITK/Utilities/tiff/VERSION b/Utilities/ITK/Utilities/tiff/VERSION
new file mode 100644
index 0000000000..0b2eb36f50
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/VERSION
@@ -0,0 +1 @@
+3.7.2
diff --git a/Utilities/ITK/Utilities/tiff/dist/newalpha b/Utilities/ITK/Utilities/tiff/dist/newalpha
new file mode 100644
index 0000000000..dc512503d3
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/dist/newalpha
@@ -0,0 +1,8 @@
+#! /bin/sh
+#	$Header: /cvsroot/Insight/Insight/Utilities/tiff/dist/newalpha,v 1.1 2003/11/25 14:11:12 jjomier Exp $
+if test -r tiff.alpha; then
+    ALPHA=`cat tiff.alpha`; rm -f tiff.alpha
+    echo "$ALPHA" | awk '{ printf "define ALPHA %1d\n", $3+1}' > tiff.alpha
+else
+    echo "define ALPHA 001" >tiff.alpha
+fi
diff --git a/Utilities/ITK/Utilities/tiff/dist/newversion b/Utilities/ITK/Utilities/tiff/dist/newversion
new file mode 100644
index 0000000000..3678a06acc
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/dist/newversion
@@ -0,0 +1,31 @@
+#! /bin/sh
+#	$Header: /cvsroot/Insight/Insight/Utilities/tiff/dist/newversion,v 1.1 2003/11/25 14:11:12 jjomier Exp $
+#
+# TIFF Software
+#
+# Copyright (c) 1994-1996 Sam Leffler
+# Copyright (c) 1994-1996 Silicon Graphics, Inc.
+# 
+# Permission to use, copy, modify, distribute, and sell this software and 
+# its documentation for any purpose is hereby granted without fee, provided
+# that (i) the above copyright notices and this permission notice appear in
+# all copies of the software and related documentation, and (ii) the names of
+# Sam Leffler and Silicon Graphics may not be used in any advertising or
+# publicity relating to the software without the specific, prior written
+# permission of Sam Leffler and Silicon Graphics.
+# 
+# THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+# EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+# WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+# 
+# IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+# ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+# OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+# LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+# OF THIS SOFTWARE.
+#
+rm -f tiff.version
+awk '
+{ print "define TIFF_VNUM \"" $1 " (" $2 ")\"" }
+' ../VERSION > tiff.version
diff --git a/Utilities/ITK/Utilities/tiff/dist/tiff.alpha b/Utilities/ITK/Utilities/tiff/dist/tiff.alpha
new file mode 100644
index 0000000000..a78fd0b8c4
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/dist/tiff.alpha
@@ -0,0 +1 @@
+define ALPHA 
diff --git a/Utilities/ITK/Utilities/tiff/dist/tiff.spec b/Utilities/ITK/Utilities/tiff/dist/tiff.spec
new file mode 100644
index 0000000000..71a4249340
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/dist/tiff.spec
@@ -0,0 +1,68 @@
+#	$Header: /cvsroot/Insight/Insight/Utilities/tiff/dist/tiff.spec,v 1.1 2003/11/25 14:11:12 jjomier Exp $
+#
+# TIFF Software
+#
+# Copyright (c) 1994-1997 Sam Leffler
+# Copyright (c) 1994-1997 Silicon Graphics, Inc.
+# 
+# Permission to use, copy, modify, distribute, and sell this software and 
+# its documentation for any purpose is hereby granted without fee, provided
+# that (i) the above copyright notices and this permission notice appear in
+# all copies of the software and related documentation, and (ii) the names of
+# Sam Leffler and Silicon Graphics may not be used in any advertising or
+# publicity relating to the software without the specific, prior written
+# permission of Sam Leffler and Silicon Graphics.
+# 
+# THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+# EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+# WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+# 
+# IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+# ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+# OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+# LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+# OF THIS SOFTWARE.
+#
+define CUR_MAJ_VERS	1006		# Major Version number
+define CUR_MIN_VERS	001		# Minor Version number
+define CUR_VERS		${CUR_MAJ_VERS}${CUR_MIN_VERS}${ALPHA}
+define TIFF_NAME	"TIFF"
+
+include tiff.version
+include tiff.alpha
+
+product tiff
+    id	"${TIFF_NAME} Tools, Version ${TIFF_VNUM}"
+    inplace
+
+    image sw
+	id	"${TIFF_NAME} Software"
+	version	"${CUR_VERS}"
+	subsys tools default
+	    id	"${TIFF_NAME} Tools & Library DSO"
+	    exp	"tiff.sw.tools"
+	endsubsys
+	subsys dev
+	    id	"${TIFF_NAME} Developement Software"
+	    exp	"tiff.sw.dev"
+	endsubsys
+    endimage
+
+    image man
+	id	"${TIFF_NAME} Documentation"
+	version	"${CUR_VERS}"
+	subsys tools default
+	    id	"${TIFF_NAME} Tools Manual Pages"
+	    exp	"tiff.man.tools"
+	endsubsys
+	subsys dev
+	    id	"${TIFF_NAME} Library Manual Pages"
+	    exp	"tiff.man.dev"
+	endsubsys
+	subsys html
+	    id	"${TIFF_NAME} HTML Materials"
+	    exp	"tiff.man.html"
+	endsubsys
+    endimage
+endproduct
diff --git a/Utilities/ITK/Utilities/tiff/dist/tiff.version b/Utilities/ITK/Utilities/tiff/dist/tiff.version
new file mode 100644
index 0000000000..9c5a223d76
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/dist/tiff.version
@@ -0,0 +1 @@
+define TIFF_VNUM "3.5.7 ()"
diff --git a/Utilities/ITK/Utilities/tiff/fax3sm_winnt.c b/Utilities/ITK/Utilities/tiff/fax3sm_winnt.c
new file mode 100644
index 0000000000..587fff11e2
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/fax3sm_winnt.c
@@ -0,0 +1,1047 @@
+/* WARNING, this file was automatically generated by the
+    mkg3states program */
+#include "tiff.h"
+#include "tif_fax3.h"
+#include "tiffconf.h"
+const  TIFFFaxTabEnt TIFFFaxMainTable[128] = {
+12,7,0,3,1,0,5,3,1,3,1,0,2,3,0,3,1,0,4,3,1,3,1,0,1,4,0,3,1,0,5,3,1,3,1,0,
+2,3,0,3,1,0,4,3,1,3,1,0,5,6,2,3,1,0,5,3,1,3,1,0,2,3,0,3,1,0,4,3,1,3,1,0,
+1,4,0,3,1,0,5,3,1,3,1,0,2,3,0,3,1,0,4,3,1,3,1,0,5,7,3,3,1,0,5,3,1,3,1,0,
+2,3,0,3,1,0,4,3,1,3,1,0,1,4,0,3,1,0,5,3,1,3,1,0,2,3,0,3,1,0,4,3,1,3,1,0,
+4,6,2,3,1,0,5,3,1,3,1,0,2,3,0,3,1,0,4,3,1,3,1,0,1,4,0,3,1,0,5,3,1,3,1,0,
+2,3,0,3,1,0,4,3,1,3,1,0,6,7,0,3,1,0,5,3,1,3,1,0,2,3,0,3,1,0,4,3,1,3,1,0,
+1,4,0,3,1,0,5,3,1,3,1,0,2,3,0,3,1,0,4,3,1,3,1,0,5,6,2,3,1,0,5,3,1,3,1,0,
+2,3,0,3,1,0,4,3,1,3,1,0,1,4,0,3,1,0,5,3,1,3,1,0,2,3,0,3,1,0,4,3,1,3,1,0,
+4,7,3,3,1,0,5,3,1,3,1,0,2,3,0,3,1,0,4,3,1,3,1,0,1,4,0,3,1,0,5,3,1,3,1,0,
+2,3,0,3,1,0,4,3,1,3,1,0,4,6,2,3,1,0,5,3,1,3,1,0,2,3,0,3,1,0,4,3,1,3,1,0,
+1,4,0,3,1,0,5,3,1,3,1,0,2,3,0,3,1,0,4,3,1,3,1,0
+};
+const TIFFFaxTabEnt TIFFFaxWhiteTable[4096] = {
+12,11,0,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,
+7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5,7,8,39,7,6,16,9,8,576,7,4,6,
+7,7,19,7,5,8,7,8,55,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,45,7,4,3,7,5,11,7,4,5,
+7,8,53,7,5,9,9,8,448,7,4,6,7,8,35,9,5,128,7,8,51,7,6,15,7,8,63,7,4,4,7,4,2,7,4,7,
+7,6,13,7,4,3,9,9,1472,7,4,5,7,8,43,7,6,17,9,9,1216,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,7,8,29,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,
+7,8,33,9,5,128,7,8,49,7,6,14,7,8,61,7,4,4,7,4,2,7,4,7,7,8,47,7,4,3,7,8,59,7,4,5,
+7,8,41,7,6,16,9,9,960,7,4,6,7,8,31,7,5,8,7,8,57,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,9,704,7,4,6,7,8,37,9,5,128,7,7,25,7,6,15,
+9,8,320,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,
+7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,11,11,1792,7,4,3,7,5,11,7,4,5,
+7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7,
+7,7,23,7,4,3,7,7,27,7,4,5,7,8,40,7,6,16,9,9,832,7,4,6,7,7,19,7,5,8,7,8,56,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,7,8,46,7,4,3,7,5,11,7,4,5,7,8,54,7,5,9,9,8,512,7,4,6,
+7,8,36,9,5,128,7,8,52,7,6,15,7,8,0,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1600,7,4,5,
+7,8,44,7,6,17,9,9,1344,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+7,8,30,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,8,34,9,5,128,7,8,50,7,6,14,
+7,8,62,7,4,4,7,4,2,7,4,7,7,8,48,7,4,3,7,8,60,7,4,5,7,8,42,7,6,16,9,9,1088,7,4,6,
+7,8,32,7,5,8,7,8,58,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5,
+7,7,26,7,5,9,9,8,640,7,4,6,7,8,38,9,5,128,7,7,25,7,6,15,9,8,384,7,4,4,7,4,2,7,4,7,
+7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,0,0,0,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,
+7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5,
+7,8,39,7,6,16,9,8,576,7,4,6,7,7,19,7,5,8,7,8,55,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+7,8,45,7,4,3,7,5,11,7,4,5,7,8,53,7,5,9,9,8,448,7,4,6,7,8,35,9,5,128,7,8,51,7,6,15,
+7,8,63,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1536,7,4,5,7,8,43,7,6,17,9,9,1280,7,4,6,
+7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,29,7,4,3,7,5,11,7,4,5,
+7,6,12,7,5,9,9,6,1664,7,4,6,7,8,33,9,5,128,7,8,49,7,6,14,7,8,61,7,4,4,7,4,2,7,4,7,
+7,8,47,7,4,3,7,8,59,7,4,5,7,8,41,7,6,16,9,9,1024,7,4,6,7,8,31,7,5,8,7,8,57,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,9,768,7,4,6,
+7,8,37,9,5,128,7,7,25,7,6,15,9,8,320,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5,
+7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+11,11,1856,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,
+7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5,7,8,40,7,6,16,9,9,896,7,4,6,
+7,7,19,7,5,8,7,8,56,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,46,7,4,3,7,5,11,7,4,5,
+7,8,54,7,5,9,9,8,512,7,4,6,7,8,36,9,5,128,7,8,52,7,6,15,7,8,0,7,4,4,7,4,2,7,4,7,
+7,6,13,7,4,3,9,9,1728,7,4,5,7,8,44,7,6,17,9,9,1408,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,7,8,30,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,
+7,8,34,9,5,128,7,8,50,7,6,14,7,8,62,7,4,4,7,4,2,7,4,7,7,8,48,7,4,3,7,8,60,7,4,5,
+7,8,42,7,6,16,9,9,1152,7,4,6,7,8,32,7,5,8,7,8,58,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,8,640,7,4,6,7,8,38,9,5,128,7,7,25,7,6,15,
+9,8,384,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,
+7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,0,0,0,7,4,3,7,5,11,7,4,5,
+7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7,
+7,7,23,7,4,3,7,7,27,7,4,5,7,8,39,7,6,16,9,8,576,7,4,6,7,7,19,7,5,8,7,8,55,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,7,8,45,7,4,3,7,5,11,7,4,5,7,8,53,7,5,9,9,8,448,7,4,6,
+7,8,35,9,5,128,7,8,51,7,6,15,7,8,63,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1472,7,4,5,
+7,8,43,7,6,17,9,9,1216,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+7,8,29,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,8,33,9,5,128,7,8,49,7,6,14,
+7,8,61,7,4,4,7,4,2,7,4,7,7,8,47,7,4,3,7,8,59,7,4,5,7,8,41,7,6,16,9,9,960,7,4,6,
+7,8,31,7,5,8,7,8,57,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5,
+7,7,26,7,5,9,9,9,704,7,4,6,7,8,37,9,5,128,7,7,25,7,6,15,9,8,320,7,4,4,7,4,2,7,4,7,
+7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,11,12,2112,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,
+7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5,
+7,8,40,7,6,16,9,9,832,7,4,6,7,7,19,7,5,8,7,8,56,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+7,8,46,7,4,3,7,5,11,7,4,5,7,8,54,7,5,9,9,8,512,7,4,6,7,8,36,9,5,128,7,8,52,7,6,15,
+7,8,0,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1600,7,4,5,7,8,44,7,6,17,9,9,1344,7,4,6,
+7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,30,7,4,3,7,5,11,7,4,5,
+7,6,12,7,5,9,9,6,1664,7,4,6,7,8,34,9,5,128,7,8,50,7,6,14,7,8,62,7,4,4,7,4,2,7,4,7,
+7,8,48,7,4,3,7,8,60,7,4,5,7,8,42,7,6,16,9,9,1088,7,4,6,7,8,32,7,5,8,7,8,58,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,8,640,7,4,6,
+7,8,38,9,5,128,7,7,25,7,6,15,9,8,384,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5,
+7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+0,0,0,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,
+7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5,7,8,39,7,6,16,9,8,576,7,4,6,
+7,7,19,7,5,8,7,8,55,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,45,7,4,3,7,5,11,7,4,5,
+7,8,53,7,5,9,9,8,448,7,4,6,7,8,35,9,5,128,7,8,51,7,6,15,7,8,63,7,4,4,7,4,2,7,4,7,
+7,6,13,7,4,3,9,9,1536,7,4,5,7,8,43,7,6,17,9,9,1280,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,7,8,29,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,
+7,8,33,9,5,128,7,8,49,7,6,14,7,8,61,7,4,4,7,4,2,7,4,7,7,8,47,7,4,3,7,8,59,7,4,5,
+7,8,41,7,6,16,9,9,1024,7,4,6,7,8,31,7,5,8,7,8,57,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,9,768,7,4,6,7,8,37,9,5,128,7,7,25,7,6,15,
+9,8,320,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,
+7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,11,12,2368,7,4,3,7,5,11,7,4,5,
+7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7,
+7,7,23,7,4,3,7,7,27,7,4,5,7,8,40,7,6,16,9,9,896,7,4,6,7,7,19,7,5,8,7,8,56,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,7,8,46,7,4,3,7,5,11,7,4,5,7,8,54,7,5,9,9,8,512,7,4,6,
+7,8,36,9,5,128,7,8,52,7,6,15,7,8,0,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1728,7,4,5,
+7,8,44,7,6,17,9,9,1408,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+7,8,30,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,8,34,9,5,128,7,8,50,7,6,14,
+7,8,62,7,4,4,7,4,2,7,4,7,7,8,48,7,4,3,7,8,60,7,4,5,7,8,42,7,6,16,9,9,1152,7,4,6,
+7,8,32,7,5,8,7,8,58,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5,
+7,7,26,7,5,9,9,8,640,7,4,6,7,8,38,9,5,128,7,7,25,7,6,15,9,8,384,7,4,4,7,4,2,7,4,7,
+7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,0,0,0,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,
+7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5,
+7,8,39,7,6,16,9,8,576,7,4,6,7,7,19,7,5,8,7,8,55,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+7,8,45,7,4,3,7,5,11,7,4,5,7,8,53,7,5,9,9,8,448,7,4,6,7,8,35,9,5,128,7,8,51,7,6,15,
+7,8,63,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1472,7,4,5,7,8,43,7,6,17,9,9,1216,7,4,6,
+7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,29,7,4,3,7,5,11,7,4,5,
+7,6,12,7,5,9,9,6,1664,7,4,6,7,8,33,9,5,128,7,8,49,7,6,14,7,8,61,7,4,4,7,4,2,7,4,7,
+7,8,47,7,4,3,7,8,59,7,4,5,7,8,41,7,6,16,9,9,960,7,4,6,7,8,31,7,5,8,7,8,57,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,9,704,7,4,6,
+7,8,37,9,5,128,7,7,25,7,6,15,9,8,320,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5,
+7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+11,12,1984,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,
+7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5,7,8,40,7,6,16,9,9,832,7,4,6,
+7,7,19,7,5,8,7,8,56,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,46,7,4,3,7,5,11,7,4,5,
+7,8,54,7,5,9,9,8,512,7,4,6,7,8,36,9,5,128,7,8,52,7,6,15,7,8,0,7,4,4,7,4,2,7,4,7,
+7,6,13,7,4,3,9,9,1600,7,4,5,7,8,44,7,6,17,9,9,1344,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,7,8,30,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,
+7,8,34,9,5,128,7,8,50,7,6,14,7,8,62,7,4,4,7,4,2,7,4,7,7,8,48,7,4,3,7,8,60,7,4,5,
+7,8,42,7,6,16,9,9,1088,7,4,6,7,8,32,7,5,8,7,8,58,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,8,640,7,4,6,7,8,38,9,5,128,7,7,25,7,6,15,
+9,8,384,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,
+7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,0,0,0,7,4,3,7,5,11,7,4,5,
+7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7,
+7,7,23,7,4,3,7,7,27,7,4,5,7,8,39,7,6,16,9,8,576,7,4,6,7,7,19,7,5,8,7,8,55,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,7,8,45,7,4,3,7,5,11,7,4,5,7,8,53,7,5,9,9,8,448,7,4,6,
+7,8,35,9,5,128,7,8,51,7,6,15,7,8,63,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1536,7,4,5,
+7,8,43,7,6,17,9,9,1280,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+7,8,29,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,8,33,9,5,128,7,8,49,7,6,14,
+7,8,61,7,4,4,7,4,2,7,4,7,7,8,47,7,4,3,7,8,59,7,4,5,7,8,41,7,6,16,9,9,1024,7,4,6,
+7,8,31,7,5,8,7,8,57,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5,
+7,7,26,7,5,9,9,9,768,7,4,6,7,8,37,9,5,128,7,7,25,7,6,15,9,8,320,7,4,4,7,4,2,7,4,7,
+7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,11,11,1920,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,
+7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5,
+7,8,40,7,6,16,9,9,896,7,4,6,7,7,19,7,5,8,7,8,56,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+7,8,46,7,4,3,7,5,11,7,4,5,7,8,54,7,5,9,9,8,512,7,4,6,7,8,36,9,5,128,7,8,52,7,6,15,
+7,8,0,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1728,7,4,5,7,8,44,7,6,17,9,9,1408,7,4,6,
+7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,30,7,4,3,7,5,11,7,4,5,
+7,6,12,7,5,9,9,6,1664,7,4,6,7,8,34,9,5,128,7,8,50,7,6,14,7,8,62,7,4,4,7,4,2,7,4,7,
+7,8,48,7,4,3,7,8,60,7,4,5,7,8,42,7,6,16,9,9,1152,7,4,6,7,8,32,7,5,8,7,8,58,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,8,640,7,4,6,
+7,8,38,9,5,128,7,7,25,7,6,15,9,8,384,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5,
+7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+0,0,0,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,
+7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5,7,8,39,7,6,16,9,8,576,7,4,6,
+7,7,19,7,5,8,7,8,55,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,45,7,4,3,7,5,11,7,4,5,
+7,8,53,7,5,9,9,8,448,7,4,6,7,8,35,9,5,128,7,8,51,7,6,15,7,8,63,7,4,4,7,4,2,7,4,7,
+7,6,13,7,4,3,9,9,1472,7,4,5,7,8,43,7,6,17,9,9,1216,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,7,8,29,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,
+7,8,33,9,5,128,7,8,49,7,6,14,7,8,61,7,4,4,7,4,2,7,4,7,7,8,47,7,4,3,7,8,59,7,4,5,
+7,8,41,7,6,16,9,9,960,7,4,6,7,8,31,7,5,8,7,8,57,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,9,704,7,4,6,7,8,37,9,5,128,7,7,25,7,6,15,
+9,8,320,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,
+7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,11,12,2240,7,4,3,7,5,11,7,4,5,
+7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7,
+7,7,23,7,4,3,7,7,27,7,4,5,7,8,40,7,6,16,9,9,832,7,4,6,7,7,19,7,5,8,7,8,56,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,7,8,46,7,4,3,7,5,11,7,4,5,7,8,54,7,5,9,9,8,512,7,4,6,
+7,8,36,9,5,128,7,8,52,7,6,15,7,8,0,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1600,7,4,5,
+7,8,44,7,6,17,9,9,1344,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+7,8,30,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,8,34,9,5,128,7,8,50,7,6,14,
+7,8,62,7,4,4,7,4,2,7,4,7,7,8,48,7,4,3,7,8,60,7,4,5,7,8,42,7,6,16,9,9,1088,7,4,6,
+7,8,32,7,5,8,7,8,58,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5,
+7,7,26,7,5,9,9,8,640,7,4,6,7,8,38,9,5,128,7,7,25,7,6,15,9,8,384,7,4,4,7,4,2,7,4,7,
+7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,0,0,0,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,
+7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5,
+7,8,39,7,6,16,9,8,576,7,4,6,7,7,19,7,5,8,7,8,55,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+7,8,45,7,4,3,7,5,11,7,4,5,7,8,53,7,5,9,9,8,448,7,4,6,7,8,35,9,5,128,7,8,51,7,6,15,
+7,8,63,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1536,7,4,5,7,8,43,7,6,17,9,9,1280,7,4,6,
+7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,29,7,4,3,7,5,11,7,4,5,
+7,6,12,7,5,9,9,6,1664,7,4,6,7,8,33,9,5,128,7,8,49,7,6,14,7,8,61,7,4,4,7,4,2,7,4,7,
+7,8,47,7,4,3,7,8,59,7,4,5,7,8,41,7,6,16,9,9,1024,7,4,6,7,8,31,7,5,8,7,8,57,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,9,768,7,4,6,
+7,8,37,9,5,128,7,7,25,7,6,15,9,8,320,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5,
+7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+11,12,2496,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,
+7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5,7,8,40,7,6,16,9,9,896,7,4,6,
+7,7,19,7,5,8,7,8,56,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,46,7,4,3,7,5,11,7,4,5,
+7,8,54,7,5,9,9,8,512,7,4,6,7,8,36,9,5,128,7,8,52,7,6,15,7,8,0,7,4,4,7,4,2,7,4,7,
+7,6,13,7,4,3,9,9,1728,7,4,5,7,8,44,7,6,17,9,9,1408,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,7,8,30,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,
+7,8,34,9,5,128,7,8,50,7,6,14,7,8,62,7,4,4,7,4,2,7,4,7,7,8,48,7,4,3,7,8,60,7,4,5,
+7,8,42,7,6,16,9,9,1152,7,4,6,7,8,32,7,5,8,7,8,58,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,8,640,7,4,6,7,8,38,9,5,128,7,7,25,7,6,15,
+9,8,384,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,
+7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,12,11,0,7,4,3,7,5,11,7,4,5,
+7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7,
+7,7,23,7,4,3,7,7,27,7,4,5,7,8,39,7,6,16,9,8,576,7,4,6,7,7,19,7,5,8,7,8,55,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,7,8,45,7,4,3,7,5,11,7,4,5,7,8,53,7,5,9,9,8,448,7,4,6,
+7,8,35,9,5,128,7,8,51,7,6,15,7,8,63,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1472,7,4,5,
+7,8,43,7,6,17,9,9,1216,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+7,8,29,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,8,33,9,5,128,7,8,49,7,6,14,
+7,8,61,7,4,4,7,4,2,7,4,7,7,8,47,7,4,3,7,8,59,7,4,5,7,8,41,7,6,16,9,9,960,7,4,6,
+7,8,31,7,5,8,7,8,57,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5,
+7,7,26,7,5,9,9,9,704,7,4,6,7,8,37,9,5,128,7,7,25,7,6,15,9,8,320,7,4,4,7,4,2,7,4,7,
+7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,11,11,1792,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,
+7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5,
+7,8,40,7,6,16,9,9,832,7,4,6,7,7,19,7,5,8,7,8,56,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+7,8,46,7,4,3,7,5,11,7,4,5,7,8,54,7,5,9,9,8,512,7,4,6,7,8,36,9,5,128,7,8,52,7,6,15,
+7,8,0,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1600,7,4,5,7,8,44,7,6,17,9,9,1344,7,4,6,
+7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,30,7,4,3,7,5,11,7,4,5,
+7,6,12,7,5,9,9,6,1664,7,4,6,7,8,34,9,5,128,7,8,50,7,6,14,7,8,62,7,4,4,7,4,2,7,4,7,
+7,8,48,7,4,3,7,8,60,7,4,5,7,8,42,7,6,16,9,9,1088,7,4,6,7,8,32,7,5,8,7,8,58,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,8,640,7,4,6,
+7,8,38,9,5,128,7,7,25,7,6,15,9,8,384,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5,
+7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+0,0,0,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,
+7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5,7,8,39,7,6,16,9,8,576,7,4,6,
+7,7,19,7,5,8,7,8,55,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,45,7,4,3,7,5,11,7,4,5,
+7,8,53,7,5,9,9,8,448,7,4,6,7,8,35,9,5,128,7,8,51,7,6,15,7,8,63,7,4,4,7,4,2,7,4,7,
+7,6,13,7,4,3,9,9,1536,7,4,5,7,8,43,7,6,17,9,9,1280,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,7,8,29,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,
+7,8,33,9,5,128,7,8,49,7,6,14,7,8,61,7,4,4,7,4,2,7,4,7,7,8,47,7,4,3,7,8,59,7,4,5,
+7,8,41,7,6,16,9,9,1024,7,4,6,7,8,31,7,5,8,7,8,57,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,9,768,7,4,6,7,8,37,9,5,128,7,7,25,7,6,15,
+9,8,320,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,
+7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,11,11,1856,7,4,3,7,5,11,7,4,5,
+7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7,
+7,7,23,7,4,3,7,7,27,7,4,5,7,8,40,7,6,16,9,9,896,7,4,6,7,7,19,7,5,8,7,8,56,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,7,8,46,7,4,3,7,5,11,7,4,5,7,8,54,7,5,9,9,8,512,7,4,6,
+7,8,36,9,5,128,7,8,52,7,6,15,7,8,0,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1728,7,4,5,
+7,8,44,7,6,17,9,9,1408,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+7,8,30,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,8,34,9,5,128,7,8,50,7,6,14,
+7,8,62,7,4,4,7,4,2,7,4,7,7,8,48,7,4,3,7,8,60,7,4,5,7,8,42,7,6,16,9,9,1152,7,4,6,
+7,8,32,7,5,8,7,8,58,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5,
+7,7,26,7,5,9,9,8,640,7,4,6,7,8,38,9,5,128,7,7,25,7,6,15,9,8,384,7,4,4,7,4,2,7,4,7,
+7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,0,0,0,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,
+7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5,
+7,8,39,7,6,16,9,8,576,7,4,6,7,7,19,7,5,8,7,8,55,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+7,8,45,7,4,3,7,5,11,7,4,5,7,8,53,7,5,9,9,8,448,7,4,6,7,8,35,9,5,128,7,8,51,7,6,15,
+7,8,63,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1472,7,4,5,7,8,43,7,6,17,9,9,1216,7,4,6,
+7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,29,7,4,3,7,5,11,7,4,5,
+7,6,12,7,5,9,9,6,1664,7,4,6,7,8,33,9,5,128,7,8,49,7,6,14,7,8,61,7,4,4,7,4,2,7,4,7,
+7,8,47,7,4,3,7,8,59,7,4,5,7,8,41,7,6,16,9,9,960,7,4,6,7,8,31,7,5,8,7,8,57,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,9,704,7,4,6,
+7,8,37,9,5,128,7,7,25,7,6,15,9,8,320,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5,
+7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+11,12,2176,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,
+7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5,7,8,40,7,6,16,9,9,832,7,4,6,
+7,7,19,7,5,8,7,8,56,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,46,7,4,3,7,5,11,7,4,5,
+7,8,54,7,5,9,9,8,512,7,4,6,7,8,36,9,5,128,7,8,52,7,6,15,7,8,0,7,4,4,7,4,2,7,4,7,
+7,6,13,7,4,3,9,9,1600,7,4,5,7,8,44,7,6,17,9,9,1344,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,7,8,30,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,
+7,8,34,9,5,128,7,8,50,7,6,14,7,8,62,7,4,4,7,4,2,7,4,7,7,8,48,7,4,3,7,8,60,7,4,5,
+7,8,42,7,6,16,9,9,1088,7,4,6,7,8,32,7,5,8,7,8,58,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,8,640,7,4,6,7,8,38,9,5,128,7,7,25,7,6,15,
+9,8,384,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,
+7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,0,0,0,7,4,3,7,5,11,7,4,5,
+7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7,
+7,7,23,7,4,3,7,7,27,7,4,5,7,8,39,7,6,16,9,8,576,7,4,6,7,7,19,7,5,8,7,8,55,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,7,8,45,7,4,3,7,5,11,7,4,5,7,8,53,7,5,9,9,8,448,7,4,6,
+7,8,35,9,5,128,7,8,51,7,6,15,7,8,63,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1536,7,4,5,
+7,8,43,7,6,17,9,9,1280,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+7,8,29,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,8,33,9,5,128,7,8,49,7,6,14,
+7,8,61,7,4,4,7,4,2,7,4,7,7,8,47,7,4,3,7,8,59,7,4,5,7,8,41,7,6,16,9,9,1024,7,4,6,
+7,8,31,7,5,8,7,8,57,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5,
+7,7,26,7,5,9,9,9,768,7,4,6,7,8,37,9,5,128,7,7,25,7,6,15,9,8,320,7,4,4,7,4,2,7,4,7,
+7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,11,12,2432,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,
+7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5,
+7,8,40,7,6,16,9,9,896,7,4,6,7,7,19,7,5,8,7,8,56,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+7,8,46,7,4,3,7,5,11,7,4,5,7,8,54,7,5,9,9,8,512,7,4,6,7,8,36,9,5,128,7,8,52,7,6,15,
+7,8,0,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1728,7,4,5,7,8,44,7,6,17,9,9,1408,7,4,6,
+7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,30,7,4,3,7,5,11,7,4,5,
+7,6,12,7,5,9,9,6,1664,7,4,6,7,8,34,9,5,128,7,8,50,7,6,14,7,8,62,7,4,4,7,4,2,7,4,7,
+7,8,48,7,4,3,7,8,60,7,4,5,7,8,42,7,6,16,9,9,1152,7,4,6,7,8,32,7,5,8,7,8,58,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,8,640,7,4,6,
+7,8,38,9,5,128,7,7,25,7,6,15,9,8,384,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5,
+7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+0,0,0,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,
+7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5,7,8,39,7,6,16,9,8,576,7,4,6,
+7,7,19,7,5,8,7,8,55,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,45,7,4,3,7,5,11,7,4,5,
+7,8,53,7,5,9,9,8,448,7,4,6,7,8,35,9,5,128,7,8,51,7,6,15,7,8,63,7,4,4,7,4,2,7,4,7,
+7,6,13,7,4,3,9,9,1472,7,4,5,7,8,43,7,6,17,9,9,1216,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,7,8,29,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,
+7,8,33,9,5,128,7,8,49,7,6,14,7,8,61,7,4,4,7,4,2,7,4,7,7,8,47,7,4,3,7,8,59,7,4,5,
+7,8,41,7,6,16,9,9,960,7,4,6,7,8,31,7,5,8,7,8,57,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,9,704,7,4,6,7,8,37,9,5,128,7,7,25,7,6,15,
+9,8,320,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,
+7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,11,12,2048,7,4,3,7,5,11,7,4,5,
+7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7,
+7,7,23,7,4,3,7,7,27,7,4,5,7,8,40,7,6,16,9,9,832,7,4,6,7,7,19,7,5,8,7,8,56,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,7,8,46,7,4,3,7,5,11,7,4,5,7,8,54,7,5,9,9,8,512,7,4,6,
+7,8,36,9,5,128,7,8,52,7,6,15,7,8,0,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1600,7,4,5,
+7,8,44,7,6,17,9,9,1344,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+7,8,30,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,8,34,9,5,128,7,8,50,7,6,14,
+7,8,62,7,4,4,7,4,2,7,4,7,7,8,48,7,4,3,7,8,60,7,4,5,7,8,42,7,6,16,9,9,1088,7,4,6,
+7,8,32,7,5,8,7,8,58,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5,
+7,7,26,7,5,9,9,8,640,7,4,6,7,8,38,9,5,128,7,7,25,7,6,15,9,8,384,7,4,4,7,4,2,7,4,7,
+7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,0,0,0,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,
+7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5,
+7,8,39,7,6,16,9,8,576,7,4,6,7,7,19,7,5,8,7,8,55,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+7,8,45,7,4,3,7,5,11,7,4,5,7,8,53,7,5,9,9,8,448,7,4,6,7,8,35,9,5,128,7,8,51,7,6,15,
+7,8,63,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1536,7,4,5,7,8,43,7,6,17,9,9,1280,7,4,6,
+7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,29,7,4,3,7,5,11,7,4,5,
+7,6,12,7,5,9,9,6,1664,7,4,6,7,8,33,9,5,128,7,8,49,7,6,14,7,8,61,7,4,4,7,4,2,7,4,7,
+7,8,47,7,4,3,7,8,59,7,4,5,7,8,41,7,6,16,9,9,1024,7,4,6,7,8,31,7,5,8,7,8,57,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,9,768,7,4,6,
+7,8,37,9,5,128,7,7,25,7,6,15,9,8,320,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5,
+7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+11,11,1920,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,
+7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5,7,8,40,7,6,16,9,9,896,7,4,6,
+7,7,19,7,5,8,7,8,56,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,46,7,4,3,7,5,11,7,4,5,
+7,8,54,7,5,9,9,8,512,7,4,6,7,8,36,9,5,128,7,8,52,7,6,15,7,8,0,7,4,4,7,4,2,7,4,7,
+7,6,13,7,4,3,9,9,1728,7,4,5,7,8,44,7,6,17,9,9,1408,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,7,8,30,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,
+7,8,34,9,5,128,7,8,50,7,6,14,7,8,62,7,4,4,7,4,2,7,4,7,7,8,48,7,4,3,7,8,60,7,4,5,
+7,8,42,7,6,16,9,9,1152,7,4,6,7,8,32,7,5,8,7,8,58,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,8,640,7,4,6,7,8,38,9,5,128,7,7,25,7,6,15,
+9,8,384,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,
+7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,0,0,0,7,4,3,7,5,11,7,4,5,
+7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7,
+7,7,23,7,4,3,7,7,27,7,4,5,7,8,39,7,6,16,9,8,576,7,4,6,7,7,19,7,5,8,7,8,55,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,7,8,45,7,4,3,7,5,11,7,4,5,7,8,53,7,5,9,9,8,448,7,4,6,
+7,8,35,9,5,128,7,8,51,7,6,15,7,8,63,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1472,7,4,5,
+7,8,43,7,6,17,9,9,1216,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+7,8,29,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,8,33,9,5,128,7,8,49,7,6,14,
+7,8,61,7,4,4,7,4,2,7,4,7,7,8,47,7,4,3,7,8,59,7,4,5,7,8,41,7,6,16,9,9,960,7,4,6,
+7,8,31,7,5,8,7,8,57,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5,
+7,7,26,7,5,9,9,9,704,7,4,6,7,8,37,9,5,128,7,7,25,7,6,15,9,8,320,7,4,4,7,4,2,7,4,7,
+7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,11,12,2304,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,
+7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5,
+7,8,40,7,6,16,9,9,832,7,4,6,7,7,19,7,5,8,7,8,56,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+7,8,46,7,4,3,7,5,11,7,4,5,7,8,54,7,5,9,9,8,512,7,4,6,7,8,36,9,5,128,7,8,52,7,6,15,
+7,8,0,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1600,7,4,5,7,8,44,7,6,17,9,9,1344,7,4,6,
+7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,30,7,4,3,7,5,11,7,4,5,
+7,6,12,7,5,9,9,6,1664,7,4,6,7,8,34,9,5,128,7,8,50,7,6,14,7,8,62,7,4,4,7,4,2,7,4,7,
+7,8,48,7,4,3,7,8,60,7,4,5,7,8,42,7,6,16,9,9,1088,7,4,6,7,8,32,7,5,8,7,8,58,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,8,640,7,4,6,
+7,8,38,9,5,128,7,7,25,7,6,15,9,8,384,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5,
+7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+0,0,0,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,
+7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5,7,8,39,7,6,16,9,8,576,7,4,6,
+7,7,19,7,5,8,7,8,55,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,45,7,4,3,7,5,11,7,4,5,
+7,8,53,7,5,9,9,8,448,7,4,6,7,8,35,9,5,128,7,8,51,7,6,15,7,8,63,7,4,4,7,4,2,7,4,7,
+7,6,13,7,4,3,9,9,1536,7,4,5,7,8,43,7,6,17,9,9,1280,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,7,8,29,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,
+7,8,33,9,5,128,7,8,49,7,6,14,7,8,61,7,4,4,7,4,2,7,4,7,7,8,47,7,4,3,7,8,59,7,4,5,
+7,8,41,7,6,16,9,9,1024,7,4,6,7,8,31,7,5,8,7,8,57,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,9,768,7,4,6,7,8,37,9,5,128,7,7,25,7,6,15,
+9,8,320,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,
+7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,11,12,2560,7,4,3,7,5,11,7,4,5,
+7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7,
+7,7,23,7,4,3,7,7,27,7,4,5,7,8,40,7,6,16,9,9,896,7,4,6,7,7,19,7,5,8,7,8,56,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7,7,8,46,7,4,3,7,5,11,7,4,5,7,8,54,7,5,9,9,8,512,7,4,6,
+7,8,36,9,5,128,7,8,52,7,6,15,7,8,0,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1728,7,4,5,
+7,8,44,7,6,17,9,9,1408,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,
+7,8,30,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,8,34,9,5,128,7,8,50,7,6,14,
+7,8,62,7,4,4,7,4,2,7,4,7,7,8,48,7,4,3,7,8,60,7,4,5,7,8,42,7,6,16,9,9,1152,7,4,6,
+7,8,32,7,5,8,7,8,58,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5,
+7,7,26,7,5,9,9,8,640,7,4,6,7,8,38,9,5,128,7,7,25,7,6,15,9,8,384,7,4,4,7,4,2,7,4,7,
+7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,
+7,5,10,7,4,4,7,4,2,7,4,7
+};
+const  TIFFFaxTabEnt TIFFFaxBlackTable[8192] = {
+12,11,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,9,15,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,10,18,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,10,17,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,11,11,1792,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,11,23,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,11,20,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,11,25,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,10,12,128,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,56,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,12,30,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+11,11,1856,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,57,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,11,21,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,12,54,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,9,15,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,12,52,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,48,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,11,12,2112,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,12,44,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,12,36,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,10,12,384,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,12,28,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,12,60,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,12,40,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,11,12,2368,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,10,16,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,10,0,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+10,10,64,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,9,15,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,10,18,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,10,17,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+11,12,1984,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,50,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,12,34,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,10,13,1664,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,26,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+10,13,1408,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,32,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,11,11,1920,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,12,61,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,12,42,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,10,13,1024,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,9,15,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,10,13,768,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,12,62,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,11,12,2240,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,12,46,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,38,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+10,13,512,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,11,19,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,11,24,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,11,22,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+11,12,2496,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,10,16,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,10,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,10,10,64,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,12,11,0,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,9,15,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,10,18,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,10,17,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,11,11,1792,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,11,23,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,11,20,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,11,25,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+10,12,192,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,10,13,1280,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,12,31,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,11,11,1856,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,12,58,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,11,21,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+10,13,896,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,9,15,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,10,13,640,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,12,49,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+11,12,2176,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,45,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,12,37,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,10,12,448,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,29,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+10,13,1536,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,41,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,11,12,2432,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,10,16,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,10,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,10,10,64,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,9,15,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,10,18,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,10,17,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,11,12,2048,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,12,51,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,35,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+10,12,320,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,12,27,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,59,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,12,33,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+11,11,1920,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,10,12,256,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,12,43,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,10,13,1152,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,9,15,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,12,55,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,63,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,11,12,2304,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,12,47,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,12,39,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,53,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,11,19,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,11,24,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,11,22,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,11,12,2560,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,10,16,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,10,0,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+10,10,64,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,12,11,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,9,15,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,10,18,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,10,17,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+11,11,1792,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,11,23,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,11,20,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,11,25,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,10,12,128,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,12,56,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,30,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,11,11,1856,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,12,57,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,11,21,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,54,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,9,15,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,12,52,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,12,48,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,11,12,2112,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,12,44,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,36,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+10,12,384,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,12,28,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,60,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,12,40,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+11,12,2368,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,10,16,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,10,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,10,10,64,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,9,15,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,10,18,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,10,17,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,11,12,1984,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,12,50,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,12,34,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,10,13,1728,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,12,26,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,10,13,1472,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,12,32,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,11,11,1920,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,12,61,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,42,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+10,13,1088,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,9,15,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,10,13,832,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,12,62,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+11,12,2240,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,46,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,12,38,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,10,13,576,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,11,19,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,11,24,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,11,22,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,11,12,2496,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,10,16,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,10,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,10,10,64,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+12,11,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,9,15,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,10,18,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,10,17,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,11,11,1792,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,11,23,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,11,20,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,11,25,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,10,12,192,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,10,13,1344,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,12,31,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+11,11,1856,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,58,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,11,21,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,10,13,960,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,9,15,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+10,13,704,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,49,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,11,12,2176,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,12,45,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,12,37,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,10,12,448,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,12,29,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,10,13,1600,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,12,41,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,11,12,2432,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,10,16,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,10,0,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+10,10,64,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,9,15,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,10,18,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,10,17,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+11,12,2048,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,51,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,12,35,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,10,12,320,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,27,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,12,59,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,33,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,11,11,1920,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+10,12,256,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,12,43,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,10,13,1216,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,9,15,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,12,55,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,12,63,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,11,12,2304,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,12,47,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,39,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,12,53,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,11,19,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,11,24,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,11,22,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+11,12,2560,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,10,16,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,10,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,10,10,64,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,
+8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,
+8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,
+8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,
+8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2
+};
diff --git a/Utilities/ITK/Utilities/tiff/itk_tiff_mangle.h b/Utilities/ITK/Utilities/tiff/itk_tiff_mangle.h
new file mode 100644
index 0000000000..6a615d8e4e
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/itk_tiff_mangle.h
@@ -0,0 +1,260 @@
+#ifndef itk_tiff_mangle_h
+#define itk_tiff_mangle_h
+
+/*
+
+
+This header file mangles all symbols exported from the tiff library.
+It is included in all files while building the tiff library.  Due to
+namespace pollution, no tiff headers should be included in .h files in
+ITK.
+
+The following commands were used to obtain the symbol list:
+
+nm libitktiff.a |grep " T "
+nm libitktiff.a |grep " D "
+nm libitktiff.a |grep " R "
+
+*/
+
+#define __TIFFmalloc itk___TIFFmalloc
+#define __TIFFfree itk___TIFFfree
+#define _TIFFerrorHandler itk__TIFFerrorHandler
+#define _TIFFwarningHandler itk__TIFFwarningHandler
+#define tiffDataWidth itk_tiffDataWidth
+#define LogL10fromY itk_LogL10fromY
+#define LogL10toY itk_LogL10toY
+#define LogL16fromY itk_LogL16fromY
+#define LogL16toY itk_LogL16toY
+#define LogLuv24fromXYZ itk_LogLuv24fromXYZ
+#define LogLuv24toXYZ itk_LogLuv24toXYZ
+#define LogLuv32fromXYZ itk_LogLuv32fromXYZ
+#define LogLuv32toXYZ itk_LogLuv32toXYZ
+#define TIFFCheckTile itk_TIFFCheckTile
+#define TIFFClientOpen itk_TIFFClientOpen
+#define TIFFClose itk_TIFFClose
+#define TIFFComputeStrip itk_TIFFComputeStrip
+#define TIFFComputeTile itk_TIFFComputeTile
+#define TIFFCreateDirectory itk_TIFFCreateDirectory
+#define TIFFCurrentDirOffset itk_TIFFCurrentDirOffset
+#define TIFFCurrentDirectory itk_TIFFCurrentDirectory
+#define TIFFCurrentRow itk_TIFFCurrentRow
+#define TIFFCurrentStrip itk_TIFFCurrentStrip
+#define TIFFCurrentTile itk_TIFFCurrentTile
+#define TIFFDefaultDirectory itk_TIFFDefaultDirectory
+#define TIFFDefaultStripSize itk_TIFFDefaultStripSize
+#define TIFFDefaultTileSize itk_TIFFDefaultTileSize
+#define TIFFError itk_TIFFError
+#define TIFFFdOpen itk_TIFFFdOpen
+#define TIFFFileName itk_TIFFFileName
+#define TIFFFileno itk_TIFFFileno
+#define TIFFFindCODEC itk_TIFFFindCODEC
+#define TIFFFlush itk_TIFFFlush
+#define TIFFFlushData itk_TIFFFlushData
+#define TIFFFlushData1 itk_TIFFFlushData1
+#define TIFFFreeDirectory itk_TIFFFreeDirectory
+#define TIFFGetBitRevTable itk_TIFFGetBitRevTable
+#define TIFFGetField itk_TIFFGetField
+#define TIFFGetFieldDefaulted itk_TIFFGetFieldDefaulted
+#define TIFFGetMode itk_TIFFGetMode
+#define TIFFGetVersion itk_TIFFGetVersion
+#define TIFFInitDumpMode itk_TIFFInitDumpMode
+
+#ifdef  LZW_SUPPORT
+ #define  TIFFInitLZW    itk_TIFFInitLZW
+#endif
+#ifdef  PACKBITS_SUPPORT
+#define  TIFFInitPackBits  itk_TIFFInitPackBits
+#endif
+#ifdef  THUNDER_SUPPORT
+#define TIFFInitThunderScan itk_TIFFInitThunderScan
+#endif
+#ifdef  NEXT_SUPPORT
+#define  TIFFInitNeXT    itk_TIFFInitNeXT
+#endif
+#ifdef  JPEG_SUPPORT
+#define  TIFFInitJPEG    itk_TIFFInitJPEG
+#endif
+#ifdef  OJPEG_SUPPORT
+#define  TIFFInitOJPEG    itk_TIFFInitOJPEG
+#endif
+#ifdef  CCITT_SUPPORT
+#define  TIFFInitCCITTRLE  itk_TIFFInitCCITTRLE
+#define  TIFFInitCCITTRLEW  itk_TIFFInitCCITTRLEW
+#define  TIFFInitCCITTFax3  itk_TIFFInitCCITTFax3
+#define  TIFFInitCCITTFax4  itk_TIFFInitCCITTFax4
+#endif
+#ifdef JBIG_SUPPORT
+#define  TIFFInitJBIG    itk_TIFFInitJBIG
+#endif
+#ifdef  ZIP_SUPPORT
+#define  TIFFInitZIP    itk_TIFFInitZIP
+#endif
+#ifdef  PIXARLOG_SUPPORT
+#define  TIFFInitPixarLog  itk_TIFFInitPixarLog
+#endif
+#ifdef LOGLUV_SUPPORT
+#define TIFFInitSGILog    itk_TIFFInitSGILog
+#endif
+
+#define TIFFIsByteSwapped itk_TIFFIsByteSwapped
+#define TIFFIsMSB2LSB itk_TIFFIsMSB2LSB
+#define TIFFIsTiled itk_TIFFIsTiled
+#define TIFFIsUpSampled itk_TIFFIsUpSampled
+#define TIFFLastDirectory itk_TIFFLastDirectory
+#define TIFFNumberOfDirectories itk_TIFFNumberOfDirectories
+#define TIFFNumberOfStrips itk_TIFFNumberOfStrips
+#define TIFFNumberOfTiles itk_TIFFNumberOfTiles
+#define TIFFOpen itk_TIFFOpen
+#define TIFFPredictorInit itk_TIFFPredictorInit
+#define TIFFPrintDirectory itk_TIFFPrintDirectory
+#define TIFFRGBAImageBegin itk_TIFFRGBAImageBegin
+#define TIFFRGBAImageEnd itk_TIFFRGBAImageEnd
+#define TIFFRGBAImageGet itk_TIFFRGBAImageGet
+#define TIFFRGBAImageOK itk_TIFFRGBAImageOK
+#define TIFFRasterScanlineSize itk_TIFFRasterScanlineSize
+#define TIFFReadBufferSetup itk_TIFFReadBufferSetup
+#define TIFFReadDirectory itk_TIFFReadDirectory
+#define TIFFReadEncodedStrip itk_TIFFReadEncodedStrip
+#define TIFFReadEncodedTile itk_TIFFReadEncodedTile
+#define TIFFReadRGBAImage itk_TIFFReadRGBAImage
+#define TIFFReadRGBAStrip itk_TIFFReadRGBAStrip
+#define TIFFReadRGBATile itk_TIFFReadRGBATile
+#define TIFFReadRawStrip itk_TIFFReadRawStrip
+#define TIFFReadRawTile itk_TIFFReadRawTile
+#define TIFFReadScanline itk_TIFFReadScanline
+#define TIFFReadTile itk_TIFFReadTile
+#define TIFFReassignTagToIgnore itk_TIFFReassignTagToIgnore
+#define TIFFRegisterCODEC itk_TIFFRegisterCODEC
+#define TIFFReverseBits itk_TIFFReverseBits
+#define TIFFRewriteDirectory itk_TIFFRewriteDirectory
+#define TIFFScanlineSize itk_TIFFScanlineSize
+#define TIFFSetCompressionScheme itk_TIFFSetCompressionScheme
+#define TIFFSetDirectory itk_TIFFSetDirectory
+#define TIFFSetErrorHandler itk_TIFFSetErrorHandler
+#define TIFFSetField itk_TIFFSetField
+#define TIFFSetSubDirectory itk_TIFFSetSubDirectory
+#define TIFFSetTagExtender itk_TIFFSetTagExtender
+#define TIFFSetWarningHandler itk_TIFFSetWarningHandler
+#define TIFFSetWriteOffset itk_TIFFSetWriteOffset
+#define TIFFStripSize itk_TIFFStripSize
+#define TIFFSwabArrayOfDouble itk_TIFFSwabArrayOfDouble
+#define TIFFSwabArrayOfLong itk_TIFFSwabArrayOfLong
+#define TIFFSwabArrayOfShort itk_TIFFSwabArrayOfShort
+#define TIFFSwabDouble itk_TIFFSwabDouble
+#define TIFFSwabLong itk_TIFFSwabLong
+#define TIFFSwabShort itk_TIFFSwabShort
+#define TIFFTileRowSize itk_TIFFTileRowSize
+#define TIFFTileSize itk_TIFFTileSize
+#define TIFFUnRegisterCODEC itk_TIFFUnRegisterCODEC
+#define TIFFUnlinkDirectory itk_TIFFUnlinkDirectory
+#define TIFFVGetField itk_TIFFVGetField
+#define TIFFVGetFieldDefaulted itk_TIFFVGetFieldDefaulted
+#define TIFFVSetField itk_TIFFVSetField
+#define TIFFVStripSize itk_TIFFVStripSize
+#define TIFFVTileSize itk_TIFFVTileSize
+#define TIFFWarning itk_TIFFWarning
+#define TIFFWriteBufferSetup itk_TIFFWriteBufferSetup
+#define TIFFWriteCheck itk_TIFFWriteCheck
+#define TIFFWriteDirectory itk_TIFFWriteDirectory
+#define TIFFWriteEncodedStrip itk_TIFFWriteEncodedStrip
+#define TIFFWriteEncodedTile itk_TIFFWriteEncodedTile
+#define TIFFWriteRawStrip itk_TIFFWriteRawStrip
+#define TIFFWriteRawTile itk_TIFFWriteRawTile
+#define TIFFWriteScanline itk_TIFFWriteScanline
+#define TIFFWriteTile itk_TIFFWriteTile
+#define XYZtoRGB24 itk_XYZtoRGB24
+#define _TIFFDefaultStripSize itk__TIFFDefaultStripSize
+#define _TIFFDefaultTileSize itk__TIFFDefaultTileSize
+#define _TIFFFax3fillruns itk__TIFFFax3fillruns
+#define TIFFFieldWithTag itk_TIFFFieldWithTag
+#define TIFFFindFieldInfo itk_TIFFFindFieldInfo
+#define TIFFMergeFieldInfo itk_TIFFMergeFieldInfo
+
+#define _TIFFNoPostDecode itk__TIFFNoPostDecode
+#define _TIFFNoPreCode itk__TIFFNoPreCode
+#define _TIFFNoRowDecode itk__TIFFNoRowDecode
+#define _TIFFNoRowEncode itk__TIFFNoRowEncode
+#define _TIFFNoSeek itk__TIFFNoSeek
+#define _TIFFNoStripDecode itk__TIFFNoStripDecode
+#define _TIFFNoStripEncode itk__TIFFNoStripEncode
+#define _TIFFNoTileDecode itk__TIFFNoTileDecode
+#define _TIFFNoTileEncode itk__TIFFNoTileEncode
+#define _TIFFPrintFieldInfo itk__TIFFPrintFieldInfo
+#define _TIFFSampleToTagType itk__TIFFSampleToTagType
+#define _TIFFSetDefaultCompressionState itk__TIFFSetDefaultCompressionState
+#define _TIFFSetupFieldInfo itk__TIFFSetupFieldInfo
+#define _TIFFSwab16BitData itk__TIFFSwab16BitData
+#define _TIFFSwab32BitData itk__TIFFSwab32BitData
+#define _TIFFSwab64BitData itk__TIFFSwab64BitData
+#define _TIFFfree itk__TIFFfree
+#define _TIFFgetMode itk__TIFFgetMode
+#define _TIFFmalloc itk__TIFFmalloc
+#define _TIFFmemcmp itk__TIFFmemcmp
+#define _TIFFmemcpy itk__TIFFmemcpy
+#define _TIFFmemset itk__TIFFmemset
+#define _TIFFprintAscii itk__TIFFprintAscii
+#define _TIFFprintAsciiTag itk__TIFFprintAsciiTag
+#define _TIFFrealloc itk__TIFFrealloc
+#define _TIFFsetByteArray itk__TIFFsetByteArray
+#define _TIFFsetDoubleArray itk__TIFFsetDoubleArray
+#define _TIFFsetFloatArray itk__TIFFsetFloatArray
+#define _TIFFsetLongArray itk__TIFFsetLongArray
+#define _TIFFsetNString itk__TIFFsetNString
+#define _TIFFsetShortArray itk__TIFFsetShortArray
+#define _TIFFsetString itk__TIFFsetString
+#define uv_decode itk_uv_decode
+#define uv_encode itk_uv_encode
+#define TIFFCvtIEEEFloatToNative itk_TIFFCvtIEEEFloatToNative
+#define TIFFCvtIEEEDoubleToNative itk_TIFFCvtIEEEDoubleToNative
+#define TIFFYCbCrToRGBInit itk_TIFFYCbCrToRGBInit
+#define TIFFYCbCrtoRGB itk_TIFFYCbCrtoRGB
+#define TIFFCIELabToRGBInit itk_TIFFCIELabToRGBInit
+#define TIFFXYZToRGB itk_TIFFXYZToRGB
+#define TIFFCIELabToXYZ itk_TIFFCIELabToXYZ
+#define TIFFCvtNativeToIEEEFloat itk_TIFFCvtNativeToIEEEFloat
+#define _TIFFFaxBlackTable itk__TIFFFaxBlackTable
+#define _TIFFFaxWhiteTable itk__TIFFFaxWhiteTable
+#define _TIFFFaxMainTable itk__TIFFFaxMainTable
+#define TIFFDataWidth itk_TIFFDataWidth
+#define _TIFFCreateAnonFieldInfo itk__TIFFCreateAnonFieldInfo
+#define _TIFFFindOrRegisterFieldInfo itk__TIFFFindOrRegisterFieldInfo
+#define TIFFRawStripSize itk__TIFFRawStripSize
+#define TIFFFillStrip itk_TIFFFillStrip
+#define TIFFFillTile itk_TIFFFillTile
+#define TIFFSetupStrips itk_TIFFSetupStrips
+#define TIFFCheckpointDirectory itk_TIFFCheckpointDirectory
+
+#define TIFFAccessTagMethods itk_TIFFAccessTagMethods
+#define TIFFCleanup itk_TIFFCleanup
+#define TIFFClientdata itk_TIFFClientdata
+#define TIFFGetClientInfo itk_TIFFGetClientInfo
+#define TIFFGetCloseProc itk_TIFFGetCloseProc
+#define TIFFGetConfiguredCODECs itk_TIFFGetConfiguredCODECs
+#define TIFFGetMapFileProc itk_TIFFGetMapFileProc
+#define TIFFGetReadProc itk_TIFFGetReadProc
+#define TIFFGetSeekProc itk_TIFFGetSeekProc
+#define TIFFGetSizeProc itk_TIFFGetSizeProc
+#define TIFFGetTagListCount itk_TIFFGetTagListCount
+#define TIFFGetTagListEntry itk_TIFFGetTagListEntry
+#define TIFFGetUnmapFileProc itk_TIFFGetUnmapFileProc
+#define TIFFGetWriteProc itk_TIFFGetWriteProc
+#define TIFFIsBigEndian itk_TIFFIsBigEndian
+#define TIFFIsCODECConfigured itk_TIFFIsCODECConfigured
+#define TIFFReadRGBAImageOriented itk_TIFFReadRGBAImageOriented
+#define TIFFSetClientdata itk_TIFFSetClientdata
+#define TIFFSetClientInfo itk_TIFFSetClientInfo
+#define TIFFSetFileName itk_TIFFSetFileName
+#define TIFFSetFileno itk_TIFFSetFileno
+#define TIFFSetMode itk_TIFFSetMode
+
+#define display_sRGB itk_display_sRGB
+#define _TIFFBuiltinCODECS itk_TIFFBuiltinCODECS
+
+#define TIFFFaxBlackCodes itk_TIFFFaxBlackCodes
+#define TIFFFaxBlackTable itk_TIFFFaxBlackTable
+#define TIFFFaxMainTable itk_TIFFFaxMainTable
+#define TIFFFaxWhiteCodes itk_TIFFFaxWhiteCodes
+#define TIFFFaxWhiteTable itk_TIFFFaxWhiteTable
+
+#endif
diff --git a/Utilities/ITK/Utilities/tiff/itktiff.def b/Utilities/ITK/Utilities/tiff/itktiff.def
new file mode 100644
index 0000000000..10f0bb3e69
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/itktiff.def
@@ -0,0 +1,88 @@
+
+EXPORTS TIFFOpen
+	TIFFGetVersion
+	TIFFClose
+	TIFFFlush
+	TIFFFlushData
+	TIFFGetField
+	TIFFVGetField
+	TIFFGetFieldDefaulted
+	TIFFVGetFieldDefaulted
+	TIFFReadDirectory
+	TIFFScanlineSize
+	TIFFStripSize
+	TIFFVStripSize
+	TIFFTileRowSize
+	TIFFTileSize
+	TIFFVTileSize
+	TIFFFileno
+	TIFFGetMode
+	TIFFIsTiled
+	TIFFIsByteSwapped
+	TIFFCurrentRow
+	TIFFCurrentDirectory
+	TIFFCurrentStrip
+	TIFFCurrentTile
+	TIFFReadBufferSetup
+	TIFFLastDirectory
+	TIFFSetDirectory
+	TIFFSetSubDirectory
+	TIFFUnlinkDirectory
+	TIFFSetField
+	TIFFVSetField
+	TIFFWriteDirectory
+	TIFFRewriteDirectory
+	TIFFPrintDirectory
+	TIFFReadScanline
+	TIFFWriteScanline
+	TIFFReadRGBAImage
+	TIFFPrintDirectory
+	TIFFReadScanline
+	TIFFWriteScanline
+	TIFFReadRGBAImage
+	TIFFFdOpen
+	TIFFClientOpen
+	TIFFFileName
+	TIFFError
+	TIFFWarning
+	TIFFSetErrorHandler
+	TIFFSetWarningHandler
+	TIFFComputeTile
+	TIFFCheckTile
+	TIFFNumberOfTiles
+	TIFFReadTile
+	TIFFWriteTile
+	TIFFComputeStrip
+	TIFFNumberOfStrips
+	TIFFReadEncodedStrip
+	TIFFReadRawStrip
+	TIFFReadEncodedTile
+	TIFFReadRawTile
+	TIFFReadRGBATile
+	TIFFReadRGBAStrip
+	TIFFWriteEncodedStrip
+	TIFFWriteRawStrip
+	TIFFWriteEncodedTile
+	TIFFWriteRawTile
+	TIFFSetWriteOffset
+	TIFFSwabShort
+	TIFFSwabLong
+	TIFFSwabArrayOfShort
+	TIFFSwabArrayOfLong
+	TIFFSwabArrayOfDouble
+	TIFFReverseBits
+	TIFFGetBitRevTable
+	TIFFDefaultStripSize
+	TIFFDefaultTileSize
+	TIFFRasterScanlineSize
+	_TIFFmalloc
+	_TIFFrealloc
+	_TIFFfree
+	_TIFFmemset
+	_TIFFmemcpy
+	_TIFFmemcmp
+	TIFFCreateDirectory
+	TIFFDefaultStripSize
+
+
+
diff --git a/Utilities/ITK/Utilities/tiff/mkg3states.c b/Utilities/ITK/Utilities/tiff/mkg3states.c
new file mode 100644
index 0000000000..2e86d41f89
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/mkg3states.c
@@ -0,0 +1,439 @@
+/* "$Id$ */
+
+/*
+ * Copyright (c) 1991-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/* Initialise fax decoder tables
+ * Decoder support is derived, with permission, from the code
+ * in Frank Cringle's viewfax program;
+ *      Copyright (C) 1990, 1995  Frank D. Cringle.
+ */
+#include "tif_config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include "tif_fax3.h"
+
+#define  streq(a,b)  (strcmp(a,b) == 0)
+
+/* NB: can't use names in tif_fax3.h 'cuz they are declared const */
+TIFFFaxTabEnt MainTable[128];
+TIFFFaxTabEnt WhiteTable[4096];
+TIFFFaxTabEnt BlackTable[8192];
+
+struct proto {
+    uint16 code;    /* right justified, lsb-first, zero filled */
+    uint16 val;    /* (pixel count)<<4 + code width  */
+};
+
+static struct proto Pass[] = {
+{ 0x0008, 4 },
+{ 0, 0 }
+};
+
+static struct proto Horiz[]  = {
+{ 0x0004, 3 },
+{ 0, 0 }
+};
+
+static struct proto V0[]  = {
+{ 0x0001, 1 },
+{ 0, 0 }
+};
+
+static struct proto VR[]  = {
+{ 0x0006, (1<<4)+3 },
+{ 0x0030, (2<<4)+6 },
+{ 0x0060, (3<<4)+7 },
+{ 0, 0 }
+};
+
+static struct proto VL[]  = {
+{ 0x0002, (1<<4)+3 },
+{ 0x0010, (2<<4)+6 },
+{ 0x0020, (3<<4)+7 },
+{ 0, 0 }
+};
+
+static struct proto Ext[]  = {
+{ 0x0040, 7 },
+{ 0, 0 }
+};
+
+static struct proto EOLV[]  = {
+{ 0x0000, 7 },
+{ 0, 0 }
+};
+
+static struct proto MakeUpW[] = {
+{ 0x001b, 1029 },
+{ 0x0009, 2053 },
+{ 0x003a, 3078 },
+{ 0x0076, 4103 },
+{ 0x006c, 5128 },
+{ 0x00ec, 6152 },
+{ 0x0026, 7176 },
+{ 0x00a6, 8200 },
+{ 0x0016, 9224 },
+{ 0x00e6, 10248 },
+{ 0x0066, 11273 },
+{ 0x0166, 12297 },
+{ 0x0096, 13321 },
+{ 0x0196, 14345 },
+{ 0x0056, 15369 },
+{ 0x0156, 16393 },
+{ 0x00d6, 17417 },
+{ 0x01d6, 18441 },
+{ 0x0036, 19465 },
+{ 0x0136, 20489 },
+{ 0x00b6, 21513 },
+{ 0x01b6, 22537 },
+{ 0x0032, 23561 },
+{ 0x0132, 24585 },
+{ 0x00b2, 25609 },
+{ 0x0006, 26630 },
+{ 0x01b2, 27657 },
+{ 0, 0 }
+};
+
+static struct proto MakeUpB[] = {
+{ 0x03c0, 1034 },
+{ 0x0130, 2060 },
+{ 0x0930, 3084 },
+{ 0x0da0, 4108 },
+{ 0x0cc0, 5132 },
+{ 0x02c0, 6156 },
+{ 0x0ac0, 7180 },
+{ 0x06c0, 8205 },
+{ 0x16c0, 9229 },
+{ 0x0a40, 10253 },
+{ 0x1a40, 11277 },
+{ 0x0640, 12301 },
+{ 0x1640, 13325 },
+{ 0x09c0, 14349 },
+{ 0x19c0, 15373 },
+{ 0x05c0, 16397 },
+{ 0x15c0, 17421 },
+{ 0x0dc0, 18445 },
+{ 0x1dc0, 19469 },
+{ 0x0940, 20493 },
+{ 0x1940, 21517 },
+{ 0x0540, 22541 },
+{ 0x1540, 23565 },
+{ 0x0b40, 24589 },
+{ 0x1b40, 25613 },
+{ 0x04c0, 26637 },
+{ 0x14c0, 27661 },
+{ 0, 0 }
+};
+
+static struct proto MakeUp[] = {
+{ 0x0080, 28683 },
+{ 0x0180, 29707 },
+{ 0x0580, 30731 },
+{ 0x0480, 31756 },
+{ 0x0c80, 32780 },
+{ 0x0280, 33804 },
+{ 0x0a80, 34828 },
+{ 0x0680, 35852 },
+{ 0x0e80, 36876 },
+{ 0x0380, 37900 },
+{ 0x0b80, 38924 },
+{ 0x0780, 39948 },
+{ 0x0f80, 40972 },
+{ 0, 0 }
+};
+
+static struct proto TermW[] = {
+{ 0x00ac, 8 },
+{ 0x0038, 22 },
+{ 0x000e, 36 },
+{ 0x0001, 52 },
+{ 0x000d, 68 },
+{ 0x0003, 84 },
+{ 0x0007, 100 },
+{ 0x000f, 116 },
+{ 0x0019, 133 },
+{ 0x0005, 149 },
+{ 0x001c, 165 },
+{ 0x0002, 181 },
+{ 0x0004, 198 },
+{ 0x0030, 214 },
+{ 0x000b, 230 },
+{ 0x002b, 246 },
+{ 0x0015, 262 },
+{ 0x0035, 278 },
+{ 0x0072, 295 },
+{ 0x0018, 311 },
+{ 0x0008, 327 },
+{ 0x0074, 343 },
+{ 0x0060, 359 },
+{ 0x0010, 375 },
+{ 0x000a, 391 },
+{ 0x006a, 407 },
+{ 0x0064, 423 },
+{ 0x0012, 439 },
+{ 0x000c, 455 },
+{ 0x0040, 472 },
+{ 0x00c0, 488 },
+{ 0x0058, 504 },
+{ 0x00d8, 520 },
+{ 0x0048, 536 },
+{ 0x00c8, 552 },
+{ 0x0028, 568 },
+{ 0x00a8, 584 },
+{ 0x0068, 600 },
+{ 0x00e8, 616 },
+{ 0x0014, 632 },
+{ 0x0094, 648 },
+{ 0x0054, 664 },
+{ 0x00d4, 680 },
+{ 0x0034, 696 },
+{ 0x00b4, 712 },
+{ 0x0020, 728 },
+{ 0x00a0, 744 },
+{ 0x0050, 760 },
+{ 0x00d0, 776 },
+{ 0x004a, 792 },
+{ 0x00ca, 808 },
+{ 0x002a, 824 },
+{ 0x00aa, 840 },
+{ 0x0024, 856 },
+{ 0x00a4, 872 },
+{ 0x001a, 888 },
+{ 0x009a, 904 },
+{ 0x005a, 920 },
+{ 0x00da, 936 },
+{ 0x0052, 952 },
+{ 0x00d2, 968 },
+{ 0x004c, 984 },
+{ 0x00cc, 1000 },
+{ 0x002c, 1016 },
+{ 0, 0 }
+};
+
+static struct proto TermB[] = {
+{ 0x03b0, 10 },
+{ 0x0002, 19 },
+{ 0x0003, 34 },
+{ 0x0001, 50 },
+{ 0x0006, 67 },
+{ 0x000c, 84 },
+{ 0x0004, 100 },
+{ 0x0018, 117 },
+{ 0x0028, 134 },
+{ 0x0008, 150 },
+{ 0x0010, 167 },
+{ 0x0050, 183 },
+{ 0x0070, 199 },
+{ 0x0020, 216 },
+{ 0x00e0, 232 },
+{ 0x0030, 249 },
+{ 0x03a0, 266 },
+{ 0x0060, 282 },
+{ 0x0040, 298 },
+{ 0x0730, 315 },
+{ 0x00b0, 331 },
+{ 0x01b0, 347 },
+{ 0x0760, 363 },
+{ 0x00a0, 379 },
+{ 0x0740, 395 },
+{ 0x00c0, 411 },
+{ 0x0530, 428 },
+{ 0x0d30, 444 },
+{ 0x0330, 460 },
+{ 0x0b30, 476 },
+{ 0x0160, 492 },
+{ 0x0960, 508 },
+{ 0x0560, 524 },
+{ 0x0d60, 540 },
+{ 0x04b0, 556 },
+{ 0x0cb0, 572 },
+{ 0x02b0, 588 },
+{ 0x0ab0, 604 },
+{ 0x06b0, 620 },
+{ 0x0eb0, 636 },
+{ 0x0360, 652 },
+{ 0x0b60, 668 },
+{ 0x05b0, 684 },
+{ 0x0db0, 700 },
+{ 0x02a0, 716 },
+{ 0x0aa0, 732 },
+{ 0x06a0, 748 },
+{ 0x0ea0, 764 },
+{ 0x0260, 780 },
+{ 0x0a60, 796 },
+{ 0x04a0, 812 },
+{ 0x0ca0, 828 },
+{ 0x0240, 844 },
+{ 0x0ec0, 860 },
+{ 0x01c0, 876 },
+{ 0x0e40, 892 },
+{ 0x0140, 908 },
+{ 0x01a0, 924 },
+{ 0x09a0, 940 },
+{ 0x0d40, 956 },
+{ 0x0340, 972 },
+{ 0x05a0, 988 },
+{ 0x0660, 1004 },
+{ 0x0e60, 1020 },
+{ 0, 0 }
+};
+
+static struct proto EOLH[] = {
+{ 0x0000, 11 },
+{ 0, 0 }
+};
+
+static void
+FillTable(TIFFFaxTabEnt *T, int Size, struct proto *P, int State)
+{
+    int limit = 1 << Size;
+
+    while (P->val) {
+  int width = P->val & 15;
+  int param = P->val >> 4;
+  int incr = 1 << width;
+  int code;
+  for (code = P->code; code < limit; code += incr) {
+      TIFFFaxTabEnt *E = T+code;
+      E->State = State;
+      E->Width = width;
+      E->Param = param;
+  }
+  P++;
+    }
+}
+
+static  char* storage_class = "";
+static  char* const_class = "";
+static  int packoutput = 1;
+static  char* prebrace = "{";
+static  char* postbrace = "}";
+
+void
+WriteTable(FILE* fd, const TIFFFaxTabEnt* T, int Size, const char* name)
+{
+    int i;
+    char* sep;
+
+    fprintf(fd, "%s %s TIFFFaxTabEnt %s[%d] = {",
+  storage_class, const_class, name, Size);
+    if (packoutput) {
+  sep = "\n";
+  for (i = 0; i < Size; i++) {
+      fprintf(fd, "%s%s%d,%d,%d%s",
+    sep, prebrace, T->State, T->Width, (int) T->Param, postbrace);
+      if (((i+1) % 10) == 0)
+        sep = ",\n";
+      else
+        sep = ",";
+      T++;
+  }
+    } else {
+  sep = "\n ";
+  for (i = 0; i < Size; i++) {
+      fprintf(fd, "%s%s%3d,%3d,%4d%s",
+    sep, prebrace, T->State, T->Width, (int) T->Param, postbrace);
+      if (((i+1) % 6) == 0)
+        sep = ",\n ";
+      else
+        sep = ",";
+      T++;
+  }
+    }
+    fprintf(fd, "\n};\n");
+}
+
+/* initialise the huffman code tables */
+int
+main(int argc, char* argv[])
+{
+    FILE* fd;
+    char* outputfile;
+    int c;
+    extern int optind;
+    extern char* optarg;
+
+    while ((c = getopt(argc, argv, "c:s:bp")) != -1)
+  switch (c) {
+  case 'c':
+      const_class = optarg;
+      break;
+  case 's':
+      storage_class = optarg;
+      break;
+  case 'p':
+      packoutput = 0;
+      break;
+  case 'b':
+      prebrace = "{";
+      postbrace = "}";
+      break;
+  case '?':
+      fprintf(stderr,
+    "usage: %s [-c const] [-s storage] [-p] [-b] file\n",
+    argv[0]);
+      return (-1);
+  }
+    outputfile = optind < argc ? argv[optind] : "g3states.h";
+    fd = fopen(outputfile, "w");
+    if (fd == NULL) {
+  fprintf(stderr, "%s: %s: Cannot create output file.\n",
+      argv[0], outputfile);
+  return (-2);
+    }
+    FillTable(MainTable, 7, Pass, S_Pass);
+    FillTable(MainTable, 7, Horiz, S_Horiz);
+    FillTable(MainTable, 7, V0, S_V0);
+    FillTable(MainTable, 7, VR, S_VR);
+    FillTable(MainTable, 7, VL, S_VL);
+    FillTable(MainTable, 7, Ext, S_Ext);
+    FillTable(MainTable, 7, EOLV, S_EOL);
+    FillTable(WhiteTable, 12, MakeUpW, S_MakeUpW);
+    FillTable(WhiteTable, 12, MakeUp, S_MakeUp);
+    FillTable(WhiteTable, 12, TermW, S_TermW);
+    FillTable(WhiteTable, 12, EOLH, S_EOL);
+    FillTable(BlackTable, 13, MakeUpB, S_MakeUpB);
+    FillTable(BlackTable, 13, MakeUp, S_MakeUp);
+    FillTable(BlackTable, 13, TermB, S_TermB);
+    FillTable(BlackTable, 13, EOLH, S_EOL);
+
+    fprintf(fd, "/* WARNING, this file was automatically generated by the\n");
+    fprintf(fd, "    mkg3states program */\n");
+    fprintf(fd, "#include \"tiff.h\"\n");
+    fprintf(fd, "#include \"tif_fax3.h\"\n");
+    WriteTable(fd, MainTable, 128, "TIFFFaxMainTable");
+    WriteTable(fd, WhiteTable, 4096, "TIFFFaxWhiteTable");
+    WriteTable(fd, BlackTable, 8192, "TIFFFaxBlackTable");
+    fclose(fd);
+    return (0);
+}
+
diff --git a/Utilities/ITK/Utilities/tiff/mkspans.c b/Utilities/ITK/Utilities/tiff/mkspans.c
new file mode 100644
index 0000000000..b25600d833
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/mkspans.c
@@ -0,0 +1,72 @@
+/* $Header: /cvsroot/Insight/Insight/Utilities/tiff/mkspans.c,v 1.1 2003/11/25 14:10:11 jjomier Exp $ */
+
+/*
+ * Copyright (c) 1991-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+#include "tiffcomp.h"
+
+/*
+ * Hack program to construct tables used to find
+ * runs of zeros and ones in Group 3 Fax encoding.
+ */
+
+dumparray(name, runs)
+        char *name;
+        unsigned char runs[256];
+{
+        register int i;
+        register char *sep;
+        printf("static u_char %s[256] = {\n", name);
+        sep = "    ";
+        for (i = 0; i < 256; i++) {
+                printf("%s%d", sep, runs[i]);
+                if (((i + 1) % 16) == 0) {
+                        printf(",       /* 0x%02x - 0x%02x */\n", i-15, i);
+                        sep = "    ";
+                } else
+                        sep = ", ";
+        }
+        printf("\n};\n");
+}
+
+main()
+{
+        unsigned char runs[2][256];
+
+        memset(runs[0], 0, 256*sizeof (char));
+        memset(runs[1], 0, 256*sizeof (char));
+        { register int run, runlen, i;
+          runlen = 1;
+          for (run = 0x80; run != 0xff; run = (run>>1)|0x80) {
+                for (i = run-1; i >= 0; i--) {
+                        runs[1][run|i] = runlen;
+                        runs[0][(~(run|i)) & 0xff] = runlen;
+                }
+                runlen++;
+          }
+          runs[1][0xff] = runs[0][0] = 8;
+        }
+        dumparray("bruns", runs[0]);
+        dumparray("wruns", runs[1]);
+}
diff --git a/Utilities/ITK/Utilities/tiff/mkversion.c b/Utilities/ITK/Utilities/tiff/mkversion.c
new file mode 100644
index 0000000000..974481d03b
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/mkversion.c
@@ -0,0 +1,175 @@
+/* "$Header: /cvsroot/Insight/Insight/Utilities/tiff/mkversion.c,v 1.1 2003/11/25 14:10:11 jjomier Exp $ */
+
+/*
+ * Copyright (c) 1995-1997 Sam Leffler
+ * Copyright (c) 1995-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * Generate a library version string for systems that
+ * do not have a shell (by default this is done with
+ * awk and echo from the Makefile).
+ *
+ * This was written by Peter Greenham for Acorn systems.
+ *
+ * Syntax: mkversion [-v version-file] [-a alpha-file] [<outfile>]
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static void
+usage(void)
+{
+    fprintf(stderr,
+            "usage: mkversion [-v version-file] [-a alpha-file]\n"
+            "                 [-r releasedate-file] [outfile]\n");
+    exit(-1);
+}
+
+static FILE*
+openFile(char* filename)
+{
+    FILE* fd = fopen(filename, "r");
+    if (fd == NULL) {
+        fprintf(stderr, "mkversion: %s: Could not open for reading.\n",
+            filename);
+        exit(-1);
+    }
+    return (fd);
+}
+
+int
+main(int argc, char* argv[])
+{
+    char* versionFile = "VERSION";
+    char* releaseDateFile = "RELEASE-DATE";
+    char* alphaFile = "dist/tiff.alpha";
+    char version[128];
+    char rawReleaseDate[128];
+    char tiffLibVersion[128];
+    char alpha[128];
+    FILE* fd;
+    char* cp;
+
+    argc--, argv++;
+    while (argc > 0 && argv[0][0] == '-') {
+        if (strcmp(argv[0], "-v") == 0) {
+            if (argc < 1)
+                usage();
+            argc--, argv++;
+            versionFile = argv[0];
+        } else if (strcmp(argv[0], "-a") == 0) {
+            if (argc < 1)
+                usage();
+            argc--, argv++;
+            alphaFile = argv[0];
+        } else if (strcmp(argv[0], "-r") == 0) {
+            if (argc < 1)
+                usage();
+            argc--, argv++;
+            releaseDateFile = argv[0];
+        } else
+            usage();
+        argc--, argv++;
+    }
+
+    /*
+     * Read the VERSION file.
+     */
+    fd = openFile(versionFile);
+    if (fgets(version, sizeof (version)-1, fd) == NULL) {
+        fprintf(stderr, "mkversion: No version information in %s.\n",
+            versionFile);
+        exit(-1);
+    }
+    cp = strchr(version, '\n');
+    if (cp)
+        *cp = '\0';
+    fclose(fd);
+    fd = openFile(alphaFile);
+    if (fgets(alpha, sizeof (alpha)-1, fd) == NULL) {
+        fprintf(stderr, "mkversion: No alpha information in %s.\n", alphaFile);
+        exit(-1);
+    }
+    fclose(fd);
+    cp = strchr(alpha, ' ');            /* skip to 3rd blank-separated field */
+    if (cp)
+        cp = strchr(cp+1, ' ');
+    if (cp) {                           /* append alpha to version */
+        char* tp;
+        for (tp = strchr(version, '\0'), cp++; (*tp = *cp) != 0; tp++, cp++)
+            ;
+        if (tp[-1] == '\n')
+            tp[-1] = '\0';
+    } else {
+        fprintf(stderr, "mkversion: Malformed alpha information in %s.\n",
+            alphaFile);
+        exit(-1);
+    }
+
+    /*
+     * Read the RELEASE-DATE, and translate format to emit TIFFLIB_VERSION.
+     */
+    fd = openFile(releaseDateFile);
+    if (fgets(rawReleaseDate, sizeof (version)-1, fd) == NULL) {
+        fprintf(stderr, "mkversion: No release date information in %s.\n",
+                releaseDateFile);
+        exit(-1);
+    }
+    fclose(fd);
+
+    sprintf( tiffLibVersion, "#define TIFFLIB_VERSION %4.4s%2.2s%2.2s",
+             rawReleaseDate+6, 
+             rawReleaseDate+0,
+             rawReleaseDate+3 );
+    
+    /*
+     * Emit the version.h file.
+     */
+    if (argc > 0) {
+        fd = fopen(argv[0], "w");
+        if (fd == NULL) {
+            fprintf(stderr, "mkversion: %s: Could not open for writing.\n",
+                argv[0]);
+            exit(-1);
+        }
+    } else
+        fd = stdout;
+    fprintf(fd, "#define TIFFLIB_VERSION_STR \"LIBTIFF, Version %s\\n", version);
+    fprintf(fd, "Copyright (c) 1988-1996 Sam Leffler\\n");
+    fprintf(fd, "Copyright (c) 1991-1996 Silicon Graphics, Inc.\"\n");
+
+    fprintf( fd, 
+             "/*\n"
+             " * This define can be used in code that requires\n"
+             " * compilation-related definitions specific to a\n"
+             " * version or versions of the library.  Runtime\n"
+             " * version checking should be done based on the\n"
+             " * string returned by TIFFGetVersion.\n" 
+             " */\n" );
+    fprintf(fd, "%s\n", tiffLibVersion );
+
+    if (fd != stdout)
+        fclose(fd);
+    return (0);
+}
diff --git a/Utilities/ITK/Utilities/tiff/port.h b/Utilities/ITK/Utilities/tiff/port.h
new file mode 100644
index 0000000000..e98e400a4a
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/port.h
@@ -0,0 +1,36 @@
+/*
+ * Warning, this file was automatically created by the TIFF configure script
+ * VERSION:      v3.5.7
+ * RELEASE:   
+ * DATE:         Mon Dec 17 13:18:52 EST 2001
+ * TARGET:       i686-pc-linux-gnu
+ * CCOMPILER:    /usr/bin/gcc3-3.0.1-3)
+ */
+#ifndef _PORT_
+#define _PORT_ 1
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <sys/types.h>
+#define HOST_FILLORDER FILLORDER_MSB2LSB
+#ifdef VTK_WORDS_BIGENDIAN
+#define HOST_BIGENDIAN 1
+#else
+#define HOST_BIGENDIAN 0
+#endif
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+typedef double dblparam_t;
+#ifdef __STRICT_ANSI__
+#define INLINE  __inline__
+#else
+#define INLINE  inline
+#endif
+#define GLOBALDATA(TYPE,NAME)   extern TYPE NAME
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/Utilities/ITK/Utilities/tiff/t4.h b/Utilities/ITK/Utilities/tiff/t4.h
new file mode 100644
index 0000000000..947a9e0ad0
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/t4.h
@@ -0,0 +1,285 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _T4_
+#define  _T4_
+/*
+ * CCITT T.4 1D Huffman runlength codes and
+ * related definitions.  Given the small sizes
+ * of these tables it does not seem
+ * worthwhile to make code & length 8 bits.
+ */
+typedef struct tableentry {
+    unsigned short length;  /* bit length of g3 code */
+    unsigned short code;  /* g3 code */
+    short  runlen;    /* run length in bits */
+} tableentry;
+
+#define  EOL  0x001  /* EOL code value - 0000 0000 0000 1 */
+
+/* status values returned instead of a run length */
+#define  G3CODE_EOL  -1  /* NB: ACT_EOL - ACT_WRUNT */
+#define  G3CODE_INVALID  -2  /* NB: ACT_INVALID - ACT_WRUNT */
+#define  G3CODE_EOF  -3  /* end of input data */
+#define  G3CODE_INCOMP  -4  /* incomplete run code */
+
+/*
+ * Note that these tables are ordered such that the
+ * index into the table is known to be either the
+ * run length, or (run length / 64) + a fixed offset.
+ *
+ * NB: The G3CODE_INVALID entries are only used
+ *     during state generation (see mkg3states.c).
+ */
+#ifdef G3CODES
+const tableentry TIFFFaxWhiteCodes[] = {
+    { 8, 0x35, 0 },  /* 0011 0101 */
+    { 6, 0x7, 1 },  /* 0001 11 */
+    { 4, 0x7, 2 },  /* 0111 */
+    { 4, 0x8, 3 },  /* 1000 */
+    { 4, 0xB, 4 },  /* 1011 */
+    { 4, 0xC, 5 },  /* 1100 */
+    { 4, 0xE, 6 },  /* 1110 */
+    { 4, 0xF, 7 },  /* 1111 */
+    { 5, 0x13, 8 },  /* 1001 1 */
+    { 5, 0x14, 9 },  /* 1010 0 */
+    { 5, 0x7, 10 },  /* 0011 1 */
+    { 5, 0x8, 11 },  /* 0100 0 */
+    { 6, 0x8, 12 },  /* 0010 00 */
+    { 6, 0x3, 13 },  /* 0000 11 */
+    { 6, 0x34, 14 },  /* 1101 00 */
+    { 6, 0x35, 15 },  /* 1101 01 */
+    { 6, 0x2A, 16 },  /* 1010 10 */
+    { 6, 0x2B, 17 },  /* 1010 11 */
+    { 7, 0x27, 18 },  /* 0100 111 */
+    { 7, 0xC, 19 },  /* 0001 100 */
+    { 7, 0x8, 20 },  /* 0001 000 */
+    { 7, 0x17, 21 },  /* 0010 111 */
+    { 7, 0x3, 22 },  /* 0000 011 */
+    { 7, 0x4, 23 },  /* 0000 100 */
+    { 7, 0x28, 24 },  /* 0101 000 */
+    { 7, 0x2B, 25 },  /* 0101 011 */
+    { 7, 0x13, 26 },  /* 0010 011 */
+    { 7, 0x24, 27 },  /* 0100 100 */
+    { 7, 0x18, 28 },  /* 0011 000 */
+    { 8, 0x2, 29 },  /* 0000 0010 */
+    { 8, 0x3, 30 },  /* 0000 0011 */
+    { 8, 0x1A, 31 },  /* 0001 1010 */
+    { 8, 0x1B, 32 },  /* 0001 1011 */
+    { 8, 0x12, 33 },  /* 0001 0010 */
+    { 8, 0x13, 34 },  /* 0001 0011 */
+    { 8, 0x14, 35 },  /* 0001 0100 */
+    { 8, 0x15, 36 },  /* 0001 0101 */
+    { 8, 0x16, 37 },  /* 0001 0110 */
+    { 8, 0x17, 38 },  /* 0001 0111 */
+    { 8, 0x28, 39 },  /* 0010 1000 */
+    { 8, 0x29, 40 },  /* 0010 1001 */
+    { 8, 0x2A, 41 },  /* 0010 1010 */
+    { 8, 0x2B, 42 },  /* 0010 1011 */
+    { 8, 0x2C, 43 },  /* 0010 1100 */
+    { 8, 0x2D, 44 },  /* 0010 1101 */
+    { 8, 0x4, 45 },  /* 0000 0100 */
+    { 8, 0x5, 46 },  /* 0000 0101 */
+    { 8, 0xA, 47 },  /* 0000 1010 */
+    { 8, 0xB, 48 },  /* 0000 1011 */
+    { 8, 0x52, 49 },  /* 0101 0010 */
+    { 8, 0x53, 50 },  /* 0101 0011 */
+    { 8, 0x54, 51 },  /* 0101 0100 */
+    { 8, 0x55, 52 },  /* 0101 0101 */
+    { 8, 0x24, 53 },  /* 0010 0100 */
+    { 8, 0x25, 54 },  /* 0010 0101 */
+    { 8, 0x58, 55 },  /* 0101 1000 */
+    { 8, 0x59, 56 },  /* 0101 1001 */
+    { 8, 0x5A, 57 },  /* 0101 1010 */
+    { 8, 0x5B, 58 },  /* 0101 1011 */
+    { 8, 0x4A, 59 },  /* 0100 1010 */
+    { 8, 0x4B, 60 },  /* 0100 1011 */
+    { 8, 0x32, 61 },  /* 0011 0010 */
+    { 8, 0x33, 62 },  /* 0011 0011 */
+    { 8, 0x34, 63 },  /* 0011 0100 */
+    { 5, 0x1B, 64 },  /* 1101 1 */
+    { 5, 0x12, 128 },  /* 1001 0 */
+    { 6, 0x17, 192 },  /* 0101 11 */
+    { 7, 0x37, 256 },  /* 0110 111 */
+    { 8, 0x36, 320 },  /* 0011 0110 */
+    { 8, 0x37, 384 },  /* 0011 0111 */
+    { 8, 0x64, 448 },  /* 0110 0100 */
+    { 8, 0x65, 512 },  /* 0110 0101 */
+    { 8, 0x68, 576 },  /* 0110 1000 */
+    { 8, 0x67, 640 },  /* 0110 0111 */
+    { 9, 0xCC, 704 },  /* 0110 0110 0 */
+    { 9, 0xCD, 768 },  /* 0110 0110 1 */
+    { 9, 0xD2, 832 },  /* 0110 1001 0 */
+    { 9, 0xD3, 896 },  /* 0110 1001 1 */
+    { 9, 0xD4, 960 },  /* 0110 1010 0 */
+    { 9, 0xD5, 1024 },  /* 0110 1010 1 */
+    { 9, 0xD6, 1088 },  /* 0110 1011 0 */
+    { 9, 0xD7, 1152 },  /* 0110 1011 1 */
+    { 9, 0xD8, 1216 },  /* 0110 1100 0 */
+    { 9, 0xD9, 1280 },  /* 0110 1100 1 */
+    { 9, 0xDA, 1344 },  /* 0110 1101 0 */
+    { 9, 0xDB, 1408 },  /* 0110 1101 1 */
+    { 9, 0x98, 1472 },  /* 0100 1100 0 */
+    { 9, 0x99, 1536 },  /* 0100 1100 1 */
+    { 9, 0x9A, 1600 },  /* 0100 1101 0 */
+    { 6, 0x18, 1664 },  /* 0110 00 */
+    { 9, 0x9B, 1728 },  /* 0100 1101 1 */
+    { 11, 0x8, 1792 },  /* 0000 0001 000 */
+    { 11, 0xC, 1856 },  /* 0000 0001 100 */
+    { 11, 0xD, 1920 },  /* 0000 0001 101 */
+    { 12, 0x12, 1984 },  /* 0000 0001 0010 */
+    { 12, 0x13, 2048 },  /* 0000 0001 0011 */
+    { 12, 0x14, 2112 },  /* 0000 0001 0100 */
+    { 12, 0x15, 2176 },  /* 0000 0001 0101 */
+    { 12, 0x16, 2240 },  /* 0000 0001 0110 */
+    { 12, 0x17, 2304 },  /* 0000 0001 0111 */
+    { 12, 0x1C, 2368 },  /* 0000 0001 1100 */
+    { 12, 0x1D, 2432 },  /* 0000 0001 1101 */
+    { 12, 0x1E, 2496 },  /* 0000 0001 1110 */
+    { 12, 0x1F, 2560 },  /* 0000 0001 1111 */
+    { 12, 0x1, G3CODE_EOL },  /* 0000 0000 0001 */
+    { 9, 0x1, G3CODE_INVALID },  /* 0000 0000 1 */
+    { 10, 0x1, G3CODE_INVALID },  /* 0000 0000 01 */
+    { 11, 0x1, G3CODE_INVALID },  /* 0000 0000 001 */
+    { 12, 0x0, G3CODE_INVALID },  /* 0000 0000 0000 */
+};
+
+const tableentry TIFFFaxBlackCodes[] = {
+    { 10, 0x37, 0 },  /* 0000 1101 11 */
+    { 3, 0x2, 1 },  /* 010 */
+    { 2, 0x3, 2 },  /* 11 */
+    { 2, 0x2, 3 },  /* 10 */
+    { 3, 0x3, 4 },  /* 011 */
+    { 4, 0x3, 5 },  /* 0011 */
+    { 4, 0x2, 6 },  /* 0010 */
+    { 5, 0x3, 7 },  /* 0001 1 */
+    { 6, 0x5, 8 },  /* 0001 01 */
+    { 6, 0x4, 9 },  /* 0001 00 */
+    { 7, 0x4, 10 },  /* 0000 100 */
+    { 7, 0x5, 11 },  /* 0000 101 */
+    { 7, 0x7, 12 },  /* 0000 111 */
+    { 8, 0x4, 13 },  /* 0000 0100 */
+    { 8, 0x7, 14 },  /* 0000 0111 */
+    { 9, 0x18, 15 },  /* 0000 1100 0 */
+    { 10, 0x17, 16 },  /* 0000 0101 11 */
+    { 10, 0x18, 17 },  /* 0000 0110 00 */
+    { 10, 0x8, 18 },  /* 0000 0010 00 */
+    { 11, 0x67, 19 },  /* 0000 1100 111 */
+    { 11, 0x68, 20 },  /* 0000 1101 000 */
+    { 11, 0x6C, 21 },  /* 0000 1101 100 */
+    { 11, 0x37, 22 },  /* 0000 0110 111 */
+    { 11, 0x28, 23 },  /* 0000 0101 000 */
+    { 11, 0x17, 24 },  /* 0000 0010 111 */
+    { 11, 0x18, 25 },  /* 0000 0011 000 */
+    { 12, 0xCA, 26 },  /* 0000 1100 1010 */
+    { 12, 0xCB, 27 },  /* 0000 1100 1011 */
+    { 12, 0xCC, 28 },  /* 0000 1100 1100 */
+    { 12, 0xCD, 29 },  /* 0000 1100 1101 */
+    { 12, 0x68, 30 },  /* 0000 0110 1000 */
+    { 12, 0x69, 31 },  /* 0000 0110 1001 */
+    { 12, 0x6A, 32 },  /* 0000 0110 1010 */
+    { 12, 0x6B, 33 },  /* 0000 0110 1011 */
+    { 12, 0xD2, 34 },  /* 0000 1101 0010 */
+    { 12, 0xD3, 35 },  /* 0000 1101 0011 */
+    { 12, 0xD4, 36 },  /* 0000 1101 0100 */
+    { 12, 0xD5, 37 },  /* 0000 1101 0101 */
+    { 12, 0xD6, 38 },  /* 0000 1101 0110 */
+    { 12, 0xD7, 39 },  /* 0000 1101 0111 */
+    { 12, 0x6C, 40 },  /* 0000 0110 1100 */
+    { 12, 0x6D, 41 },  /* 0000 0110 1101 */
+    { 12, 0xDA, 42 },  /* 0000 1101 1010 */
+    { 12, 0xDB, 43 },  /* 0000 1101 1011 */
+    { 12, 0x54, 44 },  /* 0000 0101 0100 */
+    { 12, 0x55, 45 },  /* 0000 0101 0101 */
+    { 12, 0x56, 46 },  /* 0000 0101 0110 */
+    { 12, 0x57, 47 },  /* 0000 0101 0111 */
+    { 12, 0x64, 48 },  /* 0000 0110 0100 */
+    { 12, 0x65, 49 },  /* 0000 0110 0101 */
+    { 12, 0x52, 50 },  /* 0000 0101 0010 */
+    { 12, 0x53, 51 },  /* 0000 0101 0011 */
+    { 12, 0x24, 52 },  /* 0000 0010 0100 */
+    { 12, 0x37, 53 },  /* 0000 0011 0111 */
+    { 12, 0x38, 54 },  /* 0000 0011 1000 */
+    { 12, 0x27, 55 },  /* 0000 0010 0111 */
+    { 12, 0x28, 56 },  /* 0000 0010 1000 */
+    { 12, 0x58, 57 },  /* 0000 0101 1000 */
+    { 12, 0x59, 58 },  /* 0000 0101 1001 */
+    { 12, 0x2B, 59 },  /* 0000 0010 1011 */
+    { 12, 0x2C, 60 },  /* 0000 0010 1100 */
+    { 12, 0x5A, 61 },  /* 0000 0101 1010 */
+    { 12, 0x66, 62 },  /* 0000 0110 0110 */
+    { 12, 0x67, 63 },  /* 0000 0110 0111 */
+    { 10, 0xF, 64 },  /* 0000 0011 11 */
+    { 12, 0xC8, 128 },  /* 0000 1100 1000 */
+    { 12, 0xC9, 192 },  /* 0000 1100 1001 */
+    { 12, 0x5B, 256 },  /* 0000 0101 1011 */
+    { 12, 0x33, 320 },  /* 0000 0011 0011 */
+    { 12, 0x34, 384 },  /* 0000 0011 0100 */
+    { 12, 0x35, 448 },  /* 0000 0011 0101 */
+    { 13, 0x6C, 512 },  /* 0000 0011 0110 0 */
+    { 13, 0x6D, 576 },  /* 0000 0011 0110 1 */
+    { 13, 0x4A, 640 },  /* 0000 0010 0101 0 */
+    { 13, 0x4B, 704 },  /* 0000 0010 0101 1 */
+    { 13, 0x4C, 768 },  /* 0000 0010 0110 0 */
+    { 13, 0x4D, 832 },  /* 0000 0010 0110 1 */
+    { 13, 0x72, 896 },  /* 0000 0011 1001 0 */
+    { 13, 0x73, 960 },  /* 0000 0011 1001 1 */
+    { 13, 0x74, 1024 },  /* 0000 0011 1010 0 */
+    { 13, 0x75, 1088 },  /* 0000 0011 1010 1 */
+    { 13, 0x76, 1152 },  /* 0000 0011 1011 0 */
+    { 13, 0x77, 1216 },  /* 0000 0011 1011 1 */
+    { 13, 0x52, 1280 },  /* 0000 0010 1001 0 */
+    { 13, 0x53, 1344 },  /* 0000 0010 1001 1 */
+    { 13, 0x54, 1408 },  /* 0000 0010 1010 0 */
+    { 13, 0x55, 1472 },  /* 0000 0010 1010 1 */
+    { 13, 0x5A, 1536 },  /* 0000 0010 1101 0 */
+    { 13, 0x5B, 1600 },  /* 0000 0010 1101 1 */
+    { 13, 0x64, 1664 },  /* 0000 0011 0010 0 */
+    { 13, 0x65, 1728 },  /* 0000 0011 0010 1 */
+    { 11, 0x8, 1792 },  /* 0000 0001 000 */
+    { 11, 0xC, 1856 },  /* 0000 0001 100 */
+    { 11, 0xD, 1920 },  /* 0000 0001 101 */
+    { 12, 0x12, 1984 },  /* 0000 0001 0010 */
+    { 12, 0x13, 2048 },  /* 0000 0001 0011 */
+    { 12, 0x14, 2112 },  /* 0000 0001 0100 */
+    { 12, 0x15, 2176 },  /* 0000 0001 0101 */
+    { 12, 0x16, 2240 },  /* 0000 0001 0110 */
+    { 12, 0x17, 2304 },  /* 0000 0001 0111 */
+    { 12, 0x1C, 2368 },  /* 0000 0001 1100 */
+    { 12, 0x1D, 2432 },  /* 0000 0001 1101 */
+    { 12, 0x1E, 2496 },  /* 0000 0001 1110 */
+    { 12, 0x1F, 2560 },  /* 0000 0001 1111 */
+    { 12, 0x1, G3CODE_EOL },  /* 0000 0000 0001 */
+    { 9, 0x1, G3CODE_INVALID },  /* 0000 0000 1 */
+    { 10, 0x1, G3CODE_INVALID },  /* 0000 0000 01 */
+    { 11, 0x1, G3CODE_INVALID },  /* 0000 0000 001 */
+    { 12, 0x0, G3CODE_INVALID },  /* 0000 0000 0000 */
+};
+#else
+extern  const tableentry TIFFFaxWhiteCodes[];
+extern  const tableentry TIFFFaxBlackCodes[];
+#endif
+#endif /* _T4_ */
diff --git a/Utilities/ITK/Utilities/tiff/tconf.h b/Utilities/ITK/Utilities/tiff/tconf.h
new file mode 100644
index 0000000000..a088c6267a
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tconf.h
@@ -0,0 +1,59 @@
+#include "tiffDllConfig.h"
+
+/* Compile with -DTIFFDLL for Windows DLL support */
+#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
+#  define WIN32
+#endif
+#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386)
+#  ifndef __32BIT__
+#    define __32BIT__
+#  endif
+#endif
+#if defined(__MSDOS__) && !defined(MSDOS)
+#  define MSDOS
+#endif
+
+#if defined(TIFFDLL)
+#  if defined(_WINDOWS) || defined(WINDOWS)
+#    ifdef FAR
+#      undef FAR
+#    endif
+#    include <windows.h>
+#    define TEXPORT  WINAPI
+#    ifdef WIN32
+#      define TEXPORTVA  WINAPIV
+#    else
+#      define TEXPORTVA  FAR _cdecl _export
+#    endif
+#  endif
+#  if defined (__BORLANDC__)
+#    if (__BORLANDC__ >= 0x0500) && defined (WIN32)
+#      include <windows.h>
+/*
+#      define TEXPORT __declspec(dllexport) WINAPI
+#      define TEXPORTRVA __declspec(dllexport) WINAPIV
+*/
+#      define TEXPORT _cdecl _export
+#      define TEXPORTRVA _cdecl _export
+#    else
+#      if defined (_Windows) && defined (__DLL__)
+#        define TEXPORT _export
+#        define TEXPORTVA _export
+#      endif
+#    endif
+#  endif
+#endif
+#ifndef TEXPORT
+#  define TEXPORT
+#endif
+#ifndef TEXPORTVA
+#  define TEXPORTVA
+#endif
+#ifndef TEXTERN
+#  define TEXTERN extern
+#endif
+
+#ifndef FAR
+#   define FAR
+#endif
+
diff --git a/Utilities/ITK/Utilities/tiff/tif_acorn.c b/Utilities/ITK/Utilities/tiff/tif_acorn.c
new file mode 100644
index 0000000000..c697903de7
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_acorn.c
@@ -0,0 +1,519 @@
+/* $Header: /cvsroot/Insight/Insight/Utilities/tiff/tif_acorn.c,v 1.2 2005/09/16 19:53:39 jjomier Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library RISC OS specific Routines.
+ * Developed out of the Unix version.
+ * Peter Greenham, May 1995
+ */
+#include "tiffiop.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+/*
+Low-level file handling
+~~~~~~~~~~~~~~~~~~~~~~~
+The functions in osfcn.h are unavailable when compiling under C, as it's a
+C++ header. Therefore they have been implemented here.
+
+Now, why have I done it this way?
+
+The definitive API library for RISC OS is Jonathan Coxhead's OSLib, which
+uses heavily optimised ARM assembler or even plain inline SWI calls for
+maximum performance and minimum runtime size. However, I don't want to make
+LIBTIFF need that to survive. Therefore I have also emulated the functions
+using macros to _swi() and _swix() defined in the swis.h header, and
+borrowing types from kernel.h, which is less efficient but doesn't need any
+third-party libraries.
+ */
+
+#ifdef INCLUDE_OSLIB
+
+#include "osfile.h"
+#include "osgbpb.h"
+#include "osargs.h"
+#include "osfind.h"
+
+#else
+
+/* OSLIB EMULATION STARTS */
+
+#include "kernel.h"
+#include "swis.h"
+
+/* From oslib:types.h */
+typedef unsigned int                            bits;
+typedef unsigned char                           byte;
+#ifndef TRUE
+#define TRUE                                    1
+#endif
+#ifndef FALSE
+#define FALSE                                   0
+#endif
+#ifndef NULL
+#define NULL                                    0
+#endif
+#ifndef SKIP
+#define SKIP                                    0
+#endif
+
+/* From oslib:os.h */
+typedef _kernel_oserror os_error;
+typedef byte os_f;
+
+/* From oslib:osfile.h */
+#undef  OS_File
+#define OS_File                                 0x8
+
+/* From oslib:osgbpb.h */
+#undef  OS_GBPB
+#define OS_GBPB                                 0xC
+#undef  OSGBPB_Write
+#define OSGBPB_Write                            0x2
+#undef  OSGBPB_Read
+#define OSGBPB_Read                             0x4
+
+extern os_error *xosgbpb_write (os_f file,
+      byte *data,
+      int size,
+      int *unwritten);
+extern int osgbpb_write (os_f file,
+      byte *data,
+      int size);
+
+#define  xosgbpb_write(file, data, size, unwritten) \
+  (os_error*) _swix(OS_GBPB, _IN(0)|_IN(1)|_IN(2)|_IN(3)|_IN(4)|_OUT(3), \
+    OSGBPB_WriteAt, \
+    file, \
+    data, \
+    size, \
+    unwritten)
+
+#define  osgbpb_write(file, data, size) \
+  _swi(OS_GBPB, _IN(0)|_IN(1)|_IN(2)|_IN(3)|_RETURN(3), \
+    OSGBPB_Write, \
+    file, \
+    data, \
+    size)
+
+extern os_error *xosgbpb_read (os_f file,
+      byte *buffer,
+      int size,
+      int *unread);
+extern int osgbpb_read (os_f file,
+      byte *buffer,
+      int size);
+
+#define  xosgbpb_read(file, buffer, size, unread) \
+  (os_error*) _swix(OS_GBPB, _IN(0)|_IN(1)|_IN(2)|_IN(3)|_OUT(3), \
+    OSGBPB_Read, \
+    file, \
+    buffer, \
+    size, \
+    unread)
+
+#define  osgbpb_read(file, buffer, size) \
+  _swi(OS_GBPB, _IN(0)|_IN(1)|_IN(2)|_IN(3)|_RETURN(3), \
+    OSGBPB_Read, \
+    file, \
+    buffer, \
+    size)
+
+/* From oslib:osfind.h */
+#undef  OS_Find
+#define OS_Find                                 0xD
+#undef  OSFind_Openin
+#define OSFind_Openin                           0x40
+#undef  OSFind_Openout
+#define OSFind_Openout                          0x80
+#undef  OSFind_Openup
+#define OSFind_Openup                           0xC0
+#undef  OSFind_Close
+#define OSFind_Close                            0x0
+
+#define  xosfind_open(reason, file_name, path, file) \
+  (os_error*) _swix(OS_Find, _IN(0)|_IN(1)|_IN(2)|_OUT(0), \
+    reason, file_name, path, file)
+
+#define  osfind_open(reason, file_name, path) \
+  (os_f) _swi(OS_Find, _IN(0)|_IN(1)|_IN(2)|_RETURN(0), \
+    reason, file_name, path)
+
+extern os_error *xosfind_openin (bits flags,
+      char *file_name,
+      char *path,
+      os_f *file);
+extern os_f osfind_openin (bits flags,
+      char *file_name,
+      char *path);
+
+#define  xosfind_openin(flags, file_name, path, file) \
+  xosfind_open(flags | OSFind_Openin, file_name, path, file)
+
+#define  osfind_openin(flags, file_name, path) \
+  osfind_open(flags | OSFind_Openin, file_name, path)
+
+extern os_error *xosfind_openout (bits flags,
+      char *file_name,
+      char *path,
+      os_f *file);
+extern os_f osfind_openout (bits flags,
+      char *file_name,
+      char *path);
+
+#define  xosfind_openout(flags, file_name, path, file) \
+  xosfind_open(flags | OSFind_Openout, file_name, path, file)
+
+#define  osfind_openout(flags, file_name, path) \
+  osfind_open(flags | OSFind_Openout, file_name, path)
+
+extern os_error *xosfind_openup (bits flags,
+      char *file_name,
+      char *path,
+      os_f *file);
+extern os_f osfind_openup (bits flags,
+      char *file_name,
+      char *path);
+
+#define  xosfind_openup(flags, file_name, path, file) \
+  xosfind_open(flags | OSFind_Openup, file_name, path, file)
+
+#define  osfind_openup(flags, file_name, path) \
+  osfind_open(flags | OSFind_Openup, file_name, path)
+
+extern os_error *xosfind_close (os_f file);
+extern void osfind_close (os_f file);
+
+#define  xosfind_close(file) \
+  (os_error*) _swix(OS_Find, _IN(0)|_IN(1), \
+    OSFind_Close, \
+    file)
+
+#define  osfind_close(file) \
+  (void) _swi(OS_Find, _IN(0)|_IN(1), \
+    OSFind_Close, \
+    file)
+
+/* From oslib:osargs.h */
+#undef  OS_Args
+#define OS_Args                                 0x9
+#undef  OSArgs_ReadPtr
+#define OSArgs_ReadPtr                          0x0
+#undef  OSArgs_SetPtr
+#define OSArgs_SetPtr                           0x1
+#undef  OSArgs_ReadExt
+#define OSArgs_ReadExt                          0x2
+
+extern os_error *xosargs_read_ptr (os_f file,
+      int *ptr);
+extern int osargs_read_ptr (os_f file);
+
+#define  xosargs_read_ptr(file, ptr) \
+  (os_error*) _swix(OS_Args, _IN(0)|_IN(1)|_OUT(2), \
+    OSArgs_ReadPtr, \
+    file, \
+    ptr)
+
+#define  osargs_read_ptr(file) \
+  _swi(OS_Args, _IN(0)|_IN(1)|_RETURN(2), \
+    OSArgs_ReadPtr, \
+    file)
+
+extern os_error *xosargs_set_ptr (os_f file,
+      int ptr);
+extern void osargs_set_ptr (os_f file,
+      int ptr);
+
+#define  xosargs_set_ptr(file, ptr) \
+  (os_error*) _swix(OS_Args, _IN(0)|_IN(1)|_IN(2), \
+    OSArgs_SetPtr, \
+    file, \
+    ptr)
+
+#define  osargs_set_ptr(file, ptr) \
+  (void) _swi(OS_Args, _IN(0)|_IN(1)|_IN(2), \
+    OSArgs_SetPtr, \
+    file, \
+    ptr)
+
+extern os_error *xosargs_read_ext (os_f file,
+      int *ext);
+extern int osargs_read_ext (os_f file);
+
+#define  xosargs_read_ext(file, ext) \
+  (os_error*) _swix(OS_Args, _IN(0)|_IN(1)|_OUT(2), \
+    OSArgs_ReadExt, \
+    file, \
+    ext)
+
+#define  osargs_read_ext(file) \
+  _swi(OS_Args, _IN(0)|_IN(1)|_RETURN(2), \
+    OSArgs_ReadExt, \
+    file)
+
+/* OSLIB EMULATION ENDS */
+
+#endif
+
+#ifndef __osfcn_h
+/* Will be set or not during tiffcomp.h */
+/* You get this to compile under C++? Please say how! */
+
+extern int open(const char* name, int flags, int mode)
+{
+  /* From what I can tell, should return <0 for failure */
+  os_error* e = (os_error*) 1; /* Cheeky way to use a pointer eh? :-) */
+  os_f file = (os_f) -1;
+
+  flags = flags;
+
+  switch(mode)
+  {
+    case O_RDONLY:
+    {
+      e = xosfind_openin(SKIP, name, SKIP, &file);
+      break;
+    }
+    case O_WRONLY:
+    case O_RDWR|O_CREAT:
+    case O_RDWR|O_CREAT|O_TRUNC:
+    {
+      e = xosfind_openout(SKIP, name, SKIP, &file);
+      break;
+    }
+    case O_RDWR:
+    {
+      e = xosfind_openup(SKIP, name, SKIP, &file);
+      break;
+    }
+  }
+  if (e)
+  {
+    file = (os_f) -1;
+  }
+  return (file);
+}
+
+extern int close(int fd)
+{
+  return ((int) xosfind_close((os_f) fd));
+}
+
+extern int write(int fd, const char *buf, int nbytes)
+{
+  /* Returns number of bytes written */
+  return (nbytes - osgbpb_write((os_f) fd, (const byte*) buf, nbytes));
+}
+
+extern int read(int fd, char *buf, int nbytes)
+{
+  /* Returns number of bytes read */
+  return (nbytes - osgbpb_read((os_f) fd, (byte*) buf, nbytes));
+}
+
+extern off_t lseek(int fd, off_t offset, int whence)
+{
+  int absolute = 0;
+
+  switch (whence)
+  {
+    case SEEK_SET:
+    {
+      absolute = (int) offset;
+      break;
+    }
+    case SEEK_CUR:
+    {
+      absolute = osargs_read_ptr((os_f) fd) + (int) offset;
+      break;
+    }
+    case SEEK_END:
+    {
+      absolute = osargs_read_ext((os_f) fd) + (int) offset;
+      break;
+    }
+  }
+
+  osargs_set_ptr((os_f) fd, absolute);
+
+  return ((off_t) osargs_read_ptr((os_f) fd));
+}
+#endif
+
+static tsize_t
+_tiffReadProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+  return ((tsize_t) read((int) fd, buf, (size_t) size));
+}
+
+static tsize_t
+_tiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+  return ((tsize_t) write((int) fd, buf, (size_t) size));
+}
+
+static toff_t
+_tiffSeekProc(thandle_t fd, toff_t off, int whence)
+{
+  return ((toff_t) lseek((int) fd, (off_t) off, whence));
+}
+
+static int
+_tiffCloseProc(thandle_t fd)
+{
+  return (close((int) fd));
+}
+
+static toff_t
+_tiffSizeProc(thandle_t fd)
+{
+  return (lseek((int) fd, SEEK_END, SEEK_SET));
+}
+
+#ifdef HAVE_MMAP
+#error "I didn't know Acorn had that!"
+#endif
+
+/* !HAVE_MMAP */
+static int
+_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
+{
+  (void) fd; (void) pbase; (void) psize;
+  return (0);
+}
+
+static void
+_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size)
+{
+  (void) fd; (void) base; (void) size;
+}
+
+/*
+ * Open a TIFF file descriptor for read/writing.
+ */
+TIFF*
+TIFFFdOpen(int fd, const char* name, const char* mode)
+{
+  TIFF* tif;
+
+  tif = TIFFClientOpen(name, mode,
+    (thandle_t) fd,
+    _tiffReadProc, _tiffWriteProc,
+    _tiffSeekProc, _tiffCloseProc, _tiffSizeProc,
+    _tiffMapProc, _tiffUnmapProc);
+  if (tif)
+  {
+    tif->tif_fd = fd;
+  }
+  return (tif);
+}
+
+/*
+ * Open a TIFF file for read/writing.
+ */
+TIFF*
+TIFFOpen(const char* name, const char* mode)
+{
+  static const char module[] = "TIFFOpen";
+  int m, fd;
+
+  m = _TIFFgetMode(mode, module);
+
+  if (m == -1)
+  {
+    return ((TIFF*) 0);
+  }
+
+  fd = open(name, 0, m);
+
+  if (fd < 0)
+  {
+    TIFFError(module, "%s: Cannot open", name);
+    return ((TIFF *)0);
+  }
+  return (TIFFFdOpen(fd, name, mode));
+}
+
+void*
+_TIFFmalloc(tsize_t s)
+{
+  return (malloc((size_t) s));
+}
+
+void
+_TIFFfree(tdata_t p)
+{
+  free(p);
+}
+
+void*
+_TIFFrealloc(tdata_t p, tsize_t s)
+{
+  return (realloc(p, (size_t) s));
+}
+
+void
+_TIFFmemset(tdata_t p, int v, tsize_t c)
+{
+  memset(p, v, (size_t) c);
+}
+
+void
+_TIFFmemcpy(tdata_t d, const tdata_t s, tsize_t c)
+{
+  memcpy(d, s, (size_t) c);
+}
+
+int
+_TIFFmemcmp(const tdata_t p1, const tdata_t p2, tsize_t c)
+{
+  return (memcmp(p1, p2, (size_t) c));
+}
+
+static void
+acornWarningHandler(const char* module, const char* fmt, va_list ap)
+{
+  if (module != NULL)
+  {
+    fprintf(stderr, "%s: ", module);
+  }
+  fprintf(stderr, "Warning, ");
+  vfprintf(stderr, fmt, ap);
+  fprintf(stderr, ".\n");
+}
+TIFFErrorHandler _TIFFwarningHandler = acornWarningHandler;
+
+static void
+acornErrorHandler(const char* module, const char* fmt, va_list ap)
+{
+  if (module != NULL)
+  {
+    fprintf(stderr, "%s: ", module);
+  }
+  vfprintf(stderr, fmt, ap);
+  fprintf(stderr, ".\n");
+}
+TIFFErrorHandler _TIFFerrorHandler = acornErrorHandler;
diff --git a/Utilities/ITK/Utilities/tiff/tif_apple.c b/Utilities/ITK/Utilities/tiff/tif_apple.c
new file mode 100644
index 0000000000..c98e9a3bf3
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_apple.c
@@ -0,0 +1,274 @@
+/* $Header: /cvsroot/Insight/Insight/Utilities/tiff/tif_apple.c,v 1.2 2005/09/16 19:53:39 jjomier Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library Macintosh-specific routines.
+ *
+ * These routines use only Toolbox and high-level File Manager traps.
+ * They make no calls to the THINK C "unix" compatibility library.  Also,
+ * malloc is not used directly but it is still referenced internally by
+ * the ANSI library in rare cases.  Heap fragmentation by the malloc ring
+ * buffer is therefore minimized.
+ *
+ * O_RDONLY and O_RDWR are treated identically here.  The tif_mode flag is
+ * checked in TIFFWriteCheck().
+ *
+ * Create below fills in a blank creator signature and sets the file type
+ * to 'TIFF'.  It is much better for the application to do this by Create'ing
+ * the file first and TIFFOpen'ing it later.
+ * ---------
+ * This code has been "Carbonized", and may not work with older MacOS versions.
+ * If so, grab the tif_apple.c out of an older libtiff distribution, like
+ * 3.5.5 from www.libtiff.org.
+ */
+
+#include "tiffiop.h"
+#include <Errors.h>
+#include <Files.h>
+#include <Memory.h>
+#include <Script.h>
+
+#if defined(__PPCC__) || defined(__SC__) || defined(__MRC__) || defined(applec)
+#define  CtoPstr  c2pstr
+#endif
+
+static tsize_t
+_tiffReadProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+  return (FSRead((short) fd, (long*) &size, (char*) buf) == noErr ?
+      size : (tsize_t) -1);
+}
+
+static tsize_t
+_tiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+  return (FSWrite((short) fd, (long*) &size, (char*) buf) == noErr ?
+      size : (tsize_t) -1);
+}
+
+static toff_t
+_tiffSeekProc(thandle_t fd, toff_t off, int whence)
+{
+  long fpos, size;
+
+  if (GetEOF((short) fd, &size) != noErr)
+    return EOF;
+  (void) GetFPos((short) fd, &fpos);
+
+  switch (whence) {
+  case SEEK_CUR:
+    if (off + fpos > size)
+      SetEOF((short) fd, off + fpos);
+    if (SetFPos((short) fd, fsFromMark, off) != noErr)
+      return EOF;
+    break;
+  case SEEK_END:
+    if (off > 0)
+      SetEOF((short) fd, off + size);
+    if (SetFPos((short) fd, fsFromStart, off + size) != noErr)
+      return EOF;
+    break;
+  case SEEK_SET:
+    if (off > size)
+      SetEOF((short) fd, off);
+    if (SetFPos((short) fd, fsFromStart, off) != noErr)
+      return EOF;
+    break;
+  }
+
+  return (toff_t)(GetFPos((short) fd, &fpos) == noErr ? fpos : EOF);
+}
+
+static int
+_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
+{
+  return (0);
+}
+
+static void
+_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size)
+{
+}
+
+static int
+_tiffCloseProc(thandle_t fd)
+{
+  return (FSClose((short) fd));
+}
+
+static toff_t
+_tiffSizeProc(thandle_t fd)
+{
+  long size;
+
+  if (GetEOF((short) fd, &size) != noErr) {
+    TIFFError("_tiffSizeProc", "%s: Cannot get file size");
+    return (-1L);
+  }
+  return ((toff_t) size);
+}
+
+/*
+ * Open a TIFF file descriptor for read/writing.
+ */
+TIFF*
+TIFFFdOpen(int fd, const char* name, const char* mode)
+{
+  TIFF* tif;
+
+  tif = TIFFClientOpen(name, mode, (thandle_t) fd,
+      _tiffReadProc, _tiffWriteProc, _tiffSeekProc, _tiffCloseProc,
+      _tiffSizeProc, _tiffMapProc, _tiffUnmapProc);
+  if (tif)
+    tif->tif_fd = fd;
+  return (tif);
+}
+
+static void ourc2pstr( char* inString )
+{
+  int  sLen = strlen( inString );
+  BlockMoveData( inString, &inString[1], sLen );
+  inString[0] = sLen;
+}
+
+/*
+ * Open a TIFF file for read/writing.
+ */
+TIFF*
+TIFFOpen(const char* name, const char* mode)
+{
+  static const char module[] = "TIFFOpen";
+  Str255 pname;
+  FInfo finfo;
+  short fref;
+  OSErr err;
+  FSSpec  fSpec;
+
+  strcpy((char*) pname, name);
+  ourc2pstr((char*) pname);
+  
+  err = FSMakeFSSpec( 0, 0, pname, &fSpec );
+
+  switch (_TIFFgetMode(mode, module)) {
+  default:
+    return ((TIFF*) 0);
+  case O_RDWR | O_CREAT | O_TRUNC:
+    if (FSpGetFInfo(&fSpec, &finfo) == noErr)
+      FSpDelete(&fSpec);
+    /* fall through */
+  case O_RDWR | O_CREAT:
+    if ((err = FSpGetFInfo(&fSpec, &finfo)) == fnfErr) {
+      if (FSpCreate(&fSpec, '    ', 'TIFF', smSystemScript) != noErr)
+        goto badCreate;
+      if (FSpOpenDF(&fSpec, fsRdWrPerm, &fref) != noErr)
+        goto badOpen;
+    } else if (err == noErr) {
+      if (FSpOpenDF(&fSpec, fsRdWrPerm, &fref) != noErr)
+        goto badOpen;
+    } else
+      goto badOpen;
+    break;
+  case O_RDONLY:
+    if (FSpOpenDF(&fSpec, fsRdPerm, &fref) != noErr)
+      goto badOpen;
+    break;
+  case O_RDWR:
+    if (FSpOpenDF(&fSpec, fsRdWrPerm, &fref) != noErr)
+      goto badOpen;
+    break;
+  }
+  return (TIFFFdOpen((int) fref, name, mode));
+badCreate:
+  TIFFError(module, "%s: Cannot create", name);
+  return ((TIFF*) 0);
+badOpen:
+  TIFFError(module, "%s: Cannot open", name);
+  return ((TIFF*) 0);
+}
+
+void
+_TIFFmemset(tdata_t p, int v, tsize_t c)
+{
+  memset(p, v, (size_t) c);
+}
+
+void
+_TIFFmemcpy(tdata_t d, const tdata_t s, tsize_t c)
+{
+  memcpy(d, s, (size_t) c);
+}
+
+int
+_TIFFmemcmp(const tdata_t p1, const tdata_t p2, tsize_t c)
+{
+  return (memcmp(p1, p2, (size_t) c));
+}
+
+tdata_t
+_TIFFmalloc(tsize_t s)
+{
+  return (NewPtr((size_t) s));
+}
+
+void
+_TIFFfree(tdata_t p)
+{
+  DisposePtr(p);
+}
+
+tdata_t
+_TIFFrealloc(tdata_t p, tsize_t s)
+{
+  Ptr n = p;
+
+  SetPtrSize(p, (size_t) s);
+  if (MemError() && (n = NewPtr((size_t) s)) != NULL) {
+    BlockMove(p, n, GetPtrSize(p));
+    DisposePtr(p);
+  }
+  return ((tdata_t) n);
+}
+
+static void
+appleWarningHandler(const char* module, const char* fmt, va_list ap)
+{
+  if (module != NULL)
+    fprintf(stderr, "%s: ", module);
+  fprintf(stderr, "Warning, ");
+  vfprintf(stderr, fmt, ap);
+  fprintf(stderr, ".\n");
+}
+TIFFErrorHandler _TIFFwarningHandler = appleWarningHandler;
+
+static void
+appleErrorHandler(const char* module, const char* fmt, va_list ap)
+{
+  if (module != NULL)
+    fprintf(stderr, "%s: ", module);
+  vfprintf(stderr, fmt, ap);
+  fprintf(stderr, ".\n");
+}
+TIFFErrorHandler _TIFFerrorHandler = appleErrorHandler;
diff --git a/Utilities/ITK/Utilities/tiff/tif_atari.c b/Utilities/ITK/Utilities/tiff/tif_atari.c
new file mode 100644
index 0000000000..a4a3c35515
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_atari.c
@@ -0,0 +1,243 @@
+/* "$Header: /cvsroot/Insight/Insight/Utilities/tiff/tif_atari.c,v 1.2 2005/09/16 19:53:39 jjomier Exp $" */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library ATARI-specific Routines.
+ */
+#include "tiffiop.h"
+#if defined(__TURBOC__)
+#include <tos.h>
+#include <stdio.h>
+#else
+#include <osbind.h>
+#include <fcntl.h>
+#endif
+
+#ifndef O_ACCMODE
+#define O_ACCMODE 3
+#endif
+
+#include <errno.h>
+
+#define AEFILNF   -33
+
+static tsize_t
+_tiffReadProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+  long r;
+
+  r = Fread((int) fd, size, buf);
+  if (r < 0) {
+    errno = (int)-r;
+    r = -1;
+  }
+  return r;
+}
+
+static tsize_t
+_tiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+  long r;
+
+  r = Fwrite((int) fd, size, buf);
+  if (r < 0) {
+    errno = (int)-r;
+    r = -1;
+  }
+  return r;
+}
+
+static toff_t
+_tiffSeekProc(thandle_t fd, off_t off, int whence)
+{
+  char buf[256];
+  long current_off, expected_off, new_off;
+
+  if (whence == SEEK_END || off <= 0)
+    return Fseek(off, (int) fd, whence);
+  current_off = Fseek(0, (int) fd, SEEK_CUR); /* find out where we are */
+  if (whence == SEEK_SET)
+    expected_off = off;
+  else
+    expected_off = off + current_off;
+  new_off = Fseek(off, (int) fd, whence);
+  if (new_off == expected_off)
+    return new_off;
+  /* otherwise extend file -- zero filling the hole */
+  if (new_off < 0)            /* error? */
+    new_off = Fseek(0, (int) fd, SEEK_END); /* go to eof */
+  _TIFFmemset(buf, 0, sizeof(buf));
+  while (expected_off > new_off) {
+    off = expected_off - new_off;
+    if (off > sizeof(buf))
+      off = sizeof(buf);
+    if ((current_off = Fwrite((int) fd, off, buf)) != off)
+      return (current_off > 0) ?
+          new_off + current_off : new_off;
+    new_off += off;
+  }
+  return new_off;
+}
+
+static int
+_tiffCloseProc(thandle_t fd)
+{
+  long r;
+
+  r = Fclose((int) fd);
+  if (r < 0) {
+    errno = (int)-r;
+    r = -1;
+  }
+  return (int)r;
+}
+
+static toff_t
+_tiffSizeProc(thandle_t fd)
+{
+  long pos, eof;
+
+  pos = Fseek(0, (int) fd, SEEK_CUR);
+  eof = Fseek(0, (int) fd, SEEK_END);
+  Fseek(pos, (int) fd, SEEK_SET);
+  return eof;
+}
+
+static int
+_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
+{
+  return (0);
+}
+
+static void
+_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size)
+{
+}
+
+/*
+* Open a TIFF file descriptor for read/writing.
+*/
+TIFF*
+TIFFFdOpen(int fd, const char* name, const char* mode)
+{
+  TIFF* tif;
+
+  tif = TIFFClientOpen(name, mode,
+    (thandle_t) fd,
+    _tiffReadProc, _tiffWriteProc, _tiffSeekProc, _tiffCloseProc,
+    _tiffSizeProc, _tiffMapProc, _tiffUnmapProc);
+  if (tif)
+    tif->tif_fd = fd;
+  return (tif);
+}
+
+/*
+* Open a TIFF file for read/writing.
+*/
+TIFF*
+TIFFOpen(const char* name, const char* mode)
+{
+  static const char module[] = "TIFFOpen";
+  int m;
+  long fd;
+
+  m = _TIFFgetMode(mode, module);
+  if (m == -1)
+    return ((TIFF*)0);
+  if (m & O_TRUNC) {
+    fd = Fcreate(name, 0);
+  } else {
+    fd = Fopen(name, m & O_ACCMODE);
+    if (fd == AEFILNF && m & O_CREAT)
+      fd = Fcreate(name, 0);
+  }
+  if (fd < 0)
+    errno = (int)fd;
+  if (fd < 0) {
+    TIFFError(module, "%s: Cannot open", name);
+    return ((TIFF*)0);
+  }
+  return (TIFFFdOpen(fd, name, mode));
+}
+
+#include <stdlib.h>
+
+tdata_t
+_TIFFmalloc(tsize_t s)
+{
+  return (malloc((size_t) s));
+}
+
+void
+_TIFFfree(tdata_t p)
+{
+  free(p);
+}
+
+tdata_t
+_TIFFrealloc(tdata_t p, tsize_t s)
+{
+  return (realloc(p, (size_t) s));
+}
+
+void
+_TIFFmemset(tdata_t p, int v, size_t c)
+{
+  memset(p, v, (size_t) c);
+}
+
+void
+_TIFFmemcpy(tdata_t d, const tdata_t s, size_t c)
+{
+  memcpy(d, s, (size_t) c);
+}
+
+int
+_TIFFmemcmp(const tdata_t p1, const tdata_t p2, tsize_t c)
+{
+  return (memcmp(p1, p2, (size_t) c));
+}
+
+static void
+atariWarningHandler(const char* module, const char* fmt, va_list ap)
+{
+  if (module != NULL)
+    fprintf(stderr, "%s: ", module);
+  fprintf(stderr, "Warning, ");
+  vfprintf(stderr, fmt, ap);
+  fprintf(stderr, ".\n");
+}
+TIFFErrorHandler _TIFFwarningHandler = atariWarningHandler;
+
+static void
+atariErrorHandler(const char* module, const char* fmt, va_list ap)
+{
+  if (module != NULL)
+    fprintf(stderr, "%s: ", module);
+  vfprintf(stderr, fmt, ap);
+  fprintf(stderr, ".\n");
+}
+TIFFErrorHandler _TIFFerrorHandler = atariErrorHandler;
diff --git a/Utilities/ITK/Utilities/tiff/tif_aux.c b/Utilities/ITK/Utilities/tiff/tif_aux.c
new file mode 100644
index 0000000000..9453bce9a0
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_aux.c
@@ -0,0 +1,264 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1991-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ *
+ * Auxiliary Support Routines.
+ */
+#include "tiffiop.h"
+#include "tif_predict.h"
+#include <math.h>
+
+static int
+TIFFDefaultTransferFunction(TIFFDirectory* td)
+{
+  uint16 **tf = td->td_transferfunction;
+  tsize_t i, n, nbytes;
+
+  tf[0] = tf[1] = tf[2] = 0;
+  if (td->td_bitspersample >= sizeof(tsize_t) * 8 - 2)
+    return 0;
+
+  n = 1<<td->td_bitspersample;
+  nbytes = n * sizeof (uint16);
+  if (!(tf[0] = (uint16 *)_TIFFmalloc(nbytes)))
+    return 0;
+  tf[0][0] = 0;
+  for (i = 1; i < n; i++) {
+    double t = (double)i/((double) n-1.);
+    tf[0][i] = (uint16)floor(65535.*pow(t, 2.2) + .5);
+  }
+
+  if (td->td_samplesperpixel - td->td_extrasamples > 1) {
+    if (!(tf[1] = (uint16 *)_TIFFmalloc(nbytes)))
+      goto bad;
+    _TIFFmemcpy(tf[1], tf[0], nbytes);
+    if (!(tf[2] = (uint16 *)_TIFFmalloc(nbytes)))
+      goto bad;
+    _TIFFmemcpy(tf[2], tf[0], nbytes);
+  }
+  return 1;
+
+bad:
+  if (tf[0])
+    _TIFFfree(tf[0]);
+  if (tf[1])
+    _TIFFfree(tf[1]);
+  if (tf[2])
+    _TIFFfree(tf[2]);
+  tf[0] = tf[1] = tf[2] = 0;
+  return 0;
+}
+
+static int
+TIFFDefaultRefBlackWhite(TIFFDirectory* td)
+{
+  int i;
+
+  if (!(td->td_refblackwhite = (float *)_TIFFmalloc(6*sizeof (float))))
+    return 0;
+        if (td->td_photometric == PHOTOMETRIC_YCBCR) {
+    /*
+     * YCbCr (Class Y) images must have the ReferenceBlackWhite
+     * tag set. Fix the broken images, which lacks that tag.
+     */
+    td->td_refblackwhite[0] = 0.0F;
+    td->td_refblackwhite[1] = td->td_refblackwhite[3] =
+      td->td_refblackwhite[5] = 255.0F;
+    td->td_refblackwhite[2] = td->td_refblackwhite[4] = 128.0F;
+  } else {
+    /*
+     * Assume RGB (Class R)
+     */
+    for (i = 0; i < 3; i++) {
+        td->td_refblackwhite[2*i+0] = 0;
+        td->td_refblackwhite[2*i+1] =
+          (float)((1L<<td->td_bitspersample)-1L);
+    }
+  }
+  return 1;
+}
+
+/*
+ * Like TIFFGetField, but return any default
+ * value if the tag is not present in the directory.
+ *
+ * NB:  We use the value in the directory, rather than
+ *  explcit values so that defaults exist only one
+ *  place in the library -- in TIFFDefaultDirectory.
+ */
+int
+TIFFVGetFieldDefaulted(TIFF* tif, ttag_t tag, va_list ap)
+{
+  TIFFDirectory *td = &tif->tif_dir;
+
+  if (TIFFVGetField(tif, tag, ap))
+    return (1);
+  switch (tag) {
+  case TIFFTAG_SUBFILETYPE:
+    *va_arg(ap, uint32 *) = td->td_subfiletype;
+    return (1);
+  case TIFFTAG_BITSPERSAMPLE:
+    *va_arg(ap, uint16 *) = td->td_bitspersample;
+    return (1);
+  case TIFFTAG_THRESHHOLDING:
+    *va_arg(ap, uint16 *) = td->td_threshholding;
+    return (1);
+  case TIFFTAG_FILLORDER:
+    *va_arg(ap, uint16 *) = td->td_fillorder;
+    return (1);
+  case TIFFTAG_ORIENTATION:
+    *va_arg(ap, uint16 *) = td->td_orientation;
+    return (1);
+  case TIFFTAG_SAMPLESPERPIXEL:
+    *va_arg(ap, uint16 *) = td->td_samplesperpixel;
+    return (1);
+  case TIFFTAG_ROWSPERSTRIP:
+    *va_arg(ap, uint32 *) = td->td_rowsperstrip;
+    return (1);
+  case TIFFTAG_MINSAMPLEVALUE:
+    *va_arg(ap, uint16 *) = td->td_minsamplevalue;
+    return (1);
+  case TIFFTAG_MAXSAMPLEVALUE:
+    *va_arg(ap, uint16 *) = td->td_maxsamplevalue;
+    return (1);
+  case TIFFTAG_PLANARCONFIG:
+    *va_arg(ap, uint16 *) = td->td_planarconfig;
+    return (1);
+  case TIFFTAG_RESOLUTIONUNIT:
+    *va_arg(ap, uint16 *) = td->td_resolutionunit;
+    return (1);
+  case TIFFTAG_PREDICTOR:
+                {
+      TIFFPredictorState* sp = (TIFFPredictorState*) tif->tif_data;
+      *va_arg(ap, uint16*) = (uint16) sp->predictor;
+      return (1);
+                }
+  case TIFFTAG_DOTRANGE:
+    *va_arg(ap, uint16 *) = 0;
+    *va_arg(ap, uint16 *) = (1<<td->td_bitspersample)-1;
+    return (1);
+  case TIFFTAG_INKSET:
+    *va_arg(ap, uint16 *) = td->td_inkset;
+    return (1);
+  case TIFFTAG_NUMBEROFINKS:
+    *va_arg(ap, uint16 *) = td->td_ninks;
+    return (1);
+  case TIFFTAG_EXTRASAMPLES:
+    *va_arg(ap, uint16 *) = td->td_extrasamples;
+    *va_arg(ap, uint16 **) = td->td_sampleinfo;
+    return (1);
+  case TIFFTAG_MATTEING:
+    *va_arg(ap, uint16 *) =
+        (td->td_extrasamples == 1 &&
+         td->td_sampleinfo[0] == EXTRASAMPLE_ASSOCALPHA);
+    return (1);
+  case TIFFTAG_TILEDEPTH:
+    *va_arg(ap, uint32 *) = td->td_tiledepth;
+    return (1);
+  case TIFFTAG_DATATYPE:
+    *va_arg(ap, uint16 *) = td->td_sampleformat-1;
+    return (1);
+  case TIFFTAG_SAMPLEFORMAT:
+    *va_arg(ap, uint16 *) = td->td_sampleformat;
+                return(1);
+  case TIFFTAG_IMAGEDEPTH:
+    *va_arg(ap, uint32 *) = td->td_imagedepth;
+    return (1);
+  case TIFFTAG_YCBCRCOEFFICIENTS:
+    if (!td->td_ycbcrcoeffs) {
+      td->td_ycbcrcoeffs = (float *)
+          _TIFFmalloc(3*sizeof (float));
+      if (!td->td_ycbcrcoeffs)
+        return (0);
+      /* defaults are from CCIR Recommendation 601-1 */
+      td->td_ycbcrcoeffs[0] = 0.299f;
+      td->td_ycbcrcoeffs[1] = 0.587f;
+      td->td_ycbcrcoeffs[2] = 0.114f;
+    }
+    *va_arg(ap, float **) = td->td_ycbcrcoeffs;
+    return (1);
+  case TIFFTAG_YCBCRSUBSAMPLING:
+    *va_arg(ap, uint16 *) = td->td_ycbcrsubsampling[0];
+    *va_arg(ap, uint16 *) = td->td_ycbcrsubsampling[1];
+    return (1);
+  case TIFFTAG_YCBCRPOSITIONING:
+    *va_arg(ap, uint16 *) = td->td_ycbcrpositioning;
+    return (1);
+  case TIFFTAG_WHITEPOINT:
+    if (!td->td_whitepoint) {
+      td->td_whitepoint = (float *)
+        _TIFFmalloc(2 * sizeof (float));
+      if (!td->td_whitepoint)
+        return (0);
+      /* TIFF 6.0 specification says that it is no default
+         value for the WhitePoint, but AdobePhotoshop TIFF
+         Technical Note tells that it should be CIE D50. */
+      td->td_whitepoint[0] =
+        D50_X0 / (D50_X0 + D50_Y0 + D50_Z0);
+      td->td_whitepoint[1] =
+        D50_Y0 / (D50_X0 + D50_Y0 + D50_Z0);
+    }
+    *va_arg(ap, float **) = td->td_whitepoint;
+    return (1);
+  case TIFFTAG_TRANSFERFUNCTION:
+    if (!td->td_transferfunction[0] &&
+        !TIFFDefaultTransferFunction(td)) {
+      TIFFError(tif->tif_name, "No space for \"TransferFunction\" tag");
+      return (0);
+    }
+    *va_arg(ap, uint16 **) = td->td_transferfunction[0];
+    if (td->td_samplesperpixel - td->td_extrasamples > 1) {
+      *va_arg(ap, uint16 **) = td->td_transferfunction[1];
+      *va_arg(ap, uint16 **) = td->td_transferfunction[2];
+    }
+    return (1);
+  case TIFFTAG_REFERENCEBLACKWHITE:
+    if (!td->td_refblackwhite && !TIFFDefaultRefBlackWhite(td))
+      return (0);
+    *va_arg(ap, float **) = td->td_refblackwhite;
+    return (1);
+  }
+  return (0);
+}
+
+/*
+ * Like TIFFGetField, but return any default
+ * value if the tag is not present in the directory.
+ */
+int
+TIFFGetFieldDefaulted(TIFF* tif, ttag_t tag, ...)
+{
+  int ok;
+  va_list ap;
+
+  va_start(ap, tag);
+  ok =  TIFFVGetFieldDefaulted(tif, tag, ap);
+  va_end(ap);
+  return (ok);
+}
+
diff --git a/Utilities/ITK/Utilities/tiff/tif_close.c b/Utilities/ITK/Utilities/tiff/tif_close.c
new file mode 100644
index 0000000000..bff8a9d9e0
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_close.c
@@ -0,0 +1,119 @@
+/* $Header: /cvsroot/Insight/Insight/Utilities/tiff/tif_close.c,v 1.2 2005/09/16 19:53:39 jjomier Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ */
+#include "tiffiop.h"
+
+/************************************************************************/
+/*                            TIFFCleanup()                             */
+/************************************************************************/
+
+/**
+ * Auxiliary function to free the TIFF structure. Given structure will be
+ * completetly freed, so you should save opened file handle and pointer
+ * to the close procedure in external variables before calling
+ * _TIFFCleanup(), if you will need these ones to close the file.
+ * 
+ * @param tif A TIFF pointer.
+ */
+
+void
+TIFFCleanup(TIFF* tif)
+{
+  if (tif->tif_mode != O_RDONLY)
+      /*
+       * Flush buffered data and directory (if dirty).
+       */
+      TIFFFlush(tif);
+  (*tif->tif_cleanup)(tif);
+  TIFFFreeDirectory(tif);
+
+  if (tif->tif_dirlist)
+      _TIFFfree(tif->tif_dirlist);
+      
+  /* Clean up client info links */
+  while( tif->tif_clientinfo )
+  {
+      TIFFClientInfoLink *link = tif->tif_clientinfo;
+
+      tif->tif_clientinfo = link->next;
+      _TIFFfree( link->name );
+      _TIFFfree( link );
+  }
+
+  if (tif->tif_rawdata && (tif->tif_flags&TIFF_MYBUFFER))
+      _TIFFfree(tif->tif_rawdata);
+  if (isMapped(tif))
+      TIFFUnmapFileContents(tif, tif->tif_base, tif->tif_size);
+
+  /* Clean up custom fields */
+  if (tif->tif_nfields > 0) 
+  {
+      int  i;
+
+      for (i = 0; i < tif->tif_nfields; i++) 
+      {
+    TIFFFieldInfo *fld = tif->tif_fieldinfo[i];
+    if (fld->field_bit == FIELD_CUSTOM && 
+        strncmp("Tag ", fld->field_name, 4) == 0) 
+    {
+        _TIFFfree(fld->field_name);
+        _TIFFfree(fld);
+    }
+      }   
+    
+      _TIFFfree(tif->tif_fieldinfo);
+  }
+
+  _TIFFfree(tif);
+}
+
+/************************************************************************/
+/*                            TIFFClose()                               */
+/************************************************************************/
+
+/**
+ * Close a previously opened TIFF file.
+ *
+ * TIFFClose closes a file that was previously opened with TIFFOpen().
+ * Any buffered data are flushed to the file, including the contents of
+ * the current directory (if modified); and all resources are reclaimed.
+ * 
+ * @param tif A TIFF pointer.
+ */
+
+void
+TIFFClose(TIFF* tif)
+{
+  TIFFCloseProc closeproc = tif->tif_closeproc;
+  thandle_t fd = tif->tif_clientdata;
+
+  TIFFCleanup(tif);
+  (void) (*closeproc)(fd);
+}
+
diff --git a/Utilities/ITK/Utilities/tiff/tif_codec.c b/Utilities/ITK/Utilities/tiff/tif_codec.c
new file mode 100644
index 0000000000..ed145a28c9
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_codec.c
@@ -0,0 +1,150 @@
+/* $Header: /cvsroot/Insight/Insight/Utilities/tiff/tif_codec.c,v 1.3 2005/11/17 22:11:20 malaterre Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library
+ *
+ * Builtin Compression Scheme Configuration Support.
+ */
+#include "tiffiop.h"
+
+static  int NotConfigured(TIFF*, int);
+
+#ifndef  LZW_SUPPORT
+#define  TIFFInitLZW    NotConfigured
+#endif
+#ifndef  PACKBITS_SUPPORT
+#define  TIFFInitPackBits  NotConfigured
+#endif
+#ifndef  THUNDER_SUPPORT
+#define  TIFFInitThunderScan  NotConfigured
+#endif
+#ifndef  NEXT_SUPPORT
+#define  TIFFInitNeXT    NotConfigured
+#endif
+#ifndef  JPEG_SUPPORT
+#define  TIFFInitJPEG    NotConfigured
+#endif
+#ifndef  OJPEG_SUPPORT
+#define  TIFFInitOJPEG    NotConfigured
+#endif
+#ifndef  CCITT_SUPPORT
+#define  TIFFInitCCITTRLE  NotConfigured
+#define  TIFFInitCCITTRLEW  NotConfigured
+#define  TIFFInitCCITTFax3  NotConfigured
+#define  TIFFInitCCITTFax4  NotConfigured
+#endif
+#ifndef JBIG_SUPPORT
+#define  TIFFInitJBIG    NotConfigured
+#endif
+#ifndef  ZIP_SUPPORT
+#define  TIFFInitZIP    NotConfigured
+#endif
+#ifndef  PIXARLOG_SUPPORT
+#define  TIFFInitPixarLog  NotConfigured
+#endif
+#ifndef LOGLUV_SUPPORT
+#define TIFFInitSGILog    NotConfigured
+#endif
+
+/*
+ * Compression schemes statically built into the library.
+ */
+#ifdef VMS
+const TIFFCodec _TIFFBuiltinCODECS[] = {
+#else
+TIFFCodec _TIFFBuiltinCODECS[] = {
+#endif
+    { "None",    COMPRESSION_NONE,  TIFFInitDumpMode },
+    { "LZW",    COMPRESSION_LZW,  TIFFInitLZW },
+    { "PackBits",  COMPRESSION_PACKBITS,  TIFFInitPackBits },
+    { "ThunderScan",  COMPRESSION_THUNDERSCAN,TIFFInitThunderScan },
+    { "NeXT",    COMPRESSION_NEXT,  TIFFInitNeXT },
+    { "JPEG",    COMPRESSION_JPEG,  TIFFInitJPEG },
+    { "Old-style JPEG",  COMPRESSION_OJPEG,  TIFFInitOJPEG },
+    { "CCITT RLE",  COMPRESSION_CCITTRLE,  TIFFInitCCITTRLE },
+    { "CCITT RLE/W",  COMPRESSION_CCITTRLEW,  TIFFInitCCITTRLEW },
+    { "CCITT Group 3",  COMPRESSION_CCITTFAX3,  TIFFInitCCITTFax3 },
+    { "CCITT Group 4",  COMPRESSION_CCITTFAX4,  TIFFInitCCITTFax4 },
+    { "ISO JBIG",  COMPRESSION_JBIG,  TIFFInitJBIG },
+    { "Deflate",  COMPRESSION_DEFLATE,  TIFFInitZIP },
+    { "AdobeDeflate",   COMPRESSION_ADOBE_DEFLATE , TIFFInitZIP }, 
+    { "PixarLog",  COMPRESSION_PIXARLOG,  TIFFInitPixarLog },
+    { "SGILog",    COMPRESSION_SGILOG,  TIFFInitSGILog },
+    { "SGILog24",  COMPRESSION_SGILOG24,  TIFFInitSGILog },
+    { NULL, 0, 0 }
+};
+
+static int
+_notConfigured(TIFF* tif)
+{
+  const TIFFCodec* c = TIFFFindCODEC(tif->tif_dir.td_compression);
+
+  TIFFError(tif->tif_name,
+      "%s compression support is not configured", c->name);
+  return (0);
+}
+
+static int
+NotConfigured(TIFF* tif, int scheme)
+{
+    (void) scheme;
+    
+    tif->tif_decodestatus = FALSE;
+    tif->tif_setupdecode = _notConfigured;
+    tif->tif_encodestatus = FALSE;
+    tif->tif_setupencode = _notConfigured;
+    return (1);
+}
+
+/************************************************************************/
+/*                       TIFFIsCODECConfigured()                        */
+/************************************************************************/
+
+/**
+ * Check whether we have working codec for the specific coding scheme.
+ * 
+ * @return returns 1 if the codec is configured and working. Otherwise
+ * 0 will be returned.
+ */
+
+int
+TIFFIsCODECConfigured(uint16 scheme)
+{
+  const TIFFCodec* codec = TIFFFindCODEC(scheme);
+
+  if(codec == NULL) {
+            return 0;
+        }
+        if(codec->init == NULL) {
+            return 0;
+        }
+  if(codec->init != NotConfigured){
+            return 1;
+        }
+  return 0;
+}
+
diff --git a/Utilities/ITK/Utilities/tiff/tif_color.c b/Utilities/ITK/Utilities/tiff/tif_color.c
new file mode 100644
index 0000000000..8f0626ce88
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_color.c
@@ -0,0 +1,267 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * CIE L*a*b* to CIE XYZ and CIE XYZ to RGB conversion routines are taken
+ * from the VIPS library (http://www.vips.ecs.soton.ac.uk) with
+ * the permission of John Cupitt, the VIPS author.
+ */
+
+/*
+ * TIFF Library.
+ *
+ * Color space conversion routines.
+ */
+
+#include "tiffiop.h"
+#include <math.h>
+
+/*
+ * Convert color value from the CIE L*a*b* 1976 space to CIE XYZ.
+ */
+void
+TIFFCIELabToXYZ(TIFFCIELabToRGB *cielab, uint32 l, int32 a, int32 b,
+    float *X, float *Y, float *Z)
+{
+  float L = (float)l * 100.0F / 255.0F;
+  float cby, tmp;
+
+  if( L < 8.856F ) {
+    *Y = (L * cielab->Y0) / 903.292F;
+    cby = 7.787F * (*Y / cielab->Y0) + 16.0F / 116.0F;
+  } else {
+    cby = (L + 16.0F) / 116.0F;
+    *Y = cielab->Y0 * cby * cby * cby;
+  }
+
+  tmp = (float)a / 500.0F + cby;
+  if( tmp < 0.2069F )
+    *X = cielab->X0 * (tmp - 0.13793F) / 7.787F;
+  else    
+    *X = cielab->X0 * tmp * tmp * tmp;
+
+  tmp = cby - (float)b / 200.0F;
+  if( tmp < 0.2069F )
+    *Z = cielab->Z0 * (tmp - 0.13793F) / 7.787F;
+  else    
+    *Z = cielab->Z0 * tmp * tmp * tmp;
+}
+
+#define RINT(R) ((uint32)((R)>0?((R)+0.5):((R)-0.5)))
+/*
+ * Convert color value from the XYZ space to RGB.
+ */
+void
+TIFFXYZToRGB(TIFFCIELabToRGB *cielab, float X, float Y, float Z,
+       uint32 *r, uint32 *g, uint32 *b)
+{
+  int i;
+  float Yr, Yg, Yb;
+  float *matrix = &cielab->display.d_mat[0][0];
+
+  /* Multiply through the matrix to get luminosity values. */
+  Yr =  matrix[0] * X + matrix[1] * Y + matrix[2] * Z;
+  Yg =  matrix[3] * X + matrix[4] * Y + matrix[5] * Z;
+  Yb =  matrix[6] * X + matrix[7] * Y + matrix[8] * Z;
+
+  /* Clip input */
+  Yr = TIFFmax( Yr, cielab->display.d_Y0R );
+  Yg = TIFFmax( Yg, cielab->display.d_Y0G );
+  Yb = TIFFmax( Yb, cielab->display.d_Y0B );
+
+  /* Turn luminosity to colour value. */
+  i = TIFFmin(cielab->range,
+        (int)((Yr - cielab->display.d_Y0R) / cielab->rstep));
+  *r = RINT(cielab->Yr2r[i]);
+
+  i = TIFFmin(cielab->range,
+        (int)((Yg - cielab->display.d_Y0G) / cielab->gstep));
+  *g = RINT(cielab->Yg2g[i]);
+
+  i = TIFFmin(cielab->range,
+        (int)((Yb - cielab->display.d_Y0B) / cielab->bstep));
+  *b = RINT(cielab->Yb2b[i]);
+
+  /* Clip output. */
+  *r = TIFFmin( *r, cielab->display.d_Vrwr );
+  *g = TIFFmin( *g, cielab->display.d_Vrwg );
+  *b = TIFFmin( *b, cielab->display.d_Vrwb );
+}
+#undef RINT
+
+/* 
+ * Allocate conversion state structures and make look_up tables for
+ * the Yr,Yb,Yg <=> r,g,b conversions.
+ */
+int
+TIFFCIELabToRGBInit(TIFFCIELabToRGB* cielab,
+        TIFFDisplay *display, float *refWhite)
+{
+  int i;
+  double gamma;
+
+  cielab->range = CIELABTORGB_TABLE_RANGE;
+
+  _TIFFmemcpy(&cielab->display, display, sizeof(TIFFDisplay));
+
+  /* Red */
+  gamma = 1.0 / cielab->display.d_gammaR ;
+  cielab->rstep =
+    (cielab->display.d_YCR - cielab->display.d_Y0R)  / cielab->range;
+  for(i = 0; i <= cielab->range; i++) {
+    cielab->Yr2r[i] = cielab->display.d_Vrwr
+        * ((float)pow((double)i / cielab->range, gamma));
+  }
+
+  /* Green */
+  gamma = 1.0 / cielab->display.d_gammaG ;
+  cielab->gstep =
+      (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
+  for(i = 0; i <= cielab->range; i++) {
+    cielab->Yg2g[i] = cielab->display.d_Vrwg
+        * ((float)pow((double)i / cielab->range, gamma));
+  }
+
+  /* Blue */
+  gamma = 1.0 / cielab->display.d_gammaB ;
+  cielab->bstep =
+      (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
+  for(i = 0; i <= cielab->range; i++) {
+    cielab->Yb2b[i] = cielab->display.d_Vrwb
+        * ((float)pow((double)i / cielab->range, gamma));
+  }
+
+  /* Init reference white point */
+  cielab->X0 = refWhite[0];
+  cielab->Y0 = refWhite[1];
+  cielab->Z0 = refWhite[2];
+
+  return 0;
+}
+
+/* 
+ * Convert color value from the YCbCr space to CIE XYZ.
+ * The colorspace conversion algorithm comes from the IJG v5a code;
+ * see below for more information on how it works.
+ */
+#define  SHIFT      16
+#define  FIX(x)      ((int32)((x) * (1L<<SHIFT) + 0.5))
+#define  ONE_HALF    ((int32)(1<<(SHIFT-1)))
+#define  Code2V(c, RB, RW, CR)  ((((c)-(int32)(RB))*(float)(CR))/(float)(((RW)-(RB)) ? ((RW)-(RB)) : 1))
+#define  CLAMP(f,min,max)  ((f)<(min)?(min):(f)>(max)?(max):(f))
+
+void
+TIFFYCbCrtoRGB(TIFFYCbCrToRGB *ycbcr, uint32 Y, int32 Cb, int32 Cr,
+         uint32 *r, uint32 *g, uint32 *b)
+{
+  /* XXX: Only 8-bit YCbCr input supported for now */
+  Y = CLAMP((int32)Y, 0, 255), Cb = CLAMP((int32)Cb, 0, 255), Cr = CLAMP((int32)Cr, 0, 255);
+
+  *r = ycbcr->clamptab[ycbcr->Y_tab[Y] + ycbcr->Cr_r_tab[Cr]];
+  *g = ycbcr->clamptab[ycbcr->Y_tab[Y]
+      + (int)((ycbcr->Cb_g_tab[Cb] + ycbcr->Cr_g_tab[Cr]) >> SHIFT)];
+  *b = ycbcr->clamptab[ycbcr->Y_tab[Y] + ycbcr->Cb_b_tab[Cb]];
+}
+
+/*
+ * Initialize the YCbCr->RGB conversion tables.  The conversion
+ * is done according to the 6.0 spec:
+ *
+ *    R = Y + Cr*(2 - 2*LumaRed)
+ *    B = Y + Cb*(2 - 2*LumaBlue)
+ *    G =   Y
+ *        - LumaBlue*Cb*(2-2*LumaBlue)/LumaGreen
+ *        - LumaRed*Cr*(2-2*LumaRed)/LumaGreen
+ *
+ * To avoid floating point arithmetic the fractional constants that
+ * come out of the equations are represented as fixed point values
+ * in the range 0...2^16.  We also eliminate multiplications by
+ * pre-calculating possible values indexed by Cb and Cr (this code
+ * assumes conversion is being done for 8-bit samples).
+ */
+int
+TIFFYCbCrToRGBInit(TIFFYCbCrToRGB* ycbcr, float *luma, float *refBlackWhite)
+{
+    TIFFRGBValue* clamptab;
+    int i;
+    
+#define LumaRed      luma[0]
+#define LumaGreen   luma[1]
+#define LumaBlue    luma[2]
+
+    clamptab = (TIFFRGBValue*)(
+  (tidata_t) ycbcr+TIFFroundup(sizeof (TIFFYCbCrToRGB), sizeof (long)));
+    _TIFFmemset(clamptab, 0, 256);    /* v < 0 => 0 */
+    ycbcr->clamptab = (clamptab += 256);
+    for (i = 0; i < 256; i++)
+  clamptab[i] = (TIFFRGBValue) i;
+    _TIFFmemset(clamptab+256, 255, 2*256);  /* v > 255 => 255 */
+    ycbcr->Cr_r_tab = (int*) (clamptab + 3*256);
+    ycbcr->Cb_b_tab = ycbcr->Cr_r_tab + 256;
+    ycbcr->Cr_g_tab = (int32*) (ycbcr->Cb_b_tab + 256);
+    ycbcr->Cb_g_tab = ycbcr->Cr_g_tab + 256;
+    ycbcr->Y_tab = ycbcr->Cb_g_tab + 256;
+
+    { float f1 = 2-2*LumaRed;    int32 D1 = FIX(f1);
+      float f2 = LumaRed*f1/LumaGreen;  int32 D2 = -FIX(f2);
+      float f3 = 2-2*LumaBlue;    int32 D3 = FIX(f3);
+      float f4 = LumaBlue*f3/LumaGreen;  int32 D4 = -FIX(f4);
+      int x;
+
+#undef LumaBlue
+#undef LumaGreen
+#undef LumaRed
+      
+      /*
+       * i is the actual input pixel value in the range 0..255
+       * Cb and Cr values are in the range -128..127 (actually
+       * they are in a range defined by the ReferenceBlackWhite
+       * tag) so there is some range shifting to do here when
+       * constructing tables indexed by the raw pixel data.
+       */
+      for (i = 0, x = -128; i < 256; i++, x++) {
+      int32 Cr = (int32)Code2V(x, refBlackWhite[4] - 128.0F,
+          refBlackWhite[5] - 128.0F, 127);
+      int32 Cb = (int32)Code2V(x, refBlackWhite[2] - 128.0F,
+          refBlackWhite[3] - 128.0F, 127);
+
+      ycbcr->Cr_r_tab[i] = (int32)((D1*Cr + ONE_HALF)>>SHIFT);
+      ycbcr->Cb_b_tab[i] = (int32)((D3*Cb + ONE_HALF)>>SHIFT);
+      ycbcr->Cr_g_tab[i] = D2*Cr;
+      ycbcr->Cb_g_tab[i] = D4*Cb + ONE_HALF;
+      ycbcr->Y_tab[i] =
+        (int32)Code2V(x + 128, refBlackWhite[0], refBlackWhite[1], 255);
+      }
+    }
+
+    return 0;
+}
+#undef  CLAMP
+#undef  Code2V
+#undef  SHIFT
+#undef  ONE_HALF
+#undef  FIX
+
diff --git a/Utilities/ITK/Utilities/tiff/tif_compress.c b/Utilities/ITK/Utilities/tiff/tif_compress.c
new file mode 100644
index 0000000000..11786651cc
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_compress.c
@@ -0,0 +1,283 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library
+ *
+ * Compression Scheme Configuration Support.
+ */
+#include "tiffiop.h"
+
+static int
+TIFFNoEncode(TIFF* tif, char* method)
+{
+  const TIFFCodec* c = TIFFFindCODEC(tif->tif_dir.td_compression);
+
+  if (c) { 
+          TIFFError(tif->tif_name, "%s %s encoding is not implemented",
+                          c->name, method);
+  } else { 
+    TIFFError(tif->tif_name,
+        "Compression scheme %u %s encoding is not implemented",
+        tif->tif_dir.td_compression, method);
+  }
+  return (-1);
+}
+
+int
+_TIFFNoRowEncode(TIFF* tif, tidata_t pp, tsize_t cc, tsample_t s)
+{
+  (void) pp; (void) cc; (void) s;
+  return (TIFFNoEncode(tif, "scanline"));
+}
+
+int
+_TIFFNoStripEncode(TIFF* tif, tidata_t pp, tsize_t cc, tsample_t s)
+{
+  (void) pp; (void) cc; (void) s;
+  return (TIFFNoEncode(tif, "strip"));
+}
+
+int
+_TIFFNoTileEncode(TIFF* tif, tidata_t pp, tsize_t cc, tsample_t s)
+{
+  (void) pp; (void) cc; (void) s;
+  return (TIFFNoEncode(tif, "tile"));
+}
+
+static int
+TIFFNoDecode(TIFF* tif, char* method)
+{
+  const TIFFCodec* c = TIFFFindCODEC(tif->tif_dir.td_compression);
+
+  if (c)
+    TIFFError(tif->tif_name, "%s %s decoding is not implemented",
+        c->name, method);
+  else
+    TIFFError(tif->tif_name,
+        "Compression scheme %u %s decoding is not implemented",
+        tif->tif_dir.td_compression, method);
+  return (-1);
+}
+
+int
+_TIFFNoRowDecode(TIFF* tif, tidata_t pp, tsize_t cc, tsample_t s)
+{
+  (void) pp; (void) cc; (void) s;
+  return (TIFFNoDecode(tif, "scanline"));
+}
+
+int
+_TIFFNoStripDecode(TIFF* tif, tidata_t pp, tsize_t cc, tsample_t s)
+{
+  (void) pp; (void) cc; (void) s;
+  return (TIFFNoDecode(tif, "strip"));
+}
+
+int
+_TIFFNoTileDecode(TIFF* tif, tidata_t pp, tsize_t cc, tsample_t s)
+{
+  (void) pp; (void) cc; (void) s;
+  return (TIFFNoDecode(tif, "tile"));
+}
+
+int
+_TIFFNoSeek(TIFF* tif, uint32 off)
+{
+  (void) off;
+  TIFFError(tif->tif_name,
+      "Compression algorithm does not support random access");
+  return (0);
+}
+
+int
+_TIFFNoPreCode(TIFF* tif, tsample_t s)
+{
+  (void) tif; (void) s;
+  return (1);
+}
+
+static int _TIFFtrue(TIFF* tif) { (void) tif; return (1); }
+static void _TIFFvoid(TIFF* tif) { (void) tif; }
+
+void
+_TIFFSetDefaultCompressionState(TIFF* tif)
+{
+  tif->tif_decodestatus = TRUE;
+  tif->tif_setupdecode = _TIFFtrue;
+  tif->tif_predecode = _TIFFNoPreCode;
+  tif->tif_decoderow = _TIFFNoRowDecode;
+  tif->tif_decodestrip = _TIFFNoStripDecode;
+  tif->tif_decodetile = _TIFFNoTileDecode;
+  tif->tif_encodestatus = TRUE;
+  tif->tif_setupencode = _TIFFtrue;
+  tif->tif_preencode = _TIFFNoPreCode;
+  tif->tif_postencode = _TIFFtrue;
+  tif->tif_encoderow = _TIFFNoRowEncode;
+  tif->tif_encodestrip = _TIFFNoStripEncode;
+  tif->tif_encodetile = _TIFFNoTileEncode;
+  tif->tif_close = _TIFFvoid;
+  tif->tif_seek = _TIFFNoSeek;
+  tif->tif_cleanup = _TIFFvoid;
+  tif->tif_defstripsize = _TIFFDefaultStripSize;
+  tif->tif_deftilesize = _TIFFDefaultTileSize;
+  tif->tif_flags &= ~TIFF_NOBITREV;
+}
+
+int
+TIFFSetCompressionScheme(TIFF* tif, int scheme)
+{
+  const TIFFCodec *c = TIFFFindCODEC((uint16) scheme);
+
+  _TIFFSetDefaultCompressionState(tif);
+  /*
+   * Don't treat an unknown compression scheme as an error.
+   * This permits applications to open files with data that
+   * the library does not have builtin support for, but which
+   * may still be meaningful.
+   */
+  return (c ? (*c->init)(tif, scheme) : 1);
+}
+
+/*
+ * Other compression schemes may be registered.  Registered
+ * schemes can also override the builtin versions provided
+ * by this library.
+ */
+typedef struct _codec {
+  struct _codec*  next;
+  TIFFCodec*  info;
+} codec_t;
+static  codec_t* registeredCODECS = NULL;
+
+const TIFFCodec*
+TIFFFindCODEC(uint16 scheme)
+{
+  const TIFFCodec* c;
+  codec_t* cd;
+
+  for (cd = registeredCODECS; cd; cd = cd->next)
+    if (cd->info->scheme == scheme)
+      return ((const TIFFCodec*) cd->info);
+  for (c = _TIFFBuiltinCODECS; c->name; c++)
+    if (c->scheme == scheme)
+      return (c);
+  return ((const TIFFCodec*) 0);
+}
+
+TIFFCodec*
+TIFFRegisterCODEC(uint16 scheme, const char* name, TIFFInitMethod init)
+{
+  codec_t* cd = (codec_t*)
+      _TIFFmalloc(sizeof (codec_t) + sizeof (TIFFCodec) + strlen(name)+1);
+
+  if (cd != NULL) {
+    cd->info = (TIFFCodec*) ((tidata_t) cd + sizeof (codec_t));
+    cd->info->name = (char*)
+        ((tidata_t) cd->info + sizeof (TIFFCodec));
+    strcpy(cd->info->name, name);
+    cd->info->scheme = scheme;
+    cd->info->init = init;
+    cd->next = registeredCODECS;
+    registeredCODECS = cd;
+  } else {
+    TIFFError("TIFFRegisterCODEC",
+        "No space to register compression scheme %s", name);
+    return NULL;
+  }
+  return (cd->info);
+}
+
+void
+TIFFUnRegisterCODEC(TIFFCodec* c)
+{
+  codec_t* cd;
+  codec_t** pcd;
+
+  for (pcd = &registeredCODECS; (cd = *pcd); pcd = &cd->next)
+    if (cd->info == c) {
+      *pcd = cd->next;
+      _TIFFfree(cd);
+      return;
+    }
+  TIFFError("TIFFUnRegisterCODEC",
+      "Cannot remove compression scheme %s; not registered", c->name);
+}
+
+/************************************************************************/
+/*                       TIFFGetConfisuredCODECs()                      */
+/************************************************************************/
+
+/**
+ * Get list of configured codecs, both built-in and registered by user.
+ * Caller is responsible to free this structure.
+ * 
+ * @return returns array of TIFFCodec records (the last record should be NULL)
+ * or NULL if function failed.
+ */
+
+TIFFCodec*
+TIFFGetConfiguredCODECs()
+{
+  int    i = 1;
+        codec_t    *cd;
+        const TIFFCodec  *c;
+  TIFFCodec  *codecs = NULL, *new_codecs;
+
+        for (cd = registeredCODECS; cd; cd = cd->next) {
+                new_codecs = _TIFFrealloc(codecs, i * sizeof(TIFFCodec));
+    if (!new_codecs) {
+      _TIFFfree (codecs);
+      return NULL;
+    }
+    codecs = new_codecs;
+    _TIFFmemcpy(codecs + i - 1, cd, sizeof(TIFFCodec));
+    i++;
+  }
+        for (c = _TIFFBuiltinCODECS; c->name; c++) {
+                if (TIFFIsCODECConfigured(c->scheme)) {
+                        new_codecs = _TIFFrealloc(codecs, i * sizeof(TIFFCodec));
+      if (!new_codecs) {
+        _TIFFfree (codecs);
+        return NULL;
+      }
+      codecs = new_codecs;
+      _TIFFmemcpy(codecs + i - 1, (tdata_t)c, sizeof(TIFFCodec));
+      i++;
+    }
+  }
+
+  new_codecs = _TIFFrealloc(codecs, i * sizeof(TIFFCodec));
+  if (!new_codecs) {
+    _TIFFfree (codecs);
+    return NULL;
+  }
+  codecs = new_codecs;
+  _TIFFmemset(codecs + i - 1, 0, sizeof(TIFFCodec));
+
+        return codecs;
+}
+
diff --git a/Utilities/ITK/Utilities/tiff/tif_config.h.in b/Utilities/ITK/Utilities/tiff/tif_config.h.in
new file mode 100644
index 0000000000..4e1c270a76
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_config.h.in
@@ -0,0 +1,253 @@
+/* libtiff/tif_config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Support CCITT Group 3 & 4 algorithms */
+#define CCITT_SUPPORT 1
+
+/* Pick up YCbCr subsampling info from the JPEG data stream to support files
+   lacking the tag (default enabled). */
+#cmakedefine CHECK_JPEG_YCBCR_SUBSAMPLING
+
+/* Support C++ stream API (requires C++ compiler) */
+#cmakedefine CXX_SUPPORT
+
+/* Treat extra sample as alpha (default enabled). The RGBA interface will
+   treat a fourth sample with no EXTRASAMPLE_ value as being ASSOCALPHA. Many
+   packages produce RGBA files but don't mark the alpha properly. */
+#cmakedefine DEFAULT_EXTRASAMPLE_AS_ALPHA
+
+/* Use the Apple OpenGL framework. */
+#cmakedefine HAVE_APPLE_OPENGL_FRAMEWORK
+
+/* Define to 1 if you have the <assert.h> header file. */
+#cmakedefine HAVE_ASSERT_H @HAVE_ASSERT_H@
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#cmakedefine HAVE_DLFCN_H @HAVE_DLFCN_H@
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#cmakedefine HAVE_FCNTL_H @HAVE_FCNTL_H@
+
+/* Define to 1 if you have the `floor' function. */
+#cmakedefine HAVE_FLOOR @HAVE_FLOOR@
+
+/* Define to 1 if you have the `getopt' function. */
+#cmakedefine HAVE_GETOPT @HAVE_GETOPT@
+
+/* Define as 0 or 1 according to the floating point format suported by the
+   machine */
+#define HAVE_IEEEFP 1
+
+/* Define to 1 if the system has the type `int16'. */
+#cmakedefine HAVE_INT16
+
+/* Define to 1 if the system has the type `int32'. */
+#cmakedefine HAVE_INT32
+
+/* Define to 1 if the system has the type `int8'. */
+#cmakedefine HAVE_INT8
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#cmakedefine HAVE_INTTYPES_H @HAVE_INTTYPES_H@
+
+/* Define to 1 if you have the `isascii' function. */
+#cmakedefine HAVE_ISASCII @HAVE_ISASCII@
+
+/* Define to 1 if you have the `c' library (-lc). */
+#cmakedefine HAVE_LIBC
+
+/* Define to 1 if you have the `m' library (-lm). */
+#cmakedefine HAVE_LIBM
+
+/* Define to 1 if you have the <limits.h> header file. */
+#cmakedefine HAVE_LIMITS_H @HAVE_LIMITS_H@
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#cmakedefine HAVE_MALLOC_H @HAVE_MALLOC_H@
+
+/* Define to 1 if you have the `memmove' function. */
+#cmakedefine HAVE_MEMMOVE @HAVE_MEMMOVE@
+
+/* Define to 1 if you have the <memory.h> header file. */
+#cmakedefine HAVE_MEMORY_H @HAVE_MEMORY_H@
+
+/* Define to 1 if you have the `memset' function. */
+#cmakedefine HAVE_MEMSET @HAVE_MEMSET@
+
+/* Define to 1 if you have the `mmap' function. */
+#cmakedefine HAVE_MMAP @HAVE_MMAP@
+
+/* Define to 1 if you have the `pow' function. */
+#cmakedefine HAVE_POW @HAVE_POW@
+
+/* Define if you have POSIX threads libraries and header files. */
+#cmakedefine HAVE_PTHREAD
+
+/* Define to 1 if you have the `sqrt' function. */
+#cmakedefine HAVE_SQRT @HAVE_SQRT@
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#cmakedefine HAVE_STDINT_H @HAVE_STDINT_H@
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#cmakedefine HAVE_STDLIB_H @HAVE_STDLIB_H@
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#cmakedefine HAVE_STRCASECMP @HAVE_STRCASECMP@
+
+/* Define to 1 if you have the `strchr' function. */
+#cmakedefine HAVE_STRCHR @HAVE_STRCHR@
+
+/* Define to 1 if you have the <strings.h> header file. */
+#cmakedefine HAVE_STRINGS_H @HAVE_STRINGS_H@
+
+/* Define to 1 if you have the <string.h> header file. */
+#cmakedefine HAVE_STRING_H @HAVE_STRING_H@
+
+/* Define to 1 if you have the `strrchr' function. */
+#cmakedefine HAVE_STRRCHR @HAVE_STRRCHR@
+
+/* Define to 1 if you have the `strstr' function. */
+#cmakedefine HAVE_STRSTR @HAVE_STRSTR@
+
+/* Define to 1 if you have the `strtol' function. */
+#cmakedefine HAVE_STRTOL @HAVE_STRTOL@
+
+/* Define to 1 if you have the `strtoul' function. */
+#cmakedefine HAVE_STRTOUL @HAVE_STRTOUL@
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#cmakedefine HAVE_SYS_STAT_H @HAVE_SYS_STAT_H@
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#cmakedefine HAVE_SYS_TIME_H @HAVE_SYS_TIME_H@
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#cmakedefine HAVE_SYS_TYPES_H @HAVE_SYS_TYPES_H@
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#cmakedefine HAVE_UNISTD_H @HAVE_UNISTD_H@
+
+/* Define to 1 if you have the <windows.h> header file. */
+#cmakedefine HAVE_WINDOWS_H @HAVE_WINDOWS_H@
+
+/* Native cpu byte order: 1 if big-endian (Motorola) or 0 if little-endian
+   (Intel) */
+#ifdef CMAKE_WORDS_BIGENDIAN
+  #define HOST_BIGENDIAN 1
+#else
+  #define HOST_BIGENDIAN 0
+#endif
+
+/* Set the native cpu bit order (FILLORDER_LSB2MSB or FILLORDER_MSB2LSB) */
+#ifdef CMAKE_WORDS_BIGENDIAN
+  #define HOST_FILLORDER FILLORDER_LSB2MSB
+#else
+  #define HOST_FILLORDER FILLORDER_MSB2LSB
+#endif
+
+/* Support JPEG compression (requires IJG JPEG library) */
+#cmakedefine JPEG_SUPPORT @JPEG_SUPPORT@
+
+/* Support LogLuv high dynamic range encoding */
+#define LOGLUV_SUPPORT 1
+
+/* Support LZW algorithm */
+#define LZW_SUPPORT 1
+
+/* Support NeXT 2-bit RLE algorithm */
+#define NEXT_SUPPORT 1
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+#cmakedefine NO_MINUS_C_MINUS_O
+
+/* Support Old JPEG compresson (read contrib/ojpeg/README first! Compilation
+   fails with unpatched IJG JPEG library) */
+#cmakedefine OJPEG_SUPPORT
+
+/* Name of package */
+#cmakedefine PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#cmakedefine PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#cmakedefine PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#cmakedefine PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#cmakedefine PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#cmakedefine PACKAGE_VERSION
+
+/* Support Macintosh PackBits algorithm */
+#define PACKBITS_SUPPORT 1
+
+/* Support Pixar log-format algorithm (requires Zlib) */
+#cmakedefine PIXARLOG_SUPPORT
+
+/* Define to the necessary symbol if this constant uses a non-standard name on
+   your system. */
+#cmakedefine PTHREAD_CREATE_JOINABLE
+
+/* The size of a `int', as computed by sizeof. */
+#define SIZEOF_INT @CMAKE_SIZEOF_INT@
+
+/* The size of a `long', as computed by sizeof. */
+#define SIZEOF_LONG @CMAKE_SIZEOF_LONG@
+
+/* Define to 1 if you have the ANSI C header files. */
+#cmakedefine STDC_HEADERS
+
+/* Support strip chopping (whether or not to convert single-strip uncompressed
+   images to mutiple strips of ~8Kb to reduce memory usage) */
+#cmakedefine STRIPCHOP_DEFAULT
+
+/* Enable SubIFD tag (330) support */
+#cmakedefine SUBIFD_SUPPORT
+
+/* Support ThunderScan 4-bit RLE algorithm */
+#cmakedefine THUNDER_SUPPORT
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#cmakedefine TIME_WITH_SYS_TIME
+
+/* Define to 1 if your <sys/time.h> declares `struct tm'. */
+#cmakedefine TM_IN_SYS_TIME
+
+/* Version number of package */
+#cmakedefine VERSION
+
+/* Define to 1 if your processor stores words with the most significant byte
+   first (like Motorola and SPARC, unlike Intel and VAX). */
+#cmakedefine WORDS_BIGENDIAN
+
+/* Define to 1 if the X Window System is missing or not being used. */
+#cmakedefine X_DISPLAY_MISSING
+
+/* Support Deflate compression */
+#cmakedefine ZIP_SUPPORT
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#cmakedefine _FILE_OFFSET_BITS
+
+/* Define for large files, on AIX-style hosts. */
+#cmakedefine _LARGE_FILES
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#cmakedefine const
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+#define inline
+//#cmakedefine inline
+#endif
+
+/* Define to `long' if <sys/types.h> does not define. */
+#cmakedefine off_t
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+#cmakedefine size_t
diff --git a/Utilities/ITK/Utilities/tiff/tif_dir.c b/Utilities/ITK/Utilities/tiff/tif_dir.c
new file mode 100644
index 0000000000..34b5720f05
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_dir.c
@@ -0,0 +1,1478 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ *
+ * Directory Tag Get & Set Routines.
+ * (and also some miscellaneous stuff)
+ */
+#include "tiffiop.h"
+
+/*
+ * These are used in the backwards compatibility code...
+ */
+#define DATATYPE_VOID    0       /* !untyped data */
+#define DATATYPE_INT    1       /* !signed integer data */
+#define DATATYPE_UINT    2       /* !unsigned integer data */
+#define DATATYPE_IEEEFP    3       /* !IEEE floating point data */
+
+static void
+setByteArray(void** vpp, void* vp, size_t nmemb, size_t elem_size)
+{
+  if (*vpp)
+    _TIFFfree(*vpp), *vpp = 0;
+  if (vp) {
+    tsize_t  bytes = nmemb * elem_size;
+    if (elem_size && bytes / elem_size == nmemb)
+      *vpp = (void*) _TIFFmalloc(bytes);
+    if (*vpp)
+      _TIFFmemcpy(*vpp, vp, bytes);
+  }
+}
+void _TIFFsetByteArray(void** vpp, void* vp, long n)
+    { setByteArray(vpp, vp, n, 1); }
+void _TIFFsetString(char** cpp, char* cp)
+    { setByteArray((void**) cpp, (void*) cp, strlen(cp)+1, 1); }
+void _TIFFsetNString(char** cpp, char* cp, long n)
+    { setByteArray((void**) cpp, (void*) cp, n, 1); }
+void _TIFFsetShortArray(uint16** wpp, uint16* wp, long n)
+    { setByteArray((void**) wpp, (void*) wp, n, sizeof (uint16)); }
+void _TIFFsetLongArray(uint32** lpp, uint32* lp, long n)
+    { setByteArray((void**) lpp, (void*) lp, n, sizeof (uint32)); }
+void _TIFFsetFloatArray(float** fpp, float* fp, long n)
+    { setByteArray((void**) fpp, (void*) fp, n, sizeof (float)); }
+void _TIFFsetDoubleArray(double** dpp, double* dp, long n)
+    { setByteArray((void**) dpp, (void*) dp, n, sizeof (double)); }
+
+/*
+ * Install extra samples information.
+ */
+static int
+setExtraSamples(TIFFDirectory* td, va_list ap, int* v)
+{
+  uint16* va;
+  int i;
+
+  *v = va_arg(ap, int);
+  if ((uint16) *v > td->td_samplesperpixel)
+    return (0);
+  va = va_arg(ap, uint16*);
+  if (*v > 0 && va == NULL)    /* typically missing param */
+    return (0);
+  for (i = 0; i < *v; i++)
+    if (va[i] > EXTRASAMPLE_UNASSALPHA)
+      return (0);
+  td->td_extrasamples = (uint16) *v;
+  _TIFFsetShortArray(&td->td_sampleinfo, va, td->td_extrasamples);
+  return (1);
+}
+
+static int
+checkInkNamesString(TIFF* tif, int slen, const char* s)
+{
+  TIFFDirectory* td = &tif->tif_dir;
+  int i = td->td_samplesperpixel;
+
+  if (slen > 0) {
+    const char* ep = s+slen;
+    const char* cp = s;
+    for (; i > 0; i--) {
+      for (; *cp != '\0'; cp++)
+        if (cp >= ep)
+          goto bad;
+      cp++;        /* skip \0 */
+    }
+    return (cp-s);
+  }
+bad:
+  TIFFError("TIFFSetField",
+      "%s: Invalid InkNames value; expecting %d names, found %d",
+      tif->tif_name,
+      td->td_samplesperpixel,
+      td->td_samplesperpixel-i);
+  return (0);
+}
+
+static int
+_TIFFVSetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+  static const char module[] = "_TIFFVSetField";
+  
+  TIFFDirectory* td = &tif->tif_dir;
+  int status = 1;
+  uint32 v32;
+  int i, v;
+  double d;
+  char* s;
+
+  switch (tag) {
+  case TIFFTAG_SUBFILETYPE:
+    td->td_subfiletype = va_arg(ap, uint32);
+    break;
+  case TIFFTAG_IMAGEWIDTH:
+    td->td_imagewidth = va_arg(ap, uint32);
+    break;
+  case TIFFTAG_IMAGELENGTH:
+    td->td_imagelength = va_arg(ap, uint32);
+    break;
+  case TIFFTAG_BITSPERSAMPLE:
+    td->td_bitspersample = (uint16) va_arg(ap, int);
+    /*
+     * If the data require post-decoding processing
+     * to byte-swap samples, set it up here.  Note
+     * that since tags are required to be ordered,
+     * compression code can override this behaviour
+     * in the setup method if it wants to roll the
+     * post decoding work in with its normal work.
+     */
+    if (tif->tif_flags & TIFF_SWAB) {
+      if (td->td_bitspersample == 16)
+        tif->tif_postdecode = _TIFFSwab16BitData;
+      else if (td->td_bitspersample == 32)
+        tif->tif_postdecode = _TIFFSwab32BitData;
+      else if (td->td_bitspersample == 64)
+        tif->tif_postdecode = _TIFFSwab64BitData;
+    }
+    break;
+  case TIFFTAG_COMPRESSION:
+    v = va_arg(ap, int) & 0xffff;
+    /*
+     * If we're changing the compression scheme,
+     * the notify the previous module so that it
+     * can cleanup any state it's setup.
+     */
+    if (TIFFFieldSet(tif, FIELD_COMPRESSION)) {
+      if (td->td_compression == v)
+        break;
+      (*tif->tif_cleanup)(tif);
+      tif->tif_flags &= ~TIFF_CODERSETUP;
+    }
+    /*
+     * Setup new compression routine state.
+     */
+    if( (status = TIFFSetCompressionScheme(tif, v)) != 0 )
+                    td->td_compression = (uint16) v;
+                else
+                    status = 0;
+    break;
+  case TIFFTAG_PHOTOMETRIC:
+    td->td_photometric = (uint16) va_arg(ap, int);
+    break;
+  case TIFFTAG_THRESHHOLDING:
+    td->td_threshholding = (uint16) va_arg(ap, int);
+    break;
+  case TIFFTAG_FILLORDER:
+    v = va_arg(ap, int);
+    if (v != FILLORDER_LSB2MSB && v != FILLORDER_MSB2LSB)
+      goto badvalue;
+    td->td_fillorder = (uint16) v;
+    break;
+  case TIFFTAG_DOCUMENTNAME:
+    _TIFFsetString(&td->td_documentname, va_arg(ap, char*));
+    break;
+  case TIFFTAG_ARTIST:
+    _TIFFsetString(&td->td_artist, va_arg(ap, char*));
+    break;
+  case TIFFTAG_DATETIME:
+    _TIFFsetString(&td->td_datetime, va_arg(ap, char*));
+    break;
+  case TIFFTAG_HOSTCOMPUTER:
+    _TIFFsetString(&td->td_hostcomputer, va_arg(ap, char*));
+    break;
+  case TIFFTAG_IMAGEDESCRIPTION:
+    _TIFFsetString(&td->td_imagedescription, va_arg(ap, char*));
+    break;
+  case TIFFTAG_MAKE:
+    _TIFFsetString(&td->td_make, va_arg(ap, char*));
+    break;
+  case TIFFTAG_MODEL:
+    _TIFFsetString(&td->td_model, va_arg(ap, char*));
+    break;
+  case TIFFTAG_COPYRIGHT:
+    _TIFFsetString(&td->td_copyright, va_arg(ap, char*));
+    break;
+  case TIFFTAG_ORIENTATION:
+    v = va_arg(ap, int);
+    if (v < ORIENTATION_TOPLEFT || ORIENTATION_LEFTBOT < v) {
+      TIFFWarning(tif->tif_name,
+          "Bad value %ld for \"%s\" tag ignored",
+          v, _TIFFFieldWithTag(tif, tag)->field_name);
+    } else
+      td->td_orientation = (uint16) v;
+    break;
+  case TIFFTAG_SAMPLESPERPIXEL:
+    /* XXX should cross check -- e.g. if pallette, then 1 */
+    v = va_arg(ap, int);
+    if (v == 0)
+      goto badvalue;
+    td->td_samplesperpixel = (uint16) v;
+    break;
+  case TIFFTAG_ROWSPERSTRIP:
+    v32 = va_arg(ap, uint32);
+    if (v32 == 0)
+      goto badvalue32;
+    td->td_rowsperstrip = v32;
+    if (!TIFFFieldSet(tif, FIELD_TILEDIMENSIONS)) {
+      td->td_tilelength = v32;
+      td->td_tilewidth = td->td_imagewidth;
+    }
+    break;
+  case TIFFTAG_MINSAMPLEVALUE:
+    td->td_minsamplevalue = (uint16) va_arg(ap, int);
+    break;
+  case TIFFTAG_MAXSAMPLEVALUE:
+    td->td_maxsamplevalue = (uint16) va_arg(ap, int);
+    break;
+  case TIFFTAG_SMINSAMPLEVALUE:
+    td->td_sminsamplevalue = (double) va_arg(ap, dblparam_t);
+    break;
+  case TIFFTAG_SMAXSAMPLEVALUE:
+    td->td_smaxsamplevalue = (double) va_arg(ap, dblparam_t);
+    break;
+  case TIFFTAG_XRESOLUTION:
+    td->td_xresolution = (float) va_arg(ap, dblparam_t);
+    break;
+  case TIFFTAG_YRESOLUTION:
+    td->td_yresolution = (float) va_arg(ap, dblparam_t);
+    break;
+  case TIFFTAG_PLANARCONFIG:
+    v = va_arg(ap, int);
+    if (v != PLANARCONFIG_CONTIG && v != PLANARCONFIG_SEPARATE)
+      goto badvalue;
+    td->td_planarconfig = (uint16) v;
+    break;
+  case TIFFTAG_PAGENAME:
+    _TIFFsetString(&td->td_pagename, va_arg(ap, char*));
+    break;
+  case TIFFTAG_XPOSITION:
+    td->td_xposition = (float) va_arg(ap, dblparam_t);
+    break;
+  case TIFFTAG_YPOSITION:
+    td->td_yposition = (float) va_arg(ap, dblparam_t);
+    break;
+  case TIFFTAG_RESOLUTIONUNIT:
+    v = va_arg(ap, int);
+    if (v < RESUNIT_NONE || RESUNIT_CENTIMETER < v)
+      goto badvalue;
+    td->td_resolutionunit = (uint16) v;
+    break;
+  case TIFFTAG_PAGENUMBER:
+    td->td_pagenumber[0] = (uint16) va_arg(ap, int);
+    td->td_pagenumber[1] = (uint16) va_arg(ap, int);
+    break;
+  case TIFFTAG_HALFTONEHINTS:
+    td->td_halftonehints[0] = (uint16) va_arg(ap, int);
+    td->td_halftonehints[1] = (uint16) va_arg(ap, int);
+    break;
+  case TIFFTAG_COLORMAP:
+    v32 = (uint32)(1L<<td->td_bitspersample);
+    _TIFFsetShortArray(&td->td_colormap[0], va_arg(ap, uint16*), v32);
+    _TIFFsetShortArray(&td->td_colormap[1], va_arg(ap, uint16*), v32);
+    _TIFFsetShortArray(&td->td_colormap[2], va_arg(ap, uint16*), v32);
+    break;
+  case TIFFTAG_EXTRASAMPLES:
+    if (!setExtraSamples(td, ap, &v))
+      goto badvalue;
+    break;
+  case TIFFTAG_MATTEING:
+    td->td_extrasamples = (uint16) (va_arg(ap, int) != 0);
+    if (td->td_extrasamples) {
+      uint16 sv = EXTRASAMPLE_ASSOCALPHA;
+      _TIFFsetShortArray(&td->td_sampleinfo, &sv, 1);
+    }
+    break;
+  case TIFFTAG_TILEWIDTH:
+    v32 = va_arg(ap, uint32);
+    if (v32 % 16) {
+      if (tif->tif_mode != O_RDONLY)
+        goto badvalue32;
+      TIFFWarning(tif->tif_name,
+          "Nonstandard tile width %d, convert file", v32);
+    }
+    td->td_tilewidth = v32;
+    tif->tif_flags |= TIFF_ISTILED;
+    break;
+  case TIFFTAG_TILELENGTH:
+    v32 = va_arg(ap, uint32);
+    if (v32 % 16) {
+      if (tif->tif_mode != O_RDONLY)
+        goto badvalue32;
+      TIFFWarning(tif->tif_name,
+          "Nonstandard tile length %d, convert file", v32);
+    }
+    td->td_tilelength = v32;
+    tif->tif_flags |= TIFF_ISTILED;
+    break;
+  case TIFFTAG_TILEDEPTH:
+    v32 = va_arg(ap, uint32);
+    if (v32 == 0)
+      goto badvalue32;
+    td->td_tiledepth = v32;
+    break;
+  case TIFFTAG_DATATYPE:
+    v = va_arg(ap, int);
+    switch (v) {
+    case DATATYPE_VOID:  v = SAMPLEFORMAT_VOID;  break;
+    case DATATYPE_INT:  v = SAMPLEFORMAT_INT;  break;
+    case DATATYPE_UINT:  v = SAMPLEFORMAT_UINT;  break;
+    case DATATYPE_IEEEFP:  v = SAMPLEFORMAT_IEEEFP;break;
+    default:    goto badvalue;
+    }
+    td->td_sampleformat = (uint16) v;
+    break;
+  case TIFFTAG_SAMPLEFORMAT:
+    v = va_arg(ap, int);
+    if (v < SAMPLEFORMAT_UINT || SAMPLEFORMAT_COMPLEXIEEEFP < v)
+      goto badvalue;
+    td->td_sampleformat = (uint16) v;
+
+                /*  Try to fix up the SWAB function for complex data. */
+                if( td->td_sampleformat == SAMPLEFORMAT_COMPLEXINT 
+                    && td->td_bitspersample == 32
+                    && tif->tif_postdecode == _TIFFSwab32BitData )
+                    tif->tif_postdecode = _TIFFSwab16BitData;
+                else if( (td->td_sampleformat == SAMPLEFORMAT_COMPLEXINT 
+                          || td->td_sampleformat == SAMPLEFORMAT_COMPLEXIEEEFP)
+                         && td->td_bitspersample == 64
+                         && tif->tif_postdecode == _TIFFSwab64BitData )
+                    tif->tif_postdecode = _TIFFSwab32BitData;
+                else if( td->td_sampleformat == SAMPLEFORMAT_COMPLEXIEEEFP
+                         && td->td_bitspersample == 128
+                         && tif->tif_postdecode == NULL )
+                    tif->tif_postdecode = _TIFFSwab64BitData;
+    break;
+  case TIFFTAG_IMAGEDEPTH:
+    td->td_imagedepth = va_arg(ap, uint32);
+    break;
+  case TIFFTAG_STONITS:
+    d = va_arg(ap, dblparam_t);
+    if (d <= 0.)
+      goto badvaluedbl;
+    td->td_stonits = d;
+    break;
+  /* Begin Pixar Tags */
+   case TIFFTAG_PIXAR_IMAGEFULLWIDTH:
+     td->td_imagefullwidth = va_arg(ap, uint32);
+     break;
+   case TIFFTAG_PIXAR_IMAGEFULLLENGTH:
+     td->td_imagefulllength = va_arg(ap, uint32);
+     break;
+   case TIFFTAG_PIXAR_TEXTUREFORMAT:
+     _TIFFsetString(&td->td_textureformat, va_arg(ap, char*));
+     break;
+   case TIFFTAG_PIXAR_WRAPMODES:
+     _TIFFsetString(&td->td_wrapmodes, va_arg(ap, char*));
+     break;
+   case TIFFTAG_PIXAR_FOVCOT:
+     td->td_fovcot = (float) va_arg(ap, dblparam_t);
+     break;
+   case TIFFTAG_PIXAR_MATRIX_WORLDTOSCREEN:
+     _TIFFsetFloatArray(&td->td_matrixWorldToScreen,
+       va_arg(ap, float*), 16);
+     break;
+   case TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA:
+     _TIFFsetFloatArray(&td->td_matrixWorldToCamera,
+       va_arg(ap, float*), 16);
+     break;
+   /* End Pixar Tags */         
+
+  case TIFFTAG_SUBIFD:
+    if ((tif->tif_flags & TIFF_INSUBIFD) == 0) {
+      td->td_nsubifd = (uint16) va_arg(ap, int);
+      _TIFFsetLongArray(&td->td_subifd, va_arg(ap, uint32*),
+          (long) td->td_nsubifd);
+    } else {
+      TIFFError(module, "%s: Sorry, cannot nest SubIFDs",
+          tif->tif_name);
+      status = 0;
+    }
+    break;
+  case TIFFTAG_YCBCRCOEFFICIENTS:
+    _TIFFsetFloatArray(&td->td_ycbcrcoeffs, va_arg(ap, float*), 3);
+    break;
+  case TIFFTAG_YCBCRPOSITIONING:
+    td->td_ycbcrpositioning = (uint16) va_arg(ap, int);
+    break;
+  case TIFFTAG_YCBCRSUBSAMPLING:
+    td->td_ycbcrsubsampling[0] = (uint16) va_arg(ap, int);
+    td->td_ycbcrsubsampling[1] = (uint16) va_arg(ap, int);
+    break;
+  case TIFFTAG_WHITEPOINT:
+    _TIFFsetFloatArray(&td->td_whitepoint, va_arg(ap, float*), 2);
+    break;
+  case TIFFTAG_PRIMARYCHROMATICITIES:
+    _TIFFsetFloatArray(&td->td_primarychromas, va_arg(ap, float*), 6);
+    break;
+  case TIFFTAG_TRANSFERFUNCTION:
+    v = (td->td_samplesperpixel - td->td_extrasamples) > 1 ? 3 : 1;
+    for (i = 0; i < v; i++)
+      _TIFFsetShortArray(&td->td_transferfunction[i],
+          va_arg(ap, uint16*), 1L<<td->td_bitspersample);
+    break;
+  case TIFFTAG_REFERENCEBLACKWHITE:
+    /* XXX should check for null range */
+    _TIFFsetFloatArray(&td->td_refblackwhite, va_arg(ap, float*), 6);
+    break;
+  case TIFFTAG_INKSET:
+    td->td_inkset = (uint16) va_arg(ap, int);
+    break;
+  case TIFFTAG_DOTRANGE:
+    /* XXX should check for null range */
+    td->td_dotrange[0] = (uint16) va_arg(ap, int);
+    td->td_dotrange[1] = (uint16) va_arg(ap, int);
+    break;
+  case TIFFTAG_INKNAMES:
+    i = va_arg(ap, int);
+    s = va_arg(ap, char*);
+    i = checkInkNamesString(tif, i, s);
+                status = i > 0;
+    if( i > 0 ) {
+      _TIFFsetNString(&td->td_inknames, s, i);
+      td->td_inknameslen = i;
+    }
+    break;
+  case TIFFTAG_NUMBEROFINKS:
+    td->td_ninks = (uint16) va_arg(ap, int);
+    break;
+  case TIFFTAG_TARGETPRINTER:
+    _TIFFsetString(&td->td_targetprinter, va_arg(ap, char*));
+    break;
+  case TIFFTAG_ICCPROFILE:
+    td->td_profileLength = (uint32) va_arg(ap, uint32);
+    _TIFFsetByteArray(&td->td_profileData, va_arg(ap, void*),
+        td->td_profileLength);
+    break;
+   case TIFFTAG_PHOTOSHOP:
+      td->td_photoshopLength = (uint32) va_arg(ap, uint32);
+      _TIFFsetByteArray (&td->td_photoshopData, va_arg(ap, void*),
+       td->td_photoshopLength);
+     break;
+  case TIFFTAG_RICHTIFFIPTC: 
+      td->td_richtiffiptcLength = (uint32) va_arg(ap, uint32);
+      _TIFFsetLongArray ((uint32**)&td->td_richtiffiptcData,
+           va_arg(ap, uint32*),
+           td->td_richtiffiptcLength);
+     break;
+  case TIFFTAG_XMLPACKET:
+    td->td_xmlpacketLength = (uint32) va_arg(ap, uint32);
+    _TIFFsetByteArray(&td->td_xmlpacketData, va_arg(ap, void*),
+        td->td_xmlpacketLength);
+    break;
+        default: {
+            const TIFFFieldInfo* fip = _TIFFFindFieldInfo(tif, tag, TIFF_ANY);
+            TIFFTagValue *tv;
+            int tv_size, iCustom;
+
+            /*
+             * This can happen if multiple images are open with
+             * different codecs which have private tags.  The
+             * global tag information table may then have tags
+             * that are valid for one file but not the other. 
+             * If the client tries to set a tag that is not valid
+             * for the image's codec then we'll arrive here.  This
+             * happens, for example, when tiffcp is used to convert
+             * between compression schemes and codec-specific tags
+             * are blindly copied.
+             */
+            if( fip == NULL || fip->field_bit != FIELD_CUSTOM )
+            {
+    TIFFError(module,
+        "%s: Invalid %stag \"%s\" (not supported by codec)",
+        tif->tif_name, isPseudoTag(tag) ? "pseudo-" : "",
+        _TIFFFieldWithTag(tif, tag)->field_name);
+    status = 0;
+    break;
+            }
+
+            /*
+             * Find the existing entry for this custom value.
+             */
+            tv = NULL;
+            for( iCustom = 0; iCustom < td->td_customValueCount; iCustom++ )
+            {
+                if( td->td_customValues[iCustom].info == fip )
+                {
+                    tv = td->td_customValues + iCustom;
+                    if( tv->value != NULL )
+                        _TIFFfree( tv->value );
+                    break;
+                }
+            }
+
+            /*
+             * Grow the custom list if the entry was not found.
+             */
+            if( tv == NULL )
+            {
+    TIFFTagValue  *new_customValues;
+    
+    td->td_customValueCount++;
+    new_customValues = (TIFFTagValue *)
+      _TIFFrealloc(td->td_customValues,
+             sizeof(TIFFTagValue) * td->td_customValueCount);
+    if (!new_customValues) {
+      TIFFError(module,
+    "%s: Failed to allocate space for list of custom values",
+          tif->tif_name);
+      status = 0;
+      goto end;
+    }
+
+    td->td_customValues = new_customValues;
+
+                tv = td->td_customValues + (td->td_customValueCount-1);
+                tv->info = fip;
+                tv->value = NULL;
+                tv->count = 0;
+            }
+
+            /*
+             * Set custom value ... save a copy of the custom tag value.
+             */
+      switch (fip->field_type) {
+        /*
+         * XXX: We can't use TIFFDataWidth() to determine the
+         * space needed to store the value. For TIFF_RATIONAL
+         * values TIFFDataWidth() returns 8, but we use 4-byte
+         * float to represent rationals.
+         */
+        case TIFF_BYTE:
+        case TIFF_ASCII:
+        case TIFF_SBYTE:
+        case TIFF_UNDEFINED:
+      tv_size = 1;
+      break;
+
+        case TIFF_SHORT:
+        case TIFF_SSHORT:
+      tv_size = 2;
+      break;
+
+        case TIFF_LONG:
+        case TIFF_SLONG:
+        case TIFF_FLOAT:
+        case TIFF_IFD:
+        case TIFF_RATIONAL:
+        case TIFF_SRATIONAL:
+      tv_size = 4;
+      break;
+
+        case TIFF_DOUBLE:
+      tv_size = 8;
+      break;
+
+        default:
+      status = 0;
+      TIFFError(module, "%s: Bad field type %d for \"%s\"",
+          tif->tif_name, fip->field_type,
+          fip->field_name);
+      goto end;
+        
+      }
+            
+            if(fip->field_passcount)
+                tv->count = (int) va_arg(ap, int);
+            else
+                tv->count = 1;
+            
+      if (fip->field_passcount) {
+                tv->value = _TIFFmalloc(tv_size * tv->count);
+    if ( !tv->value ) {
+      status = 0;
+      goto end;
+    }
+                _TIFFmemcpy(tv->value, (void *) va_arg(ap,void*),
+                            tv->count * tv_size);
+            } else if (fip->field_type == TIFF_ASCII) {
+                const char *value = (const char *) va_arg(ap,const char *);
+                tv->count = strlen(value)+1;
+                tv->value = _TIFFmalloc(tv->count);
+    if (!tv->value) {
+      status = 0;
+      goto end;
+    }
+                strcpy(tv->value, value);
+            } else {
+                /* not supporting "pass by value" types yet */
+    TIFFError(module,
+        "%s: Pass by value is not implemented.",
+        tif->tif_name);
+
+                tv->value = _TIFFmalloc(tv_size * tv->count);
+    if (!tv->value) {
+      status = 0;
+      goto end;
+    }
+                _TIFFmemset(tv->value, 0, tv->count * tv_size);
+                status = 0;
+            }
+          }
+  }
+  if (status) {
+            TIFFSetFieldBit(tif, _TIFFFieldWithTag(tif, tag)->field_bit);
+            tif->tif_flags |= TIFF_DIRTYDIRECT;
+  }
+
+end:
+  va_end(ap);
+  return (status);
+badvalue:
+  TIFFError(module, "%s: Bad value %d for \"%s\"",
+      tif->tif_name, v, _TIFFFieldWithTag(tif, tag)->field_name);
+  va_end(ap);
+  return (0);
+badvalue32:
+  TIFFError(module, "%s: Bad value %ld for \"%s\"",
+       tif->tif_name, v32, _TIFFFieldWithTag(tif, tag)->field_name);
+  va_end(ap);
+  return (0);
+badvaluedbl:
+  TIFFError(module, "%s: Bad value %f for \"%s\"",
+      tif->tif_name, d, _TIFFFieldWithTag(tif, tag)->field_name);
+  va_end(ap);
+  return (0);
+}
+
+/*
+ * Return 1/0 according to whether or not
+ * it is permissible to set the tag's value.
+ * Note that we allow ImageLength to be changed
+ * so that we can append and extend to images.
+ * Any other tag may not be altered once writing
+ * has commenced, unless its value has no effect
+ * on the format of the data that is written.
+ */
+static int
+OkToChangeTag(TIFF* tif, ttag_t tag)
+{
+  const TIFFFieldInfo* fip = _TIFFFindFieldInfo(tif, tag, TIFF_ANY);
+  if (!fip) {      /* unknown tag */
+    TIFFError("TIFFSetField", "%s: Unknown %stag %u",
+        tif->tif_name, isPseudoTag(tag) ? "pseudo-" : "", tag);
+    return (0);
+  }
+  if (tag != TIFFTAG_IMAGELENGTH && (tif->tif_flags & TIFF_BEENWRITING) &&
+      !fip->field_oktochange) {
+    /*
+     * Consult info table to see if tag can be changed
+     * after we've started writing.  We only allow changes
+     * to those tags that don't/shouldn't affect the
+     * compression and/or format of the data.
+     */
+    TIFFError("TIFFSetField",
+        "%s: Cannot modify tag \"%s\" while writing",
+        tif->tif_name, fip->field_name);
+    return (0);
+  }
+  return (1);
+}
+
+/*
+ * Record the value of a field in the
+ * internal directory structure.  The
+ * field will be written to the file
+ * when/if the directory structure is
+ * updated.
+ */
+int
+TIFFSetField(TIFF* tif, ttag_t tag, ...)
+{
+  va_list ap;
+  int status;
+
+  va_start(ap, tag);
+  status = TIFFVSetField(tif, tag, ap);
+  va_end(ap);
+  return (status);
+}
+
+/*
+ * Like TIFFSetField, but taking a varargs
+ * parameter list.  This routine is useful
+ * for building higher-level interfaces on
+ * top of the library.
+ */
+int
+TIFFVSetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+  return OkToChangeTag(tif, tag) ?
+      (*tif->tif_tagmethods.vsetfield)(tif, tag, ap) : 0;
+}
+
+static int
+_TIFFVGetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+    TIFFDirectory* td = &tif->tif_dir;
+    int            ret_val = 1;
+
+    switch (tag) {
+  case TIFFTAG_SUBFILETYPE:
+            *va_arg(ap, uint32*) = td->td_subfiletype;
+            break;
+  case TIFFTAG_IMAGEWIDTH:
+            *va_arg(ap, uint32*) = td->td_imagewidth;
+            break;
+  case TIFFTAG_IMAGELENGTH:
+            *va_arg(ap, uint32*) = td->td_imagelength;
+            break;
+  case TIFFTAG_BITSPERSAMPLE:
+            *va_arg(ap, uint16*) = td->td_bitspersample;
+            break;
+  case TIFFTAG_COMPRESSION:
+            *va_arg(ap, uint16*) = td->td_compression;
+            break;
+  case TIFFTAG_PHOTOMETRIC:
+            *va_arg(ap, uint16*) = td->td_photometric;
+            break;
+  case TIFFTAG_THRESHHOLDING:
+            *va_arg(ap, uint16*) = td->td_threshholding;
+            break;
+  case TIFFTAG_FILLORDER:
+            *va_arg(ap, uint16*) = td->td_fillorder;
+            break;
+  case TIFFTAG_DOCUMENTNAME:
+            *va_arg(ap, char**) = td->td_documentname;
+            break;
+  case TIFFTAG_ARTIST:
+            *va_arg(ap, char**) = td->td_artist;
+            break;
+  case TIFFTAG_DATETIME:
+            *va_arg(ap, char**) = td->td_datetime;
+            break;
+  case TIFFTAG_HOSTCOMPUTER:
+            *va_arg(ap, char**) = td->td_hostcomputer;
+            break;
+  case TIFFTAG_IMAGEDESCRIPTION:
+            *va_arg(ap, char**) = td->td_imagedescription;
+            break;
+  case TIFFTAG_MAKE:
+            *va_arg(ap, char**) = td->td_make;
+            break;
+  case TIFFTAG_MODEL:
+            *va_arg(ap, char**) = td->td_model;
+            break;
+  case TIFFTAG_COPYRIGHT:
+            *va_arg(ap, char**) = td->td_copyright;
+            break;
+  case TIFFTAG_ORIENTATION:
+            *va_arg(ap, uint16*) = td->td_orientation;
+            break;
+  case TIFFTAG_SAMPLESPERPIXEL:
+            *va_arg(ap, uint16*) = td->td_samplesperpixel;
+            break;
+  case TIFFTAG_ROWSPERSTRIP:
+            *va_arg(ap, uint32*) = td->td_rowsperstrip;
+            break;
+  case TIFFTAG_MINSAMPLEVALUE:
+            *va_arg(ap, uint16*) = td->td_minsamplevalue;
+            break;
+  case TIFFTAG_MAXSAMPLEVALUE:
+            *va_arg(ap, uint16*) = td->td_maxsamplevalue;
+            break;
+  case TIFFTAG_SMINSAMPLEVALUE:
+            *va_arg(ap, double*) = td->td_sminsamplevalue;
+            break;
+  case TIFFTAG_SMAXSAMPLEVALUE:
+            *va_arg(ap, double*) = td->td_smaxsamplevalue;
+            break;
+  case TIFFTAG_XRESOLUTION:
+            *va_arg(ap, float*) = td->td_xresolution;
+            break;
+  case TIFFTAG_YRESOLUTION:
+            *va_arg(ap, float*) = td->td_yresolution;
+            break;
+  case TIFFTAG_PLANARCONFIG:
+            *va_arg(ap, uint16*) = td->td_planarconfig;
+            break;
+  case TIFFTAG_XPOSITION:
+            *va_arg(ap, float*) = td->td_xposition;
+            break;
+  case TIFFTAG_YPOSITION:
+            *va_arg(ap, float*) = td->td_yposition;
+            break;
+  case TIFFTAG_PAGENAME:
+            *va_arg(ap, char**) = td->td_pagename;
+            break;
+  case TIFFTAG_RESOLUTIONUNIT:
+            *va_arg(ap, uint16*) = td->td_resolutionunit;
+            break;
+  case TIFFTAG_PAGENUMBER:
+            *va_arg(ap, uint16*) = td->td_pagenumber[0];
+            *va_arg(ap, uint16*) = td->td_pagenumber[1];
+            break;
+  case TIFFTAG_HALFTONEHINTS:
+            *va_arg(ap, uint16*) = td->td_halftonehints[0];
+            *va_arg(ap, uint16*) = td->td_halftonehints[1];
+            break;
+  case TIFFTAG_COLORMAP:
+            *va_arg(ap, uint16**) = td->td_colormap[0];
+            *va_arg(ap, uint16**) = td->td_colormap[1];
+            *va_arg(ap, uint16**) = td->td_colormap[2];
+            break;
+  case TIFFTAG_STRIPOFFSETS:
+  case TIFFTAG_TILEOFFSETS:
+            *va_arg(ap, uint32**) = td->td_stripoffset;
+            break;
+  case TIFFTAG_STRIPBYTECOUNTS:
+  case TIFFTAG_TILEBYTECOUNTS:
+            *va_arg(ap, uint32**) = td->td_stripbytecount;
+            break;
+  case TIFFTAG_MATTEING:
+            *va_arg(ap, uint16*) =
+                (td->td_extrasamples == 1 &&
+                 td->td_sampleinfo[0] == EXTRASAMPLE_ASSOCALPHA);
+            break;
+  case TIFFTAG_EXTRASAMPLES:
+            *va_arg(ap, uint16*) = td->td_extrasamples;
+            *va_arg(ap, uint16**) = td->td_sampleinfo;
+            break;
+  case TIFFTAG_TILEWIDTH:
+            *va_arg(ap, uint32*) = td->td_tilewidth;
+            break;
+  case TIFFTAG_TILELENGTH:
+            *va_arg(ap, uint32*) = td->td_tilelength;
+            break;
+  case TIFFTAG_TILEDEPTH:
+            *va_arg(ap, uint32*) = td->td_tiledepth;
+            break;
+  case TIFFTAG_DATATYPE:
+            switch (td->td_sampleformat) {
+    case SAMPLEFORMAT_UINT:
+                    *va_arg(ap, uint16*) = DATATYPE_UINT;
+                    break;
+    case SAMPLEFORMAT_INT:
+                    *va_arg(ap, uint16*) = DATATYPE_INT;
+                    break;
+    case SAMPLEFORMAT_IEEEFP:
+                    *va_arg(ap, uint16*) = DATATYPE_IEEEFP;
+                    break;
+    case SAMPLEFORMAT_VOID:
+                    *va_arg(ap, uint16*) = DATATYPE_VOID;
+                    break;
+            }
+            break;
+  case TIFFTAG_SAMPLEFORMAT:
+            *va_arg(ap, uint16*) = td->td_sampleformat;
+            break;
+  case TIFFTAG_IMAGEDEPTH:
+            *va_arg(ap, uint32*) = td->td_imagedepth;
+            break;
+  case TIFFTAG_STONITS:
+            *va_arg(ap, double*) = td->td_stonits;
+            break;
+  case TIFFTAG_SUBIFD:
+            *va_arg(ap, uint16*) = td->td_nsubifd;
+            *va_arg(ap, uint32**) = td->td_subifd;
+            break;
+  case TIFFTAG_YCBCRCOEFFICIENTS:
+            *va_arg(ap, float**) = td->td_ycbcrcoeffs;
+            break;
+  case TIFFTAG_YCBCRPOSITIONING:
+            *va_arg(ap, uint16*) = td->td_ycbcrpositioning;
+            break;
+  case TIFFTAG_YCBCRSUBSAMPLING:
+            *va_arg(ap, uint16*) = td->td_ycbcrsubsampling[0];
+            *va_arg(ap, uint16*) = td->td_ycbcrsubsampling[1];
+            break;
+  case TIFFTAG_WHITEPOINT:
+            *va_arg(ap, float**) = td->td_whitepoint;
+            break;
+  case TIFFTAG_PRIMARYCHROMATICITIES:
+            *va_arg(ap, float**) = td->td_primarychromas;
+            break;
+  case TIFFTAG_TRANSFERFUNCTION:
+            *va_arg(ap, uint16**) = td->td_transferfunction[0];
+            if (td->td_samplesperpixel - td->td_extrasamples > 1) {
+                *va_arg(ap, uint16**) = td->td_transferfunction[1];
+                *va_arg(ap, uint16**) = td->td_transferfunction[2];
+            }
+            break;
+  case TIFFTAG_REFERENCEBLACKWHITE:
+            *va_arg(ap, float**) = td->td_refblackwhite;
+            break;
+  case TIFFTAG_INKSET:
+            *va_arg(ap, uint16*) = td->td_inkset;
+            break;
+  case TIFFTAG_DOTRANGE:
+            *va_arg(ap, uint16*) = td->td_dotrange[0];
+            *va_arg(ap, uint16*) = td->td_dotrange[1];
+            break;
+  case TIFFTAG_INKNAMES:
+            *va_arg(ap, char**) = td->td_inknames;
+            break;
+  case TIFFTAG_NUMBEROFINKS:
+            *va_arg(ap, uint16*) = td->td_ninks;
+            break;
+  case TIFFTAG_TARGETPRINTER:
+            *va_arg(ap, char**) = td->td_targetprinter;
+            break;
+  case TIFFTAG_ICCPROFILE:
+            *va_arg(ap, uint32*) = td->td_profileLength;
+            *va_arg(ap, void**) = td->td_profileData;
+            break;
+   case TIFFTAG_PHOTOSHOP:
+            *va_arg(ap, uint32*) = td->td_photoshopLength;
+            *va_arg(ap, void**) = td->td_photoshopData;
+            break;
+   case TIFFTAG_RICHTIFFIPTC:
+            *va_arg(ap, uint32*) = td->td_richtiffiptcLength;
+            *va_arg(ap, void**) = td->td_richtiffiptcData;
+            break;
+  case TIFFTAG_XMLPACKET:
+            *va_arg(ap, uint32*) = td->td_xmlpacketLength;
+            *va_arg(ap, void**) = td->td_xmlpacketData;
+            break;
+            /* Begin Pixar Tags */
+   case TIFFTAG_PIXAR_IMAGEFULLWIDTH:
+            *va_arg(ap, uint32*) = td->td_imagefullwidth;
+            break;
+   case TIFFTAG_PIXAR_IMAGEFULLLENGTH:
+            *va_arg(ap, uint32*) = td->td_imagefulllength;
+            break;
+   case TIFFTAG_PIXAR_TEXTUREFORMAT:
+            *va_arg(ap, char**) = td->td_textureformat;
+            break;
+   case TIFFTAG_PIXAR_WRAPMODES:
+            *va_arg(ap, char**) = td->td_wrapmodes;
+            break;
+   case TIFFTAG_PIXAR_FOVCOT:
+            *va_arg(ap, float*) = td->td_fovcot;
+            break;
+   case TIFFTAG_PIXAR_MATRIX_WORLDTOSCREEN:
+            *va_arg(ap, float**) = td->td_matrixWorldToScreen;
+            break;
+   case TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA:
+            *va_arg(ap, float**) = td->td_matrixWorldToCamera;
+            break;
+            /* End Pixar Tags */
+
+        default:
+        {
+            const TIFFFieldInfo* fip = _TIFFFindFieldInfo(tif, tag, TIFF_ANY);
+            int           i;
+            
+            /*
+             * This can happen if multiple images are open with
+             * different codecs which have private tags.  The
+             * global tag information table may then have tags
+             * that are valid for one file but not the other. 
+             * If the client tries to get a tag that is not valid
+             * for the image's codec then we'll arrive here.
+             */
+            if( fip == NULL || fip->field_bit != FIELD_CUSTOM )
+            {
+                TIFFError("_TIFFVGetField",
+                          "%s: Invalid %stag \"%s\" (not supported by codec)",
+                          tif->tif_name, isPseudoTag(tag) ? "pseudo-" : "",
+                          _TIFFFieldWithTag(tif, tag)->field_name);
+                ret_val = 0;
+                break;
+            }
+
+            /*
+            ** Do we have a custom value?
+            */
+            ret_val = 0;
+            for (i = 0; i < td->td_customValueCount; i++)
+            {
+    TIFFTagValue *tv = td->td_customValues + i;
+
+    if (tv->info->field_tag != tag)
+      continue;
+                
+    if (fip->field_passcount) {
+      if (fip->field_readcount == TIFF_VARIABLE2) 
+        *va_arg(ap, uint32*) = (uint32)tv->count;
+      else  /* Assume TIFF_VARIABLE */
+        *va_arg(ap, uint16*) = (uint16)tv->count;
+      *va_arg(ap, void **) = tv->value;
+      ret_val = 1;
+      break;
+                } else if (fip->field_type == TIFF_ASCII) {
+      *va_arg(ap, void **) = tv->value;
+      ret_val = 1;
+      break;
+                } else {
+      TIFFError("_TIFFVGetField",
+          "%s: Pass by value is not implemented.",
+          tif->tif_name);
+      break;
+                }
+            }
+        }
+    }
+    return(ret_val);
+}
+
+/*
+ * Return the value of a field in the
+ * internal directory structure.
+ */
+int
+TIFFGetField(TIFF* tif, ttag_t tag, ...)
+{
+  int status;
+  va_list ap;
+
+  va_start(ap, tag);
+  status = TIFFVGetField(tif, tag, ap);
+  va_end(ap);
+  return (status);
+}
+
+/*
+ * Like TIFFGetField, but taking a varargs
+ * parameter list.  This routine is useful
+ * for building higher-level interfaces on
+ * top of the library.
+ */
+int
+TIFFVGetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+  const TIFFFieldInfo* fip = _TIFFFindFieldInfo(tif, tag, TIFF_ANY);
+  return (fip && (isPseudoTag(tag) || TIFFFieldSet(tif, fip->field_bit)) ?
+      (*tif->tif_tagmethods.vgetfield)(tif, tag, ap) : 0);
+}
+
+#define  CleanupField(member) {    \
+    if (td->member) {      \
+  _TIFFfree(td->member);    \
+  td->member = 0;      \
+    }          \
+}
+
+/*
+ * Release storage associated with a directory.
+ */
+void
+TIFFFreeDirectory(TIFF* tif)
+{
+  TIFFDirectory *td = &tif->tif_dir;
+  int            i;
+
+  CleanupField(td_colormap[0]);
+  CleanupField(td_colormap[1]);
+  CleanupField(td_colormap[2]);
+  CleanupField(td_documentname);
+  CleanupField(td_artist);
+  CleanupField(td_datetime);
+  CleanupField(td_hostcomputer);
+  CleanupField(td_imagedescription);
+  CleanupField(td_make);
+  CleanupField(td_model);
+  CleanupField(td_copyright);
+  CleanupField(td_pagename);
+  CleanupField(td_sampleinfo);
+  CleanupField(td_subifd);
+  CleanupField(td_ycbcrcoeffs);
+  CleanupField(td_inknames);
+  CleanupField(td_targetprinter);
+  CleanupField(td_whitepoint);
+  CleanupField(td_primarychromas);
+  CleanupField(td_refblackwhite);
+  CleanupField(td_transferfunction[0]);
+  CleanupField(td_transferfunction[1]);
+  CleanupField(td_transferfunction[2]);
+  CleanupField(td_profileData);
+  CleanupField(td_photoshopData);
+  CleanupField(td_richtiffiptcData);
+  CleanupField(td_xmlpacketData);
+  CleanupField(td_stripoffset);
+  CleanupField(td_stripbytecount);
+  /* Begin Pixar Tags */
+  CleanupField(td_textureformat);
+  CleanupField(td_wrapmodes);
+  CleanupField(td_matrixWorldToScreen);
+  CleanupField(td_matrixWorldToCamera);
+  /* End Pixar Tags */
+
+  /* Cleanup custom tag values */
+  for( i = 0; i < td->td_customValueCount; i++ ) {
+    if (td->td_customValues[i].value)
+      _TIFFfree(td->td_customValues[i].value);
+  }
+
+  td->td_customValueCount = 0;
+  CleanupField(td_customValues);
+}
+#undef CleanupField
+
+/*
+ * Client Tag extension support (from Niles Ritter).
+ */
+static TIFFExtendProc _TIFFextender = (TIFFExtendProc) NULL;
+
+TIFFExtendProc
+TIFFSetTagExtender(TIFFExtendProc extender)
+{
+  TIFFExtendProc prev = _TIFFextender;
+  _TIFFextender = extender;
+  return (prev);
+}
+
+/*
+ * Setup for a new directory.  Should we automatically call
+ * TIFFWriteDirectory() if the current one is dirty?
+ *
+ * The newly created directory will not exist on the file till
+ * TIFFWriteDirectory(), TIFFFlush() or TIFFClose() is called.
+ */
+int
+TIFFCreateDirectory(TIFF* tif)
+{
+    TIFFDefaultDirectory(tif);
+    tif->tif_diroff = 0;
+    tif->tif_nextdiroff = 0;
+    tif->tif_curoff = 0;
+    tif->tif_row = (uint32) -1;
+    tif->tif_curstrip = (tstrip_t) -1;
+
+    return 0;
+}
+
+/*
+ * Setup a default directory structure.
+ */
+int
+TIFFDefaultDirectory(TIFF* tif)
+{
+  register TIFFDirectory* td = &tif->tif_dir;
+
+  _TIFFSetupFieldInfo(tif);
+  _TIFFmemset(td, 0, sizeof (*td));
+  td->td_fillorder = FILLORDER_MSB2LSB;
+  td->td_bitspersample = 1;
+  td->td_threshholding = THRESHHOLD_BILEVEL;
+  td->td_orientation = ORIENTATION_TOPLEFT;
+  td->td_samplesperpixel = 1;
+  td->td_rowsperstrip = (uint32) -1;
+  td->td_tilewidth = 0;
+  td->td_tilelength = 0;
+  td->td_tiledepth = 1;
+  td->td_stripbytecountsorted = 1; /* Our own arrays always sorted. */
+  td->td_resolutionunit = RESUNIT_INCH;
+  td->td_sampleformat = SAMPLEFORMAT_UINT;
+  td->td_imagedepth = 1;
+  td->td_ycbcrsubsampling[0] = 2;
+  td->td_ycbcrsubsampling[1] = 2;
+  td->td_ycbcrpositioning = YCBCRPOSITION_CENTERED;
+  td->td_inkset = INKSET_CMYK;
+  td->td_ninks = 4;
+  tif->tif_postdecode = _TIFFNoPostDecode;
+        tif->tif_foundfield = NULL;
+  tif->tif_tagmethods.vsetfield = _TIFFVSetField;
+  tif->tif_tagmethods.vgetfield = _TIFFVGetField;
+  tif->tif_tagmethods.printdir = NULL;
+  /*
+   *  Give client code a chance to install their own
+   *  tag extensions & methods, prior to compression overloads.
+   */
+  if (_TIFFextender)
+    (*_TIFFextender)(tif);
+  (void) TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
+  /*
+   * NB: The directory is marked dirty as a result of setting
+   * up the default compression scheme.  However, this really
+   * isn't correct -- we want TIFF_DIRTYDIRECT to be set only
+   * if the user does something.  We could just do the setup
+   * by hand, but it seems better to use the normal mechanism
+   * (i.e. TIFFSetField).
+   */
+  tif->tif_flags &= ~TIFF_DIRTYDIRECT;
+
+        /*
+         * As per http://bugzilla.remotesensing.org/show_bug.cgi?id=19
+         * we clear the ISTILED flag when setting up a new directory.
+         * Should we also be clearing stuff like INSUBIFD?
+         */
+        tif->tif_flags &= ~TIFF_ISTILED;
+
+  return (1);
+}
+
+static int
+TIFFAdvanceDirectory(TIFF* tif, uint32* nextdir, toff_t* off)
+{
+    static const char module[] = "TIFFAdvanceDirectory";
+    uint16 dircount;
+    if (isMapped(tif))
+    {
+        toff_t poff=*nextdir;
+        if (poff+sizeof(uint16) > tif->tif_size)
+        {
+            TIFFError(module, "%s: Error fetching directory count",
+                      tif->tif_name);
+            return (0);
+        }
+        _TIFFmemcpy(&dircount, tif->tif_base+poff, sizeof (uint16));
+        if (tif->tif_flags & TIFF_SWAB)
+            TIFFSwabShort(&dircount);
+        poff+=sizeof (uint16)+dircount*sizeof (TIFFDirEntry);
+        if (off != NULL)
+            *off = poff;
+        if (((toff_t) (poff+sizeof (uint32))) > tif->tif_size)
+        {
+            TIFFError(module, "%s: Error fetching directory link",
+                      tif->tif_name);
+            return (0);
+        }
+        _TIFFmemcpy(nextdir, tif->tif_base+poff, sizeof (uint32));
+        if (tif->tif_flags & TIFF_SWAB)
+            TIFFSwabLong(nextdir);
+        return (1);
+    }
+    else
+    {
+        if (!SeekOK(tif, *nextdir) ||
+            !ReadOK(tif, &dircount, sizeof (uint16))) {
+            TIFFError(module, "%s: Error fetching directory count",
+                      tif->tif_name);
+            return (0);
+        }
+        if (tif->tif_flags & TIFF_SWAB)
+            TIFFSwabShort(&dircount);
+        if (off != NULL)
+            *off = TIFFSeekFile(tif,
+                                dircount*sizeof (TIFFDirEntry), SEEK_CUR);
+        else
+            (void) TIFFSeekFile(tif,
+                                dircount*sizeof (TIFFDirEntry), SEEK_CUR);
+        if (!ReadOK(tif, nextdir, sizeof (uint32))) {
+            TIFFError(module, "%s: Error fetching directory link",
+                      tif->tif_name);
+            return (0);
+        }
+        if (tif->tif_flags & TIFF_SWAB)
+            TIFFSwabLong(nextdir);
+        return (1);
+    }
+}
+
+/*
+ * Count the number of directories in a file.
+ */
+tdir_t
+TIFFNumberOfDirectories(TIFF* tif)
+{
+    toff_t nextdir = tif->tif_header.tiff_diroff;
+    tdir_t n = 0;
+    
+    while (nextdir != 0 && TIFFAdvanceDirectory(tif, &nextdir, NULL))
+        n++;
+    return (n);
+}
+
+/*
+ * Set the n-th directory as the current directory.
+ * NB: Directories are numbered starting at 0.
+ */
+int
+TIFFSetDirectory(TIFF* tif, tdir_t dirn)
+{
+  toff_t nextdir;
+  tdir_t n;
+
+  nextdir = tif->tif_header.tiff_diroff;
+  for (n = dirn; n > 0 && nextdir != 0; n--)
+    if (!TIFFAdvanceDirectory(tif, &nextdir, NULL))
+      return (0);
+  tif->tif_nextdiroff = nextdir;
+  /*
+   * Set curdir to the actual directory index.  The
+   * -1 is because TIFFReadDirectory will increment
+   * tif_curdir after successfully reading the directory.
+   */
+  tif->tif_curdir = (dirn - n) - 1;
+  /*
+   * Reset tif_dirnumber counter and start new list of seen directories.
+   * We need this to prevent IFD loops.
+   */
+  tif->tif_dirnumber = 0;
+  return (TIFFReadDirectory(tif));
+}
+
+/*
+ * Set the current directory to be the directory
+ * located at the specified file offset.  This interface
+ * is used mainly to access directories linked with
+ * the SubIFD tag (e.g. thumbnail images).
+ */
+int
+TIFFSetSubDirectory(TIFF* tif, uint32 diroff)
+{
+  tif->tif_nextdiroff = diroff;
+  /*
+   * Reset tif_dirnumber counter and start new list of seen directories.
+   * We need this to prevent IFD loops.
+   */
+  tif->tif_dirnumber = 0;
+  return (TIFFReadDirectory(tif));
+}
+
+/*
+ * Return file offset of the current directory.
+ */
+uint32
+TIFFCurrentDirOffset(TIFF* tif)
+{
+  return (tif->tif_diroff);
+}
+
+/*
+ * Return an indication of whether or not we are
+ * at the last directory in the file.
+ */
+int
+TIFFLastDirectory(TIFF* tif)
+{
+  return (tif->tif_nextdiroff == 0);
+}
+
+/*
+ * Unlink the specified directory from the directory chain.
+ */
+int
+TIFFUnlinkDirectory(TIFF* tif, tdir_t dirn)
+{
+  static const char module[] = "TIFFUnlinkDirectory";
+  toff_t nextdir;
+  toff_t off;
+  tdir_t n;
+
+  if (tif->tif_mode == O_RDONLY) {
+    TIFFError(module, "Can not unlink directory in read-only file");
+    return (0);
+  }
+  /*
+   * Go to the directory before the one we want
+   * to unlink and nab the offset of the link
+   * field we'll need to patch.
+   */
+  nextdir = tif->tif_header.tiff_diroff;
+  off = sizeof (uint16) + sizeof (uint16);
+  for (n = dirn-1; n > 0; n--) {
+    if (nextdir == 0) {
+      TIFFError(module, "Directory %d does not exist", dirn);
+      return (0);
+    }
+    if (!TIFFAdvanceDirectory(tif, &nextdir, &off))
+      return (0);
+  }
+  /*
+   * Advance to the directory to be unlinked and fetch
+   * the offset of the directory that follows.
+   */
+  if (!TIFFAdvanceDirectory(tif, &nextdir, NULL))
+    return (0);
+  /*
+   * Go back and patch the link field of the preceding
+   * directory to point to the offset of the directory
+   * that follows.
+   */
+  (void) TIFFSeekFile(tif, off, SEEK_SET);
+  if (tif->tif_flags & TIFF_SWAB)
+    TIFFSwabLong(&nextdir);
+  if (!WriteOK(tif, &nextdir, sizeof (uint32))) {
+    TIFFError(module, "Error writing directory link");
+    return (0);
+  }
+  /*
+   * Leave directory state setup safely.  We don't have
+   * facilities for doing inserting and removing directories,
+   * so it's safest to just invalidate everything.  This
+   * means that the caller can only append to the directory
+   * chain.
+   */
+  (*tif->tif_cleanup)(tif);
+  if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) {
+    _TIFFfree(tif->tif_rawdata);
+    tif->tif_rawdata = NULL;
+    tif->tif_rawcc = 0;
+  }
+  tif->tif_flags &= ~(TIFF_BEENWRITING|TIFF_BUFFERSETUP|TIFF_POSTENCODE);
+  TIFFFreeDirectory(tif);
+  TIFFDefaultDirectory(tif);
+  tif->tif_diroff = 0;      /* force link on next write */
+  tif->tif_nextdiroff = 0;    /* next write must be at end */
+  tif->tif_curoff = 0;
+  tif->tif_row = (uint32) -1;
+  tif->tif_curstrip = (tstrip_t) -1;
+  return (1);
+}
+
+/*      [BFC]
+ *
+ * Author: Bruce Cameron <cameron@petris.com>
+ *
+ * Set a table of tags that are to be replaced during directory process by the
+ * 'IGNORE' state - or return TRUE/FALSE for the requested tag such that
+ * 'ReadDirectory' can use the stored information.
+ *
+ * FIXME: this is never used properly. Should be removed in the future.
+ */
+int
+TIFFReassignTagToIgnore (enum TIFFIgnoreSense task, int TIFFtagID)
+{
+    static int TIFFignoretags [FIELD_LAST];
+    static int tagcount = 0 ;
+    int    i;          /* Loop index */
+    int    j;          /* Loop index */
+
+    switch (task)
+    {
+      case TIS_STORE:
+        if ( tagcount < (FIELD_LAST - 1) )
+        {
+            for ( j = 0 ; j < tagcount ; ++j )
+            {          /* Do not add duplicate tag */
+                if ( TIFFignoretags [j] == TIFFtagID )
+                    return (TRUE) ;
+            }
+            TIFFignoretags [tagcount++] = TIFFtagID ;
+            return (TRUE) ;
+        }
+        break ;
+        
+      case TIS_EXTRACT:
+        for ( i = 0 ; i < tagcount ; ++i )
+        {
+            if ( TIFFignoretags [i] == TIFFtagID )
+                return (TRUE) ;
+        }
+        break;
+        
+      case TIS_EMPTY:
+        tagcount = 0 ;      /* Clear the list */
+        return (TRUE) ;
+        
+      default:
+        break;
+    }
+    
+    return (FALSE);
+}
+
diff --git a/Utilities/ITK/Utilities/tiff/tif_dir.h b/Utilities/ITK/Utilities/tiff/tif_dir.h
new file mode 100644
index 0000000000..67d50b551e
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_dir.h
@@ -0,0 +1,265 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _TIFFDIR_
+#define  _TIFFDIR_
+/*
+ * ``Library-private'' Directory-related Definitions.
+ */
+
+/*
+ * Internal format of a TIFF directory entry.
+ */
+typedef  struct {
+#define  FIELD_SETLONGS  4
+  /* bit vector of fields that are set */
+  unsigned long  td_fieldsset[FIELD_SETLONGS];
+
+  uint32  td_imagewidth, td_imagelength, td_imagedepth;
+  uint32  td_tilewidth, td_tilelength, td_tiledepth;
+  uint32  td_subfiletype;
+  uint16  td_bitspersample;
+  uint16  td_sampleformat;
+  uint16  td_compression;
+  uint16  td_photometric;
+  uint16  td_threshholding;
+  uint16  td_fillorder;
+  uint16  td_orientation;
+  uint16  td_samplesperpixel;
+  uint32  td_rowsperstrip;
+  uint16  td_minsamplevalue, td_maxsamplevalue;
+  double  td_sminsamplevalue, td_smaxsamplevalue;
+  float  td_xresolution, td_yresolution;
+  uint16  td_resolutionunit;
+  uint16  td_planarconfig;
+  float  td_xposition, td_yposition;
+  uint16  td_pagenumber[2];
+  uint16*  td_colormap[3];
+  uint16  td_halftonehints[2];
+  uint16  td_extrasamples;
+  uint16*  td_sampleinfo;
+  double  td_stonits;
+  char*  td_documentname;
+  char*  td_artist;
+  char*  td_datetime;
+  char*  td_hostcomputer;
+  char*  td_imagedescription;
+  char*  td_make;
+  char*  td_model;
+        char*   td_copyright;
+  char*  td_pagename;
+  tstrip_t td_stripsperimage;
+  tstrip_t td_nstrips;    /* size of offset & bytecount arrays */
+  uint32*  td_stripoffset;
+  uint32*  td_stripbytecount;
+  int  td_stripbytecountsorted; /* is the bytecount array sorted ascending? */
+  uint16  td_nsubifd;
+  uint32*  td_subifd;
+  /* YCbCr parameters */
+  float*  td_ycbcrcoeffs;
+  uint16  td_ycbcrsubsampling[2];
+  uint16  td_ycbcrpositioning;
+  /* Colorimetry parameters */
+  float*  td_whitepoint;
+  float*  td_primarychromas;
+  float*  td_refblackwhite;
+  uint16*  td_transferfunction[3];
+  /* CMYK parameters */
+  uint16  td_inkset;
+  uint16  td_ninks;
+  uint16  td_dotrange[2];
+  int  td_inknameslen;
+  char*  td_inknames;
+  char*  td_targetprinter;
+  /* ICC parameters */
+  uint32  td_profileLength;
+  void  *td_profileData;
+  /* Adobe Photoshop tag handling */
+  uint32  td_photoshopLength;
+  void  *td_photoshopData;
+  /* IPTC parameters */
+  uint32  td_richtiffiptcLength;
+  void  *td_richtiffiptcData;
+        /* Begin Pixar Tag values. */
+        uint32  td_imagefullwidth, td_imagefulllength;
+   char*  td_textureformat;
+   char*  td_wrapmodes;
+   float  td_fovcot;
+   float*  td_matrixWorldToScreen;
+   float*  td_matrixWorldToCamera;
+   /* End Pixar Tag Values. */
+  uint32  td_xmlpacketLength;
+  void  *td_xmlpacketData;
+  int     td_customValueCount;
+        TIFFTagValue *td_customValues;
+} TIFFDirectory;
+
+/*
+ * Field flags used to indicate fields that have
+ * been set in a directory, and to reference fields
+ * when manipulating a directory.
+ */
+
+/*
+ * FIELD_IGNORE is used to signify tags that are to
+ * be processed but otherwise ignored.  This permits
+ * antiquated tags to be quietly read and discarded.
+ * Note that a bit *is* allocated for ignored tags;
+ * this is understood by the directory reading logic
+ * which uses this fact to avoid special-case handling
+ */ 
+#define  FIELD_IGNORE      0
+
+/* multi-item fields */
+#define  FIELD_IMAGEDIMENSIONS    1
+#define FIELD_TILEDIMENSIONS    2
+#define  FIELD_RESOLUTION    3
+#define  FIELD_POSITION      4
+
+/* single-item fields */
+#define  FIELD_SUBFILETYPE    5
+#define  FIELD_BITSPERSAMPLE    6
+#define  FIELD_COMPRESSION    7
+#define  FIELD_PHOTOMETRIC    8
+#define  FIELD_THRESHHOLDING    9
+#define  FIELD_FILLORDER      10
+#define  FIELD_DOCUMENTNAME    11
+#define  FIELD_IMAGEDESCRIPTION    12
+#define  FIELD_MAKE      13
+#define  FIELD_MODEL      14
+#define  FIELD_ORIENTATION    15
+#define  FIELD_SAMPLESPERPIXEL    16
+#define  FIELD_ROWSPERSTRIP    17
+#define  FIELD_MINSAMPLEVALUE    18
+#define  FIELD_MAXSAMPLEVALUE    19
+#define  FIELD_PLANARCONFIG    20
+#define  FIELD_PAGENAME      21
+#define  FIELD_RESOLUTIONUNIT    22
+#define  FIELD_PAGENUMBER    23
+#define  FIELD_STRIPBYTECOUNTS    24
+#define  FIELD_STRIPOFFSETS    25
+#define  FIELD_COLORMAP      26
+#define FIELD_ARTIST      27
+#define FIELD_DATETIME      28
+#define FIELD_HOSTCOMPUTER    29
+/* unused - was FIELD_SOFTWARE          30 */
+#define  FIELD_EXTRASAMPLES    31
+#define FIELD_SAMPLEFORMAT    32
+#define  FIELD_SMINSAMPLEVALUE    33
+#define  FIELD_SMAXSAMPLEVALUE    34
+#define FIELD_IMAGEDEPTH    35
+#define FIELD_TILEDEPTH      36
+#define  FIELD_HALFTONEHINTS    37
+#define FIELD_YCBCRCOEFFICIENTS    38
+#define FIELD_YCBCRSUBSAMPLING    39
+#define FIELD_YCBCRPOSITIONING    40
+#define  FIELD_REFBLACKWHITE    41
+#define  FIELD_WHITEPOINT    42
+#define  FIELD_PRIMARYCHROMAS    43
+#define  FIELD_TRANSFERFUNCTION    44
+#define  FIELD_INKSET      45
+#define  FIELD_INKNAMES      46
+#define  FIELD_DOTRANGE      47
+#define  FIELD_TARGETPRINTER    48
+#define  FIELD_SUBIFD      49
+#define  FIELD_NUMBEROFINKS    50
+#define FIELD_ICCPROFILE    51
+#define FIELD_PHOTOSHOP      52
+#define FIELD_RICHTIFFIPTC    53
+#define FIELD_STONITS      54
+/* Begin PIXAR */
+#define  FIELD_IMAGEFULLWIDTH    55
+#define  FIELD_IMAGEFULLLENGTH    56
+#define FIELD_TEXTUREFORMAT    57
+#define FIELD_WRAPMODES      58
+#define FIELD_FOVCOT      59
+#define FIELD_MATRIX_WORLDTOSCREEN  60
+#define FIELD_MATRIX_WORLDTOCAMERA  61
+#define FIELD_COPYRIGHT      62
+#define FIELD_XMLPACKET      63
+/*      FIELD_CUSTOM (see tiffio.h)     65 */
+/* end of support for well-known tags; codec-private tags follow */
+#define  FIELD_CODEC      66  /* base of codec-private tags */
+
+
+/*
+ * Pseudo-tags don't normally need field bits since they
+ * are not written to an output file (by definition).
+ * The library also has express logic to always query a
+ * codec for a pseudo-tag so allocating a field bit for
+ * one is a waste.   If codec wants to promote the notion
+ * of a pseudo-tag being ``set'' or ``unset'' then it can
+ * do using internal state flags without polluting the
+ * field bit space defined for real tags.
+ */
+#define  FIELD_PSEUDO      0
+
+#define  FIELD_LAST      (32*FIELD_SETLONGS-1)
+
+#define  TIFFExtractData(tif, type, v) \
+    ((uint32) ((tif)->tif_header.tiff_magic == TIFF_BIGENDIAN ? \
+        ((v) >> (tif)->tif_typeshift[type]) & (tif)->tif_typemask[type] : \
+  (v) & (tif)->tif_typemask[type]))
+#define  TIFFInsertData(tif, type, v) \
+    ((uint32) ((tif)->tif_header.tiff_magic == TIFF_BIGENDIAN ? \
+        ((v) & (tif)->tif_typemask[type]) << (tif)->tif_typeshift[type] : \
+  (v) & (tif)->tif_typemask[type]))
+
+
+#define BITn(n)        (((unsigned long)1L)<<((n)&0x1f)) 
+#define BITFIELDn(tif, n)    ((tif)->tif_dir.td_fieldsset[(n)/32]) 
+#define TIFFFieldSet(tif, field)  (BITFIELDn(tif, field) & BITn(field)) 
+#define TIFFSetFieldBit(tif, field)  (BITFIELDn(tif, field) |= BITn(field))
+#define TIFFClrFieldBit(tif, field)  (BITFIELDn(tif, field) &= ~BITn(field))
+
+#define  FieldSet(fields, f)    (fields[(f)/32] & BITn(f))
+#define  ResetFieldBit(fields, f)  (fields[(f)/32] &= ~BITn(f))
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+extern  void _TIFFSetupFieldInfo(TIFF*);
+extern  void _TIFFPrintFieldInfo(TIFF*, FILE*);
+extern  TIFFDataType _TIFFSampleToTagType(TIFF*);
+extern  const TIFFFieldInfo* _TIFFFindOrRegisterFieldInfo( TIFF *tif,
+                 ttag_t tag,
+                 TIFFDataType dt );
+extern  TIFFFieldInfo* _TIFFCreateAnonFieldInfo( TIFF *tif, ttag_t tag,
+                                                 TIFFDataType dt );
+
+#define _TIFFMergeFieldInfo      itk_TIFFMergeFieldInfo
+#define _TIFFFindFieldInfo      itk_TIFFFindFieldInfo
+#define _TIFFFindFieldInfoByName    itk_TIFFFindFieldInfoByName
+#define _TIFFFieldWithTag      itk_TIFFFieldWithTag
+#define _TIFFFieldWithName      itk_TIFFFieldWithName
+
+
+#if defined(__cplusplus)
+}
+#endif
+#endif /* _TIFFDIR_ */
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Utilities/ITK/Utilities/tiff/tif_dirinfo.c b/Utilities/ITK/Utilities/tiff/tif_dirinfo.c
new file mode 100644
index 0000000000..a43234e6ad
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_dirinfo.c
@@ -0,0 +1,535 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ *
+ * Core Directory Tag Support.
+ */
+#include "tiffiop.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+/*
+ * NB: NB: THIS ARRAY IS ASSUMED TO BE SORTED BY TAG.
+ *     If a tag can have both LONG and SHORT types
+ *     then the LONG must be placed before the SHORT for
+ *     writing to work properly.
+ *
+ * NOTE: The second field (field_readcount) and third field (field_writecount)
+ *       sometimes use the values TIFF_VARIABLE (-1), TIFF_VARIABLE2 (-3)
+ *       and TIFFTAG_SPP (-2). The macros should be used but would throw off 
+ *       the formatting of the code, so please interprete the -1, -2 and -3 
+ *       values accordingly.
+ */
+#ifndef VMS
+static 
+#endif
+const TIFFFieldInfo tiffFieldInfo[] = {
+    { TIFFTAG_SUBFILETYPE,   1, 1, TIFF_LONG,  FIELD_SUBFILETYPE,
+      TRUE,  FALSE,  "SubfileType" },
+/* XXX SHORT for compatibility w/ old versions of the library */
+    { TIFFTAG_SUBFILETYPE,   1, 1, TIFF_SHORT,  FIELD_SUBFILETYPE,
+      TRUE,  FALSE,  "SubfileType" },
+    { TIFFTAG_OSUBFILETYPE,   1, 1, TIFF_SHORT,  FIELD_SUBFILETYPE,
+      TRUE,  FALSE,  "OldSubfileType" },
+    { TIFFTAG_IMAGEWIDTH,   1, 1, TIFF_LONG,  FIELD_IMAGEDIMENSIONS,
+      FALSE,  FALSE,  "ImageWidth" },
+    { TIFFTAG_IMAGEWIDTH,   1, 1, TIFF_SHORT,  FIELD_IMAGEDIMENSIONS,
+      FALSE,  FALSE,  "ImageWidth" },
+    { TIFFTAG_IMAGELENGTH,   1, 1, TIFF_LONG,  FIELD_IMAGEDIMENSIONS,
+      TRUE,  FALSE,  "ImageLength" },
+    { TIFFTAG_IMAGELENGTH,   1, 1, TIFF_SHORT,  FIELD_IMAGEDIMENSIONS,
+      TRUE,  FALSE,  "ImageLength" },
+    { TIFFTAG_BITSPERSAMPLE,  -1,-1, TIFF_SHORT,  FIELD_BITSPERSAMPLE,
+      FALSE,  FALSE,  "BitsPerSample" },
+/* XXX LONG for compatibility with some broken TIFF writers */
+    { TIFFTAG_BITSPERSAMPLE,  -1,-1, TIFF_LONG,  FIELD_BITSPERSAMPLE,
+      FALSE,  FALSE,  "BitsPerSample" },
+    { TIFFTAG_COMPRESSION,  -1, 1, TIFF_SHORT,  FIELD_COMPRESSION,
+      FALSE,  FALSE,  "Compression" },
+/* XXX LONG for compatibility with some broken TIFF writers */
+    { TIFFTAG_COMPRESSION,  -1, 1, TIFF_LONG,  FIELD_COMPRESSION,
+      FALSE,  FALSE,  "Compression" },
+    { TIFFTAG_PHOTOMETRIC,   1, 1, TIFF_SHORT,  FIELD_PHOTOMETRIC,
+      FALSE,  FALSE,  "PhotometricInterpretation" },
+/* XXX LONG for compatibility with some broken TIFF writers */
+    { TIFFTAG_PHOTOMETRIC,   1, 1, TIFF_LONG,  FIELD_PHOTOMETRIC,
+      FALSE,  FALSE,  "PhotometricInterpretation" },
+    { TIFFTAG_THRESHHOLDING,   1, 1, TIFF_SHORT,  FIELD_THRESHHOLDING,
+      TRUE,  FALSE,  "Threshholding" },
+    { TIFFTAG_CELLWIDTH,   1, 1, TIFF_SHORT,  FIELD_IGNORE,
+      TRUE,  FALSE,  "CellWidth" },
+    { TIFFTAG_CELLLENGTH,   1, 1, TIFF_SHORT,  FIELD_IGNORE,
+      TRUE,  FALSE,  "CellLength" },
+    { TIFFTAG_FILLORDER,   1, 1, TIFF_SHORT,  FIELD_FILLORDER,
+      FALSE,  FALSE,  "FillOrder" },
+    { TIFFTAG_DOCUMENTNAME,  -1,-1, TIFF_ASCII,  FIELD_DOCUMENTNAME,
+      TRUE,  FALSE,  "DocumentName" },
+    { TIFFTAG_IMAGEDESCRIPTION,  -1,-1, TIFF_ASCII,  FIELD_IMAGEDESCRIPTION,
+      TRUE,  FALSE,  "ImageDescription" },
+    { TIFFTAG_MAKE,    -1,-1, TIFF_ASCII,  FIELD_MAKE,
+      TRUE,  FALSE,  "Make" },
+    { TIFFTAG_MODEL,    -1,-1, TIFF_ASCII,  FIELD_MODEL,
+      TRUE,  FALSE,  "Model" },
+    { TIFFTAG_STRIPOFFSETS,  -1,-1, TIFF_LONG,  FIELD_STRIPOFFSETS,
+      FALSE,  FALSE,  "StripOffsets" },
+    { TIFFTAG_STRIPOFFSETS,  -1,-1, TIFF_SHORT,  FIELD_STRIPOFFSETS,
+      FALSE,  FALSE,  "StripOffsets" },
+    { TIFFTAG_ORIENTATION,   1, 1, TIFF_SHORT,  FIELD_ORIENTATION,
+      FALSE,  FALSE,  "Orientation" },
+    { TIFFTAG_SAMPLESPERPIXEL,   1, 1, TIFF_SHORT,  FIELD_SAMPLESPERPIXEL,
+      FALSE,  FALSE,  "SamplesPerPixel" },
+    { TIFFTAG_ROWSPERSTRIP,   1, 1, TIFF_LONG,  FIELD_ROWSPERSTRIP,
+      FALSE,  FALSE,  "RowsPerStrip" },
+    { TIFFTAG_ROWSPERSTRIP,   1, 1, TIFF_SHORT,  FIELD_ROWSPERSTRIP,
+      FALSE,  FALSE,  "RowsPerStrip" },
+    { TIFFTAG_STRIPBYTECOUNTS,  -1,-1, TIFF_LONG,  FIELD_STRIPBYTECOUNTS,
+      FALSE,  FALSE,  "StripByteCounts" },
+    { TIFFTAG_STRIPBYTECOUNTS,  -1,-1, TIFF_SHORT,  FIELD_STRIPBYTECOUNTS,
+      FALSE,  FALSE,  "StripByteCounts" },
+    { TIFFTAG_MINSAMPLEVALUE,  -2,-1, TIFF_SHORT,  FIELD_MINSAMPLEVALUE,
+      TRUE,  FALSE,  "MinSampleValue" },
+    { TIFFTAG_MAXSAMPLEVALUE,  -2,-1, TIFF_SHORT,  FIELD_MAXSAMPLEVALUE,
+      TRUE,  FALSE,  "MaxSampleValue" },
+    { TIFFTAG_XRESOLUTION,   1, 1, TIFF_RATIONAL,  FIELD_RESOLUTION,
+      FALSE,  FALSE,  "XResolution" },
+    { TIFFTAG_YRESOLUTION,   1, 1, TIFF_RATIONAL,  FIELD_RESOLUTION,
+      FALSE,  FALSE,  "YResolution" },
+    { TIFFTAG_PLANARCONFIG,   1, 1, TIFF_SHORT,  FIELD_PLANARCONFIG,
+      FALSE,  FALSE,  "PlanarConfiguration" },
+    { TIFFTAG_PAGENAME,    -1,-1, TIFF_ASCII,  FIELD_PAGENAME,
+      TRUE,  FALSE,  "PageName" },
+    { TIFFTAG_XPOSITION,   1, 1, TIFF_RATIONAL,  FIELD_POSITION,
+      TRUE,  FALSE,  "XPosition" },
+    { TIFFTAG_YPOSITION,   1, 1, TIFF_RATIONAL,  FIELD_POSITION,
+      TRUE,  FALSE,  "YPosition" },
+    { TIFFTAG_FREEOFFSETS,  -1,-1, TIFF_LONG,  FIELD_IGNORE,
+      FALSE,  FALSE,  "FreeOffsets" },
+    { TIFFTAG_FREEBYTECOUNTS,  -1,-1, TIFF_LONG,  FIELD_IGNORE,
+      FALSE,  FALSE,  "FreeByteCounts" },
+    { TIFFTAG_GRAYRESPONSEUNIT,   1, 1, TIFF_SHORT,  FIELD_IGNORE,
+      TRUE,  FALSE,  "GrayResponseUnit" },
+    { TIFFTAG_GRAYRESPONSECURVE,-1,-1, TIFF_SHORT,  FIELD_IGNORE,
+      TRUE,  FALSE,  "GrayResponseCurve" },
+    { TIFFTAG_RESOLUTIONUNIT,   1, 1, TIFF_SHORT,  FIELD_RESOLUTIONUNIT,
+      FALSE,  FALSE,  "ResolutionUnit" },
+    { TIFFTAG_PAGENUMBER,   2, 2, TIFF_SHORT,  FIELD_PAGENUMBER,
+      TRUE,  FALSE,  "PageNumber" },
+    { TIFFTAG_COLORRESPONSEUNIT, 1, 1, TIFF_SHORT,  FIELD_IGNORE,
+      TRUE,  FALSE,  "ColorResponseUnit" },
+    { TIFFTAG_TRANSFERFUNCTION,  -1,-1, TIFF_SHORT,  FIELD_TRANSFERFUNCTION,
+      TRUE,  FALSE,  "TransferFunction" },
+    { TIFFTAG_SOFTWARE,    -1,-1, TIFF_ASCII,  FIELD_CUSTOM,
+      TRUE,  FALSE,  "Software" },
+    { TIFFTAG_DATETIME,    20,20, TIFF_ASCII,  FIELD_DATETIME,
+      TRUE,  FALSE,  "DateTime" },
+    { TIFFTAG_ARTIST,    -1,-1, TIFF_ASCII,  FIELD_ARTIST,
+      TRUE,  FALSE,  "Artist" },
+    { TIFFTAG_HOSTCOMPUTER,  -1,-1, TIFF_ASCII,  FIELD_HOSTCOMPUTER,
+      TRUE,  FALSE,  "HostComputer" },
+    { TIFFTAG_WHITEPOINT,   2, 2, TIFF_RATIONAL,FIELD_WHITEPOINT,
+      TRUE,  FALSE,  "WhitePoint" },
+    { TIFFTAG_PRIMARYCHROMATICITIES,6,6,TIFF_RATIONAL,FIELD_PRIMARYCHROMAS,
+      TRUE,  FALSE,  "PrimaryChromaticities" },
+    { TIFFTAG_COLORMAP,    -1,-1, TIFF_SHORT,  FIELD_COLORMAP,
+      TRUE,  FALSE,  "ColorMap" },
+    { TIFFTAG_HALFTONEHINTS,   2, 2, TIFF_SHORT,  FIELD_HALFTONEHINTS,
+      TRUE,  FALSE,  "HalftoneHints" },
+    { TIFFTAG_TILEWIDTH,   1, 1, TIFF_LONG,  FIELD_TILEDIMENSIONS,
+      FALSE,  FALSE,  "TileWidth" },
+    { TIFFTAG_TILEWIDTH,   1, 1, TIFF_SHORT,  FIELD_TILEDIMENSIONS,
+      FALSE,  FALSE,  "TileWidth" },
+    { TIFFTAG_TILELENGTH,   1, 1, TIFF_LONG,  FIELD_TILEDIMENSIONS,
+      FALSE,  FALSE,  "TileLength" },
+    { TIFFTAG_TILELENGTH,   1, 1, TIFF_SHORT,  FIELD_TILEDIMENSIONS,
+      FALSE,  FALSE,  "TileLength" },
+    { TIFFTAG_TILEOFFSETS,  -1, 1, TIFF_LONG,  FIELD_STRIPOFFSETS,
+      FALSE,  FALSE,  "TileOffsets" },
+    { TIFFTAG_TILEBYTECOUNTS,  -1, 1, TIFF_LONG,  FIELD_STRIPBYTECOUNTS,
+      FALSE,  FALSE,  "TileByteCounts" },
+    { TIFFTAG_TILEBYTECOUNTS,  -1, 1, TIFF_SHORT,  FIELD_STRIPBYTECOUNTS,
+      FALSE,  FALSE,  "TileByteCounts" },
+    { TIFFTAG_SUBIFD,    -1,-1, TIFF_IFD,  FIELD_SUBIFD,
+      TRUE,  TRUE,  "SubIFD" },
+    { TIFFTAG_SUBIFD,    -1,-1, TIFF_LONG,  FIELD_SUBIFD,
+      TRUE,  TRUE,  "SubIFD" },
+    { TIFFTAG_INKSET,     1, 1, TIFF_SHORT,  FIELD_INKSET,
+      FALSE,  FALSE,  "InkSet" },
+    { TIFFTAG_INKNAMES,    -1,-1, TIFF_ASCII,  FIELD_INKNAMES,
+      TRUE,  TRUE,  "InkNames" },
+    { TIFFTAG_NUMBEROFINKS,   1, 1, TIFF_SHORT,  FIELD_NUMBEROFINKS,
+      TRUE,  FALSE,  "NumberOfInks" },
+    { TIFFTAG_DOTRANGE,     2, 2, TIFF_SHORT,  FIELD_DOTRANGE,
+      FALSE,  FALSE,  "DotRange" },
+    { TIFFTAG_DOTRANGE,     2, 2, TIFF_BYTE,  FIELD_DOTRANGE,
+      FALSE,  FALSE,  "DotRange" },
+    { TIFFTAG_TARGETPRINTER,  -1,-1, TIFF_ASCII,  FIELD_TARGETPRINTER,
+      TRUE,  FALSE,  "TargetPrinter" },
+    { TIFFTAG_EXTRASAMPLES,  -1,-1, TIFF_SHORT,  FIELD_EXTRASAMPLES,
+      FALSE,  TRUE,  "ExtraSamples" },
+/* XXX for bogus Adobe Photoshop v2.5 files */
+    { TIFFTAG_EXTRASAMPLES,  -1,-1, TIFF_BYTE,  FIELD_EXTRASAMPLES,
+      FALSE,  TRUE,  "ExtraSamples" },
+    { TIFFTAG_SAMPLEFORMAT,  -1,-1, TIFF_SHORT,  FIELD_SAMPLEFORMAT,
+      FALSE,  FALSE,  "SampleFormat" },
+    { TIFFTAG_SMINSAMPLEVALUE,  -2,-1, TIFF_ANY,  FIELD_SMINSAMPLEVALUE,
+      TRUE,  FALSE,  "SMinSampleValue" },
+    { TIFFTAG_SMAXSAMPLEVALUE,  -2,-1, TIFF_ANY,  FIELD_SMAXSAMPLEVALUE,
+      TRUE,  FALSE,  "SMaxSampleValue" },
+    { TIFFTAG_YCBCRCOEFFICIENTS, 3, 3, TIFF_RATIONAL,  FIELD_YCBCRCOEFFICIENTS,
+      FALSE,  FALSE,  "YCbCrCoefficients" },
+    { TIFFTAG_YCBCRSUBSAMPLING,   2, 2, TIFF_SHORT,  FIELD_YCBCRSUBSAMPLING,
+      FALSE,  FALSE,  "YCbCrSubsampling" },
+    { TIFFTAG_YCBCRPOSITIONING,   1, 1, TIFF_SHORT,  FIELD_YCBCRPOSITIONING,
+      FALSE,  FALSE,  "YCbCrPositioning" },
+    { TIFFTAG_REFERENCEBLACKWHITE,6,6,TIFF_RATIONAL,  FIELD_REFBLACKWHITE,
+      TRUE,  FALSE,  "ReferenceBlackWhite" },
+/* XXX temporarily accept LONG for backwards compatibility */
+    { TIFFTAG_REFERENCEBLACKWHITE,6,6,TIFF_LONG,  FIELD_REFBLACKWHITE,
+      TRUE,  FALSE,  "ReferenceBlackWhite" },
+    { TIFFTAG_XMLPACKET,  -1,-3, TIFF_BYTE,  FIELD_XMLPACKET,
+      FALSE,  TRUE,  "XMLPacket" },
+/* begin SGI tags */
+    { TIFFTAG_MATTEING,     1, 1, TIFF_SHORT,  FIELD_EXTRASAMPLES,
+      FALSE,  FALSE,  "Matteing" },
+    { TIFFTAG_DATATYPE,    -2,-1, TIFF_SHORT,  FIELD_SAMPLEFORMAT,
+      FALSE,  FALSE,  "DataType" },
+    { TIFFTAG_IMAGEDEPTH,   1, 1, TIFF_LONG,  FIELD_IMAGEDEPTH,
+      FALSE,  FALSE,  "ImageDepth" },
+    { TIFFTAG_IMAGEDEPTH,   1, 1, TIFF_SHORT,  FIELD_IMAGEDEPTH,
+      FALSE,  FALSE,  "ImageDepth" },
+    { TIFFTAG_TILEDEPTH,   1, 1, TIFF_LONG,  FIELD_TILEDEPTH,
+      FALSE,  FALSE,  "TileDepth" },
+    { TIFFTAG_TILEDEPTH,   1, 1, TIFF_SHORT,  FIELD_TILEDEPTH,
+      FALSE,  FALSE,  "TileDepth" },
+/* end SGI tags */
+/* begin Pixar tags */
+    { TIFFTAG_PIXAR_IMAGEFULLWIDTH,  1, 1, TIFF_LONG,  FIELD_IMAGEFULLWIDTH,
+      TRUE,  FALSE,  "ImageFullWidth" },
+    { TIFFTAG_PIXAR_IMAGEFULLLENGTH, 1, 1, TIFF_LONG,  FIELD_IMAGEFULLLENGTH,
+      TRUE,  FALSE,  "ImageFullLength" },
+    { TIFFTAG_PIXAR_TEXTUREFORMAT,  -1,-1, TIFF_ASCII,  FIELD_TEXTUREFORMAT,
+      TRUE,  FALSE,  "TextureFormat" },
+    { TIFFTAG_PIXAR_WRAPMODES,      -1,-1, TIFF_ASCII,  FIELD_WRAPMODES,
+      TRUE,  FALSE,  "TextureWrapModes" },
+    { TIFFTAG_PIXAR_FOVCOT,       1, 1, TIFF_FLOAT,  FIELD_FOVCOT,
+      TRUE,  FALSE,  "FieldOfViewCotan" },
+    { TIFFTAG_PIXAR_MATRIX_WORLDTOSCREEN,  16,16,  TIFF_FLOAT,
+      FIELD_MATRIX_WORLDTOSCREEN,  TRUE,  FALSE,  "MatrixWorldToScreen" },
+    { TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA,  16,16,  TIFF_FLOAT,
+       FIELD_MATRIX_WORLDTOCAMERA,  TRUE,  FALSE,  "MatrixWorldToCamera" },
+    { TIFFTAG_COPYRIGHT,  -1,-1, TIFF_ASCII,  FIELD_COPYRIGHT,
+      TRUE,  FALSE,  "Copyright" },
+/* end Pixar tags */
+    { TIFFTAG_RICHTIFFIPTC, -1,-3, TIFF_LONG,   FIELD_RICHTIFFIPTC, 
+      FALSE,    TRUE,   "RichTIFFIPTC" },
+    { TIFFTAG_PHOTOSHOP,    -1,-3, TIFF_BYTE,   FIELD_PHOTOSHOP, 
+      FALSE,    TRUE,   "Photoshop" },
+    { TIFFTAG_ICCPROFILE,  -1,-3, TIFF_UNDEFINED,  FIELD_ICCPROFILE,
+      FALSE,  TRUE,  "ICC Profile" },
+    { TIFFTAG_STONITS,     1, 1, TIFF_DOUBLE,  FIELD_STONITS,
+      FALSE,  FALSE,  "StoNits" },
+};
+#define  N(a)  (sizeof (a) / sizeof (a[0]))
+
+void
+_TIFFSetupFieldInfo(TIFF* tif)
+{
+  if (tif->tif_fieldinfo) {
+    int  i;
+
+    for (i = 0; i < tif->tif_nfields; i++) 
+    {
+      TIFFFieldInfo *fld = tif->tif_fieldinfo[i];
+      if (fld->field_bit == FIELD_CUSTOM && 
+        strncmp("Tag ", fld->field_name, 4) == 0) 
+        {
+        _TIFFfree(fld->field_name);
+        _TIFFfree(fld);
+        }
+    }   
+      
+    _TIFFfree(tif->tif_fieldinfo);
+    tif->tif_nfields = 0;
+  }
+  _TIFFMergeFieldInfo(tif, tiffFieldInfo, N(tiffFieldInfo));
+}
+
+static int
+tagCompare(const void* a, const void* b)
+{
+  const TIFFFieldInfo* ta = *(const TIFFFieldInfo**) a;
+  const TIFFFieldInfo* tb = *(const TIFFFieldInfo**) b;
+  /* NB: be careful of return values for 16-bit platforms */
+  if (ta->field_tag != tb->field_tag)
+    return (ta->field_tag < tb->field_tag ? -1 : 1);
+  else
+    return ((int)tb->field_type - (int)ta->field_type);
+}
+
+static int
+tagNameCompare(const void* a, const void* b)
+{
+  const TIFFFieldInfo* ta = *(const TIFFFieldInfo**) a;
+  const TIFFFieldInfo* tb = *(const TIFFFieldInfo**) b;
+
+        return strcmp(ta->field_name, tb->field_name);
+}
+
+void
+_TIFFMergeFieldInfo(TIFF* tif, const TIFFFieldInfo info[], int n)
+{
+  TIFFFieldInfo** tp;
+  int i;
+
+        tif->tif_foundfield = NULL;
+
+  if (tif->tif_nfields > 0) {
+    tif->tif_fieldinfo = (TIFFFieldInfo**)
+        _TIFFrealloc(tif->tif_fieldinfo,
+      (tif->tif_nfields+n) * sizeof (TIFFFieldInfo*));
+  } else {
+    tif->tif_fieldinfo = (TIFFFieldInfo**)
+        _TIFFmalloc(n * sizeof (TIFFFieldInfo*));
+  }
+  assert(tif->tif_fieldinfo != NULL);
+  tp = &tif->tif_fieldinfo[tif->tif_nfields];
+  for (i = 0; i < n; i++)
+    tp[i] = (TIFFFieldInfo*) &info[i];  /* XXX */
+
+        /* Sort the field info by tag number */
+        qsort(tif->tif_fieldinfo, (size_t) (tif->tif_nfields += n),
+              sizeof (TIFFFieldInfo*), tagCompare);
+}
+
+void
+_TIFFPrintFieldInfo(TIFF* tif, FILE* fd)
+{
+  int i;
+
+  fprintf(fd, "%s: \n", tif->tif_name);
+  for (i = 0; i < tif->tif_nfields; i++) {
+    const TIFFFieldInfo* fip = tif->tif_fieldinfo[i];
+    fprintf(fd, "field[%2d] %5lu, %2d, %2d, %d, %2d, %5s, %5s, %s\n"
+      , i
+      , (unsigned long) fip->field_tag
+      , fip->field_readcount, fip->field_writecount
+      , fip->field_type
+      , fip->field_bit
+      , fip->field_oktochange ? "TRUE" : "FALSE"
+      , fip->field_passcount ? "TRUE" : "FALSE"
+      , fip->field_name
+    );
+  }
+}
+
+/*
+ * Return size of TIFFDataType in bytes
+ */
+int
+TIFFDataWidth(TIFFDataType type)
+{
+  switch(type)
+  {
+  case 0:  /* nothing */
+  case 1:  /* TIFF_BYTE */
+  case 2:  /* TIFF_ASCII */
+  case 6:  /* TIFF_SBYTE */
+  case 7:  /* TIFF_UNDEFINED */
+    return 1;
+  case 3:  /* TIFF_SHORT */
+  case 8:  /* TIFF_SSHORT */
+    return 2;
+  case 4:  /* TIFF_LONG */
+  case 9:  /* TIFF_SLONG */
+  case 11: /* TIFF_FLOAT */
+        case 13: /* TIFF_IFD */
+    return 4;
+  case 5:  /* TIFF_RATIONAL */
+  case 10: /* TIFF_SRATIONAL */
+  case 12: /* TIFF_DOUBLE */
+    return 8;
+  default:
+    return 0; /* will return 0 for unknown types */
+  }
+}
+
+/*
+ * Return nearest TIFFDataType to the sample type of an image.
+ */
+TIFFDataType
+_TIFFSampleToTagType(TIFF* tif)
+{
+  uint32 bps = TIFFhowmany8(tif->tif_dir.td_bitspersample);
+
+  switch (tif->tif_dir.td_sampleformat) {
+  case SAMPLEFORMAT_IEEEFP:
+    return (bps == 4 ? TIFF_FLOAT : TIFF_DOUBLE);
+  case SAMPLEFORMAT_INT:
+    return (bps <= 1 ? TIFF_SBYTE :
+        bps <= 2 ? TIFF_SSHORT : TIFF_SLONG);
+  case SAMPLEFORMAT_UINT:
+    return (bps <= 1 ? TIFF_BYTE :
+        bps <= 2 ? TIFF_SHORT : TIFF_LONG);
+  case SAMPLEFORMAT_VOID:
+    return (TIFF_UNDEFINED);
+  }
+  /*NOTREACHED*/
+  return (TIFF_UNDEFINED);
+}
+
+const TIFFFieldInfo*
+_TIFFFindFieldInfo(TIFF* tif, ttag_t tag, TIFFDataType dt)
+{
+  int i, n;
+
+  if (tif->tif_foundfield && tif->tif_foundfield->field_tag == tag &&
+      (dt == TIFF_ANY || dt == tif->tif_foundfield->field_type))
+    return (tif->tif_foundfield);
+  /* NB: use sorted search (e.g. binary search) */
+  if(dt != TIFF_ANY) {
+            TIFFFieldInfo key = {0, 0, 0, (TIFFDataType)0, 0, 0, 0, 0};
+            key.field_tag = tag;
+            key.field_type = dt;
+            return((const TIFFFieldInfo *) bsearch(&key, 
+               tif->tif_fieldinfo, 
+               tif->tif_nfields,
+               sizeof(TIFFFieldInfo), 
+               tagCompare));
+        } else for (i = 0, n = tif->tif_nfields; i < n; i++) {
+    const TIFFFieldInfo* fip = tif->tif_fieldinfo[i];
+    if (fip->field_tag == tag &&
+        (dt == TIFF_ANY || fip->field_type == dt))
+      return (tif->tif_foundfield = fip);
+  }
+  return ((const TIFFFieldInfo *)0);
+}
+
+const TIFFFieldInfo*
+_TIFFFindFieldInfoByName(TIFF* tif, const char *field_name, TIFFDataType dt)
+{
+  int i, n;
+
+  if (tif->tif_foundfield
+      && streq(tif->tif_foundfield->field_name, field_name)
+      && (dt == TIFF_ANY || dt == tif->tif_foundfield->field_type))
+    return (tif->tif_foundfield);
+  /* NB: use sorted search (e.g. binary search) */
+  if(dt != TIFF_ANY) {
+            TIFFFieldInfo key = {0, 0, 0, (TIFFDataType)0, 0, 0, 0, 0};
+            key.field_name = (char *)field_name;
+            key.field_type = dt;
+            return((const TIFFFieldInfo *) bsearch(&key, 
+               tif->tif_fieldinfo, 
+               tif->tif_nfields,
+               sizeof(TIFFFieldInfo), 
+               tagNameCompare));
+        } else for (i = 0, n = tif->tif_nfields; i < n; i++) {
+    const TIFFFieldInfo* fip = tif->tif_fieldinfo[i];
+    if (streq(fip->field_name, field_name) &&
+        (dt == TIFF_ANY || fip->field_type == dt))
+      return (tif->tif_foundfield = fip);
+  }
+  return ((const TIFFFieldInfo *)0);
+}
+
+const TIFFFieldInfo*
+_TIFFFieldWithTag(TIFF* tif, ttag_t tag)
+{
+  const TIFFFieldInfo* fip = _TIFFFindFieldInfo(tif, tag, TIFF_ANY);
+  if (!fip) {
+    TIFFError("TIFFFieldWithTag",
+        "Internal error, unknown tag 0x%x",
+                          (unsigned int) tag);
+    assert(fip != NULL);
+    /*NOTREACHED*/
+  }
+  return (fip);
+}
+
+const TIFFFieldInfo*
+_TIFFFieldWithName(TIFF* tif, const char *field_name)
+{
+  const TIFFFieldInfo* fip =
+    _TIFFFindFieldInfoByName(tif, field_name, TIFF_ANY);
+  if (!fip) {
+    TIFFError("TIFFFieldWithName",
+        "Internal error, unknown tag %s", field_name);
+    assert(fip != NULL);
+    /*NOTREACHED*/
+  }
+  return (fip);
+}
+
+const TIFFFieldInfo*
+_TIFFFindOrRegisterFieldInfo( TIFF *tif, ttag_t tag, TIFFDataType dt )
+
+{
+    const TIFFFieldInfo *fld;
+
+    fld = _TIFFFindFieldInfo( tif, tag, dt );
+    if( fld == NULL )
+    {
+        fld = _TIFFCreateAnonFieldInfo( tif, tag, dt );
+        _TIFFMergeFieldInfo( tif, fld, 1 );
+    }
+
+    return fld;
+}
+
+TIFFFieldInfo*
+_TIFFCreateAnonFieldInfo(TIFF *tif, ttag_t tag, TIFFDataType field_type)
+{
+    TIFFFieldInfo *fld;
+    (void)tif;
+
+    fld = (TIFFFieldInfo *) _TIFFmalloc(sizeof (TIFFFieldInfo));
+    if (fld == NULL)
+  return NULL;
+    _TIFFmemset( fld, 0, sizeof(TIFFFieldInfo) );
+
+    fld->field_tag = tag;
+    fld->field_readcount = TIFF_VARIABLE;
+    fld->field_writecount = TIFF_VARIABLE;
+    fld->field_type = field_type;
+    fld->field_bit = FIELD_CUSTOM;
+    fld->field_oktochange = TRUE;
+    fld->field_passcount = TRUE;
+    fld->field_name = (char *) _TIFFmalloc(32);
+    if (fld->field_name == NULL) {
+  _TIFFfree(fld);
+  return NULL;
+    }
+
+    /* note that this name is a special sign to TIFFClose() and
+     * _TIFFSetupFieldInfo() to free the field
+     */
+    sprintf(fld->field_name, "Tag %d", (int) tag);
+
+    return fld;    
+}
+
diff --git a/Utilities/ITK/Utilities/tiff/tif_dirread.c b/Utilities/ITK/Utilities/tiff/tif_dirread.c
new file mode 100644
index 0000000000..635001386e
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_dirread.c
@@ -0,0 +1,1611 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ *
+ * Directory Read Support Routines.
+ */
+#include "tiffiop.h"
+
+#define  IGNORE  0    /* tag placeholder used below */
+
+#if HAVE_IEEEFP
+#define itk_TIFFCvtIEEEFloatToNative(tif, n, fp)
+#define itk_TIFFCvtIEEEDoubleToNative(tif, n, dp)
+#else
+extern  void itk_TIFFCvtIEEEFloatToNative(TIFF*, uint32, float*);
+extern  void itk_TIFFCvtIEEEDoubleToNative(TIFF*, uint32, double*);
+#endif
+
+static  int EstimateStripByteCounts(TIFF*, TIFFDirEntry*, uint16);
+static  void MissingRequired(TIFF*, const char*);
+static  int CheckDirCount(TIFF*, TIFFDirEntry*, uint32);
+static  tsize_t TIFFFetchData(TIFF*, TIFFDirEntry*, char*);
+static  tsize_t TIFFFetchString(TIFF*, TIFFDirEntry*, char*);
+static  float TIFFFetchRational(TIFF*, TIFFDirEntry*);
+static  int TIFFFetchNormalTag(TIFF*, TIFFDirEntry*);
+static  int TIFFFetchPerSampleShorts(TIFF*, TIFFDirEntry*, uint16*);
+static  int TIFFFetchPerSampleLongs(TIFF*, TIFFDirEntry*, uint32*);
+static  int TIFFFetchPerSampleAnys(TIFF*, TIFFDirEntry*, double*);
+static  int TIFFFetchShortArray(TIFF*, TIFFDirEntry*, uint16*);
+static  int TIFFFetchStripThing(TIFF*, TIFFDirEntry*, long, uint32**);
+static  int TIFFFetchExtraSamples(TIFF*, TIFFDirEntry*);
+static  int TIFFFetchRefBlackWhite(TIFF*, TIFFDirEntry*);
+static  float TIFFFetchFloat(TIFF*, TIFFDirEntry*);
+static  int TIFFFetchFloatArray(TIFF*, TIFFDirEntry*, float*);
+static  int TIFFFetchDoubleArray(TIFF*, TIFFDirEntry*, double*);
+static  int TIFFFetchAnyArray(TIFF*, TIFFDirEntry*, double*);
+static  int TIFFFetchShortPair(TIFF*, TIFFDirEntry*);
+static  void ChopUpSingleUncompressedStrip(TIFF*);
+
+static char *
+CheckMalloc(TIFF* tif, size_t nmemb, size_t elem_size, const char* what)
+{
+  char  *cp = NULL;
+  tsize_t  bytes = nmemb * elem_size;
+
+  /*
+   * XXX: Check for integer overflow.
+   */
+  if (nmemb && elem_size && bytes / elem_size == nmemb)
+    cp = (char*)_TIFFmalloc(bytes);
+
+  if (cp == NULL)
+    TIFFError(tif->tif_name, "No space %s", what);
+  
+  return (cp);
+}
+
+/*
+ * Read the next TIFF directory from a file
+ * and convert it to the internal format.
+ * We read directories sequentially.
+ */
+int
+TIFFReadDirectory(TIFF* tif)
+{
+  static const char module[] = "TIFFReadDirectory";
+
+  register TIFFDirEntry* dp;
+  register int n;
+  register TIFFDirectory* td;
+  TIFFDirEntry* dir;
+  uint16 iv;
+  uint32 v;
+  double dv;
+  const TIFFFieldInfo* fip;
+  int fix;
+  uint16 dircount;
+  toff_t nextdiroff;
+  char* cp;
+  int diroutoforderwarning = 0;
+  toff_t* new_dirlist;
+
+  tif->tif_diroff = tif->tif_nextdiroff;
+  if (tif->tif_diroff == 0)    /* no more directories */
+    return (0);
+
+  /*
+   * XXX: Trick to prevent IFD looping. The one can create TIFF file
+   * with looped directory pointers. We will maintain a list of already
+   * seen directories and check every IFD offset against this list.
+   */
+  for (n = 0; n < tif->tif_dirnumber; n++) {
+    if (tif->tif_dirlist[n] == tif->tif_diroff)
+      return (0);
+  }
+  tif->tif_dirnumber++;
+  new_dirlist = _TIFFrealloc(tif->tif_dirlist,
+           tif->tif_dirnumber * sizeof(toff_t));
+  if (!new_dirlist) {
+    TIFFError(module,
+        "%s: Failed to allocate space for IFD list",
+        tif->tif_name);
+    return (0);
+  }
+  tif->tif_dirlist = new_dirlist;
+  tif->tif_dirlist[tif->tif_dirnumber - 1] = tif->tif_diroff;
+
+  /*
+   * Cleanup any previous compression state.
+   */
+  (*tif->tif_cleanup)(tif);
+  tif->tif_curdir++;
+  nextdiroff = 0;
+  if (!isMapped(tif)) {
+    if (!SeekOK(tif, tif->tif_diroff)) {
+      TIFFError(module,
+          "%s: Seek error accessing TIFF directory",
+                            tif->tif_name);
+      return (0);
+    }
+    if (!ReadOK(tif, &dircount, sizeof (uint16))) {
+      TIFFError(module,
+          "%s: Can not read TIFF directory count",
+                            tif->tif_name);
+      return (0);
+    }
+    if (tif->tif_flags & TIFF_SWAB)
+      TIFFSwabShort(&dircount);
+    dir = (TIFFDirEntry *)CheckMalloc(tif,
+              dircount,
+              sizeof (TIFFDirEntry),
+              "to read TIFF directory");
+    if (dir == NULL)
+      return (0);
+    if (!ReadOK(tif, dir, dircount*sizeof (TIFFDirEntry))) {
+      TIFFError(module,
+                                  "%.100s: Can not read TIFF directory",
+                                  tif->tif_name);
+      goto bad;
+    }
+    /*
+     * Read offset to next directory for sequential scans.
+     */
+    (void) ReadOK(tif, &nextdiroff, sizeof (uint32));
+  } else {
+    toff_t off = tif->tif_diroff;
+
+    if (off + sizeof (uint16) > tif->tif_size) {
+      TIFFError(module,
+          "%s: Can not read TIFF directory count",
+                            tif->tif_name);
+      return (0);
+    } else
+      _TIFFmemcpy(&dircount, tif->tif_base + off, sizeof (uint16));
+    off += sizeof (uint16);
+    if (tif->tif_flags & TIFF_SWAB)
+      TIFFSwabShort(&dircount);
+    dir = (TIFFDirEntry *)CheckMalloc(tif,
+        dircount, sizeof (TIFFDirEntry), "to read TIFF directory");
+    if (dir == NULL)
+      return (0);
+    if (off + dircount*sizeof (TIFFDirEntry) > tif->tif_size) {
+      TIFFError(module,
+                                  "%s: Can not read TIFF directory",
+                                  tif->tif_name);
+      goto bad;
+    } else {
+      _TIFFmemcpy(dir, tif->tif_base + off,
+            dircount*sizeof (TIFFDirEntry));
+    }
+    off += dircount* sizeof (TIFFDirEntry);
+    if (off + sizeof (uint32) <= tif->tif_size)
+      _TIFFmemcpy(&nextdiroff, tif->tif_base+off, sizeof (uint32));
+  }
+  if (tif->tif_flags & TIFF_SWAB)
+    TIFFSwabLong(&nextdiroff);
+  tif->tif_nextdiroff = nextdiroff;
+
+  tif->tif_flags &= ~TIFF_BEENWRITING;  /* reset before new dir */
+  /*
+   * Setup default value and then make a pass over
+   * the fields to check type and tag information,
+   * and to extract info required to size data
+   * structures.  A second pass is made afterwards
+   * to read in everthing not taken in the first pass.
+   */
+  td = &tif->tif_dir;
+  /* free any old stuff and reinit */
+  TIFFFreeDirectory(tif);
+  TIFFDefaultDirectory(tif);
+  /*
+   * Electronic Arts writes gray-scale TIFF files
+   * without a PlanarConfiguration directory entry.
+   * Thus we setup a default value here, even though
+   * the TIFF spec says there is no default value.
+   */
+  TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
+
+  /*
+   * Sigh, we must make a separate pass through the
+   * directory for the following reason:
+   *
+   * We must process the Compression tag in the first pass
+   * in order to merge in codec-private tag definitions (otherwise
+   * we may get complaints about unknown tags).  However, the
+   * Compression tag may be dependent on the SamplesPerPixel
+   * tag value because older TIFF specs permited Compression
+   * to be written as a SamplesPerPixel-count tag entry.
+   * Thus if we don't first figure out the correct SamplesPerPixel
+   * tag value then we may end up ignoring the Compression tag
+   * value because it has an incorrect count value (if the
+   * true value of SamplesPerPixel is not 1).
+   *
+   * It sure would have been nice if Aldus had really thought
+   * this stuff through carefully.
+   */ 
+  for (dp = dir, n = dircount; n > 0; n--, dp++) {
+    if (tif->tif_flags & TIFF_SWAB) {
+      TIFFSwabArrayOfShort(&dp->tdir_tag, 2);
+      TIFFSwabArrayOfLong(&dp->tdir_count, 2);
+    }
+    if (dp->tdir_tag == TIFFTAG_SAMPLESPERPIXEL) {
+      if (!TIFFFetchNormalTag(tif, dp))
+        goto bad;
+      dp->tdir_tag = IGNORE;
+    }
+  }
+  /*
+   * First real pass over the directory.
+   */
+  fix = 0;
+  for (dp = dir, n = dircount; n > 0; n--, dp++) {
+
+    if (fix >= tif->tif_nfields || dp->tdir_tag == IGNORE)
+      continue;
+               
+    /*
+     * Silicon Beach (at least) writes unordered
+     * directory tags (violating the spec).  Handle
+     * it here, but be obnoxious (maybe they'll fix it?).
+     */
+    if (dp->tdir_tag < tif->tif_fieldinfo[fix]->field_tag) {
+      if (!diroutoforderwarning) {
+        TIFFWarning(module,
+"%s: invalid TIFF directory; tags are not sorted in ascending order",
+                                            tif->tif_name);
+        diroutoforderwarning = 1;
+      }
+      fix = 0;      /* O(n^2) */
+    }
+    while (fix < tif->tif_nfields &&
+           tif->tif_fieldinfo[fix]->field_tag < dp->tdir_tag)
+      fix++;
+    if (fix >= tif->tif_nfields ||
+        tif->tif_fieldinfo[fix]->field_tag != dp->tdir_tag) {
+
+                    TIFFWarning(module,
+                        "%s: unknown field with tag %d (0x%x) encountered",
+                                tif->tif_name, dp->tdir_tag, dp->tdir_tag,
+                                dp->tdir_type);
+
+                    TIFFMergeFieldInfo( tif,
+                                        _TIFFCreateAnonFieldInfo( tif,
+                                              dp->tdir_tag,
+                (TIFFDataType) dp->tdir_type ),
+                                        1 );
+                    fix = 0;
+                    while (fix < tif->tif_nfields &&
+                           tif->tif_fieldinfo[fix]->field_tag < dp->tdir_tag)
+      fix++;
+    }
+    /*
+     * Null out old tags that we ignore.
+     */
+    if (tif->tif_fieldinfo[fix]->field_bit == FIELD_IGNORE) {
+  ignore:
+      dp->tdir_tag = IGNORE;
+      continue;
+    }
+    /*
+     * Check data type.
+     */
+    fip = tif->tif_fieldinfo[fix];
+    while (dp->tdir_type != (unsigned short) fip->field_type
+                       && fix < tif->tif_nfields) {
+      if (fip->field_type == TIFF_ANY)  /* wildcard */
+        break;
+                        fip = tif->tif_fieldinfo[++fix];
+      if (fix >= tif->tif_nfields ||
+          fip->field_tag != dp->tdir_tag) {
+        TIFFWarning(module,
+      "%s: wrong data type %d for \"%s\"; tag ignored",
+              tif->tif_name, dp->tdir_type,
+              tif->tif_fieldinfo[fix-1]->field_name);
+        goto ignore;
+      }
+    }
+    /*
+     * Check count if known in advance.
+     */
+    if (fip->field_readcount != TIFF_VARIABLE
+        && fip->field_readcount != TIFF_VARIABLE2) {
+      uint32 expected = (fip->field_readcount == TIFF_SPP) ?
+          (uint32) td->td_samplesperpixel :
+          (uint32) fip->field_readcount;
+      if (!CheckDirCount(tif, dp, expected))
+        goto ignore;
+    }
+
+    switch (dp->tdir_tag) {
+    case TIFFTAG_COMPRESSION:
+      /*
+       * The 5.0 spec says the Compression tag has
+       * one value, while earlier specs say it has
+       * one value per sample.  Because of this, we
+       * accept the tag if one value is supplied.
+       */
+      if (dp->tdir_count == 1) {
+        v = TIFFExtractData(tif,
+            dp->tdir_type, dp->tdir_offset);
+        if (!TIFFSetField(tif, dp->tdir_tag, (uint16)v))
+          goto bad;
+        break;
+      /* XXX: workaround for broken TIFFs */
+      } else if (dp->tdir_type == TIFF_LONG) {
+        if (!TIFFFetchPerSampleLongs(tif, dp, &v) ||
+            !TIFFSetField(tif, dp->tdir_tag, (uint16)v))
+          goto bad;
+      } else {
+        if (!TIFFFetchPerSampleShorts(tif, dp, &iv)
+            || !TIFFSetField(tif, dp->tdir_tag, iv))
+          goto bad;
+      }
+      dp->tdir_tag = IGNORE;
+      break;
+    case TIFFTAG_STRIPOFFSETS:
+    case TIFFTAG_STRIPBYTECOUNTS:
+    case TIFFTAG_TILEOFFSETS:
+    case TIFFTAG_TILEBYTECOUNTS:
+      TIFFSetFieldBit(tif, fip->field_bit);
+      break;
+    case TIFFTAG_IMAGEWIDTH:
+    case TIFFTAG_IMAGELENGTH:
+    case TIFFTAG_IMAGEDEPTH:
+    case TIFFTAG_TILELENGTH:
+    case TIFFTAG_TILEWIDTH:
+    case TIFFTAG_TILEDEPTH:
+    case TIFFTAG_PLANARCONFIG:
+    case TIFFTAG_ROWSPERSTRIP:
+      if (!TIFFFetchNormalTag(tif, dp))
+        goto bad;
+      dp->tdir_tag = IGNORE;
+      break;
+    case TIFFTAG_EXTRASAMPLES:
+      (void) TIFFFetchExtraSamples(tif, dp);
+      dp->tdir_tag = IGNORE;
+      break;
+    }
+  }
+
+  /*
+   * Allocate directory structure and setup defaults.
+   */
+  if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) {
+    MissingRequired(tif, "ImageLength");
+    goto bad;
+  }
+  if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) {
+    MissingRequired(tif, "PlanarConfiguration");
+    goto bad;
+  }
+  /* 
+    * Setup appropriate structures (by strip or by tile)
+   */
+  if (!TIFFFieldSet(tif, FIELD_TILEDIMENSIONS)) {
+    td->td_nstrips = TIFFNumberOfStrips(tif);
+    td->td_tilewidth = td->td_imagewidth;
+    td->td_tilelength = td->td_rowsperstrip;
+    td->td_tiledepth = td->td_imagedepth;
+    tif->tif_flags &= ~TIFF_ISTILED;
+  } else {
+    td->td_nstrips = TIFFNumberOfTiles(tif);
+    tif->tif_flags |= TIFF_ISTILED;
+  }
+  if (!td->td_nstrips) {
+    TIFFError(module, "%s: cannot handle zero number of %s",
+        tif->tif_name, isTiled(tif) ? "tiles" : "strips");
+    goto bad;
+  }
+  td->td_stripsperimage = td->td_nstrips;
+  if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
+    td->td_stripsperimage /= td->td_samplesperpixel;
+  if (!TIFFFieldSet(tif, FIELD_STRIPOFFSETS)) {
+    MissingRequired(tif,
+        isTiled(tif) ? "TileOffsets" : "StripOffsets");
+    goto bad;
+  }
+
+  /*
+   * Second pass: extract other information.
+   */
+  for (dp = dir, n = dircount; n > 0; n--, dp++) {
+    if (dp->tdir_tag == IGNORE)
+      continue;
+    switch (dp->tdir_tag) {
+    case TIFFTAG_MINSAMPLEVALUE:
+    case TIFFTAG_MAXSAMPLEVALUE:
+    case TIFFTAG_BITSPERSAMPLE:
+    case TIFFTAG_DATATYPE:
+    case TIFFTAG_SAMPLEFORMAT:
+      /*
+       * The 5.0 spec says the Compression tag has
+       * one value, while earlier specs say it has
+       * one value per sample.  Because of this, we
+       * accept the tag if one value is supplied.
+       *
+                         * The MinSampleValue, MaxSampleValue, BitsPerSample
+                         * DataType and SampleFormat tags are supposed to be
+                         * written as one value/sample, but some vendors
+                         * incorrectly write one value only -- so we accept
+                         * that as well (yech). Other vendors write correct
+       * value for NumberOfSamples, but incorrect one for
+       * BitsPerSample and friends, and we will read this
+       * too.
+       */
+      if (dp->tdir_count == 1) {
+        v = TIFFExtractData(tif,
+            dp->tdir_type, dp->tdir_offset);
+        if (!TIFFSetField(tif, dp->tdir_tag, (uint16)v))
+          goto bad;
+      /* XXX: workaround for broken TIFFs */
+      } else if (dp->tdir_tag == TIFFTAG_BITSPERSAMPLE
+           && dp->tdir_type == TIFF_LONG) {
+        if (!TIFFFetchPerSampleLongs(tif, dp, &v) ||
+            !TIFFSetField(tif, dp->tdir_tag, (uint16)v))
+          goto bad;
+      } else {
+        if (!TIFFFetchPerSampleShorts(tif, dp, &iv) ||
+            !TIFFSetField(tif, dp->tdir_tag, iv))
+          goto bad;
+      }
+      break;
+    case TIFFTAG_SMINSAMPLEVALUE:
+    case TIFFTAG_SMAXSAMPLEVALUE:
+      if (!TIFFFetchPerSampleAnys(tif, dp, &dv) ||
+          !TIFFSetField(tif, dp->tdir_tag, dv))
+        goto bad;
+      break;
+    case TIFFTAG_STRIPOFFSETS:
+    case TIFFTAG_TILEOFFSETS:
+      if (!TIFFFetchStripThing(tif, dp,
+          td->td_nstrips, &td->td_stripoffset))
+        goto bad;
+      break;
+    case TIFFTAG_STRIPBYTECOUNTS:
+    case TIFFTAG_TILEBYTECOUNTS:
+      if (!TIFFFetchStripThing(tif, dp,
+          td->td_nstrips, &td->td_stripbytecount))
+        goto bad;
+      break;
+    case TIFFTAG_COLORMAP:
+    case TIFFTAG_TRANSFERFUNCTION:
+      /*
+       * TransferFunction can have either 1x or 3x data
+       * values; Colormap can have only 3x items.
+       */
+      v = 1L<<td->td_bitspersample;
+      if (dp->tdir_tag == TIFFTAG_COLORMAP ||
+          dp->tdir_count != v) {
+        if (!CheckDirCount(tif, dp, 3 * v))
+          break;
+      }
+      v *= sizeof(uint16);
+      cp = CheckMalloc(tif, dp->tdir_count, sizeof (uint16),
+          "to read \"TransferFunction\" tag");
+      if (cp != NULL) {
+        if (TIFFFetchData(tif, dp, cp)) {
+          /*
+           * This deals with there being only
+           * one array to apply to all samples.
+           */
+          uint32 c = 1L << td->td_bitspersample;
+          if (dp->tdir_count == c)
+            v = 0L;
+          TIFFSetField(tif, dp->tdir_tag,
+              cp, cp+v, cp+2*v);
+        }
+        _TIFFfree(cp);
+      }
+      break;
+    case TIFFTAG_PAGENUMBER:
+    case TIFFTAG_HALFTONEHINTS:
+    case TIFFTAG_YCBCRSUBSAMPLING:
+    case TIFFTAG_DOTRANGE:
+      (void) TIFFFetchShortPair(tif, dp);
+      break;
+    case TIFFTAG_REFERENCEBLACKWHITE:
+      (void) TIFFFetchRefBlackWhite(tif, dp);
+      break;
+/* BEGIN REV 4.0 COMPATIBILITY */
+    case TIFFTAG_OSUBFILETYPE:
+      v = 0L;
+      switch (TIFFExtractData(tif, dp->tdir_type,
+          dp->tdir_offset)) {
+      case OFILETYPE_REDUCEDIMAGE:
+        v = FILETYPE_REDUCEDIMAGE;
+        break;
+      case OFILETYPE_PAGE:
+        v = FILETYPE_PAGE;
+        break;
+      }
+      if (v)
+        TIFFSetField(tif, TIFFTAG_SUBFILETYPE, v);
+      break;
+/* END REV 4.0 COMPATIBILITY */
+    default:
+      (void) TIFFFetchNormalTag(tif, dp);
+      break;
+    }
+  }
+  /*
+   * Verify Palette image has a Colormap.
+   */
+  if (td->td_photometric == PHOTOMETRIC_PALETTE &&
+      !TIFFFieldSet(tif, FIELD_COLORMAP)) {
+    MissingRequired(tif, "Colormap");
+    goto bad;
+  }
+  /*
+   * Attempt to deal with a missing StripByteCounts tag.
+   */
+  if (!TIFFFieldSet(tif, FIELD_STRIPBYTECOUNTS)) {
+    /*
+     * Some manufacturers violate the spec by not giving
+     * the size of the strips.  In this case, assume there
+     * is one uncompressed strip of data.
+     */
+    if ((td->td_planarconfig == PLANARCONFIG_CONTIG &&
+        td->td_nstrips > 1) ||
+        (td->td_planarconfig == PLANARCONFIG_SEPARATE &&
+         td->td_nstrips != td->td_samplesperpixel)) {
+        MissingRequired(tif, "StripByteCounts");
+        goto bad;
+    }
+    TIFFWarning(module,
+      "%s: TIFF directory is missing required "
+      "\"%s\" field, calculating from imagelength",
+      tif->tif_name,
+            _TIFFFieldWithTag(tif,TIFFTAG_STRIPBYTECOUNTS)->field_name);
+    if (EstimateStripByteCounts(tif, dir, dircount) < 0)
+        goto bad;
+/* 
+ * Assume we have wrong StripByteCount value (in case of single strip) in
+ * following cases:
+ *   - it is equal to zero along with StripOffset;
+ *   - it is larger than file itself (in case of uncompressed image);
+ *   - it is smaller than the size of the bytes per row multiplied on the
+ *     number of rows.  The last case should not be checked in the case of
+ *     writing new image, because we may do not know the exact strip size
+ *     until the whole image will be written and directory dumped out.
+ */
+#define  BYTECOUNTLOOKSBAD \
+    ( (td->td_stripbytecount[0] == 0 && td->td_stripoffset[0] != 0) || \
+      (td->td_compression == COMPRESSION_NONE && \
+       td->td_stripbytecount[0] > TIFFGetFileSize(tif) - td->td_stripoffset[0]) || \
+      (tif->tif_mode == O_RDONLY && \
+       td->td_compression == COMPRESSION_NONE && \
+       td->td_stripbytecount[0] < TIFFScanlineSize(tif) * td->td_imagelength) )
+  } else if (td->td_nstrips == 1 && BYTECOUNTLOOKSBAD) {
+    /*
+     * Plexus (and others) sometimes give a value
+     * of zero for a tag when they don't know what
+     * the correct value is!  Try and handle the
+     * simple case of estimating the size of a one
+     * strip image.
+     */
+    TIFFWarning(module,
+  "%s: Bogus \"%s\" field, ignoring and calculating from imagelength",
+                            tif->tif_name,
+                _TIFFFieldWithTag(tif,TIFFTAG_STRIPBYTECOUNTS)->field_name);
+    if(EstimateStripByteCounts(tif, dir, dircount) < 0)
+        goto bad;
+  }
+  if (dir) {
+    _TIFFfree(dir);
+  }
+  if (!TIFFFieldSet(tif, FIELD_MAXSAMPLEVALUE))
+    td->td_maxsamplevalue = (uint16)((1L<<td->td_bitspersample)-1);
+  /*
+   * Setup default compression scheme.
+   */
+
+  /*
+   * XXX: We can optimize checking for the strip bounds using the sorted
+   * bytecounts array. See also comments for TIFFAppendToStrip()
+   * function in tif_write.c.
+   */
+  if (td->td_nstrips > 1) {
+    tstrip_t strip;
+
+    td->td_stripbytecountsorted = 1;
+    for (strip = 1; strip < td->td_nstrips; strip++) {
+      if (td->td_stripoffset[strip - 1] >
+          td->td_stripoffset[strip]) {
+        td->td_stripbytecountsorted = 0;
+        break;
+      }
+    }
+  }
+
+  if (!TIFFFieldSet(tif, FIELD_COMPRESSION))
+    TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
+        /*
+         * Some manufacturers make life difficult by writing
+   * large amounts of uncompressed data as a single strip.
+   * This is contrary to the recommendations of the spec.
+         * The following makes an attempt at breaking such images
+   * into strips closer to the recommended 8k bytes.  A
+   * side effect, however, is that the RowsPerStrip tag
+   * value may be changed.
+         */
+  if (td->td_nstrips == 1 && td->td_compression == COMPRESSION_NONE &&
+      (tif->tif_flags & (TIFF_STRIPCHOP|TIFF_ISTILED)) == TIFF_STRIPCHOP)
+    ChopUpSingleUncompressedStrip(tif);
+
+  /*
+   * Reinitialize i/o since we are starting on a new directory.
+   */
+  tif->tif_row = (uint32) -1;
+  tif->tif_curstrip = (tstrip_t) -1;
+  tif->tif_col = (uint32) -1;
+  tif->tif_curtile = (ttile_t) -1;
+  tif->tif_tilesize = (tsize_t) -1;
+
+  tif->tif_scanlinesize = TIFFScanlineSize(tif);
+  if (!tif->tif_scanlinesize) {
+    TIFFError(module, "%s: cannot handle zero scanline size",
+        tif->tif_name);
+    return (0);
+  }
+
+  if (isTiled(tif)) {
+    tif->tif_tilesize = TIFFTileSize(tif);
+    if (!tif->tif_tilesize) {
+      TIFFError(module, "%s: cannot handle zero tile size",
+          tif->tif_name);
+      return (0);
+    }
+  } else {
+    if (!TIFFStripSize(tif)) {
+      TIFFError(module, "%s: cannot handle zero strip size",
+          tif->tif_name);
+      return (0);
+    }
+  }
+  return (1);
+bad:
+  if (dir)
+    _TIFFfree(dir);
+  return (0);
+}
+
+static int
+EstimateStripByteCounts(TIFF* tif, TIFFDirEntry* dir, uint16 dircount)
+{
+  static const char module[] = "EstimateStripByteCounts";
+
+  register TIFFDirEntry *dp;
+  register TIFFDirectory *td = &tif->tif_dir;
+  uint16 i;
+
+  if (td->td_stripbytecount)
+    _TIFFfree(td->td_stripbytecount);
+  td->td_stripbytecount = (uint32*)
+      CheckMalloc(tif, td->td_nstrips, sizeof (uint32),
+    "for \"StripByteCounts\" array");
+  if (td->td_compression != COMPRESSION_NONE) {
+    uint32 space = (uint32)(sizeof (TIFFHeader)
+        + sizeof (uint16)
+        + (dircount * sizeof (TIFFDirEntry))
+        + sizeof (uint32));
+    toff_t filesize = TIFFGetFileSize(tif);
+    uint16 n;
+
+    /* calculate amount of space used by indirect values */
+    for (dp = dir, n = dircount; n > 0; n--, dp++)
+    {
+      uint32 cc = TIFFDataWidth((TIFFDataType) dp->tdir_type);
+      if (cc == 0) {
+        TIFFError(module,
+      "%s: Cannot determine size of unknown tag type %d",
+            tif->tif_name, dp->tdir_type);
+        return -1;
+      }
+      cc = cc * dp->tdir_count;
+      if (cc > sizeof (uint32))
+        space += cc;
+    }
+    space = filesize - space;
+    if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
+      space /= td->td_samplesperpixel;
+    for (i = 0; i < td->td_nstrips; i++)
+      td->td_stripbytecount[i] = space;
+    /*
+     * This gross hack handles the case were the offset to
+     * the last strip is past the place where we think the strip
+     * should begin.  Since a strip of data must be contiguous,
+     * it's safe to assume that we've overestimated the amount
+     * of data in the strip and trim this number back accordingly.
+     */ 
+    i--;
+    if (((toff_t)(td->td_stripoffset[i]+td->td_stripbytecount[i]))
+                                                               > filesize)
+      td->td_stripbytecount[i] =
+          filesize - td->td_stripoffset[i];
+  } else {
+    uint32 rowbytes = TIFFScanlineSize(tif);
+    uint32 rowsperstrip = td->td_imagelength/td->td_stripsperimage;
+    for (i = 0; i < td->td_nstrips; i++)
+      td->td_stripbytecount[i] = rowbytes*rowsperstrip;
+  }
+  TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
+  if (!TIFFFieldSet(tif, FIELD_ROWSPERSTRIP))
+    td->td_rowsperstrip = td->td_imagelength;
+  return 1;
+}
+
+static void
+MissingRequired(TIFF* tif, const char* tagname)
+{
+  static const char module[] = "MissingRequired";
+
+  TIFFError(module,
+      "%s: TIFF directory is missing required \"%s\" field",
+      tif->tif_name, tagname);
+}
+
+/*
+ * Check the count field of a directory
+ * entry against a known value.  The caller
+ * is expected to skip/ignore the tag if
+ * there is a mismatch.
+ */
+static int
+CheckDirCount(TIFF* tif, TIFFDirEntry* dir, uint32 count)
+{
+  if (count > dir->tdir_count) {
+    TIFFWarning(tif->tif_name,
+  "incorrect count for field \"%s\" (%lu, expecting %lu); tag ignored",
+        _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name,
+        dir->tdir_count, count);
+    return (0);
+  } else if (count < dir->tdir_count) {
+    TIFFWarning(tif->tif_name,
+  "incorrect count for field \"%s\" (%lu, expecting %lu); tag trimmed",
+        _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name,
+        dir->tdir_count, count);
+    return (1);
+  }
+  return (1);
+}
+
+/*
+ * Fetch a contiguous directory item.
+ */
+static tsize_t
+TIFFFetchData(TIFF* tif, TIFFDirEntry* dir, char* cp)
+{
+  int w = TIFFDataWidth((TIFFDataType) dir->tdir_type);
+  tsize_t cc = dir->tdir_count * w;
+
+  if (!isMapped(tif)) {
+    if (!SeekOK(tif, dir->tdir_offset))
+      goto bad;
+    if (!ReadOK(tif, cp, cc))
+      goto bad;
+  } else {
+    if (dir->tdir_offset + cc > tif->tif_size)
+      goto bad;
+    _TIFFmemcpy(cp, tif->tif_base + dir->tdir_offset, cc);
+  }
+  if (tif->tif_flags & TIFF_SWAB) {
+    switch (dir->tdir_type) {
+    case TIFF_SHORT:
+    case TIFF_SSHORT:
+      TIFFSwabArrayOfShort((uint16*) cp, dir->tdir_count);
+      break;
+    case TIFF_LONG:
+    case TIFF_SLONG:
+    case TIFF_FLOAT:
+      TIFFSwabArrayOfLong((uint32*) cp, dir->tdir_count);
+      break;
+    case TIFF_RATIONAL:
+    case TIFF_SRATIONAL:
+      TIFFSwabArrayOfLong((uint32*) cp, 2*dir->tdir_count);
+      break;
+    case TIFF_DOUBLE:
+      TIFFSwabArrayOfDouble((double*) cp, dir->tdir_count);
+      break;
+    }
+  }
+  return (cc);
+bad:
+  TIFFError(tif->tif_name, "Error fetching data for field \"%s\"",
+      _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
+  return ((tsize_t) 0);
+}
+
+/*
+ * Fetch an ASCII item from the file.
+ */
+static tsize_t
+TIFFFetchString(TIFF* tif, TIFFDirEntry* dir, char* cp)
+{
+  if (dir->tdir_count <= 4) {
+    uint32 l = dir->tdir_offset;
+    if (tif->tif_flags & TIFF_SWAB)
+      TIFFSwabLong(&l);
+    _TIFFmemcpy(cp, &l, dir->tdir_count);
+    return (1);
+  }
+  return (TIFFFetchData(tif, dir, cp));
+}
+
+/*
+ * Convert numerator+denominator to float.
+ */
+static int
+cvtRational(TIFF* tif, TIFFDirEntry* dir, uint32 num, uint32 denom, float* rv)
+{
+  if (denom == 0) {
+    TIFFError(tif->tif_name,
+        "%s: Rational with zero denominator (num = %lu)",
+        _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name, num);
+    return (0);
+  } else {
+    if (dir->tdir_type == TIFF_RATIONAL)
+      *rv = ((float)num / (float)denom);
+    else
+      *rv = ((float)(int32)num / (float)(int32)denom);
+    return (1);
+  }
+}
+
+/*
+ * Fetch a rational item from the file
+ * at offset off and return the value
+ * as a floating point number.
+ */
+static float
+TIFFFetchRational(TIFF* tif, TIFFDirEntry* dir)
+{
+  uint32 l[2];
+  float v;
+
+  return (!TIFFFetchData(tif, dir, (char *)l) ||
+      !cvtRational(tif, dir, l[0], l[1], &v) ? 1.0f : v);
+}
+
+/*
+ * Fetch a single floating point value
+ * from the offset field and return it
+ * as a native float.
+ */
+static float
+TIFFFetchFloat(TIFF* tif, TIFFDirEntry* dir)
+{
+  float v;
+  int32 l = TIFFExtractData(tif, dir->tdir_type, dir->tdir_offset);
+        _TIFFmemcpy(&v, &l, sizeof(float));
+  TIFFCvtIEEEFloatToNative(tif, 1, &v);
+  return (v);
+}
+
+/*
+ * Fetch an array of BYTE or SBYTE values.
+ */
+static int
+TIFFFetchByteArray(TIFF* tif, TIFFDirEntry* dir, uint16* v)
+{
+    if (dir->tdir_count <= 4) {
+        /*
+         * Extract data from offset field.
+         */
+        if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) {
+      if (dir->tdir_type == TIFF_SBYTE)
+                switch (dir->tdir_count) {
+                    case 4: v[3] = (signed char)(dir->tdir_offset & 0xff);
+                    case 3: v[2] = (signed char)((dir->tdir_offset >> 8) & 0xff);
+                    case 2: v[1] = (signed char)((dir->tdir_offset >> 16) & 0xff);
+        case 1: v[0] = (signed char)(dir->tdir_offset >> 24);  
+                }
+      else
+                switch (dir->tdir_count) {
+                    case 4: v[3] = (uint16)(dir->tdir_offset & 0xff);
+                    case 3: v[2] = (uint16)((dir->tdir_offset >> 8) & 0xff);
+                    case 2: v[1] = (uint16)((dir->tdir_offset >> 16) & 0xff);
+        case 1: v[0] = (uint16)(dir->tdir_offset >> 24);  
+                }
+  } else {
+      if (dir->tdir_type == TIFF_SBYTE)
+                switch (dir->tdir_count) {
+                    case 4: v[3] = (signed char)(dir->tdir_offset >> 24);
+                    case 3: v[2] = (signed char)((dir->tdir_offset >> 16) & 0xff);
+                    case 2: v[1] = (signed char)((dir->tdir_offset >> 8) & 0xff);
+                    case 1: v[0] = (signed char)(dir->tdir_offset & 0xff);
+    }
+      else
+                switch (dir->tdir_count) {
+                    case 4: v[3] = (uint16)(dir->tdir_offset >> 24);
+                    case 3: v[2] = (uint16)((dir->tdir_offset >> 16) & 0xff);
+                    case 2: v[1] = (uint16)((dir->tdir_offset >> 8) & 0xff);
+                    case 1: v[0] = (uint16)(dir->tdir_offset & 0xff);
+    }
+  }
+        return (1);
+    } else
+        return (TIFFFetchData(tif, dir, (char*) v) != 0);  /* XXX */
+}
+
+/*
+ * Fetch an array of SHORT or SSHORT values.
+ */
+static int
+TIFFFetchShortArray(TIFF* tif, TIFFDirEntry* dir, uint16* v)
+{
+  if (dir->tdir_count <= 2) {
+    if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) {
+      switch (dir->tdir_count) {
+      case 2: v[1] = (uint16) (dir->tdir_offset & 0xffff);
+      case 1: v[0] = (uint16) (dir->tdir_offset >> 16);
+      }
+    } else {
+      switch (dir->tdir_count) {
+      case 2: v[1] = (uint16) (dir->tdir_offset >> 16);
+      case 1: v[0] = (uint16) (dir->tdir_offset & 0xffff);
+      }
+    }
+    return (1);
+  } else
+    return (TIFFFetchData(tif, dir, (char *)v) != 0);
+}
+
+/*
+ * Fetch a pair of SHORT or BYTE values.
+ */
+static int
+TIFFFetchShortPair(TIFF* tif, TIFFDirEntry* dir)
+{
+  uint16 v[4];
+  int ok = 0;
+
+  switch (dir->tdir_type) {
+  case TIFF_SHORT:
+  case TIFF_SSHORT:
+    ok = TIFFFetchShortArray(tif, dir, v);
+    break;
+  case TIFF_BYTE:
+  case TIFF_SBYTE:
+    ok  = TIFFFetchByteArray(tif, dir, v);
+    break;
+  }
+  if (ok)
+    TIFFSetField(tif, dir->tdir_tag, v[0], v[1]);
+  return (ok);
+}
+
+/*
+ * Fetch an array of LONG or SLONG values.
+ */
+static int
+TIFFFetchLongArray(TIFF* tif, TIFFDirEntry* dir, uint32* v)
+{
+  if (dir->tdir_count == 1) {
+    v[0] = dir->tdir_offset;
+    return (1);
+  } else
+    return (TIFFFetchData(tif, dir, (char*) v) != 0);
+}
+
+/*
+ * Fetch an array of RATIONAL or SRATIONAL values.
+ */
+static int
+TIFFFetchRationalArray(TIFF* tif, TIFFDirEntry* dir, float* v)
+{
+  int ok = 0;
+  uint32* l;
+
+  l = (uint32*)CheckMalloc(tif,
+      dir->tdir_count, TIFFDataWidth((TIFFDataType) dir->tdir_type),
+      "to fetch array of rationals");
+  if (l) {
+    if (TIFFFetchData(tif, dir, (char *)l)) {
+      uint32 i;
+      for (i = 0; i < dir->tdir_count; i++) {
+        ok = cvtRational(tif, dir,
+            l[2*i+0], l[2*i+1], &v[i]);
+        if (!ok)
+          break;
+      }
+    }
+    _TIFFfree((char *)l);
+  }
+  return (ok);
+}
+
+/*
+ * Fetch an array of FLOAT values.
+ */
+static int
+TIFFFetchFloatArray(TIFF* tif, TIFFDirEntry* dir, float* v)
+{
+
+  if (dir->tdir_count == 1) {
+    v[0] = *(float*) &dir->tdir_offset;
+    TIFFCvtIEEEFloatToNative(tif, dir->tdir_count, v);
+    return (1);
+  } else  if (TIFFFetchData(tif, dir, (char*) v)) {
+    TIFFCvtIEEEFloatToNative(tif, dir->tdir_count, v);
+    return (1);
+  } else
+    return (0);
+}
+
+/*
+ * Fetch an array of DOUBLE values.
+ */
+static int
+TIFFFetchDoubleArray(TIFF* tif, TIFFDirEntry* dir, double* v)
+{
+  if (TIFFFetchData(tif, dir, (char*) v)) {
+    TIFFCvtIEEEDoubleToNative(tif, dir->tdir_count, v);
+    return (1);
+  } else
+    return (0);
+}
+
+/*
+ * Fetch an array of ANY values.  The actual values are
+ * returned as doubles which should be able hold all the
+ * types.  Yes, there really should be an tany_t to avoid
+ * this potential non-portability ...  Note in particular
+ * that we assume that the double return value vector is
+ * large enough to read in any fundamental type.  We use
+ * that vector as a buffer to read in the base type vector
+ * and then convert it in place to double (from end
+ * to front of course).
+ */
+static int
+TIFFFetchAnyArray(TIFF* tif, TIFFDirEntry* dir, double* v)
+{
+  int i;
+
+  switch (dir->tdir_type) {
+  case TIFF_BYTE:
+  case TIFF_SBYTE:
+    if (!TIFFFetchByteArray(tif, dir, (uint16*) v))
+      return (0);
+    if (dir->tdir_type == TIFF_BYTE) {
+      uint16* vp = (uint16*) v;
+      for (i = dir->tdir_count-1; i >= 0; i--)
+        v[i] = vp[i];
+    } else {
+      int16* vp = (int16*) v;
+      for (i = dir->tdir_count-1; i >= 0; i--)
+        v[i] = vp[i];
+    }
+    break;
+  case TIFF_SHORT:
+  case TIFF_SSHORT:
+    if (!TIFFFetchShortArray(tif, dir, (uint16*) v))
+      return (0);
+    if (dir->tdir_type == TIFF_SHORT) {
+      uint16* vp = (uint16*) v;
+      for (i = dir->tdir_count-1; i >= 0; i--)
+        v[i] = vp[i];
+    } else {
+      int16* vp = (int16*) v;
+      for (i = dir->tdir_count-1; i >= 0; i--)
+        v[i] = vp[i];
+    }
+    break;
+  case TIFF_LONG:
+  case TIFF_SLONG:
+    if (!TIFFFetchLongArray(tif, dir, (uint32*) v))
+      return (0);
+    if (dir->tdir_type == TIFF_LONG) {
+      uint32* vp = (uint32*) v;
+      for (i = dir->tdir_count-1; i >= 0; i--)
+        v[i] = vp[i];
+    } else {
+      int32* vp = (int32*) v;
+      for (i = dir->tdir_count-1; i >= 0; i--)
+        v[i] = vp[i];
+    }
+    break;
+  case TIFF_RATIONAL:
+  case TIFF_SRATIONAL:
+    if (!TIFFFetchRationalArray(tif, dir, (float*) v))
+      return (0);
+    { float* vp = (float*) v;
+      for (i = dir->tdir_count-1; i >= 0; i--)
+      v[i] = vp[i];
+    }
+    break;
+  case TIFF_FLOAT:
+    if (!TIFFFetchFloatArray(tif, dir, (float*) v))
+      return (0);
+    { float* vp = (float*) v;
+      for (i = dir->tdir_count-1; i >= 0; i--)
+      v[i] = vp[i];
+    }
+    break;
+  case TIFF_DOUBLE:
+    return (TIFFFetchDoubleArray(tif, dir, (double*) v));
+  default:
+    /* TIFF_NOTYPE */
+    /* TIFF_ASCII */
+    /* TIFF_UNDEFINED */
+    TIFFError(tif->tif_name,
+        "cannot read TIFF_ANY type %d for field \"%s\"",
+        _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
+    return (0);
+  }
+  return (1);
+}
+
+/*
+ * Fetch a tag that is not handled by special case code.
+ */
+static int
+TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp)
+{
+  static const char mesg[] = "to fetch tag value";
+  int ok = 0;
+  const TIFFFieldInfo* fip = _TIFFFieldWithTag(tif, dp->tdir_tag);
+
+  if (dp->tdir_count > 1) {    /* array of values */
+    char* cp = NULL;
+
+    switch (dp->tdir_type) {
+    case TIFF_BYTE:
+    case TIFF_SBYTE:
+      /* NB: always expand BYTE values to shorts */
+      cp = CheckMalloc(tif,
+          dp->tdir_count, sizeof (uint16), mesg);
+      ok = cp && TIFFFetchByteArray(tif, dp, (uint16*) cp);
+      break;
+    case TIFF_SHORT:
+    case TIFF_SSHORT:
+      cp = CheckMalloc(tif,
+          dp->tdir_count, sizeof (uint16), mesg);
+      ok = cp && TIFFFetchShortArray(tif, dp, (uint16*) cp);
+      break;
+    case TIFF_LONG:
+    case TIFF_SLONG:
+      cp = CheckMalloc(tif,
+          dp->tdir_count, sizeof (uint32), mesg);
+      ok = cp && TIFFFetchLongArray(tif, dp, (uint32*) cp);
+      break;
+    case TIFF_RATIONAL:
+    case TIFF_SRATIONAL:
+      cp = CheckMalloc(tif,
+          dp->tdir_count, sizeof (float), mesg);
+      ok = cp && TIFFFetchRationalArray(tif, dp, (float*) cp);
+      break;
+    case TIFF_FLOAT:
+      cp = CheckMalloc(tif,
+          dp->tdir_count, sizeof (float), mesg);
+      ok = cp && TIFFFetchFloatArray(tif, dp, (float*) cp);
+      break;
+    case TIFF_DOUBLE:
+      cp = CheckMalloc(tif,
+          dp->tdir_count, sizeof (double), mesg);
+      ok = cp && TIFFFetchDoubleArray(tif, dp, (double*) cp);
+      break;
+    case TIFF_ASCII:
+    case TIFF_UNDEFINED:    /* bit of a cheat... */
+      /*
+       * Some vendors write strings w/o the trailing
+       * NULL byte, so always append one just in case.
+       */
+      cp = CheckMalloc(tif, dp->tdir_count+1, 1, mesg);
+      if( (ok = (cp && TIFFFetchString(tif, dp, cp))) != 0 )
+        cp[dp->tdir_count] = '\0';  /* XXX */
+      break;
+    }
+    if (ok) {
+      ok = (fip->field_passcount ?
+          TIFFSetField(tif, dp->tdir_tag, dp->tdir_count, cp)
+        : TIFFSetField(tif, dp->tdir_tag, cp));
+    }
+    if (cp != NULL)
+      _TIFFfree(cp);
+  } else if (CheckDirCount(tif, dp, 1)) {  /* singleton value */
+    switch (dp->tdir_type) {
+    case TIFF_BYTE:
+    case TIFF_SBYTE:
+    case TIFF_SHORT:
+    case TIFF_SSHORT:
+      /*
+       * If the tag is also acceptable as a LONG or SLONG
+       * then TIFFSetField will expect an uint32 parameter
+       * passed to it (through varargs).  Thus, for machines
+       * where sizeof (int) != sizeof (uint32) we must do
+       * a careful check here.  It's hard to say if this
+       * is worth optimizing.
+       *
+       * NB: We use TIFFFieldWithTag here knowing that
+       *     it returns us the first entry in the table
+       *     for the tag and that that entry is for the
+       *     widest potential data type the tag may have.
+       */
+      { TIFFDataType type = fip->field_type;
+        if (type != TIFF_LONG && type != TIFF_SLONG) {
+        uint16 v = (uint16)
+         TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset);
+        ok = (fip->field_passcount ?
+            TIFFSetField(tif, dp->tdir_tag, 1, &v)
+          : TIFFSetField(tif, dp->tdir_tag, v));
+        break;
+        }
+      }
+      /* fall thru... */
+    case TIFF_LONG:
+    case TIFF_SLONG:
+      { uint32 v32 =
+        TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset);
+        ok = (fip->field_passcount ? 
+            TIFFSetField(tif, dp->tdir_tag, 1, &v32)
+          : TIFFSetField(tif, dp->tdir_tag, v32));
+      }
+      break;
+    case TIFF_RATIONAL:
+    case TIFF_SRATIONAL:
+    case TIFF_FLOAT:
+      { float v = (dp->tdir_type == TIFF_FLOAT ? 
+            TIFFFetchFloat(tif, dp)
+          : TIFFFetchRational(tif, dp));
+        ok = (fip->field_passcount ?
+            TIFFSetField(tif, dp->tdir_tag, 1, &v)
+          : TIFFSetField(tif, dp->tdir_tag, v));
+      }
+      break;
+    case TIFF_DOUBLE:
+      { double v;
+        ok = (TIFFFetchDoubleArray(tif, dp, &v) &&
+          (fip->field_passcount ?
+            TIFFSetField(tif, dp->tdir_tag, 1, &v)
+          : TIFFSetField(tif, dp->tdir_tag, v))
+        );
+      }
+      break;
+    case TIFF_ASCII:
+    case TIFF_UNDEFINED:    /* bit of a cheat... */
+      { char c[2];
+        if( (ok = (TIFFFetchString(tif, dp, c) != 0)) != 0 ) {
+        c[1] = '\0';    /* XXX paranoid */
+        ok = (fip->field_passcount ?
+          TIFFSetField(tif, dp->tdir_tag, 1, c)
+              : TIFFSetField(tif, dp->tdir_tag, c));
+        }
+      }
+      break;
+    }
+  }
+  return (ok);
+}
+
+#define  NITEMS(x)  (sizeof (x) / sizeof (x[0]))
+/*
+ * Fetch samples/pixel short values for 
+ * the specified tag and verify that
+ * all values are the same.
+ */
+static int
+TIFFFetchPerSampleShorts(TIFF* tif, TIFFDirEntry* dir, uint16* pl)
+{
+  uint16 samples = tif->tif_dir.td_samplesperpixel;
+  int status = 0;
+
+  if (CheckDirCount(tif, dir, (uint32) samples)) {
+    uint16 buf[10];
+    uint16* v = buf;
+
+    if (samples > NITEMS(buf))
+      v = (uint16*) CheckMalloc(tif, samples, sizeof(uint16),
+              "to fetch per-sample values");
+    if (v && TIFFFetchShortArray(tif, dir, v)) {
+      uint16 i;
+      for (i = 1; i < samples; i++)
+        if (v[i] != v[0]) {
+          TIFFError(tif->tif_name,
+    "Cannot handle different per-sample values for field \"%s\"",
+         _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
+          goto bad;
+        }
+      *pl = v[0];
+      status = 1;
+    }
+  bad:
+    if (v && v != buf)
+      _TIFFfree(v);
+  }
+  return (status);
+}
+
+/*
+ * Fetch samples/pixel long values for 
+ * the specified tag and verify that
+ * all values are the same.
+ */
+static int
+TIFFFetchPerSampleLongs(TIFF* tif, TIFFDirEntry* dir, uint32* pl)
+{
+  uint16 samples = tif->tif_dir.td_samplesperpixel;
+  int status = 0;
+
+  if (CheckDirCount(tif, dir, (uint32) samples)) {
+    uint32 buf[10];
+    uint32* v = buf;
+
+    if (samples > NITEMS(buf))
+      v = (uint32*) CheckMalloc(tif, samples, sizeof(uint32),
+              "to fetch per-sample values");
+    if (v && TIFFFetchLongArray(tif, dir, v)) {
+      uint16 i;
+      for (i = 1; i < samples; i++)
+        if (v[i] != v[0]) {
+          TIFFError(tif->tif_name,
+    "Cannot handle different per-sample values for field \"%s\"",
+         _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
+          goto bad;
+        }
+      *pl = v[0];
+      status = 1;
+    }
+  bad:
+    if (v && v != buf)
+      _TIFFfree(v);
+  }
+  return (status);
+}
+
+/*
+ * Fetch samples/pixel ANY values for 
+ * the specified tag and verify that
+ * all values are the same.
+ */
+static int
+TIFFFetchPerSampleAnys(TIFF* tif, TIFFDirEntry* dir, double* pl)
+{
+  uint16 samples = tif->tif_dir.td_samplesperpixel;
+  int status = 0;
+
+  if (CheckDirCount(tif, dir, (uint32) samples)) {
+    double buf[10];
+    double* v = buf;
+
+    if (samples > NITEMS(buf))
+      v = (double*) CheckMalloc(tif, samples, sizeof (double),
+              "to fetch per-sample values");
+    if (v && TIFFFetchAnyArray(tif, dir, v)) {
+      uint16 i;
+      for (i = 1; i < samples; i++)
+        if (v[i] != v[0]) {
+          TIFFError(tif->tif_name,
+    "Cannot handle different per-sample values for field \"%s\"",
+         _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
+          goto bad;
+        }
+      *pl = v[0];
+      status = 1;
+    }
+  bad:
+    if (v && v != buf)
+      _TIFFfree(v);
+  }
+  return (status);
+}
+#undef NITEMS
+
+/*
+ * Fetch a set of offsets or lengths.
+ * While this routine says "strips", in fact it's also used for tiles.
+ */
+static int
+TIFFFetchStripThing(TIFF* tif, TIFFDirEntry* dir, long nstrips, uint32** lpp)
+{
+  register uint32* lp;
+  int status;
+
+        CheckDirCount(tif, dir, (uint32) nstrips);
+
+  /*
+   * Allocate space for strip information.
+   */
+  if (*lpp == NULL &&
+      (*lpp = (uint32 *)CheckMalloc(tif,
+        nstrips, sizeof (uint32), "for strip array")) == NULL)
+    return (0);
+  lp = *lpp;
+        _TIFFmemset( lp, 0, sizeof(uint32) * nstrips );
+
+  if (dir->tdir_type == (int)TIFF_SHORT) {
+    /*
+     * Handle uint16->uint32 expansion.
+     */
+    uint16* dp = (uint16*) CheckMalloc(tif,
+        dir->tdir_count, sizeof (uint16), "to fetch strip tag");
+    if (dp == NULL)
+      return (0);
+    if( (status = TIFFFetchShortArray(tif, dir, dp)) != 0 ) {
+                    int i;
+                    
+                    for( i = 0; i < nstrips && i < (int) dir->tdir_count; i++ )
+                    {
+                        lp[i] = dp[i];
+                    }
+    }
+    _TIFFfree((char*) dp);
+
+        } else if( nstrips != (int) dir->tdir_count ) {
+            /* Special case to correct length */
+
+            uint32* dp = (uint32*) CheckMalloc(tif,
+        dir->tdir_count, sizeof (uint32), "to fetch strip tag");
+            if (dp == NULL)
+                return (0);
+
+            status = TIFFFetchLongArray(tif, dir, dp);
+            if( status != 0 ) {
+                int i;
+
+                for( i = 0; i < nstrips && i < (int) dir->tdir_count; i++ )
+                {
+                    lp[i] = dp[i];
+                }
+            }
+
+            _TIFFfree( (char *) dp );
+  } else
+            status = TIFFFetchLongArray(tif, dir, lp);
+        
+  return (status);
+}
+
+#define  NITEMS(x)  (sizeof (x) / sizeof (x[0]))
+/*
+ * Fetch and set the ExtraSamples tag.
+ */
+static int
+TIFFFetchExtraSamples(TIFF* tif, TIFFDirEntry* dir)
+{
+  uint16 buf[10];
+  uint16* v = buf;
+  int status;
+
+  if (dir->tdir_count > NITEMS(buf)) {
+    v = (uint16*) CheckMalloc(tif, dir->tdir_count, sizeof (uint16),
+            "to fetch extra samples");
+    if (!v)
+      return (0);
+  }
+  if (dir->tdir_type == TIFF_BYTE)
+    status = TIFFFetchByteArray(tif, dir, v);
+  else
+    status = TIFFFetchShortArray(tif, dir, v);
+  if (status)
+    status = TIFFSetField(tif, dir->tdir_tag, dir->tdir_count, v);
+  if (v != buf)
+    _TIFFfree((char*) v);
+  return (status);
+}
+#undef NITEMS
+
+/*
+ * Fetch and set the RefBlackWhite tag.
+ */
+static int
+TIFFFetchRefBlackWhite(TIFF* tif, TIFFDirEntry* dir)
+{
+  static const char mesg[] = "for \"ReferenceBlackWhite\" array";
+  char* cp;
+  int ok;
+
+  if (dir->tdir_type == TIFF_RATIONAL)
+    return (TIFFFetchNormalTag(tif, dir));
+  /*
+   * Handle LONG's for backward compatibility.
+   */
+  cp = CheckMalloc(tif, dir->tdir_count, sizeof (uint32), mesg);
+  if( (ok = (cp && TIFFFetchLongArray(tif, dir, (uint32*) cp))) != 0) {
+    float* fp = (float*)
+        CheckMalloc(tif, dir->tdir_count, sizeof (float), mesg);
+    if( (ok = (fp != NULL)) != 0 ) {
+      uint32 i;
+      for (i = 0; i < dir->tdir_count; i++)
+        fp[i] = (float)((uint32*) cp)[i];
+      ok = TIFFSetField(tif, dir->tdir_tag, fp);
+      _TIFFfree((char*) fp);
+    }
+  }
+  if (cp)
+    _TIFFfree(cp);
+  return (ok);
+}
+
+/*
+ * Replace a single strip (tile) of uncompressed data by
+ * multiple strips (tiles), each approximately 8Kbytes.
+ * This is useful for dealing with large images or
+ * for dealing with machines with a limited amount
+ * memory.
+ */
+static void
+ChopUpSingleUncompressedStrip(TIFF* tif)
+{
+  register TIFFDirectory *td = &tif->tif_dir;
+  uint32 bytecount = td->td_stripbytecount[0];
+  uint32 offset = td->td_stripoffset[0];
+  tsize_t rowbytes = TIFFVTileSize(tif, 1), stripbytes;
+  tstrip_t strip, nstrips, rowsperstrip;
+  uint32* newcounts;
+  uint32* newoffsets;
+
+  /*
+   * Make the rows hold at least one
+   * scanline, but fill 8k if possible.
+   */
+  if (rowbytes > 8192) {
+    stripbytes = rowbytes;
+    rowsperstrip = 1;
+  } else if (rowbytes > 0 ) {
+    rowsperstrip = 8192 / rowbytes;
+    stripbytes = rowbytes * rowsperstrip;
+  }
+        else
+            return;
+
+  /* never increase the number of strips in an image */
+  if (rowsperstrip >= td->td_rowsperstrip)
+    return;
+  nstrips = (tstrip_t) TIFFhowmany(bytecount, stripbytes);
+  newcounts = (uint32*) CheckMalloc(tif, nstrips, sizeof (uint32),
+        "for chopped \"StripByteCounts\" array");
+  newoffsets = (uint32*) CheckMalloc(tif, nstrips, sizeof (uint32),
+        "for chopped \"StripOffsets\" array");
+  if (newcounts == NULL || newoffsets == NULL) {
+          /*
+     * Unable to allocate new strip information, give
+     * up and use the original one strip information.
+     */
+    if (newcounts != NULL)
+      _TIFFfree(newcounts);
+    if (newoffsets != NULL)
+      _TIFFfree(newoffsets);
+    return;
+  }
+  /*
+   * Fill the strip information arrays with
+   * new bytecounts and offsets that reflect
+   * the broken-up format.
+   */
+  for (strip = 0; strip < nstrips; strip++) {
+    if (stripbytes > (tsize_t) bytecount)
+      stripbytes = bytecount;
+    newcounts[strip] = stripbytes;
+    newoffsets[strip] = offset;
+    offset += stripbytes;
+    bytecount -= stripbytes;
+  }
+  /*
+   * Replace old single strip info with multi-strip info.
+   */
+  td->td_stripsperimage = td->td_nstrips = nstrips;
+  TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
+
+  _TIFFfree(td->td_stripbytecount);
+  _TIFFfree(td->td_stripoffset);
+  td->td_stripbytecount = newcounts;
+  td->td_stripoffset = newoffsets;
+  td->td_stripbytecountsorted = 1;
+}
+
diff --git a/Utilities/ITK/Utilities/tiff/tif_dirwrite.c b/Utilities/ITK/Utilities/tiff/tif_dirwrite.c
new file mode 100644
index 0000000000..6d61ee8282
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_dirwrite.c
@@ -0,0 +1,1237 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ *
+ * Directory Write Support Routines.
+ */
+#include "tiffiop.h"
+
+#if HAVE_IEEEFP
+#define  itk_TIFFCvtNativeToIEEEFloat(tif, n, fp)
+#define  itk_TIFFCvtNativeToIEEEDouble(tif, n, dp)
+#else
+extern  void itk_TIFFCvtNativeToIEEEFloat(TIFF*, uint32, float*);
+extern  void itk_TIFFCvtNativeToIEEEDouble(TIFF*, uint32, double*);
+#endif
+
+static  int TIFFWriteNormalTag(TIFF*, TIFFDirEntry*, const TIFFFieldInfo*);
+static  void TIFFSetupShortLong(TIFF*, ttag_t, TIFFDirEntry*, uint32);
+static  void TIFFSetupShort(TIFF*, ttag_t, TIFFDirEntry*, uint16);
+static  int TIFFSetupShortPair(TIFF*, ttag_t, TIFFDirEntry*);
+static  int TIFFWritePerSampleShorts(TIFF*, ttag_t, TIFFDirEntry*);
+static  int TIFFWritePerSampleAnys(TIFF*, TIFFDataType, ttag_t, TIFFDirEntry*);
+static  int TIFFWriteShortTable(TIFF*, ttag_t, TIFFDirEntry*, uint32, uint16**);
+static  int TIFFWriteShortArray(TIFF*, TIFFDirEntry*, uint16*);
+static  int TIFFWriteLongArray(TIFF *, TIFFDirEntry*, uint32*);
+static  int TIFFWriteRationalArray(TIFF *, TIFFDirEntry*, float*);
+static  int TIFFWriteFloatArray(TIFF *, TIFFDirEntry*, float*);
+static  int TIFFWriteDoubleArray(TIFF *, TIFFDirEntry*, double*);
+static  int TIFFWriteByteArray(TIFF*, TIFFDirEntry*, char*);
+static  int TIFFWriteAnyArray(TIFF*,
+      TIFFDataType, ttag_t, TIFFDirEntry*, uint32, double*);
+static  int TIFFWriteTransferFunction(TIFF*, TIFFDirEntry*);
+static  int TIFFWriteInkNames(TIFF*, TIFFDirEntry*);
+static  int TIFFWriteData(TIFF*, TIFFDirEntry*, char*);
+static  int TIFFLinkDirectory(TIFF*);
+
+#define  WriteRationalPair(type, tag1, v1, tag2, v2) {    \
+  TIFFWriteRational((tif), (type), (tag1), (dir), (v1))  \
+  TIFFWriteRational((tif), (type), (tag2), (dir)+1, (v2))  \
+  (dir)++;            \
+}
+#define  TIFFWriteRational(tif, type, tag, dir, v)    \
+  (dir)->tdir_tag = (tag);        \
+  (dir)->tdir_type = (type);        \
+  (dir)->tdir_count = 1;          \
+  if (!TIFFWriteRationalArray((tif), (dir), &(v)))  \
+    goto bad;
+
+/*
+ * Write the contents of the current directory
+ * to the specified file.  This routine doesn't
+ * handle overwriting a directory with auxiliary
+ * storage that's been changed.
+ */
+static int
+_TIFFWriteDirectory(TIFF* tif, int done)
+{
+  uint16 dircount;
+  toff_t diroff;
+  ttag_t tag;
+  uint32 nfields;
+  tsize_t dirsize;
+  char* data;
+  TIFFDirEntry* dir;
+  TIFFDirectory* td;
+  unsigned long b, fields[FIELD_SETLONGS];
+  int fi, nfi;
+
+  if (tif->tif_mode == O_RDONLY)
+    return (1);
+  /*
+   * Clear write state so that subsequent images with
+   * different characteristics get the right buffers
+   * setup for them.
+   */
+  if (done)
+  {
+      if (tif->tif_flags & TIFF_POSTENCODE) {
+        tif->tif_flags &= ~TIFF_POSTENCODE;
+        if (!(*tif->tif_postencode)(tif)) {
+          TIFFError(tif->tif_name,
+        "Error post-encoding before directory write");
+          return (0);
+        }
+      }
+      (*tif->tif_close)(tif);    /* shutdown encoder */
+      /*
+       * Flush any data that might have been written
+       * by the compression close+cleanup routines.
+       */
+      if (tif->tif_rawcc > 0 && !TIFFFlushData1(tif)) {
+        TIFFError(tif->tif_name,
+      "Error flushing data before directory write");
+        return (0);
+      }
+      if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) {
+        _TIFFfree(tif->tif_rawdata);
+        tif->tif_rawdata = NULL;
+        tif->tif_rawcc = 0;
+        tif->tif_rawdatasize = 0;
+      }
+      tif->tif_flags &= ~(TIFF_BEENWRITING|TIFF_BUFFERSETUP);
+  }
+
+  td = &tif->tif_dir;
+  /*
+   * Size the directory so that we can calculate
+   * offsets for the data items that aren't kept
+   * in-place in each field.
+   */
+  nfields = 0;
+  for (b = 0; b <= FIELD_LAST; b++)
+    if (TIFFFieldSet(tif, b) && b != FIELD_CUSTOM)
+      nfields += (b < FIELD_SUBFILETYPE ? 2 : 1);
+        nfields += td->td_customValueCount;
+  dirsize = nfields * sizeof (TIFFDirEntry);
+  data = (char*) _TIFFmalloc(dirsize);
+  if (data == NULL) {
+    TIFFError(tif->tif_name,
+        "Cannot write directory, out of space");
+    return (0);
+  }
+  /*
+   * Directory hasn't been placed yet, put
+   * it at the end of the file and link it
+   * into the existing directory structure.
+   */
+  if (tif->tif_diroff == 0 && !TIFFLinkDirectory(tif))
+    goto bad;
+  tif->tif_dataoff = (toff_t)(
+      tif->tif_diroff + sizeof (uint16) + dirsize + sizeof (toff_t));
+  if (tif->tif_dataoff & 1)
+    tif->tif_dataoff++;
+  (void) TIFFSeekFile(tif, tif->tif_dataoff, SEEK_SET);
+  tif->tif_curdir++;
+  dir = (TIFFDirEntry*) data;
+  /*
+   * Setup external form of directory
+   * entries and write data items.
+   */
+  _TIFFmemcpy(fields, td->td_fieldsset, sizeof (fields));
+  /*
+   * Write out ExtraSamples tag only if
+   * extra samples are present in the data.
+   */
+  if (FieldSet(fields, FIELD_EXTRASAMPLES) && !td->td_extrasamples) {
+    ResetFieldBit(fields, FIELD_EXTRASAMPLES);
+    nfields--;
+    dirsize -= sizeof (TIFFDirEntry);
+  }                /*XXX*/
+  for (fi = 0, nfi = tif->tif_nfields; nfi > 0; nfi--, fi++) {
+    const TIFFFieldInfo* fip = tif->tif_fieldinfo[fi];
+
+                /*
+                ** For custom fields, we test to see if the custom field
+                ** is set or not.  For normal fields, we just use the
+                ** FieldSet test. 
+                */
+                if( fip->field_bit == FIELD_CUSTOM )
+                {
+                    int ci, is_set = FALSE;
+
+                    for( ci = 0; ci < td->td_customValueCount; ci++ )
+                        is_set |= (td->td_customValues[ci].info == fip);
+
+                    if( !is_set )
+                        continue;
+                }
+    else if (!FieldSet(fields, fip->field_bit))
+                    continue;
+
+
+                /*
+                ** Handle other fields.
+                */
+    switch (fip->field_bit)
+                {
+    case FIELD_STRIPOFFSETS:
+      /*
+       * We use one field bit for both strip and tile
+
+       * offsets, and so must be careful in selecting
+       * the appropriate field descriptor (so that tags
+       * are written in sorted order).
+       */
+      tag = isTiled(tif) ?
+          TIFFTAG_TILEOFFSETS : TIFFTAG_STRIPOFFSETS;
+      if (tag != fip->field_tag)
+        continue;
+      
+      dir->tdir_tag = (uint16) tag;
+      dir->tdir_type = (uint16) TIFF_LONG;
+      dir->tdir_count = (uint32) td->td_nstrips;
+      if (!TIFFWriteLongArray(tif, dir, td->td_stripoffset))
+        goto bad;
+      break;
+    case FIELD_STRIPBYTECOUNTS:
+      /*
+       * We use one field bit for both strip and tile
+       * byte counts, and so must be careful in selecting
+       * the appropriate field descriptor (so that tags
+       * are written in sorted order).
+       */
+      tag = isTiled(tif) ?
+          TIFFTAG_TILEBYTECOUNTS : TIFFTAG_STRIPBYTECOUNTS;
+      if (tag != fip->field_tag)
+        continue;
+      
+      dir->tdir_tag = (uint16) tag;
+      dir->tdir_type = (uint16) TIFF_LONG;
+      dir->tdir_count = (uint32) td->td_nstrips;
+      if (!TIFFWriteLongArray(tif, dir,
+            td->td_stripbytecount))
+        goto bad;
+      break;
+    case FIELD_ROWSPERSTRIP:
+      TIFFSetupShortLong(tif, TIFFTAG_ROWSPERSTRIP,
+          dir, td->td_rowsperstrip);
+      break;
+    case FIELD_COLORMAP:
+      if (!TIFFWriteShortTable(tif, TIFFTAG_COLORMAP, dir,
+          3, td->td_colormap))
+        goto bad;
+      break;
+    case FIELD_IMAGEDIMENSIONS:
+      TIFFSetupShortLong(tif, TIFFTAG_IMAGEWIDTH,
+          dir++, td->td_imagewidth);
+      TIFFSetupShortLong(tif, TIFFTAG_IMAGELENGTH,
+          dir, td->td_imagelength);
+      break;
+    case FIELD_TILEDIMENSIONS:
+      TIFFSetupShortLong(tif, TIFFTAG_TILEWIDTH,
+          dir++, td->td_tilewidth);
+      TIFFSetupShortLong(tif, TIFFTAG_TILELENGTH,
+          dir, td->td_tilelength);
+      break;
+    case FIELD_COMPRESSION:
+      TIFFSetupShort(tif, TIFFTAG_COMPRESSION,
+          dir, td->td_compression);
+      break;
+    case FIELD_PHOTOMETRIC:
+      TIFFSetupShort(tif, TIFFTAG_PHOTOMETRIC,
+          dir, td->td_photometric);
+      break;
+    case FIELD_POSITION:
+      WriteRationalPair(TIFF_RATIONAL,
+          TIFFTAG_XPOSITION, td->td_xposition,
+          TIFFTAG_YPOSITION, td->td_yposition);
+      break;
+    case FIELD_RESOLUTION:
+      WriteRationalPair(TIFF_RATIONAL,
+          TIFFTAG_XRESOLUTION, td->td_xresolution,
+          TIFFTAG_YRESOLUTION, td->td_yresolution);
+      break;
+    case FIELD_BITSPERSAMPLE:
+    case FIELD_MINSAMPLEVALUE:
+    case FIELD_MAXSAMPLEVALUE:
+    case FIELD_SAMPLEFORMAT:
+      if (!TIFFWritePerSampleShorts(tif, fip->field_tag, dir))
+        goto bad;
+      break;
+    case FIELD_SMINSAMPLEVALUE:
+    case FIELD_SMAXSAMPLEVALUE:
+      if (!TIFFWritePerSampleAnys(tif,
+          _TIFFSampleToTagType(tif), fip->field_tag, dir))
+        goto bad;
+      break;
+    case FIELD_PAGENUMBER:
+    case FIELD_HALFTONEHINTS:
+    case FIELD_YCBCRSUBSAMPLING:
+    case FIELD_DOTRANGE:
+      if (!TIFFSetupShortPair(tif, fip->field_tag, dir))
+        goto bad;
+      break;
+    case FIELD_INKNAMES:
+      if (!TIFFWriteInkNames(tif, dir))
+        goto bad;
+      break;
+    case FIELD_TRANSFERFUNCTION:
+      if (!TIFFWriteTransferFunction(tif, dir))
+        goto bad;
+      break;
+    case FIELD_SUBIFD:
+      /*
+       * XXX: Always write this field using LONG type
+       * for backward compatibility.
+       */
+      dir->tdir_tag = (uint16) fip->field_tag;
+      dir->tdir_type = (uint16) TIFF_LONG;
+      dir->tdir_count = (uint32) td->td_nsubifd;
+      if (!TIFFWriteLongArray(tif, dir, td->td_subifd))
+        goto bad;
+      /*
+       * Total hack: if this directory includes a SubIFD
+       * tag then force the next <n> directories to be
+       * written as ``sub directories'' of this one.  This
+       * is used to write things like thumbnails and
+       * image masks that one wants to keep out of the
+       * normal directory linkage access mechanism.
+       */
+      if (dir->tdir_count > 0) {
+        tif->tif_flags |= TIFF_INSUBIFD;
+        tif->tif_nsubifd = (uint16) dir->tdir_count;
+        if (dir->tdir_count > 1)
+          tif->tif_subifdoff = dir->tdir_offset;
+        else
+          tif->tif_subifdoff = (uint32)(
+                tif->tif_diroff
+              + sizeof (uint16)
+              + ((char*)&dir->tdir_offset-data));
+      }
+      break;
+    default:
+      if (!TIFFWriteNormalTag(tif, dir, fip))
+        goto bad;
+      break;
+    }
+    dir++;
+                
+                if( fip->field_bit != FIELD_CUSTOM )
+                    ResetFieldBit(fields, fip->field_bit);
+  }
+
+  /*
+   * Write directory.
+   */
+  dircount = (uint16) nfields;
+  diroff = (uint32) tif->tif_nextdiroff;
+  if (tif->tif_flags & TIFF_SWAB) {
+    /*
+     * The file's byte order is opposite to the
+     * native machine architecture.  We overwrite
+     * the directory information with impunity
+     * because it'll be released below after we
+     * write it to the file.  Note that all the
+     * other tag construction routines assume that
+     * we do this byte-swapping; i.e. they only
+     * byte-swap indirect data.
+     */
+    for (dir = (TIFFDirEntry*) data; dircount; dir++, dircount--) {
+      TIFFSwabArrayOfShort(&dir->tdir_tag, 2);
+      TIFFSwabArrayOfLong(&dir->tdir_count, 2);
+    }
+    dircount = (uint16) nfields;
+    TIFFSwabShort(&dircount);
+    TIFFSwabLong(&diroff);
+  }
+  (void) TIFFSeekFile(tif, tif->tif_diroff, SEEK_SET);
+  if (!WriteOK(tif, &dircount, sizeof (dircount))) {
+    TIFFError(tif->tif_name, "Error writing directory count");
+    goto bad;
+  }
+  if (!WriteOK(tif, data, dirsize)) {
+    TIFFError(tif->tif_name, "Error writing directory contents");
+    goto bad;
+  }
+  if (!WriteOK(tif, &diroff, sizeof (diroff))) {
+    TIFFError(tif->tif_name, "Error writing directory link");
+    goto bad;
+  }
+  if (done) {
+    TIFFFreeDirectory(tif);
+    tif->tif_flags &= ~TIFF_DIRTYDIRECT;
+    (*tif->tif_cleanup)(tif);
+
+    /*
+    * Reset directory-related state for subsequent
+    * directories.
+    */
+    TIFFCreateDirectory(tif);
+  }
+  _TIFFfree(data);
+  return (1);
+bad:
+  _TIFFfree(data);
+  return (0);
+}
+#undef WriteRationalPair
+
+int
+TIFFWriteDirectory(TIFF* tif)
+{
+  return _TIFFWriteDirectory(tif, TRUE);
+}
+
+/*
+ * Similar to TIFFWriteDirectory(), writes the directory out
+ * but leaves all data structures in memory so that it can be
+ * written again.  This will make a partially written TIFF file
+ * readable before it is successfully completed/closed.
+ */ 
+int
+TIFFCheckpointDirectory(TIFF* tif)
+{
+  int rc;
+  /* Setup the strips arrays, if they haven't already been. */
+  if (tif->tif_dir.td_stripoffset == NULL)
+      (void) TIFFSetupStrips(tif);
+  rc = _TIFFWriteDirectory(tif, FALSE);
+  (void) TIFFSetWriteOffset(tif, TIFFSeekFile(tif, 0, SEEK_END));
+  return rc;
+}
+
+/*
+ * Process tags that are not special cased.
+ */
+static int
+TIFFWriteNormalTag(TIFF* tif, TIFFDirEntry* dir, const TIFFFieldInfo* fip)
+{
+  uint16 wc = (uint16) fip->field_writecount;
+  uint32 wc2;
+
+  dir->tdir_tag = (uint16) fip->field_tag;
+  dir->tdir_type = (uint16) fip->field_type;
+  dir->tdir_count = wc;
+  
+  switch (fip->field_type) {
+  case TIFF_SHORT:
+  case TIFF_SSHORT:
+    if (fip->field_passcount) {
+      uint16* wp;
+      if (wc == (uint16) TIFF_VARIABLE2) {
+        TIFFGetField(tif, fip->field_tag, &wc2, &wp);
+        dir->tdir_count = wc2;
+      } else {  /* Assume TIFF_VARIABLE */
+        TIFFGetField(tif, fip->field_tag, &wc, &wp);
+        dir->tdir_count = wc;
+      }
+      if (!TIFFWriteShortArray(tif, dir, wp))
+        return 0;
+    } else {
+      if (wc == 1) {
+        uint16 sv;
+        TIFFGetField(tif, fip->field_tag, &sv);
+        dir->tdir_offset =
+          TIFFInsertData(tif, dir->tdir_type, sv);
+      } else {
+        uint16* wp;
+        TIFFGetField(tif, fip->field_tag, &wp);
+        if (!TIFFWriteShortArray(tif, dir, wp))
+          return 0;
+      }
+    }
+    break;
+  case TIFF_LONG:
+  case TIFF_SLONG:
+  case TIFF_IFD:
+    if (fip->field_passcount) {
+      uint32* lp;
+      if (wc == (uint16) TIFF_VARIABLE2) {
+        TIFFGetField(tif, fip->field_tag, &wc2, &lp);
+        dir->tdir_count = wc2;
+      } else {  /* Assume TIFF_VARIABLE */
+        TIFFGetField(tif, fip->field_tag, &wc, &lp);
+        dir->tdir_count = wc;
+      }
+      if (!TIFFWriteLongArray(tif, dir, lp))
+        return 0;
+    } else {
+      if (wc == 1) {
+        /* XXX handle LONG->SHORT conversion */
+        TIFFGetField(tif, fip->field_tag,
+               &dir->tdir_offset);
+      } else {
+        uint32* lp;
+        TIFFGetField(tif, fip->field_tag, &lp);
+        if (!TIFFWriteLongArray(tif, dir, lp))
+          return 0;
+      }
+    }
+    break;
+  case TIFF_RATIONAL:
+  case TIFF_SRATIONAL:
+    if (fip->field_passcount) {
+      float* fp;
+      if (wc == (uint16) TIFF_VARIABLE2) {
+        TIFFGetField(tif, fip->field_tag, &wc2, &fp);
+        dir->tdir_count = wc2;
+      } else {  /* Assume TIFF_VARIABLE */
+        TIFFGetField(tif, fip->field_tag, &wc, &fp);
+        dir->tdir_count = wc;
+      }
+      if (!TIFFWriteRationalArray(tif, dir, fp))
+        return 0;
+    } else {
+      if (wc == 1) {
+        float fv;
+        TIFFGetField(tif, fip->field_tag, &fv);
+        if (!TIFFWriteRationalArray(tif, dir, &fv))
+          return 0;
+      } else {
+        float* fp;
+        TIFFGetField(tif, fip->field_tag, &fp);
+        if (!TIFFWriteRationalArray(tif, dir, fp))
+          return 0;
+      }
+    }
+    break;
+  case TIFF_FLOAT:
+    if (fip->field_passcount) {
+      float* fp;
+      if (wc == (uint16) TIFF_VARIABLE2) {
+        TIFFGetField(tif, fip->field_tag, &wc2, &fp);
+        dir->tdir_count = wc2;
+      } else {  /* Assume TIFF_VARIABLE */
+        TIFFGetField(tif, fip->field_tag, &wc, &fp);
+        dir->tdir_count = wc;
+      }
+      if (!TIFFWriteFloatArray(tif, dir, fp))
+        return 0;
+    } else {
+      if (wc == 1) {
+        float fv;
+        TIFFGetField(tif, fip->field_tag, &fv);
+        if (!TIFFWriteFloatArray(tif, dir, &fv))
+          return 0;
+      } else {
+        float* fp;
+        TIFFGetField(tif, fip->field_tag, &fp);
+        if (!TIFFWriteFloatArray(tif, dir, fp))
+          return 0;
+      }
+    }
+    break;
+  case TIFF_DOUBLE:
+    if (fip->field_passcount) {
+      double* dp;
+      if (wc == (uint16) TIFF_VARIABLE2) {
+        TIFFGetField(tif, fip->field_tag, &wc2, &dp);
+        dir->tdir_count = wc2;
+      } else {  /* Assume TIFF_VARIABLE */
+        TIFFGetField(tif, fip->field_tag, &wc, &dp);
+        dir->tdir_count = wc;
+      }
+      if (!TIFFWriteDoubleArray(tif, dir, dp))
+        return 0;
+    } else {
+      if (wc == 1) {
+        double dv;
+        TIFFGetField(tif, fip->field_tag, &dv);
+        if (!TIFFWriteDoubleArray(tif, dir, &dv))
+          return 0;
+      } else {
+        double* dp;
+        TIFFGetField(tif, fip->field_tag, &dp);
+        if (!TIFFWriteDoubleArray(tif, dir, dp))
+          return 0;
+      }
+    }
+    break;
+  case TIFF_ASCII:
+    { 
+                    char* cp;
+                    if (fip->field_passcount)
+                        TIFFGetField(tif, fip->field_tag, &wc, &cp);
+                    else
+                        TIFFGetField(tif, fip->field_tag, &cp);
+
+                    dir->tdir_count = (uint32) (strlen(cp) + 1);
+                    if (!TIFFWriteByteArray(tif, dir, cp))
+                        return (0);
+    }
+    break;
+
+        case TIFF_BYTE:
+        case TIFF_SBYTE:          
+    if (fip->field_passcount) {
+      char* cp;
+      if (wc == (uint16) TIFF_VARIABLE2) {
+        TIFFGetField(tif, fip->field_tag, &wc2, &cp);
+        dir->tdir_count = wc2;
+      } else {  /* Assume TIFF_VARIABLE */
+        TIFFGetField(tif, fip->field_tag, &wc, &cp);
+        dir->tdir_count = wc;
+      }
+      if (!TIFFWriteByteArray(tif, dir, cp))
+        return 0;
+    } else {
+      if (wc == 1) {
+        char cv;
+        TIFFGetField(tif, fip->field_tag, &cv);
+        if (!TIFFWriteByteArray(tif, dir, &cv))
+          return 0;
+      } else {
+        char* cp;
+        TIFFGetField(tif, fip->field_tag, &cp);
+        if (!TIFFWriteByteArray(tif, dir, cp))
+          return 0;
+      }
+    }
+                break;
+
+  case TIFF_UNDEFINED:
+    { char* cp;
+      if (wc == (unsigned short) TIFF_VARIABLE) {
+      TIFFGetField(tif, fip->field_tag, &wc, &cp);
+      dir->tdir_count = wc;
+      } else if (wc == (unsigned short) TIFF_VARIABLE2) {
+      TIFFGetField(tif, fip->field_tag, &wc2, &cp);
+      dir->tdir_count = wc2;
+      } else 
+      TIFFGetField(tif, fip->field_tag, &cp);
+      if (!TIFFWriteByteArray(tif, dir, cp))
+      return (0);
+    }
+    break;
+
+        case TIFF_NOTYPE:
+                break;
+  }
+  return (1);
+}
+
+/*
+ * Setup a directory entry with either a SHORT
+ * or LONG type according to the value.
+ */
+static void
+TIFFSetupShortLong(TIFF* tif, ttag_t tag, TIFFDirEntry* dir, uint32 v)
+{
+  dir->tdir_tag = (uint16) tag;
+  dir->tdir_count = 1;
+  if (v > 0xffffL) {
+    dir->tdir_type = (short) TIFF_LONG;
+    dir->tdir_offset = v;
+  } else {
+    dir->tdir_type = (short) TIFF_SHORT;
+    dir->tdir_offset = TIFFInsertData(tif, (int) TIFF_SHORT, v);
+  }
+}
+
+/*
+ * Setup a SHORT directory entry
+ */
+static void
+TIFFSetupShort(TIFF* tif, ttag_t tag, TIFFDirEntry* dir, uint16 v)
+{
+  dir->tdir_tag = (uint16) tag;
+  dir->tdir_count = 1;
+  dir->tdir_type = (short) TIFF_SHORT;
+  dir->tdir_offset = TIFFInsertData(tif, (int) TIFF_SHORT, v);
+}
+#undef MakeShortDirent
+
+#define  NITEMS(x)  (sizeof (x) / sizeof (x[0]))
+/*
+ * Setup a directory entry that references a
+ * samples/pixel array of SHORT values and
+ * (potentially) write the associated indirect
+ * values.
+ */
+static int
+TIFFWritePerSampleShorts(TIFF* tif, ttag_t tag, TIFFDirEntry* dir)
+{
+  uint16 buf[10], v;
+  uint16* w = buf;
+  int i, status, samples = tif->tif_dir.td_samplesperpixel;
+
+  if (samples > (int)NITEMS(buf)) {
+    w = (uint16*) _TIFFmalloc(samples * sizeof (uint16));
+    if (w == NULL) {
+      TIFFError(tif->tif_name,
+          "No space to write per-sample shorts");
+      return (0);
+    }
+  }
+  TIFFGetField(tif, tag, &v);
+  for (i = 0; i < samples; i++)
+    w[i] = v;
+  
+  dir->tdir_tag = (uint16) tag;
+  dir->tdir_type = (uint16) TIFF_SHORT;
+  dir->tdir_count = samples;
+  status = TIFFWriteShortArray(tif, dir, w);
+  if (w != buf)
+    _TIFFfree((char*) w);
+  return (status);
+}
+
+/*
+ * Setup a directory entry that references a samples/pixel array of ``type''
+ * values and (potentially) write the associated indirect values.  The source
+ * data from TIFFGetField() for the specified tag must be returned as double.
+ */
+static int
+TIFFWritePerSampleAnys(TIFF* tif,
+    TIFFDataType type, ttag_t tag, TIFFDirEntry* dir)
+{
+  double buf[10], v;
+  double* w = buf;
+  int i, status;
+  int samples = (int) tif->tif_dir.td_samplesperpixel;
+
+  if (samples > (int)NITEMS(buf)) {
+    w = (double*) _TIFFmalloc(samples * sizeof (double));
+    if (w == NULL) {
+      TIFFError(tif->tif_name,
+          "No space to write per-sample values");
+      return (0);
+    }
+  }
+  TIFFGetField(tif, tag, &v);
+  for (i = 0; i < samples; i++)
+    w[i] = v;
+  status = TIFFWriteAnyArray(tif, type, tag, dir, samples, w);
+  if (w != buf)
+    _TIFFfree(w);
+  return (status);
+}
+#undef NITEMS
+
+/*
+ * Setup a pair of shorts that are returned by
+ * value, rather than as a reference to an array.
+ */
+static int
+TIFFSetupShortPair(TIFF* tif, ttag_t tag, TIFFDirEntry* dir)
+{
+  uint16 v[2];
+
+  TIFFGetField(tif, tag, &v[0], &v[1]);
+
+  dir->tdir_tag = (uint16) tag;
+  dir->tdir_type = (uint16) TIFF_SHORT;
+  dir->tdir_count = 2;
+  return (TIFFWriteShortArray(tif, dir, v));
+}
+
+/*
+ * Setup a directory entry for an NxM table of shorts,
+ * where M is known to be 2**bitspersample, and write
+ * the associated indirect data.
+ */
+static int
+TIFFWriteShortTable(TIFF* tif,
+    ttag_t tag, TIFFDirEntry* dir, uint32 n, uint16** table)
+{
+  uint32 i, off;
+
+  dir->tdir_tag = (uint16) tag;
+  dir->tdir_type = (short) TIFF_SHORT;
+  /* XXX -- yech, fool TIFFWriteData */
+  dir->tdir_count = (uint32) (1L<<tif->tif_dir.td_bitspersample);
+  off = tif->tif_dataoff;
+  for (i = 0; i < n; i++)
+    if (!TIFFWriteData(tif, dir, (char *)table[i]))
+      return (0);
+  dir->tdir_count *= n;
+  dir->tdir_offset = off;
+  return (1);
+}
+
+/*
+ * Write/copy data associated with an ASCII or opaque tag value.
+ */
+static int
+TIFFWriteByteArray(TIFF* tif, TIFFDirEntry* dir, char* cp)
+{
+  if (dir->tdir_count > 4) {
+    if (!TIFFWriteData(tif, dir, cp))
+      return (0);
+  } else
+    _TIFFmemcpy(&dir->tdir_offset, cp, dir->tdir_count);
+  return (1);
+}
+
+/*
+ * Setup a directory entry of an array of SHORT
+ * or SSHORT and write the associated indirect values.
+ */
+static int
+TIFFWriteShortArray(TIFF* tif, TIFFDirEntry* dir, uint16* v)
+{
+  if (dir->tdir_count <= 2) {
+    if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) {
+      dir->tdir_offset = (uint32) ((long) v[0] << 16);
+      if (dir->tdir_count == 2)
+        dir->tdir_offset |= v[1] & 0xffff;
+    } else {
+      dir->tdir_offset = v[0] & 0xffff;
+      if (dir->tdir_count == 2)
+        dir->tdir_offset |= (long) v[1] << 16;
+    }
+    return (1);
+  } else
+    return (TIFFWriteData(tif, dir, (char*) v));
+}
+
+/*
+ * Setup a directory entry of an array of LONG
+ * or SLONG and write the associated indirect values.
+ */
+static int
+TIFFWriteLongArray(TIFF* tif, TIFFDirEntry* dir, uint32* v)
+{
+  if (dir->tdir_count == 1) {
+    dir->tdir_offset = v[0];
+    return (1);
+  } else
+    return (TIFFWriteData(tif, dir, (char*) v));
+}
+
+/*
+ * Setup a directory entry of an array of RATIONAL
+ * or SRATIONAL and write the associated indirect values.
+ */
+static int
+TIFFWriteRationalArray(TIFF* tif, TIFFDirEntry* dir, float* v)
+{
+  uint32 i;
+  uint32* t;
+  int status;
+
+  t = (uint32*) _TIFFmalloc(2 * dir->tdir_count * sizeof (uint32));
+  if (t == NULL) {
+    TIFFError(tif->tif_name,
+        "No space to write RATIONAL array");
+    return (0);
+  }
+  for (i = 0; i < dir->tdir_count; i++) {
+    float fv = v[i];
+    int sign = 1;
+    uint32 den;
+
+    if (fv < 0) {
+      if (dir->tdir_type == TIFF_RATIONAL) {
+        TIFFWarning(tif->tif_name,
+  "\"%s\": Information lost writing value (%g) as (unsigned) RATIONAL",
+        _TIFFFieldWithTag(tif,dir->tdir_tag)->field_name,
+        fv);
+        fv = 0;
+      } else
+        fv = -fv, sign = -1;
+    }
+    den = 1L;
+    if (fv > 0) {
+      while (fv < 1L<<(31-3) && den < 1L<<(31-3))
+        fv *= 1<<3, den *= 1L<<3;
+    }
+    t[2*i+0] = (uint32) (sign * (fv + 0.5));
+    t[2*i+1] = den;
+  }
+  status = TIFFWriteData(tif, dir, (char *)t);
+  _TIFFfree((char*) t);
+  return (status);
+}
+
+static int
+TIFFWriteFloatArray(TIFF* tif, TIFFDirEntry* dir, float* v)
+{
+  TIFFCvtNativeToIEEEFloat(tif, dir->tdir_count, v);
+  if (dir->tdir_count == 1) {
+    dir->tdir_offset = *(uint32*) &v[0];
+    return (1);
+  } else
+    return (TIFFWriteData(tif, dir, (char*) v));
+}
+
+static int
+TIFFWriteDoubleArray(TIFF* tif, TIFFDirEntry* dir, double* v)
+{
+  /*TIFFCvtNativeToIEEEDouble(tif, n, v);*/
+  return (TIFFWriteData(tif, dir, (char*) v));
+}
+
+/*
+ * Write an array of ``type'' values for a specified tag (i.e. this is a tag
+ * which is allowed to have different types, e.g. SMaxSampleType).
+ * Internally the data values are represented as double since a double can
+ * hold any of the TIFF tag types (yes, this should really be an abstract
+ * type tany_t for portability).  The data is converted into the specified
+ * type in a temporary buffer and then handed off to the appropriate array
+ * writer.
+ */
+static int
+TIFFWriteAnyArray(TIFF* tif,
+    TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, double* v)
+{
+  char buf[10 * sizeof(double)];
+  char* w = buf;
+  int i, status = 0;
+
+  if (n * TIFFDataWidth(type) > sizeof buf) {
+    w = (char*) _TIFFmalloc(n * TIFFDataWidth(type));
+    if (w == NULL) {
+      TIFFError(tif->tif_name,
+          "No space to write array");
+      return (0);
+    }
+  }
+
+  dir->tdir_tag = (uint16) tag;
+  dir->tdir_type = (uint16) type;
+  dir->tdir_count = n;
+
+  switch (type) {
+  case TIFF_BYTE:
+    { 
+      uint8* bp = (uint8*) w;
+      for (i = 0; i < (int) n; i++)
+        bp[i] = (uint8) v[i];
+      if (!TIFFWriteByteArray(tif, dir, (char*) bp))
+        goto out;
+    }
+    break;
+  case TIFF_SBYTE:
+    { 
+      int8* bp = (int8*) w;
+      for (i = 0; i < (int) n; i++)
+        bp[i] = (int8) v[i];
+      if (!TIFFWriteByteArray(tif, dir, (char*) bp))
+        goto out;
+    }
+    break;
+  case TIFF_SHORT:
+    {
+      uint16* bp = (uint16*) w;
+      for (i = 0; i < (int) n; i++)
+        bp[i] = (uint16) v[i];
+      if (!TIFFWriteShortArray(tif, dir, (uint16*)bp))
+        goto out;
+    }
+    break;
+  case TIFF_SSHORT:
+    { 
+      int16* bp = (int16*) w;
+      for (i = 0; i < (int) n; i++)
+        bp[i] = (int16) v[i];
+      if (!TIFFWriteShortArray(tif, dir, (uint16*)bp))
+        goto out;
+    }
+    break;
+  case TIFF_LONG:
+    {
+      uint32* bp = (uint32*) w;
+      for (i = 0; i < (int) n; i++)
+        bp[i] = (uint32) v[i];
+      if (!TIFFWriteLongArray(tif, dir, bp))
+        goto out;
+    }
+    break;
+  case TIFF_SLONG:
+    {
+      int32* bp = (int32*) w;
+      for (i = 0; i < (int) n; i++)
+        bp[i] = (int32) v[i];
+      if (!TIFFWriteLongArray(tif, dir, (uint32*) bp))
+        goto out;
+    }
+    break;
+  case TIFF_FLOAT:
+    { 
+      float* bp = (float*) w;
+      for (i = 0; i < (int) n; i++)
+        bp[i] = (float) v[i];
+      if (!TIFFWriteFloatArray(tif, dir, bp))
+        goto out;
+    }
+    break;
+  case TIFF_DOUBLE:
+    return (TIFFWriteDoubleArray(tif, dir, v));
+  default:
+    /* TIFF_NOTYPE */
+    /* TIFF_ASCII */
+    /* TIFF_UNDEFINED */
+    /* TIFF_RATIONAL */
+    /* TIFF_SRATIONAL */
+    goto out;
+  }
+  status = 1;
+ out:
+  if (w != buf)
+    _TIFFfree(w);
+  return (status);
+}
+
+static int
+TIFFWriteTransferFunction(TIFF* tif, TIFFDirEntry* dir)
+{
+  TIFFDirectory* td = &tif->tif_dir;
+  tsize_t n = (1L<<td->td_bitspersample) * sizeof (uint16);
+  uint16** tf = td->td_transferfunction;
+  int ncols;
+
+  /*
+   * Check if the table can be written as a single column,
+   * or if it must be written as 3 columns.  Note that we
+   * write a 3-column tag if there are 2 samples/pixel and
+   * a single column of data won't suffice--hmm.
+   */
+  switch (td->td_samplesperpixel - td->td_extrasamples) {
+  default:  if (_TIFFmemcmp(tf[0], tf[2], n)) { ncols = 3; break; }
+  case 2:    if (_TIFFmemcmp(tf[0], tf[1], n)) { ncols = 3; break; }
+  case 1: case 0:  ncols = 1;
+  }
+  return (TIFFWriteShortTable(tif,
+      TIFFTAG_TRANSFERFUNCTION, dir, ncols, tf));
+}
+
+static int
+TIFFWriteInkNames(TIFF* tif, TIFFDirEntry* dir)
+{
+  TIFFDirectory* td = &tif->tif_dir;
+
+  dir->tdir_tag = TIFFTAG_INKNAMES;
+  dir->tdir_type = (short) TIFF_ASCII;
+  dir->tdir_count = td->td_inknameslen;
+  return (TIFFWriteByteArray(tif, dir, td->td_inknames));
+}
+
+/*
+ * Write a contiguous directory item.
+ */
+static int
+TIFFWriteData(TIFF* tif, TIFFDirEntry* dir, char* cp)
+{
+  tsize_t cc;
+
+  if (tif->tif_flags & TIFF_SWAB) {
+    switch (dir->tdir_type) {
+    case TIFF_SHORT:
+    case TIFF_SSHORT:
+      TIFFSwabArrayOfShort((uint16*) cp, dir->tdir_count);
+      break;
+    case TIFF_LONG:
+    case TIFF_SLONG:
+    case TIFF_FLOAT:
+      TIFFSwabArrayOfLong((uint32*) cp, dir->tdir_count);
+      break;
+    case TIFF_RATIONAL:
+    case TIFF_SRATIONAL:
+      TIFFSwabArrayOfLong((uint32*) cp, 2*dir->tdir_count);
+      break;
+    case TIFF_DOUBLE:
+      TIFFSwabArrayOfDouble((double*) cp, dir->tdir_count);
+      break;
+    }
+  }
+  dir->tdir_offset = tif->tif_dataoff;
+  cc = dir->tdir_count * TIFFDataWidth((TIFFDataType) dir->tdir_type);
+  if (SeekOK(tif, dir->tdir_offset) &&
+      WriteOK(tif, cp, cc)) {
+    tif->tif_dataoff += (cc + 1) & ~1;
+    return (1);
+  }
+  TIFFError(tif->tif_name, "Error writing data for field \"%s\"",
+      _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
+  return (0);
+}
+
+/*
+ * Similar to TIFFWriteDirectory(), but if the directory has already
+ * been written once, it is relocated to the end of the file, in case it
+ * has changed in size.  Note that this will result in the loss of the 
+ * previously used directory space. 
+ */ 
+
+int 
+TIFFRewriteDirectory( TIFF *tif )
+{
+    static const char module[] = "TIFFRewriteDirectory";
+
+    /* We don't need to do anything special if it hasn't been written. */
+    if( tif->tif_diroff == 0 )
+        return TIFFWriteDirectory( tif );
+
+    /*
+    ** Find and zero the pointer to this directory, so that TIFFLinkDirectory
+    ** will cause it to be added after this directories current pre-link.
+    */
+    
+    /* Is it the first directory in the file? */
+    if (tif->tif_header.tiff_diroff == tif->tif_diroff) 
+    {
+        tif->tif_header.tiff_diroff = 0;
+        tif->tif_diroff = 0;
+
+        TIFFSeekFile(tif, (toff_t)(TIFF_MAGIC_SIZE+TIFF_VERSION_SIZE),
+         SEEK_SET);
+        if (!WriteOK(tif, &(tif->tif_header.tiff_diroff), 
+                     sizeof (tif->tif_diroff))) 
+        {
+            TIFFError(tif->tif_name, "Error updating TIFF header");
+            return (0);
+        }
+    }
+    else
+    {
+        toff_t  nextdir, off;
+
+  nextdir = tif->tif_header.tiff_diroff;
+  do {
+    uint16 dircount;
+
+    if (!SeekOK(tif, nextdir) ||
+        !ReadOK(tif, &dircount, sizeof (dircount))) {
+      TIFFError(module, "Error fetching directory count");
+      return (0);
+    }
+    if (tif->tif_flags & TIFF_SWAB)
+      TIFFSwabShort(&dircount);
+    (void) TIFFSeekFile(tif,
+        dircount * sizeof (TIFFDirEntry), SEEK_CUR);
+    if (!ReadOK(tif, &nextdir, sizeof (nextdir))) {
+      TIFFError(module, "Error fetching directory link");
+      return (0);
+    }
+    if (tif->tif_flags & TIFF_SWAB)
+      TIFFSwabLong(&nextdir);
+  } while (nextdir != tif->tif_diroff && nextdir != 0);
+        off = TIFFSeekFile(tif, 0, SEEK_CUR); /* get current offset */
+        (void) TIFFSeekFile(tif, off - (toff_t)sizeof(nextdir), SEEK_SET);
+        tif->tif_diroff = 0;
+  if (!WriteOK(tif, &(tif->tif_diroff), sizeof (nextdir))) {
+    TIFFError(module, "Error writing directory link");
+    return (0);
+  }
+    }
+
+    /*
+    ** Now use TIFFWriteDirectory() normally.
+    */
+
+    return TIFFWriteDirectory( tif );
+}
+
+
+/*
+ * Link the current directory into the
+ * directory chain for the file.
+ */
+static int
+TIFFLinkDirectory(TIFF* tif)
+{
+  static const char module[] = "TIFFLinkDirectory";
+  toff_t nextdir;
+  toff_t diroff, off;
+
+  tif->tif_diroff = (TIFFSeekFile(tif, (toff_t) 0, SEEK_END)+1) &~ 1;
+  diroff = tif->tif_diroff;
+  if (tif->tif_flags & TIFF_SWAB)
+    TIFFSwabLong(&diroff);
+
+  /*
+   * Handle SubIFDs
+   */
+        if (tif->tif_flags & TIFF_INSUBIFD) {
+    (void) TIFFSeekFile(tif, tif->tif_subifdoff, SEEK_SET);
+    if (!WriteOK(tif, &diroff, sizeof (diroff))) {
+      TIFFError(module,
+          "%s: Error writing SubIFD directory link",
+          tif->tif_name);
+      return (0);
+    }
+    /*
+     * Advance to the next SubIFD or, if this is
+     * the last one configured, revert back to the
+     * normal directory linkage.
+     */
+    if (--tif->tif_nsubifd)
+      tif->tif_subifdoff += sizeof (diroff);
+    else
+      tif->tif_flags &= ~TIFF_INSUBIFD;
+    return (1);
+  }
+
+  if (tif->tif_header.tiff_diroff == 0) {
+    /*
+     * First directory, overwrite offset in header.
+     */
+    tif->tif_header.tiff_diroff = tif->tif_diroff;
+    (void) TIFFSeekFile(tif,
+            (toff_t)(TIFF_MAGIC_SIZE+TIFF_VERSION_SIZE),
+                                    SEEK_SET);
+    if (!WriteOK(tif, &diroff, sizeof (diroff))) {
+      TIFFError(tif->tif_name, "Error writing TIFF header");
+      return (0);
+    }
+    return (1);
+  }
+  /*
+   * Not the first directory, search to the last and append.
+   */
+  nextdir = tif->tif_header.tiff_diroff;
+  do {
+    uint16 dircount;
+
+    if (!SeekOK(tif, nextdir) ||
+        !ReadOK(tif, &dircount, sizeof (dircount))) {
+      TIFFError(module, "Error fetching directory count");
+      return (0);
+    }
+    if (tif->tif_flags & TIFF_SWAB)
+      TIFFSwabShort(&dircount);
+    (void) TIFFSeekFile(tif,
+        dircount * sizeof (TIFFDirEntry), SEEK_CUR);
+    if (!ReadOK(tif, &nextdir, sizeof (nextdir))) {
+      TIFFError(module, "Error fetching directory link");
+      return (0);
+    }
+    if (tif->tif_flags & TIFF_SWAB)
+      TIFFSwabLong(&nextdir);
+  } while (nextdir != 0);
+        off = TIFFSeekFile(tif, 0, SEEK_CUR); /* get current offset */
+        (void) TIFFSeekFile(tif, off - (toff_t)sizeof(nextdir), SEEK_SET);
+  if (!WriteOK(tif, &diroff, sizeof (diroff))) {
+    TIFFError(module, "Error writing directory link");
+    return (0);
+  }
+  return (1);
+}
+
diff --git a/Utilities/ITK/Utilities/tiff/tif_dumpmode.c b/Utilities/ITK/Utilities/tiff/tif_dumpmode.c
new file mode 100644
index 0000000000..ac104cbbe1
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_dumpmode.c
@@ -0,0 +1,117 @@
+/* $Header: /cvsroot/Insight/Insight/Utilities/tiff/tif_dumpmode.c,v 1.3 2005/09/16 19:59:58 jjomier Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ *
+ * "Null" Compression Algorithm Support.
+ */
+#include "tiffiop.h"
+
+/*
+ * Encode a hunk of pixels.
+ */
+static int
+DumpModeEncode(TIFF* tif, tidata_t pp, tsize_t cc, tsample_t s)
+{
+  (void) s;
+  while (cc > 0) {
+    tsize_t n;
+
+    n = cc;
+    if (tif->tif_rawcc + n > tif->tif_rawdatasize)
+      n = tif->tif_rawdatasize - tif->tif_rawcc;
+
+                assert( n > 0 );
+                
+    /*
+     * Avoid copy if client has setup raw
+     * data buffer to avoid extra copy.
+     */
+    if (tif->tif_rawcp != pp)
+      _TIFFmemcpy(tif->tif_rawcp, pp, n);
+    tif->tif_rawcp += n;
+    tif->tif_rawcc += n;
+    pp += n;
+    cc -= n;
+    if (tif->tif_rawcc >= tif->tif_rawdatasize &&
+        !TIFFFlushData1(tif))
+      return (-1);
+  }
+  return (1);
+}
+
+/*
+ * Decode a hunk of pixels.
+ */
+static int
+DumpModeDecode(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s)
+{
+  (void) s;
+  if (tif->tif_rawcc < cc) {
+    TIFFError(tif->tif_name,
+        "DumpModeDecode: Not enough data for scanline %d",
+        tif->tif_row);
+    return (0);
+  }
+  /*
+   * Avoid copy if client has setup raw
+   * data buffer to avoid extra copy.
+   */
+  if (tif->tif_rawcp != buf)
+    _TIFFmemcpy(buf, tif->tif_rawcp, cc);
+  tif->tif_rawcp += cc;
+  tif->tif_rawcc -= cc;
+  return (1);
+}
+
+/*
+ * Seek forwards nrows in the current strip.
+ */
+static int
+DumpModeSeek(TIFF* tif, uint32 nrows)
+{
+  tif->tif_rawcp += nrows * tif->tif_scanlinesize;
+  tif->tif_rawcc -= nrows * tif->tif_scanlinesize;
+  return (1);
+}
+
+/*
+ * Initialize dump mode.
+ */
+int
+TIFFInitDumpMode(TIFF* tif, int scheme)
+{
+  (void) scheme;
+  tif->tif_decoderow = DumpModeDecode;
+  tif->tif_decodestrip = DumpModeDecode;
+  tif->tif_decodetile = DumpModeDecode;
+  tif->tif_encoderow = DumpModeEncode;
+  tif->tif_encodestrip = DumpModeEncode;
+  tif->tif_encodetile = DumpModeEncode;
+  tif->tif_seek = DumpModeSeek;
+  return (1);
+}
diff --git a/Utilities/ITK/Utilities/tiff/tif_error.c b/Utilities/ITK/Utilities/tiff/tif_error.c
new file mode 100644
index 0000000000..6fe5bfab22
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_error.c
@@ -0,0 +1,49 @@
+/* $Header: /cvsroot/Insight/Insight/Utilities/tiff/tif_error.c,v 1.3 2005/09/16 19:59:32 jjomier Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ */
+#include "tiffiop.h"
+
+TIFFErrorHandler
+TIFFSetErrorHandler(TIFFErrorHandler handler)
+{
+  TIFFErrorHandler prev = _TIFFerrorHandler;
+  _TIFFerrorHandler = handler;
+  return (prev);
+}
+
+void
+TIFFError(const char* module, const char* fmt, ...)
+{
+  if (_TIFFerrorHandler) {
+    va_list ap;
+    va_start(ap, fmt);
+    (*_TIFFerrorHandler)(module, fmt, ap);
+    va_end(ap);
+  }
+}
diff --git a/Utilities/ITK/Utilities/tiff/tif_extension.c b/Utilities/ITK/Utilities/tiff/tif_extension.c
new file mode 100644
index 0000000000..f603c9a43d
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_extension.c
@@ -0,0 +1,111 @@
+/* $Header: /cvsroot/Insight/Insight/Utilities/tiff/tif_extension.c,v 1.1 2005/09/16 19:52:26 jjomier Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ *
+ * Various routines support external extension of the tag set, and other
+ * application extension capabilities. 
+ */
+
+#include "tiffiop.h"
+
+int TIFFGetTagListCount( TIFF *tif )
+
+{
+    TIFFDirectory* td = &tif->tif_dir;
+    
+    return td->td_customValueCount;
+}
+
+ttag_t TIFFGetTagListEntry( TIFF *tif, int tag_index )
+
+{
+    TIFFDirectory* td = &tif->tif_dir;
+
+    if( tag_index < 0 || tag_index >= td->td_customValueCount )
+        return (ttag_t) -1;
+    else
+        return td->td_customValues[tag_index].info->field_tag;
+}
+
+/*
+** This provides read/write access to the TIFFTagMethods within the TIFF
+** structure to application code without giving access to the private
+** TIFF structure.
+*/
+TIFFTagMethods *TIFFAccessTagMethods( TIFF *tif )
+
+{
+    return &(tif->tif_tagmethods);
+}
+
+void *TIFFGetClientInfo( TIFF *tif, const char *name )
+
+{
+    TIFFClientInfoLink *link = tif->tif_clientinfo;
+
+    while( link != NULL && strcmp(link->name,name) != 0 )
+        link = link->next;
+
+    if( link != NULL )
+        return link->data;
+    else
+        return NULL;
+}
+
+void TIFFSetClientInfo( TIFF *tif, void *data, const char *name )
+
+{
+    TIFFClientInfoLink *link = tif->tif_clientinfo;
+
+    /*
+    ** Do we have an existing link with this name?  If so, just
+    ** set it.
+    */
+    while( link != NULL && strcmp(link->name,name) != 0 )
+        link = link->next;
+
+    if( link != NULL )
+    {
+        link->data = data;
+        return;
+    }
+
+    /*
+    ** Create a new link.
+    */
+
+    link = (TIFFClientInfoLink *) _TIFFmalloc(sizeof(TIFFClientInfoLink));
+    assert (link != NULL);
+    link->next = tif->tif_clientinfo;
+    link->name = (char *) _TIFFmalloc(strlen(name)+1);
+    assert (link->name != NULL);
+    strcpy(link->name, name);
+    link->data = data;
+
+    tif->tif_clientinfo = link;
+}
diff --git a/Utilities/ITK/Utilities/tiff/tif_fax3.c b/Utilities/ITK/Utilities/tiff/tif_fax3.c
new file mode 100644
index 0000000000..1c08d9204c
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_fax3.c
@@ -0,0 +1,1556 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1990-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+#include "tiffiop.h"
+#ifdef CCITT_SUPPORT
+/*
+ * TIFF Library.
+ *
+ * CCITT Group 3 (T.4) and Group 4 (T.6) Compression Support.
+ *
+ * This file contains support for decoding and encoding TIFF
+ * compression algorithms 2, 3, 4, and 32771.
+ *
+ * Decoder support is derived, with permission, from the code
+ * in Frank Cringle's viewfax program;
+ *      Copyright (C) 1990, 1995  Frank D. Cringle.
+ */
+#include "tif_fax3.h"
+#define  G3CODES
+#include "t4.h"
+#include <stdio.h>
+
+/*
+ * Compression+decompression state blocks are
+ * derived from this ``base state'' block.
+ */
+typedef struct {
+  int     rw_mode;                /* O_RDONLY for decode, else encode */
+  int  mode;      /* operating mode */
+  uint32  rowbytes;    /* bytes in a decoded scanline */
+  uint32  rowpixels;    /* pixels in a scanline */
+
+  uint16  cleanfaxdata;    /* CleanFaxData tag */
+  uint32  badfaxrun;    /* BadFaxRun tag */
+  uint32  badfaxlines;    /* BadFaxLines tag */
+  uint32  groupoptions;    /* Group 3/4 options tag */
+  uint32  recvparams;    /* encoded Class 2 session params */
+  char*  subaddress;    /* subaddress string */
+  uint32  recvtime;    /* time spent receiving (secs) */
+  char*  faxdcs;      /* Table 2/T.30 encoded session params */
+  TIFFVGetMethod vgetparent;  /* super-class method */
+  TIFFVSetMethod vsetparent;  /* super-class method */
+} Fax3BaseState;
+#define  Fax3State(tif)    ((Fax3BaseState*) (tif)->tif_data)
+
+typedef enum { G3_1D, G3_2D } Ttag;
+typedef struct {
+  Fax3BaseState b;
+
+  /* Decoder state info */
+  const unsigned char* bitmap;  /* bit reversal table */
+  uint32  data;      /* current i/o byte/word */
+  int  bit;      /* current i/o bit in byte */
+  int  EOLcnt;      /* count of EOL codes recognized */
+  TIFFFaxFillFunc fill;    /* fill routine */
+  uint32*  runs;      /* b&w runs for current/previous row */
+  uint32*  refruns;    /* runs for reference line */
+  uint32*  curruns;    /* runs for current line */
+
+  /* Encoder state info */
+  Ttag    tag;      /* encoding state */
+  unsigned char*  refline;  /* reference line for 2d decoding */
+  int  k;      /* #rows left that can be 2d encoded */
+  int  maxk;      /* max #rows that can be 2d encoded */
+} Fax3CodecState;
+#define  DecoderState(tif)  ((Fax3CodecState*) Fax3State(tif))
+#define  EncoderState(tif)  ((Fax3CodecState*) Fax3State(tif))
+
+#define  is2DEncoding(sp) \
+  (sp->b.groupoptions & GROUP3OPT_2DENCODING)
+#define  isAligned(p,t)  ((((unsigned long)(p)) & (sizeof (t)-1)) == 0)
+
+/*
+ * Group 3 and Group 4 Decoding.
+ */
+
+/*
+ * These macros glue the TIFF library state to
+ * the state expected by Frank's decoder.
+ */
+#define  DECLARE_STATE(tif, sp, mod)          \
+    static const char module[] = mod;          \
+    Fax3CodecState* sp = DecoderState(tif);        \
+    int a0;        /* reference element */    \
+    int lastx = sp->b.rowpixels;  /* last element in row */  \
+    uint32 BitAcc;      /* bit accumulator */    \
+    int BitsAvail;      /* # valid bits in BitAcc */  \
+    int RunLength;      /* length of current run */  \
+    unsigned char* cp;      /* next byte of input data */  \
+    unsigned char* ep;      /* end of input data */    \
+    uint32* pa;        /* place to stuff next run */  \
+    uint32* thisrun;      /* current row's run array */  \
+    int EOLcnt;        /* # EOL codes recognized */  \
+    const unsigned char* bitmap = sp->bitmap;  /* input data bit reverser */  \
+    const TIFFFaxTabEnt* TabEnt
+#define  DECLARE_STATE_2D(tif, sp, mod)          \
+    DECLARE_STATE(tif, sp, mod);          \
+    int b1;        /* next change on prev line */  \
+    uint32* pb        /* next run in reference line */\
+/*
+ * Load any state that may be changed during decoding.
+ */
+#define  CACHE_STATE(tif, sp) do {          \
+    BitAcc = sp->data;              \
+    BitsAvail = sp->bit;            \
+    EOLcnt = sp->EOLcnt;            \
+    cp = (unsigned char*) tif->tif_rawcp;        \
+    ep = cp + tif->tif_rawcc;            \
+} while (0)
+/*
+ * Save state possibly changed during decoding.
+ */
+#define  UNCACHE_STATE(tif, sp) do {          \
+    sp->bit = BitsAvail;            \
+    sp->data = BitAcc;              \
+    sp->EOLcnt = EOLcnt;            \
+    tif->tif_rawcc -= (tidata_t) cp - tif->tif_rawcp;      \
+    tif->tif_rawcp = (tidata_t) cp;          \
+} while (0)
+
+/*
+ * Setup state for decoding a strip.
+ */
+static int
+Fax3PreDecode(TIFF* tif, tsample_t s)
+{
+  Fax3CodecState* sp = DecoderState(tif);
+
+  (void) s;
+  assert(sp != NULL);
+  sp->bit = 0;      /* force initial read */
+  sp->data = 0;
+  sp->EOLcnt = 0;      /* force initial scan for EOL */
+  /*
+   * Decoder assumes lsb-to-msb bit order.  Note that we select
+   * this here rather than in Fax3SetupState so that viewers can
+   * hold the image open, fiddle with the FillOrder tag value,
+   * and then re-decode the image.  Otherwise they'd need to close
+   * and open the image to get the state reset.
+   */
+  sp->bitmap =
+      TIFFGetBitRevTable(tif->tif_dir.td_fillorder != FILLORDER_LSB2MSB);
+  if (sp->refruns) {    /* init reference line to white */
+    sp->refruns[0] = (uint32) sp->b.rowpixels;
+    sp->refruns[1] = 0;
+  }
+  return (1);
+}
+
+/*
+ * Routine for handling various errors/conditions.
+ * Note how they are "glued into the decoder" by
+ * overriding the definitions used by the decoder.
+ */
+
+static void
+Fax3Unexpected(const char* module, TIFF* tif, uint32 a0)
+{
+  TIFFError(module, "%s: Bad code word at scanline %d (x %lu)",
+      tif->tif_name, tif->tif_row, (unsigned long) a0);
+}
+#define  unexpected(table, a0)  Fax3Unexpected(module, tif, a0)
+
+static void
+Fax3Extension(const char* module, TIFF* tif, uint32 a0)
+{
+  TIFFError(module,
+      "%s: Uncompressed data (not supported) at scanline %d (x %lu)",
+      tif->tif_name, tif->tif_row, (unsigned long) a0);
+}
+#define  extension(a0)  Fax3Extension(module, tif, a0)
+
+static void
+Fax3BadLength(const char* module, TIFF* tif, uint32 a0, uint32 lastx)
+{
+  TIFFWarning(module, "%s: %s at scanline %d (got %lu, expected %lu)",
+      tif->tif_name,
+      a0 < lastx ? "Premature EOL" : "Line length mismatch",
+      tif->tif_row, (unsigned long) a0, (unsigned long) lastx);
+}
+#define  badlength(a0,lastx)  Fax3BadLength(module, tif, a0, lastx)
+
+static void
+Fax3PrematureEOF(const char* module, TIFF* tif, uint32 a0)
+{
+  TIFFWarning(module, "%s: Premature EOF at scanline %d (x %lu)",
+      tif->tif_name, tif->tif_row, (unsigned long) a0);
+}
+#define  prematureEOF(a0)  Fax3PrematureEOF(module, tif, a0)
+
+#define  Nop
+
+/*
+ * Decode the requested amount of G3 1D-encoded data.
+ */
+static int
+Fax3Decode1D(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s)
+{
+  DECLARE_STATE(tif, sp, "Fax3Decode1D");
+
+  (void) s;
+  CACHE_STATE(tif, sp);
+  thisrun = sp->curruns;
+  while ((long)occ > 0) {
+    a0 = 0;
+    RunLength = 0;
+    pa = thisrun;
+#ifdef FAX3_DEBUG
+    printf("\nBitAcc=%08X, BitsAvail = %d\n", BitAcc, BitsAvail);
+    printf("-------------------- %d\n", tif->tif_row);
+    fflush(stdout);
+#endif
+    SYNC_EOL(EOF1D);
+    EXPAND1D(EOF1Da);
+    (*sp->fill)(buf, thisrun, pa, lastx);
+    buf += sp->b.rowbytes;
+    occ -= sp->b.rowbytes;
+    continue;
+  EOF1D:        /* premature EOF */
+    CLEANUP_RUNS();
+  EOF1Da:        /* premature EOF */
+    (*sp->fill)(buf, thisrun, pa, lastx);
+    UNCACHE_STATE(tif, sp);
+    return (-1);
+  }
+  UNCACHE_STATE(tif, sp);
+  return (1);
+}
+
+#define  SWAP(t,a,b)  { t x; x = (a); (a) = (b); (b) = x; }
+/*
+ * Decode the requested amount of G3 2D-encoded data.
+ */
+static int
+Fax3Decode2D(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s)
+{
+  DECLARE_STATE_2D(tif, sp, "Fax3Decode2D");
+  int is1D;      /* current line is 1d/2d-encoded */
+
+  (void) s;
+  CACHE_STATE(tif, sp);
+  while ((long)occ > 0) {
+    a0 = 0;
+    RunLength = 0;
+    pa = thisrun = sp->curruns;
+#ifdef FAX3_DEBUG
+    printf("\nBitAcc=%08X, BitsAvail = %d EOLcnt = %d",
+        BitAcc, BitsAvail, EOLcnt);
+#endif
+    SYNC_EOL(EOF2D);
+    NeedBits8(1, EOF2D);
+    is1D = GetBits(1);  /* 1D/2D-encoding tag bit */
+    ClrBits(1);
+#ifdef FAX3_DEBUG
+    printf(" %s\n-------------------- %d\n",
+        is1D ? "1D" : "2D", tif->tif_row);
+    fflush(stdout);
+#endif
+    pb = sp->refruns;
+    b1 = *pb++;
+    if (is1D)
+      EXPAND1D(EOF2Da);
+    else
+      EXPAND2D(EOF2Da);
+    (*sp->fill)(buf, thisrun, pa, lastx);
+    SETVAL(0);    /* imaginary change for reference */
+    SWAP(uint32*, sp->curruns, sp->refruns);
+    buf += sp->b.rowbytes;
+    occ -= sp->b.rowbytes;
+    continue;
+  EOF2D:        /* premature EOF */
+    CLEANUP_RUNS();
+  EOF2Da:        /* premature EOF */
+    (*sp->fill)(buf, thisrun, pa, lastx);
+    UNCACHE_STATE(tif, sp);
+    return (-1);
+  }
+  UNCACHE_STATE(tif, sp);
+  return (1);
+}
+#undef SWAP
+
+/*
+ * The ZERO & FILL macros must handle spans < 2*sizeof(long) bytes.
+ * For machines with 64-bit longs this is <16 bytes; otherwise
+ * this is <8 bytes.  We optimize the code here to reflect the
+ * machine characteristics.
+ */
+#if SIZEOF_LONG == 8
+# define FILL(n, cp)                  \
+    switch (n) {                  \
+    case 15:(cp)[14] = 0xff; case 14:(cp)[13] = 0xff; case 13: (cp)[12] = 0xff;\
+    case 12:(cp)[11] = 0xff; case 11:(cp)[10] = 0xff; case 10: (cp)[9] = 0xff;\
+    case  9: (cp)[8] = 0xff; case  8: (cp)[7] = 0xff; case  7: (cp)[6] = 0xff;\
+    case  6: (cp)[5] = 0xff; case  5: (cp)[4] = 0xff; case  4: (cp)[3] = 0xff;\
+    case  3: (cp)[2] = 0xff; case  2: (cp)[1] = 0xff;            \
+    case  1: (cp)[0] = 0xff; (cp) += (n); case 0:  ;            \
+    }
+# define ZERO(n, cp)              \
+    switch (n) {              \
+    case 15:(cp)[14] = 0; case 14:(cp)[13] = 0; case 13: (cp)[12] = 0;  \
+    case 12:(cp)[11] = 0; case 11:(cp)[10] = 0; case 10: (cp)[9] = 0;  \
+    case  9: (cp)[8] = 0; case  8: (cp)[7] = 0; case  7: (cp)[6] = 0;  \
+    case  6: (cp)[5] = 0; case  5: (cp)[4] = 0; case  4: (cp)[3] = 0;  \
+    case  3: (cp)[2] = 0; case  2: (cp)[1] = 0;        \
+    case  1: (cp)[0] = 0; (cp) += (n); case 0:  ;      \
+    }
+#else
+# define FILL(n, cp)                  \
+    switch (n) {                  \
+    case 7: (cp)[6] = 0xff; case 6: (cp)[5] = 0xff; case 5: (cp)[4] = 0xff; \
+    case 4: (cp)[3] = 0xff; case 3: (cp)[2] = 0xff; case 2: (cp)[1] = 0xff; \
+    case 1: (cp)[0] = 0xff; (cp) += (n); case 0:  ;          \
+    }
+# define ZERO(n, cp)              \
+    switch (n) {              \
+    case 7: (cp)[6] = 0; case 6: (cp)[5] = 0; case 5: (cp)[4] = 0;  \
+    case 4: (cp)[3] = 0; case 3: (cp)[2] = 0; case 2: (cp)[1] = 0;  \
+    case 1: (cp)[0] = 0; (cp) += (n); case 0:  ;      \
+    }
+#endif
+
+/*
+ * Bit-fill a row according to the white/black
+ * runs generated during G3/G4 decoding.
+ */
+void
+_TIFFFax3fillruns(unsigned char* buf, uint32* runs, uint32* erun, uint32 lastx)
+{
+  static const unsigned char _fillmasks[] =
+      { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
+  unsigned char* cp;
+  uint32 x, bx, run;
+  int32 n, nw;
+  long* lp;
+
+  if ((erun-runs)&1)
+      *erun++ = 0;
+  x = 0;
+  for (; runs < erun; runs += 2) {
+      run = runs[0];
+      if (x+run > lastx || run > lastx )
+    run = runs[0] = (uint32) (lastx - x);
+      if (run) {
+    cp = buf + (x>>3);
+    bx = x&7;
+    if (run > 8-bx) {
+        if (bx) {      /* align to byte boundary */
+      *cp++ &= 0xff << (8-bx);
+      run -= 8-bx;
+        }
+        if( (n = run >> 3) != 0 ) {  /* multiple bytes to fill */
+      if ((n/sizeof (long)) > 1) {
+          /*
+           * Align to longword boundary and fill.
+           */
+          for (; n && !isAligned(cp, long); n--)
+            *cp++ = 0x00;
+          lp = (long*) cp;
+          nw = (int32)(n / sizeof (long));
+          n -= nw * sizeof (long);
+          do {
+            *lp++ = 0L;
+          } while (--nw);
+          cp = (unsigned char*) lp;
+      }
+      ZERO(n, cp);
+      run &= 7;
+        }
+        if (run)
+      cp[0] &= 0xff >> run;
+    } else
+        cp[0] &= ~(_fillmasks[run]>>bx);
+    x += runs[0];
+      }
+      run = runs[1];
+      if (x+run > lastx || run > lastx )
+    run = runs[1] = lastx - x;
+      if (run) {
+    cp = buf + (x>>3);
+    bx = x&7;
+    if (run > 8-bx) {
+        if (bx) {      /* align to byte boundary */
+      *cp++ |= 0xff >> bx;
+      run -= 8-bx;
+        }
+        if( (n = run>>3) != 0 ) {  /* multiple bytes to fill */
+      if ((n/sizeof (long)) > 1) {
+          /*
+           * Align to longword boundary and fill.
+           */
+          for (; n && !isAligned(cp, long); n--)
+        *cp++ = 0xff;
+          lp = (long*) cp;
+          nw = (int32)(n / sizeof (long));
+          n -= nw * sizeof (long);
+          do {
+        *lp++ = -1L;
+          } while (--nw);
+          cp = (unsigned char*) lp;
+      }
+      FILL(n, cp);
+      run &= 7;
+        }
+        if (run)
+      cp[0] |= 0xff00 >> run;
+    } else
+        cp[0] |= _fillmasks[run]>>bx;
+    x += runs[1];
+      }
+  }
+  assert(x == lastx);
+}
+#undef  ZERO
+#undef  FILL
+
+static char *
+CheckMalloc(TIFF* tif, size_t nmemb, size_t elem_size, const char* what)
+{
+  char  *cp = NULL;
+  tsize_t  bytes = nmemb * elem_size;
+
+  if (nmemb && elem_size && bytes / elem_size == nmemb)
+    cp = (char*) _TIFFmalloc(bytes);
+
+  if (cp == NULL)
+    TIFFError(tif->tif_name, "No space %s", what);
+  
+  return (cp);
+}
+
+/*
+ * Setup G3/G4-related compression/decompression state
+ * before data is processed.  This routine is called once
+ * per image -- it sets up different state based on whether
+ * or not decoding or encoding is being done and whether
+ * 1D- or 2D-encoded data is involved.
+ */
+static int
+Fax3SetupState(TIFF* tif)
+{
+  TIFFDirectory* td = &tif->tif_dir;
+  Fax3BaseState* sp = Fax3State(tif);
+  long rowbytes, rowpixels;
+  int needsRefLine;
+  Fax3CodecState* dsp = (Fax3CodecState*) Fax3State(tif);
+  uint32 nruns;
+
+  if (td->td_bitspersample != 1) {
+    TIFFError(tif->tif_name,
+        "Bits/sample must be 1 for Group 3/4 encoding/decoding");
+    return (0);
+  }
+  /*
+   * Calculate the scanline/tile widths.
+   */
+  if (isTiled(tif)) {
+    rowbytes = TIFFTileRowSize(tif);
+    rowpixels = td->td_tilewidth;
+  } else {
+    rowbytes = TIFFScanlineSize(tif);
+    rowpixels = td->td_imagewidth;
+  }
+  sp->rowbytes = (uint32) rowbytes;
+  sp->rowpixels = (uint32) rowpixels;
+  /*
+   * Allocate any additional space required for decoding/encoding.
+   */
+  needsRefLine = (
+      (sp->groupoptions & GROUP3OPT_2DENCODING) ||
+      td->td_compression == COMPRESSION_CCITTFAX4
+  );
+
+  nruns = needsRefLine ? 2*TIFFroundup(rowpixels,32) : (uint32)rowpixels;
+
+  dsp->runs = (uint32*) CheckMalloc(tif, 2*nruns+3, sizeof (uint32),
+            "for Group 3/4 run arrays");
+  if (dsp->runs == NULL)
+    return (0);
+  dsp->curruns = dsp->runs;
+  if (needsRefLine)
+    dsp->refruns = dsp->runs + (nruns>>1);
+  else
+    dsp->refruns = NULL;
+  if (td->td_compression == COMPRESSION_CCITTFAX3
+      && is2DEncoding(dsp)) {  /* NB: default is 1D routine */
+    tif->tif_decoderow = Fax3Decode2D;
+    tif->tif_decodestrip = Fax3Decode2D;
+    tif->tif_decodetile = Fax3Decode2D;
+  }
+
+  if (needsRefLine) {    /* 2d encoding */
+    Fax3CodecState* esp = EncoderState(tif);
+    /*
+     * 2d encoding requires a scanline
+     * buffer for the ``reference line''; the
+     * scanline against which delta encoding
+     * is referenced.  The reference line must
+     * be initialized to be ``white'' (done elsewhere).
+     */
+    esp->refline = (unsigned char*) _TIFFmalloc(rowbytes);
+    if (esp->refline == NULL) {
+      TIFFError("Fax3SetupState",
+          "%s: No space for Group 3/4 reference line",
+          tif->tif_name);
+      return (0);
+    }
+  } else          /* 1d encoding */
+    EncoderState(tif)->refline = NULL;
+
+  return (1);
+}
+
+/*
+ * CCITT Group 3 FAX Encoding.
+ */
+
+#define  Fax3FlushBits(tif, sp) {        \
+  if ((tif)->tif_rawcc >= (tif)->tif_rawdatasize)    \
+    (void) TIFFFlushData1(tif);      \
+  *(tif)->tif_rawcp++ = (tidataval_t) (sp)->data;    \
+  (tif)->tif_rawcc++;          \
+  (sp)->data = 0, (sp)->bit = 8;        \
+}
+#define  _FlushBits(tif) {          \
+  if ((tif)->tif_rawcc >= (tif)->tif_rawdatasize)    \
+    (void) TIFFFlushData1(tif);      \
+  *(tif)->tif_rawcp++ = (tidataval_t) data;    \
+  (tif)->tif_rawcc++;          \
+  data = 0, bit = 8;          \
+}
+static const int _msbmask[9] =
+    { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
+#define  _PutBits(tif, bits, length) {        \
+  while (length > bit) {          \
+    data |= bits >> (length - bit);      \
+    length -= bit;          \
+    _FlushBits(tif);        \
+  }              \
+  data |= (bits & _msbmask[length]) << (bit - length);  \
+  bit -= length;            \
+  if (bit == 0)            \
+    _FlushBits(tif);        \
+}
+  
+/*
+ * Write a variable-length bit-value to
+ * the output stream.  Values are
+ * assumed to be at most 16 bits.
+ */
+static void
+Fax3PutBits(TIFF* tif, unsigned int bits, unsigned int length)
+{
+  Fax3CodecState* sp = EncoderState(tif);
+  unsigned int bit = sp->bit;
+  int data = sp->data;
+
+  _PutBits(tif, bits, length);
+
+  sp->data = data;
+  sp->bit = bit;
+}
+
+/*
+ * Write a code to the output stream.
+ */
+#define putcode(tif, te)  Fax3PutBits(tif, (te)->code, (te)->length)
+
+#ifdef FAX3_DEBUG
+#define  DEBUG_COLOR(w) (tab == TIFFFaxWhiteCodes ? w "W" : w "B")
+#define  DEBUG_PRINT(what,len) {            \
+    int t;                \
+    printf("%08X/%-2d: %s%5d\t", data, bit, DEBUG_COLOR(what), len);  \
+    for (t = length-1; t >= 0; t--)          \
+  putchar(code & (1<<t) ? '1' : '0');        \
+    putchar('\n');              \
+}
+#endif
+
+/*
+ * Write the sequence of codes that describes
+ * the specified span of zero's or one's.  The
+ * appropriate table that holds the make-up and
+ * terminating codes is supplied.
+ */
+static void
+putspan(TIFF* tif, int32 span, const tableentry* tab)
+{
+  Fax3CodecState* sp = EncoderState(tif);
+  unsigned int bit = sp->bit;
+  int data = sp->data;
+  unsigned int code, length;
+
+  while (span >= 2624) {
+    const tableentry* te = &tab[63 + (2560>>6)];
+    code = te->code, length = te->length;
+#ifdef FAX3_DEBUG
+    DEBUG_PRINT("MakeUp", te->runlen);
+#endif
+    _PutBits(tif, code, length);
+    span -= te->runlen;
+  }
+  if (span >= 64) {
+    const tableentry* te = &tab[63 + (span>>6)];
+    assert(te->runlen == 64*(span>>6));
+    code = te->code, length = te->length;
+#ifdef FAX3_DEBUG
+    DEBUG_PRINT("MakeUp", te->runlen);
+#endif
+    _PutBits(tif, code, length);
+    span -= te->runlen;
+  }
+  code = tab[span].code, length = tab[span].length;
+#ifdef FAX3_DEBUG
+  DEBUG_PRINT("  Term", tab[span].runlen);
+#endif
+  _PutBits(tif, code, length);
+
+  sp->data = data;
+  sp->bit = bit;
+}
+
+/*
+ * Write an EOL code to the output stream.  The zero-fill
+ * logic for byte-aligning encoded scanlines is handled
+ * here.  We also handle writing the tag bit for the next
+ * scanline when doing 2d encoding.
+ */
+static void
+Fax3PutEOL(TIFF* tif)
+{
+  Fax3CodecState* sp = EncoderState(tif);
+  unsigned int bit = sp->bit;
+  int data = sp->data;
+  unsigned int code, length, tparm;
+
+  if (sp->b.groupoptions & GROUP3OPT_FILLBITS) {
+    /*
+     * Force bit alignment so EOL will terminate on
+     * a byte boundary.  That is, force the bit alignment
+     * to 16-12 = 4 before putting out the EOL code.
+     */
+    int align = 8 - 4;
+    if (align != sp->bit) {
+      if (align > sp->bit)
+        align = sp->bit + (8 - align);
+      else
+        align = sp->bit - align;
+      code = 0;
+      tparm=align; 
+      _PutBits(tif, 0, tparm);
+    }
+  }
+  code = EOL, length = 12;
+  if (is2DEncoding(sp))
+    code = (code<<1) | (sp->tag == G3_1D), length++;
+  _PutBits(tif, code, length);
+
+  sp->data = data;
+  sp->bit = bit;
+}
+
+/*
+ * Reset encoding state at the start of a strip.
+ */
+static int
+Fax3PreEncode(TIFF* tif, tsample_t s)
+{
+  Fax3CodecState* sp = EncoderState(tif);
+
+  (void) s;
+  assert(sp != NULL);
+  sp->bit = 8;
+  sp->data = 0;
+  sp->tag = G3_1D;
+  /*
+   * This is necessary for Group 4; otherwise it isn't
+   * needed because the first scanline of each strip ends
+   * up being copied into the refline.
+   */
+  if (sp->refline)
+    _TIFFmemset(sp->refline, 0x00, sp->b.rowbytes);
+  if (is2DEncoding(sp)) {
+    float res = tif->tif_dir.td_yresolution;
+    /*
+     * The CCITT spec says that when doing 2d encoding, you
+     * should only do it on K consecutive scanlines, where K
+     * depends on the resolution of the image being encoded
+     * (2 for <= 200 lpi, 4 for > 200 lpi).  Since the directory
+     * code initializes td_yresolution to 0, this code will
+     * select a K of 2 unless the YResolution tag is set
+     * appropriately.  (Note also that we fudge a little here
+     * and use 150 lpi to avoid problems with units conversion.)
+     */
+    if (tif->tif_dir.td_resolutionunit == RESUNIT_CENTIMETER)
+      res *= 2.54f;    /* convert to inches */
+    sp->maxk = (res > 150 ? 4 : 2);
+    sp->k = sp->maxk-1;
+  } else
+    sp->k = sp->maxk = 0;
+  return (1);
+}
+
+static const unsigned char zeroruns[256] = {
+    8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,  /* 0x00 - 0x0f */
+    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,  /* 0x10 - 0x1f */
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,  /* 0x20 - 0x2f */
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,  /* 0x30 - 0x3f */
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 0x40 - 0x4f */
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 0x50 - 0x5f */
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 0x60 - 0x6f */
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 0x70 - 0x7f */
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0x80 - 0x8f */
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0x90 - 0x9f */
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0xa0 - 0xaf */
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0xb0 - 0xbf */
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0xc0 - 0xcf */
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0xd0 - 0xdf */
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0xe0 - 0xef */
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0xf0 - 0xff */
+};
+static const unsigned char oneruns[256] = {
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0x00 - 0x0f */
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0x10 - 0x1f */
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0x20 - 0x2f */
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0x30 - 0x3f */
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0x40 - 0x4f */
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0x50 - 0x5f */
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0x60 - 0x6f */
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0x70 - 0x7f */
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 0x80 - 0x8f */
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 0x90 - 0x9f */
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 0xa0 - 0xaf */
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 0xb0 - 0xbf */
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,  /* 0xc0 - 0xcf */
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,  /* 0xd0 - 0xdf */
+    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,  /* 0xe0 - 0xef */
+    4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8,  /* 0xf0 - 0xff */
+};
+
+/*
+ * On certain systems it pays to inline
+ * the routines that find pixel spans.
+ */
+#ifdef VAXC
+static  int32 find0span(unsigned char*, int32, int32);
+static  int32 find1span(unsigned char*, int32, int32);
+#pragma inline(find0span,find1span)
+#endif
+
+/*
+ * Find a span of ones or zeros using the supplied
+ * table.  The ``base'' of the bit string is supplied
+ * along with the start+end bit indices.
+ */
+inline static int32
+find0span(unsigned char* bp, int32 bs, int32 be)
+{
+  int32 bits = be - bs;
+  int32 n, span;
+
+  bp += bs>>3;
+  /*
+   * Check partial byte on lhs.
+   */
+  if (bits > 0 && (n = (bs & 7))) {
+    span = zeroruns[(*bp << n) & 0xff];
+    if (span > 8-n)    /* table value too generous */
+      span = 8-n;
+    if (span > bits)  /* constrain span to bit range */
+      span = bits;
+    if (n+span < 8)    /* doesn't extend to edge of byte */
+      return (span);
+    bits -= span;
+    bp++;
+  } else
+    span = 0;
+  if (bits >= (int32)(2*8*sizeof (long))) {
+    long* lp;
+    /*
+     * Align to longword boundary and check longwords.
+     */
+    while (!isAligned(bp, long)) {
+      if (*bp != 0x00)
+        return (span + zeroruns[*bp]);
+      span += 8, bits -= 8;
+      bp++;
+    }
+    lp = (long*) bp;
+    while (bits >= (int32)(8*sizeof (long)) && *lp == 0) {
+      span += 8*sizeof (long), bits -= 8*sizeof (long);
+      lp++;
+    }
+    bp = (unsigned char*) lp;
+  }
+  /*
+   * Scan full bytes for all 0's.
+   */
+  while (bits >= 8) {
+    if (*bp != 0x00)  /* end of run */
+      return (span + zeroruns[*bp]);
+    span += 8, bits -= 8;
+    bp++;
+  }
+  /*
+   * Check partial byte on rhs.
+   */
+  if (bits > 0) {
+    n = zeroruns[*bp];
+    span += (n > bits ? bits : n);
+  }
+  return (span);
+}
+
+inline static int32
+find1span(unsigned char* bp, int32 bs, int32 be)
+{
+  int32 bits = be - bs;
+  int32 n, span;
+
+  bp += bs>>3;
+  /*
+   * Check partial byte on lhs.
+   */
+  if (bits > 0 && (n = (bs & 7))) {
+    span = oneruns[(*bp << n) & 0xff];
+    if (span > 8-n)    /* table value too generous */
+      span = 8-n;
+    if (span > bits)  /* constrain span to bit range */
+      span = bits;
+    if (n+span < 8)    /* doesn't extend to edge of byte */
+      return (span);
+    bits -= span;
+    bp++;
+  } else
+    span = 0;
+  if (bits >= (int32)(2*8*sizeof (long))) {
+    long* lp;
+    /*
+     * Align to longword boundary and check longwords.
+     */
+    while (!isAligned(bp, long)) {
+      if (*bp != 0xff)
+        return (span + oneruns[*bp]);
+      span += 8, bits -= 8;
+      bp++;
+    }
+    lp = (long*) bp;
+    while (bits >= (int32)(8*sizeof (long)) && *lp == ~0) {
+      span += 8*sizeof (long), bits -= 8*sizeof (long);
+      lp++;
+    }
+    bp = (unsigned char*) lp;
+  }
+  /*
+   * Scan full bytes for all 1's.
+   */
+  while (bits >= 8) {
+    if (*bp != 0xff)  /* end of run */
+      return (span + oneruns[*bp]);
+    span += 8, bits -= 8;
+    bp++;
+  }
+  /*
+   * Check partial byte on rhs.
+   */
+  if (bits > 0) {
+    n = oneruns[*bp];
+    span += (n > bits ? bits : n);
+  }
+  return (span);
+}
+
+/*
+ * Return the offset of the next bit in the range
+ * [bs..be] that is different from the specified
+ * color.  The end, be, is returned if no such bit
+ * exists.
+ */
+#define  finddiff(_cp, _bs, _be, _color)  \
+  (_bs + (_color ? find1span(_cp,_bs,_be) : find0span(_cp,_bs,_be)))
+/*
+ * Like finddiff, but also check the starting bit
+ * against the end in case start > end.
+ */
+#define  finddiff2(_cp, _bs, _be, _color) \
+  (_bs < _be ? finddiff(_cp,_bs,_be,_color) : _be)
+
+/*
+ * 1d-encode a row of pixels.  The encoding is
+ * a sequence of all-white or all-black spans
+ * of pixels encoded with Huffman codes.
+ */
+static int
+Fax3Encode1DRow(TIFF* tif, unsigned char* bp, uint32 bits)
+{
+  Fax3CodecState* sp = EncoderState(tif);
+  int32 span;
+        uint32 bs = 0;
+
+  for (;;) {
+    span = find0span(bp, bs, bits);    /* white span */
+    putspan(tif, span, TIFFFaxWhiteCodes);
+    bs += span;
+    if (bs >= bits)
+      break;
+    span = find1span(bp, bs, bits);    /* black span */
+    putspan(tif, span, TIFFFaxBlackCodes);
+    bs += span;
+    if (bs >= bits)
+      break;
+  }
+  if (sp->b.mode & (FAXMODE_BYTEALIGN|FAXMODE_WORDALIGN)) {
+    if (sp->bit != 8)      /* byte-align */
+      Fax3FlushBits(tif, sp);
+    if ((sp->b.mode&FAXMODE_WORDALIGN) &&
+        !isAligned(tif->tif_rawcp, uint16))
+      Fax3FlushBits(tif, sp);
+  }
+  return (1);
+}
+
+static const tableentry horizcode =
+    { 3, 0x1, 0 };    /* 001 */
+static const tableentry passcode =
+    { 4, 0x1, 0 };    /* 0001 */
+static const tableentry vcodes[7] = {
+    { 7, 0x03, 0 },  /* 0000 011 */
+    { 6, 0x03, 0 },  /* 0000 11 */
+    { 3, 0x03, 0 },  /* 011 */
+    { 1, 0x1, 0 },    /* 1 */
+    { 3, 0x2, 0 },    /* 010 */
+    { 6, 0x02, 0 },  /* 0000 10 */
+    { 7, 0x02, 0 }    /* 0000 010 */
+};
+
+/*
+ * 2d-encode a row of pixels.  Consult the CCITT
+ * documentation for the algorithm.
+ */
+static int
+Fax3Encode2DRow(TIFF* tif, unsigned char* bp, unsigned char* rp, uint32 bits)
+{
+#define  PIXEL(buf,ix)  ((((buf)[(ix)>>3]) >> (7-((ix)&7))) & 1)
+        uint32 a0 = 0;
+  uint32 a1 = (PIXEL(bp, 0) != 0 ? 0 : finddiff(bp, 0, bits, 0));
+  uint32 b1 = (PIXEL(rp, 0) != 0 ? 0 : finddiff(rp, 0, bits, 0));
+  uint32 a2, b2;
+
+  for (;;) {
+    b2 = finddiff2(rp, b1, bits, PIXEL(rp,b1));
+    if (b2 >= a1) {
+      int32 d = b1 - a1;
+      if (!(-3 <= d && d <= 3)) {  /* horizontal mode */
+        a2 = finddiff2(bp, a1, bits, PIXEL(bp,a1));
+        putcode(tif, &horizcode);
+        if (a0+a1 == 0 || PIXEL(bp, a0) == 0) {
+          putspan(tif, a1-a0, TIFFFaxWhiteCodes);
+          putspan(tif, a2-a1, TIFFFaxBlackCodes);
+        } else {
+          putspan(tif, a1-a0, TIFFFaxBlackCodes);
+          putspan(tif, a2-a1, TIFFFaxWhiteCodes);
+        }
+        a0 = a2;
+      } else {      /* vertical mode */
+        putcode(tif, &vcodes[d+3]);
+        a0 = a1;
+      }
+    } else {        /* pass mode */
+      putcode(tif, &passcode);
+      a0 = b2;
+    }
+    if (a0 >= bits)
+      break;
+    a1 = finddiff(bp, a0, bits, PIXEL(bp,a0));
+    b1 = finddiff(rp, a0, bits, !PIXEL(bp,a0));
+    b1 = finddiff(rp, b1, bits, PIXEL(bp,a0));
+  }
+  return (1);
+#undef PIXEL
+}
+
+/*
+ * Encode a buffer of pixels.
+ */
+static int
+Fax3Encode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
+{
+  Fax3CodecState* sp = EncoderState(tif);
+
+  (void) s;
+  while ((long)cc > 0) {
+    if ((sp->b.mode & FAXMODE_NOEOL) == 0)
+      Fax3PutEOL(tif);
+    if (is2DEncoding(sp)) {
+      if (sp->tag == G3_1D) {
+        if (!Fax3Encode1DRow(tif, bp, sp->b.rowpixels))
+          return (0);
+        sp->tag = G3_2D;
+      } else {
+        if (!Fax3Encode2DRow(tif, bp, sp->refline,
+                                                     sp->b.rowpixels))
+          return (0);
+        sp->k--;
+      }
+      if (sp->k == 0) {
+        sp->tag = G3_1D;
+        sp->k = sp->maxk-1;
+      } else
+        _TIFFmemcpy(sp->refline, bp, sp->b.rowbytes);
+    } else {
+      if (!Fax3Encode1DRow(tif, bp, sp->b.rowpixels))
+        return (0);
+    }
+    bp += sp->b.rowbytes;
+    cc -= sp->b.rowbytes;
+  }
+  return (1);
+}
+
+static int
+Fax3PostEncode(TIFF* tif)
+{
+  Fax3CodecState* sp = EncoderState(tif);
+
+  if (sp->bit != 8)
+    Fax3FlushBits(tif, sp);
+  return (1);
+}
+
+static void
+Fax3Close(TIFF* tif)
+{
+  if ((Fax3State(tif)->mode & FAXMODE_NORTC) == 0) {
+    Fax3CodecState* sp = EncoderState(tif);
+    unsigned int code = EOL;
+    unsigned int length = 12;
+    int i;
+
+    if (is2DEncoding(sp))
+      code = (code<<1) | (sp->tag == G3_1D), length++;
+    for (i = 0; i < 6; i++)
+      Fax3PutBits(tif, code, length);
+    Fax3FlushBits(tif, sp);
+  }
+}
+
+static void
+Fax3Cleanup(TIFF* tif)
+{
+  if (tif->tif_data) {
+    Fax3CodecState* sp = DecoderState(tif);
+
+    if (sp->runs)
+      _TIFFfree(sp->runs);
+    if (sp->refline)
+      _TIFFfree(sp->refline);
+
+    if (Fax3State(tif)->subaddress)
+      _TIFFfree(Fax3State(tif)->subaddress);
+    _TIFFfree(tif->tif_data);
+    tif->tif_data = NULL;
+  }
+}
+
+#define  FIELD_BADFAXLINES  (FIELD_CODEC+0)
+#define  FIELD_CLEANFAXDATA  (FIELD_CODEC+1)
+#define  FIELD_BADFAXRUN    (FIELD_CODEC+2)
+#define  FIELD_RECVPARAMS  (FIELD_CODEC+3)
+#define  FIELD_SUBADDRESS  (FIELD_CODEC+4)
+#define  FIELD_RECVTIME    (FIELD_CODEC+5)
+#define  FIELD_FAXDCS    (FIELD_CODEC+6)
+
+#define  FIELD_OPTIONS    (FIELD_CODEC+7)
+
+static const TIFFFieldInfo faxFieldInfo[] = {
+    { TIFFTAG_FAXMODE,     0, 0,  TIFF_ANY,  FIELD_PSEUDO,
+      FALSE,  FALSE,  "FaxMode" },
+    { TIFFTAG_FAXFILLFUNC,   0, 0,  TIFF_ANY,  FIELD_PSEUDO,
+      FALSE,  FALSE,  "FaxFillFunc" },
+    { TIFFTAG_BADFAXLINES,   1, 1,  TIFF_LONG,  FIELD_BADFAXLINES,
+      TRUE,  FALSE,  "BadFaxLines" },
+    { TIFFTAG_BADFAXLINES,   1, 1,  TIFF_SHORT,  FIELD_BADFAXLINES,
+      TRUE,  FALSE,  "BadFaxLines" },
+    { TIFFTAG_CLEANFAXDATA,   1, 1,  TIFF_SHORT,  FIELD_CLEANFAXDATA,
+      TRUE,  FALSE,  "CleanFaxData" },
+    { TIFFTAG_CONSECUTIVEBADFAXLINES,1,1, TIFF_LONG,  FIELD_BADFAXRUN,
+      TRUE,  FALSE,  "ConsecutiveBadFaxLines" },
+    { TIFFTAG_CONSECUTIVEBADFAXLINES,1,1, TIFF_SHORT,  FIELD_BADFAXRUN,
+      TRUE,  FALSE,  "ConsecutiveBadFaxLines" },
+    { TIFFTAG_FAXRECVPARAMS,   1, 1, TIFF_LONG,  FIELD_RECVPARAMS,
+      TRUE,  FALSE,  "FaxRecvParams" },
+    { TIFFTAG_FAXSUBADDRESS,  -1,-1, TIFF_ASCII,  FIELD_SUBADDRESS,
+      TRUE,  FALSE,  "FaxSubAddress" },
+    { TIFFTAG_FAXRECVTIME,   1, 1, TIFF_LONG,  FIELD_RECVTIME,
+      TRUE,  FALSE,  "FaxRecvTime" },
+    { TIFFTAG_FAXDCS,    -1,-1, TIFF_ASCII,  FIELD_FAXDCS,
+      TRUE,  FALSE,  "FaxDcs" },
+};
+static const TIFFFieldInfo fax3FieldInfo[] = {
+    { TIFFTAG_GROUP3OPTIONS,   1, 1,  TIFF_LONG,  FIELD_OPTIONS,
+      FALSE,  FALSE,  "Group3Options" },
+};
+static const TIFFFieldInfo fax4FieldInfo[] = {
+    { TIFFTAG_GROUP4OPTIONS,   1, 1,  TIFF_LONG,  FIELD_OPTIONS,
+      FALSE,  FALSE,  "Group4Options" },
+};
+#define  N(a)  (sizeof (a) / sizeof (a[0]))
+
+static int
+Fax3VSetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+  Fax3BaseState* sp = Fax3State(tif);
+
+  switch (tag) {
+  case TIFFTAG_FAXMODE:
+    sp->mode = va_arg(ap, int);
+    return (1);      /* NB: pseudo tag */
+  case TIFFTAG_FAXFILLFUNC:
+    DecoderState(tif)->fill = va_arg(ap, TIFFFaxFillFunc);
+    return (1);      /* NB: pseudo tag */
+  case TIFFTAG_GROUP3OPTIONS:
+    /* XXX: avoid reading options if compression mismatches. */
+    if (tif->tif_dir.td_compression == COMPRESSION_CCITTFAX3)
+      sp->groupoptions = va_arg(ap, uint32);
+    break;
+  case TIFFTAG_GROUP4OPTIONS:
+    /* XXX: avoid reading options if compression mismatches. */
+    if (tif->tif_dir.td_compression == COMPRESSION_CCITTFAX4)
+      sp->groupoptions = va_arg(ap, uint32);
+    break;
+  case TIFFTAG_BADFAXLINES:
+    sp->badfaxlines = va_arg(ap, uint32);
+    break;
+  case TIFFTAG_CLEANFAXDATA:
+    sp->cleanfaxdata = (uint16) va_arg(ap, int);
+    break;
+  case TIFFTAG_CONSECUTIVEBADFAXLINES:
+    sp->badfaxrun = va_arg(ap, uint32);
+    break;
+  case TIFFTAG_FAXRECVPARAMS:
+    sp->recvparams = va_arg(ap, uint32);
+    break;
+  case TIFFTAG_FAXSUBADDRESS:
+    _TIFFsetString(&sp->subaddress, va_arg(ap, char*));
+    break;
+  case TIFFTAG_FAXRECVTIME:
+    sp->recvtime = va_arg(ap, uint32);
+    break;
+  case TIFFTAG_FAXDCS:
+    _TIFFsetString(&sp->faxdcs, va_arg(ap, char*));
+    break;
+  default:
+    return (*sp->vsetparent)(tif, tag, ap);
+  }
+  TIFFSetFieldBit(tif, _TIFFFieldWithTag(tif, tag)->field_bit);
+  tif->tif_flags |= TIFF_DIRTYDIRECT;
+  return (1);
+}
+
+static int
+Fax3VGetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+  Fax3BaseState* sp = Fax3State(tif);
+
+  switch (tag) {
+  case TIFFTAG_FAXMODE:
+    *va_arg(ap, int*) = sp->mode;
+    break;
+  case TIFFTAG_FAXFILLFUNC:
+    *va_arg(ap, TIFFFaxFillFunc*) = DecoderState(tif)->fill;
+    break;
+  case TIFFTAG_GROUP3OPTIONS:
+  case TIFFTAG_GROUP4OPTIONS:
+    *va_arg(ap, uint32*) = sp->groupoptions;
+    break;
+  case TIFFTAG_BADFAXLINES:
+    *va_arg(ap, uint32*) = sp->badfaxlines;
+    break;
+  case TIFFTAG_CLEANFAXDATA:
+    *va_arg(ap, uint16*) = sp->cleanfaxdata;
+    break;
+  case TIFFTAG_CONSECUTIVEBADFAXLINES:
+    *va_arg(ap, uint32*) = sp->badfaxrun;
+    break;
+  case TIFFTAG_FAXRECVPARAMS:
+    *va_arg(ap, uint32*) = sp->recvparams;
+    break;
+  case TIFFTAG_FAXSUBADDRESS:
+    *va_arg(ap, char**) = sp->subaddress;
+    break;
+  case TIFFTAG_FAXRECVTIME:
+    *va_arg(ap, uint32*) = sp->recvtime;
+    break;
+  case TIFFTAG_FAXDCS:
+    *va_arg(ap, char**) = sp->faxdcs;
+    break;
+  default:
+    return (*sp->vgetparent)(tif, tag, ap);
+  }
+  return (1);
+}
+
+static void
+Fax3PrintDir(TIFF* tif, FILE* fd, long flags)
+{
+  Fax3BaseState* sp = Fax3State(tif);
+
+  (void) flags;
+  if (TIFFFieldSet(tif,FIELD_OPTIONS)) {
+    const char* sep = " ";
+    if (tif->tif_dir.td_compression == COMPRESSION_CCITTFAX4) {
+      fprintf(fd, "  Group 4 Options:");
+      if (sp->groupoptions & GROUP4OPT_UNCOMPRESSED)
+        fprintf(fd, "%suncompressed data", sep);
+    } else {
+
+      fprintf(fd, "  Group 3 Options:");
+      if (sp->groupoptions & GROUP3OPT_2DENCODING)
+        fprintf(fd, "%s2-d encoding", sep), sep = "+";
+      if (sp->groupoptions & GROUP3OPT_FILLBITS)
+        fprintf(fd, "%sEOL padding", sep), sep = "+";
+      if (sp->groupoptions & GROUP3OPT_UNCOMPRESSED)
+        fprintf(fd, "%suncompressed data", sep);
+    }
+    fprintf(fd, " (%lu = 0x%lx)\n",
+                        (unsigned long) sp->groupoptions,
+                        (unsigned long) sp->groupoptions);
+  }
+  if (TIFFFieldSet(tif,FIELD_CLEANFAXDATA)) {
+    fprintf(fd, "  Fax Data:");
+    switch (sp->cleanfaxdata) {
+    case CLEANFAXDATA_CLEAN:
+      fprintf(fd, " clean");
+      break;
+    case CLEANFAXDATA_REGENERATED:
+      fprintf(fd, " receiver regenerated");
+      break;
+    case CLEANFAXDATA_UNCLEAN:
+      fprintf(fd, " uncorrected errors");
+      break;
+    }
+    fprintf(fd, " (%u = 0x%x)\n",
+        sp->cleanfaxdata, sp->cleanfaxdata);
+  }
+  if (TIFFFieldSet(tif,FIELD_BADFAXLINES))
+    fprintf(fd, "  Bad Fax Lines: %lu\n",
+                        (unsigned long) sp->badfaxlines);
+  if (TIFFFieldSet(tif,FIELD_BADFAXRUN))
+    fprintf(fd, "  Consecutive Bad Fax Lines: %lu\n",
+        (unsigned long) sp->badfaxrun);
+  if (TIFFFieldSet(tif,FIELD_RECVPARAMS))
+    fprintf(fd, "  Fax Receive Parameters: %08lx\n",
+       (unsigned long) sp->recvparams);
+  if (TIFFFieldSet(tif,FIELD_SUBADDRESS))
+    fprintf(fd, "  Fax SubAddress: %s\n", sp->subaddress);
+  if (TIFFFieldSet(tif,FIELD_RECVTIME))
+    fprintf(fd, "  Fax Receive Time: %lu secs\n",
+        (unsigned long) sp->recvtime);
+  if (TIFFFieldSet(tif,FIELD_FAXDCS))
+    fprintf(fd, "  Fax DCS: %s\n", sp->faxdcs);
+}
+
+static int
+InitCCITTFax3(TIFF* tif)
+{
+  Fax3BaseState* sp;
+
+  /*
+   * Allocate state block so tag methods have storage to record values.
+   */
+  tif->tif_data = (tidata_t)
+    _TIFFmalloc(sizeof (Fax3CodecState));
+
+  if (tif->tif_data == NULL) {
+    TIFFError("TIFFInitCCITTFax3",
+        "%s: No space for state block", tif->tif_name);
+    return (0);
+  }
+
+  sp = Fax3State(tif);
+        sp->rw_mode = tif->tif_mode;
+
+  /*
+   * Merge codec-specific tag information and
+   * override parent get/set field methods.
+   */
+  _TIFFMergeFieldInfo(tif, faxFieldInfo, N(faxFieldInfo));
+  sp->vgetparent = tif->tif_tagmethods.vgetfield;
+  tif->tif_tagmethods.vgetfield = Fax3VGetField; /* hook for codec tags */
+  sp->vsetparent = tif->tif_tagmethods.vsetfield;
+  tif->tif_tagmethods.vsetfield = Fax3VSetField; /* hook for codec tags */
+  tif->tif_tagmethods.printdir = Fax3PrintDir;   /* hook for codec tags */
+  sp->groupoptions = 0;  
+  sp->recvparams = 0;
+  sp->subaddress = NULL;
+  sp->faxdcs = NULL;
+
+  if (sp->rw_mode == O_RDONLY) /* FIXME: improve for in place update */
+    tif->tif_flags |= TIFF_NOBITREV; /* decoder does bit reversal */
+  DecoderState(tif)->runs = NULL;
+  TIFFSetField(tif, TIFFTAG_FAXFILLFUNC, _TIFFFax3fillruns);
+  EncoderState(tif)->refline = NULL;
+
+  /*
+   * Install codec methods.
+   */
+  tif->tif_setupdecode = Fax3SetupState;
+  tif->tif_predecode = Fax3PreDecode;
+  tif->tif_decoderow = Fax3Decode1D;
+  tif->tif_decodestrip = Fax3Decode1D;
+  tif->tif_decodetile = Fax3Decode1D;
+  tif->tif_setupencode = Fax3SetupState;
+  tif->tif_preencode = Fax3PreEncode;
+  tif->tif_postencode = Fax3PostEncode;
+  tif->tif_encoderow = Fax3Encode;
+  tif->tif_encodestrip = Fax3Encode;
+  tif->tif_encodetile = Fax3Encode;
+  tif->tif_close = Fax3Close;
+  tif->tif_cleanup = Fax3Cleanup;
+
+  return (1);
+}
+
+int
+TIFFInitCCITTFax3(TIFF* tif, int scheme)
+{
+  (void)scheme;
+  if (InitCCITTFax3(tif)) {
+    _TIFFMergeFieldInfo(tif, fax3FieldInfo, N(fax3FieldInfo));
+
+    /*
+     * The default format is Class/F-style w/o RTC.
+     */
+    return TIFFSetField(tif, TIFFTAG_FAXMODE, FAXMODE_CLASSF);
+  } else
+    return (0);
+}
+
+/*
+ * CCITT Group 4 (T.6) Facsimile-compatible
+ * Compression Scheme Support.
+ */
+
+#define  SWAP(t,a,b)  { t x; x = (a); (a) = (b); (b) = x; }
+/*
+ * Decode the requested amount of G4-encoded data.
+ */
+static int
+Fax4Decode(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s)
+{
+  DECLARE_STATE_2D(tif, sp, "Fax4Decode");
+
+  (void) s;
+  CACHE_STATE(tif, sp);
+  while ((long)occ > 0) {
+    a0 = 0;
+    RunLength = 0;
+    pa = thisrun = sp->curruns;
+    pb = sp->refruns;
+    b1 = *pb++;
+#ifdef FAX3_DEBUG
+    printf("\nBitAcc=%08X, BitsAvail = %d\n", BitAcc, BitsAvail);
+    printf("-------------------- %d\n", tif->tif_row);
+    fflush(stdout);
+#endif
+    EXPAND2D(EOFG4);
+                if (EOLcnt)
+                    goto EOFG4;
+    (*sp->fill)(buf, thisrun, pa, lastx);
+    SETVAL(0);    /* imaginary change for reference */
+    SWAP(uint32*, sp->curruns, sp->refruns);
+    buf += sp->b.rowbytes;
+    occ -= sp->b.rowbytes;
+    continue;
+  EOFG4:
+                NeedBits16( 13, BADG4 );
+        BADG4:
+#ifdef FAX3_DEBUG
+                if( GetBits(13) != 0x1001 )
+                    fputs( "Bad RTC\n", stderr );
+#endif                
+                ClrBits( 13 );
+    (*sp->fill)(buf, thisrun, pa, lastx);
+    UNCACHE_STATE(tif, sp);
+    return (-1);
+  }
+  UNCACHE_STATE(tif, sp);
+  return (1);
+}
+#undef  SWAP
+
+/*
+ * Encode the requested amount of data.
+ */
+static int
+Fax4Encode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
+{
+  Fax3CodecState *sp = EncoderState(tif);
+
+  (void) s;
+  while ((long)cc > 0) {
+    if (!Fax3Encode2DRow(tif, bp, sp->refline, sp->b.rowpixels))
+      return (0);
+    _TIFFmemcpy(sp->refline, bp, sp->b.rowbytes);
+    bp += sp->b.rowbytes;
+    cc -= sp->b.rowbytes;
+  }
+  return (1);
+}
+
+static int
+Fax4PostEncode(TIFF* tif)
+{
+  Fax3CodecState *sp = EncoderState(tif);
+
+  /* terminate strip w/ EOFB */
+  Fax3PutBits(tif, EOL, 12);
+  Fax3PutBits(tif, EOL, 12);
+  if (sp->bit != 8)
+    Fax3FlushBits(tif, sp);
+  return (1);
+}
+
+int
+TIFFInitCCITTFax4(TIFF* tif, int scheme)
+{
+  (void)scheme;
+  if (InitCCITTFax3(tif)) {    /* reuse G3 support */
+    _TIFFMergeFieldInfo(tif, fax4FieldInfo, N(fax4FieldInfo));
+
+    tif->tif_decoderow = Fax4Decode;
+    tif->tif_decodestrip = Fax4Decode;
+    tif->tif_decodetile = Fax4Decode;
+    tif->tif_encoderow = Fax4Encode;
+    tif->tif_encodestrip = Fax4Encode;
+    tif->tif_encodetile = Fax4Encode;
+    tif->tif_postencode = Fax4PostEncode;
+    /*
+     * Suppress RTC at the end of each strip.
+     */
+    return TIFFSetField(tif, TIFFTAG_FAXMODE, FAXMODE_NORTC);
+  } else
+    return (0);
+}
+
+/*
+ * CCITT Group 3 1-D Modified Huffman RLE Compression Support.
+ * (Compression algorithms 2 and 32771)
+ */
+
+/*
+ * Decode the requested amount of RLE-encoded data.
+ */
+static int
+Fax3DecodeRLE(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s)
+{
+  DECLARE_STATE(tif, sp, "Fax3DecodeRLE");
+  int mode = sp->b.mode;
+
+  (void) s;
+  CACHE_STATE(tif, sp);
+  thisrun = sp->curruns;
+  while ((long)occ > 0) {
+    a0 = 0;
+    RunLength = 0;
+    pa = thisrun;
+#ifdef FAX3_DEBUG
+    printf("\nBitAcc=%08X, BitsAvail = %d\n", BitAcc, BitsAvail);
+    printf("-------------------- %d\n", tif->tif_row);
+    fflush(stdout);
+#endif
+    EXPAND1D(EOFRLE);
+    (*sp->fill)(buf, thisrun, pa, lastx);
+    /*
+     * Cleanup at the end of the row.
+     */
+    if (mode & FAXMODE_BYTEALIGN) {
+      int n = BitsAvail - (BitsAvail &~ 7);
+      ClrBits(n);
+    } else if (mode & FAXMODE_WORDALIGN) {
+      int n = BitsAvail - (BitsAvail &~ 15);
+      ClrBits(n);
+      if (BitsAvail == 0 && !isAligned(cp, uint16))
+          cp++;
+    }
+    buf += sp->b.rowbytes;
+    occ -= sp->b.rowbytes;
+    continue;
+  EOFRLE:        /* premature EOF */
+    (*sp->fill)(buf, thisrun, pa, lastx);
+    UNCACHE_STATE(tif, sp);
+    return (-1);
+  }
+  UNCACHE_STATE(tif, sp);
+  return (1);
+}
+
+int
+TIFFInitCCITTRLE(TIFF* tif, int scheme)
+{
+  (void)scheme;
+  if (InitCCITTFax3(tif)) {    /* reuse G3 support */
+    tif->tif_decoderow = Fax3DecodeRLE;
+    tif->tif_decodestrip = Fax3DecodeRLE;
+    tif->tif_decodetile = Fax3DecodeRLE;
+    /*
+     * Suppress RTC+EOLs when encoding and byte-align data.
+     */
+    return TIFFSetField(tif, TIFFTAG_FAXMODE,
+        FAXMODE_NORTC|FAXMODE_NOEOL|FAXMODE_BYTEALIGN);
+  } else
+    return (0);
+}
+
+int
+TIFFInitCCITTRLEW(TIFF* tif, int scheme)
+{
+  (void)scheme;
+  if (InitCCITTFax3(tif)) {    /* reuse G3 support */
+    tif->tif_decoderow = Fax3DecodeRLE;
+    tif->tif_decodestrip = Fax3DecodeRLE;
+    tif->tif_decodetile = Fax3DecodeRLE;
+    /*
+     * Suppress RTC+EOLs when encoding and word-align data.
+     */
+    return TIFFSetField(tif, TIFFTAG_FAXMODE,
+        FAXMODE_NORTC|FAXMODE_NOEOL|FAXMODE_WORDALIGN);
+  } else
+    return (0);
+}
+#endif /* CCITT_SUPPORT */
+
diff --git a/Utilities/ITK/Utilities/tiff/tif_fax3.h b/Utilities/ITK/Utilities/tiff/tif_fax3.h
new file mode 100644
index 0000000000..8b53f1b272
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_fax3.h
@@ -0,0 +1,526 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1990-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _FAX3_
+#define  _FAX3_
+/*
+ * TIFF Library.
+ *
+ * CCITT Group 3 (T.4) and Group 4 (T.6) Decompression Support.
+ *
+ * Decoder support is derived, with permission, from the code
+ * in Frank Cringle's viewfax program;
+ *      Copyright (C) 1990, 1995  Frank D. Cringle.
+ */
+#include "tiff.h"
+
+/*
+ * To override the default routine used to image decoded
+ * spans one can use the pseduo tag TIFFTAG_FAXFILLFUNC.
+ * The routine must have the type signature given below;
+ * for example:
+ *
+ * fillruns(unsigned char* buf, uint32* runs, uint32* erun, uint32 lastx)
+ *
+ * where buf is place to set the bits, runs is the array of b&w run
+ * lengths (white then black), erun is the last run in the array, and
+ * lastx is the width of the row in pixels.  Fill routines can assume
+ * the run array has room for at least lastx runs and can overwrite
+ * data in the run array as needed (e.g. to append zero runs to bring
+ * the count up to a nice multiple).
+ */
+typedef  void (*TIFFFaxFillFunc)(unsigned char*, uint32*, uint32*, uint32);
+
+/*
+ * The default run filler; made external for other decoders.
+ */
+#if defined(__cplusplus)
+extern "C" {
+#endif
+extern  void _TIFFFax3fillruns(unsigned char*, uint32*, uint32*, uint32);
+#if defined(__cplusplus)
+}
+#endif
+
+
+/* finite state machine codes */
+#define S_Null    0
+#define S_Pass    1
+#define S_Horiz    2
+#define S_V0    3
+#define S_VR    4
+#define S_VL    5
+#define S_Ext    6
+#define S_TermW    7
+#define S_TermB    8
+#define S_MakeUpW  9
+#define S_MakeUpB  10
+#define S_MakeUp  11
+#define S_EOL    12
+
+typedef struct {    /* state table entry */
+  unsigned char State;  /* see above */
+  unsigned char Width;  /* width of code in bits */
+  uint32  Param;    /* unsigned 32-bit run length in bits */
+} TIFFFaxTabEnt;
+
+extern  const TIFFFaxTabEnt TIFFFaxMainTable[];
+extern  const TIFFFaxTabEnt TIFFFaxWhiteTable[];
+extern  const TIFFFaxTabEnt TIFFFaxBlackTable[];
+
+/*
+ * The following macros define the majority of the G3/G4 decoder
+ * algorithm using the state tables defined elsewhere.  To build
+ * a decoder you need some setup code and some glue code. Note
+ * that you may also need/want to change the way the NeedBits*
+ * macros get input data if, for example, you know the data to be
+ * decoded is properly aligned and oriented (doing so before running
+ * the decoder can be a big performance win).
+ *
+ * Consult the decoder in the TIFF library for an idea of what you
+ * need to define and setup to make use of these definitions.
+ *
+ * NB: to enable a debugging version of these macros define FAX3_DEBUG
+ *     before including this file.  Trace output goes to stdout.
+ */
+
+#ifndef EndOfData
+#define EndOfData()  (cp >= ep)
+#endif
+/*
+ * Need <=8 or <=16 bits of input data.  Unlike viewfax we
+ * cannot use/assume a word-aligned, properly bit swizzled
+ * input data set because data may come from an arbitrarily
+ * aligned, read-only source such as a memory-mapped file.
+ * Note also that the viewfax decoder does not check for
+ * running off the end of the input data buffer.  This is
+ * possible for G3-encoded data because it prescans the input
+ * data to count EOL markers, but can cause problems for G4
+ * data.  In any event, we don't prescan and must watch for
+ * running out of data since we can't permit the library to
+ * scan past the end of the input data buffer.
+ *
+ * Finally, note that we must handle remaindered data at the end
+ * of a strip specially.  The coder asks for a fixed number of
+ * bits when scanning for the next code.  This may be more bits
+ * than are actually present in the data stream.  If we appear
+ * to run out of data but still have some number of valid bits
+ * remaining then we makeup the requested amount with zeros and
+ * return successfully.  If the returned data is incorrect then
+ * we should be called again and get a premature EOF error;
+ * otherwise we should get the right answer.
+ */
+#ifndef NeedBits8
+#define NeedBits8(n,eoflab) do {          \
+    if (BitsAvail < (n)) {            \
+  if (EndOfData()) {            \
+      if (BitsAvail == 0)      /* no valid bits */  \
+    goto eoflab;            \
+      BitsAvail = (n);      /* pad with zeros */  \
+  } else {              \
+      BitAcc |= ((uint32) bitmap[*cp++])<<BitsAvail;    \
+      BitsAvail += 8;            \
+  }                \
+    }                  \
+} while (0)
+#endif
+#ifndef NeedBits16
+#define NeedBits16(n,eoflab) do {          \
+    if (BitsAvail < (n)) {            \
+  if (EndOfData()) {            \
+      if (BitsAvail == 0)      /* no valid bits */  \
+    goto eoflab;            \
+      BitsAvail = (n);      /* pad with zeros */  \
+  } else {              \
+      BitAcc |= ((uint32) bitmap[*cp++])<<BitsAvail;    \
+      if ((BitsAvail += 8) < (n)) {        \
+    if (EndOfData()) {          \
+        /* NB: we know BitsAvail is non-zero here */  \
+        BitsAvail = (n);    /* pad with zeros */  \
+    } else {            \
+        BitAcc |= ((uint32) bitmap[*cp++])<<BitsAvail;  \
+        BitsAvail += 8;          \
+    }              \
+      }                \
+  }                \
+    }                  \
+} while (0)
+#endif
+#define GetBits(n)  (BitAcc & ((1<<(n))-1))
+#define ClrBits(n) do {              \
+    BitsAvail -= (n);              \
+    BitAcc >>= (n);              \
+} while (0)
+
+#ifdef FAX3_DEBUG
+static const char* StateNames[] = {
+    "Null   ",
+    "Pass   ",
+    "Horiz  ",
+    "V0     ",
+    "VR     ",
+    "VL     ",
+    "Ext    ",
+    "TermW  ",
+    "TermB  ",
+    "MakeUpW",
+    "MakeUpB",
+    "MakeUp ",
+    "EOL    ",
+};
+#define DEBUG_SHOW putchar(BitAcc & (1 << t) ? '1' : '0')
+#define LOOKUP8(wid,tab,eoflab) do {          \
+    int t;                \
+    NeedBits8(wid,eoflab);            \
+    TabEnt = tab + GetBits(wid);          \
+    printf("%08lX/%d: %s%5d\t", (long) BitAcc, BitsAvail,    \
+     StateNames[TabEnt->State], TabEnt->Param);      \
+    for (t = 0; t < TabEnt->Width; t++)          \
+  DEBUG_SHOW;              \
+    putchar('\n');              \
+    fflush(stdout);              \
+    ClrBits(TabEnt->Width);            \
+} while (0)
+#define LOOKUP16(wid,tab,eoflab) do {          \
+    int t;                \
+    NeedBits16(wid,eoflab);            \
+    TabEnt = tab + GetBits(wid);          \
+    printf("%08lX/%d: %s%5d\t", (long) BitAcc, BitsAvail,    \
+     StateNames[TabEnt->State], TabEnt->Param);      \
+    for (t = 0; t < TabEnt->Width; t++)          \
+  DEBUG_SHOW;              \
+    putchar('\n');              \
+    fflush(stdout);              \
+    ClrBits(TabEnt->Width);            \
+} while (0)
+
+#define SETVAL(x) do {              \
+    *pa++ = RunLength + (x);            \
+    printf("SETVAL: %d\t%d\n", RunLength + (x), a0);      \
+    a0 += x;                \
+    RunLength = 0;              \
+} while (0)
+#else
+#define LOOKUP8(wid,tab,eoflab) do {          \
+    NeedBits8(wid,eoflab);            \
+    TabEnt = tab + GetBits(wid);          \
+    ClrBits(TabEnt->Width);            \
+} while (0)
+#define LOOKUP16(wid,tab,eoflab) do {          \
+    NeedBits16(wid,eoflab);            \
+    TabEnt = tab + GetBits(wid);          \
+    ClrBits(TabEnt->Width);            \
+} while (0)
+
+/*
+ * Append a run to the run length array for the
+ * current row and reset decoding state.
+ */
+#define SETVAL(x) do {              \
+    *pa++ = RunLength + (x);            \
+    a0 += (x);                \
+    RunLength = 0;              \
+} while (0)
+#endif
+
+/*
+ * Synchronize input decoding at the start of each
+ * row by scanning for an EOL (if appropriate) and
+ * skipping any trash data that might be present
+ * after a decoding error.  Note that the decoding
+ * done elsewhere that recognizes an EOL only consumes
+ * 11 consecutive zero bits.  This means that if EOLcnt
+ * is non-zero then we still need to scan for the final flag
+ * bit that is part of the EOL code.
+ */
+#define  SYNC_EOL(eoflab) do {            \
+    if (EOLcnt == 0) {              \
+  for (;;) {              \
+      NeedBits16(11,eoflab);          \
+      if (GetBits(11) == 0)          \
+    break;              \
+      ClrBits(1);              \
+  }                \
+    }                  \
+    for (;;) {                \
+  NeedBits8(8,eoflab);            \
+  if (GetBits(8))              \
+      break;              \
+  ClrBits(8);              \
+    }                  \
+    while (GetBits(1) == 0)            \
+  ClrBits(1);              \
+    ClrBits(1);        /* EOL bit */      \
+    EOLcnt = 0;        /* reset EOL counter/flag */  \
+} while (0)
+
+/*
+ * Cleanup the array of runs after decoding a row.
+ * We adjust final runs to insure the user buffer is not
+ * overwritten and/or undecoded area is white filled.
+ */
+#define  CLEANUP_RUNS() do {            \
+  if (RunLength) {            \
+    SETVAL(0);              \
+  }                         \
+  if (a0 != lastx) {              \
+    badlength(a0, lastx);            \
+    while (a0 > lastx && pa > thisrun)        \
+    a0 -= *--pa;            \
+    if (a0 < lastx) {            \
+      if (a0 < 0)              \
+      a0 = 0;              \
+      if ((pa-thisrun)&1)            \
+      SETVAL(0);            \
+      SETVAL(lastx - a0);            \
+    } else if (a0 > lastx) {          \
+      SETVAL(lastx);            \
+      SETVAL(0);              \
+    }                \
+  }                  \
+} while (0)
+
+/*
+ * Decode a line of 1D-encoded data.
+ *
+ * The line expanders are written as macros so that they can be reused
+ * but still have direct access to the local variables of the "calling"
+ * function.
+ *
+ * Note that unlike the original version we have to explicitly test for
+ * a0 >= lastx after each black/white run is decoded.  This is because
+ * the original code depended on the input data being zero-padded to
+ * insure the decoder recognized an EOL before running out of data.
+ */
+#define EXPAND1D(eoflab) do {            \
+    for (;;) {                \
+  for (;;) {              \
+      LOOKUP16(12, TIFFFaxWhiteTable, eof1d);      \
+      switch (TabEnt->State) {          \
+      case S_EOL:              \
+    EOLcnt = 1;            \
+    goto done1d;            \
+      case S_TermW:            \
+    SETVAL(TabEnt->Param);          \
+    goto doneWhite1d;          \
+      case S_MakeUpW:            \
+      case S_MakeUp:            \
+    a0 += TabEnt->Param;          \
+    RunLength += TabEnt->Param;        \
+    break;              \
+      default:              \
+    unexpected("WhiteTable", a0);        \
+    goto done1d;            \
+      }                \
+  }                \
+    doneWhite1d:              \
+  if (a0 >= lastx)            \
+      goto done1d;            \
+  for (;;) {              \
+      LOOKUP16(13, TIFFFaxBlackTable, eof1d);      \
+      switch (TabEnt->State) {          \
+      case S_EOL:              \
+    EOLcnt = 1;            \
+    goto done1d;            \
+      case S_TermB:            \
+    SETVAL(TabEnt->Param);          \
+    goto doneBlack1d;          \
+      case S_MakeUpB:            \
+      case S_MakeUp:            \
+    a0 += TabEnt->Param;          \
+    RunLength += TabEnt->Param;        \
+    break;              \
+      default:              \
+    unexpected("BlackTable", a0);        \
+    goto done1d;            \
+      }                \
+  }                \
+    doneBlack1d:              \
+  if (a0 >= lastx)            \
+      goto done1d;            \
+        if( *(pa-1) == 0 && *(pa-2) == 0 )        \
+            pa -= 2;                                                    \
+    }                  \
+eof1d:                  \
+    prematureEOF(a0);              \
+    CLEANUP_RUNS();              \
+    goto eoflab;              \
+done1d:                  \
+    CLEANUP_RUNS();              \
+} while (0)
+
+/*
+ * Update the value of b1 using the array
+ * of runs for the reference line.
+ */
+#define CHECK_b1 do {              \
+    if (pa != thisrun) while (b1 <= a0 && b1 < lastx) {      \
+  b1 += pb[0] + pb[1];            \
+  pb += 2;              \
+    }                  \
+} while (0)
+
+/*
+ * Expand a row of 2D-encoded data.
+ */
+#define EXPAND2D(eoflab) do {            \
+    while (a0 < lastx) {            \
+  LOOKUP8(7, TIFFFaxMainTable, eof2d);        \
+  switch (TabEnt->State) {          \
+  case S_Pass:              \
+      CHECK_b1;              \
+      b1 += *pb++;            \
+      RunLength += b1 - a0;          \
+      a0 = b1;              \
+      b1 += *pb++;            \
+      break;              \
+  case S_Horiz:              \
+      if ((pa-thisrun)&1) {          \
+    for (;;) {  /* black first */      \
+        LOOKUP16(13, TIFFFaxBlackTable, eof2d);    \
+        switch (TabEnt->State) {        \
+        case S_TermB:          \
+      SETVAL(TabEnt->Param);        \
+      goto doneWhite2da;        \
+        case S_MakeUpB:          \
+        case S_MakeUp:          \
+      a0 += TabEnt->Param;        \
+      RunLength += TabEnt->Param;      \
+      break;            \
+        default:            \
+      goto badBlack2d;        \
+        }              \
+    }              \
+      doneWhite2da:;            \
+    for (;;) {  /* then white */      \
+        LOOKUP16(12, TIFFFaxWhiteTable, eof2d);    \
+        switch (TabEnt->State) {        \
+        case S_TermW:          \
+      SETVAL(TabEnt->Param);        \
+      goto doneBlack2da;        \
+        case S_MakeUpW:          \
+        case S_MakeUp:          \
+      a0 += TabEnt->Param;        \
+      RunLength += TabEnt->Param;      \
+      break;            \
+        default:            \
+      goto badWhite2d;        \
+        }              \
+    }              \
+      doneBlack2da:;            \
+      } else {              \
+    for (;;) {  /* white first */      \
+        LOOKUP16(12, TIFFFaxWhiteTable, eof2d);    \
+        switch (TabEnt->State) {        \
+        case S_TermW:          \
+      SETVAL(TabEnt->Param);        \
+      goto doneWhite2db;        \
+        case S_MakeUpW:          \
+        case S_MakeUp:          \
+      a0 += TabEnt->Param;        \
+      RunLength += TabEnt->Param;      \
+      break;            \
+        default:            \
+      goto badWhite2d;        \
+        }              \
+    }              \
+      doneWhite2db:;            \
+    for (;;) {  /* then black */      \
+        LOOKUP16(13, TIFFFaxBlackTable, eof2d);    \
+        switch (TabEnt->State) {        \
+        case S_TermB:          \
+      SETVAL(TabEnt->Param);        \
+      goto doneBlack2db;        \
+        case S_MakeUpB:          \
+        case S_MakeUp:          \
+      a0 += TabEnt->Param;        \
+      RunLength += TabEnt->Param;      \
+      break;            \
+        default:            \
+      goto badBlack2d;        \
+        }              \
+    }              \
+      doneBlack2db:;            \
+      }                \
+      CHECK_b1;              \
+      break;              \
+  case S_V0:              \
+      CHECK_b1;              \
+      SETVAL(b1 - a0);            \
+      b1 += *pb++;            \
+      break;              \
+  case S_VR:              \
+      CHECK_b1;              \
+      SETVAL(b1 - a0 + TabEnt->Param);        \
+      b1 += *pb++;            \
+      break;              \
+  case S_VL:              \
+      CHECK_b1;              \
+      SETVAL(b1 - a0 - TabEnt->Param);        \
+      b1 -= *--pb;            \
+      break;              \
+  case S_Ext:              \
+      *pa++ = lastx - a0;            \
+      extension(a0);            \
+      goto eol2d;              \
+  case S_EOL:              \
+      *pa++ = lastx - a0;            \
+      NeedBits8(4,eof2d);            \
+      if (GetBits(4))            \
+    unexpected("EOL", a0);          \
+            ClrBits(4);                                                 \
+      EOLcnt = 1;              \
+      goto eol2d;              \
+  default:              \
+  badMain2d:              \
+      unexpected("MainTable", a0);        \
+      goto eol2d;              \
+  badBlack2d:              \
+      unexpected("BlackTable", a0);        \
+      goto eol2d;              \
+  badWhite2d:              \
+      unexpected("WhiteTable", a0);        \
+      goto eol2d;              \
+  eof2d:                \
+      prematureEOF(a0);            \
+      CLEANUP_RUNS();            \
+      goto eoflab;            \
+  }                \
+    }                  \
+    if (RunLength) {              \
+  if (RunLength + a0 < lastx) {          \
+      /* expect a final V0 */          \
+      NeedBits8(1,eof2d);            \
+      if (!GetBits(1))            \
+    goto badMain2d;            \
+      ClrBits(1);              \
+  }                \
+  SETVAL(0);              \
+    }                  \
+eol2d:                  \
+    CLEANUP_RUNS();              \
+} while (0)
+#endif /* _FAX3_ */
diff --git a/Utilities/ITK/Utilities/tiff/tif_fax3sm.c b/Utilities/ITK/Utilities/tiff/tif_fax3sm.c
new file mode 100644
index 0000000000..08ce1ad608
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_fax3sm.c
@@ -0,0 +1,1253 @@
+/* WARNING, this file was automatically generated by the
+    mkg3states program */
+#include "tiff.h"
+#include "tif_fax3.h"
+ const TIFFFaxTabEnt TIFFFaxMainTable[128] = {
+{12,7,0},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0},{1,4,0},{3,1,0},
+{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0},{5,6,2},{3,1,0},{5,3,1},{3,1,0},
+{2,3,0},{3,1,0},{4,3,1},{3,1,0},{1,4,0},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0},
+{4,3,1},{3,1,0},{5,7,3},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0},
+{1,4,0},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0},{4,6,2},{3,1,0},
+{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0},{1,4,0},{3,1,0},{5,3,1},{3,1,0},
+{2,3,0},{3,1,0},{4,3,1},{3,1,0},{6,7,0},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0},
+{4,3,1},{3,1,0},{1,4,0},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0},
+{5,6,2},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0},{1,4,0},{3,1,0},
+{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0},{4,7,3},{3,1,0},{5,3,1},{3,1,0},
+{2,3,0},{3,1,0},{4,3,1},{3,1,0},{1,4,0},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0},
+{4,3,1},{3,1,0},{4,6,2},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0},
+{1,4,0},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0}
+};
+ const TIFFFaxTabEnt TIFFFaxWhiteTable[4096] = {
+{12,11,0},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},
+{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},
+{7,8,39},{7,6,16},{9,8,576},{7,4,6},{7,7,19},{7,5,8},{7,8,55},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,8,45},{7,4,3},{7,5,11},{7,4,5},{7,8,53},{7,5,9},{9,8,448},{7,4,6},
+{7,8,35},{9,5,128},{7,8,51},{7,6,15},{7,8,63},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},
+{9,9,1472},{7,4,5},{7,8,43},{7,6,17},{9,9,1216},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,29},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},
+{9,6,1664},{7,4,6},{7,8,33},{9,5,128},{7,8,49},{7,6,14},{7,8,61},{7,4,4},{7,4,2},{7,4,7},
+{7,8,47},{7,4,3},{7,8,59},{7,4,5},{7,8,41},{7,6,16},{9,9,960},{7,4,6},{7,8,31},{7,5,8},
+{7,8,57},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},
+{7,7,26},{7,5,9},{9,9,704},{7,4,6},{7,8,37},{9,5,128},{7,7,25},{7,6,15},{9,8,320},{7,4,4},
+{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},
+{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{11,11,1792},{7,4,3},
+{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},
+{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,40},{7,6,16},
+{9,9,832},{7,4,6},{7,7,19},{7,5,8},{7,8,56},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,8,46},{7,4,3},{7,5,11},{7,4,5},{7,8,54},{7,5,9},{9,8,512},{7,4,6},{7,8,36},{9,5,128},
+{7,8,52},{7,6,15},{7,8,0},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1600},{7,4,5},
+{7,8,44},{7,6,17},{9,9,1344},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,8,30},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},
+{7,8,34},{9,5,128},{7,8,50},{7,6,14},{7,8,62},{7,4,4},{7,4,2},{7,4,7},{7,8,48},{7,4,3},
+{7,8,60},{7,4,5},{7,8,42},{7,6,16},{9,9,1088},{7,4,6},{7,8,32},{7,5,8},{7,8,58},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},
+{9,8,640},{7,4,6},{7,8,38},{9,5,128},{7,7,25},{7,6,15},{9,8,384},{7,4,4},{7,4,2},{7,4,7},
+{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},
+{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{0,0,0},{7,4,3},{7,5,11},{7,4,5},
+{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},
+{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,39},{7,6,16},{9,8,576},{7,4,6},
+{7,7,19},{7,5,8},{7,8,55},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,45},{7,4,3},
+{7,5,11},{7,4,5},{7,8,53},{7,5,9},{9,8,448},{7,4,6},{7,8,35},{9,5,128},{7,8,51},{7,6,15},
+{7,8,63},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1536},{7,4,5},{7,8,43},{7,6,17},
+{9,9,1280},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,8,29},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,33},{9,5,128},
+{7,8,49},{7,6,14},{7,8,61},{7,4,4},{7,4,2},{7,4,7},{7,8,47},{7,4,3},{7,8,59},{7,4,5},
+{7,8,41},{7,6,16},{9,9,1024},{7,4,6},{7,8,31},{7,5,8},{7,8,57},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,9,768},{7,4,6},
+{7,8,37},{9,5,128},{7,7,25},{7,6,15},{9,8,320},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},
+{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{11,11,1856},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},
+{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},
+{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,40},{7,6,16},{9,9,896},{7,4,6},{7,7,19},{7,5,8},
+{7,8,56},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,46},{7,4,3},{7,5,11},{7,4,5},
+{7,8,54},{7,5,9},{9,8,512},{7,4,6},{7,8,36},{9,5,128},{7,8,52},{7,6,15},{7,8,0},{7,4,4},
+{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1728},{7,4,5},{7,8,44},{7,6,17},{9,9,1408},{7,4,6},
+{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,30},{7,4,3},
+{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,34},{9,5,128},{7,8,50},{7,6,14},
+{7,8,62},{7,4,4},{7,4,2},{7,4,7},{7,8,48},{7,4,3},{7,8,60},{7,4,5},{7,8,42},{7,6,16},
+{9,9,1152},{7,4,6},{7,8,32},{7,5,8},{7,8,58},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,8,640},{7,4,6},{7,8,38},{9,5,128},
+{7,7,25},{7,6,15},{9,8,384},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},
+{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{0,0,0},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},
+{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},
+{7,7,27},{7,4,5},{7,8,39},{7,6,16},{9,8,576},{7,4,6},{7,7,19},{7,5,8},{7,8,55},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,45},{7,4,3},{7,5,11},{7,4,5},{7,8,53},{7,5,9},
+{9,8,448},{7,4,6},{7,8,35},{9,5,128},{7,8,51},{7,6,15},{7,8,63},{7,4,4},{7,4,2},{7,4,7},
+{7,6,13},{7,4,3},{9,9,1472},{7,4,5},{7,8,43},{7,6,17},{9,9,1216},{7,4,6},{7,6,1},{7,5,8},
+{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,29},{7,4,3},{7,5,11},{7,4,5},
+{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,33},{9,5,128},{7,8,49},{7,6,14},{7,8,61},{7,4,4},
+{7,4,2},{7,4,7},{7,8,47},{7,4,3},{7,8,59},{7,4,5},{7,8,41},{7,6,16},{9,9,960},{7,4,6},
+{7,8,31},{7,5,8},{7,8,57},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},
+{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,9,704},{7,4,6},{7,8,37},{9,5,128},{7,7,25},{7,6,15},
+{9,8,320},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},
+{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{11,12,2112},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},
+{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},
+{7,8,40},{7,6,16},{9,9,832},{7,4,6},{7,7,19},{7,5,8},{7,8,56},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,8,46},{7,4,3},{7,5,11},{7,4,5},{7,8,54},{7,5,9},{9,8,512},{7,4,6},
+{7,8,36},{9,5,128},{7,8,52},{7,6,15},{7,8,0},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},
+{9,9,1600},{7,4,5},{7,8,44},{7,6,17},{9,9,1344},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,30},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},
+{9,6,1664},{7,4,6},{7,8,34},{9,5,128},{7,8,50},{7,6,14},{7,8,62},{7,4,4},{7,4,2},{7,4,7},
+{7,8,48},{7,4,3},{7,8,60},{7,4,5},{7,8,42},{7,6,16},{9,9,1088},{7,4,6},{7,8,32},{7,5,8},
+{7,8,58},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},
+{7,7,26},{7,5,9},{9,8,640},{7,4,6},{7,8,38},{9,5,128},{7,7,25},{7,6,15},{9,8,384},{7,4,4},
+{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},
+{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{0,0,0},{7,4,3},
+{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},
+{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,39},{7,6,16},
+{9,8,576},{7,4,6},{7,7,19},{7,5,8},{7,8,55},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,8,45},{7,4,3},{7,5,11},{7,4,5},{7,8,53},{7,5,9},{9,8,448},{7,4,6},{7,8,35},{9,5,128},
+{7,8,51},{7,6,15},{7,8,63},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1536},{7,4,5},
+{7,8,43},{7,6,17},{9,9,1280},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,8,29},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},
+{7,8,33},{9,5,128},{7,8,49},{7,6,14},{7,8,61},{7,4,4},{7,4,2},{7,4,7},{7,8,47},{7,4,3},
+{7,8,59},{7,4,5},{7,8,41},{7,6,16},{9,9,1024},{7,4,6},{7,8,31},{7,5,8},{7,8,57},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},
+{9,9,768},{7,4,6},{7,8,37},{9,5,128},{7,7,25},{7,6,15},{9,8,320},{7,4,4},{7,4,2},{7,4,7},
+{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},
+{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{11,12,2368},{7,4,3},{7,5,11},{7,4,5},
+{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},
+{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,40},{7,6,16},{9,9,896},{7,4,6},
+{7,7,19},{7,5,8},{7,8,56},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,46},{7,4,3},
+{7,5,11},{7,4,5},{7,8,54},{7,5,9},{9,8,512},{7,4,6},{7,8,36},{9,5,128},{7,8,52},{7,6,15},
+{7,8,0},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1728},{7,4,5},{7,8,44},{7,6,17},
+{9,9,1408},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,8,30},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,34},{9,5,128},
+{7,8,50},{7,6,14},{7,8,62},{7,4,4},{7,4,2},{7,4,7},{7,8,48},{7,4,3},{7,8,60},{7,4,5},
+{7,8,42},{7,6,16},{9,9,1152},{7,4,6},{7,8,32},{7,5,8},{7,8,58},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,8,640},{7,4,6},
+{7,8,38},{9,5,128},{7,7,25},{7,6,15},{9,8,384},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},
+{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{0,0,0},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},
+{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},
+{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,39},{7,6,16},{9,8,576},{7,4,6},{7,7,19},{7,5,8},
+{7,8,55},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,45},{7,4,3},{7,5,11},{7,4,5},
+{7,8,53},{7,5,9},{9,8,448},{7,4,6},{7,8,35},{9,5,128},{7,8,51},{7,6,15},{7,8,63},{7,4,4},
+{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1472},{7,4,5},{7,8,43},{7,6,17},{9,9,1216},{7,4,6},
+{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,29},{7,4,3},
+{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,33},{9,5,128},{7,8,49},{7,6,14},
+{7,8,61},{7,4,4},{7,4,2},{7,4,7},{7,8,47},{7,4,3},{7,8,59},{7,4,5},{7,8,41},{7,6,16},
+{9,9,960},{7,4,6},{7,8,31},{7,5,8},{7,8,57},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,9,704},{7,4,6},{7,8,37},{9,5,128},
+{7,7,25},{7,6,15},{9,8,320},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},
+{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{11,12,1984},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},
+{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},
+{7,7,27},{7,4,5},{7,8,40},{7,6,16},{9,9,832},{7,4,6},{7,7,19},{7,5,8},{7,8,56},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,46},{7,4,3},{7,5,11},{7,4,5},{7,8,54},{7,5,9},
+{9,8,512},{7,4,6},{7,8,36},{9,5,128},{7,8,52},{7,6,15},{7,8,0},{7,4,4},{7,4,2},{7,4,7},
+{7,6,13},{7,4,3},{9,9,1600},{7,4,5},{7,8,44},{7,6,17},{9,9,1344},{7,4,6},{7,6,1},{7,5,8},
+{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,30},{7,4,3},{7,5,11},{7,4,5},
+{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,34},{9,5,128},{7,8,50},{7,6,14},{7,8,62},{7,4,4},
+{7,4,2},{7,4,7},{7,8,48},{7,4,3},{7,8,60},{7,4,5},{7,8,42},{7,6,16},{9,9,1088},{7,4,6},
+{7,8,32},{7,5,8},{7,8,58},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},
+{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,8,640},{7,4,6},{7,8,38},{9,5,128},{7,7,25},{7,6,15},
+{9,8,384},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},
+{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{0,0,0},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},
+{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},
+{7,8,39},{7,6,16},{9,8,576},{7,4,6},{7,7,19},{7,5,8},{7,8,55},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,8,45},{7,4,3},{7,5,11},{7,4,5},{7,8,53},{7,5,9},{9,8,448},{7,4,6},
+{7,8,35},{9,5,128},{7,8,51},{7,6,15},{7,8,63},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},
+{9,9,1536},{7,4,5},{7,8,43},{7,6,17},{9,9,1280},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,29},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},
+{9,6,1664},{7,4,6},{7,8,33},{9,5,128},{7,8,49},{7,6,14},{7,8,61},{7,4,4},{7,4,2},{7,4,7},
+{7,8,47},{7,4,3},{7,8,59},{7,4,5},{7,8,41},{7,6,16},{9,9,1024},{7,4,6},{7,8,31},{7,5,8},
+{7,8,57},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},
+{7,7,26},{7,5,9},{9,9,768},{7,4,6},{7,8,37},{9,5,128},{7,7,25},{7,6,15},{9,8,320},{7,4,4},
+{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},
+{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{11,11,1920},{7,4,3},
+{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},
+{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,40},{7,6,16},
+{9,9,896},{7,4,6},{7,7,19},{7,5,8},{7,8,56},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,8,46},{7,4,3},{7,5,11},{7,4,5},{7,8,54},{7,5,9},{9,8,512},{7,4,6},{7,8,36},{9,5,128},
+{7,8,52},{7,6,15},{7,8,0},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1728},{7,4,5},
+{7,8,44},{7,6,17},{9,9,1408},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,8,30},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},
+{7,8,34},{9,5,128},{7,8,50},{7,6,14},{7,8,62},{7,4,4},{7,4,2},{7,4,7},{7,8,48},{7,4,3},
+{7,8,60},{7,4,5},{7,8,42},{7,6,16},{9,9,1152},{7,4,6},{7,8,32},{7,5,8},{7,8,58},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},
+{9,8,640},{7,4,6},{7,8,38},{9,5,128},{7,7,25},{7,6,15},{9,8,384},{7,4,4},{7,4,2},{7,4,7},
+{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},
+{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{0,0,0},{7,4,3},{7,5,11},{7,4,5},
+{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},
+{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,39},{7,6,16},{9,8,576},{7,4,6},
+{7,7,19},{7,5,8},{7,8,55},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,45},{7,4,3},
+{7,5,11},{7,4,5},{7,8,53},{7,5,9},{9,8,448},{7,4,6},{7,8,35},{9,5,128},{7,8,51},{7,6,15},
+{7,8,63},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1472},{7,4,5},{7,8,43},{7,6,17},
+{9,9,1216},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,8,29},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,33},{9,5,128},
+{7,8,49},{7,6,14},{7,8,61},{7,4,4},{7,4,2},{7,4,7},{7,8,47},{7,4,3},{7,8,59},{7,4,5},
+{7,8,41},{7,6,16},{9,9,960},{7,4,6},{7,8,31},{7,5,8},{7,8,57},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,9,704},{7,4,6},
+{7,8,37},{9,5,128},{7,7,25},{7,6,15},{9,8,320},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},
+{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{11,12,2240},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},
+{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},
+{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,40},{7,6,16},{9,9,832},{7,4,6},{7,7,19},{7,5,8},
+{7,8,56},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,46},{7,4,3},{7,5,11},{7,4,5},
+{7,8,54},{7,5,9},{9,8,512},{7,4,6},{7,8,36},{9,5,128},{7,8,52},{7,6,15},{7,8,0},{7,4,4},
+{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1600},{7,4,5},{7,8,44},{7,6,17},{9,9,1344},{7,4,6},
+{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,30},{7,4,3},
+{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,34},{9,5,128},{7,8,50},{7,6,14},
+{7,8,62},{7,4,4},{7,4,2},{7,4,7},{7,8,48},{7,4,3},{7,8,60},{7,4,5},{7,8,42},{7,6,16},
+{9,9,1088},{7,4,6},{7,8,32},{7,5,8},{7,8,58},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,8,640},{7,4,6},{7,8,38},{9,5,128},
+{7,7,25},{7,6,15},{9,8,384},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},
+{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{0,0,0},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},
+{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},
+{7,7,27},{7,4,5},{7,8,39},{7,6,16},{9,8,576},{7,4,6},{7,7,19},{7,5,8},{7,8,55},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,45},{7,4,3},{7,5,11},{7,4,5},{7,8,53},{7,5,9},
+{9,8,448},{7,4,6},{7,8,35},{9,5,128},{7,8,51},{7,6,15},{7,8,63},{7,4,4},{7,4,2},{7,4,7},
+{7,6,13},{7,4,3},{9,9,1536},{7,4,5},{7,8,43},{7,6,17},{9,9,1280},{7,4,6},{7,6,1},{7,5,8},
+{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,29},{7,4,3},{7,5,11},{7,4,5},
+{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,33},{9,5,128},{7,8,49},{7,6,14},{7,8,61},{7,4,4},
+{7,4,2},{7,4,7},{7,8,47},{7,4,3},{7,8,59},{7,4,5},{7,8,41},{7,6,16},{9,9,1024},{7,4,6},
+{7,8,31},{7,5,8},{7,8,57},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},
+{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,9,768},{7,4,6},{7,8,37},{9,5,128},{7,7,25},{7,6,15},
+{9,8,320},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},
+{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{11,12,2496},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},
+{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},
+{7,8,40},{7,6,16},{9,9,896},{7,4,6},{7,7,19},{7,5,8},{7,8,56},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,8,46},{7,4,3},{7,5,11},{7,4,5},{7,8,54},{7,5,9},{9,8,512},{7,4,6},
+{7,8,36},{9,5,128},{7,8,52},{7,6,15},{7,8,0},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},
+{9,9,1728},{7,4,5},{7,8,44},{7,6,17},{9,9,1408},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,30},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},
+{9,6,1664},{7,4,6},{7,8,34},{9,5,128},{7,8,50},{7,6,14},{7,8,62},{7,4,4},{7,4,2},{7,4,7},
+{7,8,48},{7,4,3},{7,8,60},{7,4,5},{7,8,42},{7,6,16},{9,9,1152},{7,4,6},{7,8,32},{7,5,8},
+{7,8,58},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},
+{7,7,26},{7,5,9},{9,8,640},{7,4,6},{7,8,38},{9,5,128},{7,7,25},{7,6,15},{9,8,384},{7,4,4},
+{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},
+{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{12,11,0},{7,4,3},
+{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},
+{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,39},{7,6,16},
+{9,8,576},{7,4,6},{7,7,19},{7,5,8},{7,8,55},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,8,45},{7,4,3},{7,5,11},{7,4,5},{7,8,53},{7,5,9},{9,8,448},{7,4,6},{7,8,35},{9,5,128},
+{7,8,51},{7,6,15},{7,8,63},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1472},{7,4,5},
+{7,8,43},{7,6,17},{9,9,1216},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,8,29},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},
+{7,8,33},{9,5,128},{7,8,49},{7,6,14},{7,8,61},{7,4,4},{7,4,2},{7,4,7},{7,8,47},{7,4,3},
+{7,8,59},{7,4,5},{7,8,41},{7,6,16},{9,9,960},{7,4,6},{7,8,31},{7,5,8},{7,8,57},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},
+{9,9,704},{7,4,6},{7,8,37},{9,5,128},{7,7,25},{7,6,15},{9,8,320},{7,4,4},{7,4,2},{7,4,7},
+{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},
+{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{11,11,1792},{7,4,3},{7,5,11},{7,4,5},
+{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},
+{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,40},{7,6,16},{9,9,832},{7,4,6},
+{7,7,19},{7,5,8},{7,8,56},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,46},{7,4,3},
+{7,5,11},{7,4,5},{7,8,54},{7,5,9},{9,8,512},{7,4,6},{7,8,36},{9,5,128},{7,8,52},{7,6,15},
+{7,8,0},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1600},{7,4,5},{7,8,44},{7,6,17},
+{9,9,1344},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,8,30},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,34},{9,5,128},
+{7,8,50},{7,6,14},{7,8,62},{7,4,4},{7,4,2},{7,4,7},{7,8,48},{7,4,3},{7,8,60},{7,4,5},
+{7,8,42},{7,6,16},{9,9,1088},{7,4,6},{7,8,32},{7,5,8},{7,8,58},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,8,640},{7,4,6},
+{7,8,38},{9,5,128},{7,7,25},{7,6,15},{9,8,384},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},
+{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{0,0,0},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},
+{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},
+{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,39},{7,6,16},{9,8,576},{7,4,6},{7,7,19},{7,5,8},
+{7,8,55},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,45},{7,4,3},{7,5,11},{7,4,5},
+{7,8,53},{7,5,9},{9,8,448},{7,4,6},{7,8,35},{9,5,128},{7,8,51},{7,6,15},{7,8,63},{7,4,4},
+{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1536},{7,4,5},{7,8,43},{7,6,17},{9,9,1280},{7,4,6},
+{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,29},{7,4,3},
+{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,33},{9,5,128},{7,8,49},{7,6,14},
+{7,8,61},{7,4,4},{7,4,2},{7,4,7},{7,8,47},{7,4,3},{7,8,59},{7,4,5},{7,8,41},{7,6,16},
+{9,9,1024},{7,4,6},{7,8,31},{7,5,8},{7,8,57},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,9,768},{7,4,6},{7,8,37},{9,5,128},
+{7,7,25},{7,6,15},{9,8,320},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},
+{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{11,11,1856},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},
+{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},
+{7,7,27},{7,4,5},{7,8,40},{7,6,16},{9,9,896},{7,4,6},{7,7,19},{7,5,8},{7,8,56},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,46},{7,4,3},{7,5,11},{7,4,5},{7,8,54},{7,5,9},
+{9,8,512},{7,4,6},{7,8,36},{9,5,128},{7,8,52},{7,6,15},{7,8,0},{7,4,4},{7,4,2},{7,4,7},
+{7,6,13},{7,4,3},{9,9,1728},{7,4,5},{7,8,44},{7,6,17},{9,9,1408},{7,4,6},{7,6,1},{7,5,8},
+{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,30},{7,4,3},{7,5,11},{7,4,5},
+{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,34},{9,5,128},{7,8,50},{7,6,14},{7,8,62},{7,4,4},
+{7,4,2},{7,4,7},{7,8,48},{7,4,3},{7,8,60},{7,4,5},{7,8,42},{7,6,16},{9,9,1152},{7,4,6},
+{7,8,32},{7,5,8},{7,8,58},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},
+{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,8,640},{7,4,6},{7,8,38},{9,5,128},{7,7,25},{7,6,15},
+{9,8,384},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},
+{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{0,0,0},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},
+{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},
+{7,8,39},{7,6,16},{9,8,576},{7,4,6},{7,7,19},{7,5,8},{7,8,55},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,8,45},{7,4,3},{7,5,11},{7,4,5},{7,8,53},{7,5,9},{9,8,448},{7,4,6},
+{7,8,35},{9,5,128},{7,8,51},{7,6,15},{7,8,63},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},
+{9,9,1472},{7,4,5},{7,8,43},{7,6,17},{9,9,1216},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,29},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},
+{9,6,1664},{7,4,6},{7,8,33},{9,5,128},{7,8,49},{7,6,14},{7,8,61},{7,4,4},{7,4,2},{7,4,7},
+{7,8,47},{7,4,3},{7,8,59},{7,4,5},{7,8,41},{7,6,16},{9,9,960},{7,4,6},{7,8,31},{7,5,8},
+{7,8,57},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},
+{7,7,26},{7,5,9},{9,9,704},{7,4,6},{7,8,37},{9,5,128},{7,7,25},{7,6,15},{9,8,320},{7,4,4},
+{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},
+{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{11,12,2176},{7,4,3},
+{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},
+{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,40},{7,6,16},
+{9,9,832},{7,4,6},{7,7,19},{7,5,8},{7,8,56},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,8,46},{7,4,3},{7,5,11},{7,4,5},{7,8,54},{7,5,9},{9,8,512},{7,4,6},{7,8,36},{9,5,128},
+{7,8,52},{7,6,15},{7,8,0},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1600},{7,4,5},
+{7,8,44},{7,6,17},{9,9,1344},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,8,30},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},
+{7,8,34},{9,5,128},{7,8,50},{7,6,14},{7,8,62},{7,4,4},{7,4,2},{7,4,7},{7,8,48},{7,4,3},
+{7,8,60},{7,4,5},{7,8,42},{7,6,16},{9,9,1088},{7,4,6},{7,8,32},{7,5,8},{7,8,58},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},
+{9,8,640},{7,4,6},{7,8,38},{9,5,128},{7,7,25},{7,6,15},{9,8,384},{7,4,4},{7,4,2},{7,4,7},
+{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},
+{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{0,0,0},{7,4,3},{7,5,11},{7,4,5},
+{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},
+{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,39},{7,6,16},{9,8,576},{7,4,6},
+{7,7,19},{7,5,8},{7,8,55},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,45},{7,4,3},
+{7,5,11},{7,4,5},{7,8,53},{7,5,9},{9,8,448},{7,4,6},{7,8,35},{9,5,128},{7,8,51},{7,6,15},
+{7,8,63},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1536},{7,4,5},{7,8,43},{7,6,17},
+{9,9,1280},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,8,29},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,33},{9,5,128},
+{7,8,49},{7,6,14},{7,8,61},{7,4,4},{7,4,2},{7,4,7},{7,8,47},{7,4,3},{7,8,59},{7,4,5},
+{7,8,41},{7,6,16},{9,9,1024},{7,4,6},{7,8,31},{7,5,8},{7,8,57},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,9,768},{7,4,6},
+{7,8,37},{9,5,128},{7,7,25},{7,6,15},{9,8,320},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},
+{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{11,12,2432},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},
+{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},
+{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,40},{7,6,16},{9,9,896},{7,4,6},{7,7,19},{7,5,8},
+{7,8,56},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,46},{7,4,3},{7,5,11},{7,4,5},
+{7,8,54},{7,5,9},{9,8,512},{7,4,6},{7,8,36},{9,5,128},{7,8,52},{7,6,15},{7,8,0},{7,4,4},
+{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1728},{7,4,5},{7,8,44},{7,6,17},{9,9,1408},{7,4,6},
+{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,30},{7,4,3},
+{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,34},{9,5,128},{7,8,50},{7,6,14},
+{7,8,62},{7,4,4},{7,4,2},{7,4,7},{7,8,48},{7,4,3},{7,8,60},{7,4,5},{7,8,42},{7,6,16},
+{9,9,1152},{7,4,6},{7,8,32},{7,5,8},{7,8,58},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,8,640},{7,4,6},{7,8,38},{9,5,128},
+{7,7,25},{7,6,15},{9,8,384},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},
+{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{0,0,0},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},
+{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},
+{7,7,27},{7,4,5},{7,8,39},{7,6,16},{9,8,576},{7,4,6},{7,7,19},{7,5,8},{7,8,55},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,45},{7,4,3},{7,5,11},{7,4,5},{7,8,53},{7,5,9},
+{9,8,448},{7,4,6},{7,8,35},{9,5,128},{7,8,51},{7,6,15},{7,8,63},{7,4,4},{7,4,2},{7,4,7},
+{7,6,13},{7,4,3},{9,9,1472},{7,4,5},{7,8,43},{7,6,17},{9,9,1216},{7,4,6},{7,6,1},{7,5,8},
+{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,29},{7,4,3},{7,5,11},{7,4,5},
+{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,33},{9,5,128},{7,8,49},{7,6,14},{7,8,61},{7,4,4},
+{7,4,2},{7,4,7},{7,8,47},{7,4,3},{7,8,59},{7,4,5},{7,8,41},{7,6,16},{9,9,960},{7,4,6},
+{7,8,31},{7,5,8},{7,8,57},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},
+{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,9,704},{7,4,6},{7,8,37},{9,5,128},{7,7,25},{7,6,15},
+{9,8,320},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},
+{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{11,12,2048},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},
+{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},
+{7,8,40},{7,6,16},{9,9,832},{7,4,6},{7,7,19},{7,5,8},{7,8,56},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,8,46},{7,4,3},{7,5,11},{7,4,5},{7,8,54},{7,5,9},{9,8,512},{7,4,6},
+{7,8,36},{9,5,128},{7,8,52},{7,6,15},{7,8,0},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},
+{9,9,1600},{7,4,5},{7,8,44},{7,6,17},{9,9,1344},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,30},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},
+{9,6,1664},{7,4,6},{7,8,34},{9,5,128},{7,8,50},{7,6,14},{7,8,62},{7,4,4},{7,4,2},{7,4,7},
+{7,8,48},{7,4,3},{7,8,60},{7,4,5},{7,8,42},{7,6,16},{9,9,1088},{7,4,6},{7,8,32},{7,5,8},
+{7,8,58},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},
+{7,7,26},{7,5,9},{9,8,640},{7,4,6},{7,8,38},{9,5,128},{7,7,25},{7,6,15},{9,8,384},{7,4,4},
+{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},
+{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{0,0,0},{7,4,3},
+{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},
+{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,39},{7,6,16},
+{9,8,576},{7,4,6},{7,7,19},{7,5,8},{7,8,55},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,8,45},{7,4,3},{7,5,11},{7,4,5},{7,8,53},{7,5,9},{9,8,448},{7,4,6},{7,8,35},{9,5,128},
+{7,8,51},{7,6,15},{7,8,63},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1536},{7,4,5},
+{7,8,43},{7,6,17},{9,9,1280},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,8,29},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},
+{7,8,33},{9,5,128},{7,8,49},{7,6,14},{7,8,61},{7,4,4},{7,4,2},{7,4,7},{7,8,47},{7,4,3},
+{7,8,59},{7,4,5},{7,8,41},{7,6,16},{9,9,1024},{7,4,6},{7,8,31},{7,5,8},{7,8,57},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},
+{9,9,768},{7,4,6},{7,8,37},{9,5,128},{7,7,25},{7,6,15},{9,8,320},{7,4,4},{7,4,2},{7,4,7},
+{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},
+{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{11,11,1920},{7,4,3},{7,5,11},{7,4,5},
+{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},
+{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,40},{7,6,16},{9,9,896},{7,4,6},
+{7,7,19},{7,5,8},{7,8,56},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,46},{7,4,3},
+{7,5,11},{7,4,5},{7,8,54},{7,5,9},{9,8,512},{7,4,6},{7,8,36},{9,5,128},{7,8,52},{7,6,15},
+{7,8,0},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1728},{7,4,5},{7,8,44},{7,6,17},
+{9,9,1408},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,8,30},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,34},{9,5,128},
+{7,8,50},{7,6,14},{7,8,62},{7,4,4},{7,4,2},{7,4,7},{7,8,48},{7,4,3},{7,8,60},{7,4,5},
+{7,8,42},{7,6,16},{9,9,1152},{7,4,6},{7,8,32},{7,5,8},{7,8,58},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,8,640},{7,4,6},
+{7,8,38},{9,5,128},{7,7,25},{7,6,15},{9,8,384},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},
+{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{0,0,0},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},
+{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},
+{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,39},{7,6,16},{9,8,576},{7,4,6},{7,7,19},{7,5,8},
+{7,8,55},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,45},{7,4,3},{7,5,11},{7,4,5},
+{7,8,53},{7,5,9},{9,8,448},{7,4,6},{7,8,35},{9,5,128},{7,8,51},{7,6,15},{7,8,63},{7,4,4},
+{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1472},{7,4,5},{7,8,43},{7,6,17},{9,9,1216},{7,4,6},
+{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,29},{7,4,3},
+{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,33},{9,5,128},{7,8,49},{7,6,14},
+{7,8,61},{7,4,4},{7,4,2},{7,4,7},{7,8,47},{7,4,3},{7,8,59},{7,4,5},{7,8,41},{7,6,16},
+{9,9,960},{7,4,6},{7,8,31},{7,5,8},{7,8,57},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,9,704},{7,4,6},{7,8,37},{9,5,128},
+{7,7,25},{7,6,15},{9,8,320},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},
+{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{11,12,2304},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},
+{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},
+{7,7,27},{7,4,5},{7,8,40},{7,6,16},{9,9,832},{7,4,6},{7,7,19},{7,5,8},{7,8,56},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,46},{7,4,3},{7,5,11},{7,4,5},{7,8,54},{7,5,9},
+{9,8,512},{7,4,6},{7,8,36},{9,5,128},{7,8,52},{7,6,15},{7,8,0},{7,4,4},{7,4,2},{7,4,7},
+{7,6,13},{7,4,3},{9,9,1600},{7,4,5},{7,8,44},{7,6,17},{9,9,1344},{7,4,6},{7,6,1},{7,5,8},
+{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,30},{7,4,3},{7,5,11},{7,4,5},
+{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,34},{9,5,128},{7,8,50},{7,6,14},{7,8,62},{7,4,4},
+{7,4,2},{7,4,7},{7,8,48},{7,4,3},{7,8,60},{7,4,5},{7,8,42},{7,6,16},{9,9,1088},{7,4,6},
+{7,8,32},{7,5,8},{7,8,58},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},
+{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,8,640},{7,4,6},{7,8,38},{9,5,128},{7,7,25},{7,6,15},
+{9,8,384},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},
+{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{0,0,0},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},
+{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},
+{7,8,39},{7,6,16},{9,8,576},{7,4,6},{7,7,19},{7,5,8},{7,8,55},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,8,45},{7,4,3},{7,5,11},{7,4,5},{7,8,53},{7,5,9},{9,8,448},{7,4,6},
+{7,8,35},{9,5,128},{7,8,51},{7,6,15},{7,8,63},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},
+{9,9,1536},{7,4,5},{7,8,43},{7,6,17},{9,9,1280},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,29},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},
+{9,6,1664},{7,4,6},{7,8,33},{9,5,128},{7,8,49},{7,6,14},{7,8,61},{7,4,4},{7,4,2},{7,4,7},
+{7,8,47},{7,4,3},{7,8,59},{7,4,5},{7,8,41},{7,6,16},{9,9,1024},{7,4,6},{7,8,31},{7,5,8},
+{7,8,57},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},
+{7,7,26},{7,5,9},{9,9,768},{7,4,6},{7,8,37},{9,5,128},{7,7,25},{7,6,15},{9,8,320},{7,4,4},
+{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},
+{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{11,12,2560},{7,4,3},
+{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},
+{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,40},{7,6,16},
+{9,9,896},{7,4,6},{7,7,19},{7,5,8},{7,8,56},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,8,46},{7,4,3},{7,5,11},{7,4,5},{7,8,54},{7,5,9},{9,8,512},{7,4,6},{7,8,36},{9,5,128},
+{7,8,52},{7,6,15},{7,8,0},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1728},{7,4,5},
+{7,8,44},{7,6,17},{9,9,1408},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,8,30},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},
+{7,8,34},{9,5,128},{7,8,50},{7,6,14},{7,8,62},{7,4,4},{7,4,2},{7,4,7},{7,8,48},{7,4,3},
+{7,8,60},{7,4,5},{7,8,42},{7,6,16},{9,9,1152},{7,4,6},{7,8,32},{7,5,8},{7,8,58},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},
+{9,8,640},{7,4,6},{7,8,38},{9,5,128},{7,7,25},{7,6,15},{9,8,384},{7,4,4},{7,4,2},{7,4,7},
+{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},
+{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7}
+};
+ const TIFFFaxTabEnt TIFFFaxBlackTable[8192] = {
+{12,11,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,9,15},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,18},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,17},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,11,1792},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,11,23},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,20},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,11,25},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,12,128},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,12,56},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,30},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,11,1856},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,57},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,11,21},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,54},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,9,15},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,52},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,48},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{11,12,2112},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,44},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,36},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,12,384},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,28},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,60},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,40},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2368},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,16},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{10,10,64},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,9,15},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,18},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,10,17},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{11,12,1984},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,50},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,12,34},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,1664},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,26},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,1408},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,32},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,11,1920},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,12,61},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,42},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{10,13,1024},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,9,15},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{10,13,768},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,62},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2240},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,46},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,38},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,512},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,11,19},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,24},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,22},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{11,12,2496},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,10,16},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,0},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,10,64},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{12,11,0},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,9,15},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,10,18},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,17},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,11,1792},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,23},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,20},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,11,25},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{10,12,192},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,1280},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,12,31},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{11,11,1856},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,58},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,11,21},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,896},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,9,15},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,640},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,49},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2176},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,12,45},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,37},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{10,12,448},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,29},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{10,13,1536},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,41},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2432},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,16},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,10,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,10,64},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,9,15},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,18},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,17},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{11,12,2048},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,51},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,35},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,12,320},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,27},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,59},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,33},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,11,1920},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,12,256},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,43},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{10,13,1152},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,9,15},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,55},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,12,63},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{11,12,2304},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,47},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,12,39},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,53},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,19},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,24},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,22},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2560},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,10,16},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,0},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{10,10,64},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{12,11,0},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,9,15},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,10,18},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,10,17},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,11,1792},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,23},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,11,20},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,25},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{10,12,128},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,56},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,30},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{11,11,1856},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,57},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,21},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,54},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,9,15},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,52},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,48},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2112},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,44},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,36},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{10,12,384},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,28},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,60},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,12,40},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{11,12,2368},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,16},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,10,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,10,64},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,9,15},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,18},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,17},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,1984},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,12,50},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,34},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{10,13,1728},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,26},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{10,13,1472},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,32},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,11,1920},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,61},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,42},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,1088},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,9,15},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,832},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,62},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{11,12,2240},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,46},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,38},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,576},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,19},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,11,24},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,22},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2496},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,16},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{10,10,64},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{12,11,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,9,15},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,18},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,10,17},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{11,11,1792},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,23},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,11,20},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,25},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,12,192},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,1344},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,31},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,11,1856},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,12,58},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,21},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{10,13,960},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,9,15},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{10,13,704},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,49},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2176},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,45},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,37},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,12,448},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,12,29},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,1600},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,41},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{11,12,2432},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,10,16},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,0},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,10,64},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,9,15},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,10,18},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,17},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2048},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,51},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,35},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{10,12,320},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,27},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,59},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,12,33},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{11,11,1920},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,12,256},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,12,43},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,1216},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,9,15},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,55},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,63},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2304},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,12,47},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,39},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,53},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,19},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,11,24},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,11,22},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2560},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,16},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,10,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,10,64},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2}
+};
diff --git a/Utilities/ITK/Utilities/tiff/tif_flush.c b/Utilities/ITK/Utilities/tiff/tif_flush.c
new file mode 100644
index 0000000000..118616ec95
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_flush.c
@@ -0,0 +1,67 @@
+/* $Header: /cvsroot/Insight/Insight/Utilities/tiff/tif_flush.c,v 1.3 2005/09/16 19:59:32 jjomier Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ */
+#include "tiffiop.h"
+
+int
+TIFFFlush(TIFF* tif)
+{
+
+  if (tif->tif_mode != O_RDONLY) {
+    if (!TIFFFlushData(tif))
+      return (0);
+    if ((tif->tif_flags & TIFF_DIRTYDIRECT) &&
+        !TIFFWriteDirectory(tif))
+      return (0);
+  }
+  return (1);
+}
+
+/*
+ * Flush buffered data to the file.
+ *
+ * Frank Warmerdam'2000: I modified this to return 1 if TIFF_BEENWRITING
+ * is not set, so that TIFFFlush() will proceed to write out the directory.
+ * The documentation says returning 1 is an error indicator, but not having
+ * been writing isn't exactly a an error.  Hopefully this doesn't cause
+ * problems for other people. 
+ */
+int
+TIFFFlushData(TIFF* tif)
+{
+  if ((tif->tif_flags & TIFF_BEENWRITING) == 0)
+    return (0);
+  if (tif->tif_flags & TIFF_POSTENCODE) {
+    tif->tif_flags &= ~TIFF_POSTENCODE;
+    if (!(*tif->tif_postencode)(tif))
+      return (0);
+  }
+  return (TIFFFlushData1(tif));
+}
+
diff --git a/Utilities/ITK/Utilities/tiff/tif_getimage.c b/Utilities/ITK/Utilities/tiff/tif_getimage.c
new file mode 100644
index 0000000000..c60d665f82
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_getimage.c
@@ -0,0 +1,2596 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1991-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library
+ *
+ * Read and return a packed RGBA image.
+ */
+#include "tiffiop.h"
+#include <stdio.h>
+
+#ifdef _MSC_VER
+#pragma warning ( disable : 4550 )
+#endif
+
+static  int gtTileContig(TIFFRGBAImage*, uint32*, uint32, uint32);
+static  int gtTileSeparate(TIFFRGBAImage*, uint32*, uint32, uint32);
+static  int gtStripContig(TIFFRGBAImage*, uint32*, uint32, uint32);
+static  int gtStripSeparate(TIFFRGBAImage*, uint32*, uint32, uint32);
+static  int pickTileContigCase(TIFFRGBAImage*);
+static  int pickTileSeparateCase(TIFFRGBAImage*);
+
+static  const char photoTag[] = "PhotometricInterpretation";
+
+/* 
+ * Helper constants used in Orientation tag handling
+ */
+#define FLIP_VERTICALLY 0x01
+#define FLIP_HORIZONTALLY 0x02
+
+/*
+ * Color conversion constants. We will define display types here.
+ */
+
+TIFFDisplay display_sRGB = {
+  {      /* XYZ -> luminance matrix */
+    {  3.2410F, -1.5374F, -0.4986F },
+    {  -0.9692F, 1.8760F, 0.0416F },
+    {  0.0556F, -0.2040F, 1.0570F }
+  },  
+  100.0F, 100.0F, 100.0F,  /* Light o/p for reference white */
+  255, 255, 255,    /* Pixel values for ref. white */
+  1.0F, 1.0F, 1.0F,  /* Residual light o/p for black pixel */
+  2.4F, 2.4F, 2.4F,  /* Gamma values for the three guns */
+};
+
+/*
+ * Check the image to see if TIFFReadRGBAImage can deal with it.
+ * 1/0 is returned according to whether or not the image can
+ * be handled.  If 0 is returned, emsg contains the reason
+ * why it is being rejected.
+ */
+int
+TIFFRGBAImageOK(TIFF* tif, char emsg[1024])
+{
+    TIFFDirectory* td = &tif->tif_dir;
+    uint16 photometric;
+    int colorchannels;
+
+    if (!tif->tif_decodestatus) {
+  sprintf(emsg, "Sorry, requested compression method is not configured");
+  return (0);
+    }
+    switch (td->td_bitspersample) {
+    case 1: case 2: case 4:
+    case 8: case 16:
+  break;
+    default:
+  sprintf(emsg, "Sorry, can not handle images with %d-bit samples",
+      td->td_bitspersample);
+  return (0);
+    }
+    colorchannels = td->td_samplesperpixel - td->td_extrasamples;
+    if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric)) {
+  switch (colorchannels) {
+  case 1:
+      photometric = PHOTOMETRIC_MINISBLACK;
+      break;
+  case 3:
+      photometric = PHOTOMETRIC_RGB;
+      break;
+  default:
+      sprintf(emsg, "Missing needed %s tag", photoTag);
+      return (0);
+  }
+    }
+    switch (photometric) {
+    case PHOTOMETRIC_MINISWHITE:
+    case PHOTOMETRIC_MINISBLACK:
+    case PHOTOMETRIC_PALETTE:
+  if (td->td_planarconfig == PLANARCONFIG_CONTIG 
+            && td->td_samplesperpixel != 1
+            && td->td_bitspersample < 8 ) {
+      sprintf(emsg,
+                    "Sorry, can not handle contiguous data with %s=%d, "
+                    "and %s=%d and Bits/Sample=%d",
+                    photoTag, photometric,
+                    "Samples/pixel", td->td_samplesperpixel,
+                    td->td_bitspersample);
+      return (0);
+  }
+        /*
+        ** We should likely validate that any extra samples are either
+        ** to be ignored, or are alpha, and if alpha we should try to use
+        ** them.  But for now we won't bother with this. 
+        */
+  break;
+    case PHOTOMETRIC_YCBCR:
+  if (td->td_planarconfig != PLANARCONFIG_CONTIG) {
+      sprintf(emsg, "Sorry, can not handle YCbCr images with %s=%d",
+    "Planarconfiguration", td->td_planarconfig);
+      return (0);
+  }
+  break;
+    case PHOTOMETRIC_RGB: 
+  if (colorchannels < 3) {
+      sprintf(emsg, "Sorry, can not handle RGB image with %s=%d",
+    "Color channels", colorchannels);
+      return (0);
+  }
+  break;
+    case PHOTOMETRIC_SEPARATED:
+  if (td->td_inkset != INKSET_CMYK) {
+      sprintf(emsg, "Sorry, can not handle separated image with %s=%d",
+    "InkSet", td->td_inkset);
+      return (0);
+  }
+  if (td->td_samplesperpixel < 4) {
+      sprintf(emsg, "Sorry, can not handle separated image with %s=%d",
+    "Samples/pixel", td->td_samplesperpixel);
+      return (0);
+  }
+  break;
+    case PHOTOMETRIC_LOGL:
+  if (td->td_compression != COMPRESSION_SGILOG) {
+      sprintf(emsg, "Sorry, LogL data must have %s=%d",
+    "Compression", COMPRESSION_SGILOG);
+      return (0);
+  }
+  break;
+    case PHOTOMETRIC_LOGLUV:
+  if (td->td_compression != COMPRESSION_SGILOG &&
+    td->td_compression != COMPRESSION_SGILOG24) {
+      sprintf(emsg, "Sorry, LogLuv data must have %s=%d or %d",
+    "Compression", COMPRESSION_SGILOG, COMPRESSION_SGILOG24);
+      return (0);
+  }
+  if (td->td_planarconfig != PLANARCONFIG_CONTIG) {
+      sprintf(emsg, "Sorry, can not handle LogLuv images with %s=%d",
+    "Planarconfiguration", td->td_planarconfig);
+      return (0);
+  }
+  break;
+    case PHOTOMETRIC_CIELAB:
+  break;
+    default:
+  sprintf(emsg, "Sorry, can not handle image with %s=%d",
+      photoTag, photometric);
+  return (0);
+    }
+    return (1);
+}
+
+void
+TIFFRGBAImageEnd(TIFFRGBAImage* img)
+{
+  if (img->Map)
+    _TIFFfree(img->Map), img->Map = NULL;
+  if (img->BWmap)
+    _TIFFfree(img->BWmap), img->BWmap = NULL;
+  if (img->PALmap)
+    _TIFFfree(img->PALmap), img->PALmap = NULL;
+  if (img->ycbcr)
+    _TIFFfree(img->ycbcr), img->ycbcr = NULL;
+  if (img->cielab)
+    _TIFFfree(img->cielab), img->cielab = NULL;
+
+  if( img->redcmap ) {
+    _TIFFfree( img->redcmap );
+    _TIFFfree( img->greencmap );
+    _TIFFfree( img->bluecmap );
+  }
+}
+
+static int
+isCCITTCompression(TIFF* tif)
+{
+    uint16 compress;
+    TIFFGetField(tif, TIFFTAG_COMPRESSION, &compress);
+    return (compress == COMPRESSION_CCITTFAX3 ||
+      compress == COMPRESSION_CCITTFAX4 ||
+      compress == COMPRESSION_CCITTRLE ||
+      compress == COMPRESSION_CCITTRLEW);
+}
+
+int
+TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
+{
+    uint16* sampleinfo;
+    uint16 extrasamples;
+    uint16 planarconfig;
+    uint16 compress;
+    int colorchannels;
+    uint16 *red_orig, *green_orig, *blue_orig;
+    int n_color;
+
+    /* Initialize to normal values */
+    img->row_offset = 0;
+    img->col_offset = 0;
+    img->redcmap = NULL;
+    img->greencmap = NULL;
+    img->bluecmap = NULL;
+    img->req_orientation = ORIENTATION_BOTLEFT;      /* It is the default */
+    
+    img->tif = tif;
+    img->stoponerr = stop;
+    TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &img->bitspersample);
+    switch (img->bitspersample) {
+    case 1: case 2: case 4:
+    case 8: case 16:
+  break;
+    default:
+  sprintf(emsg, "Sorry, can not handle images with %d-bit samples",
+      img->bitspersample);
+  return (0);
+    }
+    img->alpha = 0;
+    TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &img->samplesperpixel);
+    TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES,
+  &extrasamples, &sampleinfo);
+    if (extrasamples >= 1)
+    {
+  switch (sampleinfo[0]) {
+  case EXTRASAMPLE_UNSPECIFIED:  /* Workaround for some images without */
+    if (img->samplesperpixel > 3)  /* correct info about alpha channel */
+      img->alpha = EXTRASAMPLE_ASSOCALPHA;
+    break;
+  case EXTRASAMPLE_ASSOCALPHA:  /* data is pre-multiplied */
+  case EXTRASAMPLE_UNASSALPHA:  /* data is not pre-multiplied */
+    img->alpha = sampleinfo[0];
+    break;
+  }
+    }
+
+#ifdef DEFAULT_EXTRASAMPLE_AS_ALPHA
+    if( !TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &img->photometric))
+        img->photometric = PHOTOMETRIC_MINISWHITE;
+
+    if( extrasamples == 0 
+        && img->samplesperpixel == 4 
+        && img->photometric == PHOTOMETRIC_RGB )
+    {
+        img->alpha = EXTRASAMPLE_ASSOCALPHA;
+        extrasamples = 1;
+    }
+#endif
+
+    colorchannels = img->samplesperpixel - extrasamples;
+    TIFFGetFieldDefaulted(tif, TIFFTAG_COMPRESSION, &compress);
+    TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planarconfig);
+    if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &img->photometric)) {
+  switch (colorchannels) {
+  case 1:
+      if (isCCITTCompression(tif))
+    img->photometric = PHOTOMETRIC_MINISWHITE;
+      else
+    img->photometric = PHOTOMETRIC_MINISBLACK;
+      break;
+  case 3:
+      img->photometric = PHOTOMETRIC_RGB;
+      break;
+  default:
+      sprintf(emsg, "Missing needed %s tag", photoTag);
+      return (0);
+  }
+    }
+    switch (img->photometric) {
+    case PHOTOMETRIC_PALETTE:
+  if (!TIFFGetField(tif, TIFFTAG_COLORMAP,
+      &red_orig, &green_orig, &blue_orig)) {
+      sprintf(emsg, "Missing required \"Colormap\" tag");
+      return (0);
+  }
+
+        /* copy the colormaps so we can modify them */
+        n_color = (1L << img->bitspersample);
+        img->redcmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color);
+        img->greencmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color);
+        img->bluecmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color);
+        if( !img->redcmap || !img->greencmap || !img->bluecmap ) {
+      sprintf(emsg, "Out of memory for colormap copy");
+      return (0);
+        }
+
+        _TIFFmemcpy( img->redcmap, red_orig, n_color * 2 );
+        _TIFFmemcpy( img->greencmap, green_orig, n_color * 2 );
+        _TIFFmemcpy( img->bluecmap, blue_orig, n_color * 2 );
+        
+  /* fall thru... */
+    case PHOTOMETRIC_MINISWHITE:
+    case PHOTOMETRIC_MINISBLACK:
+  if (planarconfig == PLANARCONFIG_CONTIG 
+            && img->samplesperpixel != 1
+            && img->bitspersample < 8 ) {
+      sprintf(emsg,
+                    "Sorry, can not handle contiguous data with %s=%d, "
+                    "and %s=%d and Bits/Sample=%d",
+                    photoTag, img->photometric,
+                    "Samples/pixel", img->samplesperpixel,
+                    img->bitspersample);
+      return (0);
+  }
+  break;
+    case PHOTOMETRIC_YCBCR:
+  if (planarconfig != PLANARCONFIG_CONTIG) {
+      sprintf(emsg, "Sorry, can not handle YCbCr images with %s=%d",
+    "Planarconfiguration", planarconfig);
+      return (0);
+  }
+  /* It would probably be nice to have a reality check here. */
+  if (planarconfig == PLANARCONFIG_CONTIG)
+      /* can rely on libjpeg to convert to RGB */
+      /* XXX should restore current state on exit */
+      switch (compress) {
+    case COMPRESSION_OJPEG:
+    case COMPRESSION_JPEG:
+        TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
+        img->photometric = PHOTOMETRIC_RGB;
+                    break;
+
+                default:
+                    /* do nothing */;
+                    break;
+      }
+  break;
+    case PHOTOMETRIC_RGB: 
+  if (colorchannels < 3) {
+      sprintf(emsg, "Sorry, can not handle RGB image with %s=%d",
+    "Color channels", colorchannels);
+      return (0);
+  }
+  break;
+    case PHOTOMETRIC_SEPARATED: {
+  uint16 inkset;
+  TIFFGetFieldDefaulted(tif, TIFFTAG_INKSET, &inkset);
+  if (inkset != INKSET_CMYK) {
+      sprintf(emsg, "Sorry, can not handle separated image with %s=%d",
+    "InkSet", inkset);
+      return (0);
+  }
+  if (img->samplesperpixel < 4) {
+      sprintf(emsg, "Sorry, can not handle separated image with %s=%d",
+    "Samples/pixel", img->samplesperpixel);
+      return (0);
+  }
+  break;
+    }
+    case PHOTOMETRIC_LOGL:
+  if (compress != COMPRESSION_SGILOG) {
+      sprintf(emsg, "Sorry, LogL data must have %s=%d",
+    "Compression", COMPRESSION_SGILOG);
+      return (0);
+  }
+  TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_8BIT);
+  img->photometric = PHOTOMETRIC_MINISBLACK;  /* little white lie */
+  img->bitspersample = 8;
+  break;
+    case PHOTOMETRIC_LOGLUV:
+  if (compress != COMPRESSION_SGILOG && compress != COMPRESSION_SGILOG24) {
+      sprintf(emsg, "Sorry, LogLuv data must have %s=%d or %d",
+    "Compression", COMPRESSION_SGILOG, COMPRESSION_SGILOG24);
+      return (0);
+  }
+  if (planarconfig != PLANARCONFIG_CONTIG) {
+      sprintf(emsg, "Sorry, can not handle LogLuv images with %s=%d",
+    "Planarconfiguration", planarconfig);
+      return (0);
+  }
+  TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_8BIT);
+  img->photometric = PHOTOMETRIC_RGB;    /* little white lie */
+  img->bitspersample = 8;
+  break;
+    case PHOTOMETRIC_CIELAB:
+  break;
+    default:
+  sprintf(emsg, "Sorry, can not handle image with %s=%d",
+      photoTag, img->photometric);
+  return (0);
+    }
+    img->Map = NULL;
+    img->BWmap = NULL;
+    img->PALmap = NULL;
+    img->ycbcr = NULL;
+    img->cielab = NULL;
+    TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &img->width);
+    TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &img->height);
+    TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &img->orientation);
+    img->isContig =
+  !(planarconfig == PLANARCONFIG_SEPARATE && colorchannels > 1);
+    if (img->isContig) {
+  img->get = TIFFIsTiled(tif) ? gtTileContig : gtStripContig;
+  if (!pickTileContigCase(img)) {
+    sprintf(emsg, "Sorry, can not handle image");
+    return 0;
+  }
+    } else {
+  img->get = TIFFIsTiled(tif) ? gtTileSeparate : gtStripSeparate;
+  if (!pickTileSeparateCase(img)) {
+    sprintf(emsg, "Sorry, can not handle image");
+    return 0;
+  }
+    }
+    return 1;
+}
+
+int
+TIFFRGBAImageGet(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
+{
+    if (img->get == NULL) {
+  TIFFError(TIFFFileName(img->tif), "No \"get\" routine setup");
+  return (0);
+    }
+    if (img->put.any == NULL) {
+  TIFFError(TIFFFileName(img->tif),
+      "No \"put\" routine setupl; probably can not handle image format");
+  return (0);
+    }
+    return (*img->get)(img, raster, w, h);
+}
+
+/*
+ * Read the specified image into an ABGR-format rastertaking in account
+ * specified orientation.
+ */
+int
+TIFFReadRGBAImageOriented(TIFF* tif,
+        uint32 rwidth, uint32 rheight, uint32* raster,
+        int orientation, int stop)
+{
+    char emsg[1024] = "";
+    TIFFRGBAImage img;
+    int ok;
+
+    if (TIFFRGBAImageOK(tif, emsg) &&
+  TIFFRGBAImageBegin(&img, tif, stop, emsg)) {
+  img.req_orientation = orientation;
+  /* XXX verify rwidth and rheight against width and height */
+  ok = TIFFRGBAImageGet(&img, raster+(rheight-img.height)*rwidth,
+      rwidth, img.height);
+  TIFFRGBAImageEnd(&img);
+    } else {
+  TIFFError(TIFFFileName(tif), emsg);
+  ok = 0;
+    }
+    return (ok);
+}
+
+/*
+ * Read the specified image into an ABGR-format raster. Use bottom left
+ * origin for raster by default.
+ */
+int
+TIFFReadRGBAImage(TIFF* tif,
+      uint32 rwidth, uint32 rheight, uint32* raster, int stop)
+{
+  return TIFFReadRGBAImageOriented(tif, rwidth, rheight, raster,
+           ORIENTATION_BOTLEFT, stop);
+}
+
+static int 
+setorientation(TIFFRGBAImage* img)
+{
+  switch (img->orientation) {
+    case ORIENTATION_TOPLEFT:
+    case ORIENTATION_LEFTTOP:
+      if (img->req_orientation == ORIENTATION_TOPRIGHT ||
+          img->req_orientation == ORIENTATION_RIGHTTOP)
+        return FLIP_HORIZONTALLY;
+      else if (img->req_orientation == ORIENTATION_BOTRIGHT ||
+          img->req_orientation == ORIENTATION_RIGHTBOT)
+        return FLIP_HORIZONTALLY | FLIP_VERTICALLY;
+      else if (img->req_orientation == ORIENTATION_BOTLEFT ||
+          img->req_orientation == ORIENTATION_LEFTBOT)
+        return FLIP_VERTICALLY;
+      else
+        return 0;
+    case ORIENTATION_TOPRIGHT:
+    case ORIENTATION_RIGHTTOP:
+      if (img->req_orientation == ORIENTATION_TOPLEFT ||
+          img->req_orientation == ORIENTATION_LEFTTOP)
+        return FLIP_HORIZONTALLY;
+      else if (img->req_orientation == ORIENTATION_BOTRIGHT ||
+          img->req_orientation == ORIENTATION_RIGHTBOT)
+        return FLIP_VERTICALLY;
+      else if (img->req_orientation == ORIENTATION_BOTLEFT ||
+          img->req_orientation == ORIENTATION_LEFTBOT)
+        return FLIP_HORIZONTALLY | FLIP_VERTICALLY;
+      else
+        return 0;
+    case ORIENTATION_BOTRIGHT:
+    case ORIENTATION_RIGHTBOT:
+      if (img->req_orientation == ORIENTATION_TOPLEFT ||
+          img->req_orientation == ORIENTATION_LEFTTOP)
+        return FLIP_HORIZONTALLY | FLIP_VERTICALLY;
+      else if (img->req_orientation == ORIENTATION_TOPRIGHT ||
+          img->req_orientation == ORIENTATION_RIGHTTOP)
+        return FLIP_VERTICALLY;
+      else if (img->req_orientation == ORIENTATION_BOTLEFT ||
+          img->req_orientation == ORIENTATION_LEFTBOT)
+        return FLIP_HORIZONTALLY;
+      else
+        return 0;
+    case ORIENTATION_BOTLEFT:
+    case ORIENTATION_LEFTBOT:
+      if (img->req_orientation == ORIENTATION_TOPLEFT ||
+          img->req_orientation == ORIENTATION_LEFTTOP)
+        return FLIP_VERTICALLY;
+      else if (img->req_orientation == ORIENTATION_TOPRIGHT ||
+          img->req_orientation == ORIENTATION_RIGHTTOP)
+        return FLIP_HORIZONTALLY | FLIP_VERTICALLY;
+      else if (img->req_orientation == ORIENTATION_BOTRIGHT ||
+          img->req_orientation == ORIENTATION_RIGHTBOT)
+        return FLIP_HORIZONTALLY;
+      else
+        return 0;
+    default:  /* NOTREACHED */
+      return 0;
+  }
+}
+
+/*
+ * Get an tile-organized image that has
+ *  PlanarConfiguration contiguous if SamplesPerPixel > 1
+ * or
+ *  SamplesPerPixel == 1
+ */  
+static int
+gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
+{
+    TIFF* tif = img->tif;
+    tileContigRoutine put = img->put.contig;
+    uint32 col, row, y, rowstoread;
+    uint32 pos;
+    uint32 tw, th;
+    unsigned char* buf;
+    int32 fromskew, toskew;
+    uint32 nrow;
+    int ret = 1, flip;
+
+    buf = (unsigned char*) _TIFFmalloc(TIFFTileSize(tif));
+    if (buf == 0) {
+  TIFFError(TIFFFileName(tif), "No space for tile buffer");
+  return (0);
+    }
+    _TIFFmemset(buf, 0, TIFFTileSize(tif));
+    TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw);
+    TIFFGetField(tif, TIFFTAG_TILELENGTH, &th);
+
+    flip = setorientation(img);
+    if (flip & FLIP_VERTICALLY) {
+      y = h - 1;
+      toskew = -(int32)(tw + w);
+    }
+    else {
+      y = 0;
+      toskew = -(int32)(tw - w);
+    }
+     
+    for (row = 0; row < h; row += nrow)
+    {
+        rowstoread = th - (row + img->row_offset) % th;
+      nrow = (row + rowstoread > h ? h - row : rowstoread);
+  for (col = 0; col < w; col += tw) 
+        {
+            if (TIFFReadTile(tif, buf, col+img->col_offset,
+                             row+img->row_offset, 0, 0) < 0 && img->stoponerr)
+            {
+                ret = 0;
+                break;
+            }
+      
+            pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif);
+
+          if (col + tw > w) 
+            {
+                /*
+                 * Tile is clipped horizontally.  Calculate
+                 * visible portion and skewing factors.
+                 */
+                uint32 npix = w - col;
+                fromskew = tw - npix;
+                (*put)(img, raster+y*w+col, col, y,
+                       npix, nrow, fromskew, toskew + fromskew, buf + pos);
+            }
+            else 
+            {
+                (*put)(img, raster+y*w+col, col, y, tw, nrow, 0, toskew, buf + pos);
+            }
+        }
+
+        y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow);
+    }
+    _TIFFfree(buf);
+
+    if (flip & FLIP_HORIZONTALLY) {
+      uint32 line;
+
+      for (line = 0; line < h; line++) {
+        uint32 *left = raster + (line * w);
+        uint32 *right = left + w - 1;
+        
+        while ( left < right ) {
+          uint32 temp = *left;
+          *left = *right;
+          *right = temp;
+          left++, right--;
+        }
+      }
+    }
+
+    return (ret);
+}
+
+/*
+ * Get an tile-organized image that has
+ *   SamplesPerPixel > 1
+ *   PlanarConfiguration separated
+ * We assume that all such images are RGB.
+ */  
+static int
+gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
+{
+    TIFF* tif = img->tif;
+    tileSeparateRoutine put = img->put.separate;
+    uint32 col, row, y, rowstoread;
+    uint32 pos;
+    uint32 tw, th;
+    unsigned char* buf;
+    unsigned char* r;
+    unsigned char* g;
+    unsigned char* b;
+    unsigned char* a;
+    tsize_t tilesize;
+    int32 fromskew, toskew;
+    int alpha = img->alpha;
+    uint32 nrow;
+    int ret = 1, flip;
+
+    tilesize = TIFFTileSize(tif);
+    buf = (unsigned char*) _TIFFmalloc(4*tilesize);
+    if (buf == 0) {
+  TIFFError(TIFFFileName(tif), "No space for tile buffer");
+  return (0);
+    }
+    _TIFFmemset(buf, 0, 4*tilesize);
+    r = buf;
+    g = r + tilesize;
+    b = g + tilesize;
+    a = b + tilesize;
+    if (!alpha)
+  _TIFFmemset(a, 0xff, tilesize);
+    TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw);
+    TIFFGetField(tif, TIFFTAG_TILELENGTH, &th);
+
+    flip = setorientation(img);
+    if (flip & FLIP_VERTICALLY) {
+      y = h - 1;
+      toskew = -(int32)(tw + w);
+    }
+    else {
+      y = 0;
+      toskew = -(int32)(tw - w);
+    }
+
+    for (row = 0; row < h; row += nrow) 
+    {
+        rowstoread = th - (row + img->row_offset) % th;
+      nrow = (row + rowstoread > h ? h - row : rowstoread);
+        for (col = 0; col < w; col += tw) 
+        {
+            if (TIFFReadTile(tif, r, col+img->col_offset,
+                             row+img->row_offset,0,0) < 0 && img->stoponerr)
+            {
+                ret = 0;
+                break;
+            }
+            if (TIFFReadTile(tif, g, col+img->col_offset,
+                             row+img->row_offset,0,1) < 0 && img->stoponerr)
+            {
+                ret = 0;
+                break;
+            }
+            if (TIFFReadTile(tif, b, col+img->col_offset,
+                             row+img->row_offset,0,2) < 0 && img->stoponerr)
+            {
+                ret = 0;
+                break;
+            }
+            if (alpha && TIFFReadTile(tif,a,col+img->col_offset,
+                                      row+img->row_offset,0,3) < 0 && img->stoponerr)
+            {
+                ret = 0;
+                break;
+            }
+
+            pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif);
+
+            if (col + tw > w) 
+            {
+                /*
+                 * Tile is clipped horizontally.  Calculate
+                 * visible portion and skewing factors.
+                 */
+                uint32 npix = w - col;
+                fromskew = tw - npix;
+                (*put)(img, raster+y*w+col, col, y,
+                       npix, nrow, fromskew, toskew + fromskew, 
+                       r + pos, g + pos, b + pos, a + pos);
+            } else {
+                (*put)(img, raster+y*w+col, col, y,
+                       tw, nrow, 0, toskew, r + pos, g + pos, b + pos, a + pos);
+            }
+        }
+
+        y += (flip & FLIP_VERTICALLY ?-(int32) nrow : (int32) nrow);
+    }
+
+    if (flip & FLIP_HORIZONTALLY) {
+      uint32 line;
+
+      for (line = 0; line < h; line++) {
+        uint32 *left = raster + (line * w);
+        uint32 *right = left + w - 1;
+        
+        while ( left < right ) {
+          uint32 temp = *left;
+          *left = *right;
+          *right = temp;
+          left++, right--;
+        }
+      }
+    }
+
+    _TIFFfree(buf);
+    return (ret);
+}
+
+/*
+ * Get a strip-organized image that has
+ *  PlanarConfiguration contiguous if SamplesPerPixel > 1
+ * or
+ *  SamplesPerPixel == 1
+ */  
+static int
+gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
+{
+    TIFF* tif = img->tif;
+    tileContigRoutine put = img->put.contig;
+    uint32 row, y, nrow, rowstoread;
+    uint32 pos;
+    unsigned char* buf;
+    uint32 rowsperstrip;
+    uint32 imagewidth = img->width;
+    tsize_t scanline;
+    int32 fromskew, toskew;
+    int ret = 1, flip;
+
+    buf = (unsigned char*) _TIFFmalloc(TIFFStripSize(tif));
+    if (buf == 0) {
+  TIFFError(TIFFFileName(tif), "No space for strip buffer");
+  return (0);
+    }
+    _TIFFmemset(buf, 0, TIFFStripSize(tif));
+
+    flip = setorientation(img);
+    if (flip & FLIP_VERTICALLY) {
+      y = h - 1;
+      toskew = -(int32)(w + w);
+    } else {
+      y = 0;
+      toskew = -(int32)(w - w);
+    }
+
+    TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
+    scanline = TIFFScanlineSize(tif);
+    fromskew = (w < imagewidth ? imagewidth - w : 0);
+    for (row = 0; row < h; row += nrow) 
+    {
+        rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip;
+        nrow = (row + rowstoread > h ? h - row : rowstoread);
+        if (TIFFReadEncodedStrip(tif,
+                                 TIFFComputeStrip(tif,row+img->row_offset, 0),
+                                 buf, 
+                                 ((row + img->row_offset)%rowsperstrip + nrow) * scanline) < 0
+            && img->stoponerr)
+        {
+            ret = 0;
+            break;
+        }
+
+        pos = ((row + img->row_offset) % rowsperstrip) * scanline;
+        (*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, buf + pos);
+        y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow);
+    }
+
+    if (flip & FLIP_HORIZONTALLY) {
+      uint32 line;
+
+      for (line = 0; line < h; line++) {
+        uint32 *left = raster + (line * w);
+        uint32 *right = left + w - 1;
+        
+        while ( left < right ) {
+          uint32 temp = *left;
+          *left = *right;
+          *right = temp;
+          left++, right--;
+        }
+      }
+    }
+
+    _TIFFfree(buf);
+    return (ret);
+}
+
+/*
+ * Get a strip-organized image with
+ *   SamplesPerPixel > 1
+ *   PlanarConfiguration separated
+ * We assume that all such images are RGB.
+ */
+static int
+gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
+{
+    TIFF* tif = img->tif;
+    tileSeparateRoutine put = img->put.separate;
+    unsigned char *buf;
+    unsigned char *r, *g, *b, *a;
+    uint32 row, y, nrow, rowstoread;
+    uint32 pos;
+    tsize_t scanline;
+    uint32 rowsperstrip, offset_row;
+    uint32 imagewidth = img->width;
+    tsize_t stripsize;
+    int32 fromskew, toskew;
+    int alpha = img->alpha;
+    int  ret = 1, flip;
+
+    stripsize = TIFFStripSize(tif);
+    r = buf = (unsigned char *)_TIFFmalloc(4*stripsize);
+    if (buf == 0) {
+  TIFFError(TIFFFileName(tif), "No space for tile buffer");
+  return (0);
+    }
+    _TIFFmemset(buf, 0, 4*stripsize);
+    g = r + stripsize;
+    b = g + stripsize;
+    a = b + stripsize;
+    if (!alpha)
+  _TIFFmemset(a, 0xff, stripsize);
+
+    flip = setorientation(img);
+    if (flip & FLIP_VERTICALLY) {
+      y = h - 1;
+      toskew = -(int32)(w + w);
+    }
+    else {
+      y = 0;
+      toskew = -(int32)(w - w);
+    }
+
+    TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
+    scanline = TIFFScanlineSize(tif);
+    fromskew = (w < imagewidth ? imagewidth - w : 0);
+    for (row = 0; row < h; row += nrow) 
+    {
+        rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip;      
+        nrow = (row + rowstoread > h ? h - row : rowstoread);
+        offset_row = row + img->row_offset;
+      if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 0),
+                                 r, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) < 0 
+            && img->stoponerr)
+        {
+            ret = 0;
+            break;
+        }
+        if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 1),
+                                 g, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) < 0 
+            && img->stoponerr)
+        {
+            ret = 0;
+            break;
+        }
+        if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 2),
+                                 b, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) < 0 
+            && img->stoponerr)
+        {
+            ret = 0;
+            break;
+        }
+        if (alpha &&
+            (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 3),
+                                  a, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) < 0 
+             && img->stoponerr))
+        {
+            ret = 0;
+            break;
+        }
+
+        pos = ((row + img->row_offset) % rowsperstrip) * scanline;
+        (*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, r + pos, g + pos, 
+               b + pos, a + pos);
+        y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow);
+    }
+
+    if (flip & FLIP_HORIZONTALLY) {
+      uint32 line;
+
+      for (line = 0; line < h; line++) {
+        uint32 *left = raster + (line * w);
+        uint32 *right = left + w - 1;
+        
+        while ( left < right ) {
+          uint32 temp = *left;
+          *left = *right;
+          *right = temp;
+          left++, right--;
+        }
+      }
+    }
+
+    _TIFFfree(buf);
+    return (ret);
+}
+
+/*
+ * The following routines move decoded data returned
+ * from the TIFF library into rasters filled with packed
+ * ABGR pixels (i.e. suitable for passing to lrecwrite.)
+ *
+ * The routines have been created according to the most
+ * important cases and optimized.  pickTileContigCase and
+ * pickTileSeparateCase analyze the parameters and select
+ * the appropriate "put" routine to use.
+ */
+#define  REPEAT8(op)  REPEAT4(op); REPEAT4(op)
+#define  REPEAT4(op)  REPEAT2(op); REPEAT2(op)
+#define  REPEAT2(op)  op; op
+#define  CASE8(x,op)      \
+    switch (x) {      \
+    case 7: op; case 6: op; case 5: op;  \
+    case 4: op; case 3: op; case 2: op;  \
+    case 1: op;        \
+    }
+#define  CASE4(x,op)  switch (x) { case 3: op; case 2: op; case 1: op; }
+#define  NOP
+
+#define  UNROLL8(w, op1, op2) {    \
+    uint32 _x;        \
+    for (_x = w; _x >= 8; _x -= 8) {  \
+  op1;        \
+  REPEAT8(op2);      \
+    }          \
+    if (_x > 0) {      \
+  op1;        \
+  CASE8(_x,op2);      \
+    }          \
+}
+#define  UNROLL4(w, op1, op2) {    \
+    uint32 _x;        \
+    for (_x = w; _x >= 4; _x -= 4) {  \
+  op1;        \
+  REPEAT4(op2);      \
+    }          \
+    if (_x > 0) {      \
+  op1;        \
+  CASE4(_x,op2);      \
+    }          \
+}
+#define  UNROLL2(w, op1, op2) {    \
+    uint32 _x;        \
+    for (_x = w; _x >= 2; _x -= 2) {  \
+  op1;        \
+  REPEAT2(op2);      \
+    }          \
+    if (_x) {        \
+  op1;        \
+  op2;        \
+    }          \
+}
+    
+#define  SKEW(r,g,b,skew)  { r += skew; g += skew; b += skew; }
+#define  SKEW4(r,g,b,a,skew)  { r += skew; g += skew; b += skew; a+= skew; }
+
+#define A1 (((uint32)0xffL)<<24)
+#define  PACK(r,g,b)  \
+  ((uint32)(r)|((uint32)(g)<<8)|((uint32)(b)<<16)|A1)
+#define  PACK4(r,g,b,a)  \
+  ((uint32)(r)|((uint32)(g)<<8)|((uint32)(b)<<16)|((uint32)(a)<<24))
+#define W2B(v) (((v)>>8)&0xff)
+#define  PACKW(r,g,b)  \
+  ((uint32)W2B(r)|((uint32)W2B(g)<<8)|((uint32)W2B(b)<<16)|A1)
+#define  PACKW4(r,g,b,a)  \
+  ((uint32)W2B(r)|((uint32)W2B(g)<<8)|((uint32)W2B(b)<<16)|((uint32)W2B(a)<<24))
+
+#define  DECLAREContigPutFunc(name) \
+static void name(\
+    TIFFRGBAImage* img, \
+    uint32* cp, \
+    uint32 x, uint32 y, \
+    uint32 w, uint32 h, \
+    int32 fromskew, int32 toskew, \
+    unsigned char* pp \
+)
+
+/*
+ * 8-bit palette => colormap/RGB
+ */
+DECLAREContigPutFunc(put8bitcmaptile)
+{
+    uint32** PALmap = img->PALmap;
+    int samplesperpixel = img->samplesperpixel;
+
+    (void) y;
+    while (h-- > 0) {
+  for (x = w; x-- > 0;)
+        {
+      *cp++ = PALmap[*pp][0];
+            pp += samplesperpixel;
+        }
+  cp += toskew;
+  pp += fromskew;
+    }
+}
+
+/*
+ * 4-bit palette => colormap/RGB
+ */
+DECLAREContigPutFunc(put4bitcmaptile)
+{
+    uint32** PALmap = img->PALmap;
+
+    (void) x; (void) y;
+    fromskew /= 2;
+    while (h-- > 0) {
+  uint32* bw;
+  UNROLL2(w, bw = PALmap[*pp++], *cp++ = *bw++);
+  cp += toskew;
+  pp += fromskew;
+    }
+}
+
+/*
+ * 2-bit palette => colormap/RGB
+ */
+DECLAREContigPutFunc(put2bitcmaptile)
+{
+    uint32** PALmap = img->PALmap;
+
+    (void) x; (void) y;
+    fromskew /= 4;
+    while (h-- > 0) {
+  uint32* bw;
+  UNROLL4(w, bw = PALmap[*pp++], *cp++ = *bw++);
+  cp += toskew;
+  pp += fromskew;
+    }
+}
+
+/*
+ * 1-bit palette => colormap/RGB
+ */
+DECLAREContigPutFunc(put1bitcmaptile)
+{
+    uint32** PALmap = img->PALmap;
+
+    (void) x; (void) y;
+    fromskew /= 8;
+    while (h-- > 0) {
+  uint32* bw;
+  UNROLL8(w, bw = PALmap[*pp++], *cp++ = *bw++);
+  cp += toskew;
+  pp += fromskew;
+    }
+}
+
+/*
+ * 8-bit greyscale => colormap/RGB
+ */
+DECLAREContigPutFunc(putgreytile)
+{
+    int samplesperpixel = img->samplesperpixel;
+    uint32** BWmap = img->BWmap;
+
+    (void) y;
+    while (h-- > 0) {
+  for (x = w; x-- > 0;)
+        {
+      *cp++ = BWmap[*pp][0];
+            pp += samplesperpixel;
+        }
+  cp += toskew;
+  pp += fromskew;
+    }
+}
+
+/*
+ * 16-bit greyscale => colormap/RGB
+ */
+DECLAREContigPutFunc(put16bitbwtile)
+{
+    int samplesperpixel = img->samplesperpixel;
+    uint32** BWmap = img->BWmap;
+
+    (void) y;
+    while (h-- > 0) {
+        uint16 *wp = (uint16 *) pp;
+
+  for (x = w; x-- > 0;)
+        {
+            /* use high order byte of 16bit value */
+
+      *cp++ = BWmap[*wp >> 8][0];
+            pp += 2 * samplesperpixel;
+            wp += samplesperpixel;
+        }
+  cp += toskew;
+  pp += fromskew;
+    }
+}
+
+/*
+ * 1-bit bilevel => colormap/RGB
+ */
+DECLAREContigPutFunc(put1bitbwtile)
+{
+    uint32** BWmap = img->BWmap;
+
+    (void) x; (void) y;
+    fromskew /= 8;
+    while (h-- > 0) {
+  uint32* bw;
+  UNROLL8(w, bw = BWmap[*pp++], *cp++ = *bw++);
+  cp += toskew;
+  pp += fromskew;
+    }
+}
+
+/*
+ * 2-bit greyscale => colormap/RGB
+ */
+DECLAREContigPutFunc(put2bitbwtile)
+{
+  uint32** BWmap = img->BWmap;
+
+  (void) x; (void) y;
+  fromskew /= 4;
+  while (h-- > 0) {
+    uint32* bw;
+    UNROLL4(w, bw = BWmap[*pp++], *cp++ = *bw++);
+    cp += toskew;
+    pp += fromskew;
+  }
+}
+
+/*
+ * 4-bit greyscale => colormap/RGB
+ */
+DECLAREContigPutFunc(put4bitbwtile)
+{
+  uint32** BWmap = img->BWmap;
+
+  (void) x; (void) y;
+  fromskew /= 2;
+  while (h-- > 0) {
+    uint32* bw;
+    UNROLL2(w, bw = BWmap[*pp++], *cp++ = *bw++);
+    cp += toskew;
+    pp += fromskew;
+  }
+}
+
+/*
+ * 8-bit packed samples, no Map => RGB
+ */
+DECLAREContigPutFunc(putRGBcontig8bittile)
+{
+    int samplesperpixel = img->samplesperpixel;
+
+    (void) x; (void) y;
+    fromskew *= samplesperpixel;
+    while (h-- > 0) {
+  UNROLL8(w, NOP,
+      *cp++ = PACK(pp[0], pp[1], pp[2]);
+      pp += samplesperpixel);
+  cp += toskew;
+  pp += fromskew;
+    }
+}
+
+/*
+ * 8-bit packed samples, w/ Map => RGB
+ */
+DECLAREContigPutFunc(putRGBcontig8bitMaptile)
+{
+    TIFFRGBValue* Map = img->Map;
+    int samplesperpixel = img->samplesperpixel;
+
+    (void) y;
+    fromskew *= samplesperpixel;
+    while (h-- > 0) {
+  for (x = w; x-- > 0;) {
+      *cp++ = PACK(Map[pp[0]], Map[pp[1]], Map[pp[2]]);
+      pp += samplesperpixel;
+  }
+  pp += fromskew;
+  cp += toskew;
+    }
+}
+
+/*
+ * 8-bit packed samples => RGBA w/ associated alpha
+ * (known to have Map == NULL)
+ */
+DECLAREContigPutFunc(putRGBAAcontig8bittile)
+{
+    int samplesperpixel = img->samplesperpixel;
+
+    (void) x; (void) y;
+    fromskew *= samplesperpixel;
+    while (h-- > 0) {
+  UNROLL8(w, NOP,
+      *cp++ = PACK4(pp[0], pp[1], pp[2], pp[3]);
+      pp += samplesperpixel);
+  cp += toskew;
+  pp += fromskew;
+    }
+}
+
+/*
+ * 8-bit packed samples => RGBA w/ unassociated alpha
+ * (known to have Map == NULL)
+ */
+DECLAREContigPutFunc(putRGBUAcontig8bittile)
+{
+    int samplesperpixel = img->samplesperpixel;
+
+    (void) y;
+    fromskew *= samplesperpixel;
+    while (h-- > 0) {
+  uint32 r, g, b, a;
+  for (x = w; x-- > 0;) {
+      a = pp[3];
+      r = (pp[0] * a) / 255;
+      g = (pp[1] * a) / 255;
+      b = (pp[2] * a) / 255;
+      *cp++ = PACK4(r,g,b,a);
+      pp += samplesperpixel;
+  }
+  cp += toskew;
+  pp += fromskew;
+    }
+}
+
+/*
+ * 16-bit packed samples => RGB
+ */
+DECLAREContigPutFunc(putRGBcontig16bittile)
+{
+    int samplesperpixel = img->samplesperpixel;
+    uint16 *wp = (uint16 *)pp;
+
+    (void) y;
+    fromskew *= samplesperpixel;
+    while (h-- > 0) {
+  for (x = w; x-- > 0;) {
+      *cp++ = PACKW(wp[0], wp[1], wp[2]);
+      wp += samplesperpixel;
+  }
+  cp += toskew;
+  wp += fromskew;
+    }
+}
+
+/*
+ * 16-bit packed samples => RGBA w/ associated alpha
+ * (known to have Map == NULL)
+ */
+DECLAREContigPutFunc(putRGBAAcontig16bittile)
+{
+    int samplesperpixel = img->samplesperpixel;
+    uint16 *wp = (uint16 *)pp;
+
+    (void) y;
+    fromskew *= samplesperpixel;
+    while (h-- > 0) {
+  for (x = w; x-- > 0;) {
+      *cp++ = PACKW4(wp[0], wp[1], wp[2], wp[3]);
+      wp += samplesperpixel;
+  }
+  cp += toskew;
+  wp += fromskew;
+    }
+}
+
+/*
+ * 16-bit packed samples => RGBA w/ unassociated alpha
+ * (known to have Map == NULL)
+ */
+DECLAREContigPutFunc(putRGBUAcontig16bittile)
+{
+    int samplesperpixel = img->samplesperpixel;
+    uint16 *wp = (uint16 *)pp;
+
+    (void) y;
+    fromskew *= samplesperpixel;
+    while (h-- > 0) {
+  uint32 r,g,b,a;
+  /*
+   * We shift alpha down four bits just in case unsigned
+   * arithmetic doesn't handle the full range.
+   * We still have plenty of accuracy, since the output is 8 bits.
+   * So we have (r * 0xffff) * (a * 0xfff)) = r*a * (0xffff*0xfff)
+   * Since we want r*a * 0xff for eight bit output,
+   * we divide by (0xffff * 0xfff) / 0xff == 0x10eff.
+   */
+  for (x = w; x-- > 0;) {
+      a = wp[3] >> 4; 
+      r = (wp[0] * a) / 0x10eff;
+      g = (wp[1] * a) / 0x10eff;
+      b = (wp[2] * a) / 0x10eff;
+      *cp++ = PACK4(r,g,b,a);
+      wp += samplesperpixel;
+  }
+  cp += toskew;
+  wp += fromskew;
+    }
+}
+
+/*
+ * 8-bit packed CMYK samples w/o Map => RGB
+ *
+ * NB: The conversion of CMYK->RGB is *very* crude.
+ */
+DECLAREContigPutFunc(putRGBcontig8bitCMYKtile)
+{
+    int samplesperpixel = img->samplesperpixel;
+    uint16 r, g, b, k;
+
+    (void) x; (void) y;
+    fromskew *= samplesperpixel;
+    while (h-- > 0) {
+  UNROLL8(w, NOP,
+      k = 255 - pp[3];
+      r = (k*(255-pp[0]))/255;
+      g = (k*(255-pp[1]))/255;
+      b = (k*(255-pp[2]))/255;
+      *cp++ = PACK(r, g, b);
+      pp += samplesperpixel);
+  cp += toskew;
+  pp += fromskew;
+    }
+}
+
+/*
+ * 8-bit packed CMYK samples w/Map => RGB
+ *
+ * NB: The conversion of CMYK->RGB is *very* crude.
+ */
+DECLAREContigPutFunc(putRGBcontig8bitCMYKMaptile)
+{
+    int samplesperpixel = img->samplesperpixel;
+    TIFFRGBValue* Map = img->Map;
+    uint16 r, g, b, k;
+
+    (void) y;
+    fromskew *= samplesperpixel;
+    while (h-- > 0) {
+  for (x = w; x-- > 0;) {
+      k = 255 - pp[3];
+      r = (k*(255-pp[0]))/255;
+      g = (k*(255-pp[1]))/255;
+      b = (k*(255-pp[2]))/255;
+      *cp++ = PACK(Map[r], Map[g], Map[b]);
+      pp += samplesperpixel;
+  }
+  pp += fromskew;
+  cp += toskew;
+    }
+}
+
+#define  DECLARESepPutFunc(name) \
+static void name(\
+    TIFFRGBAImage* img,\
+    uint32* cp,\
+    uint32 x, uint32 y, \
+    uint32 w, uint32 h,\
+    int32 fromskew, int32 toskew,\
+    unsigned char* r, unsigned char* g, unsigned char* b, unsigned char* a\
+)
+
+/*
+ * 8-bit unpacked samples => RGB
+ */
+DECLARESepPutFunc(putRGBseparate8bittile)
+{
+    (void) img; (void) x; (void) y; (void) a;
+    while (h-- > 0) {
+  UNROLL8(w, NOP, *cp++ = PACK(*r++, *g++, *b++));
+  SKEW(r, g, b, fromskew);
+  cp += toskew;
+    }
+}
+
+/*
+ * 8-bit unpacked samples => RGB
+ */
+DECLARESepPutFunc(putRGBseparate8bitMaptile)
+{
+    TIFFRGBValue* Map = img->Map;
+
+    (void) y; (void) a;
+    while (h-- > 0) {
+  for (x = w; x > 0; x--)
+      *cp++ = PACK(Map[*r++], Map[*g++], Map[*b++]);
+  SKEW(r, g, b, fromskew);
+  cp += toskew;
+    }
+}
+
+/*
+ * 8-bit unpacked samples => RGBA w/ associated alpha
+ */
+DECLARESepPutFunc(putRGBAAseparate8bittile)
+{
+    (void) img; (void) x; (void) y;
+    while (h-- > 0) {
+  UNROLL8(w, NOP, *cp++ = PACK4(*r++, *g++, *b++, *a++));
+  SKEW4(r, g, b, a, fromskew);
+  cp += toskew;
+    }
+}
+
+/*
+ * 8-bit unpacked samples => RGBA w/ unassociated alpha
+ */
+DECLARESepPutFunc(putRGBUAseparate8bittile)
+{
+    (void) img; (void) y;
+    while (h-- > 0) {
+  uint32 rv, gv, bv, av;
+  for (x = w; x-- > 0;) {
+      av = *a++;
+      rv = (*r++ * av) / 255;
+      gv = (*g++ * av) / 255;
+      bv = (*b++ * av) / 255;
+      *cp++ = PACK4(rv,gv,bv,av);
+  }
+  SKEW4(r, g, b, a, fromskew);
+  cp += toskew;
+    }
+}
+
+/*
+ * 16-bit unpacked samples => RGB
+ */
+DECLARESepPutFunc(putRGBseparate16bittile)
+{
+    uint16 *wr = (uint16*) r;
+    uint16 *wg = (uint16*) g;
+    uint16 *wb = (uint16*) b;
+
+    (void) img; (void) y; (void) a;
+    while (h-- > 0) {
+  for (x = 0; x < w; x++)
+      *cp++ = PACKW(*wr++, *wg++, *wb++);
+  SKEW(wr, wg, wb, fromskew);
+  cp += toskew;
+    }
+}
+
+/*
+ * 16-bit unpacked samples => RGBA w/ associated alpha
+ */
+DECLARESepPutFunc(putRGBAAseparate16bittile)
+{
+    uint16 *wr = (uint16*) r;
+    uint16 *wg = (uint16*) g;
+    uint16 *wb = (uint16*) b;
+    uint16 *wa = (uint16*) a;
+
+    (void) img; (void) y;
+    while (h-- > 0) {
+  for (x = 0; x < w; x++)
+      *cp++ = PACKW4(*wr++, *wg++, *wb++, *wa++);
+  SKEW4(wr, wg, wb, wa, fromskew);
+  cp += toskew;
+    }
+}
+
+/*
+ * 16-bit unpacked samples => RGBA w/ unassociated alpha
+ */
+DECLARESepPutFunc(putRGBUAseparate16bittile)
+{
+    uint16 *wr = (uint16*) r;
+    uint16 *wg = (uint16*) g;
+    uint16 *wb = (uint16*) b;
+    uint16 *wa = (uint16*) a;
+
+    (void) img; (void) y;
+    while (h-- > 0) {
+  uint32 r,g,b,a;
+  /*
+   * We shift alpha down four bits just in case unsigned
+   * arithmetic doesn't handle the full range.
+   * We still have plenty of accuracy, since the output is 8 bits.
+   * So we have (r * 0xffff) * (a * 0xfff)) = r*a * (0xffff*0xfff)
+   * Since we want r*a * 0xff for eight bit output,
+   * we divide by (0xffff * 0xfff) / 0xff == 0x10eff.
+   */
+  for (x = w; x-- > 0;) {
+      a = *wa++ >> 4; 
+      r = (*wr++ * a) / 0x10eff;
+      g = (*wg++ * a) / 0x10eff;
+      b = (*wb++ * a) / 0x10eff;
+      *cp++ = PACK4(r,g,b,a);
+  }
+  SKEW4(wr, wg, wb, wa, fromskew);
+  cp += toskew;
+    }
+}
+
+/*
+ * 8-bit packed CIE L*a*b 1976 samples => RGB
+ */
+DECLAREContigPutFunc(putcontig8bitCIELab)
+{
+  float X, Y, Z;
+  uint32 r, g, b;
+  (void) y;
+  fromskew *= 3;
+  while (h-- > 0) {
+    for (x = w; x-- > 0;) {
+      TIFFCIELabToXYZ(img->cielab,
+          (unsigned char)pp[0],
+          (signed char)pp[1],
+          (signed char)pp[2],
+          &X, &Y, &Z);
+      TIFFXYZToRGB(img->cielab, X, Y, Z, &r, &g, &b);
+      *cp++ = PACK(r, g, b);
+      pp += 3;
+    }
+    cp += toskew;
+    pp += fromskew;
+  }
+}
+
+/*
+ * YCbCr -> RGB conversion and packing routines.
+ */
+
+#define  YCbCrtoRGB(dst, Y) {            \
+  uint32 r, g, b;              \
+  TIFFYCbCrtoRGB(img->ycbcr, (Y), Cb, Cr, &r, &g, &b);    \
+  dst = PACK(r, g, b);            \
+}
+
+/*
+ * 8-bit packed YCbCr samples => RGB 
+ * This function is generic for different sampling sizes, 
+ * and can handle blocks sizes that aren't multiples of the
+ * sampling size.  However, it is substantially less optimized
+ * than the specific sampling cases.  It is used as a fallback
+ * for difficult blocks.
+ */
+#ifdef notdef
+static void putcontig8bitYCbCrGenericTile( 
+    TIFFRGBAImage* img, 
+    uint32* cp, 
+    uint32 x, uint32 y, 
+    uint32 w, uint32 h, 
+    int32 fromskew, int32 toskew, 
+    unsigned char* pp,
+    int h_group, 
+    int v_group )
+
+{
+    uint32* cp1 = cp+w+toskew;
+    uint32* cp2 = cp1+w+toskew;
+    uint32* cp3 = cp2+w+toskew;
+    int32 incr = 3*w+4*toskew;
+    int32   Cb, Cr;
+    int     group_size = v_group * h_group + 2;
+
+    (void) y;
+    fromskew = (fromskew * group_size) / h_group;
+
+    for( yy = 0; yy < h; yy++ )
+    {
+        unsigned char *pp_line;
+        int     y_line_group = yy / v_group;
+        int     y_remainder = yy - y_line_group * v_group;
+
+        pp_line = pp + v_line_group * 
+
+        
+        for( xx = 0; xx < w; xx++ )
+        {
+            Cb = pp
+        }
+    }
+    for (; h >= 4; h -= 4) {
+  x = w>>2;
+  do {
+      Cb = pp[16];
+      Cr = pp[17];
+
+      YCbCrtoRGB(cp [0], pp[ 0]);
+      YCbCrtoRGB(cp [1], pp[ 1]);
+      YCbCrtoRGB(cp [2], pp[ 2]);
+      YCbCrtoRGB(cp [3], pp[ 3]);
+      YCbCrtoRGB(cp1[0], pp[ 4]);
+      YCbCrtoRGB(cp1[1], pp[ 5]);
+      YCbCrtoRGB(cp1[2], pp[ 6]);
+      YCbCrtoRGB(cp1[3], pp[ 7]);
+      YCbCrtoRGB(cp2[0], pp[ 8]);
+      YCbCrtoRGB(cp2[1], pp[ 9]);
+      YCbCrtoRGB(cp2[2], pp[10]);
+      YCbCrtoRGB(cp2[3], pp[11]);
+      YCbCrtoRGB(cp3[0], pp[12]);
+      YCbCrtoRGB(cp3[1], pp[13]);
+      YCbCrtoRGB(cp3[2], pp[14]);
+      YCbCrtoRGB(cp3[3], pp[15]);
+
+      cp += 4, cp1 += 4, cp2 += 4, cp3 += 4;
+      pp += 18;
+  } while (--x);
+  cp += incr, cp1 += incr, cp2 += incr, cp3 += incr;
+  pp += fromskew;
+    }
+}
+#endif
+
+/*
+ * 8-bit packed YCbCr samples w/ 4,4 subsampling => RGB
+ */
+DECLAREContigPutFunc(putcontig8bitYCbCr44tile)
+{
+    uint32* cp1 = cp+w+toskew;
+    uint32* cp2 = cp1+w+toskew;
+    uint32* cp3 = cp2+w+toskew;
+    int32 incr = 3*w+4*toskew;
+
+    (void) y;
+    /* adjust fromskew */
+    fromskew = (fromskew * 18) / 4;
+    if ((h & 3) == 0 && (w & 3) == 0) {                
+        for (; h >= 4; h -= 4) {
+            x = w>>2;
+            do {
+                int32 Cb = pp[16];
+                int32 Cr = pp[17];
+
+                YCbCrtoRGB(cp [0], pp[ 0]);
+                YCbCrtoRGB(cp [1], pp[ 1]);
+                YCbCrtoRGB(cp [2], pp[ 2]);
+                YCbCrtoRGB(cp [3], pp[ 3]);
+                YCbCrtoRGB(cp1[0], pp[ 4]);
+                YCbCrtoRGB(cp1[1], pp[ 5]);
+                YCbCrtoRGB(cp1[2], pp[ 6]);
+                YCbCrtoRGB(cp1[3], pp[ 7]);
+                YCbCrtoRGB(cp2[0], pp[ 8]);
+                YCbCrtoRGB(cp2[1], pp[ 9]);
+                YCbCrtoRGB(cp2[2], pp[10]);
+                YCbCrtoRGB(cp2[3], pp[11]);
+                YCbCrtoRGB(cp3[0], pp[12]);
+                YCbCrtoRGB(cp3[1], pp[13]);
+                YCbCrtoRGB(cp3[2], pp[14]);
+                YCbCrtoRGB(cp3[3], pp[15]);
+
+                cp += 4, cp1 += 4, cp2 += 4, cp3 += 4;
+                pp += 18;
+            } while (--x);
+            cp += incr, cp1 += incr, cp2 += incr, cp3 += incr;
+            pp += fromskew;
+        }
+    } else {
+        while (h > 0) {
+            for (x = w; x > 0;) {
+                int32 Cb = pp[16];
+                int32 Cr = pp[17];
+                switch (x) {
+                default:
+                    switch (h) {
+                    default: YCbCrtoRGB(cp3[3], pp[15]); /* FALLTHROUGH */
+                    case 3:  YCbCrtoRGB(cp2[3], pp[11]); /* FALLTHROUGH */
+                    case 2:  YCbCrtoRGB(cp1[3], pp[ 7]); /* FALLTHROUGH */
+                    case 1:  YCbCrtoRGB(cp [3], pp[ 3]); /* FALLTHROUGH */
+                    }                                    /* FALLTHROUGH */
+                case 3:
+                    switch (h) {
+                    default: YCbCrtoRGB(cp3[2], pp[14]); /* FALLTHROUGH */
+                    case 3:  YCbCrtoRGB(cp2[2], pp[10]); /* FALLTHROUGH */
+                    case 2:  YCbCrtoRGB(cp1[2], pp[ 6]); /* FALLTHROUGH */
+                    case 1:  YCbCrtoRGB(cp [2], pp[ 2]); /* FALLTHROUGH */
+                    }                                    /* FALLTHROUGH */
+                case 2:
+                    switch (h) {
+                    default: YCbCrtoRGB(cp3[1], pp[13]); /* FALLTHROUGH */
+                    case 3:  YCbCrtoRGB(cp2[1], pp[ 9]); /* FALLTHROUGH */
+                    case 2:  YCbCrtoRGB(cp1[1], pp[ 5]); /* FALLTHROUGH */
+                    case 1:  YCbCrtoRGB(cp [1], pp[ 1]); /* FALLTHROUGH */
+                    }                                    /* FALLTHROUGH */
+                case 1:
+                    switch (h) {
+                    default: YCbCrtoRGB(cp3[0], pp[12]); /* FALLTHROUGH */
+                    case 3:  YCbCrtoRGB(cp2[0], pp[ 8]); /* FALLTHROUGH */
+                    case 2:  YCbCrtoRGB(cp1[0], pp[ 4]); /* FALLTHROUGH */
+                    case 1:  YCbCrtoRGB(cp [0], pp[ 0]); /* FALLTHROUGH */
+                    }                                    /* FALLTHROUGH */
+                }
+                if (x < 4) {
+                    cp += x; cp1 += x; cp2 += x; cp3 += x;
+                    x = 0;
+                }
+                else {
+                    cp += 4; cp1 += 4; cp2 += 4; cp3 += 4;
+                    x -= 4;
+                }
+                pp += 18;
+            }
+            if (h <= 4)
+                break;
+            h -= 4;
+            cp += incr, cp1 += incr, cp2 += incr, cp3 += incr;
+            pp += fromskew;
+        }
+    }
+}
+
+/*
+ * 8-bit packed YCbCr samples w/ 4,2 subsampling => RGB
+ */
+DECLAREContigPutFunc(putcontig8bitYCbCr42tile)
+{
+    uint32* cp1 = cp+w+toskew;
+    int32 incr = 2*toskew+w;
+
+    (void) y;
+    fromskew = (fromskew * 10) / 4;
+    if ((h & 3) == 0 && (w & 1) == 0) {
+        for (; h >= 2; h -= 2) {
+            x = w>>2;
+            do {
+                int32 Cb = pp[8];
+                int32 Cr = pp[9];
+                
+                YCbCrtoRGB(cp [0], pp[0]);
+                YCbCrtoRGB(cp [1], pp[1]);
+                YCbCrtoRGB(cp [2], pp[2]);
+                YCbCrtoRGB(cp [3], pp[3]);
+                YCbCrtoRGB(cp1[0], pp[4]);
+                YCbCrtoRGB(cp1[1], pp[5]);
+                YCbCrtoRGB(cp1[2], pp[6]);
+                YCbCrtoRGB(cp1[3], pp[7]);
+                
+                cp += 4, cp1 += 4;
+                pp += 10;
+            } while (--x);
+            cp += incr, cp1 += incr;
+            pp += fromskew;
+        }
+    } else {
+        while (h > 0) {
+            for (x = w; x > 0;) {
+                int32 Cb = pp[8];
+                int32 Cr = pp[9];
+                switch (x) {
+                default:
+                    switch (h) {
+                    default: YCbCrtoRGB(cp1[3], pp[ 7]); /* FALLTHROUGH */
+                    case 1:  YCbCrtoRGB(cp [3], pp[ 3]); /* FALLTHROUGH */
+                    }                                    /* FALLTHROUGH */
+                case 3:
+                    switch (h) {
+                    default: YCbCrtoRGB(cp1[2], pp[ 6]); /* FALLTHROUGH */
+                    case 1:  YCbCrtoRGB(cp [2], pp[ 2]); /* FALLTHROUGH */
+                    }                                    /* FALLTHROUGH */
+                case 2:
+                    switch (h) {
+                    default: YCbCrtoRGB(cp1[1], pp[ 5]); /* FALLTHROUGH */
+                    case 1:  YCbCrtoRGB(cp [1], pp[ 1]); /* FALLTHROUGH */
+                    }                                    /* FALLTHROUGH */
+                case 1:
+                    switch (h) {
+                    default: YCbCrtoRGB(cp1[0], pp[ 4]); /* FALLTHROUGH */
+                    case 1:  YCbCrtoRGB(cp [0], pp[ 0]); /* FALLTHROUGH */
+                    }                                    /* FALLTHROUGH */
+                }
+                if (x < 4) {
+                    cp += x; cp1 += x;
+                    x = 0;
+                }
+                else {
+                    cp += 4; cp1 += 4;
+                    x -= 4;
+                }
+                pp += 10;
+            }
+            if (h <= 2)
+                break;
+            h -= 2;
+            cp += incr, cp1 += incr;
+            pp += fromskew;
+        }
+    }
+}
+
+/*
+ * 8-bit packed YCbCr samples w/ 4,1 subsampling => RGB
+ */
+DECLAREContigPutFunc(putcontig8bitYCbCr41tile)
+{
+    (void) y;
+    /* XXX adjust fromskew */
+    do {
+  x = w>>2;
+  do {
+      int32 Cb = pp[4];
+      int32 Cr = pp[5];
+
+      YCbCrtoRGB(cp [0], pp[0]);
+      YCbCrtoRGB(cp [1], pp[1]);
+      YCbCrtoRGB(cp [2], pp[2]);
+      YCbCrtoRGB(cp [3], pp[3]);
+
+      cp += 4;
+      pp += 6;
+  } while (--x);
+
+        if( (w&3) != 0 )
+        {
+      int32 Cb = pp[4];
+      int32 Cr = pp[5];
+
+            switch( (w&3) ) {
+              case 3: YCbCrtoRGB(cp [2], pp[2]);
+              case 2: YCbCrtoRGB(cp [1], pp[1]);
+              case 1: YCbCrtoRGB(cp [0], pp[0]);
+              case 0: break;
+            }
+
+            cp += (w&3);
+            pp += 6;
+        }
+
+  cp += toskew;
+  pp += fromskew;
+    } while (--h);
+
+}
+
+/*
+ * 8-bit packed YCbCr samples w/ 2,2 subsampling => RGB
+ */
+DECLAREContigPutFunc(putcontig8bitYCbCr22tile)
+{
+    uint32* cp1 = cp+w+toskew;
+    int32 incr = 2*toskew+w;
+
+    (void) y;
+    fromskew = (fromskew * 6) / 2;
+    if ((h & 1) == 0 && (w & 1) == 0) {
+        for (; h >= 2; h -= 2) {
+            x = w>>1;
+            do {
+                int32 Cb = pp[4];
+                int32 Cr = pp[5];
+
+                YCbCrtoRGB(cp [0], pp[0]);
+                YCbCrtoRGB(cp [1], pp[1]);
+                YCbCrtoRGB(cp1[0], pp[2]);
+                YCbCrtoRGB(cp1[1], pp[3]);
+
+                cp += 2, cp1 += 2;
+                pp += 6;
+            } while (--x);
+            cp += incr, cp1 += incr;
+            pp += fromskew;
+        }
+    } else {
+        while (h > 0) {
+            for (x = w; x > 0;) {
+                int32 Cb = pp[4];
+                int32 Cr = pp[5];
+                switch (x) {
+                default:
+                    switch (h) {
+                    default: YCbCrtoRGB(cp1[1], pp[ 3]); /* FALLTHROUGH */
+                    case 1:  YCbCrtoRGB(cp [1], pp[ 1]); /* FALLTHROUGH */
+                    }                                    /* FALLTHROUGH */
+                case 1:
+                    switch (h) {
+                    default: YCbCrtoRGB(cp1[0], pp[ 2]); /* FALLTHROUGH */
+                    case 1:  YCbCrtoRGB(cp [0], pp[ 0]); /* FALLTHROUGH */
+                    }                                    /* FALLTHROUGH */
+                }
+                if (x < 2) {
+                    cp += x; cp1 += x;
+                    x = 0;
+                }
+                else {
+                    cp += 2; cp1 += 2;
+                    x -= 2;
+                }
+                pp += 6;
+            }
+            if (h <= 2)
+                break;
+            h -= 2;
+            cp += incr, cp1 += incr;
+            pp += fromskew;
+        }
+    }
+}
+
+/*
+ * 8-bit packed YCbCr samples w/ 2,1 subsampling => RGB
+ */
+DECLAREContigPutFunc(putcontig8bitYCbCr21tile)
+{
+    (void) y;
+    fromskew = (fromskew * 4) / 2;
+    do {
+  x = w>>1;
+  do {
+      int32 Cb = pp[2];
+      int32 Cr = pp[3];
+
+      YCbCrtoRGB(cp[0], pp[0]); 
+      YCbCrtoRGB(cp[1], pp[1]);
+
+      cp += 2;
+      pp += 4;
+  } while (--x);
+
+        if( (w&1) != 0 )
+        {
+      int32 Cb = pp[2];
+      int32 Cr = pp[3];
+            
+            YCbCrtoRGB(cp [0], pp[0]);
+
+      cp += 1;
+      pp += 4;
+        }
+
+  cp += toskew;
+  pp += fromskew;
+    } while (--h);
+}
+
+/*
+ * 8-bit packed YCbCr samples w/ no subsampling => RGB
+ */
+DECLAREContigPutFunc(putcontig8bitYCbCr11tile)
+{
+    (void) y;
+    fromskew *= 3;
+    do {
+        x = w; /* was x = w>>1; patched 2000/09/25 warmerda@home.com */ 
+  do {
+      int32 Cb = pp[1];
+      int32 Cr = pp[2];
+
+      YCbCrtoRGB(*cp++, pp[0]);
+
+      pp += 3;
+  } while (--x);
+  cp += toskew;
+  pp += fromskew;
+    } while (--h);
+}
+#undef  YCbCrtoRGB
+
+static tileContigRoutine
+initYCbCrConversion(TIFFRGBAImage* img)
+{
+  static char module[] = "initCIELabConversion";
+
+  float *luma, *refBlackWhite;
+  uint16 hs, vs;
+
+  if (img->ycbcr == NULL) {
+      img->ycbcr = (TIFFYCbCrToRGB*) _TIFFmalloc(
+        TIFFroundup(sizeof (TIFFYCbCrToRGB), sizeof (long))
+        + 4*256*sizeof (TIFFRGBValue)
+        + 2*256*sizeof (int)
+        + 3*256*sizeof (int32)
+      );
+      if (img->ycbcr == NULL) {
+        TIFFError(module,
+            "No space for YCbCr->RGB conversion state");
+        return (NULL);
+      }
+  }
+
+  TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRCOEFFICIENTS, &luma);
+  TIFFGetFieldDefaulted(img->tif, TIFFTAG_REFERENCEBLACKWHITE,
+            &refBlackWhite);
+  if (TIFFYCbCrToRGBInit(img->ycbcr, luma, refBlackWhite) < 0)
+    return NULL;
+
+  /*
+   * The 6.0 spec says that subsampling must be
+   * one of 1, 2, or 4, and that vertical subsampling
+   * must always be <= horizontal subsampling; so
+   * there are only a few possibilities and we just
+   * enumerate the cases.
+   */
+  TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING, &hs, &vs);
+  switch ((hs<<4)|vs) {
+    case 0x44: return (putcontig8bitYCbCr44tile);
+    case 0x42: return (putcontig8bitYCbCr42tile);
+    case 0x41: return (putcontig8bitYCbCr41tile);
+    case 0x22: return (putcontig8bitYCbCr22tile);
+    case 0x21: return (putcontig8bitYCbCr21tile);
+    case 0x11: return (putcontig8bitYCbCr11tile);
+  }
+
+  return (NULL);
+}
+
+static tileContigRoutine
+initCIELabConversion(TIFFRGBAImage* img)
+{
+  static char module[] = "initCIELabConversion";
+
+  float   *whitePoint;
+  float   refWhite[3];
+
+  if (!img->cielab) {
+    img->cielab = (TIFFCIELabToRGB *)
+      _TIFFmalloc(sizeof(TIFFCIELabToRGB));
+    if (!img->cielab) {
+      TIFFError(module,
+          "No space for CIE L*a*b*->RGB conversion state.");
+      return NULL;
+    }
+  }
+
+  TIFFGetFieldDefaulted(img->tif, TIFFTAG_WHITEPOINT, &whitePoint);
+  refWhite[1] = 100.0F;
+  refWhite[0] = whitePoint[0] / whitePoint[1] * refWhite[1];
+  refWhite[2] = (1.0F - whitePoint[0] - whitePoint[1])
+          / whitePoint[1] * refWhite[1];
+  if (TIFFCIELabToRGBInit(img->cielab, &display_sRGB, refWhite) < 0) {
+    TIFFError(module,
+        "Failed to initialize CIE L*a*b*->RGB conversion state.");
+    _TIFFfree(img->cielab);
+    return NULL;
+  }
+
+  return putcontig8bitCIELab;
+}
+
+/*
+ * Greyscale images with less than 8 bits/sample are handled
+ * with a table to avoid lots of shifts and masks.  The table
+ * is setup so that put*bwtile (below) can retrieve 8/bitspersample
+ * pixel values simply by indexing into the table with one
+ * number.
+ */
+static int
+makebwmap(TIFFRGBAImage* img)
+{
+    TIFFRGBValue* Map = img->Map;
+    int bitspersample = img->bitspersample;
+    int nsamples = 8 / bitspersample;
+    int i;
+    uint32* p;
+
+    if( nsamples == 0 )
+        nsamples = 1;
+
+    img->BWmap = (uint32**) _TIFFmalloc(
+  256*sizeof (uint32 *)+(256*nsamples*sizeof(uint32)));
+    if (img->BWmap == NULL) {
+  TIFFError(TIFFFileName(img->tif), "No space for B&W mapping table");
+  return (0);
+    }
+    p = (uint32*)(img->BWmap + 256);
+    for (i = 0; i < 256; i++) {
+  TIFFRGBValue c;
+  img->BWmap[i] = p;
+  switch (bitspersample) {
+#define  GREY(x)  c = Map[x]; *p++ = PACK(c,c,c);
+  case 1:
+      GREY(i>>7);
+      GREY((i>>6)&1);
+      GREY((i>>5)&1);
+      GREY((i>>4)&1);
+      GREY((i>>3)&1);
+      GREY((i>>2)&1);
+      GREY((i>>1)&1);
+      GREY(i&1);
+      break;
+  case 2:
+      GREY(i>>6);
+      GREY((i>>4)&3);
+      GREY((i>>2)&3);
+      GREY(i&3);
+      break;
+  case 4:
+      GREY(i>>4);
+      GREY(i&0xf);
+      break;
+  case 8:
+        case 16:
+      GREY(i);
+      break;
+  }
+#undef  GREY
+    }
+    return (1);
+}
+
+/*
+ * Construct a mapping table to convert from the range
+ * of the data samples to [0,255] --for display.  This
+ * process also handles inverting B&W images when needed.
+ */ 
+static int
+setupMap(TIFFRGBAImage* img)
+{
+    int32 x, range;
+
+    range = (int32)((1L<<img->bitspersample)-1);
+    
+    /* treat 16 bit the same as eight bit */
+    if( img->bitspersample == 16 )
+        range = (int32) 255;
+
+    img->Map = (TIFFRGBValue*) _TIFFmalloc((range+1) * sizeof (TIFFRGBValue));
+    if (img->Map == NULL) {
+  TIFFError(TIFFFileName(img->tif),
+      "No space for photometric conversion table");
+  return (0);
+    }
+    if (img->photometric == PHOTOMETRIC_MINISWHITE) {
+  for (x = 0; x <= range; x++)
+      img->Map[x] = (TIFFRGBValue) (((range - x) * 255) / range);
+    } else {
+  for (x = 0; x <= range; x++)
+      img->Map[x] = (TIFFRGBValue) ((x * 255) / range);
+    }
+    if (img->bitspersample <= 16 &&
+  (img->photometric == PHOTOMETRIC_MINISBLACK ||
+   img->photometric == PHOTOMETRIC_MINISWHITE)) {
+  /*
+   * Use photometric mapping table to construct
+   * unpacking tables for samples <= 8 bits.
+   */
+  if (!makebwmap(img))
+      return (0);
+  /* no longer need Map, free it */
+  _TIFFfree(img->Map), img->Map = NULL;
+    }
+    return (1);
+}
+
+static int
+checkcmap(TIFFRGBAImage* img)
+{
+    uint16* r = img->redcmap;
+    uint16* g = img->greencmap;
+    uint16* b = img->bluecmap;
+    long n = 1L<<img->bitspersample;
+
+    while (n-- > 0)
+  if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256)
+      return (16);
+    return (8);
+}
+
+static void
+cvtcmap(TIFFRGBAImage* img)
+{
+    uint16* r = img->redcmap;
+    uint16* g = img->greencmap;
+    uint16* b = img->bluecmap;
+    long i;
+
+    for (i = (1L<<img->bitspersample)-1; i >= 0; i--) {
+#define  CVT(x)    ((uint16)((x)>>8))
+  r[i] = CVT(r[i]);
+  g[i] = CVT(g[i]);
+  b[i] = CVT(b[i]);
+#undef  CVT
+    }
+}
+
+/*
+ * Palette images with <= 8 bits/sample are handled
+ * with a table to avoid lots of shifts and masks.  The table
+ * is setup so that put*cmaptile (below) can retrieve 8/bitspersample
+ * pixel values simply by indexing into the table with one
+ * number.
+ */
+static int
+makecmap(TIFFRGBAImage* img)
+{
+    int bitspersample = img->bitspersample;
+    int nsamples = 8 / bitspersample;
+    uint16* r = img->redcmap;
+    uint16* g = img->greencmap;
+    uint16* b = img->bluecmap;
+    uint32 *p;
+    int i;
+
+    img->PALmap = (uint32**) _TIFFmalloc(
+  256*sizeof (uint32 *)+(256*nsamples*sizeof(uint32)));
+    if (img->PALmap == NULL) {
+  TIFFError(TIFFFileName(img->tif), "No space for Palette mapping table");
+  return (0);
+    }
+    p = (uint32*)(img->PALmap + 256);
+    for (i = 0; i < 256; i++) {
+  TIFFRGBValue c;
+  img->PALmap[i] = p;
+#define  CMAP(x)  c = (TIFFRGBValue) x; *p++ = PACK(r[c]&0xff, g[c]&0xff, b[c]&0xff);
+  switch (bitspersample) {
+  case 1:
+      CMAP(i>>7);
+      CMAP((i>>6)&1);
+      CMAP((i>>5)&1);
+      CMAP((i>>4)&1);
+      CMAP((i>>3)&1);
+      CMAP((i>>2)&1);
+      CMAP((i>>1)&1);
+      CMAP(i&1);
+      break;
+  case 2:
+      CMAP(i>>6);
+      CMAP((i>>4)&3);
+      CMAP((i>>2)&3);
+      CMAP(i&3);
+      break;
+  case 4:
+      CMAP(i>>4);
+      CMAP(i&0xf);
+      break;
+  case 8:
+      CMAP(i);
+      break;
+  }
+#undef CMAP
+    }
+    return (1);
+}
+
+/* 
+ * Construct any mapping table used
+ * by the associated put routine.
+ */
+static int
+buildMap(TIFFRGBAImage* img)
+{
+    switch (img->photometric) {
+    case PHOTOMETRIC_RGB:
+    case PHOTOMETRIC_YCBCR:
+    case PHOTOMETRIC_SEPARATED:
+  if (img->bitspersample == 8)
+      break;
+  /* fall thru... */
+    case PHOTOMETRIC_MINISBLACK:
+    case PHOTOMETRIC_MINISWHITE:
+  if (!setupMap(img))
+      return (0);
+  break;
+    case PHOTOMETRIC_PALETTE:
+  /*
+   * Convert 16-bit colormap to 8-bit (unless it looks
+   * like an old-style 8-bit colormap).
+   */
+  if (checkcmap(img) == 16)
+      cvtcmap(img);
+  else
+      TIFFWarning(TIFFFileName(img->tif), "Assuming 8-bit colormap");
+  /*
+   * Use mapping table and colormap to construct
+   * unpacking tables for samples < 8 bits.
+   */
+  if (img->bitspersample <= 8 && !makecmap(img))
+      return (0);
+  break;
+    }
+    return (1);
+}
+
+/*
+ * Select the appropriate conversion routine for packed data.
+ */
+static int
+pickTileContigCase(TIFFRGBAImage* img)
+{
+    tileContigRoutine put = 0;
+
+    if (buildMap(img)) {
+  switch (img->photometric) {
+  case PHOTOMETRIC_RGB:
+      switch (img->bitspersample) {
+      case 8:
+    if (!img->Map) {
+        if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
+      put = putRGBAAcontig8bittile;
+        else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
+      put = putRGBUAcontig8bittile;
+        else
+      put = putRGBcontig8bittile;
+    } else
+        put = putRGBcontig8bitMaptile;
+    break;
+      case 16:
+    put = putRGBcontig16bittile;
+    if (!img->Map) {
+        if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
+      put = putRGBAAcontig16bittile;
+        else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
+      put = putRGBUAcontig16bittile;
+    }
+    break;
+      }
+      break;
+  case PHOTOMETRIC_SEPARATED:
+      if (img->bitspersample == 8) {
+    if (!img->Map)
+        put = putRGBcontig8bitCMYKtile;
+    else
+        put = putRGBcontig8bitCMYKMaptile;
+      }
+      break;
+  case PHOTOMETRIC_PALETTE:
+      switch (img->bitspersample) {
+      case 8:  put = put8bitcmaptile; break;
+      case 4: put = put4bitcmaptile; break;
+      case 2: put = put2bitcmaptile; break;
+      case 1: put = put1bitcmaptile; break;
+      }
+      break;
+  case PHOTOMETRIC_MINISWHITE:
+  case PHOTOMETRIC_MINISBLACK:
+      switch (img->bitspersample) {
+            case 16: put = put16bitbwtile; break;
+      case 8:  put = putgreytile; break;
+      case 4:  put = put4bitbwtile; break;
+      case 2:  put = put2bitbwtile; break;
+      case 1:  put = put1bitbwtile; break;
+      }
+      break;
+  case PHOTOMETRIC_YCBCR:
+      if (img->bitspersample == 8)
+    put = initYCbCrConversion(img);
+      break;
+  case PHOTOMETRIC_CIELAB:
+      if (img->bitspersample == 8)
+    put = initCIELabConversion(img);
+      break;
+  }
+    }
+    return ((img->put.contig = put) != 0);
+}
+
+/*
+ * Select the appropriate conversion routine for unpacked data.
+ *
+ * NB: we assume that unpacked single channel data is directed
+ *   to the "packed routines.
+ */
+static int
+pickTileSeparateCase(TIFFRGBAImage* img)
+{
+    tileSeparateRoutine put = 0;
+
+    if (buildMap(img)) {
+  switch (img->photometric) {
+  case PHOTOMETRIC_RGB:
+      switch (img->bitspersample) {
+      case 8:
+    if (!img->Map) {
+        if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
+      put = putRGBAAseparate8bittile;
+        else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
+      put = putRGBUAseparate8bittile;
+        else
+      put = putRGBseparate8bittile;
+    } else
+        put = putRGBseparate8bitMaptile;
+    break;
+      case 16:
+    put = putRGBseparate16bittile;
+    if (!img->Map) {
+        if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
+      put = putRGBAAseparate16bittile;
+        else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
+      put = putRGBUAseparate16bittile;
+    }
+    break;
+      }
+      break;
+  }
+    }
+    return ((img->put.separate = put) != 0);
+}
+
+/*
+ * Read a whole strip off data from the file, and convert to RGBA form.
+ * If this is the last strip, then it will only contain the portion of
+ * the strip that is actually within the image space.  The result is
+ * organized in bottom to top form.
+ */
+
+
+int
+TIFFReadRGBAStrip(TIFF* tif, uint32 row, uint32 * raster )
+
+{
+    char   emsg[1024] = "";
+    TIFFRGBAImage img;
+    int   ok;
+    uint32  rowsperstrip, rows_to_read;
+
+    if( TIFFIsTiled( tif ) )
+    {
+        TIFFError(TIFFFileName(tif),
+                  "Can't use TIFFReadRGBAStrip() with tiled file.");
+  return (0);
+    }
+    
+    TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
+    if( (row % rowsperstrip) != 0 )
+    {
+        TIFFError(TIFFFileName(tif),
+                "Row passed to TIFFReadRGBAStrip() must be first in a strip.");
+  return (0);
+    }
+
+    if (TIFFRGBAImageOK(tif, emsg) && TIFFRGBAImageBegin(&img, tif, 0, emsg)) {
+
+        img.row_offset = row;
+        img.col_offset = 0;
+
+        if( row + rowsperstrip > img.height )
+            rows_to_read = img.height - row;
+        else
+            rows_to_read = rowsperstrip;
+        
+  ok = TIFFRGBAImageGet(&img, raster, img.width, rows_to_read );
+        
+  TIFFRGBAImageEnd(&img);
+    } else {
+  TIFFError(TIFFFileName(tif), emsg);
+  ok = 0;
+    }
+    
+    return (ok);
+}
+
+/*
+ * Read a whole tile off data from the file, and convert to RGBA form.
+ * The returned RGBA data is organized from bottom to top of tile,
+ * and may include zeroed areas if the tile extends off the image.
+ */
+
+int
+TIFFReadRGBATile(TIFF* tif, uint32 col, uint32 row, uint32 * raster)
+
+{
+    char   emsg[1024] = "";
+    TIFFRGBAImage img;
+    int   ok;
+    uint32  tile_xsize, tile_ysize;
+    uint32  read_xsize, read_ysize;
+    uint32  i_row;
+
+    /*
+     * Verify that our request is legal - on a tile file, and on a
+     * tile boundary.
+     */
+    
+    if( !TIFFIsTiled( tif ) )
+    {
+        TIFFError(TIFFFileName(tif),
+                  "Can't use TIFFReadRGBATile() with stripped file.");
+  return (0);
+    }
+    
+    TIFFGetFieldDefaulted(tif, TIFFTAG_TILEWIDTH, &tile_xsize);
+    TIFFGetFieldDefaulted(tif, TIFFTAG_TILELENGTH, &tile_ysize);
+    if( (col % tile_xsize) != 0 || (row % tile_ysize) != 0 )
+    {
+        TIFFError(TIFFFileName(tif),
+                  "Row/col passed to TIFFReadRGBATile() must be top"
+                  "left corner of a tile.");
+  return (0);
+    }
+
+    /*
+     * Setup the RGBA reader.
+     */
+    
+    if (!TIFFRGBAImageOK(tif, emsg) 
+  || !TIFFRGBAImageBegin(&img, tif, 0, emsg)) {
+      TIFFError(TIFFFileName(tif), emsg);
+      return( 0 );
+    }
+
+    /*
+     * The TIFFRGBAImageGet() function doesn't allow us to get off the
+     * edge of the image, even to fill an otherwise valid tile.  So we
+     * figure out how much we can read, and fix up the tile buffer to
+     * a full tile configuration afterwards.
+     */
+
+    if( row + tile_ysize > img.height )
+        read_ysize = img.height - row;
+    else
+        read_ysize = tile_ysize;
+    
+    if( col + tile_xsize > img.width )
+        read_xsize = img.width - col;
+    else
+        read_xsize = tile_xsize;
+
+    /*
+     * Read the chunk of imagery.
+     */
+    
+    img.row_offset = row;
+    img.col_offset = col;
+
+    ok = TIFFRGBAImageGet(&img, raster, read_xsize, read_ysize );
+        
+    TIFFRGBAImageEnd(&img);
+
+    /*
+     * If our read was incomplete we will need to fix up the tile by
+     * shifting the data around as if a full tile of data is being returned.
+     *
+     * This is all the more complicated because the image is organized in
+     * bottom to top format. 
+     */
+
+    if( read_xsize == tile_xsize && read_ysize == tile_ysize )
+        return( ok );
+
+    for( i_row = 0; i_row < read_ysize; i_row++ ) {
+        memmove( raster + (tile_ysize - i_row - 1) * tile_xsize,
+                 raster + (read_ysize - i_row - 1) * read_xsize,
+                 read_xsize * sizeof(uint32) );
+        _TIFFmemset( raster + (tile_ysize - i_row - 1) * tile_xsize+read_xsize,
+                     0, sizeof(uint32) * (tile_xsize - read_xsize) );
+    }
+
+    for( i_row = read_ysize; i_row < tile_ysize; i_row++ ) {
+        _TIFFmemset( raster + (tile_ysize - i_row - 1) * tile_xsize,
+                     0, sizeof(uint32) * tile_xsize );
+    }
+
+    return (ok);
+}
+
diff --git a/Utilities/ITK/Utilities/tiff/tif_jpeg.c b/Utilities/ITK/Utilities/tiff/tif_jpeg.c
new file mode 100644
index 0000000000..ed6f2a1f89
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_jpeg.c
@@ -0,0 +1,1754 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1994-1997 Sam Leffler
+ * Copyright (c) 1994-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+#include "tiffiop.h"
+#ifdef JPEG_SUPPORT
+/*
+ * TIFF Library
+ *
+ * JPEG Compression support per TIFF Technical Note #2
+ * (*not* per the original TIFF 6.0 spec).
+ *
+ * This file is simply an interface to the libjpeg library written by
+ * the Independent JPEG Group.  You need release 5 or later of the IJG
+ * code, which you can find on the Internet at ftp.uu.net:/graphics/jpeg/.
+ *
+ * Contributed by Tom Lane <tgl@sss.pgh.pa.us>.
+ */
+#include <setjmp.h>
+
+int TIFFFillStrip(TIFF*, tstrip_t);
+int TIFFFillTile(TIFF*, ttile_t);
+
+/* We undefine FAR to avoid conflict with JPEG definition */
+
+#ifdef FAR
+#undef FAR
+#endif
+
+
+/*
+   The windows RPCNDR.H file defines boolean, but defines it with the
+   unsigned char size.  You should compile JPEG library using appropriate
+   definitions in jconfig.h header, but many users compile library in wrong
+   way. That causes errors of the following type:
+
+   "JPEGLib: JPEG parameter struct mismatch: library thinks size is 432,
+   caller expects 464"
+
+   For such users we wil fix the problem here. See install.doc file from
+   the JPEG library distribution for details.
+*/
+
+/* Define "boolean" as unsigned char, not int, per Windows custom. */
+#if defined(WIN32) && !defined(__MINGW32__)
+# ifndef __RPCNDR_H__            /* don't conflict if rpcndr.h already read */
+   typedef unsigned char boolean;
+# endif
+# define HAVE_BOOLEAN            /* prevent jmorecfg.h from redefining it */
+#endif
+
+#include "jpeglib.h"
+#include "jerror.h"
+
+/*
+ * We are using width_in_blocks which is supposed to be private to
+ * libjpeg. Unfortunately, the libjpeg delivered with Cygwin has
+ * renamed this member to width_in_data_units.  Since the header has
+ * also renamed a define, use that unique define name in order to
+ * detect the problem header and adjust to suit.
+ */
+#if defined(D_MAX_DATA_UNITS_IN_MCU)
+#define width_in_blocks width_in_data_units
+#endif
+
+/*
+ * On some machines it may be worthwhile to use _setjmp or sigsetjmp
+ * in place of plain setjmp.  These macros will make it easier.
+ */
+#define SETJMP(jbuf)    setjmp(jbuf)
+#define LONGJMP(jbuf,code)  longjmp(jbuf,code)
+#define JMP_BUF      jmp_buf
+
+typedef struct jpeg_destination_mgr jpeg_destination_mgr;
+typedef struct jpeg_source_mgr jpeg_source_mgr;
+typedef  struct jpeg_error_mgr jpeg_error_mgr;
+
+/*
+ * State block for each open TIFF file using
+ * libjpeg to do JPEG compression/decompression.
+ *
+ * libjpeg's visible state is either a jpeg_compress_struct
+ * or jpeg_decompress_struct depending on which way we
+ * are going.  comm can be used to refer to the fields
+ * which are common to both.
+ *
+ * NB: cinfo is required to be the first member of JPEGState,
+ *     so we can safely cast JPEGState* -> jpeg_xxx_struct*
+ *     and vice versa!
+ */
+typedef  struct {
+  union {
+    struct jpeg_compress_struct c;
+    struct jpeg_decompress_struct d;
+    struct jpeg_common_struct comm;
+  } cinfo;      /* NB: must be first */
+        int             cinfo_initialized;
+
+  jpeg_error_mgr  err;    /* libjpeg error manager */
+  JMP_BUF    exit_jmpbuf;  /* for catching libjpeg failures */
+  /*
+   * The following two members could be a union, but
+   * they're small enough that it's not worth the effort.
+   */
+  jpeg_destination_mgr dest;  /* data dest for compression */
+  jpeg_source_mgr  src;    /* data source for decompression */
+          /* private state */
+  TIFF*    tif;    /* back link needed by some code */
+  uint16    photometric;  /* copy of PhotometricInterpretation */
+  uint16    h_sampling;  /* luminance sampling factors */
+  uint16    v_sampling;
+  tsize_t    bytesperline;  /* decompressed bytes per scanline */
+  /* pointers to intermediate buffers when processing downsampled data */
+  JSAMPARRAY  ds_buffer[MAX_COMPONENTS];
+  int    scancount;  /* number of "scanlines" accumulated */
+  int    samplesperclump;
+
+  TIFFVGetMethod  vgetparent;  /* super-class method */
+  TIFFVSetMethod  vsetparent;  /* super-class method */
+  TIFFStripMethod  defsparent;  /* super-class method */
+  TIFFTileMethod  deftparent;  /* super-class method */
+          /* pseudo-tag fields */
+  void*    jpegtables;  /* JPEGTables tag value, or NULL */
+  uint32    jpegtables_length; /* number of bytes in same */
+  int    jpegquality;  /* Compression quality level */
+  int    jpegcolormode;  /* Auto RGB<=>YCbCr convert? */
+  int    jpegtablesmode;  /* What to put in JPEGTables */
+
+        int             ycbcrsampling_fetched;
+  uint32    recvparams;  /* encoded Class 2 session params */
+  char*    subaddress;  /* subaddress string */
+  uint32    recvtime;  /* time spent receiving (secs) */
+  char*    faxdcs;    /* encoded fax parameters (DCS, Table 2/T.30) */
+} JPEGState;
+
+#define  JState(tif)  ((JPEGState*)(tif)->tif_data)
+
+static  int JPEGDecode(TIFF*, tidata_t, tsize_t, tsample_t);
+static  int JPEGDecodeRaw(TIFF*, tidata_t, tsize_t, tsample_t);
+static  int JPEGEncode(TIFF*, tidata_t, tsize_t, tsample_t);
+static  int JPEGEncodeRaw(TIFF*, tidata_t, tsize_t, tsample_t);
+static  int JPEGInitializeLibJPEG( TIFF * tif );
+
+#define  FIELD_JPEGTABLES  (FIELD_CODEC+0)
+#define  FIELD_RECVPARAMS  (FIELD_CODEC+1)
+#define  FIELD_SUBADDRESS  (FIELD_CODEC+2)
+#define  FIELD_RECVTIME    (FIELD_CODEC+3)
+#define  FIELD_FAXDCS    (FIELD_CODEC+4)
+
+static const TIFFFieldInfo jpegFieldInfo[] = {
+    { TIFFTAG_JPEGTABLES,   -3,-3,  TIFF_UNDEFINED,  FIELD_JPEGTABLES,
+      FALSE,  TRUE,  "JPEGTables" },
+    { TIFFTAG_JPEGQUALITY,   0, 0,  TIFF_ANY,  FIELD_PSEUDO,
+      TRUE,  FALSE,  "" },
+    { TIFFTAG_JPEGCOLORMODE,   0, 0,  TIFF_ANY,  FIELD_PSEUDO,
+      FALSE,  FALSE,  "" },
+    { TIFFTAG_JPEGTABLESMODE,   0, 0,  TIFF_ANY,  FIELD_PSEUDO,
+      FALSE,  FALSE,  "" },
+    /* Specific for JPEG in faxes */
+    { TIFFTAG_FAXRECVPARAMS,   1, 1, TIFF_LONG,  FIELD_RECVPARAMS,
+      TRUE,  FALSE,  "FaxRecvParams" },
+    { TIFFTAG_FAXSUBADDRESS,  -1,-1, TIFF_ASCII,  FIELD_SUBADDRESS,
+      TRUE,  FALSE,  "FaxSubAddress" },
+    { TIFFTAG_FAXRECVTIME,   1, 1, TIFF_LONG,  FIELD_RECVTIME,
+      TRUE,  FALSE,  "FaxRecvTime" },
+    { TIFFTAG_FAXDCS,    -1, -1, TIFF_ASCII,  FIELD_FAXDCS,
+      TRUE,  FALSE,  "FaxDcs" },
+};
+#define  N(a)  (sizeof (a) / sizeof (a[0]))
+
+/*
+ * libjpeg interface layer.
+ *
+ * We use setjmp/longjmp to return control to libtiff
+ * when a fatal error is encountered within the JPEG
+ * library.  We also direct libjpeg error and warning
+ * messages through the appropriate libtiff handlers.
+ */
+
+/*
+ * Error handling routines (these replace corresponding
+ * IJG routines from jerror.c).  These are used for both
+ * compression and decompression.
+ */
+static void
+TIFFjpeg_error_exit(j_common_ptr cinfo)
+{
+  JPEGState *sp = (JPEGState *) cinfo;  /* NB: cinfo assumed first */
+  char buffer[JMSG_LENGTH_MAX];
+
+  (*cinfo->err->format_message) (cinfo, buffer);
+  TIFFError("JPEGLib", buffer);    /* display the error message */
+  jpeg_abort(cinfo);      /* clean up libjpeg state */
+  LONGJMP(sp->exit_jmpbuf, 1);    /* return to libtiff caller */
+}
+
+/*
+ * This routine is invoked only for warning messages,
+ * since error_exit does its own thing and trace_level
+ * is never set > 0.
+ */
+static void
+TIFFjpeg_output_message(j_common_ptr cinfo)
+{
+  char buffer[JMSG_LENGTH_MAX];
+
+  (*cinfo->err->format_message) (cinfo, buffer);
+  TIFFWarning("JPEGLib", buffer);
+}
+
+/*
+ * Interface routines.  This layer of routines exists
+ * primarily to limit side-effects from using setjmp.
+ * Also, normal/error returns are converted into return
+ * values per libtiff practice.
+ */
+#define  CALLJPEG(sp, fail, op)  (SETJMP((sp)->exit_jmpbuf) ? (fail) : (op))
+#define  CALLVJPEG(sp, op)  CALLJPEG(sp, 0, ((op),1))
+
+static int
+TIFFjpeg_create_compress(JPEGState* sp)
+{
+  /* initialize JPEG error handling */
+  sp->cinfo.c.err = jpeg_std_error(&sp->err);
+  sp->err.error_exit = TIFFjpeg_error_exit;
+  sp->err.output_message = TIFFjpeg_output_message;
+
+  return CALLVJPEG(sp, jpeg_create_compress(&sp->cinfo.c));
+}
+
+static int
+TIFFjpeg_create_decompress(JPEGState* sp)
+{
+  /* initialize JPEG error handling */
+  sp->cinfo.d.err = jpeg_std_error(&sp->err);
+  sp->err.error_exit = TIFFjpeg_error_exit;
+  sp->err.output_message = TIFFjpeg_output_message;
+
+  return CALLVJPEG(sp, jpeg_create_decompress(&sp->cinfo.d));
+}
+
+static int
+TIFFjpeg_set_defaults(JPEGState* sp)
+{
+  return CALLVJPEG(sp, jpeg_set_defaults(&sp->cinfo.c));
+}
+
+static int
+TIFFjpeg_set_colorspace(JPEGState* sp, J_COLOR_SPACE colorspace)
+{
+  return CALLVJPEG(sp, jpeg_set_colorspace(&sp->cinfo.c, colorspace));
+}
+
+static int
+TIFFjpeg_set_quality(JPEGState* sp, int quality, boolean force_baseline)
+{
+  return CALLVJPEG(sp,
+      jpeg_set_quality(&sp->cinfo.c, quality, force_baseline));
+}
+
+static int
+TIFFjpeg_suppress_tables(JPEGState* sp, boolean suppress)
+{
+  return CALLVJPEG(sp, jpeg_suppress_tables(&sp->cinfo.c, suppress));
+}
+
+static int
+TIFFjpeg_start_compress(JPEGState* sp, boolean write_all_tables)
+{
+  return CALLVJPEG(sp,
+      jpeg_start_compress(&sp->cinfo.c, write_all_tables));
+}
+
+static int
+TIFFjpeg_write_scanlines(JPEGState* sp, JSAMPARRAY scanlines, int num_lines)
+{
+  return CALLJPEG(sp, -1, (int) jpeg_write_scanlines(&sp->cinfo.c,
+      scanlines, (JDIMENSION) num_lines));
+}
+
+static int
+TIFFjpeg_write_raw_data(JPEGState* sp, JSAMPIMAGE data, int num_lines)
+{
+  return CALLJPEG(sp, -1, (int) jpeg_write_raw_data(&sp->cinfo.c,
+      data, (JDIMENSION) num_lines));
+}
+
+static int
+TIFFjpeg_finish_compress(JPEGState* sp)
+{
+  return CALLVJPEG(sp, jpeg_finish_compress(&sp->cinfo.c));
+}
+
+static int
+TIFFjpeg_write_tables(JPEGState* sp)
+{
+  return CALLVJPEG(sp, jpeg_write_tables(&sp->cinfo.c));
+}
+
+static int
+TIFFjpeg_read_header(JPEGState* sp, boolean require_image)
+{
+  return CALLJPEG(sp, -1, jpeg_read_header(&sp->cinfo.d, require_image));
+}
+
+static int
+TIFFjpeg_start_decompress(JPEGState* sp)
+{
+  return CALLVJPEG(sp, jpeg_start_decompress(&sp->cinfo.d));
+}
+
+static int
+TIFFjpeg_read_scanlines(JPEGState* sp, JSAMPARRAY scanlines, int max_lines)
+{
+  return CALLJPEG(sp, -1, (int) jpeg_read_scanlines(&sp->cinfo.d,
+      scanlines, (JDIMENSION) max_lines));
+}
+
+static int
+TIFFjpeg_read_raw_data(JPEGState* sp, JSAMPIMAGE data, int max_lines)
+{
+  return CALLJPEG(sp, -1, (int) jpeg_read_raw_data(&sp->cinfo.d,
+      data, (JDIMENSION) max_lines));
+}
+
+static int
+TIFFjpeg_finish_decompress(JPEGState* sp)
+{
+  return CALLJPEG(sp, -1, (int) jpeg_finish_decompress(&sp->cinfo.d));
+}
+
+static int
+TIFFjpeg_abort(JPEGState* sp)
+{
+  return CALLVJPEG(sp, jpeg_abort(&sp->cinfo.comm));
+}
+
+static int
+TIFFjpeg_destroy(JPEGState* sp)
+{
+  return CALLVJPEG(sp, jpeg_destroy(&sp->cinfo.comm));
+}
+
+static JSAMPARRAY
+TIFFjpeg_alloc_sarray(JPEGState* sp, int pool_id,
+          JDIMENSION samplesperrow, JDIMENSION numrows)
+{
+  return CALLJPEG(sp, (JSAMPARRAY) NULL,
+      (*sp->cinfo.comm.mem->alloc_sarray)
+    (&sp->cinfo.comm, pool_id, samplesperrow, numrows));
+}
+
+/*
+ * JPEG library destination data manager.
+ * These routines direct compressed data from libjpeg into the
+ * libtiff output buffer.
+ */
+
+static void
+std_init_destination(j_compress_ptr cinfo)
+{
+  JPEGState* sp = (JPEGState*) cinfo;
+  TIFF* tif = sp->tif;
+
+  sp->dest.next_output_byte = (JOCTET*) tif->tif_rawdata;
+  sp->dest.free_in_buffer = (size_t) tif->tif_rawdatasize;
+}
+
+static boolean
+std_empty_output_buffer(j_compress_ptr cinfo)
+{
+  JPEGState* sp = (JPEGState*) cinfo;
+  TIFF* tif = sp->tif;
+
+  /* the entire buffer has been filled */
+  tif->tif_rawcc = tif->tif_rawdatasize;
+  TIFFFlushData1(tif);
+  sp->dest.next_output_byte = (JOCTET*) tif->tif_rawdata;
+  sp->dest.free_in_buffer = (size_t) tif->tif_rawdatasize;
+
+  return (TRUE);
+}
+
+static void
+std_term_destination(j_compress_ptr cinfo)
+{
+  JPEGState* sp = (JPEGState*) cinfo;
+  TIFF* tif = sp->tif;
+
+  tif->tif_rawcp = (tidata_t) sp->dest.next_output_byte;
+  tif->tif_rawcc =
+      tif->tif_rawdatasize - (tsize_t) sp->dest.free_in_buffer;
+  /* NB: libtiff does the final buffer flush */
+}
+
+static void
+TIFFjpeg_data_dest(JPEGState* sp, TIFF* tif)
+{
+  (void) tif;
+  sp->cinfo.c.dest = &sp->dest;
+  sp->dest.init_destination = std_init_destination;
+  sp->dest.empty_output_buffer = std_empty_output_buffer;
+  sp->dest.term_destination = std_term_destination;
+}
+
+/*
+ * Alternate destination manager for outputting to JPEGTables field.
+ */
+
+static void
+tables_init_destination(j_compress_ptr cinfo)
+{
+  JPEGState* sp = (JPEGState*) cinfo;
+
+  /* while building, jpegtables_length is allocated buffer size */
+  sp->dest.next_output_byte = (JOCTET*) sp->jpegtables;
+  sp->dest.free_in_buffer = (size_t) sp->jpegtables_length;
+}
+
+static boolean
+tables_empty_output_buffer(j_compress_ptr cinfo)
+{
+  JPEGState* sp = (JPEGState*) cinfo;
+  void* newbuf;
+
+  /* the entire buffer has been filled; enlarge it by 1000 bytes */
+  newbuf = _TIFFrealloc((tdata_t) sp->jpegtables,
+            (tsize_t) (sp->jpegtables_length + 1000));
+  if (newbuf == NULL)
+    ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 100);
+  sp->dest.next_output_byte = (JOCTET*) newbuf + sp->jpegtables_length;
+  sp->dest.free_in_buffer = (size_t) 1000;
+  sp->jpegtables = newbuf;
+  sp->jpegtables_length += 1000;
+  return (TRUE);
+}
+
+static void
+tables_term_destination(j_compress_ptr cinfo)
+{
+  JPEGState* sp = (JPEGState*) cinfo;
+
+  /* set tables length to number of bytes actually emitted */
+  sp->jpegtables_length -= sp->dest.free_in_buffer;
+}
+
+static int
+TIFFjpeg_tables_dest(JPEGState* sp, TIFF* tif)
+{
+  (void) tif;
+  /*
+   * Allocate a working buffer for building tables.
+   * Initial size is 1000 bytes, which is usually adequate.
+   */
+  if (sp->jpegtables)
+    _TIFFfree(sp->jpegtables);
+  sp->jpegtables_length = 1000;
+  sp->jpegtables = (void*) _TIFFmalloc((tsize_t) sp->jpegtables_length);
+  if (sp->jpegtables == NULL) {
+    sp->jpegtables_length = 0;
+    TIFFError("TIFFjpeg_tables_dest", "No space for JPEGTables");
+    return (0);
+  }
+  sp->cinfo.c.dest = &sp->dest;
+  sp->dest.init_destination = tables_init_destination;
+  sp->dest.empty_output_buffer = tables_empty_output_buffer;
+  sp->dest.term_destination = tables_term_destination;
+  return (1);
+}
+
+/*
+ * JPEG library source data manager.
+ * These routines supply compressed data to libjpeg.
+ */
+
+static void
+std_init_source(j_decompress_ptr cinfo)
+{
+  JPEGState* sp = (JPEGState*) cinfo;
+  TIFF* tif = sp->tif;
+
+  sp->src.next_input_byte = (const JOCTET*) tif->tif_rawdata;
+  sp->src.bytes_in_buffer = (size_t) tif->tif_rawcc;
+}
+
+static boolean
+std_fill_input_buffer(j_decompress_ptr cinfo)
+{
+  JPEGState* sp = (JPEGState* ) cinfo;
+  static const JOCTET dummy_EOI[2] = { 0xFF, JPEG_EOI };
+
+  /*
+   * Should never get here since entire strip/tile is
+   * read into memory before the decompressor is called,
+   * and thus was supplied by init_source.
+   */
+  WARNMS(cinfo, JWRN_JPEG_EOF);
+  /* insert a fake EOI marker */
+  sp->src.next_input_byte = dummy_EOI;
+  sp->src.bytes_in_buffer = 2;
+  return (TRUE);
+}
+
+static void
+std_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
+{
+  JPEGState* sp = (JPEGState*) cinfo;
+
+  if (num_bytes > 0) {
+    if (num_bytes > (long) sp->src.bytes_in_buffer) {
+      /* oops, buffer overrun */
+      (void) std_fill_input_buffer(cinfo);
+    } else {
+      sp->src.next_input_byte += (size_t) num_bytes;
+      sp->src.bytes_in_buffer -= (size_t) num_bytes;
+    }
+  }
+}
+
+static void
+std_term_source(j_decompress_ptr cinfo)
+{
+  /* No work necessary here */
+  /* Or must we update tif->tif_rawcp, tif->tif_rawcc ??? */
+  /* (if so, need empty tables_term_source!) */
+  (void) cinfo;
+}
+
+static void
+TIFFjpeg_data_src(JPEGState* sp, TIFF* tif)
+{
+  (void) tif;
+  sp->cinfo.d.src = &sp->src;
+  sp->src.init_source = std_init_source;
+  sp->src.fill_input_buffer = std_fill_input_buffer;
+  sp->src.skip_input_data = std_skip_input_data;
+  sp->src.resync_to_restart = jpeg_resync_to_restart;
+  sp->src.term_source = std_term_source;
+  sp->src.bytes_in_buffer = 0;    /* for safety */
+  sp->src.next_input_byte = NULL;
+}
+
+/*
+ * Alternate source manager for reading from JPEGTables.
+ * We can share all the code except for the init routine.
+ */
+
+static void
+tables_init_source(j_decompress_ptr cinfo)
+{
+  JPEGState* sp = (JPEGState*) cinfo;
+
+  sp->src.next_input_byte = (const JOCTET*) sp->jpegtables;
+  sp->src.bytes_in_buffer = (size_t) sp->jpegtables_length;
+}
+
+static void
+TIFFjpeg_tables_src(JPEGState* sp, TIFF* tif)
+{
+  TIFFjpeg_data_src(sp, tif);
+  sp->src.init_source = tables_init_source;
+}
+
+/*
+ * Allocate downsampled-data buffers needed for downsampled I/O.
+ * We use values computed in jpeg_start_compress or jpeg_start_decompress.
+ * We use libjpeg's allocator so that buffers will be released automatically
+ * when done with strip/tile.
+ * This is also a handy place to compute samplesperclump, bytesperline.
+ */
+static int
+alloc_downsampled_buffers(TIFF* tif, jpeg_component_info* comp_info,
+        int num_components)
+{
+  JPEGState* sp = JState(tif);
+  int ci;
+  jpeg_component_info* compptr;
+  JSAMPARRAY buf;
+  int samples_per_clump = 0;
+
+  for (ci = 0, compptr = comp_info; ci < num_components;
+       ci++, compptr++) {
+    samples_per_clump += compptr->h_samp_factor *
+      compptr->v_samp_factor;
+    buf = TIFFjpeg_alloc_sarray(sp, JPOOL_IMAGE,
+        compptr->width_in_blocks * DCTSIZE,
+        (JDIMENSION) (compptr->v_samp_factor*DCTSIZE));
+    if (buf == NULL)
+      return (0);
+    sp->ds_buffer[ci] = buf;
+  }
+  sp->samplesperclump = samples_per_clump;
+  return (1);
+}
+
+
+/*
+ * JPEG Decoding.
+ */
+
+static int
+JPEGSetupDecode(TIFF* tif)
+{
+  JPEGState* sp = JState(tif);
+  TIFFDirectory *td = &tif->tif_dir;
+
+        JPEGInitializeLibJPEG( tif );
+
+  assert(sp != NULL);
+  assert(sp->cinfo.comm.is_decompressor);
+
+  /* Read JPEGTables if it is present */
+  if (TIFFFieldSet(tif,FIELD_JPEGTABLES)) {
+    TIFFjpeg_tables_src(sp, tif);
+    if(TIFFjpeg_read_header(sp,FALSE) != JPEG_HEADER_TABLES_ONLY) {
+      TIFFError("JPEGSetupDecode", "Bogus JPEGTables field");
+      return (0);
+    }
+  }
+
+  /* Grab parameters that are same for all strips/tiles */
+  sp->photometric = td->td_photometric;
+  switch (sp->photometric) {
+  case PHOTOMETRIC_YCBCR:
+    sp->h_sampling = td->td_ycbcrsubsampling[0];
+    sp->v_sampling = td->td_ycbcrsubsampling[1];
+    break;
+  default:
+    /* TIFF 6.0 forbids subsampling of all other color spaces */
+    sp->h_sampling = 1;
+    sp->v_sampling = 1;
+    break;
+  }
+
+  /* Set up for reading normal data */
+  TIFFjpeg_data_src(sp, tif);
+  tif->tif_postdecode = _TIFFNoPostDecode; /* override byte swapping */
+  return (1);
+}
+
+/*
+ * Set up for decoding a strip or tile.
+ */
+static int
+JPEGPreDecode(TIFF* tif, tsample_t s)
+{
+  JPEGState *sp = JState(tif);
+  TIFFDirectory *td = &tif->tif_dir;
+  static const char module[] = "JPEGPreDecode";
+  uint32 segment_width, segment_height;
+  int downsampled_output;
+  int ci;
+
+  assert(sp != NULL);
+  assert(sp->cinfo.comm.is_decompressor);
+  /*
+   * Reset decoder state from any previous strip/tile,
+   * in case application didn't read the whole strip.
+   */
+  if (!TIFFjpeg_abort(sp))
+    return (0);
+  /*
+   * Read the header for this strip/tile.
+   */
+  if (TIFFjpeg_read_header(sp, TRUE) != JPEG_HEADER_OK)
+    return (0);
+  /*
+   * Check image parameters and set decompression parameters.
+   */
+  segment_width = td->td_imagewidth;
+  segment_height = td->td_imagelength - tif->tif_row;
+  if (isTiled(tif)) {
+                segment_width = td->td_tilewidth;
+                segment_height = td->td_tilelength;
+    sp->bytesperline = TIFFTileRowSize(tif);
+  } else {
+    if (segment_height > td->td_rowsperstrip)
+      segment_height = td->td_rowsperstrip;
+    sp->bytesperline = TIFFScanlineSize(tif);
+  }
+  if (td->td_planarconfig == PLANARCONFIG_SEPARATE && s > 0) {
+    /*
+     * For PC 2, scale down the expected strip/tile size
+     * to match a downsampled component
+     */
+    segment_width = TIFFhowmany(segment_width, sp->h_sampling);
+    segment_height = TIFFhowmany(segment_height, sp->v_sampling);
+  }
+  if (sp->cinfo.d.image_width != segment_width ||
+      sp->cinfo.d.image_height != segment_height) {
+    TIFFWarning(module, 
+                 "Improper JPEG strip/tile size, expected %dx%d, got %dx%d",
+                          segment_width, 
+                          segment_height,
+                          sp->cinfo.d.image_width, 
+                          sp->cinfo.d.image_height);
+  }
+  if (sp->cinfo.d.num_components !=
+      (td->td_planarconfig == PLANARCONFIG_CONTIG ?
+       td->td_samplesperpixel : 1)) {
+    TIFFError(module, "Improper JPEG component count");
+    return (0);
+  }
+  if (sp->cinfo.d.data_precision != td->td_bitspersample) {
+    TIFFError(module, "Improper JPEG data precision");
+    return (0);
+  }
+  if (td->td_planarconfig == PLANARCONFIG_CONTIG) {
+    /* Component 0 should have expected sampling factors */
+    if (sp->cinfo.d.comp_info[0].h_samp_factor != sp->h_sampling ||
+        sp->cinfo.d.comp_info[0].v_samp_factor != sp->v_sampling) {
+          TIFFWarning(module, 
+                                    "Improper JPEG sampling factors %d,%d\n"
+                                    "Apparently should be %d,%d.",
+                                    sp->cinfo.d.comp_info[0].h_samp_factor,
+                                    sp->cinfo.d.comp_info[0].v_samp_factor,
+                                    sp->h_sampling, sp->v_sampling);
+
+          /*
+           * XXX: Files written by the Intergraph software
+           * has different sampling factors stored in the
+           * TIFF tags and in the JPEG structures. We will
+           * try to deduce Intergraph files by the presense
+           * of the tag 33918.
+           */
+          if (!_TIFFFindFieldInfo(tif, 33918, TIFF_ANY)) {
+            TIFFWarning(module, 
+          "Decompressor will try reading with "
+          "sampling %d,%d.",
+          sp->cinfo.d.comp_info[0].h_samp_factor,
+          sp->cinfo.d.comp_info[0].v_samp_factor);
+
+            sp->h_sampling = (uint16)
+          sp->cinfo.d.comp_info[0].h_samp_factor;
+            sp->v_sampling = (uint16)
+          sp->cinfo.d.comp_info[0].v_samp_factor;
+          }
+    }
+    /* Rest should have sampling factors 1,1 */
+    for (ci = 1; ci < sp->cinfo.d.num_components; ci++) {
+      if (sp->cinfo.d.comp_info[ci].h_samp_factor != 1 ||
+          sp->cinfo.d.comp_info[ci].v_samp_factor != 1) {
+        TIFFError(module, "Improper JPEG sampling factors");
+        return (0);
+      }
+    }
+  } else {
+    /* PC 2's single component should have sampling factors 1,1 */
+    if (sp->cinfo.d.comp_info[0].h_samp_factor != 1 ||
+        sp->cinfo.d.comp_info[0].v_samp_factor != 1) {
+      TIFFError(module, "Improper JPEG sampling factors");
+      return (0);
+    }
+  }
+  downsampled_output = FALSE;
+  if (td->td_planarconfig == PLANARCONFIG_CONTIG &&
+      sp->photometric == PHOTOMETRIC_YCBCR &&
+      sp->jpegcolormode == JPEGCOLORMODE_RGB) {
+  /* Convert YCbCr to RGB */
+    sp->cinfo.d.jpeg_color_space = JCS_YCbCr;
+    sp->cinfo.d.out_color_space = JCS_RGB;
+  } else {
+      /* Suppress colorspace handling */
+    sp->cinfo.d.jpeg_color_space = JCS_UNKNOWN;
+    sp->cinfo.d.out_color_space = JCS_UNKNOWN;
+    if (td->td_planarconfig == PLANARCONFIG_CONTIG &&
+        (sp->h_sampling != 1 || sp->v_sampling != 1))
+      downsampled_output = TRUE;
+    /* XXX what about up-sampling? */
+  }
+  if (downsampled_output) {
+    /* Need to use raw-data interface to libjpeg */
+    sp->cinfo.d.raw_data_out = TRUE;
+    tif->tif_decoderow = JPEGDecodeRaw;
+    tif->tif_decodestrip = JPEGDecodeRaw;
+    tif->tif_decodetile = JPEGDecodeRaw;
+  } else {
+    /* Use normal interface to libjpeg */
+    sp->cinfo.d.raw_data_out = FALSE;
+    tif->tif_decoderow = JPEGDecode;
+    tif->tif_decodestrip = JPEGDecode;
+    tif->tif_decodetile = JPEGDecode;
+  }
+  /* Start JPEG decompressor */
+  if (!TIFFjpeg_start_decompress(sp))
+    return (0);
+  /* Allocate downsampled-data buffers if needed */
+  if (downsampled_output) {
+    if (!alloc_downsampled_buffers(tif, sp->cinfo.d.comp_info,
+                 sp->cinfo.d.num_components))
+      return (0);
+    sp->scancount = DCTSIZE;  /* mark buffer empty */
+  }
+  return (1);
+}
+
+/*
+ * Decode a chunk of pixels.
+ * "Standard" case: returned data is not downsampled.
+ */
+/*ARGSUSED*/ static int
+JPEGDecode(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s)
+{
+    JPEGState *sp = JState(tif);
+    tsize_t nrows;
+    (void)s;
+
+    nrows = cc / sp->bytesperline;
+    if (cc % sp->bytesperline)
+        TIFFWarning(tif->tif_name, "fractional scanline not read");
+
+    if( nrows > (int) sp->cinfo.d.image_height )
+        nrows = sp->cinfo.d.image_height;
+
+    /* data is expected to be read in multiples of a scanline */
+    if (nrows)
+    {
+        do {
+            JSAMPROW bufptr = (JSAMPROW)buf;
+
+            if (TIFFjpeg_read_scanlines(sp, &bufptr, 1) != 1)
+                return (0);
+            ++tif->tif_row;
+            buf += sp->bytesperline;
+            cc -= sp->bytesperline;
+        } while (--nrows > 0);
+    }
+    /* Close down the decompressor if we've finished the strip or tile. */
+    return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height
+        || TIFFjpeg_finish_decompress(sp);
+}
+
+/*
+ * Decode a chunk of pixels.
+ * Returned data is downsampled per sampling factors.
+ */
+/*ARGSUSED*/ static int
+JPEGDecodeRaw(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s)
+{
+  JPEGState *sp = JState(tif);
+  tsize_t nrows;
+  (void)s;
+
+  /* data is expected to be read in multiples of a scanline */
+  if ( (nrows = sp->cinfo.d.image_height) ) {
+    /* Cb,Cr both have sampling factors 1, so this is correct */
+    JDIMENSION clumps_per_line = sp->cinfo.d.comp_info[1].downsampled_width;
+    int samples_per_clump = sp->samplesperclump;
+  
+    do {
+      jpeg_component_info *compptr;
+      int ci, clumpoffset;
+
+      /* Reload downsampled-data buffer if needed */
+      if (sp->scancount >= DCTSIZE) {
+        int n = sp->cinfo.d.max_v_samp_factor * DCTSIZE;
+
+        if (TIFFjpeg_read_raw_data(sp, sp->ds_buffer, n)
+          != n)
+          return (0);
+        sp->scancount = 0;
+      }
+      /*
+       * Fastest way to unseparate data is to make one pass
+       * over the scanline for each row of each component.
+       */
+      clumpoffset = 0;  /* first sample in clump */
+      for (ci = 0, compptr = sp->cinfo.d.comp_info;
+           ci < sp->cinfo.d.num_components;
+           ci++, compptr++) {
+          int hsamp = compptr->h_samp_factor;
+          int vsamp = compptr->v_samp_factor;
+          int ypos;
+
+          for (ypos = 0; ypos < vsamp; ypos++) {
+        JSAMPLE *inptr = sp->ds_buffer[ci][sp->scancount*vsamp + ypos];
+        JSAMPLE *outptr = (JSAMPLE*)buf + clumpoffset;
+        JDIMENSION nclump;
+
+        if (hsamp == 1) {
+            /* fast path for at least Cb and Cr */
+            for (nclump = clumps_per_line; nclump-- > 0; ) {
+          outptr[0] = *inptr++;
+          outptr += samples_per_clump;
+            }
+        } else {
+          int xpos;
+
+            /* general case */
+            for (nclump = clumps_per_line; nclump-- > 0; ) {
+          for (xpos = 0; xpos < hsamp; xpos++)
+              outptr[xpos] = *inptr++;
+          outptr += samples_per_clump;
+            }
+        }
+        clumpoffset += hsamp;
+          }
+      }
+      ++sp->scancount;
+      ++tif->tif_row;
+      buf += sp->bytesperline;
+      cc -= sp->bytesperline;
+    } while (--nrows > 0);
+  }
+
+        /* Close down the decompressor if done. */
+        return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height
+      || TIFFjpeg_finish_decompress(sp);
+}
+
+
+/*
+ * JPEG Encoding.
+ */
+
+static void
+unsuppress_quant_table (JPEGState* sp, int tblno)
+{
+  JQUANT_TBL* qtbl;
+
+  if ((qtbl = sp->cinfo.c.quant_tbl_ptrs[tblno]) != NULL)
+    qtbl->sent_table = FALSE;
+}
+
+static void
+unsuppress_huff_table (JPEGState* sp, int tblno)
+{
+  JHUFF_TBL* htbl;
+
+  if ((htbl = sp->cinfo.c.dc_huff_tbl_ptrs[tblno]) != NULL)
+    htbl->sent_table = FALSE;
+  if ((htbl = sp->cinfo.c.ac_huff_tbl_ptrs[tblno]) != NULL)
+    htbl->sent_table = FALSE;
+}
+
+static int
+prepare_JPEGTables(TIFF* tif)
+{
+  JPEGState* sp = JState(tif);
+
+        JPEGInitializeLibJPEG( tif );
+
+  /* Initialize quant tables for current quality setting */
+  if (!TIFFjpeg_set_quality(sp, sp->jpegquality, FALSE))
+    return (0);
+  /* Mark only the tables we want for output */
+  /* NB: chrominance tables are currently used only with YCbCr */
+  if (!TIFFjpeg_suppress_tables(sp, TRUE))
+    return (0);
+  if (sp->jpegtablesmode & JPEGTABLESMODE_QUANT) {
+    unsuppress_quant_table(sp, 0);
+    if (sp->photometric == PHOTOMETRIC_YCBCR)
+      unsuppress_quant_table(sp, 1);
+  }
+  if (sp->jpegtablesmode & JPEGTABLESMODE_HUFF) {
+    unsuppress_huff_table(sp, 0);
+    if (sp->photometric == PHOTOMETRIC_YCBCR)
+      unsuppress_huff_table(sp, 1);
+  }
+  /* Direct libjpeg output into jpegtables */
+  if (!TIFFjpeg_tables_dest(sp, tif))
+    return (0);
+  /* Emit tables-only datastream */
+  if (!TIFFjpeg_write_tables(sp))
+    return (0);
+
+  return (1);
+}
+
+static int
+JPEGSetupEncode(TIFF* tif)
+{
+  JPEGState* sp = JState(tif);
+  TIFFDirectory *td = &tif->tif_dir;
+  static const char module[] = "JPEGSetupEncode";
+
+        JPEGInitializeLibJPEG( tif );
+
+  assert(sp != NULL);
+  assert(!sp->cinfo.comm.is_decompressor);
+
+  /*
+   * Initialize all JPEG parameters to default values.
+   * Note that jpeg_set_defaults needs legal values for
+   * in_color_space and input_components.
+   */
+  sp->cinfo.c.in_color_space = JCS_UNKNOWN;
+  sp->cinfo.c.input_components = 1;
+  if (!TIFFjpeg_set_defaults(sp))
+    return (0);
+  /* Set per-file parameters */
+  sp->photometric = td->td_photometric;
+  switch (sp->photometric) {
+  case PHOTOMETRIC_YCBCR:
+    sp->h_sampling = td->td_ycbcrsubsampling[0];
+    sp->v_sampling = td->td_ycbcrsubsampling[1];
+    /*
+     * A ReferenceBlackWhite field *must* be present since the
+     * default value is inappropriate for YCbCr.  Fill in the
+     * proper value if application didn't set it.
+     */
+    if (!TIFFFieldSet(tif, FIELD_REFBLACKWHITE)) {
+      float refbw[6];
+      long top = 1L << td->td_bitspersample;
+      refbw[0] = 0;
+      refbw[1] = (float)(top-1L);
+      refbw[2] = (float)(top>>1);
+      refbw[3] = refbw[1];
+      refbw[4] = refbw[2];
+      refbw[5] = refbw[1];
+      TIFFSetField(tif, TIFFTAG_REFERENCEBLACKWHITE, refbw);
+    }
+    break;
+  case PHOTOMETRIC_PALETTE:    /* disallowed by Tech Note */
+  case PHOTOMETRIC_MASK:
+    TIFFError(module,
+        "PhotometricInterpretation %d not allowed for JPEG",
+        (int) sp->photometric);
+    return (0);
+  default:
+    /* TIFF 6.0 forbids subsampling of all other color spaces */
+    sp->h_sampling = 1;
+    sp->v_sampling = 1;
+    break;
+  }
+  
+  /* Verify miscellaneous parameters */
+
+  /*
+   * This would need work if libtiff ever supports different
+   * depths for different components, or if libjpeg ever supports
+   * run-time selection of depth.  Neither is imminent.
+   */
+  if (td->td_bitspersample != BITS_IN_JSAMPLE) {
+    TIFFError(module, "BitsPerSample %d not allowed for JPEG",
+        (int) td->td_bitspersample);
+    return (0);
+  }
+  sp->cinfo.c.data_precision = td->td_bitspersample;
+  if (isTiled(tif)) {
+    if ((td->td_tilelength % (sp->v_sampling * DCTSIZE)) != 0) {
+      TIFFError(module,
+          "JPEG tile height must be multiple of %d",
+          sp->v_sampling * DCTSIZE);
+      return (0);
+    }
+    if ((td->td_tilewidth % (sp->h_sampling * DCTSIZE)) != 0) {
+      TIFFError(module,
+          "JPEG tile width must be multiple of %d",
+          sp->h_sampling * DCTSIZE);
+      return (0);
+    }
+  } else {
+    if (td->td_rowsperstrip < td->td_imagelength &&
+        (td->td_rowsperstrip % (sp->v_sampling * DCTSIZE)) != 0) {
+      TIFFError(module,
+          "RowsPerStrip must be multiple of %d for JPEG",
+          sp->v_sampling * DCTSIZE);
+      return (0);
+    }
+  }
+
+  /* Create a JPEGTables field if appropriate */
+  if (sp->jpegtablesmode & (JPEGTABLESMODE_QUANT|JPEGTABLESMODE_HUFF)) {
+    if (!prepare_JPEGTables(tif))
+      return (0);
+    /* Mark the field present */
+    /* Can't use TIFFSetField since BEENWRITING is already set! */
+    TIFFSetFieldBit(tif, FIELD_JPEGTABLES);
+    tif->tif_flags |= TIFF_DIRTYDIRECT;
+  } else {
+    /* We do not support application-supplied JPEGTables, */
+    /* so mark the field not present */
+    TIFFClrFieldBit(tif, FIELD_JPEGTABLES);
+  }
+
+  /* Direct libjpeg output to libtiff's output buffer */
+  TIFFjpeg_data_dest(sp, tif);
+
+  return (1);
+}
+
+/*
+ * Set encoding state at the start of a strip or tile.
+ */
+static int
+JPEGPreEncode(TIFF* tif, tsample_t s)
+{
+  JPEGState *sp = JState(tif);
+  TIFFDirectory *td = &tif->tif_dir;
+  static const char module[] = "JPEGPreEncode";
+  uint32 segment_width, segment_height;
+  int downsampled_input;
+
+  assert(sp != NULL);
+  assert(!sp->cinfo.comm.is_decompressor);
+  /*
+   * Set encoding parameters for this strip/tile.
+   */
+  if (isTiled(tif)) {
+    segment_width = td->td_tilewidth;
+    segment_height = td->td_tilelength;
+    sp->bytesperline = TIFFTileRowSize(tif);
+  } else {
+    segment_width = td->td_imagewidth;
+    segment_height = td->td_imagelength - tif->tif_row;
+    if (segment_height > td->td_rowsperstrip)
+      segment_height = td->td_rowsperstrip;
+    sp->bytesperline = TIFFScanlineSize(tif);
+  }
+  if (td->td_planarconfig == PLANARCONFIG_SEPARATE && s > 0) {
+    /* for PC 2, scale down the strip/tile size
+     * to match a downsampled component
+     */
+    segment_width = TIFFhowmany(segment_width, sp->h_sampling);
+    segment_height = TIFFhowmany(segment_height, sp->v_sampling);
+  }
+  if (segment_width > 65535 || segment_height > 65535) {
+    TIFFError(module, "Strip/tile too large for JPEG");
+    return (0);
+  }
+  sp->cinfo.c.image_width = segment_width;
+  sp->cinfo.c.image_height = segment_height;
+  downsampled_input = FALSE;
+  if (td->td_planarconfig == PLANARCONFIG_CONTIG) {
+    sp->cinfo.c.input_components = td->td_samplesperpixel;
+    if (sp->photometric == PHOTOMETRIC_YCBCR) {
+      if (sp->jpegcolormode == JPEGCOLORMODE_RGB) {
+        sp->cinfo.c.in_color_space = JCS_RGB;
+      } else {
+        sp->cinfo.c.in_color_space = JCS_YCbCr;
+        if (sp->h_sampling != 1 || sp->v_sampling != 1)
+          downsampled_input = TRUE;
+      }
+      if (!TIFFjpeg_set_colorspace(sp, JCS_YCbCr))
+        return (0);
+      /*
+       * Set Y sampling factors;
+       * we assume jpeg_set_colorspace() set the rest to 1
+       */
+      sp->cinfo.c.comp_info[0].h_samp_factor = sp->h_sampling;
+      sp->cinfo.c.comp_info[0].v_samp_factor = sp->v_sampling;
+    } else {
+      sp->cinfo.c.in_color_space = JCS_UNKNOWN;
+      if (!TIFFjpeg_set_colorspace(sp, JCS_UNKNOWN))
+        return (0);
+      /* jpeg_set_colorspace set all sampling factors to 1 */
+    }
+  } else {
+    sp->cinfo.c.input_components = 1;
+    sp->cinfo.c.in_color_space = JCS_UNKNOWN;
+    if (!TIFFjpeg_set_colorspace(sp, JCS_UNKNOWN))
+      return (0);
+    sp->cinfo.c.comp_info[0].component_id = s;
+    /* jpeg_set_colorspace() set sampling factors to 1 */
+    if (sp->photometric == PHOTOMETRIC_YCBCR && s > 0) {
+      sp->cinfo.c.comp_info[0].quant_tbl_no = 1;
+      sp->cinfo.c.comp_info[0].dc_tbl_no = 1;
+      sp->cinfo.c.comp_info[0].ac_tbl_no = 1;
+    }
+  }
+  /* ensure libjpeg won't write any extraneous markers */
+  sp->cinfo.c.write_JFIF_header = FALSE;
+  sp->cinfo.c.write_Adobe_marker = FALSE;
+  /* set up table handling correctly */
+  if (! (sp->jpegtablesmode & JPEGTABLESMODE_QUANT)) {
+    if (!TIFFjpeg_set_quality(sp, sp->jpegquality, FALSE))
+      return (0);
+    unsuppress_quant_table(sp, 0);
+    unsuppress_quant_table(sp, 1);
+  }
+  if (sp->jpegtablesmode & JPEGTABLESMODE_HUFF)
+    sp->cinfo.c.optimize_coding = FALSE;
+  else
+    sp->cinfo.c.optimize_coding = TRUE;
+  if (downsampled_input) {
+    /* Need to use raw-data interface to libjpeg */
+    sp->cinfo.c.raw_data_in = TRUE;
+    tif->tif_encoderow = JPEGEncodeRaw;
+    tif->tif_encodestrip = JPEGEncodeRaw;
+    tif->tif_encodetile = JPEGEncodeRaw;
+  } else {
+    /* Use normal interface to libjpeg */
+    sp->cinfo.c.raw_data_in = FALSE;
+    tif->tif_encoderow = JPEGEncode;
+    tif->tif_encodestrip = JPEGEncode;
+    tif->tif_encodetile = JPEGEncode;
+  }
+  /* Start JPEG compressor */
+  if (!TIFFjpeg_start_compress(sp, FALSE))
+    return (0);
+  /* Allocate downsampled-data buffers if needed */
+  if (downsampled_input) {
+    if (!alloc_downsampled_buffers(tif, sp->cinfo.c.comp_info,
+                 sp->cinfo.c.num_components))
+      return (0);
+  }
+  sp->scancount = 0;
+
+  return (1);
+}
+
+/*
+ * Encode a chunk of pixels.
+ * "Standard" case: incoming data is not downsampled.
+ */
+static int
+JPEGEncode(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s)
+{
+  JPEGState *sp = JState(tif);
+  tsize_t nrows;
+  JSAMPROW bufptr[1];
+
+  (void) s;
+  assert(sp != NULL);
+  /* data is expected to be supplied in multiples of a scanline */
+  nrows = cc / sp->bytesperline;
+  if (cc % sp->bytesperline)
+    TIFFWarning(tif->tif_name, "fractional scanline discarded");
+
+  while (nrows-- > 0) {
+    bufptr[0] = (JSAMPROW) buf;
+    if (TIFFjpeg_write_scanlines(sp, bufptr, 1) != 1)
+      return (0);
+    if (nrows > 0)
+      tif->tif_row++;
+    buf += sp->bytesperline;
+  }
+  return (1);
+}
+
+/*
+ * Encode a chunk of pixels.
+ * Incoming data is expected to be downsampled per sampling factors.
+ */
+static int
+JPEGEncodeRaw(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s)
+{
+  JPEGState *sp = JState(tif);
+  JSAMPLE* inptr;
+  JSAMPLE* outptr;
+  tsize_t nrows;
+  JDIMENSION clumps_per_line, nclump;
+  int clumpoffset, ci, xpos, ypos;
+  jpeg_component_info* compptr;
+  int samples_per_clump = sp->samplesperclump;
+
+  (void) s;
+  assert(sp != NULL);
+  /* data is expected to be supplied in multiples of a scanline */
+  nrows = cc / sp->bytesperline;
+  if (cc % sp->bytesperline)
+    TIFFWarning(tif->tif_name, "fractional scanline discarded");
+
+  /* Cb,Cr both have sampling factors 1, so this is correct */
+  clumps_per_line = sp->cinfo.c.comp_info[1].downsampled_width;
+
+  while (nrows-- > 0) {
+    /*
+     * Fastest way to separate the data is to make one pass
+     * over the scanline for each row of each component.
+     */
+    clumpoffset = 0;    /* first sample in clump */
+    for (ci = 0, compptr = sp->cinfo.c.comp_info;
+         ci < sp->cinfo.c.num_components;
+         ci++, compptr++) {
+        int hsamp = compptr->h_samp_factor;
+        int vsamp = compptr->v_samp_factor;
+        int padding = (int) (compptr->width_in_blocks * DCTSIZE -
+           clumps_per_line * hsamp);
+        for (ypos = 0; ypos < vsamp; ypos++) {
+      inptr = ((JSAMPLE*) buf) + clumpoffset;
+      outptr = sp->ds_buffer[ci][sp->scancount*vsamp + ypos];
+      if (hsamp == 1) {
+          /* fast path for at least Cb and Cr */
+          for (nclump = clumps_per_line; nclump-- > 0; ) {
+        *outptr++ = inptr[0];
+        inptr += samples_per_clump;
+          }
+      } else {
+          /* general case */
+          for (nclump = clumps_per_line; nclump-- > 0; ) {
+        for (xpos = 0; xpos < hsamp; xpos++)
+            *outptr++ = inptr[xpos];
+        inptr += samples_per_clump;
+          }
+      }
+      /* pad each scanline as needed */
+      for (xpos = 0; xpos < padding; xpos++) {
+          *outptr = outptr[-1];
+          outptr++;
+      }
+      clumpoffset += hsamp;
+        }
+    }
+    sp->scancount++;
+    if (sp->scancount >= DCTSIZE) {
+      int n = sp->cinfo.c.max_v_samp_factor * DCTSIZE;
+      if (TIFFjpeg_write_raw_data(sp, sp->ds_buffer, n) != n)
+        return (0);
+      sp->scancount = 0;
+    }
+    if (nrows > 0)
+      tif->tif_row++;
+    buf += sp->bytesperline;
+  }
+  return (1);
+}
+
+/*
+ * Finish up at the end of a strip or tile.
+ */
+static int
+JPEGPostEncode(TIFF* tif)
+{
+  JPEGState *sp = JState(tif);
+
+  if (sp->scancount > 0) {
+    /*
+     * Need to emit a partial bufferload of downsampled data.
+     * Pad the data vertically.
+     */
+    int ci, ypos, n;
+    jpeg_component_info* compptr;
+
+    for (ci = 0, compptr = sp->cinfo.c.comp_info;
+         ci < sp->cinfo.c.num_components;
+         ci++, compptr++) {
+      int vsamp = compptr->v_samp_factor;
+      tsize_t row_width = compptr->width_in_blocks * DCTSIZE
+        * sizeof(JSAMPLE);
+      for (ypos = sp->scancount * vsamp;
+           ypos < DCTSIZE * vsamp; ypos++) {
+        _TIFFmemcpy((tdata_t)sp->ds_buffer[ci][ypos],
+              (tdata_t)sp->ds_buffer[ci][ypos-1],
+              row_width);
+
+      }
+    }
+    n = sp->cinfo.c.max_v_samp_factor * DCTSIZE;
+    if (TIFFjpeg_write_raw_data(sp, sp->ds_buffer, n) != n)
+      return (0);
+  }
+
+  return (TIFFjpeg_finish_compress(JState(tif)));
+}
+
+static void
+JPEGCleanup(TIFF* tif)
+{
+  if (tif->tif_data) {
+    JPEGState *sp = JState(tif);
+                if( sp->cinfo_initialized )
+                    TIFFjpeg_destroy(sp);  /* release libjpeg resources */
+    if (sp->jpegtables)    /* tag value */
+      _TIFFfree(sp->jpegtables);
+    _TIFFfree(tif->tif_data);  /* release local state */
+    tif->tif_data = NULL;
+  }
+}
+
+static int
+JPEGVSetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+  JPEGState* sp = JState(tif);
+  TIFFDirectory* td = &tif->tif_dir;
+  uint32 v32;
+
+  switch (tag) {
+  case TIFFTAG_JPEGTABLES:
+    v32 = va_arg(ap, uint32);
+    if (v32 == 0) {
+      /* XXX */
+      return (0);
+    }
+    _TIFFsetByteArray(&sp->jpegtables, va_arg(ap, void*),
+        (long) v32);
+    sp->jpegtables_length = v32;
+    TIFFSetFieldBit(tif, FIELD_JPEGTABLES);
+    break;
+  case TIFFTAG_JPEGQUALITY:
+    sp->jpegquality = va_arg(ap, int);
+    return (1);      /* pseudo tag */
+  case TIFFTAG_JPEGCOLORMODE:
+    sp->jpegcolormode = va_arg(ap, int);
+    /*
+     * Mark whether returned data is up-sampled or not
+     * so TIFFStripSize and TIFFTileSize return values
+     * that reflect the true amount of data.
+     */
+    tif->tif_flags &= ~TIFF_UPSAMPLED;
+    if (td->td_planarconfig == PLANARCONFIG_CONTIG) {
+        if (td->td_photometric == PHOTOMETRIC_YCBCR &&
+          sp->jpegcolormode == JPEGCOLORMODE_RGB) {
+      tif->tif_flags |= TIFF_UPSAMPLED;
+        } else {
+      if (td->td_ycbcrsubsampling[0] != 1 ||
+          td->td_ycbcrsubsampling[1] != 1)
+          (void)tif; /* XXX what about up-sampling? */
+        }
+    }
+    /*
+     * Must recalculate cached tile size
+     * in case sampling state changed.
+     */
+    tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tsize_t) -1;
+    return (1);      /* pseudo tag */
+  case TIFFTAG_JPEGTABLESMODE:
+    sp->jpegtablesmode = va_arg(ap, int);
+    return (1);      /* pseudo tag */
+  case TIFFTAG_YCBCRSUBSAMPLING:
+                /* mark the fact that we have a real ycbcrsubsampling! */
+    sp->ycbcrsampling_fetched = 1;
+    return (*sp->vsetparent)(tif, tag, ap);
+  case TIFFTAG_FAXRECVPARAMS:
+    sp->recvparams = va_arg(ap, uint32);
+    break;
+  case TIFFTAG_FAXSUBADDRESS:
+    _TIFFsetString(&sp->subaddress, va_arg(ap, char*));
+    break;
+  case TIFFTAG_FAXRECVTIME:
+    sp->recvtime = va_arg(ap, uint32);
+    break;
+  case TIFFTAG_FAXDCS:
+    _TIFFsetString(&sp->faxdcs, va_arg(ap, char*));
+    break;
+  default:
+    return (*sp->vsetparent)(tif, tag, ap);
+  }
+  TIFFSetFieldBit(tif, _TIFFFieldWithTag(tif, tag)->field_bit);
+  tif->tif_flags |= TIFF_DIRTYDIRECT;
+  return (1);
+}
+
+/*
+ * Some JPEG-in-TIFF produces do not emit the YCBCRSUBSAMPLING values in
+ * the TIFF tags, but still use non-default (2,2) values within the jpeg
+ * data stream itself.  In order for TIFF applications to work properly
+ * - for instance to get the strip buffer size right - it is imperative
+ * that the subsampling be available before we start reading the image
+ * data normally.  This function will attempt to load the first strip in
+ * order to get the sampling values from the jpeg data stream.  Various
+ * hacks are various places are done to ensure this function gets called
+ * before the td_ycbcrsubsampling values are used from the directory structure,
+ * including calling TIFFGetField() for the YCBCRSUBSAMPLING field from 
+ * TIFFStripSize(), and the printing code in tif_print.c. 
+ *
+ * Note that JPEGPreDeocode() will produce a fairly loud warning when the
+ * discovered sampling does not match the default sampling (2,2) or whatever
+ * was actually in the tiff tags. 
+ *
+ * Problems:
+ *  o This code will cause one whole strip/tile of compressed data to be
+ *    loaded just to get the tags right, even if the imagery is never read.
+ *    It would be more efficient to just load a bit of the header, and
+ *    initialize things from that. 
+ *
+ * See the bug in bugzilla for details:
+ *
+ * http://bugzilla.remotesensing.org/show_bug.cgi?id=168
+ *
+ * Frank Warmerdam, July 2002
+ */
+
+static void 
+JPEGFixupTestSubsampling( TIFF * tif )
+{
+#ifdef CHECK_JPEG_YCBCR_SUBSAMPLING
+    JPEGState *sp = JState(tif);
+    TIFFDirectory *td = &tif->tif_dir;
+
+    JPEGInitializeLibJPEG( tif );
+
+    /*
+     * Some JPEG-in-TIFF files don't provide the ycbcrsampling tags, 
+     * and use a sampling schema other than the default 2,2.  To handle
+     * this we actually have to scan the header of a strip or tile of
+     * jpeg data to get the sampling.  
+     */
+    if( !sp->cinfo.comm.is_decompressor 
+        || sp->ycbcrsampling_fetched  
+        || td->td_photometric != PHOTOMETRIC_YCBCR )
+        return;
+
+    sp->ycbcrsampling_fetched = 1;
+    if( TIFFIsTiled( tif ) )
+    {
+        if( !TIFFFillTile( tif, 0 ) )
+            return;
+    }
+    else
+    {
+        if( !TIFFFillStrip( tif, 0 ) )
+            return;
+    }
+
+    TIFFSetField( tif, TIFFTAG_YCBCRSUBSAMPLING, 
+                  (uint16) sp->h_sampling, (uint16) sp->v_sampling );
+#else
+  (void)tif;
+#endif /* CHECK_JPEG_YCBCR_SUBSAMPLING */
+}
+
+static int
+JPEGVGetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+  JPEGState* sp = JState(tif);
+
+  switch (tag) {
+  case TIFFTAG_JPEGTABLES:
+    *va_arg(ap, uint32*) = sp->jpegtables_length;
+    *va_arg(ap, void**) = sp->jpegtables;
+    break;
+  case TIFFTAG_JPEGQUALITY:
+    *va_arg(ap, int*) = sp->jpegquality;
+    break;
+  case TIFFTAG_JPEGCOLORMODE:
+    *va_arg(ap, int*) = sp->jpegcolormode;
+    break;
+  case TIFFTAG_JPEGTABLESMODE:
+    *va_arg(ap, int*) = sp->jpegtablesmode;
+    break;
+  case TIFFTAG_YCBCRSUBSAMPLING:
+                JPEGFixupTestSubsampling( tif );
+    return (*sp->vgetparent)(tif, tag, ap);
+    break;
+        case TIFFTAG_FAXRECVPARAMS:
+                *va_arg(ap, uint32*) = sp->recvparams;
+                break;
+        case TIFFTAG_FAXSUBADDRESS:
+                *va_arg(ap, char**) = sp->subaddress;
+                break;
+        case TIFFTAG_FAXRECVTIME:
+                *va_arg(ap, uint32*) = sp->recvtime;
+                break;
+        case TIFFTAG_FAXDCS:
+                *va_arg(ap, char**) = sp->faxdcs;
+                break;
+default:
+    return (*sp->vgetparent)(tif, tag, ap);
+  }
+  return (1);
+}
+
+static void
+JPEGPrintDir(TIFF* tif, FILE* fd, long flags)
+{
+  JPEGState* sp = JState(tif);
+
+  (void) flags;
+  if (TIFFFieldSet(tif,FIELD_JPEGTABLES))
+    fprintf(fd, "  JPEG Tables: (%lu bytes)\n",
+      (unsigned long) sp->jpegtables_length);
+        if (TIFFFieldSet(tif,FIELD_RECVPARAMS))
+                fprintf(fd, "  Fax Receive Parameters: %08lx\n",
+                   (unsigned long) sp->recvparams);
+        if (TIFFFieldSet(tif,FIELD_SUBADDRESS))
+                fprintf(fd, "  Fax SubAddress: %s\n", sp->subaddress);
+        if (TIFFFieldSet(tif,FIELD_RECVTIME))
+                fprintf(fd, "  Fax Receive Time: %lu secs\n",
+                    (unsigned long) sp->recvtime);
+        if (TIFFFieldSet(tif,FIELD_FAXDCS))
+                fprintf(fd, "  Fax DCS: %s\n", sp->faxdcs);
+}
+
+static uint32
+JPEGDefaultStripSize(TIFF* tif, uint32 s)
+{
+  JPEGState* sp = JState(tif);
+  TIFFDirectory *td = &tif->tif_dir;
+
+  s = (*sp->defsparent)(tif, s);
+  if (s < td->td_imagelength)
+    s = TIFFroundup(s, td->td_ycbcrsubsampling[1] * DCTSIZE);
+  return (s);
+}
+
+static void
+JPEGDefaultTileSize(TIFF* tif, uint32* tw, uint32* th)
+{
+  JPEGState* sp = JState(tif);
+  TIFFDirectory *td = &tif->tif_dir;
+
+  (*sp->deftparent)(tif, tw, th);
+  *tw = TIFFroundup(*tw, td->td_ycbcrsubsampling[0] * DCTSIZE);
+  *th = TIFFroundup(*th, td->td_ycbcrsubsampling[1] * DCTSIZE);
+}
+
+/*
+ * The JPEG library initialized used to be done in TIFFInitJPEG(), but
+ * now that we allow a TIFF file to be opened in update mode it is necessary
+ * to have some way of deciding whether compression or decompression is
+ * desired other than looking at tif->tif_mode.  We accomplish this by 
+ * examining {TILE/STRIP}BYTECOUNTS to see if there is a non-zero entry.
+ * If so, we assume decompression is desired. 
+ *
+ * This is tricky, because TIFFInitJPEG() is called while the directory is
+ * being read, and generally speaking the BYTECOUNTS tag won't have been read
+ * at that point.  So we try to defer jpeg library initialization till we
+ * do have that tag ... basically any access that might require the compressor
+ * or decompressor that occurs after the reading of the directory. 
+ *
+ * In an ideal world compressors or decompressors would be setup
+ * at the point where a single tile or strip was accessed (for read or write)
+ * so that stuff like update of missing tiles, or replacement of tiles could
+ * be done. However, we aren't trying to crack that nut just yet ...
+ *
+ * NFW, Feb 3rd, 2003.
+ */
+
+static int JPEGInitializeLibJPEG( TIFF * tif )
+{
+    JPEGState* sp = JState(tif);
+    uint32 *byte_counts = NULL;
+    int     data_is_empty = TRUE;
+
+    if( sp->cinfo_initialized )
+        return 1;
+
+    /*
+     * Do we have tile data already?  Make sure we initialize the
+     * the state in decompressor mode if we have tile data, even if we
+     * are not in read-only file access mode. 
+     */
+    if( TIFFIsTiled( tif ) 
+        && TIFFGetField( tif, TIFFTAG_TILEBYTECOUNTS, &byte_counts ) 
+        && byte_counts != NULL )
+    {
+        data_is_empty = byte_counts[0] == 0;
+    }
+    if( !TIFFIsTiled( tif ) 
+        && TIFFGetField( tif, TIFFTAG_STRIPBYTECOUNTS, &byte_counts) 
+        && byte_counts != NULL )
+    {
+        data_is_empty = byte_counts[0] == 0;
+    }
+
+    /*
+     * Initialize libjpeg.
+     */
+    if (tif->tif_mode == O_RDONLY || !data_is_empty ) {
+        if (!TIFFjpeg_create_decompress(sp))
+            return (0);
+
+    } else {
+        if (!TIFFjpeg_create_compress(sp))
+            return (0);
+    }
+
+    sp->cinfo_initialized = TRUE;
+
+    return 1;
+}
+
+int
+TIFFInitJPEG(TIFF* tif, int scheme)
+{
+  JPEGState* sp;
+
+  assert(scheme == COMPRESSION_JPEG);
+
+  /*
+   * Allocate state block so tag methods have storage to record values.
+   */
+  tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (JPEGState));
+
+  if (tif->tif_data == NULL) {
+    TIFFError("TIFFInitJPEG", "No space for JPEG state block");
+    return (0);
+  }
+        _TIFFmemset( tif->tif_data, 0, sizeof(JPEGState));
+
+  sp = JState(tif);
+  sp->tif = tif;        /* back link */
+
+  /*
+   * Merge codec-specific tag information and
+   * override parent get/set field methods.
+   */
+  _TIFFMergeFieldInfo(tif, jpegFieldInfo, N(jpegFieldInfo));
+  sp->vgetparent = tif->tif_tagmethods.vgetfield;
+  tif->tif_tagmethods.vgetfield = JPEGVGetField;  /* hook for codec tags */
+  sp->vsetparent = tif->tif_tagmethods.vsetfield;
+  tif->tif_tagmethods.vsetfield = JPEGVSetField;  /* hook for codec tags */
+  tif->tif_tagmethods.printdir = JPEGPrintDir;  /* hook for codec tags */
+
+  /* Default values for codec-specific fields */
+  sp->jpegtables = NULL;
+  sp->jpegtables_length = 0;
+  sp->jpegquality = 75;      /* Default IJG quality */
+  sp->jpegcolormode = JPEGCOLORMODE_RAW;
+  sp->jpegtablesmode = JPEGTABLESMODE_QUANT | JPEGTABLESMODE_HUFF;
+
+        sp->recvparams = 0;
+        sp->subaddress = NULL;
+        sp->faxdcs = NULL;
+
+        sp->ycbcrsampling_fetched = 0;
+
+  /*
+   * Install codec methods.
+   */
+  tif->tif_setupdecode = JPEGSetupDecode;
+  tif->tif_predecode = JPEGPreDecode;
+  tif->tif_decoderow = JPEGDecode;
+  tif->tif_decodestrip = JPEGDecode;
+  tif->tif_decodetile = JPEGDecode;
+  tif->tif_setupencode = JPEGSetupEncode;
+  tif->tif_preencode = JPEGPreEncode;
+  tif->tif_postencode = JPEGPostEncode;
+  tif->tif_encoderow = JPEGEncode;
+  tif->tif_encodestrip = JPEGEncode;
+  tif->tif_encodetile = JPEGEncode;
+  tif->tif_cleanup = JPEGCleanup;
+  sp->defsparent = tif->tif_defstripsize;
+  tif->tif_defstripsize = JPEGDefaultStripSize;
+  sp->deftparent = tif->tif_deftilesize;
+  tif->tif_deftilesize = JPEGDefaultTileSize;
+  tif->tif_flags |= TIFF_NOBITREV;  /* no bit reversal, please */
+
+        sp->cinfo_initialized = FALSE;
+
+        /*
+         * Mark the TIFFTAG_YCBCRSAMPLES as present even if it is not
+         * see: JPEGFixupTestSubsampling().
+         */
+        TIFFSetFieldBit( tif, FIELD_YCBCRSUBSAMPLING );
+
+  return (1);
+}
+#endif /* JPEG_SUPPORT */
+
diff --git a/Utilities/ITK/Utilities/tiff/tif_luv.c b/Utilities/ITK/Utilities/tiff/tif_luv.c
new file mode 100644
index 0000000000..2184436e0f
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_luv.c
@@ -0,0 +1,1601 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1997 Greg Ward Larson
+ * Copyright (c) 1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler, Greg Larson and Silicon Graphics may not be used in any
+ * advertising or publicity relating to the software without the specific,
+ * prior written permission of Sam Leffler, Greg Larson and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER, GREG LARSON OR SILICON GRAPHICS BE LIABLE
+ * FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+#include "tiffiop.h"
+#ifdef LOGLUV_SUPPORT
+
+/*
+ * TIFF Library.
+ * LogLuv compression support for high dynamic range images.
+ *
+ * Contributed by Greg Larson.
+ *
+ * LogLuv image support uses the TIFF library to store 16 or 10-bit
+ * log luminance values with 8 bits each of u and v or a 14-bit index.
+ *
+ * The codec can take as input and produce as output 32-bit IEEE float values 
+ * as well as 16-bit integer values.  A 16-bit luminance is interpreted
+ * as a sign bit followed by a 15-bit integer that is converted
+ * to and from a linear magnitude using the transformation:
+ *
+ *  L = 2^( (Le+.5)/256 - 64 )    # real from 15-bit
+ *
+ *  Le = floor( 256*(log2(L) + 64) )  # 15-bit from real
+ *
+ * The actual conversion to world luminance units in candelas per sq. meter
+ * requires an additional multiplier, which is stored in the TIFFTAG_STONITS.
+ * This value is usually set such that a reasonable exposure comes from
+ * clamping decoded luminances above 1 to 1 in the displayed image.
+ *
+ * The 16-bit values for u and v may be converted to real values by dividing
+ * each by 32768.  (This allows for negative values, which aren't useful as
+ * far as we know, but are left in case of future improvements in human
+ * color vision.)
+ *
+ * Conversion from (u,v), which is actually the CIE (u',v') system for
+ * you color scientists, is accomplished by the following transformation:
+ *
+ *  u = 4*x / (-2*x + 12*y + 3)
+ *  v = 9*y / (-2*x + 12*y + 3)
+ *
+ *  x = 9*u / (6*u - 16*v + 12)
+ *  y = 4*v / (6*u - 16*v + 12)
+ *
+ * This process is greatly simplified by passing 32-bit IEEE floats
+ * for each of three CIE XYZ coordinates.  The codec then takes care
+ * of conversion to and from LogLuv, though the application is still
+ * responsible for interpreting the TIFFTAG_STONITS calibration factor.
+ *
+ * By definition, a CIE XYZ vector of [1 1 1] corresponds to a neutral white
+ * point of (x,y)=(1/3,1/3).  However, most color systems assume some other
+ * white point, such as D65, and an absolute color conversion to XYZ then
+ * to another color space with a different white point may introduce an
+ * unwanted color cast to the image.  It is often desirable, therefore, to
+ * perform a white point conversion that maps the input white to [1 1 1]
+ * in XYZ, then record the original white point using the TIFFTAG_WHITEPOINT
+ * tag value.  A decoder that demands absolute color calibration may use
+ * this white point tag to get back the original colors, but usually it
+ * will be ignored and the new white point will be used instead that
+ * matches the output color space.
+ *
+ * Pixel information is compressed into one of two basic encodings, depending
+ * on the setting of the compression tag, which is one of COMPRESSION_SGILOG
+ * or COMPRESSION_SGILOG24.  For COMPRESSION_SGILOG, greyscale data is
+ * stored as:
+ *
+ *   1       15
+ *  |-+---------------|
+ *
+ * COMPRESSION_SGILOG color data is stored as:
+ *
+ *   1       15           8        8
+ *  |-+---------------|--------+--------|
+ *   S       Le           ue       ve
+ *
+ * For the 24-bit COMPRESSION_SGILOG24 color format, the data is stored as:
+ *
+ *       10           14
+ *  |----------|--------------|
+ *       Le'          Ce
+ *
+ * There is no sign bit in the 24-bit case, and the (u,v) chromaticity is
+ * encoded as an index for optimal color resolution.  The 10 log bits are
+ * defined by the following conversions:
+ *
+ *  L = 2^((Le'+.5)/64 - 12)    # real from 10-bit
+ *
+ *  Le' = floor( 64*(log2(L) + 12) )  # 10-bit from real
+ *
+ * The 10 bits of the smaller format may be converted into the 15 bits of
+ * the larger format by multiplying by 4 and adding 13314.  Obviously,
+ * a smaller range of magnitudes is covered (about 5 orders of magnitude
+ * instead of 38), and the lack of a sign bit means that negative luminances
+ * are not allowed.  (Well, they aren't allowed in the real world, either,
+ * but they are useful for certain types of image processing.)
+ *
+ * The desired user format is controlled by the setting the internal
+ * pseudo tag TIFFTAG_SGILOGDATAFMT to one of:
+ *  SGILOGDATAFMT_FLOAT       = IEEE 32-bit float XYZ values
+ *  SGILOGDATAFMT_16BIT        = 16-bit integer encodings of logL, u and v
+ * Raw data i/o is also possible using:
+ *  SGILOGDATAFMT_RAW         = 32-bit unsigned integer with encoded pixel
+ * In addition, the following decoding is provided for ease of display:
+ *  SGILOGDATAFMT_8BIT        = 8-bit default RGB gamma-corrected values
+ *
+ * For grayscale images, we provide the following data formats:
+ *  SGILOGDATAFMT_FLOAT       = IEEE 32-bit float Y values
+ *  SGILOGDATAFMT_16BIT       = 16-bit integer w/ encoded luminance
+ *  SGILOGDATAFMT_8BIT        = 8-bit gray monitor values
+ *
+ * Note that the COMPRESSION_SGILOG applies a simple run-length encoding
+ * scheme by separating the logL, u and v bytes for each row and applying
+ * a PackBits type of compression.  Since the 24-bit encoding is not
+ * adaptive, the 32-bit color format takes less space in many cases.
+ *
+ * Further control is provided over the conversion from higher-resolution
+ * formats to final encoded values through the pseudo tag
+ * TIFFTAG_SGILOGENCODE:
+ *  SGILOGENCODE_NODITHER     = do not dither encoded values
+ *  SGILOGENCODE_RANDITHER    = apply random dithering during encoding
+ *
+ * The default value of this tag is SGILOGENCODE_NODITHER for
+ * COMPRESSION_SGILOG to maximize run-length encoding and
+ * SGILOGENCODE_RANDITHER for COMPRESSION_SGILOG24 to turn
+ * quantization errors into noise.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+/*
+ * State block for each open TIFF
+ * file using LogLuv compression/decompression.
+ */
+typedef  struct logLuvState LogLuvState;
+
+struct logLuvState {
+  int      user_datafmt;  /* user data format */
+  int      encode_meth;  /* encoding method */
+  int      pixel_size;  /* bytes per pixel */
+
+  tidata_t*    tbuf;    /* translation buffer */
+  int      tbuflen;  /* buffer length */
+  void (*tfunc)(LogLuvState*, tidata_t, int);
+
+  TIFFVSetMethod    vgetparent;  /* super-class method */
+  TIFFVSetMethod    vsetparent;  /* super-class method */
+};
+
+#define  DecoderState(tif)  ((LogLuvState*) (tif)->tif_data)
+#define  EncoderState(tif)  ((LogLuvState*) (tif)->tif_data)
+
+#define N(a)   (sizeof(a)/sizeof(a[0]))
+#define SGILOGDATAFMT_UNKNOWN  -1
+
+#define MINRUN    4  /* minimum run length */
+
+/*
+ * Decode a string of 16-bit gray pixels.
+ */
+static int
+LogL16Decode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s)
+{
+  LogLuvState* sp = DecoderState(tif);
+  int shft, i, npixels;
+  unsigned char* bp;
+  int16* tp;
+  int16 b;
+  int cc, rc;
+
+  assert(s == 0);
+  assert(sp != NULL);
+
+  npixels = occ / sp->pixel_size;
+
+  if (sp->user_datafmt == SGILOGDATAFMT_16BIT)
+    tp = (int16*) op;
+  else {
+    assert(sp->tbuflen >= npixels);
+    tp = (int16*) sp->tbuf;
+  }
+  _TIFFmemset((tdata_t) tp, 0, npixels*sizeof (tp[0]));
+
+  bp = (unsigned char*) tif->tif_rawcp;
+  cc = tif->tif_rawcc;
+          /* get each byte string */
+  for (shft = 2*8; (shft -= 8) >= 0; ) {
+    for (i = 0; i < npixels && cc > 0; )
+      if (*bp >= 128) {    /* run */
+        rc = *bp++ + (2-128);
+        b = (int16)(*bp++ << shft);
+        cc -= 2;
+        while (rc-- && i < npixels)
+          tp[i++] |= b;
+      } else {      /* non-run */
+        rc = *bp++;    /* nul is noop */
+        while (--cc && rc-- && i < npixels)
+          tp[i++] |= (int16)*bp++ << shft;
+      }
+    if (i != npixels) {
+      TIFFError(tif->tif_name,
+    "LogL16Decode: Not enough data at row %d (short %d pixels)",
+          tif->tif_row, npixels - i);
+      tif->tif_rawcp = (tidata_t) bp;
+      tif->tif_rawcc = cc;
+      return (0);
+    }
+  }
+  (*sp->tfunc)(sp, op, npixels);
+  tif->tif_rawcp = (tidata_t) bp;
+  tif->tif_rawcc = cc;
+  return (1);
+}
+
+/*
+ * Decode a string of 24-bit pixels.
+ */
+static int
+LogLuvDecode24(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s)
+{
+  LogLuvState* sp = DecoderState(tif);
+  int cc, i, npixels;
+  unsigned char* bp;
+  uint32* tp;
+
+  assert(s == 0);
+  assert(sp != NULL);
+
+  npixels = occ / sp->pixel_size;
+
+  if (sp->user_datafmt == SGILOGDATAFMT_RAW)
+    tp = (uint32 *)op;
+  else {
+    assert(sp->tbuflen >= npixels);
+    tp = (uint32 *) sp->tbuf;
+  }
+          /* copy to array of uint32 */
+  bp = (unsigned char*) tif->tif_rawcp;
+  cc = tif->tif_rawcc;
+  for (i = 0; i < npixels && cc > 0; i++) {
+    tp[i] = bp[0] << 16 | bp[1] << 8 | bp[2];
+    bp += 3;
+    cc -= 3;
+  }
+  tif->tif_rawcp = (tidata_t) bp;
+  tif->tif_rawcc = cc;
+  if (i != npixels) {
+    TIFFError(tif->tif_name,
+      "LogLuvDecode24: Not enough data at row %d (short %d pixels)",
+        tif->tif_row, npixels - i);
+    return (0);
+  }
+  (*sp->tfunc)(sp, op, npixels);
+  return (1);
+}
+
+/*
+ * Decode a string of 32-bit pixels.
+ */
+static int
+LogLuvDecode32(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s)
+{
+  LogLuvState* sp;
+  int shft, i, npixels;
+  unsigned char* bp;
+  uint32* tp;
+  uint32 b;
+  int cc, rc;
+
+  assert(s == 0);
+  sp = DecoderState(tif);
+  assert(sp != NULL);
+
+  npixels = occ / sp->pixel_size;
+
+  if (sp->user_datafmt == SGILOGDATAFMT_RAW)
+    tp = (uint32*) op;
+  else {
+    assert(sp->tbuflen >= npixels);
+    tp = (uint32*) sp->tbuf;
+  }
+  _TIFFmemset((tdata_t) tp, 0, npixels*sizeof (tp[0]));
+
+  bp = (unsigned char*) tif->tif_rawcp;
+  cc = tif->tif_rawcc;
+          /* get each byte string */
+  for (shft = 4*8; (shft -= 8) >= 0; ) {
+    for (i = 0; i < npixels && cc > 0; )
+      if (*bp >= 128) {    /* run */
+        rc = *bp++ + (2-128);
+        b = (uint32)*bp++ << shft;
+        cc -= 2;
+        while (rc-- && i < npixels)
+          tp[i++] |= b;
+      } else {      /* non-run */
+        rc = *bp++;    /* nul is noop */
+        while (--cc && rc-- && i < npixels)
+          tp[i++] |= (uint32)*bp++ << shft;
+      }
+    if (i != npixels) {
+      TIFFError(tif->tif_name,
+    "LogLuvDecode32: Not enough data at row %d (short %d pixels)",
+          tif->tif_row, npixels - i);
+      tif->tif_rawcp = (tidata_t) bp;
+      tif->tif_rawcc = cc;
+      return (0);
+    }
+  }
+  (*sp->tfunc)(sp, op, npixels);
+  tif->tif_rawcp = (tidata_t) bp;
+  tif->tif_rawcc = cc;
+  return (1);
+}
+
+/*
+ * Decode a strip of pixels.  We break it into rows to
+ * maintain synchrony with the encode algorithm, which
+ * is row by row.
+ */
+static int
+LogLuvDecodeStrip(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
+{
+  tsize_t rowlen = TIFFScanlineSize(tif);
+
+  assert(cc%rowlen == 0);
+  while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s))
+    bp += rowlen, cc -= rowlen;
+  return (cc == 0);
+}
+
+/*
+ * Decode a tile of pixels.  We break it into rows to
+ * maintain synchrony with the encode algorithm, which
+ * is row by row.
+ */
+static int
+LogLuvDecodeTile(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
+{
+  tsize_t rowlen = TIFFTileRowSize(tif);
+
+  assert(cc%rowlen == 0);
+  while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s))
+    bp += rowlen, cc -= rowlen;
+  return (cc == 0);
+}
+
+/*
+ * Encode a row of 16-bit pixels.
+ */
+static int
+LogL16Encode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
+{
+  LogLuvState* sp = EncoderState(tif);
+  int shft, i, j, npixels;
+  tidata_t op;
+  int16* tp;
+  int16 b;
+  int occ, rc=0, mask, beg;
+
+  assert(s == 0);
+  assert(sp != NULL);
+  npixels = cc / sp->pixel_size;
+
+  if (sp->user_datafmt == SGILOGDATAFMT_16BIT)
+    tp = (int16*) bp;
+  else {
+    tp = (int16*) sp->tbuf;
+    assert(sp->tbuflen >= npixels);
+    (*sp->tfunc)(sp, bp, npixels);
+  }
+          /* compress each byte string */
+  op = tif->tif_rawcp;
+  occ = tif->tif_rawdatasize - tif->tif_rawcc;
+  for (shft = 2*8; (shft -= 8) >= 0; )
+    for (i = 0; i < npixels; i += rc) {
+      if (occ < 4) {
+        tif->tif_rawcp = op;
+        tif->tif_rawcc = tif->tif_rawdatasize - occ;
+        if (!TIFFFlushData1(tif))
+          return (-1);
+        op = tif->tif_rawcp;
+        occ = tif->tif_rawdatasize - tif->tif_rawcc;
+      }
+      mask = 0xff << shft;    /* find next run */
+      for (beg = i; beg < npixels; beg += rc) {
+        b = (int16) (tp[beg] & mask);
+        rc = 1;
+        while (rc < 127+2 && beg+rc < npixels &&
+            (tp[beg+rc] & mask) == b)
+          rc++;
+        if (rc >= MINRUN)
+          break;    /* long enough */
+      }
+      if (beg-i > 1 && beg-i < MINRUN) {
+        b = (int16) (tp[i] & mask);/*check short run */
+        j = i+1;
+        while ((tp[j++] & mask) == b)
+                                    if (j == beg) {
+                                        *op++ = (tidataval_t)(128-2+j-i);
+                                        *op++ = (tidataval_t) (b >> shft);
+                                        occ -= 2;
+                                        i = beg;
+                                        break;
+                                    }
+      }
+      while (i < beg) {    /* write out non-run */
+        if ((j = beg-i) > 127) j = 127;
+        if (occ < j+3) {
+                                    tif->tif_rawcp = op;
+                                    tif->tif_rawcc = tif->tif_rawdatasize - occ;
+                                    if (!TIFFFlushData1(tif))
+                                        return (-1);
+                                    op = tif->tif_rawcp;
+                                    occ = tif->tif_rawdatasize - tif->tif_rawcc;
+        }
+        *op++ = (tidataval_t) j; occ--;
+        while (j--) {
+          *op++ = (tidataval_t) (tp[i++] >> shft & 0xff);
+          occ--;
+        }
+      }
+      if (rc >= MINRUN) {    /* write out run */
+        *op++ = (tidataval_t) (128-2+rc);
+        *op++ = (tidataval_t) (tp[beg] >> shft & 0xff);
+        occ -= 2;
+      } else
+        rc = 0;
+    }
+  tif->tif_rawcp = op;
+  tif->tif_rawcc = tif->tif_rawdatasize - occ;
+
+  return (0);
+}
+
+/*
+ * Encode a row of 24-bit pixels.
+ */
+static int
+LogLuvEncode24(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
+{
+  LogLuvState* sp = EncoderState(tif);
+  int i, npixels, occ;
+  tidata_t op;
+  uint32* tp;
+
+  assert(s == 0);
+  assert(sp != NULL);
+  npixels = cc / sp->pixel_size;
+
+  if (sp->user_datafmt == SGILOGDATAFMT_RAW)
+    tp = (uint32*) bp;
+  else {
+    tp = (uint32*) sp->tbuf;
+    assert(sp->tbuflen >= npixels);
+    (*sp->tfunc)(sp, bp, npixels);
+  }
+          /* write out encoded pixels */
+  op = tif->tif_rawcp;
+  occ = tif->tif_rawdatasize - tif->tif_rawcc;
+  for (i = npixels; i--; ) {
+    if (occ < 3) {
+      tif->tif_rawcp = op;
+      tif->tif_rawcc = tif->tif_rawdatasize - occ;
+      if (!TIFFFlushData1(tif))
+        return (-1);
+      op = tif->tif_rawcp;
+      occ = tif->tif_rawdatasize - tif->tif_rawcc;
+    }
+    *op++ = (tidataval_t)(*tp >> 16);
+    *op++ = (tidataval_t)(*tp >> 8 & 0xff);
+    *op++ = (tidataval_t)(*tp++ & 0xff);
+    occ -= 3;
+  }
+  tif->tif_rawcp = op;
+  tif->tif_rawcc = tif->tif_rawdatasize - occ;
+
+  return (0);
+}
+
+/*
+ * Encode a row of 32-bit pixels.
+ */
+static int
+LogLuvEncode32(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
+{
+  LogLuvState* sp = EncoderState(tif);
+  int shft, i, j, npixels;
+  tidata_t op;
+  uint32* tp;
+  uint32 b;
+  int occ, rc=0, mask, beg;
+
+  assert(s == 0);
+  assert(sp != NULL);
+
+  npixels = cc / sp->pixel_size;
+
+  if (sp->user_datafmt == SGILOGDATAFMT_RAW)
+    tp = (uint32*) bp;
+  else {
+    tp = (uint32*) sp->tbuf;
+    assert(sp->tbuflen >= npixels);
+    (*sp->tfunc)(sp, bp, npixels);
+  }
+          /* compress each byte string */
+  op = tif->tif_rawcp;
+  occ = tif->tif_rawdatasize - tif->tif_rawcc;
+  for (shft = 4*8; (shft -= 8) >= 0; )
+    for (i = 0; i < npixels; i += rc) {
+      if (occ < 4) {
+        tif->tif_rawcp = op;
+        tif->tif_rawcc = tif->tif_rawdatasize - occ;
+        if (!TIFFFlushData1(tif))
+          return (-1);
+        op = tif->tif_rawcp;
+        occ = tif->tif_rawdatasize - tif->tif_rawcc;
+      }
+      mask = 0xff << shft;    /* find next run */
+      for (beg = i; beg < npixels; beg += rc) {
+        b = tp[beg] & mask;
+        rc = 1;
+        while (rc < 127+2 && beg+rc < npixels &&
+            (tp[beg+rc] & mask) == b)
+          rc++;
+        if (rc >= MINRUN)
+          break;    /* long enough */
+      }
+      if (beg-i > 1 && beg-i < MINRUN) {
+        b = tp[i] & mask;  /* check short run */
+        j = i+1;
+        while ((tp[j++] & mask) == b)
+          if (j == beg) {
+            *op++ = (tidataval_t)(128-2+j-i);
+            *op++ = (tidataval_t)(b >> shft);
+            occ -= 2;
+            i = beg;
+            break;
+          }
+      }
+      while (i < beg) {    /* write out non-run */
+        if ((j = beg-i) > 127) j = 127;
+        if (occ < j+3) {
+          tif->tif_rawcp = op;
+          tif->tif_rawcc = tif->tif_rawdatasize - occ;
+          if (!TIFFFlushData1(tif))
+            return (-1);
+          op = tif->tif_rawcp;
+          occ = tif->tif_rawdatasize - tif->tif_rawcc;
+        }
+        *op++ = (tidataval_t) j; occ--;
+        while (j--) {
+          *op++ = (tidataval_t)(tp[i++] >> shft & 0xff);
+          occ--;
+        }
+      }
+      if (rc >= MINRUN) {    /* write out run */
+        *op++ = (tidataval_t) (128-2+rc);
+        *op++ = (tidataval_t)(tp[beg] >> shft & 0xff);
+        occ -= 2;
+      } else
+        rc = 0;
+    }
+  tif->tif_rawcp = op;
+  tif->tif_rawcc = tif->tif_rawdatasize - occ;
+
+  return (0);
+}
+
+/*
+ * Encode a strip of pixels.  We break it into rows to
+ * avoid encoding runs across row boundaries.
+ */
+static int
+LogLuvEncodeStrip(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
+{
+  tsize_t rowlen = TIFFScanlineSize(tif);
+
+  assert(cc%rowlen == 0);
+  while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 0)
+    bp += rowlen, cc -= rowlen;
+  return (cc == 0);
+}
+
+/*
+ * Encode a tile of pixels.  We break it into rows to
+ * avoid encoding runs across row boundaries.
+ */
+static int
+LogLuvEncodeTile(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
+{
+  tsize_t rowlen = TIFFTileRowSize(tif);
+
+  assert(cc%rowlen == 0);
+  while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 0)
+    bp += rowlen, cc -= rowlen;
+  return (cc == 0);
+}
+
+/*
+ * Encode/Decode functions for converting to and from user formats.
+ */
+
+#include "uvcode.h"
+
+#ifndef UVSCALE
+#define U_NEU    0.210526316
+#define V_NEU    0.473684211
+#define UVSCALE    410.
+#endif
+
+#ifndef  M_LN2
+#define M_LN2    0.69314718055994530942
+#endif
+#ifndef M_PI
+#define M_PI    3.14159265358979323846
+#endif
+#ifndef log2
+#define log2(x)    ((1./M_LN2)*log(x))
+#endif
+#define exp2(x)    exp(M_LN2*(x))
+
+#define itrunc(x,m)  ((m)==SGILOGENCODE_NODITHER ? \
+        (int)(x) : \
+        (int)((x) + rand()*(1./RAND_MAX) - .5))
+
+#if !LOGLUV_PUBLIC
+static
+#endif
+double
+LogL16toY(int p16)    /* compute luminance from 16-bit LogL */
+{
+  int  Le = p16 & 0x7fff;
+  double  Y;
+
+  if (!Le)
+    return (0.);
+  Y = exp(M_LN2/256.*(Le+.5) - M_LN2*64.);
+  return (!(p16 & 0x8000) ? Y : -Y);
+}
+
+#if !LOGLUV_PUBLIC
+static
+#endif
+int
+LogL16fromY(double Y, int em)  /* get 16-bit LogL from Y */
+{
+  if (Y >= 1.8371976e19)
+    return (0x7fff);
+  if (Y <= -1.8371976e19)
+    return (0xffff);
+  if (Y > 5.4136769e-20)
+    return itrunc(256.*(log2(Y) + 64.), em);
+  if (Y < -5.4136769e-20)
+    return (~0x7fff | itrunc(256.*(log2(-Y) + 64.), em));
+  return (0);
+}
+
+static void
+L16toY(LogLuvState* sp, tidata_t op, int n)
+{
+  int16* l16 = (int16*) sp->tbuf;
+  float* yp = (float*) op;
+
+  while (n-- > 0)
+    *yp++ = (float)LogL16toY(*l16++);
+}
+
+static void
+L16toGry(LogLuvState* sp, tidata_t op, int n)
+{
+  int16* l16 = (int16*) sp->tbuf;
+  uint8* gp = (uint8*) op;
+
+  while (n-- > 0) {
+    double Y = LogL16toY(*l16++);
+    *gp++ = (uint8) ((Y <= 0.) ? 0 : (Y >= 1.) ? 255 : (int)(256.*sqrt(Y)));
+  }
+}
+
+static void
+L16fromY(LogLuvState* sp, tidata_t op, int n)
+{
+  int16* l16 = (int16*) sp->tbuf;
+  float* yp = (float*) op;
+
+  while (n-- > 0)
+    *l16++ = (int16) (LogL16fromY(*yp++, sp->encode_meth));
+}
+
+#if !LOGLUV_PUBLIC
+static
+#endif
+void
+XYZtoRGB24(float xyz[3], uint8 rgb[3])
+{
+  double  r, g, b;
+          /* assume CCIR-709 primaries */
+  r =  2.690*xyz[0] + -1.276*xyz[1] + -0.414*xyz[2];
+  g = -1.022*xyz[0] +  1.978*xyz[1] +  0.044*xyz[2];
+  b =  0.061*xyz[0] + -0.224*xyz[1] +  1.163*xyz[2];
+          /* assume 2.0 gamma for speed */
+  /* could use integer sqrt approx., but this is probably faster */
+  rgb[0] = (uint8)((r<=0.) ? 0 : (r >= 1.) ? 255 : (int)(256.*sqrt(r)));
+  rgb[1] = (uint8)((g<=0.) ? 0 : (g >= 1.) ? 255 : (int)(256.*sqrt(g)));
+  rgb[2] = (uint8)((b<=0.) ? 0 : (b >= 1.) ? 255 : (int)(256.*sqrt(b)));
+}
+
+#if !LOGLUV_PUBLIC
+static
+#endif
+double
+LogL10toY(int p10)    /* compute luminance from 10-bit LogL */
+{
+  if (p10 == 0)
+    return (0.);
+  return (exp(M_LN2/64.*(p10+.5) - M_LN2*12.));
+}
+
+#if !LOGLUV_PUBLIC
+static
+#endif
+int
+LogL10fromY(double Y, int em)  /* get 10-bit LogL from Y */
+{
+  if (Y >= 15.742)
+    return (0x3ff);
+  else if (Y <= .00024283)
+    return (0);
+  else
+    return itrunc(64.*(log2(Y) + 12.), em);
+}
+
+#define NANGLES    100
+#define uv2ang(u, v)  ( (NANGLES*.499999999/M_PI) \
+        * atan2((v)-V_NEU,(u)-U_NEU) + .5*NANGLES )
+
+static int
+oog_encode(double u, double v)    /* encode out-of-gamut chroma */
+{
+  static int  oog_table[NANGLES];
+  static int  initialized = 0;
+  register int  i;
+  
+  if (!initialized) {    /* set up perimeter table */
+    double  eps[NANGLES], ua, va, ang, epsa;
+    int  ui, vi, ustep;
+    for (i = NANGLES; i--; )
+      eps[i] = 2.;
+    for (vi = UV_NVS; vi--; ) {
+      va = UV_VSTART + (vi+.5)*UV_SQSIZ;
+      ustep = uv_row[vi].nus-1;
+      if (vi == UV_NVS-1 || vi == 0 || ustep <= 0)
+        ustep = 1;
+      for (ui = uv_row[vi].nus-1; ui >= 0; ui -= ustep) {
+        ua = uv_row[vi].ustart + (ui+.5)*UV_SQSIZ;
+        ang = uv2ang(ua, va);
+                                i = (int) ang;
+        epsa = fabs(ang - (i+.5));
+        if (epsa < eps[i]) {
+          oog_table[i] = uv_row[vi].ncum + ui;
+          eps[i] = epsa;
+        }
+      }
+    }
+    for (i = NANGLES; i--; )  /* fill any holes */
+      if (eps[i] > 1.5) {
+        int  i1, i2;
+        for (i1 = 1; i1 < NANGLES/2; i1++)
+          if (eps[(i+i1)%NANGLES] < 1.5)
+            break;
+        for (i2 = 1; i2 < NANGLES/2; i2++)
+          if (eps[(i+NANGLES-i2)%NANGLES] < 1.5)
+            break;
+        if (i1 < i2)
+          oog_table[i] =
+            oog_table[(i+i1)%NANGLES];
+        else
+          oog_table[i] =
+            oog_table[(i+NANGLES-i2)%NANGLES];
+      }
+    initialized = 1;
+  }
+  i = (int) uv2ang(u, v);    /* look up hue angle */
+  return (oog_table[i]);
+}
+
+#undef uv2ang
+#undef NANGLES
+
+#if !LOGLUV_PUBLIC
+static
+#endif
+int
+uv_encode(double u, double v, int em)  /* encode (u',v') coordinates */
+{
+  register int  vi, ui;
+
+  if (v < UV_VSTART)
+    return oog_encode(u, v);
+  vi = itrunc((v - UV_VSTART)*(1./UV_SQSIZ), em);
+  if (vi >= UV_NVS)
+    return oog_encode(u, v);
+  if (u < uv_row[vi].ustart)
+    return oog_encode(u, v);
+  ui = itrunc((u - uv_row[vi].ustart)*(1./UV_SQSIZ), em);
+  if (ui >= uv_row[vi].nus)
+    return oog_encode(u, v);
+
+  return (uv_row[vi].ncum + ui);
+}
+
+#if !LOGLUV_PUBLIC
+static
+#endif
+int
+uv_decode(double *up, double *vp, int c)  /* decode (u',v') index */
+{
+  int  upper, lower;
+  register int  ui, vi;
+
+  if (c < 0 || c >= UV_NDIVS)
+    return (-1);
+  lower = 0;        /* binary search */
+  upper = UV_NVS;
+  while (upper - lower > 1) {
+    vi = (lower + upper) >> 1;
+    ui = c - uv_row[vi].ncum;
+    if (ui > 0)
+      lower = vi;
+    else if (ui < 0)
+      upper = vi;
+    else {
+      lower = vi;
+      break;
+    }
+  }
+  vi = lower;
+  ui = c - uv_row[vi].ncum;
+  *up = uv_row[vi].ustart + (ui+.5)*UV_SQSIZ;
+  *vp = UV_VSTART + (vi+.5)*UV_SQSIZ;
+  return (0);
+}
+
+#if !LOGLUV_PUBLIC
+static
+#endif
+void
+LogLuv24toXYZ(uint32 p, float XYZ[3])
+{
+  int  Ce;
+  double  L, u, v, s, x, y;
+          /* decode luminance */
+  L = LogL10toY(p>>14 & 0x3ff);
+  if (L <= 0.) {
+    XYZ[0] = XYZ[1] = XYZ[2] = 0.;
+    return;
+  }
+          /* decode color */
+  Ce = p & 0x3fff;
+  if (uv_decode(&u, &v, Ce) < 0) {
+    u = U_NEU; v = V_NEU;
+  }
+  s = 1./(6.*u - 16.*v + 12.);
+  x = 9.*u * s;
+  y = 4.*v * s;
+          /* convert to XYZ */
+  XYZ[0] = (float)(x/y * L);
+  XYZ[1] = (float)L;
+  XYZ[2] = (float)((1.-x-y)/y * L);
+}
+
+#if !LOGLUV_PUBLIC
+static
+#endif
+uint32
+LogLuv24fromXYZ(float XYZ[3], int em)
+{
+  int  Le, Ce;
+  double  u, v, s;
+          /* encode luminance */
+  Le = LogL10fromY(XYZ[1], em);
+          /* encode color */
+  s = XYZ[0] + 15.*XYZ[1] + 3.*XYZ[2];
+  if (!Le || s <= 0.) {
+    u = U_NEU;
+    v = V_NEU;
+  } else {
+    u = 4.*XYZ[0] / s;
+    v = 9.*XYZ[1] / s;
+  }
+  Ce = uv_encode(u, v, em);
+  if (Ce < 0)      /* never happens */
+    Ce = uv_encode(U_NEU, V_NEU, SGILOGENCODE_NODITHER);
+          /* combine encodings */
+  return (Le << 14 | Ce);
+}
+
+static void
+Luv24toXYZ(LogLuvState* sp, tidata_t op, int n)
+{
+  uint32* luv = (uint32*) sp->tbuf;
+  float* xyz = (float*) op;
+
+  while (n-- > 0) {
+    LogLuv24toXYZ(*luv, xyz);
+    xyz += 3;
+    luv++;
+  }
+}
+
+static void
+Luv24toLuv48(LogLuvState* sp, tidata_t op, int n)
+{
+  uint32* luv = (uint32*) sp->tbuf;
+  int16* luv3 = (int16*) op;
+
+  while (n-- > 0) {
+    double u, v;
+
+    *luv3++ = (int16)((*luv >> 12 & 0xffd) + 13314);
+    if (uv_decode(&u, &v, *luv&0x3fff) < 0) {
+      u = U_NEU;
+      v = V_NEU;
+    }
+    *luv3++ = (int16)(u * (1L<<15));
+    *luv3++ = (int16)(v * (1L<<15));
+    luv++;
+  }
+}
+
+static void
+Luv24toRGB(LogLuvState* sp, tidata_t op, int n)
+{
+  uint32* luv = (uint32*) sp->tbuf;
+  uint8* rgb = (uint8*) op;
+
+  while (n-- > 0) {
+    float xyz[3];
+
+    LogLuv24toXYZ(*luv++, xyz);
+    XYZtoRGB24(xyz, rgb);
+    rgb += 3;
+  }
+}
+
+static void
+Luv24fromXYZ(LogLuvState* sp, tidata_t op, int n)
+{
+  uint32* luv = (uint32*) sp->tbuf;
+  float* xyz = (float*) op;
+
+  while (n-- > 0) {
+    *luv++ = LogLuv24fromXYZ(xyz, sp->encode_meth);
+    xyz += 3;
+  }
+}
+
+static void
+Luv24fromLuv48(LogLuvState* sp, tidata_t op, int n)
+{
+  uint32* luv = (uint32*) sp->tbuf;
+  int16* luv3 = (int16*) op;
+
+  while (n-- > 0) {
+    int Le, Ce;
+
+    if (luv3[0] <= 0)
+      Le = 0;
+    else if (luv3[0] >= (1<<12)+3314)
+      Le = (1<<10) - 1;
+    else if (sp->encode_meth == SGILOGENCODE_NODITHER)
+      Le = (luv3[0]-3314) >> 2;
+    else
+      Le = itrunc(.25*(luv3[0]-3314.), sp->encode_meth);
+
+    Ce = uv_encode((luv3[1]+.5)/(1<<15), (luv3[2]+.5)/(1<<15),
+          sp->encode_meth);
+    if (Ce < 0)  /* never happens */
+      Ce = uv_encode(U_NEU, V_NEU, SGILOGENCODE_NODITHER);
+    *luv++ = (uint32)Le << 14 | Ce;
+    luv3 += 3;
+  }
+}
+
+#if !LOGLUV_PUBLIC
+static
+#endif
+void
+LogLuv32toXYZ(uint32 p, float XYZ[3])
+{
+  double  L, u, v, s, x, y;
+          /* decode luminance */
+  L = LogL16toY((int)p >> 16);
+  if (L <= 0.) {
+    XYZ[0] = XYZ[1] = XYZ[2] = 0.;
+    return;
+  }
+          /* decode color */
+  u = 1./UVSCALE * ((p>>8 & 0xff) + .5);
+  v = 1./UVSCALE * ((p & 0xff) + .5);
+  s = 1./(6.*u - 16.*v + 12.);
+  x = 9.*u * s;
+  y = 4.*v * s;
+          /* convert to XYZ */
+  XYZ[0] = (float)(x/y * L);
+  XYZ[1] = (float)L;
+  XYZ[2] = (float)((1.-x-y)/y * L);
+}
+
+#if !LOGLUV_PUBLIC
+static
+#endif
+uint32
+LogLuv32fromXYZ(float XYZ[3], int em)
+{
+  unsigned int  Le, ue, ve;
+  double  u, v, s;
+          /* encode luminance */
+  Le = (unsigned int)LogL16fromY(XYZ[1], em);
+          /* encode color */
+  s = XYZ[0] + 15.*XYZ[1] + 3.*XYZ[2];
+  if (!Le || s <= 0.) {
+    u = U_NEU;
+    v = V_NEU;
+  } else {
+    u = 4.*XYZ[0] / s;
+    v = 9.*XYZ[1] / s;
+  }
+  if (u <= 0.) ue = 0;
+  else ue = itrunc(UVSCALE*u, em);
+  if (ue > 255) ue = 255;
+  if (v <= 0.) ve = 0;
+  else ve = itrunc(UVSCALE*v, em);
+  if (ve > 255) ve = 255;
+          /* combine encodings */
+  return (Le << 16 | ue << 8 | ve);
+}
+
+static void
+Luv32toXYZ(LogLuvState* sp, tidata_t op, int n)
+{
+  uint32* luv = (uint32*) sp->tbuf;
+  float* xyz = (float*) op;
+
+  while (n-- > 0) {
+    LogLuv32toXYZ(*luv++, xyz);
+    xyz += 3;
+  }
+}
+
+static void
+Luv32toLuv48(LogLuvState* sp, tidata_t op, int n)
+{
+  uint32* luv = (uint32*) sp->tbuf;
+  int16* luv3 = (int16*) op;
+
+  while (n-- > 0) {
+    double u, v;
+
+    *luv3++ = (int16)(*luv >> 16);
+    u = 1./UVSCALE * ((*luv>>8 & 0xff) + .5);
+    v = 1./UVSCALE * ((*luv & 0xff) + .5);
+    *luv3++ = (int16)(u * (1L<<15));
+    *luv3++ = (int16)(v * (1L<<15));
+    luv++;
+  }
+}
+
+static void
+Luv32toRGB(LogLuvState* sp, tidata_t op, int n)
+{
+  uint32* luv = (uint32*) sp->tbuf;
+  uint8* rgb = (uint8*) op;
+
+  while (n-- > 0) {
+    float xyz[3];
+
+    LogLuv32toXYZ(*luv++, xyz);
+    XYZtoRGB24(xyz, rgb);
+    rgb += 3;
+  }
+}
+
+static void
+Luv32fromXYZ(LogLuvState* sp, tidata_t op, int n)
+{
+  uint32* luv = (uint32*) sp->tbuf;
+  float* xyz = (float*) op;
+
+  while (n-- > 0) {
+    *luv++ = LogLuv32fromXYZ(xyz, sp->encode_meth);
+    xyz += 3;
+  }
+}
+
+static void
+Luv32fromLuv48(LogLuvState* sp, tidata_t op, int n)
+{
+  uint32* luv = (uint32*) sp->tbuf;
+  int16* luv3 = (int16*) op;
+
+  if (sp->encode_meth == SGILOGENCODE_NODITHER) {
+    while (n-- > 0) {
+      *luv++ = (uint32)luv3[0] << 16 |
+        (luv3[1]*(uint32)(UVSCALE+.5) >> 7 & 0xff00) |
+        (luv3[2]*(uint32)(UVSCALE+.5) >> 15 & 0xff);
+      luv3 += 3;
+    }
+    return;
+  }
+  while (n-- > 0) {
+    *luv++ = (uint32)luv3[0] << 16 |
+  (itrunc(luv3[1]*(UVSCALE/(1<<15)), sp->encode_meth) << 8 & 0xff00) |
+    (itrunc(luv3[2]*(UVSCALE/(1<<15)), sp->encode_meth) & 0xff);
+    luv3 += 3;
+  }
+}
+
+static void
+_logLuvNop(LogLuvState* sp, tidata_t op, int n)
+{
+  (void) sp; (void) op; (void) n;
+}
+
+static int
+LogL16GuessDataFmt(TIFFDirectory *td)
+{
+#define  PACK(s,b,f)  (((b)<<6)|((s)<<3)|(f))
+  switch (PACK(td->td_samplesperpixel, td->td_bitspersample, td->td_sampleformat)) {
+  case PACK(1, 32, SAMPLEFORMAT_IEEEFP):
+    return (SGILOGDATAFMT_FLOAT);
+  case PACK(1, 16, SAMPLEFORMAT_VOID):
+  case PACK(1, 16, SAMPLEFORMAT_INT):
+  case PACK(1, 16, SAMPLEFORMAT_UINT):
+    return (SGILOGDATAFMT_16BIT);
+  case PACK(1,  8, SAMPLEFORMAT_VOID):
+  case PACK(1,  8, SAMPLEFORMAT_UINT):
+    return (SGILOGDATAFMT_8BIT);
+  }
+#undef PACK
+  return (SGILOGDATAFMT_UNKNOWN);
+}
+
+static uint32
+multiply(size_t m1, size_t m2)
+{
+  uint32  bytes = m1 * m2;
+
+  if (m1 && bytes / m1 != m2)
+    bytes = 0;
+
+  return bytes;
+}
+
+static int
+LogL16InitState(TIFF* tif)
+{
+  TIFFDirectory *td = &tif->tif_dir;
+  LogLuvState* sp = DecoderState(tif);
+  static const char module[] = "LogL16InitState";
+
+  assert(sp != NULL);
+  assert(td->td_photometric == PHOTOMETRIC_LOGL);
+
+  /* for some reason, we can't do this in TIFFInitLogL16 */
+  if (sp->user_datafmt == SGILOGDATAFMT_UNKNOWN)
+    sp->user_datafmt = LogL16GuessDataFmt(td);
+  switch (sp->user_datafmt) {
+  case SGILOGDATAFMT_FLOAT:
+    sp->pixel_size = sizeof (float);
+    break;
+  case SGILOGDATAFMT_16BIT:
+    sp->pixel_size = sizeof (int16);
+    break;
+  case SGILOGDATAFMT_8BIT:
+    sp->pixel_size = sizeof (uint8);
+    break;
+  default:
+    TIFFError(tif->tif_name,
+        "No support for converting user data format to LogL");
+    return (0);
+  }
+  sp->tbuflen = multiply(td->td_imagewidth, td->td_rowsperstrip);
+  if (multiply(sp->tbuflen, sizeof (int16)) == 0 ||
+      (sp->tbuf = (tidata_t*) _TIFFmalloc(sp->tbuflen * sizeof (int16))) == NULL) {
+    TIFFError(module, "%s: No space for SGILog translation buffer",
+        tif->tif_name);
+    return (0);
+  }
+  return (1);
+}
+
+static int
+LogLuvGuessDataFmt(TIFFDirectory *td)
+{
+  int guess;
+
+  /*
+   * If the user didn't tell us their datafmt,
+   * take our best guess from the bitspersample.
+   */
+#define  PACK(a,b)  (((a)<<3)|(b))
+  switch (PACK(td->td_bitspersample, td->td_sampleformat)) {
+  case PACK(32, SAMPLEFORMAT_IEEEFP):
+    guess = SGILOGDATAFMT_FLOAT;
+    break;
+  case PACK(32, SAMPLEFORMAT_VOID):
+  case PACK(32, SAMPLEFORMAT_UINT):
+  case PACK(32, SAMPLEFORMAT_INT):
+    guess = SGILOGDATAFMT_RAW;
+    break;
+  case PACK(16, SAMPLEFORMAT_VOID):
+  case PACK(16, SAMPLEFORMAT_INT):
+  case PACK(16, SAMPLEFORMAT_UINT):
+    guess = SGILOGDATAFMT_16BIT;
+    break;
+  case PACK( 8, SAMPLEFORMAT_VOID):
+  case PACK( 8, SAMPLEFORMAT_UINT):
+    guess = SGILOGDATAFMT_8BIT;
+    break;
+  default:
+    guess = SGILOGDATAFMT_UNKNOWN;
+    break;
+#undef PACK
+  }
+  /*
+   * Double-check samples per pixel.
+   */
+  switch (td->td_samplesperpixel) {
+  case 1:
+    if (guess != SGILOGDATAFMT_RAW)
+      guess = SGILOGDATAFMT_UNKNOWN;
+    break;
+  case 3:
+    if (guess == SGILOGDATAFMT_RAW)
+      guess = SGILOGDATAFMT_UNKNOWN;
+    break;
+  default:
+    guess = SGILOGDATAFMT_UNKNOWN;
+    break;
+  }
+  return (guess);
+}
+
+static int
+LogLuvInitState(TIFF* tif)
+{
+  TIFFDirectory* td = &tif->tif_dir;
+  LogLuvState* sp = DecoderState(tif);
+  static const char module[] = "LogLuvInitState";
+
+  assert(sp != NULL);
+  assert(td->td_photometric == PHOTOMETRIC_LOGLUV);
+
+  /* for some reason, we can't do this in TIFFInitLogLuv */
+  if (td->td_planarconfig != PLANARCONFIG_CONTIG) {
+    TIFFError(module,
+        "SGILog compression cannot handle non-contiguous data");
+    return (0);
+  }
+  if (sp->user_datafmt == SGILOGDATAFMT_UNKNOWN)
+    sp->user_datafmt = LogLuvGuessDataFmt(td);
+  switch (sp->user_datafmt) {
+  case SGILOGDATAFMT_FLOAT:
+    sp->pixel_size = 3*sizeof (float);
+    break;
+  case SGILOGDATAFMT_16BIT:
+    sp->pixel_size = 3*sizeof (int16);
+    break;
+  case SGILOGDATAFMT_RAW:
+    sp->pixel_size = sizeof (uint32);
+    break;
+  case SGILOGDATAFMT_8BIT:
+    sp->pixel_size = 3*sizeof (uint8);
+    break;
+  default:
+    TIFFError(tif->tif_name,
+        "No support for converting user data format to LogLuv");
+    return (0);
+  }
+  sp->tbuflen = multiply(td->td_imagewidth, td->td_rowsperstrip);
+  if (multiply(sp->tbuflen, sizeof (uint32)) == 0 ||
+      (sp->tbuf = (tidata_t*) _TIFFmalloc(sp->tbuflen * sizeof (uint32))) == NULL) {
+    TIFFError(module, "%s: No space for SGILog translation buffer",
+        tif->tif_name);
+    return (0);
+  }
+  return (1);
+}
+
+static int
+LogLuvSetupDecode(TIFF* tif)
+{
+  LogLuvState* sp = DecoderState(tif);
+  TIFFDirectory* td = &tif->tif_dir;
+
+  tif->tif_postdecode = _TIFFNoPostDecode;
+  switch (td->td_photometric) {
+  case PHOTOMETRIC_LOGLUV:
+    if (!LogLuvInitState(tif))
+      break;
+    if (td->td_compression == COMPRESSION_SGILOG24) {
+      tif->tif_decoderow = LogLuvDecode24;
+      switch (sp->user_datafmt) {
+      case SGILOGDATAFMT_FLOAT:
+        sp->tfunc = Luv24toXYZ;
+        break;
+      case SGILOGDATAFMT_16BIT:
+        sp->tfunc = Luv24toLuv48;
+        break;
+      case SGILOGDATAFMT_8BIT:
+        sp->tfunc = Luv24toRGB;
+        break;
+      }
+    } else {
+      tif->tif_decoderow = LogLuvDecode32;
+      switch (sp->user_datafmt) {
+      case SGILOGDATAFMT_FLOAT:
+        sp->tfunc = Luv32toXYZ;
+        break;
+      case SGILOGDATAFMT_16BIT:
+        sp->tfunc = Luv32toLuv48;
+        break;
+      case SGILOGDATAFMT_8BIT:
+        sp->tfunc = Luv32toRGB;
+        break;
+      }
+    }
+    return (1);
+  case PHOTOMETRIC_LOGL:
+    if (!LogL16InitState(tif))
+      break;
+    tif->tif_decoderow = LogL16Decode;
+    switch (sp->user_datafmt) {
+    case SGILOGDATAFMT_FLOAT:
+      sp->tfunc = L16toY;
+      break;
+    case SGILOGDATAFMT_8BIT:
+      sp->tfunc = L16toGry;
+      break;
+    }
+    return (1);
+  default:
+    TIFFError(tif->tif_name,
+    "Inappropriate photometric interpretation %d for SGILog compression; %s",
+        td->td_photometric, "must be either LogLUV or LogL");
+    break;
+  }
+  return (0);
+}
+
+static int
+LogLuvSetupEncode(TIFF* tif)
+{
+  LogLuvState* sp = EncoderState(tif);
+  TIFFDirectory* td = &tif->tif_dir;
+
+  switch (td->td_photometric) {
+  case PHOTOMETRIC_LOGLUV:
+    if (!LogLuvInitState(tif))
+      break;
+    if (td->td_compression == COMPRESSION_SGILOG24) {
+      tif->tif_encoderow = LogLuvEncode24;
+      switch (sp->user_datafmt) {
+      case SGILOGDATAFMT_FLOAT:
+        sp->tfunc = Luv24fromXYZ;
+        break;
+      case SGILOGDATAFMT_16BIT:
+        sp->tfunc = Luv24fromLuv48;
+        break;
+      case SGILOGDATAFMT_RAW:
+        break;
+      default:
+        goto notsupported;
+      }
+    } else {
+      tif->tif_encoderow = LogLuvEncode32;
+      switch (sp->user_datafmt) {
+      case SGILOGDATAFMT_FLOAT:
+        sp->tfunc = Luv32fromXYZ;
+        break;
+      case SGILOGDATAFMT_16BIT:
+        sp->tfunc = Luv32fromLuv48;
+        break;
+      case SGILOGDATAFMT_RAW:
+        break;
+      default:
+        goto notsupported;
+      }
+    }
+    break;
+  case PHOTOMETRIC_LOGL:
+    if (!LogL16InitState(tif))
+      break;
+    tif->tif_encoderow = LogL16Encode;
+    switch (sp->user_datafmt) {
+    case SGILOGDATAFMT_FLOAT:
+      sp->tfunc = L16fromY;
+      break;
+    case SGILOGDATAFMT_16BIT:
+      break;
+    default:
+      goto notsupported;
+    }
+    break;
+  default:
+    TIFFError(tif->tif_name,
+    "Inappropriate photometric interpretation %d for SGILog compression; %s",
+            td->td_photometric, "must be either LogLUV or LogL");
+    break;
+  }
+  return (1);
+notsupported:
+  TIFFError(tif->tif_name,
+      "SGILog compression supported only for %s, or raw data",
+      td->td_photometric == PHOTOMETRIC_LOGL ? "Y, L" : "XYZ, Luv");
+  return (0);
+}
+
+static void
+LogLuvClose(TIFF* tif)
+{
+  TIFFDirectory *td = &tif->tif_dir;
+
+  /*
+   * For consistency, we always want to write out the same
+   * bitspersample and sampleformat for our TIFF file,
+   * regardless of the data format being used by the application.
+   * Since this routine is called after tags have been set but
+   * before they have been recorded in the file, we reset them here.
+   */
+  td->td_samplesperpixel =
+      (td->td_photometric == PHOTOMETRIC_LOGL) ? 1 : 3;
+  td->td_bitspersample = 16;
+  td->td_sampleformat = SAMPLEFORMAT_INT;
+}
+
+static void
+LogLuvCleanup(TIFF* tif)
+{
+  LogLuvState* sp = (LogLuvState *)tif->tif_data;
+
+  if (sp) {
+    if (sp->tbuf)
+      _TIFFfree(sp->tbuf);
+    _TIFFfree(sp);
+    tif->tif_data = NULL;
+  }
+}
+
+static int
+LogLuvVSetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+  LogLuvState* sp = DecoderState(tif);
+  int bps, fmt;
+
+  switch (tag) {
+  case TIFFTAG_SGILOGDATAFMT:
+    sp->user_datafmt = va_arg(ap, int);
+    /*
+     * Tweak the TIFF header so that the rest of libtiff knows what
+     * size of data will be passed between app and library, and
+     * assume that the app knows what it is doing and is not
+     * confused by these header manipulations...
+     */
+    switch (sp->user_datafmt) {
+    case SGILOGDATAFMT_FLOAT:
+      bps = 32, fmt = SAMPLEFORMAT_IEEEFP;
+      break;
+    case SGILOGDATAFMT_16BIT:
+      bps = 16, fmt = SAMPLEFORMAT_INT;
+      break;
+    case SGILOGDATAFMT_RAW:
+      bps = 32, fmt = SAMPLEFORMAT_UINT;
+      TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
+      break;
+    case SGILOGDATAFMT_8BIT:
+      bps = 8, fmt = SAMPLEFORMAT_UINT;
+      break;
+    default:
+      TIFFError(tif->tif_name,
+          "Unknown data format %d for LogLuv compression",
+          sp->user_datafmt);
+      return (0);
+    }
+    TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps);
+    TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, fmt);
+    /*
+     * Must recalculate sizes should bits/sample change.
+     */
+    tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tsize_t) -1;
+    tif->tif_scanlinesize = TIFFScanlineSize(tif);
+    return (1);
+  case TIFFTAG_SGILOGENCODE:
+    sp->encode_meth = va_arg(ap, int);
+    if (sp->encode_meth != SGILOGENCODE_NODITHER &&
+        sp->encode_meth != SGILOGENCODE_RANDITHER) {
+      TIFFError(tif->tif_name,
+        "Unknown encoding %d for LogLuv compression",
+        sp->encode_meth);
+      return (0);
+    }
+    return (1);
+  default:
+    return (*sp->vsetparent)(tif, tag, ap);
+  }
+}
+
+static int
+LogLuvVGetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+  LogLuvState *sp = (LogLuvState *)tif->tif_data;
+
+  switch (tag) {
+  case TIFFTAG_SGILOGDATAFMT:
+    *va_arg(ap, int*) = sp->user_datafmt;
+    return (1);
+  default:
+    return (*sp->vgetparent)(tif, tag, ap);
+  }
+}
+
+static const TIFFFieldInfo LogLuvFieldInfo[] = {
+    { TIFFTAG_SGILOGDATAFMT,    0, 0,  TIFF_SHORT,  FIELD_PSEUDO,
+      TRUE,  FALSE,  "SGILogDataFmt"},
+    { TIFFTAG_SGILOGENCODE,    0, 0, TIFF_SHORT,  FIELD_PSEUDO,
+      TRUE,  FALSE,  "SGILogEncode"}
+};
+
+int
+TIFFInitSGILog(TIFF* tif, int scheme)
+{
+  static const char module[] = "TIFFInitSGILog";
+  LogLuvState* sp;
+
+  assert(scheme == COMPRESSION_SGILOG24 || scheme == COMPRESSION_SGILOG);
+
+  /*
+   * Allocate state block so tag methods have storage to record values.
+   */
+  tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (LogLuvState));
+  if (tif->tif_data == NULL)
+    goto bad;
+  sp = (LogLuvState*) tif->tif_data;
+  _TIFFmemset((tdata_t)sp, 0, sizeof (*sp));
+  sp->user_datafmt = SGILOGDATAFMT_UNKNOWN;
+  sp->encode_meth = (scheme == COMPRESSION_SGILOG24) ?
+        SGILOGENCODE_RANDITHER : SGILOGENCODE_NODITHER;
+  sp->tfunc = _logLuvNop;
+
+  /*
+   * Install codec methods.
+   * NB: tif_decoderow & tif_encoderow are filled
+   *     in at setup time.
+   */
+  tif->tif_setupdecode = LogLuvSetupDecode;
+  tif->tif_decodestrip = LogLuvDecodeStrip;
+  tif->tif_decodetile = LogLuvDecodeTile;
+  tif->tif_setupencode = LogLuvSetupEncode;
+  tif->tif_encodestrip = LogLuvEncodeStrip;
+  tif->tif_encodetile = LogLuvEncodeTile;
+  tif->tif_close = LogLuvClose;
+  tif->tif_cleanup = LogLuvCleanup;
+
+  /* override SetField so we can handle our private pseudo-tag */
+  _TIFFMergeFieldInfo(tif, LogLuvFieldInfo, N(LogLuvFieldInfo));
+  sp->vgetparent = tif->tif_tagmethods.vgetfield;
+  tif->tif_tagmethods.vgetfield = LogLuvVGetField;   /* hook for codec tags */
+  sp->vsetparent = tif->tif_tagmethods.vsetfield;
+  tif->tif_tagmethods.vsetfield = LogLuvVSetField;   /* hook for codec tags */
+
+  return (1);
+bad:
+  TIFFError(module, "%s: No space for LogLuv state block", tif->tif_name);
+  return (0);
+}
+#endif /* LOGLUV_SUPPORT */
+
diff --git a/Utilities/ITK/Utilities/tiff/tif_lzw.c b/Utilities/ITK/Utilities/tiff/tif_lzw.c
new file mode 100644
index 0000000000..862521acca
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_lzw.c
@@ -0,0 +1,1078 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+#include "tiffiop.h"
+#ifdef LZW_SUPPORT
+/*
+ * TIFF Library.
+ * Rev 5.0 Lempel-Ziv & Welch Compression Support
+ *
+ * This code is derived from the compress program whose code is
+ * derived from software contributed to Berkeley by James A. Woods,
+ * derived from original work by Spencer Thomas and Joseph Orost.
+ *
+ * The original Berkeley copyright notice appears below in its entirety.
+ */
+#include "tif_predict.h"
+
+#include <stdio.h>
+
+/*
+ * NB: The 5.0 spec describes a different algorithm than Aldus
+ *     implements.  Specifically, Aldus does code length transitions
+ *     one code earlier than should be done (for real LZW).
+ *     Earlier versions of this library implemented the correct
+ *     LZW algorithm, but emitted codes in a bit order opposite
+ *     to the TIFF spec.  Thus, to maintain compatibility w/ Aldus
+ *     we interpret MSB-LSB ordered codes to be images written w/
+ *     old versions of this library, but otherwise adhere to the
+ *     Aldus "off by one" algorithm.
+ *
+ * Future revisions to the TIFF spec are expected to "clarify this issue".
+ */
+#define  LZW_COMPAT    /* include backwards compatibility code */
+/*
+ * Each strip of data is supposed to be terminated by a CODE_EOI.
+ * If the following #define is included, the decoder will also
+ * check for end-of-strip w/o seeing this code.  This makes the
+ * library more robust, but also slower.
+ */
+#define  LZW_CHECKEOS    /* include checks for strips w/o EOI code */
+
+#define MAXCODE(n)  ((1L<<(n))-1)
+/*
+ * The TIFF spec specifies that encoded bit
+ * strings range from 9 to 12 bits.
+ */
+#define  BITS_MIN  9    /* start with 9 bits */
+#define  BITS_MAX  12    /* max of 12 bit strings */
+/* predefined codes */
+#define  CODE_CLEAR  256    /* code to clear string table */
+#define  CODE_EOI  257    /* end-of-information code */
+#define CODE_FIRST  258    /* first free code entry */
+#define  CODE_MAX  MAXCODE(BITS_MAX)
+#define  HSIZE    9001L    /* 91% occupancy */
+#define  HSHIFT    (13-8)
+#ifdef LZW_COMPAT
+/* NB: +1024 is for compatibility with old files */
+#define  CSIZE    (MAXCODE(BITS_MAX)+1024L)
+#else
+#define  CSIZE    (MAXCODE(BITS_MAX)+1L)
+#endif
+
+/*
+ * State block for each open TIFF file using LZW
+ * compression/decompression.  Note that the predictor
+ * state block must be first in this data structure.
+ */
+typedef  struct {
+  TIFFPredictorState predict;  /* predictor super class */
+
+  unsigned short  nbits;    /* # of bits/code */
+  unsigned short  maxcode;  /* maximum code for lzw_nbits */
+  unsigned short  free_ent;  /* next free entry in hash table */
+  long    nextdata;  /* next bits of i/o */
+  long    nextbits;  /* # of valid bits in lzw_nextdata */
+
+        int             rw_mode;        /* preserve rw_mode from init */
+} LZWBaseState;
+
+#define  lzw_nbits  base.nbits
+#define  lzw_maxcode  base.maxcode
+#define  lzw_free_ent  base.free_ent
+#define  lzw_nextdata  base.nextdata
+#define  lzw_nextbits  base.nextbits
+
+/*
+ * Encoding-specific state.
+ */
+typedef uint16 hcode_t;      /* codes fit in 16 bits */
+typedef struct {
+  long  hash;
+  hcode_t  code;
+} hash_t;
+
+/*
+ * Decoding-specific state.
+ */
+typedef struct code_ent {
+  struct code_ent *next;
+  unsigned short  length;    /* string len, including this token */
+  unsigned char  value;    /* data value */
+  unsigned char  firstchar;  /* first token of string */
+} code_t;
+
+typedef  int (*decodeFunc)(TIFF*, tidata_t, tsize_t, tsample_t);
+
+typedef struct {
+  LZWBaseState base;
+
+  /* Decoding specific data */
+  long  dec_nbitsmask;    /* lzw_nbits 1 bits, right adjusted */
+  long  dec_restart;    /* restart count */
+#ifdef LZW_CHECKEOS
+  long  dec_bitsleft;    /* available bits in raw data */
+#endif
+  decodeFunc dec_decode;    /* regular or backwards compatible */
+  code_t*  dec_codep;    /* current recognized code */
+  code_t*  dec_oldcodep;    /* previously recognized code */
+  code_t*  dec_free_entp;    /* next free entry */
+  code_t*  dec_maxcodep;    /* max available entry */
+  code_t*  dec_codetab;    /* kept separate for small machines */
+
+  /* Encoding specific data */
+  int  enc_oldcode;    /* last code encountered */
+  long  enc_checkpoint;    /* point at which to clear table */
+#define CHECK_GAP  10000    /* enc_ratio check interval */
+  long  enc_ratio;    /* current compression ratio */
+  long  enc_incount;    /* (input) data bytes encoded */
+  long  enc_outcount;    /* encoded (output) bytes */
+  tidata_t enc_rawlimit;    /* bound on tif_rawdata buffer */
+  hash_t*  enc_hashtab;    /* kept separate for small machines */
+} LZWCodecState;
+
+#define  LZWState(tif)    ((LZWBaseState*) (tif)->tif_data)
+#define  DecoderState(tif)  ((LZWCodecState*) LZWState(tif))
+#define  EncoderState(tif)  ((LZWCodecState*) LZWState(tif))
+
+static  int LZWDecode(TIFF*, tidata_t, tsize_t, tsample_t);
+#ifdef LZW_COMPAT
+static  int LZWDecodeCompat(TIFF*, tidata_t, tsize_t, tsample_t);
+#endif
+static  void cl_hash(LZWCodecState*);
+
+/*
+ * LZW Decoder.
+ */
+
+#ifdef LZW_CHECKEOS
+/*
+ * This check shouldn't be necessary because each
+ * strip is suppose to be terminated with CODE_EOI.
+ */
+#define  NextCode(_tif, _sp, _bp, _code, _get) {        \
+  if ((_sp)->dec_bitsleft < nbits) {        \
+    TIFFWarning(_tif->tif_name,        \
+        "LZWDecode: Strip %d not terminated with EOI code", \
+        _tif->tif_curstrip);        \
+    _code = CODE_EOI;          \
+  } else {              \
+    _get(_sp,_bp,_code);          \
+    (_sp)->dec_bitsleft -= nbits;        \
+  }                \
+}
+#else
+#define  NextCode(tif, sp, bp, code, get) get(sp, bp, code)
+#endif
+
+static int
+LZWSetupDecode(TIFF* tif)
+{
+  LZWCodecState* sp = DecoderState(tif);
+  static const char module[] = " LZWSetupDecode";
+  int code;
+
+        if( sp == NULL )
+        {
+            /*
+             * Allocate state block so tag methods have storage to record 
+             * values.
+             */
+            tif->tif_data = (tidata_t) _TIFFmalloc(sizeof(LZWCodecState));
+            if (tif->tif_data == NULL)
+            {
+                TIFFError("LZWPreDecode", "No space for LZW state block");
+                return (0);
+            }
+
+            DecoderState(tif)->dec_codetab = NULL;
+            DecoderState(tif)->dec_decode = NULL;
+            
+            /*
+             * Setup predictor setup.
+             */
+            (void) TIFFPredictorInit(tif);
+
+            sp = DecoderState(tif);
+        }
+            
+  assert(sp != NULL);
+
+  if (sp->dec_codetab == NULL) {
+    sp->dec_codetab = (code_t*)_TIFFmalloc(CSIZE*sizeof (code_t));
+    if (sp->dec_codetab == NULL) {
+      TIFFError(module, "No space for LZW code table");
+      return (0);
+    }
+    /*
+     * Pre-load the table.
+     */
+                code = 255;
+                do {
+                    sp->dec_codetab[code].value = code;
+                    sp->dec_codetab[code].firstchar = code;
+                    sp->dec_codetab[code].length = 1;
+                    sp->dec_codetab[code].next = NULL;
+                } while (code--);
+  }
+  return (1);
+}
+
+/*
+ * Setup state for decoding a strip.
+ */
+static int
+LZWPreDecode(TIFF* tif, tsample_t s)
+{
+  LZWCodecState *sp = DecoderState(tif);
+
+  (void) s;
+  assert(sp != NULL);
+  /*
+   * Check for old bit-reversed codes.
+   */
+  if (tif->tif_rawdata[0] == 0 && (tif->tif_rawdata[1] & 0x1)) {
+#ifdef LZW_COMPAT
+    if (!sp->dec_decode) {
+      TIFFWarning(tif->tif_name,
+          "Old-style LZW codes, convert file");
+      /*
+       * Override default decoding methods with
+       * ones that deal with the old coding.
+       * Otherwise the predictor versions set
+       * above will call the compatibility routines
+       * through the dec_decode method.
+       */
+      tif->tif_decoderow = LZWDecodeCompat;
+      tif->tif_decodestrip = LZWDecodeCompat;
+      tif->tif_decodetile = LZWDecodeCompat;
+      /*
+       * If doing horizontal differencing, must
+       * re-setup the predictor logic since we
+       * switched the basic decoder methods...
+       */
+      (*tif->tif_setupdecode)(tif);
+      sp->dec_decode = LZWDecodeCompat;
+    }
+    sp->lzw_maxcode = MAXCODE(BITS_MIN);
+#else /* !LZW_COMPAT */
+    if (!sp->dec_decode) {
+      TIFFError(tif->tif_name,
+          "Old-style LZW codes not supported");
+      sp->dec_decode = LZWDecode;
+    }
+    return (0);
+#endif/* !LZW_COMPAT */
+  } else {
+    sp->lzw_maxcode = MAXCODE(BITS_MIN)-1;
+    sp->dec_decode = LZWDecode;
+  }
+  sp->lzw_nbits = BITS_MIN;
+  sp->lzw_nextbits = 0;
+  sp->lzw_nextdata = 0;
+
+  sp->dec_restart = 0;
+  sp->dec_nbitsmask = MAXCODE(BITS_MIN);
+#ifdef LZW_CHECKEOS
+  sp->dec_bitsleft = tif->tif_rawcc << 3;
+#endif
+  sp->dec_free_entp = sp->dec_codetab + CODE_FIRST;
+  /*
+   * Zero entries that are not yet filled in.  We do
+   * this to guard against bogus input data that causes
+   * us to index into undefined entries.  If you can
+   * come up with a way to safely bounds-check input codes
+   * while decoding then you can remove this operation.
+   */
+  _TIFFmemset(sp->dec_free_entp, 0, (CSIZE-CODE_FIRST)*sizeof (code_t));
+  sp->dec_oldcodep = &sp->dec_codetab[-1];
+  sp->dec_maxcodep = &sp->dec_codetab[sp->dec_nbitsmask-1];
+  return (1);
+}
+
+/*
+ * Decode a "hunk of data".
+ */
+#define  GetNextCode(sp, bp, code) {        \
+  nextdata = (nextdata<<8) | *(bp)++;      \
+  nextbits += 8;            \
+  if (nextbits < nbits) {          \
+    nextdata = (nextdata<<8) | *(bp)++;    \
+    nextbits += 8;          \
+  }              \
+  code = (hcode_t)((nextdata >> (nextbits-nbits)) & nbitsmask);  \
+  nextbits -= nbits;          \
+}
+
+static void
+codeLoop(TIFF* tif)
+{
+  TIFFError(tif->tif_name,
+      "LZWDecode: Bogus encoding, loop in the code table; scanline %d",
+      tif->tif_row);
+}
+
+static int
+LZWDecode(TIFF* tif, tidata_t op0, tsize_t occ0, tsample_t s)
+{
+  LZWCodecState *sp = DecoderState(tif);
+  char *op = (char*) op0;
+  long occ = (long) occ0;
+  char *tp;
+  unsigned char *bp;
+  hcode_t code;
+  int len;
+  long nbits, nextbits, nextdata, nbitsmask;
+  code_t *codep, *free_entp, *maxcodep, *oldcodep;
+
+  (void) s;
+  assert(sp != NULL);
+  /*
+   * Restart interrupted output operation.
+   */
+  if (sp->dec_restart) {
+    long residue;
+
+    codep = sp->dec_codep;
+    residue = codep->length - sp->dec_restart;
+    if (residue > occ) {
+      /*
+       * Residue from previous decode is sufficient
+       * to satisfy decode request.  Skip to the
+       * start of the decoded string, place decoded
+       * values in the output buffer, and return.
+       */
+      sp->dec_restart += occ;
+      do {
+        codep = codep->next;
+      } while (--residue > occ && codep);
+      if (codep) {
+        tp = op + occ;
+        do {
+          *--tp = codep->value;
+          codep = codep->next;
+        } while (--occ && codep);
+      }
+      return (1);
+    }
+    /*
+     * Residue satisfies only part of the decode request.
+     */
+    op += residue, occ -= residue;
+    tp = op;
+    do {
+      int t;
+      --tp;
+      t = codep->value;
+      codep = codep->next;
+      *tp = t;
+    } while (--residue && codep);
+    sp->dec_restart = 0;
+  }
+
+  bp = (unsigned char *)tif->tif_rawcp;
+  nbits = sp->lzw_nbits;
+  nextdata = sp->lzw_nextdata;
+  nextbits = sp->lzw_nextbits;
+  nbitsmask = sp->dec_nbitsmask;
+  oldcodep = sp->dec_oldcodep;
+  free_entp = sp->dec_free_entp;
+  maxcodep = sp->dec_maxcodep;
+
+  while (occ > 0) {
+    NextCode(tif, sp, bp, code, GetNextCode);
+    if (code == CODE_EOI)
+      break;
+    if (code == CODE_CLEAR) {
+      free_entp = sp->dec_codetab + CODE_FIRST;
+      nbits = BITS_MIN;
+      nbitsmask = MAXCODE(BITS_MIN);
+      maxcodep = sp->dec_codetab + nbitsmask-1;
+      NextCode(tif, sp, bp, code, GetNextCode);
+      if (code == CODE_EOI)
+        break;
+      *op++ = (char)code, occ--;
+      oldcodep = sp->dec_codetab + code;
+      continue;
+    }
+    codep = sp->dec_codetab + code;
+
+    /*
+      * Add the new entry to the code table.
+      */
+    if (free_entp < &sp->dec_codetab[0] ||
+      free_entp >= &sp->dec_codetab[CSIZE]) {
+      TIFFError(tif->tif_name,
+      "LZWDecode: Corrupted LZW table at scanline %d",
+      tif->tif_row);
+      return (0);
+    }
+
+    free_entp->next = oldcodep;
+    if (free_entp->next < &sp->dec_codetab[0] ||
+      free_entp->next >= &sp->dec_codetab[CSIZE]) {
+      TIFFError(tif->tif_name,
+      "LZWDecode: Corrupted LZW table at scanline %d",
+      tif->tif_row);
+      return (0);
+    }
+    free_entp->firstchar = free_entp->next->firstchar;
+    free_entp->length = free_entp->next->length+1;
+    free_entp->value = (codep < free_entp) ?
+        codep->firstchar : free_entp->firstchar;
+    if (++free_entp > maxcodep) {
+      if (++nbits > BITS_MAX)    /* should not happen */
+        nbits = BITS_MAX;
+      nbitsmask = MAXCODE(nbits);
+      maxcodep = sp->dec_codetab + nbitsmask-1;
+    }
+    oldcodep = codep;
+    if (code >= 256) {
+      /*
+        * Code maps to a string, copy string
+       * value to output (written in reverse).
+        */
+      if(codep->length == 0) {
+          TIFFError(tif->tif_name,
+              "LZWDecode: Wrong length of decoded string: "
+          "data probably corrupted at scanline %d",
+          tif->tif_row);  
+          return (0);
+      }
+      if (codep->length > occ) {
+        /*
+         * String is too long for decode buffer,
+         * locate portion that will fit, copy to
+         * the decode buffer, and setup restart
+         * logic for the next decoding call.
+         */
+        sp->dec_codep = codep;
+        do {
+          codep = codep->next;
+        } while (codep && codep->length > occ);
+        if (codep) {
+          sp->dec_restart = occ;
+          tp = op + occ;
+          do  {
+            *--tp = codep->value;
+            codep = codep->next;
+          }  while (--occ && codep);
+          if (codep)
+            codeLoop(tif);
+        }
+        break;
+      }
+      len = codep->length;
+      tp = op + len;
+      do {
+        int t;
+        --tp;
+        t = codep->value;
+        codep = codep->next;
+        *tp = t;
+      } while (codep && tp > op);
+      if (codep) {
+          codeLoop(tif);
+          break;
+      }
+      op += len, occ -= len;
+    } else
+      *op++ = (char)code, occ--;
+  }
+
+  tif->tif_rawcp = (tidata_t) bp;
+  sp->lzw_nbits = (unsigned short) nbits;
+  sp->lzw_nextdata = nextdata;
+  sp->lzw_nextbits = nextbits;
+  sp->dec_nbitsmask = nbitsmask;
+  sp->dec_oldcodep = oldcodep;
+  sp->dec_free_entp = free_entp;
+  sp->dec_maxcodep = maxcodep;
+
+  if (occ > 0) {
+    TIFFError(tif->tif_name,
+    "LZWDecode: Not enough data at scanline %d (short %d bytes)",
+        tif->tif_row, occ);
+    return (0);
+  }
+  return (1);
+}
+
+#ifdef LZW_COMPAT
+/*
+ * Decode a "hunk of data" for old images.
+ */
+#define  GetNextCodeCompat(sp, bp, code) {      \
+  nextdata |= (unsigned long) *(bp)++ << nextbits;  \
+  nextbits += 8;            \
+  if (nextbits < nbits) {          \
+    nextdata |= (unsigned long) *(bp)++ << nextbits;\
+    nextbits += 8;          \
+  }              \
+  code = (hcode_t)(nextdata & nbitsmask);      \
+  nextdata >>= nbits;          \
+  nextbits -= nbits;          \
+}
+
+static int
+LZWDecodeCompat(TIFF* tif, tidata_t op0, tsize_t occ0, tsample_t s)
+{
+  LZWCodecState *sp = DecoderState(tif);
+  char *op = (char*) op0;
+  long occ = (long) occ0;
+  char *tp;
+  unsigned char *bp;
+  int code, nbits;
+  long nextbits, nextdata, nbitsmask;
+  code_t *codep, *free_entp, *maxcodep, *oldcodep;
+
+  (void) s;
+  assert(sp != NULL);
+  /*
+   * Restart interrupted output operation.
+   */
+  if (sp->dec_restart) {
+    long residue;
+
+    codep = sp->dec_codep;
+    residue = codep->length - sp->dec_restart;
+    if (residue > occ) {
+      /*
+       * Residue from previous decode is sufficient
+       * to satisfy decode request.  Skip to the
+       * start of the decoded string, place decoded
+       * values in the output buffer, and return.
+       */
+      sp->dec_restart += occ;
+      do {
+        codep = codep->next;
+      } while (--residue > occ);
+      tp = op + occ;
+      do {
+        *--tp = codep->value;
+        codep = codep->next;
+      } while (--occ);
+      return (1);
+    }
+    /*
+     * Residue satisfies only part of the decode request.
+     */
+    op += residue, occ -= residue;
+    tp = op;
+    do {
+      *--tp = codep->value;
+      codep = codep->next;
+    } while (--residue);
+    sp->dec_restart = 0;
+  }
+
+  bp = (unsigned char *)tif->tif_rawcp;
+  nbits = sp->lzw_nbits;
+  nextdata = sp->lzw_nextdata;
+  nextbits = sp->lzw_nextbits;
+  nbitsmask = sp->dec_nbitsmask;
+  oldcodep = sp->dec_oldcodep;
+  free_entp = sp->dec_free_entp;
+  maxcodep = sp->dec_maxcodep;
+
+  while (occ > 0) {
+    NextCode(tif, sp, bp, code, GetNextCodeCompat);
+    if (code == CODE_EOI)
+      break;
+    if (code == CODE_CLEAR) {
+      free_entp = sp->dec_codetab + CODE_FIRST;
+      nbits = BITS_MIN;
+      nbitsmask = MAXCODE(BITS_MIN);
+      maxcodep = sp->dec_codetab + nbitsmask;
+      NextCode(tif, sp, bp, code, GetNextCodeCompat);
+      if (code == CODE_EOI)
+        break;
+      *op++ = code, occ--;
+      oldcodep = sp->dec_codetab + code;
+      continue;
+    }
+    codep = sp->dec_codetab + code;
+
+    /*
+      * Add the new entry to the code table.
+      */
+    if (free_entp < &sp->dec_codetab[0] ||
+      free_entp >= &sp->dec_codetab[CSIZE]) {
+      TIFFError(tif->tif_name,
+      "LZWDecodeCompat: Corrupted LZW table at scanline %d",
+      tif->tif_row);
+      return (0);
+    }
+
+    free_entp->next = oldcodep;
+    if (free_entp->next < &sp->dec_codetab[0] ||
+      free_entp->next >= &sp->dec_codetab[CSIZE]) {
+      TIFFError(tif->tif_name,
+      "LZWDecodeCompat: Corrupted LZW table at scanline %d",
+      tif->tif_row);
+      return (0);
+    }
+    free_entp->firstchar = free_entp->next->firstchar;
+    free_entp->length = free_entp->next->length+1;
+    free_entp->value = (codep < free_entp) ?
+        codep->firstchar : free_entp->firstchar;
+    if (++free_entp > maxcodep) {
+      if (++nbits > BITS_MAX)    /* should not happen */
+        nbits = BITS_MAX;
+      nbitsmask = MAXCODE(nbits);
+      maxcodep = sp->dec_codetab + nbitsmask;
+    }
+    oldcodep = codep;
+    if (code >= 256) {
+      /*
+        * Code maps to a string, copy string
+       * value to output (written in reverse).
+        */
+      if(codep->length == 0) {
+          TIFFError(tif->tif_name,
+              "LZWDecodeCompat: Wrong length of decoded "
+          "string: data probably corrupted at scanline %d",
+          tif->tif_row);  
+          return (0);
+      }
+      if (codep->length > occ) {
+        /*
+         * String is too long for decode buffer,
+         * locate portion that will fit, copy to
+         * the decode buffer, and setup restart
+         * logic for the next decoding call.
+         */
+        sp->dec_codep = codep;
+        do {
+          codep = codep->next;
+        } while (codep->length > occ);
+        sp->dec_restart = occ;
+        tp = op + occ;
+        do  {
+          *--tp = codep->value;
+          codep = codep->next;
+        }  while (--occ);
+        break;
+      }
+      op += codep->length, occ -= codep->length;
+      tp = op;
+      do {
+        *--tp = codep->value;
+      } while( (codep = codep->next) != NULL);
+    } else
+      *op++ = code, occ--;
+  }
+
+  tif->tif_rawcp = (tidata_t) bp;
+  sp->lzw_nbits = nbits;
+  sp->lzw_nextdata = nextdata;
+  sp->lzw_nextbits = nextbits;
+  sp->dec_nbitsmask = nbitsmask;
+  sp->dec_oldcodep = oldcodep;
+  sp->dec_free_entp = free_entp;
+  sp->dec_maxcodep = maxcodep;
+
+  if (occ > 0) {
+    TIFFError(tif->tif_name,
+      "LZWDecodeCompat: Not enough data at scanline %d (short %d bytes)",
+        tif->tif_row, occ);
+    return (0);
+  }
+  return (1);
+}
+#endif /* LZW_COMPAT */
+
+/*
+ * LZW Encoding.
+ */
+
+static int
+LZWSetupEncode(TIFF* tif)
+{
+  LZWCodecState* sp = EncoderState(tif);
+  static const char module[] = "LZWSetupEncode";
+
+  assert(sp != NULL);
+  sp->enc_hashtab = (hash_t*) _TIFFmalloc(HSIZE*sizeof (hash_t));
+  if (sp->enc_hashtab == NULL) {
+    TIFFError(module, "No space for LZW hash table");
+    return (0);
+  }
+  return (1);
+}
+
+/*
+ * Reset encoding state at the start of a strip.
+ */
+static int
+LZWPreEncode(TIFF* tif, tsample_t s)
+{
+  LZWCodecState *sp = EncoderState(tif);
+
+  (void) s;
+  assert(sp != NULL);
+  sp->lzw_nbits = BITS_MIN;
+  sp->lzw_maxcode = MAXCODE(BITS_MIN);
+  sp->lzw_free_ent = CODE_FIRST;
+  sp->lzw_nextbits = 0;
+  sp->lzw_nextdata = 0;
+  sp->enc_checkpoint = CHECK_GAP;
+  sp->enc_ratio = 0;
+  sp->enc_incount = 0;
+  sp->enc_outcount = 0;
+  /*
+   * The 4 here insures there is space for 2 max-sized
+   * codes in LZWEncode and LZWPostDecode.
+   */
+  sp->enc_rawlimit = tif->tif_rawdata + tif->tif_rawdatasize-1 - 4;
+  cl_hash(sp);    /* clear hash table */
+  sp->enc_oldcode = (hcode_t) -1;  /* generates CODE_CLEAR in LZWEncode */
+  return (1);
+}
+
+#define  CALCRATIO(sp, rat) {          \
+  if (incount > 0x007fffff) { /* NB: shift will overflow */\
+    rat = outcount >> 8;        \
+    rat = (rat == 0 ? 0x7fffffff : incount/rat);  \
+  } else              \
+    rat = (incount<<8) / outcount;      \
+}
+#define  PutNextCode(op, c) {          \
+  nextdata = (nextdata << nbits) | c;      \
+  nextbits += nbits;          \
+  *op++ = (unsigned char)(nextdata >> (nextbits-8));    \
+  nextbits -= 8;            \
+  if (nextbits >= 8) {          \
+    *op++ = (unsigned char)(nextdata >> (nextbits-8));  \
+    nextbits -= 8;          \
+  }              \
+  outcount += nbits;          \
+}
+
+/*
+ * Encode a chunk of pixels.
+ *
+ * Uses an open addressing double hashing (no chaining) on the 
+ * prefix code/next character combination.  We do a variant of
+ * Knuth's algorithm D (vol. 3, sec. 6.4) along with G. Knott's
+ * relatively-prime secondary probe.  Here, the modular division
+ * first probe is gives way to a faster exclusive-or manipulation. 
+ * Also do block compression with an adaptive reset, whereby the
+ * code table is cleared when the compression ratio decreases,
+ * but after the table fills.  The variable-length output codes
+ * are re-sized at this point, and a CODE_CLEAR is generated
+ * for the decoder. 
+ */
+static int
+LZWEncode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
+{
+  register LZWCodecState *sp = EncoderState(tif);
+  register long fcode;
+  register hash_t *hp;
+  register int h, c;
+  hcode_t ent;
+  long disp;
+  long incount, outcount, checkpoint;
+  long nextdata, nextbits;
+  int free_ent, maxcode, nbits;
+  tidata_t op, limit;
+
+  (void) s;
+  if (sp == NULL)
+    return (0);
+  /*
+   * Load local state.
+   */
+  incount = sp->enc_incount;
+  outcount = sp->enc_outcount;
+  checkpoint = sp->enc_checkpoint;
+  nextdata = sp->lzw_nextdata;
+  nextbits = sp->lzw_nextbits;
+  free_ent = sp->lzw_free_ent;
+  maxcode = sp->lzw_maxcode;
+  nbits = sp->lzw_nbits;
+  op = tif->tif_rawcp;
+  limit = sp->enc_rawlimit;
+  ent = sp->enc_oldcode;
+
+  if (ent == (hcode_t) -1 && cc > 0) {
+    /*
+     * NB: This is safe because it can only happen
+     *     at the start of a strip where we know there
+     *     is space in the data buffer.
+     */
+    PutNextCode(op, CODE_CLEAR);
+    ent = *bp++; cc--; incount++;
+  }
+  while (cc > 0) {
+    c = *bp++; cc--; incount++;
+    fcode = ((long)c << BITS_MAX) + ent;
+    h = (c << HSHIFT) ^ ent;  /* xor hashing */
+#ifdef _WINDOWS
+    /*
+     * Check hash index for an overflow.
+     */
+    if (h >= HSIZE)
+      h -= HSIZE;
+#endif
+    hp = &sp->enc_hashtab[h];
+    if (hp->hash == fcode) {
+      ent = hp->code;
+      continue;
+    }
+    if (hp->hash >= 0) {
+      /*
+       * Primary hash failed, check secondary hash.
+       */
+      disp = HSIZE - h;
+      if (h == 0)
+        disp = 1;
+      do {
+        /*
+         * Avoid pointer arithmetic 'cuz of
+         * wraparound problems with segments.
+         */
+        if ((h -= disp) < 0)
+          h += HSIZE;
+        hp = &sp->enc_hashtab[h];
+        if (hp->hash == fcode) {
+          ent = hp->code;
+          goto hit;
+        }
+      } while (hp->hash >= 0);
+    }
+    /*
+     * New entry, emit code and add to table.
+     */
+    /*
+     * Verify there is space in the buffer for the code
+     * and any potential Clear code that might be emitted
+     * below.  The value of limit is setup so that there
+     * are at least 4 bytes free--room for 2 codes.
+     */
+    if (op > limit) {
+      tif->tif_rawcc = (tsize_t)(op - tif->tif_rawdata);
+      TIFFFlushData1(tif);
+      op = tif->tif_rawdata;
+    }
+    PutNextCode(op, ent);
+    ent = c;
+    hp->code = free_ent++;
+    hp->hash = fcode;
+    if (free_ent == CODE_MAX-1) {
+      /* table is full, emit clear code and reset */
+      cl_hash(sp);
+      sp->enc_ratio = 0;
+      incount = 0;
+      outcount = 0;
+      free_ent = CODE_FIRST;
+      PutNextCode(op, CODE_CLEAR);
+      nbits = BITS_MIN;
+      maxcode = MAXCODE(BITS_MIN);
+    } else {
+      /*
+       * If the next entry is going to be too big for
+       * the code size, then increase it, if possible.
+       */
+      if (free_ent > maxcode) {
+        nbits++;
+        assert(nbits <= BITS_MAX);
+        maxcode = (int) MAXCODE(nbits);
+      } else if (incount >= checkpoint) {
+        long rat;
+        /*
+         * Check compression ratio and, if things seem
+         * to be slipping, clear the hash table and
+         * reset state.  The compression ratio is a
+         * 24+8-bit fractional number.
+         */
+        checkpoint = incount+CHECK_GAP;
+        CALCRATIO(sp, rat);
+        if (rat <= sp->enc_ratio) {
+          cl_hash(sp);
+          sp->enc_ratio = 0;
+          incount = 0;
+          outcount = 0;
+          free_ent = CODE_FIRST;
+          PutNextCode(op, CODE_CLEAR);
+          nbits = BITS_MIN;
+          maxcode = MAXCODE(BITS_MIN);
+        } else
+          sp->enc_ratio = rat;
+      }
+    }
+  hit:
+    ;
+  }
+
+  /*
+   * Restore global state.
+   */
+  sp->enc_incount = incount;
+  sp->enc_outcount = outcount;
+  sp->enc_checkpoint = checkpoint;
+  sp->enc_oldcode = ent;
+  sp->lzw_nextdata = nextdata;
+  sp->lzw_nextbits = nextbits;
+  sp->lzw_free_ent = free_ent;
+  sp->lzw_maxcode = maxcode;
+  sp->lzw_nbits = nbits;
+  tif->tif_rawcp = op;
+  return (1);
+}
+
+/*
+ * Finish off an encoded strip by flushing the last
+ * string and tacking on an End Of Information code.
+ */
+static int
+LZWPostEncode(TIFF* tif)
+{
+  register LZWCodecState *sp = EncoderState(tif);
+  tidata_t op = tif->tif_rawcp;
+  long nextbits = sp->lzw_nextbits;
+  long nextdata = sp->lzw_nextdata;
+  long outcount = sp->enc_outcount;
+  int nbits = sp->lzw_nbits;
+
+  if (op > sp->enc_rawlimit) {
+    tif->tif_rawcc = (tsize_t)(op - tif->tif_rawdata);
+    TIFFFlushData1(tif);
+    op = tif->tif_rawdata;
+  }
+  if (sp->enc_oldcode != (hcode_t) -1) {
+    PutNextCode(op, sp->enc_oldcode);
+    sp->enc_oldcode = (hcode_t) -1;
+  }
+  PutNextCode(op, CODE_EOI);
+  if (nextbits > 0) 
+    *op++ = (unsigned char)(nextdata << (8-nextbits));
+  tif->tif_rawcc = (tsize_t)(op - tif->tif_rawdata);
+  return (1);
+}
+
+/*
+ * Reset encoding hash table.
+ */
+static void
+cl_hash(LZWCodecState* sp)
+{
+  register hash_t *hp = &sp->enc_hashtab[HSIZE-1];
+  register long i = HSIZE-8;
+
+   do {
+    i -= 8;
+    hp[-7].hash = -1;
+    hp[-6].hash = -1;
+    hp[-5].hash = -1;
+    hp[-4].hash = -1;
+    hp[-3].hash = -1;
+    hp[-2].hash = -1;
+    hp[-1].hash = -1;
+    hp[ 0].hash = -1;
+    hp -= 8;
+  } while (i >= 0);
+      for (i += 8; i > 0; i--, hp--)
+    hp->hash = -1;
+}
+
+static void
+LZWCleanup(TIFF* tif)
+{
+  if (tif->tif_data) {
+    if (DecoderState(tif)->dec_codetab)
+      _TIFFfree(DecoderState(tif)->dec_codetab);
+
+    if (EncoderState(tif)->enc_hashtab)
+      _TIFFfree(EncoderState(tif)->enc_hashtab);
+
+    _TIFFfree(tif->tif_data);
+    tif->tif_data = NULL;
+  }
+}
+
+int
+TIFFInitLZW(TIFF* tif, int scheme)
+{
+  assert(scheme == COMPRESSION_LZW);
+  /*
+   * Allocate state block so tag methods have storage to record values.
+   */
+  tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (LZWCodecState));
+  if (tif->tif_data == NULL)
+    goto bad;
+  DecoderState(tif)->dec_codetab = NULL;
+  DecoderState(tif)->dec_decode = NULL;
+  EncoderState(tif)->enc_hashtab = NULL;
+        LZWState(tif)->rw_mode = tif->tif_mode;
+
+  /*
+   * Install codec methods.
+   */
+  tif->tif_setupdecode = LZWSetupDecode;
+  tif->tif_predecode = LZWPreDecode;
+  tif->tif_decoderow = LZWDecode;
+  tif->tif_decodestrip = LZWDecode;
+  tif->tif_decodetile = LZWDecode;
+  tif->tif_setupencode = LZWSetupEncode;
+  tif->tif_preencode = LZWPreEncode;
+  tif->tif_postencode = LZWPostEncode;
+  tif->tif_encoderow = LZWEncode;
+  tif->tif_encodestrip = LZWEncode;
+  tif->tif_encodetile = LZWEncode;
+  tif->tif_cleanup = LZWCleanup;
+  /*
+   * Setup predictor setup.
+   */
+  (void) TIFFPredictorInit(tif);
+  return (1);
+bad:
+  TIFFError("TIFFInitLZW", "No space for LZW state block");
+  return (0);
+}
+
+/*
+ * Copyright (c) 1985, 1986 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * James A. Woods, derived from original work by Spencer Thomas
+ * and Joseph Orost.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#endif /* LZW_SUPPORT */
+
diff --git a/Utilities/ITK/Utilities/tiff/tif_msdos.c b/Utilities/ITK/Utilities/tiff/tif_msdos.c
new file mode 100644
index 0000000000..ff4ab9a7ba
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_msdos.c
@@ -0,0 +1,179 @@
+/* $Header: /cvsroot/Insight/Insight/Utilities/tiff/tif_msdos.c,v 1.3 2005/09/16 19:59:08 jjomier Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library MSDOS-specific Routines.
+ */
+#if defined(__WATCOMC__) || defined(__BORLANDC__) || defined(_MSC_VER)
+#include <io.h>    /* for open, close, etc. function prototypes */
+#include <stdio.h>
+#endif
+#include "tiffiop.h"
+
+static tsize_t 
+_tiffReadProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+  return (read((int) fd, buf, size));
+}
+
+static tsize_t
+_tiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+  return (write((int) fd, buf, size));
+}
+
+static toff_t
+_tiffSeekProc(thandle_t fd, toff_t off, int whence)
+{
+  return (lseek((int) fd, (off_t) off, whence));
+}
+
+static int
+_tiffCloseProc(thandle_t fd)
+{
+  return (close((int) fd));
+}
+
+#include <sys/stat.h>
+
+static toff_t
+_tiffSizeProc(thandle_t fd)
+{
+  struct stat sb;
+  return (fstat((int) fd, &sb) < 0 ? 0 : sb.st_size);
+}
+
+static int
+_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
+{
+  return (0);
+}
+
+static void
+_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size)
+{
+}
+
+/*
+ * Open a TIFF file descriptor for read/writing.
+ */
+TIFF*
+TIFFFdOpen(int fd, const char* name, const char* mode)
+{
+  TIFF* tif;
+
+  tif = TIFFClientOpen(name, mode,
+      (void*) fd,
+      _tiffReadProc, _tiffWriteProc, _tiffSeekProc, _tiffCloseProc,
+      _tiffSizeProc, _tiffMapProc, _tiffUnmapProc);
+  if (tif)
+    tif->tif_fd = fd;
+  return (tif);
+}
+
+/*
+ * Open a TIFF file for read/writing.
+ */
+TIFF*
+TIFFOpen(const char* name, const char* mode)
+{
+  static const char module[] = "TIFFOpen";
+  int m, fd;
+
+  m = _TIFFgetMode(mode, module);
+  if (m == -1)
+    return ((TIFF*)0);
+  fd = open(name, m|O_BINARY, 0666);
+  if (fd < 0) {
+    TIFFError(module, "%s: Cannot open", name);
+    return ((TIFF*)0);
+  }
+  return (TIFFFdOpen(fd, name, mode));
+}
+
+#ifdef __GNUC__
+extern  char* malloc();
+extern  char* realloc();
+#else
+#include <malloc.h>
+#endif
+
+tdata_t
+_TIFFmalloc(tsize_t s)
+{
+  return (malloc((size_t) s));
+}
+
+void
+_TIFFfree(tdata_t p)
+{
+  free(p);
+}
+
+tdata_t
+_TIFFrealloc(tdata_t p, tsize_t s)
+{
+  return (realloc(p, (size_t) s));
+}
+
+void
+_TIFFmemset(tdata_t p, int v, tsize_t c)
+{
+  memset(p, v, (size_t) c);
+}
+
+void
+_TIFFmemcpy(tdata_t d, const tdata_t s, tsize_t c)
+{
+  memcpy(d, s, (size_t) c);
+}
+
+int
+_TIFFmemcmp(const tdata_t p1, const tdata_t p2, tsize_t c)
+{
+  return (memcmp(p1, p2, (size_t) c));
+}
+
+static void
+msdosWarningHandler(const char* module, const char* fmt, va_list ap)
+{
+  if (module != NULL)
+    fprintf(stderr, "%s: ", module);
+  fprintf(stderr, "Warning, ");
+  vfprintf(stderr, fmt, ap);
+  fprintf(stderr, ".\n");
+}
+TIFFErrorHandler _TIFFwarningHandler = msdosWarningHandler;
+
+static void
+msdosErrorHandler(const char* module, const char* fmt, va_list ap)
+{
+  if (module != NULL)
+    fprintf(stderr, "%s: ", module);
+  vfprintf(stderr, fmt, ap);
+  fprintf(stderr, ".\n");
+}
+TIFFErrorHandler _TIFFerrorHandler = msdosErrorHandler;
diff --git a/Utilities/ITK/Utilities/tiff/tif_next.c b/Utilities/ITK/Utilities/tiff/tif_next.c
new file mode 100644
index 0000000000..e384180d24
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_next.c
@@ -0,0 +1,143 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+#include "tiffiop.h"
+#ifdef NEXT_SUPPORT
+/*
+ * TIFF Library.
+ *
+ * NeXT 2-bit Grey Scale Compression Algorithm Support
+ */
+
+#define SETPIXEL(op, v) {      \
+  switch (npixels++ & 3) {    \
+  case 0:  op[0]  = (unsigned char) ((v) << 6); break;  \
+  case 1:  op[0] |= (v) << 4; break;  \
+  case 2:  op[0] |= (v) << 2; break;  \
+  case 3:  *op++ |= (v);     break;  \
+  }          \
+}
+
+#define LITERALROW  0x00
+#define LITERALSPAN  0x40
+#define WHITE     ((1<<2)-1)
+
+static int
+NeXTDecode(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s)
+{
+  register unsigned char *bp, *op;
+  register tsize_t cc;
+  register int n;
+  tidata_t row;
+  tsize_t scanline;
+
+  (void) s;
+  /*
+   * Each scanline is assumed to start off as all
+   * white (we assume a PhotometricInterpretation
+   * of ``min-is-black'').
+   */
+  for (op = buf, cc = occ; cc-- > 0;)
+    *op++ = 0xff;
+
+  bp = (unsigned char *)tif->tif_rawcp;
+  cc = tif->tif_rawcc;
+  scanline = tif->tif_scanlinesize;
+  for (row = buf; (long)occ > 0; occ -= scanline, row += scanline) {
+    n = *bp++, cc--;
+    switch (n) {
+    case LITERALROW:
+      /*
+       * The entire scanline is given as literal values.
+       */
+      if (cc < scanline)
+        goto bad;
+      _TIFFmemcpy(row, bp, scanline);
+      bp += scanline;
+      cc -= scanline;
+      break;
+    case LITERALSPAN: {
+      int off;
+      /*
+       * The scanline has a literal span
+       * that begins at some offset.
+       */
+      off = (bp[0] * 256) + bp[1];
+      n = (bp[2] * 256) + bp[3];
+      if (cc < 4+n || off+n > scanline)
+        goto bad;
+      _TIFFmemcpy(row+off, bp+4, n);
+      bp += 4+n;
+      cc -= 4+n;
+      break;
+    }
+    default: {
+      register int npixels = 0, grey;
+      unsigned long imagewidth = tif->tif_dir.td_imagewidth;
+
+      /*
+       * The scanline is composed of a sequence
+       * of constant color ``runs''.  We shift
+       * into ``run mode'' and interpret bytes
+       * as codes of the form <color><npixels>
+       * until we've filled the scanline.
+       */
+      op = row;
+      for (;;) {
+        grey = (n>>6) & 0x3;
+        n &= 0x3f;
+        while (n-- > 0)
+          SETPIXEL(op, grey);
+        if (npixels >= (int) imagewidth)
+          break;
+        if (cc == 0)
+          goto bad;
+        n = *bp++, cc--;
+      }
+      break;
+    }
+    }
+  }
+  tif->tif_rawcp = (tidata_t) bp;
+  tif->tif_rawcc = cc;
+  return (1);
+bad:
+  TIFFError(tif->tif_name, "NeXTDecode: Not enough data for scanline %ld",
+      (long) tif->tif_row);
+  return (0);
+}
+
+int
+TIFFInitNeXT(TIFF* tif, int scheme)
+{
+  (void) scheme;
+  tif->tif_decoderow = NeXTDecode;
+  tif->tif_decodestrip = NeXTDecode;
+  tif->tif_decodetile = NeXTDecode;
+  return (1);
+}
+#endif /* NEXT_SUPPORT */
+
diff --git a/Utilities/ITK/Utilities/tiff/tif_ojpeg.c b/Utilities/ITK/Utilities/tiff/tif_ojpeg.c
new file mode 100644
index 0000000000..43a54a02ea
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_ojpeg.c
@@ -0,0 +1,2640 @@
+/* $Id$ */
+
+#include "tiffiop.h"
+#ifdef OJPEG_SUPPORT
+
+/* JPEG Compression support, as per the original TIFF 6.0 specification.
+
+   WARNING: KLUDGE ALERT!  The type of JPEG encapsulation defined by the TIFF
+                           Version 6.0 specification is now totally obsolete and
+   deprecated for new applications and images.  This file is an unsupported hack
+   that was created solely in order to read (but NOT write!) a few old,
+   unconverted images still present on some users' computer systems.  The code
+   isn't pretty or robust, and it won't read every "old format" JPEG-in-TIFF
+   file (see Samuel Leffler's draft "TIFF Technical Note No. 2" for a long and
+   incomplete list of known problems), but it seems to work well enough in the
+   few cases of practical interest to the author; so, "caveat emptor"!  This
+   file should NEVER be enhanced to write new images using anything other than
+   the latest approved JPEG-in-TIFF encapsulation method, implemented by the
+   "tif_jpeg.c" file elsewhere in this library.
+
+   This file interfaces with Release 6B of the JPEG Library written by theu
+   Independent JPEG Group, which you can find on the Internet at:
+   ftp://ftp.uu.net:/graphics/jpeg/.
+
+   The "C" Preprocessor macros, "[CD]_LOSSLESS_SUPPORTED", are defined by your
+   JPEG Library Version 6B only if you have applied a (massive!) patch by Ken
+   Murchison of Oceana Matrix Ltd. <ken@oceana.com> to support lossless Huffman
+   encoding (TIFF "JPEGProc" tag value = 14).  This patch can be found on the
+   Internet at: ftp://ftp.oceana.com/pub/ljpeg-6b.tar.gz.
+
+   Some old files produced by the Wang Imaging application for Microsoft Windows
+   apparently can be decoded only with a special patch to the JPEG Library,
+   which defines a subroutine named "jpeg_reset_huff_decode()" in its "jdhuff.c"
+   module (the "jdshuff.c" module, if Ken Murchison's patch has been applied).
+   Unfortunately the patch differs slightly in each case, and some TIFF Library
+   have reported problems finding the code, so both versions appear below; you
+   should carefully extract and apply only the version that applies to your JPEG
+   Library!
+
+   Contributed by Scott Marovich <marovich@hpl.hp.com> with considerable help
+   from Charles Auer <Bumble731@msn.com> to unravel the mysteries of image files
+   created by the Wang Imaging application for Microsoft Windows.
+*/
+#if 0  /* Patch for JPEG Library WITHOUT lossless Huffman coding */
+*** jdhuff.c.orig  Mon Oct 20 17:51:10 1997
+--- jdhuff.c  Sun Nov 11 17:33:58 2001
+***************
+*** 648,651 ****
+--- 648,683 ----
+    for (i = 0; i < NUM_HUFF_TBLS; i++) {
+      entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL;
+    }
+  }
++ 
++ /*
++  * BEWARE OF KLUDGE:  This subroutine is a hack for decoding illegal JPEG-in-
++  *                    TIFF encapsulations produced by Microsoft's Wang Imaging
++  * for Windows application with the public-domain TIFF Library.  Based upon an
++  * examination of selected output files, this program apparently divides a JPEG
++  * bit-stream into consecutive horizontal TIFF "strips", such that the JPEG
++  * encoder's/decoder's DC coefficients for each image component are reset before
++  * each "strip".  Moreover, a "strip" is not necessarily encoded in a multiple
++  * of 8 bits, so one must sometimes discard 1-7 bits at the end of each "strip"
++  * for alignment to the next input-Byte storage boundary.  IJG JPEG Library
++  * decoder state is not normally exposed to client applications, so this sub-
++  * routine provides the TIFF Library with a "hook" to make these corrections.
++  * It should be called after "jpeg_start_decompress()" and before
++  * "jpeg_finish_decompress()", just before decoding each "strip" using
++  * "jpeg_read_raw_data()" or "jpeg_read_scanlines()".
++  *
++  * This kludge is not sanctioned or supported by the Independent JPEG Group, and
++  * future changes to the IJG JPEG Library might invalidate it.  Do not send bug
++  * reports about this code to IJG developers.  Instead, contact the author for
++  * advice: Scott B. Marovich <marovich@hpl.hp.com>, Hewlett-Packard Labs, 6/01.
++  */
++ GLOBAL(void)
++ jpeg_reset_huff_decode (register j_decompress_ptr cinfo)
++ { register huff_entropy_ptr entropy = (huff_entropy_ptr)cinfo->entropy;
++   register int ci = 0;
++ 
++   /* Discard encoded input bits, up to the next Byte boundary */
++   entropy->bitstate.bits_left &= ~7;
++   /* Re-initialize DC predictions to 0 */
++   do entropy->saved.last_dc_val[ci] = 0; while (++ci < cinfo->comps_in_scan);
++ }
+#endif /* Patch for JPEG Library WITHOUT lossless Huffman coding */
+#if 0  /* Patch for JPEG Library WITH lossless Huffman coding */
+*** jdshuff.c.orig  Mon Mar 11 16:44:54 2002
+--- jdshuff.c  Mon Mar 11 16:44:54 2002
+***************
+*** 357,360 ****
+--- 357,393 ----
+    for (i = 0; i < NUM_HUFF_TBLS; i++) {
+      entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL;
+    }
+  }
++ 
++ /*
++  * BEWARE OF KLUDGE:  This subroutine is a hack for decoding illegal JPEG-in-
++  *                    TIFF encapsulations produced by Microsoft's Wang Imaging
++  * for Windows application with the public-domain TIFF Library.  Based upon an
++  * examination of selected output files, this program apparently divides a JPEG
++  * bit-stream into consecutive horizontal TIFF "strips", such that the JPEG
++  * encoder's/decoder's DC coefficients for each image component are reset before
++  * each "strip".  Moreover, a "strip" is not necessarily encoded in a multiple
++  * of 8 bits, so one must sometimes discard 1-7 bits at the end of each "strip"
++  * for alignment to the next input-Byte storage boundary.  IJG JPEG Library
++  * decoder state is not normally exposed to client applications, so this sub-
++  * routine provides the TIFF Library with a "hook" to make these corrections.
++  * It should be called after "jpeg_start_decompress()" and before
++  * "jpeg_finish_decompress()", just before decoding each "strip" using
++  * "jpeg_read_raw_data()" or "jpeg_read_scanlines()".
++  *
++  * This kludge is not sanctioned or supported by the Independent JPEG Group, and
++  * future changes to the IJG JPEG Library might invalidate it.  Do not send bug
++  * reports about this code to IJG developers.  Instead, contact the author for
++  * advice: Scott B. Marovich <marovich@hpl.hp.com>, Hewlett-Packard Labs, 6/01.
++  */
++ GLOBAL(void)
++ jpeg_reset_huff_decode (register j_decompress_ptr cinfo)
++ { register shuff_entropy_ptr entropy = (shuff_entropy_ptr)
++                                        ((j_lossy_d_ptr)cinfo->codec)->entropy_private;
++   register int ci = 0;
++ 
++   /* Discard encoded input bits, up to the next Byte boundary */
++   entropy->bitstate.bits_left &= ~7;
++   /* Re-initialize DC predictions to 0 */
++   do entropy->saved.last_dc_val[ci] = 0; while (++ci < cinfo->comps_in_scan);
++ }
+#endif /* Patch for JPEG Library WITH lossless Huffman coding */
+#include <setjmp.h>
+#include <stdio.h>
+#ifdef FAR
+#undef FAR /* Undefine FAR to avoid conflict with JPEG definition */
+#endif
+#define JPEG_INTERNALS /* Include "jpegint.h" for "DSTATE_*" symbols */
+#define JPEG_CJPEG_DJPEG /* Include all Version 6B+ "jconfig.h" options */
+#undef INLINE
+#include "jpeglib.h"
+#undef JPEG_CJPEG_DJPEG
+#undef JPEG_INTERNALS
+
+/* Hack for files produced by Wang Imaging application on Microsoft Windows */
+extern void jpeg_reset_huff_decode(j_decompress_ptr);
+
+/* On some machines, it may be worthwhile to use "_setjmp()" or "sigsetjmp()"
+   instead of "setjmp()".  These macros make it easier:
+*/
+#define SETJMP(jbuf)setjmp(jbuf)
+#define LONGJMP(jbuf,code)longjmp(jbuf,code)
+#define JMP_BUF jmp_buf
+
+#define TIFFTAG_WANG_PAGECONTROL 32934
+
+/* Bit-vector offsets for keeping track of TIFF records that we've parsed. */
+
+#define FIELD_JPEGPROC FIELD_CODEC
+#define FIELD_JPEGIFOFFSET (FIELD_CODEC+1)
+#define FIELD_JPEGIFBYTECOUNT (FIELD_CODEC+2)
+#define FIELD_JPEGRESTARTINTERVAL (FIELD_CODEC+3)
+#define FIELD_JPEGTABLES (FIELD_CODEC+4) /* New, post-6.0 JPEG-in-TIFF tag! */
+#define FIELD_JPEGLOSSLESSPREDICTORS (FIELD_CODEC+5)
+#define FIELD_JPEGPOINTTRANSFORM (FIELD_CODEC+6)
+#define FIELD_JPEGQTABLES (FIELD_CODEC+7)
+#define FIELD_JPEGDCTABLES (FIELD_CODEC+8)
+#define FIELD_JPEGACTABLES (FIELD_CODEC+9)
+#define FIELD_WANG_PAGECONTROL (FIELD_CODEC+10)
+#define FIELD_JPEGCOLORMODE (FIELD_CODEC+11)
+
+typedef struct jpeg_destination_mgr jpeg_destination_mgr;
+typedef struct jpeg_source_mgr jpeg_source_mgr;
+typedef struct jpeg_error_mgr jpeg_error_mgr;
+
+/* State variable for each open TIFF file that uses "libjpeg" for JPEG
+   decompression.  (Note:  This file should NEVER perform JPEG compression
+   except in the manner implemented by the "tif_jpeg.c" file, elsewhere in this
+   library; see comments above.)  JPEG Library internal state is recorded in a
+   "jpeg_{de}compress_struct", while a "jpeg_common_struct" records a few items
+   common to both compression and expansion.  The "cinfo" field containing JPEG
+   Library state MUST be the 1st member of our own state variable, so that we
+   can safely "cast" pointers back and forth.
+*/
+typedef struct             /* This module's private, per-image state variable */
+  {
+    union         /* JPEG Library state variable; this MUST be our 1st field! */
+      {
+        struct jpeg_compress_struct c;
+        struct jpeg_decompress_struct d;
+        struct jpeg_common_struct comm;
+      } cinfo;
+    jpeg_error_mgr err;                         /* JPEG Library error manager */
+    JMP_BUF exit_jmpbuf;             /* ...for catching JPEG Library failures */
+#   ifdef never
+
+ /* (The following two fields could be a "union", but they're small enough that
+    it's not worth the effort.)
+ */
+    jpeg_destination_mgr dest;             /* Destination for compressed data */
+#   endif
+    jpeg_source_mgr src;                           /* Source of expanded data */
+    JSAMPARRAY ds_buffer[MAX_COMPONENTS]; /* ->Temporary downsampling buffers */
+    TIFF *tif;                        /* Reverse pointer, needed by some code */
+    TIFFVGetMethod vgetparent;                    /* "Super class" methods... */
+    TIFFVSetMethod vsetparent;
+    TIFFStripMethod defsparent;
+    TIFFTileMethod deftparent;
+    void *jpegtables;           /* ->"New" JPEG tables, if we synthesized any */
+    uint32 is_WANG,    /* <=> Wang Imaging for Microsoft Windows output file? */
+           jpegtables_length;   /* Length of "new" JPEG tables, if they exist */
+    tsize_t bytesperline;          /* No. of decompressed Bytes per scan line */
+    int jpegquality,                             /* Compression quality level */
+        jpegtablesmode,                          /* What to put in JPEGTables */
+        samplesperclump,
+        scancount;                           /* No. of scan lines accumulated */
+    J_COLOR_SPACE photometric;          /* IJG JPEG Library's photometry code */
+    unsigned char h_sampling,                          /* Luminance sampling factors */
+           v_sampling,
+           jpegcolormode;           /* Who performs RGB <-> YCbCr conversion? */
+      /* JPEGCOLORMODE_RAW <=> TIFF Library or its client */
+      /* JPEGCOLORMODE_RGB <=> JPEG Library               */
+    /* These fields are added to support TIFFGetField */
+    uint16 jpegproc;
+    uint32 jpegifoffset;
+    uint32 jpegifbytecount;
+    uint32 jpegrestartinterval;
+    void* jpeglosslesspredictors;
+    uint16 jpeglosslesspredictors_length;
+    void* jpegpointtransform;
+    uint32 jpegpointtransform_length;
+    void* jpegqtables;
+    uint32 jpegqtables_length;
+    void* jpegdctables;
+    uint32 jpegdctables_length;
+    void* jpegactables;
+    uint32 jpegactables_length;
+
+  } OJPEGState;
+#define OJState(tif)((OJPEGState*)(tif)->tif_data)
+
+static const TIFFFieldInfo ojpegFieldInfo[]=/* JPEG-specific TIFF-record tags */
+  {
+
+ /* This is the current JPEG-in-TIFF metadata-encapsulation tag, and its
+    treatment in this file is idiosyncratic.  It should never appear in a
+    "source" image conforming to the TIFF Version 6.0 specification, so we
+    arrange to report an error if it appears.  But in order to support possible
+    future conversion of "old" JPEG-in-TIFF encapsulations to "new" ones, we
+    might wish to synthesize an equivalent value to be returned by the TIFF
+    Library's "getfield" method.  So, this table tells the TIFF Library to pass
+    these records to us in order to filter them below.
+ */
+    {
+      TIFFTAG_JPEGTABLES            ,TIFF_VARIABLE2,TIFF_VARIABLE2,
+      TIFF_UNDEFINED,FIELD_JPEGTABLES            ,FALSE,TRUE ,"JPEGTables"
+    },
+
+ /* These tags are defined by the TIFF Version 6.0 specification and are now
+    obsolete.  This module reads them from an old "source" image, but it never
+    writes them to a new "destination" image.
+ */
+    {
+      TIFFTAG_JPEGPROC              ,1            ,1            ,
+      TIFF_SHORT    ,FIELD_JPEGPROC              ,FALSE,FALSE,"JPEGProc"
+    },
+    {
+      TIFFTAG_JPEGIFOFFSET          ,1            ,1            ,
+      TIFF_LONG     ,FIELD_JPEGIFOFFSET          ,FALSE,FALSE,"JPEGInterchangeFormat"
+    },
+    {
+      TIFFTAG_JPEGIFBYTECOUNT       ,1            ,1            ,
+      TIFF_LONG     ,FIELD_JPEGIFBYTECOUNT       ,FALSE,FALSE,"JPEGInterchangeFormatLength"
+    },
+    {
+      TIFFTAG_JPEGRESTARTINTERVAL   ,1            ,1            ,
+      TIFF_SHORT    ,FIELD_JPEGRESTARTINTERVAL   ,FALSE,FALSE,"JPEGRestartInterval"
+    },
+    {
+      TIFFTAG_JPEGLOSSLESSPREDICTORS,TIFF_VARIABLE,TIFF_VARIABLE,
+      TIFF_SHORT    ,FIELD_JPEGLOSSLESSPREDICTORS,FALSE,TRUE ,"JPEGLosslessPredictors"
+    },
+    {
+      TIFFTAG_JPEGPOINTTRANSFORM    ,TIFF_VARIABLE,TIFF_VARIABLE,
+      TIFF_SHORT    ,FIELD_JPEGPOINTTRANSFORM    ,FALSE,TRUE ,"JPEGPointTransforms"
+    },
+    {
+      TIFFTAG_JPEGQTABLES           ,TIFF_VARIABLE,TIFF_VARIABLE,
+      TIFF_LONG     ,FIELD_JPEGQTABLES           ,FALSE,TRUE ,"JPEGQTables"
+    },
+    {
+      TIFFTAG_JPEGDCTABLES          ,TIFF_VARIABLE,TIFF_VARIABLE,
+      TIFF_LONG     ,FIELD_JPEGDCTABLES          ,FALSE,TRUE ,"JPEGDCTables"
+    },
+    {
+      TIFFTAG_JPEGACTABLES          ,TIFF_VARIABLE,TIFF_VARIABLE,
+      TIFF_LONG     ,FIELD_JPEGACTABLES          ,FALSE,TRUE ,"JPEGACTables"
+    },
+    {
+      TIFFTAG_WANG_PAGECONTROL      ,TIFF_VARIABLE,1            ,
+      TIFF_LONG     ,FIELD_WANG_PAGECONTROL      ,FALSE,FALSE,"WANG PageControl"
+    },
+
+ /* This is a pseudo tag intended for internal use only by the TIFF Library and
+    its clients, which should never appear in an input/output image file.  It
+    specifies whether the TIFF Library (or its client) should do YCbCr <-> RGB
+    color-space conversion (JPEGCOLORMODE_RAW <=> 0) or whether we should ask
+    the JPEG Library to do it (JPEGCOLORMODE_RGB <=> 1).
+ */
+    {
+      TIFFTAG_JPEGCOLORMODE         ,0            ,0            ,
+      TIFF_ANY      ,FIELD_PSEUDO                ,FALSE,FALSE,"JPEGColorMode"
+    }
+  };
+static const char JPEGLib_name[]={"JPEG Library"},
+                  bad_bps[]={"%u BitsPerSample not allowed for JPEG"},
+                  bad_photometry[]={"PhotometricInterpretation %u not allowed for JPEG"},
+                  bad_subsampling[]={"invalid YCbCr subsampling factor(s)"},
+#                 ifdef never
+                  no_write_frac[]={"fractional scan line discarded"},
+#                 endif
+                  no_read_frac[]={"fractional scan line not read"},
+                  no_jtable_space[]={"No space for JPEGTables"};
+
+/* The following diagnostic subroutines interface with and replace default
+   subroutines in the JPEG Library.  Our basic strategy is to use "setjmp()"/
+   "longjmp()" in order to return control to the TIFF Library when the JPEG
+   library detects an error, and to use TIFF Library subroutines for displaying
+   diagnostic messages to a client application.
+*/
+static void
+TIFFojpeg_error_exit(register j_common_ptr cinfo)
+{
+    char buffer[JMSG_LENGTH_MAX];
+    int code = cinfo->err->msg_code;
+
+    if (((OJPEGState *)cinfo)->is_WANG) {
+  if (code == JERR_SOF_DUPLICATE || code == JERR_SOI_DUPLICATE)
+      return;      /* ignore it */
+    }
+
+    (*cinfo->err->format_message)(cinfo,buffer);
+    TIFFError(JPEGLib_name,buffer); /* Display error message */
+    jpeg_abort(cinfo); /* Clean up JPEG Library state */
+    LONGJMP(((OJPEGState *)cinfo)->exit_jmpbuf,1); /* Return to TIFF client */
+}
+
+static void
+TIFFojpeg_output_message(register j_common_ptr cinfo)
+  { char buffer[JMSG_LENGTH_MAX];
+
+ /* This subroutine is invoked only for warning messages, since the JPEG
+    Library's "error_exit" method does its own thing and "trace_level" is never
+    set > 0.
+ */
+    (*cinfo->err->format_message)(cinfo,buffer);
+    TIFFWarning(JPEGLib_name,buffer);
+  }
+
+/* The following subroutines, which also interface with the JPEG Library, exist
+   mainly in limit the side effects of "setjmp()" and convert JPEG normal/error
+   conditions into TIFF Library return codes.
+*/
+#define CALLJPEG(sp,fail,op)(SETJMP((sp)->exit_jmpbuf)?(fail):(op))
+#define CALLVJPEG(sp,op)CALLJPEG(sp,0,((op),1))
+#ifdef never
+
+static int
+TIFFojpeg_create_compress(register OJPEGState *sp)
+  {
+    sp->cinfo.c.err = jpeg_std_error(&sp->err); /* Initialize error handling */
+    sp->err.error_exit = TIFFojpeg_error_exit;
+    sp->err.output_message = TIFFojpeg_output_message;
+    return CALLVJPEG(sp,jpeg_create_compress(&sp->cinfo.c));
+  }
+
+/* The following subroutines comprise a JPEG Library "destination" data manager
+   by directing compressed data from the JPEG Library to a TIFF Library output
+   buffer.
+*/
+static void
+std_init_destination(register j_compress_ptr cinfo){} /* "Dummy" stub */
+
+static boolean
+std_empty_output_buffer(register j_compress_ptr cinfo)
+  {
+#   define sp ((OJPEGState *)cinfo)
+    register TIFF *tif = sp->tif;
+
+    tif->tif_rawcc = tif->tif_rawdatasize; /* Entire buffer has been filled */
+    TIFFFlushData1(tif);
+    sp->dest.next_output_byte = (JOCTET *)tif->tif_rawdata;
+    sp->dest.free_in_buffer = (size_t)tif->tif_rawdatasize;
+    return TRUE;
+#   undef sp
+  }
+
+static void
+std_term_destination(register j_compress_ptr cinfo)
+  {
+#   define sp ((OJPEGState *)cinfo)
+    register TIFF *tif = sp->tif;
+
+ /* NB: The TIFF Library does the final buffer flush. */
+    tif->tif_rawcp = (tidata_t)sp->dest.next_output_byte;
+    tif->tif_rawcc = tif->tif_rawdatasize - (tsize_t)sp->dest.free_in_buffer;
+#   undef sp
+  }
+
+/* Alternate destination manager to output JPEGTables field: */
+
+static void
+tables_init_destination(register j_compress_ptr cinfo)
+  {
+#   define sp ((OJPEGState *)cinfo)
+ /* The "jpegtables_length" field is the allocated buffer size while building */
+    sp->dest.next_output_byte = (JOCTET *)sp->jpegtables;
+    sp->dest.free_in_buffer = (size_t)sp->jpegtables_length;
+#   undef sp
+  }
+
+static boolean
+tables_empty_output_buffer(register j_compress_ptr cinfo)
+  { void *newbuf;
+#   define sp ((OJPEGState *)cinfo)
+
+ /* The entire buffer has been filled, so enlarge it by 1000 bytes. */
+    if (!( newbuf = _TIFFrealloc( (tdata_t)sp->jpegtables
+                                , (tsize_t)(sp->jpegtables_length + 1000)
+                                )
+         )
+       ) ERREXIT1(cinfo,JERR_OUT_OF_MEMORY,100);
+    sp->dest.next_output_byte = (JOCTET *)newbuf + sp->jpegtables_length;
+    sp->dest.free_in_buffer = (size_t)1000;
+    sp->jpegtables = newbuf;
+    sp->jpegtables_length += 1000;
+    return TRUE;
+#   undef sp
+  }
+
+static void
+tables_term_destination(register j_compress_ptr cinfo)
+  {
+#   define sp ((OJPEGState *)cinfo)
+ /* Set tables length to no. of Bytes actually emitted. */
+    sp->jpegtables_length -= sp->dest.free_in_buffer;
+#   undef sp
+  }
+
+/*ARGSUSED*/ static int
+TIFFojpeg_tables_dest(register OJPEGState *sp, TIFF *tif)
+  {
+
+ /* Allocate a working buffer for building tables.  The initial size is 1000
+    Bytes, which is usually adequate.
+ */
+    if (sp->jpegtables) _TIFFfree(sp->jpegtables);
+    if (!(sp->jpegtables = (void*)
+                           _TIFFmalloc((tsize_t)(sp->jpegtables_length = 1000))
+         )
+       )
+      {
+        sp->jpegtables_length = 0;
+        TIFFError("TIFFojpeg_tables_dest",no_jtable_space);
+        return 0;
+      };
+    sp->cinfo.c.dest = &sp->dest;
+    sp->dest.init_destination = tables_init_destination;
+    sp->dest.empty_output_buffer = tables_empty_output_buffer;
+    sp->dest.term_destination = tables_term_destination;
+    return 1;
+  }
+#else /* well, hardly ever */
+
+static int
+_notSupported(register TIFF *tif)
+  { const TIFFCodec *c = TIFFFindCODEC(tif->tif_dir.td_compression);
+
+    TIFFError(tif->tif_name,"%s compression not supported",c->name);
+    return 0;
+  }
+#endif /* never */
+
+/* The following subroutines comprise a JPEG Library "source" data manager by
+   by directing compressed data to the JPEG Library from a TIFF Library input
+   buffer.
+*/
+static void
+std_init_source(register j_decompress_ptr cinfo)
+  {
+#   define sp ((OJPEGState *)cinfo)
+    register TIFF *tif = sp->tif;
+
+    if (sp->src.bytes_in_buffer == 0)
+      {
+        sp->src.next_input_byte = (const JOCTET *)tif->tif_rawdata;
+        sp->src.bytes_in_buffer = (size_t)tif->tif_rawcc;
+      };
+#   undef sp
+  }
+
+static boolean
+std_fill_input_buffer(register j_decompress_ptr cinfo)
+  { static const JOCTET dummy_EOI[2]={0xFF,JPEG_EOI};
+#   define sp ((OJPEGState *)cinfo)
+
+ /* Control should never get here, since an entire strip/tile is read into
+    memory before the decompressor is called; thus, data should have been
+    supplied by the "init_source" method.  ...But, sometimes things fail.
+ */
+    WARNMS(cinfo,JWRN_JPEG_EOF);
+    sp->src.next_input_byte = dummy_EOI; /* Insert a fake EOI marker */
+    sp->src.bytes_in_buffer = sizeof dummy_EOI;
+    return TRUE;
+#   undef sp
+  }
+
+static void
+std_skip_input_data(register j_decompress_ptr cinfo, long num_bytes)
+  {
+#   define sp ((OJPEGState *)cinfo)
+
+    if (num_bytes > 0)
+    {
+      if (num_bytes > (long)sp->src.bytes_in_buffer) /* oops: buffer overrun */
+        (void)std_fill_input_buffer(cinfo);
+      else
+        {
+          sp->src.next_input_byte += (size_t)num_bytes;
+          sp->src.bytes_in_buffer -= (size_t)num_bytes;
+        }
+    }
+#   undef sp
+  }
+
+/*ARGSUSED*/ static void
+std_term_source(register j_decompress_ptr cinfo){} /* "Dummy" stub */
+
+/* Allocate temporary I/O buffers for downsampled data, using values computed in
+   "jpeg_start_{de}compress()".  We use the JPEG Library's allocator so that
+   buffers will be released automatically when done with a strip/tile.  This is
+   also a handy place to compute samplesperclump, bytesperline, etc.
+*/
+static int
+alloc_downsampled_buffers(TIFF *tif,jpeg_component_info *comp_info,
+                          int num_components)
+  { register OJPEGState *sp = OJState(tif);
+
+    sp->samplesperclump = 0;
+    if (num_components > 0)
+      { tsize_t size = sp->cinfo.comm.is_decompressor
+#                    ifdef D_LOSSLESS_SUPPORTED
+                     ? sp->cinfo.d.min_codec_data_unit
+#                    else
+                     ? DCTSIZE
+#                    endif
+#                    ifdef C_LOSSLESS_SUPPORTED
+                     : sp->cinfo.c.data_unit;
+#                    else
+                     : DCTSIZE;
+#                    endif
+        int ci = 0;
+        register jpeg_component_info *compptr = comp_info;
+
+        do
+          { JSAMPARRAY buf;
+
+            sp->samplesperclump +=
+              compptr->h_samp_factor * compptr->v_samp_factor;
+#           if defined(C_LOSSLESS_SUPPORTED) || defined(D_LOSSLESS_SUPPORTED)
+            if (!(buf = CALLJPEG(sp,0,(*sp->cinfo.comm.mem->alloc_sarray)(&sp->cinfo.comm,JPOOL_IMAGE,compptr->width_in_data_units*size,compptr->v_samp_factor*size))))
+#           else
+            if (!(buf = CALLJPEG(sp,0,(*sp->cinfo.comm.mem->alloc_sarray)(&sp->cinfo.comm,JPOOL_IMAGE,compptr->width_in_blocks*size,compptr->v_samp_factor*size))))
+#           endif
+              return 0;
+            sp->ds_buffer[ci] = buf;
+          }
+        while (++compptr,++ci < num_components);
+      };
+    return 1;
+  }
+#ifdef never
+
+/* JPEG Encoding begins here. */
+
+/*ARGSUSED*/ static int
+OJPEGEncode(register TIFF *tif,tidata_t buf,tsize_t cc,tsample_t s)
+  { tsize_t rows;                          /* No. of unprocessed rows in file */
+    register OJPEGState *sp = OJState(tif);
+
+ /* Encode a chunk of pixels, where returned data is NOT down-sampled (the
+    standard case).  The data is expected to be written in scan-line multiples.
+ */
+    if (cc % sp->bytesperline) TIFFWarning(tif->tif_name,no_write_frac);
+    if ( (cc /= bytesperline)      /* No. of complete rows in caller's buffer */
+       > (rows = sp->cinfo.c.image_height - sp->cinfo.c.next_scanline)
+       ) cc = rows;
+    while (--cc >= 0)
+      {
+        if (   CALLJPEG(sp,-1,jpeg_write_scanlines(&sp->cinfo.c,(JSAMPARRAY)&buf,1))
+            != 1
+           ) return 0;
+        ++tif->tif_row;
+        buf += sp->bytesperline;
+      };
+    return 1;
+  }
+
+/*ARGSUSED*/ static int
+OJPEGEncodeRaw(register TIFF *tif,tidata_t buf,tsize_t cc,tsample_t s)
+  { tsize_t rows;                          /* No. of unprocessed rows in file */
+    JDIMENSION lines_per_MCU, size;
+    register OJPEGState *sp = OJState(tif);
+
+ /* Encode a chunk of pixels, where returned data is down-sampled as per the
+    sampling factors.  The data is expected to be written in scan-line
+    multiples.
+ */
+    cc /= sp->bytesperline;
+    if (cc % sp->bytesperline) TIFFWarning(tif->tif_name,no_write_frac);
+    if ( (cc /= bytesperline)      /* No. of complete rows in caller's buffer */
+       > (rows = sp->cinfo.c.image_height - sp->cinfo.c.next_scanline)
+       ) cc = rows;
+#   ifdef C_LOSSLESS_SUPPORTED
+    lines_per_MCU = sp->cinfo.c.max_samp_factor*(size = sp->cinfo.d.data_unit);
+#   else
+    lines_per_MCU = sp->cinfo.c.max_samp_factor*(size = DCTSIZE);
+#   endif
+    while (--cc >= 0)
+      { int ci = 0, clumpoffset = 0;
+        register jpeg_component_info *compptr = sp->cinfo.c.comp_info;
+
+     /* The fastest way to separate the data is to make 1 pass over the scan
+        line for each row of each component.
+     */
+        do
+          { int ypos = 0;
+
+            do
+              { int padding;
+                register JSAMPLE *inptr = (JSAMPLE*)buf + clumpoffset,
+                                 *outptr =
+                  sp->ds_buffer[ci][sp->scancount*compptr->v_samp_factor+ypos];
+             /* Cb,Cr both have sampling factors 1, so this is correct */
+                register int clumps_per_line =
+                  sp->cinfo.c.comp_info[1].downsampled_width,
+                             xpos;
+
+                padding = (int)
+#                         ifdef C_LOSSLESS_SUPPORTED
+                          ( compptr->width_in_data_units * size
+#                         else
+                          ( compptr->width_in_blocks * size
+#                         endif
+                          - clumps_per_line * compptr->h_samp_factor
+                          );
+                if (compptr->h_samp_factor == 1) /* Cb & Cr fast path */
+                  do *outptr++ = *inptr;
+                  while ((inptr += sp->samplesperclump),--clumps_per_line > 0);
+                else /* general case */
+                  do
+                    {
+                      xpos = 0;
+                      do *outptr++ = inptr[xpos];
+                      while (++xpos < compptr->h_samp_factor);
+                    }
+                  while ((inptr += sp->samplesperclump),--clumps_per_line > 0);
+                xpos = 0; /* Pad each scan line as needed */
+                do outptr[0] = outptr[-1]; while (++outptr,++xpos < padding);
+                clumpoffset += compptr->h_samp_factor;
+              }
+            while (++ypos < compptr->v_samp_factor);
+          }
+        while (++compptr,++ci < sp->cinfo.c.num_components);
+        if (++sp->scancount >= size)
+          {
+            if (   CALLJPEG(sp,-1,jpeg_write_raw_data(&sp->cinfo.c,sp->ds_buffer,lines_per_MCU))
+                != lines_per_MCU
+               ) return 0;
+            sp->scancount = 0;
+          };
+        ++tif->tif_row++
+        buf += sp->bytesperline;
+      };
+    return 1;
+  }
+
+static int
+OJPEGSetupEncode(register TIFF *tif)
+  { static const char module[]={"OJPEGSetupEncode"};
+    uint32 segment_height, segment_width;
+    int status = 1;                              /* Assume success by default */
+    register OJPEGState *sp = OJState(tif);
+#   define td (&tif->tif_dir)
+
+ /* Verify miscellaneous parameters.  This will need work if the TIFF Library
+    ever supports different depths for different components, or if the JPEG
+    Library ever supports run-time depth selection.  Neither seems imminent.
+ */
+    if (td->td_bitspersample != 8)
+      {
+        TIFFError(module,bad_bps,td->td_bitspersample);
+        status = 0;
+      };
+
+ /* The TIFF Version 6.0 specification and IJG JPEG Library accept different
+    sets of color spaces, so verify that our image belongs to the common subset
+    and map its photometry code, then initialize to handle subsampling and
+    optional JPEG Library YCbCr <-> RGB color-space conversion.
+ */
+    switch (td->td_photometric)
+      {
+        case PHOTOMETRIC_YCBCR     :
+
+       /* ISO IS 10918-1 requires that JPEG subsampling factors be 1-4, but
+          TIFF Version 6.0 is more restrictive: only 1, 2, and 4 are allowed.
+       */
+          if (   (   td->td_ycbcrsubsampling[0] == 1
+                  || td->td_ycbcrsubsampling[0] == 2
+                  || td->td_ycbcrsubsampling[0] == 4
+                 )
+              && (   td->td_ycbcrsubsampling[1] == 1
+                  || td->td_ycbcrsubsampling[1] == 2
+                  || td->td_ycbcrsubsampling[1] == 4
+                 )
+             )
+            sp->cinfo.c.raw_data_in =
+              ( (sp->h_sampling = td->td_ycbcrsubsampling[0]) << 3
+              | (sp->v_sampling = td->td_ycbcrsubsampling[1])
+              ) != 011;
+          else
+            {
+              TIFFError(module,bad_subsampling);
+              status = 0;
+            };
+
+       /* A ReferenceBlackWhite field MUST be present, since the default value
+          is inapproriate for YCbCr.  Fill in the proper value if the
+          application didn't set it.
+       */
+          if (!TIFFFieldSet(tif,FIELD_REFBLACKWHITE))
+            { float refbw[6];
+              long top = 1L << td->td_bitspersample;
+ 
+              refbw[0] = 0;
+              refbw[1] = (float)(top-1L);
+              refbw[2] = (float)(top>>1);
+              refbw[3] = refbw[1];
+              refbw[4] = refbw[2];
+              refbw[5] = refbw[1];
+              TIFFSetField(tif,TIFFTAG_REFERENCEBLACKWHITE,refbw);
+            };
+          sp->cinfo.c.jpeg_color_space = JCS_YCbCr;
+          if (sp->jpegcolormode == JPEGCOLORMODE_RGB)
+            {
+              sp->cinfo.c.raw_data_in = FALSE;
+              sp->in_color_space = JCS_RGB;
+              break;
+            };
+          goto L2;
+        case PHOTOMETRIC_MINISBLACK:
+          sp->cinfo.c.jpeg_color_space = JCS_GRAYSCALE;
+          goto L1;
+        case PHOTOMETRIC_RGB       :
+          sp->cinfo.c.jpeg_color_space = JCS_RGB;
+          goto L1;
+        case PHOTOMETRIC_SEPARATED :
+          sp->cinfo.c.jpeg_color_space = JCS_CMYK;
+      L1: sp->jpegcolormode = JPEGCOLORMODE_RAW; /* No JPEG Lib. conversion */
+      L2: sp->cinfo.d.in_color_space = sp->cinfo.d.jpeg_color-space;
+          break;
+        default                    :
+          TIFFError(module,bad_photometry,td->td_photometric);
+          status = 0;
+      };
+    tif->tif_encoderow = tif->tif_encodestrip = tif->tif_encodetile =
+      sp->cinfo.c.raw_data_in ? OJPEGEncodeRaw : OJPEGEncode;
+    if (isTiled(tif))
+      { tsize_t size;
+
+#       ifdef C_LOSSLESS_SUPPORTED
+        if ((size = sp->v_sampling*sp->cinfo.c.data_unit) < 16) size = 16;
+#       else
+        if ((size = sp->v_sampling*DCTSIZE) < 16) size = 16;
+#       endif
+        if ((segment_height = td->td_tilelength) % size)
+          {
+            TIFFError(module,"JPEG tile height must be multiple of %d",size);
+            status = 0;
+          };
+#       ifdef C_LOSSLESS_SUPPORTED
+        if ((size = sp->h_sampling*sp->cinfo.c.data_unit) < 16) size = 16;
+#       else
+        if ((size = sp->h_sampling*DCTSIZE) < 16) size = 16;
+#       endif
+        if ((segment_width = td->td_tilewidth) % size)
+          {
+            TIFFError(module,"JPEG tile width must be multiple of %d",size);
+            status = 0;
+          };
+        sp->bytesperline = TIFFTileRowSize(tif);
+      }
+    else
+      { tsize_t size;
+
+#       ifdef C_LOSSLESS_SUPPORTED
+        if ((size = sp->v_sampling*sp->cinfo.c.data_unit) < 16) size = 16;
+#       else
+        if ((size = sp->v_sampling*DCTSIZE) < 16) size = 16;
+#       endif
+        if (td->td_rowsperstrip < (segment_height = td->td_imagelength))
+          {
+            if (td->td_rowsperstrip % size)
+              {
+                TIFFError(module,"JPEG RowsPerStrip must be multiple of %d",size);
+                status = 0;
+              };
+            segment_height = td->td_rowsperstrip;
+          };
+        segment_width = td->td_imagewidth;
+        sp->bytesperline = tif->tif_scanlinesize;
+      };
+    if (segment_width > 65535 || segment_height > 65535)
+      {
+        TIFFError(module,"Strip/tile too large for JPEG");
+        status = 0;
+      };
+
+ /* Initialize all JPEG parameters to default values.  Note that the JPEG
+    Library's "jpeg_set_defaults()" method needs legal values for the
+    "in_color_space" and "input_components" fields.
+ */
+    sp->cinfo.c.input_components = 1; /* Default for JCS_UNKNOWN */
+    if (!CALLVJPEG(sp,jpeg_set_defaults(&sp->cinfo.c))) status = 0;
+    switch (sp->jpegtablesmode & (JPEGTABLESMODE_HUFF|JPEGTABLESMODE_QUANT))
+      { register JHUFF_TBL *htbl;
+        register JQUANT_TBL *qtbl;
+
+        case 0                                       :
+          sp->cinfo.c.optimize_coding = TRUE;
+        case JPEGTABLESMODE_HUFF                     :
+          if (!CALLVJPEG(sp,jpeg_set_quality(&sp->cinfo.c,sp->jpegquality,FALSE)))
+            return 0;
+          if (qtbl = sp->cinfo.c.quant_tbl_ptrs[0]) qtbl->sent_table = FALSE;
+          if (qtbl = sp->cinfo.c.quant_tbl_ptrs[1]) qtbl->sent_table = FALSE;
+          goto L3;
+        case JPEGTABLESMODE_QUANT                    :
+          sp->cinfo.c.optimize_coding = TRUE;
+
+       /* We do not support application-supplied JPEG tables, so mark the field
+          "not present".
+       */
+      L3: TIFFClrFieldBit(tif,FIELD_JPEGTABLES);
+          break;
+        case JPEGTABLESMODE_HUFF|JPEGTABLESMODE_QUANT:
+          if (   !CALLVJPEG(sp,jpeg_set_quality(&sp->cinfo.c,sp->jpegquality,FALSE))
+              || !CALLVJPEG(sp,jpeg_suppress_tables(&sp->cinfo.c,TRUE))
+             )
+            {
+              status = 0;
+              break;
+            };
+          if (qtbl = sp->cinfo.c.quant_tbl_ptrs[0]) qtbl->sent_table = FALSE;
+          if (htbl = sp->cinfo.c.dc_huff_tbl_ptrs[0]) htbl->sent_table = FALSE;
+          if (htbl = sp->cinfo.c.ac_huff_tbl_ptrs[0]) htbl->sent_table = FALSE;
+          if (sp->cinfo.c.jpeg_color_space == JCS_YCbCr)
+            {
+              if (qtbl = sp->cinfo.c.quant_tbl_ptrs[1])
+                qtbl->sent_table = FALSE;
+              if (htbl = sp->cinfo.c.dc_huff_tbl_ptrs[1])
+                htbl->sent_table = FALSE;
+              if (htbl = sp->cinfo.c.ac_huff_tbl_ptrs[1])
+                htbl->sent_table = FALSE;
+            };
+          if (   TIFFojpeg_tables_dest(sp,tif)
+              && CALLVJPEG(sp,jpeg_write_tables(&sp->cinfo.c))
+             )
+            {
+    
+           /* Mark the field "present".  We can't use "TIFFSetField()" because
+              "BEENWRITING" is already set!
+           */
+              TIFFSetFieldBit(tif,FIELD_JPEGTABLES);
+              tif->tif_flags |= TIFF_DIRTYDIRECT;
+            }
+          else status = 0;
+      };
+    if (   sp->cinfo.c.raw_data_in
+        && !alloc_downsampled_buffers(tif,sp->cinfo.c.comp_info,
+                                      sp->cinfo.c.num_components)
+       ) status = 0;
+    if (status == 0) return 0; /* If TIFF errors, don't bother to continue */
+ /* Grab parameters that are same for all strips/tiles. */
+
+    sp->dest.init_destination = std_init_destination;
+    sp->dest.empty_output_buffer = std_empty_output_buffer;
+    sp->dest.term_destination = std_term_destination;
+    sp->cinfo.c.dest = &sp->dest;
+    sp->cinfo.c.data_precision = td->td_bitspersample;
+    sp->cinfo.c.write_JFIF_header = /* Don't write extraneous markers */
+    sp->cinfo.c.write_Adobe_marker = FALSE;
+    sp->cinfo.c.image_width = segment_width;
+    sp->cinfo.c.image_height = segment_height;
+    sp->cinfo.c.comp_info[0].h_samp_factor =
+    sp->cinfo.c.comp_info[0].v_samp_factor = 1;
+    return CALLVJPEG(sp,jpeg_start_compress(&sp->cinfo.c,FALSE));
+#   undef td
+  }
+
+static int
+OJPEGPreEncode(register TIFF *tif,tsample_t s)
+  { register OJPEGState *sp = OJState(tif);
+#   define td (&tif->tif_dir)
+
+ /* If we are about to write the first row of an image plane, which should
+    coincide with a JPEG "scan", reset the JPEG Library's compressor.  Otherwise
+    let the compressor run "as is" and return a "success" status without further
+    ado.
+ */
+    if (     (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip)
+           % td->td_stripsperimage
+        == 0
+       )
+      {
+        if (   (sp->cinfo.c.comp_info[0].component_id = s) == 1)
+            && sp->cinfo.c.jpeg_color_space == JCS_YCbCr
+           )
+          {
+            sp->cinfo.c.comp_info[0].quant_tbl_no =
+            sp->cinfo.c.comp_info[0].dc_tbl_no =
+            sp->cinfo.c.comp_info[0].ac_tbl_no = 1;
+            sp->cinfo.c.comp_info[0].h_samp_factor = sp->h_sampling;
+            sp->cinfo.c.comp_info[0].v_samp_factor = sp->v_sampling;
+    
+         /* Scale expected strip/tile size to match a downsampled component. */
+    
+            sp->cinfo.c.image_width = TIFFhowmany(segment_width,sp->h_sampling);
+            sp->cinfo.c.image_height=TIFFhowmany(segment_height,sp->v_sampling);
+          };
+        sp->scancount = 0; /* Mark subsampling buffer(s) empty */
+      };
+    return 1;
+#   undef td
+  }
+
+static int
+OJPEGPostEncode(register TIFF *tif)
+  { register OJPEGState *sp = OJState(tif);
+
+ /* Finish up at the end of a strip or tile. */
+
+    if (sp->scancount > 0) /* emit partial buffer of down-sampled data */
+      { JDIMENSION n;
+
+#       ifdef C_LOSSLESS_SUPPORTED
+        if (   sp->scancount < sp->cinfo.c.data_unit
+            && sp->cinfo.c.num_components > 0
+           )
+#       else
+        if (sp->scancount < DCTSIZE && sp->cinfo.c.num_components > 0)
+#       endif
+          { int ci = 0,                            /* Pad the data vertically */
+#           ifdef C_LOSSLESS_SUPPORTED
+                size = sp->cinfo.c.data_unit;
+#           else
+                size = DCTSIZE;
+#           endif
+            register jpeg_component_info *compptr = sp->cinfo.c.comp_info;
+
+            do
+#              ifdef C_LOSSLESS_SUPPORTED
+               { tsize_t row_width = compptr->width_in_data_units
+#              else
+                 tsize_t row_width = compptr->width_in_blocks
+#              endif
+                   *size*sizeof(JSAMPLE);
+                 int ypos = sp->scancount*compptr->v_samp_factor;
+
+                 do _TIFFmemcpy( (tdata_t)sp->ds_buffer[ci][ypos]
+                               , (tdata_t)sp->ds_buffer[ci][ypos-1]
+                               , row_width
+                               );
+                 while (++ypos < compptr->v_samp_factor*size);
+               }
+            while (++compptr,++ci < sp->cinfo.c.num_components);
+          };
+        n = sp->cinfo.c.max_v_samp_factor*size;
+        if (CALLJPEG(sp,-1,jpeg_write_raw_data(&sp->cinfo.c,sp->ds_buffer,n)) != n)
+          return 0;
+      };
+    return CALLVJPEG(sp,jpeg_finish_compress(&sp->cinfo.c));
+  }
+#endif /* never */
+
+/* JPEG Decoding begins here. */
+
+/*ARGSUSED*/ static int
+OJPEGDecode(register TIFF *tif,tidata_t buf,tsize_t cc,tsample_t s)
+  { tsize_t bytesperline = isTiled(tif)
+                         ? TIFFTileRowSize(tif)
+                         : tif->tif_scanlinesize,
+            rows;                          /* No. of unprocessed rows in file */
+    register OJPEGState *sp = OJState(tif);
+
+ /* Decode a chunk of pixels, where the input data has not NOT been down-
+    sampled, or else the TIFF Library's client has used the "JPEGColorMode" TIFF
+    pseudo-tag to request that the JPEG Library do color-space conversion; this
+    is the normal case.  The data is expected to be read in scan-line multiples,
+    and this subroutine is called for both pixel-interleaved and separate color
+    planes.
+
+    WARNING:  Unlike "OJPEGDecodeRawContig()", below, the no. of Bytes in each
+              decoded row is calculated here as "bytesperline" instead of
+    using "sp->bytesperline", which might be a little smaller.  This can
+    occur for an old tiled image whose width isn't a multiple of 8 pixels.
+    That's illegal according to the TIFF Version 6 specification, but some
+    test files, like "zackthecat.tif", were built that way.  In those cases,
+    we want to embed the image's true width in our caller's buffer (which is
+    presumably allocated according to the expected tile width) by
+    effectively "padding" it with unused Bytes at the end of each row.
+ */
+    if ( (cc /= bytesperline)      /* No. of complete rows in caller's buffer */
+       > (rows = sp->cinfo.d.output_height - sp->cinfo.d.output_scanline)
+       ) cc = rows;
+    while (--cc >= 0)
+      {
+        if (   CALLJPEG(sp,-1,jpeg_read_scanlines(&sp->cinfo.d,(JSAMPARRAY)&buf,1))
+            != 1
+           ) return 0;
+        buf += bytesperline;
+        ++tif->tif_row;
+      };
+
+ /* BEWARE OF KLUDGE:  If our input file was produced by Microsoft's Wang
+                       Imaging for Windows application, the DC coefficients of
+    each JPEG image component (Y,Cb,Cr) must be reset at the end of each TIFF
+    "strip", and any JPEG data bits remaining in the current Byte of the
+    decoder's input buffer must be discarded.  To do so, we create an "ad hoc"
+    interface in the "jdhuff.c" module of IJG JPEG Library Version 6 (module
+    "jdshuff.c", if Ken Murchison's lossless-Huffman patch is applied), and we
+    invoke that interface here after decoding each "strip".
+ */
+    if (sp->is_WANG) jpeg_reset_huff_decode(&sp->cinfo.d);
+    return 1;
+  }
+
+/*ARGSUSED*/ static int
+OJPEGDecodeRawContig(register TIFF *tif,tidata_t buf,tsize_t cc,tsample_t s)
+  { tsize_t rows;                          /* No. of unprocessed rows in file */
+    JDIMENSION lines_per_MCU, size;
+    register OJPEGState *sp = OJState(tif);
+
+ /* Decode a chunk of pixels, where the input data has pixel-interleaved color
+    planes, some of which have been down-sampled, but the TIFF Library's client
+    has NOT used the "JPEGColorMode" TIFF pseudo-tag to request that the JPEG
+    Library do color-space conversion.  In other words, we must up-sample/
+    expand/duplicate image components according to the image's sampling factors,
+    without changing its color space.  The data is expected to be read in scan-
+    line multiples.
+ */
+    if ( (cc /= sp->bytesperline)  /* No. of complete rows in caller's buffer */
+       > (rows = sp->cinfo.d.output_height - sp->cinfo.d.output_scanline)
+       ) cc = rows;
+    lines_per_MCU = sp->cinfo.d.max_v_samp_factor
+#   ifdef D_LOSSLESS_SUPPORTED
+                  * (size = sp->cinfo.d.min_codec_data_unit);
+#   else
+                  * (size = DCTSIZE);
+#   endif
+    while (--cc >= 0)
+      { int clumpoffset, ci;
+        register jpeg_component_info *compptr;
+
+        if (sp->scancount >= size) /* reload downsampled-data buffers */
+          {
+            if (   CALLJPEG(sp,-1,jpeg_read_raw_data(&sp->cinfo.d,sp->ds_buffer,lines_per_MCU))
+                != lines_per_MCU
+               ) return 0;
+            sp->scancount = 0;
+          };
+
+     /* The fastest way to separate the data is: make 1 pass over the scan
+        line for each row of each component.
+     */
+        clumpoffset = ci = 0;
+        compptr = sp->cinfo.d.comp_info;
+        do
+          { int ypos = 0;
+
+            if (compptr->h_samp_factor == 1) /* fast path */
+              do
+                { register JSAMPLE *inptr =
+                    sp->ds_buffer[ci][sp->scancount*compptr->v_samp_factor+ypos],
+                                   *outptr = (JSAMPLE *)buf + clumpoffset;
+                  register int clumps_per_line = compptr->downsampled_width;
+
+                  do *outptr = *inptr++;
+                  while ((outptr += sp->samplesperclump),--clumps_per_line > 0);
+                }
+              while ( (clumpoffset += compptr->h_samp_factor)
+                    , ++ypos < compptr->v_samp_factor
+                    );
+            else /* general case */
+              do
+                { register JSAMPLE *inptr =
+                    sp->ds_buffer[ci][sp->scancount*compptr->v_samp_factor+ypos],
+                                   *outptr = (JSAMPLE *)buf + clumpoffset;
+                  register int clumps_per_line = compptr->downsampled_width;
+
+                  do
+                    { register int xpos = 0;
+
+                      do outptr[xpos] = *inptr++;
+                      while (++xpos < compptr->h_samp_factor);
+                    }
+                  while ((outptr += sp->samplesperclump),--clumps_per_line > 0);
+                }
+              while ( (clumpoffset += compptr->h_samp_factor)
+                    , ++ypos < compptr->v_samp_factor
+                    );
+          }
+        while (++compptr,++ci < sp->cinfo.d.num_components);
+        ++sp->scancount;
+        buf += sp->bytesperline;
+        ++tif->tif_row;
+      };
+
+ /* BEWARE OF KLUDGE:  If our input file was produced by Microsoft's Wang
+                       Imaging for Windows application, the DC coefficients of
+    each JPEG image component (Y,Cb,Cr) must be reset at the end of each TIFF
+    "strip", and any JPEG data bits remaining in the current Byte of the
+    decoder's input buffer must be discarded.  To do so, we create an "ad hoc"
+    interface in the "jdhuff.c" module of IJG JPEG Library Version 6 (module
+    "jdshuff.c", if Ken Murchison's lossless-Huffman patch is applied), and we
+    invoke that interface here after decoding each "strip".
+ */
+    if (sp->is_WANG) jpeg_reset_huff_decode(&sp->cinfo.d);
+    return 1;
+  }
+
+/*ARGSUSED*/ static int
+OJPEGDecodeRawSeparate(TIFF *tif,register tidata_t buf,tsize_t cc,tsample_t s)
+  { tsize_t rows;                          /* No. of unprocessed rows in file */
+    JDIMENSION lines_per_MCU,
+               size,                                             /* ...of MCU */
+               v;                   /* Component's vertical up-sampling ratio */
+    register OJPEGState *sp = OJState(tif);
+    register jpeg_component_info *compptr = sp->cinfo.d.comp_info + s;
+
+ /* Decode a chunk of pixels, where the input data has separate color planes,
+    some of which have been down-sampled, but the TIFF Library's client has NOT
+    used the "JPEGColorMode" TIFF pseudo-tag to request that the JPEG Library
+    do color-space conversion.  The data is expected to be read in scan-line
+    multiples.
+ */
+    v = sp->cinfo.d.max_v_samp_factor/compptr->v_samp_factor;
+    if ( (cc /= compptr->downsampled_width) /* No. of rows in caller's buffer */
+       > (rows = (sp->cinfo.d.output_height-sp->cinfo.d.output_scanline+v-1)/v)
+       ) cc = rows; /* No. of rows of "clumps" to read */
+    lines_per_MCU = sp->cinfo.d.max_v_samp_factor
+#   ifdef D_LOSSLESS_SUPPORTED
+                  * (size = sp->cinfo.d.min_codec_data_unit);
+#   else
+                  * (size = DCTSIZE);
+#   endif
+ L: if (sp->scancount >= size) /* reload downsampled-data buffers */
+      {
+        if (   CALLJPEG(sp,-1,jpeg_read_raw_data(&sp->cinfo.d,sp->ds_buffer,lines_per_MCU))
+            != lines_per_MCU
+           ) return 0;
+        sp->scancount = 0;
+      };
+    rows = 0;
+    do
+      { register JSAMPLE *inptr =
+          sp->ds_buffer[s][sp->scancount*compptr->v_samp_factor + rows];
+        register int clumps_per_line = compptr->downsampled_width;
+
+        do *buf++ = *inptr++; while (--clumps_per_line > 0); /* Copy scanline */
+        tif->tif_row += v;
+        if (--cc <= 0) return 1; /* End of caller's buffer? */
+      }
+    while (++rows < compptr->v_samp_factor);
+    ++sp->scancount;
+    goto L;
+  }
+
+/* "OJPEGSetupDecode()" temporarily forces the JPEG Library to use the following
+   subroutine as a "dummy" input reader in order to fool the library into
+   thinking that it has read the image's first "Start of Scan" (SOS) marker, so
+   that it initializes accordingly.
+*/
+/*ARGSUSED*/ METHODDEF(int)
+fake_SOS_marker(j_decompress_ptr cinfo){return JPEG_REACHED_SOS;}
+
+/*ARGSUSED*/ METHODDEF(int)
+suspend(j_decompress_ptr cinfo){return JPEG_SUSPENDED;}
+
+/* The JPEG Library's "null" color-space converter actually re-packs separate
+   color planes (it's native image representation) into a pixel-interleaved,
+   contiguous plane.  But if our TIFF Library client is tryng to process a
+   PLANARCONFIG_SEPARATE image, we don't want that; so here are modifications of
+   code in the JPEG Library's "jdcolor.c" file, which simply copy Bytes to a
+   color plane specified by the current JPEG "scan".
+*/
+METHODDEF(void)
+ycc_rgb_convert(register j_decompress_ptr cinfo,JSAMPIMAGE in,JDIMENSION row,
+                register JSAMPARRAY out,register int nrows)
+  { typedef struct                /* "jdcolor.c" color-space conversion state */
+      {
+
+     /* WARNING:  This declaration is ugly and dangerous!  It's supposed to be
+                  private to the JPEG Library's "jdcolor.c" module, but we also
+        need it here.  Since the library's copy might change without notice, be
+        sure to keep this one synchronized or the following code will break!
+     */
+        struct jpeg_color_deconverter pub; /* Public fields */
+     /* Private state for YCC->RGB conversion */
+        int *Cr_r_tab,   /* ->Cr to R conversion table */
+            *Cb_b_tab;   /* ->Cb to B conversion table */
+        INT32 *Cr_g_tab, /* ->Cr to G conversion table */
+              *Cb_g_tab; /* ->Cb to G conversion table */
+      } *my_cconvert_ptr;
+    my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
+    JSAMPARRAY irow0p = in[0] + row;
+    register JSAMPLE *range_limit = cinfo->sample_range_limit;
+    register JSAMPROW outp, Y;
+
+    switch (cinfo->output_scan_number - 1)
+      { JSAMPARRAY irow1p, irow2p;
+        register INT32 *table0, *table1;
+        SHIFT_TEMPS
+
+        case RGB_RED  : irow2p = in[2] + row;
+                        table0 = (INT32 *)cconvert->Cr_r_tab;
+                        while (--nrows >= 0)
+                          { register JSAMPROW Cr = *irow2p++;
+                             register int i = cinfo->output_width;
+
+                             Y = *irow0p++;
+                             outp = *out++;
+                             while (--i >= 0)
+                               *outp++ = range_limit[*Y++ + table0[*Cr++]];
+                          };
+                        return;
+        case RGB_GREEN: irow1p = in[1] + row;
+                        irow2p = in[2] + row;
+                        table0 = cconvert->Cb_g_tab;
+                        table1 = cconvert->Cr_g_tab;
+                        while (--nrows >= 0)
+                          { register JSAMPROW Cb = *irow1p++,
+                                              Cr = *irow2p++;
+                             register int i = cinfo->output_width;
+
+                             Y = *irow0p++;
+                             outp = *out++;
+                             while (--i >= 0)
+                               *outp++ =
+                                 range_limit[ *Y++
+                                            + RIGHT_SHIFT(table0[*Cb++]+table1[*Cr++],16)
+                                            ];
+                          };
+                        return;
+        case RGB_BLUE : irow1p = in[1] + row;
+                        table0 = (INT32 *)cconvert->Cb_b_tab;
+                        while (--nrows >= 0)
+                          { register JSAMPROW Cb = *irow1p++;
+                             register int i = cinfo->output_width;
+
+                             Y = *irow0p++;
+                             outp = *out++;
+                             while (--i >= 0)
+                               *outp++ = range_limit[*Y++ + table0[*Cb++]];
+                          }
+      }
+  }
+
+METHODDEF(void)
+null_convert(register j_decompress_ptr cinfo,JSAMPIMAGE in,JDIMENSION row,
+             register JSAMPARRAY out,register int nrows)
+  { register JSAMPARRAY irowp = in[cinfo->output_scan_number - 1] + row;
+
+    while (--nrows >= 0) _TIFFmemcpy(*out++,*irowp++,cinfo->output_width);
+  }
+
+static int
+OJPEGSetupDecode(register TIFF *tif)
+  { static char module[]={"OJPEGSetupDecode"};
+    J_COLOR_SPACE jpeg_color_space,   /* Color space of JPEG-compressed image */
+                  out_color_space;       /* Color space of decompressed image */
+    uint32 segment_width;
+    int status = 1;                              /* Assume success by default */
+    boolean downsampled_output=FALSE, /* <=> Want JPEG Library's "raw" image? */
+            is_JFIF;                                       /* <=> JFIF image? */
+    register OJPEGState *sp = OJState(tif);
+#   define td (&tif->tif_dir)
+
+ /* Verify miscellaneous parameters.  This will need work if the TIFF Library
+    ever supports different depths for different components, or if the JPEG
+    Library ever supports run-time depth selection.  Neither seems imminent.
+ */
+    if (td->td_bitspersample != sp->cinfo.d.data_precision)
+      {
+        TIFFError(module,bad_bps,td->td_bitspersample);
+        status = 0;
+      };
+
+ /* The TIFF Version 6.0 specification and IJG JPEG Library accept different
+    sets of color spaces, so verify that our image belongs to the common subset
+    and map its photometry code, then initialize to handle subsampling and
+    optional JPEG Library YCbCr <-> RGB color-space conversion.
+ */
+    switch (td->td_photometric)
+      {
+        case PHOTOMETRIC_YCBCR     :
+
+       /* ISO IS 10918-1 requires that JPEG subsampling factors be 1-4, but
+          TIFF Version 6.0 is more restrictive: only 1, 2, and 4 are allowed.
+       */
+          if (   (   td->td_ycbcrsubsampling[0] == 1
+                  || td->td_ycbcrsubsampling[0] == 2
+                  || td->td_ycbcrsubsampling[0] == 4
+                 )
+              && (   td->td_ycbcrsubsampling[1] == 1
+                  || td->td_ycbcrsubsampling[1] == 2
+                  || td->td_ycbcrsubsampling[1] == 4
+                 )
+             )
+            downsampled_output =
+              (
+                (sp->h_sampling = td->td_ycbcrsubsampling[0]) << 3
+              | (sp->v_sampling = td->td_ycbcrsubsampling[1])
+              ) != 011;
+          else
+            {
+              TIFFError(module,bad_subsampling);
+              status = 0;
+            };
+          jpeg_color_space = JCS_YCbCr;
+          if (sp->jpegcolormode == JPEGCOLORMODE_RGB)
+            {
+              downsampled_output = FALSE;
+              out_color_space = JCS_RGB;
+              break;
+            };
+          goto L2;
+        case PHOTOMETRIC_MINISBLACK:
+          jpeg_color_space = JCS_GRAYSCALE;
+          goto L1;
+        case PHOTOMETRIC_RGB       :
+          jpeg_color_space = JCS_RGB;
+          goto L1;
+        case PHOTOMETRIC_SEPARATED :
+          jpeg_color_space = JCS_CMYK;
+      L1: sp->jpegcolormode = JPEGCOLORMODE_RAW; /* No JPEG Lib. conversion */
+      L2: out_color_space = jpeg_color_space;
+          break;
+        default                    :
+          TIFFError(module,bad_photometry,td->td_photometric);
+          status = 0;
+      };
+    if (status == 0) return 0; /* If TIFF errors, don't bother to continue */
+
+ /* Set parameters that are same for all strips/tiles. */
+
+    sp->cinfo.d.src = &sp->src;
+    sp->src.init_source = std_init_source;
+    sp->src.fill_input_buffer = std_fill_input_buffer;
+    sp->src.skip_input_data = std_skip_input_data;
+    sp->src.resync_to_restart = jpeg_resync_to_restart;
+    sp->src.term_source = std_term_source;
+
+ /* BOGOSITY ALERT!  The Wang Imaging application for Microsoft Windows produces
+                     images containing "JPEGInterchangeFormat[Length]" TIFF
+    records that resemble JFIF-in-TIFF encapsulations but, in fact, violate the
+    TIFF Version 6 specification in several ways; nevertheless, we try to handle
+    them gracefully because there are apparently a lot of them around.  The
+    purported "JFIF" data stream in one of these files vaguely resembles a JPEG
+    "tables only" data stream, except that there's no trailing EOI marker.  The
+    rest of the JPEG data stream lies in a discontiguous file region, identified
+    by the 0th Strip offset (which is *also* illegal!), where it begins with an
+    SOS marker and apparently continues to the end of the file.  There is no
+    trailing EOI marker here, either.
+ */
+    is_JFIF = !sp->is_WANG && TIFFFieldSet(tif,FIELD_JPEGIFOFFSET);
+
+ /* Initialize decompression parameters that won't be overridden by JPEG Library
+    defaults set during the "jpeg_read_header()" call, below.
+ */
+    segment_width = td->td_imagewidth;
+    if (isTiled(tif))
+      {
+        if (sp->is_WANG) /* we don't know how to handle it */
+          {
+            TIFFError(module,"Tiled Wang image not supported");
+            return 0;
+          };
+
+     /* BOGOSITY ALERT!  "TIFFTileRowSize()" seems to work fine for modern JPEG-
+                         in-TIFF encapsulations where the image width--like the
+        tile width--is a multiple of 8 or 16 pixels.  But image widths and
+        heights are aren't restricted to 8- or 16-bit multiples, and we need
+        the exact Byte count of decompressed scan lines when we call the JPEG
+        Library.  At least one old file ("zackthecat.tif") in the TIFF Library
+        test suite has widths and heights slightly less than the tile sizes, and
+        it apparently used the bogus computation below to determine the number
+        of Bytes per scan line (was this due to an old, broken version of
+        "TIFFhowmany()"?).  Before we get here, "OJPEGSetupDecode()" verified
+        that our image uses 8-bit samples, so the following check appears to
+        return the correct answer in all known cases tested to date.
+     */
+        if (is_JFIF || (segment_width & 7) == 0)
+          sp->bytesperline = TIFFTileRowSize(tif); /* Normal case */
+        else
+          {
+            /* Was the file-encoder's segment-width calculation bogus? */
+            segment_width = (segment_width/sp->h_sampling + 1) * sp->h_sampling;
+            sp->bytesperline = segment_width * td->td_samplesperpixel;
+          }
+      }
+    else sp->bytesperline = TIFFVStripSize(tif,1);
+
+ /* BEWARE OF KLUDGE:  If we have JPEG Interchange File Format (JFIF) image,
+                       then we want to read "metadata" in the bit-stream's
+    header and validate it against corresponding information in TIFF records.
+    But if we have a *really old* JPEG file that's not JFIF, then we simply
+    assign TIFF-record values to JPEG Library variables without checking.
+ */
+    if (is_JFIF) /* JFIF image */
+      { unsigned char *end_of_data;
+        int subsampling_factors;
+        register unsigned char *p;
+        register int i;
+
+     /* WARNING:  Although the image file contains a JFIF bit stream, it might
+                  also contain some old TIFF records causing "OJPEGVSetField()"
+        to have allocated quantization or Huffman decoding tables.  But when the
+        JPEG Library reads and parses the JFIF header below, it reallocate these
+        tables anew without checking for "dangling" pointers, thereby causing a
+        memory "leak".  We have enough information to potentially deallocate the
+        old tables here, but unfortunately JPEG Library Version 6B uses a "pool"
+        allocator for small objects, with no deallocation procedure; instead, it
+        reclaims a whole pool when an image is closed/destroyed, so well-behaved
+        TIFF client applications (i.e., those which close their JPEG images as
+        soon as they're no longer needed) will waste memory for a short time but
+        recover it eventually.  But ill-behaved TIFF clients (i.e., those which
+        keep many JPEG images open gratuitously) can exhaust memory prematurely.
+        If the JPEG Library ever implements a deallocation procedure, insert
+        this clean-up code:
+     */
+#       ifdef someday
+        if (sp->jpegtablesmode & JPEGTABLESMODE_QUANT) /* free quant. tables */
+          { register int i = 0;
+
+            do
+              { register JQUANT_TBL *q;
+
+                if (q = sp->cinfo.d.quant_tbl_ptrs[i])
+                  {
+                    jpeg_free_small(&sp->cinfo.comm,q,sizeof *q);
+                    sp->cinfo.d.quant_tbl_ptrs[i] = 0;
+                  }
+              }
+            while (++i < NUM_QUANT_TBLS);
+          };
+        if (sp->jpegtablesmode & JPEGTABLESMODE_HUFF) /* free Huffman tables */
+          { register int i = 0;
+
+            do
+              { register JHUFF_TBL *h;
+
+                if (h = sp->cinfo.d.dc_huff_tbl_ptrs[i])
+                  {
+                    jpeg_free_small(&sp->cinfo.comm,h,sizeof *h);
+                    sp->cinfo.d.dc_huff_tbl_ptrs[i] = 0;
+                  };
+                if (h = sp->cinfo.d.ac_huff_tbl_ptrs[i])
+                  {
+                    jpeg_free_small(&sp->cinfo.comm,h,sizeof *h);
+                    sp->cinfo.d.ac_huff_tbl_ptrs[i] = 0;
+                  }
+              }
+            while (++i < NUM_HUFF_TBLS);
+          };
+#       endif /* someday */
+
+     /* Since we might someday wish to try rewriting "old format" JPEG-in-TIFF
+        encapsulations in "new format" files, try to synthesize the value of a
+        modern "JPEGTables" TIFF record by scanning the JPEG data from just past
+        the "Start of Information" (SOI) marker until something other than a
+        legitimate "table" marker is found, as defined in ISO IS 10918-1
+        Appending B.2.4; namely:
+
+        -- Define Quantization Table (DQT)
+        -- Define Huffman Table (DHT)
+        -- Define Arithmetic Coding table (DAC)
+        -- Define Restart Interval (DRI)
+        -- Comment (COM)
+        -- Application data (APPn)
+
+        For convenience, we also accept "Expansion" (EXP) markers, although they
+        are apparently not a part of normal "table" data.
+     */
+        sp->jpegtables = p = (unsigned char *)sp->src.next_input_byte;
+        end_of_data = p + sp->src.bytes_in_buffer;
+        p += 2;
+        while (p < end_of_data && p[0] == 0xFF)
+          switch (p[1])
+            {
+              default  : goto L;
+              case 0xC0: /* SOF0  */
+              case 0xC1: /* SOF1  */
+              case 0xC2: /* SOF2  */
+              case 0xC3: /* SOF3  */
+              case 0xC4: /* DHT   */
+              case 0xC5: /* SOF5  */
+              case 0xC6: /* SOF6  */
+              case 0xC7: /* SOF7  */
+              case 0xC9: /* SOF9  */
+              case 0xCA: /* SOF10 */
+              case 0xCB: /* SOF11 */
+              case 0xCC: /* DAC   */
+              case 0xCD: /* SOF13 */
+              case 0xCE: /* SOF14 */
+              case 0xCF: /* SOF15 */
+              case 0xDB: /* DQT   */
+              case 0xDD: /* DRI   */
+              case 0xDF: /* EXP   */
+              case 0xE0: /* APP0  */
+              case 0xE1: /* APP1  */
+              case 0xE2: /* APP2  */
+              case 0xE3: /* APP3  */
+              case 0xE4: /* APP4  */
+              case 0xE5: /* APP5  */
+              case 0xE6: /* APP6  */
+              case 0xE7: /* APP7  */
+              case 0xE8: /* APP8  */
+              case 0xE9: /* APP9  */
+              case 0xEA: /* APP10 */
+              case 0xEB: /* APP11 */
+              case 0xEC: /* APP12 */
+              case 0xED: /* APP13 */
+              case 0xEE: /* APP14 */
+              case 0xEF: /* APP15 */
+              case 0xFE: /* COM   */
+                         p += (p[2] << 8 | p[3]) + 2;
+            };
+     L: if (p - (unsigned char *)sp->jpegtables > 2) /* fake "JPEGTables" */
+          {
+
+         /* In case our client application asks, pretend that this image file
+            contains a modern "JPEGTables" TIFF record by copying to a buffer
+            the initial part of the JFIF bit-stream that we just scanned, from
+            the SOI marker through the "metadata" tables, then append an EOI
+            marker and flag the "JPEGTables" TIFF record as "present".
+         */
+            sp->jpegtables_length = p - (unsigned char*)sp->jpegtables + 2;
+            p = sp->jpegtables;
+            if (!(sp->jpegtables = _TIFFmalloc(sp->jpegtables_length)))
+              {
+                TIFFError(module,no_jtable_space);
+                return 0;
+              };
+            _TIFFmemcpy(sp->jpegtables,p,sp->jpegtables_length-2);
+            p = (unsigned char *)sp->jpegtables + sp->jpegtables_length;
+            p[-2] = 0xFF; p[-1] = JPEG_EOI; /* Append EOI marker */
+            TIFFSetFieldBit(tif,FIELD_JPEGTABLES);
+            tif->tif_flags |= TIFF_DIRTYDIRECT;
+          }
+        else sp->jpegtables = 0; /* Don't simulate "JPEGTables" */
+        if (   CALLJPEG(sp,-1,jpeg_read_header(&sp->cinfo.d,TRUE))
+            != JPEG_HEADER_OK
+           ) return 0;
+        if (   sp->cinfo.d.image_width  != segment_width
+            || sp->cinfo.d.image_height != td->td_imagelength 
+           )
+          {
+            TIFFError(module,"Improper JPEG strip/tile size");
+            return 0;
+          };
+        if (sp->cinfo.d.num_components != td->td_samplesperpixel)
+          {
+            TIFFError(module,"Improper JPEG component count");
+            return 0;
+          };
+        if (sp->cinfo.d.data_precision != td->td_bitspersample)
+          {
+            TIFFError(module,"Improper JPEG data precision");
+            return 0;
+          };
+
+     /* Check that JPEG image components all have the same subsampling factors
+        declared (or defaulted) in the TIFF file, since TIFF Version 6.0 is more
+        restrictive than JPEG:  Only the 0th component may have horizontal and
+        vertical subsampling factors other than <1,1>.
+     */
+        subsampling_factors = sp->h_sampling << 3 | sp->v_sampling;
+        i = 0;
+        do
+          {
+            if (   ( sp->cinfo.d.comp_info[i].h_samp_factor << 3
+                   | sp->cinfo.d.comp_info[i].v_samp_factor
+                   )
+                != subsampling_factors
+               )
+              {
+                TIFFError(module,"Improper JPEG subsampling factors");
+                return 0;
+              };
+            subsampling_factors = 011; /* Required for image components > 0 */
+          }
+        while (++i < sp->cinfo.d.num_components);
+      }
+    else /* not JFIF image */
+      { int (*save)(j_decompress_ptr cinfo) = sp->cinfo.d.marker->read_markers;
+        register int i;
+
+     /* We're not assuming that this file's JPEG bit stream has any header
+        "metadata", so fool the JPEG Library into thinking that we read a
+        "Start of Input" (SOI) marker and a "Start of Frame" (SOFx) marker, then
+        force it to read a simulated "Start of Scan" (SOS) marker when we call
+        "jpeg_read_header()" below.  This should cause the JPEG Library to
+        establish reasonable defaults.
+     */
+        sp->cinfo.d.marker->saw_SOI =       /* Pretend we saw SOI marker */
+        sp->cinfo.d.marker->saw_SOF = TRUE; /* Pretend we saw SOF marker */
+        sp->cinfo.d.marker->read_markers =
+          sp->is_WANG ? suspend : fake_SOS_marker;
+        sp->cinfo.d.global_state = DSTATE_INHEADER;
+        sp->cinfo.d.Se = DCTSIZE2-1; /* Suppress JPEG Library warning */
+        sp->cinfo.d.image_width  = segment_width;
+        sp->cinfo.d.image_height = td->td_imagelength;
+
+     /* The following color-space initialization, including the complicated
+        "switch"-statement below, essentially duplicates the logic used by the
+        JPEG Library's "jpeg_init_colorspace()" subroutine during compression.
+     */
+        sp->cinfo.d.num_components = td->td_samplesperpixel;
+        sp->cinfo.d.comp_info = (jpeg_component_info *)
+          (*sp->cinfo.d.mem->alloc_small)
+            ( &sp->cinfo.comm
+            , JPOOL_IMAGE
+            , sp->cinfo.d.num_components * sizeof *sp->cinfo.d.comp_info
+            );
+        i = 0;
+        do
+          {
+            sp->cinfo.d.comp_info[i].component_index = i;
+            sp->cinfo.d.comp_info[i].component_needed = TRUE;
+            sp->cinfo.d.cur_comp_info[i] = &sp->cinfo.d.comp_info[i];
+          }
+        while (++i < sp->cinfo.d.num_components);
+        switch (jpeg_color_space)
+          {
+            case JCS_UNKNOWN  :
+              i = 0;
+              do
+                {
+                  sp->cinfo.d.comp_info[i].component_id = i;
+                  sp->cinfo.d.comp_info[i].h_samp_factor =
+                  sp->cinfo.d.comp_info[i].v_samp_factor = 1;
+                }
+              while (++i < sp->cinfo.d.num_components);
+              break;
+            case JCS_GRAYSCALE:
+              sp->cinfo.d.comp_info[0].component_id =
+              sp->cinfo.d.comp_info[0].h_samp_factor =
+              sp->cinfo.d.comp_info[0].v_samp_factor = 1;
+              break;
+            case JCS_RGB      :
+              sp->cinfo.d.comp_info[0].component_id = 'R';
+              sp->cinfo.d.comp_info[1].component_id = 'G';
+              sp->cinfo.d.comp_info[2].component_id = 'B';
+              i = 0;
+              do sp->cinfo.d.comp_info[i].h_samp_factor =
+                 sp->cinfo.d.comp_info[i].v_samp_factor = 1;
+              while (++i < sp->cinfo.d.num_components);
+              break;
+            case JCS_CMYK     :
+              sp->cinfo.d.comp_info[0].component_id = 'C';
+              sp->cinfo.d.comp_info[1].component_id = 'M';
+              sp->cinfo.d.comp_info[2].component_id = 'Y';
+              sp->cinfo.d.comp_info[3].component_id = 'K';
+              i = 0;
+              do sp->cinfo.d.comp_info[i].h_samp_factor =
+                 sp->cinfo.d.comp_info[i].v_samp_factor = 1;
+              while (++i < sp->cinfo.d.num_components);
+              break;
+            case JCS_YCbCr    :
+              i = 0;
+              do
+                {
+                  sp->cinfo.d.comp_info[i].component_id = i+1;
+                  sp->cinfo.d.comp_info[i].h_samp_factor =
+                  sp->cinfo.d.comp_info[i].v_samp_factor = 1;
+                  sp->cinfo.d.comp_info[i].quant_tbl_no =
+                  sp->cinfo.d.comp_info[i].dc_tbl_no =
+                  sp->cinfo.d.comp_info[i].ac_tbl_no = i > 0;
+                }
+              while (++i < sp->cinfo.d.num_components);
+              sp->cinfo.d.comp_info[0].h_samp_factor = sp->h_sampling;
+              sp->cinfo.d.comp_info[0].v_samp_factor = sp->v_sampling;
+          };
+        sp->cinfo.d.comps_in_scan = td->td_planarconfig == PLANARCONFIG_CONTIG
+                                  ? sp->cinfo.d.num_components
+                                  : 1;
+        i = CALLJPEG(sp,-1,jpeg_read_header(&sp->cinfo.d,!sp->is_WANG));
+        sp->cinfo.d.marker->read_markers = save; /* Restore input method */
+        if (sp->is_WANG) /* produced by Wang Imaging on Microsoft Windows */
+          {
+            if (i != JPEG_SUSPENDED) return 0;
+
+         /* BOGOSITY ALERT!  Files prooduced by the Wang Imaging application for
+                             Microsoft Windows are a special--and, technically
+            illegal--case.  A JPEG SOS marker and rest of the data stream should
+            be located at the end of the file, in a position identified by the
+            0th Strip offset.
+         */
+            i = td->td_nstrips - 1;
+            sp->src.next_input_byte = tif->tif_base + td->td_stripoffset[0];
+            sp->src.bytes_in_buffer = td->td_stripoffset[i] -
+              td->td_stripoffset[0] + td->td_stripbytecount[i];
+            i = CALLJPEG(sp,-1,jpeg_read_header(&sp->cinfo.d,TRUE));
+          };
+        if (i != JPEG_HEADER_OK) return 0;
+      };
+
+ /* Some of our initialization must wait until the JPEG Library is initialized
+    above, in order to override its defaults.
+ */
+    if (   (sp->cinfo.d.raw_data_out = downsampled_output)
+        && !alloc_downsampled_buffers(tif,sp->cinfo.d.comp_info,
+                                      sp->cinfo.d.num_components)
+       ) return 0;
+    sp->cinfo.d.jpeg_color_space = jpeg_color_space;
+    sp->cinfo.d.out_color_space = out_color_space;
+    sp->cinfo.d.dither_mode = JDITHER_NONE; /* Reduce image "noise" */
+    sp->cinfo.d.two_pass_quantize = FALSE;
+
+ /* If the image consists of separate, discontiguous TIFF "samples" (= color
+    planes, hopefully = JPEG "scans"), then we must use the JPEG Library's
+    "buffered image" mode to decompress the entire image into temporary buffers,
+    because the JPEG Library must parse the entire JPEG bit-stream in order to
+    be satsified that it has a complete set of color components for each pixel,
+    but the TIFF Library must allow our client to extract 1 component at a time.
+    Initializing the JPEG Library's "buffered image" mode is tricky:  First, we
+    start its decompressor, then we tell the decompressor to "consume" (i.e.,
+    buffer) the entire bit-stream.
+
+    WARNING:  Disabling "fancy" up-sampling seems to slightly reduce "noise" for
+              certain old Wang Imaging files, but it absolutely *must* be
+    enabled if the image has separate color planes, since in that case, the JPEG
+    Library doesn't use an "sp->cinfo.d.cconvert" structure (so de-referencing
+    this pointer below will cause a fatal crash) but writing our own code to up-
+    sample separate color planes is too much work for right now.  Maybe someday?
+ */
+    sp->cinfo.d.do_fancy_upsampling = /* Always let this default (to TRUE)? */
+    sp->cinfo.d.buffered_image = td->td_planarconfig == PLANARCONFIG_SEPARATE;
+    if (!CALLJPEG(sp,0,jpeg_start_decompress(&sp->cinfo.d))) return 0;
+    if (sp->cinfo.d.buffered_image) /* separate color planes */
+      {
+        if (sp->cinfo.d.raw_data_out)
+          tif->tif_decoderow = tif->tif_decodestrip = tif->tif_decodetile =
+            OJPEGDecodeRawSeparate;
+        else
+          {
+            tif->tif_decoderow = tif->tif_decodestrip = tif->tif_decodetile =
+              OJPEGDecode;
+
+         /* In JPEG Library Version 6B, color-space conversion isn't implemented
+            for separate color planes, so we must do it ourself if our TIFF
+            client doesn't want to:
+         */
+            sp->cinfo.d.cconvert->color_convert =
+              sp->cinfo.d.jpeg_color_space == sp->cinfo.d.out_color_space
+              ? null_convert : ycc_rgb_convert;
+          };
+    L3: switch (CALLJPEG(sp,0,jpeg_consume_input(&sp->cinfo.d)))
+          {
+            default              : goto L3;
+
+         /* If no JPEG "End of Information" (EOI) marker is found when bit-
+            stream parsing ends, check whether we have enough data to proceed
+            before reporting an error.
+         */
+            case JPEG_SUSPENDED  : if (  sp->cinfo.d.input_scan_number
+                                        *sp->cinfo.d.image_height
+                                       + sp->cinfo.d.input_iMCU_row
+                                        *sp->cinfo.d.max_v_samp_factor
+#                                       ifdef D_LOSSLESS_SUPPORTED
+                                        *sp->cinfo.d.data_units_in_MCU
+                                        *sp->cinfo.d.min_codec_data_unit
+#                                       else
+                                        *sp->cinfo.d.blocks_in_MCU
+                                        *DCTSIZE
+#                                       endif
+                                      < td->td_samplesperpixel
+                                       *sp->cinfo.d.image_height
+                                      )
+                                     {
+                                       TIFFError(tif->tif_name,
+                                         "Premature end of JPEG bit-stream");
+                                       return 0;
+                                     }
+            case JPEG_REACHED_EOI: ;
+          }
+      }
+    else /* pixel-interleaved color planes */
+      tif->tif_decoderow = tif->tif_decodestrip = tif->tif_decodetile =
+        downsampled_output ? OJPEGDecodeRawContig : OJPEGDecode;
+    return 1;
+#   undef td
+  }
+
+static int
+OJPEGPreDecode(register TIFF *tif,tsample_t s)
+  { register OJPEGState *sp = OJState(tif);
+#   define td (&tif->tif_dir)
+
+ /* If we are about to read the first row of an image plane (hopefully, these
+    are coincident with JPEG "scans"!), reset the JPEG Library's decompressor
+    appropriately.  Otherwise, let the decompressor run "as is" and return a
+    "success" status without further ado.
+ */
+    if (     (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip)
+           % td->td_stripsperimage
+        == 0
+       )
+      {
+        if (   sp->cinfo.d.buffered_image
+            && !CALLJPEG(sp,0,jpeg_start_output(&sp->cinfo.d,s+1))
+           ) return 0;
+        sp->cinfo.d.output_scanline = 0;
+
+     /* Mark subsampling buffers "empty". */
+
+#       ifdef D_LOSSLESS_SUPPORTED
+        sp->scancount = sp->cinfo.d.min_codec_data_unit;
+#       else
+        sp->scancount = DCTSIZE;
+#       endif
+      };
+    return 1;
+#   undef td
+  }
+
+/*ARGSUSED*/ static void
+OJPEGPostDecode(register TIFF *tif,tidata_t buf,tsize_t cc)
+  { register OJPEGState *sp = OJState(tif);
+#   define td (&tif->tif_dir)
+
+ /* The JPEG Library decompressor has reached the end of a strip/tile.  If this
+    is the end of a TIFF image "sample" (= JPEG "scan") in a file with separate
+    components (color planes), then end the "scan".  If it ends the image's last
+    sample/scan, then also stop the JPEG Library's decompressor.
+ */
+    if (sp->cinfo.d.output_scanline >= sp->cinfo.d.output_height)
+      {
+        if (sp->cinfo.d.buffered_image)
+          CALLJPEG(sp,-1,jpeg_finish_output(&sp->cinfo.d)); /* End JPEG scan */
+        if (   (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip)
+            >= td->td_nstrips-1
+           ) CALLJPEG(sp,0,jpeg_finish_decompress(&sp->cinfo.d));
+      }
+#   undef td
+  }
+
+static int
+OJPEGVSetField(register TIFF *tif,ttag_t tag,va_list ap)
+{
+    uint32 v32;
+    register OJPEGState *sp = OJState(tif);
+#   define td (&tif->tif_dir)
+    toff_t tiffoff=0;
+    uint32 bufoff=0;
+    uint32 code_count=0;
+    int i2=0;
+    int k2=0;
+
+    switch (tag)
+      {
+
+     /* If a "ReferenceBlackWhite" TIFF tag appears in the file explicitly, undo
+        any modified default definition that we might have installed below, then
+        install the real one.
+     */
+        case TIFFTAG_REFERENCEBLACKWHITE   : if (td->td_refblackwhite)
+                                               {
+                                                 _TIFFfree(td->td_refblackwhite);
+                                                 td->td_refblackwhite = 0;
+                                               };
+        default                            : return
+                                               (*sp->vsetparent)(tif,tag,ap);
+
+     /* BEWARE OF KLUDGE:  Some old-format JPEG-in-TIFF files, including those
+                           produced by the Wang Imaging application for Micro-
+        soft Windows, illegally omit a "ReferenceBlackWhite" TIFF tag, even
+        though the TIFF specification's default is intended for the RGB color
+        space and is inappropriate for the YCbCr color space ordinarily used for
+        JPEG images.  Since many TIFF client applications request the value of
+        this tag immediately after a TIFF image directory is parsed, and before
+        any other code in this module receives control, we are forced to fix
+        this problem very early in image-file processing.  Fortunately, legal
+        TIFF files are supposed to store their tags in numeric order, so a
+        mandatory "PhotometricInterpretation" tag should always appear before
+        an optional "ReferenceBlackWhite" tag.  Hence, we slyly peek ahead when
+        we discover the desired photometry, by installing modified black and
+        white reference levels.
+     */
+        case TIFFTAG_PHOTOMETRIC           :
+          if (   (v32 = (*sp->vsetparent)(tif,tag,ap))
+              && td->td_photometric == PHOTOMETRIC_YCBCR
+             )
+    {
+            if ( (td->td_refblackwhite = _TIFFmalloc(6*sizeof(float))) )
+              { register long top = 1 << td->td_bitspersample;
+
+                td->td_refblackwhite[0] = 0;
+                td->td_refblackwhite[1] = td->td_refblackwhite[3] =
+                td->td_refblackwhite[5] = top - 1;
+                td->td_refblackwhite[2] = td->td_refblackwhite[4] = top >> 1;
+              }
+            else
+              {
+                TIFFError(tif->tif_name,
+                  "Cannot set default reference black and white levels");
+                v32 = 0;
+              };
+    }
+          return v32;
+
+     /* BEWARE OF KLUDGE:  According to Charles Auer <Bumble731@msn.com>, if our
+                           input is a multi-image (multi-directory) JPEG-in-TIFF
+        file is produced by the Wang Imaging application on Microsoft Windows,
+        for some reason the first directory excludes the vendor-specific "WANG
+        PageControl" tag (32934) that we check below, so the only other way to
+        identify these directories is apparently to look for a software-
+        identification tag with the substring, "Wang Labs".  Single-image files
+        can apparently pass both tests, which causes no harm here, but what a
+        mess this is!
+     */
+        case TIFFTAG_SOFTWARE              :
+        {
+            char *software;
+
+            v32 = (*sp->vsetparent)(tif,tag,ap);
+            if( TIFFGetField( tif, TIFFTAG_SOFTWARE, &software )
+                && strstr( software, "Wang Labs" ) )
+                sp->is_WANG = 1;
+            return v32;
+        }
+
+        case TIFFTAG_JPEGPROC              :
+        case TIFFTAG_JPEGIFOFFSET          :
+        case TIFFTAG_JPEGIFBYTECOUNT       :
+        case TIFFTAG_JPEGRESTARTINTERVAL   :
+        case TIFFTAG_JPEGLOSSLESSPREDICTORS:
+        case TIFFTAG_JPEGPOINTTRANSFORM    :
+        case TIFFTAG_JPEGQTABLES           :
+        case TIFFTAG_JPEGDCTABLES          :
+        case TIFFTAG_JPEGACTABLES          :
+        case TIFFTAG_WANG_PAGECONTROL      :
+        case TIFFTAG_JPEGCOLORMODE         : ;
+      };
+    v32 = va_arg(ap,uint32); /* No. of values in this TIFF record */
+
+    /* This switch statement is added for OJPEGVSetField */
+    if(v32 !=0){
+        switch(tag){
+            case TIFFTAG_JPEGPROC:
+                sp->jpegproc=v32;
+                break;
+            case TIFFTAG_JPEGIFOFFSET:
+                sp->jpegifoffset=v32;
+    break;
+            case TIFFTAG_JPEGIFBYTECOUNT:
+    sp->jpegifbytecount=v32;
+    break;
+            case TIFFTAG_JPEGRESTARTINTERVAL:
+    sp->jpegrestartinterval=v32;
+    break;
+            case TIFFTAG_JPEGLOSSLESSPREDICTORS:
+    sp->jpeglosslesspredictors_length=v32;
+    break;
+            case TIFFTAG_JPEGPOINTTRANSFORM:
+    sp->jpegpointtransform_length=v32;
+    break;
+            case TIFFTAG_JPEGQTABLES:
+    sp->jpegqtables_length=v32;
+    break;
+            case TIFFTAG_JPEGACTABLES:
+    sp->jpegactables_length=v32;
+    break;
+            case TIFFTAG_JPEGDCTABLES:
+    sp->jpegdctables_length=v32;
+    break;
+            default:
+    break;
+        }
+    }
+
+ /* BEWARE:  The following actions apply only if we are reading a "source" TIFF
+             image to be decompressed for a client application program.  If we
+    ever enhance this file's CODEC to write "destination" JPEG-in-TIFF images,
+    we'll need an "if"- and another "switch"-statement below, because we'll
+    probably want to store these records' values in some different places.  Most
+    of these need not be parsed here in order to decode JPEG bit stream, so we
+    set boolean flags to note that they have been seen, but we otherwise ignore
+    them.
+ */
+    switch (tag)
+      { JHUFF_TBL **h;
+
+     /* Validate the JPEG-process code. */
+
+        case TIFFTAG_JPEGPROC              :
+          switch (v32)
+            {
+              default               : TIFFError(tif->tif_name,
+                                        "Unknown JPEG process");
+                                      return 0;
+#             ifdef C_LOSSLESS_SUPPORTED
+
+           /* Image uses (lossy) baseline sequential coding. */
+
+              case JPEGPROC_BASELINE: sp->cinfo.d.process = JPROC_SEQUENTIAL;
+                                      sp->cinfo.d.data_unit = DCTSIZE;
+                                      break;
+
+           /* Image uses (lossless) Huffman coding. */
+
+              case JPEGPROC_LOSSLESS: sp->cinfo.d.process = JPROC_LOSSLESS;
+                                      sp->cinfo.d.data_unit = 1;
+#             else /* not C_LOSSLESS_SUPPORTED */
+              case JPEGPROC_LOSSLESS: TIFFError(JPEGLib_name,
+                                        "Does not support lossless Huffman coding");
+                                      return 0;
+              case JPEGPROC_BASELINE: ;
+#             endif /* C_LOSSLESS_SUPPORTED */
+            };
+          break;
+
+     /* The TIFF Version 6.0 specification says that if the value of a TIFF
+        "JPEGInterchangeFormat" record is 0, then we are to behave as if this
+        record were absent; i.e., the data does *not* represent a JPEG Inter-
+        change Format File (JFIF), so don't even set the boolean "I've been
+        here" flag below.  Otherwise, the field's value represents the file
+        offset of the JPEG SOI marker.
+     */
+        case TIFFTAG_JPEGIFOFFSET          :
+          if (v32)
+            {
+              sp->src.next_input_byte = tif->tif_base + v32;
+              break;
+            };
+          return 1;
+        case TIFFTAG_JPEGIFBYTECOUNT       :
+          sp->src.bytes_in_buffer = v32;
+          break;
+
+     /* The TIFF Version 6.0 specification says that if the JPEG "Restart"
+        marker interval is 0, then the data has no "Restart" markers; i.e., we
+        must behave as if this TIFF record were absent.  So, don't even set the
+        boolean "I've been here" flag below.
+     */
+     /*
+      * Instead, set the field bit so TIFFGetField can get whether or not
+      * it was set.
+      */
+        case TIFFTAG_JPEGRESTARTINTERVAL   :
+          if (v32)
+              sp->cinfo.d.restart_interval = v32;
+              break;
+     /* The TIFF Version 6.0 specification says that this tag is supposed to be
+        a vector containing a value for each image component, but for lossless
+        Huffman coding (the only JPEG process defined by the specification for
+        which this tag should be needed), ISO IS 10918-1 uses only a single
+        value, equivalent to the "Ss" field in a JPEG bit-stream's "Start of
+        Scan" (SOS) marker.  So, we extract the first vector element and ignore
+        the rest.  (I hope this is correct!)
+     */
+        case TIFFTAG_JPEGLOSSLESSPREDICTORS:
+           if (v32)
+             {
+               sp->cinfo.d.Ss = *va_arg(ap,uint16 *);
+               sp->jpeglosslesspredictors = 
+        _TIFFmalloc(sp->jpeglosslesspredictors_length
+        * sizeof(uint16));
+               if(sp->jpeglosslesspredictors==NULL){return(0);}
+               for(i2=0;i2<sp->jpeglosslesspredictors_length;i2++){
+                ((uint16*)sp->jpeglosslesspredictors)[i2] =
+      ((uint16*)sp->cinfo.d.Ss)[i2];
+               }
+               sp->jpeglosslesspredictors_length*=sizeof(uint16);
+               break;
+             };
+           return v32;
+
+     /* The TIFF Version 6.0 specification says that this tag is supposed to be
+        a vector containing a value for each image component, but for lossless
+        Huffman coding (the only JPEG process defined by the specification for
+        which this tag should be needed), ISO IS 10918-1 uses only a single
+        value, equivalent to the "Al" field in a JPEG bit-stream's "Start of
+        Scan" (SOS) marker.  So, we extract the first vector element and ignore
+        the rest.  (I hope this is correct!)
+     */
+        case TIFFTAG_JPEGPOINTTRANSFORM    :
+           if (v32)
+             {
+               sp->cinfo.d.Al = *va_arg(ap,uint16 *);
+               sp->jpegpointtransform =
+        _TIFFmalloc(sp->jpegpointtransform_length*sizeof(uint16));
+               if(sp->jpegpointtransform==NULL){return(0);}
+               for(i2=0;i2<sp->jpegpointtransform_length;i2++) {
+                ((uint16*)sp->jpegpointtransform)[i2] =
+      ((uint16*)sp->cinfo.d.Al)[i2];
+               }
+               sp->jpegpointtransform_length*=sizeof(uint16);
+               break;
+             }
+           return v32;
+
+     /* We have a vector of offsets to quantization tables, so load 'em! */
+
+        case TIFFTAG_JPEGQTABLES           :
+          if (v32)
+            { uint32 *v;
+              int i;
+              if (v32 > NUM_QUANT_TBLS)
+                {
+                  TIFFError(tif->tif_name,"Too many quantization tables");
+                  return 0;
+                };
+              i = 0;
+              v = va_arg(ap,uint32 *);
+                sp->jpegqtables=_TIFFmalloc(64*sp->jpegqtables_length);
+                if(sp->jpegqtables==NULL){return(0);}
+                tiffoff = TIFFSeekFile(tif, 0, SEEK_CUR);
+                bufoff=0;
+                for(i2=0;i2<sp->jpegqtables_length;i2++){
+                    TIFFSeekFile(tif, v[i2], SEEK_SET);
+                    TIFFReadFile(tif, &(((unsigned char*)(sp->jpegqtables))[bufoff]),
+         64);
+                    bufoff+=64;
+                }
+                sp->jpegqtables_length=bufoff;
+                TIFFSeekFile(tif, tiffoff, SEEK_SET);
+
+              do /* read quantization table */
+                { register UINT8 *from = tif->tif_base + *v++;
+                  register UINT16 *to;
+                  register int j = DCTSIZE2;
+
+                  if (!( sp->cinfo.d.quant_tbl_ptrs[i]
+                       = CALLJPEG(sp,0,jpeg_alloc_quant_table(&sp->cinfo.comm))
+                       )
+                     )
+                    {
+                      TIFFError(JPEGLib_name,"No space for quantization table");
+                      return 0;
+                    };
+                  to = sp->cinfo.d.quant_tbl_ptrs[i]->quantval;
+                  do *to++ = *from++; while (--j > 0);
+                }
+              while (++i < v32);
+              sp->jpegtablesmode |= JPEGTABLESMODE_QUANT;
+            };
+          break;
+
+     /* We have a vector of offsets to DC Huffman tables, so load 'em! */
+
+        case TIFFTAG_JPEGDCTABLES          :
+          h = sp->cinfo.d.dc_huff_tbl_ptrs;
+          goto L;
+
+     /* We have a vector of offsets to AC Huffman tables, so load 'em! */
+
+        case TIFFTAG_JPEGACTABLES          :
+          h = sp->cinfo.d.ac_huff_tbl_ptrs;
+       L: if (v32)
+            { uint32 *v;
+              int i;
+              if (v32 > NUM_HUFF_TBLS)
+                {
+                  TIFFError(tif->tif_name,"Too many Huffman tables");
+                  return 0;
+                };
+              v = va_arg(ap,uint32 *);
+                if(tag == TIFFTAG_JPEGDCTABLES) {
+                    sp->jpegdctables=_TIFFmalloc(272*sp->jpegdctables_length);
+                    if(sp->jpegdctables==NULL){return(0);}
+                    tiffoff = TIFFSeekFile(tif, 0, SEEK_CUR);
+                    bufoff=0;
+                    code_count=0;                
+                    for(i2=0;i2<sp->jpegdctables_length;i2++){
+                        TIFFSeekFile(tif, v[i2], SEEK_SET);
+                        TIFFReadFile(tif,
+             &(((unsigned char*)(sp->jpegdctables))[bufoff]),
+             16);
+                        code_count=0;
+                        for(k2=0;k2<16;k2++){
+                            code_count+=((unsigned char*)(sp->jpegdctables))[k2+bufoff];
+                        }
+                        TIFFReadFile(tif,
+             &(((unsigned char*)(sp->jpegdctables))[bufoff+16]),
+             code_count);
+                        bufoff+=16;
+                        bufoff+=code_count;
+                    }
+                    sp->jpegdctables_length=bufoff;
+                    TIFFSeekFile(tif, tiffoff, SEEK_SET);
+                }
+                if(tag==TIFFTAG_JPEGACTABLES){
+                    sp->jpegactables=_TIFFmalloc(272*sp->jpegactables_length);
+                    if(sp->jpegactables==NULL){return(0);}
+                    tiffoff = TIFFSeekFile(tif, 0, SEEK_CUR);
+                    bufoff=0;
+                    code_count=0;                
+                    for(i2=0;i2<sp->jpegactables_length;i2++){
+                        TIFFSeekFile(tif, v[i2], SEEK_SET);
+                        TIFFReadFile(tif, &(((unsigned char*)(sp->jpegactables))[bufoff]), 16);
+                        code_count=0;
+                        for(k2=0;k2<16;k2++){
+                            code_count+=((unsigned char*)(sp->jpegactables))[k2+bufoff];
+                        }
+                        TIFFReadFile(tif, &(((unsigned char*)(sp->jpegactables))[bufoff+16]), code_count);
+                        bufoff+=16;
+                        bufoff+=code_count;
+                    }
+                    sp->jpegactables_length=bufoff;
+                    TIFFSeekFile(tif, tiffoff, SEEK_SET);
+                }
+              i = 0;
+              do /* copy each Huffman table */
+                { int size = 0;
+                  register UINT8 *from = tif->tif_base + *v++, *to;
+                  register int j = sizeof (*h)->bits;
+
+               /* WARNING:  This code relies on the fact that an image file not
+                            "memory mapped" was read entirely into a single
+                  buffer by "TIFFInitOJPEG()", so we can do a fast memory-to-
+                  memory copy here.  Each table consists of 16 Bytes, which are
+                  suffixed to a 0 Byte when copied, followed by a variable
+                  number of Bytes whose length is the sum of the first 16.
+               */
+                  if (!( *h
+                       = CALLJPEG(sp,0,jpeg_alloc_huff_table(&sp->cinfo.comm))
+                       )
+                     )
+                    {
+                      TIFFError(JPEGLib_name,"No space for Huffman table");
+                      return 0;
+                    };
+                  to = (*h++)->bits;
+                  *to++ = 0;
+                  while (--j > 0) size += *to++ = *from++; /* Copy 16 Bytes */
+                  if (size > sizeof (*h)->huffval/sizeof *(*h)->huffval)
+                    {
+                      TIFFError(tif->tif_name,"Huffman table too big");
+                      return 0;
+                    };
+                  if ((j = size) > 0) do *to++ = *from++; while (--j > 0);
+                  while (++size <= sizeof (*h)->huffval/sizeof *(*h)->huffval)
+                    *to++ = 0; /* Zero the rest of the table for cleanliness */
+                }
+              while (++i < v32);
+              sp->jpegtablesmode |= JPEGTABLESMODE_HUFF;
+            };
+          break;
+
+     /* The following vendor-specific TIFF tag occurs in (highly illegal) files
+        produced by the Wang Imaging application for Microsoft Windows.  These
+        can apparently have several "pages", in which case this tag specifies
+        the offset of a "page control" structure, which we don't currently know
+        how to handle.  0 indicates a 1-page image with no "page control", which
+        we make a feeble effort to handle.
+     */
+        case TIFFTAG_WANG_PAGECONTROL      :
+          if (v32 == 0) v32 = -1;
+          sp->is_WANG = v32;
+          tag = TIFFTAG_JPEGPROC+FIELD_WANG_PAGECONTROL-FIELD_JPEGPROC;
+          break;
+
+     /* This pseudo tag indicates whether our caller is expected to do YCbCr <->
+        RGB color-space conversion (JPEGCOLORMODE_RAW <=> 0) or whether we must
+        ask the JPEG Library to do it (JPEGCOLORMODE_RGB <=> 1).
+     */
+        case TIFFTAG_JPEGCOLORMODE         :
+          sp->jpegcolormode = v32;
+
+       /* Mark the image to indicate whether returned data is up-sampled, so
+          that "TIFF{Strip,Tile}Size()" reflect the true amount of data present.
+       */
+          v32 = tif->tif_flags; /* Save flags temporarily */
+          tif->tif_flags &= ~TIFF_UPSAMPLED;
+          if (   td->td_photometric == PHOTOMETRIC_YCBCR
+              &&    (td->td_ycbcrsubsampling[0]<<3 | td->td_ycbcrsubsampling[1])
+                 != 011
+              && sp->jpegcolormode == JPEGCOLORMODE_RGB
+             ) tif->tif_flags |= TIFF_UPSAMPLED;
+
+       /* If the up-sampling state changed, re-calculate tile size. */
+
+          if ((tif->tif_flags ^ v32) & TIFF_UPSAMPLED)
+            {
+              tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tsize_t) -1;
+              tif->tif_flags |= TIFF_DIRTYDIRECT;
+            };
+          return 1;
+      };
+    TIFFSetFieldBit(tif,tag-TIFFTAG_JPEGPROC+FIELD_JPEGPROC);
+    return 1;
+#   undef td
+  }
+
+static int
+OJPEGVGetField(register TIFF *tif,ttag_t tag,va_list ap)
+  { register OJPEGState *sp = OJState(tif);
+
+    switch (tag)
+      {
+
+     /* If this file has managed to synthesize a set of consolidated "metadata"
+        tables for the current (post-TIFF Version 6.0 specification) JPEG-in-
+        TIFF encapsulation strategy, then tell our caller about them; otherwise,
+        keep mum.
+     */
+        case TIFFTAG_JPEGTABLES            :
+          if (sp->jpegtables_length) /* we have "new"-style JPEG tables */
+            {
+              *va_arg(ap,uint32 *) = sp->jpegtables_length;
+              *va_arg(ap,char **) = sp->jpegtables;
+              return 1;
+            };
+
+     /* This pseudo tag indicates whether our caller is expected to do YCbCr <->
+        RGB color-space conversion (JPEGCOLORMODE_RAW <=> 0) or whether we must
+        ask the JPEG Library to do it (JPEGCOLORMODE_RGB <=> 1).
+     */
+        case TIFFTAG_JPEGCOLORMODE         :
+          *va_arg(ap,uint32 *) = sp->jpegcolormode;
+          return 1;
+
+     /* The following tags are defined by the TIFF Version 6.0 specification
+        and are obsolete.  If our caller asks for information about them, do not
+        return anything, even if we parsed them in an old-format "source" image.
+     */
+        case TIFFTAG_JPEGPROC              :
+    *va_arg(ap, uint16*)=sp->jpegproc;
+    return(1);
+    break;
+        case TIFFTAG_JPEGIFOFFSET          :
+    *va_arg(ap, uint32*)=sp->jpegifoffset;
+    return(1);
+    break;
+        case TIFFTAG_JPEGIFBYTECOUNT       :
+    *va_arg(ap, uint32*)=sp->jpegifbytecount;
+    return(1);
+    break;
+        case TIFFTAG_JPEGRESTARTINTERVAL   :
+    *va_arg(ap, uint32*)=sp->jpegrestartinterval;
+    return(1);
+    break;
+        case TIFFTAG_JPEGLOSSLESSPREDICTORS:
+                *va_arg(ap, uint32*)=sp->jpeglosslesspredictors_length;
+                *va_arg(ap, void**)=sp->jpeglosslesspredictors;
+                return(1);
+                break;
+        case TIFFTAG_JPEGPOINTTRANSFORM    :
+                *va_arg(ap, uint32*)=sp->jpegpointtransform_length;
+                *va_arg(ap, void**)=sp->jpegpointtransform;
+                return(1);
+                break;
+        case TIFFTAG_JPEGQTABLES           :
+                *va_arg(ap, uint32*)=sp->jpegqtables_length;
+                *va_arg(ap, void**)=sp->jpegqtables;
+                return(1);
+                break;
+        case TIFFTAG_JPEGDCTABLES          :
+                *va_arg(ap, uint32*)=sp->jpegdctables_length;
+                *va_arg(ap, void**)=sp->jpegdctables;
+                return(1);
+                break;
+        case TIFFTAG_JPEGACTABLES          : 
+                *va_arg(ap, uint32*)=sp->jpegactables_length;
+                *va_arg(ap, void**)=sp->jpegactables;
+                return(1);
+                break;
+      };
+    return (*sp->vgetparent)(tif,tag,ap);
+  }
+
+static void
+OJPEGPrintDir(register TIFF *tif,FILE *fd,long flags)
+  { register OJPEGState *sp = OJState(tif);
+
+    if (   ( flags
+           & (TIFFPRINT_JPEGQTABLES|TIFFPRINT_JPEGDCTABLES|TIFFPRINT_JPEGACTABLES)
+           )
+        && sp->jpegtables_length
+       )
+      fprintf(fd,"  JPEG Table Data: <present>, %lu bytes\n",
+        sp->jpegtables_length);
+  }
+
+static uint32
+OJPEGDefaultStripSize(register TIFF *tif,register uint32 s)
+  { register OJPEGState *sp = OJState(tif);
+#   define td (&tif->tif_dir)
+
+    if ((s = (*sp->defsparent)(tif,s)) < td->td_imagelength)
+      { register tsize_t size = sp->cinfo.comm.is_decompressor
+#                             ifdef D_LOSSLESS_SUPPORTED
+                              ? sp->cinfo.d.min_codec_data_unit
+#                             else
+                              ? DCTSIZE
+#                             endif
+#                             ifdef C_LOSSLESS_SUPPORTED
+                              : sp->cinfo.c.data_unit;
+#                             else
+                              : DCTSIZE;
+#                             endif
+
+        size = TIFFroundup(size,16);
+        s = TIFFroundup(s,td->td_ycbcrsubsampling[1]*size);
+      };
+    return s;
+#   undef td
+  }
+
+static void
+OJPEGDefaultTileSize(register TIFF *tif,register uint32 *tw,register uint32 *th)
+  { register OJPEGState *sp = OJState(tif);
+    register tsize_t size;
+#   define td (&tif->tif_dir)
+
+    size = sp->cinfo.comm.is_decompressor
+#        ifdef D_LOSSLESS_SUPPORTED
+         ? sp->cinfo.d.min_codec_data_unit
+#        else
+         ? DCTSIZE
+#        endif
+#        ifdef C_LOSSLESS_SUPPORTED
+         : sp->cinfo.c.data_unit;
+#        else
+         : DCTSIZE;
+#        endif
+    size = TIFFroundup(size,16);
+    (*sp->deftparent)(tif,tw,th);
+    *tw = TIFFroundup(*tw,td->td_ycbcrsubsampling[0]*size);
+    *th = TIFFroundup(*th,td->td_ycbcrsubsampling[1]*size);
+#   undef td
+  }
+
+static void
+OJPEGCleanUp(register TIFF *tif)
+  { register OJPEGState *sp;
+
+    if ( (sp = OJState(tif)) )
+      {
+        CALLVJPEG(sp,jpeg_destroy(&sp->cinfo.comm)); /* Free JPEG Lib. vars. */
+        if (sp->jpegtables) {_TIFFfree(sp->jpegtables);sp->jpegtables=0;}
+        if (sp->jpeglosslesspredictors) {
+    _TIFFfree(sp->jpeglosslesspredictors);
+    sp->jpeglosslesspredictors = 0;
+  }
+        if (sp->jpegpointtransform) {
+    _TIFFfree(sp->jpegpointtransform);
+    sp->jpegpointtransform=0;
+  }
+        if (sp->jpegqtables) {_TIFFfree(sp->jpegqtables);sp->jpegqtables=0;}
+        if (sp->jpegactables) {_TIFFfree(sp->jpegactables);sp->jpegactables=0;}
+        if (sp->jpegdctables) {_TIFFfree(sp->jpegdctables);sp->jpegdctables=0;}
+     /* If the image file isn't "memory mapped" and we read it all into a
+        single, large memory buffer, free the buffer now.
+     */
+        if (!isMapped(tif) && tif->tif_base) /* free whole-file buffer */
+          {
+            _TIFFfree(tif->tif_base);
+            tif->tif_base = 0;
+            tif->tif_size = 0;
+          };
+        _TIFFfree(sp); /* Release local variables */
+        tif->tif_data = 0;
+      }
+  }
+
+int
+TIFFInitOJPEG(register TIFF *tif,int scheme)
+  { register OJPEGState *sp;
+#   define td (&tif->tif_dir)
+#   ifndef never
+
+ /* This module supports a decompression-only CODEC, which is intended strictly
+    for viewing old image files using the obsolete JPEG-in-TIFF encapsulation
+    specified by the TIFF Version 6.0 specification.  It does not, and never
+    should, support compression for new images.  If a client application asks us
+    to, refuse and complain loudly!
+ */
+    if (tif->tif_mode != O_RDONLY) return _notSupported(tif);
+#   endif /* never */
+    if (!isMapped(tif))
+      {
+
+     /* BEWARE OF KLUDGE:  If our host operating-system doesn't let an image
+                           file be "memory mapped", then we want to read the
+        entire file into a single (possibly large) memory buffer as if it had
+        been "memory mapped".  Although this is likely to waste space, because
+        analysis of the file's content might cause parts of it to be read into
+        smaller buffers duplicatively, it appears to be the lesser of several
+        evils.  Very old JPEG-in-TIFF encapsulations aren't guaranteed to be
+        JFIF bit streams, or to have a TIFF "JPEGTables" record or much other
+        "metadata" to help us locate the decoding tables and entropy-coded data,
+        so we're likely do a lot of random-access grokking around, and we must
+        ultimately tell the JPEG Library to sequentially scan much of the file
+        anyway.  This is all likely to be easier if we use "brute force" to
+        read the entire file, once, and don't use incremental disc I/O.  If our
+        client application tries to process a file so big that we can't buffer
+        it entirely, then tough shit: we'll give up and exit!
+     */
+        if (!(tif->tif_base = _TIFFmalloc(tif->tif_size=TIFFGetFileSize(tif))))
+          {
+            TIFFError(tif->tif_name,"Cannot allocate file buffer");
+            return 0;
+          };
+        if (!SeekOK(tif,0) || !ReadOK(tif,tif->tif_base,tif->tif_size))
+          {
+            TIFFError(tif->tif_name,"Cannot read file");
+            return 0;
+          }
+      };
+
+ /* Allocate storage for this module's per-file variables. */
+
+    if (!(tif->tif_data = (tidata_t)_TIFFmalloc(sizeof *sp)))
+      {
+        TIFFError("TIFFInitOJPEG","No space for JPEG state block");
+        return 0;
+      };
+    (sp = OJState(tif))->tif = tif; /* Initialize reverse pointer */
+    sp->cinfo.d.err = jpeg_std_error(&sp->err); /* Initialize error handling */
+    sp->err.error_exit = TIFFojpeg_error_exit;
+    sp->err.output_message = TIFFojpeg_output_message;
+    if (!CALLVJPEG(sp,jpeg_create_decompress(&sp->cinfo.d))) return 0;
+
+ /* Install CODEC-specific tag information and override default TIFF Library
+    "method" subroutines with our own, CODEC-specific methods.  Like all good
+    members of an object-class, we save some of these subroutine pointers for
+    "fall back" in case our own methods fail.
+ */
+    _TIFFMergeFieldInfo(tif,ojpegFieldInfo,
+      sizeof ojpegFieldInfo/sizeof *ojpegFieldInfo);
+    sp->defsparent = tif->tif_defstripsize;
+    sp->deftparent = tif->tif_deftilesize;
+    sp->vgetparent = tif->tif_tagmethods.vgetfield;
+    sp->vsetparent = tif->tif_tagmethods.vsetfield;
+    tif->tif_defstripsize = OJPEGDefaultStripSize;
+    tif->tif_deftilesize = OJPEGDefaultTileSize;
+    tif->tif_tagmethods.vgetfield = OJPEGVGetField;
+    tif->tif_tagmethods.vsetfield = OJPEGVSetField;
+    tif->tif_tagmethods.printdir = OJPEGPrintDir;
+#   ifdef never
+    tif->tif_setupencode = OJPEGSetupEncode;
+    tif->tif_preencode = OJPEGPreEncode;
+    tif->tif_postencode = OJPEGPostEncode;
+#   else /* well, hardly ever */
+    tif->tif_setupencode = tif->tif_postencode = _notSupported;
+    tif->tif_preencode = (TIFFPreMethod)_notSupported;
+#   endif /* never */
+    tif->tif_setupdecode = OJPEGSetupDecode;
+    tif->tif_predecode = OJPEGPreDecode;
+    tif->tif_postdecode = OJPEGPostDecode;
+    tif->tif_cleanup = OJPEGCleanUp;
+
+ /* If the image file doesn't have "JPEGInterchangeFormat[Length]" TIFF records
+    to guide us, we have few clues about where its encapsulated JPEG bit stream
+    is located, so establish intelligent defaults:  If the Image File Directory
+    doesn't immediately follow the TIFF header, assume that the JPEG data lies
+    in between; otherwise, assume that it follows the Image File Directory.
+ */
+    if (tif->tif_header.tiff_diroff > sizeof tif->tif_header)
+      {
+        sp->src.next_input_byte = tif->tif_base + sizeof tif->tif_header;
+        sp->src.bytes_in_buffer = tif->tif_header.tiff_diroff
+                                - sizeof tif->tif_header;
+      }
+    else /* this case is ugly! */
+      { uint32 maxoffset = tif->tif_size;
+        uint16 dircount;
+
+     /* Calculate the offset to the next Image File Directory, if there is one,
+        or to the end of the file, if not.  Then arrange to read the file from
+        the end of the Image File Directory to that offset.
+     */
+        if (tif->tif_nextdiroff) maxoffset = tif->tif_nextdiroff; /* Not EOF */
+        _TIFFmemcpy(&dircount,(const tdata_t)
+          (sp->src.next_input_byte = tif->tif_base+tif->tif_header.tiff_diroff),
+          sizeof dircount);
+        if (tif->tif_flags & TIFF_SWAB) TIFFSwabShort(&dircount);
+        sp->src.next_input_byte += dircount*sizeof(TIFFDirEntry)
+                                + sizeof maxoffset + sizeof dircount;
+        sp->src.bytes_in_buffer = tif->tif_base - sp->src.next_input_byte
+                                + maxoffset;
+      };
+
+ /* IJG JPEG Library Version 6B can be configured for either 8- or 12-bit sample
+    precision, but we assume that "old JPEG" TIFF clients only need 8 bits.
+ */
+    sp->cinfo.d.data_precision = 8;
+#   ifdef C_LOSSLESS_SUPPORTED
+
+ /* If the "JPEGProc" TIFF tag is missing from the Image File Dictionary, the
+    JPEG Library will use its (lossy) baseline sequential process by default.
+ */
+    sp->cinfo.d.data_unit = DCTSIZE;
+#   endif /* C_LOSSLESS_SUPPORTED */
+
+ /* Initialize other CODEC-specific variables requiring default values. */
+
+    tif->tif_flags |= TIFF_NOBITREV; /* No bit-reversal within data bytes */
+    sp->h_sampling = sp->v_sampling = 1; /* No subsampling by default */
+    sp->is_WANG = 0; /* Assume not a MS Windows Wang Imaging file by default */
+    sp->jpegtables = 0; /* No "new"-style JPEG tables synthesized yet */
+    sp->jpegtables_length = 0;
+    sp->jpegquality = 75; /* Default IJG quality */
+    sp->jpegcolormode = JPEGCOLORMODE_RAW;
+    sp->jpegtablesmode = 0; /* No tables found yet */
+    sp->jpeglosslesspredictors=0;
+    sp->jpeglosslesspredictors_length=0;
+    sp->jpegpointtransform=0;
+    sp->jpegpointtransform_length=0;
+    sp->jpegqtables=0;
+    sp->jpegqtables_length=0;
+    sp->jpegdctables=0;
+    sp->jpegdctables_length=0;
+    sp->jpegactables=0;
+    sp->jpegactables_length=0;
+    return 1;
+#   undef td
+  }
+#endif /* OJPEG_SUPPORT */
+
diff --git a/Utilities/ITK/Utilities/tiff/tif_open.c b/Utilities/ITK/Utilities/tiff/tif_open.c
new file mode 100644
index 0000000000..625bff527a
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_open.c
@@ -0,0 +1,642 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ */
+#include "tiffiop.h"
+
+void _TIFFSetDefaultCompressionState(TIFF* tif);
+
+static const long typemask[13] = {
+  (long)0L,    /* TIFF_NOTYPE */
+  (long)0x000000ffL,  /* TIFF_BYTE */
+  (long)0xffffffffL,  /* TIFF_ASCII */
+  (long)0x0000ffffL,  /* TIFF_SHORT */
+  (long)0xffffffffL,  /* TIFF_LONG */
+  (long)0xffffffffL,  /* TIFF_RATIONAL */
+  (long)0x000000ffL,  /* TIFF_SBYTE */
+  (long)0x000000ffL,  /* TIFF_UNDEFINED */
+  (long)0x0000ffffL,  /* TIFF_SSHORT */
+  (long)0xffffffffL,  /* TIFF_SLONG */
+  (long)0xffffffffL,  /* TIFF_SRATIONAL */
+  (long)0xffffffffL,  /* TIFF_FLOAT */
+  (long)0xffffffffL,  /* TIFF_DOUBLE */
+};
+static const int bigTypeshift[13] = {
+  0,    /* TIFF_NOTYPE */
+  24,    /* TIFF_BYTE */
+  0,    /* TIFF_ASCII */
+  16,    /* TIFF_SHORT */
+  0,    /* TIFF_LONG */
+  0,    /* TIFF_RATIONAL */
+  24,    /* TIFF_SBYTE */
+  24,    /* TIFF_UNDEFINED */
+  16,    /* TIFF_SSHORT */
+  0,    /* TIFF_SLONG */
+  0,    /* TIFF_SRATIONAL */
+  0,    /* TIFF_FLOAT */
+  0,    /* TIFF_DOUBLE */
+};
+static const int litTypeshift[13] = {
+  0,    /* TIFF_NOTYPE */
+  0,    /* TIFF_BYTE */
+  0,    /* TIFF_ASCII */
+  0,    /* TIFF_SHORT */
+  0,    /* TIFF_LONG */
+  0,    /* TIFF_RATIONAL */
+  0,    /* TIFF_SBYTE */
+  0,    /* TIFF_UNDEFINED */
+  0,    /* TIFF_SSHORT */
+  0,    /* TIFF_SLONG */
+  0,    /* TIFF_SRATIONAL */
+  0,    /* TIFF_FLOAT */
+  0,    /* TIFF_DOUBLE */
+};
+
+/*
+ * Dummy functions to fill the omitted client procedures.
+ */
+static int
+_tiffDummyMapProc(thandle_t d, tdata_t* pbase, toff_t* psize)
+{
+  (void)d;
+  (void)pbase;
+  (void)psize;
+  return (0);
+}
+
+static void
+_tiffDummyUnmapProc(thandle_t fd, tdata_t base, toff_t size)
+{
+  (void)fd;
+  (void)base;
+  (void)size;
+}
+
+/*
+ * Initialize the shift & mask tables, and the
+ * byte swapping state according to the file
+ * contents and the machine architecture.
+ */
+static void
+TIFFInitOrder(TIFF* tif, int magic, int bigendian)
+{
+  tif->tif_typemask = typemask;
+  if (magic == TIFF_BIGENDIAN) {
+    tif->tif_typeshift = bigTypeshift;
+    if (!bigendian)
+      tif->tif_flags |= TIFF_SWAB;
+  } else {
+    tif->tif_typeshift = litTypeshift;
+    if (bigendian)
+      tif->tif_flags |= TIFF_SWAB;
+  }
+}
+
+int
+_TIFFgetMode(const char* mode, const char* module)
+{
+  int m = -1;
+
+  switch (mode[0]) {
+  case 'r':
+    m = O_RDONLY;
+    if (mode[1] == '+')
+      m = O_RDWR;
+    break;
+  case 'w':
+  case 'a':
+    m = O_RDWR|O_CREAT;
+    if (mode[0] == 'w')
+      m |= O_TRUNC;
+    break;
+  default:
+    TIFFError(module, "\"%s\": Bad mode", mode);
+    break;
+  }
+  return (m);
+}
+
+TIFF*
+TIFFClientOpen(
+  const char* name, const char* mode,
+  thandle_t clientdata,
+  TIFFReadWriteProc readproc,
+  TIFFReadWriteProc writeproc,
+  TIFFSeekProc seekproc,
+  TIFFCloseProc closeproc,
+  TIFFSizeProc sizeproc,
+  TIFFMapFileProc mapproc,
+  TIFFUnmapFileProc unmapproc
+)
+{
+  static const char module[] = "TIFFClientOpen";
+  TIFF *tif;
+  int m, bigendian;
+  const char* cp;
+
+  m = _TIFFgetMode(mode, module);
+  if (m == -1)
+    goto bad2;
+  tif = (TIFF *)_TIFFmalloc(sizeof (TIFF) + strlen(name) + 1);
+  if (tif == NULL) {
+    TIFFError(module, "%s: Out of memory (TIFF structure)", name);
+    goto bad2;
+  }
+  _TIFFmemset(tif, 0, sizeof (*tif));
+  tif->tif_name = (char *)tif + sizeof (TIFF);
+  strcpy(tif->tif_name, name);
+  tif->tif_mode = m &~ (O_CREAT|O_TRUNC);
+  tif->tif_curdir = (tdir_t) -1;    /* non-existent directory */
+  tif->tif_curoff = 0;
+  tif->tif_curstrip = (tstrip_t) -1;  /* invalid strip */
+  tif->tif_row = (uint32) -1;    /* read/write pre-increment */
+  tif->tif_clientdata = clientdata;
+  if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc) {
+    TIFFError(module,
+        "One of the client procedures is NULL pointer.");
+    goto bad2;
+  }
+  tif->tif_readproc = readproc;
+  tif->tif_writeproc = writeproc;
+  tif->tif_seekproc = seekproc;
+  tif->tif_closeproc = closeproc;
+  tif->tif_sizeproc = sizeproc;
+        if (mapproc)
+    tif->tif_mapproc = mapproc;
+  else
+    tif->tif_mapproc = _tiffDummyMapProc;
+  if (unmapproc)
+    tif->tif_unmapproc = unmapproc;
+  else
+    tif->tif_unmapproc = _tiffDummyUnmapProc;
+  _TIFFSetDefaultCompressionState(tif);  /* setup default state */
+  /*
+   * Default is to return data MSB2LSB and enable the
+   * use of memory-mapped files and strip chopping when
+   * a file is opened read-only.
+   */
+  tif->tif_flags = FILLORDER_MSB2LSB;
+  if (m == O_RDONLY )
+            tif->tif_flags |= TIFF_MAPPED;
+
+#ifdef STRIPCHOP_DEFAULT
+  if (m == O_RDONLY || m == O_RDWR)
+    tif->tif_flags |= STRIPCHOP_DEFAULT;
+#endif
+
+  { union { int32 i; char c[4]; } u; u.i = 1; bigendian = u.c[0] == 0; }
+  /*
+   * Process library-specific flags in the open mode string.
+   * The following flags may be used to control intrinsic library
+   * behaviour that may or may not be desirable (usually for
+   * compatibility with some application that claims to support
+   * TIFF but only supports some braindead idea of what the
+   * vendor thinks TIFF is):
+   *
+   * 'l'    use little-endian byte order for creating a file
+   * 'b'    use big-endian byte order for creating a file
+   * 'L'    read/write information using LSB2MSB bit order
+   * 'B'    read/write information using MSB2LSB bit order
+   * 'H'    read/write information using host bit order
+   * 'M'    enable use of memory-mapped files when supported
+   * 'm'    disable use of memory-mapped files
+   * 'C'    enable strip chopping support when reading
+   * 'c'    disable strip chopping support
+   *
+   * The use of the 'l' and 'b' flags is strongly discouraged.
+   * These flags are provided solely because numerous vendors,
+   * typically on the PC, do not correctly support TIFF; they
+   * only support the Intel little-endian byte order.  This
+   * support is not configured by default because it supports
+   * the violation of the TIFF spec that says that readers *MUST*
+   * support both byte orders.  It is strongly recommended that
+   * you not use this feature except to deal with busted apps
+   * that write invalid TIFF.  And even in those cases you should
+   * bang on the vendors to fix their software.
+   *
+   * The 'L', 'B', and 'H' flags are intended for applications
+   * that can optimize operations on data by using a particular
+   * bit order.  By default the library returns data in MSB2LSB
+   * bit order for compatibiltiy with older versions of this
+   * library.  Returning data in the bit order of the native cpu
+   * makes the most sense but also requires applications to check
+   * the value of the FillOrder tag; something they probably do
+   * not do right now.
+   *
+   * The 'M' and 'm' flags are provided because some virtual memory
+   * systems exhibit poor behaviour when large images are mapped.
+   * These options permit clients to control the use of memory-mapped
+   * files on a per-file basis.
+   *
+   * The 'C' and 'c' flags are provided because the library support
+   * for chopping up large strips into multiple smaller strips is not
+   * application-transparent and as such can cause problems.  The 'c'
+   * option permits applications that only want to look at the tags,
+   * for example, to get the unadulterated TIFF tag information.
+   */
+  for (cp = mode; *cp; cp++)
+    switch (*cp) {
+    case 'b':
+      if ((m&O_CREAT) && !bigendian)
+        tif->tif_flags |= TIFF_SWAB;
+      break;
+    case 'l':
+      if ((m&O_CREAT) && bigendian)
+        tif->tif_flags |= TIFF_SWAB;
+      break;
+    case 'B':
+      tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
+          FILLORDER_MSB2LSB;
+      break;
+    case 'L':
+      tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
+          FILLORDER_LSB2MSB;
+      break;
+    case 'H':
+      tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
+          HOST_FILLORDER;
+      break;
+    case 'M':
+      if (m == O_RDONLY)
+        tif->tif_flags |= TIFF_MAPPED;
+      break;
+    case 'm':
+      if (m == O_RDONLY)
+        tif->tif_flags &= ~TIFF_MAPPED;
+      break;
+    case 'C':
+      if (m == O_RDONLY)
+        tif->tif_flags |= TIFF_STRIPCHOP;
+      break;
+    case 'c':
+      if (m == O_RDONLY)
+        tif->tif_flags &= ~TIFF_STRIPCHOP;
+      break;
+    }
+  /*
+   * Read in TIFF header.
+   */
+  if (!ReadOK(tif, &tif->tif_header, sizeof (TIFFHeader))) {
+    if (tif->tif_mode == O_RDONLY) {
+      TIFFError(name, "Cannot read TIFF header");
+      goto bad;
+    }
+    /*
+     * Setup header and write.
+     */
+    tif->tif_header.tiff_magic = tif->tif_flags & TIFF_SWAB
+        ? (bigendian ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN)
+        : (bigendian ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN);
+    tif->tif_header.tiff_version = TIFF_VERSION;
+    if (tif->tif_flags & TIFF_SWAB)
+      TIFFSwabShort(&tif->tif_header.tiff_version);
+    tif->tif_header.tiff_diroff = 0;  /* filled in later */
+
+    if (!WriteOK(tif, &tif->tif_header, sizeof (TIFFHeader))) {
+      TIFFError(name, "Error writing TIFF header");
+      goto bad;
+    }
+    /*
+     * Setup the byte order handling.
+     */
+    TIFFInitOrder(tif, tif->tif_header.tiff_magic, bigendian);
+    /*
+     * Setup default directory.
+     */
+    if (!TIFFDefaultDirectory(tif))
+      goto bad;
+    tif->tif_diroff = 0;
+    tif->tif_dirlist = NULL;
+    tif->tif_dirnumber = 0;
+    return (tif);
+  }
+  /*
+   * Setup the byte order handling.
+   */
+  if (tif->tif_header.tiff_magic != TIFF_BIGENDIAN &&
+      tif->tif_header.tiff_magic != TIFF_LITTLEENDIAN) {
+    TIFFError(name,  "Not a TIFF file, bad magic number %d (0x%x)",
+        tif->tif_header.tiff_magic,
+        tif->tif_header.tiff_magic);
+    goto bad;
+  }
+  TIFFInitOrder(tif, tif->tif_header.tiff_magic, bigendian);
+  /*
+   * Swap header if required.
+   */
+  if (tif->tif_flags & TIFF_SWAB) {
+    TIFFSwabShort(&tif->tif_header.tiff_version);
+    TIFFSwabLong(&tif->tif_header.tiff_diroff);
+  }
+  /*
+   * Now check version (if needed, it's been byte-swapped).
+   * Note that this isn't actually a version number, it's a
+   * magic number that doesn't change (stupid).
+   */
+  if (tif->tif_header.tiff_version == TIFF_BIGTIFF_VERSION) {
+    TIFFError(name,
+                          "This is a BigTIFF file.  This format not supported\n"
+                          "by this version of libtiff." );
+    goto bad;
+  }
+  if (tif->tif_header.tiff_version != TIFF_VERSION) {
+    TIFFError(name,
+        "Not a TIFF file, bad version number %d (0x%x)",
+        tif->tif_header.tiff_version,
+        tif->tif_header.tiff_version); 
+    goto bad;
+  }
+  tif->tif_flags |= TIFF_MYBUFFER;
+  tif->tif_rawcp = tif->tif_rawdata = 0;
+  tif->tif_rawdatasize = 0;
+  /*
+   * Setup initial directory.
+   */
+  switch (mode[0]) {
+  case 'r':
+    tif->tif_nextdiroff = tif->tif_header.tiff_diroff;
+    /*
+     * Try to use a memory-mapped file if the client
+     * has not explicitly suppressed usage with the
+     * 'm' flag in the open mode (see above).
+     */
+    if ((tif->tif_flags & TIFF_MAPPED) &&
+  !TIFFMapFileContents(tif, (tdata_t*) &tif->tif_base, &tif->tif_size))
+      tif->tif_flags &= ~TIFF_MAPPED;
+    if (TIFFReadDirectory(tif)) {
+      tif->tif_rawcc = -1;
+      tif->tif_flags |= TIFF_BUFFERSETUP;
+      return (tif);
+    }
+    break;
+  case 'a':
+    /*
+     * New directories are automatically append
+     * to the end of the directory chain when they
+     * are written out (see TIFFWriteDirectory).
+     */
+    if (!TIFFDefaultDirectory(tif))
+      goto bad;
+    return (tif);
+  }
+bad:
+  tif->tif_mode = O_RDONLY;  /* XXX avoid flush */
+        TIFFCleanup(tif);
+bad2:
+  return ((TIFF*)0);
+}
+
+/*
+ * Query functions to access private data.
+ */
+
+/*
+ * Return open file's name.
+ */
+const char *
+TIFFFileName(TIFF* tif)
+{
+  return (tif->tif_name);
+}
+
+/*
+ * Set the file name.
+ */
+const char *
+TIFFSetFileName(TIFF* tif, const char *name)
+{
+  const char* old_name = tif->tif_name;
+  tif->tif_name = (char *)name;
+  return (old_name);
+}
+
+/*
+ * Return open file's I/O descriptor.
+ */
+int
+TIFFFileno(TIFF* tif)
+{
+  return (tif->tif_fd);
+}
+
+/*
+ * Set open file's I/O descriptor, and return previous value.
+ */
+int
+TIFFSetFileno(TIFF* tif, int fd)
+{
+        int old_fd = tif->tif_fd;
+  tif->tif_fd = fd;
+  return old_fd;
+}
+
+/*
+ * Return open file's clientdata.
+ */
+thandle_t
+TIFFClientdata(TIFF* tif)
+{
+  return (tif->tif_clientdata);
+}
+
+/*
+ * Set open file's clientdata, and return previous value.
+ */
+thandle_t
+TIFFSetClientdata(TIFF* tif, thandle_t newvalue)
+{
+  thandle_t m = tif->tif_clientdata;
+  tif->tif_clientdata = newvalue;
+  return m;
+}
+
+/*
+ * Return read/write mode.
+ */
+int
+TIFFGetMode(TIFF* tif)
+{
+  return (tif->tif_mode);
+}
+
+/*
+ * Return read/write mode.
+ */
+int
+TIFFSetMode(TIFF* tif, int mode)
+{
+  int old_mode = tif->tif_mode;
+  tif->tif_mode = mode;
+  return (old_mode);
+}
+
+/*
+ * Return nonzero if file is organized in
+ * tiles; zero if organized as strips.
+ */
+int
+TIFFIsTiled(TIFF* tif)
+{
+  return (isTiled(tif));
+}
+
+/*
+ * Return current row being read/written.
+ */
+uint32
+TIFFCurrentRow(TIFF* tif)
+{
+  return (tif->tif_row);
+}
+
+/*
+ * Return index of the current directory.
+ */
+tdir_t
+TIFFCurrentDirectory(TIFF* tif)
+{
+  return (tif->tif_curdir);
+}
+
+/*
+ * Return current strip.
+ */
+tstrip_t
+TIFFCurrentStrip(TIFF* tif)
+{
+  return (tif->tif_curstrip);
+}
+
+/*
+ * Return current tile.
+ */
+ttile_t
+TIFFCurrentTile(TIFF* tif)
+{
+  return (tif->tif_curtile);
+}
+
+/*
+ * Return nonzero if the file has byte-swapped data.
+ */
+int
+TIFFIsByteSwapped(TIFF* tif)
+{
+  return ((tif->tif_flags & TIFF_SWAB) != 0);
+}
+
+/*
+ * Return nonzero if the data is returned up-sampled.
+ */
+int
+TIFFIsUpSampled(TIFF* tif)
+{
+  return (isUpSampled(tif));
+}
+
+/*
+ * Return nonzero if the data is returned in MSB-to-LSB bit order.
+ */
+int
+TIFFIsMSB2LSB(TIFF* tif)
+{
+  return (isFillOrder(tif, FILLORDER_MSB2LSB));
+}
+
+/*
+ * Return nonzero if given file was written in big-endian order.
+ */
+int
+TIFFIsBigEndian(TIFF* tif)
+{
+  return (tif->tif_header.tiff_magic == TIFF_BIGENDIAN);
+}
+
+/*
+ * Return pointer to file read method.
+ */
+TIFFReadWriteProc
+TIFFGetReadProc(TIFF* tif)
+{
+  return (tif->tif_readproc);
+}
+
+/*
+ * Return pointer to file write method.
+ */
+TIFFReadWriteProc
+TIFFGetWriteProc(TIFF* tif)
+{
+  return (tif->tif_writeproc);
+}
+
+/*
+ * Return pointer to file seek method.
+ */
+TIFFSeekProc
+TIFFGetSeekProc(TIFF* tif)
+{
+  return (tif->tif_seekproc);
+}
+
+/*
+ * Return pointer to file close method.
+ */
+TIFFCloseProc
+TIFFGetCloseProc(TIFF* tif)
+{
+  return (tif->tif_closeproc);
+}
+
+/*
+ * Return pointer to file size requesting method.
+ */
+TIFFSizeProc
+TIFFGetSizeProc(TIFF* tif)
+{
+  return (tif->tif_sizeproc);
+}
+
+/*
+ * Return pointer to memory mapping method.
+ */
+TIFFMapFileProc
+TIFFGetMapFileProc(TIFF* tif)
+{
+  return (tif->tif_mapproc);
+}
+
+/*
+ * Return pointer to memory unmapping method.
+ */
+TIFFUnmapFileProc
+TIFFGetUnmapFileProc(TIFF* tif)
+{
+  return (tif->tif_unmapproc);
+}
+
diff --git a/Utilities/ITK/Utilities/tiff/tif_packbits.c b/Utilities/ITK/Utilities/tiff/tif_packbits.c
new file mode 100644
index 0000000000..0632397d9c
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_packbits.c
@@ -0,0 +1,292 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+#include "tiffiop.h"
+#ifdef PACKBITS_SUPPORT
+/*
+ * TIFF Library.
+ *
+ * PackBits Compression Algorithm Support
+ */
+#include <stdio.h>
+
+static int
+PackBitsPreEncode(TIFF* tif, tsample_t s)
+{
+  (void) s;
+
+        if (!(tif->tif_data = _TIFFmalloc(sizeof(tsize_t))))
+    return (0);
+  /*
+   * Calculate the scanline/tile-width size in bytes.
+   */
+  if (isTiled(tif))
+    *(tsize_t*)tif->tif_data = TIFFTileRowSize(tif);
+  else
+    *(tsize_t*)tif->tif_data = TIFFScanlineSize(tif);
+  return (1);
+}
+
+static int
+PackBitsPostEncode(TIFF* tif)
+{
+        if (tif->tif_data)
+            _TIFFfree(tif->tif_data);
+  return (1);
+}
+
+/*
+ * NB: tidata is the type representing *(tidata_t);
+ *     if tidata_t is made signed then this type must
+ *     be adjusted accordingly.
+ */
+typedef unsigned char tidata;
+
+/*
+ * Encode a run of pixels.
+ */
+static int
+PackBitsEncode(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s)
+{
+  unsigned char* bp = (unsigned char*) buf;
+  tidata_t op, ep, lastliteral;
+  long n, slop;
+  int b;
+  enum { BASE, LITERAL, RUN, LITERAL_RUN } state;
+
+  (void) s;
+  op = tif->tif_rawcp;
+  ep = tif->tif_rawdata + tif->tif_rawdatasize;
+  state = BASE;
+  lastliteral = 0;
+  while (cc > 0) {
+    /*
+     * Find the longest string of identical bytes.
+     */
+    b = *bp++, cc--, n = 1;
+    for (; cc > 0 && b == *bp; cc--, bp++)
+      n++;
+  again:
+    if (op + 2 >= ep) {    /* insure space for new data */
+      /*
+       * Be careful about writing the last
+       * literal.  Must write up to that point
+       * and then copy the remainder to the
+       * front of the buffer.
+       */
+      if (state == LITERAL || state == LITERAL_RUN) {
+        slop = op - lastliteral;
+        tif->tif_rawcc += lastliteral - tif->tif_rawcp;
+        if (!TIFFFlushData1(tif))
+          return (-1);
+        op = tif->tif_rawcp;
+        while (slop-- > 0)
+          *op++ = *lastliteral++;
+        lastliteral = tif->tif_rawcp;
+      } else {
+        tif->tif_rawcc += op - tif->tif_rawcp;
+        if (!TIFFFlushData1(tif))
+          return (-1);
+        op = tif->tif_rawcp;
+      }
+    }
+    switch (state) {
+    case BASE:    /* initial state, set run/literal */
+      if (n > 1) {
+        state = RUN;
+        if (n > 128) {
+          *op++ = (tidata) -127;
+          *op++ = (tidataval_t) b;
+          n -= 128;
+          goto again;
+        }
+        *op++ = (tidataval_t)(-(n-1));
+        *op++ = (tidataval_t) b;
+      } else {
+        lastliteral = op;
+        *op++ = 0;
+        *op++ = (tidataval_t) b;
+        state = LITERAL;
+      }
+      break;
+    case LITERAL:    /* last object was literal string */
+      if (n > 1) {
+        state = LITERAL_RUN;
+        if (n > 128) {
+          *op++ = (tidata) -127;
+          *op++ = (tidataval_t) b;
+          n -= 128;
+          goto again;
+        }
+        *op++ = (tidataval_t)(-(n-1));  /* encode run */
+        *op++ = (tidataval_t) b;
+      } else {      /* extend literal */
+        if (++(*lastliteral) == 127)
+          state = BASE;
+        *op++ = (tidataval_t) b;
+      }
+      break;
+    case RUN:    /* last object was run */
+      if (n > 1) {
+        if (n > 128) {
+          *op++ = (tidata) -127;
+          *op++ = (tidataval_t) b;
+          n -= 128;
+          goto again;
+        }
+        *op++ = (tidataval_t)(-(n-1));
+        *op++ = (tidataval_t) b;
+      } else {
+        lastliteral = op;
+        *op++ = 0;
+        *op++ = (tidataval_t) b;
+        state = LITERAL;
+      }
+      break;
+    case LITERAL_RUN:  /* literal followed by a run */
+      /*
+       * Check to see if previous run should
+       * be converted to a literal, in which
+       * case we convert literal-run-literal
+       * to a single literal.
+       */
+      if (n == 1 && op[-2] == (tidata) -1 &&
+          *lastliteral < 126) {
+        state = (((*lastliteral) += 2) == 127 ?
+            BASE : LITERAL);
+        op[-2] = op[-1];  /* replicate */
+      } else
+        state = RUN;
+      goto again;
+    }
+  }
+  tif->tif_rawcc += op - tif->tif_rawcp;
+  tif->tif_rawcp = op;
+  return (1);
+}
+
+/*
+ * Encode a rectangular chunk of pixels.  We break it up
+ * into row-sized pieces to insure that encoded runs do
+ * not span rows.  Otherwise, there can be problems with
+ * the decoder if data is read, for example, by scanlines
+ * when it was encoded by strips.
+ */
+static int
+PackBitsEncodeChunk(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
+{
+  tsize_t rowsize = *(tsize_t*)tif->tif_data;
+
+  while ((long)cc > 0) {
+    int  chunk = rowsize;
+    
+    if( cc < chunk )
+        chunk = cc;
+
+    if (PackBitsEncode(tif, bp, chunk, s) < 0)
+        return (-1);
+    bp += chunk;
+    cc -= chunk;
+  }
+  return (1);
+}
+
+static int
+PackBitsDecode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s)
+{
+  char *bp;
+  tsize_t cc;
+  long n;
+  int b;
+
+  (void) s;
+  bp = (char*) tif->tif_rawcp;
+  cc = tif->tif_rawcc;
+  while (cc > 0 && (long)occ > 0) {
+    n = (long) *bp++, cc--;
+    /*
+     * Watch out for compilers that
+     * don't sign extend chars...
+     */
+    if (n >= 128)
+      n -= 256;
+    if (n < 0) {    /* replicate next byte -n+1 times */
+      if (n == -128)  /* nop */
+        continue;
+                        n = -n + 1;
+                        if( occ < n )
+                        {
+                            TIFFWarning(tif->tif_name,
+                                        "PackBitsDecode: discarding %d bytes "
+                                        "to avoid buffer overrun",
+                                        n - occ);
+                            n = occ;
+                        }
+      occ -= n;
+      b = *bp++, cc--;
+      while (n-- > 0)
+        *op++ = (tidataval_t) b;
+    } else {    /* copy next n+1 bytes literally */
+      if (occ < n + 1)
+                        {
+                            TIFFWarning(tif->tif_name,
+                                        "PackBitsDecode: discarding %d bytes "
+                                        "to avoid buffer overrun",
+                                        n - occ + 1);
+                            n = occ - 1;
+                        }
+                        _TIFFmemcpy(op, bp, ++n);
+      op += n; occ -= n;
+      bp += n; cc -= n;
+    }
+  }
+  tif->tif_rawcp = (tidata_t) bp;
+  tif->tif_rawcc = cc;
+  if (occ > 0) {
+    TIFFError(tif->tif_name,
+        "PackBitsDecode: Not enough data for scanline %ld",
+        (long) tif->tif_row);
+    return (0);
+  }
+  return (1);
+}
+
+int
+TIFFInitPackBits(TIFF* tif, int scheme)
+{
+  (void) scheme;
+  tif->tif_decoderow = PackBitsDecode;
+  tif->tif_decodestrip = PackBitsDecode;
+  tif->tif_decodetile = PackBitsDecode;
+  tif->tif_preencode = PackBitsPreEncode;
+        tif->tif_postencode = PackBitsPostEncode;
+  tif->tif_encoderow = PackBitsEncode;
+  tif->tif_encodestrip = PackBitsEncodeChunk;
+  tif->tif_encodetile = PackBitsEncodeChunk;
+  return (1);
+}
+#endif /* PACKBITS_SUPPORT */
+
diff --git a/Utilities/ITK/Utilities/tiff/tif_pixarlog.c b/Utilities/ITK/Utilities/tiff/tif_pixarlog.c
new file mode 100644
index 0000000000..1512faba8e
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_pixarlog.c
@@ -0,0 +1,1333 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1996-1997 Sam Leffler
+ * Copyright (c) 1996 Pixar
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Pixar, Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Pixar, Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL PIXAR, SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+#include "tiffiop.h"
+#ifdef PIXARLOG_SUPPORT
+
+/*
+ * TIFF Library.
+ * PixarLog Compression Support
+ *
+ * Contributed by Dan McCoy.
+ *
+ * PixarLog film support uses the TIFF library to store companded
+ * 11 bit values into a tiff file, which are compressed using the 
+ * zip compressor.  
+ *
+ * The codec can take as input and produce as output 32-bit IEEE float values 
+ * as well as 16-bit or 8-bit unsigned integer values.
+ *
+ * On writing any of the above are converted into the internal
+ * 11-bit log format.   In the case of  8 and 16 bit values, the
+ * input is assumed to be unsigned linear color values that represent
+ * the range 0-1.  In the case of IEEE values, the 0-1 range is assumed to
+ * be the normal linear color range, in addition over 1 values are
+ * accepted up to a value of about 25.0 to encode "hot" hightlights and such.
+ * The encoding is lossless for 8-bit values, slightly lossy for the
+ * other bit depths.  The actual color precision should be better
+ * than the human eye can perceive with extra room to allow for
+ * error introduced by further image computation.  As with any quantized
+ * color format, it is possible to perform image calculations which
+ * expose the quantization error. This format should certainly be less 
+ * susceptable to such errors than standard 8-bit encodings, but more
+ * susceptable than straight 16-bit or 32-bit encodings.
+ *
+ * On reading the internal format is converted to the desired output format.
+ * The program can request which format it desires by setting the internal
+ * pseudo tag TIFFTAG_PIXARLOGDATAFMT to one of these possible values:
+ *  PIXARLOGDATAFMT_FLOAT     = provide IEEE float values.
+ *  PIXARLOGDATAFMT_16BIT     = provide unsigned 16-bit integer values
+ *  PIXARLOGDATAFMT_8BIT      = provide unsigned 8-bit integer values
+ *
+ * alternately PIXARLOGDATAFMT_8BITABGR provides unsigned 8-bit integer
+ * values with the difference that if there are exactly three or four channels
+ * (rgb or rgba) it swaps the channel order (bgr or abgr).
+ *
+ * PIXARLOGDATAFMT_11BITLOG provides the internal encoding directly
+ * packed in 16-bit values.   However no tools are supplied for interpreting
+ * these values.
+ *
+ * "hot" (over 1.0) areas written in floating point get clamped to
+ * 1.0 in the integer data types.
+ *
+ * When the file is closed after writing, the bit depth and sample format
+ * are set always to appear as if 8-bit data has been written into it.
+ * That way a naive program unaware of the particulars of the encoding
+ * gets the format it is most likely able to handle.
+ *
+ * The codec does it's own horizontal differencing step on the coded
+ * values so the libraries predictor stuff should be turned off.
+ * The codec also handle byte swapping the encoded values as necessary
+ * since the library does not have the information necessary
+ * to know the bit depth of the raw unencoded buffer.
+ * 
+ */
+
+#include "tif_predict.h"
+#include "zlib.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+/* Tables for converting to/from 11 bit coded values */
+
+#define  TSIZE   2048    /* decode table size (11-bit tokens) */
+#define  TSIZEP1 2049    /* Plus one for slop */
+#define  ONE   1250    /* token value of 1.0 exactly */
+#define  RATIO   1.004    /* nominal ratio for log part */
+
+#define CODE_MASK 0x7ff         /* 11 bits. */
+
+static float  Fltsize;
+static float  LogK1, LogK2;
+
+#define REPEAT(n, op)   { int i; i=n; do { i--; op; } while (i>0); }
+
+static void
+horizontalAccumulateF(uint16 *wp, int n, int stride, float *op, 
+  float *ToLinearF)
+{
+    register unsigned int  cr, cg, cb, ca, mask;
+    register float  t0, t1, t2, t3;
+
+    if (n >= stride) {
+  mask = CODE_MASK;
+  if (stride == 3) {
+      t0 = ToLinearF[cr = wp[0]];
+      t1 = ToLinearF[cg = wp[1]];
+      t2 = ToLinearF[cb = wp[2]];
+      op[0] = t0;
+      op[1] = t1;
+      op[2] = t2;
+      n -= 3;
+      while (n > 0) {
+    wp += 3;
+    op += 3;
+    n -= 3;
+    t0 = ToLinearF[(cr += wp[0]) & mask];
+    t1 = ToLinearF[(cg += wp[1]) & mask];
+    t2 = ToLinearF[(cb += wp[2]) & mask];
+    op[0] = t0;
+    op[1] = t1;
+    op[2] = t2;
+      }
+  } else if (stride == 4) {
+      t0 = ToLinearF[cr = wp[0]];
+      t1 = ToLinearF[cg = wp[1]];
+      t2 = ToLinearF[cb = wp[2]];
+      t3 = ToLinearF[ca = wp[3]];
+      op[0] = t0;
+      op[1] = t1;
+      op[2] = t2;
+      op[3] = t3;
+      n -= 4;
+      while (n > 0) {
+    wp += 4;
+    op += 4;
+    n -= 4;
+    t0 = ToLinearF[(cr += wp[0]) & mask];
+    t1 = ToLinearF[(cg += wp[1]) & mask];
+    t2 = ToLinearF[(cb += wp[2]) & mask];
+    t3 = ToLinearF[(ca += wp[3]) & mask];
+    op[0] = t0;
+    op[1] = t1;
+    op[2] = t2;
+    op[3] = t3;
+      }
+  } else {
+      REPEAT(stride, *op = ToLinearF[*wp&mask]; wp++; op++)
+      n -= stride;
+      while (n > 0) {
+    REPEAT(stride,
+        wp[stride] += *wp; *op = ToLinearF[*wp&mask]; wp++; op++)
+    n -= stride;
+      }
+  }
+    }
+}
+
+static void
+horizontalAccumulate12(uint16 *wp, int n, int stride, int16 *op,
+  float *ToLinearF)
+{
+    register unsigned int  cr, cg, cb, ca, mask;
+    register float  t0, t1, t2, t3;
+
+#define SCALE12 2048.0F
+#define CLAMP12(t) (((t) < 3071) ? (uint16) (t) : 3071)
+
+    if (n >= stride) {
+  mask = CODE_MASK;
+  if (stride == 3) {
+      t0 = ToLinearF[cr = wp[0]] * SCALE12;
+      t1 = ToLinearF[cg = wp[1]] * SCALE12;
+      t2 = ToLinearF[cb = wp[2]] * SCALE12;
+      op[0] = CLAMP12(t0);
+      op[1] = CLAMP12(t1);
+      op[2] = CLAMP12(t2);
+      n -= 3;
+      while (n > 0) {
+    wp += 3;
+    op += 3;
+    n -= 3;
+    t0 = ToLinearF[(cr += wp[0]) & mask] * SCALE12;
+    t1 = ToLinearF[(cg += wp[1]) & mask] * SCALE12;
+    t2 = ToLinearF[(cb += wp[2]) & mask] * SCALE12;
+    op[0] = CLAMP12(t0);
+    op[1] = CLAMP12(t1);
+    op[2] = CLAMP12(t2);
+      }
+  } else if (stride == 4) {
+      t0 = ToLinearF[cr = wp[0]] * SCALE12;
+      t1 = ToLinearF[cg = wp[1]] * SCALE12;
+      t2 = ToLinearF[cb = wp[2]] * SCALE12;
+      t3 = ToLinearF[ca = wp[3]] * SCALE12;
+      op[0] = CLAMP12(t0);
+      op[1] = CLAMP12(t1);
+      op[2] = CLAMP12(t2);
+      op[3] = CLAMP12(t3);
+      n -= 4;
+      while (n > 0) {
+    wp += 4;
+    op += 4;
+    n -= 4;
+    t0 = ToLinearF[(cr += wp[0]) & mask] * SCALE12;
+    t1 = ToLinearF[(cg += wp[1]) & mask] * SCALE12;
+    t2 = ToLinearF[(cb += wp[2]) & mask] * SCALE12;
+    t3 = ToLinearF[(ca += wp[3]) & mask] * SCALE12;
+    op[0] = CLAMP12(t0);
+    op[1] = CLAMP12(t1);
+    op[2] = CLAMP12(t2);
+    op[3] = CLAMP12(t3);
+      }
+  } else {
+      REPEAT(stride, t0 = ToLinearF[*wp&mask] * SCALE12;
+                           *op = CLAMP12(t0); wp++; op++)
+      n -= stride;
+      while (n > 0) {
+    REPEAT(stride,
+        wp[stride] += *wp; t0 = ToLinearF[wp[stride]&mask]*SCALE12;
+        *op = CLAMP12(t0);  wp++; op++)
+    n -= stride;
+      }
+  }
+    }
+}
+
+static void
+horizontalAccumulate16(uint16 *wp, int n, int stride, uint16 *op,
+  uint16 *ToLinear16)
+{
+    register unsigned int  cr, cg, cb, ca, mask;
+
+    if (n >= stride) {
+  mask = CODE_MASK;
+  if (stride == 3) {
+      op[0] = ToLinear16[cr = wp[0]];
+      op[1] = ToLinear16[cg = wp[1]];
+      op[2] = ToLinear16[cb = wp[2]];
+      n -= 3;
+      while (n > 0) {
+    wp += 3;
+    op += 3;
+    n -= 3;
+    op[0] = ToLinear16[(cr += wp[0]) & mask];
+    op[1] = ToLinear16[(cg += wp[1]) & mask];
+    op[2] = ToLinear16[(cb += wp[2]) & mask];
+      }
+  } else if (stride == 4) {
+      op[0] = ToLinear16[cr = wp[0]];
+      op[1] = ToLinear16[cg = wp[1]];
+      op[2] = ToLinear16[cb = wp[2]];
+      op[3] = ToLinear16[ca = wp[3]];
+      n -= 4;
+      while (n > 0) {
+    wp += 4;
+    op += 4;
+    n -= 4;
+    op[0] = ToLinear16[(cr += wp[0]) & mask];
+    op[1] = ToLinear16[(cg += wp[1]) & mask];
+    op[2] = ToLinear16[(cb += wp[2]) & mask];
+    op[3] = ToLinear16[(ca += wp[3]) & mask];
+      }
+  } else {
+      REPEAT(stride, *op = ToLinear16[*wp&mask]; wp++; op++)
+      n -= stride;
+      while (n > 0) {
+    REPEAT(stride,
+        wp[stride] += *wp; *op = ToLinear16[*wp&mask]; wp++; op++)
+    n -= stride;
+      }
+  }
+    }
+}
+
+/* 
+ * Returns the log encoded 11-bit values with the horizontal
+ * differencing undone.
+ */
+static void
+horizontalAccumulate11(uint16 *wp, int n, int stride, uint16 *op)
+{
+    register unsigned int  cr, cg, cb, ca, mask;
+
+    if (n >= stride) {
+  mask = CODE_MASK;
+  if (stride == 3) {
+      op[0] = cr = wp[0];  op[1] = cg = wp[1];  op[2] = cb = wp[2];
+      n -= 3;
+      while (n > 0) {
+    wp += 3;
+    op += 3;
+    n -= 3;
+    op[0] = (cr += wp[0]) & mask;
+    op[1] = (cg += wp[1]) & mask;
+    op[2] = (cb += wp[2]) & mask;
+      }
+  } else if (stride == 4) {
+      op[0] = cr = wp[0];  op[1] = cg = wp[1];
+      op[2] = cb = wp[2];  op[3] = ca = wp[3];
+      n -= 4;
+      while (n > 0) {
+    wp += 4;
+    op += 4;
+    n -= 4;
+    op[0] = (cr += wp[0]) & mask;
+    op[1] = (cg += wp[1]) & mask;
+    op[2] = (cb += wp[2]) & mask;
+    op[3] = (ca += wp[3]) & mask;
+      } 
+  } else {
+      REPEAT(stride, *op = *wp&mask; wp++; op++)
+      n -= stride;
+      while (n > 0) {
+    REPEAT(stride,
+        wp[stride] += *wp; *op = *wp&mask; wp++; op++)
+        n -= stride;
+      }
+  }
+    }
+}
+
+static void
+horizontalAccumulate8(uint16 *wp, int n, int stride, unsigned char *op,
+  unsigned char *ToLinear8)
+{
+    register unsigned int  cr, cg, cb, ca, mask;
+
+    if (n >= stride) {
+  mask = CODE_MASK;
+  if (stride == 3) {
+      op[0] = ToLinear8[cr = wp[0]];
+      op[1] = ToLinear8[cg = wp[1]];
+      op[2] = ToLinear8[cb = wp[2]];
+      n -= 3;
+      while (n > 0) {
+    n -= 3;
+    wp += 3;
+    op += 3;
+    op[0] = ToLinear8[(cr += wp[0]) & mask];
+    op[1] = ToLinear8[(cg += wp[1]) & mask];
+    op[2] = ToLinear8[(cb += wp[2]) & mask];
+      }
+  } else if (stride == 4) {
+      op[0] = ToLinear8[cr = wp[0]];
+      op[1] = ToLinear8[cg = wp[1]];
+      op[2] = ToLinear8[cb = wp[2]];
+      op[3] = ToLinear8[ca = wp[3]];
+      n -= 4;
+      while (n > 0) {
+    n -= 4;
+    wp += 4;
+    op += 4;
+    op[0] = ToLinear8[(cr += wp[0]) & mask];
+    op[1] = ToLinear8[(cg += wp[1]) & mask];
+    op[2] = ToLinear8[(cb += wp[2]) & mask];
+    op[3] = ToLinear8[(ca += wp[3]) & mask];
+      }
+  } else {
+      REPEAT(stride, *op = ToLinear8[*wp&mask]; wp++; op++)
+      n -= stride;
+      while (n > 0) {
+    REPEAT(stride,
+        wp[stride] += *wp; *op = ToLinear8[*wp&mask]; wp++; op++)
+    n -= stride;
+      }
+  }
+    }
+}
+
+
+static void
+horizontalAccumulate8abgr(uint16 *wp, int n, int stride, unsigned char *op,
+  unsigned char *ToLinear8)
+{
+    register unsigned int  cr, cg, cb, ca, mask;
+    register unsigned char  t0, t1, t2, t3;
+
+    if (n >= stride) {
+  mask = CODE_MASK;
+  if (stride == 3) {
+      op[0] = 0;
+      t1 = ToLinear8[cb = wp[2]];
+      t2 = ToLinear8[cg = wp[1]];
+      t3 = ToLinear8[cr = wp[0]];
+      op[1] = t1;
+      op[2] = t2;
+      op[3] = t3;
+      n -= 3;
+      while (n > 0) {
+    n -= 3;
+    wp += 3;
+    op += 4;
+    op[0] = 0;
+    t1 = ToLinear8[(cb += wp[2]) & mask];
+    t2 = ToLinear8[(cg += wp[1]) & mask];
+    t3 = ToLinear8[(cr += wp[0]) & mask];
+    op[1] = t1;
+    op[2] = t2;
+    op[3] = t3;
+      }
+  } else if (stride == 4) {
+      t0 = ToLinear8[ca = wp[3]];
+      t1 = ToLinear8[cb = wp[2]];
+      t2 = ToLinear8[cg = wp[1]];
+      t3 = ToLinear8[cr = wp[0]];
+      op[0] = t0;
+      op[1] = t1;
+      op[2] = t2;
+      op[3] = t3;
+      n -= 4;
+      while (n > 0) {
+    n -= 4;
+    wp += 4;
+    op += 4;
+    t0 = ToLinear8[(ca += wp[3]) & mask];
+    t1 = ToLinear8[(cb += wp[2]) & mask];
+    t2 = ToLinear8[(cg += wp[1]) & mask];
+    t3 = ToLinear8[(cr += wp[0]) & mask];
+    op[0] = t0;
+    op[1] = t1;
+    op[2] = t2;
+    op[3] = t3;
+      }
+  } else {
+      REPEAT(stride, *op = ToLinear8[*wp&mask]; wp++; op++)
+      n -= stride;
+      while (n > 0) {
+    REPEAT(stride,
+        wp[stride] += *wp; *op = ToLinear8[*wp&mask]; wp++; op++)
+    n -= stride;
+      }
+  }
+    }
+}
+
+/*
+ * State block for each open TIFF
+ * file using PixarLog compression/decompression.
+ */
+typedef  struct {
+  TIFFPredictorState  predict;
+  z_stream    stream;
+  uint16      *tbuf; 
+  uint16      stride;
+  int      state;
+  int      user_datafmt;
+  int      quality;
+#define PLSTATE_INIT 1
+
+  TIFFVSetMethod    vgetparent;  /* super-class method */
+  TIFFVSetMethod    vsetparent;  /* super-class method */
+
+  float *ToLinearF;
+  uint16 *ToLinear16;
+  unsigned char *ToLinear8;
+  uint16  *FromLT2;
+  uint16  *From14; /* Really for 16-bit data, but we shift down 2 */
+  uint16  *From8;
+  
+} PixarLogState;
+
+static int
+PixarLogMakeTables(PixarLogState *sp)
+{
+
+/*
+ *    We make several tables here to convert between various external
+ *    representations (float, 16-bit, and 8-bit) and the internal
+ *    11-bit companded representation.  The 11-bit representation has two
+ *    distinct regions.  A linear bottom end up through .018316 in steps
+ *    of about .000073, and a region of constant ratio up to about 25.
+ *    These floating point numbers are stored in the main table ToLinearF. 
+ *    All other tables are derived from this one.  The tables (and the
+ *    ratios) are continuous at the internal seam.
+ */
+
+    int  nlin, lt2size;
+    int  i, j;
+    double  b, c, linstep, v;
+    float *ToLinearF;
+    uint16 *ToLinear16;
+    unsigned char *ToLinear8;
+    uint16  *FromLT2;
+    uint16  *From14; /* Really for 16-bit data, but we shift down 2 */
+    uint16  *From8;
+
+    c = log(RATIO);  
+    nlin = (int)(1./c);  /* nlin must be an integer */
+    c = 1./nlin;
+    b = exp(-c*ONE);  /* multiplicative scale factor [b*exp(c*ONE) = 1] */
+    linstep = b*c*exp(1.);
+
+    LogK1 = (float)(1./c);  /* if (v >= 2)  token = k1*log(v*k2) */
+    LogK2 = (float)(1./b);
+    lt2size = (int)(2./linstep) + 1;
+    FromLT2 = (uint16 *)_TIFFmalloc(lt2size*sizeof(uint16));
+    From14 = (uint16 *)_TIFFmalloc(16384*sizeof(uint16));
+    From8 = (uint16 *)_TIFFmalloc(256*sizeof(uint16));
+    ToLinearF = (float *)_TIFFmalloc(TSIZEP1 * sizeof(float));
+    ToLinear16 = (uint16 *)_TIFFmalloc(TSIZEP1 * sizeof(uint16));
+    ToLinear8 = (unsigned char *)_TIFFmalloc(TSIZEP1 * sizeof(unsigned char));
+    if (FromLT2 == NULL || From14  == NULL || From8   == NULL ||
+   ToLinearF == NULL || ToLinear16 == NULL || ToLinear8 == NULL) {
+  if (FromLT2) _TIFFfree(FromLT2);
+  if (From14) _TIFFfree(From14);
+  if (From8) _TIFFfree(From8);
+  if (ToLinearF) _TIFFfree(ToLinearF);
+  if (ToLinear16) _TIFFfree(ToLinear16);
+  if (ToLinear8) _TIFFfree(ToLinear8);
+  sp->FromLT2 = NULL;
+  sp->From14 = NULL;
+  sp->From8 = NULL;
+  sp->ToLinearF = NULL;
+  sp->ToLinear16 = NULL;
+  sp->ToLinear8 = NULL;
+  return 0;
+    }
+
+    j = 0;
+
+    for (i = 0; i < nlin; i++)  {
+  v = i * linstep;
+  ToLinearF[j++] = (float)v;
+    }
+
+    for (i = nlin; i < TSIZE; i++)
+  ToLinearF[j++] = (float)(b*exp(c*i));
+
+    ToLinearF[2048] = ToLinearF[2047];
+
+    for (i = 0; i < TSIZEP1; i++)  {
+  v = ToLinearF[i]*65535.0 + 0.5;
+  ToLinear16[i] = (v > 65535.0) ? 65535 : (uint16)v;
+  v = ToLinearF[i]*255.0  + 0.5;
+  ToLinear8[i]  = (v > 255.0) ? 255 : (unsigned char)v;
+    }
+
+    j = 0;
+    for (i = 0; i < lt2size; i++)  {
+  if ((i*linstep)*(i*linstep) > ToLinearF[j]*ToLinearF[j+1])
+      j++;
+  FromLT2[i] = j;
+    }
+
+    /*
+     * Since we lose info anyway on 16-bit data, we set up a 14-bit
+     * table and shift 16-bit values down two bits on input.
+     * saves a little table space.
+     */
+    j = 0;
+    for (i = 0; i < 16384; i++)  {
+  while ((i/16383.)*(i/16383.) > ToLinearF[j]*ToLinearF[j+1])
+      j++;
+  From14[i] = j;
+    }
+
+    j = 0;
+    for (i = 0; i < 256; i++)  {
+  while ((i/255.)*(i/255.) > ToLinearF[j]*ToLinearF[j+1])
+      j++;
+  From8[i] = j;
+    }
+
+    Fltsize = (float)(lt2size/2);
+
+    sp->ToLinearF = ToLinearF;
+    sp->ToLinear16 = ToLinear16;
+    sp->ToLinear8 = ToLinear8;
+    sp->FromLT2 = FromLT2;
+    sp->From14 = From14;
+    sp->From8 = From8;
+
+    return 1;
+}
+
+#define  DecoderState(tif)  ((PixarLogState*) (tif)->tif_data)
+#define  EncoderState(tif)  ((PixarLogState*) (tif)->tif_data)
+
+static  int PixarLogEncode(TIFF*, tidata_t, tsize_t, tsample_t);
+static  int PixarLogDecode(TIFF*, tidata_t, tsize_t, tsample_t);
+
+#define N(a)   (sizeof(a)/sizeof(a[0]))
+#define PIXARLOGDATAFMT_UNKNOWN  -1
+
+static int
+PixarLogGuessDataFmt(TIFFDirectory *td)
+{
+  int guess = PIXARLOGDATAFMT_UNKNOWN;
+  int format = td->td_sampleformat;
+
+  /* If the user didn't tell us his datafmt,
+   * take our best guess from the bitspersample.
+   */
+  switch (td->td_bitspersample) {
+   case 32:
+    if (format == SAMPLEFORMAT_IEEEFP)
+      guess = PIXARLOGDATAFMT_FLOAT;
+    break;
+   case 16:
+    if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT)
+      guess = PIXARLOGDATAFMT_16BIT;
+    break;
+   case 12:
+    if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_INT)
+      guess = PIXARLOGDATAFMT_12BITPICIO;
+    break;
+   case 11:
+    if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT)
+      guess = PIXARLOGDATAFMT_11BITLOG;
+    break;
+   case 8:
+    if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT)
+      guess = PIXARLOGDATAFMT_8BIT;
+    break;
+  }
+
+  return guess;
+}
+
+static uint32
+multiply(size_t m1, size_t m2)
+{
+  uint32  bytes = m1 * m2;
+
+  if (m1 && bytes / m1 != m2)
+    bytes = 0;
+
+  return bytes;
+}
+
+static int
+PixarLogSetupDecode(TIFF* tif)
+{
+  TIFFDirectory *td = &tif->tif_dir;
+  PixarLogState* sp = DecoderState(tif);
+  tsize_t tbuf_size;
+  static const char module[] = "PixarLogSetupDecode";
+
+  assert(sp != NULL);
+
+  /* Make sure no byte swapping happens on the data
+   * after decompression. */
+  tif->tif_postdecode = _TIFFNoPostDecode;
+
+  /* for some reason, we can't do this in TIFFInitPixarLog */
+
+  sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ?
+      td->td_samplesperpixel : 1);
+  tbuf_size = multiply(multiply(multiply(sp->stride, td->td_imagewidth),
+              td->td_rowsperstrip), sizeof(uint16));
+  if (tbuf_size == 0)
+    return (0);
+  sp->tbuf = (uint16 *) _TIFFmalloc(tbuf_size);
+  if (sp->tbuf == NULL)
+    return (0);
+  if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN)
+    sp->user_datafmt = PixarLogGuessDataFmt(td);
+  if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) {
+    TIFFError(module, 
+      "PixarLog compression can't handle bits depth/data format combination (depth: %d)", 
+      td->td_bitspersample);
+    return (0);
+  }
+
+  if (inflateInit(&sp->stream) != Z_OK) {
+    TIFFError(module, "%s: %s", tif->tif_name, sp->stream.msg);
+    return (0);
+  } else {
+    sp->state |= PLSTATE_INIT;
+    return (1);
+  }
+}
+
+/*
+ * Setup state for decoding a strip.
+ */
+static int
+PixarLogPreDecode(TIFF* tif, tsample_t s)
+{
+  PixarLogState* sp = DecoderState(tif);
+
+  (void) s;
+  assert(sp != NULL);
+  sp->stream.next_in = tif->tif_rawdata;
+  sp->stream.avail_in = tif->tif_rawcc;
+  return (inflateReset(&sp->stream) == Z_OK);
+}
+
+static int
+PixarLogDecode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s)
+{
+  TIFFDirectory *td = &tif->tif_dir;
+  PixarLogState* sp = DecoderState(tif);
+  static const char module[] = "PixarLogDecode";
+  int i, nsamples, llen;
+  uint16 *up;
+
+  switch (sp->user_datafmt) {
+  case PIXARLOGDATAFMT_FLOAT:
+    nsamples = occ / sizeof(float);  /* XXX float == 32 bits */
+    break;
+  case PIXARLOGDATAFMT_16BIT:
+  case PIXARLOGDATAFMT_12BITPICIO:
+  case PIXARLOGDATAFMT_11BITLOG:
+    nsamples = occ / sizeof(uint16); /* XXX uint16 == 16 bits */
+    break;
+  case PIXARLOGDATAFMT_8BIT:
+  case PIXARLOGDATAFMT_8BITABGR:
+    nsamples = occ;
+    break;
+  default:
+    TIFFError(tif->tif_name,
+      "%d bit input not supported in PixarLog",
+      td->td_bitspersample);
+    return 0;
+  }
+
+  llen = sp->stride * td->td_imagewidth;
+
+  (void) s;
+  assert(sp != NULL);
+  sp->stream.next_out = (unsigned char *) sp->tbuf;
+  sp->stream.avail_out = nsamples * sizeof(uint16);
+  do {
+    int state = inflate(&sp->stream, Z_PARTIAL_FLUSH);
+    if (state == Z_STREAM_END) {
+      break;      /* XXX */
+    }
+    if (state == Z_DATA_ERROR) {
+      TIFFError(module,
+          "%s: Decoding error at scanline %d, %s",
+          tif->tif_name, tif->tif_row, sp->stream.msg);
+      if (inflateSync(&sp->stream) != Z_OK)
+        return (0);
+      continue;
+    }
+    if (state != Z_OK) {
+      TIFFError(module, "%s: zlib error: %s",
+          tif->tif_name, sp->stream.msg);
+      return (0);
+    }
+  } while (sp->stream.avail_out > 0);
+
+  /* hopefully, we got all the bytes we needed */
+  if (sp->stream.avail_out != 0) {
+    TIFFError(module,
+        "%s: Not enough data at scanline %d (short %d bytes)",
+        tif->tif_name, tif->tif_row, sp->stream.avail_out);
+    return (0);
+  }
+
+  up = sp->tbuf;
+  /* Swap bytes in the data if from a different endian machine. */
+  if (tif->tif_flags & TIFF_SWAB)
+    TIFFSwabArrayOfShort(up, nsamples);
+
+  for (i = 0; i < nsamples; i += llen, up += llen) {
+    switch (sp->user_datafmt)  {
+    case PIXARLOGDATAFMT_FLOAT:
+      horizontalAccumulateF(up, llen, sp->stride,
+          (float *)op, sp->ToLinearF);
+      op += llen * sizeof(float);
+      break;
+    case PIXARLOGDATAFMT_16BIT:
+      horizontalAccumulate16(up, llen, sp->stride,
+          (uint16 *)op, sp->ToLinear16);
+      op += llen * sizeof(uint16);
+      break;
+    case PIXARLOGDATAFMT_12BITPICIO:
+      horizontalAccumulate12(up, llen, sp->stride,
+          (int16 *)op, sp->ToLinearF);
+      op += llen * sizeof(int16);
+      break;
+    case PIXARLOGDATAFMT_11BITLOG:
+      horizontalAccumulate11(up, llen, sp->stride,
+          (uint16 *)op);
+      op += llen * sizeof(uint16);
+      break;
+    case PIXARLOGDATAFMT_8BIT:
+      horizontalAccumulate8(up, llen, sp->stride,
+          (unsigned char *)op, sp->ToLinear8);
+      op += llen * sizeof(unsigned char);
+      break;
+    case PIXARLOGDATAFMT_8BITABGR:
+      horizontalAccumulate8abgr(up, llen, sp->stride,
+          (unsigned char *)op, sp->ToLinear8);
+      op += llen * sizeof(unsigned char);
+      break;
+    default:
+      TIFFError(tif->tif_name,
+          "PixarLogDecode: unsupported bits/sample: %d", 
+          td->td_bitspersample);
+      return (0);
+    }
+  }
+
+  return (1);
+}
+
+static int
+PixarLogSetupEncode(TIFF* tif)
+{
+  TIFFDirectory *td = &tif->tif_dir;
+  PixarLogState* sp = EncoderState(tif);
+  tsize_t tbuf_size;
+  static const char module[] = "PixarLogSetupEncode";
+
+  assert(sp != NULL);
+
+  /* for some reason, we can't do this in TIFFInitPixarLog */
+
+  sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ?
+      td->td_samplesperpixel : 1);
+  tbuf_size = multiply(multiply(multiply(sp->stride, td->td_imagewidth),
+              td->td_rowsperstrip), sizeof(uint16));
+  if (tbuf_size == 0)
+    return (0);
+  sp->tbuf = (uint16 *) _TIFFmalloc(tbuf_size);
+  if (sp->tbuf == NULL)
+    return (0);
+  if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN)
+    sp->user_datafmt = PixarLogGuessDataFmt(td);
+  if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) {
+    TIFFError(module, "PixarLog compression can't handle %d bit linear encodings", td->td_bitspersample);
+    return (0);
+  }
+
+  if (deflateInit(&sp->stream, sp->quality) != Z_OK) {
+    TIFFError(module, "%s: %s", tif->tif_name, sp->stream.msg);
+    return (0);
+  } else {
+    sp->state |= PLSTATE_INIT;
+    return (1);
+  }
+}
+
+/*
+ * Reset encoding state at the start of a strip.
+ */
+static int
+PixarLogPreEncode(TIFF* tif, tsample_t s)
+{
+  PixarLogState *sp = EncoderState(tif);
+
+  (void) s;
+  assert(sp != NULL);
+  sp->stream.next_out = tif->tif_rawdata;
+  sp->stream.avail_out = tif->tif_rawdatasize;
+  return (deflateReset(&sp->stream) == Z_OK);
+}
+
+static void
+horizontalDifferenceF(float *ip, int n, int stride, uint16 *wp, uint16 *FromLT2)
+{
+
+    int32 r1, g1, b1, a1, r2, g2, b2, a2, mask;
+    float fltsize = Fltsize;
+
+#define  CLAMP(v) ( (v<(float)0.)   ? 0        \
+      : (v<(float)2.)   ? FromLT2[(int)(v*fltsize)]  \
+      : (v>(float)24.2) ? 2047      \
+      : LogK1*log(v*LogK2) + 0.5 )
+
+    mask = CODE_MASK;
+    if (n >= stride) {
+  if (stride == 3) {
+      r2 = wp[0] = (uint16) CLAMP(ip[0]);
+      g2 = wp[1] = (uint16) CLAMP(ip[1]);
+      b2 = wp[2] = (uint16) CLAMP(ip[2]);
+      n -= 3;
+      while (n > 0) {
+    n -= 3;
+    wp += 3;
+    ip += 3;
+    r1 = (int32) CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1;
+    g1 = (int32) CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1;
+    b1 = (int32) CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1;
+      }
+  } else if (stride == 4) {
+      r2 = wp[0] = (uint16) CLAMP(ip[0]);
+      g2 = wp[1] = (uint16) CLAMP(ip[1]);
+      b2 = wp[2] = (uint16) CLAMP(ip[2]);
+      a2 = wp[3] = (uint16) CLAMP(ip[3]);
+      n -= 4;
+      while (n > 0) {
+    n -= 4;
+    wp += 4;
+    ip += 4;
+    r1 = (int32) CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1;
+    g1 = (int32) CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1;
+    b1 = (int32) CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1;
+    a1 = (int32) CLAMP(ip[3]); wp[3] = (a1-a2) & mask; a2 = a1;
+      }
+  } else {
+      ip += n - 1;  /* point to last one */
+      wp += n - 1;  /* point to last one */
+      n -= stride;
+      while (n > 0) {
+    REPEAT(stride, wp[0] = (uint16) CLAMP(ip[0]);
+        wp[stride] -= wp[0];
+        wp[stride] &= mask;
+        wp--; ip--)
+    n -= stride;
+      }
+      REPEAT(stride, wp[0] = (uint16) CLAMP(ip[0]); wp--; ip--)
+  }
+    }
+}
+
+static void
+horizontalDifference16(unsigned short *ip, int n, int stride, 
+  unsigned short *wp, uint16 *From14)
+{
+    register int  r1, g1, b1, a1, r2, g2, b2, a2, mask;
+
+/* assumption is unsigned pixel values */
+#undef   CLAMP
+#define  CLAMP(v) From14[(v) >> 2]
+
+    mask = CODE_MASK;
+    if (n >= stride) {
+  if (stride == 3) {
+      r2 = wp[0] = CLAMP(ip[0]);  g2 = wp[1] = CLAMP(ip[1]);
+      b2 = wp[2] = CLAMP(ip[2]);
+      n -= 3;
+      while (n > 0) {
+    n -= 3;
+    wp += 3;
+    ip += 3;
+    r1 = CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1;
+    g1 = CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1;
+    b1 = CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1;
+      }
+  } else if (stride == 4) {
+      r2 = wp[0] = CLAMP(ip[0]);  g2 = wp[1] = CLAMP(ip[1]);
+      b2 = wp[2] = CLAMP(ip[2]);  a2 = wp[3] = CLAMP(ip[3]);
+      n -= 4;
+      while (n > 0) {
+    n -= 4;
+    wp += 4;
+    ip += 4;
+    r1 = CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1;
+    g1 = CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1;
+    b1 = CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1;
+    a1 = CLAMP(ip[3]); wp[3] = (a1-a2) & mask; a2 = a1;
+      }
+  } else {
+      ip += n - 1;  /* point to last one */
+      wp += n - 1;  /* point to last one */
+      n -= stride;
+      while (n > 0) {
+    REPEAT(stride, wp[0] = CLAMP(ip[0]);
+        wp[stride] -= wp[0];
+        wp[stride] &= mask;
+        wp--; ip--)
+    n -= stride;
+      }
+      REPEAT(stride, wp[0] = CLAMP(ip[0]); wp--; ip--)
+  }
+    }
+}
+
+
+static void
+horizontalDifference8(unsigned char *ip, int n, int stride, 
+  unsigned short *wp, uint16 *From8)
+{
+    register int  r1, g1, b1, a1, r2, g2, b2, a2, mask;
+
+#undef   CLAMP
+#define  CLAMP(v) (From8[(v)])
+
+    mask = CODE_MASK;
+    if (n >= stride) {
+  if (stride == 3) {
+      r2 = wp[0] = CLAMP(ip[0]);  g2 = wp[1] = CLAMP(ip[1]);
+      b2 = wp[2] = CLAMP(ip[2]);
+      n -= 3;
+      while (n > 0) {
+    n -= 3;
+    r1 = CLAMP(ip[3]); wp[3] = (r1-r2) & mask; r2 = r1;
+    g1 = CLAMP(ip[4]); wp[4] = (g1-g2) & mask; g2 = g1;
+    b1 = CLAMP(ip[5]); wp[5] = (b1-b2) & mask; b2 = b1;
+    wp += 3;
+    ip += 3;
+      }
+  } else if (stride == 4) {
+      r2 = wp[0] = CLAMP(ip[0]);  g2 = wp[1] = CLAMP(ip[1]);
+      b2 = wp[2] = CLAMP(ip[2]);  a2 = wp[3] = CLAMP(ip[3]);
+      n -= 4;
+      while (n > 0) {
+    n -= 4;
+    r1 = CLAMP(ip[4]); wp[4] = (r1-r2) & mask; r2 = r1;
+    g1 = CLAMP(ip[5]); wp[5] = (g1-g2) & mask; g2 = g1;
+    b1 = CLAMP(ip[6]); wp[6] = (b1-b2) & mask; b2 = b1;
+    a1 = CLAMP(ip[7]); wp[7] = (a1-a2) & mask; a2 = a1;
+    wp += 4;
+    ip += 4;
+      }
+  } else {
+      wp += n + stride - 1;  /* point to last one */
+      ip += n + stride - 1;  /* point to last one */
+      n -= stride;
+      while (n > 0) {
+    REPEAT(stride, wp[0] = CLAMP(ip[0]);
+        wp[stride] -= wp[0];
+        wp[stride] &= mask;
+        wp--; ip--)
+    n -= stride;
+      }
+      REPEAT(stride, wp[0] = CLAMP(ip[0]); wp--; ip--)
+  }
+    }
+}
+
+/*
+ * Encode a chunk of pixels.
+ */
+static int
+PixarLogEncode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
+{
+  TIFFDirectory *td = &tif->tif_dir;
+  PixarLogState *sp = EncoderState(tif);
+  static const char module[] = "PixarLogEncode";
+  int   i, n, llen;
+  unsigned short * up;
+
+  (void) s;
+
+  switch (sp->user_datafmt) {
+  case PIXARLOGDATAFMT_FLOAT:
+    n = cc / sizeof(float);    /* XXX float == 32 bits */
+    break;
+  case PIXARLOGDATAFMT_16BIT:
+  case PIXARLOGDATAFMT_12BITPICIO:
+  case PIXARLOGDATAFMT_11BITLOG:
+    n = cc / sizeof(uint16);  /* XXX uint16 == 16 bits */
+    break;
+  case PIXARLOGDATAFMT_8BIT:
+  case PIXARLOGDATAFMT_8BITABGR:
+    n = cc;
+    break;
+  default:
+    TIFFError(tif->tif_name,
+      "%d bit input not supported in PixarLog",
+      td->td_bitspersample);
+    return 0;
+  }
+
+  llen = sp->stride * td->td_imagewidth;
+
+  for (i = 0, up = sp->tbuf; i < n; i += llen, up += llen) {
+    switch (sp->user_datafmt)  {
+    case PIXARLOGDATAFMT_FLOAT:
+      horizontalDifferenceF((float *)bp, llen, 
+        sp->stride, up, sp->FromLT2);
+      bp += llen * sizeof(float);
+      break;
+    case PIXARLOGDATAFMT_16BIT:
+      horizontalDifference16((uint16 *)bp, llen, 
+        sp->stride, up, sp->From14);
+      bp += llen * sizeof(uint16);
+      break;
+    case PIXARLOGDATAFMT_8BIT:
+      horizontalDifference8((unsigned char *)bp, llen, 
+        sp->stride, up, sp->From8);
+      bp += llen * sizeof(unsigned char);
+      break;
+    default:
+      TIFFError(tif->tif_name,
+        "%d bit input not supported in PixarLog",
+        td->td_bitspersample);
+      return 0;
+    }
+  }
+ 
+  sp->stream.next_in = (unsigned char *) sp->tbuf;
+  sp->stream.avail_in = n * sizeof(uint16);
+
+  do {
+    if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) {
+      TIFFError(module, "%s: Encoder error: %s",
+          tif->tif_name, sp->stream.msg);
+      return (0);
+    }
+    if (sp->stream.avail_out == 0) {
+      tif->tif_rawcc = tif->tif_rawdatasize;
+      TIFFFlushData1(tif);
+      sp->stream.next_out = tif->tif_rawdata;
+      sp->stream.avail_out = tif->tif_rawdatasize;
+    }
+  } while (sp->stream.avail_in > 0);
+  return (1);
+}
+
+/*
+ * Finish off an encoded strip by flushing the last
+ * string and tacking on an End Of Information code.
+ */
+
+static int
+PixarLogPostEncode(TIFF* tif)
+{
+  PixarLogState *sp = EncoderState(tif);
+  static const char module[] = "PixarLogPostEncode";
+  int state;
+
+  sp->stream.avail_in = 0;
+
+  do {
+    state = deflate(&sp->stream, Z_FINISH);
+    switch (state) {
+    case Z_STREAM_END:
+    case Z_OK:
+        if (sp->stream.avail_out != tif->tif_rawdatasize) {
+          tif->tif_rawcc =
+        tif->tif_rawdatasize - sp->stream.avail_out;
+          TIFFFlushData1(tif);
+          sp->stream.next_out = tif->tif_rawdata;
+          sp->stream.avail_out = tif->tif_rawdatasize;
+        }
+        break;
+    default:
+        TIFFError(module, "%s: zlib error: %s",
+      tif->tif_name, sp->stream.msg);
+        return (0);
+    }
+  } while (state != Z_STREAM_END);
+  return (1);
+}
+
+static void
+PixarLogClose(TIFF* tif)
+{
+  TIFFDirectory *td = &tif->tif_dir;
+
+  /* In a really sneaky maneuver, on close, we covertly modify both
+   * bitspersample and sampleformat in the directory to indicate
+   * 8-bit linear.  This way, the decode "just works" even for
+   * readers that don't know about PixarLog, or how to set
+   * the PIXARLOGDATFMT pseudo-tag.
+   */
+  td->td_bitspersample = 8;
+  td->td_sampleformat = SAMPLEFORMAT_UINT;
+}
+
+static void
+PixarLogCleanup(TIFF* tif)
+{
+  PixarLogState* sp = (PixarLogState*) tif->tif_data;
+
+  if (sp) {
+    if (sp->FromLT2) _TIFFfree(sp->FromLT2);
+    if (sp->From14) _TIFFfree(sp->From14);
+    if (sp->From8) _TIFFfree(sp->From8);
+    if (sp->ToLinearF) _TIFFfree(sp->ToLinearF);
+    if (sp->ToLinear16) _TIFFfree(sp->ToLinear16);
+    if (sp->ToLinear8) _TIFFfree(sp->ToLinear8);
+    if (sp->state&PLSTATE_INIT) {
+      if (tif->tif_mode == O_RDONLY)
+        inflateEnd(&sp->stream);
+      else
+        deflateEnd(&sp->stream);
+    }
+    if (sp->tbuf)
+      _TIFFfree(sp->tbuf);
+    _TIFFfree(sp);
+    tif->tif_data = NULL;
+  }
+}
+
+static int
+PixarLogVSetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+    PixarLogState *sp = (PixarLogState *)tif->tif_data;
+    int result;
+    static const char module[] = "PixarLogVSetField";
+
+    switch (tag) {
+     case TIFFTAG_PIXARLOGQUALITY:
+    sp->quality = va_arg(ap, int);
+    if (tif->tif_mode != O_RDONLY && (sp->state&PLSTATE_INIT)) {
+      if (deflateParams(&sp->stream,
+          sp->quality, Z_DEFAULT_STRATEGY) != Z_OK) {
+        TIFFError(module, "%s: zlib error: %s",
+          tif->tif_name, sp->stream.msg);
+        return (0);
+      }
+    }
+    return (1);
+     case TIFFTAG_PIXARLOGDATAFMT:
+  sp->user_datafmt = va_arg(ap, int);
+  /* Tweak the TIFF header so that the rest of libtiff knows what
+   * size of data will be passed between app and library, and
+   * assume that the app knows what it is doing and is not
+   * confused by these header manipulations...
+   */
+  switch (sp->user_datafmt) {
+   case PIXARLOGDATAFMT_8BIT:
+   case PIXARLOGDATAFMT_8BITABGR:
+      TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
+      TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
+      break;
+   case PIXARLOGDATAFMT_11BITLOG:
+      TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
+      TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
+      break;
+   case PIXARLOGDATAFMT_12BITPICIO:
+      TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
+      TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT);
+      break;
+   case PIXARLOGDATAFMT_16BIT:
+      TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
+      TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
+      break;
+   case PIXARLOGDATAFMT_FLOAT:
+      TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 32);
+      TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP);
+      break;
+  }
+  /*
+   * Must recalculate sizes should bits/sample change.
+   */
+  tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tsize_t) -1;
+  tif->tif_scanlinesize = TIFFScanlineSize(tif);
+  result = 1;    /* NB: pseudo tag */
+  break;
+     default:
+  result = (*sp->vsetparent)(tif, tag, ap);
+    }
+    return (result);
+}
+
+static int
+PixarLogVGetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+    PixarLogState *sp = (PixarLogState *)tif->tif_data;
+
+    switch (tag) {
+     case TIFFTAG_PIXARLOGQUALITY:
+  *va_arg(ap, int*) = sp->quality;
+  break;
+     case TIFFTAG_PIXARLOGDATAFMT:
+  *va_arg(ap, int*) = sp->user_datafmt;
+  break;
+     default:
+  return (*sp->vgetparent)(tif, tag, ap);
+    }
+    return (1);
+}
+
+static const TIFFFieldInfo pixarlogFieldInfo[] = {
+    {TIFFTAG_PIXARLOGDATAFMT,0,0,TIFF_ANY,  FIELD_PSEUDO,FALSE,FALSE,""},
+    {TIFFTAG_PIXARLOGQUALITY,0,0,TIFF_ANY,  FIELD_PSEUDO,FALSE,FALSE,""}
+};
+
+int
+TIFFInitPixarLog(TIFF* tif, int scheme)
+{
+  PixarLogState* sp;
+
+  assert(scheme == COMPRESSION_PIXARLOG);
+
+  /*
+   * Allocate state block so tag methods have storage to record values.
+   */
+  tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (PixarLogState));
+  if (tif->tif_data == NULL)
+    goto bad;
+  sp = (PixarLogState*) tif->tif_data;
+  _TIFFmemset(sp, 0, sizeof (*sp));
+  sp->stream.data_type = Z_BINARY;
+  sp->user_datafmt = PIXARLOGDATAFMT_UNKNOWN;
+
+  /*
+   * Install codec methods.
+   */
+  tif->tif_setupdecode = PixarLogSetupDecode;
+  tif->tif_predecode = PixarLogPreDecode;
+  tif->tif_decoderow = PixarLogDecode;
+  tif->tif_decodestrip = PixarLogDecode;
+  tif->tif_decodetile = PixarLogDecode;
+  tif->tif_setupencode = PixarLogSetupEncode;
+  tif->tif_preencode = PixarLogPreEncode;
+  tif->tif_postencode = PixarLogPostEncode;
+  tif->tif_encoderow = PixarLogEncode;
+  tif->tif_encodestrip = PixarLogEncode;
+  tif->tif_encodetile = PixarLogEncode;
+  tif->tif_close = PixarLogClose;
+  tif->tif_cleanup = PixarLogCleanup;
+
+  /* Override SetField so we can handle our private pseudo-tag */
+  _TIFFMergeFieldInfo(tif, pixarlogFieldInfo, N(pixarlogFieldInfo));
+  sp->vgetparent = tif->tif_tagmethods.vgetfield;
+  tif->tif_tagmethods.vgetfield = PixarLogVGetField;   /* hook for codec tags */
+  sp->vsetparent = tif->tif_tagmethods.vsetfield;
+  tif->tif_tagmethods.vsetfield = PixarLogVSetField;   /* hook for codec tags */
+
+  /* Default values for codec-specific fields */
+  sp->quality = Z_DEFAULT_COMPRESSION; /* default comp. level */
+  sp->state = 0;
+
+  /* we don't wish to use the predictor, 
+   * the default is none, which predictor value 1
+   */
+  (void) TIFFPredictorInit(tif);
+
+  /*
+   * build the companding tables 
+   */
+  PixarLogMakeTables(sp);
+
+  return (1);
+bad:
+  TIFFError("TIFFInitPixarLog", "No space for PixarLog state block");
+  return (0);
+}
+#endif /* PIXARLOG_SUPPORT */
+
diff --git a/Utilities/ITK/Utilities/tiff/tif_predict.c b/Utilities/ITK/Utilities/tiff/tif_predict.c
new file mode 100644
index 0000000000..c6513d798a
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_predict.c
@@ -0,0 +1,463 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ *
+ * Predictor Tag Support (used by multiple codecs).
+ */
+#include "tiffiop.h"
+#include "tif_predict.h"
+
+#define  PredictorState(tif)  ((TIFFPredictorState*) (tif)->tif_data)
+
+static  void horAcc8(TIFF*, tidata_t, tsize_t);
+static  void horAcc16(TIFF*, tidata_t, tsize_t);
+static  void swabHorAcc16(TIFF*, tidata_t, tsize_t);
+static  void horDiff8(TIFF*, tidata_t, tsize_t);
+static  void horDiff16(TIFF*, tidata_t, tsize_t);
+static  int PredictorDecodeRow(TIFF*, tidata_t, tsize_t, tsample_t);
+static  int PredictorDecodeTile(TIFF*, tidata_t, tsize_t, tsample_t);
+static  int PredictorEncodeRow(TIFF*, tidata_t, tsize_t, tsample_t);
+static  int PredictorEncodeTile(TIFF*, tidata_t, tsize_t, tsample_t);
+
+static int
+PredictorSetup(TIFF* tif)
+{
+  TIFFPredictorState* sp = PredictorState(tif);
+  TIFFDirectory* td = &tif->tif_dir;
+
+  if (sp->predictor == 1)    /* no differencing */
+    return (1);
+  if (sp->predictor != 2) {
+    TIFFError(tif->tif_name, "\"Predictor\" value %d not supported",
+        sp->predictor);
+    return (0);
+  }
+  if (td->td_bitspersample != 8 && td->td_bitspersample != 16) {
+    TIFFError(tif->tif_name,
+    "Horizontal differencing \"Predictor\" not supported with %d-bit samples",
+        td->td_bitspersample);
+    return (0);
+  }
+  sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ?
+      td->td_samplesperpixel : 1);
+  /*
+   * Calculate the scanline/tile-width size in bytes.
+   */
+  if (isTiled(tif))
+    sp->rowsize = TIFFTileRowSize(tif);
+  else
+    sp->rowsize = TIFFScanlineSize(tif);
+  return (1);
+}
+
+static int
+PredictorSetupDecode(TIFF* tif)
+{
+  TIFFPredictorState* sp = PredictorState(tif);
+  TIFFDirectory* td = &tif->tif_dir;
+
+  if (!(*sp->setupdecode)(tif) || !PredictorSetup(tif))
+    return (0);
+  if (sp->predictor == 2) {
+    switch (td->td_bitspersample) {
+    case 8:  sp->pfunc = horAcc8; break;
+    case 16: sp->pfunc = horAcc16; break;
+    }
+    /*
+     * Override default decoding method with
+     * one that does the predictor stuff.
+     */
+    sp->coderow = tif->tif_decoderow;
+    tif->tif_decoderow = PredictorDecodeRow;
+    sp->codestrip = tif->tif_decodestrip;
+    tif->tif_decodestrip = PredictorDecodeTile;
+    sp->codetile = tif->tif_decodetile;
+    tif->tif_decodetile = PredictorDecodeTile;
+    /*
+     * If the data is horizontally differenced
+     * 16-bit data that requires byte-swapping,
+     * then it must be byte swapped before the
+     * accumulation step.  We do this with a
+     * special-purpose routine and override the
+     * normal post decoding logic that the library
+     * setup when the directory was read.
+     */
+    if (tif->tif_flags&TIFF_SWAB) {
+      if (sp->pfunc == horAcc16) {
+        sp->pfunc = swabHorAcc16;
+        tif->tif_postdecode = _TIFFNoPostDecode;
+      } /* else handle 32-bit case... */
+    }
+  }
+  return (1);
+}
+
+static int
+PredictorSetupEncode(TIFF* tif)
+{
+  TIFFPredictorState* sp = PredictorState(tif);
+  TIFFDirectory* td = &tif->tif_dir;
+
+  if (!(*sp->setupencode)(tif) || !PredictorSetup(tif))
+    return (0);
+  if (sp->predictor == 2) {
+    switch (td->td_bitspersample) {
+    case 8:  sp->pfunc = horDiff8; break;
+    case 16: sp->pfunc = horDiff16; break;
+    }
+    /*
+     * Override default encoding method with
+     * one that does the predictor stuff.
+     */
+    sp->coderow = tif->tif_encoderow;
+    tif->tif_encoderow = PredictorEncodeRow;
+    sp->codestrip = tif->tif_encodestrip;
+    tif->tif_encodestrip = PredictorEncodeTile;
+    sp->codetile = tif->tif_encodetile;
+    tif->tif_encodetile = PredictorEncodeTile;
+  }
+  return (1);
+}
+
+#define REPEAT4(n, op)    \
+    switch (n) {    \
+    default: { int i; for (i = n-4; i > 0; i--) { op; } } \
+    case 4:  op;    \
+    case 3:  op;    \
+    case 2:  op;    \
+    case 1:  op;    \
+    case 0:  ;      \
+    }
+
+static void
+horAcc8(TIFF* tif, tidata_t cp0, tsize_t cc)
+{
+  TIFFPredictorState* sp = PredictorState(tif);
+  tsize_t stride = sp->stride;
+
+  char* cp = (char*) cp0;
+  if (cc > stride) {
+    cc -= stride;
+    /*
+     * Pipeline the most common cases.
+     */
+    if (stride == 3)  {
+      unsigned int cr = cp[0];
+      unsigned int cg = cp[1];
+      unsigned int cb = cp[2];
+      do {
+        cc -= 3, cp += 3;
+        cp[0] = (char) (cr += cp[0]);
+        cp[1] = (char) (cg += cp[1]);
+        cp[2] = (char) (cb += cp[2]);
+      } while ((int32) cc > 0);
+    } else if (stride == 4)  {
+      unsigned int cr = cp[0];
+      unsigned int cg = cp[1];
+      unsigned int cb = cp[2];
+      unsigned int ca = cp[3];
+      do {
+        cc -= 4, cp += 4;
+        cp[0] = (char) (cr += cp[0]);
+        cp[1] = (char) (cg += cp[1]);
+        cp[2] = (char) (cb += cp[2]);
+        cp[3] = (char) (ca += cp[3]);
+      } while ((int32) cc > 0);
+    } else  {
+      do {
+        REPEAT4(stride, cp[stride] = (char) (cp[stride] + *cp); cp++)
+        cc -= stride;
+      } while ((int32) cc > 0);
+    }
+  }
+}
+
+static void
+swabHorAcc16(TIFF* tif, tidata_t cp0, tsize_t cc)
+{
+  TIFFPredictorState* sp = PredictorState(tif);
+  tsize_t stride = sp->stride;
+  uint16* wp = (uint16*) cp0;
+  tsize_t wc = cc / 2;
+
+  if (wc > stride) {
+    TIFFSwabArrayOfShort(wp, wc);
+    wc -= stride;
+    do {
+      REPEAT4(stride, wp[stride] += wp[0]; wp++)
+      wc -= stride;
+    } while ((int32) wc > 0);
+  }
+}
+
+static void
+horAcc16(TIFF* tif, tidata_t cp0, tsize_t cc)
+{
+  tsize_t stride = PredictorState(tif)->stride;
+  uint16* wp = (uint16*) cp0;
+  tsize_t wc = cc / 2;
+
+  if (wc > stride) {
+    wc -= stride;
+    do {
+      REPEAT4(stride, wp[stride] += wp[0]; wp++)
+      wc -= stride;
+    } while ((int32) wc > 0);
+  }
+}
+
+/*
+ * Decode a scanline and apply the predictor routine.
+ */
+static int
+PredictorDecodeRow(TIFF* tif, tidata_t op0, tsize_t occ0, tsample_t s)
+{
+  TIFFPredictorState *sp = PredictorState(tif);
+
+  assert(sp != NULL);
+  assert(sp->coderow != NULL);
+  assert(sp->pfunc != NULL);
+  if ((*sp->coderow)(tif, op0, occ0, s)) {
+    (*sp->pfunc)(tif, op0, occ0);
+    return (1);
+  } else
+    return (0);
+}
+
+/*
+ * Decode a tile/strip and apply the predictor routine.
+ * Note that horizontal differencing must be done on a
+ * row-by-row basis.  The width of a "row" has already
+ * been calculated at pre-decode time according to the
+ * strip/tile dimensions.
+ */
+static int
+PredictorDecodeTile(TIFF* tif, tidata_t op0, tsize_t occ0, tsample_t s)
+{
+  TIFFPredictorState *sp = PredictorState(tif);
+
+  assert(sp != NULL);
+  assert(sp->codetile != NULL);
+  if ((*sp->codetile)(tif, op0, occ0, s)) {
+    tsize_t rowsize = sp->rowsize;
+    assert(rowsize > 0);
+    assert(sp->pfunc != NULL);
+    while ((long)occ0 > 0) {
+      (*sp->pfunc)(tif, op0, (tsize_t) rowsize);
+      occ0 -= rowsize;
+      op0 += rowsize;
+    }
+    return (1);
+  } else
+    return (0);
+}
+
+static void
+horDiff8(TIFF* tif, tidata_t cp0, tsize_t cc)
+{
+  TIFFPredictorState* sp = PredictorState(tif);
+  tsize_t stride = sp->stride;
+  char* cp = (char*) cp0;
+
+  if (cc > stride) {
+    cc -= stride;
+    /*
+     * Pipeline the most common cases.
+     */
+    if (stride == 3) {
+      int r1, g1, b1;
+      int r2 = cp[0];
+      int g2 = cp[1];
+      int b2 = cp[2];
+      do {
+        r1 = cp[3]; cp[3] = r1-r2; r2 = r1;
+        g1 = cp[4]; cp[4] = g1-g2; g2 = g1;
+        b1 = cp[5]; cp[5] = b1-b2; b2 = b1;
+        cp += 3;
+      } while ((int32)(cc -= 3) > 0);
+    } else if (stride == 4) {
+      int r1, g1, b1, a1;
+      int r2 = cp[0];
+      int g2 = cp[1];
+      int b2 = cp[2];
+      int a2 = cp[3];
+      do {
+        r1 = cp[4]; cp[4] = r1-r2; r2 = r1;
+        g1 = cp[5]; cp[5] = g1-g2; g2 = g1;
+        b1 = cp[6]; cp[6] = b1-b2; b2 = b1;
+        a1 = cp[7]; cp[7] = a1-a2; a2 = a1;
+        cp += 4;
+      } while ((int32)(cc -= 4) > 0);
+    } else {
+      cp += cc - 1;
+      do {
+        REPEAT4(stride, cp[stride] -= cp[0]; cp--)
+      } while ((int32)(cc -= stride) > 0);
+    }
+  }
+}
+
+static void
+horDiff16(TIFF* tif, tidata_t cp0, tsize_t cc)
+{
+  TIFFPredictorState* sp = PredictorState(tif);
+  tsize_t stride = sp->stride;
+  int16 *wp = (int16*) cp0;
+  tsize_t wc = cc/2;
+
+  if (wc > stride) {
+    wc -= stride;
+    wp += wc - 1;
+    do {
+      REPEAT4(stride, wp[stride] -= wp[0]; wp--)
+      wc -= stride;
+    } while ((int32) wc > 0);
+  }
+}
+
+static int
+PredictorEncodeRow(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
+{
+  TIFFPredictorState *sp = PredictorState(tif);
+
+  assert(sp != NULL);
+  assert(sp->pfunc != NULL);
+  assert(sp->coderow != NULL);
+/* XXX horizontal differencing alters user's data XXX */
+  (*sp->pfunc)(tif, bp, cc);
+  return ((*sp->coderow)(tif, bp, cc, s));
+}
+
+static int
+PredictorEncodeTile(TIFF* tif, tidata_t bp0, tsize_t cc0, tsample_t s)
+{
+  TIFFPredictorState *sp = PredictorState(tif);
+  tsize_t cc = cc0, rowsize;
+  unsigned char* bp = bp0;
+
+  assert(sp != NULL);
+  assert(sp->pfunc != NULL);
+  assert(sp->codetile != NULL);
+  rowsize = sp->rowsize;
+  assert(rowsize > 0);
+  while ((long)cc > 0) {
+    (*sp->pfunc)(tif, bp, (tsize_t) rowsize);
+    cc -= rowsize;
+    bp += rowsize;
+  }
+  return ((*sp->codetile)(tif, bp0, cc0, s));
+}
+
+#define  FIELD_PREDICTOR  (FIELD_CODEC+0)    /* XXX */
+
+static const TIFFFieldInfo predictFieldInfo[] = {
+    { TIFFTAG_PREDICTOR,   1, 1, TIFF_SHORT,  FIELD_PREDICTOR,
+      FALSE,  FALSE,  "Predictor" },
+};
+#define  N(a)  (sizeof (a) / sizeof (a[0]))
+
+static int
+PredictorVSetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+  TIFFPredictorState *sp = PredictorState(tif);
+
+  switch (tag) {
+  case TIFFTAG_PREDICTOR:
+    sp->predictor = (uint16) va_arg(ap, int);
+    TIFFSetFieldBit(tif, FIELD_PREDICTOR);
+    break;
+  default:
+    return (*sp->vsetparent)(tif, tag, ap);
+  }
+  tif->tif_flags |= TIFF_DIRTYDIRECT;
+  return (1);
+}
+
+static int
+PredictorVGetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+  TIFFPredictorState *sp = PredictorState(tif);
+
+  switch (tag) {
+  case TIFFTAG_PREDICTOR:
+    *va_arg(ap, uint16*) = sp->predictor;
+    break;
+  default:
+    return (*sp->vgetparent)(tif, tag, ap);
+  }
+  return (1);
+}
+
+static void
+PredictorPrintDir(TIFF* tif, FILE* fd, long flags)
+{
+  TIFFPredictorState* sp = PredictorState(tif);
+
+  (void) flags;
+  if (TIFFFieldSet(tif,FIELD_PREDICTOR)) {
+    fprintf(fd, "  Predictor: ");
+    switch (sp->predictor) {
+    case 1: fprintf(fd, "none "); break;
+    case 2: fprintf(fd, "horizontal differencing "); break;
+    }
+    fprintf(fd, "%u (0x%x)\n", sp->predictor, sp->predictor);
+  }
+  if (sp->printdir)
+    (*sp->printdir)(tif, fd, flags);
+}
+
+int
+TIFFPredictorInit(TIFF* tif)
+{
+  TIFFPredictorState* sp = PredictorState(tif);
+
+  /*
+   * Merge codec-specific tag information and
+   * override parent get/set field methods.
+   */
+  _TIFFMergeFieldInfo(tif, predictFieldInfo, N(predictFieldInfo));
+  sp->vgetparent = tif->tif_tagmethods.vgetfield;
+  tif->tif_tagmethods.vgetfield =
+            PredictorVGetField;/* hook for predictor tag */
+  sp->vsetparent = tif->tif_tagmethods.vsetfield;
+  tif->tif_tagmethods.vsetfield =
+            PredictorVSetField;/* hook for predictor tag */
+  sp->printdir = tif->tif_tagmethods.printdir;
+  tif->tif_tagmethods.printdir =
+            PredictorPrintDir;  /* hook for predictor tag */
+
+  sp->setupdecode = tif->tif_setupdecode;
+  tif->tif_setupdecode = PredictorSetupDecode;
+  sp->setupencode = tif->tif_setupencode;
+  tif->tif_setupencode = PredictorSetupEncode;
+
+  sp->predictor = 1;      /* default value */
+  sp->pfunc = NULL;      /* no predictor routine */
+  return (1);
+}
+
diff --git a/Utilities/ITK/Utilities/tiff/tif_predict.h b/Utilities/ITK/Utilities/tiff/tif_predict.h
new file mode 100644
index 0000000000..0913c72def
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_predict.h
@@ -0,0 +1,61 @@
+/* $Header: /cvsroot/Insight/Insight/Utilities/tiff/tif_predict.h,v 1.3 2005/09/16 19:58:47 jjomier Exp $ */
+
+/*
+ * Copyright (c) 1995-1997 Sam Leffler
+ * Copyright (c) 1995-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _TIFFPREDICT_
+#define  _TIFFPREDICT_
+/*
+ * ``Library-private'' Support for the Predictor Tag
+ */
+
+/*
+ * Codecs that want to support the Predictor tag must place
+ * this structure first in their private state block so that
+ * the predictor code can cast tif_data to find its state.
+ */
+typedef struct {
+  int  predictor;    /* predictor tag value */
+  int  stride;      /* sample stride over data */
+  tsize_t  rowsize;    /* tile/strip row size */
+
+  TIFFPostMethod  pfunc;    /* horizontal differencer/accumulator */
+  TIFFCodeMethod  coderow;  /* parent codec encode/decode row */
+  TIFFCodeMethod  codestrip;  /* parent codec encode/decode strip */
+  TIFFCodeMethod  codetile;  /* parent codec encode/decode tile */
+  TIFFVGetMethod  vgetparent;  /* super-class method */
+  TIFFVSetMethod  vsetparent;  /* super-class method */
+  TIFFPrintMethod  printdir;  /* super-class method */
+  TIFFBoolMethod  setupdecode;  /* super-class method */
+  TIFFBoolMethod  setupencode;  /* super-class method */
+} TIFFPredictorState;
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+extern  int TIFFPredictorInit(TIFF*);
+#if defined(__cplusplus)
+}
+#endif
+#endif /* _TIFFPREDICT_ */
diff --git a/Utilities/ITK/Utilities/tiff/tif_print.c b/Utilities/ITK/Utilities/tiff/tif_print.c
new file mode 100644
index 0000000000..c3a2174fa1
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_print.c
@@ -0,0 +1,618 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ *
+ * Directory Printing Support
+ */
+#include "tiffiop.h"
+#include <stdio.h>
+
+#include <ctype.h>
+
+static const char *photoNames[] = {
+    "min-is-white",        /* PHOTOMETRIC_MINISWHITE */
+    "min-is-black",        /* PHOTOMETRIC_MINISBLACK */
+    "RGB color",        /* PHOTOMETRIC_RGB */
+    "palette color (RGB from colormap)",  /* PHOTOMETRIC_PALETTE */
+    "transparency mask",      /* PHOTOMETRIC_MASK */
+    "separated",        /* PHOTOMETRIC_SEPARATED */
+    "YCbCr",          /* PHOTOMETRIC_YCBCR */
+    "7 (0x7)",
+    "CIE L*a*b*",        /* PHOTOMETRIC_CIELAB */
+};
+#define  NPHOTONAMES  (sizeof (photoNames) / sizeof (photoNames[0]))
+
+static const char *orientNames[] = {
+    "0 (0x0)",
+    "row 0 top, col 0 lhs",      /* ORIENTATION_TOPLEFT */
+    "row 0 top, col 0 rhs",      /* ORIENTATION_TOPRIGHT */
+    "row 0 bottom, col 0 rhs",      /* ORIENTATION_BOTRIGHT */
+    "row 0 bottom, col 0 lhs",      /* ORIENTATION_BOTLEFT */
+    "row 0 lhs, col 0 top",      /* ORIENTATION_LEFTTOP */
+    "row 0 rhs, col 0 top",      /* ORIENTATION_RIGHTTOP */
+    "row 0 rhs, col 0 bottom",      /* ORIENTATION_RIGHTBOT */
+    "row 0 lhs, col 0 bottom",      /* ORIENTATION_LEFTBOT */
+};
+#define  NORIENTNAMES  (sizeof (orientNames) / sizeof (orientNames[0]))
+
+/*
+ * Print the contents of the current directory
+ * to the specified stdio file stream.
+ */
+void
+TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
+{
+  register TIFFDirectory *td;
+  char *sep;
+  uint16 i;
+  long l, n;
+
+  fprintf(fd, "TIFF Directory at offset 0x%lx\n",
+    (unsigned long)tif->tif_diroff);
+  td = &tif->tif_dir;
+  if (TIFFFieldSet(tif,FIELD_SUBFILETYPE)) {
+    fprintf(fd, "  Subfile Type:");
+    sep = " ";
+    if (td->td_subfiletype & FILETYPE_REDUCEDIMAGE) {
+      fprintf(fd, "%sreduced-resolution image", sep);
+      sep = "/";
+    }
+    if (td->td_subfiletype & FILETYPE_PAGE) {
+      fprintf(fd, "%smulti-page document", sep);
+      sep = "/";
+    }
+    if (td->td_subfiletype & FILETYPE_MASK)
+      fprintf(fd, "%stransparency mask", sep);
+    fprintf(fd, " (%lu = 0x%lx)\n",
+        (long) td->td_subfiletype, (long) td->td_subfiletype);
+  }
+  if (TIFFFieldSet(tif,FIELD_IMAGEDIMENSIONS)) {
+    fprintf(fd, "  Image Width: %lu Image Length: %lu",
+        (unsigned long) td->td_imagewidth, (unsigned long) td->td_imagelength);
+    if (TIFFFieldSet(tif,FIELD_IMAGEDEPTH))
+      fprintf(fd, " Image Depth: %lu",
+          (unsigned long) td->td_imagedepth);
+    fprintf(fd, "\n");
+  }
+
+   /* Begin Pixar */
+   if (TIFFFieldSet(tif,FIELD_IMAGEFULLWIDTH) ||
+       TIFFFieldSet(tif,FIELD_IMAGEFULLLENGTH)) {
+    fprintf(fd, "  Pixar Full Image Width: %lu Full Image Length: %lu\n",
+      (unsigned long) td->td_imagefullwidth,
+      (unsigned long) td->td_imagefulllength);
+   }
+   if (TIFFFieldSet(tif,FIELD_TEXTUREFORMAT))
+    _TIFFprintAsciiTag(fd, "Texture Format", td->td_textureformat);
+   if (TIFFFieldSet(tif,FIELD_WRAPMODES))
+    _TIFFprintAsciiTag(fd, "Texture Wrap Modes", td->td_wrapmodes);
+   if (TIFFFieldSet(tif,FIELD_FOVCOT))
+    fprintf(fd, "  Field of View Cotangent: %g\n", td->td_fovcot);
+  if (TIFFFieldSet(tif,FIELD_MATRIX_WORLDTOSCREEN)) {
+    typedef float  Matrix[4][4];
+    Matrix*    m = (Matrix*)td->td_matrixWorldToScreen;
+    
+    fprintf(fd, "  Matrix NP:\n\t%g %g %g %g\n\t%g %g %g %g\n\t%g %g %g %g\n\t%g %g %g %g\n",
+      (*m)[0][0], (*m)[0][1], (*m)[0][2], (*m)[0][3],
+      (*m)[1][0], (*m)[1][1], (*m)[1][2], (*m)[1][3],
+      (*m)[2][0], (*m)[2][1], (*m)[2][2], (*m)[2][3],
+      (*m)[3][0], (*m)[3][1], (*m)[3][2], (*m)[3][3]);
+   }
+   if (TIFFFieldSet(tif,FIELD_MATRIX_WORLDTOCAMERA)) {
+    typedef float  Matrix[4][4];
+    Matrix*    m = (Matrix*)td->td_matrixWorldToCamera;
+    
+    fprintf(fd, "  Matrix Nl:\n\t%g %g %g %g\n\t%g %g %g %g\n\t%g %g %g %g\n\t%g %g %g %g\n",
+      (*m)[0][0], (*m)[0][1], (*m)[0][2], (*m)[0][3],
+      (*m)[1][0], (*m)[1][1], (*m)[1][2], (*m)[1][3],
+      (*m)[2][0], (*m)[2][1], (*m)[2][2], (*m)[2][3],
+      (*m)[3][0], (*m)[3][1], (*m)[3][2], (*m)[3][3]);
+   }
+   /* End Pixar */
+  
+  if (TIFFFieldSet(tif,FIELD_TILEDIMENSIONS)) {
+    fprintf(fd, "  Tile Width: %lu Tile Length: %lu",
+        (unsigned long) td->td_tilewidth, (unsigned long) td->td_tilelength);
+    if (TIFFFieldSet(tif,FIELD_TILEDEPTH))
+      fprintf(fd, " Tile Depth: %lu",
+          (unsigned long) td->td_tiledepth);
+    fprintf(fd, "\n");
+  }
+  if (TIFFFieldSet(tif,FIELD_RESOLUTION)) {
+    fprintf(fd, "  Resolution: %g, %g",
+        td->td_xresolution, td->td_yresolution);
+    if (TIFFFieldSet(tif,FIELD_RESOLUTIONUNIT)) {
+      switch (td->td_resolutionunit) {
+      case RESUNIT_NONE:
+        fprintf(fd, " (unitless)");
+        break;
+      case RESUNIT_INCH:
+        fprintf(fd, " pixels/inch");
+        break;
+      case RESUNIT_CENTIMETER:
+        fprintf(fd, " pixels/cm");
+        break;
+      default:
+        fprintf(fd, " (unit %u = 0x%x)",
+            td->td_resolutionunit,
+            td->td_resolutionunit);
+        break;
+      }
+    }
+    fprintf(fd, "\n");
+  }
+  if (TIFFFieldSet(tif,FIELD_POSITION))
+    fprintf(fd, "  Position: %g, %g\n",
+        td->td_xposition, td->td_yposition);
+  if (TIFFFieldSet(tif,FIELD_BITSPERSAMPLE))
+    fprintf(fd, "  Bits/Sample: %u\n", td->td_bitspersample);
+  if (TIFFFieldSet(tif,FIELD_SAMPLEFORMAT)) {
+    fprintf(fd, "  Sample Format: ");
+    switch (td->td_sampleformat) {
+    case SAMPLEFORMAT_VOID:
+      fprintf(fd, "void\n");
+      break;
+    case SAMPLEFORMAT_INT:
+      fprintf(fd, "signed integer\n");
+      break;
+    case SAMPLEFORMAT_UINT:
+      fprintf(fd, "unsigned integer\n");
+      break;
+    case SAMPLEFORMAT_IEEEFP:
+      fprintf(fd, "IEEE floating point\n");
+      break;
+    case SAMPLEFORMAT_COMPLEXINT:
+      fprintf(fd, "complex signed integer\n");
+      break;
+    case SAMPLEFORMAT_COMPLEXIEEEFP:
+      fprintf(fd, "complex IEEE floating point\n");
+      break;
+    default:
+      fprintf(fd, "%u (0x%x)\n",
+          td->td_sampleformat, td->td_sampleformat);
+      break;
+    }
+  }
+  if (TIFFFieldSet(tif,FIELD_COMPRESSION)) {
+    const TIFFCodec* c = TIFFFindCODEC(td->td_compression);
+    fprintf(fd, "  Compression Scheme: ");
+    if (c)
+      fprintf(fd, "%s\n", c->name);
+    else
+      fprintf(fd, "%u (0x%x)\n",
+          td->td_compression, td->td_compression);
+  }
+  if (TIFFFieldSet(tif,FIELD_PHOTOMETRIC)) {
+    fprintf(fd, "  Photometric Interpretation: ");
+    if (td->td_photometric < NPHOTONAMES)
+      fprintf(fd, "%s\n", photoNames[td->td_photometric]);
+    else {
+      switch (td->td_photometric) {
+      case PHOTOMETRIC_LOGL:
+        fprintf(fd, "CIE Log2(L)\n");
+        break;
+      case PHOTOMETRIC_LOGLUV:
+        fprintf(fd, "CIE Log2(L) (u',v')\n");
+        break;
+      default:
+        fprintf(fd, "%u (0x%x)\n",
+            td->td_photometric, td->td_photometric);
+        break;
+      }
+    }
+  }
+  if (TIFFFieldSet(tif,FIELD_EXTRASAMPLES) && td->td_extrasamples) {
+    fprintf(fd, "  Extra Samples: %u<", td->td_extrasamples);
+    sep = "";
+    for (i = 0; i < td->td_extrasamples; i++) {
+      switch (td->td_sampleinfo[i]) {
+      case EXTRASAMPLE_UNSPECIFIED:
+        fprintf(fd, "%sunspecified", sep);
+        break;
+      case EXTRASAMPLE_ASSOCALPHA:
+        fprintf(fd, "%sassoc-alpha", sep);
+        break;
+      case EXTRASAMPLE_UNASSALPHA:
+        fprintf(fd, "%sunassoc-alpha", sep);
+        break;
+      default:
+        fprintf(fd, "%s%u (0x%x)", sep,
+            td->td_sampleinfo[i], td->td_sampleinfo[i]);
+        break;
+      }
+      sep = ", ";
+    }
+    fprintf(fd, ">\n");
+  }
+  if (TIFFFieldSet(tif,FIELD_STONITS)) {
+    fprintf(fd, "  Sample to Nits conversion factor: %.4e\n",
+        td->td_stonits);
+  }
+  if (TIFFFieldSet(tif,FIELD_INKSET)) {
+    fprintf(fd, "  Ink Set: ");
+    switch (td->td_inkset) {
+    case INKSET_CMYK:
+      fprintf(fd, "CMYK\n");
+      break;
+    default:
+      fprintf(fd, "%u (0x%x)\n",
+          td->td_inkset, td->td_inkset);
+      break;
+    }
+  }
+  if (TIFFFieldSet(tif,FIELD_INKNAMES)) {
+    char* cp;
+    fprintf(fd, "  Ink Names: ");
+    i = td->td_samplesperpixel;
+    sep = "";
+    for (cp = td->td_inknames; i > 0; cp = strchr(cp,'\0')+1, i--) {
+      fputs(sep, fd);
+      _TIFFprintAscii(fd, cp);
+      sep = ", ";
+    }
+                fputs("\n", fd);
+  }
+  if (TIFFFieldSet(tif,FIELD_NUMBEROFINKS))
+    fprintf(fd, "  Number of Inks: %u\n", td->td_ninks);
+  if (TIFFFieldSet(tif,FIELD_DOTRANGE))
+    fprintf(fd, "  Dot Range: %u-%u\n",
+        td->td_dotrange[0], td->td_dotrange[1]);
+  if (TIFFFieldSet(tif,FIELD_TARGETPRINTER))
+    _TIFFprintAsciiTag(fd, "Target Printer", td->td_targetprinter);
+  if (TIFFFieldSet(tif,FIELD_THRESHHOLDING)) {
+    fprintf(fd, "  Thresholding: ");
+    switch (td->td_threshholding) {
+    case THRESHHOLD_BILEVEL:
+      fprintf(fd, "bilevel art scan\n");
+      break;
+    case THRESHHOLD_HALFTONE:
+      fprintf(fd, "halftone or dithered scan\n");
+      break;
+    case THRESHHOLD_ERRORDIFFUSE:
+      fprintf(fd, "error diffused\n");
+      break;
+    default:
+      fprintf(fd, "%u (0x%x)\n",
+          td->td_threshholding, td->td_threshholding);
+      break;
+    }
+  }
+  if (TIFFFieldSet(tif,FIELD_FILLORDER)) {
+    fprintf(fd, "  FillOrder: ");
+    switch (td->td_fillorder) {
+    case FILLORDER_MSB2LSB:
+      fprintf(fd, "msb-to-lsb\n");
+      break;
+    case FILLORDER_LSB2MSB:
+      fprintf(fd, "lsb-to-msb\n");
+      break;
+    default:
+      fprintf(fd, "%u (0x%x)\n",
+          td->td_fillorder, td->td_fillorder);
+      break;
+    }
+  }
+  if (TIFFFieldSet(tif,FIELD_YCBCRSUBSAMPLING))
+        {
+            /*
+             * For hacky reasons (see tif_jpeg.c - JPEGFixupTestSubsampling),
+             * we need to fetch this rather than trust what is in our
+             * structures.
+             */
+            uint16 subsampling[2];
+
+            TIFFGetField( tif, TIFFTAG_YCBCRSUBSAMPLING, 
+                          subsampling + 0, subsampling + 1 );
+    fprintf(fd, "  YCbCr Subsampling: %u, %u\n",
+                        subsampling[0], subsampling[1] );
+        }
+  if (TIFFFieldSet(tif,FIELD_YCBCRPOSITIONING)) {
+    fprintf(fd, "  YCbCr Positioning: ");
+    switch (td->td_ycbcrpositioning) {
+    case YCBCRPOSITION_CENTERED:
+      fprintf(fd, "centered\n");
+      break;
+    case YCBCRPOSITION_COSITED:
+      fprintf(fd, "cosited\n");
+      break;
+    default:
+      fprintf(fd, "%u (0x%x)\n",
+          td->td_ycbcrpositioning, td->td_ycbcrpositioning);
+      break;
+    }
+  }
+  if (TIFFFieldSet(tif,FIELD_YCBCRCOEFFICIENTS))
+    fprintf(fd, "  YCbCr Coefficients: %g, %g, %g\n",
+        td->td_ycbcrcoeffs[0],
+        td->td_ycbcrcoeffs[1],
+        td->td_ycbcrcoeffs[2]);
+  if (TIFFFieldSet(tif,FIELD_HALFTONEHINTS))
+    fprintf(fd, "  Halftone Hints: light %u dark %u\n",
+        td->td_halftonehints[0], td->td_halftonehints[1]);
+  if (TIFFFieldSet(tif,FIELD_ARTIST))
+    _TIFFprintAsciiTag(fd, "Artist", td->td_artist);
+  if (TIFFFieldSet(tif,FIELD_DATETIME))
+    _TIFFprintAsciiTag(fd, "Date & Time", td->td_datetime);
+  if (TIFFFieldSet(tif,FIELD_HOSTCOMPUTER))
+    _TIFFprintAsciiTag(fd, "Host Computer", td->td_hostcomputer);
+  if (TIFFFieldSet(tif,FIELD_COPYRIGHT))
+    _TIFFprintAsciiTag(fd, "Copyright", td->td_copyright);
+  if (TIFFFieldSet(tif,FIELD_DOCUMENTNAME))
+    _TIFFprintAsciiTag(fd, "Document Name", td->td_documentname);
+  if (TIFFFieldSet(tif,FIELD_IMAGEDESCRIPTION))
+    _TIFFprintAsciiTag(fd, "Image Description", td->td_imagedescription);
+  if (TIFFFieldSet(tif,FIELD_MAKE))
+    _TIFFprintAsciiTag(fd, "Make", td->td_make);
+  if (TIFFFieldSet(tif,FIELD_MODEL))
+    _TIFFprintAsciiTag(fd, "Model", td->td_model);
+  if (TIFFFieldSet(tif,FIELD_ORIENTATION)) {
+    fprintf(fd, "  Orientation: ");
+    if (td->td_orientation < NORIENTNAMES)
+      fprintf(fd, "%s\n", orientNames[td->td_orientation]);
+    else
+      fprintf(fd, "%u (0x%x)\n",
+          td->td_orientation, td->td_orientation);
+  }
+  if (TIFFFieldSet(tif,FIELD_SAMPLESPERPIXEL))
+    fprintf(fd, "  Samples/Pixel: %u\n", td->td_samplesperpixel);
+  if (TIFFFieldSet(tif,FIELD_ROWSPERSTRIP)) {
+    fprintf(fd, "  Rows/Strip: ");
+    if (td->td_rowsperstrip == (uint32) -1)
+      fprintf(fd, "(infinite)\n");
+    else
+      fprintf(fd, "%lu\n", (unsigned long) td->td_rowsperstrip);
+  }
+  if (TIFFFieldSet(tif,FIELD_MINSAMPLEVALUE))
+    fprintf(fd, "  Min Sample Value: %u\n", td->td_minsamplevalue);
+  if (TIFFFieldSet(tif,FIELD_MAXSAMPLEVALUE))
+    fprintf(fd, "  Max Sample Value: %u\n", td->td_maxsamplevalue);
+  if (TIFFFieldSet(tif,FIELD_SMINSAMPLEVALUE))
+    fprintf(fd, "  SMin Sample Value: %g\n",
+        td->td_sminsamplevalue);
+  if (TIFFFieldSet(tif,FIELD_SMAXSAMPLEVALUE))
+    fprintf(fd, "  SMax Sample Value: %g\n",
+        td->td_smaxsamplevalue);
+  if (TIFFFieldSet(tif,FIELD_PLANARCONFIG)) {
+    fprintf(fd, "  Planar Configuration: ");
+    switch (td->td_planarconfig) {
+    case PLANARCONFIG_CONTIG:
+      fprintf(fd, "single image plane\n");
+      break;
+    case PLANARCONFIG_SEPARATE:
+      fprintf(fd, "separate image planes\n");
+      break;
+    default:
+      fprintf(fd, "%u (0x%x)\n",
+          td->td_planarconfig, td->td_planarconfig);
+      break;
+    }
+  }
+  if (TIFFFieldSet(tif,FIELD_PAGENAME))
+    _TIFFprintAsciiTag(fd, "Page Name", td->td_pagename);
+  if (TIFFFieldSet(tif,FIELD_PAGENUMBER))
+    fprintf(fd, "  Page Number: %u-%u\n",
+        td->td_pagenumber[0], td->td_pagenumber[1]);
+  if (TIFFFieldSet(tif,FIELD_COLORMAP)) {
+    fprintf(fd, "  Color Map: ");
+    if (flags & TIFFPRINT_COLORMAP) {
+      fprintf(fd, "\n");
+      n = 1L<<td->td_bitspersample;
+      for (l = 0; l < n; l++)
+        fprintf(fd, "   %5lu: %5u %5u %5u\n",
+            l,
+            td->td_colormap[0][l],
+            td->td_colormap[1][l],
+            td->td_colormap[2][l]);
+    } else
+      fprintf(fd, "(present)\n");
+  }
+  if (TIFFFieldSet(tif,FIELD_WHITEPOINT))
+    fprintf(fd, "  White Point: %g-%g\n",
+        td->td_whitepoint[0], td->td_whitepoint[1]);
+  if (TIFFFieldSet(tif,FIELD_PRIMARYCHROMAS))
+    fprintf(fd, "  Primary Chromaticities: %g,%g %g,%g %g,%g\n",
+        td->td_primarychromas[0], td->td_primarychromas[1],
+        td->td_primarychromas[2], td->td_primarychromas[3],
+        td->td_primarychromas[4], td->td_primarychromas[5]);
+  if (TIFFFieldSet(tif,FIELD_REFBLACKWHITE)) {
+    fprintf(fd, "  Reference Black/White:\n");
+    for (i = 0; i < td->td_samplesperpixel; i++)
+      fprintf(fd, "    %2d: %5g %5g\n",
+          i,
+          td->td_refblackwhite[2*i+0],
+          td->td_refblackwhite[2*i+1]);
+  }
+  if (TIFFFieldSet(tif,FIELD_TRANSFERFUNCTION)) {
+    fprintf(fd, "  Transfer Function: ");
+    if (flags & TIFFPRINT_CURVES) {
+      fprintf(fd, "\n");
+      n = 1L<<td->td_bitspersample;
+      for (l = 0; l < n; l++) {
+        fprintf(fd, "    %2lu: %5u",
+            l, td->td_transferfunction[0][l]);
+        for (i = 1; i < td->td_samplesperpixel; i++)
+          fprintf(fd, " %5u",
+              td->td_transferfunction[i][l]);
+        fputc('\n', fd);
+      }
+    } else
+      fprintf(fd, "(present)\n");
+  }
+  if (TIFFFieldSet(tif,FIELD_ICCPROFILE))
+    fprintf(fd, "  ICC Profile: <present>, %lu bytes\n",
+        (unsigned long) td->td_profileLength);
+   if (TIFFFieldSet(tif,FIELD_PHOTOSHOP))
+     fprintf(fd, "  Photoshop Data: <present>, %lu bytes\n",
+         (unsigned long) td->td_photoshopLength);
+   if (TIFFFieldSet(tif,FIELD_RICHTIFFIPTC))
+     fprintf(fd, "  RichTIFFIPTC Data: <present>, %lu bytes\n",
+         (unsigned long) td->td_richtiffiptcLength);
+  if (TIFFFieldSet(tif, FIELD_SUBIFD)) {
+    fprintf(fd, "  SubIFD Offsets:");
+    for (i = 0; i < td->td_nsubifd; i++)
+      fprintf(fd, " %5lu", (long) td->td_subifd[i]);
+    fputc('\n', fd);
+  }
+   if (TIFFFieldSet(tif,FIELD_XMLPACKET)) {
+            fprintf(fd, "  XMLPacket (XMP Metadata):\n" );
+            for( i=0; i < td->td_xmlpacketLength; i++ )
+                fputc( ((char *)td->td_xmlpacketData)[i], fd );
+            fprintf( fd, "\n" );
+        }
+
+        /*
+        ** Custom tag support.
+        */
+        {
+            int  i;
+            short count;
+
+            count = (short) TIFFGetTagListCount( tif );
+            for( i = 0; i < count; i++ )
+            {
+                ttag_t  tag = TIFFGetTagListEntry( tif, i );
+                const TIFFFieldInfo *fld;
+
+                fld = TIFFFieldWithTag( tif, tag );
+                if( fld == NULL )
+                    continue;
+
+                if( fld->field_passcount )
+                {
+                    short value_count;
+                    int j;
+                    void *raw_data;
+                    
+                    if( TIFFGetField( tif, tag, &value_count, &raw_data ) != 1 )
+                        continue;
+
+                    fprintf(fd, "  %s: ", fld->field_name );
+
+                    for( j = 0; j < value_count; j++ )
+                    {
+      if( fld->field_type == TIFF_BYTE )
+                            fprintf( fd, "%d",
+                                     (int) ((char *) raw_data)[j] );
+      else if( fld->field_type == TIFF_SHORT )
+                            fprintf( fd, "%d",
+                                     (int) ((unsigned short *) raw_data)[j] );
+      else if( fld->field_type == TIFF_SSHORT )
+                            fprintf( fd, "%d",
+                                     (int) ((short *) raw_data)[j] );
+                        else if( fld->field_type == TIFF_LONG )
+                            fprintf( fd, "%d",
+                                     (int) ((unsigned long *) raw_data)[j] );
+                        else if( fld->field_type == TIFF_SLONG )
+                            fprintf( fd, "%d",
+                                     (int) ((long *) raw_data)[j] );
+      else if( fld->field_type == TIFF_RATIONAL )
+          fprintf( fd, "%f",
+             ((float *) raw_data)[j] );
+      else if( fld->field_type == TIFF_SRATIONAL )
+          fprintf( fd, "%f",
+             ((float *) raw_data)[j] );
+                        else if( fld->field_type == TIFF_ASCII )
+                        {
+                            fprintf( fd, "%s",
+                                     (char *) raw_data );
+                            break;
+                        }
+                        else if( fld->field_type == TIFF_DOUBLE )
+                            fprintf( fd, "%f",
+                                     ((double *) raw_data)[j] );
+                        else if( fld->field_type == TIFF_FLOAT )
+                            fprintf( fd, "%f",
+                                     ((float *) raw_data)[j] );
+                        else
+                        {
+                            fprintf( fd,
+                                     "<unsupported data type in TIFFPrint>" );
+                            break;
+                        }
+
+                        if( j < value_count-1 )
+                            fprintf( fd, "," );
+                    }
+                    fprintf( fd, "\n" );
+                } 
+                else if( !fld->field_passcount
+                         && fld->field_type == TIFF_ASCII )
+                {
+                    char *data;
+                    
+                    if( TIFFGetField( tif, tag, &data ) )
+                        fprintf(fd, "  %s: %s\n", fld->field_name, data );
+                }
+            }
+        }
+        
+  if (tif->tif_tagmethods.printdir)
+    (*tif->tif_tagmethods.printdir)(tif, fd, flags);
+  if ((flags & TIFFPRINT_STRIPS) &&
+      TIFFFieldSet(tif,FIELD_STRIPOFFSETS)) {
+    tstrip_t s;
+
+    fprintf(fd, "  %lu %s:\n",
+        (long) td->td_nstrips,
+        isTiled(tif) ? "Tiles" : "Strips");
+    for (s = 0; s < td->td_nstrips; s++)
+      fprintf(fd, "    %3lu: [%8lu, %8lu]\n",
+          (unsigned long) s,
+          (unsigned long) td->td_stripoffset[s],
+          (unsigned long) td->td_stripbytecount[s]);
+  }
+}
+
+void
+_TIFFprintAscii(FILE* fd, const char* cp)
+{
+  for (; *cp != '\0'; cp++) {
+    const char* tp;
+
+    if (isprint((int)*cp)) {
+      fputc(*cp, fd);
+      continue;
+    }
+    for (tp = "\tt\bb\rr\nn\vv"; *tp; tp++)
+      if (*tp++ == *cp)
+        break;
+    if (*tp)
+      fprintf(fd, "\\%c", *tp);
+    else
+      fprintf(fd, "\\%03o", *cp & 0xff);
+  }
+}
+
+void
+_TIFFprintAsciiTag(FILE* fd, const char* name, const char* value)
+{
+  fprintf(fd, "  %s: \"", name);
+  _TIFFprintAscii(fd, value);
+  fprintf(fd, "\"\n");
+}
+
diff --git a/Utilities/ITK/Utilities/tiff/tif_read.c b/Utilities/ITK/Utilities/tiff/tif_read.c
new file mode 100644
index 0000000000..7fdace2706
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_read.c
@@ -0,0 +1,641 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ * Scanline-oriented Read Support
+ */
+#include "tiffiop.h"
+#include <stdio.h>
+
+  int TIFFFillStrip(TIFF*, tstrip_t);
+  int TIFFFillTile(TIFF*, ttile_t);
+static  int TIFFStartStrip(TIFF*, tstrip_t);
+static  int TIFFStartTile(TIFF*, ttile_t);
+static  int TIFFCheckRead(TIFF*, int);
+
+#define  NOSTRIP  ((tstrip_t) -1)      /* undefined state */
+#define  NOTILE  ((ttile_t) -1)      /* undefined state */
+
+/*
+ * Seek to a random row+sample in a file.
+ */
+static int
+TIFFSeek(TIFF* tif, uint32 row, tsample_t sample)
+{
+  register TIFFDirectory *td = &tif->tif_dir;
+  tstrip_t strip;
+
+  if (row >= td->td_imagelength) {  /* out of range */
+    TIFFError(tif->tif_name, "%lu: Row out of range, max %lu",
+        (unsigned long) row, (unsigned long) td->td_imagelength);
+    return (0);
+  }
+  if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
+    if (sample >= td->td_samplesperpixel) {
+      TIFFError(tif->tif_name,
+          "%lu: Sample out of range, max %lu",
+          (unsigned long) sample, (unsigned long) td->td_samplesperpixel);
+      return (0);
+    }
+    strip = sample*td->td_stripsperimage + row/td->td_rowsperstrip;
+  } else
+    strip = row / td->td_rowsperstrip;
+  if (strip != tif->tif_curstrip) {   /* different strip, refill */
+    if (!TIFFFillStrip(tif, strip))
+      return (0);
+  } else if (row < tif->tif_row) {
+    /*
+     * Moving backwards within the same strip: backup
+     * to the start and then decode forward (below).
+     *
+     * NB: If you're planning on lots of random access within a
+     * strip, it's better to just read and decode the entire
+     * strip, and then access the decoded data in a random fashion.
+     */
+    if (!TIFFStartStrip(tif, strip))
+      return (0);
+  }
+  if (row != tif->tif_row) {
+    /*
+     * Seek forward to the desired row.
+     */
+    if (!(*tif->tif_seek)(tif, row - tif->tif_row))
+      return (0);
+    tif->tif_row = row;
+  }
+  return (1);
+}
+
+int
+TIFFReadScanline(TIFF* tif, tdata_t buf, uint32 row, tsample_t sample)
+{
+  int e;
+
+  if (!TIFFCheckRead(tif, 0))
+    return (-1);
+  if( (e = TIFFSeek(tif, row, sample)) != 0) {
+    /*
+     * Decompress desired row into user buffer.
+     */
+    e = (*tif->tif_decoderow)
+        (tif, (tidata_t) buf, tif->tif_scanlinesize, sample);
+
+                /* we are now poised at the beginning of the next row */
+                tif->tif_row = row + 1;
+
+    if (e)
+      (*tif->tif_postdecode)(tif, (tidata_t) buf,
+          tif->tif_scanlinesize);
+  }
+  return (e > 0 ? 1 : -1);
+}
+
+/*
+ * Read a strip of data and decompress the specified
+ * amount into the user-supplied buffer.
+ */
+tsize_t
+TIFFReadEncodedStrip(TIFF* tif, tstrip_t strip, tdata_t buf, tsize_t size)
+{
+  TIFFDirectory *td = &tif->tif_dir;
+  uint32 nrows;
+  tsize_t stripsize;
+        tstrip_t sep_strip, strips_per_sep;
+
+  if (!TIFFCheckRead(tif, 0))
+    return (-1);
+  if (strip >= td->td_nstrips) {
+    TIFFError(tif->tif_name, "%ld: Strip out of range, max %ld",
+        (long) strip, (long) td->td_nstrips);
+    return (-1);
+  }
+  /*
+   * Calculate the strip size according to the number of
+   * rows in the strip (check for truncated last strip on any
+         * of the separations).
+   */
+        if( td->td_rowsperstrip >= td->td_imagelength )
+            strips_per_sep = 1;
+        else
+            strips_per_sep = (td->td_imagelength+td->td_rowsperstrip-1)
+                / td->td_rowsperstrip;
+
+        sep_strip = strip % strips_per_sep;
+
+  if (sep_strip != strips_per_sep-1 ||
+      (nrows = td->td_imagelength % td->td_rowsperstrip) == 0)
+    nrows = td->td_rowsperstrip;
+
+  stripsize = TIFFVStripSize(tif, nrows);
+  if (size == (tsize_t) -1)
+    size = stripsize;
+  else if (size > stripsize)
+    size = stripsize;
+  if (TIFFFillStrip(tif, strip) 
+            && (*tif->tif_decodestrip)(tif, (tidata_t) buf, size, 
+                         (tsample_t)(strip / td->td_stripsperimage)) > 0 ) {
+    (*tif->tif_postdecode)(tif, (tidata_t) buf, size);
+    return (size);
+  } else
+    return ((tsize_t) -1);
+}
+
+static tsize_t
+TIFFReadRawStrip1(TIFF* tif,
+    tstrip_t strip, tdata_t buf, tsize_t size, const char* module)
+{
+  TIFFDirectory *td = &tif->tif_dir;
+
+  if (!isMapped(tif)) {
+    tsize_t cc;
+
+    if (!SeekOK(tif, td->td_stripoffset[strip])) {
+      TIFFError(module,
+          "%s: Seek error at scanline %lu, strip %lu",
+          tif->tif_name,
+          (unsigned long) tif->tif_row, (unsigned long) strip);
+      return (-1);
+    }
+    cc = TIFFReadFile(tif, buf, size);
+    if (cc != size) {
+      TIFFError(module,
+    "%s: Read error at scanline %lu; got %lu bytes, expected %lu",
+          tif->tif_name,
+          (unsigned long) tif->tif_row,
+          (unsigned long) cc,
+          (unsigned long) size);
+      return (-1);
+    }
+  } else {
+    if (td->td_stripoffset[strip] + size > tif->tif_size) {
+      TIFFError(module,
+    "%s: Read error at scanline %lu, strip %lu; got %lu bytes, expected %lu",
+          tif->tif_name,
+          (unsigned long) tif->tif_row,
+          (unsigned long) strip,
+          (unsigned long) tif->tif_size - td->td_stripoffset[strip],
+          (unsigned long) size);
+      return (-1);
+    }
+    _TIFFmemcpy(buf, tif->tif_base + td->td_stripoffset[strip],
+                            size);
+  }
+  return (size);
+}
+
+/*
+ * Read a strip of data from the file.
+ */
+tsize_t
+TIFFReadRawStrip(TIFF* tif, tstrip_t strip, tdata_t buf, tsize_t size)
+{
+  static const char module[] = "TIFFReadRawStrip";
+  TIFFDirectory *td = &tif->tif_dir;
+  tsize_t bytecount;
+
+  if (!TIFFCheckRead(tif, 0))
+    return ((tsize_t) -1);
+  if (strip >= td->td_nstrips) {
+    TIFFError(tif->tif_name, "%lu: Strip out of range, max %lu",
+        (unsigned long) strip, (unsigned long) td->td_nstrips);
+    return ((tsize_t) -1);
+  }
+  bytecount = td->td_stripbytecount[strip];
+  if (bytecount <= 0) {
+    TIFFError(tif->tif_name,
+        "%lu: Invalid strip byte count, strip %lu",
+        (unsigned long) bytecount, (unsigned long) strip);
+    return ((tsize_t) -1);
+  }
+  if (size != (tsize_t)-1 && size < bytecount)
+    bytecount = size;
+  return (TIFFReadRawStrip1(tif, strip, buf, bytecount, module));
+}
+
+/*
+ * Read the specified strip and setup for decoding. 
+ * The data buffer is expanded, as necessary, to
+ * hold the strip's data.
+ */
+int
+TIFFFillStrip(TIFF* tif, tstrip_t strip)
+{
+  static const char module[] = "TIFFFillStrip";
+  TIFFDirectory *td = &tif->tif_dir;
+  tsize_t bytecount;
+
+  bytecount = td->td_stripbytecount[strip];
+  if (bytecount <= 0) {
+    TIFFError(tif->tif_name,
+        "%lu: Invalid strip byte count, strip %lu",
+        (unsigned long) bytecount, (unsigned long) strip);
+    return (0);
+  }
+  if (isMapped(tif) &&
+      (isFillOrder(tif, td->td_fillorder)
+             || (tif->tif_flags & TIFF_NOBITREV))) {
+    /*
+     * The image is mapped into memory and we either don't
+     * need to flip bits or the compression routine is going
+     * to handle this operation itself.  In this case, avoid
+     * copying the raw data and instead just reference the
+     * data from the memory mapped file image.  This assumes
+     * that the decompression routines do not modify the
+     * contents of the raw data buffer (if they try to,
+     * the application will get a fault since the file is
+     * mapped read-only).
+     */
+    if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata)
+      _TIFFfree(tif->tif_rawdata);
+    tif->tif_flags &= ~TIFF_MYBUFFER;
+    if ( td->td_stripoffset[strip] + bytecount > tif->tif_size) {
+      /*
+       * This error message might seem strange, but it's
+       * what would happen if a read were done instead.
+       */
+      TIFFError(module,
+        "%s: Read error on strip %lu; got %lu bytes, expected %lu",
+          tif->tif_name,
+          (unsigned long) strip,
+          (unsigned long) tif->tif_size - td->td_stripoffset[strip],
+          (unsigned long) bytecount);
+      tif->tif_curstrip = NOSTRIP;
+      return (0);
+    }
+    tif->tif_rawdatasize = bytecount;
+    tif->tif_rawdata = tif->tif_base + td->td_stripoffset[strip];
+  } else {
+    /*
+     * Expand raw data buffer, if needed, to
+     * hold data strip coming from file
+     * (perhaps should set upper bound on
+     *  the size of a buffer we'll use?).
+     */
+    if (bytecount > tif->tif_rawdatasize) {
+      tif->tif_curstrip = NOSTRIP;
+      if ((tif->tif_flags & TIFF_MYBUFFER) == 0) {
+        TIFFError(module,
+        "%s: Data buffer too small to hold strip %lu",
+            tif->tif_name, (unsigned long) strip);
+        return (0);
+      }
+      if (!TIFFReadBufferSetup(tif, 0,
+          TIFFroundup(bytecount, 1024)))
+        return (0);
+    }
+    if (TIFFReadRawStrip1(tif, strip, (unsigned char *)tif->tif_rawdata,
+        bytecount, module) != bytecount)
+      return (0);
+    if (!isFillOrder(tif, td->td_fillorder) &&
+        (tif->tif_flags & TIFF_NOBITREV) == 0)
+      TIFFReverseBits(tif->tif_rawdata, bytecount);
+  }
+  return (TIFFStartStrip(tif, strip));
+}
+
+/*
+ * Tile-oriented Read Support
+ * Contributed by Nancy Cam (Silicon Graphics).
+ */
+
+/*
+ * Read and decompress a tile of data.  The
+ * tile is selected by the (x,y,z,s) coordinates.
+ */
+tsize_t
+TIFFReadTile(TIFF* tif,
+    tdata_t buf, uint32 x, uint32 y, uint32 z, tsample_t s)
+{
+  if (!TIFFCheckRead(tif, 1) || !TIFFCheckTile(tif, x, y, z, s))
+    return (-1);
+  return (TIFFReadEncodedTile(tif,
+      TIFFComputeTile(tif, x, y, z, s), buf, (tsize_t) -1));
+}
+
+/*
+ * Read a tile of data and decompress the specified
+ * amount into the user-supplied buffer.
+ */
+tsize_t
+TIFFReadEncodedTile(TIFF* tif, ttile_t tile, tdata_t buf, tsize_t size)
+{
+  TIFFDirectory *td = &tif->tif_dir;
+  tsize_t tilesize = tif->tif_tilesize;
+
+  if (!TIFFCheckRead(tif, 1))
+    return (-1);
+  if (tile >= td->td_nstrips) {
+    TIFFError(tif->tif_name, "%ld: Tile out of range, max %ld",
+        (long) tile, (unsigned long) td->td_nstrips);
+    return (-1);
+  }
+  if (size == (tsize_t) -1)
+    size = tilesize;
+  else if (size > tilesize)
+    size = tilesize;
+  if (TIFFFillTile(tif, tile) && (*tif->tif_decodetile)(tif,
+      (tidata_t) buf, size, (tsample_t)(tile/td->td_stripsperimage))) {
+    (*tif->tif_postdecode)(tif, (tidata_t) buf, size);
+    return (size);
+  } else
+    return (-1);
+}
+
+static tsize_t
+TIFFReadRawTile1(TIFF* tif,
+    ttile_t tile, tdata_t buf, tsize_t size, const char* module)
+{
+  TIFFDirectory *td = &tif->tif_dir;
+
+  if (!isMapped(tif)) {
+    tsize_t cc;
+
+    if (!SeekOK(tif, td->td_stripoffset[tile])) {
+      TIFFError(module,
+          "%s: Seek error at row %ld, col %ld, tile %ld",
+          tif->tif_name,
+          (long) tif->tif_row,
+          (long) tif->tif_col,
+          (long) tile);
+      return ((tsize_t) -1);
+    }
+    cc = TIFFReadFile(tif, buf, size);
+    if (cc != size) {
+      TIFFError(module,
+      "%s: Read error at row %ld, col %ld; got %lu bytes, expected %lu",
+          tif->tif_name,
+          (long) tif->tif_row,
+          (long) tif->tif_col,
+          (unsigned long) cc,
+          (unsigned long) size);
+      return ((tsize_t) -1);
+    }
+  } else {
+    if (td->td_stripoffset[tile] + size > tif->tif_size) {
+      TIFFError(module,
+    "%s: Read error at row %ld, col %ld, tile %ld; got %lu bytes, expected %lu",
+          tif->tif_name,
+          (long) tif->tif_row,
+          (long) tif->tif_col,
+          (long) tile,
+          (unsigned long) tif->tif_size - td->td_stripoffset[tile],
+          (unsigned long) size);
+      return ((tsize_t) -1);
+    }
+    _TIFFmemcpy(buf, tif->tif_base + td->td_stripoffset[tile], size);
+  }
+  return (size);
+}
+
+/*
+ * Read a tile of data from the file.
+ */
+tsize_t
+TIFFReadRawTile(TIFF* tif, ttile_t tile, tdata_t buf, tsize_t size)
+{
+  static const char module[] = "TIFFReadRawTile";
+  TIFFDirectory *td = &tif->tif_dir;
+  tsize_t bytecount;
+
+  if (!TIFFCheckRead(tif, 1))
+    return ((tsize_t) -1);
+  if (tile >= td->td_nstrips) {
+    TIFFError(tif->tif_name, "%lu: Tile out of range, max %lu",
+        (unsigned long) tile, (unsigned long) td->td_nstrips);
+    return ((tsize_t) -1);
+  }
+  bytecount = td->td_stripbytecount[tile];
+  if (size != (tsize_t) -1 && size < bytecount)
+    bytecount = size;
+  return (TIFFReadRawTile1(tif, tile, buf, bytecount, module));
+}
+
+/*
+ * Read the specified tile and setup for decoding. 
+ * The data buffer is expanded, as necessary, to
+ * hold the tile's data.
+ */
+int
+TIFFFillTile(TIFF* tif, ttile_t tile)
+{
+  static const char module[] = "TIFFFillTile";
+  TIFFDirectory *td = &tif->tif_dir;
+  tsize_t bytecount;
+
+  bytecount = td->td_stripbytecount[tile];
+  if (bytecount <= 0) {
+    TIFFError(tif->tif_name,
+        "%lu: Invalid tile byte count, tile %lu",
+        (unsigned long) bytecount, (unsigned long) tile);
+    return (0);
+  }
+  if (isMapped(tif) &&
+      (isFillOrder(tif, td->td_fillorder)
+             || (tif->tif_flags & TIFF_NOBITREV))) {
+    /*
+     * The image is mapped into memory and we either don't
+     * need to flip bits or the compression routine is going
+     * to handle this operation itself.  In this case, avoid
+     * copying the raw data and instead just reference the
+     * data from the memory mapped file image.  This assumes
+     * that the decompression routines do not modify the
+     * contents of the raw data buffer (if they try to,
+     * the application will get a fault since the file is
+     * mapped read-only).
+     */
+    if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata)
+      _TIFFfree(tif->tif_rawdata);
+    tif->tif_flags &= ~TIFF_MYBUFFER;
+    if ( td->td_stripoffset[tile] + bytecount > tif->tif_size) {
+      tif->tif_curtile = NOTILE;
+      return (0);
+    }
+    tif->tif_rawdatasize = bytecount;
+    tif->tif_rawdata = tif->tif_base + td->td_stripoffset[tile];
+  } else {
+    /*
+     * Expand raw data buffer, if needed, to
+     * hold data tile coming from file
+     * (perhaps should set upper bound on
+     *  the size of a buffer we'll use?).
+     */
+    if (bytecount > tif->tif_rawdatasize) {
+      tif->tif_curtile = NOTILE;
+      if ((tif->tif_flags & TIFF_MYBUFFER) == 0) {
+        TIFFError(module,
+        "%s: Data buffer too small to hold tile %ld",
+            tif->tif_name, (long) tile);
+        return (0);
+      }
+      if (!TIFFReadBufferSetup(tif, 0,
+          TIFFroundup(bytecount, 1024)))
+        return (0);
+    }
+    if (TIFFReadRawTile1(tif, tile,
+                                     (unsigned char *)tif->tif_rawdata,
+                                     bytecount, module) != bytecount)
+      return (0);
+    if (!isFillOrder(tif, td->td_fillorder) &&
+        (tif->tif_flags & TIFF_NOBITREV) == 0)
+      TIFFReverseBits(tif->tif_rawdata, bytecount);
+  }
+  return (TIFFStartTile(tif, tile));
+}
+
+/*
+ * Setup the raw data buffer in preparation for
+ * reading a strip of raw data.  If the buffer
+ * is specified as zero, then a buffer of appropriate
+ * size is allocated by the library.  Otherwise,
+ * the client must guarantee that the buffer is
+ * large enough to hold any individual strip of
+ * raw data.
+ */
+int
+TIFFReadBufferSetup(TIFF* tif, tdata_t bp, tsize_t size)
+{
+  static const char module[] = "TIFFReadBufferSetup";
+
+  if (tif->tif_rawdata) {
+    if (tif->tif_flags & TIFF_MYBUFFER)
+      _TIFFfree(tif->tif_rawdata);
+    tif->tif_rawdata = NULL;
+  }
+  if (bp) {
+    tif->tif_rawdatasize = size;
+    tif->tif_rawdata = (tidata_t) bp;
+    tif->tif_flags &= ~TIFF_MYBUFFER;
+  } else {
+    tif->tif_rawdatasize = TIFFroundup(size, 1024);
+    tif->tif_rawdata = (tidata_t) _TIFFmalloc(tif->tif_rawdatasize);
+    tif->tif_flags |= TIFF_MYBUFFER;
+  }
+  if (tif->tif_rawdata == NULL) {
+    TIFFError(module,
+        "%s: No space for data buffer at scanline %ld",
+        tif->tif_name, (long) tif->tif_row);
+    tif->tif_rawdatasize = 0;
+    return (0);
+  }
+  return (1);
+}
+
+/*
+ * Set state to appear as if a
+ * strip has just been read in.
+ */
+static int
+TIFFStartStrip(TIFF* tif, tstrip_t strip)
+{
+  TIFFDirectory *td = &tif->tif_dir;
+
+  if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
+    if (!(*tif->tif_setupdecode)(tif))
+      return (0);
+    tif->tif_flags |= TIFF_CODERSETUP;
+  }
+  tif->tif_curstrip = strip;
+  tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
+  tif->tif_rawcp = tif->tif_rawdata;
+  tif->tif_rawcc = td->td_stripbytecount[strip];
+  return ((*tif->tif_predecode)(tif,
+      (tsample_t)(strip / td->td_stripsperimage)));
+}
+
+/*
+ * Set state to appear as if a
+ * tile has just been read in.
+ */
+static int
+TIFFStartTile(TIFF* tif, ttile_t tile)
+{
+  TIFFDirectory *td = &tif->tif_dir;
+
+  if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
+    if (!(*tif->tif_setupdecode)(tif))
+      return (0);
+    tif->tif_flags |= TIFF_CODERSETUP;
+  }
+  tif->tif_curtile = tile;
+  tif->tif_row =
+      (tile % TIFFhowmany(td->td_imagewidth, td->td_tilewidth)) *
+    td->td_tilelength;
+  tif->tif_col =
+      (tile % TIFFhowmany(td->td_imagelength, td->td_tilelength)) *
+    td->td_tilewidth;
+  tif->tif_rawcp = tif->tif_rawdata;
+  tif->tif_rawcc = td->td_stripbytecount[tile];
+  return ((*tif->tif_predecode)(tif,
+      (tsample_t)(tile/td->td_stripsperimage)));
+}
+
+static int
+TIFFCheckRead(TIFF* tif, int tiles)
+{
+  if (tif->tif_mode == O_WRONLY) {
+    TIFFError(tif->tif_name, "File not open for reading");
+    return (0);
+  }
+  if (tiles ^ isTiled(tif)) {
+    TIFFError(tif->tif_name, tiles ?
+        "Can not read tiles from a stripped image" :
+        "Can not read scanlines from a tiled image");
+    return (0);
+  }
+  return (1);
+}
+
+void
+_TIFFNoPostDecode(TIFF* tif, tidata_t buf, tsize_t cc)
+{
+    (void) tif; (void) buf; (void) cc;
+}
+
+void
+_TIFFSwab16BitData(TIFF* tif, tidata_t buf, tsize_t cc)
+{
+    (void) tif;
+    assert((cc & 1) == 0);
+    TIFFSwabArrayOfShort((uint16*) buf, cc/2);
+}
+
+void
+_TIFFSwab32BitData(TIFF* tif, tidata_t buf, tsize_t cc)
+{
+    (void) tif;
+    assert((cc & 3) == 0);
+    TIFFSwabArrayOfLong((uint32*) buf, cc/4);
+}
+
+void
+_TIFFSwab64BitData(TIFF* tif, tidata_t buf, tsize_t cc)
+{
+    (void) tif;
+    assert((cc & 7) == 0);
+    TIFFSwabArrayOfDouble((double*) buf, cc/8);
+}
+
diff --git a/Utilities/ITK/Utilities/tiff/tif_stream.cxx b/Utilities/ITK/Utilities/tiff/tif_stream.cxx
new file mode 100644
index 0000000000..234394c436
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_stream.cxx
@@ -0,0 +1,289 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1988-1996 Sam Leffler
+ * Copyright (c) 1991-1996 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library UNIX-specific Routines.
+ */
+#include <iostream>
+#include "tiffiop.h"
+
+using namespace std;
+
+class tiffis_data
+{
+  public:
+
+  istream  *myIS;
+        long  myStreamStartPos;
+};
+
+class tiffos_data
+{
+  public:
+
+  ostream  *myOS;
+  long  myStreamStartPos;
+};
+
+static tsize_t
+_tiffosReadProc(thandle_t, tdata_t, tsize_t)
+{
+        return 0;
+}
+
+static tsize_t
+_tiffisReadProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+        tiffis_data  *data = (tiffis_data *)fd;
+
+        data->myIS->read((char *)buf, (int)size);
+
+        return data->myIS->gcount();
+}
+
+static tsize_t
+_tiffosWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+  tiffos_data  *data = (tiffos_data *)fd;
+  ostream    *os = data->myOS;
+  int    pos = os->tellp();
+
+  os->write((const char *)buf, size);
+
+  return ((int)os->tellp()) - pos;
+}
+
+static tsize_t
+_tiffisWriteProc(thandle_t, tdata_t, tsize_t)
+{
+  return 0;
+}
+
+static toff_t
+_tiffosSeekProc(thandle_t fd, toff_t off, int whence)
+{
+  tiffos_data  *data = (tiffos_data *)fd;
+  ostream  *os = data->myOS;
+
+  // if the stream has already failed, don't do anything
+  if( os->fail() )
+    return os->tellp();
+
+  switch(whence) {
+  case SEEK_SET:
+      os->seekp(data->myStreamStartPos + off, ios::beg);
+    break;
+  case SEEK_CUR:
+    os->seekp(off, ios::cur);
+    break;
+  case SEEK_END:
+    os->seekp(off, ios::end);
+    break;
+  }
+
+  // Attempt to workaround problems with seeking past the end of the
+  // stream.  ofstream doesn't have a problem with this but
+  // ostrstream/ostringstream does. In that situation, add intermediate
+  // '\0' characters.
+  if( os->fail() ) {
+    ios::iostate  old_state;
+    toff_t    origin;
+
+    old_state = os->rdstate();
+    // reset the fail bit or else tellp() won't work below
+    os->clear(os->rdstate() & ~ios::failbit);
+    switch( whence ) {
+      case SEEK_SET:
+        origin = data->myStreamStartPos;
+        break;
+      case SEEK_CUR:
+        origin = os->tellp();
+        break;
+      case SEEK_END:
+        os->seekp(0, ios::end);
+        origin = os->tellp();
+        break;
+    }
+    // restore original stream state
+    os->clear(old_state);  
+
+    // only do something if desired seek position is valid
+    if( origin + off > data->myStreamStartPos ) {
+      toff_t  num_fill;
+
+      // clear the fail bit 
+      os->clear(os->rdstate() & ~ios::failbit);
+
+      // extend the stream to the expected size
+      os->seekp(0, ios::end);
+      num_fill = origin + off - (toff_t)os->tellp();
+      for( toff_t i = 0; i < num_fill; i++ )
+        os->put('\0');
+
+      // retry the seek
+      os->seekp(origin + off, ios::beg);
+    }
+  }
+
+  return os->tellp();
+}
+
+static toff_t
+_tiffisSeekProc(thandle_t fd, toff_t off, int whence)
+{
+  tiffis_data  *data = (tiffis_data *)fd;
+
+  switch(whence) {
+  case SEEK_SET:
+    data->myIS->seekg(data->myStreamStartPos + off, ios::beg);
+    break;
+  case SEEK_CUR:
+    data->myIS->seekg(off, ios::cur);
+    break;
+  case SEEK_END:
+    data->myIS->seekg(off, ios::end);
+    break;
+  }
+
+  return ((long)data->myIS->tellg()) - data->myStreamStartPos;
+}
+
+static toff_t
+_tiffosSizeProc(thandle_t fd)
+{
+  tiffos_data  *data = (tiffos_data *)fd;
+  ostream    *os = data->myOS;
+  toff_t    pos = os->tellp();
+  toff_t    len;
+
+  os->seekp(0, ios::end);
+  len = os->tellp();
+  os->seekp(pos);
+
+  return len;
+}
+
+static toff_t
+_tiffisSizeProc(thandle_t fd)
+{
+  tiffis_data  *data = (tiffis_data *)fd;
+  int    pos = data->myIS->tellg();
+  int    len;
+
+  data->myIS->seekg(0, ios::end);
+  len = data->myIS->tellg();
+  data->myIS->seekg(pos);
+
+  return len;
+}
+
+static int
+_tiffosCloseProc(thandle_t fd)
+{
+  // Our stream was not allocated by us, so it shouldn't be closed by us.
+  delete (tiffos_data *)fd;
+  return 0;
+}
+
+static int
+_tiffisCloseProc(thandle_t fd)
+{
+  // Our stream was not allocated by us, so it shouldn't be closed by us.
+  delete (tiffis_data *)fd;
+  return 0;
+}
+
+static int
+_tiffDummyMapProc(thandle_t , tdata_t* , toff_t* )
+{
+  return (0);
+}
+
+static void
+_tiffDummyUnmapProc(thandle_t , tdata_t , toff_t )
+{
+}
+
+/*
+ * Open a TIFF file descriptor for read/writing.
+ */
+static TIFF*
+_tiffStreamOpen(const char* name, const char* mode, void *fd)
+{
+  TIFF*  tif;
+
+  if( strchr(mode, 'w') ) {
+    tiffos_data  *data = new tiffos_data;
+    data->myOS = (ostream *)fd;
+    data->myStreamStartPos = data->myOS->tellp();
+
+    // Open for writing.
+    tif = TIFFClientOpen(name, mode,
+        (thandle_t) data,
+        _tiffosReadProc, _tiffosWriteProc,
+        _tiffosSeekProc, _tiffosCloseProc,
+        _tiffosSizeProc,
+        _tiffDummyMapProc, _tiffDummyUnmapProc);
+  } else {
+    tiffis_data  *data = new tiffis_data;
+    data->myIS = (istream *)fd;
+    data->myStreamStartPos = data->myIS->tellg();
+    // Open for reading.
+    tif = TIFFClientOpen(name, mode,
+        (thandle_t) data,
+        _tiffisReadProc, _tiffisWriteProc,
+        _tiffisSeekProc, _tiffisCloseProc,
+        _tiffisSizeProc,
+        _tiffDummyMapProc, _tiffDummyUnmapProc);
+  }
+
+  return (tif);
+}
+
+TIFF*
+TIFFStreamOpen(const char* name, ostream *os)
+{
+  // If os is either a ostrstream or ostringstream, and has no data
+  // written to it yet, then tellp() will return -1 which will break us.
+  // We workaround this by writing out a dummy character and
+  // then seek back to the beginning.
+  if( !os->fail() && (int)os->tellp() < 0 ) {
+    *os << '\0';
+    os->seekp(0);
+  }
+
+  // NB: We don't support mapped files with streams so add 'm'
+  return _tiffStreamOpen(name, "wm", os);
+}
+
+TIFF*
+TIFFStreamOpen(const char* name, istream *is)
+{
+  // NB: We don't support mapped files with streams so add 'm'
+  return _tiffStreamOpen(name, "rm", is);
+}
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Utilities/ITK/Utilities/tiff/tif_strip.c b/Utilities/ITK/Utilities/tiff/tif_strip.c
new file mode 100644
index 0000000000..9b48445121
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_strip.c
@@ -0,0 +1,261 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1991-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ *
+ * Strip-organized Image Support Routines.
+ */
+#include "tiffiop.h"
+
+static uint32
+summarize(TIFF* tif, size_t summand1, size_t summand2, const char* where)
+{
+  /*
+   * XXX: We are using casting to uint32 here, bacause sizeof(size_t)
+   * may be larger than sizeof(uint32) on 64-bit architectures.
+   */
+  uint32  bytes = summand1 + summand2;
+
+  if (bytes - summand1 != summand2) {
+    TIFFError(tif->tif_name, "Integer overflow in %s", where);
+    bytes = 0;
+  }
+
+  return (bytes);
+}
+
+static uint32
+multiply(TIFF* tif, size_t nmemb, size_t elem_size, const char* where)
+{
+  uint32  bytes = nmemb * elem_size;
+
+  if (elem_size && bytes / elem_size != nmemb) {
+    TIFFError(tif->tif_name, "Integer overflow in %s", where);
+    bytes = 0;
+  }
+
+  return (bytes);
+}
+
+/*
+ * Compute which strip a (row,sample) value is in.
+ */
+tstrip_t
+TIFFComputeStrip(TIFF* tif, uint32 row, tsample_t sample)
+{
+  TIFFDirectory *td = &tif->tif_dir;
+  tstrip_t strip;
+
+  strip = row / td->td_rowsperstrip;
+  if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
+    if (sample >= td->td_samplesperpixel) {
+      TIFFError(tif->tif_name,
+          "%lu: Sample out of range, max %lu",
+          (unsigned long) sample, (unsigned long) td->td_samplesperpixel);
+      return ((tstrip_t) 0);
+    }
+    strip += sample*td->td_stripsperimage;
+  }
+  return (strip);
+}
+
+/*
+ * Compute how many strips are in an image.
+ */
+tstrip_t
+TIFFNumberOfStrips(TIFF* tif)
+{
+  TIFFDirectory *td = &tif->tif_dir;
+  tstrip_t nstrips;
+
+  nstrips = (td->td_rowsperstrip == (uint32) -1 ? 1 :
+       TIFFhowmany(td->td_imagelength, td->td_rowsperstrip));
+  if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
+    nstrips = multiply(tif, nstrips, td->td_samplesperpixel,
+           "TIFFNumberOfStrips");
+  return (nstrips);
+}
+
+/*
+ * Compute the # bytes in a variable height, row-aligned strip.
+ */
+tsize_t
+TIFFVStripSize(TIFF* tif, uint32 nrows)
+{
+  TIFFDirectory *td = &tif->tif_dir;
+
+  if (nrows == (uint32) -1)
+    nrows = td->td_imagelength;
+  if (td->td_planarconfig == PLANARCONFIG_CONTIG &&
+      td->td_photometric == PHOTOMETRIC_YCBCR &&
+      !isUpSampled(tif)) {
+    /*
+     * Packed YCbCr data contain one Cb+Cr for every
+     * HorizontalSampling*VerticalSampling Y values.
+     * Must also roundup width and height when calculating
+     * since images that are not a multiple of the
+     * horizontal/vertical subsampling area include
+     * YCbCr data for the extended image.
+     */
+                uint16 ycbcrsubsampling[2];
+                tsize_t w, scanline, samplingarea;
+
+                TIFFGetField( tif, TIFFTAG_YCBCRSUBSAMPLING, 
+                              ycbcrsubsampling + 0, 
+                              ycbcrsubsampling + 1 );
+
+    samplingarea = ycbcrsubsampling[0]*ycbcrsubsampling[1];
+    if (samplingarea == 0) {
+      TIFFError(tif->tif_name, "Invalid YCbCr subsampling");
+      return 0;
+    }
+
+    w = TIFFroundup(td->td_imagewidth, ycbcrsubsampling[0]);
+    scanline = TIFFhowmany8(multiply(tif, w, td->td_bitspersample,
+             "TIFFVStripSize"));
+    nrows = TIFFroundup(nrows, ycbcrsubsampling[1]);
+    /* NB: don't need TIFFhowmany here 'cuz everything is rounded */
+    scanline = multiply(tif, nrows, scanline, "TIFFVStripSize");
+    return ((tsize_t)
+        summarize(tif, scanline,
+            multiply(tif, 2, scanline / samplingarea,
+               "TIFFVStripSize"), "TIFFVStripSize"));
+  } else
+    return ((tsize_t) multiply(tif, nrows, TIFFScanlineSize(tif),
+             "TIFFVStripSize"));
+}
+
+
+/*
+ * Compute the # bytes in a raw strip.
+ */
+tsize_t
+TIFFRawStripSize(TIFF* tif, tstrip_t strip)
+{
+  TIFFDirectory* td = &tif->tif_dir;
+  tsize_t bytecount = td->td_stripbytecount[strip];
+
+  if (bytecount <= 0) {
+    TIFFError(tif->tif_name,
+        "%lu: Invalid strip byte count, strip %lu",
+        (unsigned long) bytecount, (unsigned long) strip);
+    bytecount = (tsize_t) -1;
+  }
+
+  return bytecount;
+}
+
+/*
+ * Compute the # bytes in a (row-aligned) strip.
+ *
+ * Note that if RowsPerStrip is larger than the
+ * recorded ImageLength, then the strip size is
+ * truncated to reflect the actual space required
+ * to hold the strip.
+ */
+tsize_t
+TIFFStripSize(TIFF* tif)
+{
+  TIFFDirectory* td = &tif->tif_dir;
+  uint32 rps = td->td_rowsperstrip;
+  if (rps > td->td_imagelength)
+    rps = td->td_imagelength;
+  return (TIFFVStripSize(tif, rps));
+}
+
+/*
+ * Compute a default strip size based on the image
+ * characteristics and a requested value.  If the
+ * request is <1 then we choose a strip size according
+ * to certain heuristics.
+ */
+uint32
+TIFFDefaultStripSize(TIFF* tif, uint32 request)
+{
+  return (*tif->tif_defstripsize)(tif, request);
+}
+
+uint32
+_TIFFDefaultStripSize(TIFF* tif, uint32 s)
+{
+  if ((int32) s < 1) {
+    /*
+     * If RowsPerStrip is unspecified, try to break the
+     * image up into strips that are approximately 8Kbytes.
+     */
+    tsize_t scanline = TIFFScanlineSize(tif);
+    s = (uint32)(8*1024) / (scanline == 0 ? 1 : scanline);
+    if (s == 0)    /* very wide images */
+      s = 1;
+  }
+  return (s);
+}
+
+/*
+ * Return the number of bytes to read/write in a call to
+ * one of the scanline-oriented i/o routines.  Note that
+ * this number may be 1/samples-per-pixel if data is
+ * stored as separate planes.
+ */
+tsize_t
+TIFFScanlineSize(TIFF* tif)
+{
+  TIFFDirectory *td = &tif->tif_dir;
+  tsize_t scanline;
+  
+  scanline = multiply (tif, td->td_bitspersample, td->td_imagewidth,
+           "TIFFScanlineSize");
+  if (td->td_planarconfig == PLANARCONFIG_CONTIG)
+    scanline = multiply (tif, scanline, td->td_samplesperpixel,
+             "TIFFScanlineSize");
+  return ((tsize_t) TIFFhowmany8(scanline));
+}
+
+/*
+ * Return the number of bytes required to store a complete
+ * decoded and packed raster scanline (as opposed to the
+ * I/O size returned by TIFFScanlineSize which may be less
+ * if data is store as separate planes).
+ */
+tsize_t
+TIFFRasterScanlineSize(TIFF* tif)
+{
+  TIFFDirectory *td = &tif->tif_dir;
+  tsize_t scanline;
+  
+  scanline = multiply (tif, td->td_bitspersample, td->td_imagewidth,
+           "TIFFRasterScanlineSize");
+  if (td->td_planarconfig == PLANARCONFIG_CONTIG) {
+    scanline = multiply (tif, scanline, td->td_samplesperpixel,
+             "TIFFRasterScanlineSize");
+    return ((tsize_t) TIFFhowmany8(scanline));
+  } else
+    return ((tsize_t) multiply (tif, TIFFhowmany8(scanline),
+              td->td_samplesperpixel,
+              "TIFFRasterScanlineSize"));
+}
+
diff --git a/Utilities/ITK/Utilities/tiff/tif_swab.c b/Utilities/ITK/Utilities/tiff/tif_swab.c
new file mode 100644
index 0000000000..d94c3ac6c7
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_swab.c
@@ -0,0 +1,218 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library Bit & Byte Swapping Support.
+ *
+ * XXX We assume short = 16-bits and long = 32-bits XXX
+ */
+#include "tiffiop.h"
+
+#ifndef itk_TIFFSwabShort
+void
+TIFFSwabShort(uint16* wp)
+{
+  register unsigned char* cp = (unsigned char*) wp;
+  unsigned char t;
+
+  t = cp[1]; cp[1] = cp[0]; cp[0] = t;
+}
+#endif
+
+#ifndef itk_TIFFSwabLong
+void
+TIFFSwabLong(uint32* lp)
+{
+  register unsigned char* cp = (unsigned char*) lp;
+  unsigned char t;
+
+  t = cp[3]; cp[3] = cp[0]; cp[0] = t;
+  t = cp[2]; cp[2] = cp[1]; cp[1] = t;
+}
+#endif
+
+#ifndef itk_TIFFSwabArrayOfShort
+void
+TIFFSwabArrayOfShort(uint16* wp, register unsigned long n)
+{
+  register unsigned char* cp;
+  register unsigned char t;
+
+  /* XXX unroll loop some */
+  while (n-- > 0) {
+    cp = (unsigned char*) wp;
+    t = cp[1]; cp[1] = cp[0]; cp[0] = t;
+    wp++;
+  }
+}
+#endif
+
+#ifndef itk_TIFFSwabArrayOfLong
+void
+TIFFSwabArrayOfLong(register uint32* lp, register unsigned long n)
+{
+  register unsigned char *cp;
+  register unsigned char t;
+
+  /* XXX unroll loop some */
+  while (n-- > 0) {
+    cp = (unsigned char *)lp;
+    t = cp[3]; cp[3] = cp[0]; cp[0] = t;
+    t = cp[2]; cp[2] = cp[1]; cp[1] = t;
+    lp++;
+  }
+}
+#endif
+
+#ifndef itk_TIFFSwabDouble
+void
+TIFFSwabDouble(double *dp)
+{
+        register uint32* lp = (uint32*) dp;
+        uint32 t;
+
+  TIFFSwabArrayOfLong(lp, 2);
+  t = lp[0]; lp[0] = lp[1]; lp[1] = t;
+}
+#endif
+
+#ifndef itk_TIFFSwabArrayOfDouble
+void
+TIFFSwabArrayOfDouble(double* dp, register unsigned long n)
+{
+  register uint32* lp = (uint32*) dp;
+        register uint32 t;
+
+  TIFFSwabArrayOfLong(lp, n + n);
+        while (n-- > 0) {
+    t = lp[0]; lp[0] = lp[1]; lp[1] = t;
+                lp += 2;
+        }
+}
+#endif
+
+/*
+ * Bit reversal tables.  TIFFBitRevTable[<byte>] gives
+ * the bit reversed value of <byte>.  Used in various
+ * places in the library when the FillOrder requires
+ * bit reversal of byte values (e.g. CCITT Fax 3
+ * encoding/decoding).  TIFFNoBitRevTable is provided
+ * for algorithms that want an equivalent table that
+ * do not reverse bit values.
+ */
+static const unsigned char TIFFBitRevTable[256] = {
+    0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+    0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+    0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+    0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+    0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+    0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+    0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+    0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+    0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+    0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+    0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+    0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+    0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+    0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+    0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+    0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+    0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+    0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+    0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+    0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+    0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+    0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+    0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+    0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+    0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+    0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+    0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+    0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+    0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+    0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+    0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+    0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
+};
+static const unsigned char TIFFNoBitRevTable[256] = {
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
+    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 
+    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 
+    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 
+    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 
+    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 
+    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 
+    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 
+    0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 
+    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 
+    0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 
+    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 
+    0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 
+    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 
+    0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 
+    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 
+    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 
+    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 
+    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 
+    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 
+    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 
+    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 
+    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 
+    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 
+    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 
+    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 
+    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 
+    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 
+    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 
+    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 
+    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 
+};
+
+const unsigned char*
+TIFFGetBitRevTable(int reversed)
+{
+  return (reversed ? TIFFBitRevTable : TIFFNoBitRevTable);
+}
+
+void
+TIFFReverseBits(register unsigned char* cp, register unsigned long n)
+{
+  for (; n > 8; n -= 8) {
+    cp[0] = TIFFBitRevTable[cp[0]];
+    cp[1] = TIFFBitRevTable[cp[1]];
+    cp[2] = TIFFBitRevTable[cp[2]];
+    cp[3] = TIFFBitRevTable[cp[3]];
+    cp[4] = TIFFBitRevTable[cp[4]];
+    cp[5] = TIFFBitRevTable[cp[5]];
+    cp[6] = TIFFBitRevTable[cp[6]];
+    cp[7] = TIFFBitRevTable[cp[7]];
+    cp += 8;
+  }
+  while (n-- > 0)
+    *cp = TIFFBitRevTable[*cp], cp++;
+}
+
diff --git a/Utilities/ITK/Utilities/tiff/tif_thunder.c b/Utilities/ITK/Utilities/tiff/tif_thunder.c
new file mode 100644
index 0000000000..66237437c9
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_thunder.c
@@ -0,0 +1,157 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+#include "tiffiop.h"
+#ifdef THUNDER_SUPPORT
+/*
+ * TIFF Library.
+ *
+ * ThunderScan 4-bit Compression Algorithm Support
+ */
+
+/*
+ * ThunderScan uses an encoding scheme designed for
+ * 4-bit pixel values.  Data is encoded in bytes, with
+ * each byte split into a 2-bit code word and a 6-bit
+ * data value.  The encoding gives raw data, runs of
+ * pixels, or pixel values encoded as a delta from the
+ * previous pixel value.  For the latter, either 2-bit
+ * or 3-bit delta values are used, with the deltas packed
+ * into a single byte.
+ */
+#define  THUNDER_DATA    0x3f  /* mask for 6-bit data */
+#define  THUNDER_CODE    0xc0  /* mask for 2-bit code word */
+/* code values */
+#define  THUNDER_RUN    0x00  /* run of pixels w/ encoded count */
+#define  THUNDER_2BITDELTAS  0x40  /* 3 pixels w/ encoded 2-bit deltas */
+#define      DELTA2_SKIP    2  /* skip code for 2-bit deltas */
+#define  THUNDER_3BITDELTAS  0x80  /* 2 pixels w/ encoded 3-bit deltas */
+#define      DELTA3_SKIP    4  /* skip code for 3-bit deltas */
+#define  THUNDER_RAW    0xc0  /* raw data encoded */
+
+static const int twobitdeltas[4] = { 0, 1, 0, -1 };
+static const int threebitdeltas[8] = { 0, 1, 2, 3, 0, -3, -2, -1 };
+
+#define  SETPIXEL(op, v) { \
+  lastpixel = (v) & 0xf; \
+  if (npixels++ & 1) \
+      *op++ |= lastpixel; \
+  else \
+      op[0] = (tidataval_t) (lastpixel << 4); \
+}
+
+static int
+ThunderDecode(TIFF* tif, tidata_t op, tsize_t maxpixels)
+{
+  register unsigned char *bp;
+  register tsize_t cc;
+  unsigned int lastpixel;
+  tsize_t npixels;
+
+  bp = (unsigned char *)tif->tif_rawcp;
+  cc = tif->tif_rawcc;
+  lastpixel = 0;
+  npixels = 0;
+  while (cc > 0 && npixels < maxpixels) {
+    int n, delta;
+
+    n = *bp++, cc--;
+    switch (n & THUNDER_CODE) {
+    case THUNDER_RUN:    /* pixel run */
+      /*
+       * Replicate the last pixel n times,
+       * where n is the lower-order 6 bits.
+       */
+      if (npixels & 1) {
+        op[0] |= lastpixel;
+        lastpixel = *op++; npixels++; n--;
+      } else
+        lastpixel |= lastpixel << 4;
+      npixels += n;
+      if (npixels < maxpixels) {
+        for (; n > 0; n -= 2)
+          *op++ = (tidataval_t) lastpixel;
+      }
+      if (n == -1)
+        *--op &= 0xf0;
+      lastpixel &= 0xf;
+      break;
+    case THUNDER_2BITDELTAS:  /* 2-bit deltas */
+      if ((delta = ((n >> 4) & 3)) != DELTA2_SKIP)
+        SETPIXEL(op, lastpixel + twobitdeltas[delta]);
+      if ((delta = ((n >> 2) & 3)) != DELTA2_SKIP)
+        SETPIXEL(op, lastpixel + twobitdeltas[delta]);
+      if ((delta = (n & 3)) != DELTA2_SKIP)
+        SETPIXEL(op, lastpixel + twobitdeltas[delta]);
+      break;
+    case THUNDER_3BITDELTAS:  /* 3-bit deltas */
+      if ((delta = ((n >> 3) & 7)) != DELTA3_SKIP)
+        SETPIXEL(op, lastpixel + threebitdeltas[delta]);
+      if ((delta = (n & 7)) != DELTA3_SKIP)
+        SETPIXEL(op, lastpixel + threebitdeltas[delta]);
+      break;
+    case THUNDER_RAW:    /* raw data */
+      SETPIXEL(op, n);
+      break;
+    }
+  }
+  tif->tif_rawcp = (tidata_t) bp;
+  tif->tif_rawcc = cc;
+  if (npixels != maxpixels) {
+    TIFFError(tif->tif_name,
+        "ThunderDecode: %s data at scanline %ld (%lu != %lu)",
+        npixels < maxpixels ? "Not enough" : "Too much",
+        (long) tif->tif_row, (long) npixels, (long) maxpixels);
+    return (0);
+  }
+  return (1);
+}
+
+static int
+ThunderDecodeRow(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s)
+{
+  tidata_t row = buf;
+  
+  (void) s;
+  while ((long)occ > 0) {
+    if (!ThunderDecode(tif, row, tif->tif_dir.td_imagewidth))
+      return (0);
+    occ -= tif->tif_scanlinesize;
+    row += tif->tif_scanlinesize;
+  }
+  return (1);
+}
+
+int
+TIFFInitThunderScan(TIFF* tif, int scheme)
+{
+  (void) scheme;
+  tif->tif_decoderow = ThunderDecodeRow;
+  tif->tif_decodestrip = ThunderDecodeRow;
+  return (1);
+}
+#endif /* THUNDER_SUPPORT */
+
diff --git a/Utilities/ITK/Utilities/tiff/tif_tile.c b/Utilities/ITK/Utilities/tiff/tif_tile.c
new file mode 100644
index 0000000000..5daf9983ed
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_tile.c
@@ -0,0 +1,264 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1991-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ *
+ * Tiled Image Support Routines.
+ */
+#include "tiffiop.h"
+
+static uint32
+summarize(TIFF* tif, size_t summand1, size_t summand2, const char* where)
+{
+  /*
+   * XXX: We are using casting to uint32 here, bacause sizeof(size_t)
+   * may be larger than sizeof(uint32) on 64-bit architectures.
+   */
+  uint32  bytes = summand1 + summand2;
+
+  if (bytes - summand1 != summand2) {
+    TIFFError(tif->tif_name, "Integer overflow in %s", where);
+    bytes = 0;
+  }
+
+  return (bytes);
+}
+
+static uint32
+multiply(TIFF* tif, size_t nmemb, size_t elem_size, const char* where)
+{
+  uint32  bytes = nmemb * elem_size;
+
+  if (elem_size && bytes / elem_size != nmemb) {
+    TIFFError(tif->tif_name, "Integer overflow in %s", where);
+    bytes = 0;
+  }
+
+  return (bytes);
+}
+
+/*
+ * Compute which tile an (x,y,z,s) value is in.
+ */
+ttile_t
+TIFFComputeTile(TIFF* tif, uint32 x, uint32 y, uint32 z, tsample_t s)
+{
+  TIFFDirectory *td = &tif->tif_dir;
+  uint32 dx = td->td_tilewidth;
+  uint32 dy = td->td_tilelength;
+  uint32 dz = td->td_tiledepth;
+  ttile_t tile = 1;
+
+  if (td->td_imagedepth == 1)
+    z = 0;
+  if (dx == (uint32) -1)
+    dx = td->td_imagewidth;
+  if (dy == (uint32) -1)
+    dy = td->td_imagelength;
+  if (dz == (uint32) -1)
+    dz = td->td_imagedepth;
+  if (dx != 0 && dy != 0 && dz != 0) {
+    uint32 xpt = TIFFhowmany(td->td_imagewidth, dx); 
+    uint32 ypt = TIFFhowmany(td->td_imagelength, dy); 
+    uint32 zpt = TIFFhowmany(td->td_imagedepth, dz); 
+
+    if (td->td_planarconfig == PLANARCONFIG_SEPARATE) 
+      tile = (xpt*ypt*zpt)*s +
+           (xpt*ypt)*(z/dz) +
+           xpt*(y/dy) +
+           x/dx;
+    else
+      tile = (xpt*ypt)*(z/dz) + xpt*(y/dy) + x/dx;
+  }
+  return (tile);
+}
+
+/*
+ * Check an (x,y,z,s) coordinate
+ * against the image bounds.
+ */
+int
+TIFFCheckTile(TIFF* tif, uint32 x, uint32 y, uint32 z, tsample_t s)
+{
+  TIFFDirectory *td = &tif->tif_dir;
+
+  if (x >= td->td_imagewidth) {
+    TIFFError(tif->tif_name, "%lu: Col out of range, max %lu",
+        (unsigned long) x, (unsigned long) td->td_imagewidth);
+    return (0);
+  }
+  if (y >= td->td_imagelength) {
+    TIFFError(tif->tif_name, "%lu: Row out of range, max %lu",
+        (unsigned long) y, (unsigned long) td->td_imagelength);
+    return (0);
+  }
+  if (z >= td->td_imagedepth) {
+    TIFFError(tif->tif_name, "%lu: Depth out of range, max %lu",
+        (unsigned long) z, (unsigned long) td->td_imagedepth);
+    return (0);
+  }
+  if (td->td_planarconfig == PLANARCONFIG_SEPARATE &&
+      s >= td->td_samplesperpixel) {
+    TIFFError(tif->tif_name, "%lu: Sample out of range, max %lu",
+        (unsigned long) s, (unsigned long) td->td_samplesperpixel);
+    return (0);
+  }
+  return (1);
+}
+
+/*
+ * Compute how many tiles are in an image.
+ */
+ttile_t
+TIFFNumberOfTiles(TIFF* tif)
+{
+  TIFFDirectory *td = &tif->tif_dir;
+  uint32 dx = td->td_tilewidth;
+  uint32 dy = td->td_tilelength;
+  uint32 dz = td->td_tiledepth;
+  ttile_t ntiles;
+
+  if (dx == (uint32) -1)
+    dx = td->td_imagewidth;
+  if (dy == (uint32) -1)
+    dy = td->td_imagelength;
+  if (dz == (uint32) -1)
+    dz = td->td_imagedepth;
+  ntiles = (dx == 0 || dy == 0 || dz == 0) ? 0 :
+      multiply(tif, multiply(tif, TIFFhowmany(td->td_imagewidth, dx),
+           TIFFhowmany(td->td_imagelength, dy),
+           "TIFFNumberOfTiles"),
+         TIFFhowmany(td->td_imagedepth, dz), "TIFFNumberOfTiles");
+  if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
+    ntiles = multiply(tif, ntiles, td->td_samplesperpixel,
+          "TIFFNumberOfTiles");
+  return (ntiles);
+}
+
+/*
+ * Compute the # bytes in each row of a tile.
+ */
+tsize_t
+TIFFTileRowSize(TIFF* tif)
+{
+  TIFFDirectory *td = &tif->tif_dir;
+  tsize_t rowsize;
+  
+  if (td->td_tilelength == 0 || td->td_tilewidth == 0)
+    return ((tsize_t) 0);
+  rowsize = multiply(tif, td->td_bitspersample, td->td_tilewidth,
+         "TIFFTileRowSize");
+  if (td->td_planarconfig == PLANARCONFIG_CONTIG)
+    rowsize = multiply(tif, rowsize, td->td_samplesperpixel,
+           "TIFFTileRowSize");
+  return ((tsize_t) TIFFhowmany8(rowsize));
+}
+
+/*
+ * Compute the # bytes in a variable length, row-aligned tile.
+ */
+tsize_t
+TIFFVTileSize(TIFF* tif, uint32 nrows)
+{
+  TIFFDirectory *td = &tif->tif_dir;
+  tsize_t tilesize;
+
+  if (td->td_tilelength == 0 || td->td_tilewidth == 0 ||
+      td->td_tiledepth == 0)
+    return ((tsize_t) 0);
+  if (td->td_planarconfig == PLANARCONFIG_CONTIG &&
+      td->td_photometric == PHOTOMETRIC_YCBCR &&
+      !isUpSampled(tif)) {
+    /*
+     * Packed YCbCr data contain one Cb+Cr for every
+     * HorizontalSampling*VerticalSampling Y values.
+     * Must also roundup width and height when calculating
+     * since images that are not a multiple of the
+     * horizontal/vertical subsampling area include
+     * YCbCr data for the extended image.
+     */
+    tsize_t w =
+        TIFFroundup(td->td_tilewidth, td->td_ycbcrsubsampling[0]);
+    tsize_t rowsize =
+        TIFFhowmany8(multiply(tif, w, td->td_bitspersample,
+            "TIFFVTileSize"));
+    tsize_t samplingarea =
+        td->td_ycbcrsubsampling[0]*td->td_ycbcrsubsampling[1];
+    if (samplingarea == 0) {
+      TIFFError(tif->tif_name, "Invalid YCbCr subsampling");
+      return 0;
+    }
+    nrows = TIFFroundup(nrows, td->td_ycbcrsubsampling[1]);
+    /* NB: don't need TIFFhowmany here 'cuz everything is rounded */
+    tilesize = multiply(tif, nrows, rowsize, "TIFFVTileSize");
+    tilesize = summarize(tif, tilesize,
+             multiply(tif, 2, tilesize / samplingarea,
+                "TIFFVTileSize"),
+             "TIFFVTileSize");
+  } else
+    tilesize = multiply(tif, nrows, TIFFTileRowSize(tif),
+            "TIFFVTileSize");
+  return ((tsize_t)
+      multiply(tif, tilesize, td->td_tiledepth, "TIFFVTileSize"));
+}
+
+/*
+ * Compute the # bytes in a row-aligned tile.
+ */
+tsize_t
+TIFFTileSize(TIFF* tif)
+{
+  return (TIFFVTileSize(tif, tif->tif_dir.td_tilelength));
+}
+
+/*
+ * Compute a default tile size based on the image
+ * characteristics and a requested value.  If a
+ * request is <1 then we choose a size according
+ * to certain heuristics.
+ */
+void
+TIFFDefaultTileSize(TIFF* tif, uint32* tw, uint32* th)
+{
+  (*tif->tif_deftilesize)(tif, tw, th);
+}
+
+void
+_TIFFDefaultTileSize(TIFF* tif, uint32* tw, uint32* th)
+{
+  (void) tif;
+  if (*(int32*) tw < 1)
+    *tw = 256;
+  if (*(int32*) th < 1)
+    *th = 256;
+  /* roundup to a multiple of 16 per the spec */
+  if (*tw & 0xf)
+    *tw = TIFFroundup(*tw, 16);
+  if (*th & 0xf)
+    *th = TIFFroundup(*th, 16);
+}
+
diff --git a/Utilities/ITK/Utilities/tiff/tif_unix.c b/Utilities/ITK/Utilities/tiff/tif_unix.c
new file mode 100644
index 0000000000..aab036f4ac
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_unix.c
@@ -0,0 +1,291 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library UNIX-specific Routines. These are should also work with the
+ * Windows Common RunTime Library.
+ */
+#include "tif_config.h"
+
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#if HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#if HAVE_IO_H
+# include <io.h>
+#endif
+
+#include "tiffiop.h"
+
+static tsize_t
+_tiffReadProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+  return ((tsize_t) read((int) (long int)fd, buf, (size_t) size));
+}
+
+static tsize_t
+_tiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+  return ((tsize_t) write((int) (long int)fd, buf, (size_t) size));
+}
+
+static toff_t
+_tiffSeekProc(thandle_t fd, toff_t off, int whence)
+{
+  return ((toff_t) lseek((int) (long int)fd, (off_t) off, whence));
+}
+
+static int
+_tiffCloseProc(thandle_t fd)
+{
+  return (close((int) (long int)fd));
+}
+
+
+static toff_t
+_tiffSizeProc(thandle_t fd)
+{
+#ifdef _AM29K
+  long fsize;
+  return ((fsize = lseek((int) fd, 0, SEEK_END)) < 0 ? 0 : fsize);
+#else
+  struct stat sb;
+  return (toff_t) (fstat((int) (long int)fd, &sb) < 0 ? 0 : sb.st_size);
+#endif
+}
+
+#ifdef HAVE_MMAP
+#include <sys/mman.h>
+
+static int
+_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
+{
+  toff_t size = _tiffSizeProc(fd);
+  if (size != (toff_t) -1) {
+    *pbase = (tdata_t)
+        mmap(0, size, PROT_READ, MAP_SHARED, (int) (long int)fd, 0);
+    if (*pbase != (tdata_t) -1) {
+      *psize = size;
+      return (1);
+    }
+  }
+  return (0);
+}
+
+static void
+_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size)
+{
+  (void) fd;
+  (void) munmap(base, (off_t) size);
+}
+#else /* !HAVE_MMAP */
+static int
+_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
+{
+  (void) fd; (void) pbase; (void) psize;
+  return (0);
+}
+
+static void
+_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size)
+{
+  (void) fd; (void) base; (void) size;
+}
+#endif /* !HAVE_MMAP */
+
+/*
+ * Open a TIFF file descriptor for read/writing.
+ */
+TIFF*
+TIFFFdOpen(int fd, const char* name, const char* mode)
+{
+  TIFF* tif;
+
+  tif = TIFFClientOpen(name, mode,
+      (thandle_t) (long int)fd,
+      _tiffReadProc, _tiffWriteProc,
+      _tiffSeekProc, _tiffCloseProc, _tiffSizeProc,
+      _tiffMapProc, _tiffUnmapProc);
+  if (tif)
+    tif->tif_fd = fd;
+  return (tif);
+}
+
+/*
+ * Open a TIFF file for read/writing.
+ */
+TIFF*
+TIFFOpen(const char* name, const char* mode)
+{
+  static const char module[] = "TIFFOpen";
+  int m, fd;
+        TIFF* tif;
+
+  m = _TIFFgetMode(mode, module);
+  if (m == -1)
+    return ((TIFF*)0);
+
+/* for cygwin and mingw */        
+#ifdef O_BINARY
+        m |= O_BINARY;
+#endif        
+        
+#ifdef _AM29K
+  fd = open(name, m);
+#else
+  fd = open(name, m, 0666);
+#endif
+  if (fd < 0) {
+    TIFFError(module, "%s: Cannot open", name);
+    return ((TIFF *)0);
+  }
+
+  tif = TIFFFdOpen((int)fd, name, mode);
+  if(!tif)
+    close(fd);
+  return tif;
+}
+
+#ifdef __WIN32__
+/*
+ * Open a TIFF file with a Unicode filename, for read/writing.
+ */
+TIFF*
+TIFFOpenW(const wchar_t* name, const char* mode)
+{
+  static const char module[] = "TIFFOpenW";
+  int m, fd;
+  int mbsize;
+  char *mbname;
+  TIFF* tif;
+
+  m = _TIFFgetMode(mode, module);
+  if (m == -1)
+    return ((TIFF*)0);
+
+/* for cygwin and mingw */        
+#ifdef O_BINARY
+        m |= O_BINARY;
+#endif        
+        
+  fd = _wopen(name, m, 0666);
+  if (fd < 0) {
+    TIFFError(module, "%s: Cannot open", name);
+    return ((TIFF *)0);
+  }
+
+  mbname = NULL;
+  mbsize = WideCharToMultiByte(CP_ACP, 0, name, -1, NULL, 0, NULL, NULL);
+  if (mbsize > 0) {
+    mbname = _TIFFmalloc(mbsize);
+    if (!mbname) {
+      TIFFError(module,
+      "Can't allocate space for filename conversion buffer");
+      return ((TIFF*)0);
+    }
+
+    WideCharToMultiByte(CP_ACP, 0, name, -1, mbname, mbsize,
+            NULL, NULL);
+  }
+
+  tif = TIFFFdOpen((int)fd, (mbname != NULL) ? mbname : "<unknown>",
+       mode);
+  
+  _TIFFfree(mbname);
+  
+  if(!tif)
+    close(fd);
+  return tif;
+}
+#endif
+
+void*
+_TIFFmalloc(tsize_t s)
+{
+  return (malloc((size_t) s));
+}
+
+void
+_TIFFfree(tdata_t p)
+{
+  free(p);
+}
+
+void*
+_TIFFrealloc(tdata_t p, tsize_t s)
+{
+  return (realloc(p, (size_t) s));
+}
+
+void
+_TIFFmemset(tdata_t p, int v, tsize_t c)
+{
+  memset(p, v, (size_t) c);
+}
+
+void
+_TIFFmemcpy(tdata_t d, const tdata_t s, tsize_t c)
+{
+  memcpy(d, s, (size_t) c);
+}
+
+int
+_TIFFmemcmp(const tdata_t p1, const tdata_t p2, tsize_t c)
+{
+  return (memcmp(p1, p2, (size_t) c));
+}
+
+static void
+unixWarningHandler(const char* module, const char* fmt, va_list ap)
+{
+  if (module != NULL)
+    fprintf(stderr, "%s: ", module);
+  fprintf(stderr, "Warning, ");
+  vfprintf(stderr, fmt, ap);
+  fprintf(stderr, ".\n");
+}
+TIFFErrorHandler _TIFFwarningHandler = unixWarningHandler;
+
+static void
+unixErrorHandler(const char* module, const char* fmt, va_list ap)
+{
+  if (module != NULL)
+    fprintf(stderr, "%s: ", module);
+  vfprintf(stderr, fmt, ap);
+  fprintf(stderr, ".\n");
+}
+TIFFErrorHandler _TIFFerrorHandler = unixErrorHandler;
diff --git a/Utilities/ITK/Utilities/tiff/tif_version.c b/Utilities/ITK/Utilities/tiff/tif_version.c
new file mode 100644
index 0000000000..525d8d412d
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_version.c
@@ -0,0 +1,33 @@
+/* $Header: /cvsroot/Insight/Insight/Utilities/tiff/tif_version.c,v 1.3 2005/09/16 19:58:18 jjomier Exp $ */
+/*
+ * Copyright (c) 1992-1997 Sam Leffler
+ * Copyright (c) 1992-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+#include "tiffiop.h"
+
+static const char TIFFVersion[] = TIFFLIB_VERSION_STR;
+
+const char*
+TIFFGetVersion(void)
+{
+  return (TIFFVersion);
+}
diff --git a/Utilities/ITK/Utilities/tiff/tif_vms.c b/Utilities/ITK/Utilities/tiff/tif_vms.c
new file mode 100644
index 0000000000..511f702526
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_vms.c
@@ -0,0 +1,588 @@
+/* $Header: /cvsroot/Insight/Insight/Utilities/tiff/tif_vms.c,v 1.1 2003/11/25 14:10:11 jjomier Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library VMS-specific Routines.
+ */
+
+#include <stdlib.h>
+#include <unixio.h>
+#include "tiffiop.h"
+#if !HAVE_IEEEFP
+#include <math.h>
+#endif
+
+#ifdef VAXC
+#define NOSHARE noshare
+#else
+#define NOSHARE
+#endif
+
+#ifdef __alpha
+/* Dummy entry point for backwards compatibility */
+void TIFFModeCCITTFax3(void){}
+#endif
+
+static tsize_t
+_tiffReadProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+        return (read((int) fd, buf, size));
+}
+
+static tsize_t
+_tiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+        return (write((int) fd, buf, size));
+}
+
+static toff_t
+_tiffSeekProc(thandle_t fd, toff_t off, int whence)
+{
+        return ((toff_t) lseek((int) fd, (off_t) off, whence));
+}
+
+static int
+_tiffCloseProc(thandle_t fd)
+{
+        return (close((int) fd));
+}
+
+#include <sys/stat.h>
+
+static toff_t
+_tiffSizeProc(thandle_t fd)
+{
+        struct stat sb;
+        return (toff_t) (fstat((int) fd, &sb) < 0 ? 0 : sb.st_size);
+}
+
+#ifdef HAVE_MMAP
+#include <starlet.h>
+#include <fab.h>
+#include <secdef.h>
+
+/*
+ * Table for storing information on current open sections. 
+ * (Should really be a linked list)
+ */
+#define MAX_MAPPED 100
+static int no_mapped = 0;
+static struct {
+        char *base;
+        char *top;
+        unsigned short channel;
+} map_table[MAX_MAPPED];
+
+/* 
+ * This routine maps a file into a private section. Note that this 
+ * method of accessing a file is by far the fastest under VMS.
+ * The routine may fail (i.e. return 0) for several reasons, for
+ * example:
+ * - There is no more room for storing the info on sections.
+ * - The process is out of open file quota, channels, ...
+ * - fd does not describe an opened file.
+ * - The file is already opened for write access by this process
+ *   or another process
+ * - There is no free "hole" in virtual memory that fits the
+ *   size of the file
+ */
+static int
+_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
+{
+        char name[256];
+        struct FAB fab;
+        unsigned short channel;
+        char *inadr[2], *retadr[2];
+        unsigned long status;
+        long size;
+        
+        if (no_mapped >= MAX_MAPPED)
+                return(0);
+        /*
+         * We cannot use a file descriptor, we
+         * must open the file once more.
+         */
+        if (getname((int)fd, name, 1) == NULL)
+                return(0);
+        /* prepare the FAB for a user file open */
+        fab = cc$rms_fab;
+        fab.fab$l_fop |= FAB$V_UFO;
+        fab.fab$b_fac = FAB$M_GET;
+        fab.fab$b_shr = FAB$M_SHRGET;
+        fab.fab$l_fna = name;
+        fab.fab$b_fns = strlen(name);
+        status = sys$open(&fab);        /* open file & get channel number */
+        if ((status&1) == 0)
+                return(0);
+        channel = (unsigned short)fab.fab$l_stv;
+        inadr[0] = inadr[1] = (char *)0; /* just an address in P0 space */
+        /*
+         * Map the blocks of the file up to
+         * the EOF block into virtual memory.
+         */
+        size = _tiffSizeProc(fd);
+        status = sys$crmpsc(inadr, retadr, 0, SEC$M_EXPREG, 0,0,0, channel,
+                TIFFhowmany(size,512), 0,0,0);
+        if ((status&1) == 0){
+                sys$dassgn(channel);
+                return(0);
+        }
+        *pbase = (tdata_t) retadr[0];   /* starting virtual address */
+        /*
+         * Use the size of the file up to the
+         * EOF mark for UNIX compatibility.
+         */
+        *psize = (toff_t) size;
+        /* Record the section in the table */
+        map_table[no_mapped].base = retadr[0];
+        map_table[no_mapped].top = retadr[1];
+        map_table[no_mapped].channel = channel;
+        no_mapped++;
+
+        return(1);
+}
+
+/*
+ * This routine unmaps a section from the virtual address space of 
+ * the process, but only if the base was the one returned from a
+ * call to TIFFMapFileContents.
+ */
+static void
+_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size)
+{
+        char *inadr[2];
+        int i, j;
+        
+        /* Find the section in the table */
+        for (i = 0;i < no_mapped; i++) {
+                if (map_table[i].base == (char *) base) {
+                        /* Unmap the section */
+                        inadr[0] = (char *) base;
+                        inadr[1] = map_table[i].top;
+                        sys$deltva(inadr, 0, 0);
+                        sys$dassgn(map_table[i].channel);
+                        /* Remove this section from the list */
+                        for (j = i+1; j < no_mapped; j++)
+                                map_table[j-1] = map_table[j];
+                        no_mapped--;
+                        return;
+                }
+        }
+}
+#else /* !HAVE_MMAP */
+static int
+_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
+{
+        return (0);
+}
+
+static void
+_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size)
+{
+}
+#endif /* !HAVE_MMAP */
+
+/*
+ * Open a TIFF file descriptor for read/writing.
+ */
+TIFF*
+TIFFFdOpen(int fd, const char* name, const char* mode)
+{
+        TIFF* tif;
+
+        tif = TIFFClientOpen(name, mode,
+            (thandle_t) fd,
+            _tiffReadProc, _tiffWriteProc, _tiffSeekProc, _tiffCloseProc,
+            _tiffSizeProc, _tiffMapProc, _tiffUnmapProc);
+        if (tif)
+                tif->tif_fd = fd;
+        return (tif);
+}
+
+/*
+ * Open a TIFF file for read/writing.
+ */
+TIFF*
+TIFFOpen(const char* name, const char* mode)
+{
+        static const char module[] = "TIFFOpen";
+        int m, fd;
+
+        m = _TIFFgetMode(mode, module);
+        if (m == -1)
+                return ((TIFF*)0);
+        if (m&O_TRUNC){
+                /*
+                 * There is a bug in open in VAXC. If you use
+                 * open w/ m=O_RDWR|O_CREAT|O_TRUNC the
+                 * wrong thing happens.  On the other hand
+                 * creat does the right thing.
+                 */
+                fd = creat((char *) /* bug in stdio.h */ name, 0666,
+                    "alq = 128", "deq = 64", "mbc = 32",
+                    "fop = tef");
+        } else if (m&O_RDWR) {
+                fd = open(name, m, 0666,
+                    "deq = 64", "mbc = 32", "fop = tef", "ctx = stm");
+        } else
+                fd = open(name, m, 0666, "mbc = 32", "ctx = stm");
+        if (fd < 0) {
+                TIFFError(module, "%s: Cannot open", name);
+                return ((TIFF*)0);
+        }
+        return (TIFFFdOpen(fd, name, mode));
+}
+
+tdata_t
+_TIFFmalloc(tsize_t s)
+{
+        return (malloc((size_t) s));
+}
+
+void
+_TIFFfree(tdata_t p)
+{
+        free(p);
+}
+
+tdata_t
+_TIFFrealloc(tdata_t p, tsize_t s)
+{
+        return (realloc(p, (size_t) s));
+}
+
+void
+_TIFFmemset(tdata_t p, int v, tsize_t c)
+{
+        memset(p, v, (size_t) c);
+}
+
+void
+_TIFFmemcpy(tdata_t d, const tdata_t s, tsize_t c)
+{
+        memcpy(d, s, (size_t) c);
+}
+
+int
+_TIFFmemcmp(const tdata_t p1, const tdata_t p2, tsize_t c)
+{
+        return (memcmp(p1, p2, (size_t) c));
+}
+
+/*
+ * On the VAX, we need to make those global, writable pointers
+ * non-shareable, otherwise they would be made shareable by default.
+ * On the AXP, this brain damage has been corrected. 
+ * 
+ * I (Karsten Spang, krs@kampsax.dk) have dug around in the GCC
+ * manual and the GAS code and have come up with the following
+ * construct, but I don't have GCC on my VAX, so it is untested.
+ * Please tell me if it does not work.
+ */
+
+static void
+vmsWarningHandler(const char* module, const char* fmt, va_list ap)
+{
+        if (module != NULL)
+                fprintf(stderr, "%s: ", module);
+        fprintf(stderr, "Warning, ");
+        vfprintf(stderr, fmt, ap);
+        fprintf(stderr, ".\n");
+}
+
+NOSHARE TIFFErrorHandler _TIFFwarningHandler = vmsWarningHandler
+#if defined(VAX) && defined(__GNUC__)
+asm("_$$PsectAttributes_NOSHR$$_TIFFwarningHandler")
+#endif
+;
+
+static void
+vmsErrorHandler(const char* module, const char* fmt, va_list ap)
+{
+        if (module != NULL)
+                fprintf(stderr, "%s: ", module);
+        vfprintf(stderr, fmt, ap);
+        fprintf(stderr, ".\n");
+}
+
+NOSHARE TIFFErrorHandler _TIFFerrorHandler = vmsErrorHandler
+#if defined(VAX) && defined(__GNUC__)
+asm("_$$PsectAttributes_NOSHR$$_TIFFerrorHandler")
+#endif
+;
+
+
+#if !HAVE_IEEEFP
+/* IEEE floting point handling */
+
+typedef struct ieeedouble {
+        u_long  mant2;                  /* fix NDR: full 8-byte swap */
+        u_long  mant    : 20,
+                exp     : 11,
+                sign    : 1;
+} ieeedouble;
+typedef struct ieeefloat {
+        u_long  mant    : 23,
+                exp     : 8,
+                sign    : 1;
+} ieeefloat;
+
+/* 
+ * NB: These are D_FLOAT's, not G_FLOAT's. A G_FLOAT is
+ *  simply a reverse-IEEE float/double.
+ */
+
+typedef struct {
+        u_long  mant1   : 7,
+                exp     : 8,
+                sign    : 1,
+                mant2   : 16,
+                mant3   : 16,
+                mant4   : 16;
+} nativedouble;
+typedef struct {
+        u_long  mant1   : 7,
+                exp     : 8,
+                sign    : 1,
+                mant2   : 16;
+} nativefloat;
+
+typedef union {
+        ieeedouble      ieee;
+        nativedouble    native;
+        char            b[8];
+        uint32          l[2];
+        double          d;
+} double_t;
+
+typedef union {
+        ieeefloat       ieee;
+        nativefloat     native;
+        char            b[4];
+        uint32          l;
+        float           f;
+} float_t;
+
+#if defined(VAXC) || defined(DECC)
+#pragma inline(ieeetod,dtoieee)
+#endif
+
+/*
+ * Convert an IEEE double precision number to native double precision.
+ * The source is contained in two longwords, the second holding the sign,
+ * exponent and the higher order bits of the mantissa, and the first
+ * holding the rest of the mantissa as follows:
+ * (Note: It is assumed that the number has been eight-byte swapped to
+ * LSB first.)
+ * 
+ * First longword:
+ *      32 least significant bits of mantissa
+ * Second longword:
+ *      0-19:   20 most significant bits of mantissa
+ *      20-30:  exponent
+ *      31:     sign
+ * The exponent is stored as excess 1023.
+ * The most significant bit of the mantissa is implied 1, and not stored.
+ * If the exponent and mantissa are zero, the number is zero.
+ * If the exponent is 0 (i.e. -1023) and the mantissa is non-zero, it is an
+ * unnormalized number with the most significant bit NOT implied.
+ * If the exponent is 2047, the number is invalid, in case the mantissa is zero,
+ * this means overflow (+/- depending of the sign bit), otherwise
+ * it simply means invalid number.
+ * 
+ * If the number is too large for the machine or was specified as overflow, 
+ * +/-HUGE_VAL is returned.
+ */
+INLINE static void
+ieeetod(double *dp)
+{
+        double_t source;
+        long sign,exp,mant;
+        double dmant;
+
+        source.ieee = ((double_t*)dp)->ieee;
+        sign = source.ieee.sign;
+        exp = source.ieee.exp;
+        mant = source.ieee.mant;
+
+        if (exp == 2047) {
+                if (mant)                       /* Not a Number (NAN) */
+                        *dp = HUGE_VAL;
+                else                            /* +/- infinity */
+                        *dp = (sign ? -HUGE_VAL : HUGE_VAL);
+                return;
+        }
+        if (!exp) {
+                if (!(mant || source.ieee.mant2)) {     /* zero */
+                        *dp=0;
+                        return;
+                } else {                        /* Unnormalized number */
+                        /* NB: not -1023, the 1 bit is not implied */
+                        exp= -1022;
+                }
+        } else {
+                mant |= 1<<20;
+                exp -= 1023;
+        }
+        dmant = (((double) mant) +
+                ((double) source.ieee.mant2) / (((double) (1<<16)) *
+                ((double) (1<<16)))) / (double) (1<<20);
+        dmant = ldexp(dmant, exp);
+        if (sign)
+                dmant= -dmant;
+        *dp = dmant;
+}
+
+INLINE static void
+dtoieee(double *dp)
+{
+        double_t num;
+        double x;
+        int exp;
+
+        num.d = *dp;
+        if (!num.d) {                   /* Zero is just binary all zeros */
+                num.l[0] = num.l[1] = 0;
+                return;
+        }
+
+        if (num.d < 0) {                /* Sign is encoded separately */
+                num.d = -num.d;
+                num.ieee.sign = 1;
+        } else {
+                num.ieee.sign = 0;
+        }
+
+        /* Now separate the absolute value into mantissa and exponent */
+        x = frexp(num.d, &exp);
+
+        /*
+         * Handle cases where the value is outside the
+         * range for IEEE floating point numbers. 
+         * (Overflow cannot happen on a VAX, but underflow
+         * can happen for G float.)
+         */
+        if (exp < -1022) {              /* Unnormalized number */
+                x = ldexp(x, -1023-exp);
+                exp = 0;
+        } else if (exp > 1023) {        /* +/- infinity */
+                x = 0;
+                exp = 2047;
+        } else {                        /* Get rid of most significant bit */
+                x *= 2;
+                x -= 1;
+                exp += 1022; /* fix NDR: 1.0 -> x=0.5, exp=1 -> ieee.exp = 1023 */
+        }
+        num.ieee.exp = exp;
+
+        x *= (double) (1<<20);
+        num.ieee.mant = (long) x;
+        x -= (double) num.ieee.mant;
+        num.ieee.mant2 = (long) (x*((double) (1<<16)*(double) (1<<16)));
+
+        if (!(num.ieee.mant || num.ieee.exp || num.ieee.mant2)) {
+                /* Avoid negative zero */
+                num.ieee.sign = 0;
+        }
+        ((double_t*)dp)->ieee = num.ieee;
+}
+
+/*
+ * Beware, these do not handle over/under-flow
+ * during conversion from ieee to native format.
+ */
+#define NATIVE2IEEEFLOAT(fp) { \
+    float_t t; \
+    if (t.ieee.exp = (fp)->native.exp) \
+        t.ieee.exp += -129 + 127; \
+    t.ieee.sign = (fp)->native.sign; \
+    t.ieee.mant = ((fp)->native.mant1<<16)|(fp)->native.mant2; \
+    *(fp) = t; \
+}
+#define IEEEFLOAT2NATIVE(fp) { \
+    float_t t; int v = (fp)->ieee.exp; \
+    if (v) v += -127 + 129;             /* alter bias of exponent */\
+    t.native.exp = v;                   /* implicit truncation of exponent */\
+    t.native.sign = (fp)->ieee.sign; \
+    v = (fp)->ieee.mant; \
+    t.native.mant1 = v >> 16; \
+    t.native.mant2 = v;\
+    *(fp) = t; \
+}
+
+#define IEEEDOUBLE2NATIVE(dp) ieeetod(dp)
+
+#define NATIVE2IEEEDOUBLE(dp) dtoieee(dp)
+
+
+/*
+ * These unions are used during floating point
+ * conversions.  The above macros define the
+ * conversion operations.
+ */
+void
+TIFFCvtIEEEFloatToNative(TIFF* tif, u_int n, float* f)
+{
+        float_t* fp = (float_t*) f;
+
+        while (n-- > 0) {
+                IEEEFLOAT2NATIVE(fp);
+                fp++;
+        }
+}
+
+void
+TIFFCvtNativeToIEEEFloat(TIFF* tif, u_int n, float* f)
+{
+        float_t* fp = (float_t*) f;
+
+        while (n-- > 0) {
+                NATIVE2IEEEFLOAT(fp);
+                fp++;
+        }
+}
+void
+TIFFCvtIEEEDoubleToNative(TIFF* tif, u_int n, double* f)
+{
+        double_t* fp = (double_t*) f;
+
+        while (n-- > 0) {
+                IEEEDOUBLE2NATIVE(fp);
+                fp++;
+        }
+}
+
+void
+TIFFCvtNativeToIEEEDouble(TIFF* tif, u_int n, double* f)
+{
+        double_t* fp = (double_t*) f;
+
+        while (n-- > 0) {
+                NATIVE2IEEEDOUBLE(fp);
+                fp++;
+        }
+}
+#endif
diff --git a/Utilities/ITK/Utilities/tiff/tif_warning.c b/Utilities/ITK/Utilities/tiff/tif_warning.c
new file mode 100644
index 0000000000..add1de81ea
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_warning.c
@@ -0,0 +1,49 @@
+/* $Header: /cvsroot/Insight/Insight/Utilities/tiff/tif_warning.c,v 1.3 2005/09/16 19:58:18 jjomier Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ */
+#include "tiffiop.h"
+
+TIFFErrorHandler
+TIFFSetWarningHandler(TIFFErrorHandler handler)
+{
+  TIFFErrorHandler prev = _TIFFwarningHandler;
+  _TIFFwarningHandler = handler;
+  return (prev);
+}
+
+void
+TIFFWarning(const char* module, const char* fmt, ...)
+{
+  if (_TIFFwarningHandler) {
+    va_list ap;
+    va_start(ap, fmt);
+    (*_TIFFwarningHandler)(module, fmt, ap);
+    va_end(ap);
+  }
+}
diff --git a/Utilities/ITK/Utilities/tiff/tif_win3.c b/Utilities/ITK/Utilities/tiff/tif_win3.c
new file mode 100644
index 0000000000..9aeec4d737
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_win3.c
@@ -0,0 +1,225 @@
+/* $Header: /cvsroot/Insight/Insight/Utilities/tiff/tif_win3.c,v 1.3 2005/09/16 19:58:18 jjomier Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library Windows 3.x-specific Routines.
+ */
+#include "tiffiop.h"
+#if defined(__WATCOMC__) || defined(__BORLANDC__) || defined(_MSC_VER)
+#include <io.h>    /* for open, close, etc. function prototypes */
+#endif
+
+#include <windows.h>
+#include <windowsx.h>
+#include <memory.h>
+
+static tsize_t 
+_tiffReadProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+  return (_hread(fd, buf, size));
+}
+
+static tsize_t
+_tiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+  return (_hwrite(fd, buf, size));
+}
+
+static toff_t
+_tiffSeekProc(thandle_t fd, toff_t off, int whence)
+{
+  return (_llseek(fd, (off_t) off, whence));
+}
+
+static int
+_tiffCloseProc(thandle_t fd)
+{
+  return (_lclose(fd));
+}
+
+#include <sys/stat.h>
+
+static toff_t
+_tiffSizeProc(thandle_t fd)
+{
+  struct stat sb;
+  return (fstat((int) fd, &sb) < 0 ? 0 : sb.st_size);
+}
+
+static int
+_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
+{
+  return (0);
+}
+
+static void
+_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size)
+{
+}
+
+/*
+ * Open a TIFF file descriptor for read/writing.
+ */
+TIFF*
+TIFFFdOpen(int fd, const char* name, const char* mode)
+{
+  TIFF* tif;
+
+  tif = TIFFClientOpen(name, mode,
+      (thandle_t) fd,
+      _tiffReadProc, _tiffWriteProc, _tiffSeekProc, _tiffCloseProc,
+      _tiffSizeProc, _tiffMapProc, _tiffUnmapProc);
+  if (tif)
+    tif->tif_fd = fd;
+  return (tif);
+}
+
+/*
+ * Open a TIFF file for read/writing.
+ */
+TIFF*
+TIFFOpen(const char* name, const char* mode)
+{
+  static const char module[] = "TIFFOpen";
+  int m, fd;
+  OFSTRUCT of;
+  int mm = 0;
+
+  m = _TIFFgetMode(mode, module);
+  if (m == -1)
+    return ((TIFF*)0);
+  if (m & O_CREAT) {
+    if ((m & O_TRUNC) || OpenFile(name, &of, OF_EXIST) != HFILE_ERROR)
+      mm |= OF_CREATE;
+  }
+  if (m & O_WRONLY)
+    mm |= OF_WRITE;
+  if (m & O_RDWR)
+    mm |= OF_READWRITE;
+  fd = OpenFile(name, &of, mm);
+  if (fd < 0) {
+    TIFFError(module, "%s: Cannot open", name);
+    return ((TIFF*)0);
+  }
+  return (TIFFFdOpen(fd, name, mode));
+}
+
+tdata_t
+_TIFFmalloc(tsize_t s)
+{
+  return (tdata_t) GlobalAllocPtr(GHND, (DWORD) s);
+}
+
+void
+_TIFFfree(tdata_t p)
+{
+  GlobalFreePtr(p);
+}
+
+tdata_t
+_TIFFrealloc(tdata_t p, tsize_t s)
+{
+  return (tdata_t) GlobalReAllocPtr(p, (DWORD) s, GHND);
+}
+
+void
+_TIFFmemset(tdata_t p, int v, tsize_t c)
+{
+  char* pp = (char*) p;
+
+  while (c > 0) {
+    tsize_t chunk = 0x10000 - ((uint32) pp & 0xffff);/* What's left in segment */
+    if (chunk > 0xff00)        /* No more than 0xff00 */
+      chunk = 0xff00;
+    if (chunk > c)          /* No more than needed */
+      chunk = c;
+    memset(pp, v, chunk);
+    pp = (char*) (chunk + (char huge*) pp);
+    c -= chunk;
+  }
+}
+
+void
+_TIFFmemcpy(tdata_t d, const tdata_t s, tsize_t c)
+{
+  if (c > 0xFFFF)
+    hmemcpy((void _huge*) d, (void _huge*) s, c);
+  else
+    (void) memcpy(d, s, (size_t) c);
+}
+
+int
+_TIFFmemcmp(const tdata_t d, const tdata_t s, tsize_t c)
+{
+  char* dd = (char*) d;
+  char* ss = (char*) s;
+  tsize_t chunks, chunkd, chunk;
+  int result;
+
+  while (c > 0) {
+    chunks = 0x10000 - ((uint32) ss & 0xffff);  /* What's left in segment */
+    chunkd = 0x10000 - ((uint32) dd & 0xffff);  /* What's left in segment */
+    chunk = c;          /* Get the largest of     */
+    if (chunk > chunks)        /*   c, chunks, chunkd,   */
+      chunk = chunks;        /*   0xff00               */
+    if (chunk > chunkd)
+      chunk = chunkd;
+    if (chunk > 0xff00)
+      chunk = 0xff00;
+    result = memcmp(dd, ss, chunk);
+    if (result != 0)
+      return (result);
+    dd = (char*) (chunk + (char huge*) dd);
+    ss = (char*) (chunk + (char huge*) ss);
+    c -= chunk;
+  }
+  return (0);
+}
+
+static void
+win3WarningHandler(const char* module, const char* fmt, va_list ap)
+{
+  char e[512] = { '\0' };
+  if (module != NULL)
+    strcat(strcpy(e, module), ":");
+  vsprintf(e+strlen(e), fmt, ap);
+  strcat(e, ".");
+  MessageBox(GetActiveWindow(), e, "LibTIFF Warning",
+      MB_OK|MB_ICONEXCLAMATION);
+}
+TIFFErrorHandler _TIFFwarningHandler = win3WarningHandler;
+
+static void
+win3ErrorHandler(const char* module, const char* fmt, va_list ap)
+{
+  char e[512] = { '\0' };
+  if (module != NULL)
+    strcat(strcpy(e, module), ":");
+  vsprintf(e+strlen(e), fmt, ap);
+  strcat(e, ".");
+  MessageBox(GetActiveWindow(), e, "LibTIFF Error", MB_OK|MB_ICONSTOP);
+}
+TIFFErrorHandler _TIFFerrorHandler = win3ErrorHandler;
diff --git a/Utilities/ITK/Utilities/tiff/tif_win32.c b/Utilities/ITK/Utilities/tiff/tif_win32.c
new file mode 100644
index 0000000000..9bd90e57d6
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_win32.c
@@ -0,0 +1,389 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library Win32-specific Routines.  Adapted from tif_unix.c 4/5/95 by
+ * Scott Wagner (wagner@itek.com), Itek Graphix, Rochester, NY USA
+ */
+#include "tiffiop.h"
+
+static tsize_t
+_tiffReadProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+  DWORD dwSizeRead;
+  if (!ReadFile(fd, buf, size, &dwSizeRead, NULL))
+    return(0);
+  return ((tsize_t) dwSizeRead);
+}
+
+static tsize_t
+_tiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+  DWORD dwSizeWritten;
+  if (!WriteFile(fd, buf, size, &dwSizeWritten, NULL))
+    return(0);
+  return ((tsize_t) dwSizeWritten);
+}
+
+static toff_t
+_tiffSeekProc(thandle_t fd, toff_t off, int whence)
+{
+  DWORD dwMoveMethod, dwMoveHigh;
+
+        /* we use this as a special code, so avoid accepting it */
+        if( off == 0xFFFFFFFF )
+            return 0xFFFFFFFF;
+        
+  switch(whence)
+  {
+  case SEEK_SET:
+    dwMoveMethod = FILE_BEGIN;
+    break;
+  case SEEK_CUR:
+    dwMoveMethod = FILE_CURRENT;
+    break;
+  case SEEK_END:
+    dwMoveMethod = FILE_END;
+    break;
+  default:
+    dwMoveMethod = FILE_BEGIN;
+    break;
+  }
+        dwMoveHigh = 0;
+  return ((toff_t)SetFilePointer(fd, (LONG) off, (PLONG)&dwMoveHigh,
+                                       dwMoveMethod));
+}
+
+static int
+_tiffCloseProc(thandle_t fd)
+{
+  return (CloseHandle(fd) ? 0 : -1);
+}
+
+static toff_t
+_tiffSizeProc(thandle_t fd)
+{
+  return ((toff_t)GetFileSize(fd, NULL));
+}
+
+#ifdef __BORLANDC__
+#pragma argsused
+#endif
+static int
+_tiffDummyMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
+{
+  return (0);
+}
+
+/*
+ * From "Hermann Josef Hill" <lhill@rhein-zeitung.de>:
+ *
+ * Windows uses both a handle and a pointer for file mapping,
+ * but according to the SDK documentation and Richter's book
+ * "Advanced Windows Programming" it is safe to free the handle
+ * after obtaining the file mapping pointer
+ *
+ * This removes a nasty OS dependency and cures a problem
+ * with Visual C++ 5.0
+ */
+static int
+_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
+{
+  toff_t size;
+  HANDLE hMapFile;
+
+  if ((size = _tiffSizeProc(fd)) == 0xFFFFFFFF)
+    return (0);
+  hMapFile = CreateFileMapping(fd, NULL, PAGE_READONLY, 0, size, NULL);
+  if (hMapFile == NULL)
+    return (0);
+  *pbase = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
+  CloseHandle(hMapFile);
+  if (*pbase == NULL)
+    return (0);
+  *psize = size;
+  return(1);
+}
+
+#ifdef __BORLANDC__
+#pragma argsused
+#endif
+static void
+_tiffDummyUnmapProc(thandle_t fd, tdata_t base, toff_t size)
+{
+}
+
+static void
+_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size)
+{
+  UnmapViewOfFile(base);
+}
+
+/*
+ * Open a TIFF file descriptor for read/writing.
+ * Note that TIFFFdOpen and TIFFOpen recognise the character 'u' in the mode
+ * string, which forces the file to be opened unmapped.
+ */
+TIFF*
+TIFFFdOpen(int ifd, const char* name, const char* mode)
+{
+  TIFF* tif;
+  BOOL fSuppressMap = (mode[1] == 'u' || (mode[1]!=0 && mode[2] == 'u'));
+
+  tif = TIFFClientOpen(name, mode, (thandle_t)ifd,
+      _tiffReadProc, _tiffWriteProc,
+      _tiffSeekProc, _tiffCloseProc, _tiffSizeProc,
+      fSuppressMap ? _tiffDummyMapProc : _tiffMapProc,
+      fSuppressMap ? _tiffDummyUnmapProc : _tiffUnmapProc);
+  if (tif)
+    tif->tif_fd = ifd;
+  return (tif);
+}
+
+/*
+ * Open a TIFF file for read/writing.
+ */
+TIFF*
+TIFFOpen(const char* name, const char* mode)
+{
+  static const char module[] = "TIFFOpen";
+  thandle_t fd;
+  int m;
+  DWORD dwMode;
+  TIFF* tif;
+
+  m = _TIFFgetMode(mode, module);
+
+  switch(m)
+  {
+  case O_RDONLY:
+    dwMode = OPEN_EXISTING;
+    break;
+  case O_RDWR:
+    dwMode = OPEN_ALWAYS;
+    break;
+  case O_RDWR|O_CREAT:
+    dwMode = OPEN_ALWAYS;
+    break;
+  case O_RDWR|O_TRUNC:
+    dwMode = CREATE_ALWAYS;
+    break;
+  case O_RDWR|O_CREAT|O_TRUNC:
+    dwMode = CREATE_ALWAYS;
+    break;
+  default:
+    return ((TIFF*)0);
+  }
+  fd = (thandle_t)CreateFileA(name,
+    (m == O_RDONLY)?GENERIC_READ:(GENERIC_READ | GENERIC_WRITE),
+    FILE_SHARE_READ, NULL, dwMode,
+    (m == O_RDONLY)?FILE_ATTRIBUTE_READONLY:FILE_ATTRIBUTE_NORMAL,
+    NULL);
+  if (fd == INVALID_HANDLE_VALUE) {
+    TIFFError(module, "%s: Cannot open", name);
+    return ((TIFF *)0);
+  }
+
+  tif = TIFFFdOpen((int)fd, name, mode);
+  if(!tif)
+    CloseHandle(fd);
+  return tif;
+}
+
+/*
+ * Open a TIFF file with a Unicode filename, for read/writing.
+ */
+TIFF*
+TIFFOpenW(const wchar_t* name, const char* mode)
+{
+  static const char module[] = "TIFFOpenW";
+  thandle_t fd;
+  int m;
+  DWORD dwMode;
+  int mbsize;
+  char *mbname;
+  TIFF *tif;
+
+  m = _TIFFgetMode(mode, module);
+
+  switch(m) {
+    case O_RDONLY:      dwMode = OPEN_EXISTING; break;
+    case O_RDWR:      dwMode = OPEN_ALWAYS;   break;
+    case O_RDWR|O_CREAT:    dwMode = OPEN_ALWAYS;   break;
+    case O_RDWR|O_TRUNC:    dwMode = CREATE_ALWAYS; break;
+    case O_RDWR|O_CREAT|O_TRUNC:  dwMode = CREATE_ALWAYS; break;
+    default:      return ((TIFF*)0);
+  }
+
+  fd = (thandle_t)CreateFileW(name,
+    (m == O_RDONLY)?GENERIC_READ:(GENERIC_READ|GENERIC_WRITE),
+    FILE_SHARE_READ, NULL, dwMode,
+    (m == O_RDONLY)?FILE_ATTRIBUTE_READONLY:FILE_ATTRIBUTE_NORMAL,
+    NULL);
+  if (fd == INVALID_HANDLE_VALUE) {
+    TIFFError(module, "%S: Cannot open", name);
+    return ((TIFF *)0);
+  }
+
+  mbname = NULL;
+  mbsize = WideCharToMultiByte(CP_ACP, 0, name, -1, NULL, 0, NULL, NULL);
+  if (mbsize > 0) {
+    mbname = _TIFFmalloc(mbsize);
+    if (!mbname) {
+      TIFFError(module,
+      "Can't allocate space for filename conversion buffer");
+      return ((TIFF*)0);
+    }
+
+    WideCharToMultiByte(CP_ACP, 0, name, -1, mbname, mbsize,
+            NULL, NULL);
+  }
+
+  tif = TIFFFdOpen((int)fd,
+       (mbname != NULL) ? mbname : "<unknown>", mode);
+
+  _TIFFfree(mbname);
+
+  return tif;
+}
+
+tdata_t
+_TIFFmalloc(tsize_t s)
+{
+  return ((tdata_t)GlobalAlloc(GMEM_FIXED, s));
+}
+
+void
+_TIFFfree(tdata_t p)
+{
+  GlobalFree(p);
+  return;
+}
+
+tdata_t
+_TIFFrealloc(tdata_t p, tsize_t s)
+{
+        void* pvTmp;
+        tsize_t old;
+
+        if(p == NULL)
+                return ((tdata_t)GlobalAlloc(GMEM_FIXED, s));
+
+        old = GlobalSize(p);
+
+        if (old>=s) {
+                if ((pvTmp = GlobalAlloc(GMEM_FIXED, s)) != NULL) {
+                  CopyMemory(pvTmp, p, s);
+                  GlobalFree(p);
+                }
+        } else {
+                if ((pvTmp = GlobalAlloc(GMEM_FIXED, s)) != NULL) {
+                  CopyMemory(pvTmp, p, old);
+                  GlobalFree(p);
+                }
+        }
+        return ((tdata_t)pvTmp);
+}
+
+void
+_TIFFmemset(void* p, int v, tsize_t c)
+{
+  FillMemory(p, c, (BYTE)v);
+}
+
+void
+_TIFFmemcpy(void* d, const tdata_t s, tsize_t c)
+{
+  CopyMemory(d, s, c);
+}
+
+int
+_TIFFmemcmp(const tdata_t p1, const tdata_t p2, tsize_t c)
+{
+  register const BYTE *pb1 = (const BYTE *) p1;
+  register const BYTE *pb2 = (const BYTE *) p2;
+  register DWORD dwTmp = c;
+  register int iTmp;
+  for (iTmp = 0; dwTmp-- && !iTmp; iTmp = (int)*pb1++ - (int)*pb2++)
+    ;
+  return (iTmp);
+}
+
+static void
+Win32WarningHandler(const char* module, const char* fmt, va_list ap)
+{
+#ifndef TIF_PLATFORM_CONSOLE
+  LPTSTR szTitle;
+  LPTSTR szTmp;
+  LPCTSTR szTitleText = "%s Warning";
+  LPCTSTR szDefaultModule = "LIBTIFF";
+  LPCTSTR szTmpModule = (module == NULL) ? szDefaultModule : module;
+  if ((szTitle = (LPTSTR)LocalAlloc(LMEM_FIXED, (strlen(szTmpModule) +
+    strlen(szTitleText) + strlen(fmt) + 128)*sizeof(char))) == NULL)
+    return;
+  sprintf(szTitle, szTitleText, szTmpModule);
+  szTmp = szTitle + (strlen(szTitle)+2)*sizeof(char);
+  vsprintf(szTmp, fmt, ap);
+  MessageBoxA(GetFocus(), szTmp, szTitle, MB_OK | MB_ICONINFORMATION);
+  LocalFree(szTitle);
+  return;
+#else
+  if (module != NULL)
+    fprintf(stderr, "%s: ", module);
+  fprintf(stderr, "Warning, ");
+  vfprintf(stderr, fmt, ap);
+  fprintf(stderr, ".\n");
+#endif        
+}
+TIFFErrorHandler _TIFFwarningHandler = Win32WarningHandler;
+
+static void
+Win32ErrorHandler(const char* module, const char* fmt, va_list ap)
+{
+#ifndef TIF_PLATFORM_CONSOLE
+  LPTSTR szTitle;
+  LPTSTR szTmp;
+  LPCTSTR szTitleText = "%s Error";
+  LPCTSTR szDefaultModule = "LIBTIFF";
+  LPCTSTR szTmpModule = (module == NULL) ? szDefaultModule : module;
+  if ((szTitle = (LPTSTR)LocalAlloc(LMEM_FIXED, (strlen(szTmpModule) +
+    strlen(szTitleText) + strlen(fmt) + 128)*sizeof(char))) == NULL)
+    return;
+  sprintf(szTitle, szTitleText, szTmpModule);
+  szTmp = szTitle + (strlen(szTitle)+2)*sizeof(char);
+  vsprintf(szTmp, fmt, ap);
+  MessageBoxA(GetFocus(), szTmp, szTitle, MB_OK | MB_ICONEXCLAMATION);
+  LocalFree(szTitle);
+  return;
+#else
+  if (module != NULL)
+    fprintf(stderr, "%s: ", module);
+  vfprintf(stderr, fmt, ap);
+  fprintf(stderr, ".\n");
+#endif        
+}
+TIFFErrorHandler _TIFFerrorHandler = Win32ErrorHandler;
+
diff --git a/Utilities/ITK/Utilities/tiff/tif_write.c b/Utilities/ITK/Utilities/tiff/tif_write.c
new file mode 100644
index 0000000000..3ad1a566b3
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_write.c
@@ -0,0 +1,716 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ *
+ * Scanline-oriented Write Support
+ */
+#include "tiffiop.h"
+#include <stdio.h>
+
+#define  STRIPINCR  20    /* expansion factor on strip array */
+
+#define  WRITECHECKSTRIPS(tif, module)        \
+  (((tif)->tif_flags&TIFF_BEENWRITING) || TIFFWriteCheck((tif),0,module))
+#define  WRITECHECKTILES(tif, module)        \
+  (((tif)->tif_flags&TIFF_BEENWRITING) || TIFFWriteCheck((tif),1,module))
+#define  BUFFERCHECK(tif)          \
+  ((((tif)->tif_flags & TIFF_BUFFERSETUP) && tif->tif_rawdata) ||  \
+      TIFFWriteBufferSetup((tif), NULL, (tsize_t) -1))
+
+static  int TIFFGrowStrips(TIFF*, int, const char*);
+static  int TIFFAppendToStrip(TIFF*, tstrip_t, tidata_t, tsize_t);
+
+int
+TIFFWriteScanline(TIFF* tif, tdata_t buf, uint32 row, tsample_t sample)
+{
+  static const char module[] = "TIFFWriteScanline";
+  register TIFFDirectory *td;
+  int status, imagegrew = 0;
+  tstrip_t strip;
+
+  if (!WRITECHECKSTRIPS(tif, module))
+    return (-1);
+  /*
+   * Handle delayed allocation of data buffer.  This
+   * permits it to be sized more intelligently (using
+   * directory information).
+   */
+  if (!BUFFERCHECK(tif))
+    return (-1);
+  td = &tif->tif_dir;
+  /*
+   * Extend image length if needed
+   * (but only for PlanarConfig=1).
+   */
+  if (row >= td->td_imagelength) {  /* extend image */
+    if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
+      TIFFError(tif->tif_name,
+    "Can not change \"ImageLength\" when using separate planes");
+      return (-1);
+    }
+    td->td_imagelength = row+1;
+    imagegrew = 1;
+  }
+  /*
+   * Calculate strip and check for crossings.
+   */
+  if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
+    if (sample >= td->td_samplesperpixel) {
+      TIFFError(tif->tif_name,
+          "%d: Sample out of range, max %d",
+          sample, td->td_samplesperpixel);
+      return (-1);
+    }
+    strip = sample*td->td_stripsperimage + row/td->td_rowsperstrip;
+  } else
+    strip = row / td->td_rowsperstrip;
+  if (strip != tif->tif_curstrip) {
+    /*
+     * Changing strips -- flush any data present.
+     */
+    if (!TIFFFlushData(tif))
+      return (-1);
+    tif->tif_curstrip = strip;
+    /*
+     * Watch out for a growing image.  The value of
+     * strips/image will initially be 1 (since it
+     * can't be deduced until the imagelength is known).
+     */
+    if (strip >= td->td_stripsperimage && imagegrew)
+      td->td_stripsperimage =
+          TIFFhowmany(td->td_imagelength,td->td_rowsperstrip);
+    tif->tif_row =
+        (strip % td->td_stripsperimage) * td->td_rowsperstrip;
+    if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
+      if (!(*tif->tif_setupencode)(tif))
+        return (-1);
+      tif->tif_flags |= TIFF_CODERSETUP;
+    }
+        
+    tif->tif_rawcc = 0;
+    tif->tif_rawcp = tif->tif_rawdata;
+
+    if( td->td_stripbytecount[strip] > 0 )
+    {
+      /* if we are writing over existing tiles, zero length */
+      td->td_stripbytecount[strip] = 0;
+
+      /* this forces TIFFAppendToStrip() to do a seek */
+      tif->tif_curoff = 0;
+    }
+
+    if (!(*tif->tif_preencode)(tif, sample))
+      return (-1);
+    tif->tif_flags |= TIFF_POSTENCODE;
+  }
+  /*
+   * Check strip array to make sure there's space.
+   * We don't support dynamically growing files that
+   * have data organized in separate bitplanes because
+   * it's too painful.  In that case we require that
+   * the imagelength be set properly before the first
+   * write (so that the strips array will be fully
+   * allocated above).
+   */
+  if (strip >= td->td_nstrips && !TIFFGrowStrips(tif, 1, module))
+    return (-1);
+  /*
+   * Ensure the write is either sequential or at the
+   * beginning of a strip (or that we can randomly
+   * access the data -- i.e. no encoding).
+   */
+  if (row != tif->tif_row) {
+    if (row < tif->tif_row) {
+      /*
+       * Moving backwards within the same strip:
+       * backup to the start and then decode
+       * forward (below).
+       */
+      tif->tif_row = (strip % td->td_stripsperimage) *
+          td->td_rowsperstrip;
+      tif->tif_rawcp = tif->tif_rawdata;
+    }
+    /*
+     * Seek forward to the desired row.
+     */
+    if (!(*tif->tif_seek)(tif, row - tif->tif_row))
+      return (-1);
+    tif->tif_row = row;
+  }
+
+        /* swab if needed - note that source buffer will be altered */
+        tif->tif_postdecode( tif, (tidata_t) buf, tif->tif_scanlinesize );
+
+  status = (*tif->tif_encoderow)(tif, (tidata_t) buf,
+      tif->tif_scanlinesize, sample);
+
+        /* we are now poised at the beginning of the next row */
+  tif->tif_row = row + 1;
+  return (status);
+}
+
+/*
+ * Encode the supplied data and write it to the
+ * specified strip.
+ *
+ * NB: Image length must be setup before writing.
+ */
+tsize_t
+TIFFWriteEncodedStrip(TIFF* tif, tstrip_t strip, tdata_t data, tsize_t cc)
+{
+  static const char module[] = "TIFFWriteEncodedStrip";
+  TIFFDirectory *td = &tif->tif_dir;
+  tsample_t sample;
+
+  if (!WRITECHECKSTRIPS(tif, module))
+    return ((tsize_t) -1);
+  /*
+   * Check strip array to make sure there's space.
+   * We don't support dynamically growing files that
+   * have data organized in separate bitplanes because
+   * it's too painful.  In that case we require that
+   * the imagelength be set properly before the first
+   * write (so that the strips array will be fully
+   * allocated above).
+   */
+  if (strip >= td->td_nstrips) {
+    if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
+      TIFFError(tif->tif_name,
+    "Can not grow image by strips when using separate planes");
+      return ((tsize_t) -1);
+    }
+    if (!TIFFGrowStrips(tif, 1, module))
+      return ((tsize_t) -1);
+    td->td_stripsperimage =
+        TIFFhowmany(td->td_imagelength, td->td_rowsperstrip);
+  }
+  /*
+   * Handle delayed allocation of data buffer.  This
+   * permits it to be sized according to the directory
+   * info.
+   */
+  if (!BUFFERCHECK(tif))
+    return ((tsize_t) -1);
+  tif->tif_curstrip = strip;
+  tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
+  if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
+    if (!(*tif->tif_setupencode)(tif))
+      return ((tsize_t) -1);
+    tif->tif_flags |= TIFF_CODERSETUP;
+  }
+        
+  tif->tif_rawcc = 0;
+  tif->tif_rawcp = tif->tif_rawdata;
+
+        if( td->td_stripbytecount[strip] > 0 )
+        {
+            /* if we are writing over existing tiles, zero length. */
+            td->td_stripbytecount[strip] = 0;
+
+            /* this forces TIFFAppendToStrip() to do a seek */
+            tif->tif_curoff = 0;
+        }
+        
+  tif->tif_flags &= ~TIFF_POSTENCODE;
+  sample = (tsample_t)(strip / td->td_stripsperimage);
+  if (!(*tif->tif_preencode)(tif, sample))
+    return ((tsize_t) -1);
+
+        /* swab if needed - note that source buffer will be altered */
+        tif->tif_postdecode( tif, (tidata_t) data, cc );
+
+  if (!(*tif->tif_encodestrip)(tif, (tidata_t) data, cc, sample))
+    return ((tsize_t) 0);
+  if (!(*tif->tif_postencode)(tif))
+    return ((tsize_t) -1);
+  if (!isFillOrder(tif, td->td_fillorder) &&
+      (tif->tif_flags & TIFF_NOBITREV) == 0)
+    TIFFReverseBits(tif->tif_rawdata, tif->tif_rawcc);
+  if (tif->tif_rawcc > 0 &&
+      !TIFFAppendToStrip(tif, strip, tif->tif_rawdata, tif->tif_rawcc))
+    return ((tsize_t) -1);
+  tif->tif_rawcc = 0;
+  tif->tif_rawcp = tif->tif_rawdata;
+  return (cc);
+}
+
+/*
+ * Write the supplied data to the specified strip.
+ *
+ * NB: Image length must be setup before writing.
+ */
+tsize_t
+TIFFWriteRawStrip(TIFF* tif, tstrip_t strip, tdata_t data, tsize_t cc)
+{
+  static const char module[] = "TIFFWriteRawStrip";
+  TIFFDirectory *td = &tif->tif_dir;
+
+  if (!WRITECHECKSTRIPS(tif, module))
+    return ((tsize_t) -1);
+  /*
+   * Check strip array to make sure there's space.
+   * We don't support dynamically growing files that
+   * have data organized in separate bitplanes because
+   * it's too painful.  In that case we require that
+   * the imagelength be set properly before the first
+   * write (so that the strips array will be fully
+   * allocated above).
+   */
+  if (strip >= td->td_nstrips) {
+    if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
+      TIFFError(tif->tif_name,
+    "Can not grow image by strips when using separate planes");
+      return ((tsize_t) -1);
+    }
+    /*
+     * Watch out for a growing image.  The value of
+     * strips/image will initially be 1 (since it
+     * can't be deduced until the imagelength is known).
+     */
+    if (strip >= td->td_stripsperimage)
+      td->td_stripsperimage =
+          TIFFhowmany(td->td_imagelength,td->td_rowsperstrip);
+    if (!TIFFGrowStrips(tif, 1, module))
+      return ((tsize_t) -1);
+  }
+  tif->tif_curstrip = strip;
+  tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
+  return (TIFFAppendToStrip(tif, strip, (tidata_t) data, cc) ?
+      cc : (tsize_t) -1);
+}
+
+/*
+ * Write and compress a tile of data.  The
+ * tile is selected by the (x,y,z,s) coordinates.
+ */
+tsize_t
+TIFFWriteTile(TIFF* tif,
+    tdata_t buf, uint32 x, uint32 y, uint32 z, tsample_t s)
+{
+  if (!TIFFCheckTile(tif, x, y, z, s))
+    return (-1);
+  /*
+   * NB: A tile size of -1 is used instead of tif_tilesize knowing
+   *     that TIFFWriteEncodedTile will clamp this to the tile size.
+   *     This is done because the tile size may not be defined until
+   *     after the output buffer is setup in TIFFWriteBufferSetup.
+   */
+  return (TIFFWriteEncodedTile(tif,
+      TIFFComputeTile(tif, x, y, z, s), buf, (tsize_t) -1));
+}
+
+/*
+ * Encode the supplied data and write it to the
+ * specified tile.  There must be space for the
+ * data.  The function clamps individual writes
+ * to a tile to the tile size, but does not (and
+ * can not) check that multiple writes to the same
+ * tile do not write more than tile size data.
+ *
+ * NB: Image length must be setup before writing; this
+ *     interface does not support automatically growing
+ *     the image on each write (as TIFFWriteScanline does).
+ */
+tsize_t
+TIFFWriteEncodedTile(TIFF* tif, ttile_t tile, tdata_t data, tsize_t cc)
+{
+  static const char module[] = "TIFFWriteEncodedTile";
+  TIFFDirectory *td;
+  tsample_t sample;
+
+  if (!WRITECHECKTILES(tif, module))
+    return ((tsize_t) -1);
+  td = &tif->tif_dir;
+  if (tile >= td->td_nstrips) {
+    TIFFError(module, "%s: Tile %lu out of range, max %lu",
+        tif->tif_name, (unsigned long) tile, (unsigned long) td->td_nstrips);
+    return ((tsize_t) -1);
+  }
+  /*
+   * Handle delayed allocation of data buffer.  This
+   * permits it to be sized more intelligently (using
+   * directory information).
+   */
+  if (!BUFFERCHECK(tif))
+    return ((tsize_t) -1);
+  tif->tif_curtile = tile;
+
+  tif->tif_rawcc = 0;
+  tif->tif_rawcp = tif->tif_rawdata;
+
+        if( td->td_stripbytecount[tile] > 0 )
+        {
+            /* if we are writing over existing tiles, zero length. */
+            td->td_stripbytecount[tile] = 0;
+
+            /* this forces TIFFAppendToStrip() to do a seek */
+            tif->tif_curoff = 0;
+        }
+        
+  /* 
+   * Compute tiles per row & per column to compute
+   * current row and column
+   */
+  tif->tif_row = (tile % TIFFhowmany(td->td_imagelength, td->td_tilelength))
+    * td->td_tilelength;
+  tif->tif_col = (tile % TIFFhowmany(td->td_imagewidth, td->td_tilewidth))
+    * td->td_tilewidth;
+
+  if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
+    if (!(*tif->tif_setupencode)(tif))
+      return ((tsize_t) -1);
+    tif->tif_flags |= TIFF_CODERSETUP;
+  }
+  tif->tif_flags &= ~TIFF_POSTENCODE;
+  sample = (tsample_t)(tile/td->td_stripsperimage);
+  if (!(*tif->tif_preencode)(tif, sample))
+    return ((tsize_t) -1);
+  /*
+   * Clamp write amount to the tile size.  This is mostly
+   * done so that callers can pass in some large number
+   * (e.g. -1) and have the tile size used instead.
+   */
+  if ( cc < 1 || cc > tif->tif_tilesize)
+    cc = tif->tif_tilesize;
+
+        /* swab if needed - note that source buffer will be altered */
+        tif->tif_postdecode( tif, (tidata_t) data, cc );
+
+  if (!(*tif->tif_encodetile)(tif, (tidata_t) data, cc, sample))
+    return ((tsize_t) 0);
+  if (!(*tif->tif_postencode)(tif))
+    return ((tsize_t) -1);
+  if (!isFillOrder(tif, td->td_fillorder) &&
+      (tif->tif_flags & TIFF_NOBITREV) == 0)
+    TIFFReverseBits((unsigned char *)tif->tif_rawdata, tif->tif_rawcc);
+  if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, tile,
+      tif->tif_rawdata, tif->tif_rawcc))
+    return ((tsize_t) -1);
+  tif->tif_rawcc = 0;
+  tif->tif_rawcp = tif->tif_rawdata;
+  return (cc);
+}
+
+/*
+ * Write the supplied data to the specified strip.
+ * There must be space for the data; we don't check
+ * if strips overlap!
+ *
+ * NB: Image length must be setup before writing; this
+ *     interface does not support automatically growing
+ *     the image on each write (as TIFFWriteScanline does).
+ */
+tsize_t
+TIFFWriteRawTile(TIFF* tif, ttile_t tile, tdata_t data, tsize_t cc)
+{
+  static const char module[] = "TIFFWriteRawTile";
+
+  if (!WRITECHECKTILES(tif, module))
+    return ((tsize_t) -1);
+  if (tile >= tif->tif_dir.td_nstrips) {
+    TIFFError(module, "%s: Tile %lu out of range, max %lu",
+        tif->tif_name, (unsigned long) tile,
+        (unsigned long) tif->tif_dir.td_nstrips);
+    return ((tsize_t) -1);
+  }
+  return (TIFFAppendToStrip(tif, tile, (tidata_t) data, cc) ?
+      cc : (tsize_t) -1);
+}
+
+#define  isUnspecified(tif, f) \
+    (TIFFFieldSet(tif,f) && (tif)->tif_dir.td_imagelength == 0)
+
+int
+TIFFSetupStrips(TIFF* tif)
+{
+  TIFFDirectory* td = &tif->tif_dir;
+
+  if (isTiled(tif))
+    td->td_stripsperimage =
+        isUnspecified(tif, FIELD_TILEDIMENSIONS) ?
+      td->td_samplesperpixel : TIFFNumberOfTiles(tif);
+  else
+    td->td_stripsperimage =
+        isUnspecified(tif, FIELD_ROWSPERSTRIP) ?
+      td->td_samplesperpixel : TIFFNumberOfStrips(tif);
+  td->td_nstrips = td->td_stripsperimage;
+  if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
+    td->td_stripsperimage /= td->td_samplesperpixel;
+  td->td_stripoffset = (uint32 *)
+      _TIFFmalloc(td->td_nstrips * sizeof (uint32));
+  td->td_stripbytecount = (uint32 *)
+      _TIFFmalloc(td->td_nstrips * sizeof (uint32));
+  if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL)
+    return (0);
+  /*
+   * Place data at the end-of-file
+   * (by setting offsets to zero).
+   */
+  _TIFFmemset(td->td_stripoffset, 0, td->td_nstrips*sizeof (uint32));
+  _TIFFmemset(td->td_stripbytecount, 0, td->td_nstrips*sizeof (uint32));
+  TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
+  TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
+  return (1);
+}
+#undef isUnspecified
+
+/*
+ * Verify file is writable and that the directory
+ * information is setup properly.  In doing the latter
+ * we also "freeze" the state of the directory so
+ * that important information is not changed.
+ */
+int
+TIFFWriteCheck(TIFF* tif, int tiles, const char* module)
+{
+  if (tif->tif_mode == O_RDONLY) {
+    TIFFError(module, "%s: File not open for writing",
+        tif->tif_name);
+    return (0);
+  }
+  if (tiles ^ isTiled(tif)) {
+    TIFFError(tif->tif_name, tiles ?
+        "Can not write tiles to a stripped image" :
+        "Can not write scanlines to a tiled image");
+    return (0);
+  }
+        
+  /*
+   * On the first write verify all the required information
+   * has been setup and initialize any data structures that
+   * had to wait until directory information was set.
+   * Note that a lot of our work is assumed to remain valid
+   * because we disallow any of the important parameters
+   * from changing after we start writing (i.e. once
+   * TIFF_BEENWRITING is set, TIFFSetField will only allow
+   * the image's length to be changed).
+   */
+  if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) {
+    TIFFError(module,
+        "%s: Must set \"ImageWidth\" before writing data",
+        tif->tif_name);
+    return (0);
+  }
+  if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) {
+    TIFFError(module,
+      "%s: Must set \"PlanarConfiguration\" before writing data",
+        tif->tif_name);
+    return (0);
+  }
+  if (tif->tif_dir.td_stripoffset == NULL && !TIFFSetupStrips(tif)) {
+    tif->tif_dir.td_nstrips = 0;
+    TIFFError(module, "%s: No space for %s arrays",
+        tif->tif_name, isTiled(tif) ? "tile" : "strip");
+    return (0);
+  }
+  tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tsize_t) -1;
+  tif->tif_scanlinesize = TIFFScanlineSize(tif);
+  tif->tif_flags |= TIFF_BEENWRITING;
+  return (1);
+}
+
+/*
+ * Setup the raw data buffer used for encoding.
+ */
+int
+TIFFWriteBufferSetup(TIFF* tif, tdata_t bp, tsize_t size)
+{
+  static const char module[] = "TIFFWriteBufferSetup";
+
+  if (tif->tif_rawdata) {
+    if (tif->tif_flags & TIFF_MYBUFFER) {
+      _TIFFfree(tif->tif_rawdata);
+      tif->tif_flags &= ~TIFF_MYBUFFER;
+    }
+    tif->tif_rawdata = NULL;
+  }
+  if (size == (tsize_t) -1) {
+    size = (isTiled(tif) ?
+        tif->tif_tilesize : TIFFStripSize(tif));
+    /*
+     * Make raw data buffer at least 8K
+     */
+    if (size < 8*1024)
+      size = 8*1024;
+    bp = NULL;      /* NB: force malloc */
+  }
+  if (bp == NULL) {
+    bp = _TIFFmalloc(size);
+    if (bp == NULL) {
+      TIFFError(module, "%s: No space for output buffer",
+          tif->tif_name);
+      return (0);
+    }
+    tif->tif_flags |= TIFF_MYBUFFER;
+  } else
+    tif->tif_flags &= ~TIFF_MYBUFFER;
+  tif->tif_rawdata = (tidata_t) bp;
+  tif->tif_rawdatasize = size;
+  tif->tif_rawcc = 0;
+  tif->tif_rawcp = tif->tif_rawdata;
+  tif->tif_flags |= TIFF_BUFFERSETUP;
+  return (1);
+}
+
+/*
+ * Grow the strip data structures by delta strips.
+ */
+static int
+TIFFGrowStrips(TIFF* tif, int delta, const char* module)
+{
+  TIFFDirectory  *td = &tif->tif_dir;
+  uint32    *new_stripoffset, *new_stripbytecount;
+
+  assert(td->td_planarconfig == PLANARCONFIG_CONTIG);
+  new_stripoffset = (uint32*)_TIFFrealloc(td->td_stripoffset,
+    (td->td_nstrips + delta) * sizeof (uint32));
+  new_stripbytecount = (uint32*)_TIFFrealloc(td->td_stripbytecount,
+    (td->td_nstrips + delta) * sizeof (uint32));
+  if (new_stripoffset == NULL || new_stripbytecount == NULL) {
+    if (new_stripoffset)
+      _TIFFfree(new_stripoffset);
+    if (new_stripbytecount)
+      _TIFFfree(new_stripbytecount);
+    td->td_nstrips = 0;
+    TIFFError(module, "%s: No space to expand strip arrays",
+        tif->tif_name);
+    return (0);
+  }
+  td->td_stripoffset = new_stripoffset;
+  td->td_stripbytecount = new_stripbytecount;
+  _TIFFmemset(td->td_stripoffset + td->td_nstrips,
+        0, delta*sizeof (uint32));
+  _TIFFmemset(td->td_stripbytecount + td->td_nstrips,
+        0, delta*sizeof (uint32));
+  td->td_nstrips += delta;
+  return (1);
+}
+
+/*
+ * Append the data to the specified strip.
+ */
+static int
+TIFFAppendToStrip(TIFF* tif, tstrip_t strip, tidata_t data, tsize_t cc)
+{
+  TIFFDirectory *td = &tif->tif_dir;
+  static const char module[] = "TIFFAppendToStrip";
+
+  if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) {
+    /*
+     * No current offset, set the current strip.
+     */
+    assert(td->td_nstrips > 0);
+    if (td->td_stripoffset[strip] != 0) {
+      /*
+       * Prevent overlapping of the data chunks. We need
+                         * this to enable in place updating of the compressed
+                         * images. Larger blocks will be moved at the end of
+                         * the file without any optimization of the spare
+                         * space, so such scheme is not too much effective.
+       */
+      if (td->td_stripbytecountsorted) {
+        if (strip == td->td_nstrips - 1
+            || td->td_stripoffset[strip + 1] <
+          td->td_stripoffset[strip] + cc) {
+          td->td_stripoffset[strip] =
+            TIFFSeekFile(tif, (toff_t)0,
+                   SEEK_END);
+        }
+      } else {
+        tstrip_t i;
+        for (i = 0; i < td->td_nstrips; i++) {
+          if (td->td_stripoffset[i] > 
+            td->td_stripoffset[strip]
+              && td->td_stripoffset[i] <
+            td->td_stripoffset[strip] + cc) {
+            td->td_stripoffset[strip] =
+              TIFFSeekFile(tif,
+                     (toff_t)0,
+                     SEEK_END);
+          }
+        }
+      }
+
+      if (!SeekOK(tif, td->td_stripoffset[strip])) {
+        TIFFError(module,
+            "%s: Seek error at scanline %lu",
+            tif->tif_name,
+            (unsigned long)tif->tif_row);
+        return (0);
+      }
+    } else
+      td->td_stripoffset[strip] =
+          TIFFSeekFile(tif, (toff_t) 0, SEEK_END);
+    tif->tif_curoff = td->td_stripoffset[strip];
+  }
+
+  if (!WriteOK(tif, data, cc)) {
+    TIFFError(module, "%s: Write error at scanline %lu",
+        tif->tif_name, (unsigned long) tif->tif_row);
+    return (0);
+  }
+  tif->tif_curoff += cc;
+  td->td_stripbytecount[strip] += cc;
+  return (1);
+}
+
+/*
+ * Internal version of TIFFFlushData that can be
+ * called by ``encodestrip routines'' w/o concern
+ * for infinite recursion.
+ */
+int
+TIFFFlushData1(TIFF* tif)
+{
+  if (tif->tif_rawcc > 0) {
+    if (!isFillOrder(tif, tif->tif_dir.td_fillorder) &&
+        (tif->tif_flags & TIFF_NOBITREV) == 0)
+      TIFFReverseBits((unsigned char *)tif->tif_rawdata,
+          tif->tif_rawcc);
+    if (!TIFFAppendToStrip(tif,
+        isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip,
+        tif->tif_rawdata, tif->tif_rawcc))
+      return (0);
+    tif->tif_rawcc = 0;
+    tif->tif_rawcp = tif->tif_rawdata;
+  }
+  return (1);
+}
+
+/*
+ * Set the current write offset.  This should only be
+ * used to set the offset to a known previous location
+ * (very carefully), or to 0 so that the next write gets
+ * appended to the end of the file.
+ */
+void
+TIFFSetWriteOffset(TIFF* tif, toff_t off)
+{
+  tif->tif_curoff = off;
+}
+
diff --git a/Utilities/ITK/Utilities/tiff/tif_zip.c b/Utilities/ITK/Utilities/tiff/tif_zip.c
new file mode 100644
index 0000000000..eafe6c0032
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tif_zip.c
@@ -0,0 +1,368 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1995-1997 Sam Leffler
+ * Copyright (c) 1995-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+#include "tiffiop.h"
+#ifdef ZIP_SUPPORT
+/*
+ * TIFF Library.
+ *
+ * ZIP (aka Deflate) Compression Support
+ *
+ * This file is simply an interface to the zlib library written by
+ * Jean-loup Gailly and Mark Adler.  You must use version 1.0 or later
+ * of the library: this code assumes the 1.0 API and also depends on
+ * the ability to write the zlib header multiple times (one per strip)
+ * which was not possible with versions prior to 0.95.  Note also that
+ * older versions of this codec avoided this bug by supressing the header
+ * entirely.  This means that files written with the old library cannot
+ * be read; they should be converted to a different compression scheme
+ * and then reconverted.
+ *
+ * The data format used by the zlib library is described in the files
+ * zlib-3.1.doc, deflate-1.1.doc and gzip-4.1.doc, available in the
+ * directory ftp://ftp.uu.net/pub/archiving/zip/doc.  The library was
+ * last found at ftp://ftp.uu.net/pub/archiving/zip/zlib/zlib-0.99.tar.gz.
+ */
+#include "tif_predict.h"
+#include "zlib.h"
+
+#include <stdio.h>
+
+/*
+ * Sigh, ZLIB_VERSION is defined as a string so there's no
+ * way to do a proper check here.  Instead we guess based
+ * on the presence of #defines that were added between the
+ * 0.95 and 1.0 distributions.
+ */
+#if !defined(Z_NO_COMPRESSION) || !defined(Z_DEFLATED)
+#error "Antiquated ZLIB software; you must use version 1.0 or later"
+#endif
+
+/*
+ * State block for each open TIFF
+ * file using ZIP compression/decompression.
+ */
+typedef  struct {
+  TIFFPredictorState predict;
+  z_stream  stream;
+  int    zipquality;    /* compression level */
+  int    state;      /* state flags */
+#define  ZSTATE_INIT  0x1    /* zlib setup successfully */
+
+  TIFFVGetMethod  vgetparent;    /* super-class method */
+  TIFFVSetMethod  vsetparent;    /* super-class method */
+} ZIPState;
+
+#define  ZState(tif)    ((ZIPState*) (tif)->tif_data)
+#define  DecoderState(tif)  ZState(tif)
+#define  EncoderState(tif)  ZState(tif)
+
+static  int ZIPEncode(TIFF*, tidata_t, tsize_t, tsample_t);
+static  int ZIPDecode(TIFF*, tidata_t, tsize_t, tsample_t);
+
+static int
+ZIPSetupDecode(TIFF* tif)
+{
+  ZIPState* sp = DecoderState(tif);
+  static const char module[] = "ZIPSetupDecode";
+
+  assert(sp != NULL);
+  if (inflateInit(&sp->stream) != Z_OK) {
+    TIFFError(module, "%s: %s", tif->tif_name, sp->stream.msg);
+    return (0);
+  } else {
+    sp->state |= ZSTATE_INIT;
+    return (1);
+  }
+}
+
+/*
+ * Setup state for decoding a strip.
+ */
+static int
+ZIPPreDecode(TIFF* tif, tsample_t s)
+{
+  ZIPState* sp = DecoderState(tif);
+
+  (void) s;
+  assert(sp != NULL);
+  sp->stream.next_in = tif->tif_rawdata;
+  sp->stream.avail_in = tif->tif_rawcc;
+  return (inflateReset(&sp->stream) == Z_OK);
+}
+
+static int
+ZIPDecode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s)
+{
+  ZIPState* sp = DecoderState(tif);
+  static const char module[] = "ZIPDecode";
+
+  (void) s;
+  assert(sp != NULL);
+  sp->stream.next_out = op;
+  sp->stream.avail_out = occ;
+  do {
+    int state = inflate(&sp->stream, Z_PARTIAL_FLUSH);
+    if (state == Z_STREAM_END)
+      break;
+    if (state == Z_DATA_ERROR) {
+      TIFFError(module,
+          "%s: Decoding error at scanline %d, %s",
+          tif->tif_name, tif->tif_row, sp->stream.msg);
+      if (inflateSync(&sp->stream) != Z_OK)
+        return (0);
+      continue;
+    }
+    if (state != Z_OK) {
+      TIFFError(module, "%s: zlib error: %s",
+          tif->tif_name, sp->stream.msg);
+      return (0);
+    }
+  } while (sp->stream.avail_out > 0);
+  if (sp->stream.avail_out != 0) {
+    TIFFError(module,
+        "%s: Not enough data at scanline %d (short %d bytes)",
+        tif->tif_name, tif->tif_row, sp->stream.avail_out);
+    return (0);
+  }
+  return (1);
+}
+
+static int
+ZIPSetupEncode(TIFF* tif)
+{
+  ZIPState* sp = EncoderState(tif);
+  static const char module[] = "ZIPSetupEncode";
+
+  assert(sp != NULL);
+  if (deflateInit(&sp->stream, sp->zipquality) != Z_OK) {
+    TIFFError(module, "%s: %s", tif->tif_name, sp->stream.msg);
+    return (0);
+  } else {
+    sp->state |= ZSTATE_INIT;
+    return (1);
+  }
+}
+
+/*
+ * Reset encoding state at the start of a strip.
+ */
+static int
+ZIPPreEncode(TIFF* tif, tsample_t s)
+{
+  ZIPState *sp = EncoderState(tif);
+
+  (void) s;
+  assert(sp != NULL);
+  sp->stream.next_out = tif->tif_rawdata;
+  sp->stream.avail_out = tif->tif_rawdatasize;
+  return (deflateReset(&sp->stream) == Z_OK);
+}
+
+/*
+ * Encode a chunk of pixels.
+ */
+static int
+ZIPEncode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
+{
+  ZIPState *sp = EncoderState(tif);
+  static const char module[] = "ZIPEncode";
+
+  (void) s;
+  sp->stream.next_in = bp;
+  sp->stream.avail_in = cc;
+  do {
+    if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) {
+      TIFFError(module, "%s: Encoder error: %s",
+          tif->tif_name, sp->stream.msg);
+      return (0);
+    }
+    if (sp->stream.avail_out == 0) {
+      tif->tif_rawcc = tif->tif_rawdatasize;
+      TIFFFlushData1(tif);
+      sp->stream.next_out = tif->tif_rawdata;
+      sp->stream.avail_out = tif->tif_rawdatasize;
+    }
+  } while (sp->stream.avail_in > 0);
+  return (1);
+}
+
+/*
+ * Finish off an encoded strip by flushing the last
+ * string and tacking on an End Of Information code.
+ */
+static int
+ZIPPostEncode(TIFF* tif)
+{
+  ZIPState *sp = EncoderState(tif);
+  static const char module[] = "ZIPPostEncode";
+  int state;
+
+  sp->stream.avail_in = 0;
+  do {
+    state = deflate(&sp->stream, Z_FINISH);
+    switch (state) {
+    case Z_STREAM_END:
+    case Z_OK:
+        if ((int)sp->stream.avail_out != (int)tif->tif_rawdatasize)
+                    {
+          tif->tif_rawcc =
+        tif->tif_rawdatasize - sp->stream.avail_out;
+          TIFFFlushData1(tif);
+          sp->stream.next_out = tif->tif_rawdata;
+          sp->stream.avail_out = tif->tif_rawdatasize;
+        }
+        break;
+    default:
+        TIFFError(module, "%s: zlib error: %s",
+      tif->tif_name, sp->stream.msg);
+        return (0);
+    }
+  } while (state != Z_STREAM_END);
+  return (1);
+}
+
+static void
+ZIPCleanup(TIFF* tif)
+{
+  ZIPState* sp = ZState(tif);
+  if (sp) {
+    if (sp->state&ZSTATE_INIT) {
+      /* NB: avoid problems in the library */
+      if (tif->tif_mode == O_RDONLY)
+        inflateEnd(&sp->stream);
+      else
+        deflateEnd(&sp->stream);
+    }
+    _TIFFfree(sp);
+    tif->tif_data = NULL;
+  }
+}
+
+static int
+ZIPVSetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+  ZIPState* sp = ZState(tif);
+  static const char module[] = "ZIPVSetField";
+
+  switch (tag) {
+  case TIFFTAG_ZIPQUALITY:
+    sp->zipquality = va_arg(ap, int);
+    if (tif->tif_mode != O_RDONLY && (sp->state&ZSTATE_INIT)) {
+      if (deflateParams(&sp->stream,
+          sp->zipquality, Z_DEFAULT_STRATEGY) != Z_OK) {
+        TIFFError(module, "%s: zlib error: %s",
+            tif->tif_name, sp->stream.msg);
+        return (0);
+      }
+    }
+    return (1);
+  default:
+    return (*sp->vsetparent)(tif, tag, ap);
+  }
+  /*NOTREACHED*/
+}
+
+static int
+ZIPVGetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+  ZIPState* sp = ZState(tif);
+
+  switch (tag) {
+  case TIFFTAG_ZIPQUALITY:
+    *va_arg(ap, int*) = sp->zipquality;
+    break;
+  default:
+    return (*sp->vgetparent)(tif, tag, ap);
+  }
+  return (1);
+}
+
+static const TIFFFieldInfo zipFieldInfo[] = {
+    { TIFFTAG_ZIPQUALITY,   0, 0,  TIFF_ANY,  FIELD_PSEUDO,
+      TRUE,  FALSE,  "" },
+};
+#define  N(a)  (sizeof (a) / sizeof (a[0]))
+
+int
+TIFFInitZIP(TIFF* tif, int scheme)
+{
+  ZIPState* sp;
+
+  assert( (scheme == COMPRESSION_DEFLATE) || (scheme == COMPRESSION_ADOBE_DEFLATE));
+
+  /*
+   * Allocate state block so tag methods have storage to record values.
+   */
+  tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (ZIPState));
+  if (tif->tif_data == NULL)
+    goto bad;
+  sp = ZState(tif);
+  sp->stream.zalloc = NULL;
+  sp->stream.zfree = NULL;
+  sp->stream.opaque = NULL;
+  sp->stream.data_type = Z_BINARY;
+
+  /*
+   * Merge codec-specific tag information and
+   * override parent get/set field methods.
+   */
+  _TIFFMergeFieldInfo(tif, zipFieldInfo, N(zipFieldInfo));
+  sp->vgetparent = tif->tif_tagmethods.vgetfield;
+  tif->tif_tagmethods.vgetfield = ZIPVGetField;  /* hook for codec tags */
+  sp->vsetparent = tif->tif_tagmethods.vsetfield;
+  tif->tif_tagmethods.vsetfield = ZIPVSetField;  /* hook for codec tags */
+
+  /* Default values for codec-specific fields */
+  sp->zipquality = Z_DEFAULT_COMPRESSION;  /* default comp. level */
+  sp->state = 0;
+
+  /*
+   * Install codec methods.
+   */
+  tif->tif_setupdecode = ZIPSetupDecode;
+  tif->tif_predecode = ZIPPreDecode;
+  tif->tif_decoderow = ZIPDecode;
+  tif->tif_decodestrip = ZIPDecode;
+  tif->tif_decodetile = ZIPDecode;
+  tif->tif_setupencode = ZIPSetupEncode;
+  tif->tif_preencode = ZIPPreEncode;
+  tif->tif_postencode = ZIPPostEncode;
+  tif->tif_encoderow = ZIPEncode;
+  tif->tif_encodestrip = ZIPEncode;
+  tif->tif_encodetile = ZIPEncode;
+  tif->tif_cleanup = ZIPCleanup;
+  /*
+   * Setup predictor setup.
+   */
+  (void) TIFFPredictorInit(tif);
+  return (1);
+bad:
+  TIFFError("TIFFInitZIP", "No space for ZIP state block");
+  return (0);
+}
+#endif /* ZIP_SUPORT */
+
diff --git a/Utilities/ITK/Utilities/tiff/tiff.h b/Utilities/ITK/Utilities/tiff/tiff.h
new file mode 100644
index 0000000000..7554238b78
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tiff.h
@@ -0,0 +1,568 @@
+#include  "itk_tiff_mangle.h"
+/* $Id$ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _TIFF_
+#define  _TIFF_
+/*
+ * Tag Image File Format (TIFF)
+ *
+ * Based on Rev 6.0 from:
+ *    Developer's Desk
+ *    Aldus Corporation
+ *    411 First Ave. South
+ *    Suite 200
+ *    Seattle, WA  98104
+ *    206-622-5500
+ *    
+ *    (http://partners.adobe.com/asn/developer/PDFS/TN/TIFF6.pdf)
+ *
+ * For Big TIFF design notes see the following link
+ *    http://gdal.maptools.org/twiki/bin/view/libtiff/BigTIFFDesign
+ */
+#define  TIFF_VERSION          42
+#define TIFF_BIGTIFF_VERSION    43
+
+#define  TIFF_BIGENDIAN    0x4d4d
+#define  TIFF_LITTLEENDIAN  0x4949
+
+/*
+ * The so called TIFF types conflict with definitions from inttypes.h 
+ * included from sys/types.h on AIX (at least using VisualAge compiler). 
+ * We try to work around this by detecting this case.  Defining 
+ * _TIFF_DATA_TYPEDEFS_ short circuits the later definitions in tiff.h, and
+ * we will in the holes not provided for by inttypes.h. 
+ *
+ * See http://bugzilla.remotesensing.org/show_bug.cgi?id=39
+ */
+#if defined(_H_INTTYPES) && defined(_ALL_SOURCE) && defined(USING_VISUALAGE)
+
+#define _TIFF_DATA_TYPEDEFS_
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+typedef unsigned int uint32;
+
+#endif
+
+/*
+ * Intrinsic data types required by the file format:
+ *
+ * 8-bit quantities  int8/uint8
+ * 16-bit quantities  int16/uint16
+ * 32-bit quantities  int32/uint32
+ * strings    unsigned char*
+ */
+#ifndef _TIFF_DATA_TYPEDEFS_
+#define _TIFF_DATA_TYPEDEFS_
+
+typedef  signed char int8;  /* NB: non-ANSI compilers may not grok */
+typedef  unsigned char uint8;
+typedef  short int16;
+typedef  unsigned short uint16;  /* sizeof (uint16) must == 2 */
+#if defined(__alpha) || (defined(_MIPS_SZLONG) && _MIPS_SZLONG == 64) || defined(__LP64__) || defined(__arch64__)
+typedef  int int32;
+typedef  unsigned int uint32;  /* sizeof (uint32) must == 4 */
+#else
+typedef  long int32;
+typedef  unsigned long uint32;  /* sizeof (uint32) must == 4 */
+#endif
+
+#endif /* _TIFF_DATA_TYPEDEFS_ */
+
+/* For TIFFReassignTagToIgnore */
+enum TIFFIgnoreSense /* IGNORE tag table */
+{
+  TIS_STORE,
+  TIS_EXTRACT,
+  TIS_EMPTY
+};
+
+/*
+ * TIFF header.
+ */
+typedef  struct {
+  uint16  tiff_magic;  /* magic number (defines byte order) */
+#define TIFF_MAGIC_SIZE    2
+  uint16  tiff_version;  /* TIFF version number */
+#define TIFF_VERSION_SIZE  2
+  uint32  tiff_diroff;  /* byte offset to first directory */
+#define TIFF_DIROFFSET_SIZE  4
+} TIFFHeader;
+
+
+/*
+ * TIFF Image File Directories are comprised of a table of field
+ * descriptors of the form shown below.  The table is sorted in
+ * ascending order by tag.  The values associated with each entry are
+ * disjoint and may appear anywhere in the file (so long as they are
+ * placed on a word boundary).
+ *
+ * If the value is 4 bytes or less, then it is placed in the offset
+ * field to save space.  If the value is less than 4 bytes, it is
+ * left-justified in the offset field.
+ */
+typedef  struct {
+  uint16    tdir_tag;  /* see below */
+  uint16    tdir_type;  /* data type; see below */
+  uint32    tdir_count;  /* number of items; length in spec */
+  uint32    tdir_offset;  /* byte offset to field data */
+} TIFFDirEntry;
+
+/*
+ * NB: In the comments below,
+ *  - items marked with a + are obsoleted by revision 5.0,
+ *  - items marked with a ! are introduced in revision 6.0.
+ *  - items marked with a % are introduced post revision 6.0.
+ *  - items marked with a $ are obsoleted by revision 6.0.
+ *  - items marked with a & are introduced by Adobe DNG specification.
+ */
+
+/*
+ * Tag data type information.
+ *
+ * Note: RATIONALs are the ratio of two 32-bit integer values.
+ */
+typedef  enum {
+  TIFF_NOTYPE  = 0,  /* placeholder */
+  TIFF_BYTE  = 1,  /* 8-bit unsigned integer */
+  TIFF_ASCII  = 2,  /* 8-bit bytes w/ last byte null */
+  TIFF_SHORT  = 3,  /* 16-bit unsigned integer */
+  TIFF_LONG  = 4,  /* 32-bit unsigned integer */
+  TIFF_RATIONAL  = 5,  /* 64-bit unsigned fraction */
+  TIFF_SBYTE  = 6,  /* !8-bit signed integer */
+  TIFF_UNDEFINED  = 7,  /* !8-bit untyped data */
+  TIFF_SSHORT  = 8,  /* !16-bit signed integer */
+  TIFF_SLONG  = 9,  /* !32-bit signed integer */
+  TIFF_SRATIONAL  = 10,  /* !64-bit signed fraction */
+  TIFF_FLOAT  = 11,  /* !32-bit IEEE floating point */
+  TIFF_DOUBLE  = 12,  /* !64-bit IEEE floating point */
+  TIFF_IFD  = 13  /* %32-bit unsigned integer (offset) */
+} TIFFDataType;
+
+/*
+ * TIFF Tag Definitions.
+ */
+#define  TIFFTAG_SUBFILETYPE    254  /* subfile data descriptor */
+#define      FILETYPE_REDUCEDIMAGE  0x1  /* reduced resolution version */
+#define      FILETYPE_PAGE    0x2  /* one page of many */
+#define      FILETYPE_MASK    0x4  /* transparency mask */
+#define  TIFFTAG_OSUBFILETYPE    255  /* +kind of data in subfile */
+#define      OFILETYPE_IMAGE    1  /* full resolution image data */
+#define      OFILETYPE_REDUCEDIMAGE  2  /* reduced size image data */
+#define      OFILETYPE_PAGE    3  /* one page of many */
+#define  TIFFTAG_IMAGEWIDTH    256  /* image width in pixels */
+#define  TIFFTAG_IMAGELENGTH    257  /* image height in pixels */
+#define  TIFFTAG_BITSPERSAMPLE    258  /* bits per channel (sample) */
+#define  TIFFTAG_COMPRESSION    259  /* data compression technique */
+#define      COMPRESSION_NONE    1  /* dump mode */
+#define      COMPRESSION_CCITTRLE  2  /* CCITT modified Huffman RLE */
+#define      COMPRESSION_CCITTFAX3  3  /* CCITT Group 3 fax encoding */
+#define     COMPRESSION_CCITT_T4        3       /* CCITT T.4 (TIFF 6 name) */
+#define      COMPRESSION_CCITTFAX4  4  /* CCITT Group 4 fax encoding */
+#define     COMPRESSION_CCITT_T6        4       /* CCITT T.6 (TIFF 6 name) */
+#define      COMPRESSION_LZW    5       /* Lempel-Ziv  & Welch */
+#define      COMPRESSION_OJPEG    6  /* !6.0 JPEG */
+#define      COMPRESSION_JPEG    7  /* %JPEG DCT compression */
+#define      COMPRESSION_NEXT    32766  /* NeXT 2-bit RLE */
+#define      COMPRESSION_CCITTRLEW  32771  /* #1 w/ word alignment */
+#define      COMPRESSION_PACKBITS  32773  /* Macintosh RLE */
+#define      COMPRESSION_THUNDERSCAN  32809  /* ThunderScan RLE */
+/* codes 32895-32898 are reserved for ANSI IT8 TIFF/IT <dkelly@apago.com) */
+#define      COMPRESSION_IT8CTPAD  32895   /* IT8 CT w/padding */
+#define      COMPRESSION_IT8LW    32896   /* IT8 Linework RLE */
+#define      COMPRESSION_IT8MP    32897   /* IT8 Monochrome picture */
+#define      COMPRESSION_IT8BL    32898   /* IT8 Binary line art */
+/* compression codes 32908-32911 are reserved for Pixar */
+#define     COMPRESSION_PIXARFILM  32908   /* Pixar companded 10bit LZW */
+#define      COMPRESSION_PIXARLOG  32909   /* Pixar companded 11bit ZIP */
+#define      COMPRESSION_DEFLATE    32946  /* Deflate compression */
+#define     COMPRESSION_ADOBE_DEFLATE   8       /* Deflate compression,
+               as recognized by Adobe */
+/* compression code 32947 is reserved for Oceana Matrix <dev@oceana.com> */
+#define     COMPRESSION_DCS             32947   /* Kodak DCS encoding */
+#define      COMPRESSION_JBIG    34661  /* ISO JBIG */
+#define     COMPRESSION_SGILOG    34676  /* SGI Log Luminance RLE */
+#define     COMPRESSION_SGILOG24  34677  /* SGI Log 24-bit packed */
+#define     COMPRESSION_JP2000          34712   /* Leadtools JPEG2000 */
+#define  TIFFTAG_PHOTOMETRIC    262  /* photometric interpretation */
+#define      PHOTOMETRIC_MINISWHITE  0  /* min value is white */
+#define      PHOTOMETRIC_MINISBLACK  1  /* min value is black */
+#define      PHOTOMETRIC_RGB    2  /* RGB color model */
+#define      PHOTOMETRIC_PALETTE    3  /* color map indexed */
+#define      PHOTOMETRIC_MASK    4  /* $holdout mask */
+#define      PHOTOMETRIC_SEPARATED  5  /* !color separations */
+#define      PHOTOMETRIC_YCBCR    6  /* !CCIR 601 */
+#define      PHOTOMETRIC_CIELAB    8  /* !1976 CIE L*a*b* */
+#define      PHOTOMETRIC_ICCLAB    9  /* ICC L*a*b* [Adobe TIFF Technote 4] */
+#define      PHOTOMETRIC_ITULAB    10  /* ITU L*a*b* */
+#define     PHOTOMETRIC_LOGL    32844  /* CIE Log2(L) */
+#define     PHOTOMETRIC_LOGLUV    32845  /* CIE Log2(L) (u',v') */
+#define  TIFFTAG_THRESHHOLDING    263  /* +thresholding used on data */
+#define      THRESHHOLD_BILEVEL    1  /* b&w art scan */
+#define      THRESHHOLD_HALFTONE    2  /* or dithered scan */
+#define      THRESHHOLD_ERRORDIFFUSE  3  /* usually floyd-steinberg */
+#define  TIFFTAG_CELLWIDTH    264  /* +dithering matrix width */
+#define  TIFFTAG_CELLLENGTH    265  /* +dithering matrix height */
+#define  TIFFTAG_FILLORDER    266  /* data order within a byte */
+#define      FILLORDER_MSB2LSB    1  /* most significant -> least */
+#define      FILLORDER_LSB2MSB    2  /* least significant -> most */
+#define  TIFFTAG_DOCUMENTNAME    269  /* name of doc. image is from */
+#define  TIFFTAG_IMAGEDESCRIPTION  270  /* info about image */
+#define  TIFFTAG_MAKE      271  /* scanner manufacturer name */
+#define  TIFFTAG_MODEL      272  /* scanner model name/number */
+#define  TIFFTAG_STRIPOFFSETS    273  /* offsets to data strips */
+#define  TIFFTAG_ORIENTATION    274  /* +image orientation */
+#define      ORIENTATION_TOPLEFT    1  /* row 0 top, col 0 lhs */
+#define      ORIENTATION_TOPRIGHT  2  /* row 0 top, col 0 rhs */
+#define      ORIENTATION_BOTRIGHT  3  /* row 0 bottom, col 0 rhs */
+#define      ORIENTATION_BOTLEFT    4  /* row 0 bottom, col 0 lhs */
+#define      ORIENTATION_LEFTTOP    5  /* row 0 lhs, col 0 top */
+#define      ORIENTATION_RIGHTTOP  6  /* row 0 rhs, col 0 top */
+#define      ORIENTATION_RIGHTBOT  7  /* row 0 rhs, col 0 bottom */
+#define      ORIENTATION_LEFTBOT    8  /* row 0 lhs, col 0 bottom */
+#define  TIFFTAG_SAMPLESPERPIXEL    277  /* samples per pixel */
+#define  TIFFTAG_ROWSPERSTRIP    278  /* rows per strip of data */
+#define  TIFFTAG_STRIPBYTECOUNTS    279  /* bytes counts for strips */
+#define  TIFFTAG_MINSAMPLEVALUE    280  /* +minimum sample value */
+#define  TIFFTAG_MAXSAMPLEVALUE    281  /* +maximum sample value */
+#define  TIFFTAG_XRESOLUTION    282  /* pixels/resolution in x */
+#define  TIFFTAG_YRESOLUTION    283  /* pixels/resolution in y */
+#define  TIFFTAG_PLANARCONFIG    284  /* storage organization */
+#define      PLANARCONFIG_CONTIG    1  /* single image plane */
+#define      PLANARCONFIG_SEPARATE  2  /* separate planes of data */
+#define  TIFFTAG_PAGENAME    285  /* page name image is from */
+#define  TIFFTAG_XPOSITION    286  /* x page offset of image lhs */
+#define  TIFFTAG_YPOSITION    287  /* y page offset of image lhs */
+#define  TIFFTAG_FREEOFFSETS    288  /* +byte offset to free block */
+#define  TIFFTAG_FREEBYTECOUNTS    289  /* +sizes of free blocks */
+#define  TIFFTAG_GRAYRESPONSEUNIT  290  /* $gray scale curve accuracy */
+#define      GRAYRESPONSEUNIT_10S  1  /* tenths of a unit */
+#define      GRAYRESPONSEUNIT_100S  2  /* hundredths of a unit */
+#define      GRAYRESPONSEUNIT_1000S  3  /* thousandths of a unit */
+#define      GRAYRESPONSEUNIT_10000S  4  /* ten-thousandths of a unit */
+#define      GRAYRESPONSEUNIT_100000S  5  /* hundred-thousandths */
+#define  TIFFTAG_GRAYRESPONSECURVE  291  /* $gray scale response curve */
+#define  TIFFTAG_GROUP3OPTIONS    292  /* 32 flag bits */
+#define  TIFFTAG_T4OPTIONS    292  /* TIFF 6.0 proper name alias */
+#define      GROUP3OPT_2DENCODING  0x1  /* 2-dimensional coding */
+#define      GROUP3OPT_UNCOMPRESSED  0x2  /* data not compressed */
+#define      GROUP3OPT_FILLBITS    0x4  /* fill to byte boundary */
+#define  TIFFTAG_GROUP4OPTIONS    293  /* 32 flag bits */
+#define TIFFTAG_T6OPTIONS               293     /* TIFF 6.0 proper name */
+#define      GROUP4OPT_UNCOMPRESSED  0x2  /* data not compressed */
+#define  TIFFTAG_RESOLUTIONUNIT    296  /* units of resolutions */
+#define      RESUNIT_NONE    1  /* no meaningful units */
+#define      RESUNIT_INCH    2  /* english */
+#define      RESUNIT_CENTIMETER    3  /* metric */
+#define  TIFFTAG_PAGENUMBER    297  /* page numbers of multi-page */
+#define  TIFFTAG_COLORRESPONSEUNIT  300  /* $color curve accuracy */
+#define      COLORRESPONSEUNIT_10S  1  /* tenths of a unit */
+#define      COLORRESPONSEUNIT_100S  2  /* hundredths of a unit */
+#define      COLORRESPONSEUNIT_1000S  3  /* thousandths of a unit */
+#define      COLORRESPONSEUNIT_10000S  4  /* ten-thousandths of a unit */
+#define      COLORRESPONSEUNIT_100000S  5  /* hundred-thousandths */
+#define  TIFFTAG_TRANSFERFUNCTION  301  /* !colorimetry info */
+#define  TIFFTAG_SOFTWARE    305  /* name & release */
+#define  TIFFTAG_DATETIME    306  /* creation date and time */
+#define  TIFFTAG_ARTIST      315  /* creator of image */
+#define  TIFFTAG_HOSTCOMPUTER    316  /* machine where created */
+#define  TIFFTAG_PREDICTOR    317  /* prediction scheme w/ LZW */
+#define  TIFFTAG_WHITEPOINT    318  /* image white point */
+#define  TIFFTAG_PRIMARYCHROMATICITIES  319  /* !primary chromaticities */
+#define  TIFFTAG_COLORMAP    320  /* RGB map for pallette image */
+#define  TIFFTAG_HALFTONEHINTS    321  /* !highlight+shadow info */
+#define  TIFFTAG_TILEWIDTH    322  /* !tile width in pixels */
+#define  TIFFTAG_TILELENGTH    323  /* !tile height in pixels */
+#define TIFFTAG_TILEOFFSETS    324  /* !offsets to data tiles */
+#define TIFFTAG_TILEBYTECOUNTS    325  /* !byte counts for tiles */
+#define  TIFFTAG_BADFAXLINES    326  /* lines w/ wrong pixel count */
+#define  TIFFTAG_CLEANFAXDATA    327  /* regenerated line info */
+#define      CLEANFAXDATA_CLEAN    0  /* no errors detected */
+#define      CLEANFAXDATA_REGENERATED  1  /* receiver regenerated lines */
+#define      CLEANFAXDATA_UNCLEAN  2  /* uncorrected errors exist */
+#define  TIFFTAG_CONSECUTIVEBADFAXLINES  328  /* max consecutive bad lines */
+#define  TIFFTAG_SUBIFD      330  /* subimage descriptors */
+#define  TIFFTAG_INKSET      332  /* !inks in separated image */
+#define      INKSET_CMYK      1  /* !cyan-magenta-yellow-black color */
+#define      INKSET_MULTIINK    2  /* !multi-ink or hi-fi color */
+#define  TIFFTAG_INKNAMES    333  /* !ascii names of inks */
+#define  TIFFTAG_NUMBEROFINKS    334  /* !number of inks */
+#define  TIFFTAG_DOTRANGE    336  /* !0% and 100% dot codes */
+#define  TIFFTAG_TARGETPRINTER    337  /* !separation target */
+#define  TIFFTAG_EXTRASAMPLES    338  /* !info about extra samples */
+#define      EXTRASAMPLE_UNSPECIFIED  0  /* !unspecified data */
+#define      EXTRASAMPLE_ASSOCALPHA  1  /* !associated alpha data */
+#define      EXTRASAMPLE_UNASSALPHA  2  /* !unassociated alpha data */
+#define  TIFFTAG_SAMPLEFORMAT    339  /* !data sample format */
+#define      SAMPLEFORMAT_UINT    1  /* !unsigned integer data */
+#define      SAMPLEFORMAT_INT    2  /* !signed integer data */
+#define      SAMPLEFORMAT_IEEEFP    3  /* !IEEE floating point data */
+#define      SAMPLEFORMAT_VOID    4  /* !untyped data */
+#define      SAMPLEFORMAT_COMPLEXINT  5  /* !complex signed int */
+#define      SAMPLEFORMAT_COMPLEXIEEEFP  6  /* !complex ieee floating */
+#define  TIFFTAG_SMINSAMPLEVALUE    340  /* !variable MinSampleValue */
+#define  TIFFTAG_SMAXSAMPLEVALUE    341  /* !variable MaxSampleValue */
+#define  TIFFTAG_CLIPPATH    343  /* %ClipPath
+               [Adobe TIFF technote 2] */
+#define  TIFFTAG_XCLIPPATHUNITS    344  /* %XClipPathUnits
+               [Adobe TIFF technote 2] */
+#define  TIFFTAG_YCLIPPATHUNITS    345  /* %YClipPathUnits
+               [Adobe TIFF technote 2] */
+#define  TIFFTAG_INDEXED      346  /* %Indexed
+               [Adobe TIFF Technote 3] */
+#define  TIFFTAG_JPEGTABLES    347  /* %JPEG table stream */
+#define  TIFFTAG_OPIPROXY    351  /* %OPI Proxy [Adobe TIFF technote] */
+/*
+ * Tags 512-521 are obsoleted by Technical Note #2 which specifies a
+ * revised JPEG-in-TIFF scheme.
+ */
+#define  TIFFTAG_JPEGPROC    512  /* !JPEG processing algorithm */
+#define      JPEGPROC_BASELINE    1  /* !baseline sequential */
+#define      JPEGPROC_LOSSLESS    14  /* !Huffman coded lossless */
+#define  TIFFTAG_JPEGIFOFFSET    513  /* !pointer to SOI marker */
+#define  TIFFTAG_JPEGIFBYTECOUNT    514  /* !JFIF stream length */
+#define  TIFFTAG_JPEGRESTARTINTERVAL  515  /* !restart interval length */
+#define  TIFFTAG_JPEGLOSSLESSPREDICTORS  517  /* !lossless proc predictor */
+#define  TIFFTAG_JPEGPOINTTRANSFORM  518  /* !lossless point transform */
+#define  TIFFTAG_JPEGQTABLES    519  /* !Q matrice offsets */
+#define  TIFFTAG_JPEGDCTABLES    520  /* !DCT table offsets */
+#define  TIFFTAG_JPEGACTABLES    521  /* !AC coefficient offsets */
+#define  TIFFTAG_YCBCRCOEFFICIENTS  529  /* !RGB -> YCbCr transform */
+#define  TIFFTAG_YCBCRSUBSAMPLING  530  /* !YCbCr subsampling factors */
+#define  TIFFTAG_YCBCRPOSITIONING  531  /* !subsample positioning */
+#define      YCBCRPOSITION_CENTERED  1  /* !as in PostScript Level 2 */
+#define      YCBCRPOSITION_COSITED  2  /* !as in CCIR 601-1 */
+#define  TIFFTAG_REFERENCEBLACKWHITE  532  /* !colorimetry info */
+#define  TIFFTAG_XMLPACKET    700  /* %XML packet
+               [Adobe XMP Specification,
+               January 2004 */
+#define TIFFTAG_OPIIMAGEID    32781  /* %OPI ImageID
+               [Adobe TIFF technote] */
+/* tags 32952-32956 are private tags registered to Island Graphics */
+#define TIFFTAG_REFPTS      32953  /* image reference points */
+#define TIFFTAG_REGIONTACKPOINT    32954  /* region-xform tack point */
+#define TIFFTAG_REGIONWARPCORNERS  32955  /* warp quadrilateral */
+#define TIFFTAG_REGIONAFFINE    32956  /* affine transformation mat */
+/* tags 32995-32999 are private tags registered to SGI */
+#define  TIFFTAG_MATTEING    32995  /* $use ExtraSamples */
+#define  TIFFTAG_DATATYPE    32996  /* $use SampleFormat */
+#define  TIFFTAG_IMAGEDEPTH    32997  /* z depth of image */
+#define  TIFFTAG_TILEDEPTH    32998  /* z depth/data tile */
+/* tags 33300-33309 are private tags registered to Pixar */
+/*
+ * TIFFTAG_PIXAR_IMAGEFULLWIDTH and TIFFTAG_PIXAR_IMAGEFULLLENGTH
+ * are set when an image has been cropped out of a larger image.  
+ * They reflect the size of the original uncropped image.
+ * The TIFFTAG_XPOSITION and TIFFTAG_YPOSITION can be used
+ * to determine the position of the smaller image in the larger one.
+ */
+#define TIFFTAG_PIXAR_IMAGEFULLWIDTH    33300   /* full image size in x */
+#define TIFFTAG_PIXAR_IMAGEFULLLENGTH   33301   /* full image size in y */
+ /* Tags 33302-33306 are used to identify special image modes and data
+  * used by Pixar's texture formats.
+  */
+#define TIFFTAG_PIXAR_TEXTUREFORMAT  33302  /* texture map format */
+#define TIFFTAG_PIXAR_WRAPMODES    33303  /* s & t wrap modes */
+#define TIFFTAG_PIXAR_FOVCOT    33304  /* cotan(fov) for env. maps */
+#define TIFFTAG_PIXAR_MATRIX_WORLDTOSCREEN 33305
+#define TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA 33306
+/* tag 33405 is a private tag registered to Eastman Kodak */
+#define TIFFTAG_WRITERSERIALNUMBER      33405   /* device serial number */
+/* tag 33432 is listed in the 6.0 spec w/ unknown ownership */
+#define  TIFFTAG_COPYRIGHT    33432  /* copyright string */
+/* IPTC TAG from RichTIFF specifications */
+#define TIFFTAG_RICHTIFFIPTC    33723
+/* 34016-34029 are reserved for ANSI IT8 TIFF/IT <dkelly@apago.com) */
+#define TIFFTAG_IT8SITE      34016  /* site name */
+#define TIFFTAG_IT8COLORSEQUENCE  34017  /* color seq. [RGB,CMYK,etc] */
+#define TIFFTAG_IT8HEADER    34018  /* DDES Header */
+#define TIFFTAG_IT8RASTERPADDING  34019  /* raster scanline padding */
+#define TIFFTAG_IT8BITSPERRUNLENGTH  34020  /* # of bits in short run */
+#define TIFFTAG_IT8BITSPEREXTENDEDRUNLENGTH 34021/* # of bits in long run */
+#define TIFFTAG_IT8COLORTABLE    34022  /* LW colortable */
+#define TIFFTAG_IT8IMAGECOLORINDICATOR  34023  /* BP/BL image color switch */
+#define TIFFTAG_IT8BKGCOLORINDICATOR  34024  /* BP/BL bg color switch */
+#define TIFFTAG_IT8IMAGECOLORVALUE  34025  /* BP/BL image color value */
+#define TIFFTAG_IT8BKGCOLORVALUE  34026  /* BP/BL bg color value */
+#define TIFFTAG_IT8PIXELINTENSITYRANGE  34027  /* MP pixel intensity value */
+#define TIFFTAG_IT8TRANSPARENCYINDICATOR 34028  /* HC transparency switch */
+#define TIFFTAG_IT8COLORCHARACTERIZATION 34029  /* color character. table */
+#define TIFFTAG_IT8HCUSAGE    34030  /* HC usage indicator */
+#define TIFFTAG_IT8TRAPINDICATOR  34031  /* Trapping indicator
+               (untrapped=0, trapped=1) */
+#define TIFFTAG_IT8CMYKEQUIVALENT  34032  /* CMYK color equivalents */
+/* tags 34232-34236 are private tags registered to Texas Instruments */
+#define TIFFTAG_FRAMECOUNT              34232   /* Sequence Frame Count */
+/* tag 34750 is a private tag registered to Adobe? */
+#define TIFFTAG_ICCPROFILE    34675  /* ICC profile data */
+/* tag 34377 is private tag registered to Adobe for PhotoShop */
+#define TIFFTAG_PHOTOSHOP    34377 
+/* tag 34750 is a private tag registered to Pixel Magic */
+#define  TIFFTAG_JBIGOPTIONS    34750  /* JBIG options */
+/* tags 34908-34914 are private tags registered to SGI */
+#define  TIFFTAG_FAXRECVPARAMS    34908  /* encoded Class 2 ses. parms */
+#define  TIFFTAG_FAXSUBADDRESS    34909  /* received SubAddr string */
+#define  TIFFTAG_FAXRECVTIME    34910  /* receive time (secs) */
+#define  TIFFTAG_FAXDCS      34911  /* encoded fax ses. params, Table 2/T.30 */
+/* tags 37439-37443 are registered to SGI <gregl@sgi.com> */
+#define TIFFTAG_STONITS      37439  /* Sample value to Nits */
+/* tag 34929 is a private tag registered to FedEx */
+#define  TIFFTAG_FEDEX_EDR    34929  /* unknown use */
+/* tag 65535 is an undefined tag used by Eastman Kodak */
+#define TIFFTAG_DCSHUESHIFTVALUES       65535   /* hue shift correction data */
+/* Adobe Digital Negative format tags */
+#define TIFFTAG_DNGVERSION    50706  /* &DNG version number */
+#define TIFFTAG_DNGBACKWARDVERSION  50707  /* &DNG compatibility version */
+#define TIFFTAG_UNIQUECAMERAMODEL  50708  /* &name for the camera model */
+#define TIFFTAG_LOCALIZEDCAMERAMODEL  50709  /* &localized camera model
+               name */
+#define TIFFTAG_CFAPLANECOLOR    50710  /* &CFAPattern->LinearRaw space
+               mapping */
+#define TIFFTAG_CFALAYOUT    50711  /* &spatial layout of the CFA */
+#define TIFFTAG_LINEARIZATIONTABLE  50712  /* &lookup table description */
+#define TIFFTAG_BLACKLEVELREPEATDIM  50713  /* &repeat pattern size for
+               the BlackLevel tag */
+#define TIFFTAG_BLACKLEVEL    50714  /* &zero light encoding level */
+#define TIFFTAG_BLACKLEVELDELTAH  50715  /* &zero light encoding level
+               differences (columns) */
+#define TIFFTAG_BLACKLEVELDELTAV  50716  /* &zero light encoding level
+               differences (rows) */
+#define TIFFTAG_WHITELEVEL    50717  /* &fully saturated encoding
+               level */
+#define TIFFTAG_DEFAULTSCALE    50718  /* &default scale factors */
+#define TIFFTAG_DEFAULTCROPORIGIN  50719  /* &origin of the final image
+               area */
+#define TIFFTAG_DEFAULTCROPSIZE    50720  /* &size of the final image 
+               area */
+#define TIFFTAG_COLORMATRIX1    50721  /* &XYZ->reference color space
+               transformation matrix 1 */
+#define TIFFTAG_COLORMATRIX2    50722  /* &XYZ->reference color space
+               transformation matrix 2 */
+#define TIFFTAG_CAMERACALIBRATION1  50723  /* &calibration matrix 1 */
+#define TIFFTAG_CAMERACALIBRATION2  50724  /* &calibration matrix 2 */
+#define TIFFTAG_REDUCTIONMATRIX1  50725  /* &dimensionality reduction
+               matrix 1 */
+#define TIFFTAG_REDUCTIONMATRIX2  50726  /* &dimensionality reduction
+               matrix 2 */
+#define TIFFTAG_ANALOGBALANCE    50727  /* &gain applied the stored raw
+               values*/
+#define TIFFTAG_ASSHOTNEUTRAL    50728  /* &selected white balance in
+               linear reference space */
+#define TIFFTAG_ASSHOTWHITEXY    50729  /* &selected white balance in
+               x-y chromaticity
+               coordinates */
+#define TIFFTAG_BASELINEEXPOSURE  50730  /* &how much to move the zero
+               point */
+#define TIFFTAG_BASELINENOISE    50731  /* &relative noise level */
+#define TIFFTAG_BASELINESHARPNESS  50732  /* &relative amount of
+               sharpening */
+#define TIFFTAG_BAYERGREENSPLIT    50733  /* &how closely the values of
+               the green pixels in the
+               blue/green rows track the
+               values of the green pixels
+               in the red/green rows */
+#define TIFFTAG_LINEARRESPONSELIMIT  50734  /* &non-linear encoding range */
+#define TIFFTAG_CAMERASERIALNUMBER  50735  /* &camera's serial number */
+#define TIFFTAG_CHROMABLURRADIUS  50737  /* &chroma blur radius */
+#define TIFFTAG_ANTIALIASSTRENGTH  50738  /* &relative strength of the
+               camera's anti-alias filter */
+#define TIFFTAG_DNGPRIVATEDATA    50740  /* &manufacturer's private data */
+#define TIFFTAG_MAKERNOTESAFETY    50741  /* &whether the EXIF MakerNote
+               tag is safe to preserve
+               along with the rest of the
+               EXIF data */
+#define  TIFFTAG_CALIBRATIONILLUMINANT1  50778  /* &illuminant 1 */
+#define TIFFTAG_CALIBRATIONILLUMINANT2  50779  /* &illuminant 2 */
+#define TIFFTAG_BESTQUALITYSCALE  50780  /* &best quality multiplier */
+
+/*
+ * The following are ``pseudo tags'' that can be used to control
+ * codec-specific functionality.  These tags are not written to file.
+ * Note that these values start at 0xffff+1 so that they'll never
+ * collide with Aldus-assigned tags.
+ *
+ * If you want your private pseudo tags ``registered'' (i.e. added to
+ * this file), please post a bug report via the tracking system at
+ * http://www.remotesensing.org/libtiff/bugs.html with the appropriate
+ * C definitions to add.
+ */
+#define  TIFFTAG_FAXMODE      65536  /* Group 3/4 format control */
+#define      FAXMODE_CLASSIC  0x0000    /* default, include RTC */
+#define      FAXMODE_NORTC  0x0001    /* no RTC at end of data */
+#define      FAXMODE_NOEOL  0x0002    /* no EOL code at end of row */
+#define      FAXMODE_BYTEALIGN  0x0004    /* byte align row */
+#define      FAXMODE_WORDALIGN  0x0008    /* word align row */
+#define      FAXMODE_CLASSF  FAXMODE_NORTC  /* TIFF Class F */
+#define  TIFFTAG_JPEGQUALITY    65537  /* Compression quality level */
+/* Note: quality level is on the IJG 0-100 scale.  Default value is 75 */
+#define  TIFFTAG_JPEGCOLORMODE    65538  /* Auto RGB<=>YCbCr convert? */
+#define      JPEGCOLORMODE_RAW  0x0000    /* no conversion (default) */
+#define      JPEGCOLORMODE_RGB  0x0001    /* do auto conversion */
+#define  TIFFTAG_JPEGTABLESMODE    65539  /* What to put in JPEGTables */
+#define      JPEGTABLESMODE_QUANT 0x0001    /* include quantization tbls */
+#define      JPEGTABLESMODE_HUFF  0x0002    /* include Huffman tbls */
+/* Note: default is JPEGTABLESMODE_QUANT | JPEGTABLESMODE_HUFF */
+#define  TIFFTAG_FAXFILLFUNC    65540  /* G3/G4 fill function */
+#define  TIFFTAG_PIXARLOGDATAFMT    65549  /* PixarLogCodec I/O data sz */
+#define      PIXARLOGDATAFMT_8BIT  0  /* regular u_char samples */
+#define      PIXARLOGDATAFMT_8BITABGR  1  /* ABGR-order u_chars */
+#define      PIXARLOGDATAFMT_11BITLOG  2  /* 11-bit log-encoded (raw) */
+#define      PIXARLOGDATAFMT_12BITPICIO  3  /* as per PICIO (1.0==2048) */
+#define      PIXARLOGDATAFMT_16BIT  4  /* signed short samples */
+#define      PIXARLOGDATAFMT_FLOAT  5  /* IEEE float samples */
+/* 65550-65556 are allocated to Oceana Matrix <dev@oceana.com> */
+#define TIFFTAG_DCSIMAGERTYPE           65550   /* imager model & filter */
+#define     DCSIMAGERMODEL_M3           0       /* M3 chip (1280 x 1024) */
+#define     DCSIMAGERMODEL_M5           1       /* M5 chip (1536 x 1024) */
+#define     DCSIMAGERMODEL_M6           2       /* M6 chip (3072 x 2048) */
+#define     DCSIMAGERFILTER_IR          0       /* infrared filter */
+#define     DCSIMAGERFILTER_MONO        1       /* monochrome filter */
+#define     DCSIMAGERFILTER_CFA         2       /* color filter array */
+#define     DCSIMAGERFILTER_OTHER       3       /* other filter */
+#define TIFFTAG_DCSINTERPMODE           65551   /* interpolation mode */
+#define     DCSINTERPMODE_NORMAL        0x0     /* whole image, default */
+#define     DCSINTERPMODE_PREVIEW       0x1     /* preview of image (384x256) */
+#define TIFFTAG_DCSBALANCEARRAY         65552   /* color balance values */
+#define TIFFTAG_DCSCORRECTMATRIX        65553   /* color correction values */
+#define TIFFTAG_DCSGAMMA                65554   /* gamma value */
+#define TIFFTAG_DCSTOESHOULDERPTS       65555   /* toe & shoulder points */
+#define TIFFTAG_DCSCALIBRATIONFD        65556   /* calibration file desc */
+/* Note: quality level is on the ZLIB 1-9 scale. Default value is -1 */
+#define  TIFFTAG_ZIPQUALITY    65557  /* compression quality level */
+#define  TIFFTAG_PIXARLOGQUALITY    65558  /* PixarLog uses same scale */
+/* 65559 is allocated to Oceana Matrix <dev@oceana.com> */
+#define TIFFTAG_DCSCLIPRECTANGLE  65559  /* area of image to acquire */
+#define TIFFTAG_SGILOGDATAFMT    65560  /* SGILog user data format */
+#define     SGILOGDATAFMT_FLOAT    0  /* IEEE float samples */
+#define     SGILOGDATAFMT_16BIT    1  /* 16-bit samples */
+#define     SGILOGDATAFMT_RAW    2  /* uninterpreted data */
+#define     SGILOGDATAFMT_8BIT    3  /* 8-bit RGB monitor values */
+#define TIFFTAG_SGILOGENCODE    65561 /* SGILog data encoding control*/
+#define     SGILOGENCODE_NODITHER  0     /* do not dither encoded values*/
+#define     SGILOGENCODE_RANDITHER  1     /* randomly dither encd values */
+#endif /* _TIFF_ */
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Utilities/ITK/Utilities/tiff/tiffDllConfig.h.in b/Utilities/ITK/Utilities/tiff/tiffDllConfig.h.in
new file mode 100644
index 0000000000..fd80c1c999
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tiffDllConfig.h.in
@@ -0,0 +1,7 @@
+#ifndef _tiffDllConfig_h
+#define _tiffDllConfig_h
+
+#cmakedefine TIFFDLL
+#cmakedefine TIFFSTATIC
+
+#endif
diff --git a/Utilities/ITK/Utilities/tiff/tiffcomp.h b/Utilities/ITK/Utilities/tiff/tiffcomp.h
new file mode 100644
index 0000000000..a738e97c84
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tiffcomp.h
@@ -0,0 +1,214 @@
+/* $Header: /cvsroot/Insight/Insight/Utilities/tiff/tiffcomp.h,v 1.1 2003/11/25 14:10:11 jjomier Exp $ */
+
+/*
+ * Copyright (c) 1990-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _COMPAT_
+#define _COMPAT_
+/*
+ * This file contains a hodgepodge of definitions and
+ * declarations that are needed to provide compatibility
+ * between the native system and the base implementation
+ * that the library assumes.
+ *
+ * NB: This file is a mess.
+ */
+
+/*
+ * Setup basic type definitions and function declaratations.
+ */
+
+/*
+ * Simplify Acorn RISC OS identifier (to avoid confusion with Acorn RISC iX
+ * and with defunct Unix Risc OS)
+ * No need to specify __arm - hey, Acorn might port the OS, no problem here!
+ */
+#ifdef __acornriscos
+#undef __acornriscos
+#endif
+#if defined(__acorn) && defined(__riscos)
+#define __acornriscos
+#endif
+
+#if defined(__MWERKS__) || defined(THINK_C)
+#include <unix.h>
+#include <math.h>
+#endif
+
+#include <stdio.h>
+
+#if defined(__PPCC__) || defined(__SC__) || defined(__MRC__)
+#include <types.h>
+#elif !defined(__MWERKS__) && !defined(THINK_C) && !defined(__acornriscos) && !defined(applec)
+#include <sys/types.h>
+#endif
+
+#if defined(VMS)
+#include <file.h>
+#include <unixio.h>
+#elif !defined(__acornriscos)
+#include <fcntl.h>
+#endif
+
+/*
+ * This maze of checks controls defines or not the
+ * target system has BSD-style typdedefs declared in
+ * an include file and/or whether or not to include
+ * <unistd.h> to get the SEEK_* definitions.  Some
+ * additional includes are also done to pull in the
+ * appropriate definitions we're looking for.
+ */
+#if defined(__MWERKS__) || defined(THINK_C) || defined(__PPCC__) || defined(__SC__) || defined(__MRC__)
+#include <stdlib.h>
+#define BSDTYPES
+#define HAVE_UNISTD_H   0
+#elif (defined(_WINDOWS) || defined(__WIN32__) || defined(_Windows) || defined(_WIN32)) && !defined(unix)
+#define BSDTYPES
+#elif defined(OS2_16) || defined(OS2_32)
+#define BSDTYPES
+#elif defined(__acornriscos)
+#include <stdlib.h>
+#define BSDTYPES
+#define HAVE_UNISTD_H   0
+#elif defined(VMS)
+#define HAVE_UNISTD_H   0
+#else
+#define HAVE_UNISTD_H   1
+#endif
+
+/*
+ * The library uses the ANSI C/POSIX SEEK_*
+ * definitions that should be defined in unistd.h
+ * (except on system where they are in stdio.h and
+ * there is no unistd.h).
+ */
+#if !defined(SEEK_SET) && HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+/*
+ * The library uses memset, memcpy, and memcmp.
+ * ANSI C and System V define these in string.h.
+ */
+#include <string.h>
+
+/*
+ * The BSD typedefs are used throughout the library.
+ * If your system doesn't have them in <sys/types.h>,
+ * then define BSDTYPES in your Makefile.
+ */
+#if defined(BSDTYPES)
+typedef unsigned char u_char;
+typedef unsigned short u_short;
+typedef unsigned int u_int;
+typedef unsigned long u_long;
+#endif
+
+/*
+ * dblparam_t is the type that a double precision
+ * floating point value will have on the parameter
+ * stack (when coerced by the compiler).
+ */
+/* Note: on MacPowerPC "extended" is undefined. So only use it for 68K-Macs */
+#if defined(__SC__) || defined(THINK_C)
+typedef extended dblparam_t;
+#else
+typedef double dblparam_t;
+#endif
+
+/*
+ * If your compiler supports inline functions, then
+ * set INLINE appropriately to get the known hotspots
+ * in the library expanded inline.
+ */
+#if defined(__GNUC__)
+#if defined(__STRICT_ANSI__)
+#define INLINE  __inline__
+#else
+#define INLINE  inline
+#endif
+#else /* !__GNUC__ */
+#define INLINE
+#endif
+
+/*
+ * GLOBALDATA is a macro that is used to define global variables
+ * private to the library.  We use this indirection to hide
+ * brain-damage in VAXC (and GCC) under VAX/VMS.  In these
+ * environments the macro places the variable in a non-shareable
+ * program section, which ought to be done by default (sigh!)
+ *
+ * Apparently DEC are aware of the problem as this behaviour is the
+ * default under VMS on AXP.
+ *
+ * The GNU C variant is untested.
+ */
+#if defined(VAX) && defined(VMS)
+#if defined(VAXC)
+#define GLOBALDATA(TYPE,NAME)   extern noshare TYPE NAME
+#endif
+#if defined(__GNUC__)
+#define GLOBALDATA(TYPE,NAME)   extern TYPE NAME \
+        asm("_$$PsectAttributes_NOSHR$$" #NAME)
+#endif
+#else   /* !VAX/VMS */
+#define GLOBALDATA(TYPE,NAME)   extern TYPE NAME
+#endif
+
+#if defined(__acornriscos)
+/*
+ * osfcn.h is part of C++Lib on Acorn C/C++, and as such can't be used
+ * on C alone. For that reason, the relevant functions are
+ * implemented in tif_acorn.c, and the elements from the header
+ * file are included here.
+ */
+#if defined(__cplusplus)
+#include <osfcn.h>
+#else
+#define O_RDONLY        0
+#define O_WRONLY        1
+#define O_RDWR          2
+#define O_APPEND        8
+#define O_CREAT         0x200
+#define O_TRUNC         0x400
+typedef long off_t;
+extern int open(const char *name, int flags, int mode);
+extern int close(int fd);
+extern int write(int fd, const char *buf, int nbytes);
+extern int read(int fd, char *buf, int nbytes);
+extern off_t lseek(int fd, off_t offset, int whence);
+extern int creat(const char *path, int mode);
+#endif /* __cplusplus */
+#endif /* __acornriscos */
+
+/* Bit and byte order, the default is MSB to LSB */
+#ifdef VMS
+#undef HOST_FILLORDER
+#undef HOST_BIGENDIAN
+#define HOST_FILLORDER FILLORDER_LSB2MSB
+#define HOST_BIGENDIAN  0
+#endif
+
+
+#endif /* _COMPAT_ */
diff --git a/Utilities/ITK/Utilities/tiff/tiffconf.h b/Utilities/ITK/Utilities/tiff/tiffconf.h
new file mode 100644
index 0000000000..563a2da3f3
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tiffconf.h
@@ -0,0 +1,80 @@
+/* libtiff/tiffconf.h.  Generated by configure.  */
+/*
+  Configuration defines for installed libtiff.
+  Editing this file no longer has any effect on the libtiff build!
+*/
+
+#ifndef _TIFFCONF_
+#define _TIFFCONF_
+
+/* Define as 0 or 1 according to the floating point format suported by the
+   machine */
+#define HAVE_IEEEFP 1
+
+/* Set the native cpu bit order (FILLORDER_LSB2MSB or FILLORDER_MSB2LSB) */
+#define HOST_FILLORDER FILLORDER_LSB2MSB
+
+/* Native cpu byte order: 1 if big-endian (Motorola) or 0 if little-endian
+   (Intel) */
+#define HOST_BIGENDIAN 0
+
+/* Support CCITT Group 3 & 4 algorithms */
+#define CCITT_SUPPORT 1
+
+/* Support JPEG compression (requires IJG JPEG library) */
+#define JPEG_SUPPORT 1
+
+/* Support LogLuv high dynamic range encoding */
+#define LOGLUV_SUPPORT 1
+
+/* Support LZW algorithm */
+#define LZW_SUPPORT 1
+
+/* Support NeXT 2-bit RLE algorithm */
+#define NEXT_SUPPORT 1
+
+/* Support Old JPEG compresson (read contrib/ojpeg/README first! Compilation
+   fails with unpatched IJG JPEG library) */
+/* #undef OJPEG_SUPPORT */
+
+/* Support Macintosh PackBits algorithm */
+#define PACKBITS_SUPPORT 1
+
+/* Support Pixar log-format algorithm (requires Zlib) */
+#define PIXARLOG_SUPPORT 1
+
+/* Support ThunderScan 4-bit RLE algorithm */
+#define THUNDER_SUPPORT 1
+
+/* Support Deflate compression */
+#define ZIP_SUPPORT 1
+
+/* Support strip chopping (whether or not to convert single-strip uncompressed
+   images to mutiple strips of ~8Kb to reduce memory usage) */
+#define STRIPCHOP_DEFAULT TIFF_STRIPCHOP
+
+/* Enable SubIFD tag (330) support */
+#define SUBIFD_SUPPORT 1
+
+/* Treat extra sample as alpha (default enabled). The RGBA interface will
+   treat a fourth sample with no EXTRASAMPLE_ value as being ASSOCALPHA. Many
+   packages produce RGBA files but don't mark the alpha properly. */
+#define DEFAULT_EXTRASAMPLE_AS_ALPHA 1
+
+/* Pick up YCbCr subsampling info from the JPEG data stream to support files
+   lacking the tag (default enabled). */
+#define CHECK_JPEG_YCBCR_SUBSAMPLING 1
+
+/*
+ * Feature support definitions.
+ * XXX: These macros are obsoleted. Don't use them in your apps!
+ * Macros stays here for backward compatibility and should be always defined.
+ */
+#define COLORIMETRY_SUPPORT
+#define YCBCR_SUPPORT
+#define CMYK_SUPPORT
+#define ICC_SUPPORT
+#define PHOTOSHOP_SUPPORT
+#define IPTC_SUPPORT
+
+#endif /* _TIFFCONF_ */
diff --git a/Utilities/ITK/Utilities/tiff/tiffio.h b/Utilities/ITK/Utilities/tiff/tiffio.h
new file mode 100644
index 0000000000..4d151d1e3e
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tiffio.h
@@ -0,0 +1,501 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _TIFFIO_
+#define  _TIFFIO_
+
+/*
+ * TIFF I/O Library Definitions.
+ */
+#include "tiff.h"
+#include "tiffvers.h"
+
+/*
+ * TIFF is defined as an incomplete type to hide the
+ * library's internal data structures from clients.
+ */
+typedef  struct tiff TIFF;
+
+/*
+ * The following typedefs define the intrinsic size of
+ * data types used in the *exported* interfaces.  These
+ * definitions depend on the proper definition of types
+ * in tiff.h.  Note also that the varargs interface used
+ * to pass tag types and values uses the types defined in
+ * tiff.h directly.
+ *
+ * NB: ttag_t is unsigned int and not unsigned short because
+ *     ANSI C requires that the type before the ellipsis be a
+ *     promoted type (i.e. one of int, unsigned int, pointer,
+ *     or double) and because we defined pseudo-tags that are
+ *     outside the range of legal Aldus-assigned tags.
+ * NB: tsize_t is int32 and not uint32 because some functions
+ *     return -1.
+ * NB: toff_t is not off_t for many reasons; TIFFs max out at
+ *     32-bit file offsets being the most important, and to ensure
+ *     that it is unsigned, rather than signed.
+ */
+typedef  uint32 ttag_t;    /* directory tag */
+typedef  uint16 tdir_t;    /* directory index */
+typedef  uint16 tsample_t;  /* sample number */
+typedef  uint32 tstrip_t;  /* strip number */
+typedef uint32 ttile_t;    /* tile number */
+typedef  int32 tsize_t;    /* i/o size in bytes */
+typedef  void* tdata_t;    /* image data ref */
+typedef  uint32 toff_t;    /* file offset */
+
+#if !defined(__WIN32__) && (defined(_WIN32) || defined(WIN32))
+#define __WIN32__
+#endif
+
+/*
+ * On windows you should define USE_WIN32_FILEIO if you are using tif_win32.c
+ * or AVOID_WIN32_FILEIO if you are using something else (like tif_unix.c).
+ *
+ * By default tif_win32.c is assumed on windows if not using the cygwin
+ * environment.
+ */
+
+#if defined(_WINDOWS) || defined(__WIN32__) || defined(_Windows)
+#  if !defined(__CYGWIN) && !defined(AVOID_WIN32_FILEIO) && !defined(USE_WIN32_FILIO)
+#    define USE_WIN32_FILEIO
+#  endif
+#endif
+
+#if defined(USE_WIN32_FILEIO)
+# include <windows.h>
+# ifdef __WIN32__
+DECLARE_HANDLE(thandle_t);  /* Win32 file handle */
+# else
+typedef  HFILE thandle_t;  /* client data handle */
+# endif /* __WIN32__ */
+#else
+typedef  void* thandle_t;  /* client data handle */
+#endif /* USE_WIN32_FILEIO */
+
+#ifndef NULL
+# define NULL  (void *)0
+#endif
+
+/*
+ * Flags to pass to TIFFPrintDirectory to control
+ * printing of data structures that are potentially
+ * very large.   Bit-or these flags to enable printing
+ * multiple items.
+ */
+#define  TIFFPRINT_NONE    0x0    /* no extra info */
+#define  TIFFPRINT_STRIPS  0x1    /* strips/tiles info */
+#define  TIFFPRINT_CURVES  0x2    /* color/gray response curves */
+#define  TIFFPRINT_COLORMAP  0x4    /* colormap */
+#define  TIFFPRINT_JPEGQTABLES  0x100    /* JPEG Q matrices */
+#define  TIFFPRINT_JPEGACTABLES  0x200    /* JPEG AC tables */
+#define  TIFFPRINT_JPEGDCTABLES  0x200    /* JPEG DC tables */
+
+/* 
+ * Colour conversion stuff
+ */
+
+/* reference white */
+#define D65_X0 (95.0470F)
+#define D65_Y0 (100.0F)
+#define D65_Z0 (108.8827F)
+
+#define D50_X0 (96.4250F)
+#define D50_Y0 (100.0F)
+#define D50_Z0 (82.4680F)
+
+/* Structure for holding information about a display device. */
+
+typedef  unsigned char TIFFRGBValue;    /* 8-bit samples */
+
+typedef struct {
+  float d_mat[3][3];     /* XYZ -> luminance matrix */
+  float d_YCR;      /* Light o/p for reference white */
+  float d_YCG;
+  float d_YCB;
+  uint32 d_Vrwr;      /* Pixel values for ref. white */
+  uint32 d_Vrwg;
+  uint32 d_Vrwb;
+  float d_Y0R;      /* Residual light for black pixel */
+  float d_Y0G;
+  float d_Y0B;
+  float d_gammaR;      /* Gamma values for the three guns */
+  float d_gammaG;
+  float d_gammaB;
+} TIFFDisplay;
+
+typedef struct {        /* YCbCr->RGB support */
+  TIFFRGBValue* clamptab;      /* range clamping table */
+  int*  Cr_r_tab;
+  int*  Cb_b_tab;
+  int32*  Cr_g_tab;
+  int32*  Cb_g_tab;
+        int32*  Y_tab;
+} TIFFYCbCrToRGB;
+
+typedef struct {        /* CIE Lab 1976->RGB support */
+  int  range;        /* Size of conversion table */
+#define CIELABTORGB_TABLE_RANGE 1500
+  float  rstep, gstep, bstep;
+  float  X0, Y0, Z0;      /* Reference white point */
+  TIFFDisplay display;
+  float  Yr2r[CIELABTORGB_TABLE_RANGE + 1];  /* Conversion of Yr to r */
+  float  Yg2g[CIELABTORGB_TABLE_RANGE + 1];  /* Conversion of Yg to g */
+  float  Yb2b[CIELABTORGB_TABLE_RANGE + 1];  /* Conversion of Yb to b */
+} TIFFCIELabToRGB;
+
+/*
+ * RGBA-style image support.
+ */
+typedef struct _TIFFRGBAImage TIFFRGBAImage;
+/*
+ * The image reading and conversion routines invoke
+ * ``put routines'' to copy/image/whatever tiles of
+ * raw image data.  A default set of routines are 
+ * provided to convert/copy raw image data to 8-bit
+ * packed ABGR format rasters.  Applications can supply
+ * alternate routines that unpack the data into a
+ * different format or, for example, unpack the data
+ * and draw the unpacked raster on the display.
+ */
+typedef void (*tileContigRoutine)
+    (TIFFRGBAImage*, uint32*, uint32, uint32, uint32, uint32, int32, int32,
+  unsigned char*);
+typedef void (*tileSeparateRoutine)
+    (TIFFRGBAImage*, uint32*, uint32, uint32, uint32, uint32, int32, int32,
+  unsigned char*, unsigned char*, unsigned char*, unsigned char*);
+/*
+ * RGBA-reader state.
+ */
+struct _TIFFRGBAImage {
+  TIFF*  tif;        /* image handle */
+  int  stoponerr;      /* stop on read error */
+  int  isContig;      /* data is packed/separate */
+  int  alpha;        /* type of alpha data present */
+  uint32  width;        /* image width */
+  uint32  height;        /* image height */
+  uint16  bitspersample;      /* image bits/sample */
+  uint16  samplesperpixel;    /* image samples/pixel */
+  uint16  orientation;      /* image orientation */
+  uint16  req_orientation;    /* requested orientation */
+  uint16  photometric;      /* image photometric interp */
+  uint16*  redcmap;      /* colormap pallete */
+  uint16*  greencmap;
+  uint16*  bluecmap;
+            /* get image data routine */
+  int  (*get)(TIFFRGBAImage*, uint32*, uint32, uint32);
+  union {
+      void (*any)(TIFFRGBAImage*);
+      tileContigRoutine  contig;
+      tileSeparateRoutine  separate;
+  } put;          /* put decoded strip/tile */
+  TIFFRGBValue* Map;      /* sample mapping array */
+  uint32** BWmap;        /* black&white map */
+  uint32** PALmap;      /* palette image map */
+  TIFFYCbCrToRGB* ycbcr;      /* YCbCr conversion state */
+        TIFFCIELabToRGB* cielab;    /* CIE L*a*b conversion state */
+
+        int  row_offset;
+        int     col_offset;
+};
+
+/*
+ * Macros for extracting components from the
+ * packed ABGR form returned by TIFFReadRGBAImage.
+ */
+#define  TIFFGetR(abgr)  ((abgr) & 0xff)
+#define  TIFFGetG(abgr)  (((abgr) >> 8) & 0xff)
+#define  TIFFGetB(abgr)  (((abgr) >> 16) & 0xff)
+#define  TIFFGetA(abgr)  (((abgr) >> 24) & 0xff)
+
+/*
+ * A CODEC is a software package that implements decoding,
+ * encoding, or decoding+encoding of a compression algorithm.
+ * The library provides a collection of builtin codecs.
+ * More codecs may be registered through calls to the library
+ * and/or the builtin implementations may be overridden.
+ */
+typedef  int (*TIFFInitMethod)(TIFF*, int);
+typedef struct {
+  char*    name;
+  uint16    scheme;
+  TIFFInitMethod  init;
+} TIFFCodec;
+
+#include <stdio.h>
+#include <stdarg.h>
+
+/* share internal LogLuv conversion routines? */
+#ifndef LOGLUV_PUBLIC
+#define LOGLUV_PUBLIC    1  
+#endif
+
+#if defined(c_plusplus) || defined(__cplusplus)
+extern "C" {
+#endif
+typedef  void (*TIFFErrorHandler)(const char*, const char*, va_list);
+typedef  tsize_t (*TIFFReadWriteProc)(thandle_t, tdata_t, tsize_t);
+typedef  toff_t (*TIFFSeekProc)(thandle_t, toff_t, int);
+typedef  int (*TIFFCloseProc)(thandle_t);
+typedef  toff_t (*TIFFSizeProc)(thandle_t);
+typedef  int (*TIFFMapFileProc)(thandle_t, tdata_t*, toff_t*);
+typedef  void (*TIFFUnmapFileProc)(thandle_t, tdata_t, toff_t);
+typedef  void (*TIFFExtendProc)(TIFF*); 
+
+extern  const char* TIFFGetVersion(void);
+
+extern  const TIFFCodec* TIFFFindCODEC(uint16);
+extern  TIFFCodec* TIFFRegisterCODEC(uint16, const char*, TIFFInitMethod);
+extern  void TIFFUnRegisterCODEC(TIFFCodec*);
+extern  int TIFFIsCODECConfigured(uint16);
+extern  TIFFCodec* TIFFGetConfiguredCODECs();
+
+extern  tdata_t _TIFFmalloc(tsize_t);
+extern  tdata_t _TIFFrealloc(tdata_t, tsize_t);
+extern  void _TIFFmemset(tdata_t, int, tsize_t);
+extern  void _TIFFmemcpy(tdata_t, const tdata_t, tsize_t);
+extern  int _TIFFmemcmp(const tdata_t, const tdata_t, tsize_t);
+extern  void _TIFFfree(tdata_t);
+
+extern  void TIFFCleanup(TIFF*);
+extern  void TIFFClose(TIFF*);
+extern  int TIFFFlush(TIFF*);
+extern  int TIFFFlushData(TIFF*);
+extern  int TIFFGetField(TIFF*, ttag_t, ...);
+extern  int TIFFVGetField(TIFF*, ttag_t, va_list);
+extern  int TIFFGetFieldDefaulted(TIFF*, ttag_t, ...);
+extern  int TIFFVGetFieldDefaulted(TIFF*, ttag_t, va_list);
+extern  int TIFFReadDirectory(TIFF*);
+extern  tsize_t TIFFScanlineSize(TIFF*);
+extern  tsize_t TIFFRasterScanlineSize(TIFF*);
+extern  tsize_t TIFFStripSize(TIFF*);
+extern  tsize_t TIFFRawStripSize(TIFF*, tstrip_t);
+extern  tsize_t TIFFVStripSize(TIFF*, uint32);
+extern  tsize_t TIFFTileRowSize(TIFF*);
+extern  tsize_t TIFFTileSize(TIFF*);
+extern  tsize_t TIFFVTileSize(TIFF*, uint32);
+extern  uint32 TIFFDefaultStripSize(TIFF*, uint32);
+extern  void TIFFDefaultTileSize(TIFF*, uint32*, uint32*);
+extern  int TIFFFileno(TIFF*);
+extern  int TIFFSetFileno(TIFF*, int);
+extern  thandle_t TIFFClientdata(TIFF*);
+extern  thandle_t TIFFSetClientdata(TIFF*, thandle_t);
+extern  int TIFFGetMode(TIFF*);
+extern  int TIFFSetMode(TIFF*, int);
+extern  int TIFFIsTiled(TIFF*);
+extern  int TIFFIsByteSwapped(TIFF*);
+extern  int TIFFIsUpSampled(TIFF*);
+extern  int TIFFIsMSB2LSB(TIFF*);
+extern  int TIFFIsBigEndian(TIFF*);
+extern  TIFFReadWriteProc TIFFGetReadProc(TIFF*);
+extern  TIFFReadWriteProc TIFFGetWriteProc(TIFF*);
+extern  TIFFSeekProc TIFFGetSeekProc(TIFF*);
+extern  TIFFCloseProc TIFFGetCloseProc(TIFF*);
+extern  TIFFSizeProc TIFFGetSizeProc(TIFF*);
+extern  TIFFMapFileProc TIFFGetMapFileProc(TIFF*);
+extern  TIFFUnmapFileProc TIFFGetUnmapFileProc(TIFF*);
+extern  uint32 TIFFCurrentRow(TIFF*);
+extern  tdir_t TIFFCurrentDirectory(TIFF*);
+extern  tdir_t TIFFNumberOfDirectories(TIFF*);
+extern  uint32 TIFFCurrentDirOffset(TIFF*);
+extern  tstrip_t TIFFCurrentStrip(TIFF*);
+extern  ttile_t TIFFCurrentTile(TIFF*);
+extern  int TIFFReadBufferSetup(TIFF*, tdata_t, tsize_t);
+extern  int TIFFWriteBufferSetup(TIFF*, tdata_t, tsize_t);
+extern  int TIFFSetupStrips(TIFF *);
+extern  int TIFFWriteCheck(TIFF*, int, const char *);
+extern  int TIFFCreateDirectory(TIFF*);
+extern  int TIFFLastDirectory(TIFF*);
+extern  int TIFFSetDirectory(TIFF*, tdir_t);
+extern  int TIFFSetSubDirectory(TIFF*, uint32);
+extern  int TIFFUnlinkDirectory(TIFF*, tdir_t);
+extern  int TIFFSetField(TIFF*, ttag_t, ...);
+extern  int TIFFVSetField(TIFF*, ttag_t, va_list);
+extern  int TIFFWriteDirectory(TIFF *);
+extern  int TIFFCheckpointDirectory(TIFF *);
+extern  int TIFFRewriteDirectory(TIFF *);
+extern  int TIFFReassignTagToIgnore(enum TIFFIgnoreSense, int);
+
+#if defined(c_plusplus) || defined(__cplusplus)
+extern  void TIFFPrintDirectory(TIFF*, FILE*, long = 0);
+extern  int TIFFReadScanline(TIFF*, tdata_t, uint32, tsample_t = 0);
+extern  int TIFFWriteScanline(TIFF*, tdata_t, uint32, tsample_t = 0);
+extern  int TIFFReadRGBAImage(TIFF*, uint32, uint32, uint32*, int = 0);
+extern  int TIFFReadRGBAImageOriented(TIFF*, uint32, uint32, uint32*,
+              int = ORIENTATION_BOTLEFT, int = 0);
+#else
+extern  void TIFFPrintDirectory(TIFF*, FILE*, long);
+extern  int TIFFReadScanline(TIFF*, tdata_t, uint32, tsample_t);
+extern  int TIFFWriteScanline(TIFF*, tdata_t, uint32, tsample_t);
+extern  int TIFFReadRGBAImage(TIFF*, uint32, uint32, uint32*, int);
+extern  int TIFFReadRGBAImageOriented(TIFF*, uint32, uint32, uint32*, int, int);
+#endif
+
+extern  int TIFFReadRGBAStrip(TIFF*, tstrip_t, uint32 * );
+extern  int TIFFReadRGBATile(TIFF*, uint32, uint32, uint32 * );
+extern  int TIFFRGBAImageOK(TIFF*, char [1024]);
+extern  int TIFFRGBAImageBegin(TIFFRGBAImage*, TIFF*, int, char [1024]);
+extern  int TIFFRGBAImageGet(TIFFRGBAImage*, uint32*, uint32, uint32);
+extern  void TIFFRGBAImageEnd(TIFFRGBAImage*);
+extern  TIFF* TIFFOpen(const char*, const char*);
+# ifdef __WIN32__
+extern  TIFF* TIFFOpenW(const wchar_t*, const char*);
+# endif /* __WIN32__ */
+extern  TIFF* TIFFFdOpen(int, const char*, const char*);
+extern  TIFF* TIFFClientOpen(const char*, const char*,
+      thandle_t,
+      TIFFReadWriteProc, TIFFReadWriteProc,
+      TIFFSeekProc, TIFFCloseProc,
+      TIFFSizeProc,
+      TIFFMapFileProc, TIFFUnmapFileProc);
+extern  const char* TIFFFileName(TIFF*);
+extern const char* TIFFSetFileName(TIFF*, const char *);
+extern  void TIFFError(const char*, const char*, ...);
+extern  void TIFFWarning(const char*, const char*, ...);
+extern  TIFFErrorHandler TIFFSetErrorHandler(TIFFErrorHandler);
+extern  TIFFErrorHandler TIFFSetWarningHandler(TIFFErrorHandler);
+extern  TIFFExtendProc TIFFSetTagExtender(TIFFExtendProc);
+extern  ttile_t TIFFComputeTile(TIFF*, uint32, uint32, uint32, tsample_t);
+extern  int TIFFCheckTile(TIFF*, uint32, uint32, uint32, tsample_t);
+extern  ttile_t TIFFNumberOfTiles(TIFF*);
+extern  tsize_t TIFFReadTile(TIFF*,
+      tdata_t, uint32, uint32, uint32, tsample_t);
+extern  tsize_t TIFFWriteTile(TIFF*,
+      tdata_t, uint32, uint32, uint32, tsample_t);
+extern  tstrip_t TIFFComputeStrip(TIFF*, uint32, tsample_t);
+extern  tstrip_t TIFFNumberOfStrips(TIFF*);
+extern  tsize_t TIFFReadEncodedStrip(TIFF*, tstrip_t, tdata_t, tsize_t);
+extern  tsize_t TIFFReadRawStrip(TIFF*, tstrip_t, tdata_t, tsize_t);
+extern  tsize_t TIFFReadEncodedTile(TIFF*, ttile_t, tdata_t, tsize_t);
+extern  tsize_t TIFFReadRawTile(TIFF*, ttile_t, tdata_t, tsize_t);
+extern  tsize_t TIFFWriteEncodedStrip(TIFF*, tstrip_t, tdata_t, tsize_t);
+extern  tsize_t TIFFWriteRawStrip(TIFF*, tstrip_t, tdata_t, tsize_t);
+extern  tsize_t TIFFWriteEncodedTile(TIFF*, ttile_t, tdata_t, tsize_t);
+extern  tsize_t TIFFWriteRawTile(TIFF*, ttile_t, tdata_t, tsize_t);
+extern  int TIFFDataWidth(TIFFDataType);    /* table of tag datatype widths */
+extern  void TIFFSetWriteOffset(TIFF*, toff_t);
+extern  void TIFFSwabShort(uint16*);
+extern  void TIFFSwabLong(uint32*);
+extern  void TIFFSwabDouble(double*);
+extern  void TIFFSwabArrayOfShort(uint16*, unsigned long);
+extern  void TIFFSwabArrayOfLong(uint32*, unsigned long);
+extern  void TIFFSwabArrayOfDouble(double*, unsigned long);
+extern  void TIFFReverseBits(unsigned char *, unsigned long);
+extern  const unsigned char* TIFFGetBitRevTable(int);
+
+#ifdef LOGLUV_PUBLIC
+#define U_NEU    0.210526316
+#define V_NEU    0.473684211
+#define UVSCALE    410.
+extern  double LogL16toY(int);
+extern  double LogL10toY(int);
+extern  void XYZtoRGB24(float*, uint8*);
+extern  int uv_decode(double*, double*, int);
+extern  void LogLuv24toXYZ(uint32, float*);
+extern  void LogLuv32toXYZ(uint32, float*);
+#if defined(c_plusplus) || defined(__cplusplus)
+extern  int LogL16fromY(double, int = SGILOGENCODE_NODITHER);
+extern  int LogL10fromY(double, int = SGILOGENCODE_NODITHER);
+extern  int uv_encode(double, double, int = SGILOGENCODE_NODITHER);
+extern  uint32 LogLuv24fromXYZ(float*, int = SGILOGENCODE_NODITHER);
+extern  uint32 LogLuv32fromXYZ(float*, int = SGILOGENCODE_NODITHER);
+#else
+extern  int LogL16fromY(double, int);
+extern  int LogL10fromY(double, int);
+extern  int uv_encode(double, double, int);
+extern  uint32 LogLuv24fromXYZ(float*, int);
+extern  uint32 LogLuv32fromXYZ(float*, int);
+#endif
+#endif /* LOGLUV_PUBLIC */
+
+/*
+** Stuff, related to tag handling and creating custom tags.
+*/
+extern  int  TIFFGetTagListCount( TIFF * );
+extern  ttag_t TIFFGetTagListEntry( TIFF *, int tag_index );
+    
+#define  TIFF_ANY  TIFF_NOTYPE  /* for field descriptor searching */
+#define  TIFF_VARIABLE  -1    /* marker for variable length tags */
+#define  TIFF_SPP  -2    /* marker for SamplesPerPixel tags */
+#define  TIFF_VARIABLE2  -3    /* marker for uint32 var-length tags */
+
+#define FIELD_CUSTOM    65    
+
+typedef  struct {
+  ttag_t  field_tag;    /* field's tag */
+  short  field_readcount;  /* read count/TIFF_VARIABLE/TIFF_SPP */
+  short  field_writecount;  /* write count/TIFF_VARIABLE */
+  TIFFDataType field_type;  /* type of associated data */
+  unsigned short field_bit;  /* bit in fieldsset bit vector */
+  unsigned char field_oktochange;  /* if true, can change while writing */
+  unsigned char field_passcount;  /* if true, pass dir count on set */
+  char  *field_name;    /* ASCII name */
+} TIFFFieldInfo;
+
+typedef struct _TIFFTagValue {
+    const TIFFFieldInfo  *info;
+    int             count;
+    void           *value;
+} TIFFTagValue;
+
+extern  void TIFFMergeFieldInfo(TIFF*, const TIFFFieldInfo[], int);
+extern  const TIFFFieldInfo* TIFFFindFieldInfo(TIFF*, ttag_t, TIFFDataType);
+extern  const TIFFFieldInfo* TIFFFindFieldInfoByName(TIFF* , const char *,
+                 TIFFDataType);
+extern  const TIFFFieldInfo* TIFFFieldWithTag(TIFF*, ttag_t);
+extern  const TIFFFieldInfo* TIFFFieldWithName(TIFF*, const char *);
+
+typedef  int (*TIFFVSetMethod)(TIFF*, ttag_t, va_list);
+typedef  int (*TIFFVGetMethod)(TIFF*, ttag_t, va_list);
+typedef  void (*TIFFPrintMethod)(TIFF*, FILE*, long);
+    
+typedef struct {
+    TIFFVSetMethod  vsetfield;  /* tag set routine */
+    TIFFVGetMethod  vgetfield;  /* tag get routine */
+    TIFFPrintMethod  printdir;  /* directory print routine */
+} TIFFTagMethods;
+        
+extern  TIFFTagMethods *TIFFAccessTagMethods( TIFF * );
+extern  void *TIFFGetClientInfo( TIFF *, const char * );
+extern  void TIFFSetClientInfo( TIFF *, void *, const char * );
+    
+extern int TIFFCIELabToRGBInit(TIFFCIELabToRGB*, TIFFDisplay *, float*);
+extern void TIFFCIELabToXYZ(TIFFCIELabToRGB *, uint32, int32, int32,
+          float *, float *, float *);
+extern void TIFFXYZToRGB(TIFFCIELabToRGB *, float, float, float,
+       uint32 *, uint32 *, uint32 *);
+
+extern int TIFFYCbCrToRGBInit(TIFFYCbCrToRGB*, float*, float*);
+extern void TIFFYCbCrtoRGB(TIFFYCbCrToRGB *, uint32, int32, int32,
+         uint32 *, uint32 *, uint32 *);
+
+#if defined(c_plusplus) || defined(__cplusplus)
+}
+#endif
+
+#endif /* _TIFFIO_ */
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Utilities/ITK/Utilities/tiff/tiffio.hxx b/Utilities/ITK/Utilities/tiff/tiffio.hxx
new file mode 100644
index 0000000000..72e0772beb
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tiffio.hxx
@@ -0,0 +1,42 @@
+/* $Id: tiffio.hxx,v 1.1 2005/09/16 19:52:26 jjomier Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _TIFFIO_HXX_
+#define  _TIFFIO_HXX_
+
+/*
+ * TIFF I/O library definitions which provide C++ streams API.
+ */
+
+#include <iostream>
+#include "tiff.h"
+
+extern  TIFF* TIFFStreamOpen(const char*, std::ostream *);
+extern  TIFF* TIFFStreamOpen(const char*, std::istream *);
+
+#endif /* _TIFFIO_HXX_ */
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Utilities/ITK/Utilities/tiff/tiffiop.h b/Utilities/ITK/Utilities/tiff/tiffiop.h
new file mode 100644
index 0000000000..4a1dfac7cc
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tiffiop.h
@@ -0,0 +1,306 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _TIFFIOP_
+#define  _TIFFIOP_
+/*
+ * ``Library-private'' definitions.
+ */
+
+#include "tif_config.h"
+
+#if HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#if HAVE_STRING_H
+# include <string.h>
+#endif
+
+#if HAVE_ASSERT_H
+# include <assert.h>
+#else
+# define assert(x) 
+#endif
+
+#include "tiffio.h"
+#include "tif_dir.h"
+
+typedef double dblparam_t;
+
+#define GLOBALDATA(TYPE,NAME)  extern TYPE NAME
+
+#define    streq(a,b)      (strcmp(a,b) == 0)
+
+#ifndef TRUE
+#define  TRUE  1
+#define  FALSE  0
+#endif
+
+typedef struct client_info {
+    struct client_info *next;
+    void      *data;
+    char      *name;
+} TIFFClientInfoLink;
+
+/*
+ * Typedefs for ``method pointers'' used internally.
+ */
+typedef  unsigned char tidataval_t;  /* internal image data value type */
+typedef  tidataval_t* tidata_t;    /* reference to internal image data */
+
+typedef  void (*TIFFVoidMethod)(TIFF*);
+typedef  int (*TIFFBoolMethod)(TIFF*);
+typedef  int (*TIFFPreMethod)(TIFF*, tsample_t);
+typedef  int (*TIFFCodeMethod)(TIFF*, tidata_t, tsize_t, tsample_t);
+typedef  int (*TIFFSeekMethod)(TIFF*, uint32);
+typedef  void (*TIFFPostMethod)(TIFF*, tidata_t, tsize_t);
+typedef  uint32 (*TIFFStripMethod)(TIFF*, uint32);
+typedef  void (*TIFFTileMethod)(TIFF*, uint32*, uint32*);
+
+struct tiff {
+  char*    tif_name;  /* name of open file */
+  int    tif_fd;    /* open file descriptor */
+  int    tif_mode;  /* open mode (O_*) */
+  uint32    tif_flags;
+#define  TIFF_FILLORDER    0x0003  /* natural bit fill order for machine */
+#define  TIFF_DIRTYHEADER  0x0004  /* header must be written on close */
+#define  TIFF_DIRTYDIRECT  0x0008  /* current directory must be written */
+#define  TIFF_BUFFERSETUP  0x0010  /* data buffers setup */
+#define  TIFF_CODERSETUP    0x0020  /* encoder/decoder setup done */
+#define  TIFF_BEENWRITING  0x0040  /* written 1+ scanlines to file */
+#define  TIFF_SWAB    0x0080  /* byte swap file information */
+#define  TIFF_NOBITREV    0x0100  /* inhibit bit reversal logic */
+#define  TIFF_MYBUFFER    0x0200  /* my raw data buffer; free on close */
+#define  TIFF_ISTILED    0x0400  /* file is tile, not strip- based */
+#define  TIFF_MAPPED    0x0800  /* file is mapped into memory */
+#define  TIFF_POSTENCODE    0x1000  /* need call to postencode routine */
+#define  TIFF_INSUBIFD    0x2000  /* currently writing a subifd */
+#define  TIFF_UPSAMPLED    0x4000  /* library is doing data up-sampling */ 
+#define  TIFF_STRIPCHOP    0x8000  /* enable strip chopping support */
+  toff_t    tif_diroff;  /* file offset of current directory */
+  toff_t    tif_nextdiroff;  /* file offset of following directory */
+  toff_t*    tif_dirlist;  /* list of offsets to already seen */
+          /* directories to prevent IFD looping */
+  uint16    tif_dirnumber;  /* number of already seen directories */
+  TIFFDirectory  tif_dir;  /* internal rep of current directory */
+  TIFFHeader  tif_header;  /* file's header block */
+  const int*  tif_typeshift;  /* data type shift counts */
+  const long*  tif_typemask;  /* data type masks */
+  uint32    tif_row;  /* current scanline */
+  tdir_t    tif_curdir;  /* current directory (index) */
+  tstrip_t  tif_curstrip;  /* current strip for read/write */
+  toff_t    tif_curoff;  /* current offset for read/write */
+  toff_t    tif_dataoff;  /* current offset for writing dir */
+/* SubIFD support */
+  uint16    tif_nsubifd;  /* remaining subifds to write */
+  toff_t    tif_subifdoff;  /* offset for patching SubIFD link */
+/* tiling support */
+  uint32     tif_col;  /* current column (offset by row too) */
+  ttile_t    tif_curtile;  /* current tile for read/write */
+  tsize_t    tif_tilesize;  /* # of bytes in a tile */
+/* compression scheme hooks */
+  int    tif_decodestatus;
+  TIFFBoolMethod  tif_setupdecode;/* called once before predecode */
+  TIFFPreMethod  tif_predecode;  /* pre- row/strip/tile decoding */
+  TIFFBoolMethod  tif_setupencode;/* called once before preencode */
+  int    tif_encodestatus;
+  TIFFPreMethod  tif_preencode;  /* pre- row/strip/tile encoding */
+  TIFFBoolMethod  tif_postencode;  /* post- row/strip/tile encoding */
+  TIFFCodeMethod  tif_decoderow;  /* scanline decoding routine */
+  TIFFCodeMethod  tif_encoderow;  /* scanline encoding routine */
+  TIFFCodeMethod  tif_decodestrip;/* strip decoding routine */
+  TIFFCodeMethod  tif_encodestrip;/* strip encoding routine */
+  TIFFCodeMethod  tif_decodetile;  /* tile decoding routine */
+  TIFFCodeMethod  tif_encodetile;  /* tile encoding routine */
+  TIFFVoidMethod  tif_close;  /* cleanup-on-close routine */
+  TIFFSeekMethod  tif_seek;  /* position within a strip routine */
+  TIFFVoidMethod  tif_cleanup;  /* cleanup state routine */
+  TIFFStripMethod  tif_defstripsize;/* calculate/constrain strip size */
+  TIFFTileMethod  tif_deftilesize;/* calculate/constrain tile size */
+  tidata_t  tif_data;  /* compression scheme private data */
+/* input/output buffering */
+  tsize_t    tif_scanlinesize;/* # of bytes in a scanline */
+  tsize_t    tif_scanlineskew;/* scanline skew for reading strips */
+  tidata_t  tif_rawdata;  /* raw data buffer */
+  tsize_t    tif_rawdatasize;/* # of bytes in raw data buffer */
+  tidata_t  tif_rawcp;  /* current spot in raw buffer */
+  tsize_t    tif_rawcc;  /* bytes unread from raw buffer */
+/* memory-mapped file support */
+  tidata_t  tif_base;  /* base of mapped file */
+  toff_t    tif_size;  /* size of mapped file region (bytes) */
+  TIFFMapFileProc  tif_mapproc;  /* map file method */
+  TIFFUnmapFileProc tif_unmapproc;/* unmap file method */
+/* input/output callback methods */
+  thandle_t  tif_clientdata;  /* callback parameter */
+  TIFFReadWriteProc tif_readproc;  /* read method */
+  TIFFReadWriteProc tif_writeproc;/* write method */
+  TIFFSeekProc  tif_seekproc;  /* lseek method */
+  TIFFCloseProc  tif_closeproc;  /* close method */
+  TIFFSizeProc  tif_sizeproc;  /* filesize method */
+/* post-decoding support */
+  TIFFPostMethod  tif_postdecode;  /* post decoding routine */
+/* tag support */
+  TIFFFieldInfo**  tif_fieldinfo;  /* sorted table of registered tags */
+  int    tif_nfields;  /* # entries in registered tag table */
+  const TIFFFieldInfo *tif_foundfield;/* cached pointer to already found tag */
+        TIFFTagMethods  tif_tagmethods; /* tag get/set/print routines */
+        TIFFClientInfoLink *tif_clientinfo; /* extra client information. */
+};
+
+#define  isPseudoTag(t)  (t > 0xffff)  /* is tag value normal or pseudo */
+
+#define  isTiled(tif)  (((tif)->tif_flags & TIFF_ISTILED) != 0)
+#define  isMapped(tif)  (((tif)->tif_flags & TIFF_MAPPED) != 0)
+#define  isFillOrder(tif, o)  (((tif)->tif_flags & (o)) != 0)
+#define  isUpSampled(tif)  (((tif)->tif_flags & TIFF_UPSAMPLED) != 0)
+#define  TIFFReadFile(tif, buf, size) \
+  ((*(tif)->tif_readproc)((tif)->tif_clientdata,buf,size))
+#define  TIFFWriteFile(tif, buf, size) \
+  ((*(tif)->tif_writeproc)((tif)->tif_clientdata,buf,size))
+#define  TIFFSeekFile(tif, off, whence) \
+  ((*(tif)->tif_seekproc)((tif)->tif_clientdata,(toff_t)(off),whence))
+#define  TIFFCloseFile(tif) \
+  ((*(tif)->tif_closeproc)((tif)->tif_clientdata))
+#define  TIFFGetFileSize(tif) \
+  ((*(tif)->tif_sizeproc)((tif)->tif_clientdata))
+#define  TIFFMapFileContents(tif, paddr, psize) \
+  ((*(tif)->tif_mapproc)((tif)->tif_clientdata,paddr,psize))
+#define  TIFFUnmapFileContents(tif, addr, size) \
+  ((*(tif)->tif_unmapproc)((tif)->tif_clientdata,addr,size))
+
+/*
+ * Default Read/Seek/Write definitions.
+ */
+#ifndef ReadOK
+#define  ReadOK(tif, buf, size) \
+  (TIFFReadFile(tif, (tdata_t) buf, (tsize_t)(size)) == (tsize_t)(size))
+#endif
+#ifndef SeekOK
+#define  SeekOK(tif, off) \
+  (TIFFSeekFile(tif, (toff_t) off, SEEK_SET) == (toff_t) off)
+#endif
+#ifndef WriteOK
+#define  WriteOK(tif, buf, size) \
+  (TIFFWriteFile(tif, (tdata_t) buf, (tsize_t) size) == (tsize_t) size)
+#endif
+
+/* NB: the uint32 casts are to silence certain ANSI-C compilers */
+#define TIFFhowmany(x, y) ((((uint32)(x))+(((uint32)(y))-1))/((uint32)(y)))
+#define TIFFhowmany8(x) (((x)&0x07)?((uint32)(x)>>3)+1:(uint32)(x)>>3)
+#define  TIFFroundup(x, y) (TIFFhowmany(x,y)*(y))
+
+#define TIFFmax(A,B) ((A)>(B)?(A):(B))
+#define TIFFmin(A,B) ((A)<(B)?(A):(B))
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+extern  int _TIFFgetMode(const char*, const char*);
+extern  int _TIFFNoRowEncode(TIFF*, tidata_t, tsize_t, tsample_t);
+extern  int _TIFFNoStripEncode(TIFF*, tidata_t, tsize_t, tsample_t);
+extern  int _TIFFNoTileEncode(TIFF*, tidata_t, tsize_t, tsample_t);
+extern  int _TIFFNoRowDecode(TIFF*, tidata_t, tsize_t, tsample_t);
+extern  int _TIFFNoStripDecode(TIFF*, tidata_t, tsize_t, tsample_t);
+extern  int _TIFFNoTileDecode(TIFF*, tidata_t, tsize_t, tsample_t);
+extern  void _TIFFNoPostDecode(TIFF*, tidata_t, tsize_t);
+extern  int  _TIFFNoPreCode (TIFF*, tsample_t); 
+extern  int _TIFFNoSeek(TIFF*, uint32);
+extern  void _TIFFSwab16BitData(TIFF*, tidata_t, tsize_t);
+extern  void _TIFFSwab32BitData(TIFF*, tidata_t, tsize_t);
+extern  void _TIFFSwab64BitData(TIFF*, tidata_t, tsize_t);
+extern  int TIFFFlushData1(TIFF*);
+extern  void TIFFFreeDirectory(TIFF*);
+extern  int TIFFDefaultDirectory(TIFF*);
+extern  int TIFFSetCompressionScheme(TIFF*, int);
+extern  int TIFFSetDefaultCompressionState(TIFF*);
+extern  uint32 _TIFFDefaultStripSize(TIFF*, uint32);
+extern  void _TIFFDefaultTileSize(TIFF*, uint32*, uint32*);
+
+extern  void _TIFFsetByteArray(void**, void*, long);
+extern  void _TIFFsetString(char**, char*);
+extern  void _TIFFsetShortArray(uint16**, uint16*, long);
+extern  void _TIFFsetLongArray(uint32**, uint32*, long);
+extern  void _TIFFsetFloatArray(float**, float*, long);
+extern  void _TIFFsetDoubleArray(double**, double*, long);
+
+extern  void _TIFFprintAscii(FILE*, const char*);
+extern  void _TIFFprintAsciiTag(FILE*, const char*, const char*);
+
+GLOBALDATA(TIFFErrorHandler,_TIFFwarningHandler);
+GLOBALDATA(TIFFErrorHandler,_TIFFerrorHandler);
+
+extern  int TIFFInitDumpMode(TIFF*, int);
+#ifdef PACKBITS_SUPPORT
+extern  int TIFFInitPackBits(TIFF*, int);
+#endif
+#ifdef CCITT_SUPPORT
+extern  int TIFFInitCCITTRLE(TIFF*, int), TIFFInitCCITTRLEW(TIFF*, int);
+extern  int TIFFInitCCITTFax3(TIFF*, int), TIFFInitCCITTFax4(TIFF*, int);
+#endif
+#ifdef THUNDER_SUPPORT
+extern  int TIFFInitThunderScan(TIFF*, int);
+#endif
+#ifdef NEXT_SUPPORT
+extern  int TIFFInitNeXT(TIFF*, int);
+#endif
+#ifdef LZW_SUPPORT
+extern  int TIFFInitLZW(TIFF*, int);
+#endif
+#ifdef OJPEG_SUPPORT
+extern  int TIFFInitOJPEG(TIFF*, int);
+#endif
+#ifdef JPEG_SUPPORT
+extern  int TIFFInitJPEG(TIFF*, int);
+#endif
+#ifdef JBIG_SUPPORT
+extern  int TIFFInitJBIG(TIFF*, int);
+#endif
+#ifdef ZIP_SUPPORT
+extern  int TIFFInitZIP(TIFF*, int);
+#endif
+#ifdef PIXARLOG_SUPPORT
+extern  int TIFFInitPixarLog(TIFF*, int);
+#endif
+#ifdef LOGLUV_SUPPORT
+extern  int TIFFInitSGILog(TIFF*, int);
+#endif
+#ifdef VMS
+extern  const TIFFCodec _TIFFBuiltinCODECS[];
+#else
+extern  TIFFCodec _TIFFBuiltinCODECS[];
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+#endif /* _TIFFIOP_ */
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Utilities/ITK/Utilities/tiff/tiffvers.h b/Utilities/ITK/Utilities/tiff/tiffvers.h
new file mode 100644
index 0000000000..9492587237
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/tiffvers.h
@@ -0,0 +1,9 @@
+#define TIFFLIB_VERSION_STR "LIBTIFF, Version 3.7.2\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc."
+/*
+ * This define can be used in code that requires
+ * compilation-related definitions specific to a
+ * version or versions of the library.  Runtime
+ * version checking should be done based on the
+ * string returned by TIFFGetVersion.
+ */
+#define TIFFLIB_VERSION 20050315
diff --git a/Utilities/ITK/Utilities/tiff/uvcode.h b/Utilities/ITK/Utilities/tiff/uvcode.h
new file mode 100644
index 0000000000..c402688801
--- /dev/null
+++ b/Utilities/ITK/Utilities/tiff/uvcode.h
@@ -0,0 +1,173 @@
+/* Version 1.0 generated April 7, 1997 by Greg Ward Larson, SGI */
+#define UV_SQSIZ  (float)0.003500
+#define UV_NDIVS  16289
+#define UV_VSTART  (float)0.016940
+#define UV_NVS    163
+static struct {
+  float  ustart;
+  short  nus, ncum;
+}  uv_row[UV_NVS] = {
+    { (float)0.247663,  4,  0 },
+    { (float)0.243779,  6,  4 },
+    { (float)0.241684,  7,  10 },
+    { (float)0.237874,  9,  17 },
+    { (float)0.235906,  10,  26 },
+    { (float)0.232153,  12,  36 },
+    { (float)0.228352,  14,  48 },
+    { (float)0.226259,  15,  62 },
+    { (float)0.222371,  17,  77 },
+    { (float)0.220410,  18,  94 },
+    { (float)0.214710,  21,  112 },
+    { (float)0.212714,  22,  133 },
+    { (float)0.210721,  23,  155 },
+    { (float)0.204976,  26,  178 },
+    { (float)0.202986,  27,  204 },
+    { (float)0.199245,  29,  231 },
+    { (float)0.195525,  31,  260 },
+    { (float)0.193560,  32,  291 },
+    { (float)0.189878,  34,  323 },
+    { (float)0.186216,  36,  357 },
+    { (float)0.186216,  36,  393 },
+    { (float)0.182592,  38,  429 },
+    { (float)0.179003,  40,  467 },
+    { (float)0.175466,  42,  507 },
+    { (float)0.172001,  44,  549 },
+    { (float)0.172001,  44,  593 },
+    { (float)0.168612,  46,  637 },
+    { (float)0.168612,  46,  683 },
+    { (float)0.163575,  49,  729 },
+    { (float)0.158642,  52,  778 },
+    { (float)0.158642,  52,  830 },
+    { (float)0.158642,  52,  882 },
+    { (float)0.153815,  55,  934 },
+    { (float)0.153815,  55,  989 },
+    { (float)0.149097,  58,  1044 },
+    { (float)0.149097,  58,  1102 },
+    { (float)0.142746,  62,  1160 },
+    { (float)0.142746,  62,  1222 },
+    { (float)0.142746,  62,  1284 },
+    { (float)0.138270,  65,  1346 },
+    { (float)0.138270,  65,  1411 },
+    { (float)0.138270,  65,  1476 },
+    { (float)0.132166,  69,  1541 },
+    { (float)0.132166,  69,  1610 },
+    { (float)0.126204,  73,  1679 },
+    { (float)0.126204,  73,  1752 },
+    { (float)0.126204,  73,  1825 },
+    { (float)0.120381,  77,  1898 },
+    { (float)0.120381,  77,  1975 },
+    { (float)0.120381,  77,  2052 },
+    { (float)0.120381,  77,  2129 },
+    { (float)0.112962,  82,  2206 },
+    { (float)0.112962,  82,  2288 },
+    { (float)0.112962,  82,  2370 },
+    { (float)0.107450,  86,  2452 },
+    { (float)0.107450,  86,  2538 },
+    { (float)0.107450,  86,  2624 },
+    { (float)0.107450,  86,  2710 },
+    { (float)0.100343,  91,  2796 },
+    { (float)0.100343,  91,  2887 },
+    { (float)0.100343,  91,  2978 },
+    { (float)0.095126,  95,  3069 },
+    { (float)0.095126,  95,  3164 },
+    { (float)0.095126,  95,  3259 },
+    { (float)0.095126,  95,  3354 },
+    { (float)0.088276,  100,  3449 },
+    { (float)0.088276,  100,  3549 },
+    { (float)0.088276,  100,  3649 },
+    { (float)0.088276,  100,  3749 },
+    { (float)0.081523,  105,  3849 },
+    { (float)0.081523,  105,  3954 },
+    { (float)0.081523,  105,  4059 },
+    { (float)0.081523,  105,  4164 },
+    { (float)0.074861,  110,  4269 },
+    { (float)0.074861,  110,  4379 },
+    { (float)0.074861,  110,  4489 },
+    { (float)0.074861,  110,  4599 },
+    { (float)0.068290,  115,  4709 },
+    { (float)0.068290,  115,  4824 },
+    { (float)0.068290,  115,  4939 },
+    { (float)0.068290,  115,  5054 },
+    { (float)0.063573,  119,  5169 },
+    { (float)0.063573,  119,  5288 },
+    { (float)0.063573,  119,  5407 },
+    { (float)0.063573,  119,  5526 },
+    { (float)0.057219,  124,  5645 },
+    { (float)0.057219,  124,  5769 },
+    { (float)0.057219,  124,  5893 },
+    { (float)0.057219,  124,  6017 },
+    { (float)0.050985,  129,  6141 },
+    { (float)0.050985,  129,  6270 },
+    { (float)0.050985,  129,  6399 },
+    { (float)0.050985,  129,  6528 },
+    { (float)0.050985,  129,  6657 },
+    { (float)0.044859,  134,  6786 },
+    { (float)0.044859,  134,  6920 },
+    { (float)0.044859,  134,  7054 },
+    { (float)0.044859,  134,  7188 },
+    { (float)0.040571,  138,  7322 },
+    { (float)0.040571,  138,  7460 },
+    { (float)0.040571,  138,  7598 },
+    { (float)0.040571,  138,  7736 },
+    { (float)0.036339,  142,  7874 },
+    { (float)0.036339,  142,  8016 },
+    { (float)0.036339,  142,  8158 },
+    { (float)0.036339,  142,  8300 },
+    { (float)0.032139,  146,  8442 },
+    { (float)0.032139,  146,  8588 },
+    { (float)0.032139,  146,  8734 },
+    { (float)0.032139,  146,  8880 },
+    { (float)0.027947,  150,  9026 },
+    { (float)0.027947,  150,  9176 },
+    { (float)0.027947,  150,  9326 },
+    { (float)0.023739,  154,  9476 },
+    { (float)0.023739,  154,  9630 },
+    { (float)0.023739,  154,  9784 },
+    { (float)0.023739,  154,  9938 },
+    { (float)0.019504,  158,  10092 },
+    { (float)0.019504,  158,  10250 },
+    { (float)0.019504,  158,  10408 },
+    { (float)0.016976,  161,  10566 },
+    { (float)0.016976,  161,  10727 },
+    { (float)0.016976,  161,  10888 },
+    { (float)0.016976,  161,  11049 },
+    { (float)0.012639,  165,  11210 },
+    { (float)0.012639,  165,  11375 },
+    { (float)0.012639,  165,  11540 },
+    { (float)0.009991,  168,  11705 },
+    { (float)0.009991,  168,  11873 },
+    { (float)0.009991,  168,  12041 },
+    { (float)0.009016,  170,  12209 },
+    { (float)0.009016,  170,  12379 },
+    { (float)0.009016,  170,  12549 },
+    { (float)0.006217,  173,  12719 },
+    { (float)0.006217,  173,  12892 },
+    { (float)0.005097,  175,  13065 },
+    { (float)0.005097,  175,  13240 },
+    { (float)0.005097,  175,  13415 },
+    { (float)0.003909,  177,  13590 },
+    { (float)0.003909,  177,  13767 },
+    { (float)0.002340,  177,  13944 },
+    { (float)0.002389,  170,  14121 },
+    { (float)0.001068,  164,  14291 },
+    { (float)0.001653,  157,  14455 },
+    { (float)0.000717,  150,  14612 },
+    { (float)0.001614,  143,  14762 },
+    { (float)0.000270,  136,  14905 },
+    { (float)0.000484,  129,  15041 },
+    { (float)0.001103,  123,  15170 },
+    { (float)0.001242,  115,  15293 },
+    { (float)0.001188,  109,  15408 },
+    { (float)0.001011,  103,  15517 },
+    { (float)0.000709,  97,  15620 },
+    { (float)0.000301,  89,  15717 },
+    { (float)0.002416,  82,  15806 },
+    { (float)0.003251,  76,  15888 },
+    { (float)0.003246,  69,  15964 },
+    { (float)0.004141,  62,  16033 },
+    { (float)0.005963,  55,  16095 },
+    { (float)0.008839,  47,  16150 },
+    { (float)0.010490,  40,  16197 },
+    { (float)0.016994,  31,  16237 },
+    { (float)0.023659,  21,  16268 },
+};
diff --git a/Utilities/ITK/Utilities/zlib/.NoDartCoverage b/Utilities/ITK/Utilities/zlib/.NoDartCoverage
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/Utilities/ITK/Utilities/zlib/CMakeLists.txt b/Utilities/ITK/Utilities/zlib/CMakeLists.txt
new file mode 100644
index 0000000000..1d7c0dddf2
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/CMakeLists.txt
@@ -0,0 +1,41 @@
+PROJECT(ITKZLIB)
+INCLUDE_REGULAR_EXPRESSION("^(deflate|inf|trees|zconf|zlib|zutil).*$")
+
+INCLUDE_DIRECTORIES(BEFORE ${ITKZLIB_SOURCE_DIR})
+INCLUDE_DIRECTORIES(BEFORE ${ITKZLIB_BINARY_DIR})
+
+# source files for zlib
+SET(ZLIB_SRCS
+adler32.c   gzio.c      inftrees.c  uncompr.c
+compress.c  infblock.c  infutil.c   zutil.c
+crc32.c     infcodes.c  
+deflate.c   inffast.c   
+inflate.c   trees.c 
+)
+
+# for windows add the .def and .rc files to the source list
+IF(WIN32)
+  IF(BUILD_SHARED_LIBS)
+    SET(ZLIB_DLL 1)
+  ENDIF(BUILD_SHARED_LIBS)
+  IF(NOT UNIX)
+    IF(NOT BORLAND)
+      IF(NOT MINGW)
+        SET(ZLIB_SRCS ${ZLIB_SRCS} zlib.def zlib.rc  )
+      ENDIF(NOT MINGW)
+    ENDIF(NOT BORLAND)  
+  ENDIF(NOT UNIX)
+ENDIF(WIN32)
+
+CONFIGURE_FILE(${ITKZLIB_SOURCE_DIR}/.NoDartCoverage 
+               ${ITKZLIB_BINARY_DIR}/.NoDartCoverage)
+CONFIGURE_FILE(${ITKZLIB_SOURCE_DIR}/zlibDllConfig.h.in
+               ${ITKZLIB_BINARY_DIR}/zlibDllConfig.h)
+
+
+ADD_LIBRARY(itkzlib ${ZLIB_SRCS})
+
+INSTALL_TARGETS(/lib/InsightToolkit itkzlib)
+INSTALL_FILES(${VXL_INSTALL_ROOT}/include/InsightToolkit/Utilities/zlib ".h" zlibDllConfig)
+INSTALL_FILES(/include/InsightToolkit/Utilities/zlib "(\\.h)$")
+
diff --git a/Utilities/ITK/Utilities/zlib/adler32.c b/Utilities/ITK/Utilities/zlib/adler32.c
new file mode 100644
index 0000000000..16cf9a703f
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/adler32.c
@@ -0,0 +1,48 @@
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* @(#) $Id$ */
+
+#include "zlib.h"
+
+#define BASE 65521L /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i)  {s1 += buf[i]; s2 += s1;}
+#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf)   DO8(buf,0); DO8(buf,8);
+
+/* ========================================================================= */
+uLong ZEXPORT adler32(adler, buf, len)
+    uLong adler;
+    const Bytef *buf;
+    uInt len;
+{
+    unsigned long s1 = adler & 0xffff;
+    unsigned long s2 = (adler >> 16) & 0xffff;
+    int k;
+
+    if (buf == Z_NULL) return 1L;
+
+    while (len > 0) {
+        k = len < NMAX ? len : NMAX;
+        len -= k;
+        while (k >= 16) {
+            DO16(buf);
+	    buf += 16;
+            k -= 16;
+        }
+        if (k != 0) do {
+            s1 += *buf++;
+	    s2 += s1;
+        } while (--k);
+        s1 %= BASE;
+        s2 %= BASE;
+    }
+    return (s2 << 16) | s1;
+}
diff --git a/Utilities/ITK/Utilities/zlib/compress.c b/Utilities/ITK/Utilities/zlib/compress.c
new file mode 100644
index 0000000000..1cee470913
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/compress.c
@@ -0,0 +1,68 @@
+/* compress.c -- compress a memory buffer
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* @(#) $Id$ */
+
+#include "zlib.h"
+
+/* ===========================================================================
+     Compresses the source buffer into the destination buffer. The level
+   parameter has the same meaning as in deflateInit.  sourceLen is the byte
+   length of the source buffer. Upon entry, destLen is the total size of the
+   destination buffer, which must be at least 0.1% larger than sourceLen plus
+   12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
+
+     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+   Z_STREAM_ERROR if the level parameter is invalid.
+*/
+int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
+    Bytef *dest;
+    uLongf *destLen;
+    const Bytef *source;
+    uLong sourceLen;
+    int level;
+{
+    z_stream stream;
+    int err;
+
+    stream.next_in = (Bytef*)source;
+    stream.avail_in = (uInt)sourceLen;
+#ifdef MAXSEG_64K
+    /* Check for source > 64K on 16-bit machine: */
+    if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
+#endif
+    stream.next_out = dest;
+    stream.avail_out = (uInt)*destLen;
+    if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+
+    stream.zalloc = (alloc_func)0;
+    stream.zfree = (free_func)0;
+    stream.opaque = (voidpf)0;
+
+    err = deflateInit(&stream, level);
+    if (err != Z_OK) return err;
+
+    err = deflate(&stream, Z_FINISH);
+    if (err != Z_STREAM_END) {
+        deflateEnd(&stream);
+        return err == Z_OK ? Z_BUF_ERROR : err;
+    }
+    *destLen = stream.total_out;
+
+    err = deflateEnd(&stream);
+    return err;
+}
+
+/* ===========================================================================
+ */
+int ZEXPORT compress (dest, destLen, source, sourceLen)
+    Bytef *dest;
+    uLongf *destLen;
+    const Bytef *source;
+    uLong sourceLen;
+{
+    return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
+}
diff --git a/Utilities/ITK/Utilities/zlib/crc32.c b/Utilities/ITK/Utilities/zlib/crc32.c
new file mode 100644
index 0000000000..a91101a81c
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/crc32.c
@@ -0,0 +1,162 @@
+/* crc32.c -- compute the CRC-32 of a data stream
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* @(#) $Id$ */
+
+#include "zlib.h"
+
+#define local static
+
+#ifdef DYNAMIC_CRC_TABLE
+
+local int crc_table_empty = 1;
+local uLongf crc_table[256];
+local void make_crc_table OF((void));
+
+/*
+  Generate a table for a byte-wise 32-bit CRC calculation on the polynomial:
+  x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
+
+  Polynomials over GF(2) are represented in binary, one bit per coefficient,
+  with the lowest powers in the most significant bit.  Then adding polynomials
+  is just exclusive-or, and multiplying a polynomial by x is a right shift by
+  one.  If we call the above polynomial p, and represent a byte as the
+  polynomial q, also with the lowest power in the most significant bit (so the
+  byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
+  where a mod b means the remainder after dividing a by b.
+
+  This calculation is done using the shift-register method of multiplying and
+  taking the remainder.  The register is initialized to zero, and for each
+  incoming bit, x^32 is added mod p to the register if the bit is a one (where
+  x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
+  x (which is shifting right by one and adding x^32 mod p if the bit shifted
+  out is a one).  We start with the highest power (least significant bit) of
+  q and repeat for all eight bits of q.
+
+  The table is simply the CRC of all possible eight bit values.  This is all
+  the information needed to generate CRC's on data a byte at a time for all
+  combinations of CRC register values and incoming bytes.
+*/
+local void make_crc_table()
+{
+  uLong c;
+  int n, k;
+  uLong poly;            /* polynomial exclusive-or pattern */
+  /* terms of polynomial defining this crc (except x^32): */
+  static const Byte p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
+
+  /* make exclusive-or pattern from polynomial (0xedb88320L) */
+  poly = 0L;
+  for (n = 0; n < sizeof(p)/sizeof(Byte); n++)
+    poly |= 1L << (31 - p[n]);
+ 
+  for (n = 0; n < 256; n++)
+  {
+    c = (uLong)n;
+    for (k = 0; k < 8; k++)
+      c = c & 1 ? poly ^ (c >> 1) : c >> 1;
+    crc_table[n] = c;
+  }
+  crc_table_empty = 0;
+}
+#else
+/* ========================================================================
+ * Table of CRC-32's of all single-byte values (made by make_crc_table)
+ */
+local const uLongf crc_table[256] = {
+  0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+  0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+  0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+  0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+  0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+  0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+  0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+  0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+  0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+  0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+  0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+  0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+  0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+  0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+  0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+  0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+  0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+  0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+  0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+  0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+  0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+  0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+  0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+  0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+  0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+  0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+  0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+  0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+  0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+  0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+  0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+  0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+  0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+  0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+  0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+  0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+  0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+  0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+  0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+  0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+  0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+  0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+  0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+  0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+  0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+  0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+  0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+  0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+  0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+  0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+  0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+  0x2d02ef8dL
+};
+#endif
+
+/* =========================================================================
+ * This function can be used by asm versions of crc32()
+ */
+const uLongf * ZEXPORT get_crc_table()
+{
+#ifdef DYNAMIC_CRC_TABLE
+  if (crc_table_empty) make_crc_table();
+#endif
+  return (const uLongf *)crc_table;
+}
+
+/* ========================================================================= */
+#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
+#define DO2(buf)  DO1(buf); DO1(buf);
+#define DO4(buf)  DO2(buf); DO2(buf);
+#define DO8(buf)  DO4(buf); DO4(buf);
+
+/* ========================================================================= */
+uLong ZEXPORT crc32(crc, buf, len)
+    uLong crc;
+    const Bytef *buf;
+    uInt len;
+{
+    if (buf == Z_NULL) return 0L;
+#ifdef DYNAMIC_CRC_TABLE
+    if (crc_table_empty)
+      make_crc_table();
+#endif
+    crc = crc ^ 0xffffffffL;
+    while (len >= 8)
+    {
+      DO8(buf);
+      len -= 8;
+    }
+    if (len) do {
+      DO1(buf);
+    } while (--len);
+    return crc ^ 0xffffffffL;
+}
diff --git a/Utilities/ITK/Utilities/zlib/deflate.c b/Utilities/ITK/Utilities/zlib/deflate.c
new file mode 100644
index 0000000000..25d5818e2e
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/deflate.c
@@ -0,0 +1,1350 @@
+/* deflate.c -- compress data using the deflation algorithm
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/*
+ *  ALGORITHM
+ *
+ *      The "deflation" process depends on being able to identify portions
+ *      of the input text which are identical to earlier input (within a
+ *      sliding window trailing behind the input currently being processed).
+ *
+ *      The most straightforward technique turns out to be the fastest for
+ *      most input files: try all possible matches and select the longest.
+ *      The key feature of this algorithm is that insertions into the string
+ *      dictionary are very simple and thus fast, and deletions are avoided
+ *      completely. Insertions are performed at each input character, whereas
+ *      string matches are performed only when the previous match ends. So it
+ *      is preferable to spend more time in matches to allow very fast string
+ *      insertions and avoid deletions. The matching algorithm for small
+ *      strings is inspired from that of Rabin & Karp. A brute force approach
+ *      is used to find longer strings when a small match has been found.
+ *      A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
+ *      (by Leonid Broukhis).
+ *         A previous version of this file used a more sophisticated algorithm
+ *      (by Fiala and Greene) which is guaranteed to run in linear amortized
+ *      time, but has a larger average cost, uses more memory and is patented.
+ *      However the F&G algorithm may be faster for some highly redundant
+ *      files if the parameter max_chain_length (described below) is too large.
+ *
+ *  ACKNOWLEDGEMENTS
+ *
+ *      The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
+ *      I found it in 'freeze' written by Leonid Broukhis.
+ *      Thanks to many people for bug reports and testing.
+ *
+ *  REFERENCES
+ *
+ *      Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
+ *      Available in ftp://ds.internic.net/rfc/rfc1951.txt
+ *
+ *      A description of the Rabin and Karp algorithm is given in the book
+ *         "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
+ *
+ *      Fiala,E.R., and Greene,D.H.
+ *         Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
+ *
+ */
+
+/* @(#) $Id$ */
+
+#include "deflate.h"
+
+const char deflate_copyright[] =
+   " deflate 1.1.3 Copyright 1995-1998 Jean-loup Gailly ";
+/*
+  If you use the zlib library in a product, an acknowledgment is welcome
+  in the documentation of your product. If for some reason you cannot
+  include such an acknowledgment, I would appreciate that you keep this
+  copyright string in the executable of your product.
+ */
+
+/* ===========================================================================
+ *  Function prototypes.
+ */
+typedef enum {
+    need_more,      /* block not completed, need more input or more output */
+    block_done,     /* block flush performed */
+    finish_started, /* finish started, need only more output at next deflate */
+    finish_done     /* finish done, accept no more input or output */
+} block_state;
+
+typedef block_state (*compress_func) OF((deflate_state *s, int flush));
+/* Compression function. Returns the block state after the call. */
+
+local void fill_window    OF((deflate_state *s));
+local block_state deflate_stored OF((deflate_state *s, int flush));
+local block_state deflate_fast   OF((deflate_state *s, int flush));
+local block_state deflate_slow   OF((deflate_state *s, int flush));
+local void lm_init        OF((deflate_state *s));
+local void putShortMSB    OF((deflate_state *s, uInt b));
+local void flush_pending  OF((z_streamp strm));
+local int read_buf        OF((z_streamp strm, Bytef *buf, unsigned size));
+#ifdef ASMV
+      void match_init OF((void)); /* asm code initialization */
+      uInt longest_match  OF((deflate_state *s, IPos cur_match));
+#else
+local uInt longest_match  OF((deflate_state *s, IPos cur_match));
+#endif
+
+#ifdef DEBUG
+local  void check_match OF((deflate_state *s, IPos start, IPos match,
+                            int length));
+#endif
+
+/* ===========================================================================
+ * Local data
+ */
+
+#define NIL 0
+/* Tail of hash chains */
+
+#ifndef TOO_FAR
+#  define TOO_FAR 4096
+#endif
+/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+/* Values for max_lazy_match, good_match and max_chain_length, depending on
+ * the desired pack level (0..9). The values given below have been tuned to
+ * exclude worst case performance for pathological files. Better values may be
+ * found for specific files.
+ */
+typedef struct config_s {
+   ush good_length; /* reduce lazy search above this match length */
+   ush max_lazy;    /* do not perform lazy search above this match length */
+   ush nice_length; /* quit search above this match length */
+   ush max_chain;
+   compress_func func;
+} config;
+
+local const config configuration_table[10] = {
+/*      good lazy nice chain */
+/* 0 */ {0,    0,  0,    0, deflate_stored},  /* store only */
+/* 1 */ {4,    4,  8,    4, deflate_fast}, /* maximum speed, no lazy matches */
+/* 2 */ {4,    5, 16,    8, deflate_fast},
+/* 3 */ {4,    6, 32,   32, deflate_fast},
+
+/* 4 */ {4,    4, 16,   16, deflate_slow},  /* lazy matches */
+/* 5 */ {8,   16, 32,   32, deflate_slow},
+/* 6 */ {8,   16, 128, 128, deflate_slow},
+/* 7 */ {8,   32, 128, 256, deflate_slow},
+/* 8 */ {32, 128, 258, 1024, deflate_slow},
+/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* maximum compression */
+
+/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
+ * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
+ * meaning.
+ */
+
+#define EQUAL 0
+/* result of memcmp for equal strings */
+
+struct static_tree_desc_s {int dummy;}; /* for buggy compilers */
+
+/* ===========================================================================
+ * Update a hash value with the given input byte
+ * IN  assertion: all calls to to UPDATE_HASH are made with consecutive
+ *    input characters, so that a running hash key can be computed from the
+ *    previous key instead of complete recalculation each time.
+ */
+#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask)
+
+
+/* ===========================================================================
+ * Insert string str in the dictionary and set match_head to the previous head
+ * of the hash chain (the most recent string with same hash key). Return
+ * the previous length of the hash chain.
+ * If this file is compiled with -DFASTEST, the compression level is forced
+ * to 1, and no hash chains are maintained.
+ * IN  assertion: all calls to to INSERT_STRING are made with consecutive
+ *    input characters and the first MIN_MATCH bytes of str are valid
+ *    (except for the last MIN_MATCH-1 bytes of the input file).
+ */
+#ifdef FASTEST
+#define INSERT_STRING(s, str, match_head) \
+   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+    match_head = s->head[s->ins_h], \
+    s->head[s->ins_h] = (Pos)(str))
+#else
+#define INSERT_STRING(s, str, match_head) \
+   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+    s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \
+    s->head[s->ins_h] = (Pos)(str))
+#endif
+
+/* ===========================================================================
+ * Initialize the hash table (avoiding 64K overflow for 16 bit systems).
+ * prev[] will be initialized on the fly.
+ */
+#define CLEAR_HASH(s) \
+    s->head[s->hash_size-1] = NIL; \
+    zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));
+
+/* ========================================================================= */
+int ZEXPORT deflateInit_(strm, level, version, stream_size)
+    z_streamp strm;
+    int level;
+    const char *version;
+    int stream_size;
+{
+    return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
+			 Z_DEFAULT_STRATEGY, version, stream_size);
+    /* To do: ignore strm->next_in if we use it as window */
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
+		  version, stream_size)
+    z_streamp strm;
+    int  level;
+    int  method;
+    int  windowBits;
+    int  memLevel;
+    int  strategy;
+    const char *version;
+    int stream_size;
+{
+    deflate_state *s;
+    int noheader = 0;
+    static const char* my_version = ZLIB_VERSION;
+
+    ushf *overlay;
+    /* We overlay pending_buf and d_buf+l_buf. This works since the average
+     * output size for (length,distance) codes is <= 24 bits.
+     */
+
+    if (version == Z_NULL || version[0] != my_version[0] ||
+        stream_size != sizeof(z_stream)) {
+	return Z_VERSION_ERROR;
+    }
+    if (strm == Z_NULL) return Z_STREAM_ERROR;
+
+    strm->msg = Z_NULL;
+    if (strm->zalloc == Z_NULL) {
+	strm->zalloc = zcalloc;
+	strm->opaque = (voidpf)0;
+    }
+    if (strm->zfree == Z_NULL) strm->zfree = zcfree;
+
+    if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#ifdef FASTEST
+    level = 1;
+#endif
+
+    if (windowBits < 0) { /* undocumented feature: suppress zlib header */
+        noheader = 1;
+        windowBits = -windowBits;
+    }
+    if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
+        windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
+	strategy < 0 || strategy > Z_HUFFMAN_ONLY) {
+        return Z_STREAM_ERROR;
+    }
+    s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
+    if (s == Z_NULL) return Z_MEM_ERROR;
+    strm->state = (struct internal_state FAR *)s;
+    s->strm = strm;
+
+    s->noheader = noheader;
+    s->w_bits = windowBits;
+    s->w_size = 1 << s->w_bits;
+    s->w_mask = s->w_size - 1;
+
+    s->hash_bits = memLevel + 7;
+    s->hash_size = 1 << s->hash_bits;
+    s->hash_mask = s->hash_size - 1;
+    s->hash_shift =  ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);
+
+    s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
+    s->prev   = (Posf *)  ZALLOC(strm, s->w_size, sizeof(Pos));
+    s->head   = (Posf *)  ZALLOC(strm, s->hash_size, sizeof(Pos));
+
+    s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
+
+    overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
+    s->pending_buf = (uchf *) overlay;
+    s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);
+
+    if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
+        s->pending_buf == Z_NULL) {
+        strm->msg = (char*)ERR_MSG(Z_MEM_ERROR);
+        deflateEnd (strm);
+        return Z_MEM_ERROR;
+    }
+    s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
+    s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
+
+    s->level = level;
+    s->strategy = strategy;
+    s->method = (Byte)method;
+
+    return deflateReset(strm);
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
+    z_streamp strm;
+    const Bytef *dictionary;
+    uInt  dictLength;
+{
+    deflate_state *s;
+    uInt length = dictLength;
+    uInt n;
+    IPos hash_head = 0;
+
+    if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL ||
+        strm->state->status != INIT_STATE) return Z_STREAM_ERROR;
+
+    s = strm->state;
+    strm->adler = adler32(strm->adler, dictionary, dictLength);
+
+    if (length < MIN_MATCH) return Z_OK;
+    if (length > MAX_DIST(s)) {
+	length = MAX_DIST(s);
+#ifndef USE_DICT_HEAD
+	dictionary += dictLength - length; /* use the tail of the dictionary */
+#endif
+    }
+    zmemcpy(s->window, dictionary, length);
+    s->strstart = length;
+    s->block_start = (long)length;
+
+    /* Insert all strings in the hash table (except for the last two bytes).
+     * s->lookahead stays null, so s->ins_h will be recomputed at the next
+     * call of fill_window.
+     */
+    s->ins_h = s->window[0];
+    UPDATE_HASH(s, s->ins_h, s->window[1]);
+    for (n = 0; n <= length - MIN_MATCH; n++) {
+	INSERT_STRING(s, n, hash_head);
+    }
+    if (hash_head) hash_head = 0;  /* to make compiler happy */
+    return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateReset (strm)
+    z_streamp strm;
+{
+    deflate_state *s;
+    
+    if (strm == Z_NULL || strm->state == Z_NULL ||
+        strm->zalloc == Z_NULL || strm->zfree == Z_NULL) return Z_STREAM_ERROR;
+
+    strm->total_in = strm->total_out = 0;
+    strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */
+    strm->data_type = Z_UNKNOWN;
+
+    s = (deflate_state *)strm->state;
+    s->pending = 0;
+    s->pending_out = s->pending_buf;
+
+    if (s->noheader < 0) {
+        s->noheader = 0; /* was set to -1 by deflate(..., Z_FINISH); */
+    }
+    s->status = s->noheader ? BUSY_STATE : INIT_STATE;
+    strm->adler = 1;
+    s->last_flush = Z_NO_FLUSH;
+
+    _tr_init(s);
+    lm_init(s);
+
+    return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateParams(strm, level, strategy)
+    z_streamp strm;
+    int level;
+    int strategy;
+{
+    deflate_state *s;
+    compress_func func;
+    int err = Z_OK;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    s = strm->state;
+
+    if (level == Z_DEFAULT_COMPRESSION) {
+	level = 6;
+    }
+    if (level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) {
+	return Z_STREAM_ERROR;
+    }
+    func = configuration_table[s->level].func;
+
+    if (func != configuration_table[level].func && strm->total_in != 0) {
+	/* Flush the last buffer: */
+	err = deflate(strm, Z_PARTIAL_FLUSH);
+    }
+    if (s->level != level) {
+	s->level = level;
+	s->max_lazy_match   = configuration_table[level].max_lazy;
+	s->good_match       = configuration_table[level].good_length;
+	s->nice_match       = configuration_table[level].nice_length;
+	s->max_chain_length = configuration_table[level].max_chain;
+    }
+    s->strategy = strategy;
+    return err;
+}
+
+/* =========================================================================
+ * Put a short in the pending buffer. The 16-bit value is put in MSB order.
+ * IN assertion: the stream state is correct and there is enough room in
+ * pending_buf.
+ */
+local void putShortMSB (s, b)
+    deflate_state *s;
+    uInt b;
+{
+    put_byte(s, (Byte)(b >> 8));
+    put_byte(s, (Byte)(b & 0xff));
+}   
+
+/* =========================================================================
+ * Flush as much pending output as possible. All deflate() output goes
+ * through this function so some applications may wish to modify it
+ * to avoid allocating a large strm->next_out buffer and copying into it.
+ * (See also read_buf()).
+ */
+local void flush_pending(strm)
+    z_streamp strm;
+{
+    unsigned len = strm->state->pending;
+
+    if (len > strm->avail_out) len = strm->avail_out;
+    if (len == 0) return;
+
+    zmemcpy(strm->next_out, strm->state->pending_out, len);
+    strm->next_out  += len;
+    strm->state->pending_out  += len;
+    strm->total_out += len;
+    strm->avail_out  -= len;
+    strm->state->pending -= len;
+    if (strm->state->pending == 0) {
+        strm->state->pending_out = strm->state->pending_buf;
+    }
+}
+
+/* ========================================================================= */
+int ZEXPORT deflate (strm, flush)
+    z_streamp strm;
+    int flush;
+{
+    int old_flush; /* value of flush param for previous deflate call */
+    deflate_state *s;
+
+    if (strm == Z_NULL || strm->state == Z_NULL ||
+	flush > Z_FINISH || flush < 0) {
+        return Z_STREAM_ERROR;
+    }
+    s = strm->state;
+
+    if (strm->next_out == Z_NULL ||
+        (strm->next_in == Z_NULL && strm->avail_in != 0) ||
+	(s->status == FINISH_STATE && flush != Z_FINISH)) {
+        ERR_RETURN(strm, Z_STREAM_ERROR);
+    }
+    if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);
+
+    s->strm = strm; /* just in case */
+    old_flush = s->last_flush;
+    s->last_flush = flush;
+
+    /* Write the zlib header */
+    if (s->status == INIT_STATE) {
+
+        uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
+        uInt level_flags = (s->level-1) >> 1;
+
+        if (level_flags > 3) level_flags = 3;
+        header |= (level_flags << 6);
+	if (s->strstart != 0) header |= PRESET_DICT;
+        header += 31 - (header % 31);
+
+        s->status = BUSY_STATE;
+        putShortMSB(s, header);
+
+	/* Save the adler32 of the preset dictionary: */
+	if (s->strstart != 0) {
+	    putShortMSB(s, (uInt)(strm->adler >> 16));
+	    putShortMSB(s, (uInt)(strm->adler & 0xffff));
+	}
+	strm->adler = 1L;
+    }
+
+    /* Flush as much pending output as possible */
+    if (s->pending != 0) {
+        flush_pending(strm);
+        if (strm->avail_out == 0) {
+	    /* Since avail_out is 0, deflate will be called again with
+	     * more output space, but possibly with both pending and
+	     * avail_in equal to zero. There won't be anything to do,
+	     * but this is not an error situation so make sure we
+	     * return OK instead of BUF_ERROR at next call of deflate:
+             */
+	    s->last_flush = -1;
+	    return Z_OK;
+	}
+
+    /* Make sure there is something to do and avoid duplicate consecutive
+     * flushes. For repeated and useless calls with Z_FINISH, we keep
+     * returning Z_STREAM_END instead of Z_BUFF_ERROR.
+     */
+    } else if (strm->avail_in == 0 && flush <= old_flush &&
+	       flush != Z_FINISH) {
+        ERR_RETURN(strm, Z_BUF_ERROR);
+    }
+
+    /* User must not provide more input after the first FINISH: */
+    if (s->status == FINISH_STATE && strm->avail_in != 0) {
+        ERR_RETURN(strm, Z_BUF_ERROR);
+    }
+
+    /* Start a new block or continue the current one.
+     */
+    if (strm->avail_in != 0 || s->lookahead != 0 ||
+        (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
+        block_state bstate;
+
+	bstate = (*(configuration_table[s->level].func))(s, flush);
+
+        if (bstate == finish_started || bstate == finish_done) {
+            s->status = FINISH_STATE;
+        }
+        if (bstate == need_more || bstate == finish_started) {
+	    if (strm->avail_out == 0) {
+	        s->last_flush = -1; /* avoid BUF_ERROR next call, see above */
+	    }
+	    return Z_OK;
+	    /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
+	     * of deflate should use the same flush parameter to make sure
+	     * that the flush is complete. So we don't have to output an
+	     * empty block here, this will be done at next call. This also
+	     * ensures that for a very small output buffer, we emit at most
+	     * one empty block.
+	     */
+	}
+        if (bstate == block_done) {
+            if (flush == Z_PARTIAL_FLUSH) {
+                _tr_align(s);
+            } else { /* FULL_FLUSH or SYNC_FLUSH */
+                _tr_stored_block(s, (char*)0, 0L, 0);
+                /* For a full flush, this empty block will be recognized
+                 * as a special marker by inflate_sync().
+                 */
+                if (flush == Z_FULL_FLUSH) {
+                    CLEAR_HASH(s);             /* forget history */
+                }
+            }
+            flush_pending(strm);
+	    if (strm->avail_out == 0) {
+	      s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */
+	      return Z_OK;
+	    }
+        }
+    }
+    Assert(strm->avail_out > 0, "bug2");
+
+    if (flush != Z_FINISH) return Z_OK;
+    if (s->noheader) return Z_STREAM_END;
+
+    /* Write the zlib trailer (adler32) */
+    putShortMSB(s, (uInt)(strm->adler >> 16));
+    putShortMSB(s, (uInt)(strm->adler & 0xffff));
+    flush_pending(strm);
+    /* If avail_out is zero, the application will call deflate again
+     * to flush the rest.
+     */
+    s->noheader = -1; /* write the trailer only once! */
+    return s->pending != 0 ? Z_OK : Z_STREAM_END;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateEnd (strm)
+    z_streamp strm;
+{
+    int status;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+
+    status = strm->state->status;
+    if (status != INIT_STATE && status != BUSY_STATE &&
+	status != FINISH_STATE) {
+      return Z_STREAM_ERROR;
+    }
+
+    /* Deallocate in reverse order of allocations: */
+    TRY_FREE(strm, strm->state->pending_buf);
+    TRY_FREE(strm, strm->state->head);
+    TRY_FREE(strm, strm->state->prev);
+    TRY_FREE(strm, strm->state->window);
+
+    ZFREE(strm, strm->state);
+    strm->state = Z_NULL;
+
+    return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
+}
+
+/* =========================================================================
+ * Copy the source state to the destination state.
+ * To simplify the source, this is not supported for 16-bit MSDOS (which
+ * doesn't have enough memory anyway to duplicate compression states).
+ */
+int ZEXPORT deflateCopy (dest, source)
+    z_streamp dest;
+    z_streamp source;
+{
+#ifdef MAXSEG_64K
+    return Z_STREAM_ERROR;
+#else
+    deflate_state *ds;
+    deflate_state *ss;
+    ushf *overlay;
+
+
+    if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) {
+        return Z_STREAM_ERROR;
+    }
+
+    ss = source->state;
+
+    *dest = *source;
+
+    ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
+    if (ds == Z_NULL) return Z_MEM_ERROR;
+    dest->state = (struct internal_state FAR *) ds;
+    *ds = *ss;
+    ds->strm = dest;
+
+    ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
+    ds->prev   = (Posf *)  ZALLOC(dest, ds->w_size, sizeof(Pos));
+    ds->head   = (Posf *)  ZALLOC(dest, ds->hash_size, sizeof(Pos));
+    overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2);
+    ds->pending_buf = (uchf *) overlay;
+
+    if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
+        ds->pending_buf == Z_NULL) {
+        deflateEnd (dest);
+        return Z_MEM_ERROR;
+    }
+    /* following zmemcpy do not work for 16-bit MSDOS */
+    zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
+    zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos));
+    zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos));
+    zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
+
+    ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
+    ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
+    ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;
+
+    ds->l_desc.dyn_tree = ds->dyn_ltree;
+    ds->d_desc.dyn_tree = ds->dyn_dtree;
+    ds->bl_desc.dyn_tree = ds->bl_tree;
+
+    return Z_OK;
+#endif
+}
+
+/* ===========================================================================
+ * Read a new buffer from the current input stream, update the adler32
+ * and total number of bytes read.  All deflate() input goes through
+ * this function so some applications may wish to modify it to avoid
+ * allocating a large strm->next_in buffer and copying from it.
+ * (See also flush_pending()).
+ */
+local int read_buf(strm, buf, size)
+    z_streamp strm;
+    Bytef *buf;
+    unsigned size;
+{
+    unsigned len = strm->avail_in;
+
+    if (len > size) len = size;
+    if (len == 0) return 0;
+
+    strm->avail_in  -= len;
+
+    if (!strm->state->noheader) {
+        strm->adler = adler32(strm->adler, strm->next_in, len);
+    }
+    zmemcpy(buf, strm->next_in, len);
+    strm->next_in  += len;
+    strm->total_in += len;
+
+    return (int)len;
+}
+
+/* ===========================================================================
+ * Initialize the "longest match" routines for a new zlib stream
+ */
+local void lm_init (s)
+    deflate_state *s;
+{
+    s->window_size = (ulg)2L*s->w_size;
+
+    CLEAR_HASH(s);
+
+    /* Set the default configuration parameters:
+     */
+    s->max_lazy_match   = configuration_table[s->level].max_lazy;
+    s->good_match       = configuration_table[s->level].good_length;
+    s->nice_match       = configuration_table[s->level].nice_length;
+    s->max_chain_length = configuration_table[s->level].max_chain;
+
+    s->strstart = 0;
+    s->block_start = 0L;
+    s->lookahead = 0;
+    s->match_length = s->prev_length = MIN_MATCH-1;
+    s->match_available = 0;
+    s->ins_h = 0;
+#ifdef ASMV
+    match_init(); /* initialize the asm code */
+#endif
+}
+
+/* ===========================================================================
+ * Set match_start to the longest match starting at the given string and
+ * return its length. Matches shorter or equal to prev_length are discarded,
+ * in which case the result is equal to prev_length and match_start is
+ * garbage.
+ * IN assertions: cur_match is the head of the hash chain for the current
+ *   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+ * OUT assertion: the match length is not greater than s->lookahead.
+ */
+#ifndef ASMV
+/* For 80x86 and 680x0, an optimized version will be provided in match.asm or
+ * match.S. The code will be functionally equivalent.
+ */
+#ifndef FASTEST
+local uInt longest_match(s, cur_match)
+    deflate_state *s;
+    IPos cur_match;                             /* current match */
+{
+    unsigned chain_length = s->max_chain_length;/* max hash chain length */
+    register Bytef *scan = s->window + s->strstart; /* current string */
+    register Bytef *match;                       /* matched string */
+    register int len;                           /* length of current match */
+    int best_len = s->prev_length;              /* best match length so far */
+    int nice_match = s->nice_match;             /* stop if match long enough */
+    IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
+        s->strstart - (IPos)MAX_DIST(s) : NIL;
+    /* Stop when cur_match becomes <= limit. To simplify the code,
+     * we prevent matches with the string of window index 0.
+     */
+    Posf *prev = s->prev;
+    uInt wmask = s->w_mask;
+
+#ifdef UNALIGNED_OK
+    /* Compare two bytes at a time. Note: this is not always beneficial.
+     * Try with and without -DUNALIGNED_OK to check.
+     */
+    register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
+    register ush scan_start = *(ushf*)scan;
+    register ush scan_end   = *(ushf*)(scan+best_len-1);
+#else
+    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+    register Byte scan_end1  = scan[best_len-1];
+    register Byte scan_end   = scan[best_len];
+#endif
+
+    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+     * It is easy to get rid of this optimization if necessary.
+     */
+    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+    /* Do not waste too much time if we already have a good match: */
+    if (s->prev_length >= s->good_match) {
+        chain_length >>= 2;
+    }
+    /* Do not look for matches beyond the end of the input. This is necessary
+     * to make deflate deterministic.
+     */
+    if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
+
+    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+    do {
+        Assert(cur_match < s->strstart, "no future");
+        match = s->window + cur_match;
+
+        /* Skip to next match if the match length cannot increase
+         * or if the match length is less than 2:
+         */
+#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
+        /* This code assumes sizeof(unsigned short) == 2. Do not use
+         * UNALIGNED_OK if your compiler uses a different size.
+         */
+        if (*(ushf*)(match+best_len-1) != scan_end ||
+            *(ushf*)match != scan_start) continue;
+
+        /* It is not necessary to compare scan[2] and match[2] since they are
+         * always equal when the other bytes match, given that the hash keys
+         * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
+         * strstart+3, +5, ... up to strstart+257. We check for insufficient
+         * lookahead only every 4th comparison; the 128th check will be made
+         * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
+         * necessary to put more guard bytes at the end of the window, or
+         * to check more often for insufficient lookahead.
+         */
+        Assert(scan[2] == match[2], "scan[2]?");
+        scan++, match++;
+        do {
+        } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 scan < strend);
+        /* The funny "do {}" generates better code on most compilers */
+
+        /* Here, scan <= window+strstart+257 */
+        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+        if (*scan == *match) scan++;
+
+        len = (MAX_MATCH - 1) - (int)(strend-scan);
+        scan = strend - (MAX_MATCH-1);
+
+#else /* UNALIGNED_OK */
+
+        if (match[best_len]   != scan_end  ||
+            match[best_len-1] != scan_end1 ||
+            *match            != *scan     ||
+            *++match          != scan[1])      continue;
+
+        /* The check at best_len-1 can be removed because it will be made
+         * again later. (This heuristic is not always a win.)
+         * It is not necessary to compare scan[2] and match[2] since they
+         * are always equal when the other bytes match, given that
+         * the hash keys are equal and that HASH_BITS >= 8.
+         */
+        scan += 2, match++;
+        Assert(*scan == *match, "match[2]?");
+
+        /* We check for insufficient lookahead only every 8th comparison;
+         * the 256th check will be made at strstart+258.
+         */
+        do {
+        } while (*++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 scan < strend);
+
+        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+        len = MAX_MATCH - (int)(strend - scan);
+        scan = strend - MAX_MATCH;
+
+#endif /* UNALIGNED_OK */
+
+        if (len > best_len) {
+            s->match_start = cur_match;
+            best_len = len;
+            if (len >= nice_match) break;
+#ifdef UNALIGNED_OK
+            scan_end = *(ushf*)(scan+best_len-1);
+#else
+            scan_end1  = scan[best_len-1];
+            scan_end   = scan[best_len];
+#endif
+        }
+    } while ((cur_match = prev[cur_match & wmask]) > limit
+             && --chain_length != 0);
+
+    if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
+    return s->lookahead;
+}
+
+#else /* FASTEST */
+/* ---------------------------------------------------------------------------
+ * Optimized version for level == 1 only
+ */
+local uInt longest_match(s, cur_match)
+    deflate_state *s;
+    IPos cur_match;                             /* current match */
+{
+    register Bytef *scan = s->window + s->strstart; /* current string */
+    register Bytef *match;                       /* matched string */
+    register int len;                           /* length of current match */
+    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+
+    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+     * It is easy to get rid of this optimization if necessary.
+     */
+    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+    Assert(cur_match < s->strstart, "no future");
+
+    match = s->window + cur_match;
+
+    /* Return failure if the match length is less than 2:
+     */
+    if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1;
+
+    /* The check at best_len-1 can be removed because it will be made
+     * again later. (This heuristic is not always a win.)
+     * It is not necessary to compare scan[2] and match[2] since they
+     * are always equal when the other bytes match, given that
+     * the hash keys are equal and that HASH_BITS >= 8.
+     */
+    scan += 2, match += 2;
+    Assert(*scan == *match, "match[2]?");
+
+    /* We check for insufficient lookahead only every 8th comparison;
+     * the 256th check will be made at strstart+258.
+     */
+    do {
+    } while (*++scan == *++match && *++scan == *++match &&
+	     *++scan == *++match && *++scan == *++match &&
+	     *++scan == *++match && *++scan == *++match &&
+	     *++scan == *++match && *++scan == *++match &&
+	     scan < strend);
+
+    Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+    len = MAX_MATCH - (int)(strend - scan);
+
+    if (len < MIN_MATCH) return MIN_MATCH - 1;
+
+    s->match_start = cur_match;
+    return len <= s->lookahead ? len : s->lookahead;
+}
+#endif /* FASTEST */
+#endif /* ASMV */
+
+#ifdef DEBUG
+/* ===========================================================================
+ * Check that the match at match_start is indeed a match.
+ */
+local void check_match(s, start, match, length)
+    deflate_state *s;
+    IPos start, match;
+    int length;
+{
+    /* check that the match is indeed a match */
+    if (zmemcmp(s->window + match,
+                s->window + start, length) != EQUAL) {
+        fprintf(stderr, " start %u, match %u, length %d\n",
+		start, match, length);
+        do {
+	    fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
+	} while (--length != 0);
+        z_error("invalid match");
+    }
+    if (z_verbose > 1) {
+        fprintf(stderr,"\\[%d,%d]", start-match, length);
+        do { putc(s->window[start++], stderr); } while (--length != 0);
+    }
+}
+#else
+#  define check_match(s, start, match, length)
+#endif
+
+/* ===========================================================================
+ * Fill the window when the lookahead becomes insufficient.
+ * Updates strstart and lookahead.
+ *
+ * IN assertion: lookahead < MIN_LOOKAHEAD
+ * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ *    At least one byte has been read, or avail_in == 0; reads are
+ *    performed for at least two bytes (required for the zip translate_eol
+ *    option -- not supported here).
+ */
+local void fill_window(s)
+    deflate_state *s;
+{
+    register unsigned n, m;
+    register Posf *p;
+    unsigned more;    /* Amount of free space at the end of the window. */
+    uInt wsize = s->w_size;
+
+    do {
+        more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
+
+        /* Deal with !@#$% 64K limit: */
+        if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
+            more = wsize;
+
+        } else if (more == (unsigned)(-1)) {
+            /* Very unlikely, but possible on 16 bit machine if strstart == 0
+             * and lookahead == 1 (input done one byte at time)
+             */
+            more--;
+
+        /* If the window is almost full and there is insufficient lookahead,
+         * move the upper half to the lower one to make room in the upper half.
+         */
+        } else if (s->strstart >= wsize+MAX_DIST(s)) {
+
+            zmemcpy(s->window, s->window+wsize, (unsigned)wsize);
+            s->match_start -= wsize;
+            s->strstart    -= wsize; /* we now have strstart >= MAX_DIST */
+            s->block_start -= (long) wsize;
+
+            /* Slide the hash table (could be avoided with 32 bit values
+               at the expense of memory usage). We slide even when level == 0
+               to keep the hash table consistent if we switch back to level > 0
+               later. (Using level 0 permanently is not an optimal usage of
+               zlib, so we don't care about this pathological case.)
+             */
+	    n = s->hash_size;
+	    p = &s->head[n];
+	    do {
+		m = *--p;
+		*p = (Pos)(m >= wsize ? m-wsize : NIL);
+	    } while (--n);
+
+	    n = wsize;
+#ifndef FASTEST
+	    p = &s->prev[n];
+	    do {
+		m = *--p;
+		*p = (Pos)(m >= wsize ? m-wsize : NIL);
+		/* If n is not on any hash chain, prev[n] is garbage but
+		 * its value will never be used.
+		 */
+	    } while (--n);
+#endif
+            more += wsize;
+        }
+        if (s->strm->avail_in == 0) return;
+
+        /* If there was no sliding:
+         *    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+         *    more == window_size - lookahead - strstart
+         * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+         * => more >= window_size - 2*WSIZE + 2
+         * In the BIG_MEM or MMAP case (not yet supported),
+         *   window_size == input_size + MIN_LOOKAHEAD  &&
+         *   strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+         * Otherwise, window_size == 2*WSIZE so more >= 2.
+         * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+         */
+        Assert(more >= 2, "more < 2");
+
+        n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
+        s->lookahead += n;
+
+        /* Initialize the hash value now that we have some input: */
+        if (s->lookahead >= MIN_MATCH) {
+            s->ins_h = s->window[s->strstart];
+            UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+            Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+        }
+        /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+         * but this is not important since only literal bytes will be emitted.
+         */
+
+    } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
+}
+
+/* ===========================================================================
+ * Flush the current block, with given end-of-file flag.
+ * IN assertion: strstart is set to the end of the current match.
+ */
+#define FLUSH_BLOCK_ONLY(s, eof) { \
+   _tr_flush_block(s, (s->block_start >= 0L ? \
+                   (charf *)&s->window[(unsigned)s->block_start] : \
+                   (charf *)Z_NULL), \
+		(ulg)((long)s->strstart - s->block_start), \
+		(eof)); \
+   s->block_start = s->strstart; \
+   flush_pending(s->strm); \
+   Tracev((stderr,"[FLUSH]")); \
+}
+
+/* Same but force premature exit if necessary. */
+#define FLUSH_BLOCK(s, eof) { \
+   FLUSH_BLOCK_ONLY(s, eof); \
+   if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \
+}
+
+/* ===========================================================================
+ * Copy without compression as much as possible from the input stream, return
+ * the current block state.
+ * This function does not insert new strings in the dictionary since
+ * uncompressible data is probably not useful. This function is used
+ * only for the level=0 compression option.
+ * NOTE: this function should be optimized to avoid extra copying from
+ * window to pending_buf.
+ */
+local block_state deflate_stored(s, flush)
+    deflate_state *s;
+    int flush;
+{
+    /* Stored blocks are limited to 0xffff bytes, pending_buf is limited
+     * to pending_buf_size, and each stored block has a 5 byte header:
+     */
+    ulg max_block_size = 0xffff;
+    ulg max_start;
+
+    if (max_block_size > s->pending_buf_size - 5) {
+        max_block_size = s->pending_buf_size - 5;
+    }
+
+    /* Copy as much as possible from input to output: */
+    for (;;) {
+        /* Fill the window as much as possible: */
+        if (s->lookahead <= 1) {
+
+            Assert(s->strstart < s->w_size+MAX_DIST(s) ||
+		   s->block_start >= (long)s->w_size, "slide too late");
+
+            fill_window(s);
+            if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more;
+
+            if (s->lookahead == 0) break; /* flush the current block */
+        }
+	Assert(s->block_start >= 0L, "block gone");
+
+	s->strstart += s->lookahead;
+	s->lookahead = 0;
+
+	/* Emit a stored block if pending_buf will be full: */
+ 	max_start = s->block_start + max_block_size;
+        if (s->strstart == 0 || (ulg)s->strstart >= max_start) {
+	    /* strstart == 0 is possible when wraparound on 16-bit machine */
+	    s->lookahead = (uInt)(s->strstart - max_start);
+	    s->strstart = (uInt)max_start;
+            FLUSH_BLOCK(s, 0);
+	}
+	/* Flush if we may have to slide, otherwise block_start may become
+         * negative and the data will be gone:
+         */
+        if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) {
+            FLUSH_BLOCK(s, 0);
+	}
+    }
+    FLUSH_BLOCK(s, flush == Z_FINISH);
+    return flush == Z_FINISH ? finish_done : block_done;
+}
+
+/* ===========================================================================
+ * Compress as much as possible from the input stream, return the current
+ * block state.
+ * This function does not perform lazy evaluation of matches and inserts
+ * new strings in the dictionary only for unmatched strings or for short
+ * matches. It is used only for the fast compression options.
+ */
+local block_state deflate_fast(s, flush)
+    deflate_state *s;
+    int flush;
+{
+    IPos hash_head = NIL; /* head of the hash chain */
+    int bflush;           /* set if current block must be flushed */
+
+    for (;;) {
+        /* Make sure that we always have enough lookahead, except
+         * at the end of the input file. We need MAX_MATCH bytes
+         * for the next match, plus MIN_MATCH bytes to insert the
+         * string following the next match.
+         */
+        if (s->lookahead < MIN_LOOKAHEAD) {
+            fill_window(s);
+            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+	        return need_more;
+	    }
+            if (s->lookahead == 0) break; /* flush the current block */
+        }
+
+        /* Insert the string window[strstart .. strstart+2] in the
+         * dictionary, and set hash_head to the head of the hash chain:
+         */
+        if (s->lookahead >= MIN_MATCH) {
+            INSERT_STRING(s, s->strstart, hash_head);
+        }
+
+        /* Find the longest match, discarding those <= prev_length.
+         * At this point we have always match_length < MIN_MATCH
+         */
+        if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
+            /* To simplify the code, we prevent matches with the string
+             * of window index 0 (in particular we have to avoid a match
+             * of the string with itself at the start of the input file).
+             */
+            if (s->strategy != Z_HUFFMAN_ONLY) {
+                s->match_length = longest_match (s, hash_head);
+            }
+            /* longest_match() sets match_start */
+        }
+        if (s->match_length >= MIN_MATCH) {
+            check_match(s, s->strstart, s->match_start, s->match_length);
+
+            _tr_tally_dist(s, s->strstart - s->match_start,
+                           s->match_length - MIN_MATCH, bflush);
+
+            s->lookahead -= s->match_length;
+
+            /* Insert new strings in the hash table only if the match length
+             * is not too large. This saves time but degrades compression.
+             */
+#ifndef FASTEST
+            if (s->match_length <= s->max_insert_length &&
+                s->lookahead >= MIN_MATCH) {
+                s->match_length--; /* string at strstart already in hash table */
+                do {
+                    s->strstart++;
+                    INSERT_STRING(s, s->strstart, hash_head);
+                    /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+                     * always MIN_MATCH bytes ahead.
+                     */
+                } while (--s->match_length != 0);
+                s->strstart++; 
+            } else
+#endif
+	    {
+                s->strstart += s->match_length;
+                s->match_length = 0;
+                s->ins_h = s->window[s->strstart];
+                UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+                Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+                /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+                 * matter since it will be recomputed at next deflate call.
+                 */
+            }
+        } else {
+            /* No match, output a literal byte */
+            Tracevv((stderr,"%c", s->window[s->strstart]));
+            _tr_tally_lit (s, s->window[s->strstart], bflush);
+            s->lookahead--;
+            s->strstart++; 
+        }
+        if (bflush) FLUSH_BLOCK(s, 0);
+    }
+    FLUSH_BLOCK(s, flush == Z_FINISH);
+    return flush == Z_FINISH ? finish_done : block_done;
+}
+
+/* ===========================================================================
+ * Same as above, but achieves better compression. We use a lazy
+ * evaluation for matches: a match is finally adopted only if there is
+ * no better match at the next window position.
+ */
+local block_state deflate_slow(s, flush)
+    deflate_state *s;
+    int flush;
+{
+    IPos hash_head = NIL;    /* head of hash chain */
+    int bflush;              /* set if current block must be flushed */
+
+    /* Process the input block. */
+    for (;;) {
+        /* Make sure that we always have enough lookahead, except
+         * at the end of the input file. We need MAX_MATCH bytes
+         * for the next match, plus MIN_MATCH bytes to insert the
+         * string following the next match.
+         */
+        if (s->lookahead < MIN_LOOKAHEAD) {
+            fill_window(s);
+            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+	        return need_more;
+	    }
+            if (s->lookahead == 0) break; /* flush the current block */
+        }
+
+        /* Insert the string window[strstart .. strstart+2] in the
+         * dictionary, and set hash_head to the head of the hash chain:
+         */
+        if (s->lookahead >= MIN_MATCH) {
+            INSERT_STRING(s, s->strstart, hash_head);
+        }
+
+        /* Find the longest match, discarding those <= prev_length.
+         */
+        s->prev_length = s->match_length, s->prev_match = s->match_start;
+        s->match_length = MIN_MATCH-1;
+
+        if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
+            s->strstart - hash_head <= MAX_DIST(s)) {
+            /* To simplify the code, we prevent matches with the string
+             * of window index 0 (in particular we have to avoid a match
+             * of the string with itself at the start of the input file).
+             */
+            if (s->strategy != Z_HUFFMAN_ONLY) {
+                s->match_length = longest_match (s, hash_head);
+            }
+            /* longest_match() sets match_start */
+
+            if (s->match_length <= 5 && (s->strategy == Z_FILTERED ||
+                 (s->match_length == MIN_MATCH &&
+                  s->strstart - s->match_start > TOO_FAR))) {
+
+                /* If prev_match is also MIN_MATCH, match_start is garbage
+                 * but we will ignore the current match anyway.
+                 */
+                s->match_length = MIN_MATCH-1;
+            }
+        }
+        /* If there was a match at the previous step and the current
+         * match is not better, output the previous match:
+         */
+        if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
+            uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
+            /* Do not insert strings in hash table beyond this. */
+
+            check_match(s, s->strstart-1, s->prev_match, s->prev_length);
+
+            _tr_tally_dist(s, s->strstart -1 - s->prev_match,
+			   s->prev_length - MIN_MATCH, bflush);
+
+            /* Insert in hash table all strings up to the end of the match.
+             * strstart-1 and strstart are already inserted. If there is not
+             * enough lookahead, the last two strings are not inserted in
+             * the hash table.
+             */
+            s->lookahead -= s->prev_length-1;
+            s->prev_length -= 2;
+            do {
+                if (++s->strstart <= max_insert) {
+                    INSERT_STRING(s, s->strstart, hash_head);
+                }
+            } while (--s->prev_length != 0);
+            s->match_available = 0;
+            s->match_length = MIN_MATCH-1;
+            s->strstart++;
+
+            if (bflush) FLUSH_BLOCK(s, 0);
+
+        } else if (s->match_available) {
+            /* If there was no match at the previous position, output a
+             * single literal. If there was a match but the current match
+             * is longer, truncate the previous match to a single literal.
+             */
+            Tracevv((stderr,"%c", s->window[s->strstart-1]));
+	    _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+	    if (bflush) {
+                FLUSH_BLOCK_ONLY(s, 0);
+            }
+            s->strstart++;
+            s->lookahead--;
+            if (s->strm->avail_out == 0) return need_more;
+        } else {
+            /* There is no previous match to compare with, wait for
+             * the next step to decide.
+             */
+            s->match_available = 1;
+            s->strstart++;
+            s->lookahead--;
+        }
+    }
+    Assert (flush != Z_NO_FLUSH, "no flush?");
+    if (s->match_available) {
+        Tracevv((stderr,"%c", s->window[s->strstart-1]));
+        _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+        s->match_available = 0;
+    }
+    FLUSH_BLOCK(s, flush == Z_FINISH);
+    return flush == Z_FINISH ? finish_done : block_done;
+}
diff --git a/Utilities/ITK/Utilities/zlib/deflate.h b/Utilities/ITK/Utilities/zlib/deflate.h
new file mode 100644
index 0000000000..1283904f6b
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/deflate.h
@@ -0,0 +1,318 @@
+/* deflate.h -- internal compression state
+ * Copyright (C) 1995-1998 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id$ */
+
+#ifndef _DEFLATE_H
+#define _DEFLATE_H
+
+#include "zutil.h"
+
+/* ===========================================================================
+ * Internal compression state.
+ */
+
+#define LENGTH_CODES 29
+/* number of length codes, not counting the special END_BLOCK code */
+
+#define LITERALS  256
+/* number of literal bytes 0..255 */
+
+#define L_CODES (LITERALS+1+LENGTH_CODES)
+/* number of Literal or Length codes, including the END_BLOCK code */
+
+#define D_CODES   30
+/* number of distance codes */
+
+#define BL_CODES  19
+/* number of codes used to transfer the bit lengths */
+
+#define HEAP_SIZE (2*L_CODES+1)
+/* maximum heap size */
+
+#define MAX_BITS 15
+/* All codes must not exceed MAX_BITS bits */
+
+#define INIT_STATE    42
+#define BUSY_STATE   113
+#define FINISH_STATE 666
+/* Stream status */
+
+
+/* Data structure describing a single value and its code string. */
+typedef struct ct_data_s {
+    union {
+        ush  freq;       /* frequency count */
+        ush  code;       /* bit string */
+    } fc;
+    union {
+        ush  dad;        /* father node in Huffman tree */
+        ush  len;        /* length of bit string */
+    } dl;
+} FAR ct_data;
+
+#define Freq fc.freq
+#define Code fc.code
+#define Dad  dl.dad
+#define Len  dl.len
+
+typedef struct static_tree_desc_s  static_tree_desc;
+
+typedef struct tree_desc_s {
+    ct_data *dyn_tree;           /* the dynamic tree */
+    int     max_code;            /* largest code with non zero frequency */
+    static_tree_desc *stat_desc; /* the corresponding static tree */
+} FAR tree_desc;
+
+typedef ush Pos;
+typedef Pos FAR Posf;
+typedef unsigned IPos;
+
+/* A Pos is an index in the character window. We use short instead of int to
+ * save space in the various tables. IPos is used only for parameter passing.
+ */
+
+typedef struct internal_state {
+    z_streamp strm;      /* pointer back to this zlib stream */
+    int   status;        /* as the name implies */
+    Bytef *pending_buf;  /* output still pending */
+    ulg   pending_buf_size; /* size of pending_buf */
+    Bytef *pending_out;  /* next pending byte to output to the stream */
+    int   pending;       /* nb of bytes in the pending buffer */
+    int   noheader;      /* suppress zlib header and adler32 */
+    Byte  data_type;     /* UNKNOWN, BINARY or ASCII */
+    Byte  method;        /* STORED (for zip only) or DEFLATED */
+    int   last_flush;    /* value of flush param for previous deflate call */
+
+                /* used by deflate.c: */
+
+    uInt  w_size;        /* LZ77 window size (32K by default) */
+    uInt  w_bits;        /* log2(w_size)  (8..16) */
+    uInt  w_mask;        /* w_size - 1 */
+
+    Bytef *window;
+    /* Sliding window. Input bytes are read into the second half of the window,
+     * and move to the first half later to keep a dictionary of at least wSize
+     * bytes. With this organization, matches are limited to a distance of
+     * wSize-MAX_MATCH bytes, but this ensures that IO is always
+     * performed with a length multiple of the block size. Also, it limits
+     * the window size to 64K, which is quite useful on MSDOS.
+     * To do: use the user input buffer as sliding window.
+     */
+
+    ulg window_size;
+    /* Actual size of window: 2*wSize, except when the user input buffer
+     * is directly used as sliding window.
+     */
+
+    Posf *prev;
+    /* Link to older string with same hash index. To limit the size of this
+     * array to 64K, this link is maintained only for the last 32K strings.
+     * An index in this array is thus a window index modulo 32K.
+     */
+
+    Posf *head; /* Heads of the hash chains or NIL. */
+
+    uInt  ins_h;          /* hash index of string to be inserted */
+    uInt  hash_size;      /* number of elements in hash table */
+    uInt  hash_bits;      /* log2(hash_size) */
+    uInt  hash_mask;      /* hash_size-1 */
+
+    uInt  hash_shift;
+    /* Number of bits by which ins_h must be shifted at each input
+     * step. It must be such that after MIN_MATCH steps, the oldest
+     * byte no longer takes part in the hash key, that is:
+     *   hash_shift * MIN_MATCH >= hash_bits
+     */
+
+    long block_start;
+    /* Window position at the beginning of the current output block. Gets
+     * negative when the window is moved backwards.
+     */
+
+    uInt match_length;           /* length of best match */
+    IPos prev_match;             /* previous match */
+    int match_available;         /* set if previous match exists */
+    uInt strstart;               /* start of string to insert */
+    uInt match_start;            /* start of matching string */
+    uInt lookahead;              /* number of valid bytes ahead in window */
+
+    uInt prev_length;
+    /* Length of the best match at previous step. Matches not greater than this
+     * are discarded. This is used in the lazy match evaluation.
+     */
+
+    uInt max_chain_length;
+    /* To speed up deflation, hash chains are never searched beyond this
+     * length.  A higher limit improves compression ratio but degrades the
+     * speed.
+     */
+
+    uInt max_lazy_match;
+    /* Attempt to find a better match only when the current match is strictly
+     * smaller than this value. This mechanism is used only for compression
+     * levels >= 4.
+     */
+#   define max_insert_length  max_lazy_match
+    /* Insert new strings in the hash table only if the match length is not
+     * greater than this length. This saves time but degrades compression.
+     * max_insert_length is used only for compression levels <= 3.
+     */
+
+    int level;    /* compression level (1..9) */
+    int strategy; /* favor or force Huffman coding*/
+
+    uInt good_match;
+    /* Use a faster search when the previous match is longer than this */
+
+    int nice_match; /* Stop searching when current match exceeds this */
+
+                /* used by trees.c: */
+    /* Didn't use ct_data typedef below to supress compiler warning */
+    struct ct_data_s dyn_ltree[HEAP_SIZE];   /* literal and length tree */
+    struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
+    struct ct_data_s bl_tree[2*BL_CODES+1];  /* Huffman tree for bit lengths */
+
+    struct tree_desc_s l_desc;               /* desc. for literal tree */
+    struct tree_desc_s d_desc;               /* desc. for distance tree */
+    struct tree_desc_s bl_desc;              /* desc. for bit length tree */
+
+    ush bl_count[MAX_BITS+1];
+    /* number of codes at each bit length for an optimal tree */
+
+    int heap[2*L_CODES+1];      /* heap used to build the Huffman trees */
+    int heap_len;               /* number of elements in the heap */
+    int heap_max;               /* element of largest frequency */
+    /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+     * The same heap array is used to build all trees.
+     */
+
+    uch depth[2*L_CODES+1];
+    /* Depth of each subtree used as tie breaker for trees of equal frequency
+     */
+
+    uchf *l_buf;          /* buffer for literals or lengths */
+
+    uInt  lit_bufsize;
+    /* Size of match buffer for literals/lengths.  There are 4 reasons for
+     * limiting lit_bufsize to 64K:
+     *   - frequencies can be kept in 16 bit counters
+     *   - if compression is not successful for the first block, all input
+     *     data is still in the window so we can still emit a stored block even
+     *     when input comes from standard input.  (This can also be done for
+     *     all blocks if lit_bufsize is not greater than 32K.)
+     *   - if compression is not successful for a file smaller than 64K, we can
+     *     even emit a stored file instead of a stored block (saving 5 bytes).
+     *     This is applicable only for zip (not gzip or zlib).
+     *   - creating new Huffman trees less frequently may not provide fast
+     *     adaptation to changes in the input data statistics. (Take for
+     *     example a binary file with poorly compressible code followed by
+     *     a highly compressible string table.) Smaller buffer sizes give
+     *     fast adaptation but have of course the overhead of transmitting
+     *     trees more frequently.
+     *   - I can't count above 4
+     */
+
+    uInt last_lit;      /* running index in l_buf */
+
+    ushf *d_buf;
+    /* Buffer for distances. To simplify the code, d_buf and l_buf have
+     * the same number of elements. To use different lengths, an extra flag
+     * array would be necessary.
+     */
+
+    ulg opt_len;        /* bit length of current block with optimal trees */
+    ulg static_len;     /* bit length of current block with static trees */
+    uInt matches;       /* number of string matches in current block */
+    int last_eob_len;   /* bit length of EOB code for last block */
+
+#ifdef DEBUG
+    ulg compressed_len; /* total bit length of compressed file mod 2^32 */
+    ulg bits_sent;      /* bit length of compressed data sent mod 2^32 */
+#endif
+
+    ush bi_buf;
+    /* Output buffer. bits are inserted starting at the bottom (least
+     * significant bits).
+     */
+    int bi_valid;
+    /* Number of valid bits in bi_buf.  All bits above the last valid bit
+     * are always zero.
+     */
+
+} FAR deflate_state;
+
+/* Output a byte on the stream.
+ * IN assertion: there is enough room in pending_buf.
+ */
+#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
+
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+#define MAX_DIST(s)  ((s)->w_size-MIN_LOOKAHEAD)
+/* In order to simplify the code, particularly on 16 bit machines, match
+ * distances are limited to MAX_DIST instead of WSIZE.
+ */
+
+        /* in trees.c */
+void _tr_init         OF((deflate_state *s));
+int  _tr_tally        OF((deflate_state *s, unsigned dist, unsigned lc));
+void _tr_flush_block  OF((deflate_state *s, charf *buf, ulg stored_len,
+                          int eof));
+void _tr_align        OF((deflate_state *s));
+void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
+                          int eof));
+
+#define d_code(dist) \
+   ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
+/* Mapping from a distance to a distance code. dist is the distance - 1 and
+ * must not have side effects. _dist_code[256] and _dist_code[257] are never
+ * used.
+ */
+
+#ifndef DEBUG
+/* Inline versions of _tr_tally for speed: */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+  extern uch _length_code[];
+  extern uch _dist_code[];
+#else
+  extern const uch _length_code[];
+  extern const uch _dist_code[];
+#endif
+
+# define _tr_tally_lit(s, c, flush) \
+  { uch cc = (c); \
+    s->d_buf[s->last_lit] = 0; \
+    s->l_buf[s->last_lit++] = cc; \
+    s->dyn_ltree[cc].Freq++; \
+    flush = (s->last_lit == s->lit_bufsize-1); \
+   }
+# define _tr_tally_dist(s, distance, length, flush) \
+  { uch len = (length); \
+    ush dist = (distance); \
+    s->d_buf[s->last_lit] = dist; \
+    s->l_buf[s->last_lit++] = len; \
+    dist--; \
+    s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
+    s->dyn_dtree[d_code(dist)].Freq++; \
+    flush = (s->last_lit == s->lit_bufsize-1); \
+  }
+#else
+# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
+# define _tr_tally_dist(s, distance, length, flush) \
+              flush = _tr_tally(s, distance, length) 
+#endif
+
+#endif
diff --git a/Utilities/ITK/Utilities/zlib/example.c b/Utilities/ITK/Utilities/zlib/example.c
new file mode 100644
index 0000000000..8307c841e4
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/example.c
@@ -0,0 +1,556 @@
+/* example.c -- usage example of the zlib compression library
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* @(#) $Id$ */
+
+#include <stdio.h>
+#include "zlib.h"
+
+#ifdef STDC
+#  include <string.h>
+#  include <stdlib.h>
+#else
+   extern void exit  OF((int));
+#endif
+
+#if defined(VMS) || defined(RISCOS)
+#  define TESTFILE "foo-gz"
+#else
+#  define TESTFILE "foo.gz"
+#endif
+
+#define CHECK_ERR(err, msg) { \
+    if (err != Z_OK) { \
+        fprintf(stderr, "%s error: %d\n", msg, err); \
+        exit(1); \
+    } \
+}
+
+const char hello[] = "hello, hello!";
+/* "hello world" would be more standard, but the repeated "hello"
+ * stresses the compression code better, sorry...
+ */
+
+const char dictionary[] = "hello";
+uLong dictId; /* Adler32 value of the dictionary */
+
+void test_compress      OF((Byte *compr, uLong comprLen,
+		            Byte *uncompr, uLong uncomprLen));
+void test_gzio          OF((const char *out, const char *in, 
+		            Byte *uncompr, int uncomprLen));
+void test_deflate       OF((Byte *compr, uLong comprLen));
+void test_inflate       OF((Byte *compr, uLong comprLen,
+		            Byte *uncompr, uLong uncomprLen));
+void test_large_deflate OF((Byte *compr, uLong comprLen,
+		            Byte *uncompr, uLong uncomprLen));
+void test_large_inflate OF((Byte *compr, uLong comprLen,
+		            Byte *uncompr, uLong uncomprLen));
+void test_flush         OF((Byte *compr, uLong *comprLen));
+void test_sync          OF((Byte *compr, uLong comprLen,
+		            Byte *uncompr, uLong uncomprLen));
+void test_dict_deflate  OF((Byte *compr, uLong comprLen));
+void test_dict_inflate  OF((Byte *compr, uLong comprLen,
+		            Byte *uncompr, uLong uncomprLen));
+int  main               OF((int argc, char *argv[]));
+
+/* ===========================================================================
+ * Test compress() and uncompress()
+ */
+void test_compress(compr, comprLen, uncompr, uncomprLen)
+    Byte *compr, *uncompr;
+    uLong comprLen, uncomprLen;
+{
+    int err;
+    uLong len = strlen(hello)+1;
+
+    err = compress(compr, &comprLen, (const Bytef*)hello, len);
+    CHECK_ERR(err, "compress");
+
+    strcpy((char*)uncompr, "garbage");
+
+    err = uncompress(uncompr, &uncomprLen, compr, comprLen);
+    CHECK_ERR(err, "uncompress");
+
+    if (strcmp((char*)uncompr, hello)) {
+        fprintf(stderr, "bad uncompress\n");
+	exit(1);
+    } else {
+        printf("uncompress(): %s\n", (char *)uncompr);
+    }
+}
+
+/* ===========================================================================
+ * Test read/write of .gz files
+ */
+void test_gzio(out, in, uncompr, uncomprLen)
+    const char *out; /* compressed output file */
+    const char *in;  /* compressed input file */
+    Byte *uncompr;
+    int  uncomprLen;
+{
+    int err;
+    int len = strlen(hello)+1;
+    gzFile file;
+    z_off_t pos;
+
+    file = gzopen(out, "wb");
+    if (file == NULL) {
+        fprintf(stderr, "gzopen error\n");
+        exit(1);
+    }
+    gzputc(file, 'h');
+    if (gzputs(file, "ello") != 4) {
+        fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err));
+	exit(1);
+    }
+    if (gzprintf(file, ", %s!", "hello") != 8) {
+        fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err));
+	exit(1);
+    }
+    gzseek(file, 1L, SEEK_CUR); /* add one zero byte */
+    gzclose(file);
+
+    file = gzopen(in, "rb");
+    if (file == NULL) {
+        fprintf(stderr, "gzopen error\n");
+    }
+    strcpy((char*)uncompr, "garbage");
+
+    uncomprLen = gzread(file, uncompr, (unsigned)uncomprLen);
+    if (uncomprLen != len) {
+        fprintf(stderr, "gzread err: %s\n", gzerror(file, &err));
+	exit(1);
+    }
+    if (strcmp((char*)uncompr, hello)) {
+        fprintf(stderr, "bad gzread: %s\n", (char*)uncompr);
+	exit(1);
+    } else {
+        printf("gzread(): %s\n", (char *)uncompr);
+    }
+
+    pos = gzseek(file, -8L, SEEK_CUR);
+    if (pos != 6 || gztell(file) != pos) {
+	fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n",
+		(long)pos, (long)gztell(file));
+	exit(1);
+    }
+
+    if (gzgetc(file) != ' ') {
+	fprintf(stderr, "gzgetc error\n");
+	exit(1);
+    }
+
+    gzgets(file, (char*)uncompr, uncomprLen);
+    uncomprLen = strlen((char*)uncompr);
+    if (uncomprLen != 6) { /* "hello!" */
+        fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err));
+	exit(1);
+    }
+    if (strcmp((char*)uncompr, hello+7)) {
+        fprintf(stderr, "bad gzgets after gzseek\n");
+	exit(1);
+    } else {
+        printf("gzgets() after gzseek: %s\n", (char *)uncompr);
+    }
+
+    gzclose(file);
+}
+
+/* ===========================================================================
+ * Test deflate() with small buffers
+ */
+void test_deflate(compr, comprLen)
+    Byte *compr;
+    uLong comprLen;
+{
+    z_stream c_stream; /* compression stream */
+    int err;
+    int len = strlen(hello)+1;
+
+    c_stream.zalloc = (alloc_func)0;
+    c_stream.zfree = (free_func)0;
+    c_stream.opaque = (voidpf)0;
+
+    err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
+    CHECK_ERR(err, "deflateInit");
+
+    c_stream.next_in  = (Bytef*)hello;
+    c_stream.next_out = compr;
+
+    while (c_stream.total_in != (uLong)len && c_stream.total_out < comprLen) {
+        c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */
+        err = deflate(&c_stream, Z_NO_FLUSH);
+        CHECK_ERR(err, "deflate");
+    }
+    /* Finish the stream, still forcing small buffers: */
+    for (;;) {
+        c_stream.avail_out = 1;
+        err = deflate(&c_stream, Z_FINISH);
+        if (err == Z_STREAM_END) break;
+        CHECK_ERR(err, "deflate");
+    }
+
+    err = deflateEnd(&c_stream);
+    CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with small buffers
+ */
+void test_inflate(compr, comprLen, uncompr, uncomprLen)
+    Byte *compr, *uncompr;
+    uLong comprLen, uncomprLen;
+{
+    int err;
+    z_stream d_stream; /* decompression stream */
+
+    strcpy((char*)uncompr, "garbage");
+
+    d_stream.zalloc = (alloc_func)0;
+    d_stream.zfree = (free_func)0;
+    d_stream.opaque = (voidpf)0;
+
+    d_stream.next_in  = compr;
+    d_stream.avail_in = 0;
+    d_stream.next_out = uncompr;
+
+    err = inflateInit(&d_stream);
+    CHECK_ERR(err, "inflateInit");
+
+    while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) {
+        d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
+        err = inflate(&d_stream, Z_NO_FLUSH);
+        if (err == Z_STREAM_END) break;
+        CHECK_ERR(err, "inflate");
+    }
+
+    err = inflateEnd(&d_stream);
+    CHECK_ERR(err, "inflateEnd");
+
+    if (strcmp((char*)uncompr, hello)) {
+        fprintf(stderr, "bad inflate\n");
+	exit(1);
+    } else {
+        printf("inflate(): %s\n", (char *)uncompr);
+    }
+}
+
+/* ===========================================================================
+ * Test deflate() with large buffers and dynamic change of compression level
+ */
+void test_large_deflate(compr, comprLen, uncompr, uncomprLen)
+    Byte *compr, *uncompr;
+    uLong comprLen, uncomprLen;
+{
+    z_stream c_stream; /* compression stream */
+    int err;
+
+    c_stream.zalloc = (alloc_func)0;
+    c_stream.zfree = (free_func)0;
+    c_stream.opaque = (voidpf)0;
+
+    err = deflateInit(&c_stream, Z_BEST_SPEED);
+    CHECK_ERR(err, "deflateInit");
+
+    c_stream.next_out = compr;
+    c_stream.avail_out = (uInt)comprLen;
+
+    /* At this point, uncompr is still mostly zeroes, so it should compress
+     * very well:
+     */
+    c_stream.next_in = uncompr;
+    c_stream.avail_in = (uInt)uncomprLen;
+    err = deflate(&c_stream, Z_NO_FLUSH);
+    CHECK_ERR(err, "deflate");
+    if (c_stream.avail_in != 0) {
+        fprintf(stderr, "deflate not greedy\n");
+	exit(1);
+    }
+
+    /* Feed in already compressed data and switch to no compression: */
+    deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);
+    c_stream.next_in = compr;
+    c_stream.avail_in = (uInt)comprLen/2;
+    err = deflate(&c_stream, Z_NO_FLUSH);
+    CHECK_ERR(err, "deflate");
+
+    /* Switch back to compressing mode: */
+    deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED);
+    c_stream.next_in = uncompr;
+    c_stream.avail_in = (uInt)uncomprLen;
+    err = deflate(&c_stream, Z_NO_FLUSH);
+    CHECK_ERR(err, "deflate");
+
+    err = deflate(&c_stream, Z_FINISH);
+    if (err != Z_STREAM_END) {
+        fprintf(stderr, "deflate should report Z_STREAM_END\n");
+	exit(1);
+    }
+    err = deflateEnd(&c_stream);
+    CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with large buffers
+ */
+void test_large_inflate(compr, comprLen, uncompr, uncomprLen)
+    Byte *compr, *uncompr;
+    uLong comprLen, uncomprLen;
+{
+    int err;
+    z_stream d_stream; /* decompression stream */
+
+    strcpy((char*)uncompr, "garbage");
+
+    d_stream.zalloc = (alloc_func)0;
+    d_stream.zfree = (free_func)0;
+    d_stream.opaque = (voidpf)0;
+
+    d_stream.next_in  = compr;
+    d_stream.avail_in = (uInt)comprLen;
+
+    err = inflateInit(&d_stream);
+    CHECK_ERR(err, "inflateInit");
+
+    for (;;) {
+        d_stream.next_out = uncompr;            /* discard the output */
+	d_stream.avail_out = (uInt)uncomprLen;
+        err = inflate(&d_stream, Z_NO_FLUSH);
+        if (err == Z_STREAM_END) break;
+        CHECK_ERR(err, "large inflate");
+    }
+
+    err = inflateEnd(&d_stream);
+    CHECK_ERR(err, "inflateEnd");
+
+    if (d_stream.total_out != 2*uncomprLen + comprLen/2) {
+        fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out);
+	exit(1);
+    } else {
+        printf("large_inflate(): OK\n");
+    }
+}
+
+/* ===========================================================================
+ * Test deflate() with full flush
+ */
+void test_flush(compr, comprLen)
+    Byte *compr;
+    uLong *comprLen;
+{
+    z_stream c_stream; /* compression stream */
+    int err;
+    int len = strlen(hello)+1;
+
+    c_stream.zalloc = (alloc_func)0;
+    c_stream.zfree = (free_func)0;
+    c_stream.opaque = (voidpf)0;
+
+    err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
+    CHECK_ERR(err, "deflateInit");
+
+    c_stream.next_in  = (Bytef*)hello;
+    c_stream.next_out = compr;
+    c_stream.avail_in = 3;
+    c_stream.avail_out = (uInt)*comprLen;
+    err = deflate(&c_stream, Z_FULL_FLUSH);
+    CHECK_ERR(err, "deflate");
+
+    compr[3]++; /* force an error in first compressed block */
+    c_stream.avail_in = len - 3;
+
+    err = deflate(&c_stream, Z_FINISH);
+    if (err != Z_STREAM_END) {
+        CHECK_ERR(err, "deflate");
+    }
+    err = deflateEnd(&c_stream);
+    CHECK_ERR(err, "deflateEnd");
+
+    *comprLen = c_stream.total_out;
+}
+
+/* ===========================================================================
+ * Test inflateSync()
+ */
+void test_sync(compr, comprLen, uncompr, uncomprLen)
+    Byte *compr, *uncompr;
+    uLong comprLen, uncomprLen;
+{
+    int err;
+    z_stream d_stream; /* decompression stream */
+
+    strcpy((char*)uncompr, "garbage");
+
+    d_stream.zalloc = (alloc_func)0;
+    d_stream.zfree = (free_func)0;
+    d_stream.opaque = (voidpf)0;
+
+    d_stream.next_in  = compr;
+    d_stream.avail_in = 2; /* just read the zlib header */
+
+    err = inflateInit(&d_stream);
+    CHECK_ERR(err, "inflateInit");
+
+    d_stream.next_out = uncompr;
+    d_stream.avail_out = (uInt)uncomprLen;
+
+    inflate(&d_stream, Z_NO_FLUSH);
+    CHECK_ERR(err, "inflate");
+
+    d_stream.avail_in = (uInt)comprLen-2;   /* read all compressed data */
+    err = inflateSync(&d_stream);           /* but skip the damaged part */
+    CHECK_ERR(err, "inflateSync");
+
+    err = inflate(&d_stream, Z_FINISH);
+    if (err != Z_DATA_ERROR) {
+        fprintf(stderr, "inflate should report DATA_ERROR\n");
+        /* Because of incorrect adler32 */
+	exit(1);
+    }
+    err = inflateEnd(&d_stream);
+    CHECK_ERR(err, "inflateEnd");
+
+    printf("after inflateSync(): hel%s\n", (char *)uncompr);
+}
+
+/* ===========================================================================
+ * Test deflate() with preset dictionary
+ */
+void test_dict_deflate(compr, comprLen)
+    Byte *compr;
+    uLong comprLen;
+{
+    z_stream c_stream; /* compression stream */
+    int err;
+
+    c_stream.zalloc = (alloc_func)0;
+    c_stream.zfree = (free_func)0;
+    c_stream.opaque = (voidpf)0;
+
+    err = deflateInit(&c_stream, Z_BEST_COMPRESSION);
+    CHECK_ERR(err, "deflateInit");
+
+    err = deflateSetDictionary(&c_stream,
+			       (const Bytef*)dictionary, sizeof(dictionary));
+    CHECK_ERR(err, "deflateSetDictionary");
+
+    dictId = c_stream.adler;
+    c_stream.next_out = compr;
+    c_stream.avail_out = (uInt)comprLen;
+
+    c_stream.next_in = (Bytef*)hello;
+    c_stream.avail_in = (uInt)strlen(hello)+1;
+
+    err = deflate(&c_stream, Z_FINISH);
+    if (err != Z_STREAM_END) {
+        fprintf(stderr, "deflate should report Z_STREAM_END\n");
+	exit(1);
+    }
+    err = deflateEnd(&c_stream);
+    CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with a preset dictionary
+ */
+void test_dict_inflate(compr, comprLen, uncompr, uncomprLen)
+    Byte *compr, *uncompr;
+    uLong comprLen, uncomprLen;
+{
+    int err;
+    z_stream d_stream; /* decompression stream */
+
+    strcpy((char*)uncompr, "garbage");
+
+    d_stream.zalloc = (alloc_func)0;
+    d_stream.zfree = (free_func)0;
+    d_stream.opaque = (voidpf)0;
+
+    d_stream.next_in  = compr;
+    d_stream.avail_in = (uInt)comprLen;
+
+    err = inflateInit(&d_stream);
+    CHECK_ERR(err, "inflateInit");
+
+    d_stream.next_out = uncompr;
+    d_stream.avail_out = (uInt)uncomprLen;
+
+    for (;;) {
+        err = inflate(&d_stream, Z_NO_FLUSH);
+        if (err == Z_STREAM_END) break;
+	if (err == Z_NEED_DICT) {
+	    if (d_stream.adler != dictId) {
+		fprintf(stderr, "unexpected dictionary");
+		exit(1);
+	    }
+	    err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary,
+				       sizeof(dictionary));
+	}
+        CHECK_ERR(err, "inflate with dict");
+    }
+
+    err = inflateEnd(&d_stream);
+    CHECK_ERR(err, "inflateEnd");
+
+    if (strcmp((char*)uncompr, hello)) {
+        fprintf(stderr, "bad inflate with dict\n");
+	exit(1);
+    } else {
+        printf("inflate with dictionary: %s\n", (char *)uncompr);
+    }
+}
+
+/* ===========================================================================
+ * Usage:  example [output.gz  [input.gz]]
+ */
+
+int main(argc, argv)
+    int argc;
+    char *argv[];
+{
+    Byte *compr, *uncompr;
+    uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */
+    uLong uncomprLen = comprLen;
+    static const char* myVersion = ZLIB_VERSION;
+
+    if (zlibVersion()[0] != myVersion[0]) {
+        fprintf(stderr, "incompatible zlib version\n");
+        exit(1);
+
+    } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) {
+        fprintf(stderr, "warning: different zlib version\n");
+    }
+
+    compr    = (Byte*)calloc((uInt)comprLen, 1);
+    uncompr  = (Byte*)calloc((uInt)uncomprLen, 1);
+    /* compr and uncompr are cleared to avoid reading uninitialized
+     * data and to ensure that uncompr compresses well.
+     */
+    if (compr == Z_NULL || uncompr == Z_NULL) {
+        printf("out of memory\n");
+	exit(1);
+    }
+    test_compress(compr, comprLen, uncompr, uncomprLen);
+
+    test_gzio((argc > 1 ? argv[1] : TESTFILE),
+              (argc > 2 ? argv[2] : TESTFILE),
+	      uncompr, (int)uncomprLen);
+
+    test_deflate(compr, comprLen);
+    test_inflate(compr, comprLen, uncompr, uncomprLen);
+
+    test_large_deflate(compr, comprLen, uncompr, uncomprLen);
+    test_large_inflate(compr, comprLen, uncompr, uncomprLen);
+
+    test_flush(compr, &comprLen);
+    test_sync(compr, comprLen, uncompr, uncomprLen);
+    comprLen = uncomprLen;
+
+    test_dict_deflate(compr, comprLen);
+    test_dict_inflate(compr, comprLen, uncompr, uncomprLen);
+
+    exit(0);
+    return 0; /* to avoid warning */
+}
diff --git a/Utilities/ITK/Utilities/zlib/gzio.c b/Utilities/ITK/Utilities/zlib/gzio.c
new file mode 100644
index 0000000000..f7c336a55a
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/gzio.c
@@ -0,0 +1,875 @@
+/* gzio.c -- IO on .gz files
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ *
+ * Compile this file with -DNO_DEFLATE to avoid the compression code.
+ */
+
+/* @(#) $Id$ */
+
+#include <stdio.h>
+
+#include "zutil.h"
+
+struct internal_state {int dummy;}; /* for buggy compilers */
+
+#ifndef Z_BUFSIZE
+#  ifdef MAXSEG_64K
+#    define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */
+#  else
+#    define Z_BUFSIZE 16384
+#  endif
+#endif
+#ifndef Z_PRINTF_BUFSIZE
+#  define Z_PRINTF_BUFSIZE 4096
+#endif
+
+#define ALLOC(size) malloc(size)
+#define TRYFREE(p) {if (p) free(p);}
+
+static int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
+
+/* gzip flag byte */
+#define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
+#define HEAD_CRC     0x02 /* bit 1 set: header CRC present */
+#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
+#define COMMENT      0x10 /* bit 4 set: file comment present */
+#define RESERVED     0xE0 /* bits 5..7: reserved */
+
+typedef struct gz_stream {
+    z_stream stream;
+    int      z_err;   /* error code for last stream operation */
+    int      z_eof;   /* set if end of input file */
+    FILE     *file;   /* .gz file */
+    Byte     *inbuf;  /* input buffer */
+    Byte     *outbuf; /* output buffer */
+    uLong    crc;     /* crc32 of uncompressed data */
+    char     *msg;    /* error message */
+    char     *path;   /* path name for debugging only */
+    int      transparent; /* 1 if input file is not a .gz file */
+    char     mode;    /* 'w' or 'r' */
+    long     startpos; /* start of compressed data in file (header skipped) */
+} gz_stream;
+
+
+local gzFile gz_open      OF((const char *path, const char *mode, int  fd));
+local int do_flush        OF((gzFile file, int flush));
+local int    get_byte     OF((gz_stream *s));
+local void   check_header OF((gz_stream *s));
+local int    destroy      OF((gz_stream *s));
+local void   putLong      OF((FILE *file, uLong x));
+local uLong  getLong      OF((gz_stream *s));
+
+/* ===========================================================================
+     Opens a gzip (.gz) file for reading or writing. The mode parameter
+   is as in fopen ("rb" or "wb"). The file is given either by file descriptor
+   or path name (if fd == -1).
+     gz_open return NULL if the file could not be opened or if there was
+   insufficient memory to allocate the (de)compression state; errno
+   can be checked to distinguish the two cases (if errno is zero, the
+   zlib error is Z_MEM_ERROR).
+*/
+local gzFile gz_open (path, mode, fd)
+    const char *path;
+    const char *mode;
+    int  fd;
+{
+    int err;
+    int level = Z_DEFAULT_COMPRESSION; /* compression level */
+    int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */
+    char *p = (char*)mode;
+    gz_stream *s;
+    char fmode[80]; /* copy of mode, without the compression level */
+    char *m = fmode;
+
+    if (!path || !mode) return Z_NULL;
+
+    s = (gz_stream *)ALLOC(sizeof(gz_stream));
+    if (!s) return Z_NULL;
+
+    s->stream.zalloc = (alloc_func)0;
+    s->stream.zfree = (free_func)0;
+    s->stream.opaque = (voidpf)0;
+    s->stream.next_in = s->inbuf = Z_NULL;
+    s->stream.next_out = s->outbuf = Z_NULL;
+    s->stream.avail_in = s->stream.avail_out = 0;
+    s->file = NULL;
+    s->z_err = Z_OK;
+    s->z_eof = 0;
+    s->crc = crc32(0L, Z_NULL, 0);
+    s->msg = NULL;
+    s->transparent = 0;
+
+    s->path = (char*)ALLOC(strlen(path)+1);
+    if (s->path == NULL) {
+        return destroy(s), (gzFile)Z_NULL;
+    }
+    strcpy(s->path, path); /* do this early for debugging */
+
+    s->mode = '\0';
+    do {
+        if (*p == 'r') s->mode = 'r';
+        if (*p == 'w' || *p == 'a') s->mode = 'w';
+        if (*p >= '0' && *p <= '9') {
+	    level = *p - '0';
+	} else if (*p == 'f') {
+	  strategy = Z_FILTERED;
+	} else if (*p == 'h') {
+	  strategy = Z_HUFFMAN_ONLY;
+	} else {
+	    *m++ = *p; /* copy the mode */
+	}
+    } while (*p++ && m != fmode + sizeof(fmode));
+    if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL;
+    
+    if (s->mode == 'w') {
+#ifdef NO_DEFLATE
+        err = Z_STREAM_ERROR;
+#else
+        err = deflateInit2(&(s->stream), level,
+                           Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy);
+        /* windowBits is passed < 0 to suppress zlib header */
+
+        s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
+#endif
+        if (err != Z_OK || s->outbuf == Z_NULL) {
+            return destroy(s), (gzFile)Z_NULL;
+        }
+    } else {
+        s->stream.next_in  = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE);
+
+        err = inflateInit2(&(s->stream), -MAX_WBITS);
+        /* windowBits is passed < 0 to tell that there is no zlib header.
+         * Note that in this case inflate *requires* an extra "dummy" byte
+         * after the compressed stream in order to complete decompression and
+         * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are
+         * present after the compressed stream.
+         */
+        if (err != Z_OK || s->inbuf == Z_NULL) {
+            return destroy(s), (gzFile)Z_NULL;
+        }
+    }
+    s->stream.avail_out = Z_BUFSIZE;
+
+    errno = 0;
+    s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode);
+
+    if (s->file == NULL) {
+        return destroy(s), (gzFile)Z_NULL;
+    }
+    if (s->mode == 'w') {
+        /* Write a very simple .gz header:
+         */
+        fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
+             Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE);
+	s->startpos = 10L;
+	/* We use 10L instead of ftell(s->file) to because ftell causes an
+         * fflush on some systems. This version of the library doesn't use
+         * startpos anyway in write mode, so this initialization is not
+         * necessary.
+         */
+    } else {
+	check_header(s); /* skip the .gz header */
+	s->startpos = (ftell(s->file) - s->stream.avail_in);
+    }
+    
+    return (gzFile)s;
+}
+
+/* ===========================================================================
+     Opens a gzip (.gz) file for reading or writing.
+*/
+gzFile ZEXPORT gzopen (path, mode)
+    const char *path;
+    const char *mode;
+{
+    return gz_open (path, mode, -1);
+}
+
+/* ===========================================================================
+     Associate a gzFile with the file descriptor fd. fd is not dup'ed here
+   to mimic the behavio(u)r of fdopen.
+*/
+gzFile ZEXPORT gzdopen (fd, mode)
+    int fd;
+    const char *mode;
+{
+    char name[20];
+
+    if (fd < 0) return (gzFile)Z_NULL;
+    sprintf(name, "<fd:%d>", fd); /* for debugging */
+
+    return gz_open (name, mode, fd);
+}
+
+/* ===========================================================================
+ * Update the compression level and strategy
+ */
+int ZEXPORT gzsetparams (file, level, strategy)
+    gzFile file;
+    int level;
+    int strategy;
+{
+    gz_stream *s = (gz_stream*)file;
+
+    if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
+
+    /* Make room to allow flushing */
+    if (s->stream.avail_out == 0) {
+
+	s->stream.next_out = s->outbuf;
+	if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
+	    s->z_err = Z_ERRNO;
+	}
+	s->stream.avail_out = Z_BUFSIZE;
+    }
+
+    return deflateParams (&(s->stream), level, strategy);
+}
+
+/* ===========================================================================
+     Read a byte from a gz_stream; update next_in and avail_in. Return EOF
+   for end of file.
+   IN assertion: the stream s has been sucessfully opened for reading.
+*/
+local int get_byte(s)
+    gz_stream *s;
+{
+    if (s->z_eof) return EOF;
+    if (s->stream.avail_in == 0) {
+	errno = 0;
+	s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
+	if (s->stream.avail_in == 0) {
+	    s->z_eof = 1;
+	    if (ferror(s->file)) s->z_err = Z_ERRNO;
+	    return EOF;
+	}
+	s->stream.next_in = s->inbuf;
+    }
+    s->stream.avail_in--;
+    return *(s->stream.next_in)++;
+}
+
+/* ===========================================================================
+      Check the gzip header of a gz_stream opened for reading. Set the stream
+    mode to transparent if the gzip magic header is not present; set s->err
+    to Z_DATA_ERROR if the magic header is present but the rest of the header
+    is incorrect.
+    IN assertion: the stream s has already been created sucessfully;
+       s->stream.avail_in is zero for the first time, but may be non-zero
+       for concatenated .gz files.
+*/
+local void check_header(s)
+    gz_stream *s;
+{
+    int method; /* method byte */
+    int flags;  /* flags byte */
+    uInt len;
+    int c;
+
+    /* Check the gzip magic header */
+    for (len = 0; len < 2; len++) {
+	c = get_byte(s);
+	if (c != gz_magic[len]) {
+	    if (len != 0) s->stream.avail_in++, s->stream.next_in--;
+	    if (c != EOF) {
+		s->stream.avail_in++, s->stream.next_in--;
+		s->transparent = 1;
+	    }
+	    s->z_err = s->stream.avail_in != 0 ? Z_OK : Z_STREAM_END;
+	    return;
+	}
+    }
+    method = get_byte(s);
+    flags = get_byte(s);
+    if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
+	s->z_err = Z_DATA_ERROR;
+	return;
+    }
+
+    /* Discard time, xflags and OS code: */
+    for (len = 0; len < 6; len++) (void)get_byte(s);
+
+    if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
+	len  =  (uInt)get_byte(s);
+	len += ((uInt)get_byte(s))<<8;
+	/* len is garbage if EOF but the loop below will quit anyway */
+	while (len-- != 0 && get_byte(s) != EOF) ;
+    }
+    if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
+	while ((c = get_byte(s)) != 0 && c != EOF) ;
+    }
+    if ((flags & COMMENT) != 0) {   /* skip the .gz file comment */
+	while ((c = get_byte(s)) != 0 && c != EOF) ;
+    }
+    if ((flags & HEAD_CRC) != 0) {  /* skip the header crc */
+	for (len = 0; len < 2; len++) (void)get_byte(s);
+    }
+    s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
+}
+
+ /* ===========================================================================
+ * Cleanup then free the given gz_stream. Return a zlib error code.
+   Try freeing in the reverse order of allocations.
+ */
+local int destroy (s)
+    gz_stream *s;
+{
+    int err = Z_OK;
+
+    if (!s) return Z_STREAM_ERROR;
+
+    TRYFREE(s->msg);
+
+    if (s->stream.state != NULL) {
+	if (s->mode == 'w') {
+#ifdef NO_DEFLATE
+	    err = Z_STREAM_ERROR;
+#else
+	    err = deflateEnd(&(s->stream));
+#endif
+	} else if (s->mode == 'r') {
+	    err = inflateEnd(&(s->stream));
+	}
+    }
+    if (s->file != NULL && fclose(s->file)) {
+#ifdef ESPIPE
+	if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */
+#endif
+	    err = Z_ERRNO;
+    }
+    if (s->z_err < 0) err = s->z_err;
+
+    TRYFREE(s->inbuf);
+    TRYFREE(s->outbuf);
+    TRYFREE(s->path);
+    TRYFREE(s);
+    return err;
+}
+
+/* ===========================================================================
+     Reads the given number of uncompressed bytes from the compressed file.
+   gzread returns the number of bytes actually read (0 for end of file).
+*/
+int ZEXPORT gzread (file, buf, len)
+    gzFile file;
+    voidp buf;
+    unsigned len;
+{
+    gz_stream *s = (gz_stream*)file;
+    Bytef *start = (Bytef*)buf; /* starting point for crc computation */
+    Byte  *next_out; /* == stream.next_out but not forced far (for MSDOS) */
+
+    if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR;
+
+    if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1;
+    if (s->z_err == Z_STREAM_END) return 0;  /* EOF */
+
+    next_out = (Byte*)buf;
+    s->stream.next_out = (Bytef*)buf;
+    s->stream.avail_out = len;
+
+    while (s->stream.avail_out != 0) {
+
+	if (s->transparent) {
+	    /* Copy first the lookahead bytes: */
+	    uInt n = s->stream.avail_in;
+	    if (n > s->stream.avail_out) n = s->stream.avail_out;
+	    if (n > 0) {
+		zmemcpy(s->stream.next_out, s->stream.next_in, n);
+		next_out += n;
+		s->stream.next_out = next_out;
+		s->stream.next_in   += n;
+		s->stream.avail_out -= n;
+		s->stream.avail_in  -= n;
+	    }
+	    if (s->stream.avail_out > 0) {
+		s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out,
+					     s->file);
+	    }
+	    len -= s->stream.avail_out;
+	    s->stream.total_in  += (uLong)len;
+	    s->stream.total_out += (uLong)len;
+            if (len == 0) s->z_eof = 1;
+	    return (int)len;
+	}
+        if (s->stream.avail_in == 0 && !s->z_eof) {
+
+            errno = 0;
+            s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
+            if (s->stream.avail_in == 0) {
+                s->z_eof = 1;
+		if (ferror(s->file)) {
+		    s->z_err = Z_ERRNO;
+		    break;
+		}
+            }
+            s->stream.next_in = s->inbuf;
+        }
+        s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
+
+	if (s->z_err == Z_STREAM_END) {
+	    /* Check CRC and original size */
+	    s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
+	    start = s->stream.next_out;
+
+	    if (getLong(s) != s->crc) {
+		s->z_err = Z_DATA_ERROR;
+	    } else {
+	        (void)getLong(s);
+                /* The uncompressed length returned by above getlong() may
+                 * be different from s->stream.total_out) in case of
+		 * concatenated .gz files. Check for such files:
+		 */
+		check_header(s);
+		if (s->z_err == Z_OK) {
+		    uLong total_in = s->stream.total_in;
+		    uLong total_out = s->stream.total_out;
+
+		    inflateReset(&(s->stream));
+		    s->stream.total_in = total_in;
+		    s->stream.total_out = total_out;
+		    s->crc = crc32(0L, Z_NULL, 0);
+		}
+	    }
+	}
+	if (s->z_err != Z_OK || s->z_eof) break;
+    }
+    s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
+
+    return (int)(len - s->stream.avail_out);
+}
+
+
+/* ===========================================================================
+      Reads one byte from the compressed file. gzgetc returns this byte
+   or -1 in case of end of file or error.
+*/
+int ZEXPORT gzgetc(file)
+    gzFile file;
+{
+    unsigned char c;
+
+    return gzread(file, &c, 1) == 1 ? c : -1;
+}
+
+
+/* ===========================================================================
+      Reads bytes from the compressed file until len-1 characters are
+   read, or a newline character is read and transferred to buf, or an
+   end-of-file condition is encountered.  The string is then terminated
+   with a null character.
+      gzgets returns buf, or Z_NULL in case of error.
+
+      The current implementation is not optimized at all.
+*/
+char * ZEXPORT gzgets(file, buf, len)
+    gzFile file;
+    char *buf;
+    int len;
+{
+    char *b = buf;
+    if (buf == Z_NULL || len <= 0) return Z_NULL;
+
+    while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ;
+    *buf = '\0';
+    return b == buf && len > 0 ? Z_NULL : b;
+}
+
+
+#ifndef NO_DEFLATE
+/* ===========================================================================
+     Writes the given number of uncompressed bytes into the compressed file.
+   gzwrite returns the number of bytes actually written (0 in case of error).
+*/
+int ZEXPORT gzwrite (file, buf, len)
+    gzFile file;
+    const voidp buf;
+    unsigned len;
+{
+    gz_stream *s = (gz_stream*)file;
+
+    if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
+
+    s->stream.next_in = (Bytef*)buf;
+    s->stream.avail_in = len;
+
+    while (s->stream.avail_in != 0) {
+
+        if (s->stream.avail_out == 0) {
+
+            s->stream.next_out = s->outbuf;
+            if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
+                s->z_err = Z_ERRNO;
+                break;
+            }
+            s->stream.avail_out = Z_BUFSIZE;
+        }
+        s->z_err = deflate(&(s->stream), Z_NO_FLUSH);
+        if (s->z_err != Z_OK) break;
+    }
+    s->crc = crc32(s->crc, (const Bytef *)buf, len);
+
+    return (int)(len - s->stream.avail_in);
+}
+
+/* ===========================================================================
+     Converts, formats, and writes the args to the compressed file under
+   control of the format string, as in fprintf. gzprintf returns the number of
+   uncompressed bytes actually written (0 in case of error).
+*/
+#ifdef STDC
+#include <stdarg.h>
+
+int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...)
+{
+    char buf[Z_PRINTF_BUFSIZE];
+    va_list va;
+    int len;
+
+    va_start(va, format);
+#ifdef HAS_vsnprintf
+    (void)vsnprintf(buf, sizeof(buf), format, va);
+#else
+    (void)vsprintf(buf, format, va);
+#endif
+    va_end(va);
+    len = strlen(buf); /* some *sprintf don't return the nb of bytes written */
+    if (len <= 0) return 0;
+
+    return gzwrite(file, buf, (unsigned)len);
+}
+#else /* not ANSI C */
+
+int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
+	               a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
+    gzFile file;
+    const char *format;
+    int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
+	a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
+{
+    char buf[Z_PRINTF_BUFSIZE];
+    int len;
+
+#ifdef HAS_snprintf
+    snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8,
+	     a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+#else
+    sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8,
+	    a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+#endif
+    len = strlen(buf); /* old sprintf doesn't return the nb of bytes written */
+    if (len <= 0) return 0;
+
+    return gzwrite(file, buf, len);
+}
+#endif
+
+/* ===========================================================================
+      Writes c, converted to an unsigned char, into the compressed file.
+   gzputc returns the value that was written, or -1 in case of error.
+*/
+int ZEXPORT gzputc(file, c)
+    gzFile file;
+    int c;
+{
+    unsigned char cc = (unsigned char) c; /* required for big endian systems */
+
+    return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1;
+}
+
+
+/* ===========================================================================
+      Writes the given null-terminated string to the compressed file, excluding
+   the terminating null character.
+      gzputs returns the number of characters written, or -1 in case of error.
+*/
+int ZEXPORT gzputs(file, s)
+    gzFile file;
+    const char *s;
+{
+    return gzwrite(file, (char*)s, (unsigned)strlen(s));
+}
+
+
+/* ===========================================================================
+     Flushes all pending output into the compressed file. The parameter
+   flush is as in the deflate() function.
+*/
+local int do_flush (file, flush)
+    gzFile file;
+    int flush;
+{
+    uInt len;
+    int done = 0;
+    gz_stream *s = (gz_stream*)file;
+
+    if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
+
+    s->stream.avail_in = 0; /* should be zero already anyway */
+
+    for (;;) {
+        len = Z_BUFSIZE - s->stream.avail_out;
+
+        if (len != 0) {
+            if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) {
+                s->z_err = Z_ERRNO;
+                return Z_ERRNO;
+            }
+            s->stream.next_out = s->outbuf;
+            s->stream.avail_out = Z_BUFSIZE;
+        }
+        if (done) break;
+        s->z_err = deflate(&(s->stream), flush);
+
+	/* Ignore the second of two consecutive flushes: */
+	if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK;
+
+        /* deflate has finished flushing only when it hasn't used up
+         * all the available space in the output buffer: 
+         */
+        done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
+ 
+        if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break;
+    }
+    return  s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
+}
+
+int ZEXPORT gzflush (file, flush)
+     gzFile file;
+     int flush;
+{
+    gz_stream *s = (gz_stream*)file;
+    int err = do_flush (file, flush);
+
+    if (err) return err;
+    fflush(s->file);
+    return  s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
+}
+#endif /* NO_DEFLATE */
+
+/* ===========================================================================
+      Sets the starting position for the next gzread or gzwrite on the given
+   compressed file. The offset represents a number of bytes in the
+      gzseek returns the resulting offset location as measured in bytes from
+   the beginning of the uncompressed stream, or -1 in case of error.
+      SEEK_END is not implemented, returns error.
+      In this version of the library, gzseek can be extremely slow.
+*/
+z_off_t ZEXPORT gzseek (file, offset, whence)
+    gzFile file;
+    z_off_t offset;
+    int whence;
+{
+    gz_stream *s = (gz_stream*)file;
+
+    if (s == NULL || whence == SEEK_END ||
+	s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) {
+	return -1L;
+    }
+    
+    if (s->mode == 'w') {
+#ifdef NO_DEFLATE
+	return -1L;
+#else
+	if (whence == SEEK_SET) {
+	    offset -= s->stream.total_in;
+	}
+	if (offset < 0) return -1L;
+
+	/* At this point, offset is the number of zero bytes to write. */
+	if (s->inbuf == Z_NULL) {
+	    s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */
+	    zmemzero(s->inbuf, Z_BUFSIZE);
+	}
+	while (offset > 0)  {
+	    uInt size = Z_BUFSIZE;
+	    if (offset < Z_BUFSIZE) size = (uInt)offset;
+
+	    size = gzwrite(file, s->inbuf, size);
+	    if (size == 0) return -1L;
+
+	    offset -= size;
+	}
+	return (z_off_t)s->stream.total_in;
+#endif
+    }
+    /* Rest of function is for reading only */
+
+    /* compute absolute position */
+    if (whence == SEEK_CUR) {
+	offset += s->stream.total_out;
+    }
+    if (offset < 0) return -1L;
+
+    if (s->transparent) {
+	/* map to fseek */
+	s->stream.avail_in = 0;
+	s->stream.next_in = s->inbuf;
+        if (fseek(s->file, offset, SEEK_SET) < 0) return -1L;
+
+	s->stream.total_in = s->stream.total_out = (uLong)offset;
+	return offset;
+    }
+
+    /* For a negative seek, rewind and use positive seek */
+    if ((uLong)offset >= s->stream.total_out) {
+	offset -= s->stream.total_out;
+    } else if (gzrewind(file) < 0) {
+	return -1L;
+    }
+    /* offset is now the number of bytes to skip. */
+
+    if (offset != 0 && s->outbuf == Z_NULL) {
+	s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
+    }
+    while (offset > 0)  {
+	int size = Z_BUFSIZE;
+	if (offset < Z_BUFSIZE) size = (int)offset;
+
+	size = gzread(file, s->outbuf, (uInt)size);
+	if (size <= 0) return -1L;
+	offset -= size;
+    }
+    return (z_off_t)s->stream.total_out;
+}
+
+/* ===========================================================================
+     Rewinds input file. 
+*/
+int ZEXPORT gzrewind (file)
+    gzFile file;
+{
+    gz_stream *s = (gz_stream*)file;
+    
+    if (s == NULL || s->mode != 'r') return -1;
+
+    s->z_err = Z_OK;
+    s->z_eof = 0;
+    s->stream.avail_in = 0;
+    s->stream.next_in = s->inbuf;
+    s->crc = crc32(0L, Z_NULL, 0);
+	
+    if (s->startpos == 0) { /* not a compressed file */
+	rewind(s->file);
+	return 0;
+    }
+
+    (void) inflateReset(&s->stream);
+    return fseek(s->file, s->startpos, SEEK_SET);
+}
+
+/* ===========================================================================
+     Returns the starting position for the next gzread or gzwrite on the
+   given compressed file. This position represents a number of bytes in the
+   uncompressed data stream.
+*/
+z_off_t ZEXPORT gztell (file)
+    gzFile file;
+{
+    return gzseek(file, 0L, SEEK_CUR);
+}
+
+/* ===========================================================================
+     Returns 1 when EOF has previously been detected reading the given
+   input stream, otherwise zero.
+*/
+int ZEXPORT gzeof (file)
+    gzFile file;
+{
+    gz_stream *s = (gz_stream*)file;
+    
+    return (s == NULL || s->mode != 'r') ? 0 : s->z_eof;
+}
+
+/* ===========================================================================
+   Outputs a long in LSB order to the given file
+*/
+local void putLong (file, x)
+    FILE *file;
+    uLong x;
+{
+    int n;
+    for (n = 0; n < 4; n++) {
+        fputc((int)(x & 0xff), file);
+        x >>= 8;
+    }
+}
+
+/* ===========================================================================
+   Reads a long in LSB order from the given gz_stream. Sets z_err in case
+   of error.
+*/
+local uLong getLong (s)
+    gz_stream *s;
+{
+    uLong x = (uLong)get_byte(s);
+    int c;
+
+    x += ((uLong)get_byte(s))<<8;
+    x += ((uLong)get_byte(s))<<16;
+    c = get_byte(s);
+    if (c == EOF) s->z_err = Z_DATA_ERROR;
+    x += ((uLong)c)<<24;
+    return x;
+}
+
+/* ===========================================================================
+     Flushes all pending output if necessary, closes the compressed file
+   and deallocates all the (de)compression state.
+*/
+int ZEXPORT gzclose (file)
+    gzFile file;
+{
+    int err;
+    gz_stream *s = (gz_stream*)file;
+
+    if (s == NULL) return Z_STREAM_ERROR;
+
+    if (s->mode == 'w') {
+#ifdef NO_DEFLATE
+	return Z_STREAM_ERROR;
+#else
+        err = do_flush (file, Z_FINISH);
+        if (err != Z_OK) return destroy((gz_stream*)file);
+
+        putLong (s->file, s->crc);
+        putLong (s->file, s->stream.total_in);
+#endif
+    }
+    return destroy((gz_stream*)file);
+}
+
+/* ===========================================================================
+     Returns the error message for the last error which occured on the
+   given compressed file. errnum is set to zlib error number. If an
+   error occured in the file system and not in the compression library,
+   errnum is set to Z_ERRNO and the application may consult errno
+   to get the exact error code.
+*/
+const char*  ZEXPORT gzerror (file, errnum)
+    gzFile file;
+    int *errnum;
+{
+    char *m;
+    gz_stream *s = (gz_stream*)file;
+
+    if (s == NULL) {
+        *errnum = Z_STREAM_ERROR;
+        return (const char*)ERR_MSG(Z_STREAM_ERROR);
+    }
+    *errnum = s->z_err;
+    if (*errnum == Z_OK) return (const char*)"";
+
+    m =  (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg);
+
+    if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err);
+
+    TRYFREE(s->msg);
+    s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3);
+    strcpy(s->msg, s->path);
+    strcat(s->msg, ": ");
+    strcat(s->msg, m);
+    return (const char*)s->msg;
+}
diff --git a/Utilities/ITK/Utilities/zlib/infblock.c b/Utilities/ITK/Utilities/zlib/infblock.c
new file mode 100644
index 0000000000..f4920faa5e
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/infblock.c
@@ -0,0 +1,398 @@
+/* infblock.c -- interpret and process block types to last block
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+#include "zutil.h"
+#include "infblock.h"
+#include "inftrees.h"
+#include "infcodes.h"
+#include "infutil.h"
+
+struct inflate_codes_state {int dummy;}; /* for buggy compilers */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* Table for deflate from PKZIP's appnote.txt. */
+local const uInt border[] = { /* Order of the bit length code lengths */
+        16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+/*
+   Notes beyond the 1.93a appnote.txt:
+
+   1. Distance pointers never point before the beginning of the output
+      stream.
+   2. Distance pointers can point back across blocks, up to 32k away.
+   3. There is an implied maximum of 7 bits for the bit length table and
+      15 bits for the actual data.
+   4. If only one code exists, then it is encoded using one bit.  (Zero
+      would be more efficient, but perhaps a little confusing.)  If two
+      codes exist, they are coded using one bit each (0 and 1).
+   5. There is no way of sending zero distance codes--a dummy must be
+      sent if there are none.  (History: a pre 2.0 version of PKZIP would
+      store blocks with no distance codes, but this was discovered to be
+      too harsh a criterion.)  Valid only for 1.93a.  2.04c does allow
+      zero distance codes, which is sent as one code of zero bits in
+      length.
+   6. There are up to 286 literal/length codes.  Code 256 represents the
+      end-of-block.  Note however that the static length tree defines
+      288 codes just to fill out the Huffman codes.  Codes 286 and 287
+      cannot be used though, since there is no length base or extra bits
+      defined for them.  Similarily, there are up to 30 distance codes.
+      However, static trees define 32 codes (all 5 bits) to fill out the
+      Huffman codes, but the last two had better not show up in the data.
+   7. Unzip can check dynamic Huffman blocks for complete code sets.
+      The exception is that a single code would not be complete (see #4).
+   8. The five bits following the block type is really the number of
+      literal codes sent minus 257.
+   9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
+      (1+6+6).  Therefore, to output three times the length, you output
+      three codes (1+1+1), whereas to output four times the same length,
+      you only need two codes (1+3).  Hmm.
+  10. In the tree reconstruction algorithm, Code = Code + Increment
+      only if BitLength(i) is not zero.  (Pretty obvious.)
+  11. Correction: 4 Bits: # of Bit Length codes - 4     (4 - 19)
+  12. Note: length code 284 can represent 227-258, but length code 285
+      really is 258.  The last length deserves its own, short code
+      since it gets used a lot in very redundant files.  The length
+      258 is special since 258 - 3 (the min match length) is 255.
+  13. The literal/length and distance code bit lengths are read as a
+      single stream of lengths.  It is possible (and advantageous) for
+      a repeat code (16, 17, or 18) to go across the boundary between
+      the two sets of lengths.
+ */
+
+
+void inflate_blocks_reset(s, z, c)
+inflate_blocks_statef *s;
+z_streamp z;
+uLongf *c;
+{
+  if (c != Z_NULL)
+    *c = s->check;
+  if (s->mode == BTREE || s->mode == DTREE)
+    ZFREE(z, s->sub.trees.blens);
+  if (s->mode == CODES)
+    inflate_codes_free(s->sub.decode.codes, z);
+  s->mode = TYPE;
+  s->bitk = 0;
+  s->bitb = 0;
+  s->read = s->write = s->window;
+  if (s->checkfn != Z_NULL)
+    z->adler = s->check = (*s->checkfn)(0L, (const Bytef *)Z_NULL, 0);
+  Tracev((stderr, "inflate:   blocks reset\n"));
+}
+
+
+inflate_blocks_statef *inflate_blocks_new(z, c, w)
+z_streamp z;
+check_func c;
+uInt w;
+{
+  inflate_blocks_statef *s;
+
+  if ((s = (inflate_blocks_statef *)ZALLOC
+       (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
+    return s;
+  if ((s->hufts =
+       (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL)
+  {
+    ZFREE(z, s);
+    return Z_NULL;
+  }
+  if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL)
+  {
+    ZFREE(z, s->hufts);
+    ZFREE(z, s);
+    return Z_NULL;
+  }
+  s->end = s->window + w;
+  s->checkfn = c;
+  s->mode = TYPE;
+  Tracev((stderr, "inflate:   blocks allocated\n"));
+  inflate_blocks_reset(s, z, Z_NULL);
+  return s;
+}
+
+
+int inflate_blocks(s, z, r)
+inflate_blocks_statef *s;
+z_streamp z;
+int r;
+{
+  uInt t;               /* temporary storage */
+  uLong b;              /* bit buffer */
+  uInt k;               /* bits in bit buffer */
+  Bytef *p;             /* input data pointer */
+  uInt n;               /* bytes available there */
+  Bytef *q;             /* output window write pointer */
+  uInt m;               /* bytes to end of window or read pointer */
+
+  /* copy input/output information to locals (UPDATE macro restores) */
+  LOAD
+
+  /* process input based on current state */
+  while (1) switch (s->mode)
+  {
+    case TYPE:
+      NEEDBITS(3)
+      t = (uInt)b & 7;
+      s->last = t & 1;
+      switch (t >> 1)
+      {
+        case 0:                         /* stored */
+          Tracev((stderr, "inflate:     stored block%s\n",
+                 s->last ? " (last)" : ""));
+          DUMPBITS(3)
+          t = k & 7;                    /* go to byte boundary */
+          DUMPBITS(t)
+          s->mode = LENS;               /* get length of stored block */
+          break;
+        case 1:                         /* fixed */
+          Tracev((stderr, "inflate:     fixed codes block%s\n",
+                 s->last ? " (last)" : ""));
+          {
+            uInt bl, bd;
+            inflate_huft *tl, *td;
+
+            inflate_trees_fixed(&bl, &bd, &tl, &td, z);
+            s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
+            if (s->sub.decode.codes == Z_NULL)
+            {
+              r = Z_MEM_ERROR;
+              LEAVE
+            }
+          }
+          DUMPBITS(3)
+          s->mode = CODES;
+          break;
+        case 2:                         /* dynamic */
+          Tracev((stderr, "inflate:     dynamic codes block%s\n",
+                 s->last ? " (last)" : ""));
+          DUMPBITS(3)
+          s->mode = TABLE;
+          break;
+        case 3:                         /* illegal */
+          DUMPBITS(3)
+          s->mode = BAD;
+          z->msg = (char*)"invalid block type";
+          r = Z_DATA_ERROR;
+          LEAVE
+      }
+      break;
+    case LENS:
+      NEEDBITS(32)
+      if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
+      {
+        s->mode = BAD;
+        z->msg = (char*)"invalid stored block lengths";
+        r = Z_DATA_ERROR;
+        LEAVE
+      }
+      s->sub.left = (uInt)b & 0xffff;
+      b = k = 0;                      /* dump bits */
+      Tracev((stderr, "inflate:       stored length %u\n", s->sub.left));
+      s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE);
+      break;
+    case STORED:
+      if (n == 0)
+        LEAVE
+      NEEDOUT
+      t = s->sub.left;
+      if (t > n) t = n;
+      if (t > m) t = m;
+      zmemcpy(q, p, t);
+      p += t;  n -= t;
+      q += t;  m -= t;
+      if ((s->sub.left -= t) != 0)
+        break;
+      Tracev((stderr, "inflate:       stored end, %lu total out\n",
+              z->total_out + (q >= s->read ? q - s->read :
+              (s->end - s->read) + (q - s->window))));
+      s->mode = s->last ? DRY : TYPE;
+      break;
+    case TABLE:
+      NEEDBITS(14)
+      s->sub.trees.table = t = (uInt)b & 0x3fff;
+#ifndef PKZIP_BUG_WORKAROUND
+      if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
+      {
+        s->mode = BAD;
+        z->msg = (char*)"too many length or distance symbols";
+        r = Z_DATA_ERROR;
+        LEAVE
+      }
+#endif
+      t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
+      if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)
+      {
+        r = Z_MEM_ERROR;
+        LEAVE
+      }
+      DUMPBITS(14)
+      s->sub.trees.index = 0;
+      Tracev((stderr, "inflate:       table sizes ok\n"));
+      s->mode = BTREE;
+    case BTREE:
+      while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
+      {
+        NEEDBITS(3)
+        s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
+        DUMPBITS(3)
+      }
+      while (s->sub.trees.index < 19)
+        s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
+      s->sub.trees.bb = 7;
+      t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
+                             &s->sub.trees.tb, s->hufts, z);
+      if (t != Z_OK)
+      {
+        ZFREE(z, s->sub.trees.blens);
+        r = t;
+        if (r == Z_DATA_ERROR)
+          s->mode = BAD;
+        LEAVE
+      }
+      s->sub.trees.index = 0;
+      Tracev((stderr, "inflate:       bits tree ok\n"));
+      s->mode = DTREE;
+    case DTREE:
+      while (t = s->sub.trees.table,
+             s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
+      {
+        inflate_huft *h;
+        uInt i, j, c;
+
+        t = s->sub.trees.bb;
+        NEEDBITS(t)
+        h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
+        t = h->bits;
+        c = h->base;
+        if (c < 16)
+        {
+          DUMPBITS(t)
+          s->sub.trees.blens[s->sub.trees.index++] = c;
+        }
+        else /* c == 16..18 */
+        {
+          i = c == 18 ? 7 : c - 14;
+          j = c == 18 ? 11 : 3;
+          NEEDBITS(t + i)
+          DUMPBITS(t)
+          j += (uInt)b & inflate_mask[i];
+          DUMPBITS(i)
+          i = s->sub.trees.index;
+          t = s->sub.trees.table;
+          if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
+              (c == 16 && i < 1))
+          {
+            ZFREE(z, s->sub.trees.blens);
+            s->mode = BAD;
+            z->msg = (char*)"invalid bit length repeat";
+            r = Z_DATA_ERROR;
+            LEAVE
+          }
+          c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
+          do {
+            s->sub.trees.blens[i++] = c;
+          } while (--j);
+          s->sub.trees.index = i;
+        }
+      }
+      s->sub.trees.tb = Z_NULL;
+      {
+        uInt bl, bd;
+        inflate_huft *tl, *td;
+        inflate_codes_statef *c;
+
+        bl = 9;         /* must be <= 9 for lookahead assumptions */
+        bd = 6;         /* must be <= 9 for lookahead assumptions */
+        t = s->sub.trees.table;
+        t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
+                                  s->sub.trees.blens, &bl, &bd, &tl, &td,
+                                  s->hufts, z);
+        ZFREE(z, s->sub.trees.blens);
+        if (t != Z_OK)
+        {
+          if (t == (uInt)Z_DATA_ERROR)
+            s->mode = BAD;
+          r = t;
+          LEAVE
+        }
+        Tracev((stderr, "inflate:       trees ok\n"));
+        if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
+        {
+          r = Z_MEM_ERROR;
+          LEAVE
+        }
+        s->sub.decode.codes = c;
+      }
+      s->mode = CODES;
+    case CODES:
+      UPDATE
+      if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
+        return inflate_flush(s, z, r);
+      r = Z_OK;
+      inflate_codes_free(s->sub.decode.codes, z);
+      LOAD
+      Tracev((stderr, "inflate:       codes end, %lu total out\n",
+              z->total_out + (q >= s->read ? q - s->read :
+              (s->end - s->read) + (q - s->window))));
+      if (!s->last)
+      {
+        s->mode = TYPE;
+        break;
+      }
+      s->mode = DRY;
+    case DRY:
+      FLUSH
+      if (s->read != s->write)
+        LEAVE
+      s->mode = DONE;
+    case DONE:
+      r = Z_STREAM_END;
+      LEAVE
+    case BAD:
+      r = Z_DATA_ERROR;
+      LEAVE
+    default:
+      r = Z_STREAM_ERROR;
+      LEAVE
+  }
+}
+
+
+int inflate_blocks_free(s, z)
+inflate_blocks_statef *s;
+z_streamp z;
+{
+  inflate_blocks_reset(s, z, Z_NULL);
+  ZFREE(z, s->window);
+  ZFREE(z, s->hufts);
+  ZFREE(z, s);
+  Tracev((stderr, "inflate:   blocks freed\n"));
+  return Z_OK;
+}
+
+
+void inflate_set_dictionary(s, d, n)
+inflate_blocks_statef *s;
+const Bytef *d;
+uInt  n;
+{
+  zmemcpy(s->window, d, n);
+  s->read = s->write = s->window + n;
+}
+
+
+/* Returns true if inflate is currently at the end of a block generated
+ * by Z_SYNC_FLUSH or Z_FULL_FLUSH. 
+ * IN assertion: s != Z_NULL
+ */
+int inflate_blocks_sync_point(s)
+inflate_blocks_statef *s;
+{
+  return s->mode == LENS;
+}
diff --git a/Utilities/ITK/Utilities/zlib/infblock.h b/Utilities/ITK/Utilities/zlib/infblock.h
new file mode 100644
index 0000000000..bd25c80753
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/infblock.h
@@ -0,0 +1,39 @@
+/* infblock.h -- header to use infblock.c
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+struct inflate_blocks_state;
+typedef struct inflate_blocks_state FAR inflate_blocks_statef;
+
+extern inflate_blocks_statef * inflate_blocks_new OF((
+    z_streamp z,
+    check_func c,               /* check function */
+    uInt w));                   /* window size */
+
+extern int inflate_blocks OF((
+    inflate_blocks_statef *,
+    z_streamp ,
+    int));                      /* initial return code */
+
+extern void inflate_blocks_reset OF((
+    inflate_blocks_statef *,
+    z_streamp ,
+    uLongf *));                  /* check value on output */
+
+extern int inflate_blocks_free OF((
+    inflate_blocks_statef *,
+    z_streamp));
+
+extern void inflate_set_dictionary OF((
+    inflate_blocks_statef *s,
+    const Bytef *d,  /* dictionary */
+    uInt  n));       /* dictionary length */
+
+extern int inflate_blocks_sync_point OF((
+    inflate_blocks_statef *s));
diff --git a/Utilities/ITK/Utilities/zlib/infcodes.c b/Utilities/ITK/Utilities/zlib/infcodes.c
new file mode 100644
index 0000000000..d4e5ee9a55
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/infcodes.c
@@ -0,0 +1,257 @@
+/* infcodes.c -- process literals and length/distance pairs
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "infblock.h"
+#include "infcodes.h"
+#include "infutil.h"
+#include "inffast.h"
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+typedef enum {        /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+      START,    /* x: set up for LEN */
+      LEN,      /* i: get length/literal/eob next */
+      LENEXT,   /* i: getting length extra (have base) */
+      DIST,     /* i: get distance next */
+      DISTEXT,  /* i: getting distance extra */
+      COPY,     /* o: copying bytes in window, waiting for space */
+      LIT,      /* o: got literal, waiting for output space */
+      WASH,     /* o: got eob, possibly still output waiting */
+      END,      /* x: got eob and all data flushed */
+      BADCODE}  /* x: got error */
+inflate_codes_mode;
+
+/* inflate codes private state */
+struct inflate_codes_state {
+
+  /* mode */
+  inflate_codes_mode mode;      /* current inflate_codes mode */
+
+  /* mode dependent information */
+  uInt len;
+  union {
+    struct {
+      inflate_huft *tree;       /* pointer into tree */
+      uInt need;                /* bits needed */
+    } code;             /* if LEN or DIST, where in tree */
+    uInt lit;           /* if LIT, literal */
+    struct {
+      uInt get;                 /* bits to get for extra */
+      uInt dist;                /* distance back to copy from */
+    } copy;             /* if EXT or COPY, where and how much */
+  } sub;                /* submode */
+
+  /* mode independent information */
+  Byte lbits;           /* ltree bits decoded per branch */
+  Byte dbits;           /* dtree bits decoder per branch */
+  inflate_huft *ltree;          /* literal/length/eob tree */
+  inflate_huft *dtree;          /* distance tree */
+
+};
+
+
+inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z)
+uInt bl, bd;
+inflate_huft *tl;
+inflate_huft *td; /* need separate declaration for Borland C++ */
+z_streamp z;
+{
+  inflate_codes_statef *c;
+
+  if ((c = (inflate_codes_statef *)
+       ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
+  {
+    c->mode = START;
+    c->lbits = (Byte)bl;
+    c->dbits = (Byte)bd;
+    c->ltree = tl;
+    c->dtree = td;
+    Tracev((stderr, "inflate:       codes new\n"));
+  }
+  return c;
+}
+
+
+int inflate_codes(s, z, r)
+inflate_blocks_statef *s;
+z_streamp z;
+int r;
+{
+  uInt j;               /* temporary storage */
+  inflate_huft *t;      /* temporary pointer */
+  uInt e;               /* extra bits or operation */
+  uLong b;              /* bit buffer */
+  uInt k;               /* bits in bit buffer */
+  Bytef *p;             /* input data pointer */
+  uInt n;               /* bytes available there */
+  Bytef *q;             /* output window write pointer */
+  uInt m;               /* bytes to end of window or read pointer */
+  Bytef *f;             /* pointer to copy strings from */
+  inflate_codes_statef *c = s->sub.decode.codes;  /* codes state */
+
+  /* copy input/output information to locals (UPDATE macro restores) */
+  LOAD
+
+  /* process input and output based on current state */
+  while (1) switch (c->mode)
+  {             /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+    case START:         /* x: set up for LEN */
+#ifndef SLOW
+      if (m >= 258 && n >= 10)
+      {
+        UPDATE
+        r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
+        LOAD
+        if (r != Z_OK)
+        {
+          c->mode = r == Z_STREAM_END ? WASH : BADCODE;
+          break;
+        }
+      }
+#endif /* !SLOW */
+      c->sub.code.need = c->lbits;
+      c->sub.code.tree = c->ltree;
+      c->mode = LEN;
+    case LEN:           /* i: get length/literal/eob next */
+      j = c->sub.code.need;
+      NEEDBITS(j)
+      t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+      DUMPBITS(t->bits)
+      e = (uInt)(t->exop);
+      if (e == 0)               /* literal */
+      {
+        c->sub.lit = t->base;
+        Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+                 "inflate:         literal '%c'\n" :
+                 "inflate:         literal 0x%02x\n", t->base));
+        c->mode = LIT;
+        break;
+      }
+      if (e & 16)               /* length */
+      {
+        c->sub.copy.get = e & 15;
+        c->len = t->base;
+        c->mode = LENEXT;
+        break;
+      }
+      if ((e & 64) == 0)        /* next table */
+      {
+        c->sub.code.need = e;
+        c->sub.code.tree = t + t->base;
+        break;
+      }
+      if (e & 32)               /* end of block */
+      {
+        Tracevv((stderr, "inflate:         end of block\n"));
+        c->mode = WASH;
+        break;
+      }
+      c->mode = BADCODE;        /* invalid code */
+      z->msg = (char*)"invalid literal/length code";
+      r = Z_DATA_ERROR;
+      LEAVE
+    case LENEXT:        /* i: getting length extra (have base) */
+      j = c->sub.copy.get;
+      NEEDBITS(j)
+      c->len += (uInt)b & inflate_mask[j];
+      DUMPBITS(j)
+      c->sub.code.need = c->dbits;
+      c->sub.code.tree = c->dtree;
+      Tracevv((stderr, "inflate:         length %u\n", c->len));
+      c->mode = DIST;
+    case DIST:          /* i: get distance next */
+      j = c->sub.code.need;
+      NEEDBITS(j)
+      t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+      DUMPBITS(t->bits)
+      e = (uInt)(t->exop);
+      if (e & 16)               /* distance */
+      {
+        c->sub.copy.get = e & 15;
+        c->sub.copy.dist = t->base;
+        c->mode = DISTEXT;
+        break;
+      }
+      if ((e & 64) == 0)        /* next table */
+      {
+        c->sub.code.need = e;
+        c->sub.code.tree = t + t->base;
+        break;
+      }
+      c->mode = BADCODE;        /* invalid code */
+      z->msg = (char*)"invalid distance code";
+      r = Z_DATA_ERROR;
+      LEAVE
+    case DISTEXT:       /* i: getting distance extra */
+      j = c->sub.copy.get;
+      NEEDBITS(j)
+      c->sub.copy.dist += (uInt)b & inflate_mask[j];
+      DUMPBITS(j)
+      Tracevv((stderr, "inflate:         distance %u\n", c->sub.copy.dist));
+      c->mode = COPY;
+    case COPY:          /* o: copying bytes in window, waiting for space */
+#ifndef __TURBOC__ /* Turbo C bug for following expression */
+      f = (uInt)(q - s->window) < c->sub.copy.dist ?
+          s->end - (c->sub.copy.dist - (q - s->window)) :
+          q - c->sub.copy.dist;
+#else
+      f = q - c->sub.copy.dist;
+      if ((uInt)(q - s->window) < c->sub.copy.dist)
+        f = s->end - (c->sub.copy.dist - (uInt)(q - s->window));
+#endif
+      while (c->len)
+      {
+        NEEDOUT
+        OUTBYTE(*f++)
+        if (f == s->end)
+          f = s->window;
+        c->len--;
+      }
+      c->mode = START;
+      break;
+    case LIT:           /* o: got literal, waiting for output space */
+      NEEDOUT
+      OUTBYTE(c->sub.lit)
+      c->mode = START;
+      break;
+    case WASH:          /* o: got eob, possibly more output */
+      if (k > 7)        /* return unused byte, if any */
+      {
+        Assert(k < 16, "inflate_codes grabbed too many bytes")
+        k -= 8;
+        n++;
+        p--;            /* can always return one */
+      }
+      FLUSH
+      if (s->read != s->write)
+        LEAVE
+      c->mode = END;
+    case END:
+      r = Z_STREAM_END;
+      LEAVE
+    case BADCODE:       /* x: got error */
+      r = Z_DATA_ERROR;
+      LEAVE
+    default:
+      r = Z_STREAM_ERROR;
+      LEAVE
+  }
+#ifdef NEED_DUMMY_RETURN
+  return Z_STREAM_ERROR;  /* Some dumb compilers complain without this */
+#endif
+}
+
+
+void inflate_codes_free(c, z)
+inflate_codes_statef *c;
+z_streamp z;
+{
+  ZFREE(z, c);
+  Tracev((stderr, "inflate:       codes free\n"));
+}
diff --git a/Utilities/ITK/Utilities/zlib/infcodes.h b/Utilities/ITK/Utilities/zlib/infcodes.h
new file mode 100644
index 0000000000..6c750d896f
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/infcodes.h
@@ -0,0 +1,27 @@
+/* infcodes.h -- header to use infcodes.c
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+struct inflate_codes_state;
+typedef struct inflate_codes_state FAR inflate_codes_statef;
+
+extern inflate_codes_statef *inflate_codes_new OF((
+    uInt, uInt,
+    inflate_huft *, inflate_huft *,
+    z_streamp ));
+
+extern int inflate_codes OF((
+    inflate_blocks_statef *,
+    z_streamp ,
+    int));
+
+extern void inflate_codes_free OF((
+    inflate_codes_statef *,
+    z_streamp ));
+
diff --git a/Utilities/ITK/Utilities/zlib/inffast.c b/Utilities/ITK/Utilities/zlib/inffast.c
new file mode 100644
index 0000000000..61a78ee933
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/inffast.c
@@ -0,0 +1,170 @@
+/* inffast.c -- process literals and length/distance pairs fast
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "infblock.h"
+#include "infcodes.h"
+#include "infutil.h"
+#include "inffast.h"
+
+struct inflate_codes_state {int dummy;}; /* for buggy compilers */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* macros for bit input with no checking and for returning unused bytes */
+#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}}
+#define UNGRAB {c=z->avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;}
+
+/* Called with number of bytes left to write in window at least 258
+   (the maximum string length) and number of input bytes available
+   at least ten.  The ten bytes are six bytes for the longest length/
+   distance pair plus four bytes for overloading the bit buffer. */
+
+int inflate_fast(bl, bd, tl, td, s, z)
+uInt bl, bd;
+inflate_huft *tl;
+inflate_huft *td; /* need separate declaration for Borland C++ */
+inflate_blocks_statef *s;
+z_streamp z;
+{
+  inflate_huft *t;      /* temporary pointer */
+  uInt e;               /* extra bits or operation */
+  uLong b;              /* bit buffer */
+  uInt k;               /* bits in bit buffer */
+  Bytef *p;             /* input data pointer */
+  uInt n;               /* bytes available there */
+  Bytef *q;             /* output window write pointer */
+  uInt m;               /* bytes to end of window or read pointer */
+  uInt ml;              /* mask for literal/length tree */
+  uInt md;              /* mask for distance tree */
+  uInt c;               /* bytes to copy */
+  uInt d;               /* distance back to copy from */
+  Bytef *r;             /* copy source pointer */
+
+  /* load input, output, bit values */
+  LOAD
+
+  /* initialize masks */
+  ml = inflate_mask[bl];
+  md = inflate_mask[bd];
+
+  /* do until not enough input or output space for fast loop */
+  do {                          /* assume called with m >= 258 && n >= 10 */
+    /* get literal/length code */
+    GRABBITS(20)                /* max bits for literal/length code */
+    if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
+    {
+      DUMPBITS(t->bits)
+      Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+                "inflate:         * literal '%c'\n" :
+                "inflate:         * literal 0x%02x\n", t->base));
+      *q++ = (Byte)t->base;
+      m--;
+      continue;
+    }
+    do {
+      DUMPBITS(t->bits)
+      if (e & 16)
+      {
+        /* get extra bits for length */
+        e &= 15;
+        c = t->base + ((uInt)b & inflate_mask[e]);
+        DUMPBITS(e)
+        Tracevv((stderr, "inflate:         * length %u\n", c));
+
+        /* decode distance base of block to copy */
+        GRABBITS(15);           /* max bits for distance code */
+        e = (t = td + ((uInt)b & md))->exop;
+        do {
+          DUMPBITS(t->bits)
+          if (e & 16)
+          {
+            /* get extra bits to add to distance base */
+            e &= 15;
+            GRABBITS(e)         /* get extra bits (up to 13) */
+            d = t->base + ((uInt)b & inflate_mask[e]);
+            DUMPBITS(e)
+            Tracevv((stderr, "inflate:         * distance %u\n", d));
+
+            /* do the copy */
+            m -= c;
+            if ((uInt)(q - s->window) >= d)     /* offset before dest */
+            {                                   /*  just copy */
+              r = q - d;
+              *q++ = *r++;  c--;        /* minimum count is three, */
+              *q++ = *r++;  c--;        /*  so unroll loop a little */
+            }
+            else                        /* else offset after destination */
+            {
+              e = d - (uInt)(q - s->window); /* bytes from offset to end */
+              r = s->end - e;           /* pointer to offset */
+              if (c > e)                /* if source crosses, */
+              {
+                c -= e;                 /* copy to end of window */
+                do {
+                  *q++ = *r++;
+                } while (--e);
+                r = s->window;          /* copy rest from start of window */
+              }
+            }
+            do {                        /* copy all or what's left */
+              *q++ = *r++;
+            } while (--c);
+            break;
+          }
+          else if ((e & 64) == 0)
+          {
+            t += t->base;
+            e = (t += ((uInt)b & inflate_mask[e]))->exop;
+          }
+          else
+          {
+            z->msg = (char*)"invalid distance code";
+            UNGRAB
+            UPDATE
+            return Z_DATA_ERROR;
+          }
+        } while (1);
+        break;
+      }
+      if ((e & 64) == 0)
+      {
+        t += t->base;
+        if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0)
+        {
+          DUMPBITS(t->bits)
+          Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+                    "inflate:         * literal '%c'\n" :
+                    "inflate:         * literal 0x%02x\n", t->base));
+          *q++ = (Byte)t->base;
+          m--;
+          break;
+        }
+      }
+      else if (e & 32)
+      {
+        Tracevv((stderr, "inflate:         * end of block\n"));
+        UNGRAB
+        UPDATE
+        return Z_STREAM_END;
+      }
+      else
+      {
+        z->msg = (char*)"invalid literal/length code";
+        UNGRAB
+        UPDATE
+        return Z_DATA_ERROR;
+      }
+    } while (1);
+  } while (m >= 258 && n >= 10);
+
+  /* not enough input or output--restore pointers and return */
+  UNGRAB
+  UPDATE
+  return Z_OK;
+}
diff --git a/Utilities/ITK/Utilities/zlib/inffast.h b/Utilities/ITK/Utilities/zlib/inffast.h
new file mode 100644
index 0000000000..8facec5531
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/inffast.h
@@ -0,0 +1,17 @@
+/* inffast.h -- header to use inffast.c
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+extern int inflate_fast OF((
+    uInt,
+    uInt,
+    inflate_huft *,
+    inflate_huft *,
+    inflate_blocks_statef *,
+    z_streamp ));
diff --git a/Utilities/ITK/Utilities/zlib/inffixed.h b/Utilities/ITK/Utilities/zlib/inffixed.h
new file mode 100644
index 0000000000..77f7e76314
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/inffixed.h
@@ -0,0 +1,151 @@
+/* inffixed.h -- table for decoding fixed codes
+ * Generated automatically by the maketree.c program
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+local uInt fixed_bl = 9;
+local uInt fixed_bd = 5;
+local inflate_huft fixed_tl[] = {
+    {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
+    {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192},
+    {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160},
+    {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224},
+    {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144},
+    {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208},
+    {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176},
+    {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240},
+    {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
+    {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200},
+    {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168},
+    {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232},
+    {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152},
+    {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216},
+    {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184},
+    {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248},
+    {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
+    {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196},
+    {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164},
+    {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228},
+    {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148},
+    {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212},
+    {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180},
+    {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244},
+    {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
+    {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204},
+    {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172},
+    {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236},
+    {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156},
+    {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220},
+    {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188},
+    {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252},
+    {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
+    {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194},
+    {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162},
+    {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226},
+    {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146},
+    {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210},
+    {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178},
+    {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242},
+    {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
+    {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202},
+    {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170},
+    {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234},
+    {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154},
+    {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218},
+    {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186},
+    {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250},
+    {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
+    {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198},
+    {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166},
+    {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230},
+    {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150},
+    {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214},
+    {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182},
+    {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246},
+    {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
+    {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206},
+    {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174},
+    {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238},
+    {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158},
+    {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222},
+    {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190},
+    {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254},
+    {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
+    {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193},
+    {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161},
+    {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225},
+    {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145},
+    {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209},
+    {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177},
+    {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241},
+    {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
+    {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201},
+    {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169},
+    {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233},
+    {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153},
+    {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217},
+    {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185},
+    {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249},
+    {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
+    {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197},
+    {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165},
+    {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229},
+    {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149},
+    {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213},
+    {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181},
+    {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245},
+    {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
+    {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205},
+    {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173},
+    {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237},
+    {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157},
+    {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221},
+    {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189},
+    {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253},
+    {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
+    {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195},
+    {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163},
+    {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227},
+    {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147},
+    {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211},
+    {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179},
+    {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243},
+    {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
+    {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203},
+    {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171},
+    {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235},
+    {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155},
+    {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219},
+    {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187},
+    {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251},
+    {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
+    {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199},
+    {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167},
+    {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231},
+    {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151},
+    {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215},
+    {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183},
+    {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247},
+    {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
+    {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207},
+    {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175},
+    {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239},
+    {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159},
+    {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223},
+    {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191},
+    {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255}
+  };
+local inflate_huft fixed_td[] = {
+    {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097},
+    {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385},
+    {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193},
+    {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577},
+    {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145},
+    {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577},
+    {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289},
+    {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577}
+  };
diff --git a/Utilities/ITK/Utilities/zlib/inflate.c b/Utilities/ITK/Utilities/zlib/inflate.c
new file mode 100644
index 0000000000..32e9b8de67
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/inflate.c
@@ -0,0 +1,366 @@
+/* inflate.c -- zlib interface to inflate modules
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+#include "zutil.h"
+#include "infblock.h"
+
+struct inflate_blocks_state {int dummy;}; /* for buggy compilers */
+
+typedef enum {
+      METHOD,   /* waiting for method byte */
+      FLAG,     /* waiting for flag byte */
+      DICT4,    /* four dictionary check bytes to go */
+      DICT3,    /* three dictionary check bytes to go */
+      DICT2,    /* two dictionary check bytes to go */
+      DICT1,    /* one dictionary check byte to go */
+      DICT0,    /* waiting for inflateSetDictionary */
+      BLOCKS,   /* decompressing blocks */
+      CHECK4,   /* four check bytes to go */
+      CHECK3,   /* three check bytes to go */
+      CHECK2,   /* two check bytes to go */
+      CHECK1,   /* one check byte to go */
+      DONE,     /* finished check, done */
+      BAD}      /* got an error--stay here */
+inflate_mode;
+
+/* inflate private state */
+struct internal_state {
+
+  /* mode */
+  inflate_mode  mode;   /* current inflate mode */
+
+  /* mode dependent information */
+  union {
+    uInt method;        /* if FLAGS, method byte */
+    struct {
+      uLong was;                /* computed check value */
+      uLong need;               /* stream check value */
+    } check;            /* if CHECK, check values to compare */
+    uInt marker;        /* if BAD, inflateSync's marker bytes count */
+  } sub;        /* submode */
+
+  /* mode independent information */
+  int  nowrap;          /* flag for no wrapper */
+  uInt wbits;           /* log2(window size)  (8..15, defaults to 15) */
+  inflate_blocks_statef 
+    *blocks;            /* current inflate_blocks state */
+
+};
+
+
+int ZEXPORT inflateReset(z)
+z_streamp z;
+{
+  if (z == Z_NULL || z->state == Z_NULL)
+    return Z_STREAM_ERROR;
+  z->total_in = z->total_out = 0;
+  z->msg = Z_NULL;
+  z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
+  inflate_blocks_reset(z->state->blocks, z, Z_NULL);
+  Tracev((stderr, "inflate: reset\n"));
+  return Z_OK;
+}
+
+
+int ZEXPORT inflateEnd(z)
+z_streamp z;
+{
+  if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
+    return Z_STREAM_ERROR;
+  if (z->state->blocks != Z_NULL)
+    inflate_blocks_free(z->state->blocks, z);
+  ZFREE(z, z->state);
+  z->state = Z_NULL;
+  Tracev((stderr, "inflate: end\n"));
+  return Z_OK;
+}
+
+
+int ZEXPORT inflateInit2_(z, w, version, stream_size)
+z_streamp z;
+int w;
+const char *version;
+int stream_size;
+{
+  if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+      stream_size != sizeof(z_stream))
+      return Z_VERSION_ERROR;
+
+  /* initialize state */
+  if (z == Z_NULL)
+    return Z_STREAM_ERROR;
+  z->msg = Z_NULL;
+  if (z->zalloc == Z_NULL)
+  {
+    z->zalloc = zcalloc;
+    z->opaque = (voidpf)0;
+  }
+  if (z->zfree == Z_NULL) z->zfree = zcfree;
+  if ((z->state = (struct internal_state FAR *)
+       ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
+    return Z_MEM_ERROR;
+  z->state->blocks = Z_NULL;
+
+  /* handle undocumented nowrap option (no zlib header or check) */
+  z->state->nowrap = 0;
+  if (w < 0)
+  {
+    w = - w;
+    z->state->nowrap = 1;
+  }
+
+  /* set window size */
+  if (w < 8 || w > 15)
+  {
+    inflateEnd(z);
+    return Z_STREAM_ERROR;
+  }
+  z->state->wbits = (uInt)w;
+
+  /* create inflate_blocks state */
+  if ((z->state->blocks =
+      inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))
+      == Z_NULL)
+  {
+    inflateEnd(z);
+    return Z_MEM_ERROR;
+  }
+  Tracev((stderr, "inflate: allocated\n"));
+
+  /* reset state */
+  inflateReset(z);
+  return Z_OK;
+}
+
+
+int ZEXPORT inflateInit_(z, version, stream_size)
+z_streamp z;
+const char *version;
+int stream_size;
+{
+  return inflateInit2_(z, DEF_WBITS, version, stream_size);
+}
+
+
+#define NEEDBYTE {if(z->avail_in==0)return r;r=f;}
+#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
+
+int ZEXPORT inflate(z, f)
+z_streamp z;
+int f;
+{
+  int r;
+  uInt b;
+
+  if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL)
+    return Z_STREAM_ERROR;
+  f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
+  r = Z_BUF_ERROR;
+  while (1) switch (z->state->mode)
+  {
+    case METHOD:
+      NEEDBYTE
+      if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED)
+      {
+        z->state->mode = BAD;
+        z->msg = (char*)"unknown compression method";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
+      {
+        z->state->mode = BAD;
+        z->msg = (char*)"invalid window size";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      z->state->mode = FLAG;
+    case FLAG:
+      NEEDBYTE
+      b = NEXTBYTE;
+      if (((z->state->sub.method << 8) + b) % 31)
+      {
+        z->state->mode = BAD;
+        z->msg = (char*)"incorrect header check";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      Tracev((stderr, "inflate: zlib header ok\n"));
+      if (!(b & PRESET_DICT))
+      {
+        z->state->mode = BLOCKS;
+        break;
+      }
+      z->state->mode = DICT4;
+    case DICT4:
+      NEEDBYTE
+      z->state->sub.check.need = (uLong)NEXTBYTE << 24;
+      z->state->mode = DICT3;
+    case DICT3:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE << 16;
+      z->state->mode = DICT2;
+    case DICT2:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE << 8;
+      z->state->mode = DICT1;
+    case DICT1:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE;
+      z->adler = z->state->sub.check.need;
+      z->state->mode = DICT0;
+      return Z_NEED_DICT;
+    case DICT0:
+      z->state->mode = BAD;
+      z->msg = (char*)"need dictionary";
+      z->state->sub.marker = 0;       /* can try inflateSync */
+      return Z_STREAM_ERROR;
+    case BLOCKS:
+      r = inflate_blocks(z->state->blocks, z, r);
+      if (r == Z_DATA_ERROR)
+      {
+        z->state->mode = BAD;
+        z->state->sub.marker = 0;       /* can try inflateSync */
+        break;
+      }
+      if (r == Z_OK)
+        r = f;
+      if (r != Z_STREAM_END)
+        return r;
+      r = f;
+      inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
+      if (z->state->nowrap)
+      {
+        z->state->mode = DONE;
+        break;
+      }
+      z->state->mode = CHECK4;
+    case CHECK4:
+      NEEDBYTE
+      z->state->sub.check.need = (uLong)NEXTBYTE << 24;
+      z->state->mode = CHECK3;
+    case CHECK3:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE << 16;
+      z->state->mode = CHECK2;
+    case CHECK2:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE << 8;
+      z->state->mode = CHECK1;
+    case CHECK1:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE;
+
+      if (z->state->sub.check.was != z->state->sub.check.need)
+      {
+        z->state->mode = BAD;
+        z->msg = (char*)"incorrect data check";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      Tracev((stderr, "inflate: zlib check ok\n"));
+      z->state->mode = DONE;
+    case DONE:
+      return Z_STREAM_END;
+    case BAD:
+      return Z_DATA_ERROR;
+    default:
+      return Z_STREAM_ERROR;
+  }
+#ifdef NEED_DUMMY_RETURN
+  return Z_STREAM_ERROR;  /* Some dumb compilers complain without this */
+#endif
+}
+
+
+int ZEXPORT inflateSetDictionary(z, dictionary, dictLength)
+z_streamp z;
+const Bytef *dictionary;
+uInt  dictLength;
+{
+  uInt length = dictLength;
+
+  if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0)
+    return Z_STREAM_ERROR;
+
+  if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR;
+  z->adler = 1L;
+
+  if (length >= ((uInt)1<<z->state->wbits))
+  {
+    length = (1<<z->state->wbits)-1;
+    dictionary += dictLength - length;
+  }
+  inflate_set_dictionary(z->state->blocks, dictionary, length);
+  z->state->mode = BLOCKS;
+  return Z_OK;
+}
+
+
+int ZEXPORT inflateSync(z)
+z_streamp z;
+{
+  uInt n;       /* number of bytes to look at */
+  Bytef *p;     /* pointer to bytes */
+  uInt m;       /* number of marker bytes found in a row */
+  uLong r, w;   /* temporaries to save total_in and total_out */
+
+  /* set up */
+  if (z == Z_NULL || z->state == Z_NULL)
+    return Z_STREAM_ERROR;
+  if (z->state->mode != BAD)
+  {
+    z->state->mode = BAD;
+    z->state->sub.marker = 0;
+  }
+  if ((n = z->avail_in) == 0)
+    return Z_BUF_ERROR;
+  p = z->next_in;
+  m = z->state->sub.marker;
+
+  /* search */
+  while (n && m < 4)
+  {
+    static const Byte mark[4] = {0, 0, 0xff, 0xff};
+    if (*p == mark[m])
+      m++;
+    else if (*p)
+      m = 0;
+    else
+      m = 4 - m;
+    p++, n--;
+  }
+
+  /* restore */
+  z->total_in += p - z->next_in;
+  z->next_in = p;
+  z->avail_in = n;
+  z->state->sub.marker = m;
+
+  /* return no joy or set up to restart on a new block */
+  if (m != 4)
+    return Z_DATA_ERROR;
+  r = z->total_in;  w = z->total_out;
+  inflateReset(z);
+  z->total_in = r;  z->total_out = w;
+  z->state->mode = BLOCKS;
+  return Z_OK;
+}
+
+
+/* Returns true if inflate is currently at the end of a block generated
+ * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
+ * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
+ * but removes the length bytes of the resulting empty stored block. When
+ * decompressing, PPP checks that at the end of input packet, inflate is
+ * waiting for these length bytes.
+ */
+int ZEXPORT inflateSyncPoint(z)
+z_streamp z;
+{
+  if (z == Z_NULL || z->state == Z_NULL || z->state->blocks == Z_NULL)
+    return Z_STREAM_ERROR;
+  return inflate_blocks_sync_point(z->state->blocks);
+}
diff --git a/Utilities/ITK/Utilities/zlib/inftrees.c b/Utilities/ITK/Utilities/zlib/inftrees.c
new file mode 100644
index 0000000000..daa41dec09
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/inftrees.c
@@ -0,0 +1,456 @@
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+
+#if !defined(BUILDFIXED) && !defined(STDC)
+#  define BUILDFIXED   /* non ANSI compilers may not accept inffixed.h */
+#endif
+
+const char inflate_copyright[] =
+   " inflate 1.1.3 Copyright 1995-1998 Mark Adler ";
+/*
+  If you use the zlib library in a product, an acknowledgment is welcome
+  in the documentation of your product. If for some reason you cannot
+  include such an acknowledgment, I would appreciate that you keep this
+  copyright string in the executable of your product.
+ */
+struct internal_state  {int dummy;}; /* for buggy compilers */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+
+local int huft_build OF((
+    uIntf *,            /* code lengths in bits */
+    uInt,               /* number of codes */
+    uInt,               /* number of "simple" codes */
+    const uIntf *,      /* list of base values for non-simple codes */
+    const uIntf *,      /* list of extra bits for non-simple codes */
+    inflate_huft * FAR*,/* result: starting table */
+    uIntf *,            /* maximum lookup bits (returns actual) */
+    inflate_huft *,     /* space for trees */
+    uInt *,             /* hufts used in space */
+    uIntf * ));         /* space for values */
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+local const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */
+        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+        /* see note #13 above about 258 */
+local const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */
+        0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+        3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */
+local const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */
+        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+        8193, 12289, 16385, 24577};
+local const uInt cpdext[30] = { /* Extra bits for distance codes */
+        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+        7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+        12, 12, 13, 13};
+
+/*
+   Huffman code decoding is performed using a multi-level table lookup.
+   The fastest way to decode is to simply build a lookup table whose
+   size is determined by the longest code.  However, the time it takes
+   to build this table can also be a factor if the data being decoded
+   is not very long.  The most common codes are necessarily the
+   shortest codes, so those codes dominate the decoding time, and hence
+   the speed.  The idea is you can have a shorter table that decodes the
+   shorter, more probable codes, and then point to subsidiary tables for
+   the longer codes.  The time it costs to decode the longer codes is
+   then traded against the time it takes to make longer tables.
+
+   This results of this trade are in the variables lbits and dbits
+   below.  lbits is the number of bits the first level table for literal/
+   length codes can decode in one step, and dbits is the same thing for
+   the distance codes.  Subsequent tables are also less than or equal to
+   those sizes.  These values may be adjusted either when all of the
+   codes are shorter than that, in which case the longest code length in
+   bits is used, or when the shortest code is *longer* than the requested
+   table size, in which case the length of the shortest code in bits is
+   used.
+
+   There are two different values for the two tables, since they code a
+   different number of possibilities each.  The literal/length table
+   codes 286 possible values, or in a flat code, a little over eight
+   bits.  The distance table codes 30 possible values, or a little less
+   than five bits, flat.  The optimum values for speed end up being
+   about one bit more than those, so lbits is 8+1 and dbits is 5+1.
+   The optimum values may differ though from machine to machine, and
+   possibly even between compilers.  Your mileage may vary.
+ */
+
+
+/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
+#define BMAX 15         /* maximum bit length of any code */
+
+local int huft_build(b, n, s, d, e, t, m, hp, hn, v)
+uIntf *b;               /* code lengths in bits (all assumed <= BMAX) */
+uInt n;                 /* number of codes (assumed <= 288) */
+uInt s;                 /* number of simple-valued codes (0..s-1) */
+const uIntf *d;         /* list of base values for non-simple codes */
+const uIntf *e;         /* list of extra bits for non-simple codes */
+inflate_huft * FAR *t;  /* result: starting table */
+uIntf *m;               /* maximum lookup bits, returns actual */
+inflate_huft *hp;       /* space for trees */
+uInt *hn;               /* hufts used in space */
+uIntf *v;               /* working area: values in order of bit length */
+/* Given a list of code lengths and a maximum table size, make a set of
+   tables to decode that set of codes.  Return Z_OK on success, Z_BUF_ERROR
+   if the given code set is incomplete (the tables are still built in this
+   case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
+   lengths), or Z_MEM_ERROR if not enough memory. */
+{
+
+  uInt a;                       /* counter for codes of length k */
+  uInt c[BMAX+1];               /* bit length count table */
+  uInt f;                       /* i repeats in table every f entries */
+  int g;                        /* maximum code length */
+  int h;                        /* table level */
+  register uInt i;              /* counter, current code */
+  register uInt j;              /* counter */
+  register int k;               /* number of bits in current code */
+  int l;                        /* bits per table (returned in m) */
+  uInt mask;                    /* (1 << w) - 1, to avoid cc -O bug on HP */
+  register uIntf *p;            /* pointer into c[], b[], or v[] */
+  inflate_huft *q;              /* points to current table */
+  struct inflate_huft_s r;      /* table entry for structure assignment */
+  inflate_huft *u[BMAX];        /* table stack */
+  register int w;               /* bits before this table == (l * h) */
+  uInt x[BMAX+1];               /* bit offsets, then code stack */
+  uIntf *xp;                    /* pointer into x */
+  int y;                        /* number of dummy codes added */
+  uInt z;                       /* number of entries in current table */
+
+
+  /* Generate counts for each bit length */
+  p = c;
+#define C0 *p++ = 0;
+#define C2 C0 C0 C0 C0
+#define C4 C2 C2 C2 C2
+  C4                            /* clear c[]--assume BMAX+1 is 16 */
+  p = b;  i = n;
+  do {
+    c[*p++]++;                  /* assume all entries <= BMAX */
+  } while (--i);
+  if (c[0] == n)                /* null input--all zero length codes */
+  {
+    *t = (inflate_huft *)Z_NULL;
+    *m = 0;
+    return Z_OK;
+  }
+
+
+  /* Find minimum and maximum length, bound *m by those */
+  l = *m;
+  for (j = 1; j <= BMAX; j++)
+    if (c[j])
+      break;
+  k = j;                        /* minimum code length */
+  if ((uInt)l < j)
+    l = j;
+  for (i = BMAX; i; i--)
+    if (c[i])
+      break;
+  g = i;                        /* maximum code length */
+  if ((uInt)l > i)
+    l = i;
+  *m = l;
+
+
+  /* Adjust last length count to fill out codes, if needed */
+  for (y = 1 << j; j < i; j++, y <<= 1)
+    if ((y -= c[j]) < 0)
+      return Z_DATA_ERROR;
+  if ((y -= c[i]) < 0)
+    return Z_DATA_ERROR;
+  c[i] += y;
+
+
+  /* Generate starting offsets into the value table for each length */
+  x[1] = j = 0;
+  p = c + 1;  xp = x + 2;
+  while (--i) {                 /* note that i == g from above */
+    *xp++ = (j += *p++);
+  }
+
+
+  /* Make a table of values in order of bit lengths */
+  p = b;  i = 0;
+  do {
+    if ((j = *p++) != 0)
+      v[x[j]++] = i;
+  } while (++i < n);
+  n = x[g];                     /* set n to length of v */
+
+
+  /* Generate the Huffman codes and for each, make the table entries */
+  x[0] = i = 0;                 /* first Huffman code is zero */
+  p = v;                        /* grab values in bit order */
+  h = -1;                       /* no tables yet--level -1 */
+  w = -l;                       /* bits decoded == (l * h) */
+  u[0] = (inflate_huft *)Z_NULL;        /* just to keep compilers happy */
+  q = (inflate_huft *)Z_NULL;   /* ditto */
+  z = 0;                        /* ditto */
+
+  /* go through the bit lengths (k already is bits in shortest code) */
+  for (; k <= g; k++)
+  {
+    a = c[k];
+    while (a--)
+    {
+      /* here i is the Huffman code of length k bits for value *p */
+      /* make tables up to required level */
+      while (k > w + l)
+      {
+        h++;
+        w += l;                 /* previous table always l bits */
+
+        /* compute minimum size table less than or equal to l bits */
+        z = g - w;
+        z = z > (uInt)l ? (uInt)l : z;        /* table size upper limit */
+        if ((f = 1 << (j = k - w)) > a + 1)     /* try a k-w bit table */
+        {                       /* too few codes for k-w bit table */
+          f -= a + 1;           /* deduct codes from patterns left */
+          xp = c + k;
+          if (j < z)
+            while (++j < z)     /* try smaller tables up to z bits */
+            {
+              if ((f <<= 1) <= *++xp)
+                break;          /* enough codes to use up j bits */
+              f -= *xp;         /* else deduct codes from patterns */
+            }
+        }
+        z = 1 << j;             /* table entries for j-bit table */
+
+        /* allocate new table */
+        if (*hn + z > MANY)     /* (note: doesn't matter for fixed) */
+          return Z_MEM_ERROR;   /* not enough memory */
+        u[h] = q = hp + *hn;
+        *hn += z;
+
+        /* connect to last table, if there is one */
+        if (h)
+        {
+          x[h] = i;             /* save pattern for backing up */
+          r.bits = (Byte)l;     /* bits to dump before this table */
+          r.exop = (Byte)j;     /* bits in this table */
+          j = i >> (w - l);
+          r.base = (uInt)(q - u[h-1] - j);   /* offset to this table */
+          u[h-1][j] = r;        /* connect to last table */
+        }
+        else
+          *t = q;               /* first table is returned result */
+      }
+
+      /* set up table entry in r */
+      r.bits = (Byte)(k - w);
+      if (p >= v + n)
+        r.exop = 128 + 64;      /* out of values--invalid code */
+      else if (*p < s)
+      {
+        r.exop = (Byte)(*p < 256 ? 0 : 32 + 64);     /* 256 is end-of-block */
+        r.base = *p++;          /* simple code is just the value */
+      }
+      else
+      {
+        r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */
+        r.base = d[*p++ - s];
+      }
+
+      /* fill code-like entries with r */
+      f = 1 << (k - w);
+      for (j = i >> w; j < z; j += f)
+        q[j] = r;
+
+      /* backwards increment the k-bit code i */
+      for (j = 1 << (k - 1); i & j; j >>= 1)
+        i ^= j;
+      i ^= j;
+
+      /* backup over finished tables */
+      mask = (1 << w) - 1;      /* needed on HP, cc -O bug */
+      while ((i & mask) != x[h])
+      {
+        h--;                    /* don't need to update q */
+        w -= l;
+        mask = (1 << w) - 1;
+      }
+    }
+  }
+
+
+  /* Return Z_BUF_ERROR if we were given an incomplete table */
+  return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
+}
+
+
+int inflate_trees_bits(c, bb, tb, hp, z)
+uIntf *c;               /* 19 code lengths */
+uIntf *bb;              /* bits tree desired/actual depth */
+inflate_huft * FAR *tb; /* bits tree result */
+inflate_huft *hp;       /* space for trees */
+z_streamp z;            /* for messages */
+{
+  int r;
+  uInt hn = 0;          /* hufts used in space */
+  uIntf *v;             /* work area for huft_build */
+
+  if ((v = (uIntf*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL)
+    return Z_MEM_ERROR;
+  r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL,
+                 tb, bb, hp, &hn, v);
+  if (r == Z_DATA_ERROR)
+    z->msg = (char*)"oversubscribed dynamic bit lengths tree";
+  else if (r == Z_BUF_ERROR || *bb == 0)
+  {
+    z->msg = (char*)"incomplete dynamic bit lengths tree";
+    r = Z_DATA_ERROR;
+  }
+  ZFREE(z, v);
+  return r;
+}
+
+
+int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, hp, z)
+uInt nl;                /* number of literal/length codes */
+uInt nd;                /* number of distance codes */
+uIntf *c;               /* that many (total) code lengths */
+uIntf *bl;              /* literal desired/actual bit depth */
+uIntf *bd;              /* distance desired/actual bit depth */
+inflate_huft * FAR *tl; /* literal/length tree result */
+inflate_huft * FAR *td; /* distance tree result */
+inflate_huft *hp;       /* space for trees */
+z_streamp z;            /* for messages */
+{
+  int r;
+  uInt hn = 0;          /* hufts used in space */
+  uIntf *v;             /* work area for huft_build */
+
+  /* allocate work area */
+  if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
+    return Z_MEM_ERROR;
+
+  /* build literal/length tree */
+  r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v);
+  if (r != Z_OK || *bl == 0)
+  {
+    if (r == Z_DATA_ERROR)
+      z->msg = (char*)"oversubscribed literal/length tree";
+    else if (r != Z_MEM_ERROR)
+    {
+      z->msg = (char*)"incomplete literal/length tree";
+      r = Z_DATA_ERROR;
+    }
+    ZFREE(z, v);
+    return r;
+  }
+
+  /* build distance tree */
+  r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v);
+  if (r != Z_OK || (*bd == 0 && nl > 257))
+  {
+    if (r == Z_DATA_ERROR)
+      z->msg = (char*)"oversubscribed distance tree";
+    else if (r == Z_BUF_ERROR) {
+#ifdef PKZIP_BUG_WORKAROUND
+      r = Z_OK;
+    }
+#else
+      z->msg = (char*)"incomplete distance tree";
+      r = Z_DATA_ERROR;
+    }
+    else if (r != Z_MEM_ERROR)
+    {
+      z->msg = (char*)"empty distance tree with lengths";
+      r = Z_DATA_ERROR;
+    }
+    ZFREE(z, v);
+    return r;
+#endif
+  }
+
+  /* done */
+  ZFREE(z, v);
+  return Z_OK;
+}
+
+
+/* build fixed tables only once--keep them here */
+#ifdef BUILDFIXED
+local int fixed_built = 0;
+#define FIXEDH 544      /* number of hufts used by fixed tables */
+local inflate_huft fixed_mem[FIXEDH];
+local uInt fixed_bl;
+local uInt fixed_bd;
+local inflate_huft *fixed_tl;
+local inflate_huft *fixed_td;
+#else
+#include "inffixed.h"
+#endif
+
+
+int inflate_trees_fixed(bl, bd, tl, td, z)
+uIntf *bl;               /* literal desired/actual bit depth */
+uIntf *bd;               /* distance desired/actual bit depth */
+inflate_huft * FAR *tl;  /* literal/length tree result */
+inflate_huft * FAR *td;  /* distance tree result */
+z_streamp z;             /* for memory allocation */
+{
+#ifdef BUILDFIXED
+  /* build fixed tables if not already */
+  if (!fixed_built)
+  {
+    int k;              /* temporary variable */
+    uInt f = 0;         /* number of hufts used in fixed_mem */
+    uIntf *c;           /* length list for huft_build */
+    uIntf *v;           /* work area for huft_build */
+
+    /* allocate memory */
+    if ((c = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
+      return Z_MEM_ERROR;
+    if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
+    {
+      ZFREE(z, c);
+      return Z_MEM_ERROR;
+    }
+
+    /* literal table */
+    for (k = 0; k < 144; k++)
+      c[k] = 8;
+    for (; k < 256; k++)
+      c[k] = 9;
+    for (; k < 280; k++)
+      c[k] = 7;
+    for (; k < 288; k++)
+      c[k] = 8;
+    fixed_bl = 9;
+    huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl,
+               fixed_mem, &f, v);
+
+    /* distance table */
+    for (k = 0; k < 30; k++)
+      c[k] = 5;
+    fixed_bd = 5;
+    huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd,
+               fixed_mem, &f, v);
+
+    /* done */
+    ZFREE(z, v);
+    ZFREE(z, c);
+    fixed_built = 1;
+  }
+#endif
+  z = z;  /* prevent warning for unused variable*/
+  *bl = fixed_bl;
+  *bd = fixed_bd;
+  *tl = fixed_tl;
+  *td = fixed_td;
+  return Z_OK;
+}
diff --git a/Utilities/ITK/Utilities/zlib/inftrees.h b/Utilities/ITK/Utilities/zlib/inftrees.h
new file mode 100644
index 0000000000..85853e097b
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/inftrees.h
@@ -0,0 +1,58 @@
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* Huffman code lookup table entry--this entry is four bytes for machines
+   that have 16-bit pointers (e.g. PC's in the small or medium model). */
+
+typedef struct inflate_huft_s FAR inflate_huft;
+
+struct inflate_huft_s {
+  union {
+    struct {
+      Byte Exop;        /* number of extra bits or operation */
+      Byte Bits;        /* number of bits in this code or subcode */
+    } what;
+    uInt pad;           /* pad structure to a power of 2 (4 bytes for */
+  } word;               /*  16-bit, 8 bytes for 32-bit int's) */
+  uInt base;            /* literal, length base, distance base,
+                           or table offset */
+};
+
+/* Maximum size of dynamic tree.  The maximum found in a long but non-
+   exhaustive search was 1004 huft structures (850 for length/literals
+   and 154 for distances, the latter actually the result of an
+   exhaustive search).  The actual maximum is not known, but the
+   value below is more than safe. */
+#define MANY 1440
+
+extern int inflate_trees_bits OF((
+    uIntf *,                    /* 19 code lengths */
+    uIntf *,                    /* bits tree desired/actual depth */
+    inflate_huft * FAR *,       /* bits tree result */
+    inflate_huft *,             /* space for trees */
+    z_streamp));                /* for messages */
+
+extern int inflate_trees_dynamic OF((
+    uInt,                       /* number of literal/length codes */
+    uInt,                       /* number of distance codes */
+    uIntf *,                    /* that many (total) code lengths */
+    uIntf *,                    /* literal desired/actual bit depth */
+    uIntf *,                    /* distance desired/actual bit depth */
+    inflate_huft * FAR *,       /* literal/length tree result */
+    inflate_huft * FAR *,       /* distance tree result */
+    inflate_huft *,             /* space for trees */
+    z_streamp));                /* for messages */
+
+extern int inflate_trees_fixed OF((
+    uIntf *,                    /* literal desired/actual bit depth */
+    uIntf *,                    /* distance desired/actual bit depth */
+    inflate_huft * FAR *,       /* literal/length tree result */
+    inflate_huft * FAR *,       /* distance tree result */
+    z_streamp));                /* for memory allocation */
diff --git a/Utilities/ITK/Utilities/zlib/infutil.c b/Utilities/ITK/Utilities/zlib/infutil.c
new file mode 100644
index 0000000000..824dab5712
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/infutil.c
@@ -0,0 +1,87 @@
+/* inflate_util.c -- data and routines common to blocks and codes
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+#include "zutil.h"
+#include "infblock.h"
+#include "inftrees.h"
+#include "infcodes.h"
+#include "infutil.h"
+
+struct inflate_codes_state {int dummy;}; /* for buggy compilers */
+
+/* And'ing with mask[n] masks the lower n bits */
+uInt inflate_mask[17] = {
+    0x0000,
+    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+
+/* copy as much as possible from the sliding window to the output area */
+int inflate_flush(s, z, r)
+inflate_blocks_statef *s;
+z_streamp z;
+int r;
+{
+  uInt n;
+  Bytef *p;
+  Bytef *q;
+
+  /* local copies of source and destination pointers */
+  p = z->next_out;
+  q = s->read;
+
+  /* compute number of bytes to copy as far as end of window */
+  n = (uInt)((q <= s->write ? s->write : s->end) - q);
+  if (n > z->avail_out) n = z->avail_out;
+  if (n && r == Z_BUF_ERROR) r = Z_OK;
+
+  /* update counters */
+  z->avail_out -= n;
+  z->total_out += n;
+
+  /* update check information */
+  if (s->checkfn != Z_NULL)
+    z->adler = s->check = (*s->checkfn)(s->check, q, n);
+
+  /* copy as far as end of window */
+  zmemcpy(p, q, n);
+  p += n;
+  q += n;
+
+  /* see if more to copy at beginning of window */
+  if (q == s->end)
+  {
+    /* wrap pointers */
+    q = s->window;
+    if (s->write == s->end)
+      s->write = s->window;
+
+    /* compute bytes to copy */
+    n = (uInt)(s->write - q);
+    if (n > z->avail_out) n = z->avail_out;
+    if (n && r == Z_BUF_ERROR) r = Z_OK;
+
+    /* update counters */
+    z->avail_out -= n;
+    z->total_out += n;
+
+    /* update check information */
+    if (s->checkfn != Z_NULL)
+      z->adler = s->check = (*s->checkfn)(s->check, q, n);
+
+    /* copy */
+    zmemcpy(p, q, n);
+    p += n;
+    q += n;
+  }
+
+  /* update pointers */
+  z->next_out = p;
+  s->read = q;
+
+  /* done */
+  return r;
+}
diff --git a/Utilities/ITK/Utilities/zlib/infutil.h b/Utilities/ITK/Utilities/zlib/infutil.h
new file mode 100644
index 0000000000..99d1135d06
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/infutil.h
@@ -0,0 +1,98 @@
+/* infutil.h -- types and macros common to blocks and codes
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+#ifndef _INFUTIL_H
+#define _INFUTIL_H
+
+typedef enum {
+      TYPE,     /* get type bits (3, including end bit) */
+      LENS,     /* get lengths for stored */
+      STORED,   /* processing stored block */
+      TABLE,    /* get table lengths */
+      BTREE,    /* get bit lengths tree for a dynamic block */
+      DTREE,    /* get length, distance trees for a dynamic block */
+      CODES,    /* processing fixed or dynamic block */
+      DRY,      /* output remaining window bytes */
+      DONE,     /* finished last block, done */
+      BAD}      /* got a data error--stuck here */
+inflate_block_mode;
+
+/* inflate blocks semi-private state */
+struct inflate_blocks_state {
+
+  /* mode */
+  inflate_block_mode  mode;     /* current inflate_block mode */
+
+  /* mode dependent information */
+  union {
+    uInt left;          /* if STORED, bytes left to copy */
+    struct {
+      uInt table;               /* table lengths (14 bits) */
+      uInt index;               /* index into blens (or border) */
+      uIntf *blens;             /* bit lengths of codes */
+      uInt bb;                  /* bit length tree depth */
+      inflate_huft *tb;         /* bit length decoding tree */
+    } trees;            /* if DTREE, decoding info for trees */
+    struct {
+      inflate_codes_statef 
+         *codes;
+    } decode;           /* if CODES, current state */
+  } sub;                /* submode */
+  uInt last;            /* true if this block is the last block */
+
+  /* mode independent information */
+  uInt bitk;            /* bits in bit buffer */
+  uLong bitb;           /* bit buffer */
+  inflate_huft *hufts;  /* single malloc for tree space */
+  Bytef *window;        /* sliding window */
+  Bytef *end;           /* one byte after sliding window */
+  Bytef *read;          /* window read pointer */
+  Bytef *write;         /* window write pointer */
+  check_func checkfn;   /* check function */
+  uLong check;          /* check on output */
+
+};
+
+
+/* defines for inflate input/output */
+/*   update pointers and return */
+#define UPDBITS {s->bitb=b;s->bitk=k;}
+#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
+#define UPDOUT {s->write=q;}
+#define UPDATE {UPDBITS UPDIN UPDOUT}
+#define LEAVE {UPDATE return inflate_flush(s,z,r);}
+/*   get bytes and bits */
+#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
+#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
+#define NEXTBYTE (n--,*p++)
+#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}
+#define DUMPBITS(j) {b>>=(j);k-=(j);}
+/*   output bytes */
+#define WAVAIL (uInt)(q<s->read?s->read-q-1:s->end-q)
+#define LOADOUT {q=s->write;m=(uInt)WAVAIL;}
+#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}}
+#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
+#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
+#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
+/*   load local pointers */
+#define LOAD {LOADIN LOADOUT}
+
+/* masks for lower bits (size given to avoid silly warnings with Visual C++) */
+extern uInt inflate_mask[17];
+
+/* copy as much as possible from the sliding window to the output area */
+extern int inflate_flush OF((
+    inflate_blocks_statef *,
+    z_streamp ,
+    int));
+
+struct internal_state      {int dummy;}; /* for buggy compilers */
+
+#endif
diff --git a/Utilities/ITK/Utilities/zlib/itk_zlib_mangle.h b/Utilities/ITK/Utilities/zlib/itk_zlib_mangle.h
new file mode 100644
index 0000000000..8339d7e63d
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/itk_zlib_mangle.h
@@ -0,0 +1,86 @@
+#ifndef itk_zlib_mangle_h
+#define itk_zlib_mangle_h
+
+/*
+
+This header file mangles all symbols exported from the zlib library.
+It is included in all files while building the zlib library.  Due to
+namespace pollution, no zlib headers should be included in .h files in
+ITK.
+
+The following command was used to obtain the symbol list:
+
+nm libitkzlib.a |grep " T "
+
+*/
+
+#define deflate_copyright itk_deflate_copyright
+#define _length_code itk__length_code
+#define _dist_code itk__dist_code
+#define _tr_align itk__tr_align
+#define _tr_flush_block itk__tr_flush_block
+#define _tr_init itk__tr_init
+#define _tr_stored_block itk__tr_stored_block
+#define _tr_tally itk__tr_tally
+#define adler32 itk_adler32
+#define compress itk_compress
+#define compress2 itk_compress2
+#define crc32 itk_crc32
+#define deflate itk_deflate
+#define deflateCopy itk_deflateCopy
+#define deflateEnd itk_deflateEnd
+#define deflateInit2_ itk_deflateInit2_
+#define deflateInit_ itk_deflateInit_
+#define deflateParams itk_deflateParams
+#define deflateReset itk_deflateReset
+#define deflateSetDictionary itk_deflateSetDictionary
+#define get_crc_table itk_get_crc_table
+#define gzclose itk_gzclose
+#define gzdopen itk_gzdopen
+#define gzeof itk_gzeof
+#define gzerror itk_gzerror
+#define gzflush itk_gzflush
+#define gzgetc itk_gzgetc
+#define gzgets itk_gzgets
+#define gzopen itk_gzopen
+#define gzprintf itk_gzprintf
+#define gzputc itk_gzputc
+#define gzputs itk_gzputs
+#define gzread itk_gzread
+#define gzrewind itk_gzrewind
+#define gzseek itk_gzseek
+#define gzsetparams itk_gzsetparams
+#define gztell itk_gztell
+#define gzwrite itk_gzwrite
+#define inflate itk_inflate
+#define inflateEnd itk_inflateEnd
+#define inflateInit2_ itk_inflateInit2_
+#define inflateInit_ itk_inflateInit_
+#define inflateReset itk_inflateReset
+#define inflateSetDictionary itk_inflateSetDictionary
+#define inflateSync itk_inflateSync
+#define inflateSyncPoint itk_inflateSyncPoint
+#define inflate_blocks itk_inflate_blocks
+#define inflate_blocks_free itk_inflate_blocks_free
+#define inflate_blocks_new itk_inflate_blocks_new
+#define inflate_blocks_reset itk_inflate_blocks_reset
+#define inflate_blocks_sync_point itk_inflate_blocks_sync_point
+#define inflate_codes itk_inflate_codes
+#define inflate_codes_free itk_inflate_codes_free
+#define inflate_codes_new itk_inflate_codes_new
+#define inflate_copyright itk_inflate_copyright
+#define inflate_fast itk_inflate_fast
+#define inflate_flush itk_inflate_flush
+#define inflate_mask itk_inflate_mask
+#define inflate_set_dictionary itk_inflate_set_dictionary
+#define inflate_trees_bits itk_inflate_trees_bits
+#define inflate_trees_dynamic itk_inflate_trees_dynamic
+#define inflate_trees_fixed itk_inflate_trees_fixed
+#define uncompress itk_uncompress
+#define zError itk_zError
+#define zcalloc itk_zcalloc
+#define zcfree itk_zcfree
+#define zlibVersion itk_zlibVersion
+#define z_errmsg itk_z_errmsg
+
+#endif
diff --git a/Utilities/ITK/Utilities/zlib/maketree.c b/Utilities/ITK/Utilities/zlib/maketree.c
new file mode 100644
index 0000000000..af0e293095
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/maketree.c
@@ -0,0 +1,86 @@
+/* maketree.c -- make inffixed.h table for decoding fixed codes
+ * Copyright (C) 1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* This program is included in the distribution for completeness.
+   You do not need to compile or run this program since inffixed.h
+   is already included in the distribution.  To use this program
+   you need to compile zlib with BUILDFIXED defined and then compile
+   and link this program with the zlib library.  Then the output of
+   this program can be piped to inffixed.h. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "zutil.h"
+#include "inftrees.h"
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* generate initialization table for an inflate_huft structure array */
+void maketree(uInt b, inflate_huft *t)
+{
+  int i, e;
+
+  i = 0;
+  while (1)
+  {
+    e = t[i].exop;
+    if (e && (e & (16+64)) == 0)        /* table pointer */
+    {
+      fprintf(stderr, "maketree: cannot initialize sub-tables!\n");
+      exit(1);
+    }
+    if (i % 4 == 0)
+      printf("\n   ");
+    printf(" {{{%u,%u}},%u}", t[i].exop, t[i].bits, t[i].base);
+    if (++i == (1<<b))
+      break;
+    putchar(',');
+  }
+  puts("");
+}
+
+/* create the fixed tables in C initialization syntax */
+int main(void)
+{
+  int r;
+  uInt bl, bd;
+  inflate_huft *tl, *td;
+  z_stream z;
+
+  z.zalloc = zcalloc;
+  z.opaque = (voidpf)0;
+  z.zfree = zcfree;
+  r = inflate_trees_fixed(&bl, &bd, &tl, &td, &z);
+  if (r)
+  {
+    fprintf(stderr, "inflate_trees_fixed error %d\n", r);
+    return 1;
+  }
+  puts("/* inffixed.h -- table for decoding fixed codes");
+  puts(" * Generated automatically by the maketree.c program");
+  puts(" */");
+  puts("");
+  puts("/* WARNING: this file should *not* be used by applications. It is");
+  puts("   part of the implementation of the compression library and is");
+  puts("   subject to change. Applications should only use zlib.h.");
+  puts(" */");
+  puts("");
+  printf("local uInt fixed_bl = %d;\n", bl);
+  printf("local uInt fixed_bd = %d;\n", bd);
+  printf("local inflate_huft fixed_tl[] = {");
+  maketree(bl, tl);
+  puts("  };");
+  printf("local inflate_huft fixed_td[] = {");
+  maketree(bd, td);
+  puts("  };");
+  return 0;
+}
diff --git a/Utilities/ITK/Utilities/zlib/minigzip.c b/Utilities/ITK/Utilities/zlib/minigzip.c
new file mode 100644
index 0000000000..7215eaeb0f
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/minigzip.c
@@ -0,0 +1,320 @@
+/* minigzip.c -- simulate gzip using the zlib compression library
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/*
+ * minigzip is a minimal implementation of the gzip utility. This is
+ * only an example of using zlib and isn't meant to replace the
+ * full-featured gzip. No attempt is made to deal with file systems
+ * limiting names to 14 or 8+3 characters, etc... Error checking is
+ * very limited. So use minigzip only for testing; use gzip for the
+ * real thing. On MSDOS, use only on file names without extension
+ * or in pipe mode.
+ */
+
+/* @(#) $Id$ */
+
+#include <stdio.h>
+#include "zlib.h"
+
+#ifdef STDC
+#  include <string.h>
+#  include <stdlib.h>
+#else
+   extern void exit  OF((int));
+#endif
+
+#ifdef USE_MMAP
+#  include <sys/types.h>
+#  include <sys/mman.h>
+#  include <sys/stat.h>
+#endif
+
+#if defined(MSDOS) || defined(OS2) || defined(WIN32)
+#  include <fcntl.h>
+#  include <io.h>
+#  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
+#else
+#  define SET_BINARY_MODE(file)
+#endif
+
+#ifdef VMS
+#  define unlink delete
+#  define GZ_SUFFIX "-gz"
+#endif
+#ifdef RISCOS
+#  define unlink remove
+#  define GZ_SUFFIX "-gz"
+#  define fileno(file) file->__file
+#endif
+#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
+#  include <unix.h> /* for fileno */
+#endif
+
+#ifndef WIN32 /* unlink already in stdio.h for WIN32 */
+  extern int unlink OF((const char *));
+#endif
+
+#ifndef GZ_SUFFIX
+#  define GZ_SUFFIX ".gz"
+#endif
+#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1)
+
+#define BUFLEN      16384
+#define MAX_NAME_LEN 1024
+
+#ifdef MAXSEG_64K
+#  define local static
+   /* Needed for systems with limitation on stack size. */
+#else
+#  define local
+#endif
+
+char *prog;
+
+void error            OF((const char *msg));
+void gz_compress      OF((FILE   *in, gzFile out));
+#ifdef USE_MMAP
+int  gz_compress_mmap OF((FILE   *in, gzFile out));
+#endif
+void gz_uncompress    OF((gzFile in, FILE   *out));
+void file_compress    OF((char  *file, char *mode));
+void file_uncompress  OF((char  *file));
+int  main             OF((int argc, char *argv[]));
+
+/* ===========================================================================
+ * Display error message and exit
+ */
+void error(msg)
+    const char *msg;
+{
+    fprintf(stderr, "%s: %s\n", prog, msg);
+    exit(1);
+}
+
+/* ===========================================================================
+ * Compress input to output then close both files.
+ */
+
+void gz_compress(in, out)
+    FILE   *in;
+    gzFile out;
+{
+    local char buf[BUFLEN];
+    int len;
+    int err;
+
+#ifdef USE_MMAP
+    /* Try first compressing with mmap. If mmap fails (minigzip used in a
+     * pipe), use the normal fread loop.
+     */
+    if (gz_compress_mmap(in, out) == Z_OK) return;
+#endif
+    for (;;) {
+        len = fread(buf, 1, sizeof(buf), in);
+        if (ferror(in)) {
+            perror("fread");
+            exit(1);
+        }
+        if (len == 0) break;
+
+        if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err));
+    }
+    fclose(in);
+    if (gzclose(out) != Z_OK) error("failed gzclose");
+}
+
+#ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech@eso.org> */
+
+/* Try compressing the input file at once using mmap. Return Z_OK if
+ * if success, Z_ERRNO otherwise.
+ */
+int gz_compress_mmap(in, out)
+    FILE   *in;
+    gzFile out;
+{
+    int len;
+    int err;
+    int ifd = fileno(in);
+    caddr_t buf;    /* mmap'ed buffer for the entire input file */
+    off_t buf_len;  /* length of the input file */
+    struct stat sb;
+
+    /* Determine the size of the file, needed for mmap: */
+    if (fstat(ifd, &sb) < 0) return Z_ERRNO;
+    buf_len = sb.st_size;
+    if (buf_len <= 0) return Z_ERRNO;
+
+    /* Now do the actual mmap: */
+    buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0); 
+    if (buf == (caddr_t)(-1)) return Z_ERRNO;
+
+    /* Compress the whole file at once: */
+    len = gzwrite(out, (char *)buf, (unsigned)buf_len);
+
+    if (len != (int)buf_len) error(gzerror(out, &err));
+
+    munmap(buf, buf_len);
+    fclose(in);
+    if (gzclose(out) != Z_OK) error("failed gzclose");
+    return Z_OK;
+}
+#endif /* USE_MMAP */
+
+/* ===========================================================================
+ * Uncompress input to output then close both files.
+ */
+void gz_uncompress(in, out)
+    gzFile in;
+    FILE   *out;
+{
+    local char buf[BUFLEN];
+    int len;
+    int err;
+
+    for (;;) {
+        len = gzread(in, buf, sizeof(buf));
+        if (len < 0) error (gzerror(in, &err));
+        if (len == 0) break;
+
+        if ((int)fwrite(buf, 1, (unsigned)len, out) != len) {
+	    error("failed fwrite");
+	}
+    }
+    if (fclose(out)) error("failed fclose");
+
+    if (gzclose(in) != Z_OK) error("failed gzclose");
+}
+
+
+/* ===========================================================================
+ * Compress the given file: create a corresponding .gz file and remove the
+ * original.
+ */
+void file_compress(file, mode)
+    char  *file;
+    char  *mode;
+{
+    local char outfile[MAX_NAME_LEN];
+    FILE  *in;
+    gzFile out;
+
+    strcpy(outfile, file);
+    strcat(outfile, GZ_SUFFIX);
+
+    in = fopen(file, "rb");
+    if (in == NULL) {
+        perror(file);
+        exit(1);
+    }
+    out = gzopen(outfile, mode);
+    if (out == NULL) {
+        fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile);
+        exit(1);
+    }
+    gz_compress(in, out);
+
+    unlink(file);
+}
+
+
+/* ===========================================================================
+ * Uncompress the given file and remove the original.
+ */
+void file_uncompress(file)
+    char  *file;
+{
+    local char buf[MAX_NAME_LEN];
+    char *infile, *outfile;
+    FILE  *out;
+    gzFile in;
+    int len = strlen(file);
+
+    strcpy(buf, file);
+
+    if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) {
+        infile = file;
+        outfile = buf;
+        outfile[len-3] = '\0';
+    } else {
+        outfile = file;
+        infile = buf;
+        strcat(infile, GZ_SUFFIX);
+    }
+    in = gzopen(infile, "rb");
+    if (in == NULL) {
+        fprintf(stderr, "%s: can't gzopen %s\n", prog, infile);
+        exit(1);
+    }
+    out = fopen(outfile, "wb");
+    if (out == NULL) {
+        perror(file);
+        exit(1);
+    }
+
+    gz_uncompress(in, out);
+
+    unlink(infile);
+}
+
+
+/* ===========================================================================
+ * Usage:  minigzip [-d] [-f] [-h] [-1 to -9] [files...]
+ *   -d : decompress
+ *   -f : compress with Z_FILTERED
+ *   -h : compress with Z_HUFFMAN_ONLY
+ *   -1 to -9 : compression level
+ */
+
+int main(argc, argv)
+    int argc;
+    char *argv[];
+{
+    int uncompr = 0;
+    gzFile file;
+    char outmode[20];
+
+    strcpy(outmode, "wb6 ");
+
+    prog = argv[0];
+    argc--, argv++;
+
+    while (argc > 0) {
+      if (strcmp(*argv, "-d") == 0)
+	uncompr = 1;
+      else if (strcmp(*argv, "-f") == 0)
+	outmode[3] = 'f';
+      else if (strcmp(*argv, "-h") == 0)
+	outmode[3] = 'h';
+      else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' &&
+	       (*argv)[2] == 0)
+	outmode[2] = (*argv)[1];
+      else
+	break;
+      argc--, argv++;
+    }
+    if (argc == 0) {
+        SET_BINARY_MODE(stdin);
+        SET_BINARY_MODE(stdout);
+        if (uncompr) {
+            file = gzdopen(fileno(stdin), "rb");
+            if (file == NULL) error("can't gzdopen stdin");
+            gz_uncompress(file, stdout);
+        } else {
+            file = gzdopen(fileno(stdout), outmode);
+            if (file == NULL) error("can't gzdopen stdout");
+            gz_compress(stdin, file);
+        }
+    } else {
+        do {
+            if (uncompr) {
+                file_uncompress(*argv);
+            } else {
+                file_compress(*argv, outmode);
+            }
+        } while (argv++, --argc);
+    }
+    exit(0);
+    return 0; /* to avoid warning */
+}
diff --git a/Utilities/ITK/Utilities/zlib/trees.c b/Utilities/ITK/Utilities/zlib/trees.c
new file mode 100644
index 0000000000..f01fb30d85
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/trees.c
@@ -0,0 +1,1214 @@
+/* trees.c -- output deflated data using Huffman coding
+ * Copyright (C) 1995-1998 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/*
+ *  ALGORITHM
+ *
+ *      The "deflation" process uses several Huffman trees. The more
+ *      common source values are represented by shorter bit sequences.
+ *
+ *      Each code tree is stored in a compressed form which is itself
+ * a Huffman encoding of the lengths of all the code strings (in
+ * ascending order by source values).  The actual code strings are
+ * reconstructed from the lengths in the inflate process, as described
+ * in the deflate specification.
+ *
+ *  REFERENCES
+ *
+ *      Deutsch, L.P.,"'Deflate' Compressed Data Format Specification".
+ *      Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc
+ *
+ *      Storer, James A.
+ *          Data Compression:  Methods and Theory, pp. 49-50.
+ *          Computer Science Press, 1988.  ISBN 0-7167-8156-5.
+ *
+ *      Sedgewick, R.
+ *          Algorithms, p290.
+ *          Addison-Wesley, 1983. ISBN 0-201-06672-6.
+ */
+
+/* @(#) $Id$ */
+
+/* #define GEN_TREES_H */
+
+#include "deflate.h"
+
+#ifdef DEBUG
+#  include <ctype.h>
+#endif
+
+/* ===========================================================================
+ * Constants
+ */
+
+#define MAX_BL_BITS 7
+/* Bit length codes must not exceed MAX_BL_BITS bits */
+
+#define END_BLOCK 256
+/* end of block literal code */
+
+#define REP_3_6      16
+/* repeat previous bit length 3-6 times (2 bits of repeat count) */
+
+#define REPZ_3_10    17
+/* repeat a zero length 3-10 times  (3 bits of repeat count) */
+
+#define REPZ_11_138  18
+/* repeat a zero length 11-138 times  (7 bits of repeat count) */
+
+local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */
+   = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
+
+local const int extra_dbits[D_CODES] /* extra bits for each distance code */
+   = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
+
+local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */
+   = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
+
+local const uch bl_order[BL_CODES]
+   = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+/* The lengths of the bit length codes are sent in order of decreasing
+ * probability, to avoid transmitting the lengths for unused bit length codes.
+ */
+
+#define Buf_size (8 * 2*sizeof(char))
+/* Number of bits used within bi_buf. (bi_buf might be implemented on
+ * more than 16 bits on some systems.)
+ */
+
+/* ===========================================================================
+ * Local data. These are initialized only once.
+ */
+
+#define DIST_CODE_LEN  512 /* see definition of array dist_code below */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+/* non ANSI compilers may not accept trees.h */
+
+local ct_data static_ltree[L_CODES+2];
+/* The static literal tree. Since the bit lengths are imposed, there is no
+ * need for the L_CODES extra codes used during heap construction. However
+ * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
+ * below).
+ */
+
+local ct_data static_dtree[D_CODES];
+/* The static distance tree. (Actually a trivial tree since all codes use
+ * 5 bits.)
+ */
+
+uch _dist_code[DIST_CODE_LEN];
+/* Distance codes. The first 256 values correspond to the distances
+ * 3 .. 258, the last 256 values correspond to the top 8 bits of
+ * the 15 bit distances.
+ */
+
+uch _length_code[MAX_MATCH-MIN_MATCH+1];
+/* length code for each normalized match length (0 == MIN_MATCH) */
+
+local int base_length[LENGTH_CODES];
+/* First normalized length for each code (0 = MIN_MATCH) */
+
+local int base_dist[D_CODES];
+/* First normalized distance for each code (0 = distance of 1) */
+
+#else
+#  include "trees.h"
+#endif /* GEN_TREES_H */
+
+struct static_tree_desc_s {
+    const ct_data *static_tree;  /* static tree or NULL */
+    const intf *extra_bits;      /* extra bits for each code or NULL */
+    int     extra_base;          /* base index for extra_bits */
+    int     elems;               /* max number of elements in the tree */
+    int     max_length;          /* max bit length for the codes */
+};
+
+local static_tree_desc  static_l_desc =
+{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};
+
+local static_tree_desc  static_d_desc =
+{static_dtree, extra_dbits, 0,          D_CODES, MAX_BITS};
+
+local static_tree_desc  static_bl_desc =
+{(const ct_data *)0, extra_blbits, 0,   BL_CODES, MAX_BL_BITS};
+
+/* ===========================================================================
+ * Local (static) routines in this file.
+ */
+
+local void tr_static_init OF((void));
+local void init_block     OF((deflate_state *s));
+local void pqdownheap     OF((deflate_state *s, ct_data *tree, int k));
+local void gen_bitlen     OF((deflate_state *s, tree_desc *desc));
+local void gen_codes      OF((ct_data *tree, int max_code, ushf *bl_count));
+local void build_tree     OF((deflate_state *s, tree_desc *desc));
+local void scan_tree      OF((deflate_state *s, ct_data *tree, int max_code));
+local void send_tree      OF((deflate_state *s, ct_data *tree, int max_code));
+local int  build_bl_tree  OF((deflate_state *s));
+local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
+                              int blcodes));
+local void compress_block OF((deflate_state *s, ct_data *ltree,
+                              ct_data *dtree));
+local void set_data_type  OF((deflate_state *s));
+local unsigned bi_reverse OF((unsigned value, int length));
+local void bi_windup      OF((deflate_state *s));
+local void bi_flush       OF((deflate_state *s));
+local void copy_block     OF((deflate_state *s, charf *buf, unsigned len,
+                              int header));
+
+#ifdef GEN_TREES_H
+local void gen_trees_header OF((void));
+#endif
+
+#ifndef DEBUG
+#  define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)
+   /* Send a code of the given tree. c and tree must not have side effects */
+
+#else /* DEBUG */
+#  define send_code(s, c, tree) \
+     { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \
+       send_bits(s, tree[c].Code, tree[c].Len); }
+#endif
+
+/* ===========================================================================
+ * Output a short LSB first on the stream.
+ * IN assertion: there is enough room in pendingBuf.
+ */
+#define put_short(s, w) { \
+    put_byte(s, (uch)((w) & 0xff)); \
+    put_byte(s, (uch)((ush)(w) >> 8)); \
+}
+
+/* ===========================================================================
+ * Send a value on a given number of bits.
+ * IN assertion: length <= 16 and value fits in length bits.
+ */
+#ifdef DEBUG
+local void send_bits      OF((deflate_state *s, int value, int length));
+
+local void send_bits(s, value, length)
+    deflate_state *s;
+    int value;  /* value to send */
+    int length; /* number of bits */
+{
+    Tracevv((stderr," l %2d v %4x ", length, value));
+    Assert(length > 0 && length <= 15, "invalid length");
+    s->bits_sent += (ulg)length;
+
+    /* If not enough room in bi_buf, use (valid) bits from bi_buf and
+     * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
+     * unused bits in value.
+     */
+    if (s->bi_valid > (int)Buf_size - length) {
+        s->bi_buf |= (value << s->bi_valid);
+        put_short(s, s->bi_buf);
+        s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
+        s->bi_valid += length - Buf_size;
+    } else {
+        s->bi_buf |= value << s->bi_valid;
+        s->bi_valid += length;
+    }
+}
+#else /* !DEBUG */
+
+#define send_bits(s, value, length) \
+{ int len = length;\
+  if (s->bi_valid > (int)Buf_size - len) {\
+    int val = value;\
+    s->bi_buf |= (val << s->bi_valid);\
+    put_short(s, s->bi_buf);\
+    s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
+    s->bi_valid += len - Buf_size;\
+  } else {\
+    s->bi_buf |= (value) << s->bi_valid;\
+    s->bi_valid += len;\
+  }\
+}
+#endif /* DEBUG */
+
+
+#define MAX(a,b) (a >= b ? a : b)
+/* the arguments must not have side effects */
+
+/* ===========================================================================
+ * Initialize the various 'constant' tables.
+ */
+local void tr_static_init()
+{
+#if defined(GEN_TREES_H) || !defined(STDC)
+    static int static_init_done = 0;
+    int n;        /* iterates over tree elements */
+    int bits;     /* bit counter */
+    int length;   /* length value */
+    int code;     /* code value */
+    int dist;     /* distance index */
+    ush bl_count[MAX_BITS+1];
+    /* number of codes at each bit length for an optimal tree */
+
+    if (static_init_done) return;
+
+    /* For some embedded targets, global variables are not initialized: */
+    static_l_desc.static_tree = static_ltree;
+    static_l_desc.extra_bits = extra_lbits;
+    static_d_desc.static_tree = static_dtree;
+    static_d_desc.extra_bits = extra_dbits;
+    static_bl_desc.extra_bits = extra_blbits;
+
+    /* Initialize the mapping length (0..255) -> length code (0..28) */
+    length = 0;
+    for (code = 0; code < LENGTH_CODES-1; code++) {
+        base_length[code] = length;
+        for (n = 0; n < (1<<extra_lbits[code]); n++) {
+            _length_code[length++] = (uch)code;
+        }
+    }
+    Assert (length == 256, "tr_static_init: length != 256");
+    /* Note that the length 255 (match length 258) can be represented
+     * in two different ways: code 284 + 5 bits or code 285, so we
+     * overwrite length_code[255] to use the best encoding:
+     */
+    _length_code[length-1] = (uch)code;
+
+    /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
+    dist = 0;
+    for (code = 0 ; code < 16; code++) {
+        base_dist[code] = dist;
+        for (n = 0; n < (1<<extra_dbits[code]); n++) {
+            _dist_code[dist++] = (uch)code;
+        }
+    }
+    Assert (dist == 256, "tr_static_init: dist != 256");
+    dist >>= 7; /* from now on, all distances are divided by 128 */
+    for ( ; code < D_CODES; code++) {
+        base_dist[code] = dist << 7;
+        for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
+            _dist_code[256 + dist++] = (uch)code;
+        }
+    }
+    Assert (dist == 256, "tr_static_init: 256+dist != 512");
+
+    /* Construct the codes of the static literal tree */
+    for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
+    n = 0;
+    while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
+    while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
+    while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
+    while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
+    /* Codes 286 and 287 do not exist, but we must include them in the
+     * tree construction to get a canonical Huffman tree (longest code
+     * all ones)
+     */
+    gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count);
+
+    /* The static distance tree is trivial: */
+    for (n = 0; n < D_CODES; n++) {
+        static_dtree[n].Len = 5;
+        static_dtree[n].Code = bi_reverse((unsigned)n, 5);
+    }
+    static_init_done = 1;
+
+#  ifdef GEN_TREES_H
+    gen_trees_header();
+#  endif
+#endif /* defined(GEN_TREES_H) || !defined(STDC) */
+}
+
+/* ===========================================================================
+ * Genererate the file trees.h describing the static trees.
+ */
+#ifdef GEN_TREES_H
+#  ifndef DEBUG
+#    include <stdio.h>
+#  endif
+
+#  define SEPARATOR(i, last, width) \
+      ((i) == (last)? "\n};\n\n" :    \
+       ((i) % (width) == (width)-1 ? ",\n" : ", "))
+
+void gen_trees_header()
+{
+    FILE *header = fopen("trees.h", "w");
+    int i;
+
+    Assert (header != NULL, "Can't open trees.h");
+    fprintf(header,
+	    "/* header created automatically with -DGEN_TREES_H */\n\n");
+
+    fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n");
+    for (i = 0; i < L_CODES+2; i++) {
+	fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code,
+		static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5));
+    }
+
+    fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n");
+    for (i = 0; i < D_CODES; i++) {
+	fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code,
+		static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5));
+    }
+
+    fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n");
+    for (i = 0; i < DIST_CODE_LEN; i++) {
+	fprintf(header, "%2u%s", _dist_code[i],
+		SEPARATOR(i, DIST_CODE_LEN-1, 20));
+    }
+
+    fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n");
+    for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) {
+	fprintf(header, "%2u%s", _length_code[i],
+		SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20));
+    }
+
+    fprintf(header, "local const int base_length[LENGTH_CODES] = {\n");
+    for (i = 0; i < LENGTH_CODES; i++) {
+	fprintf(header, "%1u%s", base_length[i],
+		SEPARATOR(i, LENGTH_CODES-1, 20));
+    }
+
+    fprintf(header, "local const int base_dist[D_CODES] = {\n");
+    for (i = 0; i < D_CODES; i++) {
+	fprintf(header, "%5u%s", base_dist[i],
+		SEPARATOR(i, D_CODES-1, 10));
+    }
+
+    fclose(header);
+}
+#endif /* GEN_TREES_H */
+
+/* ===========================================================================
+ * Initialize the tree data structures for a new zlib stream.
+ */
+void _tr_init(s)
+    deflate_state *s;
+{
+    tr_static_init();
+
+    s->l_desc.dyn_tree = s->dyn_ltree;
+    s->l_desc.stat_desc = &static_l_desc;
+
+    s->d_desc.dyn_tree = s->dyn_dtree;
+    s->d_desc.stat_desc = &static_d_desc;
+
+    s->bl_desc.dyn_tree = s->bl_tree;
+    s->bl_desc.stat_desc = &static_bl_desc;
+
+    s->bi_buf = 0;
+    s->bi_valid = 0;
+    s->last_eob_len = 8; /* enough lookahead for inflate */
+#ifdef DEBUG
+    s->compressed_len = 0L;
+    s->bits_sent = 0L;
+#endif
+
+    /* Initialize the first block of the first file: */
+    init_block(s);
+}
+
+/* ===========================================================================
+ * Initialize a new block.
+ */
+local void init_block(s)
+    deflate_state *s;
+{
+    int n; /* iterates over tree elements */
+
+    /* Initialize the trees. */
+    for (n = 0; n < L_CODES;  n++) s->dyn_ltree[n].Freq = 0;
+    for (n = 0; n < D_CODES;  n++) s->dyn_dtree[n].Freq = 0;
+    for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;
+
+    s->dyn_ltree[END_BLOCK].Freq = 1;
+    s->opt_len = s->static_len = 0L;
+    s->last_lit = s->matches = 0;
+}
+
+#define SMALLEST 1
+/* Index within the heap array of least frequent node in the Huffman tree */
+
+
+/* ===========================================================================
+ * Remove the smallest element from the heap and recreate the heap with
+ * one less element. Updates heap and heap_len.
+ */
+#define pqremove(s, tree, top) \
+{\
+    top = s->heap[SMALLEST]; \
+    s->heap[SMALLEST] = s->heap[s->heap_len--]; \
+    pqdownheap(s, tree, SMALLEST); \
+}
+
+/* ===========================================================================
+ * Compares to subtrees, using the tree depth as tie breaker when
+ * the subtrees have equal frequency. This minimizes the worst case length.
+ */
+#define smaller(tree, n, m, depth) \
+   (tree[n].Freq < tree[m].Freq || \
+   (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
+
+/* ===========================================================================
+ * Restore the heap property by moving down the tree starting at node k,
+ * exchanging a node with the smallest of its two sons if necessary, stopping
+ * when the heap property is re-established (each father smaller than its
+ * two sons).
+ */
+local void pqdownheap(s, tree, k)
+    deflate_state *s;
+    ct_data *tree;  /* the tree to restore */
+    int k;               /* node to move down */
+{
+    int v = s->heap[k];
+    int j = k << 1;  /* left son of k */
+    while (j <= s->heap_len) {
+        /* Set j to the smallest of the two sons: */
+        if (j < s->heap_len &&
+            smaller(tree, s->heap[j+1], s->heap[j], s->depth)) {
+            j++;
+        }
+        /* Exit if v is smaller than both sons */
+        if (smaller(tree, v, s->heap[j], s->depth)) break;
+
+        /* Exchange v with the smallest son */
+        s->heap[k] = s->heap[j];  k = j;
+
+        /* And continue down the tree, setting j to the left son of k */
+        j <<= 1;
+    }
+    s->heap[k] = v;
+}
+
+/* ===========================================================================
+ * Compute the optimal bit lengths for a tree and update the total bit length
+ * for the current block.
+ * IN assertion: the fields freq and dad are set, heap[heap_max] and
+ *    above are the tree nodes sorted by increasing frequency.
+ * OUT assertions: the field len is set to the optimal bit length, the
+ *     array bl_count contains the frequencies for each bit length.
+ *     The length opt_len is updated; static_len is also updated if stree is
+ *     not null.
+ */
+local void gen_bitlen(s, desc)
+    deflate_state *s;
+    tree_desc *desc;    /* the tree descriptor */
+{
+    ct_data *tree        = desc->dyn_tree;
+    int max_code         = desc->max_code;
+    const ct_data *stree = desc->stat_desc->static_tree;
+    const intf *extra    = desc->stat_desc->extra_bits;
+    int base             = desc->stat_desc->extra_base;
+    int max_length       = desc->stat_desc->max_length;
+    int h;              /* heap index */
+    int n, m;           /* iterate over the tree elements */
+    int bits;           /* bit length */
+    int xbits;          /* extra bits */
+    ush f;              /* frequency */
+    int overflow = 0;   /* number of elements with bit length too large */
+
+    for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;
+
+    /* In a first pass, compute the optimal bit lengths (which may
+     * overflow in the case of the bit length tree).
+     */
+    tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */
+
+    for (h = s->heap_max+1; h < HEAP_SIZE; h++) {
+        n = s->heap[h];
+        bits = tree[tree[n].Dad].Len + 1;
+        if (bits > max_length) bits = max_length, overflow++;
+        tree[n].Len = (ush)bits;
+        /* We overwrite tree[n].Dad which is no longer needed */
+
+        if (n > max_code) continue; /* not a leaf node */
+
+        s->bl_count[bits]++;
+        xbits = 0;
+        if (n >= base) xbits = extra[n-base];
+        f = tree[n].Freq;
+        s->opt_len += (ulg)f * (bits + xbits);
+        if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits);
+    }
+    if (overflow == 0) return;
+
+    Trace((stderr,"\nbit length overflow\n"));
+    /* This happens for example on obj2 and pic of the Calgary corpus */
+
+    /* Find the first bit length which could increase: */
+    do {
+        bits = max_length-1;
+        while (s->bl_count[bits] == 0) bits--;
+        s->bl_count[bits]--;      /* move one leaf down the tree */
+        s->bl_count[bits+1] += 2; /* move one overflow item as its brother */
+        s->bl_count[max_length]--;
+        /* The brother of the overflow item also moves one step up,
+         * but this does not affect bl_count[max_length]
+         */
+        overflow -= 2;
+    } while (overflow > 0);
+
+    /* Now recompute all bit lengths, scanning in increasing frequency.
+     * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
+     * lengths instead of fixing only the wrong ones. This idea is taken
+     * from 'ar' written by Haruhiko Okumura.)
+     */
+    for (bits = max_length; bits != 0; bits--) {
+        n = s->bl_count[bits];
+        while (n != 0) {
+            m = s->heap[--h];
+            if (m > max_code) continue;
+            if (tree[m].Len != (unsigned) bits) {
+                Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
+                s->opt_len += ((long)bits - (long)tree[m].Len)
+                              *(long)tree[m].Freq;
+                tree[m].Len = (ush)bits;
+            }
+            n--;
+        }
+    }
+}
+
+/* ===========================================================================
+ * Generate the codes for a given tree and bit counts (which need not be
+ * optimal).
+ * IN assertion: the array bl_count contains the bit length statistics for
+ * the given tree and the field len is set for all tree elements.
+ * OUT assertion: the field code is set for all tree elements of non
+ *     zero code length.
+ */
+local void gen_codes (tree, max_code, bl_count)
+    ct_data *tree;             /* the tree to decorate */
+    int max_code;              /* largest code with non zero frequency */
+    ushf *bl_count;            /* number of codes at each bit length */
+{
+    ush next_code[MAX_BITS+1]; /* next code value for each bit length */
+    ush code = 0;              /* running code value */
+    int bits;                  /* bit index */
+    int n;                     /* code index */
+
+    /* The distribution counts are first used to generate the code values
+     * without bit reversal.
+     */
+    for (bits = 1; bits <= MAX_BITS; bits++) {
+        next_code[bits] = code = (code + bl_count[bits-1]) << 1;
+    }
+    /* Check that the bit counts in bl_count are consistent. The last code
+     * must be all ones.
+     */
+    Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
+            "inconsistent bit counts");
+    Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
+
+    for (n = 0;  n <= max_code; n++) {
+        int len = tree[n].Len;
+        if (len == 0) continue;
+        /* Now reverse the bits */
+        tree[n].Code = bi_reverse(next_code[len]++, len);
+
+        Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
+             n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
+    }
+}
+
+/* ===========================================================================
+ * Construct one Huffman tree and assigns the code bit strings and lengths.
+ * Update the total bit length for the current block.
+ * IN assertion: the field freq is set for all tree elements.
+ * OUT assertions: the fields len and code are set to the optimal bit length
+ *     and corresponding code. The length opt_len is updated; static_len is
+ *     also updated if stree is not null. The field max_code is set.
+ */
+local void build_tree(s, desc)
+    deflate_state *s;
+    tree_desc *desc; /* the tree descriptor */
+{
+    ct_data *tree         = desc->dyn_tree;
+    const ct_data *stree  = desc->stat_desc->static_tree;
+    int elems             = desc->stat_desc->elems;
+    int n, m;          /* iterate over heap elements */
+    int max_code = -1; /* largest code with non zero frequency */
+    int node;          /* new node being created */
+
+    /* Construct the initial heap, with least frequent element in
+     * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+     * heap[0] is not used.
+     */
+    s->heap_len = 0, s->heap_max = HEAP_SIZE;
+
+    for (n = 0; n < elems; n++) {
+        if (tree[n].Freq != 0) {
+            s->heap[++(s->heap_len)] = max_code = n;
+            s->depth[n] = 0;
+        } else {
+            tree[n].Len = 0;
+        }
+    }
+
+    /* The pkzip format requires that at least one distance code exists,
+     * and that at least one bit should be sent even if there is only one
+     * possible code. So to avoid special checks later on we force at least
+     * two codes of non zero frequency.
+     */
+    while (s->heap_len < 2) {
+        node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);
+        tree[node].Freq = 1;
+        s->depth[node] = 0;
+        s->opt_len--; if (stree) s->static_len -= stree[node].Len;
+        /* node is 0 or 1 so it does not have extra bits */
+    }
+    desc->max_code = max_code;
+
+    /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+     * establish sub-heaps of increasing lengths:
+     */
+    for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);
+
+    /* Construct the Huffman tree by repeatedly combining the least two
+     * frequent nodes.
+     */
+    node = elems;              /* next internal node of the tree */
+    do {
+        pqremove(s, tree, n);  /* n = node of least frequency */
+        m = s->heap[SMALLEST]; /* m = node of next least frequency */
+
+        s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */
+        s->heap[--(s->heap_max)] = m;
+
+        /* Create a new node father of n and m */
+        tree[node].Freq = tree[n].Freq + tree[m].Freq;
+        s->depth[node] = (uch) (MAX(s->depth[n], s->depth[m]) + 1);
+        tree[n].Dad = tree[m].Dad = (ush)node;
+#ifdef DUMP_BL_TREE
+        if (tree == s->bl_tree) {
+            fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
+                    node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
+        }
+#endif
+        /* and insert the new node in the heap */
+        s->heap[SMALLEST] = node++;
+        pqdownheap(s, tree, SMALLEST);
+
+    } while (s->heap_len >= 2);
+
+    s->heap[--(s->heap_max)] = s->heap[SMALLEST];
+
+    /* At this point, the fields freq and dad are set. We can now
+     * generate the bit lengths.
+     */
+    gen_bitlen(s, (tree_desc *)desc);
+
+    /* The field len is now set, we can generate the bit codes */
+    gen_codes ((ct_data *)tree, max_code, s->bl_count);
+}
+
+/* ===========================================================================
+ * Scan a literal or distance tree to determine the frequencies of the codes
+ * in the bit length tree.
+ */
+local void scan_tree (s, tree, max_code)
+    deflate_state *s;
+    ct_data *tree;   /* the tree to be scanned */
+    int max_code;    /* and its largest code of non zero frequency */
+{
+    int n;                     /* iterates over all tree elements */
+    int prevlen = -1;          /* last emitted length */
+    int curlen;                /* length of current code */
+    int nextlen = tree[0].Len; /* length of next code */
+    int count = 0;             /* repeat count of the current code */
+    int max_count = 7;         /* max repeat count */
+    int min_count = 4;         /* min repeat count */
+
+    if (nextlen == 0) max_count = 138, min_count = 3;
+    tree[max_code+1].Len = (ush)0xffff; /* guard */
+
+    for (n = 0; n <= max_code; n++) {
+        curlen = nextlen; nextlen = tree[n+1].Len;
+        if (++count < max_count && curlen == nextlen) {
+            continue;
+        } else if (count < min_count) {
+            s->bl_tree[curlen].Freq += count;
+        } else if (curlen != 0) {
+            if (curlen != prevlen) s->bl_tree[curlen].Freq++;
+            s->bl_tree[REP_3_6].Freq++;
+        } else if (count <= 10) {
+            s->bl_tree[REPZ_3_10].Freq++;
+        } else {
+            s->bl_tree[REPZ_11_138].Freq++;
+        }
+        count = 0; prevlen = curlen;
+        if (nextlen == 0) {
+            max_count = 138, min_count = 3;
+        } else if (curlen == nextlen) {
+            max_count = 6, min_count = 3;
+        } else {
+            max_count = 7, min_count = 4;
+        }
+    }
+}
+
+/* ===========================================================================
+ * Send a literal or distance tree in compressed form, using the codes in
+ * bl_tree.
+ */
+local void send_tree (s, tree, max_code)
+    deflate_state *s;
+    ct_data *tree; /* the tree to be scanned */
+    int max_code;       /* and its largest code of non zero frequency */
+{
+    int n;                     /* iterates over all tree elements */
+    int prevlen = -1;          /* last emitted length */
+    int curlen;                /* length of current code */
+    int nextlen = tree[0].Len; /* length of next code */
+    int count = 0;             /* repeat count of the current code */
+    int max_count = 7;         /* max repeat count */
+    int min_count = 4;         /* min repeat count */
+
+    /* tree[max_code+1].Len = -1; */  /* guard already set */
+    if (nextlen == 0) max_count = 138, min_count = 3;
+
+    for (n = 0; n <= max_code; n++) {
+        curlen = nextlen; nextlen = tree[n+1].Len;
+        if (++count < max_count && curlen == nextlen) {
+            continue;
+        } else if (count < min_count) {
+            do { send_code(s, curlen, s->bl_tree); } while (--count != 0);
+
+        } else if (curlen != 0) {
+            if (curlen != prevlen) {
+                send_code(s, curlen, s->bl_tree); count--;
+            }
+            Assert(count >= 3 && count <= 6, " 3_6?");
+            send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2);
+
+        } else if (count <= 10) {
+            send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3);
+
+        } else {
+            send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7);
+        }
+        count = 0; prevlen = curlen;
+        if (nextlen == 0) {
+            max_count = 138, min_count = 3;
+        } else if (curlen == nextlen) {
+            max_count = 6, min_count = 3;
+        } else {
+            max_count = 7, min_count = 4;
+        }
+    }
+}
+
+/* ===========================================================================
+ * Construct the Huffman tree for the bit lengths and return the index in
+ * bl_order of the last bit length code to send.
+ */
+local int build_bl_tree(s)
+    deflate_state *s;
+{
+    int max_blindex;  /* index of last bit length code of non zero freq */
+
+    /* Determine the bit length frequencies for literal and distance trees */
+    scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code);
+    scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code);
+
+    /* Build the bit length tree: */
+    build_tree(s, (tree_desc *)(&(s->bl_desc)));
+    /* opt_len now includes the length of the tree representations, except
+     * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+     */
+
+    /* Determine the number of bit length codes to send. The pkzip format
+     * requires that at least 4 bit length codes be sent. (appnote.txt says
+     * 3 but the actual value used is 4.)
+     */
+    for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
+        if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;
+    }
+    /* Update opt_len to include the bit length tree and counts */
+    s->opt_len += 3*(max_blindex+1) + 5+5+4;
+    Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
+            s->opt_len, s->static_len));
+
+    return max_blindex;
+}
+
+/* ===========================================================================
+ * Send the header for a block using dynamic Huffman trees: the counts, the
+ * lengths of the bit length codes, the literal tree and the distance tree.
+ * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ */
+local void send_all_trees(s, lcodes, dcodes, blcodes)
+    deflate_state *s;
+    int lcodes, dcodes, blcodes; /* number of codes for each tree */
+{
+    int rank;                    /* index in bl_order */
+
+    Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
+    Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
+            "too many codes");
+    Tracev((stderr, "\nbl counts: "));
+    send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */
+    send_bits(s, dcodes-1,   5);
+    send_bits(s, blcodes-4,  4); /* not -3 as stated in appnote.txt */
+    for (rank = 0; rank < blcodes; rank++) {
+        Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
+        send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
+    }
+    Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
+
+    send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */
+    Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
+
+    send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */
+    Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
+}
+
+/* ===========================================================================
+ * Send a stored block
+ */
+void _tr_stored_block(s, buf, stored_len, eof)
+    deflate_state *s;
+    charf *buf;       /* input block */
+    ulg stored_len;   /* length of input block */
+    int eof;          /* true if this is the last block for a file */
+{
+    send_bits(s, (STORED_BLOCK<<1)+eof, 3);  /* send block type */
+#ifdef DEBUG
+    s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
+    s->compressed_len += (stored_len + 4) << 3;
+#endif
+    copy_block(s, buf, (unsigned)stored_len, 1); /* with header */
+}
+
+/* ===========================================================================
+ * Send one empty static block to give enough lookahead for inflate.
+ * This takes 10 bits, of which 7 may remain in the bit buffer.
+ * The current inflate code requires 9 bits of lookahead. If the
+ * last two codes for the previous block (real code plus EOB) were coded
+ * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
+ * the last real code. In this case we send two empty static blocks instead
+ * of one. (There are no problems if the previous block is stored or fixed.)
+ * To simplify the code, we assume the worst case of last real code encoded
+ * on one bit only.
+ */
+void _tr_align(s)
+    deflate_state *s;
+{
+    send_bits(s, STATIC_TREES<<1, 3);
+    send_code(s, END_BLOCK, static_ltree);
+#ifdef DEBUG
+    s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
+#endif
+    bi_flush(s);
+    /* Of the 10 bits for the empty block, we have already sent
+     * (10 - bi_valid) bits. The lookahead for the last real code (before
+     * the EOB of the previous block) was thus at least one plus the length
+     * of the EOB plus what we have just sent of the empty static block.
+     */
+    if (1 + s->last_eob_len + 10 - s->bi_valid < 9) {
+        send_bits(s, STATIC_TREES<<1, 3);
+        send_code(s, END_BLOCK, static_ltree);
+#ifdef DEBUG
+        s->compressed_len += 10L;
+#endif
+        bi_flush(s);
+    }
+    s->last_eob_len = 7;
+}
+
+/* ===========================================================================
+ * Determine the best encoding for the current block: dynamic trees, static
+ * trees or store, and output the encoded block to the zip file.
+ */
+void _tr_flush_block(s, buf, stored_len, eof)
+    deflate_state *s;
+    charf *buf;       /* input block, or NULL if too old */
+    ulg stored_len;   /* length of input block */
+    int eof;          /* true if this is the last block for a file */
+{
+    ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
+    int max_blindex = 0;  /* index of last bit length code of non zero freq */
+
+    /* Build the Huffman trees unless a stored block is forced */
+    if (s->level > 0) {
+
+	 /* Check if the file is ascii or binary */
+	if (s->data_type == Z_UNKNOWN) set_data_type(s);
+
+	/* Construct the literal and distance trees */
+	build_tree(s, (tree_desc *)(&(s->l_desc)));
+	Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
+		s->static_len));
+
+	build_tree(s, (tree_desc *)(&(s->d_desc)));
+	Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
+		s->static_len));
+	/* At this point, opt_len and static_len are the total bit lengths of
+	 * the compressed block data, excluding the tree representations.
+	 */
+
+	/* Build the bit length tree for the above two trees, and get the index
+	 * in bl_order of the last bit length code to send.
+	 */
+	max_blindex = build_bl_tree(s);
+
+	/* Determine the best encoding. Compute first the block length in bytes*/
+	opt_lenb = (s->opt_len+3+7)>>3;
+	static_lenb = (s->static_len+3+7)>>3;
+
+	Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
+		opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
+		s->last_lit));
+
+	if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+
+    } else {
+        Assert(buf != (char*)0, "lost buf");
+	opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
+    }
+
+#ifdef FORCE_STORED
+    if (buf != (char*)0) { /* force stored block */
+#else
+    if (stored_len+4 <= opt_lenb && buf != (char*)0) {
+                       /* 4: two words for the lengths */
+#endif
+        /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+         * Otherwise we can't have processed more than WSIZE input bytes since
+         * the last block flush, because compression would have been
+         * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+         * transform a block into a stored block.
+         */
+        _tr_stored_block(s, buf, stored_len, eof);
+
+#ifdef FORCE_STATIC
+    } else if (static_lenb >= 0) { /* force static trees */
+#else
+    } else if (static_lenb == opt_lenb) {
+#endif
+        send_bits(s, (STATIC_TREES<<1)+eof, 3);
+        compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree);
+#ifdef DEBUG
+        s->compressed_len += 3 + s->static_len;
+#endif
+    } else {
+        send_bits(s, (DYN_TREES<<1)+eof, 3);
+        send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
+                       max_blindex+1);
+        compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree);
+#ifdef DEBUG
+        s->compressed_len += 3 + s->opt_len;
+#endif
+    }
+    Assert (s->compressed_len == s->bits_sent, "bad compressed size");
+    /* The above check is made mod 2^32, for files larger than 512 MB
+     * and uLong implemented on 32 bits.
+     */
+    init_block(s);
+
+    if (eof) {
+        bi_windup(s);
+#ifdef DEBUG
+        s->compressed_len += 7;  /* align on byte boundary */
+#endif
+    }
+    Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
+           s->compressed_len-7*eof));
+}
+
+/* ===========================================================================
+ * Save the match info and tally the frequency counts. Return true if
+ * the current block must be flushed.
+ */
+int _tr_tally (s, dist, lc)
+    deflate_state *s;
+    unsigned dist;  /* distance of matched string */
+    unsigned lc;    /* match length-MIN_MATCH or unmatched char (if dist==0) */
+{
+    s->d_buf[s->last_lit] = (ush)dist;
+    s->l_buf[s->last_lit++] = (uch)lc;
+    if (dist == 0) {
+        /* lc is the unmatched char */
+        s->dyn_ltree[lc].Freq++;
+    } else {
+        s->matches++;
+        /* Here, lc is the match length - MIN_MATCH */
+        dist--;             /* dist = match distance - 1 */
+        Assert((ush)dist < (ush)MAX_DIST(s) &&
+               (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
+               (ush)d_code(dist) < (ush)D_CODES,  "_tr_tally: bad match");
+
+        s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++;
+        s->dyn_dtree[d_code(dist)].Freq++;
+    }
+
+#ifdef TRUNCATE_BLOCK
+    /* Try to guess if it is profitable to stop the current block here */
+    if ((s->last_lit & 0x1fff) == 0 && s->level > 2) {
+        /* Compute an upper bound for the compressed length */
+        ulg out_length = (ulg)s->last_lit*8L;
+        ulg in_length = (ulg)((long)s->strstart - s->block_start);
+        int dcode;
+        for (dcode = 0; dcode < D_CODES; dcode++) {
+            out_length += (ulg)s->dyn_dtree[dcode].Freq *
+                (5L+extra_dbits[dcode]);
+        }
+        out_length >>= 3;
+        Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
+               s->last_lit, in_length, out_length,
+               100L - out_length*100L/in_length));
+        if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
+    }
+#endif
+    return (s->last_lit == s->lit_bufsize-1);
+    /* We avoid equality with lit_bufsize because of wraparound at 64K
+     * on 16 bit machines and because stored blocks are restricted to
+     * 64K-1 bytes.
+     */
+}
+
+/* ===========================================================================
+ * Send the block data compressed using the given Huffman trees
+ */
+local void compress_block(s, ltree, dtree)
+    deflate_state *s;
+    ct_data *ltree; /* literal tree */
+    ct_data *dtree; /* distance tree */
+{
+    unsigned dist;      /* distance of matched string */
+    int lc;             /* match length or unmatched char (if dist == 0) */
+    unsigned lx = 0;    /* running index in l_buf */
+    unsigned code;      /* the code to send */
+    int extra;          /* number of extra bits to send */
+
+    if (s->last_lit != 0) do {
+        dist = s->d_buf[lx];
+        lc = s->l_buf[lx++];
+        if (dist == 0) {
+            send_code(s, lc, ltree); /* send a literal byte */
+            Tracecv(isgraph(lc), (stderr," '%c' ", lc));
+        } else {
+            /* Here, lc is the match length - MIN_MATCH */
+            code = _length_code[lc];
+            send_code(s, code+LITERALS+1, ltree); /* send the length code */
+            extra = extra_lbits[code];
+            if (extra != 0) {
+                lc -= base_length[code];
+                send_bits(s, lc, extra);       /* send the extra length bits */
+            }
+            dist--; /* dist is now the match distance - 1 */
+            code = d_code(dist);
+            Assert (code < D_CODES, "bad d_code");
+
+            send_code(s, code, dtree);       /* send the distance code */
+            extra = extra_dbits[code];
+            if (extra != 0) {
+                dist -= base_dist[code];
+                send_bits(s, dist, extra);   /* send the extra distance bits */
+            }
+        } /* literal or match pair ? */
+
+        /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
+        Assert(s->pending < s->lit_bufsize + 2*lx, "pendingBuf overflow");
+
+    } while (lx < s->last_lit);
+
+    send_code(s, END_BLOCK, ltree);
+    s->last_eob_len = ltree[END_BLOCK].Len;
+}
+
+/* ===========================================================================
+ * Set the data type to ASCII or BINARY, using a crude approximation:
+ * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.
+ * IN assertion: the fields freq of dyn_ltree are set and the total of all
+ * frequencies does not exceed 64K (to fit in an int on 16 bit machines).
+ */
+local void set_data_type(s)
+    deflate_state *s;
+{
+    int n = 0;
+    unsigned ascii_freq = 0;
+    unsigned bin_freq = 0;
+    while (n < 7)        bin_freq += s->dyn_ltree[n++].Freq;
+    while (n < 128)    ascii_freq += s->dyn_ltree[n++].Freq;
+    while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq;
+    s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII);
+}
+
+/* ===========================================================================
+ * Reverse the first len bits of a code, using straightforward code (a faster
+ * method would use a table)
+ * IN assertion: 1 <= len <= 15
+ */
+local unsigned bi_reverse(code, len)
+    unsigned code; /* the value to invert */
+    int len;       /* its bit length */
+{
+    register unsigned res = 0;
+    do {
+        res |= code & 1;
+        code >>= 1, res <<= 1;
+    } while (--len > 0);
+    return res >> 1;
+}
+
+/* ===========================================================================
+ * Flush the bit buffer, keeping at most 7 bits in it.
+ */
+local void bi_flush(s)
+    deflate_state *s;
+{
+    if (s->bi_valid == 16) {
+        put_short(s, s->bi_buf);
+        s->bi_buf = 0;
+        s->bi_valid = 0;
+    } else if (s->bi_valid >= 8) {
+        put_byte(s, (Byte)s->bi_buf);
+        s->bi_buf >>= 8;
+        s->bi_valid -= 8;
+    }
+}
+
+/* ===========================================================================
+ * Flush the bit buffer and align the output on a byte boundary
+ */
+local void bi_windup(s)
+    deflate_state *s;
+{
+    if (s->bi_valid > 8) {
+        put_short(s, s->bi_buf);
+    } else if (s->bi_valid > 0) {
+        put_byte(s, (Byte)s->bi_buf);
+    }
+    s->bi_buf = 0;
+    s->bi_valid = 0;
+#ifdef DEBUG
+    s->bits_sent = (s->bits_sent+7) & ~7;
+#endif
+}
+
+/* ===========================================================================
+ * Copy a stored block, storing first the length and its
+ * one's complement if requested.
+ */
+local void copy_block(s, buf, len, header)
+    deflate_state *s;
+    charf    *buf;    /* the input data */
+    unsigned len;     /* its length */
+    int      header;  /* true if block header must be written */
+{
+    bi_windup(s);        /* align on byte boundary */
+    s->last_eob_len = 8; /* enough lookahead for inflate */
+
+    if (header) {
+        put_short(s, (ush)len);   
+        put_short(s, (ush)~len);
+#ifdef DEBUG
+        s->bits_sent += 2*16;
+#endif
+    }
+#ifdef DEBUG
+    s->bits_sent += (ulg)len<<3;
+#endif
+    while (len--) {
+        put_byte(s, *buf++);
+    }
+}
diff --git a/Utilities/ITK/Utilities/zlib/trees.h b/Utilities/ITK/Utilities/zlib/trees.h
new file mode 100644
index 0000000000..72facf900f
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/trees.h
@@ -0,0 +1,128 @@
+/* header created automatically with -DGEN_TREES_H */
+
+local const ct_data static_ltree[L_CODES+2] = {
+{{ 12},{  8}}, {{140},{  8}}, {{ 76},{  8}}, {{204},{  8}}, {{ 44},{  8}},
+{{172},{  8}}, {{108},{  8}}, {{236},{  8}}, {{ 28},{  8}}, {{156},{  8}},
+{{ 92},{  8}}, {{220},{  8}}, {{ 60},{  8}}, {{188},{  8}}, {{124},{  8}},
+{{252},{  8}}, {{  2},{  8}}, {{130},{  8}}, {{ 66},{  8}}, {{194},{  8}},
+{{ 34},{  8}}, {{162},{  8}}, {{ 98},{  8}}, {{226},{  8}}, {{ 18},{  8}},
+{{146},{  8}}, {{ 82},{  8}}, {{210},{  8}}, {{ 50},{  8}}, {{178},{  8}},
+{{114},{  8}}, {{242},{  8}}, {{ 10},{  8}}, {{138},{  8}}, {{ 74},{  8}},
+{{202},{  8}}, {{ 42},{  8}}, {{170},{  8}}, {{106},{  8}}, {{234},{  8}},
+{{ 26},{  8}}, {{154},{  8}}, {{ 90},{  8}}, {{218},{  8}}, {{ 58},{  8}},
+{{186},{  8}}, {{122},{  8}}, {{250},{  8}}, {{  6},{  8}}, {{134},{  8}},
+{{ 70},{  8}}, {{198},{  8}}, {{ 38},{  8}}, {{166},{  8}}, {{102},{  8}},
+{{230},{  8}}, {{ 22},{  8}}, {{150},{  8}}, {{ 86},{  8}}, {{214},{  8}},
+{{ 54},{  8}}, {{182},{  8}}, {{118},{  8}}, {{246},{  8}}, {{ 14},{  8}},
+{{142},{  8}}, {{ 78},{  8}}, {{206},{  8}}, {{ 46},{  8}}, {{174},{  8}},
+{{110},{  8}}, {{238},{  8}}, {{ 30},{  8}}, {{158},{  8}}, {{ 94},{  8}},
+{{222},{  8}}, {{ 62},{  8}}, {{190},{  8}}, {{126},{  8}}, {{254},{  8}},
+{{  1},{  8}}, {{129},{  8}}, {{ 65},{  8}}, {{193},{  8}}, {{ 33},{  8}},
+{{161},{  8}}, {{ 97},{  8}}, {{225},{  8}}, {{ 17},{  8}}, {{145},{  8}},
+{{ 81},{  8}}, {{209},{  8}}, {{ 49},{  8}}, {{177},{  8}}, {{113},{  8}},
+{{241},{  8}}, {{  9},{  8}}, {{137},{  8}}, {{ 73},{  8}}, {{201},{  8}},
+{{ 41},{  8}}, {{169},{  8}}, {{105},{  8}}, {{233},{  8}}, {{ 25},{  8}},
+{{153},{  8}}, {{ 89},{  8}}, {{217},{  8}}, {{ 57},{  8}}, {{185},{  8}},
+{{121},{  8}}, {{249},{  8}}, {{  5},{  8}}, {{133},{  8}}, {{ 69},{  8}},
+{{197},{  8}}, {{ 37},{  8}}, {{165},{  8}}, {{101},{  8}}, {{229},{  8}},
+{{ 21},{  8}}, {{149},{  8}}, {{ 85},{  8}}, {{213},{  8}}, {{ 53},{  8}},
+{{181},{  8}}, {{117},{  8}}, {{245},{  8}}, {{ 13},{  8}}, {{141},{  8}},
+{{ 77},{  8}}, {{205},{  8}}, {{ 45},{  8}}, {{173},{  8}}, {{109},{  8}},
+{{237},{  8}}, {{ 29},{  8}}, {{157},{  8}}, {{ 93},{  8}}, {{221},{  8}},
+{{ 61},{  8}}, {{189},{  8}}, {{125},{  8}}, {{253},{  8}}, {{ 19},{  9}},
+{{275},{  9}}, {{147},{  9}}, {{403},{  9}}, {{ 83},{  9}}, {{339},{  9}},
+{{211},{  9}}, {{467},{  9}}, {{ 51},{  9}}, {{307},{  9}}, {{179},{  9}},
+{{435},{  9}}, {{115},{  9}}, {{371},{  9}}, {{243},{  9}}, {{499},{  9}},
+{{ 11},{  9}}, {{267},{  9}}, {{139},{  9}}, {{395},{  9}}, {{ 75},{  9}},
+{{331},{  9}}, {{203},{  9}}, {{459},{  9}}, {{ 43},{  9}}, {{299},{  9}},
+{{171},{  9}}, {{427},{  9}}, {{107},{  9}}, {{363},{  9}}, {{235},{  9}},
+{{491},{  9}}, {{ 27},{  9}}, {{283},{  9}}, {{155},{  9}}, {{411},{  9}},
+{{ 91},{  9}}, {{347},{  9}}, {{219},{  9}}, {{475},{  9}}, {{ 59},{  9}},
+{{315},{  9}}, {{187},{  9}}, {{443},{  9}}, {{123},{  9}}, {{379},{  9}},
+{{251},{  9}}, {{507},{  9}}, {{  7},{  9}}, {{263},{  9}}, {{135},{  9}},
+{{391},{  9}}, {{ 71},{  9}}, {{327},{  9}}, {{199},{  9}}, {{455},{  9}},
+{{ 39},{  9}}, {{295},{  9}}, {{167},{  9}}, {{423},{  9}}, {{103},{  9}},
+{{359},{  9}}, {{231},{  9}}, {{487},{  9}}, {{ 23},{  9}}, {{279},{  9}},
+{{151},{  9}}, {{407},{  9}}, {{ 87},{  9}}, {{343},{  9}}, {{215},{  9}},
+{{471},{  9}}, {{ 55},{  9}}, {{311},{  9}}, {{183},{  9}}, {{439},{  9}},
+{{119},{  9}}, {{375},{  9}}, {{247},{  9}}, {{503},{  9}}, {{ 15},{  9}},
+{{271},{  9}}, {{143},{  9}}, {{399},{  9}}, {{ 79},{  9}}, {{335},{  9}},
+{{207},{  9}}, {{463},{  9}}, {{ 47},{  9}}, {{303},{  9}}, {{175},{  9}},
+{{431},{  9}}, {{111},{  9}}, {{367},{  9}}, {{239},{  9}}, {{495},{  9}},
+{{ 31},{  9}}, {{287},{  9}}, {{159},{  9}}, {{415},{  9}}, {{ 95},{  9}},
+{{351},{  9}}, {{223},{  9}}, {{479},{  9}}, {{ 63},{  9}}, {{319},{  9}},
+{{191},{  9}}, {{447},{  9}}, {{127},{  9}}, {{383},{  9}}, {{255},{  9}},
+{{511},{  9}}, {{  0},{  7}}, {{ 64},{  7}}, {{ 32},{  7}}, {{ 96},{  7}},
+{{ 16},{  7}}, {{ 80},{  7}}, {{ 48},{  7}}, {{112},{  7}}, {{  8},{  7}},
+{{ 72},{  7}}, {{ 40},{  7}}, {{104},{  7}}, {{ 24},{  7}}, {{ 88},{  7}},
+{{ 56},{  7}}, {{120},{  7}}, {{  4},{  7}}, {{ 68},{  7}}, {{ 36},{  7}},
+{{100},{  7}}, {{ 20},{  7}}, {{ 84},{  7}}, {{ 52},{  7}}, {{116},{  7}},
+{{  3},{  8}}, {{131},{  8}}, {{ 67},{  8}}, {{195},{  8}}, {{ 35},{  8}},
+{{163},{  8}}, {{ 99},{  8}}, {{227},{  8}}
+};
+
+local const ct_data static_dtree[D_CODES] = {
+{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
+{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
+{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
+{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
+{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
+{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
+};
+
+const uch _dist_code[DIST_CODE_LEN] = {
+ 0,  1,  2,  3,  4,  4,  5,  5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,  8,
+ 8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9, 10, 10, 10, 10, 10, 10, 10, 10,
+10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  0,  0, 16, 17,
+18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
+};
+
+const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {
+ 0,  1,  2,  3,  4,  5,  6,  7,  8,  8,  9,  9, 10, 10, 11, 11, 12, 12, 12, 12,
+13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
+22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
+};
+
+local const int base_length[LENGTH_CODES] = {
+0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
+64, 80, 96, 112, 128, 160, 192, 224, 0
+};
+
+local const int base_dist[D_CODES] = {
+    0,     1,     2,     3,     4,     6,     8,    12,    16,    24,
+   32,    48,    64,    96,   128,   192,   256,   384,   512,   768,
+ 1024,  1536,  2048,  3072,  4096,  6144,  8192, 12288, 16384, 24576
+};
+
diff --git a/Utilities/ITK/Utilities/zlib/uncompr.c b/Utilities/ITK/Utilities/zlib/uncompr.c
new file mode 100644
index 0000000000..d103321378
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/uncompr.c
@@ -0,0 +1,58 @@
+/* uncompr.c -- decompress a memory buffer
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* @(#) $Id$ */
+
+#include "zlib.h"
+
+/* ===========================================================================
+     Decompresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer. Upon entry, destLen is the total
+   size of the destination buffer, which must be large enough to hold the
+   entire uncompressed data. (The size of the uncompressed data must have
+   been saved previously by the compressor and transmitted to the decompressor
+   by some mechanism outside the scope of this compression library.)
+   Upon exit, destLen is the actual size of the compressed buffer.
+     This function can be used to decompress a whole file at once if the
+   input file is mmap'ed.
+
+     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer, or Z_DATA_ERROR if the input data was corrupted.
+*/
+int ZEXPORT uncompress (dest, destLen, source, sourceLen)
+    Bytef *dest;
+    uLongf *destLen;
+    const Bytef *source;
+    uLong sourceLen;
+{
+    z_stream stream;
+    int err;
+
+    stream.next_in = (Bytef*)source;
+    stream.avail_in = (uInt)sourceLen;
+    /* Check for source > 64K on 16-bit machine: */
+    if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
+
+    stream.next_out = dest;
+    stream.avail_out = (uInt)*destLen;
+    if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+
+    stream.zalloc = (alloc_func)0;
+    stream.zfree = (free_func)0;
+
+    err = inflateInit(&stream);
+    if (err != Z_OK) return err;
+
+    err = inflate(&stream, Z_FINISH);
+    if (err != Z_STREAM_END) {
+        inflateEnd(&stream);
+        return err == Z_OK ? Z_BUF_ERROR : err;
+    }
+    *destLen = stream.total_out;
+
+    err = inflateEnd(&stream);
+    return err;
+}
diff --git a/Utilities/ITK/Utilities/zlib/zconf.h b/Utilities/ITK/Utilities/zlib/zconf.h
new file mode 100644
index 0000000000..882f1f429a
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/zconf.h
@@ -0,0 +1,290 @@
+#include "itk_zlib_mangle.h"
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* @(#) $Id$ */
+
+#ifndef _ZCONF_H
+#define _ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ */
+#ifdef Z_PREFIX
+#  define deflateInit_  z_deflateInit_
+#  define deflate       z_deflate
+#  define deflateEnd    z_deflateEnd
+#  define inflateInit_  z_inflateInit_
+#  define inflate       z_inflate
+#  define inflateEnd    z_inflateEnd
+#  define deflateInit2_ z_deflateInit2_
+#  define deflateSetDictionary z_deflateSetDictionary
+#  define deflateCopy   z_deflateCopy
+#  define deflateReset  z_deflateReset
+#  define deflateParams z_deflateParams
+#  define inflateInit2_ z_inflateInit2_
+#  define inflateSetDictionary z_inflateSetDictionary
+#  define inflateSync   z_inflateSync
+#  define inflateSyncPoint z_inflateSyncPoint
+#  define inflateReset  z_inflateReset
+#  define compress      z_compress
+#  define compress2     z_compress2
+#  define uncompress    z_uncompress
+#  define adler32       z_adler32
+#  define crc32         z_crc32
+#  define get_crc_table z_get_crc_table
+
+#  define Byte          z_Byte
+#  define uInt          z_uInt
+#  define uLong         z_uLong
+#  define Bytef         z_Bytef
+#  define charf         z_charf
+#  define intf          z_intf
+#  define uIntf         z_uIntf
+#  define uLongf        z_uLongf
+#  define voidpf        z_voidpf
+#  define voidp         z_voidp
+#endif
+
+#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
+#  define WIN32
+#endif
+#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386)
+#  ifndef __32BIT__
+#    define __32BIT__
+#  endif
+#endif
+#if defined(__MSDOS__) && !defined(MSDOS)
+#  define MSDOS
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#if defined(MSDOS) && !defined(__32BIT__)
+#  define MAXSEG_64K
+#endif
+#ifdef MSDOS
+#  define UNALIGNED_OK
+#endif
+
+#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32))  && !defined(STDC)
+#  define STDC
+#endif
+#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__)
+#  ifndef STDC
+#    define STDC
+#  endif
+#endif
+
+#ifndef STDC
+#  ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+#    define const
+#  endif
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__)
+#  define NO_DUMMY_DECL
+#endif
+
+/* Old Borland C incorrectly complains about missing returns: */
+#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500)
+#  define NEED_DUMMY_RETURN
+#endif
+
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+#  ifdef MAXSEG_64K
+#    define MAX_MEM_LEVEL 8
+#  else
+#    define MAX_MEM_LEVEL 9
+#  endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+#  define MAX_WBITS   15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+            (1 << (windowBits+2)) +  (1 << (memLevel+9))
+ that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+   The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+                        /* Type declarations */
+
+#ifndef OF /* function prototypes */
+#  ifdef STDC
+#    define OF(args)  args
+#  else
+#    define OF(args)  ()
+#  endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__)
+   /* MSC small or medium model */
+#  define SMALL_MEDIUM
+#  ifdef _MSC_VER
+#    define FAR _far
+#  else
+#    define FAR far
+#  endif
+#endif
+#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__))
+#  ifndef __32BIT__
+#    define SMALL_MEDIUM
+#    define FAR _far
+#  endif
+#endif
+
+#include "zlibDllConfig.h"
+
+/* Compile with -DZLIB_DLL for Windows DLL support */
+#if defined(ZLIB_DLL)
+#  if defined(NOTUSED_WINDOWS) || defined(NOTUSEDWINDOWS)
+#    ifdef FAR
+#      undef FAR
+#    endif
+#    include <windows.h>
+#    define ZEXPORT  WINAPI
+#    ifdef WIN32
+#      define ZEXPORTVA  WINAPIV
+#    else
+#      define ZEXPORTVA  FAR _cdecl _export
+#    endif
+#  endif
+#  if defined (__BORLANDC__)
+#    if (__BORLANDC__ >= 0x0500) && defined (WIN32)
+#      include <windows.h>
+#      define ZEXPORT __declspec(dllexport) WINAPI
+#      define ZEXPORTRVA __declspec(dllexport) WINAPIV
+#    else
+#      if defined (_Windows) && defined (__DLL__)
+#        define ZEXPORT _export
+#        define ZEXPORTVA _export
+#      endif
+#    endif
+#  endif
+#endif
+
+#if defined (__BEOS__)
+#  if defined (ZLIB_DLL)
+#    define ZEXTERN extern __declspec(dllexport)
+#  else
+#    define ZEXTERN extern __declspec(dllimport)
+#  endif
+#endif
+
+#ifndef ZEXPORT
+#  define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+#  define ZEXPORTVA
+#endif
+#ifndef ZEXTERN
+#  define ZEXTERN extern
+#endif
+
+#ifndef FAR
+#   define FAR
+#endif
+
+#if !defined(MACOS) && !defined(TARGET_OS_MAC)
+typedef unsigned char  Byte;  /* 8 bits */
+#endif
+typedef unsigned int   uInt;  /* 16 bits or more */
+typedef unsigned long  uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+   /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+#  define Bytef Byte FAR
+#else
+   typedef Byte  FAR Bytef;
+#endif
+typedef char  FAR charf;
+typedef int   FAR intf;
+typedef uInt  FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+   typedef void FAR *voidpf;
+   typedef void     *voidp;
+#else
+   typedef Byte FAR *voidpf;
+   typedef Byte     *voidp;
+#endif
+
+#ifdef HAVE_UNISTD_H
+#  include <sys/types.h> /* for off_t */
+#  include <unistd.h>    /* for SEEK_* and off_t */
+#  define z_off_t  off_t
+#endif
+#ifndef SEEK_SET
+#  define SEEK_SET        0       /* Seek from beginning of file.  */
+#  define SEEK_CUR        1       /* Seek from current position.  */
+#  define SEEK_END        2       /* Set file pointer to EOF plus "offset" */
+#endif
+#ifndef z_off_t
+#  define  z_off_t long
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+#   pragma map(deflateInit_,"DEIN")
+#   pragma map(deflateInit2_,"DEIN2")
+#   pragma map(deflateEnd,"DEEND")
+#   pragma map(inflateInit_,"ININ")
+#   pragma map(inflateInit2_,"ININ2")
+#   pragma map(inflateEnd,"INEND")
+#   pragma map(inflateSync,"INSY")
+#   pragma map(inflateSetDictionary,"INSEDI")
+#   pragma map(inflate_blocks,"INBL")
+#   pragma map(inflate_blocks_new,"INBLNE")
+#   pragma map(inflate_blocks_free,"INBLFR")
+#   pragma map(inflate_blocks_reset,"INBLRE")
+#   pragma map(inflate_codes_free,"INCOFR")
+#   pragma map(inflate_codes,"INCO")
+#   pragma map(inflate_fast,"INFA")
+#   pragma map(inflate_flush,"INFLU")
+#   pragma map(inflate_mask,"INMA")
+#   pragma map(inflate_set_dictionary,"INSEDI2")
+#   pragma map(inflate_copyright,"INCOPY")
+#   pragma map(inflate_trees_bits,"INTRBI")
+#   pragma map(inflate_trees_dynamic,"INTRDY")
+#   pragma map(inflate_trees_fixed,"INTRFI")
+#   pragma map(inflate_trees_free,"INTRFR")
+#endif
+
+#if defined(_MSC_VER)
+#pragma warning ( disable : 4100 ) /* unreferenced variable */
+#pragma warning ( disable : 4127 ) /* cond expr is constant */
+#pragma warning ( disable : 4131 ) /* Old style declaration */
+#pragma warning ( disable : 4244 ) /* conversion loss of data */
+#pragma warning ( disable : 4267 )
+#endif
+
+#endif /* _ZCONF_H */
diff --git a/Utilities/ITK/Utilities/zlib/zlib.def b/Utilities/ITK/Utilities/zlib/zlib.def
new file mode 100644
index 0000000000..0d614a447b
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/zlib.def
@@ -0,0 +1,50 @@
+LIBRARY		"itkzlib"
+
+DESCRIPTION	'"""zlib data compression library"""'
+
+VERSION		1.13
+
+HEAPSIZE	1048576,4096
+
+EXPORTS
+    adler32                        @1
+    compress                       @2
+    crc32                          @3
+    deflate                        @4
+    deflateCopy                    @5
+    deflateEnd                     @6
+    deflateInit2_                  @7
+    deflateInit_                   @8
+    deflateParams                  @9
+    deflateReset                   @10
+    deflateSetDictionary           @11
+    gzclose                        @12
+    gzdopen                        @13
+    gzerror                        @14
+    gzflush                        @15
+    gzopen                         @16
+    gzread                         @17
+    gzwrite                        @18
+    inflate                        @19
+    inflateEnd                     @20
+    inflateInit2_                  @21
+    inflateInit_                   @22
+    inflateReset                   @23
+    inflateSetDictionary           @24
+    inflateSync                    @25
+    uncompress                     @26
+    zlibVersion                    @27
+    gzprintf                       @28
+    gzputc                         @29
+    gzgetc                         @30
+    gzseek                         @31
+    gzrewind                       @32
+    gztell                         @33
+    gzeof                          @34
+    gzsetparams                    @35
+    zError                         @36
+    inflateSyncPoint               @37
+    get_crc_table                  @38
+    compress2                      @39
+    gzputs                         @40
+    gzgets                         @41
diff --git a/Utilities/ITK/Utilities/zlib/zlib.h b/Utilities/ITK/Utilities/zlib/zlib.h
new file mode 100644
index 0000000000..2395c45703
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/zlib.h
@@ -0,0 +1,893 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+  version 1.1.3, July 9th, 1998
+
+  Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jean-loup Gailly        Mark Adler
+  jloup@gzip.org          madler@alumni.caltech.edu
+
+
+  The data format used by the zlib library is described by RFCs (Request for
+  Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt
+  (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+
+#ifndef _ZLIB_H
+#define _ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.1.3"
+
+/* 
+     The 'zlib' compression library provides in-memory compression and
+  decompression functions, including integrity checks of the uncompressed
+  data.  This version of the library supports only one compression method
+  (deflation) but other algorithms will be added later and will have the same
+  stream interface.
+
+     Compression can be done in a single step if the buffers are large
+  enough (for example if an input file is mmap'ed), or can be done by
+  repeated calls of the compression function.  In the latter case, the
+  application must provide more input and/or consume the output
+  (providing more output space) before each call.
+
+     The library also supports reading and writing files in gzip (.gz) format
+  with an interface similar to that of stdio.
+
+     The library does not install any signal handler. The decoder checks
+  the consistency of the compressed data, so the library should never
+  crash even in case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void   (*free_func)  OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+    Bytef    *next_in;  /* next input byte */
+    uInt     avail_in;  /* number of bytes available at next_in */
+    uLong    total_in;  /* total nb of input bytes read so far */
+
+    Bytef    *next_out; /* next output byte should be put there */
+    uInt     avail_out; /* remaining free space at next_out */
+    uLong    total_out; /* total nb of bytes output so far */
+
+    char     *msg;      /* last error message, NULL if no error */
+    struct internal_state FAR *state; /* not visible by applications */
+
+    alloc_func zalloc;  /* used to allocate the internal state */
+    free_func  zfree;   /* used to free the internal state */
+    voidpf     opaque;  /* private data object passed to zalloc and zfree */
+
+    int     data_type;  /* best guess about the data type: ascii or binary */
+    uLong   adler;      /* adler32 value of the uncompressed data */
+    uLong   reserved;   /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+   The application must update next_in and avail_in when avail_in has
+   dropped to zero. It must update next_out and avail_out when avail_out
+   has dropped to zero. The application must initialize zalloc, zfree and
+   opaque before calling the init function. All other fields are set by the
+   compression library and must not be updated by the application.
+
+   The opaque value provided by the application will be passed as the first
+   parameter for calls of zalloc and zfree. This can be useful for custom
+   memory management. The compression library attaches no meaning to the
+   opaque value.
+
+   zalloc must return Z_NULL if there is not enough memory for the object.
+   If zlib is used in a multi-threaded application, zalloc and zfree must be
+   thread safe.
+
+   On 16-bit systems, the functions zalloc and zfree must be able to allocate
+   exactly 65536 bytes, but will not be required to allocate more than this
+   if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+   pointers returned by zalloc for objects of exactly 65536 bytes *must*
+   have their offset normalized to zero. The default allocation function
+   provided by this library ensures this (see zutil.c). To reduce memory
+   requirements and avoid any allocation of 64K objects, at the expense of
+   compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+   The fields total_in and total_out can be used for statistics or
+   progress reports. After compression, total_in holds the total size of
+   the uncompressed data and may be saved for use in the decompressor
+   (particularly if the decompressor wants to decompress everything in
+   a single step).
+*/
+
+                        /* constants */
+
+#define Z_NO_FLUSH      0
+#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
+#define Z_SYNC_FLUSH    2
+#define Z_FULL_FLUSH    3
+#define Z_FINISH        4
+/* Allowed flush values; see deflate() below for details */
+
+#define Z_OK            0
+#define Z_STREAM_END    1
+#define Z_NEED_DICT     2
+#define Z_ERRNO        (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR   (-3)
+#define Z_MEM_ERROR    (-4)
+#define Z_BUF_ERROR    (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION         0
+#define Z_BEST_SPEED             1
+#define Z_BEST_COMPRESSION       9
+#define Z_DEFAULT_COMPRESSION  (-1)
+/* compression levels */
+
+#define Z_FILTERED            1
+#define Z_HUFFMAN_ONLY        2
+#define Z_DEFAULT_STRATEGY    0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY   0
+#define Z_ASCII    1
+#define Z_UNKNOWN  2
+/* Possible values of the data_type field */
+
+#define Z_DEFLATED   8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+                        /* basic functions */
+
+ZEXTERN const char * ZEXPORT zlibVersion OF((void));
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+   If the first character differs, the library code actually used is
+   not compatible with the zlib.h header file used by the application.
+   This check is automatically made by deflateInit and inflateInit.
+ */
+
+/* 
+ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
+
+     Initializes the internal stream state for compression. The fields
+   zalloc, zfree and opaque must be initialized before by the caller.
+   If zalloc and zfree are set to Z_NULL, deflateInit updates them to
+   use default allocation functions.
+
+     The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+   1 gives best speed, 9 gives best compression, 0 gives no compression at
+   all (the input data is simply copied a block at a time).
+   Z_DEFAULT_COMPRESSION requests a default compromise between speed and
+   compression (currently equivalent to level 6).
+
+     deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if level is not a valid compression level,
+   Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+   with the version assumed by the caller (ZLIB_VERSION).
+   msg is set to null if there is no error message.  deflateInit does not
+   perform any compression: this will be done by deflate().
+*/
+
+
+ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
+/*
+    deflate compresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full. It may introduce some
+  output latency (reading input without producing any output) except when
+  forced to flush.
+
+    The detailed semantics are as follows. deflate performs one or both of the
+  following actions:
+
+  - Compress more input starting at next_in and update next_in and avail_in
+    accordingly. If not all input can be processed (because there is not
+    enough room in the output buffer), next_in and avail_in are updated and
+    processing will resume at this point for the next call of deflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly. This action is forced if the parameter flush is non zero.
+    Forcing flush frequently degrades the compression ratio, so this parameter
+    should be set only when necessary (in interactive applications).
+    Some output may be provided even if flush is not set.
+
+  Before the call of deflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming
+  more output, and updating avail_in or avail_out accordingly; avail_out
+  should never be zero before the call. The application can consume the
+  compressed output when it wants, for example when the output buffer is full
+  (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
+  and with zero avail_out, it must be called again after making room in the
+  output buffer because there might be more output pending.
+
+    If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+  flushed to the output buffer and the output is aligned on a byte boundary, so
+  that the decompressor can get all input data available so far. (In particular
+  avail_in is zero after the call if enough output space has been provided
+  before the call.)  Flushing may degrade compression for some compression
+  algorithms and so it should be used only when necessary.
+
+    If flush is set to Z_FULL_FLUSH, all output is flushed as with
+  Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+  restart from this point if previous compressed data has been damaged or if
+  random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
+  the compression.
+
+    If deflate returns with avail_out == 0, this function must be called again
+  with the same value of the flush parameter and more output space (updated
+  avail_out), until the flush is complete (deflate returns with non-zero
+  avail_out).
+
+    If the parameter flush is set to Z_FINISH, pending input is processed,
+  pending output is flushed and deflate returns with Z_STREAM_END if there
+  was enough output space; if deflate returns with Z_OK, this function must be
+  called again with Z_FINISH and more output space (updated avail_out) but no
+  more input data, until it returns with Z_STREAM_END or an error. After
+  deflate has returned Z_STREAM_END, the only possible operations on the
+  stream are deflateReset or deflateEnd.
+  
+    Z_FINISH can be used immediately after deflateInit if all the compression
+  is to be done in a single step. In this case, avail_out must be at least
+  0.1% larger than avail_in plus 12 bytes.  If deflate does not return
+  Z_STREAM_END, then it must be called again as described above.
+
+    deflate() sets strm->adler to the adler32 checksum of all input read
+  so far (that is, total_in bytes).
+
+    deflate() may update data_type if it can make a good guess about
+  the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered
+  binary. This field is only for information purposes and does not affect
+  the compression algorithm in any manner.
+
+    deflate() returns Z_OK if some progress has been made (more input
+  processed or more output produced), Z_STREAM_END if all input has been
+  consumed and all output has been produced (only when flush is set to
+  Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+  if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible
+  (for example avail_in or avail_out was zero).
+*/
+
+
+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any
+   pending output.
+
+     deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+   stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+   prematurely (some input or output was discarded). In the error case,
+   msg may be set but then points to a static string (which must not be
+   deallocated).
+*/
+
+
+/* 
+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
+
+     Initializes the internal stream state for decompression. The fields
+   next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+   the caller. If next_in is not Z_NULL and avail_in is large enough (the exact
+   value depends on the compression method), inflateInit determines the
+   compression method from the zlib header and allocates all data structures
+   accordingly; otherwise the allocation will be deferred to the first call of
+   inflate.  If zalloc and zfree are set to Z_NULL, inflateInit updates them to
+   use default allocation functions.
+
+     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+   version assumed by the caller.  msg is set to null if there is no error
+   message. inflateInit does not perform any decompression apart from reading
+   the zlib header if present: this will be done by inflate().  (So next_in and
+   avail_in may be modified, but next_out and avail_out are unchanged.)
+*/
+
+
+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
+/*
+    inflate decompresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full. It may some
+  introduce some output latency (reading input without producing any output)
+  except when forced to flush.
+
+  The detailed semantics are as follows. inflate performs one or both of the
+  following actions:
+
+  - Decompress more input starting at next_in and update next_in and avail_in
+    accordingly. If not all input can be processed (because there is not
+    enough room in the output buffer), next_in is updated and processing
+    will resume at this point for the next call of inflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly.  inflate() provides as much output as possible, until there
+    is no more input data or no more space in the output buffer (see below
+    about the flush parameter).
+
+  Before the call of inflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming
+  more output, and updating the next_* and avail_* values accordingly.
+  The application can consume the uncompressed output when it wants, for
+  example when the output buffer is full (avail_out == 0), or after each
+  call of inflate(). If inflate returns Z_OK and with zero avail_out, it
+  must be called again after making room in the output buffer because there
+  might be more output pending.
+
+    If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much
+  output as possible to the output buffer. The flushing behavior of inflate is
+  not specified for values of the flush parameter other than Z_SYNC_FLUSH
+  and Z_FINISH, but the current implementation actually flushes as much output
+  as possible anyway.
+
+    inflate() should normally be called until it returns Z_STREAM_END or an
+  error. However if all decompression is to be performed in a single step
+  (a single call of inflate), the parameter flush should be set to
+  Z_FINISH. In this case all pending input is processed and all pending
+  output is flushed; avail_out must be large enough to hold all the
+  uncompressed data. (The size of the uncompressed data may have been saved
+  by the compressor for this purpose.) The next operation on this stream must
+  be inflateEnd to deallocate the decompression state. The use of Z_FINISH
+  is never required, but can be used to inform inflate that a faster routine
+  may be used for the single inflate() call.
+
+     If a preset dictionary is needed at this point (see inflateSetDictionary
+  below), inflate sets strm-adler to the adler32 checksum of the
+  dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise 
+  it sets strm->adler to the adler32 checksum of all output produced
+  so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or
+  an error code as described below. At the end of the stream, inflate()
+  checks that its computed adler32 checksum is equal to that saved by the
+  compressor and returns Z_STREAM_END only if the checksum is correct.
+
+    inflate() returns Z_OK if some progress has been made (more input processed
+  or more output produced), Z_STREAM_END if the end of the compressed data has
+  been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+  preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+  corrupted (input stream not conforming to the zlib format or incorrect
+  adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent
+  (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not
+  enough memory, Z_BUF_ERROR if no progress is possible or if there was not
+  enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR
+  case, the application may then call inflateSync to look for a good
+  compression block.
+*/
+
+
+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any
+   pending output.
+
+     inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+   was inconsistent. In the error case, msg may be set but then points to a
+   static string (which must not be deallocated).
+*/
+
+                        /* Advanced functions */
+
+/*
+    The following functions are needed only in some special applications.
+*/
+
+/*   
+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
+                                     int  level,
+                                     int  method,
+                                     int  windowBits,
+                                     int  memLevel,
+                                     int  strategy));
+
+     This is another version of deflateInit with more compression options. The
+   fields next_in, zalloc, zfree and opaque must be initialized before by
+   the caller.
+
+     The method parameter is the compression method. It must be Z_DEFLATED in
+   this version of the library.
+
+     The windowBits parameter is the base two logarithm of the window size
+   (the size of the history buffer).  It should be in the range 8..15 for this
+   version of the library. Larger values of this parameter result in better
+   compression at the expense of memory usage. The default value is 15 if
+   deflateInit is used instead.
+
+     The memLevel parameter specifies how much memory should be allocated
+   for the internal compression state. memLevel=1 uses minimum memory but
+   is slow and reduces compression ratio; memLevel=9 uses maximum memory
+   for optimal speed. The default value is 8. See zconf.h for total memory
+   usage as a function of windowBits and memLevel.
+
+     The strategy parameter is used to tune the compression algorithm. Use the
+   value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+   filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no
+   string match).  Filtered data consists mostly of small values with a
+   somewhat random distribution. In this case, the compression algorithm is
+   tuned to compress them better. The effect of Z_FILTERED is to force more
+   Huffman coding and less string matching; it is somewhat intermediate
+   between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects
+   the compression ratio but not the correctness of the compressed output even
+   if it is not set appropriately.
+
+      deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
+   method). msg is set to null if there is no error message.  deflateInit2 does
+   not perform any compression: this will be done by deflate().
+*/
+                            
+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
+                                             const Bytef *dictionary,
+                                             uInt  dictLength));
+/*
+     Initializes the compression dictionary from the given byte sequence
+   without producing any compressed output. This function must be called
+   immediately after deflateInit, deflateInit2 or deflateReset, before any
+   call of deflate. The compressor and decompressor must use exactly the same
+   dictionary (see inflateSetDictionary).
+
+     The dictionary should consist of strings (byte sequences) that are likely
+   to be encountered later in the data to be compressed, with the most commonly
+   used strings preferably put towards the end of the dictionary. Using a
+   dictionary is most useful when the data to be compressed is short and can be
+   predicted with good accuracy; the data can then be compressed better than
+   with the default empty dictionary.
+
+     Depending on the size of the compression data structures selected by
+   deflateInit or deflateInit2, a part of the dictionary may in effect be
+   discarded, for example if the dictionary is larger than the window size in
+   deflate or deflate2. Thus the strings most likely to be useful should be
+   put at the end of the dictionary, not at the front.
+
+     Upon return of this function, strm->adler is set to the Adler32 value
+   of the dictionary; the decompressor may later use this value to determine
+   which dictionary has been used by the compressor. (The Adler32 value
+   applies to the whole dictionary even if only a subset of the dictionary is
+   actually used by the compressor.)
+
+     deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+   parameter is invalid (such as NULL dictionary) or the stream state is
+   inconsistent (for example if deflate has already been called for this stream
+   or if the compression method is bsort). deflateSetDictionary does not
+   perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
+                                    z_streamp source));
+/*
+     Sets the destination stream as a complete copy of the source stream.
+
+     This function can be useful when several compression strategies will be
+   tried, for example when there are several ways of pre-processing the input
+   data with a filter. The streams that will be discarded should then be freed
+   by calling deflateEnd.  Note that deflateCopy duplicates the internal
+   compression state which can be quite large, so this strategy is slow and
+   can consume lots of memory.
+
+     deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+   (such as zalloc being NULL). msg is left unchanged in both source and
+   destination.
+*/
+
+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
+/*
+     This function is equivalent to deflateEnd followed by deflateInit,
+   but does not free and reallocate all the internal compression state.
+   The stream will keep the same compression level and any other attributes
+   that may have been set by deflateInit2.
+
+      deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
+                                      int level,
+                                      int strategy));
+/*
+     Dynamically update the compression level and compression strategy.  The
+   interpretation of level and strategy is as in deflateInit2.  This can be
+   used to switch between compression and straight copy of the input data, or
+   to switch to a different kind of input data requiring a different
+   strategy. If the compression level is changed, the input available so far
+   is compressed with the old level (and may be flushed); the new level will
+   take effect only at the next call of deflate().
+
+     Before the call of deflateParams, the stream state must be set as for
+   a call of deflate(), since the currently available input may have to
+   be compressed and flushed. In particular, strm->avail_out must be non-zero.
+
+     deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+   stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
+   if strm->avail_out was zero.
+*/
+
+/*   
+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
+                                     int  windowBits));
+
+     This is another version of inflateInit with an extra parameter. The
+   fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+   before by the caller.
+
+     The windowBits parameter is the base two logarithm of the maximum window
+   size (the size of the history buffer).  It should be in the range 8..15 for
+   this version of the library. The default value is 15 if inflateInit is used
+   instead. If a compressed stream with a larger window size is given as
+   input, inflate() will return with the error code Z_DATA_ERROR instead of
+   trying to allocate a larger window.
+
+      inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative
+   memLevel). msg is set to null if there is no error message.  inflateInit2
+   does not perform any decompression apart from reading the zlib header if
+   present: this will be done by inflate(). (So next_in and avail_in may be
+   modified, but next_out and avail_out are unchanged.)
+*/
+
+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
+                                             const Bytef *dictionary,
+                                             uInt  dictLength));
+/*
+     Initializes the decompression dictionary from the given uncompressed byte
+   sequence. This function must be called immediately after a call of inflate
+   if this call returned Z_NEED_DICT. The dictionary chosen by the compressor
+   can be determined from the Adler32 value returned by this call of
+   inflate. The compressor and decompressor must use exactly the same
+   dictionary (see deflateSetDictionary).
+
+     inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+   parameter is invalid (such as NULL dictionary) or the stream state is
+   inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+   expected one (incorrect Adler32 value). inflateSetDictionary does not
+   perform any decompression: this will be done by subsequent calls of
+   inflate().
+*/
+
+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
+/* 
+    Skips invalid compressed data until a full flush point (see above the
+  description of deflate with Z_FULL_FLUSH) can be found, or until all
+  available input is skipped. No output is provided.
+
+    inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
+  if no more input was provided, Z_DATA_ERROR if no flush point has been found,
+  or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
+  case, the application may save the current current value of total_in which
+  indicates where valid compressed data was found. In the error case, the
+  application may repeatedly call inflateSync, providing more input each time,
+  until success or end of the input data.
+*/
+
+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
+/*
+     This function is equivalent to inflateEnd followed by inflateInit,
+   but does not free and reallocate all the internal decompression state.
+   The stream will keep attributes that may have been set by inflateInit2.
+
+      inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+
+                        /* utility functions */
+
+/*
+     The following utility functions are implemented on top of the
+   basic stream-oriented functions. To simplify the interface, some
+   default options are assumed (compression level and memory usage,
+   standard memory allocation functions). The source code of these
+   utility functions can easily be modified if you need special options.
+*/
+
+ZEXTERN int ZEXPORT compress OF((Bytef *dest,   uLongf *destLen,
+                                 const Bytef *source, uLong sourceLen));
+/*
+     Compresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer. Upon entry, destLen is the total
+   size of the destination buffer, which must be at least 0.1% larger than
+   sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the
+   compressed buffer.
+     This function can be used to compress a whole file at once if the
+   input file is mmap'ed.
+     compress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer.
+*/
+
+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest,   uLongf *destLen,
+                                  const Bytef *source, uLong sourceLen,
+                                  int level));
+/*
+     Compresses the source buffer into the destination buffer. The level
+   parameter has the same meaning as in deflateInit.  sourceLen is the byte
+   length of the source buffer. Upon entry, destLen is the total size of the
+   destination buffer, which must be at least 0.1% larger than sourceLen plus
+   12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
+
+     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+   Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest,   uLongf *destLen,
+                                   const Bytef *source, uLong sourceLen));
+/*
+     Decompresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer. Upon entry, destLen is the total
+   size of the destination buffer, which must be large enough to hold the
+   entire uncompressed data. (The size of the uncompressed data must have
+   been saved previously by the compressor and transmitted to the decompressor
+   by some mechanism outside the scope of this compression library.)
+   Upon exit, destLen is the actual size of the compressed buffer.
+     This function can be used to decompress a whole file at once if the
+   input file is mmap'ed.
+
+     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer, or Z_DATA_ERROR if the input data was corrupted.
+*/
+
+
+typedef voidp gzFile;
+
+ZEXTERN gzFile ZEXPORT gzopen  OF((const char *path, const char *mode));
+/*
+     Opens a gzip (.gz) file for reading or writing. The mode parameter
+   is as in fopen ("rb" or "wb") but can also include a compression level
+   ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
+   Huffman only compression as in "wb1h". (See the description
+   of deflateInit2 for more information about the strategy parameter.)
+
+     gzopen can be used to read a file which is not in gzip format; in this
+   case gzread will directly read from the file without decompression.
+
+     gzopen returns NULL if the file could not be opened or if there was
+   insufficient memory to allocate the (de)compression state; errno
+   can be checked to distinguish the two cases (if errno is zero, the
+   zlib error is Z_MEM_ERROR).  */
+
+ZEXTERN gzFile ZEXPORT gzdopen  OF((int fd, const char *mode));
+/*
+     gzdopen() associates a gzFile with the file descriptor fd.  File
+   descriptors are obtained from calls like open, dup, creat, pipe or
+   fileno (in the file has been previously opened with fopen).
+   The mode parameter is as in gzopen.
+     The next call of gzclose on the returned gzFile will also close the
+   file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
+   descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
+     gzdopen returns NULL if there was insufficient memory to allocate
+   the (de)compression state.
+*/
+
+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
+/*
+     Dynamically update the compression level or strategy. See the description
+   of deflateInit2 for the meaning of these parameters.
+     gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
+   opened for writing.
+*/
+
+ZEXTERN int ZEXPORT    gzread  OF((gzFile file, voidp buf, unsigned len));
+/*
+     Reads the given number of uncompressed bytes from the compressed file.
+   If the input file was not in gzip format, gzread copies the given number
+   of bytes into the buffer.
+     gzread returns the number of uncompressed bytes actually read (0 for
+   end of file, -1 for error). */
+
+ZEXTERN int ZEXPORT    gzwrite OF((gzFile file, 
+                                   const voidp buf, unsigned len));
+/*
+     Writes the given number of uncompressed bytes into the compressed file.
+   gzwrite returns the number of uncompressed bytes actually written
+   (0 in case of error).
+*/
+
+ZEXTERN int ZEXPORTVA   gzprintf OF((gzFile file, const char *format, ...));
+/*
+     Converts, formats, and writes the args to the compressed file under
+   control of the format string, as in fprintf. gzprintf returns the number of
+   uncompressed bytes actually written (0 in case of error).
+*/
+
+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
+/*
+      Writes the given null-terminated string to the compressed file, excluding
+   the terminating null character.
+      gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
+/*
+      Reads bytes from the compressed file until len-1 characters are read, or
+   a newline character is read and transferred to buf, or an end-of-file
+   condition is encountered.  The string is then terminated with a null
+   character.
+      gzgets returns buf, or Z_NULL in case of error.
+*/
+
+ZEXTERN int ZEXPORT    gzputc OF((gzFile file, int c));
+/*
+      Writes c, converted to an unsigned char, into the compressed file.
+   gzputc returns the value that was written, or -1 in case of error.
+*/
+
+ZEXTERN int ZEXPORT    gzgetc OF((gzFile file));
+/*
+      Reads one byte from the compressed file. gzgetc returns this byte
+   or -1 in case of end of file or error.
+*/
+
+ZEXTERN int ZEXPORT    gzflush OF((gzFile file, int flush));
+/*
+     Flushes all pending output into the compressed file. The parameter
+   flush is as in the deflate() function. The return value is the zlib
+   error number (see function gzerror below). gzflush returns Z_OK if
+   the flush parameter is Z_FINISH and all output could be flushed.
+     gzflush should be called only when strictly necessary because it can
+   degrade compression.
+*/
+
+ZEXTERN z_off_t ZEXPORT    gzseek OF((gzFile file,
+                                      z_off_t offset, int whence));
+/* 
+      Sets the starting position for the next gzread or gzwrite on the
+   given compressed file. The offset represents a number of bytes in the
+   uncompressed data stream. The whence parameter is defined as in lseek(2);
+   the value SEEK_END is not supported.
+     If the file is opened for reading, this function is emulated but can be
+   extremely slow. If the file is opened for writing, only forward seeks are
+   supported; gzseek then compresses a sequence of zeroes up to the new
+   starting position.
+
+      gzseek returns the resulting offset location as measured in bytes from
+   the beginning of the uncompressed stream, or -1 in case of error, in
+   particular if the file is opened for writing and the new starting position
+   would be before the current position.
+*/
+
+ZEXTERN int ZEXPORT    gzrewind OF((gzFile file));
+/*
+     Rewinds the given file. This function is supported only for reading.
+
+   gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+ZEXTERN z_off_t ZEXPORT    gztell OF((gzFile file));
+/*
+     Returns the starting position for the next gzread or gzwrite on the
+   given compressed file. This position represents a number of bytes in the
+   uncompressed data stream.
+
+   gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+ZEXTERN int ZEXPORT gzeof OF((gzFile file));
+/*
+     Returns 1 when EOF has previously been detected reading the given
+   input stream, otherwise zero.
+*/
+
+ZEXTERN int ZEXPORT    gzclose OF((gzFile file));
+/*
+     Flushes all pending output if necessary, closes the compressed file
+   and deallocates all the (de)compression state. The return value is the zlib
+   error number (see function gzerror below).
+*/
+
+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
+/*
+     Returns the error message for the last error which occurred on the
+   given compressed file. errnum is set to zlib error number. If an
+   error occurred in the file system and not in the compression library,
+   errnum is set to Z_ERRNO and the application may consult errno
+   to get the exact error code.
+*/
+
+                        /* checksum functions */
+
+/*
+     These functions are not related to compression but are exported
+   anyway because they might be useful in applications using the
+   compression library.
+*/
+
+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
+
+/*
+     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+   return the updated checksum. If buf is NULL, this function returns
+   the required initial value for the checksum.
+   An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+   much faster. Usage example:
+
+     uLong adler = adler32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       adler = adler32(adler, buffer, length);
+     }
+     if (adler != original_adler) error();
+*/
+
+ZEXTERN uLong ZEXPORT crc32   OF((uLong crc, const Bytef *buf, uInt len));
+/*
+     Update a running crc with the bytes buf[0..len-1] and return the updated
+   crc. If buf is NULL, this function returns the required initial value
+   for the crc. Pre- and post-conditioning (one's complement) is performed
+   within this function so it shouldn't be done by the application.
+   Usage example:
+
+     uLong crc = crc32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       crc = crc32(crc, buffer, length);
+     }
+     if (crc != original_crc) error();
+*/
+
+
+                        /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
+                                     const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
+                                     const char *version, int stream_size));
+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int  level, int  method,
+                                      int windowBits, int memLevel,
+                                      int strategy, const char *version,
+                                      int stream_size));
+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int  windowBits,
+                                      const char *version, int stream_size));
+#define deflateInit(strm, level) \
+        deflateInit_((strm), (level),       ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit(strm) \
+        inflateInit_((strm),                ZLIB_VERSION, sizeof(z_stream))
+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+        deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+                      (strategy),           ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit2(strm, windowBits) \
+        inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+
+
+#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL)
+    struct internal_state {int dummy;}; /* hack for buggy compilers */
+#endif
+
+ZEXTERN const char   * ZEXPORT zError           OF((int err));
+ZEXTERN int            ZEXPORT inflateSyncPoint OF((z_streamp z));
+ZEXTERN const uLongf * ZEXPORT get_crc_table    OF((void));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ZLIB_H */
diff --git a/Utilities/ITK/Utilities/zlib/zlib.rc b/Utilities/ITK/Utilities/zlib/zlib.rc
new file mode 100644
index 0000000000..556d4ff950
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/zlib.rc
@@ -0,0 +1,32 @@
+#include <windows.h>
+
+#define IDR_VERSION1  1
+IDR_VERSION1	VERSIONINFO	MOVEABLE IMPURE LOADONCALL DISCARDABLE
+  FILEVERSION	 1,1,3,0
+  PRODUCTVERSION 1,1,3,0
+  FILEFLAGSMASK	VS_FFI_FILEFLAGSMASK
+  FILEFLAGS	0
+  FILEOS	VOS_DOS_WINDOWS32
+  FILETYPE	VFT_DLL
+  FILESUBTYPE	0	// not used
+BEGIN
+  BLOCK "StringFileInfo"
+  BEGIN
+    BLOCK "040904E4"
+    //language ID = U.S. English, char set = Windows, Multilingual
+
+    BEGIN
+      VALUE "FileDescription", "zlib data compression library\0"
+      VALUE "FileVersion",	"1.1.3\0"
+      VALUE "InternalName",	"zlib\0"
+      VALUE "OriginalFilename",	"zlib.dll\0"
+      VALUE "ProductName",	"ZLib.DLL\0"
+      VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
+      VALUE "LegalCopyright", "(C) 1995-1998 Jean-loup Gailly & Mark Adler\0"
+    END
+  END
+  BLOCK "VarFileInfo"
+  BEGIN
+    VALUE "Translation", 0x0409, 1252
+  END
+END
diff --git a/Utilities/ITK/Utilities/zlib/zlibDllConfig.h.in b/Utilities/ITK/Utilities/zlib/zlibDllConfig.h.in
new file mode 100644
index 0000000000..3dceb8c5d1
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/zlibDllConfig.h.in
@@ -0,0 +1,6 @@
+#ifndef _zlibDllConfig_h
+#define _zlibDllConfig_h
+
+#cmakedefine ZLIB_DLL
+
+#endif
diff --git a/Utilities/ITK/Utilities/zlib/zutil.c b/Utilities/ITK/Utilities/zlib/zutil.c
new file mode 100644
index 0000000000..b3de4e8837
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/zutil.c
@@ -0,0 +1,225 @@
+/* zutil.c -- target dependent utility functions for the compression library
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* @(#) $Id$ */
+
+#include "zutil.h"
+
+struct internal_state      {int dummy;}; /* for buggy compilers */
+
+#ifndef STDC
+extern void exit OF((int));
+#endif
+
+const char *z_errmsg[10] = {
+"need dictionary",     /* Z_NEED_DICT       2  */
+"stream end",          /* Z_STREAM_END      1  */
+"",                    /* Z_OK              0  */
+"file error",          /* Z_ERRNO         (-1) */
+"stream error",        /* Z_STREAM_ERROR  (-2) */
+"data error",          /* Z_DATA_ERROR    (-3) */
+"insufficient memory", /* Z_MEM_ERROR     (-4) */
+"buffer error",        /* Z_BUF_ERROR     (-5) */
+"incompatible version",/* Z_VERSION_ERROR (-6) */
+""};
+
+
+const char * ZEXPORT zlibVersion()
+{
+    return ZLIB_VERSION;
+}
+
+#ifdef DEBUG
+
+#  ifndef verbose
+#    define verbose 0
+#  endif
+int z_verbose = verbose;
+
+void z_error (m)
+    char *m;
+{
+    fprintf(stderr, "%s\n", m);
+    exit(1);
+}
+#endif
+
+/* exported to allow conversion of error code to string for compress() and
+ * uncompress()
+ */
+const char * ZEXPORT zError(err)
+    int err;
+{
+    return ERR_MSG(err);
+}
+
+
+#ifndef HAVE_MEMCPY
+
+void zmemcpy(dest, source, len)
+    Bytef* dest;
+    const Bytef* source;
+    uInt  len;
+{
+    if (len == 0) return;
+    do {
+        *dest++ = *source++; /* ??? to be unrolled */
+    } while (--len != 0);
+}
+
+int zmemcmp(s1, s2, len)
+    const Bytef* s1;
+    const Bytef* s2;
+    uInt  len;
+{
+    uInt j;
+
+    for (j = 0; j < len; j++) {
+        if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
+    }
+    return 0;
+}
+
+void zmemzero(dest, len)
+    Bytef* dest;
+    uInt  len;
+{
+    if (len == 0) return;
+    do {
+        *dest++ = 0;  /* ??? to be unrolled */
+    } while (--len != 0);
+}
+#endif
+
+#ifdef __TURBOC__
+#if (defined( __BORLANDC__) || !defined(SMALL_MEDIUM)) && !defined(__32BIT__)
+/* Small and medium model in Turbo C are for now limited to near allocation
+ * with reduced MAX_WBITS and MAX_MEM_LEVEL
+ */
+#  define MY_ZCALLOC
+
+/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
+ * and farmalloc(64K) returns a pointer with an offset of 8, so we
+ * must fix the pointer. Warning: the pointer must be put back to its
+ * original form in order to free it, use zcfree().
+ */
+
+#define MAX_PTR 10
+/* 10*64K = 640K */
+
+local int next_ptr = 0;
+
+typedef struct ptr_table_s {
+    voidpf org_ptr;
+    voidpf new_ptr;
+} ptr_table;
+
+local ptr_table table[MAX_PTR];
+/* This table is used to remember the original form of pointers
+ * to large buffers (64K). Such pointers are normalized with a zero offset.
+ * Since MSDOS is not a preemptive multitasking OS, this table is not
+ * protected from concurrent access. This hack doesn't work anyway on
+ * a protected system like OS/2. Use Microsoft C instead.
+ */
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+    voidpf buf = opaque; /* just to make some compilers happy */
+    ulg bsize = (ulg)items*size;
+
+    /* If we allocate less than 65520 bytes, we assume that farmalloc
+     * will return a usable pointer which doesn't have to be normalized.
+     */
+    if (bsize < 65520L) {
+        buf = farmalloc(bsize);
+        if (*(ush*)&buf != 0) return buf;
+    } else {
+        buf = farmalloc(bsize + 16L);
+    }
+    if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
+    table[next_ptr].org_ptr = buf;
+
+    /* Normalize the pointer to seg:0 */
+    *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
+    *(ush*)&buf = 0;
+    table[next_ptr++].new_ptr = buf;
+    return buf;
+}
+
+void  zcfree (voidpf opaque, voidpf ptr)
+{
+    int n;
+    if (*(ush*)&ptr != 0) { /* object < 64K */
+        farfree(ptr);
+        return;
+    }
+    /* Find the original pointer */
+    for (n = 0; n < next_ptr; n++) {
+        if (ptr != table[n].new_ptr) continue;
+
+        farfree(table[n].org_ptr);
+        while (++n < next_ptr) {
+            table[n-1] = table[n];
+        }
+        next_ptr--;
+        return;
+    }
+    ptr = opaque; /* just to make some compilers happy */
+    Assert(0, "zcfree: ptr not found");
+}
+#endif
+#endif /* __TURBOC__ */
+
+
+#if defined(M_I86) && !defined(__32BIT__)
+/* Microsoft C in 16-bit mode */
+
+#  define MY_ZCALLOC
+
+#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
+#  define _halloc  halloc
+#  define _hfree   hfree
+#endif
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+    if (opaque) opaque = 0; /* to make compiler happy */
+    return _halloc((long)items, size);
+}
+
+void  zcfree (voidpf opaque, voidpf ptr)
+{
+    if (opaque) opaque = 0; /* to make compiler happy */
+    _hfree(ptr);
+}
+
+#endif /* MSC */
+
+
+#ifndef MY_ZCALLOC /* Any system without a special alloc function */
+
+#ifndef STDC
+extern voidp  calloc OF((uInt items, uInt size));
+extern void   free   OF((voidpf ptr));
+#endif
+
+voidpf zcalloc (opaque, items, size)
+    voidpf opaque;
+    unsigned items;
+    unsigned size;
+{
+    if (opaque) items += size - size; /* make compiler happy */
+    return (voidpf)calloc(items, size);
+}
+
+void  zcfree (opaque, ptr)
+    voidpf opaque;
+    voidpf ptr;
+{
+    free(ptr);
+    if (opaque) return; /* make compiler happy */
+}
+
+#endif /* MY_ZCALLOC */
diff --git a/Utilities/ITK/Utilities/zlib/zutil.h b/Utilities/ITK/Utilities/zlib/zutil.h
new file mode 100644
index 0000000000..2fa3118198
--- /dev/null
+++ b/Utilities/ITK/Utilities/zlib/zutil.h
@@ -0,0 +1,220 @@
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id$ */
+
+#ifndef _Z_UTIL_H
+#define _Z_UTIL_H
+
+#include "zlib.h"
+
+#ifdef STDC
+#  include <stddef.h>
+#  include <string.h>
+#  include <stdlib.h>
+#endif
+#ifdef NO_ERRNO_H
+    extern int errno;
+#else
+#   include <errno.h>
+#endif
+
+#ifndef local
+#  define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+typedef unsigned char  uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long  ulg;
+
+extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */
+/* (size given to avoid silly warnings with Visual C++) */
+
+#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
+
+#define ERR_RETURN(strm,err) \
+  return (strm->msg = (char*)ERR_MSG(err), (err))
+/* To be used only when the state is known to be valid */
+
+        /* common constants */
+
+#ifndef DEF_WBITS
+#  define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+#  define DEF_MEM_LEVEL 8
+#else
+#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES    2
+/* The three kinds of block type */
+
+#define MIN_MATCH  3
+#define MAX_MATCH  258
+/* The minimum and maximum match lengths */
+
+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
+
+        /* target dependencies */
+
+#ifdef MSDOS
+#  define OS_CODE  0x00
+#  if defined(__TURBOC__) || defined(__BORLANDC__)
+#    if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
+       /* Allow compilation with ANSI keywords only enabled */
+       void _Cdecl farfree( void *block );
+       void *_Cdecl farmalloc( unsigned long nbytes );
+#    else
+#     include <alloc.h>
+#    endif
+#  else /* MSC or DJGPP */
+#    include <malloc.h>
+#  endif
+#endif
+
+#ifdef OS2
+#  define OS_CODE  0x06
+#endif
+
+#ifdef WIN32 /* Window 95 & Windows NT */
+#  define OS_CODE  0x0b
+#endif
+
+#if defined(VAXC) || defined(VMS)
+#  define OS_CODE  0x02
+#  define F_OPEN(name, mode) \
+     fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
+#endif
+
+#ifdef AMIGA
+#  define OS_CODE  0x01
+#endif
+
+#if defined(ATARI) || defined(atarist)
+#  define OS_CODE  0x05
+#endif
+
+#if defined(MACOS) || defined(TARGET_OS_MAC)
+#  define OS_CODE  0x07
+#  if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
+#    include <unix.h> /* for fdopen */
+#  else
+#    ifndef fdopen
+#      define fdopen(fd,mode) NULL /* No fdopen() */
+#    endif
+#  endif
+#endif
+
+#ifdef __50SERIES /* Prime/PRIMOS */
+#  define OS_CODE  0x0F
+#endif
+
+#ifdef TOPS20
+#  define OS_CODE  0x0a
+#endif
+
+#if defined(_BEOS_) || defined(RISCOS)
+#  define fdopen(fd,mode) NULL /* No fdopen() */
+#endif
+
+#if (defined(_MSC_VER) && (_MSC_VER > 600))
+#  define fdopen(fd,type)  _fdopen(fd,type)
+#endif
+
+
+        /* Common defaults */
+
+#ifndef OS_CODE
+#  define OS_CODE  0x03  /* assume Unix */
+#endif
+
+#ifndef F_OPEN
+#  define F_OPEN(name, mode) fopen((name), (mode))
+#endif
+
+         /* functions */
+
+#ifdef HAVE_STRERROR
+   extern char *strerror OF((int));
+#  define zstrerror(errnum) strerror(errnum)
+#else
+#  define zstrerror(errnum) ""
+#endif
+
+#if defined(pyr)
+#  define NO_MEMCPY
+#endif
+#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
+ /* Use our own functions for small and medium model with MSC <= 5.0.
+  * You may have to use the same strategy for Borland C (untested).
+  * The __SC__ check is for Symantec.
+  */
+#  define NO_MEMCPY
+#endif
+#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
+#  define HAVE_MEMCPY
+#endif
+#ifdef HAVE_MEMCPY
+#  ifdef SMALL_MEDIUM /* MSDOS small or medium model */
+#    define zmemcpy _fmemcpy
+#    define zmemcmp _fmemcmp
+#    define zmemzero(dest, len) _fmemset(dest, 0, len)
+#  else
+#    define zmemcpy memcpy
+#    define zmemcmp memcmp
+#    define zmemzero(dest, len) memset(dest, 0, len)
+#  endif
+#else
+   extern void zmemcpy  OF((Bytef* dest, const Bytef* source, uInt len));
+   extern int  zmemcmp  OF((const Bytef* s1, const Bytef* s2, uInt len));
+   extern void zmemzero OF((Bytef* dest, uInt len));
+#endif
+
+/* Diagnostic functions */
+#ifdef DEBUG
+#  include <stdio.h>
+   extern int z_verbose;
+   extern void z_error    OF((char *m));
+#  define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+#  define Trace(x) {if (z_verbose>=0) fprintf x ;}
+#  define Tracev(x) {if (z_verbose>0) fprintf x ;}
+#  define Tracevv(x) {if (z_verbose>1) fprintf x ;}
+#  define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
+#  define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
+#else
+#  define Assert(cond,msg)
+#  define Trace(x)
+#  define Tracev(x)
+#  define Tracevv(x)
+#  define Tracec(c,x)
+#  define Tracecv(c,x)
+#endif
+
+
+typedef uLong (ZEXPORT *check_func) OF((uLong check, const Bytef *buf,
+                                       uInt len));
+voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size));
+void   zcfree  OF((voidpf opaque, voidpf ptr));
+
+#define ZALLOC(strm, items, size) \
+           (*((strm)->zalloc))((strm)->opaque, (items), (size))
+#define ZFREE(strm, addr)  (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
+#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
+
+#endif /* _Z_UTIL_H */
-- 
GitLab