游戏编程常用TGA图像格式详解以及加载纹理编程实现

1623 篇文章 23 订阅
1277 篇文章 12 订阅

http://blog.csdn.net/xiajun07061225/article/details/7646058

 

TGA格式图像是游戏中十分常见的一种图像格式,所以有必要了解其内部格式以及编程实现。

TGA图像一般有非压缩和压缩两种格式,下面分别进行介绍。

一、非压缩TGA图像

注:前面的标记绿色的部分(共12字节)表示对于所有的非压缩TGA格式图像值都是相同的!所以通常用来在读取数据时鉴别是否为TGA图像。

 

名称

偏移

长度

说明

图像信息字段长度

0

1

本字段是 1 字节无符号整型,指出图像信息字段( 见本子表的后面 )长度,其取值范围是 0  255 ,当它 0 时表示没有图像的信息字段

颜色表类型

1

1

表示没有颜色表,表示颜色表存在。由于本格式是无颜色表的,因此此项通常被忽略。

图像类型码

2

1

该字段总为 2  这也是此类型为格式 2 的原因。

颜色表规格字段

颜色表首址

3

2

颜色表首的入口索引,整型(低位-高位)

如果颜色表字段为0,则忽略该字段

颜色表的长度

5

2

颜色表的表项总数,整型(低位-高位)

颜色表项位数

7

1

位数(bit),16 代表 16  TGA 24 代表 24  TGA 32 代表 32  TGA

图像规格字段

图像 坐标起始位置

8

2

图像左下角 X坐标的整型(低位-高位)值

图像 坐标起始位置

10

2

图像左下角 Y坐标的整型(低位-高位)值

图像宽度

12

2

以像素为单位,图像宽度的整型(低位-高位)

图像高度

14

2

以像素为单位,图像宽度的整型(低位-高位)

图像每像素存储占用位数

16

1

它的值为1624  32 等等。决定了该图像是 TGA 16TGA24,TGA 32 等等。

图像描述符字节

17

1

bits 3-0 - 每像素对应的属性位的位数;

对于TGA 16 该值为 0  1,对于 TGA                     24,该值为 0,对于 TGA 32,该值为 8

 

bit 4    - 保留,必须为 0

 

bit 5    - 屏幕起始位置标志

0 = 原点在左下角

1 = 原点在左上角

对于 truevision 图像必须为 0

 

bits 7-6 - 交叉数据存储标志

00 = 无交叉

01 = 两路奇/偶交叉

10 = 四路交叉

11 = 保留(一般这个字节设为0x00即可)

图像信息字段

18

可变

包含一个自由格式的,长度是图像由“图像信息字段”指定。它常常被忽略(即偏移 0 处值为 0 ),注意其最大可以含有 255 个字符。如果需要存储更多信息,可以放在图像数据之后。

颜色表数据

可变

可变

如果颜色表类型为 0,则该域不存在,否则越过该域直接读取图像颜色表规格中描述了每项的字节数,为 23之一。

图像数据

可变

可变

RGB颜色数据,存放顺序为:BGR(A)


下面的程序实现了绘制一个立方体,并进行纹理贴图。

需要注意的是:TGA图像中数据存放的顺序是BGR(A),而在OpenGL中顺序是RGB(A),所以在进行纹理生成的时候必须先进行格式的转化。

在OpenGL中只能加载24位或者32位的TGA图像生成纹理。

TGATexture.h定义了一些结构体以及函数声明:

  1. #ifndef TGATEXTURE_H   
  2. #define TGATEXTURE_H   
  3.   
  4. #include <GL/glut.h>   
  5. #include <iostream>   
  6.   
  7. using namespace std;  
  8.   
  9. //纹理结构体定义   
  10. typedef struct  
  11. {  
  12.     GLubyte *imageData;//图像数据   
  13.     GLuint bpp;//像素深度   
  14.     GLuint width;//图像宽度   
  15.     GLuint height;//图像高度   
  16.     GLuint texID;//对应的纹理ID   
  17. }TextureImage;  
  18.   
  19. //加载TGA图像,生成纹理   
  20. bool LoadTGA(TextureImage *texture,char *fileName);  
  21.   
  22. #endif  
#ifndef TGATEXTURE_H
#define TGATEXTURE_H

#include <GL/glut.h>
#include <iostream>

