#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;
}
GLbyte *gltReadTGABits(const char *szFileName, GLint *iWidth, GLint *iHeight, GLint *iComponents, GLenum *eFormat)
{
FILE *pFile;
TGAHEADER tgaHeader;
unsigned long lImageSize;
short sDepth;
GLbyte *pBits = NULL;
*iWidth = 0;
*iHeight = 0;
*eFormat = GL_RGB;
*iComponents = GL_RGB;
pFile = fopen(szFileName, "rb");
if (pFile == NULL)
{
return NULL;
}
//读取文件头tgaheader
fread(&tgaHeader, 18, 1, pFile);
#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
*iWidth = tgaHeader.width;
*iHeight = tgaHeader.height;
//图像每像素多少字节
sDepth = tgaHeader.bits / 8;
//只处理像素占8、24、32位的
if (tgaHeader.bits != 8 && tgaHeader.bits != 24 && tgaHeader.bits != 32)
{
return NULL;
}
//计算图像缓冲区大小
lImageSize = tgaHeader.width * tgaHeader.height * sDepth;
//进行内存定义并进行成功检验
pBits = (GLbyte*)malloc(lImageSize * sizeof(GLbyte));
if (pBits == NULL)
return NULL;
//读入位 检查读取错误。这项操作应该发现RLE或者其他我们不想识别的奇怪格式
if (fread(pBits, lImageSize, 1, pFile) != 1)
{
free(pBits);
return NULL;
}
//设置成希望的OpenGL格式
switch (sDepth)
{
#ifdef OPENGL_ES
case 3://最可能情况
*eFormat = GL_BGR;
*iComponents = GL_RGB;
break;
#endif
#ifdef WIN32
case 3:
*eFormat = GL_BGR;
*iComponents = GL_RGB;
break;
#endif
#ifdef linux
case 3:
*eFormat = GL_BGR;
*iComponents = GL_RGB;
break;
#endif
case 4:
*eFormat = GL_BGRA;
*iComponents = GL_RGBA;
break;
case 1:
*eFormat = GL_LUMINANCE;
*iComponents = GL_LUMINANCE;
break;
default: //RGB
//如果是在iPhone上,TGA为BGR,并且iPhone不支持没有Alpha的BGR, 但是它支持RGB,所以只要将红色和蓝色调整一下就能满足需求
//但为了加快iPhone的载入速度,请保存带有Alpha的TGA。
#ifdef OPENGL_ES
//不带Alpha的tga图 原本为BGR ,这里互换B和R,变成RGB,让iPhone能支持没有Alpha的tga图片,但最好给tga图加上alpha值让iPhone加快加载速度
for (int i = 0; i < lImageSize; i += 3)
{
GLbyte temp = pBits[i];
pBits[i] = pBits[i + 2];
pBits[i + 2] = temp;
}
#endif
break;
}
//文件操作完成
fclose(pFile);
//返回指向图像数据的指针
return pBits;
}
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;
}
【OpenGL】读取像素代码示例
猜你喜欢
转载自blog.csdn.net/qq_39574690/article/details/115255624
今日推荐
周排行