基于JPEG压缩编码的数据压缩算法的研究与实现

 

JPEG压缩方法由于其较高的压缩比和理想的压缩效果,是目前应用最广泛的图像压缩方法。它采用一种特殊的有损压缩算法,将不易被人眼察觉 的图像颜色删除,从而能够将图像压缩在很小的储存空间。JPEG压缩技术十分先进,它用有损压缩方式去除冗余的图像数据,在获得极高的压缩率的同时能展现 十分丰富生动的图像,换句话说,就是可以用最少的磁盘空间得到较好的图像品质。

本文对JPEG图像压缩方法进行了基本介绍,包括它的发展历史,现 阶段的研究情况,压缩原理等。其中重点介绍了哈夫曼编码和游程编码的基本原理和在JPEG压缩编码算法中的具体应用,以及以变换编码方法为例,介绍了离散 余弦变换(DCT)的基本过程。最后介绍了用VC++编写JPEG压缩程序所涉及到的几个基本模块,从而实现了BMP图像和JPEG图像的相互转换,这也 是最主要的编程思想和依据。

关键词: 图像压缩,JPEG,DCT,哈夫曼编码,行程编码

摘 要 I

ABSTRACT II

第一章 绪论 1

1.1 图像压缩的意义 1

1.2 JPEG图像压缩的国际标准 2

1.3 本论文的研究内容 3

第二章 JPEG图像压缩技术基础研究 4

2.1 JPEG图像压缩技术 4

2.2 JPEG压缩中图像文件的格式 5

2.2.1 BMP图像的格式 5

2.2.2 JPEG图像格式 8

2.3 本章小结 8

第三章 JPEG图像压缩相关算法及实现 9

3.1 JPEG图像压缩编码方法 9

3.1.1 哈夫曼编码的原理 10

3.1.2 哈夫曼编码在图像压缩中的实现 11

3.2 JPEG图像压缩原理 13

3.2.1 前向DCT变换 14

3.2.2 量化 15

3.2.3 使用哈夫曼可变字长编码器对量化系数进行编码 16

3.3 本章小结 19

第四章 JPEG图像压缩的设计与实现 20

4.1 总体设计 20

4.1.1设计思想 20

4.1.2 模块设计 20

4.2 JPEG图像压缩软件的实现 21

4.2.1 BMP图像的读入、显示模块 22

4.2.2 DCT量化编码模块 25

4.2.3 组成位数据流模块 29

4.2.4 JPEG图像存储模块 31

4.2.5 解压缩模块 31

4.3 软件应用 32

4.4 压缩效果的评价 33

4.4.1 压缩效果理论分析 34

4.4.2 压缩效果实际分析 34

4.5 本章小结 35

第五章 总 结 36

5.1 JPEG图像压缩结论 36

5.2 JPEG图像压缩前景分析 36

参考文献 38

致 谢 39

附 录 40

ABSTRACT

JPEG compression is the most widely used image compression method because of its higher compression ratio and ideal compression effect. It uses a special lossy compression algorithm and deletes colors of images that is not detected easily by human eye, thus images can be compressed in a small storage space. JPEG compression technology is very advanced, it is used lossy compression methods to remove redundant image data. Thus, high compression ratios can be got, at the same time, a very rich and vivid images can be displayed, in other words, it is possible to get better image quality with the least disk space.

The paper introduces the JPEG compression algorithm firstly, including its history and the basic situation of this stage, compression principle, and so on. Referring to the JPEG compression method, the paper focuses on the basic tenets of Huffman coding and run-length coding and their specific application in JPEG compression algorithm. To transform coding method as an example, it introduces the discrete cosine transform (DCT) the basic process. Finally, Using the VC + +, it involves several basic modules of JPEG compression process and realizes the BMP images and JPEG image conversion, which is the most important ideological basis for programming.

KEY WORDS:Image compression, JPEG, DCT, Huffman coding, run-length coding

第一章 绪论

1.1 图像压缩的意义

人类社会已经进入信息时代了,在这个时代,人们每天都可以通过各种手段(如PDA、网络、电视、广播等等)获得大量的信息,而信息的本质,就要求交流和传播,在有必要的时候还要进行储存。在大量信息给人们生活增加了更多色彩的同时,随之而来的问题就是,如何利用有限的传输和储存资源来传输和保存更多的信息,这就要用到压缩数据的方法。具体的说,数据压缩的意义[1]有以下几个方面:首先是为了减少存储容量,以利信息的保存。如果说数据库是一个桶,那么单位数据的体积越小,同一数据库存储的信息也就越多。一般的卫星图像的4个信道的平均压缩比为2,也就是说,同一容量的数据库可以成倍地增加有效库存。其次是有利于数据传输。由于数据压缩是一种”去伪存真,去粗取精”的筛选,又由于可以用”代码”表示一组数据,所以压缩后的数据非常”精干”,这样就可以极大地减少必须传输的数据量,以满足人眼和机器分析的要求。第三是便于特征提取,以利计算机模式识别。如用计算机对卫星图像中不同类型的农作物进行分类时,使用图像压缩方法,只要考虑区分植物与非植物的特征以及区分植物类型特征即可,从而减少了数据量又满足了实际需要。数据压缩技术经过几十年的发展,现在来说还是比较成熟的。

而在介绍图像的压缩编码之前,先考虑一个问题:为什么要压缩?其实这个问题不用我回答,你也能想得到。因为图像信息的数据量实在是太惊人了。举一个例子就明白:一张A4(210mm×297mm) 幅面的照片,若用中等分辨率(300dpi)的扫描仪按真彩色扫描,其数据量为多少?让我们来计算一下:共有(300×210/25.4) ×(300×297/25.4)个象素,每个象素占3个字节,其数据量为26M字节,其数据量之大可见一斑了。

如今在Internet上,传统基于字符界面的应用逐渐被能够浏览图像信息的WWW(World Wide Web)方式所取代。WWW尽管漂亮,但是也带来了一个问题:图像信息的数据量太大了,本来就已经非常紧张的网络带宽变得更加不堪重负,使得World Wide Web变成了World Wide Wait。总之,大数据量的图像信息会给存储器的存储容量,通信干线信道的带宽,以及计算机的处理速度增加极大的压力。单纯靠增加存储器容量,提高信道带宽以及计算机的处理速度等方法来解决这个问题是不现实的,这时就要考虑压缩。

压缩的理论基础是信息论。从信息论的角度来看,压缩就是去掉信息中的冗余,即保留不确定的信息,去掉确定的信息(可推知的),也就是用一种更接近信息本质的描述来代替原有冗余的描述。这个本质的东西就是信息量(即不确定因素)。

图像压缩一般通过改变图像的表示方式来达到,因此压缩和编码是分不开的。图像压缩的主要应用是图像信息的传输和存储,可广泛地应用于广播电视、电视会议、计算机通讯、传真、多媒体系统、医学图像、卫星图像等领域。

1.2 JPEG图像压缩的国际标准

图像数据文件的格式有很多,如GIF、TIFF、PCX、TGA、BMP、JPG等。其中BMP图像对于原始的图像数据(直接来自于CCD数码相机)不压缩或压缩比例很小。JPEG由于有较高的压缩比,被广泛地应用于多媒体和网络程序中,例如HTML语法中选用的图像格式之一就是JPEG(另一种是GIF), 目前网站上百分之八十的图像都是采用JPEG的压缩标准。美国国防部及情报部门亦采用此标准为各部门间交流图像资料的标准格式。JPEG全名为Joint Photographic Experts Group,它是一个在国际标准组织(ISO)下从事静态影像压缩标准制定的委员会,它和国际电信同盟(ITU)下属的国际电话与电报顾问委员会(CCITT)及国际电工委员会(IEC)合作,共同制定出了第一套国标静态影像压缩标准:ISO/IEC 10918-1,也被称作CCITT Rec.T.81,就是俗称的JPEG,它被公布于1992年9月份。