using namespace std;

//纹理结构体定义
typedef struct
{
	GLubyte *imageData;//图像数据
	GLuint bpp;//像素深度
	GLuint width;//图像宽度
	GLuint height;//图像高度
	GLuint texID;//对应的纹理ID
}TextureImage;

//加载TGA图像,生成纹理
bool LoadTGA(TextureImage *texture,char *fileName);

#endif
TGATexture.cpp则包含加载TGA图像生成纹理的函数具体实现:

  1. #include "TGATexture.h"   
  2.   
  3. //加载TGA图像(无压缩格式),生成纹理   
  4. bool LoadTGA(TextureImage *texture, char *filename)         // Loads A TGA File Into Memory   
  5. {      
  6.     GLubyte     TGAheader[12]={0,0,2,0,0,0,0,0,0,0,0,0};    // Uncompressed TGA Header   
  7.     GLubyte     TGAcompare[12];                             // Used To Compare TGA Header   
  8.     GLubyte     header[6];                                  // First 6 Useful Bytes From The Header   
  9.     GLuint      bytesPerPixel;                              // Holds Number Of Bytes Per Pixel Used In The TGA File   
  10.     GLuint      imageSize;                                  // Used To Store The Image Size When Setting Aside Ram   
  11.     GLuint      temp;                                       // Temporary Variable   
  12.     GLuint      type=GL_RGBA;                               // Set The Default GL Mode To RBGA (32 BPP)   
  13.   
  14.     FILE *file = fopen(filename, "rb");                     // Open The TGA File   
  15.   
  16.     if( file==NULL ||                                       // Does File Even Exist?   
  17.         fread(TGAcompare,1,sizeof(TGAcompare),file)!=sizeof(TGAcompare) ||  // Are There 12 Bytes To Read?   
  18.         memcmp(TGAheader,TGAcompare,sizeof(TGAheader))!=0               ||  // Does The Header Match What We Want?   
  19.         fread(header,1,sizeof(header),file)!=sizeof(header))                // If So Read Next 6 Header Bytes   
  20.     {  
  21.         if (file == NULL)                                   // Did The File Even Exist? *Added Jim Strong*   
  22.             return false;                                   // Return False   
  23.         else  
  24.         {  
  25.             fclose(file);                                   // If Anything Failed, Close The File   
  26.             return false;                                   // Return False   
  27.         }  
  28.     }  
  29.   
  30.     texture->width  = header[1] * 256 + header[0];           // Determine The TGA Width  (highbyte*256+lowbyte)   
  31.     texture->height = header[3] * 256 + header[2];           // Determine The TGA Height (highbyte*256+lowbyte)   
  32.   
  33.     //OpenGL中纹理只能使用24位或者32位的TGA图像   
  34.     if( texture->width   <=0  ||                              // Is The Width Less Than Or Equal To Zero   
  35.         texture->height  <=0  ||                              // Is The Height Less Than Or Equal To Zero   
  36.         (header[4]!=24 && header[4]!=32))                   // Is The TGA 24 or 32 Bit?   
  37.     {  
  38.         fclose(file);                                       // If Anything Failed, Close The File   
  39.         return false;                                       // Return False   
  40.     }  
  41.   
  42.     texture->bpp = header[4];                            // Grab The TGA's Bits Per Pixel (24 or 32)   
  43.     bytesPerPixel   = texture->bpp/8;                        // Divide By 8 To Get The Bytes Per Pixel   
  44.     imageSize       = texture->width*texture->height*bytesPerPixel;   // Calculate The Memory Required For The TGA Data   
  45.   
  46.     texture->imageData=(GLubyte *)malloc(imageSize);     // Reserve Memory To Hold The TGA Data   
  47.   
  48.     if( texture->imageData==NULL ||                          // Does The Storage Memory Exist?   
  49.         fread(texture->imageData, 1, imageSize, file)!=imageSize)    // Does The Image Size Match The Memory Reserved?   
  50.     {  
  51.         if(texture->imageData!=NULL)                     // Was Image Data Loaded   
  52.             free(texture->imageData);                        // If So, Release The Image Data   
  53.   
  54.         fclose(file);                                       // Close The File   
  55.         return false;                                       // Return False   
  56.     }  
  57.   
  58.     //RGB数据格式转换,便于在OpenGL中使用   
  59.     for(GLuint i=0; i<int(imageSize); i+=bytesPerPixel)      // Loop Through The Image Data   
  60.     {                                                       // Swaps The 1st And 3rd Bytes ('R'ed and 'B'lue)   
  61.         temp=texture->imageData[i];                          // Temporarily Store The Value At Image Data 'i'   
  62.         texture->imageData[i] = texture->imageData[i + 2];    // Set The 1st Byte To The Value Of The 3rd Byte   
  63.         texture->imageData[i + 2] = temp;                    // Set The 3rd Byte To The Value In 'temp' (1st Byte Value)   
  64.     }  
  65.   
  66.     fclose (file);                                          // Close The File   
  67.   
  68.     // Build A Texture From The Data   
  69.     glGenTextures(1, &texture[0].texID);                    // Generate OpenGL texture IDs   
  70.   
  71.     glBindTexture(GL_TEXTURE_2D, texture[0].texID);         // Bind Our Texture   
  72.     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);   // Linear Filtered   
  73.     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);   // Linear Filtered   
  74.   
  75.     if (texture[0].bpp==24)                                 // Was The TGA 24 Bits   
  76.     {  
  77.         type=GL_RGB;                                        // If So Set The 'type' To GL_RGB   
  78.     }  
  79.   
  80.     glTexImage2D(GL_TEXTURE_2D, 0, type, texture[0].width, texture[0].height, 0, type, GL_UNSIGNED_BYTE, texture[0].imageData);  
  81.   
  82.     return true;                                            // Texture Building Went Ok, Return True   
  83. }  
