diff --git a/DirectXTex/DirectXTex.h b/DirectXTex/DirectXTex.h index 150e49e..4926303 100644 --- a/DirectXTex/DirectXTex.h +++ b/DirectXTex/DirectXTex.h @@ -457,8 +457,22 @@ namespace DirectX // levels of '0' indicates a full mipchain, otherwise is generates that number of total levels (including the source base image) // Defaults to Fant filtering which is equivalent to a box filter - HRESULT PremultiplyAlpha( _In_ const Image& srcImage, _Out_ ScratchImage& image ); - HRESULT PremultiplyAlpha( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, _Out_ ScratchImage& result ); + enum TEX_PMALPHA_FLAGS + { + TEX_PMALPHA_DEFAULT = 0, + + TEX_PMALPHA_IGNORE_SRGB = 0x1, + // ignores sRGB colorspace conversions + + TEX_PMALPHA_SRGB_IN = 0x1000000, + TEX_PMALPHA_SRGB_OUT = 0x2000000, + TEX_PMALPHA_SRGB = ( TEX_PMALPHA_SRGB_IN | TEX_PMALPHA_SRGB_OUT ), + // if the input format type is IsSRGB(), then SRGB_IN is on by default + // if the output format type is IsSRGB(), then SRGB_OUT is on by default + }; + + HRESULT PremultiplyAlpha( _In_ const Image& srcImage, _In_ DWORD flags, _Out_ ScratchImage& image ); + HRESULT PremultiplyAlpha( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, _In_ DWORD flags, _Out_ ScratchImage& result ); // Converts to a premultiplied alpha version of the texture enum TEX_COMPRESS_FLAGS diff --git a/DirectXTex/DirectXTexPMAlpha.cpp b/DirectXTex/DirectXTexPMAlpha.cpp index c1f0650..ce06688 100644 --- a/DirectXTex/DirectXTexPMAlpha.cpp +++ b/DirectXTex/DirectXTexPMAlpha.cpp @@ -56,6 +56,49 @@ static HRESULT _PremultiplyAlpha( _In_ const Image& srcImage, _In_ const Image& return S_OK; } +static HRESULT _PremultiplyAlphaLinear( _In_ const Image& srcImage, _In_ DWORD flags, _In_ const Image& destImage ) +{ + assert( srcImage.width == destImage.width ); + assert( srcImage.height == destImage.height ); + + static_assert( TEX_PMALPHA_SRGB_IN == TEX_FILTER_SRGB_IN, "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*" ); + static_assert( TEX_PMALPHA_SRGB_OUT == TEX_FILTER_SRGB_OUT, "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*" ); + static_assert( TEX_PMALPHA_SRGB == TEX_FILTER_SRGB, "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*" ); + flags &= TEX_PMALPHA_SRGB; + + ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast( _aligned_malloc( (sizeof(XMVECTOR)*srcImage.width), 16 ) ) ); + if ( !scanline ) + return E_OUTOFMEMORY; + + const uint8_t *pSrc = srcImage.pixels; + uint8_t *pDest = destImage.pixels; + if ( !pSrc || !pDest ) + return E_POINTER; + + for( size_t h = 0; h < srcImage.height; ++h ) + { + if ( !_LoadScanlineLinear( scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format, flags ) ) + return E_FAIL; + + XMVECTOR* ptr = scanline.get(); + for( size_t w = 0; w < srcImage.width; ++w ) + { + XMVECTOR v = *ptr; + XMVECTOR alpha = XMVectorSplatW( *ptr ); + alpha = XMVectorMultiply( v, alpha ); + *(ptr++) = XMVectorSelect( v, alpha, g_XMSelect1110 ); + } + + if ( !_StoreScanlineLinear( pDest, destImage.rowPitch, destImage.format, scanline.get(), srcImage.width, flags ) ) + return E_FAIL; + + pSrc += srcImage.rowPitch; + pDest += destImage.rowPitch; + } + + return S_OK; +} + //===================================================================================== // Entry-points @@ -65,7 +108,7 @@ static HRESULT _PremultiplyAlpha( _In_ const Image& srcImage, _In_ const Image& // Converts to a premultiplied alpha version of the texture //------------------------------------------------------------------------------------- _Use_decl_annotations_ -HRESULT PremultiplyAlpha( const Image& srcImage, ScratchImage& image ) +HRESULT PremultiplyAlpha( const Image& srcImage, DWORD flags, ScratchImage& image ) { if ( !srcImage.pixels ) return E_POINTER; @@ -92,7 +135,7 @@ HRESULT PremultiplyAlpha( const Image& srcImage, ScratchImage& image ) return E_POINTER; } - hr = _PremultiplyAlpha( srcImage, *rimage ); + hr = ( flags & TEX_PMALPHA_IGNORE_SRGB ) ? _PremultiplyAlpha( srcImage, *rimage ) : _PremultiplyAlphaLinear( srcImage, flags, *rimage ); if ( FAILED(hr) ) { image.Release(); @@ -107,7 +150,7 @@ HRESULT PremultiplyAlpha( const Image& srcImage, ScratchImage& image ) // Converts to a premultiplied alpha version of the texture (complex) //------------------------------------------------------------------------------------- _Use_decl_annotations_ -HRESULT PremultiplyAlpha( const Image* srcImages, size_t nimages, const TexMetadata& metadata, ScratchImage& result ) +HRESULT PremultiplyAlpha( const Image* srcImages, size_t nimages, const TexMetadata& metadata, DWORD flags, ScratchImage& result ) { if ( !srcImages || !nimages ) return E_INVALIDARG; @@ -170,7 +213,7 @@ HRESULT PremultiplyAlpha( const Image* srcImages, size_t nimages, const TexMetad return E_FAIL; } - hr = _PremultiplyAlpha( src, dst ); + hr = ( flags & TEX_PMALPHA_IGNORE_SRGB ) ? _PremultiplyAlpha( src, dst ) : _PremultiplyAlphaLinear( src, flags, dst ); if ( FAILED(hr) ) { result.Release(); diff --git a/Texconv/texconv.cpp b/Texconv/texconv.cpp index cd8ea78..f94ff81 100644 --- a/Texconv/texconv.cpp +++ b/Texconv/texconv.cpp @@ -1123,7 +1123,7 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[]) goto LError; } - hr = PremultiplyAlpha( img, nimg, info, *timage ); + hr = PremultiplyAlpha( img, nimg, info, dwSRGB, *timage ); if ( FAILED(hr) ) { wprintf( L" FAILED [premultiply alpha] (%x)\n", hr);