/*****************************************************************************
 UNIVERSIDAD DE ZARAGOZA
 DEPARTAMENTO DE INFORMATICA E INGENIERIA DE SISTEMAS
 ASIGNATURA: VISION POR COMPUTADOR
******************************************************************************
 Fichero     :  imagen.c
 Proposito   :  Funciones para manejo de imagenes
 Autor       :  J.D.Tardos & J. Neira & L.M.Cascante
 Fecha       :  16-5-97
******************************************************************************/

#include <stdio.h>
#include <math.h>
#include "imagen.h"

#define ExisteComentario(Imagen)    ((Imagen).comentario[0] != '\0')
#define VaciaComentario(Imagen)     (Imagen).comentario[0] = '\0'

/*****************************************************************************
    Funciones para leer y escribir .pgm
*****************************************************************************/

void inicializar_imagen(IMAGEN *imagen, int filas, int columnas)
{
  VaciaComentario(*imagen) ;
  FILAS(*imagen) = filas ;
  COLUMNAS(*imagen) = columnas;
}


void detecta_comentarios (FILE *f, IMAGEN *ima)
/* Cuando encuentra un caracter '#' en un fichero pgm lee el resto de la
   linea y la guarda en un campo de la imagen */
{
  int c ;

  while ( (c = getc(f) ) == (int)'#')
     fgets(COMENTARIO(*ima), 100, f) ;
  ungetc(c, f) ;
}


void lee_cabecera (FILE *f, IMAGEN *ima, int magic_number)
/* lee la cabecera de un fichero pgm o pnm */
{
  int grises, n ;
  char espacio ;

  VaciaComentario(*ima) ;
  fscanf(f, "P%d ", &n) ;  /* Intenta leer el 'magic number' */
  if ( n != magic_number ) {
    fprintf (stderr, "Error: el fichero no contiene una imagen pgm o pnm %d\n",
n) ;
    exit(1) ;
  }
  detecta_comentarios (f, ima);
  fscanf (f, "%d ", &(COLUMNAS(*ima))); /* lee la anchura */
  detecta_comentarios (f, ima);
  fscanf (f, "%d ", &(FILAS(*ima))); /* lee la altura */
  detecta_comentarios (f, ima);
  fscanf (f, "%d%c", &grises, &espacio);
  printf("Cabecera fichero: P%d %d %d %d \n" ,n,  COLUMNAS(*ima) , FILAS(*ima
), grises ) ;
}


FILE* abrir_fichero(char *fichero)
{
  FILE *fp;
  char nombre[255];

  if ((fp = fopen (fichero, "r")) == NULL) {
    strcpy (nombre, "/users2/VISION/salidas/imagenes/");
    strcat (nombre, fichero);
    if ((fp = fopen (nombre, "r")) == NULL) {
      printf ("El fichero %s no existe.\n", fichero);
      exit(1);
    }
  }
  printf("Leyendo fichero de imagen: %s \n", fichero) ;
  return fp ;
}


void leer_imagen (char *fichero, IMAGEN *ima)
/* Intenta leer un fichero de formato pgm */
{
  FILE *f;
  int i ;

  f = abrir_fichero(fichero) ;
  lee_cabecera(f, ima, 5) ;
  for (i=0; i < FILAS(*ima); i++)
    fread(&PIXEL(*ima,i,0), COLUMNAS(*ima), 1, f) ;
}

void escribir_imagen2 (FILE *f, IMAGEN *ima)
/* Intentara escribir la imagen pgm en un fichero.*/
{
  int i ;

  fprintf (f, "P5\n");
  if (ExisteComentario(*ima))
    fprintf (f, "#%s\n", (*ima).comentario);
  fprintf (f, "%d %d\n", COLUMNAS(*ima), FILAS(*ima));
  fprintf (f, "%d\n", 255 );
  for (i=0; i < FILAS(*ima); i++)
    fwrite(&PIXEL(*ima,i,0), COLUMNAS(*ima), 1, f) ;
}


void escribir_imagen (char *fichero, IMAGEN *ima)
{
  FILE *f ;

  if ((f = fopen(fichero, "w")) == NULL)
    fprintf(stderr,"No puedo escribir fichero: %s", fichero) ;
  else
    escribir_imagen2 (f, ima);
}


void ver_imagen(IMAGEN *imagen, char *comentario)
   /* Muestra la imagen en una ventana */
{
  FILE *f ;
  char comando[255];

  sprintf (comando, "display -title \"%s\" pgm:-", comentario);
  if ((f = popen(comando, "w")) == NULL)
    fprintf(stderr,"No puedo mostrar la imagen\n") ;
  else
    escribir_imagen2 (f, imagen);
}


