/****************************************************************************/
/*                                                                          */
/*                           BIBLIOTHEQUE IMAGE                             */
/*                                                                          */
/****************************************************************************/

#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#include "image.h"
#include "canal.h"
#include "grille.h"
#include "visu.h"
#include <stdio.h>

/****************************************************************************/
Image CreeImage(char * nom,char * commentaire,Type type,Visu visu,
		int tailleX,int tailleY,Fenetre * fenetre,Lut * lut)
/****************************************************************************/


{
int   i;
Image image;

if ( (image=(Image)calloc(1,sizeof(*image)))==NULL) return(NULL);

if (nom!=NULL)
	if ( (image->nom=strdup(nom))==NULL) {LibereImage(image);return(NULL);}

if (commentaire!=NULL)
	if ( (image->commentaire=strdup(commentaire))==NULL) {LibereImage(image);return(NULL);}

image->type=type;
image->visu=visu;

image->taille.x=tailleX;
image->taille.y=tailleY;

if (fenetre==NULL)
	{
	image->fenetre.origine.x=0;
	image->fenetre.origine.y=0;
	image->fenetre.taille=image->taille;
    image->fenetre.suivant=NULL;
	}
else image->fenetre=*fenetre;

switch(type)
	{
	case T_OCTET:
		{
		if ( (image->donnee.octet=(Octet**)calloc(tailleY,sizeof(Octet*)))==NULL) {LibereImage(image);return(NULL);}
		for (i=0;i<tailleY;i++)
			if( (image->donnee.octet[i]=(Octet*)calloc(tailleX,sizeof(Octet)))==NULL) {LibereImage(image);return(NULL);}
		break;
		}
	case T_ENTIER:
		{
		if ( (image->donnee.entier=(Entier**)calloc(tailleY,sizeof(Entier*)))==NULL) {LibereImage(image);return(NULL);}
		for (i=0;i<tailleY;i++)
			if( (image->donnee.entier[i]=(Entier*)calloc(tailleX,sizeof(Entier)))==NULL) {LibereImage(image);return(NULL);}
		break;
		}
	case T_ENTIERL:
		{
		if ( (image->donnee.entierL=(EntierL**)calloc(tailleY,sizeof(EntierL*)))==NULL) {LibereImage(image);return(NULL);}
		for (i=0;i<tailleY;i++)
			if( (image->donnee.entierL[i]=(EntierL*)calloc(tailleX,sizeof(EntierL)))==NULL) {LibereImage(image);return(NULL);}
		break;
		}
	case T_REEL:
		{
		if ( (image->donnee.reel=(Reel**)calloc(tailleY,sizeof(Reel*)))==NULL) {LibereImage(image);return(NULL);}
		for (i=0;i<tailleY;i++)
			if( (image->donnee.reel[i]=(Reel*)calloc(tailleX,sizeof(Reel)))==NULL) {LibereImage(image);return(NULL);}
		break;
		}
	case T_REELL:
		{
		if ( (image->donnee.reelL=(ReelL**)calloc(tailleY,sizeof(ReelL*)))==NULL) {LibereImage(image);return(NULL);}
		for (i=0;i<tailleY;i++)
			if( (image->donnee.reelL[i]=(ReelL*)calloc(tailleX,sizeof(ReelL)))==NULL) {LibereImage(image);return(NULL);}
		break;
		}
	case T_COMPLEXE:
		{
		if ( (image->donnee.complexe=(Complexe**)calloc(tailleY,sizeof(Complexe*)))==NULL) {LibereImage(image);return(NULL);}
		for (i=0;i<tailleY;i++)
			if( (image->donnee.complexe[i]=(Complexe*)calloc(tailleX,sizeof(Complexe)))==NULL) {LibereImage(image);return(NULL);}
		break;
		}
	case T_COMPLEXEL:
		{
		if ( (image->donnee.complexeL=(ComplexeL**)calloc(tailleY,sizeof(ComplexeL*)))==NULL) {LibereImage(image);return(NULL);}
		for (i=0;i<tailleY;i++)
			if( (image->donnee.complexeL[i]=(ComplexeL*)calloc(tailleX,sizeof(ComplexeL)))==NULL) {LibereImage(image);return(NULL);}
		break;
		}
	case T_COULEUR:
		{
		if ( (image->donnee.couleur=(Couleur**)calloc(tailleY,sizeof(Couleur*)))==NULL) {LibereImage(image);return(NULL);}
		for (i=0;i<tailleY;i++)
			if( (image->donnee.couleur[i]=(Couleur*)calloc(tailleX,sizeof(Couleur)))==NULL) {LibereImage(image);return(NULL);}
		break;
      }
	case T_VECTEUR2D:
		{
		if ((image->donnee.vecteur2D=(Vecteur2D**)calloc(tailleY,sizeof(Vecteur2D*)))==NULL) {LibereImage (image);return (NULL);}
		for (i=0;i<tailleY;i++)
			if( (image->donnee.vecteur2D[i]=(Vecteur2D*)calloc(tailleX,sizeof(Vecteur2D)))==NULL) {LibereImage(image);return(NULL);}
		break;

		}
	}

if (lut==NULL) image->lut=NULL;
else
	{
	if ( (image->lut=(Lut *)malloc(sizeof(Lut)+lut->taille*sizeof(Couleur)))==NULL) {LibereImage(image);return(NULL);}
	memcpy(image->lut,lut,sizeof(Lut)+lut->taille*sizeof(Couleur));
	}

image->info=NULL;
image->util=NULL;
image->fenetreL=NULL;
image->suivant=NULL;

return(image);
}


