Home : Course Map : Chapter 11 : Java : Supplements :
Lookup Tables
JavaTech
Course Map
Chapter 11

Introduction
Image Class
Image Loading
  Demo 1 Demo 2  
Pixels/Transparency
  Demo 3
Pixel Handling
  Demo 4  
Demo 5
Exercises

    Supplements
Java 2D Imaging
BufferedImage
Creating Buf.Image
Pixel Handling
  Demo 1 Demo 2
Filters
  Convolutions
     Demo 3
  AffineTransforms
     Demo 4
  LookupTable
     Demo 5 Demo 6
  Rescale
     Demo 7
  Color Conversion
     Demo 8
  Custom
     Demo 9
Exercises
Java Adv Imaging
AWT Flicker:
  Override Update
     Demo 1  Demo 2
  Clipping
     Demo 3
  Double Buffer
     Demo 4

     About JavaTech
     Codes List
     Exercises
     Feedback
     References
     Resources
     Tips
     Topic Index
     Course Guide
     What's New

Lookup tables provide a very flexible approach to transforming the colors of an image. One can use a lookup table filter, for example, to create a negative of the source image.

The LookupOp filter uses an instance of LookupTable (or, actually, one of its two subclasses) to map source pixels to destination pixels according to the source pixel component values. (Note that this filter can not be used with indexed color model images.)

So, for example, the 8 bits of the red component for an RGB pixel would need a table of up to 256 elements, each holding a value for the corresponding red component in the destination pixel. You can provide one table used by all three components or separate tables for each. (Four table for ARGB pixels.)

There are two subclasses of the abstract LookupTable. The ByteLookupTable and the ShortLookupTable essentially offer the same features except for the type of arrays. Each offers a constructor for creating a single table for all color components and a constructor for creating multiple tables, one for each color component.

The following table shows how to can create a table that selects only colors above a given threshold:

    short[] threshold = new short[256];
    for (int i = threshold_level; i < 256; i++)
      threshold[i] = (short) i;
    LookupTable threshold_table = new ShortLookupTable (0, threshold);
    LookupOp threshold_op = new LookupOp (threshold_table, null);
    fDstImage = threshold_op.filter (fSrcImage, null);

The program LookupTableApplet shown below demonstrates the above technique. The threshold_op filter is applied to the source image with a user selected threshold level.

LookupTableApplet
Resources: saturn.jpg, saturnVoyager.jpg

import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import javax.swing.event.*;

/** Demonstrate using a lookup table to provide a threshold filter.**/
public class LookupTableApplet extends JApplet
                          implements ChangeListener {

  BufferedImage fSrcImage, fDstImage;
  ImageIcon fDstIcon;
  JLabel fThresLabel;
  JSlider fThresSlider;

  /**
    * Build the interface with the source and filter output image
    * displayed side by side.
   **/
  public void init () {

    setLayout (new BorderLayout ());

    fSrcImage = getBufImage ("saturnVoyager.jpg");
    if (fSrcImage == null) {
        System.out.println ("Error in reading image file!");
        return;
    }

    JPanel control_panel = new JPanel();
    control_panel.add (fThresLabel =
          new JLabel ("Threshold 100 ",SwingConstants.RIGHT) );
    control_panel.add (fThresSlider =
          new JSlider (Adjustable.HORIZONTAL, 0, 255, 100));
    fThresSlider.addChangeListener (this);

    // Filter image with an initial value for threshold
    thresholdFilter (100);

    // Use ImageIcon objects to hold the two images
    ImageIcon src_icon = new ImageIcon (fSrcImage);
    fDstIcon = new ImageIcon (fDstImage);

    // Put the icons on labels
    JLabel src_display = new JLabel (src_icon);
    JLabel dst_display = new JLabel (fDstIcon);

    // And then display the labels on the scroll panes
    JScrollPane src_pane = new JScrollPane (src_display);
    JScrollPane dst_pane = new JScrollPane (dst_display);

    // Use a JSplitPane to show the source and destination
    // images side by side.
    JSplitPane split_pane =
      new JSplitPane (JSplitPane.HORIZONTAL_SPLIT,
                      true, src_pane, dst_pane);

    split_pane.setResizeWeight (0.5);
    split_pane.setContinuousLayout (true);

    // Add the DrawingPanel to the contentPane.
    add (split_pane, BorderLayout.CENTER);
    add (control_panel, BorderLayout.SOUTH);

  } // init

  /**
    * This class implements ChangeListener for the
    * slider. So the ChangeEvents come here when the
    * slider is moved.
   **/
  public void stateChanged (ChangeEvent evt) {

    // Use the labels to show the numerical values of the
    // scroll bar settings.
    fThresLabel.setText ("Threshold " +
                       Integer.toHexString (fThresSlider.getValue ()));

    // Get the values from the slider and set a new threshold
    thresholdFilter (fThresSlider.getValue ());

    // Reset the destination images with the modified version.
    fDstIcon.setImage(fDstImage);
    // Repaint to show the modified image.
    repaint ();

  } // stateChanged

  /** Create the filter to execute a threshold setting on the
    * color component values.
   **/
  void thresholdFilter (int threshold_level) {

    short[] threshold = new short[256];
    for (int i = threshold_level; i < 256; i++)
      threshold[i] = (short) i;
    LookupTable threshold_table = new ShortLookupTable (0, threshold);
    LookupOp threshold_op = new LookupOp (threshold_table, null);
    fDstImage = threshold_op.filter (fSrcImage, null);

  } // thresholdFilter

  /**
   *  Download the image file and convert to a
   *  BufferedImage object.
   */
  BufferedImage getBufImage (String image_name){

    // Get the image
    Image img = getImage (getCodeBase(), image_name);

    // and use a MediaTracker to load it before converting it to
    // a BufferedImage.
    try {
      MediaTracker tracker = new MediaTracker (this);
      tracker.addImage (img,0);
      tracker.waitForID (0);
    } catch (InterruptedException e) { return null; }

    int width = img.getWidth (this);
    int height= img.getHeight (this);

    BufferedImage buffered_image =
      new BufferedImage (width, height, BufferedImage.TYPE_INT_RGB);
    Graphics2D g2 = buffered_image.createGraphics ();
    g2.drawImage (img,0 ,0, null);

    return buffered_image;

  } // getBufImage

} // class LookupTableApplet

 

