Here's a code snippet that will save a block of memory to disk as a
Gif compressed image.  You must provide a pointer to the block of memory
and an optional pointer to the associated color palette as a series of
256 8 bit RGB values.  If no color palette is specified then the image is
assumed to be grayscale.

That's all there is to it.

John W. Ratcliff
jratcliff@verant.com

//*******************************************************************
//** Begin SGIF.H header file.
//*******************************************************************

#ifndef SGIF_H

#define SGIF_H

class SGif
{
public:
  static int	SaveGif(const char *filename, // filename to save as.
                     int wid, // width of image
                     int hit, // height of image
                     const unsigned char *image, // image data
                     const unsigned char *pal=0);  // color palette 256 3 byte RGB tuples
                     // If no color palette assigned, then grayscale
                     // is assumed.
};

#endif


//*******************************************************************
//** Begin SGIF.CPP
//*******************************************************************


#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "sgif.h"

static void initialize(void);

static struct
{
	char name[3];
	char version[3];
	short xres, yres;
	unsigned short packed;
	char back_col_index;
	char aspect_ratio;
} gif_header;

static void write_code(unsigned short code);

static FILE *fsave;
static short clear, codebits, colors, end, length, lastentry,
	nbits, nbytes, entries, actual,
	startbits, xres, yres;
static unsigned char buffer[16384],block[266],test[100];
static unsigned short hashcode, next, str_index[5003];

int	SGif::SaveGif(const char *filename,
            int wid,
            int hit,
            const unsigned char *image,
            const unsigned char *cpal)
{
	short i, row, col, color,temp;
	unsigned short hashentry;
	unsigned char bits;
  unsigned char pal[768];

  if ( cpal ) // if color palette specified, copy it
  {
    memcpy(pal,cpal,768);
  }
  else
  {
    // Set up default grayscale color palette.
    for (int i=0; i<256; i++)
    {
      pal[i*3+0] = i;
      pal[i*3+1] = i;
      pal[i*3+2] = i;
    }
  }

	xres = (short) wid;
	yres = (short) hit;

	fsave = fopen(filename, "wb");

	if ( fsave== NULL )
	{
    return 0;
	}

	strcpy(gif_header.name,"GIF");
	strcpy(gif_header.version, "87a");

	gif_header.xres = (short) wid;
	gif_header.yres = (short) hit;
	gif_header.packed = 0xF7;
	bits = 8;
	colors = 256;


	gif_header.back_col_index = 0;
	gif_header.aspect_ratio = 0;
	fwrite(&gif_header,1,13,fsave);

	fwrite(pal,1,768,fsave);

	fputc(',',fsave);
	fputc(0,fsave);
	fputc(0,fsave);
	fputc(0,fsave);
	fputc(0,fsave);
	fwrite(&xres,1,2,fsave);
	fwrite(&yres,1,2,fsave);
	fputc(0,fsave);
	startbits = bits+1;
	clear = 1 << (startbits - 1);
	end = clear+1;
	fputc(bits,fsave);
	codebits = startbits;
	nbytes = 0;
	nbits = 0;
	for (i = 0; i < 266; i++)
		block[i] = 0;
	initialize();

	for (row = 0; row < yres; row++)
	{
		for (col = 0; col < xres; col++)
		{
			color = (short) *image++;
			test[0] = (unsigned char) ++length;
			test[length] = (unsigned char) color;
			switch(length)
			{
				case 1:
					lastentry = color;
					break;
				case 2:
					hashcode = 301 * (test[1]+1);
				default:
					hashcode *= (color + length);
					hashentry = ++hashcode % 5003;
					for( i = 0; i < 5003; i++)
					{
						hashentry = (hashentry + 1) % 5003;
						if (memcmp(&buffer[str_index[hashentry]+2],
							test,length+1)	== 0)
							break;
						if (str_index[hashentry] == 0)
							i = 5003;
					}
					if (str_index[hashentry] != 0 && length < 97)
					{
						memcpy(&lastentry,&buffer[str_index[hashentry]],2);
						break;
					}
					write_code(lastentry);
					entries++;
					if (str_index[hashentry] == 0)
					{
						temp = entries+end;
						str_index[hashentry] = next;
						memcpy(&buffer[next],&temp,2);
						memcpy(&buffer[next+2],test,length+1);
						next += length+3;
						actual++;
					}
					test[0] = 1;
					test[1] = (unsigned char) color;
					length = 1;
					lastentry = color;
					if ((entries+end) == (1<<codebits))
						codebits++;
					if ( entries + end > 4093 || actual > 3335
						|| next > 15379)
					{
						write_code(lastentry);
						initialize();
					}
			}
		}
	}
	write_code(lastentry);
	write_code(end);
	fputc(0,fsave);
	fputc(';',fsave);
	fclose(fsave);
	return(1);
}

void initialize(void)
{
	write_code(clear);
	entries = 0;
	actual = 0;
	next = 1;
	length = 0;
	codebits = startbits;
	buffer[0] = 0;
	memset(str_index,0x00,10006);
}

void write_code(unsigned short code)
{
	block[nbytes  ] |= ((code << nbits) & 0xFF);
	block[nbytes+1] |= ((code >> (8 - nbits)) & 0xFF);
	block[nbytes+2] |= (((code>>(8 - nbits)) >> 8) & 0xFF);
	nbits += codebits;

	while (nbits >= 8)
	{
		nbits -= 8;
		nbytes++;
	}

	if (nbytes < 251 && code != end) return;
	if (code == end)
	{
		while (nbits > 0)
		{
			nbits -= 8;
			nbytes++;
		}
	}
	fputc(nbytes,fsave);
	fwrite(block,nbytes,1,fsave);
	memcpy(block,&block[nbytes],5);
	memset(&block[5],0x00,260);
	nbytes = 0;
}

//*******************************************************************
//** Test application demonstrating usage of the Sgif utility
//*******************************************************************

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include "sgif.h"

void main(int argc,char **argv)
{
  // gif saving test program.
  int wid = 256;
  int hit = 256;
  unsigned char *image = new unsigned char[wid*hit];
  for (int y=0; y<hit; y++)
  {
    memset( &image[y*wid], y, wid); // build gradient
  }

  printf("Saving test1.gif\n");

  SGif::SaveGif("test1.gif",wid,hit,image);

  // now create a test color palette.
  unsigned char pal[768];
  for (int i=0; i<256; i++)
  {
    pal[i*3+0] = i; // set red component.
    pal[i*3+1] = i/2; // set green component.
    pal[i*3+2] = i/4; // set blue component.
  }

  printf("Saving test2.gif\n");

  SGif::SaveGif("test2.gif",wid,hit,image,pal);

  delete image;
}

