home *** CD-ROM | disk | FTP | other *** search
- /*
- * read a GIF file. decode and stuff into raster array and color maps.
- *
- * this was adopted from PBMplus.
- */
-
- static char *sccsid = "@(#) readgif.c 1.1 91/6/3 rosenkra\0\0 ";
-
- #include <stdio.h>
- #include <osbind.h>
- #include "mgif.h"
-
-
- #ifdef LOCAL
- #undef LOCAL
- #endif
- #ifdef GLOBAL
- #undef GLOBAL
- #endif
- #define LOCAL /*static*/
- #define GLOBAL
- #define reg_t register
-
- #define ENDFILE(f) _Eof != 0 /* to track EOF on input file */
-
-
- /*
- * globals for GIF decode procedure (only needed in this file,
- * should actually be static)
- */
- LOCAL ulong_t _BitOffset = 0; /* Bit Offset of next code */
- LOCAL int _XC = 0; /* Output X and Y coords of current pixel */
- LOCAL int _YC = 0;
- LOCAL int _HEIGHT; /* image size */
- LOCAL int _WIDTH;
- LOCAL int _Pass = 0; /* Used by output routine if interlaced pic */
- LOCAL int _OutCount = 0; /* Decompressor output 'stack count' */
- LOCAL int _Interlace; /* flag for interlaced image */
- LOCAL int _CodeSize; /* Code size, read from GIF header */
- LOCAL int _InitCodeSize; /* Start code size, used during Clear */
- LOCAL int _Code; /* Value returned by read_code */
- LOCAL int _MaxCode; /* limit value for current code size */
- LOCAL int _ClearCode; /* GIF clear code */
- LOCAL int _EOFCode; /* GIF end-of-information code */
- LOCAL int _CurCode; /* Decompressor variables */
- LOCAL int _OldCode;
- LOCAL int _InCode;
- LOCAL int _FirstFree; /* First free code, gen'd per GIF spec */
- LOCAL int _FreeCode; /* Decompr, next free slot in hash table */
- LOCAL int _FinChar; /* Decompr variable */
- LOCAL int _BitMask; /* AND mask for data size */
- LOCAL int _ReadMask; /* Code AND mask for cur code size */
- LOCAL int _Prefix[HASHSIZ];/* hash table used by the decompr */
- LOCAL int _Suffix[HASHSIZ];
- LOCAL int _OutCode[OUTSIZ];/* output array used by the decompr */
- LOCAL int _BitsPerPixel; /* image attributes */
- LOCAL int _ColorMapSize;
- LOCAL int _ImageNum = 0; /* if multi-image file (not used) */
- LOCAL int _Eof = 0; /* EOF on input flag (_GETC) */
-
-
- /*
- * local functions
- */
- LOCAL int _ReadRaster ();
- LOCAL int _ReadCode ();
- LOCAL int _AddPixel ();
- LOCAL void _InstCMap ();
- LOCAL int _ScanSD ();
- LOCAL void _SkipEB ();
- LOCAL int _ScanID ();
- LOCAL void _ScanCM ();
- LOCAL int _ScanMAGIC ();
- LOCAL int _GetKey ();
- LOCAL int _GETC ();
-
-
-
- /*------------------------------*/
- /* ReadGIF */
- /*------------------------------*/
- GLOBAL int ReadGIF (fname, codedgif, raster, scrninf, id, colormap, opt)
- char *fname; /* file name with .GIF */
- uchar_t *codedgif; /* place to put raw raster data, coded */
- uchar_t *raster; /* place to put raster */
- screen_t *scrninf; /* image info struct */
- image_t *id; /* image id struct */
- uchar_t colormap[][3]; /* color map */
- int opt; /* SILENT, INQUIRE, VERBOSE, NORMAL */
- {
-
- /*
- * read a GIF87a image from open file infile into raster array.
- * the array will contain index into color table. caller supplies
- * all needed space (raster array, headers, color map, etc). colormap
- * will contain either global or local color map, depending on image.
- *
- * The following illustrates the general file layout of .GIF files:
- *
- * +-----------------------+
- * | +-------------------+ |
- * | | GIF Signature | | GIF87a (required)
- * | +-------------------+ |
- * | +-------------------+ |
- * | | Screen Descriptor | | 7 bytes, ends with 00 (required)
- * | +-------------------+ |
- * | +-------------------+ |
- * | | Global Color Map | | 3*2^bits bytes (optional but
- * | +-------------------+ | usual)
- * | +-------------------+ |
- * | | Extension Block | | ! (optional)
- * | +-------------------+ |
- * . . . . . .
- * | +-------------------+ |
- * | | Image Descriptor | | , (required)
- * | +-------------------+ |
- * | +-------------------+ |
- * | | Local Color Map | | (optional)
- * | +-------------------+ |
- * | +-------------------+ |
- * | | Raster Data | | (required)
- * | +-------------------+ |
- * . . . . . .
- * |- GIF Terminator -| (required)
- * +-----------------------+
- */
-
- static int firsttime = 1;
-
- uchar_t lcm[MAPSIZ][3];
- uchar_t gcm[MAPSIZ][3];
- int infile;
- reg_t long ii;
- int flag;
-
-
-
- /*
- * open file...
- */
- if (opt != SILENT)
- {
- printf (" \n");
- printf ("\nEnter ReadGIF\n\n");
- printf ("Open file: %s\n", fname);
- }
- if ((infile = openb (fname, 0)) < 0)
- {
- return (EGIFFILE);
- }
-
-
-
- /*
- * get ready for next image by clearing variables, tables
- */
- _BitOffset = 0;
- _XC = 0;
- _YC = 0;
- _Pass = 0;
- _OutCount = 0;
- _CodeSize = 0;
- _InitCodeSize = 0;
- _Code = 0;
- _MaxCode = 0;
- _ClearCode = 0;
- _EOFCode = 0;
- _CurCode = 0;
- _OldCode = 0;
- _InCode = 0;
- _FirstFree = 0;
- _FreeCode = 0;
- _FinChar = 0;
- _BitMask = 0;
- _ReadMask = 0;
- _Eof = 0;
-
- for (ii = 0; ii < HASHSIZ; ii++)
- {
- _Prefix[ii] = 0;
- _Suffix[ii] = 0;
- }
-
- for (ii = 0; ii < OUTSIZ; ii++)
- _OutCode[ii] = 0;
-
- if (firsttime)
- firsttime = 0;
- else
- {
- /* these take a while to do */
- if (opt != SILENT)
- printf ("\nResetting tables\n");
-
- for (ii = 0; ii < MAXRAW; ii++)
- codedgif[ii] = 0;
-
- for (ii = 0; ii < MAXIMG; ii++)
- raster[ii] = 0;
-
- }
-
-
- /*
- * make sure it is a gif file (file header is this...)
- */
- if (opt != SILENT)
- printf ("\nRead MAGIC\n");
- if (!_ScanMAGIC (infile, "GIF87a", opt))
- {
- close (infile);
- return (EGIFMAGIC);
- }
-
-
-
- /*
- * read screen descriptor...
- */
- if (opt != SILENT)
- printf ("\nRead screen descriptor\n");
- if (!_ScanSD (infile, scrninf, opt))
- {
- close (infile);
- return (EGIFSDESC);
- }
- if (opt != SILENT)
- {
- printf (" Screen width (s_dx) = %d\n", (int) (scrninf->s_dx));
- printf (" Screen height (s_dy) = %d\n", (int) (scrninf->s_dy));
- printf (" Global map? (s_gcm) = %d\n", (int) (scrninf->s_gcm));
- printf (" Color resolution (s_cr) = %d\n", (int) (scrninf->s_cr));
- printf (" Bits/pixel (s_bits) = %d\n", (int) (scrninf->s_bits));
- printf (" Num colors (s_colors) = %d\n", (int) (scrninf->s_colors));
- printf (" Background color (s_bgnd) = %d\n", (int) (scrninf->s_bgnd));
- }
-
-
-
- /*
- * read global color map if we have one...
- */
- if (scrninf->s_gcm)
- {
- if (opt != SILENT)
- printf ("\nRead global color map\n");
- _ScanCM (infile, scrninf->s_colors, (char *) gcm, opt);
- }
- else
- {
- if (opt != SILENT)
- printf ("\nNo global color map\n");
- }
-
-
- /*
- * read image descriptor
- */
- _ImageNum++;
- if (opt != SILENT)
- printf ("\nRead image descriptor, image: %d\n", _ImageNum);
-
- flag = _ScanID (infile, id, opt);
-
- if (flag == 0)
- {
- return (EGIFEOF);
- }
- if (flag == 1)
- return (EGIFIDBAD);
-
- if (opt != SILENT)
- {
- printf (" Image left (i_x) = %d\n", (int) (id->i_x));
- printf (" Image top (i_y) = %d\n", (int) (id->i_y));
- printf (" Image width (i_dx) = %d\n", (int) (id->i_dx));
- printf (" Image height (i_dy) = %d\n", (int) (id->i_dy));
- printf (" Use local map? (i_gcm) = %d\n", (int) (id->i_gcm));
- printf (" Interlaced? (i_intlace) = %d\n", (int) (id->i_intlace));
- printf (" Bits per pixel (i_bits) = %d\n", (int) (id->i_bits));
- printf (" Number colors (i_colors) = %d\n", (int) (id->i_colors));
- printf (" (If no local color map, use screen bits and colors)\n");
- }
-
-
- /*
- * read local color map, if there
- */
- if (id->i_gcm)
- {
- if (opt != SILENT)
- printf ("\nRead local color map\n");
- _ScanCM (infile, id->i_colors, (char *) lcm, opt);
- _InstCMap (id->i_colors, (uchar_t *) lcm, colormap, opt);
- }
- else
- {
- if (opt != SILENT)
- printf ("\nUse global color map\n");
- _InstCMap (scrninf->s_colors, (uchar_t *) gcm, colormap, opt);
-
- /*
- * make sure to reset these from global info...
- */
- id->i_colors = scrninf->s_colors;
- id->i_bits = scrninf->s_bits;
- }
-
- _BitsPerPixel = id->i_bits;
- _ColorMapSize = 1 << _BitsPerPixel;
- _BitMask = _ColorMapSize - 1;
- _WIDTH = id->i_dx;
- _HEIGHT = id->i_dy;
- _Interlace = id->i_intlace;
-
- if (opt != SILENT)
- {
- printf (" BitsPerPixel = %d\n", _BitsPerPixel);
- printf (" ColorMapSize = %d\n", _ColorMapSize);
- printf (" BitMask = %04x\n", _BitMask);
- printf (" WIDTH = %d\n", _WIDTH);
- printf (" HEIGHT = %d\n", _HEIGHT);
- printf (" Interlace = %d\n", _Interlace);
- }
-
-
-
- /*
- * check size vs internal buffer...
- */
- if (((long) _WIDTH * (long) _HEIGHT) > MAXIMG)
- {
- return (EGIFBIG);
- }
-
-
-
- /*
- * if just an inquiry, quit now...
- */
- if (opt == INQUIRE)
- return (EGIFOK);
-
-
-
- /*
- * read raster data
- */
- if (_ReadRaster (infile, codedgif, scrninf, raster, opt))
- {
- return (EGIFRAST);
- }
-
- /* at this point, Raster[] contains colormap indices at each pixel */
-
- return (EGIFOK);
- }
-
-
-
-
- /*------------------------------*/
- /* _ReadRaster */
- /*------------------------------*/
- LOCAL int _ReadRaster (infile, codedgif, scrninf, raster, opt)
- int infile;
- uchar_t *codedgif;
- screen_t *scrninf;
- uchar_t *raster;
- int opt;
- {
-
- /* externals: _CodeSize,_Eof,_ClearCode,_EOFCode,_FreeCode,_FirstFree,
- _InitCodeSize,_MaxCode,_ReadMask,... */
-
- /*
- * Decode a raster image
- */
-
- uchar_t *pcoded;
- uchar_t *praster;
- uint_t ch;
- uint_t ch1;
- int i;
- int nread;
-
-
-
-
- /*
- * Start reading the raster data. First we get the intial code size
- * and compute decompressor constant values, based on this code size.
- */
- if (opt != SILENT)
- printf ("\nRead raster data\n");
-
- _CodeSize = _GETC (infile);
- if (ENDFILE (infile))
- {
- /* fprintf (stderr, "_ReadRaster: unexpected EOF\n");*/
- return (1);
- }
- _ClearCode = (1 << _CodeSize);
- _EOFCode = _ClearCode + 1;
- _FreeCode = _FirstFree = _ClearCode + 2;
-
-
-
- /*
- * The GIF spec has it that the code size is the code size used to
- * compute the above values is the code size given in the file, but
- * the code size used in compression/decompression is the code size
- * given in the file plus one. (thus the ++).
- */
- _CodeSize++;
- _InitCodeSize = _CodeSize;
- _MaxCode = (1 << _CodeSize);
- _ReadMask = _MaxCode - 1;
-
- if (opt != SILENT)
- {
- printf (" CodeSize = %04x\n", _CodeSize);
- printf (" ClearCode = %04x\n", _ClearCode);
- printf (" EOFCode = %04x\n", _EOFCode);
- printf (" MaxCode = %04x\n", _MaxCode);
- printf (" ReadMask = %04x\n", _ReadMask);
- }
-
-
-
- /*
- * Read the raster data. Here we just transpose it from the GIF array
- * to the Raster array, turning it from a series of blocks into one
- * long data stream, which makes life much easier for _ReadCode().
- */
- pcoded = codedgif;
- do
- {
- if (_GetKey ())
- return (1);
-
- ch = (uint_t) _GETC (infile);
-
- nread = read (infile, pcoded, ch);
- if (nread != ch)
- {
- /* fprintf (stderr, "error reading raster data\n");*/
- return (1);
- }
- pcoded += (long) ch;
-
- if (((long) pcoded - (long) codedgif) > MAXRAW-255)
- {
- /* fprintf (stderr, "corrupt GIF file (unblock)\n");*/
- return (1);
- }
-
- } while (ch);
-
-
-
- /*
- * Decompress the file, continuing until you see the GIF EOF code.
- * One obvious enhancement is to add checking for corrupt files here.
- */
- if (opt != SILENT)
- {
- printf ("\nDecompressing data\n");
- printf (" Width = %d\n", (int) scrninf->s_dx);
- printf (" Height = %d\n", (int) scrninf->s_dy);
- printf (" Bits/pixel = %d\n", (int) scrninf->s_bits);
- printf (" Number of colors = %d\n", (int) scrninf->s_colors);
- }
-
- _Code = _ReadCode (codedgif, opt);
- while (_Code != _EOFCode)
- {
-
- /*
- * Clear code sets everything back to its initial value,
- * then reads the immediately subsequent code as
- * uncompressed data.
- */
- if (_Code == _ClearCode)
- {
- _CodeSize = _InitCodeSize;
- _MaxCode = (1 << _CodeSize);
- _ReadMask = _MaxCode - 1;
- _FreeCode = _FirstFree;
- _Code = _ReadCode (codedgif, opt);
- _CurCode = _Code;
- _OldCode = _Code;
- _FinChar = _CurCode & _BitMask;
-
- _AddPixel ((uchar_t) _FinChar, raster, opt);
- }
- else
- {
-
- /*
- * If not a clear code, then must be data: save
- * same as _CurCode and _InCode
- */
- _CurCode = _Code;
- _InCode = _Code;
-
- /*
- * If greater or equal to _FreeCode, not in
- * the hash table yet;
- * repeat the last character decoded
- */
- if (_CurCode >= _FreeCode)
- {
- _CurCode = _OldCode;
- _OutCode[_OutCount++] = _FinChar;
- }
-
- /*
- * Unless this code is raw data, pursue the chain
- * pointed to by _CurCode through the hash table
- * to its end; each code in the chain puts its
- * associated output code on the output queue.
- */
- while (_CurCode > _BitMask)
- {
- if (_OutCount > 1024)
- {
- /* fprintf (stderr, "corrupt GIF file (_OutCount)\n");*/
- return (1);
- }
- _OutCode[_OutCount++] = _Suffix[_CurCode];
- _CurCode = _Prefix[_CurCode];
- }
-
- /*
- * The last code in the chain is treated as raw data
- */
- _FinChar = _CurCode & _BitMask;
- _OutCode[_OutCount++] = _FinChar;
-
- /*
- * Now we put the data out to the Output routine.
- * It's been stacked LIFO, so deal with it that way
- */
- for (i = _OutCount - 1; i >= 0; i--)
- _AddPixel ((uchar_t) _OutCode[i], raster, opt);
- _OutCount = 0;
-
- /*
- * Build the hash table on-the-fly. No table is
- * stored in the file.
- */
- _Prefix[_FreeCode] = _OldCode;
- _Suffix[_FreeCode] = _FinChar;
- _OldCode = _InCode;
-
- /*
- * Point to the next slot in the table. If we
- * exceed the current _MaxCode value, increment
- * the code size unless it's already 12. If it
- * is, do nothing: the next code decompressed
- * better be CLEAR
- */
- _FreeCode++;
- if (_FreeCode >= _MaxCode)
- {
- if (_CodeSize < 12)
- {
- _CodeSize++;
- _MaxCode *= 2;
- _ReadMask = (1 << _CodeSize) - 1;
- }
- }
- }
- _Code = _ReadCode (codedgif, opt);
- }
- return (0);
- }
-
-
-
-
- /*------------------------------*/
- /* _ReadCode */
- /*------------------------------*/
- LOCAL int _ReadCode (codedgif, opt)
- uchar_t *codedgif;
- int opt;
- {
-
- /* externals: _BitOffset,_CodeSize,_ReadMask */
-
- /*
- * Fetch the next code from the raster data stream. The codes can be
- * any length from 3 to 12 bits, packed into 8-bit bytes, so we have to
- * maintain our location in the Raster array as a BIT Offset. We compute
- * the byte Offset into the raster array by dividing this by 8, pick up
- * three bytes, compute the bit Offset into our 24-bit chunk, shift to
- * bring the desired code to the bottom, then mask it off and return it.
- */
-
- reg_t ulong_t rawcode;
- reg_t ulong_t byteoffset;
- reg_t ulong_t shft;
- reg_t int ret;
-
- /* byteoffset = _BitOffset / 8;*/
- byteoffset = _BitOffset >> 3;
-
- rawcode = codedgif[byteoffset] + (0x100 * codedgif[byteoffset + 1]);
- if (_CodeSize >= 8)
- rawcode += (0x10000 * codedgif[byteoffset + 2]);
-
- shft = _BitOffset % 8;
- rawcode >>= (shft);
- _BitOffset += _CodeSize;
-
- ret = (int) (rawcode & (ulong_t) _ReadMask);
-
- return (ret);
- }
-
-
-
-
- /*------------------------------*/
- /* _AddPixel */
- /*------------------------------*/
- LOCAL int _AddPixel (indx, raster, opt)
- uchar_t indx;
- uchar_t *raster;
- int opt;
- {
-
- /* externals: _XC,_YC,_WIDTH,_HEIGHT,_Interlace,_Pass */
-
- reg_t long oset; /* linear ptr into Raster */
-
-
- /*
- * check for array overflow...
- */
- oset = ((long) _YC * (long) _WIDTH) + (long) _XC;
-
- if (opt == VERBOSE && _XC == _WIDTH/2)
- fprintf (stderr, "_AddPixel: _XC,_YC = %d,%d, oset = %ld, indx = %02x\n",
- _XC, _YC, oset, (uint_t) indx);
-
- if (oset > MAXIMG)
- {
- fprintf (stderr, "_AddPixel: image too large\n");
- exit (1);
- }
-
-
- /*
- * add to raster array...
- */
- if (_YC < _HEIGHT)
- {
- raster[oset] = indx;
- }
-
-
- /*
- * Update the X-coordinate, and if it overflows, update the
- * Y-coordinate
- */
- if (++_XC == _WIDTH)
- {
- _XC = 0;
-
- /*
- * If a non-interlaced picture, just increment _YC to the
- * next scan line. If it's interlaced, deal with the
- * interlace as described in the GIF spec. Put the
- * decoded scan line out to the screen if we haven't gone
- * past the bottom of it
- */
- if (!_Interlace)
- _YC++;
- else
- {
- switch (_Pass)
- {
- case 0:
- _YC += 8;
- if (_YC >= _HEIGHT)
- {
- _Pass++;
- _YC = 4;
- }
- break;
- case 1:
- _YC += 8;
- if (_YC >= _HEIGHT)
- {
- _Pass++;
- _YC = 2;
- }
- break;
- case 2:
- _YC += 4;
- if (_YC >= _HEIGHT)
- {
- _Pass++;
- _YC = 1;
- }
- break;
- case 3:
- _YC += 2;
- break;
- default:
- fprintf (stderr, "_AddPixel: can't happen\n");
- }
- }
- }
- }
-
-
-
-
- /*------------------------------*/
- /* _InstCMap */
- /*------------------------------*/
- LOCAL void _InstCMap (ncolors, cm, map, opt)
- int ncolors;
- uchar_t *cm;
- uchar_t map[][3];
- int opt;
- {
-
- /*
- * copy cm colormap to map color map for ncolors
- */
-
- reg_t uchar_t *scan;
- reg_t int i;
-
- /*
- * most all images currently use global map, though this will
- * copy whatever cm points to (either local or global) into the
- * real map we use...
- */
- for (scan = cm, i = 0; ncolors > 0; i++, ncolors--)
- {
- map[i][0] = *scan++;
- map[i][1] = *scan++;
- map[i][2] = *scan++;
- }
-
- }
-
-
-
-
- /*------------------------------*/
- /* _ScanSD */
- /*------------------------------*/
- LOCAL int _ScanSD (infile, sd, opt)
- int infile;
- screen_t *sd;
- int opt;
- {
-
- /*
- * read logical screen descriptor (req'd)
- *
- * bits
- * 7 6 5 4 3 2 1 0 Byte #
- * +---------------+
- * | | 1
- * +-Screen Width -+ Raster width in pixels (LSB first)
- * | | 2
- * +---------------+
- * | | 3
- * +-Screen Height-+ Raster height in pixels (LSB first)
- * | | 4
- * +-+-----+-+-----+ M = 1, Global color map follows Descriptor
- * |M| cr |0|pixel| 5 cr+1 = # bits of color resolution
- * +-+-----+-+-----+ pixel+1 = # bits/pixel in image
- * | background | 6 background=Color index of screen background
- * +---------------+ (color is defined from the Global color
- * |0 0 0 0 0 0 0 0| 7 map or default map if none specified)
- * +---------------+
- */
-
-
- reg_t uchar_t data;
- reg_t uint_t idata;
-
-
-
- idata = (uint_t) _GETC (infile); /* width */
- sd->s_dx = idata + ((uint_t) _GETC (infile) << 8);
-
- idata = (uint_t) _GETC (infile); /* height */
- sd->s_dy = idata + ((uint_t) _GETC (infile) << 8);
-
-
- idata = _GETC (infile);
- if (idata & 8) /* bit must be 0 */
- return (0); /* error... */
-
- sd->s_gcm = (idata >> 7) & 0x01; /* global color map?*/
- sd->s_cr = (idata & 0x70) >> 4; /* color resolution */
- sd->s_bits = (idata & 7) + 1; /* pix size, bits */
- sd->s_colors = 1 << sd->s_bits; /* num colors */
- sd->s_bgnd = _GETC (infile); /* background color */
-
- idata = _GETC (infile);
- if (idata != 0) /* sorted map? */
- return (0);
-
- return (!0);
- }
-
-
-
-
- /*------------------------------*/
- /* _SkipEB */
- /*------------------------------*/
- LOCAL void _SkipEB (infile, opt)
- int infile;
- int opt;
- {
-
- /*
- * skips extension block
- *
- * 7 6 5 4 3 2 1 0 Byte #
- * +---------------+
- * |0 0 1 0 0 0 0 1| 1 '!' - GIF Extension Block Introducer
- * +---------------+
- * | function code | 2 Extension function code (0 to 255)
- * +---------------+ ---+
- * | byte count | |
- * +---------------+ |
- * : : +-- Repeated as many times as necessary
- * |func data bytes| |
- * : : |
- * +---------------+ ---+
- * . . . . . .
- * +---------------+
- * |0 0 0 0 0 0 0 0| zero byte count (terminates block)
- * +---------------+
- */
-
- reg_t uint_t count;
- char garbage[256];
-
-
-
- if (opt != SILENT)
- printf ("\nSkip extension block\n");
-
- _GETC (infile); /* get function */
-
- while (count = (uint_t) _GETC (infile)) /* get data */
- {
- if (ENDFILE (infile))
- {
- fprintf (stderr, "_SkipEB: unexpected EOF\n");
- exit (1);
- }
-
- read (infile, garbage, count);
-
- if (ENDFILE (infile))
- {
- fprintf (stderr, "_SkipEB: unexpected EOF\n");
- exit (1);
- }
- }
- }
-
-
-
-
- /*------------------------------*/
- /* _ScanID */
- /*------------------------------*/
- LOCAL int _ScanID (infile, id, opt)
- int infile;
- image_t *id;
- int opt;
- {
-
- /*
- * read image descriptor (req'd)
- *
- * bits
- * 7 6 5 4 3 2 1 0 Byte #
- * +---------------+
- * |0 0 1 0 1 1 0 0| 1 ',' - Image separator character
- * +---------------+
- * | | 2 Start of image in pixels from the
- * +- Image Left -+ left side of the screen (LSB first)
- * | | 3
- * +---------------+
- * | | 4
- * +- Image Top -+ Start of image in pixels from the
- * | | 5 top of the screen (LSB first)
- * +---------------+
- * | | 6
- * +- Image Width -+ Width of the image in pixels (LSB first)
- * | | 7
- * +---------------+
- * | | 8
- * +- Image Height-+ Height of the image in pixels (LSB first)
- * | | 9
- * +-+-+-+-+-+-----+ M=0 - Use global color map, ignore 'pixel'
- * |M|I|0|0|0|pixel| 10 M=1 - Local color map follows, use 'pixel'
- * +-+-+-+-+-+-----+ I=0 - Image formatted in Sequential order
- * I=1 - Image formatted in Interlaced order
- * pixel+1 - # bits per pixel for this image
- */
-
- reg_t uchar_t data;
-
-
- /*
- * skip extension block
- */
- do
- {
- data = (uchar_t) _GETC (infile);
-
- if (ENDFILE (infile))
- return (0);
- if (data == ';')
- return (1);
- if (data == 0x21)
- _SkipEB (infile, opt);
-
- } while (data != 0x2c); /* ',' is ID start */
-
- data = (uchar_t) _GETC (infile); /* left coord */
- id->i_x = data + ((uchar_t) _GETC (infile) << 8);
-
- data = (uchar_t) _GETC (infile); /* top coord */
- id->i_y = data + ((uchar_t) _GETC (infile) << 8);
-
- data = (uchar_t) _GETC (infile); /* width */
- id->i_dx = data + ((uchar_t) _GETC (infile) << 8);
-
- data = (uchar_t) _GETC (infile); /* height */
- id->i_dy = data + ((uchar_t) _GETC (infile) << 8);
-
- data = (uchar_t) _GETC (infile); /* flag: */
- id->i_gcm = (data >> 7) & 0x01; /* local color map? */
- id->i_intlace= (data >> 6) & 0x01; /* interlaced? */
- id->i_bits = (data & 7) + 1;
- id->i_colors = 1 << id->i_bits;
-
- return (2);
- }
-
-
-
-
- /*------------------------------*/
- /* _ScanCM */
- /*------------------------------*/
- LOCAL void _ScanCM (infile, colors, cm, opt)
- int infile;
- int colors;
- char *cm;
- int opt; /* SILENT, INQUIRE, VERBOSE */
- {
-
- /*
- * read a color map (optional)
- *
- * bits
- * 7 6 5 4 3 2 1 0 Byte #
- * +---------------+
- * | red intensity | 1 Red value for color index 0
- * +---------------+
- * |green intensity| 2 Green value for color index 0
- * +---------------+
- * | blue intensity| 3 Blue value for color index 0
- * +---------------+
- * | red intensity | 4 Red value for color index 1
- * +---------------+
- * |green intensity| 5 Green value for color index 1
- * +---------------+
- * | blue intensity| 6 Blue value for color index 1
- * +---------------+
- * : : (Continues for remaining colors)
- *
- */
-
- reg_t char *scan;
- reg_t int i;
-
-
- if (opt != SILENT)
- printf (stderr, "\nRead color map\n");
-
- for (scan = cm, i = colors; i > 0; i--, scan += 3)
- {
- *scan = (char) _GETC (infile);
- *(scan+1) = (char) _GETC (infile);
- *(scan+2) = (char) _GETC (infile);
-
- if (opt == VERBOSE)
- {
- fprintf (stderr, "addr: %08lx %08lx %08lx\n",
- (long) (scan),
- (long) (scan+1),
- (long) (scan+2));
- fprintf (stderr, "vals: %02x %02x %02x\n",
- (uint_t) (*scan),
- (uint_t) (*(scan+1)),
- (uint_t) (*(scan+2)));
- }
- }
-
- if (opt == VERBOSE)
- {
- printf ("\n Color map for %d colors:\n\n", colors);
- for (scan = cm, i = colors; i > 0; i--, scan += 3)
- printf (" %02x %02x %02x\n",
- (uint_t) (*scan),
- (uint_t) (*(scan+1)),
- (uint_t) (*(scan+2)));
- printf ("\n");
- }
- }
-
-
-
- /*------------------------------*/
- /* _ScanMAGIC */
- /*------------------------------*/
- LOCAL int _ScanMAGIC (infile, parse, opt)
- int infile;
- char *parse;
- int opt;
- {
-
- /*
- * read chars from file "infile" and look for string "parse" from
- * current file position. return 0 if no match at first mismatch.
- */
-
- reg_t char *scan;
-
-
- for (scan = parse; *scan; scan++)
- {
- if (_GETC (infile) != (int) *scan)
- return (0);
- }
- return (!0);
- }
-
-
-
-
- /*------------------------------*/
- /* _GETC */
- /*------------------------------*/
- LOCAL int _GETC (fd)
- int fd;
- {
- reg_t int ret;
- uchar_t buf[10];
-
- ret = read (fd, buf, 1);
-
- if (ret < 0)
- _Eof = 1;
-
- return ((int) buf[0]);
- }
-
-
-
-
- /*------------------------------*/
- /* _GetKey */
- /*------------------------------*/
- LOCAL int _GetKey ()
- {
-
- /*
- * ckecks for a key and flushes keyboard buffer. same as check_key().
- */
-
- if (Bconstat (2)) /* if CONSOLE has a char... */
- {
- while (Bconstat (2)) /* read char while there are */
- Bconin (2); /* chars to read (flush) */
- return (1); /* yes, there was a key */
- }
- return (0); /* no key */
- }
-
-