From 58164bbabaa585de3c3f9f66213938512e669847 Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Wed, 1 Jul 2020 01:19:51 -0700 Subject: [PATCH] texassemble: Fixed AnimatedGif handling with transparency --- Texassemble/texassemble.cpp | 79 +++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 30 deletions(-) diff --git a/Texassemble/texassemble.cpp b/Texassemble/texassemble.cpp index 10231f3..e5ad450 100644 --- a/Texassemble/texassemble.cpp +++ b/Texassemble/texassemble.cpp @@ -602,7 +602,7 @@ namespace } - void BlendRectangle(const Image& composed, const Image& raw, const RECT& destRect) + void BlendRectangle(const Image& composed, const Image& raw, const RECT& destRect, uint32_t transparent) { using namespace DirectX::PackedVector; @@ -621,18 +621,12 @@ namespace { auto srcPtr = reinterpret_cast(rawPtr); auto destPtr = reinterpret_cast(composedPtr); - for (long x = clipped.left; x < clipped.right; ++x) + for (long x = clipped.left; x < clipped.right; ++x, ++srcPtr, ++destPtr) { - XMVECTOR a = XMLoadUByteN4(reinterpret_cast(srcPtr++)); - XMVECTOR b = XMLoadUByteN4(reinterpret_cast(destPtr)); + if (transparent == *srcPtr) + continue; - XMVECTOR alpha = XMVectorSplatW(a); - - XMVECTOR blended = XMVectorMultiply(a, alpha) + XMVectorMultiply(b, XMVectorSubtract(g_XMOne, alpha)); - - blended = XMVectorSelect(g_XMIdentityR3, blended, g_XMSelect1110); - - XMStoreUByteN4(reinterpret_cast(destPtr++), blended); + *destPtr = *srcPtr; } rawPtr += raw.rowPitch; @@ -677,6 +671,24 @@ namespace PROPVARIANT propValue; PropVariantInit(&propValue); + // Get palette + WICColor rgbColors[256] = {}; + UINT actualColors = 0; + { + ComPtr palette; + hr = pWIC->CreatePalette(palette.GetAddressOf()); + if (FAILED(hr)) + return hr; + + hr = decoder->CopyPalette(palette.Get()); + if (FAILED(hr)) + return hr; + + hr = palette->GetColors(_countof(rgbColors), rgbColors, &actualColors); + if (FAILED(hr)) + return hr; + } + // Get background color UINT bgColor = 0; if (usebgcolor) @@ -697,24 +709,9 @@ namespace { uint8_t index = propValue.bVal; - ComPtr palette; - hr = pWIC->CreatePalette(palette.GetAddressOf()); - if (FAILED(hr)) - return hr; - - hr = decoder->CopyPalette(palette.Get()); - if (FAILED(hr)) - return hr; - - WICColor rgColors[256]; - UINT actualColors = 0; - hr = palette->GetColors(_countof(rgColors), rgColors, &actualColors); - if (FAILED(hr)) - return hr; - if (index < actualColors) { - bgColor = rgColors[index]; + bgColor = rgbColors[index]; } } PropVariantClear(&propValue); @@ -758,6 +755,8 @@ namespace UINT previousFrame = 0; for (UINT iframe = 0; iframe < fcount; ++iframe) { + int transparentIndex = -1; + std::unique_ptr frameImage(new (std::nothrow) ScratchImage); if (!frameImage) return E_OUTOFMEMORY; @@ -864,6 +863,27 @@ namespace } PropVariantClear(&propValue); } + + hr = frameMeta->GetMetadataByName(L"/grctlext/TransparencyFlag", &propValue); + if (SUCCEEDED(hr)) + { + hr = (propValue.vt == VT_BOOL ? S_OK : E_FAIL); + if (SUCCEEDED(hr) && propValue.boolVal) + { + PropVariantClear(&propValue); + hr = frameMeta->GetMetadataByName(L"/grctlext/TransparentColorIndex", &propValue); + if (SUCCEEDED(hr)) + { + hr = (propValue.vt == VT_UI1 ? S_OK : E_FAIL); + if (SUCCEEDED(hr) && propValue.uiVal < actualColors) + { + transparentIndex = static_cast(propValue.uiVal); + } + } + } + PropVariantClear(&propValue); + } + } UINT w, h; @@ -891,17 +911,16 @@ namespace if (FAILED(hr)) return hr; - if (!iframe) + if (!iframe || transparentIndex == -1) { Rect fullRect(0, 0, img->width, img->height); - hr = CopyRectangle(*img, fullRect, *composedImage, TEX_FILTER_DEFAULT, size_t(rct.left), size_t(rct.top)); if (FAILED(hr)) return hr; } else { - BlendRectangle(*composedImage, *img, rct); + BlendRectangle(*composedImage, *img, rct, rgbColors[transparentIndex]); } if (disposal == DM_UNDEFINED || disposal == DM_NONE)