From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/windowscodecs/converter.c | 68 ++++++++++++++++++++++++++++ dlls/windowscodecs/regsvr.c | 1 + dlls/windowscodecs/tests/converter.c | 8 ++++ 3 files changed, 77 insertions(+)
diff --git a/dlls/windowscodecs/converter.c b/dlls/windowscodecs/converter.c index 526d5c05aca..04dcb0b9fc5 100644 --- a/dlls/windowscodecs/converter.c +++ b/dlls/windowscodecs/converter.c @@ -61,6 +61,7 @@ enum pixelformat { format_32bppCMYK, format_8bppAlpha, format_48bppBGR, + format_48bppRGBHalf, format_64bppRGB, format_64bppBGRA, format_64bppPRGBA, @@ -94,6 +95,24 @@ typedef struct FormatConverter { CRITICAL_SECTION lock; /* must be held when initialized */ } FormatConverter;
+static float float_16_to_32(unsigned short in) +{ + const unsigned short s = (in & 0x8000); + const unsigned short e = (in & 0x7C00) >> 10; + const unsigned short m = in & 0x3FF; + const float sgn = (s ? -1.0f : 1.0f); + + if (e == 0) + { + if (m == 0) return sgn * 0.0f; /* +0.0 or -0.0 */ + else return sgn * powf(2, -14.0f) * (m / 1024.0f); + } + else + { + return sgn * powf(2, e - 15.0f) * (1.0f + (m / 1024.0f)); + } +} + /* https://www.w3.org/Graphics/Color/srgb */ static inline float to_sRGB_component(float f) { @@ -975,6 +994,54 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe return res; } return S_OK; + case format_48bppRGBHalf: + if (prc) + { + UINT srcstride, srcdatasize; + const USHORT *srcpixel; + const BYTE *srcrow; + DWORD *dstpixel; + BYTE *srcdata; + BYTE *dstrow; + HRESULT res; + INT x, y; + + srcstride = 6 * prc->Width; + 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++) + { + srcpixel = (const USHORT *)srcrow; + dstpixel = (DWORD *)dstrow; + for (x = 0; x < prc->Width; x++) + { + BYTE red, green, blue; + + red = (BYTE)floorf(to_sRGB_component(float_16_to_32(*srcpixel++)) * 255.0f + 0.51f); + green = (BYTE)floorf(to_sRGB_component(float_16_to_32(*srcpixel++)) * 255.0f + 0.51f); + blue = (BYTE)floorf(to_sRGB_component(float_16_to_32(*srcpixel++)) * 255.0f + 0.51f); + + *dstpixel++ = 0xff000000 | red << 16 | green << 8 | blue; + } + srcrow += srcstride; + dstrow += cbStride; + } + } + + free(srcdata); + + return res; + } + return S_OK; default: FIXME("Unimplemented conversion path!\n"); return WINCODEC_ERR_UNSUPPORTEDOPERATION; @@ -2024,6 +2091,7 @@ static const struct pixelformatinfo supported_formats[] = { {format_128bppPRGBAFloat, &GUID_WICPixelFormat128bppPRGBAFloat, NULL}, {format_128bppRGBFloat, &GUID_WICPixelFormat128bppRGBFloat, copypixels_to_128bppRGBFloat }, {format_32bppR10G10B10A2, &GUID_WICPixelFormat32bppR10G10B10A2, NULL}, + {format_48bppRGBHalf, &GUID_WICPixelFormat48bppRGBHalf}, {0} };
diff --git a/dlls/windowscodecs/regsvr.c b/dlls/windowscodecs/regsvr.c index eddb6e13024..47a2bd76d2a 100644 --- a/dlls/windowscodecs/regsvr.c +++ b/dlls/windowscodecs/regsvr.c @@ -1681,6 +1681,7 @@ static GUID const * const converter_formats[] = { &GUID_WICPixelFormat32bppPRGBA, &GUID_WICPixelFormat32bppGrayFloat, &GUID_WICPixelFormat48bppRGB, + &GUID_WICPixelFormat48bppRGBHalf, &GUID_WICPixelFormat64bppRGBA, &GUID_WICPixelFormat32bppCMYK, &GUID_WICPixelFormat96bppRGBFloat, diff --git a/dlls/windowscodecs/tests/converter.c b/dlls/windowscodecs/tests/converter.c index 63ab44fba32..2f66df954a5 100644 --- a/dlls/windowscodecs/tests/converter.c +++ b/dlls/windowscodecs/tests/converter.c @@ -684,6 +684,12 @@ static const BYTE bits_32bppBGRA_3[] = { static const struct bitmap_data testdata_32bppBGRA_3 = { &GUID_WICPixelFormat32bppBGRA, 32, bits_32bppBGRA_3, 3, 2, 96.0, 96.0};
+static const WORD bits_48bppRGBHalf[] = { + 0,0,0, 0,0x3c00,0, 0x3c00,0,0, + 0,0,0x3c00, 0,0x3290,0, 0x3290,0,0 }; +static const struct bitmap_data testdata_48bppRGBHalf = { + &GUID_WICPixelFormat48bppRGBHalf, 48, (const BYTE *)bits_48bppRGBHalf, 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,}; @@ -2343,6 +2349,8 @@ START_TEST(converter) test_conversion(&testdata_96bppRGBFloat_2, &testdata_32bppBGRA_3, "96bppRGBFloat -> 32bppBGRA", FALSE); test_conversion(&testdata_128bppRGBAFloat_2, &testdata_32bppBGRA_2, "128bppRGBAFloat -> 32bppBGRA", FALSE);
+ test_conversion(&testdata_48bppRGBHalf, &testdata_32bppBGRA_3, "48bppRGBHalf -> 32bppBGRA", FALSE); + test_invalid_conversion(); test_default_converter(); test_can_convert();