C++: how calculate alphablend?

Joaquim Miguel Jesus 1 Reputation point
2022-04-11T21:55:08.633+00:00

We have 2 array pointers pixels.
How combine, using math, the 2 pixels for get the alphablend? And the same for stretch?

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,754 questions
{count} votes

7 answers

Sort by: Most helpful
  1. Castorix31 85,701 Reputation points
    2022-04-15T08:59:13.967+00:00

    I did it with GDI + WIC, maybe it could be simplified with GDI+ or Direct2D (Blend effect, Using Color in Direct2D)

    =>

    193421-blend-xor.jpg

    #include <windows.h>  
    #include <tchar.h>  
      
    #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 = 680, nHeight = 600;  
      
    HRESULT WICCreate32BitsPerPixelHBITMAP(IStream* pstm, UINT /* cx */, HBITMAP* phbmp, WTS_ALPHATYPE* pdwAlpha);  
    void DrawBitmapTransparent(HDC hDCDest, int nXDest, int nYDest, int nBitmapWidth, int nBitmapHeight, HBITMAP hBitmap, int nXSrc, int nYSrc, int nTransparentColor, bool bXOR);  
      
    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 HBITMAP hBitmap1 = NULL, hBitmap2 = NULL, hBitmap3 = NULL;  
      
    	switch (message)  
    	{  
    	case WM_CREATE:  
    	{  
    		WCHAR wszURL1[MAX_PATH] = L"https://i.ibb.co/t8dNP1c/Red-Circle.png";  
    		WCHAR wszURL2[MAX_PATH] = L"https://i.ibb.co/4fXcqM8/Green-Circle.png";  
    		WCHAR wszURL3[MAX_PATH] = L"https://i.ibb.co/fCL4LrT/Blue-Circle.png";  
    		WCHAR wszFilename[MAX_PATH];  
      
    		HRESULT hr = URLDownloadToCacheFile(NULL, wszURL1, wszFilename, ARRAYSIZE(wszFilename), 0x0, NULL);	  
    		IStream* pstm = NULL;  
    		hr = SHCreateStreamOnFile(wszFilename, STGM_READ | STGM_SHARE_DENY_WRITE, &pstm);  
    		if (SUCCEEDED(hr))  
    		{  
    			WTS_ALPHATYPE alphatype;  
    			WICCreate32BitsPerPixelHBITMAP(pstm, NULL, &hBitmap1, &alphatype);  
    			pstm->Release();  
    		}  
      
    		hr = URLDownloadToCacheFile(NULL, wszURL2, wszFilename, ARRAYSIZE(wszFilename), 0x0, NULL);		  
    		hr = SHCreateStreamOnFile(wszFilename, STGM_READ | STGM_SHARE_DENY_WRITE, &pstm);  
    		if (SUCCEEDED(hr))  
    		{  
    			WTS_ALPHATYPE alphatype;  
    			WICCreate32BitsPerPixelHBITMAP(pstm, NULL, &hBitmap2, &alphatype);  
    			pstm->Release();  
    		}  
      
    		hr = URLDownloadToCacheFile(NULL, wszURL3, wszFilename, ARRAYSIZE(wszFilename), 0x0, NULL);	  
    		hr = SHCreateStreamOnFile(wszFilename, STGM_READ | STGM_SHARE_DENY_WRITE, &pstm);  
    		if (SUCCEEDED(hr))  
    		{  
    			WTS_ALPHATYPE alphatype;  
    			WICCreate32BitsPerPixelHBITMAP(pstm, NULL, &hBitmap3, &alphatype);  
    			pstm->Release();  
    		}  
      
    		return 0;  
    	}  
    	break;  
    	case WM_PAINT:  
    	{  
    		PAINTSTRUCT ps;  
    		HDC hDC = BeginPaint(hWnd, &ps);  
    		RECT rc;  
    		GetClientRect(hWnd, &rc);  
    		  
    		HBRUSH hBrush = CreateSolidBrush(RGB(0, 0, 0));  
    		FillRect(hDC, &rc, hBrush);  
    		DeleteObject(hBrush);  
      
    		BITMAP bm;  
    		GetObject(hBitmap1, sizeof(BITMAP), &bm);  
    		DrawBitmapTransparent(hDC, bm.bmWidth / 3, 10, bm.bmWidth, bm.bmHeight, hBitmap1, 0, 0, RGB(0, 0, 0), FALSE);  
      
    		GetObject(hBitmap2, sizeof(BITMAP), &bm);  
    		DrawBitmapTransparent(hDC, bm.bmWidth / 6, 10 + bm.bmHeight/3, bm.bmWidth, bm.bmHeight, hBitmap2, 0, 0, RGB(0, 0, 0), TRUE);  
      
    		GetObject(hBitmap3, sizeof(BITMAP), &bm);  
    		DrawBitmapTransparent(hDC, bm.bmWidth / 2, 10 + bm.bmHeight/3, bm.bmWidth, bm.bmHeight, hBitmap3, 0, 0, RGB(0, 0, 0), TRUE);  
      
    		EndPaint(hWnd, &ps);  
    	}  
    	break;  
    	case WM_DESTROY:  
    	{  
    		PostQuitMessage(0);  
    		return 0;  
    	}  
    	break;  
    	default:  
    		return DefWindowProc(hWnd, message, wParam, lParam);  
    	}  
    	return 0;  
    }  
      
      
    void DrawBitmapTransparent(HDC hDCDest, int nXDest, int nYDest, int nBitmapWidth, int nBitmapHeight, HBITMAP hBitmap, int nXSrc, int nYSrc, int nTransparentColor, bool bXOR)  
    {  
    	HDC hDCSrc;  
    	HBITMAP hBitmapOld;  
    	HDC hDCMask;  
    	HBITMAP hBitmapMask;  
    	HBITMAP hBitmapMaskOld;  
    	HDC hDCMem;  
    	HBITMAP hBitmapMem;  
    	HBITMAP hBitmapMemOld;  
    	int nBkColorOld;  
    	int nTextColorOld;  
    	BITMAP bm;  
      
    	GetObject(hBitmap, sizeof(BITMAP), &bm);  
    	if (!nBitmapWidth)  
    		nBitmapWidth = bm.bmWidth;  
    	if (!nBitmapHeight)  
    		nBitmapHeight = bm.bmHeight;  
    	hDCSrc = CreateCompatibleDC(hDCDest);  
    	hBitmapOld = (HBITMAP)SelectObject(hDCSrc, hBitmap);  
    	hDCMask = CreateCompatibleDC(hDCDest);  
    	hBitmapMask = CreateBitmap(nBitmapWidth, nBitmapHeight, 1, 1, 0);  
    	hBitmapMaskOld = (HBITMAP)SelectObject(hDCMask, hBitmapMask);  
    	hDCMem = CreateCompatibleDC(hDCDest);  
    	hBitmapMem = CreateCompatibleBitmap(hDCDest, nBitmapWidth, nBitmapHeight);  
    	hBitmapMemOld = (HBITMAP)SelectObject(hDCMem, hBitmapMem);  
    	nBkColorOld = SetBkColor(hDCSrc, nTransparentColor);  
    	BitBlt(hDCMask, 0, 0, nBitmapWidth, nBitmapHeight, hDCSrc, nXSrc, nYSrc, SRCCOPY);  
    	SetBkColor(hDCSrc, nBkColorOld);  
    	nBkColorOld = SetBkColor(hDCDest, RGB(255, 255, 255));  
    	nTextColorOld = SetTextColor(hDCDest, RGB(0, 0, 0));  
    	if (!bXOR)  
    	{  
    		BitBlt(hDCMem, 0, 0, nBitmapWidth, nBitmapHeight, hDCDest, nXDest, nYDest, SRCCOPY);  
    		BitBlt(hDCMem, 0, 0, nBitmapWidth, nBitmapHeight, hDCSrc, nXSrc, nYSrc, SRCINVERT);  
    		BitBlt(hDCMem, 0, 0, nBitmapWidth, nBitmapHeight, hDCMask, 0, 0, SRCAND);  
    		BitBlt(hDCMem, 0, 0, nBitmapWidth, nBitmapHeight, hDCSrc, nXSrc, nYSrc, SRCINVERT);  
    		BitBlt(hDCDest, nXDest, nYDest, nBitmapWidth, nBitmapHeight, hDCMem, 0, 0, SRCCOPY);  
    	}  
    	else  
    	{  
    		BitBlt(hDCMem, 0, 0, nBitmapWidth, nBitmapHeight, hDCDest, nXDest, nYDest, SRCCOPY);  
    		BitBlt(hDCMem, 0, 0, nBitmapWidth, nBitmapHeight, hDCSrc, nXSrc, nYSrc, SRCCOPY);  
    		BitBlt(hDCMem, 0, 0, nBitmapWidth, nBitmapHeight, hDCMask, 0, 0, SRCAND);  
    		BitBlt(hDCMem, 0, 0, nBitmapWidth, nBitmapHeight, hDCSrc, nXSrc, nYSrc, SRCINVERT);  
    		BitBlt(hDCDest, nXDest, nYDest, nBitmapWidth, nBitmapHeight, hDCMem, 0, 0, SRCINVERT);  
    	}  
    	SetBkColor(hDCDest, nBkColorOld);  
    	SetTextColor(hDCDest, nTextColorOld);  
    	SelectObject(hDCMem, hBitmapMemOld);  
    	DeleteDC(hDCMem);  
    	DeleteObject(hBitmapMem);  
    	SelectObject(hDCMask, hBitmapMaskOld);  
    	DeleteDC(hDCMask);  
    	DeleteObject(hBitmapMask);  
    	SelectObject(hDCSrc, hBitmapOld);  
    	DeleteDC(hDCSrc);  
    }  
      
    // 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;  
    }  
    
    1 person found this answer helpful.
    0 comments No comments

  2. Joaquim Miguel Jesus 1 Reputation point
    2022-04-13T19:23:00.533+00:00

    no luck... please correct me these code:
    BLENDFUNCTION bf;
    bf.AlphaFormat = 0;
    bf.BlendFlags = 0;
    bf.BlendOp = AC_SRC_OVER;
    bf.SourceConstantAlpha = alphavalue;

    AlphaBlend(hdc,x,y,width,height,memdc,0,0,width,height,bf);
    

    'AlphaBlend()' can work with 'Reserve' on 'RGBQUAD' and with 'AC_SRC_ALPHA' on 'bf.BlendOp'? i mean: see the all pixels alpha?


  3. Joaquim Miguel Jesus 1 Reputation point
    2022-04-13T19:46:47.783+00:00

    using these code:
    COLORREF AlphaBlend2(COLORREF Top, COLORREF Source,BYTE Alpha)
    {
    BYTE R = GetRValue(Top) + (GetRValue(Source) * Alpha) >> 8;
    BYTE G = GetGValue(Top) + (GetGValue(Source) * Alpha) >> 8;
    BYTE B = GetBValue(Top) + (GetBValue(Source) * Alpha) >> 8;
    return (RGB(R,G,B));
    }

     void Draw(HDC HDCDestination, int PosX, int PosY, BYTE SourceConstantAlpha=0x00 )  
            {  
               //StretchDIBits(HDCDestination,PosX, PosY, Width, Height,0,0,Width,Height, Pixels,&BitInfo,DIB_RGB_COLORS,SRCCOPY);  
      
                for(unsigned int Y = 0; Y < Height; Y++)  
                {  
                    for(unsigned int X = 0; X< Width; X++)  
                    {  
                        COLORREF color2 = RGB(Pixels[(Y* Width) + (X)].rgbRed, Pixels[(Y* Width) + (X)].rgbGreen, Pixels[(Y* Width) + (X)].rgbBlue);  
      
                        COLORREF color=AlphaBlend2(::GetPixel(HDCDestination, (PosX+ X), (PosY+Y)), color2,200 );  
                        ::SetPixel(HDCDestination,(PosX+X), (PosY + Y) ,color );  
      
                    }  
                }  
      
            }  
    

    heres what i get with 200(the red seems nothing link blend :( ):
    192824-image.png

    0 comments No comments

  4. Joaquim Miguel Jesus 1 Reputation point
    2022-04-14T21:25:54.06+00:00

    Castorix31: "I had posted a sample with AlphaBlend in this thread : How to make a bitmap with alpha using TransparentBlt but I don't see what you're trying to do..."
    see these image:
    193207-image.png

    now thing that we have 3 images(one for R, one for G and other for B)... we must draw them... the top images must be transparent(no backcolor) and Opacy(AlphaBlend).
    is what i'm loking for... but i didn't find a correct formulas, because i don't get results :(

    0 comments No comments

  5. Joaquim Miguel Jesus 1 Reputation point
    2022-04-21T14:07:16.217+00:00

    i'm sorry Castorix31, but my code is using, for now, GDI(not Plus) and i need use math for 3D positions.
    imagine the image have these corners positions(X, Y and Z):
    TopLeft(0,0,0); TopRight(100,0,100);
    BottomLeft(0,100,0); BottomRight(100,100,100)
    the AlphaBlend() don't works... the PlgBlt() maybe can do transparent and stretch, but not AlphaBlend :(
    unless... i use both... the AlphaBlend() for Alpha and Transparent... then using the PlgBlt() for draw the image... what you can tell me?

    https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-plgblt

    and how can i use the lpPoint parameter?

    BOOL PlgBlt(  
      [in] HDC         hdcDest,  
      [in] const POINT *lpPoint,  
      [in] HDC         hdcSrc,  
      [in] int         xSrc,  
      [in] int         ySrc,  
      [in] int         width,  
      [in] int         height,  
      [in] HBITMAP     hbmMask,  
      [in] int         xMask,  
      [in] int         yMask  
    );  
    

    "[in] lpPoint

    A pointer to an array of three points in logical space that identify three corners of the destination parallelogram. The upper-left corner of the source rectangle is mapped to the first point in this array, the upper-right corner to the second point in this array, and the lower-left corner to the third point. The lower-right corner of the source rectangle is mapped to the implicit fourth point in the parallelogram."


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.