1 //-------------------------------------------------------------------------------------
2 // DirectXTexFlipRotate.cpp
4 // DirectX Texture Library - Image flip/rotate 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 //-------------------------------------------------------------------------------------
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 )
27 if ( !srcImage.pixels || !destImage.pixels )
30 assert( srcImage.format == destImage.format );
32 IWICImagingFactory* pWIC = _GetWIC();
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 );
43 ScopedObject<IWICBitmapFlipRotator> FR;
44 hr = pWIC->CreateBitmapFlipRotator( &FR );
48 hr = FR->Initialize( source.Get(), static_cast<WICBitmapTransformOptions>( flags ) );
52 WICPixelFormatGUID pfFR;
53 hr = FR->GetPixelFormat( &pfFR );
57 if ( memcmp( &pfFR, &pfGUID, sizeof(GUID) ) != 0 )
59 // Flip/rotate should return the same format as the source...
60 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
64 hr = FR->GetSize( &nwidth, &nheight );
68 if ( destImage.width != nwidth || destImage.height != nheight )
71 hr = FR->CopyPixels( 0, static_cast<UINT>( destImage.rowPitch ), static_cast<UINT>( destImage.slicePitch ), destImage.pixels );
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 )
84 if ( !srcImage.pixels || !destImage.pixels )
87 assert( srcImage.format != DXGI_FORMAT_R32G32B32A32_FLOAT );
88 assert( srcImage.format == destImage.format );
91 HRESULT hr = _ConvertToR32G32B32A32( srcImage, temp );
95 const Image *tsrc = temp.GetImage( 0, 0, 0 );
100 hr = rtemp.Initialize2D( DXGI_FORMAT_R32G32B32A32_FLOAT, destImage.width, destImage.height, 1, 1 );
104 const Image *tdest = rtemp.GetImage( 0, 0, 0 );
108 hr = _PerformFlipRotateUsingWIC( *tsrc, flags, GUID_WICPixelFormat128bppRGBAFloat, *tdest );
114 hr = _ConvertFromR32G32B32A32( *tdest, destImage );
122 //=====================================================================================
124 //=====================================================================================
126 //-------------------------------------------------------------------------------------
128 //-------------------------------------------------------------------------------------
129 HRESULT FlipRotate( const Image& srcImage, DWORD flags, ScratchImage& image )
131 if ( !srcImage.pixels )
138 if ( (srcImage.width > 0xFFFFFFFF) || (srcImage.height > 0xFFFFFFFF) )
142 if ( IsCompressed( srcImage.format ) )
144 // We don't support flip/rotate operations on compressed images
145 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
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" );
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) )
159 case TEX_FR_ROTATE90:
160 case TEX_FR_ROTATE180:
161 case TEX_FR_ROTATE270:
168 size_t nwidth = srcImage.width;
169 size_t nheight = srcImage.height;
171 if (flags & (TEX_FR_ROTATE90|TEX_FR_ROTATE270))
173 nwidth = srcImage.height;
174 nheight = srcImage.width;
177 HRESULT hr = image.Initialize2D( srcImage.format, nwidth, nheight, 1, 1 );
181 const Image *rimage = image.GetImage( 0, 0, 0 );
185 WICPixelFormatGUID pfGUID;
186 if ( _DXGIToWIC( srcImage.format, pfGUID ) )
188 // Case 1: Source format is supported by Windows Imaging Component
189 hr = _PerformFlipRotateUsingWIC( srcImage, flags, pfGUID, *rimage );
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 );
207 //-------------------------------------------------------------------------------------
208 // Flip/rotate image (complex)
209 //-------------------------------------------------------------------------------------
210 HRESULT FlipRotate( const Image* srcImages, size_t nimages, const TexMetadata& metadata,
211 DWORD flags, ScratchImage& result )
213 if ( !srcImages || !nimages )
216 if ( IsCompressed( metadata.format ) )
218 // We don't support flip/rotate operations on compressed images
219 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
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" );
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) )
233 case TEX_FR_ROTATE90:
234 case TEX_FR_ROTATE180:
235 case TEX_FR_ROTATE270:
242 TexMetadata mdata2 = metadata;
245 if (flags & (TEX_FR_ROTATE90|TEX_FR_ROTATE270))
248 mdata2.width = metadata.height;
249 mdata2.height = metadata.width;
252 HRESULT hr = result.Initialize( mdata2 );
256 if ( nimages != result.GetImageCount() )
262 const Image* dest = result.GetImages();
269 WICPixelFormatGUID pfGUID;
270 bool wicpf = _DXGIToWIC( metadata.format, pfGUID );
272 for( size_t index=0; index < nimages; ++index )
274 const Image& src = srcImages[ index ];
275 if ( src.format != metadata.format )
282 if ( (src.width > 0xFFFFFFFF) || (src.height > 0xFFFFFFFF) )
286 const Image& dst = dest[ index ];
287 assert( dst.format == metadata.format );
291 if ( src.width != dst.height || src.height != dst.width )
299 if ( src.width != dst.width || src.height != dst.height )
308 // Case 1: Source format is supported by Windows Imaging Component
309 hr = _PerformFlipRotateUsingWIC( src, flags, pfGUID, dst );
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 );