![]() ![]() ![]() ![]() |
Working with Graphics |
All image filters must be subclasses of the ImageFilterclass. If your image filter will be modifying the colors or transparency of an image, then instead of creating a direct subclass of ImageFilter, you'll probably want to create a subclass of RGBImageFilter.
![]()
Before writing an image filter, you first should find others, studying any that are similar to what you plan to write.
Finding Examples
You can find examples of RGBImageFilter subclasses in the applets mentioned on a previous page (Dynamically Generated Color Bullets, Live Feedback ImageMap, and Image Test).Later in this page, you'll see an example of a direct ImageFilter subclass, named RotateFilter.
Creating an ImageFilter Subclass
As we mentioned before, image filters implement the ImageConsumerinterface. This lets them intercept data intended for the image consumer. ImageConsumer defines the following methods:
The ImageFilter class implements all the above methods so that they forward the method data to the filter's consumer. For example, ImageFilter implements thevoid setDimensions(int width, int height); void setProperties(Hashtable props); void setColorModel(ColorModel model); void setHints(int hintflags); void setPixels(int x, int y, int w, int h, ColorModel model, byte pixels[], int off, int scansize); void setPixels(int x, int y, int w, int h, ColorModel model, int pixels[], int off, int scansize); void imageComplete(int status);setDimensions()
method as follows:Thanks to these ImageFilter methods, your subclass probably doesn't need to implement every ImageConsumer method. You need to implement only the ImageConsumer methods that transmit data you want to change.public void setDimensions(int width, int height) { consumer.setDimensions(width, height); }For example, the CropImageFilter
class implements four of the ImageConsumer methods:
setDimensions()
,setProperties()
, and both varieties ofsetPixels()
. It also implements a constructor with arguments that specify the rectangle to be cropped. As another example, the RGBImageFilterclass implements some helper methods (including one that its subclasses must implement) and the following ImageConsumer methods:
setColorModel()
and both varieties ofsetPixels()
.Most, if not all, filters implement the
setPixels()
methods. These methods determine exactly what image data is used to construct the Image. One or both of thesetPixels()
methods may be called multiple times during the construction of a single image. Each call gives the ImageConsumer information about a rectangle of pixels within the image. When the ImageConsumer receives animageComplete()
message, then it can assume that it will receive no furthersetPixels()
calls, and that the image data is complete.The following illustration and table describe the arguments to the
setPixels()
methods.
![]()
x
,y
- Specify the pixel (relative to the image origin) at which this rectangle begins.
w
,h
- Specify the width and height, in pixels, of this rectangle.
model
- Specifies the color model used by the pixels in this rectangle.
pixels[]
- Specifies an array of pixels. The rectangle of image data is contained in this array, but the array might contain more than
w
*h
entries, depending on the values ofoffset
andscansize
. Here's the formula for determining what entry in thepixels
array contains the data for the pixel at (m,n).The above formula assumes that (m,n) is in the rectangle thisoffset + (m - x) + (n - y) * scansize [CHECK!]setPixels()
call specifies, and that (m,n) is relative to the image origin. Below is an illustration of thepixels
array that might make this clearer. It shows how a specific pixel (for example, (x,y)) maps to an entry in thepixels
array.
![]()
offset
- Specifies the index (in the
pixels
array) of the first pixel in the rectangle.scansize
- Specifies the width of each row in the
pixels
array. Due to efficiency considerations, this might be greater thanw
.The RotateFilter Image Filter
The RotateFilter class rotates an image by the specified angle. It relies on the following graphics formulas to calculate the new position of each pixel:RotateFilter implements the following ImageConsumer methods:newX = oldX*cos(angle) - oldY*sin(angle) newY = oldX*sin(angle) + oldY*cos(angle)
setDimensions()
- Records the unfiltered image's width and height for use in the
setPixels()
andimageComplete()
methods. Calculates the filtered image's final width and height, records it for use in itsimageComplete()
method, creates a buffer to store the image data as it comes in, and calls the consumer'ssetDimensions()
method to set the new width and height.setProperties()
- Adds this filter to the list of filters used by the image, and then forwards all properties to the consumer. [WHERE can you find out what all the properties are?]
setColorModel()
- Tells the consumer to expect pixels in the default RGB color model.
setHints()
- Tells the consumer to expect the image data in top-down-left-right order (the order in which you're reading this page), in complete scan lines, and with every pixel sent exactly once.
setPixels()
(both varieties of this method)- Converts the pixels to the default RGB model (if necessary) and copies the pixels into a storage buffer. Most image filters would simply modify the pixel data and forward it to the consumer, but because a rotated rectangle no longer has horizontal and vertical edges (for most angles), this filter can not efficiently forward pixels from its
setPixels()
method. Instead, RotateFilter stores all the pixel data until it receives animageComplete()
message.imageComplete()
- Rotates the image and then invokes
consumer.setPixels()
repeatedly to send each line of the image to the consumer. After sending the whole image, this method invokesconsumer.imageComplete()
.[What else do people absolutely need to know? It seems like they can assume that setDimensions() will be called before setPixels(). Are there any other assumptions they can make?]
![]() ![]() ![]() ![]() |
Working with Graphics |