windowscodecs: Generate a palette for color-keyed grayscale PNG's.

Signed-off-by: Vincent Povirk <vincent@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Vincent Povirk 2017-09-07 15:52:05 -05:00 committed by Alexandre Julliard
parent 9991e4f2ae
commit 66b126b675
5 changed files with 77 additions and 86 deletions

16
configure vendored
View File

@ -13890,23 +13890,7 @@ cat >>confdefs.h <<_ACEOF
#define SONAME_LIBPNG "$ac_cv_lib_soname_png" #define SONAME_LIBPNG "$ac_cv_lib_soname_png"
_ACEOF _ACEOF
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <png.h>
int
main ()
{
typeof(png_set_expand_gray_1_2_4_to_8) *p
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
$as_echo "#define HAVE_PNG_SET_EXPAND_GRAY_1_2_4_TO_8 1" >>confdefs.h
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi fi
else else
PNG_CFLAGS="" PNG_CFLAGS=""

View File

@ -1647,9 +1647,7 @@ then
[AC_CHECK_HEADERS([png.h]) [AC_CHECK_HEADERS([png.h])
if test "$ac_cv_header_png_h" = "yes" if test "$ac_cv_header_png_h" = "yes"
then then
WINE_CHECK_SONAME(png,png_create_read_struct, WINE_CHECK_SONAME(png,png_create_read_struct,,
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <png.h>]],[[typeof(png_set_expand_gray_1_2_4_to_8) *p]])],
[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.])])],
[PNG_CFLAGS=""],[$PNG_LIBS -lm -lz],[[libpng[[0-9]]*]]) [PNG_CFLAGS=""],[$PNG_LIBS -lm -lz],[[libpng[[0-9]]*]])
else else
PNG_CFLAGS="" PNG_CFLAGS=""

View File

