import java.io.*;
import java.awt.*;
import java.util.*;
import java.awt.image.*;
import Acme.JPM.Encoders.*;

public class StillUtil {
    static boolean mimg = true;

    public static ImArray loadImage(String f){
	Toolkit tk = (new Canvas()).getToolkit();
	double itot=0;
	if(f != null){
	    Image i = tk.getImage(f);
	    int h = -1;
	    int w = -1;
	    while((h < 0) || (w < 0)){
		h = i.getHeight(null);
		w = i.getWidth(null);
		try { Thread.sleep(250); } catch (Exception  e) {}
	    }
	    int[] data = new int[h*w];
	    int[] rdata = new int[h*w];
	    System.out.println("Grabbed image "+f+" with size "+h+"x"+w);
	    PixelGrabber pg = new PixelGrabber(i,0,0,w,h,
					       data,0,w);
	    try { pg.grabPixels(); }
	    catch (Exception e) { System.out.println("pixelgrabber bit me: "+e); return null; }
	    for(int y=0;y<h;y++){
		for(int x=0;x<w;x++){
		    int red = (data[y*w+x] >>16) & 0xff;
		    int green = (data[y*w+x] >> 8) & 0xff;
		    int blue = (data[y*w+x] >> 0) & 0xff;
		    rdata[y*w+x] = (int) ((red+green+blue)/3);
		    itot+= rdata[y*w+x];
		}
	    }
	    System.out.println("Image average: "+itot/(w*h));
	    for(int y=0;y<h;y++){
		for(int x=0;x<w;x++){
		    rdata[y*w+x] = (int) (rdata[y*w+x]*128/(itot/(w*h)));
		}
	    }      
	    return new ImArray(h,w,rdata, data, i);
	}
	else{
	    return null;
	}
    }

    public static cornerTransform anneal(ImArray ima, 
					 ImArray imb, 
					 cornerTransform t, 
					 double temp, 
					 double stepsize, 
					 double coolto,
					 boolean transonly){

	cornerTransform newct, cur;
	double cd, nd;
	Random rn = new Random();

	System.out.println("----------Annealing-----------");
	cd = ImArray.imageDifference(ima, imb, t);
	cur = t;
	while(temp > coolto){
	    double dir = rn.nextDouble();
	    if(transonly){
		if(dir > .75){
		    newct = cur.translate((rn.nextDouble())*stepsize, 0);
		}
		else if(dir > .5){
		    newct = cur.translate(-1*(rn.nextDouble())*stepsize, 0);
		}
		else if(dir > .25){
		    newct = cur.translate(0, -1*(rn.nextDouble())*stepsize);
		}
		else{
		    newct = cur.translate(0, (rn.nextDouble())*stepsize);
		}
	    }
	    else{
		newct = cur.copy();
		if(dir > .75){
		    newct.x0 += ((rn.nextDouble()*2.0)-1.0)*((double) stepsize);
		    newct.y0 += ((rn.nextDouble()*2.0)-1.0)*((double) stepsize);
		}
		else if(dir > .5){
		    newct.x1 += ((rn.nextDouble()*2.0)-1.0)*((double) stepsize);
		    newct.y1 += ((rn.nextDouble()*2.0)-1.0)*((double) stepsize);
		}
		else if(dir > .25){
		    newct.x2 += ((rn.nextDouble()*2.0)-1.0)*((double) stepsize);
		    newct.y2 += ((rn.nextDouble()*2.0)-1.0)*((double) stepsize);
		}
		else{
		    newct.x3 += ((rn.nextDouble()*2.0)-1.0)*((double) stepsize);
		    newct.y3 += ((rn.nextDouble()*2.0)-1.0)*((double) stepsize);
		}
	    }
	    nd = ImArray.imageDifference(ima, imb, newct);
	    if(nd < cd){
		cd = nd;
		cur = newct;
		System.out.println("New minimum: "+cd+
				   " ("+cur.x0+", "+cur.y0+")");
	    }
	    else if(Math.exp(-1*temp/(30*(nd-cd))) < rn.nextDouble()){
		System.out.println("Stepping up... to "+nd+
				   " ("+newct.x0+", "+newct.y0+")");
		cd = nd;
		cur = newct;
	    }
	    else{
		System.out.println("Not moving..."+
				   " ("+cur.x0+", "+cur.y0+")");
	    }
	    temp = temp - .5;
	}
	return cur;
    }

