package preprocessing;

import java.awt.image.BufferedImage;

public class BicubicInterpolation {
	
	private static int interpolate (int v0, int v1, int v2, int v3)
	{
	    double P = (v3 - v2) - (v0 - v1);
	    double Q = (v0 - v1) - P;
	    double R = v2 - v0;
	    double S = v1;
	    double result = Math.round (P*0.125 + Q*0.25 + R*0.5 + S);
	    result = (result <   0) ?   0: result;
	    result = (result > 255) ? 255: result;
	    return (int) result;
	}
	
	public static BufferedImage bicubic_interpolation (BufferedImage inimg) {

	    int width = inimg.getWidth(null);
	    int height = inimg.getHeight(null);
	    int rwidth = 2*inimg.getWidth(null);
	    int rheight = 2*inimg.getHeight(null);

	    BufferedImage outimg = new BufferedImage(rwidth, rheight, BufferedImage.TYPE_INT_ARGB);
	    int[] tmp = new int[width*height];
	    int[] out = new int[rwidth*rheight];

	    int[] inarray = Util.getImageArray(inimg);
	   
	    int size = width * height - 3;
	    for(int x = 1; x < size; x++) {
	        if ( (x + 3) % width == 0 )  x += 4;
	        {
	        int A = inarray[x-1] - inarray[x];
	        int P = (inarray[x+2] - inarray[x+1]) - A;
	        int Q = A - P;
	        int R = inarray[x+1] - inarray[x-1];
	        int r = (int)(Math.round (P*0.125 + Q*0.25 + R*0.5 + inarray[x]) );
	        r = (r < 0) ? 0 : r;
	        r = (r > 255) ? 255 : r;
	        tmp[x] = r;
	        }
	    }

	    for (int y = 1, l = 1; y < height - 2; y++, l+=2) {
	        for (int x = 1, k = 1; x < width - 2; x++, k+=2) {
	            int pos = x + y * width;
	            out[k +         l*rwidth] = inarray[pos];
	            out[k + 1 +     l*rwidth] = tmp[pos];
	            out[k +     (l+1)*rwidth] = interpolate(inarray[pos-width], inarray[pos], inarray[pos+width], inarray[pos+2*width]);
	            out[k + 1 + (l+1)*rwidth] = interpolate(tmp[pos-width], tmp[pos], tmp[pos+width], tmp[pos+2*width]);
	        }
	    }

	    int startX = 0; int startY = 0;
	    Util.greyToColorImage (out, rwidth, rheight);
	    outimg.setRGB(startX, startY, rwidth, rheight, out, 0, rwidth);
	    return outimg;
	}
	
}	