HRESULT ConvertBitmapSource( RECT rcDest, IWICBitmapSource*& pToRenderBitmapSource ) { HRESULT hr = S_OK; IWICBitmapScaler* pScaler = nullptr; WICPixelFormatGUID pxformat; IWICFormatConverter* pConverter = nullptr; pToRenderBitmapSource = nullptr; // Get the client Rect //RECT rcClient = rcDest; //hr = GetClientRect(hWnd, &rcClient) ? S_OK: E_FAIL; if( SUCCEEDED( hr ) ) { // Create a BitmapScaler hr = g_UserImageFactoryInst.m_pIWICFactory->CreateBitmapScaler( &pScaler ); //hr = IWICImagingFactory_CreateBitmapScaler( g_UserImageFactoryInst.m_pIWICFactory, &pScaler ); // Initialize the bitmap scaler from the original bitmap map bits if( SUCCEEDED( hr ) ) { pScaler->Initialize( g_UserImageFactoryInst.m_pOriginalBitmapSource, rcDest.right - rcDest.left, rcDest.bottom - rcDest.top, WICBitmapInterpolationModeFant ); } //hr = IWICBitmapScaler_GetPixelFormat( pScaler, &pxformat ); hr = pScaler->GetPixelFormat( &pxformat ); // Format convert the bitmap into 32bppBGR, a convenient // pixel format for GDI rendering if( SUCCEEDED( hr ) ) { //hr = IWICImagingFactory_CreateFormatConverter( g_UserImageFactoryInst.m_pIWICFactory, &pConverter ); hr = g_UserImageFactoryInst.m_pIWICFactory->CreateFormatConverter( &pConverter ); // Format convert to 32bppBGR if( SUCCEEDED( hr ) ) { hr = pConverter->Initialize( static_cast<IWICBitmapSource*>( pScaler ), // Input bitmap to convert GUID_WICPixelFormat32bppBGR, // &GUID_WICPixelFormat32bppBGR, WICBitmapDitherTypeNone, // Specified dither patterm NULL, // Specify a particular palette 0.f, // Alpha threshold WICBitmapPaletteTypeCustom ); // Palette translation type // Store the converted bitmap as ppToRenderBitmapSource if( SUCCEEDED( hr ) ) pConverter->QueryInterface( IID_IWICBitmapSource, reinterpret_cast<void**>( &pToRenderBitmapSource ) ); } SAFE_RELEASE( pConverter ); } SAFE_RELEASE( pScaler ); } return hr; }
STDMETHODIMP BaseFrameEncode::Commit() { HRESULT result = S_OK; IWICBitmapScaler *scaler = NULL; IWICFormatConverter *formatConverter = NULL; result = S_OK; // Create a scaler to match the requested width and height if (SUCCEEDED(result)) { result = factory->CreateBitmapScaler(&scaler); } if (SUCCEEDED(result)) { result = scaler->Initialize(destSource, destWidth, destHeight, WICBitmapInterpolationModeFant); } // Create a format converter to output into the proper format if (SUCCEEDED(result)) { result = factory->CreateFormatConverter(&formatConverter); } if (SUCCEEDED(result)) { result = formatConverter->Initialize(scaler, destPixelFormat, WICBitmapDitherTypeErrorDiffusion, destPalette, 50.0, WICBitmapPaletteTypeCustom); } // Cleanup if (formatConverter) { destSource->Release(); destSource = formatConverter; } return result; }
HRESULT App::LoadResourceBitmap( ID2D1RenderTarget *pRenderTarget, IWICImagingFactory *pIWICFactory, PCWSTR resourceName, PCWSTR resourceType, UINT destinationWidth, UINT destinationHeight, ID2D1Bitmap **ppBitmap ) { IWICBitmapDecoder *pDecoder = NULL; IWICBitmapFrameDecode *pSource = NULL; IWICStream *pStream = NULL; IWICFormatConverter *pConverter = NULL; IWICBitmapScaler *pScaler = NULL; HRSRC imageResHandle = NULL; HGLOBAL imageResDataHandle = NULL; void *pImageFile = NULL; DWORD imageFileSize = 0; // Locate the resource. imageResHandle = FindResourceW(HINST_THISCOMPONENT, resourceName, resourceType); HRESULT hr = imageResHandle ? S_OK : E_FAIL; if (SUCCEEDED(hr)) { // Load the resource. imageResDataHandle = LoadResource(HINST_THISCOMPONENT, imageResHandle); hr = imageResDataHandle ? S_OK : E_FAIL; } if (SUCCEEDED(hr)) { // Lock it to get a system memory pointer. pImageFile = LockResource(imageResDataHandle); hr = pImageFile ? S_OK : E_FAIL; } if (SUCCEEDED(hr)) { // Calculate the size. imageFileSize = SizeofResource(HINST_THISCOMPONENT, imageResHandle); hr = imageFileSize ? S_OK : E_FAIL; } if (SUCCEEDED(hr)) { // Create a WIC stream to map onto the memory. hr = pIWICFactory->CreateStream(&pStream); } if (SUCCEEDED(hr)) { // Initialize the stream with the memory pointer and size. hr = pStream->InitializeFromMemory( reinterpret_cast<BYTE*>(pImageFile), imageFileSize ); } if (SUCCEEDED(hr)) { // Create a decoder for the stream. hr = pIWICFactory->CreateDecoderFromStream( pStream, NULL, WICDecodeMetadataCacheOnLoad, &pDecoder ); } if (SUCCEEDED(hr)) { // Create the initial frame. hr = pDecoder->GetFrame(0, &pSource); } if (SUCCEEDED(hr)) { // Convert the image format to 32bppPBGRA // (DXGI_FORMAT_B8G8R8A8_UNORM + D2D1_ALPHA_MODE_PREMULTIPLIED). hr = pIWICFactory->CreateFormatConverter(&pConverter); } if (SUCCEEDED(hr)) { // If a new width or height was specified, create an // IWICBitmapScaler and use it to resize the image. if (destinationWidth != 0 || destinationHeight != 0) { UINT originalWidth, originalHeight; hr = pSource->GetSize(&originalWidth, &originalHeight); if (SUCCEEDED(hr)) { if (destinationWidth == 0) { FLOAT scalar = static_cast<FLOAT>(destinationHeight) / static_cast<FLOAT>(originalHeight); destinationWidth = static_cast<UINT>(scalar * static_cast<FLOAT>(originalWidth)); } else if (destinationHeight == 0) { FLOAT scalar = static_cast<FLOAT>(destinationWidth) / static_cast<FLOAT>(originalWidth); destinationHeight = static_cast<UINT>(scalar * static_cast<FLOAT>(originalHeight)); } hr = pIWICFactory->CreateBitmapScaler(&pScaler); if (SUCCEEDED(hr)) { hr = pScaler->Initialize( pSource, destinationWidth, destinationHeight, WICBitmapInterpolationModeCubic ); if (SUCCEEDED(hr)) { hr = pConverter->Initialize( pScaler, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, NULL, 0.f, WICBitmapPaletteTypeMedianCut ); } } } } else { hr = pConverter->Initialize( pSource, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, NULL, 0.f, WICBitmapPaletteTypeMedianCut ); } } if (SUCCEEDED(hr)) { //create a Direct2D bitmap from the WIC bitmap. hr = pRenderTarget->CreateBitmapFromWicBitmap( pConverter, NULL, ppBitmap ); } SafeRelease(&pDecoder); SafeRelease(&pSource); SafeRelease(&pStream); SafeRelease(&pConverter); SafeRelease(&pScaler); return hr; }
/// <summary> /// Load an image from a resource into a buffer /// </summary> /// <param name="resourceName">name of image resource to load</param> /// <param name="resourceType">type of resource to load</param> /// <param name="nOutputWidth">width (in pixels) of scaled output bitmap</param> /// <param name="nOutputHeight">height (in pixels) of scaled output bitmap</param> /// <param name="pOutputBuffer">buffer that will hold the loaded image</param> /// <returns>S_OK on success, otherwise failure code</returns> HRESULT CCoordinateMappingBasics::LoadResourceImage(PCWSTR resourceName, PCWSTR resourceType, UINT nOutputWidth, UINT nOutputHeight, RGBQUAD* pOutputBuffer) { IWICImagingFactory* pIWICFactory = NULL; IWICBitmapDecoder* pDecoder = NULL; IWICBitmapFrameDecode* pSource = NULL; IWICStream* pStream = NULL; IWICFormatConverter* pConverter = NULL; IWICBitmapScaler* pScaler = NULL; HRSRC imageResHandle = NULL; HGLOBAL imageResDataHandle = NULL; void *pImageFile = NULL; DWORD imageFileSize = 0; HRESULT hrCoInit = CoInitialize(NULL); HRESULT hr = hrCoInit; if (SUCCEEDED(hr)) { hr = CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, (LPVOID*)&pIWICFactory); } if (SUCCEEDED(hr)) { // Locate the resource imageResHandle = FindResourceW(HINST_THISCOMPONENT, resourceName, resourceType); hr = imageResHandle ? S_OK : E_FAIL; } if (SUCCEEDED(hr)) { // Load the resource imageResDataHandle = LoadResource(HINST_THISCOMPONENT, imageResHandle); hr = imageResDataHandle ? S_OK : E_FAIL; } if (SUCCEEDED(hr)) { // Lock it to get a system memory pointer. pImageFile = LockResource(imageResDataHandle); hr = pImageFile ? S_OK : E_FAIL; } if (SUCCEEDED(hr)) { // Calculate the size. imageFileSize = SizeofResource(HINST_THISCOMPONENT, imageResHandle); hr = imageFileSize ? S_OK : E_FAIL; } if (SUCCEEDED(hr)) { // Create a WIC stream to map onto the memory. hr = pIWICFactory->CreateStream(&pStream); } if (SUCCEEDED(hr)) { // Initialize the stream with the memory pointer and size. hr = pStream->InitializeFromMemory( reinterpret_cast<BYTE*>(pImageFile), imageFileSize); } if (SUCCEEDED(hr)) { // Create a decoder for the stream. hr = pIWICFactory->CreateDecoderFromStream( pStream, NULL, WICDecodeMetadataCacheOnLoad, &pDecoder); } if (SUCCEEDED(hr)) { // Create the initial frame. hr = pDecoder->GetFrame(0, &pSource); } if (SUCCEEDED(hr)) { // Convert the image format to 32bppPBGRA // (DXGI_FORMAT_B8G8R8A8_UNORM + D2D1_ALPHA_MODE_PREMULTIPLIED). hr = pIWICFactory->CreateFormatConverter(&pConverter); } if (SUCCEEDED(hr)) { hr = pIWICFactory->CreateBitmapScaler(&pScaler); } if (SUCCEEDED(hr)) { hr = pScaler->Initialize( pSource, nOutputWidth, nOutputHeight, WICBitmapInterpolationModeCubic ); } if (SUCCEEDED(hr)) { hr = pConverter->Initialize( pScaler, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, NULL, 0.f, WICBitmapPaletteTypeMedianCut); } UINT width = 0; UINT height = 0; if (SUCCEEDED(hr)) { hr = pConverter->GetSize(&width, &height); } // make sure the image scaled correctly so the output buffer is big enough if (SUCCEEDED(hr)) { if ((width != nOutputWidth) || (height != nOutputHeight)) { hr = E_FAIL; } } if (SUCCEEDED(hr)) { hr = pConverter->CopyPixels(NULL, width * sizeof(RGBQUAD), nOutputWidth * nOutputHeight * sizeof(RGBQUAD), reinterpret_cast<BYTE*>(pOutputBuffer)); } SafeRelease(pScaler); SafeRelease(pConverter); SafeRelease(pSource); SafeRelease(pDecoder); SafeRelease(pStream); SafeRelease(pIWICFactory); if (SUCCEEDED(hrCoInit)) { CoUninitialize(); } return hr; }
HRESULT LoadBitmapFromFile( PCWSTR uri, UINT dweight, UINT dheight, ID2D1Bitmap **bitmap ) { HRESULT hr = S_OK; IWICImagingFactory* pWICFactory = NULL; IWICBitmapDecoder* pDecoder = NULL; IWICBitmapScaler* pScaler = NULL; IWICBitmapFrameDecode* pSource = NULL; IWICFormatConverter* pConverter = NULL; hr = CoCreateInstance( CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, (LPVOID*)&pWICFactory); if (SUCCEEDED(hr)) { hr = pWICFactory->CreateDecoderFromFilename( uri, NULL, GENERIC_READ, WICDecodeMetadataCacheOnLoad, &pDecoder); } if (SUCCEEDED(hr)) { hr = pDecoder->GetFrame(0, &pSource); } if (SUCCEEDED(hr)) { hr = pWICFactory->CreateFormatConverter(&pConverter); } if (SUCCEEDED(hr)) { UINT oWeight, oHeight; hr = pSource->GetSize(&oWeight, &oHeight); if (SUCCEEDED(hr)) { hr = pWICFactory->CreateBitmapScaler(&pScaler); if (SUCCEEDED(hr)) { hr = pScaler->Initialize( pSource, dweight, dheight, WICBitmapInterpolationModeCubic); } if (SUCCEEDED(hr)) { hr = pConverter->Initialize( pScaler, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, NULL, 0.f, WICBitmapPaletteTypeMedianCut ); } } } if (SUCCEEDED(hr)) { hr = pRT->CreateBitmapFromWicBitmap(pConverter, bitmap); } Safe_Release(pWICFactory); Safe_Release(pDecoder); Safe_Release(pScaler); Safe_Release(pSource); Safe_Release(pConverter); return hr; }
// Create a Direct2D bitmap from the specified file name HRESULT DemoApp::LoadBitmapFromFile( ID2D1RenderTarget *pRenderTarget, IWICImagingFactory *pIWICFactory, PCWSTR uri, UINT destinationWidth, UINT destinationHeight, ID2D1Bitmap **ppBitmap) { HRESULT hr = S_OK; IWICBitmapDecoder *pDecoder = NULL; IWICBitmapFrameDecode *pSource = NULL; IWICStream *pStream = NULL; IWICFormatConverter *pConverter = NULL; IWICBitmapScaler *pScaler = NULL; hr = pIWICFactory->CreateDecoderFromFilename( uri, NULL, GENERIC_READ, WICDecodeMetadataCacheOnLoad, &pDecoder); if (SUCCEEDED(hr)) { // Create the initial frame hr = pDecoder->GetFrame(0, &pSource); } if (SUCCEEDED(hr)) { // Convert the image format to 32bppPBGRA // (DXGI_FORMAT_B8G8R8A8_UNORM + D2D1_ALPHA_MODE_PREMULTIPLIED). hr = pIWICFactory->CreateFormatConverter(&pConverter); } if (SUCCEEDED(hr)) { // If a new width or height was specified, create an // IWICBitmapScaler and use it to resize the image. if (destinationWidth != 0 || destinationHeight != 0) { UINT originalWidth, originalHeight; hr = pSource->GetSize(&originalWidth, &originalHeight); if (SUCCEEDED(hr)) { if (destinationWidth == 0) { FLOAT scalar = static_cast<FLOAT>(destinationHeight) / static_cast<FLOAT>(originalHeight); destinationWidth = static_cast<UINT>(scalar * static_cast<FLOAT>(originalWidth)); } else if (destinationHeight == 0) { FLOAT scalar = static_cast<FLOAT>(destinationWidth) / static_cast<FLOAT>(originalWidth); destinationHeight = static_cast<UINT>(scalar * static_cast<FLOAT>(originalHeight)); } hr = pIWICFactory->CreateBitmapScaler(&pScaler); if (SUCCEEDED(hr)) { hr = pScaler->Initialize( pSource, destinationWidth, destinationHeight, WICBitmapInterpolationModeCubic); } if (SUCCEEDED(hr)) { hr = pConverter->Initialize( pScaler, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, NULL, 0.f, WICBitmapPaletteTypeMedianCut); } } } else // Don't scale the image. { hr = pConverter->Initialize( pSource, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, NULL, 0.f, WICBitmapPaletteTypeMedianCut); } } if (SUCCEEDED(hr)) { // Create a Direct2D bitmap from the WIC bitmap. hr = pRenderTarget->CreateBitmapFromWicBitmap( pConverter, NULL, ppBitmap); } SafeRelease(&pDecoder); SafeRelease(&pSource); SafeRelease(&pStream); SafeRelease(&pConverter); SafeRelease(&pScaler); return hr; }
ID2D1Bitmap * BaseButton::LoadBitmap(wchar_t* sz_path) { ID2D1Bitmap *p_bmp=NULL; IWICBitmapDecoder *pDecoder = NULL; IWICBitmapFrameDecode *pSource = NULL; IWICStream *pStream = NULL; IWICFormatConverter *pConverter = NULL; IWICBitmapScaler *pScaler = NULL; HRESULT hr; hr = g_pIWICFactory->CreateDecoderFromFilename(sz_path,NULL,GENERIC_READ,WICDecodeMetadataCacheOnLoad,&pDecoder); if (SUCCEEDED(hr)) { // Create the initial frame. hr = pDecoder->GetFrame(0, &pSource); } if (SUCCEEDED(hr)) { // Convert the image format to 32bppPBGRA // (DXGI_FORMAT_B8G8R8A8_UNORM + D2D1_ALPHA_MODE_PREMULTIPLIED). hr = g_pIWICFactory->CreateFormatConverter(&pConverter); } if (SUCCEEDED(hr)) { // If a new width or height was specified, create an // IWICBitmapScaler and use it to resize the image. UINT originalWidth, originalHeight; hr = pSource->GetSize(&originalWidth, &originalHeight); } if (SUCCEEDED(hr)) { hr =g_pIWICFactory->CreateBitmapScaler(&pScaler); } if (SUCCEEDED(hr)) { hr = pScaler->Initialize(pSource,50,30,WICBitmapInterpolationModeCubic); } if (SUCCEEDED(hr)) { hr = pConverter->Initialize(pScaler,GUID_WICPixelFormat32bppPBGRA,WICBitmapDitherTypeNone,NULL,0.f,WICBitmapPaletteTypeMedianCut); } if (SUCCEEDED(hr)) { // Create a Direct2D bitmap from the WIC bitmap. hr =m_pRenderTarget->CreateBitmapFromWicBitmap(pConverter,NULL,&p_bmp); } SafeRelease(&pDecoder); SafeRelease(&pSource); SafeRelease(&pStream); SafeRelease(&pConverter); SafeRelease(&pScaler); // if (SUCCEEDED(hr)) // { // return TRUE; // } // else // return FALSE; return p_bmp; }
/// <summary> /// Load an image from a resource into a buffer /// </summary> /// <param name="resourceName">name of image resource to load</param> /// <param name="resourceType">type of resource to load</param> /// <param name="cOutputBuffer">size of output buffer, in bytes</param> /// <param name="outputBuffer">buffer that will hold the loaded image</param> /// <returns>S_OK on success, otherwise failure code</returns> HRESULT KinectEasyGrabber::LoadResourceImage( PCWSTR resourceName, PCWSTR resourceType, DWORD cOutputBuffer, BYTE* outputBuffer ) { HRESULT hr = S_OK; IWICImagingFactory* pIWICFactory = NULL; IWICBitmapDecoder* pDecoder = NULL; IWICBitmapFrameDecode* pSource = NULL; IWICStream* pStream = NULL; IWICFormatConverter* pConverter = NULL; IWICBitmapScaler* pScaler = NULL; HRSRC imageResHandle = NULL; HGLOBAL imageResDataHandle = NULL; void *pImageFile = NULL; DWORD imageFileSize = 0; hr = CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, (LPVOID*)&pIWICFactory); if ( FAILED(hr) ) return hr; // Locate the resource. imageResHandle = FindResourceW(HINST_THISCOMPONENT, resourceName, resourceType); hr = imageResHandle ? S_OK : E_FAIL; if (SUCCEEDED(hr)) { // Load the resource. imageResDataHandle = LoadResource(HINST_THISCOMPONENT, imageResHandle); hr = imageResDataHandle ? S_OK : E_FAIL; } if (SUCCEEDED(hr)) { // Lock it to get a system memory pointer. pImageFile = LockResource(imageResDataHandle); hr = pImageFile ? S_OK : E_FAIL; } if (SUCCEEDED(hr)) { // Calculate the size. imageFileSize = SizeofResource(HINST_THISCOMPONENT, imageResHandle); hr = imageFileSize ? S_OK : E_FAIL; } if (SUCCEEDED(hr)) { // Create a WIC stream to map onto the memory. hr = pIWICFactory->CreateStream(&pStream); } if (SUCCEEDED(hr)) { // Initialize the stream with the memory pointer and size. hr = pStream->InitializeFromMemory( reinterpret_cast<BYTE*>(pImageFile), imageFileSize ); } if (SUCCEEDED(hr)) { // Create a decoder for the stream. hr = pIWICFactory->CreateDecoderFromStream( pStream, NULL, WICDecodeMetadataCacheOnLoad, &pDecoder ); } if (SUCCEEDED(hr)) { // Create the initial frame. hr = pDecoder->GetFrame(0, &pSource); } if (SUCCEEDED(hr)) { // Convert the image format to 32bppPBGRA // (DXGI_FORMAT_B8G8R8A8_UNORM + D2D1_ALPHA_MODE_PREMULTIPLIED). hr = pIWICFactory->CreateFormatConverter(&pConverter); } if (SUCCEEDED(hr)) { hr = pIWICFactory->CreateBitmapScaler(&pScaler); } if (SUCCEEDED(hr)) { hr = pScaler->Initialize( pSource, m_colorWidth, m_colorHeight, WICBitmapInterpolationModeCubic ); } if (SUCCEEDED(hr)) { hr = pConverter->Initialize( pScaler, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, NULL, 0.f, WICBitmapPaletteTypeMedianCut ); } UINT width = 0; UINT height = 0; if (SUCCEEDED(hr)) { hr = pConverter->GetSize(&width, &height); } // make sure the output buffer is large enough if (SUCCEEDED(hr)) { if ( width*height*cBytesPerPixel > cOutputBuffer ) { hr = E_FAIL; } } if (SUCCEEDED(hr)) { hr = pConverter->CopyPixels(NULL, width*cBytesPerPixel, cOutputBuffer, outputBuffer); } SafeRelease(pScaler); SafeRelease(pConverter); SafeRelease(pSource); SafeRelease(pDecoder); SafeRelease(pStream); SafeRelease(pIWICFactory); return hr; }
bool Image::Initialize(wchar_t *filename, Graphics *graphics) { std::ifstream file; IWICImagingFactory *pWIC; IWICStream *stream; IWICBitmapDecoder *decoder; IWICBitmapFrameDecode *frame; unsigned int width, height, twidth, theight, maxsize, bpp, i, support, rowPitch, imageSize; float ratio; WICPixelFormatGUID pixelFormat; DXGI_FORMAT format; IWICComponentInfo *cinfo; IWICPixelFormatInfo *pfinfo; IWICBitmapScaler *scaler; bool autogen = false; D3D11_TEXTURE2D_DESC desc; D3D11_SUBRESOURCE_DATA initData; D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; file.open(filename, std::ios::in | std::ios::binary | std::ios::ate); if(!file.is_open()) return false; m_size = file.tellg(); file.seekg(0, std::ios::beg); m_bytes = new unsigned char [m_size]; file.read((char *)m_bytes, m_size); file.close(); RETURN_FAIL( CoCreateInstance( CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, __uuidof(IWICImagingFactory), (LPVOID*)&pWIC ) ); RETURN_FAIL( pWIC->CreateStream( &stream ) ); RETURN_FAIL( stream->InitializeFromMemory( m_bytes, m_size ) ); RETURN_FAIL( pWIC->CreateDecoderFromStream( stream, 0, WICDecodeMetadataCacheOnDemand, &decoder ) ); RETURN_FAIL( decoder->GetFrame( 0, &frame ) ); RETURN_FAIL( frame->GetSize( &width, &height ) ); SAFE_RELEASE( stream ); SAFE_RELEASE( decoder ); if( width <= 0 || height <= 0 ) return false; maxsize = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; if( width > maxsize || height > maxsize ) { ratio = static_cast<float>(height) / static_cast<float>(width); if(width > height) { twidth = maxsize; theight = static_cast<unsigned int>( static_cast<float>(maxsize) * ratio ); } else { theight = maxsize; twidth = static_cast<unsigned int>( static_cast<float>(maxsize) / ratio ); } } else { twidth = width; theight = height; } RETURN_FAIL( frame->GetPixelFormat( &pixelFormat ) ); format = DXGI_FORMAT_UNKNOWN; for( i = 0; i < _countof(g_WICFormats); ++i ) { if( memcmp( &g_WICFormats[i].wic, &pixelFormat, sizeof(GUID) ) == 0 ) { format = g_WICFormats[i].dxgi; break; } } RETURN_FAIL( pWIC->CreateComponentInfo( pixelFormat, &cinfo ) ); RETURN_FAIL( cinfo->QueryInterface( __uuidof(IWICPixelFormatInfo), (LPVOID*)&pfinfo ) ); RETURN_FAIL( pfinfo->GetBitsPerPixel( &bpp ) ); SAFE_RELEASE( cinfo ); SAFE_RELEASE( pfinfo ); RETURN_FAIL( graphics->GetDevice()->CheckFormatSupport( format, &support ) ); if( !(support & D3D11_FORMAT_SUPPORT_TEXTURE2D) ) return false; rowPitch = ( twidth * bpp + 7 ) / 8; imageSize = rowPitch * theight; std::unique_ptr<uint8_t[]> temp( new (std::nothrow) uint8_t[ imageSize ] ); if( !temp ) return false; if( twidth == width && theight == height ) { RETURN_FAIL( frame->CopyPixels( 0, rowPitch, imageSize, temp.get() ) ); } else { RETURN_FAIL( pWIC->CreateBitmapScaler( &scaler ) ); RETURN_FAIL( scaler->Initialize( frame, twidth, theight, WICBitmapInterpolationModeFant ) ); RETURN_FAIL( scaler->CopyPixels( 0, rowPitch, imageSize, temp.get() ) ); SAFE_RELEASE( scaler ); } SAFE_RELEASE( frame ); if( support & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN ) { autogen = true; } desc.Width = twidth; desc.Height = theight; desc.MipLevels = (autogen) ? 0 : 1; desc.ArraySize = 1; desc.Format = format; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Usage = D3D11_USAGE_DEFAULT; desc.CPUAccessFlags = 0; desc.BindFlags = (autogen) ? D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET : D3D11_BIND_SHADER_RESOURCE; desc.MiscFlags = (autogen) ? D3D11_RESOURCE_MISC_GENERATE_MIPS : 0; initData.pSysMem = temp.get(); initData.SysMemPitch = rowPitch; initData.SysMemSlicePitch = imageSize; RETURN_FAIL( graphics->GetDevice()->CreateTexture2D( &desc, (autogen) ? nullptr : &initData, &m_texture2D ) ); //ZeroMemory( &SRVDesc, sizeof( SRVDesc ) ); memset( &SRVDesc, 0, sizeof( SRVDesc ) ); SRVDesc.Format = desc.Format; SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; SRVDesc.Texture2D.MipLevels = (autogen) ? -1 : 1; RETURN_FAIL( graphics->GetDevice()->CreateShaderResourceView( m_texture2D, &SRVDesc, &m_shaderResourceView ) ); if( autogen ) { graphics->GetContext()->UpdateSubresource( m_texture2D, 0, nullptr, temp.get(), rowPitch, imageSize ); graphics->GetContext()->GenerateMips( m_shaderResourceView ); } SAFE_RELEASE(pWIC); }
HRESULT touchmind::Context::LoadResourceBitmap(ID2D1RenderTarget *pRenderTarget, IWICImagingFactory *pIWICFactory, PCWSTR resourceName, PCWSTR resourceType, UINT destinationWidth, UINT destinationHeight, ID2D1Bitmap **ppBitmap) { #ifdef TOUCHMIND_CONTEXT_DEBUG LOG_ENTER; #endif HRESULT hr = S_OK; IWICBitmapDecoder *pDecoder = nullptr; IWICBitmapFrameDecode *pSource = nullptr; IWICStream *pStream = nullptr; IWICFormatConverter *pConverter = nullptr; IWICBitmapScaler *pScaler = nullptr; HRSRC imageResHandle = nullptr; HGLOBAL imageResDataHandle = nullptr; void *pImageFile = nullptr; DWORD imageFileSize = 0; imageResHandle = FindResourceW(HINST_THISCOMPONENT, resourceName, resourceType); hr = imageResHandle ? S_OK : E_FAIL; if (SUCCEEDED(hr)) { imageResDataHandle = LoadResource(HINST_THISCOMPONENT, imageResHandle); hr = imageResDataHandle ? S_OK : E_FAIL; } if (SUCCEEDED(hr)) { pImageFile = LockResource(imageResDataHandle); hr = pImageFile ? S_OK : E_FAIL; } if (SUCCEEDED(hr)) { imageFileSize = SizeofResource(HINST_THISCOMPONENT, imageResHandle); hr = imageFileSize ? S_OK : E_FAIL; } if (SUCCEEDED(hr)) { hr = pIWICFactory->CreateStream(&pStream); #ifdef DEBUG_GPU_RESOURCE LOG(SEVERITY_LEVEL_INFO) << L"[GPU RESOURCE] IWICStream = [" << std::hex << pStream << L"]" << std::dec; #endif } if (SUCCEEDED(hr)) { hr = pStream->InitializeFromMemory(reinterpret_cast<BYTE *>(pImageFile), imageFileSize); } if (SUCCEEDED(hr)) { hr = pIWICFactory->CreateDecoderFromStream(pStream, nullptr, WICDecodeMetadataCacheOnLoad, &pDecoder); #ifdef DEBUG_GPU_RESOURCE LOG(SEVERITY_LEVEL_INFO) << L"[GPU RESOURCE] IWICBitmapDecoder = [" << std::hex << pDecoder << L"]" << std::dec; #endif } if (SUCCEEDED(hr)) { hr = pDecoder->GetFrame(0, &pSource); } if (SUCCEEDED(hr)) { hr = pIWICFactory->CreateFormatConverter(&pConverter); #ifdef DEBUG_GPU_RESOURCE LOG(SEVERITY_LEVEL_INFO) << L"[GPU RESOURCE] IWICFormatConverter = [" << std::hex << pConverter << L"]" << std::dec; #endif } if (SUCCEEDED(hr)) { if (destinationWidth != 0 || destinationHeight != 0) { UINT originalWidth, originalHeight; hr = pSource->GetSize(&originalWidth, &originalHeight); if (SUCCEEDED(hr)) { if (destinationWidth == 0) { FLOAT scalar = static_cast<FLOAT>(destinationHeight) / static_cast<FLOAT>(originalHeight); destinationWidth = static_cast<UINT>(scalar * static_cast<FLOAT>(originalWidth)); } else if (destinationHeight == 0) { FLOAT scalar = static_cast<FLOAT>(destinationWidth) / static_cast<FLOAT>(originalWidth); destinationHeight = static_cast<UINT>(scalar * static_cast<FLOAT>(originalHeight)); } hr = pIWICFactory->CreateBitmapScaler(&pScaler); #ifdef DEBUG_GPU_RESOURCE LOG(SEVERITY_LEVEL_INFO) << L"[GPU RESOURCE] IWICBitmapScaler = [" << std::hex << pScaler << L"]" << std::dec; #endif if (SUCCEEDED(hr)) { hr = pScaler->Initialize(pSource, destinationWidth, destinationHeight, WICBitmapInterpolationModeCubic); if (SUCCEEDED(hr)) { hr = pConverter->Initialize(pScaler, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, nullptr, 0.f, WICBitmapPaletteTypeMedianCut); } } } } else { hr = pConverter->Initialize(pSource, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, nullptr, 0.f, WICBitmapPaletteTypeMedianCut); } } if (SUCCEEDED(hr)) { hr = pRenderTarget->CreateBitmapFromWicBitmap(pConverter, nullptr, ppBitmap); #ifdef DEBUG_OUTPUT_GPU_RESOURCE LOG(SEVERITY_LEVEL_INFO) << L"[GPU RESOURCE] ID2D1Bitmap = [" << std::hex << *ppBitmap << L"]" << std::dec; #endif } SafeRelease(&pDecoder); SafeRelease(&pSource); SafeRelease(&pStream); SafeRelease(&pConverter); SafeRelease(&pScaler); #ifdef TOUCHMIND_CONTEXT_DEBUG LOG_LEAVE_HRESULT(hr); #endif return hr; }
ID2D1Bitmap* d2d::CreateBitmapFromResource(int idPic, int destinationWidth, int destinationHeight) { // Locate the resource. HRSRC imageResHandle = FindResource(NULL, MAKEINTRESOURCE(idPic), L"PNG"); if (imageResHandle == nullptr) { return nullptr; } // Load the resource. HGLOBAL imageResDataHandle = LoadResource(NULL, imageResHandle); //If hModule is NULL, the system loads the resource from the module that was used to create the current process HRESULT hr = imageResDataHandle ? S_OK : E_FAIL; if (FAILED(hr)) { return nullptr; } // Lock it to get a system memory pointer. void* pImageFile = LockResource(imageResDataHandle); if (pImageFile == nullptr) { return nullptr; } // Calculate the size. DWORD imageFileSize = SizeofResource(NULL, imageResHandle); if (imageFileSize == 0) { return nullptr; } // Create a WIC stream to map onto the memory. IWICStream *pStream = nullptr; hr = m_pWICFactory->CreateStream(&pStream); if (FAILED(hr)) { return nullptr; } // Initialize the stream with the memory pointer and size. hr = pStream->InitializeFromMemory(reinterpret_cast<BYTE*>(pImageFile), imageFileSize); if (FAILED(hr)) { return nullptr; } // Create a decoder for the stream. IWICBitmapDecoder *pDecoder = nullptr; hr = m_pWICFactory->CreateDecoderFromStream(pStream, NULL, WICDecodeMetadataCacheOnLoad, &pDecoder); if (FAILED(hr)) { return nullptr; } // Create the initial frame. IWICBitmapFrameDecode *pSource = nullptr; hr = pDecoder->GetFrame(0, &pSource); if (FAILED(hr)) { return nullptr; } // Convert the image format to 32bppPBGRA // (DXGI_FORMAT_B8G8R8A8_UNORM + D2D1_ALPHA_MODE_PREMULTIPLIED). IWICFormatConverter *pConverter = NULL; hr = m_pWICFactory->CreateFormatConverter(&pConverter); if (FAILED(hr)) { return nullptr; } // If a new width or height was specified, create an // IWICBitmapScaler and use it to resize the image. if (destinationWidth != 0 || destinationHeight != 0) { UINT originalWidth, originalHeight; hr = pSource->GetSize(&originalWidth, &originalHeight); if (SUCCEEDED(hr)) { if (destinationWidth == 0) { FLOAT scalar = static_cast<FLOAT>(destinationHeight) / static_cast<FLOAT>(originalHeight); destinationWidth = static_cast<UINT>(scalar * static_cast<FLOAT>(originalWidth)); } else if (destinationHeight == 0) { FLOAT scalar = static_cast<FLOAT>(destinationWidth) / static_cast<FLOAT>(originalWidth); destinationHeight = static_cast<UINT>(scalar * static_cast<FLOAT>(originalHeight)); } IWICBitmapScaler *pScaler = nullptr; hr = m_pWICFactory->CreateBitmapScaler(&pScaler); if (SUCCEEDED(hr)) { hr = pScaler->Initialize(pSource,destinationWidth,destinationHeight,WICBitmapInterpolationModeCubic); if (SUCCEEDED(hr)) { hr = pConverter->Initialize(pScaler,GUID_WICPixelFormat32bppPBGRA,WICBitmapDitherTypeNone,NULL,0.f,WICBitmapPaletteTypeMedianCut); } } SafeRelease(pScaler); } } else { hr = pConverter->Initialize(pSource, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, NULL, 0.f, WICBitmapPaletteTypeMedianCut); } if (FAILED(hr)) { return nullptr; } //create a Direct2D bitmap from the WIC bitmap. ID2D1Bitmap* resBitmap = nullptr; hr = m_pRenderTarget->CreateBitmapFromWicBitmap(pConverter, NULL, &resBitmap); if (FAILED(hr) || resBitmap == nullptr) { return nullptr; } SafeRelease(pDecoder); SafeRelease(pSource); SafeRelease(pStream); SafeRelease(pConverter); pokerlog << "CreateBitmapFromResource " << idPic << " OK." << endl; return resBitmap; }
HRESULT LoadResourceBitmap( ID2D1RenderTarget* pRendertarget, IWICImagingFactory* pIWICFactory, PCWSTR resourceName, PCWSTR resourceType, UINT destinationWidth, UINT destinationHeight, ID2D1Bitmap** ppBitmap ) { HRESULT hr = S_OK; IWICBitmapDecoder* pDecoder = NULL; IWICBitmapFrameDecode* pSource = NULL; IWICStream* pStream = NULL; IWICFormatConverter* pConverter = NULL; IWICBitmapScaler* pScaler = NULL; HRSRC imageResHandle = NULL; HGLOBAL imageResDataHandle = NULL; void* pImageFile = NULL; DWORD imageFileSize = 0; // Find the resource then load it imageResHandle = FindResource(HINST_THISCOMPONENT, resourceName, resourceType); hr = imageResHandle ? S_OK : E_FAIL; if (SUCCEEDED(hr)) { imageResDataHandle = LoadResource(HINST_THISCOMPONENT, imageResHandle); hr = imageResDataHandle ? S_OK : E_FAIL; } // Lock the resource and calculate the image's size if (SUCCEEDED(hr)) { // Lock it to get the system memory pointer pImageFile = LockResource(imageResDataHandle); hr = pImageFile ? S_OK : E_FAIL; } if (SUCCEEDED(hr)) { // Calculate the size imageFileSize = SizeofResource(HINST_THISCOMPONENT, imageResHandle); hr = imageFileSize ? S_OK : E_FAIL; } // Create an IWICStream object if (SUCCEEDED(hr)) { // Create a WIC stream to map onto the memory hr = pIWICFactory->CreateStream(&pStream); } if (SUCCEEDED(hr)) { // Initialize the stream with the memory pointer and size hr = pStream->InitializeFromMemory( reinterpret_cast<BYTE*>(pImageFile), imageFileSize ); } // Create IWICBitmapDecoder if (SUCCEEDED(hr)) { // Create a decoder for the stream hr = pIWICFactory->CreateDecoderFromStream( pStream, NULL, WICDecodeMetadataCacheOnLoad, &pDecoder ); } // Retrieve a frame from the image and store it in an IWICBitmapFrameDecode object if (SUCCEEDED(hr)) { // Create the initial frame hr = pDecoder->GetFrame(0, &pSource); } // Before Direct2D can use the image, it must be converted to the 32bppPBGRA pixel format. // To convert the image format, use the IWICImagingFactory::CreateFormatConverter method to create an IWICFormatConverter object, then use the IWICFormatConverter object's Initialize method to perform the conversion. if (SUCCEEDED(hr)) { // Convert the image format to 32bppPBGRA // (DXGI_FORMAT_B8G8R8A8_UNORM + D2D1_ALPHA_MODE_PREMULTIPLIED). hr = pIWICFactory->CreateFormatConverter(&pConverter); } if (SUCCEEDED(hr)) { // If a new width or height was specified, create and // IWICBitmapScaler and use it to resize the image. if (destinationWidth != 0 || destinationHeight != 0) { UINT originalWidth; UINT originalHeight; hr = pSource->GetSize(&originalWidth, &originalHeight); if (SUCCEEDED(hr)) { if (destinationWidth == 0) { FLOAT scalar = static_cast<FLOAT>(destinationHeight) / static_cast<FLOAT>(originalHeight); destinationWidth = static_cast<UINT>(scalar * static_cast<FLOAT>(originalWidth)); } else if (destinationHeight == 0) { FLOAT scalar = static_cast<FLOAT>(destinationWidth) / static_cast<FLOAT>(originalWidth); destinationHeight = static_cast<UINT>(scalar * static_cast<FLOAT>(originalHeight)); } hr = pIWICFactory->CreateBitmapScaler(&pScaler); if (SUCCEEDED(hr)) { hr = pScaler->Initialize( pSource, destinationWidth, destinationHeight, WICBitmapInterpolationModeCubic ); if (SUCCEEDED(hr)) { hr = pConverter->Initialize( pScaler, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, NULL, 0.f, WICBitmapPaletteTypeMedianCut ); } } } } else // use default width and height { hr = pConverter->Initialize( pSource, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, NULL, 0.f, WICBitmapPaletteTypeMedianCut ); } } // Finally, Create an ID2D1Bitmap object, that can be drawn by a render target and used with other Direct2D objects if (SUCCEEDED(hr)) { // Create a Direct2D bitmap from the WIC bitmap hr = pRendertarget->CreateBitmapFromWicBitmap( pConverter, NULL, ppBitmap ); } SAFE_RELEASE(pDecoder); SAFE_RELEASE(pSource); SAFE_RELEASE(pStream); SAFE_RELEASE(pConverter); SAFE_RELEASE(pScaler); return hr; }
//--------------------------------------------------------------------------------- static HRESULT CreateTextureFromWIC( _In_ ID3D11Device* d3dDevice, _In_opt_ ID3D11DeviceContext* d3dContext, _In_ IWICBitmapFrameDecode *frame, _In_ size_t maxsize, _In_ D3D11_USAGE usage, _In_ unsigned int bindFlags, _In_ unsigned int cpuAccessFlags, _In_ unsigned int miscFlags, _In_ bool forceSRGB, _Out_opt_ ID3D11Resource** texture, _Out_opt_ ID3D11ShaderResourceView** textureView ) { UINT width, height; HRESULT hr = frame->GetSize( &width, &height ); if ( FAILED(hr) ) return hr; assert( width > 0 && height > 0 ); if ( !maxsize ) { // This is a bit conservative because the hardware could support larger textures than // the Feature Level defined minimums, but doing it this way is much easier and more // performant for WIC than the 'fail and retry' model used by DDSTextureLoader switch( d3dDevice->GetFeatureLevel() ) { case D3D_FEATURE_LEVEL_9_1: case D3D_FEATURE_LEVEL_9_2: maxsize = 2048 /*D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION*/; break; case D3D_FEATURE_LEVEL_9_3: maxsize = 4096 /*D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION*/; break; case D3D_FEATURE_LEVEL_10_0: case D3D_FEATURE_LEVEL_10_1: maxsize = 8192 /*D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION*/; break; default: maxsize = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; break; } } assert( maxsize > 0 ); UINT twidth, theight; if ( width > maxsize || height > maxsize ) { float ar = static_cast<float>(height) / static_cast<float>(width); if ( width > height ) { twidth = static_cast<UINT>( maxsize ); theight = static_cast<UINT>( static_cast<float>(maxsize) * ar ); } else { theight = static_cast<UINT>( maxsize ); twidth = static_cast<UINT>( static_cast<float>(maxsize) / ar ); } assert( twidth <= maxsize && theight <= maxsize ); } else { twidth = width; theight = height; } // Determine format WICPixelFormatGUID pixelFormat; hr = frame->GetPixelFormat( &pixelFormat ); if ( FAILED(hr) ) return hr; WICPixelFormatGUID convertGUID; memcpy( &convertGUID, &pixelFormat, sizeof(WICPixelFormatGUID) ); size_t bpp = 0; DXGI_FORMAT format = _WICToDXGI( pixelFormat ); if ( format == DXGI_FORMAT_UNKNOWN ) { if ( memcmp( &GUID_WICPixelFormat96bppRGBFixedPoint, &pixelFormat, sizeof(WICPixelFormatGUID) ) == 0 ) { #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE) if ( g_WIC2 ) { memcpy( &convertGUID, &GUID_WICPixelFormat96bppRGBFloat, sizeof(WICPixelFormatGUID) ); format = DXGI_FORMAT_R32G32B32_FLOAT; } else #endif { memcpy( &convertGUID, &GUID_WICPixelFormat128bppRGBAFloat, sizeof(WICPixelFormatGUID) ); format = DXGI_FORMAT_R32G32B32A32_FLOAT; } } else { for( size_t i=0; i < _countof(g_WICConvert); ++i ) { if ( memcmp( &g_WICConvert[i].source, &pixelFormat, sizeof(WICPixelFormatGUID) ) == 0 ) { memcpy( &convertGUID, &g_WICConvert[i].target, sizeof(WICPixelFormatGUID) ); format = _WICToDXGI( g_WICConvert[i].target ); assert( format != DXGI_FORMAT_UNKNOWN ); bpp = _WICBitsPerPixel( convertGUID ); break; } } } if ( format == DXGI_FORMAT_UNKNOWN ) return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); } else { bpp = _WICBitsPerPixel( pixelFormat ); } #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE) if ( (format == DXGI_FORMAT_R32G32B32_FLOAT) && d3dContext != 0 && textureView != 0 ) { // Special case test for optional device support for autogen mipchains for R32G32B32_FLOAT UINT fmtSupport = 0; hr = d3dDevice->CheckFormatSupport( DXGI_FORMAT_R32G32B32_FLOAT, &fmtSupport ); if ( FAILED(hr) || !( fmtSupport & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN ) ) { // Use R32G32B32A32_FLOAT instead which is required for Feature Level 10.0 and up memcpy( &convertGUID, &GUID_WICPixelFormat128bppRGBAFloat, sizeof(WICPixelFormatGUID) ); format = DXGI_FORMAT_R32G32B32A32_FLOAT; bpp = 128; } } #endif if ( !bpp ) return E_FAIL; // Handle sRGB formats if ( forceSRGB ) { format = MakeSRGB( format ); } else { IWICMetadataQueryReader* metareader; if ( SUCCEEDED( frame->GetMetadataQueryReader( &metareader ) ) ) { GUID containerFormat; if ( SUCCEEDED( metareader->GetContainerFormat( &containerFormat ) ) ) { // Check for sRGB colorspace metadata bool sRGB = false; PROPVARIANT value; PropVariantInit( &value ); if ( memcmp( &containerFormat, &GUID_ContainerFormatPng, sizeof(GUID) ) == 0 ) { // Check for sRGB chunk if ( SUCCEEDED( metareader->GetMetadataByName( L"/sRGB/RenderingIntent", &value ) ) && value.vt == VT_UI1 ) { sRGB = true; } } else if ( SUCCEEDED( metareader->GetMetadataByName( L"System.Image.ColorSpace", &value ) ) && value.vt == VT_UI2 && value.uiVal == 1 ) { sRGB = true; } PropVariantClear( &value ); if ( sRGB ) format = MakeSRGB( format ); } } } // Verify our target format is supported by the current device // (handles WDDM 1.0 or WDDM 1.1 device driver cases as well as DirectX 11.0 Runtime without 16bpp format support) UINT support = 0; hr = d3dDevice->CheckFormatSupport( format, &support ); if ( FAILED(hr) || !(support & D3D11_FORMAT_SUPPORT_TEXTURE2D) ) { // Fallback to RGBA 32-bit format which is supported by all devices memcpy( &convertGUID, &GUID_WICPixelFormat32bppRGBA, sizeof(WICPixelFormatGUID) ); format = DXGI_FORMAT_R8G8B8A8_UNORM; bpp = 32; } // Allocate temporary memory for image size_t rowPitch = ( twidth * bpp + 7 ) / 8; size_t imageSize = rowPitch * theight; std::unique_ptr<uint8_t[]> temp( new (std::nothrow) uint8_t[ imageSize ] ); if (!temp) return E_OUTOFMEMORY; // Load image data if ( memcmp( &convertGUID, &pixelFormat, sizeof(GUID) ) == 0 && twidth == width && theight == height ) { // No format conversion or resize needed hr = frame->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() ); if ( FAILED(hr) ) return hr; } else if ( twidth != width || theight != height ) { // Resize IWICImagingFactory* pWIC = _GetWIC(); if ( !pWIC ) return E_NOINTERFACE; IWICBitmapScaler* scaler; hr = pWIC->CreateBitmapScaler( &scaler ); if ( FAILED(hr) ) return hr; hr = scaler->Initialize( frame, twidth, theight, WICBitmapInterpolationModeFant ); if ( FAILED(hr) ) return hr; WICPixelFormatGUID pfScaler; hr = scaler->GetPixelFormat( &pfScaler ); if ( FAILED(hr) ) return hr; if ( memcmp( &convertGUID, &pfScaler, sizeof(GUID) ) == 0 ) { // No format conversion needed hr = scaler->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() ); if ( FAILED(hr) ) return hr; } else { IWICFormatConverter* FC; hr = pWIC->CreateFormatConverter( &FC ); if ( FAILED(hr) ) return hr; hr = FC->Initialize( scaler, convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom ); if ( FAILED(hr) ) return hr; hr = FC->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() ); if ( FAILED(hr) ) return hr; } } else { // Format conversion but no resize IWICImagingFactory* pWIC = _GetWIC(); if ( !pWIC ) return E_NOINTERFACE; IWICFormatConverter* FC; hr = pWIC->CreateFormatConverter( &FC ); if ( FAILED(hr) ) return hr; hr = FC->Initialize( frame, convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom ); if ( FAILED(hr) ) return hr; hr = FC->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() ); if ( FAILED(hr) ) return hr; } // See if format is supported for auto-gen mipmaps (varies by feature level) bool autogen = false; if ( d3dContext != 0 && textureView != 0 ) // Must have context and shader-view to auto generate mipmaps { UINT fmtSupport = 0; hr = d3dDevice->CheckFormatSupport( format, &fmtSupport ); if ( SUCCEEDED(hr) && ( fmtSupport & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN ) ) { autogen = true; } } // Create texture D3D11_TEXTURE2D_DESC desc; desc.Width = twidth; desc.Height = theight; desc.MipLevels = (autogen) ? 0 : 1; desc.ArraySize = 1; desc.Format = format; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Usage = usage; desc.CPUAccessFlags = cpuAccessFlags; if ( autogen ) { desc.BindFlags = bindFlags | D3D11_BIND_RENDER_TARGET; desc.MiscFlags = miscFlags | D3D11_RESOURCE_MISC_GENERATE_MIPS; } else { desc.BindFlags = bindFlags; desc.MiscFlags = miscFlags; } D3D11_SUBRESOURCE_DATA initData; initData.pSysMem = temp.get(); initData.SysMemPitch = static_cast<UINT>( rowPitch ); initData.SysMemSlicePitch = static_cast<UINT>( imageSize ); ID3D11Texture2D* tex = nullptr; hr = d3dDevice->CreateTexture2D( &desc, (autogen) ? nullptr : &initData, &tex ); if ( SUCCEEDED(hr) && tex != 0 ) { if (textureView != 0) { D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; memset( &SRVDesc, 0, sizeof( SRVDesc ) ); SRVDesc.Format = desc.Format; SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; SRVDesc.Texture2D.MipLevels = (autogen) ? -1 : 1; hr = d3dDevice->CreateShaderResourceView( tex, &SRVDesc, textureView ); if ( FAILED(hr) ) { tex->Release(); return hr; } if ( autogen ) { assert( d3dContext != 0 ); d3dContext->UpdateSubresource( tex, 0, nullptr, temp.get(), static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize) ); d3dContext->GenerateMips( *textureView ); } } if (texture != 0) { *texture = tex; } else { SetDebugObjectName(tex, "WICTextureLoader"); tex->Release(); } } return hr; }
// 从文件读取位图 HRESULT ImageRenderer::LoadBitmapFromFile( ID2D1DeviceContext *pRenderTarget, IWICImagingFactory2 *pIWICFactory, PCWSTR uri, UINT width, UINT height, ID2D1Bitmap1 **ppBitmap ){ IWICBitmapDecoder *pDecoder = nullptr; IWICBitmapFrameDecode *pSource = nullptr; IWICStream *pStream = nullptr; IWICFormatConverter *pConverter = nullptr; IWICBitmapScaler *pScaler = nullptr; HRESULT hr = pIWICFactory->CreateDecoderFromFilename( uri, nullptr, GENERIC_READ, WICDecodeMetadataCacheOnLoad, &pDecoder ); if (SUCCEEDED(hr)) { hr = pDecoder->GetFrame(0, &pSource); } if (SUCCEEDED(hr)) { hr = pIWICFactory->CreateFormatConverter(&pConverter); } if (SUCCEEDED(hr)) { if (width != 0 || height != 0) { UINT originalWidth, originalHeight; hr = pSource->GetSize(&originalWidth, &originalHeight); if (SUCCEEDED(hr)) { if (width == 0) { FLOAT scalar = static_cast<FLOAT>(height) / static_cast<FLOAT>(originalHeight); width = static_cast<UINT>(scalar * static_cast<FLOAT>(originalWidth)); } else if (height == 0) { FLOAT scalar = static_cast<FLOAT>(width) / static_cast<FLOAT>(originalWidth); height = static_cast<UINT>(scalar * static_cast<FLOAT>(originalHeight)); } hr = pIWICFactory->CreateBitmapScaler(&pScaler); if (SUCCEEDED(hr)) { hr = pScaler->Initialize( pSource, width, height, WICBitmapInterpolationModeCubic ); } if (SUCCEEDED(hr)) { hr = pConverter->Initialize( pScaler, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, nullptr, 0.f, WICBitmapPaletteTypeMedianCut ); } } } else { hr = pConverter->Initialize( pSource, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, nullptr, 0.f, WICBitmapPaletteTypeMedianCut ); } } if (SUCCEEDED(hr)) { hr = pRenderTarget->CreateBitmapFromWicBitmap( pConverter, nullptr, ppBitmap ); } ::SafeRelease(pDecoder); ::SafeRelease(pSource); ::SafeRelease(pStream); ::SafeRelease(pConverter); ::SafeRelease(pScaler); return hr; }