swindon.ingr.com (Nik Simpson x333) (12/14/90)
Since I said that I had a GIF file viewer for Intergraph machines I've recieved several requests for the source, so rather than post it seperately all round the world I thought I'd put it here. What follows is a shar archive of two files evgif.h and evdisp.c, to compile and run use the following cc evdisp.c -ltools_s -lc_s -o evdisp To run use the following evdisp filename.gif It also supports a very limited ability to brighten images ... evdisp -b 120 filename.gif This will brighten the colour table by about 20% whatever that means, it is useful with some images that seem to be very dim. I take no responsiblity for any bugs in this code, it does crash on some gif files, so for what its worth here it is :- -----------------------------------cut here------------------------------- #! /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 <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: evgif.h evdisp.c # Wrapped by nik@st_nik on Fri Dec 14 10:56:46 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'evgif.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'evgif.h'\" else echo shar: Extracting \"'evgif.h'\" \(463 characters\) sed "s/^X//" >'evgif.h' <<'END_OF_FILE' X/* X * evgif.h, this is minor mods to xgif.h X */ X X X#define REVDATE "Rev: 2/13/89" X#define MAXEXPAND 16 X X/* include files */ X#include <tools.h> X#include <stdio.h> X#include <math.h> X#include <ctype.h> X#include <signal.h> X X X Xtypedef unsigned char byte; X X#define TRUE 1 X#define FALSE 0 X X X/* global vars */ Xint iWIDE,iHIGH,eWIDE,eHIGH,expand,numcols,strip,nostrip; Xint pausetime; Xint vsno; Xunsigned long cols[256]; Xchar *cmd; X Xbyte *Image; END_OF_FILE if test 463 -ne `wc -c <'evgif.h'`; then echo shar: \"'evgif.h'\" unpacked with wrong size! fi # end of 'evgif.h' fi if test -f 'evdisp.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'evdisp.c'\" else echo shar: Extracting \"'evdisp.c'\" \(14173 characters\) sed "s/^X//" >'evdisp.c' <<'END_OF_FILE' X/* X * Load a GIF image file into an Environ V window X * evgif.c - derived almost entirely from :- 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 "evgif.h" X X#define BOOLEAN int 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 = TRUE; X 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]; Xint bright; 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]; Xstruct vlt_slot vlt[256]; Xint numused; X Xchar *id = "GIF87a"; X Xvoid get_color_map() X{ X /* we've got the picture loaded, we know what colors are needed. get 'em */ X X register int i,j; X byte lmask, *ptr; X float brightness; X X X if (!HasColormap) X return; X X brightness=(float)bright/100.0; X X for (i=0;i<256;i++) X { X int red,green,blue; X red = (Red[i]<<8)*brightness; X green = (Green[i]<<8)*brightness; X blue = (Blue[i]<<8)*brightness; X vlt[i].v_red = (red > 65535)? 65535:red; X vlt[i].v_green = (green > 65535)? 65535:green; X vlt[i].v_blue = (blue > 65535)? 65535:blue; X vlt[i].v_slot = i; X } X X Loadvlt(vsno,vlt,256); X X} X Xint find_slot(red,green,blue) X byte red,green,blue; X{ X int slot=0; X X while (slot < 512 ) X if ((vlt[slot].v_red == (int)red) && X (vlt[slot].v_green == (int)green) && X (vlt[slot].v_blue == (int)blue)) X { X fprintf(stderr,"vlt values = %d %d %d\n",vlt[slot].v_red,vlt[slot].v_green,vlt[slot].v_blue); X fprintf(stderr,"gif values = %d %d %d\n",red,green,blue); X return vlt[slot].v_slot; X } X else X slot++; X return -1; 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 = "<stdin>"; } 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<numcols; i++) cols[i] = (unsigned long) i; X } X X/* Check for image seperator */ X X if (NEXTBYTE != IMAGESEP) X FatalError("corrupt GIF file (no image separator)"); X X/* Now read in values from the image descriptor */ X X ch = NEXTBYTE; X LeftOfs = ch + 0x100 * NEXTBYTE; X ch = NEXTBYTE; X TopOfs = ch + 0x100 * NEXTBYTE; X ch = NEXTBYTE; X Width = ch + 0x100 * NEXTBYTE; X ch = NEXTBYTE; X Height = ch + 0x100 * NEXTBYTE; X Interlace = ((NEXTBYTE & INTERLACEMASK) ? TRUE : FALSE); X X if (Verbose) X fprintf(stderr, "Reading a %d by %d %sinterlaced image...", X Width, Height, (Interlace) ? "" : "non-"); X X else X fprintf(stderr, "%s: %s is %dx%d, %d colors ", X cmd, fname, Width,Height,ColorMapSize); X X X/* Note that I ignore the possible existence of a local color map. X * I'm told there aren't many files around that use them, and the spec X * says it's defined for future use. This could lead to an error X * reading some files. X */ X X/* Start reading the raster data. First we get the intial code size X * and compute decompressor constant values, based on this code size. X */ X X CodeSize = NEXTBYTE; X ClearCode = (1 << CodeSize); X EOFCode = ClearCode + 1; X FreeCode = FirstFree = ClearCode + 2; X X/* The GIF spec has it that the code size is the code size used to X * compute the above values is the code size given in the file, but the X * code size used in compression/decompression is the code size given in X * the file plus one. (thus the ++). X */ X X CodeSize++; X InitCodeSize = CodeSize; X MaxCode = (1 << CodeSize); X ReadMask = MaxCode - 1; X X/* Read the raster data. Here we just transpose it from the GIF array X * to the Raster array, turning it from a series of blocks into one long X * data stream, which makes life much easier for ReadCode(). X */ X X ptr1 = Raster; X do { X ch = ch1 = NEXTBYTE; X while (ch--) *ptr1++ = NEXTBYTE; X if ((Raster - ptr1) > 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 memory for the display */ X Image = (byte *) malloc(Width*Height); X fprintf(stderr,"%d,%d\n",Width,Height); X if (!Image) FatalError("not enough memory for Image %d bytes",Width*Height); X 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 get_color_map(); 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 *(Image + YC * BytesPerScanline + XC) = Index; X X if (!used[Index]) { used[Index]=1; numused++; } X X/* Update the X-coordinate, and if it overflows, update the Y-coordinate */ X X if (++XC == Width) { X X/* If a non-interlaced picture, just increment YC to the next scan line. X * If it's interlaced, deal with the interlace as described in the GIF X * spec. Put the decoded scan line out to the screen if we haven't gone X * past the bottom of it X */ X X XC = 0; X if (!Interlace) YC++; X else { X switch (Pass) { X case 0: X YC += 8; 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/*************************/ X Xmain(argc, argv) X int argc; X char *argv[]; X{ X char *fname; X int i,name,wno; X X expand = 1; strip = 0; nostrip = 0; X pausetime = 0; X X X name = FALSE; X bright=100; X X for (i=1;i<argc;i++) X { X fprintf(stderr,"%s\n",argv[i]); X if (strcmp(argv[i],"-b") == 0) X bright=atoi(argv[++i]); X else X { X if (name==TRUE) X Syntax(cmd); X else X { X fname=argv[i]; X name=TRUE; X } X } X } X fprintf(stderr,"image = %s\n",fname); X fprintf(stderr,"brightness = %d\n",bright); X X Enter_tools(); X Inq_displayed_vs(&vsno); X X LoadGIF(fname); X iWIDE = Width; iHIGH = Height; X fprintf(stderr,"width= %d,height = %d\n",iWIDE,iHIGH); X fprintf(stderr,"colour slots used = %d\n",numused); X Create_win_no_cstrip(vsno,100,100,100+Width,100+Height,&wno); X Display_win(wno); X X X DrawWindow (wno,Image,Width,Height); X sleep(10); X} X X X X X/***********************************/ XSyntax() X{ X printf("Usage: evgif [-b brightness] filename \n"); 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(wno,Image,width,height) X int wno; X byte *Image; X int width,height; X{ X byte *ptr=Image; X int x,y; X short *newimage,*new_ptr; X X newimage = (short *)malloc(width*height); X X new_ptr=newimage; X for (x=0;x<width*height;x++) X *new_ptr++ = *ptr++; X X new_ptr=newimage; X hidecursor(wno); X putpixelblock16(wno,0xffffffff,0,0,width-1,height-1,new_ptr); X showcursor(wno); X} X X X X XCheckDepth() X{ X} X END_OF_FILE if test 14173 -ne `wc -c <'evdisp.c'`; then echo shar: \"'evdisp.c'\" unpacked with wrong size! fi # end of 'evdisp.c' fi echo shar: End of shell archive. exit 0 -- |--------------------------------------------------| | Nik Simpson UUCP :uunet!ingr!swindon!st_nik!nik| | Senior Systems Engineer. Intergraph UK Ltd. | |--------------------------------------------------|