OpenGL显示图片

最近想用C++在windows下实现一个基本的图像查看器功能,目前只想到了使用GDI或OpenGL两种方式。由于实在不想用GDI的API了,就用OpenGL的方式实现了一下基本的显示功能。

用GDAL读取图像,这样就能与图像格式无关。OpenGL的glDrawPixels()函数也能实现图像显示,但是现在高版本的OpenGL都采用glTexImage2D()贴纹理的方式了,也不用考虑图像大小是否是2的N次方,或者4字节对齐的问题。具体实现如下:

// ImageShow.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "ImageShow.h"

#include <iostream>
#include <glglew.h>			// 包含最新的gl.h,glu.h库
#include <glfreeglut.h>			// 包含OpenGL实用库
#include <gdal_priv.h> 

using namespace std;

unsigned int  texture;    // 纹理对象
unsigned char* imgBuf = nullptr;
int imgWidth;
int imgHeight;

void ReadImage()
{
	GDALAllRegister();

	GDALDataset* img = (GDALDataset *)GDALOpen("lena.bmp", GA_ReadOnly);
	//GDALDataset* img = (GDALDataset *)GDALOpen("dst.tif", GA_ReadOnly);
	if (img == nullptr)
	{
		return;
	}	

	imgWidth = img->GetRasterXSize();   //图像宽度
	imgHeight = img->GetRasterYSize();  //图像高度
	int bandNum = img->GetRasterCount();    //波段数	
	int depth = GDALGetDataTypeSize(img->GetRasterBand(1)->GetRasterDataType()) / 8;    //图像深度

	//申请buf
	size_t imgBufNum = (size_t)imgWidth * imgHeight * bandNum * depth;
	size_t imgBufOffset = (size_t)imgWidth * (imgHeight - 1) * bandNum * depth;
	imgBuf = new GByte[imgBufNum];
	//读取
	img->RasterIO(GF_Read, 0, 0, imgWidth, imgHeight, imgBuf + imgBufOffset, imgWidth, imgHeight,
		GDT_Byte, bandNum, nullptr, bandNum*depth, -imgWidth*bandNum*depth, depth);

	GDALClose(img);
}

void InitGL()
{
	glClearColor(0.0, 0.0, 0.0, 0.0);

	glShadeModel(GL_SMOOTH);      //平滑着色
	glEnable(GL_DEPTH_TEST);       //深度测试
	glEnable(GL_CULL_FACE);    //只渲染某一面
	glFrontFace(GL_CCW);     //逆时针正面
			
	glEnable(GL_TEXTURE_2D);    //启用2D纹理映射	

	//载入纹理图像:
	ReadImage();
	
	//生成纹理对象:
	glGenTextures(1, &texture);      	
}

void DrawGLScene()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glBindTexture(GL_TEXTURE_2D, texture);	  //绑定纹理:
	
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1); //支持4字节对齐

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);      //S方向上贴图
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);      //T方向上贴图
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);       //放大纹理过滤方式
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);       //缩小纹理过滤方式
		
	glTexImage2D(GL_TEXTURE_2D, 0, 3, imgWidth, imgHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, imgBuf);  //载入纹理:																										

	glMatrixMode(GL_MODELVIEW);							// 选择模型观察矩阵
	glLoadIdentity();									// 重置模型观察矩阵		
	glMatrixMode(GL_PROJECTION);						// 选择投影矩阵		
	glLoadIdentity();
		
	glEnable(GL_TEXTURE_2D);    //启用2D纹理映射
	glBegin(GL_QUADS);
	glTexCoord2f(0.0f, 0.0f);	
	glVertex3f(-0.5f, -0.5f, 0.0f);
	glTexCoord2f(1.0f, 0.0f);	
	glVertex3f(0.5f, -0.5f, 0.0f);
	glTexCoord2f(1.0f, 1.0f);
	glVertex3f(0.5f, 0.5f, 0.0f);
	glTexCoord2f(0.0f, 1.0f);
	glVertex3f(-0.5f, 0.5f, 0.0f);
	glEnd();
	glDisable(GL_TEXTURE_2D);

	glutSwapBuffers();
}

GLvoid ReSizeGLScene(GLsizei width, GLsizei height)    // 重置OpenGL窗口大小
{
	glViewport(0, 0, width, height);
}

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
	
	glutInitContextProfile(GLUT_CORE_PROFILE);
	glutInitWindowSize(600, 600);
	glutInitWindowPosition(0, 0);
	glutCreateWindow("opengl");
	
	InitGL();	
	glutDisplayFunc(DrawGLScene);
	glutReshapeFunc(ReSizeGLScene);
	//glutKeyboardFunc(keyboard);
	//glutMouseWheelFunc(mouse_wheel);
	//glutIdleFunc(idle);

	glutMainLoop(); 
		
	return 0;
}

最后显示的情况如下:

另外注意最后需要释放资源:

glDeleteTextures(1, &texture);
if (imgBuf)
{
	delete[] imgBuf;
	imgBuf = nullptr;
}

原文地址:https://www.cnblogs.com/charlee44/p/5745127.html