opengl绘制完成后转储BMP文件

来源:互联网 发布:淘宝知识侵权 编辑:程序博客网 时间:2024/06/06 11:46

在有OpenGL绘制完成后导出BMP文件的需求,可以采用下面代码的方法处理掉.

#include "stdafx.h"#include "PanoramaRead.h"#include "glHelper.h"#include "DumpFile.h"PanoramaRead::PanoramaRead(HDC hdc): PanoramaView(hdc){needSwapBuffers = false;}bool PanoramaRead::init(int w, int h){if (wglGetCurrentDC() == NULL) {if (renderDC != NULL) {if (SetWindowPixelFormat(renderDC) == FALSE)return false;if (CreateViewGLContext(renderDC) == FALSE)return false;}else {int argc = 1;char* argv[] = { "PanoramaRead" };glutInit(&argc, argv);   //初始化glut实用工具库glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);  //启用双缓冲,深度测试glutInitWindowSize(w, h);glutCreateWindow("PanoramaRead");GLenum err = glewInit();  //初始化扩展库if (GLEW_OK != err) {fprintf(stdout, "GLEW Error: %s\n", glewGetErrorString(err));return false;}initGL = true;if (renderDC == NULL) {renderDC = wglGetCurrentDC();}}}else {if (renderDC == NULL) {renderDC = wglGetCurrentDC();}}if (wglGetCurrentDC() == NULL) return false;PanoramaView::init(w,h);return true;}void PanoramaRead::render(unsigned char* buffer, int w, int h, unsigned char * out, int desw, int desh){int targetWidth = desw;int targetHeight = desh;enum { Color, Depth, NumRenderbuffers };GLuint framebuffer_ms, renderbuffer_ms[NumRenderbuffers];//创建渲染缓冲glGenRenderbuffers(NumRenderbuffers, renderbuffer_ms);//申请空间glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer_ms[Color]);glRenderbufferStorageMultisample(GL_RENDERBUFFER, 8, GL_RGB, targetWidth, targetHeight);glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer_ms[Depth]);glRenderbufferStorageMultisample(GL_RENDERBUFFER, 8, GL_DEPTH_COMPONENT24, targetWidth, targetHeight);//创建帧缓冲glGenFramebuffers(1, &framebuffer_ms);glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer_ms);//绑定渲染缓冲存储绘制数据glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer_ms[Color]);glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer_ms[Depth]);//检查帧缓冲状态if (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) {//绘制帧数据glViewport(0, 0, targetWidth, targetHeight);GLenum windowBuff[] = { GL_COLOR_ATTACHMENT0 };glDrawBuffers(1, windowBuff);//glDrawBuffer(GL_COLOR_ATTACHMENT0);glEnable(GL_MULTISAMPLE);//绘制PanoramaView::render(buffer, w, h);}//用于拷贝的帧缓冲区GLuint framebuffer, renderbuffer[NumRenderbuffers];//创建渲染缓冲glGenRenderbuffers(NumRenderbuffers, renderbuffer);glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer[Color]);glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB, targetWidth, targetHeight);glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer[Depth]);glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, targetWidth, targetHeight);//创建帧缓冲glGenFramebuffers(1, &framebuffer);glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);//绑定渲染缓冲存储绘制数据glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer[Color]);glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer[Depth]);//绑定绘制缓冲区为窗口前台帧缓冲区glBindFramebuffer(GL_DRAW_FRAMEBUFFER,NULL);GLenum windowBuff[] = { GL_FRONT, GL_BACK };glDrawBuffers(1, windowBuff);//直接显示至窗口if (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) {//绑定帧缓冲为读取模式glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer_ms);glBlitFramebuffer(0, 0, targetWidth, targetHeight,0, 0, targetWidth, targetHeight,GL_COLOR_BUFFER_BIT, GL_NEAREST);//交换窗口缓冲区if (renderDC != NULL) SwapBuffers(renderDC);}//复制数据至缓冲区glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);GLenum renderBuff[] = { GL_COLOR_ATTACHMENT0};glDrawBuffers(1, renderBuff);if (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) {//绑定帧缓冲为读取模式glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer_ms);//复制数据重写帧缓冲至绘制帧缓冲区glBlitFramebuffer(0, 0, targetWidth, targetHeight,0, 0, targetWidth, targetHeight,GL_COLOR_BUFFER_BIT, GL_NEAREST);glBindFramebuffer(GL_DRAW_FRAMEBUFFER, NULL);//绑定读帧缓冲区glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);//glBindBuffer(GL_PIXEL_PACK_BUFFER, NULL);glReadBuffer(GL_COLOR_ATTACHMENT0);glPixelStorei(GL_PACK_ALIGNMENT, 1);//输出数据if (out != NULL && targetWidth > 0 && targetHeight > 0) {memset(out,0, desw*desh * 3);glReadPixels(0, 0, targetWidth, targetHeight, GL_RGB, GL_UNSIGNED_BYTE, out);DumpBMP(desw, desh, out, desw*desh * 3);}}//清理资源glBindRenderbuffer(GL_RENDERBUFFER, NULL);glBindFramebuffer(GL_READ_FRAMEBUFFER, NULL);glBindFramebuffer(GL_DRAW_FRAMEBUFFER, NULL);glDeleteRenderbuffers(NumRenderbuffers, renderbuffer);glDeleteFramebuffers(1, &framebuffer);glDeleteRenderbuffers(NumRenderbuffers, renderbuffer_ms);glDeleteFramebuffers(1, &framebuffer_ms);}

