#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "image.h"
#include "canal.h"
#include "grille.h"
#include "c.h"
#include "r.h"
#include "fourier.h"



#define pi   3.1415926535897931160E0

static Complexe * CreeRacinesUnite ( int n );
static Complexe * CreeRacinesUniteInverse ( int n ) ;
static int * CreePermutation ( int n );
static void  Papillon ( int n, Complexe *s, Complexe *wn );
static int FFT1D ( int n, Complexe *s );
static int FFT1DInverse ( int n, Complexe *s );
static int FFT2D ( int n, Complexe **s );
static int FFT2DInverse ( int n, Complexe **s );
static Image MC ( Image imS1, Image imS2, Image imD );
static Image MCC ( Image imS1, Image imS2, Image imD );



static Complexe * CreeRacinesUnite ( int n )
/******************************************/
{
int i, nd2;
ReelL a, b;
Complexe *wn;

nd2 = n / 2;
if ( (wn = (Complexe *)calloc(nd2, sizeof(Complexe))) == NULL ) return ( NULL );

a = 2 * pi / n;
for ( i=0; i<nd2; i++ )
        {
        b = a * i;
        wn[i].x = (float)( cos ( b ) );
        wn[i].y = - (float)( sin ( b ) );
        }
return ( wn );
}



static Complexe * CreeRacinesUniteInverse ( int n )
/*************************************************/
{
int i, nd2;
ReelL a, b;
Complexe *wn;

nd2 = n / 2;
if ( (wn = (Complexe *)calloc(nd2, sizeof(Complexe))) == NULL ) return ( NULL );

a = 2 * pi / n;
for ( i=0; i<nd2; i++ )
        {
        b = a * i;
        wn[i].x = (float)( cos ( b ) );
        wn[i].y = (float)( sin ( b ) );
        }
return ( wn );
}



static int * CreePermutation ( int n )
/************************************/
{
int i, j, k, nd2;
int *p;

if ( (p = (int *)calloc(n, sizeof(int))) == NULL ) return (NULL);

for ( i=0; i<n; p[i]=i, i++ );
nd2 = n / 2;
j = 0;
for ( i=0; i<n-1; i++ )
        {
        if ( i < j )
                {
                p[i] = j;
                p[j] = i;
                }
        k = nd2;
        while ( k <= j )
                {
                j -= k;
                k /= 2;
                }
        j += k;
        }
return ( p );
}



static void  Papillon ( int n, Complexe *s, Complexe *wn )
/********************************************************/
{
int i, j, l, l2, nd2;
Complexe aux, w, *sj, *sjl;

nd2 = n / 2;
l = 1;
while ( l <= nd2 )
        {
        l2 = l * 2;
        for ( i=0; i<l; i++ )
                {
                w = wn[ nd2/l*i ];
                for ( j=i; j<n; j+=l2 )
                        {
                        sj = s + j;
                        sjl = sj + l;
                        aux.x = w.x * sjl->x - w.y * sjl->y;
                        aux.y = w.x * sjl->y + w.y * sjl->x;
                        sjl->x = sj->x - aux.x;
                        sjl->y = sj->y - aux.y;
                        sj->x += aux.x;
                        sj->y += aux.y;
                        }
                }
        l = l2;
        }
}



static int FFT1D ( int n, Complexe *s )
/*************************************/
{
int i, in2, nd2, *p;
Complexe *t, *wn;

wn = CreeRacinesUnite ( n );
p = CreePermutation ( n );
nd2=n/2;
if ( (t = (Complexe *)calloc(n, sizeof(Complexe))) == NULL ) return(1);

in2=nd2;
for ( i=0; i<nd2; i++ )
    {
    t[i] = s[p[i]];
    t[in2].x = -s[p[in2]].x;
    t[in2].y = -s[p[in2]].y;
    in2++;
    }
Papillon ( n, t, wn );
for ( i=0; i<n; i++ )  s[i] = t[i];

free(t);
free(p);
free(wn);
return(0);
}



static int FFT1DInverse ( int n, Complexe *s )
/********************************************/
{
int i, sgn, *p;
Complexe *t, *wn;

wn = CreeRacinesUniteInverse ( n );
p = CreePermutation ( n );
if ( (t = (Complexe *)calloc(n, sizeof(Complexe))) == NULL ) return(1);

for ( i=0; i<n; i++ )
    t[i] = s[p[i]];

Papillon ( n, t, wn );
sgn=1;
for ( i=0; i<n; i++ )
        {
        s[i].x = sgn*t[i].x / n;
        s[i].y = sgn*t[i].y / n;
        sgn=-sgn;
        }

free(t);
free(p);
free(wn);
return(0);
}



