package visual.statik.sampled;

import java.awt.*;
import java.awt.geom.*;
import java.awt.image.*;

/**
 * A BufferedImageOp that returns (a copy of) the source
 * image unchanged.
 *
 * This class is unlikely to be used directly.  However,
 * it is convenient to extend this class when implementing
 * other operations.  In such cases, it is often only
 * necessary to override the filter() method.
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public class IdentityOp implements BufferedImageOp
{
    //[copy.

    /**
     * Copy a BufferedImage into a compatible BufferedImage
     *
     * @param src      The source image
     * @param dst An empty image in which to store the result
     */
    private void copy(BufferedImage src, BufferedImage dst)
    {
       ColorModel       dstColorModel, srcColorModel;
       int              dstRGB, height, srcRGB, width;
       int[]            dstColor, srcColor;       
       Raster           srcRaster;
       

       width            = src.getWidth();
       height           = src.getHeight();

       srcColorModel    = src.getColorModel();
       srcRaster        = src.getRaster();
       srcColor         = new int[4];
       
       dstColorModel = dst.getColorModel();
       
       for (int x=0; x<width; x++)
       {
          for (int y=0; y<height; y++)
          {
             srcRGB = src.getRGB(x, y);
             srcColorModel.getComponents(srcRGB,srcColor,0);

             dstRGB = dstColorModel.getDataElement(srcColor,0);
             dst.setRGB(x, y, dstRGB);                
          }
       }
    }
    //]copy.


    //[1.

    /**
     * Creates a zeroed destination image with the correct size 
     * and number of bands (required by BufferedImageOp)
     *
     * @param src         The source image
     * @param dstCM  The ColorModel to be used in the created image
     */
    public BufferedImage createCompatibleDestImage(
                                             BufferedImage src,
                                             ColorModel    dstCM)
    {
       BufferedImage      dst;       
       int                height, width;
       WritableRaster     raster;
       

       if (dstCM == null) dstCM = src.getColorModel();
       
       height = src.getHeight();
       width  = src.getWidth();
       raster = dstCM.createCompatibleWritableRaster(width, 
                                                     height);
       

       dst = new BufferedImage(dstCM, raster,
                               dstCM.isAlphaPremultiplied(), 
                               null);
       
       return dst;       
    }
    //]1.
    

    //[2.

    /**
     * In general, performs a single-input/single-output operation on a 
     * BufferedImage (required by BufferedImageOp).
     *
     * If the destination image is null, a BufferedImage with an
     * appropriate ColorModel is created.
     *
     * In this case, this method simply "returns" a (copy of) the 
     * source.
     *
     * @param src      The source image
     * @param dst An empty image in which to srote the result (or null)
     */
    public BufferedImage filter(BufferedImage src, 
                                BufferedImage dst)
    {
       // Construct the destination image if one isn't provided
       if (dst == null)
       {
          dst = createCompatibleDestImage(src, 
                                          src.getColorModel());
       }

       // Copy the source to the destination
       copy(src, dst);

       // Return the destination (in case it is new)
       return dst;
    }
    //]2.


    //[3.

    /**
     * Returns the bounding box of the filtered destination image
     * (required by BufferedImageOp)
     *
     * @param src   The source image
     */
    public Rectangle2D getBounds2D(BufferedImage src)
    {
       Raster       raster;
       
       raster = src.getRaster();
       
       return raster.getBounds();       
    }
    

    /**
     * Returns the location of the corresponding destination point 
     * given a point in the source image (required by BufferedImageOp).
     *
     * If dstPt is specified, it is used to hold the return value.
     *
     * @param srcPt      The point in the source image
     * @param dstPt The point in the destination image
     */
    public Point2D getPoint2D(Point2D srcPt, Point2D dstPt)
    {
       if (dstPt == null) dstPt = (Point2D)srcPt.clone();
       dstPt.setLocation(srcPt);       

       return dstPt;
    }


    /**
     * Return the rendering hints for this operation
     * (required by BufferedImageOp).
     *
     * In this case, this method always returns null.
     */
    public RenderingHints getRenderingHints()
    {
       return null;
    }
    //]3.
}
