#include "defs.h"
#include <stdio.h>
#include "imageio.h"
#include "imagemath.h"
#ifdef USE_DEBUG
#include "time.h"
#endif
#ifdef USE_CLUSTER
#include "cluster.h"
#endif

#define MULT 65536

int scale(ImagePtr* dest, ImagePtr imsource,int width,int height,
	int x11,int y11, int x12, int y12, int x13,int y13,int x14,int y14,
	int x21,int y21, int x22, int y22, int x23,int y23,int x24,int y24) {
/*rescale imsource to size width,height and saves the result in dest
  also the pixels are shifted according to reference shifts in 4 edges*/

   ImagePtr imdest;		/*VarPointers to the Image Data*/
   int t,tt,actual,sum;		/*Several integers*/
   long long bx,by,bx0,by0,bx1,by1;
   long long ax2,ay2,bx2,by2;
   long long ax0,ay0,ax1,ay1;
   long long dax,day,dbx,dby;
   long long t2,tt2,ax,ay,x,y;
   long long nt2,ntt2,tmp;
   int color[256];		/*Some sort of Color Map*/
#ifdef USE_CLUSTER
   int height2;
#endif

#ifdef USE_DEBUG
   clock_t starttime;
   starttime=clock();
   fprintf(stderr,"Running scale...\n");
#endif

   imdest   = createim(width,height);
   *dest=imdest;
   /*We create a destination image twice the size of the source*/
   /*and give its adress back*/

   t=0;
   while (t<256) {
      color[t]=collorallocateim(imdest,t,t,t);
      t++;
   }
   /*We create some sort of 256 colors b/w colormap for the destination*/

   /*calculate pixel shifting formulas*/
   /* f0(x2)=ax2*x2+bx0 */
   /* f0(y2)=ay2*y2+by0 */
   tmp=(x22-x21);
   if (tmp==0) tmp=1;
   ax2=(MULT*(x12-x11))/tmp;
   tmp=(y23-y21);
   if (tmp==0) tmp=1;
   ay2=(MULT*(y13-y11))/tmp;
   bx2=(MULT*x11)-(ax2*x21);
   by2=(MULT*y11)-(ay2*y21);
   /* f1(x2)=ax2*x2+bx0 */
   /* f1(y2)=ax2*y2+bx0 */
   tmp=(x24-x23);
   if (tmp==0) tmp=1;
   ax1=(MULT*(x14-x13))/tmp;;
   tmp=(y24-y22);
   if (tmp==0) tmp=1;
   ay1=(MULT*(y14-y12))/tmp;
   bx1=(MULT*x13)-(ax1*x23);
   by1=(MULT*y12)-(ay1*y22);
   /*now calculate delta values to this constants*/
   tmp=(y23-y21);
   if (tmp==0) tmp=1;
   dax=(ax1-ax2)/tmp;
   dbx=(bx1-bx2)/tmp;
   tmp=(x22-x21);
   if (tmp==0) tmp=1;
   day=(ay1-ay2)/tmp;
   dby=(by1-by2)/tmp;
   /*and try to calculate origin constants at 0,0 coordinates */
   ax0=ax2-(dax*y21);
   bx0=bx2-(dbx*y21);
   ay0=ay2-(day*x21);
   by0=by2-(dby*x21);
   
   tt=0;
   sum=0;
   x=widthim(imsource)*256;
   y=heightim(imsource)*256;

#ifdef USE_DEBUG
   fprintf(stderr,"ax2=%lli ay2=%lli bx2=%lli by2=%lli\n",ax2,ay2,bx2,by2);
   fprintf(stderr,"ax0=%lli ay0=%lli bx0=%lli by0=%lli\n",ax0,ay0,bx0,by0);
   fprintf(stderr,"ax1=%lli ay1=%lli bx1=%lli by1=%lli\n",ax1,ay1,bx1,by1);
   fprintf(stderr,"dax=%lli dbx=%lli day=%lli dby=%lli\n",dax,dbx,day,dby);
#endif

#ifdef USE_CLUSTER
   cluster_split();
   /*time to split up the work */
   tt=cluster_split_min(0,height);
   height2=cluster_split_max(0,height);
   while (tt<height2) {
#else
   while (tt<height) {
#endif
      t=0;
      ax=ax0+(tt*dax);
      bx=bx0+(tt*dbx);
      while (t<width) {
         ay=ay0+(t*day);
         by=by0+(t*dby);
	 t2=256*(ax*t+bx)/MULT;
	 tt2=256*(ay*tt+by)/MULT;
	 nt2=256*(ax*(t+1)+bx)/MULT;
         ntt2=256*(ay*(tt+1)+by)/MULT;
	 if (t2>=nt2) { tmp=nt2; nt2=t2+1; t2=tmp; }
	 if (tt2>=ntt2) { tmp=ntt2; ntt2=tt2+1; tt2=tmp; }
	 if (nt2>=x) { t2=x-2;nt2=x-1; }
	 if (ntt2>=y) { tt2=y-2; ntt2=y-1; }
	 if (t2<0) { t2=0; nt2=1; }
	 if (tt2<0) { tt2=0; ntt2=1; }

	 actual=scalepixelim(imsource,t2,tt2,nt2,ntt2);
	 sum+=actual;
         drawpixelim(imdest,t,tt,color[actual]);
	 t++;
      }
      tt++;
   }
   /*Main Working stuff, this is important!
     Go through every pixel of the destination
     and set it to the average of the corresponding
     source regions grey value */

#ifdef USE_CLUSTER
   sum=cluster_sync_add(sum);
   processsyncim(imdest,height);
   cluster_regroup();
   /*re combine execution*/
#endif

#ifdef USE_DEBUG
   fprintf(stderr," ... took  %.4f seconds!\n",(1.0 * (clock() - starttime) / CLOCKS_PER_SEC));
#endif
  return sum;
  /*and we are finnished*/

}


