TGA文件格式

简介

TGA(or TARGA)是由Truevision公司开发的一种描述bitmap(位图)图像文件格式,能表示黑白、索引颜色、RGB颜色等bitmap,是目前应用最广泛的图像格式. 文件扩展名.tga,兼顾bitmap的图像质量、JPEG的小体积特点,支持不失真的压缩算法(RLE).

TGA格式文件目前有2个版本v1.0和v2.0: v1.0称为origin Truevision TGA; v2.0称为new TGA File或extension TGA File.

new TGA File解决了以下需求(也是新增内容, 如果没用到, 可不必关心):

  • The inclusion of a scaled-down “postage stamp” copy of the image 缩减版postage stamp图像副本
  • Date and Time of image file creation 图像文件创建的日期和时间
  • Author Name 作者名
  • Author Comments 作者备注
  • Job Name 作业名
  • Job Accumulated Time 作业累计时间
  • Gamma Value 伽马值
  • Correct Color LUT
  • Pixel Aspect Ratio 像素纵横比
  • Scan Line Offset Table 扫描线偏移表
  • Key Color 关键色
  • Software Package Name and Version Number 软件包名和版本号
  • Developer Definable Areas 开发商定义区域
  • Attribute (Alpha) channel Type 属性(α)通道类型
  • The ability for simple expansion 简单扩展能力

本文主要解析TGA v2.0格式(详见参考链接).

术语

Pseudo-Color(伪彩色): 将整个像素值用作可编程颜色表的单个索引, 该颜色表包含实际要显示的红、绿、蓝颜色强度. 使用这种图像的Truevision产品(硬件)有: VDA, VDA/D, TARGA M8, ATVista, NuVista和HR视频板.

True-Color(真彩): 每个像素的红、绿、蓝字段直接决定每种原色强度, 而非通过索引指向颜色表. 对应Truevision产品有: ICB, TARGA 16, TARGA 24, TARGA 32, ATVista和NuVista视频板.

Direct-Color(直接彩色): 每个像素分为红、绿、蓝字段, 但这些字段是单独的索引, 用来访问独立的可编程颜色查找表. 颜色表的查找结果决定了每个原色的强度. 直接彩色系统类似于伪彩色系统, 除了颜色表中的红、绿、蓝可单独改变(改单个索引或查找到的颜色值即可); 而伪彩色系统中的红、绿、蓝, 是绑定到一起存放在颜色表中的. 对应Truevision产品有: ATVista和NuVista视频板.

仅用作伪彩色设备: VDA, VDA/D, TARGA M8, HR;
仅用作真彩设备: ICB, TARGA 16, 24, 32.

Long = 32bit
Short = 16bit
Byte = 8bit
ASCII = C风格字符串, 多个字节, 以NUL byte结尾.
Bit Numbering(位序):

img

Byte Ordering(字节序): TGA采用Intel字节序(非Motorola字节序), 即低位字节优先. (tips: 解析跨字节整型数据时会用到, 如short, long类型)

TGA格式

TGA格式各主要组成部分及其分布, 如下图所示:

img

其中, 白底色模块为固定长度, 蓝底色部分表示可变长度(variable).

TGA头部(TGA Header)

18byte头部,包含5个域:

域编号(field no.) 长度 域名 描述
1 1byte Id length Image id段长度,取值0~255. 0表示无id段
2 1byte Color map type 是否包含颜色表(color map)
0: 不使用颜色表;
1: 使用颜色表
3 1byte Image type 图像类型. 应用场景详见后文Image Types章节.
0~127为Truevision公司用于一般应用, 128~255供开发者使用.
0: 没有图像数据;
1: 未压缩的颜色表图像;
2: 未压缩的TRUE-COLOR图像;
3: 未压缩的黑白图像;
9: RLE压缩的颜色表图像;
10: RLE压缩的TRUE-COLOR图像;
11: 压缩的黑白图像.
4 5byte Color map specification 描述颜色表规格.
如果Header.Color map type = 0, 则没有颜色表存在, 这5byte应全为0.
2byte First Entry Index 颜色表起点, 即颜色表第一项的索引
2byte Color map Length 颜色表长度, 即颜色表共有多少项
1byte Color map Entry Size 颜色表项大小, 即每个项占用bit数. 典型值15, 16, 24, 32. 即使是15, 每次也要用16bit解析, 然后忽略第16bit
5 10byte Image specification 描述图像维度和格式
2byte X origin of Image 图像起点(左下角)x坐标. 基于屏幕原点在左下角
2byte Y origin of Image 图像起点(左下角)y坐标. 基于屏幕原点在左下角
2byte Image Width 图像宽度(单位: pixel)
2byte Image Height 图像高度(单位: pixel)
1byte Pixel Depth 像素深度, 即每个像素的bit数, 包含属性或α通道. 常用值8, 16, 24, 32
1byte Image Descriptor 图像描述器.
bit3~0: 关联到每个像素的属性位数, 对于Targa 16, 应为0或1; 对于Targa 24, 应为0; 对于Targa 32, 应为8. 与Field 24有关.
bit5~4: 指示传输像素数据到屏幕的的顺序. bit4从左到右顺序, bit5为从上到下顺序.
bit7~6: 须为0, 兼容未来版本.

