diff --git a/Texassemble/texassemble.cpp b/Texassemble/texassemble.cpp index 6cbceec..93171f6 100644 --- a/Texassemble/texassemble.cpp +++ b/Texassemble/texassemble.cpp @@ -4,6 +4,8 @@ // DirectX Texture assembler for cube maps, volume maps, and arrays // // Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 //-------------------------------------------------------------------------------------- #pragma warning(push) @@ -71,6 +73,7 @@ enum OPTIONS OPT_DEMUL_ALPHA, OPT_TA_WRAP, OPT_TA_MIRROR, + OPT_TONEMAP, OPT_MAX }; @@ -122,6 +125,7 @@ const SValue g_pOptions [] = { L"alpha", OPT_DEMUL_ALPHA }, { L"wrap", OPT_TA_WRAP }, { L"mirror", OPT_TA_MIRROR }, + { L"tonemap", OPT_TONEMAP }, { nullptr, 0 } }; @@ -490,6 +494,7 @@ namespace wprintf(L" -alpha convert premultiplied alpha to straight alpha\n"); wprintf(L" -dx10 Force use of 'DX10' extended header\n"); wprintf(L" -nologo suppress copyright message\n"); + wprintf(L" -tonemap Apply a tonemap operator based on maximum luminance\n"); wprintf(L"\n : "); PrintList(13, g_pFormats); @@ -1055,6 +1060,84 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[]) image.swap(timage); } + // --- Tonemap (if requested) -------------------------------------------------- + if (dwOptions & (1 << OPT_TONEMAP)) + { + std::unique_ptr 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.format == tinfo.format); + assert(info.dimension == tinfo.dimension); + + image.swap(timage); + } + // --- Convert ----------------------------------------------------------------- if (format == DXGI_FORMAT_UNKNOWN) { diff --git a/Texconv/texconv.cpp b/Texconv/texconv.cpp index 30d101b..0dfeae0 100644 --- a/Texconv/texconv.cpp +++ b/Texconv/texconv.cpp @@ -4,6 +4,8 @@ // DirectX Texture Converter // // Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 //-------------------------------------------------------------------------------------- #pragma warning(push) @@ -1715,6 +1717,85 @@ 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 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.format == tinfo.format); + assert(info.dimension == tinfo.dimension); + + image.swap(timage); + cimage.reset(); + } + // --- Convert ----------------------------------------------------------------- if (dwOptions & (DWORD64(1) << OPT_NORMAL_MAP)) { @@ -1838,6 +1919,7 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[]) assert(info.arraySize == tinfo.arraySize); assert(info.mipLevels == tinfo.mipLevels); assert(info.miscFlags == tinfo.miscFlags); + assert(info.format == tinfo.format); assert(info.dimension == tinfo.dimension); image.swap(timage); @@ -1986,84 +2068,7 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[]) assert(info.depth == tinfo.depth); assert(info.arraySize == tinfo.arraySize); assert(info.miscFlags == tinfo.miscFlags); - assert(info.dimension == tinfo.dimension); - - image.swap(timage); - cimage.reset(); - } - - // --- Tonemap (if requested) -------------------------------------------------- - if (dwOptions & DWORD64(1) << OPT_TONEMAP) - { - std::unique_ptr 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.format == tinfo.format); assert(info.dimension == tinfo.dimension); image.swap(timage); diff --git a/Texdiag/texdiag.cpp b/Texdiag/texdiag.cpp index 07fef39..0792f4c 100644 --- a/Texdiag/texdiag.cpp +++ b/Texdiag/texdiag.cpp @@ -4,6 +4,8 @@ // DirectX Texture diagnostic tool // // Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 //-------------------------------------------------------------------------------------- #pragma warning(push)