JPEG压缩学习笔记

来源:互联网 发布:微信电子书制作软件 编辑:程序博客网 时间:2024/06/06 01:20

JPEG压缩学习及其C语言实现笔记

JPEG压缩流程

1.颜色转换(RGB->YUV)

2.DCT变换 (分块8*8进行DCT变换)

3.量化(-996, 19, 0, 2,0, 0, 0, 0…)

4.编码 (游程编码,哈夫曼编码)

DCT变换(离散余弦变换)空间域到频率域的变换

“变换”的基本思想是,找一组基,让图像在这组基下能量集中(少量系数值较大,其余系数接近于0)。为了达到分离能量的目的,“变换”一般应是正交的。变换必须是可逆的(否则无法解码),因此变换本身不能压缩信息。不过随后的“量化”步骤将影响不大的系数略去,即可达到压缩的目的。

适合图像压缩的变换有很多种,如Karhunen-Loeve变换(KLT,即主成分分析)、离散傅立叶变换(DFT)、离散余弦变换(DCT)、Walsh-Hadamard变换(WHT)等。

JPEG采用8x8的2-D DCT作为其核心,该变换的定义是:

其中当u,v=0时,C(u),C(v)=1/root(2),否则C(u),C(v)=1。

在计算DCT之前,要把输入图像的像素值减去128,让它的取值范围从[0,255]移到[-128,127]。

每个8x8的分块经过DCT运算得到64个系数。其中,F(0,0)称为直流系数,其余的63个系数称为交流系数。在典型的连续色调图像中,相邻像素之间的差别往往不大。这意味着空间频率的幅值集中在低频部分。对典型的8x8图像分块而言,大多数空间频率的幅值是0或者接近于0,在编码时可以忽略。DCT本身并不会降低图像的质量,最多由于整数运算的舍入误差导致重构的图像与原始图像略有差别。

如果直接采用前面的公式进行计算,则每个DCT系数F(u,v)需要64次乘法,计算全部64个DCT系数则需要64x64=4096次乘法。计算DCT是整个JPEG压缩过程中最耗时的一步,很多人研究快速算法,也有人往CPU增加新指令,使之便于DCT运算。基本思路是把2-D DCT分解为1-D DCT,再利用余弦函数的对称性来减少计算量。每个分块的计算复杂度为O(1)。对于NxM的图像,共有[N/8]x[M/8]个分块,因此,DCT这一步的计算复杂度为O(MxN)。

系数量化

量化(quantization)是JPEG压缩过程中唯一会大幅损失信息的步骤。64个DCT系数会用8x8的量化表进行均匀量化,量化表中的每个元素是1到255之间的整数,表示对应的DCT系数的量化步长。量化的作用在于降低DCT系数的精度,从而达到更好的压缩率。量化是多对一映射,因此是有损的,它是基于变换的编码器中导致信息损失的主要步骤,也是用户唯一能参与控制压缩质量的步骤。

量化的过程是将每个DCT系数除以对应的量化步长,并四舍五入为整数:

反量化(dequantization)是把量化后的系数乘以对应的量化步长:

量化表理论上应该根据输入图像确定,目标是在基本不影响图像的视觉效果的前提下,尽量提高压缩率。量化步长越大,压缩率越大,图像质量越低。JPEG标准的正文中并没有规定或推荐使用哪个量化表,不过在Annex K中有一份量化表的例子(如下图所示),适用于大多数中等质量的图片。对于超高质量和超低质量的图片,这份量化表不是最优的。通常亮度分量和色差分量各有一张量化表,而且对色差分量的将忽略更多的高频成份。实际的JPEG实现都采用这一份量化表,因此后的数据中无须包含量化表。如果把下表中的量化步长除以2,那么图像质量就接近完美了。

每个分块有64个系数需要量化,需用64次除法和取整操作,因此每个分块的计算复杂度为O(1)。对于NxM的图像,共有[N/8]x[M/8]个分块,因此量化这一步的计算复杂度为O(MxN)。

Hoffman编码

JPEG文件的格式及组织形式

参见JPEG标准的 Annex BCompressed data formats

JPEGJointPhotographic Experts Group的缩写,正是这个专家组制定了JPEG标准以及其他静态图片编解码标准。Joint(联合)是指ISO TC97 WG8(计算机与信息处理技术委员会8工作组)和CCITT SGVIII两个工作组的联合.这个专家组在1992年颁布了第一个JPEG标准, ITU1992年命名为ITU-T Recommendation T.81,  ISO/IEC1994年命名为10918-1

 

注意JPEG标准仅仅说明定义了codec部分,也就是图片如何压缩为字节流以及重新解码为图片的过程.标准没有涉及到文件的存储格式

 

JPEG标准的附录B定义了文件格式"JPEG Interchage Format"(JIF),不过这个文件格式很少被用到,主要是因为EncodersDecoders完整实现JIF很困难,此外这个标准还缺少以下几个方面:

  • Color space定义
  • Component sub-sampling 限制
  • 像素宽高比

