~ubuntu-branches/ubuntu/saucy/python-imaging/saucy-proposed

« back to all changes in this revision

Viewing changes to .pc/git-updates.diff/PIL/ImageDraw.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
# drawing interface operations
 
6
#
 
7
# History:
 
8
# 1996-04-13 fl   Created (experimental)
 
9
# 1996-08-07 fl   Filled polygons, ellipses.
 
10
# 1996-08-13 fl   Added text support
 
11
# 1998-06-28 fl   Handle I and F images
 
12
# 1998-12-29 fl   Added arc; use arc primitive to draw ellipses
 
13
# 1999-01-10 fl   Added shape stuff (experimental)
 
14
# 1999-02-06 fl   Added bitmap support
 
15
# 1999-02-11 fl   Changed all primitives to take options
 
16
# 1999-02-20 fl   Fixed backwards compatibility
 
17
# 2000-10-12 fl   Copy on write, when necessary
 
18
# 2001-02-18 fl   Use default ink for bitmap/text also in fill mode
 
19
# 2002-10-24 fl   Added support for CSS-style color strings
 
20
# 2002-12-10 fl   Added experimental support for RGBA-on-RGB drawing
 
21
# 2002-12-11 fl   Refactored low-level drawing API (work in progress)
 
22
# 2004-08-26 fl   Made Draw() a factory function, added getdraw() support
 
23
# 2004-09-04 fl   Added width support to line primitive
 
24
# 2004-09-10 fl   Added font mode handling
 
25
# 2006-06-19 fl   Added font bearing support (getmask2)
 
26
#
 
27
# Copyright (c) 1997-2006 by Secret Labs AB
 
28
# Copyright (c) 1996-2006 by Fredrik Lundh
 
29
#
 
30
# See the README file for information on usage and redistribution.
 
31
#
 
32
 
 
33
import Image, ImageColor
 
34
 
 
35
try:
 
36
    import warnings
 
37
except ImportError:
 
38
    warnings = None
 
39
 
 
40
##
 
41
# A simple 2D drawing interface for PIL images.
 
42
# <p>
 
43
# Application code should use the <b>Draw</b> factory, instead of
 
44
# directly.
 
45
 
 
46
class ImageDraw:
 
47
 
 
48
    ##
 
49
    # Create a drawing instance.
 
50
    #
 
51
    # @param im The image to draw in.
 
52
    # @param mode Optional mode to use for color values.  For RGB
 
53
    #    images, this argument can be RGB or RGBA (to blend the
 
54
    #    drawing into the image).  For all other modes, this argument
 
55
    #    must be the same as the image mode.  If omitted, the mode
 
56
    #    defaults to the mode of the image.
 
57
 
 
58
    def __init__(self, im, mode=None):
 
59
        im.load()
 
60
        if im.readonly:
 
61
            im._copy() # make it writable
 
62
        blend = 0
 
63
        if mode is None:
 
64
            mode = im.mode
 
65
        if mode != im.mode:
 
66
            if mode == "RGBA" and im.mode == "RGB":
 
67
                blend = 1
 
68
            else:
 
69
                raise ValueError("mode mismatch")
 
70
        if mode == "P":
 
71
            self.palette = im.palette
 
72
        else:
 
73
            self.palette = None
 
74
        self.im = im.im
 
75
        self.draw = Image.core.draw(self.im, blend)
 
76
        self.mode = mode
 
77
        if mode in ("I", "F"):
 
78
            self.ink = self.draw.draw_ink(1, mode)
 
79
        else:
 
80
            self.ink = self.draw.draw_ink(-1, mode)
 
81
        if mode in ("1", "P", "I", "F"):
 
82
            # FIXME: fix Fill2 to properly support matte for I+F images
 
83
            self.fontmode = "1"
 
84
        else:
 
85
            self.fontmode = "L" # aliasing is okay for other modes
 
86
        self.fill = 0
 
87
        self.font = None
 
88
 
 
89
    ##
 
90
    # Set the default pen color.
 
91
 
 
92
    def setink(self, ink):
 
93
        # compatibility
 
94
        if warnings:
 
95
            warnings.warn(
 
96
                "'setink' is deprecated; use keyword arguments instead",
 
97
                DeprecationWarning, stacklevel=2
 
98
                )
 
99
        if Image.isStringType(ink):
 
100
            ink = ImageColor.getcolor(ink, self.mode)
 
101
        if self.palette and not Image.isNumberType(ink):
 
102
            ink = self.palette.getcolor(ink)
 
103
        self.ink = self.draw.draw_ink(ink, self.mode)
 
104
 
 
105
    ##
 
106
    # Set the default background color.
 
107
 
 
108
    def setfill(self, onoff):
 
109
        # compatibility
 
110
        if warnings:
 
111
            warnings.warn(
 
112
                "'setfill' is deprecated; use keyword arguments instead",
 
113
                DeprecationWarning, stacklevel=2
 
114
                )
 
115
        self.fill = onoff
 
116
 
 
117
    ##
 
118
    # Set the default font.
 
