So i am trying to load a bunch of thumbnails (possibly up to 100+) from the web, and I seem to be running out of memory around 30 on the emulator, and around 80-85 on the phone itself.
This is not going to work but there has to be a way-
I even tried saving the images to cache memory and loading from there, but it still runs out of memory.
What is the correct way to load a lot of web thumbnail images?
each image is about 50 kb, im basically adding the imageViews dynamically through a method i made called CreateImage. This pretty much loads each thumbnail based on the URL and image name, and sets it in a dynamic imageView in a horizontalScollView.
private void createImages(String URL, String imageName){
ImageView ImageThumbnails = new ImageView(this);
ImageThumbnails.setId(ImageThumbName);
ImageThumbnails.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
ImageThumbnails.getLayoutParams().height = 85;
ImageThumbnails.getLayoutParams().width = 85;
ImageThumbnails.setPadding(4, 4, 4, 4);
ImageThumbnails.setScaleType(ImageView.ScaleType.FIT_XY);
ImageThumbnails.setOnClickListener(this);
String path = Environment.getExternalStorageDirectory()+ "/" + imageName;
File imgFile = new File(path);
if(imgFile.exists())
{
Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
Bitmap bmpCompressed = Bitmap.createScaledBitmap(myBitmap, 85, 85, true);
ImageThumbnails.setImageBitmap(bmpCompressed);
}
ll.addView(ImageThumbnails);
}
Thanks in advance,
You should read those articles on the Android portal that explain exactly how to do it and provide the code:
Displaying bitmaps: http://developer.android.com/training/displaying-bitmaps/index.html
Loading large bitmaps: http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
Use AsyncTask to download each image individually and save it to disk (individually). Thats what I did for 30+ images for a Magazine App.
I think your problem will be solved with lazy list adapter. Try this example LazyList
Related
I need to download images from server and store as thumbnails directly.
and for display images also i need to use images from .thumbnails folder directly. i am not getting how to create and save images as .thumbnail . and how to use images from that .thumbnail file.i searched online but everywhere only this below code present.
Bitmap thumb = ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(file.getPath()), width, height);
any help?
Please check below code which helps you.
Follow below steps:
Calculate the maximum possible inSampleSize that still yields an image larger than your target.
Load the image using BitmapFactory.decodeFile(file, options), passing inSampleSize as an option.
Resize to the desired dimensions using Bitmap.createScaledBitmap().
Now you have your bitmap ready and you can save it any where using the following code
Bitmap thumbnail;
File thumbnailFile = ...;
FileOutputStream fos = new FileOutputStream(thumbnailFile);
thumbnail.compress(Bitmap.CompressFormat.JPEG, 90, fos);
fos.flush();
fos.close();
hope it helps you and save your time.
Or use Glide library which store image as a full image and 1 thmbnail image which is power caching library which loads image quickly and once download image after load image from cache not from network.
Below is a Glide link please read it advantages and features and after used into your applications.
https://github.com/bumptech/glide
My application takes pictures via camera intent. How should I display their small size version in a grid view for viewing purpose. Should I create their thumbnails and store them in cache or external storage Or should I use the thumbnails created by Default Gallery application. My pictures are stored in external storage so I am expecting that Default Gallery Application would make their thumbnails automatically. If yes, then how should I map each image with the thumbnail created by Default Gallery Application.
Well, I have found that Async class could handle the memory usage scenario.
The relevant link is: http://developer.android.com/intl/es/reference/android/os/AsyncTask.html
Well, I have got an answer
public Bitmap getbitpam(String path) {
Bitmap imgthumBitmap = null;
try {
final int THUMBNAIL_SIZE =300 ;
FileInputStream fis = new FileInputStream(path);
imgthumBitmap = BitmapFactory.decodeStream(fis);
imgthumBitmap = Bitmap.createScaledBitmap(imgthumBitmap,
THUMBNAIL_SIZE, THUMBNAIL_SIZE, false);
ByteArrayOutputStream bytearroutstream = new ByteArrayOutputStream();
imgthumBitmap.compress(Bitmap.CompressFormat.JPEG, 100, bytearroutstream);
} catch (Exception ex) {
}
return imgthumBitmap;
}
However, this is taking a lot of RAM. I Have also found a strange behavior. That as I am scrolling in grid view, it is taking more RAM. The growth in memory used is cumulative and finally the app is crashing due to Memory_Low exception. Any workaround for it??
Got answer for second problem too:-- Async class.
It seems the answers I searched online (including stackoverflow.com) get the image file id through gallery selection.
I have created my own file explorer.
Then how to do that?
I can create my own small size image; but I think it would be faster if we can make use of an exisiting thumbnail; and if it does not exist, I would prefer to create a thumbnail that is saved for later use.
[Update:]
OK, thanks for advice. So I will not create a thumbnail in the device, to avoid to use too much space.
Then is is better to do two steps:
Step 1: look for an exisiting thumbnail for the image file if it exists.
Step 2: if no thumbnail exists, then create my own small size bitmap (not save the it).
Then how to do Step 1, if I do not use the Gallery intent?
[Update 2:]
I also want to get the thumbnail of a video file.
I can use MediaMetadataRetriever to get a frame at any point of time, and rescale the image to a thumbnail. But I find it is very slow: I have 4 video files in the folder, and I can sense the delay.
So I think the better way to retrieve an existing thumbnail.
If I only know the file path and file name, how can I get it?
I think this question is the same as my original one, just it has more sense to do so.
You shouldn't be using specific files for tumbnail, especially not creating tumbnails. What if the user has a lot of images and you store a tumbnail of each picture which gets viewed in your explorer. That would generated a whole lot of duplicated and unwanted data. The calculations from resizing the images each time overweighs the amount of data that would need to be stored.
I would suggest you have a default icon on images in the explorer and then resizing the images in a diffrent thread, replacing your default tumbnail as they are resized.
You could downsize the existing images on the fly:
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(image_path, opts);
int width = opts.outWidth;
int height = opts.outHeight;
then
opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
opts.inDither = true;
opts.inJustDecodeBounds = false;
opts.inSampleSize = (int)Math.pow(2.0,Math.floor(Math.log(scale_factor)/Math.log(2)));//for example double scale_factor=(double)width/desired_dimension;
and finally:
Bitmap bm = BitmapFactory.decodeFile(image_path,opts);
You could load in a separate thread ranges of existing files and update only those ones when needed.
You can use ThumbnailUtils. Look up the this utility method. Probably fits your need without much hassles. Creating duplicate downsized images is a bad design as that it will end up unnecessary data.
Bitmap resizedImage = ThumbnailUtils.extractThumbnail(rescaledImage, imagePixel, imagePixel);
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();
Here I am storing all image paths into database. In TabHost, If i click FIND tab all images should be displayed. At that time OutOfMemoryError is coming. Please help me.
It is very important for me.
Image s = pictures.get(i);
TableRow imageTableRow = new TableRow(ctx);
imageTableRow.setLayoutParams(new TableLayout.LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));
ImageView imageView = new ImageView(ctx);
Log.i("NEVERFORGET","PICTURE IMAGE PATH is : " + s.getimagePath());
Drawable d = Drawable.createFromPath(s.getimagePath());
imageView.setImageDrawable(d);
imageView.setId(i);
imageView.setLayoutParams(new TableRow.LayoutParams(100,100));
imageView.setPadding(0, 10, 0, 15);
Don't use Drawable.createFromPath() as that is bound to load images at their native resolution. Doubtless these are large images, photos etc, and will therefore require vast amounts of memory once decompressed, and hence your OOM errors. Even if you're then asking them to render into a small box, they are probably fully-sized in memory.
You should instead use BitmapFactory.decodeFile() in conjunction with a suitable choice for BitmapFactory.Options.inSampleSize.