Fix signedness warnings.
[fjl] / unjpeg.c
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 struct huffman_table {
5         unsigned num_codes[17];     /* BITS */
6         unsigned char codes[256];   /* HUFFVAL */
7         
8         /* derived values */
9         unsigned huffsize[256];
10         unsigned huffcode[256];
11         int maxcode[16];
12         int mincode[16];
13         unsigned valptr[16];
14 };
15 struct huffman_table huffman_tables[2][4];
16
17 struct mem_stream {
18         unsigned char *buf;
19         unsigned used, room;
20 };
21 struct mem_stream streams[128];
22 char huge[1048576 * 100];
23 int num_huge = 0;
24
25 void *xmalloc(size_t size)
26 {
27         void *buf = malloc(size);
28         if (buf == NULL) {
29                 perror("malloc");
30                 exit(1);
31         }
32
33         return buf;
34 }
35         
36 static int numch = 0;
37
38 unsigned char mygetc()
39 {
40         int ch = getchar();
41         ++numch;
42         if (ch == EOF) {
43                 if (feof(stdin)) {
44                         fprintf(stderr, "Error: Unexpected end of file.\n");
45                         exit(1);
46                 } else {
47                         perror("getchar()");
48                         exit(1);
49                 }
50         }
51
52         return ((unsigned char)ch);
53 }
54
55 void putchar_stream(int stream, unsigned char ch)
56 {
57         int used = streams[stream].used;
58
59         if (streams[stream].used == streams[stream].room) {
60                 streams[stream].room <<= 1;
61                 streams[stream].buf = (unsigned char *)realloc(streams[stream].buf, streams[stream].room);
62         }
63
64         streams[stream].buf[streams[stream].used++] = ch;
65 }
66
67 void flush_stream(int stream)
68 {
69         fwrite(streams[stream].buf, streams[stream].used, 1, stdout);
70         streams[stream].used = 0;
71 }
72
73 unsigned char mygetc_limit(unsigned *len)
74 {
75         if (*len == 0) {
76                 fprintf(stderr, "Error: Premature end of segment\n");
77                 exit(1);
78         }
79         --*len;
80         return mygetc();
81 }
82         
83 unsigned read_length()
84 {
85         unsigned char len1 = mygetc();
86         unsigned char len2 = mygetc();
87         unsigned len = (len1 << 8) | len2;
88
89         if (len < 2) {
90                 fprintf(stderr, "Error: Got length %u, expected at least 2\n", len);
91                 exit(1);
92         }
93
94         return len;
95 }
96                         
97 void copy_segment(unsigned char marker_code)
98 {
99         unsigned len = read_length();
100         unsigned i;
101
102         /* marker segment header */
103         putchar(0xff);
104         putchar(marker_code);
105         putchar(len >> 8);
106         putchar(len & 0xff);
107
108         for (i = 0; i < len - 2; ++i) {
109                 putchar(mygetc());
110         }
111 }
112
113 void read_huffman_tables()
114 {
115         unsigned len = read_length() - 2;
116
117         putchar(0xff);
118         putchar(0xda);
119         putchar(len >> 8);
120         putchar(len & 0xff);
121
122         for ( ;; ) {
123                 unsigned char tc_th = mygetc_limit(&len);
124                 unsigned table_class = tc_th >> 4;
125                 unsigned table_dest = tc_th & 0x0f;
126                 unsigned i, j, k, si;
127                 struct huffman_table *tbl;
128
129                 if (table_class != 0 && table_class != 1) {
130                         fprintf(stderr, "Error: Unknown table class %u\n", table_class);
131                         exit(1);
132                 }
133                 if (table_dest >= 4) {
134                         fprintf(stderr, "Error: Unknown table destination %u\n", table_dest);
135                         exit(1);
136                 }
137
138                 putchar(tc_th);
139                 tbl = &huffman_tables[table_class][table_dest];
140
141                 for (i = 0; i < 16; ++i) {
142                         tbl->num_codes[i] = mygetc_limit(&len);
143                         putchar(tbl->num_codes[i]);
144                         fprintf(stderr, "%u ", tbl->num_codes[i]);
145                 }
146                 fprintf(stderr, "\ndumping tc=%u td=%u\n", table_class, table_dest);
147                 for (i = 0, k = 0; i < 16; ++i) {
148                         for (j = 0; j < tbl->num_codes[i]; ++j, ++k) {
149                                 tbl->codes[k] = mygetc_limit(&len);
150                                 putchar(tbl->codes[k]);
151                                 fprintf(stderr, "%u: len=%u, ind=%u: code=0x%02x\n", k, i+1, j, tbl->codes[k]);
152                         }
153                 }
154
155                 /* generate derived tables */
156
157                 /* generate_size_table (figure C.1) */
158                 k = 0;
159                 for (i = 0; i < 16; ++i) {
160                         for (j = 0; j < tbl->num_codes[i]; ++j, ++k) {
161                                 tbl->huffsize[k] = i+1;
162                         }
163                 }
164                 tbl->huffsize[k] = 0;
165                 fprintf(stderr, "k=%u\n", k);
166
167                 /* generate_code_table (figure C.2) */
168                 si = tbl->huffsize[0];
169                 for (i = 0, j = 0;; ) {
170                         fprintf(stderr, "%u = %u [si=%u]\n", i, j, si);
171
172                         tbl->huffcode[i++] = j++;
173                         if (tbl->huffsize[i] == si) {
174                                 continue;
175                         }
176
177                         if (tbl->huffsize[i] == 0) {
178                                 break;
179                         }
180
181                         do {
182                                 j <<= 1;
183                         } while (++si != tbl->huffsize[i]);
184                 }
185
186                 /* decoder_tables (figure F.15) */
187                 for (i = 0, j = 0; i < 16; ++i) {
188                         if (tbl->num_codes[i] == 0) {
189                                 tbl->maxcode[i] = -1;
190                                 continue;
191                         }
192
193                         tbl->valptr[i] = j;
194                         //fprintf(stderr, "minind=%u\n", j);
195                         tbl->mincode[i] = tbl->huffcode[j];
196                         j += tbl->num_codes[i];
197                         //fprintf(stderr, "maxind=%u\n", j-1);
198                         tbl->maxcode[i] = tbl->huffcode[j - 1];
199
200                         //fprintf(stderr, "%u: min=%u, max=%u\n", i, tbl->mincode[i], tbl->maxcode[i]);
201                 }
202
203                 if (len == 0) {
204                         break;
205                 }
206         }
207 }
208
209 /* procedure NEXTBIT */
210 unsigned get_bit(unsigned *bits_available, unsigned char *bit_reservoir)
211 {
212         unsigned bit;
213
214         if (*bits_available == 0) {
215                 *bit_reservoir = mygetc();
216                 //fprintf(stderr, "Read byte (0x%02x)\n", *bit_reservoir);
217                 if (*bit_reservoir == 0xff) {
218                         unsigned char ch = mygetc();
219                         if (ch != 0) {
220                                 int i;
221                                 for (i = 0; i < 128; ++i) {
222                                         flush_stream(i);
223                                 }
224
225                                 fprintf(stderr, "Error: Couldn't handle marker 0x%02x\n", ch);
226                                 exit(1);
227                         }
228                         //fprintf(stderr, "Read stuff byte (%u)\n", ch);
229                 }
230
231                 *bits_available = 8;
232         }
233
234         bit = *bit_reservoir >> 7;
235         *bit_reservoir = (*bit_reservoir & 0x7f) << 1;
236         --*bits_available;
237
238         //fprintf(stderr, "%u\n", bit);
239
240         return bit;
241 }
242
243 /* procedure DECODE (figure F.16) */
244 unsigned char get_huffman_byte(unsigned *bits_available, unsigned char *bit_reservoir, struct huffman_table* huff_tbl)
245 {
246         unsigned code = get_bit(bits_available, bit_reservoir);
247         int i = 1;
248
249         while (code > huff_tbl->maxcode[i - 1] || huff_tbl->maxcode[i - 1] == -1) {
250                 code = (code << 1) | get_bit(bits_available, bit_reservoir);
251                 ++i;
252
253                 if (i > 16) {
254                         fprintf(stderr, "Error in Huffman decoding: Too long code (%x).numch=%u\n", code, numch);
255                         exit(1);
256                 }
257         }
258
259         /*fprintf(stderr, "h=%d => code=0x%02x\n", huff_tbl->valptr[i - 1] + code - huff_tbl->mincode[i - 1],
260                 huff_tbl->codes[huff_tbl->valptr[i - 1] + code - huff_tbl->mincode[i - 1]]);*/
261         return huff_tbl->codes[huff_tbl->valptr[i - 1] + code - huff_tbl->mincode[i - 1]];
262 }
263                         
264 /* procedure RECEIVE */
265 unsigned get_bits(unsigned num_bits, unsigned *bits_available, unsigned char *bit_reservoir)
266 {
267         unsigned val = 0, i;
268
269         for (i = 0; i < num_bits; ++i) {
270                 val <<= 1;
271                 val |= get_bit(bits_available, bit_reservoir);
272         }
273
274         return val;
275 }
276
277 /* procedure EXTEND (figure F.12) */
278 unsigned extend(int val, int bits)
279 {
280         if (val < (1 << (bits - 1))) {
281                 return val + (-1 << bits) + 1;
282         } else {
283                 return val;
284         }
285 }
286
287 void read_scan()
288 {
289         unsigned len = read_length() - 2;
290         unsigned bits_available;
291         unsigned char bit_reservoir;
292         unsigned num_components = mygetc_limit(&len);
293         unsigned i;
294         unsigned component_num[256];
295         unsigned dc_huffman_table[256], ac_huffman_table[256];
296         unsigned ss, se, ah_al;
297         int last_dc[256];
298         int last_ac[256];
299
300         for (i = 0; i < num_components; ++i) {
301                 unsigned char td_ta;
302                 component_num[i] = mygetc_limit(&len);
303                 td_ta = mygetc_limit(&len);
304                 dc_huffman_table[i] = td_ta >> 4;
305                 ac_huffman_table[i] = td_ta & 0x0f;
306                 last_dc[i] = 0;
307
308                 {
309                         unsigned j;
310                         for (j = 0; j < 64; ++j) {
311                                 last_ac[j] = 0;
312                         }
313                 }
314         }
315
316         ss = mygetc_limit(&len); 
317         se = mygetc_limit(&len); 
318         ah_al = mygetc_limit(&len); 
319
320         if (len != 0) {
321                 fprintf(stderr, "Error: %u unused bytes at end of SOS segment\n", len);
322         }
323
324         bits_available = 0;
325
326         for ( ;; ) {
327                 //fprintf(stderr, "new scan, now\n");
328
329                 int c;
330                 for (c = 0; c < num_components; ++c) {
331                         int zz[63];
332                         //fprintf(stderr, "coeff %u\n", c);
333                         //fprintf(stderr, "getting dc (table %u)\n", dc_huffman_table[c]);
334
335                         /* decode DC component */
336                         unsigned char dc_category = get_huffman_byte(&bits_available, &bit_reservoir, &huffman_tables[0][dc_huffman_table[c]]);
337                         int dc_diff;
338                         int i;
339
340                         dc_diff = get_bits(dc_category, &bits_available, &bit_reservoir);
341                         last_dc[c] += extend(dc_diff, dc_category);
342
343                         /*putchar_stream(0, last_dc[c] >> 8);
344                         putchar_stream(0, last_dc[c] & 0xff);  */
345                         huge[num_huge++] = dc_diff >> 8;
346                         huge[num_huge++] = dc_diff & 0xff;
347                         
348                         for (i = 0; i < 63; ++i) {
349                                 zz[i] = 0;
350                         }
351                         
352                         for (i = 0; i < 63; ++i) {
353                                 unsigned char rs = get_huffman_byte(&bits_available, &bit_reservoir, &huffman_tables[1][ac_huffman_table[c]]);
354                                 unsigned char r = rs >> 4;
355                                 unsigned char s = rs & 0xf;
356
357                                 if (rs == 0x00) {
358                                         /* end of block */
359                                         break;
360                                 }
361                                 if (rs == 0xf0) {
362                                         /* 16 zero coefficients */
363                                         i += 15;
364                                         continue;
365                                 }
366
367                                 i += r;
368                                 zz[i] = extend(get_bits(s, &bits_available, &bit_reservoir), s);
369                         }
370                         
371                         for (i = 0; i < 63; ++i) {
372                                 int s = i;
373                                 if (s > 54) {
374                                         s = 54;
375                                 }
376
377                                 int m;
378                                 if (zz[i] >= 0) {
379                                         m = zz[i] * 2;
380                                 } else {
381                                         m = (1 - zz[i] * 2);
382                                 }
383                                 huge[num_huge++] = m >> 8;
384                                 huge[num_huge++] = m & 0xff;
385                         }
386                 }
387         }
388 }
389
390 int main(void)
391 {
392         int i;
393         for (i = 0; i < 128; ++i) {
394                 streams[i].buf = (unsigned char *)malloc(4096);
395                 streams[i].used = 0;
396                 streams[i].room = 4096;
397         }
398
399         for ( ;; ) {
400                 unsigned char m1 = mygetc();
401                 unsigned char m2 = mygetc();
402
403                 if (m1 != 0xff) {
404                         fprintf(stderr, "Error: Expected marker (0xff), got 0x%02x\n", m1);
405                         exit(1);
406                 }
407
408                 switch (m2) {
409                 case 0xe0:
410                 case 0xe1:
411                 case 0xe2:
412                 case 0xe3:
413                 case 0xe4:
414                 case 0xe5:
415                 case 0xe6:
416                 case 0xe7:
417                 case 0xe8:
418                 case 0xe9:
419                 case 0xea:
420                 case 0xeb:
421                 case 0xec:
422                 case 0xed:
423                 case 0xee:
424                 case 0xef:
425                         /* APP0 through APPF */
426                 case 0xdb:
427                         /* DQT */
428                 case 0xc0:
429                         /* SOF0 (baseline DCT, Huffman encoded) */
430                         copy_segment(m2);
431                         break;
432                 case 0xd8:
433                         /* SOI */
434                         putchar(m1);
435                         putchar(m2);
436                         break;
437                 case 0xc4:
438                         /* DHT (define Huffman tables) */
439                         read_huffman_tables();
440                         break;
441                 case 0xda:
442                         /* SOS (start of scan) */
443                         read_scan();
444                         break;
445                 default:
446                         fprintf(stderr, "Error: Unknown marker 0x%02x\n", m2);
447                         exit(1);
448                 }
449         }
450 }