zoukankan      html  css  js  c++  java
  • android 通过uri获取bitmap图片并压缩

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

    [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] 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 之前压缩图片,以下是我改进后的代码:

    在onActivityResult中调用

    [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度,接着改。

    在onActivityResult中的代码进行改进:

    [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.html

  • 相关阅读:
    Java实现 蓝桥杯 算法提高 小X的购物计划
    Java实现 蓝桥杯 算法提高 小X的购物计划
    Java实现 第十一届 蓝桥杯 (高职专科组)省内模拟赛
    Java实现 第十一届 蓝桥杯 (高职专科组)省内模拟赛
    Java实现 第十一届 蓝桥杯 (高职专科组)省内模拟赛
    Java 第十一届 蓝桥杯 省模拟赛 小明的城堡
    Java 第十一届 蓝桥杯 省模拟赛 小明的城堡
    Java 第十一届 蓝桥杯 省模拟赛 小明的城堡
    129. Sum Root to Leaf Numbers
    117. Populating Next Right Pointers in Each Node II
  • 原文地址:https://www.cnblogs.com/exmyth/p/8420112.html
Copyright © 2011-2022 走看看