added libimago
[eradicate] / libs / imago / libpng / pngread.c
diff --git a/libs/imago/libpng/pngread.c b/libs/imago/libpng/pngread.c
new file mode 100644 (file)
index 0000000..dbda812
--- /dev/null
@@ -0,0 +1,1459 @@
+\r
+/* pngread.c - read a PNG file\r
+ *\r
+ * Last changed in libpng 1.2.30 [August 15, 2008]\r
+ * For conditions of distribution and use, see copyright notice in png.h\r
+ * Copyright (c) 1998-2008 Glenn Randers-Pehrson\r
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)\r
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)\r
+ *\r
+ * This file contains routines that an application calls directly to\r
+ * read a PNG file or stream.\r
+ */\r
+\r
+#define PNG_INTERNAL\r
+#include "png.h"\r
+#if defined(PNG_READ_SUPPORTED)\r
+\r
+/* Create a PNG structure for reading, and allocate any memory needed. */\r
+png_structp PNGAPI\r
+png_create_read_struct(png_const_charp user_png_ver, png_voidp error_ptr,\r
+   png_error_ptr error_fn, png_error_ptr warn_fn)\r
+{\r
+\r
+#ifdef PNG_USER_MEM_SUPPORTED\r
+   return (png_create_read_struct_2(user_png_ver, error_ptr, error_fn,\r
+      warn_fn, png_voidp_NULL, png_malloc_ptr_NULL, png_free_ptr_NULL));\r
+}\r
+\r
+/* Alternate create PNG structure for reading, and allocate any memory needed. */\r
+png_structp PNGAPI\r
+png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,\r
+   png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,\r
+   png_malloc_ptr malloc_fn, png_free_ptr free_fn)\r
+{\r
+#endif /* PNG_USER_MEM_SUPPORTED */\r
+\r
+#ifdef PNG_SETJMP_SUPPORTED\r
+   volatile\r
+#endif\r
+   png_structp png_ptr;\r
+\r
+#ifdef PNG_SETJMP_SUPPORTED\r
+#ifdef USE_FAR_KEYWORD\r
+   jmp_buf jmpbuf;\r
+#endif\r
+#endif\r
+\r
+   int i;\r
+\r
+   png_debug(1, "in png_create_read_struct\n");\r
+#ifdef PNG_USER_MEM_SUPPORTED\r
+   png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,\r
+      (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr);\r
+#else\r
+   png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);\r
+#endif\r
+   if (png_ptr == NULL)\r
+      return (NULL);\r
+\r
+   /* added at libpng-1.2.6 */\r
+#ifdef PNG_SET_USER_LIMITS_SUPPORTED\r
+   png_ptr->user_width_max=PNG_USER_WIDTH_MAX;\r
+   png_ptr->user_height_max=PNG_USER_HEIGHT_MAX;\r
+#endif\r
+\r
+#ifdef PNG_SETJMP_SUPPORTED\r
+#ifdef USE_FAR_KEYWORD\r
+   if (setjmp(jmpbuf))\r
+#else\r
+   if (setjmp(png_ptr->jmpbuf))\r
+#endif\r
+   {\r
+      png_free(png_ptr, png_ptr->zbuf);\r
+      png_ptr->zbuf = NULL;\r
+#ifdef PNG_USER_MEM_SUPPORTED\r
+      png_destroy_struct_2((png_voidp)png_ptr,\r
+         (png_free_ptr)free_fn, (png_voidp)mem_ptr);\r
+#else\r
+      png_destroy_struct((png_voidp)png_ptr);\r
+#endif\r
+      return (NULL);\r
+   }\r
+#ifdef USE_FAR_KEYWORD\r
+   png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf));\r
+#endif\r
+#endif\r
+\r
+#ifdef PNG_USER_MEM_SUPPORTED\r
+   png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn);\r
+#endif\r
+\r
+   png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);\r
+\r
+   if (user_png_ver)\r
+   {\r
+     i = 0;\r
+     do\r
+     {\r
+       if (user_png_ver[i] != png_libpng_ver[i])\r
+          png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;\r
+     } while (png_libpng_ver[i++]);\r
+   }\r
+   else\r
+        png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;\r
+   \r
+\r
+   if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH)\r
+   {\r
+     /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so\r
+      * we must recompile any applications that use any older library version.\r
+      * For versions after libpng 1.0, we will be compatible, so we need\r
+      * only check the first digit.\r
+      */\r
+     if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] ||\r
+         (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) ||\r
+         (user_png_ver[0] == '0' && user_png_ver[2] < '9'))\r
+     {\r
+#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)\r
+        char msg[80];\r
+        if (user_png_ver)\r
+        {\r
+          png_snprintf(msg, 80,\r
+             "Application was compiled with png.h from libpng-%.20s",\r
+             user_png_ver);\r
+          png_warning(png_ptr, msg);\r
+        }\r
+        png_snprintf(msg, 80,\r
+             "Application  is  running with png.c from libpng-%.20s",\r
+           png_libpng_ver);\r
+        png_warning(png_ptr, msg);\r
+#endif\r
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED\r
+        png_ptr->flags = 0;\r
+#endif\r
+        png_error(png_ptr,\r
+           "Incompatible libpng version in application and library");\r
+     }\r
+   }\r
+\r
+   /* initialize zbuf - compression buffer */\r
+   png_ptr->zbuf_size = PNG_ZBUF_SIZE;\r
+   png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,\r
+     (png_uint_32)png_ptr->zbuf_size);\r
+   png_ptr->zstream.zalloc = png_zalloc;\r
+   png_ptr->zstream.zfree = png_zfree;\r
+   png_ptr->zstream.opaque = (voidpf)png_ptr;\r
+\r
+   switch (inflateInit(&png_ptr->zstream))\r
+   {\r
+     case Z_OK: /* Do nothing */ break;\r
+     case Z_MEM_ERROR:\r
+     case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory error"); break;\r
+     case Z_VERSION_ERROR: png_error(png_ptr, "zlib version error"); break;\r
+     default: png_error(png_ptr, "Unknown zlib error");\r
+   }\r
+\r
+   png_ptr->zstream.next_out = png_ptr->zbuf;\r
+   png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;\r
+\r
+   png_set_read_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL);\r
+\r
+#ifdef PNG_SETJMP_SUPPORTED\r
+/* Applications that neglect to set up their own setjmp() and then encounter\r
+   a png_error() will longjmp here.  Since the jmpbuf is then meaningless we\r
+   abort instead of returning. */\r
+#ifdef USE_FAR_KEYWORD\r
+   if (setjmp(jmpbuf))\r
+      PNG_ABORT();\r
+   png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf));\r
+#else\r
+   if (setjmp(png_ptr->jmpbuf))\r
+      PNG_ABORT();\r
+#endif\r
+#endif\r
+   return (png_ptr);\r
+}\r
+\r
+#if defined(PNG_1_0_X) || defined(PNG_1_2_X)\r
+/* Initialize PNG structure for reading, and allocate any memory needed.\r
+   This interface is deprecated in favour of the png_create_read_struct(),\r
+   and it will disappear as of libpng-1.3.0. */\r
+#undef png_read_init\r
+void PNGAPI\r
+png_read_init(png_structp png_ptr)\r
+{\r
+   /* We only come here via pre-1.0.7-compiled applications */\r
+   png_read_init_2(png_ptr, "1.0.6 or earlier", 0, 0);\r
+}\r
+\r
+void PNGAPI\r
+png_read_init_2(png_structp png_ptr, png_const_charp user_png_ver,\r
+   png_size_t png_struct_size, png_size_t png_info_size)\r
+{\r
+   /* We only come here via pre-1.0.12-compiled applications */\r
+   if (png_ptr == NULL) return;\r
+#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)\r
+   if (png_sizeof(png_struct) > png_struct_size ||\r
+      png_sizeof(png_info) > png_info_size)\r
+   {\r
+      char msg[80];\r
+      png_ptr->warning_fn = NULL;\r
+      if (user_png_ver)\r
+      {\r
+        png_snprintf(msg, 80,\r
+           "Application was compiled with png.h from libpng-%.20s",\r
+           user_png_ver);\r
+        png_warning(png_ptr, msg);\r
+      }\r
+      png_snprintf(msg, 80,\r
+         "Application  is  running with png.c from libpng-%.20s",\r
+         png_libpng_ver);\r
+      png_warning(png_ptr, msg);\r
+   }\r
+#endif\r
+   if (png_sizeof(png_struct) > png_struct_size)\r
+     {\r
+       png_ptr->error_fn = NULL;\r
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED\r
+       png_ptr->flags = 0;\r
+#endif\r
+       png_error(png_ptr,\r
+       "The png struct allocated by the application for reading is too small.");\r
+     }\r
+   if (png_sizeof(png_info) > png_info_size)\r
+     {\r
+       png_ptr->error_fn = NULL;\r
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED\r
+       png_ptr->flags = 0;\r
+#endif\r
+       png_error(png_ptr,\r
+         "The info struct allocated by application for reading is too small.");\r
+     }\r
+   png_read_init_3(&png_ptr, user_png_ver, png_struct_size);\r
+}\r
+#endif /* PNG_1_0_X || PNG_1_2_X */\r
+\r
+void PNGAPI\r
+png_read_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver,\r
+   png_size_t png_struct_size)\r
+{\r
+#ifdef PNG_SETJMP_SUPPORTED\r
+   jmp_buf tmp_jmp;  /* to save current jump buffer */\r
+#endif\r
+\r
+   int i = 0;\r
+\r
+   png_structp png_ptr=*ptr_ptr;\r
+\r
+   if (png_ptr == NULL) return;\r
+\r
+   do\r
+   {\r
+     if (user_png_ver[i] != png_libpng_ver[i])\r
+     {\r
+#ifdef PNG_LEGACY_SUPPORTED\r
+       png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;\r
+#else\r
+       png_ptr->warning_fn = NULL;\r
+       png_warning(png_ptr,\r
+        "Application uses deprecated png_read_init() and should be recompiled.");\r
+       break;\r
+#endif\r
+     }\r
+   } while (png_libpng_ver[i++]);\r
+\r
+   png_debug(1, "in png_read_init_3\n");\r
+\r
+#ifdef PNG_SETJMP_SUPPORTED\r
+   /* save jump buffer and error functions */\r
+   png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf));\r
+#endif\r
+\r
+   if (png_sizeof(png_struct) > png_struct_size)\r
+   {\r
+      png_destroy_struct(png_ptr);\r
+      *ptr_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);\r
+      png_ptr = *ptr_ptr;\r
+   }\r
+\r
+   /* reset all variables to 0 */\r
+   png_memset(png_ptr, 0, png_sizeof(png_struct));\r
+\r
+#ifdef PNG_SETJMP_SUPPORTED\r
+   /* restore jump buffer */\r
+   png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf));\r
+#endif\r
+\r
+   /* added at libpng-1.2.6 */\r
+#ifdef PNG_SET_USER_LIMITS_SUPPORTED\r
+   png_ptr->user_width_max=PNG_USER_WIDTH_MAX;\r
+   png_ptr->user_height_max=PNG_USER_HEIGHT_MAX;\r
+#endif\r
+\r
+   /* initialize zbuf - compression buffer */\r
+   png_ptr->zbuf_size = PNG_ZBUF_SIZE;\r
+   png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,\r
+     (png_uint_32)png_ptr->zbuf_size);\r
+   png_ptr->zstream.zalloc = png_zalloc;\r
+   png_ptr->zstream.zfree = png_zfree;\r
+   png_ptr->zstream.opaque = (voidpf)png_ptr;\r
+\r
+   switch (inflateInit(&png_ptr->zstream))\r
+   {\r
+     case Z_OK: /* Do nothing */ break;\r
+     case Z_MEM_ERROR:\r
+     case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory"); break;\r
+     case Z_VERSION_ERROR: png_error(png_ptr, "zlib version"); break;\r
+     default: png_error(png_ptr, "Unknown zlib error");\r
+   }\r
+\r
+   png_ptr->zstream.next_out = png_ptr->zbuf;\r
+   png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;\r
+\r
+   png_set_read_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL);\r
+}\r
+\r
+#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED\r
+/* Read the information before the actual image data.  This has been\r
+ * changed in v0.90 to allow reading a file that already has the magic\r
+ * bytes read from the stream.  You can tell libpng how many bytes have\r
+ * been read from the beginning of the stream (up to the maximum of 8)\r
+ * via png_set_sig_bytes(), and we will only check the remaining bytes\r
+ * here.  The application can then have access to the signature bytes we\r
+ * read if it is determined that this isn't a valid PNG file.\r
+ */\r
+void PNGAPI\r
+png_read_info(png_structp png_ptr, png_infop info_ptr)\r
+{\r
+   if (png_ptr == NULL || info_ptr == NULL) return;\r
+   png_debug(1, "in png_read_info\n");\r
+   /* If we haven't checked all of the PNG signature bytes, do so now. */\r
+   if (png_ptr->sig_bytes < 8)\r
+   {\r
+      png_size_t num_checked = png_ptr->sig_bytes,\r
+                 num_to_check = 8 - num_checked;\r
+\r
+      png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check);\r
+      png_ptr->sig_bytes = 8;\r
+\r
+      if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))\r
+      {\r
+         if (num_checked < 4 &&\r
+             png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))\r
+            png_error(png_ptr, "Not a PNG file");\r
+         else\r
+            png_error(png_ptr, "PNG file corrupted by ASCII conversion");\r
+      }\r
+      if (num_checked < 3)\r
+         png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE;\r
+   }\r
+\r
+   for (;;)\r
+   {\r
+#ifdef PNG_USE_LOCAL_ARRAYS\r
+      PNG_CONST PNG_IHDR;\r
+      PNG_CONST PNG_IDAT;\r
+      PNG_CONST PNG_IEND;\r
+      PNG_CONST PNG_PLTE;\r
+#if defined(PNG_READ_bKGD_SUPPORTED)\r
+      PNG_CONST PNG_bKGD;\r
+#endif\r
+#if defined(PNG_READ_cHRM_SUPPORTED)\r
+      PNG_CONST PNG_cHRM;\r
+#endif\r
+#if defined(PNG_READ_gAMA_SUPPORTED)\r
+      PNG_CONST PNG_gAMA;\r
+#endif\r
+#if defined(PNG_READ_hIST_SUPPORTED)\r
+      PNG_CONST PNG_hIST;\r
+#endif\r
+#if defined(PNG_READ_iCCP_SUPPORTED)\r
+      PNG_CONST PNG_iCCP;\r
+#endif\r
+#if defined(PNG_READ_iTXt_SUPPORTED)\r
+      PNG_CONST PNG_iTXt;\r
+#endif\r
+#if defined(PNG_READ_oFFs_SUPPORTED)\r
+      PNG_CONST PNG_oFFs;\r
+#endif\r
+#if defined(PNG_READ_pCAL_SUPPORTED)\r
+      PNG_CONST PNG_pCAL;\r
+#endif\r
+#if defined(PNG_READ_pHYs_SUPPORTED)\r
+      PNG_CONST PNG_pHYs;\r
+#endif\r
+#if defined(PNG_READ_sBIT_SUPPORTED)\r
+      PNG_CONST PNG_sBIT;\r
+#endif\r
+#if defined(PNG_READ_sCAL_SUPPORTED)\r
+      PNG_CONST PNG_sCAL;\r
+#endif\r
+#if defined(PNG_READ_sPLT_SUPPORTED)\r
+      PNG_CONST PNG_sPLT;\r
+#endif\r
+#if defined(PNG_READ_sRGB_SUPPORTED)\r
+      PNG_CONST PNG_sRGB;\r
+#endif\r
+#if defined(PNG_READ_tEXt_SUPPORTED)\r
+      PNG_CONST PNG_tEXt;\r
+#endif\r
+#if defined(PNG_READ_tIME_SUPPORTED)\r
+      PNG_CONST PNG_tIME;\r
+#endif\r
+#if defined(PNG_READ_tRNS_SUPPORTED)\r
+      PNG_CONST PNG_tRNS;\r
+#endif\r
+#if defined(PNG_READ_zTXt_SUPPORTED)\r
+      PNG_CONST PNG_zTXt;\r
+#endif\r
+#endif /* PNG_USE_LOCAL_ARRAYS */\r
+      png_uint_32 length = png_read_chunk_header(png_ptr);\r
+      PNG_CONST png_bytep chunk_name = png_ptr->chunk_name;\r
+\r
+      /* This should be a binary subdivision search or a hash for\r
+       * matching the chunk name rather than a linear search.\r
+       */\r
+      if (!png_memcmp(chunk_name, png_IDAT, 4))\r
+        if (png_ptr->mode & PNG_AFTER_IDAT)\r
+          png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;\r
+\r
+      if (!png_memcmp(chunk_name, png_IHDR, 4))\r
+         png_handle_IHDR(png_ptr, info_ptr, length);\r
+      else if (!png_memcmp(chunk_name, png_IEND, 4))\r
+         png_handle_IEND(png_ptr, info_ptr, length);\r
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED\r
+      else if (png_handle_as_unknown(png_ptr, chunk_name))\r
+      {\r
+         if (!png_memcmp(chunk_name, png_IDAT, 4))\r
+            png_ptr->mode |= PNG_HAVE_IDAT;\r
+         png_handle_unknown(png_ptr, info_ptr, length);\r
+         if (!png_memcmp(chunk_name, png_PLTE, 4))\r
+            png_ptr->mode |= PNG_HAVE_PLTE;\r
+         else if (!png_memcmp(chunk_name, png_IDAT, 4))\r
+         {\r
+            if (!(png_ptr->mode & PNG_HAVE_IHDR))\r
+               png_error(png_ptr, "Missing IHDR before IDAT");\r
+            else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&\r
+                     !(png_ptr->mode & PNG_HAVE_PLTE))\r
+               png_error(png_ptr, "Missing PLTE before IDAT");\r
+            break;\r
+         }\r
+      }\r
+#endif\r
+      else if (!png_memcmp(chunk_name, png_PLTE, 4))\r
+         png_handle_PLTE(png_ptr, info_ptr, length);\r
+      else if (!png_memcmp(chunk_name, png_IDAT, 4))\r
+      {\r
+         if (!(png_ptr->mode & PNG_HAVE_IHDR))\r
+            png_error(png_ptr, "Missing IHDR before IDAT");\r
+         else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&\r
+                  !(png_ptr->mode & PNG_HAVE_PLTE))\r
+            png_error(png_ptr, "Missing PLTE before IDAT");\r
+\r
+         png_ptr->idat_size = length;\r
+         png_ptr->mode |= PNG_HAVE_IDAT;\r
+         break;\r
+      }\r
+#if defined(PNG_READ_bKGD_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_bKGD, 4))\r
+         png_handle_bKGD(png_ptr, info_ptr, length);\r
+#endif\r
+#if defined(PNG_READ_cHRM_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_cHRM, 4))\r
+         png_handle_cHRM(png_ptr, info_ptr, length);\r
+#endif\r
+#if defined(PNG_READ_gAMA_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_gAMA, 4))\r
+         png_handle_gAMA(png_ptr, info_ptr, length);\r
+#endif\r
+#if defined(PNG_READ_hIST_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_hIST, 4))\r
+         png_handle_hIST(png_ptr, info_ptr, length);\r
+#endif\r
+#if defined(PNG_READ_oFFs_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_oFFs, 4))\r
+         png_handle_oFFs(png_ptr, info_ptr, length);\r
+#endif\r
+#if defined(PNG_READ_pCAL_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_pCAL, 4))\r
+         png_handle_pCAL(png_ptr, info_ptr, length);\r
+#endif\r
+#if defined(PNG_READ_sCAL_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_sCAL, 4))\r
+         png_handle_sCAL(png_ptr, info_ptr, length);\r
+#endif\r
+#if defined(PNG_READ_pHYs_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_pHYs, 4))\r
+         png_handle_pHYs(png_ptr, info_ptr, length);\r
+#endif\r
+#if defined(PNG_READ_sBIT_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_sBIT, 4))\r
+         png_handle_sBIT(png_ptr, info_ptr, length);\r
+#endif\r
+#if defined(PNG_READ_sRGB_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_sRGB, 4))\r
+         png_handle_sRGB(png_ptr, info_ptr, length);\r
+#endif\r
+#if defined(PNG_READ_iCCP_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_iCCP, 4))\r
+         png_handle_iCCP(png_ptr, info_ptr, length);\r
+#endif\r
+#if defined(PNG_READ_sPLT_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_sPLT, 4))\r
+         png_handle_sPLT(png_ptr, info_ptr, length);\r
+#endif\r
+#if defined(PNG_READ_tEXt_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_tEXt, 4))\r
+         png_handle_tEXt(png_ptr, info_ptr, length);\r
+#endif\r
+#if defined(PNG_READ_tIME_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_tIME, 4))\r
+         png_handle_tIME(png_ptr, info_ptr, length);\r
+#endif\r
+#if defined(PNG_READ_tRNS_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_tRNS, 4))\r
+         png_handle_tRNS(png_ptr, info_ptr, length);\r
+#endif\r
+#if defined(PNG_READ_zTXt_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_zTXt, 4))\r
+         png_handle_zTXt(png_ptr, info_ptr, length);\r
+#endif\r
+#if defined(PNG_READ_iTXt_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_iTXt, 4))\r
+         png_handle_iTXt(png_ptr, info_ptr, length);\r
+#endif\r
+      else\r
+         png_handle_unknown(png_ptr, info_ptr, length);\r
+   }\r
+}\r
+#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */\r
+\r
+/* optional call to update the users info_ptr structure */\r
+void PNGAPI\r
+png_read_update_info(png_structp png_ptr, png_infop info_ptr)\r
+{\r
+   png_debug(1, "in png_read_update_info\n");\r
+   if (png_ptr == NULL) return;\r
+   if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))\r
+      png_read_start_row(png_ptr);\r
+   else\r
+      png_warning(png_ptr,\r
+      "Ignoring extra png_read_update_info() call; row buffer not reallocated");\r
+   png_read_transform_info(png_ptr, info_ptr);\r
+}\r
+\r
+#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED\r
+/* Initialize palette, background, etc, after transformations\r
+ * are set, but before any reading takes place.  This allows\r
+ * the user to obtain a gamma-corrected palette, for example.\r
+ * If the user doesn't call this, we will do it ourselves.\r
+ */\r
+void PNGAPI\r
+png_start_read_image(png_structp png_ptr)\r
+{\r
+   png_debug(1, "in png_start_read_image\n");\r
+   if (png_ptr == NULL) return;\r
+   if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))\r
+      png_read_start_row(png_ptr);\r
+}\r
+#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */\r
+\r
+#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED\r
+void PNGAPI\r
+png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)\r
+{\r
+#ifdef PNG_USE_LOCAL_ARRAYS\r
+   PNG_CONST PNG_IDAT;\r
+   PNG_CONST int png_pass_dsp_mask[7] = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55,\r
+      0xff};\r
+   PNG_CONST int png_pass_mask[7] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff};\r
+#endif\r
+   int ret;\r
+   if (png_ptr == NULL) return;\r
+   png_debug2(1, "in png_read_row (row %lu, pass %d)\n",\r
+      png_ptr->row_number, png_ptr->pass);\r
+   if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))\r
+      png_read_start_row(png_ptr);\r
+   if (png_ptr->row_number == 0 && png_ptr->pass == 0)\r
+   {\r
+   /* check for transforms that have been set but were defined out */\r
+#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED)\r
+   if (png_ptr->transformations & PNG_INVERT_MONO)\r
+      png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined.");\r
+#endif\r
+#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED)\r
+   if (png_ptr->transformations & PNG_FILLER)\r
+      png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined.");\r
+#endif\r
+#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && !defined(PNG_READ_PACKSWAP_SUPPORTED)\r
+   if (png_ptr->transformations & PNG_PACKSWAP)\r
+      png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined.");\r
+#endif\r
+#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED)\r
+   if (png_ptr->transformations & PNG_PACK)\r
+      png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined.");\r
+#endif\r
+#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED)\r
+   if (png_ptr->transformations & PNG_SHIFT)\r
+      png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined.");\r
+#endif\r
+#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED)\r
+   if (png_ptr->transformations & PNG_BGR)\r
+      png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined.");\r
+#endif\r
+#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED)\r
+   if (png_ptr->transformations & PNG_SWAP_BYTES)\r
+      png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined.");\r
+#endif\r
+   }\r
+\r
+#if defined(PNG_READ_INTERLACING_SUPPORTED)\r
+   /* if interlaced and we do not need a new row, combine row and return */\r
+   if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))\r
+   {\r
+      switch (png_ptr->pass)\r
+      {\r
+         case 0:\r
+            if (png_ptr->row_number & 0x07)\r
+            {\r
+               if (dsp_row != NULL)\r
+                  png_combine_row(png_ptr, dsp_row,\r
+                     png_pass_dsp_mask[png_ptr->pass]);\r
+               png_read_finish_row(png_ptr);\r
+               return;\r
+            }\r
+            break;\r
+         case 1:\r
+            if ((png_ptr->row_number & 0x07) || png_ptr->width < 5)\r
+            {\r
+               if (dsp_row != NULL)\r
+                  png_combine_row(png_ptr, dsp_row,\r
+                     png_pass_dsp_mask[png_ptr->pass]);\r
+               png_read_finish_row(png_ptr);\r
+               return;\r
+            }\r
+            break;\r
+         case 2:\r
+            if ((png_ptr->row_number & 0x07) != 4)\r
+            {\r
+               if (dsp_row != NULL && (png_ptr->row_number & 4))\r
+                  png_combine_row(png_ptr, dsp_row,\r
+                     png_pass_dsp_mask[png_ptr->pass]);\r
+               png_read_finish_row(png_ptr);\r
+               return;\r
+            }\r
+            break;\r
+         case 3:\r
+            if ((png_ptr->row_number & 3) || png_ptr->width < 3)\r
+            {\r
+               if (dsp_row != NULL)\r
+                  png_combine_row(png_ptr, dsp_row,\r
+                     png_pass_dsp_mask[png_ptr->pass]);\r
+               png_read_finish_row(png_ptr);\r
+               return;\r
+            }\r
+            break;\r
+         case 4:\r
+            if ((png_ptr->row_number & 3) != 2)\r
+            {\r
+               if (dsp_row != NULL && (png_ptr->row_number & 2))\r
+                  png_combine_row(png_ptr, dsp_row,\r
+                     png_pass_dsp_mask[png_ptr->pass]);\r
+               png_read_finish_row(png_ptr);\r
+               return;\r
+            }\r
+            break;\r
+         case 5:\r
+            if ((png_ptr->row_number & 1) || png_ptr->width < 2)\r
+            {\r
+               if (dsp_row != NULL)\r
+                  png_combine_row(png_ptr, dsp_row,\r
+                     png_pass_dsp_mask[png_ptr->pass]);\r
+               png_read_finish_row(png_ptr);\r
+               return;\r
+            }\r
+            break;\r
+         case 6:\r
+            if (!(png_ptr->row_number & 1))\r
+            {\r
+               png_read_finish_row(png_ptr);\r
+               return;\r
+            }\r
+            break;\r
+      }\r
+   }\r
+#endif\r
+\r
+   if (!(png_ptr->mode & PNG_HAVE_IDAT))\r
+      png_error(png_ptr, "Invalid attempt to read row data");\r
+\r
+   png_ptr->zstream.next_out = png_ptr->row_buf;\r
+   png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;\r
+   do\r
+   {\r
+      if (!(png_ptr->zstream.avail_in))\r
+      {\r
+         while (!png_ptr->idat_size)\r
+         {\r
+            png_crc_finish(png_ptr, 0);\r
+\r
+            png_ptr->idat_size = png_read_chunk_header(png_ptr);\r
+            if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))\r
+               png_error(png_ptr, "Not enough image data");\r
+         }\r
+         png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;\r
+         png_ptr->zstream.next_in = png_ptr->zbuf;\r
+         if (png_ptr->zbuf_size > png_ptr->idat_size)\r
+            png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;\r
+         png_crc_read(png_ptr, png_ptr->zbuf,\r
+            (png_size_t)png_ptr->zstream.avail_in);\r
+         png_ptr->idat_size -= png_ptr->zstream.avail_in;\r
+      }\r
+      ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);\r
+      if (ret == Z_STREAM_END)\r
+      {\r
+         if (png_ptr->zstream.avail_out || png_ptr->zstream.avail_in ||\r
+            png_ptr->idat_size)\r
+            png_error(png_ptr, "Extra compressed data");\r
+         png_ptr->mode |= PNG_AFTER_IDAT;\r
+         png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;\r
+         break;\r
+      }\r
+      if (ret != Z_OK)\r
+         png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :\r
+                   "Decompression error");\r
+\r
+   } while (png_ptr->zstream.avail_out);\r
+\r
+   png_ptr->row_info.color_type = png_ptr->color_type;\r
+   png_ptr->row_info.width = png_ptr->iwidth;\r
+   png_ptr->row_info.channels = png_ptr->channels;\r
+   png_ptr->row_info.bit_depth = png_ptr->bit_depth;\r
+   png_ptr->row_info.pixel_depth = png_ptr->pixel_depth;\r
+   png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,\r
+       png_ptr->row_info.width);\r
+\r
+   if (png_ptr->row_buf[0])\r
+   png_read_filter_row(png_ptr, &(png_ptr->row_info),\r
+      png_ptr->row_buf + 1, png_ptr->prev_row + 1,\r
+      (int)(png_ptr->row_buf[0]));\r
+\r
+   png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf,\r
+      png_ptr->rowbytes + 1);\r
+\r
+#if defined(PNG_MNG_FEATURES_SUPPORTED)\r
+   if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&\r
+      (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))\r
+   {\r
+      /* Intrapixel differencing */\r
+      png_do_read_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1);\r
+   }\r
+#endif\r
+\r
+\r
+   if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA))\r
+      png_do_read_transformations(png_ptr);\r
+\r
+#if defined(PNG_READ_INTERLACING_SUPPORTED)\r
+   /* blow up interlaced rows to full size */\r
+   if (png_ptr->interlaced &&\r
+      (png_ptr->transformations & PNG_INTERLACE))\r
+   {\r
+      if (png_ptr->pass < 6)\r
+/*       old interface (pre-1.0.9):\r
+         png_do_read_interlace(&(png_ptr->row_info),\r
+            png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations);\r
+ */\r
+         png_do_read_interlace(png_ptr);\r
+\r
+      if (dsp_row != NULL)\r
+         png_combine_row(png_ptr, dsp_row,\r
+            png_pass_dsp_mask[png_ptr->pass]);\r
+      if (row != NULL)\r
+         png_combine_row(png_ptr, row,\r
+            png_pass_mask[png_ptr->pass]);\r
+   }\r
+   else\r
+#endif\r
+   {\r
+      if (row != NULL)\r
+         png_combine_row(png_ptr, row, 0xff);\r
+      if (dsp_row != NULL)\r
+         png_combine_row(png_ptr, dsp_row, 0xff);\r
+   }\r
+   png_read_finish_row(png_ptr);\r
+\r
+   if (png_ptr->read_row_fn != NULL)\r
+      (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);\r
+}\r
+#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */\r
+\r
+#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED\r
+/* Read one or more rows of image data.  If the image is interlaced,\r
+ * and png_set_interlace_handling() has been called, the rows need to\r
+ * contain the contents of the rows from the previous pass.  If the\r
+ * image has alpha or transparency, and png_handle_alpha()[*] has been\r
+ * called, the rows contents must be initialized to the contents of the\r
+ * screen.\r
+ *\r
+ * "row" holds the actual image, and pixels are placed in it\r
+ * as they arrive.  If the image is displayed after each pass, it will\r
+ * appear to "sparkle" in.  "display_row" can be used to display a\r
+ * "chunky" progressive image, with finer detail added as it becomes\r
+ * available.  If you do not want this "chunky" display, you may pass\r
+ * NULL for display_row.  If you do not want the sparkle display, and\r
+ * you have not called png_handle_alpha(), you may pass NULL for rows.\r
+ * If you have called png_handle_alpha(), and the image has either an\r
+ * alpha channel or a transparency chunk, you must provide a buffer for\r
+ * rows.  In this case, you do not have to provide a display_row buffer\r
+ * also, but you may.  If the image is not interlaced, or if you have\r
+ * not called png_set_interlace_handling(), the display_row buffer will\r
+ * be ignored, so pass NULL to it.\r
+ *\r
+ * [*] png_handle_alpha() does not exist yet, as of this version of libpng\r
+ */\r
+\r
+void PNGAPI\r
+png_read_rows(png_structp png_ptr, png_bytepp row,\r
+   png_bytepp display_row, png_uint_32 num_rows)\r
+{\r
+   png_uint_32 i;\r
+   png_bytepp rp;\r
+   png_bytepp dp;\r
+\r
+   png_debug(1, "in png_read_rows\n");\r
+   if (png_ptr == NULL) return;\r
+   rp = row;\r
+   dp = display_row;\r
+   if (rp != NULL && dp != NULL)\r
+      for (i = 0; i < num_rows; i++)\r
+      {\r
+         png_bytep rptr = *rp++;\r
+         png_bytep dptr = *dp++;\r
+\r
+         png_read_row(png_ptr, rptr, dptr);\r
+      }\r
+   else if (rp != NULL)\r
+      for (i = 0; i < num_rows; i++)\r
+      {\r
+         png_bytep rptr = *rp;\r
+         png_read_row(png_ptr, rptr, png_bytep_NULL);\r
+         rp++;\r
+      }\r
+   else if (dp != NULL)\r
+      for (i = 0; i < num_rows; i++)\r
+      {\r
+         png_bytep dptr = *dp;\r
+         png_read_row(png_ptr, png_bytep_NULL, dptr);\r
+         dp++;\r
+      }\r
+}\r
+#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */\r
+\r
+#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED\r
+/* Read the entire image.  If the image has an alpha channel or a tRNS\r
+ * chunk, and you have called png_handle_alpha()[*], you will need to\r
+ * initialize the image to the current image that PNG will be overlaying.\r
+ * We set the num_rows again here, in case it was incorrectly set in\r
+ * png_read_start_row() by a call to png_read_update_info() or\r
+ * png_start_read_image() if png_set_interlace_handling() wasn't called\r
+ * prior to either of these functions like it should have been.  You can\r
+ * only call this function once.  If you desire to have an image for\r
+ * each pass of a interlaced image, use png_read_rows() instead.\r
+ *\r
+ * [*] png_handle_alpha() does not exist yet, as of this version of libpng\r
+ */\r
+void PNGAPI\r
+png_read_image(png_structp png_ptr, png_bytepp image)\r
+{\r
+   png_uint_32 i, image_height;\r
+   int pass, j;\r
+   png_bytepp rp;\r
+\r
+   png_debug(1, "in png_read_image\n");\r
+   if (png_ptr == NULL) return;\r
+\r
+#ifdef PNG_READ_INTERLACING_SUPPORTED\r
+   pass = png_set_interlace_handling(png_ptr);\r
+#else\r
+   if (png_ptr->interlaced)\r
+      png_error(png_ptr,\r
+        "Cannot read interlaced image -- interlace handler disabled.");\r
+   pass = 1;\r
+#endif\r
+\r
+\r
+   image_height=png_ptr->height;\r
+   png_ptr->num_rows = image_height; /* Make sure this is set correctly */\r
+\r
+   for (j = 0; j < pass; j++)\r
+   {\r
+      rp = image;\r
+      for (i = 0; i < image_height; i++)\r
+      {\r
+         png_read_row(png_ptr, *rp, png_bytep_NULL);\r
+         rp++;\r
+      }\r
+   }\r
+}\r
+#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */\r
+\r
+#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED\r
+/* Read the end of the PNG file.  Will not read past the end of the\r
+ * file, will verify the end is accurate, and will read any comments\r
+ * or time information at the end of the file, if info is not NULL.\r
+ */\r
+void PNGAPI\r
+png_read_end(png_structp png_ptr, png_infop info_ptr)\r
+{\r
+   png_debug(1, "in png_read_end\n");\r
+   if (png_ptr == NULL) return;\r
+   png_crc_finish(png_ptr, 0); /* Finish off CRC from last IDAT chunk */\r
+\r
+   do\r
+   {\r
+#ifdef PNG_USE_LOCAL_ARRAYS\r
+      PNG_CONST PNG_IHDR;\r
+      PNG_CONST PNG_IDAT;\r
+      PNG_CONST PNG_IEND;\r
+      PNG_CONST PNG_PLTE;\r
+#if defined(PNG_READ_bKGD_SUPPORTED)\r
+      PNG_CONST PNG_bKGD;\r
+#endif\r
+#if defined(PNG_READ_cHRM_SUPPORTED)\r
+      PNG_CONST PNG_cHRM;\r
+#endif\r
+#if defined(PNG_READ_gAMA_SUPPORTED)\r
+      PNG_CONST PNG_gAMA;\r
+#endif\r
+#if defined(PNG_READ_hIST_SUPPORTED)\r
+      PNG_CONST PNG_hIST;\r
+#endif\r
+#if defined(PNG_READ_iCCP_SUPPORTED)\r
+      PNG_CONST PNG_iCCP;\r
+#endif\r
+#if defined(PNG_READ_iTXt_SUPPORTED)\r
+      PNG_CONST PNG_iTXt;\r
+#endif\r
+#if defined(PNG_READ_oFFs_SUPPORTED)\r
+      PNG_CONST PNG_oFFs;\r
+#endif\r
+#if defined(PNG_READ_pCAL_SUPPORTED)\r
+      PNG_CONST PNG_pCAL;\r
+#endif\r
+#if defined(PNG_READ_pHYs_SUPPORTED)\r
+      PNG_CONST PNG_pHYs;\r
+#endif\r
+#if defined(PNG_READ_sBIT_SUPPORTED)\r
+      PNG_CONST PNG_sBIT;\r
+#endif\r
+#if defined(PNG_READ_sCAL_SUPPORTED)\r
+      PNG_CONST PNG_sCAL;\r
+#endif\r
+#if defined(PNG_READ_sPLT_SUPPORTED)\r
+      PNG_CONST PNG_sPLT;\r
+#endif\r
+#if defined(PNG_READ_sRGB_SUPPORTED)\r
+      PNG_CONST PNG_sRGB;\r
+#endif\r
+#if defined(PNG_READ_tEXt_SUPPORTED)\r
+      PNG_CONST PNG_tEXt;\r
+#endif\r
+#if defined(PNG_READ_tIME_SUPPORTED)\r
+      PNG_CONST PNG_tIME;\r
+#endif\r
+#if defined(PNG_READ_tRNS_SUPPORTED)\r
+      PNG_CONST PNG_tRNS;\r
+#endif\r
+#if defined(PNG_READ_zTXt_SUPPORTED)\r
+      PNG_CONST PNG_zTXt;\r
+#endif\r
+#endif /* PNG_USE_LOCAL_ARRAYS */\r
+      png_uint_32 length = png_read_chunk_header(png_ptr);\r
+      PNG_CONST png_bytep chunk_name = png_ptr->chunk_name;\r
+\r
+      if (!png_memcmp(chunk_name, png_IHDR, 4))\r
+         png_handle_IHDR(png_ptr, info_ptr, length);\r
+      else if (!png_memcmp(chunk_name, png_IEND, 4))\r
+         png_handle_IEND(png_ptr, info_ptr, length);\r
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED\r
+      else if (png_handle_as_unknown(png_ptr, chunk_name))\r
+      {\r
+         if (!png_memcmp(chunk_name, png_IDAT, 4))\r
+         {\r
+            if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))\r
+               png_error(png_ptr, "Too many IDAT's found");\r
+         }\r
+         png_handle_unknown(png_ptr, info_ptr, length);\r
+         if (!png_memcmp(chunk_name, png_PLTE, 4))\r
+            png_ptr->mode |= PNG_HAVE_PLTE;\r
+      }\r
+#endif\r
+      else if (!png_memcmp(chunk_name, png_IDAT, 4))\r
+      {\r
+         /* Zero length IDATs are legal after the last IDAT has been\r
+          * read, but not after other chunks have been read.\r
+          */\r
+         if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))\r
+            png_error(png_ptr, "Too many IDAT's found");\r
+         png_crc_finish(png_ptr, length);\r
+      }\r
+      else if (!png_memcmp(chunk_name, png_PLTE, 4))\r
+         png_handle_PLTE(png_ptr, info_ptr, length);\r
+#if defined(PNG_READ_bKGD_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_bKGD, 4))\r
+         png_handle_bKGD(png_ptr, info_ptr, length);\r
+#endif\r
+#if defined(PNG_READ_cHRM_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_cHRM, 4))\r
+         png_handle_cHRM(png_ptr, info_ptr, length);\r
+#endif\r
+#if defined(PNG_READ_gAMA_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_gAMA, 4))\r
+         png_handle_gAMA(png_ptr, info_ptr, length);\r
+#endif\r
+#if defined(PNG_READ_hIST_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_hIST, 4))\r
+         png_handle_hIST(png_ptr, info_ptr, length);\r
+#endif\r
+#if defined(PNG_READ_oFFs_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_oFFs, 4))\r
+         png_handle_oFFs(png_ptr, info_ptr, length);\r
+#endif\r
+#if defined(PNG_READ_pCAL_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_pCAL, 4))\r
+         png_handle_pCAL(png_ptr, info_ptr, length);\r
+#endif\r
+#if defined(PNG_READ_sCAL_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_sCAL, 4))\r
+         png_handle_sCAL(png_ptr, info_ptr, length);\r
+#endif\r
+#if defined(PNG_READ_pHYs_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_pHYs, 4))\r
+         png_handle_pHYs(png_ptr, info_ptr, length);\r
+#endif\r
+#if defined(PNG_READ_sBIT_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_sBIT, 4))\r
+         png_handle_sBIT(png_ptr, info_ptr, length);\r
+#endif\r
+#if defined(PNG_READ_sRGB_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_sRGB, 4))\r
+         png_handle_sRGB(png_ptr, info_ptr, length);\r
+#endif\r
+#if defined(PNG_READ_iCCP_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_iCCP, 4))\r
+         png_handle_iCCP(png_ptr, info_ptr, length);\r
+#endif\r
+#if defined(PNG_READ_sPLT_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_sPLT, 4))\r
+         png_handle_sPLT(png_ptr, info_ptr, length);\r
+#endif\r
+#if defined(PNG_READ_tEXt_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_tEXt, 4))\r
+         png_handle_tEXt(png_ptr, info_ptr, length);\r
+#endif\r
+#if defined(PNG_READ_tIME_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_tIME, 4))\r
+         png_handle_tIME(png_ptr, info_ptr, length);\r
+#endif\r
+#if defined(PNG_READ_tRNS_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_tRNS, 4))\r
+         png_handle_tRNS(png_ptr, info_ptr, length);\r
+#endif\r
+#if defined(PNG_READ_zTXt_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_zTXt, 4))\r
+         png_handle_zTXt(png_ptr, info_ptr, length);\r
+#endif\r
+#if defined(PNG_READ_iTXt_SUPPORTED)\r
+      else if (!png_memcmp(chunk_name, png_iTXt, 4))\r
+         png_handle_iTXt(png_ptr, info_ptr, length);\r
+#endif\r
+      else\r
+         png_handle_unknown(png_ptr, info_ptr, length);\r
+   } while (!(png_ptr->mode & PNG_HAVE_IEND));\r
+}\r
+#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */\r
+\r
+/* free all memory used by the read */\r
+void PNGAPI\r
+png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,\r
+   png_infopp end_info_ptr_ptr)\r
+{\r
+   png_structp png_ptr = NULL;\r
+   png_infop info_ptr = NULL, end_info_ptr = NULL;\r
+#ifdef PNG_USER_MEM_SUPPORTED\r
+   png_free_ptr free_fn = NULL;\r
+   png_voidp mem_ptr = NULL;\r
+#endif\r
+\r
+   png_debug(1, "in png_destroy_read_struct\n");\r
+   if (png_ptr_ptr != NULL)\r
+      png_ptr = *png_ptr_ptr;\r
+   if (png_ptr == NULL)\r
+      return;\r
+\r
+#ifdef PNG_USER_MEM_SUPPORTED\r
+   free_fn = png_ptr->free_fn;\r
+   mem_ptr = png_ptr->mem_ptr;\r
+#endif\r
+\r
+   if (info_ptr_ptr != NULL)\r
+      info_ptr = *info_ptr_ptr;\r
+\r
+   if (end_info_ptr_ptr != NULL)\r
+      end_info_ptr = *end_info_ptr_ptr;\r
+\r
+   png_read_destroy(png_ptr, info_ptr, end_info_ptr);\r
+\r
+   if (info_ptr != NULL)\r
+   {\r
+#if defined(PNG_TEXT_SUPPORTED)\r
+      png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, -1);\r
+#endif\r
+\r
+#ifdef PNG_USER_MEM_SUPPORTED\r
+      png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn,\r
+          (png_voidp)mem_ptr);\r
+#else\r
+      png_destroy_struct((png_voidp)info_ptr);\r
+#endif\r
+      *info_ptr_ptr = NULL;\r
+   }\r
+\r
+   if (end_info_ptr != NULL)\r
+   {\r
+#if defined(PNG_READ_TEXT_SUPPORTED)\r
+      png_free_data(png_ptr, end_info_ptr, PNG_FREE_TEXT, -1);\r
+#endif\r
+#ifdef PNG_USER_MEM_SUPPORTED\r
+      png_destroy_struct_2((png_voidp)end_info_ptr, (png_free_ptr)free_fn,\r
+         (png_voidp)mem_ptr);\r
+#else\r
+      png_destroy_struct((png_voidp)end_info_ptr);\r
+#endif\r
+      *end_info_ptr_ptr = NULL;\r
+   }\r
+\r
+   if (png_ptr != NULL)\r
+   {\r
+#ifdef PNG_USER_MEM_SUPPORTED\r
+      png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn,\r
+          (png_voidp)mem_ptr);\r
+#else\r
+      png_destroy_struct((png_voidp)png_ptr);\r
+#endif\r
+      *png_ptr_ptr = NULL;\r
+   }\r
+}\r
+\r
+/* free all memory used by the read (old method) */\r
+void /* PRIVATE */\r
+png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr)\r
+{\r
+#ifdef PNG_SETJMP_SUPPORTED\r
+   jmp_buf tmp_jmp;\r
+#endif\r
+   png_error_ptr error_fn;\r
+   png_error_ptr warning_fn;\r
+   png_voidp error_ptr;\r
+#ifdef PNG_USER_MEM_SUPPORTED\r
+   png_free_ptr free_fn;\r
+#endif\r
+\r
+   png_debug(1, "in png_read_destroy\n");\r
+   if (info_ptr != NULL)\r
+      png_info_destroy(png_ptr, info_ptr);\r
+\r
+   if (end_info_ptr != NULL)\r
+      png_info_destroy(png_ptr, end_info_ptr);\r
+\r
+   png_free(png_ptr, png_ptr->zbuf);\r
+   png_free(png_ptr, png_ptr->big_row_buf);\r
+   png_free(png_ptr, png_ptr->prev_row);\r
+   png_free(png_ptr, png_ptr->chunkdata);\r
+#if defined(PNG_READ_DITHER_SUPPORTED)\r
+   png_free(png_ptr, png_ptr->palette_lookup);\r
+   png_free(png_ptr, png_ptr->dither_index);\r
+#endif\r
+#if defined(PNG_READ_GAMMA_SUPPORTED)\r
+   png_free(png_ptr, png_ptr->gamma_table);\r
+#endif\r
+#if defined(PNG_READ_BACKGROUND_SUPPORTED)\r
+   png_free(png_ptr, png_ptr->gamma_from_1);\r
+   png_free(png_ptr, png_ptr->gamma_to_1);\r
+#endif\r
+#ifdef PNG_FREE_ME_SUPPORTED\r
+   if (png_ptr->free_me & PNG_FREE_PLTE)\r
+      png_zfree(png_ptr, png_ptr->palette);\r
+   png_ptr->free_me &= ~PNG_FREE_PLTE;\r
+#else\r
+   if (png_ptr->flags & PNG_FLAG_FREE_PLTE)\r
+      png_zfree(png_ptr, png_ptr->palette);\r
+   png_ptr->flags &= ~PNG_FLAG_FREE_PLTE;\r
+#endif\r
+#if defined(PNG_tRNS_SUPPORTED) || \\r
+    defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)\r
+#ifdef PNG_FREE_ME_SUPPORTED\r
+   if (png_ptr->free_me & PNG_FREE_TRNS)\r
+      png_free(png_ptr, png_ptr->trans);\r
+   png_ptr->free_me &= ~PNG_FREE_TRNS;\r
+#else\r
+   if (png_ptr->flags & PNG_FLAG_FREE_TRNS)\r
+      png_free(png_ptr, png_ptr->trans);\r
+   png_ptr->flags &= ~PNG_FLAG_FREE_TRNS;\r
+#endif\r
+#endif\r
+#if defined(PNG_READ_hIST_SUPPORTED)\r
+#ifdef PNG_FREE_ME_SUPPORTED\r
+   if (png_ptr->free_me & PNG_FREE_HIST)\r
+      png_free(png_ptr, png_ptr->hist);\r
+   png_ptr->free_me &= ~PNG_FREE_HIST;\r
+#else\r
+   if (png_ptr->flags & PNG_FLAG_FREE_HIST)\r
+      png_free(png_ptr, png_ptr->hist);\r
+   png_ptr->flags &= ~PNG_FLAG_FREE_HIST;\r
+#endif\r
+#endif\r
+#if defined(PNG_READ_GAMMA_SUPPORTED)\r
+   if (png_ptr->gamma_16_table != NULL)\r
+   {\r
+      int i;\r
+      int istop = (1 << (8 - png_ptr->gamma_shift));\r
+      for (i = 0; i < istop; i++)\r
+      {\r
+         png_free(png_ptr, png_ptr->gamma_16_table[i]);\r
+      }\r
+   png_free(png_ptr, png_ptr->gamma_16_table);\r
+   }\r
+#if defined(PNG_READ_BACKGROUND_SUPPORTED)\r
+   if (png_ptr->gamma_16_from_1 != NULL)\r
+   {\r
+      int i;\r
+      int istop = (1 << (8 - png_ptr->gamma_shift));\r
+      for (i = 0; i < istop; i++)\r
+      {\r
+         png_free(png_ptr, png_ptr->gamma_16_from_1[i]);\r
+      }\r
+   png_free(png_ptr, png_ptr->gamma_16_from_1);\r
+   }\r
+   if (png_ptr->gamma_16_to_1 != NULL)\r
+   {\r
+      int i;\r
+      int istop = (1 << (8 - png_ptr->gamma_shift));\r
+      for (i = 0; i < istop; i++)\r
+      {\r
+         png_free(png_ptr, png_ptr->gamma_16_to_1[i]);\r
+      }\r
+   png_free(png_ptr, png_ptr->gamma_16_to_1);\r
+   }\r
+#endif\r
+#endif\r
+#if defined(PNG_TIME_RFC1123_SUPPORTED)\r
+   png_free(png_ptr, png_ptr->time_buffer);\r
+#endif\r
+\r
+   inflateEnd(&png_ptr->zstream);\r
+#ifdef PNG_PROGRESSIVE_READ_SUPPORTED\r
+   png_free(png_ptr, png_ptr->save_buffer);\r
+#endif\r
+\r
+#ifdef PNG_PROGRESSIVE_READ_SUPPORTED\r
+#ifdef PNG_TEXT_SUPPORTED\r
+   png_free(png_ptr, png_ptr->current_text);\r
+#endif /* PNG_TEXT_SUPPORTED */\r
+#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */\r
+\r
+   /* Save the important info out of the png_struct, in case it is\r
+    * being used again.\r
+    */\r
+#ifdef PNG_SETJMP_SUPPORTED\r
+   png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf));\r
+#endif\r
+\r
+   error_fn = png_ptr->error_fn;\r
+   warning_fn = png_ptr->warning_fn;\r
+   error_ptr = png_ptr->error_ptr;\r
+#ifdef PNG_USER_MEM_SUPPORTED\r
+   free_fn = png_ptr->free_fn;\r
+#endif\r
+\r
+   png_memset(png_ptr, 0, png_sizeof(png_struct));\r
+\r
+   png_ptr->error_fn = error_fn;\r
+   png_ptr->warning_fn = warning_fn;\r
+   png_ptr->error_ptr = error_ptr;\r
+#ifdef PNG_USER_MEM_SUPPORTED\r
+   png_ptr->free_fn = free_fn;\r
+#endif\r
+\r
+#ifdef PNG_SETJMP_SUPPORTED\r
+   png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf));\r
+#endif\r
+\r
+}\r
+\r
+void PNGAPI\r
+png_set_read_status_fn(png_structp png_ptr, png_read_status_ptr read_row_fn)\r
+{\r
+   if (png_ptr == NULL) return;\r
+   png_ptr->read_row_fn = read_row_fn;\r
+}\r
+\r
+\r
+#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED\r
+#if defined(PNG_INFO_IMAGE_SUPPORTED)\r
+void PNGAPI\r
+png_read_png(png_structp png_ptr, png_infop info_ptr,\r
+                           int transforms,\r
+                           voidp params)\r
+{\r
+   int row;\r
+\r
+   if (png_ptr == NULL) return;\r
+#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)\r
+   /* invert the alpha channel from opacity to transparency\r
+    */\r
+   if (transforms & PNG_TRANSFORM_INVERT_ALPHA)\r
+       png_set_invert_alpha(png_ptr);\r
+#endif\r
+\r
+   /* png_read_info() gives us all of the information from the\r
+    * PNG file before the first IDAT (image data chunk).\r
+    */\r
+   png_read_info(png_ptr, info_ptr);\r
+   if (info_ptr->height > PNG_UINT_32_MAX/png_sizeof(png_bytep))\r
+      png_error(png_ptr, "Image is too high to process with png_read_png()");\r
+\r
+   /* -------------- image transformations start here ------------------- */\r
+\r
+#if defined(PNG_READ_16_TO_8_SUPPORTED)\r
+   /* tell libpng to strip 16 bit/color files down to 8 bits per color\r
+    */\r
+   if (transforms & PNG_TRANSFORM_STRIP_16)\r
+       png_set_strip_16(png_ptr);\r
+#endif\r
+\r
+#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)\r
+   /* Strip alpha bytes from the input data without combining with\r
+    * the background (not recommended).\r
+    */\r
+   if (transforms & PNG_TRANSFORM_STRIP_ALPHA)\r
+       png_set_strip_alpha(png_ptr);\r
+#endif\r
+\r
+#if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED)\r
+   /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single\r
+    * byte into separate bytes (useful for paletted and grayscale images).\r
+    */\r
+   if (transforms & PNG_TRANSFORM_PACKING)\r
+       png_set_packing(png_ptr);\r
+#endif\r
+\r
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)\r
+   /* Change the order of packed pixels to least significant bit first\r
+    * (not useful if you are using png_set_packing).\r
+    */\r
+   if (transforms & PNG_TRANSFORM_PACKSWAP)\r
+       png_set_packswap(png_ptr);\r
+#endif\r
+\r
+#if defined(PNG_READ_EXPAND_SUPPORTED)\r
+   /* Expand paletted colors into true RGB triplets\r
+    * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel\r
+    * Expand paletted or RGB images with transparency to full alpha\r
+    * channels so the data will be available as RGBA quartets.\r
+    */\r
+   if (transforms & PNG_TRANSFORM_EXPAND)\r
+       if ((png_ptr->bit_depth < 8) ||\r
+           (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ||\r
+           (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)))\r
+         png_set_expand(png_ptr);\r
+#endif\r
+\r
+   /* We don't handle background color or gamma transformation or dithering.\r
+    */\r
+\r
+#if defined(PNG_READ_INVERT_SUPPORTED)\r
+   /* invert monochrome files to have 0 as white and 1 as black\r
+    */\r
+   if (transforms & PNG_TRANSFORM_INVERT_MONO)\r
+       png_set_invert_mono(png_ptr);\r
+#endif\r
+\r
+#if defined(PNG_READ_SHIFT_SUPPORTED)\r
+   /* If you want to shift the pixel values from the range [0,255] or\r
+    * [0,65535] to the original [0,7] or [0,31], or whatever range the\r
+    * colors were originally in:\r
+    */\r
+   if ((transforms & PNG_TRANSFORM_SHIFT)\r
+       && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT))\r
+   {\r
+      png_color_8p sig_bit;\r
+\r
+      png_get_sBIT(png_ptr, info_ptr, &sig_bit);\r
+      png_set_shift(png_ptr, sig_bit);\r
+   }\r
+#endif\r
+\r
+#if defined(PNG_READ_BGR_SUPPORTED)\r
+   /* flip the RGB pixels to BGR (or RGBA to BGRA)\r
+    */\r
+   if (transforms & PNG_TRANSFORM_BGR)\r
+       png_set_bgr(png_ptr);\r
+#endif\r
+\r
+#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)\r
+   /* swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR)\r
+    */\r
+   if (transforms & PNG_TRANSFORM_SWAP_ALPHA)\r
+       png_set_swap_alpha(png_ptr);\r
+#endif\r
+\r
+#if defined(PNG_READ_SWAP_SUPPORTED)\r
+   /* swap bytes of 16 bit files to least significant byte first\r
+    */\r
+   if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)\r
+       png_set_swap(png_ptr);\r
+#endif\r
+\r
+   /* We don't handle adding filler bytes */\r
+\r
+   /* Optional call to gamma correct and add the background to the palette\r
+    * and update info structure.  REQUIRED if you are expecting libpng to\r
+    * update the palette for you (i.e., you selected such a transform above).\r
+    */\r
+   png_read_update_info(png_ptr, info_ptr);\r
+\r
+   /* -------------- image transformations end here ------------------- */\r
+\r
+#ifdef PNG_FREE_ME_SUPPORTED\r
+   png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);\r
+#endif\r
+   if (info_ptr->row_pointers == NULL)\r
+   {\r
+      info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr,\r
+         info_ptr->height * png_sizeof(png_bytep));\r
+#ifdef PNG_FREE_ME_SUPPORTED\r
+      info_ptr->free_me |= PNG_FREE_ROWS;\r
+#endif\r
+      for (row = 0; row < (int)info_ptr->height; row++)\r
+      {\r
+         info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr,\r
+            png_get_rowbytes(png_ptr, info_ptr));\r
+      }\r
+   }\r
+\r
+   png_read_image(png_ptr, info_ptr->row_pointers);\r
+   info_ptr->valid |= PNG_INFO_IDAT;\r
+\r
+   /* read rest of file, and get additional chunks in info_ptr - REQUIRED */\r
+   png_read_end(png_ptr, info_ptr);\r
+\r
+   transforms = transforms; /* quiet compiler warnings */\r
+   params = params;\r
+\r
+}\r
+#endif /* PNG_INFO_IMAGE_SUPPORTED */\r
+#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */\r
+#endif /* PNG_READ_SUPPORTED */\r