    public static cornerTransform downhill(ImArray ima, ImArray imb, cornerTransform t, 
					   int steps, int ssize, boolean transonly){

	cornerTransform newct, cur;
	double cd, nd;
	Random rn = new Random();
	boolean keepgoing;

	System.out.println("----------Downhill simplex----------");
	cd = ImArray.imageDifference(ima, imb, t);
	System.out.println("Starting with a difference of "+cd);
	cur = t;
	for(;steps>0;steps--){
	    System.out.println(steps+" downhill steps to go");
	    keepgoing = false;
	    newct = cur.translate(ssize, 0);
	    nd = ImArray.imageDifference(ima, imb, newct);
	    if(nd < cd){
		cd = nd;
		cur = newct;
		System.out.println("New minimum: "+cd+
				   " ("+cur.x0+", "+cur.y0+")");
		keepgoing = true;
	    }
	    System.out.print("#");
      
	    newct = cur.translate(-1*ssize, 0);
	    nd = ImArray.imageDifference(ima, imb, newct);
	    if(nd < cd){
		cd = nd;;
		cur = newct;
		System.out.println("New minimum: "+cd+
				   " ("+cur.x0+", "+cur.y0+")");
		keepgoing = true;
	    }
	    System.out.print("#");
      
	    newct = cur.translate(0, 1*ssize);
	    nd = ImArray.imageDifference(ima, imb, newct);
	    if(nd < cd){
		cd = nd;
		cur = newct;
		System.out.println("New minimum: "+cd+
				   " ("+cur.x0+", "+cur.y0+")");
		keepgoing = true;
	    }
	    System.out.print("#");
      
	    newct = cur.translate(0, -1*ssize);
	    nd = ImArray.imageDifference(ima, imb, newct);
	    if(nd < cd){
		cd = nd;;
		cur = newct;
		System.out.println("New minimum: "+cd+
				   " ("+cur.x0+", "+cur.y0+")");
		keepgoing = true;
	    }
	    System.out.print("#");
      
	    if(!transonly){
		//------------------------------------------------------------
		newct = cur.copy();
		newct.y0 -= ssize;
		newct.y2 += ssize;
		nd = ImArray.imageDifference(ima, imb, newct);
		if(nd < cd){
		    cd = nd;
		    cur = newct;
		    System.out.println("New minimum: "+cd+
				       " ("+cur.x0+", "+cur.y0+")");
		    keepgoing = true;
		}
		System.out.print(".");
		//------------------------------------------------------------
		newct = cur.copy();
		newct.y0 += ssize;
		newct.y2 -= ssize;
		nd = ImArray.imageDifference(ima, imb, newct);
		if(nd < cd){
		    cd = nd;
		    cur = newct;
		    System.out.println("New minimum: "+cd+
				       " ("+cur.x0+", "+cur.y0+")");
		    keepgoing = true;
		}
		System.out.print(".");
		//------------------------------------------------------------
		newct = cur.copy();
		newct.y1 += ssize;
		newct.y3 -= ssize;
		nd = ImArray.imageDifference(ima, imb, newct);
		if(nd < cd){
		    cd = nd;
		    cur = newct;
		    System.out.println("New minimum: "+cd+
				       " ("+cur.x0+", "+cur.y0+")");
		    keepgoing = true;
		}
		System.out.print(".");
		//------------------------------------------------------------
		newct = cur.copy();
		newct.y1 -= ssize;
		newct.y3 += ssize;
		nd = ImArray.imageDifference(ima, imb, newct);
		if(nd < cd){
		    cd = nd;
		    cur = newct;
		    System.out.println("New minimum: "+cd+
				       " ("+cur.x0+", "+cur.y0+")");
		    keepgoing = true;
		}
		System.out.print(".");
		//------------------------------------------------------------
		newct = cur.copy();
		newct.x0 += ssize;
		newct.x2 += ssize;
		nd = ImArray.imageDifference(ima, imb, newct);
		if(nd < cd){
		    cd = nd;
		    cur = newct;
		    System.out.println("New minimum: "+cd+
				       " ("+cur.x0+", "+cur.y0+")");
		    keepgoing = true;
		}
		System.out.print(".");
		//------------------------------------------------------------
		newct = cur.copy();
		newct.x0 -= ssize;
		newct.x2 -= ssize;
		nd = ImArray.imageDifference(ima, imb, newct);
		if(nd < cd){
		    cd = nd;
		    cur = newct;
		    System.out.println("New minimum: "+cd+
				       " ("+cur.x0+", "+cur.y0+")");
		    keepgoing = true;
		}
		System.out.print(".");
		//------------------------------------------------------------
		newct = cur.copy();
		newct.x1 -= ssize;
		newct.x3 -= ssize;
		nd = ImArray.imageDifference(ima, imb, newct);
		if(nd < cd){
		    cd = nd;
		    cur = newct;
		    System.out.println("New minimum: "+cd+
				       " ("+cur.x0+", "+cur.y0+")");
		    keepgoing = true;
		}
		System.out.print(".");
		//------------------------------------------------------------
		newct = cur.copy();
		newct.x1 += ssize;
		newct.x3 += ssize;
		nd = ImArray.imageDifference(ima, imb, newct);
		if(nd < cd){
		    cd = nd;
		    cur = newct;
		    System.out.println("New minimum: "+cd+
				       " ("+cur.x0+", "+cur.y0+")");
		    keepgoing = true;
		}

		System.out.print(".");
		//------------------------------------------------------------
		newct = cur.copy();
		newct.x0 += ssize;
		newct.x2 += ssize;
		newct.x1 -= ssize;
		newct.x3 -= ssize;
		nd = ImArray.imageDifference(ima, imb, newct);
		if(nd < cd){
		    cd = nd;
		    cur = newct;
		    System.out.println("New minimum: "+cd+
				       " ("+cur.x0+", "+cur.y0+")");
		    keepgoing = true;
		}
		System.out.print(".");
		//------------------------------------------------------------
		newct = cur.copy();
		newct.x0 -= ssize;
		newct.x2 -= ssize;
		newct.x1 += ssize;
		newct.x3 += ssize;
		nd = ImArray.imageDifference(ima, imb, newct);
		if(nd < cd){
		    cd = nd;
		    cur = newct;
		    System.out.println("New minimum: "+cd+
				       " ("+cur.x0+", "+cur.y0+")");
		    keepgoing = true;
		}
		System.out.print(".");
		//------------------------------------------------------------
		newct = cur.copy();
		newct.x0 += ssize;
		nd = ImArray.imageDifference(ima, imb, newct);
		if(nd < cd){
		    cd = nd;
		    cur = newct;
		    System.out.println("New minimum: "+cd+
				       " ("+cur.x0+", "+cur.y0+")");
		    keepgoing = true;
		}
		System.out.print(".");
		//------------------------------------------------------------
		newct = cur.copy();
		newct.x0 -= ssize;
		nd = ImArray.imageDifference(ima, imb, newct);
		if(nd < cd){
		    cd = nd;
		    cur = newct;
		    System.out.println("New minimum: "+cd+
				       " ("+cur.x0+", "+cur.y0+")");
		    keepgoing = true;
		}
		System.out.print(".");
		//------------------------------------------------------------
		newct = cur.copy();
		newct.y0 += ssize;
		nd = ImArray.imageDifference(ima, imb, newct);
		if(nd < cd){
		    cd = nd;
		    cur = newct;
		    System.out.println("New minimum: "+cd+
				       " ("+cur.x0+", "+cur.y0+")");
		    keepgoing = true;
		}
		System.out.print(".");
		//------------------------------------------------------------
		newct = cur.copy();
		newct.y0 -= ssize;
		nd = ImArray.imageDifference(ima, imb, newct);
		if(nd < cd){
		    cd = nd;
		    cur = newct;
		    System.out.println("New minimum: "+cd+
				       " ("+cur.x0+", "+cur.y0+")");
		    keepgoing = true;
		}
		System.out.print(".");
		//------------------------------------------------------------
		newct.x1 += ssize;
		nd = ImArray.imageDifference(ima, imb, newct);
		if(nd < cd){
		    cd = nd;
		    cur = newct;
		    System.out.println("New minimum: "+cd+
				       " ("+cur.x0+", "+cur.y0+")");
		    keepgoing = true;
		}
		System.out.print(".");
		//------------------------------------------------------------
		newct = cur.copy();
		newct.x1 -= ssize;
		nd = ImArray.imageDifference(ima, imb, newct);
		if(nd < cd){
		    cd = nd;
		    cur = newct;
		    System.out.println("New minimum: "+cd+
				       " ("+cur.x0+", "+cur.y0+")");
		    keepgoing = true;
		}
		System.out.print(".");
		//------------------------------------------------------------
		newct = cur.copy();
		newct.y1 += ssize;
		nd = ImArray.imageDifference(ima, imb, newct);
		if(nd < cd){
		    cd = nd;
		    cur = newct;
		    System.out.println("New minimum: "+cd+
				       " ("+cur.x0+", "+cur.y0+")");
		    keepgoing = true;
		}
		System.out.print(".");
		//------------------------------------------------------------
		newct = cur.copy();
		newct.y1 -= ssize;
		nd = ImArray.imageDifference(ima, imb, newct);
		if(nd < cd){
		    cd = nd;
		    cur = newct;
		    System.out.println("New minimum: "+cd+
				       " ("+cur.x0+", "+cur.y0+")");
		    keepgoing = true;
		}
		System.out.print(".");
		//------------------------------------------------------------
		newct = cur.copy();
		newct.x2 += ssize;
		nd = ImArray.imageDifference(ima, imb, newct);
		if(nd < cd){
		    cd = nd;
		    cur = newct;
		    System.out.println("New minimum: "+cd+
				       " ("+cur.x0+", "+cur.y0+")");
		    keepgoing = true;
		}
		System.out.print(".");
		//------------------------------------------------------------
		newct = cur.copy();
		newct.x2 -= ssize;
		nd = ImArray.imageDifference(ima, imb, newct);
		if(nd < cd){
		    cd = nd;
		    cur = newct;
		    System.out.println("New minimum: "+cd+
				       " ("+cur.x0+", "+cur.y0+")");
		    keepgoing = true;
		}
		System.out.print(".");
		//------------------------------------------------------------
		newct = cur.copy();
		newct.y2 += ssize;
		nd = ImArray.imageDifference(ima, imb, newct);
		if(nd < cd){
		    cd = nd;
		    cur = newct;
		    System.out.println("New minimum: "+cd+
				       " ("+cur.x0+", "+cur.y0+")");
		    keepgoing = true;
		}
		System.out.print(".");
		//------------------------------------------------------------
		newct = cur.copy();
		newct.y2 -= ssize;
		nd = ImArray.imageDifference(ima, imb, newct);
		if(nd < cd){
		    cd = nd;
		    cur = newct;
		    System.out.println("New minimum: "+cd+
				       " ("+cur.x0+", "+cur.y0+")");
		    keepgoing = true;
		}
		System.out.print(".");
		//------------------------------------------------------------
		newct = cur.copy();
		newct.x3 += ssize;
		nd = ImArray.imageDifference(ima, imb, newct);
		if(nd < cd){
		    cd = nd;
		    cur = newct;
		    System.out.println("New minimum: "+cd+
				       " ("+cur.x0+", "+cur.y0+")");
		    keepgoing = true;
		}
		System.out.print(".");
		//------------------------------------------------------------
		newct = cur.copy();
		newct.x3 -= ssize;
		nd = ImArray.imageDifference(ima, imb, newct);
		if(nd < cd){
		    cd = nd;
		    cur = newct;
		    System.out.println("New minimum: "+cd+
				       " ("+cur.x0+", "+cur.y0+")");
		    keepgoing = true;
		}
		System.out.print(".");
		//------------------------------------------------------------
		newct = cur.copy();
		newct.y3 += ssize;
		nd = ImArray.imageDifference(ima, imb, newct);
		if(nd < cd){
		    cd = nd;
		    cur = newct;
		    System.out.println("New minimum: "+cd+
				       " ("+cur.x0+", "+cur.y0+")");
		    keepgoing = true;
		}
		System.out.print(".");
		//------------------------------------------------------------
		newct = cur.copy();
		newct.y3 -= ssize;
		nd = ImArray.imageDifference(ima, imb, newct);
		if(nd < cd){
		    cd = nd;
		    cur = newct;
		    System.out.println("New minimum: "+cd+
				       " ("+cur.x0+", "+cur.y0+")");
		    keepgoing = true;
		}
		System.out.println(".");


	    }
  
	    if(!keepgoing)
		return cur;
	}
	return cur;
    }

