在開發圖檔浏覽器等軟體是,很多時候要顯示圖檔的縮略圖,而一般情況下,我們要将圖檔按照固定大小取縮略圖,一般取縮略圖的方法是使用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 (no bitmap), but the out... fields will still be set, allowing the caller to query the bitmap without having to allocate the memory for its pixels.
意思就是說如果該值設為true那麼将不傳回實際的bitmap不給其配置設定記憶體空間而裡面隻包括一些解碼邊界資訊即圖檔大小資訊,那麼相應的方法也就出來了,通過設定inJustDecodeBounds為true,擷取到outHeight(圖檔原始高度)和 outWidth(圖檔的原始寬度),然後計算一個inSampleSize(縮放值),然後就可以取圖檔了,這裡要注意的是,inSampleSize 可能小于0,必須做判斷。也就是說先将Options的屬性inJustDecodeBounds設為true,先擷取圖檔的基本大小資訊資料(資訊沒有儲存在bitmap裡面,而是儲存在options裡面),通過options.outHeight和 options. outWidth擷取的大小資訊以及自己想要到得圖檔大小計算出來縮放比例inSampleSize,然後緊接着将inJustDecodeBounds設為false,就可以根據已經得到的縮放比例得到自己想要的圖檔縮放圖了。
具體代碼如下:
FrameLayout fr=(FrameLayout)findViewById(R.id.FrameLayout01);
BitmapFactory.Options options = new BitmapFactory.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 {
FileOutputStream out=new FileOutputStream(file);
if(bitmap.compress(Bitmap.CompressFormat.PNG, 100, out)){
out.flush();
out.close();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ok,這樣就把圖檔儲存在/sdcard/feng.png這個檔案裡面了,呵呵。
方法2:按長寬各自比例進行縮放
但是這裡的縮放儲存是按長寬比例的,下邊也可以按固定大小縮放哦:
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();
Bitmap resizeBitmap = bitmap;
//Bitmap to byte[]
byte[] photoData = bitmap2Bytes(resizeBitmap);
//save file
String fileName = "/sdcard/test.jpg";
FileUtil.writeToFile(fileName, photoData);