1. 程式人生 > >Andorid開發工具類之——BitmapUtils(壓縮圖片利器,告別oom,程式更快)

Andorid開發工具類之——BitmapUtils(壓縮圖片利器,告別oom,程式更快)

最近開發的一個專案使用到了圖片載入上傳和儲存,由於是接受別人的做,也基本上做完了。但是程式已啟動到需要載入圖片上傳到伺服器的介面的時候記憶體就暴漲,雖然也沒有oom,估計舊點的手機肯定會爆,只要不啟動到圖片載入的頁面,記憶體基本上佔用只用20+mb,選擇圖片後達到了80兆。這肯定是不行的,隨後自己研究了幾天,把有關上傳和載入圖片的程式碼全部推翻了,自己重寫了一遍,現在基本上不管怎麼載入圖片也不會超過30MB了,不載入圖片20多MB.載入的方式和邏輯就不說明了,這裡主要提供一個核心類,圖片壓縮。

Android涉及到圖片肯定會用到Bitmap,然而Bitmap的佔記憶體的方式也不是我們想的那麼簡單,具體一張Bitmap圖片佔用記憶體的方式為多大,自行谷歌去。

好了提供一套從壓縮到儲存,到上傳的工具類;保證好用;

/**
 * 圖片處理類
 *
 * @author Ricko
 */
public class BitmpUtils {

    /**
     * 取樣率壓縮  按照圖片寬高自動計算縮放比,圖片質量有保障
     *
     * @param filePath  設定寬高並不是設定圖片實際寬高,而是根據寬高自動計算縮放比,壓縮後圖片不會變形,寬高會根據計算的縮放比同時縮放,
     *                  寬高建議都設定300   設定300後圖片大小為100-200KB,圖片質量能接受;設定為400到500,圖片大小為500-600kb,上傳偏大,可自行設定
     * @param reqHeight  
     * @param reqWidth
     * @return
     */
    public static Bitmap getSmallBitmap(String filePath, int reqHeight, int reqWidth) {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filePath, options);
        //計算圖片的縮放值
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;
        if (height > reqHeight || width > reqWidth) {
            final int heightRatio = Math.round((float) height / (float) reqHeight);
            final int widthRatio = Math.round((float) width / (float) reqWidth);
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
        }
        options.inSampleSize = inSampleSize;
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeFile(filePath, options);
    }

 
   /**
     *這個可以壓縮到指定的寬,但是圖片大小可能達不到預期,圖片本身較小的可以使用,圖片較大的建議使用上一個壓縮方式
     * 根據自定義寬度設定圖片大小,高度自適應  0不壓縮
     *
     * @param path
     * @param width
     * @return
     */
    public static Bitmap createScaledBitemap(String path, int width) {
        Bitmap bit = BitmapFactory.decodeFile(path);
        int bitWidth = bit.getWidth();//得到圖片寬
        float scaleWidth = ((float) width) / ((float) bitWidth);//計算寬度縮放比例
        if (width == 0) {
            return bit;
        } else {
            int height = (int) (bit.getHeight() * scaleWidth);//根據寬度縮放比例設定高度
            Bitmap bitmap = Bitmap.createScaledBitmap(bit, width, height, true);
            return bitmap;
        }
    }

    /**
     *這是個儲存Bitmap到sd卡中的方法,可以返回儲存圖片的路徑
     * 儲存Bitmap到sd
     *
     * @param mBitmap
     * @param bitName 圖片儲存的名稱,返回儲存圖片的路徑
     */
    public static String saveBitmap(Bitmap mBitmap, String bitName) {
        File f;
        //判斷是否有sd卡 有就儲存到sd卡,沒有就儲存到app快取目錄
        if (isStorage()) {
            File file = new File("/data/data/name");//儲存的路徑
            if (!file.exists()) {//判斷目錄是否存在
                file.mkdir();//不存在就建立目錄
            }
            f = new File(file, bitName + ".jpg");
        } else {
            File file = new File(AppContext.getContext().getCacheDir().toString());
            if (!file.exists()) {//判斷目錄是否存在
                file.mkdir();
            }
            f = new File(file, bitName + ".jpg");
        }
        FileOutputStream fOut = null;
        try {
            fOut = new FileOutputStream(f);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        if (fOut != null) {
            mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
            try {
                fOut.flush();
                fOut.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return f.toString();
    }
    /**
     * 判斷是否有sd卡
     *
     * @return
     */
    public static boolean isStorage() {
        boolean isstorage = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
        return isstorage;
    }

    /**
     *把Bimtmap轉成Base64,用於上傳圖片到伺服器,一般是先壓縮然後轉成Base64,在上傳
     *
     *
     */
    public static String getBitmapStrBase64(Bitmap bitmap) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
        byte[] bytes = baos.toByteArray();
        return Base64.encodeToString(bytes, Base64.NO_WRAP);
    }

    public static String bitmapToBase64(Bitmap bitmap) {

        String result = null;
        ByteArrayOutputStream baos = null;
        try {
            if (bitmap != null) {
                baos = new ByteArrayOutputStream();
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
                baos.flush();
                baos.close();
                byte[] bitmapBytes = baos.toByteArray();
                result = Base64.encodeToString(bitmapBytes, Base64.NO_WRAP);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (baos != null) {
                    baos.flush();
                    baos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    // 把Base64轉換成Bitmap
    public static Bitmap getBitmapFromBase64(String iconBase64) {
        byte[] bitmapArray = Base64.decode(iconBase64, Base64.DEFAULT);
        return BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.length);
    }
}