天天看點

Android開發技術:Android對圖檔的壓縮讀取和儲存

        在開發圖檔浏覽器等軟體是,很多時候要顯示圖檔的縮略圖,而一般情況下,我們要将圖檔按照固定大小取縮略圖,一般取縮略圖的方法是使用BitmapFactory的decodeFile方法,然後通過傳遞進去 BitmapFactory.Option類型的參數進行取縮略圖,在Option中,屬性值inSampleSize表示縮略圖大小為原始圖檔大小的幾分之一,即如果這個值為2,則取出的縮略圖的寬和高都是原始圖檔的1/2,圖檔大小就為原始大小的1/4。

  然而,如果我們想取固定大小的縮略圖就比較困難了,比如,我們想将不同大小的圖檔去出來的縮略圖高度都為200px,而且要保證圖檔不失真,那怎麼辦?我們總不能将原始圖檔加載到記憶體中再進行縮放處理吧,要知道在移動開發中,記憶體是相當寶貴的,而且一張100K的圖檔,加載完所占用的記憶體何止 100K?

  經過研究,發現,Options中有個屬性inJustDecodeBounds,研究了一下,終于明白是什麼意思了,SDK中的E文是這麼說的

  If set to true, the decoder will return null (nobitmap), but the out... fields will still be set, allowing the caller to querythe bitmap without having to allocate the memory for its pixels.

  意思就是說如果該值設為true那麼将不傳回實際的bitmap不給其配置設定記憶體空間而裡面隻包括一些解碼邊界資訊即圖檔大小資訊,那麼相應的方法也就出來了,通過設定inJustDecodeBounds為true,擷取到outHeight(圖檔原始高度)和outWidth(圖檔的原始寬度),然後計算一個inSampleSize(縮放值),然後就可以取圖檔了,這裡要注意的是,inSampleSize 可能小于0,必須做判斷。

具體代碼如下:

FrameLayout fr=(FrameLayout)findViewById(R.id.FrameLayout01);

        BitmapFactory.Options options = newBitmapFactory.Options();

        options.inJustDecodeBounds = true;

        Bitmap bitmap =BitmapFactory.decodeFile("/sdcard/test.jpg", options); //此時傳回bm為空

        options.inJustDecodeBounds = false;

         //縮放比

        int be = (int)(options.outHeight /(float)200);

        if (be <= 0)

            be = 1;

        options.inSampleSize = be;

        //重新讀入圖檔,注意這次要把options.inJustDecodeBounds 設為 false哦

       bitmap=BitmapFactory.decodeFile("/sdcard/test.jpg",options);

        int w = bitmap.getWidth();

        int h = bitmap.getHeight();

        System.out.println(w+"  "+h);

        ImageView iv=new ImageView(this);

        iv.setImageBitmap(bitmap);

這樣我們就可以讀取較大的圖檔而不會記憶體溢出了。如果你想把壓縮後的圖檔儲存在Sdcard上的話就很簡單了:

File file=new File("/sdcard/feng.png");

        try {

            FileOutputStreamout=new FileOutputStream(file);

           if(bitmap.compress(Bitmap.CompressFormat.PNG, 100, out)){

               out.flush();

               out.close();

            }

        } catch (FileNotFoundException e) {

            // TODO Auto-generatedcatch block

            e.printStackTrace();

        } catch (IOException e) {

            // TODO Auto-generatedcatch block

            e.printStackTrace();

        }

ok,這樣就把圖檔儲存在/sdcard/feng.png這個檔案裡面了,呵呵。

但是這裡的縮放儲存是按長寬比例的,下邊也可以按固定大小縮放哦:

        int bmpWidth  = bitmap.getWidth(); 

        int bmpHeight = bitmap.getHeight(); 

        //縮放圖檔的尺寸  

        float scaleWidth  = (float) sWidth /bmpWidth;     //按固定大小縮放 sWidth 寫多大就多大

        float scaleHeight = (float) sHeight /bmpHeight;  //

        Matrix matrix = new Matrix();  

        matrix.postScale(scaleWidth,scaleHeight);  

        //産生縮放後的Bitmap對象  

        Bitmap resizeBitmap = Bitmap.createBitmap( 

            bitmap, 0, 0, bmpWidth,bmpHeight, matrix, false);  

        bitmap.recycle();  

                BitmapresizeBitmap = bitmap;  

        //Bitmap to byte[]  

        byte[] photoData =bitmap2Bytes(resizeBitmap);  

        //save file  

        String fileName ="/sdcard/test.jpg";  

       FileUtil.writeToFile(fileName, photoData);