/****************************************************************************/
Image CreeImageDest(Image imS, Image imD, Type type)
/****************************************************************************/

{

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

if (imD==NULL)
	{
	if ((imD=CreeImage(NULL,NULL, type, imS->visu, imS->taille.x, imS->taille.y,
	  &imS->fenetre, imS->lut))==NULL) return(NULL);
	}
else
	{
	if (imD->type!=type) return(NULL);
	if (imD->fenetre.taille.x!=imS->fenetre.taille.x) return (NULL);
	if (imD->fenetre.taille.y!=imS->fenetre.taille.y) return (NULL);
	free(imD->util);
	imD->util=NULL;
	free(imD->info);
	imD->info=NULL;
	if (imS->lut!=imD->lut)
	{
	free(imD->lut);
	if (imS->lut==NULL) imD->lut=NULL;
		else
		{
		if ( (imD->lut=(Lut *)malloc(sizeof(Lut)+imS->lut->taille*sizeof(Couleur)))==NULL) return(NULL);
		memcpy(imD->lut,imS->lut,sizeof(Lut)+imS->lut->taille*sizeof(Couleur));
		}
	}
   free(imD->commentaire);
   imD->commentaire=NULL;
   free(imD->nom);
   imD->nom=NULL;
   }
return(imD);
}



/****************************************************************************/
Image CreeImageSimple(Image image, Type type,Visu visu, int tailleX,
	int tailleY)
/****************************************************************************/

{
if (image==NULL)
 {if( (image=CreeImage(NULL,NULL,type,visu,tailleX,tailleY,NULL,NULL))==NULL) return(NULL);}
else
	{
	if ( image->fenetre.taille.x!=tailleX) return (NULL);
	if ( image->fenetre.taille.y!=tailleY) return (NULL);
	if ( image->type!=type) return(NULL);
	image->visu=visu;
	free(image->info);
	image->info=NULL;
	free(image->lut);
	image->lut=NULL;
	free(image->commentaire);
	image->commentaire=NULL;
	free(image->nom);
	image->nom=NULL;
	}
return(image);
}


/***********************************************************************/
Image CreeImageGeneS(Image imD,char *nomGene,int n)

