Fredrik Lundh is sharing code with you
Bitbucket is a code hosting site. Unlimited public and private repositories. Free for small teams.
Don't show this againpil-2009-raclette / PIL / Image.py
- commit
- 454b4d2672f3
- parent
- 64f9636f4d92
- branch
- default
- tags
- pil-117-20090317, pil-117a1-20090317
Don't try to open files twice if plugins are already loaded.
1 |
770a9717f387
|
# |
2 |
770a9717f387
|
# The Python Imaging Library. |
3 |
d6bf12873cb1
|
# $Id$ |
4 |
770a9717f387
|
# |
5 |
770a9717f387
|
# the Image class wrapper |
6 |
770a9717f387
|
# |
7 |
770a9717f387
|
# partial release history: |
8 |
770a9717f387
|
# 1995-09-09 fl Created |
9 |
770a9717f387
|
# 1996-03-11 fl PIL release 0.0 (proof of concept) |
10 |
770a9717f387
|
# 1996-04-30 fl PIL release 0.1b1 |
11 |
770a9717f387
|
# 1999-07-28 fl PIL release 1.0 final |
12 |
770a9717f387
|
# 2000-06-07 fl PIL release 1.1 |
13 |
770a9717f387
|
# 2000-10-20 fl PIL release 1.1.1 |
14 |
770a9717f387
|
# 2001-05-07 fl PIL release 1.1.2 |
15 |
770a9717f387
|
# 2002-03-15 fl PIL release 1.1.3 |
16 |
770a9717f387
|
# 2003-05-10 fl PIL release 1.1.4 |
17 |
770a9717f387
|
# 2005-03-28 fl PIL release 1.1.5 |
18 |
770a9717f387
|
# 2006-12-02 fl PIL release 1.1.6 |
19 |
e3ee359e6767
|
# 2009-03-XX fl PIL release 1.1.7 |
20 |
770a9717f387
|
# |
21 |
e3ee359e6767
|
# Copyright (c) 1997-2009 by Secret Labs AB. All rights reserved. |
22 |
e3ee359e6767
|
# Copyright (c) 1995-2009 by Fredrik Lundh. |
23 |
770a9717f387
|
# |
24 |
770a9717f387
|
# See the README file for information on usage and redistribution. |
25 |
770a9717f387
|
# |
26 |
770a9717f387
|
|
27 |
e3ee359e6767
|
VERSION = "1.1.7a0" |
28 |
770a9717f387
|
|
29 |
770a9717f387
|
try: |
30 |
770a9717f387
|
import warnings |
31 |
770a9717f387
|
except ImportError: |
32 |
770a9717f387
|
warnings = None |
33 |
770a9717f387
|
|
34 |
770a9717f387
|
class _imaging_not_installed: |
35 |
770a9717f387
|
# module placeholder |
36 |
770a9717f387
|
def __getattr__(self, id): |
37 |
770a9717f387
|
raise ImportError("The _imaging C module is not installed") |
38 |
770a9717f387
|
|
39 |
770a9717f387
|
try: |
40 |
770a9717f387
|
# give Tk a chance to set up the environment, in case we're |
41 |
770a9717f387
|
# using an _imaging module linked against libtcl/libtk (use |
42 |
770a9717f387
|
# __import__ to hide this from naive packagers; we don't really |
43 |
770a9717f387
|
# depend on Tk unless ImageTk is used, and that module already |
44 |
770a9717f387
|
# imports Tkinter) |
45 |
770a9717f387
|
__import__("FixTk") |
46 |
770a9717f387
|
except ImportError: |
47 |
770a9717f387
|
pass |
48 |
770a9717f387
|
|
49 |
770a9717f387
|
try: |
50 |
770a9717f387
|
# If the _imaging C module is not present, you can still use |
51 |
770a9717f387
|
# the "open" function to identify files, but you cannot load |
52 |
770a9717f387
|
# them. Note that other modules should not refer to _imaging |
53 |
770a9717f387
|
# directly; import Image and use the Image.core variable instead. |
54 |
770a9717f387
|
import _imaging |
55 |
770a9717f387
|
core = _imaging |
56 |
770a9717f387
|
del _imaging |
57 |
770a9717f387
|
except ImportError, v: |
58 |
770a9717f387
|
core = _imaging_not_installed() |
59 |
770a9717f387
|
if str(v)[:20] == "Module use of python" and warnings: |
60 |
770a9717f387
|
# The _imaging C module is present, but not compiled for |
61 |
770a9717f387
|
# the right version (windows only). Print a warning, if |
62 |
770a9717f387
|
# possible. |
63 |
770a9717f387
|
warnings.warn( |
64 |
770a9717f387
|
"The _imaging extension was built for another version " |
65 |
770a9717f387
|
"of Python; most PIL functions will be disabled", |
66 |
770a9717f387
|
RuntimeWarning |
67 |
770a9717f387
|
) |
68 |
770a9717f387
|
|
69 |
770a9717f387
|
import ImageMode |
70 |
770a9717f387
|
import ImagePalette |
71 |
770a9717f387
|
|
72 |
770a9717f387
|
import os, string, sys |
73 |
770a9717f387
|
|
74 |
770a9717f387
|
# type stuff |
75 |
770a9717f387
|
from types import IntType, StringType, TupleType |
76 |
770a9717f387
|
|
77 |
770a9717f387
|
try: |
78 |
770a9717f387
|
UnicodeStringType = type(unicode("")) |
79 |
770a9717f387
|
## |
80 |
770a9717f387
|
# (Internal) Checks if an object is a string. If the current |
81 |
770a9717f387
|
# Python version supports Unicode, this checks for both 8-bit |
82 |
770a9717f387
|
# and Unicode strings. |
83 |
770a9717f387
|
def isStringType(t): |
84 |
770a9717f387
|
return isinstance(t, StringType) or isinstance(t, UnicodeStringType) |
85 |
770a9717f387
|
except NameError: |
86 |
770a9717f387
|
def isStringType(t): |
87 |
770a9717f387
|
return isinstance(t, StringType) |
88 |
770a9717f387
|
|
89 |
770a9717f387
|
## |
90 |
770a9717f387
|
# (Internal) Checks if an object is a tuple. |
91 |
770a9717f387
|
|
92 |
770a9717f387
|
def isTupleType(t): |
93 |
770a9717f387
|
return isinstance(t, TupleType) |
94 |
770a9717f387
|
|
95 |
770a9717f387
|
## |
96 |
770a9717f387
|
# (Internal) Checks if an object is an image object. |
97 |
770a9717f387
|
|
98 |
770a9717f387
|
def isImageType(t): |
99 |
770a9717f387
|
return hasattr(t, "im") |
100 |
770a9717f387
|
|
101 |
770a9717f387
|
## |
102 |
770a9717f387
|
# (Internal) Checks if an object is a string, and that it points to a |
103 |
770a9717f387
|
# directory. |
104 |
770a9717f387
|
|
105 |
770a9717f387
|
def isDirectory(f): |
106 |
770a9717f387
|
return isStringType(f) and os.path.isdir(f) |
107 |
770a9717f387
|
|
108 |
770a9717f387
|
from operator import isNumberType, isSequenceType |
109 |
770a9717f387
|
|
110 |
770a9717f387
|
# |
111 |
770a9717f387
|
# Debug level |
112 |
770a9717f387
|
|
113 |
770a9717f387
|
DEBUG = 0 |
114 |
770a9717f387
|
|
115 |
770a9717f387
|
# |
116 |
770a9717f387
|
# Constants (also defined in _imagingmodule.c!) |
117 |
770a9717f387
|
|
118 |
770a9717f387
|
NONE = 0 |
119 |
770a9717f387
|
|
120 |
770a9717f387
|
# transpose |
121 |
770a9717f387
|
FLIP_LEFT_RIGHT = 0 |
122 |
770a9717f387
|
FLIP_TOP_BOTTOM = 1 |
123 |
770a9717f387
|
ROTATE_90 = 2 |
124 |
770a9717f387
|
ROTATE_180 = 3 |
125 |
770a9717f387
|
ROTATE_270 = 4 |
126 |
770a9717f387
|
|
127 |
770a9717f387
|
# transforms |
128 |
770a9717f387
|
AFFINE = 0 |
129 |
770a9717f387
|
EXTENT = 1 |
130 |
770a9717f387
|
PERSPECTIVE = 2 |
131 |
770a9717f387
|
QUAD = 3 |
132 |
770a9717f387
|
MESH = 4 |
133 |
770a9717f387
|
|
134 |
770a9717f387
|
# resampling filters |
135 |
770a9717f387
|
NONE = 0 |
136 |
770a9717f387
|
NEAREST = 0 |
137 |
770a9717f387
|
ANTIALIAS = 1 # 3-lobed lanczos |
138 |
770a9717f387
|
LINEAR = BILINEAR = 2 |
139 |
770a9717f387
|
CUBIC = BICUBIC = 3 |
140 |
770a9717f387
|
|
141 |
770a9717f387
|
# dithers |
142 |
770a9717f387
|
NONE = 0 |
143 |
770a9717f387
|
NEAREST = 0 |
144 |
770a9717f387
|
ORDERED = 1 # Not yet implemented |
145 |
770a9717f387
|
RASTERIZE = 2 # Not yet implemented |
146 |
770a9717f387
|
FLOYDSTEINBERG = 3 # default |
147 |
770a9717f387
|
|
148 |
770a9717f387
|
# palettes/quantizers |
149 |
770a9717f387
|
WEB = 0 |
150 |
770a9717f387
|
ADAPTIVE = 1 |
151 |
770a9717f387
|
|
152 |
770a9717f387
|
# categories |
153 |
770a9717f387
|
NORMAL = 0 |
154 |
770a9717f387
|
SEQUENCE = 1 |
155 |
770a9717f387
|
CONTAINER = 2 |
156 |
770a9717f387
|
|
157 |
770a9717f387
|
# -------------------------------------------------------------------- |
158 |
770a9717f387
|
# Registries |
159 |
770a9717f387
|
|
160 |
770a9717f387
|
ID = [] |
161 |
770a9717f387
|
OPEN = {} |
162 |
770a9717f387
|
MIME = {} |
163 |
770a9717f387
|
SAVE = {} |
164 |
770a9717f387
|
EXTENSION = {} |
165 |
770a9717f387
|
|
166 |
770a9717f387
|
# -------------------------------------------------------------------- |
167 |
770a9717f387
|
# Modes supported by this version |
168 |
770a9717f387
|
|
169 |
770a9717f387
|
_MODEINFO = { |
170 |
770a9717f387
|
# NOTE: this table will be removed in future versions. use |
171 |
770a9717f387
|
# getmode* functions or ImageMode descriptors instead. |
172 |
770a9717f387
|
|
173 |
770a9717f387
|
# official modes |
174 |
770a9717f387
|
"1": ("L", "L", ("1",)), |
175 |
770a9717f387
|
"L": ("L", "L", ("L",)), |
176 |
770a9717f387
|
"I": ("L", "I", ("I",)), |
177 |
770a9717f387
|
"F": ("L", "F", ("F",)), |
178 |
770a9717f387
|
"P": ("RGB", "L", ("P",)), |
179 |
770a9717f387
|
"RGB": ("RGB", "L", ("R", "G", "B")), |
180 |
770a9717f387
|
"RGBX": ("RGB", "L", ("R", "G", "B", "X")), |
181 |
770a9717f387
|
"RGBA": ("RGB", "L", ("R", "G", "B", "A")), |
182 |
770a9717f387
|
"CMYK": ("RGB", "L", ("C", "M", "Y", "K")), |
183 |
770a9717f387
|
"YCbCr": ("RGB", "L", ("Y", "Cb", "Cr")), |
184 |
770a9717f387
|
|
185 |
5862df75157e
|
# Experimental modes include I;16, I;16L, I;16B, RGBa, BGR;15, and |
186 |
5862df75157e
|
# BGR;24. Use these modes only if you know exactly what you're |
187 |
5862df75157e
|
# doing... |
188 |
770a9717f387
|
|
189 |
770a9717f387
|
} |
190 |
770a9717f387
|
|
191 |
770a9717f387
|
if sys.byteorder == 'little': |
192 |
770a9717f387
|
_ENDIAN = '<' |
193 |
770a9717f387
|
else: |
194 |
770a9717f387
|
_ENDIAN = '>' |
195 |
770a9717f387
|
|
196 |
770a9717f387
|
_MODE_CONV = { |
197 |
770a9717f387
|
# official modes |
198 |
ac9410828fed
|
"1": ('|b1', None), # broken |
199 |
770a9717f387
|
"L": ('|u1', None), |
200 |
ac9410828fed
|
"I": (_ENDIAN + 'i4', None), |
201 |
ac9410828fed
|
"F": (_ENDIAN + 'f4', None), |
202 |
770a9717f387
|
"P": ('|u1', None), |
203 |
770a9717f387
|
"RGB": ('|u1', 3), |
204 |
770a9717f387
|
"RGBX": ('|u1', 4), |
205 |
770a9717f387
|
"RGBA": ('|u1', 4), |
206 |
770a9717f387
|
"CMYK": ('|u1', 4), |
207 |
770a9717f387
|
"YCbCr": ('|u1', 4), |
208 |
770a9717f387
|
} |
209 |
770a9717f387
|
|
210 |
770a9717f387
|
def _conv_type_shape(im): |
211 |
49cea88ebb6b
|
shape = im.size[1], im.size[0] |
212 |
770a9717f387
|
typ, extra = _MODE_CONV[im.mode] |
213 |
770a9717f387
|
if extra is None: |
214 |
770a9717f387
|
return shape, typ |
215 |
770a9717f387
|
else: |
216 |
770a9717f387
|
return shape+(extra,), typ |
217 |
770a9717f387
|
|
218 |
770a9717f387
|
|
219 |
770a9717f387
|
MODES = _MODEINFO.keys() |
220 |
770a9717f387
|
MODES.sort() |
221 |
770a9717f387
|
|
222 |
770a9717f387
|
# raw modes that may be memory mapped. NOTE: if you change this, you |
223 |
770a9717f387
|
# may have to modify the stride calculation in map.c too! |
224 |
5862df75157e
|
_MAPMODES = ("L", "P", "RGBX", "RGBA", "CMYK", "I;16", "I;16L", "I;16B") |
225 |
770a9717f387
|
|
226 |
770a9717f387
|
## |
227 |
770a9717f387
|
# Gets the "base" mode for given mode. This function returns "L" for |
228 |
770a9717f387
|
# images that contain grayscale data, and "RGB" for images that |
229 |
770a9717f387
|
# contain color data. |
230 |
770a9717f387
|
# |
231 |
770a9717f387
|
# @param mode Input mode. |
232 |
770a9717f387
|
# @return "L" or "RGB". |
233 |
770a9717f387
|
# @exception KeyError If the input mode was not a standard mode. |
234 |
770a9717f387
|
|
235 |
770a9717f387
|
def getmodebase(mode): |
236 |
770a9717f387
|
return ImageMode.getmode(mode).basemode |
237 |
770a9717f387
|
|
238 |
770a9717f387
|
## |
239 |
770a9717f387
|
# Gets the storage type mode. Given a mode, this function returns a |
240 |
770a9717f387
|
# single-layer mode suitable for storing individual bands. |
241 |
770a9717f387
|
# |
242 |
770a9717f387
|
# @param mode Input mode. |
243 |
770a9717f387
|
# @return "L", "I", or "F". |
244 |
770a9717f387
|
# @exception KeyError If the input mode was not a standard mode. |
245 |
770a9717f387
|
|
246 |
770a9717f387
|
def getmodetype(mode): |
247 |
770a9717f387
|
return ImageMode.getmode(mode).basetype |
248 |
770a9717f387
|
|
249 |
770a9717f387
|
## |
250 |
770a9717f387
|
# Gets a list of individual band names. Given a mode, this function |
251 |
770a9717f387
|
# returns a tuple containing the names of individual bands (use |
252 |
770a9717f387
|
# {@link #getmodetype} to get the mode used to store each individual |
253 |
770a9717f387
|
# band. |
254 |
770a9717f387
|
# |
255 |
770a9717f387
|
# @param mode Input mode. |
256 |
770a9717f387
|
# @return A tuple containing band names. The length of the tuple |
257 |
770a9717f387
|
# gives the number of bands in an image of the given mode. |
258 |
770a9717f387
|
# @exception KeyError If the input mode was not a standard mode. |
259 |
770a9717f387
|
|
260 |
770a9717f387
|
def getmodebandnames(mode): |
261 |
770a9717f387
|
return ImageMode.getmode(mode).bands |
262 |
770a9717f387
|
|
263 |
770a9717f387
|
## |
264 |
770a9717f387
|
# Gets the number of individual bands for this mode. |
265 |
770a9717f387
|
# |
266 |
770a9717f387
|
# @param mode Input mode. |
267 |
770a9717f387
|
# @return The number of bands in this mode. |
268 |
770a9717f387
|
# @exception KeyError If the input mode was not a standard mode. |
269 |
770a9717f387
|
|
270 |
770a9717f387
|
def getmodebands(mode): |
271 |
770a9717f387
|
return len(ImageMode.getmode(mode).bands) |
272 |
770a9717f387
|
|
273 |
770a9717f387
|
# -------------------------------------------------------------------- |
274 |
770a9717f387
|
# Helpers |
275 |
770a9717f387
|
|
276 |
770a9717f387
|
_initialized = 0 |
277 |
770a9717f387
|
|
278 |
770a9717f387
|
## |
279 |
770a9717f387
|
# Explicitly loads standard file format drivers. |
280 |
770a9717f387
|
|
281 |
770a9717f387
|
def preinit(): |
282 |
770a9717f387
|
"Load standard file format drivers." |
283 |
770a9717f387
|
|
284 |
770a9717f387
|
global _initialized |
285 |
770a9717f387
|
if _initialized >= 1: |
286 |
770a9717f387
|
return |
287 |
770a9717f387
|
|
288 |
770a9717f387
|
try: |
289 |
770a9717f387
|
import BmpImagePlugin |
290 |
770a9717f387
|
except ImportError: |
291 |
770a9717f387
|
pass |
292 |
770a9717f387
|
try: |
293 |
770a9717f387
|
import GifImagePlugin |
294 |
770a9717f387
|
except ImportError: |
295 |
770a9717f387
|
pass |
296 |
770a9717f387
|
try: |
297 |
770a9717f387
|
import JpegImagePlugin |
298 |
770a9717f387
|
except ImportError: |
299 |
770a9717f387
|
pass |
300 |
770a9717f387
|
try: |
301 |
770a9717f387
|
import PpmImagePlugin |
302 |
770a9717f387
|
except ImportError: |
303 |
770a9717f387
|
pass |
304 |
770a9717f387
|
try: |
305 |
770a9717f387
|
import PngImagePlugin |
306 |
770a9717f387
|
except ImportError: |
307 |
770a9717f387
|
pass |
308 |
770a9717f387
|
# try: |
309 |
770a9717f387
|
# import TiffImagePlugin |
310 |
770a9717f387
|
# except ImportError: |
311 |
770a9717f387
|
# pass |
312 |
770a9717f387
|
|
313 |
770a9717f387
|
_initialized = 1 |
314 |
770a9717f387
|
|
315 |
770a9717f387
|
## |
316 |
770a9717f387
|
# Explicitly initializes the Python Imaging Library. This function |
317 |
770a9717f387
|
# loads all available file format drivers. |
318 |
770a9717f387
|
|
319 |
770a9717f387
|
def init(): |
320 |
770a9717f387
|
"Load all file format drivers." |
321 |
770a9717f387
|
|
322 |
770a9717f387
|
global _initialized |
323 |
770a9717f387
|
if _initialized >= 2: |
324 |
454b4d2672f3
|
return 0 |
325 |
770a9717f387
|
|
326 |
770a9717f387
|
visited = {} |
327 |
770a9717f387
|
|
328 |
770a9717f387
|
directories = sys.path |
329 |
770a9717f387
|
|
330 |
770a9717f387
|
try: |
331 |
770a9717f387
|
directories = directories + [os.path.dirname(__file__)] |
332 |
770a9717f387
|
except NameError: |
333 |
770a9717f387
|
pass |
334 |
770a9717f387
|
|
335 |
770a9717f387
|
# only check directories (including current, if present in the path) |
336 |
770a9717f387
|
for directory in filter(isDirectory, directories): |
337 |
770a9717f387
|
fullpath = os.path.abspath(directory) |
338 |
770a9717f387
|
if visited.has_key(fullpath): |
339 |
770a9717f387
|
continue |
340 |
770a9717f387
|
for file in os.listdir(directory): |
341 |
770a9717f387
|
if file[-14:] == "ImagePlugin.py": |
342 |
770a9717f387
|
f, e = os.path.splitext(file) |
343 |
770a9717f387
|
try: |
344 |
770a9717f387
|
sys.path.insert(0, directory) |
345 |
770a9717f387
|
try: |
346 |
770a9717f387
|
__import__(f, globals(), locals(), []) |
347 |
770a9717f387
|
finally: |
348 |
770a9717f387
|
del sys.path[0] |
349 |
770a9717f387
|
except ImportError: |
350 |
770a9717f387
|
if DEBUG: |
351 |
770a9717f387
|
print "Image: failed to import", |
352 |
770a9717f387
|
print f, ":", sys.exc_value |
353 |
770a9717f387
|
visited[fullpath] = None |
354 |
770a9717f387
|
|
355 |
770a9717f387
|
if OPEN or SAVE: |
356 |
770a9717f387
|
_initialized = 2 |
357 |
454b4d2672f3
|
return 1 |
358 |
770a9717f387
|
|
359 |
770a9717f387
|
# -------------------------------------------------------------------- |
360 |
770a9717f387
|
# Codec factories (used by tostring/fromstring and ImageFile.load) |
361 |
770a9717f387
|
|
362 |
770a9717f387
|
def _getdecoder(mode, decoder_name, args, extra=()): |
363 |
770a9717f387
|
|
364 |
770a9717f387
|
# tweak arguments |
365 |
770a9717f387
|
if args is None: |
366 |
770a9717f387
|
args = () |
367 |
770a9717f387
|
elif not isTupleType(args): |
368 |
770a9717f387
|
args = (args,) |
369 |
770a9717f387
|
|
370 |
770a9717f387
|
try: |
371 |
770a9717f387
|
# get decoder |
372 |
770a9717f387
|
decoder = getattr(core, decoder_name + "_decoder") |
373 |
770a9717f387
|
# print decoder, (mode,) + args + extra |
374 |
770a9717f387
|
return apply(decoder, (mode,) + args + extra) |
375 |
770a9717f387
|
except AttributeError: |
376 |
770a9717f387
|
raise IOError("decoder %s not available" % decoder_name) |
377 |
770a9717f387
|
|
378 |
770a9717f387
|
def _getencoder(mode, encoder_name, args, extra=()): |
379 |
770a9717f387
|
|
380 |
770a9717f387
|
# tweak arguments |
381 |
770a9717f387
|
if args is None: |
382 |
770a9717f387
|
args = () |
383 |
770a9717f387
|
elif not isTupleType(args): |
384 |
770a9717f387
|
args = (args,) |
385 |
770a9717f387
|
|
386 |
770a9717f387
|
try: |
387 |
770a9717f387
|
# get encoder |
388 |
770a9717f387
|
encoder = getattr(core, encoder_name + "_encoder") |
389 |
770a9717f387
|
# print encoder, (mode,) + args + extra |
390 |
770a9717f387
|
return apply(encoder, (mode,) + args + extra) |
391 |
770a9717f387
|
except AttributeError: |
392 |
770a9717f387
|
raise IOError("encoder %s not available" % encoder_name) |
393 |
770a9717f387
|
|
394 |
770a9717f387
|
|
395 |
770a9717f387
|
# -------------------------------------------------------------------- |
396 |
770a9717f387
|
# Simple expression analyzer |
397 |
770a9717f387
|
|
398 |
770a9717f387
|
class _E: |
399 |
770a9717f387
|
def __init__(self, data): self.data = data |
400 |
770a9717f387
|
def __coerce__(self, other): return self, _E(other) |
401 |
770a9717f387
|
def __add__(self, other): return _E((self.data, "__add__", other.data)) |
402 |
770a9717f387
|
def __mul__(self, other): return _E((self.data, "__mul__", other.data)) |
403 |
770a9717f387
|
|
404 |
770a9717f387
|
def _getscaleoffset(expr): |
405 |
770a9717f387
|
stub = ["stub"] |
406 |
770a9717f387
|
data = expr(_E(stub)).data |
407 |
770a9717f387
|
try: |
408 |
770a9717f387
|
(a, b, c) = data # simplified syntax |
409 |
770a9717f387
|
if (a is stub and b == "__mul__" and isNumberType(c)): |
410 |
770a9717f387
|
return c, 0.0 |
411 |
770a9717f387
|
if (a is stub and b == "__add__" and isNumberType(c)): |
412 |
770a9717f387
|
return 1.0, c |
413 |
770a9717f387
|
except TypeError: pass |
414 |
770a9717f387
|
try: |
415 |
770a9717f387
|
((a, b, c), d, e) = data # full syntax |
416 |
770a9717f387
|
if (a is stub and b == "__mul__" and isNumberType(c) and |
417 |
770a9717f387
|
d == "__add__" and isNumberType(e)): |
418 |
770a9717f387
|
return c, e |
419 |
770a9717f387
|
except TypeError: pass |
420 |
770a9717f387
|
raise ValueError("illegal expression") |
421 |
770a9717f387
|
|
422 |
770a9717f387
|
|
423 |
770a9717f387
|
# -------------------------------------------------------------------- |
424 |
770a9717f387
|
# Implementation wrapper |
425 |
770a9717f387
|
|
426 |
770a9717f387
|
## |
427 |
770a9717f387
|
# This class represents an image object. To create Image objects, use |
428 |
770a9717f387
|
# the appropriate factory functions. There's hardly ever any reason |
429 |
770a9717f387
|
# to call the Image constructor directly. |
430 |
770a9717f387
|
# |
431 |
770a9717f387
|
# @see #open |
432 |
770a9717f387
|
# @see #new |
433 |
770a9717f387
|
# @see #fromstring |
434 |
770a9717f387
|
|
435 |
770a9717f387
|
class Image: |
436 |
770a9717f387
|
|
437 |
770a9717f387
|
format = None |
438 |
770a9717f387
|
format_description = None |
439 |
770a9717f387
|
|
440 |
770a9717f387
|
def __init__(self): |
441 |
1b72111c5eb5
|
# FIXME: take "new" parameters / other image? |
442 |
db1b40ca85c4
|
# FIXME: turn mode and size into delegating properties? |
443 |
770a9717f387
|
self.im = None |
444 |
770a9717f387
|
self.mode = "" |
445 |
770a9717f387
|
self.size = (0, 0) |
446 |
770a9717f387
|
self.palette = None |
447 |
770a9717f387
|
self.info = {} |
448 |
770a9717f387
|
self.category = NORMAL |
449 |
770a9717f387
|
self.readonly = 0 |
450 |
770a9717f387
|
|
451 |
770a9717f387
|
def _new(self, im): |
452 |
770a9717f387
|
new = Image() |
453 |
770a9717f387
|
new.im = im |
454 |
770a9717f387
|
new.mode = im.mode |
455 |
770a9717f387
|
new.size = im.size |
456 |
770a9717f387
|
new.palette = self.palette |
457 |
770a9717f387
|
if im.mode == "P": |
458 |
770a9717f387
|
new.palette = ImagePalette.ImagePalette() |
459 |
770a9717f387
|
try: |
460 |
770a9717f387
|
new.info = self.info.copy() |
461 |
770a9717f387
|
except AttributeError: |
462 |
770a9717f387
|
# fallback (pre-1.5.2) |
463 |
770a9717f387
|
new.info = {} |
464 |
770a9717f387
|
for k, v in self.info: |
465 |
770a9717f387
|
new.info[k] = v |
466 |
770a9717f387
|
return new |
467 |
770a9717f387
|
|
468 |
770a9717f387
|
_makeself = _new # compatibility |
469 |
770a9717f387
|
|
470 |
770a9717f387
|
def _copy(self): |
471 |
770a9717f387
|
self.load() |
472 |
770a9717f387
|
self.im = self.im.copy() |
473 |
770a9717f387
|
self.readonly = 0 |
474 |
770a9717f387
|
|
475 |
770a9717f387
|
def _dump(self, file=None, format=None): |
476 |
770a9717f387
|
import tempfile |
477 |
770a9717f387
|
if not file: |
478 |
770a9717f387
|
file = tempfile.mktemp() |
479 |
770a9717f387
|
self.load() |
480 |
770a9717f387
|
if not format or format == "PPM": |
481 |
770a9717f387
|
self.im.save_ppm(file) |
482 |
770a9717f387
|
else: |
483 |
770a9717f387
|
file = file + "." + format |
484 |
770a9717f387
|
self.save(file, format) |
485 |
770a9717f387
|
return file |
486 |
770a9717f387
|
|
487 |
1b72111c5eb5
|
def __repr__(self): |
488 |
1b72111c5eb5
|
return "<%s.%s image mode=%s size=%dx%d at 0x%X>" % ( |
489 |
1b72111c5eb5
|
self.__class__.__module__, self.__class__.__name__, |
490 |
1b72111c5eb5
|
self.mode, self.size[0], self.size[1], |
491 |
1b72111c5eb5
|
id(self) |
492 |
1b72111c5eb5
|
) |
493 |
1b72111c5eb5
|
|
494 |
770a9717f387
|
def __getattr__(self, name): |
495 |
770a9717f387
|
if name == "__array_interface__": |
496 |
770a9717f387
|
# numpy array interface support |
497 |
770a9717f387
|
new = {} |
498 |
770a9717f387
|
shape, typestr = _conv_type_shape(self) |
499 |
770a9717f387
|
new['shape'] = shape |
500 |
770a9717f387
|
new['typestr'] = typestr |
501 |
770a9717f387
|
new['data'] = self.tostring() |
502 |
770a9717f387
|
return new |
503 |
770a9717f387
|
raise AttributeError(name) |
504 |
770a9717f387
|
|
505 |
770a9717f387
|
## |
506 |
770a9717f387
|
# Returns a string containing pixel data. |
507 |
770a9717f387
|
# |
508 |
770a9717f387
|
# @param encoder_name What encoder to use. The default is to |
509 |
770a9717f387
|
# use the standard "raw" encoder. |
510 |
770a9717f387
|
# @param *args Extra arguments to the encoder. |
511 |
770a9717f387
|
# @return An 8-bit string. |
512 |
770a9717f387
|
|
513 |
770a9717f387
|
def tostring(self, encoder_name="raw", *args): |
514 |
770a9717f387
|
"Return image as a binary string" |
515 |
770a9717f387
|
|
516 |
770a9717f387
|
# may pass tuple instead of argument list |
517 |
770a9717f387
|
if len(args) == 1 and isTupleType(args[0]): |
518 |
770a9717f387
|
args = args[0] |
519 |
770a9717f387
|
|
520 |
770a9717f387
|
if encoder_name == "raw" and args == (): |
521 |
770a9717f387
|
args = self.mode |
522 |
770a9717f387
|
|
523 |
770a9717f387
|
self.load() |
524 |
770a9717f387
|
|
525 |
770a9717f387
|
# unpack data |
526 |
770a9717f387
|
e = _getencoder(self.mode, encoder_name, args) |
527 |
770a9717f387
|
e.setimage(self.im) |
528 |
770a9717f387
|
|
529 |
770a9717f387
|
bufsize = max(65536, self.size[0] * 4) # see RawEncode.c |
530 |
770a9717f387
|
|
531 |
770a9717f387
|
data = [] |
532 |
770a9717f387
|
while 1: |
533 |
770a9717f387
|
l, s, d = e.encode(bufsize) |
534 |
770a9717f387
|
data.append(d) |
535 |
770a9717f387
|
if s: |
536 |
770a9717f387
|
break |
537 |
770a9717f387
|
if s < 0: |
538 |
770a9717f387
|
raise RuntimeError("encoder error %d in tostring" % s) |
539 |
770a9717f387
|
|
540 |
770a9717f387
|
return string.join(data, "") |
541 |
770a9717f387
|
|
542 |
770a9717f387
|
## |
543 |
770a9717f387
|
# Returns the image converted to an X11 bitmap. This method |
544 |
770a9717f387
|
# only works for mode "1" images. |
545 |
770a9717f387
|
# |
546 |
770a9717f387
|
# @param name The name prefix to use for the bitmap variables. |
547 |
770a9717f387
|
# @return A string containing an X11 bitmap. |
548 |
770a9717f387
|
# @exception ValueError If the mode is not "1" |
549 |
770a9717f387
|
|
550 |
770a9717f387
|
def tobitmap(self, name="image"): |
551 |
770a9717f387
|
"Return image as an XBM bitmap" |
552 |
770a9717f387
|
|
553 |
770a9717f387
|
self.load() |
554 |
770a9717f387
|
if self.mode != "1": |
555 |
770a9717f387
|
raise ValueError("not a bitmap") |
556 |
770a9717f387
|
data = self.tostring("xbm") |
557 |
770a9717f387
|
return string.join(["#define %s_width %d\n" % (name, self.size[0]), |
558 |
770a9717f387
|
"#define %s_height %d\n"% (name, self.size[1]), |
559 |
770a9717f387
|
"static char %s_bits[] = {\n" % name, data, "};"], "") |
560 |
770a9717f387
|
|
561 |
770a9717f387
|
## |
562 |
770a9717f387
|
# Loads this image with pixel data from a string. |
563 |
770a9717f387
|
# <p> |
564 |
770a9717f387
|
# This method is similar to the {@link #fromstring} function, but |
565 |
770a9717f387
|
# loads data into this image instead of creating a new image |
566 |
770a9717f387
|
# object. |
567 |
770a9717f387
|
|
568 |
770a9717f387
|
def fromstring(self, data, decoder_name="raw", *args): |
569 |
770a9717f387
|
"Load data to image from binary string" |
570 |
770a9717f387
|
|
571 |
770a9717f387
|
# may pass tuple instead of argument list |
572 |
770a9717f387
|
if len(args) == 1 and isTupleType(args[0]): |
573 |
770a9717f387
|
args = args[0] |
574 |
770a9717f387
|
|
575 |
770a9717f387
|
# default format |
576 |
770a9717f387
|
if decoder_name == "raw" and args == (): |
577 |
770a9717f387
|
args = self.mode |
578 |
770a9717f387
|
|
579 |
770a9717f387
|
# unpack data |
580 |
770a9717f387
|
d = _getdecoder(self.mode, decoder_name, args) |
581 |
770a9717f387
|
d.setimage(self.im) |
582 |
770a9717f387
|
s = d.decode(data) |
583 |
770a9717f387
|
|
584 |
770a9717f387
|
if s[0] >= 0: |
585 |
770a9717f387
|
raise ValueError("not enough image data") |
586 |
770a9717f387
|
if s[1] != 0: |
587 |
770a9717f387
|
raise ValueError("cannot decode image data") |
588 |
770a9717f387
|
|
589 |
770a9717f387
|
## |
590 |
770a9717f387
|
# Allocates storage for the image and loads the pixel data. In |
591 |
770a9717f387
|
# normal cases, you don't need to call this method, since the |
592 |
770a9717f387
|
# Image class automatically loads an opened image when it is |
593 |
770a9717f387
|
# accessed for the first time. |
594 |
770a9717f387
|
# |
595 |
770a9717f387
|
# @return An image access object. |
596 |
770a9717f387
|
|
597 |
770a9717f387
|
def load(self): |
598 |
770a9717f387
|
"Explicitly load pixel data." |
599 |
770a9717f387
|
if self.im and self.palette and self.palette.dirty: |
600 |
770a9717f387
|
# realize palette |
601 |
770a9717f387
|
apply(self.im.putpalette, self.palette.getdata()) |
602 |
770a9717f387
|
self.palette.dirty = 0 |
603 |
770a9717f387
|
self.palette.mode = "RGB" |
604 |
770a9717f387
|
self.palette.rawmode = None |
605 |
770a9717f387
|
if self.info.has_key("transparency"): |
606 |
770a9717f387
|
self.im.putpalettealpha(self.info["transparency"], 0) |
607 |
770a9717f387
|
self.palette.mode = "RGBA" |
608 |
770a9717f387
|
if self.im: |
609 |
770a9717f387
|
return self.im.pixel_access(self.readonly) |
610 |
770a9717f387
|
|
611 |
770a9717f387
|
## |
612 |
770a9717f387
|
# Verifies the contents of a file. For data read from a file, this |
613 |
770a9717f387
|
# method attempts to determine if the file is broken, without |
614 |
770a9717f387
|
# actually decoding the image data. If this method finds any |
615 |
770a9717f387
|
# problems, it raises suitable exceptions. If you need to load |
616 |
770a9717f387
|
# the image after using this method, you must reopen the image |
617 |
770a9717f387
|
# file. |
618 |
770a9717f387
|
|
619 |
770a9717f387
|
def verify(self): |
620 |
770a9717f387
|
"Verify file contents." |
621 |
770a9717f387
|
pass |
622 |
770a9717f387
|
|
623 |
770a9717f387
|
## |
624 |
770a9717f387
|
# Returns a converted copy of this image. For the "P" mode, this |
625 |
770a9717f387
|
# method translates pixels through the palette. If mode is |
626 |
770a9717f387
|
# omitted, a mode is chosen so that all information in the image |
627 |
770a9717f387
|
# and the palette can be represented without a palette. |
628 |
770a9717f387
|
# <p> |
629 |
770a9717f387
|
# The current version supports all possible conversions between |
630 |
770a9717f387
|
# "L", "RGB" and "CMYK." |
631 |
770a9717f387
|
# <p> |
632 |
770a9717f387
|
# When translating a colour image to black and white (mode "L"), |
633 |
770a9717f387
|
# the library uses the ITU-R 601-2 luma transform: |
634 |
770a9717f387
|
# <p> |
635 |
770a9717f387
|
# <b>L = R * 299/1000 + G * 587/1000 + B * 114/1000</b> |
636 |
770a9717f387
|
# <p> |
637 |
770a9717f387
|
# When translating a greyscale image into a bilevel image (mode |
638 |
770a9717f387
|
# "1"), all non-zero values are set to 255 (white). To use other |
639 |
770a9717f387
|
# thresholds, use the {@link #Image.point} method. |
640 |
770a9717f387
|
# |
641 |
db1b40ca85c4
|
# @def convert(mode, matrix=None, **options) |
642 |
770a9717f387
|
# @param mode The requested mode. |
643 |
770a9717f387
|
# @param matrix An optional conversion matrix. If given, this |
644 |
770a9717f387
|
# should be 4- or 16-tuple containing floating point values. |
645 |
db1b40ca85c4
|
# @param options Additional options, given as keyword arguments. |
646 |
db1b40ca85c4
|
# @keyparam dither Dithering method, used when converting from |
647 |
db1b40ca85c4
|
# mode "RGB" to "P". |
648 |
db1b40ca85c4
|
# Available methods are NONE or FLOYDSTEINBERG (default). |
649 |
db1b40ca85c4
|
# @keyparam palette Palette to use when converting from mode "RGB" |
650 |
db1b40ca85c4
|
# to "P". Available palettes are WEB or ADAPTIVE. |
651 |
db1b40ca85c4
|
# @keyparam colors Number of colors to use for the ADAPTIVE palette. |
652 |
db1b40ca85c4
|
# Defaults to 256. |
653 |
770a9717f387
|
# @return An Image object. |
654 |
770a9717f387
|
|
655 |
770a9717f387
|
def convert(self, mode=None, data=None, dither=None, |
656 |
770a9717f387
|
palette=WEB, colors=256): |
657 |
770a9717f387
|
"Convert to other pixel format" |
658 |
770a9717f387
|
|
659 |
770a9717f387
|
if not mode: |
660 |
770a9717f387
|
# determine default mode |
661 |
770a9717f387
|
if self.mode == "P": |
662 |
770a9717f387
|
self.load() |
663 |
770a9717f387
|
if self.palette: |
664 |
770a9717f387
|
mode = self.palette.mode |
665 |
770a9717f387
|
else: |
666 |
770a9717f387
|
mode = "RGB" |
667 |
770a9717f387
|
else: |
668 |
770a9717f387
|
return self.copy() |
669 |
770a9717f387
|
|
670 |
770a9717f387
|
self.load() |
671 |
770a9717f387
|
|
672 |
770a9717f387
|
if data: |
673 |
770a9717f387
|
# matrix conversion |
674 |
770a9717f387
|
if mode not in ("L", "RGB"): |
675 |
770a9717f387
|
raise ValueError("illegal conversion") |
676 |
770a9717f387
|
im = self.im.convert_matrix(mode, data) |
677 |
770a9717f387
|
return self._new(im) |
678 |
770a9717f387
|
|
679 |
770a9717f387
|
if mode == "P" and palette == ADAPTIVE: |
680 |
770a9717f387
|
im = self.im.quantize(colors) |
681 |
770a9717f387
|
return self._new(im) |
682 |
770a9717f387
|
|
683 |
770a9717f387
|
# colourspace conversion |
684 |
770a9717f387
|
if dither is None: |
685 |
770a9717f387
|
dither = FLOYDSTEINBERG |
686 |
770a9717f387
|
|
687 |
770a9717f387
|
try: |
688 |
770a9717f387
|
im = self.im.convert(mode, dither) |
689 |
770a9717f387
|
except ValueError: |
690 |
770a9717f387
|
try: |
691 |
770a9717f387
|
# normalize source image and try again |
692 |
770a9717f387
|
im = self.im.convert(getmodebase(self.mode)) |
693 |
770a9717f387
|
im = im.convert(mode, dither) |
694 |
770a9717f387
|
except KeyError: |
695 |
770a9717f387
|
raise ValueError("illegal conversion") |
696 |
770a9717f387
|
|
697 |
770a9717f387
|
return self._new(im) |
698 |
770a9717f387
|
|
699 |
770a9717f387
|
def quantize(self, colors=256, method=0, kmeans=0, palette=None): |
700 |
770a9717f387
|
|
701 |
770a9717f387
|
# methods: |
702 |
770a9717f387
|
# 0 = median cut |
703 |
770a9717f387
|
# 1 = maximum coverage |
704 |
770a9717f387
|
|
705 |
770a9717f387
|
# NOTE: this functionality will be moved to the extended |
706 |
770a9717f387
|
# quantizer interface in a later version of PIL. |
707 |
770a9717f387
|
|
708 |
770a9717f387
|
self.load() |
709 |
770a9717f387
|
|
710 |
770a9717f387
|
if palette: |
711 |
770a9717f387
|
# use palette from reference image |
712 |
770a9717f387
|
palette.load() |
713 |
770a9717f387
|
if palette.mode != "P": |
714 |
770a9717f387
|
raise ValueError("bad mode for palette image") |
715 |
770a9717f387
|
if self.mode != "RGB" and self.mode != "L": |
716 |
770a9717f387
|
raise ValueError( |
717 |
770a9717f387
|
"only RGB or L mode images can be quantized to a palette" |
718 |
770a9717f387
|
) |
719 |
770a9717f387
|
im = self.im.convert("P", 1, palette.im) |
720 |
770a9717f387
|
return self._makeself(im) |
721 |
770a9717f387
|
|
722 |
770a9717f387
|
im = self.im.quantize(colors, method, kmeans) |
723 |
770a9717f387
|
return self._new(im) |
724 |
770a9717f387
|
|
725 |
770a9717f387
|
## |
726 |
770a9717f387
|
# Copies this image. Use this method if you wish to paste things |
727 |
770a9717f387
|
# into an image, but still retain the original. |
728 |
770a9717f387
|
# |
729 |
770a9717f387
|
# @return An Image object. |
730 |
770a9717f387
|
|
731 |
770a9717f387
|
def copy(self): |
732 |
770a9717f387
|
"Copy raster data" |
733 |
770a9717f387
|
|
734 |
770a9717f387
|
self.load() |
735 |
770a9717f387
|
im = self.im.copy() |
736 |
770a9717f387
|
return self._new(im) |
737 |
770a9717f387
|
|
738 |
770a9717f387
|
## |
739 |
770a9717f387
|
# Returns a rectangular region from this image. The box is a |
740 |
770a9717f387
|
# 4-tuple defining the left, upper, right, and lower pixel |
741 |
770a9717f387
|
# coordinate. |
742 |
770a9717f387
|
# <p> |
743 |
770a9717f387
|
# This is a lazy operation. Changes to the source image may or |
744 |
770a9717f387
|
# may not be reflected in the cropped image. To break the |
745 |
770a9717f387
|
# connection, call the {@link #Image.load} method on the cropped |
746 |
770a9717f387
|
# copy. |
747 |
770a9717f387
|
# |
748 |
770a9717f387
|
# @param The crop rectangle, as a (left, upper, right, lower)-tuple. |
749 |
770a9717f387
|
# @return An Image object. |
750 |
770a9717f387
|
|
751 |
770a9717f387
|
def crop(self, box=None): |
752 |
770a9717f387
|
"Crop region from image" |
753 |
770a9717f387
|
|
754 |
770a9717f387
|
self.load() |
755 |
770a9717f387
|
if box is None: |
756 |
770a9717f387
|
return self.copy() |
757 |
770a9717f387
|
|
758 |
770a9717f387
|
# lazy operation |
759 |
770a9717f387
|
return _ImageCrop(self, box) |
760 |
770a9717f387
|
|
761 |
770a9717f387
|
## |
762 |
770a9717f387
|
# Configures the image file loader so it returns a version of the |
763 |
770a9717f387
|
# image that as closely as possible matches the given mode and |
764 |
770a9717f387
|
# size. For example, you can use this method to convert a colour |
765 |
770a9717f387
|
# JPEG to greyscale while loading it, or to extract a 128x192 |
766 |
770a9717f387
|
# version from a PCD file. |
767 |
770a9717f387
|
# <p> |
768 |
770a9717f387
|
# Note that this method modifies the Image object in place. If |
769 |
770a9717f387
|
# the image has already been loaded, this method has no effect. |
770 |
770a9717f387
|
# |
771 |
770a9717f387
|
# @param mode The requested mode. |
772 |
770a9717f387
|
# @param size The requested size. |
773 |
770a9717f387
|
|
774 |
770a9717f387
|
def draft(self, mode, size): |
775 |
770a9717f387
|
"Configure image decoder" |
776 |
770a9717f387
|
|
777 |
770a9717f387
|
pass |
778 |
770a9717f387
|
|
779 |
770a9717f387
|
def _expand(self, xmargin, ymargin=None): |
780 |
770a9717f387
|
if ymargin is None: |
781 |
770a9717f387
|
ymargin = xmargin |
782 |
770a9717f387
|
self.load() |
783 |
770a9717f387
|
return self._new(self.im.expand(xmargin, ymargin, 0)) |
784 |
770a9717f387
|
|
785 |
770a9717f387
|
## |
786 |
770a9717f387
|
# Filters this image using the given filter. For a list of |
787 |
770a9717f387
|
# available filters, see the <b>ImageFilter</b> module. |
788 |
770a9717f387
|
# |
789 |
770a9717f387
|
# @param filter Filter kernel. |
790 |
770a9717f387
|
# @return An Image object. |
791 |
770a9717f387
|
# @see ImageFilter |
792 |
770a9717f387
|
|
793 |
770a9717f387
|
def filter(self, filter): |
794 |
770a9717f387
|
"Apply environment filter to image" |
795 |
770a9717f387
|
|
796 |
770a9717f387
|
self.load() |
797 |
770a9717f387
|
|
798 |
1e08a00b485b
|
if callable(filter): |
799 |
770a9717f387
|
filter = filter() |
800 |
1e08a00b485b
|
if not hasattr(filter, "filter"): |
801 |
1e08a00b485b
|
raise TypeError("filter argument should be ImageFilter.Filter instance or class") |
802 |
770a9717f387
|
|
803 |
770a9717f387
|
if self.im.bands == 1: |
804 |
770a9717f387
|
return self._new(filter.filter(self.im)) |
805 |
770a9717f387
|
# fix to handle multiband images since _imaging doesn't |
806 |
770a9717f387
|
ims = [] |
807 |
770a9717f387
|
for c in range(self.im.bands): |
808 |
770a9717f387
|
ims.append(self._new(filter.filter(self.im.getband(c)))) |
809 |
770a9717f387
|
return merge(self.mode, ims) |
810 |
770a9717f387
|
|
811 |
770a9717f387
|
## |
812 |
770a9717f387
|
# Returns a tuple containing the name of each band in this image. |
813 |
770a9717f387
|
# For example, <b>getbands</b> on an RGB image returns ("R", "G", "B"). |
814 |
770a9717f387
|
# |
815 |
770a9717f387
|
# @return A tuple containing band names. |
816 |
770a9717f387
|
|
817 |
770a9717f387
|
def getbands(self): |
818 |
770a9717f387
|
"Get band names" |
819 |
770a9717f387
|
|
820 |
770a9717f387
|
return ImageMode.getmode(self.mode).bands |
821 |
770a9717f387
|
|
822 |
770a9717f387
|
## |
823 |
770a9717f387
|
# Calculates the bounding box of the non-zero regions in the |
824 |
770a9717f387
|
# image. |
825 |
770a9717f387
|
# |
826 |
770a9717f387
|
# @return The bounding box is returned as a 4-tuple defining the |
827 |
770a9717f387
|
# left, upper, right, and lower pixel coordinate. If the image |
828 |
770a9717f387
|
# is completely empty, this method returns None. |
829 |
770a9717f387
|
|
830 |
770a9717f387
|
def getbbox(self): |
831 |
770a9717f387
|
"Get bounding box of actual data (non-zero pixels) in image" |
832 |
770a9717f387
|
|
833 |
770a9717f387
|
self.load() |
834 |
770a9717f387
|
return self.im.getbbox() |
835 |
770a9717f387
|
|
836 |
770a9717f387
|
## |
837 |
770a9717f387
|
# Returns a list of colors used in this image. |
838 |
770a9717f387
|
# |
839 |
770a9717f387
|
# @param maxcolors Maximum number of colors. If this number is |
840 |
770a9717f387
|
# exceeded, this method returns None. The default limit is |
841 |
770a9717f387
|
# 256 colors. |
842 |
770a9717f387
|
# @return An unsorted list of (count, pixel) values. |
843 |
770a9717f387
|
|
844 |
770a9717f387
|
def getcolors(self, maxcolors=256): |
845 |
770a9717f387
|
"Get colors from image, up to given limit" |
846 |
770a9717f387
|
|
847 |
770a9717f387
|
self.load() |
848 |
770a9717f387
|
if self.mode in ("1", "L", "P"): |
849 |
770a9717f387
|
h = self.im.histogram() |
850 |
770a9717f387
|
out = [] |
851 |
770a9717f387
|
for i in range(256): |
852 |
770a9717f387
|
if h[i]: |
853 |
770a9717f387
|
out.append((h[i], i)) |
854 |
770a9717f387
|
if len(out) > maxcolors: |
855 |
770a9717f387
|
return None |
856 |
770a9717f387
|
return out |
857 |
770a9717f387
|
return self.im.getcolors(maxcolors) |
858 |
770a9717f387
|
|
859 |
770a9717f387
|
## |
860 |
770a9717f387
|
# Returns the contents of this image as a sequence object |
861 |
770a9717f387
|
# containing pixel values. The sequence object is flattened, so |
862 |
770a9717f387
|
# that values for line one follow directly after the values of |
863 |
770a9717f387
|
# line zero, and so on. |
864 |
770a9717f387
|
# <p> |
865 |
770a9717f387
|
# Note that the sequence object returned by this method is an |
866 |
770a9717f387
|
# internal PIL data type, which only supports certain sequence |
867 |
770a9717f387
|
# operations. To convert it to an ordinary sequence (e.g. for |
868 |
770a9717f387
|
# printing), use <b>list(im.getdata())</b>. |
869 |
770a9717f387
|
# |
870 |
770a9717f387
|
# @param band What band to return. The default is to return |
871 |
770a9717f387
|
# all bands. To return a single band, pass in the index |
872 |
770a9717f387
|
# value (e.g. 0 to get the "R" band from an "RGB" image). |
873 |
770a9717f387
|
# @return A sequence-like object. |
874 |
770a9717f387
|
|
875 |
770a9717f387
|
def getdata(self, band = None): |
876 |
770a9717f387
|
"Get image data as sequence object." |
877 |
770a9717f387
|
|
878 |
770a9717f387
|
self.load() |
879 |
770a9717f387
|
if band is not None: |
880 |
770a9717f387
|
return self.im.getband(band) |
881 |
770a9717f387
|
return self.im # could be abused |
882 |
770a9717f387
|
|
883 |
770a9717f387
|
## |
884 |
770a9717f387
|
# Gets the the minimum and maximum pixel values for each band in |
885 |
770a9717f387
|
# the image. |
886 |
770a9717f387
|
# |
887 |
770a9717f387
|
# @return For a single-band image, a 2-tuple containing the |
888 |
770a9717f387
|
# minimum and maximum pixel value. For a multi-band image, |
889 |
770a9717f387
|
# a tuple containing one 2-tuple for each band. |
890 |
770a9717f387
|
|
891 |
770a9717f387
|
def getextrema(self): |
892 |
770a9717f387
|
"Get min/max value" |
893 |
770a9717f387
|
|
894 |
770a9717f387
|
self.load() |
895 |
770a9717f387
|
if self.im.bands > 1: |
896 |
770a9717f387
|
extrema = [] |
897 |
770a9717f387
|
for i in range(self.im.bands): |
898 |
770a9717f387
|
extrema.append(self.im.getband(i).getextrema()) |
899 |
770a9717f387
|
return tuple(extrema) |
900 |
770a9717f387
|
return self.im.getextrema() |
901 |
770a9717f387
|
|
902 |
770a9717f387
|
## |
903 |
770a9717f387
|
# Returns a PyCObject that points to the internal image memory. |
904 |
770a9717f387
|
# |
905 |
770a9717f387
|
# @return A PyCObject object. |
906 |
770a9717f387
|
|
907 |
770a9717f387
|
def getim(self): |
908 |
770a9717f387
|
"Get PyCObject pointer to internal image memory" |
909 |
770a9717f387
|
|
910 |
770a9717f387
|
self.load() |
911 |
770a9717f387
|
return self.im.ptr |
912 |
770a9717f387
|
|
913 |
770a9717f387
|
|
914 |
770a9717f387
|
## |
915 |
770a9717f387
|
# Returns the image palette as a list. |
916 |
770a9717f387
|
# |
917 |
770a9717f387
|
# @return A list of color values [r, g, b, ...], or None if the |
918 |
770a9717f387
|
# image has no palette. |
919 |
770a9717f387
|
|
920 |
770a9717f387
|
def getpalette(self): |
921 |
770a9717f387
|
"Get palette contents." |
922 |
770a9717f387
|
|
923 |
770a9717f387
|
self.load() |
924 |
770a9717f387
|
try: |
925 |
770a9717f387
|
return map(ord, self.im.getpalette()) |
926 |
770a9717f387
|
except ValueError: |
927 |
770a9717f387
|
return None # no palette |
928 |
770a9717f387
|
|
929 |
770a9717f387
|
|
930 |
770a9717f387
|
## |
931 |
770a9717f387
|
# Returns the pixel value at a given position. |
932 |
770a9717f387
|
# |
933 |
770a9717f387
|
# @param xy The coordinate, given as (x, y). |
934 |
770a9717f387
|
# @return The pixel value. If the image is a multi-layer image, |
935 |
770a9717f387
|
# this method returns a tuple. |
936 |
770a9717f387
|
|
937 |
770a9717f387
|
def getpixel(self, xy): |
938 |
770a9717f387
|
"Get pixel value" |
939 |
770a9717f387
|
|
940 |
770a9717f387
|
self.load() |
941 |
770a9717f387
|
return self.im.getpixel(xy) |
942 |
770a9717f387
|
|
943 |
770a9717f387
|
## |
944 |
770a9717f387
|
# Returns the horizontal and vertical projection. |
945 |
770a9717f387
|
# |
946 |
770a9717f387
|
# @return Two sequences, indicating where there are non-zero |
947 |
770a9717f387
|
# pixels along the X-axis and the Y-axis, respectively. |
948 |
770a9717f387
|
|
949 |
770a9717f387
|
def getprojection(self): |
950 |
770a9717f387
|
"Get projection to x and y axes" |
951 |
770a9717f387
|
|
952 |
770a9717f387
|
self.load() |
953 |
770a9717f387
|
x, y = self.im.getprojection() |
954 |
770a9717f387
|
return map(ord, x), map(ord, y) |
955 |
770a9717f387
|
|
956 |
770a9717f387
|
## |
957 |
770a9717f387
|
# Returns a histogram for the image. The histogram is returned as |
958 |
770a9717f387
|
# a list of pixel counts, one for each pixel value in the source |
959 |
770a9717f387
|
# image. If the image has more than one band, the histograms for |
960 |
770a9717f387
|
# all bands are concatenated (for example, the histogram for an |
961 |
770a9717f387
|
# "RGB" image contains 768 values). |
962 |
770a9717f387
|
# <p> |
963 |
770a9717f387
|
# A bilevel image (mode "1") is treated as a greyscale ("L") image |
964 |
770a9717f387
|
# by this method. |
965 |
770a9717f387
|
# <p> |
966 |
770a9717f387
|
# If a mask is provided, the method returns a histogram for those |
967 |
770a9717f387
|
# parts of the image where the mask image is non-zero. The mask |
968 |
770a9717f387
|
# image must have the same size as the image, and be either a |
969 |
770a9717f387
|
# bi-level image (mode "1") or a greyscale image ("L"). |
970 |
770a9717f387
|
# |
971 |
770a9717f387
|
# @def histogram(mask=None) |
972 |
770a9717f387
|
# @param mask An optional mask. |
973 |
770a9717f387
|
# @return A list containing pixel counts. |
974 |
770a9717f387
|
|
975 |
770a9717f387
|
def histogram(self, mask=None, extrema=None): |
976 |
770a9717f387
|
"Take histogram of image" |
977 |
770a9717f387
|
|
978 |
770a9717f387
|
self.load() |
979 |
770a9717f387
|
if mask: |
980 |
770a9717f387
|
mask.load() |
981 |
770a9717f387
|
return self.im.histogram((0, 0), mask.im) |
982 |
770a9717f387
|
if self.mode in ("I", "F"): |
983 |
770a9717f387
|
if extrema is None: |
984 |
770a9717f387
|
extrema = self.getextrema() |
985 |
770a9717f387
|
return self.im.histogram(extrema) |
986 |
770a9717f387
|
return self.im.histogram() |
987 |
770a9717f387
|
|
988 |
770a9717f387
|
## |
989 |
770a9717f387
|
# (Deprecated) Returns a copy of the image where the data has been |
990 |
770a9717f387
|
# offset by the given distances. Data wraps around the edges. If |
991 |
770a9717f387
|
# yoffset is omitted, it is assumed to be equal to xoffset. |
992 |
770a9717f387
|
# <p> |
993 |
770a9717f387
|
# This method is deprecated. New code should use the <b>offset</b> |
994 |
770a9717f387
|
# function in the <b>ImageChops</b> module. |
995 |
770a9717f387
|
# |
996 |
770a9717f387
|
# @param xoffset The horizontal distance. |
997 |
770a9717f387
|
# @param yoffset The vertical distance. If omitted, both |
998 |
770a9717f387
|
# distances are set to the same value. |
999 |
770a9717f387
|
# @return An Image object. |
1000 |
770a9717f387
|
|
1001 |
770a9717f387
|
def offset(self, xoffset, yoffset=None): |
1002 |
770a9717f387
|
"(deprecated) Offset image in horizontal and/or vertical direction" |
1003 |
770a9717f387
|
if warnings: |
1004 |
770a9717f387
|
warnings.warn( |
1005 |
770a9717f387
|
"'offset' is deprecated; use 'ImageChops.offset' instead", |
1006 |
770a9717f387
|
DeprecationWarning, stacklevel=2 |
1007 |
770a9717f387
|
) |
1008 |
770a9717f387
|
import ImageChops |
1009 |
770a9717f387
|
return ImageChops.offset(self, xoffset, yoffset) |
1010 |
770a9717f387
|
|
1011 |
770a9717f387
|
## |
1012 |
770a9717f387
|
# Pastes another image into this image. The box argument is either |
1013 |
770a9717f387
|
# a 2-tuple giving the upper left corner, a 4-tuple defining the |
1014 |
770a9717f387
|
# left, upper, right, and lower pixel coordinate, or None (same as |
1015 |
770a9717f387
|
# (0, 0)). If a 4-tuple is given, the size of the pasted image |
1016 |
770a9717f387
|
# must match the size of the region. |
1017 |
770a9717f387
|
# <p> |
1018 |
770a9717f387
|
# If the modes don't match, the pasted image is converted to the |
1019 |
770a9717f387
|
# mode of this image (see the {@link #Image.convert} method for |
1020 |
770a9717f387
|
# details). |
1021 |
770a9717f387
|
# <p> |
1022 |
770a9717f387
|
# Instead of an image, the source can be a integer or tuple |
1023 |
770a9717f387
|
# containing pixel values. The method then fills the region |
1024 |
770a9717f387
|
# with the given colour. When creating RGB images, you can |
1025 |
770a9717f387
|
# also use colour strings as supported by the ImageColor module. |
1026 |
770a9717f387
|
# <p> |
1027 |
770a9717f387
|
# If a mask is given, this method updates only the regions |
1028 |
770a9717f387
|
# indicated by the mask. You can use either "1", "L" or "RGBA" |
1029 |
770a9717f387
|
# images (in the latter case, the alpha band is used as mask). |
1030 |
770a9717f387
|
# Where the mask is 255, the given image is copied as is. Where |
1031 |
770a9717f387
|
# the mask is 0, the current value is preserved. Intermediate |
1032 |
770a9717f387
|
# values can be used for transparency effects. |
1033 |
770a9717f387
|
# <p> |
1034 |
770a9717f387
|
# Note that if you paste an "RGBA" image, the alpha band is |
1035 |
770a9717f387
|
# ignored. You can work around this by using the same image as |
1036 |
770a9717f387
|
# both source image and mask. |
1037 |
770a9717f387
|
# |
1038 |
770a9717f387
|
# @param im Source image or pixel value (integer or tuple). |
1039 |
770a9717f387
|
# @param box An optional 4-tuple giving the region to paste into. |
1040 |
770a9717f387
|
# If a 2-tuple is used instead, it's treated as the upper left |
1041 |
770a9717f387
|
# corner. If omitted or None, the source is pasted into the |
1042 |
770a9717f387
|
# upper left corner. |
1043 |
770a9717f387
|
# <p> |
1044 |
770a9717f387
|
# If an image is given as the second argument and there is no |
1045 |
770a9717f387
|
# third, the box defaults to (0, 0), and the second argument |
1046 |
770a9717f387
|
# is interpreted as a mask image. |
1047 |
770a9717f387
|
# @param mask An optional mask image. |
1048 |
770a9717f387
|
# @return An Image object. |
1049 |
770a9717f387
|
|
1050 |
770a9717f387
|
def paste(self, im, box=None, mask=None): |
1051 |
770a9717f387
|
"Paste other image into region" |
1052 |
770a9717f387
|
|
1053 |
770a9717f387
|
if isImageType(box) and mask is None: |
1054 |
770a9717f387
|
# abbreviated paste(im, mask) syntax |
1055 |
770a9717f387
|
mask = box; box = None |
1056 |
770a9717f387
|
|
1057 |
770a9717f387
|
if box is None: |
1058 |
770a9717f387
|
# cover all of self |
1059 |
770a9717f387
|
box = (0, 0) + self.size |
1060 |
770a9717f387
|
|
1061 |
770a9717f387
|
if len(box) == 2: |
1062 |
770a9717f387
|
# lower left corner given; get size from image or mask |
1063 |
770a9717f387
|
if isImageType(im): |
1064 |
770a9717f387
|
size = im.size |
1065 |
770a9717f387
|
elif isImageType(mask): |
1066 |
770a9717f387
|
size = mask.size |
1067 |
770a9717f387
|
else: |
1068 |
770a9717f387
|
# FIXME: use self.size here? |
1069 |
770a9717f387
|
raise ValueError( |
1070 |
770a9717f387
|
"cannot determine region size; use 4-item box" |
1071 |
770a9717f387
|
) |
1072 |
770a9717f387
|
box = box + (box[0]+size[0], box[1]+size[1]) |
1073 |
770a9717f387
|
|
1074 |
770a9717f387
|
if isStringType(im): |
1075 |
770a9717f387
|
import ImageColor |
1076 |
770a9717f387
|
im = ImageColor.getcolor(im, self.mode) |
1077 |
770a9717f387
|
|
1078 |
770a9717f387
|
elif isImageType(im): |
1079 |
770a9717f387
|
im.load() |
1080 |
770a9717f387
|
if self.mode != im.mode: |
1081 |
770a9717f387
|
if self.mode != "RGB" or im.mode not in ("RGBA", "RGBa"): |
1082 |
770a9717f387
|
# should use an adapter for this! |
1083 |
770a9717f387
|
im = im.convert(self.mode) |
1084 |
770a9717f387
|
im = im.im |
1085 |
770a9717f387
|
|
1086 |
770a9717f387
|
self.load() |
1087 |
770a9717f387
|
if self.readonly: |
1088 |
770a9717f387
|
self._copy() |
1089 |
770a9717f387
|
|
1090 |
770a9717f387
|
if mask: |
1091 |
770a9717f387
|
mask.load() |
1092 |
770a9717f387
|
self.im.paste(im, box, mask.im) |
1093 |
770a9717f387
|
else: |
1094 |
770a9717f387
|
self.im.paste(im, box) |
1095 |
770a9717f387
|
|
1096 |
770a9717f387
|
## |
1097 |
770a9717f387
|
# Maps this image through a lookup table or function. |
1098 |
770a9717f387
|
# |
1099 |
770a9717f387
|
# @param lut A lookup table, containing 256 values per band in the |
1100 |
770a9717f387
|
# image. A function can be used instead, it should take a single |
1101 |
770a9717f387
|
# argument. The function is called once for each possible pixel |
1102 |
770a9717f387
|
# value, and the resulting table is applied to all bands of the |
1103 |
770a9717f387
|
# image. |
1104 |
770a9717f387
|
# @param mode Output mode (default is same as input). In the |
1105 |
770a9717f387
|
# current version, this can only be used if the source image |
1106 |
770a9717f387
|
# has mode "L" or "P", and the output has mode "1". |
1107 |
770a9717f387
|
# @return An Image object. |
1108 |
770a9717f387
|
|
1109 |
770a9717f387
|
def point(self, lut, mode=None): |
1110 |
770a9717f387
|
"Map image through lookup table" |
1111 |
770a9717f387
|
|
1112 |
770a9717f387
|
self.load() |
1113 |
770a9717f387
|
|
1114 |
87168c0c877f
|
if isinstance(lut, ImagePointHandler): |
1115 |
87168c0c877f
|
return lut.point(self) |
1116 |
87168c0c877f
|
|
1117 |
770a9717f387
|
if not isSequenceType(lut): |
1118 |
770a9717f387
|
# if it isn't a list, it should be a function |
1119 |
770a9717f387
|
if self.mode in ("I", "I;16", "F"): |
1120 |
770a9717f387
|
# check if the function can be used with point_transform |
1121 |
770a9717f387
|
scale, offset = _getscaleoffset(lut) |
1122 |
770a9717f387
|
return self._new(self.im.point_transform(scale, offset)) |
1123 |
770a9717f387
|
# for other modes, convert the function to a table |
1124 |
770a9717f387
|
lut = map(lut, range(256)) * self.im.bands |
1125 |
770a9717f387
|
|
1126 |
770a9717f387
|
if self.mode == "F": |
1127 |
770a9717f387
|
# FIXME: _imaging returns a confusing error message for this case |
1128 |
770a9717f387
|
raise ValueError("point operation not supported for this mode") |
1129 |
770a9717f387
|
|
1130 |
770a9717f387
|
return self._new(self.im.point(lut, mode)) |
1131 |
770a9717f387
|
|
1132 |
770a9717f387
|
## |
1133 |
770a9717f387
|
# Adds or replaces the alpha layer in this image. If the image |
1134 |
770a9717f387
|
# does not have an alpha layer, it's converted to "LA" or "RGBA". |
1135 |
770a9717f387
|
# The new layer must be either "L" or "1". |
1136 |
770a9717f387
|
# |
1137 |
770a9717f387
|
# @param im The new alpha layer. This can either be an "L" or "1" |
1138 |
770a9717f387
|
# image having the same size as this image, or an integer or |
1139 |
770a9717f387
|
# other color value. |
1140 |
770a9717f387
|
|
1141 |
770a9717f387
|
def putalpha(self, alpha): |
1142 |
770a9717f387
|
"Set alpha layer" |
1143 |
770a9717f387
|
|
1144 |
770a9717f387
|
self.load() |
1145 |
770a9717f387
|
if self.readonly: |
1146 |
770a9717f387
|
self._copy() |
1147 |
770a9717f387
|
|
1148 |
770a9717f387
|
if self.mode not in ("LA", "RGBA"): |
1149 |
770a9717f387
|
# attempt to promote self to a matching alpha mode |
1150 |
770a9717f387
|
try: |
1151 |
770a9717f387
|
mode = getmodebase(self.mode) + "A" |
1152 |
770a9717f387
|
try: |
1153 |
770a9717f387
|
self.im.setmode(mode) |
1154 |
770a9717f387
|
except (AttributeError, ValueError): |
1155 |
770a9717f387
|
# do things the hard way |
1156 |
770a9717f387
|
im = self.im.convert(mode) |
1157 |
770a9717f387
|
if im.mode not in ("LA", "RGBA"): |
1158 |
770a9717f387
|
raise ValueError # sanity check |
1159 |
770a9717f387
|
self.im = im |
1160 |
770a9717f387
|
self.mode = self.im.mode |
1161 |
770a9717f387
|
except (KeyError, ValueError): |
1162 |
770a9717f387
|
raise ValueError("illegal image mode") |
1163 |
770a9717f387
|
|
1164 |
770a9717f387
|
if self.mode == "LA": |
1165 |
770a9717f387
|
band = 1 |
1166 |
770a9717f387
|
else: |
1167 |
770a9717f387
|
band = 3 |
1168 |
770a9717f387
|
|
1169 |
770a9717f387
|
if isImageType(alpha): |
1170 |
770a9717f387
|
# alpha layer |
1171 |
770a9717f387
|
if alpha.mode not in ("1", "L"): |
1172 |
770a9717f387
|
raise ValueError("illegal image mode") |
1173 |
770a9717f387
|
alpha.load() |
1174 |
770a9717f387
|
if alpha.mode == "1": |
1175 |
770a9717f387
|
alpha = alpha.convert("L") |
1176 |
770a9717f387
|
else: |
1177 |
770a9717f387
|
# constant alpha |
1178 |
770a9717f387
|
try: |
1179 |
770a9717f387
|
self.im.fillband(band, alpha) |
1180 |
770a9717f387
|
except (AttributeError, ValueError): |
1181 |
770a9717f387
|
# do things the hard way |
1182 |
770a9717f387
|
alpha = new("L", self.size, alpha) |
1183 |
770a9717f387
|
else: |
1184 |
770a9717f387
|
return |
1185 |
770a9717f387
|
|
1186 |
770a9717f387
|
self.im.putband(alpha.im, band) |
1187 |
770a9717f387
|
|
1188 |
770a9717f387
|
## |
1189 |
770a9717f387
|
# Copies pixel data to this image. This method copies data from a |
1190 |
770a9717f387
|
# sequence object into the image, starting at the upper left |
1191 |
770a9717f387
|
# corner (0, 0), and continuing until either the image or the |
1192 |
770a9717f387
|
# sequence ends. The scale and offset values are used to adjust |
1193 |
770a9717f387
|
# the sequence values: <b>pixel = value*scale + offset</b>. |
1194 |
770a9717f387
|
# |
1195 |
770a9717f387
|
# @param data A sequence object. |
1196 |
770a9717f387
|
# @param scale An optional scale value. The default is 1.0. |
1197 |
770a9717f387
|
# @param offset An optional offset value. The default is 0.0. |
1198 |
770a9717f387
|
|
1199 |
770a9717f387
|
def putdata(self, data, scale=1.0, offset=0.0): |
1200 |
770a9717f387
|
"Put data from a sequence object into an image." |
1201 |
770a9717f387
|
|
1202 |
770a9717f387
|
self.load() |
1203 |
770a9717f387
|
if self.readonly: |
1204 |
770a9717f387
|
self._copy() |
1205 |
770a9717f387
|
|
1206 |
770a9717f387
|
self.im.putdata(data, scale, offset) |
1207 |
770a9717f387
|
|
1208 |
770a9717f387
|
## |
1209 |
770a9717f387
|
# Attaches a palette to this image. The image must be a "P" or |
1210 |
770a9717f387
|
# "L" image, and the palette sequence must contain 768 integer |
1211 |
770a9717f387
|
# values, where each group of three values represent the red, |
1212 |
770a9717f387
|
# green, and blue values for the corresponding pixel |
1213 |
770a9717f387
|
# index. Instead of an integer sequence, you can use an 8-bit |
1214 |
770a9717f387
|
# string. |
1215 |
770a9717f387
|
# |
1216 |
770a9717f387
|
# @def putpalette(data) |
1217 |
770a9717f387
|
# @param data A palette sequence (either a list or a string). |
1218 |
770a9717f387
|
|
1219 |
770a9717f387
|
def putpalette(self, data, rawmode="RGB"): |
1220 |
770a9717f387
|
"Put palette data into an image." |
1221 |
770a9717f387
|
|
1222 |
770a9717f387
|
if self.mode not in ("L", "P"): |
1223 |
770a9717f387
|
raise ValueError("illegal image mode") |
1224 |
915c68a71749
|
self.load() |
1225 |
915c68a71749
|
if isinstance(data, ImagePalette.ImagePalette): |
1226 |
915c68a71749
|
palette = ImagePalette.raw(data.rawmode, data.palette) |
1227 |
915c68a71749
|
else: |
1228 |
915c68a71749
|
if not isStringType(data): |
1229 |
915c68a71749
|
data = string.join(map(chr, data), "") |
1230 |
915c68a71749
|
palette = ImagePalette.raw(rawmode, data) |
1231 |
770a9717f387
|
self.mode = "P" |
1232 |
915c68a71749
|
self.palette = palette |
1233 |
770a9717f387
|
self.palette.mode = "RGB" |
1234 |
770a9717f387
|
self.load() # install new palette |
1235 |
770a9717f387
|
|
1236 |
770a9717f387
|
## |
1237 |
770a9717f387
|
# Modifies the pixel at the given position. The colour is given as |
1238 |
770a9717f387
|
# a single numerical value for single-band images, and a tuple for |
1239 |
770a9717f387
|
# multi-band images. |
1240 |
770a9717f387
|
# <p> |
1241 |
770a9717f387
|
# Note that this method is relatively slow. For more extensive |
1242 |
770a9717f387
|
# changes, use {@link #Image.paste} or the <b>ImageDraw</b> module |
1243 |
770a9717f387
|
# instead. |
1244 |
770a9717f387
|
# |
1245 |
770a9717f387
|
# @param xy The pixel coordinate, given as (x, y). |
1246 |
770a9717f387
|
# @param value The pixel value. |
1247 |
770a9717f387
|
# @see #Image.paste |
1248 |
770a9717f387
|
# @see #Image.putdata |
1249 |
770a9717f387
|
# @see ImageDraw |
1250 |
770a9717f387
|
|
1251 |
770a9717f387
|
def putpixel(self, xy, value): |
1252 |
770a9717f387
|
"Set pixel value" |
1253 |
770a9717f387
|
|
1254 |
770a9717f387
|
self.load() |
1255 |
770a9717f387
|
if self.readonly: |
1256 |
770a9717f387
|
self._copy() |
1257 |
770a9717f387
|
|
1258 |
770a9717f387
|
return self.im.putpixel(xy, value) |
1259 |
770a9717f387
|
|
1260 |
770a9717f387
|
## |
1261 |
770a9717f387
|
# Returns a resized copy of this image. |
1262 |
770a9717f387
|
# |
1263 |
770a9717f387
|
# @def resize(size, filter=NEAREST) |
1264 |
770a9717f387
|
# @param size The requested size in pixels, as a 2-tuple: |
1265 |
770a9717f387
|
# (width, height). |
1266 |
770a9717f387
|
# @param filter An optional resampling filter. This can be |
1267 |
770a9717f387
|
# one of <b>NEAREST</b> (use nearest neighbour), <b>BILINEAR</b> |
1268 |
770a9717f387
|
# (linear interpolation in a 2x2 environment), <b>BICUBIC</b> |
1269 |
770a9717f387
|
# (cubic spline interpolation in a 4x4 environment), or |
1270 |
770a9717f387
|
# <b>ANTIALIAS</b> (a high-quality downsampling filter). |
1271 |
770a9717f387
|
# If omitted, or if the image has mode "1" or "P", it is |
1272 |
770a9717f387
|
# set <b>NEAREST</b>. |
1273 |
770a9717f387
|
# @return An Image object. |
1274 |
770a9717f387
|
|
1275 |
770a9717f387
|
def resize(self, size, resample=NEAREST): |
1276 |
770a9717f387
|
"Resize image" |
1277 |
770a9717f387
|
|
1278 |
770a9717f387
|
if resample not in (NEAREST, BILINEAR, BICUBIC, ANTIALIAS): |
1279 |
770a9717f387
|
raise ValueError("unknown resampling filter") |
1280 |
770a9717f387
|
|
1281 |
770a9717f387
|
self.load() |
1282 |
770a9717f387
|
|
1283 |
770a9717f387
|
if self.mode in ("1", "P"): |
1284 |
770a9717f387
|
resample = NEAREST |
1285 |
770a9717f387
|
|
1286 |
770a9717f387
|
if resample == ANTIALIAS: |
1287 |
770a9717f387
|
# requires stretch support (imToolkit & PIL 1.1.3) |
1288 |
770a9717f387
|
try: |
1289 |
770a9717f387
|
im = self.im.stretch(size, resample) |
1290 |
770a9717f387
|
except AttributeError: |
1291 |
770a9717f387
|
raise ValueError("unsupported resampling filter") |
1292 |
770a9717f387
|
else: |
1293 |
770a9717f387
|
im = self.im.resize(size, resample) |
1294 |
770a9717f387
|
|
1295 |
770a9717f387
|
return self._new(im) |
1296 |
770a9717f387
|
|
1297 |
770a9717f387
|
## |
1298 |
770a9717f387
|
# Returns a rotated copy of this image. This method returns a |
1299 |
770a9717f387
|
# copy of this image, rotated the given number of degrees counter |
1300 |
770a9717f387
|
# clockwise around its centre. |
1301 |
770a9717f387
|
# |
1302 |
770a9717f387
|
# @def rotate(angle, filter=NEAREST) |
1303 |
770a9717f387
|
# @param angle In degrees counter clockwise. |
1304 |
770a9717f387
|
# @param filter An optional resampling filter. This can be |
1305 |
770a9717f387
|
# one of <b>NEAREST</b> (use nearest neighbour), <b>BILINEAR</b> |
1306 |
770a9717f387
|
# (linear interpolation in a 2x2 environment), or <b>BICUBIC</b> |
1307 |
770a9717f387
|
# (cubic spline interpolation in a 4x4 environment). |
1308 |
770a9717f387
|
# If omitted, or if the image has mode "1" or "P", it is |
1309 |
770a9717f387
|
# set <b>NEAREST</b>. |
1310 |
770a9717f387
|
# @param expand Optional expansion flag. If true, expands the output |
1311 |
770a9717f387
|
# image to make it large enough to hold the entire rotated image. |
1312 |
770a9717f387
|
# If false or omitted, make the output image the same size as the |
1313 |
770a9717f387
|
# input image. |
1314 |
770a9717f387
|
# @return An Image object. |
1315 |
770a9717f387
|
|
1316 |
770a9717f387
|
def rotate(self, angle, resample=NEAREST, expand=0): |
1317 |
770a9717f387
|
"Rotate image. Angle given as degrees counter-clockwise." |
1318 |
770a9717f387
|
|
1319 |
770a9717f387
|
if expand: |
1320 |
770a9717f387
|
import math |
1321 |
770a9717f387
|
angle = -angle * math.pi / 180 |
1322 |
770a9717f387
|
matrix = [ |
1323 |
770a9717f387
|
math.cos(angle), math.sin(angle), 0.0, |
1324 |
770a9717f387
|
-math.sin(angle), math.cos(angle), 0.0 |
1325 |
770a9717f387
|
] |
1326 |
770a9717f387
|
def transform(x, y, (a, b, c, d, e, f)=matrix): |
1327 |
770a9717f387
|
return a*x + b*y + c, d*x + e*y + f |
1328 |
770a9717f387
|
|
1329 |
770a9717f387
|
# calculate output size |
1330 |
770a9717f387
|
w, h = self.size |
1331 |
770a9717f387
|
xx = [] |
1332 |
770a9717f387
|
yy = [] |
1333 |
770a9717f387
|
for x, y in ((0, 0), (w, 0), (w, h), (0, h)): |
1334 |
770a9717f387
|
x, y = transform(x, y) |
1335 |
770a9717f387
|
xx.append(x) |
1336 |
770a9717f387
|
yy.append(y) |
1337 |
770a9717f387
|
w = int(math.ceil(max(xx)) - math.floor(min(xx))) |
1338 |
770a9717f387
|
h = int(math.ceil(max(yy)) - math.floor(min(yy))) |
1339 |
770a9717f387
|
|
1340 |
770a9717f387
|
# adjust center |
1341 |
770a9717f387
|
x, y = transform(w / 2.0, h / 2.0) |
1342 |
770a9717f387
|
matrix[2] = self.size[0] / 2.0 - x |
1343 |
770a9717f387
|
matrix[5] = self.size[1] / 2.0 - y |
1344 |
770a9717f387
|
|
1345 |
db1b40ca85c4
|
return self.transform((w, h), AFFINE, matrix, resample) |
1346 |
770a9717f387
|
|
1347 |
770a9717f387
|
if resample not in (NEAREST, BILINEAR, BICUBIC): |
1348 |
770a9717f387
|
raise ValueError("unknown resampling filter") |
1349 |
770a9717f387
|
|
1350 |
770a9717f387
|
self.load() |
1351 |
770a9717f387
|
|
1352 |
770a9717f387
|
if self.mode in ("1", "P"): |
1353 |
770a9717f387
|
resample = NEAREST |
1354 |
770a9717f387
|
|
1355 |
770a9717f387
|
return self._new(self.im.rotate(angle, resample)) |
1356 |
770a9717f387
|
|
1357 |
770a9717f387
|
## |
1358 |
770a9717f387
|
# Saves this image under the given filename. If no format is |
1359 |
770a9717f387
|
# specified, the format to use is determined from the filename |
1360 |
770a9717f387
|
# extension, if possible. |
1361 |
770a9717f387
|
# <p> |
1362 |
770a9717f387
|
# Keyword options can be used to provide additional instructions |
1363 |
770a9717f387
|
# to the writer. If a writer doesn't recognise an option, it is |
1364 |
770a9717f387
|
# silently ignored. The available options are described later in |
1365 |
770a9717f387
|
# this handbook. |
1366 |
770a9717f387
|
# <p> |
1367 |
770a9717f387
|
# You can use a file object instead of a filename. In this case, |
1368 |
770a9717f387
|
# you must always specify the format. The file object must |
1369 |
770a9717f387
|
# implement the <b>seek</b>, <b>tell</b>, and <b>write</b> |
1370 |
770a9717f387
|
# methods, and be opened in binary mode. |
1371 |
770a9717f387
|
# |
1372 |
770a9717f387
|
# @def save(file, format=None, **options) |
1373 |
770a9717f387
|
# @param file File name or file object. |
1374 |
770a9717f387
|
# @param format Optional format override. If omitted, the |
1375 |
770a9717f387
|
# format to use is determined from the filename extension. |
1376 |
770a9717f387
|
# If a file object was used instead of a filename, this |
1377 |
770a9717f387
|
# parameter should always be used. |
1378 |
770a9717f387
|
# @param **options Extra parameters to the image writer. |
1379 |
770a9717f387
|
# @return None |
1380 |
770a9717f387
|
# @exception KeyError If the output format could not be determined |
1381 |
770a9717f387
|
# from the file name. Use the format option to solve this. |
1382 |
770a9717f387
|
# @exception IOError If the file could not be written. The file |
1383 |
770a9717f387
|
# may have been created, and may contain partial data. |
1384 |
770a9717f387
|
|
1385 |
770a9717f387
|
def save(self, fp, format=None, **params): |
1386 |
770a9717f387
|
"Save image to file or stream" |
1387 |
770a9717f387
|
|
1388 |
770a9717f387
|
if isStringType(fp): |
1389 |
770a9717f387
|
filename = fp |
1390 |
770a9717f387
|
else: |
1391 |
770a9717f387
|
if hasattr(fp, "name") and isStringType(fp.name): |
1392 |
770a9717f387
|
filename = fp.name |
1393 |
770a9717f387
|
else: |
1394 |
770a9717f387
|
filename = "" |
1395 |
770a9717f387
|
|
1396 |
770a9717f387
|
# may mutate self! |
1397 |
770a9717f387
|
self.load() |
1398 |
770a9717f387
|
|
1399 |
770a9717f387
|
self.encoderinfo = params |
1400 |
770a9717f387
|
self.encoderconfig = () |
1401 |
770a9717f387
|
|
1402 |
770a9717f387
|
preinit() |
1403 |
770a9717f387
|
|
1404 |
770a9717f387
|
ext = string.lower(os.path.splitext(filename)[1]) |
1405 |
770a9717f387
|
|
1406 |
770a9717f387
|
if not format: |
1407 |
770a9717f387
|
try: |
1408 |
770a9717f387
|
format = EXTENSION[ext] |
1409 |
770a9717f387
|
except KeyError: |
1410 |
770a9717f387
|
init() |
1411 |
770a9717f387
|
try: |
1412 |
770a9717f387
|
format = EXTENSION[ext] |
1413 |
770a9717f387
|
except KeyError: |
1414 |
770a9717f387
|
raise KeyError(ext) # unknown extension |
1415 |
770a9717f387
|
|
1416 |
770a9717f387
|
try: |
1417 |
770a9717f387
|
save_handler = SAVE[string.upper(format)] |
1418 |
770a9717f387
|
except KeyError: |
1419 |
770a9717f387
|
init() |
1420 |
770a9717f387
|
save_handler = SAVE[string.upper(format)] # unknown format |
1421 |
770a9717f387
|
|
1422 |
770a9717f387
|
if isStringType(fp): |
1423 |
770a9717f387
|
import __builtin__ |
1424 |
770a9717f387
|
fp = __builtin__.open(fp, "wb") |
1425 |
770a9717f387
|
close = 1 |
1426 |
770a9717f387
|
else: |
1427 |
770a9717f387
|
close = 0 |
1428 |
770a9717f387
|
|
1429 |
770a9717f387
|
try: |
1430 |
770a9717f387
|
save_handler(self, fp, filename) |
1431 |
770a9717f387
|
finally: |
1432 |
770a9717f387
|
# do what we can to clean up |
1433 |
770a9717f387
|
if close: |
1434 |
770a9717f387
|
fp.close() |
1435 |
770a9717f387
|
|
1436 |
770a9717f387
|
## |
1437 |
770a9717f387
|
# Seeks to the given frame in this sequence file. If you seek |
1438 |
770a9717f387
|
# beyond the end of the sequence, the method raises an |
1439 |
770a9717f387
|
# <b>EOFError</b> exception. When a sequence file is opened, the |
1440 |
770a9717f387
|
# library automatically seeks to frame 0. |
1441 |
770a9717f387
|
# <p> |
1442 |
770a9717f387
|
# Note that in the current version of the library, most sequence |
1443 |
770a9717f387
|
# formats only allows you to seek to the next frame. |
1444 |
770a9717f387
|
# |
1445 |
770a9717f387
|
# @param frame Frame number, starting at 0. |
1446 |
770a9717f387
|
# @exception EOFError If the call attempts to seek beyond the end |
1447 |
770a9717f387
|
# of the sequence. |
1448 |
770a9717f387
|
# @see #Image.tell |
1449 |
770a9717f387
|
|
1450 |
770a9717f387
|
def seek(self, frame): |
1451 |
770a9717f387
|
"Seek to given frame in sequence file" |
1452 |
770a9717f387
|
|
1453 |
770a9717f387
|
# overridden by file handlers |
1454 |
770a9717f387
|
if frame != 0: |
1455 |
770a9717f387
|
raise EOFError |
1456 |
770a9717f387
|
|
1457 |
770a9717f387
|
## |
1458 |
770a9717f387
|
# Displays this image. This method is mainly intended for |
1459 |
770a9717f387
|
# debugging purposes. |
1460 |
770a9717f387
|
# <p> |
1461 |
770a9717f387
|
# On Unix platforms, this method saves the image to a temporary |
1462 |
770a9717f387
|
# PPM file, and calls the <b>xv</b> utility. |
1463 |
770a9717f387
|
# <p> |
1464 |
770a9717f387
|
# On Windows, it saves the image to a temporary BMP file, and uses |
1465 |
770a9717f387
|
# the standard BMP display utility to show it (usually Paint). |
1466 |
770a9717f387
|
# |
1467 |
770a9717f387
|
# @def show(title=None) |
1468 |
770a9717f387
|
# @param title Optional title to use for the image window, |
1469 |
770a9717f387
|
# where possible. |
1470 |
770a9717f387
|
|
1471 |
770a9717f387
|
def show(self, title=None, command=None): |
1472 |
770a9717f387
|
"Display image (for debug purposes only)" |
1473 |
770a9717f387
|
|
1474 |
db1b40ca85c4
|
_show(self, title=title, command=command) |
1475 |
770a9717f387
|
|
1476 |
770a9717f387
|
## |
1477 |
770a9717f387
|
# Split this image into individual bands. This method returns a |
1478 |
770a9717f387
|
# tuple of individual image bands from an image. For example, |
1479 |
770a9717f387
|
# splitting an "RGB" image creates three new images each |
1480 |
770a9717f387
|
# containing a copy of one of the original bands (red, green, |
1481 |
770a9717f387
|
# blue). |
1482 |
770a9717f387
|
# |
1483 |
770a9717f387
|
# @return A tuple containing bands. |
1484 |
770a9717f387
|
|
1485 |
770a9717f387
|
def split(self): |
1486 |
770a9717f387
|
"Split image into bands" |
1487 |
770a9717f387
|
|
1488 |
9a61b4e0d39c
|
if self.im.bands == 1: |
1489 |
9a61b4e0d39c
|
ims = [self.copy()] |
1490 |
9a61b4e0d39c
|
else: |
1491 |
9a61b4e0d39c
|
ims = [] |
1492 |
9a61b4e0d39c
|
self.load() |
1493 |
9a61b4e0d39c
|
for i in range(self.im.bands): |
1494 |
9a61b4e0d39c
|
ims.append(self._new(self.im.getband(i))) |
1495 |
770a9717f387
|
return tuple(ims) |
1496 |
770a9717f387
|
|
1497 |
770a9717f387
|
## |
1498 |
770a9717f387
|
# Returns the current frame number. |
1499 |
770a9717f387
|
# |
1500 |
770a9717f387
|
# @return Frame number, starting with 0. |
1501 |
770a9717f387
|
# @see #Image.seek |
1502 |
770a9717f387
|
|
1503 |
770a9717f387
|
def tell(self): |
1504 |
770a9717f387
|
"Return current frame number" |
1505 |
770a9717f387
|
|
1506 |
770a9717f387
|
return 0 |
1507 |
770a9717f387
|
|
1508 |
770a9717f387
|
## |
1509 |
770a9717f387
|
# Make this image into a thumbnail. This method modifies the |
1510 |
770a9717f387
|
# image to contain a thumbnail version of itself, no larger than |
1511 |
770a9717f387
|
# the given size. This method calculates an appropriate thumbnail |
1512 |
770a9717f387
|
# size to preserve the aspect of the image, calls the {@link |
1513 |
770a9717f387
|
# #Image.draft} method to configure the file reader (where |
1514 |
770a9717f387
|
# applicable), and finally resizes the image. |
1515 |
770a9717f387
|
# <p> |
1516 |
770a9717f387
|
# Note that the bilinear and bicubic filters in the current |
1517 |
770a9717f387
|
# version of PIL are not well-suited for thumbnail generation. |
1518 |
770a9717f387
|
# You should use <b>ANTIALIAS</b> unless speed is much more |
1519 |
770a9717f387
|
# important than quality. |
1520 |
770a9717f387
|
# <p> |
1521 |
770a9717f387
|
# Also note that this function modifies the Image object in place. |
1522 |
770a9717f387
|
# If you need to use the full resolution image as well, apply this |
1523 |
770a9717f387
|
# method to a {@link #Image.copy} of the original image. |
1524 |
770a9717f387
|
# |
1525 |
770a9717f387
|
# @param size Requested size. |
1526 |
770a9717f387
|
# @param resample Optional resampling filter. This can be one |
1527 |
770a9717f387
|
# of <b>NEAREST</b>, <b>BILINEAR</b>, <b>BICUBIC</b>, or |
1528 |
770a9717f387
|
# <b>ANTIALIAS</b> (best quality). If omitted, it defaults |
1529 |
770a9717f387
|
# to <b>NEAREST</b> (this will be changed to ANTIALIAS in a |
1530 |
770a9717f387
|
# future version). |
1531 |
770a9717f387
|
# @return None |
1532 |
770a9717f387
|
|
1533 |
770a9717f387
|
def thumbnail(self, size, resample=NEAREST): |
1534 |
770a9717f387
|
"Create thumbnail representation (modifies image in place)" |
1535 |
770a9717f387
|
|
1536 |
770a9717f387
|
# FIXME: the default resampling filter will be changed |
1537 |
770a9717f387
|
# to ANTIALIAS in future versions |
1538 |
770a9717f387
|
|
1539 |
770a9717f387
|
# preserve aspect ratio |
1540 |
770a9717f387
|
x, y = self.size |
1541 |
770a9717f387
|
if x > size[0]: y = max(y * size[0] / x, 1); x = size[0] |
1542 |
770a9717f387
|
if y > size[1]: x = max(x * size[1] / y, 1); y = size[1] |
1543 |
770a9717f387
|
size = x, y |
1544 |
770a9717f387
|
|
1545 |
770a9717f387
|
if size == self.size: |
1546 |
770a9717f387
|
return |
1547 |
770a9717f387
|
|
1548 |
770a9717f387
|
self.draft(None, size) |
1549 |
770a9717f387
|
|
1550 |
770a9717f387
|
self.load() |
1551 |
770a9717f387
|
|
1552 |
770a9717f387
|
try: |
1553 |
770a9717f387
|
im = self.resize(size, resample) |
1554 |
770a9717f387
|
except ValueError: |
1555 |
770a9717f387
|
if resample != ANTIALIAS: |
1556 |
770a9717f387
|
raise |
1557 |
770a9717f387
|
im = self.resize(size, NEAREST) # fallback |
1558 |
770a9717f387
|
|
1559 |
770a9717f387
|
self.im = im.im |
1560 |
770a9717f387
|
self.mode = im.mode |
1561 |
770a9717f387
|
self.size = size |
1562 |
770a9717f387
|
|
1563 |
770a9717f387
|
self.readonly = 0 |
1564 |
770a9717f387
|
|
1565 |
770a9717f387
|
# FIXME: the different tranform methods need further explanation |
1566 |
770a9717f387
|
# instead of bloating the method docs, add a separate chapter. |
1567 |
770a9717f387
|
|
1568 |
770a9717f387
|
## |
1569 |
770a9717f387
|
# Transforms this image. This method creates a new image with the |
1570 |
770a9717f387
|
# given size, and the same mode as the original, and copies data |
1571 |
770a9717f387
|
# to the new image using the given transform. |
1572 |
770a9717f387
|
# <p> |
1573 |
770a9717f387
|
# @def transform(size, method, data, resample=NEAREST) |
1574 |
770a9717f387
|
# @param size The output size. |
1575 |
770a9717f387
|
# @param method The transformation method. This is one of |
1576 |
770a9717f387
|
# <b>EXTENT</b> (cut out a rectangular subregion), <b>AFFINE</b> |
1577 |
770a9717f387
|
# (affine transform), <b>PERSPECTIVE</b> (perspective |
1578 |
770a9717f387
|
# transform), <b>QUAD</b> (map a quadrilateral to a |
1579 |
770a9717f387
|
# rectangle), or <b>MESH</b> (map a number of source quadrilaterals |
1580 |
770a9717f387
|
# in one operation). |
1581 |
770a9717f387
|
# @param data Extra data to the transformation method. |
1582 |
770a9717f387
|
# @param resample Optional resampling filter. It can be one of |
1583 |
770a9717f387
|
# <b>NEAREST</b> (use nearest neighbour), <b>BILINEAR</b> |
1584 |
770a9717f387
|
# (linear interpolation in a 2x2 environment), or |
1585 |
770a9717f387
|
# <b>BICUBIC</b> (cubic spline interpolation in a 4x4 |
1586 |
770a9717f387
|
# environment). If omitted, or if the image has mode |
1587 |
770a9717f387
|
# "1" or "P", it is set to <b>NEAREST</b>. |
1588 |
770a9717f387
|
# @return An Image object. |
1589 |
770a9717f387
|
|
1590 |
770a9717f387
|
def transform(self, size, method, data=None, resample=NEAREST, fill=1): |
1591 |
770a9717f387
|
"Transform image" |
1592 |
770a9717f387
|
|
1593 |
87168c0c877f
|
if isinstance(method, ImageTransformHandler): |
1594 |
87168c0c877f
|
return method.transform(size, self, resample=resample, fill=fill) |
1595 |
1e08a00b485b
|
if hasattr(method, "getdata"): |
1596 |
87168c0c877f
|
# compatibility w. old-style transform objects |
1597 |
770a9717f387
|
method, data = method.getdata() |
1598 |
770a9717f387
|
if data is None: |
1599 |
770a9717f387
|
raise ValueError("missing method data") |
1600 |
770a9717f387
|
im = new(self.mode, size, None) |
1601 |
770a9717f387
|
if method == MESH: |
1602 |
770a9717f387
|
# list of quads |
1603 |
770a9717f387
|
for box, quad in data: |
1604 |
770a9717f387
|
im.__transformer(box, self, QUAD, quad, resample, fill) |
1605 |
770a9717f387
|
else: |
1606 |
770a9717f387
|
im.__transformer((0, 0)+size, self, method, data, resample, fill) |
1607 |
770a9717f387
|
|
1608 |
770a9717f387
|
return im |
1609 |
770a9717f387
|
|
1610 |
770a9717f387
|
def __transformer(self, box, image, method, data, |
1611 |
770a9717f387
|
resample=NEAREST, fill=1): |
1612 |
770a9717f387
|
|
1613 |
770a9717f387
|
# FIXME: this should be turned into a lazy operation (?) |
1614 |
770a9717f387
|
|
1615 |
770a9717f387
|
w = box[2]-box[0] |
1616 |
770a9717f387
|
h = box[3]-box[1] |
1617 |
770a9717f387
|
|
1618 |
770a9717f387
|
if method == AFFINE: |
1619 |
770a9717f387
|
# change argument order to match implementation |
1620 |
770a9717f387
|
data = (data[2], data[0], data[1], |
1621 |
770a9717f387
|
data[5], data[3], data[4]) |
1622 |
770a9717f387
|
elif method == EXTENT: |
1623 |
770a9717f387
|
# convert extent to an affine transform |
1624 |
770a9717f387
|
x0, y0, x1, y1 = data |
1625 |
770a9717f387
|
xs = float(x1 - x0) / w |
1626 |
770a9717f387
|
ys = float(y1 - y0) / h |
1627 |
770a9717f387
|
method = AFFINE |
1628 |
770a9717f387
|
data = (x0 + xs/2, xs, 0, y0 + ys/2, 0, ys) |
1629 |
770a9717f387
|
elif method == PERSPECTIVE: |
1630 |
770a9717f387
|
# change argument order to match implementation |
1631 |
770a9717f387
|
data = (data[2], data[0], data[1], |
1632 |
770a9717f387
|
data[5], data[3], data[4], |
1633 |
770a9717f387
|
data[6], data[7]) |
1634 |
770a9717f387
|
elif method == QUAD: |
1635 |
770a9717f387
|
# quadrilateral warp. data specifies the four corners |
1636 |
770a9717f387
|
# given as NW, SW, SE, and NE. |
1637 |
770a9717f387
|
nw = data[0:2]; sw = data[2:4]; se = data[4:6]; ne = data[6:8] |
1638 |
770a9717f387
|
x0, y0 = nw; As = 1.0 / w; At = 1.0 / h |
1639 |
770a9717f387
|
data = (x0, (ne[0]-x0)*As, (sw[0]-x0)*At, |
1640 |
770a9717f387
|
(se[0]-sw[0]-ne[0]+x0)*As*At, |
1641 |
770a9717f387
|
y0, (ne[1]-y0)*As, (sw[1]-y0)*At, |
1642 |
770a9717f387
|
(se[1]-sw[1]-ne[1]+y0)*As*At) |
1643 |
770a9717f387
|
else: |
1644 |
770a9717f387
|
raise ValueError("unknown transformation method") |
1645 |
770a9717f387
|
|
1646 |
770a9717f387
|
if resample not in (NEAREST, BILINEAR, BICUBIC): |
1647 |
770a9717f387
|
raise ValueError("unknown resampling filter") |
1648 |
770a9717f387
|
|
1649 |
770a9717f387
|
image.load() |
1650 |
770a9717f387
|
|
1651 |
770a9717f387
|
self.load() |
1652 |
770a9717f387
|
|
1653 |
770a9717f387
|
if image.mode in ("1", "P"): |
1654 |
770a9717f387
|
resample = NEAREST |
1655 |
770a9717f387
|
|
1656 |
770a9717f387
|
self.im.transform2(box, image.im, method, data, resample, fill) |
1657 |
770a9717f387
|
|
1658 |
770a9717f387
|
## |
1659 |
770a9717f387
|
# Returns a flipped or rotated copy of this image. |
1660 |
770a9717f387
|
# |
1661 |
770a9717f387
|
# @param method One of <b>FLIP_LEFT_RIGHT</b>, <b>FLIP_TOP_BOTTOM</b>, |
1662 |
770a9717f387
|
# <b>ROTATE_90</b>, <b>ROTATE_180</b>, or <b>ROTATE_270</b>. |
1663 |
770a9717f387
|
|
1664 |
770a9717f387
|
def transpose(self, method): |
1665 |
770a9717f387
|
"Transpose image (flip or rotate in 90 degree steps)" |
1666 |
770a9717f387
|
|
1667 |
770a9717f387
|
self.load() |
1668 |
770a9717f387
|
im = self.im.transpose(method) |
1669 |
770a9717f387
|
return self._new(im) |
1670 |
770a9717f387
|
|
1671 |
770a9717f387
|
# -------------------------------------------------------------------- |
1672 |
770a9717f387
|
# Lazy operations |
1673 |
770a9717f387
|
|
1674 |
770a9717f387
|
class _ImageCrop(Image): |
1675 |
770a9717f387
|
|
1676 |
770a9717f387
|
def __init__(self, im, box): |
1677 |
770a9717f387
|
|
1678 |
770a9717f387
|
Image.__init__(self) |
1679 |
770a9717f387
|
|
1680 |
770a9717f387
|
x0, y0, x1, y1 = box |
1681 |
770a9717f387
|
if x1 < x0: |
1682 |
770a9717f387
|
x1 = x0 |
1683 |
770a9717f387
|
if y1 < y0: |
1684 |
770a9717f387
|
y1 = y0 |
1685 |
770a9717f387
|
|
1686 |
770a9717f387
|
self.mode = im.mode |
1687 |
770a9717f387
|
self.size = x1-x0, y1-y0 |
1688 |
770a9717f387
|
|
1689 |
770a9717f387
|
self.__crop = x0, y0, x1, y1 |
1690 |
770a9717f387
|
|
1691 |
770a9717f387
|
self.im = im.im |
1692 |
770a9717f387
|
|
1693 |
770a9717f387
|
def load(self): |
1694 |
770a9717f387
|
|
1695 |
770a9717f387
|
# lazy evaluation! |
1696 |
770a9717f387
|
if self.__crop: |
1697 |
770a9717f387
|
self.im = self.im.crop(self.__crop) |
1698 |
770a9717f387
|
self.__crop = None |
1699 |
770a9717f387
|
|
1700 |
088820f6f4b5
|
if self.im: |
1701 |
088820f6f4b5
|
return self.im.pixel_access(self.readonly) |
1702 |
088820f6f4b5
|
|
1703 |
770a9717f387
|
# FIXME: future versions should optimize crop/paste |
1704 |
770a9717f387
|
# sequences! |
1705 |
770a9717f387
|
|
1706 |
770a9717f387
|
# -------------------------------------------------------------------- |
1707 |
87168c0c877f
|
# Abstract handlers. |
1708 |
87168c0c877f
|
|
1709 |
87168c0c877f
|
class ImagePointHandler: |
1710 |
87168c0c877f
|
# used as a mixin by point transforms (for use with im.point) |
1711 |
87168c0c877f
|
pass |
1712 |
87168c0c877f
|
|
1713 |
87168c0c877f
|
class ImageTransformHandler: |
1714 |
87168c0c877f
|
# used as a mixin by geometry transforms (for use with im.transform) |
1715 |
87168c0c877f
|
pass |
1716 |
87168c0c877f
|
|
1717 |
87168c0c877f
|
# -------------------------------------------------------------------- |
1718 |
770a9717f387
|
# Factories |
1719 |
770a9717f387
|
|
1720 |
770a9717f387
|
# |
1721 |
770a9717f387
|
# Debugging |
1722 |
770a9717f387
|
|
1723 |
770a9717f387
|
def _wedge(): |
1724 |
770a9717f387
|
"Create greyscale wedge (for debugging only)" |
1725 |
770a9717f387
|
|
1726 |
770a9717f387
|
return Image()._new(core.wedge("L")) |
1727 |
770a9717f387
|
|
1728 |
770a9717f387
|
## |
1729 |
770a9717f387
|
# Creates a new image with the given mode and size. |
1730 |
770a9717f387
|
# |
1731 |
770a9717f387
|
# @param mode The mode to use for the new image. |
1732 |
770a9717f387
|
# @param size A 2-tuple, containing (width, height) in pixels. |
1733 |
770a9717f387
|
# @param color What colour to use for the image. Default is black. |
1734 |
770a9717f387
|
# If given, this should be a single integer or floating point value |
1735 |
770a9717f387
|
# for single-band modes, and a tuple for multi-band modes (one value |
1736 |
770a9717f387
|
# per band). When creating RGB images, you can also use colour |
1737 |
770a9717f387
|
# strings as supported by the ImageColor module. If the colour is |
1738 |
770a9717f387
|
# None, the image is not initialised. |
1739 |
770a9717f387
|
# @return An Image object. |
1740 |
770a9717f387
|
|
1741 |
770a9717f387
|
def new(mode, size, color=0): |
1742 |
770a9717f387
|
"Create a new image" |
1743 |
770a9717f387
|
|
1744 |
770a9717f387
|
if color is None: |
1745 |
770a9717f387
|
# don't initialize |
1746 |
770a9717f387
|
return Image()._new(core.new(mode, size)) |
1747 |
770a9717f387
|
|
1748 |
770a9717f387
|
if isStringType(color): |
1749 |
770a9717f387
|
# css3-style specifier |
1750 |
770a9717f387
|
|
1751 |
770a9717f387
|
import ImageColor |
1752 |
770a9717f387
|
color = ImageColor.getcolor(color, mode) |
1753 |
770a9717f387
|
|
1754 |
770a9717f387
|
return Image()._new(core.fill(mode, size, color)) |
1755 |
770a9717f387
|
|
1756 |
770a9717f387
|
## |
1757 |
770a9717f387
|
# Creates an image memory from pixel data in a string. |
1758 |
770a9717f387
|
# <p> |
1759 |
770a9717f387
|
# In its simplest form, this function takes three arguments |
1760 |
770a9717f387
|
# (mode, size, and unpacked pixel data). |
1761 |
770a9717f387
|
# <p> |
1762 |
770a9717f387
|
# You can also use any pixel decoder supported by PIL. For more |
1763 |
770a9717f387
|
# information on available decoders, see the section <a |
1764 |
770a9717f387
|
# href="pil-decoder.htm"><i>Writing Your Own File Decoder</i></a>. |
1765 |
770a9717f387
|
# <p> |
1766 |
770a9717f387
|
# Note that this function decodes pixel data only, not entire images. |
1767 |
770a9717f387
|
# If you have an entire image in a string, wrap it in a |
1768 |
770a9717f387
|
# <b>StringIO</b> object, and use {@link #open} to load it. |
1769 |
770a9717f387
|
# |
1770 |
770a9717f387
|
# @param mode The image mode. |
1771 |
770a9717f387
|
# @param size The image size. |
1772 |
770a9717f387
|
# @param data An 8-bit string containing raw data for the given mode. |
1773 |
770a9717f387
|
# @param decoder_name What decoder to use. |
1774 |
770a9717f387
|
# @param *args Additional parameters for the given decoder. |
1775 |
770a9717f387
|
# @return An Image object. |
1776 |
770a9717f387
|
|
1777 |
770a9717f387
|
def fromstring(mode, size, data, decoder_name="raw", *args): |
1778 |
770a9717f387
|
"Load image from string" |
1779 |
770a9717f387
|
|
1780 |
770a9717f387
|
# may pass tuple instead of argument list |
1781 |
770a9717f387
|
if len(args) == 1 and isTupleType(args[0]): |
1782 |
770a9717f387
|
args = args[0] |
1783 |
770a9717f387
|
|
1784 |
770a9717f387
|
if decoder_name == "raw" and args == (): |
1785 |
770a9717f387
|
args = mode |
1786 |
770a9717f387
|
|
1787 |
770a9717f387
|
im = new(mode, size) |
1788 |
770a9717f387
|
im.fromstring(data, decoder_name, args) |
1789 |
770a9717f387
|
return im |
1790 |
770a9717f387
|
|
1791 |
770a9717f387
|
## |
1792 |
770a9717f387
|
# (New in 1.1.4) Creates an image memory from pixel data in a string |
1793 |
770a9717f387
|
# or byte buffer. |
1794 |
770a9717f387
|
# <p> |
1795 |
770a9717f387
|
# This function is similar to {@link #fromstring}, but uses data in |
1796 |
770a9717f387
|
# the byte buffer, where possible. This means that changes to the |
1797 |
770a9717f387
|
# original buffer object are reflected in this image). Not all modes |
1798 |
770a9717f387
|
# can share memory; supported modes include "L", "RGBX", "RGBA", and |
1799 |
770a9717f387
|
# "CMYK". |
1800 |
770a9717f387
|
# <p> |
1801 |
770a9717f387
|
# Note that this function decodes pixel data only, not entire images. |
1802 |
770a9717f387
|
# If you have an entire image file in a string, wrap it in a |
1803 |
770a9717f387
|
# <b>StringIO</b> object, and use {@link #open} to load it. |
1804 |
770a9717f387
|
# <p> |
1805 |
770a9717f387
|
# In the current version, the default parameters used for the "raw" |
1806 |
770a9717f387
|
# decoder differs from that used for {@link fromstring}. This is a |
1807 |
770a9717f387
|
# bug, and will probably be fixed in a future release. The current |
1808 |
770a9717f387
|
# release issues a warning if you do this; to disable the warning, |
1809 |
770a9717f387
|
# you should provide the full set of parameters. See below for |
1810 |
770a9717f387
|
# details. |
1811 |
770a9717f387
|
# |
1812 |
770a9717f387
|
# @param mode The image mode. |
1813 |
770a9717f387
|
# @param size The image size. |
1814 |
770a9717f387
|
# @param data An 8-bit string or other buffer object containing raw |
1815 |
770a9717f387
|
# data for the given mode. |
1816 |
770a9717f387
|
# @param decoder_name What decoder to use. |
1817 |
770a9717f387
|
# @param *args Additional parameters for the given decoder. For the |
1818 |
770a9717f387
|
# default encoder ("raw"), it's recommended that you provide the |
1819 |
770a9717f387
|
# full set of parameters: |
1820 |
770a9717f387
|
# <b>frombuffer(mode, size, data, "raw", mode, 0, 1)</b>. |
1821 |
770a9717f387
|
# @return An Image object. |
1822 |
770a9717f387
|
# @since 1.1.4 |
1823 |
770a9717f387
|
|
1824 |
770a9717f387
|
def frombuffer(mode, size, data, decoder_name="raw", *args): |
1825 |
770a9717f387
|
"Load image from string or buffer" |
1826 |
770a9717f387
|
|
1827 |
770a9717f387
|
# may pass tuple instead of argument list |
1828 |
770a9717f387
|
if len(args) == 1 and isTupleType(args[0]): |
1829 |
770a9717f387
|
args = args[0] |
1830 |
770a9717f387
|
|
1831 |
770a9717f387
|
if decoder_name == "raw": |
1832 |
770a9717f387
|
if args == (): |
1833 |
770a9717f387
|
if warnings: |
1834 |
770a9717f387
|
warnings.warn( |
1835 |
770a9717f387
|
"the frombuffer defaults may change in a future release; " |
1836 |
770a9717f387
|
"for portability, change the call to read:\n" |
1837 |
770a9717f387
|
" frombuffer(mode, size, data, 'raw', mode, 0, 1)", |
1838 |
770a9717f387
|
RuntimeWarning, stacklevel=2 |
1839 |
770a9717f387
|
) |
1840 |
770a9717f387
|
args = mode, 0, -1 # may change to (mode, 0, 1) post-1.1.6 |
1841 |
770a9717f387
|
if args[0] in _MAPMODES: |
1842 |
770a9717f387
|
im = new(mode, (1,1)) |
1843 |
770a9717f387
|
im = im._new( |
1844 |
770a9717f387
|
core.map_buffer(data, size, decoder_name, None, 0, args) |
1845 |
770a9717f387
|
) |
1846 |
770a9717f387
|
im.readonly = 1 |
1847 |
770a9717f387
|
return im |
1848 |
770a9717f387
|
|
1849 |
db1b40ca85c4
|
return fromstring(mode, size, data, decoder_name, args) |
1850 |
770a9717f387
|
|
1851 |
770a9717f387
|
|
1852 |
770a9717f387
|
## |
1853 |
49cea88ebb6b
|
# (New in 1.1.6) Creates an image memory from an object exporting |
1854 |
770a9717f387
|
# the array interface (using the buffer protocol). |
1855 |
770a9717f387
|
# |
1856 |
770a9717f387
|
# If obj is not contiguous, then the tostring method is called |
1857 |
770a9717f387
|
# and {@link frombuffer} is used. |
1858 |
770a9717f387
|
# |
1859 |
770a9717f387
|
# @param obj Object with array interface |
1860 |
770a9717f387
|
# @param mode Mode to use (will be determined from type if None) |
1861 |
770a9717f387
|
# @return An image memory. |
1862 |
770a9717f387
|
|
1863 |
770a9717f387
|
def fromarray(obj, mode=None): |
1864 |
770a9717f387
|
arr = obj.__array_interface__ |
1865 |
770a9717f387
|
shape = arr['shape'] |
1866 |
770a9717f387
|
ndim = len(shape) |
1867 |
770a9717f387
|
try: |
1868 |
770a9717f387
|
strides = arr['strides'] |
1869 |
770a9717f387
|
except KeyError: |
1870 |
770a9717f387
|
strides = None |
1871 |
770a9717f387
|
if mode is None: |
1872 |
d0601283ed62
|
try: |
1873 |
d0601283ed62
|
typekey = (1, 1) + shape[2:], arr['typestr'] |
1874 |
d0601283ed62
|
mode, rawmode = _fromarray_typemap[typekey] |
1875 |
d0601283ed62
|
except KeyError: |
1876 |
d0601283ed62
|
# print typekey |
1877 |
d0601283ed62
|
raise TypeError("Cannot handle this data type") |
1878 |
d0601283ed62
|
else: |
1879 |
d0601283ed62
|
rawmode = mode |
1880 |
d0601283ed62
|
if mode in ["1", "L", "I", "P", "F"]: |
1881 |
770a9717f387
|
ndmax = 2 |
1882 |
d0601283ed62
|
elif mode == "RGB": |
1883 |
770a9717f387
|
ndmax = 3 |
1884 |
49cea88ebb6b
|
else: |
1885 |
49cea88ebb6b
|
ndmax = 4 |
1886 |
770a9717f387
|
if ndim > ndmax: |
1887 |
770a9717f387
|
raise ValueError("Too many dimensions.") |
1888 |
770a9717f387
|
|
1889 |
49cea88ebb6b
|
size = shape[1], shape[0] |
1890 |
770a9717f387
|
if strides is not None: |
1891 |
770a9717f387
|
obj = obj.tostring() |
1892 |
770a9717f387
|
|
1893 |
d0601283ed62
|
return frombuffer(mode, size, obj, "raw", rawmode, 0, 1) |
1894 |
d0601283ed62
|
|
1895 |
d0601283ed62
|
_fromarray_typemap = { |
1896 |
d0601283ed62
|
# (shape, typestr) => mode, rawmode |
1897 |
d0601283ed62
|
# first two members of shape are set to one |
1898 |
ac9410828fed
|
# ((1, 1), "|b1"): ("1", "1"), # broken |
1899 |
d0601283ed62
|
((1, 1), "|u1"): ("L", "L"), |
1900 |
d0601283ed62
|
((1, 1), "|i1"): ("I", "I;8"), |
1901 |
5862df75157e
|
((1, 1), "<i2"): ("I", "I;16L"), |
1902 |
d0601283ed62
|
((1, 1), ">i2"): ("I", "I;16B"), |
1903 |
5862df75157e
|
((1, 1), "<i4"): ("I", "I;32L"), |
1904 |
d0601283ed62
|
((1, 1), ">i4"): ("I", "I;32B"), |
1905 |
5862df75157e
|
((1, 1), "<f4"): ("F", "F;32LF"), |
1906 |
d0601283ed62
|
((1, 1), ">f4"): ("F", "F;32BF"), |
1907 |
5862df75157e
|
((1, 1), "<f8"): ("F", "F;64LF"), |
1908 |
d0601283ed62
|
((1, 1), ">f8"): ("F", "F;64BF"), |
1909 |
d0601283ed62
|
((1, 1, 3), "|u1"): ("RGB", "RGB"), |
1910 |
d0601283ed62
|
((1, 1, 4), "|u1"): ("RGBA", "RGBA"), |
1911 |
d0601283ed62
|
} |
1912 |
d0601283ed62
|
|
1913 |
d0601283ed62
|
# shortcuts |
1914 |
d0601283ed62
|
_fromarray_typemap[((1, 1), _ENDIAN + "i4")] = ("I", "I") |
1915 |
d0601283ed62
|
_fromarray_typemap[((1, 1), _ENDIAN + "f4")] = ("F", "F") |
1916 |
770a9717f387
|
|
1917 |
770a9717f387
|
## |
1918 |
770a9717f387
|
# Opens and identifies the given image file. |
1919 |
770a9717f387
|
# <p> |
1920 |
770a9717f387
|
# This is a lazy operation; this function identifies the file, but the |
1921 |
770a9717f387
|
# actual image data is not read from the file until you try to process |
1922 |
770a9717f387
|
# the data (or call the {@link #Image.load} method). |
1923 |
770a9717f387
|
# |
1924 |
770a9717f387
|
# @def open(file, mode="r") |
1925 |
770a9717f387
|
# @param file A filename (string) or a file object. The file object |
1926 |
770a9717f387
|
# must implement <b>read</b>, <b>seek</b>, and <b>tell</b> methods, |
1927 |
770a9717f387
|
# and be opened in binary mode. |
1928 |
770a9717f387
|
# @param mode The mode. If given, this argument must be "r". |
1929 |
770a9717f387
|
# @return An Image object. |
1930 |
770a9717f387
|
# @exception IOError If the file cannot be found, or the image cannot be |
1931 |
770a9717f387
|
# opened and identified. |
1932 |
770a9717f387
|
# @see #new |
1933 |
770a9717f387
|
|
1934 |
770a9717f387
|
def open(fp, mode="r"): |
1935 |
770a9717f387
|
"Open an image file, without loading the raster data" |
1936 |
770a9717f387
|
|
1937 |
770a9717f387
|
if mode != "r": |
1938 |
770a9717f387
|
raise ValueError("bad mode") |
1939 |
770a9717f387
|
|
1940 |
770a9717f387
|
if isStringType(fp): |
1941 |
770a9717f387
|
import __builtin__ |
1942 |
770a9717f387
|
filename = fp |
1943 |
770a9717f387
|
fp = __builtin__.open(fp, "rb") |
1944 |
770a9717f387
|
else: |
1945 |
770a9717f387
|
filename = "" |
1946 |
770a9717f387
|
|
1947 |
770a9717f387
|
prefix = fp.read(16) |
1948 |
770a9717f387
|
|
1949 |
770a9717f387
|
preinit() |
1950 |
770a9717f387
|
|
1951 |
770a9717f387
|
for i in ID: |
1952 |
770a9717f387
|
try: |
1953 |
770a9717f387
|
factory, accept = OPEN[i] |
1954 |
770a9717f387
|
if not accept or accept(prefix): |
1955 |
770a9717f387
|
fp.seek(0) |
1956 |
770a9717f387
|
return factory(fp, filename) |
1957 |
770a9717f387
|
except (SyntaxError, IndexError, TypeError): |
1958 |
770a9717f387
|
pass |
1959 |
770a9717f387
|
|
1960 |
454b4d2672f3
|
if init(): |
1961 |
770a9717f387
|
|
1962 |
454b4d2672f3
|
for i in ID: |
1963 |
454b4d2672f3
|
try: |
1964 |
454b4d2672f3
|
factory, accept = OPEN[i] |
1965 |
454b4d2672f3
|
if not accept or accept(prefix): |
1966 |
454b4d2672f3
|
fp.seek(0) |
1967 |
454b4d2672f3
|
return factory(fp, filename) |
1968 |
454b4d2672f3
|
except (SyntaxError, IndexError, TypeError): |
1969 |
454b4d2672f3
|
pass |
1970 |
770a9717f387
|
|
1971 |
770a9717f387
|
raise IOError("cannot identify image file") |
1972 |
770a9717f387
|
|
1973 |
770a9717f387
|
# |
1974 |
770a9717f387
|
# Image processing. |
1975 |
770a9717f387
|
|
1976 |
770a9717f387
|
## |
1977 |
770a9717f387
|
# Creates a new image by interpolating between two input images, using |
1978 |
770a9717f387
|
# a constant alpha. |
1979 |
770a9717f387
|
# |
1980 |
770a9717f387
|
# <pre> |
1981 |
770a9717f387
|
# out = image1 * (1.0 - alpha) + image2 * alpha |
1982 |
770a9717f387
|
# </pre> |
1983 |
770a9717f387
|
# |
1984 |
770a9717f387
|
# @param im1 The first image. |
1985 |
770a9717f387
|
# @param im2 The second image. Must have the same mode and size as |
1986 |
770a9717f387
|
# the first image. |
1987 |
770a9717f387
|
# @param alpha The interpolation alpha factor. If alpha is 0.0, a |
1988 |
770a9717f387
|
# copy of the first image is returned. If alpha is 1.0, a copy of |
1989 |
770a9717f387
|
# the second image is returned. There are no restrictions on the |
1990 |
770a9717f387
|
# alpha value. If necessary, the result is clipped to fit into |
1991 |
770a9717f387
|
# the allowed output range. |
1992 |
770a9717f387
|
# @return An Image object. |
1993 |
770a9717f387
|
|
1994 |
770a9717f387
|
def blend(im1, im2, alpha): |
1995 |
770a9717f387
|
"Interpolate between images." |
1996 |
770a9717f387
|
|
1997 |
770a9717f387
|
im1.load() |
1998 |
770a9717f387
|
im2.load() |
1999 |
770a9717f387
|
return im1._new(core.blend(im1.im, im2.im, alpha)) |
2000 |
770a9717f387
|
|
2001 |
770a9717f387
|
## |
2002 |
770a9717f387
|
# Creates a new image by interpolating between two input images, |
2003 |
770a9717f387
|
# using the mask as alpha. |
2004 |
770a9717f387
|
# |
2005 |
770a9717f387
|
# @param image1 The first image. |
2006 |
770a9717f387
|
# @param image2 The second image. Must have the same mode and |
2007 |
770a9717f387
|
# size as the first image. |
2008 |
770a9717f387
|
# @param mask A mask image. This image can can have mode |
2009 |
770a9717f387
|
# "1", "L", or "RGBA", and must have the same size as the |
2010 |
770a9717f387
|
# other two images. |
2011 |
770a9717f387
|
|
2012 |
770a9717f387
|
def composite(image1, image2, mask): |
2013 |
770a9717f387
|
"Create composite image by blending images using a transparency mask" |
2014 |
770a9717f387
|
|
2015 |
770a9717f387
|
image = image2.copy() |
2016 |
770a9717f387
|
image.paste(image1, None, mask) |
2017 |
770a9717f387
|
return image |
2018 |
770a9717f387
|
|
2019 |
770a9717f387
|
## |
2020 |
770a9717f387
|
# Applies the function (which should take one argument) to each pixel |
2021 |
770a9717f387
|
# in the given image. If the image has more than one band, the same |
2022 |
770a9717f387
|
# function is applied to each band. Note that the function is |
2023 |
770a9717f387
|
# evaluated once for each possible pixel value, so you cannot use |
2024 |
770a9717f387
|
# random components or other generators. |
2025 |
770a9717f387
|
# |
2026 |
770a9717f387
|
# @def eval(image, function) |
2027 |
770a9717f387
|
# @param image The input image. |
2028 |
770a9717f387
|
# @param function A function object, taking one integer argument. |
2029 |
770a9717f387
|
# @return An Image object. |
2030 |
770a9717f387
|
|
2031 |
770a9717f387
|
def eval(image, *args): |
2032 |
770a9717f387
|
"Evaluate image expression" |
2033 |
770a9717f387
|
|
2034 |
770a9717f387
|
return image.point(args[0]) |
2035 |
770a9717f387
|
|
2036 |
770a9717f387
|
## |
2037 |
770a9717f387
|
# Creates a new image from a number of single-band images. |
2038 |
770a9717f387
|
# |
2039 |
770a9717f387
|
# @param mode The mode to use for the output image. |
2040 |
770a9717f387
|
# @param bands A sequence containing one single-band image for |
2041 |
770a9717f387
|
# each band in the output image. All bands must have the |
2042 |
770a9717f387
|
# same size. |
2043 |
770a9717f387
|
# @return An Image object. |
2044 |
770a9717f387
|
|
2045 |
770a9717f387
|
def merge(mode, bands): |
2046 |
770a9717f387
|
"Merge a set of single band images into a new multiband image." |
2047 |
770a9717f387
|
|
2048 |
770a9717f387
|
if getmodebands(mode) != len(bands) or "*" in mode: |
2049 |
770a9717f387
|
raise ValueError("wrong number of bands") |
2050 |
770a9717f387
|
for im in bands[1:]: |
2051 |
770a9717f387
|
if im.mode != getmodetype(mode): |
2052 |
770a9717f387
|
raise ValueError("mode mismatch") |
2053 |
770a9717f387
|
if im.size != bands[0].size: |
2054 |
770a9717f387
|
raise ValueError("size mismatch") |
2055 |
770a9717f387
|
im = core.new(mode, bands[0].size) |
2056 |
770a9717f387
|
for i in range(getmodebands(mode)): |
2057 |
770a9717f387
|
bands[i].load() |
2058 |
770a9717f387
|
im.putband(bands[i].im, i) |
2059 |
770a9717f387
|
return bands[0]._new(im) |
2060 |
770a9717f387
|
|
2061 |
770a9717f387
|
# -------------------------------------------------------------------- |
2062 |
770a9717f387
|
# Plugin registry |
2063 |
770a9717f387
|
|
2064 |
770a9717f387
|
## |
2065 |
770a9717f387
|
# Register an image file plugin. This function should not be used |
2066 |
770a9717f387
|
# in application code. |
2067 |
770a9717f387
|
# |
2068 |
770a9717f387
|
# @param id An image format identifier. |
2069 |
770a9717f387
|
# @param factory An image file factory method. |
2070 |
770a9717f387
|
# @param accept An optional function that can be used to quickly |
2071 |
770a9717f387
|
# reject images having another format. |
2072 |
770a9717f387
|
|
2073 |
770a9717f387
|
def register_open(id, factory, accept=None): |
2074 |
770a9717f387
|
id = string.upper(id) |
2075 |
770a9717f387
|
ID.append(id) |
2076 |
770a9717f387
|
OPEN[id] = factory, accept |
2077 |
770a9717f387
|
|
2078 |
770a9717f387
|
## |
2079 |
770a9717f387
|
# Registers an image MIME type. This function should not be used |
2080 |
770a9717f387
|
# in application code. |
2081 |
770a9717f387
|
# |
2082 |
770a9717f387
|
# @param id An image format identifier. |
2083 |
770a9717f387
|
# @param mimetype The image MIME type for this format. |
2084 |
770a9717f387
|
|
2085 |
770a9717f387
|
def register_mime(id, mimetype): |
2086 |
770a9717f387
|
MIME[string.upper(id)] = mimetype |
2087 |
770a9717f387
|
|
2088 |
770a9717f387
|
## |
2089 |
770a9717f387
|
# Registers an image save function. This function should not be |
2090 |
770a9717f387
|
# used in application code. |
2091 |
770a9717f387
|
# |
2092 |
770a9717f387
|
# @param id An image format identifier. |
2093 |
770a9717f387
|
# @param driver A function to save images in this format. |
2094 |
770a9717f387
|
|
2095 |
770a9717f387
|
def register_save(id, driver): |
2096 |
770a9717f387
|
SAVE[string.upper(id)] = driver |
2097 |
770a9717f387
|
|
2098 |
770a9717f387
|
## |
2099 |
770a9717f387
|
# Registers an image extension. This function should not be |
2100 |
770a9717f387
|
# used in application code. |
2101 |
770a9717f387
|
# |
2102 |
770a9717f387
|
# @param id An image format identifier. |
2103 |
770a9717f387
|
# @param extension An extension used for this format. |
2104 |
770a9717f387
|
|
2105 |
770a9717f387
|
def register_extension(id, extension): |
2106 |
770a9717f387
|
EXTENSION[string.lower(extension)] = string.upper(id) |
2107 |
770a9717f387
|
|
2108 |
770a9717f387
|
|
2109 |
770a9717f387
|
# -------------------------------------------------------------------- |
2110 |
db1b40ca85c4
|
# Simple display support. User code may override this. |
2111 |
db1b40ca85c4
|
|
2112 |
db1b40ca85c4
|
def _show(image, **options): |
2113 |
db1b40ca85c4
|
# override me, as necessary |
2114 |
db1b40ca85c4
|
_showxv(image, **options) |
2115 |
770a9717f387
|
|
2116 |
5105a1ce6d11
|
def _showxv(image, title=None, **options): |
2117 |
5105a1ce6d11
|
import ImageShow |
2118 |
5105a1ce6d11
|
ImageShow.show(image, title, **options) |