1 背景

JPEG在大约25年前开发了著名的数字图片编码标准,称为JPEG图像格式。JPEG 是联合图像专家组创建的,旨在用于照片压缩的一个标准。作为大多数消费类数码相机和手机的标准文件格式,几乎可以在任何地方找到它。

JPEG 有几个优点:
  1. JPEG 可以包含数百万种颜色,因此它们可以生成丰富、生动的图像
  2. JPEG产生的文件大小相对较小,即使有这么多颜色
  3. 所有现代浏览器都支持它们。

JPEG 是一种通用网络文件格式。JPEG 是为静态照片设计的,因此对于透明度或动画就不支持了。

2 JPEG 组织

由于最近社交网络使用量的增加,1年在线共享的JPEG编码图像数量增长到每天800,2014亿张,令人印象深刻。JPEG 2000 是另一个成功的 JPEG 标准,也获得了 2015 年技术和工程艾美奖。该标准使用最先进的压缩技术,提供更高的压缩和更广泛的应用领域。它广泛用于专业水平,即电影制作和医学成像。JPEG还开发了JBIG2,JPEG-LS,JPSearch和JPEG-XR标准。最近,JPEG推出了JPEG-AIC,JPEG Systems和JPEG-XT。JPEG-XT 定义了 JPEG 的向后兼容扩展,增加了对 HDR、无损/近无损和 alpha 编码的支持。下图显示了 JPEG 系列标准的概述。

2.1 JPEG 标准

JPEG官网地址:https://jpeg.org/index.html

2.2 JPEG1部分

2.3 JPEG 2000

2.4 JPEG Pleno

JPEG 推出了所谓的 JPEG Pleno 标准,该标准的第 2 部分专门用于光场编码。JPEG Pleno 光场编码标准包括两种编码模式,一种基于 4D-DCT,一种是所谓的4D-Transform模式,另一种是基于深度的合成,即所谓的4D-Prediction。4D-Transform 编码模式首次标准化了 4D 原生光场编码解决方案,其中全面利用了四个维度的全光场冗余,以某种方式将流行的 JPEG Baseline 标准几十年前采用的 2D 编码框架扩展到 4D .

2.5 JPEG Systems


JPEG 致力于对其文件格式、功能和代码语法进行系统审查和整合。目标是为未来和遗留标准定义一个称为 JPEG 系统的总体框架,以确保这些标准之间的互操作性和功能交换。

2.6 JPEG XL

JPEG XL 旨在满足网络图像传输和专业摄影的需求。它支持宽色域以及高动态范围和高位深度图像。

2.7 JPEG XR

JPEG XR 标准为广泛的应用程序提供实用的编码技术,具有出色的压缩能力和重要的附加功能。JPEG XR 的主要预期应用是表示连续色调静止图像,例如摄影图像。

2.8 JPEG XS

2.9 JPEG XT


JPEG XT 以完全向后兼容的方式扩展了 JPEG 规范。现有的工具和软件将继续使用新的代码流,以期兼容具有更高位深度(9 至 16 位)的图像压缩、高动态范围成像、无损alpha 通道的压缩和表示。

2.11 JPEG LS

2.12 JPSearch

JPSearch的目标是解决图像搜索和检索系统中的互操作性问题。
2.13 JPEG的发展路线图

3 JPEG 基础架构

基于 DCT 的处理模式框架。 下图充分说明了单分量(灰度)图像压缩的基本情况,也是JPEG图像编码的核心思想。 我们可以将图像拆分为 8x8 灰度图像块,图像样本压缩过程如下图所示。而彩色图像压缩可以近似地看作是多张灰度图像的压缩,或者一次压缩一个完整的图像。
JPEG 压缩算法的第一步是将图像分组为多个 8x8 (64) 像素块。每个 8x8 块被视为一个 64 点离散信号,并使用类似于快速傅里叶变换的方法进行编码,将无符号值转换为有符号数,称为系数。这些数字现在可以重新排序以方便压缩。基本上,数字代表每个像素的强度——色度、亮度和颜色。 该方法最早可以在 CACM 1991 年 4 月 Gregory Wallace 的文章中找到:The JPEG Still Compression Standard。 该编码步骤称为”前向离散余弦变换,FDCT”。该方法具有独特的逆函数——逆 DCT (IDCT)——将存储的图像解码回 8x8 块以重建存储的图像。
上图的基本步骤如下:
  1. 数据源:输入一个 8x8 像素块,表示亮度值。
  2. FDCT:FDCT 转换为 8x8 系数数组以表示相应的频率。
  3. 量化:量化阶段查询专用表,例如基于人类视觉系统对 64 个频率分量中的每一个的敏感度。因此,第一个分量可以乘以 1 以保持完全准确,而最后一个分量可以乘以 .001,因为它几乎不被察觉。
  4. 熵编码:熵编码通常使用霍夫曼编码完成,使用反映值频率的表。
  5. 存储:可以存储或传输生成的压缩比特流。

而解码过程则是编码的逆过程。

3.1 DCT

JPEG 基线压缩过程的关键是称为离散余弦变换 (DCT) 的数学变换。DCT 属于一类数学运算,包括众所周知的快速傅立叶变换 (FFT) 以及许多其他运算。这些操作的基本目的是获取信号并将其从一种表示形式转换为另一种表示形式。例如,图像是人类视觉系统感知的二维信号。DCT 可用于将信号(空间信息)转换为数字数据(“频率”或“光谱”信息),以便图像的信息以可用于压缩的量化形式存在。DCT变换的核心公式如下:
DCT变换后的表现:

