Added patch to improve palette support in windowscodecs.dll.

This commit is contained in:
Sebastian Lackner 2016-09-28 17:55:15 +02:00
parent b3eb9ef535
commit 2bf9187a19
20 changed files with 2058 additions and 28 deletions

View File

@ -351,6 +351,7 @@ patch_enable_all ()
enable_windowscodecs_32bppGrayFloat="$1"
enable_windowscodecs_IMILBitmapSource="$1"
enable_windowscodecs_IWICPalette_InitializeFromBitmap="$1"
enable_windowscodecs_Palette_Images="$1"
enable_windowscodecs_WICCreateBitmapFromSection="$1"
enable_wine_inf_Directory_ContextMenuHandlers="$1"
enable_wine_inf_Dummy_CA_Certificate="$1"
@ -1233,6 +1234,9 @@ patch_enable ()
windowscodecs-IWICPalette_InitializeFromBitmap)
enable_windowscodecs_IWICPalette_InitializeFromBitmap="$2"
;;
windowscodecs-Palette_Images)
enable_windowscodecs_Palette_Images="$2"
;;
windowscodecs-WICCreateBitmapFromSection)
enable_windowscodecs_WICCreateBitmapFromSection="$2"
;;
@ -2036,6 +2040,13 @@ if test "$enable_wined3d_CSMT_Helper" -eq 1; then
enable_wined3d_Silence_FIXMEs=1
fi
if test "$enable_windowscodecs_Palette_Images" -eq 1; then
if test "$enable_windowscodecs_32bppGrayFloat" -gt 1; then
abort "Patchset windowscodecs-32bppGrayFloat disabled, but windowscodecs-Palette_Images depends on that."
fi
enable_windowscodecs_32bppGrayFloat=1
fi
if test "$enable_windowscodecs_IWICPalette_InitializeFromBitmap" -eq 1; then
if test "$enable_gdiplus_Grayscale_PNG" -gt 1; then
abort "Patchset gdiplus-Grayscale_PNG disabled, but windowscodecs-IWICPalette_InitializeFromBitmap depends on that."
@ -7176,20 +7187,66 @@ fi
# |
# | Modified files:
# | * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/image.c, dlls/gdiplus/tests/image.c, dlls/windowscodecs/palette.c,
# | dlls/windowscodecs/pngformat.c, dlls/windowscodecs/tests/palette.c, include/gdiplusflat.h
# | dlls/windowscodecs/tests/palette.c, include/gdiplusflat.h
# |
if test "$enable_windowscodecs_IWICPalette_InitializeFromBitmap" -eq 1; then
patch_apply windowscodecs-IWICPalette_InitializeFromBitmap/0001-windowscodecs-tests-Add-some-tests-for-IWICPalette-I.patch
patch_apply windowscodecs-IWICPalette_InitializeFromBitmap/0002-windowscodecs-Implement-IWICPalette-InitializeFromBi.patch
patch_apply windowscodecs-IWICPalette_InitializeFromBitmap/0003-gdiplus-Implement-GdipInitializePalette.-v2.patch
patch_apply windowscodecs-IWICPalette_InitializeFromBitmap/0004-gdiplus-tests-Add-some-tests-for-GdipInitializePalet.patch
patch_apply windowscodecs-IWICPalette_InitializeFromBitmap/0005-windowscodecs-Return-S_OK-from-PngFrameEncode_SetPal.patch
(
echo '+ { "Dmitry Timoshkov", "windowscodecs/tests: Add some tests for IWICPalette::InitializeFromBitmap.", 2 },';
echo '+ { "Dmitry Timoshkov", "windowscodecs: Implement IWICPalette::InitializeFromBitmap.", 5 },';
echo '+ { "Dmitry Timoshkov", "gdiplus: Implement GdipInitializePalette.", 2 },';
echo '+ { "Dmitry Timoshkov", "gdiplus/tests: Add some tests for GdipInitializePalette.", 2 },';
echo '+ { "Dmitry Timoshkov", "windowscodecs: Return S_OK from PngFrameEncode_SetPalette.", 1 },';
) >> "$patchlist"
fi
# Patchset windowscodecs-Palette_Images
# |
# | This patchset has the following (direct or indirect) dependencies:
# | * windowscodecs-32bppGrayFloat
# |
# | Modified files:
# | * dlls/windowscodecs/bmpdecode.c, dlls/windowscodecs/bmpencode.c, dlls/windowscodecs/main.c,
# | dlls/windowscodecs/pngformat.c, dlls/windowscodecs/tests/converter.c, dlls/windowscodecs/tiffformat.c
# |
if test "$enable_windowscodecs_Palette_Images" -eq 1; then
patch_apply windowscodecs-Palette_Images/0001-windowscodecs-Implement-IWICBitmapDecoder-CopyPalett.patch
patch_apply windowscodecs-Palette_Images/0002-windowscodecs-Implement-IWICBitmapFrameEncode-SetPal.patch
patch_apply windowscodecs-Palette_Images/0003-windowscodecs-Fix-IWICBitmapEncoder-SetPalette-for-a.patch
patch_apply windowscodecs-Palette_Images/0004-windowscodecs-Decode-PNG-images-with-a-tRNS-chunk-in.patch
patch_apply windowscodecs-Palette_Images/0005-windowscodecs-Add-support-for-palette-image-formats-.patch
patch_apply windowscodecs-Palette_Images/0006-windowscodecs-Fix-IWICBitmapEncoder-SetPalette-for-a.patch
patch_apply windowscodecs-Palette_Images/0007-windowscodecs-Implement-IWICBitmapFrameEncode-SetPal.patch
patch_apply windowscodecs-Palette_Images/0008-windowscodecs-Implement-IWICBitmapDecoder-CopyPalett.patch
patch_apply windowscodecs-Palette_Images/0009-windowscodecs-Implement-IWICBitmapFrameEncode-SetPal.patch
patch_apply windowscodecs-Palette_Images/0010-windowscodecs-Fix-IWICBitmapEncoder-SetPalette-for-a.patch
patch_apply windowscodecs-Palette_Images/0011-windowscodecs-tests-Add-some-tests-for-encoding-1bpp.patch
patch_apply windowscodecs-Palette_Images/0012-windowscodecs-tests-Add-tests-for-encoding-2bpp-4bpp.patch
patch_apply windowscodecs-Palette_Images/0013-windowscodecs-Use-V_UI1-instead-of-V_UNION-to-assign.patch
patch_apply windowscodecs-Palette_Images/0014-windowscodecs-Add-support-for-palette-image-formats-.patch
patch_apply windowscodecs-Palette_Images/0015-windowscodecs-Write-the-image-bits-as-a-bottom-top-a.patch
patch_apply windowscodecs-Palette_Images/0016-windowscodecs-Limit-number-of-colors-in-a-palette-in.patch
patch_apply windowscodecs-Palette_Images/0017-windowscodecs-Add-support-for-palette-image-formats-.patch
(
echo '+ { "Dmitry Timoshkov", "windowscodecs: Implement IWICBitmapDecoder::CopyPalette in PNG decoder.", 1 },';
echo '+ { "Dmitry Timoshkov", "windowscodecs: Implement IWICBitmapFrameEncode::SetPalette in PNG encoder.", 1 },';
echo '+ { "Dmitry Timoshkov", "windowscodecs: Fix IWICBitmapEncoder::SetPalette for a not initialized case in PNG encoder.", 1 },';
echo '+ { "Dmitry Timoshkov", "windowscodecs: Decode PNG images with a tRNS chunk in their native formats.", 1 },';
echo '+ { "Dmitry Timoshkov", "windowscodecs: Add support for palette image formats to PNG encoder.", 1 },';
echo '+ { "Dmitry Timoshkov", "windowscodecs: Fix IWICBitmapEncoder::SetPalette for a not initialized case in BMP encoder.", 1 },';
echo '+ { "Dmitry Timoshkov", "windowscodecs: Implement IWICBitmapFrameEncode::SetPalette in BMP encoder.", 1 },';
echo '+ { "Dmitry Timoshkov", "windowscodecs: Implement IWICBitmapDecoder::CopyPalette in TIFF decoder.", 1 },';
echo '+ { "Dmitry Timoshkov", "windowscodecs: Implement IWICBitmapFrameEncode::SetPalette in the TIFF encoder.", 1 },';
echo '+ { "Dmitry Timoshkov", "windowscodecs: Fix IWICBitmapEncoder::SetPalette for a not initialized case in TIFF encoder.", 1 },';
echo '+ { "Dmitry Timoshkov", "windowscodecs/tests: Add some tests for encoding 1bpp/8bpp images with a palette.", 1 },';
echo '+ { "Dmitry Timoshkov", "windowscodecs/tests: Add tests for encoding 2bpp/4bpp images with a palette.", 1 },';
echo '+ { "Dmitry Timoshkov", "windowscodecs: Use V_UI1() instead of V_UNION() to assign a VT_UI1 variant member.", 1 },';
echo '+ { "Dmitry Timoshkov", "windowscodecs: Add support for palette image formats to TIFF encoder.", 1 },';
echo '+ { "Dmitry Timoshkov", "windowscodecs: Write the image bits as a bottom-top array in BMP encoder.", 1 },';
echo '+ { "Dmitry Timoshkov", "windowscodecs: Limit number of colors in a palette in BMP decoder.", 1 },';
echo '+ { "Dmitry Timoshkov", "windowscodecs: Add support for palette image formats to BMP encoder.", 1 },';
) >> "$patchlist"
fi

View File

@ -1,25 +0,0 @@
From 611e1f496ee05a60f29088df17289ae6de9fded0 Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Tue, 26 Jul 2016 16:28:08 +0800
Subject: windowscodecs: Return S_OK from PngFrameEncode_SetPalette.
---
dlls/windowscodecs/pngformat.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c
index bb2aef9..b84e1e6 100644
--- a/dlls/windowscodecs/pngformat.c
+++ b/dlls/windowscodecs/pngformat.c
@@ -1539,7 +1539,7 @@ static HRESULT WINAPI PngFrameEncode_SetPalette(IWICBitmapFrameEncode *iface,
IWICPalette *pIPalette)
{
FIXME("(%p,%p): stub\n", iface, pIPalette);
- return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+ return S_OK;
}
static HRESULT WINAPI PngFrameEncode_SetThumbnail(IWICBitmapFrameEncode *iface,
--
2.9.0

View File

@ -0,0 +1,31 @@
From 3ed4435cbd9872e7cfc9122874839e3656b007a6 Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Tue, 20 Sep 2016 14:09:22 +0800
Subject: windowscodecs: Implement IWICBitmapDecoder::CopyPalette in PNG
decoder.
---
dlls/windowscodecs/pngformat.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c
index bb2aef9..623577e 100644
--- a/dlls/windowscodecs/pngformat.c
+++ b/dlls/windowscodecs/pngformat.c
@@ -855,10 +855,10 @@ static HRESULT WINAPI PngDecoder_GetDecoderInfo(IWICBitmapDecoder *iface,
}
static HRESULT WINAPI PngDecoder_CopyPalette(IWICBitmapDecoder *iface,
- IWICPalette *pIPalette)
+ IWICPalette *palette)
{
- FIXME("(%p,%p): stub\n", iface, pIPalette);
- return E_NOTIMPL;
+ TRACE("(%p,%p)\n", iface, palette);
+ return WINCODEC_ERR_PALETTEUNAVAILABLE;
}
static HRESULT WINAPI PngDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface,
--
2.9.0

View File

