急!急!急! 求一份将基于MFC渲染的OpenGL场景保存为JPG等图片格式的全代码 如题,先有基于MFC渲染的一个OpenGL场景,需要保存成图片,需要做成想平时各种软件狗保存时那样,可以在保存时弹出文件对话框,自主选择路径和文件名和格式等,求有好心的大神提供一份完整的代码,小弟感激不尽!! 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 参考保存为 bmp 的//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;}///////////////////////////////////////////////////// savevoid CxxxxDlg::OnButton2() { // TODO: Add your control notification handler code here if(ScreenShot("Gl.bmp")) AfxMessageBox("Gl.bmp saved");} writeBMP是什么东东 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;} 不太懂你这个函数 out_file.Open(filename,CFile::modeCreate | CFile::modeWrite); 第一个参数报错,我强制转换后 程序可以运行,但是不知道保存在哪的,而且我想要想GDI里面调用DoModal那样保存的时候弹出对话框,选择路径和文件名, 还请您费费心,谢谢了 ///////////////////////////////////////////////////// savevoid CxxxxDlg::OnButton2() { // TODO: Add your control notification handler code here if(ScreenShot("Gl.bmp")) AfxMessageBox("Gl.bmp saved");} filename 就是 save 后 文件名。如果 是 Unicode 版本,要 使用 ScreenShot(L"Gl.bmp"); 我的代码,前面一个加了有错,后面不加有错,我用的是VC2010旗舰版,一般情况双引号的字符串都是要加L的,但是这个加了有错。if(ScreenShot("Gl.bmp")) AfxMessageBox(L"Gl.bmp saved");这个是后面函数的错误:error C2664: “BOOL CFile::Open(LPCTSTR,UINT,CFileException *)”: 不能将参数 1 从“const char []”转换为“LPCTSTR”,代码什么都没改。 writeBMP(const char filename[], 这里 要 改 WCHAR "保存后的图片打开显示图片错误"用 “画图” 打开看看。用通用的方法(与 GL 无关) 截图 是//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");} 前一个方法 在 vc6 win7 上 的 “画图“ 打开是没问题的 ! 据说bmp每行像素数据的字节数必须是4的倍数,不足需要补1到3个0: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;} 有一句 dwBmBitsSize = ((Bitmap.bmWidth*wBitCount+31)/32)*4*Bitmap.bmHeight; 前一种 header.bfSize = h*(w*3+31)/32*4 + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); // header.bfSize = w*h*3 + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); 纠正15楼代码第7行 int alinepixelsbytescount=(w*3+31)/32*4;应改为 int alinepixelsbytescount=(w*3+3)/4*4; 1.看看 lImageSize = iViewport[2] * iViewport[3] * 3;// = w*h*3这句有没有问题2. 把窗口 w 设置为 4的倍数 奇怪!为什么程序在某处打断点时运行的结果正常,不在该处打断点时运行的结果就不正常了? 怎么同时打开两张图片 关于N元移位进位反馈寄存器的密码学原理 100分白送,要的快来。 网络俄罗斯方块 问个保存文件名的问题 关于对话框中菜单的显示 有没有带树型数据网格的控件,最好是开放源码? 如何用WORD文档来调式COM 求大神。。。vs2010连sql2008r2连不上 在看一个SOCKET编程 发现当服务器端关闭之后还会调用以下代码,但是不明白为什么要这样做 新手求助一个mfc statictext的问题
保存为 bmp 的//
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");
}
writeBMP是什么东东
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;
}
// save
void CxxxxDlg::OnButton2()
{
// TODO: Add your control notification handler code here
if(ScreenShot("Gl.bmp")) AfxMessageBox("Gl.bmp saved");
}
如果 是 Unicode 版本,要 使用
ScreenShot(L"Gl.bmp");
if(ScreenShot("Gl.bmp")) AfxMessageBox(L"Gl.bmp saved");
这个是后面函数的错误:
error C2664: “BOOL CFile::Open(LPCTSTR,UINT,CFileException *)”: 不能将参数 1 从“const char []”转换为“LPCTSTR”,代码什么都没改。
用 “画图” 打开看看。用通用的方法(与 GL 无关) 截图 是//
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 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;
}
dwBmBitsSize = ((Bitmap.bmWidth*wBitCount+31)/32)*4*Bitmap.bmHeight;
header.bfSize = h*(w*3+31)/32*4 + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
// header.bfSize = w*h*3 + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
int alinepixelsbytescount=(w*3+31)/32*4;
应改为
int alinepixelsbytescount=(w*3+3)/4*4;
lImageSize = iViewport[2] * iViewport[3] * 3;// = w*h*3
这句有没有问题
2. 把窗口 w 设置为 4的倍数