#include #include #include #include #include static int a_count; int curr_frame; typedef int code_int; typedef long int count_int; static long pixel_index; #define BITS 12 #define HSIZE 5003 typedef char char_type; static int n_bits; static int maxbits = BITS; static code_int maxcode; static code_int maxmaxcode = (code_int)1 << BITS; # define MAXCODE(n_bits) (((code_int) 1 << (n_bits)) - 1) static count_int htab [HSIZE]; static unsigned short codetab [HSIZE]; #define HashTabOf(i) htab[i] #define CodeTabOf(i) codetab[i] static code_int hsize = HSIZE; #define tab_prefixof(i) CodeTabOf(i) #define tab_suffixof(i) ((char_type*)(htab))[i] #define de_stack ((char_type*)&tab_suffixof((code_int)1< 0 ) { fputc( a_count, stdout ); fwrite( accum, 1, a_count, stdout ); a_count = 0; } } static void char_init() { a_count = 0; } static void char_out( c ) int c; { accum[ a_count++ ] = c; if( a_count >= 254 ) flush_char(); } void output( code ) code_int code; { cur_accum &= masks[ cur_bits ]; if( cur_bits > 0 ) cur_accum |= ((long)code << cur_bits); else cur_accum = code; cur_bits += n_bits; while( cur_bits >= 8 ) { char_out( (unsigned int)(cur_accum & 0xff) ); cur_accum >>= 8; cur_bits -= 8; } if ( free_ent > maxcode || clear_flg ) { if( clear_flg ) { maxcode = MAXCODE (n_bits = g_init_bits); clear_flg = 0; } else { ++n_bits; if ( n_bits == maxbits ) maxcode = maxmaxcode; else maxcode = MAXCODE(n_bits); } } if( code == EOFCode ) { while( cur_bits > 0 ) { char_out( (unsigned int)(cur_accum & 0xff) ); cur_accum >>= 8; cur_bits -= 8; } flush_char(); fflush( stdout ); } } static void cl_hash(hsize) /* reset code table */ register count_int hsize; { register count_int *htab_p = htab+hsize; register long i; register long m1 = -1; i = hsize - 16; do { /* might use Sys V memset(3) here */ *(htab_p-16) = m1; *(htab_p-15) = m1; *(htab_p-12) = m1; *(htab_p-13) = m1; *(htab_p-12) = m1; *(htab_p-11) = m1; *(htab_p-10) = m1; *(htab_p-9) = m1; *(htab_p-8) = m1; *(htab_p-7) = m1; *(htab_p-6) = m1; *(htab_p-5) = m1; *(htab_p-4) = m1; *(htab_p-3) = m1; *(htab_p-2) = m1; *(htab_p-1) = m1; htab_p -= 16; } while ((i -= 16) >= 0); for ( i += 16; i > 0; --i ) *--htab_p = m1; } static void cl_block () /* table clear for block compress */ { cl_hash ( (count_int) hsize ); free_ent = ClearCode + 2; clear_flg = 1; output( (code_int)ClearCode ); } static void compress(init_bits ) int init_bits; { register long fcode; register code_int i /* = 0 */; register int c; register code_int ent; register code_int disp; register code_int hsize_reg; register int hshift; long int q; long int m; m = -1; for(q = 0; q < HSIZE; q++) { htab[q] = m; codetab[q] = 0; } in_count = 1; out_count = 0; cur_bits = 0; cur_accum = 0; sprintf(accum,""); pixel_index = -1; g_init_bits = init_bits; offset = 0; out_count = 0; clear_flg = 0; in_count = 1; maxcode = MAXCODE(n_bits = g_init_bits); ClearCode = (1 << (init_bits - 1)); EOFCode = ClearCode + 1; free_ent = ClearCode + 2; char_init(); cl_block(); ent = GIFNextPixel(); hshift = 0; for ( fcode = (long) hsize; fcode < 65536L; fcode *= 2L ) ++hshift; hshift = 8 - hshift; /* set hash code range bound */ hsize_reg = hsize; cl_hash( (count_int)hsize_reg); /* clear hash table */ output( (code_int)ClearCode ); while ( (c = GIFNextPixel()) != EOF ) { ++in_count; fcode = (long) (((long) c << maxbits) + ent); i = (((code_int)c << hshift) ^ ent); /* xor hashing */ if ( HashTabOf (i) == fcode ) { ent = CodeTabOf (i); continue; } else if ( (long)HashTabOf (i) < 0 ) /* empty slot */ goto nomatch; disp = hsize_reg - i; /* secondary hash (after G. Knott) */ if ( i == 0 ) disp = 1; probe: if ( (i -= disp) < 0 ) i += hsize_reg; if ( HashTabOf (i) == fcode ) { ent = CodeTabOf (i); continue; } if ( (long)HashTabOf (i) > 0 ) goto probe; nomatch: output ( (code_int) ent ); ++out_count; ent = c; if ( free_ent < maxmaxcode ) { CodeTabOf (i) = free_ent++; /* code -> hashtable */ HashTabOf (i) = fcode; } else cl_block(); } /* * Put out the final code. */ output( (code_int)ent ); ++out_count; output( (code_int)EOFCode ); } main(argc,argv) int argc; char *argv[]; { static char count[10] = "0"; static char dchar[1] = ""; long i; long x; int y; int q; int mon; int row; int col; int colors[24] = {0,255,255,222,189,0,204,150,0,181,123,0,110,46,0,159,81,0,165,99,0,253,243,0}; if(getenv("PATH_INFO") != NULL) { strcpy(s,getenv("PATH_INFO")+1); } else { strcpy(s,argv[1]); } if(getenv("PATH_INFO") != NULL) printf("Content-type: image/gif\n\n"); framewidth = strlen(count)*18; offset = (108 - framewidth)/2; putc(0x47,stdout); /* G */ putc(0x49,stdout); /* I */ putc(0x46,stdout); /* F */ putc(0x38,stdout); /* 8 */ putc(0x39,stdout); /* 9 */ putc(0x61,stdout); /* a */ putc(108,stdout); putc(0,stdout); /* width */ putc(0x19,stdout); putc(0,stdout); /* height */ putc(0xAA,stdout); /* global block */ putc(0x00,stdout); /* background color */ putc(0x00,stdout); /* pixel aspect */ for(i = 0;i < 24;i++) { putc(colors[i],stdout); } /* color table */ putc(0x21,stdout); /* extension block */ putc(0xF9,stdout); /* graphic control extension */ putc(0x04,stdout); /* block size (fixed) */ putc(0x05,stdout); /* flags */ putc(0x04,stdout); putc(0x0,stdout); /* delay */ putc(0x00,stdout); /* transparent color */ putc(0x00,stdout); /* block terminator */ putc(0x21,stdout); /* extension block */ putc(0xFF,stdout); /* special purpose */ putc(0x0B,stdout); /* block size */ putc(0x4E,stdout); /* application identifier */ putc(0x45,stdout); putc(0x54,stdout); putc(0x53,stdout); putc(0x43,stdout); putc(0x41,stdout); putc(0x50,stdout); putc(0x45,stdout); putc(0x32,stdout); putc(0x2E,stdout); putc(0x30,stdout); putc(0x03,stdout); putc(0x01,stdout); putc(0x0F,stdout); putc(0x27,stdout); putc(0x00,stdout); /* terminator */ putc(0x2C,stdout); /* image seperator */ putc(offset,stdout); /* x offset */ putc(0x00,stdout); putc(0x00,stdout); /* y offset */ putc(0x00,stdout); putc(framewidth,stdout); /* width */ putc(0x00,stdout); putc(0x19,stdout); /* height */ putc(0x00,stdout); putc(0x02,stdout); /* local table, etc */ x = 0; mon = 0; for(row = 0; row < 25; row++) { for(i = 0; i < strlen(count); i++) { sprintf(dchar,"%c",count[i]); y = atoi(dchar); for(col = 0; col < 18; col++) { framebuff[mon++] = frames[y][col + row*18 + x*18]; } } } /* output compressed frame 1 */ putc(3,stdout); compress(4); putc(0x00,stdout); /* terminator */ x = 25; mon = 0; for(row = 0; row < 25; row++) { for(i = 0; i < strlen(count); i++) { sprintf(dchar,"%c",count[i]); y = atoi(dchar); for(col = 0; col < 18; col++) { if(frames[y][col + row*18 + x*18] == frames[y][col + row*18 + (x-25)*18]) { framebuff[mon++] = 0; } else { framebuff[mon++] = frames[y][col + row*18 + x*18]; } } } } putc(0x21,stdout); /* extension block */ putc(0xF9,stdout); /* graphic control extension */ putc(0x04,stdout); /* block size (fixed) */ putc(0x09,stdout); /* flags */ putc(0x04,stdout); putc(0x0,stdout); /* delay */ putc(0x00,stdout); /* transparent color */ putc(0x00,stdout); /* block terminator */ putc(0x2C,stdout); /* image seperator */ putc((108 - framewidth)/2,stdout); /* x offset */ putc(0x00,stdout); putc(0x00,stdout); /* y offset */ putc(0x00,stdout); putc(framewidth,stdout); /* width */ putc(0x00,stdout); putc(0x19,stdout); /* height */ putc(0x00,stdout); putc(0x82,stdout); /* local table, etc */ for(mon = 0;mon < 24;mon++) { putc(colors[mon],stdout); } /* color table */ /* output compressed frame */ putc(3,stdout); compress(4); putc(0x00,stdout); /* terminator */ putc(0x3B,stdout); /* end of GIF */ exit(0); }