nakada@husc8.HARVARD.EDU (Paul Nakada) (07/30/88)
# this is a Gif picture viewer for the Sun 3 computer .. It may work on others, # butit hasn't been tested on anything besides a Sun 3/60. The code here works # ok, but it needs some help with the unix interface. I am but a novice # programmer, so please feel free to delve into it. This program in it's original # incarnation was written by scott hemphill .. it was then converted to create a # sun raster file. I hope somebody finds this useful... # paul nakada # nakada@husc4.harvard.edu # nakada@husc4.bitnet # nakada@husc4.uucp # #----------------------------<cut here, save, and sh <filename> >---------- # -------- Makefile -------- echo extracting file Makefile cat << '#*\\\THE_END//////*#' > Makefile CFILES = main.c error.c headers.c raster.c OBJECTS = main.o error.o headers.o raster.o PRINT = main.c error.c headers.c raster.c CMD = vg DESTIN = . CFLAGS = -O $(DEFS) DEFS = LIBS = -lsuntool -lsunwindow -lpixrect $(CMD) : $(OBJECTS) /lib/libc.a /usr/lib/libsuntool.a /usr/lib/libsunwindow.a /usr/lib/libpixrect.a ld /lib/crt0.o $(OBJECTS) -o $(CMD) $(LIBS) -lc depend : @makedepend $(CFILES) clean : -rm $(OBJECTS) $(CMD) print : print -h $(PRINT) lint : lint $(CFILES) #*\\\THE_END//////*# # -------- error.c -------- echo extracting file error.c cat << '#*\\\THE_END//////*#' > error.c #include <stdio.h> #include "viewgif.h" void usage() { fprintf(stderr, "usage: %s [file ... ]\n", progname); exit(1); } void fatal(s) char *s; { fprintf(stderr,"%s: %s\n",progname, s); exit(-1); } #*\\\THE_END//////*# # -------- headers.c -------- echo extracting file headers.c cat << '#*\\\THE_END//////*#' > headers.c #include <stdio.h> #include <ctype.h> #include <suntool/sunview.h> #include <suntool/canvas.h> #include "viewgif.h" #include "sunvgif.h" void checksignature() { char buf[6]; fread(buf, 1, 6, infile); if (strncmp(buf,"GIF",3)) fatal ("file is not a GIF file"); if (strncmp(&buf[3],"87a",3)) fatal("unknown GIF version number"); } void readscreen() { unsigned char buf[7]; xx=yy=0; fread(buf,1,7,infile); screenwidth=buf[0] + (buf[1] << 8); screenheight = buf[2] + (buf[3] << 8); global = buf[4] & 0x80; if (global) { globalbits = (buf[4] & 0x07) + 1; fread(globalmap,3,1 << globalbits,infile); } } void initcolors(colortable, colormap,ncolors) char colortable[256][3]; unsigned char colormap[256][3]; int ncolors; { register unsigned color; register i; for (i=0; i < ncolors; i++) { red[i] = colormap[i][0]; green[i] = colormap[i][1]; blue[i] = colormap[i][2]; } pw_setcmsname(pw, filename); pw_putcolormap(pw, 0, ncolors, red, green, blue); } #*\\\THE_END//////*# # -------- main.c -------- echo extracting file main.c cat << '#*\\\THE_END//////*#' > main.c #include <stdio.h> #include <ctype.h> #include <suntool/sunview.h> #include <suntool/canvas.h> #include "viewgif.h" #include "sunvgif.h" void main(argc, argv) int argc; char *argv[]; { extern int optinf, opterr; int i; bool used_stdin = FALSE; opterr = 1; scale = 2; progname=argv[0]; argc--; argv++; if (argv[0][0]=='-') if (argv[0][1] >='1' && argv[0][1]<='4') { scale=argv[0][1]-'0'; argc--; argv++; } for (i=0; i<argc; i++) { if (strcmp(argv[i],"-") == 0) { if (used_stdin) { fprintf(stderr,"standard input used twice\n"); exit(1); } else { used_stdin=TRUE; } } #ifdef unix else if (access(argv[i],4) == -1) { fprintf(stderr, "%s: cannot access %s: ",progname, argv[i]); perror(""); exit(1); } #endif unix } infile=stdin; filename="stdin"; i=0; do { if (argc > 0) { infile = fopen(argv[i],"r"); filename=argv[i]; } do_prog(); (void) fclose(infile); } while (++i < argc); exit(0); } void draw_loop() { int quit = FALSE; char ch; do { ch = getc(infile); switch (ch) { case '\0': break; /* this kludge for non-standard files */ case ',': readimage(); break; case ';': quit = TRUE; (void) notify_set_itimer_func(frame,draw_loop, ITIMER_REAL,((struct itimerval *) 0), ((struct itimerval *) 0)); break; case '!': readextension(); break; default: fatal("illegal GIF block type"); fprintf(stderr,ch); break; } } while (!quit); } void do_prog() { checksignature(); readscreen(); frame = window_create(NULL,FRAME,0); window_set(frame,WIN_HEIGHT,scale*screenheight+28,WIN_WIDTH,scale*screenwidth+14,0); canvas = window_create(frame,CANVAS,CANVAS_AUTO_SHRINK,FALSE, CANVAS_WIDTH,screenwidth, CANVAS_HEIGHT,screenheight, WIN_VERTICAL_SCROLLBAR,scrollbar_create(0), WIN_HORIZONTAL_SCROLLBAR,scrollbar_create(0),0); pw = canvas_pixwin(canvas); (void) notify_set_itimer_func(frame,draw_loop,ITIMER_REAL,&NOTIFY_POLLING_ITIMER, ((struct itimerval *) 0)); window_main_loop(frame); } #*\\\THE_END//////*# # -------- raster.c -------- echo extracting file raster.c cat << '#*\\\THE_END//////*#' > raster.c #include <stdio.h> #include <suntool/sunview.h> #include <suntool/canvas.h> #include "viewgif.h" #include "sunvgif.h" void outcode(p) register codetype *p; { int x, y; if (p->prefix) outcode(p->prefix); for (y=0; y < scale; y++) { for (x=0; x < scale; x++) { if (interleaved) pw_put(pw, (left + xx) * scale + x,(interleavetable[yy] + top) * scale + y, p->suffix); else pw_put(pw, (left + xx) * scale + x,(yy + top) * scale + y, p->suffix); } } if (++xx > width-1) { xx=0; yy++; pw_show(pw); } } void process(code) register code; { static avail, oldcode; register codetype *p; if (code == clear) { codesize=datasize + 1; codemask = (1 << codesize) - 1; avail = clear + 2; oldcode = -1; } else if (code < avail) { outcode(&codetable[code]); if (oldcode != -1) { p = &codetable[avail++]; p->prefix = &codetable[oldcode]; p->first = p->prefix->first; p->suffix = codetable[code].first; if ((avail & codemask) == 0 && avail < 4096) { codesize++; codemask += avail; } } oldcode = code; } else if (code == avail && oldcode != -1) { p = &codetable[avail++]; p->prefix = &codetable[oldcode]; p->first = p->prefix->first; p->suffix = p->first; outcode(p); if ((avail & codemask) == 0 && avail < 4096) { codesize++; codemask += avail; } oldcode = code; } else { fatal("illegal code in raster data"); } } void readraster(width, height) unsigned int width, height; { unsigned char buf[255]; register bits=0; register unsigned count,datum=0; register unsigned char *ch; register int code; datasize = getc(infile); clear = 1 << datasize; eoi = clear+1; codesize = datasize + 1; codemask = (1 << codesize) - 1; codetable = (codetype*)malloc(4096*sizeof(codetype)); if (!codetable) fatal("not enough memory for code table"); for (code = 0; code < clear; code++) { codetable[code].prefix = (codetype*)0; codetable[code].first = code; codetable[code].suffix = code; } for (count = getc(infile); count > 0; count = getc(infile)) { fread(buf,1,count,infile); for (ch=buf; count-- > 0; ch++) { datum += *ch << bits; bits += 8; while (bits >= codesize) { code = datum & codemask; datum >>= codesize; bits -= codesize; if (code == eoi) goto exitloop; /* This kludge put in because some GIF files aren't standard */ process(code); } } } exitloop: free(codetable); } /* Read image information (position, size, local color map, etc.) and convert to postscript. */ void readimage() { unsigned char buf[9]; bool local; char localmap[256][3]; int localbits; register row; register i; fread(buf, 1, 9, infile); left = buf[0] + (buf[1] << 8); top = buf[2] + (buf[3] << 8); width = buf[4] + (buf[5] << 8); height = buf[6] + (buf[7] << 8); local = buf[8] & 0x80; interleaved = buf[8] & 0x40; if (local) { localbits = (buf[8] & 0x7) + 1; fread(localmap, 3, 1<<localbits, infile); initcolors(colortable, localmap, 1<<localbits); } else if (global) { initcolors(colortable, globalmap, 1<<globalbits); } else { fatal("no colormap present for image"); } if (interleaved) { interleavetable = (int*) malloc(height * sizeof(int)); if (!interleavetable) fatal("not enough memory for interleave table"); row = 0; for (i = 0; i < height; i += 8) interleavetable[row++] = i; for (i = 4; i < height; i += 8) interleavetable[row++] = i; for (i = 2; i < height; i += 4) interleavetable[row++] = i; for (i = 1; i < height; i += 2) interleavetable[row++] = i; } pw_batch_on(pw); readraster(width, height); pw_batch_off(pw); } /* Read a GIF extension block (and do nothing with it). */ void readextension() { unsigned char code, count; char buf[255]; code = getc(infile); while (count = getc(infile)) fread(buf,1,count,infile); } #*\\\THE_END//////*# # -------- sunvgif.h -------- echo extracting file sunvgif.h cat << '#*\\\THE_END//////*#' > sunvgif.h Frame frame; Canvas canvas; Pixwin *pw; #*\\\THE_END//////*# # -------- viewgif.h -------- echo extracting file viewgif.h cat << '#*\\\THE_END//////*#' > viewgif.h #define TIMER_NULL ((struct itimerval *) 0) #define TRUE 1 #define FALSE 0 typedef int bool; typedef struct codestruct { struct codestruct *prefix; unsigned char first,suffix; } codetype; char *malloc(); int strncmp(); FILE *infile, *fopen(); void main(), usage(), fatal(), checksignature(), readscreen(), initcolors(), outcode(), process(), readraster(), readimage(), readextension(), draw_loop(), do_prog(); int scale, datasize, codesize, codemask, clear, eoi, *interleavetable, globalbits; unsigned int screenwidth, screenheight, xx,yy, left,width, top,height; bool global, interleaved; char colortable[256][3], *progname, *filename; unsigned char red[256], green[256], blue[256], globalmap[256][3]; codetype *codetable; #*\\\THE_END//////*# echo Done with extraction -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_- Paul Nakada '89 #8-) nakada@husc4.harvard.edu Harvard College nakada@husc4.bitnet Cambridge, MA {ihnp4!think, seismo, rutgers}!harvard!husc4!nakada _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_