Home | Gaming | Programming | Play Online | Contact | Keyword Query
Games++ Games & Game Programming

GAMES++
Games++ Home
Games++ Gaming
Games++ Programming
Beta Testing Games
Free Online Games
Hints & Cheats

BROWSER UTILITIES
E-mail This Page
Add to Favorites

SITE SEARCH

Web Games++

AFFILIATES
Cheat Codes
Trickster Wiki
Game Ratings
Gameboy Cheats
PlayStation Cheats
BlackBerry Games
Photoshop Tutorials
Illustrator Tutorials
ImageReady Tutorials

ADVERTISEMENT

ADVERTISEMENT

Displaying GIF Graphic Files In C

C/C++ Programming

By Steven H. Don

/****************************************************************************
** This support Compuserve 256 colour GIF87a and GIF89a image up to        **
** 320x200 in size.                                                        **
****************************************************************************/

//This program requires a stack of at least 19.5K!!

#include "stdio.h"

typedef
  struct GIFHeader {
    char          Signature [7];
    unsigned int  ScreenWidth, ScreenHeight;
    unsigned char Depth, Background, Zero;
  };
  struct GIFDescriptor {
    char          Separator;
    unsigned int  ImageLeft, ImageTop, ImageWidth, ImageHeight;
    unsigned char Depth;
  };

  char far *Screen = (char far *)0xA0000000L;
  //For loading from the file
  FILE                 *GIFFile;
  unsigned int         BPointer;
  unsigned char        Buffer [257];
  //GIF data is stored in blocks of a certain size
  unsigned char        BlockSize;
  //For loading the code
  unsigned char        CodeSize;
  char                 BitsIn;
  unsigned char        Temp;
  //Coordinates
  unsigned int         X, Y, tlX, tlY, brX, brY;
  //The string table
  unsigned int         Prefix [4096];
  unsigned char        Suffix [4096];

//This sets the display to VGA 320x200 in 256 colours
void VGAScreen ()
{
  asm {
    mov ax, 0x13
    int 0x10
  }
}

//This resets the display to text mode
void TextScreen ()
{
  asm {
    mov ax, 0x3
    int 0x10
  }
}

//This sets a DAC register to a specific Red Green Blue-value
void SetDAC(unsigned char DAC, unsigned char R, unsigned char G, unsigned char B)
{
  outportb (0x3C8, DAC);
  outportb (0x3C9, R);
  outportb (0x3C9, G);
  outportb (0x3C9, B);
}

//This sets one pixel on the screen
void PutPixel (unsigned int x, unsigned int y, unsigned char c)
{
  Screen [(y << 8) + (y << 6) + x] = c;
}

//Function to read from the buffer
unsigned char LoadByte ()
{
  //Read next block}
  if (BPointer == BlockSize) {
    fread (Buffer, BlockSize + 1, 1, GIFFile);
    BPointer = 0;
  }

  //Return byte
  return Buffer [BPointer++];
}

//Procedure to read the next code from the file
unsigned int ReadCode ()
{
  int           Counter;
  unsigned int  Code;

  Code = 0;
  //Read the code, bit by bit
  for (Counter = 0; Counter < CodeSize; Counter++) {
    //Maybe, a new byte needs to be loaded with a further 8 bits
    if (++BitsIn == 9) {
      Temp = LoadByte ();
      BitsIn = 1;
    }

    //Add the current bit to the code
    if (Temp & 1) Code += 1 << Counter;
    Temp >>= 1;
  }
  return Code;
}

//Procedure to draw a pixel
void NextPixel (unsigned int c)
{
  //Actually draw the pixel on screen
  PutPixel (X, Y, c & 255);

  //Move to next row, if necessary
  if (++X == brX) {
    X = tlX;
    Y++;
  }
}

//Local function to output a string. Returns the first character.
unsigned char OutString (unsigned int CurCode)
{
  unsigned int  OutCount;
  unsigned char OutCode [1024];

  //If it's a single character, output that
  if (CurCode < 256) {
    NextPixel (CurCode);
  } else {
    OutCount = 0;

    //Store the string, which ends up in reverse order
    do {
      OutCode [OutCount++] = Suffix [CurCode];
      CurCode = Prefix [CurCode];
    } while (CurCode > 255);

    //Add the last character
    OutCode [OutCount++] = CurCode;

    //Output all the string, in the correct order
    do {
      NextPixel (OutCode [--OutCount]);
    } while (OutCount);
  }
  //Return 1st character
  return CurCode;
}

