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