    public static Image writeMerge(ImArray ima, ImArray imb, 
				   cornerTransform cur){
	int xmin, xmax, ymin,ymax;
	xmin = ymin = 0;
	xmax = ima.width;
	ymax = ima.height;
	for(int y = (-1*ima.height); y <(2*ima.height); y+=10){
	    for(int x = (-1*ima.width); x < (2*ima.width); x+=10){
		int ttx = cur.x((((int) (x))), (((int) (y))));
		int tty = cur.y((((int) (x))), (((int) (y))));
		if((ttx > 0) && (tty > 0) &&
		   (ttx < imb.width) && (tty < imb.height)){
		    if(y < ymin)
			ymin = y;
		    if(y > ymax)
			ymax = y;
		    if(x < xmin)
			xmin = x;
		    if(x > xmax)
			xmax = x;
		}
	    }
	}
      
	int xoffset = xmin - 10;
	int yoffset = ymin - 10;
	double xscale, yscale;
	xscale = ((double) (xmax-xmin+20))/((double) (ima.width));
	yscale = ((double) (ymax-ymin+20))/((double) (ima.height));
	int tmpct = 0;
	System.out.println("Allocating "+((int) (xscale*yscale*(ima.height+1)*(ima.width+1))+5)+" int's");
	int newim[] = new int[(int) (2.25*xscale*yscale*(ima.height+1)*(ima.width+1))+5];
	System.out.println("ImA hxw = "+ima.height+"x"+ima.width);
	double resinc=1.0;
	int sch = (int) (resinc*yscale*ima.height);
	int scw = (int) (resinc*xscale*ima.width);

	System.out.println("xoffset: "+xoffset+", yoffset: "+yoffset);

	for(int fy=0;fy<(sch);fy++){
	    for(int fx=0;fx<(scw);fx++){
		int x = (int) (((double) fx)/resinc + xoffset);
		int y = (int) (((double) fy)/resinc + yoffset);
		double dx = (((double) fx)/resinc + xoffset);
		double dy = (((double) fy)/resinc + yoffset);
		boolean ina = false, inb=false;
		if((x >0) && (y >0) &&
		   (x < ima.width) && (y < ima.height))
		    ina = true;
		int ttx;
		int tty;
		ttx = cur.x(dx,dy);
		tty = cur.y(dx,dy);
		if((ttx < imb.width) && (tty < imb.height) &&
		   (ttx > 0) && (tty > 0))
		    inb = true;
		if(ina && inb){
		    //	  if(tmpct == 0){
		    //	  if((x+y)%60 > 30){
		    //	    newim[(int) (x+(scw*y))] = 
		    //	      ima.oim[(int) ((x)+(ima.width*(y)))];
		    //	    tmpct = 1;
		    //	  }
		    //	  else {
		    //newim[(int) (x+(scw*y))] = 
		    //	      imb.oim[(int) (ttx+(imb.width*tty))];
		    //	    tmpct = 0;
		    //}
		    int bytea, byteb;
		    bytea = (ima.oim[(int) ((x)+(ima.width*(y)))]);
		    byteb = imb.oim[(int) (ttx+(imb.width*tty))];
		    int reda = (bytea >>16) & 0xff;
		    int greena = (bytea >> 8) & 0xff;
		    int bluea = (bytea >> 0) & 0xff;
		    int redb = (byteb >>16) & 0xff;
		    int greenb = (byteb >> 8) & 0xff;
		    int blueb = (byteb >> 0) & 0xff;

		    double axfact = (x < (ima.width-x)) ? x:(ima.width-x);
		    double bxfact = (ttx < (imb.width-ttx)) ? ttx:(imb.width-ttx);

		    double ayfact = (y < (ima.height-y)) ? y:(ima.height-y);
		    double byfact = (tty < (imb.height-tty)) ? tty:(imb.height-tty);

		    double afact = (axfact < ayfact) ? axfact:ayfact;
		    double bfact = (bxfact < byfact) ? bxfact:byfact;
		    //	  System.out.println("afact: "+afact+" @"+x+","+y);
		    afact = afact*afact/75;
		    bfact = bfact*bfact/75;
		    if(mimg){
			newim[(int) (fx+(scw*fy))] = 
			    ((int) (255) << 24) + 
			    (((int) (((afact*reda)+(bfact*redb))/(afact+bfact))) << 16) + 
			    (((int) (((afact*greena)+(bfact*greenb))/(afact+bfact))) << 8) +
			    (((int) (((afact*bluea)+(bfact*blueb))/(afact+bfact))) << 0);
		    }
		    else{
			int diff = 0;
			diff += Math.abs(reda-redb)/3;
			diff += Math.abs(greena-greenb)/3;
			diff += Math.abs(bluea-blueb)/3;
			newim[(int) (fx+(scw*fy))] = 
			    ((int) (255) << 24) + 
			    (diff << 16) +
			    (diff << 8) +
			    (diff << 0);	    
		    }
		}
		else if(ina)
		    newim[(int) (fx+(scw*fy))] = ima.oim[(int) ((x)+(ima.width*(y)))];
		else if(inb)
		    newim[(int) (fx+(scw*fy))] = imb.oim[(int) (ttx+(imb.width*tty))];
		else
		    newim[(int) (fx+(scw*fy))] = (255 << 24);
	    }
	}

	Toolkit tk = (new Canvas()).getToolkit();
	Image newi = tk.createImage(new MemoryImageSource((int) (scw), (int) (sch), newim, 0, (int) (scw)));
	try {
	    OutputStream fileout = new FileOutputStream("/tmp/img.ppm");
	    (new PpmEncoder(newi, fileout)).encode();
	} catch (Exception e) { System.out.println("Doh! "+e); }
	return newi;
    }