//This actually loads the GIF
void LoadGIF (char *Filename)
{
  //For loading from the GIF file
  struct GIFHeader     Header;
  struct GIFDescriptor Descriptor;

  //Colour information
  unsigned char        BitsPerPixel,
                       NumOfColours;
  unsigned int         DAC;
  unsigned char        Palette [256][3];

  //For indexing the string table
  unsigned int         FirstFree, FreeCode;

  //All the code information
  unsigned char        InitCodeSize;
  unsigned int         Code, OldCode, MaxCode;

  //Special codes
  unsigned int         ClearCode, EOICode;

  //Check whether the GIF file exists, and open it
  GIFFile = fopen (Filename, "rb");
  if (GIFFile == 0) {
    TextScreen ();
    printf ("Could not open file %s", Filename);
    return;
  }

  //Read header
  fread (&Header, 6, 1, GIFFile);
  Header.Signature [6] = 0;
  fread (&Header.ScreenWidth, sizeof (Header) - 7, 1, GIFFile);

  //Check signature and terminator
  if ((strcmp (Header.Signature, "GIF87a")
    && strcmp (Header.Signature, "GIF89a"))
    || Header.Zero) {
    TextScreen ();
    printf ("Not a valid GIF file\n");
    return;
  }

  //Get amount of colours in image
  BitsPerPixel = 1 + (Header.Depth & 7);
  NumOfColours = (1 << BitsPerPixel) - 1;

  //Load global colour map
  fread (Palette, 3, (NumOfColours + 1), GIFFile);
  for (DAC = 0; DAC <= NumOfColours; DAC++)
    SetDAC (DAC, Palette [DAC][0] >> 2,
                 Palette [DAC][1] >> 2,
                 Palette [DAC][2] >> 2);

  //Load the image descriptor
  fread (&Descriptor, sizeof (Descriptor), 1, GIFFile);

  if (Descriptor.Separator != ',') {
    TextScreen ();
    printf ("Incorrect image descriptor.\n");
    return;
  }

  //Get image corner coordinates
  tlX = Descriptor.ImageLeft;
  tlY = Descriptor.ImageTop;
  brX = tlX + Descriptor.ImageWidth;
  brY = tlY + Descriptor.ImageHeight;

  //Some restrictions apply
  if (Descriptor.Depth & 128) {
    TextScreen ();
    printf ("Local colour maps not supported\n");
    return;
  }
  if (Descriptor.Depth & 64) {
    TextScreen ();
    printf ("Interlaced images not supported\n");
    return;
  }

  //Get initial code size
  fread (&CodeSize, 1, 1, GIFFile);

  //GIF data is stored in blocks, so it's necessary to know the size
  fread (&BlockSize, 1, 1, GIFFile);

  //Start loader
  BPointer = BlockSize;

  //Special codes used in the GIF spec
  ClearCode        = 1 << CodeSize;     //Code to reset
  EOICode          = ClearCode + 1;     //End of file

  //Initialize the string table
  FirstFree        = ClearCode + 2;     //Strings start here
  FreeCode         = FirstFree;         //Strings can be added here

  //Initial size of the code and its maximum value
  InitCodeSize     = ++CodeSize;
  MaxCode          = 1 << CodeSize;

  BitsIn = 8;

  //Start at top left of image
  X = Descriptor.ImageLeft;
  Y = Descriptor.ImageTop;

  do {
    //Read next code
    Code = ReadCode ();

    //If it's an End-Of-Information code, stop processing
         if (Code == EOICode) break;
    //If it's a clear code...
    else if (Code == ClearCode) {
      //Clear the string table
      FreeCode = FirstFree;

      //Set the code size to initial values
      CodeSize = InitCodeSize;
      MaxCode  = 1 << CodeSize;

      //The next code may be read
      Code = ReadCode ();
      OldCode = Code;

      //Set pixel
      NextPixel (Code);
    //Other codes
    } else {
      /*If the code is already in the string table, it's string is displayed,
      and the old string followed by the new string's first character is
      added to the string table.*/
      if (Code < FreeCode)
        Suffix [FreeCode] = OutString (Code);
      else {
      /*If it is not already in the string table, the old string followed by
      the old string's first character is added to the string table and
      displayed.*/
        Suffix [FreeCode] = OutString (OldCode);
        NextPixel (Suffix [FreeCode]);
      }

      //Finish adding to string table
      Prefix [FreeCode++] = OldCode;

      //If the code size needs to be adjusted, do so
      if (FreeCode >= MaxCode && CodeSize < 12) {
        CodeSize++;
        MaxCode <<= 1;
      }

      //The current code is now old
      OldCode = Code;
    }
  } while (Code != EOICode);

  //Close the GIF file
  fclose (GIFFile);
}

void main (int argcount, char *argvalue[])
{
  char FileName [80];

  //Check if a filename was passed as a parameter, otherwise ask for one
  if (argcount > 1) {
    strcpy (FileName, argvalue [1]);
  } else {
    printf ("Enter filename:");
    gets (FileName);
  }

  //Switch to graphics screen
  VGAScreen ();
  //Load GIF file
  LoadGIF (FileName);
  //Wait for keypress
  getch ();
  //Switch back to text mode
  TextScreen ();
}

Copyright © 1998-2007, Games++ All rights reserved. | Privacy Policy