/*
 * fade.c: show images on a PC fading from one to other.
 *
 * I don't wanna write the header so only ...
 *
 * (c) 1992, Raul Rivero
 */

#include <grx.h>
#include <mousex.h>
#include <lug/lug.h>
#include <lug/lugfnts.h>

extern int LUGverbose;
extern char *MY_NAME;

main(argc, argv)
int argc;
char **argv;
{
  register int i;
  bitmap_hdr in;
  int ditherflag = 0;

  MY_NAME = argv[0];

  /*
   * Get options ( some day I'll build a procedure ).
   */
  if ( argc > 1 ) {             /* else core on SGI */
    while ( argv[1][0] == '-' ) {
      for ( i = 1; argv[1][i]; i++ ) {
        switch ( argv[1][i] ) {
                case 'v':
                        LUGverbose++;
                        break;
                case 'd':
                        ditherflag++;
                        break;
                case '!':
                        print_copyright();
                        break;
                default :
                        usage();
                        break;
        }
      }
      argv++;
      argc--;
    }
  }

  if ( argc < 2 ) {
    usage();
  }

  while( 1 ) {
    for ( i = 1; i < argc; i++ ) {
      read_lug_file( argv[i], &in );
      show_bitmap2( argv[i], &in, ditherflag );
      freebitmap( &in );
    }
  }
}

usage()
{
  char *msg = "\n\
%s: Usage: %s [-vd!] <input_file> \n\n\
Flags:\n\
\t-v: verbose\n\
\t-d: dither instead of quantize ( if required )\n\
\t-!: hey!, what about this program ?!\n\n\
The file type is got using its suffix:\n\n\
\t* .gif\t\t\t* .hf\t\t\t* .pbm/.pgm/.ppm\n\
\t* .pcx\t\t\t* .raw\t\t\t* .rgb\n\
\t* .rla\t\t\t* .rle\t\t\t* .sgi\n\
\t* .sun\t\t\t* .tga\t\t\t* .tif/.tiff\n\
\t* .ps\t\t\t* .jpeg/.jpg\t\t* .pix (** default **)\n\n\
The Alias 'pix' format will be used by default.\n\n\
If required, the quantization method is the default process to reduce\n\
the number of colors.\n\n";

  fprintf( stderr, msg, MY_NAME, MY_NAME );
  exit( 1 );
}

print_copyright()
{
  char *msg = "\
slug ( %s ) - show several image file formats\n\n\
This program - (c) 1992, Raul Rivero\n\
LUG  library - (c) 1992, Raul Rivero && Math Dept. ( U. of Oviedo )\n\n\
This software is free and you can get a full copy of original LUG library\n\
via E-mail to rivero@pinon.ccu.uniovi.es or via anonymous ftp to \n\
ftp.uniovi.es ( /uniovi/mathdept/src ).\n\n\
The LUG library includes support for several file formats, viewers on\n\
different architectures and digital image processing.\n\n\
Supported input formats:\n\n\
\t* Pix ( Alias )  *** default ***\n\
\t* TIFF ( needs Sam Leffler's TIFF library )\n\
\t* RLE ( needs Utah Raster Toolkit library )\n\
\t* RLA ( Wavefront )\n\
\t* SGI ( internal Silicon Graphics file format )\n\
\t* Targa ( Truevision )\n\
\t* GIF ( Compuserve )\n\
\t* PCX ( ZSoft )\n\
\t* PBM/PGM/PPM\n\
\t* Postscript\n\
\t* JPEG ( needs Thomas G. Lane's JPEG library )\n";

  fprintf( stderr, msg, LUGVERSIONs );
  exit( 1 );
}

