顯示廣告
隱藏 ✕
看板 KnucklesNote
作者 Knuckles (站長 那克斯)
標題 [AndroidStudio] 將圖檔的寬高縮小 bitmap resize
時間 2016-09-13 Tue. 13:16:08


手機相機存的圖片解析度都很大
如果直接顯示出來會浪費記憶體
上傳到網路上會傳很久

所以必需先做縮圖的處理

參考 Android Developer 如何有效率的載入大圖檔
https://developer.android.com/training/displaying-bitmaps/load-bitmap.html
這個方法只能簡單的將圖片的寬高減半
    private Bitmap getScaledBitmap(String imagePath) {
        // 取得原始圖檔的大小
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true; //只抓長度和寬度
        BitmapFactory.decodeFile(imagePath, options);
        int width = options.outWidth;

        // 新圖的寬要小於等於這個值
        final int MAX_WIDTH = 1024;

        // 求出要縮小的 scale 值,必需是2的次方,ex: 1,2,4,8,16...
        int scale = 1;
        while(width > MAX_WIDTH){
            width /= 2;
            scale *= 2;
        }

        // 使用 scale 值產生縮小的圖檔
        BitmapFactory.Options scaledOptions = new BitmapFactory.Options();
        scaledOptions.inSampleSize = scale;
        return BitmapFactory.decodeFile(imagePath, scaledOptions);
    }

前面取得原始圖檔大小時,因為使用了 options.inJustDecodeBounds = true;
所以 BitmapFactory.decodeFile(imagePath, options)
只會將寬高存入 options,然後傳出出 null 值
可避免將原本太大的圖檔載入記憶體

但因為只是簡單的將像素減半,縮圖的品質不會很好

如果要縮小成指定的寬高值時,參考
http://stackoverflow.com/questions/4837715/how-to-resize-a-bitmap-in-android
改成
    private Bitmap getResizedBitmap(String imagePath) {
        // 取得原始圖檔的bitmap與寬高
        BitmapFactory.Options options = new BitmapFactory.Options();
        Bitmap bitmap = BitmapFactory.decodeFile(imagePath, options);
        int width = options.outWidth, height = options.outHeight;

        // 將圖檔等比例縮小至寬度為1024
        final int MAX_WIDTH = 1024;
        float resize = 1; // 縮小值 resize 可為任意小數
        if(width>MAX_WIDTH){
            resize = ((float) MAX_WIDTH) / width;
        }

        // 產生縮圖需要的參數 matrix
        Matrix matrix = new Matrix();
        matrix.postScale(resize, resize); // 設定寬高的縮放比例

        // 產生縮小後的圖
        Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
        return resizedBitmap;
    }

其中 Bitmap.createBitmap 的最後一個參數設為 true 時可產生品質比較好的縮圖
以下兩張縮圖分別為設為 false 與 true 時:
[圖]
 
[圖]



整合以上兩種方法,當圖檔非常大時 (寬度>MAX_WIDTH*2)
先用方法一產生不那麼大的檔 (寬度<=MAX_WIDTH*2)
再用方法二縮至指定的大小 (寬度<=MAX_WIDTH)
    private Bitmap getResizedBitmap(String imagePath) {
        final int MAX_WIDTH = 1024; // 新圖的寬要小於等於這個值

        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true; //只讀取寬度和高度
        BitmapFactory.decodeFile(imagePath, options);
        int width = options.outWidth, height = options.outHeight;

        // 求出要縮小的 scale 值,必需是2的次方,ex: 1,2,4,8,16...
        int scale = 1;
        while(width > MAX_WIDTH*2){
            width /= 2;
            height /= 2;
            scale *= 2;
        }

        // 使用 scale 值產生縮小的圖檔
        BitmapFactory.Options scaledOptions = new BitmapFactory.Options();
        scaledOptions.inSampleSize = scale;
        Bitmap scaledBitmap = BitmapFactory.decodeFile(imagePath, scaledOptions);

        float resize = 1; //縮小值 resize 可為任意小數
        if(width>MAX_WIDTH){
            resize = ((float) MAX_WIDTH) / width;
        }

        Matrix matrix = new Matrix(); // 產生縮圖需要的參數 matrix
        matrix.postScale(resize, resize); // 設定寬與高的縮放比例

        // 產生縮小後的圖
        return Bitmap.createBitmap(scaledBitmap, 0, 0, width, height, matrix, true);
    }




--
※ 作者: Knuckles 時間: 2016-09-13 13:16:08
※ 編輯: Knuckles 時間: 2016-09-14 09:26:24
※ 看板: KnucklesNote 文章推薦值: 0 目前人氣: 0 累積人氣: 1872 
分享網址: 複製 已複製
r)回覆 e)編輯 d)刪除 M)收藏 ^x)轉錄 同主題: =)首篇 [)上篇 ])下篇