mirror of
https://github.com/microsoft/DirectXTex
synced 2024-11-21 20:10:05 +00:00
texconv -tonemap option
This commit is contained in:
parent
2f31eb519c
commit
c5f238b6d4
@ -621,6 +621,8 @@ namespace DirectX
|
||||
|
||||
HRESULT __cdecl EvaluateImage( _In_ const Image& image,
|
||||
_In_ std::function<void __cdecl(_In_reads_(width) const XMVECTOR* pixels, size_t width, size_t y)> pixelFunc );
|
||||
HRESULT __cdecl EvaluateImage( _In_reads_(nimages) const Image* images, _In_ size_t nimages, _In_ const TexMetadata& metadata,
|
||||
_In_ std::function<void __cdecl(_In_reads_(width) const XMVECTOR* pixels, size_t width, size_t y)> pixelFunc );
|
||||
|
||||
HRESULT __cdecl TransformImage( _In_ const Image& image,
|
||||
_In_ std::function<void __cdecl(_Out_writes_(width) XMVECTOR* outPixels,
|
||||
|
@ -497,6 +497,99 @@ HRESULT DirectX::EvaluateImage(
|
||||
}
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
HRESULT DirectX::EvaluateImage(
|
||||
const Image* images,
|
||||
size_t nimages,
|
||||
const TexMetadata& metadata,
|
||||
std::function<void __cdecl(_In_reads_(width) const XMVECTOR* pixels, size_t width, size_t y)> pixelFunc)
|
||||
{
|
||||
if (!images || !nimages)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (!IsValid(metadata.format))
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (IsPlanar(metadata.format) || IsPalettized(metadata.format) || IsTypeless(metadata.format))
|
||||
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||
|
||||
if (metadata.width > UINT32_MAX
|
||||
|| metadata.height > UINT32_MAX)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (metadata.IsVolumemap() && metadata.depth > UINT32_MAX)
|
||||
return E_INVALIDARG;
|
||||
|
||||
ScratchImage temp;
|
||||
DXGI_FORMAT format = metadata.format;
|
||||
if (IsCompressed(format))
|
||||
{
|
||||
HRESULT hr = Decompress(images, nimages, metadata, DXGI_FORMAT_R32G32B32A32_FLOAT, temp);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
if (nimages != temp.GetImageCount())
|
||||
return E_UNEXPECTED;
|
||||
|
||||
images = temp.GetImages();
|
||||
format = DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
}
|
||||
|
||||
switch (metadata.dimension)
|
||||
{
|
||||
case TEX_DIMENSION_TEXTURE1D:
|
||||
case TEX_DIMENSION_TEXTURE2D:
|
||||
for (size_t index = 0; index < nimages; ++index)
|
||||
{
|
||||
const Image& img = images[index];
|
||||
if (img.format != format)
|
||||
return E_FAIL;
|
||||
|
||||
if ((img.width > UINT32_MAX) || (img.height > UINT32_MAX))
|
||||
return E_FAIL;
|
||||
|
||||
HRESULT hr = EvaluateImage_(img, pixelFunc);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
}
|
||||
break;
|
||||
|
||||
case TEX_DIMENSION_TEXTURE3D:
|
||||
{
|
||||
size_t index = 0;
|
||||
size_t d = metadata.depth;
|
||||
for (size_t level = 0; level < metadata.mipLevels; ++level)
|
||||
{
|
||||
for (size_t slice = 0; slice < d; ++slice, ++index)
|
||||
{
|
||||
if (index >= nimages)
|
||||
return E_FAIL;
|
||||
|
||||
const Image& img = images[index];
|
||||
if (img.format != format)
|
||||
return E_FAIL;
|
||||
|
||||
if ((img.width > UINT32_MAX) || (img.height > UINT32_MAX))
|
||||
return E_FAIL;
|
||||
|
||||
HRESULT hr = EvaluateImage_(img, pixelFunc);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (d > 1)
|
||||
d >>= 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Use a user-supplied function to compute a new image from an input image
|
||||
|
@ -86,6 +86,7 @@ enum OPTIONS
|
||||
OPT_WIC_QUALITY,
|
||||
OPT_WIC_LOSSLESS,
|
||||
OPT_COLORKEY,
|
||||
OPT_TONEMAP,
|
||||
OPT_MAX
|
||||
};
|
||||
|
||||
@ -153,6 +154,7 @@ SValue g_pOptions[] =
|
||||
{ L"wicq", OPT_WIC_QUALITY },
|
||||
{ L"wiclossless", OPT_WIC_LOSSLESS },
|
||||
{ L"c", OPT_COLORKEY },
|
||||
{ L"tonemap", OPT_TONEMAP },
|
||||
{ nullptr, 0 }
|
||||
};
|
||||
|
||||
@ -659,13 +661,14 @@ namespace
|
||||
wprintf(L" -bcuniform Use uniform rather than perceptual weighting for BC1-3\n");
|
||||
wprintf(L" -bcdither Use dithering for BC1-3\n");
|
||||
wprintf(L" -bcmax Use exhaustive compression (BC7 only)\n");
|
||||
wprintf(L" -bcquick USe quick compression (BC7 only)\n");
|
||||
wprintf(L" -bcquick Use quick compression (BC7 only)\n");
|
||||
wprintf(L" -wicq <quality> When writing images with WIC use quality (0.0 to 1.0)\n");
|
||||
wprintf(L" -wiclossless When writing images with WIC use lossless mode\n");
|
||||
wprintf(
|
||||
L" -aw <weight> BC7 GPU compressor weighting for alpha error metric\n"
|
||||
L" (defaults to 1.0)\n");
|
||||
wprintf(L" -c <hex-RGB> colorkey (a.k.a. chromakey) transparency\n");
|
||||
wprintf(L" -tonemap Apply a tonemap operator based on maximum luminance\n");
|
||||
|
||||
wprintf(L"\n");
|
||||
wprintf(L" <format>: ");
|
||||
@ -1956,6 +1959,82 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
||||
cimage.reset();
|
||||
}
|
||||
|
||||
// --- Tonemap (if requested) --------------------------------------------------
|
||||
if (dwOptions & DWORD64(1) << OPT_TONEMAP)
|
||||
{
|
||||
std::unique_ptr<ScratchImage> timage(new (std::nothrow) ScratchImage);
|
||||
if (!timage)
|
||||
{
|
||||
wprintf(L"\nERROR: Memory allocation failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Compute max luminosity across all images
|
||||
XMVECTOR maxLum = XMVectorZero();
|
||||
hr = EvaluateImage(image->GetImages(), image->GetImageCount(), image->GetMetadata(),
|
||||
[&](const XMVECTOR* pixels, size_t width, size_t y)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(y);
|
||||
|
||||
for (size_t j = 0; j < width; ++j)
|
||||
{
|
||||
static const XMVECTORF32 s_luminance = { 0.3f, 0.59f, 0.11f, 0.f };
|
||||
|
||||
XMVECTOR v = *pixels++;
|
||||
|
||||
v = XMVector3Dot(v, s_luminance);
|
||||
|
||||
maxLum = XMVectorMax(v, maxLum);
|
||||
}
|
||||
});
|
||||
if (FAILED(hr))
|
||||
{
|
||||
wprintf(L" FAILED [tonemap maxlum] (%x)\n", hr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Reinhard et al, "Photographic Tone Reproduction for Digital Images"
|
||||
// http://www.cs.utah.edu/~reinhard/cdrom/
|
||||
maxLum = XMVectorMultiply(maxLum, maxLum);
|
||||
|
||||
hr = TransformImage(image->GetImages(), image->GetImageCount(), image->GetMetadata(),
|
||||
[&](XMVECTOR* outPixels, const XMVECTOR* inPixels, size_t width, size_t y)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(y);
|
||||
|
||||
for (size_t j = 0; j < width; ++j)
|
||||
{
|
||||
XMVECTOR value = inPixels[j];
|
||||
|
||||
XMVECTOR scale = XMVectorDivide(XMVectorAdd(g_XMOne, XMVectorDivide(value, maxLum)), XMVectorAdd(g_XMOne, value));
|
||||
XMVECTOR nvalue = XMVectorMultiply(value, scale);
|
||||
|
||||
value = XMVectorSelect(value, nvalue, g_XMSelect1110);
|
||||
|
||||
outPixels[j] = value;
|
||||
}
|
||||
}, *timage);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
wprintf(L" FAILED [tonemap apply] (%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) --------------------------------------
|
||||
if ((dwOptions & (DWORD64(1) << OPT_PREMUL_ALPHA))
|
||||
&& HasAlpha(info.format)
|
||||
|
Loading…
Reference in New Issue
Block a user