/*  
    Copyright (C) 2003 Johan Borg

    This file is part of xmerge.

    xmerge is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
                
    xmerge is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
                          
    You should have received a copy of the GNU General Public License
    along with xmerge; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "xmerge.h"

double ewa_W[4096];
double merge_L[4096];

#define BITORD rgb

extern int Bpp;
extern int BC_r,BC_g,BC_b;
extern int OFS_r,OFS_g,OFS_b;


#undef DEBUG 

void mapcupd(IMG * img,double *x,double *y) {
 double a,b,c,d,e,f,g,h;
 a=img->a=(x[1]-x[0])/(double)img->sx;
 c=img->c=(y[2]-y[0])/(double)img->sy;
 b=img->b=(x[0]+x[3]-x[1]-x[2])/(double)img->sx/(double)img->sy;
 d=img->d=(y[0]+y[3]-y[1]-y[2])/(double)img->sx/(double)img->sy;
 e=img->e=(x[2]-x[0])/(double)img->sy;
 f=img->f=x[0];
 g=img->g=(y[1]-y[0])/(double)img->sx;
 h=img->h=y[0];
 
  
 if (b==0) {
  if (d==0) {
     img->p[0]=e/(-a*c+g*e);
     img->p[1]=-c/(-a*c+g*e);     
     img->p[2]=(c*f-h*e)/(-a*c+g*e);
     img->p[3]=-a/(-a*c+g*e);
     img->p[4]=g/(-a*c+g*e);     
     img->p[5]=(h*a-g*f)/(-a*c+g*e);
     
#ifdef DEBUG
   printf("1\n");
#endif   
  } else if (e==0) {
     img->p[0]=f/a;
     img->p[1]=-h*a+g*f;
     img->p[2]=a*c-d*f;
#ifdef DEBUG
   printf("2\n");
#endif   
  } else { 
     img->p[0]=-a*c+g*e-d*f;
     img->p[1]=a*a*c*c-2.0*a*c*g*e-2.0*a*c*d*f+g*g*e*e-2.0*g*e*d*f+d*d*f*f+4.0*d*e*h*a;
     img->p[2]=2.0*d*a*c+2.0*d*g*e-2.0*d*d*f;
     img->p[3]=d*d;
     img->p[4]=-4.0*d*e*a;
     img->p[5]=1.0/d/a/2.0;
     img->p[6]=a*c-g*e-d*f;
     img->p[7]=1.0/d/e/2.0;
#ifdef DEBUG
   printf("3\n");
#endif   
  } 
 } else if (d==0) {
  if (g==0) { 
   img->p[0]=-c*f+h*e;
   img->p[1]=a*c-b*h;
   img->p[2]=h/c;
#ifdef DEBUG
   printf("4\n");
#endif   
  } else {
    img->p[0]=a*c-b*h-g*e;
    img->p[1]=a*a*c*c-2.0*a*c*b*h-2.0*a*c*g*e+b*b*h*h-2.0*g*e*b*h+g*g*e*e+4.0*b*c*g*f;
    img->p[2]=2.0*b*c*a-2.0*b*b*h+2.0*b*g*e;
    img->p[3]=b*b;
    img->p[4]=-4.0*b*c*g;
    img->p[5]=1.0/2.0/b/g;
    img->p[6]=-a*c-b*h+g*e;
    img->p[7]=1.0/2.0/b/c;
#ifdef DEBUG
   printf("5\n");
#endif   
  } 
 } else if (d*e==b*c) { 	//odd symmetry case...
  //test shape: {0,0},{10,0},{10,10},{21,11}
  img->p[0]=(-d*f+b*h)/(d*a-b*g);
  img->p[1]=d/(d*a-b*g);
  img->p[2]=-b/(d*a-b*g);
  img->p[3]=-h*a+g*f;
  img->p[4]=c*a-d*f-b*c*g/d+b*h;
#ifdef DEBUG  
  printf("6\n");
#endif  
 } else if (b*g==a*d) {		//the other odd symmetry case
//test shape:  {0,0} {10,10} {0,10} {11,21}
  img->p[0]=c*f-h*e;
  img->p[1]=(-d*f+b*h+g*e-b*c*g/d);
  img->p[2]=(-d*f+b*h)/(d*e-b*c);
  img->p[3]=d/(d*e-b*c);
  img->p[4]=-b/(d*e-b*c);
#ifdef DEBUG
  printf("7\n");
#endif  
 } else {
  img->p[0]=1.0/2.0/(b*g-a*d);
  img->p[1]=e*g-d*f+b*h-c*a;
  img->p[2]=e*e*g*g+c*c*a*a+d*d*f*f+b*b*h*h-2.0*c*a*e*g-2.0*c*a*b*h-2.0*e*g*b*h+4.0*a*d*e*h-2.0*b*h*d*f-2.0*e*g*d*f-2.0*a*d*c*f+4.0*b*g*f*c; 
  img->p[3]=2.0*a*d*c-2.0*d*d*f-4.0*b*g*c+2.0*d*b*h+2.0*d*e*g;
  img->p[4]=-2.0*b*b*h+2.0*b*d*f+2.0*b*c*a-4.0*a*d*e+2.0*b*e*g;
  img->p[5]=1.0/2.0/(d*e-c*b);
  img->p[6]=e*g+d*f-b*h-c*a;
#ifdef DEBUG
  printf("8\n");
#endif  
 }
#ifdef DEBUG 
 printf("a: %f b: %f c: %f d: %f e: %f f: %f g: %f h: %f\n",a,b,c,d,e,f,g,h);
#endif 
}

void mapc(IMG * img,double x,double y,double * nx,double * ny){
// *nx=x*((img->dx2-img->dx1)*(img->sy-y)+(img->dx4-img->dx3)*y)/img->sx/img->sy;
// *ny=y*((img->dy3-img->dy1)*(img->sx-x)+(img->dy4-img->dy2)*x)/img->sx/img->sy;
 *nx=x*(img->a+img->b*y)+img->e*y+img->f;
 *ny=y*(img->c+img->d*x)+img->g*x+img->h;
}




//perhaps we should invert the mapping, for faster mapping here and easier calculation of later mapping parameters
//some really degenerated cases are ignored, and will probbably cause strange behaviour
inline void mapcrs(IMG * img,double X,double Y,double * nx,double * ny){
 double a,b,c,d,e,f,g,h;
 double P,Q;
  
 a=img->a;  b=img->b;
 c=img->c;  d=img->d;
 e=img->e;  f=img->f;
 g=img->g;  h=img->h;
 
 
 if (b==0) {
  if (d==0) {
   *nx=img->p[0]*Y+img->p[1]*X+img->p[2];
   *ny=img->p[3]*Y+img->p[4]*X+img->p[5];
  } else if (e==0) {
   *nx = X/a-img->p[0];
   *ny = (-g*X+a*Y+img->p[1])/(d*X+img->p[2]);  
  } else { 
   P=sqrt(img->p[1]+img->p[2]*X+img->p[3]*X*X+img->p[4]*Y);
   *nx = (d*X+img->p[0]+P)*img->p[5];
   *ny = (d*X+img->p[6]-P)*img->p[7];
  } 
 } else if (d==0) {
  if (g==0) { 
   *nx = (-Y*e+c*X+img->p[0])/(b*Y+img->p[1]);
   *ny = Y/c-img->p[2];
  } else {
   P=sqrt(img->p[1]+Y*img->p[2]+Y*Y*img->p[3]+X*img->p[4]);
   *nx = (b*Y+img->p[0]-P)*img->p[5];
   *ny = (b*Y+img->p[6]+P)*img->p[7];
  } 
 } else if (d*e==b*c) { 	//odd symmetry case...
  *nx = img->p[0]+X*img->p[1]+Y*img->p[2];
  *ny = (img->p[3]-X*g+Y*a)/(img->p[4]+X*d-Y*b);  
 } else if (b*g==a*d) {		//the other odd symmetry case
  *nx = (img->p[0]-X*c+Y*e)/(img->p[1]+X*d-Y*b);  
  *ny = img->p[2]+X*img->p[3]+Y*img->p[4];
 } else {
  P=-d*X+b*Y;
  Q=sqrt(img->p[2]+img->p[3]*X+P*P+img->p[4]*Y);

  *nx=img->p[0]*( P-img->p[1]-Q);
  *ny=img->p[5]*(-P-img->p[6]-Q);
 }
}




inline void mapcr(IMG * img,double X,double Y,double * nx,double * ny,double * dxx,double * dxy,double * dyx,double * dyy){
 double a,b,c,d,e,f,g,h;
 double D,Dxx,Dxy,Dyx,Dyy;
 double P,Q;
  
 a=img->a;  b=img->b;
 c=img->c;  d=img->d;
 e=img->e;  f=img->f;
 g=img->g;  h=img->h;
 
 
 if (b==0) {
  if (d==0) {
   *nx=img->p[0]*Y+img->p[1]*X+img->p[2];
   *ny=img->p[3]*Y+img->p[4]*X+img->p[5];
  } else if (e==0) {
   *nx = X/a-img->p[0];
   *ny = (-g*X+a*Y+img->p[1])/(d*X+img->p[2]);  
  } else { 
   P=sqrt(img->p[1]+img->p[2]*X+img->p[3]*X*X+img->p[4]*Y);
   *nx = (d*X+img->p[0]+P)*img->p[5];
   *ny = (d*X+img->p[6]-P)*img->p[7];
  } 
 } else if (d==0) {
  if (g==0) { 
   *nx = (-Y*e+c*X+img->p[0])/(b*Y+img->p[1]);
   *ny = Y/c-img->p[2];
  } else {
   P=sqrt(img->p[1]+Y*img->p[2]+Y*Y*img->p[3]+X*img->p[4]);
   *nx = (b*Y+img->p[0]-P)*img->p[5];
   *ny = (b*Y+img->p[6]+P)*img->p[7];
  } 
 } else if (d*e==b*c) { 	//odd symmetry case...
  *nx = img->p[0]+X*img->p[1]+Y*img->p[2];
  *ny = (img->p[3]-X*g+Y*a)/(img->p[4]+X*d-Y*b);  
 } else if (b*g==a*d) {		//the other odd symmetry case
  *nx = (img->p[0]-X*c+Y*e)/(img->p[1]+X*d-Y*b);  
  *ny = img->p[2]+X*img->p[3]+Y*img->p[4];
 } else {
  P=-d*X+b*Y;
  Q=sqrt(img->p[2]+img->p[3]*X+P*P+img->p[4]*Y);

  *nx=img->p[0]*( P-img->p[1]-Q);
  *ny=img->p[5]*(-P-img->p[6]-Q);
 }
 
 Dxx=a+b*(*ny);
 Dxy=*nx*b+e;
 Dyx=*ny*d+g;
 Dyy=c+d*(*nx);
 
 D=Dxx*Dyy-Dyx*Dxy;
 
 *dxx=Dyy/D;
 *dxy=-Dyx/D;
 *dyx=-Dxy/D;
 *dyy=Dxx/D;
}














//the trick here is that we traverse the target image line by line
//which means we must keep track of where images enter and leave the cover ... :/
//we visit all points of the target, as the overhead of iterating unmapped areas is highly marginal
//(sure, we could do this by subdividing the target in small triangles and 4-edged shapes, but this seems messy, especially as we write the image directly to disk)

typedef struct imap_helpt {
 IMG *img;
 int x;		//we could use the weight reaching 0 or 1 for this, but I'm scared of round-off errors
 int stat;
 double d[4];
 double w;
 int m;
} imap_helpt;


inline int ewa_pixel(IMG *img,double x,double y,double * CR,double *CG,double *CB,double *W) {
 double A,B,C,F0,F;
 double U,V,U0,V0,Ux,Uy,Vx,Vy;
 double Q,DQ,DDQ,w,n;
 int u,v,u1,u2,v1,v2,xd,yd,a;
 double xm,ym,tm;
 double cR,cG,cB;
 pixt *pix;

 pix=img->pix;
 mapcr(img,x*1.0,y*1.0,&U0,&V0,&Ux,&Uy,&Vx,&Vy);

 xd=img->sx;
 yd=img->sy;
 
     
 if ((Ux*Ux+Vx*Vx)<pL*pL) {
  F=sqrt(Ux*Ux+Vx*Vx);
  Ux*=pL/F;
  Vx*=pL/F;
 }
    
 if ((Uy*Uy+Vy*Vy)<pL*pL) {
  F=sqrt(Uy*Uy+Vy*Vy);
  Uy*=pL/F;
  Vy*=pL/F;
 }

 A = Vx*Vx+Vy*Vy;
 B = -2.*(Ux*Vx+Uy*Vy);
 C = Ux*Ux+Uy*Uy;
 F0 = Ux*Vy-Uy*Vx;
 F = F0*F0;
    
    

 A=pE/pT*A/F/pG;		
 B=pE/pT*B/F/pG;
 C=pE/pT*C/F/pG;
    
 tm=3.0*B*B+4.0*A*C;
 xm=2.0*sqrt(C*pE/pT/tm);
 ym=2.0*sqrt(A*pE/pT/tm);

     
 u1=floor(U0-xm);	
 u2=ceil(U0+xm);
    
 v1=floor(V0-ym);
 v2=ceil(V0+ym);
     
// if (u1<0) u1=0;	//why did I comment these out? they seem like a rather good idea 
// if (u2>=xd) u2=xd-1;
// if (v1<0) v1=0;
// if (v2>=xd) v2=yd-1;
     

//should modify this to take the edge case into account, using the background color correctly





 cR=cG=cB=0; 
 n = 0;
 DDQ = 2.*A; 
 U = u1-U0;
 
 
 for(v=v1;v<=v2;v++)  {		// scan the box 
  V = v-V0;
  if ((v<0) || (v>=yd)) continue;
  DQ = A*(2.*U+1.)+B*V;		// Q(U+1,V)-Q(U,V) 
  Q = (C*V+B*U)*V+A*U*U;

  for(u=u1;u<=u2;u++) {
      
   if ((u>=0) && (u<xd)) {  
    a=Q+0.5;			// ignore pixel if Q out of range 
    if (a<4096) {
     w=W[a];
 
     cR=cR+w*pix[xd*v+u].R;
     cG=cG+w*pix[xd*v+u].G;
     cB=cB+w*pix[xd*v+u].B;       
 
     n=n+w; 		// denominator (for normalization) 
    } 
   } 
   Q=Q+DQ; 
   DQ=DQ+DDQ;
  } 
 }
 
 
 if (!n) {
//  *CR=BC_r;
//  *CG=BC_g;
//  *CB=BC_b;
  return 0;
 } 
 n=1/n;

 *CR=cR*n*img->Gr;
 *CG=cG*n*img->Gg;    
 *CB=cB*n*img->Gb;
 
 return 1;    
}



//we calculate the weights for overlapping images using the product of the distances of the 2 closest edges for all relevant images
//the final weight is calculated as cos(pi*w)-1 for the normalized lengths
//ideas: perhaps the angle between the two edges should be taken into account, or even the second to closest edge selected based on orthogonal distance?

//(for most cases the current method works ok (but it's really slow, ofcourse))

inline double imap_dist(IMG *img,double x,double y) {
 edget *pos;
 double x1,y1,x2,y2;
 double X,Y,d,dmin,dnmin,f; 
 int h;
 d=0;
 
 dmin=dnmin=1e43; 

 pos=img->edge;
 x2=pos->X;
 y2=pos->Y;

 h=0;

 while(pos) {
  x1=x2;
  y1=y2;
  if (pos->next) {x2=pos->next->X; y2=pos->next->Y;} else {x2=img->edge->X; y2=img->edge->Y; }
      
  X=x-x1;
  Y=y-y1;
  
  d=X*X+Y*Y;
  if (d<dmin) { dnmin=dmin; dmin=d; h=1;} else if(d<dnmin) dnmin=d;
  
   
  f=(X*(x2-x1)+Y*(y2-y1))/((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
  X=X-(x2-x1)*f;
  Y=Y-(y2-y1)*f;
  d=X*X+Y*Y;

  if ((f>0) && (f<1)) {
   if (d<dmin) { dnmin=dmin; dmin=d; h=0;} else if(d<dnmin) dnmin=d;
  }   

  pos=pos->next;
 }
 if (h) return dmin; else return sqrt(dmin*dnmin);
}


extern int writing,write_abort;

//unsigned char * imap_ewa_merge(int *dx,int *dy) {
void imap_ewa_merge(int ml,int mt,int mr,int mb,int fd) {

 int a,b,c,dr,dg,db,x,y,A,no,nx,Nl,nl;
 double aR,aG,aB,xa[4],ya[4];
 double cR,cG,cB,xt,X2,N,w,ww;
 double *W;
 double *L;
  
 int n;
 int Xd,Yd,X2s; 
 edget *edge,*edge2;

 imap_helpt **ih,**iH;
 unsigned char * dest;
 

 writing=1;

//#define C (-0.5)
#define C 0
 
 ih=malloc(sizeof(imap_helpt*)*Ot);
 iH=malloc(sizeof(imap_helpt*)*Ot);
 
 for (a=0;a<Ot;a++) {
  ih[a]=malloc(sizeof(imap_helpt));
  ih[a]->img=simg[a];
  xa[0]=simg[a]->dx1+C; ya[0]=simg[a]->dy1+C;
  xa[1]=simg[a]->dx2+C; ya[1]=simg[a]->dy2+C;
  xa[2]=simg[a]->dx3+C; ya[2]=simg[a]->dy3+C;
  xa[3]=simg[a]->dx4+C; ya[3]=simg[a]->dy4+C;
  mapcupd(simg[a],xa,ya);
 } 
 
 update_edges();
 
 mr-=1;
 mb-=1;
 
  
 Xd=mr-ml;
 Yd=mb-mt;

 
 Nl=256*1024/(Xd*3);	//writing every line will probbably result in poor performance
 a=Nl*3*Xd;
 printf("Nl: %d buf: %d bytes\n",Nl,a);


 if (a<256) a=256;

 dest=malloc(a);
 

 snprintf(dest,255,"P6\n%d %d\n255\n",Xd,Yd);
 write(fd,dest,strlen(dest));
 
 N=0;
 no=0; 
 
 W=ewa_W;
 L=merge_L;
  
 
 b=0;
 nl=0; 
  
 for(y=mt;y<mb;y++) {
 
  if (nl==Nl) {
   printf("writing line %d of %d       \r",y-mt,Yd);
   fflush(stdout);
   write(fd,dest,Nl*Xd*3);
   nl=0;
   b=0;
  }
  nl++;
  if (write_abort) {
   close(fd);
   writing=0;
   write_abort=0;
   printf("aborting write\n");
   if (write_abort==2) exit(0);
   return;
  }
  
 
  for (a=0;a<Ot;a++) ih[a]->x=ml-1;
 
  nx=ml-1;
  
  A=1;  

  for(x=ml;x<mr;x++) { 
  
   A=0;
   a=0;
   if (nx<x) {
    nx=1000000;
    A=1;
    for(n=0;n<Ot;n++) {
     if (ih[n]->x<x) {
      edge=ih[n]->img->edge;
      X2=1000000;
      X2s=0;
      while(edge){
       if (edge->next) edge2=edge->next; else edge2=ih[n]->img->edge;
       
       if ((y>edge->Y) && (y<=edge2->Y)) c=1; else if ((y<=edge->Y) && (y>edge2->Y)) c=-1; else c=0;
       if ((edge2->Y!=edge->Y) && (c)){   
        xt=(edge2->X-edge->X)*(y-edge->Y)/(edge2->Y-edge->Y)+edge->X;
        if ((xt>x) && (xt<X2)) { X2s=c; X2=xt; }
       } 
       edge=edge->next;
      }
      ih[n]->stat=(X2s>0);  //X1s and X2s should never be equal... 
      ih[n]->x=X2;  
      if (X2<nx) nx=X2;
      if (X2s>0) iH[a++]=ih[n];
     } else {
      if (ih[n]->stat) iH[a++]=ih[n];
      if (ih[n]->x<nx) nx=ih[n]->x;
     } 
    } 
   } 
   

   if (A) n=no=a; else n=no;
      
   
   
   if (n>1) {
    
    aR=aG=aB=0;
    
    N=0;
    ww=0;
    
    for(a=0;a<n;a++) {
     w=iH[a]->w=imap_dist(iH[a]->img,x,y);
     ww+=w;
    } 
     
    for(a=0;a<n;a++) {
    
     if (ewa_pixel(iH[a]->img,x,y,&cR,&cG,&cB,W)) {
      w=iH[a]->w/ww;
      c=w*4096;
      w=L[c];

      cR*=w;//*iH[a]->img->Gr;
      cG*=w;//*iH[a]->img->Gg;
      cB*=w;//*iH[a]->img->Gb;
      aR+=cR;
      aG+=cG;
      aB+=cB;
      N+=w;
     } 
    } 
    
    
 
    N=1/N;
    aR*=N;
    aG*=N;
    aB*=N;
    aR-=(double)OFS_r;
    aG-=(double)OFS_g;
    aB-=(double)OFS_b;
    
    
   } else if (n) {
    if (ewa_pixel(iH[0]->img,x,y,&aR,&aG,&aB,W)) {
//    cR*=iH[0]->img->Gr;
//    cG*=iH[0]->img->Gg;
//    cB*=iH[0]->img->Gb;
     aR-=(double)OFS_r;
     aG-=(double)OFS_g;
     aB-=(double)OFS_b;
    } else {
     aR=BC_r;
     aG=BC_g;
     aB=BC_b;    
    } 
   } else {
    aR=BC_r;
    aG=BC_g;
    aB=BC_b;
   }
   
   if (aR>255) dr=255; else if (aR<0) dr=0; else dr=aR+0.5;
   if (aG>255) dg=255; else if (aG<0) dg=0; else dg=aG+0.5;
   if (aB>255) db=255; else if (aB<0) db=0; else db=aB+0.5;
    
   dest[b++]=dr;
   dest[b++]=dg;
   dest[b++]=db;
    
  }
 }
 write(fd,dest,nl*Xd*3);
 close(fd);
 writing=0;
}






extern int Bgr;


void imapx_near_16_rgb (unsigned char * dest,int dx,int tx2,int ty2,double *x,double *y,IMG *img);
void imapx_near_24_rgb (unsigned char * dest,int dx,int tx2,int ty2,double *x,double *y,IMG *img);
void imapx_near_32_rgb (unsigned char * dest,int dx,int tx2,int ty2,double *x,double *y,IMG *img);
void imapx_near_16_bgr (unsigned char * dest,int dx,int tx2,int ty2,double *x,double *y,IMG *img);
void imapx_near_24_bgr (unsigned char * dest,int dx,int tx2,int ty2,double *x,double *y,IMG *img);
void imapx_near_32_bgr (unsigned char * dest,int dx,int tx2,int ty2,double *x,double *y,IMG *img);


void imapx_near (unsigned char * dest,int dx,int tx2,int ty2,double *x,double *y,IMG *img) {
 if (Bgr) {
  if (Bpp==2) imapx_near_16_bgr(dest,dx,tx2,ty2,x,y,img);
  if (Bpp==3) imapx_near_24_bgr(dest,dx,tx2,ty2,x,y,img);
  if (Bpp==4) imapx_near_32_bgr(dest,dx,tx2,ty2,x,y,img);
 } else {
  if (Bpp==2) imapx_near_16_rgb(dest,dx,tx2,ty2,x,y,img);
  if (Bpp==3) imapx_near_24_rgb(dest,dx,tx2,ty2,x,y,img);
  if (Bpp==4) imapx_near_32_rgb(dest,dx,tx2,ty2,x,y,img);
 }
}




void imapx_16_rgb(unsigned char * dest,int dx,int dy,int dxo,int dyo,int zoom,IMG *img);
void imapx_24_rgb(unsigned char * dest,int dx,int dy,int dxo,int dyo,int zoom,IMG *img);
void imapx_32_rgb(unsigned char * dest,int dx,int dy,int dxo,int dyo,int zoom,IMG *img);
void imapx_16_bgr(unsigned char * dest,int dx,int dy,int dxo,int dyo,int zoom,IMG *img);
void imapx_24_bgr(unsigned char * dest,int dx,int dy,int dxo,int dyo,int zoom,IMG *img);
void imapx_32_bgr(unsigned char * dest,int dx,int dy,int dxo,int dyo,int zoom,IMG *img);


void imapx(unsigned char * dest,int dx,int dy,int dxo,int dyo,int zoom,IMG *img) {
 if (Bgr) {
  if (Bpp==2) imapx_16_bgr(dest,dx,dy,dxo,dyo,zoom,img);
  if (Bpp==3) imapx_24_bgr(dest,dx,dy,dxo,dyo,zoom,img);
  if (Bpp==4) imapx_32_bgr(dest,dx,dy,dxo,dyo,zoom,img);
 } else {
  if (Bpp==2) imapx_16_rgb(dest,dx,dy,dxo,dyo,zoom,img);
  if (Bpp==3) imapx_24_rgb(dest,dx,dy,dxo,dyo,zoom,img);
  if (Bpp==4) imapx_32_rgb(dest,dx,dy,dxo,dyo,zoom,img); 
 } 
}


void mline_16 (unsigned char * Data,int Dxl,int Dyl,int x1,int y1,int x2,int y2,unsigned int f,unsigned int b);
void mline_24 (unsigned char * Data,int Dxl,int Dyl,int x1,int y1,int x2,int y2,unsigned int f,unsigned int b);
void mline_32 (unsigned char * Data,int Dxl,int Dyl,int x1,int y1,int x2,int y2,unsigned int f,unsigned int b);

void mline(unsigned char * Data,int Dxl,int Dyl,int x1,int y1,int x2,int y2,unsigned int f,unsigned int b) {
 if (Bpp==2) mline_16(Data,Dxl,Dyl,x1,y1,x2,y2,f,b);
 if (Bpp==3) mline_24(Data,Dxl,Dyl,x1,y1,x2,y2,f,b);
 if (Bpp==4) mline_32(Data,Dxl,Dyl,x1,y1,x2,y2,f,b);
}