119
 
 
120
    def setfont(self, font):
 
121
        # compatibility
 
122
        self.font = font
 
123
 
 
124
    ##
 
125
    # Get the current default font.
 
126
 
 
127
    def getfont(self):
 
128
        if not self.font:
 
129
            # FIXME: should add a font repository
 
130
            import ImageFont
 
131
            self.font = ImageFont.load_default()
 
132
        return self.font
 
133
 
 
134
    def _getink(self, ink, fill=None):
 
135
        if ink is None and fill is None:
 
136
            if self.fill:
 
137
                fill = self.ink
 
138
            else:
 
139
                ink = self.ink
 
140
        else:
 
141
            if ink is not None:
 
142
                if Image.isStringType(ink):
 
143
                    ink = ImageColor.getcolor(ink, self.mode)
 
144
                if self.palette and not Image.isNumberType(ink):
 
145
                    ink = self.palette.getcolor(ink)
 
146
                ink = self.draw.draw_ink(ink, self.mode)
 
147
            if fill is not None:
 
148
                if Image.isStringType(fill):
 
149
                    fill = ImageColor.getcolor(fill, self.mode)
 
150
                if self.palette and not Image.isNumberType(fill):
 
151
                    fill = self.palette.getcolor(fill)
 
152
                fill = self.draw.draw_ink(fill, self.mode)
 
153
        return ink, fill
 
154
 
 
155
    ##
 
156
    # Draw an arc.
 
157
 
 
158
    def arc(self, xy, start, end, fill=None):
 
159
        ink, fill = self._getink(fill)
 
160
        if ink is not None:
 
161
            self.draw.draw_arc(xy, start, end, ink)
 
162
 
 
163
    ##
 
164
    # Draw a bitmap.
 
165
 
 
166
    def bitmap(self, xy, bitmap, fill=None):
 
167
        bitmap.load()
 
168
        ink, fill = self._getink(fill)
 
169
        if ink is None:
 
170
            ink = fill
 
171
        if ink is not None:
 
172
            self.draw.draw_bitmap(xy, bitmap.im, ink)
 
173
 
 
174
    ##
 
175
    # Draw a chord.
 
176
 
 
177
    def chord(self, xy, start, end, fill=None, outline=None):
 
178
        ink, fill = self._getink(outline, fill)
 
179
        if fill is not None:
 
180
            self.draw.draw_chord(xy, start, end, fill, 1)
 
181
        if ink is not None:
 
182
            self.draw.draw_chord(xy, start, end, ink, 0)
 
183
 
 
184
    ##
 
185
    # Draw an ellipse.
 
186
 
 
187
    def ellipse(self, xy, fill=None, outline=None):
 
188
        ink, fill = self._getink(outline, fill)
 
189
        if fill is not None:
 
190
            self.draw.draw_ellipse(xy, fill, 1)
 
191
        if ink is not None:
 
192
            self.draw.draw_ellipse(xy, ink, 0)
 
193
 
 
194
    ##
 
195
    # Draw a line, or a connected sequence of line segments.
 
196
 
 
197
    def line(self, xy, fill=None, width=0):
 
198
        ink, fill = self._getink(fill)
 
199
        if ink is not None:
 
200
            self.draw.draw_lines(xy, ink, width)
 
201
 
 
202
    ##
 
203
    # (Experimental) Draw a shape.
 
204
 
 
205
    def shape(self, shape, fill=None, outline=None):
 
206
        # experimental
 
207
        shape.close()
 
208
        ink, fill = self._getink(outline, fill)
 
209
        if fill is not None:
 
210
            self.draw.draw_outline(shape, fill, 1)
 
211
        if ink is not None:
 
212
            self.draw.draw_outline(shape, ink, 0)
 
213
 
 
214
    ##
 
215
    # Draw a pieslice.
 
216
 
 
217
    def pieslice(self, xy, start, end, fill=None, outline=None):
 
218
        ink, fill = self._getink(outline, fill)
 
219
        if fill is not None:
 
220
            self.draw.draw_pieslice(xy, start, end, fill, 1)
 
221
        if ink is not None:
 
222
            self.draw.draw_pieslice(xy, start, end, ink, 0)
 
223
 
 
224
    ##
 
225
    # Draw one or more individual pixels.
 
226
 
 
227
    def point(self, xy, fill=None):
 
228
        ink, fill = self._getink(fill)
 
229
        if ink is not None:
 
230
            self.draw.draw_points(xy, ink)
 
231
 
 
232
    ##
 
233
    # Draw a polygon.
 
234
 
 
235
    def polygon(self, xy, fill=None, outline=None):
 
236
        ink, fill = self._getink(outline, fill)
 
237
        if fill is not None:
 
238
            self.draw.draw_polygon(xy, fill, 1)
 
239
        if ink is not None:
 
240
            self.draw.draw_polygon(xy, ink, 0)
 
241
 
 
242
    ##
 
243
    # Draw a rectangle.
 
244
 
 
245
    def rectangle(self, xy, fill=None, outline=None):
 
