Android加載大圖片OOM撬呢、圖片壓縮

  • 圖像:一個(gè)一個(gè)像素點(diǎn)構(gòu)成滥朱。所有不同的顏色像素點(diǎn)構(gòu)成一幅完整圖像。
  • 位圖表示圖像的方法:記錄一幅圖像中所有像素點(diǎn)(pixels)信息
  • 圖像(位圖)的深度:表示一個(gè)像素點(diǎn)用多少個(gè)bit位
    • 單色位圖:用1bit描述一個(gè)像素點(diǎn)信息毒涧。
    • 256色位圖:用8bits描述一個(gè)像素點(diǎn)信息
    • 24位位圖:用24bits描述一個(gè)像素點(diǎn)信息
view.getWidth獲取的是像素px

加載大圖片產(chǎn)生OOM問(wèn)題

在使用BitmapFactory的decodeStream,decodeFile,decodeResource方法時(shí)贮预,超出系統(tǒng)分配的內(nèi)存大小(一般是8M)契讲,報(bào)出OOM仿吞。

  • 解決方法,設(shè)置采樣率inSampleSize捡偏,用于減少要加載像素個(gè)數(shù)

      //加載sd卡上jpg圖片顯示在imageView
      
      //Bitmap bm = BitmapFactory.decodeFile("/sdcard/biger.jpg");
      //加載大圖片唤冈,產(chǎn)生OOM問(wèn)題,解決辦法:想方設(shè)法減少像素個(gè)數(shù)
      
      Options opts = new Options();
      opts.inSampleSize = 8;//設(shè)置采樣率霹琼,成倍數(shù)減少像素點(diǎn)务傲。inSamleSize = 8 總像素點(diǎn)是原圖像的1/64
      Bitmap bm = BitmapFactory.decodeFile("/sdcard/biger.jpg", opts);
      
      //Bitmap.Config.ARGB_8888 描述一個(gè)像素用32bits,Alpha R G B
      
      iv.setImageBitmap(bm);
    
  • 采樣率一般設(shè)置方法:分別獲得屏幕的分辨率(寬方向像素個(gè)數(shù) X 高方向像素個(gè)數(shù))和圖片分辨率(寬方向像素個(gè)數(shù) X 高方向像素個(gè)數(shù))枣申。用圖片的寬方向上像素個(gè)數(shù)除以屏幕的寬方向上像素個(gè)數(shù),用圖片的高方向上像素個(gè)數(shù)除以屏幕的高方向上像素個(gè)數(shù)看杭。取兩個(gè)比值中最大值或均值作為采樣率忠藤。

  • 采樣率設(shè)置之后的寬高應(yīng)該大于ImageView期望的寬高,否則會(huì)被拉伸而變模糊

  • 屏幕分辨率

      //獲得屏幕分辨率
      //1.獲得窗口管理器
      WindowManager manager = (WindowManager) getSystemService(WINDOW_SERVICE);
      
      //2.獲得默認(rèn)顯示對(duì)象
      Display display = manager.getDefaultDisplay();
      
      //在api13之下使用
      //int windowWidth = display.getWidth();
      //int windowHeight = display.getHeight();
      
      //在api13以上使用
      Point outSize = new Point();
      display.getSize(outSize);//先傳入對(duì)象楼雹,方法中將數(shù)據(jù)再填入對(duì)象中
      
      int windowWidth = outSize.x;
      int windowHeight = outSize.y;
      
      System.out.println(windowWidth + " * " + windowHeight);
    
  • 獲得jpg圖片的分辨率

      int sampleWidth = 0;
      int samleHeight = 0;
      //獲得jpg圖片分辨率
      try {
          //獲得Exif接口對(duì)象
          ExifInterface exif = new ExifInterface("/sdcard/biger.jpg");
          
          //獲得圖片的寬方向像素個(gè)數(shù)
          int width = exif.getAttributeInt(ExifInterface.TAG_IMAGE_WIDTH, -1);
          //獲得圖片的高方向像素個(gè)數(shù)
          int height = exif.getAttributeInt(ExifInterface.TAG_IMAGE_LENGTH, -1);
          
          System.out.println(width + " X " + height);
          
          sampleWidth = width / windowWidth;
          samleHeight = height / windowHeight;
          
      } catch (Exception e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
      }
    
  • 其它類(lèi)型圖片png,bmp獲得分辨率(也可以獲取JPG的)

  •   /*
      //其它類(lèi)型圖片png,bmp獲得分辨率方法
      Options opt = new Options();
      opt.inJustDecodeBounds = true;//僅獲得圖片的分辨率模孩,寬和高尖阔。并不會(huì)將文件轉(zhuǎn)成bitmap對(duì)象
      
      BitmapFactory.decodeFile("/sdcard/biger.png", opt );
      
      int width = opt.outWidth;
      int height = opt.outHeight;
      */
    
  • 計(jì)算采樣率

      opts.inSampleSize = sampleWidth > samleHeight ? sampleWidth : samleHeight;
    
  • 采樣率設(shè)置應(yīng)遵循如下原則
    1、BitmapFactory.Options的inJustDecodeBounds 設(shè)置為true榨咐,并加載圖片
    2介却、從BitmapFactory.Options中獲取圖片的原始寬高,outHeight块茁、outWidth
    3齿坷、計(jì)算采樣率inSampleSize
    4、BitmapFactory.Options的inJustDecodeBounds 設(shè)置為false数焊,然后重新加載圖片

