#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "image.h"
#include "grille.h"
#include "canal.h"
#include "o.h"
#include "fourier.h"
#include "c.h"



Image  TransfereC ( Image imS, Image imD )
/****************************************/

{
Canal canL,canE;
Complexe *valeur;
int x,y,i;

if ( (imD=CreeImageDest(imS, imD, T_COMPLEXE))==NULL) return(NULL);

if (imD==imS) return(imD);

LitTailleFenetre(imD,&x, &y);
if ((valeur=(Complexe *)calloc(x,sizeof(Complexe)))==NULL) return(NULL);
if ((canL=CreeCanal(imS, T_COMPLEXE, B_LIGNE, Z_FENETRE))==NULL) return(NULL);
if ((canE=CreeCanal(imD, T_COMPLEXE, B_LIGNE, Z_FENETRE))==NULL) return(NULL);

for (i=0;i<y;i++)
   {
   LitCanal(canL, valeur);
   EcritCanal(canE, valeur);
   }

free(valeur);
LibereCanal(canL);
LibereCanal(canE);
return (imD) ;
}


Image  MultC ( Image imS1, Image imS2, Image imD )
/************************************************/

{
int i,j,x,y;
Canal canL1, canL2, canE;
Complexe *val1,*val2,v1,v2;

if (TesteFenetre(imS1,imS2)) return(NULL);
if ((imD=CreeImageDest(imS1,imD,T_COMPLEXE))==NULL) return(NULL);

LitTailleFenetre(imS1,&x,&y);
if ((val1=(Complexe*)calloc(x,sizeof(Complexe)))==NULL) return(NULL);
if ((val2=(Complexe*)calloc(x,sizeof(Complexe)))==NULL) return(NULL);
if ((canL1=CreeCanal(imS1,T_COMPLEXE,B_LIGNE,Z_FENETRE))==NULL) return(NULL);
if ((canL2=CreeCanal(imS2,T_COMPLEXE,B_LIGNE,Z_FENETRE))==NULL) return(NULL);
if ((canE=CreeCanal(imD,T_COMPLEXE,B_LIGNE,Z_FENETRE))==NULL) return(NULL);

for (i=0;i<y;i++)
    {
    LitCanal(canL1,val1);
    LitCanal(canL2,val2);
    for (j=0;j<x;j++)
        {
	v1=val1[j];
		  v2=val2[j];
        val1[j].x=v1.x*v2.x-v1.y*v2.y;
        val1[j].y=v1.x*v2.y+v2.x*v1.y;
        }
    EcritCanal(canE,val1);
     }

LibereCanal(canE);
LibereCanal(canL2);
LibereCanal(canL1);
free(val2);
free(val1);
return(imD);
}

Image ConstMultC(Image imS, Image imD, Reel cteX,Reel cteY)
/*********************************************************/

{
int i,j,x,y;
Canal canL;
Complexe **grille,*val;
Reel vx,vy;

if ((imD=CreeImageDest(imS,imD,T_COMPLEXE))==NULL) return(NULL);

LitTailleFenetre(imS,&x,&y);
if ((val=(Complexe*)calloc(x,sizeof(Complexe)))==NULL) return(NULL);
if ((canL=CreeCanal(imS,T_COMPLEXE,B_LIGNE,Z_FENETRE))==NULL) return(NULL);
if ((grille=(Complexe**)CreeGrille(imD,Z_FENETRE))==NULL) return(NULL);
for (i=0;i<y;i++)
	 {
	 LitCanal(canL,val);
	for (j=0;j<x;j++)
		{
		vx=val[j].x;
		  vy=val[j].y;
		grille[i][j].x=vx*cteX-vy*cteY;
		grille[i][j].y=vy*cteX+vx*cteY;
		  }
	  }

LibereGrille(grille);
LibereCanal(canL);
free(val);
return(imD);
}


Image  NiveauC ( Image imS, Image imD, Reel valeurX, Reel valeurY )
/*****************************************************************/

