/*
 * This software is copyrighted as noted below.  It may be freely copied,
 * modified, and redistributed, provided that the copyright notice is
 * preserved on all copies.
 *
 * There is no warranty or other guarantee of fitness for this software,
 * it is provided solely "as is".  Bug reports or fixes may be sent
 * to the author, who may or may not act on them as he desires.
 *
 * You may not include this software in a program or other software product
 * without supplying the source, or without informing the end-user that the
 * source is available for no extra charge.
 *
 * If you modify this software, you should include a notice giving the
 * name of the person performing the modification, the date of modification,
 * and the reason for such modification.
 */
/*
 * fadesec.c - fades from one sequence to another one. 
 *
 * Author:      Raul Rivero
 *              Mathematics Dept. 
 *              University of Oviedo
 * Date:        Wed Nov 20 1991
 * Copyright (c) 1991, Raul Rivero
 *
 */
/*
 * Modifications:
 *
 * --
 *
 * Author:      Raul Rivero
 *              Vicerrectorado de Estudiantes 
 *              University of Oviedo
 * Date:        Mon Dec 27 1993
 *
 *		This code was written before LUG, so it was c-h-a-n-g-e-d
 *              to use LUG. It appears works fine but be careful ( i don't
 *              have too much time to check it :-( ).
 *
 * --
 */ 

#include <lug.h>
#include <lugfnts.h>

long tam_fichero();
byte *lee_fichero();

byte *rbuf, *gbuf, *bbuf;

extern char *MY_NAME;
extern int LUGverbose;

main(argc, argv)
int argc;
char **argv;
{
  int numero;
  int ini1, ini2;

  MY_NAME = argv[0];
 
  if ( argc > 1 )
    if (!strcmp("-v", argv[1])) { 
      /*
       * Activamos la opcion 'verbose' y desplazamos los argumentos.
       */
    LUGverbose= 1;
    argc--;
    argv++;
  } 

  if (argc < 5)
    old_error(0);
  
  if ( !(ini1= atoi(argv[2])) || !(ini2= atoi(argv[4])) || 
       !(numero= atoi(argv[6])) )
    old_error(1);

  trata(argv[1], ini1, argv[3], ini2, argv[5], numero);
  VPRINTF(stdout, "\rFundido concluido.                                  \n");
  return(0);
}

/*
 * Se encarga de llamar al fundido con los fichero correspondientes y de
 * copiar los dos frames que quedan iguales.
 */
trata(nombre1, ini1, nombre2, ini2, nombre, veces)
char *nombre1, *nombre2, *nombre;
int ini1, ini2, veces;
{
  register int i;
  char aux1[80], aux2[80];
  char destino[80];
  float incremento;
  float grado;

  /*
   * Como el primer y ultimo frame son iguales ( estamos en un fundido ),
   * nos limitamos a copiarlos ( ley del minimo esfuerzo ).
   */
  VPRINTF(stdout, "Copiando frames"), fflush(stdout);
  sprintf(aux1, "%s.%d", nombre1, ini1++);
  sprintf(destino, "%s.1", nombre);
  copia(aux1, destino);    /* el primero */
  sprintf(aux2, "%s.%d", nombre2, ini2+veces-1);
  sprintf(destino, "%s.%d", nombre, veces);
  copia(aux2, destino);    /* el ultimo */
  ini2++;

  /*
   * Vamos a hacer <veces> fundidos de una pareja de imagenes. Para ello
   * utilizamos una variable que nos indicara el % de la imagen segunda
   * que debemos poner.
   */
  incremento = 1.0 / ((float) (veces-1));
  grado= incremento;

  /*
   * Ahora nos limitamos a llamar a fade para que funda dos imagenes y lo
   * almacene en otra.
   */
  for (i= 2; i< veces; i++, grado+= incremento) {
    sprintf(aux1, "%s.%d", nombre1, ini1++);
    sprintf(aux2, "%s.%d", nombre2, ini2++);
    sprintf(destino, "%s.%d", nombre, i);
    VPRINTF(stdout, "\r Paso %d: %s & %s -> %s", i, aux1, aux2, destino), fflush(stdout);
    fade(aux1, aux2, destino, grado);
  }
}

#define ASIGNA     {  rptr1= img_base.r;      \
                      gptr1= img_base.g;      \
                      bptr1= img_base.b;      \
                      rptr2= img_destino.r;   \
                      gptr2= img_destino.g;   \
                      bptr2= img_destino.b;   \
                      dif_ptr= dif; }
/*
 * Aqui esta el tomate y seria muy largo explicarlo. Si no entiendes algo
 * puedes preguntarme ( pero no opino ni de politica, ni de religion, ni
 * de deporte, ni de sexo, ni de ciencia, ni de arte. Para cualquier otro
 * tema, ya sabes, estoy disponible ).
 */
