Reputation:
I have look at many different methods of creating a reduced size bitmap of an image, but none of them work properly / I need something different.
This is a little difficult to explain :-)
What I need is a bitmap that keeps the ratio of the picture, but is less than a certain size - eg 1mb or the equivalent in pixel dimensions (As this bitmap needs to added as a putExtra() for an intent).
Problems I'm having so far:
Most of the methods that I've looked at create a scaled version of the bitmap. So: Image -> Bitmap1 (unscaled) -> Bitmap2 (scaled). But if the resolution of the image is very high, it is not scaled down enough. I think the solution would be to create a bitmap of an exact size so that any resolution can be reduced enough.
However, the side effect of this method would be that images already less than the required size will be resized up (or the resizing won't work?). So there needs to be an "if" to check if the image can be converted to a bitmap without resizing.
I have no idea how to go about doing this so any help is very much appreciated! :-)
This is what I'm using at the moment (It does NOT do I want it to do):
// This is called when an image is picked from the gallery
@Override
public void onActivityResult(int requestCode, int resultCode,
Intent imageReturnedIntent) {
super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
switch (requestCode) {
case 0:
if (resultCode == Activity.RESULT_OK) {
selectedImage = imageReturnedIntent.getData();
viewImage = imageReturnedIntent.getData();
try {
decodeUri(selectedImage);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
iv_preview.setImageBitmap(mImageBitmap);
}
break; // The rest is unnecessary
This is the part which is currently scaling the size:
private Bitmap decodeUri(Uri selectedImage) throws FileNotFoundException {
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true; //
BitmapFactory.decodeStream(getActivity().getContentResolver()
.openInputStream(selectedImage), null, o);
// The new size we want to scale to
final int REQUIRED_SIZE = 260; // Is this kilobites? 306
// Find the correct scale value. It should be the power of 2.
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 1;
while (true) {
if (width_tmp / 2 < REQUIRED_SIZE || height_tmp / 2 < REQUIRED_SIZE) {
break;
}
width_tmp /= 2;
height_tmp /= 2;
scale *= 2;
}
// Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
o2.inScaled = false; // Better quality?
mImageBitmap = BitmapFactory.decodeStream(getActivity()
.getContentResolver().openInputStream(selectedImage), null, o2);
return BitmapFactory.decodeStream(getActivity().getContentResolver()
.openInputStream(selectedImage), null, o2);
}
If anything needs to be explained more please say.
Thank you
Upvotes: 3
Views: 9109
Reputation: 4607
How to call:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Uri selectedImage = data.getData();
String[] filePathColumn = { MediaStore.Images.Media.DATA };
Cursor cursor = getContentResolver().query(selectedImage,
filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String picturePath = cursor.getString(columnIndex);
cursor.close();
pho1.setImageBitmap(decodeSampledBitmapFromResource(picturePath,
80, 60));
Methods:
public static int calculateInSampleSize(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) {
// Calculate ratios of height and width to requested height and
// width
final int heightRatio = Math.round((float) height
/ (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
// Choose the smallest ratio as inSampleSize value, this will
// guarantee
// a final image with both dimensions larger than or equal to the
// requested height and width.
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
public static Bitmap decodeSampledBitmapFromResource(String path,
int reqWidth, int reqHeight) {
Log.d("path", path);
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth,
reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(path, options);
}
Upvotes: 2