]> git.cworth.org Git - apitrace/blob - thirdparty/directxtex/DirectXTex/DirectXTexFlipRotate.cpp
directxtex: Fix include filename case.
[apitrace] / thirdparty / directxtex / DirectXTex / DirectXTexFlipRotate.cpp
1 //-------------------------------------------------------------------------------------
2 // DirectXTexFlipRotate.cpp
3 //  
4 // DirectX Texture Library - Image flip/rotate 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 //-------------------------------------------------------------------------------------
22 // Do flip/rotate operation using WIC
23 //-------------------------------------------------------------------------------------
24 static HRESULT _PerformFlipRotateUsingWIC( _In_ const Image& srcImage, _In_ DWORD flags,
25                                            _In_ const WICPixelFormatGUID& pfGUID, _In_ const Image& destImage )
26 {
27     if ( !srcImage.pixels || !destImage.pixels )
28         return E_POINTER;
29
30     assert( srcImage.format == destImage.format );
31
32     IWICImagingFactory* pWIC = _GetWIC();
33     if ( !pWIC )
34         return E_NOINTERFACE;
35
36     ScopedObject<IWICBitmap> source;
37     HRESULT hr = pWIC->CreateBitmapFromMemory( static_cast<UINT>( srcImage.width ), static_cast<UINT>( srcImage.height ), pfGUID,
38                                                static_cast<UINT>( srcImage.rowPitch ), static_cast<UINT>( srcImage.slicePitch ),
39                                                srcImage.pixels, &source );
40     if ( FAILED(hr) )
41         return hr;
42
43     ScopedObject<IWICBitmapFlipRotator> FR;
44     hr = pWIC->CreateBitmapFlipRotator( &FR );
45     if ( FAILED(hr) )
46         return hr;
47
48     hr = FR->Initialize( source.Get(), static_cast<WICBitmapTransformOptions>( flags ) );
49     if ( FAILED(hr) )
50         return hr;
51
52     WICPixelFormatGUID pfFR;
53     hr = FR->GetPixelFormat( &pfFR );
54     if ( FAILED(hr) )
55         return hr;
56
57     if ( memcmp( &pfFR, &pfGUID, sizeof(GUID) ) != 0 )
58     {
59         // Flip/rotate should return the same format as the source...
60         return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
61     }
62
63     UINT nwidth, nheight;
64     hr = FR->GetSize( &nwidth, &nheight );
65     if ( FAILED(hr) )
66         return hr;
67
68     if ( destImage.width != nwidth || destImage.height != nheight )
69         return E_FAIL;
70
71     hr = FR->CopyPixels( 0, static_cast<UINT>( destImage.rowPitch ), static_cast<UINT>( destImage.slicePitch ), destImage.pixels );
72     if ( FAILED(hr) )
73         return hr;
74
75     return S_OK;
76 }
77
78
79 //-------------------------------------------------------------------------------------
80 // Do conversion, flip/rotate using WIC, conversion cycle
81 //-------------------------------------------------------------------------------------
82 static HRESULT _PerformFlipRotateViaF32( _In_ const Image& srcImage, _In_ DWORD flags, _In_ const Image& destImage )
83 {
84     if ( !srcImage.pixels || !destImage.pixels )
85         return E_POINTER;
86
87     assert( srcImage.format != DXGI_FORMAT_R32G32B32A32_FLOAT );
88     assert( srcImage.format == destImage.format );
89
90     ScratchImage temp;
91     HRESULT hr = _ConvertToR32G32B32A32( srcImage, temp );
92     if ( FAILED(hr) )
93         return hr;
94
95     const Image *tsrc = temp.GetImage( 0, 0, 0 );
96     if ( !tsrc )
97         return E_POINTER;
98
99     ScratchImage rtemp;
100     hr = rtemp.Initialize2D( DXGI_FORMAT_R32G32B32A32_FLOAT, destImage.width, destImage.height, 1, 1 );
101     if ( FAILED(hr) )
102         return hr;
103
104     const Image *tdest = rtemp.GetImage( 0, 0, 0 );
105     if ( !tdest )
106         return E_POINTER;
107
108     hr = _PerformFlipRotateUsingWIC( *tsrc, flags, GUID_WICPixelFormat128bppRGBAFloat, *tdest );
109     if ( FAILED(hr) )
110         return hr;
111
112     temp.Release();
113
114     hr = _ConvertFromR32G32B32A32( *tdest, destImage );
115     if ( FAILED(hr) )
116         return hr;
117
118     return S_OK;
119 }
120
121
122 //=====================================================================================
123 // Entry-points
124 //=====================================================================================
125
126 //-------------------------------------------------------------------------------------
127 // Flip/rotate image
128 //-------------------------------------------------------------------------------------
129 HRESULT FlipRotate( const Image& srcImage, DWORD flags, ScratchImage& image )
130 {
131     if ( !srcImage.pixels )
132         return E_POINTER;
133
134     if ( !flags )
135         return E_INVALIDARG;
136
137 #ifdef _AMD64_
138     if ( (srcImage.width > 0xFFFFFFFF) || (srcImage.height > 0xFFFFFFFF) )
139         return E_INVALIDARG;
140 #endif
141
142     if ( IsCompressed( srcImage.format ) )
143     {
144         // We don't support flip/rotate operations on compressed images
145         return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
146     }
147
148     static_assert( TEX_FR_ROTATE0 == WICBitmapTransformRotate0, "TEX_FR_ROTATE0 no longer matches WIC" );
149     static_assert( TEX_FR_ROTATE90 == WICBitmapTransformRotate90, "TEX_FR_ROTATE90 no longer matches WIC" );
150     static_assert( TEX_FR_ROTATE180 == WICBitmapTransformRotate180, "TEX_FR_ROTATE180 no longer matches WIC" );
151     static_assert( TEX_FR_ROTATE270 == WICBitmapTransformRotate270, "TEX_FR_ROTATE270 no longer matches WIC" );
152     static_assert( TEX_FR_FLIP_HORIZONTAL == WICBitmapTransformFlipHorizontal, "TEX_FR_FLIP_HORIZONTAL no longer matches WIC" );
153     static_assert( TEX_FR_FLIP_VERTICAL == WICBitmapTransformFlipVertical, "TEX_FR_FLIP_VERTICAL no longer matches WIC" );
154
155     // Only supports 90, 180, 270, or no rotation flags... not a combination of rotation flags
156     switch ( flags & (TEX_FR_ROTATE90|TEX_FR_ROTATE180|TEX_FR_ROTATE270) )
157     {
158     case 0:
159     case TEX_FR_ROTATE90:
160     case TEX_FR_ROTATE180:
161     case TEX_FR_ROTATE270:
162         break;
163
164     default:
165         return E_INVALIDARG;
166     }
167
168     size_t nwidth = srcImage.width;
169     size_t nheight = srcImage.height;
170
171     if (flags & (TEX_FR_ROTATE90|TEX_FR_ROTATE270))
172     {
173         nwidth = srcImage.height;
174         nheight = srcImage.width;
175     }
176
177     HRESULT hr = image.Initialize2D( srcImage.format, nwidth, nheight, 1, 1 );
178     if ( FAILED(hr) )
179         return hr;
180    
181     const Image *rimage = image.GetImage( 0, 0, 0 );
182     if ( !rimage )
183         return E_POINTER;
184
185     WICPixelFormatGUID pfGUID;
186     if ( _DXGIToWIC( srcImage.format, pfGUID ) )
187     {
188         // Case 1: Source format is supported by Windows Imaging Component
189         hr = _PerformFlipRotateUsingWIC( srcImage, flags, pfGUID, *rimage );
190     }
191     else
192     {
193         // Case 2: Source format is not supported by WIC, so we have to convert, flip/rotate, and convert back
194         hr = _PerformFlipRotateViaF32( srcImage, flags, *rimage );
195     }
196
197     if ( FAILED(hr) )
198     {
199         image.Release();
200         return hr;
201     }
202
203     return S_OK;
204 }
205
206
207 //-------------------------------------------------------------------------------------
208 // Flip/rotate image (complex)
209 //-------------------------------------------------------------------------------------
210 HRESULT FlipRotate( const Image* srcImages, size_t nimages, const TexMetadata& metadata,
211                     DWORD flags, ScratchImage& result )
212 {
213     if ( !srcImages || !nimages )
214         return E_INVALIDARG;
215
216     if ( IsCompressed( metadata.format ) )
217     {
218         // We don't support flip/rotate operations on compressed images
219         return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
220     }
221
222     static_assert( TEX_FR_ROTATE0 == WICBitmapTransformRotate0, "TEX_FR_ROTATE0 no longer matches WIC" );
223     static_assert( TEX_FR_ROTATE90 == WICBitmapTransformRotate90, "TEX_FR_ROTATE90 no longer matches WIC" );
224     static_assert( TEX_FR_ROTATE180 == WICBitmapTransformRotate180, "TEX_FR_ROTATE180 no longer matches WIC" );
225     static_assert( TEX_FR_ROTATE270 == WICBitmapTransformRotate270, "TEX_FR_ROTATE270 no longer matches WIC" );
226     static_assert( TEX_FR_FLIP_HORIZONTAL == WICBitmapTransformFlipHorizontal, "TEX_FR_FLIP_HORIZONTAL no longer matches WIC" );
227     static_assert( TEX_FR_FLIP_VERTICAL == WICBitmapTransformFlipVertical, "TEX_FR_FLIP_VERTICAL no longer matches WIC" );
228
229     // Only supports 90, 180, 270, or no rotation flags... not a combination of rotation flags
230     switch ( flags & (TEX_FR_ROTATE90|TEX_FR_ROTATE180|TEX_FR_ROTATE270) )
231     {
232     case 0:
233     case TEX_FR_ROTATE90:
234     case TEX_FR_ROTATE180:
235     case TEX_FR_ROTATE270:
236         break;
237
238     default:
239         return E_INVALIDARG;
240     }
241
242     TexMetadata mdata2 = metadata;
243
244     bool flipwh = false;
245     if (flags & (TEX_FR_ROTATE90|TEX_FR_ROTATE270))
246     {
247         flipwh = true;
248         mdata2.width = metadata.height;
249         mdata2.height = metadata.width;
250     }
251
252     HRESULT hr = result.Initialize( mdata2 );
253     if ( FAILED(hr) )
254         return hr;
255
256     if ( nimages != result.GetImageCount() )
257     {
258         result.Release();
259         return E_FAIL;
260     }
261
262     const Image* dest = result.GetImages();
263     if ( !dest )
264     {
265         result.Release();
266         return E_POINTER;
267     }
268
269     WICPixelFormatGUID pfGUID;
270     bool wicpf = _DXGIToWIC( metadata.format, pfGUID );
271
272     for( size_t index=0; index < nimages; ++index )
273     {
274         const Image& src = srcImages[ index ];
275         if ( src.format != metadata.format )
276         {
277             result.Release();
278             return E_FAIL;
279         }
280
281 #ifdef _AMD64_
282         if ( (src.width > 0xFFFFFFFF) || (src.height > 0xFFFFFFFF) )
283             return E_FAIL;
284 #endif
285
286         const Image& dst = dest[ index ];
287         assert( dst.format == metadata.format );
288
289         if ( flipwh )
290         {
291             if ( src.width != dst.height || src.height != dst.width )
292             {
293                 result.Release();
294                 return E_FAIL;
295             }
296         }
297         else
298         {
299             if ( src.width != dst.width || src.height != dst.height )
300             {
301                 result.Release();
302                 return E_FAIL;
303             }
304         }
305
306         if (wicpf)
307         {
308             // Case 1: Source format is supported by Windows Imaging Component
309             hr = _PerformFlipRotateUsingWIC( src, flags, pfGUID, dst );
310         }
311         else
312         {
313             // Case 2: Source format is not supported by WIC, so we have to convert, flip/rotate, and convert back
314             hr = _PerformFlipRotateViaF32( src, flags, dst );
315         }
316
317         if ( FAILED(hr) )
318         {
319             result.Release();
320             return hr;
321         }
322     }
323
324     return S_OK;
325 }
326
327 }; // namespace