/*****************************************************************************
    Funciones para leer y escribir imagenes en color .ppm
*****************************************************************************/

void inicializar_imagen_color(IMAGEN_COLOR imagen_color, int filas, int columnas
)
{ int i ;

  for (i = 0; i<3; i++)
    inicializar_imagen(&(imagen_color[i]), filas, columnas) ;
}


void leer_imagen_color (char *fichero, IMAGEN_COLOR imagen)
/* Intenta leer un fichero de formato pgm */
{
  FILE *f;
  int i,j ;

  f = abrir_fichero(fichero) ;
  lee_cabecera(f, &imagen[0], 6) ;
  for (i=1; i<=2; i++) {
    FILAS(imagen[i]) = FILAS(imagen[0]) ;
    COLUMNAS(imagen[i]) = COLUMNAS(imagen[0]) ;
  }
  for (i=0; i < FILAS(imagen[0]); i++) {
     for (j=0; j < COLUMNAS(imagen[0]); j++) {
        fread(&R(imagen,i,j),1,1,f) ;
        fread(&G(imagen,i,j),1,1,f) ;
        fread(&B(imagen,i,j),1,1,f) ;
     }
   }
}


void escribir_imagen_color2 (FILE *f, IMAGEN_COLOR imagen)
/* Intentara escribir la imagen pnm en un fichero.*/
{
  int i, j;

   fprintf (f, "P6\n");
   if (ExisteComentario(imagen[0]))
    fprintf (f, "#%s\n", (imagen[0]).comentario);
   fprintf (f, "%d %d\n", COLUMNAS(imagen[0]), FILAS(imagen[0]));
   fprintf (f, "%d\n", 255);
   for (i=0; i < FILAS(imagen[0]); i++) {
     for (j=0; j < COLUMNAS(imagen[0]); j++) {
        fwrite (&R(imagen,i,j),1,1,f);
        fwrite (&G(imagen,i,j),1,1,f);
        fwrite (&B(imagen,i,j),1,1,f);
     }
  }
}

void escribir_imagen_color(char *fichero, IMAGEN_COLOR imagen)
/* Intentara escribir la imagen pnm en un fichero.*/
{
  FILE *f ;

  if ((f = fopen(fichero, "w")) == NULL)
    fprintf(stderr,"No puedo escribir fichero: %s", fichero) ;
  else
    escribir_imagen_color2 (f, imagen);
}


void ver_imagen_color(IMAGEN_COLOR imagen, char *comentario)
   /* Muestra la imagen en una ventana */
{
  FILE *f ;
  char comando[255];

  sprintf (comando, "display -title \"%s\" pnm:-", comentario);
  if ((f = popen(comando, "w")) == NULL)
    fprintf(stderr,"No puedo mostrar la imagen\n") ;
  else
    escribir_imagen_color2 (f, imagen);
}



/*****************************************************************************
    Funciones para manejo de histogramas
******************************************************************************/


void reproducir_histograma (HISTOGRAMA hist, int umbral, IMAGEN *imagen)
{
  int i,j;
  double max = 0;

  inicializar_imagen (imagen, 202, GRISES+2);

  for (i = 0; i < GRISES; ++i)
  {
  if (hist[i] > 0)
      if (log10(hist[i]) > max)
         max =log10(hist[i]);
  }

  for (i = 1; i < FILAS (*imagen) - 1; i++)
     for (j = 1; j < COLUMNAS (*imagen) - 1; j++)
         if (j == umbral)
            PIXEL (*imagen,201-i,j) = 100;
         else
	    if (hist[j-1] > 0)
               PIXEL (*imagen,201-i,j) = (i >= (log10(hist[j-1])*200.0/max)? 255 : 0);
	    else 
               PIXEL (*imagen,201-i,j) = 255;

  for (i = 0; i < FILAS (*imagen); i++)
  {
      PIXEL (*imagen,i,0) = 200;
      PIXEL (*imagen,i,GRISES+1) = 200;
  }
  
  for (j = 0; j < COLUMNAS (*imagen); j++)
  {
      PIXEL (*imagen,0,j) = 200;
      PIXEL (*imagen,201,j) = 200;
  }
}


void ver_histograma (HISTOGRAMA hist, int umbral, char* comentario)
{
    IMAGEN imagen;

    reproducir_histograma (hist, umbral, &imagen);
    ver_imagen (&imagen, comentario);
}