@ -0,0 +1,62 @@
From 252fc281bc7a0dbedec51582534184bfd83137d2 Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Tue, 20 Sep 2016 14:13:28 +0800
Subject: windowscodecs: Implement IWICBitmapFrameEncode::SetPalette in PNG
encoder.
---
dlls/windowscodecs/pngformat.c | 23 ++++++++++++++++++++---
1 file changed, 20 insertions(+), 3 deletions(-)
diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c
index 623577e..1fda2b7 100644
--- a/dlls/windowscodecs/pngformat.c
+++ b/dlls/windowscodecs/pngformat.c
@@ -1359,6 +1359,8 @@ typedef struct PngEncoder {
BYTE *data;
UINT stride;
UINT passes;
+ WICColor palette[256];
+ UINT colors;
} PngEncoder;
static inline PngEncoder *impl_from_IWICBitmapEncoder(IWICBitmapEncoder *iface)
@@ -1536,10 +1538,24 @@ static HRESULT WINAPI PngFrameEncode_SetColorContexts(IWICBitmapFrameEncode *ifa
}
static HRESULT WINAPI PngFrameEncode_SetPalette(IWICBitmapFrameEncode *iface,
- IWICPalette *pIPalette)
+ IWICPalette *palette)
{
- FIXME("(%p,%p): stub\n", iface, pIPalette);
- return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+ PngEncoder *This = impl_from_IWICBitmapFrameEncode(iface);
+ HRESULT hr;
+
+ TRACE("(%p,%p)\n", iface, palette);
+
+ if (!palette) return E_INVALIDARG;
+
+ EnterCriticalSection(&This->lock);
+
+ if (This->frame_initialized)
+ hr = IWICPalette_GetColors(palette, 256, This->palette, &This->colors);
+ else
+ hr = WINCODEC_ERR_NOTINITIALIZED;
+
+ LeaveCriticalSection(&This->lock);
+ return hr;
}
static HRESULT WINAPI PngFrameEncode_SetThumbnail(IWICBitmapFrameEncode *iface,
@@ -2044,6 +2060,7 @@ HRESULT PngEncoder_CreateInstance(REFIID iid, void** ppv)
This->frame_committed = FALSE;
This->committed = FALSE;
This->data = NULL;
+ This->colors = 0;
InitializeCriticalSection(&This->lock);
This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PngEncoder.lock");
--
2.9.0

View File

@ -0,0 +1,41 @@
From 21789956f3eab8c48e1291437a9edef7ab4de638 Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Tue, 20 Sep 2016 14:15:41 +0800
Subject: windowscodecs: Fix IWICBitmapEncoder::SetPalette for a not
initialized case in PNG encoder.
---
dlls/windowscodecs/pngformat.c | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c
index 1fda2b7..fa54a23 100644
--- a/dlls/windowscodecs/pngformat.c
+++ b/dlls/windowscodecs/pngformat.c
@@ -1919,10 +1919,20 @@ static HRESULT WINAPI PngEncoder_SetColorContexts(IWICBitmapEncoder *iface,
return E_NOTIMPL;
}
-static HRESULT WINAPI PngEncoder_SetPalette(IWICBitmapEncoder *iface, IWICPalette *pIPalette)
+static HRESULT WINAPI PngEncoder_SetPalette(IWICBitmapEncoder *iface, IWICPalette *palette)
{
- TRACE("(%p,%p)\n", iface, pIPalette);
- return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+ PngEncoder *This = impl_from_IWICBitmapEncoder(iface);
+ HRESULT hr;
+
+ TRACE("(%p,%p)\n", iface, palette);
+
+ EnterCriticalSection(&This->lock);
+
+ hr = This->stream ? WINCODEC_ERR_UNSUPPORTEDOPERATION : WINCODEC_ERR_NOTINITIALIZED;
+
+ LeaveCriticalSection(&This->lock);
+
+ return hr;
}
static HRESULT WINAPI PngEncoder_SetThumbnail(IWICBitmapEncoder *iface, IWICBitmapSource *pIThumbnail)
--
2.9.0

View File

@ -0,0 +1,82 @@
From c047c038ead7bf00fba1ad1ba19ec6f1e67ace6a Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Tue, 20 Sep 2016 14:22:44 +0800
Subject: windowscodecs: Decode PNG images with a tRNS chunk in their native
formats.
... instead of auto-converting them to PNG_COLOR_TYPE_RGB_ALPHA.
---
dlls/windowscodecs/pngformat.c | 36 +++++++-----------------------------
1 file changed, 7 insertions(+), 29 deletions(-)
diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c
index fa54a23..4473b98 100644
--- a/dlls/windowscodecs/pngformat.c
+++ b/dlls/windowscodecs/pngformat.c
@@ -321,11 +321,6 @@ MAKE_FUNCPTR(png_get_tRNS);
MAKE_FUNCPTR(png_set_bgr);
MAKE_FUNCPTR(png_set_crc_action);
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_gray_to_rgb);
MAKE_FUNCPTR(png_set_interlace_handling);
@@ -386,11 +381,6 @@ static void *load_libpng(void)
LOAD_FUNCPTR(png_set_bgr);
LOAD_FUNCPTR(png_set_crc_action);
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_gray_to_rgb);
LOAD_FUNCPTR(png_set_interlace_handling);
@@ -582,6 +572,8 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
int num_trans;
png_uint_32 transparency;
png_color_16p trans_values;
+ png_colorp png_palette;
+ int num_palette;
jmp_buf jmpbuf;
BYTE chunk_type[4];
ULONG chunk_size;
@@ -648,25 +640,11 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
/* check for color-keyed alpha */
transparency = ppng_get_tRNS(This->png_ptr, This->info_ptr, &trans, &num_trans, &trans_values);
- if (transparency && color_type != PNG_COLOR_TYPE_PALETTE)
- {
- /* expand to RGBA */
- 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_tRNS_to_alpha(This->png_ptr);
- color_type = PNG_COLOR_TYPE_RGB_ALPHA;
- }
+ if (!ppng_get_PLTE(This->png_ptr, This->info_ptr, &png_palette, &num_palette))
+ num_palette = 0;
+
+ TRACE("color_type %d, bit_depth %d, transparency %d, num_palette %d\n",
+ color_type, bit_depth, transparency, num_palette);
switch (color_type)
{
--
2.9.0

View File

@ -0,0 +1,99 @@
From 1f1114e95a0ae40ca396b6612b46de78a4e4a676 Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Tue, 20 Sep 2016 14:28:49 +0800
Subject: windowscodecs: Add support for palette image formats to PNG encoder.
---
dlls/windowscodecs/pngformat.c | 45 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 45 insertions(+)
diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c
index 4473b98..870240a 100644
--- a/dlls/windowscodecs/pngformat.c
+++ b/dlls/windowscodecs/pngformat.c
@@ -1,5 +1,6 @@
/*
* Copyright 2009 Vincent Povirk for CodeWeavers
+ * Copyright 2016 Dmitry Timoshkov
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -326,8 +327,10 @@ MAKE_FUNCPTR(png_set_gray_to_rgb);
MAKE_FUNCPTR(png_set_interlace_handling);
MAKE_FUNCPTR(png_set_IHDR);
MAKE_FUNCPTR(png_set_pHYs);
+MAKE_FUNCPTR(png_set_PLTE);
MAKE_FUNCPTR(png_set_read_fn);
MAKE_FUNCPTR(png_set_strip_16);
+MAKE_FUNCPTR(png_set_tRNS);
MAKE_FUNCPTR(png_set_tRNS_to_alpha);
MAKE_FUNCPTR(png_set_write_fn);
MAKE_FUNCPTR(png_read_end);
@@ -386,8 +389,10 @@ static void *load_libpng(void)
LOAD_FUNCPTR(png_set_interlace_handling);
LOAD_FUNCPTR(png_set_IHDR);
LOAD_FUNCPTR(png_set_pHYs);
+ LOAD_FUNCPTR(png_set_PLTE);
LOAD_FUNCPTR(png_set_read_fn);
LOAD_FUNCPTR(png_set_strip_16);
+ LOAD_FUNCPTR(png_set_tRNS);
LOAD_FUNCPTR(png_set_tRNS_to_alpha);
LOAD_FUNCPTR(png_set_write_fn);
LOAD_FUNCPTR(png_read_end);
@@ -1305,6 +1310,10 @@ struct png_pixelformat {
static const struct png_pixelformat formats[] = {
{&GUID_WICPixelFormat24bppBGR, 24, 8, PNG_COLOR_TYPE_RGB, 0, 1},
{&GUID_WICPixelFormatBlackWhite, 1, 1, PNG_COLOR_TYPE_GRAY, 0, 0},
+ {&GUID_WICPixelFormat1bppIndexed, 1, 1, PNG_COLOR_TYPE_PALETTE, 0, 0},
+ {&GUID_WICPixelFormat2bppIndexed, 2, 2, PNG_COLOR_TYPE_PALETTE, 0, 0},
+ {&GUID_WICPixelFormat4bppIndexed, 4, 4, PNG_COLOR_TYPE_PALETTE, 0, 0},
+ {&GUID_WICPixelFormat8bppIndexed, 8, 8, PNG_COLOR_TYPE_PALETTE, 0, 0},
{&GUID_WICPixelFormat2bppGray, 2, 2, PNG_COLOR_TYPE_GRAY, 0, 0},
{&GUID_WICPixelFormat4bppGray, 4, 4, PNG_COLOR_TYPE_GRAY, 0, 0},
{&GUID_WICPixelFormat8bppGray, 8, 8, PNG_COLOR_TYPE_GRAY, 0, 0},
@@ -1600,6 +1609,42 @@ static HRESULT WINAPI PngFrameEncode_WritePixels(IWICBitmapFrameEncode *iface,
(This->yres+0.0127) / 0.0254, PNG_RESOLUTION_METER);
}
+ if (This->format->color_type == PNG_COLOR_TYPE_PALETTE && This->colors)
+ {
+ png_color png_palette[256];
+ png_byte trans[256];
+ UINT i, num_trans = 0, colors;
+
+ /* Newer libpng versions don't accept larger palettes than the declared
+ * bit depth, so we need to generate the palette of the correct length.
+ */
+ colors = 1 << This->format->bit_depth;
+
+ for (i = 0; i < colors; i++)
+ {
+ if (i < This->colors)
+ {
+ png_palette[i].red = (This->palette[i] >> 16) & 0xff;
+ png_palette[i].green = (This->palette[i] >> 8) & 0xff;
+ png_palette[i].blue = This->palette[i] & 0xff;
+ trans[i] = (This->palette[i] >> 24) & 0xff;
+ if (trans[i] != 0xff)
+ num_trans++;
+ }
+ else
+ {
+ png_palette[i].red = 0;
+ png_palette[i].green = 0;
+ png_palette[i].blue = 0;
+ }
+ }
+
+ ppng_set_PLTE(This->png_ptr, This->info_ptr, png_palette, colors);
+
+ if (num_trans)
+ ppng_set_tRNS(This->png_ptr, This->info_ptr, trans, colors, NULL);
+ }
+
ppng_write_info(This->png_ptr, This->info_ptr);
if (This->format->remove_filler)
--
2.9.0

View File

@ -0,0 +1,33 @@
From 22248b62a738aaebc5907f4f9518d9a4dd288255 Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Tue, 20 Sep 2016 14:30:58 +0800
Subject: windowscodecs: Fix IWICBitmapEncoder::SetPalette for a not
initialized case in BMP encoder.
---
dlls/windowscodecs/bmpencode.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/dlls/windowscodecs/bmpencode.c b/dlls/windowscodecs/bmpencode.c
index 3dce8bb..c09b542 100644
--- a/dlls/windowscodecs/bmpencode.c
+++ b/dlls/windowscodecs/bmpencode.c
@@ -465,10 +465,12 @@ static HRESULT WINAPI BmpEncoder_SetColorContexts(IWICBitmapEncoder *iface,
return E_NOTIMPL;
}
-static HRESULT WINAPI BmpEncoder_SetPalette(IWICBitmapEncoder *iface, IWICPalette *pIPalette)
+static HRESULT WINAPI BmpEncoder_SetPalette(IWICBitmapEncoder *iface, IWICPalette *palette)
{
- TRACE("(%p,%p)\n", iface, pIPalette);
- return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+ BmpEncoder *This = impl_from_IWICBitmapEncoder(iface);
+
+ TRACE("(%p,%p)\n", iface, palette);
+ return This->stream ? WINCODEC_ERR_UNSUPPORTEDOPERATION : WINCODEC_ERR_NOTINITIALIZED;
}
static HRESULT WINAPI BmpEncoder_SetThumbnail(IWICBitmapEncoder *iface, IWICBitmapSource *pIThumbnail)
--
2.9.0

View File

