1 //-------------------------------------------------------------------------------------
2 // DirectXTexResize.cpp
4 // DirectX Texture Library - Image resizing operations
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"
21 extern HRESULT _ResizeSeparateColorAndAlpha( _In_ IWICImagingFactory* pWIC, _In_ IWICBitmap* original,
22 _In_ size_t newWidth, _In_ size_t newHeight, _In_ DWORD filter, _Inout_ const Image* img );
24 //-------------------------------------------------------------------------------------
25 // Do image resize using WIC
26 //-------------------------------------------------------------------------------------
27 static HRESULT _PerformResizeUsingWIC( _In_ const Image& srcImage, _In_ DWORD filter,
28 _In_ const WICPixelFormatGUID& pfGUID, _In_ const Image& destImage )
30 if ( !srcImage.pixels || !destImage.pixels )
33 assert( srcImage.format == destImage.format );
35 IWICImagingFactory* pWIC = _GetWIC();
39 ScopedObject<IWICComponentInfo> componentInfo;
40 HRESULT hr = pWIC->CreateComponentInfo( pfGUID, &componentInfo );
44 ScopedObject<IWICPixelFormatInfo2> pixelFormatInfo;
45 hr = componentInfo->QueryInterface( __uuidof(IWICPixelFormatInfo2), (void**)&pixelFormatInfo );
49 BOOL supportsTransparency = FALSE;
50 hr = pixelFormatInfo->SupportsTransparency( &supportsTransparency );
54 ScopedObject<IWICBitmap> source;
55 hr = pWIC->CreateBitmapFromMemory( static_cast<UINT>( srcImage.width ), static_cast<UINT>( srcImage.height ), pfGUID,
56 static_cast<UINT>( srcImage.rowPitch ), static_cast<UINT>( srcImage.slicePitch ),
57 srcImage.pixels, &source );
61 if ( (filter & TEX_FILTER_SEPARATE_ALPHA) && supportsTransparency )
63 hr = _ResizeSeparateColorAndAlpha( pWIC, source.Get(), destImage.width, destImage.height, filter, &destImage );
69 ScopedObject<IWICBitmapScaler> scaler;
70 hr = pWIC->CreateBitmapScaler( &scaler );
74 hr = scaler->Initialize( source.Get(), static_cast<UINT>( destImage.width ), static_cast<UINT>( destImage.height ), _GetWICInterp( filter ) );
78 WICPixelFormatGUID pfScaler;
79 hr = scaler->GetPixelFormat( &pfScaler );
83 if ( memcmp( &pfScaler, &pfGUID, sizeof(WICPixelFormatGUID) ) == 0 )
85 hr = scaler->CopyPixels( 0, static_cast<UINT>( destImage.rowPitch ), static_cast<UINT>( destImage.slicePitch ), destImage.pixels );
91 // The WIC bitmap scaler is free to return a different pixel format than the source image, so here we
93 ScopedObject<IWICFormatConverter> FC;
94 hr = pWIC->CreateFormatConverter( &FC );
98 hr = FC->Initialize( scaler.Get(), pfGUID, _GetWICDither( filter ), 0, 0, WICBitmapPaletteTypeCustom );
102 hr = FC->CopyPixels( 0, static_cast<UINT>( destImage.rowPitch ), static_cast<UINT>( destImage.slicePitch ), destImage.pixels );
112 //-------------------------------------------------------------------------------------
113 // Do conversion, resize using WIC, conversion cycle
114 //-------------------------------------------------------------------------------------
115 static HRESULT _PerformResizeViaF32( _In_ const Image& srcImage, _In_ DWORD filter, _In_ const Image& destImage )
117 if ( !srcImage.pixels || !destImage.pixels )
120 assert( srcImage.format != DXGI_FORMAT_R32G32B32A32_FLOAT );
121 assert( srcImage.format == destImage.format );
124 HRESULT hr = _ConvertToR32G32B32A32( srcImage, temp );
128 const Image *tsrc = temp.GetImage( 0, 0, 0 );
133 hr = rtemp.Initialize2D( DXGI_FORMAT_R32G32B32A32_FLOAT, destImage.width, destImage.height, 1, 1 );
137 const Image *tdest = rtemp.GetImage( 0, 0, 0 );
141 hr = _PerformResizeUsingWIC( *tsrc, filter, GUID_WICPixelFormat128bppRGBAFloat, *tdest );
147 hr = _ConvertFromR32G32B32A32( *tdest, destImage );
155 //=====================================================================================
157 //=====================================================================================
159 //-------------------------------------------------------------------------------------
161 //-------------------------------------------------------------------------------------
162 HRESULT Resize( const Image& srcImage, size_t width, size_t height, DWORD filter, ScratchImage& image )
164 if ( width == 0 || height == 0 )
168 if ( (srcImage.width > 0xFFFFFFFF) || (srcImage.height > 0xFFFFFFFF) )
171 if ( (width > 0xFFFFFFFF) || (height > 0xFFFFFFFF) )
175 if ( !srcImage.pixels )
178 if ( IsCompressed( srcImage.format ) )
180 // We don't support resizing compressed images
181 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
184 HRESULT hr = image.Initialize2D( srcImage.format, width, height, 1, 1 );
188 const Image *rimage = image.GetImage( 0, 0, 0 );
192 // WIC only supports CLAMP
194 WICPixelFormatGUID pfGUID;
195 if ( _DXGIToWIC( srcImage.format, pfGUID ) )
197 // Case 1: Source format is supported by Windows Imaging Component
198 hr = _PerformResizeUsingWIC( srcImage, filter, pfGUID, *rimage );
202 // Case 2: Source format is not supported by WIC, so we have to convert, resize, and convert back
203 hr = _PerformResizeViaF32( srcImage, filter, *rimage );
216 //-------------------------------------------------------------------------------------
217 // Resize image (complex)
218 //-------------------------------------------------------------------------------------
219 HRESULT Resize( const Image* srcImages, size_t nimages, const TexMetadata& metadata,
220 size_t width, size_t height, DWORD filter, ScratchImage& result )
222 if ( !srcImages || !nimages || width == 0 || height == 0 )
226 if ( (width > 0xFFFFFFFF) || (height > 0xFFFFFFFF) )
230 TexMetadata mdata2 = metadata;
231 mdata2.width = width;
232 mdata2.height = height;
233 mdata2.mipLevels = 1;
234 HRESULT hr = result.Initialize( mdata2 );
238 WICPixelFormatGUID pfGUID;
239 bool wicpf = _DXGIToWIC( metadata.format, pfGUID );
241 switch ( metadata.dimension )
243 case TEX_DIMENSION_TEXTURE1D:
244 case TEX_DIMENSION_TEXTURE2D:
245 assert( metadata.depth == 1 );
247 for( size_t item = 0; item < metadata.arraySize; ++item )
249 size_t srcIndex = metadata.ComputeIndex( 0, item, 0 );
250 if ( srcIndex >= nimages )
256 const Image* srcimg = &srcImages[ srcIndex ];
257 const Image* destimg = result.GetImage( 0, item, 0 );
258 if ( !srcimg || !destimg )
264 if ( srcimg->format != metadata.format )
271 if ( (srcimg->width > 0xFFFFFFFF) || (srcimg->height > 0xFFFFFFFF) )
280 // Case 1: Source format is supported by Windows Imaging Component
281 hr = _PerformResizeUsingWIC( *srcimg, filter, pfGUID, *destimg );
285 // Case 2: Source format is not supported by WIC, so we have to convert, resize, and convert back
286 hr = _PerformResizeViaF32( *srcimg, filter, *destimg );
297 case TEX_DIMENSION_TEXTURE3D:
298 assert( metadata.arraySize == 1 );
300 for( size_t slice = 0; slice < metadata.depth; ++slice )
302 size_t srcIndex = metadata.ComputeIndex( 0, 0, slice );
303 if ( srcIndex >= nimages )
309 const Image* srcimg = &srcImages[ srcIndex ];
310 const Image* destimg = result.GetImage( 0, 0, slice );
311 if ( !srcimg || !destimg )
317 if ( srcimg->format != metadata.format )
324 if ( (srcimg->width > 0xFFFFFFFF) || (srcimg->height > 0xFFFFFFFF) )
333 // Case 1: Source format is supported by Windows Imaging Component
334 hr = _PerformResizeUsingWIC( *srcimg, filter, pfGUID, *destimg );
338 // Case 2: Source format is not supported by WIC, so we have to convert, resize, and convert back
339 hr = _PerformResizeViaF32( *srcimg, filter, *destimg );