文章目录

  • 一、Android 中使用 libwebp.so 库解码 WebP 图片
  • 二、完整代码示例
  • 三、参考资料

一、Android 中使用 libwebp.so 库解码 WebP 图片


libwebp.jar 中解码相关的的方法如下 : libwebpJNI 是 Java 层调用 libwebp.so 动态库的入口类 ;

    public static byte[] WebPDecodeRGB(byte[] var0, long var1, int[] var3, int[] var4) {return libwebpJNI.WebPDecodeRGB(var0, var1, var3, var4);}public static byte[] WebPDecodeRGBA(byte[] var0, long var1, int[] var3, int[] var4) {return libwebpJNI.WebPDecodeRGBA(var0, var1, var3, var4);}public static byte[] WebPDecodeARGB(byte[] var0, long var1, int[] var3, int[] var4) {return libwebpJNI.WebPDecodeARGB(var0, var1, var3, var4);}public static byte[] WebPDecodeBGR(byte[] var0, long var1, int[] var3, int[] var4) {return libwebpJNI.WebPDecodeBGR(var0, var1, var3, var4);}public static byte[] WebPDecodeBGRA(byte[] var0, long var1, int[] var3, int[] var4) {return libwebpJNI.WebPDecodeBGRA(var0, var1, var3, var4);}

在本博客示例中 , 使用的是 WebPDecodeARGB 方法 , 传入的 444 个参数作用 :

  • byte[] var0 : ARGB 字节数据 ;
  • int var1 : ARGB 字节数据字节个数 ;
  • int[] var3 : 图像宽度 , 传入的是数组 , 只有 1 个元素 , 作为返回值使用 ;
  • int[] var4 : 图像高度 , 传入的是数组 , 只有 1 个元素 , 作为返回值使用 ;
    public static byte[] WebPDecodeARGB(byte[] var0, long var1, int[] var3, int[] var4) {return libwebpJNI.WebPDecodeARGB(var0, var1, var3, var4);}

