DirectXTex updated to read & write new miscFlags2 alpha mode metadata for DDS files

- Added helper to see if a texure's alpha channel is all opaque
- Reads and writes DXT2 and DXT4 DDS files
- Updated PremultiplyAlpha function to set miscFlags2 appropriately
- Texconv updated for new feature, "-dx10" switch now allows write of miscFlags2 data
This commit is contained in:
walbourn_cp 2013-03-22 17:52:43 -07:00
parent ee978ad449
commit 0d382fbe25
9 changed files with 341 additions and 74 deletions

View File

@ -169,20 +169,33 @@ extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DX10 =
#define DDS_FLAGS_VOLUME 0x00200000 // DDSCAPS2_VOLUME #define DDS_FLAGS_VOLUME 0x00200000 // DDSCAPS2_VOLUME
// Subset here matches D3D10_RESOURCE_DIMENSION and D3D11_RESOURCE_DIMENSION // Subset here matches D3D10_RESOURCE_DIMENSION and D3D11_RESOURCE_DIMENSION
typedef enum DDS_RESOURCE_DIMENSION enum DDS_RESOURCE_DIMENSION
{ {
DDS_DIMENSION_TEXTURE1D = 2, DDS_DIMENSION_TEXTURE1D = 2,
DDS_DIMENSION_TEXTURE2D = 3, DDS_DIMENSION_TEXTURE2D = 3,
DDS_DIMENSION_TEXTURE3D = 4, DDS_DIMENSION_TEXTURE3D = 4,
} DDS_RESOURCE_DIMENSION; };
// Subset here matches D3D10_RESOURCE_MISC_FLAG and D3D11_RESOURCE_MISC_FLAG // Subset here matches D3D10_RESOURCE_MISC_FLAG and D3D11_RESOURCE_MISC_FLAG
typedef enum DDS_RESOURCE_MISC_FLAG enum DDS_RESOURCE_MISC_FLAG
{ {
DDS_RESOURCE_MISC_TEXTURECUBE = 0x4L, DDS_RESOURCE_MISC_TEXTURECUBE = 0x4L,
} DDS_RESOURCE_MISC_FLAG; };
typedef struct enum DDS_MISC_FLAGS2
{
DDS_MISC_FLAGS2_ALPHA_MODE_MASK = 0x3L,
};
enum DDS_ALPHA_MODE
{
DDS_ALPHA_MODE_STRAIGHT = 0,
DDS_ALPHA_MODE_PREMULTIPLIED = 1,
DDS_ALPHA_MODE_4TH_CHANNEL = 2,
DDS_ALPHA_MODE_OPAQUE = 3,
};
struct DDS_HEADER
{ {
uint32_t dwSize; uint32_t dwSize;
uint32_t dwFlags; uint32_t dwFlags;
@ -198,17 +211,20 @@ typedef struct
uint32_t dwCaps3; uint32_t dwCaps3;
uint32_t dwCaps4; uint32_t dwCaps4;
uint32_t dwReserved2; uint32_t dwReserved2;
} DDS_HEADER; };
typedef struct struct DDS_HEADER_DXT10
{ {
DXGI_FORMAT dxgiFormat; DXGI_FORMAT dxgiFormat;
uint32_t resourceDimension; uint32_t resourceDimension;
uint32_t miscFlag; // see DDS_RESOURCE_MISC_FLAG uint32_t miscFlag; // see DDS_RESOURCE_MISC_FLAG
uint32_t arraySize; uint32_t arraySize;
uint32_t reserved; uint32_t miscFlags2; // see DDS_MISC_FLAGS2
} DDS_HEADER_DXT10; };
#pragma pack(pop) #pragma pack(pop)
static_assert( sizeof(DDS_HEADER) == 124, "DDS Header size mismatch" );
static_assert( sizeof(DDS_HEADER_DXT10) == 20, "DDS DX10 Extended Header size mismatch");
}; // namespace }; // namespace

View File

@ -27,7 +27,7 @@
#include <dxgiformat.h> #include <dxgiformat.h>
#include <d3d11.h> #include <d3d11.h>
#define DIRECTX_TEX_VERSION 101 #define DIRECTX_TEX_VERSION 102
#if defined(_MSC_VER) && (_MSC_VER<1610) && !defined(_In_reads_) #if defined(_MSC_VER) && (_MSC_VER<1610) && !defined(_In_reads_)
#define _Analysis_assume_(exp) #define _Analysis_assume_(exp)
@ -99,6 +99,20 @@ namespace DirectX
TEX_MISC_TEXTURECUBE = 0x4L, TEX_MISC_TEXTURECUBE = 0x4L,
}; };
enum TEX_MISC_FLAG2
{
TEX_MISC2_ALPHA_MODE_MASK = 0x3L,
};
enum TEX_ALPHA_MODE
// Matches DDS_ALPHA_MODE, encoded in MISC_FLAGS2
{
TEX_ALPHA_MODE_STRAIGHT = 0,
TEX_ALPHA_MODE_PREMULTIPLIED = 1,
TEX_ALPHA_MODE_4TH_CHANNEL = 2,
TEX_ALPHA_MODE_OPAQUE = 3,
};
struct TexMetadata struct TexMetadata
{ {
size_t width; size_t width;
@ -107,11 +121,19 @@ namespace DirectX
size_t arraySize; // For cubemap, this is a multiple of 6 size_t arraySize; // For cubemap, this is a multiple of 6
size_t mipLevels; size_t mipLevels;
uint32_t miscFlags; uint32_t miscFlags;
uint32_t miscFlags2;
DXGI_FORMAT format; DXGI_FORMAT format;
TEX_DIMENSION dimension; TEX_DIMENSION dimension;
size_t ComputeIndex( _In_ size_t mip, _In_ size_t item, _In_ size_t slice ) const; size_t ComputeIndex( _In_ size_t mip, _In_ size_t item, _In_ size_t slice ) const;
// Returns size_t(-1) to indicate an out-of-range error // Returns size_t(-1) to indicate an out-of-range error
bool IsCubemap() const { return (miscFlags & TEX_MISC_TEXTURECUBE) != 0; }
// Helpers for miscFlags
bool IsPMAlpha() const { return ((miscFlags2 & TEX_MISC2_ALPHA_MODE_MASK) == TEX_ALPHA_MODE_PREMULTIPLIED) != 0; }
void SetAlphaMode( TEX_ALPHA_MODE mode ) { miscFlags2 = (miscFlags2 & ~TEX_MISC2_ALPHA_MODE_MASK) | static_cast<uint32_t>(mode); }
// Helpers for miscFlags2
}; };
enum DDS_FLAGS enum DDS_FLAGS
@ -135,6 +157,9 @@ namespace DirectX
DDS_FLAGS_FORCE_DX10_EXT = 0x10000, DDS_FLAGS_FORCE_DX10_EXT = 0x10000,
// Always use the 'DX10' header extension for DDS writer (i.e. don't try to write DX9 compatible DDS files) // Always use the 'DX10' header extension for DDS writer (i.e. don't try to write DX9 compatible DDS files)
DDS_FLAGS_FORCE_DX10_EXT_MISC2 = 0x20000,
// DDS_FLAGS_FORCE_DX10_EXT including miscFlags2 information (result may not be compatible with D3DX10 or D3DX11)
}; };
enum WIC_FLAGS enum WIC_FLAGS
@ -227,6 +252,8 @@ namespace DirectX
uint8_t* GetPixels() const { return _memory; } uint8_t* GetPixels() const { return _memory; }
size_t GetPixelsSize() const { return _size; } size_t GetPixelsSize() const { return _size; }
bool IsAlphaAllOpaque() const;
private: private:
size_t _nimages; size_t _nimages;
size_t _size; size_t _size;

