"Fossies" - the Fresh Open Source Software Archive

Member "libgd-2.3.3/src/gd_gif_out.c" (11 Sep 2021, 43178 Bytes) of package /linux/www/libgd-2.3.3.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "gd_gif_out.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.3.2_vs_2.3.3.

    1 /**
    2  * File: GIF Output
    3  *
    4  * Write GIF images.
    5  */
    6 
    7 #ifdef HAVE_CONFIG_H
    8 #include "config.h"
    9 #endif
   10 
   11 #include <stdio.h>
   12 #include <math.h>
   13 #include <string.h>
   14 #include <stdlib.h>
   15 #include "gd.h"
   16 #include "gdhelpers.h"
   17 
   18 /* Code drawn from ppmtogif.c, from the pbmplus package
   19 **
   20 ** Based on GIFENCOD by David Rowley <mgardi@watdscu.waterloo.edu>. A
   21 ** Lempel-Zim compression based on "compress".
   22 **
   23 ** Modified by Marcel Wijkstra <wijkstra@fwi.uva.nl>
   24 **
   25 ** Copyright (C) 1989 by Jef Poskanzer.
   26 **
   27 ** Permission to use, copy, modify, and distribute this software and its
   28 ** documentation for any purpose and without fee is hereby granted, provided
   29 ** that the above copyright notice appear in all copies and that both that
   30 ** copyright notice and this permission notice appear in supporting
   31 ** documentation.  This software is provided "as is" without express or
   32 ** implied warranty.
   33 **
   34 ** The Graphics Interchange Format(c) is the Copyright property of
   35 ** CompuServe Incorporated.  GIF(sm) is a Service Mark property of
   36 ** CompuServe Incorporated.
   37 */
   38 
   39 /* a code_int must be able to hold 2**GIFBITS values of type int, and also -1 */
   40 typedef int code_int;
   41 
   42 #ifdef SIGNED_COMPARE_SLOW
   43 typedef unsigned long int count_int;
   44 typedef unsigned short int count_short;
   45 #else /* SIGNED_COMPARE_SLOW */
   46 typedef long int count_int;
   47 #endif /* SIGNED_COMPARE_SLOW */
   48 
   49 /* 2.0.28: threadsafe */
   50 
   51 #define maxbits GIFBITS
   52 
   53 /* should NEVER generate this code */
   54 #define maxmaxcode ((code_int)1 << GIFBITS)
   55 
   56 #define HSIZE   5003    /* 80% occupancy */
   57 #define hsize   HSIZE   /* Apparently invariant, left over from compress */
   58 
   59 typedef struct {
   60     int Width, Height;
   61     int curx, cury;
   62     long CountDown;
   63     int Pass;
   64     int Interlace;
   65     int n_bits;
   66     code_int maxcode;
   67     count_int htab [HSIZE];
   68     unsigned short codetab [HSIZE];
   69     /* first unused entry */
   70     code_int free_ent;
   71     /* block compression parameters -- after all codes are used up,
   72      * and compression rate changes, start over. */
   73     int clear_flg;
   74     int offset;
   75     long int in_count;
   76     /* # of codes output (for debugging) */
   77     long int out_count;
   78     int g_init_bits;
   79     gdIOCtx * g_outfile;
   80     int ClearCode;
   81     int EOFCode;
   82     unsigned long cur_accum;
   83     int cur_bits;
   84     int a_count;
   85     char accum[ 256 ];
   86 } GifCtx;
   87 
   88 static int gifPutWord(int w, gdIOCtx *out);
   89 static int colorstobpp(int colors);
   90 static void BumpPixel(GifCtx *ctx);
   91 static int GIFNextPixel(gdImagePtr im, GifCtx *ctx);
   92 static void GIFEncode(gdIOCtxPtr fp, int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im);
   93 static void GIFAnimEncode(gdIOCtxPtr fp, int IWidth, int IHeight, int LeftOfs, int TopOfs, int GInterlace, int Transparent, int Delay, int Disposal, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im);
   94 static void compress(int init_bits, gdIOCtx *outfile, gdImagePtr im, GifCtx *ctx);
   95 static void output(code_int code, GifCtx *ctx);
   96 static void cl_block(GifCtx *ctx);
   97 static void cl_hash(register count_int chsize, GifCtx *ctx);
   98 static void char_init(GifCtx *ctx);
   99 static void char_out(int c, GifCtx *ctx);
  100 static void flush_char(GifCtx *ctx);
  101 
  102 static int _gdImageGifCtx(gdImagePtr im, gdIOCtxPtr out);
  103 static int _gdImageGifAnimAddCtx(gdImagePtr im, gdIOCtxPtr out,
  104                                        int LocalCM, int LeftOfs, int TopOfs,
  105                                        int Delay, int Disposal,
  106                                        gdImagePtr previm);
  107 
  108 
  109 
  110 /*
  111   Function: gdImageGifPtr
  112 
  113     Identical to <gdImageGif> except that it returns a pointer to a
  114     memory area with the GIF data. This memory must be freed by the
  115     caller when it is no longer needed.
  116 
  117     The caller *must* invoke <gdFree>, not _free()_.  This is because
  118     it is not guaranteed that libgd will use the same implementation
  119     of malloc, free, etc. as your proggram.
  120 
  121     The 'size' parameter receives the total size of the block of
  122     memory.
  123 
  124   Parameters:
  125 
  126     im      - The image to write
  127     size    - Output: the size of the resulting image.
  128 
  129   Returns:
  130 
  131     A pointer to the GIF data or NULL if an error occurred.
  132 
  133 */
  134 BGD_DECLARE(void *) gdImageGifPtr(gdImagePtr im, int *size)
  135 {
  136     void *rv;
  137     gdIOCtx *out = gdNewDynamicCtx(2048, NULL);
  138     if (out == NULL) return NULL;
  139     if (!_gdImageGifCtx(im, out)) {
  140         rv = gdDPExtractData(out, size);
  141     } else {
  142         rv = NULL;
  143     }
  144     out->gd_free(out);
  145     return rv;
  146 }
  147 
  148 /*
  149   Function: gdImageGif
  150 
  151     <gdImageGif> outputs the specified image to the specified file in
  152     GIF format. The file must be open for binary writing. (Under MSDOS
  153     and all versions of Windows, it is important to use "wb" as
  154     opposed to simply "w" as the mode when opening the file; under
  155     Unix there is no penalty for doing so). <gdImageGif> does not close
  156     the file; your code must do so.
  157 
  158     GIF does not support true color; GIF images can contain a maximum
  159     of 256 colors. If the image to be written is a truecolor image,
  160     such as those created with gdImageCreateTrueColor or loaded from a
  161     JPEG or a truecolor PNG image file, a palette-based temporary
  162     image will automatically be created internally using the
  163     <gdImageCreatePaletteFromTrueColor> function. The original image
  164     pixels are not modified. This conversion produces high quality
  165     palettes but does require some CPU time. If you are regularly
  166     converting truecolor to palette in this way, you should consider
  167     creating your image as a palette-based image in the first place.
  168 
  169   Variants:
  170 
  171     <gdImageGifCtx> outputs the image via a <gdIOCtx> struct.
  172 
  173     <gdImageGifPtr> stores the image in a large array of bytes.
  174 
  175   Parameters:
  176 
  177     im      - The image to write
  178     outFile - The FILE pointer to write the image to.
  179 
  180   Returns:
  181 
  182     Nothing
  183 
  184   Example:
  185 
  186     > gdImagePtr im;
  187     > int black, white;
  188     > FILE *out;
  189     > // Create the image
  190     > im = gdImageCreate(100, 100);
  191     > // Allocate background
  192     > white = gdImageColorAllocate(im, 255, 255, 255);
  193     > // Allocate drawing color
  194     > black = gdImageColorAllocate(im, 0, 0, 0);
  195     > // Draw rectangle
  196     > gdImageRectangle(im, 0, 0, 99, 99, black);
  197     > // Open output file in binary mode
  198     > out = fopen("rect.gif", "wb");
  199     > // Write GIF
  200     > gdImageGif(im, out);
  201     > // Close file
  202     > fclose(out);
  203     > // Destroy image
  204     > gdImageDestroy(im);
  205 
  206 */
  207 BGD_DECLARE(void) gdImageGif(gdImagePtr im, FILE *outFile)
  208 {
  209     gdIOCtx *out = gdNewFileCtx(outFile);
  210     if (out == NULL) return;
  211     gdImageGifCtx(im, out);
  212     out->gd_free(out);
  213 }
  214 
  215 /*
  216   Function: gdImageGifCtx
  217 
  218     Writes a GIF image via a <gdIOCtx>.  See <gdImageGif>.
  219 
  220   Parameters:
  221 
  222     im      - The image to write
  223     out     - The <gdIOCtx> struct used to do the writing.
  224 
  225   Returns:
  226 
  227     Nothing.
  228 
  229 */
  230 BGD_DECLARE(void) gdImageGifCtx(gdImagePtr im, gdIOCtxPtr out)
  231 {
  232     _gdImageGifCtx(im, out);
  233 }
  234 
  235 /* returns 0 on success, 1 on failure */
  236 static int _gdImageGifCtx(gdImagePtr im, gdIOCtxPtr out)
  237 {
  238     gdImagePtr pim = 0, tim = im;
  239     int interlace, BitsPerPixel;
  240     interlace = im->interlace;
  241 
  242     if(im->trueColor) {
  243         /* Expensive, but the only way that produces an
  244         acceptable result: mix down to a palette
  245         based temporary image. */
  246         pim = gdImageCreatePaletteFromTrueColor(im, 1, 256);
  247         if(!pim) {
  248             return 1;
  249         }
  250         tim = pim;
  251     }
  252 
  253     BitsPerPixel = colorstobpp(tim->colorsTotal);
  254 
  255     /* All set, let's do it. */
  256     GIFEncode(
  257         out, tim->sx, tim->sy, interlace, 0, tim->transparent, BitsPerPixel,
  258         tim->red, tim->green, tim->blue, tim);
  259 
  260     if(pim) {
  261         /* Destroy palette based temporary image. */
  262         gdImageDestroy( pim);
  263     }
  264 
  265     return 0;
  266 }
  267 
  268 
  269 /*
  270   Function: gdImageGifAnimBeginPtr
  271 
  272     Like <gdImageGifAnimBegin> except that it outputs to a memory
  273     buffer.  See <gdImageGifAnimBegin>.
  274 
  275     The returned memory must be freed by the caller when it is no
  276     longer needed. **The caller must invoke <gdFree>(), not free()**,
  277     unless the caller is absolutely certain that the same
  278     implementations of malloc, free, etc. are used both at library
  279     build time and at application build time (but don't; it could
  280     always change).
  281 
  282     The 'size' parameter receives the total size of the block of
  283     memory.
  284 
  285   Parameters:
  286 
  287     im          - The reference image
  288     size        - Output: the size in bytes of the result.
  289     GlobalCM    - Global colormap flag: 1 -> yes, 0 -> no, -1 -> do default
  290     Loops       - Loop count; 0 -> infinite, -1 means no loop
  291 
  292   Returns:
  293 
  294    A pointer to the resulting data (the contents of the start of the
  295    GIF) or NULL if an error occurred.
  296 
  297 */
  298 
  299 BGD_DECLARE(void *) gdImageGifAnimBeginPtr(gdImagePtr im, int *size, int GlobalCM, int Loops)
  300 {
  301     void *rv;
  302     gdIOCtx *out = gdNewDynamicCtx(2048, NULL);
  303     if (out == NULL) return NULL;
  304     gdImageGifAnimBeginCtx(im, out, GlobalCM, Loops);
  305     rv = gdDPExtractData(out, size);
  306     out->gd_free(out);
  307     return rv;
  308 }
  309 
  310 
  311 /*
  312   Function: gdImageGifAnimBegin
  313 
  314     This function must be called as the first function when creating a
  315     GIF animation. It writes the correct GIF file headers to selected
  316     file output, and prepares for frames to be added for the
  317     animation. The image argument is not used to produce an image
  318     frame to the file, it is only used to establish the GIF animation
  319     frame size, interlacing options and the color
  320     palette. <gdImageGifAnimAdd> is used to add the first and
  321     subsequent frames to the animation, and the animation must be
  322     terminated by writing a semicolon character (;) to it or by using
  323     gdImageGifAnimEnd to do that.
  324 
  325     The GlobalCM flag indicates if a global color map (or palette) is
  326     used in the GIF89A header. A nonzero value specifies that a global
  327     color map should be used to reduce the size of the animation. Of
  328     course, if the color maps of individual frames differ greatly, a
  329     global color map may not be a good idea. GlobalCM=1 means write
  330     global color map, GlobalCM=0 means do not, and GlobalCM=-1 means
  331     to do the default, which currently is to use a global color map.
  332 
  333     If Loops is 0 or greater, the Netscape 2.0 extension for animation
  334     loop count is written. 0 means infinite loop count. -1 means that
  335     the extension is not added which results in no looping. -1 is the
  336     default.
  337 
  338   Variants:
  339 
  340     <gdImageGifAnimBeginCtx> outputs the image via a <gdIOCtx> struct.
  341 
  342     <gdImageGifAnimBeginPtr> stores the image in a large array of bytes.
  343 
  344   Parameters:
  345 
  346     im          - The reference image
  347     outfile     - The output FILE*.
  348     GlobalCM    - Global colormap flag: 1 -> yes, 0 -> no, -1 -> do default
  349     Loops       - Loop count; 0 -> infinite, -1 means no loop
  350 
  351   Returns:
  352 
  353     Nothing.
  354 
  355   Example:
  356 
  357     See <gdImageGifAnimBegin>.
  358 
  359 */
  360 
  361 BGD_DECLARE(void) gdImageGifAnimBegin(gdImagePtr im, FILE *outFile, int GlobalCM, int Loops)
  362 {
  363     gdIOCtx *out = gdNewFileCtx(outFile);
  364     if (out == NULL) return;
  365     gdImageGifAnimBeginCtx(im, out, GlobalCM, Loops);
  366     out->gd_free(out);
  367 }
  368 
  369 
  370 
  371 /*
  372   Function: gdImageGifAnimBeginCtx
  373 
  374     Like <gdImageGifAnimBegin> except that it outputs to <gdIOCtx>.
  375     See <gdImageGifAnimBegin>.
  376 
  377   Parameters:
  378 
  379     im          - The reference image
  380     out         - Pointer to the output <gdIOCtx>.
  381     GlobalCM    - Global colormap flag: 1 -> yes, 0 -> no, -1 -> do default
  382     Loops       - Loop count; 0 -> infinite, -1 means no loop
  383 
  384   Returns:
  385 
  386     Nothing.
  387 
  388 */
  389 BGD_DECLARE(void) gdImageGifAnimBeginCtx(gdImagePtr im, gdIOCtxPtr out, int GlobalCM, int Loops)
  390 {
  391     int B;
  392     int RWidth, RHeight;
  393     int Resolution;
  394     int ColorMapSize;
  395     int BitsPerPixel;
  396     int Background = 0;
  397     int i;
  398 
  399     /* Default is to use global color map */
  400     if (GlobalCM < 0) {
  401         GlobalCM = 1;
  402     }
  403 
  404     BitsPerPixel = colorstobpp(im->colorsTotal);
  405     ColorMapSize = 1 << BitsPerPixel;
  406 
  407     RWidth = im->sx;
  408     RHeight = im->sy;
  409 
  410     Resolution = BitsPerPixel;
  411 
  412     /* Write the Magic header */
  413     gdPutBuf("GIF89a", 6, out);
  414 
  415     /* Write out the screen width and height */
  416     gifPutWord(RWidth, out);
  417     gifPutWord(RHeight, out);
  418 
  419     /* Indicate that there is a global colour map */
  420     B = GlobalCM ? 0x80 : 0;
  421 
  422     /* OR in the resolution */
  423     B |= (Resolution - 1) << 4;
  424 
  425     /* OR in the Bits per Pixel */
  426     B |= (BitsPerPixel - 1);
  427 
  428     /* Write it out */
  429     gdPutC(B, out);
  430 
  431     /* Write out the Background colour */
  432     gdPutC(Background, out);
  433 
  434     /* Byte of 0's (future expansion) */
  435     gdPutC(0, out);
  436 
  437     /* Write out the Global Colour Map */
  438     if(GlobalCM) {
  439         for(i = 0; i < ColorMapSize; ++i) {
  440             gdPutC(im->red[i], out);
  441             gdPutC(im->green[i], out);
  442             gdPutC(im->blue[i], out);
  443         }
  444     }
  445 
  446     if(Loops >= 0) {
  447         gdPutBuf("!\377\13NETSCAPE2.0\3\1", 16, out);
  448         gifPutWord(Loops, out);
  449         gdPutC(0, out);
  450     }
  451 }
  452 
  453 
  454 
  455 /*
  456   Function: gdImageGifAnimAddPtr
  457 
  458     Like <gdImageGifAnimAdd> (which contains more information) except
  459     that it stores the data to write into memory and returns a pointer
  460     to it.
  461 
  462     This memory must be freed by the caller when it is no longer
  463     needed. **The caller must invoke <gdFree>(), not free(),** unless
  464     the caller is absolutely certain that the same implementations of
  465     malloc, free, etc. are used both at library build time and at
  466     application build time (but don't; it could always change).
  467 
  468     The 'size' parameter receives the total size of the block of
  469     memory.
  470 
  471   Parameters:
  472 
  473     im          - The image to add.
  474     size        - Output: the size of the resulting buffer.
  475     LocalCM     - Flag.  If 1, use a local color map for this frame.
  476     LeftOfs     - Left offset of image in frame.
  477     TopOfs      - Top offset of image in frame.
  478     Delay       - Delay before next frame (in 1/100 seconds)
  479     Disposal    - MODE: How to treat this frame when the next one loads.
  480     previm      - NULL or a pointer to the previous image written.
  481 
  482   Returns:
  483 
  484     Pointer to the resulting data or NULL if an error occurred.
  485 
  486 */
  487 BGD_DECLARE(void *) gdImageGifAnimAddPtr(gdImagePtr im, int *size, int LocalCM,
  488                                          int LeftOfs, int TopOfs, int Delay,
  489                                          int Disposal, gdImagePtr previm)
  490 {
  491     void *rv;
  492     gdIOCtx *out = gdNewDynamicCtx(2048, NULL);
  493     if (out == NULL) return NULL;
  494     if (!_gdImageGifAnimAddCtx(im, out, LocalCM, LeftOfs, TopOfs, Delay, Disposal, previm)) {
  495         rv = gdDPExtractData(out, size);
  496     } else {
  497         rv = NULL;
  498     }
  499     out->gd_free(out);
  500     return rv;
  501 }
  502 
  503 
  504 /*
  505   Function: gdImageGifAnimAdd
  506 
  507     This function writes GIF animation frames to GIF animation, which
  508     was initialized with <gdImageGifAnimBegin>. With _LeftOfs_ and
  509     _TopOfs_ you can place this frame in different offset than (0,0)
  510     inside the image screen as defined in <gdImageGifAnimBegin>. Delay
  511     between the previous frame and this frame is in 1/100s
  512     units. _Disposal_ is usually <gdDisposalNone>, meaning that the
  513     pixels changed by this frame should remain on the display when the
  514     next frame begins to render, but can also be <gdDisposalUnknown>
  515     (not recommended), <gdDisposalRestoreBackground> (restores the
  516     first allocated color of the global palette), or
  517     <gdDisposalRestorePrevious> (restores the appearance of the
  518     affected area before the frame was rendered). Only
  519     <gdDisposalNone> is a sensible choice for the first frame. If
  520     _previm_ is passed, the built-in GIF optimizer will always use
  521     <gdDisposalNone> regardless of the Disposal parameter.
  522 
  523     Setting the _LocalCM_ flag to 1 adds a local palette for this
  524     image to the animation. Otherwise the global palette is assumed
  525     and the user must make sure the palettes match. Use
  526     <gdImagePaletteCopy> to do that.
  527 
  528     Automatic optimization is activated by giving the previous image
  529     as a parameter. This function then compares the images and only
  530     writes the changed pixels to the new frame in animation. The
  531     _Disposal_ parameter for optimized animations must be set to 1,
  532     also for the first frame. _LeftOfs_ and _TopOfs_ parameters are
  533     ignored for optimized frames. To achieve good optimization, it is
  534     usually best to use a single global color map. To allow
  535     <gdImageGifAnimAdd> to compress unchanged pixels via the use of a
  536     transparent color, the image must include a transparent color.
  537 
  538 
  539   Variants:
  540 
  541     <gdImageGifAnimAddCtx> outputs its data via a <gdIOCtx> struct.
  542 
  543     <gdImageGifAnimAddPtr> outputs its data to a memory buffer which
  544     it returns.
  545 
  546   Parameters:
  547 
  548     im          - The image to add.
  549     outfile     - The output FILE* being written.
  550     LocalCM     - Flag.  If 1, use a local color map for this frame.
  551     LeftOfs     - Left offset of image in frame.
  552     TopOfs      - Top offset of image in frame.
  553     Delay       - Delay before next frame (in 1/100 seconds)
  554     Disposal    - MODE: How to treat this frame when the next one loads.
  555     previm      - NULL or a pointer to the previous image written.
  556 
  557   Returns:
  558 
  559     Nothing.
  560 
  561   Example:
  562     (start code)
  563 
  564     {
  565     gdImagePtr im, im2, im3;
  566     int black, white, trans;
  567     FILE *out;
  568 
  569     im = gdImageCreate(100, 100);     // Create the image
  570     white = gdImageColorAllocate(im, 255, 255, 255); // Allocate background
  571     black = gdImageColorAllocate(im, 0, 0, 0); // Allocate drawing color
  572     trans = gdImageColorAllocate(im, 1, 1, 1); // trans clr for compression
  573     gdImageRectangle(im, 0, 0, 10, 10, black); // Draw rectangle
  574 
  575     out = fopen("anim.gif", "wb");// Open output file in binary mode
  576     gdImageGifAnimBegin(im, out, 1, 3);// Write GIF hdr, global clr map,loops
  577     // Write the first frame.  No local color map.  Delay = 1s
  578     gdImageGifAnimAdd(im, out, 0, 0, 0, 100, 1, NULL);
  579 
  580     // construct the second frame
  581     im2 = gdImageCreate(100, 100);
  582     (void)gdImageColorAllocate(im2, 255, 255, 255); // White background
  583     gdImagePaletteCopy (im2, im);  // Make sure the palette is identical
  584     gdImageRectangle(im2, 0, 0, 15, 15, black);    // Draw something
  585     // Allow animation compression with transparent pixels
  586     gdImageColorTransparent (im2, trans);
  587     gdImageGifAnimAdd(im2, out, 0, 0, 0, 100, 1, im);  // Add second frame
  588 
  589     // construct the third frame
  590     im3 = gdImageCreate(100, 100);
  591     (void)gdImageColorAllocate(im3, 255, 255, 255); // white background
  592     gdImagePaletteCopy (im3, im); // Make sure the palette is identical
  593     gdImageRectangle(im3, 0, 0, 15, 20, black); // Draw something
  594     // Allow animation compression with transparent pixels
  595     gdImageColorTransparent (im3, trans);
  596     // Add the third frame, compressing against the second one
  597     gdImageGifAnimAdd(im3, out, 0, 0, 0, 100, 1, im2);
  598     gdImageGifAnimEnd(out);  // End marker, same as putc(';', out);
  599     fclose(out); // Close file
  600 
  601     // Destroy images
  602     gdImageDestroy(im);
  603     gdImageDestroy(im2);
  604     gdImageDestroy(im3);
  605     }
  606 
  607     (end code)
  608 */
  609 
  610 BGD_DECLARE(void) gdImageGifAnimAdd(gdImagePtr im, FILE *outFile, int LocalCM,
  611                                     int LeftOfs, int TopOfs, int Delay,
  612                                     int Disposal, gdImagePtr previm)
  613 {
  614     gdIOCtx *out = gdNewFileCtx(outFile);
  615     if (out == NULL) return;
  616     gdImageGifAnimAddCtx(im, out, LocalCM, LeftOfs, TopOfs, Delay, Disposal, previm);
  617     out->gd_free(out);
  618 }
  619 
  620 static int comparewithmap(gdImagePtr im1, gdImagePtr im2, int c1, int c2, int *colorMap)
  621 {
  622     if(!colorMap) {
  623         return c1 == c2;
  624     }
  625 
  626     if(-2 != colorMap[c1]) {
  627         return colorMap[c1] == c2;
  628     }
  629 
  630     return (colorMap[c1] = gdImageColorExactAlpha(im2, im1->red[c1], im1->green[c1], im1->blue[c1], im1->alpha[c1])) == c2;
  631 }
  632 
  633 /*
  634   Function: gdImageGifAnimAddCtx
  635 
  636     Adds an animation frame via a <gdIOCtxPtr>.  See gdImageGifAnimAdd>.
  637 
  638   Parameters:
  639 
  640     im          - The image to add.
  641     out         - The output <gdIOCtxPtr>.
  642     LocalCM     - Flag.  If 1, use a local color map for this frame.
  643     LeftOfs     - Left offset of image in frame.
  644     TopOfs      - Top offset of image in frame.
  645     Delay       - Delay before next frame (in 1/100 seconds)
  646     Disposal    - MODE: How to treat this frame when the next one loads.
  647     previm      - NULL or a pointer to the previous image written.
  648 
  649   Returns:
  650 
  651     Nothing.
  652 
  653 */
  654 BGD_DECLARE(void) gdImageGifAnimAddCtx(gdImagePtr im, gdIOCtxPtr out,
  655                                        int LocalCM, int LeftOfs, int TopOfs,
  656                                        int Delay, int Disposal,
  657                                        gdImagePtr previm)
  658 {
  659     _gdImageGifAnimAddCtx(im, out, LocalCM, LeftOfs, TopOfs, Delay, Disposal, previm);
  660 }
  661 
  662 /* returns 0 on success, 1 on failure */
  663 static int _gdImageGifAnimAddCtx(gdImagePtr im, gdIOCtxPtr out,
  664                                        int LocalCM, int LeftOfs, int TopOfs,
  665                                        int Delay, int Disposal,
  666                                        gdImagePtr previm)
  667 {
  668     gdImagePtr pim = NULL, tim = im;
  669     int interlace, transparent, BitsPerPixel;
  670     interlace = im->interlace;
  671     transparent = im->transparent;
  672 
  673     /* Default is no local color map */
  674     if(LocalCM < 0) {
  675         LocalCM = 0;
  676     }
  677 
  678     if(im->trueColor) {
  679         /* Expensive, but the only way that produces an
  680             acceptable result: mix down to a palette
  681             based temporary image. */
  682         pim = gdImageCreatePaletteFromTrueColor(im, 1, 256);
  683         if (!pim) {
  684             return 1;
  685         }
  686         tim = pim;
  687     }
  688 
  689     if (previm) {
  690         /* create optimized animation.  Compare this image to
  691            the previous image and crop the temporary copy of
  692            current image to include only changed rectangular
  693            area.  Also replace unchanged pixels inside this
  694            area with transparent color.  Transparent color
  695            needs to be already allocated!
  696            Preconditions:
  697            TopOfs, LeftOfs are assumed 0
  698 
  699            Images should be of same size.  If not, a temporary
  700            copy is made with the same size as previous image.
  701 
  702         */
  703         gdImagePtr prev_pim = 0, prev_tim = previm;
  704         int x, y;
  705         int min_x = 0;
  706         int min_y = tim->sy;
  707         int max_x = 0;
  708         int max_y = 0;
  709         int colorMap[256];
  710 
  711         if (previm->trueColor) {
  712             prev_pim = gdImageCreatePaletteFromTrueColor(previm, 1, 256);
  713             if (!prev_pim) {
  714                 goto fail_end;
  715             }
  716             prev_tim = prev_pim;
  717         }
  718 
  719         for (x = 0; x < 256; ++x) {
  720             colorMap[x] = -2;
  721         }
  722 
  723         /* First find bounding box of changed areas. */
  724         /* first find the top changed row */
  725         for (y = 0; y < tim->sy; ++y) {
  726             for (x = 0; x < tim->sx; ++x) {
  727                 if (!comparewithmap(prev_tim, tim,
  728                                     prev_tim->pixels[y][x],
  729                                     tim->pixels[y][x],
  730                                     colorMap)) {
  731                     min_y = max_y = y;
  732                     min_x = max_x = x;
  733                     goto break_top;
  734                 }
  735             }
  736         }
  737 
  738 break_top:
  739         if (tim->sy == min_y) {
  740             /* No changes in this frame!! Encode empty image. */
  741             transparent = 0;
  742             min_x = min_y = 1;
  743             max_x = max_y = 0;
  744         } else {
  745             /* Then the bottom row */
  746             for (y = tim->sy - 1; y > min_y; --y) {
  747                 for (x = 0; x < tim->sx; ++x) {
  748                     if (!gdImageBoundsSafe(prev_tim, x,y))
  749                         continue;
  750                     if (!comparewithmap
  751                             (prev_tim, tim,
  752                              prev_tim->pixels[y][x],
  753                              tim->pixels[y][x],
  754                              colorMap)) {
  755                         max_y = y;
  756                         if(x < min_x) {
  757                             min_x = x;
  758                         }
  759                         if(x > max_x) {
  760                             max_x = x;
  761                         }
  762                         goto break_bot;
  763                     }
  764                 }
  765             }
  766 
  767 break_bot:
  768             /* left side */
  769             for (x = 0; x < min_x; ++x) {
  770                 for (y = min_y; y <= max_y; ++y) {
  771                     if (!gdImageBoundsSafe(prev_tim, x,y))
  772                         continue;
  773                     if (!comparewithmap
  774                             (prev_tim, tim,
  775                              prev_tim->pixels[y][x],
  776                              tim->pixels[y][x],
  777                              colorMap)) {
  778                         min_x = x;
  779                         goto break_left;
  780                     }
  781                 }
  782             }
  783 
  784 break_left:
  785             /* right side */
  786             for (x = tim->sx - 1; x > max_x; --x) {
  787                 for (y = min_y; y <= max_y; ++y) {
  788                     if (!gdImageBoundsSafe(prev_tim, x,y))
  789                         continue;
  790                     if (!comparewithmap
  791                             (prev_tim, tim,
  792                              prev_tim->pixels[y][x],
  793                              tim->pixels[y][x],
  794                              colorMap)) {
  795                         max_x = x;
  796                         goto break_right;
  797                     }
  798                 }
  799             }
  800 
  801 break_right:
  802             ;
  803         }
  804 
  805         LeftOfs = min_x;
  806         TopOfs = min_y;
  807         Disposal = 1;
  808 
  809         /* Make a copy of the image with the new offsets.
  810            But only if necessary. */
  811         if (min_x != 0 || max_x != tim->sx - 1
  812                 || min_y != 0 || max_y != tim->sy - 1
  813                 || transparent >= 0) {
  814 
  815             gdImagePtr pim2 = gdImageCreate(max_x-min_x + 1, max_y-min_y + 1);
  816 
  817             if (!pim2) {
  818                 if (prev_pim) {
  819                     gdImageDestroy(prev_pim);
  820                 }
  821                 goto fail_end;
  822             }
  823 
  824             gdImagePaletteCopy(pim2, LocalCM ? tim : prev_tim);
  825             gdImageCopy(pim2, tim, 0, 0, min_x, min_y,
  826                         max_x - min_x + 1, max_y - min_y + 1);
  827 
  828             if (pim) {
  829                 gdImageDestroy(pim);
  830             }
  831 
  832             tim = pim = pim2;
  833         }
  834 
  835         /* now let's compare pixels for transparent
  836            optimization.  But only if transparent is set. */
  837         if (transparent >= 0) {
  838             for(y = 0; y < tim->sy; ++y) {
  839                 for (x = 0; x < tim->sx; ++x) {
  840                     if(comparewithmap
  841                             (prev_tim, tim,
  842                              prev_tim->pixels[min_y + y][min_x + x],
  843                              tim->pixels[y][x], 0)) {
  844                         gdImageSetPixel(tim, x, y, transparent);
  845                         break;
  846                     }
  847                 }
  848             }
  849         }
  850 
  851         if(prev_pim) {
  852             gdImageDestroy(prev_pim);
  853         }
  854     }
  855 
  856     BitsPerPixel = colorstobpp(tim->colorsTotal);
  857 
  858     /* All set, let's do it. */
  859     GIFAnimEncode(
  860         out, tim->sx, tim->sy, LeftOfs, TopOfs, interlace, transparent,
  861         Delay, Disposal, BitsPerPixel,
  862         LocalCM ? tim->red : 0, tim->green, tim->blue, tim);
  863     if(pim) {
  864         /* Destroy palette based temporary image. */
  865         gdImageDestroy(pim);
  866     }
  867     return 0;
  868 
  869 fail_end:
  870     if(pim) {
  871         /* Destroy palette based temporary image. */
  872         gdImageDestroy(pim);
  873     }
  874     return 1;
  875 }
  876 
  877 
  878 
  879 /*
  880   Function: gdImageGifAnimEnd
  881 
  882     Terminates the GIF file properly.
  883 
  884     (Previous versions of this function's documentation suggested just
  885     manually writing a semicolon (';') instead since that is all this
  886     function does.  While that has no longer changed, we now suggest
  887     that you do not do this and instead always call
  888     <gdImageGifAnimEnd> (or equivalent) since later versions could
  889     possibly do more or different things.)
  890 
  891   Variants:
  892 
  893     <gdImageGifAnimEndCtx> outputs its data via a <gdIOCtx> struct.
  894 
  895     <gdImageGifAnimEndPtr> outputs its data to a memory buffer which
  896     it returns.
  897 
  898   Parameters:
  899 
  900     outfile     - the destination FILE*.
  901 
  902   Returns:
  903 
  904     Nothing.
  905 
  906 */
  907 
  908 BGD_DECLARE(void) gdImageGifAnimEnd(FILE *outFile)
  909 {
  910 #if 1
  911     putc(';', outFile);
  912 #else
  913     gdIOCtx *out = gdNewFileCtx(outFile);
  914     if (out == NULL) return;
  915     gdImageGifAnimEndCtx(out);
  916     out->gd_free(out);
  917 #endif
  918 }
  919 
  920 /*
  921   Function: gdImageGifAnimEndPtr
  922 
  923     Like <gdImageGifAnimEnd> (which contains more information) except
  924     that it stores the data to write into memory and returns a pointer
  925     to it.
  926 
  927     This memory must be freed by the caller when it is no longer
  928     needed. **The caller must invoke <gdFree>(), not free(),** unless
  929     the caller is absolutely certain that the same implementations of
  930     malloc, free, etc. are used both at library build time and at
  931     application build time (but don't; it could always change).
  932 
  933     The 'size' parameter receives the total size of the block of
  934     memory.
  935 
  936   Parameters:
  937 
  938     size        - Output: the size of the resulting buffer.
  939 
  940   Returns:
  941 
  942     Pointer to the resulting data or NULL if an error occurred.
  943 
  944 */
  945 
  946 BGD_DECLARE(void *) gdImageGifAnimEndPtr(int *size)
  947 {
  948     char *rv = (char *) gdMalloc(1);
  949     if(!rv) {
  950         return 0;
  951     }
  952     *rv = ';';
  953     *size = 1;
  954     return (void *)rv;
  955 }
  956 
  957 /*
  958   Function: gdImageGifAnimEndCtx
  959 
  960     Like <gdImageGifAnimEnd>, but writes its data via a <gdIOCtx>.
  961 
  962   Parameters:
  963 
  964     out         - the destination <gdIOCtx>.
  965 
  966   Returns:
  967 
  968     Nothing.
  969 
  970 */
  971 
  972 BGD_DECLARE(void) gdImageGifAnimEndCtx(gdIOCtx *out)
  973 {
  974     /*
  975      * Write the GIF file terminator
  976      */
  977     gdPutC(';', out);
  978 }
  979 
  980 static int colorstobpp(int colors)
  981 {
  982     int bpp = 0;
  983 
  984     if(colors <= 2)
  985         bpp = 1;
  986     else if(colors <= 4)
  987         bpp = 2;
  988     else if(colors <= 8)
  989         bpp = 3;
  990     else if(colors <= 16)
  991         bpp = 4;
  992     else if(colors <= 32)
  993         bpp = 5;
  994     else if(colors <= 64)
  995         bpp = 6;
  996     else if(colors <= 128)
  997         bpp = 7;
  998     else if(colors <= 256)
  999         bpp = 8;
 1000 
 1001     return bpp;
 1002 }
 1003 
 1004 /*****************************************************************************
 1005  *
 1006  * GIFENCODE.C    - GIF Image compression interface
 1007  *
 1008  * GIFEncode( FName, GHeight, GWidth, GInterlace, Background, Transparent,
 1009  *            BitsPerPixel, Red, Green, Blue, gdImagePtr )
 1010  *
 1011  *****************************************************************************/
 1012 
 1013 #define TRUE 1
 1014 #define FALSE 0
 1015 
 1016 /* Bump the 'curx' and 'cury' to point to the next pixel */
 1017 static void BumpPixel(GifCtx *ctx)
 1018 {
 1019     /* Bump the current X position */
 1020     ++(ctx->curx);
 1021 
 1022     /* If we are at the end of a scan line, set curx back to the beginning
 1023      * If we are interlaced, bump the cury to the appropriate spot,
 1024      * otherwise, just increment it. */
 1025     if(ctx->curx == ctx->Width) {
 1026         ctx->curx = 0;
 1027 
 1028         if(!ctx->Interlace) {
 1029             ++(ctx->cury);
 1030         } else {
 1031             switch(ctx->Pass) {
 1032 
 1033             case 0:
 1034                 ctx->cury += 8;
 1035                 if(ctx->cury >= ctx->Height) {
 1036                     ++(ctx->Pass);
 1037                     ctx->cury = 4;
 1038                 }
 1039                 break;
 1040 
 1041             case 1:
 1042                 ctx->cury += 8;
 1043                 if(ctx->cury >= ctx->Height) {
 1044                     ++(ctx->Pass);
 1045                     ctx->cury = 2;
 1046                 }
 1047                 break;
 1048 
 1049             case 2:
 1050                 ctx->cury += 4;
 1051                 if(ctx->cury >= ctx->Height) {
 1052                     ++(ctx->Pass);
 1053                     ctx->cury = 1;
 1054                 }
 1055                 break;
 1056 
 1057             case 3:
 1058                 ctx->cury += 2;
 1059                 break;
 1060             }
 1061         }
 1062     }
 1063 }
 1064 
 1065 /* Return the next pixel from the image */
 1066 static int GIFNextPixel(gdImagePtr im, GifCtx *ctx)
 1067 {
 1068     int r;
 1069 
 1070     if(ctx->CountDown == 0) {
 1071         return EOF;
 1072     }
 1073 
 1074     --(ctx->CountDown);
 1075 
 1076     r = gdImageGetPixel(im, ctx->curx, ctx->cury);
 1077 
 1078     BumpPixel(ctx);
 1079 
 1080     return r;
 1081 }
 1082 
 1083 /* public */
 1084 
 1085 static void GIFEncode(gdIOCtxPtr fp, int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im)
 1086 {
 1087     int B;
 1088     int RWidth, RHeight;
 1089     int LeftOfs, TopOfs;
 1090     int Resolution;
 1091     int ColorMapSize;
 1092     int InitCodeSize;
 1093     int i;
 1094     GifCtx ctx;
 1095 
 1096     memset(&ctx, 0, sizeof(ctx));
 1097 
 1098     ctx.Interlace = GInterlace;
 1099     ctx.in_count = 1;
 1100 
 1101     ColorMapSize = 1 << BitsPerPixel;
 1102 
 1103     RWidth = ctx.Width = GWidth;
 1104     RHeight = ctx.Height = GHeight;
 1105     LeftOfs = TopOfs = 0;
 1106 
 1107     Resolution = BitsPerPixel;
 1108 
 1109     /* Calculate number of bits we are expecting */
 1110     ctx.CountDown = (long)ctx.Width * (long)ctx.Height;
 1111 
 1112     /* Indicate which pass we are on (if interlace) */
 1113     ctx.Pass = 0;
 1114 
 1115     /* The initial code size */
 1116     if(BitsPerPixel <= 1) {
 1117         InitCodeSize = 2;
 1118     } else {
 1119         InitCodeSize = BitsPerPixel;
 1120     }
 1121 
 1122     /* Set up the current x and y position */
 1123     ctx.curx = ctx.cury = 0;
 1124 
 1125     /* Write the Magic header */
 1126     gdPutBuf(Transparent < 0 ? "GIF87a" : "GIF89a", 6, fp);
 1127 
 1128     /* Write out the screen width and height */
 1129     gifPutWord(RWidth, fp);
 1130     gifPutWord(RHeight, fp);
 1131 
 1132     /* Indicate that there is a global colour map */
 1133     /* Yes, there is a color map */
 1134     B = 0x80;
 1135 
 1136     /* OR in the resolution */
 1137     B |= (Resolution - 1) << 4;
 1138 
 1139     /* OR in the Bits per Pixel */
 1140     B |= (BitsPerPixel - 1);
 1141 
 1142     /* Write it out */
 1143     gdPutC(B, fp);
 1144 
 1145     /* Write out the Background colour */
 1146     gdPutC(Background, fp);
 1147 
 1148     /* Byte of 0's (future expansion) */
 1149     gdPutC(0, fp);
 1150 
 1151     /* Write out the Global Colour Map */
 1152     for(i = 0; i < ColorMapSize; ++i) {
 1153         gdPutC(Red[i], fp);
 1154         gdPutC(Green[i], fp);
 1155         gdPutC(Blue[i], fp);
 1156     }
 1157 
 1158     /* Write out extension for transparent colour index, if necessary. */
 1159     if(Transparent >= 0) {
 1160         gdPutC('!', fp);
 1161         gdPutC(0xf9, fp);
 1162         gdPutC(4, fp);
 1163         gdPutC(1, fp);
 1164         gdPutC(0, fp);
 1165         gdPutC(0, fp);
 1166         gdPutC((unsigned char) Transparent, fp);
 1167         gdPutC(0, fp);
 1168     }
 1169 
 1170     /* Write an Image separator */
 1171     gdPutC(',', fp);
 1172 
 1173     /* Write the Image header */
 1174     gifPutWord(LeftOfs, fp);
 1175     gifPutWord(TopOfs, fp);
 1176     gifPutWord(ctx.Width, fp);
 1177     gifPutWord(ctx.Height, fp);
 1178 
 1179     /* Write out whether or not the image is interlaced */
 1180     if(ctx.Interlace) {
 1181         gdPutC(0x40, fp);
 1182     } else {
 1183         gdPutC(0x00, fp);
 1184     }
 1185 
 1186     /* Write out the initial code size */
 1187     gdPutC(InitCodeSize, fp);
 1188 
 1189     /* Go and actually compress the data */
 1190     compress(InitCodeSize + 1, fp, im, &ctx);
 1191 
 1192     /* Write out a Zero-length packet (to end the series) */
 1193     gdPutC(0, fp);
 1194 
 1195     /* Write the GIF file terminator */
 1196     gdPutC(';', fp);
 1197 }
 1198 
 1199 static void GIFAnimEncode(gdIOCtxPtr fp, int IWidth, int IHeight, int LeftOfs, int TopOfs, int GInterlace, int Transparent, int Delay, int Disposal, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im)
 1200 {
 1201     int B;
 1202     int ColorMapSize;
 1203     int InitCodeSize;
 1204     int i;
 1205     GifCtx ctx;
 1206 
 1207     memset(&ctx, 0, sizeof(ctx));
 1208 
 1209     ctx.Interlace = GInterlace;
 1210     ctx.in_count = 1;
 1211 
 1212     ColorMapSize = 1 << BitsPerPixel;
 1213 
 1214     if(LeftOfs < 0) {
 1215         LeftOfs = 0;
 1216     }
 1217     if(TopOfs < 0) {
 1218         TopOfs = 0;
 1219     }
 1220     if(Delay < 0) {
 1221         Delay = 100;
 1222     }
 1223     if(Disposal < 0) {
 1224         Disposal = 1;
 1225     }
 1226 
 1227     ctx.Width = IWidth;
 1228     ctx.Height = IHeight;
 1229 
 1230     /* Calculate number of bits we are expecting */
 1231     ctx.CountDown = (long)ctx.Width * (long)ctx.Height;
 1232 
 1233     /* Indicate which pass we are on (if interlace) */
 1234     ctx.Pass = 0;
 1235 
 1236     /* The initial code size */
 1237     if(BitsPerPixel <= 1) {
 1238         InitCodeSize = 2;
 1239     } else {
 1240         InitCodeSize = BitsPerPixel;
 1241     }
 1242 
 1243     /* Set up the current x and y position */
 1244     ctx.curx = ctx.cury = 0;
 1245 
 1246     /* Write out extension for image animation and looping */
 1247     gdPutC('!', fp);
 1248     gdPutC(0xf9, fp);
 1249     gdPutC(4, fp);
 1250     gdPutC((Transparent >= 0 ? 1 : 0) | (Disposal << 2), fp);
 1251     gdPutC((unsigned char)(Delay & 255), fp);
 1252     gdPutC((unsigned char)((Delay >> 8) & 255), fp);
 1253     gdPutC((unsigned char) Transparent, fp);
 1254     gdPutC(0, fp);
 1255 
 1256     /* Write an Image separator */
 1257     gdPutC(',', fp);
 1258 
 1259     /* Write out the Image header */
 1260     gifPutWord(LeftOfs, fp);
 1261     gifPutWord(TopOfs, fp);
 1262     gifPutWord(ctx.Width, fp);
 1263     gifPutWord(ctx.Height, fp);
 1264 
 1265     /* Indicate that there is a local colour map */
 1266     B = (Red && Green && Blue) ? 0x80 : 0;
 1267 
 1268     /* OR in the interlacing */
 1269     B |= ctx.Interlace ? 0x40 : 0;
 1270 
 1271     /* OR in the Bits per Pixel */
 1272     B |= (Red && Green && Blue) ? (BitsPerPixel - 1) : 0;
 1273 
 1274     /* Write it out */
 1275     gdPutC(B, fp);
 1276 
 1277     /* Write out the Local Colour Map */
 1278     if(Red && Green && Blue) {
 1279         for(i = 0; i < ColorMapSize; ++i) {
 1280             gdPutC(Red[i], fp);
 1281             gdPutC(Green[i], fp);
 1282             gdPutC(Blue[i], fp);
 1283         }
 1284     }
 1285 
 1286     /* Write out the initial code size */
 1287     gdPutC(InitCodeSize, fp);
 1288 
 1289     /* Go and actually compress the data */
 1290     compress(InitCodeSize + 1, fp, im, &ctx);
 1291 
 1292     /* Write out a Zero-length packet (to end the series) */
 1293     gdPutC(0, fp);
 1294 }
 1295 
 1296 /***************************************************************************
 1297  *
 1298  *  GIFCOMPR.C       - GIF Image compression routines
 1299  *
 1300  *  Lempel-Ziv compression based on 'compress'.  GIF modifications by
 1301  *  David Rowley (mgardi@watdcsu.waterloo.edu)
 1302  *
 1303  ***************************************************************************/
 1304 
 1305 /* General DEFINEs */
 1306 
 1307 #define GIFBITS 12
 1308 
 1309 #ifdef NO_UCHAR
 1310 typedef char char_type;
 1311 #else /* NO_UCHAR */
 1312 typedef unsigned char char_type;
 1313 #endif /* NO_UCHAR */
 1314 
 1315 /*
 1316  *
 1317  * GIF Image compression - modified 'compress'
 1318  *
 1319  * Based on: compress.c - File compression ala IEEE Computer, June 1984.
 1320  *
 1321  * By Authors:  Spencer W. Thomas       (decvax!harpo!utah-cs!utah-gr!thomas)
 1322  *              Jim McKie               (decvax!mcvax!jim)
 1323  *              Steve Davies            (decvax!vax135!petsd!peora!srd)
 1324  *              Ken Turkowski           (decvax!decwrl!turtlevax!ken)
 1325  *              James A. Woods          (decvax!ihnp4!ames!jaw)
 1326  *              Joe Orost               (decvax!vax135!petsd!joe)
 1327  *
 1328  */
 1329 #include <ctype.h>
 1330 
 1331 #define ARGVAL() (*++(*argv) || (--argc && *++argv))
 1332 
 1333 #ifdef COMPATIBLE /* But wrong! */
 1334 #   define MAXCODE(n_bits) ((code_int) 1 << (n_bits) - 1)
 1335 #else /* COMPATIBLE */
 1336 #   define MAXCODE(n_bits) (((code_int) 1 << (n_bits)) - 1)
 1337 #endif /* COMPATIBLE */
 1338 
 1339 #define HashTabOf(i) ctx->htab[i]
 1340 #define CodeTabOf(i) ctx->codetab[i]
 1341 
 1342 
 1343 /*
 1344  * To save much memory, we overlay the table used by compress() with those
 1345  * used by decompress().  The tab_prefix table is the same size and type
 1346  * as the codetab.  The tab_suffix table needs 2**GIFBITS characters.  We
 1347  * get this from the beginning of htab.  The output stack uses the rest
 1348  * of htab, and contains characters.  There is plenty of room for any
 1349  * possible stack (stack used to be 8000 characters).
 1350  */
 1351 
 1352 #define tab_prefixof(i) CodeTabOf(i)
 1353 #define tab_suffixof(i) ((char_type*)(htab))[i]
 1354 #define de_stack ((char_type*)&tab_suffixof((code_int)1 << GIFBITS))
 1355 
 1356 /*
 1357  * compress stdin to stdout
 1358  *
 1359  * Algorithm:  use open addressing double hashing (no chaining) on the
 1360  * prefix code / next character combination.  We do a variant of Knuth's
 1361  * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
 1362  * secondary probe.  Here, the modular division first probe is gives way
 1363  * to a faster exclusive-or manipulation.  Also do block compression with
 1364  * an adaptive reset, whereby the code table is cleared when the compression
 1365  * ratio decreases, but after the table fills.  The variable-length output
 1366  * codes are re-sized at this point, and a special CLEAR code is generated
 1367  * for the decompressor.  Late addition:  construct the table according to
 1368  * file size for noticeable speed improvement on small files.  Please direct
 1369  * questions about this implementation to ames!jaw.
 1370  */
 1371 
 1372 static void output(code_int code, GifCtx *ctx);
 1373 
 1374 static void compress(int init_bits, gdIOCtxPtr outfile, gdImagePtr im, GifCtx *ctx)
 1375 {
 1376     register long fcode;
 1377     register code_int i;
 1378     register int c;
 1379     register code_int ent;
 1380     register code_int disp;
 1381     register code_int hsize_reg;
 1382     register int hshift;
 1383 
 1384     /* Set up the globals:
 1385      *  g_init_bits - initial number of bits
 1386      *  g_outfile   - pointer to output file */
 1387     ctx->g_init_bits = init_bits;
 1388     ctx->g_outfile = outfile;
 1389 
 1390     /* Set up the necessary values */
 1391     ctx->offset = 0;
 1392     ctx->out_count = 0;
 1393     ctx->clear_flg = 0;
 1394     ctx->in_count = 1;
 1395     ctx->maxcode = MAXCODE(ctx->n_bits = ctx->g_init_bits);
 1396 
 1397     ctx->ClearCode = (1 << (init_bits - 1));
 1398     ctx->EOFCode = ctx->ClearCode + 1;
 1399     ctx->free_ent = ctx->ClearCode + 2;
 1400 
 1401     char_init(ctx);
 1402 
 1403     ent = GIFNextPixel(im, ctx);
 1404 
 1405     hshift = 0;
 1406     for(fcode = (long)hsize; fcode < 65536L; fcode *= 2L) {
 1407         ++hshift;
 1408     }
 1409     hshift = 8 - hshift; /* set hash code range bound */
 1410 
 1411     hsize_reg = hsize;
 1412     cl_hash((count_int) hsize_reg, ctx); /* clear hash table */
 1413 
 1414     output((code_int)ctx->ClearCode, ctx);
 1415 
 1416 #ifdef SIGNED_COMPARE_SLOW
 1417     while((c = GIFNextPixel(im, ctx)) != (unsigned) EOF) {
 1418 #else /* SIGNED_COMPARE_SLOW */
 1419     while((c = GIFNextPixel(im, ctx)) != EOF) {
 1420 #endif /* SIGNED_COMPARE_SLOW */
 1421 
 1422         ++(ctx->in_count);
 1423 
 1424         fcode = (long) (((long) c << maxbits) + ent);
 1425         i = (((code_int)c << hshift) ^ ent); /* xor hashing */
 1426 
 1427         if(HashTabOf(i) == fcode) {
 1428             ent = CodeTabOf (i);
 1429             continue;
 1430         } else if ((long)HashTabOf (i) < 0) {/* empty slot */
 1431             goto nomatch;
 1432         }
 1433 
 1434         disp = hsize_reg - i; /* secondary hash (after G. Knott) */
 1435 
 1436         if(i == 0) {
 1437             disp = 1;
 1438         }
 1439 
 1440 probe:
 1441         if((i -= disp) < 0) {
 1442             i += hsize_reg;
 1443         }
 1444 
 1445         if(HashTabOf(i) == fcode) {
 1446             ent = CodeTabOf (i);
 1447             continue;
 1448         }
 1449 
 1450         if((long)HashTabOf(i) > 0) {
 1451             goto probe;
 1452         }
 1453 
 1454 nomatch:
 1455         output((code_int) ent, ctx);
 1456         ++(ctx->out_count);
 1457         ent = c;
 1458 #ifdef SIGNED_COMPARE_SLOW
 1459         if((unsigned) ctx->free_ent < (unsigned) maxmaxcode) {
 1460 #else /*SIGNED_COMPARE_SLOW*/
 1461         if (ctx->free_ent < maxmaxcode) {  /* } */
 1462 #endif /*SIGNED_COMPARE_SLOW*/
 1463             CodeTabOf(i) = ctx->free_ent++; /* code -> hashtable */
 1464             HashTabOf(i) = fcode;
 1465         } else {
 1466             cl_block(ctx);
 1467         }
 1468     }
 1469 
 1470     /* Put out the final code. */
 1471     output((code_int)ent, ctx);
 1472     ++(ctx->out_count);
 1473     output((code_int) ctx->EOFCode, ctx);
 1474 }
 1475 
 1476 /*****************************************************************
 1477  * TAG( output )
 1478  *
 1479  * Output the given code.
 1480  * Inputs:
 1481  *      code:   A n_bits-bit integer.  If == -1, then EOF.  This assumes
 1482  *              that n_bits =< (long)wordsize - 1.
 1483  * Outputs:
 1484  *      Outputs code to the file.
 1485  * Assumptions:
 1486  *      Chars are 8 bits long.
 1487  * Algorithm:
 1488  *      Maintain a GIFBITS character long buffer (so that 8 codes will
 1489  * fit in it exactly).  Use the VAX insv instruction to insert each
 1490  * code in turn.  When the buffer fills up empty it and start over.
 1491  */
 1492 
 1493 static const unsigned long masks[] = {
 1494     0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
 1495     0x001F, 0x003F, 0x007F, 0x00FF,
 1496     0x01FF, 0x03FF, 0x07FF, 0x0FFF,
 1497     0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF
 1498 };
 1499 
 1500 /* Arbitrary value to mark output is done.  When we see EOFCode, then we don't
 1501  * expect to see any more data.  If we do (e.g. corrupt image inputs), cur_bits
 1502  * might be negative, so flag it to return early.
 1503  */
 1504 #define CUR_BITS_FINISHED -1000
 1505 
 1506 static void output(code_int code, GifCtx *ctx)
 1507 {
 1508     if (ctx->cur_bits == CUR_BITS_FINISHED)
 1509         return;
 1510     ctx->cur_accum &= masks[ctx->cur_bits];
 1511 
 1512     if(ctx->cur_bits > 0) {
 1513         ctx->cur_accum |= ((long)code << ctx->cur_bits);
 1514     } else {
 1515         ctx->cur_accum = code;
 1516     }
 1517 
 1518     ctx->cur_bits += ctx->n_bits;
 1519 
 1520     while(ctx->cur_bits >= 8) {
 1521         char_out((unsigned int)(ctx->cur_accum & 0xff), ctx);
 1522         ctx->cur_accum >>= 8;
 1523         ctx->cur_bits -= 8;
 1524     }
 1525 
 1526     /*
 1527      * If the next entry is going to be too big for the code size,
 1528      * then increase it, if possible.
 1529      */
 1530     if(ctx->free_ent > ctx->maxcode || ctx->clear_flg) {
 1531         if(ctx->clear_flg) {
 1532             ctx->maxcode = MAXCODE (ctx->n_bits = ctx->g_init_bits);
 1533             ctx->clear_flg = 0;
 1534         } else {
 1535             ++(ctx->n_bits);
 1536             if(ctx->n_bits == maxbits) {
 1537                 ctx->maxcode = maxmaxcode;
 1538             } else {
 1539                 ctx->maxcode = MAXCODE(ctx->n_bits);
 1540             }
 1541         }
 1542     }
 1543 
 1544     if(code == ctx->EOFCode) {
 1545         /* At EOF, write the rest of the buffer. */
 1546         while(ctx->cur_bits > 0) {
 1547             char_out((unsigned int)(ctx->cur_accum & 0xff), ctx);
 1548             ctx->cur_accum >>= 8;
 1549             ctx->cur_bits -= 8;
 1550         }
 1551         /* Flag that it's done to prevent re-entry. */
 1552         ctx->cur_bits = CUR_BITS_FINISHED;
 1553 
 1554         flush_char(ctx);
 1555     }
 1556 }
 1557 
 1558 /*
 1559  * Clear out the hash table
 1560  */
 1561 static void cl_block (GifCtx *ctx) /* table clear for block compress */
 1562 {
 1563     cl_hash((count_int) hsize, ctx);
 1564     ctx->free_ent = ctx->ClearCode + 2;
 1565     ctx->clear_flg = 1;
 1566 
 1567     output((code_int)ctx->ClearCode, ctx);
 1568 }
 1569 
 1570 static void cl_hash(register count_int chsize, GifCtx *ctx) /* reset code table */
 1571 {
 1572     register count_int *htab_p = ctx->htab+chsize;
 1573     register long i;
 1574     register long m1 = -1;
 1575 
 1576     i = chsize - 16;
 1577     do { /* might use Sys V memset(3) here */
 1578         *(htab_p - 16) = m1;
 1579         *(htab_p - 15) = m1;
 1580         *(htab_p - 14) = m1;
 1581         *(htab_p - 13) = m1;
 1582         *(htab_p - 12) = m1;
 1583         *(htab_p - 11) = m1;
 1584         *(htab_p - 10) = m1;
 1585         *(htab_p - 9) = m1;
 1586         *(htab_p - 8) = m1;
 1587         *(htab_p - 7) = m1;
 1588         *(htab_p - 6) = m1;
 1589         *(htab_p - 5) = m1;
 1590         *(htab_p - 4) = m1;
 1591         *(htab_p - 3) = m1;
 1592         *(htab_p - 2) = m1;
 1593         *(htab_p - 1) = m1;
 1594         htab_p -= 16;
 1595     } while((i -= 16) >= 0);
 1596 
 1597     for(i += 16; i > 0; --i) {
 1598         *--htab_p = m1;
 1599     }
 1600 }
 1601 
 1602 /******************************************************************************
 1603  *
 1604  * GIF Specific routines
 1605  *
 1606  ******************************************************************************/
 1607 
 1608 /*
 1609  * Set up the 'byte output' routine
 1610  */
 1611 static void char_init(GifCtx *ctx)
 1612 {
 1613     ctx->a_count = 0;
 1614 }
 1615 
 1616 /*
 1617  * Add a character to the end of the current packet, and if it is 254
 1618  * characters, flush the packet to disk.
 1619  */
 1620 static void char_out(int c, GifCtx *ctx)
 1621 {
 1622     ctx->accum[ctx->a_count++] = c;
 1623     if(ctx->a_count >= 254) {
 1624         flush_char(ctx);
 1625     }
 1626 }
 1627 
 1628 /*
 1629  * Flush the packet to disk, and reset the accumulator
 1630  */
 1631 static void flush_char(GifCtx *ctx)
 1632 {
 1633     if(ctx->a_count > 0) {
 1634         gdPutC(ctx->a_count, ctx->g_outfile);
 1635         gdPutBuf(ctx->accum, ctx->a_count, ctx->g_outfile);
 1636         ctx->a_count = 0;
 1637     }
 1638 }
 1639 
 1640 static int gifPutWord(int w, gdIOCtx *out)
 1641 {
 1642     /* Byte order is little-endian */
 1643     gdPutC(w & 0xFF, out);
 1644     gdPutC((w >> 8) & 0xFF, out);
 1645     return 0;
 1646 }