图像/颜色表数据(Image/Color Map Data)

域编号(field no.) 长度 域名 描述
6 可变.
取决于Header.Id length(field 1)值
Image Id 可选域. Header.Id length = 0表明无该段
7 可变.
取决于Header.Color map type(field 2)及Color map Length(field 4.2), Color map Entry Size(4.3)
Color Map Data 实际颜色表信息.
field 2 = 0, 表明无color map存在; field = 1, 则长度为(field 4.2 * field 4.3)bits.
每个颜色表项(entry)用整数字节存储, 不会出现小数字节. 颜色表项的RGB颜色, 存放在多字节项的连续位段中.
8 可变.
Image Data 图像数据信息.
包含Width × Height pixels, Width和Height在Field 5.6和5.5中定义.
每个像素都存储为整数字节.

颜色表数据

根据颜色表规格(field 4)的字段, 知颜色表数据(Image Map Data, field 7)信息:
First Entry Index => 颜色表的第一项的索引;
Color map Length => 颜色表中项的数量;
Color map Entry Size => 颜色表中每一项的大小.

tips: 颜色表中, 每个元素称为一个颜色表项(Color Map Entry), 简称项(Entry).

问题1: 根据TGA格式各组成部分的排列,颜色表所在域Image Map Data紧跟Image ID, 前面的域都能确定大小, 为何还需要提供First Entry Index?

由于官方文档描述不清, 个人理解: 颜色表中存放着若干项, 但不一定都用到. 比如有1000个项, 但只用了其中72个(从342开始), 此时, 可设置First Entry Index = 342, Color map Length = 72.

问题2: 颜色表规格描述了颜色表位置、项数、每项大小, 但存放什么内容呢?

存放RGB颜色值, 但每个R、G、B分量占用空间不一定是1byte, 而是\(min(\frac{field 4.3}{3}, 8)\)bit, 即(Color map Entry Size)/3和8的最小值.
例如, Color map Entry Size指定项大小为8, 则每个R、G、B分量占2bit(多余高位忽略);
Color map Entry Size = 16, 则每个R、G、B分量占5bit;
Color map Entry Size = 24, 则每个R、G、B分量占8bit;
Color map Entry Size = 32, 则每个R、G、B分量占8bit;

图像数据

根据图像规格(field 5)的字段, 知图像数据(Image Data, field 8)信息:
Image Width => 图像宽度(pixel)
Image Height => 图像高度(pixel)
Pixel Depth => 每个像素的位数, 通常是8、16、24、32(其他值也能用).

问题3: Pixel存放什么?
根据不同的Image Type(详见后文), Pixel存放内容有不同的解读.
对于颜色表图像(COLOR-MAPPED), Image type(field 3)=1或9, Pixel存放的就是颜色表项的索引(基于前面的First Entry Index计算).
对于真彩图像(TRUE-COLOR), Image type(field 3)=2或10, Pixel存放的就是R、G、B值(由Image Descriptor决定属性位数, 即α通道).
对于黑白图像(BLACK and WHITE), Image type(field 3)=3或11, Pixel存放的就是灰度值(8bit即可).

Pixel通常会有下面几种类型:

img

from: TGA File Format Summary

开发者区域(Develop Area)

域编号(field no.) 长度 域名 描述
9 取决于开发者 Develop Area 可用于存储任何类型信息, 推荐用于存储应用程序特定信息(即不适用于其他产品、未被TGA格式涵盖的信息).
大小、格式取决于开发者. 普通读者可忽略这段内容, 除非了解具体格式信息.

