I am creating a sort of 'Gallery' app that is displaying all the images in a grid.
The issue is: that some of the images are not displayed in the right orientation.
Here is the code to retrieve the thumbnails
final String[] projection = { MediaStore.Images.Thumbnails.DATA, MediaStore.Images.Thumbnails.IMAGE_ID };
//query the thumbnails provider
Cursor thumbnailsCursor = context.getContentResolver().query(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, projection, null,
null, null);
if (thumbnailsCursor.moveToFirst()) {
do {
//get the thumbnail path
fullPath = thumbnailsCursor.getString(fullPathColumnIndex);
thumbnailUri = Uri.parse(fullPath);
//add the uri to the list
thumbnailsList.add(thumbnailUri);
} while (thumbnailsCursor.moveToNext());
thumbnailsCursor.close();
Inside the getView() of the BaseAdapter I am using Picasso image loader library to display the thumbnail, but sometimes the orientation is wrong.
Picasso.with(context).load(new File(photoItem.thumbnail.getPath())).noFade().into(holder.photoImageView);
I have tried querying the real photo data and retrieve the orientation but the process is too slow( couple of seconds long) and the displayed images are too large.
Given the ID of the image you can query the MediaStore to get the path to the original image, and then grab the exif for the orientation from there.
This process is quite fast, and usually only takes a few milliseconds.
Cursor cursor =
CustomApplication
.getContext()
.getContentResolver()
.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
new String[] {MediaStore.Images.Media.DATA}, MediaStore.Images.Media._ID + "=?",
new String[] {"" + PHOTO_ID}, null);
if (cursor != null && cursor.getCount() > 0) {
cursor.moveToFirst();
String fullPath = cursor.getString(0);
cursor.close();
ExifInterface exif = new ExifInterface(fullPath);
int exifOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
//ROTATE AND FLIP YOUR THUMBNAIL AS NEEDED BASED ON exifOrientation
}
Here is the correct solution. You can query the orientation data from MediaStore so use
MediaStore.Images.Media.ORIENTATION to get orientation degreee.
final String[] projection = { MediaStore.Images.Thumbnails.DATA, MediaStore.Images.Thumbnails.IMAGE_ID, MediaStore.Images.Media.ORIENTATION };
Cursor thumbnailsCursor = context.getContentResolver().query(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, projection, null, null, null);
if (thumbnailsCursor.moveToFirst()) {
do {
int orientationColumnIndex = thumbnailsCursor.getColumnIndex(MediaStore.Images.Media.ORIENTATION);
int orientation = cur.getInt(orientationColumnIndex);
//do what you want to do with orientation value
}while (thumbnailsCursor.moveToNext());
thumbnailsCursor.close();
will give you the orientation in degrees.
You could use the ExifInterface class as follows:
int originalOrientation = ExifInterface.ORIENTATION_NORMAL;
try {
ExifInterface exif = new ExifInterface(photoItem.thumbnail.getPath().toString());
originalOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
} catch (IOException e) {
e.printStackTrace();
}
Then you can check if it is rotated and do whatever logic you need (such as passing in a rotate angle to the Picasso request).
if (originalOrientation == ExifInterface.ORIENTATION_ROTATE_90 || originalOrientation == ExifInterface.ORIENTATION_ROTATE_270) {
//do something
}
This is the method I use and I have never noticed any performance impact.
I have found that you can apply custom transformations for your loading task in picasso lib.
here is solution refer it.
at there transform method is using MATRIX same as other have given ansewer..
i have not checked yet.
public static float getOrientationValue(String location) {
ExifInterface exif = null;
try {
exif = new ExifInterface(new File(location).getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
}
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
int rotate = 0;
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_270:
rotate += 90;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate += 90;
case ExifInterface.ORIENTATION_ROTATE_90:
rotate += 90;
}
return rotate;
}
or
public static int getOrientation(Context context, Uri photoUri) {
/* it's on the external media. */
Cursor cursor = context.getContentResolver().query(photoUri,
new String[] { MediaStore.Images.ImageColumns.ORIENTATION }, null, null, null);
if (cursor.getCount() != 1) {
return -1;
}
cursor.moveToFirst();
return cursor.getInt(0);
}
Related
This is definitive fix for the Android's problem of duplicating a photo. Tested it on 2.3 (which has the bug), 4.x (which doesnt have the bug) and 5.x (which has the bug too).
The problem is that the photo is saved in two formats: usually one is the timestamp.jpg, and the other one is the full_date_and_time.jpg; sometimes in the same folder, sometimes in different folders. For example, "1430910805600.jpg" and "2015-05-06 11.14.00.jpg". Worstly, one cannot be converted to the other.
The fix uses code that i found in some questions here in StackOverflow, and also an improvement of my own.
First, you get the image with the URI you used to create the intent, get its added date, and delete it. Then, you get the last image added to the gallery, and compare with the added date of the original image. I delete it if difference is less than one second (its usually less than 10ms).
This is the code used to take the photo:
private static final int EXTCAMERA_RETURN = 1234324334;
private String imageFN; // stored globally but could be a parameter
...
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, "tctemp.jpg");
values.put (MediaStore.Images.Media.IS_PRIVATE, 1);
capturedImageURI = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, capturedImageURI);
startActivityForResult(intent, EXTCAMERA_RETURN);
And this is the one to grab the taken photo:
String[] projection = {MediaStore.Images.Media.DATA, BaseColumns._ID, MediaStore.Images.Media.DATE_ADDED};
Cursor cursor = managedQuery(capturedImageURI, projection, null, null, null);
cursor.moveToFirst();
String capturedImageFilePath = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));
long date = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATE_ADDED));
if (capturedImageFilePath == null || !AndroidUtils.copyFile(capturedImageFilePath,imageFN,cameraType == CAMERA_NATIVE_NOCOPY))
resultCode = RESULT_OK+1; // error
else
{
autoRotatePhoto(imageFN);
getContentResolver().delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, BaseColumns._ID + "=" + cursor.getString(cursor.getColumnIndexOrThrow(BaseColumns._ID)), null);
try {new File(capturedImageFilePath).delete();} catch (Exception e) {} // on android 2.3 the code above does not work, so we just ensure that we delete the file
removeLastImageFromGallery(date);
}
This code is used to remove the last photo of the gallery IF the difference is less than one second
private void removeLastImageFromGallery(long orig)
{
try
{
final String[] imageColumns = { MediaStore.Images.Media._ID, MediaStore.Images.Media.DATE_ADDED };
final String imageOrderBy = MediaStore.Images.Media._ID+" DESC";
Cursor imageCursor = managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, imageColumns, null, null, imageOrderBy);
if (imageCursor.moveToFirst())
{
long last = imageCursor.getLong(imageCursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATE_ADDED));
int id = imageCursor.getInt(imageCursor.getColumnIndex(MediaStore.Images.Media._ID));
long dif = Math.abs(orig-last);
if (dif < 1) // 1 second - usually is less than 10ms
getContentResolver().delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, MediaStore.Images.Media._ID + "=?", new String[]{ Long.toString(id) } );
}
}
catch (Exception e)
{
AndroidUtils.handleException(e, false);
}
}
Finally, the autorotate code is:
public static void autoRotatePhoto(String imagePath)
{
try
{
File f = new File(imagePath);
ExifInterface exif = new ExifInterface(f.getPath());
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
AndroidUtils.debug(imagePath+" -> "+orientation);
int angle = 0;
switch (orientation)
{
case ExifInterface.ORIENTATION_ROTATE_90: angle = 90; break;
case ExifInterface.ORIENTATION_ROTATE_180: angle = 180; break;
case ExifInterface.ORIENTATION_ROTATE_270: angle = 270; break;
default: return;
}
Matrix mat = new Matrix();
mat.postRotate(angle);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;
Bitmap bmp = BitmapFactory.decodeStream(new FileInputStream(f), null, options);
Bitmap bitmap = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), mat, true);
FileOutputStream out = new FileOutputStream(f);
bitmap.compress(Bitmap.CompressFormat.JPEG, 85, out);
out.close();
AndroidUtils.debug("auto-rotated "+imagePath);
}
catch (Exception e)
{
AndroidUtils.handleException(e, false);
}
}
The AndroidUtils.debug and handleException are used to dump the Log and print the exception. The copyFile is shown here:
public static boolean copyFile(String in, String out, boolean deleteOriginal)
{
try
{
byte[] buf = new byte[4096];
FileInputStream fin = new FileInputStream(in);
FileOutputStream fout = new FileOutputStream(out);
int r;
while ((r=fin.read(buf,0,buf.length)) > 0)
fout.write(buf,0,r);
fin.close();
fout.close();
if (deleteOriginal)
new File(in).delete();
return true;
}
catch (Exception e)
{
handleException(e,false);
return false;
}
}
I'm unable to get the orientation when selecting an image from my library. If I go to image details, I can see the image orientation is set to 90 degrees. However, my orientation is always 0.
String[] orientationColumn = { MediaStore.Images.ImageColumns.ORIENTATION };
Cursor cur = managedQuery(data.getData(), orientationColumn, null, null, null);
int orientation = -1;
if (cur != null && cur.moveToFirst()) {
orientation = cur.getInt(cur.getColumnIndex(orientationColumn[0]));
}
Using ExitInterface:
ExifInterface exif = new ExifInterface(data.getData().getPath());
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION);
Both ways return 0. I launch the select from library activity like so:
protected void selectFromLibrary() {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setAction(Intent.ACTION_GET_CONTENT);
intent.setData(MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
intent.setType("image/*");
startActivityForResult(intent,
REQUEST_SELECT_IMAGE_FILE);
}
This is on an LG G2 running 4.4.2
I've come across couple of solutions (like here Images taken with ACTION_IMAGE_CAPTURE always returns 1 for ExifInterface.TAG_ORIENTATION on some newer devices), but none of them where working for me.
What finally saved me was this piece of code:
http://androidxref.com/4.0.4/xref/packages/apps/Gallery2/src/com/android/gallery3d/data/Exif.java
So, at the beginning I am trying to get orientation using default exif methods. When it fails, I am releasing the beast.
My full code:
protected Matrix getRotationMatrix(String path, String mimeType, Context ctx, Uri imgUri)
{
Matrix mtx = new Matrix();
try {
ExifInterface exif = new ExifInterface(path);
if (mimeType.contains("jpeg") && exif != null) {
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
if (orientation != ExifInterface.ORIENTATION_UNDEFINED) {
switch (orientation) {
case ExifInterface.ORIENTATION_NORMAL:
break;
case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
mtx.setScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
mtx.setRotate(180);
break;
case ExifInterface.ORIENTATION_FLIP_VERTICAL:
mtx.setRotate(180);
mtx.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_TRANSPOSE:
mtx.setRotate(90);
mtx.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_90:
mtx.setRotate(90);
break;
case ExifInterface.ORIENTATION_TRANSVERSE:
mtx.setRotate(-90);
mtx.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
mtx.setRotate(-90);
break;
}
}
else
{
if (ctx != null && imgUri != null)
{
Cursor cursor = ctx.getContentResolver().query(imgUri,
new String[]{MediaStore.Images.ImageColumns.ORIENTATION},
null, null, null);
try {
if (cursor.moveToFirst()) {
orientation = cursor.getInt(0);
if (orientation != ExifInterface.ORIENTATION_UNDEFINED)
mtx.postRotate(cursor.getInt(0));
else {
// last try...
mtx.postRotate( Exif.getOrientation(ctx.getContentResolver().openInputStream(imgUri)));
}
}
} finally {
cursor.close();
}
}
}
}
}
catch(Exception ex)
{
return mtx;
}
return mtx;
}
Then I use this matrix inside Bitmap.createBitmap method to get image rotated in right way.
setRotation method in Camera.Parameters does not work in all devices. Somebody suggests to manually change the EXIF information to solve the problem. Can you give me a short example on how to set the exif information with ExifInterface in such a way to set the image orientation as portrait?
private int savePicture(byte[] data)
{
File pictureFile = getOutputMediaFile();
if (pictureFile == null)
return FILE_CREATION_ERROR;
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
return FILE_NOT_FOUND;
} catch (IOException e) {
return ACCESSING_FILE_ERROR;
}
return OKAY;
}
I've tried with this:
try {
ExifInterface exifi = new ExifInterface(pictureFile.getAbsolutePath());
exifi.setAttribute(ExifInterface.TAG_ORIENTATION, String.valueOf(ExifInterface.ORIENTATION_ROTATE_90));
exifi.saveAttributes();
} catch (IOException e) {
Log.e(TAG, "Exif error");
}
but nothing change when I visualize the pictures from the android gallery.
For those who actually want to write these EXIF information out, here is some code:
ExifInterface exifInterface = new ExifInterface(someFile.getPath());
exifInterface.setAttribute(ExifInterface.TAG_ORIENTATION,
String.valueOf(orientation));
exifInterface.saveAttributes();
whereas orientation is one of the standard orientations, i.e. ExifInterface.ORIENTATION_ROTATE_{90,180,270}.
If orientation is saved into file but doesn't appear in the gallery it may be because of orientation is cached in MediaStore. So you need to try to update this information there also.
Here is the code snipped (untested)
/**
* #param fileUri the media store file uri
* #param orientation in degrees 0, 90, 180, 270
* #param context
* #return
*/
public boolean setOrientation(Uri fileUri, int orientation, Context context) {
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.ORIENTATION, orientation);
int rowsUpdated = context.getContentResolver().update(fileUri, values, null, null);
return rowsUpdated > 0;
}
/**
* Get content uri for the file path
*
* #param path
* #param context
* #return
*/
public Uri getContentUriForFilePath(String path, Context context) {
String[] projection = {
MediaStore.Images.Media._ID
};
Cursor cursor = context.getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection,
MediaStore.Images.Media.DATA + " = ?", new String[] {
path
}, null);
Uri result = null;
if (cursor != null) {
try {
if (cursor.moveToNext()) {
long mediaId = cursor.getLong(0);
result = ContentUris.withAppendedId(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, mediaId);
}
} finally {
cursor.close();
}
}
return result;
}
Well, I was stuck in such kind of problem, and tried the solution that you are working on and ended up using Matrix function.
Whatever the images I was taking, it was all landscape, so in app I just applied the below code, and it worked well:-
Matrix matrix = new Matrix();
//set image rotation value to 90 degrees in matrix.
matrix.postRotate(90);
//supply the original width and height, if you don't want to change the height and width of //bitmap.
Bitmap bMapRotate = Bitmap.createBitmap(bMap, 0, 0, newWidth, newHeight, matrix, true);
its below code is work for me ..
File imageFile = new File(string_path); //add path here
ExifInterface exif = null;
try {
exif = new ExifInterface(imageFile.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
}
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
int rotate = 0;
switch (orientation) {
case ORIENTATION_ROTATE_270:
rotate = 270;
break;
case ORIENTATION_ROTATE_180:
rotate = 180;
break;
case ORIENTATION_ROTATE_90:
rotate = 90;
break;
}
Matrix matrix = new Matrix();
matrix.postRotate(rotate);
this.btmap = Bitmap.createBitmap(this.btmap, 0, 0, this.btmap.getWidth(), this.btmap.getHeight(), matrix, true);
Glide.with(this).load(this.btmap).into((ImageView) getActivity().findViewById(R.id.btnimg));
How to pick an image from gallery (SD Card) for my app?
I have implemented the second answer (With the downsampling). When I select an image in portrait, the image will be shown in landscape mode.. Does anybody know why this is? And how to fix this? Thanks in advance!
P.s. Sorry I've made a new topic out of this but the poster protected his topic against newbies like me :)
You have to get the exif rotation of the pic, like this and arrange youur bitmap accordingly
public static int getExifRotation(String imgPath)
{
try
{
ExifInterface exif = new ExifInterface(imgPath);
String rotationAmount = exif.getAttribute(ExifInterface.TAG_ORIENTATION);
if (!TextUtils.isEmpty(rotationAmount))
{
int rotationParam = Integer.parseInt(rotationAmount);
switch (rotationParam)
{
case ExifInterface.ORIENTATION_NORMAL:
return 0;
case ExifInterface.ORIENTATION_ROTATE_90:
return 90;
case ExifInterface.ORIENTATION_ROTATE_180:
return 180;
case ExifInterface.ORIENTATION_ROTATE_270:
return 270;
default:
return 0;
}
}
else
{
return 0;
}
}
catch (Exception ex)
{
return 0;
}
}
get the path of the picture
public String getPath(Uri uri) {
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(uri, projection, null, null, null);
int column_index = cursor
.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
Thin make a matrix and use bitmap constructor that uses matrix
Matrix matrix = new Matrix();
matrix.preRotate(90);
// or
matrix.postRotate(90);
so inside your onActivityResult you should have something like this
Uri selectedImageUri = data.getData();
selectedImagePath = getPath(selectedImageUri);
orientation = getExifRotation(selectedImagePath);
Matrix matrix = new Matrix();
matrix.postRotate(90);
if(orientation == 90){
bitmap = Bitmap.createBitmap(bitmap, 0, 0,
bitmap.getWidth(), bitmap.getHeight(),
matrix, true);}
make sure you resample your image first though, so how he has it in his answer first and then do this
I've looked into figuring out how to set the size of a picture, and I stumbled upon CameraParameters and the setPictureSize method associated with it. The problem is, I can't figure out how to use any of these. I don't know what needs to be imported, what object to create, how to use the setPictureSize method, or where to even place that code. I have 2 chunks of code that I feel may be a good place to use setPictureSize. These chunks are:
takePicture = (Button) findViewById(R.id.takePicture);
takePicture.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (name.getText().length() == 0 || experimentInput.getText().length() == 0) {
showDialog(DIALOG_REJECT);
return;
}
ContentValues values = new ContentValues();
imageUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
time = getTime() ;
startActivityForResult(intent, CAMERA_PIC_REQUESTED);
}
});
and:
public static File convertImageUriToFile (Uri imageUri, Activity activity) {
if (activity == null) Log.d("test", "NULL!");
Cursor cursor = null;
try {
String [] proj={MediaStore.Images.Media.DATA, MediaStore.Images.Media._ID, MediaStore.Images.ImageColumns.ORIENTATION};
cursor = activity.managedQuery( imageUri,
proj, // Which columns to return
null, // WHERE clause; which rows to return (all rows)
null, // WHERE clause selection arguments (none)
null); // Order-by clause (ascending by name)
int file_ColumnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
int orientation_ColumnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.ORIENTATION);
if (cursor.moveToFirst()) {
#SuppressWarnings("unused")
String orientation = cursor.getString(orientation_ColumnIndex);
return new File(cursor.getString(file_ColumnIndex));
}
return null;
} finally {
if (cursor != null) {
cursor.close();
}
}
}
public String getPath(Uri uri) {
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(uri, projection, null, null, null);
if(cursor!=null)
{
//HERE YOU WILL GET A NULLPOINTER IF CURSOR IS NULL
//THIS CAN BE, IF YOU USED OI FILE MANAGER FOR PICKING THE MEDIA
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
else return null;
}
So, my question is, how do I use setPictureSize and where should I put it? No website, nor the android development guide, nor any other related StackOverflow question was helpful to me.
Editted Code:
public Bitmap getPath(Uri uri) {
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(uri, projection, null, null, null);
if(cursor!=null)
{
//HERE YOU WILL GET A NULLPOINTER IF CURSOR IS NULL
//THIS CAN BE, IF YOU USED OI FILE MANAGER FOR PICKING THE MEDIA
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
int desiredImageWidth = 100; // pixels
int desiredImageHeight = 100; // pixels
BitmapFactory.Options o = new BitmapFactory.Options();
o.inSampleSize = 2; // will cut the size of the image in half; OPTIONAL
Bitmap newImage = Bitmap.createScaledBitmap(BitmapFactory.decodeFile(cursor.getString(column_index), o),
desiredImageWidth,
desiredImageHeight,
false);
return newImage; //cursor.getString(column_index);
}
else return null;
}
That's used for when you're actually using the camera through a custom View. What you're doing right here is sending an implicit intent to Android to open another Activity that uses the camera to take a picture.
In this case, you can limit the size of your image by using MediaStore.EXTRA_SIZE_LIMIT. If you want to specify the dimensions of the image, than you have to load it from the URI that it was saved to, create a new scaled image, then resave it over the old one.
Once you have the URI of the image (which is from the DATA attribute in the projection), you can resize the image like so:
int desiredImageWidth = 100; // pixels
int desiredImageHeight = 100; // pixels
BitmapFactory.Options o = new BitmapFactory.Options();
o.inSampleSize = 2; // will cut the size of the image in half; OPTIONAL
Bitmap newImage = Bitmap.createScaleBitmap(BitmapFactory.decodeFile(imagePath, o),
desiredImageWidth,
desiredImageHeight,
false);
Then save it over the old one.