//------------------------------------------------------------------------------------- // Compression //------------------------------------------------------------------------------------- _Use_decl_annotations_ HRESULT Compress( const Image& srcImage, DXGI_FORMAT format, DWORD compress, float alphaRef, ScratchImage& image ) { if ( IsCompressed(srcImage.format) || !IsCompressed(format) || IsTypeless(format) ) return E_INVALIDARG; // Image size must be a multiple of 4 (degenerate cases for mipmaps are allowed) bool degenerate = false; size_t width = srcImage.width; if ( (width % 4) != 0 ) { if ( width != 1 && width != 2 ) return E_INVALIDARG; degenerate = true; } size_t height = srcImage.height; if ( (height % 4) != 0 ) { if ( height != 1 && height != 2 ) return E_INVALIDARG; degenerate = true; } // Create compressed image HRESULT hr = image.Initialize2D( format, width, height, 1, 1 ); if ( FAILED(hr) ) return hr; const Image *img = image.GetImage( 0, 0, 0 ); if ( !img ) { image.Release(); return E_POINTER; } // Compress single image if ( (compress & TEX_COMPRESS_PARALLEL) && !degenerate ) { #ifndef _OPENMP return E_NOTIMPL; #else hr = _CompressBC_Parallel( srcImage, *img, _GetBCFlags( compress ), alphaRef ); #endif // _OPENMP } else { hr = _CompressBC( srcImage, *img, _GetBCFlags( compress ), alphaRef, degenerate ); } if ( FAILED(hr) ) image.Release(); return hr; }
//------------------------------------------------------------------------------------- // Compression //------------------------------------------------------------------------------------- _Use_decl_annotations_ HRESULT Compress( const Image& srcImage, DXGI_FORMAT format, DWORD compress, float alphaRef, ScratchImage& image ) { if ( IsCompressed(srcImage.format) || !IsCompressed(format) ) return E_INVALIDARG; if ( IsTypeless(format) || IsTypeless(srcImage.format) || IsPlanar(srcImage.format) || IsPalettized(srcImage.format) ) return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); // Create compressed image HRESULT hr = image.Initialize2D( format, srcImage.width, srcImage.height, 1, 1 ); if ( FAILED(hr) ) return hr; const Image *img = image.GetImage( 0, 0, 0 ); if ( !img ) { image.Release(); return E_POINTER; } // Compress single image if (compress & TEX_COMPRESS_PARALLEL) { #ifndef _OPENMP return E_NOTIMPL; #else hr = _CompressBC_Parallel( srcImage, *img, _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef ); #endif // _OPENMP } else { hr = _CompressBC( srcImage, *img, _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef ); } if ( FAILED(hr) ) image.Release(); return hr; }
//------------------------------------------------------------------------------------- // Decompression //------------------------------------------------------------------------------------- _Use_decl_annotations_ HRESULT Decompress( const Image& cImage, DXGI_FORMAT format, ScratchImage& image ) { if ( !IsCompressed(cImage.format) || IsCompressed(format) ) return E_INVALIDARG; if ( format == DXGI_FORMAT_UNKNOWN ) { // Pick a default decompressed format based on BC input format format = _DefaultDecompress( cImage.format ); if ( format == DXGI_FORMAT_UNKNOWN ) { // Input is not a compressed format return E_INVALIDARG; } } else { if ( !IsValid(format) ) return E_INVALIDARG; if ( IsTypeless(format) || IsPlanar(format) || IsPalettized(format) ) return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); } // Create decompressed image HRESULT hr = image.Initialize2D( format, cImage.width, cImage.height, 1, 1 ); if ( FAILED(hr) ) return hr; const Image *img = image.GetImage( 0, 0, 0 ); if ( !img ) { image.Release(); return E_POINTER; } // Decompress single image hr = _DecompressBC( cImage, *img ); if ( FAILED(hr) ) image.Release(); return hr; }
//------------------------------------------------------------------------------------- // Converts to a premultiplied alpha version of the texture //------------------------------------------------------------------------------------- _Use_decl_annotations_ HRESULT PremultiplyAlpha( const Image& srcImage, ScratchImage& image ) { if ( !srcImage.pixels ) return E_POINTER; if ( IsCompressed(srcImage.format) || IsVideo(srcImage.format) || IsTypeless(srcImage.format) || !HasAlpha(srcImage.format) ) return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); #ifdef _M_X64 if ( (srcImage.width > 0xFFFFFFFF) || (srcImage.height > 0xFFFFFFFF) ) return E_INVALIDARG; #endif HRESULT hr = image.Initialize2D( srcImage.format, srcImage.width, srcImage.height, 1, 1 ); if ( FAILED(hr) ) return hr; const Image *rimage = image.GetImage( 0, 0, 0 ); if ( !rimage ) { image.Release(); return E_POINTER; } hr = _PremultiplyAlpha( srcImage, *rimage ); if ( FAILED(hr) ) { image.Release(); return hr; } return S_OK; }
HRESULT Decompress( const Image* cImages, size_t nimages, const TexMetadata& metadata, DXGI_FORMAT format, ScratchImage& images ) { if ( !cImages || !nimages ) return E_INVALIDARG; if ( IsCompressed(format) || IsTypeless(format) ) return E_INVALIDARG; if ( format == DXGI_FORMAT_UNKNOWN ) { // Pick a default decompressed format based on BC input format format = _DefaultDecompress( cImages[0].format ); if ( format == DXGI_FORMAT_UNKNOWN ) { // Input is not a compressed format return E_FAIL; } } else if ( !IsValid(format) ) return E_INVALIDARG; images.Release(); TexMetadata mdata2 = metadata; mdata2.format = format; HRESULT hr = images.Initialize( mdata2 ); if ( FAILED(hr) ) return hr; if ( nimages != images.GetImageCount() ) { images.Release(); return E_FAIL; } const Image* dest = images.GetImages(); if ( !dest ) { images.Release(); return E_POINTER; } for( size_t index=0; index < nimages; ++index ) { assert( dest[ index ].format == format ); const Image& src = cImages[ index ]; if ( !IsCompressed( src.format ) ) { images.Release(); return E_FAIL; } if ( src.width != dest[ index ].width || src.height != dest[ index ].height ) { images.Release(); return E_FAIL; } hr = _DecompressBC( src, dest[ index ] ); if ( FAILED(hr) ) { images.Release(); return hr; } } return S_OK; }
HRESULT Compress( const Image* srcImages, size_t nimages, const TexMetadata& metadata, DXGI_FORMAT format, DWORD compress, float alphaRef, ScratchImage& cImages ) { if ( !srcImages || !nimages ) return E_INVALIDARG; if ( !IsCompressed(format) || IsTypeless(format) ) return E_INVALIDARG; // Image size must be a multiple of 4 (degenerate cases for mipmaps are allowed) size_t width = srcImages[0].width; if ( (width % 4) != 0 ) { if ( width != 1 && width != 2 ) return E_INVALIDARG; } size_t height = srcImages[0].height; if ( (height % 4) != 0 ) { if ( height != 1 && height != 2 ) return E_INVALIDARG; } cImages.Release(); TexMetadata mdata2 = metadata; mdata2.format = format; HRESULT hr = cImages.Initialize( mdata2 ); if ( FAILED(hr) ) return hr; if ( nimages != cImages.GetImageCount() ) { cImages.Release(); return E_FAIL; } const Image* dest = cImages.GetImages(); if ( !dest ) { cImages.Release(); return E_POINTER; } for( size_t index=0; index < nimages; ++index ) { assert( dest[ index ].format == format ); const Image& src = srcImages[ index ]; height = src.height; width = src.width; if ( width != dest[ index ].width || height != dest[ index ].height ) { cImages.Release(); return E_FAIL; } bool degenerate = ((height < 4) || (width < 4)) != 0; if ( (compress & TEX_COMPRESS_PARALLEL) && !degenerate) { #ifndef _OPENMP return E_NOTIMPL; #else if ( compress & TEX_COMPRESS_PARALLEL ) { hr = _CompressBC_Parallel( src, dest[ index ], _GetBCFlags( compress ), alphaRef ); if ( FAILED(hr) ) { cImages.Release(); return hr; } } #endif // _OPENMP } else { hr = _CompressBC( src, dest[ index ], _GetBCFlags( compress ), alphaRef, degenerate ); if ( FAILED(hr) ) { cImages.Release(); return hr; } } } return S_OK; }
_Use_decl_annotations_ HRESULT Compress( const Image* srcImages, size_t nimages, const TexMetadata& metadata, DXGI_FORMAT format, DWORD compress, float alphaRef, ScratchImage& cImages ) { if ( !srcImages || !nimages ) return E_INVALIDARG; if ( IsCompressed(metadata.format) || !IsCompressed(format) ) return E_INVALIDARG; if ( IsTypeless(format) || IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format) ) return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); cImages.Release(); TexMetadata mdata2 = metadata; mdata2.format = format; HRESULT hr = cImages.Initialize( mdata2 ); if ( FAILED(hr) ) return hr; if ( nimages != cImages.GetImageCount() ) { cImages.Release(); return E_FAIL; } const Image* dest = cImages.GetImages(); if ( !dest ) { cImages.Release(); return E_POINTER; } for( size_t index=0; index < nimages; ++index ) { assert( dest[ index ].format == format ); const Image& src = srcImages[ index ]; if ( src.width != dest[ index ].width || src.height != dest[ index ].height ) { cImages.Release(); return E_FAIL; } if ( (compress & TEX_COMPRESS_PARALLEL) ) { #ifndef _OPENMP return E_NOTIMPL; #else if ( compress & TEX_COMPRESS_PARALLEL ) { hr = _CompressBC_Parallel( src, dest[ index ], _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef ); if ( FAILED(hr) ) { cImages.Release(); return hr; } } #endif // _OPENMP } else { hr = _CompressBC( src, dest[ index ], _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef ); if ( FAILED(hr) ) { cImages.Release(); return hr; } } } return S_OK; }
//------------------------------------------------------------------------------------- // 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 ) { if ( !srcImages || !nimages ) return E_INVALIDARG; if ( IsCompressed(metadata.format) || IsVideo(metadata.format) || IsTypeless(metadata.format) || !HasAlpha(metadata.format) ) return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); #ifdef _M_X64 if ( (metadata.width > 0xFFFFFFFF) || (metadata.height > 0xFFFFFFFF) ) return E_INVALIDARG; #endif if ( metadata.IsPMAlpha() ) { // Already premultiplied return E_FAIL; } TexMetadata mdata2 = metadata; mdata2.SetAlphaMode(TEX_ALPHA_MODE_PREMULTIPLIED); 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; } 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 ( src.width != dst.width || src.height != dst.height ) { result.Release(); return E_FAIL; } hr = _PremultiplyAlpha( src, dst ); if ( FAILED(hr) ) { result.Release(); return hr; } } return S_OK; }