Android 在已有工程中實現微信圖片壓縮


這個我們需要自己去編譯,但是已經有人幫我們編譯好了,壓縮算法也已經實現,因此,我們去下載然后編譯即可: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方法進行壓縮

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’] 

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM