Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/windowscodecs/bmpencode.c | 44 ++++++++++++++++++++++------ dlls/windowscodecs/info.c | 8 ++++- dlls/windowscodecs/regsvr.c | 5 ++++ dlls/windowscodecs/tests/converter.c | 13 ++++++-- 4 files changed, 57 insertions(+), 13 deletions(-)
diff --git a/dlls/windowscodecs/bmpencode.c b/dlls/windowscodecs/bmpencode.c index b8783a499e..35130e7d5a 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} }; @@ -184,11 +191,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)); @@ -207,6 +216,7 @@ static HRESULT WINAPI BmpFrameEncode_SetPalette(IWICBitmapFrameEncode *iface, IWICPalette *palette) { BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); + HRESULT hr;
TRACE("(%p,%p)\n", iface, palette);
@@ -215,7 +225,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, @@ -330,8 +347,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) { @@ -348,6 +365,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); @@ -361,6 +379,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; + } + hr = IStream_Write(This->stream, This->bits, bih.bV5SizeImage, &byteswritten); if (FAILED(hr)) return hr; if (byteswritten != bih.bV5SizeImage) return E_FAIL; diff --git a/dlls/windowscodecs/info.c b/dlls/windowscodecs/info.c index e131107e99..86707e1253 100644 --- a/dlls/windowscodecs/info.c +++ b/dlls/windowscodecs/info.c @@ -2461,6 +2461,12 @@ HRESULT CreateComponentEnumerator(DWORD componentTypes, DWORD options, IEnumUnkn return hr; }
+static BOOL is_1bpp_format(const WICPixelFormatGUID *format) +{ + return IsEqualGUID(format, &GUID_WICPixelFormatBlackWhite) || + IsEqualGUID(format, &GUID_WICPixelFormat1bppIndexed); +} + HRESULT WINAPI WICConvertBitmapSource(REFWICPixelFormatGUID dstFormat, IWICBitmapSource *pISrc, IWICBitmapSource **ppIDst) { HRESULT res; @@ -2476,7 +2482,7 @@ HRESULT WINAPI WICConvertBitmapSource(REFWICPixelFormatGUID dstFormat, IWICBitma res = IWICBitmapSource_GetPixelFormat(pISrc, &srcFormat); if (FAILED(res)) return res;
- if (IsEqualGUID(&srcFormat, dstFormat)) + if (IsEqualGUID(&srcFormat, dstFormat) || (is_1bpp_format(&srcFormat) && is_1bpp_format(dstFormat))) { IWICBitmapSource_AddRef(pISrc); *ppIDst = pISrc; diff --git a/dlls/windowscodecs/regsvr.c b/dlls/windowscodecs/regsvr.c index 05c8f03a3d..7600de3099 100644 --- a/dlls/windowscodecs/regsvr.c +++ b/dlls/windowscodecs/regsvr.c @@ -1347,6 +1347,11 @@ static GUID const * const bmp_encode_formats[] = { &GUID_WICPixelFormat16bppBGR565, &GUID_WICPixelFormat24bppBGR, &GUID_WICPixelFormat32bppBGR, + &GUID_WICPixelFormatBlackWhite, + &GUID_WICPixelFormat1bppIndexed, + &GUID_WICPixelFormat2bppIndexed, + &GUID_WICPixelFormat4bppIndexed, + &GUID_WICPixelFormat8bppIndexed, NULL };
diff --git a/dlls/windowscodecs/tests/converter.c b/dlls/windowscodecs/tests/converter.c index 13c50d7dff..0d37b72397 100644 --- a/dlls/windowscodecs/tests/converter.c +++ b/dlls/windowscodecs/tests/converter.c @@ -814,6 +814,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);
@@ -824,6 +826,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);
@@ -834,6 +838,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);
@@ -844,6 +850,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);
@@ -854,6 +862,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);
@@ -1521,8 +1531,6 @@ 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, @@ -1533,7 +1541,6 @@ if (!strcmp(winetest_platform, "windows")) /* FIXME: enable once implemented in &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");