mirror of
https://github.com/microsoft/DirectXTex.git
synced 2025-07-14 14:10:13 +02:00
Added TGA_FLAGS for TGA reader (#197)
This commit is contained in:
parent
9dbde8de5d
commit
80f38c3903
@ -192,6 +192,17 @@ namespace DirectX
|
|||||||
// Enables the loader to read large dimension .dds files (i.e. greater than known hardware requirements)
|
// Enables the loader to read large dimension .dds files (i.e. greater than known hardware requirements)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum TGA_FLAGS : unsigned long
|
||||||
|
{
|
||||||
|
TGA_FLAGS_NONE = 0x0,
|
||||||
|
|
||||||
|
TGA_FLAGS_BGR = 0x1,
|
||||||
|
// 24bpp files are returned as BGRX; 32bpp files are returned as BGRA
|
||||||
|
|
||||||
|
TGA_FLAGS_ALLOW_ALL_ZERO_ALPHA = 0x2,
|
||||||
|
// If the loaded image has an all zero alpha channel, normally we assume it should be opaque. This flag leaves it alone.
|
||||||
|
};
|
||||||
|
|
||||||
enum WIC_FLAGS : unsigned long
|
enum WIC_FLAGS : unsigned long
|
||||||
{
|
{
|
||||||
WIC_FLAGS_NONE = 0x0,
|
WIC_FLAGS_NONE = 0x0,
|
||||||
@ -254,9 +265,11 @@ namespace DirectX
|
|||||||
|
|
||||||
HRESULT __cdecl GetMetadataFromTGAMemory(
|
HRESULT __cdecl GetMetadataFromTGAMemory(
|
||||||
_In_reads_bytes_(size) const void* pSource, _In_ size_t size,
|
_In_reads_bytes_(size) const void* pSource, _In_ size_t size,
|
||||||
|
_In_ TGA_FLAGS flags,
|
||||||
_Out_ TexMetadata& metadata) noexcept;
|
_Out_ TexMetadata& metadata) noexcept;
|
||||||
HRESULT __cdecl GetMetadataFromTGAFile(
|
HRESULT __cdecl GetMetadataFromTGAFile(
|
||||||
_In_z_ const wchar_t* szFile,
|
_In_z_ const wchar_t* szFile,
|
||||||
|
_In_ TGA_FLAGS flags,
|
||||||
_Out_ TexMetadata& metadata) noexcept;
|
_Out_ TexMetadata& metadata) noexcept;
|
||||||
|
|
||||||
HRESULT __cdecl GetMetadataFromWICMemory(
|
HRESULT __cdecl GetMetadataFromWICMemory(
|
||||||
@ -271,6 +284,14 @@ namespace DirectX
|
|||||||
_Out_ TexMetadata& metadata,
|
_Out_ TexMetadata& metadata,
|
||||||
_In_opt_ std::function<void __cdecl(IWICMetadataQueryReader*)> getMQR = nullptr);
|
_In_opt_ std::function<void __cdecl(IWICMetadataQueryReader*)> getMQR = nullptr);
|
||||||
|
|
||||||
|
// Compatability helpers
|
||||||
|
HRESULT __cdecl GetMetadataFromTGAMemory(
|
||||||
|
_In_reads_bytes_(size) const void* pSource, _In_ size_t size,
|
||||||
|
_Out_ TexMetadata& metadata) noexcept;
|
||||||
|
HRESULT __cdecl GetMetadataFromTGAFile(
|
||||||
|
_In_z_ const wchar_t* szFile,
|
||||||
|
_Out_ TexMetadata& metadata) noexcept;
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------
|
||||||
// Bitmap image container
|
// Bitmap image container
|
||||||
struct Image
|
struct Image
|
||||||
@ -401,13 +422,19 @@ namespace DirectX
|
|||||||
// TGA operations
|
// TGA operations
|
||||||
HRESULT __cdecl LoadFromTGAMemory(
|
HRESULT __cdecl LoadFromTGAMemory(
|
||||||
_In_reads_bytes_(size) const void* pSource, _In_ size_t size,
|
_In_reads_bytes_(size) const void* pSource, _In_ size_t size,
|
||||||
|
_In_ TGA_FLAGS flags,
|
||||||
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image) noexcept;
|
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image) noexcept;
|
||||||
HRESULT __cdecl LoadFromTGAFile(
|
HRESULT __cdecl LoadFromTGAFile(
|
||||||
_In_z_ const wchar_t* szFile,
|
_In_z_ const wchar_t* szFile,
|
||||||
|
_In_ TGA_FLAGS flags,
|
||||||
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image) noexcept;
|
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image) noexcept;
|
||||||
|
|
||||||
HRESULT __cdecl SaveToTGAMemory(_In_ const Image& image, _Out_ Blob& blob, _In_opt_ const TexMetadata* metadata = nullptr) noexcept;
|
HRESULT __cdecl SaveToTGAMemory(_In_ const Image& image,
|
||||||
HRESULT __cdecl SaveToTGAFile(_In_ const Image& image, _In_z_ const wchar_t* szFile, _In_opt_ const TexMetadata* metadata = nullptr) noexcept;
|
_In_ TGA_FLAGS flags,
|
||||||
|
_Out_ Blob& blob, _In_opt_ const TexMetadata* metadata = nullptr) noexcept;
|
||||||
|
HRESULT __cdecl SaveToTGAFile(_In_ const Image& image,
|
||||||
|
_In_ TGA_FLAGS flags,
|
||||||
|
_In_z_ const wchar_t* szFile, _In_opt_ const TexMetadata* metadata = nullptr) noexcept;
|
||||||
|
|
||||||
// WIC operations
|
// WIC operations
|
||||||
HRESULT __cdecl LoadFromWICMemory(
|
HRESULT __cdecl LoadFromWICMemory(
|
||||||
@ -440,6 +467,17 @@ namespace DirectX
|
|||||||
_In_z_ const wchar_t* szFile, _In_opt_ const GUID* targetFormat = nullptr,
|
_In_z_ const wchar_t* szFile, _In_opt_ const GUID* targetFormat = nullptr,
|
||||||
_In_opt_ std::function<void __cdecl(IPropertyBag2*)> setCustomProps = nullptr);
|
_In_opt_ std::function<void __cdecl(IPropertyBag2*)> setCustomProps = nullptr);
|
||||||
|
|
||||||
|
// Compatability helpers
|
||||||
|
HRESULT __cdecl LoadFromTGAMemory(
|
||||||
|
_In_reads_bytes_(size) const void* pSource, _In_ size_t size,
|
||||||
|
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image) noexcept;
|
||||||
|
HRESULT __cdecl LoadFromTGAFile(
|
||||||
|
_In_z_ const wchar_t* szFile,
|
||||||
|
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image) noexcept;
|
||||||
|
|
||||||
|
HRESULT __cdecl SaveToTGAMemory(_In_ const Image& image, _Out_ Blob& blob, _In_opt_ const TexMetadata* metadata = nullptr) noexcept;
|
||||||
|
HRESULT __cdecl SaveToTGAFile(_In_ const Image& image, _In_z_ const wchar_t* szFile, _In_opt_ const TexMetadata* metadata = nullptr) noexcept;
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------
|
||||||
// Texture conversion, resizing, mipmap generation, and block compression
|
// Texture conversion, resizing, mipmap generation, and block compression
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
//=====================================================================================
|
//=====================================================================================
|
||||||
DEFINE_ENUM_FLAG_OPERATORS(CP_FLAGS);
|
DEFINE_ENUM_FLAG_OPERATORS(CP_FLAGS);
|
||||||
DEFINE_ENUM_FLAG_OPERATORS(DDS_FLAGS);
|
DEFINE_ENUM_FLAG_OPERATORS(DDS_FLAGS);
|
||||||
|
DEFINE_ENUM_FLAG_OPERATORS(TGA_FLAGS);
|
||||||
DEFINE_ENUM_FLAG_OPERATORS(WIC_FLAGS);
|
DEFINE_ENUM_FLAG_OPERATORS(WIC_FLAGS);
|
||||||
DEFINE_ENUM_FLAG_OPERATORS(TEX_FR_FLAGS);
|
DEFINE_ENUM_FLAG_OPERATORS(TEX_FR_FLAGS);
|
||||||
DEFINE_ENUM_FLAG_OPERATORS(TEX_FILTER_FLAGS);
|
DEFINE_ENUM_FLAG_OPERATORS(TEX_FILTER_FLAGS);
|
||||||
@ -148,3 +149,43 @@ inline HRESULT __cdecl SaveToDDSFile(const Image& image, DDS_FLAGS flags, const
|
|||||||
|
|
||||||
return SaveToDDSFile(&image, 1, mdata, flags, szFile);
|
return SaveToDDSFile(&image, 1, mdata, flags, szFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//=====================================================================================
|
||||||
|
// Compatability helpers
|
||||||
|
//=====================================================================================
|
||||||
|
_Use_decl_annotations_
|
||||||
|
inline HRESULT __cdecl GetMetadataFromTGAMemory(const void* pSource, size_t size, TexMetadata& metadata) noexcept
|
||||||
|
{
|
||||||
|
return GetMetadataFromTGAMemory(pSource, size, TGA_FLAGS_NONE, metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
_Use_decl_annotations_
|
||||||
|
inline HRESULT __cdecl GetMetadataFromTGAFile(const wchar_t* szFile, TexMetadata& metadata) noexcept
|
||||||
|
{
|
||||||
|
return GetMetadataFromTGAFile(szFile, TGA_FLAGS_NONE, metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
_Use_decl_annotations_
|
||||||
|
inline HRESULT __cdecl LoadFromTGAMemory(const void* pSource, size_t size, TexMetadata* metadata, ScratchImage& image) noexcept
|
||||||
|
{
|
||||||
|
return LoadFromTGAMemory(pSource, size, TGA_FLAGS_NONE, metadata, image);
|
||||||
|
}
|
||||||
|
|
||||||
|
_Use_decl_annotations_
|
||||||
|
inline HRESULT __cdecl LoadFromTGAFile(const wchar_t* szFile, TexMetadata* metadata, ScratchImage& image) noexcept
|
||||||
|
{
|
||||||
|
return LoadFromTGAFile(szFile, TGA_FLAGS_NONE, metadata, image);
|
||||||
|
}
|
||||||
|
|
||||||
|
_Use_decl_annotations_
|
||||||
|
inline HRESULT __cdecl SaveToTGAMemory(const Image& image, Blob& blob, const TexMetadata* metadata) noexcept
|
||||||
|
{
|
||||||
|
return SaveToTGAMemory(image, TGA_FLAGS_NONE, blob, metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
_Use_decl_annotations_
|
||||||
|
inline HRESULT __cdecl SaveToTGAFile(const Image& image, const wchar_t* szFile, const TexMetadata* metadata) noexcept
|
||||||
|
{
|
||||||
|
return SaveToTGAFile(image, TGA_FLAGS_NONE, szFile, metadata);
|
||||||
|
}
|
||||||
|
@ -134,6 +134,7 @@ namespace
|
|||||||
HRESULT DecodeTGAHeader(
|
HRESULT DecodeTGAHeader(
|
||||||
_In_reads_bytes_(size) const void* pSource,
|
_In_reads_bytes_(size) const void* pSource,
|
||||||
size_t size,
|
size_t size,
|
||||||
|
TGA_FLAGS flags,
|
||||||
_Out_ TexMetadata& metadata,
|
_Out_ TexMetadata& metadata,
|
||||||
size_t& offset,
|
size_t& offset,
|
||||||
_Inout_opt_ uint32_t* convFlags) noexcept
|
_Inout_opt_ uint32_t* convFlags) noexcept
|
||||||
@ -177,16 +178,22 @@ namespace
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 24:
|
case 24:
|
||||||
metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
if (flags & TGA_FLAGS_BGR)
|
||||||
metadata.SetAlphaMode(TEX_ALPHA_MODE_OPAQUE);
|
{
|
||||||
|
metadata.format = DXGI_FORMAT_B8G8R8X8_UNORM;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
metadata.SetAlphaMode(TEX_ALPHA_MODE_OPAQUE);
|
||||||
|
}
|
||||||
|
|
||||||
if (convFlags)
|
if (convFlags)
|
||||||
*convFlags |= CONV_FLAGS_EXPAND;
|
*convFlags |= CONV_FLAGS_EXPAND;
|
||||||
// We could use DXGI_FORMAT_B8G8R8X8_UNORM, but we prefer DXGI 1.0 formats
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 32:
|
case 32:
|
||||||
metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
metadata.format = (flags & TGA_FLAGS_BGR) ? DXGI_FORMAT_B8G8R8A8_UNORM : DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
// We could use DXGI_FORMAT_B8G8R8A8_UNORM, but we prefer DXGI 1.0 formats
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -275,6 +282,7 @@ namespace
|
|||||||
HRESULT UncompressPixels(
|
HRESULT UncompressPixels(
|
||||||
_In_reads_bytes_(size) const void* pSource,
|
_In_reads_bytes_(size) const void* pSource,
|
||||||
size_t size,
|
size_t size,
|
||||||
|
TGA_FLAGS flags,
|
||||||
_In_ const Image* image,
|
_In_ const Image* image,
|
||||||
_In_ uint32_t convFlags) noexcept
|
_In_ uint32_t convFlags) noexcept
|
||||||
{
|
{
|
||||||
@ -444,7 +452,7 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If there are no non-zero alpha channel entries, we'll assume alpha is not used and force it to opaque
|
// If there are no non-zero alpha channel entries, we'll assume alpha is not used and force it to opaque
|
||||||
if (maxalpha == 0)
|
if (maxalpha == 0 && !(flags & TGA_FLAGS_ALLOW_ALL_ZERO_ALPHA))
|
||||||
{
|
{
|
||||||
opaquealpha = true;
|
opaquealpha = true;
|
||||||
hr = SetAlphaChannelToOpaque(image);
|
hr = SetAlphaChannelToOpaque(image);
|
||||||
@ -458,7 +466,7 @@ namespace
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//----------------------------------------------------------------------- 24/32-bit
|
//------------------------------------------------------ 24/32-bit (with swizzling)
|
||||||
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
||||||
{
|
{
|
||||||
uint32_t minalpha = 255;
|
uint32_t minalpha = 255;
|
||||||
@ -589,7 +597,7 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If there are no non-zero alpha channel entries, we'll assume alpha is not used and force it to opaque
|
// If there are no non-zero alpha channel entries, we'll assume alpha is not used and force it to opaque
|
||||||
if (maxalpha == 0)
|
if (maxalpha == 0 && !(flags & TGA_FLAGS_ALLOW_ALL_ZERO_ALPHA))
|
||||||
{
|
{
|
||||||
opaquealpha = true;
|
opaquealpha = true;
|
||||||
hr = SetAlphaChannelToOpaque(image);
|
hr = SetAlphaChannelToOpaque(image);
|
||||||
@ -603,6 +611,189 @@ namespace
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------- 32-bit (BGR)
|
||||||
|
case DXGI_FORMAT_B8G8R8A8_UNORM:
|
||||||
|
{
|
||||||
|
assert((convFlags & CONV_FLAGS_EXPAND) == 0);
|
||||||
|
|
||||||
|
uint32_t minalpha = 255;
|
||||||
|
uint32_t maxalpha = 0;
|
||||||
|
|
||||||
|
for (size_t y = 0; y < image->height; ++y)
|
||||||
|
{
|
||||||
|
size_t offset = ((convFlags & CONV_FLAGS_INVERTX) ? (image->width - 1) : 0);
|
||||||
|
|
||||||
|
auto dPtr = reinterpret_cast<uint32_t*>(image->pixels
|
||||||
|
+ (image->rowPitch * ((convFlags & CONV_FLAGS_INVERTY) ? y : (image->height - y - 1))))
|
||||||
|
+ offset;
|
||||||
|
|
||||||
|
for (size_t x = 0; x < image->width; )
|
||||||
|
{
|
||||||
|
if (sPtr >= endPtr)
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
|
if (*sPtr & 0x80)
|
||||||
|
{
|
||||||
|
// Repeat
|
||||||
|
size_t j = size_t(*sPtr & 0x7F) + 1;
|
||||||
|
++sPtr;
|
||||||
|
|
||||||
|
assert(offset * 4 < rowPitch);
|
||||||
|
|
||||||
|
if (sPtr + 3 >= endPtr)
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
|
uint32_t alpha = *(sPtr + 3);
|
||||||
|
|
||||||
|
auto t = *reinterpret_cast<const uint32_t*>(sPtr);
|
||||||
|
|
||||||
|
minalpha = std::min(minalpha, alpha);
|
||||||
|
maxalpha = std::max(maxalpha, alpha);
|
||||||
|
|
||||||
|
sPtr += 4;
|
||||||
|
|
||||||
|
for (; j > 0; --j, ++x)
|
||||||
|
{
|
||||||
|
if (x >= image->width)
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
|
*dPtr = t;
|
||||||
|
|
||||||
|
if (convFlags & CONV_FLAGS_INVERTX)
|
||||||
|
--dPtr;
|
||||||
|
else
|
||||||
|
++dPtr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Literal
|
||||||
|
size_t j = size_t(*sPtr & 0x7F) + 1;
|
||||||
|
++sPtr;
|
||||||
|
|
||||||
|
if (sPtr + (j * 4) > endPtr)
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
|
for (; j > 0; --j, ++x)
|
||||||
|
{
|
||||||
|
if (x >= image->width)
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
|
assert(offset * 4 < rowPitch);
|
||||||
|
|
||||||
|
if (sPtr + 3 >= endPtr)
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
|
uint32_t alpha = *(sPtr + 3);
|
||||||
|
*dPtr = *reinterpret_cast<const uint32_t*>(sPtr);
|
||||||
|
|
||||||
|
minalpha = std::min(minalpha, alpha);
|
||||||
|
maxalpha = std::max(maxalpha, alpha);
|
||||||
|
|
||||||
|
sPtr += 4;
|
||||||
|
|
||||||
|
if (convFlags & CONV_FLAGS_INVERTX)
|
||||||
|
--dPtr;
|
||||||
|
else
|
||||||
|
++dPtr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there are no non-zero alpha channel entries, we'll assume alpha is not used and force it to opaque
|
||||||
|
if (maxalpha == 0 && !(flags & TGA_FLAGS_ALLOW_ALL_ZERO_ALPHA))
|
||||||
|
{
|
||||||
|
opaquealpha = true;
|
||||||
|
hr = SetAlphaChannelToOpaque(image);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
else if (minalpha == 255)
|
||||||
|
{
|
||||||
|
opaquealpha = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------- 24-bit (BGR)
|
||||||
|
case DXGI_FORMAT_B8G8R8X8_UNORM:
|
||||||
|
{
|
||||||
|
assert((convFlags & CONV_FLAGS_EXPAND) != 0);
|
||||||
|
|
||||||
|
for (size_t y = 0; y < image->height; ++y)
|
||||||
|
{
|
||||||
|
size_t offset = ((convFlags & CONV_FLAGS_INVERTX) ? (image->width - 1) : 0);
|
||||||
|
|
||||||
|
auto dPtr = reinterpret_cast<uint32_t*>(image->pixels
|
||||||
|
+ (image->rowPitch * ((convFlags & CONV_FLAGS_INVERTY) ? y : (image->height - y - 1))))
|
||||||
|
+ offset;
|
||||||
|
|
||||||
|
for (size_t x = 0; x < image->width; )
|
||||||
|
{
|
||||||
|
if (sPtr >= endPtr)
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
|
if (*sPtr & 0x80)
|
||||||
|
{
|
||||||
|
// Repeat
|
||||||
|
size_t j = size_t(*sPtr & 0x7F) + 1;
|
||||||
|
++sPtr;
|
||||||
|
|
||||||
|
assert(offset * 3 < rowPitch);
|
||||||
|
|
||||||
|
if (sPtr + 2 >= endPtr)
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
|
uint32_t t = uint32_t(*sPtr) | uint32_t(*(sPtr + 1) << 8) | uint32_t(*(sPtr + 2) << 16);
|
||||||
|
sPtr += 3;
|
||||||
|
|
||||||
|
for (; j > 0; --j, ++x)
|
||||||
|
{
|
||||||
|
if (x >= image->width)
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
|
*dPtr = t;
|
||||||
|
|
||||||
|
if (convFlags & CONV_FLAGS_INVERTX)
|
||||||
|
--dPtr;
|
||||||
|
else
|
||||||
|
++dPtr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Literal
|
||||||
|
size_t j = size_t(*sPtr & 0x7F) + 1;
|
||||||
|
++sPtr;
|
||||||
|
|
||||||
|
if (sPtr + (j * 3) > endPtr)
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
|
for (; j > 0; --j, ++x)
|
||||||
|
{
|
||||||
|
if (x >= image->width)
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
|
assert(offset * 3 < rowPitch);
|
||||||
|
|
||||||
|
if (sPtr + 2 >= endPtr)
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
|
*dPtr = uint32_t(*sPtr) | uint32_t(*(sPtr + 1) << 8) | uint32_t(*(sPtr + 2) << 16);
|
||||||
|
sPtr += 3;
|
||||||
|
|
||||||
|
if (convFlags & CONV_FLAGS_INVERTX)
|
||||||
|
--dPtr;
|
||||||
|
else
|
||||||
|
++dPtr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------
|
||||||
default:
|
default:
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
@ -618,6 +809,7 @@ namespace
|
|||||||
HRESULT CopyPixels(
|
HRESULT CopyPixels(
|
||||||
_In_reads_bytes_(size) const void* pSource,
|
_In_reads_bytes_(size) const void* pSource,
|
||||||
size_t size,
|
size_t size,
|
||||||
|
TGA_FLAGS flags,
|
||||||
_In_ const Image* image,
|
_In_ const Image* image,
|
||||||
_In_ uint32_t convFlags) noexcept
|
_In_ uint32_t convFlags) noexcept
|
||||||
{
|
{
|
||||||
@ -702,7 +894,7 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If there are no non-zero alpha channel entries, we'll assume alpha is not used and force it to opaque
|
// If there are no non-zero alpha channel entries, we'll assume alpha is not used and force it to opaque
|
||||||
if (maxalpha == 0)
|
if (maxalpha == 0 && !(flags & TGA_FLAGS_ALLOW_ALL_ZERO_ALPHA))
|
||||||
{
|
{
|
||||||
opaquealpha = true;
|
opaquealpha = true;
|
||||||
hr = SetAlphaChannelToOpaque(image);
|
hr = SetAlphaChannelToOpaque(image);
|
||||||
@ -716,7 +908,7 @@ namespace
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//----------------------------------------------------------------------- 24/32-bit
|
//------------------------------------------------------ 24/32-bit (with swizzling)
|
||||||
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
||||||
{
|
{
|
||||||
uint32_t minalpha = 255;
|
uint32_t minalpha = 255;
|
||||||
@ -770,7 +962,7 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If there are no non-zero alpha channel entries, we'll assume alpha is not used and force it to opaque
|
// If there are no non-zero alpha channel entries, we'll assume alpha is not used and force it to opaque
|
||||||
if (maxalpha == 0)
|
if (maxalpha == 0 && !(flags & TGA_FLAGS_ALLOW_ALL_ZERO_ALPHA))
|
||||||
{
|
{
|
||||||
opaquealpha = true;
|
opaquealpha = true;
|
||||||
hr = SetAlphaChannelToOpaque(image);
|
hr = SetAlphaChannelToOpaque(image);
|
||||||
@ -784,6 +976,91 @@ namespace
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------- 32-bit (BGR)
|
||||||
|
case DXGI_FORMAT_B8G8R8A8_UNORM:
|
||||||
|
{
|
||||||
|
assert((convFlags & CONV_FLAGS_EXPAND) == 0);
|
||||||
|
|
||||||
|
uint32_t minalpha = 255;
|
||||||
|
uint32_t maxalpha = 0;
|
||||||
|
|
||||||
|
for (size_t y = 0; y < image->height; ++y)
|
||||||
|
{
|
||||||
|
size_t offset = ((convFlags & CONV_FLAGS_INVERTX) ? (image->width - 1) : 0);
|
||||||
|
|
||||||
|
auto dPtr = reinterpret_cast<uint32_t*>(image->pixels
|
||||||
|
+ (image->rowPitch * ((convFlags & CONV_FLAGS_INVERTY) ? y : (image->height - y - 1))))
|
||||||
|
+ offset;
|
||||||
|
|
||||||
|
for (size_t x = 0; x < image->width; ++x)
|
||||||
|
{
|
||||||
|
assert(offset * 4 < rowPitch);
|
||||||
|
|
||||||
|
if (sPtr + 3 >= endPtr)
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
|
uint32_t alpha = *(sPtr + 3);
|
||||||
|
*dPtr = *reinterpret_cast<const uint32_t*>(sPtr);
|
||||||
|
|
||||||
|
minalpha = std::min(minalpha, alpha);
|
||||||
|
maxalpha = std::max(maxalpha, alpha);
|
||||||
|
|
||||||
|
sPtr += 4;
|
||||||
|
|
||||||
|
if (convFlags & CONV_FLAGS_INVERTX)
|
||||||
|
--dPtr;
|
||||||
|
else
|
||||||
|
++dPtr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there are no non-zero alpha channel entries, we'll assume alpha is not used and force it to opaque
|
||||||
|
if (maxalpha == 0 && !(flags & TGA_FLAGS_ALLOW_ALL_ZERO_ALPHA))
|
||||||
|
{
|
||||||
|
opaquealpha = true;
|
||||||
|
hr = SetAlphaChannelToOpaque(image);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
else if (minalpha == 255)
|
||||||
|
{
|
||||||
|
opaquealpha = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------- 24-bit (BGR)
|
||||||
|
case DXGI_FORMAT_B8G8R8X8_UNORM:
|
||||||
|
{
|
||||||
|
assert((convFlags & CONV_FLAGS_EXPAND) != 0);
|
||||||
|
|
||||||
|
for (size_t y = 0; y < image->height; ++y)
|
||||||
|
{
|
||||||
|
size_t offset = ((convFlags & CONV_FLAGS_INVERTX) ? (image->width - 1) : 0);
|
||||||
|
|
||||||
|
auto dPtr = reinterpret_cast<uint32_t*>(image->pixels
|
||||||
|
+ (image->rowPitch * ((convFlags & CONV_FLAGS_INVERTY) ? y : (image->height - y - 1))))
|
||||||
|
+ offset;
|
||||||
|
|
||||||
|
for (size_t x = 0; x < image->width; ++x)
|
||||||
|
{
|
||||||
|
assert(offset * 3 < rowPitch);
|
||||||
|
|
||||||
|
if (sPtr + 2 >= endPtr)
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
|
*dPtr = uint32_t(*sPtr) | uint32_t(*(sPtr + 1) << 8) | uint32_t(*(sPtr + 2) << 16);
|
||||||
|
sPtr += 3;
|
||||||
|
|
||||||
|
if (convFlags & CONV_FLAGS_INVERTX)
|
||||||
|
--dPtr;
|
||||||
|
else
|
||||||
|
++dPtr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------
|
||||||
default:
|
default:
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
@ -980,17 +1257,18 @@ _Use_decl_annotations_
|
|||||||
HRESULT DirectX::GetMetadataFromTGAMemory(
|
HRESULT DirectX::GetMetadataFromTGAMemory(
|
||||||
const void* pSource,
|
const void* pSource,
|
||||||
size_t size,
|
size_t size,
|
||||||
|
TGA_FLAGS flags,
|
||||||
TexMetadata& metadata) noexcept
|
TexMetadata& metadata) noexcept
|
||||||
{
|
{
|
||||||
if (!pSource || size == 0)
|
if (!pSource || size == 0)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
size_t offset;
|
size_t offset;
|
||||||
return DecodeTGAHeader(pSource, size, metadata, offset, nullptr);
|
return DecodeTGAHeader(pSource, size, flags, metadata, offset, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
_Use_decl_annotations_
|
_Use_decl_annotations_
|
||||||
HRESULT DirectX::GetMetadataFromTGAFile(const wchar_t* szFile, TexMetadata& metadata) noexcept
|
HRESULT DirectX::GetMetadataFromTGAFile(const wchar_t* szFile, TGA_FLAGS flags, TexMetadata& metadata) noexcept
|
||||||
{
|
{
|
||||||
if (!szFile)
|
if (!szFile)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
@ -1034,7 +1312,7 @@ HRESULT DirectX::GetMetadataFromTGAFile(const wchar_t* szFile, TexMetadata& meta
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t offset;
|
size_t offset;
|
||||||
return DecodeTGAHeader(header, bytesRead, metadata, offset, nullptr);
|
return DecodeTGAHeader(header, bytesRead, flags, metadata, offset, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1045,6 +1323,7 @@ _Use_decl_annotations_
|
|||||||
HRESULT DirectX::LoadFromTGAMemory(
|
HRESULT DirectX::LoadFromTGAMemory(
|
||||||
const void* pSource,
|
const void* pSource,
|
||||||
size_t size,
|
size_t size,
|
||||||
|
TGA_FLAGS flags,
|
||||||
TexMetadata* metadata,
|
TexMetadata* metadata,
|
||||||
ScratchImage& image) noexcept
|
ScratchImage& image) noexcept
|
||||||
{
|
{
|
||||||
@ -1056,7 +1335,7 @@ HRESULT DirectX::LoadFromTGAMemory(
|
|||||||
size_t offset;
|
size_t offset;
|
||||||
uint32_t convFlags = 0;
|
uint32_t convFlags = 0;
|
||||||
TexMetadata mdata;
|
TexMetadata mdata;
|
||||||
HRESULT hr = DecodeTGAHeader(pSource, size, mdata, offset, &convFlags);
|
HRESULT hr = DecodeTGAHeader(pSource, size, flags, mdata, offset, &convFlags);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
@ -1075,11 +1354,11 @@ HRESULT DirectX::LoadFromTGAMemory(
|
|||||||
|
|
||||||
if (convFlags & CONV_FLAGS_RLE)
|
if (convFlags & CONV_FLAGS_RLE)
|
||||||
{
|
{
|
||||||
hr = UncompressPixels(pPixels, remaining, image.GetImage(0, 0, 0), convFlags);
|
hr = UncompressPixels(pPixels, remaining, flags, image.GetImage(0, 0, 0), convFlags);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
hr = CopyPixels(pPixels, remaining, image.GetImage(0, 0, 0), convFlags);
|
hr = CopyPixels(pPixels, remaining, flags, image.GetImage(0, 0, 0), convFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
@ -1122,6 +1401,7 @@ HRESULT DirectX::LoadFromTGAMemory(
|
|||||||
_Use_decl_annotations_
|
_Use_decl_annotations_
|
||||||
HRESULT DirectX::LoadFromTGAFile(
|
HRESULT DirectX::LoadFromTGAFile(
|
||||||
const wchar_t* szFile,
|
const wchar_t* szFile,
|
||||||
|
TGA_FLAGS flags,
|
||||||
TexMetadata* metadata,
|
TexMetadata* metadata,
|
||||||
ScratchImage& image) noexcept
|
ScratchImage& image) noexcept
|
||||||
{
|
{
|
||||||
@ -1171,7 +1451,7 @@ HRESULT DirectX::LoadFromTGAFile(
|
|||||||
size_t offset;
|
size_t offset;
|
||||||
uint32_t convFlags = 0;
|
uint32_t convFlags = 0;
|
||||||
TexMetadata mdata;
|
TexMetadata mdata;
|
||||||
HRESULT hr = DecodeTGAHeader(header, bytesRead, mdata, offset, &convFlags);
|
HRESULT hr = DecodeTGAHeader(header, bytesRead, flags, mdata, offset, &convFlags);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
@ -1269,7 +1549,7 @@ HRESULT DirectX::LoadFromTGAFile(
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t tflags = TEXP_SCANLINE_NONE;
|
uint32_t tflags = TEXP_SCANLINE_NONE;
|
||||||
if (maxalpha == 0)
|
if (maxalpha == 0 && !(flags & TGA_FLAGS_ALLOW_ALL_ZERO_ALPHA))
|
||||||
{
|
{
|
||||||
opaquealpha = true;
|
opaquealpha = true;
|
||||||
tflags = TEXP_SCANLINE_SETALPHA;
|
tflags = TEXP_SCANLINE_SETALPHA;
|
||||||
@ -1290,7 +1570,63 @@ HRESULT DirectX::LoadFromTGAFile(
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// If we start using DXGI_FORMAT_B8G8R8X8_UNORM or DXGI_FORMAT_B8G8R8A8_UNORM we need to check for a fully 0 alpha channel
|
case DXGI_FORMAT_B8G8R8A8_UNORM:
|
||||||
|
{
|
||||||
|
assert(image.GetImageCount() == 1);
|
||||||
|
const Image* img = image.GetImage(0, 0, 0);
|
||||||
|
if (!img)
|
||||||
|
{
|
||||||
|
image.Release();
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scan for non-zero alpha channel
|
||||||
|
uint32_t minalpha = 255;
|
||||||
|
uint32_t maxalpha = 0;
|
||||||
|
|
||||||
|
const uint8_t *pPixels = img->pixels;
|
||||||
|
if (!pPixels)
|
||||||
|
{
|
||||||
|
image.Release();
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t rowPitch = img->rowPitch;
|
||||||
|
|
||||||
|
for (size_t h = 0; h < img->height; ++h)
|
||||||
|
{
|
||||||
|
auto sPtr = reinterpret_cast<const uint32_t*>(pPixels);
|
||||||
|
|
||||||
|
for (size_t x = 0; x < img->width; ++x)
|
||||||
|
{
|
||||||
|
uint32_t alpha = ((*sPtr & 0xFF000000) >> 24);
|
||||||
|
|
||||||
|
minalpha = std::min(minalpha, alpha);
|
||||||
|
maxalpha = std::max(maxalpha, alpha);
|
||||||
|
|
||||||
|
++sPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
pPixels += rowPitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there are no non-zero alpha channel entries, we'll assume alpha is not used and force it to opaque
|
||||||
|
if (maxalpha == 0 && !(flags & TGA_FLAGS_ALLOW_ALL_ZERO_ALPHA))
|
||||||
|
{
|
||||||
|
opaquealpha = true;
|
||||||
|
hr = SetAlphaChannelToOpaque(img);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
image.Release();
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (minalpha == 255)
|
||||||
|
{
|
||||||
|
opaquealpha = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case DXGI_FORMAT_B5G5R5A1_UNORM:
|
case DXGI_FORMAT_B5G5R5A1_UNORM:
|
||||||
{
|
{
|
||||||
@ -1333,7 +1669,7 @@ HRESULT DirectX::LoadFromTGAFile(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If there are no non-zero alpha channel entries, we'll assume alpha is not used and force it to opaque
|
// If there are no non-zero alpha channel entries, we'll assume alpha is not used and force it to opaque
|
||||||
if (maxalpha == 0)
|
if (maxalpha == 0 && !(flags & TGA_FLAGS_ALLOW_ALL_ZERO_ALPHA))
|
||||||
{
|
{
|
||||||
opaquealpha = true;
|
opaquealpha = true;
|
||||||
hr = SetAlphaChannelToOpaque(img);
|
hr = SetAlphaChannelToOpaque(img);
|
||||||
@ -1350,6 +1686,10 @@ HRESULT DirectX::LoadFromTGAFile(
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_B8G8R8X8_UNORM:
|
||||||
|
// Should never be trying to direct-read 24bpp
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1377,11 +1717,11 @@ HRESULT DirectX::LoadFromTGAFile(
|
|||||||
|
|
||||||
if (convFlags & CONV_FLAGS_RLE)
|
if (convFlags & CONV_FLAGS_RLE)
|
||||||
{
|
{
|
||||||
hr = UncompressPixels(temp.get(), remaining, image.GetImage(0, 0, 0), convFlags);
|
hr = UncompressPixels(temp.get(), remaining, flags, image.GetImage(0, 0, 0), convFlags);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
hr = CopyPixels(temp.get(), remaining, image.GetImage(0, 0, 0), convFlags);
|
hr = CopyPixels(temp.get(), remaining, flags, image.GetImage(0, 0, 0), convFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
@ -1451,7 +1791,11 @@ HRESULT DirectX::LoadFromTGAFile(
|
|||||||
// Save a TGA file to memory
|
// Save a TGA file to memory
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_Use_decl_annotations_
|
||||||
HRESULT DirectX::SaveToTGAMemory(const Image& image, Blob& blob, const TexMetadata* metadata) noexcept
|
HRESULT DirectX::SaveToTGAMemory(
|
||||||
|
const Image& image,
|
||||||
|
TGA_FLAGS /*flags*/,
|
||||||
|
Blob& blob,
|
||||||
|
const TexMetadata* metadata) noexcept
|
||||||
{
|
{
|
||||||
if (!image.pixels)
|
if (!image.pixels)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
@ -1535,7 +1879,11 @@ HRESULT DirectX::SaveToTGAMemory(const Image& image, Blob& blob, const TexMetada
|
|||||||
// Save a TGA file to disk
|
// Save a TGA file to disk
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_Use_decl_annotations_
|
||||||
HRESULT DirectX::SaveToTGAFile(const Image& image, const wchar_t* szFile, const TexMetadata* metadata) noexcept
|
HRESULT DirectX::SaveToTGAFile(
|
||||||
|
const Image& image,
|
||||||
|
TGA_FLAGS /*flags*/,
|
||||||
|
const wchar_t* szFile,
|
||||||
|
const TexMetadata* metadata) noexcept
|
||||||
{
|
{
|
||||||
if (!szFile)
|
if (!szFile)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user