]> git.sesse.net Git - fjl/blob - driver.c
bbc569e5d143e1b41c35b460f53f1b1c25721863
[fjl] / driver.c
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 #include "bytesource.h"
5 #include "choice.h"
6 #include "dehuff.h"
7 #include "input.h"
8 #include "zigzag.h"
9
10 struct jpeg_image {
11         unsigned precision;
12         unsigned width, height;
13         unsigned num_components;
14         unsigned hsample[256], vsample[256], qtable[256];
15         uint32_t qvalues[256][DCTSIZE2];
16 };
17
18 ssize_t stdio_read(void* userdata, uint8_t* buf, size_t count) 
19 {
20         return fread(buf, 1, count, (FILE*)userdata);
21 }
22
23 void read_dqt(struct byte_source* source, struct jpeg_image* image)
24 {
25         unsigned len = read_uint16(byte_source_input_func, source);
26         assert(len >= 67);
27         uint8_t precision_table = read_uint8(byte_source_input_func, source);
28         int precision = precision_table >> 4;  // 0 = 8 bits, otherwise 16 bits.
29         int table = precision_table & 0x0f;
30
31         if (precision != 0) {
32                 assert(len == 131);
33                 fprintf(stderr, "Quantization table %u: 16 bits/entry\n", table);
34         } else {
35                 assert(len == 67);
36                 fprintf(stderr, "Quantization table %u: 8 bits/entry\n", table);
37         }
38         
39         for (unsigned i = 0; i < 64; ++i) {
40                 if (precision != 0) {
41                         image->qvalues[table][unzigzag[i]] =
42                                 read_uint16(byte_source_input_func, source);
43                 } else {
44                         image->qvalues[table][unzigzag[i]] =
45                                 read_uint8(byte_source_input_func, source);
46                 }       
47         }
48 }
49
50 void read_sof(struct byte_source* source, struct jpeg_image* image)
51 {
52         unsigned len = read_uint16(byte_source_input_func, source);
53         assert(len >= 8);
54         image->precision = read_uint8(byte_source_input_func, source);
55         assert(image->precision == 8);
56         image->width = read_uint16(byte_source_input_func, source);
57         image->height = read_uint16(byte_source_input_func, source);
58         image->num_components = read_uint8(byte_source_input_func, source);
59         len -= 8;
60
61         fprintf(stderr, "%u-bit %ux%u JPEG with %u components\n",
62                 image->precision, image->width, image->height, image->num_components);
63
64         for (unsigned i = 0; i < image->num_components; ++i) {
65                 assert(len >= 3);
66                 unsigned c = read_uint8(byte_source_input_func, source);
67                 unsigned sampling_factors = read_uint8(byte_source_input_func, source);
68                 image->hsample[c] = sampling_factors >> 4;
69                 image->vsample[c] = sampling_factors & 0x0f;
70                 image->qtable[c] = read_uint8(byte_source_input_func, source);
71                 len -= 3;
72
73                 fprintf(stderr, "Component %u: sampling factors %u x %x, quantization table %u\n",
74                         c, image->hsample[c], image->vsample[c], image->qtable[c]);
75         }
76 }
77
78 void read_scan(struct byte_source* source, struct jpeg_image* image, huffman_tables_t* tables)
79 {
80         unsigned len = read_uint16(byte_source_input_func, source);
81         assert(len >= 2);
82         len -= 2;
83
84         assert(len >= 1);
85         unsigned num_components = read_uint8(byte_source_input_func, source);
86         --len;
87
88         unsigned component_num[256];
89         unsigned dc_huffman_table[256], ac_huffman_table[256];
90         unsigned ss, se, ah_al;
91         int last_dc[256];
92
93         for (unsigned i = 0; i < num_components; ++i) {
94                 unsigned char td_ta;
95                 assert(len >= 2);
96                 component_num[i] = read_uint8(byte_source_input_func, source);
97                 td_ta = read_uint8(byte_source_input_func, source);
98                 len -= 2;
99                 dc_huffman_table[i] = td_ta >> 4;
100                 ac_huffman_table[i] = td_ta & 0x0f;
101                 last_dc[i] = 0;
102         }
103
104         assert(len >= 3);
105         ss = read_uint8(byte_source_input_func, source);
106         se = read_uint8(byte_source_input_func, source);
107         ah_al = read_uint8(byte_source_input_func, source);
108         len -= 3;
109
110         if (len != 0) {
111                 fprintf(stderr, "Error: %u unused bytes at end of SOS segment\n", len);
112         }
113
114         struct bit_source bits;
115         init_bit_source(&bits, byte_source_input_func, source);
116
117         for ( ;; ) {
118                 for (unsigned c = 0; c < num_components; ++c) {
119                         unsigned cn = component_num[c];
120                         unsigned nc = image->vsample[cn] * image->hsample[cn];
121                         for (unsigned n = 0; n < nc; ++n) {
122                                 const struct huffman_table* dc_table = &((*tables)[DC_CLASS][dc_huffman_table[c]]);
123                                 const struct huffman_table* ac_table = &((*tables)[AC_CLASS][ac_huffman_table[c]]);
124
125                                 // decode DC component
126                                 unsigned dc_category = read_huffman_symbol(dc_table, &bits);
127                                 possibly_refill(&bits, dc_category);
128                                 last_dc[c] += extend(read_bits(&bits, dc_category), dc_category);
129
130                 //              printf("dc=%d ac=", last_dc[c]);
131                                 putchar(last_dc[c]);
132
133                                 // decode AC components
134                                 int zz[63] = { 0 };
135                                 for (unsigned i = 0; i < 63; ++i) {
136                                         unsigned rs = read_huffman_symbol(ac_table, &bits);
137                                         unsigned r = rs >> 4;
138                                         unsigned s = rs & 0xf;
139
140                                         if (rs == 0x00) {
141                                                 /* end of block */
142                                                 break;
143                                         }
144                                         if (rs == 0xf0) {
145                                                 /* 16 zero coefficients */
146                                                 i += 15;
147                                                 continue;
148                                         }
149
150                                         possibly_refill(&bits, s);
151
152                                         i += r;
153                                         zz[unzigzag[i]] = extend(read_bits(&bits, s), s);
154                                 }
155                                 
156                                 for (unsigned i = 0; i < 63; ++i) {
157                                         putchar(zz[i]);
158                                         //printf("%d ", zz[i]);
159                                 }
160                                 //printf("\n");
161                         }
162                 }
163         }
164         if (len != 0) {
165                 fprintf(stderr, "Error: %u unused bytes at end of SOS segment\n", len);
166         }
167 }
168                         
169 void skip_segment(struct byte_source* source)
170 {
171         uint8_t buf[4096];
172         for ( ;; ) {
173                 ssize_t ret = byte_source_input_func(source, buf, 4096);
174                 if (ret == -1) {
175                         fprintf(stderr, "Input error!\n");
176                         exit(1);
177                 }
178                 if (ret == 0) {
179                         return;
180                 }
181         }
182 }
183         
184 int main(void)
185 {
186         struct jpeg_image jpeg;
187         init_choices();
188
189         struct byte_source source;
190         init_byte_source(&source, stdio_read, stdin);
191
192         huffman_tables_t tables;
193
194         for ( ;; ) {
195                 uint8_t m2 = byte_source_read_marker(&source);
196                 assert(m2 != 0x00);
197
198                 fprintf(stderr, "Marker 0x%02x, at position %ld\n", m2, ftell(stdin) - source.bytes_available);
199
200                 switch (m2) {
201                 case 0xe0:
202                 case 0xe1:
203                 case 0xe2:
204                 case 0xe3:
205                 case 0xe4:
206                 case 0xe5:
207                 case 0xe6:
208                 case 0xe7:
209                 case 0xe8:
210                 case 0xe9:
211                 case 0xea:
212                 case 0xeb:
213                 case 0xec:
214                 case 0xed:
215                 case 0xee:
216                 case 0xef:
217                         /* APP0 through APPF */
218                 case 0xfc:
219                         /* some EXIF stuff */
220                 case 0xfe:
221                         /* comment */
222                 case 0xff:
223                         /* ignore */
224                         skip_segment(&source);
225                         break;
226                 case 0xdb:
227                         /* DQT */
228                         read_dqt(&source, &jpeg);
229                         break;
230                 case 0xc0:
231                         /* SOF0 (baseline DCT, Huffman encoded) */
232                         read_sof(&source, &jpeg);
233                         break;
234                 case 0xd8:
235                         /* SOI */
236                         break;
237                 case 0xc4:
238                         /* DHT (define Huffman tables) */
239                         read_huffman_tables(&tables, byte_source_input_func, &source);
240                         break;
241                 case 0xda:
242                         /* SOS (start of scan) */
243                         read_scan(&source, &jpeg, &tables);
244                         break;
245                 default:
246                         fprintf(stderr, "Error: Unknown marker 0x%02x\n", m2);
247                         exit(1);
248                 }
249         }
250 }