Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!csd4.milw.wisc.edu!nic.MR.NET!shamash!com50!pwcs!minnow!jeff From: jeff@minnow.sp.unisys.com (Jeff Sampson) Newsgroups: comp.graphics Subject: generate GIF file source code Keywords: C source code GIF Message-ID: <1310@minnow.sp.unisys.com> Date: 24 Feb 89 20:09:19 GMT Reply-To: jeff@minnow.UUCP (Jeff Sampson) Followup-To: comp.graphics Organization: Unisys Corporation - Roseville, MN Lines: 406 There were several requests for a program to create GIF pictures lately. I just finished this one and it seems to work on my files. I'm sure there are bugs, but some people sounded quite interested in source code. So if anyone is still interested... - cut here - cut here - /* This is my interpretation of the GIF compression algorithim. I first * wrote it in BASIC, because I am not a C programmer. This is my first * C program, so I don't want to here complaints about my style and the fact * that I don't use structures and my variables are all global. If you can * live with that, here is a program that works. I wrote it using Borland's * Turbo-C, but it does compile on big machines. * * This was done from an example by Bob Montgomery. Most of the variables * that are important have the same names as his example. * * Feel free to hack this up all you want. I tried to comment it to the point * where (if you have Bob Montgomery's example and the spec from * Compu-Serve) it makes sense. * * Input file format: * * I used a simple x by y array of 8 bit pixels for my input file. * This is because my Matrox PIP512a digitizer board saves pictures in * this format. Each byte is a pixel, if you use one bit or all 8 bits. * This way I didn't have to unpack different formats. You can either * hack this program to read your format or write a translator from your * format to mine. * * Palette data: * * Again, since my Matrox card uses a 256 level grey scale, that is what * my program generates. If you have your own palette, you could read the * palette data from a file. * * I have only tried this for 8 bit per pixel data. The header data and * the palette data will probably need to be changed for smaller bit sizes. * * If you are tempted to use the string functions in C to improve this, * keep in mind C uses null terminated strings. I didn't think this would * work because the data produced can contain nulls. * * Jeff Sampson - Unisys Corp. * (612)-635-7469 */ #include #define STRSIZE 256 #define TABSIZE 24000 /* If you get forced clear codes, you can make TABSIZE bigger * if your system can handle it, however turbo-c will compile * a size of 24000 from the environment. If you make it bigger, * keep in mind pointers and tree pointer tables may need to be * long ints. */ /* function declarations */ void sendbits(); void makestream(); void gif(); int tabcomp(); /* variables */ char infile[30], outfile[30], tmpchar; unsigned char strbuf[STRSIZE], table[TABSIZE]; int xsize, ysize, bits, colors, nextent, nextstr, codesize, i, code, inpchar, suffix, x, y, eofcode, clearcode, j, offset, ch, buf[256], bufpnt, prefix, nodepnt, strpnt, val, maxcode; unsigned int ltbuf[4096], eqbuf[4096], gtbuf[4096], tabcnt[4096]; FILE *iptr,*optr; main() { printf("Generic raster file to GIF compression program by Jeff Sampson.\n"); printf("\nEnter file name to convert "); scanf("%s",infile); printf("\nEnter output file name "); scanf("%s",outfile); printf("\nEnter X dimension "); scanf("%d",&xsize); printf("\nEnter Y dimension "); scanf("%d",&ysize); printf("\nEnter number of bits per pixel "); scanf("%d",&bits); printf("\n\n"); /* strcpy(infile,"jeff.mat"); strcpy(outfile,"jeff.gif"); xsize=512; ysize=480; bits=8; */ /* set up GIF variables */ colors=1 << bits; clearcode=colors; eofcode=colors + 1; codesize=bits+1; maxcode=colors << 1; /* init output buffer pointers */ offset=0; ch=0; bufpnt=0; /* open files (Note: turbo-c needs the "b" on opens to specify "binary") */ iptr=fopen(infile,"rb"); optr=fopen(outfile,"wb"); /* set up binary tree pointers */ nextent=colors+2; nextstr=1; /* start buffer at location 1, value of 0 = empty */ eqbuf[nextent]=0; /* build GIF header in output file */ fputs("GIF87a",optr); tmpchar=xsize & 255; fputc(tmpchar,optr); tmpchar=xsize >> 8; fputc(tmpchar,optr); tmpchar=ysize & 255; fputc(tmpchar,optr); tmpchar=ysize >> 8; fputc(tmpchar,optr); /* The fwrites worked on Turbo-C but didn't work on a 32 bit UNIX machine fwrite(&xsize,2,1,optr); fwrite(&ysize,2,1,optr); */ fputc(151,optr); /* some flags that worked for me */ fputc(0,optr); fputc(0,optr); /* build color table ( I just create a grey scale now, this could be loaded from a file) */ for (i=0; i> 8; fputc(tmpchar,optr); tmpchar=ysize & 255; fputc(tmpchar,optr); tmpchar=ysize >> 8; fputc(tmpchar,optr); /* fwrite(&xsize,2,1,optr); fwrite(&ysize,2,1,optr); */ fputc(0,optr); fputc(bits,optr); /* done with header */ sendbits(clearcode); /* send out clearcode*/ /* pre load first character */ inpchar=fgetc(iptr); suffix=inpchar; strbuf[0]=suffix; strpnt=1; /* read characters one at a time and do compression routine for each one */ for ( y=0; y> 1; } } /* function makestream() - add current bit to bitstream */ void makestream(num1) int num1; { /* slide this bit over to the right spot and OR it into current byte */ for (j=0; j STRSIZE ) { printf("strbuf overflow, increase STRSIZE"); exit(); } /* search string table for the entry in strbuf */ nodepnt=colors+2; /* start at beginning of table */ if (eqbuf[nodepnt] != 0 ) { /* if 0, first entry and skip table search */ val=1; while ( val != 0 ) { /* loop until found or added */ val=tabcomp(); /* compare entry in table with strbuf */ if (val < 0 ) { if ( ltbuf[nodepnt] != 0 ) /* if less than and not null entry, */ nodepnt=ltbuf[nodepnt]; /* then load new node pointer, try again */ else { ltbuf[nodepnt]=nextent; /* if less than and null entry, */ break; /* then add new entry at this point */ } } if ( val > 0 ) { if ( gtbuf[nodepnt] != 0 ) nodepnt=gtbuf[nodepnt]; else { gtbuf[nodepnt]=nextent; break; } } if ( val == 0 ) { /* if found, */ suffix=nodepnt; /* load suffix with entry number and return */ return; } } } /* add entry in strbuf to the string table - first copy strbuf to the * next spot in the table. */ for ( i=0; i 4095) { printf("normal clearcode\n"); sendbits(clearcode); codesize=bits+1; nextent=colors+2; nextstr=1; eqbuf[nextent]=0; codesize=bits+1; maxcode=colors << 1; code=colors+2; } /* Note: this is a trick to allow a small table size if running on a small * machine. If running on a large machine and you get this message, you * can increase the size of TABSIZE */ if (nextstr > (TABSIZE-1000)) { printf("forced clearcode - nextstr=%d\n",nextstr); sendbits(clearcode); codesize=bits+1; nextent=colors+2; nextstr=1; eqbuf[nextent]=0; codesize=bits+1; maxcode=colors << 1; code=colors+2; } /* When size of numbers goes beyond current output length, this adds on more * bit to the current size */ if (code > maxcode) { codesize=codesize+1; maxcode=maxcode << 1; } } /* function tabcomp() - compare entry in table with strbuf * This doesn't do a real value compare, just enough to select a spot * in the binary tree. Also notice if one entry has more bytes than another, * I consider it to be larger. * * Returns 1 - table > strbuf * 0 - table = strbuf * -1 - table < strbuf */ int tabcomp() { int temp; /* check for table entry shorter than strbuf, if so return (-1) */ if (tabcnt[nodepnt] < strpnt ) return(-1); /* check for table entry longer than strbuf, if so return (1) */ if (tabcnt[nodepnt] > strpnt ) return(1); /* now scan through and compare each byte */ for ( i=0; i strbuf[i] ) return(1); } return(0); } - cut here - cut here - Jeff Sampson UUCP: ...!pyramid!pwcs!minnow!jeff Unisys Corporation ...!amdahl!ems!minnow!jeff Phone: (612) 635-7469 CSNET: jeff@minnow.SP.Unisys.Com