通過BitmapFactory.Options解決activity之間傳遞圖片出現內存溢出(OOM)問題


在activity之間通過intent或者bundle傳遞較大圖片時,很容易出現OOM問題。通過調試以及查閱資料,知道大概是因為intent和bundle不能傳遞大量數據導致了這個問題。因此解決這個問題的其中一個思路就是通過BitmapFactory.Options將原圖縮小,減小傳遞的數據量大小。
 
1.采樣率inSampleSize(即圖片縮小比例值)
實際上就是通過BitmapFactory.Options獲得一個采樣率inSampleSize,使原始圖片按照inSampleSize的大小進行比例縮小。inSampleSize一般是2的次方值。例如inSampleSize=2時,原始圖片的width和height都縮小為原來的1/2;inSampleSize=4時,原始圖片的width和height都縮小為原來的1/4。需注意的是:
1).當inSampleSize<1時,默認inSampleSize=1;
2).當inSampleSize>1同時inSampleSize不等於2的次方值時,默認向下取整,inSampleSize取值為與其最相近的2的次方值,例如inSampleSize=3時,默認inSampleSize=2;
 
2.BitmapFactory加載圖片的方式
1).BitmapFactory.decodeFile(String pathName, BitmapFactory.Options opts)從文件中加載一個Bitmap
2).BitmapFactory.decodeResource(Resources res, int id, BitmapFactory.Options opts)從圖片資源中加載一個Bitmap
3).BitmapFactory.decodeByteArray(byte[] data, int offset, int length, BitmapFactory.Options opts)從字節數組中加載一個Bitmap
4).BitmapFactory.decodeStream(InputStream is, Rect outPadding, BitmapFactory.Options opts)從輸入流中加載一個Bitmap
同時以上幾種方法也都支持BitmapFactory.Options參數。
 
3.如何通過BitmapFactory.Options
1).BitmapFactory加載原圖,通過BitmapFactory.Options的outWidth和outHeight分別獲得原圖的width和height。
2).個人認為圖片大小超過1M就會出現OOM問題,故通過計算圖片大小並判斷其是否超過1M來不斷縮小圖片dewidth和height,最終獲得采樣率inSampleSize。
3).BitmapFactory重新加載圖片,獲得按inSampleSize縮小后的圖片。
BitmapFactory.Options的inJustDecodeBounds為true的時候,BitmapFactory.decodeByteArray返回null;為false的時候,BitmapFactory.decodeByteArray返回加載的Bitmap。BitmapFactory.decodeFile以及BitmapFactory.decodeByteArray都是一樣的。
 
以下是自己封裝的一個類BitmapOption,傳入參數是原始的Bitmap,返回的是縮小圖片的字節數組格式的數據。經實驗,以下代碼可行。傳入原始圖片大小為1080*1920(24位),縮小后,傳遞到下一個activity,沒出現OOM問題。

 1 public class BitmapOption {
 2     public BitmapOption(){}
 3     public static byte[] getSmallerBitmapBytes(Bitmap bitmap){
 4         ByteArrayOutputStream ops=new ByteArrayOutputStream();
 5         //將壓縮的bitmap寫入字節數組輸出流ops,第二個參數設置為100的話就是沒壓縮
 6         bitmap.compress(Bitmap.CompressFormat.JPEG,100,ops);
 7         byte[] bytes=ops.toByteArray();
 8         //通過BitmapFactory.Options來縮小圖片,一定程度的避免了傳遞圖片數據出現內存溢出
 9         BitmapFactory.Options options = new BitmapFactory.Options();
10         //inJustDecodeBounds設置為true,BitmapFactory.decodeByteArray不返回bitmap
11         options.inJustDecodeBounds = true;
12         //BitmapFactory.decodeByteArray加載原圖
13         BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
14         /*
15         * 獲取采樣率inSampleSize
16         *inSampleSize大於1時,圖片高、寬分別以2的inSampleSize次方分之一縮小
17         *inSampleSize小於等於1時,圖片高、寬不變
18         * */
19         options.inSampleSize = getinSampleSize(options);
20         if (options.inSampleSize==1)return bytes;
21 
22         //inJustDecodeBounds設置為false,BitmapFactory.decodeByteArray返回bitmap
23         options.inJustDecodeBounds = false;
24         //BitmapFactory.decodeByteArray重新加載圖片:通過option得到縮小的bitmap,並將縮小的bitmap字節序列化后返回
25         Bitmap smallerBitmap = BitmapFactory.decodeByteArray(bytes,0,bytes.length,options);
26         ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
27         smallerBitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
28         byte[] smallerbytes = byteArrayOutputStream.toByteArray();
29         return smallerbytes;
30     }
31 
32     //獲取option采樣率inSampleSize
33     private static int getinSampleSize(BitmapFactory.Options options) {
34         int inSampleSize = 1;
35         int imageWidth = options.outWidth;//取出bitmap的原始高寬
36         int imageHeight = options.outHeight;
37         //個人認為intent,bundle傳遞圖片的時候,當圖片內存大於1024KB的時候,會發生內存溢出,
38         // 所以為解決內存溢出問題,此處選擇通過計算圖片大小來查找縮放比例系數小於1024KB時,找到inSampleSize
39         while (getImageMemory(imageWidth, imageHeight, inSampleSize) > 1024) {
40             inSampleSize *= 2;
41         }
42         return inSampleSize;
43     }
44 
45     //24位位圖內存大小計算
46     private static int getImageMemory(int imagewidth, int imageheight, int inSampleSize) {
47         return (imagewidth / inSampleSize) * (imageheight / inSampleSize) * 3 / 1024;
48     }
49 }

 


免責聲明!

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



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