Tga图片格式分析以及程序实现

转载 2006年06月10日 19:07:00
 

本文转自本人Blog: Singlerblog.mblogger.cn

继位图之后,我们来看看Tga图片的格式,以及程序实现。

 

一、 文件格式

Tga常见的格式有非压缩RGB和压缩RGB两种格式,其他格式的我们在这里不做讲述。文件的第三个Byte位作为标记:2为非压缩RGB格式,10为压缩RGB格式。它们的具体格式如下:

 

1、非压缩格式

图片类型:2-非压缩RGB格式

 

名称

偏移

长度

说明

图像信息字段长度

0

1

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

颜色表类型

1

1

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

图像类型码

2

1

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

颜色表规格字段

颜色表首址

3

2

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

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

颜色表的长度

5

2

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

颜色表项位数

7

1

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

图像规格字段

图像X 坐标起始位置

8

2

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

图像Y 坐标起始位置

10

2

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

图像宽度

12

2

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

图像高度

14

2

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

图像每像素存储占用位数

16

2

它的值为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,则该域不存在,否则越过该域直接读取图像颜色表规格中描述了每项的字节数,为 234之一。

图像数据

可变

可变

RGB颜色数据,存放顺序为:BBB GGG RRR (AAA)

 

 

2、压缩格式

图片类型:10-压缩RGB格式

 

名称

偏移

长度

说明

图像信息字段长度

0

1

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

颜色表类型

1

1

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

图像类型码

2

1

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

颜色表规格字段

颜色表首址

3

2

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

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

颜色表的长度

5

2

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

颜色表项位数

7

1

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

图像规格字段

图像 X坐标起始位置

8

2

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

图像 Y坐标起始位置

10

2

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

图像宽度

12

2

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

图像高度

14

2

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

图像每像素存储占用位数

16

2

它的值为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,则该域不存在,否则越过该域直接读取图像颜色表规格中描述了每项的字节数,为 234之一。

图像数据

可变

可变

采用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仅包含一个像素的颜色值,即为重复的那个颜色值。

 

关于RLE代码的实现,可以参考本文后面的“程序实现”部分的代码。

 

二、 程序实现

好了,弄清楚了文件格式后,编写程序就不是个难事清了。为了读取方便,我定义了结构体来表示Tga文件头:

 

//------------------------------------------------

//Name:TgaHeader

//Introduce:The tga header information in file

//------------------------------------------------

typedef struct tagTgaHeader

{

  BYTE  ubImageInfoByteCnt;    //The image information length, in byte

  BYTE  ubColorTableExist;       //0-have not color table,1-have

  BYTE  ubImageType;              //Image type,2-uncompare RGB image,10-compare RGB image

  BYTE  ubColorTableInfo[5];    //Color table information

  BYTE  ubImageInfo[10];          //Image information

}TgaHeader, *LPTGAHEADER;

//------------------------------------------------

 

1、文件头信息

 

  //Load the file header

  TgaHeader header;

  memset(&header, 0, sizeof(header));

  is.read((char*)&header, sizeof(header));

  if(header.ubImageType != 2 && header.ubImageType != 10)

              return false;

 

2、获取图像规格信息

 

  //Get image size

  m_iImageWidth = (header.ubImageInfo[5]<<8) + header.ubImageInfo[4];

  m_iImageHeight = (header.ubImageInfo[7]<<8) + header.ubImageInfo[6];

  m_iBitsPerPixel = header.ubImageInfo[8];

  if(         m_iImageWidth <=0 || m_iImageHeight <= 0 ||

              (m_iBitsPerPixel != 24 && m_iBitsPerPixel != 32))

              return false;

  m_iImageDataSize = m_iImageWidth * m_iImageHeight * m_iBitsPerPixel/8;

 

3、读取图片信息字段

 

//Load the image information

char info[255] = {'/0'};

is.read(info, header.ubImageInfoByteCnt);

 

4、读取图片数据

对于非压缩格式(header.ubImageType = 2),我们可以直接读取:

 

//Load image data

if(m_pImageData) delete []m_pImageData;

m_pImageData = new unsigned char[m_iImageDataSize];

