标准的GetDIBits调用方式是两次调用:
第一次传入空的 lpvBits,此时的lpbi作为传出参数,从中可以获得lpvBits所需的内存区域大小。
BYTE *lpvBits = NULL;
BITMAPINFO bmpInfo = {0};
bmpInfo.bmiHeader.biSize = sizeof(bmpInfo.bmiHeader);
/* 第一次调用GetDIBits获得bmpInfo */
nRet = ::GetDIBits(hDC, hBitmap, 0, pBmpData->bmHeight, NULL, &bmpInfo, DIB_RGB_COLORS);
if (nRet == 0) {
nRet = GetLastError();
TRACE( _T("GetDIBits for bmpInfo failed %d/n"), nRet);
goto err;
}
以上调用如果成功,就会在bmpInfo.bmiHeader.biSizeImage记录位数据所占的内存区大小,
此时就可以动态分配内存,然后再次调用GetDIBits获得实际的位数据:
lpvBits= new BYTE[bmpInfo.bmiHeader.biSizeImage];
if (NULL == pBitsBuffer) {
nRet = -1;
TRACE( _T("Allocate memory for lpvBits failed/n"));
goto err;
}
/* 第二次调用GetDIBits获得位图数据 */
nRet = ::GetDIBits(hDC, hBitmap, 0, pBmpData->bmHeight, lpvBits, &bmpInfo, DIB_RGB_COLORS);
if (nRet == 0) {
nRet = GetLastError();
TRACE( _T("GetDIBits for lpvBits failed %d/n"), nRet);
goto err;
}
很多时候,因为位图的长宽和颜色深度都是已知的,因此位数据所占的内存区大小可以由公式
width * heigth * pixelBits / 8 计算获得
那是否可以省略第一步调用呢?
答案是:最好不要
原因是 bmpInfo.bmiHeader.biSizeImage 并不一定等于 width * heigth * pixelBits / 8
标准的GetDIBits调用通常需要两次调用来获取位图数据。第一次获取BITMAPINFO所需内存大小,第二次获取实际位图数据。尽管位图大小可计算,但直接跳过第一次调用可能导致错误,因为bmpInfo.bmiHeader.biSizeImage可能不等于预期值。
597

被折叠的 条评论
为什么被折叠?



