Skip to content

Commit 29cc141

Browse files
author
differrari
committed
[DEFLATE] multiple blocks
1 parent 74d2d64 commit 29cc141

1 file changed

Lines changed: 154 additions & 155 deletions

File tree

‎shared/image/png.c‎

Lines changed: 154 additions & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "std/memory_access.h"
44
#include "compression/huffman.h"
55
#include "std/memory.h"
6+
#include "math/math.h"
67

78
typedef struct png_chunk_hdr {
89
uint32_t length;
@@ -34,23 +35,6 @@ typedef union zlib_hdr {
3435
uint16_t hdr;
3536
}__attribute__((packed)) zlib_hdr;
3637

37-
typedef union deflate_dynamic_hdr {
38-
struct {
39-
uint32_t bfinal: 1;
40-
uint32_t btype: 2;
41-
uint32_t hlit: 5;
42-
43-
uint32_t hdist: 5;
44-
uint32_t hclen1: 3;
45-
46-
uint32_t hclen2: 1;
47-
uint32_t rsvd: 7;
48-
49-
uint32_t rsvd2: 8;
50-
};
51-
uint32_t value;
52-
} deflate_dynamic_hdr;
53-
5438
huff_tree_node* deflate_decode_codes(uint8_t max_code_length, uint16_t alphabet_length, uint16_t lengths[]){
5539
uint8_t bl_count[max_code_length] = {};
5640
for (int i = 0; i < max_code_length; i++){
@@ -93,7 +77,7 @@ huff_tree_node* deflate_decode_codes(uint8_t max_code_length, uint16_t alphabet_
9377
} while(0)
9478

9579
#define READ_BITS(from, to, amount, bs, c) do { \
96-
if (bs+amount > 16) \
80+
if (bs + amount > 16) \
9781
to = (((uint16_t)from[c+2] << (16-bs)) & ((1 << amount) - 1)) | \
9882
(((uint16_t)from[c+1] << (8-bs)) & ((1 << amount) - 1)) | \
9983
(((uint16_t)from[c] >> bs) & ((1 << amount) - 1) ); \
@@ -131,169 +115,182 @@ uint32_t dist_bases[] = {
131115
/*13*/ 16385, 24577 //28-29
132116
};
133117

134-
size_t png_load_idat(void* ptr, size_t size, uint8_t *output_buf){
135-
//DEFLATE func
118+
size_t deflate_decode(void* ptr, size_t size, uint8_t *output_buf){
136119
zlib_hdr hdr = *(zlib_hdr*)ptr;
137120
if (hdr.cm != 8){
138121
printf("Only DEFLATE is supported");
139122
}
140123
uintptr_t p = (uintptr_t)ptr + sizeof(zlib_hdr);
141-
//TODO: move to deflate header
142-
deflate_dynamic_hdr dyn_hdr = (deflate_dynamic_hdr)read_unaligned32((uint32_t*)p);
143-
uint8_t hclen = (dyn_hdr.hclen1) | (dyn_hdr.hclen2 << 3);
144-
printf("HCLEN %b %b",dyn_hdr.hclen1,dyn_hdr.hclen2);
145-
printf("DEFLATE DYNAMIC HEADER. LAST? %i. Type %i. HLIT %i, HDIST %i, HCLEN2 %i", dyn_hdr.bfinal, dyn_hdr.btype, dyn_hdr.hlit, dyn_hdr.hdist, hclen);
146124

147-
p += 2;
148-
uint8_t bs = 1;
149125
uint8_t *bytes = (uint8_t*)p;
126+
uint8_t bs = 0;
150127
int c = 0;
151-
uint8_t code_order[19] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
152-
uint16_t permuted[19] = {};
153-
for (uint8_t i = 0; i < hclen+4; i++){
154-
READ_BITS(bytes, permuted[code_order[i]], 3, bs, c);
155-
printf("[%i] = %i",code_order[i],permuted[code_order[i]]);
156-
ADVANCE_BIT(bs, c, 3);
157-
}
158-
huff_tree_node *huff_decode_nodes = deflate_decode_codes(8, 19, permuted);
159-
160-
huffman_viz(huff_decode_nodes, 0, 0);
161-
162-
int tree_data_size = dyn_hdr.hlit + dyn_hdr.hdist + 258;
128+
bool final = false;
129+
uintptr_t out_cursor = 0;
163130

164-
printf("Expecting to read %i",tree_data_size);
131+
while (!final){
132+
uint8_t hclen = 0;//4
133+
uint8_t hdist = 0;//5
134+
uint8_t hlit = 0;//5
135+
uint8_t btype = 0;//2
136+
READ_BITS(bytes, final, 1, bs, c);
137+
ADVANCE_BIT(bs, c, 1);
138+
READ_BITS(bytes, btype, 2, bs, c);
139+
ADVANCE_BIT(bs, c, 2);
140+
READ_BITS(bytes, hlit, 5, bs, c);
141+
ADVANCE_BIT(bs, c, 5);
142+
READ_BITS(bytes, hdist, 5, bs, c);
143+
ADVANCE_BIT(bs, c, 5);
144+
READ_BITS(bytes, hclen, 4, bs, c);
145+
ADVANCE_BIT(bs, c, 4);
146+
printf("DEFLATE DYNAMIC HEADER. LAST? %i. Type %i. HLIT %i, HDIST %i, HCLEN %i", final, btype, hlit, hdist, hclen);
147+
148+
uint8_t code_order[19] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
149+
uint16_t permuted[19] = {};
150+
for (uint8_t i = 0; i < hclen+4; i++){
151+
READ_BITS(bytes, permuted[code_order[i]], 3, bs, c);
152+
ADVANCE_BIT(bs, c, 3);
153+
}
154+
huff_tree_node *huff_decode_nodes = deflate_decode_codes(8, 19, permuted);
155+
156+
huffman_viz(huff_decode_nodes, 0, 0);
157+
158+
int tree_data_size = hlit + hdist + 258;
165159

166-
huff_tree_node *tree_root = huff_decode_nodes;
160+
printf("Expecting to read %i",tree_data_size);
167161

168-
uint16_t *full_huffman = malloc(sizeof(uint16_t) * tree_data_size);
162+
huff_tree_node *tree_root = huff_decode_nodes;
169163

170-
uint16_t last_code_len = 0;
164+
uint16_t *full_huffman = malloc(sizeof(uint16_t) * tree_data_size);
171165

172-
for (int i = 0; i < tree_data_size;){
173-
uint8_t next_bit;
174-
READ_BITS(bytes, next_bit, 1, bs, c);
175-
ADVANCE_BIT(bs, c, 1);
176-
tree_root = huffman_traverse(tree_root, next_bit);
177-
if (!tree_root) {
178-
printf("DEFLATE ERROR: no tree found");
179-
return 0;
180-
}
181-
if (!tree_root->left && !tree_root->right){
182-
uint8_t extra = 0;
183-
switch (tree_root->entry){
184-
case 16:
185-
READ_BITS(bytes, extra, 2, bs, c);
186-
extra += 3;
187-
ADVANCE_BIT(bs, c, 2);
188-
for (int j = 0; j < extra; j++)
189-
full_huffman[i+j] = last_code_len;
190-
break;
191-
case 17:
192-
READ_BITS(bytes, extra, 3, bs, c);
193-
extra += 3;
194-
ADVANCE_BIT(bs, c, 3);
195-
for (int j = 0; j < extra; j++)
196-
full_huffman[i+j] = 0;
197-
break;
198-
case 18:
199-
READ_BITS(bytes, extra, 7, bs, c);
200-
extra += 11;
201-
ADVANCE_BIT(bs, c, 7);
202-
for (int j = 0; j < extra; j++)
203-
full_huffman[i+j] = 0;
204-
break;
205-
default:
206-
full_huffman[i] = tree_root->entry;
207-
break;
166+
uint16_t last_code_len = 0;
167+
168+
for (int i = 0; i < tree_data_size;){
169+
uint8_t next_bit = 0;
170+
READ_BITS(bytes, next_bit, 1, bs, c);
171+
ADVANCE_BIT(bs, c, 1);
172+
tree_root = huffman_traverse(tree_root, next_bit);
173+
if (!tree_root) {
174+
printf("DEFLATE ERROR: no tree found");
175+
return 0;
176+
}
177+
if (!tree_root->left && !tree_root->right){
178+
uint8_t extra = 0;
179+
switch (tree_root->entry){
180+
case 16:
181+
READ_BITS(bytes, extra, 2, bs, c);
182+
extra += 3;
183+
ADVANCE_BIT(bs, c, 2);
184+
for (int j = 0; j < extra; j++)
185+
full_huffman[i+j] = last_code_len;
186+
break;
187+
case 17:
188+
READ_BITS(bytes, extra, 3, bs, c);
189+
extra += 3;
190+
ADVANCE_BIT(bs, c, 3);
191+
for (int j = 0; j < extra; j++)
192+
full_huffman[i+j] = 0;
193+
break;
194+
case 18:
195+
READ_BITS(bytes, extra, 7, bs, c);
196+
extra += 11;
197+
ADVANCE_BIT(bs, c, 7);
198+
for (int j = 0; j < extra; j++)
199+
full_huffman[i+j] = 0;
200+
break;
201+
default:
202+
full_huffman[i] = tree_root->entry;
203+
break;
204+
}
205+
tree_root = huff_decode_nodes;
206+
if (extra)
207+
i+= extra;
208+
else i++;
209+
last_code_len = tree_root->entry;
208210
}
209-
tree_root = huff_decode_nodes;
210-
if (extra)
211-
i+= extra;
212-
else i++;
213-
last_code_len = tree_root->entry;
214211
}
215-
}
216-
printf("Finished processing data");
217-
// huffman_free(huff_decode_nodes);
212+
// huffman_free(huff_decode_nodes);
218213

219-
printf("**** LITERAL/LENGTH ****");
220-
huff_tree_node *litlen_tree = deflate_decode_codes(dyn_hdr.hlit + 257, dyn_hdr.hlit + 257, full_huffman);
221-
huffman_viz(litlen_tree, 0, 0);
214+
printf("**** LITERAL/LENGTH ****");
215+
huff_tree_node *litlen_tree = deflate_decode_codes(hlit + 257, hlit + 257, full_huffman);
216+
huffman_viz(litlen_tree, 0, 0);
222217

223-
printf("**** DISTANCE ****");
224-
huff_tree_node *dist_tree = deflate_decode_codes(dyn_hdr.hdist + 1, dyn_hdr.hdist + 1, full_huffman + dyn_hdr.hlit + 257);
218+
printf("**** DISTANCE ****");
219+
huff_tree_node *dist_tree = deflate_decode_codes(hdist + 1, hdist + 1, full_huffman + hlit + 257);
225220

226-
huffman_viz(dist_tree, 0, 0);
227-
printf("**** WOO ****");
221+
huffman_viz(dist_tree, 0, 0);
222+
// printf("**** WOO ****");
228223

229-
// free(full_huffman, tree_data_size * sizeof(uint16_t));
224+
// free(full_huffman, tree_data_size * sizeof(uint16_t));
230225

231-
tree_root = litlen_tree;
226+
tree_root = litlen_tree;
232227

233-
uintptr_t out_cursor = 0;
234-
235-
printf("Compressed data at %x",bytes + c);
236-
237-
uint16_t val = 0;
238-
while (val != 0x100){
239-
uint8_t next_bit;
240-
READ_BITS(bytes, next_bit, 1, bs, c);
241-
ADVANCE_BIT(bs, c, 1);
242-
tree_root = huffman_traverse(tree_root, next_bit);
243-
if (!tree_root) {
244-
printf("DEFLATE ERROR: no tree found");
245-
return 0;
246-
}
247-
if (!tree_root->left && !tree_root->right){
248-
val = tree_root->entry;
249-
if (val < 0x100){
250-
output_buf[out_cursor] = (val & 0xFF);
251-
// printf("Literal %x",val);
252-
out_cursor++;
253-
} else if (val == 0x100){
254-
break;
255-
} else {
256-
uint8_t extra = 0;
257-
if (val > 264 && val < 285)
258-
extra = (val-261)/4;
259-
uint16_t extra_val = 0;
260-
READ_BITS(bytes, extra_val, extra, bs, c);
261-
ADVANCE_BIT(bs, c, extra);
262-
uint16_t length = base_lengths[val - 257] + extra_val;
263-
huff_tree_node *dist_node = dist_tree;
264-
while (dist_node->left || dist_node->right){
265-
READ_BITS(bytes, next_bit, 1, bs, c);
266-
ADVANCE_BIT(bs, c, 1);
267-
dist_node = huffman_traverse(dist_node, next_bit);
268-
if (!dist_node){
269-
printf("DEFLATE ERROR: no tree found");
270-
return 0;
228+
printf("Compressed data at %x",bytes + c);
229+
230+
uint16_t val = 0;
231+
while (val != 0x100){
232+
uint8_t next_bit = 0;
233+
READ_BITS(bytes, next_bit, 1, bs, c);
234+
ADVANCE_BIT(bs, c, 1);
235+
printf("%x",next_bit);
236+
tree_root = huffman_traverse(tree_root, next_bit);
237+
if (!tree_root) {
238+
printf("DEFLATE ERROR: no tree found");
239+
return 0;
240+
}
241+
if (!tree_root->left && !tree_root->right){
242+
val = tree_root->entry;
243+
if (val < 0x100){
244+
output_buf[out_cursor] = (val & 0xFF);
245+
printf("Literal %x",output_buf[out_cursor]);
246+
out_cursor++;
247+
} else if (val == 0x100){
248+
break;
249+
} else {
250+
uint8_t extra = 0;
251+
if (val > 264 && val < 285)
252+
extra = (val-261)/4;
253+
uint16_t extra_val = 0;
254+
READ_BITS(bytes, extra_val, extra, bs, c);
255+
ADVANCE_BIT(bs, c, extra);
256+
uint16_t length = base_lengths[val - 257] + extra_val;
257+
huff_tree_node *dist_node = dist_tree;
258+
while (dist_node->left || dist_node->right){
259+
READ_BITS(bytes, next_bit, 1, bs, c);
260+
ADVANCE_BIT(bs, c, 1);
261+
dist_node = huffman_traverse(dist_node, next_bit);
262+
if (!dist_node){
263+
printf("DEFLATE ERROR: no tree found");
264+
return 0;
265+
}
271266
}
267+
uint16_t dist_base = dist_node->entry;
268+
uint8_t extra_dist = 0;
269+
uint16_t extra_dist_val = 0;
270+
if (dist_base > 3){
271+
extra_dist = (dist_base-2)/2;
272+
READ_BITS(bytes, extra_dist_val, extra_dist, bs, c);
273+
ADVANCE_BIT(bs, c, extra_dist);
274+
}
275+
// printf("Dista base %i + extra %i",dist_base,extra_dist);
276+
uint32_t distance = dist_bases[dist_base] + extra_dist_val;
277+
// printf("Last %x",output_buf[out_cursor-1]);
278+
// printf("Copying %i bytes from %i bytes back. %x + %x",length,distance,output_buf, out_cursor);
279+
memcpy(output_buf - distance + out_cursor - 1, output_buf + out_cursor, length);
280+
printf("Sanity check 1 %x",output_buf[distance + out_cursor]);
281+
out_cursor += length;
282+
// printf("Sanity check 2 %x",output_buf[out_cursor-1]);
272283
}
273-
uint16_t dist_base = dist_node->entry;
274-
uint8_t extra_dist = 0;
275-
uint16_t extra_dist_val = 0;
276-
if (dist_base > 3){
277-
extra_dist = (dist_base-2)/2;
278-
READ_BITS(bytes, extra_dist_val, extra_dist, bs, c);
279-
ADVANCE_BIT(bs, c, extra_dist);
280-
}
281-
// printf("Dista base %i + extra %i",dist_base,extra_dist);
282-
uint32_t distance = dist_bases[dist_base] + extra_dist_val;
283-
// printf("Copying %i bytes from %i bytes back. %x + %x",length,distance,output_buf, out_cursor);
284-
memcpy(output_buf - distance + out_cursor, output_buf + out_cursor, length);
285-
out_cursor += length;
284+
tree_root = litlen_tree;
286285
}
287-
tree_root = litlen_tree;
288286
}
289287
}
290288

289+
printf("Wrote a total of %i bytes",out_cursor);
290+
291291
// huffman_free(litlen_tree);
292292
// huffman_free(dist_tree);
293293

294-
//TODO: other DEFLATE blocks
295-
//TODO: generalize to DEFLATE funcs
296-
297294
return out_cursor;
298295
}
299296

@@ -332,7 +329,6 @@ uint64_t header = *(uint64_t*)file;
332329
uint32_t length = __builtin_bswap32(hdr->length);
333330
if (strstart(hdr->type, "IHDR", true) == 4){
334331
png_ihdr *ihdr = (png_ihdr*)(p + sizeof(png_chunk_hdr));
335-
printf("Couldn't find png IHDR");
336332
info = (image_info){__builtin_bswap32(ihdr->width),__builtin_bswap32(ihdr->height)};
337333
}
338334
if (strstart(hdr->type, "IDAT", true) == 4){
@@ -343,9 +339,12 @@ uint64_t header = *(uint64_t*)file;
343339
if (!out_buf) out_buf = (uintptr_t)malloc(info.width * info.height * system_bpp);//TODO: bpp might be too big, read image format
344340
printf("Found some idat %x",p + sizeof(png_chunk_hdr) - (uintptr_t)file);
345341
uintptr_t prev_off = out_off;
346-
out_off += png_load_idat((void*)(p + sizeof(png_chunk_hdr)), length, (uint8_t*)(out_buf + out_off));
347-
memcpy(buf + prev_off, (void*)out_buf, out_off);
348-
// return;
342+
out_off += deflate_decode((void*)(p + sizeof(png_chunk_hdr)), length, (uint8_t*)(out_buf + out_off));
343+
memcpy(buf + prev_off, (void*)out_buf, min(out_off, size-prev_off));
344+
// for (uint32_t i = 0; i < out_off; i++){
345+
// printf("[%i] = %x",i, out_buf[i]);
346+
// }
347+
return;
349348
}
350349
p += sizeof(png_chunk_hdr) + __builtin_bswap32(hdr->length) + sizeof(uint32_t);
351350
} while(strstart(hdr->type, "IEND", true) != 4);

0 commit comments

Comments
 (0)