不少人在調用圖庫選擇圖片時會在onActivityResult中用Media.getBitmap來獲取返回的圖片,以下:html
- Uri mImageCaptureUri = data.getData();
- Bitmap photoBmp = null;
- if (mImageCaptureUri != null) {
- photoBmp = MediaStore.Images.Media.getBitmap(ac.getContentResolver(), mImageCaptureUri);
- }
可是Media.getBitmap這個方法獲取已知uri圖片的方式並不可取,咱來看看Media.getBitmap()方法的源碼:java
- public static final Bitmap getBitmap(ContentResolver cr, Uri url)
- throws FileNotFoundException, IOException {
- InputStream input = cr.openInputStream(url);
- Bitmap bitmap = BitmapFactory.decodeStream(input);
- input.close();
- return bitmap;
- }
其實它很簡單很粗暴,返回的是原始大小的bitmap,當圖庫選擇的圖片很大時程序極有可能會報OOM。數據庫
爲了不OOM,我們須要改進該方法,在 BitmapFactory.decodeStream 以前壓縮圖片,如下是我改進後的代碼:post
在onActivityResult中調用url
- Uri mImageCaptureUri = data.getData();
- Bitmap photoBmp = null;
- if (mImageCaptureUri != null) {
- photoBmp = getBitmapFormUri(ac, mImageCaptureUri);
- }
- /**
- * 經過uri獲取圖片並進行壓縮
- *
- * @param uri
- */
- public static Bitmap getBitmapFormUri(Activity ac, Uri uri) throws FileNotFoundException, IOException {
- InputStream input = ac.getContentResolver().openInputStream(uri);
- BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options();
- onlyBoundsOptions.inJustDecodeBounds = true;
- onlyBoundsOptions.inDither = true;//optional
- onlyBoundsOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;//optional
- BitmapFactory.decodeStream(input, null, onlyBoundsOptions);
- input.close();
- int originalWidth = onlyBoundsOptions.outWidth;
- int originalHeight = onlyBoundsOptions.outHeight;
- if ((originalWidth == -1) || (originalHeight == -1))
- return null;
- //圖片分辨率以480x800爲標準
- float hh = 800f;//這裏設置高度爲800f
- float ww = 480f;//這裏設置寬度爲480f
- //縮放比。因爲是固定比例縮放,只用高或者寬其中一個數據進行計算便可
- int be = 1;//be=1表示不縮放
- if (originalWidth > originalHeight && originalWidth > ww) {//若是寬度大的話根據寬度固定大小縮放
- be = (int) (originalWidth / ww);
- } else if (originalWidth < originalHeight && originalHeight > hh) {//若是高度高的話根據寬度固定大小縮放
- be = (int) (originalHeight / hh);
- }
- if (be <= 0)
- be = 1;
- //比例壓縮
- BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
- bitmapOptions.inSampleSize = be;//設置縮放比例
- bitmapOptions.inDither = true;//optional
- bitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;//optional
- input = ac.getContentResolver().openInputStream(uri);
- Bitmap bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions);
- input.close();
- return compressImage(bitmap);//再進行質量壓縮
- }
- /**
- * 質量壓縮方法
- *
- * @param image
- * @return
- */
- public static Bitmap compressImage(Bitmap image) {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//質量壓縮方法,這裏100表示不壓縮,把壓縮後的數據存放到baos中
- int options = 100;
- while (baos.toByteArray().length / 1024 > 100) { //循環判斷若是壓縮後圖片是否大於100kb,大於繼續壓縮
- baos.reset();//重置baos即清空baos
- //第一個參數 :圖片格式 ,第二個參數: 圖片質量,100爲最高,0爲最差 ,第三個參數:保存壓縮後的數據的流
- image.compress(Bitmap.CompressFormat.JPEG, options, baos);//這裏壓縮options%,把壓縮後的數據存放到baos中
- options -= 10;//每次都減小10
- }
- ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把壓縮後的數據baos存放到ByteArrayInputStream中
- Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream數據生成圖片
- return bitmap;
- }
OOM的問題解決了,可是又碰到另一個問題,用三星手機拍照或者選擇照片後返回來的圖片竟然轉了90度,接着改。spa
在onActivityResult中的代碼進行改進:.net
- Uri originalUri = null;
- File file = null;
- if (null != data && data.getData() != null) {
- originalUri = data.getData();
- file = getFileFromMediaUri(ac, originalUri);
- }
- Bitmap photoBmp = getBitmapFormUri(ac, Uri.fromFile(file));
- int degree = getBitmapDegree(file.getAbsolutePath());
- /**
- * 把圖片旋轉爲正的方向
- */
- Bitmap newbitmap = rotateBitmapByDegree(photoBmp, degree);
- /**
- * 經過Uri獲取文件
- * @param ac
- * @param uri
- * @return
- */
- public static File getFileFromMediaUri(Context ac, Uri uri) {
- if(uri.getScheme().toString().compareTo("content") == 0){
- ContentResolver cr = ac.getContentResolver();
- Cursor cursor = cr.query(uri, null, null, null, null);// 根據Uri從數據庫中找
- if (cursor != null) {
- cursor.moveToFirst();
- String filePath = cursor.getString(cursor.getColumnIndex("_data"));// 獲取圖片路徑
- cursor.close();
- if (filePath != null) {
- return new File(filePath);
- }
- }
- }else if(uri.getScheme().toString().compareTo("file") == 0){
- return new File(uri.toString().replace("file://",""));
- }
- return null;
- }
- /**
- * 讀取圖片的旋轉的角度
- *
- * @param path 圖片絕對路徑
- * @return 圖片的旋轉角度
- */
- public static int getBitmapDegree(String path) {
- int degree = 0;
- try {
- // 從指定路徑下讀取圖片,並獲取其EXIF信息
- ExifInterface exifInterface = new ExifInterface(path);
- // 獲取圖片的旋轉信息
- int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
- ExifInterface.ORIENTATION_NORMAL);
- switch (orientation) {
- case ExifInterface.ORIENTATION_ROTATE_90:
- degree = 90;
- break;
- case ExifInterface.ORIENTATION_ROTATE_180:
- degree = 180;
- break;
- case ExifInterface.ORIENTATION_ROTATE_270:
- degree = 270;
- break;
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- return degree;
- }
- /**
- * 將圖片按照某個角度進行旋轉
- *
- * @param bm 須要旋轉的圖片
- * @param degree 旋轉角度
- * @return 旋轉後的圖片
- */
- public static Bitmap rotateBitmapByDegree(Bitmap bm, int degree) {
- Bitmap returnBm = null;
- // 根據旋轉角度,生成旋轉矩陣
- Matrix matrix = new Matrix();
- matrix.postRotate(degree);
- try {
- // 將原始圖片按照旋轉矩陣進行旋轉,並獲得新的圖片
- returnBm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
- } catch (OutOfMemoryError e) {
- }
- if (returnBm == null) {
- returnBm = bm;
- }
- if (bm != returnBm) {
- bm.recycle();
- }
- return returnBm;
- }
來自:http://www.cnblogs.com/popqq520/p/5404738.htmlcode