Drawing scaled images in Android is expensive.

So I wrote a custom view which displays a list of bitmaps. The way this works is to draw a grid of images by loading them from disk, then drawing those images using Canvas.drawBitmap(Bitmap, Rect, Rect, Paint).

And during scrolling it was dog slow.

So what I did was to pre-scale the images in a weak hash map:

    private WeakHashMap fScaledBitmaps = new WeakHashMap();

    private Bitmap getScaledBitmap(String url, int cellWidth, int cellHeight)
    {
        /*
         * Check our cache and return if it's present
         */
        Bitmap bmap = fScaledBitmaps.get(url);
        if (bmap != null) {
            if ((bmap.getWidth() == cellWidth) && (bmap.getHeight() == cellHeight)) return bmap;
            // size different; kill bitmap
            bmap.recycle();
            fScaledBitmaps.remove(url);
        }
        
        bmap = ... get our image from interior cache ...
        if (bmap == null) {
            // bitmap not present; return null
            return null;
        } else {
            // Bitmap loaded. Now grab the scaled version
            Bitmap scale = Bitmap.createScaledBitmap(bmap, cellWidth, cellHeight, true);
            bmap.recycle();

            fScaledBitmaps.put(url, scale);
            return scale;
        }
    }

And this sped up scrolling from sluggish drawing once a second to quick and smooth.

Lesson: drawing a scaled image to a canvas is frighteningly expensive. Like an order of magnitude slower than pre-scaling the bitmap and storing it in a weak reference or weak hash map.

2 thoughts on “Drawing scaled images in Android is expensive.

  1. Behind the scenes I’m doing a lot more than what I’ve described here, for the purposes of clarity.

    Specifically when I download an image from the remote server, I spool it to a temporary file, and rely on the GC to release the bitmaps from the weak association when memory runs low. In practice this seems to work okay, even on my low end test devices, though you do have to monitor how much temporary file space you’re using and aggressively prune the older files when using beyond a certain threshold.

    Like

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s