Optimizing for Size

MIDlets are intended to run on devices with limited memory and relatively slow wireless internet connections. Therefore, it is important that your MIDlet be as small as possible. Keeping your MIDlet small will help conserve space on the device, and reduce the time it takes to download your application. We will look at several means of reducing MIDlet size, including image optimization, code obfuscation, and custom data compression techniques.

As you already know, MIDP supports the PNG format exclusively. The PNG format allows for a wide range of color depths. Often, you can greatly reduce the size of your PNG files by lowering the color depth of your images. In general, use the lowest color depth that is possible without losing detail. In many cases, you may be able to get away with 4 bits per pixel (16 colors).


Reducing Color Depth in Paint Shop Pro

In Paint Shop Pro, you can reduce the color depth of your image by opening the image file, going to the “Image” menu and selecting one of the options under the “Decrease Color Depth” sub-menu.


Setting Palette Transparency in Paint Shop Pro

If your image has transparent pixels, confirm that the transparency settings have been preserved by going to the “Image” menu and selecting “Palette,” followed by “Set Palette Transparency…”


Setting Palette Transparency in Paint Shop Pro

If necessary, re-select the color which represents your transparency pixels in the “Set Palette Transparency” dialog.

Another means of reducing the size of your application is by a process known as obfuscation. Simply put, obfuscation scrambles your class files by changing the names of identifiers and removing unused code. One of the purposes of obfuscation is to make your compiled code harder to reverse engineer, thereby making it more secure. However, obfuscation has the fringe benefit of making your JAR file smaller, often substantially so. This is because obfuscation usually shortens the length of your identifiers, thereby reducing the size of the class files.


Configuring Obfuscation in NetBeans

In NetBeans, enabling obfuscation is a simple and straightforward process. NetBeans includes a free obfuscator known as ProGuard. To set the obfuscation level for your project, open the project properties dialog, and select “Build” > “Obfuscation” from the “Category” tree. If you are compiling an application, as opposed to a library, you can probably use the highest level of obfuscation. Note that too much obfuscation can be a problem for libraries, because external applications will need to be able to find the class members using their original names.

Lastly, we will look at doing our own compression. Sometimes, its necessary to roll your own compression routines when storing data structures which are customized for your application. In games, this is often the case for map data. Note that the java.util.zip package does not exist in Java ME. Even if you are able to find a third-party ZIP library, compiling it into your code may actually use more space than what you’re saving by compressing your data.

One of the simplest and easiest to implement compression techniques is Run-length Encoding, or RLE. This is where runs of identical values are replaced by a single value followed by a count. There are numerous variations of this technique, and going into all of them is beyond the scope of this article. However, you should be able to find an effective algorithm by experimenting on your own.

For example, in one particular project I had data that contained frequent long runs of zeros, but very few runs of any other values. I found that encoding every value as a run would save very little space, and in some cases even make the data larger. However, only encoding the runs of zeros would consistently shrink the data, in some cases by as much as half. In this project, I used an algorithm that would only encode and decode runs when it encountered a zero, and treat any other value as a literal. To see how this works, take the following sequence of bytes:

7,3,9,4,9,3,0,0,0,0,0,0,0,3,5,6

Using the algorithm I just described, this sequence would be encoded as follows, for a savings of 5 bytes:
7,3,9,4,9,3,0,7,3,5,6

Notice the seven following the zero to indicate that there is a run of seven zeros. Now, if we were to treat every value as a run, we’d end up with:
7,1,3,1,9,1,4,1,9,1,3,1,0,7,3,1,5,1,6,1

Taking this approach, our “compressed” data is actually 4 bytes larger than the original sequence. This is why you may need to experiment with your own sets of data to come up with the optimal algorithm for your own applications.

Bookmark this Post

Leave a Reply