随著多媒体应用领域的激增,传统JPEG压缩技术已无法满足人们对多媒体影像资料的要求。因此,更高压缩率以及更多新功能的新一代静态影像压缩技术JPEG 2000就诞生了。JPEG 2000与传统JPEG最大的不同,在于它放弃了JPEG所采用的以离散余弦转换(Discrete Cosine Transform)为主的区块编码方式,而改用以小波转换(Wavelet transform)为主的多解析编码方式。小波变换的主要目的是要将影像的频率成分抽取出来。JPEG2000中只采用了数学编码。编码的基本单位变为TILE,它可以任意大小甚至是整幅图像,TILE越大,压缩的效果越好,但对系统缓存的要求也就越高。JPEG2000的于JPEG相比增加了不少新的功能,如对图像中细节较多或较为感兴趣的区域(形状与大小可以是任意的)进行高精度的无损编码、很强的容错性、支持水印等。JPEG2000的许多优点和新的功能都是建立在复杂的计算与较大的缓存基础上,因此其速度与JPEG相比要慢许多。

JPEG-LS[2](JPEG-Lossless)标准是JPEG组织在1997年制定的连续色度(Continuous-tone)图像的无损压缩标准,它的无损压缩效果与JPEG2000相当,但算法相对简单。它的压缩原理也是基于预测,误差编码,但它的预测器要比JPEG中的复杂,并根据预测误差符合双边几何分布(Two-sided geometric distribution)的推论对误差进行修正,同时它对即将编码的像素的背景(Context)也进行建模以提高预测精度。

1.3 本论文的研究内容

1.JPEG图像压缩意义和现状.

2.JPEG压缩方法的原理及实现的具体步骤。

3.通过试验,主要观察JPEG有损压缩方法对图像的压缩效果。

4.哈夫曼编码是种常用的熵编码方法,论文中分析了它的原理和在图像压缩中应用。

第二章 JPEG图像压缩技术基础研究

2.1 JPEG图像压缩技术

图像数据的压缩基于两点:(1)像信息存在着很大的冗余度,数据之间存在着相关性,如相邻像素之间色彩的相关性等。(2)人眼是图像信息的接收端。因此,可利用人的视觉对于边缘急剧变化不敏感(视觉掩盖效应),以及人眼对图像的亮度信息敏感、对颜色分辨率弱的特点实现高压缩比,而解压缩后的图像信号仍有着满意的主观质量。

从信号系统的角度理解,数据的压缩就是对原来信号进行某种变换。借助这种变换,信号的表达更经济,存储传输更为方便。从信息论角度理解,信号本身的具体表达形式不过是其内在携带信息的外在表象,一定的信息可以用各种形式加以体现,每种表达形式的表达效率并不相同,存在着信息冗余。数据压缩的目的就是寻找在一定约束条件下最为高效的信息表达方式。从压缩技术的角度理解,数据压缩一般分为:建模、去相关、量化、编码四道工序。

由此发展出数据压缩的两类基本方法:第一类压缩过程是可逆的,也就是说,从压缩后的图像能够完全恢复出原来的图像,信息没有任何丢失,称为无损压缩;第二类压缩过程是不可逆的,无法完全恢复出原图像,信息有一定的丢失,称为有损压缩。选择哪一类压缩,要折衷考虑,尽管我们希望能够无损压缩,但是通常有损压缩的压缩比(即原图像占的字节数与压缩后图像占的字节数之比,压缩比越大,说明压缩效率越高)比无损压缩的高。

无损压缩是将相同的或相似的数据或数据特征归类,使用较少的数据量描述原始数据,达到减少数据量的目的。无损压缩又称信息保持编码,或叫做熵保持编码[3]。图像的无损压缩通常分为两步,即去相关和编码。去相关就是要去除图像冗余,降低信源熵。

在对数据进行编码时,可对那些经常出现的数据指定较少的位数表示,而那些不常出现的数据指定较多的位数表示。用这种方法得到的代码,其码的位数,也即码长就是不固定的,故称为变长码。Huffman在1952年根据香农(Shannon)在1948年和范若(Fano)在1949年阐述的这种编码思想提出了一种不定长编码的方法,也称哈夫曼(Huffman)编码[4]。哈夫曼编码的基本方法是先对图像数据扫描一遍,计算出各种像素出现的概率,按概率的大小指定不同长度的唯一码字,由此得到一张该图像的哈夫曼码表。哈夫曼编码(Huffman编码)是完全依据字符出现概率来构造字符的平均长度最短的码字,又称为最佳编码。

有损压缩是有利用人眼的视觉特性有针对性地简化不重要的数据,以减少总的数据量。有损算法有很多种,比较常见的主要是预测编码、变换编码等。预测编码法中最重要的是线性预测法,通常也成为”差值脉冲编码调制法”(DPCM)。DPCM编码的基本思想是用反馈方法预测估值。变换域编码[5]就是将通常在时间域或空间域描述的信号通过多维坐标的旋转、变换,将原散布在各坐标轴上的能量集中到少数坐标轴上,减少各信号分量的相关性。因此,可以使用较少的编码位数来表示一组信号样本,实现高效率的压缩编码。变换编码是一种有损编码。变换编码中理论上最佳的是K-L变换,其去相关最彻底,但目前尚无快速算法,且变换矩阵随数据集变化,不能广泛应用。而离散余弦变换(DCT)是一种实变换,去相关能力仅次于K-L变换,压缩效果好,压缩比易于调整,压缩率高,易于硬件实现。DCT有固定基,性能最接近K-L变换,现已出现了DCT的多种快速算法。有损压缩方法利用了人类视觉对图像中的某些频率成分不敏感的特性,允许压缩过程中损失一定的信息;虽然不能完全恢复原始数据,但是所损失的部分对理解原始图像的影响较小,却换来了大得多的压缩比。只要损失的数据不太影响人眼主观接收的效果,就可采用。

通过上面简单分析可知,压缩比与图像内容、压缩方法、允许失真的限制等等因素有关。实际编码图像时,也常常采用混合编码方法,甚至一幅图像采用好几种算法在多层次上反复进行处理,其目的当然是为了达到尽可能高的压缩比而不影响图像质量。除了压缩比,衡量压缩效果的常用指标为[6]PSNR(Peak Signal-to-Noise Ratio),但它要和主观评价相配合来对压缩效果进行评价。

2.2 JPEG压缩中图像文件的格式

由于图像数据文件的格式有很多,如GIF、TIFF、PCX、TGA、BMP、JPEG等。而现在实现的是BMP和JPEG的相互转换,所以要具体介绍BMP和JPEG文件的格式。

2.2.1 BMP图像的格式

BMP图像采用RGB(Red Green Blue)色彩模型,将各种颜色视为为红,绿,蓝(R,G,B)三个部分的组合。由于一幅图像中许多像素对应的颜色是相同的,BMP图像中采用了一个表:表中的每一行记录一种颜色的R,G,B值。这样,当表示一个象素的颜色时,只需要指出该颜色是在第几行,即该颜色在表中的索引值,这个表在BMP图像中称为调色板。有一种图,它的颜色数高达256×256×256种,也就是说包含上述提到的R,G,B颜色表示方法中所有的颜色,这种图叫做真彩色图(True Color)。真彩色图并不是说一幅图包含了所有的颜色,而是说它具有显示所有颜色的能力,即最多可以包含所有的颜色。表示真彩色图时,每个象素直接用R,G,B三个分量字节表示,而不采用调色板技术。

下面来看一看Windows的位图文件(.bmp文件)的格式是什么样子的。BMP文件大体上分成四个部分,如图2-1。

