Signed-off-by: Nikolay Sivov nsivov@codeweavers.com
-- v3: windowscodecs/converter: Implement 48bppRGB -> 128bppRGBFloat conversion.
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/windowscodecs/converter.c | 60 ++++++++++++++++++++++++++++ dlls/windowscodecs/tests/converter.c | 22 ++++++++-- 2 files changed, 78 insertions(+), 4 deletions(-)
diff --git a/dlls/windowscodecs/converter.c b/dlls/windowscodecs/converter.c index b5e253c98ea..b32478d948a 100644 --- a/dlls/windowscodecs/converter.c +++ b/dlls/windowscodecs/converter.c @@ -1038,6 +1038,17 @@ static HRESULT copypixels_to_32bppPRGBA(struct FormatConverter *This, const WICR } }
+static void set_24bppbgr_pixel(BYTE **dstpixel, WICColor color) +{ + BYTE *dst = *dstpixel; + + *dst++ = color; + *dst++ = color >> 8; + *dst++ = color >> 16; + + *dstpixel += 3; +} + static HRESULT copypixels_to_24bppBGR(struct FormatConverter *This, const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format) { @@ -1045,6 +1056,55 @@ static HRESULT copypixels_to_24bppBGR(struct FormatConverter *This, const WICRec
switch (source_format) { + case format_BlackWhite: + if (prc) + { + static const WICColor colors[2] = { 0, 0xffffff }; + BYTE *srcdata, *dstpixel, *dstrow; + UINT srcstride, srcdatasize; + const BYTE *srcbyte; + const BYTE *srcrow; + HRESULT res; + INT x, y; + + srcstride = (prc->Width+7)/8; + srcdatasize = srcstride * prc->Height; + + srcdata = malloc(srcdatasize); + if (!srcdata) return E_OUTOFMEMORY; + + res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); + + if (SUCCEEDED(res)) + { + srcrow = srcdata; + dstrow = pbBuffer; + for (y=0; y<prc->Height; y++) { + srcbyte = srcrow; + dstpixel= dstrow; + for (x=0; x<prc->Width; x+=8) { + BYTE srcval; + srcval=*srcbyte++; + + set_24bppbgr_pixel(&dstpixel, colors[srcval>>7&1]); + if (x+1 < prc->Width) set_24bppbgr_pixel(&dstpixel, colors[srcval>>6&1]); + if (x+2 < prc->Width) set_24bppbgr_pixel(&dstpixel, colors[srcval>>5&1]); + if (x+3 < prc->Width) set_24bppbgr_pixel(&dstpixel, colors[srcval>>4&1]); + if (x+4 < prc->Width) set_24bppbgr_pixel(&dstpixel, colors[srcval>>3&1]); + if (x+5 < prc->Width) set_24bppbgr_pixel(&dstpixel, colors[srcval>>2&1]); + if (x+6 < prc->Width) set_24bppbgr_pixel(&dstpixel, colors[srcval>>1&1]); + if (x+7 < prc->Width) set_24bppbgr_pixel(&dstpixel, colors[srcval>>0&1]); + } + srcrow += srcstride; + dstrow += cbStride; + } + } + + free(srcdata); + + return res; + } + return S_OK; case format_24bppBGR: case format_24bppRGB: if (prc) diff --git a/dlls/windowscodecs/tests/converter.c b/dlls/windowscodecs/tests/converter.c index 24cc5a9fb5d..bd9a18122d4 100644 --- a/dlls/windowscodecs/tests/converter.c +++ b/dlls/windowscodecs/tests/converter.c @@ -433,6 +433,19 @@ static const BYTE bits_24bppBGR[] = { static const struct bitmap_data testdata_24bppBGR = { &GUID_WICPixelFormat24bppBGR, 24, bits_24bppBGR, 32, 2, 96.0, 96.0};
+static const BYTE bits_24bppBGR_BW[] = { + 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, + 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, + 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, + 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, + + 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, + 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, + 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, + 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0, 255,255,255, 0,0,0}; +static const struct bitmap_data testdata_24bppBGR_BW = { + &GUID_WICPixelFormat24bppBGR, 24, bits_24bppBGR_BW, 32, 2, 96.0, 96.0}; + static const BYTE bits_24bppRGB[] = { 0,0,255, 0,255,0, 255,0,0, 0,0,0, 0,0,255, 0,255,0, 255,0,0, 0,0,0, 0,0,255, 0,255,0, 255,0,0, 0,0,0, 0,0,255, 0,255,0, 255,0,0, 0,0,0, @@ -725,11 +738,11 @@ static void test_can_convert(void) {WIC_PIXEL_FORMAT(1bppIndexed), TRUE, TRUE, 35}, {WIC_PIXEL_FORMAT(2bppIndexed), TRUE, TRUE, 35}, {WIC_PIXEL_FORMAT(4bppIndexed), TRUE, TRUE, 35}, - {WIC_PIXEL_FORMAT(8bppIndexed), TRUE, TRUE, 27}, + {WIC_PIXEL_FORMAT(8bppIndexed), TRUE, TRUE, 26}, {WIC_PIXEL_FORMAT(BlackWhite), TRUE, TRUE, 35}, {WIC_PIXEL_FORMAT(2bppGray), TRUE, TRUE, 35}, {WIC_PIXEL_FORMAT(4bppGray), TRUE, TRUE, 35}, - {WIC_PIXEL_FORMAT(8bppGray), TRUE, TRUE, 27}, + {WIC_PIXEL_FORMAT(8bppGray), TRUE, TRUE, 26}, {WIC_PIXEL_FORMAT(16bppGray), TRUE, TRUE, 35},
{WIC_PIXEL_FORMAT(8bppAlpha), TRUE, TRUE, 35, TRUE}, @@ -737,7 +750,7 @@ static void test_can_convert(void) {WIC_PIXEL_FORMAT(16bppBGR555), TRUE, TRUE, 35}, {WIC_PIXEL_FORMAT(16bppBGR565), TRUE, TRUE, 35}, {WIC_PIXEL_FORMAT(16bppBGRA5551), TRUE, TRUE, 33, TRUE}, - {WIC_PIXEL_FORMAT(24bppBGR), TRUE, TRUE, 28}, + {WIC_PIXEL_FORMAT(24bppBGR), TRUE, TRUE, 27}, {WIC_PIXEL_FORMAT(24bppRGB), TRUE, TRUE, 30}, {WIC_PIXEL_FORMAT(32bppBGR), TRUE, TRUE, 15}, {WIC_PIXEL_FORMAT(32bppBGRA), TRUE, TRUE, 15}, @@ -2216,7 +2229,8 @@ START_TEST(converter) test_conversion(&testdata_24bppRGB, &testdata_4bppIndexed, "24bppRGB -> 4bppIndexed", TRUE); test_conversion(&testdata_24bppRGB, &testdata_8bppIndexed, "24bppRGB -> 8bppIndexed", FALSE);
- test_conversion(&testdata_BlackWhite, &testdata_8bppIndexed_BW, "BlackWhite -> 8bppIndexed", TRUE); + test_conversion(&testdata_BlackWhite, &testdata_8bppIndexed_BW, "BlackWhite -> 8bppIndexed", FALSE); + test_conversion(&testdata_BlackWhite, &testdata_24bppBGR_BW, "BlackWhite -> 24bppBGR", FALSE); test_conversion(&testdata_1bppIndexed, &testdata_8bppIndexed_BW, "1bppIndexed -> 8bppIndexed", TRUE); test_conversion(&testdata_2bppIndexed, &testdata_8bppIndexed_4colors, "2bppIndexed -> 8bppIndexed", TRUE); test_conversion(&testdata_4bppIndexed, &testdata_8bppIndexed, "4bppIndexed -> 8bppIndexed", TRUE);
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/windowscodecs/converter.c | 61 +++++++++++++++++++++++++++- dlls/windowscodecs/regsvr.c | 12 ++++++ dlls/windowscodecs/tests/converter.c | 38 +++++++++++++---- 3 files changed, 102 insertions(+), 9 deletions(-)
diff --git a/dlls/windowscodecs/converter.c b/dlls/windowscodecs/converter.c index b32478d948a..d72f6b2d8d4 100644 --- a/dlls/windowscodecs/converter.c +++ b/dlls/windowscodecs/converter.c @@ -101,13 +101,14 @@ static inline float to_sRGB_component(float f) return 1.055f * powf(f, 1.0f/2.4f) - 0.055f; }
-#if 0 /* FIXME: enable once needed */ static inline float from_sRGB_component(float f) { if (f <= 0.04045f) return f / 12.92f; return powf((f + 0.055f) / 1.055f, 2.4f); }
+#if 0 /* FIXME: enable once needed */ + static void from_sRGB(BYTE *bgr) { float r, g, b; @@ -1687,6 +1688,62 @@ static HRESULT copypixels_to_64bppRGBA(struct FormatConverter *This, const WICRe } }
+static HRESULT copypixels_to_128bppRGBFloat(struct FormatConverter *This, const WICRect *prc, + UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format) +{ + HRESULT hr; + + switch (source_format) + { + case format_48bppRGB: + { + UINT srcstride, srcdatasize; + const USHORT *srcpixel; + const BYTE *srcrow; + float *dstpixel; + BYTE *srcdata; + BYTE *dstrow; + INT x, y; + + if (!prc) + return S_OK; + + srcstride = 6 * prc->Width; + srcdatasize = srcstride * prc->Height; + + srcdata = malloc(srcdatasize); + if (!srcdata) return E_OUTOFMEMORY; + + hr = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); + if (SUCCEEDED(hr)) + { + srcrow = srcdata; + dstrow = pbBuffer; + for (y = 0; y < prc->Height; y++) + { + srcpixel = (USHORT *)srcrow; + dstpixel= (float *)dstrow; + for (x = 0; x < prc->Width; x++) + { + *dstpixel++ = from_sRGB_component(*srcpixel++ / 65535.0f); + *dstpixel++ = from_sRGB_component(*srcpixel++ / 65535.0f); + *dstpixel++ = from_sRGB_component(*srcpixel++ / 65535.0f); + *dstpixel++ = 1.0f; + } + srcrow += srcstride; + dstrow += cbStride; + } + } + + free(srcdata); + return S_OK; + } + default: + FIXME("Unimplemented conversion path %d.\n", source_format); + return WINCODEC_ERR_UNSUPPORTEDOPERATION; + } +} + static const struct pixelformatinfo supported_formats[] = { {format_1bppIndexed, &GUID_WICPixelFormat1bppIndexed, NULL, TRUE}, {format_2bppIndexed, &GUID_WICPixelFormat2bppIndexed, NULL, TRUE}, @@ -1722,7 +1779,7 @@ static const struct pixelformatinfo supported_formats[] = { {format_96bppRGBFloat, &GUID_WICPixelFormat96bppRGBFloat, NULL}, {format_128bppRGBAFloat, &GUID_WICPixelFormat128bppRGBAFloat, NULL}, {format_128bppPRGBAFloat, &GUID_WICPixelFormat128bppPRGBAFloat, NULL}, - {format_128bppRGBFloat, &GUID_WICPixelFormat128bppRGBFloat, NULL}, + {format_128bppRGBFloat, &GUID_WICPixelFormat128bppRGBFloat, copypixels_to_128bppRGBFloat }, {format_32bppR10G10B10A2, &GUID_WICPixelFormat32bppR10G10B10A2, NULL}, {0} }; diff --git a/dlls/windowscodecs/regsvr.c b/dlls/windowscodecs/regsvr.c index 4d27f637f78..59bc8263b7d 100644 --- a/dlls/windowscodecs/regsvr.c +++ b/dlls/windowscodecs/regsvr.c @@ -1683,6 +1683,7 @@ static GUID const * const converter_formats[] = { &GUID_WICPixelFormat48bppRGB, &GUID_WICPixelFormat64bppRGBA, &GUID_WICPixelFormat32bppCMYK, + &GUID_WICPixelFormat128bppRGBFloat, NULL };
@@ -2461,6 +2462,17 @@ static struct regsvr_pixelformat const pixelformat_list[] = { WICPixelFormatNumericRepresentationFloat, 1 }, + { &GUID_WICPixelFormat128bppRGBFloat, + "The Wine Project", + "128bpp RGBFloat", + NULL, /* no version */ + &GUID_VendorMicrosoft, + 128, /* bitsperpixel */ + 3, /* channel count */ + channel_masks_128bit, + WICPixelFormatNumericRepresentationFloat, + 0 + }, { NULL } /* list terminator */ };
diff --git a/dlls/windowscodecs/tests/converter.c b/dlls/windowscodecs/tests/converter.c index bd9a18122d4..1657a8b6abd 100644 --- a/dlls/windowscodecs/tests/converter.c +++ b/dlls/windowscodecs/tests/converter.c @@ -233,7 +233,7 @@ static void DeleteTestBitmap(BitmapTestSrc *This)
static BOOL compare_bits(const struct bitmap_data *expect, UINT buffersize, const BYTE *converted_bits) { - BOOL equal; + BOOL equal, is_float = FALSE;
if (IsEqualGUID(expect->format, &GUID_WICPixelFormat32bppBGR)) { @@ -248,11 +248,13 @@ static BOOL compare_bits(const struct bitmap_data *expect, UINT buffersize, cons break; } } - else if (IsEqualGUID(expect->format, &GUID_WICPixelFormat32bppGrayFloat)) + else if (IsEqualGUID(expect->format, &GUID_WICPixelFormat32bppGrayFloat) + || IsEqualGUID(expect->format, &GUID_WICPixelFormat128bppRGBFloat)) { UINT i; const float *a=(const float*)expect->bits, *b=(const float*)converted_bits; equal=TRUE; + is_float = TRUE; for (i=0; i<(buffersize/4); i++) if (!near_equal(a[i], b[i])) { @@ -297,14 +299,28 @@ static BOOL compare_bits(const struct bitmap_data *expect, UINT buffersize, cons if (!equal && winetest_debug > 1) { UINT i, bps; + bps = expect->bpp / 8; if (!bps) bps = buffersize; printf("converted_bits (%u bytes):\n ", buffersize); - for (i = 0; i < buffersize; i++) + if (is_float) + { + const float *src = (const float *)converted_bits; + for (i = 0; i < buffersize / 4; i++) + { + printf("%f,", src[i]); + if (!((i + 1) % 32)) printf("\n "); + else if (!((i+1) % bps)) printf(" "); + } + } + else { - printf("%u,", converted_bits[i]); - if (!((i + 1) % 32)) printf("\n "); - else if (!((i+1) % bps)) printf(" "); + for (i = 0; i < buffersize; i++) + { + printf("%u,", converted_bits[i]); + if (!((i + 1) % 32)) printf("\n "); + else if (!((i+1) % bps)) printf(" "); + } } printf("\n"); } @@ -649,6 +665,12 @@ static const WORD bits_64bppRGBA_2[] = { static const struct bitmap_data testdata_64bppRGBA_2 = { &GUID_WICPixelFormat64bppRGBA, 64, (BYTE*)bits_64bppRGBA_2, 3, 2, 96.0, 96.0};
+static const float bits_128bppRGBFloat[] = { + 0.0f,0.0f,0.0f,1.0f, 0.0f,1.0f,0.0f,1.0f, 0.214039f,0.214053f,0.214039f,1.0f, + 1.0f,1.0f,1.0f,1.0f, 0.000012f,0.000012f,0.000012f,1.0f, 0.0f,0.0f,0.000012f,1.0f,}; +static const struct bitmap_data testdata_128bppRGBFloat = { + &GUID_WICPixelFormat128bppRGBFloat, 128, (const BYTE *)bits_128bppRGBFloat, 3, 2, 96.0, 96.0}; + static void test_conversion(const struct bitmap_data *src, const struct bitmap_data *dst, const char *name, BOOL todo) { BitmapTestSrc *src_obj; @@ -776,7 +798,7 @@ static void test_can_convert(void) {WIC_PIXEL_FORMAT(96bppRGBFloat), TRUE, TRUE, 35, TRUE}, {WIC_PIXEL_FORMAT(128bppRGBAFloat), TRUE, TRUE, 35}, {WIC_PIXEL_FORMAT(128bppPRGBAFloat), TRUE, TRUE, 35}, - {WIC_PIXEL_FORMAT(128bppRGBFloat), TRUE, TRUE, 35}, + {WIC_PIXEL_FORMAT(128bppRGBFloat), TRUE, TRUE, 34},
{WIC_PIXEL_FORMAT(32bppCMYK)},
@@ -2272,6 +2294,8 @@ START_TEST(converter) test_conversion(&testdata_32bppBGRA, &testdata_16bppBGRA5551, "32bppBGRA -> 16bppBGRA5551", FALSE); test_conversion(&testdata_48bppRGB, &testdata_64bppRGBA_2, "48bppRGB -> 64bppRGBA", FALSE);
+ test_conversion(&testdata_48bppRGB, &testdata_128bppRGBFloat, "48bppRGB -> 128bppRGBFloat", FALSE); + test_invalid_conversion(); test_default_converter(); test_can_convert();
This merge request was approved by Esme Povirk.