/*****************************************************************************
 UNIVERSIDAD DE ZARAGOZA
 DEPARTAMENTO DE INFORMATICA E INGENIERIA DE SISTEMAS
 AREA DE LENGUAJES Y SISTEMAS INFORMATICOS
******************************************************************************
******************************************************************************
 Fichero     :  rle.c
 Asignatura  :  Vision por Computador
 Fecha       :  2003-02
******************************************************************************/

/*****************************************************************************
                              F U N C I O N E S
******************************************************************************/

/*****************************************************************************/
   void inicializar_run_length ()
   /*****************************************************************************
   Inicializa la estructuda de datos para la rle.
   ******************************************************************************/
      {
      int i;
   
      for (i = 0; i < MAX_FILAS; ++i)
         {
         PRIMER_SEGMENTO(i) = NULO;
         ULTIMO_SEGMENTO(i) = NULO;
         }
   
      NFILAS = 0;
      NBLOBS = 0;
      USADOS = 0;
      NSEGMENTOS = 0;
      }

/*****************************************************************************/
   void run_length (IMAGEN *imagen)
   /*****************************************************************************
   Genera el codigo run-length en la variable rle a partir de los
   datos de la imagen BINARIA del parametro. Escribe en pantalla el numero
   total de segmentos creados.
   ******************************************************************************/
      {
      }

/*****************************************************************************/
   void descodificar_run_length (IMAGEN *imagen)
   /*****************************************************************************
   Reconstruye la imagen binaria a partir de la codificacion run-length
   almacenada en la variable rle. Es una version sencilla pero
   poco eficiente (primero pone toda la imagen a fondo y luego superpone
   los segmentos de los blobs.
   IMPORTANTE: La imagen del parametro DEBE estar previamente inicializada,
   con el numero adecuado de filas y columnas!!!!!
   ******************************************************************************/
      {
      int i, j, l, s;
   
      for (i = 0; i < FILAS (*imagen); ++i)
         for (j = 0; j < COLUMNAS (*imagen); ++j)
            PIXEL (*imagen, i, j) = FONDO;
   
      for (s = 0; s < NSEGMENTOS; ++s)
         for (l = 0, i = FILA (s), j = COLUMNA (s); l < LONGITUD (s); ++l, ++j)
             if ((0 <= i) && (i < FILAS (*imagen)) &&
                (0 <= j) && (j < COLUMNAS(*imagen)))
                PIXEL (*imagen, i, j) = OBJETO;
             else
                fprintf (stderr, "Segmento %d, fila %d, columna %d, longitud %d, \
                     queda por fuera de las dimensiones de la imagen!!!\n",
                          s, FILA(s), COLUMNA (s), LONGITUD (s));
      }

/*****************************************************************************/
   int comparar_imagenes (IMAGEN *imagen1, IMAGEN *imagen2)
   /*****************************************************************************
   Determina si las imagenes de los parametros son identicas o no.
   ******************************************************************************/
      {
      int iguales;
   
      iguales = (FILAS(*imagen1) == FILAS(*imagen2)) &&
                (COLUMNAS(*imagen1) == COLUMNAS(*imagen2));
   
      if (!iguales)
         {
         fprintf(stderr, "Las imagenes no tienen las mismas dimensiones!\n");
         return 0;
         }
   
         {
         int i, j;
      
         for (i = 0; (i < FILAS (*imagen1)) && iguales; ++i)
             for (j = 0; (j < COLUMNAS (*imagen1)) && iguales; ++j)
                 iguales = PIXEL (*imagen1, i, j) == PIXEL (*imagen2, i, j);
         }

      if (!iguales)
         {
           fprintf(stderr, "Las imagenes no son iguales!\n");
           return 0;
         }
      else   
         return iguales;
      }

/*****************************************************************************/
   void colorear (IMAGEN *imagen)
   /*****************************************************************************
   A partir del digo run-length construye una imagen  en la que los pixels
   pertenecientes a cada blob tienen un valor diferente.  La visualizacion
   de la imagen resultante (con ver_imagen) permite verificar visualmente
   que la rle haya sido hecha correctamente.
   ******************************************************************************/
      {
      int i, j, l, blob, numero = 0;
   
      for (i = 0; i < FILAS (*imagen); ++i)
         for (j = 0; j < COLUMNAS (*imagen); ++j)
            PIXEL (*imagen, i, j) = BLANCO;
   
      for (blob = 0; blob < NBLOBS; ++blob)
         {
         int seg = PRIMERO (blob);
      
         if (seg != NULO)
            {
            long f, c;
         
            numero++;
            while (seg != NULO)
               {
               for (l = 0, i = FILA (seg), j = COLUMNA (seg);
                   l < LONGITUD (seg); ++l, ++j)
                  PIXEL (*imagen, i, j) = (numero * BLANCO) / (USADOS + 1);
               seg = SIGUIENTE (seg);
               }
            }
         }
      }

