【Android 内存优化】Android 原生 API 图片压缩原理 ( 哈夫曼编码开关 | 哈夫曼编码原理 | libjpeg-turbo 函数库 )

简介: 【Android 内存优化】Android 原生 API 图片压缩原理 ( 哈夫曼编码开关 | 哈夫曼编码原理 | libjpeg-turbo 函数库 )

文章目录

一、 哈夫曼编码开关

二、 哈夫曼编码原理

三、 libjpeg-turbo 函数库

四、 libjpeg-turbo 函数库下载



【Android 内存优化】图片文件压缩 ( Android 原生 API 提供的图片压缩功能能 | 图片质量压缩 | 图片尺寸压缩 ) 简要介绍了 图片文件压缩格式 , 以及 Android 提供的图片质量 , 尺寸压缩原生 API ;



【Android 内存优化】Android 原生 API 图片压缩代码示例 ( PNG 格式压缩 | JPEG 格式压缩 | WEBP 格式压缩 | 动态权限申请 | Android10 存储策略 ) 主要使用了上述 Android 原生 API 压缩图片功能进行图片压缩 ;



【Android 内存优化】Android 原生 API 图片压缩原理 ( 图片质量压缩方法 | 查找 Java 源码中的 native 方法对应的 C++ 源码 ) 中主要查找 Bitmap.java 对应的 Native 层的 C++ 类 Bitmap.cpp 源码文件 , 并分析了其动态注册 Native 方法的过程 ;



【Android 内存优化】Android 原生 API 图片压缩原理 ( Bitmap_compress 方法解析 | Skia 二维图形库 | libjpeg 函数库 | libpng 函数库 ) 博客中分析了 Bitmap.cpp 中的 Bitmap_compress 方法 ;







一、 哈夫曼编码开关


上一篇博客 【Android 内存优化】Android 原生 API 图片压缩原理 ( Bitmap_compress 方法解析 | Skia 二维图形库 | libjpeg 函数库 | libpng 函数库 ) 分析到了 实际的图片压缩方法是由 Skia 图形库执行的 , Skia 图形库根据不同的压缩格式 , 选择不同的函数库进行压缩 , 如果压缩格式是 JPEG 格式 , 那么使用 libjpeg 库进行图片压缩 , 如果压缩格式是 PNG 库 , 那么使用 libpng 库进行压缩 ;



1. 哈夫曼编码 : 在 libjpeg 中提供了图片哈夫曼编码功能 , 该功能非常消耗 CPU 性能 , 因此早期的 Android 版本禁用了该功能 , 在 7.0 之后的版本 , 此时 Android 设备上的 CPU 性能很高 , 这时才将哈夫曼编码功能打开 ; ( SkImageDecoder_libjpeg.cpp 代码参考 )



2. 打开哈夫曼编码 : 将 jpeg_compress_struct 结构体的 optimize_coding 成员设置成 TRUE ; 作用是 通知 libjpeg-turbo 为图像计算最佳的哈夫曼编码表 , 该操作可以 提高图片压缩比例 , 代价是编码速度较慢 ;



3. 源码参考 :


SkImageDecoder_libjpeg.cpp 中 SkJPEGImageEncoder 类 ( SkImageEncoder 对应的 JPEG 格式图片压缩实现类 ) 中的 onEncode 方法 , 在 7.0 以后的版本 , 打开图片压缩哈夫曼编码功能 ;


// 该类是 SkImageEncoder 的子类 , 在 Bitmap.cpp 中使用的就是
class SkJPEGImageEncoder : public SkImageEncoder {
protected:
    virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) {
  // ... 
  jpeg_compress_struct    cinfo;
  // ... 
        // 打开哈夫曼编码 
        // 通知 libjpeg-turbo 为图像计算最佳的哈夫曼编码表
        // 该功能可以提高压缩比例 , 代价是编码速度较慢
        cinfo.optimize_coding = TRUE;
        // ... 
        return true;
    }
};


源码位置 7.0.0/external/skia/src/images/SkImageDecoder_libjpeg.cpp ( 7.0.0 以后的源码才添加了上述功能 )






