[英]the size of a png image
例外是Unhandled exception at 0x770CAE54 (ntdll.dll) in OpenCVPaint.exe: 0xC0000374: A heap has been corrupted (parameters: 0x770DFE38).
堆中有一个Corruption ,因为我写到一个我不应该写的地方(我没有分配足够的空间)。 但是我怎么会写到一个我不应该写的地方呢?
我部分修复了它,我更改了代码中的my_pic.create()
行和列,所以我猜就足够了。 但为什么我需要这样做? 为什么h
为 67 而w
为 73 会出错(正是它应该需要的)? 如果不是67(HEIGHT)x73(WIDTH)x3(RGB)
需要多少内存?
如果我更改类型(当前CV_8UC3
可以工作,但捕获的图像远不准确)而不是创建行,它也可以工作。
bmi.biImageSize` 计算为 67,为什么? 这会导致问题吗?
代码如下:
#include <opencv2\opencv.hpp>
#include <Windows.h>
using namespace cv;
Mat screenCapture()
{
HDC hdcSource = GetDC(NULL);
HDC hdcMemory = CreateCompatibleDC(hdcSource);
Mat my_pic;
int i, j;
int w, h;
POINT p1, p2; //Windows.h
p1.x = 437;
p1.y = 247;
p2.x = 510;
p2.y = 314;
w = p2.x - p1.x;
h = p2.y - p1.y;
HBITMAP hBitmap = CreateCompatibleBitmap(hdcSource, w, h);
HBITMAP hBitmapOld = (HBITMAP)SelectObject(hdcMemory, hBitmap);
BITMAPINFOHEADER bmi = { 0 };
bmi.biSize = sizeof(BITMAPINFOHEADER);
bmi.biPlanes = 1;
bmi.biBitCount = 24;
bmi.biWidth = w;
bmi.biHeight = -h;
bmi.biCompression = BI_RGB;
bmi.biSizeImage = ((bmi.biWidth * bmi.biBitCount + 31) & ~31) / 8 * bmi.biHeight<0 ? -bmi.biHeight : bmi.biHeight;
bmi.biXPelsPerMeter = 0;
bmi.biYPelsPerMeter = 0;
bmi.biClrImportant = 0;
bmi.biClrUsed = 256;
while (!(BitBlt(hdcMemory, 0, 0, w, h, hdcSource, p1.x, p1.y, SRCCOPY)));
while (!(hBitmap = (HBITMAP)SelectObject(hdcMemory, hBitmapOld)));
my_pic.create(h, w, CV_8UC3); //THE PROBLEM IS HERE, NOT ENOUGH ALLOCATED
while (!(GetDIBits(hdcSource, hBitmap, 0, h, my_pic.data, (BITMAPINFO*)&bmi, DIB_RGB_COLORS)));
DeleteDC(hdcSource);
DeleteDC(hdcMemory);
return my_pic;
}
int main()
{
Mat img = screenCapture();
malloc(0); //exception occurs here
return 0;
}
请注意, GetDIBits函数要求图像具有宽度为 DWORD 对齐的扫描线(必须是sizeof(DWORD)
的倍数,对于 Window 的 DIB 为4
)。 从链接:
除 RLE 压缩位图外,扫描线必须在 DWORD 上对齐。
由于原始图像具有未对齐的宽度,因此应用程序负责通过调整宽度计算来强制对齐。
当图像未对齐,并且应用程序没有设置对齐图像时,通常最终发生的情况是:
1) 显示图像,但有“阶梯”效果,显示图像的每条扫描线似乎偏离了一定量,或者,
2) 没有分配足够的内存来处理图像,因此可能会出现堆错误。
问题似乎是在create
函数中没有为图像分配足够的内存来匹配对齐调整所需的额外字节。 因此,例如,如果宽度为 437,则计算分配内存量时使用的实际宽度应基于宽度 440,而不是 437。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.