Imported Upstream version 1.6.13
[platform/upstream/libpng.git] / contrib / gregbook / readpng2.c
index 2ee6b68..2e4c536 100644 (file)
 
 
 #include <stdlib.h>     /* for exit() prototype */
+#include <setjmp.h>
 
-#include "png.h"        /* libpng header; includes zlib.h and setjmp.h */
+#include <zlib.h>
+#include "png.h"        /* libpng header from the local directory */
 #include "readpng2.h"   /* typedefs, common macros, public prototypes */
 
 
@@ -67,90 +69,17 @@ static void readpng2_row_callback(png_structp png_ptr, png_bytep new_row,
                                  png_uint_32 row_num, int pass);
 static void readpng2_end_callback(png_structp png_ptr, png_infop info_ptr);
 static void readpng2_error_handler(png_structp png_ptr, png_const_charp msg);
+static void readpng2_warning_handler(png_structp png_ptr, png_const_charp msg);
 
 
 
 
 void readpng2_version_info(void)
 {
-#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) && \
-    (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__)) && \
-    defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200)
-    /*
-     * WARNING:  This preprocessor approach means that the following code
-     *           cannot be used with a libpng DLL older than 1.2.0--the
-     *           compiled-in symbols for the new functions will not exist.
-     *           (Could use dlopen() and dlsym() on Unix and corresponding
-     *           calls for Windows, but not portable...)
-     */
-    {
-        int mmxsupport = png_mmx_support();
-        if (mmxsupport < 0)
-            fprintf(stderr, "   Compiled with libpng %s; using libpng %s "
-              "without MMX support.\n", PNG_LIBPNG_VER_STRING, png_libpng_ver);
-        else {
-            int compilerID;
-            png_uint_32 mmx_mask = png_get_mmx_flagmask(
-              PNG_SELECT_READ | PNG_SELECT_WRITE, &compilerID);
-
-            fprintf(stderr, "   Compiled with libpng %s; using libpng %s "
-              "with MMX support\n   (%s version).", PNG_LIBPNG_VER_STRING,
-              png_libpng_ver, compilerID == 1? "MSVC++" :
-              (compilerID == 2? "GNU C" : "unknown"));
-            fprintf(stderr, "  Processor (x86%s) %s MMX instructions.\n",
-#if defined(__x86_64__)
-              "_64",
-#else
-              "",
-#endif
-              mmxsupport? "supports" : "does not support");
-            if (mmxsupport > 0) {
-                int num_optims = 0;
-
-                fprintf(stderr,
-                  "      Potential MMX optimizations supported by libpng:\n");
-                if (mmx_mask & PNG_ASM_FLAG_MMX_READ_FILTER_SUB)
-                    ++num_optims;
-                if (mmx_mask & PNG_ASM_FLAG_MMX_READ_FILTER_UP)
-                    ++num_optims;
-                if (mmx_mask & PNG_ASM_FLAG_MMX_READ_FILTER_AVG)
-                    ++num_optims;
-                if (mmx_mask & PNG_ASM_FLAG_MMX_READ_FILTER_PAETH)
-                    ++num_optims;
-                if (num_optims)
-                    fprintf(stderr,
-                      "         decoding %s row filters (reading)\n",
-                      (num_optims == 4)? "all non-trivial" : "some");
-                if (mmx_mask & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW) {
-                    fprintf(stderr, "         combining rows (reading)\n");
-                    ++num_optims;
-                }
-                if (mmx_mask & PNG_ASM_FLAG_MMX_READ_INTERLACE) {
-                    fprintf(stderr,
-                      "         expanding interlacing (reading)\n");
-                    ++num_optims;
-                }
-                mmx_mask &= ~( PNG_ASM_FLAG_MMX_READ_COMBINE_ROW  \
-                             | PNG_ASM_FLAG_MMX_READ_INTERLACE    \
-                             | PNG_ASM_FLAG_MMX_READ_FILTER_SUB   \
-                             | PNG_ASM_FLAG_MMX_READ_FILTER_UP    \
-                             | PNG_ASM_FLAG_MMX_READ_FILTER_AVG   \
-                             | PNG_ASM_FLAG_MMX_READ_FILTER_PAETH );
-                if (mmx_mask) {
-                    fprintf(stderr, "         other (unknown)\n");
-                    ++num_optims;
-                }
-                if (num_optims == 0)
-                    fprintf(stderr, "         (none)\n");
-            }
-        }
-    }
-#else
-    fprintf(stderr, "   Compiled with libpng %s; using libpng %s "
-      "without MMX support.\n", PNG_LIBPNG_VER_STRING, png_libpng_ver);
-#endif
+    fprintf(stderr, "   Compiled with libpng %s; using libpng %s\n",
+      PNG_LIBPNG_VER_STRING, png_libpng_ver);
 
