【小记】BITMAP To BMP 调用 GetDIBits 引发栈内存损坏问题

BITMAP bitmap;
if (!GetObject(hBitmap, sizeof(bitmap), &bitmap)) { // 外部传入 hBitmap
    return false;
}

// 创建位图信息头
BITMAPINFO bitInfo;
BITMAPINFOHEADER& bi = bitInfo.bmiHeader;
bi.biWidth = bitmap.bmWidth;
bi.biHeight = bitmap.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = bitmap.bmBitsPixel; // 这里为 8 位
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
bi.biSize = sizeof(BITMAPINFOHEADER);

// 创建位图文件头
BITMAPFILEHEADER bf;
bf.bfType = 0x4D42;  // "BM"
bf.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + bitmap.bmWidthBytes * bitmap.bmHeight;
bf.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bf.bfReserved1 = 0;
bf.bfReserved2 = 0;

// 创建一个足够大的缓冲区来存储位图文件头、位图信息头和像素数据
bufferSize = bf.bfSize;
buffer = (unsigned char*)GlobalAlloc(GMEM_FIXED, bufferSize);
if (buffer == nullptr) {
    return false;
}

// 将位图文件头、位图信息头和像素数据复制到缓冲区 (或直接写入文件)
memcpy(buffer, &bf, sizeof(bf));
memcpy(buffer + sizeof(bf), &bi, sizeof(bi));

HDC hdc = CreateCompatibleDC(NULL);
if (hdc == NULL) {
    return false;
}

if (!GetDIBits(hdc, hBitmap, 0, (UINT)bitmap.bmHeight, buffer + bf.bfOffBits, &bitInfo, DIB_RGB_COLORS)) {
    GlobalFree(buffer);
    bufferSize = 0;
    return false;
}

DeleteObject(bitmap); 
ReleaseDC(hdc); 

return true;

 

太忙,简单说一下:

当 BMP 小于 16 位时,需要额外的内存空间来存储颜色数据。只传入一个 BITMAPINFOHEADER 是不行的,在 GetDIBits 调用后会引发栈内存损坏导致程序崩溃。需要传入一个完整的 BITMAPINFO 类型才行。

posted @ 2024-01-14 17:10  芯片烤电池  阅读(13)  评论(0编辑  收藏  举报