1 // This file is part of Deark.
2 // Copyright (C) 2016 Jason Summers
3 // See the file COPYING for terms of use.
5 // Old Print Shop and PrintMaster formats
7 #include <deark-config.h>
8 #include <deark-private.h>
9 DE_DECLARE_MODULE(de_module_printshop
);
10 DE_DECLARE_MODULE(de_module_newprintshop
);
11 DE_DECLARE_MODULE(de_module_printmaster
);
13 // **************************************************************************
14 // The Print Shop .DAT/.NAM format
15 // **************************************************************************
17 #define PRINTSHOP_FMT_DAT 1
18 #define PRINTSHOP_FMT_POG 2
19 #define PRINTSHOP_FMT_SHP 3
21 typedef struct localctx_struct
{
26 static void do_printshop_etc_image(deark
*c
, lctx
*d
, i64 imgnum
,
27 i64 pos
, i64
*bytes_consumed
)
38 if(d
->fmt
==PRINTSHOP_FMT_SHP
) {
40 if(x
!=0x0b) goto done
; // No more images?
41 height
= (i64
)de_getbyte(pos
+1);
42 width
= (i64
)de_getbyte(pos
+2);
43 if(width
==0 || height
==0) goto done
;
44 rowspan
= (width
+7)/8; // This is just a guess.
46 imgspan
= 4 + rowspan
* height
+ 1;
47 if(pos
+imgspan
> c
->infile
->len
) goto done
;
49 else { // DAT or POG format
52 rowspan
= (width
+7)/8;
53 imgspan
= rowspan
* height
;
54 if(pos
+imgspan
> c
->infile
->len
) goto done
; // Reached end of file
57 de_dbg(c
, "image[%d] at %d, %d"DE_CHAR_TIMES
"%d", (int)imgnum
, (int)pos
, (int)width
, (int)height
);
60 fi
= de_finfo_create(c
);
62 if(d
->namefile
&& (d
->namefile
->len
>= (imgnum
+1)*16)) {
63 de_ucstring
*name
= NULL
;
64 name
= ucstring_create(c
);
65 dbuf_read_to_ucstring(d
->namefile
, imgnum
*16, 16, name
, DE_CONVFLAG_STOP_AT_NUL
, DE_ENCODING_ASCII
);
66 de_dbg(c
, "name: \"%s\"", ucstring_getpsz(name
));
67 de_finfo_set_name_from_ucstring(c
, fi
, name
, 0);
68 ucstring_destroy(name
);
71 de_convert_and_write_image_bilevel(c
->infile
, pos
+ imgoffset
,
72 width
, height
, rowspan
, DE_CVTF_WHITEISZERO
, fi
, 0);
76 *bytes_consumed
= imgspan
;
78 de_finfo_destroy(c
, fi
);
81 static void do_printshop_etc(deark
*c
, lctx
*d
)
84 const char *namefile_fn
= NULL
;
89 int num_images_is_known
= 0;
91 namefile_fn
= de_get_ext_option(c
, "namefile");
92 if(!namefile_fn
) namefile_fn
= de_get_ext_option(c
, "file2");
95 d
->namefile
= dbuf_open_input_file(c
, namefile_fn
);
98 de_dbg(c
, "Using name file: %s", namefile_fn
);
101 if(d
->fmt
== PRINTSHOP_FMT_POG
) {
102 num_images
= de_getu16le(8);
103 de_dbg(c
, "number of images: %d", (int)num_images
);
104 num_images_is_known
= 1;
114 if(num_images_is_known
&& (img_count
>= num_images
)) break;
115 if(pos
>= c
->infile
->len
) break;
116 do_printshop_etc_image(c
, d
, img_count
, pos
, &bytes_consumed
);
117 if(bytes_consumed
<1) break;
118 pos
+= bytes_consumed
;
122 if(num_images_is_known
&& (c
->infile
->len
- pos
)>=128) {
123 de_warn(c
, "%d bytes of data were ignored. This file may not have "
124 "been fully decoded.", (int)(c
->infile
->len
- pos
));
127 dbuf_close(d
->namefile
);
131 static void de_run_printshop(deark
*c
, de_module_params
*mparams
)
134 d
= de_malloc(c
, sizeof(lctx
));
135 d
->fmt
= PRINTSHOP_FMT_DAT
;
136 de_declare_fmt(c
, "The Print Shop (DAT/NAM)");
137 do_printshop_etc(c
, d
);
141 static int de_identify_printshop(deark
*c
)
143 // TODO: Check to see if the base filename begins with "gr".
144 // TODO: Check to see if the last [len mod 572] bytes of the file are either
147 if(de_input_file_has_ext(c
, "dat")) {
148 if((c
->infile
->len
% 572)==0) {
155 void de_module_printshop(deark
*c
, struct deark_module_info
*mi
)
157 mi
->id
= "printshop";
158 mi
->desc
= "The Print Shop .DAT/.NAM";
159 mi
->run_fn
= de_run_printshop
;
160 mi
->identify_fn
= de_identify_printshop
;
163 // **************************************************************************
164 // The New Print Shop .POG/.PNM format
165 // **************************************************************************
167 static void de_run_newprintshop(deark
*c
, de_module_params
*mparams
)
170 d
= de_malloc(c
, sizeof(lctx
));
171 d
->fmt
= PRINTSHOP_FMT_POG
;
172 de_declare_fmt(c
, "The New Print Shop (POG/PNM)");
173 do_printshop_etc(c
, d
);
177 static int de_identify_newprintshop(deark
*c
)
179 if(de_input_file_has_ext(c
, "pog")) {
180 if((c
->infile
->len
% 572)==10) {
190 void de_module_newprintshop(deark
*c
, struct deark_module_info
*mi
)
192 // There's no surefire way to distinguish between Print Shop and
193 // New Print Shop files, so it's more convenient to put them in separate
194 // modules (so the user can simply use -m to select the format).
195 mi
->id
= "newprintshop";
196 mi
->desc
= "The New Print Shop .POG/.PNM";
197 mi
->run_fn
= de_run_newprintshop
;
198 mi
->identify_fn
= de_identify_newprintshop
;
201 // **************************************************************************
202 // PrintMaster .SHP/.SDR format
203 // **************************************************************************
205 static void de_run_printmaster(deark
*c
, de_module_params
*mparams
)
208 d
= de_malloc(c
, sizeof(lctx
));
209 d
->fmt
= PRINTSHOP_FMT_SHP
;
210 de_declare_fmt(c
, "PrintMaster (SHP/SDR)");
211 do_printshop_etc(c
, d
);
215 static int de_identify_printmaster(deark
*c
)
220 sdr_ext
= de_input_file_has_ext(c
, "sdr");
222 if(!de_memcmp(b
, "\x0b\x34\x58", 3)) {
223 return sdr_ext
? 90 : 10;
225 if(!sdr_ext
) return 0;
226 if(b
[0]==0x0b) return 30;
230 void de_module_printmaster(deark
*c
, struct deark_module_info
*mi
)
232 mi
->id
= "printmaster";
233 mi
->desc
= "PrintMaster .SHP/.SDR";
234 mi
->run_fn
= de_run_printmaster
;
235 mi
->identify_fn
= de_identify_printmaster
;