为了使文件格式更形象,在下文中给出图解。首先做出一些约定,在图2-2中:1B存储在一个字节中;2B存储在2个字节中;4B存储在4个字节中;b1、b2存储在4Bit中,也即半个字节中。本小节中的给出的图解都采用图2-2中的约定。

图2-1 BMP文件的结构

图2-2在BMP图像格式说明中的约定

图2-1第一部分为位图文件头(Bit map file header)这个结构的长度是固定的,为14个字节,结构如图2-3所示。

图2-3 BMP文件头的结构

开头两个字节指定文件类型,必须是0×424D,即字符串”BM”,也就是说所有.bmp文件的头两个字节都是”BM”。bfSize指定文件大小,其中包括这14个字节。bfReserved1,bfReserved2为保留字,不用考虑。bfOffBits为从文件头到实际的位图数据的偏移字节数,即图2-4中前三个部分的长度之和。

第二部分为位图信息头(Bit map info header), 这个结构的长度是固定的,为40个字节各部分,如图2-4。 biSize指定这个位图信息头的长度,等于40。biWidth指定图像的宽度,单位是象素。biHeight指定图像的高度,单位同样是象素。biPlanes必须是1,不用考虑。biBitCount指定表示颜色时要用到的位数,常用的值为1(黑白二色图),4(16色图),8(256色),24(真彩色图)。biCompression指定位图是否压缩,今后所讨论的只有不压缩的情况,即biCompression为0的情况。biSizeImage指定实际的位图数据占用的字节数,其实也可以从式(2-1)中计算出来。

a) 信息头的前24个字节

b) 信息头的后16个字节

图2-4 BMP图像的信息头

(2-1)

公式2-1中的biWidth’必须是4的整倍数(所以不是biWidth,而是biWidth’,表示大于或等于biWidth的,离4最近的整倍数。举个例子,如果biWidth=240,则biWidth’=240;如果biWidth=241,biWidth’=244。biXPelsPerMeter指定目标设备的水平分辨率,单位是每米的象素个数,打印时用到这个参数。biYPelsPerMeter指定目标设备的垂直分辨率,单位同上。biClrUsed指定本图像实际用到的颜色数,如果该值为零,则用到的颜色数为2的biBitCount次方。biClrImportant指定本图像中重要的颜色数,如果该值为零,则认为所有的颜色都是重要的。

第三部分为调色板(Palette),当然,这里是对那些需要调色板的位图文件而言的。有些位图,如真彩色图,前面已经讲过,是不需要调色板的,位图信息头后直接是位图数据。 如果视调色板实际上为一个数组,共有biClrUsed个元素(如果该值为零,则有2的biBitCount次方个元素)。数组中每个元素占用四个字节,四个字节分别为 rgbBlue(该颜色的蓝色分量) rgbGreen(该颜色的绿色分量),rgbRed(该颜色的红色分量),rgbReserved(保留值)。

第四部分就是实际的图像数据了。对于用到调色板的位图,图像数据就是该像素颜色在调色板中的索引值,对于真彩色图,图像数据就是实际的R,G,B值。对于256色位图,一个字节刚好可以表示1个像素。对于真彩色图,三个字节才能表示1个像素。要注意两点:

1)每一行的字节数必须是4的整倍数,如果不是,则需要补齐。这在前面介绍biSizeImage时已经提到了。

2)一般来说,BMP文件的数据从下到上,从左到右的。也就是说,从文件中最先读到的是图像最下面一行的左边第一个像素,然后是左边第二个像素…接下来是倒数第二行左边第一个像素,左边第二个像素…依次类推,最后得到的是最上面一行的最后一个像素。

介绍完BMP图像的格式,就好对它进行处理了。

2.2.2 JPEG图像格式

JPEG文件大体上可以分成以下两个部分[7]:标记码(Tag)加压缩数据。先介绍标记码部分。标记码部分给出了JPEG图像的所有信息(有点类似于BMP中的头信息,但要复杂的多),如图像的宽、高、Huffman表、量化表等等。标记码有很多,但绝大多数的JPEG文件只包含几种。标记码的结构为:

SOI

DQT

DRI

SOF0

DHT

SOS

EOI

标记码由两个字节组成,高字节为0XFF,每个标记码之前可以填上个数不限的填充字节0XFF。

2.3 本章小结

本章主要介绍了JPEG图像压缩技术基础,以及程序中要用到的BMP图像的格式。

第三章 JPEG图像压缩相关算法及实现

3.1 JPEG图像压缩编码方法

压缩编码的方法有很多,主要分成以下四大类:(1)象素编码;(2)预测编码;(3)变换编码;(4)其它方法。所谓象素编码是指,编码时对每个象素单独处理,不考虑象素之间的相关性。在象素编码中常用的几种方法有:(1)脉冲编码调制(Pulse Code Modulation,简称PCM);(2)熵编码(Entropy Coding);(3)行程编码(Run Length Coding);(4)位平面编码(Bit Plane Coding)。所谓预测编码是指,去除相邻象素之间的相关性和冗余性,只对新的信息进行编码。举个简单的例子,因为象素的灰度是连续的,所以在一片区域中,相邻象素之间灰度值的差别可能很小。如果我们只记录第一个象素的灰度,其它象素的灰度都用它与前一个象素灰度之差来表示,就能起到压缩的目的。如248,2,1,0,1,3,实际上这6个象素的灰度是248,250,251,251,252,255。表示250需要8个比特,而表示2只需要两个比特,这样就实现了压缩。常用的预测编码有Δ调制(Delta Modulation,简称DM);微分预测编码(Differential Pulse Code Modulation,DPCM),具体的细节在此就不详述了。所谓变换编码是指,将给定的图像变换到另一个数据域(如频域)上,使得大量的信息能用较少的数据来表示,从而达到压缩的目的。变换编码有很多,如(1)离散傅立叶变换(Discrete Fourier Transform,简称DFT);(2)离散余弦变换(Discrete Cosine Transform,简称DCT);(3)离散哈达玛变换(Discrete Hadamard Transform,简称DHT)。其它的编码方法也有很多,如混合编码(Hybird Coding)、矢量量化(Vector Quantize,VQ) 、LZW算法。

行程编码[8](Run Length coding)的原理也很简单:将一行中颜色值相同的相邻象素用一个计数值和该颜色值来代替。例如aaabccccccddeee可以表示为3a1b6c2d3e。如果一幅图像是由很多块颜色相同的大面积区域组成,那么采用行程编码的压缩效率是惊人的。然而,该算法也导致了一个致命弱点,如果图像中每两个相邻点的颜色都不同,用这种算法不但不能压缩,反而数据量增加一倍。所以现在单纯采用行程编码的压缩算法用得并不多,PCX文件算是其中的一种。

算术编码也是一种常见的无损压缩算法,由于它可以对编码对象的概率分布进行自适应,其效率要高于哈夫曼编码,现在正得到越来越广泛的应用。LZW编码是一种字典压缩算法,其压缩效率比较高,压缩速度较快。如果原始图像数据值中带有随机变化的”噪音图像”,则很难利用LZW算法进行压缩。当前流行的GIF、TIFF等图像文件格式都采用这种压缩算法。这类方法广泛用于文本数据、程序和特殊应用场合的图像数据(如指纹图像、医学图像等)的压缩。由于压缩比的限制,仅使用无损压缩方法不可能解决图像和数字视频的存储和传输问题。

哈夫曼编码是压缩编码中常用的一种编码方法,广泛的应用于图像的压缩,JPEG标准中基准模式采用的就是哈夫曼编码。本章对其原理和在图像压缩中的应用进行论述。

3.1.1 哈夫曼编码的原理

哈夫曼编码基于不同符号的概率分布,对出现次数较多的符号赋予较短的代码,出现次数较少的符号赋予较长的代码。这里,以一个例子说明如何赋予各个符号哈夫曼码值,即如何生成哈夫曼表。

