X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=thirdparty%2Fdirectxtex%2FDirectXTex%2FDirectXTexFlipRotate.cpp;fp=thirdparty%2Fdirectxtex%2FDirectXTex%2FDirectXTexFlipRotate.cpp;h=5ff94d59baef81149af88f4681679cf486ea7d49;hb=f6a9034a9d6d58ab27b574a0c146a36782762d55;hp=0000000000000000000000000000000000000000;hpb=a4bcf6ae9c4988600a7c4b5b8f9ee37528f342d4;p=apitrace diff --git a/thirdparty/directxtex/DirectXTex/DirectXTexFlipRotate.cpp b/thirdparty/directxtex/DirectXTex/DirectXTexFlipRotate.cpp new file mode 100644 index 0000000..5ff94d5 --- /dev/null +++ b/thirdparty/directxtex/DirectXTex/DirectXTexFlipRotate.cpp @@ -0,0 +1,327 @@ +//------------------------------------------------------------------------------------- +// 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" + +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; + + ScopedObject source; + HRESULT hr = pWIC->CreateBitmapFromMemory( static_cast( srcImage.width ), static_cast( srcImage.height ), pfGUID, + static_cast( srcImage.rowPitch ), static_cast( srcImage.slicePitch ), + srcImage.pixels, &source ); + if ( FAILED(hr) ) + return hr; + + ScopedObject FR; + hr = pWIC->CreateBitmapFlipRotator( &FR ); + if ( FAILED(hr) ) + return hr; + + hr = FR->Initialize( source.Get(), static_cast( 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( destImage.rowPitch ), static_cast( 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 +//------------------------------------------------------------------------------------- +HRESULT FlipRotate( const Image& srcImage, DWORD flags, ScratchImage& image ) +{ + if ( !srcImage.pixels ) + return E_POINTER; + + if ( !flags ) + return E_INVALIDARG; + +#ifdef _AMD64_ + 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) +//------------------------------------------------------------------------------------- +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 _AMD64_ + 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