"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 }