假设将对由1,2,3,4,5,6,7,共7个数字组成的原信息进行哈夫曼编码,首先应对信息中各个数字出现的次数进行统计,得出各个数字的出现的相对概率。假设各个数据出现的次数如表3-1所示。

表3-1 7个数字的概率分布

数字 1 2 3 4 5 6 7

出现的次数 10 10 10 20 20 25 5

相对概率 0.1 0.1 0.1 0.2 0.2 0.25 0.05

根据表3-1生成哈夫曼树如图3-1所示。

具体的过程是这样的。先将所有的数字随意排列成一行构成7个最底层节点,首先将这一行中最小的两个概率值相加,0.1+0.05=0.15得到新的节点。这时拥有的概率值为0.2,0.2,0.2,0.1,0.1,0.15,0.25,再将这时最小的两个概率值相加,0.1+0.1=0.2得到新的节点。这时拥有的概率值为0.2,0.2,0.2,0.2,0.15,0.25,再将这时最小的两个概率值相加……,直到得到根节点,概率值为1.0为止。相加时,对于概率值相等的多个节点,可以任意选取。 除根节点外,设节点左面的分支为0,右边的分支为1(当然,也可以反过来),对于各个数值的代码就是从根节点出发到最底层的节点所经过的分支的序列。如4的代码为00,7的码值为1011,通常将4和7称为码值(Code value),00和1011被称为相应的码字(Code word),所有码字和码值的对应关系如表3-2所示。进行压缩编码时,只要将原数字(码值)用码字代替即可。如果概率统计十分不准确,则压缩效率会很低,甚至起不到压缩效果。

图3-1 由表3-1生成的哈夫曼树

将所有的码字和码值生成一个表,表达码字和码值的对应关系,称为哈夫曼表,为了整字节的输出码字,表中还要有各个码字的长度,例如JPEG标准中推荐的亮度信息直流系数的哈夫曼表如表3-3所示。

表3-2由图3-1得到的码字和码值的对应关系

码值 1 2 3 4 5 6 7

码字 1000 1001 1010 00 01 11 1011

哈夫曼表一般是事先确定的,(也可以在线实时调整)。本文以JPEG中的一个哈夫曼表(表3-3)为例,来说明如何实现哈夫曼编码,解码。

3.1.2 哈夫曼编码在图像压缩中的实现

在JPEG文件格式中,哈夫曼表以哈夫曼码字中位数相同的个数和所有的哈夫曼码值的形式存储,实际上是存储了一个哈夫曼树。根据JPEG文件开始部分对于亮度信息所用的哈夫曼表(对应表3-3)说明字段的可以得到下面两个数组:

bits[17] = { 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };

huffval[] ={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };

表3-3 JPEG标准中推荐的亮度信息哈夫曼表

码值 码字的长度 码字

0 2 00

1 3 010

2 3 011

3 3 100

4 3 101

5 3 110

6 4 1110

7 5 11110

8 6 111110

9 7 1111110

10 8 11111110

11

9

111111110

这两个数组和上面那个表是对应的。bits[]数组中的元素除bits[0]外,bits[1],bits[2],bits[3],…bits[16]代表哈夫曼代码中长度为1,2,3…16的个数。huffval[]中的各个元素是按照哈夫曼代码长度递增的顺序相对应的哈夫曼值(Huffman value),也即被代表的信息,如果几个元素对应的哈夫曼代码长度相同,顺序可以交换。从这两个数组出发,看看是如何实现编码的。

首先,应该生成哈夫曼表。建立huffcode[],huffcode[],ehufco[],ehufsi[]四个整数型数组,此处它们的元素个数只要大于12即可。

第一步:得到huffsize[]。

int p,l,i,lastp;

p = 0;

for (l = 1; l <= 16; l++) {

i = bits[l];

while (i–)

huffsize[p++] = l;

}

huffsize[p] = 0; /*使huffsize[]最后一个元素为零,是为了后面生成huffcode[]时,能够跳出循环*/

lastp=p; /* lastp-1即是所有码值的个数,后面的程序要用到它*/

这样, huffsize[]对12个哈夫曼码字的有效位的位数(单位是Bit)都有了记录,这主要使为了编码后输出码字时一定要知道码字的长度。

第二步得到huffcode[],它的各个元素是与huffsize[]各元素相对应的哈夫曼码字。

{ int code,si;

code = 0;

si = huffsize[0];

p = 0;

while (huffsize[p]) {

while ( huffsize[p] == si) {

huffcode[p++] = code;

code++;

}

code <<= 1;

si++;

}

}

从程序中可以看出,相邻的相同长度的哈夫曼码字彼此间差1。长度为si+1的代码中数值最小的代码,是长度为si的代码中数值最大的代码加1后并左移一位,这就能保证没有任何一个代码是另外一个代码的前缀,也就是说11,110这样的两个代码是不允许的。否则,解码时就会出现问题。

第三步得到ehufco[],ehufsi[]。

for (p = 0; p < lastp; p++) {

i = huffval[p];

ehufco[i] = huffcode[p];

ehufsi[i] = huffsize[p];

}

很简单,这里只是将huffcode[],huffsize[]中的元素调整了顺序,赋予了ehufco[],ehufsi[],以val[]的元素为索引值。显然,这样调整后,哈夫曼编码的过程就是一个查表过程。

3.2 JPEG图像压缩原理

JPEG的压缩原理其实是前面介绍的那些原理的综合,博采众家之长,这也正是JPEG有高压缩比的原因。其编码器的流程如图3-2:

图3-2 JPEG编码器流程

解码器基本上为上述过程的逆过程如图3-3:

图3-3 解码器流程

3.2.1 前项DCT变换

JPEG 里, 要对数据压缩, 先要做一次前向DCT(Forward cosine transform FDCT)变换,一次只对一个块(Block)进行变换。将原始图像数据视为空间的函数f(x,y),x为像素所处的行,y为像素所处的列,u和v对应频域空间的行和列,前向DCT变换的公式如式(3-1),DCT反变换的公式如式(3-2)。

(3-1)

(3-2)

在(3-1)和(3-2)中当u,v=0时, ;其它情况下, 。 DCT 变换的原理,和离散傅立叶变换差不多,它是将空间域的信号变换到频域,FDCT相当于谐波分析,此处频域共有64个不同的空间频率(对应不同的和),事实上,这种频率体现出光强变化的快慢[9],FDCT得到的数据就是对应频域中各个频率的幅值F(u,v)。值得注意的是在频域中,能量(或者说幅值)主要集中在低频(对应较小的u和v),对应高频的幅值大部分为零或接近零,这显然非常有利于数据的压缩。F(0,0)称为直流系数(DC Coefficient),从公式可以看出它相当于原始图像数据某种意义上的平均值,一般数值较大;其余的F(u,v)称为交流系数(AC Coefficient)。FDCT原理上是可逆的,原始图像数据的损失是由于公式中有余弦函数,计算时的精度引起的,但这往往可以忽略。这里还要注意两个问题:

1)FDCT是对每 8×8个点为一个单位处理的。所以如果原始图片的宽度(Width)或高度(Height)不是 8 的整倍数, 都需要先补成 8的倍数, 好一块一块的处理。例如某幅图像为698×695(高度×宽度),高度,宽度均不是8的整数倍,这在对图像压缩时,图像的右边应再加一列,图像的底部应再加6行,这样图像变为704×696,对于多加的行和列的像素值取为0即可。

2)FDCT变换前,先要将原始图像数据零均值化,如果原始图像的精度为P,则应将数值从[0,2p-1]变换到[-2p-1,2p-1-1],显然将原始数据减去2p-1即可。对于关心的8位的灰度图像,减去128,数据范围为[-27,27-1]。

3.2.2 量化

