关于CDib类中BITMAPFILEHEADER使用方法的不解

okaimee 2010-05-20 03:44:00
在《精通visual c++图像处理编程》这本书第三章的范例中,其CDib类有这样一个方法:
BOOL CDib::Read(CFile *pFile)
{
WaitCursorBegin();//显示沙漏光标

LPBITMAPINFOHEADER lpbi;
DWORD dwSize;
TRY
{
// 读取DIB文件头
BITMAPFILEHEADER bmfHdr;
pFile->Read(&bmfHdr, sizeof(BITMAPFILEHEADER));
// 判断是否为DIB文件
if (bmfHdr.bfType != DIB_HEADER_MARKER/*"BM"*/)
{
WaitCursorEnd();
return FALSE;
}
DWORD dwLength = pFile->GetLength();
if (bmfHdr.bfSize != dwLength)
bmfHdr.bfSize = dwLength;

// 读取DIB缓存
dwSize = bmfHdr.bfSize - sizeof(BITMAPFILEHEADER);
lpbi = (LPBITMAPINFOHEADER)GlobalAllocPtr(GHND, dwSize);

DWORD dwCount = pFile->Read(lpbi, dwSize);
// 是否读取成功
if (dwCount != dwSize)
{
GlobalFreePtr(lpbi);
WaitCursorEnd();
return FALSE;
}

// 测试是否为Windows DIB——OS/2 DIB在使用其它DIB API时会导致奇怪的问题,因为头中的域是不同的,而且,颜色表项也比较小
// 如果不是Windows DIB(如果大小不对),返回NULL
if (lpbi->biSize != sizeof(BITMAPINFOHEADER))
{
GlobalFreePtr(lpbi);
WaitCursorEnd();
return FALSE;
}

// 为颜色数项赋值
int nNumColors = (UINT)lpbi->biClrUsed;
if (nNumColors == 0)
{
// 对于24位像素没有颜色表,除此以外都是默认大小
if (lpbi->biBitCount != 24)
nNumColors = 1 << lpbi->biBitCount; // 标准大小的颜色表
}

// 如果值为0,则赋默认值
if (lpbi->biClrUsed == 0)
lpbi->biClrUsed = nNumColors;
if (lpbi->biSizeImage == 0)
lpbi->biSizeImage = ((((lpbi->biWidth * (DWORD)lpbi->biBitCount) + 31) & ~31) >> 3) * lpbi->biHeight;
}
CATCH (CException, e)
{
GlobalFreePtr(lpbi);
WaitCursorEnd();
return FALSE;
}
END_CATCH

// 通过DIB缓存建立CDib
BOOL bSuccess = Create((LPBYTE)lpbi);
GlobalFreePtr(lpbi);
WaitCursorEnd();

return bSuccess;
}


我在这里有点没看明白:
1、
dwSize = bmfHdr.bfSize - sizeof(BITMAPFILEHEADER);
lpbi = (LPBITMAPINFOHEADER)GlobalAllocPtr(GHND, dwSize);
lpbi指向的是“LPBITMAPINFOHEADER+RGBQUAD”还是只有“LPBITMAPINFOHEADER”?
2、
函数最后的Create调用的是CDib类的Create函数,用来创建CDib对象:
BOOL bSuccess = Create((LPBYTE)lpbi);
这里传入的参数lpbi是不是就是指向BITMAPFILEHEADER的指针呢?
创建CDib对象只需要BITMAPFILEHEADER就可以了吗?不需要RGBQUAD和位图数据吗?
Create函数如下:
BOOL CDib::Create(LPBYTE lpDIB)
{
if (lpDIB == NULL)
return FALSE;

DWORD dwSize = DIBlockSize(lpDIB);

HDIB hDib = GlobalAlloc(GHND, dwSize);
// 测试DIB句柄是否正确
if (! hDib)
return FALSE;

LPBYTE lpbi = (LPBYTE)GlobalLock(hDib);
if (! lpbi)
return FALSE;

CopyMemory(lpbi, lpDIB, dwSize);
GlobalUnlock(hDib);

Destroy();
m_hDib = hDib;
return UpdateInternal();
}

我是小白,求解惑
...全文
354 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
向立天 2010-05-24
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 okaimee 的回复:]
太感谢啦,向大哥,你实在是一个毫不为己,专门为人的伟大的,牛X的CSDN战士^_^
[/Quote]
谢谢
严重了
主要是比较闲
okaimee 2010-05-24
  • 打赏
  • 举报
回复
太感谢啦,向大哥,你实在是一个毫不为己,专门为人的伟大的,牛X的CSDN战士^_^
向立天 2010-05-24
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 okaimee 的回复:]
引用 9 楼 xianglitian 的回复:
不是开始的部分
而是把这块内存按着LPBITMAPINFOHEADER来处理
比如
一个内存上的内如是0x3000
而他的地址是void* p;
那么如果按字符读(char*)p结果就是字符0
如果按短整型读(short*)p结果就是整数48
哦,,那是不是应该这样理解:对于dwSize的整个内存,从开始按照LPBITMAPINFOH……
[/Quote]
差不多就是这个意思
okaimee 2010-05-24
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 xianglitian 的回复:]
不是开始的部分
而是把这块内存按着LPBITMAPINFOHEADER来处理
比如
一个内存上的内如是0x3000
而他的地址是void* p;
那么如果按字符读(char*)p结果就是字符0
如果按短整型读(short*)p结果就是整数48[/Quote]
哦,,那是不是应该这样理解:对于dwSize的整个内存,从开始按照LPBITMAPINFOHEADER来进行读取,并将首地址赋给lpbi。而余下的没有读取的部分就不再读了。所以,只要知道颜色表+位图数据的大小,用lpbi这个指针也能读出后续的颜色表+位图数据的数据,尽管LPBITMAPINFOHEADER并不包含这部分数据,是这样吗?
向立天 2010-05-24
  • 打赏
  • 举报
