Home : Course Map : Chapter 11 : Java : Supplements :
Custom Filters
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

You can implement the BufferedImageOp interface to create your own custom filters. In addition to the filter() method, there are four other methods in the interface that must be implemented. The following RotateOp example illustrates the basics of creating a filter.

The filter() method offers the option of using an existing BufferedImage object, passed via the second argument, to receive the output of the filter. If this reference is null, a BufferedImage must be created and it must possess the same dimensions as the source image, similar raster and color model.

The createCompatibleDestImage() method does the job of making a suitable destination image. For the BufferedImage constructor it uses a color model either passed as an argument or from the source. It also gets a raster suitable for this color model and it checks to see if the alpha transparency factor pre-multiplies the color components.

The getBound2Ds() method returns the bounds object obtained from the source image. The getPoint2D() method, which asks for the point in the destination image that corresponds to the given point in the source image, just returns the same point as in the source image since in this filter the dimensions are unchanged. There are no RenderingHints provided for displaying the filter output image.

The RotateColorsApplet program shown below uses the custom filter called RotateOp, which shifts the RGB color components each time the image is repainted on the RotateImagePanel, a subclass of JPanel.

RotateColorsApplet
+ RotateImagePanel + RotateOp

Resources: liftoff.jpg

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

/**
  * Demonstration of the RotateOp filter. Most of the work is done on the
  * RotateImagePanel, which is displayed on this applet. The applet is
  * Runnable and periodically signals to the RotateImagePanel to repaint
  * itself with the image filtered for a different color.
 **/
public class RotateColorsApplet extends JApplet
                       implements Runnable
{
  // Will use thread reference as a flag
  Thread fThread;
  int fDeltaT = 1000; //msecs of sleep time

  // Need a reference to the panel for the
  // thread loop.
  RotateImagePanel fRotateImagePanel;

  
  public void init () {
    Container content_pane = getContentPane ();

    // Create an instance of DrawingPanel
    fRotateImagePanel = new RotateImagePanel ();

    // Add the DrawingPanel to the contentPane.
    content_pane.add (fRotateImagePanel);
  } // init

  /**  Create the image on the panel and then start the thread.**/
  public void start () {
    // Tell the panel to create the image source.
    fRotateImagePanel.init (this);
    if (fThread == null) {
        fThread = new Thread (this);
        fThread.start ();
    }
  } // start

  /** Stop the thread web page unloaded by setting loop flag in run().**/
  public void stop ()  {
     fThread = null;
  }

  /** Loop the image display so that it rotates the image each frame.**/
  public void run () {
    while (fThread != null) {
      try {
         Thread.sleep (fDeltaT);
      } catch (InterruptedException e) { }
      // Repaint filtered image.
      repaint ();
    }
  } // run
} // class RotateColorsApplet


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

/** Load an image, apply the rotate filter to it, and then display it. **/
class RotateImagePanel extends JPanel
{

  BufferedImage fBufferedImage;
  int fWidth, fHeight;
  RotateOp fRotate;

  void init (JApplet applet) {
    // Get the image
    Image img = applet.getImage (applet.getCodeBase(), "liftoff.jpg");

    // 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) { }

    int fWidth = img.getWidth (this);
    int fHeight= img.getHeight (this);

    fBufferedImage =
      new BufferedImage (fWidth, fHeight, BufferedImage.TYPE_INT_RGB);
    Graphics2D g2 = fBufferedImage.createGraphics ();
    g2.drawImage (img,0 ,0, null);

    // Create the color rotation filter object.
    fRotate = new RotateOp ();

  } // init

  /** Before drawing the image, apply the filter.**/
  public void paintComponent (Graphics g) {
    fRotate.filter (fBufferedImage, fBufferedImage);
    g.drawImage (fBufferedImage, 0, 0, this );

  }
} // RotateImagePanel

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

/** Demonstrate a custom filter by shift the color components. **/
public class RotateOp implements BufferedImageOp {

  public final BufferedImage filter (BufferedImage source_img,
                                     BufferedImage dest_img) {

    // If no destination image provided, make one of same form as source
    if (dest_img == null)
        dest_img = createCompatibleDestImage (source_img, null);

    int width = source_img.getWidth ();
    int height= source_img.getHeight ();

    for (int y=0; y < height; y++) {
        for (int x=0; x < width; x++) {
            int pixel = source_img.getRGB (x,y);

            // Get the component colors
            int red   = (pixel >> 16) & 0xff;
            int green = (pixel >> 8)  & 0xff;
            int blue  =  pixel        & 0xff;

            // Rotate the values
            int tmp = blue;
            blue = green;
            green = red;
            red = tmp;

            // Put new value into corresponding pixel of destination image;
            pixel =   (255 << 24) |  (red << 16) |  (green << 8) | blue;
            dest_img.setRGB (x,y,pixel);
        }
    }
    return dest_img;
  } // filter

  /**
    *  Create a destination image if needed. Must be same width as source
    *  and will by default use the same color model. Otherwise, it will use
    *  the one passed to it.
   **/
  public BufferedImage createCompatibleDestImage (BufferedImage source_img,
                                            ColorModel dest_color_model) {
    // If no color model passed, use the same as in source
    if (dest_color_model == null)
        dest_color_model = source_img.getColorModel ();

    int width = source_img.getWidth ();
    int height= source_img.getHeight ();

    // Create a new image with this color model & raster. Check if the
    // color components already multiplied by the alpha factor.
    return new BufferedImage (
           dest_color_model,
           dest_color_model.createCompatibleWritableRaster (width,height),
           dest_color_model.isAlphaPremultiplied (),
           null);
  } // createCompatibleDestImage

  /** Use the source image for the destination bounds size. **/
  public final Rectangle2D getBounds2D (BufferedImage source_img) {
    return source_img.getRaster ().getBounds ();
  } // getBounds2D

  /** The point in the source corresponds to same point
    * in the destination.
   **/
  public final Point2D getPoint2D (Point2D source_point,
                                   Point2D dest_point) {

    if (dest_point == null) dest_point = new Point2D.Float ();
    dest_point.setLocation (source_point.getX (), source_point.getY ());
    return dest_point;
  } // getPoint2D

  /** This filter doesn't provide any rendering hints. **/
  public final RenderingHints getRenderingHints () {
    return null;
  }

}// class RotateOp

See Knudsen (1999) and the other references for more details about creating custom filters.

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.