对于前面得到的64个空间频率振幅值按比例缩小,并取其最接近的整数值的处理过程称为量化。JPEG标准中推荐的量化表如表3-4。一共有64个元素,按照从上到下,从左到右的顺序与FDCT变换后的幅值对应,每一元素记为Q,u和v对应行和列,量化公式为式(3-3),解码时反量化公式为式(3-4)。

(3-3)

(3-4)

代表量化后的幅值, 代表还原(反量化)后的幅值。

RoundInteger 顾名思义是对数值取整,四舍五入就行了。

JPEG标准中推荐的量化表如表3-4。依据心理视觉阀制作,对 8bit 的亮度和色度的图像的处理效果不错,当然可以使用任意的量化表。

表3-4 JPEG标准推荐的量化表

16, 11, 10, 16, 24, 40, 51, 61,

12, 12, 14, 19, 26, 58, 60, 55,

14, 13, 16, 24, 40, 57, 69, 56,

14, 17, 22, 29, 51, 87, 80, 62,

18, 22, 37, 56, 68, 109, 103, 77,

24, 35, 55, 64, 81, 104, 113, 92,

49, 64, 78, 87, 103, 121, 120, 101,

72, 92, 95, 98, 112, 100, 103, 99

由于量化的缘故,产生了信息损失。量化表中对应于和较小的元素数值较小,意味着对低频幅值的量化信息损失较小,相对的,u和v较大时,数值也就较大了,意味着对高频幅值的量化信息损失较大。但事实上人眼对高空间频率远没有低频敏感,所以处理后的视觉损失很小。量化表是控制 JPEG 压缩比的关键[10,11,12],当量化表中某个元素取值较大时,压缩比就高,但图像失真就大。对于像素数值精度为N的数据经过FDCT和量化环节后,数据的整数部分的有效位数(以二进制计算)最多增加3位。对于8位

的灰度图像,此时数据的范围为[-210,210-1]。

3.2.3 使用哈夫曼可变字长编码器对量化系数进行编码

哈夫曼编码要分成3步来完成,1)按Z字型[13]的顺序(Zig-zag sequence)调整量化后的系数;2)将按之字型顺序排列的系数转化为中间符号(Intermediate symbol)序列;3)将中间符号中的一部分进行变长码字编码(Variable-lengths code coding)也就是哈夫曼编码,另一部分进行变长整数编码(Variable-lengths integer code),最终输出数据流[14]。

先看第一步,由前面的叙述可以看出,经过FDCT和量化两个环节后,较高空间频率(对应较大的u和v)的系数很小,大部分为零,因此,按Z字型的顺序调整系数的用意就是使为零的高空间频率系数能够连在一起,以利于游程编码(Run-length coding)。根据这一点,应使u和v较小的系数排列在前面,Z字形顺序如图3-4,图中 表示坐标为(i,j)

图3-4 z字形顺序

再看第二步。在这一步里,DC系数和AC系数是分开来处理的。由于DC系数是一块(Block)图像中像素值的平均值,相邻块之间的DC系数又很大的相关性,或者说往往相差不大,所以对相邻块的DC系数差值(DC Difference)进行编码,如图3-5所示。 紧接着将DIFF转变成中间符号:

Symbol-1 Symbol-2

(SIZE) (AMPLITUDE)

DIFF=DCi-DCi-1

图3-5 DC系数的编码

symbol-1是DIFF的有效位数(以二进制来计算),记为SIZE。如果DIFF为3,则symbol-1应为2。由于计算机中将负数存为反码或补码的形式,当DIFF为负数时,DIFF的有效位数为(-DIFF)的有效位数。前面提到,经过FDCT和量化两个环节后,对于8位

的灰度图,此时的数值范围为[-210,210-1],故DIFF的范围为[-211+1,211-1]故对DIFF来说,SIZE取值范围为0-11。

symbol-2是DIFF的幅值,记为AMPLITUDE,如果DIFF=3,则symbol-2为3。

对于AC系数,同样变成多个中间符号:

symbol-1 symbol-2

(RUNLENGTH,SIZE) (AMPLITUDE)

symbol-1包含RUNLENGTH,SIZE两部分。RUNLENGTH代表某一非零AC系数前面连续的AC系数为零的个数,这是对为零的AC系数进行游程编码。SIZE代表非零AC系数的有效位数。这里要注意,symbol-1的长度是固定的,占8位,RUNLENGTH,SIZE各占4位,故RUNLENGTH最大值为15,它最多可以记录15个连续的为零的系数。在symbol-1后面,往往有symbol-2,但在两种情况下没有:1)连续为零的系数大于15。此时,要用多个symbol-1来完成游程编码,symbol-1为(15,0)时,表示有16个连续的零系数,因为AC系数有63个,故在symbol-1完成游程编码时最多有3个连续的(15,0);2)当一窜连续为零的系数包含最后的AC系数 。这时以标记(0,0)表示后面的系数全为零,此块(Block)的数据结束,(0,0)一般称为EOB(End of block)。symbol-2表示非零系数的数值。

下面看一看哈夫曼编码的最后一步,对上一步产生的中间符号序列中symbol-1进行变长码字编码(Variable-lengths code coding VLC)也就是哈夫曼编码,对symbol-2进行变长整数编码(Variable-lengths integer code VLI),最终输出数据流。DC系数和AC系数的哈夫曼编码是分开的,在8位的灰度图像中,对于DC系数,symbol-1可以有12种取值,对于AC系数,symbol-1可以有162种取值,故它们采用的哈夫曼表不同。对于出现次数较多的symbol-1赋予较短的码字,出现次数较少的symbol-1赋予较长的码字,说它是变长码字编码是恰如其分的。对symbol-2进行变长整数编码实际就是省去非零数值的高位为零的那几位,表达一个非零的数,用它的有效位数个位就足够了,它的位数记录在symbol-1中的SIZE中。例如3,写成二进制数11就行了,没必要写成00000011。这里注意一点,在JPEG中,进行VLI编码时,数值为正,用原码表示,数值为负,用反码表示,例如-3,VLI编码后,变为00。

下面看一个对数据哈夫曼编码的实例。假设某原始图像的一块数据经FDCT和量化环节

后,数据变为:

15 0 -1 0 0 0 0 0

-2 0 0 0 0 0 0 0

-1 -1 0 0 0 0 0 0

0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0

上面的数据是按照从上到下,从左到右的顺序排列的。首先,按z字型的顺序(Zig-zag sequence)调整后的系数序列为:

15 0 -2 -1 -1 -1 0 0 -1 0 ???? 0

假设前一Block的DC系数为12,将系数转为中间符号的序列为:

(2)(3), (1,2)(-2), (0,1)(-1), (0,1)(-1), (0,1)(-1), (2,1)(-1), (0,0)

对于DC系数的symbol-1(2),查哈夫曼表为011,对于AC系数的各symbol-1查哈夫曼表为:

(0,0) 1010

(0,1) 00

(1,2) 11011

(2,1) 11100

对DC和AC系数的Symbol-2进行VLI编码为:

(3) 11

(-2) 01 (为-2的反码)

(-1) 0

则最终,整个输出的压缩数据为:

0111111011010000000001110001010

以上我们介绍了JPEG压缩的原理,其中DC系数使用了预测编码DPCM,AC系数使用了变换编码DCT,二者都使用了熵编码Huffman,可见几乎所有传统的压缩方法在这里都用到了。这几种方法的结合正是产生JPEG高压缩比的原因。

3.3 本章小结

本章介绍了JPEG图像压缩中的各种编码方法和JPEG压缩的原理,其中重点分析了哈夫曼编码的原理及在图像压缩中如何生成哈夫曼表以进行编码、解码。

第四章 JPEG图像压缩的设计与实现

4.1 总体设计

4.1.1设计思想

