前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Android 内存优化】Android 原生 API 图片压缩原理 ( 哈夫曼编码开关 | 哈夫曼编码原理 | libjpeg-turbo 函数库 )

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

作者头像
韩曙亮
发布2023-03-27 21:52:26
7540
发布2023-03-27 21:52:26
举报
文章被收录于专栏:韩曙亮的移动开发专栏

文章目录

【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 以后的版本 , 打开图片压缩哈夫曼编码功能 ;

代码语言:javascript
复制
// 该类是 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 发布版本地址 进入该界面 ;

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

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-06-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 一、 哈夫曼编码开关
  • 二、 哈夫曼编码原理
  • 三、 libjpeg-turbo 函数库
  • 四、 libjpeg-turbo 函数库下载
相关产品与服务
图片处理
图片处理(Image Processing,IP)是由腾讯云数据万象提供的丰富的图片处理服务,广泛应用于腾讯内部各产品。支持对腾讯云对象存储 COS 或第三方源的图片进行处理,提供基础处理能力(图片裁剪、转格式、缩放、打水印等)、图片瘦身能力(Guetzli 压缩、AVIF 转码压缩)、盲水印版权保护能力,同时支持先进的图像 AI 功能(图像增强、图像标签、图像评分、图像修复、商品抠图等),满足多种业务场景下的图片处理需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档