SolutionsTools & SDKSupportForums Register



Quick Links
 
March 2004
 
 
Jack's Hack for the month of March, 2004:

Optimizing Images for Multiple Devices Using ImageMagick

As the capabilities of devices in the marketplace continue to evolve, and display sizes and resolutions continue to advance, delivering images over the mobile web becomes a more and more complex issue. This month in Jack's Hack, we'll take a look at a tool that can be used to programatically scale images and deliver them across a variety of devices.

Way back when in the bad old days, as a developer you had only one choice of image format to employ in your wireless content, WBMP images. Displays were relatively small, and even when they increased in size, the fact that only 1-bit images were supported, and that maximum object sizes were still held low (1.5 - 3 k max), thinking about image size and formats was a non iussue. Times have changed. With the increasing proliferation of devices with color screens, support for M-Services featuers, and WAP2 XHTML devices, a whole new world of image options has opened up.

As devices proliferate in the marketplace, the device manufacturers are constantly seeking to differentiate their phones with unique features, which sometimes include small, compact designs, and in other cases include bright, high-resolution displays. There are effectivley 3 classes of color displays in the marketplace today. On the compact front, there are the devices that have small, horizontally oriented displays, on the order of 101x80 pixels. These devices include the SonyEricsson T68, and the Siemens SL55. In the mid-range there are devices with hoizontal displays on the order of 120x160. The Sharp GX-10, and Nokia Series40 (and even Series60) devices, and the Motorola V400/V500/V600 could be considered to fit within this category. Newly shipping devices are starting to appear in the marketplace with QVGA displays 240x320. Images that fit well on the mid-range deivce appear tiny on these new high-resolution displays.

There are two approaches to managing this increasing diversification of display capabiliites

  1. Maintain a tree of images for each device (or class of device)
  2. Maintian a single, large, root image and scale as appropriate for each device

One way to approach the problem of managing these images is to use the Open Source tool ImageMagick. We'll take a look at how ImageMagick and the associated java iterface, JMagick, can be used to scale images on the fly for delivery.

You will need to download ImageMagick from http://www.imagemagick.org (the code that will be show in based on using version 5.5.7), there are Solaris, Linux, and Windows source and binary versions available. Once you have the ImageMagick environment set up on your system, you will also need to download the Java interface since ImageMagick is a C based application. JMagick is Open Source and can be found at http://www.yeo.id.au/jmagick/. There are source and binary versions available, but all of the documentation lives in the JavaDoc that comes with the source packages. Once you get your environment set up, you can leverage your favorite servlet engine, Tomcat, WebSphere, whatever the mood strikes...

There are a vast array of functions that ImageMagick/JMagick can be used for, but we're going to focus purely on the ability that the tool has to scale imgages. The scenario is as follows. You want to build a site that can accomodate these new QVGA srcreen devices, as well as handle your older, 160x120 display sizes without either 1) sending overly large data to small displays, or 2) getting tiny images on big screens. To that end, we create a simple Scale servlet so we can pass in an image, and our desired width, and get back something apporpriately sized for our device. For this to work properly, we will maintian the largest size image that we can conceivable deliver (maybe 640x480, but this will depend on the image format itself, and exactly the purpose of the image). We pass in only the width to our script so that we can rely on our code to maintian the aspect ratio (so we don't squish or stretch the images unintentionally...)

The code listing can be broken down into 7 steps:

  1. Parse the file name to scale
  2. Parse the desired width of the file
  3. Load the file and find out its initial dimensions
  4. Find the ratio that the image needs to be scaled down by (to maintain the aspect ratio)
  5. Calculate the new height based on this ratio
  6. Scale the image
  7. Return the image via the ServletOutputStream
public class Scale extends HttpServlet {


    public void doGet(HttpServletRequest request,
                      HttpServletResponse response)
        throws IOException, ServletException
    {
	ResourceBundle rb =
            ResourceBundle.getBundle("Scale",request.getLocale());
    String ImagePath = rb.getString("scale.ImagePath");

	int height = 0;
(1)	String imageid = request.getParameter("imageid");
(2)	int width = Integer.parseInt(request.getParameter("wid"));
	try{
	    ServletOutputStream sout = response.getOutputStream();
	    response.setContentType("image/jpeg");
(3)         ImageInfo info = new ImageInfo(ImagePath + imageid);
	    MagickImage image = new MagickImage(info);
	    Dimension xy = new Dimension(image.getDimension());
	    Double x = new Double(xy.getWidth());
(4)	    Double scale =  new Double(x.floatValue() / width);
(5)	    Double y = new Double(xy.getHeight() / scale.floatValue());
	    height = y.intValue();
(6)	    MagickImage cropped = image.scaleImage(width,height);
	    ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
	    byteStream.write(cropped.imageToBlob(info));
(7)	    byteStream.writeTo(sout);
	    sout.flush();
	    sout.close();
	    
	}	catch (Exception me){
	

With this simple class we now have the ability to dynamcailly scale any image as needed. To leverage this, we simply need to pass our images into it instead of refering to them directly in our XHTML code. For example, instead of using:

<img src="/servlets-examples/images/imageid=wed-240.jpg" 
		alt="happy couple">

We can instead use:

<img src="/servlets-examples/servlet/Scale?imageid=wed-240.jpg&wid=60" 
		alt="happy couple"/>

Now the xhtml code above is coming from a static file, but you will likely want to incorporate this code into a dynaimc page serving mechanism so you can choose the apporpriate width based on the particular device accessing your site

You can download the source of the script above along with the properties files here, remember, you will also need ImageMagick and JMagick for all of this to work.

Happy Hacking!



 
Copyright © 2000-2008 Openwave Systems Inc.    About Us  |  Openwave  |  Terms & Conditions  |  Privacy Policy  |  Update Profile