]> git.cworth.org Git - apitrace/blobdiff - thirdparty/directxtex/DirectXTex/DirectXTexFlipRotate.cpp
thirdparty/directxtex: Import DirectXTex library.
[apitrace] / thirdparty / directxtex / DirectXTex / DirectXTexFlipRotate.cpp
diff --git a/thirdparty/directxtex/DirectXTex/DirectXTexFlipRotate.cpp b/thirdparty/directxtex/DirectXTex/DirectXTexFlipRotate.cpp
new file mode 100644 (file)
index 0000000..5ff94d5
--- /dev/null
@@ -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<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 );
+    if ( FAILED(hr) )
+        return hr;
+
+    ScopedObject<IWICBitmapFlipRotator> FR;
+    hr = pWIC->CreateBitmapFlipRotator( &FR );
+    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
+//-------------------------------------------------------------------------------------
+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