参数说明:

 unsigned char* buffer:输入图像缓冲区
 int w:输入图像宽 

 int h:输入图像高
 unsigned char * out:输出缓冲区,需自建好
 int desw:输出宽
 int desh:输出高

PanoramaView::render(buffer, w, h);为个人自己的OpenGL绘制函数,在此绘制函数中,开启了双缓冲模式的话请勿使用SwapBuffers,否则后续保存的文件无效


static int index = 0;static void DumpBMP(BITMAPINFOHEADER bmiHeader, BYTE *pBuffer, long lBufferSize){BITMAPFILEHEADER header = { 0 };header.bfType = 0x4D42;header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);header.bfSize = header.bfOffBits + lBufferSize;BYTE * RGB = new BYTE[lBufferSize];memcpy(RGB, pBuffer, lBufferSize);char buffer[1024];sprintf_s(buffer, 1024, "./tmp/%d.bmp", index++);FILE * file = NULL;fopen_s(&file, buffer, "wb+");fwrite(&header, sizeof(BITMAPFILEHEADER), 1, file);fwrite(&bmiHeader, sizeof(BITMAPINFOHEADER), 1, file);for (int i = 0; i < abs(bmiHeader.biHeight); i++) {for (int j = 0; j < bmiHeader.biWidth; j++) {long index = (i*bmiHeader.biWidth + j) * 3;//fwrite(&RGB[index + 2], 1, 1, file);//B//fwrite(&RGB[index + 1], 1, 1, file);//G//fwrite(&RGB[index], 1, 1, file);//RBYTE tmp = RGB[index];RGB[index] = RGB[index + 2];RGB[index + 2] = tmp;}}fwrite(RGB, lBufferSize, 1, file);fclose(file);delete[]RGB;}static void DumpBMP(int width, int height, BYTE *pBuffer, long lBufferSize){BITMAPINFOHEADER bmiHeader = { 0 };bmiHeader.biCompression = BI_RGB;bmiHeader.biBitCount = 24;bmiHeader.biSize = sizeof(BITMAPINFOHEADER);bmiHeader.biWidth = width;bmiHeader.biHeight = -height;bmiHeader.biPlanes = 1;bmiHeader.biSizeImage = width * height * 3;bmiHeader.biClrImportant = 0;DumpBMP(bmiHeader, pBuffer, lBufferSize);}


原创粉丝点击