在已有工程中实现微信图片压缩

一、编译

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

首先将上面下载好的已经编译好的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方法进行压缩

  1. 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’]
}
}

参考:
http://blog.csdn.net/qq_25412055/article/details/53878655
http://www.jianshu.com/p/e9e1db845c21

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值