JPEG专家组开发了两种基本的压缩算法、两种数据编码方法、四种编码模式。具体如下:
压缩算法:
l 有损的离散余弦变换(Discrete Cosine Transform,DCT);
l 无损的预测技术压缩。
数据编码方法:
l 哈夫曼编码;
l 算术编码;
编码模式:
l 基于DCT顺序模式:编/解码通过一次扫描完成;
l 基于DCT递进模式:编/解码需要多次扫描完成,扫描效果从粗糙到精细,逐级递进;
l 无损模式:基于DPCM,保证解码后完全精确恢复到原图像采样值;
l 层次模式:图像在多个空间多种分辨率进行编码,可以根据需要只对低分辨率数据作解码,放弃高分辨率信息。
在实际应用中,JPEG图像使用的是离散余弦变换(傅里叶变换的一种,将连续信号函数拆分为多个离散余弦函数积分的组合去掉噪音和实现压缩存储)、哈夫曼编码、顺序模式。
JPEG压缩编码算法的主要计算步骤如下:
(0) 8*8分块。
(1) 正向离散余弦变换(FDCT)。
(2) 量化(quantization)。
(3) Z字形编码(zigzag scan)。
(4) 使用差分脉冲编码调制(DPCM)对直流系数(DC)进行编码。
(5) 使用行程长度编码(RLE)对交流系数(AC)进行编码。
(6) 熵编码(霍夫曼编码)。
JFIF格式的JPEG文件(*.jpg)的块状类型一般顺序为:
SOI(0xFFD8)(图像开始标志,2byte)
APP0(0xFFE0)(X/Y方向像素密度,缩略图像素数,缩略图RGB位图数据)
[APPn(0xFFEn)]可选
DQT(0xFFDB)
SOF0(0xFFC0)(帧图像开始,图像宽像素,图像高像素,颜色分量数,量化表)
DHT(0xFFC4)(哈夫曼表)
SOS(0xFFDA)
压缩数据(真正的图像YCrCb图像MCU颜色分量数据)
EOI(0xFFD9)
3.存储方式
内部数据为大端模式存放。如果,整幅图像的宽度和高度不是MCU宽度和高度的整数倍,那么编码时会用某些数值填充进去,保证解码过程中MCU的完整性(解码完成后,可直接忽视图像宽度和高度外的数据)。
在数据流中,MCU的排列方法是从左到右,从上到下。
3.2 数据单元(数据单元上面是存储的颜色分量,MCU上面也就是存储的颜色分量Y+Cr+Cb):
每个MCU又分为若干个数据单元。数据单元的大小必定为8*8,所以每个MCU的数据单元个数为Hmax*Vmax。解码的过程其实就是哈夫曼树的查找过程。
首先查阅标记段SOS中的颜色分量信息,可以得出各个颜色分量对应使用的直流分量和交流分量使用的哈夫曼树编号。一般来说,
Y分量:直流分量:直流0号哈夫曼树,交流分量:交流0号哈夫曼树;
Cr分量:直流分量:直流1号哈夫曼树,交流分量:交流1号哈夫曼树;
Cb分量:直流分量:直流1号哈夫曼树,交流分量:交流1号哈夫曼树。
4.2 反量化
不同的颜色分量使用不同的量化表,这个可以从标记段SOF中的颜色分量信息字段查得。一般是Y分量使用量化表0,而Cr、Cb两个分量共同使用量化表1。反量化的过程比较简单。只需要对8*8的颜色分量单元的64个值逐一乘以对应的量化表内位置相同的值则可。图像内全部的颜色分量单元都要进行反量化。
由于离散余弦变化要求定义域的对称,所以在编码时把RGB的数值范围从[0,255]统一减去128偏移成[-128,127]。因此解码时必须为每个分量加上128。具体公式如下:
R=Y +1.402*Cb +128;
G=Y-0.34414*Cr -0.71414*Cb +128;
B=Y +1.772*Cb +128;
还有一个问题,通过变换得出的R、G、B值可能超出了其定义域,所以要作出检查。如果大于255,则截断为255;如果小于0,则截断为0。
下面补充RGB模式向YCrCb模式的公式:
Y =0.299*R +0.587*G +0.114*B ;
Cr= -0.1687*R - 0.3313*G +0.5*B +128;
Cb=0.5 *R - 0.4187*G - 0.0813*B+128;