This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

| GIF Export Submitted by

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

Download Associated File: gifsave.cpp (6,157 bytes)

    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;
    }

The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.