Writing Mobile Code Essential Software Engineering for Building Mobile Applications [Electronic resources]

Ivo Salmre

نسخه متنی -صفحه : 159/ 85
نمايش فراداده

Choosing Appropriate Bitmap Formats and Sizes

Working with bitmap images is common both for low-level graphics work as well as high-level user interface design. Most user interface frameworks offer some notion of a PictureBox control that can display bitmaps, and lower-level graphics libraries deal mainly with bitmap-level operations. Many kinds of interesting applications work with bitmap images, such as street maps, medical images, real estate photos, and play fields for games to name only a few. When working with bitmap data, it is important to think of both the file representation of an image as well as the in-memory storage of image data. Several different file formats exist for storing and streaming bitmap data, each with specific strengths and weaknesses. Regardless of the file format used, the in-memory representation of bitmaps is usually as a matrix in memory corresponding to the pixel dimensions of the image; it is a noncompressed format suitable for quick use with the graphics hardware and the underlying operating system.

Size Does Matter

The first question to ask when looking at bitmap data for mobile devices is what are the physical pixel dimensions of the images you are proposing to bring down to the devices and load into memory?

To keep the math simple, let's assume we are dealing with square-shaped bitmaps. A 1-megapixel image would translate to 1,000 pixels x 1,000 pixels. This resolution is far larger than the screens of most mobile devices and until recently larger than most desktop screens (1024 x 768 is only 786,432 pixels). Even inexpensive digital cameras today take photographs in excess of 2 megapixels, 4 megapixel cameras are not uncommon, and the pixel count keeps climbing every year.

Physical displays with many pixels consume more power than lower-resolution screens, cost more, take up more space, and are more fragile. In addition, a larger screen means larger amounts of device memory and processing power devoted to graphics. Doubtless over time, mobile device screens will continue to get more pixels but there are good reasons to believe that the resolution will continue to lag both digital camera output and desktop display resolutions. Even assuming a large mobile device display of 500 x 500 pixels, it will contain only 250,000 pixels. This is one fourth of a 1-megapixel image and only one sixteenth of a 4-megapixel image. To approach this from another direction, to fit a 4-megapixel image on 240 x 320 Pocket PC display (76,800 pixels) would require throwing out a staggering 98 percent of the pixels in the image. Similarly, a 2-megapixel image would require throwing out 96 percent of the pixels to fit on the same Pocket PC screen, and a 1-megapixel would contain a 92 percent excess of pixels.

Why does this matter? Several reasons:

Download size If your application does not need the extra pixels, what is the point in downloading them? Downloading larger files takes more time and often costs more money. Mobile device Web applications specifically cater to reduced screen sizes by having lower-resolution images. This makes sense for rich on-device applications as well.

On-device storage size If your mobile device application downloads a large image, you will need to store it somewhere. This typically means either storing it in a RAM-based file system or in flash storage. In either case, unnecessarily large images require extra read and write time and use up space that could either be used for more images or other data. Would you rather have a single 4-megapixel image on your device or dozens of screen-sized images?

In-memory representation This is perhaps the most significant aspect to consider. If your mobile application loads a 4-megapixel image into memory, it is creating an in-memory bitmap with 4 million pixels. How often do you declare and use an integer array of 4 million items in your application? That is an awful lot of limited availability program memory to use and almost certainly significantly larger than your loaded code and all other application state. Regardless of the efficiency of the file compression used an in-memory bitmap is just that, a mapping of image bits into memory. Further, if you are using an image file format that requires mathematically complex algorithms to achieve high compression ratios, this math will need to be done to uncompress the images as well, meaning that this will cost your application dearly in performance. Having large bitmaps loaded into memory is a great way to use up all the free memory on a device and either drive the performance of your mobile application right into the ground or cause your application to fail because it has run out of memory.

The moral of the story here should be clear: It does not make sense to use images with pixel counts larger than your device's screen size. These images will be slow to transfer, will need a lot of memory to store and load into memory, and will need to be transformed down into a size that fits on the mobile device's screen regardless. Paying attention to your mobile device's available screen size and choosing image sizes that relate to the space you have to work with makes the most sense. If your application will have a PictureBox that is 120 x 120 pixels, use an image of that size.

