png.c revision cecd5765c41f64cc68d4a5d77bb4afe92707a49e
13ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
23ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
43ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
53ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
63ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                            PPPP   N   N   GGGG                              %
73ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                            P   P  NN  N  G                                  %
83ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                            PPPP   N N N  G  GG                              %
93ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                            P      N  NN  G   G                              %
103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                            P      N   N   GGG                               %
113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%              Read/Write Portable Network Graphics Image Format              %
143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                              Software Design                                %
163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                John Cristy                                  %
173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                           Glenn Randers-Pehrson                             %
183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                               November 1997                                 %
193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2116af1cbdffcc02e7239d432e5fb51734fcf9f9ffcristy%  Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization      %
223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  dedicated to making software imaging solutions freely available.           %
233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  You may not use this file except in compliance with the License.  You may  %
253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  obtain a copy of the License at                                            %
263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    http://www.imagemagick.org/script/license.php                            %
283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  Unless required by applicable law or agreed to in writing, software        %
303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  distributed under the License is distributed on an "AS IS" BASIS,          %
313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  See the License for the specific language governing permissions and        %
333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  limitations under the License.                                             %
343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Include declarations.
433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/studio.h"
455a2ca481ab4ff6751bba842263739966e53441aacristy#include "magick/attribute.h"
463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/blob.h"
473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/blob-private.h"
483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/cache.h"
493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/color.h"
503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/color-private.h"
513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/colorspace.h"
523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/constitute.h"
533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/enhance.h"
543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/exception.h"
553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/exception-private.h"
563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/geometry.h"
57f2e1166e90de2dfe2e6a2aed7cd5f73640f34a7acristy#include "magick/histogram.h"
583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/image.h"
593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/image-private.h"
603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/layer.h"
613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/list.h"
623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/log.h"
633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/magick.h"
643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/memory_.h"
653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/module.h"
663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/monitor.h"
673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/monitor-private.h"
683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/option.h"
693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/quantum-private.h"
703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/profile.h"
713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/property.h"
723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/quantize.h"
733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/resource_.h"
743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/semaphore.h"
753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/quantum-private.h"
763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/static.h"
773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/statistic.h"
783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/string_.h"
79f2f2727f17ecbb23d902f70bb98f81faabc92dbdcristy#include "magick/string-private.h"
803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/transform.h"
813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/utility.h"
823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MAGICKCORE_PNG_DELEGATE)
83286a6355c4544b794da2b6df973faad07c69e541glennrp
847ef138c2e0e2bd4acefd810968b0324f6dc469f1glennrp/* Suppress libpng pedantic warnings that were added in
857ef138c2e0e2bd4acefd810968b0324f6dc469f1glennrp * libpng-1.2.41 and libpng-1.4.0.  If you are working on
867ef138c2e0e2bd4acefd810968b0324f6dc469f1glennrp * migration to libpng-2.0, remove these defines and then
877ef138c2e0e2bd4acefd810968b0324f6dc469f1glennrp * fix any code that generates warnings.
887ef138c2e0e2bd4acefd810968b0324f6dc469f1glennrp */
89991e92a91acb9e432cd6c05843e4f6a57643e29dglennrp/* #define PNG_DEPRECATED   Use of this function is deprecated */
907ef138c2e0e2bd4acefd810968b0324f6dc469f1glennrp#define PNG_USE_RESULT  /* The result of this function must be checked */
917ef138c2e0e2bd4acefd810968b0324f6dc469f1glennrp#define PNG_NORETURN    /* This function does not return */
927ef138c2e0e2bd4acefd810968b0324f6dc469f1glennrp#define PNG_ALLOCATED   /* The result of the function is new memory */
937ef138c2e0e2bd4acefd810968b0324f6dc469f1glennrp#define PNG_DEPSTRUCT   /* Access to this struct member is deprecated */
94286a6355c4544b794da2b6df973faad07c69e541glennrp
953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "png.h"
963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "zlib.h"
973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* ImageMagick differences */
993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define first_scene scene
1003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if PNG_LIBPNG_VER < 10400
1022c74c978809443456f5a21cd43b25b0a55c7881aglennrp#    define trans_color  trans_values   /* Changed at libpng-1.4.0beta35 */
1032c74c978809443456f5a21cd43b25b0a55c7881aglennrp#    define trans_alpha  trans          /* Changed at libpng-1.4.0beta74 */
1042c74c978809443456f5a21cd43b25b0a55c7881aglennrp#else
1052c74c978809443456f5a21cd43b25b0a55c7881aglennrp   /* We could parse PNG_LIBPNG_VER_STRING here but it's too much bother..
1062c74c978809443456f5a21cd43b25b0a55c7881aglennrp    * Just don't use libpng-1.4.0beta32-34 or beta67-73
1072c74c978809443456f5a21cd43b25b0a55c7881aglennrp    */
1082c74c978809443456f5a21cd43b25b0a55c7881aglennrp#  ifndef  PNG_USER_CHUNK_CACHE_MAX     /* Added at libpng-1.4.0beta32 */
1092c74c978809443456f5a21cd43b25b0a55c7881aglennrp#    define trans_color  trans_values   /* Changed at libpng-1.4.0beta35 */
1102c74c978809443456f5a21cd43b25b0a55c7881aglennrp#  endif
1112c74c978809443456f5a21cd43b25b0a55c7881aglennrp#  ifndef  PNG_TRANSFORM_GRAY_TO_RGB    /* Added at libpng-1.4.0beta67 */
1122c74c978809443456f5a21cd43b25b0a55c7881aglennrp#    define trans_alpha  trans          /* Changed at libpng-1.4.0beta74 */
1132c74c978809443456f5a21cd43b25b0a55c7881aglennrp#  endif
1143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
1153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
116c451207335b7a8bb4e44f904f3d65a2727e41214glennrp#if PNG_LIBPNG_VER > 10011
1173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
1183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Optional declarations. Define or undefine them as you like.
1193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
1203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* #define PNG_DEBUG -- turning this on breaks VisualC compiling */
1213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
1233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Features under construction.  Define these to work on them.
1243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
1253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#undef MNG_OBJECT_BUFFERS
1263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#undef MNG_BASI_SUPPORTED
1273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define MNG_COALESCE_LAYERS /* In 5.4.4, this interfered with MMAP'ed files. */
1283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define MNG_INSERT_LAYERS   /* Troublesome, but seem to work as of 5.4.4 */
1293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define PNG_BUILD_PALETTE   /* This works as of 5.4.3. */
1303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define PNG_SORT_PALETTE    /* This works as of 5.4.0. */
1313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MAGICKCORE_JPEG_DELEGATE)
1323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#  define JNG_SUPPORTED /* Not finished as of 5.5.2.  See "To do" comments. */
1333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
1343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if !defined(RGBColorMatchExact)
1353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define IsPNGColorEqual(color,target) \
1363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   (((color).red == (target).red) && \
1373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ((color).green == (target).green) && \
1383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ((color).blue == (target).blue))
1393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
1403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
1423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Establish thread safety.
1433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  setjmp/longjmp is claimed to be safe on these platforms:
1443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  setjmp/longjmp is alleged to be unsafe on these platforms:
1453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
1463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#ifndef SETJMP_IS_THREAD_SAFE
1473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define PNG_SETJMP_NOT_THREAD_SAFE
1483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
1493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
1513ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic SemaphoreInfo
1523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *png_semaphore = (SemaphoreInfo *) NULL;
1533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
1543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
1563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  This temporary until I set up malloc'ed object attributes array.
1573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Recompile with MNG_MAX_OBJECTS=65536L to avoid this limit but
1583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  waste more memory.
1593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
1603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define MNG_MAX_OBJECTS 256
1613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
1633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  If this not defined, spec is interpreted strictly.  If it is
1643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  defined, an attempt will be made to recover from some errors,
1653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  including
1663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      o global PLTE too short
1673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
1683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#undef MNG_LOOSE
1693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
1713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Don't try to define PNG_MNG_FEATURES_SUPPORTED here.  Make sure
1723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  it's defined in libpng/pngconf.h, version 1.0.9 or later.  It won't work
1733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  with earlier versions of libpng.  From libpng-1.0.3a to libpng-1.0.8,
1743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  PNG_READ|WRITE_EMPTY_PLTE were used but those have been deprecated in
1753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  libpng in favor of PNG_MNG_FEATURES_SUPPORTED, so we set them here.
1763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  PNG_MNG_FEATURES_SUPPORTED is disabled by default in libpng-1.0.9 and
1773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  will be enabled by default in libpng-1.2.0.
1783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
1793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#ifdef PNG_MNG_FEATURES_SUPPORTED
1803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#  ifndef PNG_READ_EMPTY_PLTE_SUPPORTED
1813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#    define PNG_READ_EMPTY_PLTE_SUPPORTED
1823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#  endif
1833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#  ifndef PNG_WRITE_EMPTY_PLTE_SUPPORTED
1843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#    define PNG_WRITE_EMPTY_PLTE_SUPPORTED
1853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#  endif
1863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
1873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
1893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Maximum valid unsigned long in PNG/MNG chunks is (2^31)-1
1903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  This macro is only defined in libpng-1.0.3 and later.
1913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Previously it was PNG_MAX_UINT but that was deprecated in libpng-1.2.6
1923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
1933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#ifndef PNG_UINT_31_MAX
1943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define PNG_UINT_31_MAX (png_uint_32) 0x7fffffffL
1953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
1963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
1983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Constant strings for known chunk types.  If you need to add a chunk,
1993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  add a string holding the name here.   To make the code more
2003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  portable, we use ASCII numbers like this, not characters.
2013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
2023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2033ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_MHDR[5]={ 77,  72,  68,  82, (png_byte) '\0'};
2043ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_BACK[5]={ 66,  65,  67,  75, (png_byte) '\0'};
2053ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_BASI[5]={ 66,  65,  83,  73, (png_byte) '\0'};
2063ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_CLIP[5]={ 67,  76,  73,  80, (png_byte) '\0'};
2073ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_CLON[5]={ 67,  76,  79,  78, (png_byte) '\0'};
2083ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_DEFI[5]={ 68,  69,  70,  73, (png_byte) '\0'};
2093ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_DHDR[5]={ 68,  72,  68,  82, (png_byte) '\0'};
2103ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_DISC[5]={ 68,  73,  83,  67, (png_byte) '\0'};
2113ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_ENDL[5]={ 69,  78,  68,  76, (png_byte) '\0'};
2123ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_FRAM[5]={ 70,  82,  65,  77, (png_byte) '\0'};
2133ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_IEND[5]={ 73,  69,  78,  68, (png_byte) '\0'};
2143ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_IHDR[5]={ 73,  72,  68,  82, (png_byte) '\0'};
2153ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_JHDR[5]={ 74,  72,  68,  82, (png_byte) '\0'};
2163ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_LOOP[5]={ 76,  79,  79,  80, (png_byte) '\0'};
2173ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_MAGN[5]={ 77,  65,  71,  78, (png_byte) '\0'};
2183ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_MEND[5]={ 77,  69,  78,  68, (png_byte) '\0'};
2193ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_MOVE[5]={ 77,  79,  86,  69, (png_byte) '\0'};
2203ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_PAST[5]={ 80,  65,  83,  84, (png_byte) '\0'};
2213ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_PLTE[5]={ 80,  76,  84,  69, (png_byte) '\0'};
2223ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_SAVE[5]={ 83,  65,  86,  69, (png_byte) '\0'};
2233ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_SEEK[5]={ 83,  69,  69,  75, (png_byte) '\0'};
2243ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_SHOW[5]={ 83,  72,  79,  87, (png_byte) '\0'};
2253ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_TERM[5]={ 84,  69,  82,  77, (png_byte) '\0'};
2263ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_bKGD[5]={ 98,  75,  71,  68, (png_byte) '\0'};
2273ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_cHRM[5]={ 99,  72,  82,  77, (png_byte) '\0'};
2283ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_gAMA[5]={103,  65,  77,  65, (png_byte) '\0'};
2293ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_iCCP[5]={105,  67,  67,  80, (png_byte) '\0'};
2303ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_nEED[5]={110,  69,  69,  68, (png_byte) '\0'};
2313ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_pHYg[5]={112,  72,  89, 103, (png_byte) '\0'};
2323ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_vpAg[5]={118, 112,  65, 103, (png_byte) '\0'};
2333ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_pHYs[5]={112,  72,  89, 115, (png_byte) '\0'};
2343ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_sBIT[5]={115,  66,  73,  84, (png_byte) '\0'};
2353ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_sRGB[5]={115,  82,  71,  66, (png_byte) '\0'};
2363ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_tRNS[5]={116,  82,  78,  83, (png_byte) '\0'};
2373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(JNG_SUPPORTED)
2393ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_IDAT[5]={ 73,  68,  65,  84, (png_byte) '\0'};
2403ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_JDAT[5]={ 74,  68,  65,  84, (png_byte) '\0'};
2413ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_JDAA[5]={ 74,  68,  65,  65, (png_byte) '\0'};
2423ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_JdAA[5]={ 74, 100,  65,  65, (png_byte) '\0'};
2433ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_JSEP[5]={ 74,  83,  69,  80, (png_byte) '\0'};
2443ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_oFFs[5]={111,  70,  70, 115, (png_byte) '\0'};
2453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
2463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
2483ed852eea50f9d4cd633efb8c2b054b8e33c253cristyOther known chunks that are not yet supported by ImageMagick:
2493ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_hIST[5]={104,  73,  83,  84, (png_byte) '\0'};
2503ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_iCCP[5]={105,  67,  67,  80, (png_byte) '\0'};
2513ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_iTXt[5]={105,  84,  88, 116, (png_byte) '\0'};
2523ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_sPLT[5]={115,  80,  76,  84, (png_byte) '\0'};
2533ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_sTER[5]={115,  84,  69,  82, (png_byte) '\0'};
2543ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_tEXt[5]={116,  69,  88, 116, (png_byte) '\0'};
2553ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_tIME[5]={116,  73,  77,  69, (png_byte) '\0'};
2563ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_byte FARDATA mng_zTXt[5]={122,  84,  88, 116, (png_byte) '\0'};
2573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
2583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2593ed852eea50f9d4cd633efb8c2b054b8e33c253cristytypedef struct _MngBox
2603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
2613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  long
2623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    left,
2633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    right,
2643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    top,
2653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    bottom;
2663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} MngBox;
2673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2683ed852eea50f9d4cd633efb8c2b054b8e33c253cristytypedef struct _MngPair
2693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
2703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  volatile long
2713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    a,
2723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    b;
2733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} MngPair;
2743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#ifdef MNG_OBJECT_BUFFERS
2763ed852eea50f9d4cd633efb8c2b054b8e33c253cristytypedef struct _MngBuffer
2773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
2783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned long
2803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    height,
2813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    width;
2823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
2843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *image;
2853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_color
2873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    plte[256];
2883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  int
2903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    reference_count;
2913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned char
2933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    alpha_sample_depth,
2943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    compression_method,
2953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    color_type,
2963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    concrete,
2973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    filter_method,
2983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    frozen,
2993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image_type,
3003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    interlace_method,
3013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pixel_sample_depth,
3023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    plte_length,
3033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    sample_depth,
3043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    viewable;
3053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} MngBuffer;
3063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
3073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3083ed852eea50f9d4cd633efb8c2b054b8e33c253cristytypedef struct _MngInfo
3093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
3103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#ifdef MNG_OBJECT_BUFFERS
3123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MngBuffer
3133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *ob[MNG_MAX_OBJECTS];
3143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
3153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image *
3173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image;
3183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  RectangleInfo
3203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    page;
3213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  int
3233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    adjoin,
3243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#ifndef PNG_READ_EMPTY_PLTE_SUPPORTED
3253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    bytes_in_read_buffer,
3263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    found_empty_plte,
3273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
3283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    equal_backgrounds,
3293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    equal_chrms,
3303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    equal_gammas,
3313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) || \
3323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    defined(PNG_MNG_FEATURES_SUPPORTED)
3333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    equal_palettes,
3343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
3353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    equal_physs,
3363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    equal_srgbs,
3373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    framing_mode,
3383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    have_global_bkgd,
3393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    have_global_chrm,
3403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    have_global_gama,
3413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    have_global_phys,
3423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    have_global_sbit,
3433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    have_global_srgb,
3443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    have_saved_bkgd_index,
3453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    have_write_global_chrm,
3463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    have_write_global_gama,
3473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    have_write_global_plte,
3483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    have_write_global_srgb,
3493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    need_fram,
3503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    object_id,
3513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    old_framing_mode,
3523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    optimize,
3533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    saved_bkgd_index;
3543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  int
3563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    new_number_colors;
3573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  long
3593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image_found,
3603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    loop_count[256],
3613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    loop_iteration[256],
3623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    scenes_found,
3633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x_off[MNG_MAX_OBJECTS],
3643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    y_off[MNG_MAX_OBJECTS];
3653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MngBox
3673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    clip,
3683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    frame,
3693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image_box,
3703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    object_clip[MNG_MAX_OBJECTS];
3713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned char
3733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /* These flags could be combined into one byte */
3743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    exists[MNG_MAX_OBJECTS],
3753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    frozen[MNG_MAX_OBJECTS],
3763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    loop_active[256],
3773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    invisible[MNG_MAX_OBJECTS],
3783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    viewable[MNG_MAX_OBJECTS];
3793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickOffsetType
3813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    loop_jump[256];
3823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_colorp
3843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    global_plte;
3853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_color_8
3873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    global_sbit;
3883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_byte
3903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#ifndef PNG_READ_EMPTY_PLTE_SUPPORTED
3913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    read_buffer[8],
3923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
3933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    global_trns[256];
3943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  float
3963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    global_gamma;
3973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ChromaticityInfo
3993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    global_chrm;
4003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  RenderingIntent
4023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    global_srgb_intent;
4033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned long
4053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    delay,
4063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    global_plte_length,
4073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    global_trns_length,
4083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    global_x_pixels_per_unit,
4093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    global_y_pixels_per_unit,
4103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    mng_width,
4113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    mng_height,
4123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ticks_per_second;
4133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned int
4153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    IsPalette,
4163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    global_phys_unit_type,
4173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    basi_warning,
4183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    clon_warning,
4193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    dhdr_warning,
4203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    jhdr_warning,
4213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    magn_warning,
4223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    past_warning,
4233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    phyg_warning,
4243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    phys_warning,
4253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    sbit_warning,
4263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    show_warning,
4273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    mng_type,
4283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    write_mng,
4293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    write_png_colortype,
4303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    write_png_depth,
4313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    write_png8,
4323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    write_png24,
4333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    write_png32;
4343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#ifdef MNG_BASI_SUPPORTED
4363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned long
4373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    basi_width,
4383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    basi_height;
4393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned int
4413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    basi_depth,
4423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    basi_color_type,
4433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    basi_compression_method,
4443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    basi_filter_type,
4453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    basi_interlace_method,
4463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    basi_red,
4473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    basi_green,
4483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    basi_blue,
4493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    basi_alpha,
4503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    basi_viewable;
4513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
4523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_uint_16
4543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    magn_first,
4553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    magn_last,
4563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    magn_mb,
4573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    magn_ml,
4583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    magn_mr,
4593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    magn_mt,
4603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    magn_mx,
4613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    magn_my,
4623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    magn_methx,
4633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    magn_methy;
4643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  PixelPacket
4663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    mng_global_bkgd;
4673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} MngInfo;
4693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif /* VER */
4703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
4723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Forward declarations.
4733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
4743ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType
4753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  WritePNGImage(const ImageInfo *,Image *);
4763ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType
4773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  WriteMNGImage(const ImageInfo *,Image *);
4783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(JNG_SUPPORTED)
4793ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType
4803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  WriteJNGImage(const ImageInfo *,Image *);
4813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
4823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4833ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic inline long MagickMax(const long x,const long y)
4843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
4853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (x > y)
4863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(x);
4873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(y);
4883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
4893ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic inline long MagickMin(const long x,const long y)
4903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
4913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (x < y)
4923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(x);
4933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(y);
4943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
4953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
496c451207335b7a8bb4e44f904f3d65a2727e41214glennrp#if PNG_LIBPNG_VER > 10111
4973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_SORT_PALETTE)
4983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
4993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   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                       %
5043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  CompressColormapTransFirst compresses an image colormap removing
5103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  any duplicate and unused color entries and putting the transparent colors
5113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  first.  Returns MagickTrue on success, MagickFalse on error.
5123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the CompressColormapTransFirst method is:
5143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      unsigned int CompressColormapTransFirst(Image *image)
5163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
5183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image: the address of a structure of type Image.
52098156a3a465a004545e39434c63052b955a74d1cglennrp%      This function updates image->colors and image->colormap.
5213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
5233ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType CompressColormapTransFirst(Image *image)
5243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
5253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  int
5263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    remap_needed,
5273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    k;
5283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  long
5303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    j,
5313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    new_number_colors,
5323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    number_colors,
5333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    y;
5343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  PixelPacket
5363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *colormap;
5373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register const IndexPacket
5393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *indices;
5403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register const PixelPacket
5423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p;
5433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  IndexPacket
5453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    top_used;
5463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register long
5483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i,
5493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x;
5503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  IndexPacket
5523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *map,
5533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *opacity;
5543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned char
5563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *marker,
5573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    have_transparency;
5583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
5603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Determine if colormap can be compressed.
5613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
5623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (Image *) NULL);
5633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image->signature == MagickSignature);
5643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
56598156a3a465a004545e39434c63052b955a74d1cglennrp    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
56698156a3a465a004545e39434c63052b955a74d1cglennrp           "    CompressColorMapTransFirst %s (%ld colors)",
56798156a3a465a004545e39434c63052b955a74d1cglennrp           image->filename,image->colors);
5683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->storage_class != PseudoClass || image->colors > 256 ||
5693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->colors < 2)
57098156a3a465a004545e39434c63052b955a74d1cglennrp    {
57198156a3a465a004545e39434c63052b955a74d1cglennrp      if (image->debug != MagickFalse)
57298156a3a465a004545e39434c63052b955a74d1cglennrp        {
57398156a3a465a004545e39434c63052b955a74d1cglennrp          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
57498156a3a465a004545e39434c63052b955a74d1cglennrp               "    Could not compress colormap");
57598156a3a465a004545e39434c63052b955a74d1cglennrp          if (image->colors > 256 || image->colors == 0)
57698156a3a465a004545e39434c63052b955a74d1cglennrp            return(MagickFalse);
57798156a3a465a004545e39434c63052b955a74d1cglennrp          else
57898156a3a465a004545e39434c63052b955a74d1cglennrp            return(MagickTrue);
57998156a3a465a004545e39434c63052b955a74d1cglennrp        }
58098156a3a465a004545e39434c63052b955a74d1cglennrp    }
5813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  marker=(unsigned char *) AcquireQuantumMemory(image->colors,sizeof(*marker));
5823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (marker == (unsigned char *) NULL)
5833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
5843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->filename);
5853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  opacity=(IndexPacket *) AcquireQuantumMemory(image->colors,sizeof(*opacity));
5863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (opacity == (IndexPacket *) NULL)
5873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
5883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      marker=(unsigned char *) RelinquishMagickMemory(marker);
5893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
5903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->filename);
5913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
5923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
5933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Mark colors that are present.
5943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
5953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  number_colors=(long) image->colors;
5963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < number_colors; i++)
5973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
5983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    marker[i]=MagickFalse;
5993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    opacity[i]=OpaqueOpacity;
6003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
6013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  top_used=0;
6023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (y=0; y < (long) image->rows; y++)
6033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
6043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
6053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (p == (const PixelPacket *) NULL)
6063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
6073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    indices=GetVirtualIndexQueue(image);
6083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (image->matte != MagickFalse)
6093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (x=0; x < (long) image->columns; x++)
6103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
6113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        marker[(int) indices[x]]=MagickTrue;
612ce70c17bb6433add2eb069515a4f3105989e0662cristy        opacity[(int) indices[x]]=GetOpacityPixelComponent(p);
6133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (indices[x] > top_used)
6143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           top_used=indices[x];
6153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        p++;
6163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
6173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    else
6183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (x=0; x < (long) image->columns; x++)
6193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
6203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        marker[(int) indices[x]]=MagickTrue;
6213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (indices[x] > top_used)
6223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           top_used=indices[x];
6233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
6243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
6253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->matte != MagickFalse)
6273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
6283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
6293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Mark background color, topmost occurrence if more than one.
6303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
6313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    for (i=number_colors-1; i; i--)
6323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
6333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (IsColorEqual(image->colormap+i,&image->background_color))
6343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
6353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          marker[i]=MagickTrue;
6363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
6373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
6383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
6393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
6403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
6413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Unmark duplicates.
6423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
6433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < number_colors-1; i++)
6443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (marker[i])
6453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
6463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        for (j=i+1; j < number_colors; j++)
6473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if ((opacity[i] == opacity[j]) &&
6483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (IsColorEqual(image->colormap+i,image->colormap+j)))
6493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            marker[j]=MagickFalse;
6503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       }
6513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
6523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Count colors that still remain.
6533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
6543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  have_transparency=MagickFalse;
6553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  new_number_colors=0;
6563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < number_colors; i++)
6573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (marker[i])
6583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
6593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        new_number_colors++;
6603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (opacity[i] != OpaqueOpacity)
6613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          have_transparency=MagickTrue;
6623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
6633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((!have_transparency || (marker[0] &&
6643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (opacity[0] == (Quantum) TransparentOpacity)))
6653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      && (new_number_colors == number_colors))
6663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
6673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
6683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        No duplicate or unused entries, and transparency-swap not needed.
6693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
6703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      marker=(unsigned char *) RelinquishMagickMemory(marker);
6713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      opacity=(IndexPacket *) RelinquishMagickMemory(opacity);
6723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return(MagickTrue);
6733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
6743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  remap_needed=MagickFalse;
6763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((long) top_used >= new_number_colors)
6773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     remap_needed=MagickTrue;
6783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
6803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Compress colormap.
6813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
6823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  colormap=(PixelPacket *) AcquireQuantumMemory(image->colors,
6843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    sizeof(*colormap));
6853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (colormap == (PixelPacket *) NULL)
6863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
6873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      marker=(unsigned char *) RelinquishMagickMemory(marker);
6883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      opacity=(IndexPacket *) RelinquishMagickMemory(opacity);
6893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
6903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->filename);
6913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
6923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
6933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Eliminate unused colormap entries.
6943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
6953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  map=(IndexPacket *) AcquireQuantumMemory((size_t) number_colors,
6963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    sizeof(*map));
6973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (map == (IndexPacket *) NULL)
6983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
6993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      marker=(unsigned char *) RelinquishMagickMemory(marker);
7003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      opacity=(IndexPacket *) RelinquishMagickMemory(opacity);
7013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      colormap=(PixelPacket *) RelinquishMagickMemory(colormap);
7023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
7033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->filename);
7043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
7053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  k=0;
7063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < number_colors; i++)
7073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
7083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    map[i]=(IndexPacket) k;
7093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (marker[i])
7103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
7113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        for (j=i+1; j < number_colors; j++)
7123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
7133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if ((opacity[i] == opacity[j]) &&
7143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (IsColorEqual(image->colormap+i,image->colormap+j)))
7153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
7163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               map[j]=(IndexPacket) k;
7173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               marker[j]=MagickFalse;
7183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
7193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
7203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        k++;
7213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
7223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
7233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  j=0;
7243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < number_colors; i++)
7253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
7263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (marker[i])
7273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
7283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        colormap[j]=image->colormap[i];
7293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        j++;
7303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
7313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
7323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (have_transparency && (opacity[0] != (Quantum) TransparentOpacity))
7333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
7343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
7353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Move the first transparent color to palette entry 0.
7363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
7373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (i=1; i < number_colors; i++)
7383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
7393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (marker[i] && opacity[i] == (Quantum) TransparentOpacity)
7403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
7413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            PixelPacket
7423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              temp_colormap;
7433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            temp_colormap=colormap[0];
7453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            colormap[0]=colormap[(int) map[i]];
7463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            colormap[(long) map[i]]=temp_colormap;
7473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            for (j=0; j < number_colors; j++)
7483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
7493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (map[j] == 0)
7503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                map[j]=map[i];
7513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              else if (map[j] == map[i])
7523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                map[j]=0;
7533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
7543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            remap_needed=MagickTrue;
7553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
7563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
7573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
7583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   }
7593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  opacity=(IndexPacket *) RelinquishMagickMemory(opacity);
7613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  marker=(unsigned char *) RelinquishMagickMemory(marker);
7623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (remap_needed)
7643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
7653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ExceptionInfo
7663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *exception;
7673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      register IndexPacket
7693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *pixels;
7703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      register PixelPacket
7723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *q;
7733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
7753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Remap pixels.
7763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
7773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      exception=(&image->exception);
7783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (y=0; y < (long) image->rows; y++)
7793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
7803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
7813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (q == (PixelPacket *) NULL)
7823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
7833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixels=GetAuthenticIndexQueue(image);
7843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        for (x=0; x < (long) image->columns; x++)
7853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
7863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          j=(int) pixels[x];
7873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          pixels[x]=map[j];
7883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
7893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (SyncAuthenticPixels(image,exception) == MagickFalse)
7903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
7913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
7923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (i=0; i < new_number_colors; i++)
7933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->colormap[i]=colormap[i];
7943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
7953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  colormap=(PixelPacket *) RelinquishMagickMemory(colormap);
7963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->colors=(unsigned long) new_number_colors;
7973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  map=(IndexPacket *) RelinquishMagickMemory(map);
7983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickTrue);
7993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
8003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
8013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
8033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   I m a g e I s G r a y                                                     %
8083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   Like IsGrayImage except does not change DirectClass to PseudoClass        %
8143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
8173ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType ImageIsGray(Image *image)
8183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
8193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register const PixelPacket
8203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p;
8213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register long
8233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i,
8243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x,
8253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    y;
8263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (Image *) NULL);
8283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image->signature == MagickSignature);
8293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
8303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
8313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->storage_class == PseudoClass)
8333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
8343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (i=0; i < (long) image->colors; i++)
8353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (IsGray(image->colormap+i) == MagickFalse)
8363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          return(MagickFalse);
8373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return(MagickTrue);
8383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
8393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (y=0; y < (long) image->rows; y++)
8403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
8413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
8423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (p == (const PixelPacket *) NULL)
8433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return(MagickFalse);
8443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    for (x=(long) image->columns-1; x >= 0; x--)
8453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
8463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       if (IsGray(p) == MagickFalse)
8473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          return(MagickFalse);
8483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       p++;
8493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
8503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
8513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickTrue);
8523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
8533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
8553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   I m a g e I s M o n o c h r o m e                                         %
8603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   Like IsMonochromeImage except does not change DirectClass to PseudoClass  %
8663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   and is more accurate.                                                     %
8673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
8703ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType ImageIsMonochrome(Image *image)
8713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
8723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register const PixelPacket
8733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p;
8743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register long
8763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i,
8773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x,
8783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    y;
8793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (Image *) NULL);
8813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image->signature == MagickSignature);
8823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
8833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
8843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->storage_class == PseudoClass)
8853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
8863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (i=0; i < (long) image->colors; i++)
8873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
8883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if ((IsGray(image->colormap+i) == MagickFalse) ||
8893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            ((image->colormap[i].red != 0) &&
8903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             (image->colormap[i].red != (Quantum) QuantumRange)))
8913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          return(MagickFalse);
8923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
8933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return(MagickTrue);
8943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
8953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (y=0; y < (long) image->rows; y++)
8963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
8973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
8983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (p == (const PixelPacket *) NULL)
8993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return(MagickFalse);
9003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    for (x=(long) image->columns-1; x >= 0; x--)
9013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
9023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if ((p->red != 0) && (p->red != (Quantum) QuantumRange))
9033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        return(MagickFalse);
9043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (IsGray(p) == MagickFalse)
9053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        return(MagickFalse);
9063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if ((p->opacity != OpaqueOpacity) &&
9073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (p->opacity != (Quantum) TransparentOpacity))
9083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        return(MagickFalse);
9093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      p++;
9103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
9113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
9123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickTrue);
9133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
914c451207335b7a8bb4e44f904f3d65a2727e41214glennrp#endif /* PNG_LIBPNG_VER > 10011 */
9153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif /* MAGICKCORE_PNG_DELEGATE */
9163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
9183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   I s M N G                                                                 %
9233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  IsMNG() returns MagickTrue if the image format type, identified by the
9293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  magick string, is MNG.
9303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the IsMNG method is:
9323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType IsMNG(const unsigned char *magick,const size_t length)
9343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
9363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o magick: compare image format pattern against these bytes.
9383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o length: Specifies the length of the magick string.
9403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
9433ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType IsMNG(const unsigned char *magick,const size_t length)
9443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
9453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (length < 8)
9463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
9473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (memcmp(magick,"\212MNG\r\n\032\n",8) == 0)
9483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickTrue);
9493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickFalse);
9503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
9513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
9533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   I s J N G                                                                 %
9583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  IsJNG() returns MagickTrue if the image format type, identified by the
9643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  magick string, is JNG.
9653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the IsJNG method is:
9673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType IsJNG(const unsigned char *magick,const size_t length)
9693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
9713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o magick: compare image format pattern against these bytes.
9733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o length: Specifies the length of the magick string.
9753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
9783ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType IsJNG(const unsigned char *magick,const size_t length)
9793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
9803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (length < 8)
9813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
9823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (memcmp(magick,"\213JNG\r\n\032\n",8) == 0)
9833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickTrue);
9843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickFalse);
9853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
9863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
9883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   I s P N G                                                                 %
9933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  IsPNG() returns MagickTrue if the image format type, identified by the
9993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  magick string, is PNG.
10003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
10013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the IsPNG method is:
10023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
10033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType IsPNG(const unsigned char *magick,const size_t length)
10043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
10053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
10063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
10073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o magick: compare image format pattern against these bytes.
10083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
10093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o length: Specifies the length of the magick string.
10103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
10113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
10123ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType IsPNG(const unsigned char *magick,const size_t length)
10133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
10143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (length < 8)
10153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
10163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (memcmp(magick,"\211PNG\r\n\032\n",8) == 0)
10173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickTrue);
10183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickFalse);
10193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
10203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MAGICKCORE_PNG_DELEGATE)
10223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(__cplusplus) || defined(c_plusplus)
10233ed852eea50f9d4cd633efb8c2b054b8e33c253cristyextern "C" {
10243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
10253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1026c451207335b7a8bb4e44f904f3d65a2727e41214glennrp#if (PNG_LIBPNG_VER > 10011)
10273ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic size_t WriteBlobMSBULong(Image *image,const unsigned long value)
10283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
10293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned char
10303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    buffer[4];
10313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (Image *) NULL);
10333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image->signature == MagickSignature);
10343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  buffer[0]=(unsigned char) (value >> 24);
10353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  buffer[1]=(unsigned char) (value >> 16);
10363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  buffer[2]=(unsigned char) (value >> 8);
10373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  buffer[3]=(unsigned char) value;
10383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return((size_t) WriteBlob(image,4,buffer));
10393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
10403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10413ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic void PNGLong(png_bytep p,png_uint_32 value)
10423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
10433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *p++=(png_byte) ((value >> 24) & 0xff);
10443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *p++=(png_byte) ((value >> 16) & 0xff);
10453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *p++=(png_byte) ((value >> 8) & 0xff);
10463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *p++=(png_byte) (value & 0xff);
10473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
10483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10493ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic void PNGsLong(png_bytep p,png_int_32 value)
10503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
10513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *p++=(png_byte) ((value >> 24) & 0xff);
10523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *p++=(png_byte) ((value >> 16) & 0xff);
10533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *p++=(png_byte) ((value >> 8) & 0xff);
10543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *p++=(png_byte) (value & 0xff);
10553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
10563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10573ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic void PNGShort(png_bytep p,png_uint_16 value)
10583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
10593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *p++=(png_byte) ((value >> 8) & 0xff);
10603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *p++=(png_byte) (value & 0xff);
10613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
10623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10633ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic void PNGType(png_bytep p,png_bytep type)
10643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
10653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CopyMagickMemory(p,type,4*sizeof(png_byte));
10663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
10673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10683ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic void LogPNGChunk(int logging, png_bytep type, size_t length)
10693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
10703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
10713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
10723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      "  Writing %c%c%c%c chunk, length: %lu",
10733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      type[0],type[1],type[2],type[3],(unsigned long) length);
10743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1075c451207335b7a8bb4e44f904f3d65a2727e41214glennrp#endif /* PNG_LIBPNG_VER > 10011 */
10763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(__cplusplus) || defined(c_plusplus)
10783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
10793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
10803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1081c451207335b7a8bb4e44f904f3d65a2727e41214glennrp#if PNG_LIBPNG_VER > 10011
10823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
10833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
10853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
10863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
10873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   R e a d P N G I m a g e                                                   %
10883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
10893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
10903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
10913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
10933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  ReadPNGImage() reads a Portable Network Graphics (PNG) or
10943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  Multiple-image Network Graphics (MNG) image file and returns it.  It
10953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  allocates the memory necessary for the new Image structure and returns a
10963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  pointer to the new image or set of images.
10973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
10983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  MNG support written by Glenn Randers-Pehrson, glennrp@image...
10993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the ReadPNGImage method is:
11013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      Image *ReadPNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
11033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
11053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image_info: the image info.
11073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o exception: return any errors or warnings in this structure.
11093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  To do, more or less in chronological order (as of version 5.5.2,
11113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   November 26, 2002 -- glennrp -- see also "To do" under WriteMNGImage):
11123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    Get 16-bit cheap transparency working.
11143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    (At this point, PNG decoding is supposed to be in full MNG-LC compliance)
11163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    Preserve all unknown and not-yet-handled known chunks found in input
11183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    PNG file and copy them into output PNG files according to the PNG
11193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    copying rules.
11203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    (At this point, PNG encoding should be in full MNG compliance)
11223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    Provide options for choice of background to use when the MNG BACK
11243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    chunk is not present or is not mandatory (i.e., leave transparent,
11253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    user specified, MNG BACK, PNG bKGD)
11263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    Implement LOOP/ENDL [done, but could do discretionary loops more
11283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    efficiently by linking in the duplicate frames.].
11293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    Decode and act on the MHDR simplicity profile (offer option to reject
11313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    files or attempt to process them anyway when the profile isn't LC or VLC).
11323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    Upgrade to full MNG without Delta-PNG.
11343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        o  BACK [done a while ago except for background image ID]
11363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        o  MOVE [done 15 May 1999]
11373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        o  CLIP [done 15 May 1999]
11383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        o  DISC [done 19 May 1999]
11393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        o  SAVE [partially done 19 May 1999 (marks objects frozen)]
11403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        o  SEEK [partially done 19 May 1999 (discard function only)]
11413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        o  SHOW
11423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        o  PAST
11433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        o  BASI
11443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        o  MNG-level tEXt/iTXt/zTXt
11453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        o  pHYg
11463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        o  pHYs
11473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        o  sBIT
11483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        o  bKGD
11493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        o  iTXt (wait for libpng implementation).
11503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    Use the scene signature to discover when an identical scene is
11523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    being reused, and just point to the original image->exception instead
11533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    of storing another set of pixels.  This not specific to MNG
11543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    but could be applied generally.
11553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    Upgrade to full MNG with Delta-PNG.
11573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    JNG tEXt/iTXt/zTXt
11593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    We will not attempt to read files containing the CgBI chunk.
11613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    They are really Xcode files meant for display on the iPhone.
11623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    These are not valid PNG files and it is impossible to recover
11633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    the orginal PNG from files that have been converted to Xcode-PNG,
11643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    since irretrievable loss of color data has occurred due to the
11653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    use of premultiplied alpha.
11663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
11673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
11683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(__cplusplus) || defined(c_plusplus)
11693ed852eea50f9d4cd633efb8c2b054b8e33c253cristyextern "C" {
11703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
11713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
11723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
11733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  This the function that does the actual reading of data.  It is
11743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  the same as the one supplied in libpng, except that it receives the
11753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  datastream from the ReadBlob() function instead of standard input.
11763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
11773ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic void png_get_data(png_structp png_ptr,png_bytep data,png_size_t length)
11783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
11793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
11803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *image;
11813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
11823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image=(Image *) png_get_io_ptr(png_ptr);
11833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (length)
11843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
11853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      png_size_t
11863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        check;
11873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
11883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      check=(png_size_t) ReadBlob(image,(size_t) length,data);
11893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (check != length)
11903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
11913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          char
11923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            msg[MaxTextExtent];
11933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
11943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) FormatMagickString(msg,MaxTextExtent,
11953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            "Expected %lu bytes; found %lu bytes",(unsigned long) length,
11963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (unsigned long) check);
11973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          png_warning(png_ptr,msg);
11983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          png_error(png_ptr,"Read Exception");
11993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
12003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
12013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
12023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
12033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if !defined(PNG_READ_EMPTY_PLTE_SUPPORTED) && \
12043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    !defined(PNG_MNG_FEATURES_SUPPORTED)
12053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* We use mng_get_data() instead of png_get_data() if we have a libpng
12063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy * older than libpng-1.0.3a, which was the first to allow the empty
12073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy * PLTE, or a newer libpng in which PNG_MNG_FEATURES_SUPPORTED was
12083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy * ifdef'ed out.  Earlier versions would crash if the bKGD chunk was
12093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy * encountered after an empty PLTE, so we have to look ahead for bKGD
12103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy * chunks and remove them from the datastream that is passed to libpng,
12113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy * and store their contents for later use.
12123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */
12133ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic void mng_get_data(png_structp png_ptr,png_bytep data,png_size_t length)
12143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
12153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MngInfo
12163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *mng_info;
12173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
12183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
12193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *image;
12203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
12213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_size_t
12223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    check;
12233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
12243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register long
12253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i;
12263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
12273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  i=0;
12283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mng_info=(MngInfo *) png_get_io_ptr(png_ptr);
12293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image=(Image *) mng_info->image;
12303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  while (mng_info->bytes_in_read_buffer && length)
12313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
12323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    data[i]=mng_info->read_buffer[i];
12333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    mng_info->bytes_in_read_buffer--;
12343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    length--;
12353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i++;
12363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
12373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (length)
12383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
12393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      check=(png_size_t) ReadBlob(image,(size_t) length,(char *) data);
12403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (check != length)
12413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        png_error(png_ptr,"Read Exception");
12423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (length == 4)
12433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
12443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if ((data[0] == 0) && (data[1] == 0) && (data[2] == 0) &&
12453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (data[3] == 0))
12463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
12473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              check=(png_size_t) ReadBlob(image,(size_t) length,
12483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (char *) mng_info->read_buffer);
12493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_info->read_buffer[4]=0;
12503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_info->bytes_in_read_buffer=4;
12513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (memcmp(mng_info->read_buffer,mng_PLTE,4) == 0)
12523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->found_empty_plte=MagickTrue;
12533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (memcmp(mng_info->read_buffer,mng_IEND,4) == 0)
12543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
12553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  mng_info->found_empty_plte=MagickFalse;
12563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  mng_info->have_saved_bkgd_index=MagickFalse;
12573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
12583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
12593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if ((data[0] == 0) && (data[1] == 0) && (data[2] == 0) &&
12603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (data[3] == 1))
12613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
12623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              check=(png_size_t) ReadBlob(image,(size_t) length,
12633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (char *) mng_info->read_buffer);
12643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_info->read_buffer[4]=0;
12653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_info->bytes_in_read_buffer=4;
12663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (memcmp(mng_info->read_buffer,mng_bKGD,4) == 0)
12673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (mng_info->found_empty_plte)
12683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  {
12693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    /*
12703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      Skip the bKGD data byte and CRC.
12713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    */
12723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    check=(png_size_t)
12733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      ReadBlob(image,5,(char *) mng_info->read_buffer);
12743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    check=(png_size_t) ReadBlob(image,(size_t) length,
12753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      (char *) mng_info->read_buffer);
12763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    mng_info->saved_bkgd_index=mng_info->read_buffer[0];
12773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    mng_info->have_saved_bkgd_index=MagickTrue;
12783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    mng_info->bytes_in_read_buffer=0;
12793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  }
12803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
12813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
12823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
12833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
12843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
12853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
12863ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic void png_put_data(png_structp png_ptr,png_bytep data,png_size_t length)
12873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
12883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
12893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *image;
12903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
12913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image=(Image *) png_get_io_ptr(png_ptr);
12923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (length)
12933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
12943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      png_size_t
12953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        check;
12963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
12973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      check=(png_size_t) WriteBlob(image,(unsigned long) length,data);
12983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (check != length)
12993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        png_error(png_ptr,"WriteBlob Failed");
13003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
13013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
13023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
13033ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic void png_flush_data(png_structp png_ptr)
13043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
13053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) png_ptr;
13063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
13073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
13083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#ifdef PNG_WRITE_EMPTY_PLTE_SUPPORTED
13093ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic int PalettesAreEqual(Image *a,Image *b)
13103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
13113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  long
13123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i;
13133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
13143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((a == (Image *) NULL) || (b == (Image *) NULL))
13153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return((int) MagickFalse);
13163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (a->storage_class != PseudoClass || b->storage_class != PseudoClass)
13173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return((int) MagickFalse);
13183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (a->colors != b->colors)
13193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return((int) MagickFalse);
13203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < (long) a->colors; i++)
13213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
13223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if ((a->colormap[i].red != b->colormap[i].red) ||
13233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (a->colormap[i].green != b->colormap[i].green) ||
13243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (a->colormap[i].blue != b->colormap[i].blue))
13253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return((int) MagickFalse);
13263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
13273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return((int) MagickTrue);
13283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
13293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
13303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
13313ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic void MngInfoDiscardObject(MngInfo *mng_info,int i)
13323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
13333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (i && (i < MNG_MAX_OBJECTS) && (mng_info != (MngInfo *) NULL) &&
13343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mng_info->exists[i] && !mng_info->frozen[i])
13353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
13363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#ifdef MNG_OBJECT_BUFFERS
13373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (mng_info->ob[i] != (MngBuffer *) NULL)
13383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
13393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (mng_info->ob[i]->reference_count > 0)
13403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_info->ob[i]->reference_count--;
13413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (mng_info->ob[i]->reference_count == 0)
13423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
13433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (mng_info->ob[i]->image != (Image *) NULL)
13443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->ob[i]->image=DestroyImage(mng_info->ob[i]->image);
13453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_info->ob[i]=DestroyString(mng_info->ob[i]);
13463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
13473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
13483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mng_info->ob[i]=(MngBuffer *) NULL;
13493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
13503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mng_info->exists[i]=MagickFalse;
13513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mng_info->invisible[i]=MagickFalse;
13523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mng_info->viewable[i]=MagickFalse;
13533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mng_info->frozen[i]=MagickFalse;
13543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mng_info->x_off[i]=0;
13553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mng_info->y_off[i]=0;
13563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mng_info->object_clip[i].left=0;
13573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mng_info->object_clip[i].right=(long) PNG_UINT_31_MAX;
13583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mng_info->object_clip[i].top=0;
13593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mng_info->object_clip[i].bottom=(long) PNG_UINT_31_MAX;
13603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
13613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
13623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
13633ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic void MngInfoFreeStruct(MngInfo *mng_info,int *have_mng_structure)
13643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
13653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (*have_mng_structure && (mng_info != (MngInfo *) NULL))
13663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
13673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      register long
13683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        i;
13693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
13703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (i=1; i < MNG_MAX_OBJECTS; i++)
13713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        MngInfoDiscardObject(mng_info,i);
13723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (mng_info->global_plte != (png_colorp) NULL)
13733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        mng_info->global_plte=(png_colorp)
13743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          RelinquishMagickMemory(mng_info->global_plte);
13753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mng_info=(MngInfo *) RelinquishMagickMemory(mng_info);
13763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      *have_mng_structure=MagickFalse;
13773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
13783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
13793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
13803ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MngBox mng_minimum_box(MngBox box1,MngBox box2)
13813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
13823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MngBox
13833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    box;
13843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
13853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  box=box1;
13863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (box.left < box2.left)
13873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    box.left=box2.left;
13883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (box.top < box2.top)
13893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    box.top=box2.top;
13903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (box.right > box2.right)
13913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    box.right=box2.right;
13923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (box.bottom > box2.bottom)
13933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    box.bottom=box2.bottom;
13943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return box;
13953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
13963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
13973ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MngBox mng_read_box(MngBox previous_box,char delta_type,unsigned char *p)
13983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
13993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   MngBox
14003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      box;
14013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
14023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
14033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Read clipping boundaries from DEFI, CLIP, FRAM, or PAST chunk.
14043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
14053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  box.left=(long) ((p[0]  << 24) | (p[1]  << 16) | (p[2]  << 8) | p[3]);
14063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  box.right=(long) ((p[4]  << 24) | (p[5]  << 16) | (p[6]  << 8) | p[7]);
14073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  box.top=(long) ((p[8]  << 24) | (p[9]  << 16) | (p[10] << 8) | p[11]);
14083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  box.bottom=(long) ((p[12] << 24) | (p[13] << 16) | (p[14] << 8) | p[15]);
14093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (delta_type != 0)
14103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
14113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      box.left+=previous_box.left;
14123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      box.right+=previous_box.right;
14133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      box.top+=previous_box.top;
14143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      box.bottom+=previous_box.bottom;
14153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
14163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(box);
14173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
14183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
14193ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MngPair mng_read_pair(MngPair previous_pair,int delta_type,
14203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned char *p)
14213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
14223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MngPair
14233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pair;
14243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
14253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Read two longs from CLON, MOVE or PAST chunk
14263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
14273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  pair.a=(long) ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
14283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  pair.b=(long) ((p[4] << 24) | (p[5] << 16) | (p[6] << 8) | p[7]);
14293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (delta_type != 0)
14303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
14313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      pair.a+=previous_pair.a;
14323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      pair.b+=previous_pair.b;
14333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
14343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(pair);
14353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
14363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
14373ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic long mng_get_long(unsigned char *p)
14383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
14393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return((long) ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]));
14403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
14413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
14423ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic void PNGErrorHandler(png_struct *ping,png_const_charp message)
14433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
14443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
14453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *image;
14463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
14473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image=(Image *) png_get_error_ptr(ping);
14483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
14493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
14503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      "  libpng-%s error: %s", PNG_LIBPNG_VER_STRING,message);
14513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ThrowMagickException(&image->exception,GetMagickModule(),CoderError,
14523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    message,"`%s'",image->filename);
14533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  longjmp(ping->jmpbuf,1);
14543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
14553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
14563ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic void PNGWarningHandler(png_struct *ping,png_const_charp message)
14573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
14583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
14593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *image;
14603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
14613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (LocaleCompare(message, "Missing PLTE before tRNS") == 0)
14623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    png_error(ping, message);
14633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image=(Image *) png_get_error_ptr(ping);
14643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
14653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
14663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      "  libpng-%s warning: %s", PNG_LIBPNG_VER_STRING,
14673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      message);
14683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ThrowMagickException(&image->exception,GetMagickModule(),CoderWarning,
14693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    message,"`%s'",image->filename);
14703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
14713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
14723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#ifdef PNG_USER_MEM_SUPPORTED
14733ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_voidp png_IM_malloc(png_structp png_ptr,png_uint_32 size)
14743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
14753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if (PNG_LIBPNG_VER < 10011)
14763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_voidp
14773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ret;
14783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
14793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_ptr=png_ptr;
14803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ret=((png_voidp) AcquireMagickMemory((size_t) size));
14813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (ret == NULL)
14823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    png_error("Insufficient memory.");
14833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(ret);
14843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#else
14853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_ptr=png_ptr;
14863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return((png_voidp) AcquireMagickMemory((size_t) size));
14873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
14883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
14893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
14903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
14913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Free a pointer.  It is removed from the list at the same time.
14923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
14933ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic png_free_ptr png_IM_free(png_structp png_ptr,png_voidp ptr)
14943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
14953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_ptr=png_ptr;
14963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ptr=RelinquishMagickMemory(ptr);
14973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return((png_free_ptr) NULL);
14983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
14993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
15003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
15013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(__cplusplus) || defined(c_plusplus)
15023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
15033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
15043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
15053ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic int
15063ed852eea50f9d4cd633efb8c2b054b8e33c253cristypng_read_raw_profile(Image *image, const ImageInfo *image_info,
15073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   png_textp text,int ii)
15083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
15093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register long
15103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i;
15113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
15123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register unsigned char
15133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *dp;
15143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
15153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register png_charp
15163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    sp;
15173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
15183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_uint_32
15193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    length,
15203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    nibbles;
15213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
15223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  StringInfo
15233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *profile;
15243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
15253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned char
15263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    unhex[103]={0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
15273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
15283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                 0,0,0,0,0,0,0,0,0,1, 2,3,4,5,6,7,8,9,0,0,
15293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
15303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,10,11,12,
15313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                 13,14,15};
15323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
15333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  sp=text[ii].text+1;
15343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* look for newline */
15353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  while (*sp != '\n')
15363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     sp++;
15373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* look for length */
15383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  while (*sp == '\0' || *sp == ' ' || *sp == '\n')
15393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     sp++;
1540f2f2727f17ecbb23d902f70bb98f81faabc92dbdcristy  length=(png_uint_32) StringToLong(sp);
15413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  while (*sp != ' ' && *sp != '\n')
15423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     sp++;
15433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* allocate space */
15443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (length == 0)
15453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
15463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) ThrowMagickException(&image->exception,GetMagickModule(),
15473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      CoderWarning,"UnableToCopyProfile","`%s'","invalid profile length");
15483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
15493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
15503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  profile=AcquireStringInfo(length);
15513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (profile == (StringInfo *) NULL)
15523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
15533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) ThrowMagickException(&image->exception,GetMagickModule(),
15543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ResourceLimitError,"MemoryAllocationFailed","`%s'",
15553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      "unable to copy profile");
15563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
15573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
15583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* copy profile, skipping white space and column 1 "=" signs */
15593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  dp=GetStringInfoDatum(profile);
15603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  nibbles=length*2;
15613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < (long) nibbles; i++)
15623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
15633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    while (*sp < '0' || (*sp > '9' && *sp < 'a') || *sp > 'f')
15643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
15653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (*sp == '\0')
15663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
15673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) ThrowMagickException(&image->exception,GetMagickModule(),
15683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            CoderWarning,"UnableToCopyProfile","`%s'","ran out of data");
15693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          profile=DestroyStringInfo(profile);
15703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          return(MagickFalse);
15713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
15723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      sp++;
15733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
15743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (i%2 == 0)
15753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      *dp=(unsigned char) (16*unhex[(int) *sp++]);
15763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    else
15773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (*dp++)+=unhex[(int) *sp++];
15783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
15793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
15803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    We have already read "Raw profile type.
15813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
15823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) SetImageProfile(image,&text[ii].key[17],profile);
15833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  profile=DestroyStringInfo(profile);
15843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_info->verbose)
15853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) printf(" Found a generic profile, type %s\n",&text[ii].key[17]);
15863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return MagickTrue;
15873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
15883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
15893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
15903ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic int read_vpag_chunk_callback(png_struct *ping, png_unknown_chunkp chunk)
15913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
15923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
15933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *image;
15943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
15953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
15963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* The unknown chunk structure contains the chunk data:
15973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     png_byte name[5];
15983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     png_byte *data;
15993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     png_size_t size;
16003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
16013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     Note that libpng has already taken care of the CRC handling.
16023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
16033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
16043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
16053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (chunk->name[0] != 118 || chunk->name[1] != 112 ||
16063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      chunk->name[2] != 65 ||chunk-> name[3] != 103)
16073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(0); /* Did not recognize */
16083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
16093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* recognized vpAg */
16103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
16113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (chunk->size != 9)
16123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(-1); /* Error return */
16133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
16143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (chunk->data[8] != 0)
16153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(0);  /* ImageMagick requires pixel units */
16163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
16173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image=(Image *) png_get_user_chunk_ptr(ping);
16183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
16193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->page.width=(unsigned long) ((chunk->data[0] << 24) |
16203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     (chunk->data[1] << 16) | (chunk->data[2] << 8) | chunk->data[3]);
16213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->page.height=(unsigned long) ((chunk->data[4] << 24) |
16223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     (chunk->data[5] << 16) | (chunk->data[6] << 8) | chunk->data[7]);
16233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
16243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* Return one of the following: */
16253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     /* return(-n);  chunk had an error */
16263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     /* return(0);  did not recognize */
16273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     /* return(n);  success */
16283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
16293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(1);
16303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
16313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
16323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
16333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
16343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
16353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
16373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
16383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
16393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   R e a d O n e P N G I m a g e                                             %
16403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
16413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
16423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
16433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
16453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  ReadOnePNGImage() reads a Portable Network Graphics (PNG) image file
16463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  (minus the 8-byte signature)  and returns it.  It allocates the memory
16473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  necessary for the new Image structure and returns a pointer to the new
16483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  image.
16493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
16503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the ReadOnePNGImage method is:
16513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
16523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      Image *ReadOnePNGImage(MngInfo *mng_info, const ImageInfo *image_info,
16533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%         ExceptionInfo *exception)
16543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
16553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
16563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
16573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o mng_info: Specifies a pointer to a MngInfo structure.
16583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
16593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image_info: the image info.
16603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
16613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o exception: return any errors or warnings in this structure.
16623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
16633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
16643ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic Image *ReadOnePNGImage(MngInfo *mng_info,
16653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    const ImageInfo *image_info, ExceptionInfo *exception)
16663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
16673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* Read one PNG image */
16683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
16693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
16703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *image;
16713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
16723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  int
16733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    logging,
16743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    num_text,
16753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    num_passes,
1676c11cf6a442f3046940608a5743a68cc891deb13eglennrp    pass,
1677c11cf6a442f3046940608a5743a68cc891deb13eglennrp    ping_info_bit_depth,
1678c11cf6a442f3046940608a5743a68cc891deb13eglennrp    ping_info_color_type,
1679c11cf6a442f3046940608a5743a68cc891deb13eglennrp    ping_info_interlace_method,
1680c11cf6a442f3046940608a5743a68cc891deb13eglennrp    ping_info_compression_method,
1681cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp    ping_info_filter_method,
1682cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp    ping_info_num_trans;
16833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
16843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
16853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
16863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
16873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  PixelPacket
16883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    transparent_color;
16893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1690cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp  png_bytep
1691cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp     ping_trans_alpha;
1692cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp
1693cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp  png_color_16p
1694cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp     ping_background,
1695cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp     ping_trans_color;
1696cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp
16973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_info
16983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *end_info,
16993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *ping_info;
17003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
17013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_struct
17023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *ping;
17033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1704c11cf6a442f3046940608a5743a68cc891deb13eglennrp  png_uint_32
1705c11cf6a442f3046940608a5743a68cc891deb13eglennrp    ping_info_height,
1706c451207335b7a8bb4e44f904f3d65a2727e41214glennrp    ping_info_width,
1707c451207335b7a8bb4e44f904f3d65a2727e41214glennrp    ping_rowbytes;
1708c11cf6a442f3046940608a5743a68cc891deb13eglennrp
17093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_textp
17103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    text;
17113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
17123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  QuantumInfo
17133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *quantum_info;
17143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
17153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned char
17163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *png_pixels;
17173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
17183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  long
17193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    y;
17203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
17213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register unsigned char
17223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p;
17233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
17243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register IndexPacket
17253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *indices;
17263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
17273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register long
17283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i,
17293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x;
17303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
17313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register PixelPacket
17323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q;
17333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
17343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  size_t
17353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    length;
17363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
17373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned long
17383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    row_offset;
17393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
17403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
17413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_byte unused_chunks[]=
17423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
17433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    104,  73,  83,  84, (png_byte) '\0',   /* hIST */
17443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    105,  84,  88, 116, (png_byte) '\0',   /* iTXt */
17453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    112,  67,  65,  76, (png_byte) '\0',   /* pCAL */
17463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    115,  67,  65,  76, (png_byte) '\0',   /* sCAL */
17473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    115,  80,  76,  84, (png_byte) '\0',   /* sPLT */
17483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    116,  73,  77,  69, (png_byte) '\0',   /* tIME */
17493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  };
17503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
17513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
17523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  logging=LogMagickEvent(CoderEvent,GetMagickModule(),
17533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    "  enter ReadOnePNGImage()");
17543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
17553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
1756f84a193d5f435588cd78d521fff3f1f852e227f8cristy  LockSemaphoreInfo(png_semaphore);
17573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
17583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
17593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if (PNG_LIBPNG_VER < 10007)
17603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_info->verbose)
17613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    printf("Your PNG library (libpng-%s) is rather old.\n",
17623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       PNG_LIBPNG_VER_STRING);
17633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
17643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
176561b4c957269727a0a2526edc2331881da8346100glennrp#if (PNG_LIBPNG_VER >= 10400)
176661b4c957269727a0a2526edc2331881da8346100glennrp#  ifndef  PNG_TRANSFORM_GRAY_TO_RGB    /* Added at libpng-1.4.0beta67 */
176761b4c957269727a0a2526edc2331881da8346100glennrp  if (image_info->verbose)
176861b4c957269727a0a2526edc2331881da8346100glennrp    {
176961b4c957269727a0a2526edc2331881da8346100glennrp      printf("Your PNG library (libpng-%s) is an old beta version.\n",
177061b4c957269727a0a2526edc2331881da8346100glennrp           PNG_LIBPNG_VER_STRING);
177161b4c957269727a0a2526edc2331881da8346100glennrp      printf("Please update it.\n");
177261b4c957269727a0a2526edc2331881da8346100glennrp    }
177361b4c957269727a0a2526edc2331881da8346100glennrp#  endif
177461b4c957269727a0a2526edc2331881da8346100glennrp#endif
177561b4c957269727a0a2526edc2331881da8346100glennrp
177661b4c957269727a0a2526edc2331881da8346100glennrp
1777ed5525230af20461366cdc5b8bbe0f7f9b166c44cristy  quantum_info = (QuantumInfo *) NULL;
17783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image=mng_info->image;
17793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
17803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
17813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Allocate the PNG structures
17823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
17833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#ifdef PNG_USER_MEM_SUPPORTED
17843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy ping=png_create_read_struct_2(PNG_LIBPNG_VER_STRING, image,
17853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   PNGErrorHandler,PNGWarningHandler, NULL,
17863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   (png_malloc_ptr) png_IM_malloc,(png_free_ptr) png_IM_free);
17873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#else
17883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ping=png_create_read_struct(PNG_LIBPNG_VER_STRING,image,
17893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    PNGErrorHandler,PNGWarningHandler);
17903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
17913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (ping == (png_struct *) NULL)
17923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
17933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ping_info=png_create_info_struct(ping);
17943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (ping_info == (png_info *) NULL)
17953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
17963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      png_destroy_read_struct(&ping,(png_info **) NULL,(png_info **) NULL);
17973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
17983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
17993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  end_info=png_create_info_struct(ping);
18003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (end_info == (png_info *) NULL)
18013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
18023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      png_destroy_read_struct(&ping,&ping_info,(png_info **) NULL);
18033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
18043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
18053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_pixels=(unsigned char *) NULL;
18063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (setjmp(ping->jmpbuf))
18073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
18083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
18093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        PNG image is corrupt.
18103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
18113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      png_destroy_read_struct(&ping,&ping_info,&end_info);
18123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
1813f84a193d5f435588cd78d521fff3f1f852e227f8cristy      UnlockSemaphoreInfo(png_semaphore);
18143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
18153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (logging != MagickFalse)
18163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
18173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "  exit ReadOnePNGImage() with error.");
18183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (image != (Image *) NULL)
18197b755eb4f94efbb57160cce0d7afe7f8ed4ef066cristy        {
18207b755eb4f94efbb57160cce0d7afe7f8ed4ef066cristy          InheritException(exception,&image->exception);
18217b755eb4f94efbb57160cce0d7afe7f8ed4ef066cristy          image->columns=0;
18227b755eb4f94efbb57160cce0d7afe7f8ed4ef066cristy        }
18233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return(GetFirstImageInList(image));
18243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
18253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
18263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Prepare PNG for reading.
18273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
1828c451207335b7a8bb4e44f904f3d65a2727e41214glennrp
18293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mng_info->image_found++;
18303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_set_sig_bytes(ping,8);
18313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (LocaleCompare(image_info->magick,"MNG") == 0)
18323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
18333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_MNG_FEATURES_SUPPORTED)
18343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) png_permit_mng_features(ping,PNG_ALL_MNG_FEATURES);
18353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      png_set_read_fn(ping,image,png_get_data);
18363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#else
18373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_READ_EMPTY_PLTE_SUPPORTED)
18383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      png_permit_empty_plte(ping,MagickTrue);
18393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      png_set_read_fn(ping,image,png_get_data);
18403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#else
18413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mng_info->image=image;
18423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mng_info->bytes_in_read_buffer=0;
18433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mng_info->found_empty_plte=MagickFalse;
18443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mng_info->have_saved_bkgd_index=MagickFalse;
18453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      png_set_read_fn(ping,mng_info,mng_get_data);
18463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
18473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
18483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
18493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
18503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    png_set_read_fn(ping,image,png_get_data);
18513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
18523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
18533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* Ignore unused chunks and all unknown chunks except for vpAg */
18543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_set_keep_unknown_chunks(ping, 1, NULL, 0);
18553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_set_keep_unknown_chunks(ping, 2, mng_vpAg, 1);
18563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_set_keep_unknown_chunks(ping, 1, unused_chunks,
18573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     (int)sizeof(unused_chunks)/5);
18583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* Callback for other unknown chunks */
18593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_set_read_user_chunk_fn(ping, image, read_vpag_chunk_callback);
18603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
18613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1862991e92a91acb9e432cd6c05843e4f6a57643e29dglennrp#if (PNG_LIBPNG_VER < 10400)
1863991e92a91acb9e432cd6c05843e4f6a57643e29dglennrp#  if defined(PNG_USE_PNGGCCRD) && defined(PNG_ASSEMBLER_CODE_SUPPORTED) && \
1864991e92a91acb9e432cd6c05843e4f6a57643e29dglennrp   (PNG_LIBPNG_VER >= 10200) && (PNG_LIBPNG_VER < 10220) && defined(__i386__)
18653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* Disable thread-unsafe features of pnggccrd */
18663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (png_access_version_number() >= 10200)
18673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
18683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    png_uint_32 mmx_disable_mask=0;
18693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    png_uint_32 asm_flags;
18703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
18713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    mmx_disable_mask |= ( PNG_ASM_FLAG_MMX_READ_COMBINE_ROW  \
18723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        | PNG_ASM_FLAG_MMX_READ_FILTER_SUB   \
18733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        | PNG_ASM_FLAG_MMX_READ_FILTER_AVG   \
18743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        | PNG_ASM_FLAG_MMX_READ_FILTER_PAETH );
18753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    asm_flags=png_get_asm_flags(ping);
18763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    png_set_asm_flags(ping, asm_flags & ~mmx_disable_mask);
18773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
1878991e92a91acb9e432cd6c05843e4f6a57643e29dglennrp#  endif
18793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
18803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
18813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_read_info(ping,ping_info);
1882c11cf6a442f3046940608a5743a68cc891deb13eglennrp
1883c11cf6a442f3046940608a5743a68cc891deb13eglennrp  png_get_IHDR(ping,ping_info,&ping_info_width,&ping_info_height,
1884c11cf6a442f3046940608a5743a68cc891deb13eglennrp               &ping_info_bit_depth,&ping_info_color_type,
1885c11cf6a442f3046940608a5743a68cc891deb13eglennrp               &ping_info_interlace_method,&ping_info_compression_method,
1886c11cf6a442f3046940608a5743a68cc891deb13eglennrp               &ping_info_filter_method);
1887c11cf6a442f3046940608a5743a68cc891deb13eglennrp
1888cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp  (void) png_get_tRNS(ping, ping_info, &ping_trans_alpha, &ping_info_num_trans,
1889cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp                      &ping_trans_color);
1890cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp
1891cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp  (void) png_get_bKGD(ping, ping_info, &ping_background);
1892cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp
1893c451207335b7a8bb4e44f904f3d65a2727e41214glennrp  ping_rowbytes=png_get_rowbytes(ping,ping_info);
1894c451207335b7a8bb4e44f904f3d65a2727e41214glennrp
1895c11cf6a442f3046940608a5743a68cc891deb13eglennrp  if (ping_info_bit_depth < 8)
18963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
1897c11cf6a442f3046940608a5743a68cc891deb13eglennrp      if (((int) ping_info_color_type == PNG_COLOR_TYPE_PALETTE))
18983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        png_set_packing(ping);
18993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
1900c11cf6a442f3046940608a5743a68cc891deb13eglennrp  image->depth=ping_info_bit_depth;
19013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->depth=GetImageQuantumDepth(image,MagickFalse);
1902c11cf6a442f3046940608a5743a68cc891deb13eglennrp  image->interlace=ping_info_interlace_method != 0 ? PNGInterlace : NoInterlace;
19033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
19043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
19053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
19063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "    PNG width: %lu, height: %lu",
1907c11cf6a442f3046940608a5743a68cc891deb13eglennrp        ping_info_width, ping_info_height);
19083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
19093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "    PNG color_type: %d, bit_depth: %d",
1910c11cf6a442f3046940608a5743a68cc891deb13eglennrp        ping_info_color_type, ping_info_bit_depth);
19113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
19123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "    PNG compression_method: %d",
1913c11cf6a442f3046940608a5743a68cc891deb13eglennrp        ping_info_compression_method);
19143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
19153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "    PNG interlace_method: %d, filter_method: %d",
1916c11cf6a442f3046940608a5743a68cc891deb13eglennrp        ping_info_interlace_method,ping_info_filter_method);
19173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
19183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
19193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if (PNG_LIBPNG_VER > 10008) && defined(PNG_READ_iCCP_SUPPORTED)
19209f2d324dcf6661f13b8b06f1e580cf3c7e49a446glennrp  if (png_get_valid(ping,ping_info,PNG_INFO_iCCP))
19213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
19223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      int
19233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        compression;
19243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
19253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      png_charp
19263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        info,
19273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        name;
19283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
19293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      png_uint_32
19303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        profile_length;
19313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
19323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) png_get_iCCP(ping,ping_info,&name,(int *) &compression,&info,
19333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        &profile_length);
19343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (profile_length != 0)
19353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
19363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          StringInfo
19373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            *profile;
19383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
19393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (logging != MagickFalse)
19403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
19413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              "    Reading PNG iCCP chunk.");
19423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          profile=AcquireStringInfo(profile_length);
19433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          SetStringInfoDatum(profile,(const unsigned char *) info);
19443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) SetImageProfile(image,"icc",profile);
19453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          profile=DestroyStringInfo(profile);
19463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
19473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
19483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
19493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_READ_sRGB_SUPPORTED)
19503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
19513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    int
19523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      intent;
19533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
19543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (mng_info->have_global_srgb)
19553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->rendering_intent=(RenderingIntent)
19563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (mng_info->global_srgb_intent+1);
19573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (png_get_sRGB(ping,ping_info,&intent))
19583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
19593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->rendering_intent=(RenderingIntent) (intent+1);
19603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (logging != MagickFalse)
19613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
19623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            "    Reading PNG sRGB chunk: rendering_intent: %d",intent+1);
19633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
19643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
19653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
19663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
19673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     double
19683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        file_gamma;
19693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
197062ff42431eb077e309a72d0aefefe059f180c4baglennrp     if (!png_get_gAMA(ping,ping_info,&file_gamma))
197162ff42431eb077e309a72d0aefefe059f180c4baglennrp       if (mng_info->have_global_gama)
197262ff42431eb077e309a72d0aefefe059f180c4baglennrp         png_set_gAMA(ping,ping_info,mng_info->global_gamma);
19733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     if (png_get_gAMA(ping,ping_info,&file_gamma))
19743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       {
19753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         image->gamma=(float) file_gamma;
19763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         if (logging != MagickFalse)
19773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
19783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             "    Reading PNG gAMA chunk: gamma: %f",file_gamma);
19793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       }
19803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
198162ff42431eb077e309a72d0aefefe059f180c4baglennrp  if (!png_get_valid(ping,ping_info,PNG_INFO_cHRM))
198262ff42431eb077e309a72d0aefefe059f180c4baglennrp    {
198362ff42431eb077e309a72d0aefefe059f180c4baglennrp      if (mng_info->have_global_chrm != MagickFalse)
198462ff42431eb077e309a72d0aefefe059f180c4baglennrp        {
198562ff42431eb077e309a72d0aefefe059f180c4baglennrp          (void) png_set_cHRM(ping,ping_info,
198662ff42431eb077e309a72d0aefefe059f180c4baglennrp            mng_info->global_chrm.white_point.x,
198762ff42431eb077e309a72d0aefefe059f180c4baglennrp            mng_info->global_chrm.white_point.y,
198862ff42431eb077e309a72d0aefefe059f180c4baglennrp            mng_info->global_chrm.red_primary.x,
198962ff42431eb077e309a72d0aefefe059f180c4baglennrp            mng_info->global_chrm.red_primary.y,
199062ff42431eb077e309a72d0aefefe059f180c4baglennrp            mng_info->global_chrm.green_primary.x,
199162ff42431eb077e309a72d0aefefe059f180c4baglennrp            mng_info->global_chrm.green_primary.y,
199262ff42431eb077e309a72d0aefefe059f180c4baglennrp            mng_info->global_chrm.blue_primary.x,
199362ff42431eb077e309a72d0aefefe059f180c4baglennrp            mng_info->global_chrm.blue_primary.y);
199462ff42431eb077e309a72d0aefefe059f180c4baglennrp        }
199562ff42431eb077e309a72d0aefefe059f180c4baglennrp    }
19969f2d324dcf6661f13b8b06f1e580cf3c7e49a446glennrp  if (png_get_valid(ping,ping_info,PNG_INFO_cHRM))
19973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
19983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) png_get_cHRM(ping,ping_info,
19993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        &image->chromaticity.white_point.x,
20003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        &image->chromaticity.white_point.y,
20013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        &image->chromaticity.red_primary.x,
20023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        &image->chromaticity.red_primary.y,
20033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        &image->chromaticity.green_primary.x,
20043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        &image->chromaticity.green_primary.y,
20053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        &image->chromaticity.blue_primary.x,
20063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        &image->chromaticity.blue_primary.y);
20073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (logging != MagickFalse)
20083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
20093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "    Reading PNG cHRM chunk.");
20103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
20113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->rendering_intent)
20123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
201362ff42431eb077e309a72d0aefefe059f180c4baglennrp      png_set_sRGB(ping,ping_info,image->rendering_intent-1);
201462ff42431eb077e309a72d0aefefe059f180c4baglennrp      png_set_gAMA(ping,ping_info,0.45455f);
201562ff42431eb077e309a72d0aefefe059f180c4baglennrp      png_set_cHRM(ping,ping_info,
201662ff42431eb077e309a72d0aefefe059f180c4baglennrp                  0.6400f, 0.3300f, 0.3000f, 0.6000f,
201762ff42431eb077e309a72d0aefefe059f180c4baglennrp                  0.1500f, 0.0600f, 0.3127f, 0.3290f);
20183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
20193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_oFFs_SUPPORTED)
20209f2d324dcf6661f13b8b06f1e580cf3c7e49a446glennrp  if (png_get_valid(ping,ping_info,PNG_INFO_oFFs))
20213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
20223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->page.x=png_get_x_offset_pixels(ping, ping_info);
20233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->page.y=png_get_y_offset_pixels(ping, ping_info);
20243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (logging != MagickFalse)
20253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (image->page.x || image->page.y)
20263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
20273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            "    Reading PNG oFFs chunk: x: %ld, y: %ld.",image->page.x,
20283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->page.y);
20293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
20303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
20313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_pHYs_SUPPORTED)
203262ff42431eb077e309a72d0aefefe059f180c4baglennrp  if (!png_get_valid(ping,ping_info,PNG_INFO_pHYs))
203362ff42431eb077e309a72d0aefefe059f180c4baglennrp    {
203462ff42431eb077e309a72d0aefefe059f180c4baglennrp      if (mng_info->have_global_phys)
203562ff42431eb077e309a72d0aefefe059f180c4baglennrp        {
203662ff42431eb077e309a72d0aefefe059f180c4baglennrp          png_set_pHYs(ping,ping_info,
203762ff42431eb077e309a72d0aefefe059f180c4baglennrp                       mng_info->global_x_pixels_per_unit,
203862ff42431eb077e309a72d0aefefe059f180c4baglennrp                       mng_info->global_y_pixels_per_unit,
203962ff42431eb077e309a72d0aefefe059f180c4baglennrp                       mng_info->global_phys_unit_type);
204062ff42431eb077e309a72d0aefefe059f180c4baglennrp        }
204162ff42431eb077e309a72d0aefefe059f180c4baglennrp    }
204262ff42431eb077e309a72d0aefefe059f180c4baglennrp
20439f2d324dcf6661f13b8b06f1e580cf3c7e49a446glennrp  if (png_get_valid(ping,ping_info,PNG_INFO_pHYs))
20443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
20453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      int
20463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        unit_type;
20473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
20483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      png_uint_32
20493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        x_resolution,
20503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        y_resolution;
20513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
20523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
20533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Set image resolution.
20543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
20553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) png_get_pHYs(ping,ping_info,&x_resolution,&y_resolution,
20563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          &unit_type);
20573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->x_resolution=(float) x_resolution;
20583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->y_resolution=(float) y_resolution;
20593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (unit_type == PNG_RESOLUTION_METER)
20603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
20613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->units=PixelsPerCentimeterResolution;
20623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->x_resolution=(double) x_resolution/100.0;
20633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->y_resolution=(double) y_resolution/100.0;
20643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
20653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (logging != MagickFalse)
20663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
20673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "    Reading PNG pHYs chunk: xres: %lu, yres: %lu, units: %d.",
20683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          x_resolution, y_resolution, unit_type);
20693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
20703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
20719f2d324dcf6661f13b8b06f1e580cf3c7e49a446glennrp  if (png_get_valid(ping,ping_info,PNG_INFO_PLTE))
20723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
20733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      int
20743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        number_colors;
20753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
20763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      png_colorp
20773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        palette;
20783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
20793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) png_get_PLTE(ping,ping_info,&palette,&number_colors);
20803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if ((number_colors == 0) &&
2081c11cf6a442f3046940608a5743a68cc891deb13eglennrp          ((int) ping_info_color_type == PNG_COLOR_TYPE_PALETTE))
20823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
20833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (mng_info->global_plte_length)
20843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
20853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              png_set_PLTE(ping,ping_info,mng_info->global_plte,
20863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (int) mng_info->global_plte_length);
20879f2d324dcf6661f13b8b06f1e580cf3c7e49a446glennrp              if (!png_get_valid(ping,ping_info,PNG_INFO_tRNS))
20883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (mng_info->global_trns_length)
20893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  {
20903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    if (mng_info->global_trns_length >
20913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        mng_info->global_plte_length)
20923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      (void) ThrowMagickException(&image->exception,
20933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        GetMagickModule(),CoderError,
20943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        "global tRNS has more entries than global PLTE",
20953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        "`%s'",image_info->filename);
20963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    png_set_tRNS(ping,ping_info,mng_info->global_trns,
20973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      (int) mng_info->global_trns_length,NULL);
20983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  }
20993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_READ_bKGD_SUPPORTED)
21003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (
21013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#ifndef PNG_READ_EMPTY_PLTE_SUPPORTED
21023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   mng_info->have_saved_bkgd_index ||
21033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
21049f2d324dcf6661f13b8b06f1e580cf3c7e49a446glennrp                   png_get_valid(ping,ping_info,PNG_INFO_bKGD))
21053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    {
21063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      png_color_16
21073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                         background;
21083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
21093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#ifndef PNG_READ_EMPTY_PLTE_SUPPORTED
21103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      if (mng_info->have_saved_bkgd_index)
21113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        background.index=mng_info->saved_bkgd_index;
21123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
2113cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp                      if (png_get_valid(ping, ping_info, PNG_INFO_bKGD))
2114cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp                        background.index=ping_background->index;
21153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      background.red=(png_uint_16)
21163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        mng_info->global_plte[background.index].red;
21173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      background.green=(png_uint_16)
21183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        mng_info->global_plte[background.index].green;
21193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      background.blue=(png_uint_16)
21203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        mng_info->global_plte[background.index].blue;
21213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      png_set_bKGD(ping,ping_info,&background);
21223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    }
21233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
21243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
21253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              else
21263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) ThrowMagickException(&image->exception,GetMagickModule(),
21273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  CoderError,"No global PLTE in file","`%s'",
21283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  image_info->filename);
21293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
21303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
21313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
21323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_READ_bKGD_SUPPORTED)
21339f2d324dcf6661f13b8b06f1e580cf3c7e49a446glennrp  if (mng_info->have_global_bkgd &&
21349f2d324dcf6661f13b8b06f1e580cf3c7e49a446glennrp          (!png_get_valid(ping,ping_info,PNG_INFO_bKGD)))
21353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->background_color=mng_info->mng_global_bkgd;
21369f2d324dcf6661f13b8b06f1e580cf3c7e49a446glennrp  if (png_get_valid(ping,ping_info,PNG_INFO_bKGD))
21373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
21383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
21393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Set image background color.
21403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
21413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (logging != MagickFalse)
21423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
21433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "    Reading PNG bKGD chunk.");
2144c11cf6a442f3046940608a5743a68cc891deb13eglennrp      if (ping_info_bit_depth <= MAGICKCORE_QUANTUM_DEPTH)
21453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
2146cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp          image->background_color.red=ping_background->red;
2147cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp          image->background_color.green=ping_background->green;
2148cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp          image->background_color.blue=ping_background->blue;
21493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
21503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else
21513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
21523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->background_color.red=
2153cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp            ScaleShortToQuantum(ping_background->red);
21543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->background_color.green=
2155cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp            ScaleShortToQuantum(ping_background->green);
21563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->background_color.blue=
2157cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp            ScaleShortToQuantum(ping_background->blue);
21583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
21593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
21603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
21613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  transparent_color.red=0;
21623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  transparent_color.green=0;
21633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  transparent_color.blue=0;
21643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  transparent_color.opacity=0;
21659f2d324dcf6661f13b8b06f1e580cf3c7e49a446glennrp  if (png_get_valid(ping,ping_info,PNG_INFO_tRNS))
21663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
21673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
21683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Image has a transparent background.
21693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
21703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      int
21713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        max_sample;
21723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
21733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (logging != MagickFalse)
21743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
21753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "    Reading PNG tRNS chunk.");
21763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2177c11cf6a442f3046940608a5743a68cc891deb13eglennrp      max_sample = (1 << ping_info_bit_depth) - 1;
21783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2179c11cf6a442f3046940608a5743a68cc891deb13eglennrp      if ((ping_info_color_type == PNG_COLOR_TYPE_GRAY &&
21803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (int)ping_info->trans_color.gray > max_sample) ||
2181c11cf6a442f3046940608a5743a68cc891deb13eglennrp          (ping_info_color_type == PNG_COLOR_TYPE_RGB &&
21823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          ((int)ping_info->trans_color.red > max_sample ||
21833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (int)ping_info->trans_color.green > max_sample ||
21843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (int)ping_info->trans_color.blue > max_sample)))
21853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
21863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (logging != MagickFalse)
21873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
21883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              "    Ignoring PNG tRNS chunk with out-of-range sample.");
21893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if (PNG_LIBPNG_VER < 10007)
21903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          ping_info->trans_alpha=(unsigned char *) RelinquishMagickMemory(
21913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            ping_info->trans_alpha);
21923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          ping_info->valid&=(~PNG_INFO_tRNS);
21933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#else
21943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          png_free_data(ping, ping_info, PNG_FREE_TRNS, 0);
21953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
21963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->matte=MagickFalse;
21973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
21983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else
21993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
22003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          transparent_color.red= (Quantum)(ping_info->trans_color.red);
22013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          transparent_color.green= (Quantum) (ping_info->trans_color.green);
22023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          transparent_color.blue= (Quantum) (ping_info->trans_color.blue);
22033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          transparent_color.opacity= (Quantum) (ping_info->trans_color.gray);
2204c11cf6a442f3046940608a5743a68cc891deb13eglennrp          if (ping_info_color_type == PNG_COLOR_TYPE_GRAY)
22053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
2206c11cf6a442f3046940608a5743a68cc891deb13eglennrp              if (ping_info_bit_depth < 8)
22073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
22083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  transparent_color.opacity=(Quantum) (((
22093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    ping_info->trans_color.gray)*255)/max_sample);
22103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
22113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              transparent_color.red=transparent_color.opacity;
22123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              transparent_color.green=transparent_color.opacity;
22133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              transparent_color.blue=transparent_color.opacity;
22143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
22153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
22163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
22173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_READ_sBIT_SUPPORTED)
22183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (mng_info->have_global_sbit)
22193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
22209f2d324dcf6661f13b8b06f1e580cf3c7e49a446glennrp      if (!png_get_valid(ping,ping_info,PNG_INFO_sBIT))
22213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        png_set_sBIT(ping,ping_info,&mng_info->global_sbit);
22223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
22233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
22243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  num_passes=png_set_interlace_handling(ping);
22253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_read_update_info(ping,ping_info);
22263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
22273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Initialize image structure.
22283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
22293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mng_info->image_box.left=0;
2230c11cf6a442f3046940608a5743a68cc891deb13eglennrp  mng_info->image_box.right=(long) ping_info_width;
22313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mng_info->image_box.top=0;
2232c11cf6a442f3046940608a5743a68cc891deb13eglennrp  mng_info->image_box.bottom=(long) ping_info_height;
22333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (mng_info->mng_type == 0)
22343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
2235c11cf6a442f3046940608a5743a68cc891deb13eglennrp      mng_info->mng_width=ping_info_width;
2236c11cf6a442f3046940608a5743a68cc891deb13eglennrp      mng_info->mng_height=ping_info_height;
22373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mng_info->frame=mng_info->image_box;
22383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mng_info->clip=mng_info->image_box;
22393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
22403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
22413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
22423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->page.y=mng_info->y_off[mng_info->object_id];
22433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
22443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->compression=ZipCompression;
2245c11cf6a442f3046940608a5743a68cc891deb13eglennrp  image->columns=ping_info_width;
2246c11cf6a442f3046940608a5743a68cc891deb13eglennrp  image->rows=ping_info_height;
2247c11cf6a442f3046940608a5743a68cc891deb13eglennrp  if (((int) ping_info_color_type == PNG_COLOR_TYPE_PALETTE) ||
2248c11cf6a442f3046940608a5743a68cc891deb13eglennrp      ((int) ping_info_color_type == PNG_COLOR_TYPE_GRAY_ALPHA) ||
2249c11cf6a442f3046940608a5743a68cc891deb13eglennrp      ((int) ping_info_color_type == PNG_COLOR_TYPE_GRAY))
22503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
22513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->storage_class=PseudoClass;
2252c11cf6a442f3046940608a5743a68cc891deb13eglennrp      image->colors=1UL << ping_info_bit_depth;
22533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if (MAGICKCORE_QUANTUM_DEPTH == 8)
22543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (image->colors > 256)
22553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->colors=256;
22563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#else
22573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (image->colors > 65536L)
22583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->colors=65536L;
22593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
2260c11cf6a442f3046940608a5743a68cc891deb13eglennrp      if ((int) ping_info_color_type == PNG_COLOR_TYPE_PALETTE)
22613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
22623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          int
22633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            number_colors;
22643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
22653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          png_colorp
22663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            palette;
22673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
22683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) png_get_PLTE(ping,ping_info,&palette,&number_colors);
22693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->colors=(unsigned long) number_colors;
22703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (logging != MagickFalse)
22713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
22723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              "    Reading PNG PLTE chunk: number_colors: %d.",number_colors);
22733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
22743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
22753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
22763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->storage_class == PseudoClass)
22773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
22783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
22793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Initialize image colormap.
22803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
22813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (AcquireImageColormap(image,image->colors) == MagickFalse)
22823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
2283c11cf6a442f3046940608a5743a68cc891deb13eglennrp      if ((int) ping_info_color_type == PNG_COLOR_TYPE_PALETTE)
22843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
22853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          int
22863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            number_colors;
22873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
22883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          png_colorp
22893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            palette;
22903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
22913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) png_get_PLTE(ping,ping_info,&palette,&number_colors);
22923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          for (i=0; i < (long) image->colors; i++)
22933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
22943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->colormap[i].red=ScaleCharToQuantum(palette[i].red);
22953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->colormap[i].green=ScaleCharToQuantum(palette[i].green);
22963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->colormap[i].blue=ScaleCharToQuantum(palette[i].blue);
22973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
22983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
22993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else
23003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
23013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          unsigned long
23023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            scale;
23033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2304c11cf6a442f3046940608a5743a68cc891deb13eglennrp          scale=(QuantumRange/((1UL << ping_info_bit_depth)-1));
23053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (scale < 1)
23063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             scale=1;
23073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          for (i=0; i < (long) image->colors; i++)
23083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
23093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->colormap[i].red=(Quantum) (i*scale);
23103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->colormap[i].green=(Quantum) (i*scale);
23113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->colormap[i].blue=(Quantum) (i*scale);
23123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
23133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       }
23143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
23153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
23163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Read image scanlines.
23173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
23183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->delay != 0)
23193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    mng_info->scenes_found++;
23203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((image_info->number_scenes != 0) && (mng_info->scenes_found > (long)
23213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (image_info->first_scene+image_info->number_scenes)))
23223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
23233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (logging != MagickFalse)
23243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
23253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "    Skipping PNG image data for scene %ld",
23263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          mng_info->scenes_found-1);
23273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      png_destroy_read_struct(&ping,&ping_info,&end_info);
23283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
2329f84a193d5f435588cd78d521fff3f1f852e227f8cristy      UnlockSemaphoreInfo(png_semaphore);
23303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
23313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (logging != MagickFalse)
23323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
23333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "  exit ReadOnePNGImage().");
23343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return(image);
23353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
23363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
23373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
23383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      "    Reading PNG IDAT chunk(s)");
23393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (num_passes > 1)
23403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    png_pixels=(unsigned char *) AcquireQuantumMemory(image->rows,
2341c451207335b7a8bb4e44f904f3d65a2727e41214glennrp      ping_rowbytes*sizeof(*png_pixels));
23423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
2343c451207335b7a8bb4e44f904f3d65a2727e41214glennrp    png_pixels=(unsigned char *) AcquireQuantumMemory(ping_rowbytes,
23443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      sizeof(*png_pixels));
23453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (png_pixels == (unsigned char *) NULL)
23463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
23473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
23483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
23493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      "    Converting PNG pixels to pixel packets");
23503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
23513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Convert PNG pixels to pixel packets.
23523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
23533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (setjmp(ping->jmpbuf))
23543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
23553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
23563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        PNG image is corrupt.
23573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
23583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      png_destroy_read_struct(&ping,&ping_info,&end_info);
23593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
2360f84a193d5f435588cd78d521fff3f1f852e227f8cristy      UnlockSemaphoreInfo(png_semaphore);
23613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
23623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (quantum_info != (QuantumInfo *) NULL)
23633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        quantum_info = DestroyQuantumInfo(quantum_info);
23643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (png_pixels != (unsigned char *) NULL)
23653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        png_pixels=(unsigned char *) RelinquishMagickMemory(png_pixels);
23663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (logging != MagickFalse)
23673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
23683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "  exit ReadOnePNGImage() with error.");
23693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (image != (Image *) NULL)
23707b755eb4f94efbb57160cce0d7afe7f8ed4ef066cristy        {
23717b755eb4f94efbb57160cce0d7afe7f8ed4ef066cristy          InheritException(exception,&image->exception);
23727b755eb4f94efbb57160cce0d7afe7f8ed4ef066cristy          image->columns=0;
23737b755eb4f94efbb57160cce0d7afe7f8ed4ef066cristy        }
23743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return(GetFirstImageInList(image));
23753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
2376ed5525230af20461366cdc5b8bbe0f7f9b166c44cristy  quantum_info=AcquireQuantumInfo(image_info,image);
2377ed5525230af20461366cdc5b8bbe0f7f9b166c44cristy  if (quantum_info == (QuantumInfo *) NULL)
2378ed5525230af20461366cdc5b8bbe0f7f9b166c44cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
23793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->storage_class == DirectClass)
23803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    for (pass=0; pass < num_passes; pass++)
23813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
23823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
23833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Convert image to DirectClass pixel packets.
23843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
23853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if (MAGICKCORE_QUANTUM_DEPTH == 8)
23863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      int
23873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        depth;
23883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2389c11cf6a442f3046940608a5743a68cc891deb13eglennrp      depth=(long) ping_info_bit_depth;
23903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
2391c11cf6a442f3046940608a5743a68cc891deb13eglennrp      image->matte=(((int) ping_info_color_type == PNG_COLOR_TYPE_RGB_ALPHA) ||
2392c11cf6a442f3046940608a5743a68cc891deb13eglennrp          ((int) ping_info_color_type == PNG_COLOR_TYPE_GRAY_ALPHA) ||
23939f2d324dcf6661f13b8b06f1e580cf3c7e49a446glennrp          (png_get_valid(ping,ping_info,PNG_INFO_tRNS))) ?
23949f2d324dcf6661f13b8b06f1e580cf3c7e49a446glennrp          MagickTrue : MagickFalse;
23953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
23963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (y=0; y < (long) image->rows; y++)
23973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
23983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (num_passes > 1)
2399c451207335b7a8bb4e44f904f3d65a2727e41214glennrp          row_offset=ping_rowbytes*y;
24003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        else
24013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          row_offset=0;
24023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        png_read_row(ping,png_pixels+row_offset,NULL);
2403abc8f408bb48da2d73cb760d61f16063695081d2cristy        q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
24043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (q == (PixelPacket *) NULL)
24053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
24063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if (0 && (MAGICKCORE_QUANTUM_DEPTH == 8) && !defined(MAGICKCORE_HDRI_SUPPORT))
24073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (depth == 16)
24083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
24093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            register Quantum
24103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              *p,
24113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              *r;
24123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
24133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            r=png_pixels+row_offset;
24143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            p=r;
2415c11cf6a442f3046940608a5743a68cc891deb13eglennrp            if (ping_info_color_type == PNG_COLOR_TYPE_GRAY)
24163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
24173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                for (x=(long) image->columns-1; x >= 0; x--)
24183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
24193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  *r++=*p++;
24203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  p++;
24219f2d324dcf6661f13b8b06f1e580cf3c7e49a446glennrp                  if (png_get_valid(ping,ping_info,PNG_INFO_tRNS)) &&
24223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     (((*(p-2) << 8)|*(p-1)) == transparent_color.opacity))
24233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    {
24243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                       /* Cheap transparency */
24253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                       *r++=TransparentOpacity;
24263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    }
24273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  else
24283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                       *r++=OpaqueOpacity;
24293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
24303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
2431c11cf6a442f3046940608a5743a68cc891deb13eglennrp            else if (ping_info_color_type == PNG_COLOR_TYPE_RGB)
24323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
24339f2d324dcf6661f13b8b06f1e580cf3c7e49a446glennrp              if (png_get_valid(ping,ping_info,PNG_INFO_tRNS))
24343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                for (x=(long) image->columns-1; x >= 0; x--)
24353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
24363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  *r++=*p++;
24373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  p++;
24383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  *r++=*p++;
24393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  p++;
24403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  *r++=*p++;
24413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  p++;
24423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if ((((*(p-6) << 8)|*(p-5)) == transparent_color.red) &&
24433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                       (((*(p-4) << 8)|*(p-3)) == transparent_color.green) &&
24443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                       (((*(p-2) << 8)|*(p-1)) == transparent_color.blue))
24453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    {
24463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                       /* Cheap transparency */
24473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                       *r++=TransparentOpacity;
24483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    }
24493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  else
24503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                       *r++=OpaqueOpacity;
24513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
24523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              else
24533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                for (x=(long) image->columns-1; x >= 0; x--)
24543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
24553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  *r++=*p++;
24563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  p++;
24573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  *r++=*p++;
24583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  p++;
24593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  *r++=*p++;
24603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  p++;
24613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  *r++=OpaqueOpacity;
24623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
24633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
2464c11cf6a442f3046940608a5743a68cc891deb13eglennrp            else if (ping_info_color_type == PNG_COLOR_TYPE_RGB_ALPHA)
24653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              for (x=(long) (4*image->columns); x != 0; x--)
24663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
24673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                *r++=*p++;
24683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                p++;
24693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
2470c11cf6a442f3046940608a5743a68cc891deb13eglennrp            else if (ping_info_color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
24713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              for (x=(long) (2*image->columns); x != 0; x--)
24723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
24733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                *r++=*p++;
24743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                p++;
24753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
24763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
2477c11cf6a442f3046940608a5743a68cc891deb13eglennrp        if (depth == 8 && ping_info_color_type == PNG_COLOR_TYPE_GRAY)
24783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
24793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            GrayQuantum,png_pixels+row_offset);
2480c11cf6a442f3046940608a5743a68cc891deb13eglennrp        if (ping_info_color_type == PNG_COLOR_TYPE_GRAY ||
2481c11cf6a442f3046940608a5743a68cc891deb13eglennrp            ping_info_color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
24823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
24833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            quantum_info->depth=8;
24843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
24853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              GrayAlphaQuantum,png_pixels+row_offset);
24863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
2487c11cf6a442f3046940608a5743a68cc891deb13eglennrp        else if (depth == 8 && ping_info_color_type == PNG_COLOR_TYPE_RGB)
24883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
24893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             RGBQuantum,png_pixels+row_offset);
2490c11cf6a442f3046940608a5743a68cc891deb13eglennrp        else if (ping_info_color_type == PNG_COLOR_TYPE_RGB ||
2491c11cf6a442f3046940608a5743a68cc891deb13eglennrp              ping_info_color_type == PNG_COLOR_TYPE_RGB_ALPHA)
24923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
24933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            quantum_info->depth=8;
24943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
24953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              RGBAQuantum,png_pixels+row_offset);
24963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
2497c11cf6a442f3046940608a5743a68cc891deb13eglennrp        else if (ping_info_color_type == PNG_COLOR_TYPE_PALETTE)
24983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
24993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              IndexQuantum,png_pixels+row_offset);
25003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#else /* (MAGICKCORE_QUANTUM_DEPTH != 8) */
2501c11cf6a442f3046940608a5743a68cc891deb13eglennrp        if ((int) ping_info_color_type == PNG_COLOR_TYPE_GRAY)
25023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
25033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            GrayQuantum,png_pixels+row_offset,exception);
2504c11cf6a442f3046940608a5743a68cc891deb13eglennrp        else if ((int) ping_info_color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
25053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
25063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            GrayAlphaQuantum,png_pixels+row_offset,exception);
2507c11cf6a442f3046940608a5743a68cc891deb13eglennrp        else if ((int) ping_info_color_type == PNG_COLOR_TYPE_RGB_ALPHA)
25083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
25093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            RGBAQuantum,png_pixels+row_offset,exception);
2510c11cf6a442f3046940608a5743a68cc891deb13eglennrp        else if ((int) ping_info_color_type == PNG_COLOR_TYPE_PALETTE)
25113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
25123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            IndexQuantum,png_pixels+row_offset,exception);
25133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        else
25143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
25153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            RGBQuantum,png_pixels+row_offset,exception);
25163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
25177a287bfadeadea12e47c2376ca78a5d101687142cristy        if ((image->previous == (Image *) NULL) && (num_passes == 1))
25187a287bfadeadea12e47c2376ca78a5d101687142cristy          {
25197a287bfadeadea12e47c2376ca78a5d101687142cristy            status=SetImageProgress(image,LoadImageTag,y,image->rows);
25207a287bfadeadea12e47c2376ca78a5d101687142cristy            if (status == MagickFalse)
25217a287bfadeadea12e47c2376ca78a5d101687142cristy              break;
25227a287bfadeadea12e47c2376ca78a5d101687142cristy          }
25233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (SyncAuthenticPixels(image,exception) == MagickFalse)
25243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
25253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
25267a287bfadeadea12e47c2376ca78a5d101687142cristy      if ((image->previous == (Image *) NULL) && (num_passes != 1))
25273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
25283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          status=SetImageProgress(image,LoadImageTag,pass,num_passes);
25293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (status == MagickFalse)
25303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
25313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
25323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
25333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else /* image->storage_class != DirectClass */
25343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    for (pass=0; pass < num_passes; pass++)
25353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
25363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Quantum
25373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *quantum_scanline;
25383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
25393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      register Quantum
25403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *r;
25413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
25423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
25433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Convert grayscale image to PseudoClass pixel packets.
25443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
2545c11cf6a442f3046940608a5743a68cc891deb13eglennrp      image->matte=ping_info_color_type == PNG_COLOR_TYPE_GRAY_ALPHA ?
25463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        MagickTrue : MagickFalse;
25473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      quantum_scanline=(Quantum *) AcquireQuantumMemory(image->columns,
25483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (image->matte ?  2 : 1)*sizeof(*quantum_scanline));
25493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (quantum_scanline == (Quantum *) NULL)
25503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
25513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (y=0; y < (long) image->rows; y++)
25523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
25533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (num_passes > 1)
2554c451207335b7a8bb4e44f904f3d65a2727e41214glennrp          row_offset=ping_rowbytes*y;
25553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        else
25563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          row_offset=0;
25573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        png_read_row(ping,png_pixels+row_offset,NULL);
25583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
25593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (q == (PixelPacket *) NULL)
25603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
25613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        indices=GetAuthenticIndexQueue(image);
25623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        p=png_pixels+row_offset;
25633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        r=quantum_scanline;
2564c11cf6a442f3046940608a5743a68cc891deb13eglennrp        switch (ping_info_bit_depth)
25653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
25663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 1:
25673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
25683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            register long
25693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              bit;
25703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
25713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            for (x=(long) image->columns-7; x > 0; x-=8)
25723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
25733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              for (bit=7; bit >= 0; bit--)
25743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                *r++=(Quantum) ((*p) & (0x01 << bit) ? 0x01 : 0x00);
25753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              p++;
25763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
25773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if ((image->columns % 8) != 0)
25783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
25793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                for (bit=7; bit >= (long) (8-(image->columns % 8)); bit--)
25803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  *r++=(Quantum) ((*p) & (0x01 << bit) ? 0x01 : 0x00);
25813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
25823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
25833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
25843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 2:
25853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
25863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            for (x=(long) image->columns-3; x > 0; x-=4)
25873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
25883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              *r++=(*p >> 6) & 0x03;
25893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              *r++=(*p >> 4) & 0x03;
25903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              *r++=(*p >> 2) & 0x03;
25913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              *r++=(*p++) & 0x03;
25923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
25933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if ((image->columns % 4) != 0)
25943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
25953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                for (i=3; i >= (long) (4-(image->columns % 4)); i--)
25963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  *r++=(Quantum) ((*p >> (i*2)) & 0x03);
25973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
25983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
25993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
26003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 4:
26013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
26023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            for (x=(long) image->columns-1; x > 0; x-=2)
26033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
26043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              *r++=(*p >> 4) & 0x0f;
26053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              *r++=(*p++) & 0x0f;
26063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
26073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if ((image->columns % 2) != 0)
26083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              *r++=(*p++ >> 4) & 0x0f;
26093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
26103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
26113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 8:
26123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
2613c11cf6a442f3046940608a5743a68cc891deb13eglennrp            if (ping_info_color_type == 4)
26143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              for (x=(long) image->columns-1; x >= 0; x--)
26153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
26163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                *r++=*p++;
26173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                /* In image.h, OpaqueOpacity is 0
26183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                 * TransparentOpacity is QuantumRange
26193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                 * In a PNG datastream, Opaque is QuantumRange
26203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                 * and Transparent is 0.
26213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                 */
26223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                q->opacity=ScaleCharToQuantum((unsigned char) (255-(*p++)));
26233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                q++;
26243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
26253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
26263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              for (x=(long) image->columns-1; x >= 0; x--)
26273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                *r++=*p++;
26283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
26293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
26303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 16:
26313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
26323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            for (x=(long) image->columns-1; x >= 0; x--)
26333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
26343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if (MAGICKCORE_QUANTUM_DEPTH == 16)
26353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              unsigned long
26363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                quantum;
26373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
26383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (image->colors > 256)
26393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                *r=((*p++) << 8);
26403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              else
26413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                *r=0;
26423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              quantum=(*r);
26433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              quantum|=(*p++);
26443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              *r=(Quantum) quantum;
26453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              r++;
2646c11cf6a442f3046940608a5743a68cc891deb13eglennrp              if (ping_info_color_type == 4)
26473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
26483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  quantum=((*p++) << 8);
26493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  quantum|=(*p++);
26503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  q->opacity=(Quantum) (QuantumRange-quantum);
26513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  q++;
26523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
26533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#else
26543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if (MAGICKCORE_QUANTUM_DEPTH == 32)
26553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              unsigned long
26563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                quantum;
26573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
26583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (image->colors > 256)
26593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                *r=((*p++) << 8);
26603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              else
26613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                *r=0;
26623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              quantum=(*r);
26633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              quantum|=(*p++);
26643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              *r=quantum;
26653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              r++;
2666c11cf6a442f3046940608a5743a68cc891deb13eglennrp              if (ping_info_color_type == 4)
26673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
26683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  q->opacity=(*p << 8) | *(p+1);
26693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  q->opacity*=65537L;
267046f08209f719f4adeea742c45873c2714e80cdb9cristy                  q->opacity=(Quantum) GetAlphaPixelComponent(q);
26713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  p+=2;
26723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  q++;
26733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
26743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#else /* MAGICKCORE_QUANTUM_DEPTH == 8 */
26753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              *r++=(*p++);
26763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              p++; /* strip low byte */
2677c11cf6a442f3046940608a5743a68cc891deb13eglennrp              if (ping_info_color_type == 4)
26783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
26793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  q->opacity=(Quantum) (QuantumRange-(*p++));
26803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  p++;
26813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  q++;
26823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
26833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
26843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
26853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
26863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
26873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
26883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          default:
26893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
26903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
26913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
26923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Transfer image scanline.
26933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
26943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        r=quantum_scanline;
26953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        for (x=0; x < (long) image->columns; x++)
26963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          indices[x]=(*r++);
26973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (SyncAuthenticPixels(image,exception) == MagickFalse)
26983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
26997a287bfadeadea12e47c2376ca78a5d101687142cristy        if ((image->previous == (Image *) NULL) && (num_passes == 1))
27007a287bfadeadea12e47c2376ca78a5d101687142cristy          {
27017a287bfadeadea12e47c2376ca78a5d101687142cristy            status=SetImageProgress(image,LoadImageTag,y,image->rows);
27027a287bfadeadea12e47c2376ca78a5d101687142cristy            if (status == MagickFalse)
27037a287bfadeadea12e47c2376ca78a5d101687142cristy              break;
27047a287bfadeadea12e47c2376ca78a5d101687142cristy          }
27053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
27067a287bfadeadea12e47c2376ca78a5d101687142cristy      if ((image->previous == (Image *) NULL) && (num_passes != 1))
27073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
27083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          status=SetImageProgress(image,LoadImageTag,pass,num_passes);
27093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (status == MagickFalse)
27103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
27113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
27123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      quantum_scanline=(Quantum *) RelinquishMagickMemory(quantum_scanline);
27133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
2714b32b90a7e1ee2275333589072c496b5f69e17feccristy  if (quantum_info != (QuantumInfo *) NULL)
2715b32b90a7e1ee2275333589072c496b5f69e17feccristy    quantum_info=DestroyQuantumInfo(quantum_info);
27163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->storage_class == PseudoClass)
27173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) SyncImage(image);
27183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_read_end(ping,ping_info);
27193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
27203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_info->number_scenes != 0 && mng_info->scenes_found-1 <
27213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (long) image_info->first_scene && image->delay != 0)
27223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
27233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      png_destroy_read_struct(&ping,&ping_info,&end_info);
27243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      png_pixels=(unsigned char *) RelinquishMagickMemory(png_pixels);
27253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->colors=2;
27263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) SetImageBackgroundColor(image);
27273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
2728f84a193d5f435588cd78d521fff3f1f852e227f8cristy      UnlockSemaphoreInfo(png_semaphore);
27293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
27303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (logging != MagickFalse)
27313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
27323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "  exit ReadOnePNGImage() early.");
27333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return(image);
27343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
27359f2d324dcf6661f13b8b06f1e580cf3c7e49a446glennrp  if (png_get_valid(ping,ping_info,PNG_INFO_tRNS))
27363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
27373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ClassType
27383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        storage_class;
27393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
27403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
27413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Image has a transparent background.
27423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
27433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      storage_class=image->storage_class;
27443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->matte=MagickTrue;
2745c11cf6a442f3046940608a5743a68cc891deb13eglennrp
2746c11cf6a442f3046940608a5743a68cc891deb13eglennrp#if 1  /* balfour fix */
2747c11cf6a442f3046940608a5743a68cc891deb13eglennrp/* From imagemagick discourse server, 5 Feb 2010 */
2748c11cf6a442f3046940608a5743a68cc891deb13eglennrp
2749c11cf6a442f3046940608a5743a68cc891deb13eglennrp    if (storage_class == PseudoClass)
2750c11cf6a442f3046940608a5743a68cc891deb13eglennrp   {
2751c11cf6a442f3046940608a5743a68cc891deb13eglennrp      if ((int) ping_info_color_type == PNG_COLOR_TYPE_PALETTE)
2752c11cf6a442f3046940608a5743a68cc891deb13eglennrp      {
2753cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp         for (x=0; x < ping_info_num_trans; x++)
2754c11cf6a442f3046940608a5743a68cc891deb13eglennrp         {
2755c11cf6a442f3046940608a5743a68cc891deb13eglennrp            image->colormap[x].opacity = ScaleCharToQuantum((unsigned char)(255-ping_info->trans_alpha[x]));
2756c11cf6a442f3046940608a5743a68cc891deb13eglennrp         }
2757c11cf6a442f3046940608a5743a68cc891deb13eglennrp      }
2758c11cf6a442f3046940608a5743a68cc891deb13eglennrp      else if (ping_info_color_type == PNG_COLOR_TYPE_GRAY)
2759c11cf6a442f3046940608a5743a68cc891deb13eglennrp      {
2760c11cf6a442f3046940608a5743a68cc891deb13eglennrp         for (x=0; x < (int) image->colors; x++)
2761c11cf6a442f3046940608a5743a68cc891deb13eglennrp         {
2762c11cf6a442f3046940608a5743a68cc891deb13eglennrp            if (image->colormap[x].red == transparent_color.opacity)
2763c11cf6a442f3046940608a5743a68cc891deb13eglennrp            {
2764c11cf6a442f3046940608a5743a68cc891deb13eglennrp               image->colormap[x].opacity = (Quantum) TransparentOpacity;
2765c11cf6a442f3046940608a5743a68cc891deb13eglennrp            }
2766c11cf6a442f3046940608a5743a68cc891deb13eglennrp         }
2767c11cf6a442f3046940608a5743a68cc891deb13eglennrp      }
2768c11cf6a442f3046940608a5743a68cc891deb13eglennrp   }
2769c11cf6a442f3046940608a5743a68cc891deb13eglennrp   else
2770c11cf6a442f3046940608a5743a68cc891deb13eglennrp   {
2771c11cf6a442f3046940608a5743a68cc891deb13eglennrp
2772c11cf6a442f3046940608a5743a68cc891deb13eglennrp      for (y=0; y < (long) image->rows; y++)
2773c11cf6a442f3046940608a5743a68cc891deb13eglennrp      {
2774c11cf6a442f3046940608a5743a68cc891deb13eglennrp        image->storage_class=storage_class;
2775c11cf6a442f3046940608a5743a68cc891deb13eglennrp        q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
2776c11cf6a442f3046940608a5743a68cc891deb13eglennrp        if (q == (PixelPacket *) NULL)
2777c11cf6a442f3046940608a5743a68cc891deb13eglennrp          break;
2778c11cf6a442f3046940608a5743a68cc891deb13eglennrp        indices=GetAuthenticIndexQueue(image);
2779c11cf6a442f3046940608a5743a68cc891deb13eglennrp
2780c11cf6a442f3046940608a5743a68cc891deb13eglennrp          for (x=(long) image->columns-1; x >= 0; x--)
2781c11cf6a442f3046940608a5743a68cc891deb13eglennrp          {
2782c11cf6a442f3046940608a5743a68cc891deb13eglennrp            if (ScaleQuantumToChar(q->red) == transparent_color.red &&
2783c11cf6a442f3046940608a5743a68cc891deb13eglennrp                ScaleQuantumToChar(q->green) == transparent_color.green &&
2784c11cf6a442f3046940608a5743a68cc891deb13eglennrp                ScaleQuantumToChar(q->blue) == transparent_color.blue)
2785c11cf6a442f3046940608a5743a68cc891deb13eglennrp               q->opacity=(Quantum) TransparentOpacity;
2786c11cf6a442f3046940608a5743a68cc891deb13eglennrp            else
2787c11cf6a442f3046940608a5743a68cc891deb13eglennrp              SetOpacityPixelComponent(q,OpaqueOpacity);
2788c11cf6a442f3046940608a5743a68cc891deb13eglennrp            q++;
2789c11cf6a442f3046940608a5743a68cc891deb13eglennrp          }
2790c11cf6a442f3046940608a5743a68cc891deb13eglennrp        if (SyncAuthenticPixels(image,exception) == MagickFalse)
2791c11cf6a442f3046940608a5743a68cc891deb13eglennrp          break;
2792c11cf6a442f3046940608a5743a68cc891deb13eglennrp      }
2793c11cf6a442f3046940608a5743a68cc891deb13eglennrp   }
2794c11cf6a442f3046940608a5743a68cc891deb13eglennrp
2795c11cf6a442f3046940608a5743a68cc891deb13eglennrp#else /* not balfour */
2796c11cf6a442f3046940608a5743a68cc891deb13eglennrp
2797c11cf6a442f3046940608a5743a68cc891deb13eglennrp
27983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (y=0; y < (long) image->rows; y++)
27993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
28003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->storage_class=storage_class;
28013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
28023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (q == (PixelPacket *) NULL)
28033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
28043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        indices=GetAuthenticIndexQueue(image);
28053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
28063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (storage_class == PseudoClass)
28073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
28083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            IndexPacket
28093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              indexpacket;
28103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2811c11cf6a442f3046940608a5743a68cc891deb13eglennrp            if ((int) ping_info_color_type == PNG_COLOR_TYPE_PALETTE)
28123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              for (x=0; x < (long) image->columns; x++)
28133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
28143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                indexpacket=indices[x];
2815cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp                if (indexpacket < ping_info_num_trans)
28163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  q->opacity=ScaleCharToQuantum((unsigned char)
28173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    (255-ping_info->trans_alpha[(long) indexpacket]));
28183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                else
2819ce70c17bb6433add2eb069515a4f3105989e0662cristy                  SetOpacityPixelComponent(q,OpaqueOpacity);
28203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                q++;
28213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
2822c11cf6a442f3046940608a5743a68cc891deb13eglennrp            else if (ping_info_color_type == PNG_COLOR_TYPE_GRAY)
28233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              for (x=0; x < (long) image->columns; x++)
28243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
28253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                indexpacket=indices[x];
28263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                q->red=image->colormap[(long) indexpacket].red;
28273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                q->green=q->red;
28283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                q->blue=q->red;
28293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (q->red == transparent_color.opacity)
28303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  q->opacity=(Quantum) TransparentOpacity;
28313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                else
2832ce70c17bb6433add2eb069515a4f3105989e0662cristy                  SetOpacityPixelComponent(q,OpaqueOpacity);
28333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                q++;
28343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
28353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
28363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        else
28373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          for (x=(long) image->columns-1; x >= 0; x--)
28383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
28393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (ScaleQuantumToChar(q->red) == transparent_color.red &&
28403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                ScaleQuantumToChar(q->green) == transparent_color.green &&
28413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                ScaleQuantumToChar(q->blue) == transparent_color.blue)
28423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               q->opacity=(Quantum) TransparentOpacity;
28433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
2844ce70c17bb6433add2eb069515a4f3105989e0662cristy              SetOpacityPixelComponent(q,OpaqueOpacity);
28453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            q++;
28463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
28473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (SyncAuthenticPixels(image,exception) == MagickFalse)
28483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
28493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
2850c11cf6a442f3046940608a5743a68cc891deb13eglennrp#endif /* not balfour */
28513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->storage_class=DirectClass;
28523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
28533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if (MAGICKCORE_QUANTUM_DEPTH == 8)
28543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->depth > 8)
28553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image->depth=8;
28563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
28573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (png_get_text(ping,ping_info,&text,&num_text) != 0)
28583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    for (i=0; i < (long) num_text; i++)
28593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
28603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /* Check for a profile */
28613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
28623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (logging != MagickFalse)
28633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
28643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "    Reading PNG text chunk");
28653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (memcmp(text[i].key, "Raw profile type ",17) == 0)
28663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) png_read_raw_profile(image,image_info,text,(int) i);
28673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else
28683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
28693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          char
28703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            *value;
28713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
28723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          length=text[i].text_length;
28733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          value=(char *) AcquireQuantumMemory(length+MaxTextExtent,
28743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            sizeof(*value));
28753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (value == (char *) NULL)
28763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
28773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) ThrowMagickException(&image->exception,GetMagickModule(),
28783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                ResourceLimitError,"MemoryAllocationFailed","`%s'",
28793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->filename);
28803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              break;
28813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
28823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          *value='\0';
28833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) ConcatenateMagickString(value,text[i].text,length+2);
28843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) SetImageProperty(image,text[i].key,value);
28853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (logging != MagickFalse)
28863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
28873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              "      Keyword: %s",text[i].key);
28883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          value=DestroyString(value);
28893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
28903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
28913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#ifdef MNG_OBJECT_BUFFERS
28923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
28933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Store the object if necessary.
28943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
28953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (object_id && !mng_info->frozen[object_id])
28963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
28973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (mng_info->ob[object_id] == (MngBuffer *) NULL)
28983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
28993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /*
29003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            create a new object buffer.
29013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          */
29023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          mng_info->ob[object_id]=(MngBuffer *)
290390823213d62b0ba18557e61f1e6892c6fffd6cd4cristy            AcquireAlignedMemory(1,sizeof(MngBuffer));
29043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (mng_info->ob[object_id] != (MngBuffer *) NULL)
29053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
29063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_info->ob[object_id]->image=(Image *) NULL;
29073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_info->ob[object_id]->reference_count=1;
29083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
29093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
29103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if ((mng_info->ob[object_id] == (MngBuffer *) NULL) ||
29113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          mng_info->ob[object_id]->frozen)
29123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
29133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (mng_info->ob[object_id] == (MngBuffer *) NULL)
29143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) ThrowMagickException(&image->exception,GetMagickModule(),
29153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              ResourceLimitError,"MemoryAllocationFailed","`%s'",
29163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              image->filename);
29173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (mng_info->ob[object_id]->frozen)
29183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) ThrowMagickException(&image->exception,GetMagickModule(),
29193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              ResourceLimitError,"Cannot overwrite frozen MNG object buffer",
29203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              "`%s'",image->filename);
29213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
29223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else
29233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
29243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
29253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (mng_info->ob[object_id]->image != (Image *) NULL)
29263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_info->ob[object_id]->image=DestroyImage
29273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (mng_info->ob[object_id]->image);
29283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          mng_info->ob[object_id]->image=CloneImage(image,0,0,MagickTrue,
29293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            &image->exception);
29303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (mng_info->ob[object_id]->image != (Image *) NULL)
29313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_info->ob[object_id]->image->file=(FILE *) NULL;
29323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          else
29333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) ThrowMagickException(&image->exception,GetMagickModule(),
29343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              ResourceLimitError,"Cloning image for object buffer failed",
29353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              "`%s'",image->filename);
2936c11cf6a442f3046940608a5743a68cc891deb13eglennrp          if (ping_info_width > 250000L || ping_info_height > 250000L)
29373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             png_error(ping,"PNG Image dimensions are too large.");
2938c11cf6a442f3046940608a5743a68cc891deb13eglennrp          mng_info->ob[object_id]->width=ping_info_width;
2939c11cf6a442f3046940608a5743a68cc891deb13eglennrp          mng_info->ob[object_id]->height=ping_info_height;
2940c11cf6a442f3046940608a5743a68cc891deb13eglennrp          mng_info->ob[object_id]->color_type=ping_info_color_type;
2941c11cf6a442f3046940608a5743a68cc891deb13eglennrp          mng_info->ob[object_id]->sample_depth=ping_info_bit_depth;
2942c11cf6a442f3046940608a5743a68cc891deb13eglennrp          mng_info->ob[object_id]->interlace_method=ping_info_interlace_method;
2943c11cf6a442f3046940608a5743a68cc891deb13eglennrp          mng_info->ob[object_id]->compression_method=
2944c11cf6a442f3046940608a5743a68cc891deb13eglennrp             ping_info_compression_method;
2945c11cf6a442f3046940608a5743a68cc891deb13eglennrp          mng_info->ob[object_id]->filter_method=ping_info_filter_method;
29469f2d324dcf6661f13b8b06f1e580cf3c7e49a446glennrp          if (png_get_valid(ping,ping_info,PNG_INFO_PLTE))
29473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
29483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              int
29493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                number_colors;
29503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
29513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              png_colorp
29523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                plte;
29533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
29543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              /*
29553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                Copy the PLTE to the object buffer.
29563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              */
29573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              png_get_PLTE(ping,ping_info,&plte,&number_colors);
29583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_info->ob[object_id]->plte_length=number_colors;
29593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              for (i=0; i < number_colors; i++)
29603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
29613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->ob[object_id]->plte[i]=plte[i];
29623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
29633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
29643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          else
29653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_info->ob[object_id]->plte_length=0;
29663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
29673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
29683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
29693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
29703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Relinquish resources.
29713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
29723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_destroy_read_struct(&ping,&ping_info,&end_info);
29733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
29743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_pixels=(unsigned char *) RelinquishMagickMemory(png_pixels);
29753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
2976f84a193d5f435588cd78d521fff3f1f852e227f8cristy  UnlockSemaphoreInfo(png_semaphore);
29773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
29783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
29793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
29803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
29813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      "  exit ReadOnePNGImage()");
29823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(image);
29833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
29843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* end of reading one PNG image */
29853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
29863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
29873ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic Image *ReadPNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
29883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
29893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
29903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *image,
29913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *previous;
29923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
29933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
29943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
29953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
29963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MngInfo
29973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *mng_info;
29983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
29993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  char
30003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    magic_number[MaxTextExtent];
30013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
30023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  int
30033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    have_mng_structure,
30043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    logging;
30053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
30063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ssize_t
30073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count;
30083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
30093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
30103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Open image file.
30113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
30123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info != (const ImageInfo *) NULL);
30133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info->signature == MagickSignature);
30143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_info->debug != MagickFalse)
30153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
30163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image_info->filename);
30173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(exception != (ExceptionInfo *) NULL);
30183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(exception->signature == MagickSignature);
30193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  logging=LogMagickEvent(CoderEvent,GetMagickModule(),"enter ReadPNGImage()");
30203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image=AcquireImage(image_info);
30213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mng_info=(MngInfo *) NULL;
30223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
30233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == MagickFalse)
30243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(FileOpenError,"UnableToOpenFile");
30253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
30263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Verify PNG signature.
30273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
30283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  count=ReadBlob(image,8,(unsigned char *) magic_number);
30293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (memcmp(magic_number,"\211PNG\r\n\032\n",8) != 0)
30303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
30313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
30323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Allocate a MngInfo structure.
30333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
30343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  have_mng_structure=MagickFalse;
303590823213d62b0ba18557e61f1e6892c6fffd6cd4cristy  mng_info=(MngInfo *) AcquireAlignedMemory(1,sizeof(MngInfo));
30363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (mng_info == (MngInfo *) NULL)
30373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
30383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
30393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Initialize members of the MngInfo structure.
30403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
30413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ResetMagickMemory(mng_info,0,sizeof(MngInfo));
30423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mng_info->image=image;
30433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  have_mng_structure=MagickTrue;
30443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
30453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  previous=image;
30463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image=ReadOnePNGImage(mng_info,image_info,exception);
30473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MngInfoFreeStruct(mng_info,&have_mng_structure);
30483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image == (Image *) NULL)
30493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
30503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (previous != (Image *) NULL)
30513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
30523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (previous->signature != MagickSignature)
30533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            ThrowReaderException(CorruptImageError,"CorruptImage");
30543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) CloseBlob(previous);
30553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) DestroyImageList(previous);
30563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
30573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (logging != MagickFalse)
30583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
30593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "exit ReadPNGImage() with error");
30603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return((Image *) NULL);
30613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
30623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloseBlob(image);
30633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((image->columns == 0) || (image->rows == 0))
30643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
30653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (logging != MagickFalse)
30663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
30673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "exit ReadPNGImage() with error.");
30683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ThrowReaderException(CorruptImageError,"CorruptImage");
30693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
30703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (LocaleCompare(image_info->magick,"PNG8") == 0)
30713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
30723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) SetImageType(image,PaletteType);
30733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (image->matte != MagickFalse)
30743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
30753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /* To do: Reduce to binary transparency */
30763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
30773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
30783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (LocaleCompare(image_info->magick,"PNG24") == 0)
30793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
30803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) SetImageType(image,TrueColorType);
30813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->matte=MagickFalse;
30823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
30833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (LocaleCompare(image_info->magick,"PNG32") == 0)
30843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) SetImageType(image,TrueColorMatteType);
30853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
30863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(CoderEvent,GetMagickModule(),"exit ReadPNGImage()");
30873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(image);
30883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
30893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
30903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
30913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
30923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(JNG_SUPPORTED)
30933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
30943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
30953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
30963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
30973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
30983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   R e a d O n e J N G I m a g e                                             %
30993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
31003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
31013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
31023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
31033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
31043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  ReadOneJNGImage() reads a JPEG Network Graphics (JNG) image file
31053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  (minus the 8-byte signature)  and returns it.  It allocates the memory
31063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  necessary for the new Image structure and returns a pointer to the new
31073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  image.
31083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
31093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  JNG support written by Glenn Randers-Pehrson, glennrp@image...
31103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
31113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the ReadOneJNGImage method is:
31123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
31133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      Image *ReadOneJNGImage(MngInfo *mng_info, const ImageInfo *image_info,
31143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%         ExceptionInfo *exception)
31153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
31163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
31173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
31183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o mng_info: Specifies a pointer to a MngInfo structure.
31193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
31203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image_info: the image info.
31213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
31223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o exception: return any errors or warnings in this structure.
31233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
31243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
31253ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic Image *ReadOneJNGImage(MngInfo *mng_info,
31263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    const ImageInfo *image_info, ExceptionInfo *exception)
31273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
31283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
31293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *alpha_image,
31303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *color_image,
31313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *image,
31323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *jng_image;
31333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
31343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ImageInfo
31353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *alpha_image_info,
31363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *color_image_info;
31373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
31383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  long
31393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    y;
31403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
31413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
31423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
31433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
31443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_uint_32
31453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    jng_height,
31463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    jng_width;
31473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
31483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_byte
31493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    jng_color_type,
31503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    jng_image_sample_depth,
31513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    jng_image_compression_method,
31523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    jng_image_interlace_method,
31533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    jng_alpha_sample_depth,
31543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    jng_alpha_compression_method,
31553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    jng_alpha_filter_method,
31563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    jng_alpha_interlace_method;
31573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
31583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register const PixelPacket
31593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *s;
31603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
31613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register long
31623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i,
31633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x;
31643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
31653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register PixelPacket
31663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q;
31673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
31683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register unsigned char
31693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p;
31703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
31713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned int
31723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    logging,
31733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    read_JSEP,
31743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    reading_idat,
31753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    skip_to_iend;
31763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
31773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned long
31783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    length;
31793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
31803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  jng_alpha_compression_method=0;
31813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  jng_alpha_sample_depth=8;
31823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  jng_color_type=0;
31833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  jng_height=0;
31843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  jng_width=0;
31853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  alpha_image=(Image *) NULL;
31863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  color_image=(Image *) NULL;
31873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  alpha_image_info=(ImageInfo *) NULL;
31883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  color_image_info=(ImageInfo *) NULL;
31893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
31903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  logging=LogMagickEvent(CoderEvent,GetMagickModule(),
31913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    "  enter ReadOneJNGImage()");
31923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
31933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image=mng_info->image;
31943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (GetAuthenticPixelQueue(image) != (PixelPacket *) NULL)
31953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
31963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
31973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Allocate next image structure.
31983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
31993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (logging != MagickFalse)
32003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
32013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           "  AcquireNextImage()");
32023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      AcquireNextImage(image_info,image);
32033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (GetNextImageInList(image) == (Image *) NULL)
32043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        return((Image *) NULL);
32053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image=SyncNextImageInList(image);
32063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
32073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mng_info->image=image;
32083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
32093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
32103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Signature bytes have already been read.
32113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
32123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
32133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  read_JSEP=MagickFalse;
32143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  reading_idat=MagickFalse;
32153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  skip_to_iend=MagickFalse;
32163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (;;)
32173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
32183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    char
32193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      type[MaxTextExtent];
32203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
32213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    unsigned char
32223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      *chunk;
32233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
32243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    unsigned int
32253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      count;
32263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
32273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
32283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Read a new JNG chunk.
32293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
32303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
32313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      2*GetBlobSize(image));
32323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (status == MagickFalse)
32333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
32343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    type[0]='\0';
32353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) ConcatenateMagickString(type,"errr",MaxTextExtent);
32363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    length=ReadBlobMSBLong(image);
32373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count=(unsigned int) ReadBlob(image,4,(unsigned char *) type);
32383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
32393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (logging != MagickFalse)
32403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
32413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "  Reading JNG chunk type %c%c%c%c, length: %lu",
32423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        type[0],type[1],type[2],type[3],length);
32433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
32443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (length > PNG_UINT_31_MAX || count == 0)
32453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ThrowReaderException(CorruptImageError,"CorruptImage");
32463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    p=NULL;
32473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    chunk=(unsigned char *) NULL;
32483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (length)
32493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
32503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        chunk=(unsigned char *) AcquireQuantumMemory(length,sizeof(*chunk));
32513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (chunk == (unsigned char *) NULL)
32523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
32533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        for (i=0; i < (long) length; i++)
32543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          chunk[i]=(unsigned char) ReadBlobByte(image);
32553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        p=chunk;
32563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
32573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) ReadBlobMSBLong(image);  /* read crc word */
32583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
32593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (skip_to_iend)
32603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
32613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (length)
32623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          chunk=(unsigned char *) RelinquishMagickMemory(chunk);
32633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
32643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
32653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
32663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (memcmp(type,mng_JHDR,4) == 0)
32673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
32683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (length == 16)
32693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
32703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            jng_width=(unsigned long) ((p[0] << 24) | (p[1] << 16) |
32713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (p[2] << 8) | p[3]);
32723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            jng_height=(unsigned long) ((p[4] << 24) | (p[5] << 16) |
32733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (p[6] << 8) | p[7]);
32743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            jng_color_type=p[8];
32753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            jng_image_sample_depth=p[9];
32763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            jng_image_compression_method=p[10];
32773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            jng_image_interlace_method=p[11];
32783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->interlace=jng_image_interlace_method != 0 ? PNGInterlace :
32793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              NoInterlace;
32803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            jng_alpha_sample_depth=p[12];
32813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            jng_alpha_compression_method=p[13];
32823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            jng_alpha_filter_method=p[14];
32833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            jng_alpha_interlace_method=p[15];
32843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (logging != MagickFalse)
32853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
32863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
32873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  "    jng_width:      %16lu",jng_width);
32883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
32893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  "    jng_width:      %16lu",jng_height);
32903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
32913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  "    jng_color_type: %16d",jng_color_type);
32923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
32933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  "    jng_image_sample_depth:      %3d",
32943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  jng_image_sample_depth);
32953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
32963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  "    jng_image_compression_method:%3d",
32973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  jng_image_compression_method);
32983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
32993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  "    jng_image_interlace_method:  %3d",
33003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  jng_image_interlace_method);
33013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
33023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  "    jng_alpha_sample_depth:      %3d",
33033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  jng_alpha_sample_depth);
33043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
33053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  "    jng_alpha_compression_method:%3d",
33063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  jng_alpha_compression_method);
33073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
33083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  "    jng_alpha_filter_method:     %3d",
33093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  jng_alpha_filter_method);
33103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
33113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  "    jng_alpha_interlace_method:  %3d",
33123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  jng_alpha_interlace_method);
33133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
33143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
33153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (length)
33163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          chunk=(unsigned char *) RelinquishMagickMemory(chunk);
33173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
33183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
33193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
33203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
33213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if ((reading_idat == MagickFalse) && (read_JSEP == MagickFalse) &&
33223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ((memcmp(type,mng_JDAT,4) == 0) || (memcmp(type,mng_JdAA,4) == 0) ||
33233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (memcmp(type,mng_IDAT,4) == 0) || (memcmp(type,mng_JDAA,4) == 0)))
33243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
33253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
33263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           o create color_image
33273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           o open color_blob, attached to color_image
33283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           o if (color type has alpha)
33293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               open alpha_blob, attached to alpha_image
33303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
33313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
333290823213d62b0ba18557e61f1e6892c6fffd6cd4cristy        color_image_info=(ImageInfo *)AcquireAlignedMemory(1,sizeof(ImageInfo));
33333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (color_image_info == (ImageInfo *) NULL)
33343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
33353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        GetImageInfo(color_image_info);
33363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        color_image=AcquireImage(color_image_info);
33373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (color_image == (Image *) NULL)
33383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
33393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
33403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (logging != MagickFalse)
33413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
33423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            "    Creating color_blob.");
33433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) AcquireUniqueFilename(color_image->filename);
33443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        status=OpenBlob(color_image_info,color_image,WriteBinaryBlobMode,
33453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          exception);
33463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (status == MagickFalse)
33473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          return((Image *) NULL);
33483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
33493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if ((image_info->ping == MagickFalse) && (jng_color_type >= 12))
33503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
33513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            alpha_image_info=(ImageInfo *)
335290823213d62b0ba18557e61f1e6892c6fffd6cd4cristy              AcquireAlignedMemory(1,sizeof(ImageInfo));
33533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (alpha_image_info == (ImageInfo *) NULL)
33543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
33553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            GetImageInfo(alpha_image_info);
33563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            alpha_image=AcquireImage(alpha_image_info);
33573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (alpha_image == (Image *) NULL)
33583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
33593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                alpha_image=DestroyImage(alpha_image);
33603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                ThrowReaderException(ResourceLimitError,
33613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  "MemoryAllocationFailed");
33623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
33633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (logging != MagickFalse)
33643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
33653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                "    Creating alpha_blob.");
33663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) AcquireUniqueFilename(alpha_image->filename);
33673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            status=OpenBlob(alpha_image_info,alpha_image,WriteBinaryBlobMode,
33683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              exception);
33693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (status == MagickFalse)
33703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              return((Image *) NULL);
33713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (jng_alpha_compression_method == 0)
33723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
33733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                unsigned char
33743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  data[18];
33753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
33763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (logging != MagickFalse)
33773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
33783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    "    Writing IHDR chunk to alpha_blob.");
33793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) WriteBlob(alpha_image,8,(const unsigned char *)
33803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  "\211PNG\r\n\032\n");
33813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) WriteBlobMSBULong(alpha_image,13L);
33823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                PNGType(data,mng_IHDR);
33833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                LogPNGChunk((int) logging,mng_IHDR,13L);
33843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                PNGLong(data+4,jng_width);
33853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                PNGLong(data+8,jng_height);
33863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                data[12]=jng_alpha_sample_depth;
33873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                data[13]=0; /* color_type gray */
33883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                data[14]=0; /* compression method 0 */
33893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                data[15]=0; /* filter_method 0 */
33903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                data[16]=0; /* interlace_method 0 */
33913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) WriteBlob(alpha_image,17,data);
33923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) WriteBlobMSBULong(alpha_image,crc32(0,data,17));
33933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
33943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
33953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        reading_idat=MagickTrue;
33963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
33973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
33983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (memcmp(type,mng_JDAT,4) == 0)
33993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
34003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
34013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           Copy chunk to color_image->blob
34023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
34033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
34043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (logging != MagickFalse)
34053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
34063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            "    Copying JDAT chunk data to color_blob.");
34073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
34083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) WriteBlob(color_image,length,chunk);
34093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (length)
34103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          chunk=(unsigned char *) RelinquishMagickMemory(chunk);
34113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
34123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
34133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
34143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (memcmp(type,mng_IDAT,4) == 0)
34153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
34163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        png_byte
34173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           data[5];
34183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
34193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
34203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           Copy IDAT header and chunk data to alpha_image->blob
34213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
34223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
34233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (image_info->ping == MagickFalse)
34243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
34253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (logging != MagickFalse)
34263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
34273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                "    Copying IDAT chunk data to alpha_blob.");
34283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
34293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) WriteBlobMSBULong(alpha_image,(unsigned long) length);
34303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            PNGType(data,mng_IDAT);
34313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            LogPNGChunk((int) logging,mng_IDAT,length);
34323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) WriteBlob(alpha_image,4,data);
34333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) WriteBlob(alpha_image,length,chunk);
34343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) WriteBlobMSBULong(alpha_image,
34353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              crc32(crc32(0,data,4),chunk,(uInt) length));
34363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
34373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (length)
34383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          chunk=(unsigned char *) RelinquishMagickMemory(chunk);
34393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
34403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
34413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
34423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if ((memcmp(type,mng_JDAA,4) == 0) || (memcmp(type,mng_JdAA,4) == 0))
34433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
34443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
34453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           Copy chunk data to alpha_image->blob
34463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
34473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
34483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (image_info->ping == MagickFalse)
34493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
34503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (logging != MagickFalse)
34513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
34523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                "    Copying JDAA chunk data to alpha_blob.");
34533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
34543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) WriteBlob(alpha_image,length,chunk);
34553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
34563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (length)
34573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          chunk=(unsigned char *) RelinquishMagickMemory(chunk);
34583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
34593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
34603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
34613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (memcmp(type,mng_JSEP,4) == 0)
34623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
34633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        read_JSEP=MagickTrue;
34643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (length)
34653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          chunk=(unsigned char *) RelinquishMagickMemory(chunk);
34663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
34673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
34683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
34693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (memcmp(type,mng_bKGD,4) == 0)
34703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
34713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (length == 2)
34723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
34733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->background_color.red=ScaleCharToQuantum(p[1]);
34743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->background_color.green=image->background_color.red;
34753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->background_color.blue=image->background_color.red;
34763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
34773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (length == 6)
34783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
34793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->background_color.red=ScaleCharToQuantum(p[1]);
34803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->background_color.green=ScaleCharToQuantum(p[3]);
34813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->background_color.blue=ScaleCharToQuantum(p[5]);
34823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
34833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        chunk=(unsigned char *) RelinquishMagickMemory(chunk);
34843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
34853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
34863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
34873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (memcmp(type,mng_gAMA,4) == 0)
34883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
34893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (length == 4)
34903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->gamma=((float) mng_get_long(p))*0.00001;
34913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        chunk=(unsigned char *) RelinquishMagickMemory(chunk);
34923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
34933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
34943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
34953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (memcmp(type,mng_cHRM,4) == 0)
34963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
34973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (length == 32)
34983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
34993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->chromaticity.white_point.x=0.00001*mng_get_long(p);
35003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->chromaticity.white_point.y=0.00001*mng_get_long(&p[4]);
35013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->chromaticity.red_primary.x=0.00001*mng_get_long(&p[8]);
35023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->chromaticity.red_primary.y=0.00001*mng_get_long(&p[12]);
35033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->chromaticity.green_primary.x=0.00001*mng_get_long(&p[16]);
35043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->chromaticity.green_primary.y=0.00001*mng_get_long(&p[20]);
35053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->chromaticity.blue_primary.x=0.00001*mng_get_long(&p[24]);
35063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->chromaticity.blue_primary.y=0.00001*mng_get_long(&p[28]);
35073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
35083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        chunk=(unsigned char *) RelinquishMagickMemory(chunk);
35093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
35103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
35113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
35123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (memcmp(type,mng_sRGB,4) == 0)
35133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
35143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (length == 1)
35153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
35163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->rendering_intent=(RenderingIntent) (p[0]+1);
35173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->gamma=0.45455f;
35183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->chromaticity.red_primary.x=0.6400f;
35193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->chromaticity.red_primary.y=0.3300f;
35203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->chromaticity.green_primary.x=0.3000f;
35213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->chromaticity.green_primary.y=0.6000f;
35223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->chromaticity.blue_primary.x=0.1500f;
35233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->chromaticity.blue_primary.y=0.0600f;
35243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->chromaticity.white_point.x=0.3127f;
35253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->chromaticity.white_point.y=0.3290f;
35263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
35273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        chunk=(unsigned char *) RelinquishMagickMemory(chunk);
35283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
35293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
35303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
35313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (memcmp(type,mng_oFFs,4) == 0)
35323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
35333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (length > 8)
35343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
35353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->page.x=mng_get_long(p);
35363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->page.y=mng_get_long(&p[4]);
35373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if ((int) p[8] != 0)
35383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
35393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->page.x/=10000;
35403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->page.y/=10000;
35413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
35423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
35433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (length)
35443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          chunk=(unsigned char *) RelinquishMagickMemory(chunk);
35453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
35463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
35473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
35483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (memcmp(type,mng_pHYs,4) == 0)
35493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
35503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (length > 8)
35513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
35523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->x_resolution=(double) mng_get_long(p);
35533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->y_resolution=(double) mng_get_long(&p[4]);
35543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if ((int) p[8] == PNG_RESOLUTION_METER)
35553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
35563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->units=PixelsPerCentimeterResolution;
35573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->x_resolution=image->x_resolution/100.0f;
35583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->y_resolution=image->y_resolution/100.0f;
35593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
35603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
35613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        chunk=(unsigned char *) RelinquishMagickMemory(chunk);
35623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
35633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
35643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
35653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if 0
35663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (memcmp(type,mng_iCCP,4) == 0)
35673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
35683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /* To do. */
35693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (length)
35703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          chunk=(unsigned char *) RelinquishMagickMemory(chunk);
35713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
35723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
35733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
35743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
35753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (length)
35763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      chunk=(unsigned char *) RelinquishMagickMemory(chunk);
35773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
35783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (memcmp(type,mng_IEND,4))
35793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      continue;
35803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    break;
35813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
35823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
35833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
35843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* IEND found */
35853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
35863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
35873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Finish up reading image data:
35883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
35893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       o read main image from color_blob.
35903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
35913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       o close color_blob.
35923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
35933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       o if (color_type has alpha)
35943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if alpha_encoding is PNG
35953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               read secondary image from alpha_blob via ReadPNG
35963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if alpha_encoding is JPEG
35973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               read secondary image from alpha_blob via ReadJPEG
35983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
35993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       o close alpha_blob.
36003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
36013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       o copy intensity of secondary image into
36023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         opacity samples of main image.
36033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
36043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       o destroy the secondary image.
36053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
36063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
36073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloseBlob(color_image);
36083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
36093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
36103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      "    Reading jng_image from color_blob.");
36113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) FormatMagickString(color_image_info->filename,MaxTextExtent,"%s",
36123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    color_image->filename);
36133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  color_image_info->ping=MagickFalse;   /* To do: avoid this */
36143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  jng_image=ReadImage(color_image_info,exception);
36153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (jng_image == (Image *) NULL)
36163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return((Image *) NULL);
36173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
36183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RelinquishUniqueFileResource(color_image->filename);
36193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  color_image=DestroyImage(color_image);
36203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  color_image_info=DestroyImageInfo(color_image_info);
36213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
36223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (jng_image == (Image *) NULL)
36233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return((Image *) NULL);
36243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
36253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
36263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
36273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      "    Copying jng_image pixels to main image.");
36283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->rows=jng_height;
36293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->columns=jng_width;
36303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  length=image->columns*sizeof(PixelPacket);
36313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (y=0; y < (long) image->rows; y++)
36323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
36333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    s=GetVirtualPixels(jng_image,0,y,image->columns,1,&image->exception);
36343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
36353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) CopyMagickMemory(q,s,length);
36363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (SyncAuthenticPixels(image,exception) == MagickFalse)
36373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
36383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
36393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  jng_image=DestroyImage(jng_image);
36403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_info->ping == MagickFalse)
36413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
36423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     if (jng_color_type >= 12)
36433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       {
36443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         if (jng_alpha_compression_method == 0)
36453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           {
36463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             png_byte
36473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               data[5];
36483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             (void) WriteBlobMSBULong(alpha_image,0x00000000L);
36493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             PNGType(data,mng_IEND);
36503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             LogPNGChunk((int) logging,mng_IEND,0L);
36513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             (void) WriteBlob(alpha_image,4,data);
36523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             (void) WriteBlobMSBULong(alpha_image,crc32(0,data,4));
36533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           }
36543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (void) CloseBlob(alpha_image);
36553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         if (logging != MagickFalse)
36563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
36573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             "    Reading opacity from alpha_blob.");
36583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
36593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (void) FormatMagickString(alpha_image_info->filename,MaxTextExtent,
36603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           "%s",alpha_image->filename);
36613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
36623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         jng_image=ReadImage(alpha_image_info,exception);
36633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         if (jng_image != (Image *) NULL)
36643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           for (y=0; y < (long) image->rows; y++)
36653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           {
36663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             s=GetVirtualPixels(jng_image,0,y,image->columns,1,
36673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                &image->exception);
36683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
36693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             if (image->matte != MagickFalse)
36703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               for (x=(long) image->columns; x != 0; x--,q++,s++)
36713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  q->opacity=(Quantum) QuantumRange-s->red;
36723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             else
36733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               for (x=(long) image->columns; x != 0; x--,q++,s++)
36743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               {
36753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  q->opacity=(Quantum) QuantumRange-s->red;
36763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if (q->opacity != OpaqueOpacity)
36773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    image->matte=MagickTrue;
36783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               }
36793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             if (SyncAuthenticPixels(image,exception) == MagickFalse)
36803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               break;
36813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           }
36823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (void) RelinquishUniqueFileResource(alpha_image->filename);
36833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         alpha_image=DestroyImage(alpha_image);
36843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         alpha_image_info=DestroyImageInfo(alpha_image_info);
36853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         if (jng_image != (Image *) NULL)
36863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           jng_image=DestroyImage(jng_image);
36873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       }
36883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
36893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
36903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
36913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Read the JNG image.
36923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
36933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (mng_info->mng_type == 0)
36943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
36953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mng_info->mng_width=jng_width;
36963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mng_info->mng_height=jng_height;
36973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
36983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->page.width == 0 && image->page.height == 0)
36993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
37003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image->page.width=jng_width;
37013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image->page.height=jng_height;
37023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
37033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->page.x == 0 && image->page.y == 0)
37043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
37053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image->page.x=mng_info->x_off[mng_info->object_id];
37063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image->page.y=mng_info->y_off[mng_info->object_id];
37073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
37083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
37093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
37103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image->page.y=mng_info->y_off[mng_info->object_id];
37113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
37123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mng_info->image_found++;
37133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=SetImageProgress(image,LoadImagesTag,2*TellBlob(image),
37143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    2*GetBlobSize(image));
37153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
37163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
37173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      "  exit ReadOneJNGImage()");
37183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(image);
37193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
37203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
37213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
37223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
37233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
37243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
37253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
37263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   R e a d J N G I m a g e                                                   %
37273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
37283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
37293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
37303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
37313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
37323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  ReadJNGImage() reads a JPEG Network Graphics (JNG) image file
37333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  (including the 8-byte signature)  and returns it.  It allocates the memory
37343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  necessary for the new Image structure and returns a pointer to the new
37353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  image.
37363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
37373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  JNG support written by Glenn Randers-Pehrson, glennrp@image...
37383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
37393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the ReadJNGImage method is:
37403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
37413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      Image *ReadJNGImage(const ImageInfo *image_info, ExceptionInfo
37423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%         *exception)
37433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
37443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
37453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
37463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image_info: the image info.
37473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
37483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o exception: return any errors or warnings in this structure.
37493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
37503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
37513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
37523ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic Image *ReadJNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
37533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
37543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
37553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *image,
37563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *previous;
37573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
37583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
37593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
37603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
37613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MngInfo
37623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *mng_info;
37633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
37643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  char
37653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    magic_number[MaxTextExtent];
37663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
37673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  int
37683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    have_mng_structure,
37693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    logging;
37703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
37713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  size_t
37723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count;
37733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
37743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
37753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Open image file.
37763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
37773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info != (const ImageInfo *) NULL);
37783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info->signature == MagickSignature);
37793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image_info->filename);
37803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(exception != (ExceptionInfo *) NULL);
37813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(exception->signature == MagickSignature);
37823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  logging=LogMagickEvent(CoderEvent,GetMagickModule(),"enter ReadJNGImage()");
37833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image=AcquireImage(image_info);
37843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mng_info=(MngInfo *) NULL;
37853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
37863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == MagickFalse)
37873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return((Image *) NULL);
37883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (LocaleCompare(image_info->magick,"JNG") != 0)
37893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
37903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
37913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Verify JNG signature.
37923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
37933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  count=(size_t) ReadBlob(image,8,(unsigned char *) magic_number);
37943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (memcmp(magic_number,"\213JNG\r\n\032\n",8) != 0)
37953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
37963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
37973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Allocate a MngInfo structure.
37983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
37993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  have_mng_structure=MagickFalse;
380090823213d62b0ba18557e61f1e6892c6fffd6cd4cristy  mng_info=(MngInfo *) AcquireAlignedMemory(1,sizeof(*mng_info));
38013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (mng_info == (MngInfo *) NULL)
38023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
38033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
38043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Initialize members of the MngInfo structure.
38053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
38063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ResetMagickMemory(mng_info,0,sizeof(MngInfo));
38073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  have_mng_structure=MagickTrue;
38083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
38093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mng_info->image=image;
38103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  previous=image;
38113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image=ReadOneJNGImage(mng_info,image_info,exception);
38123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MngInfoFreeStruct(mng_info,&have_mng_structure);
38133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image == (Image *) NULL)
38143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
38153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (IsImageObject(previous) != MagickFalse)
38163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
38173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) CloseBlob(previous);
38183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) DestroyImageList(previous);
38193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
38203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (logging != MagickFalse)
38213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
38223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "exit ReadJNGImage() with error");
38233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return((Image *) NULL);
38243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
38253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloseBlob(image);
38263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->columns == 0 || image->rows == 0)
38273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
38283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (logging != MagickFalse)
38293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
38303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "exit ReadJNGImage() with error");
38313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ThrowReaderException(CorruptImageError,"CorruptImage");
38323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
38333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
38343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(CoderEvent,GetMagickModule(),"exit ReadJNGImage()");
38353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(image);
38363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
38373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
38383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
38393ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic Image *ReadMNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
38403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
38413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  char
38423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    page_geometry[MaxTextExtent];
38433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
38443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
38453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *image,
38463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *previous;
38473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
38483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  int
38493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    have_mng_structure;
38503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
38513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  volatile int
38523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    first_mng_object,
38533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    logging,
38543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    object_id,
38553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    term_chunk_found,
38563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    skip_to_iend;
38573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
38583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  volatile long
38593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image_count=0;
38603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
38613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
38623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
38633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
38643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickOffsetType
38653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    offset;
38663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
38673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MngInfo
38683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *mng_info;
38693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
38703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MngBox
38713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    default_fb,
38723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    fb,
38733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    previous_fb;
38743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
38753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MNG_INSERT_LAYERS)
38763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  PixelPacket
38773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    mng_background_color;
38783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
38793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
38803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register unsigned char
38813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p;
38823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
38833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register long
38843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i;
38853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
38863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  size_t
38873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count;
38883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
38893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  long
38903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    loop_level;
38913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
38923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  volatile short
38933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    skipping_loop;
38943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
38953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MNG_INSERT_LAYERS)
38963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned int
38973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    mandatory_back=0;
38983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
38993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
39003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  volatile unsigned int
39013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#ifdef MNG_OBJECT_BUFFERS
39023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    mng_background_object=0,
39033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
39043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    mng_type=0;   /* 0: PNG or JNG; 1: MNG; 2: MNG-LC; 3: MNG-VLC */
39053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
39063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned long
39073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    default_frame_timeout,
39083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    frame_timeout,
39093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MNG_INSERT_LAYERS)
39103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image_height,
39113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image_width,
39123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
39133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    length;
39143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
39153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  volatile unsigned long
39163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    default_frame_delay,
39173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    final_delay,
39183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    final_image_delay,
39193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    frame_delay,
39203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MNG_INSERT_LAYERS)
39213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    insert_layers,
39223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
39233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    mng_iterations=1,
39243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    simplicity=0,
39253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    subframe_height=0,
39263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    subframe_width=0;
39273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
39283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  previous_fb.top=0;
39293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  previous_fb.bottom=0;
39303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  previous_fb.left=0;
39313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  previous_fb.right=0;
39323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  default_fb.top=0;
39333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  default_fb.bottom=0;
39343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  default_fb.left=0;
39353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  default_fb.right=0;
39363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
39373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
39383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Set image_info->type=OptimizeType (new in version 5.4.0) to get the
39393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    following optimizations:
39403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
39413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    o  16-bit depth is reduced to 8 if all pixels contain samples whose
39423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       high byte and low byte are identical.
39433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    o  Opaque matte channel is removed.
39443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    o  If matte channel is present but only one transparent color is
39453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       present, RGB+tRNS is written instead of RGBA
39463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    o  Grayscale images are reduced to 1, 2, or 4 bit depth if
39473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       this can be done without loss.
39483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    o  Palette is sorted to remove unused entries and to put a
39493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       transparent color first, if PNG_SORT_PALETTE is also defined.
39503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   */
39513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
39523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
39533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Open image file.
39543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
39553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info != (const ImageInfo *) NULL);
39563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info->signature == MagickSignature);
39573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image_info->filename);
39583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(exception != (ExceptionInfo *) NULL);
39593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(exception->signature == MagickSignature);
39603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  logging=LogMagickEvent(CoderEvent,GetMagickModule(),"enter ReadMNGImage()");
39613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image=AcquireImage(image_info);
39623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mng_info=(MngInfo *) NULL;
39633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
39643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == MagickFalse)
39653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return((Image *) NULL);
39663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  first_mng_object=MagickFalse;
39673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  skipping_loop=(-1);
39683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  have_mng_structure=MagickFalse;
39693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
39703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Allocate a MngInfo structure.
39713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
397290823213d62b0ba18557e61f1e6892c6fffd6cd4cristy  mng_info=(MngInfo *) AcquireAlignedMemory(1,sizeof(MngInfo));
39733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (mng_info == (MngInfo *) NULL)
39743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
39753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
39763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Initialize members of the MngInfo structure.
39773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
39783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ResetMagickMemory(mng_info,0,sizeof(MngInfo));
39793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mng_info->image=image;
39803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  have_mng_structure=MagickTrue;
39813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if (MAGICKCORE_QUANTUM_DEPTH == 16)
39823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    mng_info->optimize=image_info->type == OptimizeType;
39833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
39843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
39853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (LocaleCompare(image_info->magick,"MNG") == 0)
39863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
39873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      char
39883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        magic_number[MaxTextExtent];
39893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
39903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
39913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Verify MNG signature.
39923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
39933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      count=(size_t) ReadBlob(image,8,(unsigned char *) magic_number);
39943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (memcmp(magic_number,"\212MNG\r\n\032\n",8) != 0)
39953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ThrowReaderException(CorruptImageError,"ImproperImageHeader");
39963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
39973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Initialize some nonzero members of the MngInfo structure.
39983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
39993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (i=0; i < MNG_MAX_OBJECTS; i++)
40003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
40013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        mng_info->object_clip[i].right=(long) PNG_UINT_31_MAX;
40023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        mng_info->object_clip[i].bottom=(long) PNG_UINT_31_MAX;
40033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
40043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mng_info->exists[0]=MagickTrue;
40053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
40063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  first_mng_object=MagickTrue;
40073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mng_type=0;
40083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MNG_INSERT_LAYERS)
40093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  insert_layers=MagickFalse; /* should be False when converting or mogrifying */
40103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
40113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  default_frame_delay=0;
40123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  default_frame_timeout=0;
40133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  frame_delay=0;
40143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  final_delay=1;
40153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mng_info->ticks_per_second=1UL*image->ticks_per_second;
40163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  object_id=0;
40173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  skip_to_iend=MagickFalse;
40183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  term_chunk_found=MagickFalse;
40193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mng_info->framing_mode=1;
40203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MNG_INSERT_LAYERS)
40213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mandatory_back=MagickFalse;
40223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
40233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MNG_INSERT_LAYERS)
40243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mng_background_color=image->background_color;
40253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
40263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  default_fb=mng_info->frame;
40273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  previous_fb=mng_info->frame;
40283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  do
40293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
40303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    char
40313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      type[MaxTextExtent];
40323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
40333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (LocaleCompare(image_info->magick,"MNG") == 0)
40343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
40353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        unsigned char
40363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          *chunk;
40373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
40383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
40393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Read a new chunk.
40403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
40413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        type[0]='\0';
40423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) ConcatenateMagickString(type,"errr",MaxTextExtent);
40433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        length=ReadBlobMSBLong(image);
40443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        count=(size_t) ReadBlob(image,4,(unsigned char *) type);
40453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
40463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (logging != MagickFalse)
40473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
40483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           "  Reading MNG chunk type %c%c%c%c, length: %lu",
40493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           type[0],type[1],type[2],type[3],length);
40503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
40513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (length > PNG_UINT_31_MAX)
40523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          status=MagickFalse;
40533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (count == 0)
40543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          ThrowReaderException(CorruptImageError,"CorruptImage");
40553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        p=NULL;
40563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        chunk=(unsigned char *) NULL;
40573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (length)
40583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
40593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            chunk=(unsigned char *) AcquireQuantumMemory(length,sizeof(*chunk));
40603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (chunk == (unsigned char *) NULL)
40613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
40623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            for (i=0; i < (long) length; i++)
40633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              chunk[i]=(unsigned char) ReadBlobByte(image);
40643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            p=chunk;
40653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
40663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) ReadBlobMSBLong(image);  /* read crc word */
40673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
40683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if !defined(JNG_SUPPORTED)
40693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (memcmp(type,mng_JHDR,4) == 0)
40703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
40713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            skip_to_iend=MagickTrue;
40723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (mng_info->jhdr_warning == 0)
40733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) ThrowMagickException(&image->exception,GetMagickModule(),
40743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                CoderError,"JNGCompressNotSupported","`%s'",image->filename);
40753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_info->jhdr_warning++;
40763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
40773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
40783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (memcmp(type,mng_DHDR,4) == 0)
40793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
40803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            skip_to_iend=MagickTrue;
40813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (mng_info->dhdr_warning == 0)
40823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) ThrowMagickException(&image->exception,GetMagickModule(),
40833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                CoderError,"DeltaPNGNotSupported","`%s'",image->filename);
40843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_info->dhdr_warning++;
40853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
40863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (memcmp(type,mng_MEND,4) == 0)
40873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
40883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (skip_to_iend)
40893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
40903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (memcmp(type,mng_IEND,4) == 0)
40913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              skip_to_iend=MagickFalse;
40923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length)
40933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              chunk=(unsigned char *) RelinquishMagickMemory(chunk);
40943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (logging != MagickFalse)
40953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
40963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                "  Skip to IEND.");
40973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            continue;
40983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
40993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (memcmp(type,mng_MHDR,4) == 0)
41003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
41013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_info->mng_width=(unsigned long) ((p[0] << 24) | (p[1] << 16) |
41023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (p[2] << 8) | p[3]);
41033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_info->mng_height=(unsigned long) ((p[4] << 24) | (p[5] << 16) |
41043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (p[6] << 8) | p[7]);
41053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (logging != MagickFalse)
41063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
41073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
41083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  "  MNG width: %lu",mng_info->mng_width);
41093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
41103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  "  MNG height: %lu",mng_info->mng_height);
41113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
41123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            p+=8;
41133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_info->ticks_per_second=(unsigned long) mng_get_long(p);
41143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (mng_info->ticks_per_second == 0)
41153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              default_frame_delay=0;
41163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
41173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              default_frame_delay=1UL*image->ticks_per_second/
41183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->ticks_per_second;
41193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            frame_delay=default_frame_delay;
41203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            simplicity=0;
41213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length > 16)
41223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
41233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                p+=16;
41243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                simplicity=(unsigned long) mng_get_long(p);
41253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
41263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_type=1;    /* Full MNG */
41273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if ((simplicity != 0) && ((simplicity | 11) == 11))
41283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_type=2; /* LC */
41293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if ((simplicity != 0) && ((simplicity | 9) == 9))
41303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_type=3; /* VLC */
41313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MNG_INSERT_LAYERS)
41323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (mng_type != 3)
41333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              insert_layers=MagickTrue;
41343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
41353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (GetAuthenticPixelQueue(image) != (PixelPacket *) NULL)
41363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
41373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                /*
41383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  Allocate next image structure.
41393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                */
41403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                AcquireNextImage(image_info,image);
41413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (GetNextImageInList(image) == (Image *) NULL)
41423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  return((Image *) NULL);
41433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image=SyncNextImageInList(image);
41443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->image=image;
41453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
41463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
41473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if ((mng_info->mng_width > 65535L) ||
41483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (mng_info->mng_height > 65535L))
41493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              ThrowReaderException(ImageError,"WidthOrHeightExceedsLimit");
41503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) FormatMagickString(page_geometry,MaxTextExtent,"%lux%lu+0+0",
41513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_info->mng_width,mng_info->mng_height);
41523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_info->frame.left=0;
41533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_info->frame.right=(long) mng_info->mng_width;
41543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_info->frame.top=0;
41553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_info->frame.bottom=(long) mng_info->mng_height;
41563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_info->clip=default_fb=previous_fb=mng_info->frame;
41573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            for (i=0; i < MNG_MAX_OBJECTS; i++)
41583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_info->object_clip[i]=mng_info->frame;
41593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            chunk=(unsigned char *) RelinquishMagickMemory(chunk);
41603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            continue;
41613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
41623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
41633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (memcmp(type,mng_TERM,4) == 0)
41643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
41653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            int
41663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              repeat=0;
41673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
41683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
41693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length)
41703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              repeat=p[0];
41713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (repeat == 3)
41723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
41733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                final_delay=(png_uint_32) mng_get_long(&p[2]);
41743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_iterations=(png_uint_32) mng_get_long(&p[6]);
41753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (mng_iterations == PNG_UINT_31_MAX)
41763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  mng_iterations=0;
41773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->iterations=mng_iterations;
41783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                term_chunk_found=MagickTrue;
41793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
41803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (logging != MagickFalse)
41813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
41823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
41833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  "    repeat=%d",repeat);
41843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
41853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  "    final_delay=%ld",final_delay);
41863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
41873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  "    image->iterations=%ld",image->iterations);
41883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
41893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            chunk=(unsigned char *) RelinquishMagickMemory(chunk);
41903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            continue;
41913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
41923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (memcmp(type,mng_DEFI,4) == 0)
41933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
41943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (mng_type == 3)
41953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) ThrowMagickException(&image->exception,GetMagickModule(),
41963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                CoderError,"DEFI chunk found in MNG-VLC datastream","`%s'",
41973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->filename);
41983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            object_id=(p[0] << 8) | p[1];
41993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (mng_type == 2 && object_id != 0)
42003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) ThrowMagickException(&image->exception,GetMagickModule(),
42013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                CoderError,"Nonzero object_id in MNG-LC datastream","`%s'",
42023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->filename);
42033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (object_id > MNG_MAX_OBJECTS)
42043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
42053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                /*
42063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  Instead ofsuing a warning we should allocate a larger
42073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  MngInfo structure and continue.
42083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                */
42093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) ThrowMagickException(&image->exception,GetMagickModule(),
42103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  CoderError,"object id too large","`%s'",image->filename);
42113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                object_id=MNG_MAX_OBJECTS;
42123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
42133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (mng_info->exists[object_id])
42143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (mng_info->frozen[object_id])
42153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
42163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  chunk=(unsigned char *) RelinquishMagickMemory(chunk);
42173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  (void) ThrowMagickException(&image->exception,
42183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    GetMagickModule(),CoderError,
42193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    "DEFI cannot redefine a frozen MNG object","`%s'",
42203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    image->filename);
42213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  continue;
42223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
42233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_info->exists[object_id]=MagickTrue;
42243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length > 2)
42253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_info->invisible[object_id]=p[2];
42263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
42273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Extract object offset info.
42283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
42293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length > 11)
42303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
42313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->x_off[object_id]=(long) ((p[4] << 24) | (p[5] << 16) |
42323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (p[6] << 8) | p[7]);
42333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->y_off[object_id]=(long) ((p[8] << 24) | (p[9] << 16) |
42343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (p[10] << 8) | p[11]);
42353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (logging != MagickFalse)
42363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  {
42373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
42383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      "  x_off[%d]: %lu",object_id,mng_info->x_off[object_id]);
42393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
42403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      "  y_off[%d]: %lu",object_id,mng_info->y_off[object_id]);
42413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  }
42423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
42433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
42443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Extract object clipping info.
42453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
42463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length > 27)
42473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_info->object_clip[object_id]=mng_read_box(mng_info->frame,0,
42483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                &p[12]);
42493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            chunk=(unsigned char *) RelinquishMagickMemory(chunk);
42503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            continue;
42513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
42523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (memcmp(type,mng_bKGD,4) == 0)
42533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
42543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_info->have_global_bkgd=MagickFalse;
42553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length > 5)
42563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
42573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->mng_global_bkgd.red=
42583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  ScaleShortToQuantum((unsigned short) ((p[0] << 8) | p[1]));
42593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->mng_global_bkgd.green=
42603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  ScaleShortToQuantum((unsigned short) ((p[2] << 8) | p[3]));
42613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->mng_global_bkgd.blue=
42623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  ScaleShortToQuantum((unsigned short) ((p[4] << 8) | p[5]));
42633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->have_global_bkgd=MagickTrue;
42643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
42653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            chunk=(unsigned char *) RelinquishMagickMemory(chunk);
42663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            continue;
42673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
42683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (memcmp(type,mng_BACK,4) == 0)
42693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
42703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MNG_INSERT_LAYERS)
42713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length > 6)
42723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mandatory_back=p[6];
42733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
42743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mandatory_back=0;
42753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (mandatory_back && length > 5)
42763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
42773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_background_color.red=
42783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    ScaleShortToQuantum((unsigned short) ((p[0] << 8) | p[1]));
42793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_background_color.green=
42803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    ScaleShortToQuantum((unsigned short) ((p[2] << 8) | p[3]));
42813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_background_color.blue=
42823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    ScaleShortToQuantum((unsigned short) ((p[4] << 8) | p[5]));
42833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_background_color.opacity=OpaqueOpacity;
42843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
42853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#ifdef MNG_OBJECT_BUFFERS
42863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length > 8)
42873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_background_object=(p[7] << 8) | p[8];
42883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
42893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
42903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            chunk=(unsigned char *) RelinquishMagickMemory(chunk);
42913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            continue;
42923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
42933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (memcmp(type,mng_PLTE,4) == 0)
42943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
42953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
42963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Read global PLTE.
42973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
42983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length && (length < 769))
42993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
43003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (mng_info->global_plte == (png_colorp) NULL)
43013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  mng_info->global_plte=(png_colorp) AcquireQuantumMemory(256,
43023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    sizeof(*mng_info->global_plte));
43033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                for (i=0; i < (long) (length/3); i++)
43043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
43053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  mng_info->global_plte[i].red=p[3*i];
43063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  mng_info->global_plte[i].green=p[3*i+1];
43073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  mng_info->global_plte[i].blue=p[3*i+2];
43083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
43093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->global_plte_length=length/3;
43103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
43113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#ifdef MNG_LOOSE
43123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            for ( ; i < 256; i++)
43133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
43143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_info->global_plte[i].red=i;
43153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_info->global_plte[i].green=i;
43163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_info->global_plte[i].blue=i;
43173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
43183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length)
43193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_info->global_plte_length=256;
43203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
43213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
43223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_info->global_plte_length=0;
43233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            chunk=(unsigned char *) RelinquishMagickMemory(chunk);
43243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            continue;
43253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
43263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (memcmp(type,mng_tRNS,4) == 0)
43273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
43283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /* read global tRNS */
43293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
43303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length < 257)
43313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              for (i=0; i < (long) length; i++)
43323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->global_trns[i]=p[i];
43333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
43343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#ifdef MNG_LOOSE
43353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            for ( ; i < 256; i++)
43363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_info->global_trns[i]=255;
43373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
43383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_info->global_trns_length=length;
43393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            chunk=(unsigned char *) RelinquishMagickMemory(chunk);
43403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            continue;
43413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
43423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (memcmp(type,mng_gAMA,4) == 0)
43433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
43443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length == 4)
43453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
43463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                long
43473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  igamma;
43483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
43493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                igamma=mng_get_long(p);
43503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->global_gamma=((float) igamma)*0.00001;
43513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->have_global_gama=MagickTrue;
43523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
43533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
43543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_info->have_global_gama=MagickFalse;
43553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            chunk=(unsigned char *) RelinquishMagickMemory(chunk);
43563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            continue;
43573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
43583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
43593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (memcmp(type,mng_cHRM,4) == 0)
43603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
43613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
43623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Read global cHRM
43633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
43643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length == 32)
43653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
43663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->global_chrm.white_point.x=0.00001*mng_get_long(p);
43673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->global_chrm.white_point.y=0.00001*mng_get_long(&p[4]);
43683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->global_chrm.red_primary.x=0.00001*mng_get_long(&p[8]);
43693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->global_chrm.red_primary.y=0.00001*
43703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  mng_get_long(&p[12]);
43713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->global_chrm.green_primary.x=0.00001*
43723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  mng_get_long(&p[16]);
43733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->global_chrm.green_primary.y=0.00001*
43743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  mng_get_long(&p[20]);
43753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->global_chrm.blue_primary.x=0.00001*
43763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  mng_get_long(&p[24]);
43773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->global_chrm.blue_primary.y=0.00001*
43783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  mng_get_long(&p[28]);
43793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->have_global_chrm=MagickTrue;
43803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
43813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
43823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_info->have_global_chrm=MagickFalse;
43833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            chunk=(unsigned char *) RelinquishMagickMemory(chunk);
43843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            continue;
43853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
43863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (memcmp(type,mng_sRGB,4) == 0)
43873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
43883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
43893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Read global sRGB.
43903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
43913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length)
43923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
43933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->global_srgb_intent=(RenderingIntent) (p[0]+1);
43943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->have_global_srgb=MagickTrue;
43953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
43963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
43973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_info->have_global_srgb=MagickFalse;
43983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            chunk=(unsigned char *) RelinquishMagickMemory(chunk);
43993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            continue;
44003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
44013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (memcmp(type,mng_iCCP,4) == 0)
44023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
44033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /* To do. */
44043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
44053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
44063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Read global iCCP.
44073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
44083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length)
44093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              chunk=(unsigned char *) RelinquishMagickMemory(chunk);
44103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            continue;
44113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
44123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (memcmp(type,mng_FRAM,4) == 0)
44133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
44143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (mng_type == 3)
44153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) ThrowMagickException(&image->exception,GetMagickModule(),
44163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                CoderError,"FRAM chunk found in MNG-VLC datastream","`%s'",
44173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->filename);
44183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if ((mng_info->framing_mode == 2) || (mng_info->framing_mode == 4))
44193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              image->delay=frame_delay;
44203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            frame_delay=default_frame_delay;
44213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            frame_timeout=default_frame_timeout;
44223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            fb=default_fb;
44233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length)
44243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (p[0])
44253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->framing_mode=p[0];
44263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (logging != MagickFalse)
44273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
44283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                "    Framing_mode=%d",mng_info->framing_mode);
44293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length > 6)
44303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
44313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                /*
44323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  Note the delay and frame clipping boundaries.
44333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                */
44343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                p++; /* framing mode */
44353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                while (*p && ((p-chunk) < (long) length))
44363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  p++;  /* frame name */
44373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                p++;  /* frame name terminator */
44383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if ((p-chunk) < (long) (length-4))
44393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  {
44403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    int
44413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      change_delay,
44423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      change_timeout,
44433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      change_clipping;
44443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
44453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    change_delay=(*p++);
44463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    change_timeout=(*p++);
44473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    change_clipping=(*p++);
44483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    p++; /* change_sync */
44493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    if (change_delay)
44503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      {
44513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        frame_delay=(1UL*image->ticks_per_second*
44523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                            (mng_get_long(p))/mng_info->ticks_per_second);
44533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        if (change_delay == 2)
44543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          default_frame_delay=frame_delay;
44553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        p+=4;
44563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        if (logging != MagickFalse)
44573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
44583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                            "    Framing_delay=%ld",frame_delay);
44593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      }
44603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    if (change_timeout)
44613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      {
44623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        frame_timeout=(1UL*image->ticks_per_second*
44633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                            (mng_get_long(p))/mng_info->ticks_per_second);
44643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        if (change_delay == 2)
44653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          default_frame_timeout=frame_timeout;
44663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        p+=4;
44673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        if (logging != MagickFalse)
44683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
44693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                            "    Framing_timeout=%ld",frame_timeout);
44703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      }
44713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    if (change_clipping)
44723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      {
44733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        fb=mng_read_box(previous_fb,(char) p[0],&p[1]);
44743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        p+=17;
44753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        previous_fb=fb;
44763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        if (logging != MagickFalse)
44773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
44783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                            "    Frame_clipping: L=%ld R=%ld T=%ld B=%ld",
44793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                              fb.left, fb.right,fb.top,fb.bottom);
44803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        if (change_clipping == 2)
44813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          default_fb=fb;
44823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      }
44833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  }
44843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
44853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_info->clip=fb;
44863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_info->clip=mng_minimum_box(fb,mng_info->frame);
44873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            subframe_width=(unsigned long) (mng_info->clip.right
44883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               -mng_info->clip.left);
44893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            subframe_height=(unsigned long) (mng_info->clip.bottom
44903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               -mng_info->clip.top);
44913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
44923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Insert a background layer behind the frame if framing_mode is 4.
44933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
44943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MNG_INSERT_LAYERS)
44953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (logging != MagickFalse)
44963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
44973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                "   subframe_width=%lu, subframe_height=%lu",
44983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                subframe_width, subframe_height);
44993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (insert_layers && (mng_info->framing_mode == 4) &&
45003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (subframe_width) && (subframe_height))
45013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
45023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                /*
45033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  Allocate next image structure.
45043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                */
45053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (GetAuthenticPixelQueue(image) != (PixelPacket *) NULL)
45063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  {
45073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    AcquireNextImage(image_info,image);
45083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    if (GetNextImageInList(image) == (Image *) NULL)
45093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      {
45103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        image=DestroyImageList(image);
45113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        MngInfoFreeStruct(mng_info,&have_mng_structure);
45123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        return((Image *) NULL);
45133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      }
45143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    image=SyncNextImageInList(image);
45153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  }
45163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->image=image;
45173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (term_chunk_found)
45183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  {
45193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    image->start_loop=MagickTrue;
45203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    image->iterations=mng_iterations;
45213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    term_chunk_found=MagickFalse;
45223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  }
45233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                else
45243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    image->start_loop=MagickFalse;
45253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->columns=subframe_width;
45263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->rows=subframe_height;
45273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->page.width=subframe_width;
45283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->page.height=subframe_height;
45293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->page.x=mng_info->clip.left;
45303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->page.y=mng_info->clip.top;
45313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->background_color=mng_background_color;
45323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->matte=MagickFalse;
45333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->delay=0;
45343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) SetImageBackgroundColor(image);
45353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (logging != MagickFalse)
45363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
45373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    "  Inserted background layer, L=%ld, R=%ld, T=%ld, B=%ld",
45383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    mng_info->clip.left,mng_info->clip.right,
45393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    mng_info->clip.top,mng_info->clip.bottom);
45403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
45413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
45423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            chunk=(unsigned char *) RelinquishMagickMemory(chunk);
45433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            continue;
45443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
45453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (memcmp(type,mng_CLIP,4) == 0)
45463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
45473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            unsigned int
45483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              first_object,
45493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              last_object;
45503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
45513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
45523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Read CLIP.
45533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
45543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            first_object=(p[0] << 8) | p[1];
45553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            last_object=(p[2] << 8) | p[3];
45563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            for (i=(int) first_object; i <= (int) last_object; i++)
45573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
45583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (mng_info->exists[i] && !mng_info->frozen[i])
45593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
45603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  MngBox
45613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    box;
45623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
45633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  box=mng_info->object_clip[i];
45643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  mng_info->object_clip[i]=mng_read_box(box,(char) p[4],&p[5]);
45653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
45663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
45673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            chunk=(unsigned char *) RelinquishMagickMemory(chunk);
45683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            continue;
45693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
45703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (memcmp(type,mng_SAVE,4) == 0)
45713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
45723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            for (i=1; i < MNG_MAX_OBJECTS; i++)
45733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (mng_info->exists[i])
45743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
45753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                 mng_info->frozen[i]=MagickTrue;
45763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#ifdef MNG_OBJECT_BUFFERS
45773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                 if (mng_info->ob[i] != (MngBuffer *) NULL)
45783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    mng_info->ob[i]->frozen=MagickTrue;
45793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
45803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
45813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length)
45823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              chunk=(unsigned char *) RelinquishMagickMemory(chunk);
45833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            continue;
45843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
45853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
45863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if ((memcmp(type,mng_DISC,4) == 0) || (memcmp(type,mng_SEEK,4) == 0))
45873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
45883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
45893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Read DISC or SEEK.
45903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
45913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if ((length == 0) || !memcmp(type,mng_SEEK,4))
45923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
45933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                for (i=1; i < MNG_MAX_OBJECTS; i++)
45943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  MngInfoDiscardObject(mng_info,i);
45953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
45963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
45973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
45983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                register long
45993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  j;
46003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
46013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                for (j=0; j < (long) length; j+=2)
46023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
46033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  i=p[j] << 8 | p[j+1];
46043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  MngInfoDiscardObject(mng_info,i);
46053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
46063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
46073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length)
46083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              chunk=(unsigned char *) RelinquishMagickMemory(chunk);
46093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            continue;
46103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
46113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (memcmp(type,mng_MOVE,4) == 0)
46123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
46133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            unsigned long
46143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              first_object,
46153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              last_object;
46163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
46173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
46183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              read MOVE
46193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
46203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            first_object=(p[0] << 8) | p[1];
46213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            last_object=(p[2] << 8) | p[3];
46223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            for (i=(long) first_object; i <= (long) last_object; i++)
46233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
46243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (mng_info->exists[i] && !mng_info->frozen[i])
46253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
46263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  MngPair
46273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    new_pair;
46283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
46293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  MngPair
46303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    old_pair;
46313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
46323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  old_pair.a=mng_info->x_off[i];
46333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  old_pair.b=mng_info->y_off[i];
46343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  new_pair=mng_read_pair(old_pair,(int) p[4],&p[5]);
46353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  mng_info->x_off[i]=new_pair.a;
46363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  mng_info->y_off[i]=new_pair.b;
46373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
46383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
46393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            chunk=(unsigned char *) RelinquishMagickMemory(chunk);
46403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            continue;
46413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
46423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
46433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (memcmp(type,mng_LOOP,4) == 0)
46443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
46453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            long loop_iters=1;
46463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            loop_level=chunk[0];
46473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_info->loop_active[loop_level]=1;  /* mark loop active */
46483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
46493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Record starting point.
46503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
46513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            loop_iters=mng_get_long(&chunk[1]);
46523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (logging != MagickFalse)
46533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
46543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                "  LOOP level %ld  has %ld iterations ",loop_level,loop_iters);
46553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (loop_iters == 0)
46563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              skipping_loop=loop_level;
46573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
46583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
46593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->loop_jump[loop_level]=TellBlob(image);
46603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->loop_count[loop_level]=loop_iters;
46613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
46623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_info->loop_iteration[loop_level]=0;
46633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            chunk=(unsigned char *) RelinquishMagickMemory(chunk);
46643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            continue;
46653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
46663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (memcmp(type,mng_ENDL,4) == 0)
46673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
46683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            loop_level=chunk[0];
46693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (skipping_loop > 0)
46703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
46713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (skipping_loop == loop_level)
46723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  {
46733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    /*
46743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      Found end of zero-iteration loop.
46753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    */
46763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    skipping_loop=(-1);
46773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    mng_info->loop_active[loop_level]=0;
46783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  }
46793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
46803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
46813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
46823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (mng_info->loop_active[loop_level] == 1)
46833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  {
46843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    mng_info->loop_count[loop_level]--;
46853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    mng_info->loop_iteration[loop_level]++;
46863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    if (logging != MagickFalse)
46873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
46883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        "  ENDL: LOOP level %ld  has %ld remaining iterations ",
46893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        loop_level,mng_info->loop_count[loop_level]);
46903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    if (mng_info->loop_count[loop_level] != 0)
46913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      {
46923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        offset=SeekBlob(image,mng_info->loop_jump[loop_level],
46933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          SEEK_SET);
46943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        if (offset < 0)
46953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          ThrowReaderException(CorruptImageError,
46963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                            "ImproperImageHeader");
46973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      }
46983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    else
46993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      {
47003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        short
47013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          last_level;
47023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
47033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        /*
47043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          Finished loop.
47053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        */
47063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        mng_info->loop_active[loop_level]=0;
47073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        last_level=(-1);
47083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        for (i=0; i < loop_level; i++)
47093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          if (mng_info->loop_active[i] == 1)
47103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                            last_level=(short) i;
47113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        loop_level=last_level;
47123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      }
47133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  }
47143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
47153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            chunk=(unsigned char *) RelinquishMagickMemory(chunk);
47163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            continue;
47173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
47183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (memcmp(type,mng_CLON,4) == 0)
47193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
47203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (mng_info->clon_warning == 0)
47213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) ThrowMagickException(&image->exception,GetMagickModule(),
47223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                CoderError,"CLON is not implemented yet","`%s'",
47233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->filename);
47243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_info->clon_warning++;
47253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
47263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (memcmp(type,mng_MAGN,4) == 0)
47273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
47283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            png_uint_16
47293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_first,
47303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_last,
47313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_mb,
47323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_ml,
47333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_mr,
47343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_mt,
47353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_mx,
47363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_my,
47373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_methx,
47383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_methy;
47393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
47403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length > 1)
47413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_first=(p[0] << 8) | p[1];
47423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
47433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_first=0;
47443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length > 3)
47453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_last=(p[2] << 8) | p[3];
47463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
47473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_last=magn_first;
47483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#ifndef MNG_OBJECT_BUFFERS
47493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (magn_first || magn_last)
47503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (mng_info->magn_warning == 0)
47513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
47523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  (void) ThrowMagickException(&image->exception,
47533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     GetMagickModule(),CoderError,
47543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     "MAGN is not implemented yet for nonzero objects",
47553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     "`%s'",image->filename);
47563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   mng_info->magn_warning++;
47573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
47583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
47593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length > 4)
47603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_methx=p[4];
47613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
47623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_methx=0;
47633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
47643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length > 6)
47653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_mx=(p[5] << 8) | p[6];
47663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
47673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_mx=1;
47683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (magn_mx == 0)
47693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_mx=1;
47703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
47713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length > 8)
47723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_my=(p[7] << 8) | p[8];
47733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
47743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_my=magn_mx;
47753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (magn_my == 0)
47763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_my=1;
47773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
47783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length > 10)
47793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_ml=(p[9] << 8) | p[10];
47803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
47813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_ml=magn_mx;
47823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (magn_ml == 0)
47833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_ml=1;
47843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
47853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length > 12)
47863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_mr=(p[11] << 8) | p[12];
47873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
47883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_mr=magn_mx;
47893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (magn_mr == 0)
47903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_mr=1;
47913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
47923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length > 14)
47933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_mt=(p[13] << 8) | p[14];
47943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
47953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_mt=magn_my;
47963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (magn_mt == 0)
47973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_mt=1;
47983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
47993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length > 16)
48003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_mb=(p[15] << 8) | p[16];
48013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
48023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_mb=magn_my;
48033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (magn_mb == 0)
48043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_mb=1;
48053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
48063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length > 17)
48073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_methy=p[17];
48083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
48093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              magn_methy=magn_methx;
48103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
48113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (magn_methx > 5 || magn_methy > 5)
48123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (mng_info->magn_warning == 0)
48133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
48143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  (void) ThrowMagickException(&image->exception,
48153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     GetMagickModule(),CoderError,
48163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     "Unknown MAGN method in MNG datastream","`%s'",
48173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     image->filename);
48183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   mng_info->magn_warning++;
48193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
48203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#ifdef MNG_OBJECT_BUFFERS
48213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /* Magnify existing objects in the range magn_first to magn_last */
48223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
48233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (magn_first == 0 || magn_last == 0)
48243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
48253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                /* Save the magnification factors for object 0 */
48263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->magn_mb=magn_mb;
48273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->magn_ml=magn_ml;
48283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->magn_mr=magn_mr;
48293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->magn_mt=magn_mt;
48303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->magn_mx=magn_mx;
48313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->magn_my=magn_my;
48323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->magn_methx=magn_methx;
48333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->magn_methy=magn_methy;
48343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
48353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
48363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (memcmp(type,mng_PAST,4) == 0)
48373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
48383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (mng_info->past_warning == 0)
48393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) ThrowMagickException(&image->exception,GetMagickModule(),
48403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                CoderError,"PAST is not implemented yet","`%s'",
48413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->filename);
48423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_info->past_warning++;
48433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
48443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (memcmp(type,mng_SHOW,4) == 0)
48453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
48463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (mng_info->show_warning == 0)
48473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) ThrowMagickException(&image->exception,GetMagickModule(),
48483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                CoderError,"SHOW is not implemented yet","`%s'",
48493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->filename);
48503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_info->show_warning++;
48513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
48523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (memcmp(type,mng_sBIT,4) == 0)
48533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
48543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length < 4)
48553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_info->have_global_sbit=MagickFalse;
48563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
48573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
48583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->global_sbit.gray=p[0];
48593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->global_sbit.red=p[0];
48603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->global_sbit.green=p[1];
48613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->global_sbit.blue=p[2];
48623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->global_sbit.alpha=p[3];
48633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->have_global_sbit=MagickTrue;
48643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             }
48653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
48663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (memcmp(type,mng_pHYs,4) == 0)
48673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
48683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length > 8)
48693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
48703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->global_x_pixels_per_unit=
48713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    (unsigned long) mng_get_long(p);
48723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->global_y_pixels_per_unit=
48733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    (unsigned long) mng_get_long(&p[4]);
48743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->global_phys_unit_type=p[8];
48753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->have_global_phys=MagickTrue;
48763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
48773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
48783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_info->have_global_phys=MagickFalse;
48793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
48803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (memcmp(type,mng_pHYg,4) == 0)
48813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
48823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (mng_info->phyg_warning == 0)
48833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) ThrowMagickException(&image->exception,GetMagickModule(),
48843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                CoderError,"pHYg is not implemented.","`%s'",image->filename);
48853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_info->phyg_warning++;
48863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
48873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (memcmp(type,mng_BASI,4) == 0)
48883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
48893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            skip_to_iend=MagickTrue;
48903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (mng_info->basi_warning == 0)
48913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) ThrowMagickException(&image->exception,GetMagickModule(),
48923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                CoderError,"BASI is not implemented yet","`%s'",
48933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->filename);
48943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_info->basi_warning++;
48953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#ifdef MNG_BASI_SUPPORTED
48963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            basi_width=(unsigned long) ((p[0] << 24) | (p[1] << 16) |
48973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               (p[2] << 8) | p[3]);
48983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            basi_height=(unsigned long) ((p[4] << 24) | (p[5] << 16) |
48993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               (p[6] << 8) | p[7]);
49003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            basi_color_type=p[8];
49013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            basi_compression_method=p[9];
49023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            basi_filter_type=p[10];
49033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            basi_interlace_method=p[11];
49043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length > 11)
49053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              basi_red=(p[12] << 8) & p[13];
49063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
49073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              basi_red=0;
49083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length > 13)
49093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              basi_green=(p[14] << 8) & p[15];
49103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
49113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              basi_green=0;
49123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length > 15)
49133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              basi_blue=(p[16] << 8) & p[17];
49143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
49153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              basi_blue=0;
49163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length > 17)
49173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              basi_alpha=(p[18] << 8) & p[19];
49183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
49193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
49203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (basi_sample_depth == 16)
49213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  basi_alpha=65535L;
49223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                else
49233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  basi_alpha=255;
49243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
49253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length > 19)
49263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              basi_viewable=p[20];
49273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
49283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              basi_viewable=0;
49293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
49303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            chunk=(unsigned char *) RelinquishMagickMemory(chunk);
49313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            continue;
49323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
49333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (memcmp(type,mng_IHDR,4)
49343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(JNG_SUPPORTED)
49353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            && memcmp(type,mng_JHDR,4)
49363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
49373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            )
49383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
49393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /* Not an IHDR or JHDR chunk */
49403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (length)
49413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              chunk=(unsigned char *) RelinquishMagickMemory(chunk);
49423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            continue;
49433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
49443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* Process IHDR */
49453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (logging != MagickFalse)
49463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
49473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            "  Processing %c%c%c%c chunk",type[0],type[1],type[2],type[3]);
49483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        mng_info->exists[object_id]=MagickTrue;
49493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        mng_info->viewable[object_id]=MagickTrue;
49503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (mng_info->invisible[object_id])
49513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
49523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (logging != MagickFalse)
49533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
49543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                "  Skipping invisible object");
49553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            skip_to_iend=MagickTrue;
49563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            chunk=(unsigned char *) RelinquishMagickMemory(chunk);
49573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            continue;
49583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
49593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MNG_INSERT_LAYERS)
49603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (length < 8)
49613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          ThrowReaderException(CorruptImageError,"ImproperImageHeader");
49623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image_width=(unsigned  long) mng_get_long(p);
49633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image_height=(unsigned  long) mng_get_long(&p[4]);
49643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
49653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        chunk=(unsigned char *) RelinquishMagickMemory(chunk);
49663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
49673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
49683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Insert a transparent background layer behind the entire animation
49693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if it is not full screen.
49703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
49713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MNG_INSERT_LAYERS)
49723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (insert_layers && mng_type && first_mng_object)
49733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
49743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if ((mng_info->clip.left > 0) || (mng_info->clip.top > 0) ||
49753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (image_width < mng_info->mng_width) ||
49763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (mng_info->clip.right < (long) mng_info->mng_width) ||
49773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (image_height < mng_info->mng_height) ||
49783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (mng_info->clip.bottom < (long) mng_info->mng_height))
49793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
49803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (GetAuthenticPixelQueue(image) != (PixelPacket *) NULL)
49813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  {
49823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    /*
49833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      Allocate next image structure.
49843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    */
49853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    AcquireNextImage(image_info,image);
49863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    if (GetNextImageInList(image) == (Image *) NULL)
49873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      {
49883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        image=DestroyImageList(image);
49893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        MngInfoFreeStruct(mng_info,&have_mng_structure);
49903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        return((Image *) NULL);
49913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      }
49923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    image=SyncNextImageInList(image);
49933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  }
49943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->image=image;
49953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (term_chunk_found)
49963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  {
49973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    image->start_loop=MagickTrue;
49983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    image->iterations=mng_iterations;
49993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    term_chunk_found=MagickFalse;
50003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  }
50013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                else
50023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    image->start_loop=MagickFalse;
50033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                /*
50043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  Make a background rectangle.
50053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                */
50063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->delay=0;
50073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->columns=mng_info->mng_width;
50083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->rows=mng_info->mng_height;
50093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->page.width=mng_info->mng_width;
50103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->page.height=mng_info->mng_height;
50113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->page.x=0;
50123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->page.y=0;
50133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->background_color=mng_background_color;
50143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) SetImageBackgroundColor(image);
50153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (logging != MagickFalse)
50163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
50173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    "  Inserted transparent background layer, W=%lud, H=%lud",
50183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    mng_info->mng_width,mng_info->mng_height);
50193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
50203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
50213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
50223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Insert a background layer behind the upcoming image if
50233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          framing_mode is 3, and we haven't already inserted one.
50243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
50253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (insert_layers && (mng_info->framing_mode == 3) &&
50263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (subframe_width) && (subframe_height) && (simplicity == 0 ||
50273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (simplicity & 0x08)))
50283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
50293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (GetAuthenticPixelQueue(image) != (PixelPacket *) NULL)
50303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
50313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              /*
50323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                Allocate next image structure.
50333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              */
50343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              AcquireNextImage(image_info,image);
50353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (GetNextImageInList(image) == (Image *) NULL)
50363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
50373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  image=DestroyImageList(image);
50383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  MngInfoFreeStruct(mng_info,&have_mng_structure);
50393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  return((Image *) NULL);
50403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
50413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              image=SyncNextImageInList(image);
50423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
50433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_info->image=image;
50443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (term_chunk_found)
50453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
50463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->start_loop=MagickTrue;
50473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->iterations=mng_iterations;
50483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                term_chunk_found=MagickFalse;
50493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
50503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
50513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->start_loop=MagickFalse;
50523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->delay=0;
50533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->columns=subframe_width;
50543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->rows=subframe_height;
50553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->page.width=subframe_width;
50563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->page.height=subframe_height;
50573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->page.x=mng_info->clip.left;
50583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->page.y=mng_info->clip.top;
50593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->background_color=mng_background_color;
50603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->matte=MagickFalse;
50613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) SetImageBackgroundColor(image);
50623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (logging != MagickFalse)
50633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
50643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                "  Inserted background layer, L=%ld, R=%ld, T=%ld, B=%ld",
50653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->clip.left,mng_info->clip.right,
50663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->clip.top,mng_info->clip.bottom);
50673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
50683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif /* MNG_INSERT_LAYERS */
50693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        first_mng_object=MagickFalse;
50703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (GetAuthenticPixelQueue(image) != (PixelPacket *) NULL)
50713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
50723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
50733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Allocate next image structure.
50743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
50753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            AcquireNextImage(image_info,image);
50763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (GetNextImageInList(image) == (Image *) NULL)
50773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
50783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image=DestroyImageList(image);
50793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                MngInfoFreeStruct(mng_info,&have_mng_structure);
50803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                return((Image *) NULL);
50813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
50823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image=SyncNextImageInList(image);
50833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
50843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        mng_info->image=image;
50853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
50863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          GetBlobSize(image));
50873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (status == MagickFalse)
50883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
50893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (term_chunk_found)
50903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
50913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->start_loop=MagickTrue;
50923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            term_chunk_found=MagickFalse;
50933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
50943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        else
50953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->start_loop=MagickFalse;
50963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (mng_info->framing_mode == 1 || mng_info->framing_mode == 3)
50973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
50983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->delay=frame_delay;
50993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            frame_delay=default_frame_delay;
51003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
51013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        else
51023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->delay=0;
51033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->page.width=mng_info->mng_width;
51043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->page.height=mng_info->mng_height;
51053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->page.x=mng_info->x_off[object_id];
51063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->page.y=mng_info->y_off[object_id];
51073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->iterations=mng_iterations;
51083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
51093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Seek back to the beginning of the IHDR or JHDR chunk's length field.
51103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
51113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (logging != MagickFalse)
51123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
51133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            "  Seeking back to beginning of %c%c%c%c chunk",type[0],type[1],
51143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            type[2],type[3]);
51153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        offset=SeekBlob(image,-((long) length+12),SEEK_CUR);
51163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (offset < 0)
51173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          ThrowReaderException(CorruptImageError,"ImproperImageHeader");
51183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
51193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
51203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    previous=image;
51213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    mng_info->image=image;
51223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    mng_info->mng_type=mng_type;
51233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    mng_info->object_id=object_id;
51243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
51253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (memcmp(type,mng_IHDR,4) == 0)
51263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image=ReadOnePNGImage(mng_info,image_info,exception);
51273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(JNG_SUPPORTED)
51283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    else
51293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image=ReadOneJNGImage(mng_info,image_info,exception);
51303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
51313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
51323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (image == (Image *) NULL)
51333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
51343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (IsImageObject(previous) != MagickFalse)
51353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
51363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) DestroyImageList(previous);
51373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) CloseBlob(previous);
51383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
51393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        MngInfoFreeStruct(mng_info,&have_mng_structure);
51403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        return((Image *) NULL);
51413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
51423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (image->columns == 0 || image->rows == 0)
51433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
51443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) CloseBlob(image);
51453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image=DestroyImageList(image);
51463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        MngInfoFreeStruct(mng_info,&have_mng_structure);
51473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        return((Image *) NULL);
51483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
51493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    mng_info->image=image;
51503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
51513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (mng_type)
51523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
51533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        MngBox
51543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          crop_box;
51553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
51563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (mng_info->magn_methx || mng_info->magn_methy)
51573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
51583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            png_uint_32
51593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               magnified_height,
51603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               magnified_width;
51613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
51623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (logging != MagickFalse)
51633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
51643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                "  Processing MNG MAGN chunk");
51653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
51663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (mng_info->magn_methx == 1)
51673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
51683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                magnified_width=mng_info->magn_ml;
51693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (image->columns > 1)
51703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   magnified_width += mng_info->magn_mr;
51713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (image->columns > 2)
51723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   magnified_width += (image->columns-2)*(mng_info->magn_mx);
51733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
51743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
51753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
51763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                magnified_width=image->columns;
51773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (image->columns > 1)
51783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   magnified_width += mng_info->magn_ml-1;
51793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (image->columns > 2)
51803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   magnified_width += mng_info->magn_mr-1;
51813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (image->columns > 3)
51823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   magnified_width += (image->columns-3)*(mng_info->magn_mx-1);
51833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
51843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (mng_info->magn_methy == 1)
51853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
51863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                magnified_height=mng_info->magn_mt;
51873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (image->rows > 1)
51883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   magnified_height += mng_info->magn_mb;
51893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (image->rows > 2)
51903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   magnified_height += (image->rows-2)*(mng_info->magn_my);
51913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
51923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
51933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
51943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                magnified_height=image->rows;
51953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (image->rows > 1)
51963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   magnified_height += mng_info->magn_mt-1;
51973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (image->rows > 2)
51983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   magnified_height += mng_info->magn_mb-1;
51993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (image->rows > 3)
52003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   magnified_height += (image->rows-3)*(mng_info->magn_my-1);
52013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
52023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (magnified_height > image->rows ||
52033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                magnified_width > image->columns)
52043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
52053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                Image
52063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  *large_image;
52073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
52083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                int
52093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  yy;
52103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
52113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                long
52123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  m,
52133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  y;
52143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
52153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                register long
52163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  x;
52173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
52183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                register PixelPacket
52193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  *n,
52203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  *q;
52213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
52223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                PixelPacket
52233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  *next,
52243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  *prev;
52253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
52263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                png_uint_16
52273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  magn_methx,
52283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  magn_methy;
52293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
52303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                /*
52313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  Allocate next image structure.
52323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                */
52333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (logging != MagickFalse)
52343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
52353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    "    Allocate magnified image");
52363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                AcquireNextImage(image_info,image);
52373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (GetNextImageInList(image) == (Image *) NULL)
52383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  {
52393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    image=DestroyImageList(image);
52403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    MngInfoFreeStruct(mng_info,&have_mng_structure);
52413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    return((Image *) NULL);
52423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  }
52433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
52443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                large_image=SyncNextImageInList(image);
52453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
52463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                large_image->columns=magnified_width;
52473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                large_image->rows=magnified_height;
52483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
52493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                magn_methx=mng_info->magn_methx;
52503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                magn_methy=mng_info->magn_methy;
52513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
52523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if (MAGICKCORE_QUANTUM_DEPTH == 32)
52533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define QM unsigned short
52543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (magn_methx != 1 || magn_methy != 1)
52553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  {
52563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  /*
52573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     Scale pixels to unsigned shorts to prevent
52583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     overflow of intermediate values of interpolations
52593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  */
52603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     for (y=0; y < (long) image->rows; y++)
52613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     {
52623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                       q=GetAuthenticPixels(image,0,y,image->columns,1,
52633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          exception);
52643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                       for (x=(long) image->columns-1; x >= 0; x--)
52653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                       {
52663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          q->red=ScaleQuantumToShort(q->red);
52673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          q->green=ScaleQuantumToShort(q->green);
52683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          q->blue=ScaleQuantumToShort(q->blue);
52693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          q->opacity=ScaleQuantumToShort(q->opacity);
52703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          q++;
52713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                       }
52723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                       if (SyncAuthenticPixels(image,exception) == MagickFalse)
52733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                         break;
52743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     }
52753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  }
52763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#else
52773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define QM Quantum
52783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
52793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
52803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (image->matte != MagickFalse)
52813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   (void) SetImageBackgroundColor(large_image);
52823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                else
52833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  {
52843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    large_image->background_color.opacity=OpaqueOpacity;
52853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    (void) SetImageBackgroundColor(large_image);
52863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    if (magn_methx == 4)
52873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      magn_methx=2;
52883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    if (magn_methx == 5)
52893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      magn_methx=3;
52903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    if (magn_methy == 4)
52913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      magn_methy=2;
52923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    if (magn_methy == 5)
52933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      magn_methy=3;
52943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  }
52953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
52963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                /* magnify the rows into the right side of the large image */
52973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
52983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (logging != MagickFalse)
52993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
53003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    "    Magnify the rows to %lu",large_image->rows);
53013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                m=(long) mng_info->magn_mt;
53023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                yy=0;
53033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                length=(size_t) image->columns;
53043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                next=(PixelPacket *) AcquireQuantumMemory(length,sizeof(*next));
53053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                prev=(PixelPacket *) AcquireQuantumMemory(length,sizeof(*prev));
53063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if ((prev == (PixelPacket *) NULL) ||
53073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    (next == (PixelPacket *) NULL))
53083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  {
53093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     image=DestroyImageList(image);
53103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     MngInfoFreeStruct(mng_info,&have_mng_structure);
53113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     ThrowReaderException(ResourceLimitError,
53123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                       "MemoryAllocationFailed");
53133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  }
53143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                n=GetAuthenticPixels(image,0,0,image->columns,1,exception);
53153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) CopyMagickMemory(next,n,length);
53163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                for (y=0; y < (long) image->rows; y++)
53173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
53183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if (y == 0)
53193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    m=(long) mng_info->magn_mt;
53203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  else if (magn_methy > 1 && y == (long) image->rows-2)
53213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    m=(long) mng_info->magn_mb;
53223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  else if (magn_methy <= 1 && y == (long) image->rows-1)
53233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    m=(long) mng_info->magn_mb;
53243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  else if (magn_methy > 1 && y == (long) image->rows-1)
53253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    m=1;
53263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  else
53273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    m=(long) mng_info->magn_my;
53283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  n=prev;
53293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  prev=next;
53303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  next=n;
53313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if (y < (long) image->rows-1)
53323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    {
53333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      n=GetAuthenticPixels(image,0,y+1,image->columns,1,
53343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          exception);
53353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      (void) CopyMagickMemory(next,n,length);
53363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    }
53373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  for (i=0; i < m; i++, yy++)
53383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  {
53393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    register PixelPacket
53403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      *pixels;
53413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
53423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    assert(yy < (long) large_image->rows);
53433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    pixels=prev;
53443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    n=next;
53453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    q=GetAuthenticPixels(large_image,0,yy,large_image->columns,
53463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          1,exception);
53473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    q+=(large_image->columns-image->columns);
53483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    for (x=(long) image->columns-1; x >= 0; x--)
53493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    {
53503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      /* TO DO: get color as function of indices[x] */
53513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      /*
53523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      if (image->storage_class == PseudoClass)
53533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        {
53543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        }
53553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      */
53563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
53573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      if (magn_methy <= 1)
53583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        {
53593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          *q=(*pixels); /* replicate previous */
53603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        }
53613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      else if (magn_methy == 2 || magn_methy == 4)
53623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        {
53633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          if (i == 0)
53643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                             *q=(*pixels);
53653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          else
53663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                            {
53673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                              /* Interpolate */
53683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                              (*q).red=(QM) (((long) (2*i*((*n).red
53693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                 -(*pixels).red)+m))/((long) (m*2))
53703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                 +(*pixels).red);
53713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                              (*q).green=(QM) (((long) (2*i*((*n).green
53723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                 -(*pixels).green)+m))/((long) (m*2))
53733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                 +(*pixels).green);
53743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                              (*q).blue=(QM) (((long) (2*i*((*n).blue
53753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                 -(*pixels).blue)+m))/((long) (m*2))
53763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                 +(*pixels).blue);
53773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                              if (image->matte != MagickFalse)
53783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                 (*q).opacity=(QM) (((long)
53793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                 (2*i*((*n).opacity
53803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                 -(*pixels).opacity)+m))
53813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                 /((long) (m*2))+(*pixels).opacity);
53823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                            }
53833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          if (magn_methy == 4)
53843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                            {
53853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                              /* Replicate nearest */
53863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                              if (i <= ((m+1) << 1))
53873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                 (*q).opacity=(*pixels).opacity+0;
53883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                              else
53893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                 (*q).opacity=(*n).opacity+0;
53903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                            }
53913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        }
53923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      else /* if (magn_methy == 3 || magn_methy == 5) */
53933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        {
53943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          /* Replicate nearest */
53953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          if (i <= ((m+1) << 1))
53963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                             *q=(*pixels);
53973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          else
53983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                             *q=(*n);
53993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          if (magn_methy == 5)
54003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                            {
54013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                              (*q).opacity=(QM) (((long) (2*i*((*n).opacity
54023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                 -(*pixels).opacity)+m))/((long) (m*2))
54033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                 +(*pixels).opacity);
54043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                            }
54053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        }
54063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      n++;
54073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      q++;
54083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      pixels++;
54093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    } /* x */
54103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    if (SyncAuthenticPixels(large_image,exception) == 0)
54113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      break;
54123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  } /* i */
54133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                } /* y */
54143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                prev=(PixelPacket *) RelinquishMagickMemory(prev);
54153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                next=(PixelPacket *) RelinquishMagickMemory(next);
54163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
54173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                length=image->columns;
54183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
54193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (logging != MagickFalse)
54203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
54213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    "    Delete original image");
54223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
54233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                DeleteImageFromList(&image);
54243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
54253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image=large_image;
54263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
54273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->image=image;
54283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
54293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                /* magnify the columns */
54303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (logging != MagickFalse)
54313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
54323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    "    Magnify the columns to %lu",image->columns);
54333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
54343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                for (y=0; y < (long) image->rows; y++)
54353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
54363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  register PixelPacket
54373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    *pixels;
54383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
54393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
54403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  pixels=q+(image->columns-length);
54413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  n=pixels+1;
54423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  for (x=(long) (image->columns-length);
54433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    x < (long) image->columns; x++)
54443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  {
54453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    if (x == (long) (image->columns-length))
54463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      m=(long) mng_info->magn_ml;
54473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    else if (magn_methx > 1 && x == (long) image->columns-2)
54483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      m=(long) mng_info->magn_mr;
54493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    else if (magn_methx <= 1 && x == (long) image->columns-1)
54503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      m=(long) mng_info->magn_mr;
54513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    else if (magn_methx > 1 && x == (long) image->columns-1)
54523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      m=1;
54533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    else
54543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      m=(long) mng_info->magn_mx;
54553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    for (i=0; i < m; i++)
54563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    {
54573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      if (magn_methx <= 1)
54583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        {
54593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          /* replicate previous */
54603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          *q=(*pixels);
54613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        }
54623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      else if (magn_methx == 2 || magn_methx == 4)
54633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        {
54643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          if (i == 0)
54653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                            *q=(*pixels);
54663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          else
54673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                            {
54683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                              /* Interpolate */
54693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                              (*q).red=(QM) ((2*i*((*n).red
54703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                 -(*pixels).red)+m)
54713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                 /((long) (m*2))+(*pixels).red);
54723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                              (*q).green=(QM) ((2*i*((*n).green
54733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                 -(*pixels).green)
54743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                 +m)/((long) (m*2))+(*pixels).green);
54753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                              (*q).blue=(QM) ((2*i*((*n).blue
54763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                 -(*pixels).blue)+m)
54773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                 /((long) (m*2))+(*pixels).blue);
54783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                              if (image->matte != MagickFalse)
54793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                 (*q).opacity=(QM) ((2*i*((*n).opacity
54803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                   -(*pixels).opacity)+m)/((long) (m*2))
54813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                   +(*pixels).opacity);
54823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                            }
54833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          if (magn_methx == 4)
54843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                            {
54853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                              /* Replicate nearest */
54863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                              if (i <= ((m+1) << 1))
54873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                 (*q).opacity=(*pixels).opacity+0;
54883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                              else
54893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                 (*q).opacity=(*n).opacity+0;
54903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                            }
54913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        }
54923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      else /* if (magn_methx == 3 || magn_methx == 5) */
54933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        {
54943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          /* Replicate nearest */
54953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          if (i <= ((m+1) << 1))
54963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                             *q=(*pixels);
54973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          else
54983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                             *q=(*n);
54993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          if (magn_methx == 5)
55003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                            {
55013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                              /* Interpolate */
55023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                              (*q).opacity=(QM) ((2*i*((*n).opacity
55033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                 -(*pixels).opacity)+m) /((long) (m*2))
55043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                 +(*pixels).opacity);
55053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                            }
55063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        }
55073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      q++;
55083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    }
55093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    n++;
55103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    p++;
55113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  }
55123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if (SyncAuthenticPixels(image,exception) == MagickFalse)
55133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    break;
55143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
55153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if (MAGICKCORE_QUANTUM_DEPTH == 32)
55163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (magn_methx != 1 || magn_methy != 1)
55173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
55183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                /*
55193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   Rescale pixels to Quantum
55203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                */
55213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   for (y=0; y < (long) image->rows; y++)
55223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   {
55233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
55243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     for (x=(long) image->columns-1; x >= 0; x--)
55253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     {
55263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        q->red=ScaleShortToQuantum(q->red);
55273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        q->green=ScaleShortToQuantum(q->green);
55283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        q->blue=ScaleShortToQuantum(q->blue);
55293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        q->opacity=ScaleShortToQuantum(q->opacity);
55303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        q++;
55313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     }
55323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     if (SyncAuthenticPixels(image,exception) == MagickFalse)
55333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                       break;
55343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   }
55353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
55363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
55373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (logging != MagickFalse)
55383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
55393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    "  Finished MAGN processing");
55403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
55413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
55423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
55433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
55443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Crop_box is with respect to the upper left corner of the MNG.
55453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
55463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        crop_box.left=mng_info->image_box.left+mng_info->x_off[object_id];
55473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        crop_box.right=mng_info->image_box.right+mng_info->x_off[object_id];
55483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        crop_box.top=mng_info->image_box.top+mng_info->y_off[object_id];
55493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        crop_box.bottom=mng_info->image_box.bottom+mng_info->y_off[object_id];
55503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        crop_box=mng_minimum_box(crop_box,mng_info->clip);
55513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        crop_box=mng_minimum_box(crop_box,mng_info->frame);
55523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        crop_box=mng_minimum_box(crop_box,mng_info->object_clip[object_id]);
55533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if ((crop_box.left != (mng_info->image_box.left
55543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            +mng_info->x_off[object_id])) ||
55553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (crop_box.right != (mng_info->image_box.right
55563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            +mng_info->x_off[object_id])) ||
55573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (crop_box.top != (mng_info->image_box.top
55583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            +mng_info->y_off[object_id])) ||
55593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (crop_box.bottom != (mng_info->image_box.bottom
55603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            +mng_info->y_off[object_id])))
55613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
55623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (logging != MagickFalse)
55633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
55643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                "  Crop the PNG image");
55653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if ((crop_box.left < crop_box.right) &&
55663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (crop_box.top < crop_box.bottom))
55673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
55683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                Image
55693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  *im;
55703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
55713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                RectangleInfo
55723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  crop_info;
55733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
55743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                /*
55753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  Crop_info is with respect to the upper left corner of
55763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  the image.
55773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                */
55783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                crop_info.x=(crop_box.left-mng_info->x_off[object_id]);
55793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                crop_info.y=(crop_box.top-mng_info->y_off[object_id]);
55803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                crop_info.width=(unsigned long) (crop_box.right-crop_box.left);
55813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                crop_info.height=(unsigned long) (crop_box.bottom-crop_box.top);
55823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->page.width=image->columns;
55833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->page.height=image->rows;
55843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->page.x=0;
55853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->page.y=0;
55863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                im=CropImage(image,&crop_info,exception);
55873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (im != (Image *) NULL)
55883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  {
55893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    image->columns=im->columns;
55903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    image->rows=im->rows;
55913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    im=DestroyImage(im);
55923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    image->page.width=image->columns;
55933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    image->page.height=image->rows;
55943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    image->page.x=crop_box.left;
55953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    image->page.y=crop_box.top;
55963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  }
55973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
55983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
55993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
56003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                /*
56013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  No pixels in crop area.  The MNG spec still requires
56023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  a layer, though, so make a single transparent pixel in
56033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  the top left corner.
56043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                */
56053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->columns=1;
56063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->rows=1;
56073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->colors=2;
56083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) SetImageBackgroundColor(image);
56093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->page.width=1;
56103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->page.height=1;
56113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->page.x=0;
56123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image->page.y=0;
56133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
56143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
56153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#ifndef PNG_READ_EMPTY_PLTE_SUPPORTED
56163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image=mng_info->image;
56173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
56183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
56193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
56203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if (MAGICKCORE_QUANTUM_DEPTH == 16)  /* TO DO: treat Q:32 */
56213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /* Determine if bit depth can be reduced from 16 to 8.
56223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     * Note that the method GetImageDepth doesn't check background
56233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     * and doesn't handle PseudoClass specially.  Also it uses
56243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     * multiplication and division by 257 instead of shifting, so
56253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     * might be slower.
56263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     */
56273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (mng_info->optimize && image->depth == 16)
56283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
56293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        int
56303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          ok_to_reduce;
56313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
56323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        const PixelPacket
56333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          *p;
56343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
56353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ok_to_reduce=(((((unsigned long) image->background_color.red >> 8) &
56363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     0xff)
56373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          == ((unsigned long) image->background_color.red & 0xff)) &&
56383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           ((((unsigned long) image->background_color.green >> 8) & 0xff)
56393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          == ((unsigned long) image->background_color.green & 0xff)) &&
56403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           ((((unsigned long) image->background_color.blue >> 8) & 0xff)
56413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          == ((unsigned long) image->background_color.blue & 0xff)));
56423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (ok_to_reduce && image->storage_class == PseudoClass)
56433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
56443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            int indx;
56453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
56463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            for (indx=0; indx < (long) image->colors; indx++)
56473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
56483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                ok_to_reduce=(((((unsigned long) image->colormap[indx].red >>
56493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    8) & 0xff)
56503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  == ((unsigned long) image->colormap[indx].red & 0xff)) &&
56513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  ((((unsigned long) image->colormap[indx].green >> 8) & 0xff)
56523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  == ((unsigned long) image->colormap[indx].green & 0xff)) &&
56533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  ((((unsigned long) image->colormap[indx].blue >> 8) & 0xff)
56543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  == ((unsigned long) image->colormap[indx].blue & 0xff)));
56553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (ok_to_reduce == MagickFalse)
56563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  break;
56573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
56583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
56593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if ((ok_to_reduce != MagickFalse) &&
56603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (image->storage_class != PseudoClass))
56613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
56623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            long
56633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              y;
56643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
56653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            register long
56663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              x;
56673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
56683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            for (y=0; y < (long) image->rows; y++)
56693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
56703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
56713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (p == (const PixelPacket *) NULL)
56723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
56733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              for (x=(long) image->columns-1; x >= 0; x--)
56743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
56753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                ok_to_reduce=((
56763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  (((unsigned long) p->red >> 8) & 0xff) ==
56773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  ((unsigned long) p->red & 0xff)) &&
56783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  ((((unsigned long) p->green >> 8) & 0xff) ==
56793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  ((unsigned long) p->green & 0xff)) &&
56803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  ((((unsigned long) p->blue >> 8) & 0xff) ==
56813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  ((unsigned long) p->blue & 0xff)) &&
56823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  (((!image->matte ||
56833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  (((unsigned long) p->opacity >> 8) & 0xff) ==
56843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  ((unsigned long) p->opacity & 0xff)))));
56853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (ok_to_reduce == 0)
56863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  break;
56873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                p++;
56883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
56893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (x != 0)
56903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
56913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
56923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
56933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (ok_to_reduce)
56943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
56953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->depth=8;
56963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (logging != MagickFalse)
56973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
56983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                "  Reducing PNG bit depth to 8 without loss of info");
56993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
57003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
57013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
57023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      GetImageException(image,exception);
57033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (image_info->number_scenes != 0)
57043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
57053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (mng_info->scenes_found >
57063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             (long) (image_info->first_scene+image_info->number_scenes))
57073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
57083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
57093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (logging != MagickFalse)
57103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
57113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "  Finished reading image datastream.");
57123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  } while (LocaleCompare(image_info->magick,"MNG") == 0);
57133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloseBlob(image);
57143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
57153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
57163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      "  Finished reading all image datastreams.");
57173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MNG_INSERT_LAYERS)
57183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (insert_layers && !mng_info->image_found && (mng_info->mng_width) &&
57193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       (mng_info->mng_height))
57203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
57213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
57223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Insert a background layer if nothing else was found.
57233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
57243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (logging != MagickFalse)
57253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
57263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "  No images found.  Inserting a background layer.");
57273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (GetAuthenticPixelQueue(image) != (PixelPacket *) NULL)
57283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
57293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /*
57303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            Allocate next image structure.
57313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          */
57323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          AcquireNextImage(image_info,image);
57333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (GetNextImageInList(image) == (Image *) NULL)
57343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
57353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              image=DestroyImageList(image);
57363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              MngInfoFreeStruct(mng_info,&have_mng_structure);
57373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (logging != MagickFalse)
57383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
57393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  "  Allocation failed, returning NULL.");
57403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              return((Image *) NULL);
57413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
57423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image=SyncNextImageInList(image);
57433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
57443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->columns=mng_info->mng_width;
57453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->rows=mng_info->mng_height;
57463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->page.width=mng_info->mng_width;
57473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->page.height=mng_info->mng_height;
57483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->page.x=0;
57493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->page.y=0;
57503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->background_color=mng_background_color;
57513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->matte=MagickFalse;
57523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (image_info->ping == MagickFalse)
57533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) SetImageBackgroundColor(image);
57543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mng_info->image_found++;
57553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
57563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
57573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->iterations=mng_iterations;
57583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (mng_iterations == 1)
57593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image->start_loop=MagickTrue;
57603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  while (GetPreviousImageInList(image) != (Image *) NULL)
57613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
57623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image_count++;
57633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (image_count > 10*mng_info->image_found)
57643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
57653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (logging != MagickFalse)
57663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) LogMagickEvent(CoderEvent,GetMagickModule(),"  No beginning");
57673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) ThrowMagickException(&image->exception,GetMagickModule(),
57683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          CoderError,"Linked list is corrupted, beginning of list not found",
57693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "`%s'",image_info->filename);
57703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        return((Image *) NULL);
57713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
57723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image=GetPreviousImageInList(image);
57733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (GetNextImageInList(image) == (Image *) NULL)
57743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
57753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (logging != MagickFalse)
57763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) LogMagickEvent(CoderEvent,GetMagickModule(),"  Corrupt list");
57773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) ThrowMagickException(&image->exception,GetMagickModule(),
57783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          CoderError,"Linked list is corrupted; next_image is NULL","`%s'",
57793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image_info->filename);
57803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
57813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
57823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (mng_info->ticks_per_second && mng_info->image_found > 1 &&
57833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             GetNextImageInList(image) ==
57843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     (Image *) NULL)
57853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
57863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (logging != MagickFalse)
57873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
57883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            "  First image null");
57893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) ThrowMagickException(&image->exception,GetMagickModule(),
57903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        CoderError,"image->next for first image is NULL but shouldn't be.",
57913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "`%s'",image_info->filename);
57923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
57933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (mng_info->image_found == 0)
57943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
57953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (logging != MagickFalse)
57963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
57973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "  No visible images found.");
57983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) ThrowMagickException(&image->exception,GetMagickModule(),
57993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        CoderError,"No visible images in file","`%s'",image_info->filename);
58003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (image != (Image *) NULL)
58013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image=DestroyImageList(image);
58023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      MngInfoFreeStruct(mng_info,&have_mng_structure);
58033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return((Image *) NULL);
58043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
58053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
58063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (mng_info->ticks_per_second)
58073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    final_delay=1UL*MagickMax(image->ticks_per_second,1L)*
58083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            final_delay/mng_info->ticks_per_second;
58093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
58103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image->start_loop=MagickTrue;
58113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* Find final nonzero image delay */
58123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  final_image_delay=0;
58133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  while (GetNextImageInList(image) != (Image *) NULL)
58143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
58153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (image->delay)
58163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        final_image_delay=image->delay;
58173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image=GetNextImageInList(image);
58183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
58193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (final_delay < final_image_delay)
58203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    final_delay=final_image_delay;
58213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->delay=final_delay;
58223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
58233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
58243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "  image->delay=%lu, final_delay=%lu",image->delay,final_delay);
58253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
58263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
58273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      int
58283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        scene;
58293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
58303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      scene=0;
58313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image=GetFirstImageInList(image);
58323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
58333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "  Before coalesce:");
58343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
58353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "    scene 0 delay=%lu",image->delay);
58363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      while (GetNextImageInList(image) != (Image *) NULL)
58373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
58383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image=GetNextImageInList(image);
58393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
58403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "    scene %d delay=%lu",++scene,image->delay);
58413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
58423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
58433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
58443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image=GetFirstImageInList(image);
58453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#ifdef MNG_COALESCE_LAYERS
58463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (insert_layers)
58473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
58483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Image
58493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *next_image,
58503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *next;
58513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
58523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      unsigned long
58533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        scene;
58543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
58553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (logging != MagickFalse)
58563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(CoderEvent,GetMagickModule(),"  Coalesce Images");
58573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      scene=image->scene;
58583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      next_image=CoalesceImages(image,&image->exception);
58593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (next_image == (Image *) NULL)
58603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
58613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image=DestroyImageList(image);
58623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image=next_image;
58633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (next=image; next != (Image *) NULL; next=next_image)
58643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
58653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         next->page.width=mng_info->mng_width;
58663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         next->page.height=mng_info->mng_height;
58673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         next->page.x=0;
58683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         next->page.y=0;
58693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         next->scene=scene++;
58703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         next_image=GetNextImageInList(next);
58713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         if (next_image == (Image *) NULL)
58723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           break;
58733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         if (next->delay == 0)
58743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           {
58753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             scene--;
58763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             next_image->previous=GetPreviousImageInList(next);
58773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             if (GetPreviousImageInList(next) == (Image *) NULL)
58783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               image=next_image;
58793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             else
58803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               next->previous->next=next_image;
58813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             next=DestroyImage(next);
58823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           }
58833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
58843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
58853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
58863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
58873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  while (GetNextImageInList(image) != (Image *) NULL)
58883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image=GetNextImageInList(image);
58893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->dispose=BackgroundDispose;
58903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
58913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
58923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
58933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      int
58943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        scene;
58953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
58963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      scene=0;
58973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image=GetFirstImageInList(image);
58983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
58993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "  After coalesce:");
59003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
59013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "    scene 0 delay=%lu dispose=%d",image->delay,(int) image->dispose);
59023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      while (GetNextImageInList(image) != (Image *) NULL)
59033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
59043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image=GetNextImageInList(image);
59053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
59063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            "    scene %d delay=%lu dispose=%d",++scene,
59073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->delay,(int) image->dispose);
59083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
59093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
59103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image=GetFirstImageInList(image);
59113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MngInfoFreeStruct(mng_info,&have_mng_structure);
59123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  have_mng_structure=MagickFalse;
59133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
59143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(CoderEvent,GetMagickModule(),"exit ReadMNGImage()");
59153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(GetFirstImageInList(image));
59163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
59173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#else /* PNG_LIBPNG_VER > 95 */
59183ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic Image *ReadPNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
59193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
59203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  printf("Your PNG library is too old: You have libpng-%s\n",
59213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     PNG_LIBPNG_VER_STRING);
59223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ThrowMagickException(exception,GetMagickModule(),CoderError,
59233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    "PNG library is too old","`%s'",image_info->filename);
59243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(Image *) NULL;
59253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
59263ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic Image *ReadMNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
59273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
59283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(ReadPNGImage(image_info,exception));
59293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
59303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif /* PNG_LIBPNG_VER > 95 */
59313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
59323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
59333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
59343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
59353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
59363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
59373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
59383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   R e g i s t e r P N G I m a g e                                           %
59393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
59403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
59413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
59423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
59433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
59443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  RegisterPNGImage() adds properties for the PNG image format to
59453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  the list of supported formats.  The properties include the image format
59463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  tag, a method to read and/or write the format, whether the format
59473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  supports the saving of more than one frame to the same file or blob,
59483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  whether the format supports native in-memory I/O, and a brief
59493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  description of the format.
59503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
59513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the RegisterPNGImage method is:
59523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
59533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      unsigned long RegisterPNGImage(void)
59543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
59553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
59563ed852eea50f9d4cd633efb8c2b054b8e33c253cristyModuleExport unsigned long RegisterPNGImage(void)
59573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
59583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  char
59593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    version[MaxTextExtent];
59603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
59613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickInfo
59623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *entry;
59633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
59643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  static const char
59653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *PNGNote=
59663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
59673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      "See http://www.libpng.org/ for details about the PNG format."
59683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    },
59693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *JNGNote=
59703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
59713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      "See http://www.libpng.org/pub/mng/ for details about the JNG\n"
59723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      "format."
59733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    },
59743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *MNGNote=
59753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
59763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      "See http://www.libpng.org/pub/mng/ for details about the MNG\n"
59773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      "format."
59783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    };
59793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
59803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *version='\0';
59813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_LIBPNG_VER_STRING)
59823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ConcatenateMagickString(version,"libpng ",MaxTextExtent);
59833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ConcatenateMagickString(version,PNG_LIBPNG_VER_STRING,MaxTextExtent);
59843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if (PNG_LIBPNG_VER > 10005)
59853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (LocaleCompare(PNG_LIBPNG_VER_STRING,png_get_header_ver(NULL)) != 0)
59863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
59873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) ConcatenateMagickString(version,",",MaxTextExtent);
59883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) ConcatenateMagickString(version,png_get_libpng_ver(NULL),
59893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            MaxTextExtent);
59903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
59913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
59923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
59933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry=SetMagickInfo("MNG");
59943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->seekable_stream=MagickTrue;  /* To do: eliminate this. */
59953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MAGICKCORE_PNG_DELEGATE)
59963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadMNGImage;
59973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->encoder=(EncodeImageHandler *) WriteMNGImage;
59983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
59993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->magick=(IsImageFormatHandler *) IsMNG;
60003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->description=ConstantString("Multiple-image Network Graphics");
60013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (*version != '\0')
60023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    entry->version=ConstantString(version);
60033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->module=ConstantString("PNG");
60043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->note=ConstantString(MNGNote);
60053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
60063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
60073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry=SetMagickInfo("PNG");
60083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MAGICKCORE_PNG_DELEGATE)
60093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadPNGImage;
60103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->encoder=(EncodeImageHandler *) WritePNGImage;
60113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
60123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->magick=(IsImageFormatHandler *) IsPNG;
60133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->adjoin=MagickFalse;
60143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->description=ConstantString("Portable Network Graphics");
60153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->module=ConstantString("PNG");
60163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (*version != '\0')
60173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    entry->version=ConstantString(version);
60183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->note=ConstantString(PNGNote);
60193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
60203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
60213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry=SetMagickInfo("PNG8");
60223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MAGICKCORE_PNG_DELEGATE)
60233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadPNGImage;
60243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->encoder=(EncodeImageHandler *) WritePNGImage;
60253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
60263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->magick=(IsImageFormatHandler *) IsPNG;
60273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->adjoin=MagickFalse;
60283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->description=ConstantString(
60293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            "8-bit indexed with optional binary transparency");
60303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->module=ConstantString("PNG");
60313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
60323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
60333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry=SetMagickInfo("PNG24");
60343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *version='\0';
60353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(ZLIB_VERSION)
60363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ConcatenateMagickString(version,"zlib ",MaxTextExtent);
60373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ConcatenateMagickString(version,ZLIB_VERSION,MaxTextExtent);
60383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (LocaleCompare(ZLIB_VERSION,zlib_version) != 0)
60393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
60403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) ConcatenateMagickString(version,",",MaxTextExtent);
60413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) ConcatenateMagickString(version,zlib_version,MaxTextExtent);
60423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
60433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
60443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (*version != '\0')
60453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    entry->version=ConstantString(version);
60463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MAGICKCORE_PNG_DELEGATE)
60473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadPNGImage;
60483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->encoder=(EncodeImageHandler *) WritePNGImage;
60493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
60503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->magick=(IsImageFormatHandler *) IsPNG;
60513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->adjoin=MagickFalse;
60523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->description=ConstantString("opaque 24-bit RGB");
60533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->module=ConstantString("PNG");
60543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
60553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
60563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry=SetMagickInfo("PNG32");
60573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MAGICKCORE_PNG_DELEGATE)
60583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadPNGImage;
60593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->encoder=(EncodeImageHandler *) WritePNGImage;
60603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
60613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->magick=(IsImageFormatHandler *) IsPNG;
60623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->adjoin=MagickFalse;
60633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->description=ConstantString("opaque or transparent 32-bit RGBA");
60643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->module=ConstantString("PNG");
60653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
60663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
60673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry=SetMagickInfo("JNG");
60683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(JNG_SUPPORTED)
60693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MAGICKCORE_PNG_DELEGATE)
60703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadJNGImage;
60713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->encoder=(EncodeImageHandler *) WriteJNGImage;
60723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
60733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
60743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->magick=(IsImageFormatHandler *) IsJNG;
60753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->adjoin=MagickFalse;
60763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->description=ConstantString("JPEG Network Graphics");
60773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->module=ConstantString("PNG");
60783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->note=ConstantString(JNGNote);
60793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
608018b17443128598500357da7bff2f01683cf32890cristy#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
608118b17443128598500357da7bff2f01683cf32890cristy  png_semaphore=AllocateSemaphoreInfo();
608218b17443128598500357da7bff2f01683cf32890cristy#endif
60833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickImageCoderSignature);
60843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
60853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
60863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
60873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
60883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
60893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
60903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
60913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   U n r e g i s t e r P N G I m a g e                                       %
60923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
60933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
60943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
60953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
60963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
60973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  UnregisterPNGImage() removes format registrations made by the
60983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  PNG module from the list of supported formats.
60993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
61003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the UnregisterPNGImage method is:
61013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
61023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      UnregisterPNGImage(void)
61033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
61043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
61053ed852eea50f9d4cd633efb8c2b054b8e33c253cristyModuleExport void UnregisterPNGImage(void)
61063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
61073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("MNG");
61083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("PNG");
61093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("PNG8");
61103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("PNG24");
61113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("PNG32");
61123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("JNG");
61133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
6114514e9e77a37d27ed811aca06ea6c300bc06cc1f2cristy  if (png_semaphore != (SemaphoreInfo *) NULL)
6115514e9e77a37d27ed811aca06ea6c300bc06cc1f2cristy    DestroySemaphoreInfo(&png_semaphore);
61163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
61173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
61183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
61193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MAGICKCORE_PNG_DELEGATE)
61203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if PNG_LIBPNG_VER > 95
61213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
61223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
61233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
61243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
61253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
61263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   W r i t e M N G I m a g e                                                 %
61273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
61283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
61293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
61303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
61313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
61323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  WriteMNGImage() writes an image in the Portable Network Graphics
61333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  Group's "Multiple-image Network Graphics" encoded image format.
61343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
61353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  MNG support written by Glenn Randers-Pehrson, glennrp@image...
61363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
61373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the WriteMNGImage method is:
61383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
61393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType WriteMNGImage(const ImageInfo *image_info,Image *image)
61403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
61413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows.
61423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
61433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image_info: the image info.
61443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
61453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image:  The image.
61463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
61473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
61483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  To do (as of version 5.5.2, November 26, 2002 -- glennrp -- see also
61493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    "To do" under ReadPNGImage):
61503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
61513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    Fix problem with palette sorting (when PNG_SORT_PALETTE is enabled,
61523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    some GIF animations don't convert properly)
61533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
61543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    Preserve all unknown and not-yet-handled known chunks found in input
61553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    PNG file and copy them  into output PNG files according to the PNG
61563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    copying rules.
61573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
61583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    Write the iCCP chunk at MNG level when (icc profile length > 0)
61593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
61603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    Improve selection of color type (use indexed-colour or indexed-colour
61613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    with tRNS when 256 or fewer unique RGBA values are present).
61623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
61633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    Figure out what to do with "dispose=<restore-to-previous>" (dispose == 3)
61643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    This will be complicated if we limit ourselves to generating MNG-LC
61653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    files.  For now we ignore disposal method 3 and simply overlay the next
61663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    image on it.
61673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
61683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    Check for identical PLTE's or PLTE/tRNS combinations and use a
61693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    global MNG PLTE or PLTE/tRNS combination when appropriate.
61703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    [mostly done 15 June 1999 but still need to take care of tRNS]
61713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
61723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    Check for identical sRGB and replace with a global sRGB (and remove
61733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    gAMA/cHRM if sRGB is found; check for identical gAMA/cHRM and
61743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    replace with global gAMA/cHRM (or with sRGB if appropriate; replace
61753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    local gAMA/cHRM with local sRGB if appropriate).
61763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
61773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    Check for identical sBIT chunks and write global ones.
61783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
61793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    Provide option to skip writing the signature tEXt chunks.
61803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
61813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    Use signatures to detect identical objects and reuse the first
61823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    instance of such objects instead of writing duplicate objects.
61833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
61843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    Use a smaller-than-32k value of compression window size when
61853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    appropriate.
61863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
61873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    Encode JNG datastreams.  Mostly done as of 5.5.2; need to write
61883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    ancillary text chunks and save profiles.
61893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
61903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    Provide an option to force LC files (to ensure exact framing rate)
61913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    instead of VLC.
61923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
61933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    Provide an option to force VLC files instead of LC, even when offsets
61943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    are present.  This will involve expanding the embedded images with a
61953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    transparent region at the top and/or left.
61963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
61973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
61983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if (PNG_LIBPNG_VER > 99 && PNG_LIBPNG_VER < 10007)
61993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* This function became available in libpng version 1.0.6g. */
62003ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic void
62013ed852eea50f9d4cd633efb8c2b054b8e33c253cristypng_set_compression_buffer_size(png_structp png_ptr, png_uint_32 size)
62023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
62033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (png_ptr->zbuf)
62043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       png_free(png_ptr, png_ptr->zbuf); png_ptr->zbuf=NULL;
62053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    png_ptr->zbuf_size=(png_size_t) size;
62063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    png_ptr->zbuf=(png_bytep) png_malloc(png_ptr, size);
62073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (png_ptr->zbuf == 0)
62083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       png_error(png_ptr,"Unable to allocate zbuf");
62093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
62103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
62113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
62123ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic void
62133ed852eea50f9d4cd633efb8c2b054b8e33c253cristypng_write_raw_profile(const ImageInfo *image_info,png_struct *ping,
62143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   png_info *ping_info, unsigned char *profile_type, unsigned char
62153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   *profile_description, unsigned char *profile_data, png_uint_32 length)
62163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
62173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if (PNG_LIBPNG_VER > 10005)
62183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   png_textp
62193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     text;
62203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
62213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   register long
62223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     i;
62233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
62243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   unsigned char
62253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     *sp;
62263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
62273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   png_charp
62283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     dp;
62293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
62303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   png_uint_32
62313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     allocated_length,
62323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     description_length;
62333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
62343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   unsigned char
62353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     hex[16]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
62363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
62373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
62383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if (PNG_LIBPNG_VER <= 10005)
62393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   if (image_info->verbose)
62403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     (void) printf("Not ");
62413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   image_info=image_info;
62423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   ping=ping;
62433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   ping_info=ping_info;
62443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   profile_type=profile_type;
62453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   profile_description=profile_description;
62463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   profile_data=profile_data;
62473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   length=length;
62483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
62493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   if (LocaleNCompare((char *) profile_type+1, "ng-chunk-",9) == 0)
62503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return;
62513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
62523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   if (image_info->verbose)
62533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     {
62543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     (void) printf("writing raw profile: type=%s, length=%lu\n",
62553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       (char *) profile_type, length);
62563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     }
62573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if (PNG_LIBPNG_VER > 10005)
62583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   text=(png_textp) png_malloc(ping,(png_uint_32) sizeof(png_text));
62593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   description_length=(png_uint_32) strlen((const char *) profile_description);
62603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   allocated_length=(png_uint_32) (length*2 + (length >> 5) + 20
62613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      + description_length);
62623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   text[0].text=(png_charp) png_malloc(ping,allocated_length);
62633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   text[0].key=(png_charp) png_malloc(ping, (png_uint_32) 80);
62643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   text[0].key[0]='\0';
62653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   (void) ConcatenateMagickString(text[0].key,
62663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      "Raw profile type ",MaxTextExtent);
62673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   (void) ConcatenateMagickString(text[0].key,(const char *) profile_type,62);
62683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   sp=profile_data;
62693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   dp=text[0].text;
62703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   *dp++='\n';
62713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   (void) CopyMagickString(dp,(const char *) profile_description,
62723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     allocated_length);
62733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   dp+=description_length;
62743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   *dp++='\n';
62753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   (void) FormatMagickString(dp,allocated_length-
62763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     (png_size_t) (dp-text[0].text),"%8lu ",length);
62773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   dp+=8;
62783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   for (i=0; i < (long) length; i++)
62793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   {
62803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     if (i%36 == 0)
62813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       *dp++='\n';
62823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     *(dp++)=(char) hex[((*sp >> 4) & 0x0f)];
62833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     *(dp++)=(char) hex[((*sp++ ) & 0x0f)];
62843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   }
62853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   *dp++='\n';
62863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   *dp='\0';
62873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   text[0].text_length=(png_size_t) (dp-text[0].text);
62883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   text[0].compression=image_info->compression == NoCompression ||
62893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     (image_info->compression == UndefinedCompression &&
62903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     text[0].text_length < 128) ? -1 : 0;
62913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   if (text[0].text_length <= allocated_length)
62923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     png_set_text(ping,ping_info,text,1);
62933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   png_free(ping,text[0].text);
62943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   png_free(ping,text[0].key);
62953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   png_free(ping,text);
62963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
62973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
62983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
62993ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType png_write_chunk_from_profile(Image *image,
63003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   const char *string, int logging)
63013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
63023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  char
63033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *name;
63043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
63053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const StringInfo
63063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *profile;
63073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
63083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned char
63093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *data;
63103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
63113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_uint_32 length;
63123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
63133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ResetImageProfileIterator(image);
63143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (name=GetNextImageProfile(image); name != (const char *) NULL; ){
63153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    profile=GetImageProfile(image,name);
63163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (profile != (const StringInfo *) NULL)
63173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
63183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        StringInfo
63193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          *png_profile;
63203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
63213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (LocaleNCompare(name,string,11) == 0) {
63223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (logging != MagickFalse)
63233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
63243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             "  Found %s profile",name);
63253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
63263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       png_profile=CloneStringInfo(profile);
63273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       data=GetStringInfoDatum(png_profile),
63283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       length=(png_uint_32) GetStringInfoLength(png_profile);
63293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       data[4]=data[3];
63303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       data[3]=data[2];
63313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       data[2]=data[1];
63323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       data[1]=data[0];
63333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       (void) WriteBlobMSBULong(image,length-5);  /* data length */
63343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       (void) WriteBlob(image,length-1,data+1);
63353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       (void) WriteBlobMSBULong(image,crc32(0,data+1,(uInt) length-1));
63363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       png_profile=DestroyStringInfo(png_profile);
63373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
63383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
63393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      name=GetNextImageProfile(image);
63403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   }
63413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   return(MagickTrue);
63423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
63433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
63443ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
63453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   const ImageInfo *image_info,Image *image)
63463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
63473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* Write one PNG image */
63483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  char
63493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    s[2];
63503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
63513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const char
63523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *name,
63533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *property,
63543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *value;
63553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
63563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const StringInfo
63573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *profile;
63583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
63593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
63603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  int
63613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image_matte,
63623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    num_passes,
6363cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp    pass;
6364cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp
6365cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp  png_bytep
6366cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp     ping_trans_alpha;
63673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
63683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_colorp
63693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     palette;
63703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6371cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp  png_color_16
6372cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp    ping_background,
6373cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp    ping_trans_color;
6374cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp
63753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_info
63763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *ping_info;
63773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
63783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_struct
63793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *ping;
63803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6381c11cf6a442f3046940608a5743a68cc891deb13eglennrp  png_uint_32
6382c11cf6a442f3046940608a5743a68cc891deb13eglennrp    ping_info_height,
6383c11cf6a442f3046940608a5743a68cc891deb13eglennrp    ping_info_width;
6384c11cf6a442f3046940608a5743a68cc891deb13eglennrp
63853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  long
63863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    y;
63873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
63883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
63893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
63903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
63913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  QuantumInfo
63923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *quantum_info;
63933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
63943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register IndexPacket
63953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *indices;
63963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
63973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register long
63983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i,
63993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x;
64003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
64013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned char
64023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *png_pixels;
64033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
64043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned int
64053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    logging,
64063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    matte;
64073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6408cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp  volatile int
6409cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp    ping_info_bit_depth,
6410cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp    ping_info_color_type,
6411cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp    ping_info_interlace_method,
6412cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp    ping_info_compression_method,
6413cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp    ping_info_filter_method,
6414cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp    ping_info_num_trans;
6415cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp
64163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  volatile unsigned long
64173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image_colors,
6418cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp    image_depth,
6419cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp    old_bit_depth;
64203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
64213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned long
64223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    quality,
64233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    rowbytes,
64243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    save_image_depth;
64253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
64263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  logging=LogMagickEvent(CoderEvent,GetMagickModule(),
64273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    "  enter WriteOnePNGImage()");
64283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
64293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
6430f84a193d5f435588cd78d521fff3f1f852e227f8cristy  LockSemaphoreInfo(png_semaphore);
64313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
64323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6433cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp  /* Initialize some stuff */
6434cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp  ping_info_bit_depth=0,
6435cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp  ping_info_color_type=0,
6436cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp  ping_info_interlace_method=0,
6437cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp  ping_info_compression_method=0,
6438cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp  ping_info_filter_method=0,
6439cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp  ping_info_num_trans = 0;
6440cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp
6441cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp  ping_background.red = 0;
6442cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp  ping_background.green = 0;
6443cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp  ping_background.blue = 0;
6444cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp  ping_background.gray = 0;
6445cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp  ping_background.index = 0;
6446cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp
6447cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp  ping_trans_color.red=0;
6448cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp  ping_trans_color.green=0;
6449cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp  ping_trans_color.blue=0;
6450cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp  ping_trans_color.gray=0;
6451cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp
6452cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp  ping_trans_alpha = NULL;
6453cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp
6454ed5525230af20461366cdc5b8bbe0f7f9b166c44cristy  quantum_info = (QuantumInfo *) NULL;
64553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image_colors=image->colors;
64563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image_depth=image->depth;
64573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image_matte=image->matte;
64583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
64593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->colorspace != RGBColorspace)
64603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) TransformImageColorspace(image,RGBColorspace);
64613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mng_info->IsPalette=image->storage_class == PseudoClass &&
6462057310ded72df25c84f1ad647129a95c1f1753e3cristy            image_colors <= 256 && !IsOpaqueImage(image,&image->exception);
64633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mng_info->optimize=image_info->type == OptimizeType;
64643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
64653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
64663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Allocate the PNG structures
64673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
64683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#ifdef PNG_USER_MEM_SUPPORTED
64693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ping=png_create_write_struct_2(PNG_LIBPNG_VER_STRING,image,
64703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    PNGErrorHandler,PNGWarningHandler,(void *) NULL,
64713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (png_malloc_ptr) png_IM_malloc,(png_free_ptr) png_IM_free);
64723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#else
64733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ping=png_create_write_struct(PNG_LIBPNG_VER_STRING,image,
64743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    PNGErrorHandler,PNGWarningHandler);
64753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
64763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (ping == (png_struct *) NULL)
64773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
64783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ping_info=png_create_info_struct(ping);
64793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (ping_info == (png_info *) NULL)
64803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
64813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      png_destroy_write_struct(&ping,(png_info **) NULL);
64823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
64833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
64843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_set_write_fn(ping,image,png_put_data,png_flush_data);
64853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_pixels=(unsigned char *) NULL;
64863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
64873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (setjmp(ping->jmpbuf))
64883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
64893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
64903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        PNG write failed.
64913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
64923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#ifdef PNG_DEBUG
64933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     if (image_info->verbose)
64943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) printf("PNG write has failed.\n");
64953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
64963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      png_destroy_write_struct(&ping,&ping_info);
64973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
6498f84a193d5f435588cd78d521fff3f1f852e227f8cristy      UnlockSemaphoreInfo(png_semaphore);
64993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
65003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return(MagickFalse);
65013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
65023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
65033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Prepare PNG for writing.
65043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
65053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_MNG_FEATURES_SUPPORTED)
65063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (mng_info->write_mng)
65073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     (void) png_permit_mng_features(ping,PNG_ALL_MNG_FEATURES);
65083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#else
65093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy# ifdef PNG_WRITE_EMPTY_PLTE_SUPPORTED
65103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (mng_info->write_mng)
65113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     png_permit_empty_plte(ping,MagickTrue);
65123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy# endif
65133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
65143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  x=0;
6515c11cf6a442f3046940608a5743a68cc891deb13eglennrp  ping_info_width=image->columns;
6516c11cf6a442f3046940608a5743a68cc891deb13eglennrp  ping_info_height=image->rows;
65173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (mng_info->write_png8 || mng_info->write_png24 || mng_info->write_png32)
65183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     image_depth=8;
65193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (mng_info->write_png_depth != 0)
65203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     image_depth=mng_info->write_png_depth;
65213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* Adjust requested depth to next higher valid depth if necessary */
65223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_depth > 8)
65233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     image_depth=16;
65243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((image_depth > 4) && (image_depth < 8))
65253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     image_depth=8;
65263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_depth == 3)
65273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     image_depth=4;
65283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
65293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
65303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6531c11cf6a442f3046940608a5743a68cc891deb13eglennrp        "    width=%lu",ping_info_width);
65323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6533c11cf6a442f3046940608a5743a68cc891deb13eglennrp        "    height=%lu",ping_info_height);
65343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
65353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "    image_matte=%u",image->matte);
65363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
65373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "    image_depth=%lu",image->depth);
65383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
65393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "    requested PNG image_depth=%lu",image->depth);
65403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
65413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  save_image_depth=image_depth;
6542c11cf6a442f3046940608a5743a68cc891deb13eglennrp  ping_info_bit_depth=(png_byte) save_image_depth;
65433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_pHYs_SUPPORTED)
65443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((image->x_resolution != 0) && (image->y_resolution != 0) &&
65453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (!mng_info->write_mng || !mng_info->equal_physs))
65463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
65473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      int
65483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        unit_type;
65493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
65503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      png_uint_32
65513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        x_resolution,
65523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        y_resolution;
65533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
65543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (image->units == PixelsPerInchResolution)
65553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
65563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          unit_type=PNG_RESOLUTION_METER;
65573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          x_resolution=(png_uint_32) (100.0*image->x_resolution/2.54);
65583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          y_resolution=(png_uint_32) (100.0*image->y_resolution/2.54);
65593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
65603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else if (image->units == PixelsPerCentimeterResolution)
65613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
65623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          unit_type=PNG_RESOLUTION_METER;
65633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          x_resolution=(png_uint_32) (100.0*image->x_resolution);
65643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          y_resolution=(png_uint_32) (100.0*image->y_resolution);
65653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
65663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else
65673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
65683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          unit_type=PNG_RESOLUTION_UNKNOWN;
65693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          x_resolution=(png_uint_32) image->x_resolution;
65703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          y_resolution=(png_uint_32) image->y_resolution;
65713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
65723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       png_set_pHYs(ping,ping_info,x_resolution,y_resolution,unit_type);
65733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       if (logging != MagickFalse)
65743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
65753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           "    Setting up pHYs chunk");
65763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
65773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
65783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_oFFs_SUPPORTED)
65793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->page.x || image->page.y)
65803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
65813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       png_set_oFFs(ping,ping_info,(png_int_32) image->page.x,
65823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (png_int_32) image->page.y, 0);
65833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       if (logging != MagickFalse)
65843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
65853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           "    Setting up oFFs chunk");
65863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
65873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
65883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_matte && (!mng_info->adjoin || !mng_info->equal_backgrounds))
65893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
65903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      png_color_16
65913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        background;
65923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
65933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (image_depth < MAGICKCORE_QUANTUM_DEPTH)
65943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
65953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          unsigned long
65963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             maxval;
65973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
65983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          maxval=(1UL << image_depth)-1;
65993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          background.red=(png_uint_16)
66003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (QuantumScale*(maxval*image->background_color.red));
66013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          background.green=(png_uint_16)
66023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (QuantumScale*(maxval*image->background_color.green));
66033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          background.blue=(png_uint_16)
66043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (QuantumScale*(maxval*image->background_color.blue));
66053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          background.gray=(png_uint_16)
66063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (QuantumScale*(maxval*PixelIntensity(&image->background_color)));
66073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
66083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else
66093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
66103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          background.red=image->background_color.red;
66113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          background.green=image->background_color.green;
66123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          background.blue=image->background_color.blue;
66133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          background.gray=
66143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (png_uint_16) PixelIntensity(&image->background_color);
66153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
66163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      background.index=(png_byte) background.gray;
66173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (logging != MagickFalse)
66183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
66193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "    Setting up bKGd chunk");
66203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      png_set_bKGD(ping,ping_info,&background);
66213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
66223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
66233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Select the color type.
66243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
66253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  matte=image_matte;
66263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  old_bit_depth=0;
66273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (mng_info->write_png8)
66283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
6629c11cf6a442f3046940608a5743a68cc891deb13eglennrp      ping_info_color_type=(png_byte) PNG_COLOR_TYPE_PALETTE;
6630c11cf6a442f3046940608a5743a68cc891deb13eglennrp      ping_info_bit_depth=8;
6631c11cf6a442f3046940608a5743a68cc891deb13eglennrp      image_depth=ping_info_bit_depth;
66323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
66333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /* TO DO: make this a function cause it's used twice, except
66343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             for reducing the sample depth from 8. */
66353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
66363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          QuantizeInfo
66373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            quantize_info;
66383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
66393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          unsigned long
66403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             number_colors,
66413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             save_number_colors;
66423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
66433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          number_colors=image_colors;
66443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if ((image->storage_class == DirectClass) || (number_colors > 256))
66453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
66463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              GetQuantizeInfo(&quantize_info);
66473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              quantize_info.dither=IsPaletteImage(image,&image->exception) ==
66483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                MagickFalse ? MagickTrue : MagickFalse;
66493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              quantize_info.number_colors= (matte != MagickFalse ? 255UL :
66503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                256UL);
66513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) QuantizeImage(&quantize_info,image);
66523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              number_colors=image_colors;
66533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) SyncImage(image);
66543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (logging != MagickFalse)
66553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
66563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  "    Colors quantized to %ld",number_colors);
66573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
66583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (matte)
66593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            ping_info->valid|=PNG_INFO_tRNS;
66603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /*
66613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            Set image palette.
66623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          */
6663c11cf6a442f3046940608a5743a68cc891deb13eglennrp          ping_info_color_type=(png_byte) PNG_COLOR_TYPE_PALETTE;
66643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          ping_info->valid|=PNG_INFO_PLTE;
66653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_SORT_PALETTE)
66663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          save_number_colors=image_colors;
66673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (CompressColormapTransFirst(image) == MagickFalse)
66683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
666998156a3a465a004545e39434c63052b955a74d1cglennrp          number_colors=image->colors;
66703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image_colors=save_number_colors;
66713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
66723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          palette=(png_color *) AcquireQuantumMemory(257,
66733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            sizeof(*palette));
66743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (palette == (png_color *) NULL)
66753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
66763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (logging != MagickFalse)
66773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
667898156a3a465a004545e39434c63052b955a74d1cglennrp                "  Setting up PLTE chunk with %d colors",
667998156a3a465a004545e39434c63052b955a74d1cglennrp                (int) number_colors);
66803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          for (i=0; i < (long) number_colors; i++)
66813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
66823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            palette[i].red=ScaleQuantumToChar(image->colormap[i].red);
66833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            palette[i].green=ScaleQuantumToChar(image->colormap[i].green);
66843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            palette[i].blue=ScaleQuantumToChar(image->colormap[i].blue);
66853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (logging != MagickFalse)
66863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
66873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if MAGICKCORE_QUANTUM_DEPTH == 8
66883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                "    %3ld (%3d,%3d,%3d)",
66893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#else
66903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                "    %5ld (%5d,%5d,%5d)",
66913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
66923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                i,palette[i].red,palette[i].green,palette[i].blue);
66933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
66943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
66953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (matte)
66963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
66973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              number_colors++;
66983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              palette[i].red=ScaleQuantumToChar((Quantum) QuantumRange);
66993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              palette[i].green=ScaleQuantumToChar((Quantum) QuantumRange);
67003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              palette[i].blue=ScaleQuantumToChar((Quantum) QuantumRange);
67013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
67023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          png_set_PLTE(ping,ping_info,palette,(int) number_colors);
67033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if (PNG_LIBPNG_VER > 10008)
67043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          palette=(png_colorp) RelinquishMagickMemory(palette);
67053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
6706c11cf6a442f3046940608a5743a68cc891deb13eglennrp            image_depth=ping_info_bit_depth;
6707cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp            ping_info_num_trans=0;
67083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (matte)
67093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
67103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              ExceptionInfo
67113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                *exception;
67123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
67133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              /*
67143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                Identify which colormap entry is transparent.
67153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              */
67163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              ping_info->trans_alpha=(unsigned char *) AcquireQuantumMemory(
67173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                number_colors,sizeof(*ping_info->trans_alpha));
6718a58299c3f51696bac0bef0ca0ff131054b78f46fglennrp              if (ping_info->trans_alpha == (unsigned char *) NULL)
67193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                ThrowWriterException(ResourceLimitError,
67203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  "MemoryAllocationFailed");
67213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              assert(number_colors <= 256);
67223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              for (i=0; i < (long) number_colors; i++)
67233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                 ping_info->trans_alpha[i]=255;
67243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              exception=(&image->exception);
67253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              for (y=0; y < (long) image->rows; y++)
67263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
67273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                register const PixelPacket
67283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  *p;
67293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
67303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                p=GetAuthenticPixels(image,0,y,image->columns,1,exception);
67313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (p == (PixelPacket *) NULL)
67323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  break;
67333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                indices=GetAuthenticIndexQueue(image);
67343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                for (x=0; x < (long) image->columns; x++)
67353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
67363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if (p->opacity != OpaqueOpacity)
67373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    {
67383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      indices[x]=(IndexPacket) (number_colors-1);
67393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      ping_info->trans_alpha[(long) indices[x]]=(png_byte) (255-
6740ce70c17bb6433add2eb069515a4f3105989e0662cristy                        ScaleQuantumToChar(GetOpacityPixelComponent(p)));
67413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    }
67423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  p++;
67433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
67443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (SyncAuthenticPixels(image,exception) == MagickFalse)
67453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  break;
67463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
67473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              for (i=0; i < (long) number_colors; i++)
67483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (ping_info->trans_alpha[i] != 255)
6749cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp                  ping_info_num_trans=(unsigned short) (i+1);
6750cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp              if (ping_info_num_trans == 0)
67513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                ping_info->valid&=(~PNG_INFO_tRNS);
67523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (!(ping_info->valid & PNG_INFO_tRNS))
6753cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp                ping_info_num_trans=0;
6754cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp              if (ping_info_num_trans == 0)
67553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                ping_info->trans_alpha=(unsigned char *)
67563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  RelinquishMagickMemory(ping_info->trans_alpha);
67573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
67583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /*
67593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            Identify which colormap entry is the background color.
67603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          */
67613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          for (i=0; i < (long) MagickMax(1L*number_colors-1L,1L); i++)
6762cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp            if (IsPNGColorEqual(ping_background,image->colormap[i]))
67633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              break;
6764cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp          ping_background.index=(png_byte) i;
67653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
67663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (image_matte != MagickFalse)
67673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
67683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /* TO DO: reduce to binary transparency */
67693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
67703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    } /* end of write_png8 */
67713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else if (mng_info->write_png24)
67723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
67733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image_matte=MagickFalse;
6774c11cf6a442f3046940608a5743a68cc891deb13eglennrp      ping_info_color_type=(png_byte) PNG_COLOR_TYPE_RGB;
67753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
67763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else if (mng_info->write_png32)
67773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
67783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image_matte=MagickTrue;
6779c11cf6a442f3046940608a5743a68cc891deb13eglennrp      ping_info_color_type=(png_byte) PNG_COLOR_TYPE_RGB_ALPHA;
67803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
67813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
67823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
6783c11cf6a442f3046940608a5743a68cc891deb13eglennrp      image_depth=ping_info_bit_depth;
67843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (mng_info->write_png_colortype)
67853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
6786c11cf6a442f3046940608a5743a68cc891deb13eglennrp          ping_info_color_type=(png_byte) mng_info->write_png_colortype-1;
6787c11cf6a442f3046940608a5743a68cc891deb13eglennrp          if (ping_info_color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
6788c11cf6a442f3046940608a5743a68cc891deb13eglennrp              ping_info_color_type == PNG_COLOR_TYPE_RGB_ALPHA)
67893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image_matte=MagickTrue;
67903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
67913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else
67923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
67933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (logging != MagickFalse)
67943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
67953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             "Selecting PNG colortype");
6796c11cf6a442f3046940608a5743a68cc891deb13eglennrp          ping_info_color_type=(png_byte) ((matte == MagickTrue)?
67973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          PNG_COLOR_TYPE_RGB_ALPHA:PNG_COLOR_TYPE_RGB);
67983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if(image_info->type == TrueColorType)
67993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
6800c11cf6a442f3046940608a5743a68cc891deb13eglennrp              ping_info_color_type=(png_byte) PNG_COLOR_TYPE_RGB;
68013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              image_matte=MagickFalse;
68023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
68033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if(image_info->type == TrueColorMatteType)
68043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
6805c11cf6a442f3046940608a5743a68cc891deb13eglennrp              ping_info_color_type=(png_byte) PNG_COLOR_TYPE_RGB_ALPHA;
68063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              image_matte=MagickTrue;
68073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
68083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if ((image_info->type == UndefinedType ||
68093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             image_info->type == OptimizeType ||
68103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             image_info->type == GrayscaleType) &&
68113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             image_matte == MagickFalse && ImageIsGray(image))
68123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
6813c11cf6a442f3046940608a5743a68cc891deb13eglennrp              ping_info_color_type=(png_byte) PNG_COLOR_TYPE_GRAY;
68143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              image_matte=MagickFalse;
68153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
68163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if ((image_info->type == UndefinedType ||
68173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             image_info->type == OptimizeType ||
68183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              image_info->type == GrayscaleMatteType) &&
68193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              image_matte == MagickTrue && ImageIsGray(image))
68203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
6821c11cf6a442f3046940608a5743a68cc891deb13eglennrp              ping_info_color_type=(png_byte) PNG_COLOR_TYPE_GRAY_ALPHA;
68223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              image_matte=MagickTrue;
68233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
68243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
68253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (logging != MagickFalse)
68263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6827c11cf6a442f3046940608a5743a68cc891deb13eglennrp         "Selected PNG colortype=%d",ping_info_color_type);
68283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6829c11cf6a442f3046940608a5743a68cc891deb13eglennrp      if (ping_info_bit_depth < 8)
68303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       {
6831c11cf6a442f3046940608a5743a68cc891deb13eglennrp         if (ping_info_color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
6832c11cf6a442f3046940608a5743a68cc891deb13eglennrp             ping_info_color_type == PNG_COLOR_TYPE_RGB ||
6833c11cf6a442f3046940608a5743a68cc891deb13eglennrp             ping_info_color_type == PNG_COLOR_TYPE_RGB_ALPHA)
6834c11cf6a442f3046940608a5743a68cc891deb13eglennrp           ping_info_bit_depth=8;
68353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       }
68363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6837c11cf6a442f3046940608a5743a68cc891deb13eglennrp      if (ping_info_color_type == PNG_COLOR_TYPE_GRAY)
68383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
68393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (image->matte == MagickFalse && image->colors < 256)
68403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
68413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (ImageIsMonochrome(image))
68423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
6843c11cf6a442f3046940608a5743a68cc891deb13eglennrp                  ping_info_bit_depth=1;
6844c11cf6a442f3046940608a5743a68cc891deb13eglennrp                  if (ping_info_bit_depth < (int)mng_info->write_png_depth)
6845c11cf6a442f3046940608a5743a68cc891deb13eglennrp                    ping_info_bit_depth = mng_info->write_png_depth;
68463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
68473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
68483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
6849c11cf6a442f3046940608a5743a68cc891deb13eglennrp      if (ping_info_color_type == PNG_COLOR_TYPE_PALETTE)
68503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
6851c11cf6a442f3046940608a5743a68cc891deb13eglennrp           ping_info_bit_depth=1;
6852c11cf6a442f3046940608a5743a68cc891deb13eglennrp           while ((int) (1 << ping_info_bit_depth) < (long) image_colors)
6853c11cf6a442f3046940608a5743a68cc891deb13eglennrp             ping_info_bit_depth <<= 1;
68543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
68553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           if (logging != MagickFalse)
68563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             {
68573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
68583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                "    Number of colors: %lu",image_colors);
68593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6860c11cf6a442f3046940608a5743a68cc891deb13eglennrp                "    Tentative PNG bit depth: %d",ping_info_bit_depth);
68613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             }
68623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           if (mng_info->write_png_depth)
68633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             {
6864c11cf6a442f3046940608a5743a68cc891deb13eglennrp               old_bit_depth=ping_info_bit_depth;
6865c11cf6a442f3046940608a5743a68cc891deb13eglennrp               if (ping_info_bit_depth < (int)mng_info->write_png_depth)
68663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                 {
6867c11cf6a442f3046940608a5743a68cc891deb13eglennrp                   ping_info_bit_depth = mng_info->write_png_depth;
6868c11cf6a442f3046940608a5743a68cc891deb13eglennrp                   if (ping_info_bit_depth > 8)
6869c11cf6a442f3046940608a5743a68cc891deb13eglennrp                      ping_info_bit_depth = 8;
6870c11cf6a442f3046940608a5743a68cc891deb13eglennrp                   if (ping_info_bit_depth != (int) old_bit_depth)
68713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     {
68723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                       if (logging != MagickFalse)
68733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
68743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                           "    Colors increased to %ld",image_colors);
68753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     }
68763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                 }
68773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             }
68783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
68793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
6880c11cf6a442f3046940608a5743a68cc891deb13eglennrp  image_depth=ping_info_bit_depth;
68813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
68823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
68833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6884c11cf6a442f3046940608a5743a68cc891deb13eglennrp        "    Tentative PNG color type: %d",ping_info_color_type);
68853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
68863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "    image_info->type: %d",image_info->type);
68873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
68883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "    image_depth: %lu",image_depth);
68893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6890c11cf6a442f3046940608a5743a68cc891deb13eglennrp        "    ping_info_bit_depth: %d",ping_info_bit_depth);
68913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
68923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
68933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (matte && (mng_info->optimize || mng_info->IsPalette))
68943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
68953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      register const PixelPacket
68963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *p;
68973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
68983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      p=GetVirtualPixels(image,0,0,image->columns,1,&image->exception);
6899c11cf6a442f3046940608a5743a68cc891deb13eglennrp      ping_info_color_type=PNG_COLOR_TYPE_GRAY_ALPHA;
69003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (y=0; y < (long) image->rows; y++)
69013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
69023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
69033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (p == (const PixelPacket *) NULL)
69043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
69053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        for (x=(long) image->columns-1; x >= 0; x--)
69063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
69073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (IsGray(p) == MagickFalse)
69083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
6909c11cf6a442f3046940608a5743a68cc891deb13eglennrp              ping_info_color_type=(png_byte) PNG_COLOR_TYPE_RGB_ALPHA;
69103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              break;
69113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
69123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          p++;
69133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
69143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
69153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
69163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Determine if there is any transparent color.
69173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
69183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (y=0; y < (long) image->rows; y++)
69193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
69203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
69213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (p == (const PixelPacket *) NULL)
69223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
69233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        for (x=(long) image->columns-1; x >= 0; x--)
69243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
69253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (p->opacity != OpaqueOpacity)
69263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
69273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          p++;
69283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
69293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (x != 0)
69303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
69313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
69323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if ((y == (long) image->rows) && (x == (long) image->columns))
69333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
69343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /*
69353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            No transparent pixels are present.  Change 4 or 6 to 0 or 2,
69363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            and do not set the PNG_INFO_tRNS flag in ping_info->valid.
69373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          */
69383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image_matte=MagickFalse;
6939c11cf6a442f3046940608a5743a68cc891deb13eglennrp          ping_info_color_type&=0x03;
69403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
69413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else
69423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
69433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          unsigned int
69443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mask;
69453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
69463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          mask=0xffff;
6947c11cf6a442f3046940608a5743a68cc891deb13eglennrp          if (ping_info_bit_depth == 8)
69483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             mask=0x00ff;
6949c11cf6a442f3046940608a5743a68cc891deb13eglennrp          if (ping_info_bit_depth == 4)
69503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             mask=0x000f;
6951c11cf6a442f3046940608a5743a68cc891deb13eglennrp          if (ping_info_bit_depth == 2)
69523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             mask=0x0003;
6953c11cf6a442f3046940608a5743a68cc891deb13eglennrp          if (ping_info_bit_depth == 1)
69543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             mask=0x0001;
69553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          ping_info->valid|=PNG_INFO_tRNS;
69563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          ping_info->trans_color.red=(png_uint_16)
6957ce70c17bb6433add2eb069515a4f3105989e0662cristy            (ScaleQuantumToShort(GetRedPixelComponent(p)) & mask);
69583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          ping_info->trans_color.green=(png_uint_16)
6959ce70c17bb6433add2eb069515a4f3105989e0662cristy            (ScaleQuantumToShort(GetGreenPixelComponent(p)) & mask);
69603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          ping_info->trans_color.blue=(png_uint_16)
6961ce70c17bb6433add2eb069515a4f3105989e0662cristy            (ScaleQuantumToShort(GetBluePixelComponent(p)) & mask);
69623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          ping_info->trans_color.gray=(png_uint_16)
69633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (ScaleQuantumToShort(PixelIntensityToQuantum(p)) & mask);
69643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          ping_info->trans_color.index=(png_byte)
696546f08209f719f4adeea742c45873c2714e80cdb9cristy            (ScaleQuantumToChar((Quantum) (GetAlphaPixelComponent(p))));
69663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
69673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (ping_info->valid & PNG_INFO_tRNS)
69683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
69693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /*
69703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            Determine if there is one and only one transparent color
69713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            and if so if it is fully transparent.
69723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          */
69733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          for (y=0; y < (long) image->rows; y++)
69743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
69753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            p=GetVirtualPixels(image,0,y,image->columns,1,
69763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               &image->exception);
69773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            x=0;
69783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (p == (const PixelPacket *) NULL)
69793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              break;
69803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            for (x=(long) image->columns-1; x >= 0; x--)
69813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
69823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (p->opacity != OpaqueOpacity)
69833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
69843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if (IsPNGColorEqual(ping_info->trans_color,*p) == 0)
69853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  {
69863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     break;  /* Can't use RGB + tRNS for multiple
69873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                transparent colors.  */
69883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  }
69893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if (p->opacity != (Quantum) TransparentOpacity)
69903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  {
69913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     break;  /* Can't use RGB + tRNS for
69923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                semitransparency. */
69933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  }
69943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
69953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               else
69963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
69973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if (IsPNGColorEqual(ping_info->trans_color,*p))
69983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      break; /* Can't use RGB + tRNS when another pixel
69993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                having the same RGB samples is
70003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                transparent. */
70013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
70023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            p++;
70033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
70043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (x != 0)
70053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               break;
70063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
70073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (x != 0)
70083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            ping_info->valid&=(~PNG_INFO_tRNS);
70093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
70103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (ping_info->valid & PNG_INFO_tRNS)
70113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
7012c11cf6a442f3046940608a5743a68cc891deb13eglennrp          ping_info_color_type &= 0x03;  /* changes 4 or 6 to 0 or 2 */
70133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (image_depth == 8)
70143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
70153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              ping_info->trans_color.red&=0xff;
70163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              ping_info->trans_color.green&=0xff;
70173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              ping_info->trans_color.blue&=0xff;
70183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              ping_info->trans_color.gray&=0xff;
70193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
70203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
70213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
70223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    matte=image_matte;
70233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (ping_info->valid & PNG_INFO_tRNS)
70243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image_matte=MagickFalse;
70253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if ((mng_info->optimize || mng_info->IsPalette) &&
70263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        mng_info->write_png_colortype-1 != PNG_COLOR_TYPE_PALETTE &&
70273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ImageIsGray(image) && (!image_matte || image_depth >= 8))
70283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
70293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (image_matte != MagickFalse)
7030c11cf6a442f3046940608a5743a68cc891deb13eglennrp            ping_info_color_type=PNG_COLOR_TYPE_GRAY_ALPHA;
70313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        else
70323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
7033c11cf6a442f3046940608a5743a68cc891deb13eglennrp            ping_info_color_type=PNG_COLOR_TYPE_GRAY;
70343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (save_image_depth == 16 && image_depth == 8)
70353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              ping_info->trans_color.gray*=0x0101;
70363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
70373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (image_depth > MAGICKCORE_QUANTUM_DEPTH)
70383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image_depth=MAGICKCORE_QUANTUM_DEPTH;
70393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (image_colors == 0 || image_colors-1 > MaxColormapSize)
70403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image_colors=1 << image_depth;
70413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (image_depth > 8)
7042c11cf6a442f3046940608a5743a68cc891deb13eglennrp          ping_info_bit_depth=16;
70433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        else
70443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
7045c11cf6a442f3046940608a5743a68cc891deb13eglennrp            ping_info_bit_depth=8;
7046c11cf6a442f3046940608a5743a68cc891deb13eglennrp            if ((int) ping_info_color_type == PNG_COLOR_TYPE_PALETTE)
70473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
70483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if(!mng_info->write_png_depth)
70493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  {
7050c11cf6a442f3046940608a5743a68cc891deb13eglennrp                    ping_info_bit_depth=1;
7051c11cf6a442f3046940608a5743a68cc891deb13eglennrp                    while ((int) (1 << ping_info_bit_depth)
70523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        < (long) image_colors)
7053c11cf6a442f3046940608a5743a68cc891deb13eglennrp                      ping_info_bit_depth <<= 1;
70543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  }
70553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
7056c11cf6a442f3046940608a5743a68cc891deb13eglennrp            else if (mng_info->optimize && ping_info_color_type ==
70573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                PNG_COLOR_TYPE_GRAY && image_colors < 17 &&
70583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->IsPalette)
70593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
70603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
70613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              /* Check if grayscale is reducible */
70623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                int
70633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  depth_4_ok=MagickTrue,
70643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  depth_2_ok=MagickTrue,
70653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  depth_1_ok=MagickTrue;
70663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
70673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                for (i=0; i < (long) image_colors; i++)
70683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
70693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   unsigned char
70703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     intensity;
70713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
70723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   intensity=ScaleQuantumToChar(image->colormap[i].red);
70733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
70743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   if ((intensity & 0x0f) != ((intensity & 0xf0) >> 4))
70753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     depth_4_ok=depth_2_ok=depth_1_ok=MagickFalse;
70763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   else if ((intensity & 0x03) != ((intensity & 0x0c) >> 2))
70773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     depth_2_ok=depth_1_ok=MagickFalse;
70783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   else if ((intensity & 0x01) != ((intensity & 0x02) >> 1))
70793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     depth_1_ok=MagickFalse;
70803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
70813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (depth_1_ok && mng_info->write_png_depth <= 1)
7082c11cf6a442f3046940608a5743a68cc891deb13eglennrp                   ping_info_bit_depth=1;
70833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                else if (depth_2_ok && mng_info->write_png_depth <= 2)
7084c11cf6a442f3046940608a5743a68cc891deb13eglennrp                   ping_info_bit_depth=2;
70853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                else if (depth_4_ok && mng_info->write_png_depth <= 4)
7086c11cf6a442f3046940608a5743a68cc891deb13eglennrp                   ping_info_bit_depth=4;
70873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
70883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
7089c11cf6a442f3046940608a5743a68cc891deb13eglennrp          image_depth=ping_info_bit_depth;
70903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
70913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    else
70923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (mng_info->IsPalette)
70933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
70943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (image_depth <= 8)
70953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
70963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            unsigned long
70973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               number_colors;
70983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
70993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            number_colors=image_colors;
71003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (matte)
71013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               ping_info->valid|=PNG_INFO_tRNS;
71023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
71033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Set image palette.
71043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
7105c11cf6a442f3046940608a5743a68cc891deb13eglennrp            ping_info_color_type=(png_byte) PNG_COLOR_TYPE_PALETTE;
71063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            ping_info->valid|=PNG_INFO_PLTE;
71073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (mng_info->have_write_global_plte && !matte)
71083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
71093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                 png_set_PLTE(ping,ping_info,NULL,0);
71103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                 if (logging)
71113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
71123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     "  Setting up empty PLTE chunk");
71133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
71143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
71153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
71163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_SORT_PALETTE)
71173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                unsigned long
71183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   save_number_colors;
71193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
71203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (mng_info->optimize)
71213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  {
71223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    save_number_colors=image_colors;
71233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    if (CompressColormapTransFirst(image) == MagickFalse)
71243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                       ThrowWriterException(ResourceLimitError,
71253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                            "MemoryAllocationFailed");
712698156a3a465a004545e39434c63052b955a74d1cglennrp                    number_colors=image->colors;
71273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    image_colors=save_number_colors;
71283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  }
71293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
71303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                palette=(png_color *) AcquireQuantumMemory(257,
71313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  sizeof(*palette));
71323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (palette == (png_color *) NULL)
71333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  ThrowWriterException(ResourceLimitError,
71343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     "MemoryAllocationFailed");
71353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                for (i=0; i < (long) number_colors; i++)
71363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
71373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  palette[i].red=ScaleQuantumToChar(image->colormap[i].red);
71383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  palette[i].green=ScaleQuantumToChar(image->colormap[i].green);
71393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  palette[i].blue=ScaleQuantumToChar(image->colormap[i].blue);
71403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
71413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (logging)
71423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
714398156a3a465a004545e39434c63052b955a74d1cglennrp                    "  Setting up PLTE chunk with %d colors",
714498156a3a465a004545e39434c63052b955a74d1cglennrp                    (int) number_colors);
71453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                png_set_PLTE(ping,ping_info,palette,(int) number_colors);
71463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if (PNG_LIBPNG_VER > 10008)
71473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                palette=(png_colorp) RelinquishMagickMemory(palette);
71483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
71493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
71503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /* color_type is PNG_COLOR_TYPE_PALETTE */
71513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (!mng_info->write_png_depth)
71523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
71533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                ping_info->bit_depth=1;
71543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                while ((1UL << ping_info->bit_depth) < number_colors)
7155c11cf6a442f3046940608a5743a68cc891deb13eglennrp                  ping_info_bit_depth <<= 1;
71563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
7157cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp            ping_info_num_trans=0;
71583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (matte)
71593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
71603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              ExceptionInfo
71613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                *exception;
71623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
71633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              register const PixelPacket
71643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                *p;
71653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
71663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              int
71673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                trans[256];
71683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
71693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              register const IndexPacket
71703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                *packet_indices;
71713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
71723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              /*
71733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                Identify which colormap entry is transparent.
71743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              */
71753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              assert(number_colors <= 256);
71763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              for (i=0; i < (long) number_colors; i++)
71773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                trans[i]=256;
71783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              exception=(&image->exception);
71793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              for (y=0; y < (long) image->rows; y++)
71803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
71813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                p=GetVirtualPixels(image,0,y,image->columns,1,exception);
71823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (p == (const PixelPacket *) NULL)
71833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  break;
71843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                packet_indices=GetVirtualIndexQueue(image);
71853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                for (x=0; x < (long) image->columns; x++)
71863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
71873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if (p->opacity != OpaqueOpacity)
71883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    {
71893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      IndexPacket
71903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        packet_index;
71913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
71923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      packet_index=packet_indices[x];
71933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      assert((unsigned long) packet_index < number_colors);
71943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      if (trans[(long) packet_index] != 256)
71953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        {
71963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          if (trans[(long) packet_index] != (png_byte) (255-
7197ce70c17bb6433add2eb069515a4f3105989e0662cristy                             ScaleQuantumToChar(GetOpacityPixelComponent(p))))
71983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                            {
7199c11cf6a442f3046940608a5743a68cc891deb13eglennrp                              ping_info_color_type=(png_byte)
72003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                                PNG_COLOR_TYPE_RGB_ALPHA;
72013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                              break;
72023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                            }
72033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        }
72043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      trans[(long) packet_index]=(png_byte) (255-
7205ce70c17bb6433add2eb069515a4f3105989e0662cristy                        ScaleQuantumToChar(GetOpacityPixelComponent(p)));
72063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    }
72073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  p++;
72083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
7209c11cf6a442f3046940608a5743a68cc891deb13eglennrp                if ((int) ping_info_color_type == PNG_COLOR_TYPE_RGB_ALPHA)
72103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
7211cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp                  ping_info_num_trans=0;
72123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  ping_info->valid&=(~PNG_INFO_tRNS);
72133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  ping_info->valid&=(~PNG_INFO_PLTE);
72143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  mng_info->IsPalette=MagickFalse;
72153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  (void) SyncImage(image);
72163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if (logging)
72173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    (void) LogMagickEvent(CoderEvent, GetMagickModule(),
72183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      "    Cannot write image as indexed PNG, writing RGBA.");
72193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  break;
72203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
72213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
72223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if ((ping_info->valid & PNG_INFO_tRNS))
72233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
72243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                for (i=0; i < (long) number_colors; i++)
72253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
72263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if (trans[i] == 256)
72273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    trans[i]=255;
72283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if (trans[i] != 255)
7229cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp                    ping_info_num_trans=(unsigned short) (i+1);
72303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
72313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
7232cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp              if (ping_info_num_trans == 0)
72333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                ping_info->valid&=(~PNG_INFO_tRNS);
72343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (!(ping_info->valid & PNG_INFO_tRNS))
7235cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp                ping_info_num_trans=0;
7236cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp              if (ping_info_num_trans != 0)
72373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
72383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                ping_info->trans_alpha=(unsigned char *) AcquireQuantumMemory(
72393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  number_colors,sizeof(*ping_info->trans_alpha));
72403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (ping_info->trans_alpha == (unsigned char *) NULL)
72413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  ThrowWriterException(ResourceLimitError,
72423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     "MemoryAllocationFailed");
72433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                for (i=0; i < (long) number_colors; i++)
72443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    ping_info->trans_alpha[i]=(png_byte) trans[i];
72453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
72463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
72473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
72483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
72493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Identify which colormap entry is the background color.
72503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
72513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            for (i=0; i < (long) MagickMax(1L*number_colors-1L,1L); i++)
7252cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp              if (IsPNGColorEqual(ping_background,image->colormap[i]))
72533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
7254cecd5765c41f64cc68d4a5d77bb4afe92707a49eglennrp            ping_background.index=(png_byte) i;
72553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
72563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
72573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    else
72583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
72593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (image_depth < 8)
72603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image_depth=8;
72613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if ((save_image_depth == 16) && (image_depth == 8))
72623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
72633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            ping_info->trans_color.red*=0x0101;
72643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            ping_info->trans_color.green*=0x0101;
72653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            ping_info->trans_color.blue*=0x0101;
72663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            ping_info->trans_color.gray*=0x0101;
72673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
72683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
72693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
72703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
72713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Adjust background and transparency samples in sub-8-bit grayscale files.
72723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
7273c11cf6a442f3046940608a5743a68cc891deb13eglennrp    if (ping_info_bit_depth < 8 && ping_info_color_type ==
72743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        PNG_COLOR_TYPE_GRAY)
72753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
72763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         png_uint_16
72773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           maxval;
72783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
72793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         png_color_16
72803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           background;
72813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7282c11cf6a442f3046940608a5743a68cc891deb13eglennrp         maxval=(png_uint_16) ((1 << ping_info_bit_depth)-1);
72833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
72843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
72853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         background.gray=(png_uint_16)
72863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           (QuantumScale*(maxval*(PixelIntensity(&image->background_color))));
72873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
72883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         if (logging != MagickFalse)
72893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
72903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             "  Setting up bKGD chunk");
72913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         png_set_bKGD(ping,ping_info,&background);
72923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
72933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         ping_info->trans_color.gray=(png_uint_16) (QuantumScale*(maxval*
72943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           ping_info->trans_color.gray));
72953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
72963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
72973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
7298c11cf6a442f3046940608a5743a68cc891deb13eglennrp      "    PNG color type: %d",ping_info_color_type);
72993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
73003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Initialize compression level and filtering.
73013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
73023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
73033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
73043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      "  Setting up deflate compression");
73053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if (PNG_LIBPNG_VER > 99)
73063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
73073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
73083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      "    Compression buffer size: 32768");
73093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_set_compression_buffer_size(ping,32768L);
73103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
73113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
73123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
73133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      "    Compression mem level: 9");
73143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_set_compression_mem_level(ping, 9);
73153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  quality=image->quality == UndefinedCompressionQuality ? 75UL :
73163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     image->quality;
73173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (quality > 9)
73183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
73193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      int
73203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        level;
73213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
73223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      level=(int) MagickMin((long) quality/10,9);
73233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (logging != MagickFalse)
73243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
73253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "    Compression level: %d",level);
73263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      png_set_compression_level(ping,level);
73273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
73283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
73293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
73303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (logging != MagickFalse)
73313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
73323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "    Compression strategy: Z_HUFFMAN_ONLY");
73333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      png_set_compression_strategy(ping, Z_HUFFMAN_ONLY);
73343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
73353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
73363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
73373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      "  Setting up filtering");
73383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_MNG_FEATURES_SUPPORTED) && defined(PNG_INTRAPIXEL_DIFFERENCING)
73393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
73403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* This became available in libpng-1.0.9.  Output must be a MNG. */
73413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (mng_info->write_mng && ((quality % 10) == 7))
73423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
73433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (logging != MagickFalse)
73443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
73453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "    Filter_type: PNG_INTRAPIXEL_DIFFERENCING");
7346c11cf6a442f3046940608a5743a68cc891deb13eglennrp      ping_info_filter_method=PNG_INTRAPIXEL_DIFFERENCING;
73473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
73483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
73493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (logging != MagickFalse)
73503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
73513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "    Filter_type: 0");
73523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
73533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
73543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    int
73553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      base_filter;
73563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
73573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if ((quality % 10) > 5)
73583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      base_filter=PNG_ALL_FILTERS;
73593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    else
73603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if ((quality % 10) != 5)
73613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        base_filter=(int) quality % 10;
73623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else
7363c11cf6a442f3046940608a5743a68cc891deb13eglennrp        if (((int) ping_info_color_type == PNG_COLOR_TYPE_GRAY) ||
7364c11cf6a442f3046940608a5743a68cc891deb13eglennrp            ((int) ping_info_color_type == PNG_COLOR_TYPE_PALETTE) ||
73653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (quality < 50))
73663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          base_filter=PNG_NO_FILTERS;
73673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        else
73683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          base_filter=PNG_ALL_FILTERS;
73693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (logging != MagickFalse)
73703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
73713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (base_filter == PNG_ALL_FILTERS)
73723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
73733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            "    Base filter method: ADAPTIVE");
73743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        else
73753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
73763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            "    Base filter method: NONE");
73773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
73783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    png_set_filter(ping,PNG_FILTER_TYPE_BASE,base_filter);
73793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
73803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
73813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ResetImageProfileIterator(image);
73823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (name=GetNextImageProfile(image); name != (const char *) NULL; )
73833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
73843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    profile=GetImageProfile(image,name);
73853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (profile != (StringInfo *) NULL)
73863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
73873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if (PNG_LIBPNG_VER > 10008) && defined(PNG_WRITE_iCCP_SUPPORTED)
73883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if ((LocaleCompare(name,"ICC") == 0) ||
73893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (LocaleCompare(name,"ICM") == 0))
73903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          png_set_iCCP(ping,ping_info,(const png_charp) name,0,(png_charp)
73913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            GetStringInfoDatum(profile),
73923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     (png_uint_32) GetStringInfoLength(profile));
73933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        else
73943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
73953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          png_write_raw_profile(image_info,ping,ping_info,(unsigned char *)
73963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            name,(unsigned char *) name,GetStringInfoDatum(profile),
73973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (png_uint_32) GetStringInfoLength(profile));
73983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
73993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (logging != MagickFalse)
74003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
74013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "  Setting up text chunk with %s profile",name);
74023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    name=GetNextImageProfile(image);
74033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
74043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
74053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_WRITE_sRGB_SUPPORTED)
74063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((mng_info->have_write_global_srgb == 0) &&
74073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ((image->rendering_intent != UndefinedIntent) ||
74083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (image->colorspace == sRGBColorspace)))
74093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
74103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
74113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Note image rendering intent.
74123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
74133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (logging != MagickFalse)
74143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
74153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            "  Setting up sRGB chunk");
74163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) png_set_sRGB(ping,ping_info,(int) (image->rendering_intent-1));
74173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      png_set_gAMA(ping,ping_info,0.45455);
74183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
74193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((!mng_info->write_mng) || !(ping_info->valid & PNG_INFO_sRGB))
74203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
74213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
74223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if ((mng_info->have_write_global_gama == 0) && (image->gamma != 0.0))
74233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
74243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /*
74253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            Note image gamma.
74263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            To do: check for cHRM+gAMA == sRGB, and write sRGB instead.
74273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          */
74283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (logging != MagickFalse)
74293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
74303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              "  Setting up gAMA chunk");
74313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          png_set_gAMA(ping,ping_info,image->gamma);
74323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
74333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if ((mng_info->have_write_global_chrm == 0) &&
74343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (image->chromaticity.red_primary.x != 0.0))
74353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
74363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /*
74373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            Note image chromaticity.
74383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            To do: check for cHRM+gAMA == sRGB, and write sRGB instead.
74393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          */
74403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           PrimaryInfo
74413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             bp,
74423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             gp,
74433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             rp,
74443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             wp;
74453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
74463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           wp=image->chromaticity.white_point;
74473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           rp=image->chromaticity.red_primary;
74483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           gp=image->chromaticity.green_primary;
74493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           bp=image->chromaticity.blue_primary;
74503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
74513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           if (logging != MagickFalse)
74523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
74533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               "  Setting up cHRM chunk");
74543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           png_set_cHRM(ping,ping_info,wp.x,wp.y,rp.x,rp.y,gp.x,gp.y,
74553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               bp.x,bp.y);
74563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       }
74573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
7458c11cf6a442f3046940608a5743a68cc891deb13eglennrp  ping_info_interlace_method=image_info->interlace != NoInterlace;
74593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
74603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (mng_info->write_mng)
74613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    png_set_sig_bytes(ping,8);
74623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
74633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* Bail out if cannot meet defined PNG:bit-depth or PNG:color-type */
74643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
74653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (mng_info->write_png_colortype)
74663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
74673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     if (mng_info->write_png_colortype-1 == PNG_COLOR_TYPE_GRAY)
74683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       if (ImageIsGray(image) == MagickFalse)
74693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         {
7470c11cf6a442f3046940608a5743a68cc891deb13eglennrp           ping_info_color_type = PNG_COLOR_TYPE_RGB;
7471c11cf6a442f3046940608a5743a68cc891deb13eglennrp           if (ping_info_bit_depth < 8)
7472c11cf6a442f3046940608a5743a68cc891deb13eglennrp             ping_info_bit_depth=8;
74733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         }
74743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
74753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     if (mng_info->write_png_colortype-1 == PNG_COLOR_TYPE_GRAY_ALPHA)
74763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       if (ImageIsGray(image) == MagickFalse)
7477c11cf6a442f3046940608a5743a68cc891deb13eglennrp         ping_info_color_type = PNG_COLOR_TYPE_RGB_ALPHA;
74783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
74793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
74803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((mng_info->write_png_depth &&
7481c11cf6a442f3046940608a5743a68cc891deb13eglennrp     (int) mng_info->write_png_depth != ping_info_bit_depth) ||
74823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     (mng_info->write_png_colortype &&
7483c11cf6a442f3046940608a5743a68cc891deb13eglennrp     ((int) mng_info->write_png_colortype-1 != ping_info_color_type &&
7484991e92a91acb9e432cd6c05843e4f6a57643e29dglennrp      mng_info->write_png_colortype != 7 &&
7485c11cf6a442f3046940608a5743a68cc891deb13eglennrp      !(mng_info->write_png_colortype == 5 && ping_info_color_type == 0))))
74863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
74873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (logging != MagickFalse)
74883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
74893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (mng_info->write_png_depth)
74903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
74913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
74923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  "  Defined PNG:bit-depth=%u, Computed depth=%u",
74933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  mng_info->write_png_depth,
7494c11cf6a442f3046940608a5743a68cc891deb13eglennrp                  ping_info_bit_depth);
74953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
74963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (mng_info->write_png_colortype)
74973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
74983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
74993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  "  Defined PNG:color-type=%u, Computed color type=%u",
75003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  mng_info->write_png_colortype-1,
7501c11cf6a442f3046940608a5743a68cc891deb13eglennrp                  ping_info_color_type);
75023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
75033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
75043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      png_error(ping,
75053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "Cannot write image with defined PNG:bit-depth or PNG:color-type.");
75063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
75073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
75083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_matte && !image->matte)
75093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
75103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /* Add an opaque matte channel */
75113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->matte = MagickTrue;
75123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) SetImageOpacity(image,0);
75133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
75143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
75153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
75163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
75173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      "  Writing PNG header chunks");
75183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7519c11cf6a442f3046940608a5743a68cc891deb13eglennrp  png_set_IHDR(ping,ping_info,ping_info_width,ping_info_height,
7520c11cf6a442f3046940608a5743a68cc891deb13eglennrp               ping_info_bit_depth,ping_info_color_type,
7521c11cf6a442f3046940608a5743a68cc891deb13eglennrp               ping_info_interlace_method,ping_info_compression_method,
7522c11cf6a442f3046940608a5743a68cc891deb13eglennrp               ping_info_filter_method);
7523c11cf6a442f3046940608a5743a68cc891deb13eglennrp
75243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_write_info_before_PLTE(ping, ping_info);
75253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* write any png-chunk-b profiles */
75263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) png_write_chunk_from_profile(image,"PNG-chunk-b",(int) logging);
75273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_write_info(ping,ping_info);
75283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* write any PNG-chunk-m profiles */
75293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) png_write_chunk_from_profile(image,"PNG-chunk-m",(int) logging);
75303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
75313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->page.width || image->page.height)
75323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
75333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       unsigned char
75343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         chunk[14];
75353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
75363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       (void) WriteBlobMSBULong(image,9L);  /* data length=8 */
75373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       PNGType(chunk,mng_vpAg);
75383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       LogPNGChunk((int) logging,mng_vpAg,9L);
75393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       PNGLong(chunk+4,(png_uint_32) image->page.width);
75403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       PNGLong(chunk+8,(png_uint_32) image->page.height);
75413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       chunk[12]=0;   /* unit = pixels */
75423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       (void) WriteBlob(image,13,chunk);
75433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       (void) WriteBlobMSBULong(image,crc32(0,chunk,13));
75443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
75453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
75463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if (PNG_LIBPNG_VER == 10206)
75473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /* avoid libpng-1.2.6 bug by setting PNG_HAVE_IDAT flag */
75483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define PNG_HAVE_IDAT               0x04
75493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ping->mode |= PNG_HAVE_IDAT;
75503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#undef PNG_HAVE_IDAT
75513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
75523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
75533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_set_packing(ping);
75543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
75553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Allocate memory.
75563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
75573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  rowbytes=image->columns;
75583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_depth <= 8)
75593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
75603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (mng_info->write_png24 || (mng_info->write_png_depth == 8 &&
75613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          mng_info->write_png_colortype-1 == PNG_COLOR_TYPE_RGB))
75623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        rowbytes*=3;
75633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else if (mng_info->write_png32 || (mng_info->write_png_depth == 8 &&
75643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           mng_info->write_png_colortype-1 == PNG_COLOR_TYPE_RGB_ALPHA))
75653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        rowbytes*=4;
75663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else if ((!mng_info->write_png8 ||
75673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           mng_info->write_png_colortype-1 == PNG_COLOR_TYPE_GRAY ||
75683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           mng_info->write_png_colortype-1 == PNG_COLOR_TYPE_GRAY_ALPHA )&&
75693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           ((mng_info->optimize || mng_info->IsPalette) && ImageIsGray(image)))
75703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        rowbytes*=(image_matte ? 2 : 1);
75713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else
75723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
75733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (!mng_info->IsPalette)
75743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            rowbytes*=(image_matte ? 4 : 3);
75753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
75763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
75773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
75783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
75793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if ((mng_info->optimize || mng_info->IsPalette) &&
75803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          ImageIsGray(image))
75813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        rowbytes*=(image_matte ? 4 : 2);
75823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else
75833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        rowbytes*=(image_matte ? 8 : 6);
75843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
75853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging)
75863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
75873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      "  Allocating %lu bytes of memory for pixels",rowbytes);
75883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_pixels=(unsigned char *) AcquireQuantumMemory(rowbytes,
75893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    sizeof(*png_pixels));
75903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (png_pixels == (unsigned char *) NULL)
75913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
75923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
75933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Initialize image scanlines.
75943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
75953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (setjmp(ping->jmpbuf))
75963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
75973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
75983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        PNG write failed.
75993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
76003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#ifdef PNG_DEBUG
76013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     if (image_info->verbose)
76023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) printf("PNG write has failed.\n");
76033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
76043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      png_destroy_write_struct(&ping,&ping_info);
76053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (quantum_info != (QuantumInfo *) NULL)
76063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        quantum_info=DestroyQuantumInfo(quantum_info);
76073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (png_pixels != (unsigned char *) NULL)
76083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        png_pixels=(unsigned char *) RelinquishMagickMemory(png_pixels);
76093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
7610f84a193d5f435588cd78d521fff3f1f852e227f8cristy      UnlockSemaphoreInfo(png_semaphore);
76113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
76123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return(MagickFalse);
76133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
7614ed5525230af20461366cdc5b8bbe0f7f9b166c44cristy  quantum_info=AcquireQuantumInfo(image_info,image);
7615ed5525230af20461366cdc5b8bbe0f7f9b166c44cristy  if (quantum_info == (QuantumInfo *) NULL)
7616ed5525230af20461366cdc5b8bbe0f7f9b166c44cristy    ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
76173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  quantum_info->format=UndefinedQuantumFormat;
76183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  quantum_info->depth=image_depth;
76193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  num_passes=png_set_interlace_handling(ping);
76203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((!mng_info->write_png8 && !mng_info->write_png24 &&
76213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      !mng_info->write_png32) &&
76223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (mng_info->optimize || mng_info->IsPalette ||
76233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       (image_info->type == BilevelType)) &&
76243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      !image_matte && ImageIsMonochrome(image))
76253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
76263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      register const PixelPacket
76273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *p;
76283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
76293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      quantum_info->depth=8;
76303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (pass=0; pass < num_passes; pass++)
76313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
76323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
76333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Convert PseudoClass image to a PNG monochrome image.
76343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
76353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        for (y=0; y < (long) image->rows; y++)
76363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
76373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
76383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (p == (const PixelPacket *) NULL)
76393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
76403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (mng_info->IsPalette)
76413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
76423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) ExportQuantumPixels(image,(const CacheView *) NULL,
76433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                quantum_info,GrayQuantum,png_pixels,&image->exception);
76443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (mng_info->write_png_colortype-1 == PNG_COLOR_TYPE_PALETTE &&
76453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  mng_info->write_png_depth &&
76463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  mng_info->write_png_depth != old_bit_depth)
76473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
76483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  /* Undo pixel scaling */
76493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  for (i=0; i < (long) image->columns; i++)
76503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     *(png_pixels+i)=(unsigned char) (*(png_pixels+i)
76513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                     >> (8-old_bit_depth));
76523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
76533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
76543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          else
76553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
76563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) ExportQuantumPixels(image,(const CacheView *) NULL,
76573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                quantum_info,RedQuantum,png_pixels,&image->exception);
76583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
76593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (mng_info->write_png_colortype-1 != PNG_COLOR_TYPE_PALETTE)
76603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            for (i=0; i < (long) image->columns; i++)
76613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               *(png_pixels+i)=(unsigned char) ((*(png_pixels+i) > 127) ?
76623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      255 : 0);
76633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          png_write_row(ping,png_pixels);
76643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
76653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (image->previous == (Image *) NULL)
76663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
76673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            status=SetImageProgress(image,LoadImageTag,pass,num_passes);
76683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (status == MagickFalse)
76693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              break;
76703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
76713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
76723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
76733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
76743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    for (pass=0; pass < num_passes; pass++)
76753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
76763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      register const PixelPacket
76773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *p;
76783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
76793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if ((!mng_info->write_png8 && !mng_info->write_png24 &&
76803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         !mng_info->write_png32) &&
76813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (image_matte ||
7682c11cf6a442f3046940608a5743a68cc891deb13eglennrp         (ping_info_bit_depth >= MAGICKCORE_QUANTUM_DEPTH)) &&
76833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (mng_info->optimize || mng_info->IsPalette) && ImageIsGray(image))
76843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
76853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        for (y=0; y < (long) image->rows; y++)
76863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
76873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
76883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (p == (const PixelPacket *) NULL)
76893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
7690c11cf6a442f3046940608a5743a68cc891deb13eglennrp          if (ping_info_color_type == PNG_COLOR_TYPE_GRAY)
76913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
76923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (mng_info->IsPalette)
76933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) ExportQuantumPixels(image,(const CacheView *) NULL,
76943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  quantum_info,GrayQuantum,png_pixels,&image->exception);
76953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              else
76963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) ExportQuantumPixels(image,(const CacheView *) NULL,
76973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  quantum_info,RedQuantum,png_pixels,&image->exception);
76983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
76993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          else /* PNG_COLOR_TYPE_GRAY_ALPHA */
77003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
77013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) ExportQuantumPixels(image,(const CacheView *) NULL,
77023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                quantum_info,GrayAlphaQuantum,png_pixels,&image->exception);
77033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
77043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          png_write_row(ping,png_pixels);
77053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
77063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (image->previous == (Image *) NULL)
77073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
77083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            status=SetImageProgress(image,LoadImageTag,pass,num_passes);
77093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (status == MagickFalse)
77103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              break;
77113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
77123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
77133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    else
77143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (pass=0; pass < num_passes; pass++)
77153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
77163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if ((image_depth > 8) || (mng_info->write_png24 ||
77173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_info->write_png32 ||
77183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (!mng_info->write_png8 && !mng_info->IsPalette)))
77193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          for (y=0; y < (long) image->rows; y++)
77203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
77213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
77223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (p == (const PixelPacket *) NULL)
77233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              break;
7724c11cf6a442f3046940608a5743a68cc891deb13eglennrp            if (ping_info_color_type == PNG_COLOR_TYPE_GRAY)
77253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
77263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (image->storage_class == DirectClass)
77273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  (void) ExportQuantumPixels(image,(const CacheView *) NULL,
77283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    quantum_info,RedQuantum,png_pixels,&image->exception);
77293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                else
77303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  (void) ExportQuantumPixels(image,(const CacheView *) NULL,
77313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    quantum_info,GrayQuantum,png_pixels,&image->exception);
77323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
7733c11cf6a442f3046940608a5743a68cc891deb13eglennrp            else if (ping_info_color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
77343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) ExportQuantumPixels(image,(const CacheView *) NULL,
77353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                quantum_info,GrayAlphaQuantum,png_pixels,&image->exception);
77363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else if (image_matte != MagickFalse)
77373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) ExportQuantumPixels(image,(const CacheView *) NULL,
77383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                quantum_info,RGBAQuantum,png_pixels,&image->exception);
77393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
77403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) ExportQuantumPixels(image,(const CacheView *) NULL,
77413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                quantum_info,RGBQuantum,png_pixels,&image->exception);
77423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            png_write_row(ping,png_pixels);
77433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
77443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else
77453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /* not ((image_depth > 8) || (mng_info->write_png24 ||
77463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_info->write_png32 ||
77473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (!mng_info->write_png8 && !mng_info->IsPalette))) */
77483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
7749c11cf6a442f3046940608a5743a68cc891deb13eglennrp          if ((ping_info_color_type != PNG_COLOR_TYPE_GRAY) &&
7750c11cf6a442f3046940608a5743a68cc891deb13eglennrp              (ping_info_color_type != PNG_COLOR_TYPE_GRAY_ALPHA))
77513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
77523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (logging)
77533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
77543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  "  pass %d, Image Is not GRAY or GRAY_ALPHA",pass);
77553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              quantum_info->depth=8;
77563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              image_depth=8;
77573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
77583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          for (y=0; y < (long) image->rows; y++)
77593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
77603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (logging)
77613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
77623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                "  pass %d, Image Is RGB, 16-bit GRAY, or GRAY_ALPHA",pass);
77633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
77643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (p == (const PixelPacket *) NULL)
77653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              break;
7766c11cf6a442f3046940608a5743a68cc891deb13eglennrp            if (ping_info_color_type == PNG_COLOR_TYPE_GRAY)
77673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) ExportQuantumPixels(image,(const CacheView *) NULL,
77683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                quantum_info,GrayQuantum,png_pixels,&image->exception);
7769c11cf6a442f3046940608a5743a68cc891deb13eglennrp            else if (ping_info_color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
77703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) ExportQuantumPixels(image,(const CacheView *) NULL,
77713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                quantum_info,GrayAlphaQuantum,png_pixels,&image->exception);
77723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
77733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) ExportQuantumPixels(image,(const CacheView *) NULL,
77743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                quantum_info,IndexQuantum,png_pixels,&image->exception);
77753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            png_write_row(ping,png_pixels);
77763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
77773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
77783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (image->previous == (Image *) NULL)
77793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
77803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            status=SetImageProgress(image,LoadImageTag,pass,num_passes);
77813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (status == MagickFalse)
77823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              break;
77833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
77843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     }
77853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
7786b32b90a7e1ee2275333589072c496b5f69e17feccristy  if (quantum_info != (QuantumInfo *) NULL)
7787b32b90a7e1ee2275333589072c496b5f69e17feccristy    quantum_info=DestroyQuantumInfo(quantum_info);
77883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
77893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
77903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
77913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
77923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "  Writing PNG image data");
77933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
7794c11cf6a442f3046940608a5743a68cc891deb13eglennrp        "    Width: %lu",ping_info_width);
77953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
7796c11cf6a442f3046940608a5743a68cc891deb13eglennrp        "    Height: %lu",ping_info_height);
77973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (mng_info->write_png_depth)
77983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
77993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
78003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            "    Defined PNG:bit-depth: %d",mng_info->write_png_depth);
78013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
78023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
7803c11cf6a442f3046940608a5743a68cc891deb13eglennrp        "    PNG bit-depth written: %d",ping_info_bit_depth);
78043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (mng_info->write_png_colortype)
78053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
78063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
78073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            "    Defined PNG:color-type: %d",mng_info->write_png_colortype-1);
78083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
78093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
7810c11cf6a442f3046940608a5743a68cc891deb13eglennrp        "    PNG color-type written: %d",ping_info_color_type);
78113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
7812c11cf6a442f3046940608a5743a68cc891deb13eglennrp        "    PNG Interlace method: %d",ping_info_interlace_method);
78133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
78143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
78153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Generate text chunks.
78163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
78173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if (PNG_LIBPNG_VER <= 10005)
78183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ping_info->num_text=0;
78193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
78203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ResetImagePropertyIterator(image);
78213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  property=GetNextImageProperty(image);
78223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  while (property != (const char *) NULL)
78233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
78243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if (PNG_LIBPNG_VER > 10005)
78253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    png_textp
78263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      text;
78273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
78283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
78293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    value=GetImageProperty(image,property);
78303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (value != (const char *) NULL)
78313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
78323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        text=(png_textp) png_malloc(ping,(png_uint_32) sizeof(png_text));
78333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        text[0].key=(char *) property;
78343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        text[0].text=(char *) value;
78353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        text[0].text_length=strlen(value);
78363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        text[0].compression=image_info->compression == NoCompression ||
78373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (image_info->compression == UndefinedCompression &&
78383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          text[0].text_length < 128) ? -1 : 0;
78393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (logging != MagickFalse)
78403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
78413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
78423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              "  Setting up text chunk");
78433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
78443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              "    keyword: %s",text[0].key);
78453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
78463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        png_set_text(ping,ping_info,text,1);
78473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        png_free(ping,text);
78483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
78493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    property=GetNextImageProperty(image);
78503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
78513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
78523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* write any PNG-chunk-e profiles */
78533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) png_write_chunk_from_profile(image,"PNG-chunk-e",(int) logging);
78543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
78553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
78563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
78573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      "  Writing PNG end info");
78583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_write_end(ping,ping_info);
78593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (mng_info->need_fram && (int) image->dispose == BackgroundDispose)
78603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
78613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (mng_info->page.x || mng_info->page.y ||
7862c11cf6a442f3046940608a5743a68cc891deb13eglennrp          (ping_info_width != mng_info->page.width) ||
7863c11cf6a442f3046940608a5743a68cc891deb13eglennrp          (ping_info_height != mng_info->page.height))
78643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
78653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          unsigned char
78663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            chunk[32];
78673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
78683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /*
78693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            Write FRAM 4 with clipping boundaries followed by FRAM 1.
78703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          */
78713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) WriteBlobMSBULong(image,27L);  /* data length=27 */
78723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          PNGType(chunk,mng_FRAM);
78733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          LogPNGChunk((int) logging,mng_FRAM,27L);
78743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          chunk[4]=4;
78753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          chunk[5]=0;  /* frame name separator (no name) */
78763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          chunk[6]=1;  /* flag for changing delay, for next frame only */
78773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          chunk[7]=0;  /* flag for changing frame timeout */
78783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          chunk[8]=1;  /* flag for changing frame clipping for next frame */
78793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          chunk[9]=0;  /* flag for changing frame sync_id */
78803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          PNGLong(chunk+10,(png_uint_32) (0L)); /* temporary 0 delay */
78813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          chunk[14]=0; /* clipping boundaries delta type */
78823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          PNGLong(chunk+15,(png_uint_32) (mng_info->page.x)); /* left cb */
78833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          PNGLong(chunk+19,
7884c11cf6a442f3046940608a5743a68cc891deb13eglennrp             (png_uint_32) (mng_info->page.x + ping_info_width));
78853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          PNGLong(chunk+23,(png_uint_32) (mng_info->page.y)); /* top cb */
78863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          PNGLong(chunk+27,
7887c11cf6a442f3046940608a5743a68cc891deb13eglennrp             (png_uint_32) (mng_info->page.y + ping_info_height));
78883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) WriteBlob(image,31,chunk);
78893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) WriteBlobMSBULong(image,crc32(0,chunk,31));
78903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          mng_info->old_framing_mode=4;
78913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          mng_info->framing_mode=1;
78923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
78933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else
78943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        mng_info->framing_mode=3;
78953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
78963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (mng_info->write_mng && !mng_info->need_fram &&
78973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ((int) image->dispose == 3))
78983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     (void) ThrowMagickException(&image->exception,GetMagickModule(),
78993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       CoderError,"Cannot convert GIF with disposal method 3 to MNG-LC",
79003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       "`%s'",image->filename);
79013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image_depth=save_image_depth;
79023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
79033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* Save depth actually written */
79043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7905c11cf6a442f3046940608a5743a68cc891deb13eglennrp  s[0]=(char) ping_info_bit_depth;
79063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  s[1]='\0';
79073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
79083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) SetImageProperty(image,"png:bit-depth-written",s);
79093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
79103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
79113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Free PNG resources.
79123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
79133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
79143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_destroy_write_struct(&ping,&ping_info);
79153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
79163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  png_pixels=(unsigned char *) RelinquishMagickMemory(png_pixels);
79173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
79183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
7919f84a193d5f435588cd78d521fff3f1f852e227f8cristy  UnlockSemaphoreInfo(png_semaphore);
79203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
79213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
79223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
79233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
79243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      "  exit WriteOnePNGImage()");
79253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickTrue);
79263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*  End write one PNG image */
79273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
79283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
79293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
79303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
79313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
79323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
79333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
79343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   W r i t e P N G I m a g e                                                 %
79353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
79363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
79373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
79383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
79393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
79403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  WritePNGImage() writes a Portable Network Graphics (PNG) or
79413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  Multiple-image Network Graphics (MNG) image file.
79423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
79433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  MNG support written by Glenn Randers-Pehrson, glennrp@image...
79443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
79453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the WritePNGImage method is:
79463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
79473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType WritePNGImage(const ImageInfo *image_info,Image *image)
79483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
79493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
79503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
79513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image_info: the image info.
79523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
79533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image:  The image.
79543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
79553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  Returns MagickTrue on success, MagickFalse on failure.
79563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
79573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  Communicating with the PNG encoder:
79583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
79593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  While the datastream written is always in PNG format and normally would
79603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  be given the "png" file extension, this method also writes the following
79613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  pseudo-formats which are subsets of PNG:
79623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
79633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o PNG8:    An 8-bit indexed PNG datastream is written.  If transparency
79643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%               is present, the tRNS chunk must only have values 0 and 255
79653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%               (i.e., transparency is binary: fully opaque or fully
79663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%               transparent).  The pixels contain 8-bit indices even if
79673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%               they could be represented with 1, 2, or 4 bits. Note: grayscale
79683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%               images will be written as indexed PNG files even though the
79693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%               PNG grayscale type might be slightly more efficient.
79703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
79713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o PNG24:   An 8-bit per sample RGB PNG datastream is written.  The tRNS
79723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%               chunk can be present to convey binary transparency by naming
79733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%               one of the colors as transparent.
79743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
79753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o PNG32:   An 8-bit per sample RGBA PNG is written.  Partial
79763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%               transparency is permitted, i.e., the alpha sample for
79773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%               each pixel can have any value from 0 to 255. The alpha
79783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%               channel is present even if the image is fully opaque.
79793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
79803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o -define: For more precise control of the PNG output, you can use the
79813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%               Image options "png:bit-depth" and "png:color-type".  These
79823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%               can be set from the commandline with "-define" and also
79833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%               from the application programming interfaces.
79843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
79853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%               png:color-type can be 0, 2, 3, 4, or 6.
79863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
79873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%               When png:color-type is 0 (Grayscale), png:bit-depth can
79883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%               be 1, 2, 4, 8, or 16.
79893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
79903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%               When png:color-type is 2 (RGB), png:bit-depth can
79913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%               be 8 or 16.
79923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
79933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%               When png:color-type is 3 (Indexed), png:bit-depth can
79943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%               be 1, 2, 4, or 8.  This refers to the number of bits
79953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%               used to store the index.  The color samples always have
79963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%               bit-depth 8 in indexed PNG files.
79973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
79983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%               When png:color-type is 4 (Gray-Matte) or 6 (RGB-Matte),
79993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%               png:bit-depth can be 8 or 16.
80003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
80013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  If the image cannot be written without loss in the requested PNG8, PNG24,
80023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  or PNG32 format or with the requested bit-depth and color-type without loss,
80033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  a PNG file will not be written, and the encoder will return MagickFalse.
80043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  Since image encoders should not be responsible for the "heavy lifting",
80053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  the user should make sure that ImageMagick has already reduced the
80063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  image depth and number of colors and limit transparency to binary
80073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  transparency prior to attempting to write the image in a format that
80083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  is subject to depth, color, or transparency limitations.
80093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
80103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  TODO: Enforce the previous paragraph.
80113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
80123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  TODO: Allow all other PNG subformats to be requested via new
80133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        "-define png:bit-depth -define png:color-type" options.
80143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
80153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  Note that another definition, "png:bit-depth-written" exists, but it
80163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  is not intended for external use.  It is only used internally by the
80173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  PNG encoder to inform the JNG encoder of the depth of the alpha channel.
80183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
80193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  It is possible to request that the PNG encoder write previously-formatted
80203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  ancillary chunks in the output PNG file, using the "-profile" commandline
80213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  option as shown below or by setting the profile via a programming
80223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  interface:
80233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
80243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%     -profile PNG-chunk-x:<file>
80253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
80263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  where x is a location flag and <file> is a file containing the chunk
80273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  name in the first 4 bytes, then a colon (":"), followed by the chunk data.
80283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
80293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  "x" can be "b" (before PLTE), "m" (middle, i.e., between PLTE and IDAT),
80303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  or "e" (end, i.e., after IDAT).  If you want to write multiple chunks
80313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  of the same type, then add a short unique string after the "x" to prevent
80323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  subsequent profiles from overwriting the preceding ones:
80333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
80343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%     -profile PNG-chunk-x01:file01 -profile PNG-chunk-x02:file02
80353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
80363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
80373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
80383ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType WritePNGImage(const ImageInfo *image_info,
80393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image *image)
80403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
80413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
80423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
80433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
80443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MngInfo
80453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *mng_info;
80463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
80473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const char
80483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *value;
80493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
80503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  int
80513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    have_mng_structure;
80523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
80533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned int
80543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    logging;
80553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
80563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
80573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Open image file.
80583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
80593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info != (const ImageInfo *) NULL);
80603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info->signature == MagickSignature);
80613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (Image *) NULL);
80623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image->signature == MagickSignature);
80633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
80643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  logging=LogMagickEvent(CoderEvent,GetMagickModule(),"enter WritePNGImage()");
80653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
80663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == MagickFalse)
80673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
80683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
80693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Allocate a MngInfo structure.
80703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
80713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  have_mng_structure=MagickFalse;
807290823213d62b0ba18557e61f1e6892c6fffd6cd4cristy  mng_info=(MngInfo *) AcquireAlignedMemory(1,sizeof(MngInfo));
80733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (mng_info == (MngInfo *) NULL)
80743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
80753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
80763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Initialize members of the MngInfo structure.
80773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
80783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ResetMagickMemory(mng_info,0,sizeof(MngInfo));
80793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mng_info->image=image;
80803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  have_mng_structure=MagickTrue;
80813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
80823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* See if user has requested a specific PNG subformat */
80833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
80843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mng_info->write_png8=LocaleCompare(image_info->magick,"PNG8") == 0;
80853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mng_info->write_png24=LocaleCompare(image_info->magick,"PNG24") == 0;
80863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mng_info->write_png32=LocaleCompare(image_info->magick,"PNG32") == 0;
80873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
80883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (mng_info->write_png8)
80893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
80903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         mng_info->write_png_colortype = /* 3 */ 4;
80913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         mng_info->write_png_depth = 8;
80923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         image->depth = 8;
80933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if 0 /* this does not work */
80943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         if (image->matte == MagickTrue)
80953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) SetImageType(image,PaletteMatteType);
80963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         else
80973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) SetImageType(image,PaletteType);
80983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (void) SyncImage(image);
80993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
81003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
81013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
81023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (mng_info->write_png24)
81033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
81043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         mng_info->write_png_colortype = /* 2 */ 3;
81053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         mng_info->write_png_depth = 8;
81063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         image->depth = 8;
81073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         if (image->matte == MagickTrue)
81083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) SetImageType(image,TrueColorMatteType);
81093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         else
81103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) SetImageType(image,TrueColorType);
81113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (void) SyncImage(image);
81123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
81133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
81143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (mng_info->write_png32)
81153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
81163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         mng_info->write_png_colortype = /* 6 */  7;
81173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         mng_info->write_png_depth = 8;
81183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         image->depth = 8;
81193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         if (image->matte == MagickTrue)
81203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) SetImageType(image,TrueColorMatteType);
81213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         else
81223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) SetImageType(image,TrueColorType);
81233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (void) SyncImage(image);
81243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
81253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
81263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  value=GetImageOption(image_info,"png:bit-depth");
81273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (value != (char *) NULL)
81283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
81293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (LocaleCompare(value,"1") == 0)
81303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         mng_info->write_png_depth = 1;
81313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else if (LocaleCompare(value,"2") == 0)
81323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         mng_info->write_png_depth = 2;
81333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else if (LocaleCompare(value,"4") == 0)
81343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         mng_info->write_png_depth = 4;
81353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else if (LocaleCompare(value,"8") == 0)
81363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         mng_info->write_png_depth = 8;
81373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else if (LocaleCompare(value,"16") == 0)
81383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         mng_info->write_png_depth = 16;
81393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (logging != MagickFalse)
81403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
81413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         "png:bit-depth=%d was defined.\n",mng_info->write_png_depth);
81423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
81433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  value=GetImageOption(image_info,"png:color-type");
81443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (value != (char *) NULL)
81453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
81463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /* We must store colortype+1 because 0 is a valid colortype */
81473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (LocaleCompare(value,"0") == 0)
81483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         mng_info->write_png_colortype = 1;
81493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else if (LocaleCompare(value,"2") == 0)
81503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         mng_info->write_png_colortype = 3;
81513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else if (LocaleCompare(value,"3") == 0)
81523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         mng_info->write_png_colortype = 4;
81533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else if (LocaleCompare(value,"4") == 0)
81543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         mng_info->write_png_colortype = 5;
81553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else if (LocaleCompare(value,"6") == 0)
81563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         mng_info->write_png_colortype = 7;
81573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (logging != MagickFalse)
81583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
81593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         "png:color-type=%d was defined.\n",mng_info->write_png_colortype-1);
81603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
81613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
81623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=WriteOnePNGImage(mng_info,image_info,image);
81633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
81643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloseBlob(image);
81653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
81663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MngInfoFreeStruct(mng_info,&have_mng_structure);
81673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
81683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(CoderEvent,GetMagickModule(),"exit WritePNGImage()");
81693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(status);
81703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
81713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
81723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(JNG_SUPPORTED)
81733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
81743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* Write one JNG image */
81753ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType WriteOneJNGImage(MngInfo *mng_info,
81763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   const ImageInfo *image_info,Image *image)
81773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
81783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
81793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *jpeg_image;
81803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
81813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ImageInfo
81823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *jpeg_image_info;
81833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
81843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
81853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
81863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
81873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  size_t
81883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    length;
81893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
81903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned char
81913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *blob,
81923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    chunk[80],
81933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p;
81943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
81953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned int
81963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    jng_alpha_compression_method,
81973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    jng_alpha_sample_depth,
81983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    jng_color_type,
81993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    logging,
82003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    transparent;
82013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
82023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned long
82033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    jng_quality;
82043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
82053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  logging=LogMagickEvent(CoderEvent,GetMagickModule(),
82063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    "  enter WriteOneJNGImage()");
82073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
82083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  blob=(unsigned char *) NULL;
82093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  jpeg_image=(Image *) NULL;
82103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  jpeg_image_info=(ImageInfo *) NULL;
82113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
82123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=MagickTrue;
82133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  transparent=image_info->type==GrayscaleMatteType ||
82143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     image_info->type==TrueColorMatteType;
82153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  jng_color_type=10;
82163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  jng_alpha_sample_depth=0;
82173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  jng_quality=image_info->quality == 0UL ? 75UL : image_info->quality;
82183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  jng_alpha_compression_method=0;
82193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
82203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->matte != MagickFalse)
82213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
82223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /* if any pixels are transparent */
82233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      transparent=MagickTrue;
82243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (image_info->compression==JPEGCompression)
82253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        jng_alpha_compression_method=8;
82263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
82273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
82283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (transparent)
82293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
82303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      jng_color_type=14;
82313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /* Create JPEG blob, image, and image_info */
82323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (logging != MagickFalse)
82333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
82343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "  Creating jpeg_image_info for opacity.");
82353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      jpeg_image_info=(ImageInfo *) CloneImageInfo(image_info);
82363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (jpeg_image_info == (ImageInfo *) NULL)
82373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
82383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (logging != MagickFalse)
82393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
82403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "  Creating jpeg_image.");
82413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      jpeg_image=CloneImage(image,0,0,MagickTrue,&image->exception);
82423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (jpeg_image == (Image *) NULL)
82433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
82443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) CopyMagickString(jpeg_image->magick,"JPEG",MaxTextExtent);
82453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      status=SeparateImageChannel(jpeg_image,OpacityChannel);
82463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      status=NegateImage(jpeg_image,MagickFalse);
82473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      jpeg_image->matte=MagickFalse;
82483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (jng_quality >= 1000)
82493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        jpeg_image_info->quality=jng_quality/1000;
82503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else
82513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        jpeg_image_info->quality=jng_quality;
82523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      jpeg_image_info->type=GrayscaleType;
82533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) SetImageType(jpeg_image,GrayscaleType);
82543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) AcquireUniqueFilename(jpeg_image->filename);
82553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) FormatMagickString(jpeg_image_info->filename,MaxTextExtent,
82563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "%s",jpeg_image->filename);
82573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
82583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
82593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* To do: check bit depth of PNG alpha channel */
82603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
82613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* Check if image is grayscale. */
82623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_info->type != TrueColorMatteType && image_info->type !=
82633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    TrueColorType && ImageIsGray(image))
82643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    jng_color_type-=2;
82653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
82663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (transparent)
82673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
82683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (jng_alpha_compression_method==0)
82693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
82703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          const char
82713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            *value;
82723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
82733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /* Encode opacity as a grayscale PNG blob */
82743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          status=OpenBlob(jpeg_image_info,jpeg_image,WriteBinaryBlobMode,
82753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            &image->exception);
82763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (logging != MagickFalse)
82773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
82783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              "  Creating PNG blob.");
82793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          length=0;
82803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
82813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) CopyMagickString(jpeg_image_info->magick,"PNG",MaxTextExtent);
82823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) CopyMagickString(jpeg_image->magick,"PNG",MaxTextExtent);
82833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          jpeg_image_info->interlace=NoInterlace;
82843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
82853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          blob=ImageToBlob(jpeg_image_info,jpeg_image,&length,
82863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            &image->exception);
82873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
82883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /* Retrieve sample depth used */
82893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          value=GetImageProperty(jpeg_image,"png:bit-depth-written");
82903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (value != (char *) NULL)
82913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            jng_alpha_sample_depth= (unsigned int) value[0];
82923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
82933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else
82943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
82953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /* Encode opacity as a grayscale JPEG blob */
82963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
82973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          status=OpenBlob(jpeg_image_info,jpeg_image,WriteBinaryBlobMode,
82983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            &image->exception);
82993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
83003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) CopyMagickString(jpeg_image_info->magick,"JPEG",MaxTextExtent);
83013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) CopyMagickString(jpeg_image->magick,"JPEG",MaxTextExtent);
83023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          jpeg_image_info->interlace=NoInterlace;
83033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (logging != MagickFalse)
83043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
83053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              "  Creating blob.");
83063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          blob=ImageToBlob(jpeg_image_info,jpeg_image,&length,
83073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             &image->exception);
83083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          jng_alpha_sample_depth=8;
83093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (logging != MagickFalse)
83103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
83113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              "  Successfully read jpeg_image into a blob, length=%lu.",
83123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (unsigned long) length);
83133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
83143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
83153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /* Destroy JPEG image and image_info */
83163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      jpeg_image=DestroyImage(jpeg_image);
83173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) RelinquishUniqueFileResource(jpeg_image_info->filename);
83183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      jpeg_image_info=DestroyImageInfo(jpeg_image_info);
83193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
83203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
83213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* Write JHDR chunk */
83223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobMSBULong(image,16L);  /* chunk data length=16 */
83233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  PNGType(chunk,mng_JHDR);
83243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  LogPNGChunk((int) logging,mng_JHDR,16L);
83253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  PNGLong(chunk+4,image->columns);
83263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  PNGLong(chunk+8,image->rows);
83273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  chunk[12]=jng_color_type;
83283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  chunk[13]=8;  /* sample depth */
83293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  chunk[14]=8; /*jng_image_compression_method */
83303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  chunk[15]=(unsigned char) (image_info->interlace == NoInterlace ? 0 : 8);
83313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  chunk[16]=jng_alpha_sample_depth;
83323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  chunk[17]=jng_alpha_compression_method;
83333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  chunk[18]=0; /*jng_alpha_filter_method */
83343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  chunk[19]=0; /*jng_alpha_interlace_method */
83353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlob(image,20,chunk);
83363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobMSBULong(image,crc32(0,chunk,20));
83373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
83383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
83393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
83403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "    JNG width:%15lu",image->columns);
83413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
83423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "    JNG height:%14lu",image->rows);
83433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
83443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "    JNG color type:%10d",jng_color_type);
83453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
83463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "    JNG sample depth:%8d",8);
83473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
83483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "    JNG compression:%9d",8);
83493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
83503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "    JNG interlace:%11d",0);
83513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
83523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "    JNG alpha depth:%9d",jng_alpha_sample_depth);
83533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
83543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "    JNG alpha compression:%3d",jng_alpha_compression_method);
83553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
83563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "    JNG alpha filter:%8d",0);
83573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
83583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "    JNG alpha interlace:%5d",0);
83593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
83603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
83613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* Write any JNG-chunk-b profiles */
83623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) png_write_chunk_from_profile(image,"JNG-chunk-b",(int) logging);
83633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
83643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
83653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     Write leading ancillary chunks
83663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
83673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
83683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (transparent)
83693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
83703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
83713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Write JNG bKGD chunk
83723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
83733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
83743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    unsigned char
83753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      blue,
83763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      green,
83773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      red;
83783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
83793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    long
83803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      num_bytes;
83813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
83823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (jng_color_type == 8 || jng_color_type == 12)
83833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      num_bytes=6L;
83843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    else
83853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      num_bytes=10L;
83863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobMSBULong(image,(unsigned long) (num_bytes-4L));
83873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    PNGType(chunk,mng_bKGD);
83883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    LogPNGChunk((int) logging,mng_bKGD,(unsigned long) (num_bytes-4L));
83893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    red=ScaleQuantumToChar(image->background_color.red);
83903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    green=ScaleQuantumToChar(image->background_color.green);
83913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    blue=ScaleQuantumToChar(image->background_color.blue);
83923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *(chunk+4)=0;
83933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *(chunk+5)=red;
83943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *(chunk+6)=0;
83953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *(chunk+7)=green;
83963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *(chunk+8)=0;
83973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *(chunk+9)=blue;
83983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlob(image,(size_t) num_bytes,chunk);
83993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobMSBULong(image,crc32(0,chunk,(uInt) num_bytes));
84003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
84013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
84023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((image->colorspace == sRGBColorspace || image->rendering_intent))
84033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
84043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
84053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Write JNG sRGB chunk
84063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
84073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) WriteBlobMSBULong(image,1L);
84083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      PNGType(chunk,mng_sRGB);
84093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      LogPNGChunk((int) logging,mng_sRGB,1L);
84103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (image->rendering_intent != UndefinedIntent)
84113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        chunk[4]=(unsigned char) (image->rendering_intent-1);
84123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else
84133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        chunk[4]=(unsigned char) (PerceptualIntent-1);
84143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) WriteBlob(image,5,chunk);
84153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) WriteBlobMSBULong(image,crc32(0,chunk,5));
84163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
84173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
84183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
84193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (image->gamma != 0.0)
84203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
84213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /*
84223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             Write JNG gAMA chunk
84233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          */
84243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) WriteBlobMSBULong(image,4L);
84253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          PNGType(chunk,mng_gAMA);
84263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          LogPNGChunk((int) logging,mng_gAMA,4L);
84273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          PNGLong(chunk+4,(unsigned long) (100000*image->gamma+0.5));
84283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) WriteBlob(image,8,chunk);
84293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) WriteBlobMSBULong(image,crc32(0,chunk,8));
84303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
84313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if ((mng_info->equal_chrms == MagickFalse) &&
84323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (image->chromaticity.red_primary.x != 0.0))
84333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
84343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          PrimaryInfo
84353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            primary;
84363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
84373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /*
84383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             Write JNG cHRM chunk
84393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          */
84403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) WriteBlobMSBULong(image,32L);
84413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          PNGType(chunk,mng_cHRM);
84423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          LogPNGChunk((int) logging,mng_cHRM,32L);
84433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          primary=image->chromaticity.white_point;
84443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          PNGLong(chunk+4,(unsigned long) (100000*primary.x+0.5));
84453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          PNGLong(chunk+8,(unsigned long) (100000*primary.y+0.5));
84463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          primary=image->chromaticity.red_primary;
84473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          PNGLong(chunk+12,(unsigned long) (100000*primary.x+0.5));
84483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          PNGLong(chunk+16,(unsigned long) (100000*primary.y+0.5));
84493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          primary=image->chromaticity.green_primary;
84503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          PNGLong(chunk+20,(unsigned long) (100000*primary.x+0.5));
84513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          PNGLong(chunk+24,(unsigned long) (100000*primary.y+0.5));
84523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          primary=image->chromaticity.blue_primary;
84533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          PNGLong(chunk+28,(unsigned long) (100000*primary.x+0.5));
84543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          PNGLong(chunk+32,(unsigned long) (100000*primary.y+0.5));
84553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) WriteBlob(image,36,chunk);
84563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) WriteBlobMSBULong(image,crc32(0,chunk,36));
84573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
84583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
84593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->x_resolution && image->y_resolution && !mng_info->equal_physs)
84603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
84613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
84623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         Write JNG pHYs chunk
84633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
84643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) WriteBlobMSBULong(image,9L);
84653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      PNGType(chunk,mng_pHYs);
84663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      LogPNGChunk((int) logging,mng_pHYs,9L);
84673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (image->units == PixelsPerInchResolution)
84683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
84693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          PNGLong(chunk+4,(unsigned long)
84703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (image->x_resolution*100.0/2.54+0.5));
84713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          PNGLong(chunk+8,(unsigned long)
84723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (image->y_resolution*100.0/2.54+0.5));
84733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          chunk[12]=1;
84743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
84753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else
84763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
84773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (image->units == PixelsPerCentimeterResolution)
84783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
84793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              PNGLong(chunk+4,(unsigned long)
84803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (image->x_resolution*100.0+0.5));
84813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              PNGLong(chunk+8,(unsigned long)
84823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (image->y_resolution*100.0+0.5));
84833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              chunk[12]=1;
84843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
84853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          else
84863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
84873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              PNGLong(chunk+4,(unsigned long) (image->x_resolution+0.5));
84883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              PNGLong(chunk+8,(unsigned long) (image->y_resolution+0.5));
84893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              chunk[12]=0;
84903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
84913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
84923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) WriteBlob(image,13,chunk);
84933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) WriteBlobMSBULong(image,crc32(0,chunk,13));
84943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
84953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
84963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (mng_info->write_mng == 0 && (image->page.x || image->page.y))
84973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
84983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
84993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         Write JNG oFFs chunk
85003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
85013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) WriteBlobMSBULong(image,9L);
85023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      PNGType(chunk,mng_oFFs);
85033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      LogPNGChunk((int) logging,mng_oFFs,9L);
85043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      PNGsLong(chunk+4,(long) (image->page.x));
85053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      PNGsLong(chunk+8,(long) (image->page.y));
85063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      chunk[12]=0;
85073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) WriteBlob(image,13,chunk);
85083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) WriteBlobMSBULong(image,crc32(0,chunk,13));
85093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
85103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (mng_info->write_mng == 0 && (image->page.width || image->page.height))
85113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
85123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       (void) WriteBlobMSBULong(image,9L);  /* data length=8 */
85133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       PNGType(chunk,mng_vpAg);
85143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       LogPNGChunk((int) logging,mng_vpAg,9L);
85153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       PNGLong(chunk+4,(png_uint_32) image->page.width);
85163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       PNGLong(chunk+8,(png_uint_32) image->page.height);
85173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       chunk[12]=0;   /* unit = pixels */
85183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       (void) WriteBlob(image,13,chunk);
85193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       (void) WriteBlobMSBULong(image,crc32(0,chunk,13));
85203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
85213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
85223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
85233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (transparent)
85243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
85253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (jng_alpha_compression_method==0)
85263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
85273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          register long
85283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            i;
85293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
85303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          long
85313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            len;
85323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
85333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /* Write IDAT chunk header */
85343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (logging != MagickFalse)
85353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
85363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              "  Write IDAT chunks from blob, length=%lu.",
85373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (unsigned long) length);
85383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
85393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /* Copy IDAT chunks */
85403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          len=0;
85413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          p=blob+8;
85423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          for (i=8; i<(long) length; i+=len+12)
85433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
85443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            len=(*p<<24)|((*(p+1))<<16)|((*(p+2))<<8)|(*(p+3));
85453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            p+=4;
85463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (*(p)==73 && *(p+1)==68 && *(p+2)==65 && *(p+3)==84) /* IDAT */
85473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
85483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                /* Found an IDAT chunk. */
85493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) WriteBlobMSBULong(image,(unsigned long) len);
85503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                LogPNGChunk((int) logging,mng_IDAT,(unsigned long) len);
85513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) WriteBlob(image,(size_t) len+4,p);
85523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) WriteBlobMSBULong(image,
85533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    crc32(0,p,(uInt) len+4));
85543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
85553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
85563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
85573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (logging != MagickFalse)
85583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
85593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    "    Skipping %c%c%c%c chunk, length=%lu.",
85603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    *(p),*(p+1),*(p+2),*(p+3),len);
85613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
85623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            p+=(8+len);
85633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
85643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
85653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else
85663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
85673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /* Write JDAA chunk header */
85683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (logging != MagickFalse)
85693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
85703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              "  Write JDAA chunk, length=%lu.",
85713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (unsigned long) length);
85723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) WriteBlobMSBULong(image,(unsigned long) length);
85733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          PNGType(chunk,mng_JDAA);
85743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          LogPNGChunk((int) logging,mng_JDAA,length);
85753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /* Write JDAT chunk(s) data */
85763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) WriteBlob(image,4,chunk);
85773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) WriteBlob(image,length,blob);
85783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) WriteBlobMSBULong(image,crc32(crc32(0,chunk,4),blob,
85793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             (uInt) length));
85803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
85813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      blob=(unsigned char *) RelinquishMagickMemory(blob);
85823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
85833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
85843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* Encode image as a JPEG blob */
85853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
85863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
85873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      "  Creating jpeg_image_info.");
85883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  jpeg_image_info=(ImageInfo *) CloneImageInfo(image_info);
85893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (jpeg_image_info == (ImageInfo *) NULL)
85903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
85913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
85923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
85933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
85943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      "  Creating jpeg_image.");
85953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
85963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  jpeg_image=CloneImage(image,0,0,MagickTrue,&image->exception);
85973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (jpeg_image == (Image *) NULL)
85983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
85993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CopyMagickString(jpeg_image->magick,"JPEG",MaxTextExtent);
86003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
86013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) AcquireUniqueFilename(jpeg_image->filename);
86023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) FormatMagickString(jpeg_image_info->filename,MaxTextExtent,"%s",
86033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    jpeg_image->filename);
86043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
86053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=OpenBlob(jpeg_image_info,jpeg_image,WriteBinaryBlobMode,
86063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    &image->exception);
86073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
86083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
86093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
86103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      "  Created jpeg_image, %lu x %lu.",jpeg_image->columns,
86113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      jpeg_image->rows);
86123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
86133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (jng_color_type == 8 || jng_color_type == 12)
86143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    jpeg_image_info->type=GrayscaleType;
86153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  jpeg_image_info->quality=jng_quality % 1000;
86163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CopyMagickString(jpeg_image_info->magick,"JPEG",MaxTextExtent);
86173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CopyMagickString(jpeg_image->magick,"JPEG",MaxTextExtent);
86183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
86193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
86203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      "  Creating blob.");
86213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  blob=ImageToBlob(jpeg_image_info,jpeg_image,&length,&image->exception);
86223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
86233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
86243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
86253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "  Successfully read jpeg_image into a blob, length=%lu.",
86263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (unsigned long) length);
86273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
86283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
86293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "  Write JDAT chunk, length=%lu.",
86303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (unsigned long) length);
86313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
86323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* Write JDAT chunk(s) */
86333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobMSBULong(image,(unsigned long) length);
86343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  PNGType(chunk,mng_JDAT);
86353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  LogPNGChunk((int) logging,mng_JDAT,length);
86363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlob(image,4,chunk);
86373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlob(image,length,blob);
86383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobMSBULong(image,crc32(crc32(0,chunk,4),blob,(uInt) length));
86393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
86403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  jpeg_image=DestroyImage(jpeg_image);
86413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RelinquishUniqueFileResource(jpeg_image_info->filename);
86423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  jpeg_image_info=DestroyImageInfo(jpeg_image_info);
86433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  blob=(unsigned char *) RelinquishMagickMemory(blob);
86443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
86453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* Write any JNG-chunk-e profiles */
86463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) png_write_chunk_from_profile(image,"JNG-chunk-e",(int) logging);
86473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
86483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* Write IEND chunk */
86493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobMSBULong(image,0L);
86503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  PNGType(chunk,mng_IEND);
86513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  LogPNGChunk((int) logging,mng_IEND,0);
86523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlob(image,4,chunk);
86533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobMSBULong(image,crc32(0,chunk,4));
86543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
86553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
86563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
86573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      "  exit WriteOneJNGImage()");
86583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(status);
86593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
86603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
86613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
86623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
86633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
86643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
86653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
86663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
86673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   W r i t e J N G I m a g e                                                 %
86683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
86693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
86703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
86713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
86723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
86733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  WriteJNGImage() writes a JPEG Network Graphics (JNG) image file.
86743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
86753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  JNG support written by Glenn Randers-Pehrson, glennrp@image...
86763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
86773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the WriteJNGImage method is:
86783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
86793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType WriteJNGImage(const ImageInfo *image_info,Image *image)
86803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
86813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
86823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
86833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image_info: the image info.
86843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
86853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image:  The image.
86863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
86873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
86883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
86893ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType WriteJNGImage(const ImageInfo *image_info,Image *image)
86903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
86913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
86923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
86933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
86943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MngInfo
86953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *mng_info;
86963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
86973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  int
86983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    have_mng_structure;
86993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
87003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned int
87013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    logging;
87023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
87033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
87043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Open image file.
87053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
87063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info != (const ImageInfo *) NULL);
87073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info->signature == MagickSignature);
87083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (Image *) NULL);
87093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image->signature == MagickSignature);
87103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
87113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  logging=LogMagickEvent(CoderEvent,GetMagickModule(),"enter WriteJNGImage()");
87123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
87133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == MagickFalse)
87143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(status);
87153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
87163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
87173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Allocate a MngInfo structure.
87183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
87193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  have_mng_structure=MagickFalse;
872090823213d62b0ba18557e61f1e6892c6fffd6cd4cristy  mng_info=(MngInfo *) AcquireAlignedMemory(1,sizeof(MngInfo));
87213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (mng_info == (MngInfo *) NULL)
87223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
87233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
87243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Initialize members of the MngInfo structure.
87253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
87263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ResetMagickMemory(mng_info,0,sizeof(MngInfo));
87273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mng_info->image=image;
87283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  have_mng_structure=MagickTrue;
87293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
87303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlob(image,8,(const unsigned char *) "\213JNG\r\n\032\n");
87313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
87323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=WriteOneJNGImage(mng_info,image_info,image);
87333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloseBlob(image);
87343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
87353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CatchImageException(image);
87363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MngInfoFreeStruct(mng_info,&have_mng_structure);
87373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
87383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(CoderEvent,GetMagickModule(),"exit WriteJNGImage()");
87393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(status);
87403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
87413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
87423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
87433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
87443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
87453ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType WriteMNGImage(const ImageInfo *image_info,Image *image)
87463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
87473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const char
87483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *option;
87493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
87503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
87513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *next_image;
87523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
87533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
87543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
87553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
87563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MngInfo
87573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *mng_info;
87583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
87593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  int
87603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    have_mng_structure,
87613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image_count,
87623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    need_iterations,
87633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    need_matte;
87643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
87653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  volatile int
87663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) || \
87673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    defined(PNG_MNG_FEATURES_SUPPORTED)
87683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    need_local_plte,
87693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
87703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    all_images_are_gray,
87713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    logging,
87723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    need_defi,
87733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    optimize,
87743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    use_global_plte;
87753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
87763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register long
87773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i;
87783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
87793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned char
87803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    chunk[800];
87813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
87823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  volatile unsigned int
87833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    write_jng,
87843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    write_mng;
87853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
87863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  volatile unsigned long
87873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    scene;
87883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
87893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned long
87903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    final_delay=0,
87913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    initial_delay;
87923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8793c451207335b7a8bb4e44f904f3d65a2727e41214glennrp#if (PNG_LIBPNG_VER < 10200)
87943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (image_info->verbose)
87953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      printf("Your PNG library (libpng-%s) is rather old.\n",
87963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         PNG_LIBPNG_VER_STRING);
87973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
87983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
87993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
88003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Open image file.
88013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
88023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info != (const ImageInfo *) NULL);
88033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info->signature == MagickSignature);
88043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (Image *) NULL);
88053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image->signature == MagickSignature);
88063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
88073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  logging=LogMagickEvent(CoderEvent,GetMagickModule(),"enter WriteMNGImage()");
88083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
88093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == MagickFalse)
88103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(status);
88113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
88123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
88133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Allocate a MngInfo structure.
88143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
88153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  have_mng_structure=MagickFalse;
881690823213d62b0ba18557e61f1e6892c6fffd6cd4cristy  mng_info=(MngInfo *) AcquireAlignedMemory(1,sizeof(MngInfo));
88173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (mng_info == (MngInfo *) NULL)
88183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
88193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
88203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Initialize members of the MngInfo structure.
88213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
88223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ResetMagickMemory(mng_info,0,sizeof(MngInfo));
88233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mng_info->image=image;
88243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  have_mng_structure=MagickTrue;
88253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  write_mng=LocaleCompare(image_info->magick,"MNG") == 0;
88263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
88273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
88283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   * See if user has requested a specific PNG subformat to be used
88293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   * for all of the PNGs in the MNG being written, e.g.,
88303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   *
88313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   *    convert *.png png8:animation.mng
88323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   *
88333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   * To do: check -define png:bit_depth and png:color_type as well,
88343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   * or perhaps use mng:bit_depth and mng:color_type instead for
88353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   * global settings.
88363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   */
88373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
88383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mng_info->write_png8=LocaleCompare(image_info->magick,"PNG8") == 0;
88393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mng_info->write_png24=LocaleCompare(image_info->magick,"PNG24") == 0;
88403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mng_info->write_png32=LocaleCompare(image_info->magick,"PNG32") == 0;
88413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
88423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  write_jng=MagickFalse;
88433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_info->compression == JPEGCompression)
88443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    write_jng=MagickTrue;
88453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
88463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mng_info->adjoin=image_info->adjoin &&
88473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (GetNextImageInList(image) != (Image *) NULL) && write_mng;
88483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
88493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (mng_info->write_png8 || mng_info->write_png24 || mng_info->write_png32)
88503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    optimize=MagickFalse;
88513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
88523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    optimize=(image_info->type == OptimizeType || image_info->type ==
88533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      UndefinedType);
88543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
88553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
88563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
88573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /* Log some info about the input */
88583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Image
88593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *p;
88603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
88613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
88623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "  Checking input image(s)");
88633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (optimize)
88643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
88653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "    Optimize: TRUE");
88663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else
88673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
88683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "    Optimize: FALSE");
88693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
88703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "    Image_info depth: %ld",image_info->depth);
88713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
88723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        "    Type: %d",image_info->type);
88733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
88743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      scene=0;
88753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (p=image; p != (Image *) NULL; p=GetNextImageInList(p))
88763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
88773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
88783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "    Scene: %ld",scene++);
88793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
88803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "      Image depth: %lu",p->depth);
88813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (p->matte)
88823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
88833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            "      Matte: True");
88843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        else
88853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
88863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            "      Matte: False");
88873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (p->storage_class == PseudoClass)
88883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
88893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            "      Storage class: PseudoClass");
88903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        else
88913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
88923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            "      Storage class: DirectClass");
88933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (p->colors)
88943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
88953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            "      Number of colors: %lu",p->colors);
88963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        else
88973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
88983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            "      Number of colors: unspecified");
88993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (mng_info->adjoin == MagickFalse)
89003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
89013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
89023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
89033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
89043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
89053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Sometimes we get PseudoClass images whose RGB values don't match
89063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    the colors in the colormap.  This code syncs the RGB values.
89073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
89083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
89093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Image
89103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      *p;
89113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
89123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    for (p=image; p != (Image *) NULL; p=GetNextImageInList(p))
89133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
89143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (p->taint && p->storage_class == PseudoClass)
89153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (void) SyncImage(p);
89163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (mng_info->adjoin == MagickFalse)
89173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        break;
89183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
89193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
89203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
89213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#ifdef PNG_BUILD_PALETTE
89223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (optimize)
89233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
89243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
89253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Sometimes we get DirectClass images that have 256 colors or fewer.
89263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        This code will convert them to PseudoClass and build a colormap.
89273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
89283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Image
89293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *p;
89303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
89313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (p=image; p != (Image *) NULL; p=GetNextImageInList(p))
89323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
89333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (p->storage_class != PseudoClass)
89343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
89353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            p->colors=GetNumberColors(p,(FILE *) NULL,&p->exception);
89363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (p->colors <= 256)
89373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
89383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                p->colors=0;
89393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (p->matte != MagickFalse)
89403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    (void) SetImageType(p,PaletteMatteType);
89413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                else
89423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    (void) SetImageType(p,PaletteType);
89433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
89443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
89453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (mng_info->adjoin == MagickFalse)
89463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
89473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
89483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
89493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
89503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
89513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  use_global_plte=MagickFalse;
89523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  all_images_are_gray=MagickFalse;
89533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#ifdef PNG_WRITE_EMPTY_PLTE_SUPPORTED
89543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  need_local_plte=MagickTrue;
89553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
89563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  need_defi=MagickFalse;
89573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  need_matte=MagickFalse;
89583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mng_info->framing_mode=1;
89593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mng_info->old_framing_mode=1;
89603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
89613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (write_mng)
89623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (image_info->page != (char *) NULL)
89633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
89643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /*
89653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            Determine image bounding box.
89663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          */
89673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          SetGeometry(image,&mng_info->page);
89683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) ParseMetaGeometry(image_info->page,&mng_info->page.x,
89693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            &mng_info->page.y,&mng_info->page.width,&mng_info->page.height);
89703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
89713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (write_mng)
89723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
89733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      unsigned int
89743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        need_geom;
89753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
89763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      unsigned short
89773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        red,
89783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        green,
89793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        blue;
89803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
89813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mng_info->page=image->page;
89823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      need_geom=MagickTrue;
89833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (mng_info->page.width || mng_info->page.height)
89843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         need_geom=MagickFalse;
89853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
89863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Check all the scenes.
89873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
89883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      initial_delay=image->delay;
89893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      need_iterations=MagickFalse;
89903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mng_info->equal_chrms=image->chromaticity.red_primary.x != 0.0;
89913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mng_info->equal_physs=MagickTrue,
89923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mng_info->equal_gammas=MagickTrue;
89933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mng_info->equal_srgbs=MagickTrue;
89943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mng_info->equal_backgrounds=MagickTrue;
89953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image_count=0;
89963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) || \
89973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    defined(PNG_MNG_FEATURES_SUPPORTED)
89983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      all_images_are_gray=MagickTrue;
89993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mng_info->equal_palettes=MagickFalse;
90003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      need_local_plte=MagickFalse;
90013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
90023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (next_image=image; next_image != (Image *) NULL; )
90033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
90043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (need_geom)
90053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
90063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if ((next_image->columns+next_image->page.x) > mng_info->page.width)
90073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_info->page.width=next_image->columns+next_image->page.x;
90083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if ((next_image->rows+next_image->page.y) > mng_info->page.height)
90093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_info->page.height=next_image->rows+next_image->page.y;
90103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
90113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (next_image->page.x || next_image->page.y)
90123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          need_defi=MagickTrue;
90133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (next_image->matte)
90143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          need_matte=MagickTrue;
90153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if ((int) next_image->dispose >= BackgroundDispose)
90163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (next_image->matte || next_image->page.x || next_image->page.y ||
90173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              ((next_image->columns < mng_info->page.width) &&
90183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               (next_image->rows < mng_info->page.height)))
90193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_info->need_fram=MagickTrue;
90203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (next_image->iterations)
90213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          need_iterations=MagickTrue;
90223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        final_delay=next_image->delay;
90233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (final_delay != initial_delay || final_delay > 1UL*
90243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           next_image->ticks_per_second)
90253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          mng_info->need_fram=1;
90263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) || \
90273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    defined(PNG_MNG_FEATURES_SUPPORTED)
90283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
90293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          check for global palette possibility.
90303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
90313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (image->matte != MagickFalse)
90323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           need_local_plte=MagickTrue;
90333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (need_local_plte == 0)
90343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
90353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (ImageIsGray(image) == MagickFalse)
90363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              all_images_are_gray=MagickFalse;
90373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_info->equal_palettes=PalettesAreEqual(image,next_image);
90383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (use_global_plte == 0)
90393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              use_global_plte=mng_info->equal_palettes;
90403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            need_local_plte=!mng_info->equal_palettes;
90413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
90423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
90433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (GetNextImageInList(next_image) != (Image *) NULL)
90443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
90453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (next_image->background_color.red !=
90463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                next_image->next->background_color.red ||
90473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                next_image->background_color.green !=
90483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                next_image->next->background_color.green ||
90493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                next_image->background_color.blue !=
90503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                next_image->next->background_color.blue)
90513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_info->equal_backgrounds=MagickFalse;
90523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (next_image->gamma != next_image->next->gamma)
90533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_info->equal_gammas=MagickFalse;
90543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (next_image->rendering_intent !=
90553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                next_image->next->rendering_intent)
90563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_info->equal_srgbs=MagickFalse;
90573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if ((next_image->units != next_image->next->units) ||
90583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (next_image->x_resolution != next_image->next->x_resolution) ||
90593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (next_image->y_resolution != next_image->next->y_resolution))
90603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              mng_info->equal_physs=MagickFalse;
90613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (mng_info->equal_chrms)
90623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
90633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (next_image->chromaticity.red_primary.x !=
90643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    next_image->next->chromaticity.red_primary.x ||
90653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    next_image->chromaticity.red_primary.y !=
90663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    next_image->next->chromaticity.red_primary.y ||
90673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    next_image->chromaticity.green_primary.x !=
90683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    next_image->next->chromaticity.green_primary.x ||
90693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    next_image->chromaticity.green_primary.y !=
90703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    next_image->next->chromaticity.green_primary.y ||
90713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    next_image->chromaticity.blue_primary.x !=
90723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    next_image->next->chromaticity.blue_primary.x ||
90733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    next_image->chromaticity.blue_primary.y !=
90743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    next_image->next->chromaticity.blue_primary.y ||
90753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    next_image->chromaticity.white_point.x !=
90763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    next_image->next->chromaticity.white_point.x ||
90773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    next_image->chromaticity.white_point.y !=
90783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    next_image->next->chromaticity.white_point.y)
90793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  mng_info->equal_chrms=MagickFalse;
90803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
90813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
90823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image_count++;
90833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        next_image=GetNextImageInList(next_image);
90843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
90853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (image_count < 2)
90863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
90873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          mng_info->equal_backgrounds=MagickFalse;
90883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          mng_info->equal_chrms=MagickFalse;
90893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          mng_info->equal_gammas=MagickFalse;
90903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          mng_info->equal_srgbs=MagickFalse;
90913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          mng_info->equal_physs=MagickFalse;
90923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          use_global_plte=MagickFalse;
90933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#ifdef PNG_WRITE_EMPTY_PLTE_SUPPORTED
90943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          need_local_plte=MagickTrue;
90953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
90963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          need_iterations=MagickFalse;
90973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
90983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     if (mng_info->need_fram == MagickFalse)
90993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       {
91003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         /*
91013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           Only certain framing rates 100/n are exactly representable without
91023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           the FRAM chunk but we'll allow some slop in VLC files
91033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         */
91043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         if (final_delay == 0)
91053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           {
91063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             if (need_iterations != MagickFalse)
91073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               {
91083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                 /*
91093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   It's probably a GIF with loop; don't run it *too* fast.
91103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                 */
91113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                 final_delay=10;
91123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                 (void) ThrowMagickException(&image->exception,
91133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    GetMagickModule(),CoderError,
91143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   "input has zero delay between all frames; assuming 10 cs",
91153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   "`%s'","");
91163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               }
91173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             else
91183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               mng_info->ticks_per_second=0;
91193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           }
91203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         if (final_delay != 0)
91213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           mng_info->ticks_per_second=1UL*image->ticks_per_second/final_delay;
91223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         if (final_delay > 50)
91233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           mng_info->ticks_per_second=2;
91243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         if (final_delay > 75)
91253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           mng_info->ticks_per_second=1;
91263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         if (final_delay > 125)
91273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           mng_info->need_fram=MagickTrue;
91283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         if (need_defi && final_delay > 2 && (final_delay != 4) &&
91293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (final_delay != 5) && (final_delay != 10) && (final_delay != 20) &&
91303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (final_delay != 25) && (final_delay != 50) && (final_delay !=
91313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               1UL*image->ticks_per_second))
91323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           mng_info->need_fram=MagickTrue;  /* make it exact; cannot be VLC */
91333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       }
91343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     if (mng_info->need_fram != MagickFalse)
91353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        mng_info->ticks_per_second=1UL*image->ticks_per_second;
91363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     /*
91373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        If pseudocolor, we should also check to see if all the
91383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        palettes are identical and write a global PLTE if they are.
91393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ../glennrp Feb 99.
91403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     */
91413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     /*
91423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Write the MNG version 1.0 signature and MHDR chunk.
91433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     */
91443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     (void) WriteBlob(image,8,(const unsigned char *) "\212MNG\r\n\032\n");
91453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     (void) WriteBlobMSBULong(image,28L);  /* chunk data length=28 */
91463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     PNGType(chunk,mng_MHDR);
91473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     LogPNGChunk((int) logging,mng_MHDR,28L);
91483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     PNGLong(chunk+4,mng_info->page.width);
91493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     PNGLong(chunk+8,mng_info->page.height);
91503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     PNGLong(chunk+12,mng_info->ticks_per_second);
91513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     PNGLong(chunk+16,0L);  /* layer count=unknown */
91523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     PNGLong(chunk+20,0L);  /* frame count=unknown */
91533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     PNGLong(chunk+24,0L);  /* play time=unknown   */
91543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     if (write_jng)
91553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       {
91563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         if (need_matte)
91573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           {
91583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             if (need_defi || mng_info->need_fram || use_global_plte)
91593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               PNGLong(chunk+28,27L);    /* simplicity=LC+JNG */
91603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             else
91613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               PNGLong(chunk+28,25L);    /* simplicity=VLC+JNG */
91623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           }
91633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         else
91643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           {
91653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             if (need_defi || mng_info->need_fram || use_global_plte)
91663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               PNGLong(chunk+28,19L);  /* simplicity=LC+JNG, no transparency */
91673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             else
91683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               PNGLong(chunk+28,17L);  /* simplicity=VLC+JNG, no transparency */
91693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           }
91703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       }
91713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     else
91723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       {
91733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         if (need_matte)
91743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           {
91753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             if (need_defi || mng_info->need_fram || use_global_plte)
91763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               PNGLong(chunk+28,11L);    /* simplicity=LC */
91773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             else
91783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               PNGLong(chunk+28,9L);    /* simplicity=VLC */
91793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           }
91803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         else
91813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           {
91823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             if (need_defi || mng_info->need_fram || use_global_plte)
91833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               PNGLong(chunk+28,3L);    /* simplicity=LC, no transparency */
91843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             else
91853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               PNGLong(chunk+28,1L);    /* simplicity=VLC, no transparency */
91863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           }
91873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       }
91883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     (void) WriteBlob(image,32,chunk);
91893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     (void) WriteBlobMSBULong(image,crc32(0,chunk,32));
91903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     option=GetImageOption(image_info,"mng:need-cacheoff");
91913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     if (option != (const char *) NULL)
91923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       {
91933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         size_t
91943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           length;
91953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
91963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         /*
91973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           Write "nEED CACHEOFF" to turn playback caching off for streaming MNG.
91983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         */
91993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         PNGType(chunk,mng_nEED);
92003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         length=CopyMagickString((char *) chunk+4,"CACHEOFF",20);
92013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (void) WriteBlobMSBULong(image,(unsigned long) length);
92023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         LogPNGChunk((int) logging,mng_nEED,(unsigned long) length);
92033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         length+=4;
92043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (void) WriteBlob(image,length,chunk);
92053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (void) WriteBlobMSBULong(image,crc32(0,chunk,(uInt) length));
92063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       }
92073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     if ((GetPreviousImageInList(image) == (Image *) NULL) &&
92083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (GetNextImageInList(image) != (Image *) NULL) &&
92093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (image->iterations != 1))
92103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       {
92113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         /*
92123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           Write MNG TERM chunk
92133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         */
92143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (void) WriteBlobMSBULong(image,10L);  /* data length=10 */
92153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         PNGType(chunk,mng_TERM);
92163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         LogPNGChunk((int) logging,mng_TERM,10L);
92173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         chunk[4]=3;  /* repeat animation */
92183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         chunk[5]=0;  /* show last frame when done */
92193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         PNGLong(chunk+6,(png_uint_32) (mng_info->ticks_per_second*
92203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            final_delay/MagickMax(image->ticks_per_second,1)));
92213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         if (image->iterations == 0)
92223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           PNGLong(chunk+10,PNG_UINT_31_MAX);
92233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         else
92243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           PNGLong(chunk+10,(png_uint_32) image->iterations);
92253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         if (logging != MagickFalse)
92263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           {
92273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
92283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               "     TERM delay: %lu",
92293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               (png_uint_32) (mng_info->ticks_per_second*
92303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  final_delay/MagickMax(image->ticks_per_second,1)));
92313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             if (image->iterations == 0)
92323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
92333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                 "     TERM iterations: %lu",PNG_UINT_31_MAX);
92343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             else
92353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
92363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                 "     Image iterations: %lu",image->iterations);
92373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           }
92383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (void) WriteBlob(image,14,chunk);
92393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (void) WriteBlobMSBULong(image,crc32(0,chunk,14));
92403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       }
92413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     /*
92423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       To do: check for cHRM+gAMA == sRGB, and write sRGB instead.
92433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     */
92443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     if ((image->colorspace == sRGBColorspace || image->rendering_intent) &&
92453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          mng_info->equal_srgbs)
92463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       {
92473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         /*
92483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           Write MNG sRGB chunk
92493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         */
92503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (void) WriteBlobMSBULong(image,1L);
92513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         PNGType(chunk,mng_sRGB);
92523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         LogPNGChunk((int) logging,mng_sRGB,1L);
92533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         if (image->rendering_intent != UndefinedIntent)
92543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           chunk[4]=(unsigned char) (image->rendering_intent-1);
92553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         else
92563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           chunk[4]=(unsigned char) (PerceptualIntent-1);
92573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (void) WriteBlob(image,5,chunk);
92583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (void) WriteBlobMSBULong(image,crc32(0,chunk,5));
92593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         mng_info->have_write_global_srgb=MagickTrue;
92603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       }
92613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     else
92623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       {
92633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         if (image->gamma && mng_info->equal_gammas)
92643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           {
92653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             /*
92663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                Write MNG gAMA chunk
92673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             */
92683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             (void) WriteBlobMSBULong(image,4L);
92693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             PNGType(chunk,mng_gAMA);
92703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             LogPNGChunk((int) logging,mng_gAMA,4L);
92713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             PNGLong(chunk+4,(unsigned long) (100000*image->gamma+0.5));
92723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             (void) WriteBlob(image,8,chunk);
92733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             (void) WriteBlobMSBULong(image,crc32(0,chunk,8));
92743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             mng_info->have_write_global_gama=MagickTrue;
92753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           }
92763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         if (mng_info->equal_chrms)
92773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           {
92783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             PrimaryInfo
92793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               primary;
92803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
92813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             /*
92823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                Write MNG cHRM chunk
92833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             */
92843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             (void) WriteBlobMSBULong(image,32L);
92853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             PNGType(chunk,mng_cHRM);
92863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             LogPNGChunk((int) logging,mng_cHRM,32L);
92873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             primary=image->chromaticity.white_point;
92883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             PNGLong(chunk+4,(unsigned long) (100000*primary.x+0.5));
92893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             PNGLong(chunk+8,(unsigned long) (100000*primary.y+0.5));
92903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             primary=image->chromaticity.red_primary;
92913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             PNGLong(chunk+12,(unsigned long) (100000*primary.x+0.5));
92923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             PNGLong(chunk+16,(unsigned long) (100000*primary.y+0.5));
92933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             primary=image->chromaticity.green_primary;
92943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             PNGLong(chunk+20,(unsigned long) (100000*primary.x+0.5));
92953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             PNGLong(chunk+24,(unsigned long) (100000*primary.y+0.5));
92963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             primary=image->chromaticity.blue_primary;
92973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             PNGLong(chunk+28,(unsigned long) (100000*primary.x+0.5));
92983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             PNGLong(chunk+32,(unsigned long) (100000*primary.y+0.5));
92993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             (void) WriteBlob(image,36,chunk);
93003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             (void) WriteBlobMSBULong(image,crc32(0,chunk,36));
93013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             mng_info->have_write_global_chrm=MagickTrue;
93023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           }
93033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       }
93043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     if (image->x_resolution && image->y_resolution && mng_info->equal_physs)
93053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       {
93063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         /*
93073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            Write MNG pHYs chunk
93083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         */
93093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (void) WriteBlobMSBULong(image,9L);
93103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         PNGType(chunk,mng_pHYs);
93113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         LogPNGChunk((int) logging,mng_pHYs,9L);
93123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         if (image->units == PixelsPerInchResolution)
93133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           {
93143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             PNGLong(chunk+4,(unsigned long)
93153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               (image->x_resolution*100.0/2.54+0.5));
93163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             PNGLong(chunk+8,(unsigned long)
93173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               (image->y_resolution*100.0/2.54+0.5));
93183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             chunk[12]=1;
93193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           }
93203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         else
93213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           {
93223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             if (image->units == PixelsPerCentimeterResolution)
93233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               {
93243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                 PNGLong(chunk+4,(unsigned long)
93253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   (image->x_resolution*100.0+0.5));
93263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                 PNGLong(chunk+8,(unsigned long)
93273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   (image->y_resolution*100.0+0.5));
93283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                 chunk[12]=1;
93293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               }
93303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             else
93313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               {
93323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                 PNGLong(chunk+4,(unsigned long) (image->x_resolution+0.5));
93333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                 PNGLong(chunk+8,(unsigned long) (image->y_resolution+0.5));
93343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                 chunk[12]=0;
93353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               }
93363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           }
93373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (void) WriteBlob(image,13,chunk);
93383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (void) WriteBlobMSBULong(image,crc32(0,chunk,13));
93393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       }
93403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     /*
93413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       Write MNG BACK chunk and global bKGD chunk, if the image is transparent
93423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       or does not cover the entire frame.
93433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     */
93443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     if (write_mng && (image->matte || image->page.x > 0 ||
93453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         image->page.y > 0 || (image->page.width &&
93463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (image->page.width+image->page.x < mng_info->page.width))
93473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         || (image->page.height && (image->page.height+image->page.y
93483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         < mng_info->page.height))))
93493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       {
93503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (void) WriteBlobMSBULong(image,6L);
93513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         PNGType(chunk,mng_BACK);
93523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         LogPNGChunk((int) logging,mng_BACK,6L);
93533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         red=ScaleQuantumToShort(image->background_color.red);
93543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         green=ScaleQuantumToShort(image->background_color.green);
93553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         blue=ScaleQuantumToShort(image->background_color.blue);
93563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         PNGShort(chunk+4,red);
93573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         PNGShort(chunk+6,green);
93583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         PNGShort(chunk+8,blue);
93593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (void) WriteBlob(image,10,chunk);
93603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (void) WriteBlobMSBULong(image,crc32(0,chunk,10));
93613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         if (mng_info->equal_backgrounds)
93623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           {
93633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             (void) WriteBlobMSBULong(image,6L);
93643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             PNGType(chunk,mng_bKGD);
93653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             LogPNGChunk((int) logging,mng_bKGD,6L);
93663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             (void) WriteBlob(image,10,chunk);
93673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             (void) WriteBlobMSBULong(image,crc32(0,chunk,10));
93683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           }
93693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       }
93703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
93713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#ifdef PNG_WRITE_EMPTY_PLTE_SUPPORTED
93723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     if ((need_local_plte == MagickFalse) &&
93733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (image->storage_class == PseudoClass) &&
93743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (all_images_are_gray == MagickFalse))
93753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       {
93763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         unsigned long
93773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           data_length;
93783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
93793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         /*
93803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           Write MNG PLTE chunk
93813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         */
93823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         data_length=3*image->colors;
93833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (void) WriteBlobMSBULong(image,data_length);
93843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         PNGType(chunk,mng_PLTE);
93853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         LogPNGChunk((int) logging,mng_PLTE,data_length);
93863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         for (i=0; i < (long) image->colors; i++)
93873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         {
93883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           chunk[4+i*3]=ScaleQuantumToChar(image->colormap[i].red) & 0xff;
93893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           chunk[5+i*3]=ScaleQuantumToChar(image->colormap[i].green) & 0xff;
93903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           chunk[6+i*3]=ScaleQuantumToChar(image->colormap[i].blue) & 0xff;
93913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         }
93923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (void) WriteBlob(image,data_length+4,chunk);
93933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (void) WriteBlobMSBULong(image,crc32(0,chunk,(uInt) (data_length+4)));
93943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         mng_info->have_write_global_plte=MagickTrue;
93953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       }
93963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
93973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
93983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  scene=0;
93993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mng_info->delay=0;
94003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) || \
94013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    defined(PNG_MNG_FEATURES_SUPPORTED)
94023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  mng_info->equal_palettes=MagickFalse;
94033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
94043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  do
94053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
94063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (mng_info->adjoin)
94073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
94083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) || \
94093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    defined(PNG_MNG_FEATURES_SUPPORTED)
94103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
94113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      If we aren't using a global palette for the entire MNG, check to
94123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      see if we can use one for two or more consecutive images.
94133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
94143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (need_local_plte && use_global_plte && !all_images_are_gray)
94153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
94163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (mng_info->IsPalette)
94173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
94183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
94193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              When equal_palettes is true, this image has the same palette
94203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              as the previous PseudoClass image
94213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
94223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_info->have_write_global_plte=mng_info->equal_palettes;
94233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            mng_info->equal_palettes=PalettesAreEqual(image,image->next);
94243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (mng_info->equal_palettes && !mng_info->have_write_global_plte)
94253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
94263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                /*
94273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  Write MNG PLTE chunk
94283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                */
94293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                unsigned long
94303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  data_length;
94313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
94323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                data_length=3*image->colors;
94333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) WriteBlobMSBULong(image,data_length);
94343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                PNGType(chunk,mng_PLTE);
94353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                LogPNGChunk((int) logging,mng_PLTE,data_length);
94363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                for (i=0; i < (long) image->colors; i++)
94373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
94383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  chunk[4+i*3]=ScaleQuantumToChar(image->colormap[i].red);
94393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  chunk[5+i*3]=ScaleQuantumToChar(image->colormap[i].green);
94403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  chunk[6+i*3]=ScaleQuantumToChar(image->colormap[i].blue);
94413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
94423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) WriteBlob(image,data_length+4,chunk);
94433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) WriteBlobMSBULong(image,crc32(0,chunk,
94443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   (uInt) (data_length+4)));
94453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                mng_info->have_write_global_plte=MagickTrue;
94463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
94473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
94483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        else
94493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          mng_info->have_write_global_plte=MagickFalse;
94503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
94513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
94523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (need_defi)
94533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
94543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        long
94553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          previous_x,
94563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          previous_y;
94573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
94583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (scene)
94593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
94603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            previous_x=mng_info->page.x;
94613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            previous_y=mng_info->page.y;
94623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
94633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        else
94643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
94653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            previous_x=0;
94663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            previous_y=0;
94673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
94683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        mng_info->page=image->page;
94693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if ((mng_info->page.x !=  previous_x) ||
94703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (mng_info->page.y != previous_y))
94713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
94723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             (void) WriteBlobMSBULong(image,12L);  /* data length=12 */
94733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             PNGType(chunk,mng_DEFI);
94743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             LogPNGChunk((int) logging,mng_DEFI,12L);
94753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             chunk[4]=0; /* object 0 MSB */
94763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             chunk[5]=0; /* object 0 LSB */
94773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             chunk[6]=0; /* visible  */
94783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             chunk[7]=0; /* abstract */
94793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             PNGLong(chunk+8,(png_uint_32) mng_info->page.x);
94803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             PNGLong(chunk+12,(png_uint_32) mng_info->page.y);
94813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             (void) WriteBlob(image,16,chunk);
94823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             (void) WriteBlobMSBULong(image,crc32(0,chunk,16));
94833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
94843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
94853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
94863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
94873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   mng_info->write_mng=write_mng;
94883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
94893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   if ((int) image->dispose >= 3)
94903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     mng_info->framing_mode=3;
94913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
94923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   if (mng_info->need_fram && mng_info->adjoin &&
94933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       ((image->delay != mng_info->delay) ||
94943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (mng_info->framing_mode != mng_info->old_framing_mode)))
94953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     {
94963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       if (image->delay == mng_info->delay)
94973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         {
94983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           /*
94993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             Write a MNG FRAM chunk with the new framing mode.
95003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           */
95013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           (void) WriteBlobMSBULong(image,1L);  /* data length=1 */
95023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           PNGType(chunk,mng_FRAM);
95033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           LogPNGChunk((int) logging,mng_FRAM,1L);
95043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           chunk[4]=(unsigned char) mng_info->framing_mode;
95053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           (void) WriteBlob(image,5,chunk);
95063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           (void) WriteBlobMSBULong(image,crc32(0,chunk,5));
95073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         }
95083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       else
95093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         {
95103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           /*
95113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             Write a MNG FRAM chunk with the delay.
95123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           */
95133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           (void) WriteBlobMSBULong(image,10L);  /* data length=10 */
95143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           PNGType(chunk,mng_FRAM);
95153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           LogPNGChunk((int) logging,mng_FRAM,10L);
95163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           chunk[4]=(unsigned char) mng_info->framing_mode;
95173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           chunk[5]=0;  /* frame name separator (no name) */
95183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           chunk[6]=2;  /* flag for changing default delay */
95193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           chunk[7]=0;  /* flag for changing frame timeout */
95203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           chunk[8]=0;  /* flag for changing frame clipping */
95213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           chunk[9]=0;  /* flag for changing frame sync_id */
95223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           PNGLong(chunk+10,(png_uint_32)
95233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             ((mng_info->ticks_per_second*
95243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy             image->delay)/MagickMax(image->ticks_per_second,1)));
95253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           (void) WriteBlob(image,14,chunk);
95263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           (void) WriteBlobMSBULong(image,crc32(0,chunk,14));
95273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           mng_info->delay=image->delay;
95283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         }
95293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       mng_info->old_framing_mode=mng_info->framing_mode;
95303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     }
95313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
95323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(JNG_SUPPORTED)
95333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   if (image_info->compression == JPEGCompression)
95343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     {
95353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       ImageInfo
95363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         *write_info;
95373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
95383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       if (logging != MagickFalse)
95393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
95403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           "  Writing JNG object.");
95413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       /* To do: specify the desired alpha compression method. */
95423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       write_info=CloneImageInfo(image_info);
95433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       write_info->compression=UndefinedCompression;
95443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       status=WriteOneJNGImage(mng_info,write_info,image);
95453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       write_info=DestroyImageInfo(write_info);
95463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     }
95473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   else
95483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
95493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     {
95503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       if (logging != MagickFalse)
95513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
95523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           "  Writing PNG object.");
95533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       status=WriteOnePNGImage(mng_info,image_info,image);
95543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     }
95553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
95563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (status == MagickFalse)
95573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
95583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        MngInfoFreeStruct(mng_info,&have_mng_structure);
95593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) CloseBlob(image);
95603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        return(MagickFalse);
95613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
95623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) CatchImageException(image);
95633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (GetNextImageInList(image) == (Image *) NULL)
95643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
95653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image=SyncNextImageInList(image);
95663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status=SetImageProgress(image,SaveImagesTag,scene++,
95673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      GetImageListLength(image));
95683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (status == MagickFalse)
95693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
95703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  } while (mng_info->adjoin);
95713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (write_mng)
95723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
95733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      while (GetPreviousImageInList(image) != (Image *) NULL)
95743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image=GetPreviousImageInList(image);
95753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
95763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Write the MEND chunk.
95773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
95783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) WriteBlobMSBULong(image,0x00000000L);
95793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      PNGType(chunk,mng_MEND);
95803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      LogPNGChunk((int) logging,mng_MEND,0L);
95813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) WriteBlob(image,4,chunk);
95823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) WriteBlobMSBULong(image,crc32(0,chunk,4));
95833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
95843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
95853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Relinquish resources.
95863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
95873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloseBlob(image);
95883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MngInfoFreeStruct(mng_info,&have_mng_structure);
95893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (logging != MagickFalse)
95903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(CoderEvent,GetMagickModule(),"exit WriteMNGImage()");
95913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickTrue);
95923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
9593c451207335b7a8bb4e44f904f3d65a2727e41214glennrp#else /* PNG_LIBPNG_VER > 10011 */
95943ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType WritePNGImage(const ImageInfo *image_info,Image *image)
95953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
95963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image=image;
95973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  printf("Your PNG library is too old: You have libpng-%s\n",
95983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     PNG_LIBPNG_VER_STRING);
95993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ThrowBinaryException(CoderError,"PNG library is too old",
96003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     image_info->filename);
96013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
96023ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType WriteMNGImage(const ImageInfo *image_info,Image *image)
96033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
96043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(WritePNGImage(image_info,image));
96053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
9606c451207335b7a8bb4e44f904f3d65a2727e41214glennrp#endif /* PNG_LIBPNG_VER > 10011 */
96073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
9608