opengl 保存渲染好的图像

在前面的文章中,我已经可以将媒体文件通过opengl来进行显示。

opengl 在显示的YUV视频序列上画多个框

opengl 显示BMP图像

如果希望将blend,或者其他方法处理过之后的图像数据保存为图像文件,该如何做呢?

这个时候我们就要用到glReadPixels函数,GPU渲染完数据在显存,回传内存的唯一方式glReadPixels函数,glReadPixels:读取一些像素。当前可以简单理解为“把已经绘制好的像素(它可能已经被保存到显卡的显存中)读取到内存”

 

如果使用了双缓冲区,则默认是从正在显示的缓冲(即前缓冲)中读取,而绘制工作是默认绘制到后缓冲区的。因此,如果需要读取已经绘制好的像素,往往需要先交换前后缓冲。

代码如下:

BOOL WriteBitmapFile(char * filename, int wid, int hei, unsigned char * bitmapData)
{
	int width = wid;
	int height = hei;

	BITMAPFILEHEADER bitmapFileHeader;
	memset(&bitmapFileHeader, 0, sizeof(BITMAPFILEHEADER));
	bitmapFileHeader.bfSize = sizeof(BITMAPFILEHEADER);
	bitmapFileHeader.bfType = 0x4d42;	//BM
	bitmapFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

	//填充BITMAPINFOHEADER
	BITMAPINFOHEADER bitmapInfoHeader;
	memset(&bitmapInfoHeader, 0, sizeof(BITMAPINFOHEADER));
	bitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
	bitmapInfoHeader.biWidth = width;
	bitmapInfoHeader.biHeight = height;
	bitmapInfoHeader.biPlanes = 1;
	bitmapInfoHeader.biBitCount = 24;
	bitmapInfoHeader.biCompression = BI_RGB;
	bitmapInfoHeader.biSizeImage = width * abs(height) * 3;

	//
	FILE * filePtr;
	unsigned char tempRGB;
	int imageIdx;

	//swap R B
	for (imageIdx = 0; imageIdx < bitmapInfoHeader.biSizeImage; imageIdx += 3)
	{
		tempRGB = bitmapData[imageIdx];
		bitmapData[imageIdx] = bitmapData[imageIdx + 2];
		bitmapData[imageIdx + 2] = tempRGB;
	}

	filePtr = fopen(filename, "wb");
	if (NULL == filePtr)
	{
		return FALSE;
	}

	fwrite(&bitmapFileHeader, sizeof(BITMAPFILEHEADER), 1, filePtr);

	fwrite(&bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, filePtr);

	fwrite(bitmapData, bitmapInfoHeader.biSizeImage, 1, filePtr);

	fclose(filePtr);
	return TRUE;
}


void snap_shot(int img_w, int img_h)
{
	GLubyte* pPixelData;
	GLint line_width;
	GLint PixelDataLength;

	line_width = img_w * 3; // 得到每一行的像素数据长度 
	line_width = (line_width + 3) / 4 * 4;
	
	PixelDataLength = line_width * img_h;

	// 分配内存和打开文件 
	pPixelData = (GLubyte*)malloc(PixelDataLength);
	if (pPixelData == 0)
		exit(0);


	// 读取像素 
	glPixelStorei(GL_UNPACK_ALIGNMENT, 4);

	//glReadPixels(0, 0, img_w, img_h, GL_BGR_EXT, GL_UNSIGNED_BYTE, pPixelData);
	glReadPixels(0, 0, img_w, img_h, GL_RGB, GL_UNSIGNED_BYTE, pPixelData);

	
	WriteBitmapFile("snapshot.bmp", img_w, img_h, pPixelData);
	free(pPixelData);
}

 

OpenGL中进行离屏渲染通常使用EGL来实现。EGL是一个跨平台的图形库,可以在不同的操作系统和图形硬件上运行。以下是一个简单的示例代码,说明如何使用EGL进行离屏渲染: ```c++ #include <EGL/egl.h> #include <GLES2/gl2.h> void RenderOffscreen() { // 创建EGLDisplay EGLDisplay eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); EGLint major, minor; eglInitialize(eglDisplay, &major, &minor); // 配置EGLContext属性 EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; // 创建EGLContext EGLConfig config; EGLint numConfigs; EGLint attribs[] = { EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_DEPTH_SIZE, 0, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE }; eglChooseConfig(eglDisplay, attribs, &config, 1, &numConfigs); EGLSurface eglSurface = eglCreatePbufferSurface(eglDisplay, config, NULL); EGLContext eglContext = eglCreateContext(eglDisplay, config, NULL, contextAttribs); // 绑定EGLContext和EGLSurface eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext); // 在离屏上下文中进行渲染 glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); // 将渲染结果保存到文件或内存中 // ... // 解绑EGLContext和EGLSurface eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); // 销毁EGLContext和EGLSurface eglDestroySurface(eglDisplay, eglSurface); eglDestroyContext(eglDisplay, eglContext); // 终止EGLDisplay eglTerminate(eglDisplay); } int main() { // 在主上下文中进行渲染 // ... // 在离屏上下文中进行渲染 RenderOffscreen(); return 0; } ``` 在上面的示例代码中,我们使用EGL创建一个离屏上下文和表面,使用glClear()函数在离屏上下文中进行渲染,然后将渲染结果保存到文件或内存中。最后,我们销毁离屏上下文和表面,终止EGLDisplay。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值