{
Canal canE;
Complexe *tampon,valeur;
int x,y,i;

valeur.x=valeurX;valeur.y=valeurY;
if ( (imD=CreeImageDest(imS, imD, T_COMPLEXE))==NULL) return(NULL);

LitTailleFenetre(imD,&x, &y);
if ((tampon=(Complexe *)calloc(x,sizeof(Complexe)))==NULL) return(NULL);
if ((canE=CreeCanal(imD, T_COMPLEXE, B_LIGNE, Z_FENETRE))==NULL) return(NULL);

for (i=0;i<x;i++) tampon[i]=valeur;
for (i=0;i<y;i++) EcritCanal(canE,tampon);

LibereCanal(canE);
free(tampon);
return(imD);
}


Image  ExtraitFenetreC ( Image imS, Image imD )
/*********************************************/

{
int i,x,y;
Canal canL,canE;
Complexe *val;

if (imS==NULL) return(NULL);
LitTailleFenetre(imS,&x,&y);

if ((imD=CreeImageSimple(imD,T_COMPLEXE,imS->visu,x,y))==NULL) return(NULL);
if (imS->lut!=NULL) if (EcritLut(imD,imS->lut->taille,imS->lut->table)) return(NULL);

if ((val=(Complexe*)calloc(x,sizeof(Complexe)))==NULL) return(NULL);
if ((canL=CreeCanal(imS,T_COMPLEXE,B_LIGNE,Z_FENETRE))==NULL) return(NULL);
if ((canE=CreeCanal(imD,T_COMPLEXE,B_LIGNE,Z_FENETRE))==NULL) return(NULL);

for (i=0;i<y;i++)
    {
	 LitCanal(canL,val);
    EcritCanal(canE,val);
    }


LibereCanal(canE);
LibereCanal(canL);
free(val);
return(imD);
}



Image  ConjugueC ( Image imS, Image imD )
/***************************************/
{
Canal canL,canE;
Complexe *valeur;
int x,y,i,j;

if ((imD=CreeImageDest(imS,imD,T_COMPLEXE))==NULL) return(NULL);

LitTailleFenetre(imD,&x, &y);
if ((valeur=(Complexe *)calloc(x,sizeof(Complexe)))==NULL) return(NULL);
if ((canL=CreeCanal(imS, T_COMPLEXE, B_LIGNE, Z_FENETRE))==NULL) return(NULL);
if ((canE=CreeCanal(imD, T_COMPLEXE, B_LIGNE, Z_FENETRE))==NULL) return(NULL);

for (i=0;i<y;i++)
   {
   LitCanal(canL,valeur);
   for (j=0;j<x;j++)  valeur[j].y = -valeur[j].y;
   EcritCanal(canE,valeur);
   }

LibereCanal(canE);
LibereCanal(canL);
free(valeur);

return(imD);
}



int MinMaxModuleC(Image imS, Reel *min, Reel *max)
/************************************************/

{
Canal canL;
Complexe *valeur;
Reel val;
int x,y,i,j;

if (imS==NULL) return(1);

LitTailleFenetre(imS,&x, &y);
if ((valeur=(Complexe *)calloc(x,sizeof(Complexe)))==NULL) return(1);
if ((canL=CreeCanal(imS, T_COMPLEXE, B_LIGNE, Z_FENETRE))==NULL) return(1);

LitCanal(canL, valeur);
*min=*max=Module(*valeur);
for (i=0;i<y-1;i++)
    {
    for (j=0;j<x;j++)
		{
        val=Module(valeur[j]);
        if (val>*max) *max=val;
		if (val<*min) *min=val;
        }
	 LitCanal(canL, valeur);
    }
for (j=0;j<x;j++)
		{
		val=Module(valeur[j]);
        if (val>*max) *max=val;
		if (val<*min) *min=val;
        }

LibereCanal(canL);
free(valeur);
return (0);
}

int PosMinMaxModuleC(Image imS, Point *posMin, Point *posMax, Reel *min, Reel *max)
/*********************************************************************************/

