Android Bitmap Loading for Efficient Memory Usage

Load a Bitmap from Resources Correctly

When handling bitmaps it is not long before Android developers come across the error “java.lang.OutOfMemoryError: bitmap size exceeds VM budget“. This usually occurs when the bitmaps are large (several megabytes uncompressed),  or running the code on older devices, or trying to load lots of bitmaps. This occurs because Android was design for mobile devices with limited resources, including memory, and bitmaps can require large amounts of memory. Despite Android not dealing with multi-megabyte bitmap loading automatically it can still be done. Instead of loading the whole bitmap a reduced resolution version is loaded (via a technique called subsampling). Android bitmap loading is achieved via the BitmapFactory class. The Options settings passed to the class can reduce the size of the bitmap, saving on memory usage.

Bitmaps can be BIG but Android Screens are Small

A digital image from a camera can be between 5 and 18 megapixels (MP) in size, depending upon the camera or device. This is the uncompressed size. The actual file storing the image, usually a JPEG file, is smaller than the displayed image because of compression. High end cameras can produce 20 MP or higher images. A 5 MP image can have a resolution of 2560×1920, that is greater than high definition (HD) television at 1920×1080, and bigger than the resolution of the Goggle Nexus 10 tablet device at 2560×1600. What about a 18 MP image? A size of 5184×3456!  A Nexus 5 phone has a HD screen, so why load more than 2 MPs of data if the screen can only display a maximum of 2 MPs. By using subsampling the huge photo image being viewed on the Android device only consumes as much memory as required to display it, 2 MP for a HD resolution screen. This saves precious App memory and reduces the possibility of out of memory errors. Here’s an example of loading large bitmaps on different Android devices. A 1000×1000 placeholder image was loaded into an ImageView  and the App run on two devices. One with a HVGA, 320×480, screen and another with a QVGA, 240×320 screen.

Android Bitmap on Different Screens

On the HVGA screen the 1000×1000 image is shown at 320×320, on the QVGA screen it is shown at 240×240. So the one million pixel image only requires a hundred thousand or sixty thousand pixels for actual viewing on these devices. Loading only the required size for display makes sense. On the Android Developers website there is an article on Managing Your App’s Memory and in the section Avoid wasting memory with bitmaps it states: “When you load a bitmap, keep it in RAM only at the resolution you need for the current device’s screen, scaling it down if the original bitmap is a higher resolution.

Android Bitmap Loading Code from the Developer Site

There is a series of lessons on the Android Developers site called Displaying Bitmaps Efficiently that deal with correctly loading, caching and processing bitmaps. When processing multiple large bitmaps it needs to be done away from the User Interface (UI) thread using AsyncTask, with the use of caching when appropriate. There is a sample App for the lessons, DisplayingBitmaps.zip, for Android Studio, though the code can be used in Eclipse if that is your preferred development platform. The example App was previously called Bitmap Fun from BitmapFun.zip. The basic steps in loading a large bitmap are:

  1. Determine the required size (from a known size or determining the size of the target View).
  2. Use the BitmapFactory class to get the bitmap’s size (set inJustDecodeBounds in BitmapFactory.Options to true).
  3. Using 1. and 2. calculate the subsampling value (a multiple of 2) and pass it to the BitmapFactory.Options setting inSampleSize.
  4. Use the BitmapFactory to load a reduced size bitmap.

The following section takes the code from the Android Developers article Displaying Bitmaps Efficiently to provide an example App performing the steps listed above.

Sample Code to Load an Android Bitmap from a Large Resource Image

J. M. W. Turner The Fighting Temeraire A large bitmap is needed. You may be reading this because you have a very large bitmap causing out of memory errors. Here a large image of a Turner painting is used. The image size is 5684×4226, a 24 MP image! You can grab the image from Wikimedia Commons, it is available in several sizes.

An Android App project was created in Eclipse. The large Turner image was added to the project in a folder called drawable-nodpi under the res folder. A large placeholder image (large enough to match the screen width) was also added to the folder. It can be generated from Placeholder Graphic at openclipart.org. The layout is just an ImageView with a Button below it:

Here’s the code for the App:

And the App in action:

Large Android Bitmap Loading

Using a Open Source Library to Manage Large Bitmap Loading in Android

This code is good for a single bitmap, but the Android Developers article goes on to talk about caching and background loading. One way of achieving this is to use an existing implementation, such as provided in the Display Bitmaps sample or existing libraries that support large bitmap loading with caching, including android-query (AQuery),  Android Volley for loading images over networks and Android Universal Image Loader.

Related Article

How to Get a View Size in Android

Displaying a Bitmap in Android

Use an ImageView to Show a Raster Graphic