    public static Image old_writeMerge(ImArray ima, ImArray imb, 
				       cornerTransform cur){
	double nscale = 1.5;
	int tmpct = 0;
	System.out.println("Allocating "+((int) (nscale*nscale*(ima.height+1)*(ima.width+1))+5)+" int's");
	int newim[] = new int[(int) (nscale*nscale*(ima.height+1)*(ima.width+1))+5];
	System.out.println("ImA hxw = "+ima.height+"x"+ima.width);
	int sch = (int) (nscale*ima.height);
	int scw = (int) (nscale*ima.width);


	for(int y=0;y<(sch);y++){
	    for(int x=0;x<(scw);x++){
		boolean ina = false, inb=false;
		if(((((int) (x))) < ima.width) && ((((int) (y))) < ima.height))
		    ina = true;
		int ttx = cur.x((((int) (x))), (((int) (y))));
		int tty = cur.y((((int) (x))), (((int) (y))));
		if((ttx < imb.width) && (tty < imb.height) &&
		   (ttx > 0) && (tty > 0))
		    inb = true;
		if(ina && inb){
		    //	  if(tmpct == 0){
		    //	  if((x+y)%60 > 30){
		    //	    newim[(int) (x+(scw*y))] = 
		    //	      ima.oim[(int) ((x)+(ima.width*(y)))];
		    //	    tmpct = 1;
		    //	  }
		    //	  else {
		    //newim[(int) (x+(scw*y))] = 
		    //	      imb.oim[(int) (ttx+(imb.width*tty))];
		    //	    tmpct = 0;
		    //}
		    int bytea, byteb;
		    bytea = (ima.oim[(int) ((x)+(ima.width*(y)))]);
		    byteb = imb.oim[(int) (ttx+(imb.width*tty))];
		    int reda = (bytea >>16) & 0xff;
		    int greena = (bytea >> 8) & 0xff;
		    int bluea = (bytea >> 0) & 0xff;
		    int redb = (byteb >>16) & 0xff;
		    int greenb = (byteb >> 8) & 0xff;
		    int blueb = (byteb >> 0) & 0xff;

		    double axfact = (x < (ima.width-x)) ? x:(ima.width-x);
		    double bxfact = (ttx < (imb.width-ttx)) ? ttx:(imb.width-ttx);

		    double ayfact = (y < (ima.height-y)) ? y:(ima.height-y);
		    double byfact = (tty < (imb.height-tty)) ? tty:(imb.height-tty);

		    double afact = (axfact < ayfact) ? axfact:ayfact;
		    double bfact = (bxfact < byfact) ? bxfact:byfact;
		    //	  System.out.println("afact: "+afact+" @"+x+","+y);
		    afact = afact*afact/75;
		    bfact = bfact*bfact/75;
		    if(mimg){
			newim[(int) (x+(scw*y))] = 
			    ((int) (255) << 24) + 
			    (((int) (((afact*reda)+(bfact*redb))/(afact+bfact))) << 16) + 
			    (((int) (((afact*greena)+(bfact*greenb))/(afact+bfact))) << 8) +
			    (((int) (((afact*bluea)+(bfact*blueb))/(afact+bfact))) << 0);
		    }
		    else{
			int diff = 0;
			diff += Math.abs(reda-redb)/3;
			diff += Math.abs(greena-greenb)/3;
			diff += Math.abs(bluea-blueb)/3;
			newim[(int) (x+(scw*y))] = 
			    ((int) (255) << 24) + 
			    (diff << 16) +
			    (diff << 8) +
			    (diff << 0);	    
		    }
		}
		else if(ina)
		    newim[(int) (x+(scw*y))] = ima.oim[(int) ((x)+(ima.width*(y)))];
		else if(inb)
		    newim[(int) (x+(scw*y))] = imb.oim[(int) (ttx+(imb.width*tty))];
		else
		    newim[(int) (x+(scw*y))] = (255 << 24);
	    }
	}

	Toolkit tk = (new Canvas()).getToolkit();
	Image newi = tk.createImage(new MemoryImageSource((int) (scw), (int) (sch), newim, 0, (int) (scw)));
	try {
	    OutputStream fileout = new FileOutputStream("/tmp/img.ppm");
	    (new PpmEncoder(newi, fileout)).encode();
	} catch (Exception e) { System.out.println("Doh! "+e); }
	return newi;
    }

