mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-11-04 09:57:43 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			2176 lines
		
	
	
		
			67 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			2176 lines
		
	
	
		
			67 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
#
 | 
						|
# The Python Imaging Library.
 | 
						|
# $Id$
 | 
						|
#
 | 
						|
# the Image class wrapper
 | 
						|
#
 | 
						|
# partial release history:
 | 
						|
# 1995-09-09 fl   Created
 | 
						|
# 1996-03-11 fl   PIL release 0.0 (proof of concept)
 | 
						|
# 1996-04-30 fl   PIL release 0.1b1
 | 
						|
# 1999-07-28 fl   PIL release 1.0 final
 | 
						|
# 2000-06-07 fl   PIL release 1.1
 | 
						|
# 2000-10-20 fl   PIL release 1.1.1
 | 
						|
# 2001-05-07 fl   PIL release 1.1.2
 | 
						|
# 2002-03-15 fl   PIL release 1.1.3
 | 
						|
# 2003-05-10 fl   PIL release 1.1.4
 | 
						|
# 2005-03-28 fl   PIL release 1.1.5
 | 
						|
# 2006-12-02 fl   PIL release 1.1.6
 | 
						|
# 2009-11-15 fl   PIL release 1.1.7
 | 
						|
#
 | 
						|
# Copyright (c) 1997-2009 by Secret Labs AB.  All rights reserved.
 | 
						|
# Copyright (c) 1995-2009 by Fredrik Lundh.
 | 
						|
#
 | 
						|
# See the README file for information on usage and redistribution.
 | 
						|
#
 | 
						|
 | 
						|
from __future__ import print_function
 | 
						|
 | 
						|
VERSION = "1.1.7"
 | 
						|
 | 
						|
try:
 | 
						|
    import warnings
 | 
						|
except ImportError:
 | 
						|
    warnings = None
 | 
						|
 | 
						|
class _imaging_not_installed:
 | 
						|
    # module placeholder
 | 
						|
    def __getattr__(self, id):
 | 
						|
        raise ImportError("The _imaging C module is not installed")
 | 
						|
 | 
						|
try:
 | 
						|
    # give Tk a chance to set up the environment, in case we're
 | 
						|
    # using an _imaging module linked against libtcl/libtk (use
 | 
						|
    # __import__ to hide this from naive packagers; we don't really
 | 
						|
    # depend on Tk unless ImageTk is used, and that module already
 | 
						|
    # imports Tkinter)
 | 
						|
    __import__("FixTk")
 | 
						|
except ImportError:
 | 
						|
    pass
 | 
						|
 | 
						|
try:
 | 
						|
    # If the _imaging C module is not present, you can still use
 | 
						|
    # the "open" function to identify files, but you cannot load
 | 
						|
    # them.  Note that other modules should not refer to _imaging
 | 
						|
    # directly; import Image and use the Image.core variable instead.
 | 
						|
    import _imaging as core
 | 
						|
except ImportError as v:
 | 
						|
    core = _imaging_not_installed()
 | 
						|
    if str(v)[:20] == "Module use of python" and warnings:
 | 
						|
        # The _imaging C module is present, but not compiled for
 | 
						|
        # the right version (windows only).  Print a warning, if
 | 
						|
        # possible.
 | 
						|
        warnings.warn(
 | 
						|
            "The _imaging extension was built for another version "
 | 
						|
            "of Python; most PIL functions will be disabled",
 | 
						|
            RuntimeWarning
 | 
						|
            )
 | 
						|
 | 
						|
try:
 | 
						|
    import builtins
 | 
						|
except ImportError:
 | 
						|
    import __builtin__
 | 
						|
    builtins = __builtin__
 | 
						|
 | 
						|
from PIL import ImageMode
 | 
						|
from PIL._binary import i8, o8
 | 
						|
 | 
						|
import os, sys
 | 
						|
 | 
						|
# type stuff
 | 
						|
import collections
 | 
						|
import numbers
 | 
						|
 | 
						|
if bytes is str:
 | 
						|
    def isStringType(t):
 | 
						|
        return isinstance(t, basestring)
 | 
						|
else:
 | 
						|
    def isStringType(t):
 | 
						|
        return isinstance(t, str)
 | 
						|
 | 
						|
##
 | 
						|
# (Internal) Checks if an object is an image object.
 | 
						|
 | 
						|
def isImageType(t):
 | 
						|
    return hasattr(t, "im")
 | 
						|
 | 
						|
##
 | 
						|
# (Internal) Checks if an object is a string, and that it points to a
 | 
						|
# directory.
 | 
						|
 | 
						|
def isDirectory(f):
 | 
						|
    return isStringType(f) and os.path.isdir(f)
 | 
						|
 | 
						|
#
 | 
						|
# Debug level
 | 
						|
 | 
						|
DEBUG = 0
 | 
						|
 | 
						|
#
 | 
						|
# Constants (also defined in _imagingmodule.c!)
 | 
						|
 | 
						|
NONE = 0
 | 
						|
 | 
						|
# transpose
 | 
						|
FLIP_LEFT_RIGHT = 0
 | 
						|
FLIP_TOP_BOTTOM = 1
 | 
						|
ROTATE_90 = 2
 | 
						|
ROTATE_180 = 3
 | 
						|
ROTATE_270 = 4
 | 
						|
 | 
						|
# transforms
 | 
						|
AFFINE = 0
 | 
						|
EXTENT = 1
 | 
						|
PERSPECTIVE = 2
 | 
						|
QUAD = 3
 | 
						|
MESH = 4
 | 
						|
 | 
						|
# resampling filters
 | 
						|
NONE = 0
 | 
						|
NEAREST = 0
 | 
						|
ANTIALIAS = 1 # 3-lobed lanczos
 | 
						|
LINEAR = BILINEAR = 2
 | 
						|
CUBIC = BICUBIC = 3
 | 
						|
 | 
						|
# dithers
 | 
						|
NONE = 0
 | 
						|
NEAREST = 0
 | 
						|
ORDERED = 1 # Not yet implemented
 | 
						|
RASTERIZE = 2 # Not yet implemented
 | 
						|
FLOYDSTEINBERG = 3 # default
 | 
						|
 | 
						|
# palettes/quantizers
 | 
						|
WEB = 0
 | 
						|
ADAPTIVE = 1
 | 
						|
 | 
						|
# categories
 | 
						|
NORMAL = 0
 | 
						|
SEQUENCE = 1
 | 
						|
CONTAINER = 2
 | 
						|
 | 
						|
# --------------------------------------------------------------------
 | 
						|
# Registries
 | 
						|
 | 
						|
ID = []
 | 
						|
OPEN = {}
 | 
						|
MIME = {}
 | 
						|
SAVE = {}
 | 
						|
EXTENSION = {}
 | 
						|
 | 
						|
# --------------------------------------------------------------------
 | 
						|
# Modes supported by this version
 | 
						|
 | 
						|
