https://git.reactos.org/?p=reactos.git;a=commitdiff;h=3e9c4dad6627078cb1bb3…
commit 3e9c4dad6627078cb1bb36d077a5b20676c51d4b
Author: Thomas Faber <thomas.faber(a)reactos.org>
AuthorDate: Fri Apr 24 14:56:26 2020 +0200
Commit: Thomas Faber <thomas.faber(a)reactos.org>
CommitDate: Fri Apr 24 14:56:26 2020 +0200
[WINDOWSCODECS] Use upstream Wine fix for 4bps BGRA TIFF. CORE-16796
Import Wine commits by Dmitry Timoshkov:
* 0cd8502b49 windowscodecs: Add support for 4bps RGBA format to TIFF decoder.
* 962bb99352 windowscodecs/tests: Add a separate test for 4bps BGRA TIFF format.
---
dll/win32/windowscodecs/tiffformat.c | 60 ++++++------
.../rostests/winetests/windowscodecs/tiffformat.c | 104 +++++++++++++++++++++
2 files changed, 132 insertions(+), 32 deletions(-)
diff --git a/dll/win32/windowscodecs/tiffformat.c b/dll/win32/windowscodecs/tiffformat.c
index e7141fc3e23..b3d32eec611 100644
--- a/dll/win32/windowscodecs/tiffformat.c
+++ b/dll/win32/windowscodecs/tiffformat.c
@@ -1148,48 +1148,44 @@ static HRESULT TiffFrameDecode_ReadTile(TiffFrameDecode *This,
UINT tile_x, UINT
HeapFree(GetProcessHeap(), 0, srcdata);
}
- /* 4bpp RGBA */
+ /* 4bps RGBA */
else if (This->decode_info.source_bpp == 4 && This->decode_info.samples
== 4 && This->decode_info.bpp == 32)
{
- BYTE *src, *dst;
- DWORD count;
+ BYTE *srcdata, *src, *dst;
+ DWORD x, y, count, width_bytes = (This->decode_info.tile_width * 3 + 7) / 8;
- /* 1 source byte expands to 2 BGRA samples */
- count = (This->decode_info.tile_width * This->decode_info.tile_height + 1)
/ 2;
+ count = width_bytes * This->decode_info.tile_height;
- src = This->cached_tile + count - 1;
- dst = This->cached_tile + This->decode_info.tile_size;
+ srcdata = HeapAlloc(GetProcessHeap(), 0, count);
+ if (!srcdata) return E_OUTOFMEMORY;
+ memcpy(srcdata, This->cached_tile, count);
- while (count--)
+ for (y = 0; y < This->decode_info.tile_height; y++)
{
- BYTE b = *src--;
+ src = srcdata + y * width_bytes;
+ dst = This->cached_tile + y * This->decode_info.tile_width * 4;
-#ifdef __REACTOS__
- dst -= 4;
- dst[2] = (b & 0x08) ? 0xff : 0; /* R */
- dst[1] = (b & 0x04) ? 0xff : 0; /* G */
- dst[0] = (b & 0x02) ? 0xff : 0; /* B */
- dst[3] = (b & 0x01) ? 0xff : 0; /* A */
- if (count || This->decode_info.tile_width % 2 == 0)
+ /* 1 source byte expands to 2 BGRA samples */
+
+ for (x = 0; x < This->decode_info.tile_width; x += 2)
{
- dst -= 4;
- dst[2] = (b & 0x80) ? 0xff : 0; /* R */
- dst[1] = (b & 0x40) ? 0xff : 0; /* G */
- dst[0] = (b & 0x20) ? 0xff : 0; /* B */
- dst[3] = (b & 0x10) ? 0xff : 0; /* A */
+ dst[0] = (src[0] & 0x20) ? 0xff : 0; /* B */
+ dst[1] = (src[0] & 0x40) ? 0xff : 0; /* G */
+ dst[2] = (src[0] & 0x80) ? 0xff : 0; /* R */
+ dst[3] = (src[0] & 0x10) ? 0xff : 0; /* A */
+ if (x + 1 < This->decode_info.tile_width)
+ {
+ dst[4] = (src[0] & 0x02) ? 0xff : 0; /* B */
+ dst[5] = (src[0] & 0x04) ? 0xff : 0; /* G */
+ dst[6] = (src[0] & 0x08) ? 0xff : 0; /* R */
+ dst[7] = (src[0] & 0x01) ? 0xff : 0; /* A */
+ }
+ src++;
+ dst += 8;
}
-#else
- dst -= 8;
- dst[2] = (b & 0x80) ? 0xff : 0; /* R */
- dst[1] = (b & 0x40) ? 0xff : 0; /* G */
- dst[0] = (b & 0x20) ? 0xff : 0; /* B */
- dst[3] = (b & 0x10) ? 0xff : 0; /* A */
- dst[6] = (b & 0x08) ? 0xff : 0; /* R */
- dst[5] = (b & 0x04) ? 0xff : 0; /* G */
- dst[4] = (b & 0x02) ? 0xff : 0; /* B */
- dst[7] = (b & 0x01) ? 0xff : 0; /* A */
-#endif
}
+
+ HeapFree(GetProcessHeap(), 0, srcdata);
}
/* 16bpp RGBA */
else if (This->decode_info.source_bpp == 16 &&
This->decode_info.samples == 4 && This->decode_info.bpp == 32)
diff --git a/modules/rostests/winetests/windowscodecs/tiffformat.c
b/modules/rostests/winetests/windowscodecs/tiffformat.c
index 8cdc0047a21..0c68904abad 100644
--- a/modules/rostests/winetests/windowscodecs/tiffformat.c
+++ b/modules/rostests/winetests/windowscodecs/tiffformat.c
@@ -302,6 +302,47 @@ static const struct tiff_24bpp_data
{ 900, 3 },
{ 0x11, 0x22, 0x33 }
};
+
+static const struct tiff_4bps_bgra
+{
+ USHORT byte_order;
+ USHORT version;
+ ULONG dir_offset;
+ USHORT number_of_entries;
+ struct IFD_entry entry[14];
+ ULONG next_IFD;
+ struct IFD_rational res;
+ BYTE pixel_data[4];
+} tiff_4bps_bgra =
+{
+#ifdef WORDS_BIGENDIAN
+ 'M' | 'M' << 8,
+#else
+ 'I' | 'I' << 8,
+#endif
+ 42,
+ FIELD_OFFSET(struct tiff_4bps_bgra, number_of_entries),
+ 14,
+ {
+ { 0xff, IFD_SHORT, 1, 0 }, /* SUBFILETYPE */
+ { 0x100, IFD_LONG, 1, 3 }, /* IMAGEWIDTH */
+ { 0x101, IFD_LONG, 1, 2 }, /* IMAGELENGTH */
+ { 0x102, IFD_SHORT, 1, 1 }, /* BITSPERSAMPLE */
+ { 0x103, IFD_SHORT, 1, 1 }, /* COMPRESSION */
+ { 0x106, IFD_SHORT, 1, 2 }, /* PHOTOMETRIC */
+ { 0x111, IFD_LONG, 1, FIELD_OFFSET(struct tiff_4bps_bgra, pixel_data) }, /*
STRIPOFFSETS */
+ { 0x115, IFD_SHORT, 1, 4 }, /* SAMPLESPERPIXEL */
+ { 0x116, IFD_LONG, 1, 2 }, /* ROWSPERSTRIP */
+ { 0x117, IFD_LONG, 1, 4 }, /* STRIPBYTECOUNT */
+ { 0x11a, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_4bps_bgra, res) }, /*
XRESOLUTION */
+ { 0x11b, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_4bps_bgra, res) }, /*
YRESOLUTION */
+ { 0x11c, IFD_SHORT, 1, 1 }, /* PLANARCONFIGURATION */
+ { 0x128, IFD_SHORT, 1, 2 } /* RESOLUTIONUNIT */
+ },
+ 0,
+ { 96, 1 },
+ { 0x12,0x30, 0x47,0xe0 }
+};
#include "poppack.h"
static IWICImagingFactory *factory;
@@ -1179,6 +1220,68 @@ static void test_color_formats(void)
}
}
+static void test_tiff_4bps_bgra(void)
+{
+ HRESULT hr;
+ IWICBitmapDecoder *decoder;
+ IWICBitmapFrameDecode *frame;
+ UINT frame_count, width, height, i;
+ double dpi_x, dpi_y;
+ IWICPalette *palette;
+ GUID format;
+ WICRect rc;
+ BYTE data[24];
+ static const BYTE expected_data[24] = { 0,0,0,0xff, 0xff,0,0,0, 0xff,0,0,0xff,
+ 0,0xff,0,0, 0xff,0xff,0,0xff,
0xff,0xff,0xff,0 };
+
+ hr = create_decoder(&tiff_4bps_bgra, sizeof(tiff_4bps_bgra), &decoder);
+ ok(hr == S_OK, "Failed to load TIFF image data %#x\n", hr);
+ if (hr != S_OK) return;
+
+ hr = IWICBitmapDecoder_GetFrameCount(decoder, &frame_count);
+ ok(hr == S_OK, "GetFrameCount error %#x\n", hr);
+ ok(frame_count == 1, "expected 1, got %u\n", frame_count);
+
+ hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
+ ok(hr == S_OK, "GetFrame error %#x\n", hr);
+
+ hr = IWICBitmapFrameDecode_GetSize(frame, &width, &height);
+ ok(hr == S_OK, "GetSize error %#x\n", hr);
+ ok(width == 3, "got %u\n", width);
+ ok(height == 2, "got %u\n", height);
+
+ hr = IWICBitmapFrameDecode_GetResolution(frame, &dpi_x, &dpi_y);
+ ok(hr == S_OK, "GetResolution error %#x\n", hr);
+ ok(dpi_x == 96.0, "expected 96.0, got %f\n", dpi_x);
+ ok(dpi_y == 96.0, "expected 96.0, got %f\n", dpi_y);
+
+ hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &format);
+ ok(hr == S_OK, "GetPixelFormat error %#x\n", hr);
+ ok(IsEqualGUID(&format, &GUID_WICPixelFormat32bppBGRA),
+ "got wrong format %s\n", wine_dbgstr_guid(&format));
+
+ hr = IWICImagingFactory_CreatePalette(factory, &palette);
+ ok(hr == S_OK, "CreatePalette error %#x\n", hr);
+ hr = IWICBitmapFrameDecode_CopyPalette(frame, palette);
+ ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE,
+ "expected WINCODEC_ERR_PALETTEUNAVAILABLE, got %#x\n", hr);
+ IWICPalette_Release(palette);
+
+ memset(data, 0xaa, sizeof(data));
+ rc.X = 0;
+ rc.Y = 0;
+ rc.Width = 3;
+ rc.Height = 2;
+ hr = IWICBitmapFrameDecode_CopyPixels(frame, &rc, 12, sizeof(data), data);
+ ok(hr == S_OK, "CopyPixels error %#x\n", hr);
+
+ for (i = 0; i < sizeof(data); i++)
+ ok(data[i] == expected_data[i], "%u: expected %02x, got %02x\n", i,
expected_data[i], data[i]);
+
+ IWICBitmapFrameDecode_Release(frame);
+ IWICBitmapDecoder_Release(decoder);
+}
+
START_TEST(tiffformat)
{
HRESULT hr;
@@ -1190,6 +1293,7 @@ START_TEST(tiffformat)
ok(hr == S_OK, "CoCreateInstance error %#x\n", hr);
if (FAILED(hr)) return;
+ test_tiff_4bps_bgra();
test_color_formats();
test_tiff_1bpp_palette();
test_tiff_8bpp_palette();