/*
 * 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.
 */
/*
 * linux.c - Show images on LINUX using the GL/SVGA library.
 *
 * Author:      Raul Rivero
 *              Vicerrectorado de Estudiantes 
 *              University of Oviedo
 * Date:        Sun Dec 26 1993
 * Copyright (c) 1993, Raul Rivero
 *
 */
/*
 * History: 
 *          Strongly based on the PC/GRX viewer.
 *
 *          This program didn't support true color graphic boards 'cos
 *          I could access to these boards. So I limited to 256 colors.
 *          It's too easy, so if you can, please!, do it.
 * 
 */

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

/*
 * Look here !!!
 * =============
 *
 * This code is valid only if we have defined the iLINUX
 * macro ( read the root Makefile for more information ).
 *
 */

#ifdef iLINUX

#include <vga.h>
#include <vgagl.h>

extern LUGverbose;

show_bitmap( name, in, ditherflag )
char *name;
bitmap_hdr *in;
int ditherflag;
{
  bitmap_hdr out8;
  bitmap_hdr out24;
  bitmap_hdr *bitmap8 = in;
  bitmap_hdr *bitmap24 = in;
  register int i, r, g, b;
  register int x, y;
  register byte *ptr;
  int xinit, yinit;
  int xsize, ysize, colors;
  int mode;
  vga_modeinfo *info;
  double j;

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

  if ( getenv( "GSVGAMODE" ) == NULL ) {
    fprintf( stderr, "The GSVGAMODE enviroment variable is not define. Please, do it!\n" );
    fprintf( stderr, "\nExample:  export GSVGAMODE=G1024x768x256\n" );
    exit( 99 );
  }

  /* Initialize the library */
  vga_init();
  mode = vga_getdefaultmode();

  /* We need get the graphics limits, so ... */
  info = vga_getmodeinfo( mode );
  xsize = info->width;
  ysize = info->height;
  colors = info->colors;
  VPRINTF( stderr, "Resolution:%dx%dx%d (mode: %d)\n", 
           xsize, ysize, colors, mode );

  if ( colors > 256 ) {
    fprintf( stderr, "You have defined a %d mode colors, and it's not supported now\n." );
    fprintf( stderr, "Please, define a 256 mode colors.\n"); 
    exit( 99 );
  }

  /*
   * 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;
    }
    fprintf( stderr, "Resampling to screen ( %dx%d )\n",
             xsize, ysize); 
    fprintf( stderr, "From %dx%d to %dx%d\n", in->xsize, in->ysize,
             newx, newy );
    adjust_bitmap( in, &out24, newx, newy, 0 );
    bitmap8 = bitmap24 = &out24;
  }
	
  /*
   * Ooppppsssss !!!, only 8 planes.
   */
  if ( bitmap24->depth > 8 ) {
    if ( ditherflag ) {
      fprintf( stderr, "Dithering ...\n" );
      dither_image( bitmap24, &out8, compute_levels(colors), (double) 1.0 );
    }else{
      fprintf( stderr, "Quantizing ...\n" );
      quantize( bitmap24, &out8, colors );
    }
    bitmap8 = &out8;
    /* Now we have a quantized/dithered image, so free true color */
    freebitmap( &out24 );
    /* Reset to the init ( ==> not freebitmap routine ) */
    bitmap24 = in;
  }

  /* Ok, all do it. Lets go to show the image !. */
  vga_setmode( mode );
  gl_setcontextvga( mode );
  gl_setrgbpalette();

  /*
   * Set a null color map.
   */
  for ( i = 0; i < 256; i++ ) {
    gl_setpalettecolor( i, 0, 0, 0 );
  }

  /*
   * Dump the image to screen ( centered ).
   */
  xinit = ( xsize >> 1 ) - ( bitmap8->xsize >> 1 );
  yinit = ( ysize >> 1 ) - ( bitmap8->ysize >> 1 );
  gl_putbox( xinit, yinit, bitmap8->xsize, bitmap8->ysize, bitmap8->r );

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

  (void) getchar();

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

  /*
   * We'll release all memory not equal to the inner
   * image pointer. So...
   */
  if ( bitmap8 != in )
    freebitmap( bitmap8 );
  if ( bitmap24 != in )
    freebitmap( bitmap24 );

  /*
   * Return to the text mode.
   */
  vga_setmode( TEXT );

}

#endif  /* iLINUX */
