Android處理大圖片

來源:互聯網
上載者:User

項目中經常碰到需要處理大圖片的問題,因為android對應用程式指派資源的限制,如果不進行相應的處理,容易造成OOM。

Android處理大圖的方法:

對於大圖先擷取出圖片的width和height, 然後根據view的width和height, 換算出圖片inSampleSize,,最後壓縮產生相應的圖片。

其中重要的兩個參數是:

/**111         * If set to true, the decoder will return null (no bitmap), but112         * the out... fields will still be set, allowing the caller to query113         * the bitmap without having to allocate the memory for its pixels.114         */115        public boolean inJustDecodeBounds;116117        /**118         * If set to a value > 1, requests the decoder to subsample the original119         * image, returning a smaller image to save memory. The sample size is120         * the number of pixels in either dimension that correspond to a single121         * pixel in the decoded bitmap. For example, inSampleSize == 4 returns122         * an image that is 1/4 the width/height of the original, and 1/16 the123         * number of pixels. Any value <= 1 is treated the same as 1. Note: the124         * decoder uses a final value based on powers of 2, any other value will125         * be rounded down to the nearest power of 2.126         */127        public int inSampleSize;

InJustDecodeBounds能在不分配資源給圖片的情況下擷取圖片的大小


inSampleSize計算圖片的壓縮比


開源項目xutils, Universal-Image-Loader和Foursquare對於大圖的處理都類似的


下面是Foursquare處理大圖的代碼:

public class ImageUtils {        private ImageUtils() {    }    public static void resampleImageAndSaveToNewLocation(String pathInput, String pathOutput)         throws Exception     {        Bitmap bmp = resampleImage(pathInput, 640);                OutputStream out = new FileOutputStream(pathOutput);        bmp.compress(Bitmap.CompressFormat.JPEG, 90, out);     }        public static Bitmap resampleImage(String path, int maxDim)         throws Exception {                BitmapFactory.Options bfo = new BitmapFactory.Options();         bfo.inJustDecodeBounds = true;         BitmapFactory.decodeFile(path, bfo);             BitmapFactory.Options optsDownSample = new BitmapFactory.Options();        optsDownSample.inSampleSize = getClosestResampleSize(bfo.outWidth, bfo.outHeight, maxDim);            Bitmap bmpt = BitmapFactory.decodeFile(path, optsDownSample);            Matrix m = new Matrix();                 if (bmpt.getWidth() > maxDim || bmpt.getHeight() > maxDim) {            BitmapFactory.Options optsScale = getResampling(bmpt.getWidth(), bmpt.getHeight(), maxDim);            m.postScale((float)optsScale.outWidth  / (float)bmpt.getWidth(),                         (float)optsScale.outHeight / (float)bmpt.getHeight());         }                 int sdk = new Integer(Build.VERSION.SDK).intValue();         if (sdk > 4) {            int rotation = ExifUtils.getExifRotation(path);            if (rotation != 0) {                 m.postRotate(rotation);             }        }                return Bitmap.createBitmap(bmpt, 0, 0, bmpt.getWidth(), bmpt.getHeight(), m, true);     }        private static BitmapFactory.Options getResampling(int cx, int cy, int max) {        float scaleVal = 1.0f;        BitmapFactory.Options bfo = new BitmapFactory.Options();        if (cx > cy) {            scaleVal = (float)max / (float)cx;        }        else if (cy > cx) {            scaleVal = (float)max / (float)cy;        }        else {            scaleVal = (float)max / (float)cx;        }        bfo.outWidth  = (int)(cx * scaleVal + 0.5f);        bfo.outHeight = (int)(cy * scaleVal + 0.5f);        return bfo;    }        private static int getClosestResampleSize(int cx, int cy, int maxDim) {        int max = Math.max(cx, cy);                int resample = 1;        for (resample = 1; resample < Integer.MAX_VALUE; resample++) {            if (resample * maxDim > max) {                resample--;                break;            }        }                if (resample > 0) {            return resample;        }        return 1;    }        public static BitmapFactory.Options getBitmapDims(String path) throws Exception {        BitmapFactory.Options bfo = new BitmapFactory.Options();         bfo.inJustDecodeBounds = true;         BitmapFactory.decodeFile(path, bfo);         return bfo;    }}

還有一個問題需要糾正:
看了幾篇關於處理大圖的文章都說不要調用BitmapFactory.decodeResource這個函數,因為這個函數在完成decode後,最終都是通過java層的createBitmap來完成的,需要消耗更多記憶體。
我看了BitmapFactory的源碼發現上面那個分析是錯誤的,decodeResource最終也是調用Jni去擷取圖片。請看下面時序圖。


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.