Refactoring the iff decoder
[deark.git] / modules / alphabmp.c
blob329990a25e54b66e1d0e7de5ac013e3b2aa365ea
1 // This file is part of Deark.
2 // Copyright (C) 2016 Jason Summers
3 // See the file COPYING for terms of use.
5 // Alpha Microsystems BMP
7 #include <deark-config.h>
8 #include <deark-private.h>
9 #include <deark-fmtutil.h>
10 DE_DECLARE_MODULE(de_module_alphabmp);
12 typedef struct localctx_struct {
13 i64 npwidth, h;
14 i64 pdwidth;
15 i64 bpp;
16 unsigned int has_palette;
17 unsigned int palette_is_hls;
18 i64 compression;
19 i64 num_pal_entries;
20 u32 pal[256];
21 } lctx;
23 static int do_read_palette(deark *c, lctx *d, i64 pos, i64 *pal_nbytes)
25 de_dbg(c, "palette at %d", (int)pos);
26 de_dbg_indent(c, 1);
28 d->num_pal_entries = de_getu16le(pos) + 1;
29 de_dbg(c, "number of palette colors: %d", (int)d->num_pal_entries);
30 if(d->palette_is_hls)
31 *pal_nbytes = 2 + d->num_pal_entries * 6;
32 else
33 *pal_nbytes = 2 + d->num_pal_entries * 3;
34 if(d->palette_is_hls) goto done;
36 de_read_palette_rgb(c->infile, pos+2, d->num_pal_entries, 3, d->pal, 256, 0);
37 done:
38 de_dbg_indent(c, -1);
39 return 1;
42 static void do_bitmap(deark *c, lctx *d, dbuf *unc_pixels)
44 i64 i, j;
45 i64 rowspan;
46 i64 bits_per_row;
47 u32 clr;
48 de_bitmap *img = NULL;
49 u8 b;
51 bits_per_row = de_pad_to_n(d->npwidth * d->bpp, 8);
52 rowspan = bits_per_row/8;
53 d->pdwidth = bits_per_row / d->bpp;
55 img = de_bitmap_create2(c, d->npwidth, d->pdwidth, d->h, 3);
57 for(j=0; j<d->h; j++) {
58 for(i=0; i<d->pdwidth; i++) {
59 if(d->bpp<=8) {
60 b = de_get_bits_symbol(unc_pixels, d->bpp, j*rowspan, i);
61 clr = d->pal[(unsigned int)b];
63 else {
64 clr = dbuf_getRGB(unc_pixels, j*rowspan + i*3, 0);
66 de_bitmap_setpixel_rgb(img, i, j, clr);
70 de_bitmap_write_to_file(img, NULL, 0);
72 de_bitmap_destroy(img);
75 static int do_uncompress_image(deark *c, lctx *d, i64 pos1, dbuf *unc_pixels)
77 i64 bytes_in_this_line;
78 i64 pos = pos1;
79 i64 j;
80 struct de_dfilter_ctx *dfctx = NULL;
81 struct de_dfilter_out_params dcmpro;
82 struct de_dfilter_results dres;
84 de_dbg(c, "decompressing bitmap");
86 // Each line is compressed independently, using PackBits.
87 de_dfilter_init_objects(c, NULL, &dcmpro, &dres);
88 dcmpro.f = unc_pixels;
89 dfctx = de_dfilter_create(c, dfilter_packbits_codec, NULL, &dcmpro, &dres);
91 for(j=0; j<d->h; j++) {
92 bytes_in_this_line = de_getu16le(pos);
93 pos += 2;
94 de_dfilter_addslice(dfctx, c->infile, pos, bytes_in_this_line);
95 de_dfilter_command(dfctx, DE_DFILTER_COMMAND_SOFTRESET, 0);
96 pos += bytes_in_this_line;
99 de_dfilter_finish(dfctx);
100 if(dres.errcode) {
101 de_err(c, "%s", de_dfilter_get_errmsg(c, &dres));
102 return 0;
105 de_dbg(c, "decompressed %d bytes to %d bytes", (int)(pos-pos1),
106 (int)unc_pixels->len);
108 de_dfilter_destroy(dfctx);
109 return 1;
112 static void de_run_alphabmp(deark *c, de_module_params *mparams)
114 unsigned int flags;
115 lctx *d = NULL;
116 i64 pos;
117 i64 palsize;
118 dbuf *unc_pixels = NULL;
119 int saved_indent_level;
121 de_dbg_indent_save(c, &saved_indent_level);
123 d = de_malloc(c, sizeof(lctx));
124 de_declare_fmt(c, "Alpha Microsystems BMP");
126 pos = 10;
128 de_dbg(c, "bitmap image definition block at %d", (int)pos);
129 de_dbg_indent(c, 1);
131 d->npwidth = de_getu16le(pos);
132 d->h = de_getu16le(pos+2);
133 de_dbg_dimensions(c, d->npwidth, d->h);
134 if(!de_good_image_dimensions(c, d->npwidth, d->h)) goto done;
136 d->bpp = de_getu16le(pos+4);
137 de_dbg(c, "bits/pixel: %d", (int)d->bpp);
139 flags = (unsigned int)de_getu16le(pos+6);
140 d->has_palette = flags & 0x01;
141 d->palette_is_hls = (flags>>1) & 0x01;
142 de_dbg(c, "has-palette: %d", (int)d->has_palette);
143 if(d->has_palette)
144 de_dbg(c, "palette-is-HLS: %d", (int)d->palette_is_hls);
146 d->compression = de_getu16le(pos+8);
147 de_dbg(c, "compression: %d", (int)d->compression);
148 de_dbg_indent(c, -1);
150 pos += 70;
152 if(d->has_palette) {
153 if(d->palette_is_hls && d->bpp<=8) {
154 de_err(c, "HLS palettes are not supported");
155 goto done;
157 if(!do_read_palette(c, d, pos, &palsize)) goto done;
158 pos += palsize;
160 else if(d->bpp<=8) {
161 de_err(c, "Paletted images without an embedded palette are not supported");
162 goto done;
165 de_dbg(c, "bitmap at %d", (int)pos);
166 de_dbg_indent(c, 1);
168 if(d->compression) {
169 unc_pixels = dbuf_create_membuf(c, 32768, 0);
170 if(!do_uncompress_image(c, d, pos, unc_pixels)) goto done;
172 else {
173 unc_pixels = dbuf_open_input_subfile(c->infile, pos, c->infile->len - pos);
176 if(d->bpp!=1 && d->bpp!=4 && d->bpp!=8 && d->bpp!=24) {
177 de_err(c, "%d bits/pixel is not supported", (int)d->bpp);
178 goto done;
181 do_bitmap(c, d, unc_pixels);
182 de_dbg_indent(c, -1);
184 done:
185 de_dbg_indent_restore(c, saved_indent_level);
186 dbuf_close(unc_pixels);
187 de_free(c, d);
190 static int de_identify_alphabmp(deark *c)
192 i64 flg;
194 if(!de_input_file_has_ext(c, "bmp")) return 0;
196 flg = de_getu16le(0);
197 if(flg==0xffff || flg==0xfffe) {
198 return 60;
200 return 0;
203 void de_module_alphabmp(deark *c, struct deark_module_info *mi)
205 mi->id = "alphabmp";
206 mi->desc = "Alpha Microsystems BMP";
207 mi->run_fn = de_run_alphabmp;
208 mi->identify_fn = de_identify_alphabmp;