Most real-world images are far larger than mobile devices can deal with effectively. How should this disparity be addressed? This is a good opportunity for doing processing off-device to make the on-device experience better. If your images are static images that are known at design time, shrink them down into the actual device resolutions you will be displaying. If your application is dealing with dynamic images, use a server to do the image resizing. A server could dynamically load and resize a large image to a device-sized image if need be but it is far more efficient and scalable to do this work once and cache the results on the server for future use. Because the device-sized images are small, it only requires a trivial amount of extra server storage space to store them along side full-sized images. The easiest time to do this work is when the images are uploaded to a server.

If you try to load large-resolution images into a mobile device application, you will create severe memory pressure. Avoid doing this because end users will see no benefit from images that are larger than their device's screen resolution. Instead, make sure that the digital images that do go onto devices are of a resolution that matches the screen real estate they will be displayed on. This will perform much better.

Getting the File Size Down: Compression vs. Resolution

There are three ways to reduce the file size of a digital image:

Reduce the resolution. This consists of shrinking the actual number of pixels in an image. If you go into Windows XP's Paint program, load a photograph, choose the Image->Stretch/Skew menu item and "stretch" the image to be 50 percent of its original width, you are reducing the number of pixels by half. Stretch it to 50 percent of its height next and you have removed another half of the image's original resolution. Your image is now 25 percent of the number of pixels of the original (50 percent _ 50 percent = 25 percent). Less pixel data to store means lower total size.

Choose the right file format. Various common file formats differ in their ability to compress different images. Some are good with photographs (lots of colors, few sharp lines); others are good with computer-drawn graphics (sharp lines, fewer colors). Some do no compression at all. Choosing the right format will give you the best-quality image at the lowest size.

Some image formats also allow you to choose the color depth that images are stored with. The color depth represents the number of bits used to describe the image. If fewer colors are required, a smaller color depth may be able to be chosen to reduce the file size.

Increase the compression. Lossy compression algorithms often allow you to choose the amount of loss you are willing to accept to hit the size goal you want.

The best way to meet your file size goals is to start with the image's resolution. Shrink the image down to the right dimensions for your device; this way you are getting rid of unneeded data. Second, choose the right file format that yields the best image at the lowest size and minimum color depth. Third, if you are using a lossy compression method, play with the compression settings.

So Many File Formats, So Little Time

There are many file formats available for digital images. Each has benefits and limitations. Here are descriptions of some of the most common formats that are often supported on mobile devices.

