Loading Bitmap Efficiently in Android - android

I have dug insanely deep into this topic and found out a lot of options that makes the bitmap loading easier. But what I want to achieve is a lil far-fetched. I have referred this [video] which helps in loading the bitmaps efficiently. My question is unique cause I am able to load n number of bitmap images without any glitches but the problem is that it loads the SAME image1.
CODE :
for(int i=0;i<10;i++)
{
...
in = httpConn.getInputStream();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
options.inJustDecodeBounds = false;
options.inBitmap = image;
options.inSampleSize = 1;
image = BitmapFactory.decodeStream(in,null,options);
item = new RowItem(image, product_name, cost,product_id, dream_status,username); --> item is an object of holder class which has get and set methods
rowItems.add(item); --> this is an arraylist object of type holder class
}
Here I have a loop that loads 10 images from WebService, and I am setting it in a adapter at onPostExecute of an async task. When I loop through the 10 images, what happens to me is that, only the last image(10th image) gets set in the view and it gets repeated for all the 10 images. This is due to the following line :
options.inBitmap = image;
which recycles the bitmap. My question here is that, how can I use the inBitmap function and set all the images ? I mean the logic or loop that would let me set not only the 10th image but all the other images. Any help would be highly appreciated guys.I'll be happy to help if you guys have any queries.
NOTE : I am well aware of the fact that inSampleSize should always be set in powers of 2 but setting it to 2 reduces the size of my image and setting it to 1 is what meets my expectation.

I suggest creating a BitmapPool class to smarten up the way you cache and re-use bitmaps. In your example, this pool could start off with a size of 10, and will cache 10 bitmaps. The pool size can grow or shrink depending on the implementation.
you may request a bitmap from this Pool, via getBitmap(), and
Bitmap obtained via getBitmap() call can be used as "inBitmap" while decoding the image
you may return the bitmap back to the pool once you are done using/drawing its contents via returnBitmap()
You can extend the use of BitmapPool to facilitate other bitmap requests in your app.

Related

Android- BitmapFactory.decodeFile makes my app slowly

I'm writing app with ActionBar Tabs and ViewPager. I have two tabs and two pages. First page is just Fragmet and second is ListFragment.
In first page i'm inverting infromations about plat like name, interval between water, photo etc. I can add default photo (from resources) and take photo of plant. Then i save photo's data in database like String in two ways: id of image from resources or path to saved photo.
In second page (ListFragment) is ListView with custom adapter and there is the problem.
One row of list contains two TextViews, CheckBox and ImageView.
In method getView of my custom adapter every line works fine, but decoding file to bitmap takes lot of time and it makes my app alowly, even after decoding all photos.
It's my code to set up an image in each list row:
private void setUpImage(int position, ImageView photo)
{
if(plants.get(position).getPhoto().contains("jpg"))
{
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 10;
Bitmap bitmap = BitmapFactory.decodeFile(plants.get(position).getPhoto(), options);
photo.setImageBitmap(bitmap);
}
else
{
photo.setImageResource(Integer.parseInt(plants.get(position).getPhoto()));
}
}
Do anyone know how to improve speed of decoding and seting image in each list row of my ListView?
First of all! Setting options.inSampleSize = 10; is much greater. Normally, inSampleSize is provided in power of 2. And setting it equal to 2 or 4 is ok.
You can decode your file in background thread or you can use Lazy Loading techniques.
You can get Lazy Loading code here. See this answer.

Android ListView showing images results in out of memory

Okay,
I have what I think is an odd problem.
I load photos into a list view as the user scroll (meaning if picked up from disk or online, it takes a little time and they "pop in")
1)
I ensure that I only fetch one image online + resize to 1/3 width at a time (a lock) -- this is to ensure not e.g. 5 threads each are converting a .jpg to bitmap at the same time. (Imagine a user scrolling very fast, it would then be conceivable this could happen.)
2)
All images on disk are only 1/3 width
3)
While the bitmaps are scaled up to fit device width, I call recycle and set bitmaps to null when used in the getView. (I am converting bitmaps to a BitmapDrawable object which the listitem imageview uses in a setImageDrawable call)
4)
I reuse view in getView if not null
5)
I load bitmaps like this:
BitmapFactory.Options o = new BitmapFactory.Options();
o.inPurgeable = false; // I do not use this since I resize/scale down images myself later
o.inInputShareable = false;
o.inPreferredConfig = Config.RGB_565;
res.bitmap = BitmapFactory.decodeStream(is, null, o);
6)
I also clean scrap items
public void onMovedToScrapHeap(View view) {
final TextView description = (TextView)view.findViewById(R.id.listitem_news_content);
description.setText("");
final ImageView image = (ImageView)view.findViewById(R.id.listitem_news_image);
image.setImageBitmap(null);
}
I am testing on a Samsung Galaxy II. Do you guys have any ideas on what more I could try? Since I only max need to show 10 items, I would think it should be possible...
Try using widely used library Universal Image Loader https://github.com/nostra13/Android-Universal-Image-Loader
It is simple and straight forward and you will never have to care about decoding images yourself.
Option two: There's a powerful new API for loading image is available from the team of Square http://square.github.io/picasso/
Try this, it worked for me in case of OutOfMemory...using System.gc()
bitmap = null;
imageView.setImageBitmap(null);
System.gc();