-    fprintf(stderr, "   Compiled with zlib %s; using zlib %s.\n",
+    fprintf(stderr, "   and with zlib %s; using zlib %s.\n",
       ZLIB_VERSION, zlib_version);
 }
 
@@ -176,7 +105,7 @@ int readpng2_init(mainprog_info *mainprog_ptr)
     /* could also replace libpng warning-handler (final NULL), but no need: */
 
     png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, mainprog_ptr,
-      readpng2_error_handler, NULL);
+      readpng2_error_handler, readpng2_warning_handler);
     if (!png_ptr)
         return 4;   /* out of memory */
 
@@ -203,36 +132,30 @@ int readpng2_init(mainprog_info *mainprog_ptr)
     }
 
 
-#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
     /* prepare the reader to ignore all recognized chunks whose data won't be
      * used, i.e., all chunks recognized by libpng except for IHDR, PLTE, IDAT,
      * IEND, tRNS, bKGD, gAMA, and sRGB (small performance improvement) */
     {
-        /* These byte strings were copied from png.h.  If a future libpng
-         * version recognizes more chunks, add them to this list.  If a
-         * future version of readpng2.c recognizes more chunks, delete them
-         * from this list. */
-        static const png_byte chunks_to_ignore[] = {
-             99,  72,  82,  77, '\0',  /* cHRM */
-            104,  73,  83,  84, '\0',  /* hIST */
-            105,  67,  67,  80, '\0',  /* iCCP */
-            105,  84,  88, 116, '\0',  /* iTXt */
-            111,  70,  70, 115, '\0',  /* oFFs */
-            112,  67,  65,  76, '\0',  /* pCAL */
-            112,  72,  89, 115, '\0',  /* pHYs */
-            115,  66,  73,  84, '\0',  /* sBIT */
-            115,  67,  65,  76, '\0',  /* sCAL */
-            115,  80,  76,  84, '\0',  /* sPLT */
-            115,  84,  69,  82, '\0',  /* sTER */
-            116,  69,  88, 116, '\0',  /* tEXt */
-            116,  73,  77,  69, '\0',  /* tIME */
-            122,  84,  88, 116, '\0'   /* zTXt */
-        };
-
-        png_set_keep_unknown_chunks(png_ptr, 1 /* PNG_HANDLE_CHUNK_NEVER */,
-          chunks_to_ignore, sizeof(chunks_to_ignore)/5);
+        /* These byte strings were copied from png.h.  If a future version
+         * of readpng2.c recognizes more chunks, add them to this list.
+         */
+        static PNG_CONST png_byte chunks_to_process[] = {
+            98,  75,  71,  68, '\0',  /* bKGD */
+           103,  65,  77,  65, '\0',  /* gAMA */
+           115,  82,  71,  66, '\0',  /* sRGB */
+           };
+
+       /* Ignore all chunks except for IHDR, PLTE, tRNS, IDAT, and IEND */
+       png_set_keep_unknown_chunks(png_ptr, -1 /* PNG_HANDLE_CHUNK_NEVER */,
+          NULL, -1);
+
+       /* But do not ignore chunks in the "chunks_to_process" list */
+       png_set_keep_unknown_chunks(png_ptr,
+          0 /* PNG_HANDLE_CHUNK_AS_DEFAULT */, chunks_to_process,
+          sizeof(chunks_to_process)/5);
     }
