How to decrease image size without losing its quality in android.
I have a ImageView in my project,I have to put a larger size image in it.
I am new to android.
please help.

- 3,826
- 25
- 25

- 782
- 1
- 6
- 10
-
1I have used cropping. but. Cropping an image damages its quality..after cropping i can add image to the to imageview.but it reduces the quality of the image..but when i am taking larger image..the image is not showing.. – Mainak Mukherjee Feb 10 '15 at 05:54
-
Now how can i decrease image size withou losing its quality..Can any one provide some sample code..plzz help..thanks in advance.. – Mainak Mukherjee Feb 10 '15 at 05:56
-
This will do it. -> Bitmap.createScaledBitmap(original, (int) toWidth, (int) newHeight, false); – Vijay May 27 '21 at 06:55
6 Answers
Below code Working for scale image as aspect ratio:
Bitmap bitmapImage = BitmapFactory.decodeFile("Your path");
int nh = (int) ( bitmapImage.getHeight() * (512.0 / bitmapImage.getWidth()) );
Bitmap scaled = Bitmap.createScaledBitmap(bitmapImage, 512, nh, true);
your_imageview.setImageBitmap(scaled);
Compress your image without losing quality like whatsapp
public String compressImage(String imageUri) {
String filePath = getRealPathFromURI(imageUri);
Bitmap scaledBitmap = null;
BitmapFactory.Options options = new BitmapFactory.Options();
// by setting this field as true, the actual bitmap pixels are not loaded in the memory. Just the bounds are loaded. If
// you try the use the bitmap here, you will get null.
options.inJustDecodeBounds = true;
Bitmap bmp = BitmapFactory.decodeFile(filePath, options);
int actualHeight = options.outHeight;
int actualWidth = options.outWidth;
// max Height and width values of the compressed image is taken as 816x612
float maxHeight = 816.0f;
float maxWidth = 612.0f;
float imgRatio = actualWidth / actualHeight;
float maxRatio = maxWidth / maxHeight;
// width and height values are set maintaining the aspect ratio of the image
if (actualHeight > maxHeight || actualWidth > maxWidth) {
if (imgRatio < maxRatio) {
imgRatio = maxHeight / actualHeight;
actualWidth = (int) (imgRatio * actualWidth);
actualHeight = (int) maxHeight;
} else if (imgRatio > maxRatio) {
imgRatio = maxWidth / actualWidth;
actualHeight = (int) (imgRatio * actualHeight);
actualWidth = (int) maxWidth;
} else {
actualHeight = (int) maxHeight;
actualWidth = (int) maxWidth;
}
}
// setting inSampleSize value allows to load a scaled down version of the original image
options.inSampleSize = calculateInSampleSize(options, actualWidth, actualHeight);
// inJustDecodeBounds set to false to load the actual bitmap
options.inJustDecodeBounds = false;
// this options allow android to claim the bitmap memory if it runs low on memory
options.inPurgeable = true;
options.inInputShareable = true;
options.inTempStorage = new byte[16 * 1024];
try {
// load the bitmap from its path
bmp = BitmapFactory.decodeFile(filePath, options);
} catch (OutOfMemoryError exception) {
exception.printStackTrace();
}
try {
scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.ARGB_8888);
} catch (OutOfMemoryError exception) {
exception.printStackTrace();
}
float ratioX = actualWidth / (float) options.outWidth;
float ratioY = actualHeight / (float) options.outHeight;
float middleX = actualWidth / 2.0f;
float middleY = actualHeight / 2.0f;
Matrix scaleMatrix = new Matrix();
scaleMatrix.setScale(ratioX, ratioY, middleX, middleY);
Canvas canvas = new Canvas(scaledBitmap);
canvas.setMatrix(scaleMatrix);
canvas.drawBitmap(bmp, middleX - bmp.getWidth() / 2, middleY - bmp.getHeight() / 2, new Paint(Paint.FILTER_BITMAP_FLAG));
// check the rotation of the image and display it properly
ExifInterface exif;
try {
exif = new ExifInterface(filePath);
int orientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION, 0);
Log.d("EXIF", "Exif: " + orientation);
Matrix matrix = new Matrix();
if (orientation == 6) {
matrix.postRotate(90);
Log.d("EXIF", "Exif: " + orientation);
} else if (orientation == 3) {
matrix.postRotate(180);
Log.d("EXIF", "Exif: " + orientation);
} else if (orientation == 8) {
matrix.postRotate(270);
Log.d("EXIF", "Exif: " + orientation);
}
scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0,
scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix,
true);
} catch (IOException e) {
e.printStackTrace();
}
FileOutputStream out = null;
String filename = getFilename();
try {
out = new FileOutputStream(filename);
// write the compressed bitmap at the destination specified by filename.
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return filename;
}
public String getFilename() {
File file = new File(Environment.getExternalStorageDirectory().getPath(), "MyFolder/Images");
if (!file.exists()) {
file.mkdirs();
}
String uriSting = (file.getAbsolutePath() + "/" + System.currentTimeMillis() + ".jpg");
return uriSting;
}
private String getRealPathFromURI(String contentURI) {
Uri contentUri = Uri.parse(contentURI);
Cursor cursor = getContentResolver().query(contentUri, null, null, null, null);
if (cursor == null) {
return contentUri.getPath();
} else {
cursor.moveToFirst();
int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
return cursor.getString(index);
}
}
public int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
final float totalPixels = width * height;
final float totalReqPixelsCap = reqWidth * reqHeight * 2;
while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
inSampleSize++;
}
return inSampleSize;
}

