in Texdiag/texdiag.cpp [3211:4158]
int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
{
// Parameters and defaults
TEX_FILTER_FLAGS dwFilter = TEX_FILTER_DEFAULT;
int pixelx = -1;
int pixely = -1;
uint32_t diffColor = 0;
float threshold = 0.25f;
DXGI_FORMAT diffFormat = DXGI_FORMAT_B8G8R8A8_UNORM;
uint32_t fileType = WIC_CODEC_BMP;
wchar_t szOutputFile[MAX_PATH] = {};
// Set locale for output since GetErrorDesc can get localized strings.
std::locale::global(std::locale(""));
// Initialize COM (needed for WIC)
HRESULT hr = hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
if (FAILED(hr))
{
wprintf(L"Failed to initialize COM (%08X%ls)\n", static_cast<unsigned int>(hr), GetErrorDesc(hr));
return 1;
}
// Process command line
if (argc < 2)
{
PrintUsage();
return 0;
}
uint32_t dwCommand = LookupByName(argv[1], g_pCommands);
switch (dwCommand)
{
case CMD_INFO:
case CMD_ANALYZE:
case CMD_COMPARE:
case CMD_DIFF:
case CMD_DUMPBC:
case CMD_DUMPDDS:
break;
default:
wprintf(L"Must use one of: info, analyze, compare, diff, dumpbc, or dumpdds\n\n");
return 1;
}
uint32_t dwOptions = 0;
std::list<SConversion> conversion;
for (int iArg = 2; iArg < argc; iArg++)
{
PWSTR pArg = argv[iArg];
if (('-' == pArg[0]) || ('/' == pArg[0]))
{
pArg++;
PWSTR pValue;
for (pValue = pArg; *pValue && (':' != *pValue); pValue++);
if (*pValue)
*pValue++ = 0;
uint32_t dwOption = LookupByName(pArg, g_pOptions);
if (!dwOption || (dwOptions & (1 << dwOption)))
{
PrintUsage();
return 1;
}
dwOptions |= 1 << dwOption;
// Handle options with additional value parameter
switch (dwOption)
{
case OPT_FILTER:
case OPT_FORMAT:
case OPT_FILETYPE:
case OPT_OUTPUTFILE:
case OPT_TARGET_PIXELX:
case OPT_TARGET_PIXELY:
case OPT_DIFF_COLOR:
case OPT_THRESHOLD:
case OPT_FILELIST:
if (!*pValue)
{
if ((iArg + 1 >= argc))
{
PrintUsage();
return 1;
}
iArg++;
pValue = argv[iArg];
}
break;
default:
break;
}
switch (dwOption)
{
case OPT_FORMAT:
if (dwCommand != CMD_DIFF)
{
wprintf(L"-f only valid for use with diff command\n");
return 1;
}
else
{
diffFormat = static_cast<DXGI_FORMAT>(LookupByName(pValue, g_pFormats));
if (!diffFormat)
{
diffFormat = static_cast<DXGI_FORMAT>(LookupByName(pValue, g_pFormatAliases));
if (!diffFormat)
{
wprintf(L"Invalid value specified with -f (%ls)\n", pValue);
return 1;
}
}
}
break;
case OPT_FILTER:
dwFilter = static_cast<TEX_FILTER_FLAGS>(LookupByName(pValue, g_pFilters));
if (!dwFilter)
{
wprintf(L"Invalid value specified with -if (%ls)\n", pValue);
return 1;
}
break;
case OPT_OUTPUTFILE:
if (dwCommand != CMD_DIFF)
{
wprintf(L"-o only valid for use with diff command\n");
return 1;
}
else
{
wcscpy_s(szOutputFile, MAX_PATH, pValue);
wchar_t ext[_MAX_EXT] = {};
_wsplitpath_s(szOutputFile, nullptr, 0, nullptr, 0, nullptr, 0, ext, _MAX_EXT);
fileType = LookupByName(ext, g_pExtFileTypes);
}
break;
case OPT_FILETYPE:
if (dwCommand != CMD_DUMPDDS)
{
wprintf(L"-ft only valid for use with dumpdds command\n");
return 1;
}
else
{
fileType = LookupByName(pValue, g_pDumpFileTypes);
if (!fileType)
{
wprintf(L"Invalid value specified with -ft (%ls)\n", pValue);
wprintf(L"\n");
PrintUsage();
return 1;
}
}
break;
case OPT_TARGET_PIXELX:
if (dwCommand != CMD_DUMPBC)
{
wprintf(L"-targetx only valid with dumpbc command\n");
return 1;
}
else if (swscanf_s(pValue, L"%d", &pixelx) != 1)
{
wprintf(L"Invalid value for pixel x location (%ls)\n", pValue);
return 1;
}
break;
case OPT_TARGET_PIXELY:
if (dwCommand != CMD_DUMPBC)
{
wprintf(L"-targety only valid with dumpbc command\n");
return 1;
}
else if (swscanf_s(pValue, L"%d", &pixely) != 1)
{
wprintf(L"Invalid value for pixel y location (%ls)\n", pValue);
return 1;
}
break;
case OPT_DIFF_COLOR:
if (swscanf_s(pValue, L"%x", &diffColor) != 1)
{
printf("Invalid value specified with -c (%ls)\n", pValue);
printf("\n");
PrintUsage();
return 1;
}
diffColor &= 0xFFFFFF;
break;
case OPT_THRESHOLD:
if (swscanf_s(pValue, L"%f", &threshold) != 1)
{
printf("Invalid value specified with -t (%ls)\n", pValue);
printf("\n");
PrintUsage();
return 1;
}
break;
case OPT_FILELIST:
{
std::wifstream inFile(pValue);
if (!inFile)
{
wprintf(L"Error opening -flist file %ls\n", pValue);
return 1;
}
inFile.imbue(std::locale::classic());
ProcessFileList(inFile, conversion);
}
break;
default:
break;
}
}
else if (wcspbrk(pArg, L"?*") != nullptr)
{
size_t count = conversion.size();
SearchForFiles(pArg, conversion, (dwOptions & (1 << OPT_RECURSIVE)) != 0);
if (conversion.size() <= count)
{
wprintf(L"No matching files found for %ls\n", pArg);
return 1;
}
}
else
{
SConversion conv = {};
wcscpy_s(conv.szSrc, MAX_PATH, pArg);
conversion.push_back(conv);
}
}
if (conversion.empty())
{
PrintUsage();
return 0;
}
if (~dwOptions & (1 << OPT_NOLOGO))
PrintLogo();
switch (dwCommand)
{
case CMD_COMPARE:
case CMD_DIFF:
// --- Compare/Diff ------------------------------------------------------------
if (conversion.size() != 2)
{
wprintf(L"ERROR: compare/diff needs exactly two images\n");
return 1;
}
else
{
auto pImage1 = conversion.cbegin();
wprintf(L"1: %ls", pImage1->szSrc);
fflush(stdout);
TexMetadata info1;
std::unique_ptr<ScratchImage> image1;
hr = LoadImage(pImage1->szSrc, dwOptions, dwFilter, info1, image1);
if (FAILED(hr))
{
wprintf(L" FAILED (%08X%ls)\n", static_cast<unsigned int>(hr), GetErrorDesc(hr));
return 1;
}
auto pImage2 = conversion.cbegin();
std::advance(pImage2, 1);
wprintf(L"\n2: %ls", pImage2->szSrc);
fflush(stdout);
TexMetadata info2;
std::unique_ptr<ScratchImage> image2;
hr = LoadImage(pImage2->szSrc, dwOptions, dwFilter, info2, image2);
if (FAILED(hr))
{
wprintf(L" FAILED (%08X%ls)\n", static_cast<unsigned int>(hr), GetErrorDesc(hr));
return 1;
}
wprintf(L"\n");
fflush(stdout);
if (info1.height != info2.height
|| info1.width != info2.width)
{
wprintf(L"ERROR: Can only compare/diff images of the same width & height\n");
return 1;
}
if (dwCommand == CMD_DIFF)
{
if (!*szOutputFile)
{
wchar_t ext[_MAX_EXT] = {};
wchar_t fname[_MAX_FNAME] = {};
_wsplitpath_s(pImage1->szSrc, nullptr, 0, nullptr, 0, fname, _MAX_FNAME, ext, _MAX_EXT);
if (_wcsicmp(ext, L".bmp") == 0)
{
wprintf(L"ERROR: Need to specify output file via -o\n");
return 1;
}
_wmakepath_s(szOutputFile, nullptr, nullptr, fname, L".bmp");
}
if (image1->GetImageCount() > 1 || image2->GetImageCount() > 1)
wprintf(L"WARNING: ignoring all images but first one in each file\n");
ScratchImage diffImage;
hr = Difference(*image1->GetImage(0, 0, 0), *image2->GetImage(0, 0, 0), dwFilter, diffFormat, diffColor, threshold, diffImage);
if (FAILED(hr))
{
wprintf(L"Failed diffing images (%08X%ls)\n", static_cast<unsigned int>(hr), GetErrorDesc(hr));
return 1;
}
if (dwOptions & (1 << OPT_TOLOWER))
{
std::ignore = _wcslwr_s(szOutputFile);
}
if (~dwOptions & (1 << OPT_OVERWRITE))
{
if (GetFileAttributesW(szOutputFile) != INVALID_FILE_ATTRIBUTES)
{
wprintf(L"\nERROR: Output file already exists, use -y to overwrite\n");
return 1;
}
}
hr = SaveImage(diffImage.GetImage(0, 0, 0), szOutputFile, fileType);
if (FAILED(hr))
{
wprintf(L" FAILED (%08X%ls)\n", static_cast<unsigned int>(hr), GetErrorDesc(hr));
return 1;
}
wprintf(L"Difference %ls\n", szOutputFile);
}
else if ((info1.depth == 1
&& info1.arraySize == 1
&& info1.mipLevels == 1)
|| info1.depth != info2.depth
|| info1.arraySize != info2.arraySize
|| info1.mipLevels != info2.mipLevels
|| image1->GetImageCount() != image2->GetImageCount())
{
// Compare single image
if (image1->GetImageCount() > 1 || image2->GetImageCount() > 1)
wprintf(L"WARNING: ignoring all images but first one in each file\n");
float mse, mseV[4];
hr = ComputeMSE(*image1->GetImage(0, 0, 0), *image2->GetImage(0, 0, 0), mse, mseV);
if (FAILED(hr))
{
wprintf(L"Failed comparing images (%08X%ls)\n", static_cast<unsigned int>(hr), GetErrorDesc(hr));
return 1;
}
wprintf(L"Result: %f (%f %f %f %f) PSNR %f dB\n", mse, mseV[0], mseV[1], mseV[2], mseV[3],
10.0 * log10(3.0 / (double(mseV[0]) + double(mseV[1]) + double(mseV[2]))));
}
else
{
// Compare all images
float min_mse = FLT_MAX;
float min_mseV[4] = { FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX };
float max_mse = -FLT_MAX;
float max_mseV[4] = { -FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX };
double sum_mse = 0;
double sum_mseV[4] = { 0, 0, 0, 0 };
size_t total_images = 0;
if (info1.depth > 1)
{
wprintf(L"Results by mip (%3zu) and slice (%3zu)\n\n", info1.mipLevels, info1.depth);
size_t depth = info1.depth;
for (size_t mip = 0; mip < info1.mipLevels; ++mip)
{
for (size_t slice = 0; slice < depth; ++slice)
{
const Image* img1 = image1->GetImage(mip, 0, slice);
const Image* img2 = image2->GetImage(mip, 0, slice);
if (!img1
|| !img2
|| img1->height != img2->height
|| img1->width != img2->width)
{
wprintf(L"ERROR: Unexpected mismatch at slice %3zu, mip %3zu\n", slice, mip);
return 1;
}
else
{
float mse, mseV[4];
hr = ComputeMSE(*img1, *img2, mse, mseV);
if (FAILED(hr))
{
wprintf(L"Failed comparing images at slice %3zu, mip %3zu (%08X%ls)\n", slice, mip, static_cast<unsigned int>(hr), GetErrorDesc(hr));
return 1;
}
min_mse = std::min(min_mse, mse);
max_mse = std::max(max_mse, mse);
sum_mse += double(mse);
for (size_t j = 0; j < 4; ++j)
{
min_mseV[j] = std::min(min_mseV[j], mseV[j]);
max_mseV[j] = std::max(max_mseV[j], mseV[j]);
sum_mseV[j] += double(mseV[j]);
}
++total_images;
wprintf(L"[%3zu,%3zu]: %f (%f %f %f %f) PSNR %f dB\n", mip, slice, mse, mseV[0], mseV[1], mseV[2], mseV[3],
10.0 * log10(3.0 / (double(mseV[0]) + double(mseV[1]) + double(mseV[2]))));
}
}
if (depth > 1)
depth >>= 1;
}
}
else
{
wprintf(L"Results by item (%3zu) and mip (%3zu)\n\n", info1.arraySize, info1.mipLevels);
for (size_t item = 0; item < info1.arraySize; ++item)
{
for (size_t mip = 0; mip < info1.mipLevels; ++mip)
{
const Image* img1 = image1->GetImage(mip, item, 0);
const Image* img2 = image2->GetImage(mip, item, 0);
if (!img1
|| !img2
|| img1->height != img2->height
|| img1->width != img2->width)
{
wprintf(L"ERROR: Unexpected mismatch at item %3zu, mip %3zu\n", item, mip);
return 1;
}
else
{
float mse, mseV[4];
hr = ComputeMSE(*img1, *img2, mse, mseV);
if (FAILED(hr))
{
wprintf(L"Failed comparing images at item %3zu, mip %3zu (%08X%ls)\n", item, mip, static_cast<unsigned int>(hr), GetErrorDesc(hr));
return 1;
}
min_mse = std::min(min_mse, mse);
max_mse = std::max(max_mse, mse);
sum_mse += double(mse);
for (size_t j = 0; j < 4; ++j)
{
min_mseV[j] = std::min(min_mseV[j], mseV[j]);
max_mseV[j] = std::max(max_mseV[j], mseV[j]);
sum_mseV[j] += double(mseV[j]);
}
++total_images;
wprintf(L"[%3zu,%3zu]: %f (%f %f %f %f) PSNR %f dB\n", item, mip, mse, mseV[0], mseV[1], mseV[2], mseV[3],
10.0 * log10(3.0 / (double(mseV[0]) + double(mseV[1]) + double(mseV[2]))));
}
}
}
}
// Output multi-image stats
if (total_images > 1)
{
wprintf(L"\n Minimum MSE: %f (%f %f %f %f) PSNR %f dB\n", min_mse, min_mseV[0], min_mseV[1], min_mseV[2], min_mseV[3],
10.0 * log10(3.0 / (double(min_mseV[0]) + double(min_mseV[1]) + double(min_mseV[2]))));
double total_mseV0 = sum_mseV[0] / double(total_images);
double total_mseV1 = sum_mseV[1] / double(total_images);
double total_mseV2 = sum_mseV[2] / double(total_images);
wprintf(L" Average MSE: %f (%f %f %f %f) PSNR %f dB\n", sum_mse / double(total_images),
total_mseV0,
total_mseV1,
total_mseV2,
sum_mseV[3] / double(total_images),
10.0 * log10(3.0 / (total_mseV0 + total_mseV1 + total_mseV2)));
wprintf(L" Maximum MSE: %f (%f %f %f %f) PSNR %f dB\n", max_mse, max_mseV[0], max_mseV[1], max_mseV[2], max_mseV[3],
10.0 * log10(3.0 / (double(max_mseV[0]) + double(max_mseV[1]) + double(max_mseV[2]))));
}
}
}
break;
default:
for (auto pConv = conversion.cbegin(); pConv != conversion.cend(); ++pConv)
{
// Load source image
if (pConv != conversion.begin())
wprintf(L"\n");
wprintf(L"%ls", pConv->szSrc);
fflush(stdout);
TexMetadata info;
std::unique_ptr<ScratchImage> image;
hr = LoadImage(pConv->szSrc, dwOptions, dwFilter, info, image);
if (FAILED(hr))
{
wprintf(L" FAILED (%08X%ls)\n", static_cast<unsigned int>(hr), GetErrorDesc(hr));
return 1;
}
wprintf(L"\n");
fflush(stdout);
if (dwCommand == CMD_INFO)
{
// --- Info ----------------------------------------------------------------
wprintf(L" width = %zu\n", info.width);
wprintf(L" height = %zu\n", info.height);
wprintf(L" depth = %zu\n", info.depth);
wprintf(L" mipLevels = %zu\n", info.mipLevels);
wprintf(L" arraySize = %zu\n", info.arraySize);
wprintf(L" format = ");
PrintFormat(info.format);
wprintf(L"\n dimension = ");
switch (info.dimension)
{
case TEX_DIMENSION_TEXTURE1D:
wprintf(L"%ls", (info.arraySize > 1) ? L"1DArray\n" : L"1D\n");
break;
case TEX_DIMENSION_TEXTURE2D:
if (info.IsCubemap())
{
wprintf(L"%ls", (info.arraySize > 6) ? L"CubeArray\n" : L"Cube\n");
}
else
{
wprintf(L"%ls", (info.arraySize > 1) ? L"2DArray\n" : L"2D\n");
}
break;
case TEX_DIMENSION_TEXTURE3D:
wprintf(L" 3D");
break;
}
wprintf(L" alpha mode = ");
switch (info.GetAlphaMode())
{
case TEX_ALPHA_MODE_OPAQUE:
wprintf(L"Opaque");
break;
case TEX_ALPHA_MODE_PREMULTIPLIED:
wprintf(L"Premultiplied");
break;
case TEX_ALPHA_MODE_STRAIGHT:
wprintf(L"Straight");
break;
case TEX_ALPHA_MODE_CUSTOM:
wprintf(L"Custom");
break;
case TEX_ALPHA_MODE_UNKNOWN:
wprintf(L"Unknown");
break;
}
wprintf(L"\n images = %zu\n", image->GetImageCount());
auto sizeInKb = static_cast<uint32_t>(image->GetPixelsSize() / 1024);
wprintf(L" pixel size = %u (KB)\n\n", sizeInKb);
}
else if (dwCommand == CMD_DUMPDDS)
{
// --- Dump DDS ------------------------------------------------------------
if (IsCompressed(info.format))
{
wprintf(L"ERROR: dumpdds only operates on non-compressed format DDS files\n");
return 1;
}
wchar_t ext[_MAX_EXT] = {};
wchar_t fname[_MAX_FNAME] = {};
_wsplitpath_s(pConv->szSrc, nullptr, 0, nullptr, 0, fname, _MAX_FNAME, nullptr, 0);
wcscpy_s(ext, LookupByValue(fileType, g_pDumpFileTypes));
if (info.depth > 1)
{
wprintf(L"Writing by mip (%3zu) and slice (%3zu)...", info.mipLevels, info.depth);
size_t depth = info.depth;
for (size_t mip = 0; mip < info.mipLevels; ++mip)
{
for (size_t slice = 0; slice < depth; ++slice)
{
const Image* img = image->GetImage(mip, 0, slice);
if (!img)
{
wprintf(L"ERROR: Unexpected error at slice %3zu, mip %3zu\n", slice, mip);
return 1;
}
else
{
wchar_t subFname[_MAX_FNAME] = {};
if (info.mipLevels > 1)
{
swprintf_s(subFname, L"%ls_slice%03zu_mip%03zu", fname, slice, mip);
}
else
{
swprintf_s(subFname, L"%ls_slice%03zu", fname, slice);
}
_wmakepath_s(szOutputFile, nullptr, nullptr, subFname, ext);
hr = SaveImage(img, szOutputFile, fileType);
if (FAILED(hr))
{
wprintf(L" FAILED (%08X%ls)\n", static_cast<unsigned int>(hr), GetErrorDesc(hr));
return 1;
}
}
}
if (depth > 1)
depth >>= 1;
}
wprintf(L"\n");
}
else
{
wprintf(L"Writing by item (%3zu) and mip (%3zu)...", info.arraySize, info.mipLevels);
for (size_t item = 0; item < info.arraySize; ++item)
{
for (size_t mip = 0; mip < info.mipLevels; ++mip)
{
const Image* img = image->GetImage(mip, item, 0);
if (!img)
{
wprintf(L"ERROR: Unexpected error at item %3zu, mip %3zu\n", item, mip);
return 1;
}
else
{
wchar_t subFname[_MAX_FNAME];
if (info.mipLevels > 1)
{
swprintf_s(subFname, L"%ls_item%03zu_mip%03zu", fname, item, mip);
}
else
{
swprintf_s(subFname, L"%ls_item%03zu", fname, item);
}
_wmakepath_s(szOutputFile, nullptr, nullptr, subFname, ext);
hr = SaveImage(img, szOutputFile, fileType);
if (FAILED(hr))
{
wprintf(L" FAILED (%08X%ls)\n", static_cast<unsigned int>(hr), GetErrorDesc(hr));
return 1;
}
}
}
}
wprintf(L"\n");
}
}
else if (dwCommand == CMD_DUMPBC)
{
// --- Dump BC -------------------------------------------------------------
if (!IsCompressed(info.format))
{
wprintf(L"ERROR: dumpbc only operates on BC format DDS files\n");
return 1;
}
if (pixelx >= int(info.width)
|| pixely >= int(info.height))
{
wprintf(L"WARNING: Specified pixel location (%d x %d) is out of range for image (%zu x %zu)\n", pixelx, pixely, info.width, info.height);
continue;
}
wprintf(L"Compression: ");
PrintFormat(info.format);
wprintf(L"\n");
if (info.depth > 1)
{
wprintf(L"Results by mip (%3zu) and slice (%3zu)\n", info.mipLevels, info.depth);
size_t depth = info.depth;
for (size_t mip = 0; mip < info.mipLevels; ++mip)
{
for (size_t slice = 0; slice < depth; ++slice)
{
const Image* img = image->GetImage(mip, 0, slice);
if (!img)
{
wprintf(L"ERROR: Unexpected error at slice %3zu, mip %3zu\n", slice, mip);
return 1;
}
else
{
wprintf(L"\n[%3zu, %3zu]:\n", mip, slice);
hr = DumpBCImage(*img, pixelx, pixely);
if (FAILED(hr))
{
wprintf(L"ERROR: Failed dumping image at slice %3zu, mip %3zu (%08X%ls)\n", slice, mip, static_cast<unsigned int>(hr), GetErrorDesc(hr));
return 1;
}
}
}
if (depth > 1)
depth >>= 1;
if (pixelx > 0)
pixelx >>= 1;
if (pixely > 0)
pixely >>= 1;
}
}
else
{
wprintf(L"Results by item (%3zu) and mip (%3zu)\n", info.arraySize, info.mipLevels);
for (size_t item = 0; item < info.arraySize; ++item)
{
int tpixelx = pixelx;
int tpixely = pixely;
for (size_t mip = 0; mip < info.mipLevels; ++mip)
{
const Image* img = image->GetImage(mip, item, 0);
if (!img)
{
wprintf(L"ERROR: Unexpected error at item %3zu, mip %3zu\n", item, mip);
return 1;
}
else
{
if (image->GetImageCount() > 1)
{
wprintf(L"\n[%3zu, %3zu]:\n", item, mip);
}
hr = DumpBCImage(*img, tpixelx, tpixely);
if (FAILED(hr))
{
wprintf(L"ERROR: Failed dumping image at item %3zu, mip %3zu (%08X%ls)\n", item, mip, static_cast<unsigned int>(hr), GetErrorDesc(hr));
return 1;
}
}
if (tpixelx > 0)
tpixelx >>= 1;
if (tpixely > 0)
tpixely >>= 1;
}
}
}
}
else
{
// --- Analyze -------------------------------------------------------------
if (IsPlanar(info.format))
{
auto img = image->GetImage(0, 0, 0);
assert(img);
size_t nimg = image->GetImageCount();
std::unique_ptr<ScratchImage> timage(new (std::nothrow) ScratchImage);
if (!timage)
{
wprintf(L"\nERROR: Memory allocation failed\n");
return 1;
}
hr = ConvertToSinglePlane(img, nimg, info, *timage);
if (FAILED(hr))
{
wprintf(L" FAILED [converttosingleplane] (%08X%ls)\n", static_cast<unsigned int>(hr), GetErrorDesc(hr));
return 1;
}
auto& tinfo = timage->GetMetadata();
info.format = tinfo.format;
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);
}
if (info.depth > 1)
{
wprintf(L"Results by mip (%3zu) and slice (%3zu)\n\n", info.mipLevels, info.depth);
size_t depth = info.depth;
for (size_t mip = 0; mip < info.mipLevels; ++mip)
{
for (size_t slice = 0; slice < depth; ++slice)
{
const Image* img = image->GetImage(mip, 0, slice);
if (!img)
{
wprintf(L"ERROR: Unexpected error at slice %3zu, mip %3zu\n", slice, mip);
return 1;
}
else
{
AnalyzeData data;
hr = Analyze(*img, data);
if (FAILED(hr))
{
wprintf(L"ERROR: Failed analyzing image at slice %3zu, mip %3zu (%08X%ls)\n", slice, mip, static_cast<unsigned int>(hr), GetErrorDesc(hr));
return 1;
}
wprintf(L"Result slice %3zu, mip %3zu:\n", slice, mip);
data.Print();
}
if (IsCompressed(info.format))
{
AnalyzeBCData data;
hr = AnalyzeBC(*img, data);
if (FAILED(hr))
{
wprintf(L"ERROR: Failed analyzing BC image at slice %3zu, mip %3zu (%08X%ls)\n", slice, mip, static_cast<unsigned int>(hr), GetErrorDesc(hr));
return 1;
}
data.Print(img->format);
}
wprintf(L"\n");
}
if (depth > 1)
depth >>= 1;
}
}
else
{
wprintf(L"Results by item (%3zu) and mip (%3zu)\n\n", info.arraySize, info.mipLevels);
for (size_t item = 0; item < info.arraySize; ++item)
{
for (size_t mip = 0; mip < info.mipLevels; ++mip)
{
const Image* img = image->GetImage(mip, item, 0);
if (!img)
{
wprintf(L"ERROR: Unexpected error at item %3zu, mip %3zu\n", item, mip);
return 1;
}
else
{
AnalyzeData data;
hr = Analyze(*img, data);
if (FAILED(hr))
{
wprintf(L"ERROR: Failed analyzing image at item %3zu, mip %3zu (%08X%ls)\n", item, mip, static_cast<unsigned int>(hr), GetErrorDesc(hr));
return 1;
}
if (image->GetImageCount() > 1)
{
wprintf(L"Result item %3zu, mip %3zu:\n", item, mip);
}
data.Print();
}
if (IsCompressed(info.format))
{
AnalyzeBCData data;
hr = AnalyzeBC(*img, data);
if (FAILED(hr))
{
wprintf(L"ERROR: Failed analyzing BC image at item %3zu, mip %3zu (%08X%ls)\n", item, mip, static_cast<unsigned int>(hr), GetErrorDesc(hr));
return 1;
}
data.Print(img->format);
}
wprintf(L"\n");
}
}
}
}
}
break;
}
return 0;
}