一、编解码原理
编码原理 ![](https://i-blog.csdnimg.cn/blog_migrate/f0fb927ee45dbcf3deff6990bcb9bbaf.png)
(1)零偏置电平下移(Level Offset)
对于灰度级为2^n 的像素,通过减去2^(n-1),将无符号整数变为有符号数,即值域变为正负对称。将绝对值大的数出现的概率大大减小,提高编码效率。
(2)离散余弦变换(8×8 DCT)
先将图像分为8×8的像块,如果图像的宽(高)不是8的整数倍,使用图像边缘像素填充,以不改变频谱分布。然后对每一个子块进行DCT(Discrete Cosine Transform)。DCT变换使用下式计算,C为变换核矩阵:
实现能量集中和去相关,便于去除空间冗余,提高编码效率。DCT是一种无损变换,不压缩图像(输出的是系数)这样做是在为下一步的量化做准备。
(3)量化(Quantization)
量化是编码流程中唯一会引入误差也是唯一会带来压缩效果的步骤,决定压缩质量,因此是JPEG压缩编码算法的核心。JPEG标准中采用中平型均匀量化,输入DCT系数,输出量化系数。
量化表有建议量化表和真正使用的量化表 之分。
- 建议量化表:基于人的生理感知阈值实验,对人眼敏感的低频部分采取较细的量化,对不太敏感的高频部分采取较粗的量化,减少了视觉冗余。
- 真正的量化表:
- 质量因子≤ 50:缩放因子= 50 / 质量因子
- 质量因子> 50:缩放因子 = 2 – 质量 因子/ 50
(4)DC系数——差分编码(Differential indices)
8×8像块经过DCT后得到的DC系数有两个特点:一是系数的值较大;二是相邻像块的DC系数存在相关性(即存在冗余)。根据这个特点,JPEG标准采用了DPCM(差分脉冲编码调制),以对相邻图像块之间量化DC系数的差值DIFF进行编码:
(5) AC系数——之字形扫描和游程编码(Zig-Zag+RLE)
- 之字形扫描
经过DCT变换后,AC系数大多集中在左上角的低频分量区。因此采用Z字形按频率的高低顺序读出,可以出现很多连零的情况,便于使用RLE(Run Length Encoding,游程编码),若最后的数据均为0,则直接给出EOB(End of Block)。
- 游程编码
当遇到很多连续的0时,为缩短数据长度,编码【非零系数level和它之前0的个数run】,(Run,level)。
如:0,-2,0,0,3,2,-4–>游程编码:(1,-2),(2,3),(0,2),(0,-4),EOB
(6)Huffman编码
对DC系数DPCM的结果和AC系数RLE的结果进行Huffman编码:
- 类别ID采用一元码编码。
- 类内索引采用定长码编码。共有亮度DC、亮度AC、色差DC、色差AC四张码表。
解码原理
① 解码huffman数据、② 解码DC差值、③ 重构量化后的系数、④ DCT逆变换
⑤ 丢弃填充的行/列、⑥ 反0偏置、⑦ 对丢弃的CbCr分量进行插值、⑧ YCbCr–>RGB
二、JPEG文件格式
JPEG文件以segment的形式组织,其中每个segment以一个marker开始(marker均以0xFF+一个marker的标识符),随后为2字节的marker长度(不包含marker的起始两字节)和对应的payload(SOI和EOI marker只有2字节的标识符)。
注意,连续的0xFF字节并不是marker的起始标志,而是用来填充的特殊字符。此外,部分中,0xFF后若为0x00,则跳过此字节不予处理。