This Tech Tip reprinted with permission by

Each new release of the standard edition of the Java platform brings both big and small improvements. Most people hear about all the big new features such as Generics or the new concurrency utilities package. What people don't always hear about are the small new features. These features are rarely mentioned because they are useful to a smaller audience than some of the bigger features. This tip describes several of these small enhancements to the Java 2D API added in J2SE 5.0. What actually happens when you use the new features often depends on your operating environment and your hardware. In some cases, using these features might provide very little (if any) benefit.

Bicubic Interpolation

One Java 2D API enhancement has to do with image scaling -- it also affects rotation and other affine transformations. The RenderingHints class has two constants that deal with different interpolation options: VALUE_INTERPOLATION_BILINEAR and VALUE_INTERPOLATION_BICUBIC. Setting the KEY_INTERPOLATION hint to one of the two options tells the underlying system what rules to follow when scaling an image. Prior to J2SE 5.0, the two hint values produced the same result. Because RenderingHints are simply hints, they could be ignored. In fact, the bicubic setting was always ignored, and instead, bilinear interpolation was used.

If you are unfamiliar with the two interpolation options, it helps to understand what happens when scaling up an image. For instance, where do all those new pixels in the scaled up image come from? With bilinear scaling, the pixels come from the 2x2 rectangle of pixels from the source image that are closest to the scaled pixel. The rectangle of pixels are blended using a linear function in both X and Y. With bicubic scaling, they come from the 4x4 area that surrounds the scaled pixel. The rectangle of pixels are blended using a cubic function in both X and Y. Because of the increased area and algorithmic complexity, bicubic scaling tends to create a better looking scaled image, but at the cost of performance.

In J2SE 5.0, the bicubic setting is honored. You can see this by running the following test program. When you run the program, specify an image file. The program sets the RenderingHints with the two constants, VALUE_INTERPOLATION_BILINEAR and VALUE_INTERPOLATION_BICUBIC, and reports interpolation algorithm differences (if any). First run the program with JDK 1.4 and then with JDK 5.0. You'll see that interpolation algorithm differences are reported only with the newer JDK.

 import java.awt.*;
   import java.awt.image.*;
   import javax.swing.*;
   import javax.imageio.*;  
   public class Bicubic {
     public static void main(String args[]) throws IOException {
       if (args.length == 0) {
           "Provide image name on command line");
       Image image = File(args[0]));
       int w = image.getWidth(null);
       int h = image.getHeight(null);
       BufferedImage bilinear = new BufferedImage(2*w, 2*h,
       BufferedImage bicubic = new BufferedImage(2*w, 2*h,
       Graphics2D bg = bilinear.createGraphics();
       bg.scale(2, 2);
       bg.drawImage(image, 0, 0, null);
       bg = bicubic.createGraphics();
      bg.scale(2, 2);
      bg.drawImage(image, 0, 0, null);
      for(int i=0; i<2*w; i++)
        for(int j=0; j<2*h; j++)
          if (bilinear.getRGB(i, j) != bicubic.getRGB(i, j))
            System.out.println("Interpolation algo differ");


For the JDK 1.4 environment, there is no output from running the program:

 > java Bicubic image.jpg
     [No Output]

For the JDK 1.5 environment, every pixel that differs is reported.

 > java Bicubic image.jpg
     Interpolation algo differ
     Interpolation algo differ
     Interpolation algo differ
     Interpolation algo differ
     Interpolation algo differ
     .... repeated many times

OpenGL Acceleration

The February 8, 2005 Tech Tip Introduction to JOGL described the Java programming language binding for the OpenGL 3D graphics API. In J2SE 5.0, there are some OpenGL options available to accelerate the core functionality of the 2D API. The options are "under the covers" -- they don't require the user to know how to program in OpenGL. By default, the acceleration option is disabled. To enable the option, set the sun.java2d.opengl system property to true. If you want verbose output sent about the OpenGL-based pipeline, use a value of True (uppercase T) instead of t. To see the results, use the Java 2D demo code that comes with the JDK.

  java -Dsun.java2d.opengl=True -jar Java2Demo.jar

You can find out more about the OpenGL-based pipeline in Behind the Graphics2D: The OpenGL-based Pipeline.

Creating Fonts

Prior to J2SE 5.0, the Font class allowed you to create TrueType fonts from an InputStream through the createFont() method:

  public static Font createFont(int fontFormat,
          InputStream fontStream)


where fontFormat is Font.TRUETYPE_FONT. J2SE 5.0 makes two changes to this support. First, you can create Adobe Type 1 fonts. Second, you can create a font directly from a File object with the new createFont() method signature:

 public static Font createFont(int fontFormat, 
          File fontFile)


If you simply want the fonts installed, that is, you don't want to create them with either method, you can copy the font files to the $JREHOME/lib/fonts directory. They will be automatically picked up by the runtime environment when installed in that directory.

Image Acceleration

The last set of new Java 2D features to explore relates to image acceleration. These features depend on underlying support in your system. If your system doesn't support these features, they are simply ignored.

The first image acceleration feature is buffered image caching. Video memory supports the caching of managed images. In general, programs that use the kind of images that can be managed tend to perform better that those that use unmanaged images. Prior to J2SE 5.0, only images created with the createImage() method of Component or with the createCompatibleImage() method of GraphicsConfiguration were managed by the Java 2D implementation. Now all images created with one of the BufferedImage constructors are managed by the Java 2D implementation.

Another new image acceleration feature is the ability to control the hardware acceleration of images. Note however that in J2SE 5.0, the methods used to control the hardware acceleration of images are not fully operational. See for more details.

The availability of this support depends on the platform and the type of image content. Also, on Microsoft Windows platforms, to see results, you sometimes need to set the sun.java2d.translaccel system property to true. See the description of translaccel in System Properties for Microsoft Windows Platforms for more information about the flag.

When creating Java programs, you can tell the underlying system that you want to optimize certain image operations. You do this by prioritizing how the system stores particular images in accelerated memory if possible. The key phrase here is "if possible." Prior to J2SE 5.0, you could request VolatileImage objects to be stored in accelerated memory. With J2SE 5.0, you can also request that regular Image objects be placed there. And you can create transparent VolatileImage objects. Previously, you could only create opaque ones.

The getCapabilities() method is now defined in both Image and VolatileImage -- not only in VolatileImage. This method can be used to discover if an image currently is accelerated. You can also specify the acceleration priority with the setAccelerationPriority() method, or identify its priority setting with the getAccelerationPriority() method. When its acceleration priority is zero, attempts to accelerate the specific image are disabled. The priority setting is just a hint though, and the JDK implementation can honor (or not honor) it as it sees fit.

To create transparent VolatileImage objects, use one of the two new createCompatibleVolatileImage() methods:

  • createCompatibleVolatileImage( int width, int height, int transparency)
  • createCompatibleVolatileImage( int width, int height, ImageCapabilities caps, int transparency)


As the Java platform continues to grow, watch for all those little features that don't get as much attention as the bigger ones. Little things, such as Common Unix Printer System (CUPS) printer support for Solaris and Linux, get added with little fanfare. If you happen to have a CUPS printer, the new feature is important. Be sure to read the release notes to see if a new feature is something you've been waiting for. See also the description of new features and enhancements for J2SE 5.0.

Copyright (c) 2004-2005 Sun Microsystems, Inc.
All Rights Reserved.