*.JPG/*.JPEG Files (Joint Photographic Experts Group)

True to their name, JPEG files excel at storing photographic and real-world images. JPEG is a variably lossy compression format meaning that you can generally achieve great size-compression benefits by accepting a bit of distortion to the image. All the JPEG photographs you take with common digital cameras use lossy compression. This is why you can fit a stunning looking 3-megapixel image into a 600KB file. More-sophisticated painting programs will let you set the JPEG compression ratio and enable you to explicitly trade off fidelity for size reduction. Often you can get very good looking photographs at very reasonable sizes. A Pocket PC screen resolution-sized photograph may compress down to below 20KB and still look great using JPEG file formats.

Because JPEG is meant to work with real-world images, it will usually not yield the best results for computer-generated raster images such as text on screen snapshots, sharp lines, and sharp color transitions. For these kinds of images, you will generally want to choose a nonlossy format.

*.PNG (Portable Network Graphics)

PNG is a relative newcomer to file formats but is fast gaining acceptance as an excellent file format for images. The effort to create the PNG format arose as a response to some intellectual property rights issues with the *.GIF format*. PNG files offer excellent nonlossy compression for digital images. If your platform supports *.PNG images and you need nonlossy compression, this is the format for you. The *.PNG format offers better compression than *.GIF in many cases and is a better choice if both are available.

*.GIF (Graphics Interchange Format)

Think of the GIF format as the popular predecessor to PNG. GIF files offer nonlossy compression as well but are limited to using 256 colors. Because of this limitation, the GIF format is not appropriate for storing photographic images. *.GIF files were heavily used in Web pages in the early years of popular Internet usage and for this reason still have a wide following.

*.BMP (Bitmap Files)

Bitmap files are noncompressed image data. They store data in a format similar to the in-memory bitmap format. Other than not requiring much work to decompress, there are no particular advantages of using *.BMP files other than wide availability.Chapter 13, "Step 2: Design the Right User Interface."

What to Do If the Mobile Device Is the Source of the High-Resolution Image

Many mobile phones today come with digital cameras capable of taking photographs. Some of these images may be in excess of 1 megapixel (for example, 1,000 x 1,000 pixels), and doubtless this trend will continue upward. Like photographs taken by digital cameras, the images are of far higher resolution than the devices are capable of usefully displaying on their screens; the images are intended for viewing on larger-screened devices (desktop computers) or for printing. It is very wasteful to load and keep a bitmap of this size in memory, but because of latency and connectivity issues it does not make sense to send the picture to a server to be reduced and sent back down to the device either. The solution to work with a large resolution image and still efficiently manage memory on the device is as follows:

Load the high-resolution image into memory. Note: If the image is large enough, this may not actually be possiblein which case, a smaller resolution image must somehow be created before even it can be loaded, possibly when the image itself is acquired. A lower resolution image can be saved along with the full-sized image.

Immediately make a reduced-sized copy of the image in memory that compresses the image into the dimensions it will be displayed in. This will create an in-memory bitmap image with a much lower pixel count.

Dispose and release the original high-resolution bitmap as soon as possible.

If your runtime framework supports saving images, it may make sense to save and cache the reduced size image for future use so that your mobile application does not need to go through the temporary memory and processor usage spike of loading the large image. The important thing is to keep the steady-state amount of memory your mobile application is using down to a minimum, and this means not keeping any extra pixel data in memory that you cannot display. For digital photographs, this can save megabytes of program memory and on mobile devices this will have a significant impact on the performance of your application.

Different Managed Runtime Approaches to User Interface

There are two ways for a managed runtime to integrate into a host device's graphics and user interface model. The runtime can utilize preexisting user interface libraries supported by the operating system or it can bring its own libraries with it to do this work.

The .NET Compact Framework running on Windows CE, Pocket PC, and Smartphone devices defers to the operating system to render and manage the majority of its user interface controls. What this means is that a .NET Compact Framework Window corresponds to a Windows CE Window. A .NET Compact Framework ListView control corresponds to a Windows CE ListView control, a .NET Compact Framework Button corresponds to a Windows CE Button, and so on. This is beneficial for several reasons:

Performance. The operating system folks have spent a lot of time designing and tuning their user interface controls. It would be difficult to get this level of performance in a custom implementation that hand drew all of these windows and controls and managed their interactions with the user.

Look and feel. The .NET Compact Framework controls have the same behavioral characteristics as the underlying Windows controls. A user interface implementation is made up of many small decisions such as "Exactly how are the pixels drawn to render the control?" "What happens when you select a block of text and press the back-arrow key? Or type a letter? Or double-click a word?" It is very difficult to exactly duplicate the underlying look and feel of a user interface and humans are very adept at sensing subtle differences.

Size. Re-implementing the code to draw and manage controls that are already in the operating system takes extra space in the framework. By deferring to existing operating system implementations, a considerable amount of space can be saved.

Although most controls in the .NET Compact Framework running on a Pocket PC, Smartphone, or Windows CE device delegate down to the operating system this does not mean that it is not possible to create entirely new controls using the framework. It is possible to implement a graphical control "from scratch" in the .NET Compact Framework, and this is done in cases where no underlying operating system control exists. This can be done by end developers and is done in the .NET Compact Framework for controls such as the GridControl.

Not all managed runtimes take this approach. Some get only a drawing space from the underlying operating system and draw and manage all the controls by themselves. The benefit of this approach is the potential for a common look and feel regardless of the device an application is running on. The downsides of a custom user interface implementation are extra size and processing overhead and risking not matching the look and feel of the underlying operating system. It is a trade-off.

If the .NET Compact Framework is ported to another platform (it was designed with this ability in mind) it would either need to utilize the underlying operating system's user interface capabilities or bring along its own implementation of these controls in native or managed code libraries. Varying mobile device operating systems differ greatly in their built-in support for user interface controls, so the work required and the design strategy depend highly on the target operating system.