Search code examples
c++gdi

stack error while trying to modify hbitmap data


I'm trying to modify a hbitmap to add transparent pixels before rendering it (but that's not the question) and after some googling I can't mak my code to work. This is what I'm trying:

HBITMAP hBitmap = NULL, hBitmapOld = NULL;
HDC hMemDC = NULL;
BLENDFUNCTION bf;


hMemDC = CreateCompatibleDC(hdc);

hBitmapOld = (HBITMAP)SelectObject(hMemDC, bitmap);

BITMAPINFO MyBMInfo = { 0 };
MyBMInfo.bmiHeader.biSize = sizeof(MyBMInfo.bmiHeader);

if (0 == GetDIBits(hMemDC, bitmap, 0, height, NULL, &MyBMInfo, DIB_RGB_COLORS))
    return;

// create the pixel buffer
BYTE* lpPixels = new BYTE[MyBMInfo.bmiHeader.biSizeImage];

if (0 == GetDIBits(hMemDC, bitmap, 0, height, lpPixels, &MyBMInfo, DIB_RGB_COLORS))
    return;

for (int i = 0; i < width*height; i++)//i know there's 4 bytes per pixel, it's just to try
    lpPixels[i] = 0;

if (0 == SetDIBits(hMemDC, bitmap, 0, height, lpPixels, &MyBMInfo, DIB_RGB_COLORS))
    return;

delete[] lpPixels;

bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.SourceConstantAlpha = 255; //transparency value between 0-255
bf.AlphaFormat = 0;

AlphaBlend(hdc, xabs, yabs, width, height, hMemDC, 0, 0, width, height, bf);

SelectObject(hMemDC, hBitmapOld);

DeleteDC(hMemDC);
DeleteObject(hBitmap);

Actualy I'm just trying to set the pixel to 0 which should set black (eventualy transparent) pixels for a quarter of the image (as I'm just going from 0 to w*x and pixels are 4 bytes long).

But there's some data corruption so that when that function exits I get a exception. Then my code is not correct.

I can say the bitmap is well loaded, and I get the good bitmap info from GetDIBits.

Thanks


Solution

  • I folowwed the advice of VTT but it still didn't work, it seems that the problem came from the BITMAPINFO which was not used properly, so I followed the way microsoft does here and it works:

    BITMAPINFOHEADER   bi;
    bi.biSize = sizeof(BITMAPINFOHEADER);
    bi.biWidth = width;
    bi.biHeight = height;
    bi.biPlanes = 1;
    bi.biBitCount = 32;
    bi.biCompression = BI_RGB;
    bi.biSizeImage = 0;
    bi.biXPelsPerMeter = 0;
    bi.biYPelsPerMeter = 0;
    bi.biClrUsed = 0;
    bi.biClrImportant = 0;
    if (0 == GetDIBits(hMemDC, bitmap, 0, height, NULL, (BITMAPINFO*)&bi, DIB_RGB_COLORS))
        return;
    
    // create the pixel buffer
    BYTE* lpPixels = new BYTE[bi.biWidth * bi.biHeight * bi.biBitCount / 8];
    
    if (0 == GetDIBits(hMemDC, bitmap, 0, height, lpPixels, (BITMAPINFO*)&bi, DIB_RGB_COLORS))
        return;
    
    for (int i = 0; i < width*height; i++)//i know there's 4 bytes per pixel, it's just to try
        lpPixels[i] = 0;
    
    if (0 == SetDIBits(hMemDC, bitmap, 0, height, lpPixels, (BITMAPINFO*)&bi, DIB_RGB_COLORS))
        return;