1 //-------------------------------------------------------------------------------------
4 // DirectX Texture Library - WIC-based file reader/writer
6 // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
7 // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
8 // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
11 // Copyright (c) Microsoft Corporation. All rights reserved.
13 // http://go.microsoft.com/fwlink/?LinkId=248926
14 //-------------------------------------------------------------------------------------
16 #include "DirectXTexP.h"
18 //-------------------------------------------------------------------------------------
19 // WIC Pixel Format nearest conversion table
20 //-------------------------------------------------------------------------------------
28 static WICConvert g_WICConvert[] =
30 // Directly support the formats listed in XnaTexUtil::g_WICFormats, so no conversion required
31 // Note target GUID in this conversion table must be one of those directly supported formats.
33 { GUID_WICPixelFormat1bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
34 { GUID_WICPixelFormat2bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
35 { GUID_WICPixelFormat4bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
36 { GUID_WICPixelFormat8bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
38 { GUID_WICPixelFormat2bppGray, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM
39 { GUID_WICPixelFormat4bppGray, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM
41 { GUID_WICPixelFormat16bppGrayFixedPoint, GUID_WICPixelFormat16bppGrayHalf }, // DXGI_FORMAT_R16_FLOAT
42 { GUID_WICPixelFormat32bppGrayFixedPoint, GUID_WICPixelFormat32bppGrayFloat }, // DXGI_FORMAT_R32_FLOAT
44 { GUID_WICPixelFormat16bppBGR555, GUID_WICPixelFormat16bppBGRA5551 }, // DXGI_FORMAT_B5G5R5A1_UNORM
45 { GUID_WICPixelFormat32bppBGR101010, GUID_WICPixelFormat32bppRGBA1010102 }, // DXGI_FORMAT_R10G10B10A2_UNORM
47 { GUID_WICPixelFormat24bppBGR, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
48 { GUID_WICPixelFormat24bppRGB, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
49 { GUID_WICPixelFormat32bppPBGRA, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
50 { GUID_WICPixelFormat32bppPRGBA, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
52 { GUID_WICPixelFormat48bppRGB, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
53 { GUID_WICPixelFormat48bppBGR, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
54 { GUID_WICPixelFormat64bppBGRA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
55 { GUID_WICPixelFormat64bppPRGBA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
56 { GUID_WICPixelFormat64bppPBGRA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
58 { GUID_WICPixelFormat48bppRGBFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
59 { GUID_WICPixelFormat48bppBGRFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
60 { GUID_WICPixelFormat64bppRGBAFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
61 { GUID_WICPixelFormat64bppBGRAFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
62 { GUID_WICPixelFormat64bppRGBFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
63 { GUID_WICPixelFormat64bppRGBHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
64 { GUID_WICPixelFormat48bppRGBHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
66 { GUID_WICPixelFormat128bppPRGBAFloat, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
67 { GUID_WICPixelFormat128bppRGBFloat, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
68 { GUID_WICPixelFormat128bppRGBAFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
69 { GUID_WICPixelFormat128bppRGBFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
71 { GUID_WICPixelFormat32bppCMYK, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
72 { GUID_WICPixelFormat64bppCMYK, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
73 { GUID_WICPixelFormat40bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
74 { GUID_WICPixelFormat80bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
76 #if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) || defined(_WIN7_PLATFORM_UPDATE)
77 { GUID_WICPixelFormat32bppRGB, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
78 { GUID_WICPixelFormat64bppRGB, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
79 { GUID_WICPixelFormat64bppPRGBAHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
82 // We don't support n-channel formats
88 //-------------------------------------------------------------------------------------
89 // Returns the DXGI format and optionally the WIC pixel GUID to convert to
90 //-------------------------------------------------------------------------------------
91 static DXGI_FORMAT _DetermineFormat( _In_ const WICPixelFormatGUID& pixelFormat, _In_ DWORD flags,
92 _Out_opt_ WICPixelFormatGUID* pConvert )
95 memset( pConvert, 0, sizeof(WICPixelFormatGUID) );
97 DXGI_FORMAT format = _WICToDXGI( pixelFormat );
99 if ( format == DXGI_FORMAT_UNKNOWN )
101 if ( memcmp( &GUID_WICPixelFormat96bppRGBFixedPoint, &pixelFormat, sizeof(WICPixelFormatGUID) ) == 0 )
103 #if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) || defined(_WIN7_PLATFORM_UPDATE)
107 memcpy( pConvert, &GUID_WICPixelFormat96bppRGBFloat, sizeof(WICPixelFormatGUID) );
108 format = DXGI_FORMAT_R32G32B32_FLOAT;
114 memcpy( pConvert, &GUID_WICPixelFormat128bppRGBAFloat, sizeof(WICPixelFormatGUID) );
115 format = DXGI_FORMAT_R32G32B32A32_FLOAT;
120 for( size_t i=0; i < _countof(g_WICConvert); ++i )
122 if ( memcmp( &g_WICConvert[i].source, &pixelFormat, sizeof(WICPixelFormatGUID) ) == 0 )
125 memcpy( pConvert, &g_WICConvert[i].target, sizeof(WICPixelFormatGUID) );
127 format = _WICToDXGI( g_WICConvert[i].target );
128 assert( format != DXGI_FORMAT_UNKNOWN );
135 // Handle special cases based on flags
138 case DXGI_FORMAT_B8G8R8A8_UNORM: // BGRA
139 case DXGI_FORMAT_B8G8R8X8_UNORM: // BGRX
140 if ( flags & WIC_FLAGS_FORCE_RGB )
142 format = DXGI_FORMAT_R8G8B8A8_UNORM;
144 memcpy( pConvert, &GUID_WICPixelFormat32bppRGBA, sizeof(WICPixelFormatGUID) );
148 case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
149 if ( flags & WIC_FLAGS_NO_X2_BIAS )
151 format = DXGI_FORMAT_R10G10B10A2_UNORM;
153 memcpy( pConvert, &GUID_WICPixelFormat32bppRGBA1010102, sizeof(WICPixelFormatGUID) );
157 case DXGI_FORMAT_B5G5R5A1_UNORM:
158 case DXGI_FORMAT_B5G6R5_UNORM:
159 if ( flags & WIC_FLAGS_NO_16BPP )
161 format = DXGI_FORMAT_R8G8B8A8_UNORM;
163 memcpy( pConvert, &GUID_WICPixelFormat32bppRGBA, sizeof(WICPixelFormatGUID) );
167 case DXGI_FORMAT_R1_UNORM:
168 if ( !(flags & WIC_FLAGS_ALLOW_MONO ) )
170 // By default we want to promote a black & white to gresycale since R1 is not a generally supported D3D format
171 format = DXGI_FORMAT_R8_UNORM;
173 memcpy( pConvert, &GUID_WICPixelFormat8bppGray, sizeof(WICPixelFormatGUID) );
181 //-------------------------------------------------------------------------------------
182 // Determines metadata for image
183 //-------------------------------------------------------------------------------------
184 static HRESULT _DecodeMetadata( _In_ DWORD flags,
185 _In_ IWICBitmapDecoder *decoder, _In_ IWICBitmapFrameDecode *frame,
186 _Out_ TexMetadata& metadata, _Out_opt_ WICPixelFormatGUID* pConvert )
188 if ( !decoder || !frame )
191 memset( &metadata, 0, sizeof(TexMetadata) );
193 metadata.mipLevels = 1;
194 metadata.dimension = TEX_DIMENSION_TEXTURE2D;
197 HRESULT hr = frame->GetSize( &w, &h );
204 if ( flags & WIC_FLAGS_ALL_FRAMES )
207 hr = decoder->GetFrameCount( &fcount );
211 metadata.arraySize = fcount;
214 metadata.arraySize = 1;
216 WICPixelFormatGUID pixelFormat;
217 hr = frame->GetPixelFormat( &pixelFormat );
221 metadata.format = _DetermineFormat( pixelFormat, flags, pConvert );
222 if ( metadata.format == DXGI_FORMAT_UNKNOWN )
223 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
229 //-------------------------------------------------------------------------------------
230 // Decodes a single frame
231 //-------------------------------------------------------------------------------------
232 static HRESULT _DecodeSingleFrame( _In_ DWORD flags, _In_ const TexMetadata& metadata, _In_ const WICPixelFormatGUID& convertGUID,
233 _In_ IWICBitmapFrameDecode *frame, _Inout_ ScratchImage& image )
238 HRESULT hr = image.Initialize2D( metadata.format, metadata.width, metadata.height, 1, 1 );
242 const Image *img = image.GetImage( 0, 0, 0 );
246 IWICImagingFactory* pWIC = _GetWIC();
248 return E_NOINTERFACE;
250 if ( memcmp( &convertGUID, &GUID_NULL, sizeof(GUID) ) == 0 )
252 hr = frame->CopyPixels( 0, static_cast<UINT>( img->rowPitch ), static_cast<UINT>( img->slicePitch ), img->pixels );
258 ScopedObject<IWICFormatConverter> FC;
259 hr = pWIC->CreateFormatConverter( &FC );
263 hr = FC->Initialize( frame, convertGUID, _GetWICDither( flags ), 0, 0, WICBitmapPaletteTypeCustom );
267 hr = FC->CopyPixels( 0, static_cast<UINT>( img->rowPitch ), static_cast<UINT>( img->slicePitch ), img->pixels );
276 //-------------------------------------------------------------------------------------
277 // Decodes an image array, resizing/format converting as needed
278 //-------------------------------------------------------------------------------------
279 static HRESULT _DecodeMultiframe( _In_ DWORD flags, _In_ const TexMetadata& metadata,
280 _In_ IWICBitmapDecoder *decoder, _Inout_ ScratchImage& image )
285 HRESULT hr = image.Initialize2D( metadata.format, metadata.width, metadata.height, metadata.arraySize, 1 );
289 IWICImagingFactory* pWIC = _GetWIC();
291 return E_NOINTERFACE;
293 WICPixelFormatGUID sourceGUID;
294 if ( !_DXGIToWIC( metadata.format, sourceGUID ) )
297 for( size_t index = 0; index < metadata.arraySize; ++index )
299 const Image* img = image.GetImage( 0, index, 0 );
303 ScopedObject<IWICBitmapFrameDecode> frame;
304 hr = decoder->GetFrame( static_cast<UINT>( index ), &frame );
308 WICPixelFormatGUID pfGuid;
309 hr = frame->GetPixelFormat( &pfGuid );
314 hr = frame->GetSize( &w, &h );
318 if ( memcmp( &pfGuid, &sourceGUID, sizeof(WICPixelFormatGUID) ) == 0 )
320 if ( w == metadata.width && h == metadata.height )
322 // This frame does not need resized or format converted, just copy...
323 hr = frame->CopyPixels( 0, static_cast<UINT>( img->rowPitch ), static_cast<UINT>( img->slicePitch ), img->pixels );
329 // This frame needs resizing, but not format converted
330 ScopedObject<IWICBitmapScaler> scaler;
331 hr = pWIC->CreateBitmapScaler( &scaler );
335 hr = scaler->Initialize( frame.Get(), static_cast<UINT>( metadata.width ), static_cast<UINT>( metadata.height ), _GetWICInterp( flags ) );
339 hr = scaler->CopyPixels( 0, static_cast<UINT>( img->rowPitch ), static_cast<UINT>( img->slicePitch ), img->pixels );
346 // This frame required format conversion
347 ScopedObject<IWICFormatConverter> FC;
348 hr = pWIC->CreateFormatConverter( &FC );
352 hr = FC->Initialize( frame.Get(), pfGuid, _GetWICDither( flags ), 0, 0, WICBitmapPaletteTypeCustom );
356 if ( w == metadata.width && h == metadata.height )
358 // This frame is the same size, no need to scale
359 hr = FC->CopyPixels( 0, static_cast<UINT>( img->rowPitch ), static_cast<UINT>( img->slicePitch ), img->pixels );
365 // This frame needs resizing and format converted
366 ScopedObject<IWICBitmapScaler> scaler;
367 hr = pWIC->CreateBitmapScaler( &scaler );
371 hr = scaler->Initialize( FC.Get(), static_cast<UINT>( metadata.width ), static_cast<UINT>( metadata.height ), _GetWICInterp( flags ) );
375 hr = scaler->CopyPixels( 0, static_cast<UINT>( img->rowPitch ), static_cast<UINT>( img->slicePitch ), img->pixels );
386 //-------------------------------------------------------------------------------------
387 // Encodes a single frame
388 //-------------------------------------------------------------------------------------
389 static HRESULT _EncodeImage( _In_ const Image& image, _In_ DWORD flags, _In_ IWICBitmapFrameEncode* frame, _In_opt_ IPropertyBag2* props, _In_opt_ const GUID* targetFormat )
397 WICPixelFormatGUID pfGuid;
398 if ( !_DXGIToWIC( image.format, pfGuid ) )
399 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
401 HRESULT hr = frame->Initialize( props );
406 if ( (image.width > 0xFFFFFFFF) || (image.height > 0xFFFFFFFF) )
410 hr = frame->SetSize( static_cast<UINT>( image.width ), static_cast<UINT>( image.height ) );
414 hr = frame->SetResolution( 72, 72 );
418 WICPixelFormatGUID targetGuid = (targetFormat) ? (*targetFormat) : pfGuid;
419 hr = frame->SetPixelFormat( &targetGuid );
423 if ( memcmp( &targetGuid, &pfGuid, sizeof(WICPixelFormatGUID) ) != 0 )
425 // Conversion required to write
426 IWICImagingFactory* pWIC = _GetWIC();
428 return E_NOINTERFACE;
430 ScopedObject<IWICBitmap> source;
431 hr = pWIC->CreateBitmapFromMemory( static_cast<UINT>( image.width ), static_cast<UINT>( image.height ), pfGuid,
432 static_cast<UINT>( image.rowPitch ), static_cast<UINT>( image.slicePitch ),
433 image.pixels, &source );
437 ScopedObject<IWICFormatConverter> FC;
438 hr = pWIC->CreateFormatConverter( &FC );
442 hr = FC->Initialize( source.Get(), targetGuid, _GetWICDither( flags ), 0, 0, WICBitmapPaletteTypeCustom );
446 WICRect rect = { 0, 0, static_cast<UINT>( image.width ), static_cast<UINT>( image.height ) };
447 hr = frame->WriteSource( FC.Get(), &rect );
453 // No conversion required
454 hr = frame->WritePixels( static_cast<UINT>( image.height ), static_cast<UINT>( image.rowPitch ), static_cast<UINT>( image.slicePitch ),
455 reinterpret_cast<uint8_t*>( image.pixels ) );
460 hr = frame->Commit();
467 static HRESULT _EncodeSingleFrame( _In_ const Image& image, _In_ DWORD flags,
468 _In_ REFGUID guidContainerFormat, _Inout_ IStream* stream, _In_opt_ const GUID* targetFormat )
474 IWICImagingFactory* pWIC = _GetWIC();
476 return E_NOINTERFACE;
478 ScopedObject<IWICBitmapEncoder> encoder;
479 HRESULT hr = pWIC->CreateEncoder( guidContainerFormat, 0, &encoder );
483 hr = encoder->Initialize( stream, WICBitmapEncoderNoCache );
487 ScopedObject<IWICBitmapFrameEncode> frame;
488 ScopedObject<IPropertyBag2> props;
489 hr = encoder->CreateNewFrame( &frame, &props );
493 if ( memcmp( &guidContainerFormat, &GUID_ContainerFormatBmp, sizeof(WICPixelFormatGUID) ) == 0 )
495 // Opt-in to the Windows 8 support for writing 32-bit Windows BMP files with an alpha channel if supported
496 PROPBAG2 option = { 0 };
497 option.pstrName = L"EnableV5Header32bppBGRA";
500 varValue.vt = VT_BOOL;
501 varValue.boolVal = VARIANT_TRUE;
502 hr = props->Write( 1, &option, &varValue );
505 // Fails on older versions of WIC, so we default to the null property bag
510 hr = _EncodeImage( image, flags, frame.Get(), props.Get(), targetFormat );
514 hr = encoder->Commit();
522 //-------------------------------------------------------------------------------------
523 // Encodes an image array
524 //-------------------------------------------------------------------------------------
525 static HRESULT _EncodeMultiframe( _In_count_(nimages) const Image* images, _In_ size_t nimages, _In_ DWORD flags,
526 _In_ REFGUID guidContainerFormat, _Inout_ IStream* stream, _In_opt_ const GUID* targetFormat )
528 if ( !stream || nimages < 2 )
535 IWICImagingFactory* pWIC = _GetWIC();
537 return E_NOINTERFACE;
539 ScopedObject<IWICBitmapEncoder> encoder;
540 HRESULT hr = pWIC->CreateEncoder( guidContainerFormat, 0, &encoder );
544 ScopedObject<IWICBitmapEncoderInfo> einfo;
545 hr = encoder->GetEncoderInfo( &einfo );
550 hr = einfo->DoesSupportMultiframe( &mframe );
555 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
557 hr = encoder->Initialize( stream, WICBitmapEncoderNoCache );
561 for( size_t index=0; index < nimages; ++index )
563 ScopedObject<IWICBitmapFrameEncode> frame;
564 hr = encoder->CreateNewFrame( &frame, nullptr );
568 hr = _EncodeImage( images[index], flags, frame.Get(), nullptr, targetFormat );
573 hr = encoder->Commit();
581 //=====================================================================================
583 //=====================================================================================
585 //-------------------------------------------------------------------------------------
586 // Obtain metadata from WIC-supported file in memory
587 //-------------------------------------------------------------------------------------
588 HRESULT GetMetadataFromWICMemory( LPCVOID pSource, size_t size, DWORD flags, TexMetadata& metadata )
590 if ( !pSource || size == 0 )
594 if ( size > 0xFFFFFFFF )
595 return HRESULT_FROM_WIN32( ERROR_FILE_TOO_LARGE );
598 IWICImagingFactory* pWIC = _GetWIC();
600 return E_NOINTERFACE;
602 // Create input stream for memory
603 ScopedObject<IWICStream> stream;
604 HRESULT hr = pWIC->CreateStream( &stream );
608 hr = stream->InitializeFromMemory( reinterpret_cast<BYTE*>( const_cast<void*>( pSource ) ),
609 static_cast<UINT>( size ) );
614 ScopedObject<IWICBitmapDecoder> decoder;
615 hr = pWIC->CreateDecoderFromStream( stream.Get(), 0, WICDecodeMetadataCacheOnDemand, &decoder );
619 ScopedObject<IWICBitmapFrameDecode> frame;
620 hr = decoder->GetFrame( 0, &frame );
625 hr = _DecodeMetadata( flags, decoder.Get(), frame.Get(), metadata, 0 );
633 //-------------------------------------------------------------------------------------
634 // Obtain metadata from WIC-supported file on disk
635 //-------------------------------------------------------------------------------------
636 HRESULT GetMetadataFromWICFile( LPCWSTR szFile, DWORD flags, TexMetadata& metadata )
641 IWICImagingFactory* pWIC = _GetWIC();
643 return E_NOINTERFACE;
646 ScopedObject<IWICBitmapDecoder> decoder;
647 HRESULT hr = pWIC->CreateDecoderFromFilename( szFile, 0, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &decoder );
651 ScopedObject<IWICBitmapFrameDecode> frame;
652 hr = decoder->GetFrame( 0, &frame );
657 hr = _DecodeMetadata( flags, decoder.Get(), frame.Get(), metadata, 0 );
665 //-------------------------------------------------------------------------------------
666 // Load a WIC-supported file in memory
667 //-------------------------------------------------------------------------------------
668 HRESULT LoadFromWICMemory( LPCVOID pSource, size_t size, DWORD flags, TexMetadata* metadata, ScratchImage& image )
670 if ( !pSource || size == 0 )
674 if ( size > 0xFFFFFFFF )
675 return HRESULT_FROM_WIN32( ERROR_FILE_TOO_LARGE );
678 IWICImagingFactory* pWIC = _GetWIC();
680 return E_NOINTERFACE;
684 // Create input stream for memory
685 ScopedObject<IWICStream> stream;
686 HRESULT hr = pWIC->CreateStream( &stream );
690 hr = stream->InitializeFromMemory( reinterpret_cast<uint8_t*>( const_cast<void*>( pSource ) ), static_cast<DWORD>( size ) );
695 ScopedObject<IWICBitmapDecoder> decoder;
696 hr = pWIC->CreateDecoderFromStream( stream.Get(), 0, WICDecodeMetadataCacheOnDemand, &decoder );
700 ScopedObject<IWICBitmapFrameDecode> frame;
701 hr = decoder->GetFrame( 0, &frame );
707 WICPixelFormatGUID convertGUID = {0};
708 hr = _DecodeMetadata( flags, decoder.Get(), frame.Get(), mdata, &convertGUID );
712 if ( (mdata.arraySize > 1) && (flags & WIC_FLAGS_ALL_FRAMES) )
714 hr = _DecodeMultiframe( flags, mdata, decoder.Get(), image );
718 hr = _DecodeSingleFrame( flags, mdata, convertGUID, frame.Get(), image );
728 memcpy( metadata, &mdata, sizeof(TexMetadata) );
734 //-------------------------------------------------------------------------------------
735 // Load a WIC-supported file from disk
736 //-------------------------------------------------------------------------------------
737 HRESULT LoadFromWICFile( LPCWSTR szFile, DWORD flags, TexMetadata* metadata, ScratchImage& image )
742 IWICImagingFactory* pWIC = _GetWIC();
744 return E_NOINTERFACE;
749 ScopedObject<IWICBitmapDecoder> decoder;
750 HRESULT hr = pWIC->CreateDecoderFromFilename( szFile, 0, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &decoder );
754 ScopedObject<IWICBitmapFrameDecode> frame;
755 hr = decoder->GetFrame( 0, &frame );
761 WICPixelFormatGUID convertGUID = {0};
762 hr = _DecodeMetadata( flags, decoder.Get(), frame.Get(), mdata, &convertGUID );
766 if ( (mdata.arraySize > 1) && (flags & WIC_FLAGS_ALL_FRAMES) )
768 hr = _DecodeMultiframe( flags, mdata, decoder.Get(), image );
772 hr = _DecodeSingleFrame( flags, mdata, convertGUID, frame.Get(), image );
782 memcpy( metadata, &mdata, sizeof(TexMetadata) );
788 //-------------------------------------------------------------------------------------
789 // Save a WIC-supported file to memory
790 //-------------------------------------------------------------------------------------
791 HRESULT SaveToWICMemory( const Image& image, DWORD flags, REFGUID guidContainerFormat, Blob& blob, const GUID* targetFormat )
798 ScopedObject<IStream> stream;
799 HRESULT hr = CreateStreamOnHGlobal( 0, TRUE, &stream );
803 hr = _EncodeSingleFrame( image, flags, guidContainerFormat, stream.Get(), targetFormat );
807 // Copy stream data into blob
809 hr = stream->Stat( &stat, STATFLAG_NONAME );
813 if ( stat.cbSize.HighPart > 0 )
814 return HRESULT_FROM_WIN32( ERROR_FILE_TOO_LARGE );
816 hr = blob.Initialize( stat.cbSize.LowPart );
820 LARGE_INTEGER li = { 0 };
821 hr = stream->Seek( li, STREAM_SEEK_SET, 0 );
826 hr = stream->Read( blob.GetBufferPointer(), static_cast<ULONG>( blob.GetBufferSize() ), &bytesRead );
830 if ( bytesRead != blob.GetBufferSize() )
836 HRESULT SaveToWICMemory( const Image* images, size_t nimages, DWORD flags, REFGUID guidContainerFormat, Blob& blob, const GUID* targetFormat )
838 if ( !images || nimages == 0 )
843 ScopedObject<IStream> stream;
844 HRESULT hr = CreateStreamOnHGlobal( 0, TRUE, &stream );
849 hr = _EncodeMultiframe( images, nimages, flags, guidContainerFormat, stream.Get(), targetFormat );
851 hr = _EncodeSingleFrame( images[0], flags, guidContainerFormat, stream.Get(), targetFormat );
856 // Copy stream data into blob
858 hr = stream->Stat( &stat, STATFLAG_NONAME );
862 if ( stat.cbSize.HighPart > 0 )
863 return HRESULT_FROM_WIN32( ERROR_FILE_TOO_LARGE );
865 hr = blob.Initialize( stat.cbSize.LowPart );
869 LARGE_INTEGER li = { 0 };
870 hr = stream->Seek( li, STREAM_SEEK_SET, 0 );
875 hr = stream->Read( blob.GetBufferPointer(), static_cast<ULONG>( blob.GetBufferSize() ), &bytesRead );
879 if ( bytesRead != blob.GetBufferSize() )
886 //-------------------------------------------------------------------------------------
887 // Save a WIC-supported file to disk
888 //-------------------------------------------------------------------------------------
889 HRESULT SaveToWICFile( const Image& image, DWORD flags, REFGUID guidContainerFormat, LPCWSTR szFile, const GUID* targetFormat )
897 IWICImagingFactory* pWIC = _GetWIC();
899 return E_NOINTERFACE;
901 ScopedObject<IWICStream> stream;
902 HRESULT hr = pWIC->CreateStream( &stream );
906 hr = stream->InitializeFromFilename( szFile, GENERIC_WRITE );
910 hr = _EncodeSingleFrame( image, flags, guidContainerFormat, stream.Get(), targetFormat );
917 HRESULT SaveToWICFile( const Image* images, size_t nimages, DWORD flags, REFGUID guidContainerFormat, LPCWSTR szFile, const GUID* targetFormat )
919 if ( !szFile || !images || nimages == 0 )
922 IWICImagingFactory* pWIC = _GetWIC();
924 return E_NOINTERFACE;
926 ScopedObject<IWICStream> stream;
927 HRESULT hr = pWIC->CreateStream( &stream );
931 hr = stream->InitializeFromFilename( szFile, GENERIC_WRITE );
936 hr = _EncodeMultiframe( images, nimages, flags, guidContainerFormat, stream.Get(), targetFormat );
938 hr = _EncodeSingleFrame( images[0], flags, guidContainerFormat, stream.Get(), targetFormat );