DirectXTexFlipRotate.cpp 10 KB

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