{
int i,j,x,y;
Complexe *valeur;
Reel mod;
Canal canL;

if (imS==NULL) return(1);

LitTailleFenetre(imS,&x,&y);
if ((valeur=(Complexe *)calloc(x,sizeof(Complexe)))==NULL) return(1);
if ((canL=CreeCanal(imS, T_COMPLEXE, B_LIGNE, Z_FENETRE))==NULL) return(1);

LitCanal(canL, valeur);
*max=Module(*valeur);
*min=*max;
posMin->x=posMin->y=0;
*posMax=*posMin;
for (i=0;i<y-1;i++)
	 {
	 for (j=0;j<x;j++)
		{
		mod=Module(valeur[j]);
		if (mod<*min)
				{
				*min=mod;
				posMin->x=j;
				posMin->y=i;
				}
		if (mod>*max)
				{
			*max=mod;
				posMax->x=j;
				posMax->y=i;
				}
			}
	 LitCanal(canL, valeur);
	 }
for (j=0;j<x;j++)
	 {
	mod=Module(valeur[j]);
	if (mod<*min)
		  {
		*min=mod;
		  posMin->x=j;
		  posMin->y=i;
		  }
	if (mod>*max)
		  {
		*max=mod;
		  posMax->x=j;
		  posMax->y=i;
		  }
	  }

LibereCanal(canL);
free(valeur);
return (0);
}


#define Module2(c) c.x*c.x+c.y*c.y


Image MaxMod1DirC(Image imS,Image imD)
/************************************/

{
int i,ii,j,jj,x,y;
Canal canL;
Complexe **grille,*lig0,*lig1,*lig2,*ptr,cm1,zeroC;
Reel m0,m1,m2,d0,d1,d2,g0,g1,g2;

if ((imD=CreeImageDest(imS,imD,T_COMPLEXE))==NULL) return(NULL);
LitTailleFenetre(imD,&x,&y);
if ((x<2)||(y<2)) return(NULL);
lig0=(Complexe*)calloc(x,sizeof(Complexe));
lig1=(Complexe*)calloc(x,sizeof(Complexe));
lig2=(Complexe*)calloc(x,sizeof(Complexe));
grille=(Complexe**)CreeGrille(imD,Z_FENETRE);
canL=CreeCanal(imS,T_COMPLEXE,B_LIGNE,Z_FENETRE);
zeroC.x=0;
zeroC.y=0;

if (lig0 && lig1 && lig2 && grille && canL)
	{
    PoseCanal(canL,0,y-2);
	LitCanal(canL,lig0);
	LitCanal(canL,lig1);
	PoseCanal(canL,0,0);
    ii=y-1;
	for (i=0;i<y;i++)
		{
		LitCanal(canL,lig2);
		g0=Module2(lig0[x-2]);
		g1=Module2(lig1[x-2]);
		g2=Module2(lig2[x-2]);
		m0=Module2(lig0[x-1]);
		m1=Module2(lig1[x-1]);
		m2=Module2(lig2[x-1]);
        cm1=lig1[x-1];
        jj=x-1;
		for (j=0;j<x;j++)
			{
			d0=Module2(lig0[j]);
			d1=Module2(lig1[j]);
			d2=Module2(lig2[j]);

			if (	((m1>m0)&&(m1>m2)) || ((m1==m0)&&(m1==m2)) ||
					((m1>g1)&&(m1>d1)) || ((m1==g1)&&(m1==d1)) ||
					((m1>g0)&&(m1>d2)) || ((m1==g0)&&(m1==d2)) ||
					((m1>d0)&&(m1>g2)) || ((m1==d0)&&(m1==g2))) grille[ii][jj]=cm1;
				else grille[ii][jj]=zeroC;

			jj=(jj+1)%x;
			g0=m0;
			m0=d0;
			g1=m1;
			m1=d1;
			g2=m2;
			m2=d2;
			cm1=lig1[j];
			}
		ii=(ii+1)%y;
		ptr=lig0;
		lig0=lig1;
		lig1=lig2;
        lig2=ptr;
        }
	}

LibereCanal(canL);
LibereGrille(grille);
free(lig2);
free(lig1);
free(lig0);
return(imD);
}