_MODEINFO = {
 | 
						|
    # NOTE: this table will be removed in future versions.  use
 | 
						|
    # getmode* functions or ImageMode descriptors instead.
 | 
						|
 | 
						|
    # official modes
 | 
						|
    "1": ("L", "L", ("1",)),
 | 
						|
    "L": ("L", "L", ("L",)),
 | 
						|
    "I": ("L", "I", ("I",)),
 | 
						|
    "F": ("L", "F", ("F",)),
 | 
						|
    "P": ("RGB", "L", ("P",)),
 | 
						|
    "RGB": ("RGB", "L", ("R", "G", "B")),
 | 
						|
    "RGBX": ("RGB", "L", ("R", "G", "B", "X")),
 | 
						|
    "RGBA": ("RGB", "L", ("R", "G", "B", "A")),
 | 
						|
    "CMYK": ("RGB", "L", ("C", "M", "Y", "K")),
 | 
						|
    "YCbCr": ("RGB", "L", ("Y", "Cb", "Cr")),
 | 
						|
 | 
						|
    # Experimental modes include I;16, I;16L, I;16B, RGBa, BGR;15, and
 | 
						|
    # BGR;24.  Use these modes only if you know exactly what you're
 | 
						|
    # doing...
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
if sys.byteorder == 'little':
 | 
						|
    _ENDIAN = '<'
 | 
						|
else:
 | 
						|
    _ENDIAN = '>'
 | 
						|
 | 
						|
_MODE_CONV = {
 | 
						|
    # official modes
 | 
						|
    "1": ('|b1', None), # broken
 | 
						|
    "L": ('|u1', None),
 | 
						|
    "I": (_ENDIAN + 'i4', None),
 | 
						|
    "F": (_ENDIAN + 'f4', None),
 | 
						|
    "P": ('|u1', None),
 | 
						|
    "RGB": ('|u1', 3),
 | 
						|
    "RGBX": ('|u1', 4),
 | 
						|
    "RGBA": ('|u1', 4),
 | 
						|
    "CMYK": ('|u1', 4),
 | 
						|
    "YCbCr": ('|u1', 3),
 | 
						|
}
 | 
						|
 | 
						|
def _conv_type_shape(im):
 | 
						|
    shape = im.size[1], im.size[0]
 | 
						|
    typ, extra = _MODE_CONV[im.mode]
 | 
						|
    if extra is None:
 | 
						|
        return shape, typ
 | 
						|
    else:
 | 
						|
        return shape+(extra,), typ
 | 
						|
 | 
						|
 | 
						|
MODES = sorted(_MODEINFO.keys())
 | 
						|
 | 
						|
# raw modes that may be memory mapped.  NOTE: if you change this, you
 | 
						|
# may have to modify the stride calculation in map.c too!
 | 
						|
_MAPMODES = ("L", "P", "RGBX", "RGBA", "CMYK", "I;16", "I;16L", "I;16B")
 | 
						|
 | 
						|
##
 | 
						|
# Gets the "base" mode for given mode.  This function returns "L" for
 | 
						|
# images that contain grayscale data, and "RGB" for images that
 | 
						|
# contain color data.
 | 
						|
#
 | 
						|
# @param mode Input mode.
 | 
						|
# @return "L" or "RGB".
 | 
						|
# @exception KeyError If the input mode was not a standard mode.
 | 
						|
 | 
						|
def getmodebase(mode):
 | 
						|
    return ImageMode.getmode(mode).basemode
 | 
						|
 | 
						|
##
 | 
						|
# Gets the storage type mode.  Given a mode, this function returns a
 | 
						|
# single-layer mode suitable for storing individual bands.
 | 
						|
#
 | 
						|
# @param mode Input mode.
 | 
						|
# @return "L", "I", or "F".
 | 
						|
# @exception KeyError If the input mode was not a standard mode.
 | 
						|
 | 
						|
def getmodetype(mode):
 | 
						|
    return ImageMode.getmode(mode).basetype
 | 
						|
 | 
						|
##
 | 
						|
# Gets a list of individual band names.  Given a mode, this function
 | 
						|
# returns a tuple containing the names of individual bands (use
 | 
						|
# {@link #getmodetype} to get the mode used to store each individual
 | 
						|
# band.
 | 
						|
#
 | 
						|
# @param mode Input mode.
 | 
						|
# @return A tuple containing band names.  The length of the tuple
 | 
						|
#     gives the number of bands in an image of the given mode.
 | 
						|
# @exception KeyError If the input mode was not a standard mode.
 | 
						|
 | 
						|
def getmodebandnames(mode):
 | 
						|
    return ImageMode.getmode(mode).bands
 | 
						|
 | 
						|
##
 | 
						|
# Gets the number of individual bands for this mode.
 | 
						|
#
 | 
						|
# @param mode Input mode.
 | 
						|
# @return The number of bands in this mode.
 | 
						|
# @exception KeyError If the input mode was not a standard mode.
 | 
						|
 | 
						|
def getmodebands(mode):
 | 
						|
    return len(ImageMode.getmode(mode).bands)
 | 
						|
 | 
						|
# --------------------------------------------------------------------
 | 
						|
# Helpers
 | 
						|
 | 
						|
_initialized = 0
 | 
						|
 | 
						|
##
 | 
						|
# Explicitly loads standard file format drivers.
 | 
						|
 | 
						|
def preinit():
 | 
						|
    "Load standard file format drivers."
 | 
						|
 | 
						|
    global _initialized
 | 
						|
    if _initialized >= 1:
 | 
						|
        return
 | 
						|
 | 
						|
    try:
 | 
						|
        from PIL import BmpImagePlugin
 | 
						|
    except ImportError:
 | 
						|
        pass
 | 
						|
    try:
 | 
						|
        from PIL import GifImagePlugin
 | 
						|
    except ImportError:
 | 
						|
        pass
 | 
						|
    try:
 | 
						|
        from PIL import JpegImagePlugin
 | 
						|
    except ImportError:
 | 
						|
        pass
 | 
						|
    try:
 | 
						|
        from PIL import PpmImagePlugin
 | 
						|
    except ImportError:
 | 
						|
        pass
 | 
						|
    try:
 | 
						|
        from PIL import PngImagePlugin
 | 
						|
    except ImportError:
 | 
						|
        pass
 | 
						|
#   try:
 | 
						|
#       import TiffImagePlugin
 | 
						|
#   except ImportError:
 | 
						|
#       pass
 | 
						|
 | 
						|
    _initialized = 1
 | 
						|
 | 
						|
##
 | 
						|
# Explicitly initializes the Python Imaging Library.  This function
 | 
						|
# loads all available file format drivers.
 | 
						|
 | 
						|
def init():
 | 
						|
    "Load all file format drivers."
 | 
						|
 | 
						|
    global _initialized
 | 
						|
    if _initialized >= 2:
 | 
						|
        return 0
 | 
						|
 | 
						|
    visited = {}
 | 
						|
 | 
						|
    directories = sys.path
 | 
						|
 | 
						|
    try:
 | 
						|
        directories = directories + [os.path.dirname(__file__)]
 | 
						|
    except NameError:
 | 
						|
        pass
 | 
						|
 | 
						|
    # only check directories (including current, if present in the path)
 | 
						|
    for directory in filter(isDirectory, directories):
 | 
						|
        fullpath = os.path.abspath(directory)
 | 
						|
        if fullpath in visited:
 | 
						|
            continue
 | 
						|
        for file in os.listdir(directory):
 | 
						|
            if file[-14:] == "ImagePlugin.py":
 | 
						|
                f, e = os.path.splitext(file)
 | 
						|
                try:
 | 
						|
                    sys.path.insert(0, directory)
 | 
						|
                    try:
 | 
						|
                        __import__(f, globals(), locals(), [])
 | 
						|
                    finally:
 | 
						|
                        del sys.path[0]
 | 
						|
                except ImportError:
 | 
						|
                    if DEBUG:
 | 
						|
                        print("Image: failed to import", end=' ')
 | 
						|
                        print(f, ":", sys.exc_info()[1])
 | 
						|
        visited[fullpath] = None
 | 
						|
 | 
						|
    if OPEN or SAVE:
 | 
						|
        _initialized = 2
 | 
						|
        return 1
 | 
						|
 | 
						|
# --------------------------------------------------------------------
 | 
						|
# Codec factories (used by tobytes/frombytes and ImageFile.load)
 | 
						|
 | 
						|
def _getdecoder(mode, decoder_name, args, extra=()):
 | 
						|
 | 
						|
    # tweak arguments
 | 
						|
    if args is None:
 | 
						|
        args = ()
 | 
						|
    elif not isinstance(args, tuple):
 | 
						|
        args = (args,)
 | 
						|
 | 
						|
    try:
 | 
						|
        # get decoder
 | 
						|
        decoder = getattr(core, decoder_name + "_decoder")
 | 
						|
        # print(decoder, mode, args + extra)
 | 
						|
        return decoder(mode, *args + extra)
 | 
						|
    except AttributeError:
 | 
						|
        raise IOError("decoder %s not available" % decoder_name)
 | 
						|
 | 
						|
def _getencoder(mode, encoder_name, args, extra=()):
 | 
						|
 | 
						|
    # tweak arguments
 | 
						|
    if args is None:
 | 
						|
        args = ()
 | 
						|
    elif not isinstance(args, tuple):
 | 
						|
        args = (args,)
 | 
						|
 | 
						|
    try:
 | 
						|
        # get encoder
 | 
						|
        encoder = getattr(core, encoder_name + "_encoder")
 | 
						|
        # print(encoder, mode, args + extra)
 | 
						|
        return encoder(mode, *args + extra)
 | 
						|
    except AttributeError:
 | 
						|
        raise IOError("encoder %s not available" % encoder_name)
 | 
						|
 | 
						|
 | 
						|
# --------------------------------------------------------------------
 | 
						|
# Simple expression analyzer
 | 
						|
 | 
						|
def coerce_e(value):
 | 
						|
    return value if isinstance(value, _E) else _E(value)
 | 
						|
 | 
						|
class _E:
 | 
						|
    def __init__(self, data):
 | 
						|
        self.data = data
 | 
						|
    def __add__(self, other):
 | 
						|
        return _E((self.data, "__add__", coerce_e(other).data))
 | 
						|
    def __mul__(self, other):
 | 
						|
        return _E((self.data, "__mul__", coerce_e(other).data))
 | 
						|
 | 
						|
def _getscaleoffset(expr):
 | 
						|
    stub = ["stub"]
 | 
						|
    data = expr(_E(stub)).data
 | 
						|
    try:
 | 
						|
        (a, b, c) = data # simplified syntax
 | 
						|
        if (a is stub and b == "__mul__" and isinstance(c, numbers.Number)):
 | 
						|
            return c, 0.0
 | 
						|
        if (a is stub and b == "__add__" and isinstance(c, numbers.Number)):
 | 
						|
            return 1.0, c
 | 
						|
    except TypeError: pass
 | 
						|
    try:
 | 
						|
        ((a, b, c), d, e) = data # full syntax
 | 
						|
        if (a is stub and b == "__mul__" and isinstance(c, numbers.Number) and
 | 
						|
            d == "__add__" and isinstance(e, numbers.Number)):
 | 
						|
            return c, e
 | 
						|
    except TypeError: pass
 | 
						|
    raise ValueError("illegal expression")
 | 
						|
 | 
						|
 | 
						|
# --------------------------------------------------------------------
 | 
						|
# Implementation wrapper
 | 
						|
 | 
						|
##
 | 
						|
# This class represents an image object.  To create Image objects, use
 | 
						|
# the appropriate factory functions.  There's hardly ever any reason
 | 
						|
# to call the Image constructor directly.
 | 
						|
#
 | 
						|
# @see #open
 | 
						|
# @see #new
 | 
						|
# @see #frombytes
 | 
						|
 | 
						|
class Image:
 | 
						|
 | 
						|
    format = None
 | 
						|
    format_description = None
 | 
						|
 | 
						|
    def __init__(self):
 | 
						|
        # FIXME: take "new" parameters / other image?
 | 
						|
        # FIXME: turn mode and size into delegating properties?
 | 
						|
        self.im = None
 | 
						|
        self.mode = ""
 | 
						|
        self.size = (0, 0)
 | 
						|
        self.palette = None
 | 
						|
        self.info = {}
 | 
						|
        self.category = NORMAL
 | 
						|
        self.readonly = 0
 | 
						|
 | 
						|
    def _new(self, im):
 | 
						|
        new = Image()
 | 
						|
        new.im = im
 | 
						|
        new.mode = im.mode
 | 
						|
        new.size = im.size
 | 
						|
        new.palette = self.palette
 | 
						|
        if im.mode == "P":
 | 
						|
            from PIL import ImagePalette
 | 
						|
            new.palette = ImagePalette.ImagePalette()
 | 
						|
        try:
 | 
						|
            new.info = self.info.copy()
 | 
						|
        except AttributeError:
 | 
						|
            # fallback (pre-1.5.2)
 | 
						|
            new.info = {}
 | 
						|
            for k, v in self.info:
 | 
						|
                new.info[k] = v
 | 
						|
        return new
 | 
						|
 | 
						|
    _makeself = _new # compatibility
 | 
						|
 | 
						|
    def _copy(self):
 | 
						|
        self.load()
 | 
						|
        self.im = self.im.copy()
 | 
						|
        self.readonly = 0
 | 
						|
 | 
						|
    def _dump(self, file=None, format=None):
 | 
						|
        import tempfile
 | 
						|
        if not file:
 | 
						|
            file = tempfile.mktemp()
 | 
						|
        self.load()
 | 
						|
        if not format or format == "PPM":
 | 
						|
            self.im.save_ppm(file)
 | 
						|
        else:
 | 
						|
            file = file + "." + format
 | 
						|
            self.save(file, format)
 | 
						|
        return file
 | 
						|
 | 
						|
    def __repr__(self):
 | 
						|
        return "<%s.%s image mode=%s size=%dx%d at 0x%X>" % (
 | 
						|
            self.__class__.__module__, self.__class__.__name__,
 | 
						|
            self.mode, self.size[0], self.size[1],
 | 
						|
            id(self)
 | 
						|
            )
 | 
						|
 | 
						|
    def __getattr__(self, name):
 | 
						|
        if name == "__array_interface__":
 | 
						|
            # numpy array interface support
 | 
						|
            new = {}
 | 
						|
            shape, typestr = _conv_type_shape(self)
 | 
						|
            new['shape'] = shape
 | 
						|
            new['typestr'] = typestr
 | 
						|
            new['data'] = self.tobytes()
 | 
						|
            return new
 | 
						|
        raise AttributeError(name)
 | 
						|
 | 
						|
    ##
 | 
						|
    # Returns a string containing pixel data.
 | 
						|
    #
 | 
						|
    # @param encoder_name What encoder to use.  The default is to
 | 
						|
    #    use the standard "raw" encoder.
 | 
						|
    # @param *args Extra arguments to the encoder.
 | 
						|
    # @return A bytes object.
 | 
						|
 | 
						|
    def tobytes(self, encoder_name="raw", *args):
 | 
						|
        "Return image as a bytes object"
 | 
						|
 | 
						|
        # may pass tuple instead of argument list
 | 
						|
        if len(args) == 1 and isinstance(args[0], tuple):
 | 
						|
            args = args[0]
 | 
						|
 | 
						|
        if encoder_name == "raw" and args == ():
 | 
						|
            args = self.mode
 | 
						|
 | 
						|
        self.load()
 | 
						|
 | 
						|
        # unpack data
 | 
						|
        e = _getencoder(self.mode, encoder_name, args)
 | 
						|
        e.setimage(self.im)
 | 
						|
 | 
						|
        bufsize = max(65536, self.size[0] * 4) # see RawEncode.c
 | 
						|
 | 
						|
        data = []
 | 
						|
        while True:
 | 
						|
            l, s, d = e.encode(bufsize)
 | 
						|
            data.append(d)
 | 
						|
            if s:
 | 
						|
                break
 | 
						|
        if s < 0:
 | 
						|
            raise RuntimeError("encoder error %d in tobytes" % s)
 | 
						|
 | 
						|
        return b"".join(data)
 | 
						|
 | 
						|
    # Declare tostring as alias to tobytes
 | 
						|
    def tostring(self, *args, **kw):
 | 
						|
        warnings.warn(
 | 
						|
            'tostring() is deprecated. Please call tobytes() instead.',
 | 
						|
            DeprecationWarning,
 | 
						|
            stacklevel=2,
 | 
						|
        )
 | 
						|
        return self.tobytes(*args, **kw)
 | 
						|
 | 
						|
    ##
 | 
						|
    # Returns the image converted to an X11 bitmap.  This method
 | 
						|
    # only works for mode "1" images.
 | 
						|
    #
 | 
						|
    # @param name The name prefix to use for the bitmap variables.
 | 
						|
    # @return A string containing an X11 bitmap.
 | 
						|
    # @exception ValueError If the mode is not "1"
 | 
						|
 | 
						|
    def tobitmap(self, name="image"):
 | 
						|
        "Return image as an XBM bitmap"
 | 
						|
 | 
						|
        self.load()
 | 
						|
        if self.mode != "1":
 | 
						|
            raise ValueError("not a bitmap")
 | 
						|
        data = self.tobytes("xbm")
 | 
						|
        return b"".join([("#define %s_width %d\n" % (name, self.size[0])).encode('ascii'),
 | 
						|
                ("#define %s_height %d\n"% (name, self.size[1])).encode('ascii'),
 | 
						|
                ("static char %s_bits[] = {\n" % name).encode('ascii'), data, b"};"])
 | 
						|
 | 
						|
    ##
 | 
						|
    # Loads this image with pixel data from a bytes object.
 | 
						|
    # <p>
 | 
						|
    # This method is similar to the {@link #frombytes} function, but
 | 
						|
    # loads data into this image instead of creating a new image
 | 
						|
    # object.
 | 
						|
 | 
						|
    def frombytes(self, data, decoder_name="raw", *args):
 | 
						|
        "Load data to image from a bytes object"
 | 
						|
 | 
						|
        # may pass tuple instead of argument list
 | 
						|
        if len(args) == 1 and isinstance(args[0], tuple):
 | 
						|
            args = args[0]
 | 
						|
 | 
						|
        # default format
 | 
						|
        if decoder_name == "raw" and args == ():
 | 
						|
            args = self.mode
 | 
						|
 | 
						|
        # unpack data
 | 
						|
        d = _getdecoder(self.mode, decoder_name, args)
 | 
						|
        d.setimage(self.im)
 | 
						|
        s = d.decode(data)
 | 
						|
 | 
						|
        if s[0] >= 0:
 | 
						|
            raise ValueError("not enough image data")
 | 
						|
        if s[1] != 0:
 | 
						|
            raise ValueError("cannot decode image data")
 | 
						|
 | 
						|
    def fromstring(self, *args, **kw):
 | 
						|
        """ Deprecated alias to frombytes """
 | 
						|
        warnings.warn('fromstring() is deprecated. Please call frombytes() instead.', DeprecationWarning)
 | 
						|
        return self.frombytes(*args, **kw)
 | 
						|
 | 
						|
    ##
 | 
						|
    # Allocates storage for the image and loads the pixel data.  In
 | 
						|
    # normal cases, you don't need to call this method, since the
 | 
						|
    # Image class automatically loads an opened image when it is
 | 
						|
    # accessed for the first time.
 | 
						|
    #
 | 
						|
    # @return An image access object.
 | 
						|
 | 
						|
    def load(self):
 | 
						|
        "Explicitly load pixel data."
 | 
						|
        if self.im and self.palette and self.palette.dirty:
 | 
						|
            # realize palette
 | 
						|
            self.im.putpalette(*self.palette.getdata())
 | 
						|
            self.palette.dirty = 0
 | 
						|
            self.palette.mode = "RGB"
 | 
						|
            self.palette.rawmode = None
 | 
						|
            if "transparency" in self.info:
 | 
						|
 | 
						|
# XXX Not sure how this ever worked:
 | 
						|
#                if self.info["transparency_palette"]:
 | 
						|
# Should probably be:
 | 
						|
                if "transparency_palette" in self.info:
 | 
						|
# amirite?
 | 
						|
 | 
						|
                    self.im.putpalettealpha(0, 0, self.info["transparency_palette"])
 | 
						|
                else:
 | 
						|
                    self.im.putpalettealpha(self.info["transparency"], 0)
 | 
						|
 | 
						|
                self.palette.mode = "RGBA"
 | 
						|
        if self.im:
 | 
						|
            return self.im.pixel_access(self.readonly)
 | 
						|
 | 
						|
    ##
 | 
						|
    # Verifies the contents of a file. For data read from a file, this
 | 
						|
    # method attempts to determine if the file is broken, without
 | 
						|
    # actually decoding the image data.  If this method finds any
 | 
						|
    # problems, it raises suitable exceptions.  If you need to load
 | 
						|
    # the image after using this method, you must reopen the image
 | 
						|
    # file.
 | 
						|
 | 
						|
    def verify(self):
 | 
						|
        "Verify file contents."
 | 
						|
        pass
 | 
						|
 | 
						|
    ##
 | 
						|
    # Returns a converted copy of this image. For the "P" mode, this
 | 
						|
    # method translates pixels through the palette.  If mode is
 | 
						|
    # omitted, a mode is chosen so that all information in the image
 | 
						|
    # and the palette can be represented without a palette.
 | 
						|
    # <p>
 | 
						|
    # The current version supports all possible conversions between
 | 
						|
    # "L", "RGB" and "CMYK."
 | 
						|
    # <p>
 | 
						|
    # When translating a colour image to black and white (mode "L"),
 | 
						|
    # the library uses the ITU-R 601-2 luma transform:
 | 
						|
    # <p>
 | 
						|
    # <b>L = R * 299/1000 + G * 587/1000 + B * 114/1000</b>
 | 
						|
    # <p>
 | 
						|
    # When translating a greyscale image into a bilevel image (mode
 | 
						|
    # "1"), all non-zero values are set to 255 (white). To use other
 | 
						|
    # thresholds, use the {@link #Image.point} method.
 | 
						|
    #
 | 
						|
    # @def convert(mode, matrix=None, **options)
 | 
						|
    # @param mode The requested mode.
 | 
						|
    # @param matrix An optional conversion matrix.  If given, this
 | 
						|
    #    should be 4- or 16-tuple containing floating point values.
 | 
						|
    # @param options Additional options, given as keyword arguments.
 | 
						|
    # @keyparam dither Dithering method, used when converting from
 | 
						|
    #    mode "RGB" to "P".
 | 
						|
    #    Available methods are NONE or FLOYDSTEINBERG (default).
 | 
						|
    # @keyparam palette Palette to use when converting from mode "RGB"
 | 
						|
    #    to "P".  Available palettes are WEB or ADAPTIVE.
 | 
						|
    # @keyparam colors Number of colors to use for the ADAPTIVE palette.
 | 
						|
    #    Defaults to 256.
 | 
						|
    # @return An Image object.
 | 
						|
 | 
						|
    def convert(self, mode=None, data=None, dither=None,
 | 
						|
                palette=WEB, colors=256):
 | 
						|
        "Convert to other pixel format"
 | 
						|
 | 
						|
        if not mode:
 | 
						|
            # determine default mode
 | 
						|
            if self.mode == "P":
 | 
						|
                self.load()
 | 
						|
                if self.palette:
 | 
						|
                    mode = self.palette.mode
 | 
						|
                else:
 | 
						|
                    mode = "RGB"
 | 
						|
            else:
 | 
						|
                return self.copy()
 | 
						|
 | 
						|
        self.load()
 | 
						|
 | 
						|
        if data:
 | 
						|
            # matrix conversion
 | 
						|
            if mode not in ("L", "RGB"):
 | 
						|
                raise ValueError("illegal conversion")
 | 
						|
            im = self.im.convert_matrix(mode, data)
 | 
						|
            return self._new(im)
 | 
						|
 | 
						|
        if mode == "P" and palette == ADAPTIVE:
 | 
						|
            im = self.im.quantize(colors)
 | 
						|
            return self._new(im)
 | 
						|
 | 
						|
        # colourspace conversion
 | 
						|
        if dither is None:
 | 
						|
            dither = FLOYDSTEINBERG
 | 
						|
 | 
						|
        try:
 | 
						|
            im = self.im.convert(mode, dither)
 | 
						|
        except ValueError:
 | 
						|
            try:
 | 
						|
                # normalize source image and try again
 | 
						|
                im = self.im.convert(getmodebase(self.mode))
 | 
						|
                im = im.convert(mode, dither)
 | 
						|
            except KeyError:
 | 
						|
                raise ValueError("illegal conversion")
 | 
						|
 | 
						|
        return self._new(im)
 | 
						|
 | 
						|
    def quantize(self, colors=256, method=0, kmeans=0, palette=None):
 | 
						|
 | 
						|
        # methods:
 | 
						|
        #    0 = median cut
 | 
						|
        #    1 = maximum coverage
 | 
						|
 | 
						|
        # NOTE: this functionality will be moved to the extended
 | 
						|
        # quantizer interface in a later version of PIL.
 | 
						|
 | 
						|
        self.load()
 | 
						|
 | 
						|
        if palette:
 | 
						|
            # use palette from reference image
 | 
						|
            palette.load()
 | 
						|
            if palette.mode != "P":
 | 
						|
                raise ValueError("bad mode for palette image")
 | 
						|
            if self.mode != "RGB" and self.mode != "L":
 | 
						|
                raise ValueError(
 | 
						|
                    "only RGB or L mode images can be quantized to a palette"
 | 
						|
                    )
 | 
						|
            im = self.im.convert("P", 1, palette.im)
 | 
						|
            return self._makeself(im)
 | 
						|
 | 
						|
        im = self.im.quantize(colors, method, kmeans)
 | 
						|
        return self._new(im)
 | 
						|
 | 
						|
    ##
 | 
						|
    # Copies this image. Use this method if you wish to paste things
 | 
						|
    # into an image, but still retain the original.
 | 
						|
    #
 | 
						|
    # @return An Image object.
 | 
						|
 | 
						|
    def copy(self):
 | 
						|
        "Copy raster data"
 | 
						|
 | 
						|
        self.load()
 | 
						|
        im = self.im.copy()
 | 
						|
        return self._new(im)
 | 
						|
 | 
						|
    ##
 | 
						|
    # Returns a rectangular region from this image. The box is a
 | 
						|
    # 4-tuple defining the left, upper, right, and lower pixel
 | 
						|
    # coordinate.
 | 
						|
    # <p>
 | 
						|
    # This is a lazy operation.  Changes to the source image may or
 | 
						|
    # may not be reflected in the cropped image.  To break the
 | 
						|
    # connection, call the {@link #Image.load} method on the cropped
 | 
						|
    # copy.
 | 
						|
    #
 | 
						|
    # @param The crop rectangle, as a (left, upper, right, lower)-tuple.
 | 
						|
    # @return An Image object.
 | 
						|
 | 
						|
    def crop(self, box=None):
 | 
						|
        "Crop region from image"
 | 
						|
 | 
						|
        self.load()
 | 
						|
        if box is None:
 | 
						|
            return self.copy()
 | 
						|
 | 
						|
        # lazy operation
 | 
						|
        return _ImageCrop(self, box)
 | 
						|
 | 
						|
    ##
 | 
						|
    # Configures the image file loader so it returns a version of the
 | 
						|
    # image that as closely as possible matches the given mode and
 | 
						|
    # size.  For example, you can use this method to convert a colour
 | 
						|
    # JPEG to greyscale while loading it, or to extract a 128x192
 | 
						|
    # version from a PCD file.
 | 
						|
    # <p>
 | 
						|
    # Note that this method modifies the Image object in place.  If
 | 
						|
    # the image has already been loaded, this method has no effect.
 | 
						|
    #
 | 
						|
    # @param mode The requested mode.
 | 
						|
    # @param size The requested size.
 | 
						|
 | 
						|
    def draft(self, mode, size):
 | 
						|
        "Configure image decoder"
 | 
						|
 | 
						|
        pass
 | 
						|
 | 
						|
    def _expand(self, xmargin, ymargin=None):
 | 
						|
        if ymargin is None:
 | 
						|
            ymargin = xmargin
 | 
						|
        self.load()
 | 
						|
        return self._new(self.im.expand(xmargin, ymargin, 0))
 | 
						|
 | 
						|
    ##
 | 
						|
    # Filters this image using the given filter.  For a list of
 | 
						|
    # available filters, see the <b>ImageFilter</b> module.
 | 
						|
    #
 | 
						|
    # @param filter Filter kernel.
 | 
						|
    # @return An Image object.
 | 
						|
    # @see ImageFilter
 | 
						|
 | 
						|
    def filter(self, filter):
 | 
						|
        "Apply environment filter to image"
 | 
						|
 | 
						|
        self.load()
 | 
						|
 | 
						|
        if isinstance(filter, collections.Callable):
 | 
						|
            filter = filter()
 | 
						|
        if not hasattr(filter, "filter"):
 | 
						|
            raise TypeError("filter argument should be ImageFilter.Filter instance or class")
 | 
						|
 | 
						|
        if self.im.bands == 1:
 | 
						|
            return self._new(filter.filter(self.im))
 | 
						|
        # fix to handle multiband images since _imaging doesn't
 | 
						|
        ims = []
 | 
						|
        for c in range(self.im.bands):
 | 
						|
            ims.append(self._new(filter.filter(self.im.getband(c))))
 | 
						|
        return merge(self.mode, ims)
 | 
						|
 | 
						|
    ##
 | 
						|
    # Returns a tuple containing the name of each band in this image.
 | 
						|
    # For example, <b>getbands</b> on an RGB image returns ("R", "G", "B").
 | 
						|
    #
 | 
						|
    # @return A tuple containing band names.
 | 
						|
 | 
						|
    def getbands(self):
 | 
						|
        "Get band names"
 | 
						|
 | 
						|
        return ImageMode.getmode(self.mode).bands
 | 
						|
 | 
						|
    ##
 | 
						|
    # Calculates the bounding box of the non-zero regions in the
 | 
						|
    # image.
 | 
						|
    #
 | 
						|
    # @return The bounding box is returned as a 4-tuple defining the
 | 
						|
    #    left, upper, right, and lower pixel coordinate. If the image
 | 
						|
    #    is completely empty, this method returns None.
 | 
						|
 | 
						|
    def getbbox(self):
 | 
						|
        "Get bounding box of actual data (non-zero pixels) in image"
 | 
						|
 | 
						|
        self.load()
 | 
						|
        return self.im.getbbox()
 | 
						|
 | 
						|
    ##
 | 
						|
    # Returns a list of colors used in this image.
 | 
						|
    #
 | 
						|
    # @param maxcolors Maximum number of colors.  If this number is
 | 
						|
    #    exceeded, this method returns None.  The default limit is
 | 
						|
    #    256 colors.
 | 
						|
    # @return An unsorted list of (count, pixel) values.
 | 
						|
 | 
						|
    def getcolors(self, maxcolors=256):
 | 
						|
        "Get colors from image, up to given limit"
 | 
						|
 | 
						|
        self.load()
 | 
						|
        if self.mode in ("1", "L", "P"):
 | 
						|
            h = self.im.histogram()
 | 
						|
            out = []
 | 
						|
            for i in range(256):
 | 
						|
                if h[i]:
 | 
						|
                    out.append((h[i], i))
 | 
						|
            if len(out) > maxcolors:
 | 
						|
                return None
 | 
						|
            return out
 | 
						|
        return self.im.getcolors(maxcolors)
 | 
						|
 | 
						|
    ##
 | 
						|
    # Returns the contents of this image as a sequence object
 | 
						|
    # containing pixel values.  The sequence object is flattened, so
 | 
						|
    # that values for line one follow directly after the values of
 | 
						|
    # line zero, and so on.
 | 
						|
    # <p>
 | 
						|
    # Note that the sequence object returned by this method is an
 | 
						|
    # internal PIL data type, which only supports certain sequence
 | 
						|
    # operations.  To convert it to an ordinary sequence (e.g. for
 | 
						|
    # printing), use <b>list(im.getdata())</b>.
 | 
						|
    #
 | 
						|
    # @param band What band to return.  The default is to return
 | 
						|
    #    all bands.  To return a single band, pass in the index
 | 
						|
    #    value (e.g. 0 to get the "R" band from an "RGB" image).
 | 
						|
    # @return A sequence-like object.
 | 
						|
 | 
						|
    def getdata(self, band = None):
 | 
						|
        "Get image data as sequence object."
 | 
						|
 | 
						|
        self.load()
 | 
						|
        if band is not None:
 | 
						|
            return self.im.getband(band)
 | 
						|
        return self.im # could be abused
 | 
						|
 | 
						|
    ##
 | 
						|
    # Gets the the minimum and maximum pixel values for each band in
 | 
						|
    # the image.
 | 
						|
    #
 | 
						|
    # @return For a single-band image, a 2-tuple containing the
 | 
						|
    #    minimum and maximum pixel value.  For a multi-band image,
 | 
						|
    #    a tuple containing one 2-tuple for each band.
 | 
						|
 | 
						|
    def getextrema(self):
 | 
						|
        "Get min/max value"
 | 
						|
 | 
						|
        self.load()
 | 
						|
        if self.im.bands > 1:
 | 
						|
            extrema = []
 | 
						|
            for i in range(self.im.bands):
 | 
						|
                extrema.append(self.im.getband(i).getextrema())
 | 
						|
            return tuple(extrema)
 | 
						|
        return self.im.getextrema()
 | 
						|
 | 
						|
    ##
 | 
						|
    # Returns a capsule that points to the internal image memory.
 | 
						|
    #
 | 
						|
    # @return A capsule object.
 | 
						|
 | 
						|
    def getim(self):
 | 
						|
        "Get capsule pointer to internal image memory"
 | 
						|
 | 
						|
        self.load()
 | 
						|
        return self.im.ptr
 | 
						|
 | 
						|
 | 
						|
    ##
 | 
						|
    # Returns the image palette as a list.
 | 
						|
    #
 | 
						|
    # @return A list of color values [r, g, b, ...], or None if the
 | 
						|
    #    image has no palette.
 | 
						|
 | 
						|
    def getpalette(self):
 | 
						|
        "Get palette contents."
 | 
						|
 | 
						|
        self.load()
 | 
						|
        try:
 | 
						|
            if bytes is str:
 | 
						|
                return [i8(c) for c in self.im.getpalette()]
 | 
						|
            else:
 | 
						|
                return list(self.im.getpalette())
 | 
						|
        except ValueError:
 | 
						|
            return None # no palette
 | 
						|
 | 
						|
 | 
						|
    ##
 | 
						|
    # Returns the pixel value at a given position.
 | 
						|
    #
 | 
						|
    # @param xy The coordinate, given as (x, y).
 | 
						|
    # @return The pixel value.  If the image is a multi-layer image,
 | 
						|
    #    this method returns a tuple.
 | 
						|
 | 
						|
    def getpixel(self, xy):
 | 
						|
        "Get pixel value"
 | 
						|
 | 
						|
        self.load()
 | 
						|
        return self.im.getpixel(xy)
 | 
						|
 | 
						|
    ##
 | 
						|
    # Returns the horizontal and vertical projection.
 | 
						|
    #
 | 
						|
    # @return Two sequences, indicating where there are non-zero
 | 
						|
    #     pixels along the X-axis and the Y-axis, respectively.
 | 
						|
 | 
						|
    def getprojection(self):
 | 
						|
        "Get projection to x and y axes"
 | 
						|
 | 
						|
        self.load()
 | 
						|
        x, y = self.im.getprojection()
 | 
						|
        return [i8(c) for c in x], [i8(c) for c in y]
 | 
						|
 | 
						|
    ##
 | 
						|
    # Returns a histogram for the image. The histogram is returned as
 | 
						|
    # a list of pixel counts, one for each pixel value in the source
 | 
						|
    # image. If the image has more than one band, the histograms for
 | 
						|
    # all bands are concatenated (for example, the histogram for an
 | 
						|
    # "RGB" image contains 768 values).
 | 
						|
    # <p>
 | 
						|
    # A bilevel image (mode "1") is treated as a greyscale ("L") image
 | 
						|
    # by this method.
 | 
						|
    # <p>
 | 
						|
    # If a mask is provided, the method returns a histogram for those
 | 
						|
    # parts of the image where the mask image is non-zero. The mask
 | 
						|
    # image must have the same size as the image, and be either a
 | 
						|
    # bi-level image (mode "1") or a greyscale image ("L").
 | 
						|
    #
 | 
						|
    # @def histogram(mask=None)
 | 
						|
    # @param mask An optional mask.
 | 
						|
    # @return A list containing pixel counts.
 | 
						|
 | 
						|
    def histogram(self, mask=None, extrema=None):
 | 
						|
        "Take histogram of image"
 | 
						|
 | 
						|
        self.load()
 | 
						|
        if mask:
 | 
						|
            mask.load()
 | 
						|
            return self.im.histogram((0, 0), mask.im)
 | 
						|
        if self.mode in ("I", "F"):
 | 
						|
            if extrema is None:
 | 
						|
                extrema = self.getextrema()
 | 
						|
            return self.im.histogram(extrema)
 | 
						|
        return self.im.histogram()
 | 
						|
 | 
						|
    ##
 | 
						|
    # (Deprecated) Returns a copy of the image where the data has been
 | 
						|
    # offset by the given distances. Data wraps around the edges. If
 | 
						|
    # yoffset is omitted, it is assumed to be equal to xoffset.
 | 
						|
    # <p>
 | 
						|
    # This method is deprecated. New code should use the <b>offset</b>
 | 
						|
    # function in the <b>ImageChops</b> module.
 | 
						|
    #
 | 
						|
    # @param xoffset The horizontal distance.
 | 
						|
    # @param yoffset The vertical distance.  If omitted, both
 | 
						|
    #    distances are set to the same value.
 | 
						|
    # @return An Image object.
 | 
						|
 | 
						|
    def offset(self, xoffset, yoffset=None):
 | 
						|
        "(deprecated) Offset image in horizontal and/or vertical direction"
 | 
						|
        if warnings:
 | 
						|
            warnings.warn(
 | 
						|
                "'offset' is deprecated; use 'ImageChops.offset' instead",
 | 
						|
                DeprecationWarning, stacklevel=2
 | 
						|
                )
 | 
						|
        from PIL import ImageChops
 | 
						|
        return ImageChops.offset(self, xoffset, yoffset)
 | 
						|
 | 
						|
    ##
 | 
						|
    # Pastes another image into this image. The box argument is either
 | 
						|
    # a 2-tuple giving the upper left corner, a 4-tuple defining the
 | 
						|
    # left, upper, right, and lower pixel coordinate, or None (same as
 | 
						|
    # (0, 0)).  If a 4-tuple is given, the size of the pasted image
 | 
						|
    # must match the size of the region.
 | 
						|
    # <p>
 | 
						|
    # If the modes don't match, the pasted image is converted to the
 | 
						|
    # mode of this image (see the {@link #Image.convert} method for
 | 
						|
    # details).
 | 
						|
    # <p>
 | 
						|
    # Instead of an image, the source can be a integer or tuple
 | 
						|
    # containing pixel values.  The method then fills the region
 | 
						|
    # with the given colour.  When creating RGB images, you can
 | 
						|
    # also use colour strings as supported by the ImageColor module.
 | 
						|
    # <p>
 | 
						|
    # If a mask is given, this method updates only the regions
 | 
						|
    # indicated by the mask.  You can use either "1", "L" or "RGBA"
 | 
						|
    # images (in the latter case, the alpha band is used as mask).
 | 
						|
    # Where the mask is 255, the given image is copied as is.  Where
 | 
						|
    # the mask is 0, the current value is preserved.  Intermediate
 | 
						|
    # values can be used for transparency effects.
 | 
						|
    # <p>
 | 
						|
    # Note that if you paste an "RGBA" image, the alpha band is
 | 
						|
    # ignored.  You can work around this by using the same image as
 | 
						|
    # both source image and mask.
 | 
						|
    #
 | 
						|
    # @param im Source image or pixel value (integer or tuple).
 | 
						|
    # @param box An optional 4-tuple giving the region to paste into.
 | 
						|
    #    If a 2-tuple is used instead, it's treated as the upper left
 | 
						|
    #    corner.  If omitted or None, the source is pasted into the
 | 
						|
    #    upper left corner.
 | 
						|
    #    <p>
 | 
						|
    #    If an image is given as the second argument and there is no
 | 
						|
    #    third, the box defaults to (0, 0), and the second argument
 | 
						|
    #    is interpreted as a mask image.
 | 
						|
    # @param mask An optional mask image.
 | 
						|
    # @return An Image object.
 | 
						|
 | 
						|
    def paste(self, im, box=None, mask=None):
 | 
						|
        "Paste other image into region"
 | 
						|
 | 
						|
        if isImageType(box) and mask is None:
 | 
						|
            # abbreviated paste(im, mask) syntax
 | 
						|
            mask = box; box = None
 | 
						|
 | 
						|
        if box is None:
 | 
						|
            # cover all of self
 | 
						|
            box = (0, 0) + self.size
 | 
						|
 | 
						|
        if len(box) == 2:
 | 
						|
            # lower left corner given; get size from image or mask
 | 
						|
            if isImageType(im):
 | 
						|
                size = im.size
 | 
						|
            elif isImageType(mask):
 | 
						|
                size = mask.size
 | 
						|
            else:
 | 
						|
                # FIXME: use self.size here?
 | 
						|
                raise ValueError(
 | 
						|
                    "cannot determine region size; use 4-item box"
 | 
						|
                    )
 | 
						|
            box = box + (box[0]+size[0], box[1]+size[1])
 | 
						|
 | 
						|
        if isStringType(im):
 | 
						|
            from PIL import ImageColor
 | 
						|
            im = ImageColor.getcolor(im, self.mode)
 | 
						|
 | 
						|
        elif isImageType(im):
 | 
						|
            im.load()
 | 
						|
            if self.mode != im.mode:
 | 
						|
                if self.mode != "RGB" or im.mode not in ("RGBA", "RGBa"):
 | 
						|
                    # should use an adapter for this!
 | 
						|
                    im = im.convert(self.mode)
 | 
						|
            im = im.im
 | 
						|
 | 
						|
        self.load()
 | 
						|
        if self.readonly:
 | 
						|
            self._copy()
 | 
						|
 | 
						|
        if mask:
 | 
						|
            mask.load()
 | 
						|
            self.im.paste(im, box, mask.im)
 | 
						|
        else:
 | 
						|
            self.im.paste(im, box)
 | 
						|
 | 
						|
    ##
 | 
						|
    # Maps this image through a lookup table or function.
 | 
						|
    #
 | 
						|
    # @param lut A lookup table, containing 256 values per band in the
 | 
						|
    #    image. A function can be used instead, it should take a single
 | 
						|
    #    argument. The function is called once for each possible pixel
 | 
						|
    #    value, and the resulting table is applied to all bands of the
 | 
						|
    #    image.
 | 
						|
    # @param mode Output mode (default is same as input).  In the
 | 
						|
    #    current version, this can only be used if the source image
 | 
						|
    #    has mode "L" or "P", and the output has mode "1".
 | 
						|
    # @return An Image object.
 | 
						|
 | 
						|
    def point(self, lut, mode=None):
 | 
						|
        "Map image through lookup table"
 | 
						|
 | 
						|
        self.load()
 | 
						|
 | 
						|
        if isinstance(lut, ImagePointHandler):
 | 
						|
            return lut.point(self)
 | 
						|
 | 
						|
        if not isinstance(lut, collections.Sequence):
 | 
						|
            # if it isn't a list, it should be a function
 | 
						|
            if self.mode in ("I", "I;16", "F"):
 | 
						|
                # check if the function can be used with point_transform
 | 
						|
                scale, offset = _getscaleoffset(lut)
 | 
						|
                return self._new(self.im.point_transform(scale, offset))
 | 
						|
            # for other modes, convert the function to a table
 | 
						|
            lut = [lut(i) for i in range(256)] * self.im.bands
 | 
						|
 | 
						|
        if self.mode == "F":
 | 
						|
            # FIXME: _imaging returns a confusing error message for this case
 | 
						|
            raise ValueError("point operation not supported for this mode")
 | 
						|
 | 
						|
        return self._new(self.im.point(lut, mode))
 | 
						|
 | 
						|
    ##
 | 
						|
    # Adds or replaces the alpha layer in this image.  If the image
 | 
						|
    # does not have an alpha layer, it's converted to "LA" or "RGBA".
 | 
						|
    # The new layer must be either "L" or "1".
 | 
						|
    #
 | 
						|
    # @param im The new alpha layer.  This can either be an "L" or "1"
 | 
						|
    #    image having the same size as this image, or an integer or
 | 
						|
    #    other color value.
 | 
						|
 | 
						|
    def putalpha(self, alpha):
 | 
						|
        "Set alpha layer"
 | 
						|
 | 
						|
        self.load()
 | 
						|
        if self.readonly:
 | 
						|
            self._copy()
 | 
						|
 | 
						|
        if self.mode not in ("LA", "RGBA"):
 | 
						|
            # attempt to promote self to a matching alpha mode
 | 
						|
            try:
 | 
						|
                mode = getmodebase(self.mode) + "A"
 | 
						|
                try:
 | 
						|
                    self.im.setmode(mode)
 | 
						|
                except (AttributeError, ValueError):
 | 
						|
                    # do things the hard way
 | 
						|
                    im = self.im.convert(mode)
 | 
						|
                    if im.mode not in ("LA", "RGBA"):
 | 
						|
                        raise ValueError # sanity check
 | 
						|
                    self.im = im
 | 
						|
                self.mode = self.im.mode
 | 
						|
            except (KeyError, ValueError):
 | 
						|
                raise ValueError("illegal image mode")
 | 
						|
 | 
						|
        if self.mode == "LA":
 | 
						|
            band = 1
 | 
						|
        else:
 | 
						|
            band = 3
 | 
						|
 | 
						|
        if isImageType(alpha):
 | 
						|
            # alpha layer
 | 
						|
            if alpha.mode not in ("1", "L"):
 | 
						|
                raise ValueError("illegal image mode")
 | 
						|
            alpha.load()
 | 
						|
            if alpha.mode == "1":
 | 
						|
                alpha = alpha.convert("L")
 | 
						|
        else:
 | 
						|
            # constant alpha
 | 
						|
            try:
 | 
						|
                self.im.fillband(band, alpha)
 | 
						|
            except (AttributeError, ValueError):
 | 
						|
                # do things the hard way
 | 
						|
                alpha = new("L", self.size, alpha)
 | 
						|
            else:
 | 
						|
                return
 | 
						|
 | 
						|
        self.im.putband(alpha.im, band)
 | 
						|
 | 
						|
    ##
 | 
						|
    # Copies pixel data to this image.  This method copies data from a
 | 
						|
    # sequence object into the image, starting at the upper left
 | 
						|
    # corner (0, 0), and continuing until either the image or the
 | 
						|
    # sequence ends.  The scale and offset values are used to adjust
 | 
						|
    # the sequence values: <b>pixel = value*scale + offset</b>.
 | 
						|
    #
 | 
						|
    # @param data A sequence object.
 | 
						|
    # @param scale An optional scale value.  The default is 1.0.
 | 
						|
    # @param offset An optional offset value.  The default is 0.0.
 | 
						|
 | 
						|
    def putdata(self, data, scale=1.0, offset=0.0):
 | 
						|
        "Put data from a sequence object into an image."
 | 
						|
 | 
						|
        self.load()
 | 
						|
        if self.readonly:
 | 
						|
            self._copy()
 | 
						|
 | 
						|
        self.im.putdata(data, scale, offset)
 | 
						|
 | 
						|
    ##
 | 
						|
    # Attaches a palette to this image.  The image must be a "P" or
 | 
						|
    # "L" image, and the palette sequence must contain 768 integer
 | 
						|
    # values, where each group of three values represent the red,
 | 
						|
    # green, and blue values for the corresponding pixel
 | 
						|
    # index. Instead of an integer sequence, you can use an 8-bit
 | 
						|
    # string.
 | 
						|
    #
 | 
						|
    # @def putpalette(data)
 | 
						|
    # @param data A palette sequence (either a list or a string).
 | 
						|
 | 
						|
    def putpalette(self, data, rawmode="RGB"):
 | 
						|
        "Put palette data into an image."
 | 
						|
        from PIL import ImagePalette
 | 
						|
 | 
						|
        if self.mode not in ("L", "P"):
 | 
						|
            raise ValueError("illegal image mode")
 | 
						|
        self.load()
 | 
						|
        if isinstance(data, ImagePalette.ImagePalette):
 | 
						|
            palette = ImagePalette.raw(data.rawmode, data.palette)
 | 
						|
        else:
 | 
						|
            if not isinstance(data, bytes):
 | 
						|
                if bytes is str:
 | 
						|
                    data = "".join(chr(x) for x in data)
 | 
						|
                else:
 | 
						|
                    data = bytes(data)
 | 
						|
            palette = ImagePalette.raw(rawmode, data)
 | 
						|
        self.mode = "P"
 | 
						|
        self.palette = palette
 | 
						|
        self.palette.mode = "RGB"
 | 
						|
        self.load() # install new palette
 | 
						|
 | 
						|
    ##
 | 
						|
    # Modifies the pixel at the given position. The colour is given as
 | 
						|
    # a single numerical value for single-band images, and a tuple for
 | 
						|
    # multi-band images.
 | 
						|
    # <p>
 | 
						|
    # Note that this method is relatively slow.  For more extensive
 | 
						|
    # changes, use {@link #Image.paste} or the <b>ImageDraw</b> module
 | 
						|
    # instead.
 | 
						|
    #
 | 
						|
    # @param xy The pixel coordinate, given as (x, y).
 | 
						|
    # @param value The pixel value.
 | 
						|
    # @see #Image.paste
 | 
						|
    # @see #Image.putdata
 | 
						|
    # @see ImageDraw
 | 
						|
 | 
						|
    def putpixel(self, xy, value):
 | 
						|
        "Set pixel value"
 | 
						|
 | 
						|
        self.load()
 | 
						|
        if self.readonly:
 | 
						|
            self._copy()
 | 
						|
 | 
						|
        return self.im.putpixel(xy, value)
 | 
						|
 | 
						|
    ##
 | 
						|
    # Returns a resized copy of this image.
 | 
						|
    #
 | 
						|
    # @def resize(size, filter=NEAREST)
 | 
						|
    # @param size The requested size in pixels, as a 2-tuple:
 | 
						|
    #    (width, height).
 | 
						|
    # @param filter An optional resampling filter.  This can be
 | 
						|
    #    one of <b>NEAREST</b> (use nearest neighbour), <b>BILINEAR</b>
 | 
						|
    #    (linear interpolation in a 2x2 environment), <b>BICUBIC</b>
 | 
						|
    #    (cubic spline interpolation in a 4x4 environment), or
 | 
						|
    #    <b>ANTIALIAS</b> (a high-quality downsampling filter).
 | 
						|
    #    If omitted, or if the image has mode "1" or "P", it is
 | 
						|
    #    set <b>NEAREST</b>.
 | 
						|
    # @return An Image object.
 | 
						|
 | 
						|
    def resize(self, size, resample=NEAREST):
 | 
						|
        "Resize image"
 | 
						|
 | 
						|
        if resample not in (NEAREST, BILINEAR, BICUBIC, ANTIALIAS):
 | 
						|
            raise ValueError("unknown resampling filter")
 | 
						|
 | 
						|
        self.load()
 | 
						|
 | 
						|
        if self.mode in ("1", "P"):
 | 
						|
            resample = NEAREST
 | 
						|
 | 
						|
        if resample == ANTIALIAS:
 | 
						|
            # requires stretch support (imToolkit & PIL 1.1.3)
 | 
						|
            try:
 | 
						|
                im = self.im.stretch(size, resample)
 | 
						|
            except AttributeError:
 | 
						|
                raise ValueError("unsupported resampling filter")
 | 
						|
        else:
 | 
						|
            im = self.im.resize(size, resample)
 | 
						|
 | 
						|
        return self._new(im)
 | 
						|
 | 
						|
    ##
 | 
						|
    # Returns a rotated copy of this image.  This method returns a
 | 
						|
    # copy of this image, rotated the given number of degrees counter
 | 
						|
    # clockwise around its centre.
 | 
						|
    #
 | 
						|
    # @def rotate(angle, filter=NEAREST)
 | 
						|
    # @param angle In degrees counter clockwise.
 | 
						|
    # @param filter An optional resampling filter.  This can be
 | 
						|
    #    one of <b>NEAREST</b> (use nearest neighbour), <b>BILINEAR</b>
 | 
						|
    #    (linear interpolation in a 2x2 environment), or <b>BICUBIC</b>
 | 
						|
    #    (cubic spline interpolation in a 4x4 environment).
 | 
						|
    #    If omitted, or if the image has mode "1" or "P", it is
 | 
						|
    #    set <b>NEAREST</b>.
 | 
						|
    # @param expand Optional expansion flag.  If true, expands the output
 | 
						|
    #    image to make it large enough to hold the entire rotated image.
 | 
						|
    #    If false or omitted, make the output image the same size as the
 | 
						|
    #    input image.
 | 
						|
    # @return An Image object.
 | 
						|
 | 
						|
    def rotate(self, angle, resample=NEAREST, expand=0):
 | 
						|
        "Rotate image.  Angle given as degrees counter-clockwise."
 | 
						|
 | 
						|
        if expand:
 | 
						|
            import math
 | 
						|
            angle = -angle * math.pi / 180
 | 
						|
            matrix = [
 | 
						|
                 math.cos(angle), math.sin(angle), 0.0,
 | 
						|
                -math.sin(angle), math.cos(angle), 0.0
 | 
						|
                 ]
 | 
						|
            def transform(x, y, matrix=matrix):
 | 
						|
                (a, b, c, d, e, f) = matrix
 | 
						|
                return a*x + b*y + c, d*x + e*y + f
 | 
						|
 | 
						|
            # calculate output size
 | 
						|
            w, h = self.size
 | 
						|
            xx = []
 | 
						|
            yy = []
 | 
						|
            for x, y in ((0, 0), (w, 0), (w, h), (0, h)):
 | 
						|
                x, y = transform(x, y)
 | 
						|
                xx.append(x)
 | 
						|
                yy.append(y)
 | 
						|
            w = int(math.ceil(max(xx)) - math.floor(min(xx)))
 | 
						|
            h = int(math.ceil(max(yy)) - math.floor(min(yy)))
 | 
						|
 | 
						|
            # adjust center
 | 
						|
            x, y = transform(w / 2.0, h / 2.0)
 | 
						|
            matrix[2] = self.size[0] / 2.0 - x
 | 
						|
            matrix[5] = self.size[1] / 2.0 - y
 | 
						|
 | 
						|
            return self.transform((w, h), AFFINE, matrix, resample)
 | 
						|
 | 
						|
        if resample not in (NEAREST, BILINEAR, BICUBIC):
 | 
						|
            raise ValueError("unknown resampling filter")
 | 
						|
 | 
						|
        self.load()
 | 
						|
 | 
						|
        if self.mode in ("1", "P"):
 | 
						|
            resample = NEAREST
 | 
						|
 | 
						|
        return self._new(self.im.rotate(angle, resample))
 | 
						|
 | 
						|
    ##
 | 
						|
    # Saves this image under the given filename.  If no format is
 | 
						|
    # specified, the format to use is determined from the filename
 | 
						|
    # extension, if possible.
 | 
						|
    # <p>
 | 
						|
    # Keyword options can be used to provide additional instructions
 | 
						|
    # to the writer. If a writer doesn't recognise an option, it is
 | 
						|
    # silently ignored. The available options are described later in
 | 
						|
    # this handbook.
 | 
						|
    # <p>
 | 
						|
    # You can use a file object instead of a filename. In this case,
 | 
						|
    # you must always specify the format. The file object must
 | 
						|
    # implement the <b>seek</b>, <b>tell</b>, and <b>write</b>
 | 
						|
    # methods, and be opened in binary mode.
 | 
						|
    #
 | 
						|
    # @def save(file, format=None, **options)
 | 
						|
    # @param file File name or file object.
 | 
						|
    # @param format Optional format override.  If omitted, the
 | 
						|
    #    format to use is determined from the filename extension.
 | 
						|
    #    If a file object was used instead of a filename, this
 | 
						|
    #    parameter should always be used.
 | 
						|
    # @param **options Extra parameters to the image writer.
 | 
						|
    # @return None
 | 
						|
    # @exception KeyError If the output format could not be determined
 | 
						|
    #    from the file name.  Use the format option to solve this.
 | 
						|
    # @exception IOError If the file could not be written.  The file
 | 
						|
    #    may have been created, and may contain partial data.
 | 
						|
 | 
						|
    def save(self, fp, format=None, **params):
 | 
						|
        "Save image to file or stream"
 | 
						|
 | 
						|
        if isStringType(fp):
 | 
						|
            filename = fp
 | 
						|
        else:
 | 
						|
            if hasattr(fp, "name") and isStringType(fp.name):
 | 
						|
                filename = fp.name
 | 
						|
            else:
 | 
						|
                filename = ""
 | 
						|
 | 
						|
        # may mutate self!
 | 
						|
        self.load()
 | 
						|
 | 
						|
        self.encoderinfo = params
 | 
						|
        self.encoderconfig = ()
 | 
						|
 | 
						|
        preinit()
 | 
						|
 | 
						|
        ext = os.path.splitext(filename)[1].lower()
 | 
						|
 | 
						|
        if not format:
 | 
						|
            try:
 | 
						|
                format = EXTENSION[ext]
 | 
						|
            except KeyError:
 | 
						|
                init()
 | 
						|
                try:
 | 
						|
                    format = EXTENSION[ext]
 | 
						|
                except KeyError:
 | 
						|
                    raise KeyError(ext) # unknown extension
 | 
						|
 | 
						|
        try:
 | 
						|
            save_handler = SAVE[format.upper()]
 | 
						|
        except KeyError:
 | 
						|
            init()
 | 
						|
            save_handler = SAVE[format.upper()] # unknown format
 | 
						|
 | 
						|
        if isStringType(fp):
 | 
						|
            fp = builtins.open(fp, "wb")
 | 
						|
            close = 1
 | 
						|
        else:
 | 
						|
            close = 0
 | 
						|
 | 
						|
        try:
 | 
						|
            save_handler(self, fp, filename)
 | 
						|
        finally:
 | 
						|
            # do what we can to clean up
 | 
						|
            if close:
 | 
						|
                fp.close()
 | 
						|
 | 
						|
    ##
 | 
						|
    # Seeks to the given frame in this sequence file. If you seek
 | 
						|
    # beyond the end of the sequence, the method raises an
 | 
						|
    # <b>EOFError</b> exception. When a sequence file is opened, the
 | 
						|
    # library automatically seeks to frame 0.
 | 
						|
    # <p>
 | 
						|
    # Note that in the current version of the library, most sequence
 | 
						|
    # formats only allows you to seek to the next frame.
 | 
						|
    #
 | 
						|
    # @param frame Frame number, starting at 0.
 | 
						|
    # @exception EOFError If the call attempts to seek beyond the end
 | 
						|
    #     of the sequence.
 | 
						|
    # @see #Image.tell
 | 
						|
 | 
						|
    def seek(self, frame):
 | 
						|
        "Seek to given frame in sequence file"
 | 
						|
 | 
						|
        # overridden by file handlers
 | 
						|
        if frame != 0:
 | 
						|
            raise EOFError
 | 
						|
 | 
						|
    ##
 | 
						|
    # Displays this image. This method is mainly intended for
 | 
						|
    # debugging purposes.
 | 
						|
    # <p>
 | 
						|
    # On Unix platforms, this method saves the image to a temporary
 | 
						|
    # PPM file, and calls the <b>xv</b> utility.
 | 
						|
    # <p>
 | 
						|
    # On Windows, it saves the image to a temporary BMP file, and uses
 | 
						|
    # the standard BMP display utility to show it (usually Paint).
 | 
						|
    #
 | 
						|
    # @def show(title=None)
 | 
						|
    # @param title Optional title to use for the image window,
 | 
						|
    #    where possible.
 | 
						|
 | 
						|
    def show(self, title=None, command=None):
 | 
						|
        "Display image (for debug purposes only)"
 | 
						|
 | 
						|
        _show(self, title=title, command=command)
 | 
						|
 | 
						|
    ##
 | 
						|
    # Split this image into individual bands. This method returns a
 | 
						|
    # tuple of individual image bands from an image. For example,
 | 
						|
    # splitting an "RGB" image creates three new images each
 | 
						|
    # containing a copy of one of the original bands (red, green,
 | 
						|
    # blue).
 | 
						|
    #
 | 
						|
    # @return A tuple containing bands.
 | 
						|
 | 
						|
    def split(self):
 | 
						|
        "Split image into bands"
 | 
						|
 | 
						|
        self.load()
 | 
						|
        if self.im.bands == 1:
 | 
						|
            ims = [self.copy()]
 | 
						|
        else:
 | 
						|
            ims = []
 | 
						|
            for i in range(self.im.bands):
 | 
						|
                ims.append(self._new(self.im.getband(i)))
 | 
						|
        return tuple(ims)
 | 
						|
 | 
						|
    ##
 | 
						|
    # Returns the current frame number.
 | 
						|
    #
 | 
						|
    # @return Frame number, starting with 0.
 | 
						|
    # @see #Image.seek
 | 
						|
 | 
						|
    def tell(self):
 | 
						|
        "Return current frame number"
 | 
						|
 | 
						|
        return 0
 | 
						|
 | 
						|
    ##
 | 
						|
    # Make this image into a thumbnail.  This method modifies the
 | 
						|
    # image to contain a thumbnail version of itself, no larger than
 | 
						|
    # the given size.  This method calculates an appropriate thumbnail
 | 
						|
    # size to preserve the aspect of the image, calls the {@link
 | 
						|
    # #Image.draft} method to configure the file reader (where
 | 
						|
    # applicable), and finally resizes the image.
 | 
						|
    # <p>
 | 
						|
    # Note that the bilinear and bicubic filters in the current
 | 
						|
    # version of PIL are not well-suited for thumbnail generation.
 | 
						|
    # You should use <b>ANTIALIAS</b> unless speed is much more
 | 
						|
    # important than quality.
 | 
						|
    # <p>
 | 
						|
    # Also note that this function modifies the Image object in place.
 | 
						|
    # If you need to use the full resolution image as well, apply this
 | 
						|
    # method to a {@link #Image.copy} of the original image.
 | 
						|
    #
 | 
						|
    # @param size Requested size.
 | 
						|
    # @param resample Optional resampling filter.  This can be one
 | 
						|
    #    of <b>NEAREST</b>, <b>BILINEAR</b>, <b>BICUBIC</b>, or
 | 
						|
    #    <b>ANTIALIAS</b> (best quality).  If omitted, it defaults
 | 
						|
    #    to <b>NEAREST</b> (this will be changed to ANTIALIAS in a
 | 
						|
    #    future version).
 | 
						|
    # @return None
 | 
						|
 | 
						|
    def thumbnail(self, size, resample=NEAREST):
 | 
						|
        "Create thumbnail representation (modifies image in place)"
 | 
						|
 | 
						|
        # FIXME: the default resampling filter will be changed
 | 
						|
        # to ANTIALIAS in future versions
 | 
						|
 | 
						|
        # preserve aspect ratio
 | 
						|
        x, y = self.size
 | 
						|
        if x > size[0]: y = int(max(y * size[0] / x, 1)); x = int(size[0])
 | 
						|
        if y > size[1]: x = int(max(x * size[1] / y, 1)); y = int(size[1])
 | 
						|
        size = x, y
 | 
						|
 | 
						|
        if size == self.size:
 | 
						|
            return
 | 
						|
 | 
						|
        self.draft(None, size)
 | 
						|
 | 
						|
        self.load()
 | 
						|
 | 
						|
        try:
 | 
						|
            im = self.resize(size, resample)
 | 
						|
        except ValueError:
 | 
						|
            if resample != ANTIALIAS:
 | 
						|
                raise
 | 
						|
            im = self.resize(size, NEAREST) # fallback
 | 
						|
 | 
						|
        self.im = im.im
 | 
						|
        self.mode = im.mode
 | 
						|
        self.size = size
 | 
						|
 | 
						|
        self.readonly = 0
 | 
						|
 | 
						|
    # FIXME: the different tranform methods need further explanation
 | 
						|
    # instead of bloating the method docs, add a separate chapter.
 | 
						|
 | 
						|
    ##
 | 
						|
    # Transforms this image.  This method creates a new image with the
 | 
						|
    # given size, and the same mode as the original, and copies data
 | 
						|
    # to the new image using the given transform.
 | 
						|
    # <p>
 | 
						|
    # @def transform(size, method, data, resample=NEAREST)
 | 
						|
    # @param size The output size.
 | 
						|
    # @param method The transformation method.  This is one of
 | 
						|
    #   <b>EXTENT</b> (cut out a rectangular subregion), <b>AFFINE</b>
 | 
						|
    #   (affine transform), <b>PERSPECTIVE</b> (perspective
 | 
						|
    #   transform), <b>QUAD</b> (map a quadrilateral to a
 | 
						|
    #   rectangle), or <b>MESH</b> (map a number of source quadrilaterals
 | 
						|
    #   in one operation).
 | 
						|
    # @param data Extra data to the transformation method.
 | 
						|
    # @param resample Optional resampling filter.  It can be one of
 | 
						|
    #    <b>NEAREST</b> (use nearest neighbour), <b>BILINEAR</b>
 | 
						|
    #    (linear interpolation in a 2x2 environment), or
 | 
						|
    #    <b>BICUBIC</b> (cubic spline interpolation in a 4x4
 | 
						|
    #    environment). If omitted, or if the image has mode
 | 
						|
    #    "1" or "P", it is set to <b>NEAREST</b>.
 | 
						|
    # @return An Image object.
 | 
						|
 | 
						|
    def transform(self, size, method, data=None, resample=NEAREST, fill=1):
 | 
						|
        "Transform image"
 | 
						|
 | 
						|
        if isinstance(method, ImageTransformHandler):
 | 
						|
            return method.transform(size, self, resample=resample, fill=fill)
 | 
						|
        if hasattr(method, "getdata"):
 | 
						|
            # compatibility w. old-style transform objects
 | 
						|
            method, data = method.getdata()
 | 
						|
        if data is None:
 | 
						|
            raise ValueError("missing method data")
 | 
						|
        im = new(self.mode, size, None)
 | 
						|
        if method == MESH:
 | 
						|
            # list of quads
 | 
						|
            for box, quad in data:
 | 
						|
                im.__transformer(box, self, QUAD, quad, resample, fill)
 | 
						|
        else:
 | 
						|
            im.__transformer((0, 0)+size, self, method, data, resample, fill)
 | 
						|
 | 
						|
        return im
 | 
						|
 | 
						|
    def __transformer(self, box, image, method, data,
 | 
						|
                      resample=NEAREST, fill=1):
 | 
						|
 | 
						|
        # FIXME: this should be turned into a lazy operation (?)
 | 
						|
 | 
						|
        w = box[2]-box[0]
 | 
						|
        h = box[3]-box[1]
 | 
						|
 | 
						|
        if method == AFFINE:
 | 
						|
            # change argument order to match implementation
 | 
						|
            data = (data[2], data[0], data[1],
 | 
						|
                    data[5], data[3], data[4])
 | 
						|
        elif method == EXTENT:
 | 
						|
            # convert extent to an affine transform
 | 
						|
            x0, y0, x1, y1 = data
 | 
						|
            xs = float(x1 - x0) / w
 | 
						|
            ys = float(y1 - y0) / h
 | 
						|
            method = AFFINE
 | 
						|
            data = (x0 + xs/2, xs, 0, y0 + ys/2, 0, ys)
 | 
						|
        elif method == PERSPECTIVE:
 | 
						|
            # change argument order to match implementation
 | 
						|
            data = (data[2], data[0], data[1],
 | 
						|
                    data[5], data[3], data[4],
 | 
						|
                    data[6], data[7])
 | 
						|
        elif method == QUAD:
 | 
						|
            # quadrilateral warp.  data specifies the four corners
 | 
						|
            # given as NW, SW, SE, and NE.
 | 
						|
            nw = data[0:2]; sw = data[2:4]; se = data[4:6]; ne = data[6:8]
 | 
						|
            x0, y0 = nw; As = 1.0 / w; At = 1.0 / h
 | 
						|
            data = (x0, (ne[0]-x0)*As, (sw[0]-x0)*At,
 | 
						|
                    (se[0]-sw[0]-ne[0]+x0)*As*At,
 | 
						|
                    y0, (ne[1]-y0)*As, (sw[1]-y0)*At,
 | 
						|
                    (se[1]-sw[1]-ne[1]+y0)*As*At)
 | 
						|
        else:
 | 
						|
            raise ValueError("unknown transformation method")
 | 
						|
 | 
						|
        if resample not in (NEAREST, BILINEAR, BICUBIC):
 | 
						|
            raise ValueError("unknown resampling filter")
 | 
						|
 | 
						|
        image.load()
 | 
						|
 | 
						|
        self.load()
 | 
						|
 | 
						|
        if image.mode in ("1", "P"):
 | 
						|
            resample = NEAREST
 | 
						|
 | 
						|
        self.im.transform2(box, image.im, method, data, resample, fill)
 | 
						|
 | 
						|
    ##
 | 
						|
    # Returns a flipped or rotated copy of this image.
 | 
						|
    #
 | 
						|
    # @param method One of <b>FLIP_LEFT_RIGHT</b>, <b>FLIP_TOP_BOTTOM</b>,
 | 
						|
    # <b>ROTATE_90</b>, <b>ROTATE_180</b>, or <b>ROTATE_270</b>.
 | 
						|
 | 
						|
    def transpose(self, method):
 | 
						|
        "Transpose image (flip or rotate in 90 degree steps)"
 | 
						|
 | 
						|
        self.load()
 | 
						|
        im = self.im.transpose(method)
 | 
						|
        return self._new(im)
 | 
						|
 | 
						|
# --------------------------------------------------------------------
 | 
						|
# Lazy operations
 | 
						|
 | 
						|
class _ImageCrop(Image):
 | 
						|
 | 
						|
    def __init__(self, im, box):
 | 
						|
 | 
						|
        Image.__init__(self)
 | 
						|
 | 
						|
        x0, y0, x1, y1 = box
 | 
						|
        if x1 < x0:
 | 
						|
            x1 = x0
 | 
						|
        if y1 < y0:
 | 
						|
            y1 = y0
 | 
						|
 | 
						|
        self.mode = im.mode
 | 
						|
        self.size = x1-x0, y1-y0
 | 
						|
 | 
						|
        self.__crop = x0, y0, x1, y1
 | 
						|
 | 
						|
        self.im = im.im
 | 
						|
 | 
						|
    def load(self):
 | 
						|
 | 
						|
        # lazy evaluation!
 | 
						|
        if self.__crop:
 | 
						|
            self.im = self.im.crop(self.__crop)
 | 
						|
            self.__crop = None
 | 
						|
 | 
						|
        if self.im:
 | 
						|
            return self.im.pixel_access(self.readonly)
 | 
						|
 | 
						|
        # FIXME: future versions should optimize crop/paste
 | 
						|
        # sequences!
 | 
						|
 | 
						|
# --------------------------------------------------------------------
 | 
						|
# Abstract handlers.
 | 
						|
 | 
						|
class ImagePointHandler:
 | 
						|
    # used as a mixin by point transforms (for use with im.point)
 | 
						|
    pass
 | 
						|
 | 
						|
class ImageTransformHandler:
 | 
						|
    # used as a mixin by geometry transforms (for use with im.transform)
 | 
						|
    pass
 | 
						|
 | 
						|
# --------------------------------------------------------------------
 | 
						|
# Factories
 | 
						|
 | 
						|
#
 | 
						|
# Debugging
 | 
						|
 | 
						|
def _wedge():
 | 
						|
    "Create greyscale wedge (for debugging only)"
 | 
						|
 | 
						|
    return Image()._new(core.wedge("L"))
 | 
						|
 | 
						|
##
 | 
						|
# Creates a new image with the given mode and size.
 | 
						|
#
 | 
						|
# @param mode The mode to use for the new image.
 | 
						|
# @param size A 2-tuple, containing (width, height) in pixels.
 | 
						|
# @param color What colour to use for the image.  Default is black.
 | 
						|
#    If given, this should be a single integer or floating point value
 | 
						|
#    for single-band modes, and a tuple for multi-band modes (one value
 | 
						|
#    per band).  When creating RGB images, you can also use colour
 | 
						|
#    strings as supported by the ImageColor module.  If the colour is
 | 
						|
#    None, the image is not initialised.
 | 
						|
# @return An Image object.
 | 
						|
 | 
						|
def new(mode, size, color=0):
 | 
						|
    "Create a new image"
 | 
						|
 | 
						|
    if color is None:
 | 
						|
        # don't initialize
 | 
						|
        return Image()._new(core.new(mode, size))
 | 
						|
 | 
						|
    if isStringType(color):
 | 
						|
        # css3-style specifier
 | 
						|
 | 
						|
        from PIL import ImageColor
 | 
						|
        color = ImageColor.getcolor(color, mode)
 | 
						|
 | 
						|
    return Image()._new(core.fill(mode, size, color))
 | 
						|
 | 
						|
##
 | 
						|
# Creates a copy of an image memory from pixel data in a buffer.
 | 
						|
# <p>
 | 
						|
# In its simplest form, this function takes three arguments
 | 
						|
# (mode, size, and unpacked pixel data).
 | 
						|
# <p>
 | 
						|
# You can also use any pixel decoder supported by PIL.  For more
 | 
						|
# information on available decoders, see the section <a
 | 
						|
# href="pil-decoder.htm"><i>Writing Your Own File Decoder</i></a>.
 | 
						|
# <p>
 | 
						|
# Note that this function decodes pixel data only, not entire images.
 | 
						|
# If you have an entire image in a string, wrap it in a
 | 
						|
# <b>BytesIO</b> object, and use {@link #open} to load it.
 | 
						|
#
 | 
						|
# @param mode The image mode.
 | 
						|
# @param size The image size.
 | 
						|
# @param data A byte buffer containing raw data for the given mode.
 | 
						|
# @param decoder_name What decoder to use.
 | 
						|
# @param *args Additional parameters for the given decoder.
 | 
						|
# @return An Image object.
 | 
						|
 | 
						|
def frombytes(mode, size, data, decoder_name="raw", *args):
 | 
						|
    "Load image from byte buffer"
 | 
						|
 | 
						|
    # may pass tuple instead of argument list
 | 
						|
    if len(args) == 1 and isinstance(args[0], tuple):
 | 
						|
        args = args[0]
 | 
						|
 | 
						|
    if decoder_name == "raw" and args == ():
 | 
						|
        args = mode
 | 
						|
 | 
						|
    im = new(mode, size)
 | 
						|
    im.frombytes(data, decoder_name, args)
 | 
						|
    return im
 | 
						|
 | 
						|
def fromstring(*args, **kw):
 | 
						|
    " Deprecated alias to frombytes "
 | 
						|
    warnings.warn(
 | 
						|
        'fromstring() is deprecated. Please call frombytes() instead.',
 | 
						|
        DeprecationWarning,
 | 
						|
        stacklevel=2
 | 
						|
    )
 | 
						|
    return frombytes(*args, **kw)
 | 
						|
 | 
						|
##
 | 
						|
# (New in 1.1.4) Creates an image memory referencing pixel data in a
 | 
						|
# byte buffer.
 | 
						|
# <p>
 | 
						|
# This function is similar to {@link #frombytes}, but uses data in
 | 
						|
# the byte buffer, where possible.  This means that changes to the
 | 
						|
# original buffer object are reflected in this image).  Not all modes
 | 
						|
# can share memory; supported modes include "L", "RGBX", "RGBA", and
 | 
						|
# "CMYK".
 | 
						|
# <p>
 | 
						|
# Note that this function decodes pixel data only, not entire images.
 | 
						|
# If you have an entire image file in a string, wrap it in a
 | 
						|
# <b>BytesIO</b> object, and use {@link #open} to load it.
 | 
						|
# <p>
 | 
						|
# In the current version, the default parameters used for the "raw"
 | 
						|
# decoder differs from that used for {@link fromstring}.  This is a
 | 
						|
# bug, and will probably be fixed in a future release.  The current
 | 
						|
# release issues a warning if you do this; to disable the warning,
 | 
						|
# you should provide the full set of parameters.  See below for
 | 
						|
# details.
 | 
						|
#
 | 
						|
# @param mode The image mode.
 | 
						|
# @param size The image size.
 | 
						|
# @param data A bytes or other buffer object containing raw
 | 
						|
#     data for the given mode.
 | 
						|
# @param decoder_name What decoder to use.
 | 
						|
# @param *args Additional parameters for the given decoder.  For the
 | 
						|
#     default encoder ("raw"), it's recommended that you provide the
 | 
						|
#     full set of parameters:
 | 
						|
#     <b>frombuffer(mode, size, data, "raw", mode, 0, 1)</b>.
 | 
						|
# @return An Image object.
 | 
						|
# @since 1.1.4
 | 
						|
 | 
						|
def frombuffer(mode, size, data, decoder_name="raw", *args):
 | 
						|
    "Load image from bytes or buffer"
 | 
						|
 | 
						|
    # may pass tuple instead of argument list
 | 
						|
    if len(args) == 1 and isinstance(args[0], tuple):
 | 
						|
        args = args[0]
 | 
						|
 | 
						|
    if decoder_name == "raw":
 | 
						|
        if args == ():
 | 
						|
            if warnings:
 | 
						|
                warnings.warn(
 | 
						|
                    "the frombuffer defaults may change in a future release; "
 | 
						|
                    "for portability, change the call to read:\n"
 | 
						|
                    "  frombuffer(mode, size, data, 'raw', mode, 0, 1)",
 | 
						|
                    RuntimeWarning, stacklevel=2
 | 
						|
                )
 | 
						|
            args = mode, 0, -1 # may change to (mode, 0, 1) post-1.1.6
 | 
						|
        if args[0] in _MAPMODES:
 | 
						|
            im = new(mode, (1,1))
 | 
						|
            im = im._new(
 | 
						|
                core.map_buffer(data, size, decoder_name, None, 0, args)
 | 
						|
                )
 | 
						|
            im.readonly = 1
 | 
						|
            return im
 | 
						|
 | 
						|
    return frombytes(mode, size, data, decoder_name, args)
 | 
						|
 | 
						|
 | 
						|
##
 | 
						|
# (New in 1.1.6) Creates an image memory from an object exporting
 | 
						|
# the array interface (using the buffer protocol).
 | 
						|
#
 | 
						|
# If obj is not contiguous, then the tobytes method is called
 | 
						|
# and {@link frombuffer} is used.
 | 
						|
#
 | 
						|
# @param obj Object with array interface
 | 
						|
# @param mode Mode to use (will be determined from type if None)
 | 
						|
# @return An image memory.
 | 
						|
 | 
						|
def fromarray(obj, mode=None):
 | 
						|
    arr = obj.__array_interface__
 | 
						|
    shape = arr['shape']
 | 
						|
    ndim = len(shape)
 | 
						|
    try:
 | 
						|
        strides = arr['strides']
 | 
						|
    except KeyError:
 | 
						|
        strides = None
 | 
						|
    if mode is None:
 | 
						|
        try:
 | 
						|
            typekey = (1, 1) + shape[2:], arr['typestr']
 | 
						|
            mode, rawmode = _fromarray_typemap[typekey]
 | 
						|
        except KeyError:
 | 
						|
            # print typekey
 | 
						|
            raise TypeError("Cannot handle this data type")
 | 
						|
    else:
 | 
						|
        rawmode = mode
 | 
						|
    if mode in ["1", "L", "I", "P", "F"]:
 | 
						|
        ndmax = 2
 | 
						|
    elif mode == "RGB":
 | 
						|
        ndmax = 3
 | 
						|
    else:
 | 
						|
        ndmax = 4
 | 
						|
    if ndim > ndmax:
 | 
						|
        raise ValueError("Too many dimensions.")
 | 
						|
 | 
						|
    size = shape[1], shape[0]
 | 
						|
    if strides is not None:
 | 
						|
        obj = obj.tobytes()
 | 
						|
 | 
						|
    return frombuffer(mode, size, obj, "raw", rawmode, 0, 1)
 | 
						|
 | 
						|
_fromarray_typemap = {
 | 
						|
    # (shape, typestr) => mode, rawmode
 | 
						|
    # first two members of shape are set to one
 | 
						|
    # ((1, 1), "|b1"): ("1", "1"), # broken
 | 
						|
    ((1, 1), "|u1"): ("L", "L"),
 | 
						|
    ((1, 1), "|i1"): ("I", "I;8"),
 | 
						|
    ((1, 1), "<i2"): ("I", "I;16"),
 | 
						|
    ((1, 1), ">i2"): ("I", "I;16B"),
 | 
						|
    ((1, 1), "<i4"): ("I", "I;32"),
 | 
						|
    ((1, 1), ">i4"): ("I", "I;32B"),
 | 
						|
    ((1, 1), "<f4"): ("F", "F;32F"),
 | 
						|
    ((1, 1), ">f4"): ("F", "F;32BF"),
 | 
						|
    ((1, 1), "<f8"): ("F", "F;64F"),
 | 
						|
    ((1, 1), ">f8"): ("F", "F;64BF"),
 | 
						|
    ((1, 1, 3), "|u1"): ("RGB", "RGB"),
 | 
						|
    ((1, 1, 4), "|u1"): ("RGBA", "RGBA"),
 | 
						|
    }
 | 
						|
 | 
						|
# shortcuts
 | 
						|
_fromarray_typemap[((1, 1), _ENDIAN + "i4")] = ("I", "I")
 | 
						|
_fromarray_typemap[((1, 1), _ENDIAN + "f4")] = ("F", "F")
 | 
						|
 | 
						|
##
 | 
						|
# Opens and identifies the given image file.
 | 
						|
# <p>
 | 
						|
# This is a lazy operation; this function identifies the file, but the
 | 
						|
# actual image data is not read from the file until you try to process
 | 
						|
# the data (or call the {@link #Image.load} method).
 | 
						|
#
 | 
						|
# @def open(file, mode="r")
 | 
						|
# @param file A filename (string) or a file object.  The file object
 | 
						|
#    must implement <b>read</b>, <b>seek</b>, and <b>tell</b> methods,
 | 
						|
#    and be opened in binary mode.
 | 
						|
# @param mode The mode.  If given, this argument must be "r".
 | 
						|
# @return An Image object.
 | 
						|
# @exception IOError If the file cannot be found, or the image cannot be
 | 
						|
#    opened and identified.
 | 
						|
# @see #new
 | 
						|
 | 
						|
def open(fp, mode="r"):
 | 
						|
    "Open an image file, without loading the raster data"
 | 
						|
 | 
						|
    if mode != "r":
 | 
						|
        raise ValueError("bad mode")
 | 
						|
 | 
						|
    if isStringType(fp):
 | 
						|
        filename = fp
 | 
						|
        fp = builtins.open(fp, "rb")
 | 
						|
    else:
 | 
						|
        filename = ""
 | 
						|
 | 
						|
    prefix = fp.read(16)
 | 
						|
 | 
						|
    preinit()
 | 
						|
 | 
						|
    for i in ID:
 | 
						|
        try:
 | 
						|
            factory, accept = OPEN[i]
 | 
						|
            if not accept or accept(prefix):
 | 
						|
                fp.seek(0)
 | 
						|
                return factory(fp, filename)
 | 
						|
        except (SyntaxError, IndexError, TypeError):
 | 
						|
            #import traceback
 | 
						|
            #traceback.print_exc()
 | 
						|
            pass
 | 
						|
 | 
						|
    if init():
 | 
						|
 | 
						|
        for i in ID:
 | 
						|
            try:
 | 
						|
                factory, accept = OPEN[i]
 | 
						|
                if not accept or accept(prefix):
 | 
						|
                    fp.seek(0)
 | 
						|
                    return factory(fp, filename)
 | 
						|
            except (SyntaxError, IndexError, TypeError):
 | 
						|
                #import traceback
 | 
						|
                #traceback.print_exc()
 | 
						|
                pass
 | 
						|
 | 
						|
    raise IOError("cannot identify image file")
 | 
						|
 | 
						|
#
 | 
						|
# Image processing.
 | 
						|
 | 
						|
##
 | 
						|
# Alpha composites im2 over im1.
 | 
						|
#
 | 
						|
# @param im1 The first image.
 | 
						|
# @param im2 The second image.  Must have the same mode and size as
 | 
						|
#    the first image.
 | 
						|
# @return An Image object.
 | 
						|
 | 
						|
def alpha_composite(im1, im2):
 | 
						|
    "Alpha composite im2 over im1."
 | 
						|
 | 
						|
    im1.load()
 | 
						|
    im2.load()
 | 
						|
    return im1._new(core.alpha_composite(im1.im, im2.im))
 | 
						|
 | 
						|
##
 | 
						|
# Creates a new image by interpolating between two input images, using
 | 
						|
# a constant alpha.
 | 
						|
#
 | 
						|
# <pre>
 | 
						|
#    out = image1 * (1.0 - alpha) + image2 * alpha
 | 
						|
# </pre>
 | 
						|
#
 | 
						|
# @param im1 The first image.
 | 
						|
# @param im2 The second image.  Must have the same mode and size as
 | 
						|
#    the first image.
 | 
						|
# @param alpha The interpolation alpha factor.  If alpha is 0.0, a
 | 
						|
#    copy of the first image is returned. If alpha is 1.0, a copy of
 | 
						|
#    the second image is returned. There are no restrictions on the
 | 
						|
#    alpha value. If necessary, the result is clipped to fit into
 | 
						|
#    the allowed output range.
 | 
						|
# @return An Image object.
 | 
						|
 | 
						|
def blend(im1, im2, alpha):
 | 
						|
    "Interpolate between images."
 | 
						|
 | 
						|
    im1.load()
 | 
						|
    im2.load()
 | 
						|
    return im1._new(core.blend(im1.im, im2.im, alpha))
 | 
						|
 | 
						|
##
 | 
						|
# Creates a new image by interpolating between two input images,
 | 
						|
# using the mask as alpha.
 | 
						|
#
 | 
						|
# @param image1 The first image.
 | 
						|
# @param image2 The second image.  Must have the same mode and
 | 
						|
#    size as the first image.
 | 
						|
# @param mask A mask image.  This image can can have mode
 | 
						|
#    "1", "L", or "RGBA", and must have the same size as the
 | 
						|
#    other two images.
 | 
						|
 | 
						|
def composite(image1, image2, mask):
 | 
						|
    "Create composite image by blending images using a transparency mask"
 | 
						|
 | 
						|
    image = image2.copy()
 | 
						|
    image.paste(image1, None, mask)
 | 
						|
    return image
 | 
						|
 | 
						|
##
 | 
						|
# Applies the function (which should take one argument) to each pixel
 | 
						|
# in the given image. If the image has more than one band, the same
 | 
						|
# function is applied to each band. Note that the function is
 | 
						|
# evaluated once for each possible pixel value, so you cannot use
 | 
						|
# random components or other generators.
 | 
						|
#
 | 
						|
# @def eval(image, function)
 | 
						|
# @param image The input image.
 | 
						|
# @param function A function object, taking one integer argument.
 | 
						|
# @return An Image object.
 | 
						|
 | 
						|
def eval(image, *args):
 | 
						|
    "Evaluate image expression"
 | 
						|
 | 
						|
    return image.point(args[0])
 | 
						|
 | 
						|
##
 | 
						|
# Creates a new image from a number of single-band images.
 | 
						|
#
 | 
						|
# @param mode The mode to use for the output image.
 | 
						|
# @param bands A sequence containing one single-band image for
 | 
						|
#     each band in the output image.  All bands must have the
 | 
						|
#     same size.
 | 
						|
# @return An Image object.
 | 
						|
 | 
						|
def merge(mode, bands):
 | 
						|
    "Merge a set of single band images into a new multiband image."
 | 
						|
 | 
						|
    if getmodebands(mode) != len(bands) or "*" in mode:
 | 
						|
        raise ValueError("wrong number of bands")
 | 
						|
    for im in bands[1:]:
 | 
						|
        if im.mode != getmodetype(mode):
 | 
						|
            raise ValueError("mode mismatch")
 | 
						|
        if im.size != bands[0].size:
 | 
						|
            raise ValueError("size mismatch")
 | 
						|
    im = core.new(mode, bands[0].size)
 | 
						|
    for i in range(getmodebands(mode)):
 | 
						|
        bands[i].load()
 | 
						|
        im.putband(bands[i].im, i)
 | 
						|
    return bands[0]._new(im)
 | 
						|
 | 
						|
# --------------------------------------------------------------------
 | 
						|
# Plugin registry
 | 
						|
 | 
						|
##
 | 
						|
# Register an image file plugin.  This function should not be used
 | 
						|
# in application code.
 | 
						|
#
 | 
						|
# @param id An image format identifier.
 | 
						|
# @param factory An image file factory method.
 | 
						|
# @param accept An optional function that can be used to quickly
 | 
						|
#    reject images having another format.
 | 
						|
 | 
						|
def register_open(id, factory, accept=None):
 | 
						|
    id = id.upper()
 | 
						|
    ID.append(id)
 | 
						|
    OPEN[id] = factory, accept
 | 
						|
 | 
						|
##
 | 
						|
# Registers an image MIME type.  This function should not be used
 | 
						|
# in application code.
 | 
						|
#
 | 
						|
# @param id An image format identifier.
 | 
						|
# @param mimetype The image MIME type for this format.
 | 
						|
 | 
						|
def register_mime(id, mimetype):
 | 
						|
    MIME[id.upper()] = mimetype
 | 
						|
 | 
						|
##
 | 
						|
# Registers an image save function.  This function should not be
 | 
						|
# used in application code.
 | 
						|
#
 | 
						|
# @param id An image format identifier.
 | 
						|
# @param driver A function to save images in this format.
 | 
						|
 | 
						|
def register_save(id, driver):
 | 
						|
    SAVE[id.upper()] = driver
 | 
						|
 | 
						|
##
 | 
						|
# Registers an image extension.  This function should not be
 | 
						|
# used in application code.
 | 
						|
#
 | 
						|
# @param id An image format identifier.
 | 
						|
# @param extension An extension used for this format.
 | 
						|
 | 
						|
def register_extension(id, extension):
 | 
						|
    EXTENSION[extension.lower()] = id.upper()
 | 
						|
 | 
						|
 | 
						|
# --------------------------------------------------------------------
 | 
						|
# Simple display support.  User code may override this.
 | 
						|
 | 
						|
def _show(image, **options):
 | 
						|
    # override me, as necessary
 | 
						|
    _showxv(image, **options)
 | 
						|
 | 
						|
def _showxv(image, title=None, **options):
 | 
						|
    from PIL import ImageShow
 | 
						|
    ImageShow.show(image, title, **options)
 |