You are calculating the correct image size (knowing that scan lines are
DWORD
aligned) and store it in
m_dwSizeImage
(may be also stored in
bmInfohdr.biSizeImage
). But you did not use this size when allocating the global memory. Depending on the image width,
m_dwSizeImage
may be greater than w * h * 3 (or it is always greater when Bpp is 32), resulting in the access violation.
There is another error with the color table / usage of
BITMAPINFO
:
If the DIB has no color table (Bpp > 8), you must not allocate space for it. Otherwise, the size of the color table must be calculated and allocated. The
BITMAPINFO
structure contains only one color entry as placeholder.
So you should move the image size calculation code on top of the allocation and use something like this (note the usage of
BITMAINFOHEADER
instead of
BITMAPINFO
):
SIZE_T dwColTableLen = (Bpp <= 8) ? (1 << Bpp) * sizeof(RGBQUAD) : 0;
HANDLE hData = ::GlobalAlloc(GMEM_MOVEABLE,
sizeof(BITMAPINFOHEADER) + dwColTableLen + m_dwSizeImage);
...
if (dwColTableLen)
{
LPBYTE lpColorTable = (LPBYTE)pData + sizeof(BITMAPINFOHEADER);
memcpy(lpColorTable, pColors, dwColTableLen);
}
p_imagebits = (LPBYTE)pData + sizeof(BITMAPINFOHEADER) + dwColTableLen;