root@sgzh.uu.ch (0000-Bruno Pape(0000)) (01/18/91)
Hello gif types, Here is a gif file management and demo tool. It flips through the gif files specified on the command line. "auto8 /usr/people/bruno/gif/*.gif". It is a quick hack of a gifview8 posted some time ago. I also have a 24 bit rgb version of the same. If anyone has a more sophisticated gif viewer with the same feature I would be interested. Happy giffing, Bruno --------------------------------------------------------------------------- #define CMAP_START 1024 #include <gl.h> #include <stdio.h> typedef struct { int dx,dy; /* size */ int colors,bits,cr; /* num colors, bits/pixel, color resolution */ char gcm, /* global color map flag */ bgnd; /* backgr ound color */ } screen_dscrp; typedef struct { int x,y,dx,dy, /* position, size */ colors,bits; /* num colors, bits/pixel */ char gcm,order; /* use global cm, seq. or interlaced */ } image_dscrp; char g_colors[256][3]; /* Global color map */ int bits_left,byte_count, /* bits in last_char, bytes left */ mask[14]={0,1,3,7,0xf,0x1f,0x3f,0x7f,0xff, 0x1ff,0x3ff,0x7ff,0xfff,0x1fff}, code_size,countsize,countdown, dy_table[4]={8,8,4,2},offset_table[4]={0,4,2,1}, last_char,bit_mask,least_bits; short pixel_row[4096],code_table[4096][2],cmap; FILE *stream_source; /* file for input */ screen_dscrp si; /* global screen descriptor */ /***************************************************** * Input routines * *****************************************************/ int mscanf(FILE *infile, char *parse) { char *scan; int dx,dy; for (scan=parse;*scan;scan++) if (getc(infile)!=(int)*scan) return(0); return(!0); } /* read Screen Descriptor */ int scan_SD(FILE *infile, screen_dscrp *sd) { char data; data=(char)getc(infile); sd->dx=data+((char)getc(infile)<<8); data=(char)getc(infile); sd->dy=data+((char)getc(infile)<<8); data=getc(infile); if (data&8) return(0); sd->gcm=data&0x80; sd->cr=(data&0x70)>>4; sd->bits=(data&7)+1; sd->colors=1<<sd->bits; sd->bgnd=getc(infile); if (getc(infile)!=0) return(0); return(!0); } /* skip past an extension block */ void skip_EB(FILE *infile) { int count,garbage[256]; getc(infile); /* get function */ while (count=getc(infile)) fread(garbage,1,count,infile); } /* read Image Descriptor */ int scan_ID(FILE *infile, image_dscrp *id) { char data; /* wait for ',' or ';' or '!' EOF */ do { data=(char)getc(infile); if (data==';') return(1); if (feof(infile)) return(0); if (data==0x21) skip_EB(infile); } while (data!=0x2c); data=(char)getc(infile); id->x=data+((char)getc(infile)<<8); data=(char)getc(infile); id->y=data+((char)getc(infile)<<8); data=(char)getc(infile); id->dx=data+((char)getc(infile)<<8); data=(char)getc(infile); id->dy=data+((char)getc(infile)<<8); data=(char)getc(infile); id->gcm=data&0x80; id->order=data&0x40; id->bits=(data&7)+1; id->colors=1<<id->bits; return(2); } /* read Color Map */ void scan_CM(FILE *infile, int colors, char *cm) { char *scan; int i; for (scan=cm,i=3*colors;i>0;i--) *scan++=(char)getc(infile); } /* reset code stuff */ void reset_codes(void) { code_size=least_bits+1; if (code_size<=2) code_size=3; countsize=1<<code_size; countdown=countsize-(1<<least_bits)-2; bit_mask=(long)mask[code_size]; } /* clear bitstream */ void clear_stream(FILE *infile, int bits) { getc(infile); /* skip minimum bit size */ byte_count=0; last_char=0; bits_left=0; least_bits=bits; stream_source=infile; reset_codes(); } /* read next code and adjust code width */ short get_code(void) { static char flag=0; short code; int new; if (byte_count==0) byte_count=getc(stream_source); if (bits_left<code_size) { new=(int)getc(stream_source); byte_count--; if (bits_left+8<code_size) { if (byte_count==0) byte_count=getc(stream_source); byte_count--; new|=((int)getc(stream_source)<<8); code=16; } else code=8; if (bits_left) new<<=bits_left; last_char|=new; bits_left+=code; } code=(short)(last_char&bit_mask); last_char>>=code_size; bits_left-=code_size; if (flag) { flag=0; reset_codes(); } else if (--countdown==0) { countdown=countsize; countsize<<=1; if (++code_size==13) { flag=1; code_size--; } else bit_mask=(int)mask[code_size]; } return(code); } /***************************************************** * Other routines * *****************************************************/ void install_cmap(int colors, char *cm) { char *scan; int i; for (scan=cm,i=cmap;colors>0;scan+=3,i++,colors--) mapcolor(i,(short)*scan,(short)*(scan+1),(short)*(scan+2)); } void setup_codes(int colors) { int i; for (i=0;i<colors;i++) code_table[i][0]=code_table[i][1]=i; } void read_interlaced(image_dscrp *id) { int table_ptr,row_count,dy,y,pass,end_code,clear_code; short prefix,suffix,save,stack[4096],*stack_ptr,*pixel=pixel_row; int yo = ( ( YMAXSCREEN - si.dy ) / 2 ); id->x += ( ( XMAXSCREEN - si.dx ) / 2 ); row_count=id->dx; clear_code=id->colors; end_code=clear_code+1; while ((prefix=get_code())==clear_code); reset_codes(); table_ptr=clear_code+2; for (pass=0;pass<4;pass++) { y=id->y+id->dy-1-offset_table[pass]; dy=dy_table[pass]; while (y>=0 && (save=suffix=get_code())!=end_code) { if (suffix==clear_code) { reset_codes(); while ((save=get_code())==clear_code); reset_codes(); table_ptr=clear_code+1; } else { code_table[table_ptr][0]=prefix; if (suffix==table_ptr) code_table[table_ptr][1]=code_table[prefix][1]; else { while (suffix>=id->colors) suffix=code_table[suffix][0]; code_table[table_ptr][1]=suffix; } } suffix=1; stack_ptr=stack; while (prefix>=id->colors) { *stack_ptr++=code_table[prefix][1]; prefix=code_table[prefix][0]; suffix++; } *stack_ptr=prefix; for (;suffix>0;stack_ptr--,suffix--) { *pixel++ = cmap+*stack_ptr; if (--row_count==0) { row_count=id->dx; pixel=pixel_row; rectwrite(id->x,y+yo,id->x+id->dx-1,y+yo,pixel_row); y-=dy; } } table_ptr++; prefix=save; } } } void read_sequential(image_dscrp *id) { int table_ptr,row_count,y,end_code,clear_code; short *pixel=pixel_row,prefix,suffix,save,stack[4096],*stack_ptr; id->x += ( ( XMAXSCREEN - si.dx ) / 2 ); y = id->y + id->dy - 1 + ( ( YMAXSCREEN - si.dy ) / 2 ); row_count=id->dx; clear_code=id->colors; end_code=clear_code+1; while ((prefix=get_code())==clear_code); reset_codes(); table_ptr=clear_code+2; while ((save=suffix=get_code())!=end_code) { if (suffix==clear_code) { reset_codes(); while ((save=get_code())==clear_code); reset_codes(); table_ptr=clear_code+1; } else { code_table[table_ptr][0]=prefix; if (suffix==table_ptr) code_table[table_ptr][1]=code_table[prefix][1]; else { while (suffix>=id->colors) suffix=code_table[suffix][0]; code_table[table_ptr][1]=suffix; } } suffix=1; stack_ptr=stack; while (prefix>=id->colors) { *stack_ptr++=code_table[prefix][1]; prefix=code_table[prefix][0]; suffix++; } *stack_ptr=prefix; for (;suffix>0;stack_ptr--,suffix--) { *pixel++ = cmap+*stack_ptr; if (--row_count==0) { row_count=id->dx; pixel=pixel_row; rectwrite(id->x,y,id->x+id->dx-1,y,pixel_row); y--; } } table_ptr++; prefix=save; } } int draw_image(FILE *infile) { char lcm[256][3]; int flag; image_dscrp id; /* get image descriptor and setup colors */ flag=scan_ID(infile,&id); if (flag==0) { printf("unexpected eof.\n"); exit(3); } if (flag==1) return(0); if (id.gcm) { scan_CM(infile,id.colors,lcm); install_cmap(id.colors,lcm); } else { install_cmap(si.colors,g_colors); id.colors=si.colors; id.bits=si.bits; } /* draw image */ if (id.bits==1) { /* Need extra bit for 2 color pic. */ id.bits=2; id.colors=4; } clear_stream(infile,id.bits); setup_codes(id.colors); color(si.bgnd+CMAP_START); clear(); if (id.order) read_interlaced(&id); else read_sequential(&id); return(!0); } void main(int argc, char **argv) { FILE *gif_data; int i, map = 0; if ( argc < 2 ) { printf("usage: %s <filenames>\n",argv[0]); exit(1); } prefposition( 0, XMAXSCREEN, 0, YMAXSCREEN ); winopen( argv[0] ); cmode(); onemap(); doublebuffer(); gconfig(); for ( i = 1; i < argc; i++ ) { if ( map == 1 ) map = 0; else map = 1; cmap = CMAP_START + ( map << 8 ); if ( ( gif_data = fopen(argv[i],"r") ) == NULL ) { printf("can't open %s.\n",argv[i]); exit(1); } if ( !mscanf(gif_data,"GIF87a") ) { printf("%s not a gif file.\n",argv[i]); exit(2); } if (!scan_SD(gif_data,&si)) { printf("data format error.\n"); exit(3); } printf("File %s:\n resolution: %dx%d\n colors: %d\n", argv[i],si.dx,si.dy,si.colors); if (si.gcm) scan_CM(gif_data,si.colors,g_colors); pushmatrix(); while (draw_image(gif_data)); swapbuffers(); popmatrix(); fclose(gif_data); } sginap( 100 ); } ---------------------------------------------------------------------------