Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to load and draw partially a bitmap from file in Android?

Tags:

android

bitmap

Say I have a somewhat large (i.e. not fit in most phones' memory) bitmap on disk. I want to draw only parts of it on the screen in a way that isn't scaled (i.e. inSampleSize == 1)

Is there a way to load/draw just the part I want given a Rect specifying the area without loading the entire bitmap content?

like image 564
chakrit Avatar asked Sep 13 '10 22:09

chakrit


People also ask

What is layerlist in android?

A LayerDrawable is a drawable object that manages an array of other drawables. Each drawable in the list is drawn in the order of the list—the last drawable in the list is drawn on top. Each drawable is represented by an <item> element inside a single <layer-list> element. file location: res/drawable/filename.xml.

How do you handle bitmaps in Android as it takes too much memory?

Choose the most appropriate decode method based on your image data source. These methods attempt to allocate memory for the constructed bitmap and therefore can easily result in an OutOfMemory exception. Each type of decode method has additional signatures that let you specify decoding options via the BitmapFactory.

How do you draw a bitmap?

To draw on a bitmap, use the image control's canvas and attach the mouse-event handlers to the appropriate events in the image control. Typically, you would use region operations (fills, rectangles, polylines, and so on). These are fast and efficient methods of drawing.

How do I create a bitmap from resources?

To create a bitmap from a resource, you use the BitmapFactory method decodeResource(): Bitmap bitmap = BitmapFactory. decodeResource(getResources(), R. drawable.


1 Answers

I'm quite confident this is possible since you can load a really large bitmap file into an ImageView without problems so there must be some sort of a built-in way to handle large bitmaps... and after a few attempts, I've found a solution:

Instead of loading the entire bitmap and manually draw it yourself, load it as a Drawable instead:

InputStream mapInput = getResources().openRawResource(
        R.drawable.transit_map);
_map = Drawable.createFromStream(mapInput, "transit_map");

_map.setBounds(0, 0, _mapDimension.width(), _mapDimension.height());

I'm using a resource file but since you can use Drawable.createFromStream to load image from any InputStream, it should works with arbitrary bitmap.

Then, use the Drawable.draw method to draw it onto the desired canvas like so:

int left = -(int) contentOffset.x;
int top = -(int) contentOffset.y;
int right = (int) (zoom * _mapDimension.width() - contentOffset.x);
int bottom = (int) (zoom * _mapDimension.height() - contentOffset.y);

_map.setBounds(left, top, right, bottom);
_map.draw(canvas);

As in the above case, You can also scale and translate the bitmap as well by manipulating the drawable's bounds and only the relevant parts of the bitmap will be loaded and drawn onto the Canvas.

The result is a pinch-zoomable view from just one single 200KB bitmap file. I've also tested this with a 22MB PNG file and it still works without any OutOfMemoryError including when screen orientation changes.

like image 77
chakrit Avatar answered Sep 30 '22 12:09

chakrit