28 #define TABLESIZE 5003
50 unsigned char Block[255];
53 static void WriteWordLE(FILE *File,
unsigned short Value);
55 unsigned char *Data,
int FrameLeft,
int FrameTop,
56 int FrameWidth,
int FrameHeight,
int ImageWidth);
57 static void CropFrame(
int *FrameLeft,
int *FrameTop,
58 int *FrameWidth,
int *FrameHeight,
unsigned char *Data,
59 int ImageWidth,
int ImageHeight,
int TransparentColor);
121 int ImageWidth,
int ImageHeight,
int NumFrames,
122 const unsigned char *Palette,
int NumColors,
int TransparentColor,
123 const int *Delays,
const char *OutputFile)
127 const int NumPixels = ImageWidth*ImageHeight;
128 int i, Frame, TableSizePow;
129 int FrameLeft, FrameTop, FrameWidth, FrameHeight, Success = 0;
132 if(!Image || !Palette || !OutputFile || ImageWidth <= 0
133 || ImageHeight <= 0 || NumFrames <= 0 || NumColors <= 2
134 || TransparentColor < 0 || TransparentColor >= NumColors)
137 for(Frame = 0; Frame < NumFrames; Frame++)
142 for(i = 0; i < NumPixels; i++)
143 if(Image[Frame][i] >= NumColors)
145 fprintf(stderr,
"Pixel values exceed palette.\n");
153 if(!(File = fopen(OutputFile,
"wb")))
155 fprintf(stderr,
"Unable to open \"%s\" for writing.\n", OutputFile);
159 for(TableSizePow = 1; TableSizePow < NumColors && TableSizePow < 8;)
163 fwrite(
"GIF89a", 1, 6, File);
166 putc(0xF0 | (TableSizePow - 1), File);
168 fwrite(Palette, 1, 3*NumColors, File);
171 for(i = 3*((1 << TableSizePow) - NumColors); i > 0; i--)
176 fwrite(
"\x21\xFF\x0BNETSCAPE2.0\x03\x01\xFF\xFF", 1, 19, File);
178 for(Frame = 0; Frame < NumFrames; Frame++)
180 CropFrame(&FrameLeft, &FrameTop, &FrameWidth, &FrameHeight,
181 Image[Frame], ImageWidth, ImageHeight, TransparentColor);
187 putc(TransparentColor, File);
197 FrameWidth, FrameHeight, ImageWidth);
204 fprintf(stderr,
"Error while writing to \"%s\".\n", OutputFile);
221 putc(Value & 0xFF, File);
222 putc((Value & 0xFF00) >> 8, File);
238 for(; Stream->
NumBits > MaxRemaining;
242 (
unsigned char)(Stream->
BitAccum & 0xFF);
254 Code : (Code << Stream->
NumBits);
262 unsigned char *Data,
int FrameLeft,
int FrameTop,
263 int FrameWidth,
int FrameHeight,
int ImageWidth)
267 unsigned short ClearCode, FreeCode, Prefix, NextRaise;
268 unsigned int AppendChar, InitBitsPerCode = 9;
274 ClearCode = (
unsigned short)(1 << (InitBitsPerCode - 1));
275 NextRaise = (
unsigned short)(1 << InitBitsPerCode);
276 FreeCode = ClearCode + 2;
281 putc(InitBitsPerCode - 1, File);
284 Prefix = Data[FrameLeft + ImageWidth*FrameTop];
291 for(x = 1, y = 0; y < FrameHeight; (++x >= FrameWidth) ? (x = 0, y++) : 0)
294 AppendChar = Data[(x + FrameLeft) + ImageWidth*(y + FrameTop)];
297 Hash = (long)Prefix + (AppendChar <<
MAXBITS);
299 Step = (i == 0) ? 1 : (TABLESIZE - i);
301 while(Table[i].Hash != Hash && Table[i].Hash !=
UNUSED)
305 if(Table[i].Hash !=
UNUSED)
308 Prefix = Table[i].
Code;
318 if(FreeCode == NextRaise)
325 Table[i].
Hash = Hash;
326 Table[i].
Code = FreeCode++;
332 NextRaise = (
unsigned short)(1 << InitBitsPerCode);
333 FreeCode = ClearCode + 2;
356 int *FrameWidth,
int *FrameHeight,
unsigned char *Data,
357 int ImageWidth,
int ImageHeight,
int TransparentColor)
359 int x, y, Left = ImageWidth, Right = 0, Top = ImageHeight, Bottom = 0;
361 for(y = 0; y < ImageHeight; y++, Data += ImageWidth)
362 for(x = 0; x < ImageWidth; x++)
363 if(Data[x] != TransparentColor)
375 if(Left == ImageWidth)
377 *FrameLeft = *FrameTop = 0;
378 *FrameWidth = *FrameHeight = 1;
384 *FrameWidth = Right - Left + 1;
385 *FrameHeight = Bottom - Top + 1;
402 int ImageWidth,
int ImageHeight,
int NumFrames,
int TransparentColor)
404 const int NumPixels = ImageWidth*ImageHeight;
405 int i, Frame, PrevFrame;
408 if(!Image || ImageWidth <= 0 || ImageHeight <= 0 || NumFrames <= 0)
411 for(Frame = 0; Frame < NumFrames; Frame++)
415 for(Frame = NumFrames - 1; Frame > 0; Frame--)
416 for(i = 0; i < NumPixels; i++)
418 if(Image[Frame][i] == TransparentColor)
422 for(PrevFrame = Frame - 1; PrevFrame >= 0; PrevFrame--)
423 if(Image[PrevFrame][i] != TransparentColor)
427 if(PrevFrame >= 0 && Image[PrevFrame][i] == Image[Frame][i])
428 Image[Frame][i] = TransparentColor;