w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

gd_gif_out.c
Go to the documentation of this file.
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;
68  unsigned short codetab [HSIZE];
69  /* first unused entry */
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;
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);
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 */
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 */
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 */
231 {
232  _gdImageGifCtx(im, out);
233 }
234 
235 /* returns 0 on success, 1 on failure */
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 */
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 */
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 */
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. */
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 
899 {
900 #if 1
901  putc(';', outFile);
902 #else
903  gdIOCtx *out = gdNewFileCtx(outFile);
904  if (out == NULL) return;
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 
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 
963 {
964  /*
965  * Write the GIF file terminator
966  */
967  gdPutC(';', out);
968 }
969 
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 */
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 */
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 
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 
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 
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 }
int code
Definition: aftopl.c:52
int interlace
Definition: bmp2png.c:21
int w
Definition: dviconv.c:26
int transparent
Definition: giftopnm.c:49
unsigned int Background
Definition: giftopnm.c:40
#define c(n)
Definition: gpos-common.c:150
FILE * out
Definition: hbf2gf.c:286
#define putc
Definition: jbib.h:20
static FILE * outfile
Definition: wrjpgcom.c:80
#define NULL
Definition: ftobjs.h:61
small capitals from c petite p scientific i
Definition: afcover.h:80
#define EOF
Definition: afmparse.c:59
kerning y
Definition: ttdriver.c:212
gdImagePtr gdImageCreate(int sx, int sy)
Definition: gd.c:181
int gdImageGetPixel(gdImagePtr im, int x, int y)
Definition: gd.c:1443
void gdImageDestroy(gdImagePtr im)
Definition: gd.c:387
int gdImageColorExactAlpha(gdImagePtr im, int r, int g, int b, int a)
Definition: gd.c:703
void gdImageCopy(gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int w, int h)
Definition: gd.c:2943
void gdImagePaletteCopy(gdImagePtr to, gdImagePtr from)
Definition: gd.c:923
void gdImageSetPixel(gdImagePtr im, int x, int y, int color)
Definition: gd.c:1237
gdIOCtx * gdNewDynamicCtx(int size, void *data)
Definition: gd_io_dp.c:72
gdIOCtx * gdNewFileCtx(FILE *)
Definition: gd_io_file.c:56
#define BGD_DECLARE(rt)
Definition: gd.h:79
gdImagePtr gdImageCreatePaletteFromTrueColor(gdImagePtr im, int ditherFlag, int colorsWanted)
Definition: gd_topal.c:1460
void * gdDPExtractData(struct gdIOCtx *ctx, int *size)
Definition: gd_io_dp.c:116
long int count_int
Definition: gd_gif_out.c:46
void gdImageGifAnimEndCtx(gdIOCtx *out)
Definition: gd_gif_out.c:962
void gdImageGifAnimAdd(gdImagePtr im, FILE *outFile, int LocalCM, int LeftOfs, int TopOfs, int Delay, int Disposal, gdImagePtr previm)
Definition: gd_gif_out.c:610
void gdImageGifCtx(gdImagePtr im, gdIOCtxPtr out)
Definition: gd_gif_out.c:230
void * gdImageGifAnimAddPtr(gdImagePtr im, int *size, int LocalCM, int LeftOfs, int TopOfs, int Delay, int Disposal, gdImagePtr previm)
Definition: gd_gif_out.c:487
void * gdImageGifAnimEndPtr(int *size)
Definition: gd_gif_out.c:936
void gdImageGifAnimBeginCtx(gdImagePtr im, gdIOCtxPtr out, int GlobalCM, int Loops)
Definition: gd_gif_out.c:389
void gdImageGifAnimBegin(gdImagePtr im, FILE *outFile, int GlobalCM, int Loops)
Definition: gd_gif_out.c:361
void * gdImageGifAnimBeginPtr(gdImagePtr im, int *size, int GlobalCM, int Loops)
Definition: gd_gif_out.c:299
unsigned char char_type
Definition: gd_gif_out.c:1302
void gdImageGif(gdImagePtr im, FILE *outFile)
Definition: gd_gif_out.c:207
int code_int
Definition: gd_gif_out.c:40
void gdImageGifAnimAddCtx(gdImagePtr im, gdIOCtxPtr out, int LocalCM, int LeftOfs, int TopOfs, int Delay, int Disposal, gdImagePtr previm)
Definition: gd_gif_out.c:654
void * gdImageGifPtr(gdImagePtr im, int *size)
Definition: gd_gif_out.c:134
void gdImageGifAnimEnd(FILE *outFile)
Definition: gd_gif_out.c:898
int gdPutBuf(const void *buf, int size, gdIOCtx *ctx)
Definition: gd_io.c:188
void gdPutC(const unsigned char c, gdIOCtx *ctx)
Definition: gd_io.c:31
void * gdMalloc(size_t size)
Definition: gdhelpers.c:73
int chsize()
static struct proto Pass[]
Definition: mkg3states.c:54
float x
Definition: cordic.py:15
int Height
Definition: pbmpage.c:33
int Width
Definition: pbmpage.c:32
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp
#define fp
#define B(x, y)
static int size
Definition: ppmlabel.c:24
int r
Definition: ppmqvga.c:68
static int ClearCode
Definition: ppmtogif.c:665
static int n_bits
Definition: ppmtogif.c:604
static int cur_bits
Definition: ppmtogif.c:785
static char accum[256]
Definition: ppmtogif.c:929
static code_int free_ent
Definition: ppmtogif.c:634
int Red[256]
Definition: ppmtogif.c:50
static unsigned long cur_accum
Definition: ppmtogif.c:784
static int clear_flg
Definition: ppmtogif.c:640
static long CountDown
Definition: ppmtogif.c:301
static code_int maxcode
Definition: ppmtogif.c:606
int Green[256]
Definition: ppmtogif.c:50
static long int out_count
Definition: ppmtogif.c:644
static int Interlace
Definition: ppmtogif.c:303
static FILE * g_outfile
Definition: ppmtogif.c:663
static int cury
Definition: ppmtogif.c:300
static int g_init_bits
Definition: ppmtogif.c:662
static unsigned short codetab[5003]
Definition: ppmtogif.c:615
static long int in_count
Definition: ppmtogif.c:643
static int a_count
Definition: ppmtogif.c:915
static int curx
Definition: ppmtogif.c:300
int Blue[256]
Definition: ppmtogif.c:50
static int offset
Definition: ppmtogif.c:642
static int EOFCode
Definition: ppmtogif.c:666
int colors
Definition: ppmtogif.c:51
static count_int htab[5003]
Definition: ppmtogif.c:614
bstring c int memset(void *s, int c, int length)
static void compress(int init_bits, gdIOCtx *outfile, gdImagePtr im, GifCtx *ctx)
static void output(code_int code, GifCtx *ctx)
Definition: gd_gif_out.c:1496
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)
Definition: gd_gif_out.c:1189
static void cl_hash(register count_int chsize, GifCtx *ctx)
Definition: gd_gif_out.c:1560
static int GIFNextPixel(gdImagePtr im, GifCtx *ctx)
Definition: gd_gif_out.c:1056
static int colorstobpp(int colors)
Definition: gd_gif_out.c:970
static void cl_block(GifCtx *ctx)
Definition: gd_gif_out.c:1551
#define hsize
Definition: gd_gif_out.c:57
static int gifPutWord(int w, gdIOCtx *out)
Definition: gd_gif_out.c:1630
static int _gdImageGifCtx(gdImagePtr im, gdIOCtxPtr out)
Definition: gd_gif_out.c:236
static void BumpPixel(GifCtx *ctx)
Definition: gd_gif_out.c:1007
#define CUR_BITS_FINISHED
Definition: gd_gif_out.c:1494
#define CodeTabOf(i)
Definition: gd_gif_out.c:1330
#define HashTabOf(i)
Definition: gd_gif_out.c:1329
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)
Definition: gd_gif_out.c:1075
#define maxbits
Definition: gd_gif_out.c:51
static void char_out(int c, GifCtx *ctx)
Definition: gd_gif_out.c:1610
#define MAXCODE(n_bits)
Definition: gd_gif_out.c:1326
static int comparewithmap(gdImagePtr im1, gdImagePtr im2, int c1, int c2, int *colorMap)
Definition: gd_gif_out.c:620
static const unsigned long masks[]
Definition: gd_gif_out.c:1483
#define maxmaxcode
Definition: gd_gif_out.c:54
#define HSIZE
Definition: gd_gif_out.c:56
static void char_init(GifCtx *ctx)
Definition: gd_gif_out.c:1601
static int _gdImageGifAnimAddCtx(gdImagePtr im, gdIOCtxPtr out, int LocalCM, int LeftOfs, int TopOfs, int Delay, int Disposal, gdImagePtr previm)
Definition: gd_gif_out.c:663
static void flush_char(GifCtx *ctx)
Definition: gd_gif_out.c:1621
long int out_count
Definition: gd_gif_out.c:77
gdIOCtx * g_outfile
Definition: gd_gif_out.c:79
int offset
Definition: gd_gif_out.c:74
int cur_bits
Definition: gd_gif_out.c:83
int EOFCode
Definition: gd_gif_out.c:81
int curx
Definition: gd_gif_out.c:61
code_int free_ent
Definition: gd_gif_out.c:70
int Height
Definition: gd_gif_out.c:60
code_int maxcode
Definition: gd_gif_out.c:66
count_int htab[5003]
Definition: gd_gif_out.c:67
int a_count
Definition: gd_gif_out.c:84
int g_init_bits
Definition: gd_gif_out.c:78
long int in_count
Definition: gd_gif_out.c:75
int Interlace
Definition: gd_gif_out.c:64
unsigned long cur_accum
Definition: gd_gif_out.c:82
long CountDown
Definition: gd_gif_out.c:62
int clear_flg
Definition: gd_gif_out.c:73
char accum[256]
Definition: gd_gif_out.c:85
int Width
Definition: gd_gif_out.c:60
int ClearCode
Definition: gd_gif_out.c:80
int Pass
Definition: gd_gif_out.c:63
int n_bits
Definition: gd_gif_out.c:65
int cury
Definition: gd_gif_out.c:61
Definition: inftrees.h:24
Definition: gd_io.h:59
int trueColor
Definition: gd.h:412
int alpha[256]
Definition: gd.h:409
int green[256]
Definition: gd.h:375
int interlace
Definition: gd.h:398
int blue[256]
Definition: gd.h:376
int sy
Definition: gd.h:369
int sx
Definition: gd.h:368
int transparent
Definition: gd.h:388
int colorsTotal
Definition: gd.h:373
int red[256]
Definition: gd.h:374
#define c2
Definition: t1io.c:53
#define c1
Definition: t1io.c:52
#define FILE
Definition: t1stdio.h:34