如果包含不止1个开发者区域,则创建一个开发者目录(Developer Directory)进行映射. Developer Directory由TGA File Footer(TGA脚注)的offset(field 29.2)指定位置.

扩展区域(EXTENSION AREA)

域编号(field no.) 长度 域名 描述
10~27 495byte
未来版本可能变化
Extension Area 用于满足开发者额外文件信息的需求. 由TGA File Footer(TGA脚注)域中的Extension Area Offset(field 29.1)指定位置, 如果Offset = 0, 该域不存在; 否则, Offset表面从文件开始计算的该域位置
10 2byte Extension Size 扩展区域长度. 对于TGA v2.0, 该值为495.
11 41byte Author Name 图像文件作者名. C风格字符串(ASCII编码), 须以NUL byte结尾. 如果没有用到, 必须都是NULL.
12 324byte Author Comments 作者备注. 支持最多4行(每行80字符), 每行以NUL byte终结.
13 12byte Date/Time Stamp 图像保存时的日期、时间戳, 由6个SHORT数组成.
SHORT 0: 月份(1-12);
SHORT1: 日(1-31);
SHORT2: 年(4个数字, 如2024);
SHORT3: 时(0-23);
SHORT4: 分(0-59);
SHORT5: 秒(0-59).
文件本身日期可能会被操作系统修改, 该段避免了这点. 如果未使用, 0填充.
14 41byte Job Name/ID 作业名/ID. C风格字符串, 须以NUL byte结尾. 如果未使用, 可用NUL byte或space填充(非结尾部分).
15 6byte Job Time 图像保存时作业运行时间, 由3个SHORT值组成:
SHORT 0: 时(0-65535);
SHORT 1: 分(0-59);
SHORT 2: 秒(0-59).
如未使用, 0填充.
16 41byte Software ID 软件ID, C风格字符串.
17 3byte Software Version 软件版本, C风格字符串.
SHORT(byte0~1): 版本号*100;
BYTE(byte 2): 版本字母.
e.g 版本号4.17b, 对应SHORT=417, BYTE='b'.
如未使用, SHORT=0b0, BYTE=space
18 4byte Key Color 图像保存时的关键颜色, 可认为是"背景颜色"或"透明颜色". 格式: A:R:G:B, 其中A(最高字节)是α通道.
如未使用, 设置为0.
19 4byte Pixel Aspect Ratio 像素纵横比.
SHORT 0: 分子(像素宽);
SHORT 1: 分母(像素高).
如果都设为相同非0值, 则图像用方形像素组成; 分母为0表示未指定.
20 4byte Gamma Value gamma值分数形式.
SHORT 0: gamma分子;
SHORT 1: gamma分母.
结果值应在0~10.0, 精度1位小数. 未校正的图像结果值应为1.0. 分母设为0, 表示未使用gamma段.
21~27 这部分不常用到, 略.

TGA文件脚注(TGA FILE FOOTER)

解析TGA文件时,如何判定是Origin TGA格式(v1.0)还是New TGA格式(v2.0)?
可读取TGA文件的最后26byte脚注来实现.

合法的脚注,byte8~23为签名"TRUEVISION-XFILE". 如果检测到签名,则为New TGA,说明包含Develop Area, Extension Area;否则,为Origin TGA.

Byte 0-3: The Extension Area Offset 扩展区域位置由该值决定;
Bytes 4-7: The Developer Directory Offset 见下文;
Bytes 8-23: The Signature 签名, 用于判定是否为NEW TGA
Byte 24: ASCII Character “.” NEW TGA固定值
Byte 25: Binary zero string terminator (0x00) 固定值

注意:不要求开发者读写、使用Extension或Develop Area,这些是可选的. 但推荐文件包含TGA File Footer.

域编号(field no.) 长度 域名 描述
28 4byte Extension Area Offset Extension Area的offset值, 从文件开头开始算, 可用seek()函数定位. 0表示无Extension Area.
29 4byte Developer Directory Offset Developer Directory的offset值. 0表示无Developer Directory Area.
30 16byte Signature 签名, NEW TGA是"TRUEVISION-XFILE"
31 1byte Reserved Character 保留. 须为".", 否则不认为是正确的TGA文件
32 1byte Binary Zero String Terminator 二进制0终结符. TGA脚注可解读为C风格字符串.