static int FFT2D ( int n, Complexe **s )
/**************************************/
{
int i, j, *p, nd2, jn2;
Complexe *t, *wn;

wn = CreeRacinesUnite ( n );
p = CreePermutation ( n );
nd2=n/2;
if ( (t = (Complexe *)calloc(n, sizeof(Complexe))) == NULL ) return(1);

for ( i=0; i<n; i++ )                     /* FFT sur les lignes */
        {
        /* i est pair */

        jn2=nd2;
        for ( j=0; j<nd2 ; j++ )          /* rearrangement de la ligne nøi */
                {
                t[j] =s[i][p[j]];
                t[jn2].x =-s[i][p[jn2]].x;
                t[jn2].y =-s[i][p[jn2]].y;
                jn2++;
                }

        Papillon ( n, t, wn );            /* papillon de la ligne nøi */
        for ( j=0; j<n; j++ )  s[i][j] = t[j];
        i++;

        /* i est impair */
        jn2=nd2;
        for ( j=0; j<nd2 ; j++ )          /* rearrangement de la ligne nøi */
                {
                t[jn2] =s[i][p[jn2]];
                t[j].x =-s[i][p[j]].x;
                t[j].y =-s[i][p[j]].y;
                jn2++;
                }

        Papillon ( n, t, wn );            /* papillon de la ligne nøi */
        for ( j=0; j<n; j++ )  s[i][j] = t[j];
        }

for ( j=0; j<n; j++ )                     /* FFT sur les colonnes */
        {
        for ( i=0; i<n; i++ )             /* rearrangement de la colonne nøj */
                t[i] = s[p[i]][j];
        Papillon ( n, t, wn );            /* papillon de la colonne nøj */
        for ( i=0; i<n; i++ )  s[i][j] = t[i];

        }

free(t);
free(p);
free(wn);
return(0);
}



static int FFT2DInverse ( int n, Complexe **s )
/*********************************************/
{
int i, j, *p, sgn;
Complexe *t, *wn;

wn = CreeRacinesUniteInverse ( n );
p = CreePermutation ( n );
if ( (t = (Complexe *)calloc(n, sizeof(Complexe))) == NULL )  return(1);

for ( i=0; i<n; i++ )                     /* FFT sur les lignes */
        {
        for ( j=0; j<n; j++ )             /* rearrangement de la ligne nøi */
                t[j] = s[i][p[j]];
        Papillon ( n, t, wn );            /* papillon de la ligne nøi */
        for ( j=0; j<n; j++ )
                {
                s[i][j].x = t[j].x / n;
                s[i][j].y = t[j].y / n;
                }
        }
sgn=1;
for ( j=0; j<n; j++ )                     /* FFT sur les colonnes */
        {
        for ( i=0; i<n; i++ )             /* rearrangement de la colonne nøj */
                t[i] = s[p[i]][j];
        Papillon ( n, t, wn );            /* papillon de la colonne nøj */
        for ( i=0; i<n; i++ )
                {
                s[i][j].x = sgn*t[i].x / n;
                s[i][j].y = sgn*t[i].y / n;
                sgn=-sgn;
                }
        sgn=-sgn;
        }

free(t);
free(p);
free(wn);
return(0);
}



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

{
Complexe **grille;
int i,nuns,x,y;

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

LitTailleFenetre(imS, &x, &y);
nuns=0;
for (i=0;i<8*sizeof(x);i++) if ( ((x>>i) & 1) == 1) nuns++;
if (nuns>1) return(NULL);
if ( (y!=1) && (y!=x) ) return(NULL);

if ( (imD=TransfereC(imS,imD))==NULL) return(NULL);

if ( (grille = (Complexe**)CreeGrille(imD,Z_FENETRE))==NULL) return(NULL);

if (y==1) FFT1D(x, *grille);
else FFT2D(x, grille);

LibereGrille(grille);

return(imD);
}



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

