windowscodecs: Add support for palette image formats to BMP encoder.
Signed-off-by: Dmitry Timoshkov <dmitry@baikal.ru> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
d13d34d101
commit
ee6dd81e92
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2009 Vincent Povirk for CodeWeavers
|
* Copyright 2009 Vincent Povirk for CodeWeavers
|
||||||
|
* Copyright 2016 Dmitry Timoshkov
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
@ -37,6 +38,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
|
||||||
struct bmp_pixelformat {
|
struct bmp_pixelformat {
|
||||||
const WICPixelFormatGUID *guid;
|
const WICPixelFormatGUID *guid;
|
||||||
UINT bpp;
|
UINT bpp;
|
||||||
|
UINT colors; /* palette size */
|
||||||
DWORD compression;
|
DWORD compression;
|
||||||
DWORD redmask;
|
DWORD redmask;
|
||||||
DWORD greenmask;
|
DWORD greenmask;
|
||||||
|
@ -45,13 +47,18 @@ struct bmp_pixelformat {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct bmp_pixelformat formats[] = {
|
static const struct bmp_pixelformat formats[] = {
|
||||||
{&GUID_WICPixelFormat24bppBGR, 24, BI_RGB},
|
{&GUID_WICPixelFormat24bppBGR, 24, 0, BI_RGB},
|
||||||
{&GUID_WICPixelFormat16bppBGR555, 16, BI_RGB},
|
{&GUID_WICPixelFormatBlackWhite, 1, 2, BI_RGB},
|
||||||
{&GUID_WICPixelFormat16bppBGR565, 16, BI_BITFIELDS, 0xf800, 0x7e0, 0x1f, 0},
|
{&GUID_WICPixelFormat1bppIndexed, 1, 2, BI_RGB},
|
||||||
{&GUID_WICPixelFormat32bppBGR, 32, 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
|
#if 0
|
||||||
/* Windows doesn't seem to support this one. */
|
/* 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
|
#endif
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
@ -182,9 +189,14 @@ static HRESULT WINAPI BmpFrameEncode_SetPixelFormat(IWICBitmapFrameEncode *iface
|
||||||
|
|
||||||
if (!This->initialized || This->bits) return WINCODEC_ERR_WRONGSTATE;
|
if (!This->initialized || This->bits) return WINCODEC_ERR_WRONGSTATE;
|
||||||
|
|
||||||
|
if (IsEqualGUID(pPixelFormat, &GUID_WICPixelFormatBlackWhite))
|
||||||
|
*pPixelFormat = GUID_WICPixelFormat1bppIndexed;
|
||||||
|
else if (IsEqualGUID(pPixelFormat, &GUID_WICPixelFormat2bppIndexed))
|
||||||
|
*pPixelFormat = GUID_WICPixelFormat4bppIndexed;
|
||||||
|
|
||||||
for (i=0; formats[i].guid; i++)
|
for (i=0; formats[i].guid; i++)
|
||||||
{
|
{
|
||||||
if (memcmp(formats[i].guid, pPixelFormat, sizeof(GUID)) == 0)
|
if (IsEqualGUID(formats[i].guid, pPixelFormat))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,6 +219,7 @@ static HRESULT WINAPI BmpFrameEncode_SetPalette(IWICBitmapFrameEncode *iface,
|
||||||
IWICPalette *palette)
|
IWICPalette *palette)
|
||||||
{
|
{
|
||||||
BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
|
BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
TRACE("(%p,%p)\n", iface, palette);
|
TRACE("(%p,%p)\n", iface, palette);
|
||||||
|
|
||||||
|
@ -215,7 +228,14 @@ static HRESULT WINAPI BmpFrameEncode_SetPalette(IWICBitmapFrameEncode *iface,
|
||||||
if (!This->initialized)
|
if (!This->initialized)
|
||||||
return WINCODEC_ERR_NOTINITIALIZED;
|
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,
|
static HRESULT WINAPI BmpFrameEncode_SetThumbnail(IWICBitmapFrameEncode *iface,
|
||||||
|
@ -330,8 +350,8 @@ static HRESULT WINAPI BmpFrameEncode_Commit(IWICBitmapFrameEncode *iface)
|
||||||
bih.bV5SizeImage = This->stride*This->height;
|
bih.bV5SizeImage = This->stride*This->height;
|
||||||
bih.bV5XPelsPerMeter = (This->xres+0.0127) / 0.0254;
|
bih.bV5XPelsPerMeter = (This->xres+0.0127) / 0.0254;
|
||||||
bih.bV5YPelsPerMeter = (This->yres+0.0127) / 0.0254;
|
bih.bV5YPelsPerMeter = (This->yres+0.0127) / 0.0254;
|
||||||
bih.bV5ClrUsed = 0;
|
bih.bV5ClrUsed = (This->format->bpp <= 8) ? This->colors : 0;
|
||||||
bih.bV5ClrImportant = 0;
|
bih.bV5ClrImportant = bih.bV5ClrUsed;
|
||||||
|
|
||||||
if (This->format->compression == BI_BITFIELDS)
|
if (This->format->compression == BI_BITFIELDS)
|
||||||
{
|
{
|
||||||
|
@ -348,6 +368,7 @@ static HRESULT WINAPI BmpFrameEncode_Commit(IWICBitmapFrameEncode *iface)
|
||||||
|
|
||||||
bfh.bfSize = sizeof(BITMAPFILEHEADER) + info_size + bih.bV5SizeImage;
|
bfh.bfSize = sizeof(BITMAPFILEHEADER) + info_size + bih.bV5SizeImage;
|
||||||
bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + info_size;
|
bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + info_size;
|
||||||
|
bfh.bfOffBits += bih.bV5ClrUsed * sizeof(WICColor);
|
||||||
|
|
||||||
pos.QuadPart = 0;
|
pos.QuadPart = 0;
|
||||||
hr = IStream_Seek(This->stream, pos, STREAM_SEEK_SET, NULL);
|
hr = IStream_Seek(This->stream, pos, STREAM_SEEK_SET, NULL);
|
||||||
|
@ -361,6 +382,14 @@ static HRESULT WINAPI BmpFrameEncode_Commit(IWICBitmapFrameEncode *iface)
|
||||||
if (FAILED(hr)) return hr;
|
if (FAILED(hr)) return hr;
|
||||||
if (byteswritten != info_size) return E_FAIL;
|
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);
|
hr = IStream_Write(This->stream, This->bits, bih.bV5SizeImage, &byteswritten);
|
||||||
if (FAILED(hr)) return hr;
|
if (FAILED(hr)) return hr;
|
||||||
if (byteswritten != bih.bV5SizeImage) return E_FAIL;
|
if (byteswritten != bih.bV5SizeImage) return E_FAIL;
|
||||||
|
|
|
@ -2461,6 +2461,12 @@ HRESULT CreateComponentEnumerator(DWORD componentTypes, DWORD options, IEnumUnkn
|
||||||
return hr;
|
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 WINAPI WICConvertBitmapSource(REFWICPixelFormatGUID dstFormat, IWICBitmapSource *pISrc, IWICBitmapSource **ppIDst)
|
||||||
{
|
{
|
||||||
HRESULT res;
|
HRESULT res;
|
||||||
|
@ -2476,7 +2482,7 @@ HRESULT WINAPI WICConvertBitmapSource(REFWICPixelFormatGUID dstFormat, IWICBitma
|
||||||
res = IWICBitmapSource_GetPixelFormat(pISrc, &srcFormat);
|
res = IWICBitmapSource_GetPixelFormat(pISrc, &srcFormat);
|
||||||
if (FAILED(res)) return res;
|
if (FAILED(res)) return res;
|
||||||
|
|
||||||
if (IsEqualGUID(&srcFormat, dstFormat))
|
if (IsEqualGUID(&srcFormat, dstFormat) || (is_1bpp_format(&srcFormat) && is_1bpp_format(dstFormat)))
|
||||||
{
|
{
|
||||||
IWICBitmapSource_AddRef(pISrc);
|
IWICBitmapSource_AddRef(pISrc);
|
||||||
*ppIDst = pISrc;
|
*ppIDst = pISrc;
|
||||||
|
|
|
@ -1347,6 +1347,10 @@ static GUID const * const bmp_encode_formats[] = {
|
||||||
&GUID_WICPixelFormat16bppBGR565,
|
&GUID_WICPixelFormat16bppBGR565,
|
||||||
&GUID_WICPixelFormat24bppBGR,
|
&GUID_WICPixelFormat24bppBGR,
|
||||||
&GUID_WICPixelFormat32bppBGR,
|
&GUID_WICPixelFormat32bppBGR,
|
||||||
|
&GUID_WICPixelFormatBlackWhite,
|
||||||
|
&GUID_WICPixelFormat1bppIndexed,
|
||||||
|
&GUID_WICPixelFormat4bppIndexed,
|
||||||
|
&GUID_WICPixelFormat8bppIndexed,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -804,6 +804,8 @@ static void check_bmp_format(IStream *stream, const WICPixelFormatGUID *format)
|
||||||
|
|
||||||
if (IsEqualGUID(format, &GUID_WICPixelFormat1bppIndexed))
|
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.bV5Width == 32, "wrong width %u\n", bih.bV5Width);
|
||||||
ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height);
|
ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height);
|
||||||
|
|
||||||
|
@ -814,6 +816,8 @@ static void check_bmp_format(IStream *stream, const WICPixelFormatGUID *format)
|
||||||
}
|
}
|
||||||
else if (IsEqualGUID(format, &GUID_WICPixelFormat4bppIndexed))
|
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.bV5Width == 8, "wrong width %u\n", bih.bV5Width);
|
||||||
ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height);
|
ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height);
|
||||||
|
|
||||||
|
@ -824,6 +828,8 @@ static void check_bmp_format(IStream *stream, const WICPixelFormatGUID *format)
|
||||||
}
|
}
|
||||||
else if (IsEqualGUID(format, &GUID_WICPixelFormat8bppIndexed))
|
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.bV5Width == 4, "wrong width %u\n", bih.bV5Width);
|
||||||
ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height);
|
ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height);
|
||||||
|
|
||||||
|
@ -834,6 +840,8 @@ static void check_bmp_format(IStream *stream, const WICPixelFormatGUID *format)
|
||||||
}
|
}
|
||||||
else if (IsEqualGUID(format, &GUID_WICPixelFormat32bppBGR))
|
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.bV5Width == 4, "wrong width %u\n", bih.bV5Width);
|
||||||
ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height);
|
ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height);
|
||||||
|
|
||||||
|
@ -1492,8 +1500,6 @@ START_TEST(converter)
|
||||||
test_encoder(&testdata_24bppBGR, &CLSID_WICPngEncoder,
|
test_encoder(&testdata_24bppBGR, &CLSID_WICPngEncoder,
|
||||||
&testdata_24bppBGR, &CLSID_WICPngDecoder, "PNG encoder 24bppBGR");
|
&testdata_24bppBGR, &CLSID_WICPngDecoder, "PNG encoder 24bppBGR");
|
||||||
|
|
||||||
if (!strcmp(winetest_platform, "windows")) /* FIXME: enable once implemented in Wine */
|
|
||||||
{
|
|
||||||
test_encoder(&testdata_BlackWhite, &CLSID_WICBmpEncoder,
|
test_encoder(&testdata_BlackWhite, &CLSID_WICBmpEncoder,
|
||||||
&testdata_1bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder BlackWhite");
|
&testdata_1bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder BlackWhite");
|
||||||
test_encoder(&testdata_1bppIndexed, &CLSID_WICBmpEncoder,
|
test_encoder(&testdata_1bppIndexed, &CLSID_WICBmpEncoder,
|
||||||
|
@ -1504,7 +1510,6 @@ if (!strcmp(winetest_platform, "windows")) /* FIXME: enable once implemented in
|
||||||
&testdata_4bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 4bppIndexed");
|
&testdata_4bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 4bppIndexed");
|
||||||
test_encoder(&testdata_8bppIndexed, &CLSID_WICBmpEncoder,
|
test_encoder(&testdata_8bppIndexed, &CLSID_WICBmpEncoder,
|
||||||
&testdata_8bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 8bppIndexed");
|
&testdata_8bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 8bppIndexed");
|
||||||
}
|
|
||||||
test_encoder(&testdata_32bppBGR, &CLSID_WICBmpEncoder,
|
test_encoder(&testdata_32bppBGR, &CLSID_WICBmpEncoder,
|
||||||
&testdata_32bppBGR, &CLSID_WICBmpDecoder, "BMP encoder 32bppBGR");
|
&testdata_32bppBGR, &CLSID_WICBmpDecoder, "BMP encoder 32bppBGR");
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue