1 // This file is part of Deark.
2 // Copyright (C) 2016 Jason Summers
3 // See the file COPYING for terms of use.
5 // Encapsulated PostScript
7 #include <deark-config.h>
8 #include <deark-private.h>
9 DE_DECLARE_MODULE(de_module_eps
);
11 typedef struct localctx_struct
{
26 static void de_run_eps_binary(deark
*c
)
28 i64 eps_offset
, eps_len
;
29 i64 wmf_offset
, wmf_len
;
30 i64 tiff_offset
, tiff_len
;
32 de_declare_fmt(c
, "EPS binary");
34 eps_offset
= de_getu32le(4);
35 eps_len
= de_getu32le(8);
36 wmf_offset
= de_getu32le(12);
37 wmf_len
= de_getu32le(16);
38 tiff_offset
= de_getu32le(20);
39 tiff_len
= de_getu32le(24);
42 de_dbg(c
, "Extracting EPS offs=%d len=%d", (int)eps_offset
, (int)eps_len
);
43 dbuf_create_file_from_slice(c
->infile
, eps_offset
, eps_len
, "eps", NULL
, 0);
46 de_dbg(c
, "Extracting WMF offs=%d len=%d", (int)wmf_offset
, (int)wmf_len
);
47 dbuf_create_file_from_slice(c
->infile
, wmf_offset
, wmf_len
, "preview.wmf", NULL
, DE_CREATEFLAG_IS_AUX
);
50 de_dbg(c
, "Extracting TIFF offs=%d len=%d", (int)tiff_offset
, (int)tiff_len
);
51 dbuf_create_file_from_slice(c
->infile
, tiff_offset
, tiff_len
, "preview.tif", NULL
, DE_CREATEFLAG_IS_AUX
);
55 static void process_hex_digit(deark
*c
, lctx
*d
, u8 hexdigit
, dbuf
*outf
)
60 x
= de_decode_hex_digit(hexdigit
, &errorflag
);
61 if(errorflag
) return; // Ignore non hex-digits
63 if(d
->hex_digit_count
%2 == 0) {
66 // Wait for the next hex digit
70 dbuf_writebyte(outf
, (d
->pending_byte
<<4) | x
);
75 static void do_decode_epsi_image(deark
*c
, lctx
*d
, i64 pos1
)
77 de_bitmap
*img
= NULL
;
79 i64 content_len
, total_len
;
85 d
->hex_digit_count
= 0;
87 tmpf
= dbuf_create_membuf(c
, d
->pdwidth
* d
->h
, 0);
89 // Convert from hex-encoded (base16) to binary.
90 for(i
=0; i
<d
->lines
; i
++) {
91 if(!dbuf_find_line(c
->infile
, pos
, &content_len
, &total_len
))
93 for(k
=0; k
<content_len
; k
++) {
94 process_hex_digit(c
, d
, de_getbyte(pos
+k
), tmpf
);
99 // Convert from binary to an image
101 img
= de_bitmap_create2(c
, d
->npwidth
, d
->pdwidth
, d
->h
, 1);
103 de_make_grayscale_palette(d
->pal
, 1ULL<<d
->depth
, 0x1);
104 de_convert_image_paletted(tmpf
, 0, d
->depth
, d
->src_rowspan
, d
->pal
, img
, 0);
106 createflags
= DE_CREATEFLAG_IS_AUX
;
108 createflags
|= DE_CREATEFLAG_IS_BWIMG
;
111 createflags
|= DE_CREATEFLAG_OPT_IMAGE
;
113 de_bitmap_write_to_file(img
, "preview", createflags
);
114 de_bitmap_destroy(img
);
118 static void do_decode_epsi(deark
*c
, const char *hdrfields
, i64 pos1
)
120 int width
, height
, depth
, lines
;
124 d
= de_malloc(c
, sizeof(lctx
));
126 // EPSI is a text-based format, and deark isn't very good at text formats.
127 // But we'll give it a try.
129 ret
= de_sscanf(hdrfields
, " %d %d %d %d", &width
, &height
, &depth
, &lines
);
131 de_err(c
, "Failed to parse EPSI header line");
134 de_dbg(c
, "w=%d h=%d d=%d l=%d", width
, height
, depth
, lines
);
140 if(d
->depth
!=1 && d
->depth
!=2 && d
->depth
!=4 && d
->depth
!=8) {
141 de_err(c
, "Unsupported EPSI bit depth (%d)", (int)d
->depth
);
145 d
->src_rowspan
= (d
->npwidth
* d
->depth
+7)/8;
146 d
->pdwidth
= (d
->src_rowspan
*8) / d
->depth
;
148 if(!de_good_image_dimensions(c
, d
->pdwidth
, d
->h
)) {
151 if(d
->lines
>100000 || d
->lines
<1) {
152 de_err(c
, "Bad EPSI header");
156 do_decode_epsi_image(c
, d
, pos1
);
162 static void de_run_eps_normal(deark
*c
)
166 i64 content_len
, total_len
;
168 de_declare_fmt(c
, "Encapsulated PostScript");
171 while(dbuf_find_line(c
->infile
, pos
, &content_len
, &total_len
)) {
172 de_dbg2(c
, "line: pos=%d c_len=%d t_len=%d", (int)pos
, (int)content_len
, (int)total_len
);
174 if(content_len
> (i64
)(sizeof(linebuf
)-1))
175 content_len
= sizeof(linebuf
)-1;
177 de_read(linebuf
, pos
, content_len
);
178 linebuf
[content_len
] = '\0';
180 if(!de_memcmp(linebuf
, "%%BeginPreview:", 15)) {
181 do_decode_epsi(c
, (const char*)(linebuf
+15), pos
+total_len
);
189 static void de_run_eps(deark
*c
, de_module_params
*mparams
)
193 de_read(b
, 0, (i64
)sizeof(b
));
195 if(b
[0]==0xc5 && b
[1]==0xd0) {
196 de_run_eps_binary(c
);
198 else if(b
[0]=='%' && b
[1]=='!') {
199 de_run_eps_normal(c
);
202 de_err(c
, "Not an EPS file");
206 static int de_identify_eps(deark
*c
)
209 de_read(b
, 0, (i64
)sizeof(b
));
211 if(b
[0]==0xc5 && b
[1]==0xd0 && b
[2]==0xd3 && b
[3]==0xc6)
214 if(!de_memcmp(b
, "%!PS-Adobe-", 11) &&
215 !de_memcmp(&b
[14], " EPSF-", 6) )
223 void de_module_eps(deark
*c
, struct deark_module_info
*mi
)
226 mi
->desc
= "Encapsulated PostScript";
227 mi
->desc2
= "extract preview image";
228 mi
->run_fn
= de_run_eps
;
229 mi
->identify_fn
= de_identify_eps
;