Back to index

php5  5.3.10
Classes | Defines | Typedefs | Functions | Variables
gd_gif_out.c File Reference
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include "gd.h"
#include <ctype.h>

Go to the source code of this file.

Classes

struct  GifCtx

Defines

#define maxbits   GIFBITS
#define maxmaxcode   ((code_int)1 << GIFBITS)
#define HSIZE   5003 /* 80% occupancy */
#define hsize
#define TRUE   1
#define FALSE   0
#define GIFBITS   12
#define ARGVAL()   (*++(*argv) || (--argc && *++argv))
#define MAXCODE(n_bits)   (((code_int) 1 << (n_bits)) - 1)
#define HashTabOf(i)   ctx->htab[i]
#define CodeTabOf(i)   ctx->codetab[i]
#define tab_prefixof(i)   CodeTabOf(i)
#define tab_suffixof(i)   ((char_type*)(htab))[i]
#define de_stack   ((char_type*)&tab_suffixof((code_int)1<<GIFBITS))

Typedefs

typedef int code_int
typedef long int count_int
typedef unsigned char char_type

Functions

static int gifPutWord (int w, gdIOCtx *out)
static int colorstobpp (int colors)
static void BumpPixel (GifCtx *ctx)
static int GIFNextPixel (gdImagePtr im, GifCtx *ctx)
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)
static void compress (int init_bits, gdIOCtx *outfile, gdImagePtr im, GifCtx *ctx)
static void output (code_int code, GifCtx *ctx)
static void cl_block (GifCtx *ctx)
static void cl_hash (register count_int chsize, GifCtx *ctx)
static void char_init (GifCtx *ctx)
static void char_out (int c, GifCtx *ctx)
static void flush_char (GifCtx *ctx)
void * gdImageGifPtr (gdImagePtr im, int *size)
void gdImageGif (gdImagePtr im, FILE *outFile)
void gdImageGifCtx (gdImagePtr im, gdIOCtxPtr out)
static void compress (int init_bits, gdIOCtxPtr outfile, gdImagePtr im, GifCtx *ctx)

Variables

static unsigned long masks []

Class Documentation

struct GifCtx

Definition at line 50 of file gd_gif_out.c.

Collaboration diagram for GifCtx:
Class Members
int a_count
char accum
int clear_flg
int ClearCode
unsigned short codetab
long CountDown
unsigned long cur_accum
int cur_bits
int curx
int cury
int EOFCode
code_int free_ent
int g_init_bits
gdIOCtx * g_outfile
int Height
count_int htab
long int in_count
int Interlace
code_int maxcode
int n_bits
int offset
long int out_count
int Pass
int Width

Define Documentation

#define ARGVAL ( )    (*++(*argv) || (--argc && *++argv))

Definition at line 446 of file gd_gif_out.c.

#define CodeTabOf (   i)    ctx->codetab[i]

Definition at line 455 of file gd_gif_out.c.

Definition at line 469 of file gd_gif_out.c.

#define FALSE   0

Definition at line 176 of file gd_gif_out.c.

#define GIFBITS   12

Definition at line 422 of file gd_gif_out.c.

#define HashTabOf (   i)    ctx->htab[i]

Definition at line 454 of file gd_gif_out.c.

#define HSIZE   5003 /* 80% occupancy */

Definition at line 47 of file gd_gif_out.c.

#define hsize
Value:
HSIZE            /* Apparently invariant, left over from 
                                   compress */

Definition at line 48 of file gd_gif_out.c.

#define maxbits   GIFBITS

Definition at line 42 of file gd_gif_out.c.

#define MAXCODE (   n_bits)    (((code_int) 1 << (n_bits)) - 1)

Definition at line 451 of file gd_gif_out.c.

#define maxmaxcode   ((code_int)1 << GIFBITS)

Definition at line 45 of file gd_gif_out.c.

#define tab_prefixof (   i)    CodeTabOf(i)

Definition at line 467 of file gd_gif_out.c.

#define tab_suffixof (   i)    ((char_type*)(htab))[i]

