//------------------------------------------------------------------------------------- // Resize image //------------------------------------------------------------------------------------- _Use_decl_annotations_ HRESULT Resize( const Image& srcImage, size_t width, size_t height, DWORD filter, ScratchImage& image ) { if ( width == 0 || height == 0 ) return E_INVALIDARG; #ifdef _M_X64 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; if ( _UseWICFiltering( srcImage.format, filter ) ) { WICPixelFormatGUID pfGUID; if ( _DXGIToWIC( srcImage.format, pfGUID, true ) ) { // 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 ); } } else { hr = _PerformResizeUsingCustomFilters( srcImage, filter, *rimage ); } if ( FAILED(hr) ) { image.Release(); return hr; } return S_OK; }
//------------------------------------------------------------------------------------- // 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; }
//------------------------------------------------------------------------------------- // 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; }
//------------------------------------------------------------------------------------- // Decompression //------------------------------------------------------------------------------------- _Use_decl_annotations_ HRESULT DirectX::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/from a premultiplied alpha version of the texture //------------------------------------------------------------------------------------- _Use_decl_annotations_ HRESULT DirectX::PremultiplyAlpha( const Image& srcImage, DWORD flags, ScratchImage& image) { if (!srcImage.pixels) return E_POINTER; if (IsCompressed(srcImage.format) || IsPlanar(srcImage.format) || IsPalettized(srcImage.format) || IsTypeless(srcImage.format) || !HasAlpha(srcImage.format)) return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); if ((srcImage.width > UINT32_MAX) || (srcImage.height > UINT32_MAX)) return E_INVALIDARG; 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; } if (flags & TEX_PMALPHA_REVERSE) { hr = (flags & TEX_PMALPHA_IGNORE_SRGB) ? DemultiplyAlpha(srcImage, *rimage) : DemultiplyAlphaLinear(srcImage, flags, *rimage); } else { hr = (flags & TEX_PMALPHA_IGNORE_SRGB) ? PremultiplyAlpha_(srcImage, *rimage) : PremultiplyAlphaLinear(srcImage, flags, *rimage); } if (FAILED(hr)) { image.Release(); return hr; } return S_OK; }
//------------------------------------------------------------------------------------- // Compression //------------------------------------------------------------------------------------- _Use_decl_annotations_ HRESULT DirectX::Compress( const Image& srcImage, DXGI_FORMAT format, DWORD compress, float threshold, 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), threshold); #endif // _OPENMP } else { hr = CompressBC(srcImage, *img, GetBCFlags(compress), GetSRGBFlags(compress), threshold); } if (FAILED(hr)) image.Release(); return hr; }
// Executes the basic game loop. void Game::Tick() { m_timer.Tick([&]() { Update(m_timer); }); Render(); if (m_screenshot) { OutputDebugStringA("Saving screenshot...\n"); auto commandQ = m_deviceResources->GetCommandQueue(); DX::ThrowIfFailed( SaveDDSTextureToFile(commandQ, m_screenshot.Get(), L"screenshot.dds", D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_PRESENT) ); DX::ThrowIfFailed( SaveWICTextureToFile(commandQ, m_screenshot.Get(), GUID_ContainerFormatJpeg, L"screenshot.jpg", D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_PRESENT) ); ScratchImage image; DX::ThrowIfFailed(CaptureTexture(commandQ, m_screenshot.Get(), false, image, D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_PRESENT)); DX::ThrowIfFailed(SaveToDDSFile(image.GetImages(), image.GetImageCount(), image.GetMetadata(), DDS_FLAGS_NONE, L"screenshot2.dds")); DX::ThrowIfFailed(SaveToWICFile(*image.GetImage(0, 0, 0), WIC_FLAGS_NONE, GUID_ContainerFormatJpeg, L"screenshot2.jpg")); m_screenshot.Reset(); } ++m_frame; }
//------------------------------------------------------------------------------------- // Decompression //------------------------------------------------------------------------------------- HRESULT Decompress( const Image& cImage, DXGI_FORMAT format, ScratchImage& image ) { 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( cImage.format ); if ( format == DXGI_FORMAT_UNKNOWN ) { // Input is not a compressed format return E_INVALIDARG; } } else if ( !IsCompressed(cImage.format) || !IsValid(format) ) return E_INVALIDARG; // 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; }
//------------------------------------------------------------------------------------- // Flip/rotate image //------------------------------------------------------------------------------------- _Use_decl_annotations_ 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; }
//------------------------------------------------------------------------------------- // CaptureTexture bool Test05() { ComPtr<ID3D11Device> device; ComPtr<ID3D11DeviceContext> context; HRESULT hr = CreateDevice(device.GetAddressOf(), context.GetAddressOf()); if (FAILED(hr)) { printe("Failed creating device (HRESULT %08X)\n", hr); return false; } bool success = true; size_t ncount = 0; size_t npass = 0; for (size_t index = 0; index < _countof(g_TestMedia); ++index) { if (g_TestMedia[index].options & FLAGS_NOT_SUPPORTED) { continue; } wchar_t szPath[MAX_PATH] = {}; DWORD ret = ExpandEnvironmentStringsW(g_TestMedia[index].fname, szPath, MAX_PATH); if (!ret || ret > MAX_PATH) { printe("ERROR: ExpandEnvironmentStrings FAILED\n"); return false; } #ifdef _DEBUG OutputDebugString(szPath); OutputDebugStringA("\n"); #endif // Form dest path wchar_t ext[_MAX_EXT]; wchar_t fname[_MAX_FNAME]; _wsplitpath_s(szPath, nullptr, 0, nullptr, 0, fname, _MAX_FNAME, ext, _MAX_EXT); wchar_t tempDir[MAX_PATH] = {}; ret = ExpandEnvironmentStringsW(TEMP_PATH L"d3d11", tempDir, MAX_PATH); if (!ret || ret > MAX_PATH) { printe("ERROR: ExpandEnvironmentStrings FAILED\n"); return false; } CreateDirectoryW(tempDir, nullptr); wchar_t szDestPath[MAX_PATH] = {}; _wmakepath_s(szDestPath, MAX_PATH, nullptr, tempDir, fname, L".dds"); TexMetadata metadata; ScratchImage image; if (_wcsicmp(ext, L".dds") == 0) { hr = LoadFromDDSFile(szPath, DDS_FLAGS_NONE, &metadata, image); } else { hr = LoadFromWICFile(szPath, WIC_FLAGS_NONE, &metadata, image); } bool forceNoMips = false; const TexMetadata* check = &g_TestMedia[index].metadata; if (FAILED(hr)) { success = false; printe("Failed getting data from (HRESULT %08X):\n%ls\n", hr, szPath); } else if (memcmp(&metadata, check, sizeof(TexMetadata)) != 0) { success = false; printe("Metadata error in:\n%ls\n", szPath); printmeta(&metadata); printmetachk(check); } else { bool pass = true; if (g_TestMedia[index].options & FLAGS_YUV) { if (!IsSupportedTexture(device.Get(), metadata)) { // Can't create video textures with mips on most hardware metadata.mipLevels = 1; forceNoMips = true; if (!IsSupportedTexture(device.Get(), metadata)) { print("WARNING: Format %u is not supported by this hardware\n", metadata.format); continue; } } } { ComPtr<ID3D11Resource> pResource; hr = CreateTexture(device.Get(), image.GetImages(), image.GetImageCount(), metadata, pResource.GetAddressOf()); if (FAILED(hr)) { success = false; printe("Failed creating texture from (HRESULT %08X):\n%ls\n", hr, szPath); } else { ScratchImage image2; hr = CaptureTexture(device.Get(), context.Get(), pResource.Get(), image2); if (FAILED(hr)) { success = false; printe("Failed capturing texture from (HRESULT %08X):\n%ls\n", hr, szPath); } else { const TexMetadata& mdata2 = image2.GetMetadata(); if (memcmp(&mdata2, &metadata, sizeof(TexMetadata)) != 0) { success = false; printe("Metadata error in:\n%ls\n", szDestPath); printmeta(&mdata2); printmetachk(check); } else if (!forceNoMips && image.GetImageCount() != image2.GetImageCount()) { success = false; printe("Image count in captured texture (%zu) doesn't match source (%zu) in:\n%ls\n", image2.GetImageCount(), image.GetImageCount(), szDestPath); } else { hr = SaveToDDSFile(image2.GetImages(), image2.GetImageCount(), image2.GetMetadata(), DDS_FLAGS_NONE, szDestPath); if (FAILED(hr)) { success = false; pass = false; printe("Failed writing DDS to (HRESULT %08X):\n%ls\n", hr, szDestPath); } if (!IsPlanar(metadata.format)) { float mse, mseV[4]; hr = ComputeMSE(*image.GetImage(0, 0, 0), *image2.GetImage(0, 0, 0), mse, mseV); if (FAILED(hr)) { success = false; pass = false; printe("Failed comparing captured image (HRESULT %08X):\n%ls\n", hr, szPath); } else if (fabs(mse) > 0.000001f) { success = false; pass = false; printe("Failed comparing captured image MSE = %f (%f %f %f %f)... 0.f:\n%ls\n", mse, mseV[0], mseV[1], mseV[2], mseV[3], szPath); } } } } } } // Staging resource tests { ComPtr<ID3D11Resource> pStaging; hr = CreateTextureEx(device.Get(), image.GetImages(), image.GetImageCount(), metadata, D3D11_USAGE_STAGING, 0, D3D11_CPU_ACCESS_READ, 0, false, pStaging.GetAddressOf()); if (FAILED(hr)) { success = false; pass = false; printe("Failed creating test staging texture (HRESULT %08X):\n%ls\n", hr, szPath); } else { ScratchImage image2; hr = CaptureTexture(device.Get(), context.Get(), pStaging.Get(), image2); if (FAILED(hr)) { success = false; printe("Failed capturing texture from staging texture (HRESULT %08X):\n%ls\n", hr, szPath); } else { const TexMetadata& mdata2 = image2.GetMetadata(); if (memcmp(&mdata2, &metadata, sizeof(TexMetadata)) != 0) { success = false; printe("Metadata error in:\n%ls\n", szDestPath); printmeta(&mdata2); printmetachk(check); } else if (!forceNoMips && image.GetImageCount() != image2.GetImageCount()) { success = false; printe("Image count in captured texture staging texture (%zu) doesn't match source (%zu) in:\n%ls\n", image2.GetImageCount(), image.GetImageCount(), szDestPath); } else { wchar_t tname[MAX_PATH] = {}; wcscpy_s(tname, fname); wcscat_s(tname, L"_staging"); wchar_t szDestPath2[MAX_PATH] = {}; _wmakepath_s(szDestPath2, MAX_PATH, nullptr, tempDir, tname, L".dds"); hr = SaveToDDSFile(image2.GetImages(), image2.GetImageCount(), image2.GetMetadata(), DDS_FLAGS_NONE, szDestPath2); if (FAILED(hr)) { success = false; pass = false; printe("Failed writing DDS to (HRESULT %08X):\n%ls\n", hr, szDestPath2); } if (!IsPlanar(metadata.format)) { float mse, mseV[4]; hr = ComputeMSE(*image.GetImage(0, 0, 0), *image2.GetImage(0, 0, 0), mse, mseV); if (FAILED(hr)) { success = false; pass = false; printe("Failed comparing captured image (HRESULT %08X):\n%ls\n", hr, szPath); } else if (fabs(mse) > 0.000001f) { success = false; pass = false; printe("Failed comparing captured image MSE = %f (%f %f %f %f)... 0.f:\n%ls\n", mse, mseV[0], mseV[1], mseV[2], mseV[3], szPath); } } } } } } // CaptureTexture of an MSAA resource is tested elsewhere if (pass) ++npass; } ++ncount; } print("%zu images tested, %zu images passed ", ncount, npass); return success; }
//------------------------------------------------------------------------------------- // 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; }