Refactoring the iff decoder
[deark.git] / modules / nokia.c
blob0a3a43486c68a0871711726ed4d3e959b04692b5
1 // This file is part of Deark.
2 // Copyright (C) 2016 Jason Summers
3 // See the file COPYING for terms of use.
5 // Various Nokia phone image formats
7 #include <deark-config.h>
8 #include <deark-private.h>
9 #include <deark-fmtutil.h>
10 DE_DECLARE_MODULE(de_module_nol);
11 DE_DECLARE_MODULE(de_module_ngg);
12 DE_DECLARE_MODULE(de_module_npm);
13 DE_DECLARE_MODULE(de_module_nlm);
14 DE_DECLARE_MODULE(de_module_nsl);
16 typedef struct localctx_struct {
17 i64 w, h;
18 int done_flag;
19 } lctx;
21 // **************************************************************************
22 // Nokia Operator Logo (NOL)
24 // Caution: This code is not based on any official specifications.
25 // **************************************************************************
27 static void nol_ngg_read_bitmap(deark *c, lctx *d, i64 pos)
29 de_bitmap *img = NULL;
30 i64 i, j;
31 u8 n;
33 img = de_bitmap_create(c, d->w, d->h, 1);
35 for(j=0; j<d->h; j++) {
36 for(i=0; i<d->w; i++) {
37 n = de_getbyte(pos);
38 pos++;
39 de_bitmap_setpixel_gray(img, i, j, n=='0' ? 255 : 0);
43 de_bitmap_write_to_file(img, NULL, 0);
44 de_bitmap_destroy(img);
47 static void de_run_nol(deark *c, de_module_params *mparams)
49 lctx *d = NULL;
51 d = de_malloc(c, sizeof(lctx));
53 d->w = de_getu16le(10);
54 d->h = de_getu16le(12);
55 de_dbg_dimensions(c, d->w, d->h);
56 if(!de_good_image_dimensions(c, d->w, d->h)) goto done;
58 nol_ngg_read_bitmap(c, d, 20);
59 done:
60 de_free(c, d);
63 static int de_identify_nol(deark *c)
65 if(!dbuf_memcmp(c->infile, 0, "NOL", 3)) return 80;
66 return 0;
69 void de_module_nol(deark *c, struct deark_module_info *mi)
71 mi->id = "nol";
72 mi->desc = "Nokia Operator Logo";
73 mi->run_fn = de_run_nol;
74 mi->identify_fn = de_identify_nol;
77 // **************************************************************************
78 // Nokia Group Graphic (NGG)
80 // Caution: This code is not based on any official specifications.
81 // **************************************************************************
83 static void de_run_ngg(deark *c, de_module_params *mparams)
85 lctx *d = NULL;
87 d = de_malloc(c, sizeof(lctx));
89 d->w = de_getu16le(6);
90 d->h = de_getu16le(8);
91 de_dbg_dimensions(c, d->w, d->h);
92 if(!de_good_image_dimensions(c, d->w, d->h)) goto done;
94 nol_ngg_read_bitmap(c, d, 16);
95 done:
96 de_free(c, d);
99 static int de_identify_ngg(deark *c)
101 if(!dbuf_memcmp(c->infile, 0, "NGG", 3)) return 80;
102 return 0;
105 void de_module_ngg(deark *c, struct deark_module_info *mi)
107 mi->id = "ngg";
108 mi->desc = "Nokia Group Graphic";
109 mi->run_fn = de_run_ngg;
110 mi->identify_fn = de_identify_ngg;
113 // **************************************************************************
114 // Nokia Picture Message (NPM)
116 // Caution: This code is not based on any official specifications.
117 // **************************************************************************
119 static void npm_nlm_read_bitmap(deark *c, lctx *d, i64 pos)
121 de_convert_and_write_image_bilevel2(c->infile, pos, d->w, d->h, (d->w+7)/8,
122 DE_CVTF_WHITEISZERO, NULL, 0);
125 static void de_run_npm(deark *c, de_module_params *mparams)
127 i64 txt_len;
128 i64 pos;
129 lctx *d = NULL;
130 de_ucstring *s = NULL;
132 d = de_malloc(c, sizeof(lctx));
134 pos = 4;
135 txt_len = (i64)de_getbyte_p(&pos);
136 de_dbg(c, "text length: %d", (int)txt_len);
137 if(txt_len>0) {
138 s = ucstring_create(c);
139 dbuf_read_to_ucstring(c->infile, pos, txt_len, s, 0, DE_ENCODING_ASCII);
140 de_dbg(c, "text: \"%s\"", ucstring_getpsz_d(s));
141 pos += txt_len;
143 pos += 1;
145 d->w = (i64)de_getbyte_p(&pos);
146 d->h = (i64)de_getbyte_p(&pos);
147 de_dbg_dimensions(c, d->w, d->h);
149 pos += 3;
150 npm_nlm_read_bitmap(c, d, pos);
152 ucstring_destroy(s);
153 de_free(c, d);
156 static int de_identify_npm(deark *c)
158 if(!dbuf_memcmp(c->infile, 0, "NPM", 3)) return 80;
159 return 0;
162 void de_module_npm(deark *c, struct deark_module_info *mi)
164 mi->id = "npm";
165 mi->desc = "Nokia Picture Message";
166 mi->run_fn = de_run_npm;
167 mi->identify_fn = de_identify_npm;
170 // **************************************************************************
171 // Nokia Logo Manager bitmap (NLM)
173 // Caution: This code is not based on any official specifications.
174 // **************************************************************************
176 static void de_run_nlm(deark *c, de_module_params *mparams)
178 lctx *d = NULL;
179 u8 imgtype;
180 const char *s;
182 d = de_malloc(c, sizeof(lctx));
184 imgtype = de_getbyte(5);
185 switch(imgtype) {
186 case 0: s="Operator logo"; break;
187 case 1: s="Caller logo"; break;
188 case 2: s="Startup logo"; break;
189 case 3: s="Picture image logo"; break;
190 default: s="unknown";
192 de_dbg(c, "image type: %d (%s)", (int)imgtype, s);
194 d->w = (i64)de_getbyte(7);
195 d->h = (i64)de_getbyte(8);
196 de_dbg_dimensions(c, d->w, d->h);
198 npm_nlm_read_bitmap(c, d, 10);
200 de_free(c, d);
203 static int de_identify_nlm(deark *c)
205 if(!dbuf_memcmp(c->infile, 0, "NLM ", 4)) return 80;
206 return 0;
209 void de_module_nlm(deark *c, struct deark_module_info *mi)
211 mi->id = "nlm";
212 mi->desc = "Nokia Logo Manager bitmap";
213 mi->run_fn = de_run_nlm;
214 mi->identify_fn = de_identify_nlm;
217 // **************************************************************************
218 // Nokia Startup Logo (NSL)
220 // Caution: This code is not based on any official specifications.
221 // **************************************************************************
224 static void nsl_read_bitmap(deark *c, lctx *d, i64 pos, i64 len)
226 de_bitmap *img = NULL;
227 i64 i, j;
228 u8 x;
230 de_dbg(c, "bitmap at %d, len=%d", (int)pos, (int)len);
231 d->done_flag = 1;
233 if(len!=504) {
234 de_err(c, "Unsupported NSL version (bitmap size=%d)", (int)len);
235 goto done;
238 d->w = 84;
239 d->h = 48;
241 img = de_bitmap_create(c, d->w, d->h, 1);
243 for(j=0; j<d->h; j++) {
244 for(i=0; i<d->w; i++) {
245 x = de_getbyte(pos + (j/8)*d->w + i);
246 x = x & (1<<(j%8));
247 if(x==0)
248 de_bitmap_setpixel_gray(img, i, j, 255);
252 de_bitmap_write_to_file(img, NULL, 0);
254 done:
255 de_bitmap_destroy(img);
258 #define CODE_FORM 0x464f524dU
259 #define CODE_NSLD 0x4e534c44U
261 static int my_nsl_chunk_handler(struct de_iffctx *ictx)
263 deark *c = ictx->c;
264 lctx *d = (lctx*)ictx->userdata;
266 if(ictx->chunkctx->chunk4cc.id == CODE_FORM) {
267 ictx->is_raw_container = 1;
268 return 1;
271 switch(ictx->chunkctx->chunk4cc.id) {
272 case CODE_NSLD:
273 if(ictx->level==1 && !d->done_flag) {
274 nsl_read_bitmap(c, d, ictx->chunkctx->dpos, ictx->chunkctx->dlen);
276 break;
279 ictx->handled = 1;
280 return 1;
283 static void de_run_nsl(deark *c, de_module_params *mparams)
285 lctx *d = NULL;
286 struct de_iffctx *ictx = NULL;
288 d = de_malloc(c, sizeof(lctx));
289 ictx = fmtutil_create_iff_decoder(c);
291 ictx->userdata = (void*)d;
292 ictx->handle_chunk_fn = my_nsl_chunk_handler;
293 ictx->f = c->infile;
294 ictx->sizeof_len = 2;
296 fmtutil_read_iff_format(ictx, 0, c->infile->len);
298 fmtutil_destroy_iff_decoder(ictx);
299 de_free(c, d);
302 static int de_identify_nsl(deark *c)
304 i64 x;
306 // NSL uses a variant of IFF, which is not so easy to identify.
307 // (TODO: Write an IFF format detector.)
309 if(dbuf_memcmp(c->infile, 0, "FORM", 4)) return 0;
311 x = de_getu16be(4);
312 if(x+6 != c->infile->len) return 0;
314 if(de_input_file_has_ext(c, "nsl")) {
315 return 100;
317 return 10;
320 void de_module_nsl(deark *c, struct deark_module_info *mi)
322 mi->id = "nsl";
323 mi->desc = "Nokia Startup Logo";
324 mi->run_fn = de_run_nsl;
325 mi->identify_fn = de_identify_nsl;