How to make a bitmap with alpha using TransparentBlt

T B 66 Reputation points
2021-11-26T21:16:05.56+00:00

I have the following code. I am trying to get the program images and convert them to RGBA.

 HDC hdc = GetDC(hwnd);
        HDC hdc1 = CreateCompatibleDC(hdc);
        HBITMAP hBitmap = CreateCompatibleBitmap(hdc, rect.right - rect.left, rect.bottom - rect.top);
        HBITMAP hBmpOld = (HBITMAP)SelectObject(hdc, hBitmap);
        SelectObject ( hdc, hBitmap );
        TransparentBlt(hdc, 0, 0, rect.right - rect.left, rect.bottom - rect.top, hdc1, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, 0x00000000);
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,422 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,527 questions
0 comments No comments
{count} votes

Accepted answer
  1. Castorix31 81,726 Reputation points
    2021-11-27T18:00:08.853+00:00

    A test with AlphaBlend by using some MS WIC utility functions =>

    153054-alphablend-test.jpg

    #include <windows.h>  
    #include <tchar.h>  
      
    #pragma comment (lib, "Msimg32") // AlphaBlend  
      
    #include <Urlmon.h> // URLDownloadToCacheFile  
    #pragma comment (lib, "Urlmon")  
      
    #include <shlwapi.h> // SHCreateStreamOnFile  
    #pragma comment (lib, "Shlwapi")  
      
    #include <Wincodec.h> // IWICBitmapSource  
    #pragma comment (lib, "windowscodecs")  
      
    #include <thumbcache.h> // WTS_ALPHATYPE  
      
    #pragma comment(linker,"\"/manifestdependency:type='win32' \  
    name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \  
    processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")  
      
    HINSTANCE hInst;  
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);  
    int nWidth = 520, nHeight = 400;  
    #define IDC_BUTTON 10  
      
    HRESULT WICCreate32BitsPerPixelHBITMAP(IStream* pstm, UINT /* cx */, HBITMAP* phbmp, WTS_ALPHATYPE* pdwAlpha);  
      
    int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow)  
    {  
    	CoInitialize(NULL);  
    	hInst = hInstance;  
    	WNDCLASSEX wcex =  
    	{  
    		sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW, WndProc, 0, 0, hInst, LoadIcon(NULL, IDI_APPLICATION),  
    		LoadCursor(NULL, IDC_ARROW), (HBRUSH)(COLOR_WINDOW + 1), NULL, TEXT("WindowClass"), NULL,  
    	};  
    	if (!RegisterClassEx(&wcex))  
    		return MessageBox(NULL, TEXT("Cannot register class !"), TEXT("Error"), MB_ICONERROR | MB_OK);  
    	int nX = (GetSystemMetrics(SM_CXSCREEN) - nWidth) / 2, nY = (GetSystemMetrics(SM_CYSCREEN) - nHeight) / 2;  
    	HWND hWnd = CreateWindowEx(0, wcex.lpszClassName, TEXT("Test"), WS_OVERLAPPEDWINDOW, nX, nY, nWidth, nHeight, NULL, NULL, hInst, NULL);  
    	if (!hWnd)  
    		return MessageBox(NULL, TEXT("Cannot create window !"), TEXT("Error"), MB_ICONERROR | MB_OK);  
    	ShowWindow(hWnd, SW_SHOWNORMAL);  
    	UpdateWindow(hWnd);  
    	MSG msg;  
    	while (GetMessage(&msg, NULL, 0, 0))  
    	{  
    		TranslateMessage(&msg);  
    		DispatchMessage(&msg);  
    	}  
    	CoUninitialize();  
    	return (int)msg.wParam;  
    }  
      
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)  
    {  
    	static HWND hWndButton = NULL;  
    	static HBITMAP hBitmap = NULL, hBitmapBackground = NULL;  
    	static BITMAP bm;  
    	static double i = 0;  
      
    	int wmId, wmEvent;  
    	switch (message)  
    	{  
    	case WM_CREATE:  
    	{  
    		hWndButton = CreateWindowEx(0, L"Button", L"Click", WS_CHILD | WS_VISIBLE | BS_PUSHLIKE, 220, 60, 60, 32, hWnd, (HMENU)IDC_BUTTON, hInst, NULL);  
      
    		WCHAR wszURL[MAX_PATH] = L"https://i.ibb.co/DG7XSsB/Butterfly.png";  
    		WCHAR wszFilename[MAX_PATH];  
    		HRESULT hr = URLDownloadToCacheFile(NULL, wszURL, wszFilename, ARRAYSIZE(wszFilename), 0x0, NULL);  
    		if (SUCCEEDED(hr))  
    		{  
    			IStream* pstm = NULL;  
    			hr = SHCreateStreamOnFile(wszFilename, STGM_READ | STGM_SHARE_DENY_WRITE, &pstm);  
    			if (SUCCEEDED(hr))  
    			{  
    				WTS_ALPHATYPE alphatype;  
    				WICCreate32BitsPerPixelHBITMAP(pstm, NULL, &hBitmap, &alphatype);  
    				GetObject(hBitmap, sizeof(BITMAP), &bm);  
    				pstm->Release();  
    			}			  
    		}  
    		lstrcpy(wszURL, L"https://i.ibb.co/L5rryfx/Beautiful-nature-with-white-cloud-on-blue-sky-background.jpg");		  
    		hr = URLDownloadToCacheFile(NULL, wszURL, wszFilename, ARRAYSIZE(wszFilename), 0x0, NULL);  
    		if (SUCCEEDED(hr))  
    		{  
    			IStream* pstm = NULL;  
    			hr = SHCreateStreamOnFile(wszFilename, STGM_READ | STGM_SHARE_DENY_WRITE, &pstm);  
    			if (SUCCEEDED(hr))  
    			{  
    				WTS_ALPHATYPE alphatype;  
    				WICCreate32BitsPerPixelHBITMAP(pstm, NULL, &hBitmapBackground, &alphatype);  
    				pstm->Release();  
    			}  
    		}  
    		return 0;  
    	}  
    	break;  
    	case WM_COMMAND:  
    	{  
    		wmId = LOWORD(wParam);  
    		wmEvent = HIWORD(wParam);  
    		switch (wmId)  
    		{  
    		case IDC_BUTTON:  
    		{  
    			if (wmEvent == BN_CLICKED)  
    			{	  
    				SetTimer(hWnd, 1, 10, NULL);			  
    			}  
    		}  
    		break;  
    		default:  
    			return DefWindowProc(hWnd, message, wParam, lParam);  
    		}  
    	}  
    	break;  
    	case WM_TIMER:  
    	{  
    		HDC hDC = GetDC(hWnd);  
    		HDC hDCMem = CreateCompatibleDC(hDC);  
    		HBITMAP hBitmapOld = (HBITMAP)SelectObject(hDCMem, hBitmap);  
    		BLENDFUNCTION bf = { AC_SRC_OVER, 0, i, AC_SRC_ALPHA };  
    		AlphaBlend(hDC, 0, 0, bm.bmWidth, bm.bmHeight, hDCMem, 0, 0, bm.bmWidth, bm.bmHeight, bf);  
    		i+=0.02;  
    		if (i >= 255 * 0.02)  
    		{  
    			KillTimer(hWnd, 1);  
    			i = 0;  
    			InvalidateRect(hWnd, NULL, TRUE);  
    		}  
    		SelectObject(hDCMem, hBitmapOld);  
    		DeleteObject(hDCMem);  
    		ReleaseDC(hWnd, hDC);  
    	}  
    	break;  
    	case WM_PAINT:  
    	{  
    		PAINTSTRUCT ps;  
    		BITMAP bmBackground;  
    		BeginPaint(hWnd, &ps);  
    		HDC hMemDC = CreateCompatibleDC(ps.hdc);  
    		HBITMAP hBitmapOld = (HBITMAP)SelectObject(hMemDC, hBitmapBackground);  
    		GetObject(hBitmapBackground, sizeof(BITMAP), &bmBackground);  
    		RECT rect;  
    		GetClientRect(hWnd, &rect);  
    		SetStretchBltMode(ps.hdc, COLORONCOLOR);  
    		StretchBlt(ps.hdc, 0, 0, rect.right, rect.bottom, hMemDC, 0, 0, bmBackground.bmWidth, bmBackground.bmHeight, SRCCOPY);  
    		SelectObject(hMemDC, hBitmapOld);  
    		DeleteDC(hMemDC);  
    		EndPaint(hWnd, &ps);  
    	}  
    	break;  
    	case WM_DESTROY:  
    	{  
    		PostQuitMessage(0);  
    		return 0;  
    	}  
    	break;  
    	default:  
    		return DefWindowProc(hWnd, message, wParam, lParam);  
    	}  
    	return 0;  
    }  
      
    // From MS SDK  RecipeThumbnailProvider.cpp  
      
    HRESULT ConvertBitmapSourceTo32BPPHBITMAP(IWICBitmapSource* pBitmapSource, IWICImagingFactory* pImagingFactory, HBITMAP* phbmp)  
    {  
    	*phbmp = NULL;  
      
    	IWICBitmapSource* pBitmapSourceConverted = NULL;  
    	WICPixelFormatGUID guidPixelFormatSource;  
    	HRESULT hr = pBitmapSource->GetPixelFormat(&guidPixelFormatSource);  
    	if (SUCCEEDED(hr) && (guidPixelFormatSource != GUID_WICPixelFormat32bppBGRA))  
    	{  
    		IWICFormatConverter* pFormatConverter;  
    		hr = pImagingFactory->CreateFormatConverter(&pFormatConverter);  
    		if (SUCCEEDED(hr))  
    		{  
    			// Create the appropriate pixel format converter  
    			hr = pFormatConverter->Initialize(pBitmapSource, GUID_WICPixelFormat32bppBGRA, WICBitmapDitherTypeNone, NULL, 0, WICBitmapPaletteTypeCustom);  
    			if (SUCCEEDED(hr))  
    			{  
    				hr = pFormatConverter->QueryInterface(&pBitmapSourceConverted);  
    			}  
    			pFormatConverter->Release();  
    		}  
    	}  
    	else  
    	{  
    		hr = pBitmapSource->QueryInterface(&pBitmapSourceConverted);  // No conversion necessary  
    	}  
      
    	if (SUCCEEDED(hr))  
    	{  
    		UINT nWidth, nHeight;  
    		hr = pBitmapSourceConverted->GetSize(&nWidth, &nHeight);  
    		if (SUCCEEDED(hr))  
    		{  
    			BITMAPINFO bmi = {};  
    			bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);  
    			bmi.bmiHeader.biWidth = nWidth;  
    			bmi.bmiHeader.biHeight = -static_cast<LONG>(nHeight);  
    			bmi.bmiHeader.biPlanes = 1;  
    			bmi.bmiHeader.biBitCount = 32;  
    			bmi.bmiHeader.biCompression = BI_RGB;  
      
    			BYTE* pBits;  
    			HBITMAP hbmp = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, reinterpret_cast<void**>(&pBits), NULL, 0);  
    			hr = hbmp ? S_OK : E_OUTOFMEMORY;  
    			if (SUCCEEDED(hr))  
    			{  
    				WICRect rect = { 0, 0, nWidth, nHeight };  
      
    				// Convert the pixels and store them in the HBITMAP.  Note: the name of the function is a little  
    				// misleading - we're not doing any extraneous copying here.  CopyPixels is actually converting the  
    				// image into the given buffer.  
    				hr = pBitmapSourceConverted->CopyPixels(&rect, nWidth * 4, nWidth * nHeight * 4, pBits);  
    				if (SUCCEEDED(hr))  
    				{  
    					*phbmp = hbmp;  
    				}  
    				else  
    				{  
    					DeleteObject(hbmp);  
    				}  
    			}  
    		}  
    		pBitmapSourceConverted->Release();  
    	}  
    	return hr;  
    }  
      
    HRESULT WICCreate32BitsPerPixelHBITMAP(IStream* pstm, UINT /* cx */, HBITMAP* phbmp, WTS_ALPHATYPE* pdwAlpha)  
    {  
    	*phbmp = NULL;  
      
    	IWICImagingFactory* pImagingFactory;  
    	HRESULT hr = CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pImagingFactory));  
    	if (SUCCEEDED(hr))  
    	{  
    		IWICBitmapDecoder* pDecoder;  
    		hr = pImagingFactory->CreateDecoderFromStream(pstm, &GUID_VendorMicrosoft, WICDecodeMetadataCacheOnDemand, &pDecoder);  
    		//hr = CoCreateInstance(CLSID_WICPngDecoder, NULL, CLSCTX_INPROC_SERVER, __uuidof(pDecoder), reinterpret_cast<void**>(&pDecoder));  
    		//hr = pDecoder->Initialize(pstm, WICDecodeMetadataCacheOnLoad);  
    		if (SUCCEEDED(hr))  
    		{  
    			IWICBitmapFrameDecode* pBitmapFrameDecode;  
    			hr = pDecoder->GetFrame(0, &pBitmapFrameDecode);  
    			if (SUCCEEDED(hr))  
    			{  
    				hr = ConvertBitmapSourceTo32BPPHBITMAP(pBitmapFrameDecode, pImagingFactory, phbmp);  
    				if (SUCCEEDED(hr))  
    				{  
    					*pdwAlpha = WTSAT_ARGB;  
    				}  
    				pBitmapFrameDecode->Release();  
    			}  
    			pDecoder->Release();  
    		}  
    		pImagingFactory->Release();  
    	}  
    	return hr;  
    }  
      
      
    
    2 people found this answer helpful.

1 additional answer

Sort by: Most helpful
  1. Castorix31 81,726 Reputation points
    2021-11-27T12:45:11.897+00:00

    With transparency, use AlphaBlend instead

    2 people found this answer helpful.