Image MaxMod2DirC(Image imS,Image imD)
/************************************/

{
int i,ii,j,jj,x,y,k;
Canal canL;
Complexe **grille,*lig0,*lig1,*lig2,*ligy,*ptr,cm1,zeroC;
ReelL m0,m1,m2,d0,d1,d2,g0,g1,g2,ang;

if ((imD=CreeImageDest(imS,imD,T_COMPLEXE))==NULL) return(NULL);
LitTailleFenetre(imD,&x,&y);
if ((x<2)||(y<2)) return(NULL);
lig0=(Complexe*)calloc(x,sizeof(Complexe));
lig1=(Complexe*)calloc(x,sizeof(Complexe));
lig2=(Complexe*)calloc(x,sizeof(Complexe));
ligy=(Complexe*)calloc(x,sizeof(Complexe));
grille=(Complexe**)CreeGrille(imD,Z_FENETRE);
canL=CreeCanal(imS,T_COMPLEXE,B_LIGNE,Z_FENETRE);
zeroC.x=0;
zeroC.y=0;

if (lig0 && lig1 && lig2 && ligy && grille && canL)
	{
    PoseCanal(canL,0,y-2);
	LitCanal(canL,lig0);
	LitCanal(canL,lig1);
    memcpy(ligy,lig1,x*sizeof(Complexe));
	PoseCanal(canL,0,0);
    ii=y-1;
	for (i=0;i<y-1;i++)
		{
		LitCanal(canL,lig2);
		g0=Module2(lig0[x-2]);
		g1=Module2(lig1[x-2]);
		g2=Module2(lig2[x-2]);
		m0=Module2(lig0[x-1]);
		m1=Module2(lig1[x-1]);
		m2=Module2(lig2[x-1]);
		cm1=lig1[x-1];
		if (m1>0) ang=(cm1.y>0)?acos(cm1.x/sqrt(m1)):M_PI-acos(cm1.x/sqrt(m1));
		else ang=0;
        k=((int)(4*ang/M_PI))%4;
		jj=x-1;
		for (j=0;j<x;j++)
			{
			d0=Module2(lig0[j]);
			d1=Module2(lig1[j]);
			d2=Module2(lig2[j]);
			switch(k)
				{
				case 0:
				  if (((m1>g1)&&(m1>=d1)) || ((m1==g1)&&(m1==d1))
					  || ((m1>g0)&&(m1>=d2)) || ((m1==g0)&&(m1==d2))) grille[ii][jj]=cm1;
				  else grille[ii][jj]=zeroC;
					 break;
				case 1:
				  if (((m1>g0)&&(m1>=d2)) || ((m1==g0)&&(m1==d2))
					 || ((m1>m0)&&(m1>=m2)) || ((m1==m0)&&(m1==m2))) grille[ii][jj]=cm1;
				  else grille[ii][jj]=zeroC;
					 break;
				case 2:
				  if (((m1>m0)&&(m1>=m2)) || ((m1==m0)&&(m1==m2))
					 || ((m1>=d0)&&(m1>g2)) || ((m1==d0)&&(m1==g2))) grille[ii][jj]=cm1;
				  else grille[ii][jj]=zeroC;
					 break;
				case 3:
				  if (((m1>=d0)&&(m1>g2)) || ((m1==d0)&&(m1==g2))
					 || ((m1>g1)&&(m1>=d1)) || ((m1==g1)&&(m1==d1))) grille[ii][jj]=cm1;
				  else grille[ii][jj]=zeroC;
					 break;
				}
			jj=(jj+1)%x;
			g0=m0;
			m0=d0;
			g1=m1;
			m1=d1;
			g2=m2;
			m2=d2;
			cm1=lig1[j];
			if (m1>0) ang=(cm1.y>0)?acos(cm1.x/sqrt(m1)):M_PI-acos(cm1.x/sqrt(m1));
			else ang=0;
			  k=((int)(4*ang/M_PI))%4;
			}
		ii=(ii+1)%y;
		ptr=lig0;
		lig0=lig1;
		lig1=lig2;
		  lig2=ptr;
		}
		memcpy(lig2,ligy,x*sizeof(Complexe));    // Dernière ligne de l'image
		g0=Module2(lig0[x-2]);
		g1=Module2(lig1[x-2]);
		g2=Module2(lig2[x-2]);
		m0=Module2(lig0[x-1]);
		m1=Module2(lig1[x-1]);
		m2=Module2(lig2[x-1]);
		cm1=lig1[x-1];
		if (m1>0) ang=(cm1.y>0)?acos(cm1.x/sqrt(m1)):M_PI-acos(cm1.x/sqrt(m1));
		else ang=0;
		  k=((int)(4*ang/M_PI))%4;
		jj=x-1;
		for (j=0;j<x;j++)
			{
			d0=Module2(lig0[j]);
			d1=Module2(lig1[j]);
			d2=Module2(lig2[j]);
			switch(k)
				{
				case 0:
				  if (((m1>g1)&&(m1>=d1)) || ((m1==g1)&&(m1==d1))
					  || ((m1>g0)&&(m1>=d2)) || ((m1==g0)&&(m1==d2))) grille[ii][jj]=cm1;
				  else grille[ii][jj]=zeroC;
					 break;
				case 1:
				  if (((m1>g0)&&(m1>=d2)) || ((m1==g0)&&(m1==d2))
					 || ((m1>m0)&&(m1>=m2)) || ((m1==m0)&&(m1==m2))) grille[ii][jj]=cm1;
				  else grille[ii][jj]=zeroC;
					 break;
				case 2:
				  if (((m1>m0)&&(m1>=m2)) || ((m1==m0)&&(m1==m2))
					 || ((m1>=d0)&&(m1>g2)) || ((m1==d0)&&(m1==g2))) grille[ii][jj]=cm1;
				  else grille[ii][jj]=zeroC;
					 break;
				case 3:
				  if (((m1>=d0)&&(m1>g2)) || ((m1==d0)&&(m1==g2))
					 || ((m1>g1)&&(m1>=d1)) || ((m1==g1)&&(m1==d1))) grille[ii][jj]=cm1;
				  else grille[ii][jj]=zeroC;
					 break;
				}
			jj=(jj+1)%x;
			g0=m0;
			m0=d0;
			g1=m1;
			m1=d1;
			g2=m2;
			m2=d2;
			cm1=lig1[j];
			if (m1>0) ang=(cm1.y>0)?acos(cm1.x/sqrt(m1)):M_PI-acos(cm1.x/sqrt(m1));
			else ang=0;
			  k=((int)(4*ang/M_PI))%4;
			}
	}

LibereCanal(canL);
LibereGrille(grille);
free(ligy);
free(lig2);
free(lig1);
free(lig0);
return(imD);
}