二、 哈夫曼编码原理


在 libjpeg 编码中 , 如果没有开启哈夫曼编码 , 采用的是定长的编码方式 , 如果打开了哈夫曼编码 , 采用的就是变长哈夫曼编码 , 可以大幅度压缩数据大小 ;



简介 : 哈夫曼编码是字符编码 , 适用于数据文件压缩场景 , 能大幅度压缩文件大小 ;



哈夫曼编码原理 : 每个数据的编码长度可变 , 文件中出现较多的字符使用短编码 , 出现较少的字符使用长编码 , 另外额外维护一张哈夫曼编码表 , 用于维护字符与编码的对应关系 , 总体的文件大小会降低 20% 至 90% ;






三、 libjpeg-turbo 函数库


使用哈夫曼编码进行图片压缩 , 能最大幅度压缩图片大小 , 但是 Android 原生编码中只有 7.0 以后的系统才打开了哈夫曼编码功能 , 目前的主流应用都要向下兼容到 android-17 平台版本 , 对应的系统版本是 Android 4.2 Jelly Bean , 这里就需要引入第三方库 libjpeg-turbo 函数库 , 进行哈夫曼编码图片压缩 , 该函数库是由 C 语言开发 , 需要在 Ubuntu 中进行交叉编译成 ARM 架构的函数库 ( 动态库 / 静态库 ) , 然后导入到 Android Studio 中使用 ;



Android 源码中有 libjpeg-turbo 库 , 但是Java 框架中提供的 Bitmap.java 只能调用 Bitmap.cpp 中的代码 , Bitmap.cpp 中通过 Skia 2D 图形库调用 libjpeg 库 , 在该 C++ 代码中是固定的 , 开发者无法修改框架层的源码 , 因此该函数库无法被开发者调用到 ;



NDK 交叉编译开发参考 : Android NDK 开发 专栏






四、 libjpeg-turbo 函数库下载


1. libjpeg-turbo 相关资源链接 :



① libjpeg-turbo 官方网站 : https://libjpeg-turbo.org/


② GitHub 地址 : libjpeg-turbo/libjpeg-turbo


③ libjpeg-turbo 文档 : 文档地址




2. 下载发布版本 :



在 Android 工程中使用该函数库 , 尽量下载发布的稳定版本 , 最好不要直接下载开发中的 DEBUG 版本 , 可能存在 BUG ;


如下图 , 找到 release 发布版本界面 , 下载最新的发布版本 ; 或者直接点击 libjpeg-turbo/libjpeg-turbo 项目的 Release 发布版本地址 进入该界面 ;


image.png



进入 Release 界面后 , 查看到目前最新的发布版本是 2.0.5 版本 , 直接下载该源码 ; 之后需要到 Ubuntu 中进行交叉编译 ;

image.png




下载这个 Source code (tar.gz) 源码 , 到 Ubuntu 中进行交叉编译 ; ( 也可以直接点击上述连接下载 )


image.png

