~ubuntu-branches/ubuntu/maverick/swig1.3/maverick

« back to all changes in this revision

Viewing changes to Examples/GIFPlot/Lib/gif.c

  • Committer: Bazaar Package Importer
  • Author(s): Torsten Landschoff
  • Date: 2002-03-29 01:56:07 UTC
  • Revision ID: james.westby@ubuntu.com-20020329015607-c0wt03xu8oy9ioj7
Tags: upstream-1.3.11
ImportĀ upstreamĀ versionĀ 1.3.11

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ----------------------------------------------------------------------------- 
 
2
 * gif.c
 
3
 *
 
4
 *     GIF encoding with broken compression algorithm to avoid LZW.
 
5
 * 
 
6
 * Author(s) : David Beazley (beazley@cs.uchicago.edu)
 
7
 * Copyright (C) 1995-1996
 
8
 *
 
9
 * See the file LICENSE for information on usage and redistribution.    
 
10
 * ----------------------------------------------------------------------------- */
 
11
 
 
12
/*
 
13
 * xvgifwr.c  -  handles writing of GIF files.  based on flgife.c and
 
14
 *               flgifc.c from the FBM Library, by Michael Maudlin
 
15
 *
 
16
 * Contains: 
 
17
 *   WriteGIF(fp, pic, ptype, w, h, rmap, gmap, bmap, numcols, colorstyle,
 
18
 *            comment)
 
19
 *
 
20
 * Note: slightly brain-damaged, in that it'll only write non-interlaced 
 
21
 *       GIF files (in the interests of speed, or something)
 
22
 *
 
23
 */
 
24
 
 
25
/*****************************************************************
 
26
 * Portions of this code Copyright (C) 1989 by Michael Mauldin.
 
27
 * Permission is granted to use this file in whole or in
 
28
 * part for any purpose, educational, recreational or commercial,
 
29
 * provided that this copyright notice is retained unchanged.
 
30
 * This software is available to all free of charge by anonymous
 
31
 * FTP and in the UUNET archives.
 
32
 *
 
33
 *
 
34
 * Authors:  Michael Mauldin (mlm@cs.cmu.edu)
 
35
 *           David Rowley (mgardi@watdcsu.waterloo.edu)
 
36
 *
 
37
 * Based on: compress.c - File compression ala IEEE Computer, June 1984.
 
38
 *
 
39
 *      Spencer W. Thomas       (decvax!harpo!utah-cs!utah-gr!thomas)
 
40
 *      Jim McKie               (decvax!mcvax!jim)
 
41
 *      Steve Davies            (decvax!vax135!petsd!peora!srd)
 
42
 *      Ken Turkowski           (decvax!decwrl!turtlevax!ken)
 
43
 *      James A. Woods          (decvax!ihnp4!ames!jaw)
 
44
 *      Joe Orost               (decvax!vax135!petsd!joe)
 
45
 *****************************************************************/
 
46
 
 
47
#include "gifplot.h"
 
48
#include <string.h> 
 
49
typedef long int        count_int;
 
50
typedef unsigned char   byte;
 
51
 
 
52
static int  gif_error;
 
53
static unsigned char *op;
 
54
static int  Width, Height;
 
55
static int  curx, cury;
 
56
static int  Interlace;
 
57
 
 
58
static void putgifword(int);
 
59
static void compress(int, byte **, int);
 
60
static void output_GIF(int);
 
61
static void cl_block(void);
 
62
static void cl_hash(count_int);
 
63
static void char_init(void);
 
64
static void char_out(int);
 
65
static void flush_char(void);
 
66
static void *OutBuffer;
 
67
static int   OutBufSize;
 
68
static FrameBuffer *GIF_frame;
 
69
 
 
70
static unsigned char pc2nc[256],r1[256],g1[256],b1[256];
 
71
 
 
72
/*************************************************************/
 
73
int FrameBuffer_makeGIF(FrameBuffer *f, ColorMap *c, void *outbuffer, unsigned int outbufsize)
 
