Fixed a typo
[deark.git] / modules / awbm.c
blob59cb9d9edafdb6afd85abd81e9157c0eef909f90
1 // This file is part of Deark.
2 // Copyright (C) 2016 Jason Summers
3 // See the file COPYING for terms of use.
5 // Award BIOS logo formats
7 #include <deark-config.h>
8 #include <deark-private.h>
9 DE_DECLARE_MODULE(de_module_awbm);
11 typedef struct localctx_struct {
12 i64 w, h;
13 int rgb_order;
14 } lctx;
16 #define EPA_CH 14 // "character" height (width must be 8)
18 static int do_v1_image(deark *c, i64 pos,
19 i64 w_blocks, i64 h_blocks, int special, unsigned int createflags)
21 de_bitmap *img = NULL;
22 i64 w, h;
23 i64 i, j, i2, j2;
24 i64 colors_start=0, bitmap_start;
25 u8 b;
26 u32 clr1, clr2;
27 int retval = 0;
29 w = 8 * w_blocks;
30 h = EPA_CH * h_blocks;
31 if(!de_good_image_dimensions(c, w, h)) goto done;
32 img = de_bitmap_create(c, w, h, special?4:3);
34 if(special) {
35 // The first block is not stored, and is assumed to be blank.
36 // To compensate, pretend the image starts 1 block before it does.
37 // (There's special code later to make the first block blank.)
38 bitmap_start = pos - EPA_CH;
40 else {
41 colors_start = pos;
42 bitmap_start = colors_start + w_blocks*h_blocks;
45 // Read the bitmap, "character by character"
46 for(j=0; j<h_blocks; j++) {
47 for(i=0; i<w_blocks; i++) {
48 if(special) {
49 if(j==0 && i==0) {
50 // No data (transparent)
51 clr1 = DE_STOCKCOLOR_TRANSPARENT;
52 clr2 = DE_STOCKCOLOR_TRANSPARENT;
54 else {
55 // Blue on black
56 clr1 = DE_MAKE_RGB(0x00,0x00,0xff);
57 clr2 = DE_STOCKCOLOR_BLACK;
60 else {
61 // Read the color attributes for this block of pixel
62 b = de_getbyte(colors_start + j*w_blocks + i);
63 clr1 = de_palette_pc16((int)(b&0x0f));
64 clr2 = de_palette_pc16((int)((b&0xf0)>>4));
67 // Read each individual pixel
68 for(j2=0; j2<EPA_CH; j2++) {
69 for(i2=0; i2<8; i2++) {
70 if(special && j==0 && i==0) {
71 b = 0;
73 else {
74 b = de_get_bits_symbol(c->infile, 1,
75 bitmap_start + j*w_blocks*EPA_CH + i*EPA_CH + j2, i2);
77 de_bitmap_setpixel_rgba(img, i*8+i2, j*EPA_CH+j2, b?clr1:clr2);
82 de_bitmap_write_to_file(img, NULL, createflags);
83 retval = 1;
84 done:
85 de_bitmap_destroy(img);
86 return retval;
89 static void do_v1(deark *c, lctx *d)
91 i64 w_blocks, h_blocks;
92 i64 after_bitmap;
94 de_declare_fmt(c, "Award BIOS logo v1");
96 w_blocks = (i64)de_getbyte(0);
97 h_blocks = (i64)de_getbyte(1);
98 if(!do_v1_image(c, 2, w_blocks, h_blocks, 0, 0)) goto done;
100 after_bitmap = 2 + w_blocks*h_blocks + h_blocks*EPA_CH*w_blocks;
101 if(c->infile->len >= after_bitmap+70) {
102 // The file usually contains a second image: a small Award logo.
103 do_v1_image(c, after_bitmap, 3, 2, 1, DE_CREATEFLAG_IS_AUX);
105 done:
109 static int detect_palette_at(deark *c, lctx *d, i64 pos, i64 ncolors)
111 if(pos + 4 + 3*ncolors > c->infile->len) return 0;
112 if(!dbuf_memcmp(c->infile, pos, "RGB ", 4)) return 1;
113 return 0;
117 static void do_v2(deark *c, lctx *d)
119 de_bitmap *img = NULL;
120 i64 rowspan1;
121 i64 rowspan;
122 i64 bitmap_start;
123 i64 bitmap_size;
124 i64 palette_start;
125 i64 i, j;
126 i64 k;
127 u8 cr, cg, cb;
128 u8 b;
129 u8 b1;
130 const char *s;
131 i64 ncolors = 0; // 16 or 256
132 u32 pal[256];
134 de_zeromem(pal, sizeof(pal));
135 d->w = de_getu16le(4);
136 d->h = de_getu16le(6);
137 de_dbg_dimensions(c, d->w, d->h);
138 if(!de_good_image_dimensions(c, d->w, d->h)) goto done;
140 bitmap_start = 8;
141 rowspan1 = (d->w+7)/8;
143 rowspan = d->w; // Start by guessing 8bpp
144 bitmap_size = rowspan * d->h;
146 if(detect_palette_at(c, d, bitmap_start+bitmap_size, 256)) {
147 ncolors=256;
148 de_declare_fmt(c, "Award BIOS logo v2 8-bit");
150 else {
151 // Doesn't seem to be an 8pp image. Try 4bpp.
152 rowspan = rowspan1 * 4;
153 bitmap_size = rowspan * d->h;
154 if(detect_palette_at(c, d, bitmap_start+bitmap_size, 16)) {
155 ncolors=16;
156 de_declare_fmt(c, "Award BIOS logo v2 4-bit");
160 if(!ncolors) {
161 de_err(c, "Can't detect image format");
162 goto done;
165 // Default to BGR for 16-color images, RGB for 256-color.
166 if(ncolors==16)
167 d->rgb_order = 0;
168 else
169 d->rgb_order = 1;
171 s = de_get_ext_option(c, "awbm:rgb");
172 if(s) d->rgb_order = de_atoi(s);
174 palette_start = bitmap_start+bitmap_size+4;
176 // Read the palette
177 for(i=0; i<ncolors; i++) {
178 cr = de_scale_63_to_255(de_getbyte(palette_start+i*3+0));
179 cg = de_scale_63_to_255(de_getbyte(palette_start+i*3+1));
180 cb = de_scale_63_to_255(de_getbyte(palette_start+i*3+2));
181 if(d->rgb_order)
182 pal[i] = DE_MAKE_RGB(cr, cg, cb);
183 else
184 pal[i] = DE_MAKE_RGB(cb, cg, cr);
187 img = de_bitmap_create(c, d->w, d->h, 3);
188 for(j=0; j<d->h; j++) {
189 for(i=0; i<d->w; i++) {
190 if(ncolors==16) {
191 b = 0;
192 for(k=0; k<4; k++) {
193 b1 = de_get_bits_symbol(c->infile, 1, bitmap_start + j*rowspan + k*rowspan1, i);
194 b |= b1<<k;
197 else {
198 b = de_getbyte(bitmap_start + j*rowspan + i);
200 de_bitmap_setpixel_rgb(img, i, j, pal[(unsigned int)b]);
204 de_bitmap_write_to_file(img, NULL, 0);
205 done:
206 de_bitmap_destroy(img);
209 static void de_run_awbm(deark *c, de_module_params *mparams)
211 lctx *d = NULL;
213 d = de_malloc(c, sizeof(lctx));
215 if(!dbuf_memcmp(c->infile, 0, "AWBM", 4)) {
216 do_v2(c, d);
218 else {
219 do_v1(c, d);
222 de_free(c, d);
225 static int de_identify_awbm(deark *c)
227 u8 buf[4];
228 i64 nblocks;
229 int epa_ext;
231 de_read(buf, 0, 4);
232 if(!de_memcmp(buf, "AWBM", 4)) return 100;
234 nblocks = (i64)buf[0] * (i64)buf[1];
235 if(nblocks<1 || nblocks>256) return 0;
236 if(c->infile->len == 2 + nblocks*15 + 70) {
237 epa_ext = de_input_file_has_ext(c, "epa");
238 if(epa_ext) return 100;
239 return 20;
241 return 0;
244 static void de_help_awbm(deark *c)
246 de_msg(c, "-opt awbm:rgb=0 : Assume BGR sample order");
247 de_msg(c, "-opt awbm:rgb=1 : Assume RGB sample order");
250 void de_module_awbm(deark *c, struct deark_module_info *mi)
252 mi->id = "awbm";
253 mi->desc = "Award BIOS logo";
254 mi->run_fn = de_run_awbm;
255 mi->identify_fn = de_identify_awbm;
256 mi->help_fn = de_help_awbm;