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.
Related
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();
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
I'm intending to display very large Images in Android. My first solution - to supply them as pdf - fails because not every handheld got a pdf-viewer preinstalled, and I don't want to require the users to install one.
So I have a png now (width = 3998px height=2827px) that I want to display. I downloaded this image to test how it would be displayed the gallery. It was quite painful. It seems that the galery renders this picture only once, and if I Zoom in, I cannot read the text at all.
So I wrote a testActivity which simply has an ImageView nested in a LinearLayout. I put the image into the drawable and set it as ImageView's image-source.
Unforunately the app crashes immediatly, due to an "
ERROR/AndroidRuntime(8906): Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget"
I didn't expect that ONE single Image can be too large forVM's memory. I played a little bit around, set ImageViews size to 3998 & 2827px , put the Image to sdCard and read it manually with a fileInputStream.
To my big surprise it now shows my image, but if I turn my Nexus S horizontal I get the same OutOfMemoryError as before.
Can somewone point me the main difference between recieving a Bitmap through a FileInputStream or to set it as ImageView's source.
Also I'm not able to scroll comfortable with two parent scrollViews
I searching for a simple solution to display ONE large image at a time with the ability to scroll horizontal and vertical while able to zoom in and out.
here is a sample of the image I want to display
I know it's an old post but I spent a lot of time on this problem, so here's my solution.
I wanted to display a 2000×3000 picture but I got out of memory or the image was too large to be displayed.
To begin, I get the dimensions of the picture:
o = new BitmapFactory.Options();
o.inJustDecodeBounds=true;
pictures = BitmapFactory.decodeStream(new FileInputStream(f), null, o);
Then I cut it up into four parts and displayed them with four ImageViews.
I tried to load the full picture and cut it into four (using BitmapFactory.create(bitmap,int,int,int,int)) but got out of memory again.
So I decided to use some BitMapRegionDecoder:
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
ImageView iv = new ImageView(this);
InputStream istream = null;
try {
istream = this.getContentResolver().openInputStream(Uri.fromFile(f));
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
BitmapRegionDecoder decoder = null;
try {
decoder = BitmapRegionDecoder.newInstance(istream, false);
} catch (IOException e) {
e.printStackTrace();
}
int nw = (j*width/k);
int nh = (i*height/k);
Bitmap bMap = decoder.decodeRegion(new Rect(nw,nh, (nw+width/k),(nh+height/k)), null);
iv.setImageBitmap(bMap);
}
}
This worked.
I know its an old question but I used TileView to do exactly this:
https://github.com/moagrius/TileView
Try to use this one:
https://github.com/davemorrissey/subsampling-scale-image-view
A custom image view for Android, designed for photo galleries and
displaying huge images (e.g. maps and building plans) without
OutOfMemoryErrors. Includes pinch to zoom, panning, rotation and
animation support, and allows easy extension so you can add your own
overlays and touch event detection.
You can use this "easy to integerate" source of WorldMap application:
https://github.com/johnnylambada/WorldMap
This uses a huge image of a world map, and uses cache to display a map.
To integerate, I just copied all the java files (5 i guess) and used the surfaceView in my layout file. Then I went through the small OnCreate() method of ImageViewerActivity.java and used the code in my activity (with sligh alteration, depending on my personal use).
This post is a good demo for zooming a picture using multi touch gestures. It uses Matrix to zoom as well as pan a picture.
To handle scaling etc and using full resolution, You can use MapView of OSM (open street map) and provide it with your tiles (instead of the map). Check this: http://www.haakseth.com/?p=30
We have to follow following steps to remove out of memory exception while loading huge images:
1. Read Bitmap Dimensions and Type
2. Load a Scaled down version into memory
Android Developer's Guide defines how we achieve these.
here is the link
http://developer.android.com/training/displaying-bitmaps/load-bitmap.html#load-bitmap
I am using a ViewFlipper to show some images from db.
I am taking the blob values to an ArrayList then, converting each byte array to bitmap.
And then I am setting these each bitmap to each Imageview of ViewFlipper.
If the count of images is below 10, then it is working fine. But if it exceeds 10, then suddently it caught an Exception :
OutOfMemoryException : Bitmap size exceeds VM budget.
When I use inSampleSize of BitmapFactory.Options, it is working fine.But I want to display the image with actual height and width. How can I do this without exception?
My code is :
ViewFlipper vfImage = (ViewFlipper)findViewById(R.id.vfImage);
for(Photos objPhotos :arPhotos)
{
byte[] btImages = null;
Bitmap bitmapImage = null;
btImages = objPhotos.getImage();
ImageView imgPhoto= new ImageView(this);
bitmapImage = BitmapFactory.decodeByteArray(btImages, 0, btImages.length);
imgPhoto.setImageBitmap(bitmapImage);
vfImage.addView(imgPhoto);
}
vfImage.startFlipping();
Please help me..
Thank you...
You should think about unloading the bitmaps that are currently not shown, to keep in memory only those that are on the screen right now. Good luck!
Once you have completed using your bitmaps, try and make it null like this,
Bitmap bitmapImage = null;
Try adding the above line in the last line of your for loop. This means each and every time the bitmap is made null, which reduces the memory being captured by your bitmap. Also try providing
bitmapImage.recycle();
This will recycle the bitmap and provide you with free memory.
Also you can refer to my question here