#include "stdio.h"
#include "image.h"
#include "grille.h"
#include "r.h"
#include "dev.h"



//*****************************************************************************
// Lissage de l'image par moyenne
// w=rayon du carré de calcu de la moyenne (soit un carré de 2*n+1)
// n=nb d'itération
//*****************************************************************************
Image ConvolMoyenne2R(Image imS,Image imD,int w,int n){

  int i,j,k,l,m,x,y,t;
  Reel s;
  Image imI ;
  Canal canL ;
  Reel **grilleI ;
  Reel **grilleD ;


  if ((imD=CreeImageDest(imS,imD,T_REEL))==NULL) return(NULL);
  LitTailleFenetre(imS,&x,&y) ;
  if ((grilleD=(Reel**)CreeGrille(imD,Z_FENETRE))==NULL) return (NULL);
  if ((canL=CreeCanal(imS,T_REEL,B_LIGNE,Z_FENETRE))==NULL) return (NULL);
  if ((imI=CreeImageDest(imS,NULL,T_REEL))==NULL) return(NULL);
  if ((grilleI=(Reel**)CreeGrille(imI,Z_FENETRE))==NULL) return (NULL);

  // Initialisation des images
  for(i=0;i<y;i++){
    LitCanal(canL,grilleD[i]);
  }
  t=2*w+1;
  for(m=0;m<n;m++){
    // GrilleI <- GrilleD
    for(i=0;i<y;i++)
      for(j=0;j<x;j++)
        grilleI[i][j]=grilleD[i][j] ;
    // Lissage par moyenne sur les lignes
    for(i=0;i<y;i++){
      for(j=0;j<x;j++){
        /*j1=max(j-w,0); j2=min(j+w+1,x);*/ s=0;
          for(l=j-w;l<j+w+1;l++)
            s+=grilleI[i][min(max(l,0),x-1)] ;
        grilleD[i][j]=s/t ;
      }
    }
    // Lissage par moyenne sur les colonnes
    for(i=0;i<y;i++){
      //i1=max(i-w,0); i2=min(i+w+1,y);
      for(j=0;j<x;j++){
        s=0;
        for(k=i-w;k<i+w+1;k++)
            s+=grilleD[min(max(k,0),y-1)][j] ;
        grilleD[i][j]=s/t ;
      }
    }
  }

  LibereGrille(grilleI);
  LibereImage(imI);
  LibereCanal(canL);
  LibereGrille(grilleD);
  return(imD);
}



Image Laplacien4DirR(Image imS,Image imD)
/*************************************/
// Laplacien suivant 4 directions
//On calcule le laplacien suivant les 4 directions du voisinage V8, et on retiens
// le minimum
{
Image imT;
Reel **grD,**grS,l1,l2,l3,l4,m1,m2;
int i,j,x,y,im,ip,jm,jp;

imT=TransfereR(imS,NULL);
imD=NiveauR(imS,imD,0);
grS=(Reel **)CreeGrille(imT,T_REEL);
grD=(Reel **)CreeGrille(imD,T_REEL);
LitTailleFenetre(imS,&x,&y);
if (imT && imS && grS && grD)
  {
  for (i=0;i<y;i++)
    {
    im=(i<=0)?0:i-1;
    ip=(i>=y-1)?y-1:i+1;
    for (j=0;j<x;j++)
      {
      jm=(j<=0)?0:j-1;
      jp=(j>=x-1)?x-1:j+1;
      l4=l3=l2=l1=-2*grS[i][j];
      l1=l1+grS[i][jm]+grS[i][jp];
      l2=l2+grS[im][j]+grS[ip][j];
      l3=l3+grS[im][jm]+grS[ip][jp];
      l4=l4+grS[im][jp]+grS[ip][jm];
      m1=l1>l2?l1:l2;
      m2=l3>l4?l3:l4;
      grD[i][j]=m1>m2?m1:m2;
      }
    }
  }

LibereGrille(grD);
LibereGrille(grS);
LibereImage(imT);
return(imD);
}


