~ubuntu-branches/ubuntu/wily/python-imaging/wily

« back to all changes in this revision

Viewing changes to .pc/git-updates.diff/PIL/EpsImagePlugin.py

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2013-01-31 20:49:20 UTC
  • mfrom: (27.1.1 raring-proposed)
  • Revision ID: package-import@ubuntu.com-20130131204920-b5zshy6vgfvdionl
Tags: 1.1.7+1.7.8-1ubuntu1
Rewrite build dependencies to allow cross builds.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#
 
2
# The Python Imaging Library.
 
3
# $Id$
 
4
#
 
5
# EPS file handling
 
6
#
 
7
# History:
 
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)
 
14
#
 
15
# Copyright (c) 1997-2003 by Secret Labs AB.
 
16
# Copyright (c) 1995-2003 by Fredrik Lundh
 
17
#
 
18
# See the README file for information on usage and redistribution.
 
19
#
 
20
 
 
21
__version__ = "0.5"
 
22
 
 
23
import re, string
 
24
import Image, ImageFile
 
25
 
 
26
#
 
27
# --------------------------------------------------------------------
 
28
 
 
29
def i32(c):
 
30
    return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) + (ord(c[3])<<24)
 
31
 
 
32
def o32(i):
 
33
    return chr(i&255) + chr(i>>8&255) + chr(i>>16&255) + chr(i>>24&255)
 
34
 
 
35
split = re.compile(r"^%%([^:]*):[ \t]*(.*)[ \t]*$")
 
36
field = re.compile(r"^%[%!\w]([^:]*)[ \t]*$")
 
37
 
 
38
def Ghostscript(tile, size, fp):
 
39
    """Render an image using Ghostscript (Unix only)"""
 
40
 
 
41
    # Unpack decoder tile
 
42
    decoder, tile, offset, data = tile[0]
 
43
    length, bbox = data
 
44
 
 
45
    import tempfile, os
 
46
 
 
47
    file = tempfile.mktemp()
 
48
 
 
49
    # Build ghostscript command
 
50
    command = ["gs",
 
51
               "-q",                    # quite mode
 
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"]
 
57
 
 
58
    command = string.join(command)
 
59
 
 
60
    # push data through ghostscript
 
61
    try:
 
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]))
 
66
        fp.seek(offset)
 
67
        while length > 0:
 
68
            s = fp.read(8192)
 
69
            if not s:
 
70
                break
 
71
            length = length - len(s)
 
72
            gs.write(s)
 
73
        status = gs.close()
 
74
        if status:
 
75
            raise IOError("gs failed (status %d)" % status)
 
76
        im = Image.core.open_ppm(file)
 
77
    finally:
 
78
        try: os.unlink(file)
 
79
        except: pass
 
80
 
 
81
    return im
 
82
 
 
83
 
 
84
class PSFile:
 
85
    """Wrapper that treats either CR or LF as end of line."""
 
86
    def __init__(self, fp):
 
87
        self.fp = fp
 
88
        self.char = None
 
89
    def __getattr__(self, id):
 
90
        v = getattr(self.fp, id)
 
91
        setattr(self, id, v)
 
92
        return v
 
93
    def seek(self, offset, whence=0):
 
94
        self.char = None
 
95
        self.fp.seek(offset, whence)
 
96
    def tell(self):
 
97
        pos = self.fp.tell()
 
98
        if self.char:
 
99
            pos = pos - 1
 
100
        return pos
 
101
    def readline(self):
 
102
        s = ""
 
103
        if self.char:
 
104
            c = self.char
 
105
            self.char = None
 
106
        else:
 
107
            c = self.fp.read(1)
 
108
        while c not in "\r\n":
 
109
            s = s + c
 
110
            c = self.fp.read(1)
 
111
        if c == "\r":
 
112
            self.char = self.fp.read(1)
 
113
            if self.char == "\n":
 
114
                self.char = None
 
115
        return s + "\n"
 
116
 
 
117
 
 
118
def _accept(prefix):
 
119
    return prefix[:4] == "%!PS" or i32(prefix) == 0xC6D3D0C5L
 
120
 
 
121
##
 
122
# Image plugin for Encapsulated Postscript.  This plugin supports only
 
123
# a few variants of this format.
 
124
 
 
125
class EpsImageFile(ImageFile.ImageFile):
 
126
    """EPS File Parser for the Python Imaging Library"""
 
127
 
 
128
    format = "EPS"
 
129
    format_description = "Encapsulated Postscript"
 
130
 
 
131
    def _open(self):
 
132
 
 
133
        # FIXME: should check the first 512 bytes to see if this
 
134
        # really is necessary (platform-dependent, though...)
 
135
 
 
136
        fp = PSFile(self.fp)
 
137
 
 
138
        # HEAD
 
139
        s = fp.read(512)
 
140
        if s[:4] == "%!PS":
 
141
            offset = 0
 
142
            fp.seek(0, 2)
 
143
            length = fp.tell()
 
144
        elif i32(s) == 0xC6D3D0C5L:
 
145
            offset = i32(s[4:])
 
146
            length = i32(s[8:])
 
147
            fp.seek(offset)
 
148
        else:
 
149
            raise SyntaxError, "not an EPS file"
 
150
 
 
151
        fp.seek(offset)
 
152
 
 
153
        box = None
 
154
 
 
155
        self.mode = "RGB"
 
156
        self.size = 1, 1 # FIXME: huh?
 
157
 
 
158
        #
 
159
        # Load EPS header
 
