android開發遊記:CROP 大圖片裁剪原理分析
最近專案中需要加入裁剪圖片的功能,圖片的來源包括相機拍照和相簿手動選擇,使用了系統自帶的裁圖功能Crop,但是實際使用中卻發生了一些意想不到的問題:
- 裁剪後返回的data為null
- 裁剪後返回的圖片嚴重失真
這裡總結一下出現問題的原因和解決方案:
呼叫系統裁剪元件的需要設定一些intent引數,通常如下:
Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null);
intent.setType("image/*");
intent.putExtra("crop", "true");
intent.putExtra("aspectX" , 2);
intent.putExtra("aspectY", 1);
intent.putExtra("outputX", 400);
intent.putExtra("outputY", 400);
intent.putExtra("scale", true);
intent.putExtra("return-data", true);
intent.putExtra("outputFormat",Bitmap.CompressFormat.JPEG.toString());
intent.putExtra("noFaceDetection", true);
startActivityForResult(intent, 1 );
上面的
intent.putExtra("return-data", true);
指定了是否返回資料
-如果設定為true,則在返回的data中能拿到返回的bitmap資料
-如果設定為false,則不會返回data,相應的會返回給玩家一個uri,這個uri關聯了一張外存裝置中的一張圖片,就是裁剪後的圖片
然而google為什麼要這樣設計看起來多此一舉的功能呢,直接返回data不就好了嗎?
這樣做的主要原因是因為activity間的引數傳遞大小受到嚴格限制,這主要是考慮到手機執行效能,所以做了這樣的設計。如果你裁剪的只是一張小圖片,那麼ok,設定return-data為true,直接從返回的data中取出bitmap就行了,如果你返回的是一張大圖,那麼久萎了,你會發現如果你的
intent.putExtra("outputX", 400);
intent.putExtra("outputY", 400);
這2個引數設定過大,你收到的返回bitmap將會是一個縮圖!
google這樣做是為了保證系統流暢執行,這樣想想也算合理。
那麼,如何裁剪大圖片呢?
只有把return-data設定為false
然後設定一個uri用於儲存圖片到外存裝置
Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null);
intent.setType("image/*");
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 2);
intent.putExtra("aspectY", 1);
intent.putExtra("outputX", 400);
intent.putExtra("outputY", 400);
intent.putExtra("scale", true);
intent.putExtra("return-data", false);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
intent.putExtra("outputFormat",Bitmap.CompressFormat.JPEG.toString());
intent.putExtra("noFaceDetection", true);
startActivityForResult(intent, 1);
然後在 onActivityResult 這樣處理:
switch (requestCode) {
case 1:
if(uri != null){
Bitmap bitmap = null;
try {
bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
imageView.setImageBitmap(bitmap);
}
break;
}
這樣就解決的裁剪大圖的問題
然而,你會發現呼叫系統裁剪元件會消耗大量的記憶體,有時候會殺死你應用的程序,導致你不得不做好應用的被殺恢復工作,在一些低端機上裁圖元件根本打不開,或者直接崩潰;而且返回大圖過大,而你僅僅是想要一張能看得清楚字的圖就ok了,比如說營業許可證證件照,你並不希望圖片過於高清佔用太大的記憶體空間,或者上傳產生過多的流量,使你不得不再次壓縮圖片。總之你會發現這些處理工作過於麻煩。這樣你就需要使用自定義的裁圖元件。
我調查發現市面上主流的應用如qq微信等,都沒有使用系統裁圖,而是自己編寫了一個裁圖元件來解決這些問題。
下一章我就分享一下如何自定義裁剪圖片功能元件