Reputation: 960
I am working on an application, in which I need to pick an image from sd card
and show it in image view. Now I want the user to decrease/increase its width by clicking a button and then save it back to the sd card.
I have done the image picking and showing it on ui. But unable to find how to resize it.Can anyone please suggest me how to achieve it.
Upvotes: 28
Views: 32861
Reputation: 2940
Here my static method:
public static void resizeImageFile(File originalImageFile, File resizedImageFile, int maxSize) {
Bitmap bitmap = BitmapFactory.decodeFile(originalImageFile.getAbsolutePath());
Bitmap resizedBitmap;
if (bitmap.getWidth() > bitmap.getHeight()) {
resizedBitmap = Bitmap.createScaledBitmap(bitmap, maxSize, maxSize * bitmap.getHeight() / bitmap.getWidth(), false);
} else {
resizedBitmap = Bitmap.createScaledBitmap(bitmap, maxSize * bitmap.getWidth() / bitmap.getHeight(), maxSize, false);
}
FileOutputStream fileOutputStream;
try {
fileOutputStream = new FileOutputStream(resizedImageFile);
resizedBitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
fileOutputStream.flush();
fileOutputStream.close();
bitmap.recycle();
resizedBitmap.recycle();
} catch (Exception e) {
e.printStackTrace();
}
}
Upvotes: 1
Reputation: 830
I found this useful library for this achievement: https://github.com/hkk595/Resizer
Upvotes: 1
Reputation: 11185
Solution without OutOfMemoryException
in Kotlin
fun resizeImage(file: File, scaleTo: Int = 1024) {
val bmOptions = BitmapFactory.Options()
bmOptions.inJustDecodeBounds = true
BitmapFactory.decodeFile(file.absolutePath, bmOptions)
val photoW = bmOptions.outWidth
val photoH = bmOptions.outHeight
// Determine how much to scale down the image
val scaleFactor = Math.min(photoW / scaleTo, photoH / scaleTo)
bmOptions.inJustDecodeBounds = false
bmOptions.inSampleSize = scaleFactor
val resized = BitmapFactory.decodeFile(file.absolutePath, bmOptions) ?: return
file.outputStream().use {
resized.compress(Bitmap.CompressFormat.JPEG, 75, it)
resized.recycle()
}
}
Upvotes: 13
Reputation: 15847
Just yesterday i have done this
File dir=Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
Bitmap b= BitmapFactory.decodeFile(PATH_ORIGINAL_IMAGE);
Bitmap out = Bitmap.createScaledBitmap(b, 320, 480, false);
File file = new File(dir, "resize.png");
FileOutputStream fOut;
try {
fOut = new FileOutputStream(file);
out.compress(Bitmap.CompressFormat.PNG, 100, fOut);
fOut.flush();
fOut.close();
b.recycle();
out.recycle();
} catch (Exception e) {}
Also don't forget to recycle your bitmaps
: It will save memory.
You can also get path of new created file String: newPath=file.getAbsolutePath();
Upvotes: 51
Reputation: 9182
You should ideally use multitouch instead of using a button to increase/decrease width. Here's an amazing library. Once the user decides to save the image, the image translation matrix must be stored persistently (in your sqlite database). Next time the user opens the image, you need to recall the matrix and apply it to your image.
I've actually done this before.
Upvotes: 0
Reputation: 2571
You can use Bitmap.createScaledBitmap (Bitmap src, int dstWidth, int dstHeight, boolean filter)
Upvotes: 1
Reputation: 15973
Try using this method:
public static Bitmap scaleBitmap(Bitmap bitmapToScale, float newWidth, float newHeight) {
if(bitmapToScale == null)
return null;
//get the original width and height
int width = bitmapToScale.getWidth();
int height = bitmapToScale.getHeight();
// create a matrix for the manipulation
Matrix matrix = new Matrix();
// resize the bit map
matrix.postScale(newWidth / width, newHeight / height);
// recreate the new Bitmap and set it back
return Bitmap.createBitmap(bitmapToScale, 0, 0, bitmapToScale.getWidth(), bitmapToScale.getHeight(), matrix, true);
}
Upvotes: 3