phillips@grads.cs.ubc.ca (George Phillips) (09/02/89)
Since I got more requests for this program than I could count on my
fingers, I decided to post it. Included is a GIF file viewer and
a viewer for 24 bit images as found on venera.isi.edu. These programs both
require a 24 bit deep display and have only been tried on a personal iris.
I hope they'll end up in the archives at vgr.brl.mil, but if not I'll
try and put them there myself. I look forward to your improvements.
George Phillips phillips@cs.ubc.ca {alberta,uw-beaver,uunet}!ubc-cs!phillips
#! /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: README Makefile igif.c decoder.c errs.h std.h vimg.c
# Wrapped by phillips@grads.cs.ubc.ca on Fri Sep 1 21:34:12 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(793 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
XThere are 2 programs here. igif will display GIF files on a personal
Xiris workstation. vimg displays 24 bit RGB files in the venera imglib
Xformat. Images in the imglib format can be found on venera.isi.edu.
X
XEach program uses very simple interfaces to graphics and windows. They
Xwork and are more or less directly transliterated from examples in the
Xgraphics documentation that came with our iris.
X
XBoth programs could use improvement, like getting rid of 24 bit mode or
Xadding scroll bars and so on. If you do make improvements, please send
Xthem to me (phillips@cs.ubc.ca {alberta,uw-beaver,uunet}!ubc-cs!phillips)
Xand maybe I can keep track of future versions.
X
XBut most of all, have fun displaying images.
X
XGeorge Phillips
XDepartment of Computer Science
XUniversity of British Columbia
END_OF_FILE
if test 793 -ne `wc -c <'README'`; then
echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(273 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
XCFLAGS=
X
X# If this doesn't work, try LIB=-Zg
XLIB=-lgl_s
X
Xall: igif vimg
X
Xigif: igif.o decoder.o
X cc -o igif igif.o decoder.o $(LIB)
X
Xdecoder.o: errs.h std.h
X
Xvimg: vimg.o
X cc -o vimg vimg.o $(LIB)
X
Xshar:
X shar README Makefile igif.c decoder.c errs.h std.h vimg.c >img.shar
END_OF_FILE
if test 273 -ne `wc -c <'Makefile'`; then
echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'igif.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'igif.c'\"
else
echo shar: Extracting \"'igif.c'\" \(6871 characters\)
sed "s/^X//" >'igif.c' <<'END_OF_FILE'
X/*
X * igif.c -- display a GIF image on the personal iris.
X *
X * usage: igif [ file.gif ]
X *
X * Will display the GIF file given as the first argument or a GIF file
X * read from standard input if no arguments are given.
X *
X * This is not a particularly pretty piece of code. This works on the
X * personal iris we have here, but has not been tested on other irises
X * or other SGI machines. It uses 24 bit RGB mode because that's all
X * I have looked into (plus it's easy :-). GIF images are pretty much
X * limited to 256 colours, so using some sort of colourmap mode should
X * be possible. Those with more experience could also modify the program
X * to display multiple GIF images with a single invocation.
X *
X * Copyright 1989 by George Phillips
X *
X * Permission is granted to freely distribute this program in whole or in
X * part provided you don't make money off it, you don't pretend that you
X * wrote it and that this notice accompanies the code.
X *
X * The GIF LZW decoder was written by someone else who's copyright notice
X * is contained in decode.c.
X *
X * George Phillips <phillips@grads.cs.ubc.ca>
X * Department of Computer Science
X * University of British Columbia
X */
X
X#include <stdio.h>
X#include <malloc.h>
X#include <gl.h>
X#include <device.h>
X
X#include "errs.h"
X
Xint bad_code_count;
XFILE* glob_fp;
Xstatic char* gif_name;
X
Xmain(argc, argv)
Xint argc;
Xchar* argv[];
X{
X FILE* fp;
X
X if (argc > 2) {
X fprintf(stderr, "Sorry, I can only do one GIF file at a time.\n");
X exit(1);
X }
X
X if (argc == 1) {
X gif_name = "standard input";
X gif_display(glob_fp = stdin);
X }
X else {
X char* p;
X char* lastslash;
X
X for (p = argv[1], lastslash = argv[1] - 1; *p; p++)
X if (*p == '/')
X lastslash = p;
X
X gif_name = lastslash + 1;
X
X if ((fp = fopen(argv[1], "r")) == NULL) {
X fprintf(stderr, "can't open '%s'\n", argv[1]);
X exit(1);
X }
X gif_display(glob_fp = fp);
X }
X screen_manage();
X exit(0);
X}
X
Xstatic int err = 0;
Xstatic long global[256];
Xstatic long local[256];
Xstatic long* cmap;
Xstatic long* screen;
Xstatic long* lineptr;
Xstatic int i_y;
Xstatic int pass;
Xstatic long* imagestart;
Xstatic int s_width;
Xstatic int s_height;
Xstatic int i_height;
Xstatic int is_interlaced;
X
X#define error(x) printf("%s at byte %d\n", x, ftell(fp)); return(0)
X#define reterr(x) if (err != 0) { error(x); }
X#define reteof() reterr("Unexpected EOF")
X#define skipbyte(x) getbyte(x); reteof()
X
Xgif_display(fp)
XFILE* fp;
X{
X static unsigned char buf[4096];
X int s_control, back;
X int i_top, i_left, i_width, i_control;
X int ch;
X int nc;
X int i, j;
X
X /* read signature */
X if (fread(buf, 3, 1, fp) != 1) {
X error("File too short");
X }
X
X if (strncmp(buf, "GIF", 3)) {
X error("Not a GIF file");
X }
X
X if (fread(buf, 3, 1, fp) != 1) {
X error("File too short");
X }
X
X if (strncmp(buf, "87a", 3)) {
X buf[3] = '\0';
X printf("unknown version '%s'\n", buf);
X return(0);
X }
X
X /* read screen descriptor */
X s_width = getword(fp); reteof();
X s_height = getword(fp); reteof();
X s_control = getbyte(fp); reteof();
X back = getbyte(fp); reteof();
X skipbyte(fp);
X
X if ((screen = (long*)malloc(sizeof(long) * s_width * s_height)) == NULL) {
X fprintf(stderr, "not enough memory for screen, bye!\n");
X exit(1);
X }
X /* sure, I should use bzero. Whatever */
X { register int i;
X for (i = 0; i < s_width * s_height; i++)
X screen[i] = 0;
X }
X prefsize(s_width, s_height);
X winopen(gif_name);
X RGBmode();
X gconfig();
X
X if (s_control & 128) { /* global colour map */
X if (fread(buf, (2 << (s_control & 7)) * 3, 1, fp) != 1) {
X error("EOF in global colourmap");
X }
X gif2rgb(buf, global, 2 << (s_control & 7));
X }
X
X for (;;) {
X ch = getbyte(fp);
X reterr("no terminator");
X switch (ch) {
X case ',': /* image follows */
X i_left = getword(fp); reteof();
X i_top = getword(fp); reteof();
X i_width = getword(fp); reteof();
X i_height = getword(fp); reteof();
X i_control = getbyte(fp); reteof();
X is_interlaced = i_control & 64;
X nc = 2 << (s_control & 7);
X cmap = global;
X if (i_control & 128) { /* local colour map */
X if (fread(buf, (2 << (i_control & 7)) * 3, 1, fp) != 1) {
X error("EOF in local colourmap");
X }
X nc = 2 << (i_control & 7);
X gif2rgb(buf, local, nc);
X cmap = local;
X }
X bad_code_count = 0;
X imagestart = lineptr = screen + (s_width * i_top) + i_left +
X (i_height - 1) * s_width;
X i_y = 0;
X pass = 0;
X decoder(i_width);
X /* ignore rest of blocks used by decoder */
X skipblocks(fp); reterr("Bad block in image");
X break;
X case ';': /* terminator ... */
X return(0);
X case '!': /* extension block */
X skipbyte(fp); /* function code */
X skipblocks(fp); reterr("Bad block in extension block");
X break;
X default:
X /* Supposed to ignore any unknown characters up to the image
X * separator, but I prefer to be tight about these things because
X * there are many corrupt images out there.
X */
X printf("Unknown block type '%c' (%d) at byte %d\n",
X ch, ch, ftell(fp));
X return(0);
X }
X }
X}
X
X/* Convert the GIF colourmap into long rgb components which can be directly
X * plunked into an lrect.
X *
X * GIF colourmap is a byte stream: rgbrgbrgb
X * lrect format is in 4 byte words: abgr abgr abgr
X * (the a is alpha, which should be zero)
X */
Xgif2rgb(g, r, len)
Xchar* g;
Xlong* r;
Xint len;
X{
X register int i;
X register int j;
X
X for (i = j = 0; i < len; i++, j += 3)
X r[i] = g[j] | (g[j+1] << 8) | (g[j+2] << 16);
X}
X
Xstatic int pass_width[] = { 8, 8, 4, 2 };
Xstatic int pass_start[] = { 0, 4, 2, 1 };
X
Xout_line(pixel, linelen)
Xunsigned char* pixel;
Xint linelen;
X{
X register int i;
X
X for (i = 0; i < linelen; i++)
X lineptr[i] = cmap[pixel[i]];
X
X if (!is_interlaced) {
X lineptr -= s_width;
X }
X else {
X lineptr -= pass_width[pass] * s_width;
X i_y += pass_width[pass];
X if (i_y >= i_height) {
X pass++;
X i_y = pass_start[pass];
X lineptr = imagestart - pass_start[pass] * s_width;
X }
X }
X}
X
Xint get_byte()
X{
X return(getbyte(glob_fp));
X}
X
Xint getbyte(fp)
XFILE* fp;
X{
X int ch;
X
X err = 0;
X if ((ch = fgetc(fp)) == EOF) {
X err = 1;
X return(READ_ERROR);
X }
X return(ch & 255);
X}
X
Xint getword(fp)
XFILE* fp;
X{
X int c1, c2;
X
X err = 0;
X if ((c1 = fgetc(fp)) == EOF) {
X err = 1;
X return(0);
X }
X if ((c2 = fgetc(fp)) == EOF) {
X err = 1;
X return(0);
X }
X return(((c2 & 255) << 8) | (c1 & 255));
X}
X
Xskipblocks(fp)
XFILE* fp;
X{
X int len;
X static char buf[256];
X
X err = 0;
X
X for (;;) {
X len = getbyte(fp);
X reterr("EOF in blocks");
X
X if (len == 0)
X return(0);
X
X if (fread(buf, len, 1, fp) != 1) {
X puts("EOF in blocks");
X err = 1;
X return(0);
X }
X }
X}
X
Xscreen_manage()
X{
X lrectwrite(0, 0, s_width - 1, s_height - 1, screen);
X
X qdevice(REDRAW);
X qdevice(PIECECHANGE);
X qdevice(WINQUIT);
X
X while (1) {
X short data;
X
X switch (qread(&data)) {
X case REDRAW:
X case PIECECHANGE:
X lrectwrite(0, 0, s_width - 1, s_height - 1, screen);
X break;
X case WINQUIT:
X exit(0);
X default:
X break;
X }
X }
X}
X
END_OF_FILE
if test 6871 -ne `wc -c <'igif.c'`; then
echo shar: \"'igif.c'\" unpacked with wrong size!
fi
# end of 'igif.c'
fi
if test -f 'decoder.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'decoder.c'\"
else
echo shar: Extracting \"'decoder.c'\" \(12570 characters\)
sed "s/^X//" >'decoder.c' <<'END_OF_FILE'
X/* DECODE.C - An LZW decoder for GIF
X * Copyright (C) 1987, by Steven A. Bennett
X *
X * Permission is given by the author to freely redistribute and include
X * this code in any program as long as this credit is given where due.
X *
X * In accordance with the above, I want to credit Steve Wilhite who wrote
X * the code which this is heavily inspired by...
X *
X * GIF and 'Graphics Interchange Format' are trademarks (tm) of
X * Compuserve, Incorporated, an H&R Block Company.
X *
X * Release Notes: This file contains a decoder routine for GIF images
X * which is similar, structurally, to the original routine by Steve Wilhite.
X * It is, however, somewhat noticably faster in most cases.
X *
X * GWP -- if GINFO if defined, it will use a global variable and
X * stdio routines in place of most of the get_byte calls to speed
X * things along.
X */
X
X#define GINFO
X
X#ifdef GINFO
X
X#include <stdio.h>
Xextern FILE* glob_fp;
X
X#endif
X
X#include "std.h"
X#include "errs.h"
X
XIMPORT TEXT *malloc(); /* Standard C library allocation */
X
X/* IMPORT INT get_byte()
X *
X * - This external (machine specific) function is expected to return
X * either the next byte from the GIF file, or a negative number, as
X * defined in ERRS.H.
X */
XIMPORT INT get_byte();
X
X/* IMPORT INT out_line(pixels, linelen)
X * UBYTE pixels[];
X * INT linelen;
X *
X * - This function takes a full line of pixels (one byte per pixel) and
X * displays them (or does whatever your program wants with them...). It
X * should return zero, or negative if an error or some other event occurs
X * which would require aborting the decode process... Note that the length
X * passed will almost always be equal to the line length passed to the
X * decoder function, with the sole exception occurring when an ending code
X * occurs in an odd place in the GIF file... In any case, linelen will be
X * equal to the number of pixels passed...
X */
XIMPORT INT out_line();
X
X/* IMPORT INT bad_code_count;
X *
X * This value is the only other global required by the using program, and
X * is incremented each time an out of range code is read by the decoder.
X * When this value is non-zero after a decode, your GIF file is probably
X * corrupt in some way...
X */
XIMPORT INT bad_code_count;
X
X#ifndef GINFO
X#define NULL 0L
X#endif
X
X#define MAX_CODES 4095
X
X/* Static variables */
XLOCAL WORD curr_size; /* The current code size */
XLOCAL WORD clear; /* Value for a clear code */
XLOCAL WORD ending; /* Value for a ending code */
XLOCAL WORD newcodes; /* First available code */
XLOCAL WORD top_slot; /* Highest code for current size */
XLOCAL WORD slot; /* Last read code */
X
X/* The following static variables are used
X * for seperating out codes
X */
XLOCAL WORD navail_bytes = 0; /* # bytes left in block */
XLOCAL WORD nbits_left = 0; /* # bits left in current byte */
XLOCAL UTINY b1; /* Current byte */
XLOCAL UTINY byte_buff[257]; /* Current block */
XLOCAL UTINY *pbytes; /* Pointer to next byte in block */
X
XLOCAL LONG code_mask[13] = {
X 0,
X 0x0001, 0x0003,
X 0x0007, 0x000F,
X 0x001F, 0x003F,
X 0x007F, 0x00FF,
X 0x01FF, 0x03FF,
X 0x07FF, 0x0FFF
X };
X
X
X/* This function initializes the decoder for reading a new image.
X */
XLOCAL WORD init_exp(size)
X WORD size;
X {
X curr_size = size + 1;
X top_slot = 1 << curr_size;
X clear = 1 << size;
X ending = clear + 1;
X slot = newcodes = ending + 1;
X navail_bytes = nbits_left = 0;
X return(0);
X }
X
X/* get_next_code()
X * - gets the next code from the GIF file. Returns the code, or else
X * a negative number in case of file errors...
X */
XLOCAL WORD get_next_code()
X {
X WORD i, x;
X ULONG ret;
X
X if (nbits_left == 0)
X {
X if (navail_bytes <= 0)
X {
X
X /* Out of bytes in current block, so read next block
X */
X pbytes = byte_buff;
X#ifdef GINFO
X if ((navail_bytes = fgetc(glob_fp)) == EOF)
X return(READ_ERROR);
X#else
X if ((navail_bytes = get_byte()) < 0)
X return(navail_bytes);
X#endif
X else if (navail_bytes)
X {
X#ifdef GINFO
X if (fread(byte_buff, navail_bytes, 1, glob_fp) != 1)
X return(READ_ERROR);
X#else
X for (i = 0; i < navail_bytes; ++i)
X {
X if ((x = get_byte()) < 0)
X return(x);
X byte_buff[i] = x;
X }
X#endif
X }
X }
X b1 = *pbytes++;
X nbits_left = 8;
X --navail_bytes;
X }
X
X ret = b1 >> (8 - nbits_left);
X while (curr_size > nbits_left)
X {
X if (navail_bytes <= 0)
X {
X
X /* Out of bytes in current block, so read next block
X */
X pbytes = byte_buff;
X#ifdef GINFO
X if ((navail_bytes = fgetc(glob_fp)) == EOF)
X return(READ_ERROR);
X#else
X if ((navail_bytes = get_byte()) < 0)
X return(navail_bytes);
X#endif
X else if (navail_bytes)
X {
X#ifdef GINFO
X if (fread(byte_buff, navail_bytes, 1, glob_fp) != 1)
X return(READ_ERROR);
X#else
X for (i = 0; i < navail_bytes; ++i)
X {
X if ((x = get_byte()) < 0)
X return(x);
X byte_buff[i] = x;
X }
X#endif
X }
X }
X b1 = *pbytes++;
X ret |= b1 << nbits_left;
X nbits_left += 8;
X --navail_bytes;
X }
X nbits_left -= curr_size;
X ret &= code_mask[curr_size];
X return((WORD)(ret));
X }
X
X
X/* The reason we have these seperated like this instead of using
X * a structure like the original Wilhite code did, is because this
X * stuff generally produces significantly faster code when compiled...
X * This code is full of similar speedups... (For a good book on writing
X * C for speed or for space optomisation, see Efficient C by Tom Plum,
X * published by Plum-Hall Associates...)
X */
XLOCAL UTINY stack[MAX_CODES + 1]; /* Stack for storing pixels */
XLOCAL UTINY suffix[MAX_CODES + 1]; /* Suffix table */
XLOCAL UWORD prefix[MAX_CODES + 1]; /* Prefix linked list */
X
X/* WORD decoder(linewidth)
X * WORD linewidth; * Pixels per line of image *
X *
X * - This function decodes an LZW image, according to the method used
X * in the GIF spec. Every *linewidth* "characters" (ie. pixels) decoded
X * will generate a call to out_line(), which is a user specific function
X * to display a line of pixels. The function gets it's codes from
X * get_next_code() which is responsible for reading blocks of data and
X * seperating them into the proper size codes. Finally, get_byte() is
X * the global routine to read the next byte from the GIF file.
X *
X * It is generally a good idea to have linewidth correspond to the actual
X * width of a line (as specified in the Image header) to make your own
X * code a bit simpler, but it isn't absolutely necessary.
X *
X * Returns: 0 if successful, else negative. (See ERRS.H)
X *
X */
X
XWORD decoder(linewidth)
X WORD linewidth;
X {
X FAST UTINY *sp, *bufptr;
X UTINY *buf;
X FAST WORD code, fc, oc, bufcnt;
X WORD c, size, ret;
X
X /* Initialize for decoding a new image...
X */
X if ((size = get_byte()) < 0)
X return(size);
X if (size < 2 || 9 < size)
X return(BAD_CODE_SIZE);
X init_exp(size);
X
X /* Initialize in case they forgot to put in a clear code.
X * (This shouldn't happen, but we'll try and decode it anyway...)
X */
X oc = fc = 0;
X
X /* Allocate space for the decode buffer
X */
X if ((buf = (UTINY *)malloc(linewidth + 1)) == NULL)
X return(OUT_OF_MEMORY);
X
X /* Set up the stack pointer and decode buffer pointer
X */
X sp = stack;
X bufptr = buf;
X bufcnt = linewidth;
X
X /* This is the main loop. For each code we get we pass through the
X * linked list of prefix codes, pushing the corresponding "character" for
X * each code onto the stack. When the list reaches a single "character"
X * we push that on the stack too, and then start unstacking each
X * character for output in the correct order. Special handling is
X * included for the clear code, and the whole thing ends when we get
X * an ending code.
X */
X while ((c = get_next_code()) != ending)
X {
X
X /* If we had a file error, return without completing the decode
X */
X if (c < 0)
X {
X free(buf);
X return(0);
X }
X
X /* If the code is a clear code, reinitialize all necessary items.
X */
X if (c == clear)
X {
X curr_size = size + 1;
X slot = newcodes;
X top_slot = 1 << curr_size;
X
X /* Continue reading codes until we get a non-clear code
X * (Another unlikely, but possible case...)
X */
X while ((c = get_next_code()) == clear)
X ;
X
X /* If we get an ending code immediately after a clear code
X * (Yet another unlikely case), then break out of the loop.
X */
X if (c == ending)
X break;
X
X /* Finally, if the code is beyond the range of already set codes,
X * (This one had better NOT happen... I have no idea what will
X * result from this, but I doubt it will look good...) then set it
X * to color zero.
X */
X if (c >= slot)
X c = 0;
X
X oc = fc = c;
X
X /* And let us not forget to put the char into the buffer... And
X * if, on the off chance, we were exactly one pixel from the end
X * of the line, we have to send the buffer to the out_line()
X * routine...
X */
X *bufptr++ = c;
X if (--bufcnt == 0)
X {
X if ((ret = out_line(buf, linewidth)) < 0)
X {
X free(buf);
X return(ret);
X }
X bufptr = buf;
X bufcnt = linewidth;
X }
X }
X else
X {
X
X /* In this case, it's not a clear code or an ending code, so
X * it must be a code code... So we can now decode the code into
X * a stack of character codes. (Clear as mud, right?)
X */
X code = c;
X
X /* Here we go again with one of those off chances... If, on the
X * off chance, the code we got is beyond the range of those already
X * set up (Another thing which had better NOT happen...) we trick
X * the decoder into thinking it actually got the last code read.
X * (Hmmn... I'm not sure why this works... But it does...)
X */
X if (code >= slot)
X {
X if (code > slot)
X ++bad_code_count;
X code = oc;
X *sp++ = fc;
X }
X
X /* Here we scan back along the linked list of prefixes, pushing
X * helpless characters (ie. suffixes) onto the stack as we do so.
X */
X while (code >= newcodes)
X {
X *sp++ = suffix[code];
X code = prefix[code];
X }
X
X /* Push the last character on the stack, and set up the new
X * prefix and suffix, and if the required slot number is greater
X * than that allowed by the current bit size, increase the bit
X * size. (NOTE - If we are all full, we *don't* save the new
X * suffix and prefix... I'm not certain if this is correct...
X * it might be more proper to overwrite the last code...
X */
X *sp++ = code;
X if (slot < top_slot)
X {
X suffix[slot] = fc = code;
X prefix[slot++] = oc;
X oc = c;
X }
X if (slot >= top_slot)
X if (curr_size < 12)
X {
X top_slot <<= 1;
X ++curr_size;
X }
X
X /* Now that we've pushed the decoded string (in reverse order)
X * onto the stack, lets pop it off and put it into our decode
X * buffer... And when the decode buffer is full, write another
X * line...
X */
X while (sp > stack)
X {
X *bufptr++ = *(--sp);
X if (--bufcnt == 0)
X {
X if ((ret = out_line(buf, linewidth)) < 0)
X {
X free(buf);
X return(ret);
X }
X bufptr = buf;
X bufcnt = linewidth;
X }
X }
X }
X }
X ret = 0;
X if (bufcnt != linewidth)
X ret = out_line(buf, (linewidth - bufcnt));
X free(buf);
X return(ret);
X }
X
END_OF_FILE
if test 12570 -ne `wc -c <'decoder.c'`; then
echo shar: \"'decoder.c'\" unpacked with wrong size!
fi
# end of 'decoder.c'
fi
if test -f 'errs.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'errs.h'\"
else
echo shar: Extracting \"'errs.h'\" \(366 characters\)
sed "s/^X//" >'errs.h' <<'END_OF_FILE'
X/* Various error codes used by decoder
X * and my own routines... It's okay
X * for you to define whatever you want,
X * as long as it's negative... It will be
X * returned intact up the various subroutine
X * levels...
X */
X#define OUT_OF_MEMORY -10
X#define BAD_CODE_SIZE -20
X#define READ_ERROR -1
X#define WRITE_ERROR -2
X#define OPEN_ERROR -3
X#define CREATE_ERROR -4
X
END_OF_FILE
if test 366 -ne `wc -c <'errs.h'`; then
echo shar: \"'errs.h'\" unpacked with wrong size!
fi
# end of 'errs.h'
fi
if test -f 'std.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'std.h'\"
else
echo shar: Extracting \"'std.h'\" \(278 characters\)
sed "s/^X//" >'std.h' <<'END_OF_FILE'
X/* STD.H - My own standard header file...
X */
X
X#define LOCAL static
X#define IMPORT extern
X
X#define FAST register
X
Xtypedef short WORD;
Xtypedef unsigned short UWORD;
Xtypedef char TEXT;
Xtypedef unsigned char UTINY;
Xtypedef long LONG;
Xtypedef unsigned long ULONG;
Xtypedef int INT;
X
END_OF_FILE
if test 278 -ne `wc -c <'std.h'`; then
echo shar: \"'std.h'\" unpacked with wrong size!
fi
# end of 'std.h'
fi
if test -f 'vimg.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'vimg.c'\"
else
echo shar: Extracting \"'vimg.c'\" \(4677 characters\)
sed "s/^X//" >'vimg.c' <<'END_OF_FILE'
X/*
X * vimg -- display a venera imglib 24 bit image.
X *
X * usage: vimg picture
X * or
X * vimg picture.a
X *
X * This program will display the 24 bit RGB images which can be ftp'ed from
X * venera.isi.edu. The format is very simple. Using some base name (like
X * "picture"), the following files are relevant:
X *
X * picture.a -- contains width and height information
X * picture.r -- red component of image (1 byte per pixel)
X * picture.g -- green component of image (ditto)
X * picture.b -- blue component of image (ditto)
X *
X * The program will either take a base name or the .a version. Also, if any of
X * the files are compressed, it will run uncompress -c on them. In other words,
X * it will also look for .r.Z, .b.Z and .g.Z files. I'm not really sure what
X * the standard iris setup is, but if you don't have /usr/bsd in you path,
X * it won't work. Either add it to your path or change "uncompress" to
X * /usr/bsd/uncompress in the program.
X *
X * BUGS:
X *
X * If image is bigger than 1024 on any side, then I should clip it. But I
X * don't since it gives me the urge for scrollbars...
X *
X * It seems if any optimization is turned on, then it will break if any of the
X * red, green or blue components (.r, .g or .b files) is _not_ compressed.
X *
X *
X * Copyright 1989 by George Phillips
X *
X * Permission is granted to freely distribute this program in whole or in
X * part provided you don't make money off it, you don't pretend that you
X * wrote it and that this notice accompanies the code.
X *
X * George Phillips <phillips@grads.cs.ubc.ca>
X * Department of Computer Science
X * University of British Columbia
X */
X
X#include <gl.h>
X#include <stdio.h>
X#include <malloc.h>
X#include <device.h>
X
Xint width;
Xint height;
X
Xlong* img;
Xchar* buf;
X
Xmain(argc, argv)
Xint argc;
Xchar* argv[];
X{
X int i;
X FILE* fp;
X char att[256], red[256], green[256], blue[256];
X char* myalloc();
X FILE* myopen();
X char* p;
X char* lastdot;
X char* shortname;
X char ch;
X char dimen[256];
X
X if (argc != 2) {
X fprintf(stderr, "usage: vimg basename OR vimg basename.a\n");
X exit(1);
X }
X
X shortname = argv[1] - 1;
X lastdot = NULL;
X for (p = argv[1]; *p; p++)
X if (*p == '.')
X lastdot = p;
X else if (*p == '/')
X shortname = p;
X
X shortname++;
X
X if (lastdot != NULL && !strcmp(lastdot, ".a"))
X *lastdot = '\0';
X
X sprintf(att, "%s.a", argv[1]);
X fp = myopen(att);
X fgets(dimen, 256, fp);
X ch = dimen[4];
X dimen[4] = '\0';
X width = atoi(dimen);
X dimen[4] = ch;
X dimen[8] = '\0';
X height = atoi(dimen + 4);
X
X printf("%s: width = %d, height = %d\n", argv[1], width, height);
X myclose();
X
X img = (long*)myalloc(sizeof(long) * width * height);
X buf = myalloc(width);
X
X for (i = 0; i < width * height; i++)
X img[i] = 0;
X
X sprintf(red, "%s.r", argv[1]);
X printf("reading %s\n", red);
X getcom(myopen(red), 0);
X myclose();
X
X sprintf(green, "%s.g", argv[1]);
X printf("reading %s\n", green);
X getcom(myopen(green), 8);
X myclose();
X
X sprintf(blue, "%s.b", argv[1]);
X printf("reading %s\n", blue);
X getcom(myopen(blue), 16);
X myclose();
X
X prefsize(width, height);
X winopen(shortname);
X RGBmode();
X gconfig();
X lrectwrite(0, 0, width - 1, height - 1, img);
X
X qdevice(REDRAW);
X qdevice(PIECECHANGE);
X qdevice(WINQUIT);
X
X while (1) {
X short data;
X
X switch (qread(&data)) {
X case REDRAW:
X case PIECECHANGE:
X lrectwrite(0, 0, width - 1, height - 1, img);
X break;
X case WINQUIT:
X exit(0);
X default:
X break;
X }
X }
X}
X
Xgetcom(fp, shift)
XFILE* fp;
Xint shift;
X{
X FILE* fp;
X long* line;
X int i;
X
X line = img + width * height - width;
X while (fread(buf, width, 1, fp) == 1) {
X if (line < img) {
X printf("extra data, oh well, ignored\n");
X break;
X }
X for (i = 0; i < width; i++)
X line[i] |= (buf[i] << shift);
X line -= width;
X }
X}
X
Xfatal(s)
Xchar* s;
X{
X fprintf(stderr, "%s\n", s);
X exit(1);
X}
X
X/* open a file, or a pipe to uncompress -c if it is compressed */
X/* myclose is very hardwired, but will work as long as only 1 file */
X/* is opened by myopen at a time */
X
Xint ftype;
XFILE* glob_fp;
X
XFILE* myopen(fname)
Xchar* fname;
X{
X FILE* fp;
X char cmd[256];
X
X if ((fp = fopen(fname, "r")) == NULL) {
X sprintf(cmd, "%s.Z", fname);
X if (access(cmd, 4) < 0) {
X fprintf(stderr, "Can't open %s or %s.Z\n", fname, fname);
X exit(1);
X }
X sprintf(cmd, "uncompress -c %s.Z", fname);
X if ((fp = popen(cmd, "r")) == NULL) {
X fprintf(stderr, "can't open %s or %s.Z\n", fname, fname);
X exit(1);
X }
X ftype = 2;
X }
X else
X ftype = 1;
X return(glob_fp = fp);
X}
X
Xmyclose()
X{
X if (ftype == 1)
X fclose(glob_fp);
X else
X pclose(glob_fp);
X}
X
X/* malloc or die! */
Xchar* myalloc(size)
Xint size;
X{
X char* p;
X
X if ((p = malloc(size)) == NULL) {
X fprintf(stderr, "out of memory\n");
X exit(1);
X }
X return(p);
X}
END_OF_FILE
if test 4677 -ne `wc -c <'vimg.c'`; then
echo shar: \"'vimg.c'\" unpacked with wrong size!
fi
# end of 'vimg.c'
fi
echo shar: End of shell archive.
exit 0bobf@BLUMIRIS.CHEM.UMR.EDU ("Robert B. Funchess") (05/05/90)
As stated before, one is available for anonymous FTP from here. The address,however, has been changed: clciris.chem.umr.edu (131.151.14.48). -- Bob Funchess bobf@blumiris.chem.umr.edu Chemistry Dept. University of Missouri - Rolla