3.2 量化


从 FDCT 输出后,64 个 DCT 系数中的每一个都结合 64 元素量化表进行统一量化,应用程序(或用户)必须将其指定为编码器的输入。每个元素可以是 1 到 255 之间的任意整数值,它指定了相应 DCT 系数的量化器步长。量化的目的是通过以不超过实现所需图像质量所需的精度表示 DCT 系数来实现进一步压缩。换句话说,这个处理步骤的目标是丢弃视觉上不重要的信息。量化是一种多对一的映射,因此从根本上说是有损的。它是基于 DCT 的编码器中有损的主要来源。

3.3 排序


量化后,DC 系数与 63 个 AC 系数将会被分开处理。DC 系数是 64 个图像样本的平均值的度量。由于相邻 8x8 块的 DC 系数之间通常存在很强的相关性,因此量化后的 DC 系数在编码顺序中被编码为与前一个块的 DC 项的差值。 而该操作过程是非常有意义的,也值得的,因为 DC 系数通常包含总图像能量的相当大的一部分,能够有效处理DC系数,则可以最大限度压缩图像。

接下来所有量化系数都将按“之字形”序列排序。这种排序有助于通过将低频系数(更有可能为非零)放在高频系数之前来更加高效的运用熵编码进行压缩。

3.4 熵编码


最后一个处理步骤是熵编码。该步骤通过基于量化的 DCT 系数的统计特性对其进行更高效的编码,实现了额外的无损压缩。JPEG 提案指定了两种熵编码方法——霍夫曼编码和算术编码。Baseline 顺序编解码器使用霍夫曼编码,但一般编解码器都会支持这两种编解码操作。

3.5 图像质量

对于具有中高等复杂场景的彩色图像,基于 DCT 的操作模式通常会针对指定的压缩范围产生图像质量如下:
压缩效果

(比特/像素)
图像质量
0.25~0.5
中~好,满足某一部分应用
0.5~0.75
好~很好,满足多数应用
0.75~1.5
极好,满足大多数应用
1.5~2.0
逼真,几乎与原图一样,肉眼很难分辨

4 JPEG文件结构


JPEG文件是分段存储结构,每一张图片都是由若干个信息段或者标志端组成,每个数据段都有自己的唯一标识符。标识符包含两个字节构成:第一个字节是0xFF,第二个字节是标识类型。
https://www.w3.org/Graphics/JPEG/itu-t81.pdf
jpeg文件格典型组成描述:SOI(文件开始标识,0xFFD8)+APP0(应用程序保留标记,0xFFE0)+ DQT(定义量化表,0xFFDB)+ SOF0(图像基本信息)+ DHT(定义Huffman表0xFFC4)+ SOS(扫描行开始,0xFFDA)+ EOI(文件结束标识,0xFFD9)。
对应的标志位说明如下:
看这个比较不容易理解,简单总结一下如下图:

5 JPEG 编解码库

5.1 libjpeg-turbo

libjpeg-turbo 是一种 JPEG 图像编解码器,它使用 SIMD 指令(MMX、SSE2、NEON、AltiVec)在 x86、x86-64、ARM 和 PowerPC 系统上加速基线 JPEG 压缩和解压缩。在此类系统上,libjpeg-turbo 通常是 libjpeg 的 2-6 倍,其他条件相同。在其他类型的系统上,libjpeg-turbo 凭借其高度优化的霍夫曼编码例程,仍然可以在很大程度上胜过 libjpeg。在许多情况下,libjpeg-turbo 的性能可与专有的高速 JPEG 编解码器媲美。
libjpeg-turbo 实现了传统的 libjpeg API 以及功能较弱但更直接的 TurboJPEG API。libjpeg-turbo 还具有色彩空间扩展功能,允许它从/解压缩到 32 位和大端像素缓冲区(RGBX、XBGR 等),以及一个全功能的 Java 接口。
https://libjpeg-turbo.org/
https://github.com/libjpeg-turbo/libjpeg-turbo

5.2 libjpeg


libjpeg是一个完全用C语言编写的处理JPEG图像数据格式的框架。它包含一个JPEG编解码器的算法实现,以及用于处理JPEG数据的多种实用程序。该套软件采用C语言编写,并分发为附有源代码的自由软件,采用自定义的宽松(类BSD)自由软件许可证,权利要求为署名。

https://github.com/thorfdbg/libjpeg

5.3 libhwjpeg


HwJpeg 库用于支持 Rockchip 平台 JPEG 硬编解码,是平台 MPP(Media Process Platform)库 JPEG 编解码逻辑的封装。其中,MpiJpegEncoder 类封装了硬编码相关操作,MpiJpegDecoder类封装了硬解码相关操作,用于支持图片或 MJPEG 码流解码。
https://github.com/khadas/android_hardware_rockchip_libhwjpeg

6 参考资料

http://pi.math.cornell.edu/~web6140/TopTenAlgorithms/JPEG.html
https://www.ijg.org/files/Wallace.JPEG.pdf
https://wenku.baidu.com/view/a1b075424a7302768e993992?pcf=2&re=view&bfetype=new&bfetype=new&_wkts_=1677027065394
https://blog.csdn.net/runafterhit/article/details/119300530
我是一枚爱跑步的程序猿,维护公众号和知乎专栏《MediaStack》,有兴趣可以关注,一起学习音视频知识,时不时分享实战经验。
继续阅读
阅读原文