74
{
 
75
  int   RWidth, RHeight;
 
76
  int   LeftOfs, TopOfs;
 
77
  int   ColorMapSize, InitCodeSize, Background, BitsPerPixel;
 
78
  int   i,j,nc;
 
79
  char *rmap, *gmap, *bmap;
 
80
  char *cmap;
 
81
  int   count;
 
82
 
 
83
  Interlace = 0;
 
84
  Background = 0;
 
85
  OutBuffer = outbuffer;
 
86
  OutBufSize = outbufsize;
 
87
  GIF_frame = f;
 
88
  cmap = (char *) c->cmap;
 
89
  
 
90
  op = (unsigned char *) outbuffer;
 
91
  gif_error = 0;
 
92
  for (i=0; i<256; i++) { pc2nc[i] = r1[i] = g1[i] = b1[i] = 0; }
 
93
 
 
94
  /* compute number of unique colors */
 
95
  nc = 0;
 
96
  rmap = &cmap[0];
 
97
  gmap = &cmap[256];
 
98
  bmap = &cmap[512];
 
99
 
 
100
  for (i=0; i<256; i++) {
 
101
    /* see if color #i is already used */
 
102
    for (j=0; j<i; j++) {
 
103
      if (rmap[i] == rmap[j] && gmap[i] == gmap[j] && 
 
104
          bmap[i] == bmap[j]) break;
 
105
    }
 
106
 
 
107
    if (j==i) {  /* wasn't found */
 
108
      pc2nc[i] = nc;
 
109
      r1[nc] = rmap[i];
 
110
      g1[nc] = gmap[i];
 
111
      b1[nc] = bmap[i];
 
112
      nc++;
 
113
    }
 
114
    else pc2nc[i] = pc2nc[j];
 
115
  }
 
116
 
 
117
  /* figure out 'BitsPerPixel' */
 
118
  for (i=1; i<8; i++)
 
119
    if ( (1<<i) >= nc) break;
 
120
  
 
121
  BitsPerPixel = i;
 
122
 
 
123
  ColorMapSize = 1 << BitsPerPixel;
 
124
        
 
125
  RWidth  = Width  = f->width;
 
126
  RHeight = Height = f->height;
 
127
  LeftOfs = TopOfs = 0;
 
128
 
 
129
  if (BitsPerPixel <= 1) InitCodeSize = 2;
 
130
                    else InitCodeSize = BitsPerPixel;
 
131
 
 
132
  curx = 0;
 
133
  cury = f->height - 1;
 
134
 
 
135
  strcpy((char *) op,"GIF89a");        /* Put in GIF magic number */
 
136
  op+=6;
 
137
  putgifword(RWidth);           /* screen descriptor */
 
138
  putgifword(RHeight);
 
139
 
 
140
  i = 0x80;                      /* Yes, there is a color map */
 
141
  i |= (8-1)<<4;                 /* OR in the color resolution (hardwired 8) */
 
142
  i |= (BitsPerPixel - 1);       /* OR in the # of bits per pixel */
 
143
  *(op++) = i;
 
144
  *(op++) = Background;          /* background color */
 
145
  *(op++) = 0;
 
146
  for (i=0; i<ColorMapSize; i++) {       /* write out Global colormap */
 
147
    *(op++) = r1[i];
 
148
    *(op++) = g1[i];
 
149
    *(op++) = b1[i];
 
150
  }
 
151
 
 
152
  *(op++) = ',';                /* image separator */
 
153
 
 
154
  /* Write the Image header */
 
155
  putgifword(LeftOfs);
 
156
  putgifword(TopOfs);
 
157
  putgifword(Width);
 
158
  putgifword(Height);
 
159
  *(op++) = 0;
 
160
  *(op++) = InitCodeSize;
 
161
 
 
162
  compress(InitCodeSize+1, f->pixels, f->width*f->height);
 
163
 
 
164
  *(op++) = 0;
 
165
  *(op++) = ';';
 
166
  
 
167
  count = (op - (unsigned char *) OutBuffer);
 
168
  if (gif_error) return -1;
 
169
  else return count;
 
170
}
 
171
 
 
172
/******************************/
 
173
static void putgifword(w)
 
174
int w;
 
175
{
 
176
  /* writes a 16-bit integer in GIF order (LSB first) */
 
177
  *(op++) = w & 0xff;
 
178
  *(op++) = (w>>8)&0xff;
 
179
}
 
180
 
 
181
/***********************************************************************/
 
182
 
 
183
 
 
184
static unsigned long cur_accum = 0;
 
185
static int           cur_bits = 0;
 
186
 
 
187
 
 
188
 
 
189
 
 
190
#define GP_BITS 12    /* BITS was already defined on some systems */
 
191
 
 
192
#define HSIZE  5003            /* 80% occupancy */
 
193
 
 
194
typedef unsigned char   char_type;
 
195
 
 
196
static int n_bits;                    /* number of bits/code */
 
197
static int maxbits = GP_BITS;         /* user settable max # bits/code */
 
198
static int maxcode;                   /* maximum code, given n_bits */
 
199
static int maxmaxcode = 1 << GP_BITS; /* NEVER generate this */
 
200
 
 
201
#define MAXCODE(n_bits)     ( (1 << (n_bits)) - 1)
 
