Index: GraphicsMagick-1.2.5/coders/png.c
===================================================================
--- GraphicsMagick-1.2.5.orig/coders/png.c	2018-01-19 20:08:30.737576639 +0100
+++ GraphicsMagick-1.2.5/coders/png.c	2018-01-19 20:29:20.474317244 +0100
@@ -1,5 +1,5 @@
 /*
-% Copyright (C) 2003-2008 GraphicsMagick Group
+% Copyright (C) 2003-2017 GraphicsMagick Group
 % Copyright (C) 2002 ImageMagick Studio
 % Copyright 1991-1999 E. I. du Pont de Nemours and Company
 %
@@ -34,6 +34,7 @@
 */
 
 /* GraphicsMagick differences */
+
 #define LoadImageTag LoadImageText
 #define SaveImageTag SaveImageText
 #define LoadImagesTag LoadImagesText
@@ -57,7 +58,6 @@
 #include "magick/studio.h"
 #include "magick/attribute.h"
 #include "magick/blob.h"
-#include "magick/pixel_cache.h"
 #include "magick/channel.h"
 #include "magick/color.h"
 #include "magick/constitute.h"
@@ -65,22 +65,44 @@
 #include "magick/log.h"
 #include "magick/magick.h"
 #include "magick/monitor.h"
+#include "magick/pixel_cache.h"
 #include "magick/profile.h"
 #include "magick/quantize.h"
 #include "magick/resource.h"
-#include "magick/static.h"
 #include "magick/semaphore.h"
+#include "magick/static.h"
 #include "magick/tempfile.h"
 #include "magick/transform.h"
 #include "magick/utility.h"
+#include "magick/version.h"
 #if defined(HasPNG)
+
+/* Suppress libpng pedantic warnings */
+#define PNG_DEPRECATED  /* Use of this function is deprecated */
+#define PNG_USE_RESULT  /* The result of this function must be checked */
+#define PNG_NORETURN    /* This function does not return */
+/* #define PNG_ALLOCATED */ /* The result of the function is new memory */
+#define PNG_DEPSTRUCT   /* access to this struct member is deprecated */
+
 #include "png.h"
 #include "zlib.h"
+#undef HasLCMS
+#if defined(HasLCMS)
+#  if defined(HAVE_LCMS2_LCMS2_H)
+#    include <lcms2/lcms2.h>
+#  elif defined(HAVE_LCMS2_H)
+#    include <lcms2.h>
+#  else
+#    error "LCMS 2 header missing!"
+#  endif
+#endif
 
-#if PNG_LIBPNG_VER > 95
+
+#if PNG_LIBPNG_VER > 10011
 /*
   Optional declarations. Define or undefine them as you like.
 */
+
 /* #define PNG_DEBUG -- turning this on breaks VisualC compiling */
 
 /*
@@ -90,8 +112,7 @@
 #undef MNG_BASI_SUPPORTED
 #define MNG_COALESCE_LAYERS /* In 5.4.4, this interfered with MMAP'ed files. */
 #define MNG_INSERT_LAYERS   /* Troublesome, but seem to work as of 5.4.4 */
-#define PNG_BUILD_PALETTE   /* This works as of 5.4.3. */
-#define PNG_SORT_PALETTE    /* This works as of 5.4.0. */
+#define GMPNG_BUILD_PALETTE   /* This works as of 5.4.3. */
 #if defined(HasJPEG)
 #  define JNG_SUPPORTED /* Not finished as of 5.5.2.  See "To do" comments. */
 #endif
@@ -101,10 +122,6 @@
   setjmp/longjmp is claimed to be safe on these platforms:
   setjmp/longjmp is alleged to be unsafe on these platforms:
 */
-#ifndef SETJMP_IS_THREAD_SAFE
-#define PNG_SETJMP_NOT_THREAD_SAFE
-#endif
-
 #if defined(PNG_SETJMP_NOT_THREAD_SAFE)
 static SemaphoreInfo
   *png_semaphore = (SemaphoreInfo *) NULL;
@@ -134,10 +151,6 @@ static SemaphoreInfo
   PNG_MNG_FEATURES_SUPPORTED is disabled by default in libpng-1.0.9 and
   will be enabled by default in libpng-1.2.0.
 */
-#if (PNG_LIBPNG_VER == 10009)  /* work around libpng-1.0.9 bug */
-#  undef PNG_READ_EMPTY_PLTE_SUPPORTED
-#  undef PNG_WRITE_EMPTY_PLTE_SUPPORTED
-#endif
 #ifdef PNG_MNG_FEATURES_SUPPORTED
 #  ifndef PNG_READ_EMPTY_PLTE_SUPPORTED
 #    define PNG_READ_EMPTY_PLTE_SUPPORTED
@@ -161,59 +174,72 @@ static SemaphoreInfo
   portable, we use ASCII numbers like this, not characters.
 */
 
-static png_byte FARDATA mng_MHDR[5]={ 77,  72,  68,  82, '\0'};
-static png_byte FARDATA mng_BACK[5]={ 66,  65,  67,  75, '\0'};
-static png_byte FARDATA mng_BASI[5]={ 66,  65,  83,  73, '\0'};
-static png_byte FARDATA mng_CLIP[5]={ 67,  76,  73,  80, '\0'};
-static png_byte FARDATA mng_CLON[5]={ 67,  76,  79,  78, '\0'};
-static png_byte FARDATA mng_DEFI[5]={ 68,  69,  70,  73, '\0'};
-static png_byte FARDATA mng_DHDR[5]={ 68,  72,  68,  82, '\0'};
-static png_byte FARDATA mng_DISC[5]={ 68,  73,  83,  67, '\0'};
-static png_byte FARDATA mng_ENDL[5]={ 69,  78,  68,  76, '\0'};
-static png_byte FARDATA mng_FRAM[5]={ 70,  82,  65,  77, '\0'};
-static png_byte FARDATA mng_IEND[5]={ 73,  69,  78,  68, '\0'};
-static png_byte FARDATA mng_IHDR[5]={ 73,  72,  68,  82, '\0'};
-static png_byte FARDATA mng_JHDR[5]={ 74,  72,  68,  82, '\0'};
-static png_byte FARDATA mng_LOOP[5]={ 76,  79,  79,  80, '\0'};
-static png_byte FARDATA mng_MAGN[5]={ 77,  65,  71,  78, '\0'};
-static png_byte FARDATA mng_MEND[5]={ 77,  69,  78,  68, '\0'};
-static png_byte FARDATA mng_MOVE[5]={ 77,  79,  86,  69, '\0'};
-static png_byte FARDATA mng_PAST[5]={ 80,  65,  83,  84, '\0'};
-static png_byte FARDATA mng_PLTE[5]={ 80,  76,  84,  69, '\0'};
-static png_byte FARDATA mng_SAVE[5]={ 83,  65,  86,  69, '\0'};
-static png_byte FARDATA mng_SEEK[5]={ 83,  69,  69,  75, '\0'};
-static png_byte FARDATA mng_SHOW[5]={ 83,  72,  79,  87, '\0'};
-static png_byte FARDATA mng_TERM[5]={ 84,  69,  82,  77, '\0'};
-static png_byte FARDATA mng_bKGD[5]={ 98,  75,  71,  68, '\0'};
-static png_byte FARDATA mng_cHRM[5]={ 99,  72,  82,  77, '\0'};
-static png_byte FARDATA mng_gAMA[5]={103,  65,  77,  65, '\0'};
-static png_byte FARDATA mng_iCCP[5]={105,  67,  67,  80, '\0'};
-static png_byte FARDATA mng_nEED[5]={110,  69,  69,  68, '\0'};
-static png_byte FARDATA mng_pHYg[5]={112,  72,  89, 103, '\0'};
-static png_byte FARDATA mng_pHYs[5]={112,  72,  89, 115, '\0'};
-static png_byte FARDATA mng_sBIT[5]={115,  66,  73,  84, '\0'};
-static png_byte FARDATA mng_sRGB[5]={115,  82,  71,  66, '\0'};
-static png_byte FARDATA mng_tRNS[5]={116,  82,  78,  83, '\0'};
+static png_byte const mng_MHDR[5]={ 77,  72,  68,  82, '\0'};
+static png_byte const mng_BACK[5]={ 66,  65,  67,  75, '\0'};
+static png_byte const mng_BASI[5]={ 66,  65,  83,  73, '\0'};
+static png_byte const mng_CLIP[5]={ 67,  76,  73,  80, '\0'};
+static png_byte const mng_CLON[5]={ 67,  76,  79,  78, '\0'};
+static png_byte const mng_DEFI[5]={ 68,  69,  70,  73, '\0'};
+static png_byte const mng_DHDR[5]={ 68,  72,  68,  82, '\0'};
+static png_byte const mng_DISC[5]={ 68,  73,  83,  67, '\0'};
+static png_byte const mng_ENDL[5]={ 69,  78,  68,  76, '\0'};
+static png_byte const mng_FRAM[5]={ 70,  82,  65,  77, '\0'};
+static png_byte const mng_IEND[5]={ 73,  69,  78,  68, '\0'};
+static png_byte const mng_IHDR[5]={ 73,  72,  68,  82, '\0'};
+static png_byte const mng_JHDR[5]={ 74,  72,  68,  82, '\0'};
+static png_byte const mng_LOOP[5]={ 76,  79,  79,  80, '\0'};
+static png_byte const mng_MAGN[5]={ 77,  65,  71,  78, '\0'};
+static png_byte const mng_MEND[5]={ 77,  69,  78,  68, '\0'};
+static png_byte const mng_MOVE[5]={ 77,  79,  86,  69, '\0'};
+static png_byte const mng_PAST[5]={ 80,  65,  83,  84, '\0'};
+static png_byte const mng_PLTE[5]={ 80,  76,  84,  69, '\0'};
+static png_byte const mng_SAVE[5]={ 83,  65,  86,  69, '\0'};
+static png_byte const mng_SEEK[5]={ 83,  69,  69,  75, '\0'};
+static png_byte const mng_SHOW[5]={ 83,  72,  79,  87, '\0'};
+static png_byte const mng_TERM[5]={ 84,  69,  82,  77, '\0'};
+static png_byte const mng_bKGD[5]={ 98,  75,  71,  68, '\0'};
+static png_byte const mng_caNv[5]={ 99,  97,  78, 118, '\0'};
+static png_byte const mng_cHRM[5]={ 99,  72,  82,  77, '\0'};
+static png_byte const mng_eXIf[5]={101,  88,  73, 102, '\0'};
+static png_byte const mng_gAMA[5]={103,  65,  77,  65, '\0'};
+static png_byte const mng_iCCP[5]={105,  67,  67,  80, '\0'};
+static png_byte const mng_nEED[5]={110,  69,  69,  68, '\0'};
+static png_byte const mng_orNT[5]={111, 114,  78,  84, '\0'};
+static png_byte const mng_pHYg[5]={112,  72,  89, 103, '\0'};
+static png_byte const mng_pHYs[5]={112,  72,  89, 115, '\0'};
+static png_byte const mng_sBIT[5]={115,  66,  73,  84, '\0'};
+static png_byte const mng_sRGB[5]={115,  82,  71,  66, '\0'};
+static png_byte const mng_tRNS[5]={116,  82,  78,  83, '\0'};
 
 #if defined(JNG_SUPPORTED)
-static png_byte FARDATA mng_IDAT[5]={ 73,  68,  65,  84, '\0'};
-static png_byte FARDATA mng_JDAT[5]={ 74,  68,  65,  84, '\0'};
-static png_byte FARDATA mng_JDAA[5]={ 74,  68,  65,  65, '\0'};
-static png_byte FARDATA mng_JdAA[5]={ 74, 100,  65,  65, '\0'};
-static png_byte FARDATA mng_JSEP[5]={ 74,  83,  69,  80, '\0'};
-static png_byte FARDATA mng_oFFs[5]={111,  70,  70, 115, '\0'};
+static png_byte const mng_IDAT[5]={ 73,  68,  65,  84, '\0'};
+static png_byte const mng_JDAT[5]={ 74,  68,  65,  84, '\0'};
+static png_byte const mng_JDAA[5]={ 74,  68,  65,  65, '\0'};
+static png_byte const mng_JdAA[5]={ 74, 100,  65,  65, '\0'};
+static png_byte const mng_JSEP[5]={ 74,  83,  69,  80, '\0'};
+static png_byte const mng_oFFs[5]={111,  70,  70, 115, '\0'};
 #endif
 
 /*
-static png_byte FARDATA mng_hIST[5]={104,  73,  83,  84, '\0'};
-static png_byte FARDATA mng_iCCP[5]={105,  67,  67,  80, '\0'};
-static png_byte FARDATA mng_iTXt[5]={105,  84,  88, 116, '\0'};
-static png_byte FARDATA mng_sPLT[5]={115,  80,  76,  84, '\0'};
-static png_byte FARDATA mng_tEXt[5]={116,  69,  88, 116, '\0'};
-static png_byte FARDATA mng_tIME[5]={116,  73,  77,  69, '\0'};
-static png_byte FARDATA mng_zTXt[5]={122,  84,  88, 116, '\0'};
+static png_byte const mng_hIST[5]={104,  73,  83,  84, '\0'};
+static png_byte const mng_iCCP[5]={105,  67,  67,  80, '\0'};
+static png_byte const mng_iTXt[5]={105,  84,  88, 116, '\0'};
+static png_byte const mng_sPLT[5]={115,  80,  76,  84, '\0'};
+static png_byte const mng_tEXt[5]={116,  69,  88, 116, '\0'};
+static png_byte const mng_tIME[5]={116,  73,  77,  69, '\0'};
+static png_byte const mng_zTXt[5]={122,  84,  88, 116, '\0'};
 */
 
+typedef struct _UShortPixelPacket
+{
+  unsigned short
+    red,
+    green,
+    blue,
+    opacity,
+    index;
+} UShortPixelPacket;
+
 typedef struct _MngBox
 {
   long
@@ -307,7 +333,6 @@ typedef struct _MngInfo
     need_fram,
     object_id,
     old_framing_mode,
-    optimize,
     saved_bkgd_index;
 
   int
@@ -384,9 +409,13 @@ typedef struct _MngInfo
     show_warning,
     mng_type,
     write_mng,
+    write_png_colortype,
+    write_png_depth,
     write_png8,
     write_png24,
-    write_png32;
+    write_png32,
+    write_png48,
+    write_png64;
 
 #ifdef MNG_BASI_SUPPORTED
   unsigned long
@@ -421,6 +450,12 @@ typedef struct _MngInfo
   PixelPacket
     mng_global_bkgd;
 
+  unsigned char
+    *png_pixels;
+
+  Quantum
+    *quantum_scanline;
+
 } MngInfo;
 #endif /* VER */
 
@@ -435,6 +470,7 @@ static unsigned int
 static unsigned int
   WriteJNGImage(const ImageInfo *,Image *);
 #endif
+
 static const char* PngColorTypeToString(const unsigned int color_type)
 {
   const char
@@ -461,8 +497,7 @@ static const char* PngColorTypeToString(
 
   return result;
 }
-
-
+#endif /* HasPNG */
 static size_t MagickArraySize(const size_t count, const size_t size)
 {
   size_t
@@ -476,285 +511,6 @@ static size_t MagickArraySize(const size
 }
 
 
-#if PNG_LIBPNG_VER > 95
-#if defined(PNG_SORT_PALETTE)
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%   C o m p r e s s C o l o r m a p T r a n s F i r s t                       %
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-%  Method CompressColormapTransFirst compresses an image colormap removing
-%  any duplicate and unused color entries and putting the transparent colors
-%  first.
-%
-%  The format of the CompressColormapTransFirst method is:
-%
-%      unsigned int CompressColormapTransFirst(Image *image)
-%
-%  A description of each parameter follows:
-%
-%    o image: The address of a structure of type Image.
-%
-%
-*/
-static unsigned int CompressColormapTransFirst(Image *image)
-{
-  int
-    remap_needed,
-    k;
-
-  long
-    j,
-    new_number_colors,
-    number_colors,
-    y;
-
-  PixelPacket
-    *colormap;
-
-  register const PixelPacket
-    *p;
-
-  register IndexPacket
-    *indexes,
-    top_used;
-
-  register long
-    i,
-    x;
-
-  IndexPacket
-    *map,
-    *opacity;
-
-  unsigned char
-    *marker,
-    have_transparency;
-
-  /*
-    Determine if colormap can be compressed.
-  */
-  assert(image != (Image *) NULL);
-  if (image->storage_class != PseudoClass || image->colors > 256 ||
-      image->colors < 2)
-    return(False);
-  marker=MagickAllocateMemory(unsigned char *,image->colors);
-  if (marker == (unsigned char *) NULL)
-    ThrowBinaryException(ResourceLimitError,MemoryAllocationFailed,
-                         "Unable to compress image colormap")
-      opacity=MagickAllocateMemory(IndexPacket *,
-                                   image->colors*sizeof(IndexPacket));
-  if (opacity == (IndexPacket *) NULL)
-    {
-      MagickFreeMemory(marker);
-      ThrowBinaryException(ResourceLimitError,MemoryAllocationFailed,
-                           "Unable to compress image colormap")
-        }
-  /*
-    Mark colors that are present.
-  */
-  number_colors=(long) image->colors;
-  for (i=0; i < number_colors; i++)
-    {
-      marker[i]=False;
-      opacity[i]=OpaqueOpacity;
-    }
-  top_used=0;
-  for (y=0; y < (long) image->rows; y++)
-    {
-      p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
-      if (p == (const PixelPacket *) NULL)
-        break;
-      indexes=GetIndexes(image);
-      if (image->matte)
-        for (x=0; x < (long) image->columns; x++)
-          {
-            marker[(int) indexes[x]]=True;
-            opacity[(int) indexes[x]]=p->opacity;
-            if (indexes[x] > top_used)
-              top_used=indexes[x];
-            p++;
-          }
-      else
-        for (x=0; x < (long) image->columns; x++)
-          {
-            marker[(int) indexes[x]]=True;
-            if (indexes[x] > top_used)
-              top_used=indexes[x];
-          }
-    }
-
-  if (image->matte)
-    {
-      /*
-        Mark background color, topmost occurrence if more than one.
-      */
-      for (i=number_colors-1; i; i--)
-        {
-          if (RGBColorMatchExact(image->colormap[i],image->background_color))
-            {
-              marker[i]=True;
-              break;
-            }
-        }
-    }
-  /*
-    Unmark duplicates.
-  */
-  for (i=0; i < number_colors-1; i++)
-    if (marker[i])
-      {
-        for (j=i+1; j < number_colors; j++)
-          if ((opacity[i] == opacity[j]) &&
-              (RGBColorMatchExact(image->colormap[i],image->colormap[j])))
-            marker[j]=False;
-      }
-  /*
-    Count colors that still remain.
-  */
-  have_transparency=False;
-  new_number_colors=0;
-  for (i=0; i < number_colors; i++)
-    if (marker[i])
-      {
-        new_number_colors++;
-        if (opacity[i] != OpaqueOpacity)
-          have_transparency=True;
-      }
-  if ((!have_transparency || (marker[0] && (opacity[0] == TransparentOpacity)))
-      && (new_number_colors == number_colors))
-    {
-      /*
-        No duplicate or unused entries, and transparency-swap not needed
-      */
-      MagickFreeMemory(marker);
-      MagickFreeMemory(opacity);
-      return(True);
-    }
-
-  remap_needed=False;
-  if ((long) top_used >= new_number_colors)
-    remap_needed=True;
-
-  /*
-    Compress colormap.
-  */
-
-  colormap=MagickAllocateMemory(PixelPacket *,
-                                image->colors*sizeof(PixelPacket));
-  if (colormap == (PixelPacket *) NULL)
-    {
-      MagickFreeMemory(marker);
-      MagickFreeMemory(opacity);
-      ThrowBinaryException(ResourceLimitError,MemoryAllocationFailed,
-                           "Unable to compress image colormap")
-        }
-  /*
-    Eliminate unused colormap entries.
-  */
-  map=MagickAllocateMemory(IndexPacket *,number_colors*sizeof(IndexPacket));
-  if (map == (IndexPacket *) NULL)
-    {
-      MagickFreeMemory(marker);
-      MagickFreeMemory(opacity);
-      MagickFreeMemory(colormap);
-      ThrowBinaryException(ResourceLimitError,MemoryAllocationFailed,
-                           "Unable to compress image colormap")
-        }
-  k=0;
-  for (i=0; i < number_colors; i++)
-    {
-      map[i]=(IndexPacket) k;
-      if (marker[i])
-        {
-          for (j=i+1; j < number_colors; j++)
-            {
-              if ((opacity[i] == opacity[j]) &&
-                  (RGBColorMatchExact(image->colormap[i],image->colormap[j])))
-                {
-                  map[j]=(IndexPacket) k;
-                  marker[j]=False;
-                }
-            }
-          k++;
-        }
-    }
-  j=0;
-  for (i=0; i < number_colors; i++)
-    {
-      if (marker[i])
-        {
-          colormap[j]=image->colormap[i];
-          j++;
-        }
-    }
-  if (have_transparency && (opacity[0] != TransparentOpacity))
-    {
-      /*
-        Move the first transparent color to palette entry 0.
-      */
-      for (i=1; i < number_colors; i++)
-        {
-          if (marker[i] && opacity[i] == TransparentOpacity)
-            {
-              PixelPacket
-                temp_colormap;
-
-              temp_colormap=colormap[0];
-              colormap[0]=colormap[(int) map[i]];
-              colormap[map[i]]=temp_colormap;
-              for (j=0; j < number_colors; j++)
-                {
-                  if (map[j] == 0)
-                    map[j]=map[i];
-                  else if (map[j] == map[i])
-                    map[j]=0;
-                }
-              remap_needed=True;
-              break;
-            }
-        }
-    }
-
-  MagickFreeMemory(opacity);
-  MagickFreeMemory(marker);
-
-  if (remap_needed)
-    {
-      /*
-        Remap pixels.
-      */
-      for (y=0; y < (long) image->rows; y++)
-        {
-          p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
-          if (p == (const PixelPacket *) NULL)
-            break;
-          indexes=GetIndexes(image);
-          for (x=0; x < (long) image->columns; x++)
-            {
-              j=(int) indexes[x];
-              indexes[x]=map[j];
-            }
-          if (!SyncImagePixels(image))
-            break;
-        }
-      for (i=0; i < new_number_colors; i++)
-        image->colormap[i]=colormap[i];
-    }
-  MagickFreeMemory(colormap);
-  image->colors=new_number_colors;
-  MagickFreeMemory(map);
-  return(True);
-}
-#endif
-#endif /* PNG_LIBPNG_VER > 95 */
-#endif /* HasPNG */
 
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -785,13 +541,13 @@ static unsigned int CompressColormapTran
 %
 %
 */
-static unsigned int IsMNG(const unsigned char *magick,const size_t length)
+static MagickPassFail IsMNG(const unsigned char *magick,const size_t length)
 {
   if (length < 8)
-    return(False);
+    return(MagickFail);
   if (memcmp(magick,"\212MNG\r\n\032\n",8) == 0)
-    return(True);
-  return(False);
+    return(MagickPass);
+  return(MagickFail);
 }
 
 /*
@@ -823,13 +579,13 @@ static unsigned int IsMNG(const unsigned
 %
 %
 */
-static unsigned int IsJNG(const unsigned char *magick,const size_t length)
+static MagickPassFail IsJNG(const unsigned char *magick,const size_t length)
 {
   if (length < 8)
-    return(False);
+    return(MagickFail);
   if (memcmp(magick,"\213JNG\r\n\032\n",8) == 0)
-    return(True);
-  return(False);
+    return(MagickPass);
+  return(MagickFail);
 }
 
 /*
@@ -861,13 +617,13 @@ static unsigned int IsJNG(const unsigned
 %
 %
 */
-static unsigned int IsPNG(const unsigned char *magick,const size_t length)
+static MagickPassFail IsPNG(const unsigned char *magick,const size_t length)
 {
   if (length < 8)
-    return(False);
+    return(MagickFail);
   if (memcmp(magick,"\211PNG\r\n\032\n",8) == 0)
-    return(True);
-  return(False);
+    return(MagickPass);
+  return(MagickFail);
 }
 
 #if defined(HasPNG)
@@ -875,7 +631,7 @@ static unsigned int IsPNG(const unsigned
 extern "C" {
 #endif
 
-#if (PNG_LIBPNG_VER > 95)
+#if (PNG_LIBPNG_VER > 10011)
 static size_t WriteBlobMSBULong(Image *image,const unsigned long value)
 {
   unsigned char
@@ -912,25 +668,25 @@ static void PNGShort(png_bytep p,png_uin
   *p++=(png_byte) (value & 0xff);
 }
 
-static void PNGType(png_bytep p,png_bytep type)
+static void PNGType(png_bytep p,png_byte const * type)
 {
   (void) memcpy(p,type,4*sizeof(png_byte));
 }
 
-static void LogPNGChunk(int logging, png_bytep type, unsigned long length)
+static void LogPNGChunk(int logging, png_byte const * type, size_t length)
 {
   if (logging)
     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
         "  Writing %c%c%c%c chunk, length: %lu",
         type[0],type[1],type[2],type[3],length);
 }
-#endif /* PNG_LIBPNG_VER > 95 */
+#endif /* PNG_LIBPNG_VER > 10011 */
 
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif
 
-#if PNG_LIBPNG_VER > 95
+#if PNG_LIBPNG_VER > 10011
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %                                                                             %
@@ -951,7 +707,8 @@ static void LogPNGChunk(int logging, png
 %
 %  The format of the ReadPNGImage method is:
 %
-%      Image *ReadPNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
+%      Image *ReadPNGImage(const ImageInfo *image_info,
+%                          ExceptionInfo *exception)
 %
 %  A description of each parameter follows:
 %
@@ -1012,6 +769,13 @@ static void LogPNGChunk(int logging, png
 %    Upgrade to full MNG with Delta-PNG.
 %
 %    JNG tEXt/iTXt/zTXt
+%
+%    We will not attempt to read files containing the CgBI chunk.
+%    They are really Xcode files meant for display on the iPhone.
+%    These are not valid PNG files and it is impossible to recover
+%    the orginal PNG from files that have been converted to Xcode-PNG,
+%    since irretrievable loss of color data has occurred due to the
+%    use of premultiplied alpha.
 */
 
 #if defined(__cplusplus) || defined(c_plusplus)
@@ -1033,7 +797,7 @@ static void png_get_data(png_structp png
     {
       png_size_t
         check;
-      
+
       if (length > 0x7fffffff)
         png_warning(png_ptr, "chunk length > 2G");
       check=(png_size_t) ReadBlob(image,(size_t) length,(char *) data);
@@ -1041,9 +805,9 @@ static void png_get_data(png_structp png
         {
           char
             msg[MaxTextExtent];
-          
-          (void) sprintf(msg,"Expected %lu bytes; found %lu bytes",
-                         (unsigned long) length,(unsigned long) check);
+
+            (void) sprintf(msg,"Expected %lu bytes; found %lu bytes",
+                           (unsigned long) length,(unsigned long) check);
           png_warning(png_ptr,msg);
           png_error(png_ptr,"Read Exception");
         }
@@ -1064,16 +828,16 @@ static void mng_get_data(png_structp png
 {
   MngInfo
     *mng_info;
-  
+
   Image
     *image;
-  
+
   png_size_t
     check;
-  
+
   register long
     i;
-  
+
   i=0;
   mng_info=(MngInfo *) png_get_io_ptr(png_ptr);
   image=(Image *) mng_info->image;
@@ -1099,11 +863,11 @@ static void mng_get_data(png_structp png
               mng_info->read_buffer[4]=0;
               mng_info->bytes_in_read_buffer=4;
               if (!memcmp(mng_info->read_buffer,mng_PLTE,4))
-                mng_info->found_empty_plte=True;
+                mng_info->found_empty_plte=MagickTrue;
               if (!memcmp(mng_info->read_buffer,mng_IEND,4))
                 {
-                  mng_info->found_empty_plte=False;
-                  mng_info->have_saved_bkgd_index=False;
+                  mng_info->found_empty_plte=MagickFalse;
+                  mng_info->have_saved_bkgd_index=MagickFalse;
                 }
             }
           if ((data[0] == 0) && (data[1] == 0) && (data[2] == 0) &&
@@ -1122,9 +886,10 @@ static void mng_get_data(png_structp png
                     check=(png_size_t)
                       ReadBlob(image,5,(char *) mng_info->read_buffer);
                     check=(png_size_t) ReadBlob(image,(size_t) length,
-                                                (char *) mng_info->read_buffer);
+                                                (char *)
+                                                mng_info->read_buffer);
                     mng_info->saved_bkgd_index=mng_info->read_buffer[0];
-                    mng_info->have_saved_bkgd_index=True;
+                    mng_info->have_saved_bkgd_index=MagickTrue;
                     mng_info->bytes_in_read_buffer=0;
                   }
             }
@@ -1137,13 +902,13 @@ static void png_put_data(png_structp png
 {
   Image
     *image;
-  
+
   image=(Image *) png_get_io_ptr(png_ptr);
   if (length)
     {
       png_size_t
         check;
-      
+
       check=(png_size_t) WriteBlob(image,(unsigned long) length,(char *) data);
       if (check != length)
         png_error(png_ptr,"WriteBlob Failed");
@@ -1153,12 +918,12 @@ static void png_put_data(png_structp png
 static void png_flush_data(png_structp png_ptr)
 {
   ARG_NOT_USED(png_ptr);
-  
+
   /* There is currently no safe API to "flush" a blob. */
 #if 0
   Image
     *image;
-  
+
   image=(Image *) png_get_io_ptr(png_ptr);
   (void) SyncBlob(image);
 #endif
@@ -1169,21 +934,21 @@ static int PalettesAreEqual(Image *a,Ima
 {
   long
     i;
-  
+
   if ((a == (Image *) NULL) || (b == (Image *) NULL))
-    return((int) False);
+    return(MagickFail);
   if (a->storage_class!=PseudoClass || b->storage_class!=PseudoClass)
-    return((int) False);
+    return(MagickFail);
   if (a->colors != b->colors)
-    return((int) False);
+    return(MagickFail);
   for (i=0; i < (long) a->colors; i++)
     {
       if ((a->colormap[i].red != b->colormap[i].red) ||
           (a->colormap[i].green != b->colormap[i].green) ||
           (a->colormap[i].blue != b->colormap[i].blue))
-        return((int) False);
+        return(MagickFail);
     }
-  return((int) True);
+  return((int) MagickTrue);
 }
 #endif
 
@@ -1200,16 +965,19 @@ static void MngInfoDiscardObject(MngInfo
           if (mng_info->ob[i]->reference_count == 0)
             {
               if (mng_info->ob[i]->image != (Image *) NULL)
-                DestroyImage(mng_info->ob[i]->image);
+                {
+                  DestroyImage(mng_info->ob[i]->image);
+                  mng_info->ob[i]->image=(Image *) NULL;
+                }
               MagickFreeMemory(mng_info->ob[i]);
             }
         }
       mng_info->ob[i]=(MngBuffer *) NULL;
 #endif
-      mng_info->exists[i]=False;
-      mng_info->invisible[i]=False;
-      mng_info->viewable[i]=False;
-      mng_info->frozen[i]=False;
+      mng_info->exists[i]=MagickFalse;
+      mng_info->invisible[i]=MagickFalse;
+      mng_info->viewable[i]=MagickFalse;
+      mng_info->frozen[i]=MagickFalse;
       mng_info->x_off[i]=0;
       mng_info->y_off[i]=0;
       mng_info->object_clip[i].left=0;
@@ -1225,13 +993,13 @@ static void MngInfoFreeStruct(MngInfo *m
     {
       register long
         i;
-      
+
       for (i=1; i < MNG_MAX_OBJECTS; i++)
         MngInfoDiscardObject(mng_info,i);
-      if (mng_info->global_plte != (png_colorp) NULL)
-        MagickFreeMemory(mng_info->global_plte);
+      mng_info->image=(Image *)NULL;
+      MagickFreeMemory(mng_info->global_plte);
       MagickFreeMemory(mng_info);
-      *have_mng_structure=False;
+      *have_mng_structure=MagickFalse;
     }
 }
 
@@ -1239,7 +1007,7 @@ static MngBox mng_minimum_box(MngBox box
 {
   MngBox
     box;
-  
+
   box=box1;
   if (box.left < box2.left)
     box.left=box2.left;
@@ -1252,18 +1020,27 @@ static MngBox mng_minimum_box(MngBox box
   return box;
 }
 
-static MngBox mng_read_box(MngBox previous_box,char delta_type,unsigned char *p)
+static long mng_get_long(unsigned char *p)
+{
+  return ((long) (((magick_uint32_t) p[0] << 24) |
+                  ((magick_uint32_t) p[1] << 16) |
+                  ((magick_uint32_t) p[2] <<  8) |
+                  (magick_uint32_t)  p[3]));
+}
+
+static MngBox mng_read_box(MngBox previous_box,char delta_type,
+                           unsigned char *p)
 {
   MngBox
     box;
-  
+
   /*
     Read clipping boundaries from DEFI, CLIP, FRAM, or PAST chunk.
   */
-  box.left=(long) ((p[0]  << 24) | (p[1]  << 16) | (p[2]  << 8) | p[3]);
-  box.right=(long) ((p[4]  << 24) | (p[5]  << 16) | (p[6]  << 8) | p[7]);
-  box.top=(long) ((p[8]  << 24) | (p[9]  << 16) | (p[10] << 8) | p[11]);
-  box.bottom=(long) ((p[12] << 24) | (p[13] << 16) | (p[14] << 8) | p[15]);
+  box.left  = mng_get_long(p);
+  box.right = mng_get_long(&p[4]);
+  box.top   = mng_get_long(&p[8]);
+  box.bottom= mng_get_long(&p[12]);
   if (delta_type != 0)
     {
       box.left+=previous_box.left;
@@ -1282,8 +1059,9 @@ static MngPair mng_read_pair(MngPair pre
   /*
     Read two longs from CLON, MOVE or PAST chunk
   */
-  pair.a=(long) ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
-  pair.b=(long) ((p[4] << 24) | (p[5] << 16) | (p[6] << 8) | p[7]);
+  pair.a= mng_get_long(p);
+  pair.b= mng_get_long(&p[4]);
+
   if (delta_type != 0)
     {
       pair.a+=previous_pair.a;
@@ -1292,34 +1070,34 @@ static MngPair mng_read_pair(MngPair pre
   return(pair);
 }
 
-static long mng_get_long(unsigned char *p)
-{
-  return((long) ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]));
-}
-
 static void PNGErrorHandler(png_struct *ping,png_const_charp message)
 {
   Image
     *image;
-  
+
   image=(Image *) png_get_error_ptr(ping);
   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                        "  libpng-%.1024s error: %.1024s", PNG_LIBPNG_VER_STRING,
-                        message);
+                        "  libpng-%.1024s error: %.1024s",
+                        PNG_LIBPNG_VER_STRING, message);
   (void) ThrowException2(&image->exception,CoderError,message,image->filename);
+#if (PNG_LIBPNG_VER < 10500)
   longjmp(ping->jmpbuf,1);
+#else
+  png_longjmp(ping,1);
+#endif
+  SignalHandlerExit(1); /* Avoid GCC warning about non-exit function which does exit */
 }
 
 static void PNGWarningHandler(png_struct *ping,png_const_charp message)
 {
   Image
     *image;
-  
+
   if (LocaleCompare(message, "Missing PLTE before tRNS") == 0)
     png_error(ping, message);
   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                        "  libpng-%.1024s warning: %.1024s", PNG_LIBPNG_VER_STRING,
-                        message);
+                        "  libpng-%.1024s warning: %.1024s",
+                        PNG_LIBPNG_VER_STRING, message);
   image=(Image *) png_get_error_ptr(ping);
   (void) ThrowException2(&image->exception,CoderWarning,message,
                          image->filename);
@@ -1332,19 +1110,8 @@ static png_voidp png_IM_malloc(png_struc
 static png_voidp png_IM_malloc(png_structp png_ptr,png_size_t size)
 #endif
 {
-#if (PNG_LIBPNG_VER < 10011)
-  png_voidp
-    ret;
-  
-  png_ptr=png_ptr;
-  ret=MagickAllocateMemory(png_voidp,(size_t) size);
-  if (ret == NULL)
-    png_error("Insufficient memory.");
-  return (ret);
-#else
-  png_ptr=png_ptr;
+  (void) png_ptr;
   return MagickAllocateMemory(png_voidp,(size_t) size);
-#endif
 }
 
 /*
@@ -1352,7 +1119,7 @@ static png_voidp png_IM_malloc(png_struc
 */
 static png_free_ptr png_IM_free(png_structp png_ptr,png_voidp ptr)
 {
-  png_ptr=png_ptr;
+  (void) png_ptr;
   MagickFreeMemory(ptr);
   return((png_free_ptr) NULL);
 }
@@ -1362,7 +1129,7 @@ static png_free_ptr png_IM_free(png_stru
 }
 #endif
 
-static int
+static MagickPassFail
 png_read_raw_profile(Image *image, const ImageInfo *image_info,
                      png_textp text,int ii)
 {
@@ -1408,15 +1175,15 @@ png_read_raw_profile(Image *image, const
   if (length == 0)
     {
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                            "invalid profile length");
-      return (False);
+          "invalid profile length");
+      return (MagickFail);
     }
   info=MagickAllocateMemory(unsigned char *,length);
   if (info == (unsigned char *) NULL)
     {
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                            "Unable to copy profile");
-      return (False);
+          "Unable to copy profile");
+      return (MagickFail);
     }
   /* copy profile, skipping white space and column 1 "=" signs */
   dp=info;
@@ -1427,10 +1194,10 @@ png_read_raw_profile(Image *image, const
         {
           if (*sp == '\0')
             {
-              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                    "ran out of profile data");
               MagickFreeMemory(info);
-              return (False);
+              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                  "ran out of profile data");
+              return (MagickFail);
             }
           sp++;
         }
@@ -1449,13 +1216,16 @@ png_read_raw_profile(Image *image, const
   else if (!memcmp(&text[ii].key[17], "icm\0",4))
     {
       strlcpy(profile_name,"ICM",sizeof(profile_name));
-      strlcpy(profile_description,"ICM (ICCP) profile.",sizeof(profile_description));
+      strlcpy(profile_description,"ICM (ICCP) profile.",
+              sizeof(profile_description));
     }
   else
     {
       strlcpy(profile_name,&text[ii].key[17],sizeof(profile_name));
-      strlcpy(profile_description,"generic profile, type ",sizeof(profile_description));
-      strlcat(profile_description,&text[ii].key[17],sizeof(profile_description));
+      strlcpy(profile_description,"generic profile, type ",
+              sizeof(profile_description));
+      strlcat(profile_description,&text[ii].key[17],
+              sizeof(profile_description));
     }
   if (image_info->verbose)
     (void) printf(" Found a %.1024s\n",profile_description);
@@ -1463,13 +1233,144 @@ png_read_raw_profile(Image *image, const
     {
       MagickFreeMemory(info);
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                            "unable to copy profile");
-      return (False);
+           "unable to copy profile");
+      return MagickFail;
     }
   MagickFreeMemory(info);
-  return True;
+  return MagickTrue;
 }
 
+#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+
+static int read_user_chunk_callback(png_struct *ping, png_unknown_chunkp chunk)
+{
+  Image
+    *image;
+
+
+  /* The unknown chunk structure contains the chunk data:
+     png_byte name[5];
+     png_byte *data;
+     png_size_t size;
+
+     Note that libpng has already taken care of the CRC handling.
+
+     Returns one of the following:
+         return(-n);  chunk had an error
+         return(0);  did not recognize
+         return(n);  success
+  */
+
+  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+     "    read_user_chunk: found %c%c%c%c chunk",
+       chunk->name[0],chunk->name[1],chunk->name[2],chunk->name[3]);
+
+  if (chunk->name[0]  == 101 &&
+      (chunk->name[1] ==  88 || chunk->name[1] == 120 ) &&
+      chunk->name[2]  ==  73 &&
+      chunk->name[3]  == 102)
+    {
+      /* process eXIf or exIf chunk */
+
+      unsigned char
+        *profile;
+
+      unsigned char
+        *p;
+
+      png_byte
+        *s;
+
+      size_t
+        i;
+
+(void) LogMagickEvent(CoderEvent,GetMagickModule(),
+        " recognized eXIf chunk");
+
+      image=(Image *) png_get_user_chunk_ptr(ping);
+
+#if PNG_LIBPNG_VER >= 14000
+      profile=(unsigned char *) png_malloc(ping,
+        (png_alloc_size_t) chunk->size+6);
+#else
+      profile=(unsigned char *) png_malloc(ping,
+         (png_size_t) chunk->size+6);
+#endif
+      p=profile;
+
+      if (*p != 'E' || *(p+1) != 'x' || *(p+2) != 'i' ||
+          *(p+3) != 'f' || *(p+4) != '\0' || *(p+5) != '\0')
+        {
+          /* Initialize profile with "Exif\0\0" if it
+             doesn't already begin with it by accident
+          */
+          *p++ ='E';
+          *p++ ='x';
+          *p++ ='i';
+          *p++ ='f';
+          *p++ ='\0';
+          *p++ ='\0';
+        }
+
+      /* copy chunk->data to profile */
+      s=chunk->data;
+      for (i=0; i<chunk->size; i++)
+        *p++ = *s++;
+
+      (void) SetImageProfile(image,"exif",
+         (const unsigned char *)profile, chunk->size+6);
+      return(1);
+    }
+
+  /* orNT */
+  if (chunk->name[0] == 111 &&
+      chunk->name[1] == 114 &&
+      chunk->name[2] ==  78 &&
+      chunk->name[3] ==  84)
+    {
+     /* recognized orNT */
+     if (chunk->size != 1)
+       return(-1); /* Error return */
+
+     image=(Image *) png_get_user_chunk_ptr(ping);
+     if (chunk->data[0] < 9)
+       image->orientation = chunk->data[0];
+     else
+       image->orientation = 0;
+     return(1);
+    }
+
+  /* caNv */
+  if (chunk->name[0] ==  99 &&
+      chunk->name[1] ==  97 &&
+      chunk->name[2] ==  78 &&
+      chunk->name[3] == 118)
+    {
+     /* recognized caNv */
+
+     if (chunk->size != 16)
+       return(-1); /* Error return */
+
+     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+             " recognized caNv chunk");
+
+     image=(Image *) png_get_user_chunk_ptr(ping);
+
+     image->page.width=(size_t) mng_get_long(chunk->data);
+     image->page.height=(size_t) mng_get_long(&chunk->data[4]);
+     image->page.x=(size_t) mng_get_long(&chunk->data[8]);
+     image->page.y=(size_t) mng_get_long(&chunk->data[12]);
+
+     return(1);
+    }
+
+  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+         " unrecognized user chunk");
+
+  return(0); /* Did not recognize */
+}
+#endif /* PNG_UNKNOWN_CHUNKS_SUPPORTED */
+
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %                                                                             %
@@ -1505,7 +1406,8 @@ png_read_raw_profile(Image *image, const
 %
 */
 static Image *ReadOnePNGImage(MngInfo *mng_info,
-                              const ImageInfo *image_info, ExceptionInfo *exception)
+                              const ImageInfo *image_info,
+                              ExceptionInfo *exception)
 {
   /* Read one PNG image */
 
@@ -1516,11 +1418,25 @@ static Image *ReadOnePNGImage(MngInfo *m
     logging,
     num_text,
     num_passes,
-    pass;
+    pass,
+    ping_bit_depth,
+    ping_colortype,
+    ping_file_depth,
+    ping_interlace_method,
+    ping_compression_method,
+    ping_filter_method,
+    ping_num_trans;
 
-  PixelPacket
+  LongPixelPacket
     transparent_color;
 
+  png_bytep
+     ping_trans_alpha;
+
+  png_color_16p
+     ping_background,
+     ping_trans_color;
+
   png_info
     *end_info,
     *ping_info;
@@ -1528,18 +1444,17 @@ static Image *ReadOnePNGImage(MngInfo *m
   png_struct
     *ping;
 
+  png_uint_32
+    ping_rowbytes,
+    ping_width,
+    ping_height;
+
   png_textp
     text;
 
-  unsigned char
-    *png_pixels;
-
   long
     y;
 
-  register unsigned char
-    *p;
-
   register IndexPacket
     *indexes;
 
@@ -1563,22 +1478,29 @@ static Image *ReadOnePNGImage(MngInfo *m
       115,  67,  65,  76, '\0',   /* sCAL */
       115,  80,  76,  84, '\0',   /* sPLT */
       116,  73,  77,  69, '\0',   /* tIME */
+#ifdef PNG_APNG_SUPPORTED /* libpng was built with APNG patch; */
+                          /* ignore the APNG chunks */
+       97,  99,  84,  76, '\0',   /* acTL */
+      102,  99,  84,  76, '\0',   /* fcTL */
+      102, 100,  65,  84, '\0',   /* fdAT */
+#endif
     };
 #endif
 
   logging=LogMagickEvent(CoderEvent,GetMagickModule(),
                          "  enter ReadOnePNGImage()");
 
-  transparent_color.red=0;
-  transparent_color.green=0;
-  transparent_color.blue=0;
-  transparent_color.opacity=0;
+  /* Set to an out-of-range color unless tRNS chunk is present */
+  transparent_color.red=65537;
+  transparent_color.green=65537;
+  transparent_color.blue=65537;
+  transparent_color.opacity=65537;
 
 #if defined(PNG_SETJMP_NOT_THREAD_SAFE)
   AcquireSemaphoreInfo(&png_semaphore);
 #endif
 
-#if (PNG_LIBPNG_VER < 10007)
+#if (PNG_LIBPNG_VER < 10012)
   if (image_info->verbose)
     printf("Your PNG library (libpng-%s) is rather old.\n",
            PNG_LIBPNG_VER_STRING);
@@ -1592,37 +1514,36 @@ static Image *ReadOnePNGImage(MngInfo *m
 #ifdef PNG_USER_MEM_SUPPORTED
   ping=png_create_read_struct_2(PNG_LIBPNG_VER_STRING, image,
                                 PNGErrorHandler,PNGWarningHandler, NULL,
-                                (png_malloc_ptr) png_IM_malloc,(png_free_ptr) png_IM_free);
+                                (png_malloc_ptr) png_IM_malloc,
+                                (png_free_ptr) png_IM_free);
 #else
   ping=png_create_read_struct(PNG_LIBPNG_VER_STRING,image,
                               PNGErrorHandler,PNGWarningHandler);
 #endif
   if (ping == (png_struct *) NULL)
-    ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
-  ping_info=png_create_info_struct(ping);
-  if (ping_info == (png_info *) NULL)
     {
-      png_destroy_read_struct(&ping,(png_info **) NULL,(png_info **) NULL);
-      ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
-    }
-  end_info=png_create_info_struct(ping);
-  if (end_info == (png_info *) NULL)
-    {
-      png_destroy_read_struct(&ping,&ping_info,(png_info **) NULL);
+#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
+      LiberateSemaphoreInfo(&png_semaphore);
+#endif
       ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
     }
-  png_pixels=(unsigned char *) NULL;
-  if (setjmp(ping->jmpbuf))
+
+  png_set_crc_action(ping, PNG_CRC_QUIET_USE, PNG_CRC_QUIET_USE);
+
+  mng_info->png_pixels=(unsigned char *) NULL;
+  mng_info->quantum_scanline=(Quantum *) NULL;
+
+  if (setjmp(png_jmpbuf(ping)))
     {
       /*
         PNG image is corrupt.
       */
       png_destroy_read_struct(&ping,&ping_info,&end_info);
+      MagickFreeMemory(mng_info->quantum_scanline);
+      MagickFreeMemory(mng_info->png_pixels);
 #if defined(PNG_SETJMP_NOT_THREAD_SAFE)
       LiberateSemaphoreInfo(&png_semaphore);
 #endif
-      if (png_pixels != (unsigned char *) NULL)
-        MagickFreeMemory(png_pixels);
       if (logging)
         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                               "  exit ReadOnePNGImage() with error.");
@@ -1634,6 +1555,45 @@ static Image *ReadOnePNGImage(MngInfo *m
         }
       return(image);
     }
+
+/* { From here through end of ReadOnePNGImage(), use png_error(), not Throw() */
+
+  ping_info=png_create_info_struct(ping);
+  if (ping_info == (png_info *) NULL)
+    {
+      png_destroy_read_struct(&ping,(png_info **) NULL,(png_info **) NULL);
+      png_error(ping,"Could not allocate PNG info struct");
+    }
+
+  end_info=png_create_info_struct(ping);
+  if (end_info == (png_info *) NULL)
+    {
+      png_destroy_read_struct(&ping,&ping_info,(png_info **) NULL);
+      png_error(ping,"Could not allocate PNG end_info struct");
+    }
+
+#ifdef PNG_BENIGN_ERRORS_SUPPORTED
+  /* Allow benign errors */
+  png_set_benign_errors(ping, 1);
+#endif
+
+  /* Just use libpng's limit (PNG_USER_CHUNK_MALLOC_MAX == 8000000) on
+     chunk size */
+#ifdef PNG_SET_USER_LIMITS_SUPPORTED
+  /* Reject images with too many rows or columns */
+  png_set_user_limits(ping,
+    (png_uint_32) 0x7fffffffL,
+    (png_uint_32) 0x7fffffffL);
+#endif /* PNG_SET_USER_LIMITS_SUPPORTED */
+
+  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                            "    PNG width limit: %lu, height limit: %lu",
+    (unsigned long) 0x7fffffffL,
+    (unsigned long) 0x7fffffffL);
+  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                            "    PNG pixels limit: %lu",
+    (unsigned long) GetMagickResourceLimit(PixelsResource));
+
   /*
     Prepare PNG for reading.
   */
@@ -1645,16 +1605,16 @@ static Image *ReadOnePNGImage(MngInfo *m
       (void) png_permit_mng_features(ping,PNG_ALL_MNG_FEATURES);
       png_set_read_fn(ping,image,png_get_data);
 #else
-#if defined(PNG_READ_EMPTY_PLTE_SUPPORTED)
-      png_permit_empty_plte(ping,True);
+# if defined(PNG_READ_EMPTY_PLTE_SUPPORTED)
+      png_permit_empty_plte(ping,MagickTrue);
       png_set_read_fn(ping,image,png_get_data);
-#else
+# else
       mng_info->image=image;
       mng_info->bytes_in_read_buffer=0;
-      mng_info->found_empty_plte=False;
-      mng_info->have_saved_bkgd_index=False;
+      mng_info->found_empty_plte=MagickFalse;
+      mng_info->have_saved_bkgd_index=MagickFalse;
       png_set_read_fn(ping,mng_info,mng_get_data);
-#endif
+# endif
 #endif
     }
   else
@@ -1662,10 +1622,22 @@ static Image *ReadOnePNGImage(MngInfo *m
 
 #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
   /* Ignore unknown chunks */
+# if PNG_LIBPNG_VER < 10700 /* Avoid a libpng16 warning */
+  png_set_keep_unknown_chunks(ping, 2, NULL, 0);
+# else
   png_set_keep_unknown_chunks(ping, 1, NULL, 0);
-  /* Ignore unused chunks */
+# endif
+  /* Ignore unused chunks and all unknown chunks except for caNv */
+  png_set_keep_unknown_chunks(ping, 2, (png_bytep) mng_caNv, 1);
   png_set_keep_unknown_chunks(ping, 1, unused_chunks,
                               (int)sizeof(unused_chunks)/5);
+  /* Callback for other unknown chunks */
+  png_set_read_user_chunk_fn(ping, image, read_user_chunk_callback);
+#endif
+
+#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
+    /* Disable new libpng-1.5.10 feature while reading */
+    png_set_check_for_invalid_index (ping, 0);
 #endif
 
 #if defined(PNG_USE_PNGGCCRD) && defined(PNG_ASSEMBLER_CODE_SUPPORTED)  \
@@ -1687,47 +1659,105 @@ static Image *ReadOnePNGImage(MngInfo *m
 
   png_read_info(ping,ping_info);
 
+  (void) png_get_IHDR(ping,ping_info,
+                      &ping_width,
+                      &ping_height,
+                      &ping_bit_depth,
+                      &ping_colortype,
+                      &ping_interlace_method,
+                      &ping_compression_method,
+
+                      &ping_filter_method);
+
 #if (QuantumDepth == 8)
-  image->depth=8;
-#else
-  if (ping_info->bit_depth > 8)
+  if (ping_bit_depth > 8)
+  {
+#  if defined(PNG_READ_STRIP_16_TO_8_SUPPORTED) || \
+      defined(PNG_READ_16_TO_8_SUPPORTED)
+    png_set_strip_16(ping);
+#  else
+#    ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
+    png_set_scale_16(ping);
+#    endif
+#  endif
+    ping_bit_depth=8;
+    image->depth=8;
+  }
+#else /* QuantumDepth > 8 */
+  if (ping_bit_depth > 8)
     image->depth=16;
   else
     image->depth=8;
 #endif
 
-  if (ping_info->bit_depth < 8)
-    {
-      if ((ping_info->color_type == PNG_COLOR_TYPE_PALETTE))
-        {
-          png_set_packing(ping);
-          image->depth=8;
-        }
-    }
+  ping_file_depth = ping_bit_depth;
+
+  /* Save bit-depth and color-type in case we later want to write a PNG00 */
+  {
+      char
+        msg[MaxTextExtent];
+
+      (void) FormatString(msg,"%d",(int) ping_colortype);
+      (void) SetImageAttribute(image,"png:IHDR.color-type-orig",msg);
+
+      (void) FormatString(msg,"%d",(int) ping_bit_depth);
+      (void) SetImageAttribute(image,"png:IHDR.bit-depth-orig",msg);
+  }
+
+  (void) png_get_tRNS(ping, ping_info, &ping_trans_alpha, &ping_num_trans,
+                      &ping_trans_color);
+
+  (void) png_get_bKGD(ping, ping_info, &ping_background);
+
   if (logging)
     {
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                             "    PNG width: %lu, height: %lu",
-                            ping_info->width, ping_info->height);
+                            (unsigned long)ping_width,
+                            (unsigned long)ping_height);
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                             "    PNG color_type: %d, bit_depth: %d",
-                            ping_info->color_type, ping_info->bit_depth);
+                            ping_colortype, ping_bit_depth);
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                             "    PNG compression_method: %d",
-                            ping_info->compression_type);
+                            ping_compression_method);
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                             "    PNG interlace_method: %d, filter_method: %d",
-                            ping_info->interlace_type,ping_info->filter_type);
+                            ping_interlace_method,
+                            ping_filter_method);
     }
 
-#if (PNG_LIBPNG_VER > 10008) && defined(PNG_READ_iCCP_SUPPORTED)
-  if (ping_info->valid & PNG_INFO_iCCP)
+  /* Too big? */
+  if (ping_width >
+    (magick_uint64_t) GetMagickResourceLimit(PixelsResource)/ping_height)
+  {
+    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+      "Number of pixels exceeds resource limit");
+    png_error(ping, "Number of pixels exceeds resource limit");
+  }
+
+  if (ping_bit_depth < 8)
+    {
+       png_set_packing(ping);
+       ping_bit_depth=8;
+       image->depth=8;
+    }
+
+#if defined(PNG_READ_iCCP_SUPPORTED)
+    if (png_get_valid(ping, ping_info, PNG_INFO_iCCP))
     {
       int
         compression;
 
+#if (PNG_LIBPNG_VER < 10500)
+      png_charp
+        info;
+#else
+      png_bytep
+        info;
+#endif
+
       png_charp
-        info,
         name;
 
       png_uint_32
@@ -1749,21 +1779,27 @@ static Image *ReadOnePNGImage(MngInfo *m
             }
         }
     }
-#endif /* #if (PNG_LIBPNG_VER > 10008) && defined(PNG_READ_iCCP_SUPPORTED) */
+#endif /* #if defined(PNG_READ_iCCP_SUPPORTED) */
 #if defined(PNG_READ_sRGB_SUPPORTED)
   {
     int
       intent;
 
-    if (mng_info->have_global_srgb)
-      image->rendering_intent=(RenderingIntent)
-        (mng_info->global_srgb_intent+1);
+    if (!png_get_sRGB(ping,ping_info,&intent))
+      {
+        if (mng_info->have_global_srgb)
+          {
+            png_set_sRGB(ping,ping_info,(mng_info->global_srgb_intent+1));
+          }
+      }
     if (png_get_sRGB(ping,ping_info,&intent))
       {
         image->rendering_intent=(RenderingIntent) (intent+1);
         if (logging)
           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                "    Reading PNG sRGB chunk: rendering_intent: %d",intent+1);
+                                "    Reading PNG sRGB chunk:"
+                                " rendering_intent: %d",
+                                intent+1);
       }
   }
 #endif
@@ -1771,19 +1807,34 @@ static Image *ReadOnePNGImage(MngInfo *m
     double
       file_gamma;
 
-    if (mng_info->have_global_gama)
-      image->gamma=mng_info->global_gamma;
+    if (!png_get_gAMA(ping,ping_info,&file_gamma))
+      {
+        if (mng_info->have_global_gama)
+          png_set_gAMA(ping,ping_info,mng_info->global_gamma);
+      }
     if (png_get_gAMA(ping,ping_info,&file_gamma))
       {
         image->gamma=(float) file_gamma;
         if (logging)
           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                "    Reading PNG gAMA chunk: gamma: %f",file_gamma);
+                                "    Reading PNG gAMA chunk: gamma: %f",
+                                file_gamma);
       }
   }
-  if (mng_info->have_global_chrm)
-    image->chromaticity=mng_info->global_chrm;
-  if (ping_info->valid & PNG_INFO_cHRM)
+  if (!png_get_valid(ping, ping_info, PNG_INFO_cHRM))
+    {
+      if (mng_info->have_global_chrm)
+        (void) png_set_cHRM(ping,ping_info,
+                     mng_info->global_chrm.white_point.x,
+                     mng_info->global_chrm.white_point.y,
+                     mng_info->global_chrm.red_primary.x,
+                     mng_info->global_chrm.red_primary.y,
+                     mng_info->global_chrm.green_primary.x,
+                     mng_info->global_chrm.green_primary.y,
+                     mng_info->global_chrm.blue_primary.x,
+                     mng_info->global_chrm.blue_primary.y);
+    }
+  if (png_get_valid(ping, ping_info, PNG_INFO_cHRM))
     {
       (void) png_get_cHRM(ping,ping_info,
                           &image->chromaticity.white_point.x,
@@ -1810,24 +1861,32 @@ static Image *ReadOnePNGImage(MngInfo *m
       image->chromaticity.white_point.x=0.3127f;
       image->chromaticity.white_point.y=0.3290f;
     }
-  if (mng_info->have_global_gama || image->rendering_intent)
-    ping_info->valid|=PNG_INFO_gAMA;
-  if (mng_info->have_global_chrm || image->rendering_intent)
-    ping_info->valid|=PNG_INFO_cHRM;
 #if defined(PNG_oFFs_SUPPORTED)
-  if (mng_info->mng_type == 0 && (ping_info->valid & PNG_INFO_oFFs))
+  if (mng_info->mng_type == 0 && (png_get_valid(ping, ping_info,
+                                                PNG_INFO_oFFs)))
     {
       image->page.x=png_get_x_offset_pixels(ping, ping_info);
       image->page.y=png_get_y_offset_pixels(ping, ping_info);
       if (logging)
         if (image->page.x || image->page.y)
           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                "    Reading PNG oFFs chunk: x: %ld, y: %ld.",image->page.x,
+                                "    Reading PNG oFFs chunk: x: %ld, y: %ld.",
+                                image->page.x,
                                 image->page.y);
     }
 #endif
 #if defined(PNG_pHYs_SUPPORTED)
-  if (ping_info->valid & PNG_INFO_pHYs)
+  if (!png_get_valid(ping, ping_info, PNG_INFO_pHYs))
+    {
+      if (mng_info->have_global_phys)
+        {
+          png_set_pHYs(ping,ping_info,
+                       mng_info->global_x_pixels_per_unit,
+                       mng_info->global_y_pixels_per_unit,
+                       mng_info->global_phys_unit_type);
+        }
+    }
+  if (png_get_valid(ping, ping_info, PNG_INFO_pHYs))
     {
       int
         unit_type;
@@ -1851,28 +1910,14 @@ static Image *ReadOnePNGImage(MngInfo *m
         }
       if (logging)
         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                              "    Reading PNG pHYs chunk: xres: %lu, yres: %lu, units: %d.",
-                              x_resolution, y_resolution, unit_type);
-    }
-  else
-    {
-      if (mng_info->have_global_phys)
-        {
-          image->x_resolution=(float) mng_info->global_x_pixels_per_unit;
-          image->y_resolution=(float) mng_info->global_y_pixels_per_unit;
-          if (mng_info->global_phys_unit_type == PNG_RESOLUTION_METER)
-            {
-              image->units=PixelsPerCentimeterResolution;
-              image->x_resolution=(double)
-                mng_info->global_x_pixels_per_unit/100.0;
-              image->y_resolution=(double)
-                mng_info->global_y_pixels_per_unit/100.0;
-            }
-          ping_info->valid|=PNG_INFO_pHYs;
-        }
+                              "    Reading PNG pHYs chunk:"
+                              " xres: %lu, yres: %lu, units: %d.",
+                              (unsigned long)x_resolution,
+                              (unsigned long)y_resolution,
+                              unit_type);
     }
 #endif
-  if (ping_info->valid & PNG_INFO_PLTE)
+  if (png_get_valid(ping, ping_info, PNG_INFO_PLTE))
     {
       int
         number_colors;
@@ -1881,21 +1926,20 @@ static Image *ReadOnePNGImage(MngInfo *m
         palette;
 
       (void) png_get_PLTE(ping,ping_info,&palette,&number_colors);
-      if (number_colors == 0 && ping_info->color_type ==
+      if (number_colors == 0 && ping_colortype ==
           PNG_COLOR_TYPE_PALETTE)
         {
           if (mng_info->global_plte_length)
             {
               png_set_PLTE(ping,ping_info,mng_info->global_plte,
                            (int) mng_info->global_plte_length);
-              if (!(ping_info->valid & PNG_INFO_tRNS))
+              if (!(png_get_valid(ping, ping_info, PNG_INFO_tRNS)))
                 if (mng_info->global_trns_length)
                   {
                     if (mng_info->global_trns_length >
                         mng_info->global_plte_length)
-                      (void) ThrowException2(&image->exception,CoderError,
-                                             "global tRNS has more entries than global PLTE",
-                                             image_info->filename);
+                       png_error(ping, "global tRNS has more entries"
+                                             " than global PLTE");
                     png_set_tRNS(ping,ping_info,mng_info->global_trns,
                                  (int) mng_info->global_trns_length,NULL);
                   }
@@ -1904,7 +1948,7 @@ static Image *ReadOnePNGImage(MngInfo *m
 #ifndef PNG_READ_EMPTY_PLTE_SUPPORTED
                   mng_info->have_saved_bkgd_index ||
 #endif
-                  ping_info->valid & PNG_INFO_bKGD)
+                  png_get_valid(ping, ping_info, PNG_INFO_bKGD))
                 {
                   png_color_16
                     background;
@@ -1912,9 +1956,9 @@ static Image *ReadOnePNGImage(MngInfo *m
 #ifndef PNG_READ_EMPTY_PLTE_SUPPORTED
                   if (mng_info->have_saved_bkgd_index)
                     background.index=mng_info->saved_bkgd_index;
-                  else
 #endif
-                    background.index=ping_info->background.index;
+                  if (png_get_valid(ping, ping_info, PNG_INFO_bKGD))
+                    background.index=ping_background->index;
                   background.red=(png_uint_16)
                     mng_info->global_plte[background.index].red;
                   background.green=(png_uint_16)
@@ -1926,40 +1970,81 @@ static Image *ReadOnePNGImage(MngInfo *m
 #endif
             }
           else
-            (void) ThrowException2(&image->exception,CoderError,
-                                   "No global PLTE in file",image_info->filename);
+            png_error (ping, "No global PLTE in file");
         }
     }
 
 #if defined(PNG_READ_bKGD_SUPPORTED)
-  if (mng_info->have_global_bkgd && !(ping_info->valid & PNG_INFO_bKGD))
+  if (mng_info->have_global_bkgd &&
+              !(png_get_valid(ping,ping_info, PNG_INFO_bKGD)))
     image->background_color=mng_info->mng_global_bkgd;
-  if (ping_info->valid & PNG_INFO_bKGD)
+  if (png_get_valid(ping, ping_info, PNG_INFO_bKGD))
     {
       /*
         Set image background color.
       */
+
       if (logging)
         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                               "    Reading PNG bKGD chunk.");
-      if (ping_info->bit_depth <= QuantumDepth)
+
+      if (ping_bit_depth == QuantumDepth)
         {
-          image->background_color.red=ping_info->background.red;
-          image->background_color.green=ping_info->background.green;
-          image->background_color.blue=ping_info->background.blue;
+          image->background_color.red  = ping_background->red;
+          image->background_color.green= ping_background->green;
+          image->background_color.blue = ping_background->blue;
         }
-      else
+      else /* Scale background components to 16-bit */
         {
+          unsigned int
+            bkgd_scale;
+
+          if (logging != MagickFalse)
+            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+              "    raw ping_background=(%d,%d,%d).",ping_background->red,
+              ping_background->green,ping_background->blue);
+
+          bkgd_scale = 1;
+          if (ping_file_depth == 1)
+             bkgd_scale = 255;
+          else if (ping_file_depth == 2)
+             bkgd_scale = 85;
+          else if (ping_file_depth == 4)
+             bkgd_scale = 17;
+          if (ping_file_depth <= 8)
+             bkgd_scale *= 257;
+
+          ping_background->red *= bkgd_scale;
+          ping_background->green *= bkgd_scale;
+          ping_background->blue *= bkgd_scale;
+
+          if (logging != MagickFalse)
+            {
+            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+              "    bkgd_scale=%d.",bkgd_scale);
+            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+              "    ping_background=(%d,%d,%d).",ping_background->red,
+              ping_background->green,ping_background->blue);
+            }
+
           image->background_color.red=
-            ScaleShortToQuantum(ping_info->background.red);
+            ScaleShortToQuantum(ping_background->red);
           image->background_color.green=
-            ScaleShortToQuantum(ping_info->background.green);
+            ScaleShortToQuantum(ping_background->green);
           image->background_color.blue=
-            ScaleShortToQuantum(ping_info->background.blue);
+            ScaleShortToQuantum(ping_background->blue);
+          image->background_color.opacity=OpaqueOpacity;
+
+          if (logging != MagickFalse)
+            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+              "    image->background_color=(%d,%d,%d).",
+              image->background_color.red,
+              image->background_color.green,image->background_color.blue);
         }
     }
 #endif
-  if (ping_info->valid & PNG_INFO_tRNS)
+
+  if (png_get_valid(ping, ping_info, PNG_INFO_tRNS))
     {
       int
         bit_mask;
@@ -1968,49 +2053,71 @@ static Image *ReadOnePNGImage(MngInfo *m
         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
           "    Reading PNG tRNS chunk.");
 
-      bit_mask = (1 << ping_info->bit_depth) - 1;
+      bit_mask = (1U << ping_file_depth) - 1;
 
       /*
         Image has a transparent background.
       */
+
       transparent_color.red=
-        (Quantum)(ping_info->trans_values.red & bit_mask);
+        (unsigned long)(ping_trans_color->red & bit_mask);
       transparent_color.green=
-        (Quantum) (ping_info->trans_values.green & bit_mask);
+        (unsigned long) (ping_trans_color->green & bit_mask);
       transparent_color.blue=
-        (Quantum) (ping_info->trans_values.blue & bit_mask);
+        (unsigned long) (ping_trans_color->blue & bit_mask);
       transparent_color.opacity=
-        (Quantum) (ping_info->trans_values.gray & bit_mask);
-      if (ping_info->color_type == PNG_COLOR_TYPE_GRAY)
+        (unsigned long) (ping_trans_color->gray & bit_mask);
+
+      if (ping_colortype == PNG_COLOR_TYPE_GRAY)
         {
+#if (QuantumDepth == 8)
+          if (ping_file_depth < QuantumDepth)
+#endif
+            transparent_color.opacity=(unsigned long) (
+                ping_trans_color->gray *
+                (65535L/((1UL << ping_file_depth)-1)));
+
+#if (QuantumDepth == 8)
+          else
+            transparent_color.opacity=(unsigned long) (
+                (ping_trans_color->gray * 65535L)/
+                ((1UL << ping_file_depth)-1));
+#endif
+          if (logging != MagickFalse)
+            {
+              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                   "    Raw tRNS graylevel is %d.",ping_trans_color->gray);
+              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                   "    scaled graylevel is %d.",
+                   (int) transparent_color.opacity);
+            }
           transparent_color.red=transparent_color.opacity;
           transparent_color.green=transparent_color.opacity;
           transparent_color.blue=transparent_color.opacity;
         }
     }
 #if defined(PNG_READ_sBIT_SUPPORTED)
-  if (mng_info->have_global_sbit)
-    {
-      int
-        not_valid;
-      not_valid=!ping_info->valid;
-      if (not_valid & PNG_INFO_sBIT)
+  if (!png_get_valid(ping, ping_info, PNG_INFO_sBIT))
+    if (mng_info->have_global_sbit)
         png_set_sBIT(ping,ping_info,&mng_info->global_sbit);
-    }
 #endif
   num_passes=png_set_interlace_handling(ping);
+
   png_read_update_info(ping,ping_info);
+
+  ping_rowbytes=(png_uint_32) png_get_rowbytes(ping,ping_info);
+
   /*
     Initialize image structure.
   */
   mng_info->image_box.left=0;
-  mng_info->image_box.right=(long) ping_info->width;
+  mng_info->image_box.right=(long) ping_width;
   mng_info->image_box.top=0;
-  mng_info->image_box.bottom=(long) ping_info->height;
+  mng_info->image_box.bottom=(long) ping_height;
   if (mng_info->mng_type == 0)
     {
-      mng_info->mng_width=ping_info->width;
-      mng_info->mng_height=ping_info->height;
+      mng_info->mng_width=ping_width;
+      mng_info->mng_height=ping_height;
       mng_info->frame=mng_info->image_box;
       mng_info->clip=mng_info->image_box;
     }
@@ -2019,14 +2126,14 @@ static Image *ReadOnePNGImage(MngInfo *m
       image->page.y=mng_info->y_off[mng_info->object_id];
     }
   image->compression=ZipCompression;
-  image->columns=ping_info->width;
-  image->rows=ping_info->height;
-  if ((ping_info->color_type == PNG_COLOR_TYPE_PALETTE) ||
-      (ping_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) ||
-      (ping_info->color_type == PNG_COLOR_TYPE_GRAY))
+  image->columns=ping_width;
+  image->rows=ping_height;
+  if ((ping_colortype == PNG_COLOR_TYPE_PALETTE) ||
+      (ping_colortype == PNG_COLOR_TYPE_GRAY_ALPHA) ||
+      (ping_colortype == PNG_COLOR_TYPE_GRAY))
     {
       image->storage_class=PseudoClass;
-      image->colors=1 << ping_info->bit_depth;
+      image->colors=1U << ping_file_depth;
 #if (QuantumDepth == 8)
       if (image->colors > 256)
         image->colors=256;
@@ -2034,7 +2141,7 @@ static Image *ReadOnePNGImage(MngInfo *m
       if (image->colors > 65536L)
         image->colors=65536L;
 #endif
-      if (ping_info->color_type == PNG_COLOR_TYPE_PALETTE)
+      if (ping_colortype == PNG_COLOR_TYPE_PALETTE)
         {
           int
             number_colors;
@@ -2046,7 +2153,8 @@ static Image *ReadOnePNGImage(MngInfo *m
           image->colors=number_colors;
           if (logging)
             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                  "    Reading PNG PLTE chunk: number_colors: %d.",number_colors);
+                                  "    Reading PNG PLTE chunk:"
+                                  " number_colors: %d.",number_colors);
         }
     }
 
@@ -2056,8 +2164,8 @@ static Image *ReadOnePNGImage(MngInfo *m
         Initialize image colormap.
       */
       if (!AllocateImageColormap(image,image->colors))
-        ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
-      if (ping_info->color_type == PNG_COLOR_TYPE_PALETTE)
+        png_error(ping, "Could not allocate image colormap");
+      if (ping_colortype == PNG_COLOR_TYPE_PALETTE)
         {
           int
             number_colors;
@@ -2078,7 +2186,7 @@ static Image *ReadOnePNGImage(MngInfo *m
           unsigned long
             scale;
 
-          scale=(MaxRGB/((1 << ping_info->bit_depth)-1));
+          scale=(MaxRGB/((1U << ping_file_depth)-1));
           if (scale < 1)
             scale=1;
           for (i=0; i < (long) image->colors; i++)
@@ -2089,41 +2197,58 @@ static Image *ReadOnePNGImage(MngInfo *m
             }
         }
     }
-  /*
-    Read image scanlines.
-  */
   if (image->delay != 0)
     mng_info->scenes_found++;
-  if (image_info->ping && (image_info->number_scenes != 0) &&
+  if (image_info->ping && ((mng_info->mng_type == 0) ||
+     ((image_info->number_scenes != 0) &&
       mng_info->scenes_found > (long) (image_info->first_scene+
-                                       image_info->number_scenes))
+                                       image_info->number_scenes))))
     {
+      /* This happens later in non-ping decodes */
+      if (png_get_valid(ping,ping_info,PNG_INFO_tRNS))
+        image->storage_class=DirectClass;
+
       if (logging)
         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                               "    Skipping PNG image data for scene %ld",
                               mng_info->scenes_found-1);
       png_destroy_read_struct(&ping,&ping_info,&end_info);
+      MagickFreeMemory(mng_info->quantum_scanline);
+      MagickFreeMemory(mng_info->png_pixels);
 #if defined(PNG_SETJMP_NOT_THREAD_SAFE)
       LiberateSemaphoreInfo(&png_semaphore);
 #endif
-      if (image != (Image *) NULL)
-        image->columns=0;
       if (logging)
         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                               "  exit ReadOnePNGImage().");
       return (image);
     }
+
+  /*
+    Read image scanlines.
+  */
   if (logging)
     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                           "    Reading PNG IDAT chunk(s)");
   if (num_passes > 1)
-    png_pixels=MagickAllocateMemory(unsigned char *,
-                                    ping_info->rowbytes*image->rows);
+  {
+    if (ping_rowbytes < GetMagickResourceLimit(MemoryResource)/image->rows)
+      mng_info->png_pixels=MagickAllocateMemory(unsigned char *,
+               ping_rowbytes*image->rows);
+    else
+      png_error(ping, "png_pixels array exceeds MemoryResource");
+  }
   else
-    png_pixels=MagickAllocateMemory(unsigned char *,
-                                    ping_info->rowbytes);
-  if (png_pixels == (unsigned char *) NULL)
-    ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
+  {
+    if ((magick_int64_t)ping_rowbytes < GetMagickResourceLimit(MemoryResource))
+      mng_info->png_pixels=MagickAllocateMemory(unsigned char *, ping_rowbytes);
+    else
+      png_error(ping, "png_rowbytes array exceeds MemoryResource");
+  }
+  if (mng_info->png_pixels == (unsigned char *) NULL)
+  {
+    png_error(ping, "Could not allocate png_pixels array");
+  }
 
   if (logging)
     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
@@ -2141,22 +2266,28 @@ static Image *ReadOnePNGImage(MngInfo *m
         int
           depth;
 
-        depth=(long) ping_info->bit_depth;
+        depth=(long) ping_bit_depth;
 #endif
-        image->matte=((ping_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) ||
-                      (ping_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) ||
-                      (ping_info->valid & PNG_INFO_tRNS));
+        image->matte=((ping_colortype == PNG_COLOR_TYPE_RGB_ALPHA) ||
+                      (ping_colortype == PNG_COLOR_TYPE_GRAY_ALPHA) ||
+                      (png_get_valid(ping, ping_info, PNG_INFO_tRNS)));
 
         for (y=0; y < (long) image->rows; y++)
           {
             if (num_passes > 1)
-              row_offset=ping_info->rowbytes*y;
+              row_offset=ping_rowbytes*y;
+
             else
               row_offset=0;
-            png_read_row(ping,png_pixels+row_offset,NULL);
-            /* FIXME: Use SetImagePixels? */
-            if (!GetImagePixels(image,0,y,image->columns,1))
+
+            png_read_row(ping,mng_info->png_pixels+row_offset,NULL);
+
+            if (!SetImagePixels(image,0,y,image->columns,1))
               break;
+
+            if (pass < num_passes-1)
+              continue;
+
 #if (QuantumDepth == 8)
             if (depth == 16)
               {
@@ -2164,16 +2295,18 @@ static Image *ReadOnePNGImage(MngInfo *m
                   *p,
                   *r;
 
-                r=png_pixels+row_offset;
+                r=mng_info->png_pixels+row_offset;
                 p=r;
-                if (ping_info->color_type == PNG_COLOR_TYPE_GRAY)
+                if (ping_colortype == PNG_COLOR_TYPE_GRAY)
                   {
                     for (x=(long) image->columns; x > 0; x--)
                       {
                         *r++=*p++;
                         p++;
-                        if ((ping_info->valid & PNG_INFO_tRNS) &&
-                            (((*(p-2) << 8)|*(p-1)) == transparent_color.opacity))
+                        if ((png_get_valid(ping, ping_info, PNG_INFO_tRNS)) &&
+                            ((unsigned long) (((magick_uint32_t) *(p-2) << 8)|
+                                              (magick_uint32_t) *(p-1))
+                            == transparent_color.opacity))
                           {
                             /* Cheap transparency */
                             *r++=TransparentOpacity;
@@ -2182,9 +2315,9 @@ static Image *ReadOnePNGImage(MngInfo *m
                           *r++=OpaqueOpacity;
                       }
                   }
-                else if (ping_info->color_type == PNG_COLOR_TYPE_RGB)
+                else if (ping_colortype == PNG_COLOR_TYPE_RGB)
                   {
-                    if (ping_info->valid & PNG_INFO_tRNS)
+                    if (png_get_valid(ping, ping_info, PNG_INFO_tRNS))
                       for (x=(long) image->columns; x > 0; x--)
                         {
                           *r++=*p++;
@@ -2193,9 +2326,12 @@ static Image *ReadOnePNGImage(MngInfo *m
                           p++;
                           *r++=*p++;
                           p++;
-                          if ((((*(p-6) << 8)|*(p-5)) == transparent_color.red) &&
-                              (((*(p-4) << 8)|*(p-3)) == transparent_color.green) &&
-                              (((*(p-2) << 8)|*(p-1)) == transparent_color.blue))
+                          if (((unsigned long) (((magick_uint32_t) *(p-6) << 8)|*(p-5)) ==
+                              transparent_color.red) &&
+                              ((unsigned long) (((magick_uint32_t) *(p-4) << 8)|*(p-3)) ==
+                              transparent_color.green) &&
+                              ((unsigned long) (((magick_uint32_t) *(p-2) << 8)|*(p-1)) ==
+                              transparent_color.blue))
                             {
                               /* Cheap transparency */
                               *r++=TransparentOpacity;
@@ -2215,231 +2351,239 @@ static Image *ReadOnePNGImage(MngInfo *m
                           *r++=OpaqueOpacity;
                         }
                   }
-                else if (ping_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+                else if (ping_colortype == PNG_COLOR_TYPE_RGB_ALPHA)
                   for (x=(long) (4*image->columns); x > 0; x--)
                     {
                       *r++=*p++;
                       p++;
                     }
-                else if (ping_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+                else if (ping_colortype == PNG_COLOR_TYPE_GRAY_ALPHA)
                   for (x=(long) (2*image->columns); x > 0; x--)
                     {
                       *r++=*p++;
                       p++;
                     }
               }
-            if (depth == 8 && ping_info->color_type == PNG_COLOR_TYPE_GRAY)
+            if (depth == 8 && ping_colortype == PNG_COLOR_TYPE_GRAY)
               (void) ImportImagePixelArea(image,(QuantumType) GrayQuantum,
-                                          image->depth,png_pixels+row_offset,0,0);
-            if (ping_info->color_type == PNG_COLOR_TYPE_GRAY ||
-                ping_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+                                          image->depth,mng_info->png_pixels+
+                                          row_offset,0,0);
+            else if (ping_colortype == PNG_COLOR_TYPE_GRAY)
               {
                 image->depth=8;
-                (void) ImportImagePixelArea(image,(QuantumType) GrayAlphaQuantum,
-                                            image->depth,png_pixels+row_offset,0,0);
+                (void) ImportImagePixelArea(image,
+                                           (QuantumType) GrayQuantum,
+                                            image->depth,mng_info->png_pixels+
+                                            row_offset,0,0);
                 image->depth=depth;
               }
-            else if (depth == 8 && ping_info->color_type == PNG_COLOR_TYPE_RGB)
+            else if (ping_colortype == PNG_COLOR_TYPE_GRAY_ALPHA)
+              {
+                image->depth=8;
+                (void) ImportImagePixelArea(image,
+                                           (QuantumType) GrayAlphaQuantum,
+                                            image->depth,mng_info->png_pixels+
+                                            row_offset,0,0);
+                image->depth=depth;
+              }
+            else if (depth == 8 && ping_colortype == PNG_COLOR_TYPE_RGB)
               (void) ImportImagePixelArea(image,(QuantumType) RGBQuantum,
-                                          image->depth,png_pixels+row_offset,0,0);
-            else if (ping_info->color_type == PNG_COLOR_TYPE_RGB ||
-                     ping_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+                                          image->depth,mng_info->png_pixels+
+                                          row_offset,0,0);
+            else if (ping_colortype == PNG_COLOR_TYPE_RGB)
+              {
+                image->depth=8;
+                (void) ImportImagePixelArea(image,(QuantumType) RGBQuantum,
+                                            image->depth,mng_info->png_pixels+
+                                            row_offset,0,0);
+                image->depth=depth;
+              }
+            else if (ping_colortype == PNG_COLOR_TYPE_RGB_ALPHA)
               {
                 image->depth=8;
                 (void) ImportImagePixelArea(image,(QuantumType) RGBAQuantum,
-                                            image->depth,png_pixels+row_offset,0,0);
+                                            image->depth,mng_info->png_pixels+
+                                            row_offset,0,0);
                 image->depth=depth;
               }
-            else if (ping_info->color_type == PNG_COLOR_TYPE_PALETTE)
+            else if (ping_colortype == PNG_COLOR_TYPE_PALETTE)
               (void) ImportImagePixelArea(image,(QuantumType) IndexQuantum,
-                                          ping_info->bit_depth,png_pixels+row_offset,0,0); /* FIXME, sample size ??? */
+                                          ping_bit_depth,mng_info->png_pixels+
+                                          row_offset,0,0);
+                                          /* FIXME, sample size ??? */
 #else /* (QuantumDepth != 8) */
 
-            if (ping_info->color_type == PNG_COLOR_TYPE_GRAY)
+            if (ping_colortype == PNG_COLOR_TYPE_GRAY)
               (void) ImportImagePixelArea(image,(QuantumType) GrayQuantum,
-                                          image->depth,png_pixels+row_offset,0,0);
-            else if (ping_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+                                          image->depth,mng_info->png_pixels+
+                                          row_offset,0,0);
+            else if (ping_colortype == PNG_COLOR_TYPE_GRAY_ALPHA)
               (void) ImportImagePixelArea(image,(QuantumType) GrayAlphaQuantum,
-                                          image->depth,png_pixels+row_offset,0,0);
-            else if (ping_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+                                          image->depth,mng_info->png_pixels+
+                                          row_offset,0,0);
+            else if (ping_colortype == PNG_COLOR_TYPE_RGB_ALPHA)
               (void) ImportImagePixelArea(image,(QuantumType) RGBAQuantum,
-                                          image->depth,png_pixels+row_offset,0,0);
-            else if (ping_info->color_type == PNG_COLOR_TYPE_PALETTE)
+                                          image->depth,mng_info->png_pixels+
+                                          row_offset,0,0);
+            else if (ping_colortype == PNG_COLOR_TYPE_PALETTE)
               (void) ImportImagePixelArea(image,(QuantumType) IndexQuantum,
-                                          ping_info->bit_depth,png_pixels+row_offset,0,0); /* FIXME, sample size ??? */
+                                          ping_bit_depth,mng_info->png_pixels+
+                                          row_offset,0,0);
+                                          /* FIXME, sample size ??? */
             else
               (void) ImportImagePixelArea(image,(QuantumType) RGBQuantum,
-                                          image->depth,png_pixels+row_offset,0,0);
+                                          image->depth,mng_info->png_pixels+
+                                          row_offset,0,0);
 #endif
             if (!SyncImagePixels(image))
               break;
           }
+
         if (image->previous == (Image *) NULL)
           if (!MagickMonitor(LoadImageTag,pass,num_passes,exception))
             break;
       }
+
   else /* image->storage_class != DirectClass */
-    for (pass=0; pass < num_passes; pass++)
-      {
-        Quantum
-          *quantum_scanline;
+    {
+      image->matte=ping_colortype == PNG_COLOR_TYPE_GRAY_ALPHA;
+      mng_info->quantum_scanline=
+        MagickAllocateMemory(Quantum *,
+                             (image->matte ?  2 : 1) *
+                             image->columns*sizeof(Quantum));
+      if (mng_info->quantum_scanline == (Quantum *) NULL)
+        png_error(ping, "Could not allocate quantum_scanline");
+      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                            "      Allocated quantum_scanline");
 
-        register Quantum
-          *r;
+      for (pass=0; pass < num_passes; pass++)
+        {
+          register Quantum
+            *r;
 
-        /*
-          Convert grayscale image to PseudoClass pixel packets.
-        */
-        image->matte=ping_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA;
-        quantum_scanline=MagickAllocateMemory(Quantum *,(image->matte ?  2 : 1) *
-                                              image->columns*sizeof(Quantum));
-        if (quantum_scanline == (Quantum *) NULL)
-          ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
-        for (y=0; y < (long) image->rows; y++)
-          {
-            if (num_passes > 1)
-              row_offset=ping_info->rowbytes*y;
-            else
-              row_offset=0;
-            png_read_row(ping,png_pixels+row_offset,NULL);
-            q=SetImagePixels(image,0,y,image->columns,1);
-            if (q == (PixelPacket *) NULL)
-              break;
-            indexes=GetIndexes(image);
-            p=png_pixels+row_offset;
-            r=quantum_scanline;
-            switch (ping_info->bit_depth)
-              {
-              case 1:
-                {
-                  register long
-                    bit;
+          /*
+            Convert grayscale image to PseudoClass pixel packets.
+          */
+          for (y=0; y < (long) image->rows; y++)
+            {
+              register unsigned char
+                *p;
 
-                  for (x=(long) image->columns-7; x > 0; x-=8)
-                    {
-                      for (bit=7; bit >= 0; bit--)
-                        *r++=((*p) & (0x01 << bit) ? 0x01 : 0x00);
-                      p++;
-                    }
-                  if ((image->columns % 8) != 0)
-                    {
-                      for (bit=7; bit >= (long) (8-(image->columns % 8)); bit--)
-                        *r++=((*p) & (0x01 << bit) ? 0x01 : 0x00);
-                    }
-                  break;
-                }
-              case 2:
-                {
-                  for (x=(long) image->columns-3; x > 0; x-=4)
-                    {
-                      *r++=(*p >> 6) & 0x03;
-                      *r++=(*p >> 4) & 0x03;
-                      *r++=(*p >> 2) & 0x03;
-                      *r++=(*p++) & 0x03;
-                    }
-                  if ((image->columns % 4) != 0)
-                    {
-                      for (i=3; i >= (long) (4-(image->columns % 4)); i--)
-                        *r++=(*p >> (i*2)) & 0x03;
-                    }
-                  break;
-                }
-              case 4:
-                {
-                  for (x=(long) image->columns-1; x > 0; x-=2)
-                    {
-                      *r++=(*p >> 4) & 0x0f;
-                      *r++=(*p++) & 0x0f;
-                    }
-                  if ((image->columns % 2) != 0)
-                    *r++=(*p++ >> 4) & 0x0f;
-                  break;
-                }
-              case 8:
-                {
-                  if (ping_info->color_type == 4)
-                    for (x=(long) image->columns; x > 0; x--)
-                      {
-                        *r++=*p++;
-                        /* In image.h, OpaqueOpacity is 0
-                         * TransparentOpacity is MaxRGB
-                         * In a PNG datastream, Opaque is MaxRGB
-                         * and Transparent is 0.
-                         */
-                        q->opacity=ScaleCharToQuantum(255-(*p++));
-                        q++;
-                      }
-                  else
-                    for (x=(long) image->columns; x > 0; x--)
-                      *r++=*p++;
-                  break;
-                }
-              case 16:
+              if (num_passes > 1)
+                row_offset=ping_rowbytes*y;
+
+              else
+                row_offset=0;
+
+              png_read_row(ping,mng_info->png_pixels+row_offset,NULL);
+              q=SetImagePixels(image,0,y,image->columns,1);
+              if (q == (PixelPacket *) NULL)
+                break;
+
+              if (pass < num_passes-1)
+                continue;
+
+              indexes=GetIndexes(image);
+              p=mng_info->png_pixels+row_offset;
+              r=mng_info->quantum_scanline;
+              switch (ping_bit_depth)
                 {
-                  for (x=(long) image->columns; x > 0; x--)
-                    {
-#if (QuantumDepth == 16)
-                      if (image->colors > 256)
-                        *r=((*p++) << 8);
-                      else
-                        *r=0;
-                      *r|=(*p++);
-                      r++;
-                      if (ping_info->color_type == 4)
+                case 8:
+                  {
+                    if (ping_colortype == 4)
+                      for (x=(long) image->columns; x > 0; x--)
                         {
-                          q->opacity=((*p++) << 8);
-                          q->opacity|=(*p++);
-                          q->opacity=(Quantum) (MaxRGB-q->opacity);
+                          *r++=*p++;
+                          /* In image.h, OpaqueOpacity is 0
+                           * TransparentOpacity is MaxRGB
+                           * In a PNG datastream, Opaque is MaxRGB
+                           * and Transparent is 0.
+                           */
+                          q->opacity=ScaleCharToQuantum(255-(*p++));
                           q++;
                         }
+                    else
+                      for (x=(long) image->columns; x > 0; x--)
+                        *r++=*p++;
+                    break;
+                  }
+                case 16:
+                  {
+                    for (x=(long) image->columns; x > 0; x--)
+                      {
+#if (QuantumDepth == 16)
+                        if (image->colors > 256)
+                          *r=(((magick_uint32_t) *p++) << 8);
+                        else
+                          *r=0;
+                        *r|=(*p++);
+                        r++;
+                        if (ping_colortype == 4)
+                          {
+                            q->opacity=(((magick_uint32_t) *p++) << 8);
+                            q->opacity|=((magick_uint32_t) *p++);
+                            q->opacity=(Quantum) (MaxRGB-q->opacity);
+                            q++;
+                          }
 #else
 #if (QuantumDepth == 32)
-                      if (image->colors > 256)
-                        *r=((*p++) << 8);
-                      else
-                        *r=0;
-                      *r|=(*p++);
-                      r++;
-                      if (ping_info->color_type == 4)
-                        {
-                          q->opacity=((*p++) << 8);
-                          q->opacity|=(*p++);
-                          q->opacity*=65537L;
-                          q->opacity=(Quantum) (MaxRGB-q->opacity);
-                          q++;
-                        }
+                        if (image->colors > 256)
+                          *r=(((magick_uint32_t) *p++) << 8);
+                        else
+                          *r=0;
+                        *r|=(*p++);
+                        r++;
+                        if (ping_colortype == 4)
+                          {
+                            q->opacity=(((magick_uint32_t) *p++) << 8);
+                            q->opacity|=((magick_uint32_t) *p++);
+                            q->opacity*=65537U;
+                            q->opacity=(Quantum) (MaxRGB-q->opacity);
+                            q++;
+                          }
 #else /* QuantumDepth == 8 */
-                      *r++=(*p++);
-                      p++; /* strip low byte */
-                      if (ping_info->color_type == 4)
-                        {
-                          q->opacity=(Quantum) (MaxRGB-(*p++));
-                          p++;
-                          q++;
-                        }
+                        *r++=(*p++);
+                        p++; /* strip low byte */
+                        if (ping_colortype == 4)
+                          {
+                            q->opacity=(Quantum) (MaxRGB-(*p++));
+                            p++;
+                            q++;
+                          }
 #endif
 #endif
-                    }
+                      }
+                    break;
+                  }
+                default:
                   break;
                 }
-              default:
+              /*
+                Transfer image scanline.
+              */
+              r=mng_info->quantum_scanline;
+
+              for (x=0; x < (long) image->columns; x++)
+                indexes[x]=(*r++);
+
+              if (!SyncImagePixels(image))
                 break;
-              }
-            /*
-              Transfer image scanline.
-            */
-            r=quantum_scanline;
-            for (x=0; x < (long) image->columns; x++)
-              indexes[x]=(*r++);
-            if (!SyncImagePixels(image))
-              break;
-          }
-        if (image->previous == (Image *) NULL)
-          if (!MagickMonitor(LoadImageTag,pass,num_passes,exception))
+            }
+
+          /* Quit 'passes' loop if we encountered an error */
+          if (y < (long) image->rows)
             break;
-        MagickFreeMemory(quantum_scanline);
+
+          if (image->previous == (Image *) NULL)
+            if (!MagickMonitor(LoadImageTag,pass,num_passes,exception))
+              break;
       }
 
+      MagickFreeMemory(mng_info->quantum_scanline);
+      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                            "      Free'ed quantum_scanline after last pass");
+    }
+
   if (image->storage_class == PseudoClass)
     (void) SyncImage(image);
   png_read_end(ping,ping_info);
@@ -2448,18 +2592,19 @@ static Image *ReadOnePNGImage(MngInfo *m
       (long) image_info->first_scene && image->delay != 0.)
     {
       png_destroy_read_struct(&ping,&ping_info,&end_info);
-      MagickFreeMemory(png_pixels);
+      MagickFreeMemory(mng_info->quantum_scanline);
+      MagickFreeMemory(mng_info->png_pixels);
       image->colors=2;
       (void) SetImage(image,TransparentOpacity);
 #if defined(PNG_SETJMP_NOT_THREAD_SAFE)
-      LiberateSemaphoreInfo(&png_semaphore);
+       LiberateSemaphoreInfo(&png_semaphore);
 #endif
       if (logging)
         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                               "  exit ReadOnePNGImage().");
       return (image);
     }
-  if (ping_info->valid & PNG_INFO_tRNS)
+  if (png_get_valid(ping, ping_info, PNG_INFO_tRNS))
     {
       ClassType
         storage_class;
@@ -2468,49 +2613,57 @@ static Image *ReadOnePNGImage(MngInfo *m
         Image has a transparent background.
       */
       storage_class=image->storage_class;
-      image->matte=True;
+      image->matte=MagickTrue;
       for (y=0; y < (long) image->rows; y++)
         {
-          image->storage_class=storage_class;
           q=SetImagePixels(image,0,y,image->columns,1);
           if (q == (PixelPacket *) NULL)
             break;
           indexes=GetIndexes(image);
 
-          q->opacity=OpaqueOpacity;
           if (storage_class == PseudoClass)
             {
               IndexPacket
                 index;
 
-              if (ping_info->color_type == PNG_COLOR_TYPE_PALETTE)
+              if (ping_colortype == PNG_COLOR_TYPE_PALETTE)
                 for (x=0; x < (long) image->columns; x++)
                   {
                     index=indexes[x];
-                    if (index < ping_info->num_trans)
+                    if (index < (unsigned int) ping_num_trans)
                       q->opacity=
-                        ScaleCharToQuantum(255-ping_info->trans[index]);
+                        ScaleCharToQuantum(255-ping_trans_alpha[index]);
+                    else
+                      q->opacity=OpaqueOpacity;
                     q++;
                   }
-              else if (ping_info->color_type == PNG_COLOR_TYPE_GRAY)
+              else if (ping_colortype == PNG_COLOR_TYPE_GRAY)
                 for (x=0; x < (long) image->columns; x++)
                   {
                     index=indexes[x];
                     q->red=image->colormap[index].red;
                     q->green=image->colormap[index].green;
                     q->blue=image->colormap[index].blue;
-                    if (q->red == transparent_color.opacity)
+                    if ((unsigned long) ScaleQuantumToShort(q->red) ==
+                        transparent_color.opacity)
                       q->opacity=TransparentOpacity;
+                    else
+                      q->opacity=OpaqueOpacity;
                     q++;
                   }
             }
           else
             for (x=(long) image->columns; x > 0; x--)
               {
-                if (q->red == transparent_color.red &&
-                    q->green == transparent_color.green &&
-                    q->blue == transparent_color.blue)
+                if ((unsigned long) ScaleQuantumToShort(q->red) ==
+                    transparent_color.red &&
+                    (unsigned long) ScaleQuantumToShort(q->green) ==
+                    transparent_color.green &&
+                    (unsigned long) ScaleQuantumToShort(q->blue) ==
+                    transparent_color.blue)
                   q->opacity=TransparentOpacity;
+                else
+                  q->opacity=OpaqueOpacity;
                 q++;
               }
           if (!SyncImagePixels(image))
@@ -2530,19 +2683,23 @@ static Image *ReadOnePNGImage(MngInfo *m
         if (logging)
           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                                 "    Reading PNG text chunk");
-        if (!memcmp(text[i].key, "Raw profile type ",17))
-          (void) png_read_raw_profile(image,image_info,text,(int) i);
+        if (strlen(text[i].key) > 16 &&
+            !memcmp(text[i].key, "Raw profile type ",17))
+          {
+            if (png_read_raw_profile(image,image_info,text,(int) i) ==
+              MagickFail)
+            break;
+          }
         else
           {
             char
               *value;
 
-            length=text[i].text_length;
+            length=(unsigned long) text[i].text_length;
             value=MagickAllocateMemory(char *,length+1);
             if (value == (char *) NULL)
               {
-                (void) ThrowException3(&image->exception,ResourceLimitError,
-                                       MemoryAllocationFailed,UnableToReadTextChunk);
+                png_warning(ping, "Could not allocate memory for text chunk");
                 break;
               }
             *value='\0';
@@ -2577,11 +2734,9 @@ static Image *ReadOnePNGImage(MngInfo *m
           mng_info->ob[object_id]->frozen)
         {
           if (mng_info->ob[object_id] == (MngBuffer *) NULL)
-            (void) ThrowException(&image->exception,ResourceLimitError,
-                                  MemoryAllocationFailed,image->filename);
+            png_error(ping, "Could not allocate MNG object");
           if (mng_info->ob[object_id]->frozen)
-            (void) ThrowException(&image->exception,ResourceLimitError,
-                                  "Cannot overwrite frozen MNG object buffer",image->filename);
+            png_error(ping, "Could not overwrite MNG frozen object buffer");
         }
       else
         {
@@ -2597,14 +2752,16 @@ static Image *ReadOnePNGImage(MngInfo *m
             filter_method;
 
           if (mng_info->ob[object_id]->image != (Image *) NULL)
-            DestroyImage(mng_info->ob[object_id]->image);
-          mng_info->ob[object_id]->image=CloneImage(image,0,0,True,
+            {
+              DestroyImage(mng_info->ob[object_id]->image);
+              mng_info->ob[object_id]->image=(Image *) NULL;
+            }
+          mng_info->ob[object_id]->image=CloneImage(image,0,0,MagickTrue,
                                                     &image->exception);
           if (mng_info->ob[object_id]->image != (Image *) NULL)
             mng_info->ob[object_id]->image->file=(FILE *) NULL;
           else
-            (void) ThrowException(&image->exception,ResourceLimitError,
-                                  "Cloning image for object buffer failed",image->filename);
+            png_error(ping, "Cloning image for object buffer failed");
           png_get_IHDR(ping,ping_info,&width,&height,&bit_depth,&color_type,
                        &interlace_method,&compression_method,&filter_method);
           if (width > 250000L || height > 250000L)
@@ -2616,7 +2773,7 @@ static Image *ReadOnePNGImage(MngInfo *m
           mng_info->ob[object_id]->interlace_method=interlace_method;
           mng_info->ob[object_id]->compression_method=compression_method;
           mng_info->ob[object_id]->filter_method=filter_method;
-          if (ping_info->valid & PNG_INFO_PLTE)
+          if (png_get_valid(ping, ping_info, PNG_INFO_PLTE))
             {
               int
                 number_colors;
@@ -2643,8 +2800,9 @@ static Image *ReadOnePNGImage(MngInfo *m
     Free memory.
   */
   png_destroy_read_struct(&ping,&ping_info,&end_info);
+  MagickFreeMemory(mng_info->quantum_scanline);
+  MagickFreeMemory(mng_info->png_pixels);
 
-  MagickFreeMemory(png_pixels);
 #if defined(PNG_SETJMP_NOT_THREAD_SAFE)
   LiberateSemaphoreInfo(&png_semaphore);
 #endif
@@ -2654,6 +2812,8 @@ static Image *ReadOnePNGImage(MngInfo *m
                           "  exit ReadOnePNGImage()");
   return (image);
 
+  /* End of setjmp-controlled block } */
+
   /* end of reading one PNG image */
 }
 
@@ -2661,8 +2821,7 @@ static Image *ReadPNGImage(const ImageIn
                            ExceptionInfo *exception)
 {
   Image
-    *image,
-    *previous;
+    *image;
 
   MngInfo
     *mng_info;
@@ -2688,27 +2847,41 @@ static Image *ReadPNGImage(const ImageIn
   image=AllocateImage(image_info);
   mng_info=(MngInfo *) NULL;
   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
-  if (status == False)
+  if (status == MagickFalse)
     ThrowReaderException(FileOpenError,UnableToOpenFile,image);
   /*
     Verify PNG signature.
   */
   (void) ReadBlob(image,8,magic_number);
   if (memcmp(magic_number,"\211PNG\r\n\032\n",8) != 0)
+  {
     ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
+  }
+
+  /*
+     Verify that file size large enough to contain a PNG datastream
+     if using a seekable blob
+  */
+  if (BlobIsSeekable(image) && GetBlobSize(image) < 61)
+  {
+    ThrowReaderException(CorruptImageError,InsufficientImageDataInFile,image);
+  }
+
   /*
     Allocate a MngInfo structure.
   */
-  have_mng_structure=False;
+  have_mng_structure=MagickFalse;
   mng_info=MagickAllocateMemory(MngInfo *,sizeof(MngInfo));
   if (mng_info == (MngInfo *) NULL)
+  {
     ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
+  }
   /*
     Initialize members of the MngInfo structure.
   */
   (void) memset(mng_info,0,sizeof(MngInfo));
   mng_info->image=image;
-  have_mng_structure=True;
+  have_mng_structure=MagickTrue;
 
   image=ReadOnePNGImage(mng_info,image_info,exception);
   MngInfoFreeStruct(mng_info,&have_mng_structure);
@@ -2725,6 +2898,7 @@ static Image *ReadPNGImage(const ImageIn
       if (image->exception.severity > exception->severity)
         CopyException(exception,&image->exception);
       DestroyImageList(image);
+      image=(Image *) NULL;
       if (logging)
         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                               "exit ReadPNGImage() with error.");
@@ -2741,7 +2915,7 @@ static Image *ReadPNGImage(const ImageIn
   if (LocaleCompare(image_info->magick,"PNG24") == 0)
     {
       (void) SetImageType(image,TrueColorType);
-      image->matte=False;
+      image->matte=MagickFalse;
     }
   if (LocaleCompare(image_info->magick,"PNG32") == 0)
     (void) SetImageType(image,TrueColorMatteType);
@@ -2753,20 +2927,33 @@ static Image *ReadPNGImage(const ImageIn
 
 
 #if defined(JNG_SUPPORTED)
-void
-DestroyJNG(unsigned char *chunk,Image *color_image,ImageInfo *color_image_info,
-   Image *alpha_image,ImageInfo *alpha_image_info)
-{
-  if (chunk)
-    MagickFreeMemory(chunk);
-  if (color_image_info)
-    DestroyImageInfo(color_image_info);
-  if (alpha_image_info)
-    DestroyImageInfo(alpha_image_info);
-  if (color_image)
-    DestroyImage(color_image);
-  if (alpha_image)
-    DestroyImage(alpha_image);
+
+static void
+DestroyJNG(unsigned char *chunk,Image **color_image,
+   ImageInfo **color_image_info,
+   Image **alpha_image,ImageInfo **alpha_image_info)
+{
+  MagickFreeMemory(chunk);
+  if (*color_image_info)
+  {
+    DestroyImageInfo(*color_image_info);
+    *color_image_info = (ImageInfo *)NULL;
+  }
+  if (*alpha_image_info)
+  {
+    DestroyImageInfo(*alpha_image_info);
+    *alpha_image_info = (ImageInfo *)NULL;
+  }
+  if (*color_image)
+  {
+    DestroyImage(*color_image);
+    *color_image = (Image *)NULL;
+  }
+  if (*alpha_image)
+  {
+    DestroyImage(*alpha_image);
+    *alpha_image = (Image *)NULL;
+  }
 }
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -2821,13 +3008,10 @@ static Image *ReadOneJNGImage(MngInfo *m
   long
     y;
 
-  png_uint_32
+  unsigned long
     jng_height,
     jng_width;
 
-  magick_int64_t
-    pixels_resource;
-
   png_byte
     jng_color_type,
     jng_image_sample_depth,
@@ -2842,7 +3026,6 @@ static Image *ReadOneJNGImage(MngInfo *m
     *s;
 
   register long
-    i,
     x;
 
   register PixelPacket
@@ -2855,7 +3038,6 @@ static Image *ReadOneJNGImage(MngInfo *m
     logging,
     read_JSEP,
     reading_idat,
-    skip_to_iend,
     status;
 
   size_t
@@ -2894,11 +3076,8 @@ static Image *ReadOneJNGImage(MngInfo *m
     Signature bytes have already been read.
   */
 
-  read_JSEP=False;
-  reading_idat=False;
-  skip_to_iend=False;
-
-  pixels_resource = GetMagickResourceLimit(PixelsResource);
+  read_JSEP=MagickFalse;
+  reading_idat=MagickFalse;
 
   for (;;)
     {
@@ -2915,62 +3094,73 @@ static Image *ReadOneJNGImage(MngInfo *m
         Read a new JNG chunk.
       */
 
-      if (!MagickMonitor(LoadImagesTag,TellBlob(image),2*GetBlobSize(image),
-                         exception))
-        break;
+      if (!MagickMonitor(LoadImagesTag,TellBlob(image),2*GetBlobSize(image),exception))
+          break;
 
       type[0]='\0';
       (void) strcat(type,"errr");
-      length=(size_t)ReadBlobMSBLong(image);
-      count=ReadBlob(image,4,type);
+      length=(size_t) ReadBlobMSBLong(image);
+      count=(unsigned int) ReadBlob(image,4,type);
 
       if (logging)
-        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                              "  Reading JNG chunk type %c%c%c%c, length: %lu",
-                              type[0],type[1],type[2],type[3],length);
+        {
+          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                " Reading JNG chunk type %c%c%c%c, "
+                                "length: %lu",
+                                type[0],type[1],type[2],type[3],
+                                length);
+
+          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                "   count=%u",count);
+        }
 
       if (length > PNG_MAX_UINT || count == 0)
-      {
-        DestroyJNG(NULL,color_image,color_image_info,
-                   alpha_image,alpha_image_info);
-        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                              "chunk length (%lu) > PNG_MAX_UINT",length);
-        return ((Image*)NULL);
-      }
+        {
+          DestroyJNG(NULL,&color_image,&color_image_info,
+            &alpha_image,&alpha_image_info);
+          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+              "chunk length (%lu) > PNG_MAX_UINT",
+                                length);
+          ThrowException(exception,CorruptImageError,
+                         ImproperImageHeader,image->filename);
+          return ((Image*)NULL);
+        }
+
       chunk=(unsigned char *) NULL;
       p=NULL;
       if (length)
         {
           chunk=MagickAllocateMemory(unsigned char *,length);
           if (chunk == (unsigned char *) NULL)
-          {
-            DestroyJNG(chunk,color_image,color_image_info,
-                       alpha_image,alpha_image_info);
-            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                  "    Could not allocate chunk memory");
-            return ((Image*)NULL);
-          }
-          for (i=0; i < (long) length; i++)
-            chunk[i]=ReadBlobByte(image);
+            {
+              DestroyJNG(chunk,&color_image,&color_image_info,
+                &alpha_image,&alpha_image_info);
+              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                  "    Could not allocate chunk memory");
+              ThrowException(exception,ResourceLimitError,
+                             MemoryAllocationFailed,image->filename);
+              return ((Image*)NULL);
+            }
+          if (ReadBlob(image,length,chunk) < length)
+            {
+              DestroyJNG(chunk,&color_image,&color_image_info,
+                &alpha_image,&alpha_image_info);
+              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                  "    chunk reading was incomplete");
+              ThrowException(exception,CorruptImageError,
+                             InsufficientImageDataInFile,image->filename);
+              return ((Image*)NULL);
+            }
           p=chunk;
         }
       (void) ReadBlobMSBLong(image);  /* read crc word */
 
-      if (skip_to_iend)
-        {
-          if (length)
-            MagickFreeMemory(chunk);
-          continue;
-        }
-
       if (!memcmp(type,mng_JHDR,4))
         {
           if (length == 16)
             {
-              jng_width=(unsigned long) ((p[0] << 24) | (p[1] << 16) |
-                                         (p[2] << 8) | p[3]);
-              jng_height=(unsigned long) ((p[4] << 24) | (p[5] << 16) |
-                                          (p[6] << 8) | p[7]);
+              jng_width=(unsigned long) mng_get_long(p);
+              jng_height=(unsigned long) mng_get_long(&p[4]);
               jng_color_type=p[8];
               jng_image_sample_depth=p[9];
               jng_image_compression_method=p[10];
@@ -2982,39 +3172,51 @@ static Image *ReadOneJNGImage(MngInfo *m
               if (logging)
                 {
                   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                        "    jng_width:      %16lu",jng_width);
+                      "    jng_width:      %16lu",
+                      jng_width);
                   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                        "    jng_width:      %16lu",jng_height);
+                      "    jng_height:     %16lu",
+                      jng_height);
                   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                        "    jng_color_type: %16d",jng_color_type);
+                      "    jng_color_type: %16d",
+                      jng_color_type);
                   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                        "    jng_image_sample_depth:      %3d",
-                                        jng_image_sample_depth);
+                      "    jng_image_sample_depth:      %3d",
+                      jng_image_sample_depth);
                   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                        "    jng_image_compression_method:%3d",
-                                        jng_image_compression_method);
+                      "    jng_image_compression_method:%3d",
+                      jng_image_compression_method);
                   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                        "    jng_image_interlace_method:  %3d",
-                                        jng_image_interlace_method);
+                      "    jng_image_interlace_method:  %3d",
+                      jng_image_interlace_method);
                   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                        "    jng_alpha_sample_depth:      %3d",
-                                        jng_alpha_sample_depth);
+                      "    jng_alpha_sample_depth:      %3d",
+                      jng_alpha_sample_depth);
                   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                        "    jng_alpha_compression_method:%3d",
-                                        jng_alpha_compression_method);
+                      "    jng_alpha_compression_method:%3d",
+                      jng_alpha_compression_method);
                   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                        "    jng_alpha_filter_method:     %3d",
-                                        jng_alpha_filter_method);
+                      "    jng_alpha_filter_method:     %3d",
+                      jng_alpha_filter_method);
                   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                        "    jng_alpha_interlace_method:  %3d",
-                                        jng_alpha_interlace_method);
+                      "    jng_alpha_interlace_method:  %3d",
+                      jng_alpha_interlace_method);
                 }
             }
-          if (length)
-            MagickFreeMemory(chunk);
 
+          MagickFreeMemory(chunk);
 
-          SetMagickResourceLimit(PixelsResource,jng_width*jng_height);
+          if (jng_width > 65535 || jng_height > 65535)
+            {
+              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                 "    JNG width or height too large: (%lu x %lu)",
+                  jng_width, jng_height);
+              ThrowException(exception,CorruptImageError,
+                             ImproperImageHeader,image->filename);
+              DestroyJNG(chunk,&color_image,&color_image_info,
+                &alpha_image,&alpha_image_info);
+              return ((Image *)NULL);
+            }
 
           /* Rationalize dimensions with blob size if it is available */
           if (BlobIsSeekable(image))
@@ -3026,10 +3228,16 @@ static Image *ReadOneJNGImage(MngInfo *m
               if ((blob_size == 0) ||
                   ((((double) jng_width*jng_height)/blob_size) > 512.0))
                 {
+                  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                        "    Unreasonable dimensions: "
+                                        "geometry = %lux%lu, "
+                                        "blob size = %ld",
+                                        jng_width, jng_height, blob_size);
+
                   ThrowException(exception,CorruptImageError,
                                  InsufficientImageDataInFile,image->filename);
-                  DestroyJNG(chunk,color_image,color_image_info,
-                             alpha_image,alpha_image_info);
+                  DestroyJNG(chunk,&color_image,&color_image_info,
+                             &alpha_image,&alpha_image_info);
                   return ((Image *)NULL);
                 }
             }
@@ -3037,11 +3245,9 @@ static Image *ReadOneJNGImage(MngInfo *m
           continue;
         }
 
-
-      if (!reading_idat && !read_JSEP && (!memcmp(type,mng_JDAT,4) ||
-                                          !memcmp(type,mng_JdAA,4) ||
-                                          !memcmp(type,mng_IDAT,4) ||
-                                          !memcmp(type,mng_JDAA,4)))
+      if ((reading_idat == MagickFalse) && (read_JSEP == MagickFalse) &&
+         ((memcmp(type,mng_JDAT,4) == 0) || (memcmp(type,mng_JdAA,4) == 0) ||
+         (memcmp(type,mng_IDAT,4) == 0) || (memcmp(type,mng_JDAA,4) == 0)))
         {
           /*
             o create color_image
@@ -3052,58 +3258,66 @@ static Image *ReadOneJNGImage(MngInfo *m
 
           color_image_info=MagickAllocateMemory(ImageInfo *,sizeof(ImageInfo));
           if (color_image_info == (ImageInfo *) NULL)
-          {
-            DestroyJNG(chunk,color_image,color_image_info,
-                       alpha_image,alpha_image_info);
-            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                  "    could not allocate color_image_info");
-            return ((Image *)NULL);
-          }
+            {
+              DestroyJNG(chunk,&color_image,&color_image_info,
+                &alpha_image,&alpha_image_info);
+              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                  "    could not allocate color_image_info");
+              ThrowException(exception,ResourceLimitError,
+                             MemoryAllocationFailed,image->filename);
+              return ((Image *)NULL);
+            }
           GetImageInfo(color_image_info);
           color_image=AllocateImage(color_image_info);
           if (color_image == (Image *) NULL)
-          {
-            DestroyJNG(chunk,color_image,color_image_info,
-                       alpha_image,alpha_image_info);
-            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                  "    could not allocate color_image");
-            return ((Image *)NULL);
-          }
+            {
+              DestroyJNG(chunk,&color_image,&color_image_info,
+                &alpha_image,&alpha_image_info);
+              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                  "    could not allocate color_image");
+              ThrowException(exception,ResourceLimitError,
+                             MemoryAllocationFailed,image->filename);
+              return ((Image *)NULL);
+            }
           if (logging)
             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                                   "    Creating color_blob.");
           (void) AcquireUniqueFilename(color_image->filename);
           status=OpenBlob(color_image_info,color_image,WriteBinaryBlobMode,
                           exception);
-          if (status == False)
-          {
-            DestroyJNG(chunk,color_image,color_image_info,
-                       alpha_image,alpha_image_info);
-            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                  "    could not open alpha_image blob");
-            return ((Image *)NULL);
-          }
+          if (status == MagickFalse)
+            {
+              DestroyJNG(chunk,&color_image,&color_image_info,
+                &alpha_image,&alpha_image_info);
+              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                  "    could not open color_image blob");
+              return ((Image *)NULL);
+            }
 
           if (!image_info->ping && jng_color_type >= 12)
             {
               alpha_image_info=MagickAllocateMemory(ImageInfo *,
                                                     sizeof(ImageInfo));
               if (alpha_image_info == (ImageInfo *) NULL)
-              {
-                DestroyJNG(chunk,color_image,color_image_info,
-                           alpha_image,alpha_image_info);
-                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                      "    could not allocate alpha_image_alpha");
-                return ((Image *)NULL);
-              }
+                {
+                  DestroyJNG(chunk,&color_image,&color_image_info,
+                    &alpha_image,&alpha_image_info);
+                  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                      "    could not allocate alpha_image_info");
+                  ThrowException(exception,ResourceLimitError,
+                                 MemoryAllocationFailed,image->filename);
+                  return ((Image *)NULL);
+                }
               GetImageInfo(alpha_image_info);
               alpha_image=AllocateImage(alpha_image_info);
               if (alpha_image == (Image *) NULL)
                 {
-                  DestroyJNG(chunk,color_image,color_image_info,
-                             alpha_image,alpha_image_info);
+                  DestroyJNG(chunk,&color_image,&color_image_info,
+                    &alpha_image,&alpha_image_info);
                   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                        "    could not allocate alpha_image");
+                      "    could not allocate alpha_image");
+                  ThrowException(exception,ResourceLimitError,
+                                 MemoryAllocationFailed,image->filename);
                   return ((Image *)NULL);
                 }
               if (logging)
@@ -3112,13 +3326,14 @@ static Image *ReadOneJNGImage(MngInfo *m
               (void) AcquireUniqueFilename(alpha_image->filename);
               status=OpenBlob(alpha_image_info,alpha_image,WriteBinaryBlobMode,
                               exception);
-              if (status == False)
-              {
-                DestroyJNG(chunk,color_image,color_image_info,
-                           alpha_image,alpha_image_info);
-                DestroyImage(alpha_image);
-                return ((Image *)NULL);
-              }
+              if (status == MagickFalse)
+                {
+                  DestroyJNG(chunk,&color_image,&color_image_info,
+                    &alpha_image,&alpha_image_info);
+                  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                      "    could not open alpha_image blob");
+                  return ((Image *)NULL);
+                }
               if (jng_alpha_compression_method == 0)
                 {
                   unsigned char
@@ -3126,7 +3341,8 @@ static Image *ReadOneJNGImage(MngInfo *m
 
                   if (logging)
                     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                          "    Writing IHDR chunk to alpha_blob.");
+                                          "    Writing IHDR chunk"
+                                          " to alpha_blob.");
                   (void) WriteBlob(alpha_image,8,"\211PNG\r\n\032\n");
                   (void) WriteBlobMSBULong(alpha_image,13L);
                   PNGType(data,mng_IHDR);
@@ -3142,7 +3358,7 @@ static Image *ReadOneJNGImage(MngInfo *m
                   (void) WriteBlobMSBULong(alpha_image,crc32(0,data,17));
                 }
             }
-          reading_idat=True;
+          reading_idat=MagickTrue;
         }
 
       if (!memcmp(type,mng_JDAT,4))
@@ -3153,11 +3369,13 @@ static Image *ReadOneJNGImage(MngInfo *m
 
           if (logging)
             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                  "    Copying JDAT chunk data to color_blob.");
-
-          if (length) {
-            if (color_image != (Image *)NULL)
-              (void) WriteBlob(color_image,length,(char *) chunk);
+                                  "    Copying %l"
+                                  "u bytes of JDAT chunk data"
+                                  " to color_blob.",
+                                  length);
+          if (length && color_image != (Image *)NULL)
+          {
+            (void) WriteBlob(color_image,length,(char *) chunk);
             MagickFreeMemory(chunk);
           }
           continue;
@@ -3172,22 +3390,31 @@ static Image *ReadOneJNGImage(MngInfo *m
             Copy IDAT header and chunk data to alpha_image->blob
           */
 
-          if (!image_info->ping)
+          if (alpha_image != NULL && image_info->ping == MagickFalse)
             {
               if (logging)
+              {
                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                      "    Copying IDAT chunk data to alpha_blob.");
-
+                    "    Copying IDAT chunk data"
+                    " to alpha_blob.");
+              }
+              if (length == 0)
+              {
+                if (logging)
+                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                    "    IDAT chunk has length 0");
+                MagickFreeMemory(chunk);
+                continue;
+              }
               (void) WriteBlobMSBULong(alpha_image,(unsigned long) length);
               PNGType(data,mng_IDAT);
               LogPNGChunk(logging,mng_IDAT,length);
               (void) WriteBlob(alpha_image,4,(char *) data);
               (void) WriteBlob(alpha_image,length,(char *) chunk);
               (void) WriteBlobMSBULong(alpha_image,
-                                       crc32(crc32(0,data,4),chunk,length));
+                                       crc32(crc32(0,data,4),chunk,(uInt) length));
             }
-          if (length)
-            MagickFreeMemory(chunk);
+          MagickFreeMemory(chunk);
           continue;
         }
 
@@ -3197,24 +3424,23 @@ static Image *ReadOneJNGImage(MngInfo *m
             Copy chunk data to alpha_image->blob
           */
 
-          if (!image_info->ping)
+          if (alpha_image != NULL && image_info->ping == MagickFalse)
             {
               if (logging)
                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                      "    Copying JDAA chunk data to alpha_blob.");
+                                      "    Copying JDAA chunk data"
+                                      " to alpha_blob.");
 
               (void) WriteBlob(alpha_image,length,(char *) chunk);
             }
-          if (length)
-            MagickFreeMemory(chunk);
+          MagickFreeMemory(chunk);
           continue;
         }
 
       if (!memcmp(type,mng_JSEP,4))
         {
-          read_JSEP=True;
-          if (length)
-            MagickFreeMemory(chunk);
+          read_JSEP=MagickTrue;
+          MagickFreeMemory(chunk);
           continue;
         }
 
@@ -3292,8 +3518,7 @@ static Image *ReadOneJNGImage(MngInfo *m
                   image->page.y/=10000;
                 }
             }
-          if (length)
-            MagickFreeMemory(chunk);
+          MagickFreeMemory(chunk);
           continue;
         }
 
@@ -3318,14 +3543,12 @@ static Image *ReadOneJNGImage(MngInfo *m
       if (!memcmp(type,mng_iCCP,4))
         {
           /* To do. */
-          if (length)
-            MagickFreeMemory(chunk);
+          MagickFreeMemory(chunk);
           continue;
         }
 #endif
 
-      if (length)
-        MagickFreeMemory(chunk);
+      MagickFreeMemory(chunk);
 
       if (memcmp(type,mng_IEND,4))
         continue;
@@ -3356,176 +3579,193 @@ static Image *ReadOneJNGImage(MngInfo *m
     o destroy the secondary image.
   */
 
-  CloseBlob(color_image);
-  if (logging)
-    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                          "    Reading jng_image from color_blob.");
-
-  FormatString(color_image_info->filename,"%.1024s",color_image->filename);
-
-  color_image_info->ping=MagickFalse;   /* To do: avoid this */
-  jng_image=ReadImage(color_image_info,exception);
-  (void) LiberateUniqueFileResource(color_image->filename);
-  DestroyImage(color_image);
-  color_image = (Image *)NULL;
-  DestroyImageInfo(color_image_info);
-  color_image_info = (ImageInfo *)NULL;
-
-  if (jng_image == (Image *) NULL)
+  if (color_image_info == (ImageInfo *) NULL || color_image == (Image *) NULL)
     {
-      /*
-        Don't throw exception here since ReadImage() will already have thrown it.
-      */
-      DestroyImage(image);
+      DestroyImage(color_image);
+      color_image=(Image *) NULL;
       return (Image *) NULL;
     }
 
-  if (logging)
-    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                          "    Copying jng_image pixels to main image.");
-  image->rows=jng_height;
-  image->columns=jng_width;
-  length=MagickArraySize(image->columns,sizeof(PixelPacket));
-  if (jng_height == 0 || jng_width == 0)
+  else
     {
+      CloseBlob(color_image);
       if (logging)
-      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-          "    jng_width=%lu jng_height=%lu",
-          (unsigned long)jng_width,(unsigned long)jng_height);
-      DestroyJNG(NULL,&color_image,&color_image_info,
-        &alpha_image,&alpha_image_info);
-      DestroyImage(jng_image);
-      return ((Image *)NULL);     
-    }
+        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+            "    Reading jng_image from color_blob.");
+
+      FormatString(color_image_info->filename,"%.1024s",color_image->filename);
+
+      color_image_info->ping=MagickFalse;   /* To do: avoid this */
+      jng_image=ReadImage(color_image_info,exception);
+      (void) LiberateUniqueFileResource(color_image->filename);
+      DestroyImage(color_image);
+      color_image = (Image *)NULL;
+      DestroyImageInfo(color_image_info);
+      color_image_info = (ImageInfo *)NULL;
+
+      if (jng_image == (Image *) NULL)
+        {
+          /*
+            Don't throw exception here since ReadImage() will already
+            have thrown it.
+          */
+          DestroyJNG(/*chunk*/ NULL,&color_image,&color_image_info,
+                     &alpha_image,&alpha_image_info);
+          return (Image *) NULL;
+        }
 
-  for (y=0; y < (long) image->rows; y++)
-    {
-      s=AcquireImagePixels(jng_image,0,y,image->columns,1,&image->exception);
-      q=SetImagePixels(image,0,y,image->columns,1);
-      if ((s == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
-        break;
-      (void) memcpy(q,s,length);
-      if (!SyncImagePixels(image))
-        break;
-    }
-  DestroyImage(jng_image);
-  if ((unsigned long) y != image->rows)
-    {
       if (logging)
         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                              "Failed to transfer JPEG scanlines");
-      return ((Image *)NULL);
-    }
-
-  if (!image_info->ping)
-    {
-      if (jng_color_type >= 12)
+            "    Copying jng_image pixels to main image.");
+      image->rows=jng_height;
+      image->columns=jng_width;
+      length=MagickArraySize(image->columns,sizeof(PixelPacket));
+      if (jng_height == 0 || jng_width == 0 || length == 0)
+        {
+          if (logging)
+          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+              "    jng_width=%lu jng_height=%lu",
+              (unsigned long)jng_width,(unsigned long)jng_height);
+          DestroyJNG(NULL,&color_image,&color_image_info,
+            &alpha_image,&alpha_image_info);
+          DestroyImage(jng_image);
+          ThrowException(exception,CorruptImageError,
+                         ImproperImageHeader,image->filename);
+          return ((Image *)NULL);
+        }
+      for (y=0; y < (long) image->rows; y++)
+        {
+          s=AcquireImagePixels(jng_image,0,y,image->columns,1,
+             exception);
+          q=SetImagePixels(image,0,y,image->columns,1);
+          if ((s == (const PixelPacket *) NULL) ||
+              (q == (PixelPacket *) NULL))
+            break;
+          (void) memcpy(q,s,length);
+          if (!SyncImagePixels(image))
+            break;
+        }
+      DestroyImage(jng_image);
+      jng_image = (Image *)NULL;
+      if ((unsigned long) y != image->rows)
         {
-          if (jng_alpha_compression_method == 0)
-            {
-              png_byte
-                data[5];
-              (void) WriteBlobMSBULong(alpha_image,0x00000000L);
-              PNGType(data,mng_IEND);
-              LogPNGChunk(logging,mng_IEND,0L);
-              (void) WriteBlob(alpha_image,4,(char *) data);
-              (void) WriteBlobMSBULong(alpha_image,crc32(0,data,4));
-            }
-          CloseBlob(alpha_image);
           if (logging)
             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                  "    Reading opacity from alpha_blob.");
+                                  "Failed to transfer JPEG scanlines");
+          DestroyJNG(NULL,&color_image,&color_image_info,
+                     &alpha_image,&alpha_image_info);
+          return ((Image *)NULL);
+        }
+      if (alpha_image != (Image *)NULL && !image_info->ping)
+        {
+          if (jng_color_type >= 12)
+            {
+              if (jng_alpha_compression_method == 0)
+                {
+                  png_byte
+                    data[5];
+                  (void) WriteBlobMSBULong(alpha_image,0x00000000L);
+                  PNGType(data,mng_IEND);
+                  LogPNGChunk(logging,mng_IEND,0L);
+                  (void) WriteBlob(alpha_image,4,(char *) data);
+                  (void) WriteBlobMSBULong(alpha_image,crc32(0,data,4));
+                }
+              CloseBlob(alpha_image);
+              if (logging)
+                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                     "    Reading opacity from alpha_blob.");
 
-          FormatString(alpha_image_info->filename,"%.1024s",
-                       alpha_image->filename);
+              FormatString(alpha_image_info->filename,"%.1024s",
+                           alpha_image->filename);
 
-          jng_image=ReadImage(alpha_image_info,exception);
+              jng_image=ReadImage(alpha_image_info,exception);
 
-          if (jng_image == (Image *)NULL)
-            {
-              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                   "    jng_image is NULL.");
-              DestroyJNG(NULL,&color_image,&color_image_info,
-                &alpha_image,&alpha_image_info);
-            }
-          else
-            {
-              if (logging)
+              if (jng_image == (Image *)NULL)
                 {
                   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                       "    Read jng_image.");
-                  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                       "      jng_image->width=%lu, jng_image->height=%lu",
-                       (unsigned long)jng_width,(unsigned long)jng_height);
-                  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                       "      image->rows=%lu, image->columns=%lu",
-                      (unsigned long)image->rows,
-                      (unsigned long)image->columns);
-                }
- 
-              for (y=0; y < (long) image->rows; y++)
-                {
-                  s=AcquireImagePixels(jng_image,0,y,image->columns,1,
-                                       &image->exception);
-                  if (image->matte)
-                    {
-                      q=SetImagePixels(image,0,y,image->columns,1);
-                      for (x=(long) image->columns; x > 0; x--,q++,s++)
-                        q->opacity=(Quantum) MaxRGB-s->red;
-                    }
-                  else
-                    {
-                      q=SetImagePixels(image,0,y,image->columns,1);
-                      for (x=(long) image->columns; x > 0; x--,q++,s++)
-                        {
-                          q->opacity=(Quantum) MaxRGB-s->red;
-                          if (q->opacity != OpaqueOpacity)
-                            image->matte=MagickTrue;
-                        }
-                    }
-                  if (!SyncImagePixels(image))
-                    break;
-                }
-              (void) LiberateUniqueFileResource(alpha_image->filename);
-              DestroyJNG(NULL,&color_image,&color_image_info,
-                &alpha_image,&alpha_image_info);
-              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                  " Destroy the JNG image");
-              DestroyImage(jng_image);
-              jng_image = (Image *)NULL;
+                       "    jng_image is NULL.");
+                  DestroyJNG(NULL,&color_image,&color_image_info,
+                    &alpha_image,&alpha_image_info);
+                }
+             else
+                {
+
+                 if (logging)
+                   {
+                     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                          "    Read jng_image.");
+                     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                          "      jng_image->width=%lu, jng_image->height=%lu",
+                          (unsigned long)jng_width,(unsigned long)jng_height);
+                     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                          "      image->rows=%lu, image->columns=%lu",
+                         (unsigned long)image->rows,
+                         (unsigned long)image->columns);
+                   }
+
+                 for (y=0; y < (long) image->rows; y++)
+                   {
+                     s=AcquireImagePixels(jng_image,0,y,image->columns,1,
+                                          &image->exception);
+                     if (s == (PixelPacket *) NULL)
+                       break;
+                     if (image->matte)
+                       {
+                         q=SetImagePixels(image,0,y,image->columns,1);
+                         if (q == (PixelPacket *) NULL)
+                           break;
+                         for (x=(long) image->columns; x > 0; x--,q++,s++)
+                           q->opacity=(Quantum) MaxRGB-s->red;
+                       }
+                     else
+                       {
+                         q=SetImagePixels(image,0,y,image->columns,1);
+                         if (q == (PixelPacket *) NULL)
+                           break;
+                         for (x=(long) image->columns; x > 0; x--,q++,s++)
+                           {
+                             q->opacity=(Quantum) MaxRGB-s->red;
+                             if (q->opacity != OpaqueOpacity)
+                               image->matte=MagickTrue;
+                           }
+                       }
+                     if (!SyncImagePixels(image))
+                       break;
+                   }
+                 (void) LiberateUniqueFileResource(alpha_image->filename);
+                 DestroyJNG(NULL,&color_image,&color_image_info,
+                   &alpha_image,&alpha_image_info);
+                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                     " Destroy the JNG image");
+                 DestroyImage(jng_image);
+                 jng_image = (Image *)NULL;
+               }
             }
-
-          (void) LiberateUniqueFileResource(alpha_image->filename);
-          DestroyJNG(NULL,color_image,color_image_info,
-                     alpha_image,alpha_image_info);
-          DestroyImage(jng_image);
-          jng_image = (Image *)NULL;
         }
+
+      /*
+        Read the JNG image.
+      */
+      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+          " Read the JNG image");
+      image->page.width=jng_width;
+      image->page.height=jng_height;
+      image->page.x=mng_info->x_off[mng_info->object_id];
+      image->page.y=mng_info->y_off[mng_info->object_id];
+      mng_info->image_found++;
+      (void) MagickMonitor(LoadImagesTag,2*GetBlobSize(image),2*GetBlobSize(image),exception);
     }
 
-  /*
-    Read the JNG image.
-  */
-  image->page.width=jng_width;
-  image->page.height=jng_height;
-  image->page.x=mng_info->x_off[mng_info->object_id];
-  image->page.y=mng_info->y_off[mng_info->object_id];
-  mng_info->image_found++;
-  (void) MagickMonitor(LoadImagesTag,2*GetBlobSize(image),2*GetBlobSize(image),
-                       exception);
+  /* Clean up in case we didn't earlier */
 
-  DestroyJNG(NULL,color_image,color_image_info,
-             alpha_image,alpha_image_info);
+  DestroyJNG(NULL,&color_image,&color_image_info,
+    &alpha_image,&alpha_image_info);
 
   if (logging)
     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                           "  exit ReadOneJNGImage()");
 
-  SetMagickResourceLimit(PixelsResource,pixels_resource);
-
-  if (image != (Image *)NULL)
-    DestroyImageList(image);
-  return((Image *)NULL);
+  return (image);
 }
 
 /*
@@ -3563,7 +3803,8 @@ static Image *ReadOneJNGImage(MngInfo *m
 %
 */
 
-static Image *ReadJNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
+static Image *ReadJNGImage(const ImageInfo *image_info,
+                           ExceptionInfo *exception)
 {
   Image
     *image;
@@ -3592,55 +3833,97 @@ static Image *ReadJNGImage(const ImageIn
   image=AllocateImage(image_info);
   mng_info=(MngInfo *) NULL;
   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
-  if (status == False)
-    ThrowReaderException(FileOpenError,UnableToOpenFile,image);
+  if (status == MagickFalse)
+  {
+    (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Unable to open file");
+    ThrowException(exception,FileOpenError,UnableToOpenFile,image->filename);
+    DestroyImageList(image);
+    image=(Image *) NULL;
+    return ((Image *)NULL);
+  }
   if (LocaleCompare(image_info->magick,"JNG") != 0)
-    ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
+  {
+    (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Improper Image Header");
+    ThrowException(exception,CorruptImageError,ImproperImageHeader,image->filename);
+    DestroyImageList(image);
+    image=(Image *) NULL;
+    return((Image *)NULL);
+  }
   /*
     Verify JNG signature.
   */
-  (void) ReadBlob(image,8,magic_number);
-  if (memcmp(magic_number,"\213JNG\r\n\032\n",8) != 0)
-    ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
+  if ((ReadBlob(image,8,magic_number) != 8) ||
+      (memcmp(magic_number,"\213JNG\r\n\032\n",8) != 0))
+  {
+    (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Improper Image Header");
+    ThrowException(exception,CorruptImageError,ImproperImageHeader,image->filename);
+    DestroyImageList(image);
+    image=(Image *) NULL;
+    return((Image *)NULL);
+  }
+
+  if (BlobIsSeekable(image) && GetBlobSize(image) < 147)
+  {
+    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+        "Insufficient Image Data");
+    ThrowException(exception,CorruptImageError,InsufficientImageDataInFile,image->filename);
+    DestroyImageList(image);
+    image=(Image *) NULL;
+    return((Image *)NULL);
+  }
+
   /*
     Allocate a MngInfo structure.
   */
-  have_mng_structure=False;
+  have_mng_structure=MagickFalse;
   mng_info=MagickAllocateMemory(MngInfo *,sizeof(MngInfo));
   if (mng_info == (MngInfo *) NULL)
-    ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
+  {
+    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+        "Memory Allocation Failed");
+    ThrowException(exception,ResourceLimitError,MemoryAllocationFailed,image->filename);
+    DestroyImageList(image);
+    image=(Image *) NULL;
+    return((Image *)NULL);
+  }
   /*
     Initialize members of the MngInfo structure.
   */
   (void) memset(mng_info,0,sizeof(MngInfo));
-  have_mng_structure=True;
+  have_mng_structure=MagickTrue;
 
   mng_info->image=image;
   image=ReadOneJNGImage(mng_info,image_info,exception);
-  MngInfoFreeStruct(mng_info,&have_mng_structure);
-  if (image == (Image *) NULL)
+  if (image == (Image *) NULL || image->columns == 0 || image->rows == 0)
     {
       if (logging)
         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                              "exit ReadJNGImage() with error");
-      return((Image *) NULL);
+            "exit ReadJNGImage() with error");
+      if (image != (Image *) NULL)
+        {
+          DestroyImageList(image);
+          image=(Image *) NULL;
+        }
+      if (mng_info->image != (Image *) NULL)
+        {
+          DestroyImageList(mng_info->image);
+          mng_info->image=(Image *) NULL;
+        }
+      MngInfoFreeStruct(mng_info,&have_mng_structure);
+      return((Image *)NULL);
     }
+
   CloseBlob(image);
-  if (image->columns == 0 || image->rows == 0)
-    {
-      DestroyImageList(image);
-      if (logging)
-        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                              "exit ReadJNGImage() with error");
-      return((Image *) NULL);
-    }
+  MngInfoFreeStruct(mng_info,&have_mng_structure);
+
   if (logging)
     (void) LogMagickEvent(CoderEvent,GetMagickModule(),"exit ReadJNGImage()");
   return (image);
 }
 #endif
 
-static Image *ReadMNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
+static Image *ReadMNGImage(const ImageInfo *image_info,
+                           ExceptionInfo *exception)
 {
   char
     page_geometry[MaxTextExtent];
@@ -3675,9 +3958,6 @@ static Image *ReadMNGImage(const ImageIn
     mng_background_color;
 #endif
 
-  register unsigned char
-    *p;
-
   register long
     i;
 
@@ -3686,7 +3966,7 @@ static Image *ReadMNGImage(const ImageIn
 
   short
     loop_level,
-    loops_active;
+    loops_active = 0;
 
   volatile short
     skipping_loop;
@@ -3734,21 +4014,6 @@ static Image *ReadMNGImage(const ImageIn
   default_fb.right=0;
 
   /*
-    Set image_info->type=OptimizeType (new in version 5.4.0) to get the
-    following optimizations:
-
-    o  16-bit depth is reduced to 8 if all pixels contain samples whose
-    high byte and low byte are identical.
-    o  Opaque matte channel is removed.
-    o  If matte channel is present but only one transparent color is
-    present, RGB+tRNS is written instead of RGBA
-    o  Grayscale images are reduced to 1, 2, or 4 bit depth if
-    this can be done without loss.
-    o  Palette is sorted to remove unused entries and to put a
-    transparent color first, if PNG_SORT_PALETTE is also defined.
-  */
-
-  /*
     Open image file.
   */
   assert(image_info != (const ImageInfo *) NULL);
@@ -3759,11 +4024,11 @@ static Image *ReadMNGImage(const ImageIn
   image=AllocateImage(image_info);
   mng_info=(MngInfo *) NULL;
   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
-  if (status == False)
+  if (status == MagickFalse)
     ThrowReaderException(FileOpenError,UnableToOpenFile,image);
-  first_mng_object=False;
+  first_mng_object=MagickFalse;
   skipping_loop=(-1);
-  have_mng_structure=False;
+  have_mng_structure=MagickFalse;
   /*
     Allocate a MngInfo structure.
   */
@@ -3775,10 +4040,7 @@ static Image *ReadMNGImage(const ImageIn
   */
   (void) memset(mng_info,0,sizeof(MngInfo));
   mng_info->image=image;
-  have_mng_structure=True;
-#if (QuantumDepth == 16)
-  mng_info->optimize=image_info->type == OptimizeType;
-#endif
+  have_mng_structure=MagickTrue;
 
   if (LocaleCompare(image_info->magick,"MNG") == 0)
     {
@@ -3790,10 +4052,10 @@ static Image *ReadMNGImage(const ImageIn
       */
       (void) ReadBlob(image,8,magic_number);
       if (memcmp(magic_number,"\212MNG\r\n\032\n",8) != 0)
-      {
-        MngInfoFreeStruct(mng_info,&have_mng_structure);
-        ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
-      }
+        {
+          MngInfoFreeStruct(mng_info,&have_mng_structure);
+          ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
+        }
       /*
         Initialize some nonzero members of the MngInfo structure.
       */
@@ -3802,12 +4064,12 @@ static Image *ReadMNGImage(const ImageIn
           mng_info->object_clip[i].right=PNG_MAX_UINT;
           mng_info->object_clip[i].bottom=PNG_MAX_UINT;
         }
-      mng_info->exists[0]=True;
+      mng_info->exists[0]=MagickTrue;
     }
-  first_mng_object=True;
+  first_mng_object=MagickTrue;
   mng_type=0;
 #ifdef MNG_INSERT_LAYERS
-  insert_layers=False;  /* should be False when converting or mogrifying */
+  insert_layers=MagickFalse;  /* should be False if converting or mogrifying */
 #endif
   default_frame_delay=0;
   default_frame_timeout=0;
@@ -3815,11 +4077,11 @@ static Image *ReadMNGImage(const ImageIn
   final_delay=1;
   mng_info->ticks_per_second=100;
   object_id=0;
-  skip_to_iend=False;
-  term_chunk_found=False;
+  skip_to_iend=MagickFalse;
+  term_chunk_found=MagickFalse;
   mng_info->framing_mode=1;
 #ifdef MNG_INSERT_LAYERS
-  mandatory_back=False;
+  mandatory_back=MagickFalse;
 #endif
 #ifdef MNG_INSERT_LAYERS
   mng_background_color=image->background_color;
@@ -3831,31 +4093,41 @@ static Image *ReadMNGImage(const ImageIn
 
       if (LocaleCompare(image_info->magick,"MNG") == 0)
         {
+          register unsigned char
+            *p = 0;
+
           unsigned char
-            *chunk;
+            *chunk = NULL;
 
           /*
             Read a new chunk.
           */
           type[0]='\0';
           (void) strcat(type,"errr");
-          length=ReadBlobMSBLong(image);
+          length=(size_t) ReadBlobMSBLong(image);
           count=ReadBlob(image,4,type);
+          if (count < 4)
+            {
+              if (logging)
+                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                      "  Reading MNG chunk, count: %"
+                                      "lu",
+                                      count);
+              MngInfoFreeStruct(mng_info,&have_mng_structure);
+              ThrowReaderException(CorruptImageError,CorruptImage,image);
+            }
 
           if (logging)
             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                  "  Reading MNG chunk type %c%c%c%c, length: %lu",
+                                  "  Reading MNG chunk type %c%c%c%c,"
+                                  " length: %lu",
                                   type[0],type[1],type[2],type[3],length);
 
           if (length > PNG_MAX_UINT)
-            status=False;
-          if (count == 0)
-          {
-            MngInfoFreeStruct(mng_info,&have_mng_structure);
-            ThrowReaderException(CorruptImageError,CorruptImage,image);
-          }
-          p=NULL;
-          chunk=(unsigned char *) NULL;
+            {
+              MngInfoFreeStruct(mng_info,&have_mng_structure);
+              ThrowReaderException(CorruptImageError,CorruptImage,image);
+            }
           if (length)
             {
               chunk=MagickAllocateMemory(unsigned char *,length);
@@ -3865,8 +4137,12 @@ static Image *ReadMNGImage(const ImageIn
                 ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,
                                      image);
               }
-              for (i=0; i < (long) length; i++)
-                chunk[i]=ReadBlobByte(image);
+              if (ReadBlob(image,length,chunk) < length)
+                {
+                  MagickFreeMemory(chunk);
+                  MngInfoFreeStruct(mng_info,&have_mng_structure);
+                  ThrowReaderException(CorruptImageError,CorruptImage,image);
+                }
               p=chunk;
             }
           (void) ReadBlobMSBLong(image);  /* read crc word */
@@ -3874,35 +4150,32 @@ static Image *ReadMNGImage(const ImageIn
 #if !defined(JNG_SUPPORTED)
           if (!memcmp(type,mng_JHDR,4))
             {
-              skip_to_iend=True;
+              skip_to_iend=MagickTrue;
               if (!mng_info->jhdr_warning)
-              {
-                MngInfoFreeStruct(mng_info,&have_mng_structure);
                 (void) ThrowException(&image->exception,CoderError,
-                                      JNGCompressionNotSupported,image->filename);
-              }
+                                      JNGCompressionNotSupported,
+                                      image->filename);
               mng_info->jhdr_warning++;
             }
 #endif
           if (!memcmp(type,mng_DHDR,4))
             {
-              skip_to_iend=True;
+              skip_to_iend=MagickTrue;
               if (!mng_info->dhdr_warning)
-              {
-                MngInfoFreeStruct(mng_info,&have_mng_structure);
                 (void) ThrowException(&image->exception,CoderError,
                                       DeltaPNGNotSupported,image->filename);
-              }
               mng_info->dhdr_warning++;
             }
           if (!memcmp(type,mng_MEND,4))
-            break;
+            {
+              MagickFreeMemory(chunk);
+              break;
+            }
           if (skip_to_iend)
             {
               if (!memcmp(type,mng_IEND,4))
-                skip_to_iend=False;
-              if (length)
-                MagickFreeMemory(chunk);
+                skip_to_iend=MagickFalse;
+              MagickFreeMemory(chunk);
               if (logging)
                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                                       "  Skip to IEND.");
@@ -3910,17 +4183,44 @@ static Image *ReadMNGImage(const ImageIn
             }
           if (!memcmp(type,mng_MHDR,4))
             {
-              mng_info->mng_width=(unsigned long) ((p[0] << 24) | (p[1] << 16) |
-                                                   (p[2] << 8) | p[3]);
-              mng_info->mng_height=(unsigned long) ((p[4] << 24) | (p[5] << 16) |
-                                                    (p[6] << 8) | p[7]);
+              if (length < 16)
+                {
+                  MagickFreeMemory(chunk);
+                  MngInfoFreeStruct(mng_info,&have_mng_structure);
+                  ThrowReaderException(CorruptImageError,CorruptImage,image);
+                }
+#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
+              /* To quiet a Coverity complaint */
+              AcquireSemaphoreInfo(&png_semaphore);
+#endif
+              mng_info->mng_width=(unsigned long) mng_get_long(p);
+              mng_info->mng_height=(unsigned long) mng_get_long(&p[4]);
               if (logging)
                 {
                   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                        "  MNG width: %lu",mng_info->mng_width);
+                                        "  MNG width: %lu",
+                                        mng_info->mng_width);
                   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                        "  MNG height: %lu",mng_info->mng_height);
+                                        "  MNG height: %lu",
+                                        mng_info->mng_height);
                 }
+#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
+               LiberateSemaphoreInfo(&png_semaphore);
+#endif
+              if ((long) mng_info->mng_width >
+                  65535 ||
+                  (long) mng_info->mng_height >
+                  65535)
+                {
+                  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                      "   MNG width or height too large: %lu, %lu",
+                      mng_info->mng_width,mng_info->mng_height);
+                  MagickFreeMemory(chunk);
+                  MngInfoFreeStruct(mng_info,&have_mng_structure);
+                  ThrowReaderException(CorruptImageError,ImproperImageHeader,
+                      image);
+                }
+
               p+=8;
               mng_info->ticks_per_second=mng_get_long(p);
               if (mng_info->ticks_per_second == 0)
@@ -3929,7 +4229,7 @@ static Image *ReadMNGImage(const ImageIn
                 default_frame_delay=100/mng_info->ticks_per_second;
               frame_delay=default_frame_delay;
               simplicity=0;
-              if (length > 16)
+              if (length >= 28)
                 {
                   p+=16;
                   simplicity=mng_get_long(p);
@@ -3946,7 +4246,7 @@ static Image *ReadMNGImage(const ImageIn
                 mng_type=3; /* VLC */
 #ifdef MNG_INSERT_LAYERS
               if (mng_type != 3 && !image_info->ping)
-                insert_layers=True;
+                insert_layers=MagickTrue;
 #endif
               if (GetPixels(image) != (PixelPacket *) NULL)
                 {
@@ -3967,6 +4267,7 @@ static Image *ReadMNGImage(const ImageIn
                       "  MNG width or height is too large: %lu, %lu",
                       mng_info->mng_width,mng_info->mng_height);
                   MagickFreeMemory(chunk);
+                  MngInfoFreeStruct(mng_info,&have_mng_structure);
                   ThrowReaderException(CorruptImageError,
                      ImproperImageHeader,image);
                 }
@@ -3977,7 +4278,15 @@ static Image *ReadMNGImage(const ImageIn
               mng_info->frame.right=(long) mng_info->mng_width;
               mng_info->frame.top=0;
               mng_info->frame.bottom=(long) mng_info->mng_height;
+
+              /* To quiet a Coverity complaint */
+#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
+              AcquireSemaphoreInfo(&png_semaphore);              
+#endif
               mng_info->clip=default_fb=previous_fb=mng_info->frame;
+#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
+              LiberateSemaphoreInfo(&png_semaphore);
+#endif
               for (i=0; i < MNG_MAX_OBJECTS; i++)
                 mng_info->object_clip[i]=mng_info->frame;
               MagickFreeMemory(chunk);
@@ -3989,17 +4298,16 @@ static Image *ReadMNGImage(const ImageIn
               int
                 repeat=0;
 
-
               if (length)
                 repeat=p[0];
-              if (repeat == 3)
+              if (repeat == 3 && length > 8)
                 {
                   final_delay=(png_uint_32) mng_get_long(&p[2]);
                   mng_iterations=(png_uint_32) mng_get_long(&p[6]);
                   if (mng_iterations == PNG_MAX_UINT)
                     mng_iterations=0;
                   image->iterations=mng_iterations;
-                  term_chunk_found=True;
+                  term_chunk_found=MagickTrue;
                 }
               if (logging)
                 {
@@ -4017,13 +4325,29 @@ static Image *ReadMNGImage(const ImageIn
           if (!memcmp(type,mng_DEFI,4))
             {
               if (mng_type == 3)
-                (void) ThrowException2(&image->exception,CoderError,
-                                       "DEFI chunk found in MNG-VLC datastream",
-                                       (char *) NULL);
-              object_id=(p[0] << 8) | p[1];
+                {
+                  if (logging)
+                    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                          "DEFI chunk found in MNG-VLC"
+                                          " datastream");
+                  MagickFreeMemory(chunk);
+                  continue;
+                }
+              if (length < 2)
+                {
+                  if (logging)
+                    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                          "  DEFI chunk must be at least"
+                                          " 2 bytes long");
+                  MagickFreeMemory(chunk);
+                  MngInfoFreeStruct(mng_info,&have_mng_structure);
+                  ThrowReaderException(CorruptImageError,CorruptImage,image);
+                }
+              object_id=((magick_uint32_t) p[0] << 8) | (magick_uint32_t) p[1];
               if (mng_type == 2 && object_id != 0)
                 (void) ThrowException2(&image->exception,CoderError,
-                                       "Nonzero object_id in MNG-LC datastream",
+                                       "Nonzero object_id in MNG-LC"
+                                       " datastream",
                                        (char *) NULL);
               if (object_id > MNG_MAX_OBJECTS)
                 {
@@ -4031,20 +4355,22 @@ static Image *ReadMNGImage(const ImageIn
                     Instead of issuing a warning we should allocate a larger
                     MngInfo structure and continue.
                   */
-                  (void) ThrowException2(&image->exception,CoderError,
-                                         "object id too large",(char *) NULL);
+                  if (logging)
+                    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                          "object id too large");
                   object_id=MNG_MAX_OBJECTS;
                 }
               if (mng_info->exists[object_id])
                 if (mng_info->frozen[object_id])
                   {
+                    if (logging)
+                      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                            "DEFI cannot redefine a frozen"
+                                           " MNG object");
                     MagickFreeMemory(chunk);
-                    (void) ThrowException2(&image->exception,CoderError,
-                                           "DEFI cannot redefine a frozen MNG object",
-                                           (char *) NULL);
                     continue;
                   }
-              mng_info->exists[object_id]=True;
+              mng_info->exists[object_id]=MagickTrue;
               if (length > 2)
                 mng_info->invisible[object_id]=p[2];
               /*
@@ -4052,10 +4378,8 @@ static Image *ReadMNGImage(const ImageIn
               */
               if (length > 11)
                 {
-                  mng_info->x_off[object_id]=(long) ((p[4] << 24) | (p[5] << 16) |
-                                                     (p[6] << 8) | p[7]);
-                  mng_info->y_off[object_id]=(long) ((p[8] << 24) | (p[9] << 16) |
-                                                     (p[10] << 8) | p[11]);
+                  mng_info->x_off[object_id]= mng_get_long(&p[4]);
+                  mng_info->y_off[object_id]= mng_get_long(&p[8]);
                   if (logging)
                     {
                       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
@@ -4070,23 +4394,26 @@ static Image *ReadMNGImage(const ImageIn
                 Extract object clipping info.
               */
               if (length > 27)
-                mng_info->object_clip[object_id]=mng_read_box(mng_info->frame,0,
-                                                              &p[12]);
+                mng_info->object_clip[object_id]
+                   =mng_read_box( mng_info->frame,0,&p[12]);
               MagickFreeMemory(chunk);
               continue;
             }
           if (!memcmp(type,mng_bKGD,4))
             {
-              mng_info->have_global_bkgd=False;
+              mng_info->have_global_bkgd=MagickFalse;
               if (length > 5)
                 {
                   mng_info->mng_global_bkgd.red
-                    =ScaleShortToQuantum(((p[0] << 8) | p[1]));
+                    =ScaleShortToQuantum((((magick_uint32_t) p[0] << 8) |
+                                          (magick_uint32_t) p[1]));
                   mng_info->mng_global_bkgd.green
-                    =ScaleShortToQuantum(((p[2] << 8) | p[3]));
+                    =ScaleShortToQuantum((((magick_uint32_t) p[2] << 8) |
+                                          (magick_uint32_t) p[3]));
                   mng_info->mng_global_bkgd.blue
-                    =ScaleShortToQuantum(((p[4] << 8) | p[5]));
-                  mng_info->have_global_bkgd=True;
+                    =ScaleShortToQuantum((((magick_uint32_t) p[4] << 8) |
+                                          (magick_uint32_t) p[5]));
+                  mng_info->have_global_bkgd=MagickTrue;
                 }
               MagickFreeMemory(chunk);
               continue;
@@ -4101,16 +4428,20 @@ static Image *ReadMNGImage(const ImageIn
               if (mandatory_back && length > 5)
                 {
                   mng_background_color.red=
-                    ScaleShortToQuantum(((p[0] << 8) | p[1]));
+                    ScaleShortToQuantum((((magick_uint32_t) p[0] << 8) |
+                                         (magick_uint32_t) p[1]));
                   mng_background_color.green=
-                    ScaleShortToQuantum(((p[2] << 8) | p[3]));
+                    ScaleShortToQuantum((((magick_uint32_t) p[2] << 8) |
+                                         (magick_uint32_t) p[3]));
                   mng_background_color.blue=
-                    ScaleShortToQuantum(((p[4] << 8) | p[5]));
+                    ScaleShortToQuantum((((magick_uint32_t) p[4] << 8) |
+                                         (magick_uint32_t) p[5]));
                   mng_background_color.opacity=OpaqueOpacity;
                 }
 #ifdef MNG_OBJECT_BUFFERS
               if (length > 8)
-                mng_background_object=(p[7] << 8) | p[8];
+                mng_background_object=((magick_uint32_t) p[7] << 8) |
+                  (magick_uint32_t) p[8];
 #endif
 #endif
               MagickFreeMemory(chunk);
@@ -4118,9 +4449,6 @@ static Image *ReadMNGImage(const ImageIn
             }
           if (!memcmp(type,mng_PLTE,4))
             {
-              register long
-                i;
-
               /*
                 Read global PLTE.
               */
@@ -4154,9 +4482,6 @@ static Image *ReadMNGImage(const ImageIn
             }
           if (!memcmp(type,mng_tRNS,4))
             {
-              register long
-                i;
-
               /* read global tRNS */
 
               if (length < 257)
@@ -4180,10 +4505,10 @@ static Image *ReadMNGImage(const ImageIn
 
                   igamma=mng_get_long(p);
                   mng_info->global_gamma=((float) igamma)*0.00001;
-                  mng_info->have_global_gama=True;
+                  mng_info->have_global_gama=MagickTrue;
                 }
               else
-                mng_info->have_global_gama=False;
+                mng_info->have_global_gama=MagickFalse;
               MagickFreeMemory(chunk);
               continue;
             }
@@ -4195,9 +4520,12 @@ static Image *ReadMNGImage(const ImageIn
               */
               if (length == 32)
                 {
-                  mng_info->global_chrm.white_point.x=0.00001*mng_get_long(p);
-                  mng_info->global_chrm.white_point.y=0.00001*mng_get_long(&p[4]);
-                  mng_info->global_chrm.red_primary.x=0.00001*mng_get_long(&p[8]);
+                  mng_info->global_chrm.white_point.x=0.00001*
+                    mng_get_long(p);
+                  mng_info->global_chrm.white_point.y=0.00001*
+                    mng_get_long(&p[4]);
+                  mng_info->global_chrm.red_primary.x=0.00001*
+                    mng_get_long(&p[8]);
                   mng_info->global_chrm.red_primary.y=0.00001*
                     mng_get_long(&p[12]);
                   mng_info->global_chrm.green_primary.x=0.00001*
@@ -4208,10 +4536,10 @@ static Image *ReadMNGImage(const ImageIn
                     mng_get_long(&p[24]);
                   mng_info->global_chrm.blue_primary.y=0.00001*
                     mng_get_long(&p[28]);
-                  mng_info->have_global_chrm=True;
+                  mng_info->have_global_chrm=MagickTrue;
                 }
               else
-                mng_info->have_global_chrm=False;
+                mng_info->have_global_chrm=MagickFalse;
               MagickFreeMemory(chunk);
               continue;
             }
@@ -4223,10 +4551,10 @@ static Image *ReadMNGImage(const ImageIn
               if (length)
                 {
                   mng_info->global_srgb_intent=(RenderingIntent) (p[0]+1);
-                  mng_info->have_global_srgb=True;
+                  mng_info->have_global_srgb=MagickTrue;
                 }
               else
-                mng_info->have_global_srgb=False;
+                mng_info->have_global_srgb=MagickFalse;
               MagickFreeMemory(chunk);
               continue;
             }
@@ -4237,17 +4565,18 @@ static Image *ReadMNGImage(const ImageIn
               /*
                 Read global iCCP.
               */
-              if (length)
-                MagickFreeMemory(chunk);
+              MagickFreeMemory(chunk);
               continue;
             }
           if (!memcmp(type,mng_FRAM,4))
             {
               if (mng_type == 3)
                 (void) ThrowException2(&image->exception,CoderError,
-                                       "FRAM chunk found in MNG-VLC datastream",
+                                       "FRAM chunk found in MNG-VLC"
+                                       " datastream",
                                        (char *) NULL);
-              if ((mng_info->framing_mode == 2) || (mng_info->framing_mode == 4))
+              if ((mng_info->framing_mode == 2) ||
+                  (mng_info->framing_mode == 4))
                 image->delay=frame_delay;
               frame_delay=default_frame_delay;
               frame_timeout=default_frame_timeout;
@@ -4257,7 +4586,8 @@ static Image *ReadMNGImage(const ImageIn
                   mng_info->framing_mode=p[0];
               if (logging)
                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                      "    Framing_mode=%d",mng_info->framing_mode);
+                                      "    Framing_mode=%d",
+                                      mng_info->framing_mode);
               if (length > 6)
                 {
                   /*
@@ -4278,7 +4608,7 @@ static Image *ReadMNGImage(const ImageIn
                       change_timeout=(*p++);
                       change_clipping=(*p++);
                       p++; /* change_sync */
-                      if (change_delay)
+                      if (change_delay && (p-chunk) < (ssize_t) (length-4))
                         {
                           frame_delay=(100*(mng_get_long(p))/
                                        mng_info->ticks_per_second);
@@ -4290,11 +4620,11 @@ static Image *ReadMNGImage(const ImageIn
                                                   "    Framing_delay=%ld",
                                                   frame_delay);
                         }
-                      if (change_timeout)
+                      if (change_timeout && (p-chunk) < (ssize_t) (length-4))
                         {
                           frame_timeout=
                             (100*(mng_get_long(p))/mng_info->ticks_per_second);
-                          if (change_delay == 2)
+                          if (change_timeout == 2)
                             default_frame_timeout=frame_timeout;
                           p+=4;
                           if (logging)
@@ -4302,14 +4632,15 @@ static Image *ReadMNGImage(const ImageIn
                                                   "    Framing_timeout=%ld",
                                                   frame_timeout);
                         }
-                      if (change_clipping)
+                      if (change_clipping && (p-chunk) < (ssize_t) (length-16))
                         {
                           fb=mng_read_box(previous_fb,p[0],&p[1]);
-                          p+=17;
+                          p+=16;
                           previous_fb=fb;
                           if (logging)
                             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                                  "    Frame_clipping: L=%ld R=%ld T=%ld B=%ld",
+                                                  "    Frame_clipping:"
+                                                  " L=%ld R=%ld T=%ld B=%ld",
                                                   fb.left, fb.right,fb.top,
                                                   fb.bottom);
                           if (change_clipping == 2)
@@ -4317,17 +4648,26 @@ static Image *ReadMNGImage(const ImageIn
                         }
                     }
                 }
+#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
+              /* To quiet a Coverity complaint */
+              AcquireSemaphoreInfo(&png_semaphore);
+#endif
               mng_info->clip=fb;
               mng_info->clip=mng_minimum_box(fb,mng_info->frame);
+#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
+              LiberateSemaphoreInfo(&png_semaphore);
+#endif
               subframe_width=(mng_info->clip.right-mng_info->clip.left);
               subframe_height=(mng_info->clip.bottom-mng_info->clip.top);
               /*
-                Insert a background layer behind the frame if framing_mode is 4.
+                Insert a background layer behind the frame
+                if framing_mode is 4.
               */
 #ifdef MNG_INSERT_LAYERS
               if (logging)
                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                      "   subframe_width=%lu, subframe_height=%lu",
+                                      "   subframe_width=%lu,"
+                                      " subframe_height=%lu",
                                       subframe_width, subframe_height);
               if (insert_layers && (mng_info->framing_mode == 4) &&
                   (subframe_width) && (subframe_height))
@@ -4349,12 +4689,12 @@ static Image *ReadMNGImage(const ImageIn
                   mng_info->image=image;
                   if (term_chunk_found)
                     {
-                      image->start_loop=True;
+                      image->start_loop=MagickTrue;
                       image->iterations=mng_iterations;
-                      term_chunk_found=False;
+                      term_chunk_found=MagickFalse;
                     }
                   else
-                    image->start_loop=False;
+                    image->start_loop=MagickFalse;
                   image->columns=subframe_width;
                   image->rows=subframe_height;
                   image->page.width=subframe_width;
@@ -4362,14 +4702,17 @@ static Image *ReadMNGImage(const ImageIn
                   image->page.x=mng_info->clip.left;
                   image->page.y=mng_info->clip.top;
                   image->background_color=mng_background_color;
-                  image->matte=False;
+                  image->matte=MagickFalse;
                   image->delay=0;
                   (void) SetImage(image,OpaqueOpacity);
                   if (logging)
                     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                          "  Inserted background layer, L=%ld, R=%ld, T=%ld, B=%ld",
-                                          mng_info->clip.left,mng_info->clip.right,
-                                          mng_info->clip.top,mng_info->clip.bottom);
+                                          "  Inserted background layer,"
+                                          " L=%ld, R=%ld, T=%ld, B=%ld",
+                                          mng_info->clip.left,
+                                          mng_info->clip.right,
+                                          mng_info->clip.top,
+                                          mng_info->clip.bottom);
                 }
 #endif
               MagickFreeMemory(chunk);
@@ -4384,19 +4727,26 @@ static Image *ReadMNGImage(const ImageIn
               /*
                 Read CLIP.
               */
-              first_object=(p[0] << 8) | p[1];
-              last_object=(p[2] << 8) | p[3];
-              for (i=(int) first_object; i <= (int) last_object; i++)
-                {
-                  if (i > MNG_MAX_OBJECTS)
-                      continue;
-                  if (mng_info->exists[i] && !mng_info->frozen[i])
+              if (length > 3)
+                {
+                  first_object=((magick_uint32_t) p[0] << 8) | (magick_uint32_t) p[1];
+                  last_object=((magick_uint32_t) p[2] << 8) | (magick_uint32_t) p[3];
+                  p+=4;
+
+                  for (i=(int) first_object; i <= (int) last_object; i++)
                     {
-                      MngBox
-                        box;
+                      if (i > MNG_MAX_OBJECTS)
+                        continue;
+                      if (mng_info->exists[i] && !mng_info->frozen[i])
+                        {
+                          MngBox
+                            box;
 
-                      box=mng_info->object_clip[i];
-                      mng_info->object_clip[i]=mng_read_box(box,p[4],&p[5]);
+                          box=mng_info->object_clip[i];
+                          if ((p-chunk) < (ssize_t) (length-17))
+                            mng_info->object_clip[i]=
+                                mng_read_box(box,p[0],&p[1]);
+                        }
                     }
                 }
               MagickFreeMemory(chunk);
@@ -4404,28 +4754,21 @@ static Image *ReadMNGImage(const ImageIn
             }
           if (!memcmp(type,mng_SAVE,4))
             {
-              register long
-                i;
-
               for (i=1; i < MNG_MAX_OBJECTS; i++)
                 if (mng_info->exists[i])
                   {
-                    mng_info->frozen[i]=True;
+                    mng_info->frozen[i]=MagickTrue;
 #ifdef MNG_OBJECT_BUFFERS
                     if (mng_info->ob[i] != (MngBuffer *) NULL)
-                      mng_info->ob[i]->frozen=True;
+                      mng_info->ob[i]->frozen=MagickTrue;
 #endif
                   }
-              if (length)
-                MagickFreeMemory(chunk);
+              MagickFreeMemory(chunk);
               continue;
             }
 
           if (!memcmp(type,mng_DISC,4) || !memcmp(type,mng_SEEK,4))
             {
-              register long
-                i;
-
               /*
                 Read DISC or SEEK.
               */
@@ -4441,12 +4784,11 @@ static Image *ReadMNGImage(const ImageIn
 
                   for (j=0; j < (long) length; j+=2)
                     {
-                      i=p[j] << 8 | p[j+1];
+                      i=(magick_uint32_t) p[j] << 8 | (magick_uint32_t) p[j+1];
                       MngInfoDiscardObject(mng_info,i);
                     }
                 }
-              if (length)
-                MagickFreeMemory(chunk);
+              MagickFreeMemory(chunk);
               continue;
             }
           if (!memcmp(type,mng_MOVE,4))
@@ -4458,25 +4800,32 @@ static Image *ReadMNGImage(const ImageIn
               /*
                 read MOVE
               */
-              first_object=(p[0] << 8) | p[1];
-              last_object=(p[2] << 8) | p[3];
-              for (i=(long) first_object; i <= (long) last_object; i++)
-                {
-                  if (i > MNG_MAX_OBJECTS)
-                      continue;
-                  if (mng_info->exists[i] && !mng_info->frozen[i])
+
+              if (length > 3)
+                {
+                  first_object=((magick_uint32_t) p[0] << 8) | (magick_uint32_t) p[1];
+                  last_object=((magick_uint32_t) p[2] << 8) | (magick_uint32_t) p[3];
+                  p+=4;
+
+                  for (i=(long) first_object; i <= (long) last_object; i++)
                     {
-                      MngPair
-                        new_pair;
+                      if (i > MNG_MAX_OBJECTS)
+                        continue;
+                      if (mng_info->exists[i] && !mng_info->frozen[i] &&
+                          (p-chunk) < (ssize_t) (length-8))
+                        {
+                          MngPair
+                            new_pair;
 
-                      MngPair
-                        old_pair;
+                          MngPair
+                            old_pair;
 
-                      old_pair.a=mng_info->x_off[i];
-                      old_pair.b=mng_info->y_off[i];
-                      new_pair=mng_read_pair(old_pair,(int) p[4],&p[5]);
-                      mng_info->x_off[i]=new_pair.a;
-                      mng_info->y_off[i]=new_pair.b;
+                          old_pair.a=mng_info->x_off[i];
+                          old_pair.b=mng_info->y_off[i];
+                          new_pair=mng_read_pair(old_pair,(int) p[0],&p[1]);
+                          mng_info->x_off[i]=new_pair.a;
+                          mng_info->y_off[i]=new_pair.b;
+                        }
                     }
                 }
               MagickFreeMemory(chunk);
@@ -4486,21 +4835,25 @@ static Image *ReadMNGImage(const ImageIn
           if (!memcmp(type,mng_LOOP,4))
             {
               long loop_iters=1;
-              loop_level=chunk[0];
-              loops_active++;
-              mng_info->loop_active[loop_level]=1;  /* mark loop active */
-              /*
-                Record starting point.
-              */
-              loop_iters=mng_get_long(&chunk[1]);
-              if (loop_iters == 0)
-                skipping_loop=loop_level;
-              else
+
+              if (length > 0) /* To do: check spec, if empty LOOP is allowed */
                 {
-                  mng_info->loop_jump[loop_level]=TellBlob(image);
-                  mng_info->loop_count[loop_level]=loop_iters;
+                  loop_level=chunk[0];
+                  loops_active++;
+                  mng_info->loop_active[loop_level]=1;  /* mark loop active */
+                  /*
+                    Record starting point.
+                  */
+                  loop_iters=mng_get_long(&chunk[1]);
+                  if (loop_iters == 0)
+                    skipping_loop=loop_level;
+                  else
+                    {
+                      mng_info->loop_jump[loop_level]=TellBlob(image);
+                      mng_info->loop_count[loop_level]=loop_iters;
+                    }
+                  mng_info->loop_iteration[loop_level]=0;
                 }
-              mng_info->loop_iteration[loop_level]=0;
               MagickFreeMemory(chunk);
               continue;
             }
@@ -4572,11 +4925,11 @@ static Image *ReadMNGImage(const ImageIn
                 magn_methy;
 
               if (length > 1)
-                magn_first=(p[0] << 8) | p[1];
+                magn_first=((magick_uint32_t) p[0] << 8) | (magick_uint32_t) p[1];
               else
                 magn_first=0;
               if (length > 3)
-                magn_last=(p[2] << 8) | p[3];
+                magn_last=((magick_uint32_t) p[2] << 8) | (magick_uint32_t) p[3];
               else
                 magn_last=magn_first;
 #ifndef MNG_OBJECT_BUFFERS
@@ -4584,7 +4937,8 @@ static Image *ReadMNGImage(const ImageIn
                 if (!mng_info->magn_warning)
                   {
                     (void) ThrowException2(&image->exception,CoderError,
-                                           "MAGN is not implemented yet for nonzero objects",
+                                           "MAGN is not implemented yet"
+                                           " for nonzero objects",
                                            image->filename);
                     mng_info->magn_warning++;
                   }
@@ -4595,42 +4949,42 @@ static Image *ReadMNGImage(const ImageIn
                 magn_methx=0;
 
               if (length > 6)
-                magn_mx=(p[5] << 8) | p[6];
+                magn_mx=((magick_uint32_t) p[5] << 8) | (magick_uint32_t) p[6];
               else
                 magn_mx=1;
               if (magn_mx == 0)
                 magn_mx=1;
 
               if (length > 8)
-                magn_my=(p[7] << 8) | p[8];
+                magn_my=((magick_uint32_t) p[7] << 8) | (magick_uint32_t) p[8];
               else
                 magn_my=magn_mx;
               if (magn_my == 0)
                 magn_my=1;
 
               if (length > 10)
-                magn_ml=(p[9] << 8) | p[10];
+                magn_ml=((magick_uint32_t) p[9] << 8) | (magick_uint32_t) p[10];
               else
                 magn_ml=magn_mx;
               if (magn_ml == 0)
                 magn_ml=1;
 
               if (length > 12)
-                magn_mr=(p[11] << 8) | p[12];
+                magn_mr=((magick_uint32_t) p[11] << 8) | (magick_uint32_t) p[12];
               else
                 magn_mr=magn_mx;
               if (magn_mr == 0)
                 magn_mr=1;
 
               if (length > 14)
-                magn_mt=(p[13] << 8) | p[14];
+                magn_mt=((magick_uint32_t) p[13] << 8) | (magick_uint32_t) p[14];
               else
                 magn_mt=magn_my;
               if (magn_mt == 0)
                 magn_mt=1;
 
               if (length > 16)
-                magn_mb=(p[15] << 8) | p[16];
+                magn_mb=((magick_uint32_t) p[15] << 8) | (magick_uint32_t) p[16];
               else
                 magn_mb=magn_my;
               if (magn_mb == 0)
@@ -4645,12 +4999,14 @@ static Image *ReadMNGImage(const ImageIn
                 if (!mng_info->magn_warning)
                   {
                     (void) ThrowException2(&image->exception,CoderError,
-                                           "Unknown MAGN method in MNG datastream",
+                                           "Unknown MAGN method in"
+                                           " MNG datastream",
                                            image->filename);
                     mng_info->magn_warning++;
                   }
 #ifdef MNG_OBJECT_BUFFERS
-              /* Magnify existing objects in the range magn_first to magn_last */
+              /* Magnify existing objects in the range magn_first
+                 to magn_last */
 #endif
               if (magn_first == 0 || magn_last == 0)
                 {
@@ -4684,7 +5040,7 @@ static Image *ReadMNGImage(const ImageIn
           if (!memcmp(type,mng_sBIT,4))
             {
               if (length < 4)
-                mng_info->have_global_sbit=False;
+                mng_info->have_global_sbit=MagickFalse;
               else
                 {
                   mng_info->global_sbit.gray=p[0];
@@ -4692,7 +5048,7 @@ static Image *ReadMNGImage(const ImageIn
                   mng_info->global_sbit.green=p[1];
                   mng_info->global_sbit.blue=p[2];
                   mng_info->global_sbit.alpha=p[3];
-                  mng_info->have_global_sbit=True;
+                  mng_info->have_global_sbit=MagickTrue;
                 }
             }
           if (!memcmp(type,mng_pHYs,4))
@@ -4702,10 +5058,10 @@ static Image *ReadMNGImage(const ImageIn
                   mng_info->global_x_pixels_per_unit=mng_get_long(p);
                   mng_info->global_y_pixels_per_unit=mng_get_long(&p[4]);
                   mng_info->global_phys_unit_type=p[8];
-                  mng_info->have_global_phys=True;
+                  mng_info->have_global_phys=MagickTrue;
                 }
               else
-                mng_info->have_global_phys=False;
+                mng_info->have_global_phys=MagickFalse;
             }
           if (!memcmp(type,mng_pHYg,4))
             {
@@ -4717,35 +5073,36 @@ static Image *ReadMNGImage(const ImageIn
             }
           if (!memcmp(type,mng_BASI,4))
             {
-              skip_to_iend=True;
+              skip_to_iend=MagickTrue;
               if (!mng_info->basi_warning)
                 (void) ThrowException2(&image->exception,CoderError,
                                        "BASI is not implemented yet",
                                        image->filename);
               mng_info->basi_warning++;
 #ifdef MNG_BASI_SUPPORTED
-              basi_width=(unsigned long) ((p[0] << 24) | (p[1] << 16) |
-                                          (p[2] << 8) | p[3]);
-              basi_height=(unsigned long) ((p[4] << 24) | (p[5] << 16) |
-                                           (p[6] << 8) | p[7]);
+              basi_width=(unsigned long) mng_get_long(p);
+                                          ((magick_uint32_t) p[1] << 16) |
+                                          ((magick_uint32_t) p[2] << 8) |
+                                          (magick_uint32_t) p[3]);
+              basi_height=(unsigned long) mng_get_long(&p[4]);
               basi_color_type=p[8];
               basi_compression_method=p[9];
               basi_filter_type=p[10];
               basi_interlace_method=p[11];
               if (length > 11)
-                basi_red=(p[12] << 8) & p[13];
+                basi_red=((magick_uint32_t) p[12] << 8) & (magick_uint32_t) p[13];
               else
                 basi_red=0;
               if (length > 13)
-                basi_green=(p[14] << 8) & p[15];
+                basi_green=((magick_uint32_t) p[14] << 8) & (magick_uint32_t) p[15];
               else
                 basi_green=0;
               if (length > 15)
-                basi_blue=(p[16] << 8) & p[17];
+                basi_blue=((magick_uint32_t) p[16] << 8) & (magick_uint32_t) p[17];
               else
                 basi_blue=0;
               if (length > 17)
-                basi_alpha=(p[18] << 8) & p[19];
+                basi_alpha=((magick_uint32_t) p[18] << 8) & (magick_uint32_t) p[19];
               else
                 {
                   if (basi_sample_depth == 16)
@@ -4768,8 +5125,7 @@ static Image *ReadMNGImage(const ImageIn
               )
             {
               /* Not an IHDR or JHDR chunk */
-              if (length)
-                MagickFreeMemory(chunk);
+              MagickFreeMemory(chunk);
               continue;
             }
           /* Process IHDR */
@@ -4777,23 +5133,25 @@ static Image *ReadMNGImage(const ImageIn
             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                                   "  Processing %c%c%c%c chunk",
                                   type[0],type[1],type[2],type[3]);
-          mng_info->exists[object_id]=True;
-          mng_info->viewable[object_id]=True;
+          mng_info->exists[object_id]=MagickTrue;
+          mng_info->viewable[object_id]=MagickTrue;
           if (mng_info->invisible[object_id])
             {
               if (logging)
                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                                       "  Skipping invisible object");
-              skip_to_iend=True;
+              skip_to_iend=MagickTrue;
               MagickFreeMemory(chunk);
               continue;
             }
 #ifdef MNG_INSERT_LAYERS
           if (length < 8)
           {
+            MagickFreeMemory(chunk);
             MngInfoFreeStruct(mng_info,&have_mng_structure);
             ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
           }
+
           image_width=mng_get_long(p);
           image_height=mng_get_long(&p[4]);
 #endif
@@ -4829,12 +5187,12 @@ static Image *ReadMNGImage(const ImageIn
                   mng_info->image=image;
                   if (term_chunk_found)
                     {
-                      image->start_loop=True;
+                      image->start_loop=MagickTrue;
                       image->iterations=mng_iterations;
-                      term_chunk_found=False;
+                      term_chunk_found=MagickFalse;
                     }
                   else
-                    image->start_loop=False;
+                    image->start_loop=MagickFalse;
                   /*
                     Make a background rectangle.
                   */
@@ -4849,8 +5207,10 @@ static Image *ReadMNGImage(const ImageIn
                   (void) SetImage(image,TransparentOpacity);
                   if (logging)
                     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                          "  Inserted transparent background layer, W=%lud, H=%lud",
-                                          mng_info->mng_width,mng_info->mng_height);
+                                          "  Inserted transparent background"
+                                          " layer, W=%lud, H=%lud",
+                                          mng_info->mng_width,
+                                          mng_info->mng_height);
                 }
             }
           /*
@@ -4878,12 +5238,12 @@ static Image *ReadMNGImage(const ImageIn
               mng_info->image=image;
               if (term_chunk_found)
                 {
-                  image->start_loop=True;
+                  image->start_loop=MagickTrue;
                   image->iterations=mng_iterations;
-                  term_chunk_found=False;
+                  term_chunk_found=MagickFalse;
                 }
               else
-                image->start_loop=False;
+                image->start_loop=MagickFalse;
               image->delay=0;
               image->columns=subframe_width;
               image->rows=subframe_height;
@@ -4892,16 +5252,19 @@ static Image *ReadMNGImage(const ImageIn
               image->page.x=mng_info->clip.left;
               image->page.y=mng_info->clip.top;
               image->background_color=mng_background_color;
-              image->matte=False;
+              image->matte=MagickFalse;
               (void) SetImage(image,OpaqueOpacity);
               if (logging)
                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                      "  Inserted background layer, L=%ld, R=%ld, T=%ld, B=%ld",
-                                      mng_info->clip.left,mng_info->clip.right,
-                                      mng_info->clip.top,mng_info->clip.bottom);
+                                      "  Inserted background layer,"
+                                      " L=%ld, R=%ld, T=%ld, B=%ld",
+                                      mng_info->clip.left,
+                                      mng_info->clip.right,
+                                      mng_info->clip.top,
+                                      mng_info->clip.bottom);
             }
 #endif /* MNG_INSERT_LAYERS */
-          first_mng_object=False;
+          first_mng_object=MagickFalse;
           if (GetPixels(image) != (PixelPacket *) NULL)
             {
               /*
@@ -4917,16 +5280,15 @@ static Image *ReadMNGImage(const ImageIn
               image=SyncNextImageInList(image);
             }
           mng_info->image=image;
-          if (!MagickMonitor(LoadImagesTag,TellBlob(image),GetBlobSize(image),
-                             exception))
+          if (!MagickMonitor(LoadImagesTag,TellBlob(image),GetBlobSize(image),exception))
             break;
           if (term_chunk_found)
             {
-              image->start_loop=True;
-              term_chunk_found=False;
+              image->start_loop=MagickTrue;
+              term_chunk_found=MagickFalse;
             }
           else
-            image->start_loop=False;
+            image->start_loop=MagickFalse;
           if (mng_info->framing_mode == 1 || mng_info->framing_mode == 3)
             {
               image->delay=frame_delay;
@@ -4940,11 +5302,13 @@ static Image *ReadMNGImage(const ImageIn
           image->page.y=mng_info->y_off[object_id];
           image->iterations=mng_iterations;
           /*
-            Seek back to the beginning of the IHDR or JHDR chunk's length field.
+            Seek back to the beginning of the IHDR or JHDR chunk's
+            length field.
           */
           if (logging)
             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                  "  Seeking back to beginning of %c%c%c%c chunk",
+                                  "  Seeking back to beginning of"
+                                  " %c%c%c%c chunk",
                                   type[0],type[1],
                                   type[2],type[3]);
           (void) SeekBlob(image,-((long) length+12),SEEK_CUR);
@@ -5009,7 +5373,8 @@ static Image *ReadMNGImage(const ImageIn
                   if (image->columns > 2)
                     magnified_width += mng_info->magn_mr-1;
                   if (image->columns > 3)
-                    magnified_width += (image->columns-3)*(mng_info->magn_mx-1);
+                    magnified_width += (image->columns-3)*
+                       (mng_info->magn_mx-1);
                 }
               if (mng_info->magn_methy == 1)
                 {
@@ -5043,7 +5408,6 @@ static Image *ReadMNGImage(const ImageIn
                     y;
 
                   register long
-                    i,
                     x;
 
                   register PixelPacket
@@ -5056,7 +5420,7 @@ static Image *ReadMNGImage(const ImageIn
                     *prev;
 
                   size_t
-                    length;
+                    row_length;
 
                   png_uint_16
                     magn_methx,
@@ -5095,6 +5459,8 @@ static Image *ReadMNGImage(const ImageIn
                       for (y=0; y < (long) image->rows; y++)
                         {
                           q=GetImagePixels(image,0,y,image->columns,1);
+                          if(q == (PixelPacket *) NULL)
+                            break;
                           for (x=(long) image->columns; x > 0; x--)
                             {
                               q->red=ScaleQuantumToShort(q->red);
@@ -5135,9 +5501,9 @@ static Image *ReadMNGImage(const ImageIn
                                           large_image->rows);
                   m=mng_info->magn_mt;
                   yy=0;
-                  length=MagickArraySize(image->columns,sizeof(PixelPacket));
-                  next=MagickAllocateMemory(PixelPacket *,length);
-                  prev=MagickAllocateMemory(PixelPacket *,length);
+                  row_length=MagickArraySize(image->columns,sizeof(PixelPacket));
+                  next=MagickAllocateMemory(PixelPacket *,row_length);
+                  prev=MagickAllocateMemory(PixelPacket *,row_length);
                   if ((prev == (PixelPacket *) NULL) ||
                       (next == (PixelPacket *) NULL))
                     {
@@ -5149,7 +5515,9 @@ static Image *ReadMNGImage(const ImageIn
                                            MemoryAllocationFailed,image)
                     }
                   n=GetImagePixels(image,0,0,image->columns,1);
-                  (void) memcpy(next,n,length);
+                  if(n == (PixelPacket *) NULL)
+                     return ((Image *) NULL);
+                  (void) memcpy(next,n,row_length);
                   for (y=0; y < (long) image->rows; y++)
                     {
                       if (y == 0)
@@ -5168,14 +5536,19 @@ static Image *ReadMNGImage(const ImageIn
                       if (y < (long) image->rows-1)
                         {
                           n=GetImagePixels(image,0,y+1,image->columns,1);
-                          (void) memcpy(next,n,length);
+                          if(n == (PixelPacket *) NULL)
+                             break;
+                          (void) memcpy(next,n,row_length);
                         }
                       for (i=0; i < m; i++, yy++)
                         {
                           assert(yy < (long) large_image->rows);
                           p=prev;
                           n=next;
-                          q=SetImagePixels(large_image,0,yy,large_image->columns,1);
+                          q=SetImagePixels(large_image,0,yy,
+                                           large_image->columns,1);
+                          if (q == (const PixelPacket *) NULL)
+                            break;
                           q+=(large_image->columns-image->columns);
                           for (x=(long) image->columns; x > 0; x--)
                             {
@@ -5198,15 +5571,20 @@ static Image *ReadMNGImage(const ImageIn
                                     {
                                       /* Interpolate */
                                       (*q).red=(QM) (((long) (2*i*((*n).red
-                                                                   -(*p).red)+m))/((long) (m*2))+(*p).red);
+                                               -(*p).red)+m))/
+                                               ((long) (m*2))+(*p).red);
                                       (*q).green=(QM) (((long) (2*i*((*n).green
-                                                                     -(*p).green)+m))/((long) (m*2))+(*p).green);
+                                                 -(*p).green)+m))/
+                                                 ((long) (m*2))+(*p).green);
                                       (*q).blue=(QM) (((long) (2*i*((*n).blue
-                                                                    -(*p).blue)+m))/((long) (m*2))+(*p).blue);
+                                                     -(*p).blue)+m))/
+                                                     ((long) (m*2))+(*p).blue);
                                       if (image->matte)
                                         (*q).opacity=(QM) (((long)
-                                                            (2*i*((*n).opacity-(*p).opacity)+m))
-                                                           /((long) (m*2))+(*p).opacity);
+                                                      (2*i*((*n).opacity-
+                                                      (*p).opacity)+m))
+                                                      /((long) (m*2))+
+                                                      (*p).opacity);
                                     }
                                   if (magn_methy == 4)
                                     {
@@ -5217,7 +5595,8 @@ static Image *ReadMNGImage(const ImageIn
                                         (*q).opacity=(*n).opacity+0;
                                     }
                                 }
-                              else /* if (magn_methy == 3 || magn_methy == 5) */
+                              else /* if (magn_methy == 3 ||
+                                          magn_methy == 5) */
                                 {
                                   /* Replicate nearest */
                                   if (i <= ((m+1) << 1))
@@ -5226,9 +5605,11 @@ static Image *ReadMNGImage(const ImageIn
                                     *q=(*n);
                                   if (magn_methy == 5)
                                     {
-                                      (*q).opacity=(QM) (((long) (2*i*((*n).opacity
-                                                                       -(*p).opacity)+m))/((long) (m*2))+
-                                                         (*p).opacity);
+                                      (*q).opacity=(QM) (
+                                             ((long) (2*i*((*n).opacity
+                                             -(*p).opacity)+m))/
+                                             ((long) (m*2))+
+                                             (*p).opacity);
                                     }
                                 }
                               n++;
@@ -5242,7 +5623,7 @@ static Image *ReadMNGImage(const ImageIn
                   MagickFreeMemory(prev);
                   MagickFreeMemory(next);
 
-                  length=image->columns;
+                  row_length=image->columns;
 
                   if (logging)
                     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
@@ -5263,18 +5644,23 @@ static Image *ReadMNGImage(const ImageIn
                   for (y=0; y < (long) image->rows; y++)
                     {
                       q=GetImagePixels(image,0,y,image->columns,1);
-                      p=q+(image->columns-length);
+                      if(q == (PixelPacket * ) NULL)
+                        break;
+                      p=q+(image->columns-row_length);
                       n=p+1;
-                      for (x=(long) (image->columns-length);
+                      for (x=(long) (image->columns-row_length);
                            x < (long) image->columns; x++)
                         {
-                          if (x == (long) (image->columns-length))
+                          if (x == (long) (image->columns-row_length))
                             m=mng_info->magn_ml;
-                          else if (magn_methx > 1 && x == (long) image->columns-2)
+                          else if (magn_methx > 1 &&
+                                   x == (long) image->columns-2)
                             m=mng_info->magn_mr;
-                          else if (magn_methx <= 1 && x == (long) image->columns-1)
+                          else if (magn_methx <= 1 &&
+                                   x == (long) image->columns-1)
                             m=mng_info->magn_mr;
-                          else if (magn_methx > 1 && x == (long) image->columns-1)
+                          else if (magn_methx > 1 &&
+                                   x == (long) image->columns-1)
                             m=1;
                           else
                             m=mng_info->magn_mx;
@@ -5292,15 +5678,22 @@ static Image *ReadMNGImage(const ImageIn
                                   else
                                     {
                                       /* Interpolate */
-                                      (*q).red=(QM) ((2*i*((*n).red-(*p).red)+m)
-                                                     /((long) (m*2))+(*p).red);
-                                      (*q).green=(QM) ((2*i*((*n).green-(*p).green)
-                                                        +m)/((long) (m*2))+(*p).green);
-                                      (*q).blue=(QM) ((2*i*((*n).blue-(*p).blue)+m)
-                                                      /((long) (m*2))+(*p).blue);
+                                      (*q).red=(QM) ((2*i*((*n).red-
+                                                     (*p).red)+m)
+                                                     /((long) (m*2))+
+                                                     (*p).red);
+                                      (*q).green=(QM) ((2*i*((*n).green-
+                                                       (*p).green)
+                                                       +m)/((long) (m*2))+
+                                                       (*p).green);
+                                      (*q).blue=(QM) ((2*i*((*n).blue-
+                                                      (*p).blue)+m)
+                                                      /((long) (m*2))+
+                                                      (*p).blue);
                                       if (image->matte)
                                         (*q).opacity=(QM) ((2*i*((*n).opacity
-                                                                 -(*p).opacity)+m)/((long) (m*2))
+                                                           -(*p).opacity)+m)/
+                                                           ((long) (m*2))
                                                            +(*p).opacity);
                                     }
                                   if (magn_methx == 4)
@@ -5312,7 +5705,8 @@ static Image *ReadMNGImage(const ImageIn
                                         (*q).opacity=(*n).opacity+0;
                                     }
                                 }
-                              else /* if (magn_methx == 3 || magn_methx == 5) */
+                              else /* if (magn_methx == 3 ||
+                                      magn_methx == 5) */
                                 {
                                   /* Replicate nearest */
                                   if (i <= ((m+1) << 1))
@@ -5323,7 +5717,8 @@ static Image *ReadMNGImage(const ImageIn
                                     {
                                       /* Interpolate */
                                       (*q).opacity=(QM) ((2*i*((*n).opacity
-                                                               -(*p).opacity)+m) /((long) (m*2))
+                                                         -(*p).opacity)+m)/
+                                                         ((long) (m*2))
                                                          +(*p).opacity);
                                     }
                                 }
@@ -5344,6 +5739,8 @@ static Image *ReadMNGImage(const ImageIn
                       for (y=0; y < (long) image->rows; y++)
                         {
                           q=GetImagePixels(image,0,y,image->columns,1);
+                          if(q == (PixelPacket *) NULL)
+                            break;
                           for (x=(long) image->columns; x > 0; x--)
                             {
                               q->red=ScaleShortToQuantum(q->red);
@@ -5369,7 +5766,8 @@ static Image *ReadMNGImage(const ImageIn
           crop_box.left=mng_info->image_box.left+mng_info->x_off[object_id];
           crop_box.right=mng_info->image_box.right+mng_info->x_off[object_id];
           crop_box.top=mng_info->image_box.top+mng_info->y_off[object_id];
-          crop_box.bottom=mng_info->image_box.bottom+mng_info->y_off[object_id];
+          crop_box.bottom=mng_info->image_box.bottom+
+                          mng_info->y_off[object_id];
           crop_box=mng_minimum_box(crop_box,mng_info->clip);
           crop_box=mng_minimum_box(crop_box,mng_info->frame);
           crop_box=mng_minimum_box(crop_box,mng_info->object_clip[object_id]);
@@ -5440,81 +5838,6 @@ static Image *ReadMNGImage(const ImageIn
 #endif
         }
 
-#if (QuantumDepth == 16)  /* TO DO: treat Q:32 */
-      /* Determine if bit depth can be reduced from 16 to 8.
-       * Note that the method GetImageDepth doesn't check background
-       * and doesn't handle PseudoClass specially.  Also it uses
-       * multiplication and division by 257 instead of shifting, so
-       * might be slower.
-       */
-      if (mng_info->optimize && image->depth == 16)
-        {
-          int
-            ok_to_reduce;
-
-          const PixelPacket
-            *p;
-
-          ok_to_reduce=((((image->background_color.red >> 8) & 0xff)
-                         == (image->background_color.red & 0xff)) &&
-                        (((image->background_color.green >> 8) & 0xff)
-                         == (image->background_color.green & 0xff)) &&
-                        (((image->background_color.blue >> 8) & 0xff)
-                         == (image->background_color.blue & 0xff)));
-          if (ok_to_reduce && image->storage_class == PseudoClass)
-            {
-              int index;
-
-              for (index=0; index < (long) image->colors; index++)
-                {
-                  ok_to_reduce=((((image->colormap[index].red >> 8) & 0xff)
-                                 == (image->colormap[index].red & 0xff)) &&
-                                (((image->colormap[index].green >> 8) & 0xff)
-                                 == (image->colormap[index].green & 0xff)) &&
-                                (((image->colormap[index].blue >> 8) & 0xff)
-                                 == (image->colormap[index].blue & 0xff)));
-                  if (!ok_to_reduce)
-                    break;
-                }
-            }
-          if (ok_to_reduce && image->storage_class != PseudoClass)
-            {
-              long
-                y;
-
-              register long
-                x;
-
-              for (y=0; y < (long) image->rows; y++)
-                {
-                  p=AcquireImagePixels(image,0,y,image->columns,1,
-                                       &image->exception);
-                  if (p == (const PixelPacket *) NULL)
-                    break;
-                  for (x=(long) image->columns; x > 0; x--)
-                    {
-                      ok_to_reduce=((((p->red >> 8) & 0xff) == (p->red & 0xff)) &&
-                                    (((p->green >> 8) & 0xff) == (p->green & 0xff)) &&
-                                    (((p->blue >> 8) & 0xff) == (p->blue & 0xff)) &&
-                                    (((!image->matte ||
-                                       ((p->opacity >> 8) & 0xff) == (p->opacity & 0xff)))));
-                      if (!ok_to_reduce)
-                        break;
-                      p++;
-                    }
-                  if (x != 0)
-                    break;
-                }
-            }
-          if (ok_to_reduce)
-            {
-              image->depth=8;
-              if (logging)
-                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                      "  Reducing PNG bit depth to 8 without loss of info");
-            }
-        }
-#endif
       /*
         Transfer most significant exception to exception argument
         FIXME: should status be used to terminate processing?
@@ -5543,7 +5866,8 @@ static Image *ReadMNGImage(const ImageIn
       */
       if (logging)
         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                              "  No images found.  Inserting a background layer.");
+                              "  No images found.  Inserting a"
+                              " background layer.");
       if (GetPixels(image) != (PixelPacket *) NULL)
         {
           /*
@@ -5568,7 +5892,7 @@ static Image *ReadMNGImage(const ImageIn
       image->page.x=0;
       image->page.y=0;
       image->background_color=mng_background_color;
-      image->matte=False;
+      image->matte=MagickFalse;
       if (!image_info->ping)
         (void) SetImage(image,OpaqueOpacity);
       mng_info->image_found++;
@@ -5576,16 +5900,19 @@ static Image *ReadMNGImage(const ImageIn
 #endif
   image->iterations=mng_iterations;
   if (mng_iterations == 1)
-    image->start_loop=True;
+    image->start_loop=MagickTrue;
   while (image->previous != (Image *) NULL)
     {
       image_count++;
       if (image_count > 10*mng_info->image_found)
         {
           if (logging)
-            (void) LogMagickEvent(CoderEvent,GetMagickModule(),"  No beginning");
+            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                  "  No beginning");
+          MngInfoFreeStruct(mng_info,&have_mng_structure);
           (void) ThrowException2(&image->exception,(ExceptionType) CoderError,
-                                 "Linked list is corrupted, beginning of list not found",
+                                 "Linked list is corrupted,"
+                                 " beginning of list not found",
                                  image_info->filename);
           return((Image *) NULL);
         }
@@ -5593,9 +5920,11 @@ static Image *ReadMNGImage(const ImageIn
       if (image->next == (Image *) NULL)
         {
           if (logging)
-            (void) LogMagickEvent(CoderEvent,GetMagickModule(),"  Corrupt list");
+            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                  "  Corrupt list");
           (void) ThrowException2(&image->exception,(ExceptionType) CoderError,
-                                 "Linked list is corrupted; next_image is NULL",
+                                 "Linked list is corrupted;"
+                                 " next_image is NULL",
                                  image_info->filename);
         }
     }
@@ -5606,7 +5935,8 @@ static Image *ReadMNGImage(const ImageIn
         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                               "  First image null");
       (void) ThrowException2(&image->exception,(ExceptionType) CoderError,
-                             "image->next for first image is NULL but shouldn't be.",
+                             "image->next for first image is NULL but"
+                             " shouldn't be.",
                              image_info->filename);
     }
   if (!mng_info->image_found)
@@ -5625,7 +5955,7 @@ static Image *ReadMNGImage(const ImageIn
   if (mng_info->ticks_per_second)
     final_delay=100*final_delay/mng_info->ticks_per_second;
   else
-    image->start_loop=True;
+    image->start_loop=MagickTrue;
   /* Find final nonzero image delay */
   final_image_delay=0;
   while (image->next != (Image *) NULL)
@@ -5674,7 +6004,8 @@ static Image *ReadMNGImage(const ImageIn
         scene;
 
       if (logging)
-        (void) LogMagickEvent(CoderEvent,GetMagickModule(),"  Coalesce Images");
+        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                              "  Coalesce Images");
       scene=image->scene;
       next_image=CoalesceImages(image,&image->exception);
       if (next_image == (Image *) NULL)
@@ -5734,13 +6065,14 @@ static Image *ReadMNGImage(const ImageIn
   while (image->previous != (Image *) NULL)
     image=image->previous;
   MngInfoFreeStruct(mng_info,&have_mng_structure);
-  have_mng_structure=False;
+  have_mng_structure=MagickFalse;
   if (logging)
     (void) LogMagickEvent(CoderEvent,GetMagickModule(),"exit ReadMNGImage()");
   return(image);
 }
-#else /* PNG_LIBPNG_VER > 95 */
-static Image *ReadPNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
+#else /* PNG_LIBPNG_VER > 10011 */
+static Image *ReadPNGImage(const ImageInfo *image_info,
+                           ExceptionInfo *exception)
 {
   printf("Your PNG library is too old: You have libpng-%s\n",
      PNG_LIBPNG_VER_STRING);
@@ -5748,11 +6080,12 @@ static Image *ReadPNGImage(const ImageIn
     image_info->filename);
   return (Image *) NULL;
 }
-static Image *ReadMNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
+static Image *ReadMNGImage(const ImageInfo *image_info,
+                           ExceptionInfo *exception)
 {
   return (ReadPNGImage(image_info,exception));
 }
-#endif /* PNG_LIBPNG_VER > 95 */
+#endif /* PNG_LIBPNG_VER > 10011 */
 #endif
 
 /*
@@ -5971,8 +6304,8 @@ ModuleExport void UnregisterPNGImage(voi
 %  A description of each parameter follows.
 %
 %    o status: Method WriteMNGImage return True if the image is written.
-%      False is returned is there is a memory shortage or if the image file
-%      fails to write.
+%      MagickFalse is returned is there is a memory shortage or if the
+%      image file fails to write.
 %
 %    o image_info: Specifies a pointer to a ImageInfo structure.
 %
@@ -6030,27 +6363,13 @@ ModuleExport void UnregisterPNGImage(voi
 */
 
 
-#if (PNG_LIBPNG_VER > 99 && PNG_LIBPNG_VER < 10007)
-/* This function became available in libpng version 1.0.6g. */
-static void
-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=NULL;
-  png_ptr->zbuf_size=(png_size_t) size;
-  png_ptr->zbuf=(png_bytep) png_malloc(png_ptr, size);
-  if (!png_ptr->zbuf)
-    png_error(png_ptr,"Unable to allocate zbuf");
-}
-#endif
-
 static void
 png_write_raw_profile(const ImageInfo *image_info,png_struct *ping,
                       png_info *ping_info, const char *profile_type,
-                      const char *profile_description, const unsigned char *profile_data,
+                      const char *profile_description,
+                      const unsigned char *profile_data,
                       png_uint_32 length)
 {
-#if (PNG_LIBPNG_VER > 10005)
   png_textp
     text;
 
@@ -6069,40 +6388,28 @@ png_write_raw_profile(const ImageInfo *i
 
   unsigned char
     hex[16]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
-#endif
 
-#if (PNG_LIBPNG_VER <= 10005)
-  if (image_info->verbose)
-    (void) printf("Not ");
-  (void) image_info;
-  (void) ping;
-  (void) ping_info;
-  (void) profile_type;
-  (void) profile_description;
-  (void) profile_data;
-  (void) length;
-#endif
   if (image_info->verbose)
     {
       (void) printf("writing raw profile: type=%.1024s, length=%lu\n",
-                    profile_type, length);
+                    profile_type, (unsigned long)length);
     }
-#if (PNG_LIBPNG_VER > 10005)
-# if PNG_LIBPNG_VER >= 14000
+#if PNG_LIBPNG_VER >= 14000
   text=(png_textp) png_malloc(ping,(png_alloc_size_t) sizeof(png_text));
-# else
+#else
   text=(png_textp) png_malloc(ping,(png_size_t) sizeof(png_text));
-# endif
-  description_length=strlen((const char *) profile_description);
+#endif
+  description_length=(png_uint_32) strlen((const char *) profile_description);
   allocated_length=(png_uint_32) (length*2 + (length >> 5) + 20
                                   + description_length);
-# if PNG_LIBPNG_VER >= 14000
-  text[0].text=(png_charp) png_malloc(ping, (png_alloc_size_t) allocated_length);
-  text[0].key=(png_charp) png_malloc(ping, (png_alloc_size_t) 80);
-# else
-  text[0].text=(png_charp) png_malloc(ping, (png_size_t) allocated_length);
-  text[0].key=(png_charp) png_malloc(ping, (png_size_t) 80);
-# endif
+#if PNG_LIBPNG_VER >= 14000
+   text[0].text=(png_charp) png_malloc(ping,
+      (png_alloc_size_t) allocated_length);
+   text[0].key=(png_charp) png_malloc(ping, (png_alloc_size_t) 80);
+#else
+   text[0].text=(png_charp) png_malloc(ping, (png_size_t) allocated_length);
+   text[0].key=(png_charp) png_malloc(ping, (png_size_t) 80);
+#endif
   text[0].key[0]='\0';
   (void) strcat(text[0].key, "Raw profile type ");
   (void) strncat(text[0].key, (const char *) profile_type, 61);
@@ -6112,7 +6419,7 @@ png_write_raw_profile(const ImageInfo *i
   (void) strcpy(dp,(const char *) profile_description);
   dp+=description_length;
   *dp++='\n';
-  (void) sprintf(dp,"%8lu ",length);
+  (void) sprintf(dp,"%8lu ",(unsigned long)length);
   dp+=8;
   for (i=0; i < (long) length; i++)
     {
@@ -6132,12 +6439,27 @@ png_write_raw_profile(const ImageInfo *i
   png_free(ping,text[0].text);
   png_free(ping,text[0].key);
   png_free(ping,text);
-#endif
 }
 
-static unsigned int WriteOnePNGImage(MngInfo *mng_info,
-                                     const ImageInfo *image_info,Image *image)
+static MagickPassFail WriteOnePNGImage(MngInfo *mng_info,
+                                       const ImageInfo *image_info,Image *imagep)
 {
+  const char
+    *gm_vers,
+    *libpng_runv,
+    *libpng_vers,
+    *zlib_runv,
+    *zlib_vers;
+
+#ifdef HasLCMS
+  char
+    lcms_vers[32];
+#endif
+
+  Image
+    * volatile imagev = imagep,  /* Use only 'imagev' before setjmp() */
+    *image;                      /* Use only 'image' after setjmp() */
+
   /* Write one PNG image */
   const ImageAttribute
     *attribute;
@@ -6147,21 +6469,41 @@ static unsigned int WriteOnePNGImage(Mng
 
   int
     num_passes,
-    pass;
+    pass,
+    ping_bit_depth = 0,
+    ping_colortype = 0,
+    ping_interlace_method = 0,
+    ping_compression_method = 0;
+
+  volatile int
+    ping_filter_method = 0,
+    ping_num_trans = 0,
+    ping_valid_trns = 0;
+
+  volatile png_bytep
+    ping_trans_alpha = NULL;
 
   png_colorp
     palette;
 
+  png_color_16
+    ping_background,
+    ping_trans_color;
+
   png_info
     *ping_info;
 
   png_struct
     *ping;
 
+  png_uint_32
+    ping_width,
+    ping_height;
+
   long
     y;
 
-  register IndexPacket
+  register const IndexPacket
     *indexes;
 
   register long
@@ -6172,9 +6514,11 @@ static unsigned int WriteOnePNGImage(Mng
     *png_pixels;
 
   unsigned int
+    image_colors,
+    image_depth,
+    image_matte,
     logging,
-    matte,
-    not_valid;
+    matte;
 
   unsigned long
     quantum_size,  /* depth for ExportImage */
@@ -6187,67 +6531,85 @@ static unsigned int WriteOnePNGImage(Mng
   logging=LogMagickEvent(CoderEvent,GetMagickModule(),
                          "  enter WriteOnePNGImage()");
 
-  /*
-    Make sure that image is in an RGB type space.
-  */
-  (void) TransformColorspace(image,RGBColorspace);
-  
-  /*
-    Analyze image to be written.
-  */
-  if (!GetImageCharacteristics(image,&characteristics,
-                               (OptimizeType == image_info->type),
-                               &image->exception))
-    {
-      CloseBlob(image);
-      return MagickFail;
-    }
+  if (imagev == (Image *) NULL)
+    return(MagickFalse);
 
-  if (image->storage_class == PseudoClass &&
-      image->colors <= 256)
-    {
-      mng_info->IsPalette=MagickTrue;
-      image->depth=8;
-    }
-
-  if (mng_info->write_png8 || mng_info->write_png24 || mng_info->write_png32)
-    image->depth=8;
-  else if (image->depth < 8)
-    image->depth=8;
-  else if (image->depth > 8 && image->depth < 16)
-    image->depth=16;
-  else if (image->depth > 16)
-    image->depth=16;
+  /* Define these outside of the following "if logging()" block so they will
+   * show in debuggers.
+   */
+    gm_vers=MagickLibVersionText;
+#ifdef HasLCMS
+    (void) sprintf(lcms_vers,"%.4d",LCMS_VERSION);
+#endif
+    libpng_runv=png_get_libpng_ver(NULL);
+    libpng_vers=PNG_LIBPNG_VER_STRING;
+    zlib_runv=zlib_version;
+    zlib_vers=ZLIB_VERSION;
+
+  if (logging != MagickFalse)
+    {
+       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+            "    GM version     = %.31s", gm_vers);
+       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+            "    Libpng version = %.31s", libpng_vers);
+       if (LocaleCompare(libpng_vers,libpng_runv) != 0)
+       {
+       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+            "      running with   %.31s", libpng_runv);
+       }
+       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+            "    Zlib version   = %.31s", zlib_vers);
+       if (LocaleCompare(zlib_vers,zlib_runv) != 0)
+       {
+       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+            "      running with   %.31s", zlib_runv);
+       }
+#ifdef HasLCMS
+       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+            "    LCMS version   = %.31s", lcms_vers);
+#endif
+    }
+  /* Initialize some stuff */
+  ping_background.red = 0;
+  ping_background.green = 0;
+  ping_background.blue = 0;
+  ping_background.gray = 0;
+  ping_background.index = 0;
+
+  ping_trans_color.red=0;
+  ping_trans_color.green=0;
+  ping_trans_color.blue=0;
+  ping_trans_color.gray=0;
 
   /*
     Allocate the PNG structures
   */
 #ifdef PNG_USER_MEM_SUPPORTED
-  ping=png_create_write_struct_2(PNG_LIBPNG_VER_STRING,image,
+  ping=png_create_write_struct_2(PNG_LIBPNG_VER_STRING,imagev,
                                  PNGErrorHandler,PNGWarningHandler,
                                  (void *) NULL,
                                  (png_malloc_ptr) png_IM_malloc,
                                  (png_free_ptr) png_IM_free);
 #else
-  ping=png_create_write_struct(PNG_LIBPNG_VER_STRING,image,
+  ping=png_create_write_struct(PNG_LIBPNG_VER_STRING,imagev,
                                PNGErrorHandler,PNGWarningHandler);
 #endif
   if (ping == (png_struct *) NULL)
-    ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image);
+    ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,imagev);
   ping_info=png_create_info_struct(ping);
   if (ping_info == (png_info *) NULL)
     {
       png_destroy_write_struct(&ping,(png_info **) NULL);
-      ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image);
+      ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,imagev);
     }
-  png_set_write_fn(ping,image,png_put_data,png_flush_data);
+  png_set_write_fn(ping,imagev,png_put_data,png_flush_data);
   png_pixels=(unsigned char *) NULL;
 
 #if defined(PNG_SETJMP_NOT_THREAD_SAFE)
   AcquireSemaphoreInfo(&png_semaphore);
 #endif
 
-  if (setjmp(ping->jmpbuf))
+  if (setjmp(png_jmpbuf(ping)))
     {
       /*
         PNG write failed.
@@ -6261,130 +6623,142 @@ static unsigned int WriteOnePNGImage(Mng
 #if defined(PNG_SETJMP_NOT_THREAD_SAFE)
       LiberateSemaphoreInfo(&png_semaphore);
 #endif
-      return(False);
+      return(MagickFail);
     }
+
+/* { For navigation to end of setjmp-controlled block */
+
+#ifdef PNG_BENIGN_ERRORS_SUPPORTED
+  /* Allow benign errors */
+  png_set_benign_errors(ping, 1);
+#endif
+
+  image=imagev;  /* Use 'image' after this point for optimization */
+
+  /*
+    Make sure that image is in an RGB type space.
+  */
+  if (!TransformColorspace(image,RGBColorspace))
+    {
+      CloseBlob(image);
+#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
+      LiberateSemaphoreInfo(&png_semaphore);
+#endif
+      return MagickFail;
+    }
+
+  /*
+    Analyze image to be written.
+  */
+  if (!GetImageCharacteristics(image,&characteristics,
+                               (OptimizeType == image_info->type),
+                               &image->exception))
+    {
+      CloseBlob(image);
+#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
+      LiberateSemaphoreInfo(&png_semaphore);
+#endif
+      return MagickFail;
+    }
+
+  if (logging)
+    {
+      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                            "  Image Characteristics:\n"
+                            "    CMYK:       %u\n"
+                            "    Grayscale:  %u\n"
+                            "    Monochrome: %u\n"
+                            "    Opaque:     %u\n"
+                            "    Palette:    %u",
+                            characteristics.cmyk,
+                            characteristics.grayscale ,
+                            characteristics.monochrome,
+                            characteristics.opaque,
+                            characteristics.palette);
+    }
+
+  if (image->storage_class == PseudoClass)
+    image_colors=image->colors;
+  else
+    image_colors=0;
+
+  image_depth=image->depth;
+  image_matte=image->matte;
+
+  if (image->storage_class == PseudoClass &&
+      image_colors <= 256)
+    {
+      mng_info->IsPalette=MagickTrue;
+      image_depth=8;
+    }
+
+  if (mng_info->write_png8 || mng_info->write_png24 || mng_info->write_png32)
+    image_depth=8;
+
+  else if (mng_info->write_png48 || mng_info->write_png64)
+      image_depth=16;
+
+  else if (image_depth < 8)
+    image_depth=8;
+
+  else if (image_depth > 8)
+    image_depth=16;
+
   /*
     Prepare PNG for writing.
   */
+
 #if defined(PNG_MNG_FEATURES_SUPPORTED)
   if (mng_info->write_mng)
+  {
+# ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
+    /* Disable new libpng-1.5.10 feature when writing a MNG */
+    png_set_check_for_invalid_index (ping, 0);
+# endif
     (void) png_permit_mng_features(ping,PNG_ALL_MNG_FEATURES);
+  }
 #else
 # ifdef PNG_WRITE_EMPTY_PLTE_SUPPORTED
   if (mng_info->write_mng)
-    png_permit_empty_plte(ping,True);
+    png_permit_empty_plte(ping,MagickTrue);
 # endif
 #endif
   x=0;
-  ping_info->width=image->columns;
-  ping_info->height=image->rows;
+  ping_width=image->columns;
+  ping_height=image->rows;
   if (logging)
     {
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                            "    width=%lu",ping_info->width);
+                            "    width=%lu",
+                            (unsigned long)ping_width);
+      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                            "    height=%lu",
+                            (unsigned long)ping_height);
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                            "    height=%lu",ping_info->height);
+                            "    image->depth=%u",image_depth);
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                            "    image->depth=%u",image->depth);
+                            "  image_colors=%u",image_colors);
     }
 
 
-  quantum_size=(image->depth > 8) ? 16:8;
+  quantum_size=(image_depth > 8) ? 16:8;
 
-  save_image_depth=image->depth;
-  ping_info->bit_depth=(png_byte) save_image_depth;
+  save_image_depth=image_depth;
+  ping_bit_depth=(png_byte) save_image_depth;
   if (logging)
     {
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                            "    ping_info->bit_depth=%u",ping_info->bit_depth);
-    }
-#if defined(PNG_pHYs_SUPPORTED)
-  if ((image->x_resolution != 0) && (image->y_resolution != 0) &&
-      (!mng_info->write_mng || !mng_info->equal_physs))
-    {
-      int
-        unit_type;
-
-      png_uint_32
-        x_resolution,
-        y_resolution;
-
-      if (image->units == PixelsPerInchResolution)
-        {
-          unit_type=PNG_RESOLUTION_METER;
-          x_resolution=(png_uint_32) (100.0*image->x_resolution/2.54);
-          y_resolution=(png_uint_32) (100.0*image->y_resolution/2.54);
-        }
-      else if (image->units == PixelsPerCentimeterResolution)
-        {
-          unit_type=PNG_RESOLUTION_METER;
-          x_resolution=(png_uint_32) (100.0*image->x_resolution);
-          y_resolution=(png_uint_32) (100.0*image->y_resolution);
-        }
-      else
-        {
-          unit_type=PNG_RESOLUTION_UNKNOWN;
-          x_resolution=(png_uint_32) image->x_resolution;
-          y_resolution=(png_uint_32) image->y_resolution;
-        }
-      png_set_pHYs(ping,ping_info,x_resolution,y_resolution,unit_type);
-      if (logging)
-        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                              "    Setting up pHYs chunk");
-    }
-#endif
-#if defined(PNG_oFFs_SUPPORTED)
-  if (mng_info->write_mng == 0 && (image->page.x || image->page.y))
-    {
-      png_set_oFFs(ping,ping_info,(png_int_32) image->page.x,
-                   (png_int_32) image->page.y, 0);
-      if (logging)
-        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                              "    Setting up oFFs chunk");
-    }
-#endif
-  if (image->matte && (!mng_info->adjoin || !mng_info->equal_backgrounds))
-    {
-      png_color_16
-        background;
-
-      if (image->depth < QuantumDepth)
-        {
-          int
-            maxval;
-
-          maxval=(1 << image->depth)-1;
-          background.red=(png_uint_16)
-            (maxval*image->background_color.red/MaxRGB);
-          background.green=(png_uint_16)
-            (maxval*image->background_color.green/MaxRGB);
-          background.blue=(png_uint_16)
-            (maxval*image->background_color.blue/MaxRGB);
-          background.gray=(png_uint_16)
-            (maxval*PixelIntensity(&image->background_color)/MaxRGB);
-        }
-      else
-        {
-          background.red=image->background_color.red;
-          background.green=image->background_color.green;
-          background.blue=image->background_color.blue;
-          background.gray=
-            (png_uint_16) PixelIntensity(&image->background_color);
-        }
-      background.index=(png_byte) background.gray;
-      if (logging)
-        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                              "    Setting up bKGD chunk");
-      png_set_bKGD(ping,ping_info,&background);
+                            "    ping_bit_depth=%u",
+                            ping_bit_depth);
     }
   /*
     Select the color type.
   */
-  matte=image->matte;
+  matte=image_matte;
   if (mng_info->write_png8)
     {
-      ping_info->color_type=PNG_COLOR_TYPE_PALETTE;
-      ping_info->bit_depth=8;
+      ping_colortype=PNG_COLOR_TYPE_PALETTE;
+      ping_bit_depth=8;
       {
         /* TO DO: make this a function cause it's used twice, except
            for reducing the sample depth from 8. */
@@ -6393,11 +6767,10 @@ static unsigned int WriteOnePNGImage(Mng
           quantize_info;
 
         unsigned long
-          number_colors,
-          save_number_colors;
+          number_colors;
 
-        number_colors=image->colors;
-        if (number_colors == 0 || number_colors > 256)
+        number_colors=image_colors;
+        if ((number_colors == 0) || (number_colors > 256))
           {
             GetQuantizeInfo(&quantize_info);
             quantize_info.dither=image_info->dither;
@@ -6406,185 +6779,180 @@ static unsigned int WriteOnePNGImage(Mng
             number_colors=image->colors;
             if (logging)
               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                    "    Colors quantized to %ld",number_colors);
+                                    "    Colors quantized to %ld",
+                                    number_colors);
+            image_colors=image->colors;
           }
-        if (matte)
-          ping_info->valid|=PNG_INFO_tRNS;
+
         /*
           Set image palette.
         */
-        ping_info->color_type=PNG_COLOR_TYPE_PALETTE;
-        ping_info->valid|=PNG_INFO_PLTE;
-#if defined(PNG_SORT_PALETTE)
-        save_number_colors=image->colors;
-        (void) CompressColormapTransFirst(image);
-        number_colors=image->colors;
-        image->colors=save_number_colors;
-#endif
+
+        ping_colortype=PNG_COLOR_TYPE_PALETTE;
+
+        if (logging)
+          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                "  Setting up PLTE chunk with %d colors",
+                                (int) number_colors);
         palette=MagickAllocateMemory(png_color *,
                                      number_colors*sizeof(png_color));
         if (palette == (png_color *) NULL)
-          ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,
-                               image);
-        if (logging)
-          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                "  Setting up PLTE chunk");
-        for (i=0; i < (long) number_colors; i++)
-          {
-            palette[i].red=ScaleQuantumToChar(image->colormap[i].red);
-            palette[i].green=ScaleQuantumToChar(image->colormap[i].green);
-            palette[i].blue=ScaleQuantumToChar(image->colormap[i].blue);
-            if (logging)
-              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+          png_error(ping, "Could not allocate palette");
+        else
+        {
+          for (i=0; i < (long) number_colors; i++)
+            {
+              palette[i].red=ScaleQuantumToChar(image->colormap[i].red);
+              palette[i].green=ScaleQuantumToChar(image->colormap[i].green);
+              palette[i].blue=ScaleQuantumToChar(image->colormap[i].blue);
+              if (logging)
+                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
 #if QuantumDepth == 8
-                                    "    %3ld (%3d,%3d,%3d)",
+                                      "    %3ld (%3d,%3d,%3d)",
 #else
-                                    "    %5ld (%5d,%5d,%5d)",
+                                      "    %5ld (%5d,%5d,%5d)",
 #endif
-                                    i,palette[i].red,palette[i].green,palette[i].blue);
+                                      i,palette[i].red,palette[i].green,
+                                      palette[i].blue);
 
-          }
-        png_set_PLTE(ping,ping_info,palette,(int) number_colors);
-#if (PNG_LIBPNG_VER > 10008)
-        MagickFreeMemory(palette);
-#endif
+            }
+          png_set_PLTE(ping,ping_info,palette,(int) number_colors);
+          MagickFreeMemory(palette);
+        }
         /*
           Identify which colormap entry is transparent.
         */
-        ping_info->trans=MagickAllocateMemory(unsigned char *,number_colors);
-        if (ping_info->trans == (unsigned char *) NULL)
-          ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,
-                               image);
-        assert(number_colors <= 256);
-        for (i=0; i < (long) number_colors; i++)
-          ping_info->trans[i]=255;
-        for (y=0; y < (long) image->rows; y++)
+        ping_trans_alpha=MagickAllocateMemory(unsigned char *, number_colors);
+        if (ping_trans_alpha == (unsigned char *) NULL)
+          png_error(ping, "Could not allocate ping_trans_alpha");
+        else
           {
-            register const PixelPacket
-              *p=NULL;
-
-            p=AcquireImagePixels(image,0,y,image->columns,1,
-                                 &image->exception);
-            if (p == (const PixelPacket *) NULL)
-              break;
-            indexes=GetIndexes(image);
-            for (x=0; x < (long) image->columns; x++)
+            assert(number_colors <= 256);
+            for (i=0; i < (long) number_colors; i++)
+              ping_trans_alpha[i]=255;
+            for (y=0; y < (long) image->rows; y++)
               {
-                if (p->opacity != OpaqueOpacity)
+                register const PixelPacket
+                  *p=NULL;
+
+                p=AcquireImagePixels(image,0,y,image->columns,1,
+                                     &image->exception);
+                if (p == (const PixelPacket *) NULL)
+                  break;
+                indexes=GetIndexes(image);
+                for (x=0; x < (long) image->columns; x++)
                   {
-                    IndexPacket
-                      index;
+                    if (p->opacity != OpaqueOpacity)
+                      {
+                        IndexPacket
+                          index;
 
-                    index=indexes[x];
-                    assert((unsigned long) index < number_colors);
-                    ping_info->trans[index]=(png_byte) (255-
-                                                        ScaleQuantumToChar(p->opacity));
+                        index=indexes[x];
+                        assert((unsigned long) index < number_colors);
+                        ping_trans_alpha[index]=(png_byte) (255-
+                                                ScaleQuantumToChar(p->opacity));
+                      }
+                    p++;
                   }
-                p++;
               }
+            ping_num_trans=0;
+            for (i=0; i < (long) number_colors; i++)
+              if (ping_trans_alpha[i] != 255)
+                ping_num_trans=(unsigned short) (i+1);
+            if (ping_num_trans != 0)
+              ping_valid_trns = 1;
+            MagickFreeMemory(ping_trans_alpha);
           }
-        ping_info->num_trans=0;
-        for (i=0; i < (long) number_colors; i++)
-          if (ping_info->trans[i] != 255)
-            ping_info->num_trans=(unsigned short) (i+1);
-        if (ping_info->num_trans == 0)
-          ping_info->valid&=(~PNG_INFO_tRNS);
-        if (!(ping_info->valid & PNG_INFO_tRNS))
-          ping_info->num_trans=0;
-        if (ping_info->num_trans == 0)
-          MagickFreeMemory(ping_info->trans);
         /*
           Identify which colormap entry is the background color.
         */
         for (i=0; i < (long) Max(number_colors-1,1); i++)
-          if (RGBColorMatchExact(ping_info->background,image->colormap[i]))
+          if (RGBColorMatchExact(ping_background,image->colormap[i]))
             break;
-        ping_info->background.index=(png_uint_16) i;
+        ping_background.index=(png_uint_16) i;
       }
-      if (image->matte)
+      if (image_matte)
         {
           /* TO DO: reduce to binary transparency */
         }
     }
-  else if (mng_info->write_png24)
+  else if (mng_info->write_png24 || mng_info->write_png48)
     {
-      image->matte=False;
-      ping_info->color_type=PNG_COLOR_TYPE_RGB;
+      image_matte=MagickFalse;
+      ping_colortype=PNG_COLOR_TYPE_RGB;
     }
-  else if (mng_info->write_png32)
+  else if (mng_info->write_png32 || mng_info->write_png64)
     {
-      image->matte=True;
-      ping_info->color_type=PNG_COLOR_TYPE_RGB_ALPHA;
+      image_matte=MagickTrue;
+      ping_colortype=PNG_COLOR_TYPE_RGB_ALPHA;
     }
   else
     {
-      if (ping_info->bit_depth < 8)
-        ping_info->bit_depth=8;
+      if (ping_bit_depth < 8)
+        ping_bit_depth=8;
 
-      ping_info->color_type=PNG_COLOR_TYPE_RGB;
+      ping_colortype=PNG_COLOR_TYPE_RGB;
       if (characteristics.monochrome)
         {
           if (characteristics.opaque)
             {
-              ping_info->color_type=PNG_COLOR_TYPE_GRAY;
-              ping_info->bit_depth=1;
+              ping_colortype=PNG_COLOR_TYPE_GRAY;
+              ping_bit_depth=1;
             }
           else
             {
-              ping_info->color_type=PNG_COLOR_TYPE_GRAY_ALPHA;
+              ping_colortype=PNG_COLOR_TYPE_GRAY_ALPHA;
             }
         }
       else if (characteristics.grayscale)
         {
           if (characteristics.opaque)
-            ping_info->color_type=PNG_COLOR_TYPE_GRAY;
+            ping_colortype=PNG_COLOR_TYPE_GRAY;
           else
-            ping_info->color_type=PNG_COLOR_TYPE_GRAY_ALPHA;
+            ping_colortype=PNG_COLOR_TYPE_GRAY_ALPHA;
         }
-      else if (characteristics.palette && image->colors <= 256)
+      else if (characteristics.palette && image_colors <= 256)
         {
-          ping_info->color_type=PNG_COLOR_TYPE_PALETTE;
-          ping_info->bit_depth=8;
+          ping_colortype=PNG_COLOR_TYPE_PALETTE;
+          ping_bit_depth=8;
           mng_info->IsPalette=MagickTrue;
         }
       else
         {
           if (characteristics.opaque)
-            ping_info->color_type=PNG_COLOR_TYPE_RGB;
+            ping_colortype=PNG_COLOR_TYPE_RGB;
           else
-            ping_info->color_type=PNG_COLOR_TYPE_RGB_ALPHA;
+            ping_colortype=PNG_COLOR_TYPE_RGB_ALPHA;
         }
       if (image_info->type == BilevelType)
         {
           if (characteristics.monochrome)
             {
-              if (!image->matte)
-                ping_info->bit_depth=1;
+              if (!image_matte)
+                ping_bit_depth=1;
             }
         }
       if (image_info->type == GrayscaleType)
-        ping_info->color_type=PNG_COLOR_TYPE_GRAY;
+        ping_colortype=PNG_COLOR_TYPE_GRAY;
       if (image_info->type == GrayscaleMatteType)
-        ping_info->color_type=PNG_COLOR_TYPE_GRAY_ALPHA;
-      /*       if (!mng_info->optimize && matte) */
-      /*         ping_info->color_type=PNG_COLOR_TYPE_RGB_ALPHA; */
+        ping_colortype=PNG_COLOR_TYPE_GRAY_ALPHA;
 
       if (logging)
         {
           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                                 "    Tentative PNG color type: %s (%d)",
-                                PngColorTypeToString(ping_info->color_type),
-                                ping_info->color_type);
+                                PngColorTypeToString(ping_colortype),
+                                ping_colortype);
           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                                 "    image_info->type: %d",image_info->type);
           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                "    image->depth: %u",image->depth);
+                                "    image->depth: %u",image_depth);
           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                "    ping_info->bit_depth: %d",
-                                ping_info->bit_depth);
+                                "    ping_bit_depth: %d",
+                                ping_bit_depth);
         }
 
-      if (matte && (mng_info->optimize || mng_info->IsPalette))
+      if (matte && mng_info->IsPalette)
         {
           register const PixelPacket
             *p=NULL;
@@ -6593,10 +6961,11 @@ static unsigned int WriteOnePNGImage(Mng
             {
               /*
                 No transparent pixels are present.  Change 4 or 6 to 0 or 2,
-                and do not set the PNG_INFO_tRNS flag in ping_info->valid.
+                and unset the ping_valid_trns flag.
               */
-              image->matte=False;
-              ping_info->color_type&=0x03;
+              image_matte=MagickFalse;
+              ping_colortype&=0x03;
+              ping_valid_trns=0;
             }
           else
             {
@@ -6607,13 +6976,13 @@ static unsigned int WriteOnePNGImage(Mng
                 opaque = MagickTrue;
 
               mask=0xffff;
-              if (ping_info->bit_depth == 8)
+              if (ping_bit_depth == 8)
                 mask=0x00ff;
-              if (ping_info->bit_depth == 4)
+              if (ping_bit_depth == 4)
                 mask=0x000f;
-              if (ping_info->bit_depth == 2)
+              if (ping_bit_depth == 2)
                 mask=0x0003;
-              if (ping_info->bit_depth == 1)
+              if (ping_bit_depth == 1)
                 mask=0x0001;
 
               /*
@@ -6621,7 +6990,8 @@ static unsigned int WriteOnePNGImage(Mng
               */
               for (y=0; y < (long) image->rows; y++)
                 {
-                  p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
+                  p=AcquireImagePixels(image,0,y,image->columns,1,
+                                       &image->exception);
                   if (p == (const PixelPacket *) NULL)
                     break;
                   for (x=(long) image->columns; x > 0; x--)
@@ -6638,22 +7008,30 @@ static unsigned int WriteOnePNGImage(Mng
                 }
               if ((!opaque) && (p != (const PixelPacket *) NULL))
                 {
-                  ping_info->valid|=PNG_INFO_tRNS;
-                  ping_info->trans_values.red=ScaleQuantumToShort(p->red)&mask;
-                  ping_info->trans_values.green=ScaleQuantumToShort(p->green)&mask;
-                  ping_info->trans_values.blue=ScaleQuantumToShort(p->blue)&mask;
-                  ping_info->trans_values.gray=
+                  ping_trans_color.red=ScaleQuantumToShort(p->red)&mask;
+                  ping_trans_color.green=ScaleQuantumToShort(p->green)
+                                                &mask;
+                  ping_trans_color.blue=ScaleQuantumToShort(p->blue)
+                                               &mask;
+                  ping_trans_color.gray=
                     (png_uint_16) ScaleQuantumToShort(PixelIntensity(p))&mask;
-                  ping_info->trans_values.index=(unsigned char)
+                  ping_trans_color.index=(unsigned char)
                     (ScaleQuantumToChar(MaxRGB-p->opacity));
+                  ping_valid_trns=1;
+                  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                    "  Found transparent color: (%d,%d,%d)",
+                    ping_trans_color.red, ping_trans_color.green,
+                    ping_trans_color.blue);
                 }
             }
-          if (ping_info->valid & PNG_INFO_tRNS)
+          if (ping_valid_trns != 0)
             {
               /*
                 Determine if there is one and only one transparent color
                 and if so if it is fully transparent.
               */
+              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                 "  Determine if there is exactly one transparent color");
               for (y=0; y < (long) image->rows; y++)
                 {
                   p=AcquireImagePixels(image,0,y,image->columns,1,
@@ -6665,7 +7043,7 @@ static unsigned int WriteOnePNGImage(Mng
                     {
                       if (p->opacity != OpaqueOpacity)
                         {
-                          if (!RGBColorMatchExact(ping_info->trans_values,*p))
+                          if (!RGBColorMatchExact(ping_trans_color,*p))
                             {
                               break;  /* Can't use RGB + tRNS for multiple
                                          transparent colors.  */
@@ -6678,7 +7056,7 @@ static unsigned int WriteOnePNGImage(Mng
                         }
                       else
                         {
-                          if (RGBColorMatchExact(ping_info->trans_values,*p))
+                          if (RGBColorMatchExact(ping_trans_color,*p))
                             break; /* Can't use RGB + tRNS when another pixel
                                       having the same RGB samples is
                                       transparent. */
@@ -6689,99 +7067,73 @@ static unsigned int WriteOnePNGImage(Mng
                     break;
                 }
               if (x != 0)
-                ping_info->valid&=(~PNG_INFO_tRNS);
+                {
+                  ping_valid_trns = 0;
+                }
+              else if (logging)
+                {
+                  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                        "Single transparent color (%d,%d,%d index=%d)",
+                                        ping_trans_color.red,ping_trans_color.green,
+                                        ping_trans_color.blue,ping_trans_color.index);
+                }
             }
-          if (ping_info->valid & PNG_INFO_tRNS)
+          if (ping_valid_trns != 0)
             {
-              ping_info->color_type &= 0x03;  /* changes 4 or 6 to 0 or 2 */
-              if (image->depth == 8)
+              ping_colortype &= 0x03;  /* changes 4 or 6 to 0 or 2 */
+              if (image_depth == 8)
                 {
-                  ping_info->trans_values.red&=0xff;
-                  ping_info->trans_values.green&=0xff;
-                  ping_info->trans_values.blue&=0xff;
-                  ping_info->trans_values.gray&=0xff;
+                  ping_trans_color.red&=0xff;
+                  ping_trans_color.green&=0xff;
+                  ping_trans_color.blue&=0xff;
+                  ping_trans_color.gray&=0xff;
                 }
             }
         }
-      matte=image->matte;
-      if (ping_info->valid & PNG_INFO_tRNS)
-        image->matte=False;
-      if ((mng_info->optimize || mng_info->IsPalette) &&
-          characteristics.grayscale && (!image->matte || image->depth >= 8))
+      matte=image_matte;
+      if (ping_valid_trns != 0)
+        image_matte=MagickFalse;
+      if (mng_info->IsPalette &&
+          characteristics.grayscale && (!image_matte || image_depth >= 8))
         {
-          if (image->matte)
-            ping_info->color_type=PNG_COLOR_TYPE_GRAY_ALPHA;
+          if (image_matte)
+            ping_colortype=PNG_COLOR_TYPE_GRAY_ALPHA;
           else
             {
-              ping_info->color_type=PNG_COLOR_TYPE_GRAY;
-              if (save_image_depth == 16 && image->depth == 8)
-                ping_info->trans_values.gray*=0x0101;
-            }
-          if (image->depth > QuantumDepth)
-            image->depth=QuantumDepth;
-          if (image->colors == 0 || image->colors-1 > MaxRGB)
-            image->colors=1 << image->depth;
-          if (image->depth > 8)
-            ping_info->bit_depth=16;
+              ping_colortype=PNG_COLOR_TYPE_GRAY;
+              if (save_image_depth == 16 && image_depth == 8)
+                ping_trans_color.gray*=0x0101;
+            }
+          if (image_depth > QuantumDepth)
+            image_depth=QuantumDepth;
+          if (image_colors == 0 || image_colors-1 > MaxRGB)
+            image_colors=1U << image_depth;
+          if (image_depth > 8)
+            ping_bit_depth=16;
           else
             {
-              if (ping_info->color_type == PNG_COLOR_TYPE_PALETTE)
+              if (ping_colortype == PNG_COLOR_TYPE_PALETTE)
                 {
-                  ping_info->bit_depth=1;
-                  while ((int) (1 << ping_info->bit_depth) < (long) image->colors)
-                    ping_info->bit_depth <<= 1;
-                }
-              else if (mng_info->optimize && ping_info->color_type ==
-                       PNG_COLOR_TYPE_GRAY && image->colors < 17 &&
-                       mng_info->IsPalette)
-                {
-
-                  /* Check if grayscale is reducible */
-                  int
-                    i,
-                    depth_4_ok=True,
-                    depth_2_ok=True,
-                    depth_1_ok=True;
-
-                  for (i=0; i < (long) image->colors; i++)
-                    {
-                      unsigned char
-                        intensity;
-
-                      intensity=ScaleQuantumToChar(image->colormap[i].red);
-
-                      if ((intensity & 0x0f) != ((intensity & 0xf0) >> 4))
-                        depth_4_ok=depth_2_ok=depth_1_ok=False;
-                      else if ((intensity & 0x03) != ((intensity & 0x0c) >> 2))
-                        depth_2_ok=depth_1_ok=False;
-                      else if ((intensity & 0x01) != ((intensity & 0x02) >> 1))
-                        depth_1_ok=False;
-                    }
-                  if (depth_1_ok)
-                    ping_info->bit_depth=1;
-                  else if (depth_2_ok)
-                    ping_info->bit_depth=2;
-                  else if (depth_4_ok)
-                    ping_info->bit_depth=4;
+                  ping_bit_depth=1;
+                  while ((int) (1U << ping_bit_depth) <
+                                (long) image_colors)
+                    ping_bit_depth <<= 1;
                 }
             }
         }
       else
         if (mng_info->IsPalette)
           {
-            if (image->depth <= 8)
+            if (image_depth <= 8)
               {
                 unsigned long
                   number_colors;
 
-                number_colors=image->colors;
-                if (matte)
-                  ping_info->valid|=PNG_INFO_tRNS;
+                number_colors=image_colors;
                 /*
                   Set image palette.
                 */
-                ping_info->color_type=PNG_COLOR_TYPE_PALETTE;
-                ping_info->valid|=PNG_INFO_PLTE;
+                ping_colortype=PNG_COLOR_TYPE_PALETTE;
                 if (mng_info->have_write_global_plte && !matte)
                   {
                     png_set_PLTE(ping,ping_info,NULL,0);
@@ -6791,52 +7143,49 @@ static unsigned int WriteOnePNGImage(Mng
                   }
                 else
                   {
-#if defined(PNG_SORT_PALETTE)
-                    unsigned long
-                      save_number_colors;
-
-                    if (mng_info->optimize)
-                      {
-                        save_number_colors=image->colors;
-                        (void) CompressColormapTransFirst(image);
-                        number_colors=image->colors;
-                        image->colors=save_number_colors;
-                      }
-#endif
                     palette=MagickAllocateArray(png_color *,
-                                                number_colors,sizeof(png_color));
+                                                number_colors,
+                                                sizeof(png_color));
                     if (palette == (png_color *) NULL)
-                      ThrowWriterException(ResourceLimitError,
-                                           MemoryAllocationFailed,image);
+                      png_error(ping, "Could not allocate palette");
                     for (i=0; i < (long) number_colors; i++)
                       {
-                        palette[i].red=ScaleQuantumToChar(image->colormap[i].red);
-                        palette[i].green=ScaleQuantumToChar(image->colormap[i].green);
-                        palette[i].blue=ScaleQuantumToChar(image->colormap[i].blue);
+                        palette[i].red=ScaleQuantumToChar
+                                       (image->colormap[i].red);
+                        palette[i].green=ScaleQuantumToChar
+                                       (image->colormap[i].green);
+                        palette[i].blue=ScaleQuantumToChar
+                                       (image->colormap[i].blue);
                       }
                     if (logging)
                       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                            "  Setting up PLTE chunk");
+                           "  Setting up PLTE chunk with %d colors",
+                           (int) number_colors);
                     png_set_PLTE(ping,ping_info,palette,(int) number_colors);
-#if (PNG_LIBPNG_VER > 10008)
                     MagickFreeMemory(palette);
-#endif
                   }
-                ping_info->bit_depth=1;
-                while ((1UL << ping_info->bit_depth) < number_colors)
-                  ping_info->bit_depth <<= 1;
-                ping_info->num_trans=0;
+                ping_bit_depth=1;
+                while ((1U << ping_bit_depth) < number_colors)
+                  ping_bit_depth <<= 1;
+                ping_num_trans=0;
                 if (matte)
                   {
                     int
-                      trans[256];
+                      num_alpha=0,
+                      trans_alpha[256];
 
                     /*
                       Identify which colormap entry is transparent.
                     */
                     assert(number_colors <= 256);
+
+                    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                     "  Look for transparent colormap entry, number_colors=%d",
+                        (int) number_colors);
+
                     for (i=0; i < (long) number_colors; i++)
-                      trans[i]=256;
+                      trans_alpha[i]=256;
+
                     for (y=0; y < (long) image->rows; y++)
                       {
                         register const PixelPacket
@@ -6856,56 +7205,78 @@ static unsigned int WriteOnePNGImage(Mng
 
                                 index=indexes[x];
                                 assert((unsigned long) index < number_colors);
-                                if (trans[index] != 256)
+                                if (trans_alpha[index] == 256)
                                   {
-                                    if (trans[index] != (png_byte) (255-
-                                                                    ScaleQuantumToChar(p->opacity)))
-                                      {
-                                        ping_info->color_type=PNG_COLOR_TYPE_RGB_ALPHA;
-                                        break;
-                                      }
+                                    (void) LogMagickEvent(CoderEvent,
+                                      GetMagickModule(),
+                                      "  Index=%d is transparent",(int) index);
+                                    trans_alpha[index]=(png_byte) (255-
+                                      ScaleQuantumToChar(p->opacity));
+                                    num_alpha++;
                                   }
-                                trans[index]=(png_byte) (255-
-                                                         ScaleQuantumToChar(p->opacity));
                               }
                             p++;
                           }
-                        if (ping_info->color_type==PNG_COLOR_TYPE_RGB_ALPHA)
-                          {
-                            ping_info->num_trans=0;
-                            ping_info->valid&=(~PNG_INFO_tRNS);
-                            ping_info->valid&=(~PNG_INFO_PLTE);
-                            mng_info->IsPalette=False;
-                            (void) SyncImage(image);
-                            if (logging)
-                              (void) LogMagickEvent(CoderEvent, GetMagickModule(),
-                                                    "    Cannot write image as indexed PNG, writing RGBA.");
-                            break;
-                          }
                       }
-                    if ((ping_info->valid & PNG_INFO_tRNS))
+
+                      (void) LogMagickEvent(CoderEvent, GetMagickModule(),
+                         "  num_alpha = %d",num_alpha);
+                      if (num_alpha == 1)
+                         ping_valid_trns=1;
+                      else
+                      {
+                         ping_colortype=PNG_COLOR_TYPE_RGB_ALPHA;
+                         ping_num_trans=0;
+                         if (ping_bit_depth < 8)
+                            ping_bit_depth=8;
+                         ping_valid_trns = 0;
+                         png_set_invalid(ping, ping_info, PNG_INFO_PLTE);
+                         mng_info->IsPalette=MagickFalse;
+                         image_matte=MagickTrue;
+                         (void) SyncImage(image);
+                         if (logging)
+                           (void) LogMagickEvent(CoderEvent,
+                                                 GetMagickModule(),
+                                                 "    Cannot write image"
+                                                 " as indexed PNG,"
+                                                 " writing RGBA.");
+                       }
+
+                    if (ping_valid_trns != 0)
                       {
                         for (i=0; i < (long) number_colors; i++)
                           {
-                            if (trans[i] == 256)
-                              trans[i]=255;
-                            if (trans[i] != 255)
-                              ping_info->num_trans=(unsigned short) (i+1);
+                            if (trans_alpha[i] == 256)
+                              trans_alpha[i]=255;
+                            if (trans_alpha[i] != 255)
+                              ping_num_trans=(unsigned short) (i+1);
                           }
+                      (void) LogMagickEvent(CoderEvent, GetMagickModule(),
+                         "  ping_num_trans = %d",ping_num_trans);
                       }
-                    if (ping_info->num_trans == 0)
-                      ping_info->valid&=(~PNG_INFO_tRNS);
-                    if (!(ping_info->valid & PNG_INFO_tRNS))
-                      ping_info->num_trans=0;
-                    if (ping_info->num_trans != 0)
+                    if (ping_num_trans == 0)
+                       ping_valid_trns = 0;
+                    else
+                       ping_valid_trns = 1;
+                    if (ping_valid_trns == 0)
+                       ping_num_trans=0;
+
+                    if (ping_valid_trns != 0)
                       {
-                        ping_info->trans=MagickAllocateMemory(unsigned char *,
-                                                              number_colors);
-                        if (ping_info->trans == (unsigned char *) NULL)
-                          ThrowWriterException(ResourceLimitError,
-                                               MemoryAllocationFailed,image);
-                        for (i=0; i < (long) number_colors; i++)
-                          ping_info->trans[i]=(png_byte) trans[i];
+                        ping_trans_alpha=MagickAllocateMemory(
+                          unsigned char *, number_colors);
+                        if (ping_trans_alpha == (unsigned char *) NULL)
+                          png_error(ping, "Could not allocate trans_alpha");
+
+                        for (i=0; i<(int) number_colors; i++)
+                          {
+                            if (trans_alpha[i] == 256)
+                               ping_trans_alpha[i]=255;
+                            else
+                               ping_trans_alpha[i]=(png_byte) trans_alpha[i];
+                           (void) LogMagickEvent(CoderEvent, GetMagickModule(),
+                              "    Alpha[%d]=%d",(int) i, (int) trans_alpha[i]);
+                          }
                       }
                   }
 
@@ -6913,68 +7284,58 @@ static unsigned int WriteOnePNGImage(Mng
                   Identify which colormap entry is the background color.
                 */
                 for (i=0; i < (long) Max(number_colors-1,1); i++)
-                  if (RGBColorMatchExact(ping_info->background,image->colormap[i]))
+                  if (RGBColorMatchExact(ping_background,
+                                         image->colormap[i]))
                     break;
-                ping_info->background.index=(png_uint_16) i;
+                ping_background.index=(png_uint_16) i;
               }
           }
         else
           {
-            if (image->depth < 8)
-              image->depth=8;
-            if ((save_image_depth == 16) && (image->depth == 8))
+            if (image_depth < 8)
+              image_depth=8;
+            if ((save_image_depth == 16) && (image_depth == 8))
               {
-                ping_info->trans_values.red*=0x0101;
-                ping_info->trans_values.green*=0x0101;
-                ping_info->trans_values.blue*=0x0101;
-                ping_info->trans_values.gray*=0x0101;
+                ping_trans_color.red*=0x0101;
+                ping_trans_color.green*=0x0101;
+                ping_trans_color.blue*=0x0101;
+                ping_trans_color.gray*=0x0101;
               }
           }
 
       /*
-        Adjust background and transparency samples in sub-8-bit grayscale files.
+        Adjust background and transparency samples in sub-8-bit
+        grayscale files.
       */
-      if (ping_info->bit_depth < 8 && ping_info->color_type ==
+      if (ping_bit_depth < 8 && ping_colortype ==
           PNG_COLOR_TYPE_GRAY)
         {
           png_uint_16
             maxval;
 
-          png_color_16
-            background;
-
-          maxval=(1 << ping_info->bit_depth)-1;
-
-
-          background.gray=(png_uint_16)
-            (maxval*(PixelIntensity(&image->background_color))/MaxRGB);
+          maxval=(1U << ping_bit_depth)-1;
 
-          if (logging)
-            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                  "  Setting up bKGD chunk");
-          png_set_bKGD(ping,ping_info,&background);
-
-          ping_info->trans_values.gray=(png_uint_16)(maxval*
-                                                     ping_info->trans_values.gray/MaxRGB);
+          ping_trans_color.gray=(png_uint_16)(maxval*
+                                ping_trans_color.gray/
+                                MaxRGB);
         }
     }
+
   if (logging)
     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                           "    PNG color type: %s (%d)",
-                          PngColorTypeToString(ping_info->color_type),
-                          ping_info->color_type);
+                          PngColorTypeToString(ping_colortype),
+                          ping_colortype);
   /*
     Initialize compression level and filtering.
   */
   if (logging)
     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                           "  Setting up deflate compression");
-#if (PNG_LIBPNG_VER > 99)
   if (logging)
     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                           "    Compression buffer size: 32768");
   png_set_compression_buffer_size(ping,32768L);
-#endif
   if (logging)
     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                           "    Compression mem level: 9");
@@ -6996,6 +7357,7 @@ static unsigned int WriteOnePNGImage(Mng
         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                               "    Compression strategy: Z_HUFFMAN_ONLY");
       png_set_compression_strategy(ping, Z_HUFFMAN_ONLY);
+      png_set_compression_level(ping,2);
     }
   if (logging)
     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
@@ -7008,7 +7370,7 @@ static unsigned int WriteOnePNGImage(Mng
       if (logging)
         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                               "    Filter_type: PNG_INTRAPIXEL_DIFFERENCING");
-      ping_info->filter_type=PNG_INTRAPIXEL_DIFFERENCING;
+      ping_filter_method=PNG_INTRAPIXEL_DIFFERENCING;
     }
   else
     if (logging)
@@ -7025,8 +7387,8 @@ static unsigned int WriteOnePNGImage(Mng
       if ((image_info->quality % 10) != 5)
         base_filter=(int) image_info->quality % 10;
       else
-        if ((ping_info->color_type == PNG_COLOR_TYPE_GRAY) ||
-            (ping_info->color_type == PNG_COLOR_TYPE_PALETTE) ||
+        if ((ping_colortype == PNG_COLOR_TYPE_GRAY) ||
+            (ping_colortype == PNG_COLOR_TYPE_PALETTE) ||
             (image_info->quality < 50))
           base_filter=PNG_NO_FILTERS;
         else
@@ -7042,6 +7404,155 @@ static unsigned int WriteOnePNGImage(Mng
       }
     png_set_filter(ping,PNG_FILTER_TYPE_BASE,base_filter);
   }
+
+  ping_interlace_method=(image_info->interlace == LineInterlace);
+
+  if (mng_info->write_mng)
+    png_set_sig_bytes(ping,8);
+
+  if (logging)
+    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                          "  Writing PNG header chunks");
+
+  png_set_IHDR(ping,ping_info,
+               ping_width,
+               ping_height,
+               ping_bit_depth,
+               ping_colortype,
+               ping_interlace_method,
+               ping_compression_method,
+               ping_filter_method);
+
+  if (ping_colortype == 3 && ping_valid_trns != 0)
+     {
+        if (logging)
+           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+              "  Setting up tRNS chunk");
+        (void) png_set_tRNS(ping, ping_info,
+                           ping_trans_alpha,
+                           ping_num_trans,
+                           &ping_trans_color);
+     }
+
+  MagickFreeMemory(ping_trans_alpha);
+
+  if (image_matte && (!mng_info->adjoin || !mng_info->equal_backgrounds))
+    {
+      if (logging)
+         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+              "  Setting up bKGD chunk");
+      if (ping_bit_depth < 8 && ping_colortype == PNG_COLOR_TYPE_GRAY)
+        {
+          png_uint_16
+            maxval;
+
+          png_color_16
+            background;
+
+          maxval=(1U << ping_bit_depth)-1;
+
+
+          background.gray=(png_uint_16)
+            (maxval*(PixelIntensity(&image->background_color))/MaxRGB);
+
+          png_set_bKGD(ping,ping_info,&background);
+        }
+
+      else
+        {
+          png_color_16
+            background;
+
+          if (image_depth < QuantumDepth)
+            {
+              int
+                maxval;
+
+              maxval=(1U << image_depth)-1;
+              background.red=(png_uint_16)
+                (maxval*image->background_color.red/MaxRGB);
+              background.green=(png_uint_16)
+                (maxval*image->background_color.green/MaxRGB);
+              background.blue=(png_uint_16)
+                (maxval*image->background_color.blue/MaxRGB);
+              background.gray=(png_uint_16)
+                (maxval*PixelIntensity(&image->background_color)/MaxRGB);
+            }
+          else
+            {
+              background.red=image->background_color.red;
+              background.green=image->background_color.green;
+              background.blue=image->background_color.blue;
+              background.gray=
+                (png_uint_16) PixelIntensity(&image->background_color);
+            }
+          background.index=(png_byte) background.gray;
+          png_set_bKGD(ping,ping_info,&background);
+        }
+    }
+
+#if defined(PNG_pHYs_SUPPORTED)
+  if ((image->x_resolution != 0) && (image->y_resolution != 0) &&
+      (!mng_info->write_mng || !mng_info->equal_physs))
+    {
+      int
+        unit_type;
+
+      png_uint_32
+        x_resolution,
+        y_resolution;
+
+      if (image->units == PixelsPerInchResolution)
+        {
+          unit_type=PNG_RESOLUTION_METER;
+          x_resolution=(png_uint_32) ((100.0*image->x_resolution+0.5)/2.54);
+          y_resolution=(png_uint_32) ((100.0*image->y_resolution+0.5)/2.54);
+        }
+      else if (image->units == PixelsPerCentimeterResolution)
+        {
+          unit_type=PNG_RESOLUTION_METER;
+          x_resolution=(png_uint_32) (100.0*image->x_resolution+0.5);
+          y_resolution=(png_uint_32) (100.0*image->y_resolution+0.5);
+        }
+      else
+        {
+          unit_type=PNG_RESOLUTION_UNKNOWN;
+          x_resolution=(png_uint_32) image->x_resolution;
+          y_resolution=(png_uint_32) image->y_resolution;
+        }
+
+      png_set_pHYs(ping,ping_info,x_resolution,y_resolution,unit_type);
+
+      if (logging)
+      {
+        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+             "    Setting up pHYs chunk");
+        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+             "      x_resolution=%lu",(unsigned long) x_resolution);
+        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+             "      y_resolution=%lu",(unsigned long) y_resolution);
+        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+             "      unit_type=%lu",(unsigned long) unit_type);
+      }
+    }
+#endif
+
+#if defined(PNG_oFFs_SUPPORTED)
+  if (mng_info->write_mng == 0 && (image->page.x || image->page.y))
+    {
+      if (!((image->page.width != 0 && image->page.width != image->columns) ||
+          (image->page.height != 0 && image->page.height != image->rows)))
+        {
+          png_set_oFFs(ping,ping_info,(png_int_32) image->page.x,
+                   (png_int_32) image->page.y, 0);
+          if (logging)
+            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                              "    Setting up oFFs chunk");
+        }
+      /* else write caNv instead, later */
+    }
+#endif
+
   {
     ImageProfileIterator
       *profile_iterator;
@@ -7063,20 +7574,28 @@ static unsigned int WriteOnePNGImage(Mng
           {
             if (LocaleCompare(profile_name,"ICM") == 0)
               {
-#if (PNG_LIBPNG_VER > 10008) && defined(PNG_WRITE_iCCP_SUPPORTED)
+#if defined(PNG_WRITE_iCCP_SUPPORTED)
                 {
                   if (logging)
                     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                                           "  Setting up iCCP chunk");
+
                   png_set_iCCP(ping,ping_info,(png_charp) "icm",
-                               (int) 0, (png_charp) profile_info,
+                               (int) 0,
+#if (PNG_LIBPNG_VER < 10500)
+                               (png_charp) profile_info,
+#else
+                               (png_const_bytep) profile_info,
+#endif
+
                                (png_uint_32) profile_length);
                 }
 #else
                 {
                   if (logging)
                     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                          "  Setting up text chunk with iCCP Profile");
+                                          "  Setting up text chunk with"
+                                          " iCCP Profile");
                   png_write_raw_profile(image_info,ping,ping_info,
                                         "icm",
                                         "ICC Profile",
@@ -7089,18 +7608,23 @@ static unsigned int WriteOnePNGImage(Mng
               {
                 if (logging)
                   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                        "  Setting up text chunk with iPTC Profile");
+                                        "  Setting up text chunk with"
+                                        " iPTC Profile");
                 png_write_raw_profile(image_info,ping,ping_info,
                                       "iptc",
                                       "IPTC profile",
                                       profile_info,
                                       (png_uint_32) profile_length);
               }
+            else if (LocaleCompare(profile_name,"exif") == 0)
+              /* Do not write exif; we'll write it later as eXIf */
+              ;
             else
               {
                 if (logging)
                   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                        "  Setting up text chunk with %s profile",
+                                        "  Setting up text chunk with"
+                                        " %s profile",
                                         profile_name);
                 png_write_raw_profile(image_info,ping,ping_info,
                                       profile_name,
@@ -7131,8 +7655,8 @@ static unsigned int WriteOnePNGImage(Mng
         (void) png_set_sRGB(ping,ping_info,PerceptualIntent);
       png_set_gAMA(ping,ping_info,0.45455);
     }
-  not_valid=(!ping_info->valid);
-  if ((!mng_info->write_mng) || not_valid & PNG_INFO_sRGB)
+  if ((!mng_info->write_mng) ||
+       !png_get_valid(ping, ping_info, PNG_INFO_sRGB))
 #endif
     {
       if (!mng_info->have_write_global_gama && (image->gamma != 0.0))
@@ -7171,16 +7695,40 @@ static unsigned int WriteOnePNGImage(Mng
                        bp.x,bp.y);
         }
     }
-  ping_info->interlace_type=image_info->interlace != NoInterlace;
 
-  if (mng_info->write_mng)
-    png_set_sig_bytes(ping,8);
+  png_write_info(ping,ping_info);
 
-  if (logging)
-    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                          "  Writing PNG header chunks");
+  /* write orNT if image->orientation is defined and not TopLeft */
+  if (image->orientation > 1 && image->orientation < 9)
+    {
+      unsigned char
+        chunk[6];
+      (void) WriteBlobMSBULong(image,1L);  /* data length=1 */
+      PNGType(chunk,mng_orNT);
+      LogPNGChunk(logging,mng_orNT,1L);
+      chunk[4]=image->orientation;
+      (void) WriteBlob(image,5,chunk);
+      (void) WriteBlobMSBULong(image,crc32(0,chunk,5));
+    }
 
-  png_write_info(ping,ping_info);
+  /* write caNv chunk */
+  if ((image->page.width != 0 && image->page.width != image->columns) ||
+      (image->page.height != 0 && image->page.height != image->rows) ||
+      image->page.x != 0 || image->page.y != 0)
+    {
+      unsigned char
+        chunk[22];
+
+      (void) WriteBlobMSBULong(image,16L);  /* data length=16 */
+      PNGType(chunk,mng_caNv);
+      LogPNGChunk(logging,mng_caNv,16L);
+      PNGLong(chunk+4,(png_uint_32) image->page.width);
+      PNGLong(chunk+8,(png_uint_32) image->page.height);
+      PNGsLong(chunk+12,(png_int_32) image->page.x);
+      PNGsLong(chunk+16,(png_int_32) image->page.y);
+      (void) WriteBlob(image,20,chunk);
+      (void) WriteBlobMSBULong(image,crc32(0,chunk,20));
+    }
 
 #if (PNG_LIBPNG_VER == 10206)
   /* avoid libpng-1.2.6 bug by setting PNG_HAVE_IDAT flag */
@@ -7193,46 +7741,65 @@ static unsigned int WriteOnePNGImage(Mng
   /*
     Allocate memory.
   */
+  if (logging)
+    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                          "  mng_info: columns=%lu, image_depth=%u, "
+                          "write_png8=%u, write_png24=%u, write_png32=%u "
+                          "write_png48=%u, write_png64=%u, IsPalette=%u, "
+                          "image_matte=%u",
+                          image->columns, image_depth, mng_info->write_png8,
+                          mng_info->write_png24, mng_info->write_png32,
+                          mng_info->write_png48, mng_info->write_png64,
+                          mng_info->IsPalette, image_matte
+                          );
   rowbytes=image->columns;
-  if (image->depth <= 8)
+  if (image_depth <= 8)
     {
       if (mng_info->write_png24)
         rowbytes*=3;
       else if (mng_info->write_png32)
         rowbytes*=4;
-      else if (!mng_info->write_png8 &&
-               ((mng_info->optimize || mng_info->IsPalette) &&
+      else if (!mng_info->write_png8 && (mng_info->IsPalette &&
                 IsGrayImage(image,&image->exception)))
-        rowbytes*=(image->matte ? 2 : 1);
+        rowbytes*=(image_matte ? 2 : 1);
       else
         {
           if (!mng_info->IsPalette)
-            rowbytes*=(image->matte ? 4 : 3);
+            rowbytes*=(image_matte ? 4 : 3);
         }
     }
   else
     {
-      if ((mng_info->optimize || mng_info->IsPalette) &&
+      if (mng_info->write_png48)
+        rowbytes*=6;
+
+      else if (mng_info->write_png64)
+        rowbytes*=8;
+
+      else if (mng_info->IsPalette &&
           IsGrayImage(image,&image->exception))
-        rowbytes*=(image->matte ? 4 : 2);
+        rowbytes*=(image_matte ? 4 : 2);
+
       else
-        rowbytes*=(image->matte ? 8 : 6);
+        rowbytes*=(image_matte ? 8 : 6);
     }
   if (logging)
     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                          "  Allocating %lu bytes of memory for pixels",rowbytes);
+                          "  Allocating %lu bytes of memory for pixels",
+                          rowbytes);
   png_pixels=MagickAllocateMemory(unsigned char *,rowbytes);
   if (png_pixels == (unsigned char *) NULL)
-    ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image);
+    png_error(ping, "Could not allocate png_pixels");
   /*
     Initialize image scanlines.
   */
   num_passes=png_set_interlace_handling(ping);
   if ((!mng_info->write_png8 && !mng_info->write_png24 &&
-       !mng_info->write_png32) && (mng_info->optimize ||
-                                   mng_info->IsPalette ||
-                                   image_info->type == BilevelType) &&
-      !image->matte && IsMonochromeImage(image,&image->exception))
+       !mng_info->write_png32 && !mng_info->write_png48 &&
+       !mng_info->write_png64) && (mng_info->IsPalette ||
+       image_info->type == BilevelType) &&
+       !image_matte &&
+       IsMonochromeImage(image,&image->exception))
     for (pass=0; pass < num_passes; pass++)
       {
         /*
@@ -7243,7 +7810,8 @@ static unsigned int WriteOnePNGImage(Mng
                                 "  pass %d, Image Is Monochrome",pass);
         for (y=0; y < (long) image->rows; y++)
           {
-            if (!AcquireImagePixels(image,0,y,image->columns,1,&image->exception))
+            if (!AcquireImagePixels(image,0,y,image->columns,1,
+                                    &image->exception))
               break;
             if (mng_info->IsPalette)
               (void) ExportImagePixelArea(image,(QuantumType) GrayQuantum,
@@ -7258,7 +7826,7 @@ static unsigned int WriteOnePNGImage(Mng
               if (!MagickMonitor(SaveImageTag,(magick_uint64_t) y*(pass+1),
                                  (magick_uint64_t) image->rows*num_passes,
                                  &image->exception))
-                break;
+                  break;
 
           }
       }
@@ -7266,9 +7834,10 @@ static unsigned int WriteOnePNGImage(Mng
     for (pass=0; pass < num_passes; pass++)
       {
         if ((!mng_info->write_png8 && !mng_info->write_png24 &&
-             !mng_info->write_png32) &&
-            (!image->matte || (ping_info->bit_depth >= QuantumDepth)) &&
-            (mng_info->optimize || mng_info->IsPalette) &&
+             !mng_info->write_png32 && !mng_info->write_png48 &&
+             !mng_info->write_png64) &&
+            (!image_matte || (ping_bit_depth >= QuantumDepth)) &&
+            mng_info->IsPalette &&
             IsGrayImage(image,&image->exception))
           {
             if (logging)
@@ -7279,71 +7848,96 @@ static unsigned int WriteOnePNGImage(Mng
                 if (!AcquireImagePixels(image,0,y,image->columns,1,
                                         &image->exception))
                   break;
-                if (ping_info->color_type == PNG_COLOR_TYPE_GRAY)
+                if (ping_colortype == PNG_COLOR_TYPE_GRAY)
                   {
                     if (mng_info->IsPalette)
-                      (void) ExportImagePixelArea(image,(QuantumType) GrayQuantum,
+                      (void) ExportImagePixelArea(image,
+                                                  (QuantumType) GrayQuantum,
                                                   quantum_size,png_pixels,0,0);
                     else
-                      (void) ExportImagePixelArea(image,(QuantumType) RedQuantum,
-                                                  quantum_size,png_pixels,0,0);
+                      (void) ExportImagePixelArea(image,
+                                                  (QuantumType) RedQuantum,
+                                                  quantum_size,
+                                                 png_pixels,0,0);
+                  }
+                else if (ping_colortype == PNG_COLOR_TYPE_PALETTE)
+                  {
+                    (void) ExportImagePixelArea(image,(QuantumType)
+                                                IndexQuantum,
+                                                quantum_size,
+                                                png_pixels,0,0);
                   }
                 else /* PNG_COLOR_TYPE_GRAY_ALPHA */
                   {
-                    (void) ExportImagePixelArea(image,(QuantumType) GrayAlphaQuantum,
-                                                quantum_size,png_pixels,0,0);
+                    (void) ExportImagePixelArea(image,(QuantumType)
+                                                GrayAlphaQuantum,
+                                                quantum_size,
+                                                png_pixels,0,0);
                   }
                 png_write_row(ping,png_pixels);
                 if (image->previous == (Image *) NULL)
                   if (!MagickMonitor(SaveImageTag,(magick_uint64_t) y*(pass+1),
                                      (magick_uint64_t) image->rows*num_passes,
                                      &image->exception))
-                    break;
+                      break;
               }
           }
         else
           for (pass=0; pass < num_passes; pass++)
             {
-              if ((image->depth > 8) ||
-                  (mng_info->write_png24 ||
-                   mng_info->write_png32 ||
+              if ((image_depth > 8) ||
+                  (mng_info->write_png24 || mng_info->write_png32 ||
+                   mng_info->write_png48 || mng_info->write_png64 ||
                    (!mng_info->write_png8 && !mng_info->IsPalette)))
                 {
                   if (logging)
                     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                          "  pass %d, Image Is RGB, PNG colortype is %s (%d)",pass,
-                                          PngColorTypeToString(ping_info->color_type),
-                                          ping_info->color_type);
+                                          "  pass %d, Image Is RGB,"
+                                          " PNG colortype is %s (%d)",pass,
+                                          PngColorTypeToString(
+                                             ping_colortype),
+                                          ping_colortype);
                   for (y=0; y < (long) image->rows; y++)
                     {
                       if (!AcquireImagePixels(image,0,y,image->columns,1,
                                               &image->exception))
                         break;
-                      if (ping_info->color_type == PNG_COLOR_TYPE_GRAY)
+                      if (ping_colortype == PNG_COLOR_TYPE_GRAY)
                         {
                           if (image->storage_class == DirectClass)
-                            (void) ExportImagePixelArea(image,(QuantumType) RedQuantum,
-                                                        quantum_size,png_pixels,0,0);
+                            (void) ExportImagePixelArea(image,(QuantumType)
+                                                        RedQuantum,
+                                                        quantum_size,
+                                                        png_pixels,0,0);
                           else
-                            (void) ExportImagePixelArea(image,(QuantumType) GrayQuantum,
-                                                        quantum_size,png_pixels,0,0);
+                            (void) ExportImagePixelArea(image,(QuantumType)
+                                                        GrayQuantum,
+                                                        quantum_size,
+                                                        png_pixels,0,0);
                         }
-                      else if (ping_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
-                        (void) ExportImagePixelArea(image,(QuantumType) GrayAlphaQuantum,
-                                                    quantum_size,png_pixels,0,0);
-                      else if (image->matte)
-                        (void) ExportImagePixelArea(image,(QuantumType) RGBAQuantum,
-                                                    quantum_size,png_pixels,0,0);
+                      else if (ping_colortype ==
+                               PNG_COLOR_TYPE_GRAY_ALPHA)
+                        (void) ExportImagePixelArea(image,(QuantumType)
+                                                    GrayAlphaQuantum,
+                                                    quantum_size,
+                                                    png_pixels,0,0);
+                      else if (image_matte)
+                        (void) ExportImagePixelArea(image,(QuantumType)
+                                                    RGBAQuantum,
+                                                    quantum_size,
+                                                    png_pixels,0,0);
                       else
                         {
-                          (void) ExportImagePixelArea(image,(QuantumType) RGBQuantum,
-                                                      quantum_size,png_pixels,0,0);
+                          (void) ExportImagePixelArea(image,(QuantumType)
+                                                      RGBQuantum,
+                                                      quantum_size,
+                                                      png_pixels,0,0);
                         }
                       png_write_row(ping,png_pixels);
                       if (image->previous == (Image *) NULL)
                         if (!MagickMonitor(SaveImageTag,(magick_uint64_t) y*(pass+1),
-                                           (magick_uint64_t) image->rows*num_passes,
-                                           &image->exception))
+                            (magick_uint64_t) image->rows*num_passes,
+                            &image->exception))
                           break;
                     }
                   if (logging)
@@ -7354,27 +7948,35 @@ static unsigned int WriteOnePNGImage(Mng
                 {
                   if (logging)
                     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                          "  pass %d, Image Is RGB, 16-bit GRAY, or GRAY_ALPHA",pass);
+                                          "  pass %d, Image Is RGB,"
+                                          " 16-bit GRAY, or GRAY_ALPHA",pass);
                   for (y=0; y < (long) image->rows; y++)
                     {
                       if (!AcquireImagePixels(image,0,y,image->columns,1,
                                               &image->exception))
                         break;
-                      if (ping_info->color_type == PNG_COLOR_TYPE_GRAY)
-                        (void) ExportImagePixelArea(image,(QuantumType) GrayQuantum,
-                                                    quantum_size,png_pixels,0,0);
-                      else if (ping_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
-                        (void) ExportImagePixelArea(image,(QuantumType) GrayAlphaQuantum,
-                                                    quantum_size,png_pixels,0,0);
+                      if (ping_colortype == PNG_COLOR_TYPE_GRAY)
+                        (void) ExportImagePixelArea(image,(QuantumType)
+                                                    GrayQuantum,
+                                                    quantum_size,
+                                                    png_pixels,0,0);
+                      else if (ping_colortype ==
+                               PNG_COLOR_TYPE_GRAY_ALPHA)
+                        (void) ExportImagePixelArea(image,(QuantumType)
+                                                    GrayAlphaQuantum,
+                                                    quantum_size,
+                                                    png_pixels,0,0);
                       else
-                        (void) ExportImagePixelArea(image,(QuantumType) IndexQuantum,
-                                                    quantum_size,png_pixels,0,0);
+                        (void) ExportImagePixelArea(image,(QuantumType)
+                                                    IndexQuantum,
+                                                    quantum_size,
+                                                    png_pixels,0,0);
                       png_write_row(ping,png_pixels);
                       if (image->previous == (Image *) NULL)
                         if (!MagickMonitor(SaveImageTag,(magick_uint64_t) y*(pass+1),
-                                           (magick_uint64_t) image->rows*num_passes,
-                                           &image->exception))
-                          break;
+                            (magick_uint64_t) image->rows*num_passes,
+                             &image->exception))
+                            break;
                     }
                 }
             }
@@ -7385,42 +7987,42 @@ static unsigned int WriteOnePNGImage(Mng
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                             "  Writing PNG image data");
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                            "    Width: %lu",ping_info->width);
+                            "    Width: %lu",
+                            (unsigned long)ping_width);
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                            "    Height: %lu",ping_info->height);
+                            "    Height: %lu",
+                            (unsigned long)ping_height);
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                            "    PNG sample depth: %d",ping_info->bit_depth);
+                            "    PNG sample depth: %d",ping_bit_depth);
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                             "    PNG color type: %s (%d)",
-                            PngColorTypeToString(ping_info->color_type),
-                            ping_info->color_type);
+                            PngColorTypeToString(ping_colortype),
+                            ping_colortype);
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                             "    PNG Interlace method: %d",
-                            ping_info->interlace_type);
+                            ping_interlace_method);
     }
   /*
     Generate text chunks.
   */
-#if (PNG_LIBPNG_VER <= 10005)
-  ping_info->num_text=0;
-#endif
   attribute=GetImageAttribute(image,(char *) NULL);
   for ( ; attribute != (const ImageAttribute *) NULL;
         attribute=attribute->next)
     {
-#if (PNG_LIBPNG_VER > 10005)
       png_textp
         text;
-#endif
 
       if (*attribute->key == '[')
         continue;
-#if (PNG_LIBPNG_VER > 10005)
-# if PNG_LIBPNG_VER >= 14000
-      text=(png_textp) png_malloc(ping, (png_alloc_size_t) sizeof(png_text));
-# else
-      text=(png_textp) png_malloc(ping,(png_size_t) sizeof(png_text));
-# endif
+      if (LocaleCompare(attribute->key,"png:IHDR.color-type-orig") == 0 ||
+          LocaleCompare(attribute->key,"png:IHDR.bit-depth-orig") == 0)
+        continue;
+#if PNG_LIBPNG_VER >= 14000
+            text=(png_textp) png_malloc(ping,
+                 (png_alloc_size_t) sizeof(png_text));
+#else
+            text=(png_textp) png_malloc(ping,(png_size_t) sizeof(png_text));
+#endif
       text[0].key=attribute->key;
       text[0].text=attribute->value;
       text[0].text_length=strlen(attribute->value);
@@ -7436,47 +8038,74 @@ static unsigned int WriteOnePNGImage(Mng
         }
       png_set_text(ping,ping_info,text,1);
       png_free(ping,text);
-#else
-      /* Work directly with ping_info struct; png_set_text before libpng version
-       * 1.0.5a is leaky */
-      if (ping_info->num_text == 0)
-        {
-          ping_info->text=MagickAllocateMemory(png_text *,256*sizeof(png_text));
-          if (ping_info->text == (png_text *) NULL)
-            (void) ThrowException(&image->exception,(ExceptionType)
-                                  ResourceLimitError,MemoryAllocationFailed,
-                                  image->filename);
-        }
-      i=ping_info->num_text++;
-      if (i > 255)
-        (void) ThrowException(&image->exception,(ExceptionType)
-                              ResourceLimitError,
-                              "Cannot write more than 256 PNG text chunks",
-                              image->filename);
-      ping_info->text[i].key=attribute->key;
-      ping_info->text[i].text=attribute->value;
-      ping_info->text[i].text_length=strlen(attribute->value);
-      ping_info->text[i].compression=image_info->compression == NoCompression ||
-        (image_info->compression == UndefinedCompression &&
-         ping_info->text[i].text_length < 128) ? -1 : 0;
-      if (logging)
-        {
-          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                "  Setting up text chunk");
-          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                "    keyword: %s",ping_info->text[i].key);
-        }
-#endif
     }
+
+  /* write eXIf profile */
+  {
+    ImageProfileIterator
+      *profile_iterator;
+
+    profile_iterator=AllocateImageProfileIterator(image);
+    if (profile_iterator)
+      {
+        const char
+          *profile_name;
+
+        const unsigned char
+          *profile_info;
+
+        size_t
+          profile_length;
+
+        while (NextImageProfile(profile_iterator,&profile_name,&profile_info,
+                                &profile_length) != MagickFail)
+          {
+            if (LocaleCompare(profile_name,"exif") == 0)
+              {
+                png_uint_32
+                  length;
+                unsigned char
+                  chunk[4];
+                const unsigned char
+                  *data;
+
+                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                   "  Have eXIf profile");
+
+                data=profile_info;
+
+                length=(png_uint_32) profile_length;
+
+                PNGType(chunk,mng_eXIf);
+
+                if (length < 7)
+                  break;  /* othewise crashes */
+
+                /* skip the "Exif\0\0" JFIF Exif Header ID */
+                length -= 6;
+
+                LogPNGChunk(logging,chunk,length);
+                (void) WriteBlobMSBULong(image,length);
+                (void) WriteBlob(image,4,chunk);
+                (void) WriteBlob(image,length,data+6);
+                (void) WriteBlobMSBULong(image,crc32(crc32(0,chunk,4),
+                  data+6, (uInt) length));
+                break;
+              }
+          }
+        DeallocateImageProfileIterator(profile_iterator);
+      }
+    }
+
   if (logging)
     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                           "  Writing PNG end info");
   png_write_end(ping,ping_info);
   if (mng_info->need_fram && (int) image->dispose == BackgroundDispose)
     {
-      if (mng_info->page.x || mng_info->page.y || (ping_info->width !=
+      if (mng_info->page.x || mng_info->page.y || (ping_width !=
                                                    mng_info->page.width) ||
-          (ping_info->height != mng_info->page.height))
+          (ping_height != mng_info->page.height))
         {
           unsigned char
             chunk[32];
@@ -7496,10 +8125,11 @@ static unsigned int WriteOnePNGImage(Mng
           PNGLong(chunk+10,(png_uint_32) (0L)); /* temporary 0 delay */
           chunk[14]=0; /* clipping boundaries delta type */
           PNGLong(chunk+15,(png_uint_32) (mng_info->page.x)); /* left cb */
-          PNGLong(chunk+19,(png_uint_32) (mng_info->page.x + ping_info->width));
+          PNGLong(chunk+19,(png_uint_32) (mng_info->page.x +
+                                          ping_width));
           PNGLong(chunk+23,(png_uint_32) (mng_info->page.y)); /* top cb */
           PNGLong(chunk+27,(png_uint_32) (mng_info->page.y +
-                                          ping_info->height));
+                                          ping_height));
           (void) WriteBlob(image,31,(char *) chunk);
           (void) WriteBlobMSBULong(image,crc32(0,chunk,31));
           mng_info->old_framing_mode=4;
@@ -7510,33 +8140,19 @@ static unsigned int WriteOnePNGImage(Mng
     }
   if (mng_info->write_mng && !mng_info->need_fram &&
       ((int) image->dispose == 3))
-    (void) ThrowException2(&image->exception,(ExceptionType) CoderError,
-                           "Cannot convert GIF with disposal method 3 to MNG-LC",
-                           (char *) NULL);
+    png_error(ping, "Cannot convert GIF with disposal method 3 to MNG-LC");
   image->depth=save_image_depth;
 
   /* Save depth actually written */
 
-  s[0]=(char) ping_info->bit_depth;
+  s[0]=(char) ping_bit_depth;
   s[1]='\0';
 
-  (void) SetImageAttribute(image,"[png_bit_depth]",s);
+  (void) SetImageAttribute(image,"[png:bit-depth-written]",s);
 
   /*
     Free PNG resources.
   */
-#if (PNG_LIBPNG_VER < 10007)
-  if (ping_info->valid & PNG_INFO_PLTE)
-    {
-      MagickFreeMemory(ping_info->palette);
-      ping_info->valid&=(~PNG_INFO_PLTE);
-    }
-#endif
-  if (ping_info->valid & PNG_INFO_tRNS)
-    {
-      MagickFreeMemory(ping_info->trans);
-      ping_info->valid&=(~PNG_INFO_tRNS);
-    }
   png_destroy_write_struct(&ping,&ping_info);
 
   MagickFreeMemory(png_pixels);
@@ -7545,14 +8161,101 @@ static unsigned int WriteOnePNGImage(Mng
   LiberateSemaphoreInfo(&png_semaphore);
 #endif
 
+
   if (logging)
     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                           "  exit WriteOnePNGImage()");
-  return (True);
+  return (MagickPass);
+
+  /* } end of setjmp-controlled block */
+
   /*  End write one PNG image */
 }
 
-static unsigned int WritePNGImage(const ImageInfo *image_info,Image *image)
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%   W r i t e P N G I m a g e                                                 %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  WritePNGImage() writes a Portable Network Graphics (PNG) or
+%  Multiple-image Network Graphics (MNG) image file.
+%
+%  MNG support written by Glenn Randers-Pehrson, glennrp@image...
+%
+%  The format of the WritePNGImage method is:
+%
+%      MagickPassFail WritePNGImage(const ImageInfo *image_info,Image *image)
+%
+%  A description of each parameter follows:
+%
+%    o image_info: the image info.
+%
+%    o image:  The image.
+%
+%  Returns MagickPass on success, MagickFail on failure.
+%
+%  While the datastream written is always in PNG format and normally
+%  would be given the "png" file extension, this method also writes
+%  the following pseudo-formats which are subsets of PNG:
+%
+%    o PNG8:  An 8-bit indexed PNG datastream is written.
+%             If transparency is present, the tRNS chunk
+%             must only have values 0 and 255 (i.e., transparency is binary:
+%             fully opaque or fully transparent).  The pixels contain 8-bit
+%             indices even if they could be represented with 1, 2, or 4 bits.
+%             Note: grayscale images will be written as indexed PNG files
+%             even though the PNG grayscale type might be slightly more
+%             efficient.
+%
+%    o PNG24: An 8-bit per sample RGB PNG datastream is written.  The tRNS
+%             chunk can be present to convey binary transparency by naming
+%             one of the colors as transparent.
+%
+%    o PNG32: An 8-bit per sample RGBA PNG is written.  Partial
+%             transparency is permitted, i.e., the alpha sample for
+%             each pixel can have any value from 0 to 255. The alpha
+%             channel is present even if the image is fully opaque.
+%
+%    o PNG48:   A 16-bit per sample RGB PNG datastream is written.  The tRNS
+%               chunk can be present to convey binary transparency by naming
+%               one of the colors as transparent.  If the image has more
+%               than one transparent color, has semitransparent pixels, or
+%               has an opaque pixel with the same RGB components as the
+%               transparent color, an image is not written.
+%
+%    o PNG64:   A 16-bit per sample RGBA PNG is written.  Partial
+%               transparency is permitted, i.e., the alpha sample for
+%               each pixel can have any value from 0 to 65535. The alpha
+%               channel is present even if the image is fully opaque.
+%
+%    o PNG00:   A PNG that inherits its colortype and bit-depth from the input
+%               image, if the input was a PNG, is written.  If these values
+%               cannot be found, then "PNG00" falls back to the regular "PNG"
+%               format.
+%
+%  If the image cannot be written in the requested PNG8|24|32|48|64
+%  format without loss, a PNG file will not be written, and MagickFail
+%  will be returned.  Since image encoders should not be responsible for
+%  the "heavy lifting", the user should make sure that GraphicsMagick has
+%  already reduced the image depth and number of colors and limit
+%  transparency to binary transparency prior to attempting to write the
+%  image in a format that is subject to depth, color, or transparency
+%  limitations.
+%
+%  TODO: Enforce the previous paragraph.
+%
+%  TODO: Allow all other PNG subformats to be requested via new
+%        "-define png:bit-depth -define png:color-type" options.
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+*/
+static MagickPassFail WritePNGImage(const ImageInfo *image_info,Image *image)
 {
   MngInfo
     *mng_info;
@@ -7573,13 +8276,13 @@ static unsigned int WritePNGImage(const
   assert(image->signature == MagickSignature);
   logging=LogMagickEvent(CoderEvent,GetMagickModule(),"enter WritePNGImage()");
   status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
-  if (status == False)
+  if (status == MagickFalse)
     ThrowWriterException(FileOpenError,UnableToOpenFile,image);
 
   /*
     Allocate a MngInfo structure.
   */
-  have_mng_structure=False;
+  have_mng_structure=MagickFalse;
   mng_info=MagickAllocateMemory(MngInfo *,sizeof(MngInfo));
   if (mng_info == (MngInfo *) NULL)
     ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image);
@@ -7588,10 +8291,68 @@ static unsigned int WritePNGImage(const
   */
   (void) memset(mng_info,0,sizeof(MngInfo));
   mng_info->image=image;
-  have_mng_structure=True;
+  have_mng_structure=MagickTrue;
   mng_info->write_png8=LocaleCompare(image_info->magick,"PNG8") == 0;
   mng_info->write_png24=LocaleCompare(image_info->magick,"PNG24") == 0;
   mng_info->write_png32=LocaleCompare(image_info->magick,"PNG32") == 0;
+  mng_info->write_png48=LocaleCompare(image_info->magick,"PNG48") == 0;
+  mng_info->write_png64=LocaleCompare(image_info->magick,"PNG64") == 0;
+
+        if (LocaleCompare(image_info->magick,"png00") == 0)
+          {
+          const ImageAttribute
+            *attribute;
+
+          /* Retrieve png:IHDR.bit-depth-orig and png:IHDR.color-type-orig */
+          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+             "  Format=%s",image_info->magick);
+
+          attribute=GetImageAttribute(image,"png:IHDR.bit-depth-orig");
+
+          if (attribute != (ImageAttribute *) NULL)
+            {
+              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                 "  png00 inherited bit depth=%s",attribute->value);
+
+              if (LocaleCompare(attribute->value,"1") == 0)
+                mng_info->write_png_depth = 1;
+
+              else if (LocaleCompare(attribute->value,"1") == 0)
+                mng_info->write_png_depth = 2;
+
+              else if (LocaleCompare(attribute->value,"2") == 0)
+                mng_info->write_png_depth = 4;
+
+              else if (LocaleCompare(attribute->value,"8") == 0)
+                mng_info->write_png_depth = 8;
+
+              else if (LocaleCompare(attribute->value,"16") == 0)
+                mng_info->write_png_depth = 16;
+            }
+
+          attribute=GetImageAttribute(image,"png:IHDR.color-type-orig");
+
+          if (attribute != (ImageAttribute *) NULL)
+            {
+              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                 "  png00 inherited color type=%s",attribute->value);
+
+              if (LocaleCompare(attribute->value,"0") == 0)
+                mng_info->write_png_colortype = 1;
+
+              else if (LocaleCompare(attribute->value,"2") == 0)
+                mng_info->write_png_colortype = 3;
+
+              else if (LocaleCompare(attribute->value,"3") == 0)
+                mng_info->write_png_colortype = 4;
+
+              else if (LocaleCompare(attribute->value,"4") == 0)
+                mng_info->write_png_colortype = 5;
+
+              else if (LocaleCompare(attribute->value,"6") == 0)
+                mng_info->write_png_colortype = 7;
+            }
+        }
 
   status=WriteOnePNGImage(mng_info,image_info,image);
 
@@ -7606,7 +8367,7 @@ static unsigned int WritePNGImage(const
 #if defined(JNG_SUPPORTED)
 
 /* Write one JNG image */
-static unsigned int WriteOneJNGImage(MngInfo *mng_info,
+static MagickPassFail WriteOneJNGImage(MngInfo *mng_info,
                                      const ImageInfo *image_info,Image *image)
 {
   Image
@@ -7639,11 +8400,19 @@ static unsigned int WriteOneJNGImage(Mng
   logging=LogMagickEvent(CoderEvent,GetMagickModule(),
                          "  enter WriteOneJNGImage()");
 
+  if (image->columns > 65535 || image->rows > 65535)
+    {
+      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                              "  JNG dimensions too large");
+      ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,
+                             image);
+    }
+
   blob=(char *) NULL;
   jpeg_image=(Image *) NULL;
   jpeg_image_info=(ImageInfo *) NULL;
 
-  status=True;
+  status=MagickTrue;
   transparent=image_info->type==GrayscaleMatteType ||
     image_info->type==TrueColorMatteType;
   jng_color_type=10;
@@ -7654,7 +8423,7 @@ static unsigned int WriteOneJNGImage(Mng
   if (image->matte)
     {
       /* if any pixels are transparent */
-      transparent=True;
+      transparent=MagickTrue;
       if (image_info->compression==JPEGCompression)
         jng_alpha_compression_method=8;
     }
@@ -7673,19 +8442,29 @@ static unsigned int WriteOneJNGImage(Mng
       if (logging)
         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                               "  Creating jpeg_image.");
-      jpeg_image=CloneImage(image,0,0,True,&image->exception);
+      jpeg_image=CloneImage(image,0,0,MagickTrue,&image->exception);
       if (jpeg_image == (Image *) NULL)
-      {
-        if (jpeg_image_info != (ImageInfo *)NULL)
-          DestroyImageInfo(jpeg_image_info);
-        ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,
-                             image);
-      }
+        {
+          if (jpeg_image_info != (ImageInfo *)NULL)
+            {
+              DestroyImageInfo(jpeg_image_info);
+            }
+          ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,
+                               image);
+        }
       DestroyBlob(jpeg_image);
       jpeg_image->blob=CloneBlobInfo((BlobInfo *) NULL);
       status=ChannelImage(jpeg_image,OpacityChannel);
-      status=NegateImage(jpeg_image,False);
-      jpeg_image->matte=False;
+      if (status != MagickFalse)
+        status=NegateImage(jpeg_image,MagickFalse);
+      if (status == MagickFalse)
+        {
+          DestroyImage(jpeg_image);
+          DestroyImageInfo(jpeg_image_info);
+          ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,
+                               image);
+        }
+      jpeg_image->matte=MagickFalse;
       if (jng_quality >= 1000)
         jpeg_image_info->quality=jng_quality/1000;
       else
@@ -7712,25 +8491,28 @@ static unsigned int WriteOneJNGImage(Mng
             *attribute;
 
           /* Encode opacity as a grayscale PNG blob */
-          status=OpenBlob(jpeg_image_info,jpeg_image,WriteBinaryBlobMode,
-                          &image->exception);
           if (logging)
             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                                   "  Creating PNG blob.");
-          length=0;
+          status=OpenBlob(jpeg_image_info,jpeg_image,WriteBinaryBlobMode,
+                          &image->exception);
+          if (status != MagickFalse)
+            {
+              length=0;
 
-          (void) strlcpy(jpeg_image_info->magick,"PNG",MaxTextExtent);
-          (void) strlcpy(jpeg_image->magick,"PNG",MaxTextExtent);
-          jpeg_image_info->interlace=NoInterlace;
-
-          blob=(char *) ImageToBlob(jpeg_image_info,jpeg_image,&length,
-                                    &image->exception);
-
-          /* Retrieve sample depth used */
-          attribute=GetImageAttribute(jpeg_image,"[png_bit_depth]");
-          if ((attribute != (const ImageAttribute *) NULL) &&
-              (attribute->value != (char *) NULL))
-            jng_alpha_sample_depth= (unsigned int) attribute->value[0];
+              (void) strlcpy(jpeg_image_info->magick,"PNG",MaxTextExtent);
+              (void) strlcpy(jpeg_image->magick,"PNG",MaxTextExtent);
+              jpeg_image_info->interlace=NoInterlace;
+
+              blob=(char *) ImageToBlob(jpeg_image_info,jpeg_image,&length,
+                                        &image->exception);
+
+              /* Retrieve sample depth used */
+              attribute=GetImageAttribute(jpeg_image,"[png:bit-depth-written]");
+              if ((attribute != (const ImageAttribute *) NULL) &&
+                  (attribute->value != (char *) NULL))
+                jng_alpha_sample_depth= (unsigned int) attribute->value[0];
+            }
         }
       else
         {
@@ -7738,26 +8520,32 @@ static unsigned int WriteOneJNGImage(Mng
 
           status=OpenBlob(jpeg_image_info,jpeg_image,WriteBinaryBlobMode,
                           &image->exception);
+          if (status != MagickFalse)
+            {
+              (void) strlcpy(jpeg_image_info->magick,"JPEG",MaxTextExtent);
+              (void) strlcpy(jpeg_image->magick,"JPEG",MaxTextExtent);
+              jpeg_image_info->interlace=NoInterlace;
+              if (logging)
+                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                      "  Creating blob.");
+              blob=(char *) ImageToBlob(jpeg_image_info,jpeg_image,&length,
+                                        &image->exception);
+              jng_alpha_sample_depth=8;
+              if (logging)
+                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                      "  Successfully read jpeg_image into a"
+                                      " blob, length=%lu.",
+                                      (unsigned long) length);
 
-          (void) strlcpy(jpeg_image_info->magick,"JPEG",MaxTextExtent);
-          (void) strlcpy(jpeg_image->magick,"JPEG",MaxTextExtent);
-          jpeg_image_info->interlace=NoInterlace;
-          if (logging)
-            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                  "  Creating blob.");
-          blob=(char *) ImageToBlob(jpeg_image_info,jpeg_image,&length,
-                                    &image->exception);
-          jng_alpha_sample_depth=8;
-          if (logging)
-            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                  "  Successfully read jpeg_image into a blob, length=%lu.",
-                                  (unsigned long) length);
-
+            }
         }
       /* Destroy JPEG image and image_info */
       (void) LiberateUniqueFileResource(jpeg_image_info->filename);
       DestroyImage(jpeg_image);
       DestroyImageInfo(jpeg_image_info);
+      if (status == MagickFalse)
+        ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,
+                             image);
     }
 
   /* Write JHDR chunk */
@@ -7769,7 +8557,7 @@ static unsigned int WriteOneJNGImage(Mng
   chunk[12]=jng_color_type;
   chunk[13]=8;  /* sample depth */
   chunk[14]=8; /*jng_image_compression_method */
-  chunk[15]=image_info->interlace == NoInterlace ? 0 : 8;
+  chunk[15]=(image_info->interlace == LineInterlace) ? 8 : 0;
   chunk[16]=jng_alpha_sample_depth;
   chunk[17]=jng_alpha_compression_method;
   chunk[18]=0; /*jng_alpha_filter_method */
@@ -7951,7 +8739,7 @@ static unsigned int WriteOneJNGImage(Mng
     {
       if (jng_alpha_compression_method==0)
         {
-          long
+          unsigned long
             len;
 
           register long
@@ -7968,9 +8756,9 @@ static unsigned int WriteOneJNGImage(Mng
           p=(unsigned char *) (blob+8);
           for (i=8; i<(long) length; i+=len+12)
             {
-              len=(*p<<24)|((*(p+1))<<16)|((*(p+2))<<8)|(*(p+3));
+              len=mng_get_long(p);
               p+=4;
-              if (*(p)==73 && *(p+1)==68 && *(p+2)==65 && *(p+3)==84) /* IDAT */
+              if (*(p)==73 && *(p+1)==68 && *(p+2)==65 && *(p+3)==84)
                 {
                   /* Found an IDAT chunk. */
                   (void) WriteBlobMSBULong(image,(unsigned long) len);
@@ -7983,7 +8771,8 @@ static unsigned int WriteOneJNGImage(Mng
                 {
                   if (logging)
                     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                          "    Skipping %c%c%c%c chunk, length=%lu.",
+                                          "    Skipping %c%c%c%c chunk,"
+                                          " length=%lu.",
                                           *(p),*(p+1),*(p+2),*(p+3),len);
                 }
               p+=(8+len);
@@ -7998,12 +8787,12 @@ static unsigned int WriteOneJNGImage(Mng
                                   (unsigned long) length);
           (void) WriteBlobMSBULong(image,(unsigned long) length);
           PNGType(chunk,mng_JDAA);
-          LogPNGChunk(logging,mng_JDAA,length);
+          LogPNGChunk(logging,mng_JDAA,(unsigned long) length);
           /* Write JDAT chunk(s) data */
           (void) WriteBlob(image,4,(char *) chunk);
           (void) WriteBlob(image,length,(char *) blob);
           (void) WriteBlobMSBULong(image,crc32(crc32(0,chunk,4),
-                                               (unsigned char *) blob,length));
+                                               (unsigned char *) blob,(uInt) length));
         }
       MagickFreeMemory(blob);
     }
@@ -8021,14 +8810,13 @@ static unsigned int WriteOneJNGImage(Mng
     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                           "  Creating jpeg_image.");
 
-  jpeg_image=CloneImage(image,0,0,True,&image->exception);
+  jpeg_image=CloneImage(image,0,0,MagickTrue,&image->exception);
   if (jpeg_image == (Image *) NULL)
-  {
-    if (jpeg_image_info != (ImageInfo *)NULL)
+    {
       DestroyImageInfo(jpeg_image_info);
-    ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,
-                         image);
-  }
+      ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,
+                           image);
+    }
   DestroyBlob(jpeg_image);
   jpeg_image->blob=CloneBlobInfo((BlobInfo *) NULL);
   (void) AcquireUniqueFilename(jpeg_image->filename);
@@ -8036,10 +8824,20 @@ static unsigned int WriteOneJNGImage(Mng
 
   status=OpenBlob(jpeg_image_info,jpeg_image,WriteBinaryBlobMode,
                   &image->exception);
+  if (status == MagickFalse)
+    {
+      if (jpeg_image != (Image *)NULL)
+        DestroyImage(jpeg_image);
+      if (jpeg_image_info != (ImageInfo *)NULL)
+        DestroyImageInfo(jpeg_image_info);
+      ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,
+                           image);
+    }
 
   if (logging)
     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                          "  Created jpeg_image, %lu x %lu.",jpeg_image->columns,
+                          "  Created jpeg_image, %lu x %lu.",
+                          jpeg_image->columns,
                           jpeg_image->rows);
 
   if (jng_color_type == 8 || jng_color_type == 12)
@@ -8055,7 +8853,8 @@ static unsigned int WriteOneJNGImage(Mng
   if (logging)
     {
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                            "  Successfully read jpeg_image into a blob, length=%lu.",
+                            "  Successfully read jpeg_image into a blob,"
+                            " length=%lu.",
                             (unsigned long) length);
 
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
@@ -8065,11 +8864,11 @@ static unsigned int WriteOneJNGImage(Mng
   /* Write JDAT chunk(s) */
   (void) WriteBlobMSBULong(image,(unsigned long) length);
   PNGType(chunk,mng_JDAT);
-  LogPNGChunk(logging,mng_JDAT,length);
+  LogPNGChunk(logging,mng_JDAT,(unsigned long) length);
   (void) WriteBlob(image,4,(char *) chunk);
   (void) WriteBlob(image,length,(char *) blob);
   (void) WriteBlobMSBULong(image,crc32(crc32(0,chunk,4),(unsigned char *)
-                                       blob,length));
+                                       blob,(uInt)length));
 
   (void) LiberateUniqueFileResource(jpeg_image_info->filename);
   DestroyImage(jpeg_image);
@@ -8090,7 +8889,34 @@ static unsigned int WriteOneJNGImage(Mng
 }
 
 
-static unsigned int WriteJNGImage(const ImageInfo *image_info,Image *image)
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%   W r i t e J N G I m a g e                                                 %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  WriteJNGImage() writes a JPEG Network Graphics (JNG) image file.
+%
+%  JNG support written by Glenn Randers-Pehrson, glennrp@image...
+%
+%  The format of the WriteJNGImage method is:
+%
+%      MagickPassFail WriteJNGImage(const ImageInfo *image_info,Image *image)
+%
+%  A description of each parameter follows:
+%
+%    o image_info: the image info.
+%
+%    o image:  The image.
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+*/
+static MagickPassFail WriteJNGImage(const ImageInfo *image_info,Image *image)
 {
   MngInfo
     *mng_info;
@@ -8111,13 +8937,13 @@ static unsigned int WriteJNGImage(const
   assert(image->signature == MagickSignature);
   logging=LogMagickEvent(CoderEvent,GetMagickModule(),"enter WriteJNGImage()");
   status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
-  if (status == False)
+  if (status == MagickFalse)
     ThrowWriterException(FileOpenError,UnableToOpenFile,image);
 
   /*
     Allocate a MngInfo structure.
   */
-  have_mng_structure=False;
+  have_mng_structure=MagickFalse;
   mng_info=MagickAllocateMemory(MngInfo *,sizeof(MngInfo));
   if (mng_info == (MngInfo *) NULL)
     ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image);
@@ -8126,7 +8952,7 @@ static unsigned int WriteJNGImage(const
   */
   (void) memset(mng_info,0,sizeof(MngInfo));
   mng_info->image=image;
-  have_mng_structure=True;
+  have_mng_structure=MagickTrue;
 
   (void) WriteBlob(image,8,"\213JNG\r\n\032\n");
 
@@ -8165,7 +8991,7 @@ static unsigned int WriteMNGImage(const
     all_images_are_gray,
     logging,
     need_defi,
-    optimize,
+    build_palette,
     use_global_plte;
 
   register long
@@ -8176,22 +9002,21 @@ static unsigned int WriteMNGImage(const
     chunk_length=0;
 #endif
 
-  unsigned char
-    chunk[800];
-
   unsigned int
     status;
 
   volatile unsigned int
-    scene,
     write_jng,
     write_mng;
 
+  volatile unsigned long
+    scene;
+
   unsigned long
     final_delay=0,
     initial_delay;
 
-#if (PNG_LIBPNG_VER < 10007)
+#if (PNG_LIBPNG_VER < 10200)
   if (image_info->verbose)
     printf("Your PNG library (libpng-%s) is rather old.\n",
            PNG_LIBPNG_VER_STRING);
@@ -8206,13 +9031,13 @@ static unsigned int WriteMNGImage(const
   assert(image->signature == MagickSignature);
   logging=LogMagickEvent(CoderEvent,GetMagickModule(),"enter WriteMNGImage()");
   status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
-  if (status == False)
+  if (status == MagickFalse)
     ThrowWriterException(FileOpenError,UnableToOpenFile,image);
 
   /*
     Allocate a MngInfo structure.
   */
-  have_mng_structure=False;
+  have_mng_structure=MagickFalse;
   mng_info=MagickAllocateMemory(MngInfo *,sizeof(MngInfo));
   if (mng_info == (MngInfo *) NULL)
     ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image);
@@ -8221,16 +9046,18 @@ static unsigned int WriteMNGImage(const
   */
   (void) memset(mng_info,0,sizeof(MngInfo));
   mng_info->image=image;
-  have_mng_structure=True;
+  have_mng_structure=MagickTrue;
 
   write_mng=LocaleCompare(image_info->magick,"MNG") == 0;
   mng_info->write_png8=LocaleCompare(image_info->magick,"PNG8") == 0;
   mng_info->write_png24=LocaleCompare(image_info->magick,"PNG24") == 0;
   mng_info->write_png32=LocaleCompare(image_info->magick,"PNG32") == 0;
+  mng_info->write_png48=LocaleCompare(image_info->magick,"PNG48") == 0;
+  mng_info->write_png64=LocaleCompare(image_info->magick,"PNG64") == 0;
 
-  write_jng=False;
+  write_jng=MagickFalse;
   if (image_info->compression==JPEGCompression)
-    write_jng=True;
+    write_jng=MagickTrue;
   else
     {
       Image
@@ -8239,18 +9066,22 @@ static unsigned int WriteMNGImage(const
       for (p=image; p != (Image *) NULL; p=p->next)
         {
           if (p->compression==JPEGCompression)
-            write_jng=True;
+            write_jng=MagickTrue;
         }
     }
 
   mng_info->adjoin=image_info->adjoin && (image->next != (Image *) NULL) &&
     write_mng;
 
-  if (mng_info->write_png8 || mng_info->write_png24 || mng_info->write_png32)
-    optimize=False;
+#ifdef GMPNG_BUILD_PALETTE
+  if (mng_info->write_png8)
+    build_palette=MagickTrue;
+  else if (mng_info->write_png24 || mng_info->write_png32 ||
+      mng_info->write_png48 || mng_info->write_png64)
+    build_palette=MagickFalse;
   else
-    optimize=(image_info->type == OptimizeType || image_info->type ==
-              UndefinedType);
+    build_palette=(image_info->type == UndefinedType);
+#endif
 
   if (logging)
     {
@@ -8258,17 +9089,9 @@ static unsigned int WriteMNGImage(const
       Image
         *p;
 
-      long
-        scene;
-
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                             "  Checking input image(s)");
-      if (optimize)
-        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                              "    Optimize: TRUE");
-      else
-        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                              "    Optimize: FALSE");
+
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                             "    Image_info depth: %ld",
                             image_info->depth);
@@ -8322,8 +9145,8 @@ static unsigned int WriteMNGImage(const
       }
   }
 
-#ifdef PNG_BUILD_PALETTE
-  if (optimize)
+#ifdef GMPNG_BUILD_PALETTE
+  if (build_palette)
     {
       /*
         Sometimes we get DirectClass images that have 256 colors or fewer.
@@ -8352,13 +9175,13 @@ static unsigned int WriteMNGImage(const
     }
 #endif
 
-  use_global_plte=False;
-  all_images_are_gray=False;
+  use_global_plte=MagickFalse;
+  all_images_are_gray=MagickFalse;
 #ifdef PNG_WRITE_EMPTY_PLTE_SUPPORTED
-  need_local_plte=True;
+  need_local_plte=MagickTrue;
 #endif
-  need_defi=False;
-  need_matte=False;
+  need_defi=MagickFalse;
+  need_matte=MagickFalse;
   mng_info->framing_mode=1;
   mng_info->old_framing_mode=1;
 
@@ -8370,10 +9193,14 @@ static unsigned int WriteMNGImage(const
         */
         SetGeometry(image,&mng_info->page);
         (void) ParseMetaGeometry(image_info->page,&mng_info->page.x,
-                                 &mng_info->page.y,&mng_info->page.width,&mng_info->page.height);
+                                 &mng_info->page.y,&mng_info->page.width,
+                                 &mng_info->page.height);
       }
   if (write_mng)
     {
+      unsigned char
+        chunk[800];
+
       unsigned int
         need_geom;
 
@@ -8383,46 +9210,49 @@ static unsigned int WriteMNGImage(const
         blue;
 
       mng_info->page=image->page;
-      need_geom=True;
+      need_geom=MagickTrue;
       if (mng_info->page.width || mng_info->page.height)
-        need_geom=False;
+        need_geom=MagickFalse;
       /*
         Check all the scenes.
       */
       initial_delay=(long) image->delay;
-      need_iterations=False;
+      need_iterations=MagickFalse;
       mng_info->equal_chrms=image->chromaticity.red_primary.x != 0.0;
-      mng_info->equal_physs=True,
-        mng_info->equal_gammas=True;
-      mng_info->equal_srgbs=True;
-      mng_info->equal_backgrounds=True;
+      mng_info->equal_physs=MagickTrue,
+        mng_info->equal_gammas=MagickTrue;
+      mng_info->equal_srgbs=MagickTrue;
+      mng_info->equal_backgrounds=MagickTrue;
       image_count=0;
 #if defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) ||  \
   defined(PNG_MNG_FEATURES_SUPPORTED)
-      all_images_are_gray=True;
-      mng_info->equal_palettes=False;
-      need_local_plte=False;
+      all_images_are_gray=MagickTrue;
+      mng_info->equal_palettes=MagickFalse;
+      need_local_plte=MagickFalse;
 #endif
       for (next_image=image; next_image != (Image *) NULL; )
         {
           if (need_geom)
             {
-              if ((next_image->columns+next_image->page.x) > mng_info->page.width)
+              if ((next_image->columns+next_image->page.x) >
+                   mng_info->page.width)
                 mng_info->page.width=next_image->columns+next_image->page.x;
-              if ((next_image->rows+next_image->page.y) > mng_info->page.height)
+              if ((next_image->rows+next_image->page.y) >
+                   mng_info->page.height)
                 mng_info->page.height=next_image->rows+next_image->page.y;
             }
           if (next_image->page.x || next_image->page.y)
-            need_defi=True;
+            need_defi=MagickTrue;
           if (next_image->matte)
-            need_matte=True;
+            need_matte=MagickTrue;
           if ((int) next_image->dispose >= BackgroundDispose)
-            if (next_image->matte || next_image->page.x || next_image->page.y ||
+            if (next_image->matte || next_image->page.x ||
+                next_image->page.y ||
                 ((next_image->columns < mng_info->page.width) &&
                  (next_image->rows < mng_info->page.height)))
-              mng_info->need_fram=True;
+              mng_info->need_fram=MagickTrue;
           if (next_image->iterations)
-            need_iterations=True;
+            need_iterations=MagickTrue;
           final_delay=next_image->delay;
           if (final_delay != initial_delay || final_delay > 100)
             mng_info->need_fram=1;
@@ -8432,11 +9262,11 @@ static unsigned int WriteMNGImage(const
             check for global palette possibility.
           */
           if (image->matte)
-            need_local_plte=True;
+            need_local_plte=MagickTrue;
           if (!need_local_plte)
             {
               if (!IsGrayImage(image,&image->exception))
-                all_images_are_gray=False;
+                all_images_are_gray=MagickFalse;
               mng_info->equal_palettes=PalettesAreEqual(image,next_image);
               if (!use_global_plte)
                 use_global_plte=mng_info->equal_palettes;
@@ -8451,16 +9281,17 @@ static unsigned int WriteMNGImage(const
                   next_image->next->background_color.green ||
                   next_image->background_color.blue !=
                   next_image->next->background_color.blue)
-                mng_info->equal_backgrounds=False;
+                mng_info->equal_backgrounds=MagickFalse;
               if (next_image->gamma != next_image->next->gamma)
-                mng_info->equal_gammas=False;
+                mng_info->equal_gammas=MagickFalse;
               if (next_image->rendering_intent !=
                   next_image->next->rendering_intent)
-                mng_info->equal_srgbs=False;
+                mng_info->equal_srgbs=MagickFalse;
               if ((next_image->units != next_image->next->units) ||
-                  (next_image->x_resolution != next_image->next->x_resolution) ||
+                  (next_image->x_resolution !=
+                  next_image->next->x_resolution) ||
                   (next_image->y_resolution != next_image->next->y_resolution))
-                mng_info->equal_physs=False;
+                mng_info->equal_physs=MagickFalse;
               if (mng_info->equal_chrms)
                 {
                   if (next_image->chromaticity.red_primary.x !=
@@ -8479,7 +9310,7 @@ static unsigned int WriteMNGImage(const
                       next_image->next->chromaticity.white_point.x ||
                       next_image->chromaticity.white_point.y !=
                       next_image->next->chromaticity.white_point.y)
-                    mng_info->equal_chrms=False;
+                    mng_info->equal_chrms=MagickFalse;
                 }
             }
           image_count++;
@@ -8487,16 +9318,16 @@ static unsigned int WriteMNGImage(const
         }
       if (image_count < 2)
         {
-          mng_info->equal_backgrounds=False;
-          mng_info->equal_chrms=False;
-          mng_info->equal_gammas=False;
-          mng_info->equal_srgbs=False;
-          mng_info->equal_physs=False;
-          use_global_plte=False;
+          mng_info->equal_backgrounds=MagickFalse;
+          mng_info->equal_chrms=MagickFalse;
+          mng_info->equal_gammas=MagickFalse;
+          mng_info->equal_srgbs=MagickFalse;
+          mng_info->equal_physs=MagickFalse;
+          use_global_plte=MagickFalse;
 #ifdef PNG_WRITE_EMPTY_PLTE_SUPPORTED
-          need_local_plte=True;
+          need_local_plte=MagickTrue;
 #endif
-          need_iterations=False;
+          need_iterations=MagickFalse;
         }
       if (!mng_info->need_fram)
         {
@@ -8513,7 +9344,8 @@ static unsigned int WriteMNGImage(const
                   */
                   final_delay=10;
                   (void) ThrowException2(&image->exception,CoderError,
-                                         "input has zero delay between all frames; assuming 10 cs",
+                                         "input has zero delay between"
+                                         " all frames; assuming 10 cs",
                                          (char *) NULL);
                 }
               else
@@ -8526,11 +9358,14 @@ static unsigned int WriteMNGImage(const
           if (final_delay > 75)
             mng_info->ticks_per_second=1;
           if (final_delay > 125)
-            mng_info->need_fram=True;
+            mng_info->need_fram=MagickTrue;
           if (need_defi && final_delay > 2 && (final_delay != 4) &&
-              (final_delay != 5) && (final_delay != 10) && (final_delay != 20) &&
-              (final_delay != 25) && (final_delay != 50) && (final_delay != 100))
-            mng_info->need_fram=True;  /* make it exact; cannot be VLC anyway */
+              (final_delay != 5) && (final_delay != 10) &&
+              (final_delay != 20) &&
+              (final_delay != 25) && (final_delay != 50) &&
+              (final_delay != 100))
+            mng_info->need_fram=MagickTrue;  /* make it exact;
+                                          cannot be VLC anyway */
         }
       if (mng_info->need_fram)
         mng_info->ticks_per_second=100;
@@ -8564,9 +9399,11 @@ static unsigned int WriteMNGImage(const
           else
             {
               if (need_defi || mng_info->need_fram || use_global_plte)
-                PNGLong(chunk+28,19L);  /* simplicity=LC+JNG, no transparency */
+                PNGLong(chunk+28,19L);  /* simplicity=LC+JNG,
+                                           no transparency */
               else
-                PNGLong(chunk+28,17L);  /* simplicity=VLC+JNG, no transparency */
+                PNGLong(chunk+28,17L);  /* simplicity=VLC+JNG,
+                                           no transparency */
             }
         }
       else
@@ -8598,11 +9435,11 @@ static unsigned int WriteMNGImage(const
           */
           PNGType(chunk,mng_nEED);
           chunk_length = (strlcpy((char *) chunk+4, "CACHEOFF",20));
-          (void) WriteBlobMSBULong(image,chunk_length);
-          LogPNGChunk(logging,mng_nEED,chunk_length);
+          (void) WriteBlobMSBULong(image,(const unsigned long) chunk_length);
+          LogPNGChunk(logging,mng_nEED,(unsigned long) chunk_length);
           chunk_length += 4;
           (void) WriteBlob(image,chunk_length,(char *) chunk);
-          (void) WriteBlobMSBULong(image,crc32(0,chunk,chunk_length));
+          (void) WriteBlobMSBULong(image,crc32(0,chunk,(uInt) chunk_length));
         }
 #endif
       if ((image->previous == (Image *) NULL) &&
@@ -8626,10 +9463,13 @@ static unsigned int WriteMNGImage(const
             {
               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                                     "     TERM delay: %lu",
-                                    (png_uint_32) (mng_info->ticks_per_second*final_delay/100));
+                                    (unsigned long)
+                                    (mng_info->ticks_per_second*
+                                    final_delay/100));
               if (image->iterations == 0)
                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                      "     TERM iterations: %lu",PNG_MAX_UINT);
+                                      "     TERM iterations: %lu",
+                                      (unsigned long)PNG_MAX_UINT);
               else
                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                                       "     Image iterations: %lu",
@@ -8656,7 +9496,7 @@ static unsigned int WriteMNGImage(const
             chunk[4]=(int) PerceptualIntent-1;
           (void) WriteBlob(image,5,(char *) chunk);
           (void) WriteBlobMSBULong(image,crc32(0,chunk,5));
-          mng_info->have_write_global_srgb=True;
+          mng_info->have_write_global_srgb=MagickTrue;
         }
       else
         {
@@ -8671,7 +9511,7 @@ static unsigned int WriteMNGImage(const
               PNGLong(chunk+4,(unsigned long) (100000*image->gamma+0.5));
               (void) WriteBlob(image,8,(char *) chunk);
               (void) WriteBlobMSBULong(image,crc32(0,chunk,8));
-              mng_info->have_write_global_gama=True;
+              mng_info->have_write_global_gama=MagickTrue;
             }
           if (mng_info->equal_chrms)
             {
@@ -8698,7 +9538,7 @@ static unsigned int WriteMNGImage(const
               PNGLong(chunk+32,(unsigned long) (100000*primary.y+0.5));
               (void) WriteBlob(image,36,(char *) chunk);
               (void) WriteBlobMSBULong(image,crc32(0,chunk,36));
-              mng_info->have_write_global_chrm=True;
+              mng_info->have_write_global_chrm=MagickTrue;
             }
         }
       if (image->x_resolution && image->y_resolution && mng_info->equal_physs)
@@ -8741,11 +9581,14 @@ static unsigned int WriteMNGImage(const
         Write MNG BACK chunk and global bKGD chunk, if the image is transparent
         or does not cover the entire frame.
       */
-      if (write_mng && (image->matte || image->page.x > 0 || image->page.y > 0 ||
-                        (image->page.width && (image->page.width+image->page.x <
-                                               mng_info->page.width))
-                        || (image->page.height && (image->page.height+image->page.y
-                                                   < mng_info->page.height))))
+      if (write_mng && (image->matte || image->page.x > 0 ||
+                        image->page.y > 0 ||
+                        (image->page.width &&
+                        (image->page.width+image->page.x <
+                        mng_info->page.width))
+                        || (image->page.height &&
+                        (image->page.height+image->page.y <
+                        mng_info->page.height))))
         {
           (void) WriteBlobMSBULong(image,6L);
           PNGType(chunk,mng_BACK);
@@ -8790,7 +9633,7 @@ static unsigned int WriteMNGImage(const
             }
           (void) WriteBlob(image,data_length+4,(char *) chunk);
           (void) WriteBlobMSBULong(image,crc32(0,chunk,(int) (data_length+4)));
-          mng_info->have_write_global_plte=True;
+          mng_info->have_write_global_plte=MagickTrue;
         }
 #endif
     }
@@ -8798,10 +9641,13 @@ static unsigned int WriteMNGImage(const
   mng_info->delay=0;
 #if defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) ||  \
   defined(PNG_MNG_FEATURES_SUPPORTED)
-  mng_info->equal_palettes=False;
+  mng_info->equal_palettes=MagickFalse;
 #endif
   do
     {
+      unsigned char
+        chunk[800];
+
       if (mng_info->adjoin)
         {
 #if defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) ||  \
@@ -8815,12 +9661,13 @@ static unsigned int WriteMNGImage(const
               if (mng_info->IsPalette)
                 {
                   /*
-                    When equal_palettes is true, this image has the same palette
-                    as the previous PseudoClass image
+                    When equal_palettes is true, this image has the
+                    same palette as the previous PseudoClass image
                   */
                   mng_info->have_write_global_plte=mng_info->equal_palettes;
                   mng_info->equal_palettes=PalettesAreEqual(image,image->next);
-                  if (mng_info->equal_palettes && !mng_info->have_write_global_plte)
+                  if (mng_info->equal_palettes &&
+                      !mng_info->have_write_global_plte)
                     {
                       /*
                         Write MNG PLTE chunk
@@ -8834,18 +9681,22 @@ static unsigned int WriteMNGImage(const
                       LogPNGChunk(logging,mng_PLTE,data_length);
                       for (i=0; i < (long) image->colors; i++)
                         {
-                          chunk[4+i*3]=ScaleQuantumToChar(image->colormap[i].red);
-                          chunk[5+i*3]=ScaleQuantumToChar(image->colormap[i].green);
-                          chunk[6+i*3]=ScaleQuantumToChar(image->colormap[i].blue);
+                          chunk[4+i*3]=
+                             ScaleQuantumToChar(image->colormap[i].red);
+                          chunk[5+i*3]=
+                             ScaleQuantumToChar(image->colormap[i].green);
+                          chunk[6+i*3]=
+                             ScaleQuantumToChar(image->colormap[i].blue);
                         }
                       (void) WriteBlob(image,data_length+4,(char *) chunk);
-                      (void) WriteBlobMSBULong(image,crc32(0,chunk,
-                                                           (int) (data_length+4)));
-                      mng_info->have_write_global_plte=True;
+                      (void) WriteBlobMSBULong(image,
+                                               crc32(0,chunk,(int)
+                                               (data_length+4)));
+                      mng_info->have_write_global_plte=MagickTrue;
                     }
                 }
               else
-                mng_info->have_write_global_plte=False;
+                mng_info->have_write_global_plte=MagickFalse;
             }
 #endif
           if (need_defi)
@@ -8892,9 +9743,6 @@ static unsigned int WriteMNGImage(const
           ((image->delay != mng_info->delay) ||
            (mng_info->framing_mode != mng_info->old_framing_mode)))
         {
-          unsigned char
-            chunk[16];
-
           if (image->delay == mng_info->delay)
             {
               /*
@@ -8953,18 +9801,21 @@ static unsigned int WriteMNGImage(const
         {
           MngInfoFreeStruct(mng_info,&have_mng_structure);
           CloseBlob(image);
-          return (False);
+          return (MagickFail);
         }
       (void) CatchImageException(image);
       if (image->next == (Image *) NULL)
         break;
       image=SyncNextImageInList(image);
       if (!MagickMonitor(SaveImagesTag,scene++,GetImageListLength(image),
-                         &image->exception))
-        break;
+          &image->exception))
+          break;
     } while (mng_info->adjoin);
   if (write_mng)
     {
+      unsigned char
+        chunk[16];
+
       while (image->previous != (Image *) NULL)
         image=image->previous;
       /*
@@ -8983,9 +9834,9 @@ static unsigned int WriteMNGImage(const
   MngInfoFreeStruct(mng_info,&have_mng_structure);
   if (logging)
     (void) LogMagickEvent(CoderEvent,GetMagickModule(),"exit WriteMNGImage()");
-  return(True);
+  return(MagickPass);
 }
-#else /* PNG_LIBPNG_VER > 95 */
+#else /* PNG_LIBPNG_VER > 10011 */
 static unsigned int WritePNGImage(const ImageInfo *image_info,Image *image)
 {
   image=image;
@@ -8997,5 +9848,5 @@ static unsigned int WriteMNGImage(const
 {
   return (WritePNGImage(image_info,image));
 }
-#endif /* PNG_LIBPNG_VER > 95 */
+#endif /* PNG_LIBPNG_VER > 10011 */
 #endif