因此其他的JPEG文件格式标准陆续出现了.1992年颁布了JPEG FileInterchange FormatJFIF),紧接着出现了Exchange imagefile format(Exif)ICC color profiles. 这些格式都符合JIF的字节layout,但是又增加了一些不同的markers.在某种程度上说,JFIFJIF标准的精简版本.

Exif JPEG文件格式主要用在摄像设备上,摄像产业把Exif作为行业的元数据交换格式.由于Exif标准不支持color profiles,所以大部分软件图像编辑软件使用JFIF格式存储JPEG码流.

不论是Exif还是JFIF格式,都遵守JPEG interchangeformat(JIF),他们都是由JPEG markercompressed data组成的.下面列出了JPEG的所有marker

表1 JPEGmarker定义

短名

字节码

Payload

名称

Comments

SOI

0xFF, 0xD8

None

Start Of Image

 

SOF0

0xFF, 0xC0

Variable size

Start Of Frame 0

Baseline DCT-based JPEG, and specifies the width, height, number of components

SOF2

0xFF, 0xC2

Variable size

Start of Frame 2

Progressive DCT-based JPEG

DHT

0xFF, 0xC4

variable size

Define Huffman Table(s)

Specifies one or more Huffman tables

DQT

0xFF, 0xDB

variable size

Define Quantization Table(s)

Specifies one or more quantization tables

DRI

0xFF, 0xDD

2 bytes

Define Restart Interval

Specifies the interval between RSTn markers, in macroblocks.This marker is followed by two bytes indicating the fixed size

SOS

0xFF, 0xDA

variable size

Start of Scan

Start of Scan

RSTn

0xFF, 0xDn

None

Restart

Insert every r macroblocks. where r is the restart interval set by a DRI marker.

APPn

0xFF, 0xEn

variable size

Application-sepcific

An Exif JPEG file uses an APP1 marker to store metadata; JFIF JPEG file uses an APP0 marker to store JFIF metadata

COM

0xFF, 0xFE

variable

Comment

Contains a text comment

EOI

0xFF, 0xD9

none

End of Image

 

 

2 JPEG Start ofFrame marker结构

字段名称

长度

Comments

标记代码

2 bytes

固定值0xFFC0

数据长度

2 bytes

SOF marker长度,包括长度自身但不包含标记代码

精度

1 bytes

每个样本数据的位数,通常是8位,一般软件都不支持12位和16

图像高度

2 bytes

图像高度,单位:像素

图像宽度

2 bytes

图像宽度,单位:像素

颜色分量数

1 bytes

灰度级1,YCbCrYIQ 3CMYK 4

颜色分量信息

颜色分量数x3

每个颜色分量:1byte分量ID1 byte水平垂直采样因子;1 byte 当前分量使用的量化表ID



3 JPEG Start of Scan

字段名成

长度

Comments

标记代码

2 bytes

固定值0xFFDA

数据长度

2 bytes

SOS marker长度,包括长度自身

颜色分量数

1 bytes

灰度级1, YCbCr或者YIQ 3,  CMDK 4

颜色分量信息

颜色分量数x3

每个样色分量:1 byte颜色分量ID1 byte直流/交流系数表号

压缩图像数据

bytes

 

 

1 byte

谱选择开始固定为0x00

 

1 byte

谱选择结束固定为0x3f

 

1 byte

谱选择 basic JPEG中总为00



4 JEPG APP0应用程序保留标记0

 字段名称

字段长度

 Comments

标记代码 marker

2 bytes

固定值0xFF, 0xE0

数据长度 length

2 bytes

APP0总长度,不过括marker,但是包括length

标识符 identifier

5 bytes

固定的字符串"JFIF\0"

版本号 version

2 bytes

一般为0x0101或者0x0102

像素单位 unit

1 bytes

坐标单位,0没有单位; 1 pixel/inch2 pixel/cm

水平像素数目 Xdensity

2 bytes

 

垂直像素数目 YDensity

2 bytes

 

缩略图水平像素数目

1 byte

 

缩略图垂直像素数目

1 byte

 

缩略图RGB位图

3n bytes

n = Xthumbnail * Ythumbnail, 这是一个24bits/piexlRGB位图



5 APPn应用程序保留标记

字段名称

字段长度

Comments

标记代码 marker

2 bytes

固定值0xFFE1 ~ 0xFFEF, n=1~15

数据长度 length

2 bytes

APPn的总长度,不包括marker的2bytes

详细信息

(length - 2) bytes

内容是应用特定的,比如Exif使用APP1来存放图片的metadataAdobe PhotoshopAPP1APP13两个标记段分别存储了一副图像的副本。



6 DQT DefineQuantization Table

字段名称

子字段

字段长度

Comments

标记代码 marker

 

2 bytes

固定值0xFF, 0xDB

量化表长度 length

 

2 bytes

DQT的总长度,不包括marker2bytes

量化表

 

(length-2)bytes

 

 

精度及量化表ID

1 bytes

4位:精度,只有两个可选值,0 8bits1 16bits
4位:量化表ID,取值范围为0~3

 

