android 經過uri獲取bitmap圖片並壓縮

不少人在調用圖庫選擇圖片時會在onActivityResult中用Media.getBitmap來獲取返回的圖片,以下:html

 

[java]  view plain  copy
 
  1. Uri mImageCaptureUri = data.getData();  
  2. Bitmap photoBmp = null;  
  3. if (mImageCaptureUri != null) {  
  4.     photoBmp = MediaStore.Images.Media.getBitmap(ac.getContentResolver(), mImageCaptureUri);  
  5. }  


可是Media.getBitmap這個方法獲取已知uri圖片的方式並不可取,咱來看看Media.getBitmap()方法的源碼:java

 

 

[java]  view plain  copy
 
  1. public static final Bitmap getBitmap(ContentResolver cr, Uri url)  
  2.         throws FileNotFoundException, IOException {  
  3.     InputStream input = cr.openInputStream(url);  
  4.     Bitmap bitmap = BitmapFactory.decodeStream(input);  
  5.     input.close();  
  6.     return bitmap;  
  7. }  

 

 

其實它很簡單很粗暴,返回的是原始大小的bitmap,當圖庫選擇的圖片很大時程序極有可能會報OOM。數據庫

爲了不OOM,我們須要改進該方法,在 BitmapFactory.decodeStream 以前壓縮圖片,如下是我改進後的代碼:post

在onActivityResult中調用url

[java]  view plain  copy
 
  1. Uri mImageCaptureUri = data.getData();  
  2.    
  3. Bitmap photoBmp = null;  
  4.    
  5. if (mImageCaptureUri != null) {  
  6.    
  7. photoBmp = getBitmapFormUri(ac, mImageCaptureUri);  
  8.    
  9. }  

 

[java]  view plain  copy
 
  1. /** 
  2.      * 經過uri獲取圖片並進行壓縮 
  3.      * 
  4.      * @param uri 
  5.      */  
  6.     public static Bitmap getBitmapFormUri(Activity ac, Uri uri) throws FileNotFoundException, IOException {  
  7.         InputStream input = ac.getContentResolver().openInputStream(uri);  
  8.         BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options();  
  9.         onlyBoundsOptions.inJustDecodeBounds = true;  
  10.         onlyBoundsOptions.inDither = true;//optional  
  11.         onlyBoundsOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;//optional  
  12.         BitmapFactory.decodeStream(input, null, onlyBoundsOptions);  
  13.         input.close();  
  14.         int originalWidth = onlyBoundsOptions.outWidth;  
  15.         int originalHeight = onlyBoundsOptions.outHeight;  
  16.         if ((originalWidth == -1) || (originalHeight == -1))  
  17.             return null;  
  18.         //圖片分辨率以480x800爲標準  
  19.         float hh = 800f;//這裏設置高度爲800f  
  20.         float ww = 480f;//這裏設置寬度爲480f  
  21.         //縮放比。因爲是固定比例縮放,只用高或者寬其中一個數據進行計算便可  
  22.         int be = 1;//be=1表示不縮放  
  23.         if (originalWidth > originalHeight && originalWidth > ww) {//若是寬度大的話根據寬度固定大小縮放  
  24.             be = (int) (originalWidth / ww);  
  25.         } else if (originalWidth < originalHeight && originalHeight > hh) {//若是高度高的話根據寬度固定大小縮放  
  26.             be = (int) (originalHeight / hh);  
  27.         }  
  28.         if (be <= 0)  
  29.             be = 1;  
  30.         //比例壓縮  
  31.         BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();  
  32.         bitmapOptions.inSampleSize = be;//設置縮放比例  
  33.         bitmapOptions.inDither = true;//optional  
  34.         bitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;//optional  
  35.         input = ac.getContentResolver().openInputStream(uri);  
  36.         Bitmap bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions);  
  37.         input.close();  
  38.    
  39.         return compressImage(bitmap);//再進行質量壓縮  
  40.     }  

 

[java]  view plain  copy
 
  1. /** 
  2.     * 質量壓縮方法 
  3.     * 
  4.     * @param image 
  5.     * @return 
  6.     */  
  7.    public static Bitmap compressImage(Bitmap image) {  
  8.    
  9.        ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  10.        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//質量壓縮方法,這裏100表示不壓縮,把壓縮後的數據存放到baos中  
  11.        int options = 100;  
  12.        while (baos.toByteArray().length / 1024 > 100) {  //循環判斷若是壓縮後圖片是否大於100kb,大於繼續壓縮  
  13.            baos.reset();//重置baos即清空baos  
  14.            //第一個參數 :圖片格式 ,第二個參數: 圖片質量,100爲最高,0爲最差  ,第三個參數:保存壓縮後的數據的流  
  15.            image.compress(Bitmap.CompressFormat.JPEG, options, baos);//這裏壓縮options%,把壓縮後的數據存放到baos中  
  16.            options -= 10;//每次都減小10  
  17.        }  
  18.        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把壓縮後的數據baos存放到ByteArrayInputStream中  
  19.        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream數據生成圖片  
  20.        return bitmap;  
  21.    }  

