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

网友投稿 1239 2022-05-30

文章目录

一、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); }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

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

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); }

1

2

3

使用 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 转为 IntArray var 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") }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

二、完整代码示例

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

同时测试解码的时长 ;

package kim.hsl.webp import 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.ByteBuffer class MainActivity : AppCompatActivity() { companion object{ val TAG = "MainActivity" init { System.loadLibrary("webp") } } lateinit var binding: ActivityMainBinding override 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 转为 IntArray var 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.width var 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} ") } }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

执行结果 :

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

1

2

3

4

5

6

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

7

8

使用 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 数据结构

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:❤️【Python从入门到精通】(二十六)用Python的PIL库(Pillow)处理图像真的得心应手❤️
下一篇:华为云ModelArts结合AnimeGANv2,让照片在云上动漫化 丨【华为云AI贺新年】
相关文章