160
 
 
161
        s = fp.readline()
 
162
 
 
163
        while s:
 
164
 
 
165
            if len(s) > 255:
 
166
                raise SyntaxError, "not an EPS file"
 
167
 
 
168
            if s[-2:] == '\r\n':
 
169
                s = s[:-2]
 
170
            elif s[-1:] == '\n':
 
171
                s = s[:-1]
 
172
 
 
173
            try:
 
174
                m = split.match(s)
 
175
            except re.error, v:
 
176
                raise SyntaxError, "not an EPS file"
 
177
 
 
178
            if m:
 
179
                k, v = m.group(1, 2)
 
180
                self.info[k] = v
 
181
                if k == "BoundingBox":
 
182
                    try:
 
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,
 
189
                                      (length, box))]
 
190
                    except:
 
191
                        pass
 
192
 
 
193
            else:
 
194
 
 
195
                m = field.match(s)
 
196
 
 
197
                if m:
 
198
                    k = m.group(1)
 
199
                    if k == "EndComments":
 
200
                        break
 
201
                    if k[:8] == "PS-Adobe":
 
202
                        self.info[k[:8]] = k[9:]
 
203
                    else:
 
204
                        self.info[k] = ""
 
205
                elif s[0] == '%':
 
206
                    # handle non-DSC Postscript comments that some
 
207
                    # tools mistakenly put in the Comments section
 
208
                    pass
 
209
                else:
 
210
                    raise IOError, "bad EPS header"
 
211
 
 
212
            s = fp.readline()
 
213
 
 
214
            if s[:1] != "%":
 
215
                break
 
216
 
 
217
 
 
218
        #
 
219
        # Scan for an "ImageData" descriptor
 
220
 
 
221
        while s[0] == "%":
 
222
 
 
223
            if len(s) > 255:
 
224
                raise SyntaxError, "not an EPS file"
 
225
 
 
226
            if s[-2:] == '\r\n':
 
227
                s = s[:-2]
 
228
            elif s[-1:] == '\n':
 
229
                s = s[:-1]
 
230
 
 
231
            if s[:11] == "%ImageData:":
 
232
 
 
233
                [x, y, bi, mo, z3, z4, en, id] =\
 
234
                    string.split(s[11:], maxsplit=7)
 
235
 
 
236
                x = int(x); y = int(y)
 
237
 
 
238
                bi = int(bi)
 
239
                mo = int(mo)
 
240
 
 
241
                en = int(en)
 
242
 
 
243
                if en == 1:
 
244
                    decoder = "eps_binary"
 
245
                elif en == 2:
 
246
                    decoder = "eps_hex"
 
247
                else:
 
248
                    break
 
249
                if bi != 8:
 
250
                    break
 
251
                if mo == 1:
 
252
                    self.mode = "L"
 
253
                elif mo == 2:
 
254
                    self.mode = "LAB"
 
255
                elif mo == 3:
 
256
                    self.mode = "RGB"
 
257
                else:
 
258
                    break
 
259
 
 
260
                if id[:1] == id[-1:] == '"':
 
261
                    id = id[1:-1]
 
262
 
 
263
                # Scan forward to the actual image data
 
264
                while 1:
 
265
                    s = fp.readline()
 
266
                    if not s:
 
267
                        break
 
268
                    if s[:len(id)] == id:
 
269
                        self.size = x, y
 
270
                        self.tile2 = [(decoder,
 
271
                                       (0, 0, x, y),
 
272
                                       fp.tell(),
 
273
                                       0)]
 
274
                        return
 
275
 
 
276
            s = fp.readline()
 
277
            if not s:
 
278
                break
 
279
 
 
280
        if not box:
 
281
            raise IOError, "cannot determine EPS bounding box"
 
282
 
 
283
    def load(self):
 
284
        # Load EPS via Ghostscript
 
285
        if not self.tile:
 
286
            return
 
287
        self.im = Ghostscript(self.tile, self.size, self.fp)
 
288
        self.mode = self.im.mode
 
289
        self.size = self.im.size
 
290
        self.tile = []
 
291
 
 
292
#
 
293
# --------------------------------------------------------------------
 
294
 
 
295
def _save(im, fp, filename, eps=1):
 
296
    """EPS Writer for the Python Imaging Library."""
 
297
 
 
298
    #
 
299
    # make sure image data is available
 
300
    im.load()
 
301
 
 
302
    #
 
303
    # determine postscript image mode
 
304
    if im.mode == "L":
 
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")
 
310
    else:
 
311
        raise ValueError, "image mode is not supported"
 
312
 
 
313
    if eps:
 
314
        #
 
315
        # write EPS header
 
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)
 
325
 
 
326
    #
 
327
    # image header
 
328
    fp.write("gsave\n")
 
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])
 
336
 
 
337
    ImageFile._save(im, fp, [("eps", (0,0)+im.size, 0, None)])
 
338
 
 
339
    fp.write("\n%%%%EndBinary\n")
 
340
    fp.write("grestore end\n")
 
341
    fp.flush()
 
342
 
 
343
#
 
344
# --------------------------------------------------------------------
 
345
 
 
346
Image.register_open(EpsImageFile.format, EpsImageFile, _accept)
 
347
 
 
348
Image.register_save(EpsImageFile.format, _save)
 
349
 
 
350
Image.register_extension(EpsImageFile.format, ".ps")
 
351
Image.register_extension(EpsImageFile.format, ".eps")
 
352
 
 
353
Image.register_mime(EpsImageFile.format, "application/postscript")