Port some table-generating stuff from unjpeg.
[fjl] / dehuff.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <assert.h>
4
5 #include "dehuff.h"
6
7 void reliable_read(raw_input_func_t* input_func, void* userdata, uint8_t* buf, size_t len)
8 {
9         while (len > 0) {
10                 ssize_t bytes_read = input_func(userdata, buf, len);
11                 assert(bytes_read <= len);
12
13                 // TODO: We need better error handling here. setjmp()/longjmp()
14                 // should hopefully do the trick, but we need to take care for
15                 // suspension.
16                 if (bytes_read == (ssize_t)-1) {
17                         fprintf(stderr, "Input function returned error\n");
18                         exit(1);
19                 }
20                 if (bytes_read == 0) {
21                         fprintf(stderr, "Premature EOF\n");
22                         exit(1);
23                 }
24
25                 buf += bytes_read;
26                 len -= bytes_read;
27         }
28 }
29
30 uint16_t read_length(raw_input_func_t* input_func, void* userdata)
31 {
32         uint8_t buf[2];
33         reliable_read(input_func, userdata, buf, 2);
34         return (buf[0] << 8) | buf[1];
35 }
36
37 void read_huffman_tables(huffman_tables_t* dst, raw_input_func_t* input_func, void* userdata)
38 {
39         size_t len = read_length(input_func, userdata);
40         assert(len > 2);
41         len -= 2;
42
43         // TODO: check for NULL return
44         uint8_t* buf = (uint8_t*)malloc(len);
45         uint8_t* inptr = buf;
46         reliable_read(input_func, userdata, buf, len);
47         
48         while (len > 0) {
49                 unsigned char tc_th = *inptr++;
50                 --len;
51                 unsigned table_class = tc_th >> 4;
52                 unsigned table_dest = tc_th & 0x0f;
53                 
54                 if (table_class != 0 && table_class != 1) {
55                         fprintf(stderr, "Error: Unknown table class %u\n", table_class);
56                         exit(1);
57                 }
58                 if (table_dest >= 4) {
59                         fprintf(stderr, "Error: Unknown table destination %u\n", table_dest);
60                         exit(1);
61                 }
62
63                 struct huffman_table* tbl = dst[table_class][table_dest];
64                 if (len < 16) {
65                         fprintf(stderr, "Short read for num_codes\n");
66                         exit(1);
67                 }
68                 for (unsigned i = 0; i < 16; ++i) {
69                         tbl->num_codes[i] = *inptr++;
70                         --len;
71                 }
72                 for (unsigned i = 0, k = 0; i < 16; ++i) {
73                         if (len < tbl->num_codes[i]) {
74                                 fprintf(stderr, "Short read for codes\n");
75                                 exit(1);
76                         }
77                         for (unsigned j = 0; j < tbl->num_codes[i]; ++j, ++k) {
78                                 tbl->codes[k] = *inptr++;
79                                 --len;
80                         }
81                 }
82
83                 // Generate derived tables
84
85                 // generate_size_table (figure C.1)
86                 {
87                         unsigned k = 0;
88                         for (unsigned i = 0; i < 16; ++i) {
89                                 for (unsigned j = 0; j < tbl->num_codes[i]; ++j, ++k) {
90                                         tbl->huffsize[k] = i + 1;
91                                 }
92                         }
93                         tbl->huffsize[k] = 0;
94                 }
95
96                 // generate_code_table (figure C.2)
97                 unsigned si = tbl->huffsize[0];
98                 for (unsigned i = 0, j = 0;; ) {
99                         tbl->huffcode[i++] = j++;
100                         if (tbl->huffsize[i] == si) {
101                                 continue;
102                         }
103                         if (tbl->huffsize[i] == 0) {
104                                 break;
105                         }
106
107                         do {
108                                 j <<= 1;
109                         } while (++si != tbl->huffsize[i]);
110                 }
111
112                 // decoder_tables (figure F.15)
113                 for (unsigned i = 0, j = 0; i < 16; ++i) {
114                         if (tbl->num_codes[i] == 0) {
115                                 tbl->maxcode[i] = -1;
116                                 continue;
117                         }
118
119                         tbl->valptr[i] = j;
120                         tbl->mincode[i] = tbl->huffcode[j];
121                         j += tbl->num_codes[i];
122                         tbl->maxcode[i] = tbl->huffcode[j - 1];
123                 }
124         }
125
126         free(buf);
127 }