View File

@ -189,6 +189,9 @@ inline bool HasAlpha( DXGI_FORMAT fmt )
case DXGI_FORMAT_R8G8B8A8_SNORM: case DXGI_FORMAT_R8G8B8A8_SNORM:
case DXGI_FORMAT_R8G8B8A8_SINT: case DXGI_FORMAT_R8G8B8A8_SINT:
case DXGI_FORMAT_A8_UNORM: case DXGI_FORMAT_A8_UNORM:
case DXGI_FORMAT_BC1_TYPELESS:
case DXGI_FORMAT_BC1_UNORM:
case DXGI_FORMAT_BC1_UNORM_SRGB:
case DXGI_FORMAT_BC2_TYPELESS: case DXGI_FORMAT_BC2_TYPELESS:
case DXGI_FORMAT_BC2_UNORM: case DXGI_FORMAT_BC2_UNORM:
case DXGI_FORMAT_BC2_UNORM_SRGB: case DXGI_FORMAT_BC2_UNORM_SRGB:

View File

@ -426,6 +426,85 @@ static HRESULT _DecompressBC( _In_ const Image& cImage, _In_ const Image& result
} }
//-------------------------------------------------------------------------------------
bool _IsAlphaAllOpaqueBC( _In_ const Image& cImage )
{
if ( !cImage.pixels )
return false;
// Image must be a multiple of 4 (degenerate cases of 1x1, 1x2, 2x1, and 2x2 are allowed)
size_t width = cImage.width;
if ( (width % 4) != 0 )
{
if ( width != 1 && width != 2 )
return false;
}
size_t height = cImage.height;
if ( (height % 4) != 0 )
{
if ( height != 1 && height != 2 )
return false;
}
// Promote "typeless" BC formats
DXGI_FORMAT cformat;
switch( cImage.format )
{
case DXGI_FORMAT_BC1_TYPELESS: cformat = DXGI_FORMAT_BC1_UNORM; break;
case DXGI_FORMAT_BC2_TYPELESS: cformat = DXGI_FORMAT_BC2_UNORM; break;
case DXGI_FORMAT_BC3_TYPELESS: cformat = DXGI_FORMAT_BC3_UNORM; break;
case DXGI_FORMAT_BC7_TYPELESS: cformat = DXGI_FORMAT_BC7_UNORM; break;
default: cformat = cImage.format; break;
}
// Determine BC format decoder
BC_DECODE pfDecode;
size_t sbpp;
switch(cformat)
{
case DXGI_FORMAT_BC1_UNORM:
case DXGI_FORMAT_BC1_UNORM_SRGB: pfDecode = D3DXDecodeBC1; sbpp = 8; break;
case DXGI_FORMAT_BC2_UNORM:
case DXGI_FORMAT_BC2_UNORM_SRGB: pfDecode = D3DXDecodeBC2; sbpp = 16; break;
case DXGI_FORMAT_BC3_UNORM:
case DXGI_FORMAT_BC3_UNORM_SRGB: pfDecode = D3DXDecodeBC3; sbpp = 16; break;
case DXGI_FORMAT_BC7_UNORM:
case DXGI_FORMAT_BC7_UNORM_SRGB: pfDecode = D3DXDecodeBC7; sbpp = 16; break;
default:
// BC4, BC5, and BC6 don't have alpha channels
return false;
}
// Scan blocks for non-opaque alpha
static const XMVECTORF32 threshold = { 0.99f, 0.99f, 0.99f, 0.99f };
XMVECTOR temp[16];
const uint8_t *pPixels = cImage.pixels;
for( size_t h=0; h < cImage.height; h += 4 )
{
const uint8_t *ptr = pPixels;
for( size_t count = 0; count < cImage.rowPitch; count += sbpp )
{
pfDecode( temp, ptr );
for( size_t j = 0; j < 16; ++j )
{
XMVECTOR alpha = XMVectorSplatW( temp[j] );
if ( XMVector4Less( alpha, threshold ) )
return false;
}
ptr += sbpp;
}
pPixels += cImage.rowPitch;
}
return true;
}
//===================================================================================== //=====================================================================================
// Entry-points // Entry-points
//===================================================================================== //=====================================================================================

View File

