【问题标题】:the size of a png imagepng 图像的大小
【发布时间】:2015-12-22 20:39:15
【问题描述】:

例外是Unhandled exception at 0x770CAE54 (ntdll.dll) in OpenCVPaint.exe: 0xC0000374: A heap has been corrupted (parameters: 0x770DFE38).有一个堆损坏,因为我写到了我不应该写的地方(我没有分配足够的空间)。但是我怎么会写到我不应该写的地方呢?

我部分修复了它,我更改了代码中的 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;
}

【问题讨论】:

  • 如果您能提及您对这个问题投反对票的原因,我们将不胜感激。
  • 它被否决了,因为您没有提供代码来重现您的问题。我没有这样做,但大多数想要提供帮助的人也希望看到一个可运行的示例。
  • 请发布一些Minimal, Complete, and Verifiable example 代码。我投了反对票。如果您这样做,将撤消反对票。
  • 我投票关闭 - 不清楚,没有代码,等等......
  • 收回我的反对票。可能根本不是 MCVE,但至少你做出了努力——毕竟 圣诞节 :))

标签: c++ windows opencv memory-management


【解决方案1】:

请注意,GetDIBits 函数要求图像具有宽度为 DWORD 对齐的扫描线(必须是 sizeof(DWORD) 的倍数,对于 Window 的 DIB 是 4)。从链接:

扫描线必须在 DWORD 上对齐,RLE 压缩位图除外。

由于原始图像具有未对齐的宽度,因此应用程序有责任通过调整宽度计算来强制对齐。

当图像未对齐,并且应用程序没有规定对齐图像时,通常最终会发生以下情况:

1) 图像已显示,但具有“阶梯”效应,显示图像的每条扫描线似乎都偏离了一定量,或者,

2) 没有分配足够的内存来处理图像,因此可能会出现堆错误。

问题似乎是没有为create 函数中的图像分配足够的内存来匹配对齐调整所需的额外字节。因此,例如,如果宽度为 437,则在计算要分配的内存量时使用的实际宽度应基于 440 的宽度,而不是 437。

【讨论】:

    猜你喜欢
    • 2019-07-27
    • 2017-04-22
    • 1970-01-01
    • 1970-01-01
    • 2013-09-14
    • 2012-11-08
    • 2012-11-22
    • 2018-10-14
    • 2011-08-18
    相关资源
    最近更新 更多