package resampler;

import javax.vecmath.Color3f;
import javax.vecmath.Point2f;

import resampler.ui.MainFrame;

public class AxisAlignedResampler extends Resampler
{

    /**
     * 
     * @param inputImage
     * @param outputImage
     * @param clippingMode
     */
    public AxisAlignedResampler(Image inputImage, Image outputImage, boolean clipToDestination)
    {
        super(inputImage, outputImage, clipToDestination);
    }
    
    /**
     * Do resampling and write the result
     * to the outputImage
     */
    protected void resample()
    {
        // the points passed in are always in a 
        // top left -> top right -> bottom right -> bottom left
        // order
        resample(inputPoints[3], inputPoints[1],
                outputPoints[3], outputPoints[1]);
    }
    
    /**
     * Do resampling and write the result
     * to the outputImage.  The coordinate system
     * follows the OpenGL convention that the x axis
     * goes form left to right, while y axis goes
     * from bottom to top.
     * 
     * @param srcBottomLeft
     * @param srcTopRight
     * @param dstBottomLeft
     * @param dstTopRight
     */
    protected void resample(Point2f srcBottomLeft, Point2f srcTopRight, 
            Point2f dstBottomLeft, Point2f dstTopRight)
    {
        // TODO Change the resampling code here
        float dxO = (srcTopRight.x - srcBottomLeft.x) / (dstTopRight.x - dstBottomLeft.x);
        float dyO = (srcTopRight.y - srcBottomLeft.y) / (dstTopRight.y - dstBottomLeft.y);
        float oxO = (srcBottomLeft.x * dstTopRight.x - srcTopRight.x * dstBottomLeft.x) / (dstTopRight.x - dstBottomLeft.x);
        float oyO = (srcBottomLeft.y * dstTopRight.y - srcTopRight.y * dstBottomLeft.y) / (dstTopRight.y - dstBottomLeft.y);
        
        int xlN, xhN, ylN, yhN;
        if (clipToDestination) {
            xlN = (int) Math.ceil(dstBottomLeft.x);
            xhN = (int) Math.floor(dstTopRight.x);
            ylN = (int) Math.ceil(dstBottomLeft.y);
            yhN = (int) Math.floor(dstTopRight.y);
        } else {
            xlN = ylN = 0;
            xhN = outputImage.width - 1;
            yhN = outputImage.height - 1;
        }
        
        Color3f color = new Color3f();
        float yO = oyO + dyO * ylN;
        for (int iyN = ylN; iyN <= yhN; iyN++) {
            float xO = oxO + dxO * xlN;
            for (int ixN = xlN; ixN <= xhN; ixN++) {
                int ixO = (int) (xO + 0.5f), iyO = (int) (yO + 0.5f);
                inputImage.getPixel(ixO, iyO, color);
                outputImage.setPixel(ixN, iyN, color);
                xO += dxO;
            }
            yO += dyO;
        }
    }
    
    /**
     * Resamples the whole image
     */
    public void resampleAll()
    {
        resample(
            new Point2f(0, 0),
            new Point2f(inputImage.width, inputImage.height),
            new Point2f(0, 0),
            new Point2f(outputImage.width, outputImage.height));
    }

}
