简体   繁体   English

png 图像的大小

[英]the size of a png image

The exception is Unhandled exception at 0x770CAE54 (ntdll.dll) in OpenCVPaint.exe: 0xC0000374: A heap has been corrupted (parameters: 0x770DFE38).例外是Unhandled exception at 0x770CAE54 (ntdll.dll) in OpenCVPaint.exe: 0xC0000374: A heap has been corrupted (parameters: 0x770DFE38). There's a Corruption in the heap , because I write to a place I shouldn't (I didn't allocate enough room).堆中有一个Corruption ,因为我写到一个我不应该写的地方(我没有分配足够的空间)。 But how come I write to a place I shouldn't?但是我怎么会写到一个我不应该写的地方呢?

I fixed it partially, I changed my_pic.create() rows and cols in the code so it'd suffice I guess.我部分修复了它,我更改了代码中的my_pic.create()行和列,所以我猜就足够了。 But why did I need to?但为什么我需要这样做? Why does it go wrong with h as 67 and w as 73 (exactly what it's supposed to need)?为什么h为 67 而w为 73 会出错(正是它应该需要的)? How much memory does it need if not 67(HEIGHT)x73(WIDTH)x3(RGB) ?如果不是67(HEIGHT)x73(WIDTH)x3(RGB)需要多少内存?

  • If I change the type (currently CV_8UC3 it works but the image captured is far from accurate) instead of the creating line, it works too.如果我更改类型(当前CV_8UC3可以工作,但捕获的图像远不准确)而不是创建行,它也可以工作。

  • bmi.biImageSize` is calculate to be 67, why? bmi.biImageSize` 计算为 67,为什么? does that cause the problem?这会导致问题吗?

The code is as follows:代码如下:

#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;
}

Note that the GetDIBits function requires that images have scan lines that have widths that are DWORD aligned (must be a multiple of sizeof(DWORD) , which is 4 for a Window's DIB).请注意, GetDIBits函数要求图像具有宽度为 DWORD 对齐的扫描线(必须是sizeof(DWORD)的倍数,对于 Window 的 DIB 为4 )。 From the link:从链接:

The scan lines must be aligned on a DWORD except for RLE compressed bitmaps.除 RLE 压缩位图外,扫描线必须在 DWORD 上对齐。

Since the original image has a width that is not aligned, it is the responsibility of the application to force alignment by adjusting the width calculation.由于原始图像具有未对齐的宽度,因此应用程序负责通过调整宽度计算来强制对齐。

When an image is not aligned, and no provisions are made by the application to align the image, what usually ends up happening is either:当图像未对齐,并且应用程序没有设置对齐图像时,通常最终发生的情况是:

1) The image is displayed, but has a "staircase" effect, where each scan line of the displayed image seems to be off by a certain amount or, 1) 显示图像,但有“阶梯”效果,显示图像的每条扫描线似乎偏离了一定量,或者,

2) Not enough memory is allocated to process the image, and thus heap errors may occur. 2) 没有分配足够的内存来处理图像,因此可能会出现堆错误。

The issue seems to be that not enough memory was allocated for the image in the create function to match the extra bytes required for the alignment adjustment.问题似乎是在create函数中没有为图像分配足够的内存来匹配对齐调整所需的额外字节。 So for example, if the width is 437, the actual width used in the calculation for the amount of memory to allocate should be based on a width of 440, not 437.因此,例如,如果宽度为 437,则计算分配内存量时使用的实际宽度应基于宽度 440,而不是 437。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM