windowscodecs: add png_set_expand_gray_1_2_4_to_8 support (new libpng 1.4)
authorVitaly Lipatov <lav@etersoft.ru>
Tue, 22 Jun 2010 16:23:54 +0000 (20:23 +0400)
committerVitaly Lipatov <lav@etersoft.ru>
Tue, 22 Jun 2010 16:31:43 +0000 (20:31 +0400)
configure
configure.ac
dlls/windowscodecs/pngformat.c
include/config.h.in

index 04df506e9dce41353438ed1040e97f27f81c3905..1f67c3706d498cd9c5872338123d563be6354526 100755 (executable)
--- a/configure
+++ b/configure
@@ -11450,6 +11450,49 @@ _ACEOF
 
 
 fi
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for png_set_expand_gray_1_2_4_to_8 in -lpng" >&5
+$as_echo_n "checking for png_set_expand_gray_1_2_4_to_8 in -lpng... " >&6; }
+if test "${ac_cv_lib_png_png_set_expand_gray_1_2_4_to_8+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpng -lm -lz $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char png_set_expand_gray_1_2_4_to_8 ();
+int
+main ()
+{
+return png_set_expand_gray_1_2_4_to_8 ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_png_png_set_expand_gray_1_2_4_to_8=yes
+else
+  ac_cv_lib_png_png_set_expand_gray_1_2_4_to_8=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_png_png_set_expand_gray_1_2_4_to_8" >&5
+$as_echo "$ac_cv_lib_png_png_set_expand_gray_1_2_4_to_8" >&6; }
+if test "x$ac_cv_lib_png_png_set_expand_gray_1_2_4_to_8" = x""yes; then :
+
+$as_echo "#define HAVE_PNG_SET_EXPAND_GRAY_1_2_4_TO_8 1" >>confdefs.h
+
+
+fi
+
 elif test -n "$X_CFLAGS" -a "x$with_png" != "xno"
 then
         ac_save_CPPFLAGS="$CPPFLAGS"
@@ -11522,6 +11565,47 @@ _ACEOF
 
 
 fi
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for png_set_expand_gray_1_2_4_to_8 in -lpng" >&5
+$as_echo_n "checking for png_set_expand_gray_1_2_4_to_8 in -lpng... " >&6; }
+if test "${ac_cv_lib_png_png_set_expand_gray_1_2_4_to_8+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpng $X_LIBS -lm -lz $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char png_set_expand_gray_1_2_4_to_8 ();
+int
+main ()
+{
+return png_set_expand_gray_1_2_4_to_8 ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_png_png_set_expand_gray_1_2_4_to_8=yes
+else
+  ac_cv_lib_png_png_set_expand_gray_1_2_4_to_8=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_png_png_set_expand_gray_1_2_4_to_8" >&5
+$as_echo "$ac_cv_lib_png_png_set_expand_gray_1_2_4_to_8" >&6; }
+if test "x$ac_cv_lib_png_png_set_expand_gray_1_2_4_to_8" = x""yes; then :
+  $as_echo "#define HAVE_PNG_SET_EXPAND_GRAY_1_2_4_TO_8 1" >>confdefs.h
+
+fi
+
     fi
 fi
 if test "x$ac_cv_lib_soname_png" = "x"; then :
index ddd1fc10c795ac96c97afbb8de4bae4cf14eeb09..53b1b1aa4e5e46c57230a86c519674375e82ade1 100644 (file)
@@ -1332,6 +1332,9 @@ dnl **** Check for libpng ****
 if test "$ac_cv_header_png_h" = "yes"
 then
     WINE_CHECK_SONAME(png,png_create_read_struct,,,-lm -lz,[[libpng[[0-9]]*]])
+    AC_CHECK_LIB(png,png_set_expand_gray_1_2_4_to_8,
+       [AC_DEFINE(HAVE_PNG_SET_EXPAND_GRAY_1_2_4_TO_8,1,[Define to 1 if libpng has the png_set_expand_gray_1_2_4_to_8 function.])]
+       ,,-lm -lz)
 elif test -n "$X_CFLAGS" -a "x$with_png" != "xno"
 then
     dnl libpng is in the X directory on Mac OS X
@@ -1344,6 +1347,8 @@ then
     then
         AC_SUBST(PNGINCL,"$X_CFLAGS")
         WINE_CHECK_SONAME(png,png_create_read_struct,,,[$X_LIBS -lm -lz],[[libpng[[0-9]]*]])