// Création de l'image séquence avec remplissage des noms si imD==NULL
/***********************************************************************/
{
Image imSeq;
int nc,i;
char nom[MAXNOMFICH],nomi[MAXNOMFICH],format[MAXNOMFICH];

if ((imSeq=CreeImageS(imD,n))==NULL) return(NULL);
if ((imD==NULL)&&(nomGene!=NULL))
  {
  sprintf(nom,"%d",n);
  nc=strlen(nom);
  strcpy (nom,nomGene);
  nom[strlen(nom)-4]='\0'; // Suppression de l'extension
  sprintf(format,"%s%%0%dd%s",nom,nc,strrchr(nomGene,'.'));
  for (i=0;i<n;i++)
	 {
	 sprintf(nomi,format,i);
	 EcritImageS(imSeq,nomi,i);
	 }
  }
return(imSeq);
}


/****************************************************************************/
void LibereImage(Image image)
/****************************************************************************/

{
int i;

if (image==NULL) return;

LibereImage(image->suivant);
LibereFenetreL(image->fenetreL);
free(image->util);
free(image->info);
free(image->lut);

if (image->donnee.octet!=NULL)
switch(image->type)
	{
	case T_OCTET :
		{
		for (i=image->taille.y-1;i>=0;i--) free(image->donnee.octet[i]);
		break;
		}
	case T_ENTIER :
		{
		for (i=image->taille.y-1;i>=0;i--) free(image->donnee.entier[i]);
		break;
		}
	case T_ENTIERL :
		{
		for (i=image->taille.y-1;i>=0;i--) free(image->donnee.entierL[i]);
		break;
		}
	case T_REEL :
		{
		for (i=image->taille.y-1;i>=0;i--) free(image->donnee.reel[i]);
		break;
		}
	case T_REELL :
		{
		for (i=image->taille.y-1;i>=0;i--) free(image->donnee.reelL[i]);
		break;
		}
	case T_COMPLEXE :
		{
		for (i=image->taille.y-1;i>=0;i--) free(image->donnee.complexe[i]);
		break;
		}
	case T_COMPLEXEL :
		{
		for (i=image->taille.y-1;i>=0;i--) free(image->donnee.complexeL[i]);
		break;
		}
	case T_COULEUR :
		{
		for (i=image->taille.y-1;i>=0;i--) free(image->donnee.couleur[i]);
		break;
		}
	case T_VECTEUR2D :
		{
		for (i=image->taille.y-1;i>=0;i--) free(image->donnee.vecteur2D[i]);
		break;
		}
	}
free(image->donnee.octet);
free(image->commentaire);
free(image->nom);

free(image);
}

/************************************************/
Image LibereImg(Image imS)
/* version de LibereImage utile pour les macros
/************************************************/
{
LibereImage(imS);
return(NULL);
}



/****************************************************************************/
int   LitFenetre(Image image, int *ox, int *oy, int *tx, int *ty)
/****************************************************************************/

{
if (image==NULL) return(1);
*tx=image->fenetre.taille.x;
*ty=image->fenetre.taille.y;
*ox=image->fenetre.origine.x;
*oy=image->fenetre.origine.y;
return(0);
}


/****************************************************************************/
int  LitTailleFenetre(Image image, int *x, int *y)
/****************************************************************************/

{
if (image==NULL) return(1);
*x=image->fenetre.taille.x;
*y=image->fenetre.taille.y;
return(0);
}



/****************************************************************************/
int  LitOrigineFenetre(Image image, int *ox, int *oy)
/****************************************************************************/

{
if (image==NULL) return(1);
*ox=image->fenetre.origine.x;
*oy=image->fenetre.origine.y;
return(0);
}



/****************************************************************************/
int  EcritFenetre(Image image, int ox, int oy, int tx, int ty)
/****************************************************************************/

{
if (image==NULL) return(1);
if (((ox+tx)<=image->taille.x)
   &&((oy+ty)<=image->taille.y))
	{
	image->fenetre.origine.x=ox;
	image->fenetre.origine.y=oy;
	image->fenetre.taille.x=tx;
	image->fenetre.taille.y=ty;
	}
else return(1);
return(0);
}



/****************************************************************************/
int  EcritTailleFenetre(Image image, int x, int y)
/****************************************************************************/

