OpenGL 绘制效果保存成图片

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

                    opengl中有一个非常有用的函数:glReadPixels(),可以读取各种缓冲区(深度、颜色,etc)的数值。要将opengl的绘制场景保存成图片,也需要使用这个函数。
    一个简单的例子见如下的c程序。按键盘上的“C”键,可以将读取的图像缓冲区数据存储成tmpcolor.txt。
#include "windows.h"#include <GL/glut.h>#include <GL/GLAUX.H>#include <iostream>using namespace std;//typedef GLbyte* bytePt;int winWidth = 400;int winHeight = 400;int arrLen = winWidth * winHeight * 3;GLbyte* colorArr = new GLbyte[ arrLen ];void saveColorData(bytePt& _pt, string& _str) {FILE* pFile = NULL;pFile = fopen(_str.c_str(), "wt");if(!pFile) { fprintf(stderr, "error \n"); exit(-1); }for(int i=0; i<winWidth * winHeight * 3; i ++) {if(colorArr[i] == -1) { colorArr[i] = 255; }}for(int i=0; i<winWidth * winHeight * 3; i ++) {fprintf(pFile, "%d\n", colorArr[i]);}fclose(pFile);printf("color data saved! \n");}void init() {glClearColor(0.5, 0.5, 0.5, 0.0);glShadeModel(GL_SMOOTH);}void display() {glClear(GL_COLOR_BUFFER_BIT);glMatrixMode(GL_MODELVIEW);glLoadIdentity();gluLookAt(0.0, 0.0, 100.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(45.0, 1.0, 0.1, 500.0);glMatrixMode(GL_MODELVIEW);glColor3f(1.0, 0.0, 0.0);glBegin(GL_TRIANGLES);glVertex3f(0.0, 25.0, 0.0);glVertex3f(-25.0, -25.0, 0.0);glVertex3f(25.0, -25.0, 0.0);glEnd();glFlush();}void keyboard(unsigned char key, int x , int y) {GLint viewPort[4] = {0};switch(key) {case 'c':case 'C':glGetIntegerv(GL_VIEWPORT, viewPort);glReadPixels(viewPort[0], viewPort[1], viewPort[2], viewPort[3], GL_RGB, GL_UNSIGNED_BYTE, colorArr);printf("color data read !\n");saveColorData(colorArr, (string)"tmpcolor.txt");default:break;}}int main(int argc, char** argv) {glutInit(&argc, argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);glutInitWindowPosition(200, 200);glutInitWindowSize(400, 400);glutCreateWindow(argv[0]);init();glutDisplayFunc(display);glutKeyboardFunc(keyboard);glutMainLoop();delete [] colorArr;return 0;}



    tmpcolor.txt 中将每个像素的颜色按R、G、B顺序存放成了一个向量,即(R,G,B,R,G,B,...)。而且,读取缓冲区时的坐标原点是窗口坐标系的坐标原点(图片左下角);因此,可以在matlab中通过调整得到原来的图片:

function test    a = load('tmpcolor.txt');     pos = find(a == -1);    a(pos) = 255;     r = a(1:3:end);    g = a(2:3:end);    b = a(3:3:end);    img = zeros(400,400,3);    img(:,:,1) = reshape(r,[400,400]);    img(:,:,2) = reshape(g,[400,400]);    img(:,:,3) = reshape(b,[400,400]);    img = uint8(img);        tmpR = zeros(400,400);  tmpR = img(:,:,1);    tmpG = zeros(400,400);  tmpG = img(:,:,2);    tmpB = zeros(400,400);  tmpB = img(:,:,3);        for i=1:1:400        img(i,:,1) = tmpR(:,400-i+1);        img(i,:,2) = tmpG(:,400-i+1);        img(i,:,3) = tmpB(:,400-i+1);    end        figure;    imshow(img);end

    当然,读到数据后,可以直接使用openCV等工具方便地存储图片。一段对应的opencv代码为:
void saveColorData2img(bytePt& _pt, string& _str) {cv::Mat img;vector<cv::Mat> imgPlanes;img.create(winHeight, winWidth, CV_8UC3);cv::split(img, imgPlanes);for(int i = 0; i < winHeight; i ++) {UCHAR* plane0Ptr = imgPlanes[0].ptr<UCHAR>(i);UCHAR* plane1Ptr = imgPlanes[1].ptr<UCHAR>(i);UCHAR* plane2Ptr = imgPlanes[2].ptr<UCHAR>(i);for(int j = 0; j < winWidth; j ++) {int k = 3 * (i * winWidth + j);plane2Ptr[j] = _pt[k];plane1Ptr[j] = _pt[k+1];plane0Ptr[j] = _pt[k+2];}}cv::merge(imgPlanes, img);cv::flip(img, img ,0); // !!!cv::imwrite(_str.c_str(), img);printf("opencv save opengl img done! \n");}

    需要注意的是,如果想要把集成在MFC中的openGL场景转存成图片,因为MFC中的像素格式只支持RGBA和颜色索引,所以 glReadPixels 中需要使用 GL_RGBA 作为参数。对应写了一个C++类,可供参考:

class glGrabber {public:glGrabber();~glGrabber();void glGrab();void saveColorData2Img(string& _str);private:GLbyte* colorArr;GLint viewPort[4];int winWidth;int winHeight;};//glGrabber::glGrabber() {colorArr = NULL;}//glGrabber::~glGrabber() {if(colorArr!=NULL) { delete [] colorArr; colorArr = NULL; }}//void glGrabber::glGrab() {glGetIntegerv(GL_VIEWPORT, viewPort);if(colorArr != NULL) { delete [] colorArr; colorArr = NULL; }winWidth = viewPort[2];winHeight = viewPort[3];colorArr = new GLbyte[ winWidth * winHeight * 4 ]; // MFC的像素格式只支持RGBAglReadPixels(viewPort[0], viewPort[1], viewPort[2], viewPort[3], GL_RGBA, GL_UNSIGNED_BYTE, colorArr); // RGBAprintf("x: %d, y: %d, window width: %d, window height: %d \n", viewPort[0], viewPort[1], viewPort[2], viewPort[3]);printf("color data read! \n");}//void glGrabber::saveColorData2Img(string& _str) {cv::Mat img;vector<cv::Mat> imgPlanes;img.create(winHeight, winWidth, CV_8UC3);cv::split(img, imgPlanes);for(int i = 0; i < winHeight; i ++) {UCHAR* plane0Ptr = imgPlanes[0].ptr<UCHAR>(i);UCHAR* plane1Ptr = imgPlanes[1].ptr<UCHAR>(i);UCHAR* plane2Ptr = imgPlanes[2].ptr<UCHAR>(i);for(int j = 0; j < winWidth; j ++) {int k = 4 * (i * winWidth + j); // RGBAplane2Ptr[j] = colorArr[k];plane1Ptr[j] = colorArr[k+1];plane0Ptr[j] = colorArr[k+2];}}cv::merge(imgPlanes, img);cv::flip(img, img ,0); // !!!cv::namedWindow("openglGrab");cv::imshow("openglGrab", img);cv::waitKey();//cv::imwrite(_str.c_str(), img);printf("opencv save opengl img done! \n");}


           

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow
这里写图片描述
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值