mirror of
https://github.com/microsoft/DirectXTex
synced 2024-12-24 02:11:04 +00:00
texassemble: command syntax with strip/cross, -srgb, -y, -wrap, -mirror, -alpha switches
This commit is contained in:
parent
97fa22b8ae
commit
df72538e93
@ -32,21 +32,37 @@
|
||||
|
||||
using namespace DirectX;
|
||||
|
||||
enum COMMANDS
|
||||
{
|
||||
CMD_CUBE = 1,
|
||||
CMD_VOLUME,
|
||||
CMD_ARRAY,
|
||||
CMD_CUBEARRAY,
|
||||
CMD_H_CROSS,
|
||||
CMD_V_CROSS,
|
||||
CMD_H_STRIP,
|
||||
CMD_V_STRIP,
|
||||
CMD_MAX
|
||||
};
|
||||
|
||||
enum OPTIONS
|
||||
{
|
||||
OPT_RECURSIVE = 1,
|
||||
OPT_CUBE,
|
||||
OPT_VOLUME,
|
||||
OPT_ARRAY,
|
||||
OPT_CUBEARRAY,
|
||||
OPT_WIDTH,
|
||||
OPT_HEIGHT,
|
||||
OPT_FORMAT,
|
||||
OPT_FILTER,
|
||||
OPT_SRGBI,
|
||||
OPT_SRGBO,
|
||||
OPT_SRGB,
|
||||
OPT_OUTPUTFILE,
|
||||
OPT_OVERWRITE,
|
||||
OPT_USE_DX10,
|
||||
OPT_NOLOGO,
|
||||
OPT_SEPALPHA,
|
||||
OPT_DEMUL_ALPHA,
|
||||
OPT_TA_WRAP,
|
||||
OPT_TA_MIRROR,
|
||||
OPT_MAX
|
||||
};
|
||||
|
||||
@ -67,21 +83,37 @@ struct SValue
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SValue g_pCommands[] =
|
||||
{
|
||||
{ L"cube", CMD_CUBE },
|
||||
{ L"volume", CMD_VOLUME },
|
||||
{ L"array", CMD_ARRAY },
|
||||
{ L"cubearray", CMD_CUBEARRAY },
|
||||
{ L"h-cross", CMD_H_CROSS },
|
||||
{ L"v-cross", CMD_V_CROSS },
|
||||
{ L"h-strip", CMD_H_STRIP },
|
||||
{ L"v-strip", CMD_V_STRIP },
|
||||
{ nullptr, 0 }
|
||||
};
|
||||
|
||||
SValue g_pOptions[] =
|
||||
{
|
||||
{ L"r", OPT_RECURSIVE },
|
||||
{ L"cube", OPT_CUBE },
|
||||
{ L"volume", OPT_VOLUME },
|
||||
{ L"array", OPT_ARRAY },
|
||||
{ L"cubearray", OPT_CUBEARRAY },
|
||||
{ L"w", OPT_WIDTH },
|
||||
{ L"h", OPT_HEIGHT },
|
||||
{ L"f", OPT_FORMAT },
|
||||
{ L"if", OPT_FILTER },
|
||||
{ L"srgbi", OPT_SRGBI },
|
||||
{ L"srgbo", OPT_SRGBO },
|
||||
{ L"srgb", OPT_SRGB },
|
||||
{ L"o", OPT_OUTPUTFILE },
|
||||
{ L"y", OPT_OVERWRITE },
|
||||
{ L"dx10", OPT_USE_DX10 },
|
||||
{ L"nologo", OPT_NOLOGO },
|
||||
{ L"sepalpha", OPT_SEPALPHA },
|
||||
{ L"alpha", OPT_DEMUL_ALPHA },
|
||||
{ L"wrap", OPT_TA_WRAP },
|
||||
{ L"mirror", OPT_TA_MIRROR },
|
||||
{ nullptr, 0 }
|
||||
};
|
||||
|
||||
@ -149,6 +181,13 @@ SValue g_pFormats[] =
|
||||
DEFFMT(B8G8R8X8_UNORM_SRGB),
|
||||
|
||||
// DXGI 1.2 formats
|
||||
DEFFMT(AYUV),
|
||||
DEFFMT(Y410),
|
||||
DEFFMT(Y416),
|
||||
DEFFMT(YUY2),
|
||||
DEFFMT(Y210),
|
||||
DEFFMT(Y216),
|
||||
// No support for legacy paletted video formats (AI44, IA44, P8, A8P8)
|
||||
DEFFMT(B4G4R4A4_UNORM),
|
||||
|
||||
{ nullptr, DXGI_FORMAT_UNKNOWN }
|
||||
@ -177,6 +216,27 @@ SValue g_pFilters[] =
|
||||
{ nullptr, TEX_FILTER_DEFAULT }
|
||||
};
|
||||
|
||||
#define CODEC_DDS 0xFFFF0001
|
||||
#define CODEC_TGA 0xFFFF0002
|
||||
#define CODEC_HDR 0xFFFF0005
|
||||
|
||||
SValue g_pExtFileTypes[] =
|
||||
{
|
||||
{ L".BMP", WIC_CODEC_BMP },
|
||||
{ L".JPG", WIC_CODEC_JPEG },
|
||||
{ L".JPEG", WIC_CODEC_JPEG },
|
||||
{ L".PNG", WIC_CODEC_PNG },
|
||||
{ L".DDS", CODEC_DDS },
|
||||
{ L".TGA", CODEC_TGA },
|
||||
{ L".HDR", CODEC_HDR },
|
||||
{ L".TIF", WIC_CODEC_TIFF },
|
||||
{ L".TIFF", WIC_CODEC_TIFF },
|
||||
{ L".WDP", WIC_CODEC_WMP },
|
||||
{ L".HDP", WIC_CODEC_WMP },
|
||||
{ L".JXR", WIC_CODEC_WMP },
|
||||
{ nullptr, CODEC_DDS }
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@ -345,6 +405,19 @@ namespace
|
||||
break;
|
||||
}
|
||||
|
||||
switch (info.GetAlphaMode())
|
||||
{
|
||||
case TEX_ALPHA_MODE_OPAQUE:
|
||||
wprintf(L" \x0e0:Opaque");
|
||||
break;
|
||||
case TEX_ALPHA_MODE_PREMULTIPLIED:
|
||||
wprintf(L" \x0e0:PM");
|
||||
break;
|
||||
case TEX_ALPHA_MODE_STRAIGHT:
|
||||
wprintf(L" \x0e0:NonPM");
|
||||
break;
|
||||
}
|
||||
|
||||
wprintf(L")");
|
||||
}
|
||||
|
||||
@ -385,28 +458,31 @@ namespace
|
||||
{
|
||||
PrintLogo();
|
||||
|
||||
wprintf(L"Usage: texassemble [-cube | - volume | -array | -cubearray] <options> <files>\n");
|
||||
wprintf(L"\n");
|
||||
wprintf(L"Usage: texassemble <command> <options> <files>\n\n");
|
||||
wprintf(L" cube create cubemap\n");
|
||||
wprintf(L" volume create volume map\n");
|
||||
wprintf(L" array create texture array\n");
|
||||
wprintf(L" cubearray create cubemap array\n");
|
||||
wprintf(L" h-cross or v-cross create a cross image from a cubemap\n");
|
||||
wprintf(L" h-strip or v-strip create a strip image from a cubemap\n\n");
|
||||
wprintf(L" -r wildcard filename search is recursive\n");
|
||||
wprintf(L" -cube create cubemap\n");
|
||||
wprintf(L" -volume create volume map\n");
|
||||
wprintf(L" -array create texture array\n");
|
||||
wprintf(L" -cubearray create cubemap array\n");
|
||||
wprintf(L" -w <n> width\n");
|
||||
wprintf(L" -h <n> height\n");
|
||||
wprintf(L" -f <format> format\n");
|
||||
wprintf(L" -if <filter> image filtering\n");
|
||||
wprintf(L" -srgb{i|o} sRGB {input, output}\n");
|
||||
wprintf(L" -o <filename> output filename\n");
|
||||
wprintf(L" -y overwrite existing output file (if any)\n");
|
||||
wprintf(L" -sepalpha resize alpha channel separately from color channels\n");
|
||||
wprintf(L" -wrap, -mirror texture addressing mode (wrap, mirror, or clamp)\n");
|
||||
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"\n");
|
||||
wprintf(L" <format>: ");
|
||||
wprintf(L"\n <format>: ");
|
||||
PrintList(13, g_pFormats);
|
||||
|
||||
wprintf(L"\n");
|
||||
wprintf(L" <filter>: ");
|
||||
wprintf(L"\n <filter>: ");
|
||||
PrintList(13, g_pFilters);
|
||||
}
|
||||
}
|
||||
@ -425,7 +501,9 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
||||
|
||||
DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
|
||||
DWORD dwFilter = TEX_FILTER_DEFAULT;
|
||||
DWORD dwSRGB = 0;
|
||||
DWORD dwFilterOpts = 0;
|
||||
DWORD CrossFileType = WIC_CODEC_BMP;
|
||||
|
||||
wchar_t szOutputFile[MAX_PATH] = { 0 };
|
||||
|
||||
@ -441,7 +519,31 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
||||
DWORD dwOptions = 0;
|
||||
std::list<SConversion> conversion;
|
||||
|
||||
for (int iArg = 1; iArg < argc; iArg++)
|
||||
if (argc < 2)
|
||||
{
|
||||
PrintUsage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD dwCommand = LookupByName(argv[1], g_pCommands);
|
||||
switch (dwCommand)
|
||||
{
|
||||
case CMD_CUBE:
|
||||
case CMD_VOLUME:
|
||||
case CMD_ARRAY:
|
||||
case CMD_CUBEARRAY:
|
||||
case CMD_H_CROSS:
|
||||
case CMD_V_CROSS:
|
||||
case CMD_H_STRIP:
|
||||
case CMD_V_STRIP:
|
||||
break;
|
||||
|
||||
default:
|
||||
wprintf(L"Must use one of: cube, volume, array, cubearray,\n h-cross, v-cross, h-strip, or v-strip\n\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (int iArg = 2; iArg < argc; iArg++)
|
||||
{
|
||||
PWSTR pArg = argv[iArg];
|
||||
|
||||
@ -522,12 +624,69 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
||||
}
|
||||
break;
|
||||
|
||||
case OPT_SRGBI:
|
||||
dwSRGB |= TEX_FILTER_SRGB_IN;
|
||||
break;
|
||||
|
||||
case OPT_SRGBO:
|
||||
dwSRGB |= TEX_FILTER_SRGB_OUT;
|
||||
break;
|
||||
|
||||
case OPT_SRGB:
|
||||
dwSRGB |= TEX_FILTER_SRGB;
|
||||
break;
|
||||
|
||||
case OPT_SEPALPHA:
|
||||
dwFilterOpts |= TEX_FILTER_SEPARATE_ALPHA;
|
||||
break;
|
||||
|
||||
case OPT_OUTPUTFILE:
|
||||
{
|
||||
wcscpy_s(szOutputFile, MAX_PATH, pValue);
|
||||
|
||||
wchar_t ext[_MAX_EXT];
|
||||
_wsplitpath_s(szOutputFile, nullptr, 0, nullptr, 0, nullptr, 0, ext, _MAX_EXT);
|
||||
|
||||
wprintf(L"Ext = %ls\n", ext);
|
||||
|
||||
CrossFileType = LookupByName(ext, g_pExtFileTypes);
|
||||
|
||||
switch (dwCommand)
|
||||
{
|
||||
case CMD_H_CROSS:
|
||||
case CMD_V_CROSS:
|
||||
case CMD_H_STRIP:
|
||||
case CMD_V_STRIP:
|
||||
break;
|
||||
|
||||
default:
|
||||
if (CrossFileType != CODEC_DDS)
|
||||
{
|
||||
wprintf(L"Assembled output file must be a dds\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case OPT_TA_WRAP:
|
||||
if (dwFilterOpts & TEX_FILTER_MIRROR)
|
||||
{
|
||||
wprintf(L"Can't use -wrap and -mirror at same time\n\n");
|
||||
PrintUsage();
|
||||
return 1;
|
||||
}
|
||||
dwFilterOpts |= TEX_FILTER_WRAP;
|
||||
break;
|
||||
|
||||
case OPT_TA_MIRROR:
|
||||
if (dwFilterOpts & TEX_FILTER_WRAP)
|
||||
{
|
||||
wprintf(L"Can't use -wrap and -mirror at same time\n\n");
|
||||
PrintUsage();
|
||||
return 1;
|
||||
}
|
||||
dwFilterOpts |= TEX_FILTER_MIRROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -556,22 +715,23 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (dwOptions & ((1 << OPT_CUBE) | (1 << OPT_VOLUME) | (1 << OPT_ARRAY) | (1 << OPT_CUBEARRAY)))
|
||||
{
|
||||
case (1 << OPT_VOLUME):
|
||||
case (1 << OPT_ARRAY):
|
||||
case (1 << OPT_CUBE):
|
||||
case (1 << OPT_CUBEARRAY):
|
||||
break;
|
||||
|
||||
default:
|
||||
wprintf(L"Must use one of: -cube, -volume, -array, or -cubearray\n\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (~dwOptions & (1 << OPT_NOLOGO))
|
||||
PrintLogo();
|
||||
|
||||
switch (dwCommand)
|
||||
{
|
||||
case CMD_H_CROSS:
|
||||
case CMD_V_CROSS:
|
||||
case CMD_H_STRIP:
|
||||
case CMD_V_STRIP:
|
||||
if (conversion.size() > 1)
|
||||
{
|
||||
wprintf(L"ERROR: cross/strip output only accepts 1 input file\n");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Convert images
|
||||
size_t images = 0;
|
||||
|
||||
@ -588,13 +748,25 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
||||
wprintf(L"\n");
|
||||
else if (!*szOutputFile)
|
||||
{
|
||||
if (_wcsicmp(ext, L".dds") == 0)
|
||||
switch (dwCommand)
|
||||
{
|
||||
wprintf(L"ERROR: Need to specify output file via -o\n");
|
||||
return 1;
|
||||
}
|
||||
case CMD_H_CROSS:
|
||||
case CMD_V_CROSS:
|
||||
case CMD_H_STRIP:
|
||||
case CMD_V_STRIP:
|
||||
_wmakepath_s(szOutputFile, nullptr, nullptr, fname, L".bmp");
|
||||
break;
|
||||
|
||||
_wmakepath_s(szOutputFile, nullptr, nullptr, fname, L".dds");
|
||||
default:
|
||||
if (_wcsicmp(ext, L".dds") == 0)
|
||||
{
|
||||
wprintf(L"ERROR: Need to specify output file via -o\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
_wmakepath_s(szOutputFile, nullptr, nullptr, fname, L".dds");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
wprintf(L"reading %ls", pConv->szSrc);
|
||||
@ -608,57 +780,92 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (_wcsicmp(ext, L".dds") == 0)
|
||||
switch (dwCommand)
|
||||
{
|
||||
hr = LoadFromDDSFile(pConv->szSrc, DDS_FLAGS_NONE, &info, *image.get());
|
||||
if (FAILED(hr))
|
||||
case CMD_H_CROSS:
|
||||
case CMD_V_CROSS:
|
||||
case CMD_H_STRIP:
|
||||
case CMD_V_STRIP:
|
||||
if (_wcsicmp(ext, L".dds") == 0)
|
||||
{
|
||||
wprintf(L" FAILED (%x)\n", hr);
|
||||
return 1;
|
||||
}
|
||||
hr = LoadFromDDSFile(pConv->szSrc, DDS_FLAGS_NONE, &info, *image.get());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
wprintf(L" FAILED (%x)\n", hr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (info.depth > 1
|
||||
|| info.mipLevels > 1
|
||||
|| info.IsCubemap())
|
||||
if (!info.IsCubemap())
|
||||
{
|
||||
wprintf(L"\nERROR: Input must be a cubemap\n");
|
||||
return 1;
|
||||
}
|
||||
else if (info.arraySize != 6)
|
||||
{
|
||||
wprintf(L"\nWARNING: Only the first cubemap in an array is written out as a cross/strip\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wprintf(L"\nERROR: Can't assemble complex surfaces\n");
|
||||
wprintf(L"\nERROR: Input must be a dds of a cubemap\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (_wcsicmp(ext, L".tga") == 0)
|
||||
{
|
||||
hr = LoadFromTGAFile(pConv->szSrc, &info, *image.get());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
wprintf(L" FAILED (%x)\n", hr);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (_wcsicmp(ext, L".hdr") == 0)
|
||||
{
|
||||
hr = LoadFromHDRFile(pConv->szSrc, &info, *image.get());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
wprintf(L" FAILED (%x)\n", hr);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// WIC shares the same filter values for mode and dither
|
||||
static_assert(WIC_FLAGS_DITHER == TEX_FILTER_DITHER, "WIC_FLAGS_* & TEX_FILTER_* should match");
|
||||
static_assert(WIC_FLAGS_DITHER_DIFFUSION == TEX_FILTER_DITHER_DIFFUSION, "WIC_FLAGS_* & TEX_FILTER_* should match");
|
||||
static_assert(WIC_FLAGS_FILTER_POINT == TEX_FILTER_POINT, "WIC_FLAGS_* & TEX_FILTER_* should match");
|
||||
static_assert(WIC_FLAGS_FILTER_LINEAR == TEX_FILTER_LINEAR, "WIC_FLAGS_* & TEX_FILTER_* should match");
|
||||
static_assert(WIC_FLAGS_FILTER_CUBIC == TEX_FILTER_CUBIC, "WIC_FLAGS_* & TEX_FILTER_* should match");
|
||||
static_assert(WIC_FLAGS_FILTER_FANT == TEX_FILTER_FANT, "WIC_FLAGS_* & TEX_FILTER_* should match");
|
||||
break;
|
||||
|
||||
hr = LoadFromWICFile(pConv->szSrc, dwFilter | WIC_FLAGS_ALL_FRAMES, &info, *image.get());
|
||||
if (FAILED(hr))
|
||||
default:
|
||||
if (_wcsicmp(ext, L".dds") == 0)
|
||||
{
|
||||
wprintf(L" FAILED (%x)\n", hr);
|
||||
return 1;
|
||||
hr = LoadFromDDSFile(pConv->szSrc, DDS_FLAGS_NONE, &info, *image.get());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
wprintf(L" FAILED (%x)\n", hr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (info.mipLevels > 1
|
||||
|| info.IsVolumemap()
|
||||
|| info.IsCubemap())
|
||||
{
|
||||
wprintf(L"\nERROR: Can't assemble complex surfaces\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (_wcsicmp(ext, L".tga") == 0)
|
||||
{
|
||||
hr = LoadFromTGAFile(pConv->szSrc, &info, *image.get());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
wprintf(L" FAILED (%x)\n", hr);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (_wcsicmp(ext, L".hdr") == 0)
|
||||
{
|
||||
hr = LoadFromHDRFile(pConv->szSrc, &info, *image.get());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
wprintf(L" FAILED (%x)\n", hr);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// WIC shares the same filter values for mode and dither
|
||||
static_assert(WIC_FLAGS_DITHER == TEX_FILTER_DITHER, "WIC_FLAGS_* & TEX_FILTER_* should match");
|
||||
static_assert(WIC_FLAGS_DITHER_DIFFUSION == TEX_FILTER_DITHER_DIFFUSION, "WIC_FLAGS_* & TEX_FILTER_* should match");
|
||||
static_assert(WIC_FLAGS_FILTER_POINT == TEX_FILTER_POINT, "WIC_FLAGS_* & TEX_FILTER_* should match");
|
||||
static_assert(WIC_FLAGS_FILTER_LINEAR == TEX_FILTER_LINEAR, "WIC_FLAGS_* & TEX_FILTER_* should match");
|
||||
static_assert(WIC_FLAGS_FILTER_CUBIC == TEX_FILTER_CUBIC, "WIC_FLAGS_* & TEX_FILTER_* should match");
|
||||
static_assert(WIC_FLAGS_FILTER_FANT == TEX_FILTER_FANT, "WIC_FLAGS_* & TEX_FILTER_* should match");
|
||||
|
||||
hr = LoadFromWICFile(pConv->szSrc, dwFilter | WIC_FLAGS_ALL_FRAMES, &info, *image.get());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
wprintf(L" FAILED (%x)\n", hr);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
PrintInfo(info);
|
||||
@ -666,6 +873,42 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
||||
// Convert texture
|
||||
fflush(stdout);
|
||||
|
||||
// --- Planar ------------------------------------------------------------------
|
||||
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] (%x)\n", hr);
|
||||
continue;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// --- Decompress --------------------------------------------------------------
|
||||
if (IsCompressed(info.format))
|
||||
{
|
||||
@ -697,12 +940,59 @@ 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.miscFlags2 == tinfo.miscFlags2);
|
||||
assert(info.dimension == tinfo.dimension);
|
||||
|
||||
image.swap(timage);
|
||||
}
|
||||
|
||||
// --- Undo Premultiplied Alpha (if requested) ---------------------------------
|
||||
if ((dwOptions & (DWORD64(1) << OPT_DEMUL_ALPHA))
|
||||
&& HasAlpha(info.format)
|
||||
&& info.format != DXGI_FORMAT_A8_UNORM)
|
||||
{
|
||||
if (info.GetAlphaMode() == TEX_ALPHA_MODE_STRAIGHT)
|
||||
{
|
||||
printf("\nWARNING: Image is already using straight alpha\n");
|
||||
}
|
||||
else if (!info.IsPMAlpha())
|
||||
{
|
||||
printf("\nWARNING: Image is not using premultipled alpha\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
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 = PremultiplyAlpha(img, nimg, info, TEX_PMALPHA_REVERSE | dwSRGB, *timage);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
wprintf(L" FAILED [demultiply alpha] (%x)\n", hr);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto& tinfo = timage->GetMetadata();
|
||||
info.miscFlags2 = tinfo.miscFlags2;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// --- Resize ------------------------------------------------------------------
|
||||
if (!width)
|
||||
{
|
||||
@ -738,7 +1028,6 @@ 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.miscFlags2 == tinfo.miscFlags2);
|
||||
assert(info.format == tinfo.format);
|
||||
assert(info.dimension == tinfo.dimension);
|
||||
|
||||
@ -760,7 +1049,7 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
||||
}
|
||||
|
||||
hr = Convert(image->GetImages(), image->GetImageCount(), image->GetMetadata(), format,
|
||||
dwFilter | dwFilterOpts, TEX_THRESHOLD_DEFAULT, *timage.get());
|
||||
dwFilter | dwFilterOpts | dwSRGB, TEX_THRESHOLD_DEFAULT, *timage.get());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
wprintf(L" FAILED [convert] (%x)\n", hr);
|
||||
@ -778,7 +1067,6 @@ 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.miscFlags2 == tinfo.miscFlags2);
|
||||
assert(info.dimension == tinfo.dimension);
|
||||
|
||||
image.swap(timage);
|
||||
@ -788,32 +1076,198 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
||||
loadedImages.push_back(std::move(image));
|
||||
}
|
||||
|
||||
if (images < 2)
|
||||
switch (dwCommand)
|
||||
{
|
||||
wprintf(L"\nERROR: Need at least 2 images to assemble\n\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (dwOptions & ((1 << OPT_CUBE) | (1 << OPT_VOLUME) | (1 << OPT_ARRAY) | (1 << OPT_CUBEARRAY)))
|
||||
{
|
||||
case (1 << OPT_CUBE):
|
||||
case CMD_CUBE:
|
||||
if (images != 6)
|
||||
{
|
||||
wprintf(L"\nERROR: -cube requires six images to form the faces of the cubemap\n");
|
||||
wprintf(L"\nERROR: cube requires six images to form the faces of the cubemap\n");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case (1 << OPT_CUBEARRAY):
|
||||
case CMD_CUBEARRAY:
|
||||
if ((images < 6) || (images % 6) != 0)
|
||||
{
|
||||
wprintf(L"-cubearray requires a multiple of 6 images to form the faces of the cubemaps\n");
|
||||
wprintf(L"cubearray requires a multiple of 6 images to form the faces of the cubemaps\n");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case CMD_H_CROSS:
|
||||
case CMD_V_CROSS:
|
||||
case CMD_H_STRIP:
|
||||
case CMD_V_STRIP:
|
||||
break;
|
||||
|
||||
default:
|
||||
if (images < 2)
|
||||
{
|
||||
wprintf(L"\nERROR: Need at least 2 images to assemble\n\n");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// --- Create result ---------------------------------------------------------------
|
||||
switch (dwCommand)
|
||||
{
|
||||
case CMD_H_CROSS:
|
||||
case CMD_V_CROSS:
|
||||
case CMD_H_STRIP:
|
||||
case CMD_V_STRIP:
|
||||
{
|
||||
size_t twidth, theight;
|
||||
|
||||
switch (dwCommand)
|
||||
{
|
||||
case CMD_H_CROSS:
|
||||
// posy
|
||||
// negx posz posx negz
|
||||
// negy
|
||||
twidth = width * 4;
|
||||
theight = height * 3;
|
||||
break;
|
||||
|
||||
case CMD_V_CROSS:
|
||||
// posy
|
||||
// posz posx negz
|
||||
// negy
|
||||
// negx
|
||||
twidth = width * 3;
|
||||
theight = height * 4;
|
||||
break;
|
||||
|
||||
case CMD_H_STRIP:
|
||||
twidth = width * 6;
|
||||
theight = height;
|
||||
break;
|
||||
|
||||
case CMD_V_STRIP:
|
||||
twidth = width;
|
||||
theight = height * 6;
|
||||
}
|
||||
|
||||
ScratchImage result;
|
||||
hr = result.Initialize2D(format, twidth, theight, 1, 1);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
wprintf(L"FAILED setting up result image (%x)\n", hr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset(result.GetPixels(), 0, result.GetPixelsSize());
|
||||
|
||||
auto src = loadedImages.cbegin();
|
||||
auto dest = result.GetImage(0, 0, 0);
|
||||
|
||||
for (size_t index = 0; index < 6; ++index)
|
||||
{
|
||||
auto img = (*src)->GetImage(0, index, 0);
|
||||
if (!img)
|
||||
{
|
||||
wprintf(L"FAILED: Unexpected error\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
Rect rect(0, 0, width, height);
|
||||
|
||||
size_t offsetx = 0;
|
||||
size_t offsety = 0;
|
||||
|
||||
switch (dwCommand)
|
||||
{
|
||||
case CMD_H_CROSS:
|
||||
{
|
||||
// posy
|
||||
// negx posz posx negz
|
||||
// negy
|
||||
|
||||
static const size_t s_offsetx[6] = { 2, 0, 1, 1, 1, 3 };
|
||||
static const size_t s_offsety[6] = { 1, 1, 0, 2, 1, 1 };
|
||||
|
||||
offsetx = s_offsetx[index] * width;
|
||||
offsety = s_offsety[index] * height;
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_V_CROSS:
|
||||
{
|
||||
// posy
|
||||
// posz posx negz
|
||||
// negy
|
||||
// negx
|
||||
|
||||
static const size_t s_offsetx[6] = { 1, 1, 1, 1, 0, 2 };
|
||||
static const size_t s_offsety[6] = { 1, 3, 0, 2, 1, 1 };
|
||||
|
||||
offsetx = s_offsetx[index] * width;
|
||||
offsety = s_offsety[index] * height;
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_H_STRIP:
|
||||
// posx, negx, posy, negy, posz, negz
|
||||
offsetx = index * width;
|
||||
break;
|
||||
|
||||
case CMD_V_STRIP:
|
||||
// posx, negx, posy, negy, posz, negz
|
||||
offsety = index * height;
|
||||
break;
|
||||
}
|
||||
|
||||
hr = CopyRectangle(*img, rect, *dest, dwFilter | dwFilterOpts, offsetx, offsety);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
wprintf(L"FAILED building result image (%x)\n", hr);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Write cross/strip
|
||||
wprintf(L"\nWriting %ls ", szOutputFile);
|
||||
PrintInfo(result.GetMetadata());
|
||||
wprintf(L"\n");
|
||||
fflush(stdout);
|
||||
|
||||
if (~dwOptions & (DWORD64(1) << OPT_OVERWRITE))
|
||||
{
|
||||
if (GetFileAttributesW(szOutputFile) != INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
wprintf(L"\nERROR: Output file already exists, use -y to overwrite\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
switch (CrossFileType)
|
||||
{
|
||||
case CODEC_DDS:
|
||||
hr = SaveToDDSFile(*dest, DDS_FLAGS_NONE, szOutputFile);
|
||||
break;
|
||||
|
||||
case CODEC_TGA:
|
||||
hr = SaveToTGAFile(*dest, szOutputFile);
|
||||
break;
|
||||
|
||||
case CODEC_HDR:
|
||||
hr = SaveToHDRFile(*dest, szOutputFile);
|
||||
break;
|
||||
|
||||
default:
|
||||
hr = SaveToWICFile(*dest, WIC_FLAGS_NONE, GetWICCodec(static_cast<WICCodecs>(CrossFileType)), szOutputFile);
|
||||
break;
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
wprintf(L" FAILED (%x)\n", hr);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
std::vector<Image> imageArray;
|
||||
imageArray.reserve(images);
|
||||
@ -831,18 +1285,18 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
||||
}
|
||||
|
||||
ScratchImage result;
|
||||
switch (dwOptions & ((1 << OPT_CUBE) | (1 << OPT_VOLUME) | (1 << OPT_ARRAY) | (1 << OPT_CUBEARRAY)))
|
||||
switch (dwCommand)
|
||||
{
|
||||
case (1 << OPT_VOLUME):
|
||||
case CMD_VOLUME:
|
||||
hr = result.Initialize3DFromImages(&imageArray[0], imageArray.size());
|
||||
break;
|
||||
|
||||
case (1 << OPT_ARRAY):
|
||||
case CMD_ARRAY:
|
||||
hr = result.InitializeArrayFromImages(&imageArray[0], imageArray.size(), (dwOptions & (1 << OPT_USE_DX10)) != 0);
|
||||
break;
|
||||
|
||||
case (1 << OPT_CUBE):
|
||||
case (1 << OPT_CUBEARRAY):
|
||||
case CMD_CUBE:
|
||||
case CMD_CUBEARRAY:
|
||||
hr = result.InitializeCubeFromImages(&imageArray[0], imageArray.size());
|
||||
break;
|
||||
}
|
||||
@ -859,6 +1313,15 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
||||
wprintf(L"\n");
|
||||
fflush(stdout);
|
||||
|
||||
if (~dwOptions & (DWORD64(1) << OPT_OVERWRITE))
|
||||
{
|
||||
if (GetFileAttributesW(szOutputFile) != INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
wprintf(L"\nERROR: Output file already exists, use -y to overwrite\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
hr = SaveToDDSFile(result.GetImages(), result.GetImageCount(), result.GetMetadata(),
|
||||
(dwOptions & (1 << OPT_USE_DX10)) ? (DDS_FLAGS_FORCE_DX10_EXT | DDS_FLAGS_FORCE_DX10_EXT_MISC2) : DDS_FLAGS_NONE,
|
||||
szOutputFile);
|
||||
@ -867,7 +1330,8 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
||||
wprintf(L"\nFAILED (%x)\n", hr);
|
||||
return 1;
|
||||
}
|
||||
wprintf(L"\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user