#include "TGATexture.h"

//加载TGA图像(无压缩格式),生成纹理
bool LoadTGA(TextureImage *texture, char *filename)			// Loads A TGA File Into Memory
{    
	GLubyte		TGAheader[12]={0,0,2,0,0,0,0,0,0,0,0,0};	// Uncompressed TGA Header
	GLubyte		TGAcompare[12];								// Used To Compare TGA Header
	GLubyte		header[6];									// First 6 Useful Bytes From The Header
	GLuint		bytesPerPixel;								// Holds Number Of Bytes Per Pixel Used In The TGA File
	GLuint		imageSize;									// Used To Store The Image Size When Setting Aside Ram
	GLuint		temp;										// Temporary Variable
	GLuint		type=GL_RGBA;								// Set The Default GL Mode To RBGA (32 BPP)

	FILE *file = fopen(filename, "rb");						// Open The TGA File

	if(	file==NULL ||										// Does File Even Exist?
		fread(TGAcompare,1,sizeof(TGAcompare),file)!=sizeof(TGAcompare) ||	// Are There 12 Bytes To Read?
		memcmp(TGAheader,TGAcompare,sizeof(TGAheader))!=0				||	// Does The Header Match What We Want?
		fread(header,1,sizeof(header),file)!=sizeof(header))				// If So Read Next 6 Header Bytes
	{
		if (file == NULL)									// Did The File Even Exist? *Added Jim Strong*
			return false;									// Return False
		else
		{
			fclose(file);									// If Anything Failed, Close The File
			return false;									// Return False
		}
	}

	texture->width  = header[1] * 256 + header[0];			// Determine The TGA Width	(highbyte*256+lowbyte)
	texture->height = header[3] * 256 + header[2];			// Determine The TGA Height	(highbyte*256+lowbyte)

	//OpenGL中纹理只能使用24位或者32位的TGA图像
	if(	texture->width	<=0	||								// Is The Width Less Than Or Equal To Zero
		texture->height	<=0	||								// Is The Height Less Than Or Equal To Zero
		(header[4]!=24 && header[4]!=32))					// Is The TGA 24 or 32 Bit?
	{
		fclose(file);										// If Anything Failed, Close The File
		return false;										// Return False
	}

	texture->bpp	= header[4];							// Grab The TGA's Bits Per Pixel (24 or 32)
	bytesPerPixel	= texture->bpp/8;						// Divide By 8 To Get The Bytes Per Pixel
	imageSize		= texture->width*texture->height*bytesPerPixel;	// Calculate The Memory Required For The TGA Data

	texture->imageData=(GLubyte *)malloc(imageSize);		// Reserve Memory To Hold The TGA Data

	if(	texture->imageData==NULL ||							// Does The Storage Memory Exist?
		fread(texture->imageData, 1, imageSize, file)!=imageSize)	// Does The Image Size Match The Memory Reserved?
	{
		if(texture->imageData!=NULL)						// Was Image Data Loaded
			free(texture->imageData);						// If So, Release The Image Data

		fclose(file);										// Close The File
		return false;										// Return False
	}

	//RGB数据格式转换,便于在OpenGL中使用
	for(GLuint i=0; i<int(imageSize); i+=bytesPerPixel)		// Loop Through The Image Data
	{														// Swaps The 1st And 3rd Bytes ('R'ed and 'B'lue)
		temp=texture->imageData[i];							// Temporarily Store The Value At Image Data 'i'
		texture->imageData[i] = texture->imageData[i + 2];	// Set The 1st Byte To The Value Of The 3rd Byte
		texture->imageData[i + 2] = temp;					// Set The 3rd Byte To The Value In 'temp' (1st Byte Value)
	}

	fclose (file);											// Close The File

	// Build A Texture From The Data
	glGenTextures(1, &texture[0].texID);					// Generate OpenGL texture IDs

	glBindTexture(GL_TEXTURE_2D, texture[0].texID);			// Bind Our Texture
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);	// Linear Filtered
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);	// Linear Filtered

	if (texture[0].bpp==24)									// Was The TGA 24 Bits
	{
		type=GL_RGB;										// If So Set The 'type' To GL_RGB
	}

	glTexImage2D(GL_TEXTURE_2D, 0, type, texture[0].width, texture[0].height, 0, type, GL_UNSIGNED_BYTE, texture[0].imageData);

	return true;											// Texture Building Went Ok, Return True
}
main.cpp主程序:

  1. #include "TGATexture.h"   
  2.   
  3. TextureImage texture[1];  
  4.   
  5. GLfloat xRot,yRot,zRot;//control cube's rotation   
  6.   
  7. int init()  
  8. {  
  9.     if(!LoadTGA(&texture[0],"GSK1.tga"))  
  10.         return GL_FALSE;  
  11.     glEnable(GL_TEXTURE_2D);  
  12.     glShadeModel(GL_SMOOTH);  
  13.     glClearColor(0.0f,0.0f,0.0f,0.5f);  
  14.     glClearDepth(1.0f);  
  15.     glEnable(GL_DEPTH_TEST);  
  16.     glDepthFunc(GL_LEQUAL);  
  17.     glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);  
  18.     return GL_TRUE;  
  19. }  
  20.   
  21. void display()  
  22. {  
  23.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  
  24.     glLoadIdentity();  
  25.     glTranslatef(0.0f,0.0f,-5.0f);  
  26.     glRotatef(xRot,1.0f,0.0f,0.0f);  
  27.     glRotatef(yRot,0.0f,1.0f,0.0f);  
  28.     glRotatef(zRot,0.0f,0.0f,1.0f);  
  29.   
  30.     glBindTexture(GL_TEXTURE_2D,texture[0].texID);  
  31.   
  32.     glBegin(GL_QUADS);   
  33.     // Front Face    
  34.     // Bottom Left Of The Texture and Quad    
  35.     glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);   
  36.     // Bottom Right Of The Texture and Quad    
  37.     glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);   
  38.     // Top Right Of The Texture and Quad    
  39.     glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);   
  40.     // Top Left Of The Texture and Quad    
  41.     glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);   
  42.     glEnd();   
  43.   
  44.     glBindTexture(GL_TEXTURE_2D,texture[0].texID);  
  45.     glBegin(GL_QUADS);   
  46.     // Back Face    
  47.     // Bottom Right Of The Texture and Quad    
  48.     glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);   
  49.     // Top Right Of The Texture and Quad    
  50.     glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);   
  51.     // Top Left Of The Texture and Quad    
  52.     glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);   
  53.     // Bottom Left Of The Texture and Quad    
  54.     glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);   
  55.     glEnd();   
  56.   
  57.     glBindTexture(GL_TEXTURE_2D,texture[0].texID);  
  58.     glBegin(GL_QUADS);   
  59.     // Top Face    
  60.     // Top Left Of The Texture and Quad    
  61.     glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);   
  62.     // Bottom Left Of The Texture and Quad    
  63.     glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,  1.0f,  1.0f);   
  64.     // Bottom Right Of The Texture and Quad    
  65.     glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,  1.0f,  1.0f);   
  66.     // Top Right Of The Texture and Quad    
  67.     glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);   
  68.     glEnd();   
  69.   
  70.     glBindTexture(GL_TEXTURE_2D,texture[0].texID);  
  71.     glBegin(GL_QUADS);   
  72.     // Bottom Face    
  73.     // Top Right Of The Texture and Quad    
  74.     glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);   
  75.     // Top Left Of The Texture and Quad    
  76.     glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);   
  77.     // Bottom Left Of The Texture and Quad    
  78.     glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);   
  79.     // Bottom Right Of The Texture and Quad    
  80.     glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);   
  81.     glEnd();   
  82.   
  83.     glBindTexture(GL_TEXTURE_2D,texture[0].texID);  
  84.     glBegin(GL_QUADS);   
  85.     // Right face    
  86.     // Bottom Right Of The Texture and Quad    
  87.     glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);   
  88.     // Top Right Of The Texture and Quad    
  89.     glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);   
  90.     // Top Left Of The Texture and Quad    
  91.     glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);   
  92.     // Bottom Left Of The Texture and Quad    
  93.     glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);   
  94.     glEnd();   
  95.   
  96.     glBindTexture(GL_TEXTURE_2D,texture[0].texID);  
  97.     glBegin(GL_QUADS);   
  98.     // Left Face    
  99.     // Bottom Left Of The Texture and Quad    
  100.     glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);   
  101.     // Bottom Right Of The Texture and Quad    
  102.     glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);   
  103.     // Top Right Of The Texture and Quad    
  104.     glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);   
  105.     // Top Left Of The Texture and Quad    
  106.     glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);   
  107.     glEnd();   
  108.   
  109.     glutSwapBuffers();  
  110. }  
  111.   
  112. void reshape(int w,int h)  
  113. {  
  114.     if (0 == h)  
  115.         h = 1;  
  116.       
  117.     glViewport(0,0,(GLsizei)w,(GLsizei)h);  
  118.     glMatrixMode(GL_PROJECTION);  
  119.     glLoadIdentity();  
  120.     gluPerspective(60.0f,(GLfloat)w / (GLfloat)h,1,100);  
  121.     glMatrixMode(GL_MODELVIEW);  
  122.     glLoadIdentity();  
  123. }  
  124.   
  125. void keyboard(unsigned char key,int x,int y)  
  126. {  
  127.     switch(key){  
  128.         case 'x':  
  129.             xRot += 1.0f;  
  130.             glutPostRedisplay();  
  131.             break;  
  132.         case 'y':  
  133.             yRot += 1.0f;  
  134.             glutPostRedisplay();  
  135.             break;  
  136.         case 'z':  
  137.             zRot += 1.0f;  
  138.             glutPostRedisplay();  
  139.             break;  
  140.         default:  
  141.             break;  
  142.     }  
  143. }  
  144.   
  145. int main(int argc,char** argv)  
  146. {  
  147.     glutInit(&argc,argv);  
  148.     glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);  
  149.     glutInitWindowSize(400,400);  
  150.     glutInitWindowPosition(100,100);  
  151.     glutCreateWindow("Texture Map");  
  152.     init();  
  153.     glutDisplayFunc(display);  
  154.     glutReshapeFunc(reshape);  
  155.     glutKeyboardFunc(keyboard);  
  156.     glutMainLoop();  
  157.     return 0;  
  158. }  
#include "TGATexture.h"

TextureImage texture[1];

GLfloat xRot,yRot,zRot;//control cube's rotation

int init()
{
	if(!LoadTGA(&texture[0],"GSK1.tga"))
		return GL_FALSE;
	glEnable(GL_TEXTURE_2D);
	glShadeModel(GL_SMOOTH);
	glClearColor(0.0f,0.0f,0.0f,0.5f);
	glClearDepth(1.0f);
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
	return GL_TRUE;
}

void display()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();
	glTranslatef(0.0f,0.0f,-5.0f);
	glRotatef(xRot,1.0f,0.0f,0.0f);
	glRotatef(yRot,0.0f,1.0f,0.0f);
	glRotatef(zRot,0.0f,0.0f,1.0f);

	glBindTexture(GL_TEXTURE_2D,texture[0].texID);

	glBegin(GL_QUADS); 
	// Front Face 
	// Bottom Left Of The Texture and Quad 
	glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f); 
	// Bottom Right Of The Texture and Quad 
	glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f); 
	// Top Right Of The Texture and Quad 
	glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f); 
	// Top Left Of The Texture and Quad 
	glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f); 
	glEnd(); 

	glBindTexture(GL_TEXTURE_2D,texture[0].texID);
	glBegin(GL_QUADS); 
	// Back Face 
	// Bottom Right Of The Texture and Quad 
	glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); 
	// Top Right Of The Texture and Quad 
	glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f); 
	// Top Left Of The Texture and Quad 
	glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f); 
	// Bottom Left Of The Texture and Quad 
	glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); 
	glEnd(); 

	glBindTexture(GL_TEXTURE_2D,texture[0].texID);
	glBegin(GL_QUADS); 
	// Top Face 
	// Top Left Of The Texture and Quad 
	glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f); 
	// Bottom Left Of The Texture and Quad 
	glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,  1.0f,  1.0f); 
	// Bottom Right Of The Texture and Quad 
	glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,  1.0f,  1.0f); 
	// Top Right Of The Texture and Quad 
	glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f); 
	glEnd(); 

	glBindTexture(GL_TEXTURE_2D,texture[0].texID);
	glBegin(GL_QUADS); 
	// Bottom Face 
	// Top Right Of The Texture and Quad 
	glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); 
	// Top Left Of The Texture and Quad 
	glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f); 
	// Bottom Left Of The Texture and Quad 
	glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f); 
	// Bottom Right Of The Texture and Quad 
	glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f); 
	glEnd(); 

	glBindTexture(GL_TEXTURE_2D,texture[0].texID);
	glBegin(GL_QUADS); 
	// Right face 
	// Bottom Right Of The Texture and Quad 
	glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); 
	// Top Right Of The Texture and Quad 
	glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f); 
	// Top Left Of The Texture and Quad 
	glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f); 
	// Bottom Left Of The Texture and Quad 
	glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f); 
	glEnd(); 

	glBindTexture(GL_TEXTURE_2D,texture[0].texID);
	glBegin(GL_QUADS); 
	// Left Face 
	// Bottom Left Of The Texture and Quad 
	glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); 
	// Bottom Right Of The Texture and Quad 
	glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f); 
	// Top Right Of The Texture and Quad 
	glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f); 
	// Top Left Of The Texture and Quad 
	glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f); 
	glEnd(); 

	glutSwapBuffers();
}