OOM的問題解決了,可是又碰到另一個問題,用三星手機拍照或者選擇照片後返回來的圖片竟然轉了90度,接着改。spa

 

在onActivityResult中的代碼進行改進:.net

[java]  view plain  copy
 
  1. Uri originalUri = null;  
  2.       File file = null;  
  3.       if (null != data && data.getData() != null) {  
  4.           originalUri = data.getData();  
  5.           file = getFileFromMediaUri(ac, originalUri);  
  6.       }  
  7.  Bitmap photoBmp = getBitmapFormUri(ac, Uri.fromFile(file));  
  8.   int degree = getBitmapDegree(file.getAbsolutePath());  
  9.   /** 
  10.    * 把圖片旋轉爲正的方向 
  11.    */  
  12.   Bitmap newbitmap = rotateBitmapByDegree(photoBmp, degree);  

 

[java]  view plain  copy
 
  1. /** 
  2.      * 經過Uri獲取文件 
  3.      * @param ac 
  4.      * @param uri 
  5.      * @return 
  6.      */  
  7.     public static File getFileFromMediaUri(Context ac, Uri uri) {  
  8.         if(uri.getScheme().toString().compareTo("content") == 0){  
  9.             ContentResolver cr = ac.getContentResolver();  
  10.             Cursor cursor = cr.query(uri, null, null, null, null);// 根據Uri從數據庫中找  
  11.             if (cursor != null) {  
  12.                 cursor.moveToFirst();  
  13.                 String filePath = cursor.getString(cursor.getColumnIndex("_data"));// 獲取圖片路徑  
  14.                 cursor.close();  
  15.                 if (filePath != null) {  
  16.                     return new File(filePath);  
  17.                 }  
  18.             }  
  19.         }else if(uri.getScheme().toString().compareTo("file") == 0){  
  20.             return new File(uri.toString().replace("file://",""));  
  21.         }  
  22.             return null;  
  23.         }  



[java]  view plain  copy
 
  1. /** 
  2.      * 讀取圖片的旋轉的角度 
  3.      * 
  4.      * @param path 圖片絕對路徑 
  5.      * @return 圖片的旋轉角度 
  6.      */  
  7.     public static int getBitmapDegree(String path) {  
  8.         int degree = 0;  
  9.         try {  
  10.             // 從指定路徑下讀取圖片,並獲取其EXIF信息  
  11.             ExifInterface exifInterface = new ExifInterface(path);  
  12.             // 獲取圖片的旋轉信息  
  13.             int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,  
  14.                     ExifInterface.ORIENTATION_NORMAL);  
  15.             switch (orientation) {  
  16.                 case ExifInterface.ORIENTATION_ROTATE_90:  
  17.                     degree = 90;  
  18.                     break;  
  19.                 case ExifInterface.ORIENTATION_ROTATE_180:  
  20.                     degree = 180;  
  21.                     break;  
  22.                 case ExifInterface.ORIENTATION_ROTATE_270:  
  23.                     degree = 270;  
  24.                     break;  
  25.             }  
  26.         } catch (IOException e) {  
  27.             e.printStackTrace();  
  28.         }  
  29.         return degree;  
  30.     }  

 

[java]  view plain  copy
 
  1. /** 
  2.      * 將圖片按照某個角度進行旋轉 
  3.      * 
  4.      * @param bm     須要旋轉的圖片 
  5.      * @param degree 旋轉角度 
  6.      * @return 旋轉後的圖片 
  7.      */  
  8.     public static Bitmap rotateBitmapByDegree(Bitmap bm, int degree) {  
  9.         Bitmap returnBm = null;  
  10.    
  11.         // 根據旋轉角度,生成旋轉矩陣  
  12.         Matrix matrix = new Matrix();  
  13.         matrix.postRotate(degree);  
  14.         try {  
  15.             // 將原始圖片按照旋轉矩陣進行旋轉,並獲得新的圖片  
  16.             returnBm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);  
  17.         } catch (OutOfMemoryError e) {  
  18.         }  
  19.         if (returnBm == null) {  
  20.             returnBm = bm;  
  21.         }  
  22.         if (bm != returnBm) {  
  23.             bm.recycle();  
  24.         }  
  25.         return returnBm;  
  26.     }  

來自:http://www.cnblogs.com/popqq520/p/5404738.htmlcode

相關文章
相關標籤/搜索