Image PermuteXYC(Image imS,Image imD)
/***********************************/
{
int x,y,i,j;
Complexe **grille,*valeur;
Canal canL;

if ((imD=CreeImageDest(imS,imD,T_COMPLEXE))==NULL) return(NULL);
LitTailleFenetre(imD,&x,&y);
if ((grille=(Complexe **) CreeGrille(imD,Z_FENETRE))==NULL) return(NULL);
if ((valeur=(Complexe *)calloc(x,sizeof(Complexe)))==NULL) return(NULL);
if ((canL=CreeCanal(imS,T_COMPLEXE,B_LIGNE,Z_FENETRE))==NULL) return(NULL);

for (i=0;i<y;i++)
	{
	LitCanal(canL,valeur);
	for (j=0;j<x;j++)
		{
		grille[i][j].x=valeur[j].y;
		grille[i][j].y=valeur[j].x;
		}
    }

LibereCanal(canL);
free(valeur);
LibereGrille(grille);
return(imD);
}


Image TransfereXYC(Image imX,Image imY,Image imD)
/***********************************************/

{
int x,y,i,j;
Reel *valX,*valY;
Complexe **grille;
Canal canX,canY;

if (TesteFenetre(imX,imY)) return(NULL);
LitTailleFenetre(imX,&x,&y);
if ((imD=CreeImageDest(imX,imD,T_COMPLEXE))==NULL) return(NULL);
if ((grille=(Complexe**)CreeGrille(imD,Z_FENETRE))==NULL) return(NULL);
if ((valX=(Reel*)calloc(x,sizeof(Reel)))==NULL) return(NULL);
if ((valY=(Reel*)calloc(x,sizeof(Reel)))==NULL) return(NULL);
if ((canX=CreeCanal(imX,T_REEL,B_LIGNE,Z_FENETRE))==NULL) return(NULL);
if ((canY=CreeCanal(imY,T_REEL,B_LIGNE,Z_FENETRE))==NULL) return(NULL);

for (i=0;i<y;i++)
	{
	LitCanal(canX,valX);
	LitCanal(canY,valY);
	for (j=0;j<x;j++)
		{
		grille[i][j].x=valX[j];
		grille[i][j].y=valY[j];
		}
    }

LibereCanal(canY);
LibereCanal(canX);
free(valY);
free(valX);
LibereGrille(grille);
return(imD);
}