{
Complexe **grille;
int i,nuns,x,y;

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

LitTailleFenetre(imS, &x, &y);
nuns=0;
for (i=0;i<8*sizeof(x);i++) if ( ((x>>i) & 1) == 1) nuns++;
if (nuns>1) return(NULL);
if ( (y!=1) && (y!=x) ) return(NULL);

if ( (imD=TransfereC(imS,imD))==NULL) return(NULL);

if ( (grille = (Complexe**)CreeGrille(imD,Z_FENETRE))==NULL) return(NULL);

if (y==1) FFT1DInverse(x, *grille);
else FFT2DInverse(x, grille);

LibereGrille(grille);
return(imD);
}



static  Image MC (Image imS1, Image imS2, Image imD)
/**************************************************/

{
int i,j,x,y;
Canal canL1, canL2, canE;
Reel centrage=1;
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)*centrage;
        val1[j].y=(v1.y*v2.x+v2.y*v1.x)*centrage;
        centrage*=-1;
        }
    EcritCanal(canE,val1);
    centrage*=-1;
    }

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



static  Image MCC ( Image imS1, Image imS2, Image imD )
/*****************************************************/

{
int i,j,x,y;
Canal canL1, canL2, canE;
Reel centrage=1;
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)*centrage;
        val1[j].y=(v1.y*v2.x-v2.y*v1.x)*centrage;
        centrage*=-1;
        }
    EcritCanal(canE,val1);
    centrage*=-1;
    }

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



Image  ConvolueC ( Image imS1, Image imS2, Image imD )
/****************************************************/
{
Image im;

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

if ((im =TFRDirecteC(imS2,NULL))==NULL) return(NULL);
if (     TFRDirecteC(imS1,imD)  ==NULL) return(NULL);
if (     MC(im,imD,imD)         ==NULL) return(NULL);
if (     TFRInverseC(imD,imD)   ==NULL) return(NULL);

LibereImage(im);

return(imD);
}



Image  CorreleC ( Image imS1, Image imS2, Image imD )
/***************************************************/
{
Image im;

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

if ((im =TFRDirecteC(imS2,NULL))==NULL) return(NULL);
if (     TFRDirecteC(imS1,imD)  ==NULL) return(NULL);
if (     MCC(im,imD,imD)        ==NULL) return(NULL);
if (     TFRInverseC(imD,imD)   ==NULL) return(NULL);

LibereImage(im);

return(imD);
}



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

{
if ((imD=TFRDirecteC(imS,imD))==NULL) return(NULL);
if (     MC(imD,imD,imD)      ==NULL) return(NULL);
if (     TFRInverseC(imD,imD) ==NULL) return(NULL);

return(imD);
}



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

{
if ((imD=TFRDirecteC(imS,imD))==NULL) return(NULL);
if (     MCC(imD,imD,imD)     ==NULL) return(NULL);
if (     TFRInverseC(imD,imD) ==NULL) return(NULL);

return(imD);
}



Image  FiltreFourierC ( Image imS, Image filtre, Image imD )
/**********************************************************/

{
int i,j,x,y,xf,yf,k;
Canal canL,canE;
Reel *f,x1,y1;
Complexe *val;

if (filtre==NULL) return(NULL);
LitTailleFenetre(filtre,&xf,&yf);
if (yf>1) return(NULL);
if (imS==NULL) return(NULL);
LitTailleFenetre(imS,&x,&y);
if (x!=y) return(NULL);
if (x!=2*xf) return(NULL);

if ((imD=CreeImageDest(imS,imD,T_COMPLEXE))==NULL) return(NULL);
if ((f=(Reel*)calloc(xf,sizeof(Reel)))==NULL) return(NULL);
if ((val=(Complexe*)calloc(x,sizeof(Complexe)))==NULL) return(NULL);
if ((canL=CreeCanal(filtre,T_REEL,B_LIGNE,Z_FENETRE))==NULL) return(NULL);
LitCanal(canL,f);
LibereCanal(canL);
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);
    for(j=0;j<x;j++)
        {
	x1=j-xf;
        y1=i-xf;
        k=(int)(sqrt(x1*x1+y1*y1)+.5);
        if (k<xf)
            {
            val[j].x*=f[k];
            val[j].y*=f[k];
            }
        else val[j].x=val[j].y=0;
        }
    EcritCanal(canE,val);
    }

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



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

