8 bit gifview.c
Kevin Kuehl
krk at cs.purdue.EDU
Wed Jun 13 10:19:12 AEST 1990
Chris Schoeneman just sent me a copy of gifview.c that works for 8 bit
machines. I don't have one, so I can't test it, but here it is.
Kevin
krk at cs.purdue.edu
..!{decwrl,ucbvax,gatech}!purdue!krk
/* gifview.c
* By Chris Schoeneman
* jindak at surfside.esd.sgi.com or
* nujy at vax5.ccs.cornell.edu
*
* This program is public domain. Do with it what you will.
*/
#define CMAP_START 1024
#include <gl.h>
#include <device.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; /* 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;
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 g_colors[256][3], /* global color map */
pixel_row[4096],code_table[4096][2],
cmap; /* index of first color */
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, short *cm)
{
short *scan;
int i;
for (scan=cm,i=3*colors;i>0;i--)
*scan++=(short)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, short *cm)
{
short *scan;
int i;
for (scan=cm,i=cmap;colors>0;scan+=3,i++,colors--)
mapcolor(i,*scan,*(scan+1),*(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;
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,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)
{
short 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 read_cmap(int colors, short *cm)
{
short *scan;
int i;
for (scan=cm,i=cmap;colors>0;scan+=3,i++,colors--) {
getmcolor(i,scan,scan+1,scan+2);
}
}
void main(int argc, char **argv)
{
FILE *gif_data;
int name_arg=1,map=0,planes;
short key_status,save_map[256][3];
/* open file */
if (argc<2 || argc>3) {
printf("usage: %s [-map#] <filename>\n",argv[0]);
exit(1);
}
if (argv[1][0]=='-') {
name_arg=2;
if (isdigit(argv[1][1])) map=argv[1][1]-'0';
if (map<0 || map>7) printf("%d out of range (0-7).\n");
}
gif_data=fopen(argv[name_arg],"r");
if (gif_data==NULL) {
printf("can't open %s.\n",argv[name_arg]);
exit(1);
}
if (!mscanf(gif_data,"GIF87a")) {
printf("%s not a gif file.\n",argv[name_arg]);
exit(2);
}
/* get global info */
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[name_arg],si.dx,si.dy,si.colors);
printf("Press escape to quit.\n");
/* get global colors */
if (si.gcm) scan_CM(gif_data,si.colors,g_colors);
/* open window */
prefsize(si.dx,si.dy);
maxsize(si.dx,si.dy);
minsize(si.dx,si.dy);
winopen(argv[name_arg]);
/* setup colormap mode */
cmode();
onemap();
gconfig();
planes=getplanes();
if (planes>8) cmap=CMAP_START+(map<<8);
else cmap=0;
read_cmap(si.colors,save_map);
while (draw_image(gif_data));
fclose(gif_data);
qdevice(ESCKEY); /* escape key */
qreset();
while (qread(&key_status)!=ESCKEY);
unqdevice(ESCKEY);
install_cmap(si.colors,save_map);
}
More information about the Comp.sys.sgi
mailing list