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
{
22 static void de_run_eps_binary(deark
*c
)
24 i64 eps_offset
, eps_len
;
25 i64 wmf_offset
, wmf_len
;
26 i64 tiff_offset
, tiff_len
;
28 de_declare_fmt(c
, "EPS binary");
30 eps_offset
= de_getu32le(4);
31 eps_len
= de_getu32le(8);
32 wmf_offset
= de_getu32le(12);
33 wmf_len
= de_getu32le(16);
34 tiff_offset
= de_getu32le(20);
35 tiff_len
= de_getu32le(24);
38 de_dbg(c
, "Extracting EPS offs=%d len=%d", (int)eps_offset
, (int)eps_len
);
39 dbuf_create_file_from_slice(c
->infile
, eps_offset
, eps_len
, "eps", NULL
, 0);
42 de_dbg(c
, "Extracting WMF offs=%d len=%d", (int)wmf_offset
, (int)wmf_len
);
43 dbuf_create_file_from_slice(c
->infile
, wmf_offset
, wmf_len
, "preview.wmf", NULL
, DE_CREATEFLAG_IS_AUX
);
46 de_dbg(c
, "Extracting TIFF offs=%d len=%d", (int)tiff_offset
, (int)tiff_len
);
47 dbuf_create_file_from_slice(c
->infile
, tiff_offset
, tiff_len
, "preview.tif", NULL
, DE_CREATEFLAG_IS_AUX
);
51 static void process_hex_digit(deark
*c
, lctx
*d
, u8 hexdigit
, dbuf
*outf
)
56 x
= de_decode_hex_digit(hexdigit
, &errorflag
);
57 if(errorflag
) return; // Ignore non hex-digits
59 if(d
->hex_digit_count
%2 == 0) {
62 // Wait for the next hex digit
66 dbuf_writebyte(outf
, (d
->pending_byte
<<4) | x
);
71 static void convert_row_gray(dbuf
*f
, i64 fpos
, de_bitmap
*img
,
72 i64 rownum
, int depth
)
77 for(i
=0; i
<img
->width
; i
++) {
78 b
= de_get_bits_symbol(f
, depth
, fpos
, i
);
80 else if(depth
==2) b
*=85;
81 else if(depth
==4) b
*=17;
82 de_bitmap_setpixel_gray(img
, i
, rownum
, 255-b
);
86 static void do_decode_epsi_image(deark
*c
, lctx
*d
, i64 pos1
)
88 de_bitmap
*img
= NULL
;
90 i64 content_len
, total_len
;
97 d
->hex_digit_count
= 0;
99 tmpf
= dbuf_create_membuf(c
, d
->w
* d
->h
, 0);
101 // Convert from hex-encoded (base16) to binary.
102 for(i
=0; i
<d
->lines
; i
++) {
103 if(!dbuf_find_line(c
->infile
, pos
, &content_len
, &total_len
))
105 for(k
=0; k
<content_len
; k
++) {
106 process_hex_digit(c
, d
, de_getbyte(pos
+k
), tmpf
);
111 // Convert from binary to an image
113 img
= de_bitmap_create(c
, d
->w
, d
->h
, 1);
115 src_rowspan
= (d
->w
* d
->depth
+7)/8;
117 for(j
=0; j
<d
->h
; j
++) {
118 convert_row_gray(tmpf
, j
*src_rowspan
, img
, j
, (int)d
->depth
);
121 de_bitmap_write_to_file(img
, "preview", DE_CREATEFLAG_IS_AUX
);
122 de_bitmap_destroy(img
);
126 static void do_decode_epsi(deark
*c
, const char *hdrfields
, i64 pos1
)
128 int width
, height
, depth
, lines
;
132 d
= de_malloc(c
, sizeof(lctx
));
134 // EPSI is a text-based format, and deark isn't very good at text formats.
135 // But we'll give it a try.
137 ret
= de_sscanf(hdrfields
, " %d %d %d %d", &width
, &height
, &depth
, &lines
);
139 de_err(c
, "Failed to parse EPSI header line");
142 de_dbg(c
, "w=%d h=%d d=%d l=%d", width
, height
, depth
, lines
);
148 if(!de_good_image_dimensions(c
, d
->w
, d
->h
)) {
151 if(d
->depth
!=1 && d
->depth
!=2 && d
->depth
!=4 && d
->depth
!=8) {
152 de_err(c
, "Unsupported EPSI bit depth (%d)", (int)d
->depth
);
155 if(d
->lines
>100000 || d
->lines
<1) {
156 de_err(c
, "Bad EPSI header");
160 do_decode_epsi_image(c
, d
, pos1
);
166 static void de_run_eps_normal(deark
*c
)
170 i64 content_len
, total_len
;
172 de_declare_fmt(c
, "Encapsulated PostScript");
175 while(dbuf_find_line(c
->infile
, pos
, &content_len
, &total_len
)) {
176 de_dbg2(c
, "line: pos=%d c_len=%d t_len=%d", (int)pos
, (int)content_len
, (int)total_len
);
178 if(content_len
> (i64
)(sizeof(linebuf
)-1))
179 content_len
= sizeof(linebuf
)-1;
181 de_read(linebuf
, pos
, content_len
);
182 linebuf
[content_len
] = '\0';
184 if(!de_memcmp(linebuf
, "%%BeginPreview:", 15)) {
185 do_decode_epsi(c
, (const char*)(linebuf
+15), pos
+total_len
);
193 static void de_run_eps(deark
*c
, de_module_params
*mparams
)
197 de_read(b
, 0, (i64
)sizeof(b
));
199 if(b
[0]==0xc5 && b
[1]==0xd0) {
200 de_run_eps_binary(c
);
202 else if(b
[0]=='%' && b
[1]=='!') {
203 de_run_eps_normal(c
);
206 de_err(c
, "Not an EPS file");
210 static int de_identify_eps(deark
*c
)
213 de_read(b
, 0, (i64
)sizeof(b
));
215 if(b
[0]==0xc5 && b
[1]==0xd0 && b
[2]==0xd3 && b
[3]==0xc6)
218 if(!de_memcmp(b
, "%!PS-Adobe-", 11) &&
219 !de_memcmp(&b
[14], " EPSF-", 6) )
227 void de_module_eps(deark
*c
, struct deark_module_info
*mi
)
230 mi
->desc
= "Encapsulated PostScript";
231 mi
->desc2
= "extract preview image";
232 mi
->run_fn
= de_run_eps
;
233 mi
->identify_fn
= de_identify_eps
;