Image TransCourbeImageLC(Image imLS,Image imD)
/********************************************/

{
int i,x,y,xx,yy;
Complexe **grille;
Canal canL;
Image imC;

if ((y=CompteImageL(imLS))==NULL) return(NULL);
imC=LitImageL(imLS,0);
LitTailleFenetre(imC,&x,&yy);

if ((imD=CreeImageSimple(imD,T_COMPLEXE,V_CARTE,x,y))==NULL) return(NULL);
if ((grille=(Complexe**)CreeGrille(imD,Z_FENETRE))==NULL) return(NULL);

for (i=0;i<y;i++)
	{
    imC=LitImageL(imLS,i);
	if ((canL=CreeCanal(imC,T_COMPLEXE,B_LIGNE,Z_FENETRE))==NULL) break;
    LitTailleFenetre(imC,&xx,&yy);
	 if (xx<=x) LitCanal(canL,grille[i]);
    LibereCanal(canL);
	}

LibereGrille(grille);
return(imD);
}

Image OuEtenduC(Image imS1,Image imS2,Image imD)
/**********************************************/

{
int i,j,x,y;
Complexe **grille,*val1,*val2;
Canal canL1,canL2;

if (TesteFenetre(imS1,imS2)) return(NULL);
if ((imD=CreeImageDest(imS1,imD,T_COMPLEXE))==NULL) return(NULL);
LitTailleFenetre(imS1,&x,&y);
if ((val1=(Complexe*)calloc(x,sizeof(Complexe)))==NULL) return(NULL);
if ((val2=(Complexe*)calloc(x,sizeof(Complexe)))==NULL) return(NULL);
if ((grille=(Complexe**)CreeGrille(imD,Z_FENETRE))==NULL) return(NULL);
if ((canL1=CreeCanal(imS1,T_COMPLEXE,B_LIGNE,Z_FENETRE))==NULL) return(NULL);
if ((canL2=CreeCanal(imS2,T_COMPLEXE,B_LIGNE,Z_FENETRE))==NULL) return(NULL);

for (i=0;i<y;i++)
	{
	LitCanal(canL2,val2);
	LitCanal(canL1,val1);
	for (j=0;j<x;j++)
		{
		if ( (val1[j].x!=0)||(val1[j].y!=0)) grille[i][j]=val1[j];
		else grille[i][j]=val2[j];
        }
    }

LibereCanal(canL2);
LibereCanal(canL1);
LibereGrille(grille);
free(val2);
free(val1);
return(imD);
}


Image VecteurCorrelationC(Image imS,Image imD)
/********************************************/
{
if (imS==NULL) return (NULL);
if ((imD=CreeImageDest (imS,imD,T_OCTET))==NULL) return (NULL);
imD->suivant=DepouilleCorrelC (imS,imD->suivant);
imD=TraceVecteurO(imD->suivant,imS,imD,118,186,255,1);
return (imD);
}