/*****************************************************************************/
   int crear_segmento (int fila, int columna, int longitud)
   /*****************************************************************************
   Crea en el vector de segmentos uno actual con los datos de los parametros.
   ******************************************************************************/
      {
      int seg = NSEGMENTOS;
   
      if (seg == MAXSEGS)
         {
         fprintf (stderr,
                 "El numero maximo de segmentos, %d, ha sido utilizado.\n", MAXSEGS);
         return NULO;
         }
   
      if (DEBUG) 
         fprintf (stderr, "Creando segmento %d; fila %d, col %d, long %d.\n", seg, fila, columna, longitud);
   
      if (PRIMER_SEGMENTO(fila) == NULO)
         PRIMER_SEGMENTO(fila) = seg;
   
      ULTIMO_SEGMENTO(fila) = seg;
   
      FILA (seg) = fila;
      COLUMNA (seg) = columna;
      LONGITUD (seg) = longitud;
      COLUMNA (seg) = columna;
      LONGITUD (seg) = longitud;
      BLOB (seg) = NULO;
      SIGUIENTE (seg) = NULO;
   
      NFILAS = fila + 1;
   
      return NSEGMENTOS++;
      }

/*****************************************************************************/
   int crear_blob (int segmento)
   /*****************************************************************************
   Crea en el vector de blobs compuesto por el segmento del parametro, y
   devuelve como resultado el indice en el vector donde el blob ha sido
   creado.
   ******************************************************************************/
      {
      int blob = NBLOBS;
   
      if (blob == MAXBLOBS)
         {
         fprintf (stderr,
                 "El numero maximo de blobs, %d, ha sido utilizado.\n", MAXBLOBS);
         return NULO;
         }
   
      if (DEBUG) 
         fprintf (stderr, "Creando blob %d; usados %d.\n", blob, USADOS);
      PRIMERO (blob) = segmento;
      ULTIMO (blob) = segmento;
      SIGUIENTE (segmento) = NULO;
      BLOB (segmento) = blob;
      TAMANO(blob) = LONGITUD(segmento);
      USADOS++;
   
      return NBLOBS++;
      }

/*****************************************************************************/
   void anadir_segmento_a_blob (int blob, int segmento)
   /*****************************************************************************
   Anade al final del blob del primer parametro, el segmento del 2do parametro.
   ******************************************************************************/
      {
      if (DEBUG) 
         fprintf (stderr, "Anadiendo %d a blob %d.\n", segmento, blob);
   
      SIGUIENTE (ULTIMO (blob)) = segmento;
      SIGUIENTE (segmento) = NULO;
      ULTIMO (blob) = segmento;
      BLOB (segmento) = blob;
      TAMANO(blob) += LONGITUD(segmento);
      }

/*****************************************************************************/
   void fusionar_blobs (int blob1, int blob2)
   /*****************************************************************************
   Reetiqueta todos los segmentos del blob2 como pertenecientes al blob1 y
   luego los adiciona al final de la lista de segmentos del blob1.  El
   blob2 queda con cero segmentos.
   ******************************************************************************/
      {
      int seg;
   
      if (DEBUG) 
         fprintf (stderr, "Fusionando blobs %d y %d; usados %d.\n", blob1, blob2, USADOS);
   
   /* reetiqueto los segmentos del blob2 */
      seg= PRIMERO (blob2);
      while (seg!= NULO)
         {
         BLOB (seg) = blob1;
         seg= SIGUIENTE (seg);
         }
   
      TAMANO(blob1) += TAMANO(blob2);
   
   /* fusiono las listas */
      SIGUIENTE (ULTIMO (blob1)) = PRIMERO (blob2);
      ULTIMO (blob1) = ULTIMO (blob2);
   
   /* anulo el blob2 */
      PRIMERO (blob2) = NULO;
      ULTIMO (blob2) = NULO;
      USADOS--;
      }

 /*****************************************************************************/
   void eliminar_blobs_nulos ()
   /*****************************************************************************
   Elimina de la estructura de datos los blobs que no se utilizan (por haber
   sido fusionados con otros blobs, o eliminados por el filtro de tamano).
   ******************************************************************************/
      {
      int blob, cambios, finales;
   
      cambios = TRUE;
      while (cambios)
         {
         cambios = FALSE;
         for (blob = 1; blob < NBLOBS; ++blob)
            if ((PRIMERO(blob) != NULO) && (PRIMERO(blob-1) == NULO))
               {
               rle.blobs.blob[blob-1] = rle.blobs.blob[blob];
               PRIMERO(blob) = NULO;
               cambios = TRUE;
               }
         }
   
      finales = 0;
      for (blob = 0; blob < NBLOBS; ++blob)
         if (PRIMERO(blob) != NULO) 
            {
          /* reetiqueto los segmentos del blob */
            int seg= PRIMERO (blob);
         
            while (seg!= NULO)
               {
               BLOB (seg) = blob;
               seg = SIGUIENTE (seg);
               }
         
            finales++;
         
            if (DEBUG)
               fprintf(stderr, "Blob %d, tamano %d\n", blob, TAMANO(blob));
            }
   
      NBLOBS = finales;
      }

