/* AffineTransformOp.java --  This class performs affine
   transformation between two images or rasters in 2 dimensions.
   Copyright (C) 2004, 2006 Free Software Foundation

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath 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 for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */

package java.awt.image;

import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.Arrays;

/**
 * AffineTransformOp performs matrix-based transformations (translations,
 * scales, flips, rotations, and shears).
 *
 * If interpolation is required, nearest neighbour, bilinear, and bicubic
 * methods are available.
 *
 * @author Olga Rodimina (rodimina@redhat.com)
 * @author Francis Kung (fkung@redhat.com)
 */
public class AffineTransformOp implements BufferedImageOp, RasterOp
{
    public static final int TYPE_NEAREST_NEIGHBOR = 1;

    public static final int TYPE_BILINEAR = 2;

    /**
     * @since 1.5.0
     */
    public static final int TYPE_BICUBIC = 3;

    private AffineTransform transform;
    private RenderingHints hints;

    /**
     * Construct AffineTransformOp with the given xform and interpolationType.
     * Interpolation type can be TYPE_BILINEAR, TYPE_BICUBIC or
     * TYPE_NEAREST_NEIGHBOR.
     *
     * @param xform AffineTransform that will applied to the source image
     * @param interpolationType type of interpolation used
     * @throws ImagingOpException if the transform matrix is noninvertible
     */
    public AffineTransformOp (AffineTransform xform, int interpolationType)
    {
      this.transform = xform;
      if (xform.getDeterminant() == 0)
        throw new ImagingOpException(null);

      switch (interpolationType)
      {
      case TYPE_BILINEAR:
        hints = new RenderingHints (RenderingHints.KEY_INTERPOLATION,
                                    RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        break;
      case TYPE_BICUBIC:
        hints = new RenderingHints (RenderingHints.KEY_INTERPOLATION,
                                    RenderingHints.VALUE_INTERPOLATION_BICUBIC);
        break;
      default:
        hints = new RenderingHints (RenderingHints.KEY_INTERPOLATION,
                                    RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
      }
    }

    /**
     * Construct AffineTransformOp with the given xform and rendering hints.
     *
     * @param xform AffineTransform that will applied to the source image
     * @param hints rendering hints that will be used during transformation
     * @throws ImagingOpException if the transform matrix is noninvertible
     */
    public AffineTransformOp (AffineTransform xform, RenderingHints hints)
    {
      this.transform = xform;
      this.hints = hints;
      if (xform.getDeterminant() == 0)
        throw new ImagingOpException(null);
    }

    /**
     * Creates a new BufferedImage with the size equal to that of the
     * transformed image and the correct number of bands. The newly created
     * image is created with the specified ColorModel.
     * If a ColorModel is not specified, an appropriate ColorModel is used.
     *
     * @param src the source image.
     * @param destCM color model for the destination image (can be null).
     * @return a new compatible destination image.
     */
    public BufferedImage createCompatibleDestImage (BufferedImage src,
                                                    ColorModel destCM)
    {
      if (destCM != null)
        return new BufferedImage(destCM,
                                 createCompatibleDestRaster(src.getRaster()),
                                 src.isAlphaPremultiplied(), null);

      // This behaviour was determined by Mauve testcases, and is compatible
      // with the reference implementation
      if (src.getType() == BufferedImage.TYPE_INT_ARGB_PRE
          || src.getType() == BufferedImage.TYPE_4BYTE_ABGR
          || src.getType() == BufferedImage.TYPE_4BYTE_ABGR_PRE)
        return new BufferedImage(src.getWidth(), src.getHeight(), src.getType());

      else
        return new BufferedImage(src.getWidth(), src.getHeight(),
                                 BufferedImage.TYPE_INT_ARGB);
    }

    /**
     * Creates a new WritableRaster with the size equal to the transformed
     * source raster and correct number of bands .
     *
     * @param src the source raster.
     * @throws RasterFormatException if resulting width or height of raster is 0.
     * @return a new compatible raster.
     */
    public WritableRaster createCompatibleDestRaster (Raster src)
    {
      Rectangle2D rect = getBounds2D(src);

      if (rect.getWidth() == 0 || rect.getHeight() == 0)
        throw new RasterFormatException("width or height is 0");

      return src.createCompatibleWritableRaster((int) rect.getWidth(),
                                                (int) rect.getHeight());
    }

    /**
     * Transforms source image using transform specified at the constructor.
     * The resulting transformed image is stored in the destination image if one
     * is provided; otherwise a new BufferedImage is created and returned.
     *
     * @param src source image
     * @param dst destination image
     * @throws IllegalArgumentException if the source and destination image are
     *          the same
     * @return transformed source image.
     */
    public final BufferedImage filter (BufferedImage src, BufferedImage dst)
    {
      if (dst == src)
        throw new IllegalArgumentException("src image cannot be the same as "
                                         + "the dst image");

      // If the destination image is null, then use a compatible BufferedImage
      if (dst == null)
        dst = createCompatibleDestImage(src, null);

      Graphics2D gr = dst.createGraphics();
      gr.setRenderingHints(hints);
      gr.drawImage(src, transform, null);
      return dst;
    }

    /**
     * Transforms source raster using transform specified at the constructor.
     * The resulting raster is stored in the destination raster if it is not
     * null, otherwise a new raster is created and returned.
     *
     * @param src source raster
     * @param dst destination raster
     * @throws IllegalArgumentException if the source and destination are not
     *          compatible
     * @return transformed raster.
     */
    public final WritableRaster filter(Raster src, WritableRaster dst)
    {
      // Initial checks
      if (dst == src)
        throw new IllegalArgumentException("src image cannot be the same as"
                                           + " the dst image");

      if (dst == null)
        dst = createCompatibleDestRaster(src);

      if (src.getNumBands() != dst.getNumBands())
        throw new IllegalArgumentException("src and dst must have same number"
                                           + " of bands");

      // Optimization for rasters that can be represented in the RGB colormodel:
      // wrap the rasters in images, and let Cairo do the transformation
      if (ColorModel.getRGBdefault().isCompatibleSampleModel(src.getSampleModel())
          && ColorModel.getRGBdefault().isCompatibleSampleModel(dst.getSampleModel()))
        {
          WritableRaster src2 = Raster.createWritableRaster(src.getSampleModel(),
                                                            src.getDataBuffer(),
                                                            new Point(src.getMinX(),
                                                                      src.getMinY()));
          BufferedImage iSrc = new BufferedImage(ColorModel.getRGBdefault(),
                                                 src2, false, null);
          BufferedImage iDst = new BufferedImage(ColorModel.getRGBdefault(), dst,
                                                 false, null);

          return filter(iSrc, iDst).getRaster();
        }

      // Otherwise, we need to do the transformation in java code...
      // Create arrays to hold all the points
      double[] dstPts = new double[dst.getHeight() * dst.getWidth() * 2];
      double[] srcPts = new double[dst.getHeight() * dst.getWidth() * 2];

      // Populate array with all points in the *destination* raster
      int i = 0;
      for (int x = 0; x < dst.getWidth(); x++)
        {
          for (int y = 0; y < dst.getHeight(); y++)
            {
              dstPts[i++] = x;
              dstPts[i++] = y;
            }
        }
      Rectangle srcbounds = src.getBounds();

      // Use an inverse transform to map each point in the destination to
      // a point in the source.  Note that, while all points in the destination
      // matrix are integers, this is not necessarily true for points in the
      // source (hence why interpolation is required)
      try
        {
          AffineTransform inverseTx = transform.createInverse();
          inverseTx.transform(dstPts, 0, srcPts, 0, dstPts.length / 2);
        }
      catch (NoninvertibleTransformException e)
        {
          // Shouldn't happen since the constructor traps this
          throw new ImagingOpException(e.getMessage());
        }

      // Different interpolation methods...
      if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR))
        filterNearest(src, dst, dstPts, srcPts);

      else if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_BILINEAR))
        filterBilinear(src, dst, dstPts, srcPts);

      else          // bicubic
        filterBicubic(src, dst, dstPts, srcPts);

      return dst;
    }

    /**
     * Transforms source image using transform specified at the constructor and
     * returns bounds of the transformed image.
     *
     * @param src image to be transformed
     * @return bounds of the transformed image.
     */
    public final Rectangle2D getBounds2D (BufferedImage src)
    {
      return getBounds2D (src.getRaster());
    }

    /**
     * Returns bounds of the transformed raster.
     *
     * @param src raster to be transformed
     * @return bounds of the transformed raster.
     */
    public final Rectangle2D getBounds2D (Raster src)
    {
      return transform.createTransformedShape(src.getBounds()).getBounds2D();
    }

    /**
     * Returns interpolation type used during transformations.
     *
     * @return interpolation type
     */
    public final int getInterpolationType ()
    {
      if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_BILINEAR))
        return TYPE_BILINEAR;

      else if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_BICUBIC))
        return TYPE_BICUBIC;

      else
        return TYPE_NEAREST_NEIGHBOR;
    }

    /**
     * Returns location of the transformed source point. The resulting point
     * is stored in the dstPt if one is specified.
     *
     * @param srcPt point to be transformed
     * @param dstPt destination point
     * @return the location of the transformed source point.
     */
    public final Point2D getPoint2D (Point2D srcPt, Point2D dstPt)
    {
      return transform.transform (srcPt, dstPt);
    }

    /**
     * Returns rendering hints that are used during transformation.
     *
     * @return the rendering hints used in this Op.
     */
    public final RenderingHints getRenderingHints ()
    {
      return hints;
    }

    /**
     * Returns transform used in transformation between source and destination
     * image.
     *
     * @return the transform used in this Op.
     */
    public final AffineTransform getTransform ()
    {
      return transform;
    }

    /**
     * Perform nearest-neighbour filtering
     *
     * @param src the source raster
     * @param dst the destination raster
     * @param dpts array of points on the destination raster
     * @param pts array of corresponding points on the source raster
     */
    private void filterNearest(Raster src, WritableRaster dst, double[] dpts,
                               double[] pts)
    {
      Rectangle srcbounds = src.getBounds();

      // For all points on the destination raster, copy the value from the
      // corrosponding (rounded) source point
      for (int i = 0; i < dpts.length; i += 2)
        {
          int srcX = (int) Math.round(pts[i]) + src.getMinX();
          int srcY = (int) Math.round(pts[i + 1]) + src.getMinY();

          if (srcbounds.contains(srcX, srcY))
            dst.setDataElements((int) dpts[i] + dst.getMinX(),
                                (int) dpts[i + 1] + dst.getMinY(),
                                src.getDataElements(srcX, srcY, null));
        }
    }

    /**
     * Perform bilinear filtering
     *
     * @param src the source raster
     * @param dst the destination raster
     * @param dpts array of points on the destination raster
     * @param pts array of corresponding points on the source raster
     */
    private void filterBilinear(Raster src, WritableRaster dst, double[] dpts,
                              double[] pts)
    {
      Rectangle srcbounds = src.getBounds();

      Object xyarr = null;
      Object xp1arr = null;
      Object yp1arr = null;
      Object xyp1arr = null;

      double xy;
      double xp1;
      double yp1;
      double xyp1;

      double[] result = new double[src.getNumBands()];

      // For all points in the destination raster, use bilinear interpolation
      // to find the value from the corrosponding source points
      for (int i = 0; i < dpts.length; i += 2)
        {
          int srcX = (int) Math.round(pts[i]) + src.getMinX();
          int srcY = (int) Math.round(pts[i + 1]) + src.getMinY();

          if (srcbounds.contains(srcX, srcY))
            {
              // Corner case at the bottom or right edge; use nearest neighbour
              if (pts[i] >= src.getWidth() - 1
                  || pts[i + 1] >= src.getHeight() - 1)
                dst.setDataElements((int) dpts[i] + dst.getMinX(),
                                    (int) dpts[i + 1] + dst.getMinY(),
                                    src.getDataElements(srcX, srcY, null));

              // Standard case, apply the bilinear formula
              else
                {
                  int x = (int) Math.floor(pts[i] + src.getMinX());
                  int y = (int) Math.floor(pts[i + 1] + src.getMinY());
                  double xdiff = pts[i] + src.getMinX() - x;
                  double ydiff = pts[i + 1] + src.getMinY() - y;

                  // Get surrounding pixels used in interpolation... optimized
                  // to use the smallest datatype possible.
                  if (src.getTransferType() == DataBuffer.TYPE_DOUBLE
                      || src.getTransferType() == DataBuffer.TYPE_FLOAT)
                    {
                      xyarr = src.getPixel(x, y, (double[])xyarr);
                      xp1arr  = src.getPixel(x+1, y, (double[])xp1arr);
                      yp1arr = src.getPixel(x, y+1, (double[])yp1arr);
                      xyp1arr = src.getPixel(x+1, y+1, (double[])xyp1arr);
                    }
                  else
                    {
                      xyarr = src.getPixel(x, y, (int[])xyarr);
                      xp1arr  = src.getPixel(x+1, y, (int[])xp1arr);
                      yp1arr = src.getPixel(x, y+1, (int[])yp1arr);
                      xyp1arr = src.getPixel(x+1, y+1, (int[])xyp1arr);
                    }
                  // using
                  // array[] pixels = src.getPixels(x, y, 2, 2, pixels);
                  // instead of doing four individual src.getPixel() calls
                  // should be faster, but benchmarking shows that it's not...

                  // Run interpolation for each band
                  for (int j = 0; j < src.getNumBands(); j++)
                    {
                      // Pull individual sample values out of array
                      if (src.getTransferType() == DataBuffer.TYPE_DOUBLE
                          || src.getTransferType() == DataBuffer.TYPE_FLOAT)
                        {
                          xy = ((double[])xyarr)[j];
                          xp1  = ((double[])xp1arr)[j];
                          yp1 = ((double[])yp1arr)[j];
                          xyp1 = ((double[])xyp1arr)[j];
                        }
                      else
                        {
                          xy = ((int[])xyarr)[j];
                          xp1  = ((int[])xp1arr)[j];
                          yp1 = ((int[])yp1arr)[j];
                          xyp1 = ((int[])xyp1arr)[j];
                        }

                      // If all four samples are identical, there's no need to
                      // calculate anything
                      if (xy == xp1 && xy == yp1 && xy == xyp1)
                        result[j] = xy;

                      // Run bilinear interpolation formula
                      else
                        result[j] = (xy * (1-xdiff) + xp1 * xdiff)
                                      * (1-ydiff)
                                    + (yp1 * (1-xdiff) + xyp1 * xdiff)
                                      * ydiff;
                    }

                  dst.setPixel((int)dpts[i] + dst.getMinX(),
                               (int)dpts[i+1] + dst.getMinY(),
                               result);
                }
            }
        }
    }

    /**
     * Perform bicubic filtering
     * based on http://local.wasp.uwa.edu.au/~pbourke/colour/bicubic/
     *
     * @param src the source raster
     * @param dst the destination raster
     * @param dpts array of points on the destination raster
     * @param pts array of corresponding points on the source raster
     */
    private void filterBicubic(Raster src, WritableRaster dst, double[] dpts,
                               double[] pts)
    {
      Rectangle srcbounds = src.getBounds();
      double[] result = new double[src.getNumBands()];
      Object pixels = null;

      // For all points on the destination raster, perform bicubic interpolation
      // from corrosponding source points
      for (int i = 0; i < dpts.length; i += 2)
        {
          if (srcbounds.contains((int) Math.round(pts[i]) + src.getMinX(),
                                 (int) Math.round(pts[i + 1]) + src.getMinY()))
            {
              int x = (int) Math.floor(pts[i] + src.getMinX());
              int y = (int) Math.floor(pts[i + 1] + src.getMinY());
              double dx = pts[i] + src.getMinX() - x;
              double dy = pts[i + 1] + src.getMinY() - y;
              Arrays.fill(result, 0);

              for (int m = - 1; m < 3; m++)
                for (int n = - 1; n < 3; n++)
                  {
                    // R(x) = ( P(x+2)^3 - 4 P(x+1)^3 + 6 P(x)^3 - 4 P(x-1)^3 ) / 6
                    double r1 = 0;
                    double r2 = 0;

                    // Calculate R(m - dx)
                    double rx = m - dx + 2;
                    r1 += rx * rx * rx;

                    rx = m - dx + 1;
                    if (rx > 0)
                      r1 -= 4 * rx * rx * rx;

                    rx = m - dx;
                    if (rx > 0)
                      r1 += 6 * rx * rx * rx;

                    rx = m - dx - 1;
                    if (rx > 0)
                      r1 -= 4 * rx * rx * rx;

                    r1 /= 6;

                    // Calculate R(dy - n);
                    rx = dy - n + 2;
                    if (rx > 0)
                      r2 += rx * rx * rx;

                    rx = dy - n + 1;
                    if (rx > 0)
                      r2 -= 4 * rx * rx * rx;

                    rx = dy - n;
                    if (rx > 0)
                      r2 += 6 * rx * rx * rx;

                    rx = dy - n - 1;
                    if (rx > 0)
                      r2 -= 4 * rx * rx * rx;

                    r2 /= 6;

                    // Calculate F(i+m, j+n) R(m - dx) R(dy - n)
                    // Check corner cases
                    int srcX = x + m;
                    if (srcX >= src.getMinX() + src.getWidth())
                      srcX = src.getMinX() + src.getWidth() - 1;
                    else if (srcX < src.getMinX())
                      srcX = src.getMinX();

                    int srcY = y + n;
                    if (srcY >= src.getMinY() + src.getHeight())
                      srcY = src.getMinY() + src.getHeight() - 1;
                    else if (srcY < src.getMinY())
                      srcY = src.getMinY();

                    // Calculate once for each band, using the smallest
                    // datatype possible
                    if (src.getTransferType() == DataBuffer.TYPE_DOUBLE
                        || src.getTransferType() == DataBuffer.TYPE_FLOAT)
                      {
                        pixels = src.getPixel(srcX, srcY, (double[])pixels);
                        for (int j = 0; j < result.length; j++)
                          result[j] += ((double[])pixels)[j] * r1 * r2;
                      }
                    else
                      {
                        pixels = src.getPixel(srcX, srcY, (int[])pixels);
                        for (int j = 0; j < result.length; j++)
                          result[j] += ((int[])pixels)[j] * r1 * r2;
                      }
                  }

              // Put it all together
              dst.setPixel((int)dpts[i] + dst.getMinX(),
                           (int)dpts[i+1] + dst.getMinY(),
                           result);
            }
        }
    }
}
