home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 309.lha / PBM_PLUS / ppm / ppmtogif.c < prev    next >
C/C++ Source or Header  |  1980-12-04  |  20KB  |  807 lines

  1. /* ppmtogif.c - read a portable pixmap and produce a GIF file
  2. **
  3. ** Based on GIFENCOD by David Rowley <mgardi@watdscu.waterloo.edu>.A
  4. ** Lempel-Zim compression based on "compress".
  5. **
  6. ** Copyright (C) 1989 by Jef Poskanzer.
  7. **
  8. ** Permission to use, copy, modify, and distribute this software and its
  9. ** documentation for any purpose and without fee is hereby granted, provided
  10. ** that the above copyright notice appear in all copies and that both that
  11. ** copyright notice and this permission notice appear in supporting
  12. ** documentation.  This software is provided "as is" without express or
  13. ** implied warranty.
  14. */
  15.  
  16. #include <stdio.h>
  17. #include "ppm.h"
  18. #include "ppmcmap.h"
  19.  
  20. #define MAXCOLORS 256
  21.  
  22. pixel **pixels;
  23. colorhash_table cht;
  24.  
  25. main( argc, argv )
  26. int argc;
  27. char *argv[];
  28.     {
  29.     FILE *ifd;
  30.     int argn, rows, cols, colors, i, BitsPerPixel;
  31.     pixval maxval;
  32.     colorhist_vector chv;
  33.     int Red[MAXCOLORS], Green[MAXCOLORS], Blue[MAXCOLORS];
  34.     int GetPixel();
  35.     char *usage = "[ppmfile]";
  36.  
  37.     pm_progname = argv[0];
  38.  
  39.     argn = 1;
  40.  
  41.     if ( argn < argc )
  42.     {
  43.     ifd = pm_openr( argv[argn] );
  44.     argn++;
  45.     }
  46.     else
  47.     ifd = stdin;
  48.  
  49.     if ( argn != argc )
  50.     pm_usage( usage );
  51.  
  52.     pixels = ppm_readppm( ifd, &cols, &rows, &maxval );
  53.  
  54.     pm_close( ifd );
  55.  
  56.     /* Figure out the colormap. */
  57.     fprintf( stderr, "(Computing colormap..." );
  58.     fflush( stderr );
  59.     chv = ppm_computecolorhist( pixels, cols, rows, MAXCOLORS, &colors );
  60.     if ( chv == (colorhist_vector) 0 )
  61.     pm_error(
  62.         "too many colors - try running the pixmap through 'ppmquant 256'",
  63.         0,0,0,0,0 );
  64.     fprintf( stderr, "  Done.  %d colors found.)\n", colors );
  65.  
  66.     /* Now turn the ppm colormap into the appropriate GIF colormap. */
  67.     if ( maxval > 255 )
  68.     fprintf(
  69.         stderr, "(Maxval is not 255 -- automatically rescaling colors.)\n");
  70.     for ( i = 0; i < colors; i++ )
  71.     {
  72.     if ( maxval == 255 )
  73.         {
  74.         Red[i] = PPM_GETR( chv[i].color );
  75.         Green[i] = PPM_GETG( chv[i].color );
  76.         Blue[i] = PPM_GETB( chv[i].color );
  77.         }
  78.     else
  79.         {
  80.         Red[i] = (int) PPM_GETR( chv[i].color ) * 255 / maxval;
  81.         Green[i] = (int) PPM_GETG( chv[i].color ) * 255 / maxval;
  82.         Blue[i] = (int) PPM_GETB( chv[i].color ) * 255 / maxval;
  83.         }
  84.     }
  85.     BitsPerPixel = colorstobpp( colors );
  86.  
  87.     /* And make a hash table for fast lookup. */
  88.     cht = ppm_colorhisttocolorhash( chv, colors );
  89.     ppm_freecolorhist( chv );
  90.  
  91.     /* All set, let's do it. */
  92.     GIFEncode(
  93.     stdout, cols, rows, 0, 0, BitsPerPixel, Red, Green, Blue, GetPixel );
  94.  
  95.     exit( 0 );
  96.     }
  97.  
  98. int
  99. colorstobpp( colors )
  100. int colors;
  101.     {
  102.     int bpp;
  103.  
  104.     if ( colors <= 2 )
  105.     bpp = 1;
  106.     else if ( colors <= 4 )
  107.     bpp = 2;
  108.     else if ( colors <= 8 )
  109.     bpp = 3;
  110.     else if ( colors <= 16 )
  111.     bpp = 4;
  112.     else if ( colors <= 32 )
  113.     bpp = 5;
  114.     else if ( colors <= 64 )
  115.     bpp = 6;
  116.     else if ( colors <= 128 )
  117.     bpp = 7;
  118.     else if ( colors <= 256 )
  119.     bpp = 8;
  120.     else
  121.     pm_error( "can't happen", 0,0,0,0,0 );
  122.  
  123.     return bpp;
  124.     }
  125.  
  126. GetPixel( x, y )
  127. int x, y;
  128.     {
  129.     int color;
  130.  
  131.     color = ppm_lookupcolor( cht, pixels[y][x] );
  132.     return color;
  133.     }
  134.  
  135.  
  136. /*****************************************************************************
  137.  *
  138.  * GIFENCODE.C    - GIF Image compression interface
  139.  *
  140.  * GIFEncode( FName, GHeight, GWidth, GInterlace, Background,
  141.  *            BitsPerPixel, Red, Green, Blue, GetPixel )
  142.  *
  143.  *****************************************************************************/
  144.  
  145. /*
  146.  * Pointer to function returning an int
  147.  */
  148. typedef int (* ifunptr)();
  149.  
  150. #define TRUE 1
  151. #define FALSE 0
  152.  
  153. int Width, Height;
  154. int curx, cury;
  155. long CountDown;
  156. int Pass = 0;
  157. int Interlace;
  158.  
  159. /*
  160.  * Bump the 'curx' and 'cury' to point to the next pixel
  161.  */
  162. BumpPixel()
  163. {
  164.         /*
  165.          * Bump the current X position
  166.          */
  167.         curx++;
  168.  
  169.         /*
  170.          * If we are at the end of a scan line, set curx back to the beginning
  171.          * If we are interlaced, bump the cury to the appropriate spot,
  172.          * otherwise, just increment it.
  173.          */
  174.         if( curx == Width ) {
  175.                 curx = 0;
  176.  
  177.                 if( !Interlace )
  178.                         cury++;
  179.                 else {
  180.                      switch( Pass ) {
  181.  
  182.                        case 0:
  183.                           cury += 8;
  184.                           if( cury >= Height ) {
  185.                                 Pass++;
  186.                                 cury = 4;
  187.                           }
  188.                           break;
  189.  
  190.                        case 1:
  191.                           cury += 8;
  192.                           if( cury >= Height ) {
  193.                                 Pass++;
  194.                                 cury = 2;
  195.                           }
  196.                           break;
  197.  
  198.                        case 2:
  199.                           cury += 4;
  200.                           if( cury >= Height ) {
  201.                              Pass++;
  202.                              cury = 1;
  203.                           }
  204.                           break;
  205.  
  206.                        case 3:
  207.                           cury += 2;
  208.                           break;
  209.                         }
  210.                 }
  211.         }
  212. }
  213.  
  214. /*
  215.  * Return the next pixel from the image
  216.  */
  217. GIFNextPixel( getpixel )
  218. ifunptr getpixel;
  219. {
  220.         int r;
  221.  
  222.         if( CountDown == 0 )
  223.                 return EOF;
  224.  
  225.         CountDown--;
  226.  
  227.         r = ( * getpixel )( curx, cury );
  228.  
  229.         BumpPixel();
  230.  
  231.         return r;
  232. }
  233.  
  234. /* public */
  235.  
  236. GIFEncode( fp, GWidth, GHeight, GInterlace, Background,
  237.            BitsPerPixel, Red, Green, Blue, GetPixel )
  238.  
  239. FILE *fp;
  240. int GWidth, GHeight;
  241. int GInterlace;
  242. int Background;
  243. int BitsPerPixel;
  244. int Red[], Green[], Blue[];
  245. ifunptr GetPixel;
  246.  
  247. {
  248.         int B;
  249.         int RWidth, RHeight;
  250.         int LeftOfs, TopOfs;
  251.         int Resolution;
  252.         int ColorMapSize;
  253.         int InitCodeSize;
  254.         int i;
  255.  
  256.         Interlace = GInterlace;
  257.  
  258.         ColorMapSize = 1 << BitsPerPixel;
  259.  
  260.         RWidth = Width = GWidth;
  261.         RHeight = Height = GHeight;
  262.         LeftOfs = TopOfs = 0;
  263.  
  264.         Resolution = BitsPerPixel;
  265.  
  266.         /*
  267.          * Calculate number of bits we are expecting
  268.          */
  269.         CountDown = (long)Width * (long)Height;
  270.  
  271.         /*
  272.          * Indicate which pass we are on (if interlace)
  273.          */
  274.         Pass = 0;
  275.  
  276.         /*
  277.          * The initial code size
  278.          */
  279.         if( BitsPerPixel <= 1 )
  280.                 InitCodeSize = 2;
  281.         else
  282.                 InitCodeSize = BitsPerPixel;
  283.  
  284.         /*
  285.          * Set up the current x and y position
  286.          */
  287.         curx = cury = 0;
  288.  
  289.         /*
  290.          * Write the Magic header
  291.          */
  292.         fwrite( "GIF87a", 1, 6, fp );
  293.  
  294.         /*
  295.          * Write out the screen width and height
  296.          */
  297.         Putword( RWidth, fp );
  298.         Putword( RHeight, fp );
  299.  
  300.         /*
  301.          * Indicate that there is a global colour map
  302.          */
  303.         B = 0x80;       /* Yes, there is a color map */
  304.  
  305.         /*
  306.          * OR in the resolution
  307.          */
  308.         B |= (Resolution - 1) << 5;
  309.  
  310.         /*
  311.          * OR in the Bits per Pixel
  312.          */
  313.         B |= (BitsPerPixel - 1);
  314.  
  315.         /*
  316.          * Write it out
  317.          */
  318.         fputc( B, fp );
  319.  
  320.         /*
  321.          * Write out the Background colour
  322.          */
  323.         fputc( Background, fp );
  324.  
  325.         /*
  326.          * Byte of 0's (future expansion)
  327.          */
  328.         fputc( 0, fp );
  329.  
  330.         /*
  331.          * Write out the Global Colour Map
  332.          */
  333.         for( i=0; i<ColorMapSize; i++ ) {
  334.                 fputc( Red[i], fp );
  335.                 fputc( Green[i], fp );
  336.                 fputc( Blue[i], fp );
  337.         }
  338.  
  339.         /*
  340.          * Write an Image separator
  341.          */
  342.         fputc( ',', fp );
  343.  
  344.         /*
  345.          * Write the Image header
  346.          */
  347.  
  348.         Putword( LeftOfs, fp );
  349.         Putword( TopOfs, fp );
  350.         Putword( Width, fp );
  351.         Putword( Height, fp );
  352.  
  353.         /*
  354.          * Write out whether or not the image is interlaced
  355.          */
  356.         if( Interlace )
  357.                 fputc( 0x40, fp );
  358.         else
  359.                 fputc( 0x00, fp );
  360.  
  361.         /*
  362.          * Write out the initial code size
  363.          */
  364.         fputc( InitCodeSize, fp );
  365.  
  366.         /*
  367.          * Go and actually compress the data
  368.          */
  369.         compress( InitCodeSize+1, fp, GetPixel );
  370.  
  371.         /*
  372.          * Write out a Zero-length packet (to end the series)
  373.          */
  374.         fputc( 0, fp );
  375.  
  376.         /*
  377.          * Write the GIF file terminator
  378.          */
  379.         fputc( ';', fp );
  380.  
  381.         /*
  382.          * And close the file
  383.          */
  384.         fclose( fp );
  385.  
  386. }
  387.  
  388. /*
  389.  * Write out a word to the GIF file
  390.  */
  391. Putword( w, fp )
  392. int w;
  393. FILE *fp;
  394. {
  395.         fputc( w & 0xff, fp );
  396.         fputc( (w / 256) & 0xff, fp );
  397. }
  398.  
  399.  
  400. /***************************************************************************
  401.  *
  402.  *  GIFCOMPR.C       - GIF Image compression routines
  403.  *
  404.  *  Lempel-Ziv compression based on 'compress'.  GIF modifications by
  405.  *  David Rowley (mgardi@watdcsu.waterloo.edu)
  406.  *
  407.  ***************************************************************************/
  408.  
  409. /*
  410.  * General DEFINEs
  411.  */
  412.  
  413. #define BITS    12
  414.  
  415. #define HSIZE  5003            /* 80% occupancy */
  416.  
  417. /*
  418.  * a code_int must be able to hold 2**BITS values of type int, and also -1
  419.  */
  420. typedef int             code_int;
  421.  
  422. #ifdef SIGNED_COMPARE_SLOW
  423. typedef unsigned long int count_int;
  424. typedef unsigned short int count_short;
  425. #else
  426. typedef long int          count_int;
  427. #endif
  428.  
  429. #ifdef NO_UCHAR
  430.  typedef char   char_type;
  431. #else
  432.  typedef        unsigned char   char_type;
  433. #endif /* UCHAR */
  434.  
  435. /*
  436.  *
  437.  * GIF Image compression - modified 'compress'
  438.  *
  439.  * Based on: compress.c - File compression ala IEEE Computer, June 1984.
  440.  *
  441.  * By Authors:  Spencer W. Thomas       (decvax!harpo!utah-cs!utah-gr!thomas)
  442.  *              Jim McKie               (decvax!mcvax!jim)
  443.  *              Steve Davies            (decvax!vax135!petsd!peora!srd)
  444.  *              Ken Turkowski           (decvax!decwrl!turtlevax!ken)
  445.  *              James A. Woods          (decvax!ihnp4!ames!jaw)
  446.  *              Joe Orost               (decvax!vax135!petsd!joe)
  447.  *
  448.  */
  449. #include <ctype.h>
  450. /* #include <signal.h> */
  451.  
  452. #define ARGVAL() (*++(*argv) || (--argc && *++argv))
  453.  
  454. int n_bits;                        /* number of bits/code */
  455. int maxbits = BITS;                /* user settable max # bits/code */
  456. code_int maxcode;                  /* maximum code, given n_bits */
  457. code_int maxmaxcode = (code_int)1 << BITS; /* should NEVER generate this
  458. code */
  459. #ifdef COMPATIBLE               /* But wrong! */
  460. # define MAXCODE(n_bits)        ((code_int) 1 << (n_bits) - 1)
  461. #else
  462. # define MAXCODE(n_bits)        (((code_int) 1 << (n_bits)) - 1)
  463. #endif /* COMPATIBLE */
  464.  
  465. count_int htab [HSIZE];
  466. unsigned short codetab [HSIZE];
  467. #define HashTabOf(i)       htab[i]
  468. #define CodeTabOf(i)    codetab[i]
  469.  
  470. code_int hsize = HSIZE;                 /* for dynamic table sizing */
  471. count_int fsize;
  472.  
  473. /*
  474.  * To save much memory, we overlay the table used by compress() with those
  475.  * used by decompress().  The tab_prefix table is the same size and type
  476.  * as the codetab.  The tab_suffix table needs 2**BITS characters.  We
  477.  * get this from the beginning of htab.  The output stack uses the rest
  478.  * of htab, and contains characters.  There is plenty of room for any
  479.  * possible stack (stack used to be 8000 characters).
  480.  */
  481.  
  482. #define tab_prefixof(i) CodeTabOf(i)
  483. #define tab_suffixof(i)        ((char_type *)(htab))[i]
  484. #define de_stack               ((char_type *)&tab_suffixof((code_int)1<<BITS))
  485.  
  486. code_int free_ent = 0;                  /* first unused entry */
  487. int exit_stat = 0;
  488.  
  489. /*
  490.  * block compression parameters -- after all codes are used up,
  491.  * and compression rate changes, start over.
  492.  */
  493. int clear_flg = 0;
  494.  
  495. int offset;
  496. long int in_count = 1;            /* length of input */
  497. long int out_count = 0;           /* # of codes output (for debugging) */
  498.  
  499. /*
  500.  * compress stdin to stdout
  501.  *
  502.  * Algorithm:  use open addressing double hashing (no chaining) on the
  503.  * prefix code / next character combination.  We do a variant of Knuth's
  504.  * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
  505.  * secondary probe.  Here, the modular division first probe is gives way
  506.  * to a faster exclusive-or manipulation.  Also do block compression with
  507.  * an adaptive reset, whereby the code table is cleared when the compression
  508.  * ratio decreases, but after the table fills.  The variable-length output
  509.  * codes are re-sized at this point, and a special CLEAR code is generated
  510.  * for the decompressor.  Late addition:  construct the table according to
  511.  * file size for noticeable speed improvement on small files.  Please direct
  512.  * questions about this implementation to ames!jaw.
  513.  */
  514.  
  515. int g_init_bits;
  516. FILE *g_outfile;
  517.  
  518. int ClearCode;
  519. int EOFCode;
  520.  
  521. compress( init_bits, outfile, ReadValue )
  522. int init_bits;
  523. FILE *outfile;
  524. ifunptr ReadValue;
  525. {
  526.     register long fcode;
  527.     register code_int i = 0;
  528.     register int c;
  529.     register code_int ent;
  530.     register code_int disp;
  531.     register code_int hsize_reg;
  532.     register int hshift;
  533.  
  534.     /*
  535.      * Set up the globals:  g_init_bits - initial number of bits
  536.      *                      g_outfile   - pointer to output file
  537.      */
  538.     g_init_bits = init_bits;
  539.     g_outfile = outfile;
  540.  
  541.     /*
  542.      * Set up the necessary values
  543.      */
  544.     offset = 0;
  545.     out_count = 0;
  546.     clear_flg = 0;
  547.     in_count = 1;
  548.     maxcode = MAXCODE(n_bits = g_init_bits);
  549.  
  550.     ClearCode = (1 << (init_bits - 1));
  551.     EOFCode = ClearCode + 1;
  552.     free_ent = ClearCode + 2;
  553.  
  554.     char_init();
  555.  
  556.     ent = GIFNextPixel( ReadValue );
  557.  
  558.     hshift = 0;
  559.     for ( fcode = (long) hsize;  fcode < 65536L; fcode *= 2L )
  560.         hshift++;
  561.     hshift = 8 - hshift;                /* set hash code range bound */
  562.  
  563.     hsize_reg = hsize;
  564.     cl_hash( (count_int) hsize_reg);            /* clear hash table */
  565.  
  566.     output( (code_int)ClearCode );
  567.  
  568. #ifdef SIGNED_COMPARE_SLOW
  569.     while ( (c = GIFNextPixel( ReadValue )) != (unsigned) EOF ) {
  570. #else
  571.     while ( (c = GIFNextPixel( ReadValue )) != EOF ) {
  572. #endif
  573.  
  574.         in_count++;
  575.  
  576.         fcode = (long) (((long) c << maxbits) + ent);
  577.         /* i = (((code_int)c << hshift) ~ ent);    /* xor hashing */
  578.         i = (((code_int)c << hshift) ^ ent);    /* xor hashing */
  579.  
  580.         if ( HashTabOf (i) == fcode ) {
  581.             ent = CodeTabOf (i);
  582.             continue;
  583.         } else if ( (long)HashTabOf (i) < 0 )      /* empty slot */
  584.             goto nomatch;
  585.         disp = hsize_reg - i;           /* secondary hash (after G. Knott) */
  586.         if ( i == 0 )
  587.             disp = 1;
  588. probe:
  589.         if ( (i -= disp) < 0 )
  590.             i += hsize_reg;
  591.  
  592.         if ( HashTabOf (i) == fcode ) {
  593.             ent = CodeTabOf (i);
  594.             continue;
  595.         }
  596.         if ( (long)HashTabOf (i) > 0 )
  597.             goto probe;
  598. nomatch:
  599.         output ( (code_int) ent );
  600.         out_count++;
  601.         ent = c;
  602. #ifdef SIGNED_COMPARE_SLOW
  603.         if ( (unsigned) free_ent < (unsigned) maxmaxcode) {
  604. #else
  605.         if ( free_ent < maxmaxcode ) {
  606. #endif
  607.             CodeTabOf (i) = free_ent++; /* code -> hashtable */
  608.             HashTabOf (i) = fcode;
  609.         } else
  610.                 cl_block();
  611.     }
  612.     /*
  613.      * Put out the final code.
  614.      */
  615.     output( (code_int)ent );
  616.     out_count++;
  617.     output( (code_int) EOFCode );
  618.  
  619.     return;
  620. }
  621.  
  622. /*****************************************************************
  623.  * TAG( output )
  624.  *
  625.  * Output the given code.
  626.  * Inputs:
  627.  *      code:   A n_bits-bit integer.  If == -1, then EOF.  This assumes
  628.  *              that n_bits =< (long)wordsize - 1.
  629.  * Outputs:
  630.  *      Outputs code to the file.
  631.  * Assumptions:
  632.  *      Chars are 8 bits long.
  633.  * Algorithm:
  634.  *      Maintain a BITS character long buffer (so that 8 codes will
  635.  * fit in it exactly).  Use the VAX insv instruction to insert each
  636.  * code in turn.  When the buffer fills up empty it and start over.
  637.  */
  638.  
  639. unsigned long cur_accum = 0;
  640. int cur_bits = 0;
  641.  
  642. unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
  643.                                   0x001F, 0x003F, 0x007F, 0x00FF,
  644.                                   0x01FF, 0x03FF, 0x07FF, 0x0FFF,
  645.                                   0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
  646.  
  647. output( code )
  648. code_int  code;
  649. {
  650.     cur_accum &= masks[ cur_bits ];
  651.  
  652.     if( cur_bits > 0 )
  653.         cur_accum |= ((long)code << cur_bits);
  654.     else
  655.         cur_accum = code;
  656.  
  657.     cur_bits += n_bits;
  658.  
  659.     while( cur_bits >= 8 ) {
  660.         char_out( (unsigned int)(cur_accum & 0xff) );
  661.         cur_accum >>= 8;
  662.         cur_bits -= 8;
  663.     }
  664.  
  665.     /*
  666.      * If the next entry is going to be too big for the code size,
  667.      * then increase it, if possible.
  668.      */
  669.    if ( free_ent > maxcode || clear_flg ) {
  670.  
  671.             if( clear_flg ) {
  672.  
  673.                 maxcode = MAXCODE (n_bits = g_init_bits);
  674.                 clear_flg = 0;
  675.  
  676.             } else {
  677.  
  678.                 n_bits++;
  679.                 if ( n_bits == maxbits )
  680.                     maxcode = maxmaxcode;
  681.                 else
  682.                     maxcode = MAXCODE(n_bits);
  683.             }
  684.         }
  685.  
  686.     if( code == EOFCode ) {
  687.         /*
  688.          * At EOF, write the rest of the buffer.
  689.          */
  690.         while( cur_bits > 0 ) {
  691.                 char_out( (unsigned int)(cur_accum & 0xff) );
  692.                 cur_accum >>= 8;
  693.                 cur_bits -= 8;
  694.         }
  695.  
  696.         flush_char();
  697.  
  698.         fflush( g_outfile );
  699.  
  700.         if( ferror( g_outfile ) )
  701.                 writeerr();
  702.     }
  703. }
  704.  
  705. /*
  706.  * Clear out the hash table
  707.  */
  708. cl_block ()             /* table clear for block compress */
  709. {
  710.  
  711.         cl_hash ( (count_int) hsize );
  712.         free_ent = ClearCode + 2;
  713.         clear_flg = 1;
  714.  
  715.         output( (code_int)ClearCode );
  716. }
  717.  
  718. cl_hash(hsize)          /* reset code table */
  719. register count_int hsize;
  720. {
  721.  
  722.         register count_int *htab_p = htab+hsize;
  723.  
  724.         register long i;
  725.         register long m1 = -1;
  726.  
  727.         i = hsize - 16;
  728.         do {                            /* might use Sys V memset(3) here */
  729.                 *(htab_p-16) = m1;
  730.                 *(htab_p-15) = m1;
  731.                 *(htab_p-14) = m1;
  732.                 *(htab_p-13) = m1;
  733.                 *(htab_p-12) = m1;
  734.                 *(htab_p-11) = m1;
  735.                 *(htab_p-10) = m1;
  736.                 *(htab_p-9) = m1;
  737.                 *(htab_p-8) = m1;
  738.                 *(htab_p-7) = m1;
  739.                 *(htab_p-6) = m1;
  740.                 *(htab_p-5) = m1;
  741.                 *(htab_p-4) = m1;
  742.                 *(htab_p-3) = m1;
  743.                 *(htab_p-2) = m1;
  744.                 *(htab_p-1) = m1;
  745.                 htab_p -= 16;
  746.         } while ((i -= 16) >= 0);
  747.  
  748.         for ( i += 16; i > 0; i-- )
  749.                 *--htab_p = m1;
  750. }
  751.  
  752. writeerr()
  753. {
  754.         printf( "error writing output file\n" );
  755.         exit(1);
  756. }
  757.  
  758. /******************************************************************************
  759.  *
  760.  * GIF Specific routines
  761.  *
  762.  ******************************************************************************/
  763.  
  764. /*
  765.  * Number of characters so far in this 'packet'
  766.  */
  767. int a_count;
  768.  
  769. /*
  770.  * Set up the 'byte output' routine
  771.  */
  772. char_init()
  773. {
  774.         a_count = 0;
  775. }
  776.  
  777. /*
  778.  * Define the storage for the packet accumulator
  779.  */
  780. char accum[ 256 ];
  781.  
  782. /*
  783.  * Add a character to the end of the current packet, and if it is 254
  784.  * characters, flush the packet to disk.
  785.  */
  786. char_out( c )
  787. int c;
  788. {
  789.         accum[ a_count++ ] = c;
  790.         if( a_count >= 254 )
  791.                 flush_char();
  792. }
  793.  
  794. /*
  795.  * Flush the packet to disk, and reset the accumulator
  796.  */
  797. flush_char()
  798. {
  799.         if( a_count > 0 ) {
  800.                 fputc( a_count, g_outfile );
  801.                 fwrite( accum, 1, a_count, g_outfile );
  802.                 a_count = 0;
  803.         }
  804. }
  805.  
  806. /* The End */
  807.