急!急!急! 求一份将基于MFC渲染的OpenGL场景保存为JPG等图片格式的全代码

sea_ever 2016-04-14 10:54:18
如题,先有基于MFC渲染的一个OpenGL场景,需要保存成图片,需要做成想平时各种软件狗保存时那样,可以在保存时弹出文件对话框,自主选择路径和文件名和格式等,求有好心的大神提供一份完整的代码,小弟感激不尽!!
...全文
255 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
schlafenhamster 2016-04-21
  • 打赏
  • 举报
回复
1.看看 lImageSize = iViewport[2] * iViewport[3] * 3;// = w*h*3 这句有没有问题 2. 把窗口 w 设置为 4的倍数
sea_ever 2016-04-20
  • 打赏
  • 举报
回复
引用 18 楼 zhao4zhong1 的回复:
纠正15楼代码第7行 int alinepixelsbytescount=(w*3+31)/32*4; 应改为 int alinepixelsbytescount=(w*3+3)/4*4;
还是不太对啊 保存的图片使得原来的图的左边有一小块变到右边去了就像“12345”变成了“”23451这样的,图形还有一点形变。。。
赵4老师 2016-04-19
  • 打赏
  • 举报
回复
纠正15楼代码第7行 int alinepixelsbytescount=(w*3+31)/32*4; 应改为 int alinepixelsbytescount=(w*3+3)/4*4;
schlafenhamster 2016-04-18
  • 打赏
  • 举报
回复
前一种 header.bfSize = h*(w*3+31)/32*4 + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); // header.bfSize = w*h*3 + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
schlafenhamster 2016-04-18
  • 打赏
  • 举报
回复
有一句 dwBmBitsSize = ((Bitmap.bmWidth*wBitCount+31)/32)*4*Bitmap.bmHeight;
赵4老师 2016-04-18
  • 打赏
  • 举报
回复
据说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;
}
schlafenhamster 2016-04-17
  • 打赏
  • 举报
回复
writeBMP(const char filename[], 这里 要 改 WCHAR
schlafenhamster 2016-04-17
  • 打赏
  • 举报
回复
前一个方法 在 vc6 win7 上 的 “画图“ 打开是没问题的 !
sea_ever 2016-04-17
  • 打赏
  • 举报
回复
引用 12 楼 schlafenhamster 的回复:
"保存后的图片打开显示图片错误" 用 “画图” 打开看看。 用通用的方法(与 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"); }
这个函数和我要的差距有点大,他会把覆盖在这个区域上的图形也截进去,之前那个函数我发现所保存的图片不能一般的图片浏览器或者画图打开,但是可以用VC打开,图形是没有错的,估计就是格式有错。
schlafenhamster 2016-04-17
  • 打赏
  • 举报
回复
"保存后的图片打开显示图片错误" 用 “画图” 打开看看。 用通用的方法(与 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"); }
sea_ever 2016-04-17
  • 打赏
  • 举报
回复
引用 10 楼 schlafenhamster 的回复:
writeBMP(const char filename[], 这里 要 改 WCHAR
我都不好意思再问了,又出问题了,保存后的图片打开显示图片错误,这是为什么?又给你添麻烦了
sea_ever 2016-04-16
  • 打赏
  • 举报
回复
引用 7 楼 schlafenhamster 的回复:
/////////////////////////////////////////////////// // save void CxxxxDlg::OnButton2() { // TODO: Add your control notification handler code here if(ScreenShot("Gl.bmp")) AfxMessageBox("Gl.bmp saved"); }
我的代码,前面一个加了有错,后面不加有错,我用的是VC2010旗舰版,一般情况双引号的字符串都是要加L的,但是这个加了有错。 if(ScreenShot("Gl.bmp")) AfxMessageBox(L"Gl.bmp saved"); 这个是后面函数的错误: error C2664: “BOOL CFile::Open(LPCTSTR,UINT,CFileException *)”: 不能将参数 1 从“const char []”转换为“LPCTSTR”,代码什么都没改。
schlafenhamster 2016-04-16
  • 打赏
  • 举报
回复
filename 就是 save 后 文件名。 如果 是 Unicode 版本,要 使用 ScreenShot(L"Gl.bmp");
schlafenhamster 2016-04-16
  • 打赏
  • 举报
回复
/////////////////////////////////////////////////// // save void CxxxxDlg::OnButton2() { // TODO: Add your control notification handler code here if(ScreenShot("Gl.bmp")) AfxMessageBox("Gl.bmp saved"); }
sea_ever 2016-04-16
  • 打赏
  • 举报
回复
引用 5 楼 schlafenhamster 的回复:

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那样保存的时候弹出对话框,选择路径和文件名, 还请您费费心,谢谢了
赵4老师 2016-04-15
  • 打赏
  • 举报
回复
学习了!
schlafenhamster 2016-04-15
  • 打赏
  • 举报
回复
参考 保存为 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");
}
schlafenhamster 2016-04-15
  • 打赏
  • 举报
回复

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;
}
sea_ever 2016-04-15
  • 打赏
  • 举报
回复
引用 2 楼 schlafenhamster 的回复:
参考 保存为 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是什么东东
sea_ever 2016-04-14
  • 打赏
  • 举报
回复
求好心的大神给一个代码,最近都要崩溃了,网上各种零零乱乱的说的挺多的,不太懂 现在时间来不及了,只好求一个完整的代码,我的邮箱sea_1215@163.com

15,979

社区成员

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

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