图片RGB数据格式

相关博客:
[YUV图片原理]https://yangandmore.github.io/2019/03/14/%E5%9B%BE%E7%89%87YUV%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F/
[RGB图片原理]https://yangandmore.github.io/2019/03/27/%E5%9B%BE%E7%89%87RGB%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F/
[libyuv for android库编译和简单使用]https://yangandmore.github.io/2019/03/07/libYUV%E7%BC%96%E8%AF%91/
[libturbojpeg for android库编译和简单使用]https://yangandmore.github.io/2019/03/08/libjpeg-turbo%E7%BC%96%E8%AF%91/
[yuv-tool for android库的项目]https://yangandmore.github.io/2020/07/13/yuv-tool%E5%B7%A5%E5%85%B7%E7%B1%BB/
[turbo-jpeg-tool for android库的项目]<>

一、RGB简介

三原色:Red、Green、Blue。每一种颜色值的范围是0~255。

二、格式

RGB在主要分为两大类,一种是索引形式,一种是像素形式

索引形式

如RGB1, RGB4,RGB8。分别表示每个像素用1个bit, 4个bit, 8个bit来表示,那么,这些bit存储的并非是实际的R、G、B值,而是对应点的像素在调色板中的索引。
这些格式是比较老的格式,比较节省空间,在计算机发展的初期存储的成本还是很高的,但是表现的色彩很有限。
关于调色板,可以简单理解为通过编号映射到颜色的一张二维表。如01索引,表示红色。采用索引格式的RGB,红色的像素对应存储的值便是索引01.
github

RGB1

每个像素用1个bit表示,可表示的颜色范围为双色,即最传统的黑和白。1个bit只能表示0,1两种值。需要调色板,不过调色板只包含两种颜色。

RGB4

每个像素用4个bit表示,4个bit所能够表示的索引范围是0-15,共16个。也就是可以表示16种颜色。即调色板中包含16中颜色。

RGB8

每个像素用8个bit表示。8个bit所能够表示的索引范围是0-255,共256个。也就是可以表示256中颜色。即调色板中包含256中颜色。

像素形式

如RGB565,RGB555, RGB24,RGB32,ARGB32。存储的是每一个像素点的R、G、B值。比如RGB24,分别用8个bit去表示R, G, B。
主流的有RGB565,RGB555, RGB24,RGB32, ARGB32,每一种格式按照简介,存储示意图,以及获取具体像素的方法来讲解

RGB565

每个像素用16比特位表示,占2个字节,RGB分量分别使用5位、6位、5位。
github

RGB555

每个像素用16比特位表示,占2个字节,RGB分量都使用5位(最高位不用)。
github

RGB24格式(BGR)

RGB24图像每个像素用8比特位,共24个为表示,共3个字节,注意:在内存中RGB各分量的排列顺序为:BGR
github

RGB32格式(BGRA)

RGB32图像每个像素用32比特位表示,占4个字节,R,G,B分量分别用8个bit表示,存储顺序为B,G,R,最后8个字节保留。注意:在内存中RGB各分量的排列顺序为:BGRA
github

三、PNG、JPEG、BMP

PNG

是一种无损压缩的位图图形格式 。其设计目的是试图替代GIF和TIFF文件格式,同时增加一些GIF文件格式所不具备的特性。PNG的名称来源于“可移植网络图形格式。压缩比高,生成文件体积小。

特点

  • 体积小
  • 无损压缩,采用LZ77算法的派生算法,具有较高的压缩比,不损失数据。它利用特殊的编码方法标记重复出现的数据,因而对图像的颜色没有影响,也不可能产生颜色的损失,这样就可以重复保存而不降低图像质量。
  • 索引彩色模式,PNG-8格式与GIF图像类似,同样采用8位调色板将RGB彩色图像转换为索引彩色图像。
  • 网络传输显示采用流式浏览,即使经过交错处理的图像会在完全下载之前提供浏览者一个基本的图像内容,然后再逐渐清晰起来。它允许连续读出和写入图像数据,这个特性很适合于在通信过程中显示和生成图像。
  • 支持透明效果:PNG可以为原图像定义256个透明层次,使得彩色图像的边缘能与任何背景平滑地融合,从而彻底地消除锯齿边缘。这种功能是GIF和JPEG没有的。
  • PNG同时还支持真彩和灰度级图像的Alpha通道透明度。最高支持24位真彩色图像以及8位灰度图像。
  • 支持图像亮度的Gamma校准信息。
  • 支持存储附加文本信息,以保留图像名称、作者、版权、创作时间、注释等信息。
  • 使用CRC防止文件出错。
  • 最新的PNG标准允许在一个文件内存储多幅图像。

