How to correctly call IWICImagingFactory::CreateBitmapFromHBITMAP?

MuYu 41 Reputation points
2023-09-14T08:01:24.4966667+00:00

I tried to call it like this, By writing WIC Bitmap to a file, I found that it is black and does not have the image in my wic_bitmap

I am certain that h_bitmap is valid, I have displayed it on the screen before。

All code can access by AcrylicCompositor

help……thank you very much.

        HBITMAP                     h_bitmap = this->CreateDesktopBitmap();
        ComPtr<IWICImagingFactory>  wic_factory;
        ComPtr<IWICBitmap>          wic_bitmap;
        ComPtr<IWICFormatConverter> wic_format_converter;
        CoInitialize(NULL);
        TRY_HRESULT(CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&wic_factory)));
        TRY_HRESULT(wic_factory->CreateBitmapFromHBITMAP(h_bitmap, NULL, WICBitmapUsePremultipliedAlpha, &wic_bitmap));
        DeleteObject(h_bitmap);
        TRY_HRESULT(wic_factory->CreateFormatConverter(&wic_format_converter));
        TRY_HRESULT(wic_format_converter->Initialize(wic_bitmap.Get(), GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, NULL, 0.f, WICBitmapPaletteTypeCustom));

        ComPtr<IWICBitmapEncoder>  wic_bitmap_encoder;
        ComPtr<IWICBitmapFrameEncode> wic_bitmap_frame_encode;
        ComPtr<IPropertyBag2>       property_bag;
        ComPtr<IWICStream>          wic_stream;
        ComPtr<IStream>             stream;
        TRY_HRESULT(wic_factory->CreateStream(&wic_stream));
        TRY_HRESULT(wic_stream->InitializeFromFilename(L"test.png", GENERIC_WRITE));
        TRY_HRESULT(wic_factory->CreateEncoder(GUID_ContainerFormatPng, NULL, &wic_bitmap_encoder));
        TRY_HRESULT(wic_bitmap_encoder->Initialize(wic_stream.Get(), WICBitmapEncoderNoCache));
        TRY_HRESULT(wic_bitmap_encoder->CreateNewFrame(&wic_bitmap_frame_encode, &property_bag));
        TRY_HRESULT(wic_bitmap_frame_encode->Initialize(property_bag.Get()));
        TRY_HRESULT(wic_bitmap_frame_encode->SetSize(this->rc_desktop.right, this->rc_desktop.bottom));
        WICPixelFormatGUID format = GUID_WICPixelFormat32bppPBGRA;
        TRY_HRESULT(wic_bitmap_frame_encode->SetPixelFormat(&format));
        TRY_HRESULT(wic_bitmap_frame_encode->WriteSource(wic_bitmap.Get(), NULL));
        TRY_HRESULT(wic_bitmap_frame_encode->Commit());
        TRY_HRESULT(wic_bitmap_encoder->Commit());
Windows 10
Windows 10
A Microsoft operating system that runs on personal computers and tablets.
11,614 questions
Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,625 questions
C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,736 questions
{count} votes

Accepted answer
  1. Castorix31 85,366 Reputation points
    2023-09-15T07:28:34.4666667+00:00

    This test capturing the Desktop as HBITMAP and saving it as PNG with WIC works for me (Windows 10 22H2) :

    (all the if (SUCCEEDED(hr)) have to be replaced by your TRY_HRESULT()...)

    IWICImagingFactory* m_pImagingFactory = NULL;
    
    HRESULT hrInit = CoInitialize(NULL);				
    HRESULT hr = CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&m_pImagingFactory));
    if (SUCCEEDED(hr))
    {
    				HDC hDC = GetDC(NULL);
    				HDC hDCMem = CreateCompatibleDC(hDC);
    				int nImageWidth = GetSystemMetrics(SM_CXSCREEN);
    				int nImageHeight = GetSystemMetrics(SM_CYSCREEN);
    				HBITMAP hBitmap = CreateCompatibleBitmap(hDC, nImageWidth, nImageHeight);
    				HBITMAP hBitmapOld = (HBITMAP)SelectObject(hDCMem, hBitmap);
    				BitBlt(hDCMem, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), hDC, 0, 0, SRCCOPY);
    
    				IWICBitmap* pWICBitmap;
    				hr = m_pImagingFactory->CreateBitmapFromHBITMAP(hBitmap, NULL, WICBitmapUseAlpha, &pWICBitmap);
    				if (SUCCEEDED(hr))
    				{
    					IWICBitmapEncoder* pEncoder;
    					hr = m_pImagingFactory->CreateEncoder(GUID_ContainerFormatPng, NULL, &pEncoder);
    					if (SUCCEEDED(hr))
    					{
    						IWICStream* spStream = NULL;
    						hr = m_pImagingFactory->CreateStream(&spStream);
    						if (SUCCEEDED(hr))
    						{
    							hr = spStream->InitializeFromFilename(L"capture.png", GENERIC_WRITE);
    						}
    						if (SUCCEEDED(hr))
    						{
    							hr = pEncoder->Initialize(spStream, WICBitmapEncoderNoCache);
    							IWICBitmapFrameEncode* spFrame = NULL;
    							if (SUCCEEDED(hr))
    							{
    								hr = pEncoder->CreateNewFrame(&spFrame, NULL);
    								if (SUCCEEDED(hr))
    								{
    									hr = spFrame->Initialize(NULL);
    									if (SUCCEEDED(hr))
    									{
    										hr = spFrame->SetSize(nImageWidth, nImageHeight);
    										WICPixelFormatGUID format;
    										pWICBitmap->GetPixelFormat(&format);
    										if (SUCCEEDED(hr))
    										{
    											hr = spFrame->SetPixelFormat(&format);
    											if (SUCCEEDED(hr))
    											{
    												hr = spFrame->WriteSource(pWICBitmap, NULL);
    												if (SUCCEEDED(hr))
    												{
    													hr = spFrame->Commit();
    													if (SUCCEEDED(hr))
    													{
    														hr = pEncoder->Commit();
    													}
    												}
    											}
    										}
    									}
    								}
    							}
    						}
    					}
    				}
    
    				SelectObject(hDCMem, hBitmapOld);
    				DeleteObject(hDCMem);
    				DeleteObject(hBitmap);
    				ReleaseDC(NULL, hDC);					
    }
    
    2 people found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.