]> git.cworth.org Git - apitrace/blob - thirdparty/directxtex/DirectXTex/DirectXTexResize.cpp
thirdparty/directxtex: Import DirectXTex library.
[apitrace] / thirdparty / directxtex / DirectXTex / DirectXTexResize.cpp
1 //-------------------------------------------------------------------------------------
2 // DirectXTexResize.cpp
3 //  
4 // DirectX Texture Library - Image resizing operations
5 //
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
9 // PARTICULAR PURPOSE.
10 //
11 // Copyright (c) Microsoft Corporation. All rights reserved.
12 //
13 // http://go.microsoft.com/fwlink/?LinkId=248926
14 //-------------------------------------------------------------------------------------
15
16 #include "directxtexp.h"
17
18 namespace DirectX
19 {
20
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 );
23
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 )
29 {
30     if ( !srcImage.pixels || !destImage.pixels )
31         return E_POINTER;
32
33     assert( srcImage.format == destImage.format );
34
35     IWICImagingFactory* pWIC = _GetWIC();
36     if ( !pWIC )
37         return E_NOINTERFACE;
38
39     ScopedObject<IWICComponentInfo> componentInfo;
40     HRESULT hr = pWIC->CreateComponentInfo( pfGUID, &componentInfo );
41     if ( FAILED(hr) )
42         return hr;
43
44     ScopedObject<IWICPixelFormatInfo2> pixelFormatInfo;
45     hr = componentInfo->QueryInterface( __uuidof(IWICPixelFormatInfo2), (void**)&pixelFormatInfo );
46     if ( FAILED(hr) )
47         return hr;
48
49     BOOL supportsTransparency = FALSE;
50     hr = pixelFormatInfo->SupportsTransparency( &supportsTransparency );
51     if ( FAILED(hr) )
52         return hr;
53
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 );
58     if ( FAILED(hr) )
59         return hr;
60
61     if ( (filter & TEX_FILTER_SEPARATE_ALPHA) && supportsTransparency )
62     {
63         hr = _ResizeSeparateColorAndAlpha( pWIC, source.Get(), destImage.width, destImage.height, filter, &destImage );
64         if ( FAILED(hr) )
65             return hr;
66     }
67     else
68     {
69         ScopedObject<IWICBitmapScaler> scaler;
70         hr = pWIC->CreateBitmapScaler( &scaler );
71         if ( FAILED(hr) )
72             return hr;
73
74         hr = scaler->Initialize( source.Get(), static_cast<UINT>( destImage.width ), static_cast<UINT>( destImage.height ), _GetWICInterp( filter ) );
75         if ( FAILED(hr) )
76             return hr;
77
78         WICPixelFormatGUID pfScaler;
79         hr = scaler->GetPixelFormat( &pfScaler );
80         if ( FAILED(hr) )
81             return hr;
82
83         if ( memcmp( &pfScaler, &pfGUID, sizeof(WICPixelFormatGUID) ) == 0 )
84         {
85             hr = scaler->CopyPixels( 0, static_cast<UINT>( destImage.rowPitch ), static_cast<UINT>( destImage.slicePitch ), destImage.pixels );
86             if ( FAILED(hr) )
87                 return hr;
88         }
89         else
90         {
91             // The WIC bitmap scaler is free to return a different pixel format than the source image, so here we
92             // convert it back
93             ScopedObject<IWICFormatConverter> FC;
94             hr = pWIC->CreateFormatConverter( &FC );
95             if ( FAILED(hr) )
96                 return hr;
97
98             hr = FC->Initialize( scaler.Get(), pfGUID, _GetWICDither( filter ), 0, 0, WICBitmapPaletteTypeCustom );
99             if ( FAILED(hr) )
100                 return hr;
101
102             hr = FC->CopyPixels( 0, static_cast<UINT>( destImage.rowPitch ), static_cast<UINT>( destImage.slicePitch ), destImage.pixels );  
103             if ( FAILED(hr) )
104                 return hr;
105         }
106     }
107
108     return S_OK;
109 }
110
111
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 )
116 {
117     if ( !srcImage.pixels || !destImage.pixels )
118         return E_POINTER;
119
120     assert( srcImage.format != DXGI_FORMAT_R32G32B32A32_FLOAT );
121     assert( srcImage.format == destImage.format );
122
123     ScratchImage temp;
124     HRESULT hr = _ConvertToR32G32B32A32( srcImage, temp );
125     if ( FAILED(hr) )
126         return hr;
127
128     const Image *tsrc = temp.GetImage( 0, 0, 0 );
129     if ( !tsrc )
130         return E_POINTER;
131
132     ScratchImage rtemp;
133     hr = rtemp.Initialize2D( DXGI_FORMAT_R32G32B32A32_FLOAT, destImage.width, destImage.height, 1, 1 );
134     if ( FAILED(hr) )
135         return hr;
136
137     const Image *tdest = rtemp.GetImage( 0, 0, 0 );
138     if ( !tdest )
139         return E_POINTER;
140
141     hr = _PerformResizeUsingWIC( *tsrc, filter, GUID_WICPixelFormat128bppRGBAFloat, *tdest );
142     if ( FAILED(hr) )
143         return hr;
144
145     temp.Release();
146
147     hr = _ConvertFromR32G32B32A32( *tdest, destImage );
148     if ( FAILED(hr) )
149         return hr;
150
151     return S_OK;
152 }
153
154
155 //=====================================================================================
156 // Entry-points
157 //=====================================================================================
158
159 //-------------------------------------------------------------------------------------
160 // Resize image
161 //-------------------------------------------------------------------------------------
162 HRESULT Resize( const Image& srcImage, size_t width, size_t height, DWORD filter, ScratchImage& image )
163 {
164     if ( width == 0 || height == 0 )
165         return E_INVALIDARG;
166
167 #ifdef _AMD64_
168     if ( (srcImage.width > 0xFFFFFFFF) || (srcImage.height > 0xFFFFFFFF) )
169         return E_INVALIDARG;
170
171     if ( (width > 0xFFFFFFFF) || (height > 0xFFFFFFFF) )
172         return E_INVALIDARG;
173 #endif
174
175     if ( !srcImage.pixels )
176         return E_POINTER;
177
178     if ( IsCompressed( srcImage.format ) )
179     {
180         // We don't support resizing compressed images
181         return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
182     }
183
184     HRESULT hr = image.Initialize2D( srcImage.format, width, height, 1, 1 );
185     if ( FAILED(hr) )
186         return hr;
187    
188     const Image *rimage = image.GetImage( 0, 0, 0 );
189     if ( !rimage )
190         return E_POINTER;
191
192     // WIC only supports CLAMP
193
194     WICPixelFormatGUID pfGUID;
195     if ( _DXGIToWIC( srcImage.format, pfGUID ) )
196     {
197         // Case 1: Source format is supported by Windows Imaging Component
198         hr = _PerformResizeUsingWIC( srcImage, filter, pfGUID, *rimage );
199     }
200     else
201     {
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 );
204     }
205
206     if ( FAILED(hr) )
207     {
208         image.Release();
209         return hr;
210     }
211
212     return S_OK;
213 }
214
215
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 )
221 {
222     if ( !srcImages || !nimages || width == 0 || height == 0 )
223         return E_INVALIDARG;
224
225 #ifdef _AMD64_
226     if ( (width > 0xFFFFFFFF) || (height > 0xFFFFFFFF) )
227         return E_INVALIDARG;
228 #endif
229
230     TexMetadata mdata2 = metadata;
231     mdata2.width = width;
232     mdata2.height = height;
233     mdata2.mipLevels = 1;
234     HRESULT hr = result.Initialize( mdata2 );
235     if ( FAILED(hr) )
236         return hr;
237
238     WICPixelFormatGUID pfGUID;
239     bool wicpf = _DXGIToWIC( metadata.format, pfGUID );
240
241     switch ( metadata.dimension )
242     {
243     case TEX_DIMENSION_TEXTURE1D:
244     case TEX_DIMENSION_TEXTURE2D:
245         assert( metadata.depth == 1 );
246
247         for( size_t item = 0; item < metadata.arraySize; ++item )
248         {
249             size_t srcIndex = metadata.ComputeIndex( 0, item, 0 );
250             if ( srcIndex >= nimages )
251             {
252                 result.Release();
253                 return E_FAIL;
254             }
255
256             const Image* srcimg = &srcImages[ srcIndex ];
257             const Image* destimg = result.GetImage( 0, item, 0 );
258             if ( !srcimg || !destimg )
259             {
260                 result.Release();
261                 return E_POINTER;
262             }
263
264             if ( srcimg->format != metadata.format )
265             {
266                 result.Release();
267                 return E_FAIL;
268             }
269
270 #ifdef _AMD64_
271             if ( (srcimg->width > 0xFFFFFFFF) || (srcimg->height > 0xFFFFFFFF) )
272             {
273                 result.Release();
274                 return E_FAIL;
275             }
276 #endif
277
278             if ( wicpf )
279             {
280                 // Case 1: Source format is supported by Windows Imaging Component
281                 hr = _PerformResizeUsingWIC( *srcimg, filter, pfGUID, *destimg );
282             }
283             else
284             {
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 );
287             }
288
289             if ( FAILED(hr) )
290             {
291                 result.Release();
292                 return hr;
293             }
294         }
295         break;
296
297     case TEX_DIMENSION_TEXTURE3D:
298         assert( metadata.arraySize == 1 );
299
300         for( size_t slice = 0; slice < metadata.depth; ++slice )
301         {
302             size_t srcIndex = metadata.ComputeIndex( 0, 0, slice );
303             if ( srcIndex >= nimages )
304             {
305                 result.Release();
306                 return E_FAIL;
307             }
308
309             const Image* srcimg = &srcImages[ srcIndex ];
310             const Image* destimg = result.GetImage( 0, 0, slice );
311             if ( !srcimg || !destimg )
312             {
313                 result.Release();
314                 return E_POINTER;
315             }
316
317             if ( srcimg->format != metadata.format )
318             {
319                 result.Release();
320                 return E_FAIL;
321             }
322
323 #ifdef _AMD64_
324             if ( (srcimg->width > 0xFFFFFFFF) || (srcimg->height > 0xFFFFFFFF) )
325             {
326                 result.Release();
327                 return E_FAIL;
328             }
329 #endif
330
331             if ( wicpf )
332             {
333                 // Case 1: Source format is supported by Windows Imaging Component
334                 hr = _PerformResizeUsingWIC( *srcimg, filter, pfGUID, *destimg );
335             }
336             else
337             {
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 );
340             }
341
342             if ( FAILED(hr) )
343             {
344                 result.Release();
345                 return hr;
346             }
347         }
348         break;
349
350     default:
351         result.Release();
352         return E_FAIL;
353     }
354
355     return S_OK;
356 }
357
358 }; // namespace