结构

由一个8字节的PNG文件署名域和按照特定结构组织的3个以上的数据块组成。

文件署名域

8字节的PNG文件署名域用来识别该文件是不是PNG文件。该域的值是:
89 50 4e 47 0d 0a 1a 0a

数据块类型码命名约定

  • 辅助位: 第一个字节的第5位是0(大写)=关键,1(小写)=辅助。一个解码器遇到一个不能识别的块时,如果发现辅助位为1则可以放心地忽略该块,并继续显示图像。
  • 私人位:第二个字节的第5位是0(大写)=公用,1(小写)=私人。应用程序也可以定义私有(未注册)块来达到自己的目的。需要注意的是解码器并不需要理会块的私人位——因为它没有功能上的意义,它只是一个管理上的便利,以确保公共块和私人块名称不会冲突。
  • 保留位:第三个字节的第5位必须为0(大写)。该位的意义是为将来可能的扩展保留。
  • 安全拷贝位:第4个字节的第5位是0(大写)=复制不安全,1(小写)=复制安全。
    该位为0(大写),表示该块的内容随图像数据的更新而更新,如果修改了任何关键数据块(包括增添、修改、删除以及关键块的重新排序),就不要把不能识别且“复制不安全”的块输出到新的png文件中。(如果png编辑器可以识别该块,那么当然可以选择输出适当修改后的版本) 该位为1(小写),表示不论png编辑器是否可以识别该块,也不管png文件被多大程度地修改,该块都可以被拷贝到修改后的png文件中。
    如果只有辅助块的增添、删除、修改或辅助块的重新排序,png编辑器将总是被允许将不能识别的辅助块拷贝到修改后的png文件中,这就要求:不论”安全拷贝位“如何设置,一个辅助块都不能仅随其它辅助块的更新而更新。 如果png编辑器遇到一个不能识别的关键块,因为没有办法确定修改包含这种块的文件后png文件还是否有效,所以png编辑器应立刻停止修改这个png文件。
    ** 复制安全/不安全的机制是为辅助块设计的。对于关键块,”安全拷贝位“应该总是为0。

数据块结构

PNG定义了两种类型的数据块,一种是称为关键数据块,这是必需的数据块,另一种叫做辅助数据块,这是可选的数据块。关键数据块定义了4个标准数据块,每个PNG文件都必须包含它们,PNG读写软件也都必须要支持这些数据块。
| 名称 | 字节数 | 说明 |
| ——————————————- | ———— | ————————————————————— |
| Length(长度) | 4字节 | 指定数据块中数据的长度,不超过2^31 - 1字节 |
| Chunk Type Code(数据块类型码) | 4字节 | 数据块类型码有ASCⅡ组成 |
| Chunk Data(数据块数据) | 可变长度 | 存储Chunk Type Code指定的数据 |
| CRC | 4字节 | 存储用来检测是否错误的循环冗余码 |

关键数据块

关键数据块的组成如下:

