Полезная информация

Exploring Java

Previous: 17.5 Image Producers and ConsumersChapter 17
Working with Images
Next: 17.7 Working with Audio
 

17.6 Filtering Image Data

As I said earlier, you rarely need to write an image consumer. However, there is one kind of image consumer that's worth knowing about. In this final section on images, we'll build a simple image filter. An image filter is simply a class that performs some work on image data before passing the data to another consumer.

The ColorSep applet acquires an image; uses an image filter to separate the image into red, green, and blue components; and displays the three resulting images. With this applet and a few million dollars, you could build your own color separation plant.

import java.awt.*;
import java.awt.image.*;
public class ColorSep extends java.applet.Applet { 
    Image img, redImg, greenImg, blueImg;
    public void init() {
        img = getImage( getClass().getResource( getParameter("img")) );
        redImg = createImage(new FilteredImageSource(img.getSource(), 
                                        new ColorMaskFilter( Color.red )));
        greenImg = createImage(new FilteredImageSource(img.getSource(), 
                                        new ColorMaskFilter( Color.green )));
        blueImg = createImage(new FilteredImageSource(img.getSource(), 
                                        new ColorMaskFilter( Color.blue )));
    }
    public void paint( Graphics g ) {
        int width = getSize().width, height = getSize().height;
        g.drawImage( redImg, 0, 0, width/3, height, this );
        g.drawImage( greenImg, width/3, 0, width/3, height, this );
        g.drawImage( blueImg, 2*width/3, 0, width/3, height, this );
    }
}
class ColorMaskFilter extends RGBImageFilter {
    Color color;
    ColorMaskFilter( Color mask ) {
        color = mask;
        canFilterIndexColorModel = true;
    }
    public int filterRGB(int x, int y, int pixel ) {
        return 
            255 << 24 |
            (((pixel & 0xff0000) >> 16) * color.getRed()/255) << 16 |
            (((pixel & 0xff00) >> 8) * color.getGreen()/255) << 8 |
            (pixel & 0xff) * color.getBlue()/255 ;
    }
}

The FilteredImageSource and RGBImageFilter classes form the basis for building and using image filters. A FilteredImageSource is an image producer (like MemoryImageSource) that is constructed from an image and an ImageFilter object. It fetches pixel data from the image and feeds it through the image filter before passing the data along. Because FilteredImageSource is an image producer, we can use it in our calls to createImage().

But where's the consumer? FilteredImageSource obviously consumes image data as well as producing it. The image consumer is still mostly hidden, but is peeking out from under its rock. Our class ColorMaskFilter extends RGBImageFilter, which in turn extends ImageFilter. And ImageFilter is (finally!) an image consumer. Of course, we still don't see the calls to addConsumer(), and we don't see an implementation of setPixels(); they're hidden in the ImageFilter sources and inherited by ColorMaskFilter.

So what does ColorMaskFilter actually do? Not much. ColorMaskFilter is a simple subclass of RGBImageFilter that implements one method, filterRGB(), through which all of the pixel data are fed. Its constructor saves a mask value we use for filtering. The filterRGB() method accepts a pixel value, along with its x and y coordinates, and returns the filtered version of the pixel. In ColorMaskFilter, we simply multiply the color components by the mask color to get the proper effect. A more complex filter, however, might use the coordinates to change its behavior based on the pixel's position.

One final detail: the constructor for ColorMaskFilter sets the flag canFilterIndexColorModel. This flag is inherited from RGBImageFilter. It means our filter doesn't depend on the pixel's position. In turn, this means it can filter the colors in a color table. If we were using an indexed color model, filtering the color table would be much faster than filtering the individual pixels.


Previous: 17.5 Image Producers and ConsumersExploring JavaNext: 17.7 Working with Audio
17.5 Image Producers and ConsumersBook Index17.7 Working with Audio

Other Books in this LibraryJava in a NutshellJava Language ReferenceJava AWTJava Fundamental ClassesExploring Java