Image SegLaplacienSoleil3(Image imS,Image imD,int nMoy,float seuilLap,float seuilBas)
/***********************************************************************************/
/*
Segmentation pour les images de la surface du soleil.
Les opérations réalisées sur imS sont :
   - application d'un filtre moyenne glissante de taille nMoy
   - calcul du laplacien directionnel (min dans les 4 directions)
   - segmentation par ligne de partage des eaux (épaississement conditionnel)
   - mise entre 0 et 255 de l'image binaire résultat
Paramètres de la fonction :
	 - nMoy : taille du filtre pour le calcul de la moyenne glissante
   - seuilLap : valeur du seuil de détection pour le laplacien (valeur strouss 0)
   - seuilBas : valeur du seuil inférieur pour limiter l'extension des granules
       (valeur typique -0.1)
*/
{
Image imT0,imT1;

// Moyenne glissante
imT0=ConvolMoyenne2R(imS,NULL,(abs(nMoy)-1)/2,1);

// Calcul du laplacien
Laplacien4DirR(imT0,imT0);
ConstMultR(imT0,imT0,-1);

imT1=SeuilleManuR(imT0,NULL,2,seuilBas);
imD=EpaissitCondR(imT0,imT1,imD,0);
LibereImage(imT0);
LibereImage(imT1);
SeuilleManuR(imD,imD,2,seuilLap);
EtaleR(imD,imD,255,0);
EbarbuleR(imD,imD,0);
EtaleR(imD,imD,255,0);
//  ErodeCroixR(imD,imD);
//  DilateCroixR(imD,imD);

return(imD);
}




void segment_cd3_(float *tab,int *nx,int *ny,int *itab,int *n_moy,float *seuil_lap,float *seuil_bas)
/******************************************************************************************************/
/*
Fonction pour la segmentation interfaçable avec le fortran :
tab : tableau 2d de taille nx,ny contenant l'image source
itab : tableau 2d de taille nx,ny contenant l'image segmentée
nx,ny : taille des images
Paramètres de segmentation :
	 - nMoy : taille du filtre pour le calcul de la moyenne glissante (valeur typique 5)
   - seuil_lap : valeur du seuil de détection pour le laplacien (valeur Strouss 0)
   - seuil_bas : valeur du seuil inférieur pour limiter l'extension des granules
       (valeur typique -0.1)
*/
{
int i,j,erreur=0;
Image imS,imD;
Reel **grS;
Octet **grD;

printf("%i\n",*nx);
printf("%i\n",*ny);
printf("%i\n",*n_moy);
printf("%f\n",*seuil_lap);
printf("%f\n",*seuil_bas);

imS=CreeImageSimple(NULL,T_REEL,V_CARTE,*nx,*ny);
imD=NULL;
grS=(Reel **)CreeGrille(imS,Z_FENETRE);
grD=NULL;
if (imS && grS)
  {
  for (i=0;i<*ny;i++)
    for (j=0;j<*nx;j++) grS[i][j]=(Reel)tab[i**nx+j];
//  SauveRaw(imS,"imS.raw");
//  printf("Appel de SegLaplacienSoleil\n");
  imD=SegLaplacienSoleil3(imS,NULL,*n_moy,*seuil_lap,*seuil_bas);
//  SauveRaw(imD,"imD.raw");
//  printf("Sortie de SegLaplacienSoleil\n");
  grD=(Octet **)CreeGrille(imD,Z_FENETRE);
  if (grD)
    {
    for (i=0;i<*ny;i++)
      for (j=0;j<*nx;j++)
        if (grD[i][j]>0) itab[i**nx+j]=1;
        else itab[i**nx+j]=0;
    }
  else erreur=2;
  }
else erreur=1;

if (erreur) printf("Erreur %d : Erreur dans la fonction segment_cd2\n",erreur);

LibereGrille(grD);
LibereImage(imD);
LibereGrille(grS);
LibereImage(imS);
}