数据块符号 数据块名称 多数据块 可选否 位置限制
IHDR 文件头数据块 第一块
PLTE 调色板数据块 在IDAT之前
IDAT 图像数据块 与其他IDAT连续
IEND 图像结束数据 最后一个数据块
  • IHDR:文件头数据块IHDR(header chunk):它包含有PNG文件中存储的图像数据的基本信息,并要作为第一个数据块出现在PNG数据流中,而且一个PNG数据流中只能有一个文件头数据块。
  • PLTE:调色板数据块PLTE(palette chunk)包含有与索引彩色图像(indexed-color image)相关的彩色变换数据,它仅与索引彩色图像有关,而且要放在图像数据块(image data chunk)之前。PLTE数据块是定义图像的调色板信息,PLTE可以包含1~256个调色板信息,每一个调色板信息由3个字节组成。
  • IDAT:图像数据块IDAT(image data chunk):它存储实际的数据,在数据流中可包含多个连续顺序的图像数据块。IDAT存放着图像真正的数据信息,因此,如果能够了解IDAT的结构,我们就可以很方便的生成PNG图像。
  • IEND:图像结束数据IEND(image trailer chunk):它用来标记PNG文件或者数据流已经结束,并且必须要放在文件的尾部。如果我们仔细观察PNG文件,我们会发现,文件的结尾12个字符看起来总应该是这样的:
    0000000049454E44AE426082,不难明白,由于数据块结构的定义,IEND数据块的长度总是0(00 00 00 00,除非人为加入信息),数据标识总是IEND(49 45 4E 44),因此,CRC码也总是AE 42 60 82。

辅助数据块

数据块符号 数据块名称 多数据块 可选否 位置限制
cHRM 基色和白色点数据块 在PLTE和IDAT之前
gAMA 图像Y数据块 同上
sBIT 样本有效位数据块 同上
bKGD 背景颜色数据块 在PLTE之后IDAT之前
hIST 图像直方图数据块 同上
tRNS 图像透明数据块 同上
oFFs 专用公共数据块 在IDAT之前
pHYs 物理像素尺寸数据块 同上
sCAL 专用公共数据块 同上
tIME 图像最后修改时间数据块 无限制
tEXt 文本信息数据块 同上
zTXt 压缩文本数据块 同上
fRAc 专用公共数据块 同上
gIFg 专用公共数据块 同上
gIFt 专用公共数据块 同上
gIFx 专用公共数据块 同上

JPEG

JPEG的全称是JointPhotographicExpertsGroup。它是一种常用的图像存储格式, jpg/jpeg是24位的图像文件格式,也是一种高效率的压缩格式。
JPEG格式可以分为标准JPEG、渐进式JPEG和JPEG2000三种格式。

  • 标准JPEG:只有图片完全被加载和读取完毕之后,才能看到图片的全貌。压缩比在10:1到40:1之间,压缩比越大,品质就越差,压缩比越小,品质就越好PEG由于可以提供有损压缩,因此压缩比可以达到其他传统压缩算法无法比拟的程度。其压缩模式有以下几种:顺序式编码(SequentialEncoding),递增式编码(ProgressiveEncoding),无失真编码(LosslessEncoding)和阶梯式编码(HierarchicalEncoding)。
    颜色转换:由于JPEG只支持YUV颜色模式,而不支持RGB颜色模式,所以在将彩色图像进行压缩之前,必须先对颜色模式进据转换。 DCT变换:是将图像信号在频率域上进行变换,分离出高频和低频信息的处理过程。然后再对图像的高频部分(即图像细节)进行压缩,以达到压缩图像数据的目的。对每一个矩阵作DCT变换。变换后得到一个频率系数矩阵,其中的频率系数都是浮点数。
    量化:由于在后面编码过程中使用的码本都是整数,因此需要对变换后的频率系数进行量化,将之转换为整数。由于进行数据量化后,矩阵中的数据都是近似值,和原始图像数据之间有了差异,这一差异是造成图像压缩后失真的主要原因。 编码:编码采用两种机制:1.是0值的行程长度编码;2.熵编码。
  • 渐进式JPEG:该类型的图片是对标准JPEG格式的改进,当在网页上下载渐进式JPEG图片时,首先呈现图片的大概外貌,然后再逐渐呈现具体的细节部分,因而被称之为渐进式JPEG。
  • JPEG2002:在具有标准JPEG格式和渐进式的基础上,提高压缩率,同时支持有损压缩和无损压缩。

格式