目录
相关文章
|
16天前
|
Java 测试技术 Android开发
Android性能测试——发现和定位内存泄露和卡顿
本文详细介绍了Android应用性能测试中的内存泄漏与卡顿问题及其解决方案。首先,文章描述了使用MAT工具定位内存泄漏的具体步骤,并通过实例展示了如何分析Histogram图表和Dominator Tree。接着,针对卡顿问题,文章探讨了其产生原因,并提供了多种测试方法,包括GPU呈现模式分析、FPS Meter软件测试、绘制圆点计数法及Android Studio自带的GPU监控功能。最后,文章给出了排查卡顿问题的四个方向,帮助开发者优化应用性能。
58 4
Android性能测试——发现和定位内存泄露和卡顿
|
15天前
|
Android开发 UED Kotlin
Android中如何跳转到Wi-Fi开关设置页
本文介绍如何在Android应用开发中使用隐式Intent引导用户至特定系统设置页面,如Wi-Fi设置页,并提供Kotlin代码示例。通过设置Intent的Action属性并检查设备兼容性,可轻松实现跳转功能,提升用户体验。此外,还列举了其他常用设置页面的Intent Action及注意事项。
38 15
|
21天前
|
安全 Java API
【性能与安全的双重飞跃】JDK 22外部函数与内存API:JNI的继任者,引领Java新潮流!
【9月更文挑战第7天】JDK 22外部函数与内存API的发布,标志着Java在性能与安全性方面实现了双重飞跃。作为JNI的继任者,这一新特性不仅简化了Java与本地代码的交互过程,还提升了程序的性能和安全性。我们有理由相信,在外部函数与内存API的引领下,Java将开启一个全新的编程时代,为开发者们带来更加高效、更加安全的编程体验。让我们共同期待Java在未来的辉煌成就!
46 11
|
22天前
|
安全 Java API
【本地与Java无缝对接】JDK 22外部函数和内存API:JNI终结者,性能与安全双提升!
【9月更文挑战第6天】JDK 22的外部函数和内存API无疑是Java编程语言发展史上的一个重要里程碑。它不仅解决了JNI的诸多局限和挑战,还为Java与本地代码的互操作提供了更加高效、安全和简洁的解决方案。随着FFM API的逐渐成熟和完善,我们有理由相信,Java将在更多领域展现出其强大的生命力和竞争力。让我们共同期待Java编程新纪元的到来!
43 11
|
19天前
|
监控 Java 大数据
【Java内存管理新突破】JDK 22:细粒度内存管理API,精准控制每一块内存!
【9月更文挑战第9天】虽然目前JDK 22的确切内容尚未公布,但我们可以根据Java语言的发展趋势和社区的需求,预测细粒度内存管理API可能成为未来Java内存管理领域的新突破。这套API将为开发者提供前所未有的内存控制能力,助力Java应用在更多领域发挥更大作用。我们期待JDK 22的发布,期待Java语言在内存管理领域的持续创新和发展。
|
4天前
|
负载均衡 API 数据安全/隐私保护
Zookeeper的客户端-原生的API
Zookeeper的客户端-原生的API
|
14天前
|
监控 算法 数据可视化
深入解析Android应用开发中的高效内存管理策略在移动应用开发领域,Android平台因其开放性和灵活性备受开发者青睐。然而,随之而来的是内存管理的复杂性,这对开发者提出了更高的要求。高效的内存管理不仅能够提升应用的性能,还能有效避免因内存泄漏导致的应用崩溃。本文将探讨Android应用开发中的内存管理问题,并提供一系列实用的优化策略,帮助开发者打造更稳定、更高效的应用。
在Android开发中,内存管理是一个绕不开的话题。良好的内存管理机制不仅可以提高应用的运行效率,还能有效预防内存泄漏和过度消耗,从而延长电池寿命并提升用户体验。本文从Android内存管理的基本原理出发,详细讨论了几种常见的内存管理技巧,包括内存泄漏的检测与修复、内存分配与回收的优化方法,以及如何通过合理的编程习惯减少内存开销。通过对这些内容的阐述,旨在为Android开发者提供一套系统化的内存优化指南,助力开发出更加流畅稳定的应用。
31 0
|
28天前
|
存储 JavaScript 前端开发
探索React状态管理:Redux的严格与功能、MobX的简洁与直观、Context API的原生与易用——详细对比及应用案例分析
【8月更文挑战第31天】在React开发中,状态管理对于构建大型应用至关重要。本文将探讨三种主流状态管理方案:Redux、MobX和Context API。Redux采用单一存储模型,提供预测性状态更新;MobX利用装饰器语法,使状态修改更直观;Context API则允许跨组件状态共享,无需第三方库。每种方案各具特色,适用于不同场景,选择合适的工具能让React应用更加高效有序。
41 0
|
29天前
|
API 开发者 Python
API接口:原理、实现及应用
本文详细介绍了API接口在现代软件开发中的重要性及其工作原理。API接口作为应用程序间通信的桥梁,通过预定义的方法和协议实现数据和服务的共享。文章首先解释了API接口的概念,接着通过Python Flask框架示例展示了API的设计与实现过程,并强调了安全性的重要性。最后,本文还讨论了API接口在Web服务和移动应用程序等领域的广泛应用场景。

热门文章

最新文章