Utah Raster Toolkit  9999-git
URT Development version (post-3.1b)
compgif.c
Go to the documentation of this file.
1 /*
2  * This software is copyrighted as noted below. It may be freely copied,
3  * modified, and redistributed, provided that the copyright notice is
4  * preserved on all copies.
5  *
6  * There is no warranty or other guarantee of fitness for this software,
7  * it is provided solely "as is". Bug reports or fixes may be sent
8  * to the author, who may or may not act on them as he desires.
9  *
10  * You may not include this software in a program or other software product
11  * without supplying the source, or without informing the end-user that the
12  * source is available for no extra charge.
13  *
14  * If you modify this software, you should include a notice giving the
15  * name of the person performing the modification, the date of modification,
16  * and the reason for such modification.
17  */
18 
19 /* compgif.c */
20 /*
21  *
22  * GIF Image compression - LZW algorithm implemented with Trie type
23  * structure.
24  * Written by Bailey Brown, Jr.
25  * last change May 24, 1990
26  * file: compgif.c
27  *
28  * You may use or modify this code as you wish, as long as you mention
29  * my name in your documentation.
30  *
31  * - Bailey Brown, Jr.
32  *
33  */
34 
35 #include "rle_config.h"
36 #include <stdio.h>
37 #include "rletogif.h"
38 
39 #define MAXIMUMCODE 4095 /* 2**maximum_code_size */
40 #define BLOCKSIZE 256 /* max block byte count + 1 */
41 #define NULLPREFIX -1
42 
43 
44 typedef struct str_table_entry {
45  int code;
46  int prefix;
47  int suffix;
48 } strTableEntry;
49 
50 typedef struct str_table_node {
51  strTableEntry entry;
55 } strTableNode, *strTableNodePtr, **strTable;
56 
57 int pack_bits();
58 
59 
60 /*
61  ********************************************************************
62  * compgif() recieves pointers to an input function and an output *
63  * stream, and the code size as parameters and outputs successive *
64  * blocks of LZW compressed gif data. The calling routine should *
65  * have aready written the GIF file header out to the output file. *
66  * It assumes that there will be no more than 8 bits/pixel and that *
67  * each data item comes from successive bytes returned by infun. *
68  ********************************************************************
69  */
70 int compgif(code_size, os, infun)
71 int code_size; /* i.e. for 8 bits/pixel code_size = 9; */
72 FILE* os;/* output stream should be open in write-binary mode */
73 ifunptr infun; /* input function should return consecutive pixel values */
74 {
75  strTable heap; /* our very own memory manager */
76  int heap_index;
77  int clear_code, end_code, cur_code;
78  int i, found, num_colors, prefix, compress_size;
79  int cur_char, end_of_data, bits_per_pix;
80  strTableNodePtr cur_node;
81  strTable root; /* root of string table for LZW compression */
82  /* is an array of 2**bits_per_pix pointers
83  to atomic nodes */
84  heap_index = 0;
85  heap = (strTable)malloc(sizeof(strTableNodePtr)*MAXIMUMCODE);
86  if (heap == NULL) error("can't allocate heap");
87  for (i=0; i < MAXIMUMCODE; i++) {
88  heap[i] = (strTableNodePtr)malloc(sizeof(strTableNode));
89  if (heap[i] == NULL) error("can't allocate heap");
90  }
91  bits_per_pix = code_size - 1;
92  compress_size = code_size;
93  num_colors = 1<<(bits_per_pix);
94  clear_code = num_colors;
95  end_code = clear_code + 1;
96  cur_code = end_code + 1;
97  prefix = NULLPREFIX;
98  root = (strTable)malloc(sizeof(strTableNodePtr)*num_colors);
99  if (!root) error("memory allocation failure (root)");
100  for(i=0; i<num_colors; i++) {
101  root[i] = heap[heap_index++];
102  root[i]->entry.code = i;
103  root[i]->entry.prefix = NULLPREFIX;
104  root[i]->entry.suffix = i;
105  root[i]->left = NULL;
106  root[i]->right = NULL;
107  root[i]->children = NULL;
108  }
109  /* initialize output block */
110  pack_bits(compress_size, -1, os);
111  pack_bits(compress_size, clear_code, os);
112  end_of_data = 0;
113  if((cur_char = GIFNextPixel(infun)) == EOF) error("premature end of data");
114  while (!end_of_data) {
115  prefix = cur_char;
116  cur_node = root[prefix];
117  found = 1;
118  if((cur_char = GIFNextPixel(infun)) == EOF) {
119  end_of_data = 1; break;
120  }
121  while(cur_node->children && found) {
122  cur_node = cur_node->children;
123  while(cur_node->entry.suffix != cur_char) {
124  if (cur_char < cur_node->entry.suffix) {
125  if (cur_node->left) cur_node = cur_node->left;
126  else {
127  cur_node->left = heap[heap_index++];
128  cur_node = cur_node->left;
129  found = 0; break;
130  }
131  }
132  else {
133  if (cur_node->right) cur_node = cur_node->right;
134  else {
135  cur_node->right = heap[heap_index++];
136  cur_node = cur_node->right;
137  found = 0; break;
138  }
139  }
140  }
141  if (found) {
142  prefix = cur_node->entry.code;
143  if((cur_char = GIFNextPixel(infun)) == EOF) {
144  end_of_data = 1; break;
145  }
146  }
147  }
148  if (end_of_data) break;
149  if (found) {
150  cur_node->children = heap[heap_index++];
151  cur_node = cur_node->children;
152  }
153  cur_node->children = NULL;
154  cur_node->left = NULL;
155  cur_node->right = NULL;
156  cur_node->entry.code = cur_code;
157  cur_node->entry.prefix = prefix;
158  cur_node->entry.suffix = cur_char;
159  pack_bits(compress_size, prefix, os);
160  if (cur_code > ((1<<(compress_size))-1))
161  compress_size++;
162  if (cur_code < MAXIMUMCODE) {
163  cur_code++;
164  }
165  else {
166  heap_index = num_colors; /* reinitialize string table */
167  for (i=0; i < num_colors; i++ ) root[i]->children = NULL;
168  pack_bits(compress_size, clear_code, os);
169  compress_size = bits_per_pix + 1;
170  cur_code = end_code + 1;
171  }
172  }
173  pack_bits(compress_size, prefix, os);
174  pack_bits(compress_size, end_code, os);
175  pack_bits(compress_size, -1, os);
176  for (i=0; i < MAXIMUMCODE; i++) free(heap[i]);
177  free(heap);
178  free(root);
179  return (1);
180 }
181 
182 
183 
184 /*
185  ************************************************************************
186  * pack_bits() packs the bits of the codes generated by gifenc() into *
187  * a 1..256 byte output block. The first byte of the block is the *
188  * number 0..255 of data bytes in the block. To flush or initialize *
189  * the block, pass a negative argument. *
190  ************************************************************************
191  */
192 int pack_bits(compress_size, prefix, os)
193 int compress_size;
194 int prefix;
195 FILE* os;
196 {
197  static int cur_bit = 8;
198  static unsigned char block[BLOCKSIZE] = { 0 };
199  int i, left_over_bits;
200 
201  /* if we are about to excede the bounds of block or if the flush
202  code (code_bis < 0) we output the block */
203  if((cur_bit + compress_size > (BLOCKSIZE-1)*8) || (prefix < 0)) {
204  /* handle case of data overlapping blocks */
205  if ((left_over_bits = (((cur_bit>>3) +
206  ((cur_bit & 7) != 0))<<3) - cur_bit) != 0) {
207  for (i=0; i < left_over_bits; i++) {
208  if(prefix & (1<<i)) block[cur_bit>>3] |= (char)(1<<(cur_bit & 7));
209  /* note n>>3 == n/8 and n & 7 == n % 8 */
210  cur_bit++;
211  }
212  }
213  compress_size -= left_over_bits;
214  prefix = prefix>>left_over_bits;
215  block[0] = (unsigned char)((cur_bit>>3) - 1);
216  if (block[0]) fwrite(block,1,block[0]+1,os);
217  for(i=0; i < BLOCKSIZE; i++) block[i] = 0;
218  cur_bit = 8;
219  }
220  if (prefix >= 0) {
221  for (i=0; i < compress_size; i++) {
222  if(prefix & (1<<i)) block[cur_bit>>3] |=
223  (unsigned char)(1<<(cur_bit & 7));
224  /* note n>>3 == n/8 and n & 7 == n % 8 */
225  cur_bit++;
226  }
227  }
228  return (1);
229 }
230 
231 /* end of compgif.c */
struct str_table_node * children
Definition: compgif.c:54
struct str_table_node * right
Definition: compgif.c:53
int suffix
Definition: compgif.c:47
struct str_table_node * left
Definition: compgif.c:52
int(* ifunptr)()
Definition: rletogif.h:8
#define NULLPREFIX
Definition: compgif.c:41
Definition: compgif.c:44
#define MAXIMUMCODE
Definition: compgif.c:39
#define BLOCKSIZE
Definition: compgif.c:40
int code
Definition: compgif.c:45
strTableEntry entry
Definition: compgif.c:51
int prefix
Definition: compgif.c:46