PageRenderTime 61ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/Root-branch-php-utl/SWIG/Examples/GIFPlot/Lib/gif.c

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