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