mirror of
https://github.com/microsoft/DirectXTex.git
synced 2025-07-13 21:50:13 +02:00
[texconv] Implemented alpha coverage preservation option (#82)
This commit is contained in:
parent
a79989a4f0
commit
f2c4d94a35
@ -534,6 +534,11 @@ namespace DirectX
|
|||||||
// levels of '0' indicates a full mipchain, otherwise is generates that number of total levels (including the source base image)
|
// levels of '0' indicates a full mipchain, otherwise is generates that number of total levels (including the source base image)
|
||||||
// Defaults to Fant filtering which is equivalent to a box filter
|
// Defaults to Fant filtering which is equivalent to a box filter
|
||||||
|
|
||||||
|
HRESULT __cdecl ScaleMipMapsAlphaForCoverage(
|
||||||
|
_In_ const Image* srcImages, _In_ const TexMetadata& metadata, _In_ size_t item,
|
||||||
|
_In_ float alphaReference, _Out_ ScratchImage& mipChain);
|
||||||
|
|
||||||
|
|
||||||
enum TEX_PMALPHA_FLAGS
|
enum TEX_PMALPHA_FLAGS
|
||||||
{
|
{
|
||||||
TEX_PMALPHA_DEFAULT = 0,
|
TEX_PMALPHA_DEFAULT = 0,
|
||||||
|
@ -116,6 +116,211 @@ namespace
|
|||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HRESULT ScaleAlpha(
|
||||||
|
_In_ const Image& srcImage,
|
||||||
|
_In_ float alphaScale,
|
||||||
|
_Out_ const Image& destImage)
|
||||||
|
{
|
||||||
|
assert(srcImage.width == destImage.width);
|
||||||
|
assert(srcImage.height == destImage.height);
|
||||||
|
|
||||||
|
ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast<XMVECTOR*>(_aligned_malloc((sizeof(XMVECTOR)*srcImage.width), 16)));
|
||||||
|
if (!scanline)
|
||||||
|
{
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t* pSrc = srcImage.pixels;
|
||||||
|
uint8_t* pDest = destImage.pixels;
|
||||||
|
if (!pSrc || !pDest)
|
||||||
|
{
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
const XMVECTOR vscale = XMVectorReplicate(alphaScale);
|
||||||
|
|
||||||
|
for (size_t h = 0; h < srcImage.height; ++h)
|
||||||
|
{
|
||||||
|
if (!_LoadScanline(scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format))
|
||||||
|
{
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
XMVECTOR* ptr = scanline.get();
|
||||||
|
for (size_t w = 0; w < srcImage.width; ++w)
|
||||||
|
{
|
||||||
|
XMVECTOR v = *ptr;
|
||||||
|
XMVECTOR alpha = XMVectorMultiply(XMVectorSplatW(v), vscale);
|
||||||
|
*(ptr++) = XMVectorSelect(alpha, v, g_XMSelect1110);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_StoreScanline(pDest, destImage.rowPitch, destImage.format, scanline.get(), srcImage.width))
|
||||||
|
{
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pSrc += srcImage.rowPitch;
|
||||||
|
pDest += destImage.rowPitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GenerateAlphaCoverageConvolutionVectors(
|
||||||
|
_In_ size_t N,
|
||||||
|
_Out_writes_(N*N) XMVECTOR* vectors)
|
||||||
|
{
|
||||||
|
for (size_t sy = 0; sy < N; ++sy)
|
||||||
|
{
|
||||||
|
const float fy = (sy + 0.5f) / N;
|
||||||
|
const float ify = 1.0f - fy;
|
||||||
|
|
||||||
|
for (size_t sx = 0; sx < N; ++sx)
|
||||||
|
{
|
||||||
|
const float fx = (sx + 0.5f) / N;
|
||||||
|
const float ifx = 1.0f - fx;
|
||||||
|
|
||||||
|
// [0]=(x+0, y+0), [1]=(x+0, y+1), [2]=(x+1, y+0), [3]=(x+1, y+1)
|
||||||
|
vectors[sy * N + sx] = XMVectorSet(ifx * ify, ifx * fy, fx * ify, fx * fy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HRESULT CalculateAlphaCoverage(
|
||||||
|
const Image& srcImage,
|
||||||
|
float alphaReference,
|
||||||
|
float alphaScale,
|
||||||
|
float& coverage)
|
||||||
|
{
|
||||||
|
coverage = 0.0f;
|
||||||
|
|
||||||
|
ScopedAlignedArrayXMVECTOR row0(reinterpret_cast<XMVECTOR*>(_aligned_malloc((sizeof(XMVECTOR)*srcImage.width), 16)));
|
||||||
|
if (!row0)
|
||||||
|
{
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScopedAlignedArrayXMVECTOR row1(reinterpret_cast<XMVECTOR*>(_aligned_malloc((sizeof(XMVECTOR)*srcImage.width), 16)));
|
||||||
|
if (!row1)
|
||||||
|
{
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DWORD flags = 0;
|
||||||
|
const XMVECTOR scale = XMVectorReplicate(alphaScale);
|
||||||
|
|
||||||
|
const uint8_t *pSrcRow0 = srcImage.pixels;
|
||||||
|
if (!pSrcRow0)
|
||||||
|
{
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t N = 8;
|
||||||
|
XMVECTOR convolution[N * N];
|
||||||
|
GenerateAlphaCoverageConvolutionVectors(N, convolution);
|
||||||
|
|
||||||
|
XMMATRIX alpha;
|
||||||
|
|
||||||
|
size_t coverageCount = 0;
|
||||||
|
for (size_t y = 0; y < srcImage.height - 1; ++y)
|
||||||
|
{
|
||||||
|
if (!_LoadScanlineLinear(row0.get(), srcImage.width, pSrcRow0, srcImage.rowPitch, srcImage.format, flags))
|
||||||
|
{
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t *pSrcRow1 = pSrcRow0 + srcImage.rowPitch;
|
||||||
|
if (!_LoadScanlineLinear(row1.get(), srcImage.width, pSrcRow1, srcImage.rowPitch, srcImage.format, flags))
|
||||||
|
{
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const XMVECTOR* pRow0 = row0.get();
|
||||||
|
const XMVECTOR* pRow1 = row1.get();
|
||||||
|
for (size_t x = 0; x < srcImage.width - 1; ++x)
|
||||||
|
{
|
||||||
|
// [0]=(x+0, y+0), [1]=(x+0, y+1), [2]=(x+1, y+0), [3]=(x+1, y+1)
|
||||||
|
alpha.r[0] = XMVectorSaturate(XMVectorMultiply(XMVectorSplatW(*pRow0), scale));
|
||||||
|
alpha.r[1] = XMVectorSaturate(XMVectorMultiply(XMVectorSplatW(*pRow1), scale));
|
||||||
|
alpha.r[2] = XMVectorSaturate(XMVectorMultiply(XMVectorSplatW(*(pRow0++)), scale));
|
||||||
|
alpha.r[3] = XMVectorSaturate(XMVectorMultiply(XMVectorSplatW(*(pRow1++)), scale));
|
||||||
|
XMVECTOR v = XMVectorSet(XMVectorGetX(alpha.r[0]), XMVectorGetX(alpha.r[1]), XMVectorGetX(alpha.r[2]), XMVectorGetX(alpha.r[3]));
|
||||||
|
|
||||||
|
for (size_t sy = 0; sy < N; ++sy)
|
||||||
|
{
|
||||||
|
const size_t ry = sy * N;
|
||||||
|
for (size_t sx = 0; sx < N; ++sx)
|
||||||
|
{
|
||||||
|
v = XMVectorSum(XMVectorMultiply(v, convolution[ry + sx]));
|
||||||
|
if (XMVectorGetX(v) > alphaReference)
|
||||||
|
{
|
||||||
|
++coverageCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pSrcRow0 = pSrcRow1;
|
||||||
|
}
|
||||||
|
|
||||||
|
coverage = static_cast<float>(coverageCount) / static_cast<float>((srcImage.width - 1) * (srcImage.height - 1) * N * N);
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HRESULT EstimateAlphaScaleForCoverage(
|
||||||
|
_In_ const Image& srcImage,
|
||||||
|
_In_ float alphaReference,
|
||||||
|
_In_ float targetCoverage,
|
||||||
|
_Out_ float& alphaScale)
|
||||||
|
{
|
||||||
|
float minAlphaScale = 0.0f;
|
||||||
|
float maxAlphaScale = 4.0f;
|
||||||
|
float bestAlphaScale = 1.0f;
|
||||||
|
float bestError = FLT_MAX;
|
||||||
|
|
||||||
|
// Determine desired scale using a binary search. Hardcoded to 10 steps max.
|
||||||
|
alphaScale = 1.0f;
|
||||||
|
const size_t N = 10;
|
||||||
|
for (size_t i = 0; i < N; ++i)
|
||||||
|
{
|
||||||
|
float currentCoverage = 0.0f;
|
||||||
|
HRESULT hr = CalculateAlphaCoverage(srcImage, alphaReference, alphaScale, currentCoverage);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float error = fabsf(currentCoverage - targetCoverage);
|
||||||
|
if (error < bestError)
|
||||||
|
{
|
||||||
|
bestError = error;
|
||||||
|
bestAlphaScale = alphaScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentCoverage < targetCoverage)
|
||||||
|
{
|
||||||
|
minAlphaScale = alphaScale;
|
||||||
|
}
|
||||||
|
else if (currentCoverage > targetCoverage)
|
||||||
|
{
|
||||||
|
maxAlphaScale = alphaScale;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
alphaScale = (minAlphaScale + maxAlphaScale) * 0.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3179,3 +3384,40 @@ HRESULT DirectX::GenerateMipMaps3D(
|
|||||||
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_Use_decl_annotations_
|
||||||
|
HRESULT DirectX::ScaleMipMapsAlphaForCoverage(
|
||||||
|
const Image* srcImages,
|
||||||
|
const TexMetadata& metadata,
|
||||||
|
size_t item,
|
||||||
|
float alphaReference,
|
||||||
|
ScratchImage& mipChain)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
float targetCoverage = 0.0f;
|
||||||
|
hr = CalculateAlphaCoverage(*srcImages, alphaReference, 1.0f, targetCoverage);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t levels = metadata.mipLevels;
|
||||||
|
for (size_t level = 1; level < levels; ++level)
|
||||||
|
{
|
||||||
|
float alphaScale = 0.0f;
|
||||||
|
hr = EstimateAlphaScaleForCoverage(srcImages[level], alphaReference, targetCoverage, alphaScale);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = ScaleAlpha(srcImages[level], alphaScale, *mipChain.GetImage(level, item, 0));
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
@ -101,6 +101,7 @@ enum OPTIONS
|
|||||||
OPT_COLORKEY,
|
OPT_COLORKEY,
|
||||||
OPT_TONEMAP,
|
OPT_TONEMAP,
|
||||||
OPT_X2_BIAS,
|
OPT_X2_BIAS,
|
||||||
|
OPT_PRESERVE_ALPHA_COVERAGE,
|
||||||
OPT_INVERT_Y,
|
OPT_INVERT_Y,
|
||||||
OPT_FILELIST,
|
OPT_FILELIST,
|
||||||
OPT_ROTATE_COLOR,
|
OPT_ROTATE_COLOR,
|
||||||
@ -187,6 +188,7 @@ const SValue g_pOptions[] =
|
|||||||
{ L"c", OPT_COLORKEY },
|
{ L"c", OPT_COLORKEY },
|
||||||
{ L"tonemap", OPT_TONEMAP },
|
{ L"tonemap", OPT_TONEMAP },
|
||||||
{ L"x2bias", OPT_X2_BIAS },
|
{ L"x2bias", OPT_X2_BIAS },
|
||||||
|
{ L"keepcoverage", OPT_PRESERVE_ALPHA_COVERAGE },
|
||||||
{ L"inverty", OPT_INVERT_Y },
|
{ L"inverty", OPT_INVERT_Y },
|
||||||
{ L"flist", OPT_FILELIST },
|
{ L"flist", OPT_FILELIST },
|
||||||
{ L"rotatecolor", OPT_ROTATE_COLOR },
|
{ L"rotatecolor", OPT_ROTATE_COLOR },
|
||||||
@ -751,6 +753,7 @@ namespace
|
|||||||
wprintf(L" -nits <value> paper-white value in nits to use for HDR10 (def: 200.0)\n");
|
wprintf(L" -nits <value> paper-white value in nits to use for HDR10 (def: 200.0)\n");
|
||||||
wprintf(L" -tonemap Apply a tonemap operator based on maximum luminance\n");
|
wprintf(L" -tonemap Apply a tonemap operator based on maximum luminance\n");
|
||||||
wprintf(L" -x2bias Enable *2 - 1 conversion cases for unorm/pos-only-float\n");
|
wprintf(L" -x2bias Enable *2 - 1 conversion cases for unorm/pos-only-float\n");
|
||||||
|
wprintf(L" -keepcoverage <ref> Preserve alpha coverage in generated mips for alpha test ref\n");
|
||||||
wprintf(L" -inverty Invert Y (i.e. green) channel values\n");
|
wprintf(L" -inverty Invert Y (i.e. green) channel values\n");
|
||||||
wprintf(L" -flist <filename> use text file with a list of input files (one per line)\n");
|
wprintf(L" -flist <filename> use text file with a list of input files (one per line)\n");
|
||||||
|
|
||||||
@ -1116,6 +1119,7 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
|||||||
DWORD colorKey = 0;
|
DWORD colorKey = 0;
|
||||||
DWORD dwRotateColor = 0;
|
DWORD dwRotateColor = 0;
|
||||||
float paperWhiteNits = 200.f;
|
float paperWhiteNits = 200.f;
|
||||||
|
float preserveAlphaCoverageRef = 0.0f;
|
||||||
|
|
||||||
wchar_t szPrefix[MAX_PATH];
|
wchar_t szPrefix[MAX_PATH];
|
||||||
wchar_t szSuffix[MAX_PATH];
|
wchar_t szSuffix[MAX_PATH];
|
||||||
@ -1183,6 +1187,7 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
|||||||
case OPT_FILELIST:
|
case OPT_FILELIST:
|
||||||
case OPT_ROTATE_COLOR:
|
case OPT_ROTATE_COLOR:
|
||||||
case OPT_PAPER_WHITE_NITS:
|
case OPT_PAPER_WHITE_NITS:
|
||||||
|
case OPT_PRESERVE_ALPHA_COVERAGE:
|
||||||
if (!*pValue)
|
if (!*pValue)
|
||||||
{
|
{
|
||||||
if ((iArg + 1 >= argc))
|
if ((iArg + 1 >= argc))
|
||||||
@ -1569,15 +1574,27 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
|||||||
case OPT_PAPER_WHITE_NITS:
|
case OPT_PAPER_WHITE_NITS:
|
||||||
if (swscanf_s(pValue, L"%f", &paperWhiteNits) != 1)
|
if (swscanf_s(pValue, L"%f", &paperWhiteNits) != 1)
|
||||||
{
|
{
|
||||||
wprintf(L"Invalid value specified with -nits (%ls)\n", pValue);
|
wprintf(L"Invalid value specified with -nits (%ls)\n\n", pValue);
|
||||||
wprintf(L"\n");
|
|
||||||
PrintUsage();
|
PrintUsage();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else if (paperWhiteNits > 10000.f || paperWhiteNits <= 0.f)
|
else if (paperWhiteNits > 10000.f || paperWhiteNits <= 0.f)
|
||||||
{
|
{
|
||||||
wprintf(L"-nits (%ls) parameter must be between 0 and 10000\n", pValue);
|
wprintf(L"-nits (%ls) parameter must be between 0 and 10000\n\n", pValue);
|
||||||
wprintf(L"\n");
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPT_PRESERVE_ALPHA_COVERAGE:
|
||||||
|
if (swscanf_s(pValue, L"%f", &preserveAlphaCoverageRef) != 1)
|
||||||
|
{
|
||||||
|
wprintf(L"Invalid value specified with -keepcoverage (%ls)\n\n", pValue);
|
||||||
|
PrintUsage();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (preserveAlphaCoverageRef < 0.0f || preserveAlphaCoverageRef > 1.0f)
|
||||||
|
{
|
||||||
|
wprintf(L"-keepcoverage (%ls) parameter must be between 0.0 and 1.0\n\n", pValue);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1655,6 +1672,7 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
|||||||
// Convert images
|
// Convert images
|
||||||
bool nonpow2warn = false;
|
bool nonpow2warn = false;
|
||||||
bool non4bc = false;
|
bool non4bc = false;
|
||||||
|
bool preserveAlphaCoverage = false;
|
||||||
ComPtr<ID3D11Device> pDevice;
|
ComPtr<ID3D11Device> pDevice;
|
||||||
|
|
||||||
for (auto pConv = conversion.begin(); pConv != conversion.end(); ++pConv)
|
for (auto pConv = conversion.begin(); pConv != conversion.end(); ++pConv)
|
||||||
@ -2526,6 +2544,12 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
|||||||
cimage.reset();
|
cimage.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- Determine whether preserve alpha coverage is required (if requested) ----
|
||||||
|
if (preserveAlphaCoverageRef > 0.0f && HasAlpha(info.format) && !image->IsAlphaAllOpaque())
|
||||||
|
{
|
||||||
|
preserveAlphaCoverage = true;
|
||||||
|
}
|
||||||
|
|
||||||
// --- Generate mips -----------------------------------------------------------
|
// --- Generate mips -----------------------------------------------------------
|
||||||
DWORD dwFilter3D = dwFilter;
|
DWORD dwFilter3D = dwFilter;
|
||||||
if (!ispow2(info.width) || !ispow2(info.height) || !ispow2(info.depth))
|
if (!ispow2(info.width) || !ispow2(info.height) || !ispow2(info.depth))
|
||||||
@ -2542,9 +2566,11 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((!tMips || info.mipLevels != tMips) && (info.mipLevels != 1))
|
if ((!tMips || info.mipLevels != tMips || preserveAlphaCoverage) && (info.mipLevels != 1))
|
||||||
{
|
{
|
||||||
// Mips generation only works on a single base image, so strip off existing mip levels
|
// Mips generation only works on a single base image, so strip off existing mip levels
|
||||||
|
// Also required for preserve alpha coverage so that existing mips are regenerated
|
||||||
|
|
||||||
std::unique_ptr<ScratchImage> timage(new (std::nothrow) ScratchImage);
|
std::unique_ptr<ScratchImage> timage(new (std::nothrow) ScratchImage);
|
||||||
if (!timage)
|
if (!timage)
|
||||||
{
|
{
|
||||||
@ -2670,6 +2696,59 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
|||||||
cimage.reset();
|
cimage.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- Preserve mipmap alpha coverage (if requested) ---------------------------
|
||||||
|
if (preserveAlphaCoverage && info.mipLevels != 1)
|
||||||
|
{
|
||||||
|
std::unique_ptr<ScratchImage> timage(new (std::nothrow) ScratchImage);
|
||||||
|
if (!timage)
|
||||||
|
{
|
||||||
|
wprintf(L"\nERROR: Memory allocation failed\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = timage->Initialize(image->GetMetadata());
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
wprintf(L" FAILED [keepcoverage] (%x)\n", hr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t items = image->GetMetadata().arraySize;
|
||||||
|
for (size_t item = 0; item < items; ++item)
|
||||||
|
{
|
||||||
|
auto img = image->GetImage(0, item, 0);
|
||||||
|
assert(img);
|
||||||
|
|
||||||
|
hr = CopyRectangle(*img, Rect(0, 0, info.width, info.height), *timage->GetImage(0, item, 0), TEX_FILTER_DEFAULT, 0, 0);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
wprintf(L" FAILED [keepcoverage] (%x)\n", hr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = ScaleMipMapsAlphaForCoverage(img, info, item, preserveAlphaCoverageRef, *timage);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
wprintf(L" FAILED [keepcoverage] (%x)\n", hr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& tinfo = timage->GetMetadata();
|
||||||
|
tinfo;
|
||||||
|
|
||||||
|
assert(info.width == tinfo.width);
|
||||||
|
assert(info.height == tinfo.height);
|
||||||
|
assert(info.depth == tinfo.depth);
|
||||||
|
assert(info.arraySize == tinfo.arraySize);
|
||||||
|
assert(info.mipLevels == tinfo.mipLevels);
|
||||||
|
assert(info.miscFlags == tinfo.miscFlags);
|
||||||
|
assert(info.dimension == tinfo.dimension);
|
||||||
|
|
||||||
|
image.swap(timage);
|
||||||
|
cimage.reset();
|
||||||
|
}
|
||||||
|
|
||||||
// --- Premultiplied alpha (if requested) --------------------------------------
|
// --- Premultiplied alpha (if requested) --------------------------------------
|
||||||
if ((dwOptions & (DWORD64(1) << OPT_PREMUL_ALPHA))
|
if ((dwOptions & (DWORD64(1) << OPT_PREMUL_ALPHA))
|
||||||
&& HasAlpha(info.format)
|
&& HasAlpha(info.format)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user