- 1,994
- 1
- 13
- 12
-
1@Jitty Aandyan How your code will react if image sizes and dimentions are too small or to large...And why 816x612 is hard coded can we calculate it programatically – Akshay Mar 25 '15 at 13:50
-
2basically the above code is used to reduce the size of images with maintaining the aspect ratio. most important is every images should have particular height and width these are defined by the requirements of your app. if you are using high quality images for profile pic you can change the max height max width to 300, so its respect to your implementaion. And also you can check actual height and width before compressing if it is greater than your requirement you can do the compression. – Jitty Aandyan Mar 27 '15 at 07:52
-
How to make it Dynamic for all size of Images, and for all devices with different resolution,, – Akshay Sep 01 '15 at 12:23
-
1@JittyAandyan It is working perfectly fine for the gallery images. but if I try to reduce the camera image, it will distort the picture quality and make a very small image. Any idea how to solve this? – Zeeshan Ahmed Mar 10 '16 at 07:35
-
worked perfectly @JittyAandyan, even camera images are getting compressed, quality difference is 80%, but size is gettin reduced to 50% of the original one, helped me alot while sending images to server after converting them into base64 string.. – Yogesh Patel Sep 17 '16 at 11:36
-
2look like you have mistake: `float imgRatio = (float) actualWidth / (float) actualHeight;` – ViT-Vetal- Mar 28 '17 at 10:22
-
3The code works well for portrait images `(actualWidth < actualHeight)` but for landscape images the two `(imgRatio vs maxRatio)` comparisons need to be inverted. – andreaciri Dec 09 '17 at 11:15
-
-
-
how to pass compressed image `filepath` to firebase image upload `imageRef.put(filepath)` in whatsapp method? – Phaneendra Charyulu Kanduri Mar 31 '19 at 20:04
-
After select image from gallery, why it reduces the actual image size. e.g suppose i select image 5MB image from gallery, after using this code it reduces to 200KB. it's fine, but why it also changes gallery actual image size to 200KB . Can any one explain please – Navjot.jassal Apr 29 '19 at 19:43
-
options.inPurgeable & options.inInputShareable is deprecated so instead of options.inPurgeable = true; options.inInputShareable = true; use options.inBitmap = bmp; – Nilesh Rathore Aug 05 '19 at 10:18
-
i got errer 'width and height must be > 0' in scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.ARGB_8888); please help me sir... – John dahat Jun 23 '20 at 08:42
Create Class For CompressFile Image
public class CompressFile {
public static File getCompressedImageFile(File file, Context mContext) {
try {
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
if (getFileExt(file.getName()).equals("png") || getFileExt(file.getName()).equals("PNG")) {
o.inSampleSize = 6;
} else {
o.inSampleSize = 6;
}
FileInputStream inputStream = new FileInputStream(file);
BitmapFactory.decodeStream(inputStream, null, o);
inputStream.close();
// The new size we want to scale to
final int REQUIRED_SIZE = 100;
// Find the correct scale value. It should be the power of 2.
int scale = 1;
while (o.outWidth / scale / 2 >= REQUIRED_SIZE &&
o.outHeight / scale / 2 >= REQUIRED_SIZE) {
scale *= 2;
}
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
inputStream = new FileInputStream(file);
Bitmap selectedBitmap = BitmapFactory.decodeStream(inputStream, null, o2);
ExifInterface ei = new ExifInterface(file.getAbsolutePath());
int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_UNDEFINED);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
selectedBitmap = rotateImage(selectedBitmap, 90);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
selectedBitmap = rotateImage(selectedBitmap, 180);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
selectedBitmap = rotateImage(selectedBitmap, 270);
break;
case ExifInterface.ORIENTATION_NORMAL:
default:
break;
}
inputStream.close();
// here i override the original image file
File folder = new File(Environment.getExternalStorageDirectory() + "/FolderName");
boolean success = true;
if (!folder.exists()) {
success = folder.mkdir();
}
if (success) {
File newFile = new File(new File(folder.getAbsolutePath()), file.getName());
if (newFile.exists()) {
newFile.delete();
}
FileOutputStream outputStream = new FileOutputStream(newFile);
if (getFileExt(file.getName()).equals("png") || getFileExt(file.getName()).equals("PNG")) {
selectedBitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
} else {
selectedBitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
}
return newFile;
} else {
return null;
}
} catch (Exception e) {
return null;
}
}
public static String getFileExt(String fileName) {
return fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());
}
public static Bitmap rotateImage(Bitmap source, float angle) {
Matrix matrix = new Matrix();
matrix.postRotate(angle);
return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(),
matrix, true);
}
}