针对毕业设计任务书的要求,拟采用VC++语言编写实现算法的源程序,同时因为JPEG有几种模式,其中最常用的是基于DCT变换的顺序型模式,又称为基线系统(Baseline),所以我正是根据它的实现步骤来编写程序的模块的。模块结构图如4-1:

图4-1 BMP图像转换为JPEG图像结构图

4.1.2 模块设计

本软件几个模块具体说明如下:

1.BMP图像文件的读取和JPEG图像文件的存储

2.正向离散余弦变换

对每个单独的彩色图像分量,把整个分量图像分成8*8的图像块,并作为二维离散余弦变换DCT的输入。通过DCT变换,把能量集中在少数几个系数上。

3.量化

量化是对经过DCT变换后的频率系数进行量化。量化的目的是减小非”0″系数的幅度以及增加”0″值系数的数目。量化是图像质量下降的最主要原因。对于有损压缩算法,JPEG算法使用均匀量化器进行量化,量化步距是按照系数所在的位置和每种颜色分量的色调值来确定。因为人眼对亮度信号比对色差信号更敏感,因此使用了亮度量化值和色差量化值两种量化表,我们实际使用的是后者。

4.Z形编排

量化后的DCT系数要重新编排,目的是为了增加连续的”0″系数的个数,就是”0″的游程长度,方法是按照Z形的式样编排,这样就把一个8*8的矩阵变成一个1*64的矢量,频率较低的系数放在矢量的顶部。

5.直流系数的编码

8*8图像块经过DCT变换之后得到的DC直流系数有两个特点:一是系数的数值比较大,二是相邻8*8图像块的DC系数数值变化不大。根据这个特点,算法使用了差分脉冲编码调制(DPCM)技术,对相邻图像块之间的DC系数的差值进行编码。

6.交流系数的编码

量化AC系数的特点是1*64矢量中包含有许多”0″系数,并且许多”0″是连续的,因此使用非常简单和直观的游程长度编码(RLE)对他们进行编码。JPEG使用了1个字节的高4位来表示连续”0″的个数,而使用它的低4位来表示编码下一个非”0″系数所需要的位数,跟在它后面的是量化AC系数的数值。

7.熵编码

使用熵编码还可以对DPCM编码后的直流DC系数和RLE编码后的交流AC系数作进一步的压缩。在JPEG有损压缩算法中,使用霍夫曼编码器来减少熵。使用霍夫曼编码器的理由是可以使用很简单的查表方法进行编码。压缩数据符号时,霍夫曼编码器对出现频度较高的符号分配比较短的代码,而对出现频度较低的符号分配比较长的代码。

8.组成位数据流

JPEG编码的最后一个步骤是把各种标记代码和编码后的图像数据组成一帧一帧的数据,这样做的目的是为了便于传输、存储和译码器进行译码,这样的组织的数据通常称为JPEG位数据流(JPEG bitstream)

4.2 JPEG图像压缩软件的实现

4.2.1 BMP图像的读入、显示模块

进行压缩前,必须要有源图像,这里,选择了BMP图像作来获取图像数据,之所以选择BMP图像,一是它比较常见,图像格式较为简单;二是一般情况下不对存储的BMP图像数据进行压缩。

本软件实现的是BMP文件格式的图像压缩,BMP位图文件在前面已经介绍,可以调用基本类对图像信息进行存取和实现位图的读入,由于本软件是基于MFC(Microsoft Foundation Class Library)框架的,但MFC中没有处理设备无关位图(DIB)位图的类,可以定义一个处理DIB位图的专用类CDib类,在其中封装必要而有效的DIB数据成员和处理函数。该类具有的功能如下:

Void LoadFIle(CString m_fileName); //装载BMP位图文件

BOOL SaveFile(const char* paszFilename); //存储BMP位图文件

Char* GetFileName(); //返回位图文件名

DWORD GetSize(); //返回位图文件的大小

UINT GetWidth(); //返回位图文件的宽度

UINT GetHeight(); //返回位图文件的高度

UINT GetNumberofCorlors(); //返回位图颜色数目

RGBQUAD* GetRGB();//返回颜色表首地址

BITMAPINFO* GetInfo(); //返回图像信息结构首地址

BYTE *GetData(); //返回图像数据首地址

BMP图的读取流程图如图4-2所示。

图4-2 BMP图的读取流程图

现在以程序为例来说明上述过程, BMP图像文件的读取后存储程序函数为Save,

BOOL CDib::Save(const char *pszFilename)

{

//如果没有数据,不能保存

if(m_pDib==NULL)

return(FALSE);

CFile cf;

if(!cf.Open(pszFilename,CFile::modeCreate|CFile::modeWrite))

return(FALSE);

BITMAPFILEHEADER BFH;

// 预设BITMAPFILEHEADER结构的所有量全为0

memset(&BFH,0,sizeof(BITMAPFILEHEADER));

BFH.bfType=’MB’;

BFH.bfSize=sizeof(BITMAPFILEHEADER)+m_dwDibSize;

BFH.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+

m_nPaletteEntries*sizeof(RGBQUAD);

// 写具体数据到指定文件

cf.Write(&BFH,sizeof(BITMAPFILEHEADER));

cf.Write(m_pDib,m_dwDibSize);

return(TRUE);

}

图4-3为BMP图的显示流程图。

图4-3 BMP图的显示流程图

4.2.2 DCT量化编码模块

JPEG标准中规定了4种压缩模式[15]:顺序编码(Sequential encoding),渐进编码(Progressive encoding),等级编码(Hierarchical encoding),无损编码(Lossless encoding)。应用最为广泛的为基于DCT变换的顺序编码,也称之为基准模式(Baseline mode),其它几种模式都以此为基础。这里,采用了JPEG基准模式对图像进行压缩,在基准模式中,熵编码采用哈夫曼编码方法。

假设预处理图像数据存成名为image_compact的文件。从image_compact头4个字节中读出图像的宽度和高度imge_width,image_height后,还要由此算出block_width,和block_height,因为JPEG处理图像的单位是块(Block),如果图像是698×695(宽×高),则block_width,和block_height分别为88,87,程序用block_width,和block_height来控制循环的次数。这相当于前面提到的将宽度和高度补成8的倍数。in_buffer的大小正是一行Block的大小。

此过程的流程图4-4所示

图4-4 DCT量化编码模块图

其中DCT采用的是8*8快速余弦变换,它调用了Pre_DCT()该函数。而对DCT系数进行量化时可调整量化矩阵,以调整JPEG文件的压缩比

int quant_val[64];

for(i=0;i<64;i++)

{

if(Light[i]>=0)

quant_val[i]=(int)(Light[i]/QuantTable[i]+0.5);

else

quant_val[i]=(int)(Light[i]/QuantTable[i]-0.5);

}

接着就是对量化矩阵进行Z型扫描

for(i=0;i<64;i++)

table[zig[i]]=quant_val[i];

delete Light;

然后调用CDib:RLEProg()函数来实现熵编码。

下面为程序中8×8的亮度(Y)图象子块经过量化后的系数。

15 0 -1 0 0 0 0 0

-2 -1 0 0 0 0 0 0

-1 -1 0 0 0 0 0 0

0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0

可见量化后只有左上角的几个点(低频分量)不为零,这样采用行程编码就很有效。

在编码得到了DC,AC系数码字后,为了进一步提高压缩比,就要进行熵编码了,

具体过程:第一步,熵编码的中间格式表示:先看DC系数。假设前一个8×8子块DC系数的量化值为12,则本块DC系数与它的差为3,根据下表

Size Amplitude

0 0

1 -1,1

2 -3,-2,2,3

3 -7~-4,4~7

4 -15~-8,8~15

5 -31~-16,16~31

6 -63~-32,32~63

7 -127~-64,64~127

8 -255~-128,128~255

9 -511~-256,256~511

10 -1023~512,512~1023

