JPEG压缩标准简介:JPEG(Joint Photographic Exports Group)是由ISO和IEC两大国际组织联合组成的专家组,负责制定静态数字图像数据压缩编码标准,即ISO/IEC 10918---“多灰度连续色调静态图像压缩编码”,国际上称之为JPEG标准。
标准中定义了两种基本的压缩算法、两种熵编码方法、三个系统层次,四种编码模式
两种基本压缩算法:有损的离散余弦变换DCT和无损的预测编码
三个系统层次:基本系统、扩展系统和特殊无损功能
两种熵编码方法:Huffman编码、算数编码
四种编码模式:
- 基于DCT的顺序模式(编码、解码通过一次扫描完成)
- 基于DCT的渐进模式(编码、解码需要多次扫描才能完成,扫描效果由粗到精,逐级递增)
- 无损模式(基于DCPM,保证解码完全恢复到原图像的采样值)
- 层次模式(图像在多个空间分辨率中进行编码,可以根据需要只对低分辨率数据做解码,放弃高分辨率信息)
在实际应用中,JPEG图像编码算法使用的大多数是离散余弦变换、Huffman编码、顺序编码模式。这样的方式被称之为JPEG基本系统。
JPEG整个压缩算法流程如下图所示:
知识点补充:BMP是英文Bitmap(位图)的简写,它是Windows操作系统中的标准图像文件格式,能够被多种Windows应用程序所支持。随着Windows操作系统的流行与丰富的Windows应用程序的开发,BMP位图格式理所当然地被广泛应用。这种格式的特点是包含的图像信息较丰富,几乎不进行压缩,但由此导致了它与生俱生来的缺点--占用磁盘空间过大。所以,目前BMP在单机上比较流行。
第一步:颜色模式转换
BMP图像采用的颜色模型RGB,JPEG采用的颜色模型是YCrCb,所需要将RGB颜色空间图像数据转换到JPEG使用的YCrCb颜色空间
/*
RGB和YCrCb之间的转换关系如下:
Y = 0.229R + 0.587G + 0.114B
Cr = -0.1687R - 0.3313G +0.5B +128
Cb = 0.5R = 0.418 - 0.0813B + 128
R = Y + 1.402(Cr-128)
G = Y - 0.34414(Cb-128)- 0.71414(Cr-128)
B = Y + 1.772(Cr-128)
*/
第二步:采样
研究发现,人眼对亮度变换的敏感度要比对色彩变换的敏感度高出很多。因此,我们可以认为Y分量要比Cr/Cb分量重要很多。在BMP图片中,RGB三个分量各采用一个字节进行采样,也就是常说的RGB888的模式,通常JPEG用YUV422和YUV411采样方式,代表的意义是Y、Cb、Cr三个分量的数据采样比例,允许色度的采样比率比亮度低,但不会明显降低视觉质量。
4:1:1的含义是:在2*2的单元中,本应分别有4个Y,4个U,4个V值,用12个字节进行存储。经过4:1:1采样处理以后每个单元中的值分别有4个Y、4个U、4个V,只要用6个字节就可以存储了。
第三步:数据分块
DCT变换是以8*8点的子块为基本处理单元,因此需要预先把源图像数据划分为若干子块,每个块含8 * 8个像素点,如果原始图像的长宽不是8的倍数,都需要先补成8的倍数,使其可以按8 * 8的子块处理
第四步:离散余弦变换(Discrete Cosine Transform)
离散余弦变换是音频、视频及图像信号压缩常用的一种变换编码方法。它与傅里叶变换有密切的关系,任何连续的是对称函数的傅里叶变换中只有余弦项,因此,余弦变换同傅里叶变换一样具有明确的物理意义。它将数据从空间域变换到频域,使信号的能量集中在较少的几个频域系数上来减少数据量,解码时经离散余弦逆变换IDCT,数据可以恢复到原来的空间域重构图像
8 * 8点的正向DCT公式和IDCT公式如下,可以进行空间像素域f(x,y)与频域F(U,V)的相互转换
DCT变换的物理意义如下图所示:即将图像信号在频域分解成基波和各谐波
显然,恢复图像信息可以表示为下面的式子 :
F(n) = C(n) * E(n)
这里,E(n)是一个基底,C(n)是DCT系数,F(n)则是图像信号;如果考虑垂直方向的变化,就需要一个二维基底。
第五步:Zigzag扫描排序
把8 * 8的DCT系数矩阵排列成1*64的向量,沿Z字形路径可以有效积累连续0的个数,提高编码压缩效率。DC系数和低频的AC系数被排在向量的前部
第六步:DCT系数量化
可以看出,对于低频部分采用细量化(较小的量化步长),对于高频采用了粗量化(较大的量化步长)
第七步:DC系数差分脉冲调制编码
DCT变换后得到的DC系数有两个特点:
- 系数的数字比较大
- 相邻的8 * 8 图像块的DC系数值变化不大
采用差分脉冲编码调制DPCM,即对相邻的8 * 8像素块之间的DC系数的差值进行编码,可以提高压缩率。
第八步:DC系数的中间格式转换
目的:进一步减小数据量
DC系数差值的中间格式由两部分组成:(SSSS,DIFF)
第九步:AC系数的行程长度的编码(RLC)
行程长度编码是将一个字符串中重复的连续的字符用两个字节来代替,第一个字节代表重复的次数,第二个细节可以代表被重复的字符,这种编码可以简单直观地减少数据量。例如: (4,6)就代表字符串 “6666”
但是JPEG中RLC编码略有不同,编码格式(M,N)的定义为:M是两个非零AC系数之间连续0的个数(即形成长度),N是下一个非零的AC系数的值。
/*
例如,有字符串:57,45,0,0,0,0,23,0,-30,-8,0,0,1,…………
经过RLC之后,结果为如下形式:
(0,57);(0,45);(4,23);(1,-30);(0,-8);(2,1);
*/
第十步:AC系数的中间格式转换
/*
例如:(0,57);(0,45);(4,23);(1,-30);(0,-8);(2,1)…………
根据VLI表,对应的中间格式为:
(0,6),57;(0,6),45;(4,5),23;(1,5),-30;…………
*/
第十一步:熵编码
JPEG标准规定的熵编码方式有Huffman编码和算数编码
Huffman编码:是对出现概率大的字符,分配字符长度较短的二进制编码,对出现概率小的字符,分配字符长度较长的二进制编码,从而使得字符的平均编码长度最短。
Huffman编码表:4张预先定义好的编码表,使用查表的方式进行编码。
分别为:亮度的DC系数、AC系数Huffman编码表;色度的DC系数、AC系数Huffman编码表;
编码表可参考:https://www.w3.org/Grapics/JPEG/itu-t81.pdf
其他JPEG参考资料:
JPEG标准文本:https://www.w3.org/Graphics/JPEG/itu-t81.pdf
JPEG源码:
libjpeg-turbo http://libjpeg-turbo.virtualgl.org/
libjpeg https://github.com/thorfdbg/libjpeg