@ -236,7 +236,7 @@ bool IsSupportedTexture( ID3D11Device* pDevice, const TexMetadata& metadata )
break; break;
case TEX_DIMENSION_TEXTURE2D: case TEX_DIMENSION_TEXTURE2D:
if ( metadata.miscFlags & TEX_MISC_TEXTURECUBE ) if ( metadata.IsCubemap() )
{ {
if ( !(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURECUBE) ) if ( !(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURECUBE) )
return false; return false;
@ -505,7 +505,7 @@ HRESULT CreateTextureEx( ID3D11Device* pDevice, const Image* srcImages, size_t n
desc.Usage = usage; desc.Usage = usage;
desc.BindFlags = bindFlags; desc.BindFlags = bindFlags;
desc.CPUAccessFlags = cpuAccessFlags; desc.CPUAccessFlags = cpuAccessFlags;
if (metadata.miscFlags & TEX_MISC_TEXTURECUBE) if ( metadata.IsCubemap() )
desc.MiscFlags = miscFlags | D3D11_RESOURCE_MISC_TEXTURECUBE; desc.MiscFlags = miscFlags | D3D11_RESOURCE_MISC_TEXTURECUBE;
else else
desc.MiscFlags = miscFlags & ~D3D11_RESOURCE_MISC_TEXTURECUBE; desc.MiscFlags = miscFlags & ~D3D11_RESOURCE_MISC_TEXTURECUBE;
@ -589,7 +589,7 @@ HRESULT CreateShaderResourceViewEx( ID3D11Device* pDevice, const Image* srcImage
break; break;
case TEX_DIMENSION_TEXTURE2D: case TEX_DIMENSION_TEXTURE2D:
if ( metadata.miscFlags & TEX_MISC_TEXTURECUBE ) if ( metadata.IsCubemap() )
{ {
if (metadata.arraySize > 6) if (metadata.arraySize > 6)
{ {
@ -685,6 +685,7 @@ HRESULT CaptureTexture( ID3D11Device* pDevice, ID3D11DeviceContext* pContext, ID
mdata.arraySize = desc.ArraySize; mdata.arraySize = desc.ArraySize;
mdata.mipLevels = desc.MipLevels; mdata.mipLevels = desc.MipLevels;
mdata.miscFlags = 0; mdata.miscFlags = 0;
mdata.miscFlags2 = 0;
mdata.format = desc.Format; mdata.format = desc.Format;
mdata.dimension = TEX_DIMENSION_TEXTURE1D; mdata.dimension = TEX_DIMENSION_TEXTURE1D;
@ -786,6 +787,7 @@ HRESULT CaptureTexture( ID3D11Device* pDevice, ID3D11DeviceContext* pContext, ID
mdata.arraySize = desc.ArraySize; mdata.arraySize = desc.ArraySize;
mdata.mipLevels = desc.MipLevels; mdata.mipLevels = desc.MipLevels;
mdata.miscFlags = (desc.MiscFlags & D3D11_RESOURCE_MISC_TEXTURECUBE) ? TEX_MISC_TEXTURECUBE : 0; mdata.miscFlags = (desc.MiscFlags & D3D11_RESOURCE_MISC_TEXTURECUBE) ? TEX_MISC_TEXTURECUBE : 0;
mdata.miscFlags2 = 0;
mdata.format = desc.Format; mdata.format = desc.Format;
mdata.dimension = TEX_DIMENSION_TEXTURE2D; mdata.dimension = TEX_DIMENSION_TEXTURE2D;
@ -830,6 +832,7 @@ HRESULT CaptureTexture( ID3D11Device* pDevice, ID3D11DeviceContext* pContext, ID
mdata.arraySize = 1; mdata.arraySize = 1;
mdata.mipLevels = desc.MipLevels; mdata.mipLevels = desc.MipLevels;
mdata.miscFlags = 0; mdata.miscFlags = 0;
mdata.miscFlags2 = 0;
mdata.format = desc.Format; mdata.format = desc.Format;
mdata.dimension = TEX_DIMENSION_TEXTURE3D; mdata.dimension = TEX_DIMENSION_TEXTURE3D;

View File

@ -39,6 +39,7 @@ enum CONVERSION_FLAGS
CONV_FLAGS_8332 = 0x400, // Source is a 8:3:3:2 (16bpp) format CONV_FLAGS_8332 = 0x400, // Source is a 8:3:3:2 (16bpp) format
CONV_FLAGS_A8P8 = 0x800, // Has an 8-bit palette with an alpha channel CONV_FLAGS_A8P8 = 0x800, // Has an 8-bit palette with an alpha channel
CONV_FLAGS_DX10 = 0x10000, // Has the 'DX10' extension header CONV_FLAGS_DX10 = 0x10000, // Has the 'DX10' extension header
CONV_FLAGS_PMALPHA = 0x20000, // Contains premultiplied alpha data
}; };
struct LegacyDDS struct LegacyDDS
@ -54,8 +55,8 @@ const LegacyDDS g_LegacyDDSMap[] =
{ DXGI_FORMAT_BC2_UNORM, CONV_FLAGS_NONE, DDSPF_DXT3 }, // D3DFMT_DXT3 { DXGI_FORMAT_BC2_UNORM, CONV_FLAGS_NONE, DDSPF_DXT3 }, // D3DFMT_DXT3
{ DXGI_FORMAT_BC3_UNORM, CONV_FLAGS_NONE, DDSPF_DXT5 }, // D3DFMT_DXT5 { DXGI_FORMAT_BC3_UNORM, CONV_FLAGS_NONE, DDSPF_DXT5 }, // D3DFMT_DXT5
{ DXGI_FORMAT_BC2_UNORM, CONV_FLAGS_NONE, DDSPF_DXT2 }, // D3DFMT_DXT2 (ignore premultiply) { DXGI_FORMAT_BC2_UNORM, CONV_FLAGS_PMALPHA, DDSPF_DXT2 }, // D3DFMT_DXT2
{ DXGI_FORMAT_BC3_UNORM, CONV_FLAGS_NONE, DDSPF_DXT4 }, // D3DFMT_DXT4 (ignore premultiply) { DXGI_FORMAT_BC3_UNORM, CONV_FLAGS_PMALPHA, DDSPF_DXT4 }, // D3DFMT_DXT4
{ DXGI_FORMAT_BC4_UNORM, CONV_FLAGS_NONE, DDSPF_BC4_UNORM }, { DXGI_FORMAT_BC4_UNORM, CONV_FLAGS_NONE, DDSPF_BC4_UNORM },
{ DXGI_FORMAT_BC4_SNORM, CONV_FLAGS_NONE, DDSPF_BC4_SNORM }, { DXGI_FORMAT_BC4_SNORM, CONV_FLAGS_NONE, DDSPF_BC4_SNORM },
@ -146,7 +147,7 @@ const LegacyDDS g_LegacyDDSMap[] =
// ZBuffer D3DFMT_D16_LOCKABLE // ZBuffer D3DFMT_D16_LOCKABLE
// FourCC 82 D3DFMT_D32F_LOCKABLE // FourCC 82 D3DFMT_D32F_LOCKABLE
static DXGI_FORMAT _GetDXGIFormat( const DDS_PIXELFORMAT& ddpf, DWORD flags, _Inout_opt_ DWORD* convFlags ) static DXGI_FORMAT _GetDXGIFormat( const DDS_PIXELFORMAT& ddpf, DWORD flags, _Inout_ DWORD& convFlags )
{ {
const size_t MAP_SIZE = sizeof(g_LegacyDDSMap) / sizeof(LegacyDDS); const size_t MAP_SIZE = sizeof(g_LegacyDDSMap) / sizeof(LegacyDDS);
size_t index = 0; size_t index = 0;
@ -192,8 +193,7 @@ static DXGI_FORMAT _GetDXGIFormat( const DDS_PIXELFORMAT& ddpf, DWORD flags, _In
cflags ^= CONV_FLAGS_SWIZZLE; cflags ^= CONV_FLAGS_SWIZZLE;
} }
if ( convFlags ) convFlags = cflags;
*convFlags = cflags;
return format; return format;
} }
@ -203,7 +203,7 @@ static DXGI_FORMAT _GetDXGIFormat( const DDS_PIXELFORMAT& ddpf, DWORD flags, _In
// Decodes DDS header including optional DX10 extended header // Decodes DDS header including optional DX10 extended header
//------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------
static HRESULT _DecodeDDSHeader( _In_reads_bytes_(size) LPCVOID pSource, size_t size, DWORD flags, _Out_ TexMetadata& metadata, static HRESULT _DecodeDDSHeader( _In_reads_bytes_(size) LPCVOID pSource, size_t size, DWORD flags, _Out_ TexMetadata& metadata,
_Inout_opt_ DWORD* convFlags ) _Inout_ DWORD& convFlags )
{ {
if ( !pSource ) if ( !pSource )
return E_INVALIDARG; return E_INVALIDARG;
@ -247,8 +247,7 @@ static HRESULT _DecodeDDSHeader( _In_reads_bytes_(size) LPCVOID pSource, size_t
} }
const DDS_HEADER_DXT10* d3d10ext = reinterpret_cast<const DDS_HEADER_DXT10*>( (const uint8_t*)pSource + sizeof( uint32_t ) + sizeof(DDS_HEADER) ); const DDS_HEADER_DXT10* d3d10ext = reinterpret_cast<const DDS_HEADER_DXT10*>( (const uint8_t*)pSource + sizeof( uint32_t ) + sizeof(DDS_HEADER) );
if ( convFlags ) convFlags |= CONV_FLAGS_DX10;
*convFlags |= CONV_FLAGS_DX10;
metadata.arraySize = d3d10ext->arraySize; metadata.arraySize = d3d10ext->arraySize;
if ( metadata.arraySize == 0 ) if ( metadata.arraySize == 0 )
@ -262,6 +261,10 @@ static HRESULT _DecodeDDSHeader( _In_reads_bytes_(size) LPCVOID pSource, size_t
HRESULT_FROM_WIN32( ERROR_INVALID_DATA ); HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
} }
static_assert( TEX_MISC_TEXTURECUBE == DDS_RESOURCE_MISC_TEXTURECUBE, "DDS header mismatch");
metadata.miscFlags = d3d10ext->miscFlag & ~TEX_MISC_TEXTURECUBE;
switch ( d3d10ext->resourceDimension ) switch ( d3d10ext->resourceDimension )
{ {
case DDS_DIMENSION_TEXTURE1D: case DDS_DIMENSION_TEXTURE1D:
@ -309,6 +312,15 @@ static HRESULT _DecodeDDSHeader( _In_reads_bytes_(size) LPCVOID pSource, size_t
default: default:
return HRESULT_FROM_WIN32( ERROR_INVALID_DATA ); return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
} }
static_assert( TEX_MISC2_ALPHA_MODE_MASK == DDS_MISC_FLAGS2_ALPHA_MODE_MASK, "DDS header mismatch");
static_assert( TEX_ALPHA_MODE_STRAIGHT == DDS_ALPHA_MODE_STRAIGHT, "DDS header mismatch");
static_assert( TEX_ALPHA_MODE_PREMULTIPLIED == DDS_ALPHA_MODE_PREMULTIPLIED, "DDS header mismatch");
static_assert( TEX_ALPHA_MODE_4TH_CHANNEL == DDS_ALPHA_MODE_4TH_CHANNEL, "DDS header mismatch");
static_assert( TEX_ALPHA_MODE_OPAQUE == DDS_ALPHA_MODE_OPAQUE, "DDS header mismatch");
metadata.miscFlags2 = d3d10ext->miscFlags2;
} }
else else
{ {
@ -345,6 +357,9 @@ static HRESULT _DecodeDDSHeader( _In_reads_bytes_(size) LPCVOID pSource, size_t
if ( metadata.format == DXGI_FORMAT_UNKNOWN ) if ( metadata.format == DXGI_FORMAT_UNKNOWN )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
if ( convFlags & CONV_FLAGS_PMALPHA )
metadata.miscFlags2 |= TEX_ALPHA_MODE_PREMULTIPLIED;
} }
// Special flag for handling BGR DXGI 1.1 formats // Special flag for handling BGR DXGI 1.1 formats
@ -354,38 +369,32 @@ static HRESULT _DecodeDDSHeader( _In_reads_bytes_(size) LPCVOID pSource, size_t
{ {
case DXGI_FORMAT_B8G8R8A8_UNORM: case DXGI_FORMAT_B8G8R8A8_UNORM:
metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM; metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM;
if ( convFlags ) convFlags |= CONV_FLAGS_SWIZZLE;
*convFlags |= CONV_FLAGS_SWIZZLE;
break; break;
case DXGI_FORMAT_B8G8R8X8_UNORM: case DXGI_FORMAT_B8G8R8X8_UNORM:
metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM; metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM;
if ( convFlags ) convFlags |= CONV_FLAGS_SWIZZLE | CONV_FLAGS_NOALPHA;
*convFlags |= CONV_FLAGS_SWIZZLE | CONV_FLAGS_NOALPHA;
break; break;
case DXGI_FORMAT_B8G8R8A8_TYPELESS: case DXGI_FORMAT_B8G8R8A8_TYPELESS:
metadata.format = DXGI_FORMAT_R8G8B8A8_TYPELESS; metadata.format = DXGI_FORMAT_R8G8B8A8_TYPELESS;
if ( convFlags ) convFlags |= CONV_FLAGS_SWIZZLE;
*convFlags |= CONV_FLAGS_SWIZZLE;
break; break;
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
if ( convFlags ) convFlags |= CONV_FLAGS_SWIZZLE;
*convFlags |= CONV_FLAGS_SWIZZLE;
break; break;
case DXGI_FORMAT_B8G8R8X8_TYPELESS: case DXGI_FORMAT_B8G8R8X8_TYPELESS:
metadata.format = DXGI_FORMAT_R8G8B8A8_TYPELESS; metadata.format = DXGI_FORMAT_R8G8B8A8_TYPELESS;
if ( convFlags ) convFlags |= CONV_FLAGS_SWIZZLE | CONV_FLAGS_NOALPHA;
*convFlags |= CONV_FLAGS_SWIZZLE | CONV_FLAGS_NOALPHA;
break; break;
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
if ( convFlags ) convFlags |= CONV_FLAGS_SWIZZLE | CONV_FLAGS_NOALPHA;
*convFlags |= CONV_FLAGS_SWIZZLE | CONV_FLAGS_NOALPHA;
break; break;
} }
} }
@ -401,12 +410,9 @@ static HRESULT _DecodeDDSHeader( _In_reads_bytes_(size) LPCVOID pSource, size_t
case DXGI_FORMAT_B4G4R4A4_UNORM: case DXGI_FORMAT_B4G4R4A4_UNORM:
#endif #endif
metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM; metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM;
if ( convFlags ) convFlags |= CONV_FLAGS_EXPAND;
{ if ( metadata.format == DXGI_FORMAT_B5G6R5_UNORM )
*convFlags |= CONV_FLAGS_EXPAND; convFlags |= CONV_FLAGS_NOALPHA;
if ( metadata.format == DXGI_FORMAT_B5G6R5_UNORM )
*convFlags |= CONV_FLAGS_NOALPHA;
}
} }
} }
@ -425,12 +431,18 @@ HRESULT _EncodeDDSHeader( const TexMetadata& metadata, DWORD flags,
if ( metadata.arraySize > 1 ) if ( metadata.arraySize > 1 )
{ {
if ( (metadata.arraySize != 6) || (metadata.dimension != TEX_DIMENSION_TEXTURE2D) || !(metadata.miscFlags & TEX_MISC_TEXTURECUBE) ) if ( (metadata.arraySize != 6) || (metadata.dimension != TEX_DIMENSION_TEXTURE2D) || !(metadata.IsCubemap()) )
{ {
// Texture1D arrays, Texture2D arrays, and Cubemap arrays must be stored using 'DX10' extended header
flags |= DDS_FLAGS_FORCE_DX10_EXT; flags |= DDS_FLAGS_FORCE_DX10_EXT;
} }
} }
if ( flags & DDS_FLAGS_FORCE_DX10_EXT_MISC2 )
{
flags |= DDS_FLAGS_FORCE_DX10_EXT;
}
DDS_PIXELFORMAT ddpf = { 0 }; DDS_PIXELFORMAT ddpf = { 0 };
if ( !(flags & DDS_FLAGS_FORCE_DX10_EXT) ) if ( !(flags & DDS_FLAGS_FORCE_DX10_EXT) )
{ {
@ -445,8 +457,8 @@ HRESULT _EncodeDDSHeader( const TexMetadata& metadata, DWORD flags,
case DXGI_FORMAT_R8G8_B8G8_UNORM: memcpy_s( &ddpf, sizeof(ddpf), &DDSPF_R8G8_B8G8, sizeof(DDS_PIXELFORMAT) ); break; case DXGI_FORMAT_R8G8_B8G8_UNORM: memcpy_s( &ddpf, sizeof(ddpf), &DDSPF_R8G8_B8G8, sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_G8R8_G8B8_UNORM: memcpy_s( &ddpf, sizeof(ddpf), &DDSPF_G8R8_G8B8, sizeof(DDS_PIXELFORMAT) ); break; case DXGI_FORMAT_G8R8_G8B8_UNORM: memcpy_s( &ddpf, sizeof(ddpf), &DDSPF_G8R8_G8B8, sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_BC1_UNORM: memcpy_s( &ddpf, sizeof(ddpf), &DDSPF_DXT1, sizeof(DDS_PIXELFORMAT) ); break; case DXGI_FORMAT_BC1_UNORM: memcpy_s( &ddpf, sizeof(ddpf), &DDSPF_DXT1, sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_BC2_UNORM: memcpy_s( &ddpf, sizeof(ddpf), &DDSPF_DXT3, sizeof(DDS_PIXELFORMAT) ); break; case DXGI_FORMAT_BC2_UNORM: memcpy_s( &ddpf, sizeof(ddpf), metadata.IsPMAlpha() ? (&DDSPF_DXT2) : (&DDSPF_DXT3), sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_BC3_UNORM: memcpy_s( &ddpf, sizeof(ddpf), &DDSPF_DXT5, sizeof(DDS_PIXELFORMAT) ); break; case DXGI_FORMAT_BC3_UNORM: memcpy_s( &ddpf, sizeof(ddpf), metadata.IsPMAlpha() ? (&DDSPF_DXT4) : (&DDSPF_DXT5), sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_BC4_UNORM: memcpy_s( &ddpf, sizeof(ddpf), &DDSPF_BC4_UNORM, sizeof(DDS_PIXELFORMAT) ); break; case DXGI_FORMAT_BC4_UNORM: memcpy_s( &ddpf, sizeof(ddpf), &DDSPF_BC4_UNORM, sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_BC4_SNORM: memcpy_s( &ddpf, sizeof(ddpf), &DDSPF_BC4_SNORM, sizeof(DDS_PIXELFORMAT) ); break; case DXGI_FORMAT_BC4_SNORM: memcpy_s( &ddpf, sizeof(ddpf), &DDSPF_BC4_SNORM, sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_BC5_UNORM: memcpy_s( &ddpf, sizeof(ddpf), &DDSPF_BC5_UNORM, sizeof(DDS_PIXELFORMAT) ); break; case DXGI_FORMAT_BC5_UNORM: memcpy_s( &ddpf, sizeof(ddpf), &DDSPF_BC5_UNORM, sizeof(DDS_PIXELFORMAT) ); break;
@ -547,7 +559,7 @@ HRESULT _EncodeDDSHeader( const TexMetadata& metadata, DWORD flags,
header->dwWidth = static_cast<uint32_t>( metadata.width ); header->dwWidth = static_cast<uint32_t>( metadata.width );
header->dwDepth = 1; header->dwDepth = 1;
if ( metadata.miscFlags & TEX_MISC_TEXTURECUBE ) if ( metadata.IsCubemap() )
{ {
header->dwCaps |= DDS_SURFACE_FLAGS_CUBEMAP; header->dwCaps |= DDS_SURFACE_FLAGS_CUBEMAP;
header->dwCaps2 |= DDS_CUBEMAP_ALLFACES; header->dwCaps2 |= DDS_CUBEMAP_ALLFACES;
@ -609,6 +621,10 @@ HRESULT _EncodeDDSHeader( const TexMetadata& metadata, DWORD flags,
return E_INVALIDARG; return E_INVALIDARG;
#endif #endif
static_assert( TEX_MISC_TEXTURECUBE == DDS_RESOURCE_MISC_TEXTURECUBE, "DDS header mismatch");
ext->miscFlag = metadata.miscFlags & ~TEX_MISC_TEXTURECUBE;
if ( metadata.miscFlags & TEX_MISC_TEXTURECUBE ) if ( metadata.miscFlags & TEX_MISC_TEXTURECUBE )
{ {
ext->miscFlag |= TEX_MISC_TEXTURECUBE; ext->miscFlag |= TEX_MISC_TEXTURECUBE;
@ -619,6 +635,19 @@ HRESULT _EncodeDDSHeader( const TexMetadata& metadata, DWORD flags,
{ {
ext->arraySize = static_cast<UINT>( metadata.arraySize ); ext->arraySize = static_cast<UINT>( metadata.arraySize );
} }
static_assert( TEX_MISC2_ALPHA_MODE_MASK == DDS_MISC_FLAGS2_ALPHA_MODE_MASK, "DDS header mismatch");
static_assert( TEX_ALPHA_MODE_STRAIGHT == DDS_ALPHA_MODE_STRAIGHT, "DDS header mismatch");
static_assert( TEX_ALPHA_MODE_PREMULTIPLIED == DDS_ALPHA_MODE_PREMULTIPLIED, "DDS header mismatch");
static_assert( TEX_ALPHA_MODE_4TH_CHANNEL == DDS_ALPHA_MODE_4TH_CHANNEL, "DDS header mismatch");
static_assert( TEX_ALPHA_MODE_OPAQUE == DDS_ALPHA_MODE_OPAQUE, "DDS header mismatch");
if ( flags & DDS_FLAGS_FORCE_DX10_EXT_MISC2 )
{
// This was formerly 'reserved'. D3DX10 and D3DX11 will fail if this value is anything other than 0
ext->miscFlags2 = metadata.miscFlags2;
}
} }
else else
{ {
@ -891,7 +920,7 @@ static HRESULT _CopyImage( _In_reads_bytes_(size) const void* pPixels, _In_ size
if ( !size ) if ( !size )
return E_FAIL; return E_FAIL;
if ( convFlags & CONV_FLAGS_EXPAND ) if ( convFlags & CONV_FLAGS_EXPAND )
{ {
if ( convFlags & CONV_FLAGS_888 ) if ( convFlags & CONV_FLAGS_888 )
@ -1154,7 +1183,8 @@ HRESULT GetMetadataFromDDSMemory( LPCVOID pSource, size_t size, DWORD flags, Tex
if ( !pSource || size == 0 ) if ( !pSource || size == 0 )
return E_INVALIDARG; return E_INVALIDARG;
return _DecodeDDSHeader( pSource, size, flags, metadata, 0 ); DWORD convFlags = 0;
return _DecodeDDSHeader( pSource, size, flags, metadata, convFlags );
} }
_Use_decl_annotations_ _Use_decl_annotations_
@ -1213,7 +1243,8 @@ HRESULT GetMetadataFromDDSFile( LPCWSTR szFile, DWORD flags, TexMetadata& metada
return HRESULT_FROM_WIN32( GetLastError() ); return HRESULT_FROM_WIN32( GetLastError() );
} }
return _DecodeDDSHeader( header, bytesRead, flags, metadata, 0 ); DWORD convFlags = 0;
return _DecodeDDSHeader( header, bytesRead, flags, metadata, convFlags );
} }
@ -1230,7 +1261,7 @@ HRESULT LoadFromDDSMemory( LPCVOID pSource, size_t size, DWORD flags, TexMetadat
DWORD convFlags = 0; DWORD convFlags = 0;
TexMetadata mdata; TexMetadata mdata;
HRESULT hr = _DecodeDDSHeader( pSource, size, flags, mdata, &convFlags ); HRESULT hr = _DecodeDDSHeader( pSource, size, flags, mdata, convFlags );
if ( FAILED(hr) ) if ( FAILED(hr) )
return hr; return hr;
@ -1334,7 +1365,7 @@ HRESULT LoadFromDDSFile( LPCWSTR szFile, DWORD flags, TexMetadata* metadata, Scr
DWORD convFlags = 0; DWORD convFlags = 0;
TexMetadata mdata; TexMetadata mdata;
HRESULT hr = _DecodeDDSHeader( header, bytesRead, flags, mdata, &convFlags ); HRESULT hr = _DecodeDDSHeader( header, bytesRead, flags, mdata, convFlags );
if ( FAILED(hr) ) if ( FAILED(hr) )
return hr; return hr;

View File

@ -20,6 +20,7 @@ namespace DirectX
extern bool _CalculateMipLevels( _In_ size_t width, _In_ size_t height, _Inout_ size_t& mipLevels ); extern bool _CalculateMipLevels( _In_ size_t width, _In_ size_t height, _Inout_ size_t& mipLevels );
extern bool _CalculateMipLevels3D( _In_ size_t width, _In_ size_t height, _In_ size_t depth, _Inout_ size_t& mipLevels ); extern bool _CalculateMipLevels3D( _In_ size_t width, _In_ size_t height, _In_ size_t depth, _Inout_ size_t& mipLevels );
extern bool _IsAlphaAllOpaqueBC( _In_ const Image& cImage );
//------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------
// Determines number of image array entries and pixel size // Determines number of image array entries and pixel size
@ -253,7 +254,7 @@ HRESULT ScratchImage::Initialize( const TexMetadata& mdata )
if ( !mdata.width || !mdata.height || mdata.depth != 1 || !mdata.arraySize ) if ( !mdata.width || !mdata.height || mdata.depth != 1 || !mdata.arraySize )
return E_INVALIDARG; return E_INVALIDARG;
if ( mdata.miscFlags & TEX_MISC_TEXTURECUBE ) if ( mdata.IsCubemap() )
{ {
if ( (mdata.arraySize % 6) != 0 ) if ( (mdata.arraySize % 6) != 0 )
return E_INVALIDARG; return E_INVALIDARG;
@ -282,7 +283,8 @@ HRESULT ScratchImage::Initialize( const TexMetadata& mdata )
_metadata.depth = mdata.depth; _metadata.depth = mdata.depth;
_metadata.arraySize = mdata.arraySize; _metadata.arraySize = mdata.arraySize;
_metadata.mipLevels = mipLevels; _metadata.mipLevels = mipLevels;
_metadata.miscFlags = mdata.miscFlags & TEX_MISC_TEXTURECUBE; _metadata.miscFlags = mdata.miscFlags;
_metadata.miscFlags2 = mdata.miscFlags2;
_metadata.format = mdata.format; _metadata.format = mdata.format;
_metadata.dimension = mdata.dimension; _metadata.dimension = mdata.dimension;
@ -345,6 +347,7 @@ HRESULT ScratchImage::Initialize2D( DXGI_FORMAT fmt, size_t width, size_t height
_metadata.arraySize = arraySize; _metadata.arraySize = arraySize;
_metadata.mipLevels = mipLevels; _metadata.mipLevels = mipLevels;
_metadata.miscFlags = 0; _metadata.miscFlags = 0;
_metadata.miscFlags2 = 0;
_metadata.format = fmt; _metadata.format = fmt;
_metadata.dimension = TEX_DIMENSION_TEXTURE2D; _metadata.dimension = TEX_DIMENSION_TEXTURE2D;
@ -391,6 +394,7 @@ HRESULT ScratchImage::Initialize3D( DXGI_FORMAT fmt, size_t width, size_t height
_metadata.arraySize = 1; // Direct3D 10.x/11 does not support arrays of 3D textures _metadata.arraySize = 1; // Direct3D 10.x/11 does not support arrays of 3D textures
_metadata.mipLevels = mipLevels; _metadata.mipLevels = mipLevels;
_metadata.miscFlags = 0; _metadata.miscFlags = 0;
_metadata.miscFlags2 = 0;
_metadata.format = fmt; _metadata.format = fmt;
_metadata.dimension = TEX_DIMENSION_TEXTURE3D; _metadata.dimension = TEX_DIMENSION_TEXTURE3D;
@ -684,4 +688,54 @@ const Image* ScratchImage::GetImage(size_t mip, size_t item, size_t slice) const
return &_image[index]; return &_image[index];
} }
bool ScratchImage::IsAlphaAllOpaque() const
{
if ( !HasAlpha( _metadata.format ) )
return true;
if ( IsCompressed( _metadata.format ) )
{
for( size_t index = 0; index < _nimages; ++index )
{
if ( !_IsAlphaAllOpaqueBC( _image[ index ] ) )
return false;
}
}
else
{
ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*_metadata.width), 16 ) ) );
if ( !scanline )
return false;
static const XMVECTORF32 threshold = { 0.99f, 0.99f, 0.99f, 0.99f };
for( size_t index = 0; index < _nimages; ++index )
{
const Image& img = _image[ index ];
const uint8_t *pPixels = img.pixels;
assert( pPixels );
for( size_t h = 0; h < img.height; ++h )
{
if ( !_LoadScanline( scanline.get(), img.width, pPixels, img.rowPitch, img.format ) )
return false;
XMVECTOR* ptr = scanline.get();
for( size_t w = 0; w < img.width; ++w )
{
XMVECTOR alpha = XMVectorSplatW( *ptr );
if ( XMVector4Less( alpha, threshold ) )
return false;
++ptr;
}
pPixels += img.rowPitch;
}
}
}
return true;
}
}; // namespace }; // namespace

View File

@ -123,7 +123,15 @@ HRESULT PremultiplyAlpha( const Image* srcImages, size_t nimages, const TexMetad
return E_INVALIDARG; return E_INVALIDARG;
#endif #endif
HRESULT hr = result.Initialize( metadata ); if ( metadata.IsPMAlpha() )
{
// Already premultiplied
return E_FAIL;
}
TexMetadata mdata2 = metadata;
mdata2.SetAlphaMode(TEX_ALPHA_MODE_PREMULTIPLIED);
HRESULT hr = result.Initialize( mdata2 );
if ( FAILED(hr) ) if ( FAILED(hr) )
return hr; return hr;

View File

@ -270,7 +270,7 @@ void PrintInfo( const TexMetadata& info )
break; break;
case TEX_DIMENSION_TEXTURE2D: case TEX_DIMENSION_TEXTURE2D:
if ( info.miscFlags & TEX_MISC_TEXTURECUBE ) if ( info.IsCubemap() )
{ {
wprintf( (info.arraySize > 1) ? L" CubeArray" : L" Cube" ); wprintf( (info.arraySize > 1) ? L" CubeArray" : L" Cube" );
} }
@ -717,6 +717,7 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
assert( info.arraySize == tinfo.arraySize ); assert( info.arraySize == tinfo.arraySize );
assert( info.mipLevels == tinfo.mipLevels ); assert( info.mipLevels == tinfo.mipLevels );
assert( info.miscFlags == tinfo.miscFlags ); assert( info.miscFlags == tinfo.miscFlags );
assert( info.miscFlags2 == tinfo.miscFlags2 );
assert( info.dimension == tinfo.dimension ); assert( info.dimension == tinfo.dimension );
delete image; delete image;
@ -724,7 +725,6 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
} }
// --- Flip/Rotate ------------------------------------------------------------- // --- Flip/Rotate -------------------------------------------------------------
// TODO - OPT_ROTATE ? (90, 180, 270)
if ( dwOptions & ( (1 << OPT_HFLIP) | (1 << OPT_VFLIP) ) ) if ( dwOptions & ( (1 << OPT_HFLIP) | (1 << OPT_VFLIP) ) )
{ {
ScratchImage *timage = new ScratchImage; ScratchImage *timage = new ScratchImage;
@ -765,6 +765,7 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
assert( info.arraySize == tinfo.arraySize ); assert( info.arraySize == tinfo.arraySize );
assert( info.mipLevels == tinfo.mipLevels ); assert( info.mipLevels == tinfo.mipLevels );
assert( info.miscFlags == tinfo.miscFlags ); assert( info.miscFlags == tinfo.miscFlags );
assert( info.miscFlags2 == tinfo.miscFlags2 );
assert( info.format == tinfo.format ); assert( info.format == tinfo.format );
assert( info.dimension == tinfo.dimension ); assert( info.dimension == tinfo.dimension );
@ -802,6 +803,7 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
assert( info.depth == tinfo.depth ); assert( info.depth == tinfo.depth );
assert( info.arraySize == tinfo.arraySize ); assert( info.arraySize == tinfo.arraySize );
assert( info.miscFlags == tinfo.miscFlags ); assert( info.miscFlags == tinfo.miscFlags );
assert( info.miscFlags2 == tinfo.miscFlags2 );
assert( info.format == tinfo.format ); assert( info.format == tinfo.format );
assert( info.dimension == tinfo.dimension ); assert( info.dimension == tinfo.dimension );
@ -840,6 +842,7 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
assert( info.arraySize == tinfo.arraySize ); assert( info.arraySize == tinfo.arraySize );
assert( info.mipLevels == tinfo.mipLevels ); assert( info.mipLevels == tinfo.mipLevels );
assert( info.miscFlags == tinfo.miscFlags ); assert( info.miscFlags == tinfo.miscFlags );
assert( info.miscFlags2 == tinfo.miscFlags2 );
assert( info.dimension == tinfo.dimension ); assert( info.dimension == tinfo.dimension );
delete image; delete image;
@ -963,6 +966,7 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
assert( info.arraySize == tinfo.arraySize ); assert( info.arraySize == tinfo.arraySize );
assert( info.mipLevels == tinfo.mipLevels ); assert( info.mipLevels == tinfo.mipLevels );
assert( info.miscFlags == tinfo.miscFlags ); assert( info.miscFlags == tinfo.miscFlags );
assert( info.miscFlags2 == tinfo.miscFlags2 );
assert( info.dimension == tinfo.dimension ); assert( info.dimension == tinfo.dimension );
delete image; delete image;
@ -974,29 +978,48 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
&& HasAlpha( info.format ) && HasAlpha( info.format )
&& info.format != DXGI_FORMAT_A8_UNORM ) && info.format != DXGI_FORMAT_A8_UNORM )
{ {
const Image* img = image->GetImage(0,0,0); if ( info.IsPMAlpha() )
assert( img );
size_t nimg = image->GetImageCount();
ScratchImage *timage = new ScratchImage;
if ( !timage )
{ {
wprintf( L" ERROR: Memory allocation failed\n" ); printf("WARNING: Image is already using premultiplied alpha\n");
delete image;
goto LError;
} }
else
hr = PremultiplyAlpha( img, nimg, info, *timage );
if ( FAILED(hr) )
{ {
wprintf( L" FAILED [premultiply alpha] (%x)\n", hr); const Image* img = image->GetImage(0,0,0);
delete timage; assert( img );
delete image; size_t nimg = image->GetImageCount();
continue;
}
delete image; ScratchImage *timage = new ScratchImage;
image = timage; if ( !timage )
{
wprintf( L" ERROR: Memory allocation failed\n" );
delete image;
goto LError;
}
hr = PremultiplyAlpha( img, nimg, info, *timage );
if ( FAILED(hr) )
{
wprintf( L" FAILED [premultiply alpha] (%x)\n", hr);
delete timage;
delete image;
continue;
}
const TexMetadata& 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.miscFlags2 == tinfo.miscFlags2 );
assert( info.dimension == tinfo.dimension );
delete image;
image = timage;
}
} }
// --- Compress ---------------------------------------------------------------- // --- Compress ----------------------------------------------------------------
@ -1032,12 +1055,35 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
assert( info.arraySize == tinfo.arraySize ); assert( info.arraySize == tinfo.arraySize );
assert( info.mipLevels == tinfo.mipLevels ); assert( info.mipLevels == tinfo.mipLevels );
assert( info.miscFlags == tinfo.miscFlags ); assert( info.miscFlags == tinfo.miscFlags );
assert( info.miscFlags2 == tinfo.miscFlags2 );
assert( info.dimension == tinfo.dimension ); assert( info.dimension == tinfo.dimension );
delete image; delete image;
image = timage; image = timage;
} }
// --- Set alpha mode ----------------------------------------------------------
if ( HasAlpha( info.format )
&& info.format != DXGI_FORMAT_A8_UNORM )
{
if ( image->IsAlphaAllOpaque() )
{
info.SetAlphaMode(TEX_ALPHA_MODE_OPAQUE);
}
else if ( info.IsPMAlpha() )
{
// Aleady set TEX_ALPHA_MODE_PREMULTIPLIED
}
else if ( dwOptions & (1 << OPT_SEPALPHA) )
{
info.SetAlphaMode(TEX_ALPHA_MODE_4TH_CHANNEL);
}
}
else
{
info.miscFlags2 &= ~TEX_MISC2_ALPHA_MODE_MASK;
}
// --- Save result ------------------------------------------------------------- // --- Save result -------------------------------------------------------------
{ {
const Image* img = image->GetImage(0,0,0); const Image* img = image->GetImage(0,0,0);
@ -1074,7 +1120,7 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
{ {
case CODEC_DDS: case CODEC_DDS:
hr = SaveToDDSFile( img, nimg, info, hr = SaveToDDSFile( img, nimg, info,
(dwOptions & (1 << OPT_USE_DX10) ) ? DDS_FLAGS_FORCE_DX10_EXT : DDS_FLAGS_NONE, (dwOptions & (1 << OPT_USE_DX10) ) ? (DDS_FLAGS_FORCE_DX10_EXT|DDS_FLAGS_FORCE_DX10_EXT_MISC2) : DDS_FLAGS_NONE,
pConv->szDest ); pConv->szDest );
break; break;