![JAR search and dependency download from the Maven repository](/logo.png)
com.day.image.AbstractBufferedImageOp Maven / Gradle / Ivy
Show all versions of aem-sdk-api Show documentation
/*************************************************************************
*
* ADOBE CONFIDENTIAL
* __________________
*
* Copyright 2012 Adobe Systems Incorporated
* All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains
* the property of Adobe Systems Incorporated and its suppliers,
* if any. The intellectual and technical concepts contained
* herein are proprietary to Adobe Systems Incorporated and its
* suppliers and are protected by trade secret or copyright law.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from Adobe Systems Incorporated.
**************************************************************************/
package com.day.image;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ColorConvertOp;
import java.awt.image.ColorModel;
import java.awt.image.IndexColorModel;
import java.util.Map;
/**
* The AbstractBufferedImageOp
provides a basic implementation to
* implement the BufferedImageOp
interface. Basically this
* abstract class deals with all the intricacies of make the images compatible
* with operations on each other.
*
* The most easy use of this class is to simply implement an appropriate
* constructor and {@link #doFilter(BufferedImage, BufferedImage)} method. Other
* methods need not be overwritten unless special needs arise. See the method's
* documentations for more information.
*
* @version $Revision$
* @author fmeschbe
* @since coati
* @audience wad
*/
public abstract class AbstractBufferedImageOp implements BufferedImageOp {
/** The rendering hints for color model adaption */
protected final RenderingHints hints;
/**
* Sets the internal fields of this abstract base class.
*
* @param hints The rendering hints. May be null
. The hints
* are copied to a new object. Thus modifying the object after
* a call to this method does not modify the internal hints
* object.
*/
protected AbstractBufferedImageOp(RenderingHints hints) {
this.hints = hints == null ? null : new RenderingHints((Map) hints);
}
//---------- BufferedImageOp interface -------------------------------------
/**
* Performs the operation on a BufferedImage. This implementation only cares
* to make the images compatible and calls the
* {@link #doFilter(BufferedImage, BufferedImage)} to do the actual
* filtering operation.
*
* If the color models for the two images do not match, a color
* conversion into the destination color model will be performed.
* If the destination image is null,
* a BufferedImage with an appropriate ColorModel will be created.
*
* Note: The dest image might be clipped if it is not big enough to take
* the complete resized image.
*
* Note: Extensions to this class should not need to overwrite this method.
*
* @param src The src image to be operated upon.
* @param dst The dest image into which to place the modified image. This
* may be null
in which case a new image with the
* correct size will be created.
*
* @return The newly created image (if dest was null
) or dest
* into which the resized src image has been drawn.
*
* @throws IllegalArgumentException if the dest image is the same as the
* src image.
* @throws NullPointerException if the src image is null
.
*/
public 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(), true);
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();
}
}
doFilter(src, dst);
if (needToConvert) {
ColorConvertOp ccop = new ColorConvertOp(hints);
ccop.filter(dst, origDst);
}
else if (origDst != dst) {
Graphics2D g = origDst.createGraphics();
try {
g.drawImage(dst, 0, 0, null);
} finally {
g.dispose();
}
}
return origDst;
}
/**
* Returns the bounding box of the filtered destination image. This
* implementation returns the bounding box of the source image given. This
* method is likely to be overwritten by extending classes which implement
* filtering operation resulting in the change of the image size.
*
* The IllegalArgumentException may be thrown if the source
* image is incompatible with the types of images allowed
* by the class implementing this filter.
*/
public Rectangle2D getBounds2D(BufferedImage src) {
return src.getRaster().getBounds();
}
/**
* Creates a zeroed destination image with the correct size and number of
* bands. This calls {@link #getBounds2D(BufferedImage)} to decide on the
* size of the new image. So this method needs only be overwritten by
* extending class, which need more specialized operations than just to
* create a new image with the correct size and color model.
*
* The IllegalArgumentException may be thrown if the source
* image is incompatible with the types of images allowed
* by the class implementing this filter.
*
* @param src Source image for the filter operation.
* @param destCM ColorModel of the destination. If null, the
* ColorModel of the source will be used.
*/
public BufferedImage createCompatibleDestImage(BufferedImage src,
ColorModel destCM) {
Rectangle2D bounds = getBounds2D(src);
int w = (int) (bounds.getWidth());
int h = (int) (bounds.getHeight());
BufferedImage image;
if (destCM == null) {
destCM = src.getColorModel();
// Not much support for ICM
if (destCM instanceof IndexColorModel) {
destCM = ColorModel.getRGBdefault();
}
}
image = new BufferedImage (destCM,
destCM.createCompatibleWritableRaster(w, h),
destCM.isAlphaPremultiplied(), null);
return image;
}
/**
* Returns the location of the destination point given a
* point in the source image. If dstPt is non-null, it
* will be used to hold the return value. This method is likely to be
* overwritten by extending classes which implement filtering operation
* resulting in the change of the image size or in rotated images.
*/
public Point2D getPoint2D(Point2D srcPt, Point2D dstPt) {
if (dstPt == null) {
dstPt = (Point2D)srcPt.clone();
} else {
dstPt.setLocation(srcPt);
}
return dstPt;
}
/**
* Returns a copy of the rendering hints for this BufferedImageOp. Returns
* null if no hints have been set. Modyfing the object returned does not
* modify the rendering hints set on this.
*
* @return The rendering hints of this or null
if none are
* defined.
*/
public final RenderingHints getRenderingHints() {
return hints == null ? null : new RenderingHints((Map) hints);
}
//---------- protected -----------------------------------------------------
/**
* Implements the filter algorithm. This method is called by the
* {@link #filter(BufferedImage, BufferedImage)} method to execute the
* implementation's special filtering.
*
* Implementations are guaranteed that the source and the destination image
* are not the same and neither of the images is null
.
*
* @param src The srouce image to be operated upon.
* @param dst The destination image getting the resulting image. This must
* not be null
.
*/
protected abstract void doFilter(BufferedImage src, BufferedImage dst);
}