I used this code in many projects and always it gives me good results, i remember if i choose a image having size of 5-7MB(image from 12/13 MP camera) this code returns an image of size 1MB or less than 2MB.
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 needed.
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 path from 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 choose a picture from drive etc. we still need a real path of 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've a real path of selected image so we can get a bitmap from this path using 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) {
// raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth)
inSampleSize *= 2;
}
return inSampleSize;
}
At this point we've a compressed bitmap, further more we can again compress this bitmap if we perform 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 sever end you can decode Base64 and convert back to 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 don't want to perform Base64 you can use your bitmap to convert into stream and send it to your server.