android uri to bitmap image and compress

Many people will use Media.getBitmap in onActivityResult to get the returned pictures when they call the gallery to select pictures, as follows:

Uri mImageCaptureUri = data.getData();
Bitmap photoBmp = null;
if (mImageCaptureUri != null) {
    photoBmp = MediaStore.Images.Media.getBitmap(ac.getContentResolver(), mImageCaptureUri);
}

However, Media.getBitmap is not a good way to get known uri images. Let's look at the source code of Media.getBitmap():

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;
}

In fact, it's very simple and crude. It returns the original size of bitmap. When the picture selected by the gallery is very large, the program is likely to report OOM.

In order to avoid OOM, we need to improve the method, compress the image before BitmapFactory.decodeStream. Here is my improved code:

Call in onActivityResult

Uri mImageCaptureUri = data.getData();
 
Bitmap photoBmp = null;
 
if (mImageCaptureUri != null) {
 
photoBmp = getBitmapFormUri(ac, mImageCaptureUri);
 
}
/**
     * Get pictures through uri and compress them
     *
     * @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;
        //Image resolution is based on 480x800
        float hh = 800f;//The height is set as 800f here
        float ww = 480f;//Set the width here to 480f
        //Zoom ratio. Because it is a fixed scale, only one data of height or width is used for calculation
        int be = 1;//be=1 means no scaling
        if (originalWidth > originalHeight && originalWidth > ww) {//If the width is large, scale according to the fixed size of the width
            be = (int) (originalWidth / ww);
        } else if (originalWidth < originalHeight && originalHeight > hh) {//If the height is high, scale according to the fixed size of the width
            be = (int) (originalHeight / hh);
        }
        if (be <= 0)
            be = 1;
        //Proportional compression
        BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
        bitmapOptions.inSampleSize = be;//Set scaling
        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);//Mass compression again
    }
/**
    * Mass compression method
    *
    * @param image
    * @return
    */
   public static Bitmap compressImage(Bitmap image) {
 
       ByteArrayOutputStream baos = new ByteArrayOutputStream();
       image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//Quality compression method, here 100 means no compression, store the compressed data in the BIOS
       int options = 100;
       while (baos.toByteArray().length / 1024 > 100) {  //Cycle to determine if the compressed image is greater than 100kb, greater than continue compression
           baos.reset();//Reset the BIOS to clear it
           //First parameter: picture format, second parameter: picture quality, 100 is the highest, 0 is the worst, third parameter: save the compressed data stream
           image.compress(Bitmap.CompressFormat.JPEG, options, baos);//Here, the compression options are used to store the compressed data in the BIOS
           options -= 10;//10 less each time
       }
       ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//Store the compressed data in ByteArrayInputStream
       Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//Generate image from ByteArrayInputStream data
       return bitmap;
   }

The OOM problem has been solved, but another problem has been encountered. The pictures returned after taking photos or selecting photos with Samsung mobile phone have turned 90 degrees, and then changed.

 

Code improvement in onActivityResult:

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());
  /**
   * Rotate the picture to a positive direction
   */
  Bitmap newbitmap = rotateBitmapByDegree(photoBmp, degree);
/**
     * Get file via 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);// Find from database according to Uri
            if (cursor != null) {
                cursor.moveToFirst();
                String filePath = cursor.getString(cursor.getColumnIndex("_data"));// Get picture path
                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;
        }
/**
     * Read the rotation angle of the picture
     *
     * @param path Absolute path of picture
     * @return Rotation angle of picture
     */
    public static int getBitmapDegree(String path) {
        int degree = 0;
        try {
            // Read the picture from the specified path and obtain its EXIF information
            ExifInterface exifInterface = new ExifInterface(path);
            // Get rotation information for pictures
            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;
    }
/**
     * Rotate the picture at an angle
     *
     * @param bm     Pictures to rotate
     * @param degree Rotation angle
     * @return Rotated picture
     */
    public static Bitmap rotateBitmapByDegree(Bitmap bm, int degree) {
        Bitmap returnBm = null;
 
        // Generate rotation matrix according to rotation angle
        Matrix matrix = new Matrix();
        matrix.postRotate(degree);
        try {
            // Rotate the original image according to the rotation matrix and get a new image
            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;
    }

https://blog.csdn.net/jdsjlzx/article/details/51181229

Keywords: less Mobile Database

Added by exploo on Wed, 01 Jan 2020 05:53:07 +0200