DirectXTex: WIC metadata usage
- Check/writes the sRGB information for DXGI_FORMAT_*_SRGB formats - Updated WICTextureLoader & ScreenGrab
This commit is contained in:
parent
8a267b10b2
commit
3474bcbab9
@ -223,7 +223,46 @@ static HRESULT _DecodeMetadata( _In_ DWORD flags,
|
||||
if ( metadata.format == DXGI_FORMAT_UNKNOWN )
|
||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
||||
|
||||
return S_OK;
|
||||
GUID containerFormat;
|
||||
hr = decoder->GetContainerFormat( &containerFormat );
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
ScopedObject<IWICMetadataQueryReader> metareader;
|
||||
hr = frame->GetMetadataQueryReader( &metareader );
|
||||
if ( SUCCEEDED(hr) )
|
||||
{
|
||||
// Check for sRGB colorspace metadata
|
||||
bool sRGB = false;
|
||||
|
||||
PROPVARIANT value;
|
||||
PropVariantInit( &value );
|
||||
|
||||
if ( memcmp( &containerFormat, &GUID_ContainerFormatPng, sizeof(GUID) ) == 0 )
|
||||
{
|
||||
// Check for sRGB chunk
|
||||
if ( SUCCEEDED( metareader->GetMetadataByName( L"/sRGB/RenderingIntent", &value ) ) && value.vt == VT_UI1 )
|
||||
{
|
||||
sRGB = true;
|
||||
}
|
||||
}
|
||||
else if ( SUCCEEDED( metareader->GetMetadataByName( L"System.Image.ColorSpace", &value ) ) && value.vt == VT_UI2 && value.uiVal == 1 )
|
||||
{
|
||||
sRGB = true;
|
||||
}
|
||||
|
||||
PropVariantClear( &value );
|
||||
|
||||
if ( sRGB )
|
||||
metadata.format = MakeSRGB( metadata.format );
|
||||
}
|
||||
else if ( hr == WINCODEC_ERR_UNSUPPORTEDOPERATION )
|
||||
{
|
||||
// Some formats just don't support metadata (BMP, ICO, etc.), so ignore this failure
|
||||
hr = S_OK;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
||||
@ -384,10 +423,68 @@ static HRESULT _DecodeMultiframe( _In_ DWORD flags, _In_ const TexMetadata& meta
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Encodes image metadata
|
||||
//-------------------------------------------------------------------------------------
|
||||
static HRESULT _EncodeMetadata( _In_ IWICBitmapFrameEncode* frame, _In_ const GUID& containerFormat, _In_ DXGI_FORMAT format )
|
||||
{
|
||||
if ( !frame )
|
||||
return E_POINTER;
|
||||
|
||||
ScopedObject<IWICMetadataQueryWriter> metawriter;
|
||||
HRESULT hr = frame->GetMetadataQueryWriter( &metawriter );
|
||||
if ( SUCCEEDED( hr ) )
|
||||
{
|
||||
PROPVARIANT value;
|
||||
PropVariantInit( &value );
|
||||
|
||||
bool sRGB = IsSRGB( format );
|
||||
|
||||
value.vt = VT_LPSTR;
|
||||
value.pszVal = "DirectXTex";
|
||||
|
||||
if ( memcmp( &containerFormat, &GUID_ContainerFormatPng, sizeof(GUID) ) == 0 )
|
||||
{
|
||||
// Set Software name
|
||||
(void)metawriter->SetMetadataByName( L"/tEXt/{str=Software}", &value );
|
||||
|
||||
// Set sRGB chunk
|
||||
if ( sRGB )
|
||||
{
|
||||
value.vt = VT_UI1;
|
||||
value.bVal = 0;
|
||||
(void)metawriter->SetMetadataByName( L"/sRGB/RenderingIntent", &value );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set Software name
|
||||
(void)metawriter->SetMetadataByName( L"System.ApplicationName", &value );
|
||||
|
||||
if ( sRGB )
|
||||
{
|
||||
// Set JPEG EXIF Colorspace of sRGB
|
||||
value.vt = VT_UI2;
|
||||
value.uiVal = 1;
|
||||
(void)metawriter->SetMetadataByName( L"System.Image.ColorSpace", &value );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( hr == WINCODEC_ERR_UNSUPPORTEDOPERATION )
|
||||
{
|
||||
// Some formats just don't support metadata (BMP, ICO, etc.), so ignore this failure
|
||||
hr = S_OK;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Encodes a single frame
|
||||
//-------------------------------------------------------------------------------------
|
||||
static HRESULT _EncodeImage( _In_ const Image& image, _In_ DWORD flags, _In_ IWICBitmapFrameEncode* frame, _In_opt_ IPropertyBag2* props, _In_opt_ const GUID* targetFormat )
|
||||
static HRESULT _EncodeImage( _In_ const Image& image, _In_ DWORD flags, _In_ REFGUID containerFormat,
|
||||
_In_ IWICBitmapFrameEncode* frame, _In_opt_ IPropertyBag2* props, _In_opt_ const GUID* targetFormat )
|
||||
{
|
||||
if ( !frame )
|
||||
return E_INVALIDARG;
|
||||
@ -427,6 +524,10 @@ static HRESULT _EncodeImage( _In_ const Image& image, _In_ DWORD flags, _In_ IWI
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
hr = _EncodeMetadata( frame, containerFormat, image.format );
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
if ( memcmp( &targetGuid, &pfGuid, sizeof(WICPixelFormatGUID) ) != 0 )
|
||||
{
|
||||
// Conversion required to write
|
||||
@ -472,7 +573,7 @@ static HRESULT _EncodeImage( _In_ const Image& image, _In_ DWORD flags, _In_ IWI
|
||||
}
|
||||
|
||||
static HRESULT _EncodeSingleFrame( _In_ const Image& image, _In_ DWORD flags,
|
||||
_In_ REFGUID guidContainerFormat, _Inout_ IStream* stream, _In_opt_ const GUID* targetFormat )
|
||||
_In_ REFGUID containerFormat, _Inout_ IStream* stream, _In_opt_ const GUID* targetFormat )
|
||||
{
|
||||
if ( !stream )
|
||||
return E_INVALIDARG;
|
||||
@ -483,7 +584,7 @@ static HRESULT _EncodeSingleFrame( _In_ const Image& image, _In_ DWORD flags,
|
||||
return E_NOINTERFACE;
|
||||
|
||||
ScopedObject<IWICBitmapEncoder> encoder;
|
||||
HRESULT hr = pWIC->CreateEncoder( guidContainerFormat, 0, &encoder );
|
||||
HRESULT hr = pWIC->CreateEncoder( containerFormat, 0, &encoder );
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
@ -497,7 +598,7 @@ static HRESULT _EncodeSingleFrame( _In_ const Image& image, _In_ DWORD flags,
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
if ( memcmp( &guidContainerFormat, &GUID_ContainerFormatBmp, sizeof(WICPixelFormatGUID) ) == 0 )
|
||||
if ( memcmp( &containerFormat, &GUID_ContainerFormatBmp, sizeof(WICPixelFormatGUID) ) == 0 )
|
||||
{
|
||||
// Opt-in to the Windows 8 support for writing 32-bit Windows BMP files with an alpha channel if supported
|
||||
PROPBAG2 option = { 0 };
|
||||
@ -514,7 +615,7 @@ static HRESULT _EncodeSingleFrame( _In_ const Image& image, _In_ DWORD flags,
|
||||
}
|
||||
}
|
||||
|
||||
hr = _EncodeImage( image, flags, frame.Get(), props.Get(), targetFormat );
|
||||
hr = _EncodeImage( image, flags, containerFormat, frame.Get(), props.Get(), targetFormat );
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
@ -530,7 +631,7 @@ static HRESULT _EncodeSingleFrame( _In_ const Image& image, _In_ DWORD flags,
|
||||
// Encodes an image array
|
||||
//-------------------------------------------------------------------------------------
|
||||
static HRESULT _EncodeMultiframe( _In_reads_(nimages) const Image* images, _In_ size_t nimages, _In_ DWORD flags,
|
||||
_In_ REFGUID guidContainerFormat, _Inout_ IStream* stream, _In_opt_ const GUID* targetFormat )
|
||||
_In_ REFGUID containerFormat, _Inout_ IStream* stream, _In_opt_ const GUID* targetFormat )
|
||||
{
|
||||
if ( !stream || nimages < 2 )
|
||||
return E_INVALIDARG;
|
||||
@ -544,7 +645,7 @@ static HRESULT _EncodeMultiframe( _In_reads_(nimages) const Image* images, _In_
|
||||
return E_NOINTERFACE;
|
||||
|
||||
ScopedObject<IWICBitmapEncoder> encoder;
|
||||
HRESULT hr = pWIC->CreateEncoder( guidContainerFormat, 0, &encoder );
|
||||
HRESULT hr = pWIC->CreateEncoder( containerFormat, 0, &encoder );
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
@ -572,7 +673,7 @@ static HRESULT _EncodeMultiframe( _In_reads_(nimages) const Image* images, _In_
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
hr = _EncodeImage( images[index], flags, frame.Get(), nullptr, targetFormat );
|
||||
hr = _EncodeImage( images[index], flags, containerFormat, frame.Get(), nullptr, targetFormat );
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
}
|
||||
@ -800,7 +901,7 @@ HRESULT LoadFromWICFile( LPCWSTR szFile, DWORD flags, TexMetadata* metadata, Scr
|
||||
// Save a WIC-supported file to memory
|
||||
//-------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
HRESULT SaveToWICMemory( const Image& image, DWORD flags, REFGUID guidContainerFormat, Blob& blob, const GUID* targetFormat )
|
||||
HRESULT SaveToWICMemory( const Image& image, DWORD flags, REFGUID containerFormat, Blob& blob, const GUID* targetFormat )
|
||||
{
|
||||
if ( !image.pixels )
|
||||
return E_POINTER;
|
||||
@ -812,7 +913,7 @@ HRESULT SaveToWICMemory( const Image& image, DWORD flags, REFGUID guidContainerF
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
hr = _EncodeSingleFrame( image, flags, guidContainerFormat, stream.Get(), targetFormat );
|
||||
hr = _EncodeSingleFrame( image, flags, containerFormat, stream.Get(), targetFormat );
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
@ -846,7 +947,7 @@ HRESULT SaveToWICMemory( const Image& image, DWORD flags, REFGUID guidContainerF
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
HRESULT SaveToWICMemory( const Image* images, size_t nimages, DWORD flags, REFGUID guidContainerFormat, Blob& blob, const GUID* targetFormat )
|
||||
HRESULT SaveToWICMemory( const Image* images, size_t nimages, DWORD flags, REFGUID containerFormat, Blob& blob, const GUID* targetFormat )
|
||||
{
|
||||
if ( !images || nimages == 0 )
|
||||
return E_INVALIDARG;
|
||||
@ -859,9 +960,9 @@ HRESULT SaveToWICMemory( const Image* images, size_t nimages, DWORD flags, REFGU
|
||||
return hr;
|
||||
|
||||
if ( nimages > 1 )
|
||||
hr = _EncodeMultiframe( images, nimages, flags, guidContainerFormat, stream.Get(), targetFormat );
|
||||
hr = _EncodeMultiframe( images, nimages, flags, containerFormat, stream.Get(), targetFormat );
|
||||
else
|
||||
hr = _EncodeSingleFrame( images[0], flags, guidContainerFormat, stream.Get(), targetFormat );
|
||||
hr = _EncodeSingleFrame( images[0], flags, containerFormat, stream.Get(), targetFormat );
|
||||
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
@ -900,7 +1001,7 @@ HRESULT SaveToWICMemory( const Image* images, size_t nimages, DWORD flags, REFGU
|
||||
// Save a WIC-supported file to disk
|
||||
//-------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
HRESULT SaveToWICFile( const Image& image, DWORD flags, REFGUID guidContainerFormat, LPCWSTR szFile, const GUID* targetFormat )
|
||||
HRESULT SaveToWICFile( const Image& image, DWORD flags, REFGUID containerFormat, LPCWSTR szFile, const GUID* targetFormat )
|
||||
{
|
||||
if ( !szFile )
|
||||
return E_INVALIDARG;
|
||||
@ -921,7 +1022,7 @@ HRESULT SaveToWICFile( const Image& image, DWORD flags, REFGUID guidContainerFor
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
hr = _EncodeSingleFrame( image, flags, guidContainerFormat, stream.Get(), targetFormat );
|
||||
hr = _EncodeSingleFrame( image, flags, containerFormat, stream.Get(), targetFormat );
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
@ -929,7 +1030,7 @@ HRESULT SaveToWICFile( const Image& image, DWORD flags, REFGUID guidContainerFor
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
HRESULT SaveToWICFile( const Image* images, size_t nimages, DWORD flags, REFGUID guidContainerFormat, LPCWSTR szFile, const GUID* targetFormat )
|
||||
HRESULT SaveToWICFile( const Image* images, size_t nimages, DWORD flags, REFGUID containerFormat, LPCWSTR szFile, const GUID* targetFormat )
|
||||
{
|
||||
if ( !szFile || !images || nimages == 0 )
|
||||
return E_INVALIDARG;
|
||||
@ -948,9 +1049,9 @@ HRESULT SaveToWICFile( const Image* images, size_t nimages, DWORD flags, REFGUID
|
||||
return hr;
|
||||
|
||||
if ( nimages > 1 )
|
||||
hr = _EncodeMultiframe( images, nimages, flags, guidContainerFormat, stream.Get(), targetFormat );
|
||||
hr = _EncodeMultiframe( images, nimages, flags, containerFormat, stream.Get(), targetFormat );
|
||||
else
|
||||
hr = _EncodeSingleFrame( images[0], flags, guidContainerFormat, stream.Get(), targetFormat );
|
||||
hr = _EncodeSingleFrame( images[0], flags, containerFormat, stream.Get(), targetFormat );
|
||||
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
|
@ -893,6 +893,7 @@ HRESULT DirectX::SaveWICTextureToFile( _In_ ID3D11DeviceContext* pContext,
|
||||
|
||||
// Determine source format's WIC equivalent
|
||||
WICPixelFormatGUID pfGuid;
|
||||
bool sRGB = false;
|
||||
switch ( desc.Format )
|
||||
{
|
||||
case DXGI_FORMAT_R32G32B32A32_FLOAT: pfGuid = GUID_WICPixelFormat128bppRGBAFloat; break;
|
||||
@ -909,20 +910,32 @@ HRESULT DirectX::SaveWICTextureToFile( _In_ ID3D11DeviceContext* pContext,
|
||||
case DXGI_FORMAT_A8_UNORM: pfGuid = GUID_WICPixelFormat8bppAlpha; break;
|
||||
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
|
||||
pfGuid = GUID_WICPixelFormat32bppRGBA;
|
||||
break;
|
||||
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
|
||||
pfGuid = GUID_WICPixelFormat32bppRGBA;
|
||||
sRGB = true;
|
||||
break;
|
||||
|
||||
case DXGI_FORMAT_B8G8R8A8_UNORM: // DXGI 1.1
|
||||
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
|
||||
pfGuid = GUID_WICPixelFormat32bppBGRA;
|
||||
break;
|
||||
|
||||
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: // DXGI 1.1
|
||||
pfGuid = GUID_WICPixelFormat32bppBGRA;
|
||||
sRGB = true;
|
||||
break;
|
||||
|
||||
case DXGI_FORMAT_B8G8R8X8_UNORM: // DXGI 1.1
|
||||
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
|
||||
pfGuid = GUID_WICPixelFormat32bppBGR;
|
||||
break;
|
||||
|
||||
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: // DXGI 1.1
|
||||
pfGuid = GUID_WICPixelFormat32bppBGR;
|
||||
sRGB = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
||||
}
|
||||
@ -1037,6 +1050,44 @@ HRESULT DirectX::SaveWICTextureToFile( _In_ ID3D11DeviceContext* pContext,
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
// Encode WIC metadata
|
||||
ScopedObject<IWICMetadataQueryWriter> metawriter;
|
||||
if ( SUCCEEDED( frame->GetMetadataQueryWriter( &metawriter ) ) )
|
||||
{
|
||||
PROPVARIANT value;
|
||||
PropVariantInit( &value );
|
||||
|
||||
value.vt = VT_LPSTR;
|
||||
value.pszVal = "DirectXTK";
|
||||
|
||||
if ( memcmp( &guidContainerFormat, &GUID_ContainerFormatPng, sizeof(GUID) ) == 0 )
|
||||
{
|
||||
// Set Software name
|
||||
(void)metawriter->SetMetadataByName( L"/tEXt/{str=Software}", &value );
|
||||
|
||||
// Set sRGB chunk
|
||||
if ( sRGB )
|
||||
{
|
||||
value.vt = VT_UI1;
|
||||
value.bVal = 0;
|
||||
(void)metawriter->SetMetadataByName( L"/sRGB/RenderingIntent", &value );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set Software name
|
||||
(void)metawriter->SetMetadataByName( L"System.ApplicationName", &value );
|
||||
|
||||
if ( sRGB )
|
||||
{
|
||||
// Set JPEG EXIF Colorspace of sRGB
|
||||
value.vt = VT_UI2;
|
||||
value.uiVal = 1;
|
||||
(void)metawriter->SetMetadataByName( L"System.Image.ColorSpace", &value );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE mapped;
|
||||
hr = pContext->Map( pStaging.Get(), 0, D3D11_MAP_READ, 0, &mapped );
|
||||
if ( FAILED(hr) )
|
||||
|
@ -532,6 +532,46 @@ static HRESULT CreateTextureFromWIC( _In_ ID3D11Device* d3dDevice,
|
||||
if ( !bpp )
|
||||
return E_FAIL;
|
||||
|
||||
// Handle sRGB formats
|
||||
if ( forceSRGB )
|
||||
{
|
||||
format = MakeSRGB( format );
|
||||
}
|
||||
else
|
||||
{
|
||||
ScopedObject<IWICMetadataQueryReader> metareader;
|
||||
if ( SUCCEEDED( frame->GetMetadataQueryReader( &metareader ) ) )
|
||||
{
|
||||
GUID containerFormat;
|
||||
if ( SUCCEEDED( metareader->GetContainerFormat( &containerFormat ) ) )
|
||||
{
|
||||
// Check for sRGB colorspace metadata
|
||||
bool sRGB = false;
|
||||
|
||||
PROPVARIANT value;
|
||||
PropVariantInit( &value );
|
||||
|
||||
if ( memcmp( &containerFormat, &GUID_ContainerFormatPng, sizeof(GUID) ) == 0 )
|
||||
{
|
||||
// Check for sRGB chunk
|
||||
if ( SUCCEEDED( metareader->GetMetadataByName( L"/sRGB/RenderingIntent", &value ) ) && value.vt == VT_UI1 )
|
||||
{
|
||||
sRGB = true;
|
||||
}
|
||||
}
|
||||
else if ( SUCCEEDED( metareader->GetMetadataByName( L"System.Image.ColorSpace", &value ) ) && value.vt == VT_UI2 && value.uiVal == 1 )
|
||||
{
|
||||
sRGB = true;
|
||||
}
|
||||
|
||||
PropVariantClear( &value );
|
||||
|
||||
if ( sRGB )
|
||||
format = MakeSRGB( format );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Verify our target format is supported by the current device
|
||||
// (handles WDDM 1.0 or WDDM 1.1 device driver cases as well as DirectX 11.0 Runtime without 16bpp format support)
|
||||
UINT support = 0;
|
||||
@ -645,7 +685,7 @@ static HRESULT CreateTextureFromWIC( _In_ ID3D11Device* d3dDevice,
|
||||
desc.Height = theight;
|
||||
desc.MipLevels = (autogen) ? 0 : 1;
|
||||
desc.ArraySize = 1;
|
||||
desc.Format = (forceSRGB) ? MakeSRGB( format ) : format;
|
||||
desc.Format = format;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = usage;
|
||||
|
Loading…
Reference in New Issue
Block a user