29

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 enter image description here

Guru
  • 21,652
  • 10
  • 63
  • 102
Rafael T
  • 15,401
  • 15
  • 83
  • 144

7 Answers7

30

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.

leadersheep
  • 328
  • 3
  • 7
  • Nice Solution. I now found an even better way (with much coding effort) by tiling my Images. I also have 3 Versions of the same picture in different qualitys for different ZoomLevels. This will work even on old devices, which are failing to decode 1/4 of the original Bitmap – Rafael T Aug 28 '12 at 16:21
  • 2
    What is **k** in here? Hope **width** and **height** means the actual image dimensions. Please clarify that. – AnujAroshA Oct 16 '12 at 11:05
  • 1
    Rafael: You shouldn't (in theory!) need different resolution versions - check out `BitmapFactory.Options.inSampleSize`. – Timmmm Oct 16 '12 at 12:46
  • 1
    @leadersheep : can you tell us what's the value of *k* here? – anticafe Jun 23 '13 at 06:39
  • 2
    Here, I cut my picture in 4 parts, so the k = 2 – leadersheep Jun 24 '13 at 06:52
  • What if i am having a 30x30 image and i want to display it as 150x150? – Kaveesh Kanwal May 26 '15 at 14:53
7

I know its an old question but I used TileView to do exactly this:

https://github.com/moagrius/TileView

FRR
  • 71
  • 1
  • 2
7

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.

Zikkoua
  • 806
  • 7
  • 9
  • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. – Kmeixner May 25 '15 at 14:05
  • But this library couldn't rotate the image using touches, it allow to rotate 90 degrees only. – bebosh Nov 10 '15 at 07:32
4

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).

M. Usman Khan
  • 3,689
  • 1
  • 59
  • 69
2

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.

Ben Lee
  • 3,418
  • 1
  • 18
  • 19
1

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

M. Usman Khan
  • 3,689
  • 1
  • 59
  • 69
1

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

hitesh141
  • 963
  • 12
  • 25