@ -0,0 +1,56 @@
From 30b4760745745d5fb1b41d73a9dc99732feb822f Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Tue, 20 Sep 2016 14:34:46 +0800
Subject: windowscodecs: Implement IWICBitmapFrameEncode::SetPalette in BMP
encoder.
---
dlls/windowscodecs/bmpencode.c | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/dlls/windowscodecs/bmpencode.c b/dlls/windowscodecs/bmpencode.c
index c09b542..48a8e27 100644
--- a/dlls/windowscodecs/bmpencode.c
+++ b/dlls/windowscodecs/bmpencode.c
@@ -67,6 +67,8 @@ typedef struct BmpFrameEncode {
double xres, yres;
UINT lineswritten;
UINT stride;
+ WICColor palette[256];
+ UINT colors;
BOOL committed;
} BmpFrameEncode;
@@ -197,10 +199,18 @@ static HRESULT WINAPI BmpFrameEncode_SetColorContexts(IWICBitmapFrameEncode *ifa
}
static HRESULT WINAPI BmpFrameEncode_SetPalette(IWICBitmapFrameEncode *iface,
- IWICPalette *pIPalette)
+ IWICPalette *palette)
{
- FIXME("(%p,%p): stub\n", iface, pIPalette);
- return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+ BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
+
+ TRACE("(%p,%p)\n", iface, palette);
+
+ if (!palette) return E_INVALIDARG;
+
+ if (!This->initialized)
+ return WINCODEC_ERR_NOTINITIALIZED;
+
+ return IWICPalette_GetColors(palette, 256, This->palette, &This->colors);
}
static HRESULT WINAPI BmpFrameEncode_SetThumbnail(IWICBitmapFrameEncode *iface,
@@ -520,6 +530,7 @@ static HRESULT WINAPI BmpEncoder_CreateNewFrame(IWICBitmapEncoder *iface,
encode->xres = 0.0;
encode->yres = 0.0;
encode->lineswritten = 0;
+ encode->colors = 0;
encode->committed = FALSE;
*ppIFrameEncode = &encode->IWICBitmapFrameEncode_iface;
--
2.9.0

View File

@ -0,0 +1,31 @@
From a3e55d14e3718ae0a33b73b5e6df04540c1427cb Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Tue, 20 Sep 2016 14:37:09 +0800
Subject: windowscodecs: Implement IWICBitmapDecoder::CopyPalette in TIFF
decoder.
---
dlls/windowscodecs/tiffformat.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/dlls/windowscodecs/tiffformat.c b/dlls/windowscodecs/tiffformat.c
index 1dacd87..78bc842 100644
--- a/dlls/windowscodecs/tiffformat.c
+++ b/dlls/windowscodecs/tiffformat.c
@@ -683,10 +683,10 @@ static HRESULT WINAPI TiffDecoder_GetDecoderInfo(IWICBitmapDecoder *iface,
}
static HRESULT WINAPI TiffDecoder_CopyPalette(IWICBitmapDecoder *iface,
- IWICPalette *pIPalette)
+ IWICPalette *palette)
{
- FIXME("(%p,%p): stub\n", iface, pIPalette);
- return E_NOTIMPL;
+ TRACE("(%p,%p)\n", iface, palette);
+ return WINCODEC_ERR_PALETTEUNAVAILABLE;
}
static HRESULT WINAPI TiffDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface,
--
2.9.0

View File

@ -0,0 +1,62 @@
From 74acc51c81236e4a3e0e72cacfa902c27bdeeb9d Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Tue, 20 Sep 2016 14:39:56 +0800
Subject: windowscodecs: Implement IWICBitmapFrameEncode::SetPalette in the
TIFF encoder.
---
dlls/windowscodecs/tiffformat.c | 23 ++++++++++++++++++++---
1 file changed, 20 insertions(+), 3 deletions(-)
diff --git a/dlls/windowscodecs/tiffformat.c b/dlls/windowscodecs/tiffformat.c
index 78bc842..ce5efe1 100644
--- a/dlls/windowscodecs/tiffformat.c
+++ b/dlls/windowscodecs/tiffformat.c
@@ -1441,6 +1441,8 @@ typedef struct TiffFrameEncode {
UINT width, height;
double xres, yres;
UINT lines_written;
+ WICColor palette[256];
+ UINT colors;
} TiffFrameEncode;
static inline TiffFrameEncode *impl_from_IWICBitmapFrameEncode(IWICBitmapFrameEncode *iface)
@@ -1602,10 +1604,24 @@ static HRESULT WINAPI TiffFrameEncode_SetColorContexts(IWICBitmapFrameEncode *if
}
static HRESULT WINAPI TiffFrameEncode_SetPalette(IWICBitmapFrameEncode *iface,
- IWICPalette *pIPalette)
+ IWICPalette *palette)
{
- FIXME("(%p,%p): stub\n", iface, pIPalette);
- return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+ TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
+ HRESULT hr;
+
+ TRACE("(%p,%p)\n", iface, palette);
+
+ if (!palette) return E_INVALIDARG;
+
+ EnterCriticalSection(&This->parent->lock);
+
+ if (This->initialized)
+ hr = IWICPalette_GetColors(palette, 256, This->palette, &This->colors);
+ else
+ hr = WINCODEC_ERR_NOTINITIALIZED;
+
+ LeaveCriticalSection(&This->parent->lock);
+ return hr;
}
static HRESULT WINAPI TiffFrameEncode_SetThumbnail(IWICBitmapFrameEncode *iface,
@@ -1974,6 +1990,7 @@ static HRESULT WINAPI TiffEncoder_CreateNewFrame(IWICBitmapEncoder *iface,
result->xres = 0.0;
result->yres = 0.0;
result->lines_written = 0;
+ result->colors = 0;
IWICBitmapEncoder_AddRef(iface);
*ppIFrameEncode = &result->IWICBitmapFrameEncode_iface;
--
2.9.0

View File

@ -0,0 +1,41 @@
From d395248e82997e2a8aa60a720f856a788c86631c Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Tue, 20 Sep 2016 14:45:41 +0800
Subject: windowscodecs: Fix IWICBitmapEncoder::SetPalette for a not
initialized case in TIFF encoder.
---
dlls/windowscodecs/tiffformat.c | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/dlls/windowscodecs/tiffformat.c b/dlls/windowscodecs/tiffformat.c
index ce5efe1..d94be78 100644
--- a/dlls/windowscodecs/tiffformat.c
+++ b/dlls/windowscodecs/tiffformat.c
@@ -1903,10 +1903,20 @@ static HRESULT WINAPI TiffEncoder_SetColorContexts(IWICBitmapEncoder *iface,
return E_NOTIMPL;
}
-static HRESULT WINAPI TiffEncoder_SetPalette(IWICBitmapEncoder *iface, IWICPalette *pIPalette)
+static HRESULT WINAPI TiffEncoder_SetPalette(IWICBitmapEncoder *iface, IWICPalette *palette)
{
- TRACE("(%p,%p)\n", iface, pIPalette);
- return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+ TiffEncoder *This = impl_from_IWICBitmapEncoder(iface);
+ HRESULT hr;
+
+ TRACE("(%p,%p)\n", iface, palette);
+
+ EnterCriticalSection(&This->lock);
+
+ hr = This->stream ? WINCODEC_ERR_UNSUPPORTEDOPERATION : WINCODEC_ERR_NOTINITIALIZED;
+
+ LeaveCriticalSection(&This->lock);
+
+ return hr;
}
static HRESULT WINAPI TiffEncoder_SetThumbnail(IWICBitmapEncoder *iface, IWICBitmapSource *pIThumbnail)
--
2.9.0

View File

@ -0,0 +1,553 @@
From 93ab66ef7c5d801936bc90e0e35b5b35db1f387e Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Tue, 20 Sep 2016 14:47:48 +0800
Subject: windowscodecs/tests: Add some tests for encoding 1bpp/8bpp images
with a palette.
---
dlls/windowscodecs/tests/converter.c | 359 +++++++++++++++++++++++++++++++++--
1 file changed, 340 insertions(+), 19 deletions(-)
diff --git a/dlls/windowscodecs/tests/converter.c b/dlls/windowscodecs/tests/converter.c
index 7ca201a..78bcdbf 100644
--- a/dlls/windowscodecs/tests/converter.c
+++ b/dlls/windowscodecs/tests/converter.c
@@ -1,5 +1,6 @@
/*
* Copyright 2009 Vincent Povirk
+ * Copyright 2016 Dmitry Timoshkov
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -17,6 +18,7 @@
*/
#include <stdarg.h>
+#include <stdio.h>
#include <math.h>
#define COBJMACROS
@@ -27,6 +29,8 @@
#include "wincodec.h"
#include "wine/test.h"
+static IWICImagingFactory *factory;
+
typedef struct bitmap_data {
const WICPixelFormatGUID *format;
UINT bpp;
@@ -231,6 +235,19 @@ static BOOL compare_bits(const struct bitmap_data *expect, UINT buffersize, cons
break;
}
}
+ else if (IsEqualGUID(expect->format, &GUID_WICPixelFormatBlackWhite) ||
+ IsEqualGUID(expect->format, &GUID_WICPixelFormat1bppIndexed))
+ {
+ UINT i;
+ const BYTE *a=(const BYTE*)expect->bits, *b=(const BYTE*)converted_bits;
+ equal=TRUE;
+ for (i=0; i<buffersize; i++)
+ if (a[i] != b[i] && b[i] != 0xff /* BMP encoder B&W */)
+ {
+ equal = FALSE;
+ break;
+ }
+ }
else
equal = (memcmp(expect->bits, converted_bits, buffersize) == 0);
@@ -262,7 +279,7 @@ static void compare_bitmap_data(const struct bitmap_data *expect, IWICBitmapSour
hr = IWICBitmapSource_GetPixelFormat(source, &dst_pixelformat);
ok(SUCCEEDED(hr), "GetPixelFormat(%s) failed, hr=%x\n", name, hr);
- ok(IsEqualGUID(&dst_pixelformat, expect->format), "got unexpected pixel format (%s)\n", name);
+ ok(IsEqualGUID(&dst_pixelformat, expect->format), "got unexpected pixel format %s (%s)\n", wine_dbgstr_guid(&dst_pixelformat), name);
prc.X = 0;
prc.Y = 0;
@@ -286,6 +303,21 @@ static void compare_bitmap_data(const struct bitmap_data *expect, IWICBitmapSour
HeapFree(GetProcessHeap(), 0, converted_bits);
}
+/* some encoders (like BMP) require data to be 4-bytes aligned */
+static const BYTE bits_1bpp[] = {
+ 0x55,0x55,0x55,0x55, /*01010101*/
+ 0xaa,0xaa,0xaa,0xaa}; /*10101010*/
+static const struct bitmap_data testdata_BlackWhite = {
+ &GUID_WICPixelFormatBlackWhite, 1, bits_1bpp, 32, 2, 96.0, 96.0};
+static const struct bitmap_data testdata_1bppIndexed = {
+ &GUID_WICPixelFormat1bppIndexed, 1, bits_1bpp, 32, 2, 96.0, 96.0};
+
+static const BYTE bits_8bpp[] = {
+ 0,1,2,3,
+ 4,5,6,7};
+static const struct bitmap_data testdata_8bppIndexed = {
+ &GUID_WICPixelFormat8bppIndexed, 8, bits_8bpp, 4, 2, 96.0, 96.0};
+
static const BYTE bits_24bppBGR[] = {
255,0,0, 0,255,0, 0,0,255, 0,0,0,
0,255,255, 255,0,255, 255,255,0, 255,255,255};
@@ -553,6 +585,118 @@ static void test_encoder_properties(const CLSID* clsid_encoder, IPropertyBag2 *o
}
}
+static void check_bmp_format(IStream *stream, const WICPixelFormatGUID *format)
+{
+ /* FIXME */
+}
+
+static void check_tiff_format(IStream *stream, const WICPixelFormatGUID *format)
+{
+ /* FIXME */
+}
+
+static unsigned be_uint(unsigned val)
+{
+ union
+ {
+ unsigned val;
+ char c[4];
+ } u;
+
+ u.val = val;
+ return (u.c[0] << 24) | (u.c[1] << 16) | (u.c[2] << 8) | u.c[3];
+}
+
+static void check_png_format(IStream *stream, const WICPixelFormatGUID *format)
+{
+ static const char png_sig[8] = {0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a};
+ static const char png_IHDR[8] = {0,0,0,0x0d,'I','H','D','R'};
+ HRESULT hr;
+ struct
+ {
+ char png_sig[8];
+ char ihdr_sig[8];
+ unsigned width, height;
+ char bit_depth, color_type, compression, filter, interlace;
+ } png;
+
+ memset(&png, 0, sizeof(png));
+ hr = IStream_Read(stream, &png, sizeof(png), NULL);
+ ok(hr == S_OK, "IStream_Read error %#x\n", hr);
+
+ ok(!memcmp(png.png_sig, png_sig, sizeof(png_sig)), "expected PNG signature\n");
+ ok(!memcmp(png.ihdr_sig, png_IHDR, sizeof(png_IHDR)), "expected PNG IHDR\n");
+
+ if (IsEqualGUID(format, &GUID_WICPixelFormatBlackWhite))
+ {
+ ok(be_uint(png.width) == 32, "wrong width %u\n", be_uint(png.width));
+ ok(be_uint(png.height) == 2, "wrong height %u\n", be_uint(png.height));
+
+ ok(png.bit_depth == 1, "wrong bit_depth %d\n", png.bit_depth);
+ ok(png.color_type == 0, "wrong color_type %d\n", png.color_type);
+ ok(png.compression == 0, "wrong compression %d\n", png.compression);
+ ok(png.filter == 0, "wrong filter %d\n", png.filter);
+ ok(png.interlace == 0, "wrong interlace %d\n", png.interlace);
+ }
+ else if (IsEqualGUID(format, &GUID_WICPixelFormat1bppIndexed))
+ {
+ ok(be_uint(png.width) == 32, "wrong width %u\n", be_uint(png.width));
+ ok(be_uint(png.height) == 2, "wrong height %u\n", be_uint(png.height));
+
+ ok(png.bit_depth == 1, "wrong bit_depth %d\n", png.bit_depth);
+ ok(png.color_type == 3, "wrong color_type %d\n", png.color_type);
+ ok(png.compression == 0, "wrong compression %d\n", png.compression);
+ ok(png.filter == 0, "wrong filter %d\n", png.filter);
+ ok(png.interlace == 0, "wrong interlace %d\n", png.interlace);
+ }
+ else if (IsEqualGUID(format, &GUID_WICPixelFormat8bppIndexed))
+ {
+ ok(be_uint(png.width) == 4, "wrong width %u\n", be_uint(png.width));
+ ok(be_uint(png.height) == 2, "wrong height %u\n", be_uint(png.height));
+
+ ok(png.bit_depth == 8, "wrong bit_depth %d\n", png.bit_depth);
+ ok(png.color_type == 3, "wrong color_type %d\n", png.color_type);
+ ok(png.compression == 0, "wrong compression %d\n", png.compression);
+ ok(png.filter == 0, "wrong filter %d\n", png.filter);
+ ok(png.interlace == 0, "wrong interlace %d\n", png.interlace);
+ }
+ else if (IsEqualGUID(format, &GUID_WICPixelFormat24bppBGR))
+ {
+ ok(be_uint(png.width) == 4, "wrong width %u\n", be_uint(png.width));
+ ok(be_uint(png.height) == 2, "wrong height %u\n", be_uint(png.height));
+
+ ok(png.bit_depth == 8, "wrong bit_depth %d\n", png.bit_depth);
+ ok(png.color_type == 2, "wrong color_type %d\n", png.color_type);
+ ok(png.compression == 0, "wrong compression %d\n", png.compression);
+ ok(png.filter == 0, "wrong filter %d\n", png.filter);
+ ok(png.interlace == 0 || png.interlace == 1, "wrong interlace %d\n", png.interlace);
+ }
+ else
+ ok(0, "unknown PNG pixel format %s\n", wine_dbgstr_guid(format));
+}
+
+static void check_bitmap_format(IStream *stream, const CLSID *encoder, const WICPixelFormatGUID *format)
+{
+ HRESULT hr;
+ LARGE_INTEGER pos;
+
+ pos.QuadPart = 0;
+ hr = IStream_Seek(stream, pos, SEEK_SET, (ULARGE_INTEGER *)&pos);
+ ok(hr == S_OK, "IStream_Seek error %#x\n", hr);
+
+ if (IsEqualGUID(encoder, &CLSID_WICPngEncoder))
+ check_png_format(stream, format);
+ else if (IsEqualGUID(encoder, &CLSID_WICBmpEncoder))
+ check_bmp_format(stream, format);
+ else if (IsEqualGUID(encoder, &CLSID_WICTiffEncoder))
+ check_tiff_format(stream, format);
+ else
+ ok(0, "unknown encoder %s\n", wine_dbgstr_guid(encoder));
+
+ hr = IStream_Seek(stream, pos, SEEK_SET, NULL);
+ ok(hr == S_OK, "IStream_Seek error %#x\n", hr);
+}
+
struct setting {
const WCHAR *name;
PROPBAG2_TYPE type;
@@ -562,7 +706,7 @@ struct setting {
static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* clsid_encoder,
const struct bitmap_data **dsts, const CLSID *clsid_decoder, WICRect *rc,
- const struct setting *settings, const char *name)
+ const struct setting *settings, const char *name, IWICPalette *palette)
{
HRESULT hr;
IWICBitmapEncoder *encoder;
@@ -591,9 +735,22 @@ static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* cls
if (hglobal && SUCCEEDED(hr))
{
+ if (palette)
+ {
+ hr = IWICBitmapEncoder_SetPalette(encoder, palette);
+ ok(hr == WINCODEC_ERR_NOTINITIALIZED, "wrong error %#x (%s)\n", hr, name);
+ }
+
hr = IWICBitmapEncoder_Initialize(encoder, stream, WICBitmapEncoderNoCache);
ok(SUCCEEDED(hr), "Initialize failed, hr=%x\n", hr);
+ if (palette)
+ {
+ hr = IWICBitmapEncoder_SetPalette(encoder, palette);
+ ok(hr == WINCODEC_ERR_UNSUPPORTEDOPERATION, "wrong error %#x\n", hr);
+ hr = S_OK;
+ }
+
i=0;
while (SUCCEEDED(hr) && srcs[i])
{
@@ -627,28 +784,60 @@ static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* cls
}
}
+ if (palette)
+ {
+ hr = IWICBitmapFrameEncode_SetPalette(frameencode, palette);
+ ok(hr == WINCODEC_ERR_NOTINITIALIZED, "wrong error %#x\n", hr);
+ }
+
hr = IWICBitmapFrameEncode_Initialize(frameencode, options);
ok(SUCCEEDED(hr), "Initialize failed, hr=%x\n", hr);
memcpy(&pixelformat, srcs[i]->format, sizeof(GUID));
hr = IWICBitmapFrameEncode_SetPixelFormat(frameencode, &pixelformat);
ok(SUCCEEDED(hr), "SetPixelFormat failed, hr=%x\n", hr);
- ok(IsEqualGUID(&pixelformat, srcs[i]->format), "SetPixelFormat changed the format\n");
+ ok(IsEqualGUID(&pixelformat, dsts[i]->format), "SetPixelFormat changed the format to %s (%s)\n",
+ wine_dbgstr_guid(&pixelformat), name);
hr = IWICBitmapFrameEncode_SetSize(frameencode, srcs[i]->width, srcs[i]->height);
ok(SUCCEEDED(hr), "SetSize failed, hr=%x\n", hr);
+ if (palette)
+ {
+ WICColor colors[256];
+
+ hr = IWICBitmapFrameEncode_SetPalette(frameencode, palette);
+ ok(SUCCEEDED(hr), "SetPalette failed, hr=%x (%s)\n", hr, name);
+
+ /* trash the assigned palette */
+ memset(colors, 0, sizeof(colors));
+ hr = IWICPalette_InitializeCustom(palette, colors, 256);
+ ok(hr == S_OK, "InitializeCustom error %#x\n", hr);
+ }
+
hr = IWICBitmapFrameEncode_WriteSource(frameencode, &src_obj->IWICBitmapSource_iface, rc);
if (rc && (rc->Width <= 0 || rc->Height <= 0))
{
/* WriteSource fails but WriteSource_Proxy succeeds. */
- ok(hr == E_INVALIDARG, "WriteSource failed, hr=%x (%s)\n", hr, name);
+ ok(hr == E_INVALIDARG, "WriteSource should fail, hr=%x (%s)\n", hr, name);
hr = IWICBitmapFrameEncode_WriteSource_Proxy(frameencode, &src_obj->IWICBitmapSource_iface, rc);
+ ok(SUCCEEDED(hr), "WriteSource_Proxy failed, %dx%d, hr=%x (%s)\n", rc->Width, rc->Height, hr, name);
+ }
+ else
+ {
+ if (rc)
+ ok(SUCCEEDED(hr), "WriteSource(%dx%d) failed, hr=%x (%s)\n", rc->Width, rc->Height, hr, name);
+ else
+ ok(hr == S_OK ||
+ broken(hr == E_INVALIDARG && IsEqualGUID(clsid_encoder, &CLSID_WICBmpEncoder) && IsEqualGUID(srcs[i]->format, &GUID_WICPixelFormatBlackWhite)) /* XP */,
+ "WriteSource(NULL) failed, hr=%x (%s)\n", hr, name);
}
- ok(SUCCEEDED(hr), "WriteSource failed, hr=%x (%s)\n", hr, name);
- hr = IWICBitmapFrameEncode_Commit(frameencode);
- ok(SUCCEEDED(hr), "Commit failed, hr=%x\n", hr);
+ if (SUCCEEDED(hr))
+ {
+ hr = IWICBitmapFrameEncode_Commit(frameencode);
+ ok(SUCCEEDED(hr), "Commit failed, hr=%x (%s)\n", hr, name);
+ }
IWICBitmapFrameEncode_Release(frameencode);
IPropertyBag2_Release(options);
@@ -663,6 +852,8 @@ static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* cls
{
hr = IWICBitmapEncoder_Commit(encoder);
ok(SUCCEEDED(hr), "Commit failed, hr=%x\n", hr);
+
+ check_bitmap_format(stream, clsid_encoder, dsts[0]->format);
}
if (SUCCEEDED(hr))
@@ -674,25 +865,105 @@ static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* cls
if (SUCCEEDED(hr))
{
+ IWICPalette *frame_palette;
+
+ hr = IWICImagingFactory_CreatePalette(factory, &frame_palette);
+ ok(hr == S_OK, "CreatePalette error %#x\n", hr);
+
+ hr = IWICBitmapDecoder_CopyPalette(decoder, frame_palette);
+ ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "wrong error %#x\n", hr);
+
hr = IWICBitmapDecoder_Initialize(decoder, stream, WICDecodeMetadataCacheOnDemand);
ok(SUCCEEDED(hr), "Initialize failed, hr=%x\n", hr);
+ hr = IWICBitmapDecoder_CopyPalette(decoder, frame_palette);
+ ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "wrong error %#x\n", hr);
+
+ hr = S_OK;
i=0;
while (SUCCEEDED(hr) && dsts[i])
{
hr = IWICBitmapDecoder_GetFrame(decoder, i, &framedecode);
- ok(SUCCEEDED(hr), "GetFrame failed, hr=%x\n", hr);
+ ok(SUCCEEDED(hr), "GetFrame failed, hr=%x (%s)\n", hr, name);
if (SUCCEEDED(hr))
{
compare_bitmap_data(dsts[i], (IWICBitmapSource*)framedecode, name);
+ hr = IWICBitmapFrameDecode_CopyPalette(framedecode, frame_palette);
+ if (winetest_debug > 1)
+ trace("%s, bpp %d, %s, hr %#x\n", name, dsts[i]->bpp, wine_dbgstr_guid(dsts[i]->format), hr);
+ if (dsts[i]->bpp > 8 || IsEqualGUID(dsts[i]->format, &GUID_WICPixelFormatBlackWhite))
+ ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "wrong error %#x\n", hr);
+ else
+ {
+ UINT count, ret;
+ WICColor colors[256];
+
+ ok(hr == S_OK, "CopyPalette error %#x (%s)\n", hr, name);
+
+ count = 0;
+ hr = IWICPalette_GetColorCount(frame_palette, &count);
+ ok(hr == S_OK, "GetColorCount error %#x\n", hr);
+
+ memset(colors, 0, sizeof(colors));
+ ret = 0;
+ hr = IWICPalette_GetColors(frame_palette, count, colors, &ret);
+ ok(hr == S_OK, "GetColors error %#x\n", hr);
+ ok(ret == count, "expected %u, got %u\n", count, ret);
+ if (IsEqualGUID(clsid_decoder, &CLSID_WICPngDecoder))
+ {
+ ok(count == 256 || count == 2 /* newer libpng versions */, "expected 256, got %u (%s)\n", count, name);
+
+ ok(colors[0] == 0x11111111, "got %08x (%s)\n", colors[0], name);
+ ok(colors[1] == 0x22222222, "got %08x (%s)\n", colors[1], name);
+ if (count > 2)
+ {
+ ok(colors[2] == 0x33333333, "got %08x (%s)\n", colors[2], name);
+ ok(colors[3] == 0x44444444, "got %08x (%s)\n", colors[3], name);
+ ok(colors[4] == 0x55555555, "got %08x (%s)\n", colors[4], name);
+ ok(colors[5] == 0, "got %08x (%s)\n", colors[5], name);
+ }
+ }
+ else if (IsEqualGUID(clsid_decoder, &CLSID_WICBmpDecoder) ||
+ IsEqualGUID(clsid_decoder, &CLSID_WICTiffDecoder))
+ {
+ if (IsEqualGUID(dsts[i]->format, &GUID_WICPixelFormatBlackWhite) ||
+ IsEqualGUID(dsts[i]->format, &GUID_WICPixelFormat8bppIndexed))
+ {
+ ok(count == 256, "expected 256, got %u (%s)\n", count, name);
+
+ ok(colors[0] == 0xff111111, "got %08x (%s)\n", colors[0], name);
+ ok(colors[1] == 0xff222222, "got %08x (%s)\n", colors[1], name);
+ ok(colors[2] == 0xff333333, "got %08x (%s)\n", colors[2], name);
+ ok(colors[3] == 0xff444444, "got %08x (%s)\n", colors[3], name);
+ ok(colors[4] == 0xff555555, "got %08x (%s)\n", colors[4], name);
+ ok(colors[5] == 0xff000000, "got %08x (%s)\n", colors[5], name);
+ }
+ else
+ {
+ ok(count == 2, "expected 2, got %u (%s)\n", count, name);
+
+ ok(colors[0] == 0xff111111, "got %08x (%s)\n", colors[0], name);
+ ok(colors[1] == 0xff222222, "got %08x (%s)\n", colors[1], name);
+ }
+ }
+ else
+ {
+ ok(count == 2, "expected 2, got %u (%s)\n", count, name);
+
+ ok(colors[0] == 0xff111111, "got %08x\n", colors[0]);
+ ok(colors[1] == 0xff222222, "got %08x\n", colors[1]);
+ }
+ }
+
IWICBitmapFrameDecode_Release(framedecode);
}
i++;
}
+ IWICPalette_Release(frame_palette);
IWICBitmapDecoder_Release(decoder);
}
@@ -708,13 +979,31 @@ static void test_encoder(const struct bitmap_data *src, const CLSID* clsid_encod
{
const struct bitmap_data *srcs[2];
const struct bitmap_data *dsts[2];
+ WICColor colors[256];
+ IWICPalette *palette;
+ HRESULT hr;
+
+ hr = IWICImagingFactory_CreatePalette(factory, &palette);
+ ok(hr == S_OK, "CreatePalette error %#x\n", hr);
+
+ memset(colors, 0, sizeof(colors));
+ colors[0] = 0x11111111;
+ colors[1] = 0x22222222;
+ colors[2] = 0x33333333;
+ colors[3] = 0x44444444;
+ colors[4] = 0x55555555;
+ /* TIFF decoder fails to decode a 8bpp frame if palette has less than 256 colors */
+ hr = IWICPalette_InitializeCustom(palette, colors, 256);
+ ok(hr == S_OK, "InitializeCustom error %#x\n", hr);
srcs[0] = src;
srcs[1] = NULL;
dsts[0] = dst;
dsts[1] = NULL;
- test_multi_encoder(srcs, clsid_encoder, dsts, clsid_decoder, NULL, NULL, name);
+ test_multi_encoder(srcs, clsid_encoder, dsts, clsid_decoder, NULL, NULL, name, palette);
+
+ IWICPalette_Release(palette);
}
static void test_encoder_rects(void)
@@ -733,20 +1022,20 @@ static void test_encoder_rects(void)
rc.Width = 4;
rc.Height = 2;
- test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects full");
+ test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects full", NULL);
rc.Width = 0;
- test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects width=0");
+ test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects width=0", NULL);
rc.Width = -1;
- test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects width=-1");
+ test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects width=-1", NULL);
rc.Width = 4;
rc.Height = 0;
- test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects height=0");
+ test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects height=0", NULL);
rc.Height = -1;
- test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects height=-1");
+ test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects height=-1", NULL);
}
static const struct bitmap_data *multiple_frames[3] = {
@@ -765,8 +1054,14 @@ static const struct setting png_interlace_settings[] = {
START_TEST(converter)
{
+ HRESULT hr;
+
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
+ hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IWICImagingFactory, (void **)&factory);
+ ok(hr == S_OK, "failed to create factory: %#x\n", hr);
+
test_conversion(&testdata_32bppBGRA, &testdata_32bppBGR, "BGRA -> BGR", FALSE);
test_conversion(&testdata_32bppBGR, &testdata_32bppBGRA, "BGR -> BGRA", FALSE);
test_conversion(&testdata_32bppBGRA, &testdata_32bppBGRA, "BGRA -> BGRA", FALSE);
@@ -791,22 +1086,48 @@ START_TEST(converter)
test_invalid_conversion();
test_default_converter();
- test_encoder(&testdata_32bppBGR, &CLSID_WICBmpEncoder,
- &testdata_32bppBGR, &CLSID_WICBmpDecoder, "BMP encoder 32bppBGR");
-
+ test_encoder(&testdata_BlackWhite, &CLSID_WICPngEncoder,
+ &testdata_BlackWhite, &CLSID_WICPngDecoder, "PNG encoder BlackWhite");
+ test_encoder(&testdata_1bppIndexed, &CLSID_WICPngEncoder,
+ &testdata_1bppIndexed, &CLSID_WICPngDecoder, "PNG encoder 1bppIndexed");
+ test_encoder(&testdata_8bppIndexed, &CLSID_WICPngEncoder,
+ &testdata_8bppIndexed, &CLSID_WICPngDecoder, "PNG encoder 8bppIndexed");
test_encoder(&testdata_24bppBGR, &CLSID_WICPngEncoder,
&testdata_24bppBGR, &CLSID_WICPngDecoder, "PNG encoder 24bppBGR");
+if (!strcmp(winetest_platform, "windows")) /* FIXME: enable once implemented in Wine */
+{
+ test_encoder(&testdata_BlackWhite, &CLSID_WICBmpEncoder,
+ &testdata_1bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder BlackWhite");
+ test_encoder(&testdata_1bppIndexed, &CLSID_WICBmpEncoder,
+ &testdata_1bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 1bppIndexed");
+ test_encoder(&testdata_8bppIndexed, &CLSID_WICBmpEncoder,
+ &testdata_8bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 8bppIndexed");
+}
+ test_encoder(&testdata_32bppBGR, &CLSID_WICBmpEncoder,
+ &testdata_32bppBGR, &CLSID_WICBmpDecoder, "BMP encoder 32bppBGR");
+
+ test_encoder(&testdata_BlackWhite, &CLSID_WICTiffEncoder,
+ &testdata_BlackWhite, &CLSID_WICTiffDecoder, "TIFF encoder BlackWhite");
+if (!strcmp(winetest_platform, "windows")) /* FIXME: enable once implemented in Wine */
+{
+ test_encoder(&testdata_1bppIndexed, &CLSID_WICTiffEncoder,
+ &testdata_1bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 1bppIndexed");
+ test_encoder(&testdata_8bppIndexed, &CLSID_WICTiffEncoder,
+ &testdata_8bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 8bppIndexed");
+}
test_encoder(&testdata_24bppBGR, &CLSID_WICTiffEncoder,
&testdata_24bppBGR, &CLSID_WICTiffDecoder, "TIFF encoder 24bppBGR");
test_multi_encoder(multiple_frames, &CLSID_WICTiffEncoder,
- multiple_frames, &CLSID_WICTiffDecoder, NULL, NULL, "TIFF encoder multi-frame");
+ multiple_frames, &CLSID_WICTiffDecoder, NULL, NULL, "TIFF encoder multi-frame", NULL);
test_encoder_rects();
test_multi_encoder(single_frame, &CLSID_WICPngEncoder,
- single_frame, &CLSID_WICPngDecoder, NULL, png_interlace_settings, "PNG encoder interlaced");
+ single_frame, &CLSID_WICPngDecoder, NULL, png_interlace_settings, "PNG encoder interlaced", NULL);
+
+ IWICImagingFactory_Release(factory);
CoUninitialize();
}
--
2.9.0

View File

@ -0,0 +1,391 @@
From 8b2f07d7c2e51812617bb58533a17b6f3eccaf05 Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Thu, 22 Sep 2016 19:15:33 +0800
Subject: windowscodecs/tests: Add tests for encoding 2bpp/4bpp images with a
palette.
---
dlls/windowscodecs/tests/converter.c | 292 ++++++++++++++++++++++++++++++++++-
1 file changed, 286 insertions(+), 6 deletions(-)
diff --git a/dlls/windowscodecs/tests/converter.c b/dlls/windowscodecs/tests/converter.c
index 78bcdbf..78bc8f5 100644
--- a/dlls/windowscodecs/tests/converter.c
+++ b/dlls/windowscodecs/tests/converter.c
@@ -27,6 +27,7 @@
#include "windef.h"
#include "objbase.h"
#include "wincodec.h"
+#include "wincodecsdk.h"
#include "wine/test.h"
static IWICImagingFactory *factory;
@@ -312,6 +313,20 @@ static const struct bitmap_data testdata_BlackWhite = {
static const struct bitmap_data testdata_1bppIndexed = {
&GUID_WICPixelFormat1bppIndexed, 1, bits_1bpp, 32, 2, 96.0, 96.0};
+/* some encoders (like BMP) require data to be 4-bytes aligned */
+static const BYTE bits_2bpp[] = {
+ 0x55,0x55,0x55,0x55,
+ 0xaa,0xaa,0xaa,0xaa};
+static const struct bitmap_data testdata_2bppIndexed = {
+ &GUID_WICPixelFormat2bppIndexed, 2, bits_2bpp, 16, 2, 96.0, 96.0};
+
+/* some encoders (like BMP) require data to be 4-bytes aligned */
+static const BYTE bits_4bpp[] = {
+ 0x55,0x55,0x55,0x55,
+ 0xaa,0xaa,0xaa,0xaa};
+static const struct bitmap_data testdata_4bppIndexed = {
+ &GUID_WICPixelFormat4bppIndexed, 4, bits_4bpp, 8, 2, 96.0, 96.0};
+
static const BYTE bits_8bpp[] = {
0,1,2,3,
4,5,6,7};
@@ -585,14 +600,224 @@ static void test_encoder_properties(const CLSID* clsid_encoder, IPropertyBag2 *o
}
}
-static void check_bmp_format(IStream *stream, const WICPixelFormatGUID *format)
+static void load_stream(IUnknown *reader, IStream *stream)
{
- /* FIXME */
+ HRESULT hr;
+ IWICPersistStream *persist;
+#ifdef WORDS_BIGENDIAN
+ DWORD persist_options = WICPersistOptionsBigEndian;
+#else
+ DWORD persist_options = WICPersistOptionsLittleEndian;
+#endif
+
+ hr = IUnknown_QueryInterface(reader, &IID_IWICPersistStream, (void **)&persist);
+ ok(hr == S_OK, "QueryInterface failed, hr=%x\n", hr);
+
+ hr = IWICPersistStream_LoadEx(persist, stream, NULL, persist_options);
+ ok(hr == S_OK, "LoadEx failed, hr=%x\n", hr);
+
+ IWICPersistStream_Release(persist);
}
static void check_tiff_format(IStream *stream, const WICPixelFormatGUID *format)
{
- /* FIXME */
+ HRESULT hr;
+ IWICMetadataReader *reader;
+ PROPVARIANT id, value;
+ struct
+ {
+ USHORT byte_order;
+ USHORT version;
+ ULONG dir_offset;
+ } tiff;
+ LARGE_INTEGER pos;
+ UINT count, i;
+ int width, height, bps, photo, samples, colormap;
+ struct
+ {
+ int id, *value;
+ } tag[] =
+ {
+ { 0x100, &width }, { 0x101, &height }, { 0x102, &bps },
+ { 0x106, &photo }, { 0x115, &samples }, { 0x140, &colormap }
+ };
+
+ memset(&tiff, 0, sizeof(tiff));
+ hr = IStream_Read(stream, &tiff, sizeof(tiff), NULL);
+ ok(hr == S_OK, "IStream_Read error %#x\n", hr);
+ ok(tiff.byte_order == MAKEWORD('I','I') || tiff.byte_order == MAKEWORD('M','M'),
+ "wrong TIFF byte order mark %02x\n", tiff.byte_order);
+ ok(tiff.version == 42, "wrong TIFF version %u\n", tiff.version);
+
+ pos.QuadPart = tiff.dir_offset;
+ hr = IStream_Seek(stream, pos, SEEK_SET, NULL);
+ ok(hr == S_OK, "IStream_Seek error %#x\n", hr);
+
+ hr = CoCreateInstance(&CLSID_WICIfdMetadataReader, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IWICMetadataReader, (void **)&reader);
+ ok(hr == S_OK, "CoCreateInstance error %#x\n", hr);
+
+ load_stream((IUnknown *)reader, stream);
+
+ hr = IWICMetadataReader_GetCount(reader, &count);
+ ok(hr == S_OK, "GetCount error %#x\n", hr);
+ ok(count != 0, "wrong count %u\n", count);
+
+ for (i = 0; i < sizeof(tag)/sizeof(tag[0]); i++)
+ {
+ PropVariantInit(&id);
+ PropVariantInit(&value);
+
+ id.vt = VT_UI2;
+ U(id).uiVal = tag[i].id;
+ hr = IWICMetadataReader_GetValue(reader, NULL, &id, &value);
+ ok(hr == S_OK || (tag[i].id == 0x140 && hr == WINCODEC_ERR_PROPERTYNOTFOUND),
+ "GetValue(%04x) error %#x\n", tag[i].id, hr);
+ if (hr == S_OK)
+ {
+ ok(value.vt == VT_UI2 || value.vt == VT_UI4 || value.vt == (VT_UI2 | VT_VECTOR), "wrong vt: %d\n", value.vt);
+ tag[i].value[0] = U(value).uiVal;
+ }
+ else
+ tag[i].value[0] = -1;
+ }
+
+ IWICMetadataReader_Release(reader);
+
+ if (IsEqualGUID(format, &GUID_WICPixelFormatBlackWhite))
+ {
+ ok(width == 32, "wrong width %u\n", width);
+ ok(height == 2, "wrong height %u\n", height);
+
+ ok(bps == 1, "wrong bps %d\n", bps);
+ ok(photo == 1, "wrong photometric %d\n", photo);
+ ok(samples == 1, "wrong samples %d\n", samples);
+ ok(colormap == -1, "wrong colormap %d\n", colormap);
+ }
+ else if (IsEqualGUID(format, &GUID_WICPixelFormat1bppIndexed))
+ {
+ ok(width == 32, "wrong width %u\n", width);
+ ok(height == 2, "wrong height %u\n", height);
+
+ ok(bps == 1, "wrong bps %d\n", bps);
+ ok(photo == 3, "wrong photometric %d\n", photo);
+ ok(samples == 1, "wrong samples %d\n", samples);
+ ok(colormap == 6, "wrong colormap %d\n", colormap);
+ }
+ else if (IsEqualGUID(format, &GUID_WICPixelFormat2bppIndexed))
+ {
+ ok(width == 32, "wrong width %u\n", width);
+ ok(height == 2, "wrong height %u\n", height);
+
+ ok(bps == 1, "wrong bps %d\n", bps);
+ ok(photo == 3, "wrong photometric %d\n", photo);
+ ok(samples == 1, "wrong samples %d\n", samples);
+ ok(colormap == 6, "wrong colormap %d\n", colormap);
+ }
+ else if (IsEqualGUID(format, &GUID_WICPixelFormat4bppIndexed))
+ {
+ ok(width == 8, "wrong width %u\n", width);
+ ok(height == 2, "wrong height %u\n", height);
+
+ ok(bps == 4, "wrong bps %d\n", bps);
+ ok(photo == 3, "wrong photometric %d\n", photo);
+ ok(samples == 1, "wrong samples %d\n", samples);
+ ok(colormap == 48, "wrong colormap %d\n", colormap);
+ }
+ else if (IsEqualGUID(format, &GUID_WICPixelFormat8bppIndexed))
+ {
+ ok(width == 4, "wrong width %u\n", width);
+ ok(height == 2, "wrong height %u\n", height);
+
+ ok(bps == 8, "wrong bps %d\n", bps);
+ ok(photo == 3, "wrong photometric %d\n", photo);
+ ok(samples == 1, "wrong samples %d\n", samples);
+ ok(colormap == 768, "wrong colormap %d\n", colormap);
+ }
+ else if (IsEqualGUID(format, &GUID_WICPixelFormat24bppBGR))
+ {
+ ok(width == 4, "wrong width %u\n", width);
+ ok(height == 2, "wrong height %u\n", height);
+
+ ok(bps == 3, "wrong bps %d\n", bps);
+ ok(photo == 2, "wrong photometric %d\n", photo);
+ ok(samples == 3, "wrong samples %d\n", samples);
+ ok(colormap == -1, "wrong colormap %d\n", colormap);
+ }
+ else
+ ok(0, "unknown TIFF pixel format %s\n", wine_dbgstr_guid(format));
+}
+
+static void check_bmp_format(IStream *stream, const WICPixelFormatGUID *format)
+{
+ HRESULT hr;
+ BITMAPFILEHEADER bfh;
+ BITMAPV5HEADER bih;
+
+ memset(&bfh, 0, sizeof(bfh));
+ hr = IStream_Read(stream, &bfh, sizeof(bfh), NULL);
+ ok(hr == S_OK, "IStream_Read error %#x\n", hr);
+
+ ok(bfh.bfType == 0x4d42, "wrong BMP signature %02x\n", bfh.bfType);
+ ok(bfh.bfReserved1 == 0, "wrong bfReserved1 %02x\n", bfh.bfReserved1);
+ ok(bfh.bfReserved2 == 0, "wrong bfReserved2 %02x\n", bfh.bfReserved2);
+
+ memset(&bih, 0, sizeof(bih));
+ hr = IStream_Read(stream, &bih, sizeof(bih), NULL);
+ ok(hr == S_OK, "IStream_Read error %#x\n", hr);
+
+ if (IsEqualGUID(format, &GUID_WICPixelFormat1bppIndexed))
+ {
+ ok(bih.bV5Width == 32, "wrong width %u\n", bih.bV5Width);
+ ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height);
+
+ ok(bih.bV5Planes == 1, "wrong Planes %d\n", bih.bV5Planes);
+ ok(bih.bV5BitCount == 1, "wrong BitCount %d\n", bih.bV5BitCount);
+ ok(bih.bV5ClrUsed == 256, "wrong ClrUsed %d\n", bih.bV5ClrUsed);
+ ok(bih.bV5ClrImportant == 256, "wrong ClrImportant %d\n", bih.bV5ClrImportant);
+ }
+ else if (IsEqualGUID(format, &GUID_WICPixelFormat2bppIndexed))
+ {
+ ok(bih.bV5Width == 16, "wrong width %u\n", bih.bV5Width);
+ ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height);
+
+ ok(bih.bV5Planes == 1, "wrong Planes %d\n", bih.bV5Planes);
+ ok(bih.bV5BitCount == 2, "wrong BitCount %d\n", bih.bV5BitCount);
+ ok(bih.bV5ClrUsed == 256, "wrong ClrUsed %d\n", bih.bV5ClrUsed);
+ ok(bih.bV5ClrImportant == 256, "wrong ClrImportant %d\n", bih.bV5ClrImportant);
+ }
+ else if (IsEqualGUID(format, &GUID_WICPixelFormat4bppIndexed))
+ {
+ ok(bih.bV5Width == 8, "wrong width %u\n", bih.bV5Width);
+ ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height);
+
+ ok(bih.bV5Planes == 1, "wrong Planes %d\n", bih.bV5Planes);
+ ok(bih.bV5BitCount == 4, "wrong BitCount %d\n", bih.bV5BitCount);
+ ok(bih.bV5ClrUsed == 256, "wrong ClrUsed %d\n", bih.bV5ClrUsed);
+ ok(bih.bV5ClrImportant == 256, "wrong ClrImportant %d\n", bih.bV5ClrImportant);
+ }
+ else if (IsEqualGUID(format, &GUID_WICPixelFormat8bppIndexed))
+ {
+ ok(bih.bV5Width == 4, "wrong width %u\n", bih.bV5Width);
+ ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height);
+
+ ok(bih.bV5Planes == 1, "wrong Planes %d\n", bih.bV5Planes);
+ ok(bih.bV5BitCount == 8, "wrong BitCount %d\n", bih.bV5BitCount);
+ ok(bih.bV5ClrUsed == 256, "wrong ClrUsed %d\n", bih.bV5ClrUsed);
+ ok(bih.bV5ClrImportant == 256, "wrong ClrImportant %d\n", bih.bV5ClrImportant);
+ }
+ else if (IsEqualGUID(format, &GUID_WICPixelFormat32bppBGR))
+ {
+ ok(bih.bV5Width == 4, "wrong width %u\n", bih.bV5Width);
+ ok(bih.bV5Height == 2 || bih.bV5Height == -2 /* Wine */, "wrong height %u\n", bih.bV5Height);
+
+ ok(bih.bV5Planes == 1, "wrong Planes %d\n", bih.bV5Planes);
+ ok(bih.bV5BitCount == 32, "wrong BitCount %d\n", bih.bV5BitCount);
+ ok(bih.bV5ClrUsed == 0, "wrong ClrUsed %d\n", bih.bV5ClrUsed);
+ ok(bih.bV5ClrImportant == 0, "wrong ClrImportant %d\n", bih.bV5ClrImportant);
+ }
+ else
+ ok(0, "unknown BMP pixel format %s\n", wine_dbgstr_guid(format));
}
static unsigned be_uint(unsigned val)
@@ -649,6 +874,28 @@ static void check_png_format(IStream *stream, const WICPixelFormatGUID *format)
ok(png.filter == 0, "wrong filter %d\n", png.filter);
ok(png.interlace == 0, "wrong interlace %d\n", png.interlace);
}
+ else if (IsEqualGUID(format, &GUID_WICPixelFormat2bppIndexed))
+ {
+ ok(be_uint(png.width) == 16, "wrong width %u\n", be_uint(png.width));
+ ok(be_uint(png.height) == 2, "wrong height %u\n", be_uint(png.height));
+
+ ok(png.bit_depth == 2, "wrong bit_depth %d\n", png.bit_depth);
+ ok(png.color_type == 3, "wrong color_type %d\n", png.color_type);
+ ok(png.compression == 0, "wrong compression %d\n", png.compression);
+ ok(png.filter == 0, "wrong filter %d\n", png.filter);
+ ok(png.interlace == 0, "wrong interlace %d\n", png.interlace);
+ }
+ else if (IsEqualGUID(format, &GUID_WICPixelFormat4bppIndexed))
+ {
+ ok(be_uint(png.width) == 8, "wrong width %u\n", be_uint(png.width));
+ ok(be_uint(png.height) == 2, "wrong height %u\n", be_uint(png.height));
+
+ ok(png.bit_depth == 4, "wrong bit_depth %d\n", png.bit_depth);
+ ok(png.color_type == 3, "wrong color_type %d\n", png.color_type);
+ ok(png.compression == 0, "wrong compression %d\n", png.compression);
+ ok(png.filter == 0, "wrong filter %d\n", png.filter);
+ ok(png.interlace == 0, "wrong interlace %d\n", png.interlace);
+ }
else if (IsEqualGUID(format, &GUID_WICPixelFormat8bppIndexed))
{
ok(be_uint(png.width) == 4, "wrong width %u\n", be_uint(png.width));
@@ -829,6 +1076,8 @@ static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* cls
ok(SUCCEEDED(hr), "WriteSource(%dx%d) failed, hr=%x (%s)\n", rc->Width, rc->Height, hr, name);
else
ok(hr == S_OK ||
+ broken(hr == E_NOTIMPL && IsEqualGUID(clsid_encoder, &CLSID_WICBmpEncoder) && srcs[i]->bpp == 2) ||
+ broken(hr == E_NOTIMPL && IsEqualGUID(clsid_encoder, &CLSID_WICTiffEncoder) && srcs[i]->bpp == 2) ||
broken(hr == E_INVALIDARG && IsEqualGUID(clsid_encoder, &CLSID_WICBmpEncoder) && IsEqualGUID(srcs[i]->format, &GUID_WICPixelFormatBlackWhite)) /* XP */,
"WriteSource(NULL) failed, hr=%x (%s)\n", hr, name);
}
@@ -913,7 +1162,12 @@ static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* cls
ok(ret == count, "expected %u, got %u\n", count, ret);
if (IsEqualGUID(clsid_decoder, &CLSID_WICPngDecoder))
{
- ok(count == 256 || count == 2 /* newer libpng versions */, "expected 256, got %u (%s)\n", count, name);
+ /* Newer libpng versions don't accept larger palettes than the declared
+ * bit depth, so we need to generate the palette of the correct length.
+ */
+ ok(count == 256 || (dsts[i]->bpp == 1 && count == 2) ||
+ (dsts[i]->bpp == 2 && count == 4) || (dsts[i]->bpp == 4 && count == 16),
+ "expected 256, got %u (%s)\n", count, name);
ok(colors[0] == 0x11111111, "got %08x (%s)\n", colors[0], name);
ok(colors[1] == 0x22222222, "got %08x (%s)\n", colors[1], name);
@@ -921,8 +1175,11 @@ static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* cls
{
ok(colors[2] == 0x33333333, "got %08x (%s)\n", colors[2], name);
ok(colors[3] == 0x44444444, "got %08x (%s)\n", colors[3], name);
- ok(colors[4] == 0x55555555, "got %08x (%s)\n", colors[4], name);
- ok(colors[5] == 0, "got %08x (%s)\n", colors[5], name);
+ if (count > 4)
+ {
+ ok(colors[4] == 0x55555555, "got %08x (%s)\n", colors[4], name);
+ ok(colors[5] == 0, "got %08x (%s)\n", colors[5], name);
+ }
}
}
else if (IsEqualGUID(clsid_decoder, &CLSID_WICBmpDecoder) ||
@@ -940,6 +1197,17 @@ static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* cls
ok(colors[4] == 0xff555555, "got %08x (%s)\n", colors[4], name);
ok(colors[5] == 0xff000000, "got %08x (%s)\n", colors[5], name);
}
+ else if (IsEqualGUID(dsts[i]->format, &GUID_WICPixelFormat4bppIndexed))
+ {
+ ok(count == 16, "expected 16, got %u (%s)\n", count, name);
+
+ ok(colors[0] == 0xff111111, "got %08x (%s)\n", colors[0], name);
+ ok(colors[1] == 0xff222222, "got %08x (%s)\n", colors[1], name);
+ ok(colors[2] == 0xff333333, "got %08x (%s)\n", colors[2], name);
+ ok(colors[3] == 0xff444444, "got %08x (%s)\n", colors[3], name);
+ ok(colors[4] == 0xff555555, "got %08x (%s)\n", colors[4], name);
+ ok(colors[5] == 0xff000000, "got %08x (%s)\n", colors[5], name);
+ }
else
{
ok(count == 2, "expected 2, got %u (%s)\n", count, name);
@@ -1090,6 +1358,10 @@ START_TEST(converter)
&testdata_BlackWhite, &CLSID_WICPngDecoder, "PNG encoder BlackWhite");
test_encoder(&testdata_1bppIndexed, &CLSID_WICPngEncoder,
&testdata_1bppIndexed, &CLSID_WICPngDecoder, "PNG encoder 1bppIndexed");
+ test_encoder(&testdata_2bppIndexed, &CLSID_WICPngEncoder,
+ &testdata_2bppIndexed, &CLSID_WICPngDecoder, "PNG encoder 2bppIndexed");
+ test_encoder(&testdata_4bppIndexed, &CLSID_WICPngEncoder,
+ &testdata_4bppIndexed, &CLSID_WICPngDecoder, "PNG encoder 4bppIndexed");
test_encoder(&testdata_8bppIndexed, &CLSID_WICPngEncoder,
&testdata_8bppIndexed, &CLSID_WICPngDecoder, "PNG encoder 8bppIndexed");
test_encoder(&testdata_24bppBGR, &CLSID_WICPngEncoder,
@@ -1101,6 +1373,10 @@ if (!strcmp(winetest_platform, "windows")) /* FIXME: enable once implemented in
&testdata_1bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder BlackWhite");
test_encoder(&testdata_1bppIndexed, &CLSID_WICBmpEncoder,
&testdata_1bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 1bppIndexed");
+ test_encoder(&testdata_2bppIndexed, &CLSID_WICBmpEncoder,
+ &testdata_4bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 2bppIndexed");
+ test_encoder(&testdata_4bppIndexed, &CLSID_WICBmpEncoder,
+ &testdata_4bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 4bppIndexed");
test_encoder(&testdata_8bppIndexed, &CLSID_WICBmpEncoder,
&testdata_8bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 8bppIndexed");
}
@@ -1113,6 +1389,10 @@ if (!strcmp(winetest_platform, "windows")) /* FIXME: enable once implemented in
{
test_encoder(&testdata_1bppIndexed, &CLSID_WICTiffEncoder,
&testdata_1bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 1bppIndexed");
+ test_encoder(&testdata_2bppIndexed, &CLSID_WICTiffEncoder,
+ &testdata_4bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 2bppIndexed");
+ test_encoder(&testdata_4bppIndexed, &CLSID_WICTiffEncoder,
+ &testdata_4bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 4bppIndexed");
test_encoder(&testdata_8bppIndexed, &CLSID_WICTiffEncoder,
&testdata_8bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 8bppIndexed");
}
--
2.9.0

View File

@ -0,0 +1,26 @@
From 56d7b4030df9de1de6fb35ec4f31dad2661f46f9 Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Tue, 20 Sep 2016 17:17:42 +0800
Subject: windowscodecs: Use V_UI1() instead of V_UNION() to assign a VT_UI1
variant member.
---
dlls/windowscodecs/tiffformat.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/windowscodecs/tiffformat.c b/dlls/windowscodecs/tiffformat.c
index d94be78..1f757d8 100644
--- a/dlls/windowscodecs/tiffformat.c
+++ b/dlls/windowscodecs/tiffformat.c
@@ -1971,7 +1971,7 @@ static HRESULT WINAPI TiffEncoder_CreateNewFrame(IWICBitmapEncoder *iface,
VARIANT v;
VariantInit(&v);
V_VT(&v) = VT_UI1;
- V_UNION(&v, bVal) = WICTiffCompressionDontCare;
+ V_UI1(&v) = WICTiffCompressionDontCare;
hr = IPropertyBag2_Write(*ppIEncoderOptions, 1, opts, &v);
VariantClear(&v);
if (FAILED(hr))
--
2.9.0

View File

@ -0,0 +1,154 @@
From 133eeb6996e3f60f346de05a968508ae60178736 Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Fri, 23 Sep 2016 16:36:50 +0800
Subject: windowscodecs: Add support for palette image formats to TIFF encoder.
---
dlls/windowscodecs/main.c | 4 ++--
dlls/windowscodecs/tests/converter.c | 25 ++++++++++++++++---------
dlls/windowscodecs/tiffformat.c | 26 ++++++++++++++++++++++++++
3 files changed, 44 insertions(+), 11 deletions(-)
diff --git a/dlls/windowscodecs/main.c b/dlls/windowscodecs/main.c
index 442976f..fdd26dd 100644
--- a/dlls/windowscodecs/main.c
+++ b/dlls/windowscodecs/main.c
@@ -144,8 +144,8 @@ HRESULT configure_write_source(IWICBitmapFrameEncode *iface,
if (!IsEqualGUID(&src_format, format))
{
/* FIXME: should use WICConvertBitmapSource to convert */
- ERR("format %s unsupported\n", debugstr_guid(&src_format));
- return E_FAIL;
+ FIXME("format %s unsupported\n", debugstr_guid(&src_format));
+ return E_NOTIMPL;
}
if (xres == 0.0 || yres == 0.0)
diff --git a/dlls/windowscodecs/tests/converter.c b/dlls/windowscodecs/tests/converter.c
index 78bc8f5..e7b9ba9 100644
--- a/dlls/windowscodecs/tests/converter.c
+++ b/dlls/windowscodecs/tests/converter.c
@@ -706,13 +706,13 @@ static void check_tiff_format(IStream *stream, const WICPixelFormatGUID *format)
}
else if (IsEqualGUID(format, &GUID_WICPixelFormat2bppIndexed))
{
- ok(width == 32, "wrong width %u\n", width);
+ ok(width == 16, "wrong width %u\n", width);
ok(height == 2, "wrong height %u\n", height);
- ok(bps == 1, "wrong bps %d\n", bps);
+ ok(bps == 2, "wrong bps %d\n", bps);
ok(photo == 3, "wrong photometric %d\n", photo);
ok(samples == 1, "wrong samples %d\n", samples);
- ok(colormap == 6, "wrong colormap %d\n", colormap);
+ ok(colormap == 12, "wrong colormap %d\n", colormap);
}
else if (IsEqualGUID(format, &GUID_WICPixelFormat4bppIndexed))
{
@@ -1043,8 +1043,9 @@ static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* cls
memcpy(&pixelformat, srcs[i]->format, sizeof(GUID));
hr = IWICBitmapFrameEncode_SetPixelFormat(frameencode, &pixelformat);
ok(SUCCEEDED(hr), "SetPixelFormat failed, hr=%x\n", hr);
- ok(IsEqualGUID(&pixelformat, dsts[i]->format), "SetPixelFormat changed the format to %s (%s)\n",
- wine_dbgstr_guid(&pixelformat), name);
+ ok(IsEqualGUID(&pixelformat, dsts[i]->format) ||
+ broken(IsEqualGUID(clsid_encoder, &CLSID_WICTiffEncoder) && srcs[i]->bpp == 2 && IsEqualGUID(&pixelformat, &GUID_WICPixelFormat4bppIndexed)),
+ "SetPixelFormat changed the format to %s (%s)\n", wine_dbgstr_guid(&pixelformat), name);
hr = IWICBitmapFrameEncode_SetSize(frameencode, srcs[i]->width, srcs[i]->height);
ok(SUCCEEDED(hr), "SetSize failed, hr=%x\n", hr);
@@ -1197,6 +1198,15 @@ static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* cls
ok(colors[4] == 0xff555555, "got %08x (%s)\n", colors[4], name);
ok(colors[5] == 0xff000000, "got %08x (%s)\n", colors[5], name);
}
+ else if (IsEqualGUID(dsts[i]->format, &GUID_WICPixelFormat2bppIndexed))
+ {
+ ok(count == 4, "expected 4, got %u (%s)\n", count, name);
+
+ ok(colors[0] == 0xff111111, "got %08x (%s)\n", colors[0], name);
+ ok(colors[1] == 0xff222222, "got %08x (%s)\n", colors[1], name);
+ ok(colors[2] == 0xff333333, "got %08x (%s)\n", colors[2], name);
+ ok(colors[3] == 0xff444444, "got %08x (%s)\n", colors[3], name);
+ }
else if (IsEqualGUID(dsts[i]->format, &GUID_WICPixelFormat4bppIndexed))
{
ok(count == 16, "expected 16, got %u (%s)\n", count, name);
@@ -1385,17 +1395,14 @@ if (!strcmp(winetest_platform, "windows")) /* FIXME: enable once implemented in
test_encoder(&testdata_BlackWhite, &CLSID_WICTiffEncoder,
&testdata_BlackWhite, &CLSID_WICTiffDecoder, "TIFF encoder BlackWhite");
-if (!strcmp(winetest_platform, "windows")) /* FIXME: enable once implemented in Wine */
-{
test_encoder(&testdata_1bppIndexed, &CLSID_WICTiffEncoder,
&testdata_1bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 1bppIndexed");
test_encoder(&testdata_2bppIndexed, &CLSID_WICTiffEncoder,
- &testdata_4bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 2bppIndexed");
+ &testdata_2bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 2bppIndexed");
test_encoder(&testdata_4bppIndexed, &CLSID_WICTiffEncoder,
&testdata_4bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 4bppIndexed");
test_encoder(&testdata_8bppIndexed, &CLSID_WICTiffEncoder,
&testdata_8bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 8bppIndexed");
-}
test_encoder(&testdata_24bppBGR, &CLSID_WICTiffEncoder,
&testdata_24bppBGR, &CLSID_WICTiffDecoder, "TIFF encoder 24bppBGR");
diff --git a/dlls/windowscodecs/tiffformat.c b/dlls/windowscodecs/tiffformat.c
index 1f757d8..cb2faaa 100644
--- a/dlls/windowscodecs/tiffformat.c
+++ b/dlls/windowscodecs/tiffformat.c
@@ -1,5 +1,6 @@
/*
* Copyright 2010 Vincent Povirk for CodeWeavers
+ * Copyright 2016 Dmitry Timoshkov
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -461,6 +462,12 @@ static HRESULT tiff_get_decode_info(TIFF *tiff, tiff_decode_info *decode_info)
decode_info->bpp = bps;
switch (bps)
{
+ case 1:
+ decode_info->format = &GUID_WICPixelFormat1bppIndexed;
+ break;
+ case 2:
+ decode_info->format = &GUID_WICPixelFormat2bppIndexed;
+ break;
case 4:
decode_info->format = &GUID_WICPixelFormat4bppIndexed;
break;
@@ -1402,6 +1409,10 @@ static const struct tiff_encode_format formats[] = {
{&GUID_WICPixelFormat24bppBGR, 2, 8, 3, 24, 0, 0, 1},
{&GUID_WICPixelFormat24bppRGB, 2, 8, 3, 24, 0, 0, 0},
{&GUID_WICPixelFormatBlackWhite, 1, 1, 1, 1, 0, 0, 0},
+ {&GUID_WICPixelFormat1bppIndexed, 3, 1, 1, 1, 0, 0, 0},
+ {&GUID_WICPixelFormat2bppIndexed, 3, 2, 1, 2, 0, 0, 0},
+ {&GUID_WICPixelFormat4bppIndexed, 3, 4, 1, 4, 0, 0, 0},
+ {&GUID_WICPixelFormat8bppIndexed, 3, 8, 1, 8, 0, 0, 0},
{&GUID_WICPixelFormat4bppGray, 1, 4, 1, 4, 0, 0, 0},
{&GUID_WICPixelFormat8bppGray, 1, 8, 1, 8, 0, 0, 0},
{&GUID_WICPixelFormat32bppBGRA, 2, 8, 4, 32, 1, 2, 1},
@@ -1691,6 +1702,21 @@ static HRESULT WINAPI TiffFrameEncode_WritePixels(IWICBitmapFrameEncode *iface,
pTIFFSetField(This->parent->tiff, TIFFTAG_YRESOLUTION, (float)This->yres);
}
+ if (This->format->bpp <= 8 && This->colors && !IsEqualGUID(This->format->guid, &GUID_WICPixelFormatBlackWhite))
+ {
+ uint16 red[256], green[256], blue[256];
+ UINT i;
+
+ for (i = 0; i < This->colors; i++)
+ {
+ red[i] = (This->palette[i] >> 0) & 0xff00;
+ green[i] = This->palette[i] & 0xff00;
+ blue[i] = (This->palette[i] << 8) & 0xff00;
+ }
+
+ pTIFFSetField(This->parent->tiff, TIFFTAG_COLORMAP, red, green, blue);
+ }
+
This->info_written = TRUE;
}
--
2.9.0

View File

@ -0,0 +1,73 @@
From abeeebfd3c9fc5ed2901ea10de915932c8812c66 Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Fri, 23 Sep 2016 17:02:05 +0800
Subject: windowscodecs: Write the image bits as a bottom-top array in BMP
encoder.
This matches what Windows BMP encoder does.
---
dlls/windowscodecs/bmpencode.c | 17 ++++++++++++-----
dlls/windowscodecs/tests/converter.c | 2 +-
2 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/dlls/windowscodecs/bmpencode.c b/dlls/windowscodecs/bmpencode.c
index 48a8e27..af082ae 100644
--- a/dlls/windowscodecs/bmpencode.c
+++ b/dlls/windowscodecs/bmpencode.c
@@ -292,10 +292,11 @@ static HRESULT WINAPI BmpFrameEncode_Commit(IWICBitmapFrameEncode *iface)
BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
BITMAPFILEHEADER bfh;
BITMAPV5HEADER bih;
- UINT info_size;
+ UINT info_size, i;
LARGE_INTEGER pos;
ULONG byteswritten;
HRESULT hr;
+ const BYTE *bits;
TRACE("(%p)\n", iface);
@@ -308,7 +309,7 @@ static HRESULT WINAPI BmpFrameEncode_Commit(IWICBitmapFrameEncode *iface)
bih.bV5Size = info_size = sizeof(BITMAPINFOHEADER);
bih.bV5Width = This->width;
- bih.bV5Height = -This->height; /* top-down bitmap */
+ bih.bV5Height = This->height; /* bottom-top bitmap */
bih.bV5Planes = 1;
bih.bV5BitCount = This->format->bpp;
bih.bV5Compression = This->format->compression;
@@ -346,9 +347,15 @@ static HRESULT WINAPI BmpFrameEncode_Commit(IWICBitmapFrameEncode *iface)
if (FAILED(hr)) return hr;
if (byteswritten != info_size) return E_FAIL;
- hr = IStream_Write(This->stream, This->bits, bih.bV5SizeImage, &byteswritten);
- if (FAILED(hr)) return hr;
- if (byteswritten != bih.bV5SizeImage) return E_FAIL;
+ /* write the image bits as a bottom-top array */
+ bits = This->bits + bih.bV5SizeImage;
+ for (i = 0; i < This->height; i++)
+ {
+ bits -= This->stride;
+ hr = IStream_Write(This->stream, bits, This->stride, &byteswritten);
+ if (FAILED(hr)) return hr;
+ if (byteswritten != This->stride) return E_FAIL;
+ }
This->committed = TRUE;
diff --git a/dlls/windowscodecs/tests/converter.c b/dlls/windowscodecs/tests/converter.c
index e7b9ba9..865029f 100644
--- a/dlls/windowscodecs/tests/converter.c
+++ b/dlls/windowscodecs/tests/converter.c
@@ -809,7 +809,7 @@ static void check_bmp_format(IStream *stream, const WICPixelFormatGUID *format)
else if (IsEqualGUID(format, &GUID_WICPixelFormat32bppBGR))
{
ok(bih.bV5Width == 4, "wrong width %u\n", bih.bV5Width);
- ok(bih.bV5Height == 2 || bih.bV5Height == -2 /* Wine */, "wrong height %u\n", bih.bV5Height);
+ ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height);
ok(bih.bV5Planes == 1, "wrong Planes %d\n", bih.bV5Planes);
ok(bih.bV5BitCount == 32, "wrong BitCount %d\n", bih.bV5BitCount);
--
2.9.0

View File

@ -0,0 +1,25 @@
From 7f03e6b569bdd3e0b285a3c9ef0953c4115d80a7 Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Fri, 23 Sep 2016 20:17:47 +0800
Subject: windowscodecs: Limit number of colors in a palette in BMP decoder.
---
dlls/windowscodecs/bmpdecode.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/windowscodecs/bmpdecode.c b/dlls/windowscodecs/bmpdecode.c
index 2bcb81e..47f312f 100644
--- a/dlls/windowscodecs/bmpdecode.c
+++ b/dlls/windowscodecs/bmpdecode.c
@@ -271,7 +271,7 @@ static HRESULT WINAPI BmpFrameDecode_CopyPalette(IWICBitmapFrameDecode *iface,
if (This->bih.bV5ClrUsed == 0)
count = 1 << This->bih.bV5BitCount;
else
- count = This->bih.bV5ClrUsed;
+ count = min(This->bih.bV5ClrUsed, 1 << This->bih.bV5BitCount);
tablesize = sizeof(WICColor) * count;
wiccolors = HeapAlloc(GetProcessHeap(), 0, tablesize);
--
2.9.0

View File

@ -0,0 +1,236 @@
From 3f53a82d7bb5e2cd8ea740094675a009df702fbb Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Fri, 23 Sep 2016 20:17:47 +0800
Subject: windowscodecs: Add support for palette image formats to BMP encoder.
---
dlls/windowscodecs/bmpencode.c | 44 ++++++++++++++++++++++++++++--------
dlls/windowscodecs/main.c | 8 ++++++-
dlls/windowscodecs/tests/converter.c | 18 +++++++++++----
3 files changed, 55 insertions(+), 15 deletions(-)
diff --git a/dlls/windowscodecs/bmpencode.c b/dlls/windowscodecs/bmpencode.c
index af082ae..d4ec651 100644
--- a/dlls/windowscodecs/bmpencode.c
+++ b/dlls/windowscodecs/bmpencode.c
@@ -1,5 +1,6 @@
/*
* Copyright 2009 Vincent Povirk for CodeWeavers
+ * Copyright 2016 Dmitry Timoshkov
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -37,6 +38,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
struct bmp_pixelformat {
const WICPixelFormatGUID *guid;
UINT bpp;
+ UINT colors; /* palette size */
DWORD compression;
DWORD redmask;
DWORD greenmask;
@@ -45,13 +47,18 @@ struct bmp_pixelformat {
};
static const struct bmp_pixelformat formats[] = {
- {&GUID_WICPixelFormat24bppBGR, 24, BI_RGB},
- {&GUID_WICPixelFormat16bppBGR555, 16, BI_RGB},
- {&GUID_WICPixelFormat16bppBGR565, 16, BI_BITFIELDS, 0xf800, 0x7e0, 0x1f, 0},
- {&GUID_WICPixelFormat32bppBGR, 32, BI_RGB},
+ {&GUID_WICPixelFormat24bppBGR, 24, 0, BI_RGB},
+ {&GUID_WICPixelFormatBlackWhite, 1, 2, BI_RGB},
+ {&GUID_WICPixelFormat1bppIndexed, 1, 2, BI_RGB},
+ {&GUID_WICPixelFormat2bppIndexed, 2, 4, BI_RGB},
+ {&GUID_WICPixelFormat4bppIndexed, 4, 16, BI_RGB},
+ {&GUID_WICPixelFormat8bppIndexed, 8, 256, BI_RGB},
+ {&GUID_WICPixelFormat16bppBGR555, 16, 0, BI_RGB},
+ {&GUID_WICPixelFormat16bppBGR565, 16, 0, BI_BITFIELDS, 0xf800, 0x7e0, 0x1f, 0},
+ {&GUID_WICPixelFormat32bppBGR, 32, 0, BI_RGB},
#if 0
/* Windows doesn't seem to support this one. */
- {&GUID_WICPixelFormat32bppBGRA, 32, BI_BITFIELDS, 0xff0000, 0xff00, 0xff, 0xff000000},
+ {&GUID_WICPixelFormat32bppBGRA, 32, 0, BI_BITFIELDS, 0xff0000, 0xff00, 0xff, 0xff000000},
#endif
{NULL}
};
@@ -179,11 +186,13 @@ static HRESULT WINAPI BmpFrameEncode_SetPixelFormat(IWICBitmapFrameEncode *iface
for (i=0; formats[i].guid; i++)
{
- if (memcmp(formats[i].guid, pPixelFormat, sizeof(GUID)) == 0)
+ if (IsEqualGUID(formats[i].guid, pPixelFormat))
break;
}
if (!formats[i].guid) i = 0;
+ else if (IsEqualGUID(pPixelFormat, &GUID_WICPixelFormatBlackWhite))
+ i = 2; /* GUID_WICPixelFormat1bppIndexed */
This->format = &formats[i];
memcpy(pPixelFormat, This->format->guid, sizeof(GUID));
@@ -202,6 +211,7 @@ static HRESULT WINAPI BmpFrameEncode_SetPalette(IWICBitmapFrameEncode *iface,
IWICPalette *palette)
{
BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
+ HRESULT hr;
TRACE("(%p,%p)\n", iface, palette);
@@ -210,7 +220,14 @@ static HRESULT WINAPI BmpFrameEncode_SetPalette(IWICBitmapFrameEncode *iface,
if (!This->initialized)
return WINCODEC_ERR_NOTINITIALIZED;
- return IWICPalette_GetColors(palette, 256, This->palette, &This->colors);
+ hr = IWICPalette_GetColors(palette, 256, This->palette, &This->colors);
+ if (hr == S_OK)
+ {
+ UINT i;
+ for (i = 0; i < This->colors; i++)
+ This->palette[i] |= 0xff000000; /* BMP palette has no alpha */
+ }
+ return hr;
}
static HRESULT WINAPI BmpFrameEncode_SetThumbnail(IWICBitmapFrameEncode *iface,
@@ -316,8 +333,8 @@ static HRESULT WINAPI BmpFrameEncode_Commit(IWICBitmapFrameEncode *iface)
bih.bV5SizeImage = This->stride*This->height;
bih.bV5XPelsPerMeter = (This->xres+0.0127) / 0.0254;
bih.bV5YPelsPerMeter = (This->yres+0.0127) / 0.0254;
- bih.bV5ClrUsed = 0;
- bih.bV5ClrImportant = 0;
+ bih.bV5ClrUsed = (This->format->bpp <= 8) ? This->colors : 0;
+ bih.bV5ClrImportant = bih.bV5ClrUsed;
if (This->format->compression == BI_BITFIELDS)
{
@@ -334,6 +351,7 @@ static HRESULT WINAPI BmpFrameEncode_Commit(IWICBitmapFrameEncode *iface)
bfh.bfSize = sizeof(BITMAPFILEHEADER) + info_size + bih.bV5SizeImage;
bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + info_size;
+ bfh.bfOffBits += bih.bV5ClrUsed * sizeof(WICColor);
pos.QuadPart = 0;
hr = IStream_Seek(This->stream, pos, STREAM_SEEK_SET, NULL);
@@ -347,6 +365,14 @@ static HRESULT WINAPI BmpFrameEncode_Commit(IWICBitmapFrameEncode *iface)
if (FAILED(hr)) return hr;
if (byteswritten != info_size) return E_FAIL;
+ /* write the palette */
+ if (This->format->colors)
+ {
+ hr = IStream_Write(This->stream, This->palette, This->colors * sizeof(WICColor), &byteswritten);
+ if (FAILED(hr)) return hr;
+ if (byteswritten != This->colors * sizeof(WICColor)) return E_FAIL;
+ }
+
/* write the image bits as a bottom-top array */
bits = This->bits + bih.bV5SizeImage;
for (i = 0; i < This->height; i++)
diff --git a/dlls/windowscodecs/main.c b/dlls/windowscodecs/main.c
index fdd26dd..7931b3d 100644
--- a/dlls/windowscodecs/main.c
+++ b/dlls/windowscodecs/main.c
@@ -117,6 +117,12 @@ HRESULT copy_pixels(UINT bpp, const BYTE *srcbuffer,
}
}
+static BOOL is_1bpp_format(const WICPixelFormatGUID *format)
+{
+ return IsEqualGUID(format, &GUID_WICPixelFormatBlackWhite) ||
+ IsEqualGUID(format, &GUID_WICPixelFormat1bppIndexed);
+}
+
HRESULT configure_write_source(IWICBitmapFrameEncode *iface,
IWICBitmapSource *source, const WICRect *prc,
const WICPixelFormatGUID *format,
@@ -141,7 +147,7 @@ HRESULT configure_write_source(IWICBitmapFrameEncode *iface,
format = &dst_format;
}
- if (!IsEqualGUID(&src_format, format))
+ if (!IsEqualGUID(&src_format, format) && !(is_1bpp_format(&src_format) && is_1bpp_format(format)))
{
/* FIXME: should use WICConvertBitmapSource to convert */
FIXME("format %s unsupported\n", debugstr_guid(&src_format));
diff --git a/dlls/windowscodecs/tests/converter.c b/dlls/windowscodecs/tests/converter.c
index 865029f..901fbd8 100644
--- a/dlls/windowscodecs/tests/converter.c
+++ b/dlls/windowscodecs/tests/converter.c
@@ -768,6 +768,8 @@ static void check_bmp_format(IStream *stream, const WICPixelFormatGUID *format)
if (IsEqualGUID(format, &GUID_WICPixelFormat1bppIndexed))
{
+ ok(bfh.bfOffBits == 0x0436, "wrong bfOffBits %02x\n", bfh.bfOffBits);
+
ok(bih.bV5Width == 32, "wrong width %u\n", bih.bV5Width);
ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height);
@@ -778,6 +780,8 @@ static void check_bmp_format(IStream *stream, const WICPixelFormatGUID *format)
}
else if (IsEqualGUID(format, &GUID_WICPixelFormat2bppIndexed))
{
+ ok(bfh.bfOffBits == 0x0436, "wrong bfOffBits %02x\n", bfh.bfOffBits);
+
ok(bih.bV5Width == 16, "wrong width %u\n", bih.bV5Width);
ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height);
@@ -788,6 +792,8 @@ static void check_bmp_format(IStream *stream, const WICPixelFormatGUID *format)
}
else if (IsEqualGUID(format, &GUID_WICPixelFormat4bppIndexed))
{
+ ok(bfh.bfOffBits == 0x0436, "wrong bfOffBits %02x\n", bfh.bfOffBits);
+
ok(bih.bV5Width == 8, "wrong width %u\n", bih.bV5Width);
ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height);
@@ -798,6 +804,8 @@ static void check_bmp_format(IStream *stream, const WICPixelFormatGUID *format)
}
else if (IsEqualGUID(format, &GUID_WICPixelFormat8bppIndexed))
{
+ ok(bfh.bfOffBits == 0x0436, "wrong bfOffBits %02x\n", bfh.bfOffBits);
+
ok(bih.bV5Width == 4, "wrong width %u\n", bih.bV5Width);
ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height);
@@ -808,6 +816,8 @@ static void check_bmp_format(IStream *stream, const WICPixelFormatGUID *format)
}
else if (IsEqualGUID(format, &GUID_WICPixelFormat32bppBGR))
{
+ ok(bfh.bfOffBits == 0x0036, "wrong bfOffBits %02x\n", bfh.bfOffBits);
+
ok(bih.bV5Width == 4, "wrong width %u\n", bih.bV5Width);
ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height);
@@ -1044,7 +1054,8 @@ static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* cls
hr = IWICBitmapFrameEncode_SetPixelFormat(frameencode, &pixelformat);
ok(SUCCEEDED(hr), "SetPixelFormat failed, hr=%x\n", hr);
ok(IsEqualGUID(&pixelformat, dsts[i]->format) ||
- broken(IsEqualGUID(clsid_encoder, &CLSID_WICTiffEncoder) && srcs[i]->bpp == 2 && IsEqualGUID(&pixelformat, &GUID_WICPixelFormat4bppIndexed)),
+ broken(IsEqualGUID(clsid_encoder, &CLSID_WICTiffEncoder) && srcs[i]->bpp == 2 && IsEqualGUID(&pixelformat, &GUID_WICPixelFormat4bppIndexed)) ||
+ broken(IsEqualGUID(clsid_encoder, &CLSID_WICBmpEncoder) && srcs[i]->bpp == 2 && IsEqualGUID(&pixelformat, &GUID_WICPixelFormat4bppIndexed)),
"SetPixelFormat changed the format to %s (%s)\n", wine_dbgstr_guid(&pixelformat), name);
hr = IWICBitmapFrameEncode_SetSize(frameencode, srcs[i]->width, srcs[i]->height);
@@ -1377,19 +1388,16 @@ START_TEST(converter)
test_encoder(&testdata_24bppBGR, &CLSID_WICPngEncoder,
&testdata_24bppBGR, &CLSID_WICPngDecoder, "PNG encoder 24bppBGR");
-if (!strcmp(winetest_platform, "windows")) /* FIXME: enable once implemented in Wine */
-{
test_encoder(&testdata_BlackWhite, &CLSID_WICBmpEncoder,
&testdata_1bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder BlackWhite");
test_encoder(&testdata_1bppIndexed, &CLSID_WICBmpEncoder,
&testdata_1bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 1bppIndexed");
test_encoder(&testdata_2bppIndexed, &CLSID_WICBmpEncoder,
- &testdata_4bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 2bppIndexed");
+ &testdata_2bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 2bppIndexed");
test_encoder(&testdata_4bppIndexed, &CLSID_WICBmpEncoder,
&testdata_4bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 4bppIndexed");
test_encoder(&testdata_8bppIndexed, &CLSID_WICBmpEncoder,
&testdata_8bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 8bppIndexed");
-}
test_encoder(&testdata_32bppBGR, &CLSID_WICBmpEncoder,
&testdata_32bppBGR, &CLSID_WICBmpDecoder, "BMP encoder 32bppBGR");
--
2.9.0

View File

@ -0,0 +1,2 @@
Fixes: Improve palette support in windowscodecs.dll
Depends: windowscodecs-32bppGrayFloat