Skip to content

Instantly share code, notes, and snippets.

@iamahuman
Created March 13, 2022 23:09

Revisions

  1. iamahuman created this gist Mar 13, 2022.
    50 changes: 50 additions & 0 deletions gdi_argb8888_to_pargb8888.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,50 @@
    #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;
    }