void reshape(int w,int h)
{
	if (0 == h)
		h = 1;
	
	glViewport(0,0,(GLsizei)w,(GLsizei)h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(60.0f,(GLfloat)w / (GLfloat)h,1,100);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

void keyboard(unsigned char key,int x,int y)
{
	switch(key){
		case 'x':
			xRot += 1.0f;
			glutPostRedisplay();
			break;
		case 'y':
			yRot += 1.0f;
			glutPostRedisplay();
			break;
		case 'z':
			zRot += 1.0f;
			glutPostRedisplay();
			break;
		default:
			break;
	}
}

int main(int argc,char** argv)
{
	glutInit(&argc,argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
	glutInitWindowSize(400,400);
	glutInitWindowPosition(100,100);
	glutCreateWindow("Texture Map");
	init();
	glutDisplayFunc(display);
	glutReshapeFunc(reshape);
	glutKeyboardFunc(keyboard);
	glutMainLoop();
	return 0;
}
运行结果:




二、压缩TGA图像

其格式如下表:


名称

偏移

长度

说明

图像信息字段长度

0

1

本字段是 1 字节无符号整型,指出图像信息字段( 见本子表的后面 )长度,其取值范围是 0  255 ,当它为 0 时表示没有图像的信息字段。

颜色表类型

1

1

表示没有颜色表,表示颜色表存在。由于本格式是无颜色表的,因此此项通常被忽略。

图像类型码

2

1

该字段总为 10  这也是此类型为格式 10 的原因。

颜色表规格字段

颜色表首址

3

2

颜色表首的入口索引,整型(低位-高位)

如果颜色表字段为0,则忽略该字段

颜色表的长度

5

2

颜色表的表项总数,整型(低位-高位)

颜色表项位数

7

1

位数(bit),16 代表 16  TGA 24 代表 24  TGA 32 代表 32  TGA

图像规格字段

图像 X 坐标起始位置

8

2

图像左下角 X坐标的整型(低位-高位)值

图像 Y 坐标起始位置

10

2

图像左下角 Y坐标的整型(低位-高位)值

图像宽度

12

2

以像素为单位,图像宽度的整型(低位-高位)

图像高度

14

2

以像素为单位,图像宽度的整型(低位-高位)

图像每像素存储占用位数

16

1

它的值为1624  32 等等。决定了该图像是 TGA 16TGA24,TGA 32 等等。

图像描述符字节

17

1

bits 3-0 - 每像素对应的属性位的位数;

对于TGA 16 该值为 0  1,对于 TGA                     24,该值为 0,对于 TGA 32,该值为 8

 

bit 4    - 保留,必须为 0

 

bit 5    - 屏幕起始位置标志

0 = 原点在左下角

1 = 原点在左上角

对于 truevision 图像必须为 0

 

bits 7-6 - 交叉数据存储标志

00 = 无交叉

01 = 两路奇/偶交叉

10 = 四路交叉

11 = 保留

图像信息字段

18

可变

包含一个自由格式的,长度是图像由“图像信息字段”指定。它常常被忽略(即偏移 0 处值为 0 ),注意其最大可以含有 255 个字符。如果需要存储更多信息,可以放在图像数据之后。

颜色表数据

可变

可变

如果颜色表类型为 0,则该域不存在,否则越过该域直接读取图像颜色表规格中描述了每项的字节数,为 23之一。

图像数据

可变

可变

采用RLE压缩后的RGB颜色数据。

Tga的压缩算法采用了RLE算法,RLE算法的基本思想是将数据分为两大类:

A:连续的不重复字节

B:连续的重复字节

 

RLE算法应用于RGB格式的图片压缩中,则把数据分为:

A:连续的不重复像素颜色值

B:连续的重复像素颜色值

 

然后将数据按这两类数据分成若干长度不相等数据块,每个数据块的开始都是一个1个字节长度的headerRLE在纯数据压缩中header2个字节16位),后面紧跟着data数据块,如下。

 

Header1个字节)

Data(变长)

 

每个header的第一位作为标记:0表示A类颜色数据,1表示B类颜色数据。剩下的7位意义如下:

对于A类数据:表示data有多少个像素的RGB颜色值。取值0-1270表示1个像素,所以最多为128个像素,data块则为这些不重复的像素RGB颜色值。

对于B类数据:表示有多少个像素具有相同的RGB颜色值。取值0-1270表示1个像素,所以最多为128个像素,data仅包含一个像素的颜色值,即为重复的那个颜色值。


读取其像素数据部分需要注意一下,需要分情况讨论看是A类数据还是B类数据:

  1. if(m_pImageData) delete []m_pImageData;  
  2. m_pImageData = new unsigned char[m_iImageDataSize];  
  3.   
  4.    
  5. int iBytePerPixel = m_iBitsPerPixel/8;  
  6. int iPixelCnt = m_iImageWidth * m_iImageHeight;  
  7. int iCurPixel = 0;  
  8. unsigned char ucColorBuffer[4] = {'/0'};  
  9.   
  10.    
  11. do{  
  12.             BYTE chunkheader = 0;  
  13.             is.read((char*)&chunkheader, sizeof(BYTE));  
  14.   
  15.    
  16.             //run length data   
  17.             if(chunkheader & 0x80)//B类数据   
  18.             {  
  19.                         int iCnt = (chunkheader & 0x7f) + 1;//计算连续的颜色值重复的像素数。注意:最高位的1是标记位,所以要特殊处理   
  20.                         is.read((char*)ucColorBuffer, iBytePerPixel);  
  21.                          
  22.                         for(int i = 0; i < iCnt; i++)  
  23.                         {  
  24.                                     m_pImageData[iCurPixel*iBytePerPixel + 0] = ucColorBuffer[0];  
  25.                                     m_pImageData[iCurPixel*iBytePerPixel + 1] = ucColorBuffer[1];  
  26.                                     m_pImageData[iCurPixel*iBytePerPixel + 2] = ucColorBuffer[2];  
  27.                                     if(m_iBitsPerPixel == 32)  
  28.                                     {  
  29.                                                 m_pImageData[iCurPixel*iBytePerPixel + 3] = ucColorBuffer[3];  
  30.                                     }  
  31.   
  32.    
  33.                                     iCurPixel++;  
  34.   
  35.    
  36.                                     if(iCurPixel > iPixelCnt)  
  37.                                                 return false;  
  38.                         }  
  39.             }  
  40.             //no processed data   
  41.             else//A类数据   
  42.             {  
  43.                         int iCnt = chunkheader + 1;//颜色值不重复的像素数量,注意要加一   
  44.                         for(int i = 0; i < iCnt; i++)  
  45.                         {                                               
  46.                                     is.read((char*)ucColorBuffer, iBytePerPixel);  
  47.   
  48.    
  49.                                     m_pImageData[iCurPixel*iBytePerPixel + 0] = ucColorBuffer[0];  
  50.                                     m_pImageData[iCurPixel*iBytePerPixel + 1] = ucColorBuffer[1];  
  51.                                     m_pImageData[iCurPixel*iBytePerPixel + 2] = ucColorBuffer[2];  
  52.                                     if(m_iBitsPerPixel == 32)  
  53.                                     {  
  54.                                                 m_pImageData[iCurPixel*iBytePerPixel + 3] = ucColorBuffer[3];  
  55.                                     }  
  56.   
  57.    
  58.                                     iCurPixel++;  
  59.                                                  
  60.                                     if(iCurPixel > iPixelCnt)  
  61.                                                 return false;  
  62.                         }  
  63.             }  
  64.   
  65.    
  66. }while(iCurPixel < iPixelCnt);  
if(m_pImageData) delete []m_pImageData;
m_pImageData = new unsigned char[m_iImageDataSize];

 
int iBytePerPixel = m_iBitsPerPixel/8;
int iPixelCnt = m_iImageWidth * m_iImageHeight;
int iCurPixel = 0;
unsigned char ucColorBuffer[4] = {'/0'};

 
do{
            BYTE chunkheader = 0;
            is.read((char*)&chunkheader, sizeof(BYTE));

 
            //run length data
            if(chunkheader & 0x80)//B类数据
            {
                        int iCnt = (chunkheader & 0x7f) + 1;//计算连续的颜色值重复的像素数。注意:最高位的1是标记位,所以要特殊处理
                        is.read((char*)ucColorBuffer, iBytePerPixel);
                       
                        for(int i = 0; i < iCnt; i++)
                        {
                                    m_pImageData[iCurPixel*iBytePerPixel + 0] = ucColorBuffer[0];
                                    m_pImageData[iCurPixel*iBytePerPixel + 1] = ucColorBuffer[1];
                                    m_pImageData[iCurPixel*iBytePerPixel + 2] = ucColorBuffer[2];
                                    if(m_iBitsPerPixel == 32)
                                    {
                                                m_pImageData[iCurPixel*iBytePerPixel + 3] = ucColorBuffer[3];
                                    }

 
                                    iCurPixel++;

 
                                    if(iCurPixel > iPixelCnt)
                                                return false;
                        }
            }
            //no processed data
            else//A类数据
            {
                        int iCnt = chunkheader + 1;//颜色值不重复的像素数量,注意要加一
                        for(int i = 0; i < iCnt; i++)
                        {                                             
                                    is.read((char*)ucColorBuffer, iBytePerPixel);

 
                                    m_pImageData[iCurPixel*iBytePerPixel + 0] = ucColorBuffer[0];
                                    m_pImageData[iCurPixel*iBytePerPixel + 1] = ucColorBuffer[1];
                                    m_pImageData[iCurPixel*iBytePerPixel + 2] = ucColorBuffer[2];
                                    if(m_iBitsPerPixel == 32)
                                    {
                                                m_pImageData[iCurPixel*iBytePerPixel + 3] = ucColorBuffer[3];
                                    }

 
                                    iCurPixel++;
                                               
                                    if(iCurPixel > iPixelCnt)
                                                return false;
                        }
            }

 
}while(iCurPixel < iPixelCnt);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值