{
if (image==NULL) return(1);
if (((x+image->fenetre.origine.x)<=image->taille.x)
   &&((y+image->fenetre.origine.y)<=image->taille.y))
	{
	image->fenetre.taille.x=x;
	image->fenetre.taille.y=y;
	}
else return(1);
return(0);
}




/****************************************************************************/
int  EcritOrigineFenetre(Image image, int ox, int oy)
/****************************************************************************/

{
if (image==NULL) return(1);
if (((ox+image->fenetre.taille.x)<=image->taille.x)
   &&((oy+image->fenetre.taille.y)<=image->taille.y))
	{
	image->fenetre.origine.x=ox;
	image->fenetre.origine.y=oy;
	}
else return(1);
return(0);
}



/****************************************************************************/
void  LitTailleImage(Image image, int *x, int *y)
/****************************************************************************/

{
*x=image->taille.x;
*y=image->taille.y;
}



/****************************************************************************/
int TesteFenetre(Image im1, Image im2)
/****************************************************************************/

{
if (im1==NULL) return(1);
if (im2==NULL) return(1);

if (im1->fenetre.taille.x!=im2->fenetre.taille.x) return(1);
if (im1->fenetre.taille.y!=im2->fenetre.taille.y) return(1);
return(0);
}



/****************************************************************************/
int   EcritNom(Image image, char *nom)
/****************************************************************************/

{
if (nom!=NULL)
	{
	free(image->nom);
	if ( (image->nom=strdup(nom))==NULL) return(1);
	}
return(0);
}


/****************************************************************************/
int   EcritCommentaire(Image image, char *commentaire)
/****************************************************************************/

{
if (commentaire!=NULL)
	{
	free(image->commentaire);
	if ( (image->commentaire=strdup(commentaire))==NULL) return(1);
	}
return(0);
}


/****************************************************************************/
int   EcritLut(Image image, Entier taille, Couleur *table)
/****************************************************************************/

{
if ((table!=NULL)&&(taille>0))
	{
	free(image->lut);
	if ( (image->lut=(Lut *)malloc(sizeof(Lut)+taille*sizeof(Couleur)))==NULL) return(1);
	image->lut->taille=taille;
	memcpy(image->lut->table,table,taille*sizeof(Couleur));
	}
return(0);
}


/* Manipulation des listes d'images */


/****************************************************************************/
Image  InsereImageL(Image *imListe, Image image, int index)
/****************************************************************************/

{
Image element,retour;
int i;

if (image==NULL) return(NULL);
if (image->suivant!=NULL) return(NULL);
retour=NULL;

if (index==0)
	{
	image->suivant=*imListe;
	*imListe=image;
    retour=image;
	}
else
	{
	element=*imListe;
	for (i=0;i<index-1;i++)
		{
		if (element!=NULL) element=element->suivant;
		else break;
		}

	if (element!=NULL)
		{
		image->suivant=element->suivant;
	    element->suivant=image;
		retour=image;
		}
    }

return(retour);
}


/****************************************************************************/
Image  SupprimeImageL(Image *imListe,int index)
/****************************************************************************/

{
Image element,image;
int i;

if (*imListe==NULL) return(NULL);
image=NULL;

if (index==0)
	{
	image=*imListe;
	*imListe=image->suivant;
    image->suivant=NULL;
	}
else
    {
	element=*imListe;
	for (i=0;i<index-1;i++)
		{
		if (element!=NULL) element=element->suivant;
		else break;
		}
	if (element!=NULL)
		if (element->suivant!=NULL)
			{
			image=element->suivant;
			element->suivant=image->suivant;
	        image->suivant=NULL;
			}
    }
return(image);
}



/****************************************************************************/
Image   LitImageL(Image imListe,int index)
/****************************************************************************/

{
Image element;
int i;

element=imListe;

for (i=0;i<index;i++)
	{
	if (element!=NULL) element=element->suivant;
	else break;
	}

return(element);
}


/****************************************************************************/
int   CompteImageL(Image imListe)
/****************************************************************************/