-#endif /* PNG_UNKNOWN_CHUNKS_SUPPORTED */
+#endif /* PNG_HANDLE_AS_UNKNOWN_SUPPORTED */
 
 
     /* instead of doing png_init_io() here, now we set up our callback
@@ -242,96 +165,6 @@ int readpng2_init(mainprog_info *mainprog_ptr)
       readpng2_info_callback, readpng2_row_callback, readpng2_end_callback);
 
 
-    /*
-     * may as well enable or disable MMX routines here, if supported;
-     *
-     * to enable all:  mask = png_get_mmx_flagmask (
-     *                   PNG_SELECT_READ | PNG_SELECT_WRITE, &compilerID);
-     *                 flags = png_get_asm_flags (png_ptr);
-     *                 flags |= mask;
-     *                 png_set_asm_flags (png_ptr, flags);
-     *
-     * to disable all:  mask = png_get_mmx_flagmask (
-     *                   PNG_SELECT_READ | PNG_SELECT_WRITE, &compilerID);
-     *                  flags = png_get_asm_flags (png_ptr);
-     *                  flags &= ~mask;
-     *                  png_set_asm_flags (png_ptr, flags);
-     */
-
-#if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__)) && \
-    defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200)
-    /*
-     * WARNING:  This preprocessor approach means that the following code
-     *           cannot be used with a libpng DLL older than 1.2.0--the
-     *           compiled-in symbols for the new functions will not exist.
-     *           (Could use dlopen() and dlsym() on Unix and corresponding
-     *           calls for Windows, but not portable...)
-     */
-    {
-#ifdef PNG_ASSEMBLER_CODE_SUPPORTED
-        png_uint_32 mmx_disable_mask = 0;
-        png_uint_32 asm_flags, mmx_mask;
-        int compilerID;
-
-        if (mainprog_ptr->nommxfilters)
-            mmx_disable_mask |= ( PNG_ASM_FLAG_MMX_READ_FILTER_SUB   \
-                                | PNG_ASM_FLAG_MMX_READ_FILTER_UP    \
-                                | PNG_ASM_FLAG_MMX_READ_FILTER_AVG   \
-                                | PNG_ASM_FLAG_MMX_READ_FILTER_PAETH );
-        if (mainprog_ptr->nommxcombine)
-            mmx_disable_mask |= PNG_ASM_FLAG_MMX_READ_COMBINE_ROW;
-        if (mainprog_ptr->nommxinterlace)
-            mmx_disable_mask |= PNG_ASM_FLAG_MMX_READ_INTERLACE;
-        asm_flags = png_get_asm_flags(png_ptr);
-        png_set_asm_flags(png_ptr, asm_flags & ~mmx_disable_mask);
-
-
-        /* Now query libpng's asm settings, just for yuks.  Note that this
-         * differs from the querying of its *potential* MMX capabilities
-         * in readpng2_version_info(); this is true runtime verification. */
-
-        asm_flags = png_get_asm_flags(png_ptr);
-        mmx_mask = png_get_mmx_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE,
-          &compilerID);
-        if (asm_flags & PNG_ASM_FLAG_MMX_SUPPORT_COMPILED)
-            fprintf(stderr,
-              "  MMX support (%s version) is compiled into libpng\n",
-              compilerID == 1? "MSVC++" :
-              (compilerID == 2? "GNU C" : "unknown"));
-        else
-            fprintf(stderr, "  MMX support is not compiled into libpng\n");
-        fprintf(stderr, "  MMX instructions are %ssupported by CPU\n",
-          (asm_flags & PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU)? "" : "not ");
-        fprintf(stderr, "  MMX read support for combining rows is %sabled\n",
-          (asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW)? "en" : "dis");
-        fprintf(stderr,
-          "  MMX read support for expanding interlacing is %sabled\n",
-          (asm_flags & PNG_ASM_FLAG_MMX_READ_INTERLACE)? "en" : "dis");
-        fprintf(stderr, "  MMX read support for \"sub\" filter is %sabled\n",
-          (asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_SUB)? "en" : "dis");
-        fprintf(stderr, "  MMX read support for \"up\" filter is %sabled\n",
-          (asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_UP)? "en" : "dis");
-        fprintf(stderr, "  MMX read support for \"avg\" filter is %sabled\n",
-          (asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_AVG)? "en" : "dis");
-        fprintf(stderr, "  MMX read support for \"Paeth\" filter is %sabled\n",
-          (asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_PAETH)? "en" : "dis");
-        asm_flags &= (mmx_mask & ~( PNG_ASM_FLAG_MMX_READ_COMBINE_ROW  \
-                                  | PNG_ASM_FLAG_MMX_READ_INTERLACE    \
-                                  | PNG_ASM_FLAG_MMX_READ_FILTER_SUB   \
-                                  | PNG_ASM_FLAG_MMX_READ_FILTER_UP    \
-                                  | PNG_ASM_FLAG_MMX_READ_FILTER_AVG   \
-                                  | PNG_ASM_FLAG_MMX_READ_FILTER_PAETH ));
-        if (asm_flags)
-            fprintf(stderr,
-              "  additional MMX support is also enabled (0x%02lx)\n",
-              asm_flags);
-#else  /* !PNG_ASSEMBLER_CODE_SUPPORTED */
-        fprintf(stderr, "  MMX querying is disabled in libpng.\n");
-#endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */
-    }
-#endif
-
-
     /* make sure we save our pointers for use in readpng2_decode_data() */
 
     mainprog_ptr->png_ptr = png_ptr;