    public static cornerTransform findTM(ImArray ima, ImArray imb, cornerTransform t,
					 int upto){
	cornerTransform newct, cur;
	double nd, bd;

	bd = ImArray.imageDifference(ima, imb, t);
	cur = t;
	System.out.println("Starting with a difference of "+bd);
	for(int tx=(-1*upto);tx<(upto+1);tx++){
	    for(int ty=(-1*upto);ty<(upto+1);ty++){
		newct = t.translate(tx, ty);
		nd = ImArray.imageDifference(ima, imb, newct);
		System.out.print("x");
		if(nd < bd){
		    cur = newct;
		    bd = nd;
		    System.out.println("Best translational min sofar at "+tx+", "+ty+" ("+nd+")");
		}
	    }
	}
	return cur;
    }

    public static double neighborhood(ImArray im, int x, int y){
	return im.neigh[x+(y*im.width)];
    }
    public static double neighborhood2(ImArray im, int x, int y){
	int mypix, blue, red, green;
	int tot=0, ct=0;
	double avg;
	double totvar=0;

	for(int dx = -1; dx<2;dx++){
	    for(int dy = -1; dy<2;dy++){
		if((y+dy < 0) ||
		   (y+dy >= im.height) ||
		   (x+dx >= im.width) ||
		   (x+dx < 0))
		    continue;

		mypix = im.im[(x+dx)+((y+dy)*im.width)];
		tot += mypix;
		ct++;
	    }
	}

	avg = tot/ct;

	for(int dx = -1; dx<2;dx++){
	    for(int dy = -1; dy<2;dy++){
		if((y+dy < 0) ||
		   (y+dy >= im.height) ||
		   (x+dx >= im.width) ||
		   (x+dx < 0))
		    continue;
	
		mypix = im.im[(x+dx)+((y+dy)*im.width)];
		totvar += (mypix-avg)*(mypix-avg);
	    }
	}

	return totvar;
    }

