/*****************************************************************************
*
*                                     gif.c
*
*   from DKBTrace (c) 1990  David Buck
*
*  Gif-format file reader.
*
*  NOTE:  Portions of this module were written by Steve Bennett and are used
*         here with his permission.
*
* This software is freely distributable. The source and/or object code may be
* copied or uploaded to communications services so long as this notice remains
* at the top of each file.  If any changes are made to the program, you must
* clearly indicate in the documentation and in the programs startup message
* who it was who made the changes. The documentation should also describe what
* those changes were. This software may not be included in whole or in
* part into any commercial package without the express written consent of the
* author.  It may, however, be included in other public domain or freely
* distributed software so long as the proper credit for the software is given.
*
* This software is provided as is without any guarantees or warranty. Although
* the author has attempted to find and correct any bugs in the software, he
* is not responsible for any damage caused by the use of the software.  The
* author is under no obligation to provide service, corrections, or upgrades
* to this package.
*
* Despite all the legal stuff above, if you do find bugs, I would like to hear
* about them.  Also, if you have any comments or questions, you may contact me
* at the following address:
*
*     David Buck
*     22C Sonnet Cres.
*     Nepean Ontario
*     Canada, K2H 8W7
*
*  I can also be reached on the following bulleton boards:
*
*     ATX              (613) 526-4141
*     OMX              (613) 731-3419
*     Mystic           (613) 731-0088 or (613) 731-6698
*
*  Fidonet:   1:163/109.9
*  Internet:  David_Buck@Carleton.CA
*
*  IBM Port by Aaron A. Collins. Aaron may be reached on the following BBS'es:
*
*     Lattice BBS                      (708) 916-1200
*     The Information Exchange BBS     (708) 945-5575
*     Stillwaters BBS                  (708) 403-2826
*
*****************************************************************************/

/*
   The following routines were borrowed freely from FRACTINT, and represent
   a generalized GIF file decoder.  This seems the best, most universal format
   for reading in Bitmapped images.  GIF is a Copyright of Compuserve, Inc.
   Swiped and converted to entirely "C" coded routines by AAC for the most
   in future portability!
*/

#include "frame.h"
#include "dkbproto.h"

static IMAGE *Current_Image;  
static int Bitmap_Line;
static FILE *Bit_File;
unsigned char *decoderline  /*  [2049] */ ;  /* write-line routines use this */

static IMAGE_COLOUR *gif_colour_map;
static int colourmap_size;

int out_line (pixels, linelen)
   unsigned char *pixels;
   int linelen;
   {
   register int x;
   register unsigned addr;

   addr = linelen * Bitmap_Line--;

   for (x = 0; x < linelen; x++) {
      Current_Image->red[addr+x] = gif_colour_map[*pixels].Red;
      Current_Image->green[addr+x] = gif_colour_map[*pixels].Green;
      Current_Image->blue[addr+x] = gif_colour_map[*pixels].Blue;
      pixels++;
      }

   return (0);
   }

#define READ_ERROR -1

int get_byte() /* get byte from file, return the next byte or an error */
   {
   register int byte;

   if ((byte = getc(Bit_File)) != EOF)
      return (byte);
   else {
      printf ("Premature end of file reading GIF image\n");
      exit (1);
      }
   return (0);  /* Keep the compiler happy */
   }

/* Main GIF file decoder.  */

void read_gif_image(Image, filename)
   IMAGE *Image;
   char *filename;
   {
   register int i, j, status;
   unsigned finished, planes;
   unsigned char buffer[16];

   status = 0;
   Current_Image = Image;

   if ((Bit_File = fopen(filename, "rb")) == NULL) {
      printf ("Cannot open GIF file %s\n", filename);
      exit(1);
      }

   /* zero out the full write-line */
   if ((decoderline = (unsigned char *) malloc (2049)) == NULL) {
      printf ("Cannot allocate space for gif decoder line\n");
      fclose (Bit_File);
      exit (1);
      }

   for (i = 0; i < 2049; i++)
      decoderline[i] = (unsigned char) 0;

   /* Get the screen description */
   for (i = 0; i < 13; i++)
      buffer[i] = (unsigned char)get_byte();

   if (strncmp(buffer,"GIF87a",3) ||          /* use updated GIF specs */
       buffer[3] < '0' || buffer[3] > '9' ||
       buffer[4] < '0' || buffer[4] > '9' ||
       buffer[5] < 'A' || buffer[5] > 'z' ) {

      printf ("Invalid GIF file format: %s\n", filename);
      fclose(Bit_File);
      exit (1);
      }

   planes = ((unsigned)buffer[10] & 0x0F) + 1;
   colourmap_size = (int)(1 << planes);
   if ((gif_colour_map = (IMAGE_COLOUR *)
         malloc (colourmap_size * sizeof (IMAGE_COLOUR))) == NULL) {
      printf ("Cannot allocate gif colour map\n");
      fclose (Bit_File);
      exit (1);
      }

   if ((buffer[10] & 0x80) == 0) {    /* color map (better be!) */
      printf ("Invalid GIF file format: %s\n", filename);
      fclose(Bit_File);
      exit (1);
      }

   for (i = 0; i < colourmap_size ; i++) {
      gif_colour_map[i].Red = (unsigned char)get_byte();
      gif_colour_map[i].Green = (unsigned char)get_byte();
      gif_colour_map[i].Blue = (unsigned char)get_byte();
      }

 /* Now display one or more GIF objects */
   finished = FALSE;
   while (!finished) {
      switch (get_byte()) {
         case ';':                /* End of the GIF dataset */
            finished = TRUE;
            status = 0;
            break;

         case '!':                /* GIF Extension Block */
            get_byte();           /* read (and ignore) the ID */
            while ((i = get_byte()) > 0) /* get data len*/
            for (j = 0; j < i; j++)
                get_byte(); /* flush data */
            break;

         case ',': /* Start of image object. get description */
            for (i = 0; i < 9; i++) {
               if ((buffer[i] = (unsigned char)get_byte()) < 0) {
                  status = -1;
                  break;
                  }
               }

            if (status < 0) {
               finished = TRUE;
               break;
               }

            Image->iwidth  = buffer[4] | (buffer[5] << 8);
            Image->iheight = buffer[6] | (buffer[7] << 8);
            Image->width = (DBL) Image->iwidth;
            Image->height = (DBL) Image->iheight;

            if (Image->iwidth > BITMAP_X_SIZE ||
                Image->iheight > BITMAP_Y_SIZE) {
               printf("\nBitmap File TOO BIG!!\n");
               fclose(Bit_File);
               exit (1);
               }

            Bitmap_Line = Image->iheight - 1;

            if (((Image->red = (unsigned char *) malloc(Image->iwidth*Image->iheight))==NULL) ||
                ((Image->green = (unsigned char *) malloc(Image->iwidth*Image->iheight))==NULL) ||
                ((Image->blue = (unsigned char *) malloc(Image->iwidth*Image->iheight))==NULL)) {
               printf ("Cannot allocate memory for picture\n");
               exit(1);
               }

          /* Setup the color palette for the image */
            status = decoder ((short) Image->iwidth); /*put bytes in Buf*/
            finished = TRUE;
            break;

         default:
            status = -1;
            finished = TRUE;
            break;
         }
      }

   free (decoderline);
   free (gif_colour_map);
   fclose(Bit_File);
   }
