简体   繁体   中英

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). There's a Corruption in the heap , because I write to a place I shouldn't (I didn't allocate enough room). 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. 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)? How much memory does it need if not 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.

  • bmi.biImageSize` is calculate to be 67, why? 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). From the link:

The scan lines must be aligned on a DWORD except for RLE compressed bitmaps.

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,

2) Not enough memory is allocated to process the image, and thus heap errors may occur.

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. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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