+        AC_CHECK_LIB(png,png_set_expand_gray_1_2_4_to_8,
+               [AC_DEFINE(HAVE_PNG_SET_EXPAND_GRAY_1_2_4_TO_8,1)],,[$X_LIBS -lm -lz])
     fi
 fi
 WINE_WARNING_WITH(png,[test "x$ac_cv_lib_soname_png" = "x"],
index 3334d76361c0cf1450c385f2d43f11e382d59b87..a671ff73ede6fef815ae77ac2a5759c457b95956 100644 (file)
@@ -51,6 +51,7 @@ MAKE_FUNCPTR(png_destroy_write_struct);
 MAKE_FUNCPTR(png_error);
 MAKE_FUNCPTR(png_get_bit_depth);
 MAKE_FUNCPTR(png_get_color_type);
+MAKE_FUNCPTR(png_get_error_ptr);
 MAKE_FUNCPTR(png_get_image_height);
 MAKE_FUNCPTR(png_get_image_width);
 MAKE_FUNCPTR(png_get_io_ptr);
@@ -58,8 +59,13 @@ MAKE_FUNCPTR(png_get_pHYs);
 MAKE_FUNCPTR(png_get_PLTE);
 MAKE_FUNCPTR(png_get_tRNS);
 MAKE_FUNCPTR(png_set_bgr);
-MAKE_FUNCPTR(png_set_filler);
+MAKE_FUNCPTR(png_set_error_fn);
+#if HAVE_PNG_SET_EXPAND_GRAY_1_2_4_TO_8
+MAKE_FUNCPTR(png_set_expand_gray_1_2_4_to_8);
+#else
 MAKE_FUNCPTR(png_set_gray_1_2_4_to_8);
+#endif
+MAKE_FUNCPTR(png_set_filler);
 MAKE_FUNCPTR(png_set_gray_to_rgb);
 MAKE_FUNCPTR(png_set_IHDR);
 MAKE_FUNCPTR(png_set_pHYs);
@@ -92,6 +98,7 @@ static void *load_libpng(void)
         LOAD_FUNCPTR(png_error);
         LOAD_FUNCPTR(png_get_bit_depth);
         LOAD_FUNCPTR(png_get_color_type);
+        LOAD_FUNCPTR(png_get_error_ptr);
         LOAD_FUNCPTR(png_get_image_height);
         LOAD_FUNCPTR(png_get_image_width);
         LOAD_FUNCPTR(png_get_io_ptr);
@@ -99,8 +106,13 @@ static void *load_libpng(void)
         LOAD_FUNCPTR(png_get_PLTE);
         LOAD_FUNCPTR(png_get_tRNS);
         LOAD_FUNCPTR(png_set_bgr);
-        LOAD_FUNCPTR(png_set_filler);
+        LOAD_FUNCPTR(png_set_error_fn);
+#if HAVE_PNG_SET_EXPAND_GRAY_1_2_4_TO_8
+        LOAD_FUNCPTR(png_set_expand_gray_1_2_4_to_8);
+#else
         LOAD_FUNCPTR(png_set_gray_1_2_4_to_8);
+#endif
+        LOAD_FUNCPTR(png_set_filler);
         LOAD_FUNCPTR(png_set_gray_to_rgb);
         LOAD_FUNCPTR(png_set_IHDR);
         LOAD_FUNCPTR(png_set_pHYs);
@@ -120,6 +132,23 @@ static void *load_libpng(void)
     return libpng_handle;
 }
 
+static void user_error_fn(png_structp png_ptr, png_const_charp error_message)
+{
+    jmp_buf *pjmpbuf;
+
+    /* This uses setjmp/longjmp just like the default. We can't use the
+     * default because there's no way to access the jmp buffer in the png_struct
+     * that works in 1.2 and 1.4 and allows us to dynamically load libpng. */
+    WARN("PNG error: %s\n", debugstr_a(error_message));
+    pjmpbuf = ppng_get_error_ptr(png_ptr);
+    longjmp(*pjmpbuf, 1);
+}
+
+static void user_warning_fn(png_structp png_ptr, png_const_charp warning_message)
+{
+    WARN("PNG warning: %s\n", debugstr_a(warning_message));
+}
+
 typedef struct {
     const IWICBitmapDecoderVtbl *lpVtbl;
     const IWICBitmapFrameDecodeVtbl *lpFrameVtbl;
@@ -226,6 +255,8 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
     int num_trans;
     png_uint_32 transparency;
     png_color_16p trans_values;
+    jmp_buf jmpbuf;
+
     TRACE("(%p,%p,%x)\n", iface, pIStream, cacheOptions);
 
     /* initialize libpng */
@@ -249,13 +280,14 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
     }
 
     /* set up setjmp/longjmp error handling */
-    if (setjmp(png_jmpbuf(This->png_ptr)))
+    if (setjmp(jmpbuf))
     {
         ppng_destroy_read_struct(&This->png_ptr, &This->info_ptr, &This->end_info);
         HeapFree(GetProcessHeap(), 0, row_pointers);
         This->png_ptr = NULL;
         return E_FAIL;
     }
+    ppng_set_error_fn(This->png_ptr, &jmpbuf, user_error_fn, user_warning_fn);
 
     /* seek to the start of the stream */
     seek.QuadPart = 0;
@@ -282,7 +314,11 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
         {
             if (bit_depth < 8)
             {
+#if HAVE_PNG_SET_EXPAND_GRAY_1_2_4_TO_8
+                ppng_set_expand_gray_1_2_4_to_8(This->png_ptr);
+#else
                 ppng_set_gray_1_2_4_to_8(This->png_ptr);
+#endif
                 bit_depth = 8;
             }
             ppng_set_gray_to_rgb(This->png_ptr);
@@ -849,6 +885,7 @@ static HRESULT WINAPI PngFrameEncode_WritePixels(IWICBitmapFrameEncode *iface,
     PngEncoder *This = encoder_from_frame(iface);
     png_byte **row_pointers=NULL;
     UINT i;
+    jmp_buf jmpbuf;
     TRACE("(%p,%u,%u,%u,%p)\n", iface, lineCount, cbStride, cbBufferSize, pbPixels);
 
     if (!This->frame_initialized || !This->width || !This->height || !This->format)
@@ -858,11 +895,12 @@ static HRESULT WINAPI PngFrameEncode_WritePixels(IWICBitmapFrameEncode *iface,
         return E_INVALIDARG;
 
     /* set up setjmp/longjmp error handling */
-    if (setjmp(png_jmpbuf(This->png_ptr)))
+    if (setjmp(jmpbuf))
     {
         HeapFree(GetProcessHeap(), 0, row_pointers);
         return E_FAIL;
     }
+    ppng_set_error_fn(This->png_ptr, &jmpbuf, user_error_fn, user_warning_fn);
 
     if (!This->info_written)
     {
@@ -978,16 +1016,18 @@ static HRESULT WINAPI PngFrameEncode_WriteSource(IWICBitmapFrameEncode *iface,
 static HRESULT WINAPI PngFrameEncode_Commit(IWICBitmapFrameEncode *iface)
 {
     PngEncoder *This = encoder_from_frame(iface);
+    jmp_buf jmpbuf;
     TRACE("(%p)\n", iface);
 
     if (!This->info_written || This->lines_written != This->height || This->frame_committed)
         return WINCODEC_ERR_WRONGSTATE;
 
     /* set up setjmp/longjmp error handling */
-    if (setjmp(png_jmpbuf(This->png_ptr)))
+    if (setjmp(jmpbuf))
     {
         return E_FAIL;
     }
+    ppng_set_error_fn(This->png_ptr, &jmpbuf, user_error_fn, user_warning_fn);
 
     ppng_write_end(This->png_ptr, This->info_ptr);
 
@@ -1093,6 +1133,7 @@ static HRESULT WINAPI PngEncoder_Initialize(IWICBitmapEncoder *iface,
     IStream *pIStream, WICBitmapEncoderCacheOption cacheOption)
 {
     PngEncoder *This = (PngEncoder*)iface;
+    jmp_buf jmpbuf;
 
     TRACE("(%p,%p,%u)\n", iface, pIStream, cacheOption);
 
@@ -1116,7 +1157,7 @@ static HRESULT WINAPI PngEncoder_Initialize(IWICBitmapEncoder *iface,
     This->stream = pIStream;
 
     /* set up setjmp/longjmp error handling */
-    if (setjmp(png_jmpbuf(This->png_ptr)))
+    if (setjmp(jmpbuf))
     {
         ppng_destroy_write_struct(&This->png_ptr, &This->info_ptr);
         This->png_ptr = NULL;
@@ -1124,6 +1165,7 @@ static HRESULT WINAPI PngEncoder_Initialize(IWICBitmapEncoder *iface,
         This->stream = NULL;
         return E_FAIL;
     }
+    ppng_set_error_fn(This->png_ptr, &jmpbuf, user_error_fn, user_warning_fn);
 
     /* set up custom i/o handling */
     ppng_set_write_fn(This->png_ptr, This, user_write_data, user_flush);
index 41a81bcf04a05b0ea8ac13f49e7891e6f5b8bc31..71e86ad025fbafe269b99eb027ce1e846f2f72ad 100644 (file)
 /* Define to 1 if you have the <png.h> header file. */
 #undef HAVE_PNG_H
 
+/* Define to 1 if libpng has the png_set_expand_gray_1_2_4_to_8 function. */
+#undef HAVE_PNG_SET_EXPAND_GRAY_1_2_4_TO_8
+
 /* Define to 1 if you have the `poll' function. */
 #undef HAVE_POLL