Android 圖片壓縮並保存的方法

參考:

    1.https://blog.csdn.net/pbm863521/article/details/74391787

    2.https://www.jianshu.com/p/871f0c1f0006

1.背景:

    最近一個項目的開發,需要用到相機拍照,裁剪(使用的是ucrop,推薦使用),保存,上傳圖片到七牛雲的操作,並在上傳的過程中遇到了圖片過大,服務器返回溢出的錯誤,難搞哦。在其中發現,如果調用系統的相機,拍出來的圖片會有5M的大小,但是調用美圖相機的應用,拍照大小隻有500k不到,但是用戶的手機不可能每個都裝美圖相機軟件,所以需要對圖片進行壓縮。

2.方法:

    網上大致的方法分爲三種,質量壓縮,按比例大小壓縮(尺寸壓縮),採樣率壓縮,常用到的有兩種,其中採樣率壓縮不太常用,故不作過多的闡述。主要說一下其他兩種。

2.1 質量壓縮

    保持像素的前提下改變圖片的位深及透明度(即:通過算法抹掉(同化)圖片中的一些某點附近 相近的像素)達到降低質量壓縮文件的目的。

2.2 尺寸壓縮

    通過減少單位尺寸的像素值,真正意義上的降低像素(通過縮放圖片像素來減少圖片佔用內存大小)

2.3 第三方開源庫

   近期看資料的時候看到的,魯班(luban),據說逆向微信圖片壓縮算法得來的,雖不能完全達到微信效果,但是也很可觀了,github上Star已經11K+了,我還沒試過,小夥伴可以嘗試:https://github.com/Curzibn/Luban

3.代碼 (親測可用)

3.1 指定圖片大小,使用縮放,質量壓縮的方式將圖片壓縮到 100 k以內

/**
     * 圖片按比例大小壓縮方法
     *
     * @param srcPath (根據路徑獲取圖片並壓縮)
     * @return
     */
    public static Bitmap getimage(String srcPath) {

        BitmapFactory.Options newOpts = new BitmapFactory.Options();
        // 開始讀入圖片,此時把options.inJustDecodeBounds 設回true了
        newOpts.inJustDecodeBounds = true;
        Bitmap bitmap = BitmapFactory.decodeFile(srcPath, newOpts);// 此時返回bm爲空
        newOpts.inJustDecodeBounds = false;
        int w = newOpts.outWidth;
        int h = newOpts.outHeight;
        float hh = 1920f;// 這裏設置高度爲1920f
        float ww = 1080f;// 這裏設置寬度爲1080f
        // 縮放比。由於是固定比例縮放,只用高或者寬其中一個數據進行計算即可
        int be = 1;// be=1表示不縮放
        if (w > h && w > ww) {// 如果寬度大的話根據寬度固定大小縮放
            be = (int) (newOpts.outWidth / ww);
        } else if (w < h && h > hh) {// 如果高度高的話根據寬度固定大小縮放
            be = (int) (newOpts.outHeight / hh);
        }
        if (be <= 0)
            be = 1;
        newOpts.inSampleSize = be;// 設置縮放比例
        // 重新讀入圖片,注意此時已經把options.inJustDecodeBounds 設回false了
        bitmap = BitmapFactory.decodeFile(srcPath, newOpts);
        return compressImage(bitmap);// 壓縮好比例大小後再進行質量壓縮
    }

    /**
     * 質量壓縮方法
     *
     * @param image
     * @return
     */
    public static Bitmap compressImage(Bitmap image) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);// 質量壓縮方法,這裏100表示不壓縮,把壓縮後的數據存放到baos中
        int options = 90;
        while (baos.toByteArray().length / 1024 > 100) { // 循環判斷如果壓縮後圖片是否大於100kb,大於繼續壓縮
            baos.reset(); // 重置baos即清空baos
            image.compress(Bitmap.CompressFormat.JPEG, options, baos);// 這裏壓縮options%,把壓縮後的數據存放到baos中
            options -= 10;// 每次都減少10
        }
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把壓縮後的數據baos存放到ByteArrayInputStream中
        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);// 把ByteArrayInputStream數據生成圖片
        return bitmap;
    }

3.2 將Bitmap保存到本地手機路徑

    /**
     * 保存Bitmap到指定文件
     * @param bitmap 需要保存的圖片
     * @param file 保存的文件路徑
     */
    public static void saveBitmap(Bitmap bitmap, File file) {

        try {
            FileOutputStream fos = new FileOutputStream(file);
            // 這兩保存的時候我選擇了70的質量
            bitmap.compress(Bitmap.CompressFormat.JPEG, 70, fos);
            fos.flush();
            fos.close();
        } catch (Exception e) {
            PLog.e("saveBitmap err11 = ", e);
        }
    }

 

4.總結

   開發一個項目的過程中,會遇到很多困難,中間會遇到各種各樣的問題,會百度各種各種的問題,也會test各種方法,有用或沒用,可以在旁邊新建一個記事本,將用到的,可用的,方法記錄下來,包括參考的博客地址,記錄可以雜亂一點,但不影響。這樣在項目結束之後,有了充足的時間,然後再去一點點整理,由淺及深,慢慢的去看這些博客,梳理成自己的知識。這樣在下次遇到這些問題的時候,就會有一種我遇到過,我知道怎麼解決,對於預言項目週期,以及自身成長都有不錯的效果。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章