Showing a bitmap image, such as a Portable Network Graphics (PNG) or JPEG file, in an Android application (App) is easy. In this tutorial we show you how. It is assumed you are programming in Java using the Android SDK from within the Eclipse Integrated Development Environment (IDE). For PC users starting out in Android Java development see Set Up Windows for Android Development to prepare your development environment.

The ImageView class can be used and pointed at a bitmap stored under one of the drawable folders in the res project folders. Let us start by creating a very basic App project that will contain the ImageView and bitmap to display. If you do not know how to create a basic Android project in Eclipse see the article Your First Android Program. With Eclipse open select the File menu then New and Android Application Project. In the New Android App wizard the fields are set as follows:

  • Application Name – Bitmap
  • Project Name – Bitmap
  • Package Name – biz.tekeye.bitmap
  • Build SDK – Android 4.1 (API 16)
  • Minimum Required SDK – API 3: Android 1.5 (Cupcake) – or the lowest one installed
  • Create custom launcher icon – unchecked
  • Mark this project as a library – unchecked
  • Create project in Workspace – checked

Simple Android App Screen Open in EclipsePress the Next button. Create Activity should be checked and BlankActivity selected. Press the Next button again. On the New Blank Activity screen leave the fields as default and press Finish. The Bitmap project will be created and the App’s initial screen will load in the graphical designer. Continue reading

Button and Image Borders in Android with Nine Patch Files

When designing a User Interface you may want to change the default View backgrounds to give an App its own look. In most cases the backgrounds must be able to scale correctly for different size screens on a variety of devices. Android uses Nine Patch files to provide support for scaling of backgrounds as View sizes change.

Button Background Scaling Correct and Incorrect In this picture the word Text has a background that is a rounded rectangle (a black border with a grey background). The rectangle has then been uniformly scaled to fit in Longer Text. As a result of scaling the corners and vertical edges have distorted to give the rounded rectangle an unbalanced look. Compare that to the second Longer Text where the background has maintained its balance.

How 9 Patch Scaling WorksTo correctly scale the background selected parts of the image are scaled in a particular direction or not scaled at all. Which parts are scaled and in which direction are shown in this diagram. The X indicates that corners are not scaled, the vertical edges are scaled vertically, the horizontal edges are scaled horizontally and the central area is scaled in both directions. This is probably why it is called a Nine Patch file, a.k.a 9patch .

  • 4 Corners +
  • 2 Vertical Edges +
  • 2 Horizontal Edges +
  • 1 Central Area
  • = 9 Areas (Patches) in Total

Continue reading

Animated Images in Android

Android has good support for user interface animation. Views can be animated and it is easy to sequence images using the AnimationDrawable class. This article will show a simple animation using a sequence of traffic light images. The first step is to generate the required images to be sequenced. Each image represents one frame of the animation, they will usually be the same size with changes between each frame as required. Here the images are generated using the open source vector graphics program Inkscape (see http://inkscape.org). A copy of the image used is available from the Open Clip Art Library (http://www.openclipart.org/), searching for Traffic Lights Turned Off, select the image, click on the View Image button and save the file from your browser. Open the file in Inkscape.

Four images will make up the animation, they will show the sequence of traffic lights as used in the United Kingdom, red, red and yellow, green, yellow and back to red. The SVG image has all the lights available, they are just hidden behind a translucent circle. To generate the first image select the circle covering the red light and delete it. Then from the Edit menu use Select All, or Ctrl-A, to highlight the whole image. Using the File menu select Export Bitmap. In the Export Bitmap dialog under Bitmap size enter 150 in the Height box, choose a directory and file name for the file to be generated, e.g. red.png. Click the Export button to export the bitmap. Delete the circle covering the yellow light (click away from the image to remove the selection boxes, click the yellow and press Delete). Use Select All again and export as before to a file, e.g. red_yellow.png. Use the Edit menu and choose Undo, twice, restoring the covers for the red light and yellow light and then delete the circle covering the green light, as was done for yellow. Export to green.png. Again use undo to cover the green light then delete the circle covering the yellow light and export the bitmap in the same way as before to yellow.png.

Exporting an Image from Inkscape Continue reading

Portrait and Landscape Screen Layouts in Android

Portrait v LandscapeWhen developing an Android App the Activity screens that form the user interface should be useable in both portrait and landscape modes. Most Android devices can be used in either orientation so screen support for both is helpful to the user. To achieve this produce layouts for each mode, alternatively design the portrait layout and then wrap it a ScrollView. Here is a screen from a simple App (it converts a loan’s annual interest rate to the monthly rate and vice versa).

Portrait Screen in Android

Here is the layout for the screen, you can try the following layouts by copying them into a new project in Eclipse (see Copying Code from the Articles for tips). When running the simple example here use the QVGA screen when configuring the Android Virtual Device (AVD). Continue reading