123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331 |
- //-------------------------------------------------------------------------------------
- // DirectXTexFlipRotate.cpp
- //
- // DirectX Texture Library - Image flip/rotate operations
- //
- // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
- // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
- // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
- // PARTICULAR PURPOSE.
- //
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //
- // http://go.microsoft.com/fwlink/?LinkId=248926
- //-------------------------------------------------------------------------------------
- #include "directxtexp.h"
- using Microsoft::WRL::ComPtr;
- namespace DirectX
- {
- //-------------------------------------------------------------------------------------
- // Do flip/rotate operation using WIC
- //-------------------------------------------------------------------------------------
- static HRESULT _PerformFlipRotateUsingWIC( _In_ const Image& srcImage, _In_ DWORD flags,
- _In_ const WICPixelFormatGUID& pfGUID, _In_ const Image& destImage )
- {
- if ( !srcImage.pixels || !destImage.pixels )
- return E_POINTER;
- assert( srcImage.format == destImage.format );
- IWICImagingFactory* pWIC = _GetWIC();
- if ( !pWIC )
- return E_NOINTERFACE;
- ComPtr<IWICBitmap> source;
- HRESULT hr = pWIC->CreateBitmapFromMemory( static_cast<UINT>( srcImage.width ), static_cast<UINT>( srcImage.height ), pfGUID,
- static_cast<UINT>( srcImage.rowPitch ), static_cast<UINT>( srcImage.slicePitch ),
- srcImage.pixels, source.GetAddressOf() );
- if ( FAILED(hr) )
- return hr;
- ComPtr<IWICBitmapFlipRotator> FR;
- hr = pWIC->CreateBitmapFlipRotator( FR.GetAddressOf() );
- if ( FAILED(hr) )
- return hr;
- hr = FR->Initialize( source.Get(), static_cast<WICBitmapTransformOptions>( flags ) );
- if ( FAILED(hr) )
- return hr;
- WICPixelFormatGUID pfFR;
- hr = FR->GetPixelFormat( &pfFR );
- if ( FAILED(hr) )
- return hr;
- if ( memcmp( &pfFR, &pfGUID, sizeof(GUID) ) != 0 )
- {
- // Flip/rotate should return the same format as the source...
- return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
- }
- UINT nwidth, nheight;
- hr = FR->GetSize( &nwidth, &nheight );
- if ( FAILED(hr) )
- return hr;
- if ( destImage.width != nwidth || destImage.height != nheight )
- return E_FAIL;
- hr = FR->CopyPixels( 0, static_cast<UINT>( destImage.rowPitch ), static_cast<UINT>( destImage.slicePitch ), destImage.pixels );
- if ( FAILED(hr) )
- return hr;
- return S_OK;
- }
- //-------------------------------------------------------------------------------------
- // Do conversion, flip/rotate using WIC, conversion cycle
- //-------------------------------------------------------------------------------------
- static HRESULT _PerformFlipRotateViaF32( _In_ const Image& srcImage, _In_ DWORD flags, _In_ const Image& destImage )
- {
- if ( !srcImage.pixels || !destImage.pixels )
- return E_POINTER;
- assert( srcImage.format != DXGI_FORMAT_R32G32B32A32_FLOAT );
- assert( srcImage.format == destImage.format );
- ScratchImage temp;
- HRESULT hr = _ConvertToR32G32B32A32( srcImage, temp );
- if ( FAILED(hr) )
- return hr;
- const Image *tsrc = temp.GetImage( 0, 0, 0 );
- if ( !tsrc )
- return E_POINTER;
- ScratchImage rtemp;
- hr = rtemp.Initialize2D( DXGI_FORMAT_R32G32B32A32_FLOAT, destImage.width, destImage.height, 1, 1 );
- if ( FAILED(hr) )
- return hr;
- const Image *tdest = rtemp.GetImage( 0, 0, 0 );
- if ( !tdest )
- return E_POINTER;
- hr = _PerformFlipRotateUsingWIC( *tsrc, flags, GUID_WICPixelFormat128bppRGBAFloat, *tdest );
- if ( FAILED(hr) )
- return hr;
- temp.Release();
- hr = _ConvertFromR32G32B32A32( *tdest, destImage );
- if ( FAILED(hr) )
- return hr;
- return S_OK;
- }
- //=====================================================================================
- // Entry-points
- //=====================================================================================
- //-------------------------------------------------------------------------------------
- // Flip/rotate image
- //-------------------------------------------------------------------------------------
- _Use_decl_annotations_
- HRESULT FlipRotate( const Image& srcImage, DWORD flags, ScratchImage& image )
- {
- if ( !srcImage.pixels )
- return E_POINTER;
- if ( !flags )
- return E_INVALIDARG;
- #ifdef _M_X64
- if ( (srcImage.width > 0xFFFFFFFF) || (srcImage.height > 0xFFFFFFFF) )
- return E_INVALIDARG;
- #endif
- if ( IsCompressed( srcImage.format ) )
- {
- // We don't support flip/rotate operations on compressed images
- return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
- }
- static_assert( TEX_FR_ROTATE0 == WICBitmapTransformRotate0, "TEX_FR_ROTATE0 no longer matches WIC" );
- static_assert( TEX_FR_ROTATE90 == WICBitmapTransformRotate90, "TEX_FR_ROTATE90 no longer matches WIC" );
- static_assert( TEX_FR_ROTATE180 == WICBitmapTransformRotate180, "TEX_FR_ROTATE180 no longer matches WIC" );
- static_assert( TEX_FR_ROTATE270 == WICBitmapTransformRotate270, "TEX_FR_ROTATE270 no longer matches WIC" );
- static_assert( TEX_FR_FLIP_HORIZONTAL == WICBitmapTransformFlipHorizontal, "TEX_FR_FLIP_HORIZONTAL no longer matches WIC" );
- static_assert( TEX_FR_FLIP_VERTICAL == WICBitmapTransformFlipVertical, "TEX_FR_FLIP_VERTICAL no longer matches WIC" );
- // Only supports 90, 180, 270, or no rotation flags... not a combination of rotation flags
- switch ( flags & (TEX_FR_ROTATE90|TEX_FR_ROTATE180|TEX_FR_ROTATE270) )
- {
- case 0:
- case TEX_FR_ROTATE90:
- case TEX_FR_ROTATE180:
- case TEX_FR_ROTATE270:
- break;
- default:
- return E_INVALIDARG;
- }
- size_t nwidth = srcImage.width;
- size_t nheight = srcImage.height;
- if (flags & (TEX_FR_ROTATE90|TEX_FR_ROTATE270))
- {
- nwidth = srcImage.height;
- nheight = srcImage.width;
- }
- HRESULT hr = image.Initialize2D( srcImage.format, nwidth, nheight, 1, 1 );
- if ( FAILED(hr) )
- return hr;
-
- const Image *rimage = image.GetImage( 0, 0, 0 );
- if ( !rimage )
- return E_POINTER;
- WICPixelFormatGUID pfGUID;
- if ( _DXGIToWIC( srcImage.format, pfGUID ) )
- {
- // Case 1: Source format is supported by Windows Imaging Component
- hr = _PerformFlipRotateUsingWIC( srcImage, flags, pfGUID, *rimage );
- }
- else
- {
- // Case 2: Source format is not supported by WIC, so we have to convert, flip/rotate, and convert back
- hr = _PerformFlipRotateViaF32( srcImage, flags, *rimage );
- }
- if ( FAILED(hr) )
- {
- image.Release();
- return hr;
- }
- return S_OK;
- }
- //-------------------------------------------------------------------------------------
- // Flip/rotate image (complex)
- //-------------------------------------------------------------------------------------
- _Use_decl_annotations_
- HRESULT FlipRotate( const Image* srcImages, size_t nimages, const TexMetadata& metadata,
- DWORD flags, ScratchImage& result )
- {
- if ( !srcImages || !nimages )
- return E_INVALIDARG;
- if ( IsCompressed( metadata.format ) )
- {
- // We don't support flip/rotate operations on compressed images
- return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
- }
- static_assert( TEX_FR_ROTATE0 == WICBitmapTransformRotate0, "TEX_FR_ROTATE0 no longer matches WIC" );
- static_assert( TEX_FR_ROTATE90 == WICBitmapTransformRotate90, "TEX_FR_ROTATE90 no longer matches WIC" );
- static_assert( TEX_FR_ROTATE180 == WICBitmapTransformRotate180, "TEX_FR_ROTATE180 no longer matches WIC" );
- static_assert( TEX_FR_ROTATE270 == WICBitmapTransformRotate270, "TEX_FR_ROTATE270 no longer matches WIC" );
- static_assert( TEX_FR_FLIP_HORIZONTAL == WICBitmapTransformFlipHorizontal, "TEX_FR_FLIP_HORIZONTAL no longer matches WIC" );
- static_assert( TEX_FR_FLIP_VERTICAL == WICBitmapTransformFlipVertical, "TEX_FR_FLIP_VERTICAL no longer matches WIC" );
- // Only supports 90, 180, 270, or no rotation flags... not a combination of rotation flags
- switch ( flags & (TEX_FR_ROTATE90|TEX_FR_ROTATE180|TEX_FR_ROTATE270) )
- {
- case 0:
- case TEX_FR_ROTATE90:
- case TEX_FR_ROTATE180:
- case TEX_FR_ROTATE270:
- break;
- default:
- return E_INVALIDARG;
- }
- TexMetadata mdata2 = metadata;
- bool flipwh = false;
- if (flags & (TEX_FR_ROTATE90|TEX_FR_ROTATE270))
- {
- flipwh = true;
- mdata2.width = metadata.height;
- mdata2.height = metadata.width;
- }
- HRESULT hr = result.Initialize( mdata2 );
- if ( FAILED(hr) )
- return hr;
- if ( nimages != result.GetImageCount() )
- {
- result.Release();
- return E_FAIL;
- }
- const Image* dest = result.GetImages();
- if ( !dest )
- {
- result.Release();
- return E_POINTER;
- }
- WICPixelFormatGUID pfGUID;
- bool wicpf = _DXGIToWIC( metadata.format, pfGUID );
- for( size_t index=0; index < nimages; ++index )
- {
- const Image& src = srcImages[ index ];
- if ( src.format != metadata.format )
- {
- result.Release();
- return E_FAIL;
- }
- #ifdef _M_X64
- if ( (src.width > 0xFFFFFFFF) || (src.height > 0xFFFFFFFF) )
- return E_FAIL;
- #endif
- const Image& dst = dest[ index ];
- assert( dst.format == metadata.format );
- if ( flipwh )
- {
- if ( src.width != dst.height || src.height != dst.width )
- {
- result.Release();
- return E_FAIL;
- }
- }
- else
- {
- if ( src.width != dst.width || src.height != dst.height )
- {
- result.Release();
- return E_FAIL;
- }
- }
- if (wicpf)
- {
- // Case 1: Source format is supported by Windows Imaging Component
- hr = _PerformFlipRotateUsingWIC( src, flags, pfGUID, dst );
- }
- else
- {
- // Case 2: Source format is not supported by WIC, so we have to convert, flip/rotate, and convert back
- hr = _PerformFlipRotateViaF32( src, flags, dst );
- }
- if ( FAILED(hr) )
- {
- result.Release();
- return hr;
- }
- }
- return S_OK;
- }
- }; // namespace
|