/* * Copyright (c) 2016, Harald Kuhr * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name "TwelveMonkeys" nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.twelvemonkeys.image; import java.awt.*; import java.awt.geom.AffineTransform; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.awt.image.*; /** * This is a drop-in replacement for {@link java.awt.image.AffineTransformOp}. * <p>Currently only a modification on {@link #filter(BufferedImage, BufferedImage)} is done, which does a Graphics2D fallback for the native lib.</p> * * @author <a href="mailto:mail@schmidor.de">Oliver Schmidtmer</a> * @author last modified by $Author$ * @version $Id$ */ public class AffineTransformOp implements BufferedImageOp, RasterOp { final java.awt.image.AffineTransformOp delegate; public static final int TYPE_NEAREST_NEIGHBOR = java.awt.image.AffineTransformOp.TYPE_NEAREST_NEIGHBOR; public static final int TYPE_BILINEAR = java.awt.image.AffineTransformOp.TYPE_BILINEAR; public static final int TYPE_BICUBIC = java.awt.image.AffineTransformOp.TYPE_BICUBIC; /** * @param xform The {@link AffineTransform} to use for the operation. * @param hints The {@link RenderingHints} object used to specify the interpolation type for the operation. */ public AffineTransformOp(final AffineTransform xform, final RenderingHints hints) { delegate = new java.awt.image.AffineTransformOp(xform, hints); } /** * @param xform The {@link AffineTransform} to use for the operation. * @param interpolationType One of the integer interpolation type constants defined by this class: {@link #TYPE_NEAREST_NEIGHBOR}, {@link #TYPE_BILINEAR}, {@link #TYPE_BICUBIC}. */ public AffineTransformOp(final AffineTransform xform, final int interpolationType) { delegate = new java.awt.image.AffineTransformOp(xform, interpolationType); } @Override public BufferedImage filter(final BufferedImage src, BufferedImage dst) { try { return delegate.filter(src, dst); } catch (ImagingOpException ex) { if (dst == null) { dst = createCompatibleDestImage(src, src.getColorModel()); } Graphics2D g2d = null; try { g2d = dst.createGraphics(); int interpolationType = delegate.getInterpolationType(); if (interpolationType > 0) { Object interpolationValue = RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR; switch (interpolationType) { case java.awt.image.AffineTransformOp.TYPE_BILINEAR: interpolationValue = RenderingHints.VALUE_INTERPOLATION_BILINEAR; break; case java.awt.image.AffineTransformOp.TYPE_BICUBIC: interpolationValue = RenderingHints.VALUE_INTERPOLATION_BICUBIC; break; } g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, interpolationValue); } else if (getRenderingHints() != null) { g2d.setRenderingHints(getRenderingHints()); } g2d.drawImage(src, delegate.getTransform(), null); return dst; } finally { if (g2d != null) { g2d.dispose(); } } } } @Override public Rectangle2D getBounds2D(final BufferedImage src) { return delegate.getBounds2D(src); } @Override public BufferedImage createCompatibleDestImage(final BufferedImage src, final ColorModel destCM) { return delegate.createCompatibleDestImage(src, destCM); } @Override public WritableRaster filter(final Raster src, final WritableRaster dest) { return delegate.filter(src, dest); } @Override public Rectangle2D getBounds2D(final Raster src) { return delegate.getBounds2D(src); } @Override public WritableRaster createCompatibleDestRaster(final Raster src) { return delegate.createCompatibleDestRaster(src); } @Override public Point2D getPoint2D(final Point2D srcPt, final Point2D dstPt) { return delegate.getPoint2D(srcPt, dstPt); } @Override public RenderingHints getRenderingHints() { return delegate.getRenderingHints(); } }