{
Image element;
int n;

element=imListe;
n=0;

while(element!=NULL)
	{
	element=element->suivant;
	n++;
	}
return(n);
}


/* Manipulation des listes de fenetres */


/****************************************************************************/
FenetreL CreeFenetreL(int ox, int oy, int tx, int ty)
/****************************************************************************/

{
FenetreL fenetre;

if ((fenetre=(FenetreL)calloc(1,sizeof(Fenetre)))==NULL) return(NULL);
fenetre->origine.x=ox;
fenetre->origine.y=oy;
fenetre->taille.x=tx;
fenetre->taille.y=ty;
fenetre->suivant=NULL;

return(fenetre);
}


/****************************************************************************/
void 	 LibereFenetreL(FenetreL fenetre)
/****************************************************************************/

{
int nbFenetre,i;
if (fenetre==NULL) return;

nbFenetre=CompteFenetreL(fenetre);
for (i=nbFenetre-1;i>=0;i--) free(SupprimeFenetreL(&fenetre,i));

}


/****************************************************************************/
FenetreL  InsereFenetreL(FenetreL *feListe, FenetreL fenetre, int index)
/****************************************************************************/

{
FenetreL element,retour;
int i;

if (fenetre==NULL) return(NULL);
if (fenetre->suivant!=NULL) return(NULL);
retour=NULL;

if (index==0)
	{
	fenetre->suivant=*feListe;
	*feListe=fenetre;
	retour=fenetre;
	}
else
	{
	element=*feListe;
	for (i=0;i<index-1;i++)
		{
		if (element!=NULL) element=element->suivant;
		else break;
		}

	if (element!=NULL)
		{
		fenetre->suivant=element->suivant;
		element->suivant=fenetre;
		retour=fenetre;
		}
    }

return(retour);
}


/****************************************************************************/
FenetreL  SupprimeFenetreL(FenetreL *feListe,int index)
/****************************************************************************/

{
FenetreL element,fenetre;
int i;

if (*feListe==NULL) return(NULL);
fenetre=NULL;

if (index==0)
	{
	fenetre=*feListe;
	*feListe=fenetre->suivant;
	fenetre->suivant=NULL;
	}
else
    {
	element=*feListe;
	for (i=0;i<index-1;i++)
		{
		if (element!=NULL) element=element->suivant;
		else break;
		}
	if (element!=NULL)
		if (element->suivant!=NULL)
			{
			fenetre=element->suivant;
			element->suivant=fenetre->suivant;
			fenetre->suivant=NULL;
			}
	 }
return(fenetre);
}



/****************************************************************************/
FenetreL   LitFenetreL(FenetreL feListe,int index)
/****************************************************************************/

{
FenetreL element;
int i;

element=feListe;

for (i=0;i<index;i++)
	{
	if (element!=NULL) element=element->suivant;
	else break;
	}

return(element);
}


/****************************************************************************/
int   CompteFenetreL(FenetreL feListe)
/****************************************************************************/

{
FenetreL element;
int n;

element=feListe;
n=0;

while(element!=NULL)
	{
	element=element->suivant;
	n++;
	}
return(n);
}


/* Manipulation des sequences d'images */
/****************************************************************************/
Image CreeImageS(Image image,int tailleY)
/****************************************************************************/
{
if ((image=CreeImageSimple(image,T_OCTET,V_SEQUENCE,MAXNOMFICH,tailleY))==NULL) return(NULL);
return(image);
}

/****************************************************************************/
Image  InsereImageS(Image sequence, char *nomImage,int index)
/****************************************************************************/

