Search code examples
c++windowscrashgdistretchdibits

StretchDIBits failing only at specific image dimensions


I'm using StretchDIBits to print an image and it is failing when the image is at certain sizes for some unknown reason.

The image data is loaded into an unsigned int array from some some other image source in 24-bit BGR format. I've already verified that the image and buffer are perfectly fine since, like I said, it works at some sizes but not at all.

The current size I'm testing with is 638x1014. If I change the height to 1013 it works fine, but for some reason it just flat out fails if it's 1014.

Here's some code to show you how it's all being setup:

unsigned int * buffer = new unsigned int[width * height * 3];

// Fill buffer with image data...

BITMAPINFOHEADER bi = { 0 };
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = width;
bi.biHeight = height;
bi.biPlanes = 1;
bi.biBitCount = 24;
bi.biCompression = BI_RGB;
bi.biSizeImage = width * height * 3; // Specifying this value because if I don't it will crash trying to read outside of the buffer.

StartPage(hdcPrint);
SetMapMode(hdcPrint, MM_ISOTROPIC);
SetWindowExtEx(hdcPrint, width, height, NULL);
SetViewportExtEx(hdcPrint, width, height, NULL);
SetViewportOrgEx(hdcPrint, 0, 0, NULL);

StretchDIBits(hdcPrint, 0, 0, width, width, 0, 0, width, height, buffer, (BITMAPINFO *) &bi, DIB_RGB_COLORS, SRCCOPY);

StretchDIBits returns zero when it fails and the print result is a blank page.

I have a vague idea of what the problem is because, like it says in the comment, if I don't specify biSizeImage and leave it at zero then StretchDIBits will cause a crash because it tries to read past the end of the buffer. Even so, I have no idea how to diagnose exactly why it's doing that since it works at some sizes but not others.


Solution

  • Your width is the wrong number of bytes. Windows requires that each line be a multiple of 4 bytes; 638*3 is 1914, which is 2 bytes shy.