Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

JVM Languages

Custom Image Processing in Java


Processing an Image with BufferedImageOp

Filtering a BufferedImage can be done onscreen at painting time or offscreen.

In both cases, you need a source image and an operation, an instance of BufferedImageOp. Processing the image at painting time is the easiest approach; here is how you might do it:

// createImageOp returns a useful image filter
BufferedImageOp op = createImageOp();
// loadSourceImage returns a valid image
BufferedImage sourceImage = loadSourceImage();
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
// Filter the image with a BufferedImageOp, then draw it
g2.drawImage(sourceImage, op, 0, 0);
}

You can filter an image at painting time by invoking the drawImage(BufferedImage, BufferedImageOp, int, int) method in Graphics2D that filters the source image and draws it at the specified location.


Warning: Use Image Filters with Care. The drawImage(BufferedImage, BufferedImageOp, int, int) method is very convenient but often has poor runtime performance. An image filter is likely to perform at least a few operations for every pixel in the source image, which easily results in hundreds of thousands, or even millions, of operations on medium or large images. Besides, this method might have to create a temporary image, which takes time and memory. For every filter you want to use, you will have to see whether the runtime performance is acceptable or not.

Here is an example of how to preprocess an image by doing all the operations offscreen:


BufferedImageOp op = createImageOp();
BufferedImage sourceImage = loadSourceImage();
BufferedImage destination;
destination = op.filter(sourceImage, null);

Calling the filter() method on a BufferedImageOp triggers the processing of the source image and the generation of the destination image. The second parameter, set to null here, is actually the destination image, which, when set to null, tells the filter() method to create a new image of the appropriate size.

You can, instead, pass a non-null BufferedImage object as this parameter to avoid creating a new one on each invocation. Doing so can save performance by reducing costly image creations.

The following code example shows how you can optimize a routine applying the same filter on several images of the same size:


BufferedImageOp op = createImageOp();
BufferedImage[] sourceImagesArray = loadImages();
BufferedImage destination = null;
for (BufferedImage sourceImage : sourceImagesArray) {
// on the first pass, destination is null
// so we need to retrieve the reference to
// the newly created BufferedImage
destination = op.filter(sourceImage, destination);
saveImage(destination);
}

After the first pass in the loop, the destination will be non-null and filter() will not create a new BufferedImage when invoked. By doing so, we also make sure that the destination is in a format optimized for the filter, as it is created by the filter itself.

Processing an image with Java 2D is an easy task. No matter which method you choose, you will need to write only one line of code. But we haven’t seen any concrete BufferedImageOp yet and have just used an imaginary createImageOp() method that was supposedly returning a useful filter. As of Java SE 6, the JDK contains five implementations of BufferedImageOp we can rely on to write our own filters: AffineTransformOp, ColorConvertOp, ConvolveOp, LookupOp, and RescaleOp.

You can also write your own implementation of BufferedImageOp from scratch if the JDK does not fulfill your needs.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.