@ -319,11 +319,6 @@ MAKE_FUNCPTR(png_get_tRNS);
MAKE_FUNCPTR(png_set_bgr); MAKE_FUNCPTR(png_set_bgr);
MAKE_FUNCPTR(png_set_crc_action); MAKE_FUNCPTR(png_set_crc_action);
MAKE_FUNCPTR(png_set_error_fn); MAKE_FUNCPTR(png_set_error_fn);
#ifdef 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_filler);
MAKE_FUNCPTR(png_set_filter); MAKE_FUNCPTR(png_set_filter);
MAKE_FUNCPTR(png_set_gray_to_rgb); MAKE_FUNCPTR(png_set_gray_to_rgb);
@ -388,11 +383,6 @@ static void *load_libpng(void)
LOAD_FUNCPTR(png_set_bgr); LOAD_FUNCPTR(png_set_bgr);
LOAD_FUNCPTR(png_set_crc_action); LOAD_FUNCPTR(png_set_crc_action);
LOAD_FUNCPTR(png_set_error_fn); LOAD_FUNCPTR(png_set_error_fn);
#ifdef 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_filler);
LOAD_FUNCPTR(png_set_filter); LOAD_FUNCPTR(png_set_filter);
LOAD_FUNCPTR(png_set_gray_to_rgb); LOAD_FUNCPTR(png_set_gray_to_rgb);
@ -651,43 +641,18 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
/* check for color-keyed alpha */ /* check for color-keyed alpha */
transparency = ppng_get_tRNS(This->png_ptr, This->info_ptr, &trans, &num_trans, &trans_values); transparency = ppng_get_tRNS(This->png_ptr, This->info_ptr, &trans, &num_trans, &trans_values);
if (transparency && color_type != PNG_COLOR_TYPE_PALETTE) if (transparency && (color_type == PNG_COLOR_TYPE_RGB ||
(color_type == PNG_COLOR_TYPE_GRAY && bit_depth == 16)))
{ {
/* expand to RGBA */ /* expand to RGBA */
if (color_type == PNG_COLOR_TYPE_GRAY) if (color_type == PNG_COLOR_TYPE_GRAY)
{
if (bit_depth < 8)
{
#ifdef 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); ppng_set_gray_to_rgb(This->png_ptr);
}
ppng_set_tRNS_to_alpha(This->png_ptr); ppng_set_tRNS_to_alpha(This->png_ptr);
color_type = PNG_COLOR_TYPE_RGB_ALPHA; color_type = PNG_COLOR_TYPE_RGB_ALPHA;
} }
switch (color_type) switch (color_type)
{ {
case PNG_COLOR_TYPE_GRAY:
This->bpp = bit_depth;
switch (bit_depth)
{
case 1: This->format = &GUID_WICPixelFormatBlackWhite; break;
case 2: This->format = &GUID_WICPixelFormat2bppGray; break;
case 4: This->format = &GUID_WICPixelFormat4bppGray; break;
case 8: This->format = &GUID_WICPixelFormat8bppGray; break;
case 16: This->format = &GUID_WICPixelFormat16bppGray; break;
default:
ERR("invalid grayscale bit depth: %i\n", bit_depth);
hr = E_FAIL;
goto end;
}
break;
case PNG_COLOR_TYPE_GRAY_ALPHA: case PNG_COLOR_TYPE_GRAY_ALPHA:
/* WIC does not support grayscale alpha formats so use RGBA */ /* WIC does not support grayscale alpha formats so use RGBA */
ppng_set_gray_to_rgb(This->png_ptr); ppng_set_gray_to_rgb(This->png_ptr);
@ -707,6 +672,25 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
goto end; goto end;
} }
break; break;
case PNG_COLOR_TYPE_GRAY:
This->bpp = bit_depth;
if (!transparency)
{
switch (bit_depth)
{
case 1: This->format = &GUID_WICPixelFormatBlackWhite; break;
case 2: This->format = &GUID_WICPixelFormat2bppGray; break;
case 4: This->format = &GUID_WICPixelFormat4bppGray; break;
case 8: This->format = &GUID_WICPixelFormat8bppGray; break;
case 16: This->format = &GUID_WICPixelFormat16bppGray; break;
default:
ERR("invalid grayscale bit depth: %i\n", bit_depth);
hr = E_FAIL;
goto end;
}
break;
}
/* else fall through */
case PNG_COLOR_TYPE_PALETTE: case PNG_COLOR_TYPE_PALETTE:
This->bpp = bit_depth; This->bpp = bit_depth;
switch (bit_depth) switch (bit_depth)
@ -1034,7 +1018,7 @@ static HRESULT WINAPI PngDecoder_Frame_CopyPalette(IWICBitmapFrameDecode *iface,
IWICPalette *pIPalette) IWICPalette *pIPalette)
{ {
PngDecoder *This = impl_from_IWICBitmapFrameDecode(iface); PngDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
png_uint_32 ret; png_uint_32 ret, color_type, bit_depth;
png_colorp png_palette; png_colorp png_palette;
int num_palette; int num_palette;
WICColor palette[256]; WICColor palette[256];
@ -1048,30 +1032,58 @@ static HRESULT WINAPI PngDecoder_Frame_CopyPalette(IWICBitmapFrameDecode *iface,
EnterCriticalSection(&This->lock); EnterCriticalSection(&This->lock);
ret = ppng_get_PLTE(This->png_ptr, This->info_ptr, &png_palette, &num_palette); color_type = ppng_get_color_type(This->png_ptr, This->info_ptr);
if (!ret) bit_depth = ppng_get_bit_depth(This->png_ptr, This->info_ptr);
if (color_type == PNG_COLOR_TYPE_PALETTE)
{
ret = ppng_get_PLTE(This->png_ptr, This->info_ptr, &png_palette, &num_palette);
if (!ret)
{
hr = WINCODEC_ERR_PALETTEUNAVAILABLE;
goto end;
}
if (num_palette > 256)
{
ERR("palette has %i colors?!\n", num_palette);
hr = E_FAIL;
goto end;
}
ret = ppng_get_tRNS(This->png_ptr, This->info_ptr, &trans_alpha, &num_trans, &trans_values);
if (!ret) num_trans = 0;
for (i=0; i<num_palette; i++)
{
BYTE alpha = (i < num_trans) ? trans_alpha[i] : 0xff;
palette[i] = (alpha << 24 |
png_palette[i].red << 16|
png_palette[i].green << 8|
png_palette[i].blue);
}
}
else if (color_type == PNG_COLOR_TYPE_GRAY) {
ret = ppng_get_tRNS(This->png_ptr, This->info_ptr, &trans_alpha, &num_trans, &trans_values);
if (!ret)
{
hr = WINCODEC_ERR_PALETTEUNAVAILABLE;
goto end;
}
num_palette = 1 << bit_depth;
for (i=0; i<num_palette; i++)
{
BYTE alpha = (i == trans_values[0].gray) ? 0 : 0xff;
BYTE val = i * 255 / (num_palette - 1);
palette[i] = (alpha << 24 | val << 16 | val << 8 | val);
}
}
else
{ {
hr = WINCODEC_ERR_PALETTEUNAVAILABLE; hr = WINCODEC_ERR_PALETTEUNAVAILABLE;
goto end;
}
if (num_palette > 256)
{
ERR("palette has %i colors?!\n", num_palette);
hr = E_FAIL;
goto end;
}
ret = ppng_get_tRNS(This->png_ptr, This->info_ptr, &trans_alpha, &num_trans, &trans_values);
if (!ret) num_trans = 0;
for (i=0; i<num_palette; i++)
{
BYTE alpha = (i < num_trans) ? trans_alpha[i] : 0xff;
palette[i] = (alpha << 24 |
png_palette[i].red << 16|
png_palette[i].green << 8|
png_palette[i].blue);
} }
end: end:

View File

@ -674,10 +674,10 @@ static void test_color_formats(void)
{ 24, 2, NULL, NULL, NULL }, { 24, 2, NULL, NULL, NULL },
{ 32, 2, NULL, NULL, NULL }, { 32, 2, NULL, NULL, NULL },
/* 0 - PNG_COLOR_TYPE_GRAY */ /* 0 - PNG_COLOR_TYPE_GRAY */
{ 1, 0, &GUID_WICPixelFormatBlackWhite, &GUID_WICPixelFormatBlackWhite, &GUID_WICPixelFormat1bppIndexed, TRUE }, { 1, 0, &GUID_WICPixelFormatBlackWhite, &GUID_WICPixelFormatBlackWhite, &GUID_WICPixelFormat1bppIndexed },
{ 2, 0, &GUID_WICPixelFormat2bppGray, &GUID_WICPixelFormat2bppGray, &GUID_WICPixelFormat2bppIndexed, TRUE }, { 2, 0, &GUID_WICPixelFormat2bppGray, &GUID_WICPixelFormat2bppGray, &GUID_WICPixelFormat2bppIndexed },
{ 4, 0, &GUID_WICPixelFormat4bppGray, &GUID_WICPixelFormat4bppGray, &GUID_WICPixelFormat4bppIndexed, TRUE }, { 4, 0, &GUID_WICPixelFormat4bppGray, &GUID_WICPixelFormat4bppGray, &GUID_WICPixelFormat4bppIndexed },
{ 8, 0, &GUID_WICPixelFormat8bppGray, &GUID_WICPixelFormat8bppGray, &GUID_WICPixelFormat8bppIndexed, TRUE }, { 8, 0, &GUID_WICPixelFormat8bppGray, &GUID_WICPixelFormat8bppGray, &GUID_WICPixelFormat8bppIndexed },
{ 16, 0, &GUID_WICPixelFormat16bppGray, &GUID_WICPixelFormat16bppGray, &GUID_WICPixelFormat64bppRGBA }, { 16, 0, &GUID_WICPixelFormat16bppGray, &GUID_WICPixelFormat16bppGray, &GUID_WICPixelFormat64bppRGBA },
{ 24, 0, NULL, NULL, NULL }, { 24, 0, NULL, NULL, NULL },
{ 32, 0, NULL, NULL, NULL }, { 32, 0, NULL, NULL, NULL },

View File

@ -711,9 +711,6 @@
/* Define to 1 if you have the <png.h> header file. */ /* Define to 1 if you have the <png.h> header file. */
#undef HAVE_PNG_H #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. */ /* Define to 1 if you have the `poll' function. */
#undef HAVE_POLL #undef HAVE_POLL