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