/* AffineTransformOp.java --  This class performs affine 
   transformation between two images or rasters in 2 dimensions.
   Copyright (C) 2004 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.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;

/**
 * This class performs affine transformation between two images or 
 * rasters in 2 dimensions. 
 *
 * @author Olga Rodimina (rodimina@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
     */
    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
     */
    public AffineTransformOp (AffineTransform xform, RenderingHints hints)
    {
      this.transform = xform;
      this.hints = hints;
      if (xform.getDeterminant() == 0)
        throw new ImagingOpException(null);
    }

    /**
     * Creates empty BufferedImage with the size equal to that of the 
     * transformed image and correct number of bands. The newly created 
     * image is created with the specified ColorModel. 
     * If the ColorModel is equal to null, then image is created 
     * with the ColorModel of the source image.
     *
     * @param src source image
     * @param destCM color model for the destination image
     * @return new compatible destination image
     */
    public BufferedImage createCompatibleDestImage (BufferedImage src,
                                                    ColorModel destCM)
    {

      // if destCm is not specified, use color model of the source image

      if (destCM == null) 
        destCM = src.getColorModel ();

      return new BufferedImage (destCM, 
                                createCompatibleDestRaster (src.getRaster ()),
                                src.isAlphaPremultiplied (),
                                null);		             

    }

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

      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. 
     *
     * @param src source image
     * @param dst destination image
     * @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 BufferedImage is 
      // created with ColorModel of the source image

      if (dst == null)
        dst = createCompatibleDestImage(src, src.getColorModel ());

      // FIXME: Must check if color models of src and dst images are the same.
      // If it is not, then source image should be converted to color model
      // of the destination image

      Graphics2D gr = (Graphics2D) 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.
     *
     * @param src source raster
     * @param dst destination raster
     * @return transformed raster
     */
    public final WritableRaster filter (Raster src, WritableRaster dst)
    {
      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");
      
      double[] dpts = new double[dst.getWidth() * 2];
      double[] pts = new double[dst.getWidth() * 2];
      for (int x = 0; x < dst.getWidth(); x++)
      {
	dpts[2 * x] = x + dst.getMinX();
	dpts[2 * x + 1] = x;
      }
      Rectangle srcbounds = src.getBounds();
      if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR))
      {
	for (int y = dst.getMinY(); y < dst.getMinY() + dst.getHeight(); y++)
	  {
	    try {
	      transform.inverseTransform(dpts, 0, pts, 0, dst.getWidth() * 2);
	    } catch (NoninvertibleTransformException e) {
	      // Can't happen since the constructor traps this
	      e.printStackTrace();
	    }
        
	    for (int x = 0; x < dst.getWidth(); x++)
	      {
		if (!srcbounds.contains(pts[2 * x], pts[2 * x + 1]))
		  continue;
		dst.setDataElements(x + dst.getMinX(), y,
				    src.getDataElements((int)pts[2 * x],
							(int)pts[2 * x + 1],
							null));
	      }
	  }
      }
      else if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_BILINEAR))
      {
        double[] tmp = new double[4 * src.getNumBands()];
        for (int y = dst.getMinY(); y < dst.getMinY() + dst.getHeight(); y++)
        {
          try {
            transform.inverseTransform(dpts, 0, pts, 0, dst.getWidth() * 2);
          } catch (NoninvertibleTransformException e) {
            // Can't happen since the constructor traps this
            e.printStackTrace();
          }
	    
          for (int x = 0; x < dst.getWidth(); x++)
          {
            if (!srcbounds.contains(pts[2 * x], pts[2 * x + 1]))
              continue;
            int xx = (int)pts[2 * x];
            int yy = (int)pts[2 * x + 1];
            double dx = (pts[2 * x] - xx);
            double dy = (pts[2 * x + 1] - yy);
		
            // TODO write this more intelligently
            if (xx == src.getMinX() + src.getWidth() - 1 ||
                yy == src.getMinY() + src.getHeight() - 1)
            {
              // bottom or right edge
              Arrays.fill(tmp, 0);
              src.getPixel(xx, yy, tmp);
            }
            else
	    {
              // Normal case
              src.getPixels(xx, yy, 2, 2, tmp);
	      for (int b = 0; b < src.getNumBands(); b++)
		tmp[b] = dx * dy * tmp[b]
		  + (1 - dx) * dy * tmp[b + src.getNumBands()]
		  + dx * (1 - dy) * tmp[b + 2 * src.getNumBands()]
		  + (1 - dx) * (1 - dy) * tmp[b + 3 * src.getNumBands()];
	    }
            dst.setPixel(x, y, tmp);
          }
        }
      }
      else
      {
        // Bicubic
        throw new UnsupportedOperationException("not implemented yet");
      }
      
      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)
    {
      // determine new size for the transformed raster.
      // Need to calculate transformed coordinates of the lower right
      // corner of the raster. The upper left corner is always (0,0)
              
      double x2 = (double) src.getWidth () + src.getMinX ();
      double y2 = (double) src.getHeight () + src.getMinY ();
      Point2D p2 = getPoint2D (new Point2D.Double (x2,y2), null);

      Rectangle2D rect = new Rectangle (0, 0, (int) p2.getX (), (int) p2.getY ());
      return rect.getBounds ();
    }

    /**
     * Returns interpolation type used during transformations
     *
     * @return interpolation type
     */
    public final int getInterpolationType ()
    {
      if(hints.containsValue (RenderingHints.VALUE_INTERPOLATION_BILINEAR))
        return TYPE_BILINEAR;
      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 rendering hints
     */
    public final RenderingHints getRenderingHints ()
    {
      return hints;
    }

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