From 7bda0c3a57271c48f19eebd18c0d945dad6aa3dc Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Thu, 3 Oct 2019 14:58:14 -0700 Subject: [PATCH] Return TEX_ALPHA_MODE_OPAQUE metadata if the reader knows it returned opaque alpha (#150) --- DirectXTex/DirectXTexDDS.cpp | 13 ++- DirectXTex/DirectXTexHDR.cpp | 1 + DirectXTex/DirectXTexTGA.cpp | 164 +++++++++++++++++++++++++---------- DirectXTex/DirectXTexWIC.cpp | 93 +++++++++++--------- 4 files changed, 178 insertions(+), 93 deletions(-) diff --git a/DirectXTex/DirectXTexDDS.cpp b/DirectXTex/DirectXTexDDS.cpp index 506308d..fc250b8 100644 --- a/DirectXTex/DirectXTexDDS.cpp +++ b/DirectXTex/DirectXTexDDS.cpp @@ -427,9 +427,6 @@ namespace if (metadata.format == DXGI_FORMAT_UNKNOWN) return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); - if (convFlags & CONV_FLAGS_PMALPHA) - metadata.miscFlags2 |= TEX_ALPHA_MODE_PREMULTIPLIED; - // Special flag for handling LUMINANCE legacy formats if (flags & DDS_FLAGS_EXPAND_LUMINANCE) { @@ -515,6 +512,16 @@ namespace } } + // Implicit alpha mode + if (convFlags & CONV_FLAGS_NOALPHA) + { + metadata.SetAlphaMode(TEX_ALPHA_MODE_OPAQUE); + } + else if (convFlags & CONV_FLAGS_PMALPHA) + { + metadata.SetAlphaMode(TEX_ALPHA_MODE_PREMULTIPLIED); + } + return S_OK; } } diff --git a/DirectXTex/DirectXTexHDR.cpp b/DirectXTex/DirectXTexHDR.cpp index 0437f25..9e8a6a3 100644 --- a/DirectXTex/DirectXTexHDR.cpp +++ b/DirectXTex/DirectXTexHDR.cpp @@ -282,6 +282,7 @@ namespace metadata.depth = metadata.arraySize = metadata.mipLevels = 1; metadata.format = DXGI_FORMAT_R32G32B32A32_FLOAT; metadata.dimension = TEX_DIMENSION_TEXTURE2D; + metadata.SetAlphaMode(TEX_ALPHA_MODE_OPAQUE); return S_OK; } diff --git a/DirectXTex/DirectXTexTGA.cpp b/DirectXTex/DirectXTexTGA.cpp index 44a6306..7ecad79 100644 --- a/DirectXTex/DirectXTexTGA.cpp +++ b/DirectXTex/DirectXTexTGA.cpp @@ -159,6 +159,7 @@ namespace case 24: metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM; + metadata.SetAlphaMode(TEX_ALPHA_MODE_OPAQUE); if (convFlags) *convFlags |= CONV_FLAGS_EXPAND; // We could use DXGI_FORMAT_B8G8R8X8_UNORM, but we prefer DXGI 1.0 formats @@ -280,6 +281,8 @@ namespace auto sPtr = static_cast(pSource); const uint8_t* endPtr = sPtr + size; + bool opaquealpha = false; + switch (image->format) { //--------------------------------------------------------------------------- 8-bit @@ -349,7 +352,9 @@ namespace //-------------------------------------------------------------------------- 16-bit case DXGI_FORMAT_B5G5R5A1_UNORM: { - bool nonzeroa = false; + uint32_t minalpha = 255; + uint32_t maxalpha = 0; + for (size_t y = 0; y < image->height; ++y) { size_t offset = ((convFlags & CONV_FLAGS_INVERTX) ? (image->width - 1) : 0); @@ -374,8 +379,11 @@ namespace return E_FAIL; auto t = static_cast(uint32_t(*sPtr) | uint32_t(*(sPtr + 1u) << 8)); - if (t & 0x8000) - nonzeroa = true; + + uint32_t alpha = (t & 0x8000) ? 255 : 0; + minalpha = std::min(minalpha, alpha); + maxalpha = std::max(maxalpha, alpha); + sPtr += 2; for (; j > 0; --j, ++x) @@ -406,8 +414,11 @@ namespace return E_FAIL; auto t = static_cast(uint32_t(*sPtr) | uint32_t(*(sPtr + 1u) << 8)); - if (t & 0x8000) - nonzeroa = true; + + uint32_t alpha = (t & 0x8000) ? 255 : 0; + minalpha = std::min(minalpha, alpha); + maxalpha = std::max(maxalpha, alpha); + sPtr += 2; *dPtr = t; @@ -421,19 +432,26 @@ namespace } // If there are no non-zero alpha channel entries, we'll assume alpha is not used and force it to opaque - if (!nonzeroa) + if (maxalpha == 0) { + opaquealpha = true; HRESULT hr = SetAlphaChannelToOpaque(image); if (FAILED(hr)) return hr; } + else if (minalpha == 255) + { + opaquealpha = true; + } } break; //----------------------------------------------------------------------- 24/32-bit case DXGI_FORMAT_R8G8B8A8_UNORM: { - bool nonzeroa = false; + uint32_t minalpha = 255; + uint32_t maxalpha = 0; + for (size_t y = 0; y < image->height; ++y) { size_t offset = ((convFlags & CONV_FLAGS_INVERTX) ? (image->width - 1) : 0); @@ -465,7 +483,7 @@ namespace t = uint32_t(*sPtr << 16) | uint32_t(*(sPtr + 1) << 8) | uint32_t(*(sPtr + 2)) | 0xFF000000; sPtr += 3; - nonzeroa = true; + minalpha = maxalpha = 255; } else { @@ -475,10 +493,11 @@ namespace return E_FAIL; // BGRA -> RGBA - t = uint32_t(*sPtr << 16) | uint32_t(*(sPtr + 1) << 8) | uint32_t(*(sPtr + 2)) | uint32_t(*(sPtr + 3) << 24); + uint32_t alpha = *(sPtr + 3); + t = uint32_t(*sPtr << 16) | uint32_t(*(sPtr + 1) << 8) | uint32_t(*(sPtr + 2)) | uint32_t(alpha << 24); - if (*(sPtr + 3) > 0) - nonzeroa = true; + minalpha = std::min(minalpha, alpha); + maxalpha = std::max(maxalpha, alpha); sPtr += 4; } @@ -529,7 +548,7 @@ namespace *dPtr = uint32_t(*sPtr << 16) | uint32_t(*(sPtr + 1) << 8) | uint32_t(*(sPtr + 2)) | 0xFF000000; sPtr += 3; - nonzeroa = true; + minalpha = maxalpha = 255; } else { @@ -539,10 +558,11 @@ namespace return E_FAIL; // BGRA -> RGBA - *dPtr = uint32_t(*sPtr << 16) | uint32_t(*(sPtr + 1) << 8) | uint32_t(*(sPtr + 2)) | uint32_t(*(sPtr + 3) << 24); + uint32_t alpha = *(sPtr + 3); + *dPtr = uint32_t(*sPtr << 16) | uint32_t(*(sPtr + 1) << 8) | uint32_t(*(sPtr + 2)) | uint32_t(alpha << 24); - if (*(sPtr + 3) > 0) - nonzeroa = true; + minalpha = std::min(minalpha, alpha); + maxalpha = std::max(maxalpha, alpha); sPtr += 4; } @@ -557,12 +577,17 @@ namespace } // If there are no non-zero alpha channel entries, we'll assume alpha is not used and force it to opaque - if (!nonzeroa) + if (maxalpha == 0) { + opaquealpha = true; HRESULT hr = SetAlphaChannelToOpaque(image); if (FAILED(hr)) return hr; } + else if (minalpha == 255) + { + opaquealpha = true; + } } break; @@ -571,7 +596,7 @@ namespace return E_FAIL; } - return S_OK; + return opaquealpha ? S_FALSE : S_OK; } @@ -606,6 +631,8 @@ namespace auto sPtr = static_cast(pSource); const uint8_t* endPtr = sPtr + size; + bool opaquealpha = false; + switch (image->format) { //--------------------------------------------------------------------------- 8-bit @@ -637,7 +664,9 @@ namespace //-------------------------------------------------------------------------- 16-bit case DXGI_FORMAT_B5G5R5A1_UNORM: { - bool nonzeroa = false; + uint32_t minalpha = 255; + uint32_t maxalpha = 0; + for (size_t y = 0; y < image->height; ++y) { size_t offset = ((convFlags & CONV_FLAGS_INVERTX) ? (image->width - 1) : 0); @@ -656,8 +685,9 @@ namespace sPtr += 2; *dPtr = t; - if (t & 0x8000) - nonzeroa = true; + uint32_t alpha = (t & 0x8000) ? 255 : 0; + minalpha = std::min(minalpha, alpha); + maxalpha = std::max(maxalpha, alpha); if (convFlags & CONV_FLAGS_INVERTX) --dPtr; @@ -667,19 +697,26 @@ namespace } // If there are no non-zero alpha channel entries, we'll assume alpha is not used and force it to opaque - if (!nonzeroa) + if (maxalpha == 0) { + opaquealpha = true; HRESULT hr = SetAlphaChannelToOpaque(image); if (FAILED(hr)) return hr; } + else if (minalpha == 255) + { + opaquealpha = true; + } } break; //----------------------------------------------------------------------- 24/32-bit case DXGI_FORMAT_R8G8B8A8_UNORM: { - bool nonzeroa = false; + uint32_t minalpha = 255; + uint32_t maxalpha = 0; + for (size_t y = 0; y < image->height; ++y) { size_t offset = ((convFlags & CONV_FLAGS_INVERTX) ? (image->width - 1) : 0); @@ -701,7 +738,7 @@ namespace *dPtr = uint32_t(*sPtr << 16) | uint32_t(*(sPtr + 1) << 8) | uint32_t(*(sPtr + 2)) | 0xFF000000; sPtr += 3; - nonzeroa = true; + minalpha = maxalpha = 255; } else { @@ -711,10 +748,11 @@ namespace return E_FAIL; // BGRA -> RGBA - *dPtr = uint32_t(*sPtr << 16) | uint32_t(*(sPtr + 1) << 8) | uint32_t(*(sPtr + 2)) | uint32_t(*(sPtr + 3) << 24); + uint32_t alpha = *(sPtr + 3); + *dPtr = uint32_t(*sPtr << 16) | uint32_t(*(sPtr + 1) << 8) | uint32_t(*(sPtr + 2)) | uint32_t(alpha << 24); - if (*(sPtr + 3) > 0) - nonzeroa = true; + minalpha = std::min(minalpha, alpha); + maxalpha = std::max(maxalpha, alpha); sPtr += 4; } @@ -727,12 +765,17 @@ namespace } // If there are no non-zero alpha channel entries, we'll assume alpha is not used and force it to opaque - if (!nonzeroa) + if (maxalpha == 0) { + opaquealpha = true; HRESULT hr = SetAlphaChannelToOpaque(image); if (FAILED(hr)) return hr; } + else if (minalpha == 255) + { + opaquealpha = true; + } } break; @@ -741,7 +784,7 @@ namespace return E_FAIL; } - return S_OK; + return opaquealpha ? S_FALSE : S_OK; } @@ -965,7 +1008,13 @@ HRESULT DirectX::LoadFromTGAMemory( } if (metadata) + { memcpy(metadata, &mdata, sizeof(TexMetadata)); + if (hr == S_FALSE) + { + metadata->SetAlphaMode(TEX_ALPHA_MODE_OPAQUE); + } + } return S_OK; } @@ -1051,6 +1100,8 @@ HRESULT DirectX::LoadFromTGAFile( assert(image.GetPixels()); + bool opaquealpha = false; + if (!(convFlags & (CONV_FLAGS_RLE | CONV_FLAGS_EXPAND | CONV_FLAGS_INVERTX)) && (convFlags & CONV_FLAGS_INVERTY)) { // This case we can read directly into the image buffer in place @@ -1101,7 +1152,8 @@ HRESULT DirectX::LoadFromTGAFile( size_t rowPitch = img->rowPitch; // Scan for non-zero alpha channel - bool nonzeroa = false; + uint32_t minalpha = 255; + uint32_t maxalpha = 0; for (size_t h = 0; h < img->height; ++h) { @@ -1109,22 +1161,27 @@ HRESULT DirectX::LoadFromTGAFile( for (size_t x = 0; x < img->width; ++x) { - if ((*sPtr) & 0xff000000) - { - nonzeroa = true; - break; - } + uint32_t alpha = ((*sPtr & 0xFF000000) >> 24); + + minalpha = std::min(minalpha, alpha); + maxalpha = std::max(maxalpha, alpha); ++sPtr; } - if (nonzeroa) - break; - pPixels += rowPitch; } - DWORD tflags = (!nonzeroa) ? TEXP_SCANLINE_SETALPHA : TEXP_SCANLINE_NONE; + DWORD tflags = TEXP_SCANLINE_NONE; + if (maxalpha == 0) + { + opaquealpha = true; + tflags = TEXP_SCANLINE_SETALPHA; + } + else if (minalpha == 255) + { + opaquealpha = true; + } // Swizzle scanlines pPixels = img->pixels; @@ -1150,7 +1207,8 @@ HRESULT DirectX::LoadFromTGAFile( } // Scan for non-zero alpha channel - bool nonzeroa = false; + uint32_t minalpha = 255; + uint32_t maxalpha = 0; const uint8_t *pPixels = img->pixels; if (!pPixels) @@ -1167,24 +1225,21 @@ HRESULT DirectX::LoadFromTGAFile( for (size_t x = 0; x < img->width; ++x) { - if (*sPtr & 0x8000) - { - nonzeroa = true; - break; - } + uint32_t alpha = (*sPtr & 0x8000) ? 255 : 0; + + minalpha = std::min(minalpha, alpha); + maxalpha = std::max(maxalpha, alpha); ++sPtr; } - if (nonzeroa) - break; - pPixels += rowPitch; } // If there are no non-zero alpha channel entries, we'll assume alpha is not used and force it to opaque - if (!nonzeroa) + if (maxalpha == 0) { + opaquealpha = true; hr = SetAlphaChannelToOpaque(img); if (FAILED(hr)) { @@ -1192,6 +1247,10 @@ HRESULT DirectX::LoadFromTGAFile( return hr; } } + else if (minalpha == 255) + { + opaquealpha = true; + } } break; @@ -1234,10 +1293,19 @@ HRESULT DirectX::LoadFromTGAFile( image.Release(); return hr; } + + if (hr == S_FALSE) + opaquealpha = true; } if (metadata) + { memcpy(metadata, &mdata, sizeof(TexMetadata)); + if (opaquealpha) + { + metadata->SetAlphaMode(TEX_ALPHA_MODE_OPAQUE); + } + } return S_OK; } diff --git a/DirectXTex/DirectXTexWIC.cpp b/DirectXTex/DirectXTexWIC.cpp index 534122c..5c3b801 100644 --- a/DirectXTex/DirectXTexWIC.cpp +++ b/DirectXTex/DirectXTexWIC.cpp @@ -79,8 +79,9 @@ namespace struct WICConvert { - GUID source; - GUID target; + GUID source; + GUID target; + TEX_ALPHA_MODE alphaMode; }; const WICConvert g_WICConvert[] = @@ -88,54 +89,54 @@ namespace // Directly support the formats listed in XnaTexUtil::g_WICFormats, so no conversion required // Note target GUID in this conversion table must be one of those directly supported formats. - { GUID_WICPixelFormat1bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM - { GUID_WICPixelFormat2bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM - { GUID_WICPixelFormat4bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM - { GUID_WICPixelFormat8bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat1bppIndexed, GUID_WICPixelFormat32bppRGBA, TEX_ALPHA_MODE_UNKNOWN }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat2bppIndexed, GUID_WICPixelFormat32bppRGBA, TEX_ALPHA_MODE_UNKNOWN }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat4bppIndexed, GUID_WICPixelFormat32bppRGBA, TEX_ALPHA_MODE_UNKNOWN }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat8bppIndexed, GUID_WICPixelFormat32bppRGBA, TEX_ALPHA_MODE_UNKNOWN }, // DXGI_FORMAT_R8G8B8A8_UNORM - { GUID_WICPixelFormat2bppGray, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM - { GUID_WICPixelFormat4bppGray, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM + { GUID_WICPixelFormat2bppGray, GUID_WICPixelFormat8bppGray, TEX_ALPHA_MODE_UNKNOWN }, // DXGI_FORMAT_R8_UNORM + { GUID_WICPixelFormat4bppGray, GUID_WICPixelFormat8bppGray, TEX_ALPHA_MODE_UNKNOWN }, // DXGI_FORMAT_R8_UNORM - { GUID_WICPixelFormat16bppGrayFixedPoint, GUID_WICPixelFormat16bppGrayHalf }, // DXGI_FORMAT_R16_FLOAT - { GUID_WICPixelFormat32bppGrayFixedPoint, GUID_WICPixelFormat32bppGrayFloat }, // DXGI_FORMAT_R32_FLOAT + { GUID_WICPixelFormat16bppGrayFixedPoint, GUID_WICPixelFormat16bppGrayHalf, TEX_ALPHA_MODE_UNKNOWN }, // DXGI_FORMAT_R16_FLOAT + { GUID_WICPixelFormat32bppGrayFixedPoint, GUID_WICPixelFormat32bppGrayFloat, TEX_ALPHA_MODE_UNKNOWN }, // DXGI_FORMAT_R32_FLOAT - { GUID_WICPixelFormat16bppBGR555, GUID_WICPixelFormat16bppBGRA5551 }, // DXGI_FORMAT_B5G5R5A1_UNORM - { GUID_WICPixelFormat32bppBGR101010, GUID_WICPixelFormat32bppRGBA1010102 }, // DXGI_FORMAT_R10G10B10A2_UNORM + { GUID_WICPixelFormat16bppBGR555, GUID_WICPixelFormat16bppBGRA5551, TEX_ALPHA_MODE_OPAQUE }, // DXGI_FORMAT_B5G5R5A1_UNORM + { GUID_WICPixelFormat32bppBGR101010, GUID_WICPixelFormat32bppRGBA1010102, TEX_ALPHA_MODE_OPAQUE }, // DXGI_FORMAT_R10G10B10A2_UNORM - { GUID_WICPixelFormat24bppBGR, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM - { GUID_WICPixelFormat24bppRGB, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM - { GUID_WICPixelFormat32bppPBGRA, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM - { GUID_WICPixelFormat32bppPRGBA, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat24bppBGR, GUID_WICPixelFormat32bppRGBA, TEX_ALPHA_MODE_OPAQUE }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat24bppRGB, GUID_WICPixelFormat32bppRGBA, TEX_ALPHA_MODE_OPAQUE }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat32bppPBGRA, GUID_WICPixelFormat32bppRGBA, TEX_ALPHA_MODE_UNKNOWN }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat32bppPRGBA, GUID_WICPixelFormat32bppRGBA, TEX_ALPHA_MODE_UNKNOWN }, // DXGI_FORMAT_R8G8B8A8_UNORM - { GUID_WICPixelFormat48bppRGB, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM - { GUID_WICPixelFormat48bppBGR, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM - { GUID_WICPixelFormat64bppBGRA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM - { GUID_WICPixelFormat64bppPRGBA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM - { GUID_WICPixelFormat64bppPBGRA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat48bppRGB, GUID_WICPixelFormat64bppRGBA, TEX_ALPHA_MODE_OPAQUE }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat48bppBGR, GUID_WICPixelFormat64bppRGBA, TEX_ALPHA_MODE_OPAQUE }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat64bppBGRA, GUID_WICPixelFormat64bppRGBA, TEX_ALPHA_MODE_UNKNOWN }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat64bppPRGBA, GUID_WICPixelFormat64bppRGBA, TEX_ALPHA_MODE_UNKNOWN }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat64bppPBGRA, GUID_WICPixelFormat64bppRGBA, TEX_ALPHA_MODE_UNKNOWN }, // DXGI_FORMAT_R16G16B16A16_UNORM - { GUID_WICPixelFormat48bppRGBFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT - { GUID_WICPixelFormat48bppBGRFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT - { GUID_WICPixelFormat64bppRGBAFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT - { GUID_WICPixelFormat64bppBGRAFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT - { GUID_WICPixelFormat64bppRGBFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT - { GUID_WICPixelFormat64bppRGBHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT - { GUID_WICPixelFormat48bppRGBHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat48bppRGBFixedPoint, GUID_WICPixelFormat64bppRGBAHalf, TEX_ALPHA_MODE_OPAQUE }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat48bppBGRFixedPoint, GUID_WICPixelFormat64bppRGBAHalf, TEX_ALPHA_MODE_OPAQUE }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat64bppRGBAFixedPoint, GUID_WICPixelFormat64bppRGBAHalf, TEX_ALPHA_MODE_UNKNOWN }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat64bppBGRAFixedPoint, GUID_WICPixelFormat64bppRGBAHalf, TEX_ALPHA_MODE_UNKNOWN }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat64bppRGBFixedPoint, GUID_WICPixelFormat64bppRGBAHalf, TEX_ALPHA_MODE_OPAQUE }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat64bppRGBHalf, GUID_WICPixelFormat64bppRGBAHalf, TEX_ALPHA_MODE_OPAQUE }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat48bppRGBHalf, GUID_WICPixelFormat64bppRGBAHalf, TEX_ALPHA_MODE_OPAQUE }, // DXGI_FORMAT_R16G16B16A16_FLOAT - { GUID_WICPixelFormat128bppPRGBAFloat, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT - { GUID_WICPixelFormat128bppRGBFloat, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT - { GUID_WICPixelFormat128bppRGBAFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT - { GUID_WICPixelFormat128bppRGBFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT - { GUID_WICPixelFormat32bppRGBE, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT + { GUID_WICPixelFormat128bppPRGBAFloat, GUID_WICPixelFormat128bppRGBAFloat, TEX_ALPHA_MODE_UNKNOWN }, // DXGI_FORMAT_R32G32B32A32_FLOAT + { GUID_WICPixelFormat128bppRGBFloat, GUID_WICPixelFormat128bppRGBAFloat, TEX_ALPHA_MODE_OPAQUE }, // DXGI_FORMAT_R32G32B32A32_FLOAT + { GUID_WICPixelFormat128bppRGBAFixedPoint, GUID_WICPixelFormat128bppRGBAFloat, TEX_ALPHA_MODE_UNKNOWN }, // DXGI_FORMAT_R32G32B32A32_FLOAT + { GUID_WICPixelFormat128bppRGBFixedPoint, GUID_WICPixelFormat128bppRGBAFloat, TEX_ALPHA_MODE_OPAQUE }, // DXGI_FORMAT_R32G32B32A32_FLOAT + { GUID_WICPixelFormat32bppRGBE, GUID_WICPixelFormat128bppRGBAFloat, TEX_ALPHA_MODE_OPAQUE }, // DXGI_FORMAT_R32G32B32A32_FLOAT - { GUID_WICPixelFormat32bppCMYK, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM - { GUID_WICPixelFormat64bppCMYK, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM - { GUID_WICPixelFormat40bppCMYKAlpha, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM - { GUID_WICPixelFormat80bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat32bppCMYK, GUID_WICPixelFormat32bppRGBA, TEX_ALPHA_MODE_OPAQUE }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat64bppCMYK, GUID_WICPixelFormat64bppRGBA, TEX_ALPHA_MODE_OPAQUE }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat40bppCMYKAlpha, GUID_WICPixelFormat32bppRGBA, TEX_ALPHA_MODE_UNKNOWN }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat80bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA, TEX_ALPHA_MODE_UNKNOWN }, // DXGI_FORMAT_R16G16B16A16_UNORM #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE) - { GUID_WICPixelFormat32bppRGB, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM - { GUID_WICPixelFormat64bppRGB, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM - { GUID_WICPixelFormat64bppPRGBAHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat32bppRGB, GUID_WICPixelFormat32bppRGBA, TEX_ALPHA_MODE_OPAQUE }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat64bppRGB, GUID_WICPixelFormat64bppRGBA, TEX_ALPHA_MODE_OPAQUE }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat64bppPRGBAHalf, GUID_WICPixelFormat64bppRGBAHalf, TEX_ALPHA_MODE_UNKNOWN }, // DXGI_FORMAT_R16G16B16A16_FLOAT #endif // We don't support n-channel formats @@ -148,11 +149,14 @@ namespace _In_ const WICPixelFormatGUID& pixelFormat, DWORD flags, bool iswic2, - _Out_opt_ WICPixelFormatGUID* pConvert) + _Out_opt_ WICPixelFormatGUID* pConvert, + _Out_ TEX_ALPHA_MODE* alphaMode) { if (pConvert) memset(pConvert, 0, sizeof(WICPixelFormatGUID)); + *alphaMode = TEX_ALPHA_MODE_UNKNOWN; + DXGI_FORMAT format = _WICToDXGI(pixelFormat); if (format == DXGI_FORMAT_UNKNOWN) @@ -174,6 +178,7 @@ namespace if (pConvert) memcpy_s(pConvert, sizeof(WICPixelFormatGUID), &GUID_WICPixelFormat128bppRGBAFloat, sizeof(GUID)); format = DXGI_FORMAT_R32G32B32A32_FLOAT; + *alphaMode = TEX_ALPHA_MODE_OPAQUE; } } else @@ -187,6 +192,7 @@ namespace format = _WICToDXGI(g_WICConvert[i].target); assert(format != DXGI_FORMAT_UNKNOWN); + *alphaMode = g_WICConvert[i].alphaMode; break; } } @@ -288,10 +294,13 @@ namespace if (FAILED(hr)) return hr; - metadata.format = DetermineFormat(pixelFormat, flags, iswic2, pConvert); + TEX_ALPHA_MODE alphaMode; + metadata.format = DetermineFormat(pixelFormat, flags, iswic2, pConvert, &alphaMode); if (metadata.format == DXGI_FORMAT_UNKNOWN) return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + metadata.SetAlphaMode(alphaMode); + if (!(flags & WIC_FLAGS_IGNORE_SRGB)) { GUID containerFormat;