{

int i,x,nbImage;
Octet **grille;

if (sequence==NULL)
	{if ((sequence=CreeImageS(sequence,1))==NULL) return(NULL);
	//insertion de nomImage dans nomimage(index)
	for (i=0;i<strlen(nomImage)+1;i++)
		sequence->donnee.octet[0][i]=(Octet)nomImage[i];
	}
else
{
nbImage=CompteImageS(sequence);
// allocation d'une ligne supplementaire
if ( (grille=(Octet**)realloc(sequence->donnee.octet,(nbImage+1)*sizeof(Octet*)))==NULL)
	{
	LibereImage(sequence);
	return(NULL);
	}
else
	{
	sequence->donnee.octet=grille;
	}
if ( (sequence->donnee.octet[nbImage]=(Octet*)calloc(MAXNOMFICH,sizeof(Octet)))==NULL)
	{
	LibereImage(sequence);
	return(NULL);
	}
sequence->taille.y=nbImage+1;
if (index>nbImage) return (NULL);
for (i=nbImage;i>index;i--)
	{
	//on deplace nomimage(i) dans nomimage(i+1)
   int nb=strlen((char*)sequence->donnee.octet[i-1])+1;
	for (x=0;x<nb;x++) sequence->donnee.octet[i][x]=sequence->donnee.octet[i-1][x];
	}
//insertion de nomImage dans nomimage(index)
for (i=0;i<strlen(nomImage)+1;i++)
	sequence->donnee.octet[index][i]=(Octet)nomImage[i];
}
return(sequence);
}

/****************************************************************************/
Image  SupprimeImageS(Image sequence,int index)
/****************************************************************************/

{

int i,nbImage,x;
Octet **grille;

if (sequence==NULL) return(NULL);
nbImage=CompteImageS(sequence);
if (index>nbImage-1) return (NULL);
if ((grille=(Octet**)CreeGrille(sequence,Z_IMAGE))==NULL) return (NULL);
for (i=index;i<nbImage-1;i++)
	{
   //on deplace nomimage(i+1) dans nomimage(i)
   int nb=strlen((char *)sequence->donnee.octet[i-1])+1;
	for (x=0;x<nb;x++) grille[i][x]=grille[i+1][x];
	}
//desallocation de la dernière ligne
free(sequence->donnee.octet[nbImage-1]);
sequence->taille.y=sequence->taille.y-1;
LibereGrille(grille);
return(sequence);

}

/*****************************************************************************/
Image EcritImageS(Image sequence,char *nomImage,int index)
/*****************************************************************************/

{

int x;
Octet *ligne;
Canal canL;
if (index>CompteImageS(sequence)-1) return (NULL);
if ((ligne=(Octet*)calloc(MAXNOMFICH,sizeof(Octet)))==NULL) return (NULL);
if ((canL=CreeCanal(sequence,T_OCTET,B_LIGNE,Z_IMAGE))==NULL) return (NULL);
for (x=0;x<strlen(nomImage)+1;x++) ligne[x]=(unsigned char)nomImage[x];
PoseCanal(canL,0,index);
EcritCanal(canL,ligne);
LibereCanal(canL);
free(ligne);
return(sequence);

}

/****************************************************************************/
int LitImageS(Image sequence, char *nomImage,int index)
/****************************************************************************/

{

int x,nb;
Octet *ligne;
Canal canL;
if (index>CompteImageS(sequence)-1) return (1);
if ((ligne=(Octet*)calloc(MAXNOMFICH,sizeof(Octet)))==NULL) return (1);
if ((canL=CreeCanal(sequence,T_OCTET,B_LIGNE,Z_IMAGE))==NULL) return (1);
PoseCanal(canL,0,index);
LitCanal(canL,ligne);
nb=strlen((char *)ligne)+1;
for (x=0;x<nb;x++) nomImage[x]=(char)ligne[x];
LibereCanal(canL);
free(ligne);
return(0);

}


/****************************************************************************/
int   CompteImageS(Image sequence)
/****************************************************************************/

{

int x,y;

LitTailleImage(sequence,&x,&y);
return(y);

}


/****************************************************************************/
Image CreeImageVecteur2D(Image imD,int txVect,int tyVect,int txImg,int tyImg)
/****************************************************************************/
{
imD=CreeImageSimple(imD,T_VECTEUR2D,V_VECTEUR2D,txVect,tyVect);
if (imD)
  {
  free(imD->info);
  imD->info=(void *) CreeInfoVecteur2D(txImg,tyImg,1,1,128,1);
  }
return(imD);
}
