📄 用vb语言编程实现jpeg数据压缩.htm
字号:
本来,第二步骤最后得到的DFT系数矩阵,乘以一个给定的系数矩阵得到DCT
系数矩阵,DCT系数矩阵再除以一个量化矩阵得到量化后的DCT系数矩阵,而我们
把这两步合成一步来做,即由系数矩阵和量化矩阵得到一个新的系数矩阵,亦即
附录所列的矩阵,这样,把DFT系数数矩阵乘以新的系数矩阵就直接得到量化后
的DCT矩阵。
量化过程实质上是把亮度数据和色度数据由室域转变成频域并滤除高频分量
的过程,由于人眼对高频分量不敏感,所以可以滤除高频分量,经过量化以后的
每一个8*8数据块中,第一个元素数据值为直流分量,称为DC,其余63个数据为
交流分量,称为AC。
用程序实现量化过程,除了系数矩阵的推算比较麻烦之外,其余的都比较简
单,读取Y矩阵中第一个8%块,与量化系数矩阵中对应的相乘,得到的值覆盖回
原矩阵,然后做第二个8*8块,一直到做完全部8*8块,然后做CbCr矩阵的量化,
用另外一个系数矩阵。
经过量化后的DCT系数矩阵,除DC值一般不为零外,AC系数大多是在零点附
近的浮点数。
由于霍夫曼编码的对象是整数,所以在做霍夫曼编码之前,还得对量化后的
DCT系数矩阵进行取整。
利用VB中的Int函数可以实现的YcbCr的DCT量化后系数炬阵进行取整。
经过取整以后,每一个8*8块中,有大量的AC系数的值为0。为了把尽可能多
的其值为0的AC系数串在一起,以利于第四步的AC编码及提高压缩比,还必须把
YcbCr矩阵中的每一个8*8块中的64个元素进行“之”字形排序(这样就可以做到
把尽可能多的0串在一起),其过程示意图如下:假设SB(1)—SB(64)为一个
8*8块中的64个元素,元素位置计数从1开始:
<P align=center><IMG height=195 src="用VB语言编程实现JPEG数据压缩.files/2-2.gif" width=412></P>
箭头方向表示“之”字形排序以后原8%中元素的新的位置顺序。亦即经过
“之”字形排序以下,新的8*8块中的元素值如下:等式左边表示元素位置,等
式右边表示元素值为排序之前某位置中的元素值:如SB(15)=SB(5),则左
边表示排序后的8*8块中第15个元素的值等于排序之前第5个元素的值。
SB(1)=SB(1) SB(2)=SB(2)
SB(3)=SB(9) SB(4)=SB(17)
SB(5)=SB(10) SB(6)=SB(3)
SB(7)=SB(4) SB(8)=SB(11)
SB(9)=SB(18) SB(10)=SB(25)
SB(11)=SB(33) SB(12)=SB(26)
SB(13)=SB(19) SB(14)=SB(12)
SB(15)=SB(5) SB(12)=SB(6)
......
SB(61)=SB(48) SB(62)=SB(56)
SB(63)=SB(63) SB(64)=SB(64)
用程序实现:再新开一个大小为64的数组SC,把SB的值赋给SC,再把以上
等式右边的SB换成SC即可。例如SB(15)=CB(5)换成SB(15)=SC(5)。
换完以后即完成一个8*8块的之字形变换,这里为什么要新开一个数组SC呢?
这是因为:例如把SB(9)的值赋给排序后的SB(3),则SB(3)的值就被SB(9)
的值覆盖掉了,到后面需把SB (3)的值赋给SB(6),如果不新开一个数组保留
元素的原来的值,则赋给SB(6)的就成了是SB(9)的值而不是SB(3)的值,
故要新开一个数组的保留8*8块中的原值。
完成“之”字形排序之后,就开始做第四步工作:霍夫曼编码。
<B>四、霍夫曼编码</B>
前面说到变换后的一个8*8频率系数矩阵由一个DC值和63个AC值构成,编
码时对DC值和AC值用不同的霍夫曼编码表,对亮度和色度也需用不同的霍夫
曼编码表,所以必须使用四张不同的霍夫曼编码表,才能完成JPEG编码。
DC编码:在做DC编码之前,还必须对DC值进行脉冲差值运算,具体做法
是在Y、Cb、Cr频率系数矩阵中,后一个8*8块的DC值减去前一个8*8块的DC作
为后一个8*8块新的DC值,并保留后一个8*8块的DC原值,用于后一个8*8块的
差值DC运算,亦即每次后一个8*8块的DC值减去的是第一个8*8块的原来DC值,
而不是经运算后的差值。
DC编码=霍夫曼识别码(或称标志码)+DC差值二进制码
下面给出Y、CbCr矩阵的DC差值霍夫曼编码表。
<P align=center><IMG height=797 src="用VB语言编程实现JPEG数据压缩.files/2-3.gif" width=360></P>
举例:例如Y矩阵中一个8*8块的DC值=10,二进制值为1010,码长为4,
查第一张表得霍夫曼识别长为3,识别码为101,则其霍夫曼编码为1011010,
负数的编码是取其绝对值的反码进行编码,如DC=-10,则其绝对值为10,
二进制仍为1010,反码为0101,霍夫曼编码为1010101。
AC编码:AC编码的原理和方法跟DC相似,所不同的是AC编码中多了一项
RLE压缩编码,前面说到经过量化取整以后,有许多AC值为0,并经过“之”
字形排序,把原可能多的0串列在一起。在这里RLE压缩编码的就是用一个数
值表示为0的AC值前有几个AC值为0。例如,在[M,N]这一组RLE编码中,N表
示不为0的AC值,M则表示在这不为0的AC值N之前0的个数,M最多只能为15,
如果AC数据值N之前有17个AC值为0,则先以[15,0]代表有16个值为0,再以
[1,N]表示N前有一个值为0,如果在某个AC数据值之后(该值不为0),所
有AC值皆为0,则这串数据可以用[0,0]表示。
做完RLE压缩后,再对不为0的AC值进行霍夫曼编码,跟DC值一样进行,
只不过用的是另两张霍夫曼编码表,完整的AC编码如下:
<P align=center><IMG height=56 src="用VB语言编程实现JPEG数据压缩.files/2-4.gif" width=244></P>
(完整的AC编码码串包括三部分:(1)的位置记录“0”的个数;(2)的
位置为霍夫曼识别码;(3)的位置的AC值的二进制码值)
这样的一个码串才算是一个完整的AC霍夫曼码串。
做到这里就完成了整个JPEG压缩过程。
在整个压缩过程中,最难的部分就是第四步,霍夫曼编码用程序实现起
非常繁琐,必须判断一个个DC(AC)的值,以及转换成二进制码后的码长,
再去对照霍夫曼编码表进行编码,比如对一个DC值编码,首先得先判断该DC
的值在哪段范围内,在某一段范围内的数值,其二进制码长相等。并要让程
序知道该DC的值到底为多少,然后才能进行编码,(这里面还涉及到一个数
制转换过程,即由十进制数转换成二进制数)。
压缩过程完成以后,接下去要做的工作便是码串存贮,存贮时需要注意
的—点是在抽样过程中得到4个Y块对应1个Cb块一个Cr块的对应关系,在存
贮时也要按这种对应关系存贮,即4个Y块的码串后面紧接着存放与其对应的
一个Cb块的码串及一个Cr块的码串,循环往复,存完所有串。这样的4个Y8*8
块+1个Cb块+1个Cr简称为MCU,是JPEG格式的最小存贮处理单元。
附录1:一维DCT变换公式
C1 C2 C3 C4 C5 C6 C7为常数
C1=0.9808
C2=0.9239
C3=0.8315
C4=0.7071
C5=0.5556
C6=0.3827
C7=0.1951
S18=SL(1)+SL(8)
S27=SL(2)+SL(7)
S36=SL(3)+SL(6)
S45=SL(4)+SL(5)
S1845=S18+S45
S2736=S27+S36
D18=SL(1)+SL(8)
D27=SL(2)+SL(7)
D36=SL(3)+SL(6)
D45=SL(4)+SL(5)
D1845=S18-S45
D2736=S27-S36
SL(1)=0.5*(C4*(S1845+S2736))
SL(2)=0.5*(C1*D18+C3*D27+C5*D36+C7*D45)
SL(3)=0.5*(C2*D1845+C6*D2736)
SL(4)=0.5*(C3*D18-C7*D27-C1*D36-C5*D45)
SL(5)=0.5*(C4*(S1845-S2736))
SL(6)=0.5*(C5*D18-C1*D27+C7*D36+C3*D45)
SL(7)=0.5*(C6*D1845-C2*D2736)
SL(8)=0.5*(C7*D18-C5*D27+C3*D36-C1*D45)
附录2:DCT量化系数矩阵
<P align=center><IMG height=228 src="用VB语言编程实现JPEG数据压缩.files/2-5.gif" width=624>
<IMG height=221 src="用VB语言编程实现JPEG数据压缩.files/2-6.gif" width=622></P>
</FONT></PRE>
<HR>
<P align=right><A
href="http://www.phenixsun.com/files/jgjs/jgjs.htm"><FONT
size=3><NOBR>返回目录</NOBR></FONT></A> <A
href="http://www.phenixsun.com/index.htm"><FONT
size=3><NOBR>返回首页</NOBR></FONT></A></P></TD></TR></TBODY></TABLE></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -