diff options
Diffstat (limited to 'baseline/source/huff_enc/huff_enc.c')
-rw-r--r-- | baseline/source/huff_enc/huff_enc.c | 589 |
1 files changed, 589 insertions, 0 deletions
diff --git a/baseline/source/huff_enc/huff_enc.c b/baseline/source/huff_enc/huff_enc.c new file mode 100644 index 0000000..2e739e6 --- /dev/null +++ b/baseline/source/huff_enc/huff_enc.c | |||
@@ -0,0 +1,589 @@ | |||
1 | /* | ||
2 | |||
3 | This program is part of the TACLeBench benchmark suite. | ||
4 | Version V 2.0 | ||
5 | |||
6 | Name: huff_enc | ||
7 | |||
8 | Author: David Bourgin (David.Bourgin@ufrima.imag.fr) | ||
9 | |||
10 | Function: Example of Huffman encoding | ||
11 | |||
12 | Source: ftp://turing.imag.fr/pub/compression/ (1994-09-22) | ||
13 | |||
14 | Original name: codhuff.c | ||
15 | |||
16 | Changes: I/O to char arrays instead of file i/o. | ||
17 | Dynamic memory allocation replaced by array. | ||
18 | Explicit sorting algorithm. | ||
19 | |||
20 | License: | ||
21 | |||
22 | The source code files (codrl1.c, dcodrl1.c, codrle2.c, dcodrle2.c, codrle3.c, | ||
23 | dcodrle3.c, codrle4.c, dcodrle4.c, codhuff.c, dcodhuff.c) are copyrighted. | ||
24 | They have been uploaded on ftp in turing.imag.fr (129.88.31.7):/pub/compression | ||
25 | on 22/5/94 and have been modified on 22/9/94. | ||
26 | (c) David Bourgin - 1994 | ||
27 | The source codes I provide have no buggs (!) but being that I make them | ||
28 | available for free I have some notes to make. They can change at any time | ||
29 | without notice. I assume no responsability or liability for any errors or | ||
30 | inaccurracies, make no warranty of any kind (express, implied or statutory) | ||
31 | with respect to this publication and expressly disclaim any and all warranties | ||
32 | of merchantability, fitness for particular purposes. Of course, if you have | ||
33 | some problems to use the information presented here, I will try to help you if | ||
34 | I can. | ||
35 | |||
36 | If you include the source codes in your application, here are the conditions: | ||
37 | - You have to put my name in the header of your source file (not in the | ||
38 | excutable program if you don't want) (this item is a must) | ||
39 | - I would like to see your resulting application, if possible (this item is not | ||
40 | a must, because some applications must remain secret) | ||
41 | - Whenever you gain money with your application, I would like to receive a very | ||
42 | little part in order to be encouraged to update my source codes and to develop | ||
43 | new schemes (this item is not a must) | ||
44 | |||
45 | */ | ||
46 | |||
47 | |||
48 | /* | ||
49 | Declaration of types | ||
50 | */ | ||
51 | |||
52 | |||
53 | #include "../extra.h" | ||
54 | typedef struct huff_enc_s_tree { | ||
55 | unsigned int byte; /* A byte has to be coded as an unsigned integer to | ||
56 | allow a node to have a value over 255 */ | ||
57 | unsigned long int weight; | ||
58 | struct huff_enc_s_tree *left_ptr; | ||
59 | struct huff_enc_s_tree *right_ptr; | ||
60 | } huff_enc_t_tree; | ||
61 | |||
62 | typedef struct { | ||
63 | unsigned char bits[32]; | ||
64 | unsigned int bits_nb; | ||
65 | } huff_enc_t_bin_val; | ||
66 | |||
67 | |||
68 | /* | ||
69 | Forward declaration of functions | ||
70 | */ | ||
71 | |||
72 | void huff_enc_init( void ); | ||
73 | int huff_enc_return( void ); | ||
74 | void huff_enc_beginning_of_data(); | ||
75 | int huff_enc_end_of_data(); | ||
76 | int huff_enc_read_byte(); | ||
77 | void huff_enc_write_byte( char ch ); | ||
78 | void huff_enc_write_bin_val( huff_enc_t_bin_val bin_val ); | ||
79 | void huff_enc_fill_encoding( void ); | ||
80 | void huff_enc_write_header( huff_enc_t_bin_val codes_table[257] ); | ||
81 | int huff_enc_weighhuff_enc_t_tree_comp( const void *t1, const void *t2 ); | ||
82 | void huff_enc_swapi( char *ii, char *ij, unsigned long es ); | ||
83 | char *huff_enc_pivot( char *a, unsigned long n, unsigned long es ); | ||
84 | void huff_enc_qsort( char *a, unsigned long n, unsigned long es ); | ||
85 | huff_enc_t_tree *huff_enc_build_tree_encoding( huff_enc_t_tree heap[514] ); | ||
86 | void huff_enc_encode_codes_table( huff_enc_t_tree *tree, | ||
87 | huff_enc_t_bin_val codes_table[257], huff_enc_t_bin_val *code_val ); | ||
88 | void huff_enc_create_codes_table( huff_enc_t_tree *tree, | ||
89 | huff_enc_t_bin_val codes_table[257] ); | ||
90 | void huff_enc_main(); | ||
91 | //int main( void ); | ||
92 | |||
93 | |||
94 | /* | ||
95 | Declaration of global variables | ||
96 | */ | ||
97 | |||
98 | static int huff_enc_input_pos; | ||
99 | static int huff_enc_output_pos; | ||
100 | static unsigned char huff_enc_output[1024]; | ||
101 | static unsigned char huff_enc_byte_nb_to_write = 0; | ||
102 | static unsigned char huff_enc_val_to_write = 0; | ||
103 | |||
104 | |||
105 | /* | ||
106 | Initialization- and return-value-related functions | ||
107 | */ | ||
108 | |||
109 | #define huff_enc_plaintext_len 600 | ||
110 | static const char *huff_enc_plaintext = | ||
111 | "You are doubtless asking \"How can I reduce the data size without losing " | ||
112 | "some informations?\". It's easy to answer to this question. I'll only take " | ||
113 | "an example. I'm sure you have heard about the morse. This system established " | ||
114 | "in the 19th century use a scheme very close to the huffman one. In the morse " | ||
115 | "you encode the letters to transmit with two kinds of signs. If you encode " | ||
116 | "these two sign possibilities in one bit, the symbol 'e' is transmitted in a " | ||
117 | "single bit and the symbols 'y' and 'z' need four bits. Look at the symbols " | ||
118 | "in the text you are reading, you'll fast understand the compression ratio..."; | ||
119 | |||
120 | #define huff_enc_encoded_len 419 | ||
121 | static unsigned char huff_enc_encoded[huff_enc_encoded_len] = { | ||
122 | 128, 0, 0, 0, 80, 133, 32, 32, 128, 100, 4, 32, 63, 239, 255, 240, | ||
123 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
124 | 4, 7, 167, 21, 129, 232, 69, 120, 132, 217, 20, 162, 19, 164, 39, 133, | ||
125 | 252, 138, 105, 20, 194, 19, 129, 240, 172, 138, 248, 150, 11, 11, 240, 201, | ||
126 | 68, 64, 114, 53, 17, 42, 37, 195, 128, 212, 116, 194, 41, 98, 52, 51, | ||
127 | 12, 132, 112, 244, 3, 36, 33, 52, 39, 135, 164, 33, 62, 156, 87, 14, | ||
128 | 110, 22, 87, 50, 85, 198, 99, 142, 140, 194, 81, 78, 158, 84, 129, 254, | ||
129 | 129, 248, 110, 179, 159, 192, 145, 133, 184, 184, 28, 210, 96, 146, 73, 10, | ||
130 | 226, 21, 83, 152, 74, 13, 111, 132, 199, 202, 219, 241, 74, 193, 167, 105, | ||
131 | 222, 31, 147, 6, 55, 31, 129, 40, 232, 52, 153, 160, 148, 18, 36, 197, | ||
132 | 45, 216, 202, 86, 30, 31, 177, 90, 133, 138, 248, 23, 81, 195, 160, 100, | ||
133 | 215, 93, 50, 185, 225, 251, 23, 6, 230, 225, 229, 112, 71, 80, 96, 141, | ||
134 | 205, 176, 230, 85, 196, 9, 24, 93, 90, 121, 225, 76, 68, 152, 63, 25, | ||
135 | 107, 140, 101, 204, 214, 77, 26, 194, 96, 18, 48, 77, 210, 137, 1, 253, | ||
136 | 4, 230, 248, 56, 240, 224, 111, 163, 95, 10, 12, 223, 7, 234, 167, 129, | ||
137 | 40, 36, 96, 135, 125, 245, 250, 2, 198, 120, 127, 0, 145, 133, 213, 167, | ||
138 | 135, 149, 195, 67, 235, 108, 9, 24, 87, 17, 102, 152, 37, 4, 222, 131, | ||
139 | 188, 144, 73, 36, 128, 73, 20, 81, 152, 177, 133, 248, 28, 165, 131, 120, | ||
140 | 127, 240, 242, 184, 104, 125, 109, 129, 35, 30, 4, 145, 65, 202, 88, 9, | ||
141 | 138, 103, 44, 205, 100, 167, 24, 152, 11, 24, 51, 37, 66, 9, 24, 31, | ||
142 | 174, 202, 212, 49, 152, 18, 96, 155, 208, 119, 146, 45, 97, 48, 56, 28, | ||
143 | 194, 90, 224, 204, 144, 232, 176, 36, 96, 126, 187, 43, 83, 12, 121, 129, | ||
144 | 209, 96, 197, 35, 2, 54, 176, 249, 92, 208, 204, 145, 188, 41, 170, 180, | ||
145 | 71, 16, 36, 96, 126, 187, 43, 83, 19, 0, 145, 129, 100, 209, 15, 43, | ||
146 | 135, 55, 6, 238, 180, 194, 90, 17, 229, 115, 21, 168, 251, 140, 131, 162, | ||
147 | 217, 166, 93, 22, 4, 140, 31, 91, 166, 55, 25, 202, 192, 111, 20, 171, | ||
148 | 207, 39, 192, | ||
149 | }; | ||
150 | |||
151 | |||
152 | void huff_enc_init( void ) | ||
153 | { | ||
154 | huff_enc_input_pos = 0; | ||
155 | huff_enc_output_pos = 0; | ||
156 | } | ||
157 | |||
158 | |||
159 | int huff_enc_return( void ) | ||
160 | { | ||
161 | int i; | ||
162 | _Pragma( "loopbound min 1 max 419" ) | ||
163 | for ( i = 0; i < huff_enc_encoded_len; i++ ) { | ||
164 | if ( huff_enc_encoded[i] != huff_enc_output[i] ) return i + 1; | ||
165 | } | ||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | |||
170 | /* | ||
171 | Input / output functions | ||
172 | */ | ||
173 | |||
174 | void huff_enc_beginning_of_data() | ||
175 | { | ||
176 | huff_enc_input_pos = 0; | ||
177 | } | ||
178 | |||
179 | |||
180 | int huff_enc_end_of_data() | ||
181 | { | ||
182 | return huff_enc_input_pos >= huff_enc_plaintext_len; | ||
183 | } | ||
184 | |||
185 | |||
186 | int huff_enc_read_byte() | ||
187 | { | ||
188 | return huff_enc_plaintext[huff_enc_input_pos++]; | ||
189 | } | ||
190 | |||
191 | |||
192 | void huff_enc_write_byte( char ch ) | ||
193 | { | ||
194 | huff_enc_output[huff_enc_output_pos++] = ch; | ||
195 | } | ||
196 | |||
197 | |||
198 | void huff_enc_write_bin_val( huff_enc_t_bin_val bin_val ) | ||
199 | /* Returned parameters: None | ||
200 | Action: Writes in the output stream the value binary-coded into 'bin_val' | ||
201 | Errors: An input/output error could disturb the running of the program | ||
202 | */ | ||
203 | { | ||
204 | unsigned char bit_indice; | ||
205 | unsigned char bin_pos = ( bin_val.bits_nb - 1 ) & 7; | ||
206 | unsigned int pos_byte = ( bin_val.bits_nb - 1 ) >> 3; | ||
207 | |||
208 | for ( bit_indice = 1; | ||
209 | bit_indice <= bin_val.bits_nb; | ||
210 | bit_indice++ ) { | ||
211 | /* Watch for the current bit to write */ | ||
212 | huff_enc_val_to_write = ( huff_enc_val_to_write << 1 ) | | ||
213 | ( ( bin_val.bits[pos_byte] >> bin_pos ) & 1 ); | ||
214 | /* Move to the next bit to write */ | ||
215 | if ( !bin_pos ) { | ||
216 | pos_byte--; | ||
217 | bin_pos = 7; | ||
218 | } else bin_pos--; | ||
219 | if ( huff_enc_byte_nb_to_write == 7 ) { | ||
220 | /* Are already 8 bits written? */ | ||
221 | huff_enc_write_byte( huff_enc_val_to_write ); | ||
222 | huff_enc_byte_nb_to_write = 0; | ||
223 | huff_enc_val_to_write = 0; | ||
224 | } else /* No, then the next writting will be in the next bit */ | ||
225 | huff_enc_byte_nb_to_write++; | ||
226 | } | ||
227 | } | ||
228 | |||
229 | |||
230 | void huff_enc_fill_encoding( void ) | ||
231 | /* Returned parameters: None | ||
232 | Action: Fills the last byte to write in the output stream with zero values | ||
233 | Errors: An input/output error could disturb the running of the program | ||
234 | */ | ||
235 | { | ||
236 | if ( huff_enc_byte_nb_to_write ) | ||
237 | huff_enc_write_byte( huff_enc_val_to_write << | ||
238 | ( 8 - huff_enc_byte_nb_to_write ) ); | ||
239 | } | ||
240 | |||
241 | |||
242 | void huff_enc_write_header( huff_enc_t_bin_val codes_table[257] ) | ||
243 | /* Returned parameters: None | ||
244 | Action: Writes the header in the stream of codes | ||
245 | Errors: An input/output error could disturb the running of the program | ||
246 | */ | ||
247 | { | ||
248 | unsigned int i, j; | ||
249 | huff_enc_t_bin_val bin_val_to_0; | ||
250 | huff_enc_t_bin_val bin_val_to_1; | ||
251 | huff_enc_t_bin_val bin_val; | ||
252 | /* Is used to send in binary mode via huff_enc_write_bin_val */ | ||
253 | |||
254 | *bin_val_to_0.bits = 0; | ||
255 | bin_val_to_0.bits_nb = 1; | ||
256 | *bin_val_to_1.bits = 1; | ||
257 | bin_val_to_1.bits_nb = 1; | ||
258 | for ( i = 0, j = 0; j <= 255; j++ ) | ||
259 | if ( codes_table[j].bits_nb ) i++; | ||
260 | /* From there, i contains the number of bytes of the several | ||
261 | non 0 occurrences to encode. | ||
262 | First part of the header: Specifies the bytes that appear | ||
263 | in the source of encoding */ | ||
264 | if ( i < 32 ) { | ||
265 | /* Encoding of the appeared bytes with a block of bytes */ | ||
266 | huff_enc_write_bin_val( bin_val_to_0 ); | ||
267 | bin_val.bits_nb = 5; | ||
268 | *bin_val.bits = ( unsigned char )( i - 1 ); | ||
269 | huff_enc_write_bin_val( bin_val ); | ||
270 | bin_val.bits_nb = 8; | ||
271 | for ( j = 0; j <= 255; j++ ) | ||
272 | if ( codes_table[j].bits_nb ) { | ||
273 | *bin_val.bits = ( unsigned char )j; | ||
274 | huff_enc_write_bin_val( bin_val ); | ||
275 | } | ||
276 | } else { | ||
277 | /* Encoding of the appeared bytes with a block of bits */ | ||
278 | huff_enc_write_bin_val( bin_val_to_1 ); | ||
279 | for ( j = 0; j <= 255; j++ ) | ||
280 | if ( codes_table[j].bits_nb ) | ||
281 | huff_enc_write_bin_val( bin_val_to_1 ); | ||
282 | else huff_enc_write_bin_val( bin_val_to_0 ); | ||
283 | }; | ||
284 | /* Second part of the header: Specifies the encoding of the bytes | ||
285 | (fictive or not) that appear in the source of encoding */ | ||
286 | for ( i = 0; i <= 256; i++ ) | ||
287 | if ( ( j = codes_table[i].bits_nb ) != 0 ) { | ||
288 | if ( j < 33 ) { | ||
289 | huff_enc_write_bin_val( bin_val_to_0 ); | ||
290 | bin_val.bits_nb = 5; | ||
291 | } else { | ||
292 | huff_enc_write_bin_val( bin_val_to_1 ); | ||
293 | bin_val.bits_nb = 8; | ||
294 | } | ||
295 | *bin_val.bits = ( unsigned char )( j - 1 ); | ||
296 | huff_enc_write_bin_val( bin_val ); | ||
297 | huff_enc_write_bin_val( codes_table[i] ); | ||
298 | } | ||
299 | } | ||
300 | |||
301 | |||
302 | int huff_enc_weighhuff_enc_t_tree_comp( const void *t1, const void *t2 ) | ||
303 | /* Returned parameters: Returns a comparison status | ||
304 | Action: Returns a negative, zero or positive integer depending on the weight | ||
305 | of 'tree2' is less than, equal to, or greater than the weight of | ||
306 | 'tree1' | ||
307 | Errors: None | ||
308 | */ | ||
309 | { | ||
310 | huff_enc_t_tree *const *tree1 = ( huff_enc_t_tree *const * ) t1; | ||
311 | huff_enc_t_tree *const *tree2 = ( huff_enc_t_tree *const * ) t2; | ||
312 | return ( ( *tree2 )->weight ^ ( *tree1 )->weight ) | ||
313 | ? ( ( ( *tree2 )->weight < ( *tree1 )->weight ) ? -1 : 1 ) : 0; | ||
314 | } | ||
315 | |||
316 | |||
317 | void huff_enc_swapi( char *ii, char *ij, unsigned long es ) | ||
318 | { | ||
319 | char *i, *j, c; | ||
320 | |||
321 | i = ( char * )ii; | ||
322 | j = ( char * )ij; | ||
323 | _Pragma( "loopbound min 4 max 4" ) | ||
324 | do { | ||
325 | c = *i; | ||
326 | *i++ = *j; | ||
327 | *j++ = c; | ||
328 | es -= sizeof( char ); | ||
329 | } while ( es != 0 ); | ||
330 | } | ||
331 | |||
332 | |||
333 | char *huff_enc_pivot( char *a, unsigned long n, unsigned long es ) | ||
334 | { | ||
335 | long j; | ||
336 | char *pi, *pj, *pk; | ||
337 | |||
338 | j = n / 6 * es; | ||
339 | pi = a + j; /* 1/6 */ | ||
340 | j += j; | ||
341 | pj = pi + j; /* 1/2 */ | ||
342 | pk = pj + j; /* 5/6 */ | ||
343 | if ( huff_enc_weighhuff_enc_t_tree_comp( pi, pj ) < 0 ) { | ||
344 | if ( huff_enc_weighhuff_enc_t_tree_comp( pi, pk ) < 0 ) { | ||
345 | if ( huff_enc_weighhuff_enc_t_tree_comp( pj, pk ) < 0 ) | ||
346 | return pj; | ||
347 | return pk; | ||
348 | } | ||
349 | return pi; | ||
350 | } | ||
351 | if ( huff_enc_weighhuff_enc_t_tree_comp( pj, pk ) < 0 ) { | ||
352 | if ( huff_enc_weighhuff_enc_t_tree_comp( pi, pk ) < 0 ) | ||
353 | return pi; | ||
354 | return pk; | ||
355 | } | ||
356 | return pj; | ||
357 | } | ||
358 | |||
359 | |||
360 | void huff_enc_qsort( char *a, unsigned long n, unsigned long es ) | ||
361 | { | ||
362 | unsigned long j; | ||
363 | char *pi, *pj, *pn; | ||
364 | unsigned int flowfactdummy = 0; | ||
365 | |||
366 | _Pragma( "loopbound min 0 max 8" ) | ||
367 | while ( n > 1 ) { | ||
368 | if ( n > 10 ) { | ||
369 | pi = huff_enc_pivot( a, n, es ); | ||
370 | } else { | ||
371 | pi = a + ( n >> 1 ) * es; | ||
372 | } | ||
373 | |||
374 | huff_enc_swapi( a, pi, es ); | ||
375 | pi = a; | ||
376 | pn = a + n * es; | ||
377 | pj = pn; | ||
378 | _Pragma( "loopbound min 1 max 110" ) | ||
379 | while ( 1 ) { | ||
380 | /* wcc note: this assignment expression was added to avoid assignment of | ||
381 | * multiple loop bound annotations to same loop (cf. Ticket #0002323). */ | ||
382 | flowfactdummy++; | ||
383 | _Pragma( "loopbound min 1 max 19" ) | ||
384 | do { | ||
385 | pi += es; | ||
386 | } while ( pi < pn && huff_enc_weighhuff_enc_t_tree_comp( pi, a ) < 0 ); | ||
387 | _Pragma( "loopbound min 1 max 25" ) | ||
388 | do { | ||
389 | pj -= es; | ||
390 | } while ( pj > a && huff_enc_weighhuff_enc_t_tree_comp( pj, a ) > 0 ); | ||
391 | if ( pj < pi ) | ||
392 | break; | ||
393 | huff_enc_swapi( pi, pj, es ); | ||
394 | } | ||
395 | huff_enc_swapi( a, pj, es ); | ||
396 | j = ( pj - a ) / es; | ||
397 | |||
398 | n = n - j - 1; | ||
399 | if ( j >= n ) { | ||
400 | huff_enc_qsort( a, j, es ); | ||
401 | a += ( j + 1 ) * es; | ||
402 | } else { | ||
403 | huff_enc_qsort( a + ( j + 1 )*es, n, es ); | ||
404 | n = j; | ||
405 | } | ||
406 | } | ||
407 | } | ||
408 | |||
409 | |||
410 | huff_enc_t_tree *huff_enc_build_tree_encoding( huff_enc_t_tree heap[514] ) | ||
411 | /* Returned parameters: Returns a tree of encoding | ||
412 | Action: Generates an Huffman encoding tree based on the data from | ||
413 | the stream to compress | ||
414 | Errors: None | ||
415 | */ | ||
416 | { | ||
417 | unsigned int i; | ||
418 | unsigned int heap_top = 0; | ||
419 | huff_enc_t_tree *occurrences_table[257]; | ||
420 | huff_enc_t_tree *ptr_fictive_tree; | ||
421 | |||
422 | /* Sets up the occurrences number of all bytes to 0 */ | ||
423 | for ( i = 0; i <= 256; i++ ) { | ||
424 | occurrences_table[i] = &heap[heap_top++]; | ||
425 | occurrences_table[i]->byte = i; | ||
426 | occurrences_table[i]->weight = 0; | ||
427 | occurrences_table[i]->left_ptr = 0; | ||
428 | occurrences_table[i]->right_ptr = 0; | ||
429 | } | ||
430 | /* Valids the occurrences of 'occurrences_table' with regard to the data to | ||
431 | compress */ | ||
432 | if ( !huff_enc_end_of_data() ) { | ||
433 | while ( !huff_enc_end_of_data() ) { | ||
434 | i = huff_enc_read_byte(); | ||
435 | occurrences_table[i]->weight++; | ||
436 | } | ||
437 | occurrences_table[256]->weight = 1; | ||
438 | |||
439 | /* Sorts the occurrences table depending on the weight of each character */ | ||
440 | huff_enc_qsort( ( char * )occurrences_table, 257, sizeof( huff_enc_t_tree * ) ); | ||
441 | |||
442 | for ( i = 256; ( i != 0 ) && ( !occurrences_table[i]->weight ); i-- ) | ||
443 | ; | ||
444 | i++; | ||
445 | /* From there, 'i' gives the number of different bytes with a 0 occurrence | ||
446 | in the stream to compress */ | ||
447 | while ( i > 0 ) { | ||
448 | /* Looks up (i+1)/2 times the occurrence table to link the nodes in an | ||
449 | unique tree */ | ||
450 | ptr_fictive_tree = &heap[heap_top++]; | ||
451 | ptr_fictive_tree->byte = 257; | ||
452 | ptr_fictive_tree->weight = occurrences_table[--i]->weight; | ||
453 | ptr_fictive_tree->left_ptr = occurrences_table[i]; | ||
454 | if ( i ) { | ||
455 | i--; | ||
456 | ptr_fictive_tree->weight += occurrences_table[i]->weight; | ||
457 | ptr_fictive_tree->right_ptr = occurrences_table[i]; | ||
458 | } else ptr_fictive_tree->right_ptr = 0; | ||
459 | occurrences_table[i] = ptr_fictive_tree; | ||
460 | |||
461 | //qsort( ( char * )occurrences_table, i + 1, sizeof( *huff_enc_t_tree ), | ||
462 | //huff_enc_weighhuff_enc_t_tree_comp ); | ||
463 | huff_enc_qsort( ( char * )occurrences_table, i + 1, | ||
464 | sizeof( huff_enc_t_tree * ) ); | ||
465 | |||
466 | if ( i ) /* Is there an other node in the occurrence tables? */ | ||
467 | i++; /* Yes, then takes care to the fictive node */ | ||
468 | } | ||
469 | } | ||
470 | return ( *occurrences_table ); | ||
471 | } | ||
472 | |||
473 | |||
474 | void huff_enc_encode_codes_table( huff_enc_t_tree *tree, | ||
475 | huff_enc_t_bin_val codes_table[257], | ||
476 | huff_enc_t_bin_val *code_val ) | ||
477 | /* Returned parameters: The data of 'codes_table' can have been modified | ||
478 | Action: Stores the encoding tree as a binary encoding table to speed up the | ||
479 | access. 'val_code' gives the encoding for the current node of the tree | ||
480 | Errors: None | ||
481 | */ | ||
482 | { | ||
483 | unsigned int i; | ||
484 | huff_enc_t_bin_val tmp_code_val; | ||
485 | |||
486 | if ( tree->byte == 257 ) { | ||
487 | if ( tree->left_ptr != 0 ) | ||
488 | /* The sub-trees on left begin with an bit set to 1 */ | ||
489 | { | ||
490 | tmp_code_val = *code_val; | ||
491 | for ( i = 31; i > 0; i-- ) | ||
492 | code_val->bits[i] = ( code_val->bits[i] << 1 ) | | ||
493 | ( code_val->bits[i - 1] >> 7 ); | ||
494 | *code_val->bits = ( *code_val->bits << 1 ) | 1; | ||
495 | code_val->bits_nb++; | ||
496 | huff_enc_encode_codes_table( tree->left_ptr, codes_table, code_val ); | ||
497 | *code_val = tmp_code_val; | ||
498 | }; | ||
499 | if ( tree->right_ptr != 0 ) | ||
500 | /* The sub-trees on right begin with an bit set to 0 */ | ||
501 | { | ||
502 | tmp_code_val = *code_val; | ||
503 | for ( i = 31; i > 0; i-- ) | ||
504 | code_val->bits[i] = ( code_val->bits[i] << 1 ) | | ||
505 | ( code_val->bits[i - 1] >> 7 ); | ||
506 | *code_val->bits <<= 1; | ||
507 | code_val->bits_nb++; | ||
508 | huff_enc_encode_codes_table( tree->right_ptr, codes_table, code_val ); | ||
509 | *code_val = tmp_code_val; | ||
510 | }; | ||
511 | } else codes_table[tree->byte] = *code_val; | ||
512 | } | ||
513 | |||
514 | |||
515 | void huff_enc_create_codes_table( huff_enc_t_tree *tree, | ||
516 | huff_enc_t_bin_val codes_table[257] ) | ||
517 | /* Returned parameters: The data in 'codes_table' will be modified | ||
518 | Action: Stores the encoding tree as a binary encoding table to speed up | ||
519 | the access by calling encode_codes_table | ||
520 | Errors: None | ||
521 | */ | ||
522 | { | ||
523 | unsigned int i, j; | ||
524 | huff_enc_t_bin_val code_val; | ||
525 | |||
526 | _Pragma( "loopbound min 32 max 32" ) | ||
527 | for ( i = 0; i < 32; i++ ) { | ||
528 | code_val.bits[i] = 0; | ||
529 | } | ||
530 | code_val.bits_nb = 0; | ||
531 | _Pragma( "loopbound min 257 max 257" ) | ||
532 | for ( j = 0; j < 257; j++ ) { | ||
533 | _Pragma( "loopbound min 32 max 32" ) | ||
534 | for ( i = 0; i < 32; i++ ) { | ||
535 | codes_table[j].bits[i] = 0; | ||
536 | } | ||
537 | codes_table[j].bits_nb = 0; | ||
538 | } | ||
539 | _Pragma( "marker call_encode" ) | ||
540 | _Pragma( "flowrestriction 1*huff_enc_encode_codes_table <= 77*call_encode" ) | ||
541 | huff_enc_encode_codes_table( tree, codes_table, &code_val ); | ||
542 | } | ||
543 | |||
544 | |||
545 | void _Pragma( "entrypoint" ) huff_enc_main() | ||
546 | /* Returned parameters: None | ||
547 | Action: Compresses with Huffman method all bytes read by the function | ||
548 | 'huff_enc_read_byte' | ||
549 | Errors: None | ||
550 | */ | ||
551 | { | ||
552 | huff_enc_t_tree *tree; | ||
553 | huff_enc_t_tree heap[514]; | ||
554 | huff_enc_t_bin_val encoding_table[257]; | ||
555 | unsigned char byte_read; | ||
556 | |||
557 | if ( !huff_enc_end_of_data() ) { | ||
558 | /* Generates only whether there are data */ | ||
559 | tree = huff_enc_build_tree_encoding( heap ); | ||
560 | /* Creation of the best adapted tree */ | ||
561 | huff_enc_create_codes_table( tree, encoding_table ); | ||
562 | /* Obtains the binary encoding in an array to speed up the accesses */ | ||
563 | huff_enc_write_header( encoding_table ); | ||
564 | /* Writes the defintion of the encoding */ | ||
565 | huff_enc_beginning_of_data(); /* Real compression of the data */ | ||
566 | while ( !huff_enc_end_of_data() ) { | ||
567 | byte_read = huff_enc_read_byte(); | ||
568 | huff_enc_write_bin_val( encoding_table[byte_read] ); | ||
569 | } | ||
570 | huff_enc_write_bin_val( encoding_table[256] ); | ||
571 | /* Code of the end of encoding */ | ||
572 | huff_enc_fill_encoding(); | ||
573 | /* Fills the last byte before closing file, if any */ | ||
574 | } | ||
575 | } | ||
576 | |||
577 | |||
578 | int main( int argc, char **argv ) | ||
579 | { | ||
580 | SET_UP | ||
581 | for (jobsComplete=-1; jobsComplete<maxJobs; jobsComplete++){ | ||
582 | START_LOOP | ||
583 | huff_enc_init(); | ||
584 | huff_enc_main(); | ||
585 | STOP_LOOP | ||
586 | } | ||
587 | WRITE_TO_FILE | ||
588 | return ( huff_enc_return() ); | ||
589 | } | ||