/* Function: gdImageGifAnimBeginCtx Like <gdImageGifAnimBegin> except that it outputs to <gdIOCtx>. See <gdImageGifAnimBegin>. Parameters: im - The reference image out - Pointer to the output <gdIOCtx>. GlobalCM - Global colormap flag: 1 -> yes, 0 -> no, -1 -> do default Loops - Loop count; 0 -> infinite, -1 means no loop Returns: Nothing. */ BGD_DECLARE(void) gdImageGifAnimBeginCtx(gdImagePtr im, gdIOCtxPtr out, int GlobalCM, int Loops) { int B; int RWidth, RHeight; int Resolution; int ColorMapSize; int BitsPerPixel; int Background = 0; int i; /* Default is to use global color map */ if (GlobalCM < 0) { GlobalCM = 1; } BitsPerPixel = colorstobpp(im->colorsTotal); ColorMapSize = 1 << BitsPerPixel; RWidth = im->sx; RHeight = im->sy; Resolution = BitsPerPixel; /* Write the Magic header */ gdPutBuf("GIF89a", 6, out); /* Write out the screen width and height */ gifPutWord(RWidth, out); gifPutWord(RHeight, out); /* Indicate that there is a global colour map */ B = GlobalCM ? 0x80 : 0; /* OR in the resolution */ B |= (Resolution - 1) << 4; /* OR in the Bits per Pixel */ B |= (BitsPerPixel - 1); /* Write it out */ gdPutC(B, out); /* Write out the Background colour */ gdPutC(Background, out); /* Byte of 0's (future expansion) */ gdPutC(0, out); /* Write out the Global Colour Map */ if(GlobalCM) { for(i = 0; i < ColorMapSize; ++i) { gdPutC(im->red[i], out); gdPutC(im->green[i], out); gdPutC(im->blue[i], out); } } if(Loops >= 0) { gdPutBuf("!\377\13NETSCAPE2.0\3\1", 16, out); gifPutWord(Loops, out); gdPutC(0, out); } }
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) { 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 ); }
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) { int B; int ColorMapSize; int InitCodeSize; int i; GifCtx ctx; memset(&ctx, 0, sizeof(ctx)); ctx.Interlace = GInterlace; ctx.in_count = 1; ColorMapSize = 1 << BitsPerPixel; if(LeftOfs < 0) { LeftOfs = 0; } if(TopOfs < 0) { TopOfs = 0; } if(Delay < 0) { Delay = 100; } if(Disposal < 0) { Disposal = 1; } ctx.Width = IWidth; ctx.Height = IHeight; /* 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 out extension for image animation and looping */ gdPutC('!', fp); gdPutC(0xf9, fp); gdPutC(4, fp); gdPutC((Transparent >= 0 ? 1 : 0) | (Disposal << 2), fp); gdPutC((unsigned char)(Delay & 255), fp); gdPutC((unsigned char)((Delay >> 8) & 255), fp); gdPutC((unsigned char) Transparent, fp); gdPutC(0, fp); /* Write an Image separator */ gdPutC(',', fp); /* Write out the Image header */ gifPutWord(LeftOfs, fp); gifPutWord(TopOfs, fp); gifPutWord(ctx.Width, fp); gifPutWord(ctx.Height, fp); /* Indicate that there is a local colour map */ B = (Red && Green && Blue) ? 0x80 : 0; /* OR in the interlacing */ B |= ctx.Interlace ? 0x40 : 0; /* OR in the Bits per Pixel */ B |= (Red && Green && Blue) ? (BitsPerPixel - 1) : 0; /* Write it out */ gdPutC(B, fp); /* Write out the Local Colour Map */ if(Red && Green && Blue) { for(i = 0; i < ColorMapSize; ++i) { gdPutC(Red[i], fp); gdPutC(Green[i], fp); gdPutC(Blue[i], 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); }