#include #include #include #include #include #include #include #define MAKE_ONE_GIF 2 #define GET_GLOBAL_CMAP 1 #define FIRST_ANI_GIF 3 #define NEXT_ANI_GIF 4 #define BLOKLEN 255 #define BUFLEN 1000 #define TERMIN 'T' #define LOOKUP 'L' #define SEARCH 'S' #define noOfArrays 20 /* defines the amount of memory set aside in the encoding for the * LOOKUP type nodes; for a 256 color GIF, the number of LOOKUP * nodes will be <= noOfArrays, for a 128 color GIF the number of * LOOKUP nodes will be <= 2 * noOfArrays, etc. */ #define GifPutShort(i, fout) {fputc(i&0xff, fout); fputc(i>>8, fout);} typedef struct GifTree { char typ; /* terminating, lookup, or search */ int code; /* the code to be output */ unsigned char ix; /* the color map index */ struct GifTree **node, *nxt, *alt; } GifTree; char *AddCodeToBuffer(int, short, char *); void ClearTree(int, GifTree *); int GifEncode(); unsigned int debugFlag; int UseGlobalMap=0; int GifFrameDelay=5,GifFrameLoop=1000; int chainlen = 0, maxchainlen = 0, nodecount = 0, lookuptypes = 0, nbits; short need = 8; GifTree *empty[256], GifRoot = {LOOKUP, 0, 0, empty, NULL, NULL}, *topNode, *baseNode, **nodeArray, **lastArray; extern Display *display; typedef struct { unsigned char r,g,b; } GIFCOL; GIFCOL gifcol[256]; GIFCOL gifGcol[256]; int NGlobalColors=0; set_global_map(int flag) { if(NGlobalColors==0){ /* Cant use it if it aint there */ UseGlobalMap=0; return; } UseGlobalMap=flag; } int ppmtopix(unsigned char r,unsigned char g, unsigned char b,int *n) { int i,nc=*n; if(UseGlobalMap==1){ for(i=0;i255){ printf("Too many colors \n"); return -1; } gifcol[nc].r=r; gifcol[nc].g=g; gifcol[nc].b=b; nc++; *n=nc; return nc-1; } end_ani_gif(FILE *fp) { fputc(';',fp); } add_ani_gif(Window win,FILE *fp,int count) { printf("Frame %d \n",count); if(count==0) gif_stuff(win,fp,FIRST_ANI_GIF); else gif_stuff(win,fp,NEXT_ANI_GIF); } screen_to_gif(Window win, FILE *fp) { gif_stuff(win,fp,MAKE_ONE_GIF); } get_global_colormap(Window win) { FILE *junk; gif_stuff(win,junk,GET_GLOBAL_CMAP); } local_to_global() { int i; for(i=0;i<256;i++){ gifcol[i].r=gifGcol[i].r; gifcol[i].g=gifGcol[i].g; gifcol[i].b=gifGcol[i].b; } } int use_global_map(unsigned char *pixels,unsigned char *ppm,int h, int w) { unsigned char r,g,b; int i,j,k=0,l=0; int pix,nc; for(i=0;inode = (GifTree **)malloc(256*sizeof(GifTree *)*noOfArrays)) == NULL ) return 0; lastArray = nodeArray + ( 256*noOfArrays - cc); ClearTree(cc, first); pos = AddCodeToBuffer(cc, cLength, pos); end = pixels+siz; curNode = first; while(pixels < end) { if ( curNode->node[*pixels] != NULL ) { curNode = curNode->node[*pixels]; tel++; pixels++; chainlen++; continue; } else if ( curNode->typ == SEARCH ) { newNode = curNode->nxt; while ( newNode->alt != NULL ) { if ( newNode->ix == *pixels ) break; newNode = newNode->alt; } if (newNode->ix == *pixels ) { tel++; pixels++; chainlen++; curNode = newNode; continue; } } /* ****************************************************** * If there is no more thread to follow, we create a new node. If the * current node is terminating, it will become a SEARCH node. If it is * a SEARCH node, and if we still have room, it will be converted to a * LOOKUP node. */ newNode = ++topNode; switch (curNode->typ ) { case LOOKUP: newNode->nxt = NULL; newNode->alt = NULL, curNode->node[*pixels] = newNode; break; case SEARCH: if ( nodeArray != lastArray ) { nodeArray += cc; curNode->node = nodeArray; curNode->typ = LOOKUP; curNode->node[*pixels] = newNode; curNode->node[(curNode->nxt)->ix] = curNode->nxt; lookuptypes++; newNode->nxt = NULL; newNode->alt = NULL, curNode->nxt = NULL; break; } /* otherwise do as we do with a TERMIN node */ case TERMIN: newNode->alt = curNode->nxt; newNode->nxt = NULL, curNode->nxt = newNode; curNode->typ = SEARCH; break; default: fprintf(stderr, "Silly node type: %d\n", curNode->typ); } newNode->code = next; newNode->ix = *pixels; newNode->typ = TERMIN; newNode->node = empty; nodecount++; /* * End of node creation * ****************************************************** */ if (debugFlag) { if (curNode == newNode) fprintf(stderr, "Wrong choice of node\n"); if ( curNode->typ == LOOKUP && curNode->node[*pixels] != newNode ) fprintf(stderr, "Wrong pixel coding\n"); if ( curNode->typ == TERMIN ) fprintf(stderr, "Wrong Type coding; pixel# = %d; nodecount = %d\n", tel, nodecount); } pos = AddCodeToBuffer(curNode->code, cLength, pos); if ( chainlen > maxchainlen ) maxchainlen = chainlen; chainlen = 0; if(pos-buffer>BLOKLEN) { buffer[-1] = BLOKLEN; fwrite(buffer-1, 1, BLOKLEN+1, fout); buffer[0] = buffer[BLOKLEN]; buffer[1] = buffer[BLOKLEN+1]; buffer[2] = buffer[BLOKLEN+2]; buffer[3] = buffer[BLOKLEN+3]; pos -= BLOKLEN; } curNode = first; if(next == (1<BLOKLEN) { buffer[-1] = BLOKLEN; fwrite(buffer-1, 1, BLOKLEN+1, fout); buffer[0] = buffer[BLOKLEN]; buffer[1] = buffer[BLOKLEN+1]; buffer[2] = buffer[BLOKLEN+2]; buffer[3] = buffer[BLOKLEN+3]; pos -= BLOKLEN; } next = cc+2; cLength = (depth == 1)?3:depth+1; } } pos = AddCodeToBuffer(curNode->code, cLength, pos); if(pos-buffer>BLOKLEN-3) { buffer[-1] = BLOKLEN-3; fwrite(buffer-1, 1, BLOKLEN-2, fout); buffer[0] = buffer[BLOKLEN-3]; buffer[1] = buffer[BLOKLEN-2]; buffer[2] = buffer[BLOKLEN-1]; buffer[3] = buffer[BLOKLEN]; buffer[4] = buffer[BLOKLEN+1]; pos -= BLOKLEN-3; } pos = AddCodeToBuffer(eoi, cLength, pos); pos = AddCodeToBuffer(0x0, -1, pos); buffer[-1] = pos-buffer; pos = AddCodeToBuffer(0x0,8,pos); fwrite(buffer-1, pos-buffer+1, 1, fout); free(buffer-1); free(first->node); free(baseNode); if (debugFlag) fprintf(stderr, "pixel count = %d; nodeCount = %d lookup nodes = %d\n", tel, nodecount, lookuptypes); return 1; } void ClearTree(int cc, GifTree *root) { int i; GifTree *newNode, **xx; if (debugFlag>1) fprintf(stderr, "Clear Tree cc= %d\n", cc); if (debugFlag>1) fprintf(stderr, "nodeCount = %d lookup nodes = %d\n", nodecount, lookuptypes); maxchainlen=0; lookuptypes = 1; nodecount = 0; nodeArray = root->node; xx= nodeArray; for (i = 0; i < noOfArrays; i++ ) { memmove (xx, empty, 256*sizeof(GifTree **)); xx += 256; } topNode = baseNode; for(i=0; inode[i] = newNode = ++topNode; newNode->nxt = NULL; newNode->alt = NULL; newNode->code = i; newNode->ix = i; newNode->typ = TERMIN; newNode->node = empty; nodecount++; } } char *AddCodeToBuffer(int code, short n, char *buf) { int mask; if(n<0) { if(need<8) { buf++; *buf = 0x0; } need = 8; return buf; } while(n>=need) { mask = (1<>need; n -= need; need = 8; } if(n) { mask = (1<