通过URI获取图片处理

获取流对象读取
InputStream is = getContentResolver().openInputStream(uri);
Bitmap bitmap = BitmapFactory.decodeStream(is);
is.close();

//根据uri获取真实路径

private String getRealPath(Uri fileUrl){
String fileName = null;
   Uri filePathUri = fileUrl;
   if(fileUrl!= null){
   if (fileUrl.getScheme().toString().compareTo("content")==0)           //content://开头的uri
   {      
       Cursor cursor = mContext.getContentResolver().query(videoUrl, null, null, null, null);
       if (cursor != null && cursor.moveToFirst())
       {
           int column_index = cursor.getColumnIndexOrThrow(***.***.***.DATA);
           fileName = cursor.getString(column_index);          //取出文件路径
           if(!fileName.startsWith("/mnt")){//检查是否有”/mnt“前缀
   fileName = "/mnt" + fileName; 
   }
           cursor.close();
       }
   }else if (videoUrl.getScheme().compareTo("file")==0)         //file:///开头的uri
   {
       fileName = filePathUri.toString();
       fileName = filePathUri.toString().replace("file://", "");//替换file://
      if(!fileName.startsWith("/mnt")){//加上"/mnt"头
   fileName += "/mnt"; 
   }
   }
   }
   return fileName;
}


很多人在调用图库选择图片时会在onActivityResult中用Media.getBitmap来获取返回的图片,如下:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  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]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  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;  

  1. 其实它很简单很粗暴,返回的是原始大小的bitmap,当图库选择的图片很大时程序极有可能会报OOM。

    为了避免OOM,咱们需要改进该方法,在 BitmapFactory.decodeStream 之前压缩图片,以下是我改进后的代码:

    在onActivityResult中调用

    [java]  view plain  copy
      在CODE上查看代码片 派生到我的代码片
    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
      在CODE上查看代码片 派生到我的代码片
    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.     }  
      1. * 质量压缩方法 
      2.     * 
      3.     * @param image 
      4.     * @return 
      5.     */  
      6.    public static Bitmap compressImage(Bitmap image) {  
      7.    
      8.        ByteArrayOutputStream baos = new ByteArrayOutputStream();  
      9.        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中  
      10.        int options = 100;  
      11.        while (baos.toByteArray().length / 1024 > 100) {  //循环判断如果压缩后图片是否大于100kb,大于继续压缩  
      12.            baos.reset();//重置baos即清空baos  
      13.            //第一个参数 :图片格式 ,第二个参数: 图片质量,100为最高,0为最差  ,第三个参数:保存压缩后的数据的流  
      14.            image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中  
      15.            options -= 10;//每次都减少10  
      16.        }  
      17.        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中  
      18.        Bitmap bitmap = BitmapFactory.decodeStream(isBm, nullnull);//把ByteArrayInputStream数据生成图片  
      19.        return bitmap;  
      20.    }  

      OOM的问题解决了,但是又碰到另外一个问题,用三星手机拍照或者选择照片后返回来的图片居然转了90度,接着改。


      在onActivityResult中的代码进行改进:

      [java]  view plain  copy
        在CODE上查看代码片 派生到我的代码片
      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
        在CODE上查看代码片 派生到我的代码片
      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, nullnullnullnull);// 根据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
        在CODE上查看代码片 派生到我的代码片
      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
        在CODE上查看代码片 派生到我的代码片
      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, 00, 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.     }  

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值