Definition at line 468 of file gd_gif_out.c.

#define TRUE   1

Definition at line 175 of file gd_gif_out.c.


Typedef Documentation

typedef unsigned char char_type

Definition at line 427 of file gd_gif_out.c.

typedef int code_int

Definition at line 31 of file gd_gif_out.c.

typedef long int count_int

Definition at line 37 of file gd_gif_out.c.


Function Documentation

static void BumpPixel ( GifCtx ctx) [static]

Definition at line 181 of file gd_gif_out.c.

{
        /*
         * Bump the current X position
         */
        ++(ctx->curx);

        /*
         * If we are at the end of a scan line, set curx back to the beginning
         * If we are interlaced, bump the cury to the appropriate spot,
         * otherwise, just increment it.
         */
        if( ctx->curx == ctx->Width ) {
                ctx->curx = 0;

                if( !ctx->Interlace )
                        ++(ctx->cury);
                else {
                     switch( ctx->Pass ) {

                       case 0:
                          ctx->cury += 8;
                          if( ctx->cury >= ctx->Height ) {
                                ++(ctx->Pass);
                                ctx->cury = 4;
                          }
                          break;

                       case 1:
                          ctx->cury += 8;
                          if( ctx->cury >= ctx->Height ) {
                                ++(ctx->Pass);
                                ctx->cury = 2;
                          }
                          break;

                       case 2:
                          ctx->cury += 4;
                          if( ctx->cury >= ctx->Height ) {
                             ++(ctx->Pass);
                             ctx->cury = 1;
                          }
                          break;

                       case 3:
                          ctx->cury += 2;
                          break;
                        }
                }
        }

Here is the caller graph for this function:

static void char_init ( GifCtx ctx) [static]

Definition at line 721 of file gd_gif_out.c.

{
        ctx->a_count = 0;

Here is the caller graph for this function:

static void char_out ( int  c,
GifCtx ctx 
) [static]

Definition at line 731 of file gd_gif_out.c.

{
        ctx->accum[ ctx->a_count++ ] = c;
        if( ctx->a_count >= 254 )
                flush_char(ctx);

Here is the call graph for this function:

Here is the caller graph for this function:

static void cl_block ( GifCtx ctx) [static]

Definition at line 666 of file gd_gif_out.c.

{

        cl_hash ( (count_int) hsize, ctx );
        ctx->free_ent = ctx->ClearCode + 2;
        ctx->clear_flg = 1;

        output( (code_int)ctx->ClearCode, ctx);

Here is the call graph for this function:

Here is the caller graph for this function:

static void cl_hash ( register count_int  chsize,
GifCtx ctx 
) [static]

Definition at line 677 of file gd_gif_out.c.

{

        register count_int *htab_p = ctx->htab+chsize;

        register long i;
        register long m1 = -1;

        i = chsize - 16;
        do {                            /* might use Sys V memset(3) here */
                *(htab_p-16) = m1;
                *(htab_p-15) = m1;
                *(htab_p-14) = m1;
                *(htab_p-13) = m1;
                *(htab_p-12) = m1;
                *(htab_p-11) = m1;
                *(htab_p-10) = m1;
                *(htab_p-9) = m1;
                *(htab_p-8) = m1;
                *(htab_p-7) = m1;
                *(htab_p-6) = m1;
                *(htab_p-5) = m1;
                *(htab_p-4) = m1;
                *(htab_p-3) = m1;
                *(htab_p-2) = m1;
                *(htab_p-1) = m1;
                htab_p -= 16;
        } while ((i -= 16) >= 0);

        for ( i += 16; i > 0; --i )
                *--htab_p = m1;

Here is the caller graph for this function:

static int colorstobpp ( int  colors) [static]

Definition at line 143 of file gd_gif_out.c.

{
    int bpp = 0;

    if ( colors <= 2 )
        bpp = 1;
    else if ( colors <= 4 )
        bpp = 2;
    else if ( colors <= 8 )
        bpp = 3;
    else if ( colors <= 16 )
        bpp = 4;
    else if ( colors <= 32 )
        bpp = 5;
    else if ( colors <= 64 )
        bpp = 6;
    else if ( colors <= 128 )
        bpp = 7;
    else if ( colors <= 256 )
        bpp = 8;
    return bpp;

Here is the caller graph for this function:

static void compress ( int  init_bits,
gdIOCtx outfile,
gdImagePtr  im,
GifCtx ctx 
) [static]
static void compress ( int  init_bits,
gdIOCtxPtr  outfile,
gdImagePtr  im,
GifCtx ctx 
) [static]

Definition at line 491 of file gd_gif_out.c.

{
    register long fcode;
    register code_int i /* = 0 */;
    register int c;
    register code_int ent;
    register code_int disp;
    register code_int hsize_reg;
    register int hshift;

    /*
     * Set up the globals:  g_init_bits - initial number of bits
     *                      g_outfile   - pointer to output file
     */
    ctx->g_init_bits = init_bits;
    ctx->g_outfile = outfile;

    /*
     * Set up the necessary values
     */
    ctx->offset = 0;
    ctx->out_count = 0;
    ctx->clear_flg = 0;
    ctx->in_count = 1;
    ctx->maxcode = MAXCODE(ctx->n_bits = ctx->g_init_bits);

    ctx->ClearCode = (1 << (init_bits - 1));
    ctx->EOFCode = ctx->ClearCode + 1;
    ctx->free_ent = ctx->ClearCode + 2;

    char_init(ctx);

    ent = GIFNextPixel( im, ctx );

    hshift = 0;
    for ( fcode = (long) hsize;  fcode < 65536L; fcode *= 2L )
        ++hshift;
    hshift = 8 - hshift;                /* set hash code range bound */

    hsize_reg = hsize;
    cl_hash( (count_int) hsize_reg, ctx );            /* clear hash table */

    output( (code_int)ctx->ClearCode, ctx );

#ifdef SIGNED_COMPARE_SLOW
    while ( (c = GIFNextPixel( im )) != (unsigned) EOF ) {
#else /*SIGNED_COMPARE_SLOW*/
    while ( (c = GIFNextPixel( im, ctx )) != EOF ) {  /* } */
#endif /*SIGNED_COMPARE_SLOW*/

        ++(ctx->in_count);

        fcode = (long) (((long) c << maxbits) + ent);
        i = (((code_int)c << hshift) ^ ent);    /* xor hashing */

        if ( HashTabOf (i) == fcode ) {
            ent = CodeTabOf (i);
            continue;
        } else if ( (long)HashTabOf (i) < 0 )      /* empty slot */
            goto nomatch;
        disp = hsize_reg - i;           /* secondary hash (after G. Knott) */
        if ( i == 0 )
            disp = 1;
probe:
        if ( (i -= disp) < 0 )
            i += hsize_reg;

        if ( HashTabOf (i) == fcode ) {
            ent = CodeTabOf (i);
            continue;
        }
        if ( (long)HashTabOf (i) > 0 )
            goto probe;
nomatch:
        output ( (code_int) ent, ctx );
        ++(ctx->out_count);
        ent = c;
#ifdef SIGNED_COMPARE_SLOW
        if ( (unsigned) ctx->free_ent < (unsigned) maxmaxcode) {
#else /*SIGNED_COMPARE_SLOW*/
        if ( ctx->free_ent < maxmaxcode ) {  /* } */
#endif /*SIGNED_COMPARE_SLOW*/
            CodeTabOf (i) = ctx->free_ent++; /* code -> hashtable */
            HashTabOf (i) = fcode;
        } else
                cl_block(ctx);
    }
    /*
     * Put out the final code.
     */
    output( (code_int)ent, ctx );
    ++(ctx->out_count);
    output( (code_int) ctx->EOFCode, ctx );

Here is the call graph for this function:

static void flush_char ( GifCtx ctx) [static]

Definition at line 742 of file gd_gif_out.c.

{
        if( ctx->a_count > 0 ) {
                gdPutC( ctx->a_count, ctx->g_outfile );
                gdPutBuf( ctx->accum, ctx->a_count, ctx->g_outfile );
                ctx->a_count = 0;
        }

Here is the call graph for this function:

Here is the caller graph for this function:

void gdImageGif ( gdImagePtr  im,
FILE *  outFile 
)

Definition at line 109 of file gd_gif_out.c.

{
  gdIOCtx *out = gdNewFileCtx (outFile);
  gdImageGifCtx (im, out);
  out->gd_free (out);

Here is the call graph for this function:

void gdImageGifCtx ( gdImagePtr  im,
gdIOCtxPtr  out 
)

Definition at line 116 of file gd_gif_out.c.

{
       gdImagePtr pim = 0, tim = im;
       int interlace, BitsPerPixel;
       interlace = im->interlace;
       if (im->trueColor) {
              /* Expensive, but the only way that produces an
                     acceptable result: mix down to a palette
                     based temporary image. */
              pim = gdImageCreatePaletteFromTrueColor(im, 1, 256);
              if (!pim) {
                     return;
              }
              tim = pim; 
       }
       BitsPerPixel = colorstobpp(tim->colorsTotal);
       /* All set, let's do it. */
       GIFEncode(
              out, tim->sx, tim->sy, tim->interlace, 0, tim->transparent, BitsPerPixel,
              tim->red, tim->green, tim->blue, tim);
       if (pim) {
              /* Destroy palette based temporary image. */
              gdImageDestroy(      pim);
       }

Here is the call graph for this function:

void* gdImageGifPtr ( gdImagePtr  im,
int size 
)

Definition at line 99 of file gd_gif_out.c.

{
  void *rv;
  gdIOCtx *out = gdNewDynamicCtx (2048, NULL);
  gdImageGifCtx (im, out);
  rv = gdDPExtractData (out, size);
  out->gd_free (out);
  return rv;
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 
) [static]

Definition at line 256 of file gd_gif_out.c.

{
        int B;
        int RWidth, RHeight;
        int LeftOfs, TopOfs;
        int Resolution;
        int ColorMapSize;
        int InitCodeSize;
        int i;
              GifCtx ctx;

              memset(&ctx, 0, sizeof(ctx));
        ctx.Interlace = GInterlace;
              ctx.in_count = 1;

        ColorMapSize = 1 << BitsPerPixel;

        RWidth = ctx.Width = GWidth;
        RHeight = ctx.Height = GHeight;
        LeftOfs = TopOfs = 0;

        Resolution = BitsPerPixel;

        /*
         * Calculate number of bits we are expecting
         */
        ctx.CountDown = (long)ctx.Width * (long)ctx.Height;

        /*
         * Indicate which pass we are on (if interlace)
         */
        ctx.Pass = 0;

        /*
         * The initial code size
         */
        if( BitsPerPixel <= 1 )
                InitCodeSize = 2;
        else
                InitCodeSize = BitsPerPixel;

        /*
         * Set up the current x and y position
         */
        ctx.curx = ctx.cury = 0;

        /*
         * Write the Magic header
         */
        gdPutBuf(Transparent < 0 ? "GIF87a" : "GIF89a", 6, fp );

        /*
         * Write out the screen width and height
         */
        gifPutWord( RWidth, fp );
        gifPutWord( RHeight, fp );

        /*
         * Indicate that there is a global colour map
         */
        B = 0x80;       /* Yes, there is a color map */

        /*
         * OR in the resolution
         */
        B |= (Resolution - 1) << 5;

        /*
         * OR in the Bits per Pixel
         */
        B |= (BitsPerPixel - 1);

        /*
         * Write it out
         */
        gdPutC( B, fp );

        /*
         * Write out the Background colour
         */
        gdPutC( Background, fp );

        /*
         * Byte of 0's (future expansion)
         */
        gdPutC( 0, fp );

        /*
         * Write out the Global Colour Map
         */
        for( i=0; i<ColorMapSize; ++i ) {
                gdPutC( Red[i], fp );
                gdPutC( Green[i], fp );
                gdPutC( Blue[i], fp );
        }

       /*
        * Write out extension for transparent colour index, if necessary.
        */
       if ( Transparent >= 0 ) {
           gdPutC( '!', fp );
           gdPutC( 0xf9, fp );
           gdPutC( 4, fp );
           gdPutC( 1, fp );
           gdPutC( 0, fp );
           gdPutC( 0, fp );
           gdPutC( (unsigned char) Transparent, fp );
           gdPutC( 0, fp );
       }

        /*
         * Write an Image separator
         */
        gdPutC( ',', fp );

        /*
         * Write the Image header
         */

        gifPutWord( LeftOfs, fp );
        gifPutWord( TopOfs, fp );
        gifPutWord( ctx.Width, fp );
        gifPutWord( ctx.Height, fp );

        /*
         * Write out whether or not the image is interlaced
         */
        if( ctx.Interlace )
                gdPutC( 0x40, fp );
        else
                gdPutC( 0x00, fp );

        /*
         * Write out the initial code size
         */
        gdPutC( InitCodeSize, fp );

        /*
         * Go and actually compress the data
         */
        compress( InitCodeSize+1, fp, im, &ctx );

        /*
         * Write out a Zero-length packet (to end the series)
         */
        gdPutC( 0, fp );

        /*
         * Write the GIF file terminator
         */
        gdPutC( ';', fp );

Here is the call graph for this function:

Here is the caller graph for this function:

static int GIFNextPixel ( gdImagePtr  im,
GifCtx ctx 
) [static]

Definition at line 237 of file gd_gif_out.c.

{
        int r;

        if( ctx->CountDown == 0 )
                return EOF;

        --(ctx->CountDown);

        r = gdImageGetPixel(im, ctx->curx, ctx->cury);

        BumpPixel(ctx);

        return r;

Here is the call graph for this function:

Here is the caller graph for this function:

static int gifPutWord ( int  w,
gdIOCtx out 
) [static]

Definition at line 751 of file gd_gif_out.c.

{
       /* Byte order is little-endian */
       gdPutC(w & 0xFF, out);
       gdPutC((w >> 8) & 0xFF, out);
       return 0;

Here is the call graph for this function:

Here is the caller graph for this function:

static void output ( code_int  code,
GifCtx ctx 
) [static]

Definition at line 609 of file gd_gif_out.c.

{
    ctx->cur_accum &= masks[ ctx->cur_bits ];

    if( ctx->cur_bits > 0 )
        ctx->cur_accum |= ((long)code << ctx->cur_bits);
    else
        ctx->cur_accum = code;

    ctx->cur_bits += ctx->n_bits;

    while( ctx->cur_bits >= 8 ) {
        char_out( (unsigned int)(ctx->cur_accum & 0xff), ctx );
        ctx->cur_accum >>= 8;
        ctx->cur_bits -= 8;
    }

    /*
     * If the next entry is going to be too big for the code size,
     * then increase it, if possible.
     */
   if ( ctx->free_ent > ctx->maxcode || ctx->clear_flg ) {

            if( ctx->clear_flg ) {

                ctx->maxcode = MAXCODE (ctx->n_bits = ctx->g_init_bits);
                ctx->clear_flg = 0;

            } else {

                ++(ctx->n_bits);
                if ( ctx->n_bits == maxbits )
                    ctx->maxcode = maxmaxcode;
                else
                    ctx->maxcode = MAXCODE(ctx->n_bits);
            }
        }

    if( code == ctx->EOFCode ) {
        /*
         * At EOF, write the rest of the buffer.
         */
        while( ctx->cur_bits > 0 ) {
                char_out( (unsigned int)(ctx->cur_accum & 0xff), ctx);
                ctx->cur_accum >>= 8;
                ctx->cur_bits -= 8;
        }

        flush_char(ctx);

    }

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

unsigned long masks[] [static]
Initial value:
 { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
                                  0x001F, 0x003F, 0x007F, 0x00FF,
                                  0x01FF, 0x03FF, 0x07FF, 0x0FFF,
                                  0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF }

Definition at line 603 of file gd_gif_out.c.