表项

64*(精度+1) bytes

 



EOI marker

End of Image, 图像结束marker,一般来说EOIJPEG文件的末尾处,但是有的JPEG会在EOI之后添加一些内容。

 

0xFFJPEG文件中具有标记性的含义,后一个字节则根据不同意义有不同数值,在每个标记码之前还可以添加书目不限的无意义的0xFF填充,也就是说连续的多个0xFF可以理解为一个0xFF,并表示一个标记码的开始。

注意由于compressed datajpeg压缩数据流)中可能出现0xFF的,为了和marker区分开,就需要特殊处理。具体的做法是在0xFF后添加一个没有意义的0x00。如果在图像数据流中遇到0xFF,检测紧接着的字符,处理规则如下:

1) 0x00,则表示0xFF是图像流的组成部分。

2) 0xD9,则与0xFF共同组成EOI标记,图像流结束,同时图像文件结束。

3) 0xD0~0xD7,则组成RSTn标记,则要忽视真个RSTn标记,即不对当强的0xFF和紧接着的0xDn两个字节进行译码,并按照RST标记的规则调整译码变量。

4) 0xFF,忽视当前的0xFF,对后一个0xFF在做判断

5) 其他数值,则忽视当前的0xFF,并把紧接着的数值用于译码

 

JFIF - JPEG FILE Interchange Format

JFIF是为了使得JPEG码流能够在广泛的平台和应用见进行交换的最小文件格式.这个最小文件格式不包括TIFF JPEG标准任何高级特性,以及任何应用特定的文件格式.这种简化格式的初衷就是为了方便JPEG压缩图像的交换.

JFIF语法符合ISO DIS 10918-1附录B中关于交换文件语法的定义.此外,JFIF使用APP0 marker来实现JFIF特定于JIF的部分

JFIF格式文件的 layout:

[cpp] view plaincopy

1.  0xFF,0xD8                     SOI,Start of Image 

2.  0xFF,0xE0                    APP0, length, identifies, version,units, Xdensity, YDensity, Xthumbnail Ythunbnail, (RGB)n 

3.            length                2 bytes: 这个APP0域的长度,包括长度字段本身的2 bytes,但是不包括APP0 marker自身  

4.       identifier            5 bytes: 0x4A, 0x46, 0x49, 0x46, 0x00. 字符串"JFIF"   

5.        version               2 bytes: 版本号,一般为0x0102 或者0x0101,也就是1.01或者1.02  

6.        units                 1 bytes: 坐标的单位,units=0: 没有单位;units=1: 每英寸一个点;units=2 每厘米一个点  

7.       Xdensity              2 bytes: 水平像素数  

8.        Ydensity              2 bytes: 垂直像素数  

9.        Xthumbnail            1 bytes: Thumbnail水平像素数  

10.       Ythumbnail            1 bytes: Thumbnail垂直像素数  

11.     (RGB)n               3n bytes: 打包的24bits RGB thumbnail像素 n = Xthumbnail*Ythumbnail  

12. [可选的JFIF扩展APP0 marker段]  

13. ...  

14. ...  

15. 0xFF, 0xCn                     SOFn(Start of Frame), length, frame paramters  

16. ...  

17. ...  

18. 0xFF, 0xD9                     EOI (End of Image)  

由此刻见, APP0JFIF特有的部分


Exif - Exchange Image File Format

这个标准是Camera产业联合会发布的,主要目的就是设计一种文件格式,方便交换照片文件的metadata

Exif文件的layout

[cpp] view plaincopy

1.  SOI            0xFF, 0xD8    Start of frame  

2.  APP1           0xFF, 0xE1      Exif Attribute Information  

3.  APP2           0xFF, 0xE2      Flashpix Externsion data  

4.  ...  

5.  APPz           0xFF, 0xEn  

6.  DQT            0xFF, 0xDB  

7.  DHT            0xFF, 0xC4  

8.  DRI            0xFF, 0xDD  

9.  SOF            0xFF, 0xC0(0xFF, 0xC2)  

10. SOS            0xFF, 0xDA  

11.                Compressed Data  

12.    EOI            0xFF, 0xD9  

 

利用matlab进行测试和优化

可以利用matlab对同一幅图像生成不同质量因子的一系列图像,然后提取所获得的jpg图像当中的量化表信息做为自己C语言代码当中的量化表。不过,从jpg图像中获取的量化表要人工将其重新按照zig-zag的顺序进行排列。方法如下:

lena = imread('lena_752x480.bmp','bmp');

lena_gray = rgb2gray(lena);

imwrite(lena_gray,'F:\VS\JPEG\jpeg_debug\Doc\lena_gra752x480.jpg','jpeg','Quality',22);

lena_gray_jpg = imread('F:\VS\JPEG\jpeg_debug\Doc\lena_gra752x480.jpg','jpg');

subplot(1,2,1); imshow(lena_gray);

subplot(1,2,2); imshow(lena_gray_jpg);

 

0 0
原创粉丝点击