Detailed explanation of Android to obtain bitmap images through uri and compress
Many people use it to get the returned image in onActivityResult when calling the gallery to select images, as follows:
Uri mImageCaptureUri = (); Bitmap photoBmp = null; if (mImageCaptureUri != null) { photoBmp = ((), mImageCaptureUri); }
However, this method is not advisable to obtain known uri images. Let's take a look at the source code of the() method:
public static final Bitmap getBitmap(ContentResolver cr, Uri url) throws FileNotFoundException, IOException { InputStream input = (url); Bitmap bitmap = (input); (); return bitmap; }
In fact, it is very simple and rough. It returns a bitmap of the original size. When the picture selected by the gallery is large, the program is very likely to report OOM.
To avoid OOM, we need to improve this method, I used to compress the image, and the following is my improved code:
Called in onActivityResult
Uri mImageCaptureUri = (); Bitmap photoBmp = null; if (mImageCaptureUri != null) { photoBmp = getBitmapFormUri(ac, mImageCaptureUri); }
/** * Get the picture through uri and compress it * * @param uri */ public static Bitmap getBitmapFormUri(Activity ac, Uri uri) throws FileNotFoundException, IOException { InputStream input = ().openInputStream(uri); onlyBoundsOptions = new (); = true; = true;//optional = .ARGB_8888;//optional (input, null, onlyBoundsOptions); (); int originalWidth = ; int originalHeight = ; if ((originalWidth == -1) || (originalHeight == -1)) return null; //The picture resolution is based on 480x800 float hh = 800f;//The height is set to 800f float ww = 480f;//The width is set to 480f //Scaling ratio. Since it is fixed proportional scaling, only one of the data of height or width can be calculated int be = 1;//be=1 means no scaling if (originalWidth > originalHeight && originalWidth > ww) {// If the width is large, scale it according to the width fixed size be = (int) (originalWidth / ww); } else if (originalWidth < originalHeight && originalHeight > hh) {// If the height is high, it will be scaled according to the width. be = (int) (originalHeight / hh); } if (be <= 0) be = 1; //Proportional compression bitmapOptions = new (); = be;//Set the scaling ratio = true;//optional = .ARGB_8888;//optional input = ().openInputStream(uri); Bitmap bitmap = (input, null, bitmapOptions); (); return compressImage(bitmap);//Ready mass compression }
/** * Quality compression method * * @param image * @return */ public static Bitmap compressImage(Bitmap image) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); (, 100, baos);// Quality compression method, here 100 means no compression, store the compressed data in baos int options = 100; while (().length / 1024 > 100) { //Cyclically determine whether the image is greater than 100kb after compression, which is greater than continue compression. ();//Reset baos means clear baos //The first parameter: picture format, the second parameter: picture quality, 100 is the highest, 0 is the worst, and the third parameter: save the stream of compressed data (, options, baos);//The compressed options% here, and the compressed data is stored in baos options -= 10;//Reduce by 10 each time } ByteArrayInputStream isBm = new ByteArrayInputStream(());//Storage the compressed data baos in ByteArrayInputStream Bitmap bitmap = (isBm, null, null);//Create the ByteArrayInputStream data to generate pictures return bitmap; }
The OOM problem was solved, but I encountered another problem. The picture I returned after taking a picture with a Samsung phone or selecting a photo actually turned 90 degrees. . A miserable android programmer. . Then change. .
Let's talk about the code in onActivityResult to improve:
Uri originalUri = null; File file = null; if (null != data && () != null) { originalUri = (); file = getFileFromMediaUri(ac, originalUri); } Bitmap photoBmp = getBitmapFormUri(ac, (file)); int degree = getBitmapDegree(()); /** * Rotate the picture into a positive direction */ Bitmap newbitmap = rotateBitmapByDegree(photoBmp, degree);
/** * Get files through Uri * @param ac * @param uri * @return */ public static File getFileFromMediaUri(Context ac, Uri uri) { if(().toString().compareTo("content") == 0){ ContentResolver cr = (); Cursor cursor = (uri, null, null, null, null);// Find from the database according to Uri if (cursor != null) { (); String filePath = (("_data"));// Get the image path (); if (filePath != null) { return new File(filePath); } } }else if(().toString().compareTo("file") == 0){ return new File(().replace("file://","")); } return null; }
/** * The angle of rotation of the picture * * @param path The absolute path of the picture * @return The rotation angle of the 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 the rotation information of the picture int orientation = (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) { (); } return degree; }
/** * Rotate the image at a certain angle * * @param bm Picture that needs to be rotated * @param degree Rotation angle * @return Image after rotation */ public static Bitmap rotateBitmapByDegree(Bitmap bm, int degree) { Bitmap returnBm = null; // Generate a rotation matrix according to the rotation angle Matrix matrix = new Matrix(); (degree); try { // Rotate the original image according to the rotation matrix and get a new image returnBm = (bm, 0, 0, (), (), matrix, true); } catch (OutOfMemoryError e) { } if (returnBm == null) { returnBm = bm; } if (bm != returnBm) { (); } return returnBm; }
If you have any questions, please leave a message or go to the community of this site to exchange and discuss. Thank you for reading. I hope it can help you. Thank you for your support for this site!