15,979
社区成员
发帖
与我相关
我的任务
分享
bool writeBMP(const char filename[], unsigned char* data, unsigned int w, unsigned int h) {
/** 创建位图文件信息和位图文件头结构 */
BITMAPFILEHEADER header;
BITMAPINFOHEADER bitmapInfoHeader;
/** 填充BITMAPFILEHEADER */
header.bfType = 0x4d42;// 'BM'
int alinepixelsbytescount=(w*3+31)/32*4;
header.bfSize = alinepixelsbytescount*h + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
header.bfReserved1 = 0;
header.bfReserved2 = 0;
header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
/** 写入位图文件头信息 */
CFile out_file;
out_file.Open(filename,CFile::modeCreate | CFile::modeWrite);
out_file.Write((char*)&header, sizeof(BITMAPFILEHEADER));
/** 填充BITMAPINFOHEADER */
bitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfoHeader.biWidth = w;
bitmapInfoHeader.biHeight = h;
bitmapInfoHeader.biPlanes = 1;
bitmapInfoHeader.biBitCount = 24;
bitmapInfoHeader.biCompression = BI_RGB; // BI_RLE4 BI_RLE8
bitmapInfoHeader.biSizeImage = alinepixelsbytescount*h ; // 当压缩类型为BI_RGB是也可以设置为0
bitmapInfoHeader.biXPelsPerMeter = 0;
bitmapInfoHeader.biYPelsPerMeter = 0;
bitmapInfoHeader.biClrUsed = 0;
bitmapInfoHeader.biClrImportant = 0;
/** 写入位图文件信息 */
out_file.Write((char*)&bitmapInfoHeader, sizeof(BITMAPINFOHEADER));
/** 将指针移到数据开始位置 */
out_file.Seek(header.bfOffBits,CFile::begin);
/** 写入图像数据 */
int y;
unsigned char *alinepixels=new unsigned char[alinepixelsbytescount];
memset(alinepixels+alinepixelsbytescount-4,0,4);
for (y=0;y<h;y++) {
memcpy(alinepixels,data+y*w);
out_file.Write((char*)alinepixels, alinepixelsbytescount);
}
out_file.Close();
delete [] alinepixels;
delete [] data;
return true;
}
//
HBITMAP CopyScreenToBitmap(CRect &Rect,HWND hwnd)
{
HDC hScrDC, hMemDC;
HBITMAP hOldBitmap,hBitmap;
int xScrn, yScrn;
// to screen coordinates.
MapWindowPoints(hwnd,NULL,(POINT *)&Rect,2);
hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL);
hMemDC = CreateCompatibleDC(hScrDC);
//
xScrn = GetDeviceCaps(hScrDC, HORZRES);
yScrn = GetDeviceCaps(hScrDC, VERTRES);
//
if (Rect.left < 0) Rect.left = 0;
if (Rect.top < 0) Rect.top = 0;
if (Rect.right > xScrn) Rect.right = xScrn;
if (Rect.bottom > yScrn) Rect.bottom = yScrn;
//
hBitmap = CreateCompatibleBitmap(hScrDC, Rect.Width(),Rect.Height());
hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
BitBlt(hMemDC,0,0,Rect.Width(),Rect.Height(),hScrDC,Rect.left,Rect.top,SRCCOPY);
hBitmap =(HBITMAP)SelectObject(hMemDC,hOldBitmap);
//
DeleteDC(hScrDC);
DeleteDC(hMemDC);
//
return hBitmap;
}
///////
BOOL SaveBitmapToFile(HBITMAP hBitmap, LPCSTR lpszFileName)
{
HDC hDC; //设备描述表
int iBits; //当前显示分辨率下每个像素所占字节数
WORD wBitCount; //位图中每个像素所占字节数
//定义调色板大小, 位图中像素字节大小 , 位图文件大小 , 写入文件字节数
DWORD dwPaletteSize=0,dwBmBitsSize,dwDIBSize, dwWritten;
BITMAP Bitmap; //位图属性结构
BITMAPFILEHEADER bmfHdr; //位图文件头结构
BITMAPINFOHEADER bi;//位图信息头结构
LPBITMAPINFOHEADER lpbi; //指向位图信息头结构
HANDLE fh, hDib, hPal;
HPALETTE hOldPal=NULL;//定义文件,分配内存句柄,调色板句柄
//计算位图文件每个像素所占字节数
hDC = CreateDC("DISPLAY",NULL,NULL,NULL);
iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES); //?
DeleteDC(hDC);
if (iBits <= 1) wBitCount = 1;
else if (iBits <= 4) wBitCount = 4;
else if (iBits <= 8) wBitCount = 8;
else if (iBits <= 24) wBitCount = 24;
else wBitCount = 32;
//计算调色板大小
if (wBitCount <= 8) dwPaletteSize=(1 << wBitCount)*sizeof(RGBQUAD);
//设置位图信息头结构
GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = Bitmap.bmWidth;
bi.biHeight = Bitmap.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = wBitCount;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
dwBmBitsSize = ((Bitmap.bmWidth*wBitCount+31)/32)*4*Bitmap.bmHeight;
//为位图内容分配内存
hDib = GlobalAlloc(GHND,dwBmBitsSize+dwPaletteSize+sizeof(BITMAPINFOHEADER));
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
*lpbi = bi;
// 处理调色板
hPal = GetStockObject(DEFAULT_PALETTE);
if (hPal)
{
hDC = ::GetDC(NULL);
hOldPal=SelectPalette(hDC,(HPALETTE)hPal,FALSE);
RealizePalette(hDC);
}
// 获取该调色板下新的像素值
GetDIBits(hDC,hBitmap,0,(UINT)Bitmap.bmHeight,(LPSTR)lpbi+sizeof(BITMAPINFOHEADER)+dwPaletteSize, (BITMAPINFO *)lpbi,DIB_RGB_COLORS);
//恢复调色板
if (hOldPal)
{
SelectPalette(hDC, hOldPal, TRUE);
RealizePalette(hDC);
::ReleaseDC(NULL, hDC);
}
//创建位图文件
fh=CreateFile(lpszFileName, GENERIC_WRITE,0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (fh==INVALID_HANDLE_VALUE) return FALSE;
// 设置位图文件头
bmfHdr.bfType = 0x4D42; // "BM"
dwDIBSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+dwPaletteSize+dwBmBitsSize;
bmfHdr.bfSize = dwDIBSize;
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER)+(DWORD)sizeof(BITMAPINFOHEADER)+dwPaletteSize;
// 写入位图文件头
WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
// 写入位图文件其余内容
WriteFile(fh, (LPSTR)lpbi, sizeof(BITMAPINFOHEADER)+dwPaletteSize+dwBmBitsSize , &dwWritten, NULL);
//清除
GlobalUnlock(hDib);
GlobalFree(hDib);
CloseHandle(fh);
return TRUE;
}
调用
void CxxxxDlg::OnButton2()
{
// TODO: Add your control notification handler code here
CRect rc;
GetClientRect(rc);
if(SaveBitmapToFile(CopyScreenToBitmap(rc,m_hWnd),"tmpGl.bmp"))
AfxMessageBox("tmpGl.bmp saved");
}
//
bool ScreenShot(const char* filename)
{
GLenum lastBuffer;
GLbyte* pBits = 0; // data
unsigned long lImageSize;
GLint iViewport[4]; // view
glGetIntegerv(GL_VIEWPORT, iViewport);
lImageSize = iViewport[2] * iViewport[3] * 3;
pBits = (GLbyte*)new unsigned char[lImageSize];
if (!pBits) return false;
// 从color buffer中读取数据
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
glPixelStorei(GL_PACK_SKIP_ROWS, 0);
glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
//
glGetIntegerv(GL_READ_BUFFER, (GLint*)&lastBuffer);
glReadBuffer(GL_FRONT);
glReadPixels(0, 0, iViewport[2], iViewport[3], GL_BGR_EXT, GL_UNSIGNED_BYTE, pBits);
glReadBuffer(lastBuffer);
if (writeBMP(filename,(unsigned char*)pBits,iViewport[2],iViewport[3])) return true;
return false;
}
///////////////////////////////////////////////////
// save
void CxxxxDlg::OnButton2()
{
// TODO: Add your control notification handler code here
if(ScreenShot("Gl.bmp")) AfxMessageBox("Gl.bmp saved");
}
bool writeBMP(const char filename[], unsigned char* data, unsigned int w, unsigned int h)
{
/** 创建位图文件信息和位图文件头结构 */
BITMAPFILEHEADER header;
BITMAPINFOHEADER bitmapInfoHeader;
/** 填充BITMAPFILEHEADER */
header.bfType = 0x4d42;// 'BM'
header.bfSize = w*h*3 + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
header.bfReserved1 = 0;
header.bfReserved2 = 0;
header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
/** 写入位图文件头信息 */
CFile out_file;
out_file.Open(filename,CFile::modeCreate | CFile::modeWrite);
out_file.Write((char*)&header, sizeof(BITMAPFILEHEADER));
/** 填充BITMAPINFOHEADER */
bitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfoHeader.biWidth = w;
bitmapInfoHeader.biHeight = h;
bitmapInfoHeader.biPlanes = 1;
bitmapInfoHeader.biBitCount = 24;
bitmapInfoHeader.biCompression = BI_RGB; // BI_RLE4 BI_RLE8
bitmapInfoHeader.biSizeImage = w * h * 3; // 当压缩类型为BI_RGB是也可以设置为0
bitmapInfoHeader.biXPelsPerMeter = 0;
bitmapInfoHeader.biYPelsPerMeter = 0;
bitmapInfoHeader.biClrUsed = 0;
bitmapInfoHeader.biClrImportant = 0;
/** 写入位图文件信息 */
out_file.Write((char*)&bitmapInfoHeader, sizeof(BITMAPINFOHEADER));
/** 将指针移到数据开始位置 */
out_file.Seek(header.bfOffBits,CFile::begin);
/** 写入图像数据 */
out_file.Write((char*)data, bitmapInfoHeader.biSizeImage);
out_file.Close();
delete [] data;
return true;
}