I'm creating my own gallery using ViewPager, which is 'connected' to ArrayList holding paths of images to display.
So far, I use:
Bitmap bitmap = BitmapFactory.decodeFile(path);
imageView.setImageBitmap(bitmap);
imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
It's working, but the pictures are pretty big and I unnecessarily decode whole picture, because it's scaled down later to fit layout. It is slow and a crash with OutOfMemoryError happens sometimes, when I scroll fast.
So the question is:
How can I efficiently decode an image so it fits 100% with ImageView.ScaleType.CENTER_INSIDE knowing only its path?
Do not decode it directy. use inJustDecodeBounds = true from BitmapFactory.Options, to load only width and height from the Bitmap. Then you can calcuate the inSampleSize to scale your Bitmap
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
decodeFile will return null and options will contains width and height. Then you calculate the inSampleSize and:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = false;
options.inSampleSize = myInsampleSize;
Bitmap output = BitmapFactory.decodeFile(path, options);
Related
I am new to Android programming. I was trying to display an image from my device's sd card onto an ImageView, using BitmapFactory.decodeFile(imagePath). I can read the image fine from sd card, followed the official documentation to loading bitmaps efficiently. Although one thing I cannot understand is why the bitmap returned is much greater in size than the original size? Original image size was 84.32 kb, the bitmap that I got was of the size 4.096 mb. I was trying to load the bitmap with the height and width of the image, i.e. 1280x800. If I reduce the width and height of the image in the method below , I get reduced size. But why I can't load the image in bitmap with its original size and actual width and height?
Method decodeSampledBitmap():
public static Bitmap decodeSampledBitmap(String path,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
//BitmapFactory.decodeResource(res, resId, options);
BitmapFactory.decodeFile(path, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
//return BitmapFactory.decodeResource(res, resId, options);
return BitmapFactory.decodeFile(path, options);
}
The size of the image on disk has little to do with the size of the image in memory. PNG, JPEG, and GIF images are compressed on disk. In memory, they are uncompressed.
I have a drawable that I would like to render in different sizes on the fly, as opposed to setting the size in layout file. How might I do that? I am referring to the call
imageView.setImageResource(R.drawable.image);
Decode the resource as a bitmap with a resolution (and other options) specified, then tell the ImageView to show the bitmap:
BitmapFactory.Options options = new BitmapFactory.Options();
options.outHeight = XXXX;
options.outWidth = XXXX;
Bitmap bm = BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
imageView.setImageBitmap(bm);
I have taken and modified some code used to get a high quality anti-aliased small version of a larger (500x500) bitmap image. Apparently using a Matrix produces higher quality than employing createScaledBitmap(). The results were not very impressive.. and I suspected that perhaps I had made a mistake, in particularl I was unsure as to whether the options thing was actually being employed. So I changed the inSampleSize = 1; to inSampleSize = 50; expecting to see a dramatic drop in quality, but there was no change. So now I suspect options is being ignored. Can this code be rescued?
I was hoping to perhaps find some version of createBitmap which took bith a bitmap and an options argument, but could find none.
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferQualityOverSpeed = true;
options.inJustDecodeBounds = false;
options.inDither = false;
options.inSampleSize = 1;
options.inScaled = false;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bmpSource = BitmapFactory.decodeResource(getResources(), R.drawable.bigicon);
Matrix matrix = new Matrix();
matrix.postScale(.1f,.1f);
Bitmap scaledBitmap = Bitmap.createBitmap(bmpSource, 0, 0, bmpSource.getWidth(), bmpSource.getHeight(), matrix, true);
well you should actually provide it as parameter. Change
Bitmap bmpSource = BitmapFactory.decodeResource(getResources(), R.drawable.bigicon);
with
Bitmap bmpSource = BitmapFactory.decodeResource(getResources(), R.drawable.bigicon, options);
here the documentation
Take a look of this Creating a scaled bitmap with createScaledBitmap in Android
This too: http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
I want to scale down a 500x500px resource to fit always a specific size which is determined by the width of the screen.
Currently I use the code from the Android Developers Site (Loading Large Bitmaps Efficiently), but the quality is not as good as I would use the 500x500px resource in a ImageView (as source in xml) and just scale the ImageView and not the Bitmap.
But it's slow and I want to scale the Bitmap, too, to be memory efficient and fast.
Edit: The drawable which I wanna scale is in the drawable folder of my app.
Edit2: My current approaches.
The left image is the method from Loading Large Bitmaps Efficiently without any modifications. The center image is done with the method provided by #Salman Zaidi with this little modification: o.inPreferredConfig = Config.ARGB_8888; and o2.inPreferredConfig = Config.ARGB_8888;
The right image is an imageview where the image source is defined in xml and the quality I wanna reach with a scaled bitmap.
private Bitmap decodeImage(File f) {
Bitmap b = null;
try {
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
FileInputStream fis = new FileInputStream(f);
BitmapFactory.decodeStream(fis, null, o);
fis.close();
float sc = 0.0f;
int scale = 1;
//if image height is greater than width
if (o.outHeight > o.outWidth) {
sc = o.outHeight / 400;
scale = Math.round(sc);
}
//if image width is greater than height
else {
sc = o.outWidth / 400;
scale = Math.round(sc);
}
// Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
fis = new FileInputStream(f);
b = BitmapFactory.decodeStream(fis, null, o2);
fis.close();
} catch (IOException e) {
}
return b;
}
Here '400' is the new width (in case image is in portrait mode) or new height (in case image is in landscape mode). You can set the value of your own choice.. Scaled bitmap will not take much memory space..
Dudes, inSampleSize param is made for memory optimization, while loading a bitmap from resources or memory. So for your issue you should use this:
Bitmap bmp = BitmapFactory.decode...;
bmp = bmp.createScaledBitmap(bmp, 400, 400, false);
inSampleSizelets lets you to scale bitmap with descret steps. Scale ratios are 2,4 and so on. So when your use decoding with options, where inSampleSize=2 you loads a 250x250 bitmap from memory and then stretch it to 400x400
Check this training:
http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
It shows how to resize bitmaps efficiently
In my android app I capture an image from the camera, compress it to jpeg, send it to the server and save it on hdd. There it takes 48,9kb (e.g.). I send it back in a Base64-String and decode it on the Android side like this:
byte[] img;
img = Base64.decode(base64, Base64.DEFAULT);
ByteArrayInputStream in = new ByteArrayInputStream(img);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 3;
Bitmap bmp = BitmapFactory.decodeStream(in, null, options);
return bmp;
Values bigger than 3 for
options.inSampleSize
will make the image look ugly. But if i now look at the size of
bmp
it is 156kb. Why does the size increase? How can I decode it, so that it keeps its original size and doesnt look ugly (too hard downsampling)?