202
 
 
203
static  count_int      *htab;
 
204
static  unsigned short *codetab;
 
205
static  GIFOutBufSize;
 
206
 
 
207
/* static  count_int      htab [HSIZE];
 
208
static  unsigned short codetab [HSIZE]; */
 
209
 
 
210
#define HashTabOf(i)   htab[i]
 
211
#define CodeTabOf(i)   codetab[i]
 
212
 
 
213
static int hsize = HSIZE;            /* for dynamic table sizing */
 
214
 
 
215
/*
 
216
 * To save much memory, we overlay the table used by compress() with those
 
217
 * used by decompress().  The tab_prefix table is the same size and type
 
218
 * as the codetab.  The tab_suffix table needs 2**BITS characters.  We
 
219
 * get this from the beginning of htab.  The output stack uses the rest
 
220
 * of htab, and contains characters.  There is plenty of room for any
 
221
 * possible stack (stack used to be 8000 characters).
 
222
 */
 
223
 
 
224
#define tab_prefixof(i) CodeTabOf(i)
 
225
#define tab_suffixof(i)        ((char_type *)(htab))[i]
 
226
#define de_stack               ((char_type *)&tab_suffixof(1<<GP_BITS))
 
227
 
 
228
static int free_ent = 0;                  /* first unused entry */
 
229
 
 
230
/*
 
231
 * block compression parameters -- after all codes are used up,
 
232
 * and compression rate changes, start over.
 
233
 */
 
234
static int clear_flg = 0;
 
235
 
 
236
static long int out_count = 0;           /* # of codes output (for debugging) */
 
237
 
 
238
/*
 
239
 * compress stdin to stdout
 
240
 *
 
241
 * Algorithm:  use open addressing double hashing (no chaining) on the 
 
242
 * prefix code / next character combination.  We do a variant of Knuth's
 
243
 * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
 
244
 * secondary probe.  Here, the modular division first probe is gives way
 
245
 * to a faster exclusive-or manipulation.  Also do block compression with
 
246
 * an adaptive reset, whereby the code table is cleared when the compression
 
247
 * ratio decreases, but after the table fills.  The variable-length output
 
248
 * codes are re-sized at this point, and a special CLEAR code is generated
 
249
 * for the decompressor.  Late addition:  construct the table according to
 
250
 * file size for noticeable speed improvement on small files.  Please direct
 
251
 * questions about this implementation to ames!jaw.
 
252
 */
 
253
 
 
254
static int g_init_bits;
 
255
 
 
256
static int ClearCode;
 
257
static int EOFCode;
 
258
 
 
259
 
 
260
/********************************************************/
 
261
static void compress(init_bits, data, len)
 
262
         int   init_bits;
 
263
         unsigned char **data;
 
264
         int   len;
 
