diff --git a/DirectXTex/DirectXTex.h b/DirectXTex/DirectXTex.h index 1a7481c..ae6b741 100644 --- a/DirectXTex/DirectXTex.h +++ b/DirectXTex/DirectXTex.h @@ -59,6 +59,9 @@ #define DIRECTX_TEX_VERSION 133 +struct IWICImagingFactory; + + namespace DirectX { @@ -374,19 +377,6 @@ namespace DirectX _In_z_ LPCWSTR szFile, _In_opt_ const GUID* targetFormat = nullptr, _In_opt_ std::function setCustomProps = nullptr ); - enum WICCodecs - { - WIC_CODEC_BMP =1, // Windows Bitmap (.bmp) - WIC_CODEC_JPEG, // Joint Photographic Experts Group (.jpg, .jpeg) - WIC_CODEC_PNG, // Portable Network Graphics (.png) - WIC_CODEC_TIFF, // Tagged Image File Format (.tif, .tiff) - WIC_CODEC_GIF, // Graphics Interchange Format (.gif) - WIC_CODEC_WMP, // Windows Media Photo / HD Photo / JPEG XR (.hdp, .jxr, .wdp) - WIC_CODEC_ICO, // Windows Icon (.ico) - }; - - REFGUID __cdecl GetWICCodec( _In_ WICCodecs codec ); - //--------------------------------------------------------------------------------- // Texture conversion, resizing, mipmap generation, and block compression @@ -584,6 +574,7 @@ namespace DirectX //--------------------------------------------------------------------------------- // Misc image operations + struct Rect { size_t x; @@ -619,6 +610,25 @@ namespace DirectX HRESULT __cdecl ComputeMSE( _In_ const Image& image1, _In_ const Image& image2, _Out_ float& mse, _Out_writes_opt_(4) float* mseV, _In_ DWORD flags = 0 ); + //--------------------------------------------------------------------------------- + // WIC utility code + + enum WICCodecs + { + WIC_CODEC_BMP = 1, // Windows Bitmap (.bmp) + WIC_CODEC_JPEG, // Joint Photographic Experts Group (.jpg, .jpeg) + WIC_CODEC_PNG, // Portable Network Graphics (.png) + WIC_CODEC_TIFF, // Tagged Image File Format (.tif, .tiff) + WIC_CODEC_GIF, // Graphics Interchange Format (.gif) + WIC_CODEC_WMP, // Windows Media Photo / HD Photo / JPEG XR (.hdp, .jxr, .wdp) + WIC_CODEC_ICO, // Windows Icon (.ico) + }; + + REFGUID __cdecl GetWICCodec(_In_ WICCodecs codec); + + IWICImagingFactory* __cdecl GetWICFactory( bool& iswic2 ); + void __cdecl SetWICFactory( _In_opt_ IWICImagingFactory* pWIC); + //--------------------------------------------------------------------------------- // Direct3D 11 functions bool __cdecl IsSupportedTexture( _In_ ID3D11Device* pDevice, _In_ const TexMetadata& metadata ); diff --git a/DirectXTex/DirectXTexConvert.cpp b/DirectXTex/DirectXTexConvert.cpp index f1e5713..a406b15 100644 --- a/DirectXTex/DirectXTexConvert.cpp +++ b/DirectXTex/DirectXTexConvert.cpp @@ -4374,7 +4374,8 @@ static HRESULT _ConvertUsingWIC( _In_ const Image& srcImage, _In_ const WICPixel assert( srcImage.width == destImage.width ); assert( srcImage.height == destImage.height ); - IWICImagingFactory* pWIC = _GetWIC(); + bool iswic2 = false; + IWICImagingFactory* pWIC = GetWICFactory(iswic2); if ( !pWIC ) return E_NOINTERFACE; diff --git a/DirectXTex/DirectXTexFlipRotate.cpp b/DirectXTex/DirectXTexFlipRotate.cpp index bf2b98e..3147fb8 100644 --- a/DirectXTex/DirectXTexFlipRotate.cpp +++ b/DirectXTex/DirectXTexFlipRotate.cpp @@ -31,7 +31,8 @@ static HRESULT _PerformFlipRotateUsingWIC( _In_ const Image& srcImage, _In_ DWOR assert( srcImage.format == destImage.format ); - IWICImagingFactory* pWIC = _GetWIC(); + bool iswic2 = false; + IWICImagingFactory* pWIC = GetWICFactory(iswic2); if ( !pWIC ) return E_NOINTERFACE; diff --git a/DirectXTex/DirectXTexMipmaps.cpp b/DirectXTex/DirectXTexMipmaps.cpp index 0df5b8e..3102320 100644 --- a/DirectXTex/DirectXTexMipmaps.cpp +++ b/DirectXTex/DirectXTexMipmaps.cpp @@ -166,7 +166,7 @@ static HRESULT _EnsureWicBitmapPixelFormat( _In_ IWICImagingFactory* pWIC, _In_ //--- Resizing color and alpha channels separately using WIC --- -HRESULT _ResizeSeparateColorAndAlpha( _In_ IWICImagingFactory* pWIC, _In_ IWICBitmap* original, +HRESULT _ResizeSeparateColorAndAlpha( _In_ IWICImagingFactory* pWIC, _In_ bool iswic2, _In_ IWICBitmap* original, _In_ size_t newWidth, _In_ size_t newHeight, _In_ DWORD filter, _Inout_ const Image* img ) { if ( !pWIC || !original || !img ) @@ -213,7 +213,7 @@ HRESULT _ResizeSeparateColorAndAlpha( _In_ IWICImagingFactory* pWIC, _In_ IWICBi else { #if(_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE) - if ( _IsWIC2() ) + if ( iswic2 ) { colorBytesInPixel = colorBytesPerPixel = 12; colorPixelFormat = GUID_WICPixelFormat96bppRGBFloat; @@ -451,7 +451,8 @@ static HRESULT _GenerateMipMapsUsingWIC( _In_ const Image& baseImage, _In_ DWORD if ( !baseImage.pixels || !mipChain.GetPixels() ) return E_POINTER; - IWICImagingFactory* pWIC = _GetWIC(); + bool iswic2 = false; + IWICImagingFactory* pWIC = GetWICFactory(iswic2); if ( !pWIC ) return E_NOINTERFACE; @@ -515,7 +516,7 @@ static HRESULT _GenerateMipMapsUsingWIC( _In_ const Image& baseImage, _In_ DWORD if ( (filter & TEX_FILTER_SEPARATE_ALPHA) && supportsTransparency ) { - hr = _ResizeSeparateColorAndAlpha( pWIC, source.Get(), width, height, filter, img ); + hr = _ResizeSeparateColorAndAlpha( pWIC, iswic2, source.Get(), width, height, filter, img ); if ( FAILED(hr) ) return hr; } diff --git a/DirectXTex/DirectXTexP.h b/DirectXTex/DirectXTexP.h index e4edc06..f541abe 100644 --- a/DirectXTex/DirectXTexP.h +++ b/DirectXTex/DirectXTexP.h @@ -55,8 +55,6 @@ #include "scoped.h" -struct IWICImagingFactory; - #define TEX_FILTER_MASK 0xF00000 #define XBOX_DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT DXGI_FORMAT(116) @@ -85,10 +83,6 @@ namespace DirectX DWORD __cdecl _CheckWICColorSpace( _In_ const GUID& sourceGUID, _In_ const GUID& targetGUID ); - IWICImagingFactory* __cdecl _GetWIC(); - - bool __cdecl _IsWIC2(); - inline WICBitmapDitherType __cdecl _GetWICDither( _In_ DWORD flags ) { static_assert( TEX_FILTER_DITHER == 0x10000, "TEX_FILTER_DITHER* flag values don't match mask" ); diff --git a/DirectXTex/DirectXTexResize.cpp b/DirectXTex/DirectXTexResize.cpp index 7ff093d..deff731 100644 --- a/DirectXTex/DirectXTexResize.cpp +++ b/DirectXTex/DirectXTexResize.cpp @@ -26,7 +26,7 @@ namespace DirectX // WIC related helper functions //------------------------------------------------------------------------------------- -extern HRESULT _ResizeSeparateColorAndAlpha( _In_ IWICImagingFactory* pWIC, _In_ IWICBitmap* original, +extern HRESULT _ResizeSeparateColorAndAlpha( _In_ IWICImagingFactory* pWIC, _In_ bool iswic2, _In_ IWICBitmap* original, _In_ size_t newWidth, _In_ size_t newHeight, _In_ DWORD filter, _Inout_ const Image* img ); //--- Do image resize using WIC --- @@ -38,7 +38,8 @@ static HRESULT _PerformResizeUsingWIC( _In_ const Image& srcImage, _In_ DWORD fi assert( srcImage.format == destImage.format ); - IWICImagingFactory* pWIC = _GetWIC(); + bool iswic2 = false; + IWICImagingFactory* pWIC = GetWICFactory(iswic2); if ( !pWIC ) return E_NOINTERFACE; @@ -66,7 +67,7 @@ static HRESULT _PerformResizeUsingWIC( _In_ const Image& srcImage, _In_ DWORD fi if ( (filter & TEX_FILTER_SEPARATE_ALPHA) && supportsTransparency ) { - hr = _ResizeSeparateColorAndAlpha( pWIC, source.Get(), destImage.width, destImage.height, filter, &destImage ); + hr = _ResizeSeparateColorAndAlpha( pWIC, iswic2, source.Get(), destImage.width, destImage.height, filter, &destImage ); if ( FAILED(hr) ) return hr; } diff --git a/DirectXTex/DirectXTexUtil.cpp b/DirectXTex/DirectXTexUtil.cpp index 3170ee3..e238243 100644 --- a/DirectXTex/DirectXTexUtil.cpp +++ b/DirectXTex/DirectXTexUtil.cpp @@ -15,6 +15,8 @@ #include "directxtexp.h" +using Microsoft::WRL::ComPtr; + #if defined(_XBOX_ONE) && defined(_TITLE) static_assert(XBOX_DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT == DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT, "Xbox One XDK mismatch detected"); static_assert(XBOX_DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT == DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT, "Xbox One XDK mismatch detected"); @@ -70,6 +72,8 @@ static WICTranslate g_WICFormats[] = }; static bool g_WIC2 = false; +static IWICImagingFactory* g_Factory = nullptr; + namespace DirectX { @@ -186,67 +190,6 @@ DWORD _CheckWICColorSpace( _In_ const GUID& sourceGUID, _In_ const GUID& targetG return srgb; } -bool _IsWIC2() -{ - return g_WIC2; -} - -IWICImagingFactory* _GetWIC() -{ - static IWICImagingFactory* s_Factory = nullptr; - - if ( s_Factory ) - return s_Factory; - -#if(_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE) - HRESULT hr = CoCreateInstance( - CLSID_WICImagingFactory2, - nullptr, - CLSCTX_INPROC_SERVER, - __uuidof(IWICImagingFactory2), - (LPVOID*)&s_Factory - ); - - if ( SUCCEEDED(hr) ) - { - // WIC2 is available on Windows 8 and Windows 7 SP1 with KB 2670838 installed - g_WIC2 = true; - } - else - { - hr = CoCreateInstance( - CLSID_WICImagingFactory1, - nullptr, - CLSCTX_INPROC_SERVER, - __uuidof(IWICImagingFactory), - (LPVOID*)&s_Factory - ); - - if ( FAILED(hr) ) - { - s_Factory = nullptr; - return nullptr; - } - } -#else - HRESULT hr = CoCreateInstance( - CLSID_WICImagingFactory, - nullptr, - CLSCTX_INPROC_SERVER, - __uuidof(IWICImagingFactory), - (LPVOID*)&s_Factory - ); - - if ( FAILED(hr) ) - { - s_Factory = nullptr; - return nullptr; - } -#endif - - return s_Factory; -} - //------------------------------------------------------------------------------------- // Public helper function to get common WIC codec GUIDs @@ -283,6 +226,102 @@ REFGUID GetWICCodec( WICCodecs codec ) } +//------------------------------------------------------------------------------------- +// Singleton function for WIC factory +//------------------------------------------------------------------------------------- +IWICImagingFactory* GetWICFactory(bool& iswic2) +{ + if (g_Factory) + { + iswic2 = g_WIC2; + return g_Factory; + } + +#if(_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE) + HRESULT hr = CoCreateInstance( + CLSID_WICImagingFactory2, + nullptr, + CLSCTX_INPROC_SERVER, + __uuidof(IWICImagingFactory2), + (LPVOID*)&g_Factory + ); + + if (SUCCEEDED(hr)) + { + // WIC2 is available on Windows 8 and Windows 7 SP1 with KB 2670838 installed + g_WIC2 = true; + } + else + { + g_WIC2 = false; + + hr = CoCreateInstance( + CLSID_WICImagingFactory1, + nullptr, + CLSCTX_INPROC_SERVER, + __uuidof(IWICImagingFactory), + (LPVOID*)&g_Factory + ); + + if (FAILED(hr)) + { + g_Factory = nullptr; + return nullptr; + } + } +#else + HRESULT hr = CoCreateInstance( + CLSID_WICImagingFactory, + nullptr, + CLSCTX_INPROC_SERVER, + __uuidof(IWICImagingFactory), + (LPVOID*)&s_Factory + ); + + g_WIC2 = false; + + if (FAILED(hr)) + { + g_Factory = nullptr; + return nullptr; + } +#endif + + iswic2 = g_WIC2; + return g_Factory; +} + + +//------------------------------------------------------------------------------------- +// Optional initializer for WIC factory +//------------------------------------------------------------------------------------- +void SetWICFactory(_In_opt_ IWICImagingFactory* pWIC) +{ + if (pWIC == g_Factory) + return; + + bool iswic2 = false; + if (pWIC) + { +#if(_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE) + ComPtr wic2; + HRESULT hr = pWIC->QueryInterface(_uuidof(IWICImagingFactory2), reinterpret_cast(wic2.GetAddressOf())); + if (SUCCEEDED(hr)) + { + iswic2 = true; + } +#endif + pWIC->AddRef(); + } + + g_WIC2 = iswic2; + std::swap(pWIC, g_Factory); + if ( pWIC ) + pWIC->Release(); +} + + + //===================================================================================== // DXGI Format Utilities //===================================================================================== diff --git a/DirectXTex/DirectXTexWIC.cpp b/DirectXTex/DirectXTexWIC.cpp index f599a11..00f7613 100644 --- a/DirectXTex/DirectXTexWIC.cpp +++ b/DirectXTex/DirectXTexWIC.cpp @@ -141,7 +141,7 @@ namespace DirectX //------------------------------------------------------------------------------------- // Returns the DXGI format and optionally the WIC pixel GUID to convert to //------------------------------------------------------------------------------------- -static DXGI_FORMAT _DetermineFormat( _In_ const WICPixelFormatGUID& pixelFormat, _In_ DWORD flags, +static DXGI_FORMAT _DetermineFormat( _In_ const WICPixelFormatGUID& pixelFormat, _In_ DWORD flags, _In_ bool iswic2, _Out_opt_ WICPixelFormatGUID* pConvert ) { if ( pConvert ) @@ -154,7 +154,7 @@ static DXGI_FORMAT _DetermineFormat( _In_ const WICPixelFormatGUID& pixelFormat, if ( memcmp( &GUID_WICPixelFormat96bppRGBFixedPoint, &pixelFormat, sizeof(WICPixelFormatGUID) ) == 0 ) { #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE) - if ( _IsWIC2() ) + if ( iswic2 ) { if ( pConvert ) memcpy( pConvert, &GUID_WICPixelFormat96bppRGBFloat, sizeof(WICPixelFormatGUID) ); @@ -234,7 +234,7 @@ static DXGI_FORMAT _DetermineFormat( _In_ const WICPixelFormatGUID& pixelFormat, //------------------------------------------------------------------------------------- // Determines metadata for image //------------------------------------------------------------------------------------- -static HRESULT _DecodeMetadata( _In_ DWORD flags, +static HRESULT _DecodeMetadata( _In_ DWORD flags, _In_ bool iswic2, _In_ IWICBitmapDecoder *decoder, _In_ IWICBitmapFrameDecode *frame, _Out_ TexMetadata& metadata, _Out_opt_ WICPixelFormatGUID* pConvert ) { @@ -271,7 +271,7 @@ static HRESULT _DecodeMetadata( _In_ DWORD flags, if ( FAILED(hr) ) return hr; - metadata.format = _DetermineFormat( pixelFormat, flags, pConvert ); + metadata.format = _DetermineFormat( pixelFormat, flags, iswic2, pConvert ); if ( metadata.format == DXGI_FORMAT_UNKNOWN ) return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); @@ -355,7 +355,8 @@ static HRESULT _DecodeSingleFrame( _In_ DWORD flags, _In_ const TexMetadata& met if ( !img ) return E_POINTER; - IWICImagingFactory* pWIC = _GetWIC(); + bool iswic2 = false; + IWICImagingFactory* pWIC = GetWICFactory(iswic2); if ( !pWIC ) return E_NOINTERFACE; @@ -410,7 +411,8 @@ static HRESULT _DecodeMultiframe( _In_ DWORD flags, _In_ const TexMetadata& meta if ( FAILED(hr) ) return hr; - IWICImagingFactory* pWIC = _GetWIC(); + bool iswic2 = false; + IWICImagingFactory* pWIC = GetWICFactory(iswic2); if ( !pWIC ) return E_NOINTERFACE; @@ -662,7 +664,8 @@ static HRESULT _EncodeImage( _In_ const Image& image, _In_ DWORD flags, _In_ REF if ( memcmp( &targetGuid, &pfGuid, sizeof(WICPixelFormatGUID) ) != 0 ) { // Conversion required to write - IWICImagingFactory* pWIC = _GetWIC(); + bool iswic2 = false; + IWICImagingFactory* pWIC = GetWICFactory(iswic2); if ( !pWIC ) return E_NOINTERFACE; @@ -718,7 +721,8 @@ static HRESULT _EncodeSingleFrame( _In_ const Image& image, _In_ DWORD flags, return E_INVALIDARG; // Initialize WIC - IWICImagingFactory* pWIC = _GetWIC(); + bool iswic2 = false; + IWICImagingFactory* pWIC = GetWICFactory(iswic2); if ( !pWIC ) return E_NOINTERFACE; @@ -737,7 +741,7 @@ static HRESULT _EncodeSingleFrame( _In_ const Image& image, _In_ DWORD flags, if ( FAILED(hr) ) return hr; - if ( memcmp( &containerFormat, &GUID_ContainerFormatBmp, sizeof(WICPixelFormatGUID) ) == 0 && _IsWIC2() ) + if ( memcmp( &containerFormat, &GUID_ContainerFormatBmp, sizeof(WICPixelFormatGUID) ) == 0 && iswic2 ) { // Opt-in to the WIC2 support for writing 32-bit Windows BMP files with an alpha channel PROPBAG2 option = { 0 }; @@ -780,7 +784,8 @@ static HRESULT _EncodeMultiframe( _In_reads_(nimages) const Image* images, _In_ return E_POINTER; // Initialize WIC - IWICImagingFactory* pWIC = _GetWIC(); + bool iswic2 = false; + IWICImagingFactory* pWIC = GetWICFactory(iswic2); if ( !pWIC ) return E_NOINTERFACE; @@ -850,7 +855,8 @@ HRESULT GetMetadataFromWICMemory( LPCVOID pSource, size_t size, DWORD flags, Tex return HRESULT_FROM_WIN32( ERROR_FILE_TOO_LARGE ); #endif - IWICImagingFactory* pWIC = _GetWIC(); + bool iswic2 = false; + IWICImagingFactory* pWIC = GetWICFactory(iswic2); if ( !pWIC ) return E_NOINTERFACE; @@ -877,7 +883,7 @@ HRESULT GetMetadataFromWICMemory( LPCVOID pSource, size_t size, DWORD flags, Tex return hr; // Get metadata - hr = _DecodeMetadata( flags, decoder.Get(), frame.Get(), metadata, 0 ); + hr = _DecodeMetadata( flags, iswic2, decoder.Get(), frame.Get(), metadata, 0 ); if ( FAILED(hr) ) return hr; @@ -894,7 +900,8 @@ HRESULT GetMetadataFromWICFile( LPCWSTR szFile, DWORD flags, TexMetadata& metada if ( !szFile ) return E_INVALIDARG; - IWICImagingFactory* pWIC = _GetWIC(); + bool iswic2 = false; + IWICImagingFactory* pWIC = GetWICFactory(iswic2); if ( !pWIC ) return E_NOINTERFACE; @@ -910,7 +917,7 @@ HRESULT GetMetadataFromWICFile( LPCWSTR szFile, DWORD flags, TexMetadata& metada return hr; // Get metadata - hr = _DecodeMetadata( flags, decoder.Get(), frame.Get(), metadata, 0 ); + hr = _DecodeMetadata( flags, iswic2, decoder.Get(), frame.Get(), metadata, 0 ); if ( FAILED(hr) ) return hr; @@ -932,7 +939,8 @@ HRESULT LoadFromWICMemory( LPCVOID pSource, size_t size, DWORD flags, TexMetadat return HRESULT_FROM_WIN32( ERROR_FILE_TOO_LARGE ); #endif - IWICImagingFactory* pWIC = _GetWIC(); + bool iswic2 = false; + IWICImagingFactory* pWIC = GetWICFactory(iswic2); if ( !pWIC ) return E_NOINTERFACE; @@ -962,7 +970,7 @@ HRESULT LoadFromWICMemory( LPCVOID pSource, size_t size, DWORD flags, TexMetadat // Get metadata TexMetadata mdata; WICPixelFormatGUID convertGUID = {0}; - hr = _DecodeMetadata( flags, decoder.Get(), frame.Get(), mdata, &convertGUID ); + hr = _DecodeMetadata( flags, iswic2, decoder.Get(), frame.Get(), mdata, &convertGUID ); if ( FAILED(hr) ) return hr; @@ -997,7 +1005,8 @@ HRESULT LoadFromWICFile( LPCWSTR szFile, DWORD flags, TexMetadata* metadata, Scr if ( !szFile ) return E_INVALIDARG; - IWICImagingFactory* pWIC = _GetWIC(); + bool iswic2 = false; + IWICImagingFactory* pWIC = GetWICFactory(iswic2); if ( !pWIC ) return E_NOINTERFACE; @@ -1017,7 +1026,7 @@ HRESULT LoadFromWICFile( LPCWSTR szFile, DWORD flags, TexMetadata* metadata, Scr // Get metadata TexMetadata mdata; WICPixelFormatGUID convertGUID = {0}; - hr = _DecodeMetadata( flags, decoder.Get(), frame.Get(), mdata, &convertGUID ); + hr = _DecodeMetadata( flags, iswic2, decoder.Get(), frame.Get(), mdata, &convertGUID ); if ( FAILED(hr) ) return hr; @@ -1158,7 +1167,8 @@ HRESULT SaveToWICFile( const Image& image, DWORD flags, REFGUID containerFormat, if ( !image.pixels ) return E_POINTER; - IWICImagingFactory* pWIC = _GetWIC(); + bool iswic2 = false; + IWICImagingFactory* pWIC = GetWICFactory(iswic2); if ( !pWIC ) return E_NOINTERFACE; @@ -1185,7 +1195,8 @@ HRESULT SaveToWICFile( const Image* images, size_t nimages, DWORD flags, REFGUID if ( !szFile || !images || nimages == 0 ) return E_INVALIDARG; - IWICImagingFactory* pWIC = _GetWIC(); + bool iswic2 = false; + IWICImagingFactory* pWIC = GetWICFactory(iswic2); if ( !pWIC ) return E_NOINTERFACE;