{
int i,j,x,y,xf,yf,k;
Canal canL,canE;
ReelL x1,y1;
Complexe *val,*f;

if (imS==NULL) return(NULL);
LitTailleFenetre(imS,&xf,&yf);
if (yf>1) return(NULL);
x=2*xf;
y=x;
if ((imD=CreeImageSimple(imD,T_COMPLEXE,V_CARTE,x,y))==NULL) return(NULL);

if ((f=(Complexe*)calloc(xf,sizeof(Complexe)))==NULL) 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);
LitCanal(canL,f);
LibereCanal(canL);
if ((canE=CreeCanal(imD,T_COMPLEXE,B_LIGNE,Z_FENETRE))==NULL) return(NULL);

for(i=0;i<y;i++)
    {
    for(j=0;j<x;j++)
        {
        x1=j-xf;
        y1=i-xf;
        k=(int)(sqrt(x1*x1+y1*y1)+.5);
	if (k<xf)
            {
            val[j].x=f[k].x;
            val[j].y=f[k].y;
            }
        else val[j].x=val[j].y=0;
        }
    EcritCanal(canE,val);
    }

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



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

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

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

LitTailleFenetre(imD,&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 ((canE=CreeCanal(imD, T_COMPLEXE, B_LIGNE, Z_FENETRE))==NULL) return(NULL);

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

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


/*------------------------------------------------------*/
/*  Filtrage                                           -*/
/*------------------------------------------------------*/
Image PasseBandeC(Image imS,Image imD,int b1, int b2, Reel pDegre)
/****************************************************************/

{
int x,y,i,trans,xp,d1,d2,d3,d4;
Reel **grille,w,angle,k;
Image profil,imT;

if (imS==NULL) return(NULL);
LitTailleFenetre(imS,&x,&y);
xp=(int)(sqrt((double)x*x+(double)y*y)/2);

if ((imT=CreeImageDest(imS,NULL,T_REEL))==NULL) return(NULL);
if ((profil=CreeImageSimple(NULL,T_REEL,V_COURBE,xp,1))==NULL) return(NULL);
if ((grille=(Reel **)CreeGrille(profil,Z_FENETRE))==NULL) return(NULL);

angle=pDegre*2*acos(0)/180;
if (cos(angle)==0) w=1e4;
else w=abs(2*tan(angle));
if (w==0) w=1e-4;
k=2*acos(0)/x;
trans=(int)(2*acos(0)/w/k);
if (b2<b1) {d1=b2;b2=b1;b1=d1;}
d1=b1-trans/2;
d2=b1+trans/2;
d3=b2-trans/2;
d4=b2+trans/2;

for (i=0;i<xp;i++)
	{
	if (i<d1)
		{
		grille[0][i]=0;
		continue;
		}
	if (i<d2)
		{
		  grille[0][i]=(1-cos((i-d1)*w*k))/2;
		  continue;
		}
	if (i<d3)
		{
		  grille[0][i]=1;
		  continue;
		}
	if (i<d4)
		{
		grille[0][i]=(1+cos((i-d3)*w*k))/2;
		  continue;
		}
	}

imT=CircR(imS,profil,imT);
imD=MultC(imS,imT,imD);
LibereImage (imT);
LibereGrille(grille);
LibereImage(profil);
return(imD);
}



Image RejectBandeC(Image imS,Image imD,int b1, int b2, Reel pDegre)
/*****************************************************************/

{
int x,y,i,trans,xp,d1,d2,d3,d4;
Reel **grille,w,angle,k;
Image profil,imT;

if (imS==NULL) return(NULL);
LitTailleFenetre(imS,&x,&y);
xp=(int)(sqrt((double)x*x+(double)y*y)/2);

if ((imT=CreeImageDest(imS,NULL,T_REEL))==NULL) return(NULL);
if ((profil=CreeImageSimple(NULL,T_REEL,V_COURBE,xp,1))==NULL) return(NULL);
if ((grille=(Reel **)CreeGrille(profil,Z_FENETRE))==NULL) return(NULL);

angle=pDegre*2*acos(0)/180;
if (cos(angle)==0) w=1e4;
else w=abs(2*tan(angle));
if (w==0) w=1e-4;
k=2*acos(0)/x;
trans=(int)(2*acos(0)/w/k);
if (b2<b1) {d1=b2;b2=b1;b1=d1;}
d1=b1-trans/2;
d2=b1+trans/2;
d3=b2-trans/2;
d4=b2+trans/2;

for (i=0;i<xp;i++)
	{
	if (i<d1)
		{
		grille[0][i]=1;
		continue;
		}
	if (i<d2)
		{
		  grille[0][i]=(1+cos((i-d1)*w*k))/2;
		  continue;
		}
	if (i<d3)
		{
		  grille[0][i]=0;
		  continue;
		}
	if (i<d4)
		{
		grille[0][i]=(1-cos((i-d3)*w*k))/2;
		  continue;
		}
	 grille[0][i]=1;
	}

imT=CircR(imS,profil,imT);
imD=MultC(imS,imT,imD);
LibereImage (imT);
LibereGrille(grille);
LibereImage(profil);
return(imD);
}




Image DepouilleCorrelC(Image imS,Image imD)
/*****************************************/
{
int i,n,ox,oy,tx,ty,ox0,oy0,x0,y0;
Reel min,max;
Complexe **grille;
FenetreL fen;
Point pMin,pMax;

if (imS==NULL) return(NULL);
n=CompteFenetreL(imS->fenetreL);
if (n==0) n=1;

if (imD==NULL)
	if ((imD=CreeImageSimple(imD,T_COMPLEXE,V_POINT,n,2))==NULL) return(NULL);
else
	if ((imD->type!=T_COMPLEXE)||(imD->visu!=V_POINT)||(imD->taille.x!=n)||(imD->taille.y!=2)) return (NULL);
if ((grille=(Complexe **)CreeGrille(imD,Z_FENETRE))==NULL) return(NULL);
LitFenetre(imS,&ox0,&oy0,&x0,&y0);
n=imD->fenetre.taille.x;
for (i=0;i<n;i++)
	{
	if (n!=1)
		{
		fen=LitFenetreL(imS->fenetreL,i);
		ox=fen->origine.x;
		oy=fen->origine.y;
		tx=fen->taille.x;
		ty=fen->taille.y;
		}
	else {ox=ox0;oy=oy0;tx=x0;ty=y0;}
	EcritFenetre(imS,ox,oy,tx,ty);
	PosMinMaxR(imS,&pMin,&pMax,&min,&max);
	grille[0][i].x=ox+tx/2;
	grille[0][i].y=oy+ty/2;
	grille[1][i].x=(int)pMax.x-tx/2;
	grille[1][i].y=(int)pMax.y-ty/2;
	}

EcritFenetre(imS,ox0,oy0,x0,y0);
LibereGrille(grille);
return(imD);
}



Image DepouilleAutoCorrelC(Image imS,Image imD)
/*********************************************/
{
int i,n,ox,oy,tx,ty,ox0,oy0,x0,y0;
Reel min,max;
Complexe **grille;
FenetreL fen;
Point pMin,pMax;
Image imFen;

if (imS==NULL) return(NULL);
n=CompteFenetreL(imS->fenetreL);
if (n==0) return(NULL);

if (imD==NULL)
	if ((imD=CreeImageSimple(imD,T_COMPLEXE,V_POINT,n,2))==NULL) return(NULL);
else
	if ((imD->type!=T_COMPLEXE)||(imD->visu!=V_POINT)||(imD->taille.x!=n)||(imD->taille.y!=2)) return (NULL);
if ((grille=(Complexe **)CreeGrille(imD,Z_FENETRE))==NULL) return(NULL);
LitFenetre(imS,&ox0,&oy0,&x0,&y0);
n=imD->fenetre.taille.x;
for (i=0;i<n;i++)
	{
	if (n!=1)
		{
		fen=LitFenetreL(imS->fenetreL,i);
		ox=fen->origine.x;
		oy=fen->origine.y;
		tx=fen->taille.x;
		ty=fen->taille.y;
		}
	else {ox=ox0;oy=oy0;tx=x0;ty=y0;}
	EcritFenetre(imS,ox,oy,tx,ty);
	imFen=ExtraitFenetreR(imS,NULL);
	Max4DirR(imFen,imFen);
	PosMinMaxR(imFen,&pMin,&pMax,&min,&max);
	EcritPointR(imFen,&pMax,min);
	PosMinMaxR(imFen,&pMin,&pMax,&min,&max);
	grille[0][i].x=ox+tx/2;
	grille[0][i].y=oy+ty/2;
	if (max>min)
		{
		grille[1][i].x=(int)pMax.x-tx/2;
		grille[1][i].y=(int)pMax.y-ty/2;
		}
	else
		{
		grille[1][i].x=0;
		grille[1][i].y=0;
		}
	LibereImage(imFen);
	}

EcritFenetre(imS,ox0,oy0,x0,y0);
LibereGrille(grille);
return(imD);
}




