libjpeg-turbo/libjpeg-turbo
GitHub: libjpeg-turbo/libjpeg-turbo
基于 SIMD 加速的高性能 JPEG 图像编解码库,兼容 libjpeg API 同时提供更简洁的 TurboJPEG 接口。
Stars: 4247 | Forks: 1128
# 背景
libjpeg-turbo 是一个 JPEG 图像编解码器,它使用 SIMD 指令来加速 x86、x86-64、Arm、PowerPC 和 MIPS 系统上的 baseline JPEG 压缩和解压缩,以及 x86、x86-64 和 Arm 系统上的 progressive JPEG 压缩。在这些系统上,在其他条件相同的情况下,libjpeg-turbo 通常比 libjpeg 快 2-6 倍。在其他类型的系统上,凭借其高度优化的 Huffman 编码例程,libjpeg-turbo 的性能仍然可以显著超过 libjpeg。在许多情况下,libjpeg-turbo 的性能可与专有的高速 JPEG 编解码器相媲美。
libjpeg-turbo 实现了传统的 libjpeg API 以及功能较少但更直接的 TurboJPEG API。libjpeg-turbo 还具有色彩空间扩展,允许从 32 位和大端像素缓冲区(RGBX、XBGR 等)进行压缩/解压缩,以及功能齐全的 Java 接口。
libjpeg-turbo 最初基于 libjpeg/SIMD,这是由 Miyasaka Masaru 开发的 libjpeg v6b 的 MMX 加速衍生版本。TigerVNC 和 VirtualGL 项目在 2009 年对该编解码器进行了大量增强,2010 年初,libjpeg-turbo 分拆为一个独立项目,目标是让更广泛的用户和开发者能够使用高速 JPEG 压缩/解压缩技术。libjpeg-turbo 是 JPEG 标准的 ISO/IEC 和 ITU-T 参考实现。
关于 libjpeg-turbo 的更多信息可以在 找到。
# 许可证
libjpeg-turbo 受三个兼容的 BSD 风格开源许可证保护。有关许可证条款的汇总,请参阅 [LICENSE.md](LICENSE.md)。
# 构建 libjpeg-turbo
有关完整说明,请参阅 [BUILDING.md](BUILDING.md)。
# 使用 libjpeg-turbo
libjpeg-turbo 包含两个 API,可用于压缩和解压缩 JPEG 图像:
- **TurboJPEG API**
此 API 提供了一个易于使用的界面,用于在内存中压缩和解压缩 JPEG 图像。它还提供了一些使用底层 libjpeg API 难以直接实现的功能,例如生成平面 YUV 图像和对图像执行多个同时无损变换。libjpeg-turbo 的 Java 接口是在 TurboJPEG API 之上编写的。推荐 libjpeg-turbo 的初次使用者使用 TurboJPEG API。有关其用法示例,请参阅 [tjcomp.c](src/tjcomp.c)、[tjdecomp.c](src/tjdecomp.c)、[tjtran.c](src/tjtran.c)、[TJComp.java](java/TJComp.java)、[TJDecomp.java](java/TJDecomp.java) 和 [TJTran.java](java/TJTran.java);有关 API 文档,请参阅。
- **libjpeg API**
这是用于压缩和解压缩 JPEG 图像的事实上的行业标准 API。它比 TurboJPEG API 更难使用,但也更强大。libjpeg-turbo 中的 libjpeg API 实现与 libjpeg v6b 既是 API/ABI 兼容的,也是数学兼容的。它还可以选择配置为与 libjpeg v7 和 v8 API/ABI 兼容(见下文)。有关其用法示例,请参阅 [cjpeg.c](src/cjpeg.c) 和 [djpeg.c](src/djpeg.c);有关 API 文档,请参阅 [libjpeg.txt](doc/libjpeg.txt)。 当这两个 API 用于执行类似操作时,在性能上没有显著差异。 ## 色彩空间扩展 libjpeg-turbo 包含一些扩展,允许直接从使用 BGR、BGRX、RGBX、XBGR 和 XRGB 像素顺序的缓冲区压缩(以及直接解压缩到)JPEG 图像。这是通过十个新的色彩空间常量实现的: ``` JCS_EXT_RGB /* red/green/blue */ JCS_EXT_RGBX /* red/green/blue/x */ JCS_EXT_BGR /* blue/green/red */ JCS_EXT_BGRX /* blue/green/red/x */ JCS_EXT_XBGR /* x/blue/green/red */ JCS_EXT_XRGB /* x/red/green/blue */ JCS_EXT_RGBA /* red/green/blue/alpha */ JCS_EXT_BGRA /* blue/green/red/alpha */ JCS_EXT_ABGR /* alpha/blue/green/red */ JCS_EXT_ARGB /* alpha/red/green/blue */ ``` 将 `cinfo.in_color_space`(压缩)或 `cinfo.out_color_space`(解压缩)设置为这些值之一,将导致 libjpeg-turbo 在从 RGB 缓冲区压缩或解压缩到 RGB 缓冲区时,从像素中的适当位置读取(或将它们写入)红、绿和蓝值。 您的应用程序可以在编译时使用以下代码检查这些扩展是否存在: ``` #ifdef JCS_EXTENSIONS ``` 在运行时,尝试在不支持这些扩展的 libjpeg 实现中使用它们将导致“Bogus input colorspace”错误。应用程序可以捕获此错误,以测试运行时是否支持色彩空间扩展。 在解压缩期间使用 RGBX、BGRX、XBGR 和 XRGB 色彩空间时,X 字节是未定义的,并且为了确保最佳性能,libjpeg-turbo 可以将该字节设置为其希望的任何值。如果应用程序希望将 X 字节用作 alpha 通道,则应指定 `JCS_EXT_RGBA`、`JCS_EXT_BGRA`、`JCS_EXT_ABGR` 或 `JCS_EXT_ARGB`。当使用这些色彩空间常量时,X 字节保证为 0xFF,这被解释为不透明。 您的应用程序可以在编译时使用以下代码检查 alpha 通道色彩空间扩展是否存在: ``` #ifdef JCS_ALPHA_EXTENSIONS ``` 位于 libjpeg-turbo 源代码树中的 [jcstest.c](src/jcstest.c) 演示了如何在编译时和运行时检查色彩空间扩展是否存在。 ## libjpeg v7 和 v8 API/ABI 仿真 随着 libjpeg v7 和 v8 的推出,增加了一些新功能,这使得扩展压缩和解压缩结构成为必要。不幸的是,由于这些结构的暴露性质,扩展它们也必然导致与以前的 libjpeg 版本的向后 ABI 兼容性破坏。因此,为使用 libjpeg v7 或 v8 而构建的程序无法与 libjpeg-turbo 一起工作,因为后者基于 libjpeg v6b 代码库。尽管 libjpeg v7 和 v8 不如 v6b 使用广泛,但已经有足够的程序(包括一些 Linux 发行版)进行了切换,因此有必要在 libjpeg-turbo 中仿真 libjpeg v7 和 v8 ABI。然而,应该注意的是,添加此功能主要是为了让已经编译为使用 libjpeg v7+ 的应用程序能够利用加速的 baseline JPEG 编码/解码,而无需重新编译。libjpeg-turbo 并不声称支持所有 libjpeg v7+ 功能,也不声称在所有情况下产生与 libjpeg v7+ 相同的输出(见下文)。 通过向 `cmake` 传递参数 `-DWITH_JPEG7=1` 或 `-DWITH_JPEG8=1`,您可以构建一个仿真 libjpeg v7 或 v8 ABI 的 libjpeg-turbo 版本,以便针对 libjpeg v7 或 v8 构建的程序可以与 libjpeg-turbo 一起运行。下一节描述支持哪些 libjpeg v7+ 功能以及不支持哪些。 ### 对 libjpeg v7 和 v8 功能的支持 #### 完全支持 - **libjpeg API: 解压缩器中的 IDCT 缩放扩展**
libjpeg-turbo 支持 IDCT 缩放,缩放因子为 1/8、1/4、3/8、1/2、5/8、3/4、7/8、9/8、5/4、11/8、3/2、13/8、7/4、15/8 和 2/1(只有 1/4 和 1/2 经过 SIMD 加速)。 - **libjpeg API: 算术编码** - **libjpeg API: 内存源和目标管理器**
请参阅下面的说明。 - **cjpeg: 亮度和色度的单独质量设置**
请注意,扩展 libpjeg v7+ API 以容纳此功能仅是为了方便。使用 libjpeg v6b 始终可以实现此功能(有关示例,请参阅 rdswitch.c)。 - **cjpeg: 32 位 BMP 支持** - **cjpeg: `-rgb` 选项** - **jpegtran: 无损裁剪** - **jpegtran: `-perfect` 选项** - **jpegtran: 执行无损裁剪时强制宽度/高度** - **rdjpgcom: `-raw` 选项** - **rdjpgcom: 区域设置感知** #### 不支持 注意:截至撰写本文时,已经进行了广泛的研究,探讨 DCT 缩放作为数据减少手段的实用性,以及 SmartScale 作为质量改进手段的实用性。邀请读者在 查阅研究并得出自己的结论,但我们项目的普遍看法是,这些功能尚未证明其有用性足以证明将其包含在 libjpeg-turbo 中是正当的。
- **libjpeg API: 压缩器中的 DCT 缩放**
`cinfo.scale_num` 和 `cinfo.scale_denom` 被静默忽略。 在仿真 libjpeg v7+ API/ABI 时,没有任何技术原因导致无法支持 DCT 缩放,但如果没有 SmartScale 扩展(见下文),则只有 1/2、8/15、4/7、8/13、2/3、8/11、4/5 和 8/9 的缩放因子可用,其实用性有限。 - **libjpeg API: SmartScale**
`cinfo.block_size` 被静默忽略。 SmartScale 是 JPEG 格式的扩展,允许使用 8x8 以外的 DCT 块大小。提供对此新格式的支持是可行的(尤其是在没有完全加速的情况下)。然而,直到/除非该格式成为正式的行业标准,或者至少成为社区接受的解决方案,否则我们对其实现持犹豫态度,因为无法确定它将来是否或如何更改。我们认为 SmartScale 尚未证明其作为无损格式或质量增强手段的充分有用性,因此我们提供此功能的主要兴趣在于作为支持额外 DCT 缩放因子的一种手段。 - **libjpeg API: 压缩器中的精细下采样**
`cinfo.do_fancy_downsampling` 被静默忽略。 这需要 DCT 缩放功能,而该功能不受支持。 - **jpegtran: 缩放**
这需要 DCT 缩放和 SmartScale 功能,而这些功能不受支持。 - **无损 RGB JPEG 文件**
这需要 SmartScale 功能,而该功能不受支持。 ### 那么 libjpeg v9 呢? libjpeg v9 在 JPEG 压缩结构中引入了另一个字段(`color_transform`),从而使 ABI 与 libjpeg v8 的 ABI 向后不兼容。引入此新字段仅仅是为了支持无损 SmartScale 编码。此外,实际上没有理由以这种方式扩展 API,因为通过新的 JPEG 色彩空间常量也可以同样轻松地激活颜色变换,从而保持向后 ABI 兼容性。 我们的研究(见上面的链接)表明,无损 SmartScale 通常无法完成现有标准无损格式无法更好完成的事情。因此,目前我们认为软件项目没有充分的技术理由从 libjpeg v8 升级到 libjpeg v9,因此我们没有充分的技术理由来仿真 libjpeg v9 ABI。 ## 内存源/目标管理器 默认情况下,即使在未仿真 libjpeg v8 API/ABI 时,libjpeg-turbo 1.3 及更高版本也包括 `jpeg_mem_src()` 和 `jpeg_mem_dest()` 函数。以前,必须使用 libjpeg v8 API/ABI 仿真从源代码构建 libjpeg-turbo 才能使用内存源/目标管理器,但有几个项目请求在仿真 libjpeg v6b API/ABI 时也包括这些函数。这允许需要它们的程序使用这些函数,而不会破坏不需要它们的程序的 ABI 兼容性,并且允许在“官方”libjpeg-turbo 二进制文件中提供这些函数。 请注意,在大多数 Un*x 系统上,动态链接器在函数实际被使用之前不会在库中查找该函数。因此,如果程序是针对 libjpeg-turbo 1.3+ 构建的并使用 `jpeg_mem_src()` 或 `jpeg_mem_dest()`,则该程序在针对旧版本的 libjpeg-turbo 或 libjpeg v7- 运行时不会失败,直到程序实际尝试调用 `jpeg_mem_src()` 或 `jpeg_mem_dest()`。在 Windows 上情况并非如此。如果程序是针对 libjpeg-turbo 1.3+ DLL 构建的并使用 `jpeg_mem_src()` 或 `jpeg_mem_dest()`,则它必须在运行时使用 libjpeg-turbo 1.3+ DLL。 cjpeg 和 djpeg 都已扩展为允许测试内存源/目标管理器函数。有关更多详细信息,请参阅它们各自的手册页。 # 数学兼容性 在大多数情况下,libjpeg-turbo 应产生与 libjpeg v6b 相同的输出。有两个例外: 1. 当解压缩使用 4:4:0 色度子采样的 JPEG 图像时,libjpeg v6b 和 libjpeg-turbo 的输出可能不同,因为 libjpeg-turbo 实现了“精细”(平滑)4:4:0 上采样算法,而 libjpeg 没有。 2. 当使用浮点 DCT/IDCT 时,libjpeg v6b 和 libjpeg-turbo 的输出可能因以下原因而不同: - libjpeg-turbo 中的 SSE/SSE2 浮点 DCT 实现比 libjpeg v6b 中的实现稍微一点,但差异并不明显到人眼可见的程度(PNSR 增益通常在 0.01 到 0.08 dB 范围内)。 - 当不使用 SIMD 扩展时,libjpeg-turbo 使用 libjpeg v8a 中引入的更准确(且稍快)的浮点 IDCT 算法,而不是 libjpeg v6b 中使用的算法。然而,应该注意的是,该算法基本上将浮点 IDCT 的准确性提高到了与准确整数 IDCT 的准确性相同的水平。浮点 DCT/IDCT 算法主要是一个遗留功能,它们不会产生比准确整数算法显着更高的准确性。(用数字来说,两种算法之间的典型 PNSR 差异小于 0.10 dB,而在质量范围的上部将质量级别更改 1 通常更像是 1.0 dB 的差异。) - 如果 libjpeg-turbo 中的浮点算法在特定平台上未使用 SIMD 指令实现,则浮点 DCT/IDCT 的准确性可能取决于编译器设置。 虽然 libjpeg-turbo 确实仿真了 libjpeg v8 API/ABI,但在底层它仍然使用与 libjpeg v6b 相同的算法,因此在几种特定情况下,不能期望 libjpeg-turbo 产生与 libjpeg v8 相同的输出: - 当使用 1/2 和 1/4 的缩放因子进行解压缩时,因为 libjpeg v8 实现这些缩放算法的方式与 libjpeg v6b 不同,而 libjpeg-turbo 的 SIMD 扩展基于 libjpeg v6b 的行为。 - 当使用色度子采样时,因为 libjpeg v8 使用其 DCT/IDCT 缩放算法而不是单独的下采样/上采样算法来实现此功能。在我们的测试中,由于此原因,libjpeg v8 的子采样/上采样输出不如 libjpeg v6b 准确。 - 当使用大于 1 的缩放因子和合并(又称“非精细”或“非平滑”)色度上采样进行解压缩时,因为 libjpeg v8 不支持缩放因子大于 1 的合并上采样。 # 性能陷阱 ## 重启标记 libjpeg-turbo 中优化的 Huffman 解码器处理重启标记的方式并不能让 libjpeg 基础结构的其余部分满意,因此在解压缩具有重启标记的 JPEG 图像时必须使用慢速 Huffman 解码器。这可能导致解压缩性能下降多达 20%,但性能仍将远高于 libjpeg。许多消费软件包(如 Photoshop)在生成 JPEG 图像时使用重启标记,因此这些程序生成的图像将遇到此问题。 ## 高质量级别的快速整数正向 DCT 每当使用快速整数正向 DCT 以及 98-100 的 JPEG 质量时,SIMD 加速量化函数使用的算法无法产生正确的结果。因此,在这些情况下,libjpeg-turbo 必须使用非 SIMD 量化函数。这导致性能下降多达 40%。因此,强烈建议每当以 98 或更高的 JPEG 质量编码图像时,使用准确整数正向 DCT。 # 内存调试器陷阱 当与 libjpeg-turbo 的 SIMD 扩展一起使用时,Valgrind 和 Memory Sanitizer (MSan) 可能会产生误报(具体来说,是关于未初始化内存访问的错误报告)。在使用 Valgrind、MSan 或其他内存调试器测试 libjpeg-turbo 时,有两种方法可以解决此问题: 1. 禁用 SIMD 扩展,方法是在配置构建时向 `cmake` 传递参数 `-DWITH_SIMD=0`,或者在运行时将环境变量 `JSIMD_FORCENONE` 设置为 `1`。 2. 定义 `ZERO_BUFFERS` 预处理器宏(例如,通过将 `-DZERO_BUFFERS=1` 添加到 `CMAKE_C_FLAGS`)。
此 API 提供了一个易于使用的界面,用于在内存中压缩和解压缩 JPEG 图像。它还提供了一些使用底层 libjpeg API 难以直接实现的功能,例如生成平面 YUV 图像和对图像执行多个同时无损变换。libjpeg-turbo 的 Java 接口是在 TurboJPEG API 之上编写的。推荐 libjpeg-turbo 的初次使用者使用 TurboJPEG API。有关其用法示例,请参阅 [tjcomp.c](src/tjcomp.c)、[tjdecomp.c](src/tjdecomp.c)、[tjtran.c](src/tjtran.c)、[TJComp.java](java/TJComp.java)、[TJDecomp.java](java/TJDecomp.java) 和 [TJTran.java](java/TJTran.java);有关 API 文档,请参阅
这是用于压缩和解压缩 JPEG 图像的事实上的行业标准 API。它比 TurboJPEG API 更难使用,但也更强大。libjpeg-turbo 中的 libjpeg API 实现与 libjpeg v6b 既是 API/ABI 兼容的,也是数学兼容的。它还可以选择配置为与 libjpeg v7 和 v8 API/ABI 兼容(见下文)。有关其用法示例,请参阅 [cjpeg.c](src/cjpeg.c) 和 [djpeg.c](src/djpeg.c);有关 API 文档,请参阅 [libjpeg.txt](doc/libjpeg.txt)。 当这两个 API 用于执行类似操作时,在性能上没有显著差异。 ## 色彩空间扩展 libjpeg-turbo 包含一些扩展,允许直接从使用 BGR、BGRX、RGBX、XBGR 和 XRGB 像素顺序的缓冲区压缩(以及直接解压缩到)JPEG 图像。这是通过十个新的色彩空间常量实现的: ``` JCS_EXT_RGB /* red/green/blue */ JCS_EXT_RGBX /* red/green/blue/x */ JCS_EXT_BGR /* blue/green/red */ JCS_EXT_BGRX /* blue/green/red/x */ JCS_EXT_XBGR /* x/blue/green/red */ JCS_EXT_XRGB /* x/red/green/blue */ JCS_EXT_RGBA /* red/green/blue/alpha */ JCS_EXT_BGRA /* blue/green/red/alpha */ JCS_EXT_ABGR /* alpha/blue/green/red */ JCS_EXT_ARGB /* alpha/red/green/blue */ ``` 将 `cinfo.in_color_space`(压缩)或 `cinfo.out_color_space`(解压缩)设置为这些值之一,将导致 libjpeg-turbo 在从 RGB 缓冲区压缩或解压缩到 RGB 缓冲区时,从像素中的适当位置读取(或将它们写入)红、绿和蓝值。 您的应用程序可以在编译时使用以下代码检查这些扩展是否存在: ``` #ifdef JCS_EXTENSIONS ``` 在运行时,尝试在不支持这些扩展的 libjpeg 实现中使用它们将导致“Bogus input colorspace”错误。应用程序可以捕获此错误,以测试运行时是否支持色彩空间扩展。 在解压缩期间使用 RGBX、BGRX、XBGR 和 XRGB 色彩空间时,X 字节是未定义的,并且为了确保最佳性能,libjpeg-turbo 可以将该字节设置为其希望的任何值。如果应用程序希望将 X 字节用作 alpha 通道,则应指定 `JCS_EXT_RGBA`、`JCS_EXT_BGRA`、`JCS_EXT_ABGR` 或 `JCS_EXT_ARGB`。当使用这些色彩空间常量时,X 字节保证为 0xFF,这被解释为不透明。 您的应用程序可以在编译时使用以下代码检查 alpha 通道色彩空间扩展是否存在: ``` #ifdef JCS_ALPHA_EXTENSIONS ``` 位于 libjpeg-turbo 源代码树中的 [jcstest.c](src/jcstest.c) 演示了如何在编译时和运行时检查色彩空间扩展是否存在。 ## libjpeg v7 和 v8 API/ABI 仿真 随着 libjpeg v7 和 v8 的推出,增加了一些新功能,这使得扩展压缩和解压缩结构成为必要。不幸的是,由于这些结构的暴露性质,扩展它们也必然导致与以前的 libjpeg 版本的向后 ABI 兼容性破坏。因此,为使用 libjpeg v7 或 v8 而构建的程序无法与 libjpeg-turbo 一起工作,因为后者基于 libjpeg v6b 代码库。尽管 libjpeg v7 和 v8 不如 v6b 使用广泛,但已经有足够的程序(包括一些 Linux 发行版)进行了切换,因此有必要在 libjpeg-turbo 中仿真 libjpeg v7 和 v8 ABI。然而,应该注意的是,添加此功能主要是为了让已经编译为使用 libjpeg v7+ 的应用程序能够利用加速的 baseline JPEG 编码/解码,而无需重新编译。libjpeg-turbo 并不声称支持所有 libjpeg v7+ 功能,也不声称在所有情况下产生与 libjpeg v7+ 相同的输出(见下文)。 通过向 `cmake` 传递参数 `-DWITH_JPEG7=1` 或 `-DWITH_JPEG8=1`,您可以构建一个仿真 libjpeg v7 或 v8 ABI 的 libjpeg-turbo 版本,以便针对 libjpeg v7 或 v8 构建的程序可以与 libjpeg-turbo 一起运行。下一节描述支持哪些 libjpeg v7+ 功能以及不支持哪些。 ### 对 libjpeg v7 和 v8 功能的支持 #### 完全支持 - **libjpeg API: 解压缩器中的 IDCT 缩放扩展**
libjpeg-turbo 支持 IDCT 缩放,缩放因子为 1/8、1/4、3/8、1/2、5/8、3/4、7/8、9/8、5/4、11/8、3/2、13/8、7/4、15/8 和 2/1(只有 1/4 和 1/2 经过 SIMD 加速)。 - **libjpeg API: 算术编码** - **libjpeg API: 内存源和目标管理器**
请参阅下面的说明。 - **cjpeg: 亮度和色度的单独质量设置**
请注意,扩展 libpjeg v7+ API 以容纳此功能仅是为了方便。使用 libjpeg v6b 始终可以实现此功能(有关示例,请参阅 rdswitch.c)。 - **cjpeg: 32 位 BMP 支持** - **cjpeg: `-rgb` 选项** - **jpegtran: 无损裁剪** - **jpegtran: `-perfect` 选项** - **jpegtran: 执行无损裁剪时强制宽度/高度** - **rdjpgcom: `-raw` 选项** - **rdjpgcom: 区域设置感知** #### 不支持 注意:截至撰写本文时,已经进行了广泛的研究,探讨 DCT 缩放作为数据减少手段的实用性,以及 SmartScale 作为质量改进手段的实用性。邀请读者在
`cinfo.scale_num` 和 `cinfo.scale_denom` 被静默忽略。 在仿真 libjpeg v7+ API/ABI 时,没有任何技术原因导致无法支持 DCT 缩放,但如果没有 SmartScale 扩展(见下文),则只有 1/2、8/15、4/7、8/13、2/3、8/11、4/5 和 8/9 的缩放因子可用,其实用性有限。 - **libjpeg API: SmartScale**
`cinfo.block_size` 被静默忽略。 SmartScale 是 JPEG 格式的扩展,允许使用 8x8 以外的 DCT 块大小。提供对此新格式的支持是可行的(尤其是在没有完全加速的情况下)。然而,直到/除非该格式成为正式的行业标准,或者至少成为社区接受的解决方案,否则我们对其实现持犹豫态度,因为无法确定它将来是否或如何更改。我们认为 SmartScale 尚未证明其作为无损格式或质量增强手段的充分有用性,因此我们提供此功能的主要兴趣在于作为支持额外 DCT 缩放因子的一种手段。 - **libjpeg API: 压缩器中的精细下采样**
`cinfo.do_fancy_downsampling` 被静默忽略。 这需要 DCT 缩放功能,而该功能不受支持。 - **jpegtran: 缩放**
这需要 DCT 缩放和 SmartScale 功能,而这些功能不受支持。 - **无损 RGB JPEG 文件**
这需要 SmartScale 功能,而该功能不受支持。 ### 那么 libjpeg v9 呢? libjpeg v9 在 JPEG 压缩结构中引入了另一个字段(`color_transform`),从而使 ABI 与 libjpeg v8 的 ABI 向后不兼容。引入此新字段仅仅是为了支持无损 SmartScale 编码。此外,实际上没有理由以这种方式扩展 API,因为通过新的 JPEG 色彩空间常量也可以同样轻松地激活颜色变换,从而保持向后 ABI 兼容性。 我们的研究(见上面的链接)表明,无损 SmartScale 通常无法完成现有标准无损格式无法更好完成的事情。因此,目前我们认为软件项目没有充分的技术理由从 libjpeg v8 升级到 libjpeg v9,因此我们没有充分的技术理由来仿真 libjpeg v9 ABI。 ## 内存源/目标管理器 默认情况下,即使在未仿真 libjpeg v8 API/ABI 时,libjpeg-turbo 1.3 及更高版本也包括 `jpeg_mem_src()` 和 `jpeg_mem_dest()` 函数。以前,必须使用 libjpeg v8 API/ABI 仿真从源代码构建 libjpeg-turbo 才能使用内存源/目标管理器,但有几个项目请求在仿真 libjpeg v6b API/ABI 时也包括这些函数。这允许需要它们的程序使用这些函数,而不会破坏不需要它们的程序的 ABI 兼容性,并且允许在“官方”libjpeg-turbo 二进制文件中提供这些函数。 请注意,在大多数 Un*x 系统上,动态链接器在函数实际被使用之前不会在库中查找该函数。因此,如果程序是针对 libjpeg-turbo 1.3+ 构建的并使用 `jpeg_mem_src()` 或 `jpeg_mem_dest()`,则该程序在针对旧版本的 libjpeg-turbo 或 libjpeg v7- 运行时不会失败,直到程序实际尝试调用 `jpeg_mem_src()` 或 `jpeg_mem_dest()`。在 Windows 上情况并非如此。如果程序是针对 libjpeg-turbo 1.3+ DLL 构建的并使用 `jpeg_mem_src()` 或 `jpeg_mem_dest()`,则它必须在运行时使用 libjpeg-turbo 1.3+ DLL。 cjpeg 和 djpeg 都已扩展为允许测试内存源/目标管理器函数。有关更多详细信息,请参阅它们各自的手册页。 # 数学兼容性 在大多数情况下,libjpeg-turbo 应产生与 libjpeg v6b 相同的输出。有两个例外: 1. 当解压缩使用 4:4:0 色度子采样的 JPEG 图像时,libjpeg v6b 和 libjpeg-turbo 的输出可能不同,因为 libjpeg-turbo 实现了“精细”(平滑)4:4:0 上采样算法,而 libjpeg 没有。 2. 当使用浮点 DCT/IDCT 时,libjpeg v6b 和 libjpeg-turbo 的输出可能因以下原因而不同: - libjpeg-turbo 中的 SSE/SSE2 浮点 DCT 实现比 libjpeg v6b 中的实现稍微一点,但差异并不明显到人眼可见的程度(PNSR 增益通常在 0.01 到 0.08 dB 范围内)。 - 当不使用 SIMD 扩展时,libjpeg-turbo 使用 libjpeg v8a 中引入的更准确(且稍快)的浮点 IDCT 算法,而不是 libjpeg v6b 中使用的算法。然而,应该注意的是,该算法基本上将浮点 IDCT 的准确性提高到了与准确整数 IDCT 的准确性相同的水平。浮点 DCT/IDCT 算法主要是一个遗留功能,它们不会产生比准确整数算法显着更高的准确性。(用数字来说,两种算法之间的典型 PNSR 差异小于 0.10 dB,而在质量范围的上部将质量级别更改 1 通常更像是 1.0 dB 的差异。) - 如果 libjpeg-turbo 中的浮点算法在特定平台上未使用 SIMD 指令实现,则浮点 DCT/IDCT 的准确性可能取决于编译器设置。 虽然 libjpeg-turbo 确实仿真了 libjpeg v8 API/ABI,但在底层它仍然使用与 libjpeg v6b 相同的算法,因此在几种特定情况下,不能期望 libjpeg-turbo 产生与 libjpeg v8 相同的输出: - 当使用 1/2 和 1/4 的缩放因子进行解压缩时,因为 libjpeg v8 实现这些缩放算法的方式与 libjpeg v6b 不同,而 libjpeg-turbo 的 SIMD 扩展基于 libjpeg v6b 的行为。 - 当使用色度子采样时,因为 libjpeg v8 使用其 DCT/IDCT 缩放算法而不是单独的下采样/上采样算法来实现此功能。在我们的测试中,由于此原因,libjpeg v8 的子采样/上采样输出不如 libjpeg v6b 准确。 - 当使用大于 1 的缩放因子和合并(又称“非精细”或“非平滑”)色度上采样进行解压缩时,因为 libjpeg v8 不支持缩放因子大于 1 的合并上采样。 # 性能陷阱 ## 重启标记 libjpeg-turbo 中优化的 Huffman 解码器处理重启标记的方式并不能让 libjpeg 基础结构的其余部分满意,因此在解压缩具有重启标记的 JPEG 图像时必须使用慢速 Huffman 解码器。这可能导致解压缩性能下降多达 20%,但性能仍将远高于 libjpeg。许多消费软件包(如 Photoshop)在生成 JPEG 图像时使用重启标记,因此这些程序生成的图像将遇到此问题。 ## 高质量级别的快速整数正向 DCT 每当使用快速整数正向 DCT 以及 98-100 的 JPEG 质量时,SIMD 加速量化函数使用的算法无法产生正确的结果。因此,在这些情况下,libjpeg-turbo 必须使用非 SIMD 量化函数。这导致性能下降多达 40%。因此,强烈建议每当以 98 或更高的 JPEG 质量编码图像时,使用准确整数正向 DCT。 # 内存调试器陷阱 当与 libjpeg-turbo 的 SIMD 扩展一起使用时,Valgrind 和 Memory Sanitizer (MSan) 可能会产生误报(具体来说,是关于未初始化内存访问的错误报告)。在使用 Valgrind、MSan 或其他内存调试器测试 libjpeg-turbo 时,有两种方法可以解决此问题: 1. 禁用 SIMD 扩展,方法是在配置构建时向 `cmake` 传递参数 `-DWITH_SIMD=0`,或者在运行时将环境变量 `JSIMD_FORCENONE` 设置为 `1`。 2. 定义 `ZERO_BUFFERS` 预处理器宏(例如,通过将 `-DZERO_BUFFERS=1` 添加到 `CMAKE_C_FLAGS`)。
标签:ARM架构, Bash脚本, IT参考实现, Java接口, JPEG, JS文件枚举, libjpeg-turbo, libjpeg替代, SIMD加速, TurboJPEG, x86优化, 图像压缩, 图像处理, 图像编解码, 图像解压, 多媒体, 客户端加密, 开源库, 搜索引擎爬虫, 编解码器, 霍夫曼编码, 高性能计算