SOI(文件头)+APP0(图像识别信息)+ DQT(定义量化表)+ SOF0(图像基本信息)+ DHT(定义Huffman表) + DRI(定义重新开始间隔)+ SOS(扫描行开始)+ EOI(文件尾)
除了DRI以外,其他都是必须的组成部分。

JPEG文件的格式是分为一个一个段来存储的。
其中段有标识、类型、长度和内容组成:
段 = 段标识 + 段类型 + 段长度 + 段内容

  • 段标识:一个字节:0xFF
  • 段类型:一个字节,共有30种,这里只列除必须被所有程序识别的10种。
名称 标记码 说明
SOI D8 文件头
EOI D9 文件尾
SOF0 C0 起始帧
SOF1 C1 起始帧
DHT C4 定义Huffman表
SOS DA 扫描行开始
DQT DB 定义量化表
DRI DD 定义重新开始间隔
APP0 E0 定义交换格式和图像识别信息
COM FE 注释
  • 段长度:除去段标识和段类型后剩余的字段长度

SOI文件头

作为JPEG文件的起始2个字节为SOI文件头:
FF D8

APP0图像识别信息

名称 字节数 说明
段标识 1 FF 段起始字节
段类型 1 E0 段类型为APPO
段长度 2 0010 假设除去缩略图后的值为16
交换格式 5 4A46494600 JFIF格式
主版本号 1
次版本号 1
密度单位 1 无单位(0)、点数/英寸(1)、点数/厘米(2)
X像素密度 2 水平方向的密度
Y像素密度 2 垂直方向的密度
缩略图X像素 1 缩略图水平像素数目
缩略图Y像素 1 缩略图垂直像素数目
RGB缩略图 3*n

JFIF是文件交换格式的一种

DQT定义量化表

名称 字节数 说明
段标识 1 FF
段类型 1 DB 段类型为量化表
段长度 2 3+n
QT信息 1 1 0-3位QT号,4-7位QT精度
QT n n=64×QT精度的字节数

JPEG文件一般有2个DQT段,为Y值定义一个,为C值定义一个。

SOF0图像基本信息

名称 字节数 说明
段标识 1 FF
段类型 1 C0 段类型为起始帧
段长度 2
样本精度 1 8 每个样本位数(大多数软件不支持12和16)
图片高度 2
图片宽度 2
组件数量 1 3 灰度图(1)、彩图YUV/YIQ(3)、CMYK彩色图(4)
组件ID 1 Y(1)、Cb(2)、Cr(3)、I(4)、Q(5)
采用系数 1 0-3位:垂直采用系数、4-7位:水平采用系数
量化表号 1

由于JPEG大都采用YUV,因此一般组件数量都是3个。

DHT定义huffman表

名称 字节数 说明
段标识 1 FF
段类型 1 C4 段类型为huffman表
段长度 2
HT信息 1 8 0-3位:HT号、第4位HT类型:DC表(0),AC表(1)、5-7位:必须位0
HT位表 16 这16个数的和应该≤256
HT值表 n 表头16个数的和

JPEG文件里有2类Haffman 表:一类用于DC(直流量),一类用于AC(交流量)。一般有4个表:亮度的DC和AC,色度的DC和AC。最多可有6个。

SOS扫描行开始

名称 字节数 说明
段标识 1 FF
段类型 1 DA 段类型为扫描行开始
段长度 2
扫描行内组件数量 1 3 必须≥1,≤4,通常为3
组件ID 1 Y(1)、Cb(2)、Cr(3)、I(4)、、Q(5)
Huffman表号 1 0-3位:AC表号(0、3);4-7位:DC表号(0、3)
最后3个字节 3

每个组件2个字节,分别是组件ID和Huffman表号。

EOI文件尾

文件尾为:
FF D9

其他段

注释段

名称 字节数 说明
段标识 1 FF
段类型 1 FE 段类型为注释
段长度 2
段内容 注释字符

DRI

