/* gifview.c: (or gifstat.c) * By Chris Schoeneman * jindak@surfside.esd.sgi.com or * nujy@vax5.ccs.cornell.edu * * This program is public domain. Do with it what you will * ***************************** ***************************** * * 8/1/91 * * Modified to display stereo images using duble buffers. * * Bin Li * * AGRL, Syracuse University * * bli@sugrfx * */ #define CMAP_START 1024 #include #include #include #include typedef struct { int dx,dy; /* size */ int colors,bits,cr; /* num colors, bits/pixel, color resolution */ char gcm, /* global color map flag */ bgnd; /* background 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<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<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; 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;idx; 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,id->x+id->dx-1,y,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; y=id->y+id->dy-1; 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) { 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 *left_gif,*right_gif,*f1; int name_arg=1,map=0; int inter; char left[20]; char right[20]; /* open file */ printf("Enter name of the first gif file: "); scanf("%s",left); printf("Enter name of the second gif file: "); scanf("%s",right); printf("Enter swap intervals: "); scanf("%s",&inter); if((f1 = fopen("/dev/ttyd1","w"))==NULL) { printf("cannot open /dev/ttyd1 \n"); exit(1); } cmap=CMAP_START+(map<<8); left_gif=fopen(left,"r"); if (left_gif==NULL) { printf("can't open %s.\n",left); exit(1); } if (!mscanf(left_gif,"GIF87a")) { printf("%s not a gif file.\n",left); exit(2); } right_gif=fopen(right,"r"); if (right_gif==NULL) { printf("can't open %s.\n",right); exit(1); } if (!mscanf(right_gif,"GIF87a")) { printf("%s not a gif file.\n",right); exit(2); } /* get global info */ if (!scan_SD(left_gif,&si)) { printf("data format error.\n"); exit(3); } printf("File %s:\n resolution: %dx%d\n colors: %d\n", left,si.dx,si.dy,si.colors); if (!scan_SD(right_gif,&si)) { printf("data format error.\n"); exit(3); } printf("File %s:\n resolution: %dx%d\n colors: %d\n", right,si.dx,si.dy,si.colors); /* get global colors */ if (si.gcm) scan_CM(left_gif,si.colors,g_colors); if (si.gcm) scan_CM(right_gif,si.colors,g_colors); /* open window */ prefsize(si.dx,si.dy); maxsize(si.dx,si.dy); minsize(si.dx,si.dy); winopen(); /* setup colormap mode */ cmode(); onemap(); doublebuffer(); gconfig(); swapinterval(inter); draw_image(left_gif); swapbuffers(); draw_image(right_gif); while(!getbutton(ESCKEY)) { /* fputs("A\n",f1); /send 1 byte to the glasses/ */ swapbuffers(); } }