android之圖片(bitmap)總結 持續學習中......

寫在前頭

android開發工作中,對圖片的處理其實讓人挺頭疼,對於bitamp也一直在學習中。現在這裏記錄一下,方便自己以後學習。

知識點:
1. 圖片壓縮
2. 圖片佔用內存大小及加載解析

對於圖片的壓縮(看了你可能覺得你有些地方一直存在誤區哦)

android圖片壓縮之質量壓縮。

之前一直以爲圖片的質量壓縮可以減少oom的產生,其實不然,他只是在保證圖片質量的同時減少了文件的大小,他其實不會改變佔用的內存。質量壓縮是在保持像素的前提下改變圖片的位深及透明度等,來達到壓縮圖片的目的,經過它壓縮的圖片文件大小會有改變,但是導入成bitmap後佔得內存是不變的。因爲要保持像素不變,所以它就無法無限壓縮,到達一個值之後就不會繼續變小了。顯然這個方法並不適用與縮略圖,其實也不適用於想通過壓縮圖片減少內存的使用,僅僅適用於想在保證圖片質量的同時減少文件大小的情況而已

質量壓縮:

    //參數一 bitmap圖片  參數2 你想要壓縮後圖片的最大值
    public Bitmap compressImage(Bitmap image,int imageSize) {  

        ByteArrayOutputStream baos = new ByteArrayOutputStream();  
        //質量壓縮方法,這裏100表示壓縮質量,100表示不壓縮,把壓縮後的數據存放到baos中  
        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        int options = 100;  
        //循環判斷壓縮後圖片是否大於你設置的最大值,大於則繼續壓縮         
        while ( baos.toByteArray().length / 1024>imageSize) {  
        //重置baos即清空baos 
            baos.reset(); 
            //每次都減少5 
            options -= 5;
            //這裏壓縮options%,把壓縮後的數據存放到baos中  
            image.compress(Bitmap.CompressFormat.JPEG, options, baos);

        }  
        //把壓縮後的數據baos存放到ByteArrayInputStream中  
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
        //把ByteArrayInputStream數據生成圖片  
        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);
        return bitmap;  
    } 

android圖片壓縮之大小壓縮。

尺寸壓縮是壓縮圖片的像素,一張圖片所佔內存的大小 圖片類型*寬*高,通過改變三個值減小圖片所佔的內存,防止OOM(這纔是防止oom的重要過程),當然這種方式可能會使圖片失真

public Bitmap getSmallIcon(String filePath,int yourWidth,int yourHeight) {
        BitmapFactory.Options opt= new BitmapFactory.Options();
        //禁止爲bitmap分配內存
        opt.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filePath, opt);
        opt.inSampleSize = calculateInSampleSize(opt, yourWidth,yourHeight);
        //允許爲bitmap分配內存,得到壓縮的bitmap圖片
        opt.inJustDecodeBounds = false;
        Bitmap bitmap = BitmapFactory.decodeFile(filePath, opt);
        return bitmap ;
    }

public static int calculateInSampleSize(BitmapFactory.Options options,int yourWidth, int yourHeight) {
    //獲取圖片的長度,寬度和MIME屬性
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;
        if (height > yourHeight|| width > yourWidth) {
        // 計算出實際寬高和目標寬高的比率  
            final int heightRatio = Math.round((float) height / (float) yourHeight);
            final int widthRatio = Math.round((float) width / (float) yourWidth);
            // 選擇寬和高中最小的比率作爲inSampleSize的值,這樣可以保證最終圖片的寬和高  
            // 一定都會大於等於目標的寬和高。  
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
        }
        return inSampleSize;
    }

圖片佔用內存大小及加載解析

自問:

  1. 手機進行屏幕適時,常想可不可以只切一套圖適配所有的手機呢?
  2. 一張圖片加載到手機中,佔用內存到底有多少?
  3. 圖片佔用內存跟哪些東西有關?跟手機有關係麼?同一張圖片放在不同的dpi文件夾下內存佔用會變化麼?
  4. 如果是網絡圖片,加載到手機中,佔用內存跟手機屏幕有關係麼?

大神已經分析過了,如果你想看過程,請移步:
http://blog.csdn.net/smileiam/article/details/68946182
結論的話,看下面就夠了!
結論:

1.在對手機進行屏幕適時,可以只切一套圖適配所有的手機。

    但是如果只切一套小圖,那在高屏幕密度手機上,會對圖片進行放大,這樣圖片佔用的內存往往比切相應圖片放在高密度文件夾下,佔用的內存還要大。

    那如果只切一套大圖放在高幕文件夾下,在小屏幕密度手機上,會縮小顯示,按道理是行得通的。但系統在對圖片進行縮放時,會進行大量計算,會對手機的性能有一定的影響。同時如果圖片縮放比較狠,可能導致圖片出現抖動或是毛邊。
    所以最好切出不同比便的圖片放在不同幕度的文件夾下,對於性能要求不大高的圖片,可以只切一套大圖;

2.一張圖片佔用內存=圖片長 * 圖片寬 / (資源圖片文件密度/手機屏幕密度)^2 * 每一象素佔用字節數,所以圖片佔用內存跟圖片本身大小、手機屏幕密度、圖片所在的文件夾密度,圖片編碼的色彩格式有關;

3.對於網絡圖片,在不同屏幕密度的手機上加載出來,佔用內存是一樣的。

4.對於網絡或是assets/手機本地圖片加載,如果想通過設置Options裏的
inDensity或是inTargetDensity參數來調整圖片的縮放比,必須兩個參數均設置才能起作用,只設置一個,不會起作用。

5.drawable和mipmap文件夾存放圖片的區別,首先圖片放在drawable-xhdpi和mipmap-xhdpi下,兩者佔用的內存是一樣的,
Mipmaps早在Android2.2+就可以用了,但是直到4.3 google才強烈建議使用。把圖片放到mipmaps可以提高系統渲染圖片的速度,提高圖片質量,減少GPU壓力。其他並沒有什麼區別。

寫在後面

學習中也用過一些類似luban的第三方壓縮框架,發現總會有一些問題,比如壓縮多張圖片anr等等,自己寫的纔是靠譜的嘿嘿。
如果你有好的想法,請告知。謝謝分享。

發佈了39 篇原創文章 · 獲贊 33 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章