home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / GRAPHICS / mgif.lzh / GIF / readgif.c < prev    next >
Text File  |  1991-12-01  |  25KB  |  1,103 lines

  1. /*
  2.  *    read a GIF file. decode and stuff into raster array and color maps.
  3.  *
  4.  *    this was adopted from PBMplus.
  5.  */
  6.  
  7. static char *sccsid = "@(#) readgif.c 1.1 91/6/3 rosenkra\0\0                 ";
  8.  
  9. #include <stdio.h>
  10. #include <modes.h>
  11. #include "mgif.h"
  12.  
  13.  
  14. #ifdef LOCAL
  15. #undef LOCAL
  16. #endif
  17. #ifdef GLOBAL
  18. #undef GLOBAL
  19. #endif
  20. #define LOCAL        /*static*/
  21. #define GLOBAL
  22. #define reg_t        register
  23.  
  24. #define ENDFILE(f)    _Eof != 0    /* to track EOF on input file */
  25.  
  26.  
  27. /*
  28.  *    globals for GIF decode procedure (only needed in this file,
  29.  *    should actually be static)
  30.  */
  31. LOCAL ulong_t    _BitOffset = 0;    /* Bit Offset of next code */
  32. LOCAL int    _XC = 0;    /* Output X and Y coords of current pixel */
  33. LOCAL int    _YC = 0;
  34. LOCAL int    _HEIGHT;    /* image size */
  35. LOCAL int    _WIDTH;
  36. LOCAL int    _Pass = 0;    /* Used by output routine if interlaced pic */
  37. LOCAL int    _OutCount = 0;    /* Decompressor output 'stack count' */
  38. LOCAL int    _Interlace;    /* flag for interlaced image */
  39. LOCAL int    _CodeSize;    /* Code size, read from GIF header */
  40. LOCAL int    _InitCodeSize;    /* Start code size, used during Clear */
  41. LOCAL int    _Code;        /* Value returned by read_code */
  42. LOCAL int    _MaxCode;    /* limit value for current code size */
  43. LOCAL int    _ClearCode;    /* GIF clear code */
  44. LOCAL int    _EOFCode;    /* GIF end-of-information code */
  45. LOCAL int    _CurCode;    /* Decompressor variables */
  46. LOCAL int    _OldCode;
  47. LOCAL int    _InCode;
  48. LOCAL int    _FirstFree;    /* First free code, gen'd per GIF spec */
  49. LOCAL int    _FreeCode;    /* Decompr, next free slot in hash table */
  50. LOCAL int    _FinChar;    /* Decompr variable */
  51. LOCAL int    _BitMask;    /* AND mask for data size */
  52. LOCAL int    _ReadMask;    /* Code AND mask for cur code size */
  53. LOCAL int    _Prefix[HASHSIZ];/* hash table used by the decompr */
  54. LOCAL int    _Suffix[HASHSIZ];
  55. LOCAL int    _OutCode[OUTSIZ];/* output array used by the decompr */
  56. LOCAL int    _BitsPerPixel;    /* image attributes */
  57. LOCAL int    _ColorMapSize;
  58. LOCAL int    _ImageNum = 0;    /* if multi-image file (not used) */
  59. LOCAL int    _Eof = 0;    /* EOF on input flag (_GETC) */
  60.  
  61.  
  62. /*
  63.  *    local functions
  64.  */
  65. LOCAL int    _ReadRaster ();
  66. LOCAL int    _ReadCode ();
  67. LOCAL int    _AddPixel ();
  68. LOCAL void    _InstCMap ();
  69. LOCAL int    _ScanSD ();
  70. LOCAL void    _SkipEB ();
  71. LOCAL int    _ScanID ();
  72. LOCAL void    _ScanCM ();
  73. LOCAL int    _ScanMAGIC ();
  74. LOCAL int    _GetKey ();
  75. LOCAL int    _GETC ();
  76.  
  77.  
  78.  
  79. /*------------------------------*/
  80. /*    ReadGIF            */
  81. /*------------------------------*/
  82. GLOBAL int ReadGIF (fname, codedgif, raster, scrninf, id, colormap, opt)
  83. char           *fname;        /* file name with .GIF */
  84. uchar_t           *codedgif;    /* place to put raw raster data, coded */
  85. uchar_t           *raster;        /* place to put raster */
  86. screen_t       *scrninf;    /* image info struct */
  87. image_t           *id;        /* image id struct */
  88. uchar_t        colormap[][3];    /* color map */
  89. int        opt;        /* SILENT, INQUIRE, VERBOSE, NORMAL */
  90. {
  91.  
  92. /*
  93.  *    read a GIF87a image from open file infile into raster array.
  94.  *    the array will contain index into color table. caller supplies
  95.  *    all needed space (raster array, headers, color map, etc). colormap
  96.  *    will contain either global or local color map, depending on image.
  97.  *
  98.  *    The following illustrates the general file layout of .GIF files:
  99.  *
  100.  *    +-----------------------+
  101.  *    | +-------------------+ |
  102.  *    | |   GIF Signature   | |    GIF87a            (required)
  103.  *    | +-------------------+ |
  104.  *    | +-------------------+ |
  105.  *    | | Screen Descriptor | |    7 bytes, ends with 00    (required)
  106.  *    | +-------------------+ |
  107.  *    | +-------------------+ |
  108.  *    | | Global Color Map  | |    3*2^bits bytes        (optional but
  109.  *    | +-------------------+ |                 usual)
  110.  *    | +-------------------+ |
  111.  *    | | Extension Block   | |    !            (optional)
  112.  *    | +-------------------+ |
  113.  *    . . .            . . .
  114.  *    | +-------------------+ |
  115.  *    | |  Image Descriptor | |    ,            (required)
  116.  *    | +-------------------+ |
  117.  *    | +-------------------+ |
  118.  *    | |  Local Color Map  | |                (optional)
  119.  *    | +-------------------+ |
  120.  *    | +-------------------+ |
  121.  *    | |    Raster Data    | |                (required)
  122.  *    | +-------------------+ |
  123.  *    . . .            . . .   
  124.  *    |-    GIF Terminator   -|                (required)
  125.  *    +-----------------------+
  126.  */
  127.  
  128.     static int    firsttime = 1;
  129.  
  130.     uchar_t        lcm[MAPSIZ][3];
  131.     uchar_t        gcm[MAPSIZ][3];
  132.     int        infile;
  133.     reg_t long    ii;
  134.     int        flag;
  135.  
  136.  
  137.  
  138.     /*
  139.      *   open file...
  140.      */
  141.     if (opt != SILENT)
  142.     {
  143.         printf ("   \n");
  144.         printf ("\nEnter ReadGIF\n\n");
  145.         printf ("Open file:                           %s\n", fname);
  146.     }
  147.     if ((infile = open (fname, S_IREAD)) < 0)
  148.     {
  149.         return (EGIFFILE);
  150.     }
  151.  
  152.  
  153.  
  154.     /*
  155.      *   get ready for next image by clearing variables, tables
  156.      */
  157.     _BitOffset    = 0;
  158.     _XC           = 0;
  159.     _YC           = 0;
  160.     _Pass         = 0;
  161.     _OutCount     = 0;
  162.     _CodeSize     = 0;
  163.     _InitCodeSize = 0;
  164.     _Code         = 0;
  165.     _MaxCode      = 0;
  166.     _ClearCode    = 0;
  167.     _EOFCode      = 0;
  168.     _CurCode      = 0;
  169.     _OldCode      = 0;
  170.     _InCode       = 0;
  171.     _FirstFree    = 0;
  172.     _FreeCode     = 0;
  173.     _FinChar      = 0;
  174.     _BitMask      = 0;
  175.     _ReadMask     = 0;
  176.     _Eof          = 0;
  177.  
  178.     for (ii = 0; ii < HASHSIZ; ii++)
  179.     {
  180.         _Prefix[ii] = 0;
  181.         _Suffix[ii] = 0;
  182.     }
  183.  
  184.     for (ii = 0; ii < OUTSIZ; ii++)
  185.         _OutCode[ii] = 0;
  186.  
  187.     if (firsttime)
  188.         firsttime = 0;
  189.     else
  190.     {
  191.         /* these take a while to do */
  192.         if (opt != SILENT)
  193.             printf ("\nResetting tables\n");
  194.  
  195.         for (ii = 0; ii < MAXRAW; ii++)
  196.             codedgif[ii] = 0;
  197.  
  198.         for (ii = 0; ii < MAXIMG; ii++)
  199.             raster[ii] = 0;
  200.  
  201.     }
  202.  
  203.  
  204.     /*
  205.      *   make sure it is a gif file (file header is this...)
  206.      */
  207.     if (opt != SILENT)
  208.         printf ("\nRead MAGIC\n");
  209.     if (!_ScanMAGIC (infile, "GIF87a", opt))
  210.     {
  211.         close (infile);
  212.         return (EGIFMAGIC);
  213.     }
  214.  
  215.  
  216.  
  217.     /*
  218.      *   read screen descriptor...
  219.      */
  220.     if (opt != SILENT)
  221.         printf ("\nRead screen descriptor\n");
  222.     if (!_ScanSD (infile, scrninf, opt))
  223.     {
  224.         close (infile);
  225.         return (EGIFSDESC);
  226.     }
  227.     if (opt != SILENT)
  228.     {
  229.       printf ("     Screen width (s_dx)       = %d\n", (int) (scrninf->s_dx));
  230.       printf ("     Screen height (s_dy)      = %d\n", (int) (scrninf->s_dy));
  231.       printf ("     Global map? (s_gcm)       = %d\n", (int) (scrninf->s_gcm));
  232.       printf ("     Color resolution (s_cr)   = %d\n", (int) (scrninf->s_cr));
  233.       printf ("     Bits/pixel (s_bits)       = %d\n", (int) (scrninf->s_bits));
  234.       printf ("     Num colors (s_colors)     = %d\n", (int) (scrninf->s_colors));
  235.       printf ("     Background color (s_bgnd) = %d\n", (int) (scrninf->s_bgnd));
  236.     }
  237.  
  238.  
  239.  
  240.     /*
  241.      *   read global color map if we have one...
  242.      */
  243.     if (scrninf->s_gcm)
  244.     {
  245.         if (opt != SILENT)
  246.             printf ("\nRead global color map\n");
  247.         _ScanCM (infile, scrninf->s_colors, (char *) gcm, opt);
  248.     }
  249.     else
  250.     {
  251.         if (opt != SILENT)
  252.             printf ("\nNo global color map\n");
  253.     }
  254.  
  255.  
  256.     /*
  257.      *   read image descriptor
  258.      */
  259.     _ImageNum++;
  260.     if (opt != SILENT)
  261.         printf ("\nRead image descriptor, image: %d\n", _ImageNum);
  262.  
  263.     flag = _ScanID (infile, id, opt);
  264.  
  265.     if (flag == 0)
  266.     {
  267.         return (EGIFEOF);
  268.     }
  269.     if (flag == 1)
  270.         return (EGIFIDBAD);
  271.  
  272.     if (opt != SILENT)
  273.     {
  274.       printf ("     Image left (i_x)         = %d\n", (int) (id->i_x));
  275.       printf ("     Image top (i_y)          = %d\n", (int) (id->i_y));
  276.       printf ("     Image width (i_dx)       = %d\n", (int) (id->i_dx));
  277.       printf ("     Image height (i_dy)      = %d\n", (int) (id->i_dy));
  278.       printf ("     Use local map? (i_gcm)   = %d\n", (int) (id->i_gcm));
  279.       printf ("     Interlaced? (i_intlace)  = %d\n", (int) (id->i_intlace));
  280.       printf ("     Bits per pixel (i_bits)  = %d\n", (int) (id->i_bits));
  281.       printf ("     Number colors (i_colors) = %d\n", (int) (id->i_colors));
  282.       printf ("     (If no local color map, use screen bits and colors)\n");
  283.     }
  284.  
  285.  
  286.     /*
  287.      *   read local color map, if there
  288.      */
  289.     if (id->i_gcm)
  290.     {
  291.         if (opt != SILENT)
  292.             printf ("\nRead local color map\n");
  293.         _ScanCM (infile, id->i_colors, (char *) lcm, opt);
  294.         _InstCMap (id->i_colors, (uchar_t *) lcm, colormap, opt);
  295.     }
  296.     else
  297.     {
  298.         if (opt != SILENT)
  299.             printf ("\nUse global color map\n");
  300.         _InstCMap (scrninf->s_colors, (uchar_t *) gcm, colormap, opt);
  301.  
  302.         /*
  303.          *   make sure to reset these from global info...
  304.          */
  305.         id->i_colors = scrninf->s_colors;
  306.         id->i_bits   = scrninf->s_bits;
  307.     }
  308.  
  309.     _BitsPerPixel = id->i_bits;
  310.     _ColorMapSize = 1 << _BitsPerPixel;
  311.     _BitMask      = _ColorMapSize - 1;
  312.     _WIDTH        = id->i_dx;
  313.     _HEIGHT       = id->i_dy;
  314.     _Interlace    = id->i_intlace;
  315.  
  316.     if (opt != SILENT)
  317.     {
  318.         printf ("     BitsPerPixel = %d\n", _BitsPerPixel);
  319.         printf ("     ColorMapSize = %d\n", _ColorMapSize);
  320.         printf ("     BitMask      = %04x\n", _BitMask);
  321.         printf ("     WIDTH        = %d\n", _WIDTH);
  322.         printf ("     HEIGHT       = %d\n", _HEIGHT);
  323.         printf ("     Interlace    = %d\n", _Interlace);
  324.     }
  325.  
  326.  
  327.  
  328.     /*
  329.      *   check size vs internal buffer...
  330.      */
  331.     if (((long) _WIDTH * (long) _HEIGHT) > MAXIMG)
  332.     {
  333.         return (EGIFBIG);
  334.     }
  335.  
  336.  
  337.  
  338.     /*
  339.      *   if just an inquiry, quit now...
  340.      */
  341.     if (opt == INQUIRE)
  342.         return (EGIFOK);
  343.  
  344.  
  345.  
  346.     /*
  347.      *   read raster data
  348.      */
  349.     if (_ReadRaster (infile, codedgif, scrninf, raster, opt))
  350.     {
  351.         return (EGIFRAST);
  352.     }
  353.  
  354.     /* at this point, Raster[] contains colormap indices at each pixel */
  355.  
  356.     return (EGIFOK);
  357. }
  358.  
  359.  
  360.  
  361.  
  362. /*------------------------------*/
  363. /*    _ReadRaster        */
  364. /*------------------------------*/
  365. LOCAL int _ReadRaster (infile, codedgif, scrninf, raster, opt)
  366. int        infile;
  367. uchar_t           *codedgif;
  368. screen_t       *scrninf;
  369. uchar_t           *raster;
  370. int        opt;
  371. {
  372.  
  373. /* externals: _CodeSize,_Eof,_ClearCode,_EOFCode,_FreeCode,_FirstFree,
  374.               _InitCodeSize,_MaxCode,_ReadMask,... */
  375.  
  376. /*
  377.  *    Decode a raster image
  378.  */
  379.  
  380.     uchar_t           *pcoded;
  381.     uchar_t           *praster;
  382.     uint_t        ch;
  383.     uint_t        ch1;
  384.     int        i;
  385.     int        nread;
  386.  
  387.  
  388.  
  389.  
  390.     /*
  391.      *   Start reading the raster data. First we get the intial code size
  392.      *   and compute decompressor constant values, based on this code size.
  393.      */
  394.     if (opt != SILENT)
  395.         printf ("\nRead raster data\n");
  396.  
  397.     _CodeSize  = _GETC (infile);
  398.     if (ENDFILE (infile))
  399.     {
  400. /*        fprintf (stderr, "_ReadRaster: unexpected EOF\n");*/
  401.         return (1);
  402.     }
  403.     _ClearCode = (1 << _CodeSize);
  404.     _EOFCode   = _ClearCode + 1;
  405.     _FreeCode  = _FirstFree = _ClearCode + 2;
  406.  
  407.  
  408.  
  409.     /*
  410.      *   The GIF spec has it that the code size is the code size used to
  411.      *   compute the above values is the code size given in the file, but
  412.      *   the code size used in compression/decompression is the code size
  413.      *   given in the file plus one. (thus the ++).
  414.      */
  415.     _CodeSize++;
  416.     _InitCodeSize = _CodeSize;
  417.     _MaxCode      = (1 << _CodeSize);
  418.     _ReadMask     = _MaxCode - 1;
  419.  
  420.     if (opt != SILENT)
  421.     {
  422.         printf ("     CodeSize  = %04x\n", _CodeSize);
  423.         printf ("     ClearCode = %04x\n", _ClearCode);
  424.         printf ("     EOFCode   = %04x\n", _EOFCode);
  425.         printf ("     MaxCode   = %04x\n", _MaxCode);
  426.         printf ("     ReadMask  = %04x\n", _ReadMask);
  427.     }
  428.  
  429.  
  430.  
  431.     /*
  432.      *   Read the raster data. Here we just transpose it from the GIF array
  433.      *   to the Raster array, turning it from a series of blocks into one
  434.      *   long data stream, which makes life much easier for _ReadCode().
  435.      */
  436.     pcoded = codedgif;
  437.     do
  438.     {
  439.         if (_GetKey ())
  440.             return (1);
  441.  
  442.         ch = (uint_t) _GETC (infile);
  443.  
  444.         nread = read (infile, pcoded, ch);
  445.         if (nread != ch)
  446.         {
  447. /*            fprintf (stderr, "error reading raster data\n");*/
  448.             return (1);
  449.         }
  450.         pcoded += (long) ch;
  451.  
  452.         if (((long) pcoded - (long) codedgif) > MAXRAW-255)
  453.         {
  454. /*            fprintf (stderr, "corrupt GIF file (unblock)\n");*/
  455.             return (1);
  456.         }
  457.  
  458.     } while (ch);
  459.  
  460.  
  461.  
  462.     /*
  463.      *   Decompress the file, continuing until you see the GIF EOF code.
  464.      *   One obvious enhancement is to add checking for corrupt files here.
  465.      */
  466.     if (opt != SILENT)
  467.     {
  468.         printf ("\nDecompressing data\n");
  469.         printf ("     Width            = %d\n", (int) scrninf->s_dx);
  470.         printf ("     Height           = %d\n", (int) scrninf->s_dy);
  471.         printf ("     Bits/pixel       = %d\n", (int) scrninf->s_bits);
  472.         printf ("     Number of colors = %d\n", (int) scrninf->s_colors);
  473.     }
  474.  
  475.     _Code = _ReadCode (codedgif, opt);
  476.     while (_Code != _EOFCode)
  477.     {
  478.  
  479.         /*
  480.          *   Clear code sets everything back to its initial value,
  481.          *   then reads the immediately subsequent code as
  482.          *   uncompressed data.
  483.          */
  484.         if (_Code == _ClearCode)
  485.         {
  486.             _CodeSize = _InitCodeSize;
  487.             _MaxCode  = (1 << _CodeSize);
  488.             _ReadMask = _MaxCode - 1;
  489.             _FreeCode = _FirstFree;
  490.             _Code     = _ReadCode (codedgif, opt);
  491.             _CurCode  = _Code;
  492.             _OldCode  = _Code;
  493.             _FinChar  = _CurCode & _BitMask;
  494.  
  495.             _AddPixel ((uchar_t) _FinChar, raster, opt);
  496.         }
  497.         else
  498.         {
  499.  
  500.             /*
  501.              *   If not a clear code, then must be data: save
  502.              *   same as _CurCode and _InCode
  503.              */
  504.             _CurCode = _Code;
  505.             _InCode  = _Code;
  506.  
  507.             /*
  508.              *   If greater or equal to _FreeCode, not in
  509.              *   the hash table yet;
  510.              *   repeat the last character decoded
  511.              */
  512.             if (_CurCode >= _FreeCode)
  513.             {
  514.                 _CurCode              = _OldCode;
  515.                 _OutCode[_OutCount++] = _FinChar;
  516.             }
  517.  
  518.             /*
  519.              *   Unless this code is raw data, pursue the chain
  520.              *   pointed to by _CurCode through the hash table
  521.              *   to its end; each code in the chain puts its
  522.              *   associated output code on the output queue.
  523.              */
  524.             while (_CurCode > _BitMask)
  525.             {
  526.                 if (_OutCount > 1024)
  527.                 {
  528. /*                    fprintf (stderr, "corrupt GIF file (_OutCount)\n");*/
  529.                     return (1);
  530.                 }
  531.                 _OutCode[_OutCount++] = _Suffix[_CurCode];
  532.                 _CurCode              = _Prefix[_CurCode];
  533.             }
  534.  
  535.             /*
  536.              *   The last code in the chain is treated as raw data
  537.              */
  538.             _FinChar              = _CurCode & _BitMask;
  539.             _OutCode[_OutCount++] = _FinChar;
  540.  
  541.             /*
  542.              *   Now we put the data out to the Output routine.
  543.              *   It's been stacked LIFO, so deal with it that way
  544.              */
  545.             for (i = _OutCount - 1; i >= 0; i--)
  546.                 _AddPixel ((uchar_t) _OutCode[i], raster, opt);
  547.             _OutCount = 0;
  548.  
  549.             /*
  550.              *   Build the hash table on-the-fly. No table is
  551.              *   stored in the file.
  552.              */
  553.             _Prefix[_FreeCode] = _OldCode;
  554.             _Suffix[_FreeCode] = _FinChar;
  555.             _OldCode           = _InCode;
  556.  
  557.             /*
  558.              *   Point to the next slot in the table.  If we
  559.              *   exceed the current _MaxCode value, increment
  560.              *   the code size unless it's already 12.  If it
  561.              *   is, do nothing: the next code decompressed
  562.              *   better be CLEAR
  563.              */
  564.             _FreeCode++;
  565.             if (_FreeCode >= _MaxCode)
  566.             {
  567.                 if (_CodeSize < 12)
  568.                 {
  569.                     _CodeSize++;
  570.                     _MaxCode *= 2;
  571.                     _ReadMask = (1 << _CodeSize) - 1;
  572.                 }
  573.             }
  574.         }
  575.         _Code = _ReadCode (codedgif, opt);
  576.     }
  577.     return (0);
  578. }
  579.  
  580.  
  581.  
  582.  
  583. /*------------------------------*/
  584. /*    _ReadCode        */
  585. /*------------------------------*/
  586. LOCAL int _ReadCode (codedgif, opt)
  587. uchar_t           *codedgif;
  588. int        opt;
  589. {
  590.  
  591. /* externals: _BitOffset,_CodeSize,_ReadMask */
  592.  
  593. /*
  594.  *    Fetch the next code from the raster data stream.  The codes can be
  595.  *    any length from 3 to 12 bits, packed into 8-bit bytes, so we have to
  596.  *    maintain our location in the Raster array as a BIT Offset.  We compute
  597.  *    the byte Offset into the raster array by dividing this by 8, pick up
  598.  *    three bytes, compute the bit Offset into our 24-bit chunk, shift to
  599.  *    bring the desired code to the bottom, then mask it off and return it. 
  600.  */
  601.  
  602.     reg_t ulong_t        rawcode;
  603.     reg_t ulong_t        byteoffset;
  604.     reg_t ulong_t        shft;
  605.     reg_t int        ret;
  606.  
  607. /*    byteoffset = _BitOffset / 8;*/
  608.     byteoffset = _BitOffset >> 3;
  609.  
  610.     rawcode = codedgif[byteoffset] + (0x100 * codedgif[byteoffset + 1]);
  611.     if (_CodeSize >= 8)
  612.         rawcode += (0x10000 * codedgif[byteoffset + 2]);
  613.  
  614.     shft        = _BitOffset % 8;
  615.     rawcode   >>= (shft);
  616.     _BitOffset += _CodeSize;
  617.  
  618.     ret = (int) (rawcode & (ulong_t) _ReadMask);
  619.  
  620.     return (ret);
  621. }
  622.  
  623.  
  624.  
  625.  
  626. /*------------------------------*/
  627. /*    _AddPixel        */
  628. /*------------------------------*/
  629. LOCAL int _AddPixel (indx, raster, opt)
  630. uchar_t        indx;
  631. uchar_t           *raster;
  632. int        opt;
  633. {
  634.  
  635. /* externals: _XC,_YC,_WIDTH,_HEIGHT,_Interlace,_Pass */
  636.  
  637.     reg_t long    oset;        /* linear ptr into Raster */
  638.  
  639.  
  640.     /*
  641.      *   check for array overflow...
  642.      */
  643.     oset = ((long) _YC * (long) _WIDTH) + (long) _XC;
  644.  
  645.     if (opt == VERBOSE && _XC == _WIDTH/2)
  646.         fprintf (stderr, "_AddPixel: _XC,_YC = %d,%d, oset = %ld, indx = %02x\n",
  647.                 _XC, _YC, oset, (uint_t) indx);
  648.  
  649.     if (oset > MAXIMG)
  650.     {
  651.         fprintf (stderr, "_AddPixel: image too large\n");
  652.         exit (1);
  653.     }
  654.  
  655.  
  656.     /*
  657.      *   add to raster array...
  658.      */
  659.     if (_YC < _HEIGHT)
  660.     {
  661.         raster[oset] = indx;
  662.     }
  663.  
  664.  
  665.     /*
  666.      *   Update the X-coordinate, and if it overflows, update the
  667.      *   Y-coordinate
  668.      */
  669.     if (++_XC == _WIDTH)
  670.     {
  671.         _XC = 0;
  672.  
  673.         /*
  674.          *   If a non-interlaced picture, just increment _YC to the
  675.          *   next scan line. If it's interlaced, deal with the
  676.          *   interlace as described in the GIF spec.  Put the
  677.          *   decoded scan line out to the screen if we haven't gone
  678.          *   past the bottom of it
  679.          */
  680.         if (!_Interlace)
  681.             _YC++;
  682.         else
  683.         {
  684.             switch (_Pass)
  685.             {
  686.             case 0:
  687.                 _YC += 8;
  688.                 if (_YC >= _HEIGHT)
  689.                 {
  690.                     _Pass++;
  691.                     _YC = 4;
  692.                 }
  693.                 break;
  694.             case 1:
  695.                 _YC += 8;
  696.                 if (_YC >= _HEIGHT)
  697.                 {
  698.                     _Pass++;
  699.                     _YC = 2;
  700.                 }
  701.                 break;
  702.             case 2:
  703.                 _YC += 4;
  704.                 if (_YC >= _HEIGHT)
  705.                 {
  706.                     _Pass++;
  707.                     _YC = 1;
  708.                 }
  709.                 break;
  710.             case 3:
  711.                 _YC += 2;
  712.                 break;
  713.             default:
  714.                 fprintf (stderr, "_AddPixel: can't happen\n");
  715.             }
  716.         }
  717.     }
  718. }
  719.  
  720.  
  721.  
  722.  
  723. /*------------------------------*/
  724. /*    _InstCMap        */
  725. /*------------------------------*/
  726. LOCAL void _InstCMap (ncolors, cm, map, opt)
  727. int        ncolors;
  728. uchar_t           *cm;
  729. uchar_t        map[][3];
  730. int        opt;
  731. {
  732.  
  733. /*
  734.  *    copy cm colormap to map color map for ncolors
  735.  */
  736.  
  737.     reg_t uchar_t           *scan;
  738.     reg_t int        i;
  739.  
  740.     /*
  741.      *   most all images currently use global map, though this will
  742.      *   copy whatever cm points to (either local or global) into the
  743.      *   real map we use...
  744.      */
  745.     for (scan = cm, i = 0; ncolors > 0; i++, ncolors--)
  746.     {
  747.         map[i][0] = *scan++;
  748.         map[i][1] = *scan++;
  749.         map[i][2] = *scan++;
  750.     }
  751.  
  752. }
  753.  
  754.  
  755.  
  756.  
  757. /*------------------------------*/
  758. /*    _ScanSD            */
  759. /*------------------------------*/
  760. LOCAL int _ScanSD (infile, sd, opt)
  761. int        infile;
  762. screen_t       *sd;
  763. int        opt;
  764. {
  765.  
  766. /*
  767.  *    read logical screen descriptor (req'd)
  768.  *
  769.  *        bits
  770.  *     7 6 5 4 3 2 1 0  Byte #
  771.  *    +---------------+
  772.  *    |        |  1
  773.  *    +-Screen Width -+    Raster width in pixels (LSB first)
  774.  *    |        |  2
  775.  *    +---------------+
  776.  *    |        |  3
  777.  *    +-Screen Height-+    Raster height in pixels (LSB first)
  778.  *    |        |  4
  779.  *    +-+-----+-+-----+    M = 1, Global color map follows Descriptor
  780.  *    |M|  cr |0|pixel|  5    cr+1 = # bits of color resolution
  781.  *    +-+-----+-+-----+    pixel+1 = # bits/pixel in image
  782.  *    |   background  |  6    background=Color index of screen background
  783.  *    +---------------+         (color is defined from the Global color
  784.  *    |0 0 0 0 0 0 0 0|  7          map or default map if none specified)
  785.  *    +---------------+
  786.  */
  787.  
  788.  
  789.     reg_t uchar_t    data;
  790.     reg_t uint_t    idata;
  791.  
  792.  
  793.  
  794.     idata        = (uint_t) _GETC (infile);        /* width */
  795.     sd->s_dx     = idata + ((uint_t) _GETC (infile) << 8);
  796.  
  797.     idata        = (uint_t) _GETC (infile);        /* height */
  798.     sd->s_dy     = idata + ((uint_t) _GETC (infile) << 8);
  799.  
  800.  
  801.     idata        = _GETC (infile);
  802.     if (idata & 8)                    /* bit must be 0 */
  803.         return (0);                /* error... */
  804.  
  805.     sd->s_gcm    = (idata >> 7) & 0x01;        /* global color map?*/
  806.     sd->s_cr     = (idata & 0x70) >> 4;        /* color resolution */
  807.     sd->s_bits   = (idata & 7) + 1;            /* pix size, bits */
  808.     sd->s_colors = 1 << sd->s_bits;            /* num colors */
  809.     sd->s_bgnd   = _GETC (infile);            /* background color */
  810.  
  811.     idata        = _GETC (infile);
  812.     if (idata != 0)                    /* sorted map? */
  813.         return (0);
  814.  
  815.     return (!0);
  816. }
  817.  
  818.  
  819.  
  820.  
  821. /*------------------------------*/
  822. /*    _SkipEB            */
  823. /*------------------------------*/
  824. LOCAL void _SkipEB (infile, opt)
  825. int    infile;
  826. int    opt;
  827. {
  828.  
  829. /*
  830.  *    skips extension block
  831.  *
  832.  *     7 6 5 4 3 2 1 0  Byte #
  833.  *    +---------------+
  834.  *    |0 0 1 0 0 0 0 1|  1       '!' - GIF Extension Block Introducer
  835.  *    +---------------+
  836.  *    | function code |  2       Extension function code (0 to 255)
  837.  *    +---------------+    ---+
  838.  *    |  byte count    |    |
  839.  *    +---------------+    |
  840.  *    :        :    +-- Repeated as many times as necessary
  841.  *    |func data bytes|    |
  842.  *    :        :    |
  843.  *    +---------------+    ---+
  844.  *    . . .        . . .
  845.  *    +---------------+
  846.  *    |0 0 0 0 0 0 0 0|    zero byte count (terminates block)
  847.  *    +---------------+
  848.  */
  849.  
  850.     reg_t uint_t    count;
  851.     char        garbage[256];
  852.  
  853.  
  854.  
  855.     if (opt != SILENT)
  856.         printf ("\nSkip extension block\n");
  857.  
  858.     _GETC (infile);            /* get function */
  859.  
  860.     while (count = (uint_t) _GETC (infile))    /* get data */
  861.     {
  862.         if (ENDFILE (infile))
  863.         {
  864.             fprintf (stderr, "_SkipEB: unexpected EOF\n");
  865.             exit (1);
  866.         }
  867.  
  868.         read (infile, garbage, count);
  869.  
  870.         if (ENDFILE (infile))
  871.         {
  872.             fprintf (stderr, "_SkipEB: unexpected EOF\n");
  873.             exit (1);
  874.         }
  875.     }
  876. }
  877.  
  878.  
  879.  
  880.  
  881. /*------------------------------*/
  882. /*    _ScanID            */
  883. /*------------------------------*/
  884. LOCAL int _ScanID (infile, id, opt)
  885. int        infile;
  886. image_t        *id;
  887. int        opt;
  888. {
  889.  
  890. /*
  891.  *    read image descriptor (req'd)
  892.  *
  893.  *          bits
  894.  *     7 6 5 4 3 2 1 0  Byte #
  895.  *    +---------------+
  896.  *    |0 0 1 0 1 1 0 0|  1    ',' - Image separator character
  897.  *    +---------------+
  898.  *    |        |  2    Start of image in pixels from the
  899.  *    +-  Image Left -+    left side of the screen (LSB first)
  900.  *    |        |  3
  901.  *    +---------------+
  902.  *    |        |  4
  903.  *    +-  Image Top  -+    Start of image in pixels from the
  904.  *    |        |  5    top of the screen (LSB first)
  905.  *    +---------------+
  906.  *    |        |  6
  907.  *    +- Image Width -+    Width of the image in pixels (LSB first)
  908.  *    |        |  7
  909.  *    +---------------+
  910.  *    |        |  8
  911.  *    +- Image Height-+    Height of the image in pixels (LSB first)
  912.  *    |        |  9
  913.  *    +-+-+-+-+-+-----+    M=0 - Use global color map, ignore 'pixel'
  914.  *    |M|I|0|0|0|pixel| 10    M=1 - Local color map follows, use 'pixel'
  915.  *    +-+-+-+-+-+-----+    I=0 - Image formatted in Sequential order
  916.  *                I=1 - Image formatted in Interlaced order
  917.  *                pixel+1 - # bits per pixel for this image
  918.  */
  919.  
  920.     reg_t uchar_t    data;
  921.  
  922.  
  923.     /*
  924.      *   skip extension block
  925.      */
  926.     do
  927.     {
  928.         data = (uchar_t) _GETC (infile);
  929.  
  930.         if (ENDFILE (infile))
  931.             return (0);
  932.         if (data == ';')
  933.             return (1);
  934.         if (data == 0x21)
  935.             _SkipEB (infile, opt);
  936.  
  937.     } while (data != 0x2c);                /* ',' is ID start */
  938.  
  939.     data       = (uchar_t) _GETC (infile);        /* left coord */
  940.     id->i_x    = data + ((uchar_t) _GETC (infile) << 8);
  941.  
  942.     data       = (uchar_t) _GETC (infile);        /* top coord */
  943.     id->i_y    = data + ((uchar_t) _GETC (infile) << 8);
  944.  
  945.     data       = (uchar_t) _GETC (infile);        /* width */
  946.     id->i_dx   = data + ((uchar_t) _GETC (infile) << 8);
  947.  
  948.     data       = (uchar_t) _GETC (infile);        /* height */
  949.     id->i_dy   = data + ((uchar_t) _GETC (infile) << 8);
  950.  
  951.     data         = (uchar_t) _GETC (infile);        /* flag: */
  952.     id->i_gcm    = (data >> 7) & 0x01;        /* local color map? */
  953.     id->i_intlace= (data >> 6) & 0x01;        /* interlaced? */
  954.     id->i_bits   = (data & 7) + 1;
  955.     id->i_colors = 1 << id->i_bits;
  956.  
  957.     return (2);
  958. }
  959.  
  960.  
  961.  
  962.  
  963. /*------------------------------*/
  964. /*    _ScanCM            */
  965. /*------------------------------*/
  966. LOCAL void _ScanCM (infile, colors, cm, opt)
  967. int        infile;
  968. int        colors;
  969. char           *cm;
  970. int        opt;        /* SILENT, INQUIRE, VERBOSE */
  971. {
  972.  
  973. /*
  974.  *    read a color map (optional)
  975.  *
  976.  *          bits
  977.  *     7 6 5 4 3 2 1 0  Byte #
  978.  *    +---------------+
  979.  *    | red intensity |  1    Red value for color index 0
  980.  *    +---------------+
  981.  *    |green intensity|  2    Green value for color index 0
  982.  *    +---------------+
  983.  *    | blue intensity|  3    Blue value for color index 0
  984.  *    +---------------+
  985.  *    | red intensity |  4    Red value for color index 1
  986.  *    +---------------+
  987.  *    |green intensity|  5    Green value for color index 1
  988.  *    +---------------+
  989.  *    | blue intensity|  6    Blue value for color index 1
  990.  *    +---------------+
  991.  *    :        :    (Continues for remaining colors)
  992.  *
  993.  */
  994.  
  995.     reg_t char           *scan;
  996.     reg_t int        i;
  997.  
  998.  
  999.     if (opt != SILENT)
  1000.         printf (stderr, "\nRead color map\n");
  1001.  
  1002.     for (scan = cm, i = colors; i > 0; i--, scan += 3)
  1003.     {
  1004.         *scan =     (char) _GETC (infile);
  1005.         *(scan+1) = (char) _GETC (infile);
  1006.         *(scan+2) = (char) _GETC (infile);
  1007.  
  1008.         if (opt == VERBOSE)
  1009.         {
  1010.             fprintf (stderr, "addr:     %08lx %08lx %08lx\n",
  1011.                 (long) (scan),
  1012.                 (long) (scan+1),
  1013.                 (long) (scan+2));
  1014.             fprintf (stderr, "vals:     %02x %02x %02x\n",
  1015.                 (uint_t) (*scan),
  1016.                 (uint_t) (*(scan+1)),
  1017.                 (uint_t) (*(scan+2)));
  1018.         }
  1019.     }
  1020.  
  1021.     if (opt == VERBOSE)
  1022.     {
  1023.         printf ("\n     Color map for %d colors:\n\n", colors);
  1024.         for (scan = cm, i = colors; i > 0; i--, scan += 3)
  1025.             printf ("     %02x %02x %02x\n",
  1026.                 (uint_t) (*scan),
  1027.                 (uint_t) (*(scan+1)),
  1028.                 (uint_t) (*(scan+2)));
  1029.         printf ("\n");
  1030.     }
  1031. }
  1032.  
  1033.  
  1034.  
  1035. /*------------------------------*/
  1036. /*    _ScanMAGIC        */
  1037. /*------------------------------*/
  1038. LOCAL int _ScanMAGIC (infile, parse, opt)
  1039. int    infile;
  1040. char   *parse;
  1041. int    opt;
  1042. {
  1043.  
  1044. /*
  1045.  *    read chars from file "infile" and look for string "parse" from
  1046.  *    current file position. return 0 if no match at first mismatch.
  1047.  */
  1048.  
  1049.     reg_t char  *scan;
  1050.  
  1051.  
  1052.     for (scan = parse; *scan; scan++)
  1053.     {
  1054.         if (_GETC (infile) != (int) *scan)
  1055.             return (0);
  1056.     }
  1057.     return (!0);
  1058. }
  1059.  
  1060.  
  1061.  
  1062.  
  1063. /*------------------------------*/
  1064. /*    _GETC            */
  1065. /*------------------------------*/
  1066. LOCAL int _GETC (fd)
  1067. int    fd;
  1068. {
  1069.     reg_t int    ret;
  1070.     uchar_t        buf[10];
  1071.  
  1072.     ret = read (fd, buf, 1);
  1073.  
  1074.     if (ret < 0)
  1075.         _Eof = 1;
  1076.  
  1077.     return ((int) buf[0]);
  1078. }
  1079.  
  1080.  
  1081.  
  1082.  
  1083. /*------------------------------*/
  1084. /*    _GetKey            */
  1085. /*------------------------------*/
  1086. LOCAL int _GetKey ()
  1087. {
  1088.  
  1089. /*
  1090.  *    ckecks for a key and flushes keyboard buffer. same as check_key().
  1091.  */
  1092.     char c;
  1093.     
  1094.     if (_gs_rdy(0) > 0)            /* if CONSOLE has a char... */
  1095.     {
  1096.         while (_gs_rdy(0) > 0)        /* read char while there are */
  1097.             read(0, &c, 1);            /* chars to read (flush) */
  1098.         return (1);            /* yes, there was a key */
  1099.     }
  1100.     return (0);                /* no key */
  1101. }
  1102.  
  1103.