Android Bitmap的常用壓縮方式

SeanMa發表於2018-01-11

一、前言

已經好久沒有更新部落格,大概有半年了,主要是博主這段時間忙於找工作,Android崗位的工作真的是越來越難找,好不容易在廣州找到一家,主要做海外產品,公司研發實力也不錯,所以就敲定了三方協議。現在已經在公司實習了一個月多,目前主要是負責公司某個產品的記憶體優化,剛好就總結了一下Android Bitmap常用的優化方式。

Android中的圖片是以Bitmap方式存在的,繪製的時候也是Bitmap,直接影響到app執行時的記憶體,在Android,Bitmap所佔用的記憶體計算公式是:圖片長度 x 圖片寬度 x畫素點的位元組數

二、圖片常用的壓縮格式

Enum Values
ALPHA_8 每個畫素都儲存為一個半透明(alpha)通道
ARGB_4444 此欄位已在API級別13中棄用。由於此配置的質量較差,建議使用ARGB_8888
ARGB_8888 每個畫素儲存在4個位元組。
RGB_565 每個畫素儲存在2個位元組中,只有RGB通道被編碼:紅色以5位精度儲存(32個可能值),綠色以6位精度儲存(64個可能值),藍色儲存為5位精確。

其中字母代表的意思我們大概都可以理解,接下來我們來算算它們單個畫素點的位元組數:

  • ALPHA_8:表示8位Alpha點陣圖,即透明度佔8個位,一個畫素點佔用1個位元組,它沒有顏色,只有透明度。
  • ARGB_4444:表示16位ARGB點陣圖,即A=4,R=4,G=4,B=4,一個畫素點佔4+4+4+4=16位,2個位元組。
  • ARGB_8888:表示32位ARGB點陣圖,即A=8,R=8,G=8,B=8,一個畫素點佔8+8+8+8=32位,4個位元組。
  • RGB_565 :表示16位RGB點陣圖,即R=5,G=6,B=5,它沒有透明度,一個畫素點佔5+6+5=16位,2個位元組

我們在做壓縮處理的時候,可以先通過改變Bitmap的圖片格式,來達到壓縮的效果,其實壓縮最主要就是要麼改變其寬高,要麼就通過減少其單個畫素佔用的記憶體。

三、常用的壓縮方法:

1.質量壓縮

    private void compressQuality() {
        Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.test);
        mSrcSize = bm.getByteCount() + "byte";
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        bm.compress(Bitmap.CompressFormat.JPEG, 100, bos);
        byte[] bytes = bos.toByteArray();
        mSrcBitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
    }
複製程式碼

質量壓縮不會減少圖片的畫素,它是在保持畫素的前提下改變圖片的位深及透明度,來達到壓縮圖片的目的,圖片的長,寬,畫素都不會改變,那麼bitmap所佔記憶體大小是不會變的。

我們可以看到有個引數:quality,可以調節你壓縮的比例,但是還要注意一點就是,質量壓縮堆png格式這種圖片沒有作用,因為png是無失真壓縮。

2.取樣率壓縮

    private void compressSampling() {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = 2;
        mSrcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test, options);
    }
複製程式碼

取樣率壓縮其原理其實也是縮放bitamp的尺寸,通過調節其inSampleSize引數,比如調節為2,寬高會為原來的1/2,記憶體變回原來的1/4.

3.放縮法壓縮

    private void compressMatrix() {
        Matrix matrix = new Matrix();
        matrix.setScale(0.5f, 0.5f);
        Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.test);
        mSrcBitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
        bm = null;
    }
複製程式碼

放縮法壓縮使用的是通過矩陣對圖片進行裁剪,也是通過縮放圖片尺寸,來達到壓縮圖片的效果,和取樣率的原理一樣。

4.RGB_565壓縮

    private void compressRGB565() {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inPreferredConfig = Bitmap.Config.RGB_565;
        mSrcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test, options);
    }
複製程式碼

這是通過壓縮畫素佔用的記憶體來達到壓縮的效果,一般不建議使用ARGB_4444,因為畫質實在是辣雞,如果對透明度沒有要求,建議可以改成RGB_565,相比ARGB_8888將節省一半的記憶體開銷。

5.createScaledBitmap

    private void compressScaleBitmap() {
        Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.test);
        mSrcBitmap = Bitmap.createScaledBitmap(bm, 600, 900, true);
        bm = null;
    }
複製程式碼

將圖片的大小壓縮成使用者的期望大小,來減少佔用記憶體。

四、效果圖

show.gif

五、總結

以上5種就是我們常用的壓縮方法了,這裡的壓縮也只是針對在執行載入的bitmap佔用記憶體的大小。我們在做App記憶體優化的時候,一般可以從這兩個方面入手,一個記憶體洩漏,另外一個是Bitmap壓縮了,在要求畫素不高的情況下,可以對Bitmap進行壓縮,並且針對一些只使用一次的bitmap,要做好recycle的處理。

部落格就寫到這裡,以下是原始碼地址。 ·

相關文章