void PrintInfo( const TexMetadata& info ) { wprintf( L" (%Iux%Iu", info.width, info.height); if ( TEX_DIMENSION_TEXTURE3D == info.dimension ) wprintf( L"x%Iu", info.depth); if ( info.mipLevels > 1 ) wprintf( L",%Iu", info.mipLevels); if ( info.arraySize > 1 ) wprintf( L",%Iu", info.arraySize); wprintf( L" "); PrintFormat( info.format ); switch ( info.dimension ) { case TEX_DIMENSION_TEXTURE1D: wprintf( (info.arraySize > 1) ? L" 1DArray" : L" 1D" ); break; case TEX_DIMENSION_TEXTURE2D: if ( info.IsCubemap() ) { wprintf( (info.arraySize > 6) ? L" CubeArray" : L" Cube" ); } else { wprintf( (info.arraySize > 1) ? L" 2DArray" : L" 2D" ); } break; case TEX_DIMENSION_TEXTURE3D: wprintf( L" 3D"); break; } wprintf( L")"); }
//------------------------------------------------------------------------------------- // Converts to/from a premultiplied alpha version of the texture (complex) //------------------------------------------------------------------------------------- _Use_decl_annotations_ HRESULT DirectX::PremultiplyAlpha( const Image* srcImages, size_t nimages, const TexMetadata& metadata, DWORD flags, ScratchImage& result) { if (!srcImages || !nimages) return E_INVALIDARG; if (IsCompressed(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format) || IsTypeless(metadata.format) || !HasAlpha(metadata.format)) return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); if ((metadata.width > UINT32_MAX) || (metadata.height > UINT32_MAX)) return E_INVALIDARG; if (metadata.IsPMAlpha() != ((flags & TEX_PMALPHA_REVERSE) != 0)) return E_FAIL; TexMetadata mdata2 = metadata; mdata2.SetAlphaMode((flags & TEX_PMALPHA_REVERSE) ? TEX_ALPHA_MODE_STRAIGHT : 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; } if ((src.width > UINT32_MAX) || (src.height > UINT32_MAX)) return E_FAIL; const Image& dst = dest[index]; assert(dst.format == metadata.format); if (src.width != dst.width || src.height != dst.height) { result.Release(); return E_FAIL; } if (flags & TEX_PMALPHA_REVERSE) { hr = (flags & TEX_PMALPHA_IGNORE_SRGB) ? DemultiplyAlpha(src, dst) : DemultiplyAlphaLinear(src, flags, dst); } else { hr = (flags & TEX_PMALPHA_IGNORE_SRGB) ? PremultiplyAlpha_(src, dst) : PremultiplyAlphaLinear(src, flags, dst); } if (FAILED(hr)) { result.Release(); return hr; } } return S_OK; }
//------------------------------------------------------------------------------------- // Resize image (complex) //------------------------------------------------------------------------------------- _Use_decl_annotations_ 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 _M_X64 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; bool usewic = _UseWICFiltering( metadata.format, filter ); WICPixelFormatGUID pfGUID = {0}; bool wicpf = ( usewic ) ? _DXGIToWIC( metadata.format, pfGUID, true ) : false; 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 _M_X64 if ( (srcimg->width > 0xFFFFFFFF) || (srcimg->height > 0xFFFFFFFF) ) { result.Release(); return E_FAIL; } #endif if ( usewic ) { 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 ); } } else { // Case 3: not using WIC resizing hr = _PerformResizeUsingCustomFilters( *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 _M_X64 if ( (srcimg->width > 0xFFFFFFFF) || (srcimg->height > 0xFFFFFFFF) ) { result.Release(); return E_FAIL; } #endif if ( usewic ) { 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 ); } } else { // Case 3: not using WIC resizing hr = _PerformResizeUsingCustomFilters( *srcimg, filter, *destimg ); } if ( FAILED(hr) ) { result.Release(); return hr; } } break; default: result.Release(); return E_FAIL; } 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; }