1 // This file is part of Deark.
2 // Copyright (C) 2016 Jason Summers
3 // See the file COPYING for terms of use.
5 // Jovian Logic VI (.vi)
7 #include <deark-config.h>
8 #include <deark-private.h>
9 DE_DECLARE_MODULE(de_module_jovianvi
);
11 typedef struct localctx_struct
{
21 i64 pal_first_entry_idx
;
26 static void do_read_palette(deark
*c
, lctx
*d
)
33 de_dbg(c
, "palette at %d", (int)d
->palpos
);
36 for(k
=0; k
<d
->num_pal_colors
; k
++) {
37 idx
= d
->pal_first_entry_idx
+ k
;
40 de_read(b1
, d
->palpos
+ 3*k
, 3);
43 b2
[z
] = de_scale_63_to_255(b1
[z
]); // 6-bit palette samples
46 b2
[z
] = b1
[z
]; // 8-bit palette samples
50 d
->pal
[idx
] = DE_MAKE_RGB(b2
[0],b2
[1],b2
[2]);
54 de_snprintf(tmps
, sizeof(tmps
), "(%2d,%2d,%2d) "DE_CHAR_RIGHTARROW
" ",
55 (int)b1
[0], (int)b1
[1], (int)b1
[2]);
56 de_dbg_pal_entry2(c
, k
, d
->pal
[idx
], tmps
, NULL
, NULL
);
59 de_dbg_pal_entry(c
, k
, d
->pal
[idx
]);
66 static void do_convert_grayscale(deark
*c
, lctx
*d
, de_bitmap
*img
)
72 de_convert_image_bilevel(c
->infile
, d
->bitspos
, d
->rowspan
, img
, 0);
76 for(j
=0; j
<d
->h
; j
++) {
77 for(i
=0; i
<d
->pdwidth
; i
++) {
78 v
= de_get_bits_symbol(c
->infile
, d
->bits_alloc
, d
->bitspos
+ j
*d
->rowspan
, i
);
79 if(d
->bitdepth
==4) v
*= 17;
80 else if(d
->bitdepth
==6) {
81 if(v
<=63) v
= de_scale_63_to_255(v
);
84 de_bitmap_setpixel_gray(img
, i
, j
, v
);
92 static void do_convert_rgb(deark
*c
, lctx
*d
, de_bitmap
*img
)
98 for(j
=0; j
<d
->h
; j
++) {
99 for(i
=0; i
<d
->pdwidth
; i
++) {
100 if(d
->bitdepth
==16) {
101 b0
= de_getbyte(d
->bitspos
+ j
*d
->rowspan
+ i
*2);
102 b1
= de_getbyte(d
->bitspos
+ j
*d
->rowspan
+ i
*2 + 1);
103 clr
= (((u32
)b1
)<<8) | b0
;
104 clr
= de_rgb565_to_888(clr
);
107 clr
= dbuf_getRGB(c
->infile
, d
->bitspos
+j
*d
->rowspan
+i
*3, 0);
109 de_bitmap_setpixel_rgb(img
, i
, j
, clr
);
114 static void de_run_jovianvi(deark
*c
, de_module_params
*mparams
)
117 de_bitmap
*img
= NULL
;
119 int is_grayscale
= 0;
120 const char *imgtypename
;
122 // Warning: This decoder is based on reverse engineering, and may be
123 // incorrect or incomplete.
125 d
= de_malloc(c
, sizeof(lctx
));
127 d
->imgtype
= de_getbyte(2);
128 de_dbg(c
, "image type: 0x%02x", (unsigned int)d
->imgtype
);
162 de_err(c
, "Unknown VI image type: 0x%02x", (unsigned int)d
->imgtype
);
169 d
->bits_alloc
= d
->bitdepth
;
173 if(is_grayscale
) imgtypename
="grayscale";
174 else if(has_palette
) imgtypename
="palette color";
175 else imgtypename
="RGB";
176 de_dbg(c
, "%d bits/pixel, %s", (int)d
->bitdepth
, imgtypename
);
177 de_dbg_indent(c
, -1);
178 if(is_grayscale
&& (d
->bitdepth
!=1 && d
->bitdepth
!=4 && d
->bitdepth
!=6 && d
->bitdepth
!=8)) {
179 de_err(c
, "This type of VI image is not supported");
183 d
->npwidth
= de_getu16le(3);
184 d
->h
= de_getu16le(5);
185 de_dbg_dimensions(c
, d
->npwidth
, d
->h
);
186 if(!de_good_image_dimensions(c
, d
->npwidth
, d
->h
)) goto done
;
189 d
->pal_code
= de_getbyte(9);
190 de_dbg(c
, "palette code: 0x%02x", (unsigned int)d
->pal_code
);
192 d
->pal_first_entry_idx
= (i64
)de_getbyte(10);
193 d
->num_pal_colors
= (i64
)de_getbyte(11);
194 if(d
->num_pal_colors
==0)
195 d
->num_pal_colors
= 256;
196 de_dbg(c
, "index of first palette color: %d", (int)d
->pal_first_entry_idx
);
197 de_dbg(c
, "number of palette colors: %d", (int)d
->num_pal_colors
);
200 d
->palpos
= de_getu16le(12);
201 d
->bitspos
= de_getu16le(14);
203 // Read palette, if applicable
205 do_read_palette(c
, d
);
209 de_dbg(c
, "bitmap at %d", (int)d
->bitspos
);
210 d
->rowspan
= (d
->npwidth
*d
->bits_alloc
+ 7)/8;
211 // Note that a partial pixel's worth of padding is possible in some cases, but
212 // it's not worth the trouble to make -padpix support it.
213 d
->pdwidth
= (d
->rowspan
*8)/(d
->bits_alloc
);
215 img
= de_bitmap_create2(c
, d
->npwidth
, d
->pdwidth
, d
->h
, is_grayscale
?1:3);
217 de_convert_image_paletted(c
->infile
, d
->bitspos
, d
->bitdepth
, d
->rowspan
, d
->pal
, img
, 0);
219 else if(is_grayscale
) {
220 do_convert_grayscale(c
, d
, img
);
223 do_convert_rgb(c
, d
, img
);
225 de_bitmap_write_to_file(img
, NULL
, 0);
228 de_bitmap_destroy(img
);
232 static int de_identify_jovianvi(deark
*c
)
236 if(dbuf_memcmp(c
->infile
, 0, "VI", 2)) return 0;
238 if((t
>=0x10 && t
<=0x11) ||
239 (t
>=0x20 && t
<=0x23) ||
240 (t
>=0x30 && t
<=0x31))
247 void de_module_jovianvi(deark
*c
, struct deark_module_info
*mi
)
250 mi
->desc
= "Jovian Logic VI";
251 mi
->run_fn
= de_run_jovianvi
;
252 mi
->identify_fn
= de_identify_jovianvi
;