bmp: Rewrote the RLE decompressor
[deark.git] / modules / makichan.c
blob4b135b9853f2cedb9327c30e0ccc08c4f8f3a063
1 // This file is part of Deark.
2 // Copyright (C) 2016 Jason Summers
3 // See the file COPYING for terms of use.
5 // MAKIchan graphics
6 // Supported: Most .MAG, .MKI
7 // Not supported: .MAX, some variant formats
9 #include <deark-config.h>
10 #include <deark-private.h>
11 DE_DECLARE_MODULE(de_module_makichan);
13 typedef struct localctx_struct {
14 u8 opt_allowbad;
15 i64 width, height;
16 i64 header_pos;
17 i64 flag_a_offset;
18 i64 flag_b_offset;
19 i64 flag_b_size;
20 i64 pixels_offset;
21 i64 pixels_size;
22 i64 num_colors;
23 i64 bits_per_pixel;
24 i64 rowspan;
25 i64 width_adj, height_adj;
27 u8 aspect_ratio_flag;
28 int is_max;
29 int is_mki;
30 int is_mki_b;
31 dbuf *virtual_screen;
32 dbuf *unc_pixels;
33 u32 pal[256];
34 } lctx;
36 static i64 de_int_round_up(i64 n, i64 m)
38 return ((n+(m-1))/m)*m;
41 static void read_palette(deark *c, lctx *d, i64 pos)
43 i64 k;
44 u8 cr, cg, cb;
46 de_dbg(c, "palette at %d", (int)pos);
47 de_dbg_indent(c, 1);
49 for(k=0; k<d->num_colors; k++) {
50 cg = de_getbyte(pos+3*k);
51 cr = de_getbyte(pos+3*k+1);
52 cb = de_getbyte(pos+3*k+2);
53 d->pal[k] = DE_MAKE_RGB(cr,cg,cb);
54 de_dbg_pal_entry(c, k, d->pal[k]);
57 de_dbg_indent(c, -1);
60 static int read_mki_header(deark *c, lctx *d)
62 i64 xoffset, yoffset;
63 i64 width_raw, height_raw;
64 i64 pos;
65 i64 flag_a_size;
66 i64 pix_data_a_size;
67 i64 pix_data_b_size;
68 i64 expected_file_size;
69 unsigned int extension_flags;
70 int retval = 0;
72 de_dbg(c, "MKI header at %d", (int)d->header_pos);
73 de_dbg_indent(c, 1);
75 pos = d->header_pos;
77 d->flag_b_size = de_getu16be(pos+0);
78 pix_data_a_size = de_getu16be(pos+2);
79 pix_data_b_size = de_getu16be(pos+4);
80 d->pixels_size = pix_data_a_size + pix_data_b_size;
82 extension_flags = (unsigned int)de_getu16be(pos+6);
83 de_dbg(c, "extension flags: 0x%04x", extension_flags);
84 de_dbg_indent(c, 1);
85 d->aspect_ratio_flag = extension_flags&0x0001;
86 if(extension_flags&0x0002) {
87 d->num_colors = 8;
89 else {
90 d->num_colors = 16;
91 d->bits_per_pixel = 4;
93 de_dbg(c, "number of colors: %d", (int)d->num_colors);
94 de_dbg_indent(c, -1);
96 xoffset = de_getu16be(pos+8);
97 yoffset = de_getu16be(pos+10);
98 de_dbg(c, "image offset: (%d,%d)", (int)xoffset, (int)yoffset);
100 width_raw = de_getu16be(pos+12);
101 d->width = width_raw - xoffset;
102 height_raw = de_getu16be(pos+14);
103 d->height = height_raw - yoffset;
104 de_dbg_dimensions(c, d->width, d->height);
105 if(d->width%64 != 0) {
106 de_warn(c, "Width is not a multiple of 64. This image may not be handled correctly.");
108 d->width_adj = de_int_round_up(d->width, 64);
109 if(d->height%4 != 0) {
110 de_warn(c, "Height is not a multiple of 4. This image may not be handled correctly.");
112 d->height_adj = de_int_round_up(d->height, 4);
114 d->flag_a_offset = pos + 16 + 48;
115 // The documentation seems to say that flag A is *always* 1000 bytes, regardless of
116 // how many bytes would actually be needed.
117 // This would imply that a MAKI image can't have more than 256000 pixels.
118 flag_a_size = 1000;
119 //flag_a_size = (d->width_adj*d->height_adj)/256;
121 d->flag_b_offset = d->flag_a_offset + flag_a_size;
122 d->pixels_offset = d->flag_b_offset + d->flag_b_size;
123 expected_file_size = d->pixels_offset + d->pixels_size;
124 de_dbg(c, "flag A offset=%d, size=%d", (int)d->flag_a_offset, (int)flag_a_size);
125 de_dbg(c, "flag B calculated_offset=%d, size=%d", (int)d->flag_b_offset, (int)d->flag_b_size);
126 de_dbg(c, "pix data size_A=%d, size_B=%d", (int)pix_data_a_size, (int)pix_data_b_size);
127 de_dbg(c, "pix data calculated_offset=%d, calculated_size=%d", (int)d->pixels_offset, (int)d->pixels_size);
128 de_dbg(c, "calculated file size: %d", (int)expected_file_size);
130 if(d->bits_per_pixel!=4 && d->bits_per_pixel!=8) {
131 de_err(c, "Unsupported or unknown bits/pixel");
132 goto done;
135 retval = 1;
137 done:
138 de_dbg_indent(c, -1);
139 return retval;
142 static void mki_decompress_virtual_screen(deark *c, lctx *d)
144 i64 i, j;
145 i64 a_pos, b_pos;
146 i64 vs_rowspan;
147 i64 k;
148 u8 tmpn[4];
149 u8 v;
150 u8 a_byte = 0x00;
151 int a_bitnum;
153 vs_rowspan = d->width_adj/16;
154 a_pos = d->flag_a_offset;
155 a_bitnum = -1;
156 b_pos = d->flag_b_offset;
157 d->virtual_screen = dbuf_create_membuf(c, vs_rowspan*d->height_adj, 1);
159 for(j=0; j<d->height_adj/4; j++) {
160 for(i=0; i<d->width_adj/8; i++) {
161 u8 flag_a_bit;
163 // Read next flag A bit
164 if(a_bitnum<0) {
165 a_byte = de_getbyte(a_pos++);
166 a_bitnum = 7;
168 flag_a_bit = a_byte & (1 << a_bitnum--);
170 if(!flag_a_bit)
171 continue;
173 // Read the next two bytes from flag B, and split them into 4 nibbles.
174 tmpn[0] = de_getbyte(b_pos++);
175 tmpn[2] = de_getbyte(b_pos++);
176 tmpn[1] = tmpn[0]&0x0f;
177 tmpn[3] = tmpn[2]&0x0f;
178 tmpn[0] >>= 4;
179 tmpn[2] >>= 4;
181 for(k=0; k<4; k++) {
182 i64 vs_pos;
184 vs_pos = (4*j+k)*vs_rowspan + i/2;
185 if(i%2==0) {
186 v = tmpn[k]<<4;
188 else {
189 v = dbuf_getbyte(d->virtual_screen, vs_pos) | tmpn[k];
191 dbuf_writebyte_at(d->virtual_screen, vs_pos, v);
197 static void mki_decompress_pixels(deark *c, lctx *d)
199 i64 i, j;
200 i64 p_pos;
201 i64 delta_y;
202 i64 vs_pos;
203 int vs_bitnum;
204 u8 vs_byte = 0x00;
206 d->rowspan = d->width_adj/2;
207 vs_pos = 0;
208 vs_bitnum = -1;
209 p_pos = d->pixels_offset;
210 delta_y = d->is_mki_b ? 4 : 2;
211 d->unc_pixels = dbuf_create_membuf(c, d->rowspan*d->height_adj, 1);
213 for(j=0; j<d->height; j++) {
214 for(i=0; i<d->rowspan; i++) {
215 u8 vs_bit;
216 u8 v;
218 // Read the next virtual-screen bit
219 if(vs_bitnum<0) {
220 vs_byte = dbuf_getbyte(d->virtual_screen, vs_pos++);
221 vs_bitnum = 7;
223 vs_bit = vs_byte & (1 << vs_bitnum--);
225 if(vs_bit) {
226 v = de_getbyte(p_pos++);
228 else {
229 v = 0x00;
232 if(j>=delta_y) {
233 v ^= dbuf_getbyte(d->unc_pixels, (j-delta_y)*d->rowspan + i);
235 dbuf_writebyte(d->unc_pixels, v);
240 static int read_mag_header(deark *c, lctx *d)
242 i64 xoffset, yoffset;
243 i64 width_raw, height_raw;
244 i64 pos;
245 u8 model_code;
246 u8 model_flags;
247 u8 screen_mode;
248 u8 colors_code;
249 int retval = 0;
251 de_dbg(c, "header at %d", (int)d->header_pos);
252 de_dbg_indent(c, 1);
254 pos = d->header_pos;
256 model_code = de_getbyte(pos+1);
257 model_flags = de_getbyte(pos+2);
258 de_dbg(c, "model code: 0x%02x, flags: 0x%02x",
259 (unsigned int)model_code, (unsigned int)model_flags);
260 if(model_code==0x03) {
261 switch(model_flags & 0xf8) {
262 case 0x00: case 0x10: case 0x50:
263 break;
264 case 0x20: case 0x40: case 0x60:
265 d->is_max = 1;
266 if(d->opt_allowbad) break;
267 de_err(c, "This looks like MAX format, which is not supported.");
268 goto done;
269 default:
270 de_err(c, "Unknown image type");
271 goto done;
275 screen_mode = de_getbyte(pos+3);
276 de_dbg(c, "screen mode: %d", (int)screen_mode);
277 de_dbg_indent(c, 1);
278 d->aspect_ratio_flag = screen_mode&0x01;
279 colors_code = screen_mode&0x82;
280 if(colors_code==0x00) {
281 d->num_colors = 16;
282 d->bits_per_pixel = 4;
284 else if(colors_code==0x80) {
285 d->num_colors = 256;
286 d->bits_per_pixel = 8;
288 else if(colors_code==0x02) {
289 d->num_colors = 8;
290 // TODO: Support 8 color images
292 de_dbg(c, "number of colors: %d", (int)d->num_colors);
293 de_dbg_indent(c, -1);
295 xoffset = de_getu16le(pos+4);
296 yoffset = de_getu16le(pos+6);
297 de_dbg(c, "image offset: (%d,%d)", (int)xoffset, (int)yoffset);
299 width_raw = de_getu16le(pos+8);
300 height_raw = de_getu16le(pos+10);
301 d->width = width_raw - xoffset + 1;
302 d->height = height_raw - yoffset + 1;
303 de_dbg_dimensions(c, d->width, d->height);
305 d->flag_a_offset = de_getu32le(pos+12);
306 d->flag_a_offset += d->header_pos;
307 de_dbg(c, "flag A offset: %d", (int)d->flag_a_offset);
309 d->flag_b_offset = de_getu32le(pos+16);
310 d->flag_b_offset += d->header_pos;
311 d->flag_b_size = de_getu32le(pos+20);
312 de_dbg(c, "flag B offset: %d, size=%d", (int)d->flag_b_offset, (int)d->flag_b_size);
314 d->pixels_offset = de_getu32le(pos+24);
315 d->pixels_offset += d->header_pos;
316 d->pixels_size = de_getu32le(pos+28);
317 de_dbg(c, "pixels offset: %d, size=%d", (int)d->pixels_offset, (int)d->pixels_size);
319 if(d->bits_per_pixel!=4 && d->bits_per_pixel!=8) {
320 de_err(c, "Unsupported or unknown bits/pixel");
321 goto done;
324 retval = 1;
325 done:
326 de_dbg_indent(c, -1);
327 return retval;
330 static int do_mag_decompress(deark *c, lctx *d)
332 static const u8 delta_x[16] = { 0,1,2,4,0,1,0,1,2,0,1,2,0,1,2, 0 };
333 static const u8 delta_y[16] = { 0,0,0,0,1,1,2,2,2,4,4,4,8,8,8,16 };
334 i64 x, y;
335 i64 a_pos, b_pos;
336 i64 p_pos;
337 int a_bitnum; // Index of next bit to read. -1 = no more bits in a_byte.
338 u8 a_byte = 0x00;
339 u8 b_byte;
340 int k;
341 i64 dpos;
342 u8 *action_byte_buf = NULL;
343 u8 wordbuf[2];
345 de_dbg(c, "decompressing pixels");
347 // Presumably, due to the compression scheme, every row must have a
348 // multiple of 4 bytes.
349 d->rowspan = ((d->width * d->bits_per_pixel + 31)/32)*4;
351 d->unc_pixels = dbuf_create_membuf(c, d->rowspan * d->height, 1);
353 a_pos = d->flag_a_offset;
354 a_bitnum = -1;
355 b_pos = d->flag_b_offset;
356 p_pos = d->pixels_offset;
358 action_byte_buf = de_malloc(c, d->rowspan/4);
360 for(y=0; y<d->height; y++) {
361 for(x=0; x<d->rowspan/4; x++) {
362 u8 action_byte;
363 u8 flag_a_bit;
365 // Read next flag A bit
366 if(a_bitnum<0) {
367 a_byte = de_getbyte(a_pos++);
368 a_bitnum = 7;
370 flag_a_bit = a_byte & (1 << a_bitnum--);
372 if(flag_a_bit) {
373 // If flag_a_bit is unset, re-use the action byte from the
374 // previous row.
375 // If flag bit A is set, the new action byte is the one from the
376 // previous row XORed with the next B byte (don't ask me why).
377 b_byte = de_getbyte(b_pos++);
378 action_byte_buf[x] ^= b_byte;
381 action_byte = action_byte_buf[x];
383 // Produce 4 uncompressed bytes, 2 for each nibble in the
384 // action byte.
385 for(k=0; k<2; k++) {
386 unsigned int dcode;
388 if(k==0)
389 dcode = (unsigned int)((action_byte&0xf0)>>4);
390 else
391 dcode = (unsigned int)(action_byte&0x0f);
393 if(dcode==0) {
394 // An "uncompressed" data word. Read it from the source file.
395 de_read(wordbuf, p_pos, 2);
396 p_pos += 2;
398 else {
399 // Copy the data word from an earlier location in the image.
400 dpos = d->unc_pixels->len -
401 d->rowspan*(i64)delta_y[dcode] -
402 2*(i64)delta_x[dcode];
403 dbuf_read(d->unc_pixels, wordbuf, dpos, 2);
405 dbuf_write(d->unc_pixels, wordbuf, 2);
410 de_free(c, action_byte_buf);
411 return 1;
414 static void do_create_image(deark *c, lctx *d)
416 de_bitmap *img = NULL;
417 de_finfo *fi = NULL;
419 img = de_bitmap_create(c, d->width, d->height, 3);
421 fi = de_finfo_create(c);
423 if(d->aspect_ratio_flag) {
424 fi->density.code = DE_DENSITY_UNK_UNITS;
425 fi->density.xdens = 2.0;
426 fi->density.ydens = 1.0;
429 de_convert_image_paletted(d->unc_pixels, 0,
430 d->bits_per_pixel, d->rowspan, d->pal, img, 0);
432 de_bitmap_write_to_file_finfo(img, fi, 0);
433 de_bitmap_destroy(img);
434 de_finfo_destroy(c, fi);
437 // Sets d->header_pos
438 static int find_mag_header(deark *c, lctx *d)
440 i64 pos_1a = 0;
441 int ret;
443 // Find the first 0x1a byte.
444 ret = dbuf_search_byte(c->infile, '\x1a', 0, c->infile->len, &pos_1a);
445 if(ret) {
446 // Find the first 0x00 byte after the first 0x1a byte.
447 // TODO: Is this the correct algorithm, or should we just assume the
448 // header starts immediately after the first 0x1a byte?
449 ret = dbuf_search_byte(c->infile, '\0', pos_1a+1, c->infile->len-pos_1a-1, &d->header_pos);
450 if(ret) {
451 de_dbg(c, "header found at %d", (int)d->header_pos);
452 return 1;
456 de_err(c, "Failed to find header. This is probably not a MAKIchan file.");
457 return 0;
460 static void do_mag(deark *c, lctx *d)
462 if(!find_mag_header(c, d)) goto done;
463 if(!read_mag_header(c, d)) goto done;
464 read_palette(c, d, d->header_pos+32);
465 if(!de_good_image_dimensions(c, d->width, d->height)) goto done;
466 if(!do_mag_decompress(c, d)) goto done;
467 do_create_image(c, d);
468 done:
472 static void do_mki(deark *c, lctx *d)
474 d->header_pos = 32;
475 if(!read_mki_header(c, d)) goto done;
476 read_palette(c, d, d->header_pos+16);
477 if(!de_good_image_dimensions(c, d->width, d->height)) goto done;
478 mki_decompress_virtual_screen(c, d);
479 mki_decompress_pixels(c, d);
480 do_create_image(c, d);
481 done:
485 static void de_run_makichan(deark *c, de_module_params *mparams)
487 lctx *d = NULL;
489 d = de_malloc(c, sizeof(lctx));
490 d->opt_allowbad = (u8)de_get_ext_option_bool(c, "makichan:allowbad", 0);
492 if(!dbuf_memcmp(c->infile, 0, "MAKI01", 6)) {
493 d->is_mki = 1;
494 if(de_getbyte(6)=='B') {
495 d->is_mki_b = 1;
499 if(d->is_mki) {
500 do_mki(c, d);
502 else {
503 do_mag(c, d);
506 dbuf_close(d->unc_pixels);
507 dbuf_close(d->virtual_screen);
508 de_free(c, d);
511 static int de_identify_makichan(deark *c)
513 if(!dbuf_memcmp(c->infile, 0, "MAKI0", 5))
514 return 100;
515 return 0;
518 static void de_help_makichan(deark *c)
520 de_msg(c, "-opt makichan:allowbad : Keep going after certain errors");
523 void de_module_makichan(deark *c, struct deark_module_info *mi)
525 mi->id = "makichan";
526 mi->desc = "MAKIchan graphics";
527 mi->run_fn = de_run_makichan;
528 mi->identify_fn = de_identify_makichan;
529 mi->help_fn = de_help_makichan;