/*
 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package java.awt.image;

import java.awt.color.ICC_Profile;
import java.awt.geom.Rectangle2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.Point2D;
import java.lang.annotation.Native;
import sun.awt.image.ImagingLib;

This class implements a convolution from the source to the destination. Convolution using a convolution kernel is a spatial operation that computes the output pixel from an input pixel by multiplying the kernel with the surround of the input pixel. This allows the output pixel to be affected by the immediate neighborhood in a way that can be mathematically specified with a kernel.

This class operates with BufferedImage data in which color components are premultiplied with the alpha component. If the Source BufferedImage has an alpha component, and the color components are not premultiplied with the alpha component, then the data are premultiplied before being convolved. If the Destination has color components which are not premultiplied, then alpha is divided out before storing into the Destination (if alpha is 0, the color components are set to 0). If the Destination has no alpha component, then the resulting alpha is discarded after first dividing it out of the color components.

Rasters are treated as having no alpha channel. If the above treatment of the alpha channel in BufferedImages is not desired, it may be avoided by getting the Raster of a source BufferedImage and using the filter method of this class which works with Rasters.

If a RenderingHints object is specified in the constructor, the color rendering hint and the dithering hint may be used when color conversion is required.

Note that the Source and the Destination may not be the same object.

See Also:
/** * This class implements a convolution from the source * to the destination. * Convolution using a convolution kernel is a spatial operation that * computes the output pixel from an input pixel by multiplying the kernel * with the surround of the input pixel. * This allows the output pixel to be affected by the immediate neighborhood * in a way that can be mathematically specified with a kernel. *<p> * This class operates with BufferedImage data in which color components are * premultiplied with the alpha component. If the Source BufferedImage has * an alpha component, and the color components are not premultiplied with * the alpha component, then the data are premultiplied before being * convolved. If the Destination has color components which are not * premultiplied, then alpha is divided out before storing into the * Destination (if alpha is 0, the color components are set to 0). If the * Destination has no alpha component, then the resulting alpha is discarded * after first dividing it out of the color components. * <p> * Rasters are treated as having no alpha channel. If the above treatment * of the alpha channel in BufferedImages is not desired, it may be avoided * by getting the Raster of a source BufferedImage and using the filter method * of this class which works with Rasters. * <p> * If a RenderingHints object is specified in the constructor, the * color rendering hint and the dithering hint may be used when color * conversion is required. *<p> * Note that the Source and the Destination may not be the same object. * @see Kernel * @see java.awt.RenderingHints#KEY_COLOR_RENDERING * @see java.awt.RenderingHints#KEY_DITHERING */
public class ConvolveOp implements BufferedImageOp, RasterOp { Kernel kernel; int edgeHint; RenderingHints hints; /** * Edge condition constants. */
Pixels at the edge of the destination image are set to zero. This is the default.
/** * Pixels at the edge of the destination image are set to zero. This * is the default. */
@Native public static final int EDGE_ZERO_FILL = 0;
Pixels at the edge of the source image are copied to the corresponding pixels in the destination without modification.
/** * Pixels at the edge of the source image are copied to * the corresponding pixels in the destination without modification. */
@Native public static final int EDGE_NO_OP = 1;
Constructs a ConvolveOp given a Kernel, an edge condition, and a RenderingHints object (which may be null).
Params:
  • kernel – the specified Kernel
  • edgeCondition – the specified edge condition
  • hints – the specified RenderingHints object
See Also:
/** * Constructs a ConvolveOp given a Kernel, an edge condition, and a * RenderingHints object (which may be null). * @param kernel the specified {@code Kernel} * @param edgeCondition the specified edge condition * @param hints the specified {@code RenderingHints} object * @see Kernel * @see #EDGE_NO_OP * @see #EDGE_ZERO_FILL * @see java.awt.RenderingHints */
public ConvolveOp(Kernel kernel, int edgeCondition, RenderingHints hints) { this.kernel = kernel; this.edgeHint = edgeCondition; this.hints = hints; }
Constructs a ConvolveOp given a Kernel. The edge condition will be EDGE_ZERO_FILL.
Params:
  • kernel – the specified Kernel
See Also:
/** * Constructs a ConvolveOp given a Kernel. The edge condition * will be EDGE_ZERO_FILL. * @param kernel the specified {@code Kernel} * @see Kernel * @see #EDGE_ZERO_FILL */
public ConvolveOp(Kernel kernel) { this.kernel = kernel; this.edgeHint = EDGE_ZERO_FILL; }
Returns the edge condition.
See Also:
Returns:the edge condition of this ConvolveOp.
/** * Returns the edge condition. * @return the edge condition of this {@code ConvolveOp}. * @see #EDGE_NO_OP * @see #EDGE_ZERO_FILL */
public int getEdgeCondition() { return edgeHint; }
Returns the Kernel.
Returns:the Kernel of this ConvolveOp.
/** * Returns the Kernel. * @return the {@code Kernel} of this {@code ConvolveOp}. */
public final Kernel getKernel() { return (Kernel) kernel.clone(); }
Performs a convolution on BufferedImages. Each component of the source image will be convolved (including the alpha component, if present). If the color model in the source image is not the same as that in the destination image, the pixels will be converted in the destination. If the destination image is null, a BufferedImage will be created with the source ColorModel. The IllegalArgumentException may be thrown if the source is the same as the destination.
Params:
  • src – the source BufferedImage to filter
  • dst – the destination BufferedImage for the filtered src
Throws:
Returns:the filtered BufferedImage
/** * Performs a convolution on BufferedImages. Each component of the * source image will be convolved (including the alpha component, if * present). * If the color model in the source image is not the same as that * in the destination image, the pixels will be converted * in the destination. If the destination image is null, * a BufferedImage will be created with the source ColorModel. * The IllegalArgumentException may be thrown if the source is the * same as the destination. * @param src the source {@code BufferedImage} to filter * @param dst the destination {@code BufferedImage} for the * filtered {@code src} * @return the filtered {@code BufferedImage} * @throws NullPointerException if {@code src} is {@code null} * @throws IllegalArgumentException if {@code src} equals * {@code dst} * @throws ImagingOpException if {@code src} cannot be filtered */
public final BufferedImage filter (BufferedImage src, BufferedImage dst) { if (src == null) { throw new NullPointerException("src image is null"); } if (src == dst) { throw new IllegalArgumentException("src image cannot be the "+ "same as the dst image"); } boolean needToConvert = false; ColorModel srcCM = src.getColorModel(); ColorModel dstCM; BufferedImage origDst = dst; // Can't convolve an IndexColorModel. Need to expand it if (srcCM instanceof IndexColorModel) { IndexColorModel icm = (IndexColorModel) srcCM; src = icm.convertToIntDiscrete(src.getRaster(), false); srcCM = src.getColorModel(); } if (dst == null) { dst = createCompatibleDestImage(src, null); dstCM = srcCM; origDst = dst; } else { dstCM = dst.getColorModel(); if (srcCM.getColorSpace().getType() != dstCM.getColorSpace().getType()) { needToConvert = true; dst = createCompatibleDestImage(src, null); dstCM = dst.getColorModel(); } else if (dstCM instanceof IndexColorModel) { dst = createCompatibleDestImage(src, null); dstCM = dst.getColorModel(); } } if (ImagingLib.filter(this, src, dst) == null) { throw new ImagingOpException ("Unable to convolve src image"); } if (needToConvert) { ColorConvertOp ccop = new ColorConvertOp(hints); ccop.filter(dst, origDst); } else if (origDst != dst) { java.awt.Graphics2D g = origDst.createGraphics(); try { g.drawImage(dst, 0, 0, null); } finally { g.dispose(); } } return origDst; }
Performs a convolution on Rasters. Each band of the source Raster will be convolved. The source and destination must have the same number of bands. If the destination Raster is null, a new Raster will be created. The IllegalArgumentException may be thrown if the source is the same as the destination.
Params:
  • src – the source Raster to filter
  • dst – the destination WritableRaster for the filtered src
Throws:
Returns:the filtered WritableRaster
/** * Performs a convolution on Rasters. Each band of the source Raster * will be convolved. * The source and destination must have the same number of bands. * If the destination Raster is null, a new Raster will be created. * The IllegalArgumentException may be thrown if the source is * the same as the destination. * @param src the source {@code Raster} to filter * @param dst the destination {@code WritableRaster} for the * filtered {@code src} * @return the filtered {@code WritableRaster} * @throws NullPointerException if {@code src} is {@code null} * @throws ImagingOpException if {@code src} and {@code dst} * do not have the same number of bands * @throws ImagingOpException if {@code src} cannot be filtered * @throws IllegalArgumentException if {@code src} equals * {@code dst} */
public final WritableRaster filter (Raster src, WritableRaster dst) { if (dst == null) { dst = createCompatibleDestRaster(src); } else if (src == dst) { throw new IllegalArgumentException("src image cannot be the "+ "same as the dst image"); } else if (src.getNumBands() != dst.getNumBands()) { throw new ImagingOpException("Different number of bands in src "+ " and dst Rasters"); } if (ImagingLib.filter(this, src, dst) == null) { throw new ImagingOpException ("Unable to convolve src image"); } return dst; }
Creates a zeroed destination image with the correct size and number of bands. If destCM is null, an appropriate ColorModel will be used.
Params:
  • src – Source image for the filter operation.
  • destCM – ColorModel of the destination. Can be null.
Returns:a destination BufferedImage with the correct size and number of bands.
/** * Creates a zeroed destination image with the correct size and number * of bands. If destCM is null, an appropriate ColorModel will be used. * @param src Source image for the filter operation. * @param destCM ColorModel of the destination. Can be null. * @return a destination {@code BufferedImage} with the correct * size and number of bands. */
public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel destCM) { BufferedImage image; int w = src.getWidth(); int h = src.getHeight(); WritableRaster wr = null; if (destCM == null) { destCM = src.getColorModel(); // Not much support for ICM if (destCM instanceof IndexColorModel) { destCM = ColorModel.getRGBdefault(); } else { /* Create destination image as similar to the source * as it possible... */ wr = src.getData().createCompatibleWritableRaster(w, h); } } if (wr == null) { /* This is the case when destination color model * was explicitly specified (and it may be not compatible * with source raster structure) or source is indexed image. * We should use destination color model to create compatible * destination raster here. */ wr = destCM.createCompatibleWritableRaster(w, h); } image = new BufferedImage (destCM, wr, destCM.isAlphaPremultiplied(), null); return image; }
Creates a zeroed destination Raster with the correct size and number of bands, given this source.
/** * Creates a zeroed destination Raster with the correct size and number * of bands, given this source. */
public WritableRaster createCompatibleDestRaster(Raster src) { return src.createCompatibleWritableRaster(); }
Returns the bounding box of the filtered destination image. Since this is not a geometric operation, the bounding box does not change.
/** * Returns the bounding box of the filtered destination image. Since * this is not a geometric operation, the bounding box does not * change. */
public final Rectangle2D getBounds2D(BufferedImage src) { return getBounds2D(src.getRaster()); }
Returns the bounding box of the filtered destination Raster. Since this is not a geometric operation, the bounding box does not change.
/** * Returns the bounding box of the filtered destination Raster. Since * this is not a geometric operation, the bounding box does not * change. */
public final Rectangle2D getBounds2D(Raster src) { return src.getBounds(); }
Returns the location of the destination point given a point in the source. If dstPt is non-null, it will be used to hold the return value. Since this is not a geometric operation, the srcPt will equal the dstPt.
/** * Returns the location of the destination point given a * point in the source. If dstPt is non-null, it will * be used to hold the return value. Since this is not a geometric * operation, the srcPt will equal the dstPt. */
public final Point2D getPoint2D(Point2D srcPt, Point2D dstPt) { if (dstPt == null) { dstPt = new Point2D.Float(); } dstPt.setLocation(srcPt.getX(), srcPt.getY()); return dstPt; }
Returns the rendering hints for this op.
/** * Returns the rendering hints for this op. */
public final RenderingHints getRenderingHints() { return hints; } }