/*--------------------------------------------------------------------
 * FICHERO:  PackBits.c
 * OBJETIVO: Definir las funciones que implementan el algoritmo de
 *           compresin y expansin PackBits
 * AUTOR:    Pedro Reina
 * FECHA:    L.6.6.1994
 *------------------------------------------------------------------*/

/*--------------------------------------------------------------------
 * Ficheros de cabecera
 *------------------------------------------------------------------*/

#include "PackBits.h"

/*--------------------------------------------------------------------
 * Definicin de funciones
 *------------------------------------------------------------------*/

/*--------------------------------------------------------------------
 * FUNCION:  Pkb_Expande()
 * OBJETIVO: Expandir un conjunto de octetos
 * ENTRADAS: La direccin de memoria destino de la expansin, la
 *           direccin origen que contiene los datos que hay que expandir
 *           y la cantidad de datos que hay que expandir
 * SALIDAS:  La cantidad de datos que han resultado de la expansin
 * EJEMPLO:  Pkb_Expande (Destino, Origen, 30)
 * ALGORITMO:
 *      Mientras queden datos por expandir
 *      Si el dato, n, interpretado con signo, es positivo
 *        Copiar los siguientes n+1 datos
 *      Si es negativo y distinto de -128
 *        Copiar el siguiente dato 1-n veces
 *------------------------------------------------------------------*/
entero Pkb_Expande (Destino, Origen, Total)
octeto *Destino, *Origen;
entero  Total;
  {
  entero      i, j, k;
  signed char Valor;

  for ( i=0 , j=0 ; i<Total ;  )
    {
    Valor = Origen[i++];
    if ( Valor >= 0 )
      {
      for ( k=0 ; k<Valor+1 ; k++ )
        { Destino[j++] = Origen[i++]; }
      }
    else if ( Valor != -128 )
      {
      for ( k=0 ; k<1-Valor ; k++ )
        { Destino[j++] = Origen[i]; }
      i++;
      }
    }

  return ( j );
  }

/*--------------------------------------------------------------------
 * FUNCION:  Pkb_Comprime()
 * OBJETIVO: Comprimir un conjunto de octetos
 * ENTRADAS: La direccin de memoria destino de la compresin, la
 *           direccin origen que contiene los datos que hay que comprimir
 *           y la cantidad de datos que hay que comprimir
 * SALIDAS:  La cantidad de datos que han resultado de la compresin
 * EJEMPLO:  Pkb_Comprime (Destino, Origen, 30)
 * ALGORITMO:
 *      Cada ristra de n octetos iguales se almacena como
 *        el octeto 1-n seguido del octeto que se repite
 *      Cada ristra de n octetos que no tengan iguales
 *      dos seguidos se almacena como
 *        el octeto n-1 seguido de los octetos
 *      Cada ristra puede tener, como mximo, 128 octetos
 *------------------------------------------------------------------*/
entero Pkb_Comprime (Destino, Origen, Total)
octeto *Destino, *Origen;
entero  Total;
  {
  entero i, j, k;
  logico Repetido, Sigue;
  octeto Ultimo;

  for ( i=0 , j=0 ; i<Total ;  )
    {
    if ( i+1<Total )  { Repetido = ( Origen[i] == Origen[i+1] ); }
    else              { Repetido = NO; }

    if ( Repetido )
      {
      for ( k=i+1 ; k<Total && k-i<128 && ( Origen[i] == Origen[k] ) ; k++ )
        ;
      Destino[j++] = i-k+1;
      Destino[j++] = Origen[i];
      i = k;
      }

    else
      {
      Ultimo = Origen[i];
      Sigue = SI;
      for ( k=i+1 ; k<Total && k-i<128 && Sigue ; k++ )
        {
        if ( Ultimo == Origen[k] ) { Sigue = NO; k--; }
        else                       { Ultimo = Origen[k]; }
        }
      Destino[j++] = k-i-1;
      while ( i < k )
        { Destino[j++] = Origen[i++]; }
      }
    }

  return ( j );
  }