show_bitmap2( name, in, ditherflag )
char *name;
bitmap_hdr *in;
int ditherflag;
{
        static int flag = 0;
        bitmap_hdr out8;
        bitmap_hdr out24;
        bitmap_hdr *bitmap8 = in;
        bitmap_hdr *bitmap24 = in;
        register int i, r, g, b;
        register byte *ptr, *scr;
        register int y;
        int xinit, yinit;
        static int xsize, ysize;
        double j;
        MouseEvent event;
        static byte oldcmap[256][3];
        static int oldcolors;

        if ( in->magic != LUGUSED )
                error( 19 );

        if ( !flag ) {
                /*
                 * Ok, the 1st time. So we need get the physical
                 * graphics limits.
                 */
                GrSetMode( GR_default_graphics );
                xsize = GrSizeX();
                ysize = GrSizeY();
                /*
                 * Initialize the old color map buffer and the #
                 * of colors.
                 */
                bzero( oldcmap, 256*3 );
                oldcolors = 256;
                for ( i = 0, ptr = (byte *) oldcmap; i < oldcolors ; i++ ) {
                        r = j * (double)*ptr++;
                        g = j * (double)*ptr++;
                        b = j * (double)*ptr++;
                        GrSetColor( i, r, g, b );
                }
        }

        /*
         * Resample if the bitmap are greater than
         * the screen.
         */
        if ( in->xsize > xsize || in->ysize > ysize ) {
                double xfactor, yfactor;
                int newx, newy;

                /* Get the factor to adjust */  
                xfactor = ((double) xsize) / ((double) in->xsize);
                yfactor = ((double) ysize) / ((double) in->ysize);
                /* 
                 * Now, select the correct. What we need is the image
                 * inside the physical display borders, so we choose
                 * the factor which suports this.
                 */
                if ( yfactor*in->xsize > xsize ) {
                        newx = xfactor * in->xsize;
                        newy = xfactor * in->ysize;
                }else {
                        newx = yfactor * in->xsize;
                        newy = yfactor * in->ysize;
                }
                adjust_bitmap( in, &out24, newx, newy, 0 );
                bitmap24 = &out24;
        }

        /*
         * Ooppppsssss !!!, only 8 planes.
         */
        if ( bitmap24->depth > 8 ) {
                if ( ditherflag ) {
                        /*** fprintf( stderr, "Dithering ...\n" ); ***/
                        dither_image( bitmap24, &out8, 6, (double) 1.0 );
                }else{
                        /*** fprintf( stderr, "Quantizing ...\n" ); ***/
                        quantize( bitmap24, &out8, 256 );
                }
                bitmap8 = &out8;
        }else bitmap8 = bitmap24;

        /* If we are using a resample image, now we can free it */
        if ( bitmap24 == &out24 ) {
                freebitmap( &out24 );
        }


        if ( flag ) {

#ifndef NOWAIT
                /*
                 * Currently we have another image, so wait brother.
                 */
                if(MouseDetect()) {
                        /*
                         * Ok, we can use the right button from the mouse
                         * or the ESC key ( from the keyboard, or has your
                         * mouse has a ESC key ? ).
                         */
                        MouseEventMode(0);
                        /*
                         * If you are a UNIX programmer you know the events,
                         * else what a pity !.
                         */
                        for( ; ; ) {
                                MouseGetEvent( (M_KEYPRESS|M_POLL|M_RIGHT_UP|M_NOPAINT ),
                                        &event);
                                if( event.flags ) {
                                        break;
                                }
                        }
                        MouseUnInit();

                }else {
                        /*
                         * Oooopppss!, no mouse detected so only handle
                         * the keyboard.
                         */
                        getkey();
                }
#endif  /* NOWAIT */

                /*
                 * Fade out the image.
                 */
                for ( j = 1.; j >= 0. ; j -= 0.02 ) {
                        for ( i = 0, ptr = (byte *) oldcmap;
                              i < oldcolors ; i++ ) {
                                r = j * (double)*ptr++;
                                g = j * (double)*ptr++;
                                b = j * (double)*ptr++;
                                GrSetColor( i, r, g, b );
                        }
                }
                /* Reset the video buffer */
                GrClearScreen( 0 );

        }else flag++;

        /*
         * Ok, all ready. Here we go !.
         */

        /*
         * Dump the image to screen ( centered ).
         */
        xinit = ( GrSizeX() >> 1 ) - ( bitmap8->xsize >> 1 );
        yinit = ( GrSizeY() >> 1 ) - ( bitmap8->ysize >> 1 );
        ptr = bitmap8->r;
        scr = (char *) 0xd0000000 + xinit + yinit * GrSizeX();
        for ( y = 0; y < bitmap8->ysize ; y++, scr += xsize,
                                         ptr += bitmap8->xsize ) {
                bcopy( ptr, scr, bitmap8->xsize );
        }

        /*
         * Fade in the image.
         */
        for ( j = 0.; j <= 1. ; j += 0.02 ) {
                for ( i = 0, ptr = bitmap8->cmap; i < bitmap8->colors ; i++ ) {
                        r = j * (double)*ptr++;
                        g = j * (double)*ptr++;
                        b = j * (double)*ptr++;
                        GrSetColor( i, r, g, b );
                }
        }

        /*
         * Store the camp an the # of colors.
         */
        bcopy( bitmap8->cmap, oldcmap, 3 * bitmap8->colors );
        oldcolors = bitmap8->colors;

        /*
         * Free bitmap.
         */
        if ( bitmap8 == &out8 )
                freebitmap( &out8 );

        /*
         * Bye !.
         */
}