回复
你理解的基本正确
总的说来
不管什么文件
如果你要通过裸数据生成文件就要自己写文件头
一般读文件都是通过文件头来获取文件信息的
不过关于
------
lpbi = (LPBITMAPINFOHEADER)GlobalAllocPtr(GHND, dwSize);这一部分应该是从整个dwSize这么大的内存里只读出了开始的LPBITMAPINFOHEADER部分并把这部分的首地址赋给了lpbi,我这么理解是不是就正确了?
------
不是开始的部分
而是把这块内存按着LPBITMAPINFOHEADER来处理
比如
一个内存上的内如是0x3000
而他的地址是void* p;
那么如果按字符读(char*)p结果就是字符0
如果按短整型读(short*)p结果就是整数48
okaimee 2010-05-24
  • 打赏
  • 举报
回复
新的一周啦,再作最后一次尝试,能有人帮忙看一下,我在6楼的理解是否正确。
谢谢啦
向立天 2010-05-21
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 okaimee 的回复:]
一夜过去了,新的一天会不会有人看到这个帖子呢~~
[/Quote]

建议你看看位图格式方面的资料
这些东西还是需要自己理解
http://wenku.baidu.com/view/faab02d9ad51f01dc281f1cb.html
okaimee 2010-05-21
  • 打赏
  • 举报
回复
一夜过去了,新的一天会不会有人看到这个帖子呢~~
okaimee 2010-05-21
  • 打赏
  • 举报
回复
啊,五点半了,要下班了,热心的人们不要走啊~~
okaimee 2010-05-21
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 xianglitian 的回复:]
引用 4 楼 okaimee 的回复:
一夜过去了,新的一天会不会有人看到这个帖子呢~~


建议你看看位图格式方面的资料
这些东西还是需要自己理解
http://wenku.baidu.com/view/faab02d9ad51f01dc281f1cb.html
[/Quote]
太感谢你啦,你提供的文档我下载了,并且好好地看了,对这部分有了更多的理解
发觉我的问题似乎出在强制转换上,lpbi = (LPBITMAPINFOHEADER)GlobalAllocPtr(GHND, dwSize);这一部分应该是从整个dwSize这么大的内存里只读出了开始的LPBITMAPINFOHEADER部分并把这部分的首地址赋给了lpbi,我这么理解是不是就正确了?
另外,关于Create函数中传递的参数,应该就是LPBITMAPINFOHEADER类型的指针,但是,这个指针所指向的地址必须同时也是一个完整的包含LPBITMAPINFOHEADER+颜色表+位图数据的一大块内存的首地址,我这么理解正确吗?
也就是说,如果我拥有位图数据,想要进行Create,就必须自己建立LPBITMAPINFOHEADER和颜色表,再然后为整个的“LPBITMAPINFOHEADER+颜色表+位图数据”分配空间,然后进行LPBITMAPINFOHEADER类型转化,从而获得lpbi指针?
我以上的理解是不是正确的呀?
okaimee 2010-05-20
  • 打赏
  • 举报
回复
感谢xq830210的回复
1、dwSize = bmfHdr.bfSize - sizeof(BITMAPFILEHEADER);
2、lpbi = (LPBITMAPINFOHEADER)GlobalAllocPtr(GHND, dwSize);
这里第一句中
dwSize=整个bmp文件的大小-BITMAPFILEHEADER的大小
整个bmp文件应该包括BITMAPFILEHEADER+LPBITMAPINFOHEADER+RGBQUAD+位图数据,那么
dwSize=LPBITMAPINFOHEADER+RGBQUAD+位图数据,
那么在第二句中
lpbi被分配的缓存是不是就有“LPBITMAPINFOHEADER+RGBQUAD+位图数据”那么大呢?那又怎么能转换成BITMAPINFOHEADER类型呢
于是我就迷糊了,lpbi到底是指向谁的指针

盼解惑
Normandie007 2010-05-20
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 okaimee 的回复:]
我在这里有点没看明白:
1、
dwSize = bmfHdr.bfSize - sizeof(BITMAPFILEHEADER);
lpbi = (LPBITMAPINFOHEADER)GlobalAllocPtr(GHND, dwSize);
lpbi指向的是“LPBITMAPINFOHEADER+RGBQUAD”还是只有“LPBITMAPINFOHEADER”?
[/Quote]
lpbi是LPBITMAPINFOHEADER类型的指针,所以指向的是BITMAPINFOHEADER结构。

[Quote=引用 1 楼 okaimee 的回复:]
2、
函数最后的Create调用的是CDib类的Create函数,用来创建CDib对象:
BOOL bSuccess = Create((LPBYTE)lpbi);
这里传入的参数lpbi是不是就是指向BITMAPFILEHEADER的指针呢?
创建CDib对象只需要BITMAPFILEHEADER就可以了吗?不需要RGBQUAD和位图数据吗?
[/Quote]
这里传入的参数lpbi是指向BITMAPINFOHEADER的指针。


okaimee 2010-05-20
  • 打赏
  • 举报
回复
沙发的滋味只有坐一坐才知道

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