Skip to content

Instantly share code, notes, and snippets.

@iamahuman
Created March 13, 2022 23:09
Show Gist options
  • Save iamahuman/aafb78b96b3ff77bd9c6cdda2a25fb00 to your computer and use it in GitHub Desktop.
Save iamahuman/aafb78b96b3ff77bd9c6cdda2a25fb00 to your computer and use it in GitHub Desktop.
Convert ARGB8888 bitmap to Premultipled ARGB8888 bitmap (expected by GdiAlphaBlt)
#define WIN32_LEAN_AND_MEAN
#define WINVER 0x0601
#define _WIN32_WINNT 0x0601
#include <windows.h>
HBITMAP argb8888_to_pargb8888(HBITMAP hbm, HDC hdc)
{
const BLENDFUNCTION blendfn = { AC_SRC_OVER, 0, 0xff, AC_SRC_ALPHA };
HDC hdcSrc, hdcTmp1, hdcTmp2;
HBITMAP hbmRes = NULL, hbmTmp1, hbmTmp2;
HBRUSH hbrwhite;
BITMAP bitmap;
INT width, height;
if (GetObjectType(hbm) != OBJ_BITMAP) goto done;
if (!GetObject(hbm, sizeof(BITMAP), &bitmap)) goto done;
width = bitmap.bmWidth;
height = bitmap.bmHeight;
if (!(hbrwhite = GetStockObject(WHITE_BRUSH))) goto done;
if (!(hdcSrc = CreateCompatibleDC(hdc))) goto done;
if (!SelectObject(hdcSrc, hbm)) goto free_hdcSrc;
if (!(hbmTmp1 = CreateCompatibleBitmap(hdcSrc, width, height))) goto free_hdcSrc;
if (!(hbmTmp2 = CreateCompatibleBitmap(hdcSrc, width, height))) goto free_hbmTmp1;
if (!(hdcTmp1 = CreateCompatibleDC(hdcSrc))) goto free_hbmTmp2;
if (!SelectObject(hdcTmp1, hbmTmp1)) goto free_hdcTmp1;
if (!SelectObject(hdcTmp1, hbrwhite)) goto free_hdcTmp1;
if (!(hdcTmp2 = CreateCompatibleDC(hdcSrc))) goto free_hdcTmp1;
if (!SelectObject(hdcTmp2, hbmTmp2)) goto free_hdcTmp2;
if (!SelectObject(hdcTmp2, hbrwhite)) goto free_hdcTmp2;
if (!BitBlt(hdcTmp1, 0, 0, width, height, hdcSrc, 0, 0, MERGECOPY /* PSa */)) goto free_hdcTmp2;
if (!BitBlt(hdcTmp2, 0, 0, width, height, hdcSrc, 0, 0, 0x000300AA /* PSon */)) goto free_hdcTmp2;
if (!GdiAlphaBlend(hdcTmp1, 0, 0, width, height, hdcTmp2, 0, 0, width, height, blendfn)) goto free_hdcTmp2;
if (!PatBlt(hdcTmp1, 0, 0, width, height, 0x00A50065 /* PDxn */)) goto free_hdcTmp2;
hbmRes = hbmTmp1; hbmTmp1 = NULL;
free_hdcTmp2:
DeleteDC(hdcTmp2);
free_hdcTmp1:
DeleteDC(hdcTmp1);
free_hbmTmp2:
if (hbmTmp2) DeleteObject(hbmTmp2);
free_hbmTmp1:
if (hbmTmp1) DeleteObject(hbmTmp1);
free_hdcSrc:
DeleteDC(hdcSrc);
done:
return hbmRes;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment