jpeg压缩diff举例.docx
- 文档编号:13389316
- 上传时间:2023-06-13
- 格式:DOCX
- 页数:32
- 大小:28.55KB
jpeg压缩diff举例.docx
《jpeg压缩diff举例.docx》由会员分享,可在线阅读,更多相关《jpeg压缩diff举例.docx(32页珍藏版)》请在冰点文库上搜索。
jpeg压缩diff举例
jpeg压缩diff举例
【篇一:
jpeg压缩diff举例】
jpeg文件编/解码详解
cat_ng猫猫
jpeg(jointphotographicexpertsgroup)是联合图像专家小组的英文缩写。
它由国际电话与电报咨询委员会
ccitt(theinternationaltelegraphandtelephoneconsultativecommittee)与国际标准化组织iso于1986年联合
成立的一个小组,负责制定静态数字图像的编码标准。
小组一直致力于标准化工作,开发研制出连续色调、多级灰度、静止图像的数字图像压缩编码方法,即jpeg
算法。
jpeg算法被确定为国际通用标准,其适用范围广泛,除用于静态图像编码外,还推广到电视图像序列的帧
内图像压缩。
而用jpeg算法压缩出来的静态图片文件称为jpeg文件,扩展名通常为*.jpg、*.jpe*.jpeg。
jpeg专家组开发了两种基本的压缩算法、两种数据编码方法、四种编码模式。
具体如下:
压缩算法:
l有损的离散余弦变换(discretecosinetransform,dct);
l无损的预测技术压缩。
数据编码方法:
l哈夫曼编码;
l算术编码;
编码模式:
l基于dct顺序模式:
编/解码通过一次扫描完成;
l基于dct递进模式:
编/解码需要多次扫描完成,扫描效果从粗糙到精细,逐级递进;
l无损模式:
基于dpcm,保证解码后完全精确恢复到原图像采样值;
l层次模式:
图像在多个空间多种分辨率进行编码,可以根据需要只对低分辨率数据作解码,放弃高分辨率信息。
在实际应用中,jpeg图像使用的是离散余弦变换、哈夫曼编码、顺序模式。
jpeg压缩编码算法的主要计算步骤如下:
(0)8*8分块。
(1)正向离散余弦变换(fdct)。
(2)量化(quantization)。
(3)z字形编码(zigzagscan)。
(4)使用差分脉冲编码调制(dpcm)对直流系数(dc)进行编码。
(5)使用行程长度编码(rle)对交流系数(ac)进行编码。
(6)熵编码。
笔者在实践过程中查阅了大量的资料,发现大多数书籍资料和网上资料都是从编码角度分析jpeg的编/解码方式,
并且都只是介绍编码过程中的主要方法。
所以,本文从解码角度详细分析jpeg的编/解码过程,并且加入许多笔
者实践过程中遇到的问题和解决方法,希望从另一个角度说明问题,以更好帮助读者结合其他资料解决问题。
不过,介绍解码过程之前,首先要了解jpeg文件中数据的存储格式。
一、jpeg文件格式介绍
jpeg文件使用的数据存储方式有多种。
最常用的格式称为jpeg文件交换格式(jpegfileinterchangeformat,jfif
)。
而jpeg文件大体上可以分成两个部分:
标记码(tag)和压缩数据。
标记码由两个字节构成,其前一个字节是固定值0xff,后一个字节则根据不同意义有不同数值。
在每个标记码之前
还可以添加数目不限的无意义的0xff填充,也就说连续的多个0xff可以被理解为一个0xff,并表示一个标记码
的开始。
而在一个完整的两字节的标记码后,就是该标记码对应的压缩数据流,记录了关于文件的诸种信息。
常用的标记有、、、、、、、。
注意,soi等都是标记的名称。
在文件中,标记码是以标记代码形式出现。
例如soi的标记代码为0xffd8
,即在jpeg文件中的如果出现数据0xffd8,则表示此处为一个soi标记。
本文列出一张完整的jpeg定义的标记表,供读者查阅。
这里仅列出几个常用标记的标记代码、占用字
节长度和表示的意义。
lsoi,startofimage,图像开始
u标记代码2字节固定值0xffd8
lapp0,application,应用程序保留标记0
u标记代码2字节固定值0xffe0
u包含9个具体字段:
①数据长度2字节①~⑨9个字段的总长度
即不包括标记代码,但包括本字段
②标识符5字节固定值0x4a46494600,即字符串“jfif0”
③版本号2字节一般是0x0102,表示jfif的版本号1.2
可能会有其他数值代表其他版本
④x和y的密度单位1字节只有三个值可选
0:
无单位;1:
点数/英寸;2:
点数/厘米
⑤x方向像素密度2字节取值范围未知
⑥y方向像素密度2字节取值范围未知
⑦缩略图水平像素数目1字节取值范围未知
⑧缩略图垂直像素数目1字节取值范围未知
⑨缩略图rgb位图长度可能是3的倍数缩略图rgb位图数据
本标记段可以包含图像的一个微缩版本,存为24位的rgb像素。
如果没有微缩图像(这种情况更常见),则
字段⑦“缩略图水平像素数目”和字段⑧“缩略图垂直像素数目”的值均为0。
lappn,application,应用程序保留标记n,其中n=1~15(任选)
u标记代码2字节固定值0xffe1~0xfff
u包含2个具体字段:
①数据长度2字节①~②2个字段的总长度
即不包括标记代码,但包括本字段
②详细信息数据长度-2字节内容不定
例如,adobephotoshop生成的jpeg图像中就用了app1和app13两个标记段分别存储了一幅图像的副本。
ldqt,definequantizationtable,定义量化表
u标记代码2字节固定值0xffdb
u包含9个具体字段:
①数据长度2字节字段①和多个字段②的总长度
即不包括标记代码,但包括本字段
②量化表数据长度-2字节
a)精度及量化表id1字节高4位:
精度,只有两个可选值
0:
8位;1:
16位
低4位:
量化表id,取值范围为0~3
本标记段中,字段②可以重复出现,表示多个量化表,但最多只能出现4次。
lsof0,startofframe,帧图像开始
u标记代码2字节固定值0xffc0
u包含9个具体字段:
①数据长度2字节①~⑥六个字段的总长度
即不包括标记代码,但包括本字段
②精度1字节每个数据样本的位数
通常是8位,一般软件都不支持12位和16位
③图像高度2字节图像高度(单位:
像素),如果不支持dnl就必须0
④图像宽度2字节图像宽度(单位:
像素),如果不支持dnl就必须0
⑤颜色分量数1字节只有3个数值可选
1:
灰度图;3:
ycrcb或yiq;4:
cmyk
而jfif中使用ycrcb,故这里颜色分量数恒为3
a)颜色分量id1字节
b)水平/垂直采样因子1字节高4位:
水平采样因子
低4位:
垂直采样因子
(曾经看到某资料把这两者调转了)
c)量化表1字节当前分量使用的量化表的id
本标记段中,字段⑥应该重复出现,有多少个颜色分量(字段⑤),就出现多少次(一般为3次)。
ldht,difinehuffmantable,定义哈夫曼表
u标记代码2字节固定值0xffc4
u包含2个具体字段:
①数据长度2字节字段①和多个字段②的总长度
即不包括标记代码,但包括本字段
②哈夫曼表数据长度-2字节
a)表id和表类型1字节高4位:
类型,只有两个值可选
0:
dc直流;1:
ac交流
低4位:
哈夫曼表id,
注意,dc表和ac表分开编码
b)不同位数的码字数量16字节
c)编码内容16个不同位数的码字数量之和(字节)
本标记段中,字段②可以重复出现(一般4次),也可以致出现1次。
例如,adobephotoshop生成
的jpeg图片文件中只有1个dht标记段,里边包含了4个哈夫曼表;而macromediafireworks生成
的jpeg图片文件则有4个dht标记段,每个dht标记段只有一个哈夫曼表。
ldri,definerestartinterval,定义差分编码累计复位的间隔
u标记代码2字节固定值0xffdd
u包含2个具体字段:
①数据长度2字节固定值0x0004,①~②两个字段的总长度
即不包括标记代码,但包括本字段
②mcu块的单元中的重新开始间隔
2字节设其值为n,则表示每n个mcu块就有一个
rstn标记。
第一个标记是rst0,第二个是
rst1等,rst7后再从rst0重复。
如果没有本标记段,或间隔值为0时,就表示不存在重开始间隔和标记rst
lsos,startofscan,扫描开始12字节
u标记代码2字节固定值0xffda
u包含2个具体字段:
①数据长度2字节①~④两个字段的总长度
即不包括标记代码,但包括本字段
②颜色分量数1字节应该和sof中的字段⑤的值相同,即:
1:
灰度图是;3:
ycrcb或yiq;4:
cmyk。
而jfif中使用ycrcb,故这里颜色分量数恒为3
③颜色分量信息
a)颜色分量id1字节
b)直流/交流系数表号1字节高4位:
直流分量使用的哈夫曼树编号
低4位:
交流分量使用的哈夫曼树编号
④压缩图像数据
a)谱选择开始1字节固定值0x00
b)谱选择结束1字节固定值0x3f
c)谱选择1字节在基本jpeg中总为00
本标记段中,字段③应该重复出现,有多少个颜色分量(字段②),就出现多少次(一般为3次)。
本段结束后,紧接着就是真正的图像信息了。
图像信息直至遇到一个标记代码就自动结束,一般就是以eoi标记表示结束。
leoi,endofimage,图像结束2字节
u标记代码2字节固定值0xffd9
这里补充说明一下,由于在jpeg文件中0xff具有标志性的意思,所以在压缩数据流(真正的图像信息)中
出现0xff,就需要作特别处理。
具体方法是,在数据0xff后添加一个没有意义的0x00。
换句话说,如果在图像数
据流中遇到0xff,应该检测其紧接着的字符,如果是
1)0x00,则表示0xff是图像流的组成部分,需要进行译码;
2)0xd9,则与0xff组成标记eoi,则图像流结束,同时图像文件结束;
3)0xd0~0xd7,则组成rstn标记,则要忽视整个rstn标记,即不对当前0xff和紧接的0xdn两个字节进行译码,并按rst标记的规则调整译码变量;
3)0xff,则忽视当前0xff,对后一个0xff再作判断;
4)其他数值,则忽视当前0xff,并保留紧接的此数值用于译码。
二、jpeg解码过程详解
下面来详细讲述jpeg文件的解码过程。
1.读入文件的相关信息
按照上述的jpeg文件数据存储方式,把要解码的文件的相关信息一一读出,为接下来的解码工作做好准备。
参考方法是,设计一系列的结构体对应各个标记,并存储标记内表示的信息。
其中图像长宽、多个量化
表和哈夫曼表、水平/垂直采样因子等多项信息比较重要。
以下给出读取过程中的两个问题。
1)整个文件的大体结构
jfif格式的jpeg文件(*.jpg)的一般顺序为:
soi(0xffd8)
app0(0xffe0)
[appn(0xffen)]可选
dqt(0xffdb)
sof0(0xffc0)
dht(0xffc4)
sos(0xffda)
压缩数据
eoi(0xffd9)
2)字的高低位问题
jpeg文件格式中,一个字(16位)的存储使用的是motorola格式,而不是intel格式。
也就是说,一个字的
高字节(高8位)在数据流的前面,低字节(低8位)在数据流的后面,与平时习惯的intel格式不一样。
.
3)读出哈夫曼表数据
a)理论说明
在标记段dht内,包含了一个或者多个的哈夫曼表。
对于单一个哈夫曼表,应该包括了三部分:
l哈夫曼表id和表类型
这个字节的值为一般只有四个0x00、0x01、0x10、0x11。
0x00表示dc直流0号表;
0x01表示dc直流1号表;
0x10表示ac交流0号表;
0x11表示ac交流1号表。
l不同位数的码字数量
jpeg文件的哈夫曼编码只能是1~16位。
这个字段的16个字节分别表示1~16位的编码码字在哈夫曼树中的个数。
l编码内容
这个字段记录了哈夫曼树中各个叶子结点的权。
所以,上一字段(不同位数的码字数量)的16个数
值之和就应该是本字段的长度,也就是哈夫曼树中叶子结点个数。
b)举例说明
以下面一段哈夫曼表数据举例说明(数据全部以16进制表示):
1100020200050106010000000000000000
0001110221033141125161718191221332
红色部分(第1字节)为哈夫曼表id和表类型,其值0x11表示此部分数据描述的是ac交流1号表。
蓝色部分(2~17字节)为不同位数的码字的数量。
这16个数值实际意义为:
没有1位和4
位的哈夫曼码字;2位和3位的码字各有2个;5位码字有5个;6位和8位码字各有1个;7位码字各有6个;没有9位或以上的码字。
绿色部分(18~34字节)为编码内容。
由蓝色部分数据知道,此哈夫曼树有0+2+2+0+5+1+6+1=17个叶子结点,
即本字段应该有17个字节。
这段数据表示17个叶子结点按从小到大排列,其权值依次为0、1、11、2、21、3、31、41……
4)建立哈夫曼树
a)理论说明
在读出哈夫曼表的数据后,就要建立哈夫曼树。
具体方法为:
1)第一个码字必定为0。
如果第一个码字位数为1,则码字为0;
如果第一个码字位数为2,则码字为00;
如此类推。
2)从第二个码字开始,
如果它和它前面的码字位数相同,则当前码字为它前面的码字加1;
如果它的位数比它前面的码字位数大,则当前码字是前面的码字加1后再在后边添若干个0,直至满足位数长度为止。
b)举例说明
继续以上边的例子说明问题。
n由于没有1位的码字,所以第一个码字的位数为2,即码字为00;
n由于2位的码字有两个,所以第二个码字位数仍为2,即码字为00+1=01;
n第三个码字为3位,比第二个码字长1位,所以第三个码字为:
01+1=10,然后再添1个“0”,得100;
n……
如此类推,最后得到这个哈夫曼树如下:
序号
码字长度
码字
权值
1
2
00
0x00
2
2
01
0x01
3
3
100
0x11
4
3
101
0x02
5
5
11000
0x21
6
5
11001
0x03
7
5
11010
0x31
8
5
11011
0x41
9
5
11100
0x12
10
6
111010
0x51
11
7
1110110
0x61
12
7
1110111
0x71
13
7
1111000
0x81
14
7
1111001
0x91
15
7
1111010
0x22
16
7
1111011
0x13
17
8
11111000
0x32
特别注意的是,如果中间有某个位数的码字缺失,例如没有4位码字,则应该在3位码字加1后,添加“00”补足5位,形成下一个5位码字。
在准备好所有的图片信息后,就可以对图片数据进行解码了。
2.初步了解图像数据流的结构
1)理论说明
分析图像数据流的结构,笔者准备以一个从宏观到微观的顺序为读者详细剖析,即:
a)在图片像素数据流中,信息可以被分为一段接一段的最小编码单元(minimumcodedunit,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像素。
如果,整幅图像的宽度和高度不是mcu
宽度和高度的整数倍,那么编码时会用某些数值填充进去,保证解码过程中mcu的完整性(解码完成后,可直接
忽视图像宽度和高度外的数据)。
在数据流中,mcu的排列方法是从左到右,从上到下。
b)每个mcu又分为若干个数据单元。
数据单元的大小必定为8*8,所以每个mcu的数据单元个数为hmax*vmax。
另外jpeg的压缩方法与bmp
文件有所不同,它不是把每个像素的颜色分量连续存储在一起的,而是把图片分成y,cr,cb三张子图,然后分
别压缩。
而三个颜色分量的采样密度(即采样因子)可能一样(例如1:
1:
1)也可能不一样(例如4:
1:
1)。
每个mcu内部,数据的顺序是y、cr、cb。
如果一个颜色分量有多个数据单元,则顺序是从左到右,从上到下。
2)举例说明
下面通过一幅32*35的图像,对上面两个问题列出两种采样因子的具体说明。
图1整张完整的图像(4:
1:
1)图2将图像的mcu1放大
图1及图3中灰色部分为实际图像大小(32px*35px);粗虚线表示各个mcu的分界;细虚线表示mcu内部数据单元的分界。
a)采样因子为4:
1:
1
此时,hmax=max(2,1,1)=2,vmax=max(2,1,1)=2。
所以,mcu的宽为hmax*8=16
像素,高为vmax*8=16像素。
图像实际的宽刚好是2个mcu,但高则稍稍大于2个mcu的高度,所以要补足3行mcu。
每个mcu又分为hmax*vmax=2*2=4个数据单元。
由于采样因子是4:
1:
1,即(2*2):
(1*1):
(1*1
),所以y分量的水平和垂直方向都是每2个像素采样2次;cr分量和cb分量的水平和垂直方向都是每2个像素采样1次。
因此,在一个mcu来里边,y分量有256个采样点,即4个完整的数据单元;cr分量和cb分量各自只有64个采样点。
如果以mcu1说明mcu数据的次序,则依次为y1、y2、y5、y6、cr1256、cb1256。
图2中全部256个点均是y的采样点,红色部分为cr分量和cr分量的采样点。
换句话说,对于整张图片来说,数据流的数据依次是:
[y1、y2、y5、y6、cr1256、cb1256]、[y3、y4、y7、y8、cr3478、cb3478]、[y9、y10、y13、y14、cr9101314、cb9101314]、……
图3整张完整的图像(1:
1:
1)
b)采样因子为1:
1:
1
如图3。
hmax=max(1,1,1)=1,vmax=max(1,1,1)=2。
所以,mcu的宽为hmax*8=8像素,高为vmax*8=8像素。
图像实际的宽刚好是4个mcu,但高则稍稍大于4个mcu的高度,所以要补足5行mcu。
在数据流中,mcu的顺序是:
每个mcu又分为hmax*vmax=1*1=1个数据单元,也就是一个数据单元就是一个mcu。
由于采样因子是1:
1:
1,
即(1*1):
(1*1):
(1*1),所以y分量、cr分量和cb分量的水平和垂直方向都是每1个像素采样1次,也就是
图象的每一个像素都是采样点。
因此,在一个mcu来里边,y分量、cr分量和cb分量各自有64个采样点。
有
因此,对于整张图片来说,数据流的数据依次是:
[y1、cr1、cb1]、[y2、cr2、cb2]、[y3、cr3、cb3]、…………[y19、cr19、cb19]、[y20、cr20、cb20]。
3.颜色分量单元的内部解码
1)理论说明
“颜色分量单元”是笔者为说明问题而建立的概念,指的是mcu中某个颜色分量中的一个8*8数据块,例如上面提到的y1、cr1、cb1都是一个颜色分量单元。
图像数据流是以位(bit)为单位存储信息的。
并且内部的数据都是在编码时通过正向离散余弦变换(fdct)进
行时空域向频率域变换而得到的结果,所以对于每个颜色分量单元都应该由两部分组成:
1个直流分量和63个交流分量。
解码的过程其实就是哈夫曼树的查找过程。
首先查阅标记段sos中的颜色分量信息,可以得出各个颜色分量对应使用的直流分量和交流分量使用的哈夫曼树编号。
一般来说,
y分量:
直流分量:
直流0号哈夫曼树,交流分量:
交流0号哈夫曼树;
cr分量:
直流分量:
直流1号哈夫曼树,交流分量:
交流1号哈夫曼树;
cb分量:
直流分量:
直流1号哈夫曼树,交流分量:
交流1号哈夫曼树。
颜色分量单元内部综合运用了rle行程编码和哈夫曼编码来压缩数据。
每个像素的数据流由两部分构成:
编码和数值,并且
两者基本以互相隔开方式出现(除非该编码的权值为零)。
具体读入单个颜色分量单元的步骤如下:
a)从此颜色分量单元数据流的起点开始一位一位的读入,直到读入的编码与该分量直流哈夫曼树的某个码字(叶子结点)一
致,然后用直流哈夫曼树查得该码字对应的权值。
权值(共8位)表示该直流分量数值的二进制位数,也就是接下来需要读入的位数。
b)继续读入位数据,直到读入的编码与该分量交流哈夫曼树的某个码字(叶子结点)一致,然后用交流哈夫曼树查得该码字
对应的权值。
权值的高4位表示当前数值前面有多少个连续的零,低4位表示该交流分量数值的二进制位数,也就是接下来需要读入的位数。
c)不断重复步骤b,直到满足交流分量数据结束的条件。
而结束条件有两个,只要满足其中一个即可:
①当读入码字的权值为零,表示往后的交流变量全部为零;
②已经读入63个交流分量。
d)各个数值的译码是按下表进行的:
实际数值
编码长度
编码
-
-1,1
1
0,1
-3,-2,2,3
2
00,01,10,11
-7,-6,-5,-4,4,5,6,7
3
000,001,010,011,100,101,110,111
-15,……,-8,8,……,15
4
0000,……,0111,1000,……,1111
-31,……,-16,16,……,31
5
00000,……,01111,10000,……,11111
-63,……,-32,32,……,63
6
……
-127,……,-64,64,……,127
7
……
-255,……,-128,128,……,255
8
……
-511,……,-256,256,……,511
9
……
-1023,……,-512,512,……,1023
10
……
-2047,……,-1024,1024,……,2047
11
……
-4095,……,-2048,2048,……,4095
12
……
-8191,……,-4096,4096,……,8191
13
……
-16383,……,-8192,8192,……,16383
14
……
-32767,……,-16384,16384,……,32767
15
……
2)举例说明
下面举例说明以上几点。
某个颜色分量单元数据如下:
d35e6e4d35f58a
若以二进制表示,则为:
11010011010111100110111001001101001101011111010110001010
假设该颜色分量单元对应以下直
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- jpeg 压缩 diff 举例