    public static double neighborhood1(ImArray im, int x, int y){
	int mypix, blue, red, green;
	int rtot=0, btot=0, gtot=0, ct=0;
	double ravg, bavg, gavg;
	double totvar=0;

	for(int dx = -1; dx<2;dx++){
	    for(int dy = -1; dy<2;dy++){
		if((y+dy < 0) ||
		   (y+dy >= im.height) ||
		   (x+dx >= im.width) ||
		   (x+dx < 0))
		    continue;

		mypix = im.oim[(x+dx)+((y+dy)*im.width)];
		red = (mypix >> 16) & 0xff;
		green = (mypix >> 0) & 0xff;
		blue = (mypix >> 0) & 0xff;
		rtot += red;
		gtot += green;
		btot += blue;
		ct++;
	    }
	}

	ravg = rtot/ct;
	gavg = gtot/ct;
	bavg = btot/ct;

	for(int dx = -1; dx<2;dx++){
	    for(int dy = -1; dy<2;dy++){
		if((y+dy < 0) ||
		   (y+dy >= im.height) ||
		   (x+dx >= im.width) ||
		   (x+dx < 0))
		    continue;
	
		mypix = im.oim[(x+dx)+((y+dy)*im.width)];
		red = (mypix >> 16) & 0xff;
		green = (mypix >> 0) & 0xff;
		blue = (mypix >> 0) & 0xff;
		totvar += (red-ravg)*(red-ravg);
		totvar += (blue-bavg)*(blue-bavg);
		totvar += (green-gavg)*(green-gavg);
	    }
	}

	return totvar;
    }



