opengl 显示图片以及保存图片

时间:2022-10-23 21:01:00

opengl 的贴图功能是很基本的,不过也难住了我这个新手,所以特意写了一个示例程序,以便以后查阅。


程序很简单,只是在在 x, y 平面画一个框,然后贴上一张图。并且可以保存opengl窗口到图片。


程序:

//本程序的目的是展示贴图和保存图片

#include <Windows.h>
#include <gl/glut.h>

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;

// Rotation amounts
static GLfloat xRot = 0.0f;
static GLfloat yRot = 0.0f;

const int height = 600;
const int width = 800;

static GLbyte TextData[1000*1000*4];
static GLuint TexName;
static int picrows = 0;
static int piccols = 0;

void savepic()
{
GLint viewPort[4] = {0};
glGetIntegerv(GL_VIEWPORT, viewPort);

int winrows = viewPort[3];
int wincols = viewPort[2];

GLbyte *colorArr = new GLbyte[winrows*wincols*3];
glReadPixels(viewPort[0], viewPort[1], viewPort[2], viewPort[3], GL_RGB, GL_UNSIGNED_BYTE, colorArr);
for(int i=0; i<winrows * wincols * 3; i ++) {
if(colorArr[i] == -1) { colorArr[i] = 255; }
}

Mat show = Mat(winrows, wincols, CV_8UC3, Scalar::all(0));
for (int i = 0; i< winrows; i++)
{
for (int j = 0; j< wincols; j++)
{
show.at<Vec3b>(winrows-i-1, j) = Vec3b(colorArr[(i*wincols+j)*3+2], colorArr[(i*wincols+j)*3+1], colorArr[(i*wincols+j)*3]);
}
}

delete colorArr;

imshow("show", show);
waitKey(33);
}

// Called to draw scene
void RenderScene(void)
{
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Save the matrix state and do the rotations
glPushMatrix();

glRotatef(xRot, 1.0f, 0.0f, 0.0f);
glRotatef(yRot, 0.0f, 1.0f, 0.0f);

//模型
glBegin(GL_QUADS);

glNormal3f(0.0f, 0.0f, 1.0f);
glTexCoord2f(0.0, 1.0);
glVertex3f(-1.0, 1.0, 0);

glNormal3f(0.0f, 0.0f, 1.0f);
glTexCoord2f(0.0, 0.0);
glVertex3f(-1.0, -1.0, 0);

glNormal3f(0.0f, 0.0f, 1.0f);
glTexCoord2f(1.0, 0.0);
glVertex3f(1.0, -1.0, 0);

glNormal3f(0.0f, 0.0f, 1.0f);
glTexCoord2f(1.0, 1.0);
glVertex3f(1.0, 1.0, 0);

glEnd();

// Restore the matrix state
glPopMatrix();

// Display the results
glutSwapBuffers();

//savepic();

}

// This function does any needed initialization on the rendering
// context.
void SetupRC()
{
// Black background
glClearColor(0.0f, 0.0f, 0.0f, 1.0f );

////////////set pixel storage modes
glPixelStoref( GL_UNPACK_ALIGNMENT, 1 );

glGenTextures( 1, &TexName );
glBindTexture( GL_TEXTURE_2D, TexName );
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, piccols,
picrows, 0, GL_RGBA, GL_UNSIGNED_BYTE,
TextData );

//设置s方向纹理重复,为重复设置。
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
//t方向的纹理重复
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );

//设置滤波方式为线性滤波
// when texture area is large, bilinear filter the first mipmap
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
// when texture area is small, bilinear filter the closest mipmap
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );

//GL_DECAL表示只用纹理颜色,不关心物体表面颜色
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glEnable(GL_TEXTURE_2D);

}

/////////////////////////////////////////////////////
// Handle arrow keys
void SpecialKeys(int key, int x, int y)
{
if(key == GLUT_KEY_UP)
{
xRot-= 5.0f;
}

if(key == GLUT_KEY_DOWN)
{
xRot += 5.0f;
}

if(key == GLUT_KEY_LEFT)
yRot -= 5.0f;

if(key == GLUT_KEY_RIGHT)
yRot += 5.0f;

if(key > 356.0f)
xRot = 0.0f;

if(key < -1.0f)
xRot = 355.0f;

if(key > 356.0f)
yRot = 0.0f;

if(key < -1.0f)
yRot = 355.0f;

// Refresh the Window
glutPostRedisplay();

}


//////////////////////////////////////////////////////////
// Reset projection
void ChangeSize(int w, int h)
{
// Prevent a divide by zero
if(h == 0)
h = 1;

// Set Viewport to window dimensions
glViewport(0, 0, w, h);

// Reset coordinate system
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

//GLfloat fAspect = (GLfloat) w / (GLfloat) h;
//gluPerspective(45.0f, fAspect, 1.0f, 225.0f);
glOrtho(-1.3, 1.3, -1.3, 1.3, -10, 10);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

}

//载入图片
void gettex(string name)
{
Mat t = imread(name);

piccols = t.cols;
picrows = t.rows;

assert(picrows<=1000
&&piccols<=1000);

for (int i = picrows-1; i>= 0; i--)
{
for (int j = 0; j< piccols; j++)
{
TextData[((picrows-1-i)*piccols+j)*4+0] = (GLubyte)t.at<Vec3b>(i, j)[2];
TextData[((picrows-1-i)*piccols+j)*4+1] = (GLubyte)t.at<Vec3b>(i, j)[1];
TextData[((picrows-1-i)*piccols+j)*4+2] = (GLubyte)t.at<Vec3b>(i, j)[0];
TextData[((picrows-1-i)*piccols+j)*4+3] = 255;

}
}
}

int main(int argc, char* argv[])
{
//读取tex
gettex("test.jpg");

glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(800,600);
glutCreateWindow("pic");
glutReshapeFunc(ChangeSize);
glutSpecialFunc(SpecialKeys);
glutDisplayFunc(RenderScene);
SetupRC();
glutMainLoop();

return 0;
}

需要注意的是,当打开savepic开关,并且缩小窗口的时候,会提示错误,目前不太清楚是什么原因。


原因在于保存的时候长宽必须是4的倍数才行。不然会出错。所以,改变窗口大小的话,可以在reshape函数里强制要求长宽被4整除即可。


另外放上一个obj读取的代码,写的很好。不过只能读取点,没有显示。http://download.csdn.net/detail/lcbwlx/6923111