- 543
- 7
- 14
Use this code for compress bitmap in lower size.
BitmapFactory.Options Options = new BitmapFactory.Options();
Options.inSampleSize = 4;
Options.inJustDecodeBounds = false;
action_bitmap = BitmapFactory.decodeFile(Glob.savedImage, Options);
Glob.savedImage is String path of image.

- 2,492
- 2
- 13
- 16
// we'll start with the original picture already open to a file
File imgFileOrig = getPic(); //change "getPic()" for whatever you need to open the image file.
Bitmap b = BitmapFactory.decodeFile(imgFileOrig.getAbsolutePath());
// original measurements
int origWidth = b.getWidth();
int origHeight = b.getHeight();
final int destWidth = 600;//or the width you need
if(origWidth > destWidth){
// picture is wider than we want it, we calculate its target height
int destHeight = origHeight/( origWidth / destWidth ) ;
// we create an scaled bitmap so it reduces the image, not just trim it
Bitmap b2 = Bitmap.createScaledBitmap(b, destWidth, destHeight, false);
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
// compress to the format you want, JPEG, PNG...
// 70 is the 0-100 quality percentage
b2.compress(Bitmap.CompressFormat.JPEG,70 , outStream);
// we save the file, at least until we have made use of it
File f = new File(Environment.getExternalStorageDirectory()
+ File.separator + "test.jpg");
f.createNewFile();
//write the bytes in file
FileOutputStream fo = new FileOutputStream(f);
fo.write(outStream.toByteArray());
// remember close de FileOutput
fo.close();
}

