2
# The Python Imaging Library.
8
# 1995-09-01 fl Created (0.1)
9
# 1996-05-18 fl Don't choke on "atend" fields, Ghostscript interface (0.2)
10
# 1996-08-22 fl Don't choke on floating point BoundingBox values
11
# 1996-08-23 fl Handle files from Macintosh (0.3)
12
# 2001-02-17 fl Use 're' instead of 'regex' (Python 2.1) (0.4)
13
# 2003-09-07 fl Check gs.close status (from Federico Di Gregorio) (0.5)
15
# Copyright (c) 1997-2003 by Secret Labs AB.
16
# Copyright (c) 1995-2003 by Fredrik Lundh
18
# See the README file for information on usage and redistribution.
24
import Image, ImageFile
27
# --------------------------------------------------------------------
30
return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) + (ord(c[3])<<24)
33
return chr(i&255) + chr(i>>8&255) + chr(i>>16&255) + chr(i>>24&255)
35
split = re.compile(r"^%%([^:]*):[ \t]*(.*)[ \t]*$")
36
field = re.compile(r"^%[%!\w]([^:]*)[ \t]*$")
38
def Ghostscript(tile, size, fp):
39
"""Render an image using Ghostscript (Unix only)"""
42
decoder, tile, offset, data = tile[0]
47
file = tempfile.mktemp()
49
# Build ghostscript command
52
"-g%dx%d" % size, # set output geometry (pixels)
53
"-dNOPAUSE -dSAFER", # don't pause between pages, safe mode
54
"-sDEVICE=ppmraw", # ppm driver
55
"-sOutputFile=%s" % file,# output file
56
"- >/dev/null 2>/dev/null"]
58
command = string.join(command)
60
# push data through ghostscript
62
gs = os.popen(command, "w")
63
# adjust for image origin
64
if bbox[0] != 0 or bbox[1] != 0:
65
gs.write("%d %d translate\n" % (-bbox[0], -bbox[1]))
71
length = length - len(s)
75
raise IOError("gs failed (status %d)" % status)
76
im = Image.core.open_ppm(file)
85
"""Wrapper that treats either CR or LF as end of line."""
86
def __init__(self, fp):
89
def __getattr__(self, id):
90
v = getattr(self.fp, id)
93
def seek(self, offset, whence=0):
95
self.fp.seek(offset, whence)
108
while c not in "\r\n":
112
self.char = self.fp.read(1)
113
if self.char == "\n":
119
return prefix[:4] == "%!PS" or i32(prefix) == 0xC6D3D0C5L
122
# Image plugin for Encapsulated Postscript. This plugin supports only
123
# a few variants of this format.
125
class EpsImageFile(ImageFile.ImageFile):
126
"""EPS File Parser for the Python Imaging Library"""
129
format_description = "Encapsulated Postscript"
133
# FIXME: should check the first 512 bytes to see if this
134
# really is necessary (platform-dependent, though...)
144
elif i32(s) == 0xC6D3D0C5L:
149
raise SyntaxError, "not an EPS file"
156
self.size = 1, 1 # FIXME: huh?
166
raise SyntaxError, "not an EPS file"
176
raise SyntaxError, "not an EPS file"
181
if k == "BoundingBox":
183
# Note: The DSC spec says that BoundingBox
184
# fields should be integers, but some drivers
185
# put floating point values there anyway.
186
box = map(int, map(float, string.split(v)))
187
self.size = box[2] - box[0], box[3] - box[1]
188
self.tile = [("eps", (0,0) + self.size, offset,
199
if k == "EndComments":
201
if k[:8] == "PS-Adobe":
202
self.info[k[:8]] = k[9:]
206
# handle non-DSC Postscript comments that some
207
# tools mistakenly put in the Comments section
210
raise IOError, "bad EPS header"
219
# Scan for an "ImageData" descriptor
224
raise SyntaxError, "not an EPS file"
231
if s[:11] == "%ImageData:":
233
[x, y, bi, mo, z3, z4, en, id] =\
234
string.split(s[11:], maxsplit=7)
236
x = int(x); y = int(y)
244
decoder = "eps_binary"
260
if id[:1] == id[-1:] == '"':
263
# Scan forward to the actual image data
268
if s[:len(id)] == id:
270
self.tile2 = [(decoder,
281
raise IOError, "cannot determine EPS bounding box"
284
# Load EPS via Ghostscript
287
self.im = Ghostscript(self.tile, self.size, self.fp)
288
self.mode = self.im.mode
289
self.size = self.im.size
293
# --------------------------------------------------------------------
295
def _save(im, fp, filename, eps=1):
296
"""EPS Writer for the Python Imaging Library."""
299
# make sure image data is available
303
# determine postscript image mode
305
operator = (8, 1, "image")
306
elif im.mode == "RGB":
307
operator = (8, 3, "false 3 colorimage")
308
elif im.mode == "CMYK":
309
operator = (8, 4, "false 4 colorimage")
311
raise ValueError, "image mode is not supported"
316
fp.write("%!PS-Adobe-3.0 EPSF-3.0\n")
317
fp.write("%%Creator: PIL 0.1 EpsEncode\n")
318
#fp.write("%%CreationDate: %s"...)
319
fp.write("%%%%BoundingBox: 0 0 %d %d\n" % im.size)
320
fp.write("%%Pages: 1\n")
321
fp.write("%%EndComments\n")
322
fp.write("%%Page: 1 1\n")
323
fp.write("%%ImageData: %d %d " % im.size)
324
fp.write("%d %d 0 1 1 \"%s\"\n" % operator)
329
fp.write("10 dict begin\n")
330
fp.write("/buf %d string def\n" % (im.size[0] * operator[1]))
331
fp.write("%d %d scale\n" % im.size)
332
fp.write("%d %d 8\n" % im.size) # <= bits
333
fp.write("[%d 0 0 -%d 0 %d]\n" % (im.size[0], im.size[1], im.size[1]))
334
fp.write("{ currentfile buf readhexstring pop } bind\n")
335
fp.write("%s\n" % operator[2])
337
ImageFile._save(im, fp, [("eps", (0,0)+im.size, 0, None)])
339
fp.write("\n%%%%EndBinary\n")
340
fp.write("grestore end\n")
344
# --------------------------------------------------------------------
346
Image.register_open(EpsImageFile.format, EpsImageFile, _accept)
348
Image.register_save(EpsImageFile.format, _save)
350
Image.register_extension(EpsImageFile.format, ".ps")
351
Image.register_extension(EpsImageFile.format, ".eps")
353
Image.register_mime(EpsImageFile.format, "application/postscript")