图像类型(Image Type)

解读由Field 2(Color Map Type)和Field 3(Image Type)决定的图像类型,方便判断什么时候该用什么类型.

1: 颜色表图像类型

用于存储颜色表图像,如VDA/D,TARGA M8或颜色表TrueVista图像. 该格式能快速获取、显示,但会耗费较多存储空间. 适用于存储和显示时间很关键,但文件大小不重要的情形.

文件格式要求:Color Map Type = 0x01, Image Type = 0x01.

2: 真彩图像

用于存储图像,其中每个像素都由红、绿、蓝表示(例如,ICB、TARGA 16、TARGA 24、TARGA 32、 TrueVISTA图像). 适用于存储和显示时间非常重要,但文件大小不重要的情形.

文件格式要求:Color Map Type = 0x01, Image Type = 0x02.

3: 黑白无颜色表图像

用于存储光栅图像,其中每个像素由灰度值表示(如TARGA 8, M8及一些TrueVista模式).

文件格式要求:Color Map Type = 0x00, Image Type = 0x03.

9: RLE压缩的颜色表图像

用于存储每个像素都由颜色表索引表示的图像.RLE算法压缩图像,节约大量存储空间.

文件格式要求:Color Map Type = 0x01, Image Type = 0x09.

10: RLE压缩的真彩图像

用于存储光栅图像,其中每个像素由红、绿、蓝表示. RLE算法压缩图像. 该格式用于存储ICB、TARGA 16/24/32、TrueVISTA(16bit RGB, 32bit RGB模式)图像. 适用于由计算机生成的图像,包含大段相同颜色.

文件格式要求:Color Map Type = 0x00, Image Type = 0x0A.

11: RLE压缩的黑白图像

用于存储光栅图像,其中每个像素由灰度值表示. RLE压缩图像. 用于存储黑白TARGE 8/M8,及计算机生成的包含大段相同颜色的图像.
文件格式要求:Color Map Type = 0x00, Image Type = 0x0B.

RLE编码算法

RLE(run-length encoding),即游程编码、行程编码,是一种无损文件压缩算法. 图像数据类型9、10用到了RLE压缩图像.

RLE算法思想:连续相同的数值,用 重复数 + 数值 表示. 例如,文本文件中,原始字符串"AABCCC",经RLE编码后,变成"2A1B3C".

对于图像文件,用RLE算法对图像数据(Image Data)进行编码,所得图像称为RLE图像. 其中,包含2类数据元素:RLE packet、Raw packet.

packet格式

每个packet的第1个byte,称为Repetition Count field(重复数字段). 第2个byte,称为Pixel Value field(像素值字段).

packet格式如下图所示:

img

  • packet类型(packet type)

第1个byte的bit7(最高位):
1 - 表明该packet是RLE packet;
0 - Raw packet.

  • 重复数(Repetition Count)

指明后面Pixel Value重复的次数,范围0~127.
注意:实际重复次数 = Repetition Count + 1,即值0表示重复次数1,1表示重复次数2,...,127表示重复次数128.

  • Pixel Value

对于RLE packet, 会合并连续相同的像素,用1个Pixel Value表示这些连续的像素,而Repetition Count对连续相同像素进行计数;
对于Raw packet,不会进行合并,像素原来是怎么存储的,现在依然不变,但Repetition Count会对这些连续相同的像素计数.

例如,扫描到图像的一行有128个连续相同的像素,每个像素有24bit(3byte). 现用RLE算法进行压缩. 需要多少存储空间?
如果用Raw packet,那么需要3byte * 128 = 384byte,再加上1byte Repitition Count,总计385byte;
如果用RLE packet,那么需要3byte表示重复像素,再加上1byte Repitition Count,总计4byte.

也就是说,Raw packet并不会减少图像存储空间,相反,会增加存储空间.

关于跨行

对于RLE packet,编码像素时,即使行尾与下一行头像素相同,绝不应该跨行. 应该怎么做?
编码为独立的packet,而不是同一个. 因为这样,软件能用扫描线快速随机访问每行.

参考

TGA 2.0 File Format Specifications

TGA File Format Summary

【数据压缩】TGA文件格式分析 | CSDN

【数据压缩2】TGA格式图片文件分析 | CSDN

posted @ 2024-02-22 22:39  明明1109  阅读(408)  评论(0编辑  收藏  举报