定义重新开始间隔
| 名称 | 字节数 | 值 | 说明 |
| ———— | ——— | — | ————————— |
| 段标识 | 1 | FF | |
| 段类型 | 1 | DD | |
| 段长度 | 2 | 4 | |
| 开始间隔 | 2 | n | 复位标记的间隔距离 |

开始间隔表示在压缩数据流中,每隔n个MCU 块就有一个RST标记,RST标记将Huffman 的解码数据流复位,DC也重新从0开始,因此,RST标记是一种复位标记。
RST 标记是一种特殊的段,它只具有段标识和段类型(长度=2字节),但它不是独立的段。
RST标记共有8个(RST0-RST7),从RST0起开始使用,然后是RST1….直至RST7,再从RST0重复。
RST标记的标识码是 FFD0-FFD7,对应 RST0-RST7

BMP

BMP(Bitmap-File)图形文件是Windows采用的图形文件格式,在Windows环境下运行的所有图象处理软件都支持BMP图象文件格式。

格式

BMP图片的组成部分:BMP文件头(14 bytes) + 位图信息头(40 bytes) + 调色板(由颜色索引决定) + 位图数据(由图像尺寸决定)

BMP文件头

  • 第1、2位字节位定值:

    BM:windows
    BA:os/2 bitmap array
    CI:os/2 color icon
    CP:os/2 color pointer
    IC:os/2 icon
    PT:os/2 pointer

  • 第3-6位字节位该位图文件的大小。(位图文件大小是指整个文件的大小、包含信息头等)

    例:36 08 07 00 -> 00 07 08 36 -> 460854 = 451kb

  • 第7-10位字节位保留位,共4个字节,必须设置位0
  • 最后4个字节是文件头开始到实际图像数据之间的字节偏移量

    例:36 00 00 00 -> 00 00 00 36 -> 54个字节

位图信息头

共40 bytes

  • 第1-4位字节表示位图信息头需要的字节数

    例:28 00 00 00 -> 00 00 00 28 -> 40个字节

  • 第5-8位字节表示图像宽度,以像素为单位

    例:40 01 00 00 -> 00 00 01 40 -> 320

  • 第9-12位字节表示图片高度,以像素位单位。需要注意这个数值是有符号数据,正数表示倒向位图,负数则是正向位图,大多BMP图片都是倒向位图(倒向位图:图片数据从左下角到右上角排列)
  • 第13-14位字节为目标设备说明颜色平面数,其值蒋总被设为101 00
  • 第15-16位字节为比特数/像素,即位图。其值为1、4、8、16、24、32。
  • 第17-20位字节为图像数据压缩类型:

    0:不压缩
    1:8比特编码(RLE),只用于8位位图
    2:4比特编码(RLE),只用于4位位图
    3:比特域,用于16/32位位图
    4:位图含JPEG图像(仅用于打印机)
    5:位图含PNG图像(仅用于打印机)

  • 第21-24位字节位图像大小(仅包含数据,不包含文件头和信息头),单位为字节。当压缩类型为0时,此处可以设置为0
  • 第25-28位字节为水平分辨率,单位像素/米,有符号整数
  • 第29-32位字节为垂直分辨率,单位像素/米,有符号整数
  • 第33-36位字节为颜色表中的颜色索引数,设置为0时,说明使用所有的颜色板项,一般与第15-16位字节的位图数匹配,一般指多少颜色
  • 第37-40位字节表示对图像显示有重要影响的颜色索引数码(为0时表示都重要)

调色板

调色板的大小主要决定与第33-36位的颜色索引数N。
调色板大小 = N*4(4为BGRA的分量)

位图数据

由于位图信息头中的位图高度是正的,所以位图数据在文件中的排列顺序是从左下角到右上角,以行为主序排列的。也就是第一个数据(此处指前3个bytes)是图像最后一行第一列像素色彩数据,第二个数据是图像最后一行第二列像素色彩数据。

如果RGB 24位位图则使用3个bytes存储一个像素,按照BGR顺序存储。如果是32位ARGB数据则按照BGRA的顺序存储。
如果存在调色板,则这些值代表的是调色板的索引序号。