寫(xiě)個(gè)demo測(cè)試一下:
傳送門(mén):https://github.com/jiaweizeng/LoadPhotoOOM

package cn.hzjk.loadphotooom;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

public class MainActivity extends AppCompatActivity {

    private Bitmap mBitmap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final ImageView iv = findViewById(R.id.iv_load);
        Button btn = findViewById(R.id.btn_load);


        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                /*mBitmap = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().
                        getPath() + "/IMG_2509.JPG");*/
                mBitmap = getMySampleBitmap(Environment.getExternalStorageDirectory().
                        getPath() + "/IMG_2509.JPG",iv.getWidth(),iv.getHeight());
                iv.setImageBitmap(mBitmap);

            }
        });
}
    /**   設(shè)置采樣率永淌,防止圖片太大,解析OOM
     *
     * @param file_path 圖片路徑
     * @return
     */
    public  Bitmap getMySampleBitmap(String file_path, int width, int height) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(file_path, options);
        options.inSampleSize = getMySampleSize(width, height, options);
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeFile(file_path, options);
    }
    private  int getMySampleSize(int reqWidth, int reqHeight, BitmapFactory.Options options) {
        int inSampleSize = 1;
        if (options.outWidth > reqWidth || options.outHeight > reqHeight) {
            int widthRatio = Math.round((float) options.outWidth / (float) reqWidth);
            int heightRatio = Math.round((float) options.outHeight / (float) reqHeight);
            inSampleSize = Math.min(widthRatio, heightRatio);
        }
        return inSampleSize;
    }
}

測(cè)試圖片大小8M

設(shè)置采樣率之前的內(nèi)存變化:


設(shè)置采樣率之后的內(nèi)存變化:


壓縮bitmap

private Bitmap imageZoom(Bitmap bitMap) {
    //圖片允許最大空間   單位:KB
    double maxSize =1000.00;
    //將bitmap放至數(shù)組中佩耳,意在bitmap的大兴熘(與實(shí)際讀取的原文件要大)
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    bitMap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
    byte[] b = baos.toByteArray();
    //將字節(jié)換成KB
    double mid = b.length/1024;
    //判斷bitmap占用空間是否大于允許最大空間  如果大于則壓縮 小于則不壓縮
    if (mid > maxSize) {
        //獲取bitmap大小 是允許最大大小的多少倍
        double i = mid / maxSize;
        //開(kāi)始?jí)嚎s  此處用到平方根 將寬帶和高度壓縮掉對(duì)應(yīng)的平方根倍 (1.保持刻度和高度和原bitmap比率一致,壓縮后也達(dá)到了最大大小占用空間的大懈珊瘛)
        bitMap = zoomImage(bitMap, bitMap.getWidth() / Math.sqrt(i),
                bitMap.getHeight() / Math.sqrt(i));
    }
    return bitMap;
}

/***
 * 圖片的縮放方法
 *
 * @param bgimage
 *            :源圖片資源
 * @param newWidth
 *            :縮放后寬度
 * @param newHeight
 *            :縮放后高度
 * @return
 */