11 -2047~-1024,1024~2047

查表得Size=2,Amplitude=3,所以DC中间格式为(2)(3)。

下面对AC系数编码。经过Zig-Zag扫描后,遇到的第一个非零系数为-2,其中遇到零的个数为1(即RunLength),根据下面这张AC系数表:

Size Amplitude

1 -1,1

2 -3,-2,2,3

3 -7~-4,4~7

4 -15~-8,8~15

5 -31~-16,16~31

6 -63~-32,32~63

7 -127~-64,64~127

8 -255~-128,128~255

9 -511~-256,256~511

10 -1023~512,512~1023

查表得Size=2。所以RunLength=1,Size=2,Amplitude=3,所以AC中间格式为(1,2)(-2)。

其余的点类似,可以求得这个8×8子块熵编码的中间格式为

(DC)(2)(3),(1,2)(-2),(0,1)(-1),(0,1)(-1),(0,1)(-1),(2,1)(-1),(EOB)(0,0)

第二步,熵编码:

对于(2)(3):2查DC亮度Huffman表得到11,3经过VLI编码为011;

对于(1,2)(-2):(1,2)查AC亮度Huffman表得到11011,-2是2的反码,为01;

对于(0,1)(-1):(0,1)查AC亮度Huffman表得到00,-1是1的反码,为0;

……

最后,这一8×8子块亮度信息压缩后的数据流为11011, 1101101, 000, 000, 000, 111000,1010。总共31比特,其压缩比是64×8/31=16.5,大约每个象素用半个比特。

这就是其中一个子块量化编码后的结果,而一幅图像正是被分成很多这样的子块来处理的。

4.2.3 组成位数据流模块

组成位数据流模块具体流程图如图4-5:

图4-5组成位数据流模块流程图

下面是具体的程序实现:

void CDib::ShiftWrite(int huffmanbitnum,int huffmancode)

{

int i,j,k;

if(huffmanbitnum

{

EncodeJpeg=EncodeJpeg|(huffmancode<<(surplus-huffmanbitnum));//需要编码的码串移入数据缓冲区

surplus=surplus-huffmanbitnum; //当前数据缓冲区剩余的位数

}

else//需要编码的码串比数据缓冲区剩余的位多,截断码串分两次移入数据缓冲区,使EncodeJpeg=32之后写入文件

{

i=huffmanbitnum-surplus; //截断码串后第二次移入数据缓冲区的位长

j=(int)pow(2,surplus)-1; //得到从低位到高位surplus个1,即(000111…11)

EncodeJpeg=EncodeJpeg|((huffmancode&(j<>i);

Write32bit(); //32位数据缓冲区填满后写入JPEG文件

EncodeJpeg=0; //数据缓冲区清零

k=(int)pow(2,i)-1; //

EncodeJpeg=(huffmancode&k)<<(32-i); //使被截断后剩余的码串移到32位数据缓冲区的高位

surplus=32-i; //目前数据缓冲区剩余的位数

}

}

对symble-1的哈夫曼编码,事实上就是利用被编码的数值(哈夫曼码值)去查表,对应DC系数的哈夫曼表,表存放在dc_ehufco[], dc_ehufsi[](在第二章中的哈夫曼编码部分,已经详细介绍如何生成编码用的两个数组),存放在两个数组中,dc_ehufco[]存放的是具体的哈夫曼码值,dc_ehufsi[]中存放的是哈夫曼码字的长度。可以定义一个WriteHuffmanData( )函数,具体程序见附录,它的功能是把一幅图像经DCT,量化之后的数据由哈夫曼编码后依次存入文件。它根据哈夫曼码字和它的长度两个参量,将数据送到输出缓存中去。对应AC系数的哈夫曼表,表存放在dc_ehufco[], dc_ehufsi[],查表及输出过程和DC系数是相同的。对于symble-2的VLI编码,根据其数值求出幅值的位数(有效位数)后,利用WriteHuffmanData( )函数输出到输出缓存中去。

4.2.4 JPEG图像存储模块

压缩后的图像数据存成标准的JPEG文件格式。在处理 JPG 文件时, 如果碰到一个0XFF, 而它后面的字节不是0, 并且这个字节没有意义. 那么你遇到的0XFF字节必须被忽略。在试验中,图像的存储如图4-6。

图4-6 JPEG图像的存储

在图4-6中,SOI=0XFFD8,EOI=0XFFD9,表示图像数据的开始(Start of image)和结束(End of image)。粗线框内表示某部分字段,长度从十几个字节到上万个字节不等。所有的JPEG图像开头和结尾均是SOI和EOI。一幅图像就是一帧,这一字段是对整个图像的长度和高度和各成分的分辨率和各成分用到的量化表进行说明。对图像的一次扫描(Scan)意味着对图像的一个或多个成分的每一像素对应的数值进行一次处理,扫描头中图像的各成分用到的哈夫曼表进行说明。至于熵编码后的数据,在灰度图中,以一块(Block)为最小的存储单位。按照从上到下,从左到右的顺序,把每一块中经DCT变换、量化、熵编码后的数据依次排列。

4.2.5 解压缩模块

这个模块按压缩时的压缩率来显示图像,用户可以设定解码图像的位色,并在此条件下解码图像。此过程的流程图4-7所示

图4-6 解码

图4-7 解压缩模块流程图

4.3 软件应用

程序最终调试运行得到的界面如图4-8,4-9

图4-8 BMP文件转换为JPEG文件操作界面

图4-9 JPEG文件转换为BMP文件操作界面

对于BMP文件转换为JPEG文件,点击加载图片,然后选择BMP图像文件,接着选择压缩质量,就是选择保留颜色值,最高为100,最低为1,最后点击另存图片即可存成JPEG图像。JPEG文件转换为BMP文件时只有选择色值一项不同,它是指显示的质量不一样。

4.4 压缩效果的评价

4.4.1 压缩效果理论分析

对从压缩数据恢复的图像的评价分为主观评价和客观评价两种。这里采用的客观评价参数为峰值信噪比(Peak value signal-to-noise ratio),简称为PSNR,计算公式如式(4-1)。

(4-1)

式中─B为每个像素占用的位数,这里为8;

f(m,n)为原始图像第m行,第n列像素值;

为复原图像第m行,第n列像素值;

M,N为图像的总行数和总列数。 一般来说,PSNR在30db以上时,效果较好。它反映了原图像与恢复图像的差别。而主观评价参数为压缩比,表示为压缩前图像文件的大小/压缩后图像文件的大小。另外,这里给出了单个像素差值的最大值作为一种参考,由于一幅图像的像素数从几万到几百万不等,一个像素恢复的效果较差对整个图像来说并不重要,但显然它越小越好。同时给出所有像素差值的平均值。因为图像大部分是拿来给人看的,而人的视觉机理很难用数学模型表达出来,更不用说用某一个参数来衡量,所以由人来观察图像,并给出评价是必要的。评价分为很好,好,较好,一般,较差,很差6个等级。对图像进行JPEG压缩,量化表的生成是在JPEG标准推荐的量化表的基础上进行线形放大,缩小。量化表的选取直接关系到整幅图像压缩的效果及压缩比,将图像质量Quality预先定义在1~100,当取100时,量化表的值均是1,压缩后的图像在量化环节没有信息损失,当取75时采用的量化表是JPEG标准推荐的量化表中的值均除以2,当取50时采用的量化表是JPEG标准推荐的量化表,当取35时采用的量化表是JPEG标准推荐的量化表中的值均扩大1.4倍。当取1时采用的量化表是JPEG标准推荐的量化表中的值均扩大50倍。压缩比也可用每像素平均占用的位(Bit)来表示,它越小,压缩比越小。

4.4.2 压缩效果实际分析

我们实验的图像是1024*768象素的,大小为2.25MB,保留颜色值为75压缩后变为146KB,压缩比为2.25*1024/146=15.7,压缩效果比较好。采用24位色解压缩后得到的图像跟原来几乎相同,而采用256色解压缩后则有明显的失真,可见现在一般都采用24位色来显示图像还是很好的。

而另外两幅实验图像则作了比较详细的压缩效果分析。

第一幅试验图像是698×695像素的图片,压缩效果评价结果如表4-1。

表4-1 压缩效果评价

Quality值 压缩前大小 压缩后大小

压缩比 主观评价

100 1.36MB 419KB 2.96 很好

75 1.36MB 93.7KB 14.86 很好

50 1.36MB 64.6KB 21.56 好

35 1.36MB 53.0KB 26.28 较好

1 1.36MB 12.5KB 114.11 很差

第二幅试验图像是662×719像素的图片,压缩效果评价如表4-2

表4-2 压缩效果评价

Quality值

压缩前大小 压缩后大小 压缩比 主观评价

100 1.38MB 441KB 3.20 很好

75 1.38MB 98.2KB 14.39 好

50 1.38MB 67.5KB 20.94 较好

35 1.38MB 55.5KB 25.6 一般

1 1.38MB 12.9KB 109.55 很差

可以看到,用同样的方法同样的参数(例如量化表),不同的图形压缩比,压缩效果是不同的。压缩比和图像质量是呈反比的,可以根据你的需要,选择合适的压缩比。

4.5 本章小结

本章具体介绍了JPEG图象压缩的设计思路和实现过程。最后,通过对图像的压缩试验,观察了压缩的效果,本章中给出了压缩效果的客观评价和主观评价,JPEG算法中,当用JPEG标准推荐的量化表去量化时,取得了基本令人满意的压缩效果。

第五章 总 结

5.1 JPEG图像压缩结论

JPEG格式是应用最广泛的图片格式之一,它采用一种特殊的有损压缩算法,将不易被人眼察觉的图像颜色删除,从而能够将图像压缩在很小的储存空间,由于图像中重复或不重要的资料会被丢失,因此也会造成图像数据的损伤。但是JPEG压缩技术十分先进,它用有损压缩方式去除冗余的图像数据,在获得极高的压缩率的同时能展现十分丰富生动的图像,换句话说,就是可以用最少的磁盘空间得到较好的图像品质。而且JPEG是一种很灵活的格式,具有调节图像质量的功能,允许用不同的压缩比例对文件进行压缩,支持多种压缩级别,压缩比率通常在10∶1 到40∶1 之间。因此使得JPEG在短短的几年内就获得极大的成功,目前网站上百分之八十的图像都是采用JPEG的压缩标准。但是随著多媒体应用领域的激增,传统JPEG压缩技术已无法满足人们对多媒体图像资料的要求。因此,更高压缩率以及更多新功能的新一代静态图像压缩技术必定要取代现有的技术。在压缩之前,我们这里试图将图像压缩为原来的1/4,也就是2Bits/pixel,为达到这个目的,进行了下面这些研究:

1)论文先对在数据压缩中常用的哈夫曼编码和算术编码的原理及在图像压缩中的应用进行了阐述。

2)论文中采用JPEG算法对图像进行压缩。采用不同的量化表对压缩比和压缩效果进行了观察,试验表明,把JPEG标准推荐的量化表中的数值均除以2并以此为量化表,已经可以将图像压缩到2Bits/pixel以下。

论文中的使用的方法还有许多有待改进之处:

1)论文中JPEG算法采用的量化表是以JPEG标准中推荐的量化表为基础,在日后的研究中,可以尝试使用对图像更为适合的量化表,并可以尝试采用向量量化方法,这样,应该可以得到更好的压缩效果。

