【OpenGL】gltWriteTGA函数保存像素运用实例

#pragma comment(lib, "gltools.lib")

#define _CRT_SECURE_NO_DEPRECATE

#include <GLTools.h>	// OpenGL toolkit
#include <GLShaderManager.h>

#ifdef __APPLE__
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif

#pragma pack(1)
typedef struct
{
	GLbyte	identsize;              // Size of ID field that follows header (0)
	GLbyte	colorMapType;           // 0 = None, 1 = paletted
	GLbyte	imageType;              // 0 = none, 1 = indexed, 2 = rgb, 3 = grey, +8=rle
	unsigned short	colorMapStart;          // First colour map entry
	unsigned short	colorMapLength;         // Number of colors
	unsigned char 	colorMapBits;   // bits per palette entry
	unsigned short	xstart;                 // image x origin
	unsigned short	ystart;                 // image y origin
	unsigned short	width;                  // width in pixels
	unsigned short	height;                 // height in pixels
	GLbyte	bits;                   // bits per pixel (8 16, 24, 32)
	GLbyte	descriptor;             // image descriptor
} TGAHEADER;
#pragma pack()

GLShaderManager shaderManager;

void SetupRC()
{
	glClearColor(0, 0, 1, 1);

	shaderManager.InitializeStockShaders();
}

void ChangeSize(int w, int h)
{
	glViewport(0, 0, w, h);
}

void RenderScene(void)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

	glutSwapBuffers();
}

//程序清单5.1 用gltWriteTGA函数来将屏幕图像保存为一个Targa文件
GLint gltWriteTGA(const char *szFileName)
{
	FILE *pFile; //文件指针
	TGAHEADER tgaHeader; //TGA文件头(TGAHEADER结构体是在上方定义的,原本是没有的百度找了个)

	unsigned long lImageSize;// 图像的大小 字节表示
	GLbyte *pBits = NULL; //指向位的指针
	GLint iViewport[4]; //以像素表示的视口
	GLint lastBuffer;  //存储当前的读取缓冲区设置(书籍是GLenum但由于类型不符改为GLint)

	//获取视口大小
	glGetIntegerv(GL_VIEWPORT, iViewport);

	//图像应该多大(targa文件将被紧密包装)
	lImageSize = iViewport[2] * 3 * iViewport[3];

	//分配块
	pBits = (GLbyte *)malloc(lImageSize);
	if (pBits == NULL)
		return 0;

	//从颜色缓冲区读取位
	glPixelStorei(GL_PACK_ALIGNMENT, 1);
	glPixelStorei(GL_PACK_ROW_LENGTH, 0);
	glPixelStorei(GL_PACK_SKIP_ROWS, 0);
	glPixelStorei(GL_PACK_SKIP_PIXELS, 0);

	//获取当前读取缓冲区设置并进行保存
	glGetIntegerv(GL_READ_BUFFER, &lastBuffer);
	//切换到前台缓冲区并进行读取操作
	glReadBuffer(GL_FRONT);
	glReadPixels(0, 0, iViewport[2], iViewport[3], GL_BGR, GL_UNSIGNED_BYTE, pBits);
	//恢复读取缓冲区状态
	glReadBuffer(lastBuffer);

	//初始化Targa头
	tgaHeader.identsize = 0;
	tgaHeader.colorMapType = 0;
	tgaHeader.imageType = 2;
	tgaHeader.colorMapStart = 0;
	tgaHeader.colorMapLength = 0;
	tgaHeader.colorMapBits = 0;
	tgaHeader.xstart = 0;
	tgaHeader.ystart = 0;
	tgaHeader.width = iViewport[2];
	tgaHeader.height = iViewport[3];
	tgaHeader.bits = 24;
	tgaHeader.descriptor = 0;

	//为大小字节存储顺序问题而进行字节交换
#ifdef __APPLE__
	LITTLE_ENDIAN_WORD(&tgaHeader.colorMapStart);
	LITTLE_ENDIAN_WORD(&tgaHeader.colorMapLength);
	LITTLE_ENDIAN_WORD(&tgaHeader.xstart);
	LITTLE_ENDIAN_WORD(&tgaHeader.ystart);
	LITTLE_ENDIAN_WORD(&tgaHeader.width);
	LITTLE_ENDIAN_WORD(&tgaHeader.height);
#endif

	//尝试打开文件
	pFile = fopen(szFileName, "wb");
	if (pFile == NULL)
	{
		free(pBits); //释放缓冲区并返回错误
		return 0;
	}

	//写入头文件
	fwrite(&tgaHeader, sizeof(TGAHEADER), 1, pFile);

	//写入图像数据
	fwrite(pBits, lImageSize, 1, pFile);

	//释放临时缓冲区并关闭文件
	free(pBits);
	fclose(pFile);
	//成功!
	return 1;

}

void KeyboardFunc(unsigned char key, int x, int y)
{
	if (key == 32)
	{
		gltWriteTGA("hahaha");
	}
}

int main(int argc, char* argv[])
{
	gltSetWorkingDirectory(argv[0]);

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
	glutInitWindowSize(800, 600);
	glutCreateWindow("Test Read Write Pixel");

	GLenum err = glewInit();
	if (GLEW_OK != err) {
		fprintf(stderr, "Error:%s\n", glewGetErrorString(err));
		return 1;
	}

	glutReshapeFunc(ChangeSize);
	glutDisplayFunc(RenderScene);
	glutKeyboardFunc(KeyboardFunc);

	SetupRC();

	glutMainLoop();

	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39574690/article/details/115221543