Path: utzoo!utgpu!utstat!jarvis.csri.toronto.edu!mailrus!ncar!ames!vsi1!wyse!mikew From: mikew@wyse.wyse.com (Mike Wexler) Newsgroups: comp.sources.x Subject: v03i029: program to display gif images on color servers, Part01/01 Message-ID: <2080@wyse.wyse.com> Date: 21 Feb 89 19:11:10 GMT Organization: Wyse Technology, San Jose Lines: 1398 Approved: mikew@wyse.com Submitted-by: bradley@cis.upenn.edu (John Bradley) Posting-number: Volume 3, Issue 29 Archive-name: xgif/part01 [I made to changes to this program. Adding a break after a default: statement in a switch statement. This kept Sun's compiler from complaining. And removing #include which was unnecessary since is already included. -mcw] #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'README' <<'END_OF_FILE' Xxgif is a program that displays GIF images on an 8-plane X11 display. The Ximages can be freely rescaled. X XA collection of GIF images is available via anonymous ftp to X"dsl.cis.upenn.edu" [128.91.2.12]. X XJohn Bradley - bradley@cis.upenn.edu X XRevision History: X XPATCH 1 - Somewhat more intellegent color use. Basically, it only trys Xto allocate the colors that the GIF picture actually USES, rather than one Xcolor for each entry in the GIF colormap. Ran into a bunch of pictures that Xonly used 16 colors out of a 256-entry colormap... X XAlso added [-display] option, in keeping with the New Improved Standard XCommand Line Options for X11. X XPATCH 2 - (2/13/89) Minor problem with dying on unexpected X events. XDifferent window managers send different events. Solution: simply IGNORE Xunexpected X events. X END_OF_FILE if test 817 -ne `wc -c <'README'`; then echo shar: \"'README'\" unpacked with wrong size! fi # end of 'README' fi if test -f 'AUTHOR' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'AUTHOR'\" else echo shar: Extracting \"'AUTHOR'\" \(310 characters\) sed "s/^X//" >'AUTHOR' <<'END_OF_FILE' XWritten by John Bradley (bradley@cis.upenn.edu), one of the fine folks at Xthe University of Pennsylvania. X XDo whatever you want with this program, though it *would* be nice if my name Xremained on it somewhere... Other than that, it may be freely modified, Xdistributed, and used to fill up disk space. X X--jhb END_OF_FILE if test 310 -ne `wc -c <'AUTHOR'`; then echo shar: \"'AUTHOR'\" unpacked with wrong size! fi # end of 'AUTHOR' fi if test -f 'Imakefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Imakefile'\" else echo shar: Extracting \"'Imakefile'\" \(119 characters\) sed "s/^X//" >'Imakefile' <<'END_OF_FILE' XLOCAL_LIBRARIES = $(XLIB) X XOBJS = \ X xgif.o \ X xgifload.o X XSRCS = \ X xgif.c \ X xgifload.c X XComplexProgramTarget(xgif) X END_OF_FILE if test 119 -ne `wc -c <'Imakefile'`; then echo shar: \"'Imakefile'\" unpacked with wrong size! fi # end of 'Imakefile' fi if test -f 'Makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Makefile'\" else echo shar: Extracting \"'Makefile'\" \(7275 characters\) sed "s/^X//" >'Makefile' <<'END_OF_FILE' X# Makefile generated by imake - do not edit! X# $XConsortium: imake.c,v 1.37 88/10/08 20:08:30 jim Exp $ X# X# The cpp used on this machine replaces all newlines and multiple tabs and X# spaces in a macro expansion with a single space. Imake tries to compensate X# for this, but is not always successful. X# X X########################################################################### X# X Window System Makefile generated from template file Imake.tmpl X# $XConsortium: Imake.tmpl,v 1.91 88/10/23 22:37:10 jim Exp $ X# X# Do not change the body of the imake template file. Server-specific X# parameters may be set in the appropriate .macros file; site-specific X# parameters (but shared by all servers) may be set in site.def. If you X# make any changes, you'll need to rebuild the makefiles using X# "make World" (at best) or "make Makefile; make Makefiles" (at least) in X# the top level directory. X# X# If your C preprocessor doesn't define any unique symbols, you'll need X# to set BOOTSTRAPCFLAGS when rebuilding imake (usually when doing X# "make Makefile", "make Makefiles", or "make World"). X# X# If you absolutely can't get imake to work, you'll need to set the X# variables at the top of each Makefile as well as the dependencies at the X# bottom (makedepend will do this automatically). X# X X########################################################################### X# platform-specific configuration parameters - edit Sun.macros to change X X# platform: $XConsortium: Sun.macros,v 1.52 88/10/23 11:00:55 jim Exp $ X# operating system: SunOS 3.4 X XBOOTSTRAPCFLAGS = X AS = as X CC = cc X CPP = /lib/cpp X LD = ld X LINT = lint X INSTALL = install X TAGS = ctags X RM = rm -f X MV = mv X LN = ln -s X RANLIB = ranlib XRANLIBINSTFLAGS = -t X AR = ar clq X LS = ls X LINTOPTS = -xz X LINTLIBFLAG = -C X MAKE = make XSTD_CPP_DEFINES = X STD_DEFINES = X X########################################################################### X# site-specific configuration parameters - edit site.def to change X X# site: $XConsortium: site.def,v 1.16 88/10/12 10:30:24 jim Exp $ X X########################################################################### X# definitions common to all Makefiles - do not edit X X SHELL = /bin/sh X X DESTDIR = /global X USRLIBDIR = $(DESTDIR)/lib X BINDIR = $(DESTDIR)/bin/X11 X INCDIR = $(DESTDIR)/include X ADMDIR = $(DESTDIR)/usr/adm X LIBDIR = $(USRLIBDIR)/X11 X LINTLIBDIR = $(USRLIBDIR)/lint X FONTDIR = $(LIBDIR)/fonts X XINITDIR = $(LIBDIR)/xinit X XDMDIR = $(LIBDIR)/xdm X UWMDIR = $(LIBDIR)/uwm X AWMDIR = $(LIBDIR)/awm X TWMDIR = $(LIBDIR)/twm X DTDIR = $(LIBDIR)/dt X MANPATH = /usr/man X MANSOURCEPATH = $(MANPATH)/man X MANDIR = $(MANSOURCEPATH)n X LIBMANDIR = $(MANSOURCEPATH)n3 X XAPPLOADDIR = $(LIBDIR)/app-defaults X X INSTBINFLAGS = -m 0755 X INSTUIDFLAGS = -m 4755 X INSTLIBFLAGS = -m 0664 X INSTINCFLAGS = -m 0444 X INSTMANFLAGS = -m 0444 X INSTAPPFLAGS = -m 0444 X INSTKMEMFLAGS = -m 4755 X FCFLAGS = -t X CDEBUGFLAGS = -O X X PATHSEP = / X DEPEND = $(BINDIR)/makedepend X IMAKE = $(BINDIR)/imake X RGB = $(LIBDIR)/rgb X FC = $(BINDIR)/bdftosnf X MKFONTDIR = $(BINDIR)/mkfontdir X MKDIRHIER = $(BINDIR)/mkdirhier.sh X X CFLAGS = $(CDEBUGFLAGS) $(INCLUDES) $(STD_DEFINES) $(DEFINES) X LINTFLAGS = $(LINTOPTS) $(INCLUDES) $(STD_DEFINES) $(DEFINES) -DLINT X LDFLAGS = $(CDEBUGFLAGS) -L$(USRLIBDIR) $(SYS_LIBRARIES) $(SYSAUX_LIBRARIES) X X IRULESRC = $(LIBDIR)/imake.includes X X EXTENSIONLIB = $(USRLIBDIR)/libext.a X XLIB = $(USRLIBDIR)/libX11.a X XMULIB = $(USRLIBDIR)/libXmu.a X OLDXLIB = $(USRLIBDIR)/liboldX.a X XTOOLLIB = $(USRLIBDIR)/libXt.a X XAWLIB = $(USRLIBDIR)/libXaw.a X LINTXLIB = $(USRLIBDIR)/lint/llib-lX11.ln X LINTXMU = $(USRLIBDIR)/lint/llib-lXmu.ln X LINTXTOOL = $(USRLIBDIR)/lint/llib-lXt.ln X LINTXAW = $(USRLIBDIR)/lint/llib-lXaw.ln X INCLUDES = -I$(INCDIR) X MACROFILE = Sun.macros X ICONFIGFILES = $(IRULESRC)/Imake.tmpl \ X $(IRULESRC)/$(MACROFILE) $(IRULESRC)/site.def X IMAKE_DEFINES = X IMAKE_CMD = $(NEWTOP)$(IMAKE) -TImake.tmpl -I$(NEWTOP)$(IRULESRC) \ X -s Makefile $(IMAKE_DEFINES) X RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a \ X .emacs_* tags TAGS make.log MakeOut X X########################################################################### X# rules: $XConsortium: Imake.rules,v 1.71 88/10/23 22:46:34 jim Exp $ X X########################################################################### X# start of Imakefile X XLOCAL_LIBRARIES = $(XLIB) X XOBJS = \ X xgif.o \ X xgifload.o X XSRCS = \ X xgif.c \ X xgifload.c X X PROGRAM = xgif X Xall:: xgif X Xxgif: $(OBJS) $(LOCAL_LIBRARIES) X $(RM) $@ X $(CC) -o $@ $(OBJS) $(LOCAL_LIBRARIES) $(LDFLAGS) $(SYSLAST_LIBRARIES) X Xrelink:: X $(RM) $(PROGRAM) X $(MAKE) $(MFLAGS) $(PROGRAM) X Xinstall:: xgif X $(INSTALL) -c $(INSTALLFLAGS) xgif $(BINDIR) X Xinstall.man:: xgif.man X $(INSTALL) -c $(INSTMANFLAGS) xgif.man $(MANDIR)/xgif.n X Xdepend:: $(DEPEND) X Xdepend:: X $(DEPEND) -s "# DO NOT DELETE" -- $(CFLAGS) -- $(SRCS) X X$(DEPEND): X @echo "making $@"; \ X cd $(DEPENDSRC); $(MAKE) X Xclean:: X $(RM) $(PROGRAM) X X########################################################################### X# Imake.tmpl common rules for all Makefiles - do not edit X Xemptyrule:: X Xclean:: X $(RM_CMD) \#* X XMakefile:: $(IMAKE) X XMakefile:: Imakefile \ X $(IRULESRC)/Imake.tmpl \ X $(IRULESRC)/Imake.rules \ X $(IRULESRC)/site.def \ X $(IRULESRC)/$(MACROFILE) X -@if [ -f Makefile ]; then \ X echo "$(RM) Makefile.bak; $(MV) Makefile Makefile.bak"; \ X $(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \ X else exit 0; fi X $(IMAKE_CMD) -DTOPDIR=$(TOP) X X$(IMAKE): X @echo "making $@"; \ X cd $(IMAKESRC); $(MAKE) BOOTSTRAPCFLAGS=$(BOOTSTRAPCFLAGS) X Xtags:: X $(TAGS) -w *.[ch] X $(TAGS) -xw *.[ch] > TAGS X X########################################################################### X# empty rules for directories that do not have SUBDIRS - do not edit X Xinstall:: X @echo "install done" X Xinstall.man:: X @echo "install.man done" X XMakefiles:: X X########################################################################### X# dependencies generated by makedepend X X# DO NOT DELETE X Xxgif.o: xgif.h /usr/include/stdio.h /usr/include/math.h /usr/include/ctype.h Xxgif.o: /global/include/X11/Xos.h /usr/include/sys/types.h Xxgif.o: /usr/include/sys/sysmacros.h /usr/include/strings.h Xxgif.o: /usr/include/sys/file.h /usr/include/sys/fcntl.h Xxgif.o: /usr/include/sys/time.h /usr/include/sys/time.h Xxgif.o: /global/include/X11/Xlib.h /global/include/X11/X.h Xxgif.o: /global/include/X11/Xutil.h Xxgifload.o: xgif.h /usr/include/stdio.h /usr/include/math.h Xxgifload.o: /usr/include/ctype.h /global/include/X11/Xos.h Xxgifload.o: /usr/include/sys/types.h /usr/include/sys/sysmacros.h Xxgifload.o: /usr/include/strings.h /usr/include/sys/file.h Xxgifload.o: /usr/include/sys/fcntl.h /usr/include/sys/time.h Xxgifload.o: /usr/include/sys/time.h /global/include/X11/Xlib.h Xxgifload.o: /global/include/X11/X.h /global/include/X11/Xutil.h END_OF_FILE if test 7275 -ne `wc -c <'Makefile'`; then echo shar: \"'Makefile'\" unpacked with wrong size! fi # end of 'Makefile' fi if test -f 'patchlevel.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'patchlevel.h'\" else echo shar: Extracting \"'patchlevel.h'\" \(21 characters\) sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE' X#define PATCHLEVEL 2 END_OF_FILE if test 21 -ne `wc -c <'patchlevel.h'`; then echo shar: \"'patchlevel.h'\" unpacked with wrong size! fi # end of 'patchlevel.h' fi if test -f 'xgif.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xgif.c'\" else echo shar: Extracting \"'xgif.c'\" \(8705 characters\) sed "s/^X//" >'xgif.c' <<'END_OF_FILE' X/* X * xgif.c - displays GIF pictures on an X11 display X * X * Author: John Bradley, University of Pennsylvania X * (bradley@cis.upenn.edu) X */ X X#define MAIN X#include "xgif.h" X X X/*******************************************/ Xmain(argc, argv) X int argc; X char *argv[]; X/*******************************************/ X{ X int i; X char *display, *geom, *fname; X XEvent event; X X cmd = argv[0]; X display = geom = fname = NULL; X expImage = NULL; X X expand = 1; strip = 0; nostrip = 0; X X /*********************Options*********************/ X X for (i = 1; i < argc; i++) { X char *strind; X X if (!strncmp(argv[i],"-g",2)) { /* geometry */ X i++; X geom = argv[i]; X continue; X } X X if (argv[i][0] == '=') { /* old-style geometry */ X geom = argv[i]; X continue; X } X X if (!strncmp(argv[i],"-d",2)) { /* display */ X i++; X display = argv[i]; X continue; X } X X strind = index(argv[i], ':'); /* old-style display */ X if(strind != NULL) { X display = argv[i]; X continue; X } X X if (!strcmp(argv[i],"-e")) { /* expand */ X i++; X expand=atoi(argv[i]); X continue; X } X X if (!strcmp(argv[i],"-s")) { /* strip */ X i++; X strip=atoi(argv[i]); X continue; X } X X if (!strcmp(argv[i],"-ns")) { /* nostrip */ X nostrip++; X continue; X } X X if (argv[i][0] != '-') { /* the file name */ X fname = argv[i]; X continue; X } X X Syntax(cmd); X } X X if (fname==NULL) fname="-"; X if (expand<1 || expand>MAXEXPAND) Syntax(cmd); X if (strip<0 || strip>7) Syntax(cmd); X X /*****************************************************/ X X /* Open up the display. */ X X if ( (theDisp=XOpenDisplay(display)) == NULL) { X fprintf(stderr, "%s: Can't open display\n",argv[0]); X exit(1); X } X X theScreen = DefaultScreen(theDisp); X theCmap = DefaultColormap(theDisp, theScreen); X rootW = RootWindow(theDisp,theScreen); X theGC = DefaultGC(theDisp,theScreen); X fcol = WhitePixel(theDisp,theScreen); X bcol = BlackPixel(theDisp,theScreen); X theVisual = DefaultVisual(theDisp,theScreen); X X dispcells = DisplayCells(theDisp, theScreen); X if (dispcells<=2) X FatalError("This program requires a color display, pref. 8 bits."); X X X /****************** Open/Read the File *****************/ X LoadGIF(fname); X iWIDE = theImage->width; iHIGH = theImage->height; X X eWIDE = iWIDE * expand; eHIGH = iHIGH * expand; X if (eWIDE > DisplayWidth(theDisp,theScreen)) X eWIDE = DisplayWidth(theDisp,theScreen); X if (eHIGH > DisplayHeight(theDisp,theScreen)) X eHIGH = DisplayHeight(theDisp,theScreen); X X /**************** Create/Open X Resources ***************/ X if ((mfinfo = XLoadQueryFont(theDisp,"variable"))==NULL) X FatalError("couldn't open 'variable' font\n"); X mfont=mfinfo->fid; X XSetFont(theDisp,theGC,mfont); X XSetForeground(theDisp,theGC,fcol); X XSetBackground(theDisp,theGC,bcol); X X CreateMainWindow(cmd,geom,argc,argv); X Resize(eWIDE,eHIGH); X X XSelectInput(theDisp, mainW, ExposureMask | KeyPressMask X | StructureNotifyMask); X XMapWindow(theDisp,mainW); X X /**************** Main loop *****************/ X while (1) { X XNextEvent(theDisp, &event); X HandleEvent(&event); X } X} X X X X/****************/ XHandleEvent(event) X XEvent *event; X/****************/ X{ X switch (event->type) { X case Expose: { X XExposeEvent *exp_event = (XExposeEvent *) event; X X if (exp_event->window==mainW) X DrawWindow(exp_event->x,exp_event->y, X exp_event->width, exp_event->height); X } X break; X X case KeyPress: { X XKeyEvent *key_event = (XKeyEvent *) event; X char buf[128]; X KeySym ks; X XComposeStatus status; X X XLookupString(key_event,buf,128,&ks,&status); X if (buf[0]=='q' || buf[0]=='Q') Quit(); X } X break; X X case ConfigureNotify: { X XConfigureEvent *conf_event = (XConfigureEvent *) event; X X if (conf_event->window == mainW && X (conf_event->width != eWIDE || conf_event->height != eHIGH)) X Resize(conf_event->width, conf_event->height); X } X break; X X X case CirculateNotify: X case MapNotify: X case DestroyNotify: X case GravityNotify: X case ReparentNotify: X case UnmapNotify: break; X X default: /* ignore unexpected events */ X break; X } /* end of switch */ X} X X X/***********************************/ XSyntax() X{ X printf("Usage: %s filename [[-geometry] geom] [[-display] display]\n",cmd); X printf(" [-e 1..%d] [-s 0-7] [-ns]\n",MAXEXPAND); X exit(1); X} X X X/***********************************/ XFatalError (identifier) X char *identifier; X{ X fprintf(stderr, "%s: %s\n",cmd, identifier); X exit(-1); X} X X X/***********************************/ XQuit() X{ X exit(0); X} X X X/***********************************/ XDrawWindow(x,y,w,h) X{ X XPutImage(theDisp,mainW,theGC,expImage,x,y,x,y,w,h); X} X X X/***********************************/ XResize(w,h) Xint w,h; X{ X int ix,iy,ex,ey; X byte *ximag,*ilptr,*ipptr,*elptr,*epptr; X static char *rstr = "Resizing Image. Please wait..."; X X /* warning: this code'll only run machines where int=32-bits */ X X if (w==iWIDE && h==iHIGH) { /* very special case */ X if (expImage != theImage) { X if (expImage) XDestroyImage(expImage); X expImage = theImage; X eWIDE = iWIDE; eHIGH = iHIGH; X } X } X X else { /* have to do some work */ X /* if it's a big image, this'll take a while. mention it */ X if (w*h>(500*500)) { X XDrawImageString(theDisp,mainW,theGC,CENTERX(mfinfo,w/2,rstr), X CENTERY(mfinfo,h/2),rstr, strlen(rstr)); X XFlush(theDisp); X } X X /* first, kill the old expImage, if one exists */ X if (expImage && expImage != theImage) { X free(expImage->data); expImage->data = NULL; X XDestroyImage(expImage); X } X X /* create expImage of the appropriate size */ X X eWIDE = w; eHIGH = h; X ximag = (byte *) malloc(w*h); X expImage = XCreateImage(theDisp,theVisual,8,ZPixmap,0,ximag, X eWIDE,eHIGH,8,eWIDE); X X if (!ximag || !expImage) { X fprintf(stderr,"ERROR: unable to create a %dx%d image\n",w,h); X exit(0); X } X X elptr = epptr = (byte *) expImage->data; X X for (ey=0; eydata + (iy * iWIDE); X for (ex=0; ex'xgif.h' <<'END_OF_FILE' X/* X * xgif.h - header file for xgif, but you probably already knew as much X */ X X X#define REVDATE "Rev: 2/13/89" X#define MAXEXPAND 16 X X/* include files */ X#include X#include X#include X X#include X#include X#include X X X#ifndef MAIN X#define WHERE extern X#else X#define WHERE X#endif X Xtypedef unsigned char byte; X X#define CENTERX(f,x,str) ((x)-XTextWidth(f,str,strlen(str))/2) X#define CENTERY(f,y) ((y)-((f->ascent+f->descent)/2)+f->ascent) X X X/* X stuff */ XWHERE Display *theDisp; XWHERE int theScreen, dispcells; XWHERE Colormap theCmap; XWHERE Window rootW, mainW; XWHERE GC theGC; XWHERE unsigned long fcol,bcol; XWHERE Font mfont; XWHERE XFontStruct *mfinfo; XWHERE Visual *theVisual; XWHERE XImage *theImage, *expImage; X X/* global vars */ XWHERE int iWIDE,iHIGH,eWIDE,eHIGH,expand,numcols,strip,nostrip; XWHERE unsigned long cols[256]; XWHERE XColor defs[256]; XWHERE char *cmd; END_OF_FILE if test 1025 -ne `wc -c <'xgif.h'`; then echo shar: \"'xgif.h'\" unpacked with wrong size! fi # end of 'xgif.h' fi if test -f 'xgif.man' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xgif.man'\" else echo shar: Extracting \"'xgif.man'\" \(4487 characters\) sed "s/^X//" >'xgif.man' <<'END_OF_FILE' X.TH xgif 1X X.SH NAME Xxgif \- displays GIF (*) pictures on X11 displays X.SH SYNTAX X\fBxgif\fP [\fIdisplay\fP] [ [-g] \fIgeometry\fP] [-e \fIexpansion\fP] X[-s \fIstrip\fP] [-ns] [\fIfilename\fP] X.SH DESCRIPTION X\fBxgif\fP is an X11 program that displays GIF pictures on an 8-plane Xdisplay. X.SH OPTIONS XThe '-e' option allows you to expand the picture by an integer amount. For Xexample, viewing a 320x200 picture with an expansion factor of '2' will Xresult in a 640x400 picture, each pixel of which is a 2x2 block. X.PP XYou may also specify an expansion of the picture by specifying the size of Xthe window in the \fIgeometry\fP option. This also allows you specify Xnon-integer expansion factors, and different aspect ratios. Example: if Xyou view a 320x200 picture, but specify a window size of 640x300, the picture Xwill be expanded by a factor of two along the X-axis, but only by a factor of X1.5 along the Y-axis. X.PP XIf you specify both the '-e' option and a window size (via \fIgeometry\fP), Xthe '-e' will be ignored. X.PP XThe '-s' option allows you specify the number of bits to strip off of the Xcolors. The theory runs like this: if you have 256 unique colors in your XGIF file, you will almost certainly be unable to allocate all of them on an X8-plane display, as a couple colors will already be allocated for the Xwindow manager, and such. Setting this option allows you to strip off the Xlow \fIstrip\fP bits of the R,G,B entries in the GIF colormap. This will Xhave the desired effect of making some of the (previously different) colors Xthe SAME, and you will be able to allocate all the colors you need now. X.PP XYou shouldn't ever HAVE to set this option, because if the program is unable Xto allocate the required colors, it will try again after incrementing X\fIstrip\fP. You can, however save some time, or alternately get neat Xvisual effects by setting this option. X.PP XThe '-ns' option turns off the 'auto-strip' feature described above. You Xuse this to FORCE the program to use as many colors as possible. The theory Xworks like this: if you have 256 unique colors in your GIF file, you will Xprobably be able to allocate all but a few of them. Rather than stripping off Xbits, decreasing the color resolution for the whole picture uniformly, the X'nostrip' option makes the program set the few unallocatable colors equal to Xthe 'closest' colors that were allocated. This may cause nasty 'blotches' Xon the picture. Then again, it might not. Only way to tell is to try both Xwith and without the 'auto-strip' 'feature'. X.PP XOne DEFINITE drawback of the '-ns' option is that it's only really useful Xon the FIRST picture you try to display. If you try to display two pictures Xsimultaneously, the first picture will (presumably) use up most (if not ALL) Xof the colortable, leaving NO colors for the second picture. Therefore, the Xsecond (and succeeding pictures) will probably not look very good. When you Xuse the 'auto-strip' feature, you will be able to get considerably more Xpictures on the screen simultaneously. Probably. Varies wildly, based on Xthe actual pictures being displayed. X.PP XAlso, it should be noted that if the optional \fIfilename\fP is not supplied, Xthe program will read the picture from stdin. X.SH LIMITATIONS XYou'll require (at least) an 8-plane X11 display. This program Xignores 'local colormaps' in GIF files (see the GIF spec for details). XIt also only displays the first image in GIF files that have multiple Ximages in them. X.PP XThe number of pictures you can display simultaneously varies wildly. It Xdepends on how many colors are in the GIF files, and how many of them are Xshared by other GIF files. Suffice it to say that you can ALWAYS display a Xpicture, though the colors may or may not be right. If the program was Xunable to get all the desired colors, it will mention that fact. X.PP XNote: This program points out a bug in the X11R2 server for the IBM RT XMegapel display. This bug will occasionally cause the colors in a picture Xto be wrong, but no 'unable to allocate' message will be printed by the Xprogram. (Essentially, the problem is a discrepancy between what the Xserver THINKS the colormap is, and what the colormap in the hardware XACTUALLY is.) X.PP X.SH AUTHOR XJohn Bradley - bradley@cis.upenn.edu X.PP XBased (heavily) on gif2ras.c, by Patrick J. Naughton (naughton@wind.sun.com), Xa program that converts GIF pictures to Sun Rasterfiles. X.PP X(*) GIF is a no doubt a trademark of CompuServe, so watch it! END_OF_FILE if test 4487 -ne `wc -c <'xgif.man'`; then echo shar: \"'xgif.man'\" unpacked with wrong size! fi # end of 'xgif.man' fi if test -f 'xgifload.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xgifload.c'\" else echo shar: Extracting \"'xgifload.c'\" \(15199 characters\) sed "s/^X//" >'xgifload.c' <<'END_OF_FILE' X/* X * xgifload.c - based strongly on... X * X * gif2ras.c - Converts from a Compuserve GIF (tm) image to a Sun Raster image. X * X * Copyright (c) 1988, 1989 by Patrick J. Naughton X * X * Author: Patrick J. Naughton X * naughton@wind.sun.com X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, X * provided that the above copyright notice appear in all copies and that X * both that copyright notice and this permission notice appear in X * supporting documentation. X * X * This file is provided AS IS with no warranties of any kind. The author X * shall have no liability with respect to the infringement of copyrights, X * trade secrets or any patents by this file or any part thereof. In no X * event will the author be liable for any lost revenue or profits or X * other special, indirect and consequential damages. X * X */ X X#include "xgif.h" X Xtypedef int boolean; X X#define NEXTBYTE (*ptr++) X#define IMAGESEP 0x2c X#define INTERLACEMASK 0x40 X#define COLORMAPMASK 0x80 X XFILE *fp; X Xint BitOffset = 0, /* Bit Offset of next code */ X XC = 0, YC = 0, /* Output X and Y coords of current pixel */ X Pass = 0, /* Used by output routine if interlaced pic */ X OutCount = 0, /* Decompressor output 'stack count' */ X RWidth, RHeight, /* screen dimensions */ X Width, Height, /* image dimensions */ X LeftOfs, TopOfs, /* image offset */ X BitsPerPixel, /* Bits per pixel, read from GIF header */ X BytesPerScanline, /* bytes per scanline in output raster */ X ColorMapSize, /* number of colors */ X Background, /* background color */ X CodeSize, /* Code size, read from GIF header */ X InitCodeSize, /* Starting code size, used during Clear */ X Code, /* Value returned by ReadCode */ X MaxCode, /* limiting value for current code size */ X ClearCode, /* GIF clear code */ X EOFCode, /* GIF end-of-information code */ X CurCode, OldCode, InCode, /* Decompressor variables */ X FirstFree, /* First free code, generated per GIF spec */ X FreeCode, /* Decompressor, next free slot in hash table */ X FinChar, /* Decompressor variable */ X BitMask, /* AND mask for data size */ X ReadMask; /* Code AND mask for current code size */ X Xboolean Interlace, HasColormap; Xboolean Verbose = False; X Xbyte *Image; /* The result array */ Xbyte *RawGIF; /* The heap array to hold it, raw */ Xbyte *Raster; /* The raster data stream, unblocked */ X X /* The hash table used by the decompressor */ Xint Prefix[4096]; Xint Suffix[4096]; X X /* An output array used by the decompressor */ Xint OutCode[1025]; X X /* The color map, read from the GIF header */ Xbyte Red[256], Green[256], Blue[256], used[256]; Xint numused; X Xchar *id = "GIF87a"; X X X X/*****************************/ XLoadGIF(fname) X char *fname; X/*****************************/ X{ X int filesize; X register byte ch, ch1; X register byte *ptr, *ptr1; X register int i; X X if (strcmp(fname,"-")==0) { fp = stdin; fname = ""; } X else fp = fopen(fname,"r"); X X if (!fp) FatalError("file not found"); X X /* find the size of the file */ X fseek(fp, 0L, 2); X filesize = ftell(fp); X fseek(fp, 0L, 0); X X if (!(ptr = RawGIF = (byte *) malloc(filesize))) X FatalError("not enough memory to read gif file"); X X if (!(Raster = (byte *) malloc(filesize))) X FatalError("not enough memory to read gif file"); X X if (fread(ptr, filesize, 1, fp) != 1) X FatalError("GIF data read failed"); X X if (strncmp(ptr, id, 6)) X FatalError("not a GIF file"); X X ptr += 6; X X/* Get variables from the GIF screen descriptor */ X X ch = NEXTBYTE; X RWidth = ch + 0x100 * NEXTBYTE; /* screen dimensions... not used. */ X ch = NEXTBYTE; X RHeight = ch + 0x100 * NEXTBYTE; X X if (Verbose) X fprintf(stderr, "screen dims: %dx%d.\n", RWidth, RHeight); X X ch = NEXTBYTE; X HasColormap = ((ch & COLORMAPMASK) ? True : False); X X BitsPerPixel = (ch & 7) + 1; X numcols = ColorMapSize = 1 << BitsPerPixel; X BitMask = ColorMapSize - 1; X X Background = NEXTBYTE; /* background color... not used. */ X X if (NEXTBYTE) /* supposed to be NULL */ X FatalError("corrupt GIF file (bad screen descriptor)"); X X X/* Read in global colormap. */ X X if (HasColormap) { X if (Verbose) X fprintf(stderr, "%s is %dx%d, %d bits per pixel, (%d colors).\n", X fname, Width,Height,BitsPerPixel, ColorMapSize); X for (i = 0; i < ColorMapSize; i++) { X Red[i] = NEXTBYTE; X Green[i] = NEXTBYTE; X Blue[i] = NEXTBYTE; X used[i] = 0; X } X numused = 0; X X } X X else { /* no colormap in GIF file */ X fprintf(stderr,"%s: warning! no colortable in this file. Winging it.\n",cmd); X if (!numcols) numcols=256; X for (i=0; i filesize) X FatalError("corrupt GIF file (unblock)"); X } while(ch1); X X free(RawGIF); /* We're done with the raw data now... */ X X if (Verbose) { X fprintf(stderr, "done.\n"); X fprintf(stderr, "Decompressing..."); X } X X X/* Allocate the X Image */ X Image = (byte *) malloc(Width*Height); X if (!Image) FatalError("not enough memory for XImage"); X X theImage = XCreateImage(theDisp,theVisual,8,ZPixmap,0,Image, X Width,Height,8,Width); X if (!theImage) FatalError("unable to create XImage"); X X BytesPerScanline = Width; X X X/* Decompress the file, continuing until you see the GIF EOF code. X * One obvious enhancement is to add checking for corrupt files here. X */ X X Code = ReadCode(); X while (Code != EOFCode) { X X/* Clear code sets everything back to its initial value, then reads the X * immediately subsequent code as uncompressed data. X */ X X if (Code == ClearCode) { X CodeSize = InitCodeSize; X MaxCode = (1 << CodeSize); X ReadMask = MaxCode - 1; X FreeCode = FirstFree; X CurCode = OldCode = Code = ReadCode(); X FinChar = CurCode & BitMask; X AddToPixel(FinChar); X } X else { X X/* If not a clear code, then must be data: save same as CurCode and InCode */ X X CurCode = InCode = Code; X X/* If greater or equal to FreeCode, not in the hash table yet; X * repeat the last character decoded X */ X X if (CurCode >= FreeCode) { X CurCode = OldCode; X OutCode[OutCount++] = FinChar; X } X X/* Unless this code is raw data, pursue the chain pointed to by CurCode X * through the hash table to its end; each code in the chain puts its X * associated output code on the output queue. X */ X X while (CurCode > BitMask) { X if (OutCount > 1024) { X fprintf(stderr,"\nCorrupt GIF file (OutCount)!\n"); X _exit(-1); /* calling 'exit(-1)' dumps core, so I don't */ X } X OutCode[OutCount++] = Suffix[CurCode]; X CurCode = Prefix[CurCode]; X } X X/* The last code in the chain is treated as raw data. */ X X FinChar = CurCode & BitMask; X OutCode[OutCount++] = FinChar; X X/* Now we put the data out to the Output routine. X * It's been stacked LIFO, so deal with it that way... X */ X X for (i = OutCount - 1; i >= 0; i--) X AddToPixel(OutCode[i]); X OutCount = 0; X X/* Build the hash table on-the-fly. No table is stored in the file. */ X X Prefix[FreeCode] = OldCode; X Suffix[FreeCode] = FinChar; X OldCode = InCode; X X/* Point to the next slot in the table. If we exceed the current X * MaxCode value, increment the code size unless it's already 12. If it X * is, do nothing: the next code decompressed better be CLEAR X */ X X FreeCode++; X if (FreeCode >= MaxCode) { X if (CodeSize < 12) { X CodeSize++; X MaxCode *= 2; X ReadMask = (1 << CodeSize) - 1; X } X } X } X Code = ReadCode(); X } X X free(Raster); X X if (Verbose) X fprintf(stderr, "done.\n"); X else X fprintf(stderr,"(of which %d are used)\n",numused); X X if (fp != stdin) X fclose(fp); X X ColorDicking(fname); X} X X X/* Fetch the next code from the raster data stream. The codes can be X * any length from 3 to 12 bits, packed into 8-bit bytes, so we have to X * maintain our location in the Raster array as a BIT Offset. We compute X * the byte Offset into the raster array by dividing this by 8, pick up X * three bytes, compute the bit Offset into our 24-bit chunk, shift to X * bring the desired code to the bottom, then mask it off and return it. X */ XReadCode() X{ Xint RawCode, ByteOffset; X X ByteOffset = BitOffset / 8; X RawCode = Raster[ByteOffset] + (0x100 * Raster[ByteOffset + 1]); X if (CodeSize >= 8) X RawCode += (0x10000 * Raster[ByteOffset + 2]); X RawCode >>= (BitOffset % 8); X BitOffset += CodeSize; X return(RawCode & ReadMask); X} X X XAddToPixel(Index) Xbyte Index; X{ X if (YC= Height) { X Pass++; X YC = 4; X } X break; X case 1: X YC += 8; X if (YC >= Height) { X Pass++; X YC = 2; X } X break; X case 2: X YC += 4; X if (YC >= Height) { X Pass++; X YC = 1; X } X break; X case 3: X YC += 2; X break; X default: X break; X } X } X } X} X X X X/*************************/ XColorDicking(fname) Xchar *fname; X{ X /* we've got the picture loaded, we know what colors are needed. get 'em */ X X register int i,j; X static byte lmasks[8] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80}; X byte lmask, *ptr; X X X if (!HasColormap) return; X /* no need to allocate any colors if no colormap in GIF file */ X X /* Allocate the X colors for this picture */ X X if (nostrip) { /* nostrip was set. try REAL hard to do it */ X for (i=j=0; i>8)) + X abs(g - (ctab[j].green>>8)) + X abs(b - (ctab[j].blue>>8)); X if (d=0; i--) X if (used[i]) XFreeColors(theDisp,theCmap,cols+i,1,0L); X } X else break; X } X X if (j && strip<8) X fprintf(stderr,"%s: %s stripped %d bits\n",cmd,fname,strip); X X if (strip==8) { X fprintf(stderr,"UTTERLY failed to allocate the desired colors.\n"); X for (i=0; i