1

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.

Justin G
  • 716
  • 1
  • 8
  • 24

1 Answers1

5

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.

Mark Ransom
  • 271,357
  • 39
  • 345
  • 578
  • Really? It says in the documentation if you specify 24 for biBitCount: "Each 3-byte triplet in the bitmap array represents the relative intensities of blue, green, and red, respectively". So doesn't that mean it should only be three bytes per pixel? Not four? I've tried setting it to four previously and it just results in a messed up image that looks like the result of misaligned bits. – Justin G Dec 05 '12 at 01:47
  • 1
    @Shenjoku, yes it should be 3 bytes per pixel, except for the last pixel on the line. The width should be 1916, not 1914, because 1916 divides evenly by 4 and 1914 does not. – Mark Ransom Dec 05 '12 at 01:49
  • Wow, I completely misunderstood all of the stuff I was reading trying to figure this out then. I've been banging my head on my desk for hours trying to figure this out. Thanks a ton. – Justin G Dec 05 '12 at 02:04