精华内容
下载资源
问答
  • OpenGL 绘制效果保存成图片

    千次阅读 2018-11-14 01:04:01
    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

    这里写图片描述
    展开全文
  • OpenGL图片效果处理(四)

    千次阅读 2018-06-30 23:33:08
    上一章节,给大家介绍了图片色彩处理,这一章节,我给大家介绍一下图片效果处理。图片效果处理包括:这里主要讲图片模糊处理(高斯模糊,马赛克,膨胀,腐蚀,增强对比度)。原理:通过对采样点进行处理,是采样点和...

    上一章节,给大家介绍了图片色彩处理,这一章节,我给大家介绍一下图片效果处理。

    图片效果处理包括:这里主要讲图片模糊处理(高斯模糊,马赛克,膨胀,腐蚀,增强对比度)。

    原理:通过对采样点进行处理,是采样点和周围点之间产生某种数学联系,改变采样点的色值,从而达到预期效果。

    具体实现,主要改变片元着色器里面gl_FragColor的值来达到效果,这里列出具体的计算过程,其它同上一章内容:

    1、高斯模糊:

                float  block=150.0;
                float  delta=1.0/block;
                vec4 color=vec4(0.0);
                //权重
                float factor[9];
                factor[0]=1.0; factor[1]=1.0; factor[2]=1.0;
                factor[3]=1.0; factor[4]=1.0; factor[5]=1.0;
                factor[6]=1.0; factor[7]=1.0; factor[8]=1.0;
                  for(int i=-1;i<=1;i++){//三次
                   for(int j=-1;j<=1;j++){//三次
                     float x=max(0.0,aCoordinate.x+float(i)*delta);
                     float y=max(0.0,aCoordinate.y+float(i)*delta);
                     color+= texture2D(vTexture,vec2(x,y)*factor[(i+1)*3+(j+1)]);
                   }
                  }
                color=color/9.0;

                gl_FragColor=vec4(vec3(color),1.0);

    2、马赛克效果:

                    //把图像进行分割分割成若干份,然后用马赛克填充
                     vec2 texSize =vec2(400.0,400.0);
                     vec2 mosaicSize=vec2(8.0,8.0);
                     //混合纹理
                     vec2 intXY=vec2(aCoordinate.x*texSize.x,aCoordinate.y*texSize.y);
                     vec2  XYmosaic=vec2(floor(intXY.x/mosaicSize.x)*mosaicSize.x
                                    ,floor(intXY.y/mosaicSize.y)*mosaicSize.y);
                     vec2  Umosaic=vec2( XYmosaic.x/texSize.x,XYmosaic.y/texSize.y);

                    gl_FragColor = texture2D( vTexture,Umosaic);

    3、膨胀效果:

          //寻找周围点
                float  block=500.0;
                float  delta=1.0/block;
                  vec4 maxColor=vec4(-1.0);
                for(int i=-1;i<=1;i++){//三次
                    for(int j=-1;j<=1;j++){//三次
                      float x=(aCoordinate.x+float(i)*delta);
                      float y=(aCoordinate.y+float(i)*delta);
                        //寻找最亮点,代替周围点
                      maxColor=max(maxColor,texture2D(vTexture,vec2(x,y)));
                    }
                }

                gl_FragColor=maxColor;

    4、腐蚀效果:

     //寻找周围点
                        float  block=500.0;
                        float  delta=1.0/block;
                          vec4 maxColor=vec4(1.0);
                        for(int i=-1;i<=1;i++){//三次
                            for(int j=-1;j<=1;j++){//三次
                              float x=(aCoordinate.x+float(i)*delta);
                              float y=(aCoordinate.y+float(i)*delta);
                                //寻找最暗点,代替周围点
                              maxColor=min(texture2D(vTexture,vec2(x,y)),maxColor);
                            }
                        }

                        gl_FragColor=maxColor;

    5、增强对比度:

        float a=0.5;
         vec3 y=nColor.rgb;
         vec3 x=vec3(0.0,0.0,0.0);
        //   增强对比度函数:mix(x,y,a)=x*(1-a)+y*a
         gl_FragColor =  vec4(mix(x,y,a),1.0);

    展开全文
  • OpenGL镜面效果

    千次阅读 2015-08-30 19:14:11
    我们这一节的效果图如下: 我们会给每个模型贴上纹理图,纹理图的使用上一节已经讲过了,我们会实现一个镜面的效果,如上图,每个模型下面都有一...然后把改变多边形的正面,OpenGl默认的多边形的正面是逆时针的,

    我们这一节的效果图如下:



    我们会给每个模型贴上纹理图,纹理图的使用上一节已经讲过了,我们会实现一个镜面的效果,如上图,每个模型下面都有一个像是通过镜子反射的模型一样。

    其实做法很简单,我们只需要把原来的视口矩阵反转如下的代码

    modelViewMatrix.Scale(1.0f, -1.0f, 1.0f);

    然后把改变多边形的正面,OpenGl默认的多边形的正面是逆时针的,我们在这里改为顺时针,如下代码

    glFrontFace(GL_CW);

    然后绘制镜面中的物体,绘制完成后把多边形的正面再改回逆时针的

    glFrontFace(GL_CCW);

    然后我们绘制地板,并且和刚才绘制的镜面中的物体进行混合操作

    最后我们再绘制地面上的物体,这样就实现的镜面效果


    下面是代码实现

    首先是需要包含的头文件 和全局变量

    #include <GLTools.h>
    #include <GLShaderManager.h>
    #include <GLFrustum.h>
    #include <GLBatch.h>
    #include <GLMatrixStack.h>
    #include <GLGeometryTransform.h>
    #include <StopWatch.h>
    
    #include <math.h>
    #include <stdio.h>
    
    #define FREEGLUT_STATIC
    #include <GL/glut.h>
    
    #define NUM_SPHERES 50
    GLFrame spheres[NUM_SPHERES];
    
    GLShaderManager		shaderManager;			
    GLMatrixStack		modelViewMatrix;	
    GLMatrixStack		projectionMatrix;		
    GLFrustum			viewFrustum;			
    GLGeometryTransform	transformPipeline;		
    GLFrame				cameraFrame;			
    
    GLTriangleBatch		torusBatch;
    GLTriangleBatch		sphereBatch;
    GLBatch				floorBatch;
    
    GLuint				uiTextures[3];


    然后是主函数main

    int main(int argc, char* argv[])
        {
    
    		//设置工作路径
    		gltSetWorkingDirectory(argv[0]);
    		//初始化glut
    		glutInit(&argc, argv);
    		//申请一个带有双缓冲区,颜色缓冲区的窗口
    		glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    		//窗口大小
    		glutInitWindowSize(800, 600);
    		//窗口名字
    		glutCreateWindow("OpenGL SphereWorld");
    		//窗口大小改变时的回调函数
    		glutReshapeFunc(ChangeSize);
    		//键盘按键响应函数
    		glutSpecialFunc(SpecialKeys);
    		//渲染的回调函数
    		glutDisplayFunc(RenderScene);
    
    		GLenum err = glewInit();
    		if (GLEW_OK != err) {
    			fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
    			return 1;
    		}
    
    		//初始化函数
    		SetupRC();
    		//主函数循环
    		glutMainLoop();
    		//循环结束后释放内存
    		ShutdownRC();
    
    		return 0;
        }


    然后是窗口改变大小时的回调函数ChangeSize

    void ChangeSize(int nWidth, int nHeight)
        {
    		//设置视口大小
    		glViewport(0, 0, nWidth, nHeight);
    		//将视图变换矩阵 和 模型 变换矩阵统一管理起来
    		transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
    		//设置视口变换矩阵
    		viewFrustum.SetPerspective(35.0f, float(nWidth) / float(nHeight), 1.0f, 100.0f);
    		//设置模型变换矩阵
    		projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
    		//设置视图变换矩阵
    		modelViewMatrix.LoadIdentity();
    	}


    然后是响应键盘方向键的函数SpecialKeys

    void SpecialKeys(int key, int x, int y)
        {
    		float linear = 0.1f;
    		float angular = float(m3dDegToRad(5.0f));
    
    		if (key == GLUT_KEY_UP)
    			cameraFrame.MoveForward(linear);
    
    		if (key == GLUT_KEY_DOWN)
    			cameraFrame.MoveForward(-linear);
    
    		if (key == GLUT_KEY_LEFT)
    			cameraFrame.RotateWorld(angular, 0.0f, 1.0f, 0.0f);
    
    		if (key == GLUT_KEY_RIGHT)
    			cameraFrame.RotateWorld(-angular, 0.0f, 1.0f, 0.0f);
        }


    下面是初始化函数SetupRC

    void SetupRC()
        {
    		//初始化glew
    		glewInit();
    		//初始化着色器管理类
    		shaderManager.InitializeStockShaders();
    		//开启深度测试
    		glEnable(GL_DEPTH_TEST);
    		//开启剔除
    		glEnable(GL_CULL_FACE);
    		//清除后台缓存	
    		glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    	
    		// 初始化泳圈模型
    		gltMakeTorus(torusBatch, 0.4f, 0.15f, 40, 20);
    	
    		// 初始化小球模型
    		gltMakeSphere(sphereBatch, 0.1f, 26, 13);
    	
    		//初始化地板数据
    		GLfloat texSize = 10.0f;
    		floorBatch.Begin(GL_TRIANGLE_FAN, 4, 1);
    		floorBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
    		floorBatch.Vertex3f(-20.0f, -0.41f, 20.0f);
    	
    		floorBatch.MultiTexCoord2f(0, texSize, 0.0f);
    		floorBatch.Vertex3f(20.0f, -0.41f, 20.0f);
    	
    		floorBatch.MultiTexCoord2f(0, texSize, texSize);
    		floorBatch.Vertex3f(20.0f, -0.41f, -20.0f);
    	
    		floorBatch.MultiTexCoord2f(0, 0.0f, texSize);
    		floorBatch.Vertex3f(-20.0f, -0.41f, -20.0f);
    		floorBatch.End();
    	
    		// 创建3个纹理对象
    		glGenTextures(3, uiTextures);
    	
    		// 绑定纹理1对象
    		glBindTexture(GL_TEXTURE_2D, uiTextures[0]);
    		LoadTGATexture("marble.tga", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_REPEAT);
    	
    		// 绑定纹理2对象
    		glBindTexture(GL_TEXTURE_2D, uiTextures[1]);
    		LoadTGATexture("marslike.tga", GL_LINEAR_MIPMAP_LINEAR, 
    					   GL_LINEAR, GL_CLAMP_TO_EDGE);
    	
    		// 绑定纹理3对象
    		glBindTexture(GL_TEXTURE_2D, uiTextures[2]);
    		LoadTGATexture("moonlike.tga", GL_LINEAR_MIPMAP_LINEAR,
    					   GL_LINEAR, GL_CLAMP_TO_EDGE);
                       
    		// 设置50个小球的位置
    		for(int i = 0; i < NUM_SPHERES; i++) 
    			{
    				GLfloat x = ((GLfloat)((rand() % 400) - 200) * 0.1f);
    				GLfloat z = ((GLfloat)((rand() % 400) - 200) * 0.1f);
    				spheres[i].SetOrigin(x, 0.0f, z);
    			}
        }

    下面是加载纹理图片的函数LoadTGATexture

    bool LoadTGATexture(const char *szFileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode)
    	{
    		GLbyte *pBits;
    		int nWidth, nHeight, nComponents;
    		GLenum eFormat;
    	
    		//读取纹理数据
    		pBits = gltReadTGABits(szFileName, &nWidth, &nHeight, &nComponents, &eFormat);
    		if(pBits == NULL) 
    			return false;
    		//设置纹理环绕模式
    		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
    		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);
    		//设置纹理过滤模式
    		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
    		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
    		//开启紧密包装像素数据模式
    		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    		//生成纹理图片
    		glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB, nWidth, nHeight, 0,
    					 eFormat, GL_UNSIGNED_BYTE, pBits);
    	
    		free(pBits);
    		//创建Mip贴图
    		if(minFilter == GL_LINEAR_MIPMAP_LINEAR || 
    		   minFilter == GL_LINEAR_MIPMAP_NEAREST ||
    		   minFilter == GL_NEAREST_MIPMAP_LINEAR ||
    		   minFilter == GL_NEAREST_MIPMAP_NEAREST)
    			glGenerateMipmap(GL_TEXTURE_2D);
                
    		return true;
    	}

    下面是具体绘制模型的函数DrawSongAndDance

    void DrawSongAndDance(GLfloat yRot)		// Called to draw dancing objects
    	{
    		static GLfloat vWhite[] = { 1.0f, 1.0f, 1.0f, 1.0f };
    		static GLfloat vLightPos[] = { 0.0f, 3.0f, 0.0f, 1.0f };
    	
    		// 得到光源位置
    		M3DVector4f	vLightTransformed;
    		M3DMatrix44f mCamera;
    		modelViewMatrix.GetMatrix(mCamera);
    		m3dTransformVector4(vLightTransformed, vLightPos, mCamera);
    	
    		// 绘制光源
    		modelViewMatrix.PushMatrix();
    		modelViewMatrix.Translatev(vLightPos);
    		shaderManager.UseStockShader(GLT_SHADER_FLAT, 
    									 transformPipeline.GetModelViewProjectionMatrix(),
    									 vWhite);
    		sphereBatch.Draw();
    		modelViewMatrix.PopMatrix();
        
    		//渲染50个静止的小球
    		glBindTexture(GL_TEXTURE_2D, uiTextures[2]);
    		for(int i = 0; i < NUM_SPHERES; i++) {
    			modelViewMatrix.PushMatrix();
    			modelViewMatrix.MultMatrix(spheres[i]);
    			shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
    										 modelViewMatrix.GetMatrix(),
    										 transformPipeline.GetProjectionMatrix(),
    										 vLightTransformed, 
    										 vWhite,
    										 0);
    			sphereBatch.Draw();
    			modelViewMatrix.PopMatrix();
    		}
    
    		modelViewMatrix.Translate(0.0f, 0.2f, -2.5f);
    		modelViewMatrix.PushMatrix();	// Saves the translated origin
    		modelViewMatrix.Rotate(yRot, 0.0f, 1.0f, 0.0f);
    	
    		//绑定泳圈模型的纹理对象
    		glBindTexture(GL_TEXTURE_2D, uiTextures[1]);
    		//绘制泳圈模型
    		shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
    									 modelViewMatrix.GetMatrix(),
    									 transformPipeline.GetProjectionMatrix(),
    									 vLightTransformed, 
    									 vWhite,
    									 0);
    		torusBatch.Draw();
    		modelViewMatrix.PopMatrix(); // Erased the rotate
    	
    		modelViewMatrix.Rotate(yRot * -2.0f, 0.0f, 1.0f, 0.0f);
    		modelViewMatrix.Translate(0.8f, 0.0f, 0.0f);
    	
    		//绘制旋转的小球
    		glBindTexture(GL_TEXTURE_2D, uiTextures[2]);
    		shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
    									 modelViewMatrix.GetMatrix(),
    									 transformPipeline.GetProjectionMatrix(),
    									 vLightTransformed, 
    									 vWhite,
    									 0);
    		sphereBatch.Draw();
    	}

    下面是程序退出时执行的清理函数ShutdownRC

    void ShutdownRC(void)
        {
    		//释放纹理对象
    		glDeleteTextures(3, uiTextures);
        }


    基本上每一行代码都有注释,有哪里看不懂的童鞋,我们可以一起讨论 ):











    展开全文
  • android平台上,用opengl es实现图片的波浪效果,可点击图片产生多个波浪
  • android 翻书效果,上下角是贝塞尔曲线,中间是卷曲效果,接入简单,本地和网络图片均可,效果不错,已项目实战。
  • opengl es shader 图像处理资源。实现很多种效果。有需要的可以下载
  • OpenGL: 绘制效果保存成图片

    万次阅读 2014-02-25 13:48:32
    要将opengl的绘制场景保存成图片,也需要使用这个函数。 一个简单的例子见如下的c程序。按键盘上的“C”键,可以将读取的图像缓冲区数据存储成tmpcolor.txt。#include "windows.h" #include #include #include us...
     
      
     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的像素格式只支持RGBA
    
    glReadPixels(viewPort[0], viewPort[1], viewPort[2], viewPort[3], GL_RGBA, GL_UNSIGNED_BYTE, colorArr); // RGBA
    
    printf("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); // RGBA
    plane2Ptr[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");
    }


    展开全文
  • OpenGL实现图片边缘暗角效果(1)

    千次阅读 2017-08-27 20:59:54
    在进行VR视频播放开发的时候,看到如下一段opengl代码,一开始不知道为什么这样做,会产生什么效果。 首先是创建了一个纹理: void createVigTex() { static const int scale = 6; static const int width = 16 * ...
  • 关于图片波浪的效果有很多说明和原理分析,这里用的是cos函数来实现z坐标的位移变化,效果图如下: 附上源码下载链接:点击打开链接
  • 要将opengl的绘制场景保存成图片,也需要使用这个函数。  一个简单的例子见如下的c程序。按键盘上的“C”键,可以将读取的图像缓冲区数据存储成tmpcolor.txt;按键“D”为OpenCV显示。 // OpenGL_OpenCV.cpp : 定义...
  • OpenGL水波纹效果

    2020-06-07 18:50:45
    OpenGL水波纹效果 glsl水波纹效果,可使用shadertoy直接运行。sin和iTime配合得到水波纹mask,通过mask流动变化得到水波纹效果。 脚本1 #iChannel0 "file://./bg0.jpg" // 水波纹中心点 const vec2 center = vec2...
  • Android OpenGLES2.0(九)——利用OpenGL进行图片处理

    万次阅读 热门讨论 2016-10-23 17:57:21
    在之前的博客中我们就有提过OpenGLES的常见应用范围,其中有一个就是图片的处理。为了保证效率,Android手机中许多美颜相机、图片处理应用,都用到了OpenGLES来处理图片。上一篇博客中,我们利用OpenGLES 显示出了...
  • OpenGL 喷泉效果部分解释

    千次阅读 2015-03-18 15:15:04
    PFD_SUPPORT_OPENGL | // 支持 OpenGL PFD_DOUBLEBUFFER, // 双缓存模式 PFD_TYPE_RGBA, // RGBA 颜色模式 24, // 24 位颜色深度 0, 0, 0, 0, 0, 0, // 忽略颜色位 0, // 没有非透明度缓存 0, /...
  • opengl透明mask图片做蒙版效果的实现

    千次阅读 2016-03-29 17:32:52
    (也就是cocos2d-x中那个clipingnode的效果)。看教程和看源码都是第一时间想到用模板测试。。。奈何技术不精还是怎么,效果总是出不来,翻墙,看别人各种实现,中间各种曲折。。后来实在没有办法,发帖问,有个大牛...
  • 使用opengl对水流进行模拟,由于初学,水流效果很粗糙。本人电脑i5 4核,内存4G。水流粒子数5000,没有进行任何加速(没有使用领域搜索法),电脑跑起来只有10fps左右。初学opengl或者光滑粒子流体动力学(sph)的大神...
  • 音视频之opengl渲染图片

    千次阅读 2019-03-16 11:53:44
    音视频之opengl绘制三角形 首先来看看渲染效果 我们先来看看关于纹理的坐标: 他是如下图: 顶点着色器代码:texture_vertext_shader_java_1.glsl attribute vec4 a_Position; attribute vec2 a_Texture...
  • 使用OpenGL实现遮罩效果

    千次阅读 2016-09-22 20:32:12
    本文适合于Cocos2d-X等使用OpenGL API的渲染框架一般实现自定义遮罩效果主要介绍以下几种: 使用Stencil Buffer 使用GL_SCISSOR_TEST(适合矩形区域) 使用Shader 使用BlendFunc(推荐!)
  • 通过OpenGL来显示一张汽车图片图片可以看做一个矩形,所以我们先来画一个矩形OpenGL的基本形状是三角形,一个矩形可以看成由4个三角形构成
  • 本文介绍了如何使用C++语言和OpenGL ES 2.0 API实现纹理图片的叠加显示效果
  • 基于opengl图片处理

    2014-04-10 15:14:15
    display an image with pyopengl and Pillow[/url],就知道单单使用opengl来显示图片太复杂了,但如果你除了显示还做图片处理的话,那就不一样了,这里我给大家介绍一下基于opengl图片处理。 [size=medium]在...
  • 如何使用Android中的OpenGL ES媒体效果

    千次阅读 2015-06-01 15:52:20
    作为这个媒体效果的框架,它使用GPU来处理图片处理的过程,它仅仅接收OpenGL的纹理(texture)作为输入。在本次教程中,你将会学习到如何使用OpenGL ES2.0将图片资源转化为纹理,以及如何使用框架为图片应用不同的...
  • 在Android中使用OpenGL效果渲染

    千次阅读 2016-01-08 11:32:48
      1.介绍 Android的媒体效果框架允许开发者可以很容易的应用...作为这个媒体效果的框架,它使用GPU来处理图片处理的过程,它仅仅接收OpenGL的纹理(texture)作为输入。在本次教程中,你将会学习到如何使用OpenGL
  • OpenGL ES 实现瘦脸大眼效果

    千次阅读 2020-03-16 20:55:13
    旧文中我们用 OpenGL 给小姐姐实现了瘦身和大长腿效果,结果小姐姐眯着眼睛、嘟着嘴说,我需要瘦身和大长腿效果吗? 笔者若有所思地看着她的眼睛和脸庞,终于弄明白了她需要的是什么效果。 言归正传,无论是实现瘦身...
  • 使用OpenGL ES对YUV图片进行显示,流程为先提取YUV数据中的Y,U,V分量,在通过纹理贴图的方式,这样就可以达到显示图片效果
  • 显示的效果却是: ![图片说明](https://img-ask.csdn.net/upload/201508/15/1439633465_796588.png) 我不知道我的代码错在哪了。请有OpenGL开发经验的兄弟帮忙下。我的代码如下: ``` public class ...
  • android平台下OpenGL ES 3.0给图片添加黑白滤镜
  • opengl

    千次阅读 2013-10-25 17:12:20
    强大的可移植性:适用于windows、linux、unix等 ...一般情况下,OpenGL中的点将被画成单个的像素(像素的概念,请自己搜索之~),虽然它可能足够小,但并不会是无穷小。同一像素上,OpenGL可以绘制许多坐标只有

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 25,321
精华内容 10,128
关键字:

opengl图片效果