    public static double neighborhood0(ImArray im, int x, int y){
	int bu, bd, bl, br;
	int bured, bugreen, bublue;
	int bdred, bdgreen, bdblue;
	int brred, brgreen, brblue;
	int blred, blgreen, blblue;

	double ared, agreen, ablue;
	double vred, vgreen, vblue;

	if(y == 0)
	    bu = im.oim[x+((y)*im.width)];
	else
	    bu = im.oim[x+((y-1)*im.width)];
	if(y >= im.height-1)
	    bd = im.oim[x+((y)*im.width)];
	else
	    bd = im.oim[x+((y+1)*im.width)];
	if(x >= im.width-1)
	    br = im.oim[x+(y*im.width)];
	else
	    br = im.oim[1+x+(y*im.width)];
	if(x == 0)
	    bl = im.oim[x+(y*im.width)];
	else
	    bl = im.oim[x-1+(y*im.width)];
    
	bured = (bu >>16) & 0xff;
	bdred = (bd >>16) & 0xff;
	blred = (bl >>16) & 0xff;
	brred = (br >>16) & 0xff;

	bugreen = (bu >>8) & 0xff;
	bdgreen = (bd >>8) & 0xff;
	blgreen = (bl >>8) & 0xff;
	brgreen = (br >>8) & 0xff;

	bublue = (bu >>8) & 0xff;
	bdblue = (bd >>8) & 0xff;
	blblue = (bl >>8) & 0xff;
	brblue = (br >>8) & 0xff;

	ared = (bured+bdred+blred+brred)/4;
	ablue = (bublue+bdblue+blblue+brblue)/4;
	agreen = (bugreen+bdgreen+blgreen+brgreen)/4;

	vred = (bured-ared)*(bured-ared) + (bdred-ared)*(bdred-ared) +
	    (blred-ared)*(blred-ared) + (brred-ared)*(brred-ared);
	vblue = (bublue-ablue)*(bublue-ablue) + (bdblue-ablue)*(bdblue-ablue) +
	    (blblue-ablue)*(blblue-ablue) + (brblue-ablue)*(brblue-ablue);
	vgreen = (bugreen-agreen)*(bugreen-agreen) + (bdgreen-agreen)*(bdgreen-agreen) +
	    (blgreen-agreen)*(blgreen-agreen) + (brgreen-agreen)*(brgreen-agreen);

	return vred+vblue+vgreen;
    }
}
