1 // This file is part of Deark.
2 // Copyright (C) 2016 Jason Summers
3 // See the file COPYING for terms of use.
7 #include <deark-config.h>
8 #include <deark-private.h>
9 DE_DECLARE_MODULE(de_module_msp
);
11 typedef struct localctx_struct
{
17 static void do_ver1(deark
*c
, lctx
*d
)
21 // TODO: Are version-1 MSP files padded this way?
22 // (Maybe the width is always a multiple of 8, so it doesn't matter.)
23 src_rowspan
= (d
->width
+7)/8;
25 de_convert_and_write_image_bilevel(c
->infile
, 32,
26 d
->width
, d
->height
, src_rowspan
, 0, NULL
, 0);
29 static void do_decompress_scanline(deark
*c
, lctx
*d
, de_bitmap
*img
,
30 i64 rownum
, i64 rowoffset
, i64 bytes_in_row
)
37 de_dbg2(c
, "decompressing row %d", (int)rownum
);
40 d
->rowbuf
= dbuf_create_membuf(c
, (d
->width
+7)/8, 1);
43 dbuf_empty(d
->rowbuf
);
45 // Read the compressed data byte by byte
47 while(i
<bytes_in_row
) {
48 runtype
= de_getbyte(rowoffset
+i
);
51 runcount
= (i64
)de_getbyte(rowoffset
+i
);
53 value
= de_getbyte(rowoffset
+i
);
55 // write value runcount times
56 de_dbg2(c
, "compressed, %d bytes of %d", (int)runcount
, value
);
57 dbuf_write_run(d
->rowbuf
, value
, runcount
);
60 runcount
= (i64
)runtype
;
61 de_dbg2(c
, "%d bytes uncompressed", (int)runcount
);
62 dbuf_copy(c
->infile
, rowoffset
+i
, runcount
, d
->rowbuf
);
67 de_convert_row_bilevel(d
->rowbuf
, 0, img
, rownum
, 0);
70 static void do_ver2(deark
*c
, lctx
*d
)
75 de_bitmap
*img
= NULL
;
77 rowoffset
= de_mallocarray(c
, d
->height
, sizeof(i64
));
78 rowsize
= de_mallocarray(c
, d
->height
, sizeof(i64
));
80 // Read the scanline map, and record the row sizes.
81 for(j
=0; j
<d
->height
; j
++) {
82 rowsize
[j
] = de_getu16le(32+2*j
);
85 // Calculate the position, in the file, of each row.
86 for(j
=0; j
<d
->height
; j
++) {
88 rowoffset
[j
] = 32 + 2*d
->height
;
90 rowoffset
[j
] = rowoffset
[j
-1] + rowsize
[j
-1];
91 de_dbg2(c
, "row %d offset=%d size=%d", (int)j
, (int)rowoffset
[j
], (int)rowsize
[j
]);
94 img
= de_bitmap_create(c
, d
->width
, d
->height
, 1);
96 for(j
=0; j
<d
->height
; j
++) {
97 do_decompress_scanline(c
, d
, img
, j
, rowoffset
[j
], rowsize
[j
]);
100 de_bitmap_write_to_file(img
, NULL
, 0);
103 de_free(c
, rowoffset
);
104 dbuf_close(d
->rowbuf
);
106 de_bitmap_destroy(img
);
109 static void de_run_msp(deark
*c
, de_module_params
*mparams
)
113 d
= de_malloc(c
, sizeof(lctx
));
115 d
->ver
= de_getbyte(0) == 0x4c ? 2 : 1;
116 de_dbg(c
, "version: %d", d
->ver
);
117 de_declare_fmtf(c
, "MS Paint v%d", d
->ver
);
119 d
->width
= de_getu16le(4);
120 d
->height
= de_getu16le(6);
121 de_dbg_dimensions(c
, d
->width
, d
->height
);
133 static int de_identify_msp(deark
*c
)
138 if(b
[0]==0x44 && b
[1]==0x61 && b
[2]==0x6e && b
[3]==0x4d)
140 if(b
[0]==0x4c && b
[1]==0x69 && b
[2]==0x6e && b
[3]==0x53)
145 void de_module_msp(deark
*c
, struct deark_module_info
*mi
)
148 mi
->desc
= "Microsoft Paint image";
149 mi
->run_fn
= de_run_msp
;
150 mi
->identify_fn
= de_identify_msp
;