2)论文中没有对JPEG无损算法进行研究,相信无损压缩的效果要大大好于有损压缩,毕竟它可以对压缩前后图像的单个像素最大差值进行控制。

5.2 JPEG图像压缩前景分析

随着多媒体应用领域的激增,传统JPEG压缩技术已无法满足人们对多媒体图像资料的要求。因此,更高压缩率以及更多新功能的新一代静态图像压缩技术 JPEG 2000 就诞生了。JPEG 2000 正式名称为 “ISO 15444″ ,同样是由JPEG 组织负责制定000(简称JP 2000)标准,这个标准中将采用小波变换(wavelet)算法。JPEG 2000 与传统 JPEG 最大的不同,在于它放弃了 JPEG 所采用的以离散余弦转换(Discrete Cosine Transform) 为主的区块编码方式,而改采以小波转换(Wavelet transform) 为主的多解析编码方式。小波转换的主要目的是要将图像的频率成分抽取出。

JPEG2000的优点:1、JPEG2000 作为JPEG升级版,高压缩(低码率)是其目标,其压缩率比 JPEG 高约 30% 左右。2、JPEG2000 同时支持有损和无损压缩,而 JPEG 只能支持有损压缩。因此它适合保存重要图片。3、JPEG2000 能实现渐进传输,这JPEG2000的一个极其重要的特征。这也就是我们对 GIF 格式图像常说的”渐现”特性。它先传输图像的轮廓,然后逐步传输数据,不断提高图像质量,让图像由朦胧到清晰显示,而不必是像现在的 JPEG 一样,由上到下慢慢显示。4、JPEG2000 支持所谓的”感兴趣区域”特性,你可以任意指定图像上你感兴趣区域的压缩质量,还可以选择指定的部份先解压缩。这样我们就可以很方便的突出重点了。JPEG2000的应用:JPEG 2000的应用领域可概略分成两部分,一为传统JPEG的市场,像打印机,扫描仪,数码相机等,一为新兴应用领域,像网网络传输,无线通讯,医疗图像等。目前对 JPEG 2000 热情最大的是那些数字照相机厂商。JPEG 2000和JPEG 相比优势明显,且向下兼容,取代传统的JPEG格式指日可待。

参考文献

[1] 吴乐南.数据压缩[M].电子工业出版社.2000. 1~3.

[2] 张益贞.Visual C++实现MPEG/JPEG 编解码技术[M].人民邮电出版社.2002.113~116

[3] 刘玮,王红星. 图像的无损压缩编码方法及JPEG标准模式[J]. 现代电子技术.

2002.5:7~10

[4] 严剑. Huffman算法及其在数据压缩中的应用[J]. 计算机与现代化. 1996, 48:15~20

[5] 5VK Goyal.Theoretical Foundations of Transform Coding[J].IEEE Signal

Processing Mag.2001,18:9~21

[6] 阮秋琦. 数字图像处理学[M]. 电子工业出版社.2001.235~237

[7] 许刚,廖斌,李承毅.JPEG图象文件格式分析[J].计算机系统应用.1998,10:37~39

[8] 孙即祥.图像压缩与投影重建[M].科学出版社.2005.15~20

[9] 马志荣,普杰信,赵渝青.JPEG软件压缩的实现与改进[J].计算机工程与应用. 1998, 8:39~41

[10] 龚华,刘雪松,张奎刚.JPEG标准格式的编码方法[J]. 微处理机. 2002, 1:39~40

[11] 祝宁,叶念渝.JPEG图象文件格式的分析及应用[J].电脑与信息技术.1999,3:21~24

[12] 智艾娣,智西湖.在JEPG压缩算法中选择量化表的尝试[J].小型微型计算机系统. 1997, 09:73~76

[13] 黄战华, 蔡怀宇, 李贺桥, 黄孟怀.自适应量化表的JPEG压缩技术[J].光电子激光.2000,20: 92~96

[14] 林福宗.多媒体技术基础[M].清华大学出版社.2002.73-77

[15] 贾铸.算术编码方法在图像压缩编码中的应用[J]. 电视技术. 1999, 209:8~11

 
  • 7
    点赞
  • 2
    评论
  • 2
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

johnny710vip

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值