博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android 在已有工程中实现微信图片压缩
阅读量:6874 次
发布时间:2019-06-26

本文共 5074 字,大约阅读时间需要 16 分钟。

这个我们需要自己去编译,但是已经有人帮我们编译好了,压缩算法也已经实现,因此,我们去下载然后编译即可:

首先将上面下载好的已经编译好的libjpeg放到jni目录下,将下图内容都放到jni目录中: 

这里写图片描述
安装好ndk以后,直接输入ndk-build即可。接下来就会编译生成生成两个文件夹及文件夹中的arm下的动态库 
这里写图片描述 
我的libs中的armeabi和armeabi-v7a中没有生成libbitherjni.so 
libjpegbither.so,不知道哪里出了问题,项目时间紧我就直接把现成的libbitherjni.so,libjpegbither.so文件拷贝进去了。日后研究下为什么ndk-build失败。

二、编写使用类net.bither.util.NativeUtil.java

使用的时候必须在项目中新建一个包net.bither.util,然后加入下面这个类方法,也就是使用了libjpeg开启哈夫曼算法的压缩算法:

/* * Copyright 2014 http://Bither.net * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *    http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package net.bither.util;import android.graphics.Bitmap;import android.graphics.Bitmap.Config;import android.graphics.Canvas;import android.graphics.Rect;import android.util.Log;public class NativeUtil {    private static int DEFAULT_QUALITY = 95;    public static void compressBitmap(Bitmap bit, String fileName,            boolean optimize) {        compressBitmap(bit, DEFAULT_QUALITY, fileName, optimize);    }    public static void compressBitmap(Bitmap bit, int quality, String fileName,            boolean optimize) {        Log.d("native", "compress of native");        // if (bit.getConfig() != Config.ARGB_8888) {
Bitmap result = null; result = Bitmap.createBitmap(bit.getWidth() / 3, bit.getHeight() / 3, Config.ARGB_8888);// 缩小3倍 Canvas canvas = new Canvas(result); Rect rect = new Rect(0, 0, bit.getWidth(), bit.getHeight());// original rect = new Rect(0, 0, bit.getWidth() / 3, bit.getHeight() / 3);// 缩小3倍 canvas.drawBitmap(bit, null, rect, null); saveBitmap(result, quality, fileName, optimize); result.recycle(); // } else { // saveBitmap(bit, quality, fileName, optimize); // } } private static void saveBitmap(Bitmap bit, int quality, String fileName, boolean optimize) { compressBitmap(bit, bit.getWidth(), bit.getHeight(), quality, fileName.getBytes(), optimize); } private static native String compressBitmap(Bitmap bit, int w, int h, int quality, byte[] fileNameBytes, boolean optimize); static { System.loadLibrary("jpegbither"); System.loadLibrary("bitherjni"); }}

注意包名和方法名都是不能变的,因为在编译的时候已经被确定。 

如果我们想要去修改方法名放入自己的项目中怎么办。那我们就需要去修改一下bitherlibjni.c这个文件。 
例如我想把这个方法放在com.example.test中的ImageUtils中, 
我们只需要把c文件中的

jstring Java_net_bither_util_NativeUtil_compressBitmap(JNIEnv* env,      jobject thiz, jobject bitmapcolor, int w, int h, int quality,      jbyteArray fileNameStr, jboolean optimize) {

修改为

jstring Java_com_example_test_ImageUtils_compressBitmap(JNIEnv* env,      jobject thiz, jobject bitmapcolor, int w, int h, int quality,      jbyteArray fileNameStr, jboolean optimize) {

这个对会ndk开发的同学应该都知道,接下来我们重新运行ndk-build就可以重新替换so文件然后调用我们自己的libjpeg了。 

但是,目前libjpeg是很多年前的了。github上这个库只支持arm架构的cpu,如果我们想用这个库的话,只能通过在加载so文件的时候对其进行trycatch处理,来防止x86等其他cpu架构的机器加载so文件报错。

三、调用NativeUtil.java方法进行压缩

NativeUtil.compressBitmap()

public static String compressBitmap(Bitmap image, String filePath){ 

// 最大图片大小 150KB 
int maxSize = 4; 
// 获取尺寸压缩倍数 
int ratio = NativeUtil.getRatioSize(image.getWidth(),image.getHeight()); 
// 压缩Bitmap到对应尺寸 
Bitmap result = Bitmap.createBitmap(image.getWidth() / ratio,image.getHeight() / ratio,Config.ARGB_8888); 
Canvas canvas = new Canvas(result); 
Rect rect = new Rect(0, 0, image.getWidth() / ratio, image.getHeight() / ratio); 
canvas.drawBitmap(image,null,rect,null); 
ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
// 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中 
int options = 100; 
result.compress(Bitmap.CompressFormat.JPEG, options, baos); 
// 循环判断如果压缩后图片是否大于150KB,大于继续压缩 
while (baos.toByteArray().length / 1024 > maxSize) { 
// 重置baos即清空baos 
baos.reset(); 
// 每次都减少10 
options -= 10; 
// 这里压缩options%,把压缩后的数据存放到baos中 
result.compress(Bitmap.CompressFormat.JPEG, options, baos); 
// JNI保存图片到SD卡 这个关键 
String filename = UUID.randomUUID().toString() + “.jpg”; 
String path = filePath + File.separator + filename; 
NativeUtil.saveBitmap(result, options, path, true); 
// 释放Bitmap 
if (!result.isRecycled()) { 
result.recycle(); 
return path; 
}

2.private static void saveBitmap(Bitmap bit, int quality, String fileName, boolean optimize) { 

compressBitmap(bit, bit.getWidth(), bit.getHeight(), quality, fileName.getBytes(), optimize); 
bmp 需要压缩的Bitmap对象, quality压缩质量0-100, fileName 压缩后要保存的文件地址, optimize 是否采用哈弗曼表数据计算 品质相差5-10倍 
该方法就是底层 bitherlibjni.c中的压缩方法

private static native String compressBitmap(Bitmap bit, int w, int h, int quality, byte[] fileNameBytes,boolean optimize);

  3.要注意的地方就是要在build.gradle里面添加下面代码,否则就会报找不到so文件的错误。 

sourceSets { 
main { 
jniLibs.srcDirs = [‘libs’] 
}

你可能感兴趣的文章
关于scrapy的piplines
查看>>
内核同步机制
查看>>
用 Tornado 实现简单的在线代理
查看>>
Java写到.txt文件,如何实现换行
查看>>
JavaScript之isNaN()函数讲解
查看>>
MPlayer源代码分析
查看>>
获取音视频文件AVMetadata数据
查看>>
sql serve 创建序列
查看>>
模型层的生成
查看>>
关于APP接口设计
查看>>
【VI】如何再执行上一个(历史)命令(已解决)
查看>>
KendoUI系列:DropDownList
查看>>
Axure7.0汉化方法
查看>>
我的MYSQL学习心得(九)
查看>>
JavaScript高级程序设计学习笔记--DOM
查看>>
Python易学就会(五)turtle绘制椭圆与递归
查看>>
echarts map地图设置外边框或者阴影
查看>>
使用vue-cli脚手架+webpack搭建vue项目
查看>>
Docker - 03 编排容器 Docker Compose 指令速查表
查看>>
Mybatis基本映射--INSERT
查看>>