From d57b87c0f3d129e0d1baf8a848ad4f4ad8165219 Mon Sep 17 00:00:00 2001 From: Dmitry Timoshkov Date: Mon, 13 Jul 2015 14:46:41 +0800 Subject: [PATCH] windowscodecs: Add support for 8bpp grayscale TIFF with 8bpp alpha. --- dlls/windowscodecs/tests/tiffformat.c | 103 ++++++++++++++++++++++++++ dlls/windowscodecs/tiffformat.c | 66 +++++++++++++++-- 2 files changed, 164 insertions(+), 5 deletions(-) diff --git a/dlls/windowscodecs/tests/tiffformat.c b/dlls/windowscodecs/tests/tiffformat.c index cc1951e2d47..d07caa336a6 100644 --- a/dlls/windowscodecs/tests/tiffformat.c +++ b/dlls/windowscodecs/tests/tiffformat.c @@ -92,6 +92,48 @@ static const struct tiff_1bpp_data { 900, 3 }, { 0x11, 0x22, 0x33, 0 } }; + +static const struct tiff_8bpp_alpha +{ + USHORT byte_order; + USHORT version; + ULONG dir_offset; + USHORT number_of_entries; + struct IFD_entry entry[15]; + ULONG next_IFD; + struct IFD_rational res; + BYTE pixel_data[8]; +} tiff_8bpp_alpha = +{ +#ifdef WORDS_BIGENDIAN + 'M' | 'M' << 8, +#else + 'I' | 'I' << 8, +#endif + 42, + FIELD_OFFSET(struct tiff_8bpp_alpha, number_of_entries), + 15, + { + { 0xff, IFD_SHORT, 1, 0 }, /* SUBFILETYPE */ + { 0x100, IFD_LONG, 1, 2 }, /* IMAGEWIDTH */ + { 0x101, IFD_LONG, 1, 2 }, /* IMAGELENGTH */ + { 0x102, IFD_SHORT, 2, MAKELONG(8, 8) }, /* BITSPERSAMPLE */ + { 0x103, IFD_SHORT, 1, 1 }, /* COMPRESSION: XP doesn't accept IFD_LONG here */ + { 0x106, IFD_SHORT, 1, 1 }, /* PHOTOMETRIC */ + { 0x111, IFD_LONG, 1, FIELD_OFFSET(struct tiff_8bpp_alpha, pixel_data) }, /* STRIPOFFSETS */ + { 0x115, IFD_SHORT, 1, 2 }, /* SAMPLESPERPIXEL */ + { 0x116, IFD_LONG, 1, 2 }, /* ROWSPERSTRIP */ + { 0x117, IFD_LONG, 1, 8 }, /* STRIPBYTECOUNT */ + { 0x11a, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_8bpp_alpha, res) }, + { 0x11b, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_8bpp_alpha, res) }, + { 0x11c, IFD_SHORT, 1, 1 }, /* PLANARCONFIGURATION */ + { 0x128, IFD_SHORT, 1, 2 }, /* RESOLUTIONUNIT */ + { 0x152, IFD_SHORT, 1, 1 } /* EXTRASAMPLES: 1 - Associated alpha with pre-multiplied color */ + }, + 0, + { 96, 1 }, + { 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88 } +}; #include "poppack.h" static IWICImagingFactory *factory; @@ -264,6 +306,66 @@ todo_wine IStream_Release(stream); } +static void test_tiff_8bpp_alpha(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[16]; + static const BYTE expected_data[16] = { 0x11,0x11,0x11,0x22,0x33,0x33,0x33,0x44, + 0x55,0x55,0x55,0x66,0x77,0x77,0x77,0x88 }; + + decoder = create_decoder(&tiff_8bpp_alpha, sizeof(tiff_8bpp_alpha)); + ok(decoder != 0, "Failed to load TIFF image data\n"); + + 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 == 2, "expected 2, got %u\n", width); + ok(height == 2, "expected 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_WICPixelFormat32bppPBGRA), + "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); + + rc.X = 0; + rc.Y = 0; + rc.Width = 2; + rc.Height = 2; + hr = IWICBitmapFrameDecode_CopyPixels(frame, &rc, 8, 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; @@ -277,6 +379,7 @@ START_TEST(tiffformat) test_tiff_palette(); test_QueryCapability(); + test_tiff_8bpp_alpha(); IWICImagingFactory_Release(factory); CoUninitialize(); diff --git a/dlls/windowscodecs/tiffformat.c b/dlls/windowscodecs/tiffformat.c index 7f987de0d3b..51e940f65ce 100644 --- a/dlls/windowscodecs/tiffformat.c +++ b/dlls/windowscodecs/tiffformat.c @@ -236,7 +236,7 @@ typedef struct { const WICPixelFormatGUID *format; int bps; int samples; - int bpp; + int bpp, source_bpp; int planar; int indexed; int reverse_bgr; @@ -326,23 +326,63 @@ static HRESULT tiff_get_decode_info(TIFF *tiff, tiff_decode_info *decode_info) decode_info->invert_grayscale = 1; /* fall through */ case 1: /* BlackIsZero */ - if (samples != 1) + if (samples == 2) { - FIXME("unhandled grayscale sample count %u\n", samples); + ret = pTIFFGetField(tiff, TIFFTAG_EXTRASAMPLES, &extra_sample_count, &extra_samples); + if (!ret) + { + extra_sample_count = 1; + extra_sample = 0; + extra_samples = &extra_sample; + } + } + else if (samples != 1) + { + FIXME("unhandled %dbpp sample count %u\n", bps, samples); return E_FAIL; } - decode_info->bpp = bps; + decode_info->bpp = bps * samples; + decode_info->source_bpp = decode_info->bpp; switch (bps) { case 1: + if (samples != 1) + { + FIXME("unhandled 1bpp sample count %u\n", samples); + return E_FAIL; + } decode_info->format = &GUID_WICPixelFormatBlackWhite; break; case 4: + if (samples != 1) + { + FIXME("unhandled 4bpp grayscale sample count %u\n", samples); + return E_FAIL; + } decode_info->format = &GUID_WICPixelFormat4bppGray; break; case 8: - decode_info->format = &GUID_WICPixelFormat8bppGray; + if (samples == 1) + decode_info->format = &GUID_WICPixelFormat8bppGray; + else + { + decode_info->bpp = 32; + + switch(extra_samples[0]) + { + case 1: /* Associated (pre-multiplied) alpha data */ + decode_info->format = &GUID_WICPixelFormat32bppPBGRA; + break; + case 0: /* Unspecified data */ + case 2: /* Unassociated alpha data */ + decode_info->format = &GUID_WICPixelFormat32bppBGRA; + break; + default: + FIXME("unhandled extra sample type %u\n", extra_samples[0]); + return E_FAIL; + } + } break; default: FIXME("unhandled greyscale bit count %u\n", bps); @@ -943,6 +983,22 @@ static HRESULT TiffFrameDecode_ReadTile(TiffFrameDecode *This, UINT tile_x, UINT hr = E_FAIL; } + /* 8bpp grayscale with extra alpha */ + if (hr == S_OK && This->decode_info.source_bpp == 16 && This->decode_info.samples == 2 && This->decode_info.bpp == 32) + { + BYTE *src; + DWORD *dst, count = This->decode_info.tile_width * This->decode_info.tile_height; + + src = This->cached_tile + This->decode_info.tile_width * This->decode_info.tile_height * 2 - 2; + dst = (DWORD *)(This->cached_tile + This->decode_info.tile_size - 4); + + while (count--) + { + *dst-- = src[0] | (src[0] << 8) | (src[0] << 16) | (src[1] << 24); + src -= 2; + } + } + if (hr == S_OK && This->decode_info.reverse_bgr) { if (This->decode_info.bps == 8)