尝试修改 hbitmap 数据时出现堆栈错误
stack error while trying to modify hbitmap data
我正在尝试修改 hbitmap 以在渲染它之前添加透明像素(但这不是问题所在),但经过一些谷歌搜索后我无法使我的代码工作。
这就是我正在尝试的:
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);
实际上我只是想将像素设置为 0,这应该为图像的四分之一设置黑色(最终透明)像素(因为我只是从 0 到 w*x,像素是 4 个字节长)。
但是有一些数据损坏,所以当该函数退出时我得到一个异常。那我的代码不对。
我可以说位图加载得很好,我从 GetDIBits
获得了很好的位图信息。
谢谢
来自MSDN:
biSizeImage
The size, in bytes, of the image. This may be set to zero for BI_RGB bitmaps.
If biCompression is BI_JPEG or BI_PNG, biSizeImage indicates the size of the JPEG or PNG image buffer, respectively.
所以我怀疑您创建了有效的空数组,因为位图通常不会被压缩并且稍后会发生缓冲区溢出。
要获得所需的缓冲区大小,您应该检查 biCompression
,然后(假设它是未压缩的 BI_RGB
)乘以 biWidth * biHeight * biBitCount / 8
按照VTT的建议还是不行,看来问题出在BITMAPINFO
没用好,所以按照微软的方法here并且有效:
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;
我正在尝试修改 hbitmap 以在渲染它之前添加透明像素(但这不是问题所在),但经过一些谷歌搜索后我无法使我的代码工作。 这就是我正在尝试的:
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);
实际上我只是想将像素设置为 0,这应该为图像的四分之一设置黑色(最终透明)像素(因为我只是从 0 到 w*x,像素是 4 个字节长)。
但是有一些数据损坏,所以当该函数退出时我得到一个异常。那我的代码不对。
我可以说位图加载得很好,我从 GetDIBits
获得了很好的位图信息。
谢谢
来自MSDN:
biSizeImage
The size, in bytes, of the image. This may be set to zero for BI_RGB bitmaps. If biCompression is BI_JPEG or BI_PNG, biSizeImage indicates the size of the JPEG or PNG image buffer, respectively.
所以我怀疑您创建了有效的空数组,因为位图通常不会被压缩并且稍后会发生缓冲区溢出。
要获得所需的缓冲区大小,您应该检查 biCompression
,然后(假设它是未压缩的 BI_RGB
)乘以 biWidth * biHeight * biBitCount / 8
按照VTT的建议还是不行,看来问题出在BITMAPINFO
没用好,所以按照微软的方法here并且有效:
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;