265
{
 
266
  register long fcode;
 
267
  register int i = 0;
 
268
  register int c;
 
269
  register int ent;
 
270
  register int disp;
 
271
  register int hsize_reg;
 
272
  register int hshift;
 
273
  int      code_count = 0;
 
274
 
 
275
  /* Use the output buffer as temporary storage for GIF data */
 
276
 
 
277
  if (OutBufSize < HSIZE*(sizeof(count_int) + sizeof(unsigned short))) {
 
278
    gif_error =1;
 
279
    return;
 
280
  }
 
281
 
 
282
  /* Put htab and codetab arrays into the output buffer */
 
283
 
 
284
  GIFOutBufSize = OutBufSize - HSIZE*(sizeof(count_int) + sizeof(unsigned short)) - 16;
 
285
  GIFOutBufSize = GIFOutBufSize & (~0x3);       /* Make sure it's double word alligned */
 
286
 
 
287
  htab = (count_int *) ((char *) OutBuffer + GIFOutBufSize);
 
288
  codetab = (unsigned short *) ((char *) OutBuffer + GIFOutBufSize + HSIZE*sizeof(count_int));
 
289
 
 
290
  /*
 
291
   * Set up the globals:  g_init_bits - initial number of bits
 
292
   *                      g_outfile   - pointer to output file
 
293
   */
 
294
  g_init_bits = init_bits;
 
295
 
 
296
 
 
297
  /* initialize 'compress' globals */
 
298
  maxbits = GP_BITS;
 
299
  maxmaxcode = 1<<GP_BITS;
 
300
  memset(htab,0,sizeof(htab));
 
301
  memset(codetab,0,sizeof(codetab));
 
302
  hsize = HSIZE;
 
303
  free_ent = 0;
 
304
  clear_flg = 0;
 
305
  out_count = 0;
 
306
  cur_accum = 0;
 
307
  cur_bits = 0;
 
308
 
 
309
  /*
 
310
   * Set up the necessary values
 
311
   */
 
312
  out_count = 0;
 
313
  clear_flg = 0;
 
314
  maxcode = MAXCODE(n_bits = g_init_bits);
 
315
 
 
316
  ClearCode = (1 << (init_bits - 1));
 
317
  EOFCode = ClearCode + 1;
 
318
  free_ent = ClearCode + 2;
 
319
 
 
320
  char_init();
 
321
  ent = pc2nc[data[cury][curx]];
 
322
  curx++;
 
323
  if (curx >= GIF_frame->width) {
 
324
    curx = 0;
 
325
    cury--;
 
326
  }
 
327
  len--;
 
328
 
 
329
  hshift = 0;
 
330
  for ( fcode = (long) hsize;  fcode < 65536L; fcode *= 2L )
 
331
    hshift++;
 
332
  hshift = 8 - hshift;                /* set hash code range bound */
 
333
 
 
334
  hsize_reg = hsize;
 
335
  cl_hash( (count_int) hsize_reg);            /* clear hash table */
 
336
 
 
337
  output_GIF(ClearCode);
 
338
  while (len) {
 
339
    c = pc2nc[data[cury][curx]];
 
340
    curx++;
 
341
    if (curx >= GIF_frame->width) {
 
342
      curx = 0;
 
343
      cury--;
 
344
    }
 
345
    len--;
 
346
 
 
347
    /* Uncompressed GIF */
 
348
    output_GIF(ent);
 
349
    code_count++;
 
350
    if (code_count >= ClearCode-2) {
 
351
      output_GIF(ClearCode);
 
352
      code_count = 0;
 
353
    }
 
354
    ent = c;
 
355
 
 
356
  }
 
357
  /* Put out the final code */
 
358
  output_GIF(ent);
 
359
  output_GIF(EOFCode);
 
360
}
 
361
 
 
362
 
 
363
/*****************************************************************
 
364
 * TAG( output_GIF )
 
365
 *
 
366
 * Output the given code.
 
367
 * Inputs:
 
368
 *      code:   A n_bits-bit integer.  If == -1, then EOF.  This assumes
 
369
 *              that n_bits =< (long)wordsize - 1.
 
370
 * Outputs:
 
371
 *      Outputs code to the file.
 
372
 * Assumptions:
 
373
 *      Chars are 8 bits long.
 
374
 * Algorithm:
 
375
 *      Maintain a BITS character long buffer (so that 8 codes will
 
376
 * fit in it exactly).  Use the VAX insv instruction to insert each
 
377
 * code in turn.  When the buffer fills up empty it and start over.
 
378
 */
 
379
 
 
380
static
 
381
unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
 
382
                                  0x001F, 0x003F, 0x007F, 0x00FF,
 
383
                                  0x01FF, 0x03FF, 0x07FF, 0x0FFF,
 
384
                                  0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
 
385
 
 
386
static void output_GIF(code)
 
387
int code;
 
388
{
 
389
  cur_accum &= masks[cur_bits];
 
390
 
 
391
  if (cur_bits > 0)
 
392
    cur_accum |= ((long)code << cur_bits);
 
393
  else
 
394
    cur_accum = code;
 
395
        
 
396
  cur_bits += n_bits;
 
397
 
 
398
  while( cur_bits >= 8 ) {
 
399
    char_out( (int) (cur_accum & 0xff) );
 
400
    cur_accum >>= 8;
 
401
    cur_bits -= 8;
 
402
  }
 
403
 
 
404
  /*
 
405
   * If the next entry is going to be too big for the code size,
 
406
   * then increase it, if possible.
 
407
   */
 
408
 
 
409
  if (free_ent > maxcode || clear_flg) {
 
410
 
 
411
    if( clear_flg ) {
 
412
      maxcode = MAXCODE (n_bits = g_init_bits);
 
413
      clear_flg = 0;
 
414
    }
 
415
    else {
 
416
      n_bits++;
 
417
      if ( n_bits == maxbits )
 
418
        maxcode = maxmaxcode;
 
419
      else
 
420
        maxcode = MAXCODE(n_bits);
 
421
    }
 
422
  }
 
423
        
 
424
  if( code == EOFCode ) {
 
425
    /* At EOF, write the rest of the buffer */
 
426
    while( cur_bits > 0 ) {
 
427
      char_out( (int)(cur_accum & 0xff) );
 
428
      cur_accum >>= 8;
 
429
      cur_bits -= 8;
 
430
    }
 
431
 
 
432
    flush_char();
 
433
  }
 
434
}
 