You can invert the colors of the source image by creating an array of size 256 and filling the first element with the value 256 and then decreasing by one in each element until reaching 0 in the last element.

If we wanted to apply the above threshold filter to only the red component and leave the other color components unchanged, we need to create a two dimensional array to hold the threshold array plus an identity array that leaves the other components unchanged.

  short[] identity = new short[256];
  for (int i = 0; i < 256; i++) identity[i] = (short) i;
  short[][] red_threshold = {threshold, identity, identity};
  LookupTable red_threshold_table = new ShortLookupTable (0, red_threshold);
  LookupOp red_threshold_op = new LookupOp (red_threshold_table, null);
  BufferedImage dest_image = red_threshold_op.filter (source_image, null);

The following program LookupTableOneColorApplet is the same as the above applet except that the red_threshold_op filter is used on the source image.

LookupTableOneColorApplet
Resources: saturn.jpg, saturnVoyager.jpg

import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import javax.swing.event.*;

/**
  * Demonstrate using a lookup table to provide a threshold filter
  * on a single color component.
 **/
public class LookupTableOneColorApplet extends JApplet
                          implements ChangeListener {

  BufferedImage fSrcImage, fDstImage;
  ImageIcon fDstIcon;
  JLabel fThresLabel;
  JSlider fThresSlider;

  /**
    * Build the interface with the source and filter output image
    * displayed side by side.
   **/
  public void init () {

    ... Same as LookupTableApplet ...

  /** Create the filter to execute a threshold setting on the
    * color component values.
   **/
  void thresholdFilter (int threshold_level) {

    short[] threshold = new short[256];
    for (int i = threshold_level; i < 256; i++)
      threshold[i] = (short) i;

    short[] identity = new short[256];
    for (int i = 0; i < 256; i++) identity[i] = (short) i;
    short[][] red_threshold = {threshold, identity, identity};
    LookupTable red_threshold_table =
      new ShortLookupTable (0, red_threshold);
    LookupOp red_threshold_op = new LookupOp (red_threshold_table, null);
    fDstImage = red_threshold_op.filter (fSrcImage, null);

  } // thresholdFilter

  ... Same as LookupTableApplet ...

} // class LookupTableOneColorApplet

 

There are obviously many such lookup table transforms you can create. Note that in-place filtering (i.e. destination image can be the same as the source image) can be done with the LookupOp filter.

References & Web Resources

 

Latest update: March 8, 2006

              Tech
Fractals
Fractal Drawing
   Demo 1
Fractal Draw Code
Fractal Images
  Demo 2
Image Processing
  Demo 3
Histogram Image
  Demo 4
Exercises

           Physics
Calibration/SysError
SimWithCal/SysErr
  Demo 1
Analysis
  Demo 2
Examples

Exercises

  Part I Part II Part III
Java Core 1  2  3  4  5  6  7  8  9  10  11  12 13 14 15 16 17
18 19 20
21
22 23 24
Supplements

1  2  3  4  5  6  7  8  9  10  11  12

Tech 1  2  3  4  5  6  7  8  9  10  11  12
Physics 1  2  3  4  5  6  7  8  9  10  11  12

Java is a trademark of Sun Microsystems, Inc.