OpenGL导出渲染的图像到外部文件中
需要配置Freeimage库
- 首先下载好FreeImage
- 找打dist目录下的x32目录,将.h文件放在包含目录下;将lib文件放在库目录下,将dll放在运行目录下
保存渲染结果到png格式的图像:
void grab(const char * fileName)
{
unsigned char *mpixels = new unsigned char[SCR_WIDTH * SCR_HEIGHT * 4];//WIDTH和HEIGHT为所要保存的屏幕图像的宽度与高度
glReadBuffer(GL_FRONT);
glReadPixels(0, 0, SCR_WIDTH, SCR_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, mpixels);
glReadBuffer(GL_BACK);
for (int i = 0; i < (int)SCR_WIDTH*SCR_HEIGHT * 4; i += 4)
{
mpixels[i] ^= mpixels[i + 2] ^= mpixels[i] ^= mpixels[i + 2];
}
FIBITMAP* bitmap = FreeImage_Allocate(SCR_WIDTH, SCR_HEIGHT, 32, 8, 8, 8);
for (int y = 0; y < FreeImage_GetHeight(bitmap); y++)
{
BYTE *bits = FreeImage_GetScanLine(bitmap, y);
for (int x = 0; x < FreeImage_GetWidth(bitmap); x++)
{
bits[0] = mpixels[(y*SCR_WIDTH + x) * 4 + 0];
bits[1] = mpixels[(y*SCR_WIDTH + x) * 4 + 1];
bits[2] = mpixels[(y*SCR_WIDTH + x) * 4 + 2];
bits[3] = 255;
bits += 4;
}
}
bool bSuccess = FreeImage_Save(FIF_PNG, bitmap, fileName, PNG_DEFAULT);
FreeImage_Unload(bitmap);
}
保存渲染结果到bmp格式图像中
//抓取窗口中的像素
void grab()
{
FILE* pDummyFile;
FILE* pWritingFile;
GLubyte* pPixelData;
GLubyte BMP_Header[BMP_Header_Length];
GLint i, j;
GLint PixelDataLength;
// 计算像素数据的实际长度
i = SCR_WIDTH * 3; // 得到每一行的像素数据长度
while (i % 4 != 0) // 补充数据,直到 i是的倍数
++i; // 本来还有更快的算法,
// 但这里仅追求直观,对速度没有太高要求
PixelDataLength = i * SCR_HEIGHT;
// 分配内存和打开文件
pPixelData = (GLubyte*)malloc(PixelDataLength);
if (pPixelData == 0)
exit(0);
pDummyFile = fopen("whole.bmp", "rb");//从一个正确的bmp文件中读取前54个字节,修改其中的宽度和高度信息,就可以得到新的文件头
if (pDummyFile == 0)
exit(0);
pWritingFile = fopen("test.bmp", "wb");
if (pWritingFile == 0)
exit(0);
// 读取像素
// GL_UNPACK_ALIGNMENT指定OPenGL如何从数据缓冲区中解包图像数据
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glReadPixels(0, 0, SCR_WIDTH, SCR_HEIGHT, GL_BGR_EXT, GL_UNSIGNED_BYTE, pPixelData);
// 把 whole.bmp 的文件头复制为新文件的文件头
fread(BMP_Header, sizeof(BMP_Header), 1, pDummyFile);
fwrite(BMP_Header, sizeof(BMP_Header), 1, pWritingFile);
fseek(pWritingFile, 0x0012, SEEK_SET);
i = SCR_WIDTH;
j = SCR_HEIGHT;
fwrite(&i, sizeof(i), 1, pWritingFile);
fwrite(&j, sizeof(j), 1, pWritingFile);
fseek(pWritingFile, 0, SEEK_END);
fwrite(pPixelData, PixelDataLength, 1, pWritingFile);
// 释放内存和关闭文件
fclose(pDummyFile);
fclose(pWritingFile);
free(pPixelData);
}
不使用FreeImage库保存渲染结果到bitmap图像的实现(存在bug):
void saveSceneImage(const char * fileName)
{
GLint ViewPort[4];
glGetIntegerv(GL_VIEWPORT, ViewPort);
GLsizei ColorChannel = 3;
GLsizei bufferSize = ViewPort[2] * ViewPort[3] * sizeof(GLubyte)*ColorChannel;
GLubyte * ImgData = (GLubyte*)malloc(bufferSize);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glReadPixels(ViewPort[0], ViewPort[1], ViewPort[2], ViewPort[3], GL_BGR, GL_UNSIGNED_BYTE, ImgData);
FILE * saveTxt = NULL;
saveTxt = fopen("F:\\life\\image\\saveImage.txt", "w");
if (!saveTxt)
{
cout << "Cannot save the RGB value!" << endl;
getchar();
}
for (int i = 0; i < bufferSize / 3; i++)
{
fprintf(saveTxt, "%d %d %d\n", ImgData[3 * i], ImgData[3 * i], ImgData[3 * i]);
}
BITMAPFILEHEADER hdr;
BITMAPINFOHEADER infoHdr;
infoHdr.biSize = sizeof(BITMAPINFOHEADER);
infoHdr.biWidth = ViewPort[2];
infoHdr.biHeight = ViewPort[3];
infoHdr.biPlanes = 1;
infoHdr.biBitCount = 24;
infoHdr.biCompression = 0;
infoHdr.biSizeImage = ViewPort[2] * ViewPort[3] * 3;
infoHdr.biXPelsPerMeter = 0;
infoHdr.biYPelsPerMeter = 0;
infoHdr.biClrUsed = 0;
infoHdr.biClrImportant = 0;
hdr.bfType = 0x4D42;
hdr.bfReserved1 = 0;
hdr.bfReserved2 = 0;
hdr.bfOffBits = 54;
hdr.bfSize = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + ViewPort[2] * ViewPort[3] * 3);
FILE *fid = NULL;
if (!(fid = fopen(fileName, "wb+")))
{
cout << "Cannot load bmp image format!" << endl;
getchar();
}
fwrite(&hdr, 1, sizeof(BITMAPFILEHEADER), fid);
fwrite(&infoHdr, 1, sizeof(BITMAPINFOHEADER), fid);
fwrite(ImgData, 1, ViewPort[2] * ViewPort[2] * 3, fid);
fclose(fid);
free(ImgData);
cout << "Finished!!!" << endl;
}
OpenGL导出渲染的图像到外部文件中的更多相关文章
- CAD二次开发---导入外部文件中的块并输出预览图形(五)
思路: 1)首先要定义一个数据库对象来表示包含块的文件,改数据库对象会被加载到内存中,但不会被显示在CAD窗口中. 2)调用Database类的ReadDwgFile函数将外部文件DWG文件读入到新创 ...
- AngularJS 外部文件中的控制器
在大型的应用程序中,通常是把控制器存储在外部的文件中. <!DOCTYPE html><html><head><meta http-equiv="C ...
- postman引用外部文件中的变量和数据
接口参数显示: 点击collections下文件夹test0424右边的箭头,点击run按钮: DataFile导入txt文件: 预览文件数据: 运行,成功:
- AngularJS 外部文件中的控制器其他实例
<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...
- Perl调用和管理外部文件中的变量(如软件和数据库配置文件)
编写流程时,有一个好的习惯是将流程需要调用的软件.数据库等信息与脚本进行分离,这样可以统一管理流程的软件和数据库等信息,当它们路径改变或者升级的时候管理起来就很方便,而不需要去脚本中一个个寻找再修改. ...
- 1.4.2 solr字段类型--(1.4.2.6)使用外部文件和程序
1.4.2 solr字段类型 (1.4.2.1) 字段类型定义和字段类型属性. (1.4.2.2) solr附带的字段类型 (1.4.2.3) 使用货币和汇率 (1.4.2.4) 使用Dates(日期 ...
- 外部式css样式,写在单独的一个文件中
外部式css样式(也可称为外联式)就是把css代码写一个单独的外部文件中,这个css样式文件以“.css”为扩展名,在<head>内(不是在<style>标签内)使用<l ...
- PHP自学2——将用户提交表单存储到外部普通文件中
在上一节中我们已经实现了将用户的订单信息提交到服务器端,然后服务器端将提交信息返回并显示到页面上.这一节将把上一节用户的订单信息保存到外部的普通文件中(即.txt文本文件中). 本节代码将用户提交的订 ...
- Spring 后置处理器 PropertyPlaceholderConfigurer 类(引用外部文件)
一.PropertyPlaceholderConfigurer类的作用 PropertyPlaceholderConfigurer 是 BeanFactory 后置处理器的实现,也是 BeanFact ...
随机推荐
- Educational Codeforces Round 89 (Rated for Div. 2) B. Shuffle(数学/双指针)
题目链接:https://codeforces.com/contest/1366/problem/B 题意 大小为 $n$ 的数组 $a$,除了 $a_x = 1$,其余 $a_i = 0$,依次给出 ...
- hdu1004 Let the Balloon Rise
Problem Description Contest time again! How excited it is to see balloons floating around. But to te ...
- 牛客练习赛63 C.牛牛的揠苗助长
题意:有一个长度为\(n\)的数组,从第一天开始,第\(i\)天可以使\(i\)位置上的数\(+1\),当\(i=n\)时,下次从\(i=1\)再开始,另外,在每天结束时,你可以使任意一个位置上的数\ ...
- 牛客小白月赛28 D.位运算之谜 (位运算)
题意:给你两个正整数\(x\)和\(y\),求两个正整数\(a\),\(b\),使得\(a+b=x\),\(a\)&\(b\)=\(y\),如果\(a\),\(b\),输出\(a\ xor \ ...
- 二叉树增删改查 && 程序实现
二叉排序树定义 一棵空树,或者是具有下列性质的二叉树:(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值:(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值:(3)左.右子树也 ...
- C#程序报找不到时区错误
原因:win10电脑里的时区在win7里不全有 解决:将win10时区注册表导出,在win7电脑上安装 时区注册表路径:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Wi ...
- log4net GetLogger(source).IsInfoEnabled = false
GetLogger(source).IsInfoEnabled = false解决办法 在.net core中需要把log4net.config放到 ITCP.Web\ITCP.Web\obj\Rel ...
- XV6学习(14)Lab fs: File system
代码在github上. 这次实验是要对文件系统修改,使其支持更大的文件以及符号链接,实验本身并不是很复杂.但文件系统可以说是XV6中最复杂的部分,整个文件系统包括了七层:文件描述符,路径名,目录,in ...
- OpenStack Train版-7.neutron网络服务概述
网络服务NEUTRON概述 一.NEUTRON架构 OpenStack的网络服务neutron是整个OpenStack中最复杂的一个部分,它的基本架构是一个中心服务(neutron-server)外加 ...
- MySQL 企业案例:误删核心业务表
问题描述: 1.正在运行的网站系统,MySQL 数据库,数据量 25G,日业务增量 10 - 15M 2.备份策略:每天 23:00,计划任务调用 mysqldump 执行全备脚本 3.故障时间点:上 ...