使用 libwebp.so 库解码 WebP 图片 : 读取 R.mipmap.icon_webp 资源文件 , 使用 libwebp 解码出 RGBA 数据 , 然后将 RGBA 数据转换为 Bitmap 位图 , 最后将 Bitmap 位图显示到界面中 ;

    @SuppressLint("ResourceType")fun libwebpDecode() {var webPStart = System.currentTimeMillis()// 获取 WebP 资源文件的输入流var inputStream: InputStream = resources.openRawResource(R.mipmap.icon_webp)// 将数据读取到 Byte 数组输出流中var bos: ByteArrayOutputStream = ByteArrayOutputStream()var buffer: ByteArray = ByteArray(2048)// 记录长度var len = inputStream.read(buffer)while ( len != -1 ){bos.write(buffer, 0, len)len = inputStream.read(buffer)}inputStream.close()// 读取完毕后 , 获取完整的 Byte 数组数据var data_webp: ByteArray = bos.toByteArray()// 将 ByteArray 解码成 ARGB 数据var width = IntArray(1)var height = IntArray(1)var data_argb_byte: ByteArray = libwebp.WebPDecodeARGB(data_webp, data_webp.size.toLong(), width, height)// 将 data_argb: ByteArray 转为 IntArrayvar data_argb_int = IntArray(data_argb_byte.size / 4)// 使用 nio 中的 ByteBuffer 进行读写var byteBuffer: ByteBuffer = ByteBuffer.wrap(data_argb_byte);// 将 byteBuffer 转为 IntBuffer , 然后获取其中的 int 数组byteBuffer.asIntBuffer().get(data_argb_int)// 将 ARGB 数据转为 Bitmap 位图图像var bitmap: Bitmap = Bitmap.createBitmap(data_argb_int,              // 图像数据 , int 数组格式width[0],                   // 图像宽度height[0],                  // 图像高度Bitmap.Config.ARGB_8888     // 图像颜色格式)// 界面显示解码后的位图binding.imageView.setImageBitmap(bitmap)Log.e(TAG, "使用 libwebp.so 库解码 WebP 格式图片时间 : ${System.currentTimeMillis() - webPStart} ms")}

二、完整代码示例


调用 libweb.jar 中的 libwebp.WebPDecodeARGB 函数 , 进行 WebP 图片的解码操作 ;

同时测试解码的时长 ;

package kim.hsl.webpimport android.annotation.SuppressLint
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import com.google.webp.libwebp
import kim.hsl.webp.databinding.ActivityMainBinding
import java.io.ByteArrayOutputStream
import java.io.FileOutputStream
import java.io.InputStream
import java.nio.ByteBufferclass MainActivity : AppCompatActivity() {companion object{val TAG = "MainActivity"init {System.loadLibrary("webp")}}lateinit var binding: ActivityMainBindingoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding = ActivityMainBinding.inflate(layoutInflater)setContentView(binding.root)Log.e(TAG, "libwebp 函数库版本 : ${libwebp.WebPGetDecoderVersion()}")// 测试 WebP 解码速度decodeWebP()// 测试 WebP 编码速度encodeWebP()// 使用 libwebp 库编码 WebP 图片libwebpEncode()// 使用 libwebp 库解码 WebP 图片libwebpDecode()}@SuppressLint("ResourceType")fun libwebpDecode() {var webPStart = System.currentTimeMillis()// 获取 WebP 资源文件的输入流var inputStream: InputStream = resources.openRawResource(R.mipmap.icon_webp)// 将数据读取到 Byte 数组输出流中var bos: ByteArrayOutputStream = ByteArrayOutputStream()var buffer: ByteArray = ByteArray(2048)// 记录长度var len = inputStream.read(buffer)while ( len != -1 ){bos.write(buffer, 0, len)len = inputStream.read(buffer)}inputStream.close()// 读取完毕后 , 获取完整的 Byte 数组数据var data_webp: ByteArray = bos.toByteArray()// 将 ByteArray 解码成 ARGB 数据var width = IntArray(1)var height = IntArray(1)var data_argb_byte: ByteArray = libwebp.WebPDecodeARGB(data_webp,data_webp.size.toLong(),width,height)// 将 data_argb: ByteArray 转为 IntArrayvar data_argb_int = IntArray(data_argb_byte.size / 4)// 使用 nio 中的 ByteBuffer 进行读写var byteBuffer: ByteBuffer = ByteBuffer.wrap(data_argb_byte);// 将 byteBuffer 转为 IntBuffer , 然后获取其中的 int 数组byteBuffer.asIntBuffer().get(data_argb_int)// 将 ARGB 数据转为 Bitmap 位图图像var bitmap: Bitmap = Bitmap.createBitmap(data_argb_int,              // 图像数据 , int 数组格式width[0],                   // 图像宽度height[0],                  // 图像高度Bitmap.Config.ARGB_8888     // 图像颜色格式)// 界面显示解码后的位图binding.imageView.setImageBitmap(bitmap)Log.e(TAG, "使用 libwebp.so 库解码 WebP 格式图片时间 : ${System.currentTimeMillis() - webPStart} ms")}fun libwebpEncode(){var webPStart = System.currentTimeMillis()// 读取一张本地图片var bitmap = BitmapFactory.decodeResource(resources, R.mipmap.icon_png)// 获取位图宽高var width = bitmap.widthvar height = bitmap.height// 申请一个 Byte 缓冲区var byteBuffer: ByteBuffer = ByteBuffer.allocate(bitmap.byteCount)// 将 位图 数据拷贝到 Byte 缓冲区中bitmap.copyPixelsToBuffer(byteBuffer)// 使用 libwebp.so 进行 WebP 格式编码var data: ByteArray = libwebp.WebPEncodeRGBA(byteBuffer.array(), // 位图数据width,       // 位图宽度height,      // 位图高度width * 4,   // 位图每行数据75F                 // 图像质量)// 将数据写出到文件中var fos = FileOutputStream("${cacheDir}/icon_webp2.webp")fos.write(data)fos.close()Log.e(TAG, "使用 libwebp.so 库编码 WebP 格式图片时间 : ${System.currentTimeMillis() - webPStart} ms , " +"输出文件 : ${cacheDir}/icon_webp2.webp")}fun encodeWebP(){// 读取一张本地图片var bitmap = BitmapFactory.decodeResource(resources, R.mipmap.icon_png)var pngStart = System.currentTimeMillis()var fos = FileOutputStream("${cacheDir}/icon_png.png")bitmap.compress(Bitmap.CompressFormat.PNG, 75, fos)fos.close()Log.e(TAG, "编码 png 格式图片时间 : ${System.currentTimeMillis() - pngStart} ms , " +"输出文件 : ${cacheDir}/icon_png.png")var webPStart = System.currentTimeMillis()fos = FileOutputStream("${cacheDir}/icon_webp.webp")bitmap.compress(Bitmap.CompressFormat.WEBP, 75, fos)fos.close()Log.e(TAG, "编码 WebP 格式图片时间 : ${System.currentTimeMillis() - webPStart} ms , " +"输出文件 : ${cacheDir}/icon_webp.webp")}fun decodeWebP(){var pngStart = System.currentTimeMillis()BitmapFactory.decodeResource(resources, R.mipmap.icon_png)Log.e(TAG, "解码 png 格式图片时间 : ${System.currentTimeMillis() - pngStart} ")var webPStart = System.currentTimeMillis()BitmapFactory.decodeResource(resources, R.mipmap.icon_webp)Log.e(TAG, "解码 WebP 格式图片时间 : ${System.currentTimeMillis() - webPStart} ")}
}

执行结果 :

2021-04-25 17:24:20.486 12660-12707/kim.hsl.webp E/libc: Access denied finding property "vendor.debug.egl.profiler"
2021-04-25 17:24:20.653 12660-12660/kim.hsl.webp E/MainActivity: libwebp 函数库版本 : 1537
2021-04-25 17:24:20.933 12660-12660/kim.hsl.webp E/MainActivity: 解码 png 格式图片时间 : 280
2021-04-25 17:24:21.134 12660-12660/kim.hsl.webp E/MainActivity: 解码 WebP 格式图片时间 : 201
2021-04-25 17:24:23.814 12660-12660/kim.hsl.webp E/MainActivity: 编码 png 格式图片时间 : 2410 ms , 输出文件 : /data/user/0/kim.hsl.webp/cache/icon_png.png
2021-04-25 17:24:26.902 12660-12660/kim.hsl.webp E/MainActivity: 编码 WebP 格式图片时间 : 3088 ms , 输出文件 : /data/user/0/kim.hsl.webp/cache/icon_webp.webp
2021-04-25 17:24:30.289 12660-12660/kim.hsl.webp E/MainActivity: 使用 libwebp.so 库编码 WebP 格式图片时间 : 3387 ms , 输出文件 : /data/user/0/kim.hsl.webp/cache/icon_webp2.webp
2021-04-25 17:24:30.457 12660-12660/kim.hsl.webp E/MainActivity: 使用 libwebp.so 库解码 WebP 格式图片时间 : 168 ms

使用 libwebp.so 库解码 WebP 图片的速度要 高于 Android 本身自带 API 的速度 ;

界面显示 :

三、参考资料


参考文档 :

  • 创建 WebP 图片 : https://developer.android.google.cn/studio/write/convert-webp

  • Android 中支持的媒体格式 : https://developer.android.google.cn/guide/topics/media/media-formats

  • isparta 工具官网 : http://isparta.github.io/

  • isparta 工具 GitHub 地址 : https://github.com/iSparta/iSparta

  • Google 提供的 WebP 工具 ( 国内不能访问 ) : https://developers.google.com/speed/webp/download

  • Google WebP 主页 : https://developers.google.com/speed/webp

  • WebP 相关工具下载页 : https://developers.google.com/speed/webp/download

  • WebP工具和函数库使用文档 : https://developers.google.com/speed/webp/docs/using

Android NDK 编译构建脚本参考文档 :

  • ndk-build 脚本 : https://developer.android.google.cn/ndk/guides/ndk-build
  • Android.mk 构建脚本 : https://developer.android.google.cn/ndk/guides/android_mk
  • Application.mk 构建脚本 : https://developer.android.google.cn/ndk/guides/application_mk

博客资源 :

  • iSparta 工具 : https://download.csdn.net/download/han1202012/17496041
  • Google libwebp 库 : https://download.csdn.net/download/han1202012/17498155
  • libwebp 源码及编译相关资源 : https://download.csdn.net/download/han1202012/17826464 ( 源码 , 编译脚本 , 编译结果 so 库 )

博客源码 :

  • GitHub 地址 : https://github.com/han1202012/Webp
  • CSDN 下载地址 : https://download.csdn.net/download/han1202012/18125733

【Android 安装包优化】WebP 应用 ( Android 中使用 libwebp.so 库解码 WebP 图片 )相关推荐

  1. 【Android 安装包优化】WebP 应用 ( 4.0 以下兼容 WebP | Android Studio 中使用 libwebp.so 库向下兼容版本 | libwebp 库测试可用性 )

    文章目录 一. Android Studio 中导入 libwebp.so 库 二. Android Studio 中测试 libwebp.so 库 三.参考资料 一. Android Studio ...

  2. 【Android 安装包优化】WebP 应用 ( Android 中使用 libwebp.so 库编码 WebP 图片 )

    文章目录 一.Android 中使用 libwebp.so 库编码 WebP 图片 二.完整代码示例 三.参考资料 一.Android 中使用 libwebp.so 库编码 WebP 图片 libwe ...

  3. 【Android 安装包优化】WebP 图片格式性能测试 ( 测试 WebP 图片解码速度 | 测试 WebP 图片编码速度 )

    文章目录 一.测试 WebP 图片解码速度 二.测试 WebP 图片编码速度 三.参考资料 测试结果 : WebP 格式图片 , 解码快 , 编码慢 , 占用空间小 ; 在解码速度上 , WebP 格 ...

  4. 【Android 安装包优化】Android 中使用 SVG 图片 ( Android 5.0 以下的矢量图方案 | 矢量图生成为 PNG 图片 )

    文章目录 一.Android 5.0 以下的矢量图方案 二.矢量图生成为 PNG 图片 三.完整的 build.gradle 构建脚本 四.编译效果 五.参考资料 一.Android 5.0 以下的矢 ...

  5. 【Android 安装包优化】使用 lib7zr.so 动态库处理压缩文件 ( jni 中 main 函数声明 | 命令行处理 | jni 调用 lib7zr.so 函数库处理压缩文件完整代码 )

    文章目录 一.JNI 中 main 函数声明 二.命令字符串切割并传入 main 函数 三.完整代码示例 1.完整 jni 代码 2.完整 java 代码 3.执行结果 四.参考资料 前置博客 : [ ...

  6. 【Android 安装包优化】使用 lib7zr.so 动态库处理压缩文件 ( 拷贝 lib7zr.so 动态库头文件到 Android 工程中 | 配置 CMakeLists.txt 构建脚本 )

    文章目录 一.拷贝 p7zip 源码中的头文件到 Android Studio 项目中 二.配置 CMakeLists.txt 构建脚本 1.导入动态库 2.导入头文件 三.完整 CMakeLists ...

  7. 【Android 安装包优化】Android 中使用 7zr 可执行程序 解压缩文件

    文章目录 一.Android 中使用 7zr 可执行程序 解压缩文件 二.完整代码示例 三.参考资料 一.Android 中使用 7zr 可执行程序 解压缩文件 在上一篇博客 [Android 安装包 ...

  8. 【Android 安装包优化】Android 中使用 7zr 可执行程序 压缩文件

    文章目录 一.Android 中使用 7zr 可执行程序压缩文件 二.完整代码示例 三.参考资料 一.Android 中使用 7zr 可执行程序压缩文件 在上一篇博客 [Android 安装包优化]A ...

  9. 【Android 安装包优化】Android 应用中 7zr 可执行程序准备 ( Android Studio 导入可执行 7zr 程序 | 从 Assets 资源文件拷贝 7zr 到内置存储 )

    文章目录 一.Android Studio 导入可执行 7zr 程序 二.从 Assets 资源文件拷贝 7zr 到内置存储空间 三.参考资料 一.Android Studio 导入可执行 7zr 程 ...

最新文章

  1. 小程序客服消息推送自动回复_如何让小程序客服消息根据用户输入关键词自动回复图片?...
  2. 微软:超过96%的企业用户正在测试Win10
  3. 20179214 2017-2018-2 《密码与安全新技术》第七次作业
  4. 编程统计BUF字单元数据中所含1的个数,并将结果存入COUNT单元中。
  5. python 获取字符串中的字典_python cookies提取——从字符串到字典(一行Python代码)...
  6. 寒假汇编语言作业(11)
  7. LeetCode 103——二叉树的锯齿形层次遍历
  8. python3的encode()和decode()
  9. OICQ登录号码清除器实现原理
  10. JAVA 实现阿里云的短信验证码
  11. Three.js入门教程——教不会算我输
  12. 无线网络的设置和使用
  13. [PPPOE]PPPD的选项
  14. 20220904小红书笔试
  15. 职业教育迎来新的发展期
  16. android 谷歌地图围栏,如何在谷歌地图与c做地理围栏#
  17. 计算机专业排名211大学排名,计算机专业大学排名,计算机专业强的211!
  18. Dubbo源码解析(九)Dubbo系列 源码总结+最近感悟
  19. SylixOS更新记录
  20. 51信用卡管家app产品需求文档

热门文章

  1. some language grammars
  2. RMQ(Range Minimum/Maximum Query)问题:
  3. 浏览器无法访问虚拟机的服务器
  4. Redis搭建(二):主从复制
  5. 【EF Code First】 一对一、一对多的多重关系配置
  6. java学习笔记1--开发环境平台总结
  7. jQueryui autocomplete使用示例
  8. Delphi 2010 refactor / refactoring 重构不能使用的原因以及解决
  9. 在SharePoint 2010中通过SQL数据源创建仪表板
  10. vue中如何使用mockjs摸拟接口的各种数据