我这里强调的是Win32标准C++而不是MFC,所以没用到CBITMAP,属于比较底层一点。直接上代码了!
获取位图数据核心函数就是GetDIBits,通过它来获取位图的二进制数据。
static bool BMP_SaveFile(const char* szFile, const void* pBmp, int width, int height, int bitCount=32)
{
HANDLE hFile = CreateFile(szFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
assert(hFile != NULL);
int bmp_size = width*height*(bitCount/8);
// 【写位图文件头】
BITMAPFILEHEADER bmpHeader;
bmpHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + bmp_size; // BMP图像文件的大小
bmpHeader.bfType = 0x4D42; // 位图类别,根据不同的操作系统而不同,在Windows中,此字段的值总为‘BM’
bmpHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); // BMP图像数据的偏移位置
bmpHeader.bfReserved1 = 0; // 总为0
bmpHeader.bfReserved2 = 0; // 总为0
DWORD dwBytesWritten = 0;
WriteFile(hFile, (LPSTR)&bmpHeader, sizeof(bmpHeader), &dwBytesWritten, NULL);
BITMAPINFOHEADER bmiHeader;
bmiHeader.biSize = sizeof(bmiHeader); // 本结构所占用字节数,即sizeof(BITMAPINFOHEADER);
bmiHeader.biWidth = width; // 位图宽度(单位:像素)
bmiHeader.biHeight = height; // 位图高度(单位:像素)
bmiHeader.biPlanes = 1; // 目标设备的级别,必须为1
bmiHeader.biBitCount = bitCount; // 像素的位数(每个像素所需的位数,范围:1、4、8、24、32)
bmiHeader.biCompression = 0; // 压缩类型(0:不压缩 1:BI_RLE8压缩类型 2:BI_RLE4压缩类型)
bmiHeader.biSizeImage = bmp_size; // 位图大小(单位:字节)
bmiHeader.biXPelsPerMeter = 0; // 水平分辨率(像素/米)
bmiHeader.biYPelsPerMeter = 0; // 垂直分辨率(像素/米)
bmiHeader.biClrUsed = 0; // 位图实际使用的彩色表中的颜色索引数
bmiHeader.biClrImportant = 0; // 对图象显示有重要影响的颜色索引的数目
// 【写位图信息头(BITMAPINFO的bmiHeader成员)】
WriteFile(hFile, (LPSTR)&bmiHeader, sizeof(bmiHeader), &dwBytesWritten, NULL);
// 【写像素内容】
WriteFile(hFile, pBmp, bmp_size, &dwBytesWritten, NULL);
CloseHandle(hFile);
return true;
}
/*
*基于GDI截图到粘贴板
*/
static void Capture(HWND hWnd,int width,int height,bool save=false,string fileName="pic.bmp")
{
//尝试BITBLT截图
HDC hSrcDC = ::GetDC(hWnd);
HDC hMemDC = ::CreateCompatibleDC(hSrcDC);
HBITMAP hbmp = ::CreateCompatibleBitmap(hSrcDC, width, height);
HBITMAP hOldbmp = (HBITMAP) ::SelectObject(hMemDC, hbmp);
::BitBlt(hMemDC, 0, 0, width, height, hSrcDC, 0, 0, SRCCOPY);
OpenClipboard(NULL);
EmptyClipboard();
SetClipboardData(CF_BITMAP,hbmp);
CloseClipboard();
if(save)
{
int bmp_size = width*height*4;//32/8
byte* pData = new byte[bmp_size];//位图片的数据
BITMAPINFOHEADER bmiHeader;
bmiHeader.biSize = sizeof(bmiHeader); // 本结构所占用字节数,即sizeof(BITMAPINFOHEADER);
bmiHeader.biWidth = width; // 位图宽度(单位:像素)
bmiHeader.biHeight = height; // 位图高度(单位:像素)
bmiHeader.biPlanes = 1; // 目标设备的级别,必须为1
bmiHeader.biBitCount = 32; // 像素的位数(每个像素所需的位数,范围:1、4、8、24、32)
bmiHeader.biCompression = 0; // 压缩类型(0:不压缩 1:BI_RLE8压缩类型 2:BI_RLE4压缩类型)
bmiHeader.biSizeImage = bmp_size; // 位图大小(单位:字节)
bmiHeader.biXPelsPerMeter = 0; // 水平分辨率(像素/米)
bmiHeader.biYPelsPerMeter = 0; // 垂直分辨率(像素/米)
bmiHeader.biClrUsed = 0; // 位图实际使用的彩色表中的颜色索引数
bmiHeader.biClrImportant = 0; // 对图象显示有重要影响的颜色索引的数目
int ret = GetDIBits(hSrcDC,hbmp,0,height,pData,(LPBITMAPINFO)&bmiHeader,DIB_RGB_COLORS);
if(ret)BMP_SaveFile(fileName.c_str(),pData,width,height);
if(pData)delete pData;//删除开辟的内存空间
}
//释放
::SelectObject(hMemDC,hOldbmp);
DeleteDC(hMemDC);
DeleteObject(hbmp);
ReleaseDC(NULL, hSrcDC);
}获取位图数据核心函数就是GetDIBits,通过它来获取位图的二进制数据。
收藏的用户(0) X
正在加载信息~
推荐阅读
最新回复 (0)
站点信息
- 文章2313
- 用户1336
- 访客11737676
每日一句
Grow through what you go through.
穿越困境,得以成长。
穿越困境,得以成长。
新会员