@@ -380,7 +213,11 @@ static void readpng2_info_callback(png_structp png_ptr, png_infop info_ptr)
     mainprog_info  *mainprog_ptr;
     int  color_type, bit_depth;
     png_uint_32 width, height;
+#ifdef PNG_FLOATING_POINT_SUPPORTED
     double  gamma;
+#else
+    png_fixed_point gamma;
+#endif
 
 
     /* setjmp() doesn't make sense here, because we'd either have to exit(),
@@ -469,8 +306,14 @@ static void readpng2_info_callback(png_structp png_ptr, png_infop info_ptr)
         png_set_expand(png_ptr);
     if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
         png_set_expand(png_ptr);
+#ifdef PNG_READ_16_TO_8_SUPPORTED
     if (bit_depth == 16)
+#  ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
+        png_set_scale_16(png_ptr);
+#  else
         png_set_strip_16(png_ptr);
+#  endif
+#endif
     if (color_type == PNG_COLOR_TYPE_GRAY ||
         color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
         png_set_gray_to_rgb(png_ptr);
@@ -491,11 +334,19 @@ static void readpng2_info_callback(png_structp png_ptr, png_infop info_ptr)
      * "gamma" value for the entire display system, i.e., the product of
      * LUT_exponent and CRT_exponent. */
 
+#ifdef PNG_FLOATING_POINT_SUPPORTED
     if (png_get_gAMA(png_ptr, info_ptr, &gamma))
         png_set_gamma(png_ptr, mainprog_ptr->display_exponent, gamma);
     else
         png_set_gamma(png_ptr, mainprog_ptr->display_exponent, 0.45455);
-
+#else
+    if (png_get_gAMA_fixed(png_ptr, info_ptr, &gamma))
+        png_set_gamma_fixed(png_ptr,
+            (png_fixed_point)(100000*mainprog_ptr->display_exponent+.5), gamma);
+    else
+        png_set_gamma_fixed(png_ptr,
+            (png_fixed_point)(100000*mainprog_ptr->display_exponent+.5), 45455);
+#endif
 
     /* we'll let libpng expand interlaced images, too */
 
@@ -597,6 +448,8 @@ static void readpng2_end_callback(png_structp png_ptr, png_infop info_ptr)
 
     /* all done */
 
+    (void)info_ptr; /* Unused */
+
     return;
 }
 
@@ -617,7 +470,12 @@ void readpng2_cleanup(mainprog_info *mainprog_ptr)
 }
 
 
-
+static void readpng2_warning_handler(png_structp png_ptr, png_const_charp msg)
+{
+    fprintf(stderr, "readpng2 libpng warning: %s\n", msg);
+    fflush(stderr);
+    (void)png_ptr; /* Unused */
+}
 
 
 static void readpng2_error_handler(png_structp png_ptr, png_const_charp msg)
@@ -644,5 +502,12 @@ static void readpng2_error_handler(png_structp png_ptr, png_const_charp msg)
         exit(99);
     }
 
+    /* Now we have our data structure we can use the information in it
+     * to return control to our own higher level code (all the points
+     * where 'setjmp' is called in this file.)  This will work with other
+     * error handling mechanisms as well - libpng always calls png_error
+     * when it can proceed no further, thus, so long as the error handler
+     * is intercepted, application code can do its own error recovery.
+     */
     longjmp(mainprog_ptr->jmpbuf, 1);
 }