android bitmap壓縮方案

weixin_34321977發表於2018-08-04

這篇文章來將android中的bitmap壓縮的幾種方案。

Bitmap的佔用記憶體 = 圖片長度 X 圖片寬度 X 一個畫素點佔用的位元組數。
常見的Bitmap的壓縮格式:ALPHA_8 ARGB_4444 ARGB_8888 RGB_565。(A代表透明度,R代表紅色,G代表綠色,B代表藍色)

  • ALPHA_8:是8位的點陣圖,一個畫素佔用一個位元組,是單個透明通道,只有A值,不儲存顏色資訊。
  • ARGB_4444:是16位的點陣圖,一個畫素佔用2個位元組,A=4,R=4,G=4,B=4.
  • ARGB_8888:是32位的點陣圖,一個畫素佔用4個位元組,A=8,R=8,G=8,B=8
  • RGB_565:是16位的點陣圖,一個畫素佔2個位元組,沒有透明度,R=5,G=6,B=5

1.質量壓縮

質量壓縮只能改變圖片的位深以及透明度,不能改變圖片的寬高和畫素,bitmap所佔的記憶體大小並不會改變,但是位元組數隨著質量的變小而變小了。所以質量壓縮適合去傳遞二進位制的圖片資料。注意質量壓縮只針對與jpeg格式的圖片,png的圖片是無損的。

  /**
     * 質量壓縮
     * png圖片是無損的,不能進行質量壓縮
     */
    public static Bitmap compressQuality(Context context, int resId, int quality) {
         /*原bitmap與壓縮後的bitmap的宣告*/
        Bitmap bitmapOut = null;
        Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resId);
        /*獲取圖片的格式型別*/
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(context.getResources(), resId, options);
        String mimeType = options.outMimeType;
        Log.i(TAG, "圖片格式:" + mimeType);
        if (quality < 0 || quality > 100) {
            Log.e(TAG, "圖片質量要在0-100之間");
            return null;
        }

        /*分別對jpeg與png進行質量壓縮處理*/
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        if (TextUtils.equals(mimeType,"image/jpeg")) {
            bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);
        }
        byte[] bytes = baos.toByteArray();
        bitmapOut = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);

        Log.i(TAG, "原圖片的大小:" + (bitmap.getByteCount() / 1024 / 1024)
                + "M 寬度為" + bitmap.getWidth() + " 高度為" + bitmap.getHeight());

        Log.i(TAG, "壓縮後圖片的大小:" + (bitmapOut.getByteCount() / 1024 / 1024)
                + "M 寬度為" + bitmapOut.getWidth() + " 高度為" + bitmapOut.getHeight()
                + " bytes.length=" + (bytes.length / 1024) + "KB"
                + " quality=" + quality);
        return bitmapOut;
    }

2.取樣率壓縮

設定inSampleSize的值,如果inSampleSize=2的話,寬高都會變成原來的1/2,佔用的記憶體就會變成原來的1/4.
注意:有的時候在解碼圖片的時候,避免Bitmap的記憶體分配,只想獲取到bitmap的寬高以及mimeType資訊,此時可以設定options.inJustDecodeBounds=true,這樣BitmapFactory解碼圖片時返回為Null的Bitmap物件,但同時獲取到的寬高等資料。

 /**
     * 取樣率壓縮
     */
    public static Bitmap compressSampling(Context context,int resId,int sampleSize){
        Bitmap bitmapOut = null;
        Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resId);
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = sampleSize;
        bitmapOut = BitmapFactory.decodeResource(context.getResources(),resId,options);
        Log.i(TAG, "原圖片的大小:" + (bitmap.getByteCount() / 1024 / 1024)
                + "M 寬度為" + bitmap.getWidth() + " 高度為" + bitmap.getHeight());

        Log.i(TAG, "壓縮後圖片的大小:" + (bitmapOut.getByteCount() / 1024 / 1024)
                + "M 寬度為" + bitmapOut.getWidth() + " 高度為" + bitmapOut.getHeight()
               );
        return bitmapOut;
    }

3.縮放法壓縮

使用矩陣對圖片進行縮放,

 /**
     * 縮放法壓縮
     */
    public static Bitmap compressScale(Context context,int resId,float scaleX,float scaleY){
        Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),resId);

        Matrix matrix = new Matrix();
        matrix.setScale(scaleX,scaleY);
        Bitmap bitmapOut = Bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),bitmap.getHeight(),matrix,true);
        Log.i(TAG, "compressScale--壓縮後圖片的大小:" + (bitmapOut.getByteCount() / 1024 / 1024)
                + "M 寬度為" + bitmapOut.getWidth() + " 高度為" + bitmapOut.getHeight()
        );
        return bitmapOut;
    }

4.RGB_565方法,修改Bitmap的壓縮格式

RGB_565是16位的點陣圖,ARGB_888是32位的點陣圖,通過修改壓縮格式來壓縮,記憶體會變為ARGB_8888記憶體的一半,但是寬高並沒有改變。

/**
    * 設定壓縮格式來壓縮
    */
   public static Bitmap compressConfig(Context context,int resId){
       Bitmap bitmapOut = null;
       BitmapFactory.Options options = new BitmapFactory.Options();
       options.inPreferredConfig = Bitmap.Config.RGB_565;
       bitmapOut = BitmapFactory.decodeResource(context.getResources(),resId,options);
       Log.i(TAG, "compressConfig--壓縮後圖片的大小:" + (bitmapOut.getByteCount() / 1024 / 1024)
               + "M 寬度為" + bitmapOut.getWidth() + " 高度為" + bitmapOut.getHeight()
       );
       return bitmapOut;
   }

5.指定圖片的寬高

隨便指定寬高的話,會出現圖片拉伸的情況。

 /**
     * 建立新的Bitmap,並指定圖片的寬高
     */
    public static Bitmap compressCreateScaleBitmap(Context context,int resId,int width,int height){
        Bitmap bitmapOut = null;
        Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),resId);
        bitmapOut = Bitmap.createScaledBitmap(bitmap,width,height,true);
        Log.i(TAG, "compressCreateScaleBitmap--壓縮後圖片的大小:" + (bitmapOut.getByteCount() / 1024 / 1024)
                + "M 寬度為" + bitmapOut.getWidth() + " 高度為" + bitmapOut.getHeight()
        );
        bitmap.recycle();
        return bitmapOut;
    }

相關文章