public static Bitmap zoomImage(Bitmap bgimage, double newWidth,
                               double newHeight) {
    // 獲取這個(gè)圖片的寬和高
    float width = bgimage.getWidth();
    float height = bgimage.getHeight();
    // 創(chuàng)建操作圖片用的matrix對(duì)象
    Matrix matrix = new Matrix();
    // 計(jì)算寬高縮放率
    float scaleWidth = ((float) newWidth) / width;
    float scaleHeight = ((float) newHeight) / height;
    // 縮放圖片動(dòng)作
    matrix.postScale(scaleWidth, scaleHeight);
    Bitmap bitmap = Bitmap.createBitmap(bgimage, 0, 0, (int) width,
            (int) height, matrix, true);
    return bitmap;
}

/壓縮圖片框架/ compile 'top.zibin:Luban:1.1.1' compile 'id.zelory:compressor:2.0.0'

壓縮網(wǎng)站:https://tinypng.com/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末李滴,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蛮瞄,更是在濱河造成了極大的恐慌所坯,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件裕坊,死亡現(xiàn)場(chǎng)離奇詭異包竹,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)籍凝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)周瞎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人饵蒂,你說(shuō)我怎么就攤上這事声诸。” “怎么了退盯?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵彼乌,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我渊迁,道長(zhǎng)慰照,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任琉朽,我火速辦了婚禮毒租,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘箱叁。我一直安慰自己墅垮,他們只是感情好惕医,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著算色,像睡著了一般抬伺。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上灾梦,一...
    開(kāi)封第一講書(shū)人閱讀 51,125評(píng)論 1 297
  • 那天峡钓,我揣著相機(jī)與錄音,去河邊找鬼斥废。 笑死椒楣,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的牡肉。 我是一名探鬼主播捧灰,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼统锤!你這毒婦竟也來(lái)了毛俏?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤饲窿,失蹤者是張志新(化名)和其女友劉穎煌寇,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體逾雄,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡阀溶,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了鸦泳。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片银锻。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖做鹰,靈堂內(nèi)的尸體忽然破棺而出击纬,到底是詐尸還是另有隱情,我是刑警寧澤钾麸,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布更振,位于F島的核電站,受9級(jí)特大地震影響饭尝,放射性物質(zhì)發(fā)生泄漏肯腕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一钥平、第九天 我趴在偏房一處隱蔽的房頂上張望乎芳。 院中可真熱鬧,春花似錦帖池、人聲如沸奈惑。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)肴甸。三九已至,卻和暖如春囚巴,著一層夾襖步出監(jiān)牢的瞬間原在,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工彤叉, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留庶柿,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓秽浇,卻偏偏與公主長(zhǎng)得像浮庐,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子柬焕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • 前言 在一次偶然的情況下审残,在簡(jiǎn)書(shū)上看到 一句代碼搞定 Android 圖片壓縮 真的是打瞌睡碰到了枕頭啊~ 因?yàn)樽?..
    橙一升閱讀 2,355評(píng)論 1 12
  • 源碼:GitHub:https://github.com/Nergal1/Luban CSDN:http://do...
    Nergal1閱讀 2,510評(píng)論 0 0
  • 前言 圖片壓縮在Android技術(shù)中已經(jīng)屬于爛大街,上周看了2個(gè)開(kāi)源庫(kù)然后對(duì)自己項(xiàng)目的壓縮做了對(duì)比斑举,發(fā)現(xiàn)一些新東西...
    M悇芐冋憶閱讀 386評(píng)論 0 0
  • 前言 圖片壓縮在Android技術(shù)中已經(jīng)屬于爛大街搅轿,上周看了2個(gè)開(kāi)源庫(kù)然后對(duì)自己項(xiàng)目的壓縮做了對(duì)比,發(fā)現(xiàn)一些新東西...
    08_carmelo閱讀 34,918評(píng)論 13 58
  • “露從今夜白富玷,月是故鄉(xiāng)明”璧坟,又到中秋,一顆漂泊的心竟惶惶然無(wú)處安放赎懦,都說(shuō)每逢佳節(jié)倍思親雀鹃,可山高路遙歸夢(mèng)亦難...
    云飄碧天閱讀 2,850評(píng)論 19 173