Reputation: 782
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.
Upvotes: 68
Views: 129972
Reputation: 2004
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;
// the image's max dimention is gonna be: 512x512
float maxSize = 512.0f;
// width and height values are set maintaining the aspect ratio of the image
float ratio = actualWidth > actualHeight ? maxSize / actualWidth : maxSize / actualHeight;
actualWidth = (int) (actualWidth * ratio);
actualHeight = (int) (actualHeight * ratio);
// 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;
}
Upvotes: 120
Reputation: 947
// 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();
}
Upvotes: 3
Reputation: 553
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);
}
}
Upvotes: 7
Reputation: 40810
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;
}
Upvotes: 2
Reputation: 2660
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.
Upvotes: 4
Reputation: 1028
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);
Upvotes: 0