Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Create dynamic images in Java servlets

Dynamically convert users' requests into an image

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone
Many Websites now use charts and graphs to represent some type of numeric information. In some cases, the chart or graph image is best constructed in realtime. Two reasons could motivate you to build an image dynamically: the data arrives continuously, which lends itself to dynamic image construction; or the data's volume is very large, and dynamic construction dramatically reduces storage. Of course, not every image is a candidate for dynamic construction; it's just another tool available in the Web developer's toolbox.

Image I/O packages, JDK-level requirements

If your servlet is to generate images on the fly, you first need to do image I/O (input/output). Specifically, you need to generate an image in response to an HTTP request. The core Java API provides no direct facility for saving images of any type. However, you can use Sun's Java 1.1 class library to do image I/O. Also, Sun's 1.2 image I/O offering includes a proprietary package for encoding and decoding JPEG images. Since this code is in a com.sun package, it is not part of the core API and is not a standard extension; therefore, its dependent code is not portable. The good news is that the approved Java Specification Request, JSR-000015, for a standard Java 2 extension, provides a framework for performing image I/O. This adds support to the Java 2 platform for image I/O and provides a mechanism to write portable code capable of dynamic image I/O. For this article, I create two examples, one using the Java 1.1 image I/O framework and the other using Java 1.2 code.

Image formats

The most common image format on the Web is GIF. GIF is widely supported by browsers, even old ones. Unfortunately, for writing image-generation code, GIF is potentially encumbered legally by a patent on its compression scheme. The two examples in this article create a JPEG and a PNG image. I will generate a JPEG image primarily because Sun's Java 1.2 code lets me generate this type of image. One difference between the GIF format and the JPEG format is that the GIF-compression algorithm is lossless, meaning that when the image data is subjected to a compress/decompress cycle the resulting data is identical to the original data (no information is lost); the JPEG algorithm is not lossless. Usually, the image degradation is not visible for the type of image you are generating. The second example generates a PNG image, which uses a lossless compression algorithm free of legal issues.

Image servlet design

For this article, I will decompose the image presentation system into two parts. The first part, the Image servlet, is responsible for responding to image requests and returning either an image or an error to the client. The second part is a class capable of performing image I/O. For simplicity, the type of image generated is determined by passing the name of a Java class, which should generate the image to the Image servlet. The Java class implements a simple interface for communication with the servlet. The following code shows the interface that the ImageProducer class must implement:

public interface ImageProducer
{
  /**
   *  Request the producer create an image
   *
   *  @param stream stream to write image into
   *  @return image type
   */
  public String createImage(OutputStream stream) throws IOException;
}


The ImageProducer interface consists of a single method, with a parameter to provide a stream for which the image is output and a returned string indicating the type of image -- for example, image/jpg.

The following code indicates how the servlet works with the ImageProducer to produce the image:

ImageProducer imageProducer = 
         (ImageProducer) 
Class.forName(request.getQueryString()).newInstance();
String type = imageProducer.createImage(response.getOutputStream());
response.setContentType(type); 


This code attempts to load a class named by the query string in the URL. The query string is the portion of the URL after the ?. The loaded class is then cast to an ImageProducer and asked to create an image. If everything goes well, the resulting image is returned to the client.

There are several exception types that can arise from this code; the most common are ClassNotFoundException and ClassCastException. The former results from the named ImageProducer not being available to the Classloader that loaded the servlet, and the latter results from the named class not implementing the ImageProducer interface. In the event an exception occurs, the client of course does not receive an image, and the browser displays a graphic indicating that no image was returned by the Web server. The code was tested using the Java Server Web Development Kit (JSWDK) 1.0.1, but you should get similar results on most Web servers supporting Java servlets.

Image generation on Java 1.1

For my first generated image, I will create code I can deploy on the Java 1.1 platform. Although 1.2 JVMs are fairly common, not everyone can count on deploying code on the latest platform. Some commercial Web-hosting environments, for example, are somewhat slow to update the Java Runtime Environments (JREs) on their servers. This means that any servlets you deploy must run on Java 1.1. Designing the code for Java 1.1 does not greatly complicate matters; however, I do discuss a troublesome issue regarding in-memory image creation later in the article.

I will create the image of a simple pie chart. A pie chart is a useful, easy-to-read chart. This pie chart will be complete with colorization and labeling of the pie's pieces. The chart will indicate soft drinks favored by software developers. Now I'll take a look at how you can go about this.

For doing image I/O on Java 1.1, Sun offers a class library known as Jimi. Sun purchased this class library from a small software vendor. After Sun began distributing the class library, it repackaged the classes into com.sun, but otherwise left them unchanged. The following are the steps you should take to produce a PNG image using the Jimi toolkit.

  1. Construct a Frame window to provide an AWT image.
  2. Use the AWT image to get a Graphics instance.
  3. Draw into the Graphics object.
  4. Create a JimiWriter using the HTTP output stream.
  5. Have the JimiWriter write out the AWT image previously created.


On the Java 1.1 platform, constructing an in-memory image appears to require that an AWT component exist on the desktop. Normally, you should not use Java servlet code to create AWT components. It just doesn't make sense for the Web server to create user interface components to respond to a client request. In this case however, you need an image to provide a Graphics instance that you can draw into. So, you will have to live with the small window that appears on the Web server's desktop. If you know of a way to create an image on Java 1.1 without an AWT component, please let me know. One possible design would use a template image on the Web server's disk. You could load the image data from the disk, and construct the AWT image using java.awt.Toolkit.createImage(). After you construct the AWT image, it can provide the Graphics instance, which you can draw into as usual. If this works, you could avoid the spurious window. I will leave this experiment as an exercise to the interested reader.

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone
Comments (1)
Login
Forgot your account info?

newBy Anonymous on October 7, 2009, 10:39 amyour comments

Reply | Read entire comment

View all comments

Add comment
Anonymous comments subject to approval. Register here for member benefits.
Have a JavaWorld account? Log in here. Register now for a free account.