图片的格式与压缩
2016-12-05 20:33
866 查看
BMP是一种与硬件无关的图像文件格式,采用位映射的存储格式,除了图像深度可选,不采用其他的任何压缩,因此BMP图片占用的空间很大。BMP图片的图像深度可选1bit、4bit、8bit、16bit、24bit、32bit,BMP文件存储为数据时,图像的扫描方式是按从左到右、从上到下的顺序。
典型BMP文件有三部分组成:位图文件头数据结构,它包含BMP图像文件的类型、显示内容等信息;位图信息数据结构,它包含有BMP图像的宽、高、压缩方法以及定义颜色等。
JPEG是Joint Photographic Experts Group(联合去向专家组)的缩写,文件后缀名为.jpg或.jpeg,是一种有损压缩格式,能够将图像压缩在很小存储空间,图像中重复或不重要的资料会被丢失,因此造成图像数据的损伤,尤其过高的压缩比例,将事最终解压的图片质量降低。JPEG的压缩比例通常在10:1到40:1之间,压缩比越大品质越低。JPEG格式压缩的主要是高频信息,对色彩信息保留比较好,适用于互联网。
可以使用winhex打开一个JPEG图片来查看JPEG图片的数据,0xFF,0xD8是图像开始的标记。标识数据压缩的开始,标记是用来标识压缩数据格式中不同是结构单元的,所有的标记都是有1个0xFF字节和一个不等于0或0xFF自己组成的:
0xFF,0xE0:应用数据的标记(APP0),标识应用数据段的开始
0x00,0x10:应用数据长度参数(Lp),该参数本身长度为两个字节,其值表示应用数据段包含的字节数,但是不包括APP0两个字节,长度为16个字节。
0x4A,0x46,0x49,0x46,0x00:文件标识符,即"JFIF"+"NUL"的ASCII码;
0x01,0x01:文件版本号,一般为0x01 0x01 或0x01 0x02;
0x01:表示X和Y的密度单位,值为0,无单位,只为1单位为“点数/英寸”,值为2 单位为"点数/厘米"
0x00 0x60:表示X轴方向的密度。
0x00 0x60:表示Y轴方向的密度。
0xFF 0xDB:定义量化表标记(DQT)标明量化表说明参数的开始,可能有多个量化表标记,分别用量化表0、量化表1....量化表N。这里表示量化表0;
0x00 0x43:量化表的长度参数,其值表示量化表包含的字节个数,这里长度为67个字节。
0x00 :前4位为量化表元素精度参数,值为0表示元素精度为8,值为1表示量化表元素精度为16.后4位为量化表目标标识符,指定位于解码器中的4个可能目标中的1个用于安装量化表,这里只目标0;
0x08 0x06 0x06 .... 0x32 :量化表元素,64个字节。
0xFF 0xDB:量化表标记,这里表示量化表。
0x00 0x43:量化表长度参数。
0x01:前4位为量化表的精度参数,后4位为量化表的目标表示符,这里为量化表1.
0x09 0x09 .... 0x32 ,共64个字节的量化表元素。
0xFF 0xC0:帧开始标记,下标为0表示编码过程类型为DCT;
0x00 0x11:帧头标长度参数,该参数本身长度为两个字节,表示帧头标包含的字节数,这里的长度为17个字节。
0x08:采样精度,这里为8位。
0x00 0xB5:行数(Y),指定源图像中最大的行数,这里为181行。
0x01 0x40:每行样本数(X),指定源图像中每行的最大采样数320,
因为我保存的图像像素点数为320*240,所以这个图像的行数和列数与实际图像大小相关。
0x03:帧中图像的分量数(Nf),指定帧中源图像的分量数。
0x01:分量标记符,用来指明帧分量说明参数序列中的哪一个分量,这里是C1,即第一个分量。
0x22:前4位为水平的采样因子H,表示指定分量水平尺寸和最大图像尺寸X之间的关系,后4位为垂直采样因子V,指定分量垂直尺寸和最大图像尺寸Y之间的关系。
0x00:量化表目标选择器,用来选择4个可能量化表目标中的哪一个,从中检索用于本分量的DCT系数逆量化的量化表,这里表示本分量选择量化表0.
0x02:分量标记符,这里是C2,即第二个分量。
0x11:前4位为水平采样因子(H2);后4位为垂直采样因子(V2).
0x01:量化表目标选择器,这里表示本分量选择量化表1;
0x03:分量标记符,这里是C3,即第三个分量。
0x11:前4位为水平采样因子H3,后四位为垂直采样因子V3.
0x01:量化表目标选择器,这里表示本分量选择量化表1.
0xFF 0xC4: 哈夫曼表定义参数的开始。
0x00 0x1F: 哈夫曼表的长度参数表示哈夫曼表的字节数,长度为31个字节。
0x00: 前4位为表类型,值为0代表DC表或无失真,值为1 代表AC表;后4位是哈夫曼表目标标志符,指定位于解码器中的4个可能目标中的1个用于安装哈夫曼表,这表表示的是DC-0(类型-目标)哈夫曼表;
0x00 0x01 0x05 0x01 0x01 0x01 0x01 0x01 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 :长度为i的哈夫曼表共16个字节,分别为JPEG说明中允许的哈夫曼代码长度为1到16的每个码长指定代码数目,这里表示代码长度为1的哈夫曼代码有0个,代码长度为2的哈夫曼代码有1个,代码长度为3的哈夫曼代码有5个等等。
0x00 0x01 0x02 0x3 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0B,针对代码数目列出长度为i的哈夫曼代码值,如下:
L1=0,没有码长为1的哈夫曼代码。
L2=1,码长为2的哈夫曼代码值是0x00.
L3=5, 码长为3的哈夫曼代码值是0x01 0x02 0x03 0x04 0x05.
L4=1, 码长为4的哈夫曼码值是0x6。
L5=1 码长为5的哈夫曼码值是0x7。
L6=1 码长为6的哈夫曼码值是0x8。
L7=1 码长为7的哈夫曼码值是0x9。
L8=1 码长为8的哈夫曼码值是0xA。
L9=1 码长为9的哈夫曼码值是0xB。
L10到L16均为0,所以么有码长为10~16的哈夫曼代码。
0xFF 0xC4:定义哈夫曼表标记。
0x00 0xB5:哈夫曼长度,这里长度为181个字节。
0x10:前4位为表类型,后4位是哈夫曼表目标标志符,这里表示的是AC-0哈夫曼表
0x00 0x02 0x01 。。。0x7D 表示长度为i的哈夫曼代码数目。
0x01 0x02 .... 列出了针对Li长度为i的哈夫曼代码值,共162个字节。
0xFF 0xC4 定义哈夫曼表标记。
0x01:前4位表示表类型,后4位是哈夫曼表目标标志符,这里表示的是DC-1哈夫曼表。
0xFF 0xDA:扫描开始标记,标明扫描参数开始的位置。
0x00 0x0C:扫描头标长度参数,12个字节。
0x03:扫描行中图像分量数目。
0x01:扫描分量选择器,这里表示第一个分量。
0x00:前4位为DC熵编码目标选择器,从4个可能的DC熵编码表目标中选出1个目标。后4位从AC熵编码表目标选出1个目标。
0x02:扫描分量选择器,这里表示第二个分量。
0x11:前4位为DC熵编码表目标选择器,后4位为AC熵编码表目标选择器。
0x00:指定Z型序列中每个块中的第一个DCT参数,对于顺序的DCT过程该参数设置为0;
0x3F:频谱选择参数。
0x00:前4位为后续近似位置高参数,后4位为后续近似位位置低或点变换参数。一般设置为0
0xF7 0xFA .....,压缩图像数据。
0xFF 0xD9:图像结束标记。
二、JPEG的编码解码
JPEG专家组开发了两种基本的压缩算法、两种数据编码方法、四种编码模式。
压缩算法:有损的离散余弦变换(Siscrete Consine Transform,DCT) ,无损的预测技术压缩。
数据编码方法:哈夫曼编码、算术编码
编码模式:基于DCT顺序模式—编/解码通过一次扫描完成;基于DCT递进模式—编/解码需要多次扫描完成,扫描效果从粗糙到精细,逐级递进;无损模式,基于DPCM,保证解码后完全精确恢复到原图像采样值;层次模式,图像在多个空间多个分辨率进行编码。
在实际应用中,JPEG图像使用的离散余弦变换、哈夫曼编码、顺序模式。
JPEG压缩算法的主要计算步骤如下:
① 8*8分块
② 正向离散余弦变换(FDCT)
③ 量化(quantization)
④ Z字形编码(zigzag scan)
⑤ 使用差分脉冲编码调制(DPCM)对直流系统(DC)进行编码
⑥ 使用行程长度编码(RLE)对交流系统(AC)进行编码。
⑦ 熵编码
2.1、JPEG文件格式介绍
JPEG文件是数据存储格式有多种,最常用的格式为JPEG文件交换格式(JPIF).JPEG文件大体上分为两个部分:标记码(Tag)和压缩数据。
标记码由两个字节构成,前一个字节是固定值0xFF,后一个字节根据不同意义有不同的数值。多个连续的0xFF可以被理解为一个0xFF并表示标记码的开始,在一个两字节标记码后,就是标记码对应的压缩数据流,记录了文件的多种信息。
常用的标记码有SOI、APP0、DQT、SOF0、DHF、DRI、SOS、EOI。
SOI:图像开始,固定值 0xFF 0xD8
APP0:应用程序保留标记0,固定值0xFF 0xE0,包含9个具体字段:
9个字段数据长度(2个字节)、
标识符即字符串JPIF0(5个字节)、
版本号(两个字节)0x0102表示JFIF0的版本是1.2
X和Y的密度单位(1个字节),有三个值可选0表示无单位,1表示点数/英寸,2表示点数/厘米。
X方向像素密度 2字节
Y方向的像素密度 2个字节
缩略图水平像素数目 1个字节
缩略图垂直像素数目 1个字节
缩略图RGB位图 长度可能是3的倍数
APPn,应用程序的保留标记n,n=1~15,固定值0xFFE1~0xFFF0.
DQT(Define Quantization Table) 定义了量化表,固定值0xFFDB
SOF0(start of Frame),帧图像开始 固定值0xFFC0.
DHF(Define Huffman Table),定义哈夫曼表,固定值0xFFC4
由于0xFF具有标志性的意思,实际数据流中出现0xff,在在数据0xFF后添加一个没有意义的0xFF,如果在数据流中遇到0xFF,应该检测紧接着的字符,如果是
0x00:表示是图像流的组成部分。
0xD9:图像流结束
0xD0~0xD7,促成RSTn标记。需要忽视两个字节。
0xff,忽视当前0xFF,对后一个字节在判断
其他数值,忽视当前0xFF,保留此数据用于译码。
2.2、解码过程
按照JPEG文件数据存储方式,设计一系列结构体对应各个标记,并存储标记内表示的信息,其中图像的长宽、多个量化表和哈夫曼表、水平/垂直的采样因子等重要信息。
整个GIGF0数据格式顺序为:
SOI(0xFFD8)
APP0(0xFFE0)
[APPn(0xFFEn)]可选
DQT(0xFFDB)
SOF0(0xFFC0)
DHT(0xFFC4)
SOS(0XFFDA)
压缩数据
EOI(0xFFD9)
JPEG文件格式,一个字(两个字节)存储使用Motorola格式及高字节在前低字节在后。
(1) 读哈夫曼表数据
在标记段DHT内,包含了一个或多个的哈夫曼表,对于单一哈夫曼表包括三个部分:
1) 哈夫曼表ID和表类型,这个字节的值只有四个,0x00 0x01 0x10 0x11。
0x00 表示DC直流0号表。
0x01 表示DC直流1号表
0x10 表示AC交流0号表
0x11 表示AC交流1号表
2) 不同位数的码字数量
JPEG文件的哈夫曼编码只能只能是1~16位。这个字段的16个字节分表表示1~16位的编码码字在哈夫曼树中的个数。
3) 编码内容
记录了哈夫曼树中各个叶子节点的权(不同位数的码字数量)。
解码过程:数据流 -> 最小编码单元(MCU) -> 数据单元与颜色分量
1) 在图片数据流中,信息被分为一段有单的最小编码单元数据流MCU。MCU是图像中一个正方矩阵像素的数据。矩阵大小是这样确定的:
查阅标记SOF0,可以得到图像不同颜色分量的采样因子,级Y、Cr、Cb三个分量各自的水平采样因子和垂直采样因子,大多图片的采样因子为4:1:1 或1:1:1其中4:1:1即(2*2):(1*1):(1*1),1:1:1即(1*1):(1*1):(1*1),记三个分量重水平采样因子最大值为Hmax,垂直采样因子最大值为Vmax,单个MCU矩阵宽就是Hmax*8像素,高就是Vmax*8像素,这里的Hmax为2、Vmax也为2.
如果正个图像宽度和高度不是MCU宽度和高度的整数倍,编码时会用某些数值填充。数据流中MCU的排列方法是从左到右,从上到下。
2) 每个MCU又分为若干个数据,数据单元大小必定是8*8,所以每个MCU数据单元个数是Hmax*Vmax。
JPEG的压缩方法与BMP文件有所不同,它不是把每个像素的颜色分量连续存储在一起,而是把图片分成Y、Cr、Cb三张子图分别压缩。三个颜色的采样因子可能一样(1:1:1),也可能不一样(4:1:1)。每个MCU内部,数据顺序是Y、Cr、Cb。如果一个颜色分量有多个数据单元,顺序是从左到右从上到下。
1、从文件头文件读出文件的相关信息
JPEG文件数据分为文件头和图像数据两大部分,其中文件头记录了图像的版本、长宽、采样因子、量化表、哈夫曼表等重要信息,解码前必须将文件头信息读出。
2、从图像数据流读取一个最小编码单元(MCU),并提取出里边的各个颜色分量单元。
3、将颜色分量单元从数据流回复成矩阵数据。
利用文件头给出的哈夫曼表,对分割出来的颜色分量单元进行解码,把其恢复成8x8的数据矩阵。
4、8x8数据矩阵进一步解码
此部分解码工作以8x8数据矩阵为单位,其中包括相邻矩阵的直流系统差分解码、利用文件头给出量化表反量化数据、反Zig-zag编码、隔行正负纠正、反向离散余弦变换等5个步骤,最终仍然是一个8x8的数据矩阵。
5、颜色系统YCrCb向RGB转换
将一个MCU的各个颜色分量单元解码结果整合起来,将图像颜色系统从YCrCb向RGB转换。
6、排列整合各个MCU解码数据。
不断读取数据流中的MCU并对其解码,直至读完所有的MCU位置,将各MCU解码后的数据正确排列成完整的图像。
典型BMP文件有三部分组成:位图文件头数据结构,它包含BMP图像文件的类型、显示内容等信息;位图信息数据结构,它包含有BMP图像的宽、高、压缩方法以及定义颜色等。
JPEG是Joint Photographic Experts Group(联合去向专家组)的缩写,文件后缀名为.jpg或.jpeg,是一种有损压缩格式,能够将图像压缩在很小存储空间,图像中重复或不重要的资料会被丢失,因此造成图像数据的损伤,尤其过高的压缩比例,将事最终解压的图片质量降低。JPEG的压缩比例通常在10:1到40:1之间,压缩比越大品质越低。JPEG格式压缩的主要是高频信息,对色彩信息保留比较好,适用于互联网。
可以使用winhex打开一个JPEG图片来查看JPEG图片的数据,0xFF,0xD8是图像开始的标记。标识数据压缩的开始,标记是用来标识压缩数据格式中不同是结构单元的,所有的标记都是有1个0xFF字节和一个不等于0或0xFF自己组成的:
0xFF,0xE0:应用数据的标记(APP0),标识应用数据段的开始
0x00,0x10:应用数据长度参数(Lp),该参数本身长度为两个字节,其值表示应用数据段包含的字节数,但是不包括APP0两个字节,长度为16个字节。
0x4A,0x46,0x49,0x46,0x00:文件标识符,即"JFIF"+"NUL"的ASCII码;
0x01,0x01:文件版本号,一般为0x01 0x01 或0x01 0x02;
0x01:表示X和Y的密度单位,值为0,无单位,只为1单位为“点数/英寸”,值为2 单位为"点数/厘米"
0x00 0x60:表示X轴方向的密度。
0x00 0x60:表示Y轴方向的密度。
0xFF 0xDB:定义量化表标记(DQT)标明量化表说明参数的开始,可能有多个量化表标记,分别用量化表0、量化表1....量化表N。这里表示量化表0;
0x00 0x43:量化表的长度参数,其值表示量化表包含的字节个数,这里长度为67个字节。
0x00 :前4位为量化表元素精度参数,值为0表示元素精度为8,值为1表示量化表元素精度为16.后4位为量化表目标标识符,指定位于解码器中的4个可能目标中的1个用于安装量化表,这里只目标0;
0x08 0x06 0x06 .... 0x32 :量化表元素,64个字节。
0xFF 0xDB:量化表标记,这里表示量化表。
0x00 0x43:量化表长度参数。
0x01:前4位为量化表的精度参数,后4位为量化表的目标表示符,这里为量化表1.
0x09 0x09 .... 0x32 ,共64个字节的量化表元素。
0xFF 0xC0:帧开始标记,下标为0表示编码过程类型为DCT;
0x00 0x11:帧头标长度参数,该参数本身长度为两个字节,表示帧头标包含的字节数,这里的长度为17个字节。
0x08:采样精度,这里为8位。
0x00 0xB5:行数(Y),指定源图像中最大的行数,这里为181行。
0x01 0x40:每行样本数(X),指定源图像中每行的最大采样数320,
因为我保存的图像像素点数为320*240,所以这个图像的行数和列数与实际图像大小相关。
0x03:帧中图像的分量数(Nf),指定帧中源图像的分量数。
0x01:分量标记符,用来指明帧分量说明参数序列中的哪一个分量,这里是C1,即第一个分量。
0x22:前4位为水平的采样因子H,表示指定分量水平尺寸和最大图像尺寸X之间的关系,后4位为垂直采样因子V,指定分量垂直尺寸和最大图像尺寸Y之间的关系。
0x00:量化表目标选择器,用来选择4个可能量化表目标中的哪一个,从中检索用于本分量的DCT系数逆量化的量化表,这里表示本分量选择量化表0.
0x02:分量标记符,这里是C2,即第二个分量。
0x11:前4位为水平采样因子(H2);后4位为垂直采样因子(V2).
0x01:量化表目标选择器,这里表示本分量选择量化表1;
0x03:分量标记符,这里是C3,即第三个分量。
0x11:前4位为水平采样因子H3,后四位为垂直采样因子V3.
0x01:量化表目标选择器,这里表示本分量选择量化表1.
0xFF 0xC4: 哈夫曼表定义参数的开始。
0x00 0x1F: 哈夫曼表的长度参数表示哈夫曼表的字节数,长度为31个字节。
0x00: 前4位为表类型,值为0代表DC表或无失真,值为1 代表AC表;后4位是哈夫曼表目标标志符,指定位于解码器中的4个可能目标中的1个用于安装哈夫曼表,这表表示的是DC-0(类型-目标)哈夫曼表;
0x00 0x01 0x05 0x01 0x01 0x01 0x01 0x01 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 :长度为i的哈夫曼表共16个字节,分别为JPEG说明中允许的哈夫曼代码长度为1到16的每个码长指定代码数目,这里表示代码长度为1的哈夫曼代码有0个,代码长度为2的哈夫曼代码有1个,代码长度为3的哈夫曼代码有5个等等。
0x00 0x01 0x02 0x3 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0B,针对代码数目列出长度为i的哈夫曼代码值,如下:
L1=0,没有码长为1的哈夫曼代码。
L2=1,码长为2的哈夫曼代码值是0x00.
L3=5, 码长为3的哈夫曼代码值是0x01 0x02 0x03 0x04 0x05.
L4=1, 码长为4的哈夫曼码值是0x6。
L5=1 码长为5的哈夫曼码值是0x7。
L6=1 码长为6的哈夫曼码值是0x8。
L7=1 码长为7的哈夫曼码值是0x9。
L8=1 码长为8的哈夫曼码值是0xA。
L9=1 码长为9的哈夫曼码值是0xB。
L10到L16均为0,所以么有码长为10~16的哈夫曼代码。
0xFF 0xC4:定义哈夫曼表标记。
0x00 0xB5:哈夫曼长度,这里长度为181个字节。
0x10:前4位为表类型,后4位是哈夫曼表目标标志符,这里表示的是AC-0哈夫曼表
0x00 0x02 0x01 。。。0x7D 表示长度为i的哈夫曼代码数目。
0x01 0x02 .... 列出了针对Li长度为i的哈夫曼代码值,共162个字节。
0xFF 0xC4 定义哈夫曼表标记。
0x01:前4位表示表类型,后4位是哈夫曼表目标标志符,这里表示的是DC-1哈夫曼表。
0xFF 0xDA:扫描开始标记,标明扫描参数开始的位置。
0x00 0x0C:扫描头标长度参数,12个字节。
0x03:扫描行中图像分量数目。
0x01:扫描分量选择器,这里表示第一个分量。
0x00:前4位为DC熵编码目标选择器,从4个可能的DC熵编码表目标中选出1个目标。后4位从AC熵编码表目标选出1个目标。
0x02:扫描分量选择器,这里表示第二个分量。
0x11:前4位为DC熵编码表目标选择器,后4位为AC熵编码表目标选择器。
0x00:指定Z型序列中每个块中的第一个DCT参数,对于顺序的DCT过程该参数设置为0;
0x3F:频谱选择参数。
0x00:前4位为后续近似位置高参数,后4位为后续近似位位置低或点变换参数。一般设置为0
0xF7 0xFA .....,压缩图像数据。
0xFF 0xD9:图像结束标记。
二、JPEG的编码解码
JPEG专家组开发了两种基本的压缩算法、两种数据编码方法、四种编码模式。
压缩算法:有损的离散余弦变换(Siscrete Consine Transform,DCT) ,无损的预测技术压缩。
数据编码方法:哈夫曼编码、算术编码
编码模式:基于DCT顺序模式—编/解码通过一次扫描完成;基于DCT递进模式—编/解码需要多次扫描完成,扫描效果从粗糙到精细,逐级递进;无损模式,基于DPCM,保证解码后完全精确恢复到原图像采样值;层次模式,图像在多个空间多个分辨率进行编码。
在实际应用中,JPEG图像使用的离散余弦变换、哈夫曼编码、顺序模式。
JPEG压缩算法的主要计算步骤如下:
① 8*8分块
② 正向离散余弦变换(FDCT)
③ 量化(quantization)
④ Z字形编码(zigzag scan)
⑤ 使用差分脉冲编码调制(DPCM)对直流系统(DC)进行编码
⑥ 使用行程长度编码(RLE)对交流系统(AC)进行编码。
⑦ 熵编码
2.1、JPEG文件格式介绍
JPEG文件是数据存储格式有多种,最常用的格式为JPEG文件交换格式(JPIF).JPEG文件大体上分为两个部分:标记码(Tag)和压缩数据。
标记码由两个字节构成,前一个字节是固定值0xFF,后一个字节根据不同意义有不同的数值。多个连续的0xFF可以被理解为一个0xFF并表示标记码的开始,在一个两字节标记码后,就是标记码对应的压缩数据流,记录了文件的多种信息。
常用的标记码有SOI、APP0、DQT、SOF0、DHF、DRI、SOS、EOI。
SOI:图像开始,固定值 0xFF 0xD8
APP0:应用程序保留标记0,固定值0xFF 0xE0,包含9个具体字段:
9个字段数据长度(2个字节)、
标识符即字符串JPIF0(5个字节)、
版本号(两个字节)0x0102表示JFIF0的版本是1.2
X和Y的密度单位(1个字节),有三个值可选0表示无单位,1表示点数/英寸,2表示点数/厘米。
X方向像素密度 2字节
Y方向的像素密度 2个字节
缩略图水平像素数目 1个字节
缩略图垂直像素数目 1个字节
缩略图RGB位图 长度可能是3的倍数
APPn,应用程序的保留标记n,n=1~15,固定值0xFFE1~0xFFF0.
DQT(Define Quantization Table) 定义了量化表,固定值0xFFDB
SOF0(start of Frame),帧图像开始 固定值0xFFC0.
DHF(Define Huffman Table),定义哈夫曼表,固定值0xFFC4
由于0xFF具有标志性的意思,实际数据流中出现0xff,在在数据0xFF后添加一个没有意义的0xFF,如果在数据流中遇到0xFF,应该检测紧接着的字符,如果是
0x00:表示是图像流的组成部分。
0xD9:图像流结束
0xD0~0xD7,促成RSTn标记。需要忽视两个字节。
0xff,忽视当前0xFF,对后一个字节在判断
其他数值,忽视当前0xFF,保留此数据用于译码。
2.2、解码过程
按照JPEG文件数据存储方式,设计一系列结构体对应各个标记,并存储标记内表示的信息,其中图像的长宽、多个量化表和哈夫曼表、水平/垂直的采样因子等重要信息。
整个GIGF0数据格式顺序为:
SOI(0xFFD8)
APP0(0xFFE0)
[APPn(0xFFEn)]可选
DQT(0xFFDB)
SOF0(0xFFC0)
DHT(0xFFC4)
SOS(0XFFDA)
压缩数据
EOI(0xFFD9)
JPEG文件格式,一个字(两个字节)存储使用Motorola格式及高字节在前低字节在后。
(1) 读哈夫曼表数据
在标记段DHT内,包含了一个或多个的哈夫曼表,对于单一哈夫曼表包括三个部分:
1) 哈夫曼表ID和表类型,这个字节的值只有四个,0x00 0x01 0x10 0x11。
0x00 表示DC直流0号表。
0x01 表示DC直流1号表
0x10 表示AC交流0号表
0x11 表示AC交流1号表
2) 不同位数的码字数量
JPEG文件的哈夫曼编码只能只能是1~16位。这个字段的16个字节分表表示1~16位的编码码字在哈夫曼树中的个数。
3) 编码内容
记录了哈夫曼树中各个叶子节点的权(不同位数的码字数量)。
解码过程:数据流 -> 最小编码单元(MCU) -> 数据单元与颜色分量
1) 在图片数据流中,信息被分为一段有单的最小编码单元数据流MCU。MCU是图像中一个正方矩阵像素的数据。矩阵大小是这样确定的:
查阅标记SOF0,可以得到图像不同颜色分量的采样因子,级Y、Cr、Cb三个分量各自的水平采样因子和垂直采样因子,大多图片的采样因子为4:1:1 或1:1:1其中4:1:1即(2*2):(1*1):(1*1),1:1:1即(1*1):(1*1):(1*1),记三个分量重水平采样因子最大值为Hmax,垂直采样因子最大值为Vmax,单个MCU矩阵宽就是Hmax*8像素,高就是Vmax*8像素,这里的Hmax为2、Vmax也为2.
如果正个图像宽度和高度不是MCU宽度和高度的整数倍,编码时会用某些数值填充。数据流中MCU的排列方法是从左到右,从上到下。
2) 每个MCU又分为若干个数据,数据单元大小必定是8*8,所以每个MCU数据单元个数是Hmax*Vmax。
JPEG的压缩方法与BMP文件有所不同,它不是把每个像素的颜色分量连续存储在一起,而是把图片分成Y、Cr、Cb三张子图分别压缩。三个颜色的采样因子可能一样(1:1:1),也可能不一样(4:1:1)。每个MCU内部,数据顺序是Y、Cr、Cb。如果一个颜色分量有多个数据单元,顺序是从左到右从上到下。
1、从文件头文件读出文件的相关信息
JPEG文件数据分为文件头和图像数据两大部分,其中文件头记录了图像的版本、长宽、采样因子、量化表、哈夫曼表等重要信息,解码前必须将文件头信息读出。
2、从图像数据流读取一个最小编码单元(MCU),并提取出里边的各个颜色分量单元。
3、将颜色分量单元从数据流回复成矩阵数据。
利用文件头给出的哈夫曼表,对分割出来的颜色分量单元进行解码,把其恢复成8x8的数据矩阵。
4、8x8数据矩阵进一步解码
此部分解码工作以8x8数据矩阵为单位,其中包括相邻矩阵的直流系统差分解码、利用文件头给出量化表反量化数据、反Zig-zag编码、隔行正负纠正、反向离散余弦变换等5个步骤,最终仍然是一个8x8的数据矩阵。
5、颜色系统YCrCb向RGB转换
将一个MCU的各个颜色分量单元解码结果整合起来,将图像颜色系统从YCrCb向RGB转换。
6、排列整合各个MCU解码数据。
不断读取数据流中的MCU并对其解码,直至读完所有的MCU位置,将各MCU解码后的数据正确排列成完整的图像。
相关文章推荐
- Android N Audio: setMasterVolume流程2
- 寻找字符串的最长公共前缀
- Mac CPU版本tensorflow,Theano,tensorlayer,keras搭建
- Hebernate-hql 插入一条 和 批量插入多条记录
- 【BZOJ】1012 [JSOI2008] 最大数maxnumber
- 第14周项目1-(2)验证分块查找算法
- shell脚本中整数型变量自增(加1)的实现方式
- precision和recall
- matlab提升(1):用matlab求图像的均值和方差
- Android工程gen already exists but is not a source folder. Convert to a source folder or rename it问题的解决
- POJ 2387 Til the Cows Come Home (裸SPFA)
- 基本概念学习(9013)---通用寄存器、机器字长、数据通路
- ArrayList和C++的vector
- 第十五周项目1 (1)——验证哈希表相关算法
- MySQL数据库事务剖析
- mongodb基本概念解析
- Tomcat 6 --- 你很少使用的安全管理SecurityManager
- Linux Deepin系统下安装jdk
- Unity 屏幕坐标
- 你看,那个人好像一只狗耶。(转)