从内存的角度来看,能表现图像的方式只有HBITMAP(图像句柄),建议你还是用一下
CreateDIBSection,
给你一段说明:
设备无关位图与设备有关位图
位图包含两部分:后者的BITMAPINFO结构信息、位图图像数据。设备无关位图与设备有关位图最大的区别是后者位图信息与数据是由操作系统分配,而前者是自定义的。
设备无关位图通常从位图文件或其它方式调入,在内存中生成信息,BITMAPINFO结构信息和位图图像两部分,你可以任意改变它们以符合要求,下面是从位图文件读入设备无关位图的实例:
CFile file;
//打开文件,如果失败则返回
if (!file.Open(lpszFileName,CFile::ModeRead | CFile::typeBinary))
return;
//读入位图文件头信息
BITMAPFILEHEADER bfh;
if (file.Read(&bfh,sizeof(bffh) !=sizeof(bfh))
{
file.Close();
return;
}
//如果不是位图文件,返回
if (bfh.bfType !=0x4d42) //'BM'
return;
//得到BITMAPINFO结构大小并读出内容
DWORD size_bitmapinfo=bfh.bfOffBits-sizeof(BITMAPINFOHEADER);
LPBITMAPINFO pBMI=(LPBITMAPINFO)malloc(size_bitmapinfo);
file.Read(pBMI,size_bitmapinfo);
//得到位图数据大小并读出内容
DWORD dataBytes=bfh.bfSize-bfh.bfOffBits;
LPBYTE pDIBData=(LPBYTE) malloc(dataBytes);
file.Read(pDIBData,dataBytes);
file.Close();
读出的BITMAPINFO结构信息保存在pBMI中,位图数据保存在pDIBData中。
设备有关位图的内存通常是由系统分配的,HBITMAP称为位图句柄,它是设备有关位图由系统指定的索引值,通过HBITMAP位图句柄可以访问设备有关位图。GetDIBits函数可以获取设备有关位图的BITMAPINFO结构信息和位图数据,如果仅仅是获取位图数据,还可以使用SDK::GetObject或CBitmap::GetBitmap函数,位图数据保存在BITMAP结构中。下面是获取设备有关位图的BITMAPINFO结构信息和位图数据的实例:
//获取位图hBitmap的BITMAP结构信息
BITMAP b;
GetObject(hBitmap,sizeof(b),&b);
//获取颜色表大小以决定BITMAPINFO结构大小
DWORD PalSize=b.bmBitsPixel > 8 ? 0 : 1<<b.bmBitsPixel*sizeof(RGBQUAD);
LPBITMAPINFO pBMI=(LPBITMAPINFO) malloc(sizeof(BITMAPINFOHEADER)+PalSize);
//初始化BITMAPINFOHEADER结构信息,这是必需的
//biBitCount必须是1,4,8,24值之一,如果biBitCount值为16或32,必须转化为24
LPBITMAPINFOHEADER pBMH=(LPBITMAPINFOHEADER) pBMI;
pBMH->biBitCount=b.bmBitsPixel > 8 ? 24 : b.bmBitsPixel;
pBMH->biClrImportant=0;
pBMH->biClrUsed=PalSize/sizeof(RGBQUAD);
pBMH->biCompression=BI_RGB;
pBMH->biHeight=b.bmHeight;
pBMH->biPlanes=1;
pBMH->biSize=sizeof(BITMAPINFOHEADER);
pBMH->biSizeImage=b.bmHeight*4*((bmWidth*pBMH->biBitCount+31)/32);
pBMH->biWidth=b.bmWidth;
pBMH->biXPelsPerMeter=0;
pBMH->biYPelsPerMeter=0;
//将GetDIBits函数的LPVOID参数设为NULL,表示不获取位图数据,只获取BITMAPINFO结构信息
GetDIBits
:GetDC(NULL),hBitmap,0,b.bmHieght,NULL,pBMI,DIB_RGB_COLORS);
注释:该例的BITMAPINFO结构信息是拷贝本,而位图数据是BITMAP结构的lpBits参数,它是位图的原始数据,如果位图被删除,位图数据也被删除,因此必要时需拷贝数据,拷贝方法如下:
LPBYTE pDIBData=(LPBYTE) malloc(pBMH->biSizeImage);
memcpy(pDIBData,b.lpBits)
hBitmap位图BITMAPINFO结构信息保存在pBMI中,位图数据保存在BITMAP结构中,请参阅 BITMAPINFO、BITMAPINFOHEADER、RGBQUAD结构。如果要修改设备有关位图的信息与数据,可以使用SetDIBits函数。但是只能赋予与原位图大小的新位图,而且不能改变位图颜色结构,事实上,设备有关位图的BITMAPINFO信息结构和位图数据在内存中的位置与大小是固定的,你只能在这样的内存区域内进行读写,不要试图该变它们的位置和大小,这是与设备无关位图不同的地方。如果要删除位图,使用DeleteObject函数。
与设备无关位图不同,设备有关位图可以被选入内存设备环境,可以用SDK::SelectObject或CDC::SelectObject函数做到,但是,要有一个前提:设备环境的颜色表结构必需与设备有关位图颜色表兼容,也就是说,如果设备环境的颜色表是256色的,那么设备环境只能选入单色,16色或256色位图,而不能选入24位真彩位图。而对于现在,创建一个与24位位图兼容的内存设备环境是容易的,下面是内存设备环境选入位图的实例:
//创建与视屏显示器兼容的内存设备DC
CDC dc;
dc.CreateCompatibleDC(NULL);
//选入位图
SelectObject(dc.GetSafeHdc(),hBitmap);
当设备有关位图被选入内存设备环境后,这幅位图就是设备环境的显示表面,这时就可以用画笔(HPEN)、画刷(HBRUSH)等方式进行编辑,因此,如果要编辑一幅位图,设备有关位图是必需的。
事实上我们时常会这样做:当要编辑一幅位图,就必需使用设备有关位图,如果是设备无关位图,就必须先转化为设备有关位图、当要存储一幅位图,就必须使用设备无关位图,如果是设备有关位图,就必需先转化为设备无关位图。因此,设备无关位图与设备有关位图之间的转化是必需的。设备无关位图转化为设备有关位图比较方便,用SetDIBits函数即可,但SetDIBits函数的HBITMAP参数是什么样的设备有关位图,如何创建一幅与设备无关位图颜色结构与位图大小相同的设备有关位图,用CreateDIBSection函数即可,下面是一个生成一幅100 X 100大小的单色设备有关位图的实例:
//自定义符合要求的BITMAPINFO结构
struct
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[2];
} MY_BITMAPINFO=
{
{
sizeof(BITMAPINFOHEADER),
100,100,1,1,BI_RGB,0,0,0,0,0
},
{
{0x00,0x00,0x00},{0xFF,0xFF,0xFF}
}
};
void* lpbits;
//创建根据自定义的BITMAPINFO结构信息相同的设备有关位图
HBITMAP hBitmap=CreateDIBSection
:GetDC(NULL),(LPBITMAPINFO)&MY_BITMAPINFO,DIB_RGB_COLORS,&lpbits,NULL,0);
创建的设备有关位图只有BITMAPINFO结构信息是有效的,而位图数据只是分配了内存,并没有实际内容。此时可以将一幅与其大小相同的设备无关位图拷贝,下面是两种方法,pBMI为BITMAPINFO结构内存首地址,pDIBData为位图数据首地址:
//直接用SetDIBits函数拷贝
SetDIBits
:GetDC(NULL),hBitmap,0,pBMI->bmiHeader.biHeight,pDIBData,pBMI,DIB_RGB_COLORS);
//先将设备有关位图选入内存设备作为显示表面,然后将设备无关位图在该表面显示
CDC dc;
dc.CreateCompatibleDC(NULL);
SelectObject(dc.GetSafeHdc(),hBitmap);
StretchDIBits(dc.GetSafeHdc(),0,0,X,Y,0,0,X,Y,pDIBData,pBMI,DIB_RGB_COLORS,SRCCOPY);
//X,Y为位图大小
将设备有关位图转化为设备无关位图用GetDIBits函数即可。