is.read((char*)m_pImageData, m_iImageDataSize);

 

对于压缩格式(header.ubImageType = 10),我们要按照RLE算法解码:

 

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)

           {

                       int iCnt = (chunkheader & 0x7f) + 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

           {

                       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);

 

5、注意事项

行对齐:

同位图一样,如果想把tga用于GDI,需要做行对齐处理,而却Tga文件里的数据是没有行对齐的,所以加载必须程序进行行对齐。行对齐的方法如下:

 

A:计算图片行对齐前每行的字节数:

   iRowDataLenOld = m_iImageWidth * m_iImageHeight * m_iBitsPerPixel/8;

B:计算行对齐后的字节数:

   iRowDataLenNew= (((m_iImageWidth*m_iBitsPerPixel) + 31) >> 5) << 2;

C:如果iRowDataLenOldiRowDataLenNew则不需要对齐

D:否则在每行的后面添加iRowDataLenNewiRowDataLenOld个字节,并以0填充。

 

BGR->RGB转换:

Tga文件存储颜色数据的格式为BGR(A),如果需要得到RGB(A)格式的数据(如OpenGL中)需要做BGR->RGB转换。

 

 

 

 

 

 

 

 

 



 

Tga图片格式分析以及程序实现

Tga图片格式分析以及程序实现 本文转自本人Blog: Singlerblog.mblogger.cn 继位图之后,我们来看看Tga图片的格式,以及程序实现。   一、  文件格式...
  • summerhust
  • summerhust
  • 2013年11月29日 22:11
  • 1815

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

TGA格式图像是游戏中十分常见的一种图像格式,所以有必要了解其内部格式以及编程实现。 TGA图像一般有非压缩和压缩两种格式,下面分别进行介绍。 一、非压缩TGA图像 注:前面的标记绿色的...
  • xiajun07061225
  • xiajun07061225
  • 2012年06月08日 20:23
  • 8382

各种图片格式(BMP,JPG, GIF,PNG, TGA) 简单介绍

BMP格式: Windows系统下的标准位图格式,未经过压缩,一般图像文件会比较大。在很多软件中被广泛应用.所以编程的时候用opencv,是不是首先应该考虑BMP格式会比较好,因为看到很多大神的源...
  • hyqsong
  • hyqsong
  • 2015年11月17日 10:23
  • 2070

Unity3d加载外部图片文件

unity里的图片在生成时会压缩成资源文件,有时客户想zi'ji
  • hale445566
  • hale445566
  • 2014年05月19日 19:54
  • 3491

unity导出IOS资源问题

最近做的项目发步,在Andriod上只有40多M,在IOS安装包60多M,安装后发现IOS的包变成了900多M,百思不得其解,被此问题困扰了很久,在网上查了好久,原来是图片格式的问题,unity中图片...
  • uddjmh1985
  • uddjmh1985
  • 2015年04月01日 09:18
  • 887

OpenCV支持的图像格式

OpenCV支持的图像格式
  • fengbingchun
  • fengbingchun
  • 2010年11月25日 17:41
  • 9401

BMP图片的数据存储格式说明及显示数据的转换

1、显示数据的存储格式
  • DriveLinux
  • DriveLinux
  • 2014年06月17日 19:27
  • 1029

Opengl读取TGA图片信息代码

首先是了解opengl里AUX_RGBImageRec的定义,它包含图片宽高和数据 typedef struct _AUX_RGBImageRec {     GLint sizeX,sizeY;...
  • hbyzl
  • hbyzl
  • 2017年05月26日 21:31
  • 423

常见图片格式详解

http://www.cnblogs.com/xiangism/p/5311314.html 做了几年有关图形、图像的工作,对图片格式算是小有经验,在此写成一文章总结下。虽然一开始并不想讲很理论的...
  • cocoasprite
  • cocoasprite
  • 2017年01月04日 10:35
  • 629

C++读写Tga文件

// tga.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include ...
  • lgh1700
  • lgh1700
  • 2012年07月07日 10:13
  • 1638
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Tga图片格式分析以及程序实现
举报原因:
原因补充:

(最多只允许输入30个字)