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

Image ProlongeTaillePuiss2R(Image imS,Image imD)
/**********************************************/
/*
Prolongement d'une image à une taille égale à la puissance de 2 immédiatement
supérieure. Si la taille est déjà une puissance de 2, elle n'est pas modifiée.
Le prolongement est fait par périodisation.
*/
{
int x0,y0,n,x,x1,y1,i,j;
Canal can;
Reel **grille,*val;

if (imS==NULL) return(NULL);
LitTailleFenetre(imS,&x0,&y0);
// Calcul de la puissance de 2 >= à x0
x=1;
n=x0>>1;
while (n!=0) {n>>=1;x<<=1;}
if (x0 > x) x<<=1;
x1=x;
y1=x;
// Calcul de la puissance de 2 >= à y0
x=1;
n=y0>>1;
while (n!=0) {n>>=1;x<<=1;}
if (y0 > x) x<<=1;
// La taille de l'image est la plus grande des 2 tailles en x et en y
if (x>x1) {x1=x;y1=x;}
if (y0==1) y1=1;      // Cas particulier des courbes

if ((imD=CreeImageSimple(imD,T_REEL,imS->visu,x1,y1))==NULL) return(NULL);
can=CreeCanal(imS,T_REEL,B_LIGNE,Z_FENETRE);
grille=(Reel**)CreeGrille(imD,Z_FENETRE);
val=(Reel*) calloc(x0,sizeof(Reel));
if (can && grille && val)
  {
  for (i=0;i<y1;i++)
    {
    if (i%y0==0) PoseCanal(can,0,0);
    LitCanal(can,val);
    for (j=0;j<x1;j++) grille[i][j]=val[j%x0];
    }
  }
else imD=NULL;
free(val);
LibereGrille(grille);
LibereCanal(can);
return(imD);
}

Image ExtraitFenetreProlongeR(Image imS1,Image imS2,Image imD)
/********************************************************/
/*
Extraction d'une fenetre dans une image prolongée (imS1) à partir de l'image
source du prolongement (imS2). Le résultat a la taille de la fenêtre de imS2.
*/
{
int x0,y0,tx0,ty0,tx1,ty1;
if (LitFenetre(imS1,&x0,&y0,&tx0,&ty0)) return(NULL);
if (LitTailleFenetre(imS2,&tx1,&ty1)) return(NULL);
EcritFenetre(imS1,0,0,tx1,ty1);
imD=ExtraitFenetreR(imS1,imD);
EcritFenetre(imS1,x0,y0,tx0,ty0);
return(imD);
}


Image SegLaplacienSoleil(Image imS,Image imD,float echLap,float seuilLap,float seuilRel,float seuilCourb)
/*******************************************************************************************************/
/*
Segmentation pour les images de la surface du soleil.
Les opérations réalisées sur imS sont :
  - calcul de la moyenne moy de l'image (pour sa normalisation à 110),
	- 8*exp(imS*110*0.02/moy) soit 8*exp(imS*2.2/moy) pour augmenter le contraste des granules
   - segmentation à base de laplacien et croissance de région autour des max
   - séparation des particules collées
   - mise entre 0 et 255 de l'image binaire résultat
Paramètres de la fonction :
	- echLap : échelle du laplacien correspond à l'écart type de la gaussienne
      de filtrage avant laplacien (valeur typique 1.5)
   - seuilLap : valeur du seuil de détection pour le laplacien (valeur typique 10)
   - seuilRel : valeur du pourcentage du max. pour la croissance de région (dans
       l'hypothèse ou la particule est de profil gaussien la valeur est 0.2)
   - seuilCourb : valeur max de la courbure locale pour la séparation des
       particules (valeur typique 0.1)
*/
{
Image imT0,imT1,imT2=NULL,imT3,imT4;
Reel moy;
MoyenneR(imS,&moy);
if (moy>1e-6) imT2=ConstMultR(imS,NULL,2.2/moy);
ExpR(imT2,imT2);
ConstMultR(imT2,imT2,8);

imT3=ProlongeTaillePuiss2R(imT2,NULL);
LibereImage(imT2);
imT4=SeuilLaplGermesR(imT3,NULL,echLap,seuilLap,seuilRel);
LibereImage(imT3);
imT1=ExtraitFenetreProlongeR(imT4,imS,NULL);
LibereImage(imT4);

imT0=SepareSelect3R(imT1,NULL,seuilCourb,10);
LibereImage(imT1);
ConstMultR(imT0,imT0,255);
imD=TransfereO(imT0,imD);
LibereImage(imT0);
return(imD);
}


//int Seg_Laplacien_Soleil(char *nomS,char *nomD,float echLap,float seuilLap,float seuilRel,float seuilCourb)
/*********************************************************************************************************/
/*
Segmentation pour les images de la surface du soleil.
Les opérations réalisées sur imS sont :
	- 8*exp(imS*0.02) pour augmenter le contraste des granules
   - segmentation à base de laplacien et croissance de région autour des max
   - séparation des particules collées
   - mise entre 0 et 255 de l'image binaire résultat
Paramètres de la fonction :
   - nomS : nom du fichier source au format fits
   - nomD : nom du fichier destination au format fits
	- echLap : échelle du laplacien correspond à l'écart type de la gaussienne
      de filtrage avant laplacien (valeur typique 1.5)
   - seuilLap : valeur du seuil de détection pour le laplacien (valeur typique 10)
   - seuilRel : valeur du pourcentage du max. pour la croissance de région (dans
       l'hypothèse ou la particule est de profil gaussien la valeur est 0.2)
   - seuilCourb : valeur max de la courbure locale pour la séparation des
       particules (valeur typique 0.1)
Paramètre de retour :
   <>0 en cas d'erreur
   0 si tout va bien
*/
/*{
Image imS,imD;
int retour=1;

imS=ChargeFits(NULL,nomS);
if (imS!=NULL)
  {
  imD=SegLaplacienSoleil(imS,NULL,echLap,seuilLap,seuilRel,seuilCourb);
  if (imD!=NULL) retour=SauveFits(imD,nomD);
  LibereImage(imD);
  LibereImage(imS);
  }
return(retour);
}*/



void segment_cd_(float *tab,int *nx,int *ny,int *itab,float *ech_lap,float *seuil_lap,float *seuil_rel,float *seuil_courb)
/*************************************************************************************************************************/
/*
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
ech_lap,seuil_lap,seuil_rel,seuil_courb : paramètres de la segmentation
*/
{
int i,j,erreur=0;
Image imS,imD;
Reel **grS;
Octet **grD;

/* printf("%i\n",*nx); */

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");
  imD=SegLaplacienSoleil(imS,NULL,*ech_lap,*seuil_lap,*seuil_rel,*seuil_courb);
//  SauveRaw(imD,"imD.raw");
  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_cd\n",erreur);

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