435
 
 
436
 
 
437
/********************************/
 
438
static void cl_block ()             /* table clear for block compress */
 
439
{
 
440
  /* Clear out the hash table */
 
441
 
 
442
  cl_hash ( (count_int) hsize );
 
443
  free_ent = ClearCode + 2;
 
444
  clear_flg = 1;
 
445
 
 
446
  output_GIF(ClearCode);
 
447
}
 
448
 
 
449
 
 
450
/********************************/
 
451
static void cl_hash(hsize)          /* reset code table */
 
452
register count_int hsize;
 
453
{
 
454
  register count_int *htab_p = htab+hsize;
 
455
  register long i;
 
456
  register long m1 = -1;
 
457
 
 
458
  i = hsize - 16;
 
459
  do {                            /* might use Sys V memset(3) here */
 
460
    *(htab_p-16) = m1;
 
461
    *(htab_p-15) = m1;
 
462
    *(htab_p-14) = m1;
 
463
    *(htab_p-13) = m1;
 
464
    *(htab_p-12) = m1;
 
465
    *(htab_p-11) = m1;
 
466
    *(htab_p-10) = m1;
 
467
    *(htab_p-9) = m1;
 
468
    *(htab_p-8) = m1;
 
469
    *(htab_p-7) = m1;
 
470
    *(htab_p-6) = m1;
 
471
    *(htab_p-5) = m1;
 
472
    *(htab_p-4) = m1;
 
473
    *(htab_p-3) = m1;
 
474
    *(htab_p-2) = m1;
 
475
    *(htab_p-1) = m1;
 
476
    htab_p -= 16;
 
477
  } while ((i -= 16) >= 0);
 
478
 
 
479
  for ( i += 16; i > 0; i-- )
 
480
    *--htab_p = m1;
 
481
}
 
482
 
 
483
 
 
484
/******************************************************************************
 
485
 *
 
486
 * GIF Specific routines
 
487
 *
 
488
 ******************************************************************************/
 
489
 
 
490
/*
 
491
 * Number of characters so far in this 'packet'
 
492
 */
 
493
static int a_count;
 
494
 
 
495
/*
 
496
 * Set up the 'byte output' routine
 
497
 */
 
498
static void char_init()
 
499
{
 
500
        a_count = 0;
 
501
}
 
502
 
 
503
/*
 
504
 * Define the storage for the packet accumulator
 
505
 */
 
506
static char accum[ 256 ];
 
507
 
 
508
/*
 
509
 * Add a character to the end of the current packet, and if it is 254
 
510
 * characters, flush the packet to disk.
 
511
 */
 
512
static void char_out(c)
 
513
int c;
 
514
{
 
515
  accum[ a_count++ ] = c;
 
516
  if( a_count >= 254 ) 
 
517
    flush_char();
 
518
}
 
519
 
 
520
/*
 
521
 * Flush the packet to disk, and reset the accumulator
 
522
 */
 
523
static void flush_char()
 
524
{
 
525
  if (gif_error) return;
 
526
  if( a_count > 0 ) {
 
527
    *(op++) = a_count;
 
528
    memcpy(op,accum,a_count);
 
529
    op+=a_count;
 
530
    a_count = 0;
 
531
    
 
532
    if (op > (unsigned char *) ((char *) OutBuffer + (GIFOutBufSize - 2048))) {
 
533
      gif_error = 1;
 
534
    }
 
535
  } 
 
536
}       
 
537
 
 
538
 
 
539
/* ----------------------------------------------------------------------
 
540
   int FrameBuffer_writeGIF(char *filename)
 
541
   
 
542
   Write a GIF file to filename
 
543
   ----------------------------------------------------------------------- */
 
544
 
 
545
int FrameBuffer_writeGIF(FrameBuffer *f, ColorMap *c, char *filename) {
 
546
 
 
547
  FILE *file;
 
548
  void *buffer;
 
549
  int nbytes;
 
550
  int bufsize;
 
551
 
 
552
  file = fopen(filename,"wb");
 
553
  if (file == NULL) return -1;
 
554
 
 
555
  bufsize = (f->width*f->height*3)/2;
 
556
  buffer = (void *) malloc(bufsize);
 
557
  nbytes = FrameBuffer_makeGIF(f,c,buffer,bufsize);
 
558
  if (nbytes == -1) { 
 
559
    free(buffer);
 
560
    fclose(file);
 
561
    return -1;
 
562
  }
 
563
  fwrite(buffer,nbytes,1,file);
 
564
  fclose(file);
 
565
  free(buffer);
 
566
  return 0;
 
567
}
 
568
 
 
569
    
 
570
  
 
571
  
 
572