fade(nombre1, nombre2, destino, grado)
char *nombre1, *nombre2, *destino;
float grado;
{
  register int i, j;
  bitmap_hdr img_base;
  bitmap_hdr img_destino;
  byte *rptr1, *gptr1, *bptr1;
  byte *rptr2, *gptr2, *bptr2;
  byte *buffer;
  short *dif, *dif_ptr;
  long total_size;

  /* Leemos la imagen base */
  read_lug_file( nombre1, &img_base );

  /* Ahora la destino */
  read_lug_file( nombre2, &img_destino );

  if ( img_base.xsize != img_destino.xsize ||  /* deben ser iguales */
       img_base.ysize != img_destino.ysize )
    old_error(2);

  total_size= img_base.xsize * img_base.ysize;
  if ((dif= (short *) malloc(3 * total_size * sizeof(short))) == NULL)
    old_error(3);

  /*
   * Para pasar de una imagen a otra hay que ir incrementando/disminuyendo
   * sus respectivos colores, ahora vamos a calcular esos incrementos/decrementos.
   */
  ASIGNA;
  for (i= 0; i< total_size; i++) {
    *dif_ptr++ = ((short) *rptr2++ - (short) *rptr1++);
    *dif_ptr++ = ((short) *gptr2++ - (short) *gptr1++);
    *dif_ptr++ = ((short) *bptr2++ - (short) *bptr1++);
  }

  /*
   * Tenemos que escribir imagenes que vayan desde la primera animacion hasta
   * la segunda. Asi que lo que escribiremos sera la primera imagen mas
   * el incremento que corresponda por el grado de solapacion de la segunda.
   * En otras palabras ( ya, ya se que me lo agradeces ), lo que hacemos
   * es calcular que diferencia hay de la primera imagen a la segunda y
   * segun donde estemos, el grado de fundido, metemos mas o menos de
   * este incremento.
   */
  ASIGNA;
  for (j= 0; j< total_size; j++) {
    *rptr2++ = *rptr1++ + (byte)(grado * ((float) *dif_ptr++));
    *gptr2++ = *gptr1++ + (byte)(grado * ((float) *dif_ptr++));
    *bptr2++ = *bptr1++ + (byte)(grado * ((float) *dif_ptr++));
  }
  write_lug_file( destino, &img_destino );

  /*
   * Liberamos los buffers utilizados ( you are freeeee !!! ).
   */
  free(dif);
  freebitmap( &img_base );
  freebitmap( &img_destino );
}

copia(fuente, destino)
char *fuente;
char *destino;
{
  bitmap_hdr aux;

  /* Leemos, ... */
  read_lug_file( fuente, &aux );
  /* escribimos, ... */
  write_lug_file( destino, &aux );
  /* ... y ADIOS! :-) */
  freebitmap( &aux );
}

/* 
 * This program had an error subroutine but LUG has another. So, i 
 * renamed this on.
 */ 
old_error( tipo )
int tipo;
{
  VPRINTF(stdout, "\n");
  fprintf(stderr, "%s: ", MY_NAME);
  switch( tipo ) {
    case  0: fprintf(stderr, "Uso:   %s <source> <sframe> <target> <tframe> <name> <no_frames> \n\n", MY_NAME);
	     fprintf(stdout, "Crea una secuencia que es un fundido de la animacion <source>\n");
             fprintf(stdout, "a la <target>. El fundido comenzara en el frame <sframe> para la\n");
             fprintf(stdout, "primera, en <tframe> para la ultima y se realizara en <no_frames>.\n");
             fprintf(stdout, "Como resultado se obtendra una nueva animacion, de <no_frames>, y\n");
             fprintf(stdout, "llamada <name>.\n");
	     fprintf(stdout, "El formato de los ficheros es ALIAS ( 24 planos ).\n");
             break;
    case  1: fprintf(stderr, "Error en introduccion de los numeros\n");
             fprintf(stderr, "Uso:   %s <source> <sframe> <target> <tframe> <name> <no_frames> \n\n", MY_NAME);
             break;
    case  2: fprintf(stderr, "Imaganes con distinto taman~o\n");
             break;
    case  3: fprintf(stderr, "No hay memoria\n");
             break;
    case  4: fprintf(stderr, "Las imagenes deben ser de 24 bits\n");
             break;
    case  5: fprintf(stderr, "Error en apertura de ficheros\n");
             break;
    case  6: fprintf(stderr, "Error durante copia de ficheros\n");
             break;
    default: fprintf(stderr, "Error, codigo desconocido (%d)\n", tipo);
             break;
  }
  exit(tipo);
}

