I used this code in many projects, and it always gives me good results, I remember, if I select an image of size 5-7 MB (image from a 12/13 MP camera), this code returns an image of 1 MB or less than 2 MB .
public static boolean validateUri(Uri uri) { if (uri == null) return false; else { String path = uri.getPath(); return !(uri.equals(Uri.EMPTY) || path == null || path.equals("null")); } }
First we need a full image and rotate if necessary.
public static Bitmap getFullSizeImage(Context context, Uri uri) { String filePath; if (validateUri(uri) && uri.toString().contains("file")) filePath = uri.getPath(); else filePath = getRealPathFromURI(context, uri, MediaStore.Images.Media.DATA); if (filePath == null) return null; try { int rotation = 0; ExifInterface exifInterface = new ExifInterface(filePath); int exifRotation = exifInterface.getAttributeInt( ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED); if (exifRotation != ExifInterface.ORIENTATION_UNDEFINED) { switch (exifRotation) { case ExifInterface.ORIENTATION_ROTATE_180: rotation = 180; break; case ExifInterface.ORIENTATION_ROTATE_270: rotation = 270; break; case ExifInterface.ORIENTATION_ROTATE_90: rotation = 90; break; } } Matrix matrix = new Matrix(); matrix.setRotate(rotation); // you can use other than 400 as required width/height Bitmap sourceBitmap = getBitmapFromPath(400, filePath); if (sourceBitmap == null) return null; return Bitmap.createBitmap(sourceBitmap, 0, 0, sourceBitmap.getWidth(), sourceBitmap.getHeight(), matrix, true); } catch (IOException e) { e.printStackTrace(); } return null; }
Now we need a real way from the URI
public static String getRealPathFromURI(Context context, Uri contentUri, String type) { Cursor cursor = null; String path = null; try { // String[] proj = { MediaStore.Images.Media.DATA }; String[] projection = {type}; cursor = context.getContentResolver().query(contentUri, projection, null, null, null); if (cursor == null) return null; int columnIndex = cursor.getColumnIndexOrThrow(type); cursor.moveToFirst(); path = cursor.getString(columnIndex); // we choose image from drive etc. if (path == null) path = getDocumentRealPathFromUri(context, contentUri); } catch (Exception e) { e.printStackTrace(); } finally { if (cursor != null) cursor.close(); } return path; }
If we select a picture from disk, etc., we still need the real path of the given URI
public static String getDocumentRealPathFromUri(Context context, Uri contentUri) { Cursor cursor = context.getContentResolver().query(contentUri, null, null, null, null); if (cursor == null) return null; cursor.moveToFirst(); String documentId = cursor.getString(0); documentId = documentId.substring(documentId.lastIndexOf(":") + 1); cursor.close(); cursor = context.getContentResolver().query( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, MediaStore.Images.Media._ID + " = ? ", new String[]{documentId}, null); if (cursor == null) return null; cursor.moveToFirst(); String path = cursor.getString(cursor .getColumnIndex(MediaStore.Images.Media.DATA)); cursor.close(); return path; }
Now we have a real path to the selected image, so we can get a bitmap from this path using the sample size
public static Bitmap getBitmapFromPath(int size, String realPathFromURI) { final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(realPathFromURI, options); options.inSampleSize = calculateInSampleSizeUsingPower2(options, size, size); options.inJustDecodeBounds = false; return BitmapFactory.decodeFile(realPathFromURI, options); } public static int calculateInSampleSizeUsingPower2(BitmapFactory.Options options, int reqWidth, int reqHeight) {
At this point, we have a compressed bitmap, and even more we can compress this bitmap again if we perform the Base64 operation on a given bitmap.
public static String convertToBase64(Bitmap bitmap) { if (bitmap == null) return null; ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); if (bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream)) { String base64 = encodeToString(byteArrayOutputStream.toByteArray(), DEFAULT); try { byteArrayOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } return base64; } return null; }
On your terminal, you can decode Base64 and convert it back to a file stream and save your image.
Example
Bitmap bitmap = getFullSizeImage(context, selectedPhotoUri); if(bitmap != null){ String base64Image = convertToBase64(bitmap); if (base64Image != null) { RequestParams params = new RequestParams(); try { params.put("title", "your_image_name"); params.put("profile_picture", base64Image); } catch(FileNotFoundException e) { Log.d("error", "error catch"); } } }
Note If you do not want to run Base64, you can use a bitmap to convert to a stream and send it to your server.