X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=thirdparty%2Fdirectxtex%2FDirectXTex%2FDirectXTexResize.cpp;fp=thirdparty%2Fdirectxtex%2FDirectXTex%2FDirectXTexResize.cpp;h=9f70c92980313a80fd3cc76ff5e6371abc98d749;hb=d7c738e13decf8a8a891008c51b437ccbe3434fb;hp=0000000000000000000000000000000000000000;hpb=4f9982f5ec3dccae65d5a49dfd5a81b9737d90cd;p=apitrace diff --git a/thirdparty/directxtex/DirectXTex/DirectXTexResize.cpp b/thirdparty/directxtex/DirectXTex/DirectXTexResize.cpp new file mode 100644 index 0000000..9f70c92 --- /dev/null +++ b/thirdparty/directxtex/DirectXTex/DirectXTexResize.cpp @@ -0,0 +1,358 @@ +//------------------------------------------------------------------------------------- +// DirectXTexResize.cpp +// +// DirectX Texture Library - Image resizing 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 +{ + +extern HRESULT _ResizeSeparateColorAndAlpha( _In_ IWICImagingFactory* pWIC, _In_ IWICBitmap* original, + _In_ size_t newWidth, _In_ size_t newHeight, _In_ DWORD filter, _Inout_ const Image* img ); + +//------------------------------------------------------------------------------------- +// Do image resize using WIC +//------------------------------------------------------------------------------------- +static HRESULT _PerformResizeUsingWIC( _In_ const Image& srcImage, _In_ DWORD filter, + _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 componentInfo; + HRESULT hr = pWIC->CreateComponentInfo( pfGUID, &componentInfo ); + if ( FAILED(hr) ) + return hr; + + ScopedObject pixelFormatInfo; + hr = componentInfo->QueryInterface( __uuidof(IWICPixelFormatInfo2), (void**)&pixelFormatInfo ); + if ( FAILED(hr) ) + return hr; + + BOOL supportsTransparency = FALSE; + hr = pixelFormatInfo->SupportsTransparency( &supportsTransparency ); + if ( FAILED(hr) ) + return hr; + + ScopedObject source; + 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; + + if ( (filter & TEX_FILTER_SEPARATE_ALPHA) && supportsTransparency ) + { + hr = _ResizeSeparateColorAndAlpha( pWIC, source.Get(), destImage.width, destImage.height, filter, &destImage ); + if ( FAILED(hr) ) + return hr; + } + else + { + ScopedObject scaler; + hr = pWIC->CreateBitmapScaler( &scaler ); + if ( FAILED(hr) ) + return hr; + + hr = scaler->Initialize( source.Get(), static_cast( destImage.width ), static_cast( destImage.height ), _GetWICInterp( filter ) ); + if ( FAILED(hr) ) + return hr; + + WICPixelFormatGUID pfScaler; + hr = scaler->GetPixelFormat( &pfScaler ); + if ( FAILED(hr) ) + return hr; + + if ( memcmp( &pfScaler, &pfGUID, sizeof(WICPixelFormatGUID) ) == 0 ) + { + hr = scaler->CopyPixels( 0, static_cast( destImage.rowPitch ), static_cast( destImage.slicePitch ), destImage.pixels ); + if ( FAILED(hr) ) + return hr; + } + else + { + // The WIC bitmap scaler is free to return a different pixel format than the source image, so here we + // convert it back + ScopedObject FC; + hr = pWIC->CreateFormatConverter( &FC ); + if ( FAILED(hr) ) + return hr; + + hr = FC->Initialize( scaler.Get(), pfGUID, _GetWICDither( filter ), 0, 0, WICBitmapPaletteTypeCustom ); + if ( FAILED(hr) ) + return hr; + + hr = FC->CopyPixels( 0, static_cast( destImage.rowPitch ), static_cast( destImage.slicePitch ), destImage.pixels ); + if ( FAILED(hr) ) + return hr; + } + } + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Do conversion, resize using WIC, conversion cycle +//------------------------------------------------------------------------------------- +static HRESULT _PerformResizeViaF32( _In_ const Image& srcImage, _In_ DWORD filter, _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 = _PerformResizeUsingWIC( *tsrc, filter, GUID_WICPixelFormat128bppRGBAFloat, *tdest ); + if ( FAILED(hr) ) + return hr; + + temp.Release(); + + hr = _ConvertFromR32G32B32A32( *tdest, destImage ); + if ( FAILED(hr) ) + return hr; + + return S_OK; +} + + +//===================================================================================== +// Entry-points +//===================================================================================== + +//------------------------------------------------------------------------------------- +// Resize image +//------------------------------------------------------------------------------------- +HRESULT Resize( const Image& srcImage, size_t width, size_t height, DWORD filter, ScratchImage& image ) +{ + if ( width == 0 || height == 0 ) + return E_INVALIDARG; + +#ifdef _AMD64_ + if ( (srcImage.width > 0xFFFFFFFF) || (srcImage.height > 0xFFFFFFFF) ) + return E_INVALIDARG; + + if ( (width > 0xFFFFFFFF) || (height > 0xFFFFFFFF) ) + return E_INVALIDARG; +#endif + + if ( !srcImage.pixels ) + return E_POINTER; + + if ( IsCompressed( srcImage.format ) ) + { + // We don't support resizing compressed images + return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); + } + + HRESULT hr = image.Initialize2D( srcImage.format, width, height, 1, 1 ); + if ( FAILED(hr) ) + return hr; + + const Image *rimage = image.GetImage( 0, 0, 0 ); + if ( !rimage ) + return E_POINTER; + + // WIC only supports CLAMP + + WICPixelFormatGUID pfGUID; + if ( _DXGIToWIC( srcImage.format, pfGUID ) ) + { + // Case 1: Source format is supported by Windows Imaging Component + hr = _PerformResizeUsingWIC( srcImage, filter, pfGUID, *rimage ); + } + else + { + // Case 2: Source format is not supported by WIC, so we have to convert, resize, and convert back + hr = _PerformResizeViaF32( srcImage, filter, *rimage ); + } + + if ( FAILED(hr) ) + { + image.Release(); + return hr; + } + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Resize image (complex) +//------------------------------------------------------------------------------------- +HRESULT Resize( const Image* srcImages, size_t nimages, const TexMetadata& metadata, + size_t width, size_t height, DWORD filter, ScratchImage& result ) +{ + if ( !srcImages || !nimages || width == 0 || height == 0 ) + return E_INVALIDARG; + +#ifdef _AMD64_ + if ( (width > 0xFFFFFFFF) || (height > 0xFFFFFFFF) ) + return E_INVALIDARG; +#endif + + TexMetadata mdata2 = metadata; + mdata2.width = width; + mdata2.height = height; + mdata2.mipLevels = 1; + HRESULT hr = result.Initialize( mdata2 ); + if ( FAILED(hr) ) + return hr; + + WICPixelFormatGUID pfGUID; + bool wicpf = _DXGIToWIC( metadata.format, pfGUID ); + + switch ( metadata.dimension ) + { + case TEX_DIMENSION_TEXTURE1D: + case TEX_DIMENSION_TEXTURE2D: + assert( metadata.depth == 1 ); + + for( size_t item = 0; item < metadata.arraySize; ++item ) + { + size_t srcIndex = metadata.ComputeIndex( 0, item, 0 ); + if ( srcIndex >= nimages ) + { + result.Release(); + return E_FAIL; + } + + const Image* srcimg = &srcImages[ srcIndex ]; + const Image* destimg = result.GetImage( 0, item, 0 ); + if ( !srcimg || !destimg ) + { + result.Release(); + return E_POINTER; + } + + if ( srcimg->format != metadata.format ) + { + result.Release(); + return E_FAIL; + } + +#ifdef _AMD64_ + if ( (srcimg->width > 0xFFFFFFFF) || (srcimg->height > 0xFFFFFFFF) ) + { + result.Release(); + return E_FAIL; + } +#endif + + if ( wicpf ) + { + // Case 1: Source format is supported by Windows Imaging Component + hr = _PerformResizeUsingWIC( *srcimg, filter, pfGUID, *destimg ); + } + else + { + // Case 2: Source format is not supported by WIC, so we have to convert, resize, and convert back + hr = _PerformResizeViaF32( *srcimg, filter, *destimg ); + } + + if ( FAILED(hr) ) + { + result.Release(); + return hr; + } + } + break; + + case TEX_DIMENSION_TEXTURE3D: + assert( metadata.arraySize == 1 ); + + for( size_t slice = 0; slice < metadata.depth; ++slice ) + { + size_t srcIndex = metadata.ComputeIndex( 0, 0, slice ); + if ( srcIndex >= nimages ) + { + result.Release(); + return E_FAIL; + } + + const Image* srcimg = &srcImages[ srcIndex ]; + const Image* destimg = result.GetImage( 0, 0, slice ); + if ( !srcimg || !destimg ) + { + result.Release(); + return E_POINTER; + } + + if ( srcimg->format != metadata.format ) + { + result.Release(); + return E_FAIL; + } + +#ifdef _AMD64_ + if ( (srcimg->width > 0xFFFFFFFF) || (srcimg->height > 0xFFFFFFFF) ) + { + result.Release(); + return E_FAIL; + } +#endif + + if ( wicpf ) + { + // Case 1: Source format is supported by Windows Imaging Component + hr = _PerformResizeUsingWIC( *srcimg, filter, pfGUID, *destimg ); + } + else + { + // Case 2: Source format is not supported by WIC, so we have to convert, resize, and convert back + hr = _PerformResizeViaF32( *srcimg, filter, *destimg ); + } + + if ( FAILED(hr) ) + { + result.Release(); + return hr; + } + } + break; + + default: + result.Release(); + return E_FAIL; + } + + return S_OK; +} + +}; // namespace