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 */
gdImageGifPtr(gdImagePtr im,int * size)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 */
gdImageGif(gdImagePtr im,FILE * outFile)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 */
gdImageGifCtx(gdImagePtr im,gdIOCtxPtr out)230 BGD_DECLARE(void) gdImageGifCtx(gdImagePtr im, gdIOCtxPtr out)
231 {
232 _gdImageGifCtx(im, out);
233 }
234
235 /* returns 0 on success, 1 on failure */
_gdImageGifCtx(gdImagePtr im,gdIOCtxPtr out)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
gdImageGifAnimBeginPtr(gdImagePtr im,int * size,int GlobalCM,int Loops)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
gdImageGifAnimBegin(gdImagePtr im,FILE * outFile,int GlobalCM,int Loops)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 */
gdImageGifAnimBeginCtx(gdImagePtr im,gdIOCtxPtr out,int GlobalCM,int Loops)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 */
gdImageGifAnimAddPtr(gdImagePtr im,int * size,int LocalCM,int LeftOfs,int TopOfs,int Delay,int Disposal,gdImagePtr previm)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
gdImageGifAnimAdd(gdImagePtr im,FILE * outFile,int LocalCM,int LeftOfs,int TopOfs,int Delay,int Disposal,gdImagePtr previm)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
comparewithmap(gdImagePtr im1,gdImagePtr im2,int c1,int c2,int * colorMap)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 */
gdImageGifAnimAddCtx(gdImagePtr im,gdIOCtxPtr out,int LocalCM,int LeftOfs,int TopOfs,int Delay,int Disposal,gdImagePtr previm)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 */
_gdImageGifAnimAddCtx(gdImagePtr im,gdIOCtxPtr out,int LocalCM,int LeftOfs,int TopOfs,int Delay,int Disposal,gdImagePtr previm)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 (!comparewithmap
749 (prev_tim, tim,
750 prev_tim->pixels[y][x],
751 tim->pixels[y][x],
752 colorMap)) {
753 max_y = y;
754 if(x < min_x) {
755 min_x = x;
756 }
757 if(x > max_x) {
758 max_x = x;
759 }
760 goto break_bot;
761 }
762 }
763 }
764
765 break_bot:
766 /* left side */
767 for (x = 0; x < min_x; ++x) {
768 for (y = min_y; y <= max_y; ++y) {
769 if (!comparewithmap
770 (prev_tim, tim,
771 prev_tim->pixels[y][x],
772 tim->pixels[y][x],
773 colorMap)) {
774 min_x = x;
775 goto break_left;
776 }
777 }
778 }
779
780 break_left:
781 /* right side */
782 for (x = tim->sx - 1; x > max_x; --x) {
783 for (y = min_y; y <= max_y; ++y) {
784 if (!comparewithmap
785 (prev_tim, tim,
786 prev_tim->pixels[y][x],
787 tim->pixels[y][x],
788 colorMap)) {
789 max_x = x;
790 goto break_right;
791 }
792 }
793 }
794
795 break_right:
796 ;
797 }
798
799 LeftOfs = min_x;
800 TopOfs = min_y;
801 Disposal = 1;
802
803 /* Make a copy of the image with the new offsets.
804 But only if necessary. */
805 if (min_x != 0 || max_x != tim->sx - 1
806 || min_y != 0 || max_y != tim->sy - 1
807 || transparent >= 0) {
808
809 gdImagePtr pim2 = gdImageCreate(max_x-min_x + 1, max_y-min_y + 1);
810
811 if (!pim2) {
812 if (prev_pim) {
813 gdImageDestroy(prev_pim);
814 }
815 goto fail_end;
816 }
817
818 gdImagePaletteCopy(pim2, LocalCM ? tim : prev_tim);
819 gdImageCopy(pim2, tim, 0, 0, min_x, min_y,
820 max_x - min_x + 1, max_y - min_y + 1);
821
822 if (pim) {
823 gdImageDestroy(pim);
824 }
825
826 tim = pim = pim2;
827 }
828
829 /* now let's compare pixels for transparent
830 optimization. But only if transparent is set. */
831 if (transparent >= 0) {
832 for(y = 0; y < tim->sy; ++y) {
833 for (x = 0; x < tim->sx; ++x) {
834 if(comparewithmap
835 (prev_tim, tim,
836 prev_tim->pixels[min_y + y][min_x + x],
837 tim->pixels[y][x], 0)) {
838 gdImageSetPixel(tim, x, y, transparent);
839 break;
840 }
841 }
842 }
843 }
844
845 if(prev_pim) {
846 gdImageDestroy(prev_pim);
847 }
848 }
849
850 BitsPerPixel = colorstobpp(tim->colorsTotal);
851
852 /* All set, let's do it. */
853 GIFAnimEncode(
854 out, tim->sx, tim->sy, LeftOfs, TopOfs, interlace, transparent,
855 Delay, Disposal, BitsPerPixel,
856 LocalCM ? tim->red : 0, tim->green, tim->blue, tim);
857 return 0;
858
859 fail_end:
860 if(pim) {
861 /* Destroy palette based temporary image. */
862 gdImageDestroy(pim);
863 }
864 return 1;
865 }
866
867
868
869 /*
870 Function: gdImageGifAnimEnd
871
872 Terminates the GIF file properly.
873
874 (Previous versions of this function's documentation suggested just
875 manually writing a semicolon (';') instead since that is all this
876 function does. While that has no longer changed, we now suggest
877 that you do not do this and instead always call
878 <gdImageGifAnimEnd> (or equivalent) since later versions could
879 possibly do more or different things.)
880
881 Variants:
882
883 <gdImageGifAnimEndCtx> outputs its data via a <gdIOCtx> struct.
884
885 <gdImageGifAnimEndPtr> outputs its data to a memory buffer which
886 it returns.
887
888 Parameters:
889
890 outfile - the destination FILE*.
891
892 Returns:
893
894 Nothing.
895
896 */
897
gdImageGifAnimEnd(FILE * outFile)898 BGD_DECLARE(void) gdImageGifAnimEnd(FILE *outFile)
899 {
900 #if 1
901 putc(';', outFile);
902 #else
903 gdIOCtx *out = gdNewFileCtx(outFile);
904 if (out == NULL) return;
905 gdImageGifAnimEndCtx(out);
906 out->gd_free(out);
907 #endif
908 }
909
910 /*
911 Function: gdImageGifAnimEndPtr
912
913 Like <gdImageGifAnimEnd> (which contains more information) except
914 that it stores the data to write into memory and returns a pointer
915 to it.
916
917 This memory must be freed by the caller when it is no longer
918 needed. **The caller must invoke <gdFree>(), not free(),** unless
919 the caller is absolutely certain that the same implementations of
920 malloc, free, etc. are used both at library build time and at
921 application build time (but don't; it could always change).
922
923 The 'size' parameter receives the total size of the block of
924 memory.
925
926 Parameters:
927
928 size - Output: the size of the resulting buffer.
929
930 Returns:
931
932 Pointer to the resulting data or NULL if an error occurred.
933
934 */
935
gdImageGifAnimEndPtr(int * size)936 BGD_DECLARE(void *) gdImageGifAnimEndPtr(int *size)
937 {
938 char *rv = (char *) gdMalloc(1);
939 if(!rv) {
940 return 0;
941 }
942 *rv = ';';
943 *size = 1;
944 return (void *)rv;
945 }
946
947 /*
948 Function: gdImageGifAnimEndCtx
949
950 Like <gdImageGifAnimEnd>, but writes its data via a <gdIOCtx>.
951
952 Parameters:
953
954 out - the destination <gdIOCtx>.
955
956 Returns:
957
958 Nothing.
959
960 */
961
gdImageGifAnimEndCtx(gdIOCtx * out)962 BGD_DECLARE(void) gdImageGifAnimEndCtx(gdIOCtx *out)
963 {
964 /*
965 * Write the GIF file terminator
966 */
967 gdPutC(';', out);
968 }
969
colorstobpp(int colors)970 static int colorstobpp(int colors)
971 {
972 int bpp = 0;
973
974 if(colors <= 2)
975 bpp = 1;
976 else if(colors <= 4)
977 bpp = 2;
978 else if(colors <= 8)
979 bpp = 3;
980 else if(colors <= 16)
981 bpp = 4;
982 else if(colors <= 32)
983 bpp = 5;
984 else if(colors <= 64)
985 bpp = 6;
986 else if(colors <= 128)
987 bpp = 7;
988 else if(colors <= 256)
989 bpp = 8;
990
991 return bpp;
992 }
993
994 /*****************************************************************************
995 *
996 * GIFENCODE.C - GIF Image compression interface
997 *
998 * GIFEncode( FName, GHeight, GWidth, GInterlace, Background, Transparent,
999 * BitsPerPixel, Red, Green, Blue, gdImagePtr )
1000 *
1001 *****************************************************************************/
1002
1003 #define TRUE 1
1004 #define FALSE 0
1005
1006 /* Bump the 'curx' and 'cury' to point to the next pixel */
BumpPixel(GifCtx * ctx)1007 static void BumpPixel(GifCtx *ctx)
1008 {
1009 /* Bump the current X position */
1010 ++(ctx->curx);
1011
1012 /* If we are at the end of a scan line, set curx back to the beginning
1013 * If we are interlaced, bump the cury to the appropriate spot,
1014 * otherwise, just increment it. */
1015 if(ctx->curx == ctx->Width) {
1016 ctx->curx = 0;
1017
1018 if(!ctx->Interlace) {
1019 ++(ctx->cury);
1020 } else {
1021 switch(ctx->Pass) {
1022
1023 case 0:
1024 ctx->cury += 8;
1025 if(ctx->cury >= ctx->Height) {
1026 ++(ctx->Pass);
1027 ctx->cury = 4;
1028 }
1029 break;
1030
1031 case 1:
1032 ctx->cury += 8;
1033 if(ctx->cury >= ctx->Height) {
1034 ++(ctx->Pass);
1035 ctx->cury = 2;
1036 }
1037 break;
1038
1039 case 2:
1040 ctx->cury += 4;
1041 if(ctx->cury >= ctx->Height) {
1042 ++(ctx->Pass);
1043 ctx->cury = 1;
1044 }
1045 break;
1046
1047 case 3:
1048 ctx->cury += 2;
1049 break;
1050 }
1051 }
1052 }
1053 }
1054
1055 /* Return the next pixel from the image */
GIFNextPixel(gdImagePtr im,GifCtx * ctx)1056 static int GIFNextPixel(gdImagePtr im, GifCtx *ctx)
1057 {
1058 int r;
1059
1060 if(ctx->CountDown == 0) {
1061 return EOF;
1062 }
1063
1064 --(ctx->CountDown);
1065
1066 r = gdImageGetPixel(im, ctx->curx, ctx->cury);
1067
1068 BumpPixel(ctx);
1069
1070 return r;
1071 }
1072
1073 /* public */
1074
GIFEncode(gdIOCtxPtr fp,int GWidth,int GHeight,int GInterlace,int Background,int Transparent,int BitsPerPixel,int * Red,int * Green,int * Blue,gdImagePtr im)1075 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)
1076 {
1077 int B;
1078 int RWidth, RHeight;
1079 int LeftOfs, TopOfs;
1080 int Resolution;
1081 int ColorMapSize;
1082 int InitCodeSize;
1083 int i;
1084 GifCtx ctx;
1085
1086 memset(&ctx, 0, sizeof(ctx));
1087
1088 ctx.Interlace = GInterlace;
1089 ctx.in_count = 1;
1090
1091 ColorMapSize = 1 << BitsPerPixel;
1092
1093 RWidth = ctx.Width = GWidth;
1094 RHeight = ctx.Height = GHeight;
1095 LeftOfs = TopOfs = 0;
1096
1097 Resolution = BitsPerPixel;
1098
1099 /* Calculate number of bits we are expecting */
1100 ctx.CountDown = (long)ctx.Width * (long)ctx.Height;
1101
1102 /* Indicate which pass we are on (if interlace) */
1103 ctx.Pass = 0;
1104
1105 /* The initial code size */
1106 if(BitsPerPixel <= 1) {
1107 InitCodeSize = 2;
1108 } else {
1109 InitCodeSize = BitsPerPixel;
1110 }
1111
1112 /* Set up the current x and y position */
1113 ctx.curx = ctx.cury = 0;
1114
1115 /* Write the Magic header */
1116 gdPutBuf(Transparent < 0 ? "GIF87a" : "GIF89a", 6, fp);
1117
1118 /* Write out the screen width and height */
1119 gifPutWord(RWidth, fp);
1120 gifPutWord(RHeight, fp);
1121
1122 /* Indicate that there is a global colour map */
1123 /* Yes, there is a color map */
1124 B = 0x80;
1125
1126 /* OR in the resolution */
1127 B |= (Resolution - 1) << 4;
1128
1129 /* OR in the Bits per Pixel */
1130 B |= (BitsPerPixel - 1);
1131
1132 /* Write it out */
1133 gdPutC(B, fp);
1134
1135 /* Write out the Background colour */
1136 gdPutC(Background, fp);
1137
1138 /* Byte of 0's (future expansion) */
1139 gdPutC(0, fp);
1140
1141 /* Write out the Global Colour Map */
1142 for(i = 0; i < ColorMapSize; ++i) {
1143 gdPutC(Red[i], fp);
1144 gdPutC(Green[i], fp);
1145 gdPutC(Blue[i], fp);
1146 }
1147
1148 /* Write out extension for transparent colour index, if necessary. */
1149 if(Transparent >= 0) {
1150 gdPutC('!', fp);
1151 gdPutC(0xf9, fp);
1152 gdPutC(4, fp);
1153 gdPutC(1, fp);
1154 gdPutC(0, fp);
1155 gdPutC(0, fp);
1156 gdPutC((unsigned char) Transparent, fp);
1157 gdPutC(0, fp);
1158 }
1159
1160 /* Write an Image separator */
1161 gdPutC(',', fp);
1162
1163 /* Write the Image header */
1164 gifPutWord(LeftOfs, fp);
1165 gifPutWord(TopOfs, fp);
1166 gifPutWord(ctx.Width, fp);
1167 gifPutWord(ctx.Height, fp);
1168
1169 /* Write out whether or not the image is interlaced */
1170 if(ctx.Interlace) {
1171 gdPutC(0x40, fp);
1172 } else {
1173 gdPutC(0x00, fp);
1174 }
1175
1176 /* Write out the initial code size */
1177 gdPutC(InitCodeSize, fp);
1178
1179 /* Go and actually compress the data */
1180 compress(InitCodeSize + 1, fp, im, &ctx);
1181
1182 /* Write out a Zero-length packet (to end the series) */
1183 gdPutC(0, fp);
1184
1185 /* Write the GIF file terminator */
1186 gdPutC(';', fp);
1187 }
1188
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)1189 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)
1190 {
1191 int B;
1192 int ColorMapSize;
1193 int InitCodeSize;
1194 int i;
1195 GifCtx ctx;
1196
1197 memset(&ctx, 0, sizeof(ctx));
1198
1199 ctx.Interlace = GInterlace;
1200 ctx.in_count = 1;
1201
1202 ColorMapSize = 1 << BitsPerPixel;
1203
1204 if(LeftOfs < 0) {
1205 LeftOfs = 0;
1206 }
1207 if(TopOfs < 0) {
1208 TopOfs = 0;
1209 }
1210 if(Delay < 0) {
1211 Delay = 100;
1212 }
1213 if(Disposal < 0) {
1214 Disposal = 1;
1215 }
1216
1217 ctx.Width = IWidth;
1218 ctx.Height = IHeight;
1219
1220 /* Calculate number of bits we are expecting */
1221 ctx.CountDown = (long)ctx.Width * (long)ctx.Height;
1222
1223 /* Indicate which pass we are on (if interlace) */
1224 ctx.Pass = 0;
1225
1226 /* The initial code size */
1227 if(BitsPerPixel <= 1) {
1228 InitCodeSize = 2;
1229 } else {
1230 InitCodeSize = BitsPerPixel;
1231 }
1232
1233 /* Set up the current x and y position */
1234 ctx.curx = ctx.cury = 0;
1235
1236 /* Write out extension for image animation and looping */
1237 gdPutC('!', fp);
1238 gdPutC(0xf9, fp);
1239 gdPutC(4, fp);
1240 gdPutC((Transparent >= 0 ? 1 : 0) | (Disposal << 2), fp);
1241 gdPutC((unsigned char)(Delay & 255), fp);
1242 gdPutC((unsigned char)((Delay >> 8) & 255), fp);
1243 gdPutC((unsigned char) Transparent, fp);
1244 gdPutC(0, fp);
1245
1246 /* Write an Image separator */
1247 gdPutC(',', fp);
1248
1249 /* Write out the Image header */
1250 gifPutWord(LeftOfs, fp);
1251 gifPutWord(TopOfs, fp);
1252 gifPutWord(ctx.Width, fp);
1253 gifPutWord(ctx.Height, fp);
1254
1255 /* Indicate that there is a local colour map */
1256 B = (Red && Green && Blue) ? 0x80 : 0;
1257
1258 /* OR in the interlacing */
1259 B |= ctx.Interlace ? 0x40 : 0;
1260
1261 /* OR in the Bits per Pixel */
1262 B |= (Red && Green && Blue) ? (BitsPerPixel - 1) : 0;
1263
1264 /* Write it out */
1265 gdPutC(B, fp);
1266
1267 /* Write out the Local Colour Map */
1268 if(Red && Green && Blue) {
1269 for(i = 0; i < ColorMapSize; ++i) {
1270 gdPutC(Red[i], fp);
1271 gdPutC(Green[i], fp);
1272 gdPutC(Blue[i], fp);
1273 }
1274 }
1275
1276 /* Write out the initial code size */
1277 gdPutC(InitCodeSize, fp);
1278
1279 /* Go and actually compress the data */
1280 compress(InitCodeSize + 1, fp, im, &ctx);
1281
1282 /* Write out a Zero-length packet (to end the series) */
1283 gdPutC(0, fp);
1284 }
1285
1286 /***************************************************************************
1287 *
1288 * GIFCOMPR.C - GIF Image compression routines
1289 *
1290 * Lempel-Ziv compression based on 'compress'. GIF modifications by
1291 * David Rowley (mgardi@watdcsu.waterloo.edu)
1292 *
1293 ***************************************************************************/
1294
1295 /* General DEFINEs */
1296
1297 #define GIFBITS 12
1298
1299 #ifdef NO_UCHAR
1300 typedef char char_type;
1301 #else /* NO_UCHAR */
1302 typedef unsigned char char_type;
1303 #endif /* NO_UCHAR */
1304
1305 /*
1306 *
1307 * GIF Image compression - modified 'compress'
1308 *
1309 * Based on: compress.c - File compression ala IEEE Computer, June 1984.
1310 *
1311 * By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)
1312 * Jim McKie (decvax!mcvax!jim)
1313 * Steve Davies (decvax!vax135!petsd!peora!srd)
1314 * Ken Turkowski (decvax!decwrl!turtlevax!ken)
1315 * James A. Woods (decvax!ihnp4!ames!jaw)
1316 * Joe Orost (decvax!vax135!petsd!joe)
1317 *
1318 */
1319 #include <ctype.h>
1320
1321 #define ARGVAL() (*++(*argv) || (--argc && *++argv))
1322
1323 #ifdef COMPATIBLE /* But wrong! */
1324 # define MAXCODE(n_bits) ((code_int) 1 << (n_bits) - 1)
1325 #else /* COMPATIBLE */
1326 # define MAXCODE(n_bits) (((code_int) 1 << (n_bits)) - 1)
1327 #endif /* COMPATIBLE */
1328
1329 #define HashTabOf(i) ctx->htab[i]
1330 #define CodeTabOf(i) ctx->codetab[i]
1331
1332
1333 /*
1334 * To save much memory, we overlay the table used by compress() with those
1335 * used by decompress(). The tab_prefix table is the same size and type
1336 * as the codetab. The tab_suffix table needs 2**GIFBITS characters. We
1337 * get this from the beginning of htab. The output stack uses the rest
1338 * of htab, and contains characters. There is plenty of room for any
1339 * possible stack (stack used to be 8000 characters).
1340 */
1341
1342 #define tab_prefixof(i) CodeTabOf(i)
1343 #define tab_suffixof(i) ((char_type*)(htab))[i]
1344 #define de_stack ((char_type*)&tab_suffixof((code_int)1 << GIFBITS))
1345
1346 /*
1347 * compress stdin to stdout
1348 *
1349 * Algorithm: use open addressing double hashing (no chaining) on the
1350 * prefix code / next character combination. We do a variant of Knuth's
1351 * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
1352 * secondary probe. Here, the modular division first probe is gives way
1353 * to a faster exclusive-or manipulation. Also do block compression with
1354 * an adaptive reset, whereby the code table is cleared when the compression
1355 * ratio decreases, but after the table fills. The variable-length output
1356 * codes are re-sized at this point, and a special CLEAR code is generated
1357 * for the decompressor. Late addition: construct the table according to
1358 * file size for noticeable speed improvement on small files. Please direct
1359 * questions about this implementation to ames!jaw.
1360 */
1361
1362 static void output(code_int code, GifCtx *ctx);
1363
compress(int init_bits,gdIOCtxPtr outfile,gdImagePtr im,GifCtx * ctx)1364 static void compress(int init_bits, gdIOCtxPtr outfile, gdImagePtr im, GifCtx *ctx)
1365 {
1366 register long fcode;
1367 register code_int i;
1368 register int c;
1369 register code_int ent;
1370 register code_int disp;
1371 register code_int hsize_reg;
1372 register int hshift;
1373
1374 /* Set up the globals:
1375 * g_init_bits - initial number of bits
1376 * g_outfile - pointer to output file */
1377 ctx->g_init_bits = init_bits;
1378 ctx->g_outfile = outfile;
1379
1380 /* Set up the necessary values */
1381 ctx->offset = 0;
1382 ctx->out_count = 0;
1383 ctx->clear_flg = 0;
1384 ctx->in_count = 1;
1385 ctx->maxcode = MAXCODE(ctx->n_bits = ctx->g_init_bits);
1386
1387 ctx->ClearCode = (1 << (init_bits - 1));
1388 ctx->EOFCode = ctx->ClearCode + 1;
1389 ctx->free_ent = ctx->ClearCode + 2;
1390
1391 char_init(ctx);
1392
1393 ent = GIFNextPixel(im, ctx);
1394
1395 hshift = 0;
1396 for(fcode = (long)hsize; fcode < 65536L; fcode *= 2L) {
1397 ++hshift;
1398 }
1399 hshift = 8 - hshift; /* set hash code range bound */
1400
1401 hsize_reg = hsize;
1402 cl_hash((count_int) hsize_reg, ctx); /* clear hash table */
1403
1404 output((code_int)ctx->ClearCode, ctx);
1405
1406 #ifdef SIGNED_COMPARE_SLOW
1407 while((c = GIFNextPixel(im, ctx)) != (unsigned) EOF) {
1408 #else /* SIGNED_COMPARE_SLOW */
1409 while((c = GIFNextPixel(im, ctx)) != EOF) {
1410 #endif /* SIGNED_COMPARE_SLOW */
1411
1412 ++(ctx->in_count);
1413
1414 fcode = (long) (((long) c << maxbits) + ent);
1415 i = (((code_int)c << hshift) ^ ent); /* xor hashing */
1416
1417 if(HashTabOf(i) == fcode) {
1418 ent = CodeTabOf (i);
1419 continue;
1420 } else if ((long)HashTabOf (i) < 0) {/* empty slot */
1421 goto nomatch;
1422 }
1423
1424 disp = hsize_reg - i; /* secondary hash (after G. Knott) */
1425
1426 if(i == 0) {
1427 disp = 1;
1428 }
1429
1430 probe:
1431 if((i -= disp) < 0) {
1432 i += hsize_reg;
1433 }
1434
1435 if(HashTabOf(i) == fcode) {
1436 ent = CodeTabOf (i);
1437 continue;
1438 }
1439
1440 if((long)HashTabOf(i) > 0) {
1441 goto probe;
1442 }
1443
1444 nomatch:
1445 output((code_int) ent, ctx);
1446 ++(ctx->out_count);
1447 ent = c;
1448 #ifdef SIGNED_COMPARE_SLOW
1449 if((unsigned) ctx->free_ent < (unsigned) maxmaxcode) {
1450 #else /*SIGNED_COMPARE_SLOW*/
1451 if (ctx->free_ent < maxmaxcode) { /* } */
1452 #endif /*SIGNED_COMPARE_SLOW*/
1453 CodeTabOf(i) = ctx->free_ent++; /* code -> hashtable */
1454 HashTabOf(i) = fcode;
1455 } else {
1456 cl_block(ctx);
1457 }
1458 }
1459
1460 /* Put out the final code. */
1461 output((code_int)ent, ctx);
1462 ++(ctx->out_count);
1463 output((code_int) ctx->EOFCode, ctx);
1464 }
1465
1466 /*****************************************************************
1467 * TAG( output )
1468 *
1469 * Output the given code.
1470 * Inputs:
1471 * code: A n_bits-bit integer. If == -1, then EOF. This assumes
1472 * that n_bits =< (long)wordsize - 1.
1473 * Outputs:
1474 * Outputs code to the file.
1475 * Assumptions:
1476 * Chars are 8 bits long.
1477 * Algorithm:
1478 * Maintain a GIFBITS character long buffer (so that 8 codes will
1479 * fit in it exactly). Use the VAX insv instruction to insert each
1480 * code in turn. When the buffer fills up empty it and start over.
1481 */
1482
1483 static const unsigned long masks[] = {
1484 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
1485 0x001F, 0x003F, 0x007F, 0x00FF,
1486 0x01FF, 0x03FF, 0x07FF, 0x0FFF,
1487 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF
1488 };
1489
1490 /* Arbitrary value to mark output is done. When we see EOFCode, then we don't
1491 * expect to see any more data. If we do (e.g. corrupt image inputs), cur_bits
1492 * might be negative, so flag it to return early.
1493 */
1494 #define CUR_BITS_FINISHED -1000
1495
1496 static void output(code_int code, GifCtx *ctx)
1497 {
1498 if (ctx->cur_bits == CUR_BITS_FINISHED)
1499 return;
1500 ctx->cur_accum &= masks[ctx->cur_bits];
1501
1502 if(ctx->cur_bits > 0) {
1503 ctx->cur_accum |= ((long)code << ctx->cur_bits);
1504 } else {
1505 ctx->cur_accum = code;
1506 }
1507
1508 ctx->cur_bits += ctx->n_bits;
1509
1510 while(ctx->cur_bits >= 8) {
1511 char_out((unsigned int)(ctx->cur_accum & 0xff), ctx);
1512 ctx->cur_accum >>= 8;
1513 ctx->cur_bits -= 8;
1514 }
1515
1516 /*
1517 * If the next entry is going to be too big for the code size,
1518 * then increase it, if possible.
1519 */
1520 if(ctx->free_ent > ctx->maxcode || ctx->clear_flg) {
1521 if(ctx->clear_flg) {
1522 ctx->maxcode = MAXCODE (ctx->n_bits = ctx->g_init_bits);
1523 ctx->clear_flg = 0;
1524 } else {
1525 ++(ctx->n_bits);
1526 if(ctx->n_bits == maxbits) {
1527 ctx->maxcode = maxmaxcode;
1528 } else {
1529 ctx->maxcode = MAXCODE(ctx->n_bits);
1530 }
1531 }
1532 }
1533
1534 if(code == ctx->EOFCode) {
1535 /* At EOF, write the rest of the buffer. */
1536 while(ctx->cur_bits > 0) {
1537 char_out((unsigned int)(ctx->cur_accum & 0xff), ctx);
1538 ctx->cur_accum >>= 8;
1539 ctx->cur_bits -= 8;
1540 }
1541 /* Flag that it's done to prevent re-entry. */
1542 ctx->cur_bits = CUR_BITS_FINISHED;
1543
1544 flush_char(ctx);
1545 }
1546 }
1547
1548 /*
1549 * Clear out the hash table
1550 */
1551 static void cl_block (GifCtx *ctx) /* table clear for block compress */
1552 {
1553 cl_hash((count_int) hsize, ctx);
1554 ctx->free_ent = ctx->ClearCode + 2;
1555 ctx->clear_flg = 1;
1556
1557 output((code_int)ctx->ClearCode, ctx);
1558 }
1559
1560 static void cl_hash(register count_int chsize, GifCtx *ctx) /* reset code table */
1561 {
1562 register count_int *htab_p = ctx->htab+chsize;
1563 register long i;
1564 register long m1 = -1;
1565
1566 i = chsize - 16;
1567 do { /* might use Sys V memset(3) here */
1568 *(htab_p - 16) = m1;
1569 *(htab_p - 15) = m1;
1570 *(htab_p - 14) = m1;
1571 *(htab_p - 13) = m1;
1572 *(htab_p - 12) = m1;
1573 *(htab_p - 11) = m1;
1574 *(htab_p - 10) = m1;
1575 *(htab_p - 9) = m1;
1576 *(htab_p - 8) = m1;
1577 *(htab_p - 7) = m1;
1578 *(htab_p - 6) = m1;
1579 *(htab_p - 5) = m1;
1580 *(htab_p - 4) = m1;
1581 *(htab_p - 3) = m1;
1582 *(htab_p - 2) = m1;
1583 *(htab_p - 1) = m1;
1584 htab_p -= 16;
1585 } while((i -= 16) >= 0);
1586
1587 for(i += 16; i > 0; --i) {
1588 *--htab_p = m1;
1589 }
1590 }
1591
1592 /******************************************************************************
1593 *
1594 * GIF Specific routines
1595 *
1596 ******************************************************************************/
1597
1598 /*
1599 * Set up the 'byte output' routine
1600 */
1601 static void char_init(GifCtx *ctx)
1602 {
1603 ctx->a_count = 0;
1604 }
1605
1606 /*
1607 * Add a character to the end of the current packet, and if it is 254
1608 * characters, flush the packet to disk.
1609 */
1610 static void char_out(int c, GifCtx *ctx)
1611 {
1612 ctx->accum[ctx->a_count++] = c;
1613 if(ctx->a_count >= 254) {
1614 flush_char(ctx);
1615 }
1616 }
1617
1618 /*
1619 * Flush the packet to disk, and reset the accumulator
1620 */
1621 static void flush_char(GifCtx *ctx)
1622 {
1623 if(ctx->a_count > 0) {
1624 gdPutC(ctx->a_count, ctx->g_outfile);
1625 gdPutBuf(ctx->accum, ctx->a_count, ctx->g_outfile);
1626 ctx->a_count = 0;
1627 }
1628 }
1629
1630 static int gifPutWord(int w, gdIOCtx *out)
1631 {
1632 /* Byte order is little-endian */
1633 gdPutC(w & 0xFF, out);
1634 gdPutC((w >> 8) & 0xFF, out);
1635 return 0;
1636 }
1637