How to speed up loading images as small previews?

I have 3 or 4 image paths that I use to load an image so I set it to an imageview. Why does it take long? Or better asking is there a way to make it faster? At the end of the day I am loading to fit an imageview of less than 60 dp hight and width
Uri mainImgeUri = Uri.parse(imagePath);
InputStream imageStream;
try {
imageStream = mActiviy.getContentResolver().openInputStream(mainImgeUri);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap yourSelectedImage = BitmapFactory.decodeStream(imageStream, null, options);
mainImageIV.setImageBitmap(yourSelectedImage);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
USE CASE:
What happens is that a user will add 5 images (and he get to choose them from Gallery which is mostly taken by phone camera). He hit save and my app stores the path to them in an sqlite database. Then when the user opens the app again to see them, my app query the db to get the paths to all the images and executes the code above x number of times so all the image views are loaded with the intended images
Take a look at http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
It explains how to calculate the correct inSampleSize based on the required dimensions of the output image. It also explains how to reference large bitmaps without having to load all their pixel data into memory.
The idea is that you resample bigger images and only load the smaller ones into memory making the whole process much more efficient. The example code is accessing a bitmap from resources, but this can easily be modified for your needs.
The important things to look out for in the example are inJustDecodeBounds and calculateInSampleSize.

Android LiveWallpaper: load and draw various bitmaps efficiently (example: video)

I am developing a live wallpaper that reproduces an animation (like a short video) on background.
Does anyone know how to efficiently load various full screen size bitmaps and draw them on canvas?
I have tried 2 approaches and both are not very good.
Approach #1:
Load all bitmaps on wallpaper startup.
Problem: Memory excess limit (about 35MB) cant load more than 10 bitmaps. So animations lack of different images.
Approach #2:
Load only 2 bitmaps. On run time, paint bitmap, delete old bitmap, load new bitmap, repeat.
Problem: Consumes a lot of the system, (not memory, but slows down os in general), however it works because it doesn't exceed memory limit. But still, slows down the entire system.
example:
Drawer.drawAll(res,c,p);
res.removeOldBitmaps();
res.loadNewBitmaps(wpservice,display);
A different approach i thought about is load resource on a separete thread, what do you guys think of that? do you have any other solutions?
Cheers!
Solved, the solution I found was the following:
Load images on runtime, 1 by 1.
And use this options:
/**Effective image decoder by chelin**/
public static Bitmap decodeResource(WallpaperService wpservice,int id){
int scale=1;
Resources res = wpservice.getResources();
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inPreferredConfig = Bitmap.Config.ARGB_8888;
o2.inSampleSize=scale;
o2.inPurgeable = true;
o2.inInputShareable = true;
return BitmapFactory.decodeResource(res, id, o2);
}
Hope it works as it worked for me. Cheers!

android how to load/save original size Bitmap with no OutOfMemory

I read many discussions about the inSampleSize OutOfMemory dilemma.
Cannot get a good solution so i ask a question about it.
Im currently loading a bitmap with inSampleSize=4.
That will give me a Bitmap with the size 648x388.
Original On disk size is 2592x1592.
Im writing text on 648x388 bitmap and saving it back to disk.
Im writing on the 648x388 because the 2592x1592 give me OutOfMemory .
The way it works is that there can be 1-10 648x388 Bitmaps to be saved in a while loop.
I want to change this loop to save 1-10 2592x1592 Bitmaps.
How can i securely load the 2592x1592?
I don care about the resolution going down 60% or more.
As long as the Bitmap has the same size 2592x1592.
Is there a way to maybe keep the size but make Bitmap thinner,
removing color without making quality bad.
My first thought was going something like this to get the biggest bitmap i could get:
I have not tested this but get a feeling it's a bad way
boolean work = true;
int insample = 2;
BitmapFactory.Options options = new BitmapFactory.Options();
while(work){
try{
options.inSampleSize = insample;
bitmap = BitmapFactory.decodeFile(filePath,options);
work = false;
}catch(Exception e){
insample++;
}
}
any help would be grate.
Image processing requires a lot of memory. you cant use the whole bitmap and just modify it on your phone. use a web service for that. upload, process, download. sorry there is no other way a decoded bitmap just takes a lot of memory.
And by the way you cant catch an outOFMemory Exception. the app just crashes.
There's a hard limit on process size in Android and a 4 mega-pixel image at four bytes a pixel will hit it all by itself (on many devices), without any room for your program.
I think you are going to need to do one of two things: Create a web service to do the image processing on a server/in the cloud; or learn to do your image processing "on-the-fly" by manipulating the data directly instead of using a bitmap.

Categories

Resources