- 827
- 10
- 10
The accepted answer works fine when grabbing an image from gallery, but when trying to get an image from the file manager, it fails. The reason is that the Uri has a different format that getRealPathFromURI(imageUri)
doesn't manage to get the real path from it.
In order to solve this issue, use the same methods of the accepted answer except for copressImage()
& getRealPathFromURI()
which are tweaked to support both images grabbed from file manger & gallery:
public static String compressImage(Context context, Uri uri) {
String filePath = getRealPathFromURI(context, uri);
Bitmap scaledBitmap = null;
BitmapFactory.Options options = new BitmapFactory.Options();
// by setting this field as true, the actual bitmap pixels are not loaded in the memory. Just the bounds are loaded. If
// you try the use the bitmap here, you will get null.
options.inJustDecodeBounds = true;
Bitmap bmp = BitmapFactory.decodeFile(filePath, options);
int actualHeight = options.outHeight;
int actualWidth = options.outWidth;
// max Height and width values of the compressed image is taken as 816x612
float maxHeight = 816.0f;
float maxWidth = 612.0f;
float imgRatio = actualWidth / actualHeight;
float maxRatio = maxWidth / maxHeight;
// width and height values are set maintaining the aspect ratio of the image
if (actualHeight > maxHeight || actualWidth > maxWidth) {
if (imgRatio < maxRatio) {
imgRatio = maxHeight / actualHeight;
actualWidth = (int) (imgRatio * actualWidth);
actualHeight = (int) maxHeight;
} else if (imgRatio > maxRatio) {
imgRatio = maxWidth / actualWidth;
actualHeight = (int) (imgRatio * actualHeight);
actualWidth = (int) maxWidth;
} else {
actualHeight = (int) maxHeight;
actualWidth = (int) maxWidth;
}
}
// setting inSampleSize value allows to load a scaled down version of the original image
options.inSampleSize = calculateInSampleSize(options, actualWidth, actualHeight);
// inJustDecodeBounds set to false to load the actual bitmap
options.inJustDecodeBounds = false;
// this options allow android to claim the bitmap memory if it runs low on memory
options.inPurgeable = true;
options.inInputShareable = true;
options.inTempStorage = new byte[16 * 1024];
try {
// load the bitmap from its path
bmp = BitmapFactory.decodeFile(filePath, options);
} catch (OutOfMemoryError exception) {
exception.printStackTrace();
}
try {
scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.ARGB_8888);
} catch (OutOfMemoryError exception) {
exception.printStackTrace();
}
float ratioX = actualWidth / (float) options.outWidth;
float ratioY = actualHeight / (float) options.outHeight;
float middleX = actualWidth / 2.0f;
float middleY = actualHeight / 2.0f;
Matrix scaleMatrix = new Matrix();
scaleMatrix.setScale(ratioX, ratioY, middleX, middleY);
Canvas canvas = new Canvas(scaledBitmap);
canvas.setMatrix(scaleMatrix);
canvas.drawBitmap(bmp, middleX - bmp.getWidth() / 2, middleY - bmp.getHeight() / 2, new Paint(Paint.FILTER_BITMAP_FLAG));
// check the rotation of the image and display it properly
ExifInterface exif;
try {
exif = new ExifInterface(filePath);
int orientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION, 0);
Log.d("EXIF", "Exif: " + orientation);
Matrix matrix = new Matrix();
if (orientation == 6) {
matrix.postRotate(90);
Log.d("EXIF", "Exif: " + orientation);
} else if (orientation == 3) {
matrix.postRotate(180);
Log.d("EXIF", "Exif: " + orientation);
} else if (orientation == 8) {
matrix.postRotate(270);
Log.d("EXIF", "Exif: " + orientation);
}
scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0,
scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix,
true);
} catch (IOException e) {
e.printStackTrace();
}
FileOutputStream out = null;
String filename = getFilename();
try {
out = new FileOutputStream(filename);
// write the compressed bitmap at the destination specified by filename.
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return filename;
}
public static String getRealPathFromURI(Context context, Uri uri) {
Uri queryUri = MediaStore.Files.getContentUri("external");
String columnData = MediaStore.Files.FileColumns.DATA;
String columnSize = MediaStore.Files.FileColumns.SIZE;
String[] projectionData = {MediaStore.Files.FileColumns.DATA};
String name = null;
String size = null;
Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
if ((cursor != null) && (cursor.getCount() > 0)) {
int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
int sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE);
cursor.moveToFirst();
name = cursor.getString(nameIndex);
size = cursor.getString(sizeIndex);
cursor.close();
}
String imagePath = "";
if ((name != null) && (size != null)) {
String selectionNS = columnData + " LIKE '%" + name + "' AND " + columnSize + "='" + size + "'";
Cursor cursorLike = context.getContentResolver().query(queryUri, projectionData, selectionNS, null, null);
if ((cursorLike != null) && (cursorLike.getCount() > 0)) {
cursorLike.moveToFirst();
int indexData = cursorLike.getColumnIndex(columnData);
if (cursorLike.getString(indexData) != null) {
imagePath = cursorLike.getString(indexData);
}
cursorLike.close();
}
}
return imagePath;
}

- 37,492
- 7
- 60
- 84
For Compressing image using JPEG compression and maintaining transparency like PNG use this code. It worked for me.
Bitmap newBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());
Canvas canvas = new Canvas(newBitmap);
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(bitmap, 0, 0, null);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
newBitmap.compress(Bitmap.CompressFormat.JPEG, 50, outputStream);

- 970
- 13
- 17