246
        ink, fill = self._getink(outline, fill)
 
247
        if fill is not None:
 
248
            self.draw.draw_rectangle(xy, fill, 1)
 
249
        if ink is not None:
 
250
            self.draw.draw_rectangle(xy, ink, 0)
 
251
 
 
252
    ##
 
253
    # Draw text.
 
254
 
 
255
    def text(self, xy, text, fill=None, font=None, anchor=None):
 
256
        ink, fill = self._getink(fill)
 
257
        if font is None:
 
258
            font = self.getfont()
 
259
        if ink is None:
 
260
            ink = fill
 
261
        if ink is not None:
 
262
            try:
 
263
                mask, offset = font.getmask2(text, self.fontmode)
 
264
                xy = xy[0] + offset[0], xy[1] + offset[1]
 
265
            except AttributeError:
 
266
                try:
 
267
                    mask = font.getmask(text, self.fontmode)
 
268
                except TypeError:
 
269
                    mask = font.getmask(text)
 
270
            self.draw.draw_bitmap(xy, mask, ink)
 
271
 
 
272
    ##
 
273
    # Get the size of a given string, in pixels.
 
274
 
 
275
    def textsize(self, text, font=None):
 
276
        if font is None:
 
277
            font = self.getfont()
 
278
        return font.getsize(text)
 
279
 
 
280
##
 
281
# A simple 2D drawing interface for PIL images.
 
282
#
 
283
# @param im The image to draw in.
 
284
# @param mode Optional mode to use for color values.  For RGB
 
285
#    images, this argument can be RGB or RGBA (to blend the
 
286
#    drawing into the image).  For all other modes, this argument
 
287
#    must be the same as the image mode.  If omitted, the mode
 
288
#    defaults to the mode of the image.
 
289
 
 
290
def Draw(im, mode=None):
 
291
    try:
 
292
        return im.getdraw(mode)
 
293
    except AttributeError:
 
294
        return ImageDraw(im, mode)
 
295
 
 
296
# experimental access to the outline API
 
297
try:
 
298
    Outline = Image.core.outline
 
299
except:
 
300
    Outline = None
 
301
 
 
302
##
 
303
# (Experimental) A more advanced 2D drawing interface for PIL images,
 
304
# based on the WCK interface.
 
305
#
 
306
# @param im The image to draw in.
 
307
# @param hints An optional list of hints.
 
308
# @return A (drawing context, drawing resource factory) tuple.
 
309
 
 
310
def getdraw(im=None, hints=None):
 
311
    # FIXME: this needs more work!
 
312
    # FIXME: come up with a better 'hints' scheme.
 
313
    handler = None
 
314
    if not hints or "nicest" in hints:
 
315
        try:
 
316
            import _imagingagg
 
317
            handler = _imagingagg
 
318
        except ImportError:
 
319
            pass
 
320
    if handler is None:
 
321
        import ImageDraw2
 
322
        handler = ImageDraw2
 
323
    if im:
 
324
        im = handler.Draw(im)
 
325
    return im, handler
 
326
 
 
327
##
 
328
# (experimental) Fills a bounded region with a given color.
 
329
#
 
330
# @param image Target image.
 
331
# @param xy Seed position (a 2-item coordinate tuple).
 
332
# @param value Fill color.
 
333
# @param border Optional border value.  If given, the region consists of
 
334
#     pixels with a color different from the border color.  If not given,
 
335
#     the region consists of pixels having the same color as the seed
 
336
#     pixel.
 
337
 
 
338
def floodfill(image, xy, value, border=None):
 
339
    "Fill bounded region."
 
340
    # based on an implementation by Eric S. Raymond
 
341
    pixel = image.load()
 
342
    x, y = xy
 
343
    try:
 
344
        background = pixel[x, y]
 
345
        if background == value:
 
346
            return # seed point already has fill color
 
347
        pixel[x, y] = value
 
348
    except IndexError:
 
349
        return # seed point outside image
 
350
    edge = [(x, y)]
 
351
    if border is None:
 
352
        while edge:
 
353
            newedge = []
 
354
            for (x, y) in edge:
 
355
                for (s, t) in ((x+1, y), (x-1, y), (x, y+1), (x, y-1)):
 
356
                    try:
 
357
                        p = pixel[s, t]
 
358
                    except IndexError:
 
359
                        pass
 
360
                    else:
 
361
                        if p == background:
 
362
                            pixel[s, t] = value
 
363
                            newedge.append((s, t))
 
364
            edge = newedge
 
365
    else:
 
366
        while edge:
 
367
            newedge = []
 
368
            for (x, y) in edge:
 
369
                for (s, t) in ((x+1, y), (x-1, y), (x, y+1), (x, y-1)):
 
370
                    try:
 
371
                        p = pixel[s, t]
 
372
                    except IndexError:
 
373
                        pass
 
374
                    else:
 
375
                        if p != value and p != border:
 
376
                            pixel[s, t] = value
 
377
                            newedge.append((s, t))
 
378
            edge = newedge