1
0
mirror of https://github.com/microsoft/DirectXTex synced 2024-12-27 11:50:13 +00:00

texassemble: Fixed AnimatedGif handling with transparency

This commit is contained in:
Chuck Walbourn 2020-07-01 01:19:51 -07:00
parent 8a0fa55b62
commit 58164bbaba

View File

@ -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; using namespace DirectX::PackedVector;
@ -621,18 +621,12 @@ namespace
{ {
auto srcPtr = reinterpret_cast<uint32_t*>(rawPtr); auto srcPtr = reinterpret_cast<uint32_t*>(rawPtr);
auto destPtr = reinterpret_cast<uint32_t*>(composedPtr); auto destPtr = reinterpret_cast<uint32_t*>(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<const XMUBYTEN4*>(srcPtr++)); if (transparent == *srcPtr)
XMVECTOR b = XMLoadUByteN4(reinterpret_cast<const XMUBYTEN4*>(destPtr)); continue;
XMVECTOR alpha = XMVectorSplatW(a); *destPtr = *srcPtr;
XMVECTOR blended = XMVectorMultiply(a, alpha) + XMVectorMultiply(b, XMVectorSubtract(g_XMOne, alpha));
blended = XMVectorSelect(g_XMIdentityR3, blended, g_XMSelect1110);
XMStoreUByteN4(reinterpret_cast<XMUBYTEN4*>(destPtr++), blended);
} }
rawPtr += raw.rowPitch; rawPtr += raw.rowPitch;
@ -677,6 +671,24 @@ namespace
PROPVARIANT propValue; PROPVARIANT propValue;
PropVariantInit(&propValue); PropVariantInit(&propValue);
// Get palette
WICColor rgbColors[256] = {};
UINT actualColors = 0;
{
ComPtr<IWICPalette> 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 // Get background color
UINT bgColor = 0; UINT bgColor = 0;
if (usebgcolor) if (usebgcolor)
@ -697,24 +709,9 @@ namespace
{ {
uint8_t index = propValue.bVal; uint8_t index = propValue.bVal;
ComPtr<IWICPalette> 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) if (index < actualColors)
{ {
bgColor = rgColors[index]; bgColor = rgbColors[index];
} }
} }
PropVariantClear(&propValue); PropVariantClear(&propValue);
@ -758,6 +755,8 @@ namespace
UINT previousFrame = 0; UINT previousFrame = 0;
for (UINT iframe = 0; iframe < fcount; ++iframe) for (UINT iframe = 0; iframe < fcount; ++iframe)
{ {
int transparentIndex = -1;
std::unique_ptr<ScratchImage> frameImage(new (std::nothrow) ScratchImage); std::unique_ptr<ScratchImage> frameImage(new (std::nothrow) ScratchImage);
if (!frameImage) if (!frameImage)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
@ -864,6 +863,27 @@ namespace
} }
PropVariantClear(&propValue); 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<int>(propValue.uiVal);
}
}
}
PropVariantClear(&propValue);
}
} }
UINT w, h; UINT w, h;
@ -891,17 +911,16 @@ namespace
if (FAILED(hr)) if (FAILED(hr))
return hr; return hr;
if (!iframe) if (!iframe || transparentIndex == -1)
{ {
Rect fullRect(0, 0, img->width, img->height); Rect fullRect(0, 0, img->width, img->height);
hr = CopyRectangle(*img, fullRect, *composedImage, TEX_FILTER_DEFAULT, size_t(rct.left), size_t(rct.top)); hr = CopyRectangle(*img, fullRect, *composedImage, TEX_FILTER_DEFAULT, size_t(rct.left), size_t(rct.top));
if (FAILED(hr)) if (FAILED(hr))
return hr; return hr;
} }
else else
{ {
BlendRectangle(*composedImage, *img, rct); BlendRectangle(*composedImage, *img, rct, rgbColors[transparentIndex]);
} }
if (disposal == DM_UNDEFINED || disposal == DM_NONE) if (disposal == DM_UNDEFINED || disposal == DM_NONE)