nrg: Improved support for v2
[deark.git] / modules / printshop.c
blobbf6eb390e2b584e99cfd42ce9fcb9eff1b67e5ae
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 {
22 int fmt;
23 dbuf *namefile;
24 } lctx;
26 static void do_printshop_etc_image(deark *c, lctx *d, i64 imgnum,
27 i64 pos, i64 *bytes_consumed)
29 i64 width, height;
30 i64 rowspan;
31 i64 imgspan;
32 i64 imgoffset = 0;
33 de_finfo *fi = NULL;
34 u8 x;
36 *bytes_consumed = 0;
38 if(d->fmt==PRINTSHOP_FMT_SHP) {
39 x = de_getbyte(pos);
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.
45 imgoffset = 4;
46 imgspan = 4 + rowspan * height + 1;
47 if(pos+imgspan > c->infile->len) goto done;
49 else { // DAT or POG format
50 width = 88;
51 height = 52;
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);
58 de_dbg_indent(c, 1);
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);
74 de_dbg_indent(c, -1);
76 *bytes_consumed = imgspan;
77 done:
78 de_finfo_destroy(c, fi);
81 static void do_printshop_etc(deark *c, lctx *d)
83 i64 headersize = 0;
84 const char *namefile_fn = NULL;
85 i64 bytes_consumed;
86 i64 pos;
87 i64 img_count;
88 i64 num_images = 0;
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");
94 if(namefile_fn) {
95 d->namefile = dbuf_open_input_file(c, namefile_fn);
97 if(d->namefile) {
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;
105 headersize = 10;
107 else {
108 headersize = 0;
111 pos = headersize;
112 img_count = 0;
113 while(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;
119 img_count++;
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);
128 d->namefile = NULL;
131 static void de_run_printshop(deark *c, de_module_params *mparams)
133 lctx *d;
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);
138 de_free(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
145 // 0x00 or 0x1a.
147 if(de_input_file_has_ext(c, "dat")) {
148 if((c->infile->len % 572)==0) {
149 return 10;
152 return 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)
169 lctx *d;
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);
174 de_free(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) {
181 return 90;
183 else {
184 return 10;
187 return 0;
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)
207 lctx *d;
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);
212 de_free(c, d);
215 static int de_identify_printmaster(deark *c)
217 u8 b[4];
218 int sdr_ext;
220 sdr_ext = de_input_file_has_ext(c, "sdr");
221 de_read(b, 0, 4);
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;
227 return 0;
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;