Merge remote-tracking branch 'upstream/master' into MspImagePlugin
Conflicts: Tests/helper.py
| 
						 | 
				
			
			@ -5,15 +5,18 @@ notifications:
 | 
			
		|||
 | 
			
		||||
env: MAX_CONCURRENCY=4
 | 
			
		||||
 | 
			
		||||
# Run slow PyPy* first, to give them a headstart and reduce waiting time.
 | 
			
		||||
# Run latest 3.x and 2.x next, to get quick compatibility results.
 | 
			
		||||
# Then run the remainder.
 | 
			
		||||
python:
 | 
			
		||||
  - "pypy"
 | 
			
		||||
  - "pypy3"
 | 
			
		||||
  - 2.6
 | 
			
		||||
  - 3.4
 | 
			
		||||
  - 2.7
 | 
			
		||||
  - 2.6
 | 
			
		||||
  - "2.7_with_system_site_packages" # For PyQt4
 | 
			
		||||
  - 3.2
 | 
			
		||||
  - 3.3
 | 
			
		||||
  - 3.4
 | 
			
		||||
 | 
			
		||||
install:
 | 
			
		||||
  - "travis_retry sudo apt-get -qq install libfreetype6-dev liblcms2-dev python-qt4 ghostscript libffi-dev libjpeg-turbo-progs cmake imagemagick"
 | 
			
		||||
| 
						 | 
				
			
			@ -57,6 +60,7 @@ after_success:
 | 
			
		|||
  - travis_retry pip install pep8 pyflakes
 | 
			
		||||
  - pep8 --statistics --count PIL/*.py
 | 
			
		||||
  - pep8  --statistics --count Tests/*.py
 | 
			
		||||
  - pyflakes *.py       | tee >(wc -l)
 | 
			
		||||
  - pyflakes PIL/*.py   | tee >(wc -l)
 | 
			
		||||
  - pyflakes Tests/*.py | tee >(wc -l)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										31
									
								
								CHANGES.rst
									
									
									
									
									
								
							
							
						
						| 
						 | 
				
			
			@ -4,13 +4,40 @@ Changelog (Pillow)
 | 
			
		|||
2.6.0 (unreleased)
 | 
			
		||||
------------------
 | 
			
		||||
 | 
			
		||||
- Jpeg2k Decode/Encode Memory Leak Fix #898
 | 
			
		||||
- Use redistributable image for testing #884
 | 
			
		||||
  [hugovk]
 | 
			
		||||
 | 
			
		||||
- Use redistributable ICC profiles for testing, skip if not available #923
 | 
			
		||||
  [wiredfool]
 | 
			
		||||
  
 | 
			
		||||
- Additional documentation for JPEG info and save options #890
 | 
			
		||||
  [wiredfool]
 | 
			
		||||
 | 
			
		||||
- Fix JPEG Encoding memory leak when exif or qtables were specified
 | 
			
		||||
  [wiredfool]
 | 
			
		||||
  
 | 
			
		||||
- Image.tobytes() and Image.tostring() documentation update #916 #917
 | 
			
		||||
  [mgedmin]
 | 
			
		||||
 | 
			
		||||
- On Windows, do not execute convert.exe without specifying path #912
 | 
			
		||||
  [cgohlke]
 | 
			
		||||
 | 
			
		||||
- Fix msvc build error #911
 | 
			
		||||
  [cgohlke]
 | 
			
		||||
 | 
			
		||||
- Fix for handling P + transparency -> RGBA conversions #904
 | 
			
		||||
  [wiredfool]
 | 
			
		||||
 | 
			
		||||
- Retain alpha in ImageEnhance operations #909
 | 
			
		||||
  [wiredfool]
 | 
			
		||||
 | 
			
		||||
- Jpeg2k Decode/encode memory leak fix #898
 | 
			
		||||
  [joshware, wiredfool]
 | 
			
		||||
 | 
			
		||||
- EpsFilePlugin Speed improvements #886
 | 
			
		||||
  [wiredfool, karstenw]
 | 
			
		||||
 | 
			
		||||
- Don't resize if already the right size.
 | 
			
		||||
- Don't resize if already the right size #892
 | 
			
		||||
  [radarhere]
 | 
			
		||||
 | 
			
		||||
- Fix for reading multipage TIFFs #885
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,7 +7,7 @@ Send a pull request. We'll generally want documentation and [tests](Tests/README
 | 
			
		|||
- Fork the repo
 | 
			
		||||
- Make a branch
 | 
			
		||||
- Add your changes + Tests
 | 
			
		||||
- Run the test suite. Try to run on both Python 2.x and 3.x, or you'll get tripped up. You can enable [Travis CI on your repo](https://travis-ci.org/profile/) to catch test failures prior to the pull request. 
 | 
			
		||||
- Run the test suite. Try to run on both Python 2.x and 3.x, or you'll get tripped up. You can enable [Travis CI on your repo](https://travis-ci.org/profile/) to catch test failures prior to the pull request, and [Coveralls](https://coveralls.io/repos/new) to see if the changed code is covered by tests.
 | 
			
		||||
- Push to your fork, and make a pull request. 
 | 
			
		||||
 | 
			
		||||
A few guidelines:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,8 +40,8 @@ bdf_spacing = {
 | 
			
		|||
    "C": "Cell"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
def bdf_char(f):
 | 
			
		||||
 | 
			
		||||
def bdf_char(f):
 | 
			
		||||
    # skip to STARTCHAR
 | 
			
		||||
    while True:
 | 
			
		||||
        s = f.readline()
 | 
			
		||||
| 
						 | 
				
			
			@ -82,6 +82,7 @@ def bdf_char(f):
 | 
			
		|||
 | 
			
		||||
    return id, int(props["ENCODING"]), bbox, im
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Font file plugin for the X11 BDF format.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -113,10 +114,10 @@ class BdfFontFile(FontFile.FontFile):
 | 
			
		|||
        font[4] = bdf_slant[font[4].upper()]
 | 
			
		||||
        font[11] = bdf_spacing[font[11].upper()]
 | 
			
		||||
 | 
			
		||||
        ascent = int(props["FONT_ASCENT"])
 | 
			
		||||
        descent = int(props["FONT_DESCENT"])
 | 
			
		||||
        # ascent = int(props["FONT_ASCENT"])
 | 
			
		||||
        # descent = int(props["FONT_DESCENT"])
 | 
			
		||||
 | 
			
		||||
        fontname = ";".join(font[1:])
 | 
			
		||||
        # fontname = ";".join(font[1:])
 | 
			
		||||
 | 
			
		||||
        # print "#", fontname
 | 
			
		||||
        # for i in comments:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -51,9 +51,11 @@ BIT2MODE = {
 | 
			
		|||
    32: ("RGB", "BGRX")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _accept(prefix):
 | 
			
		||||
    return prefix[:2] == b"BM"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Image plugin for the Windows BMP format.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -63,7 +65,6 @@ class BmpImageFile(ImageFile.ImageFile):
 | 
			
		|||
    format_description = "Windows Bitmap"
 | 
			
		||||
 | 
			
		||||
    def _bitmap(self, header=0, offset=0):
 | 
			
		||||
 | 
			
		||||
        if header:
 | 
			
		||||
            self.fp.seek(header)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -98,7 +99,8 @@ class BmpImageFile(ImageFile.ImageFile):
 | 
			
		|||
                self.size = self.size[0], 2**32 - self.size[1]
 | 
			
		||||
                direction = 0
 | 
			
		||||
 | 
			
		||||
            self.info["dpi"] = tuple(map(lambda x: math.ceil(x / 39.3701), pxperm))
 | 
			
		||||
            self.info["dpi"] = tuple(map(lambda x: math.ceil(x / 39.3701),
 | 
			
		||||
                                         pxperm))
 | 
			
		||||
 | 
			
		||||
        else:
 | 
			
		||||
            raise IOError("Unsupported BMP header type (%d)" % len(s))
 | 
			
		||||
| 
						 | 
				
			
			@ -163,7 +165,8 @@ class BmpImageFile(ImageFile.ImageFile):
 | 
			
		|||
        self.tile = [("raw",
 | 
			
		||||
                     (0, 0) + self.size,
 | 
			
		||||
                     offset,
 | 
			
		||||
                     (rawmode, ((self.size[0]*bits+31)>>3)&(~3), direction))]
 | 
			
		||||
                     (rawmode, ((self.size[0]*bits+31) >> 3) & (~3),
 | 
			
		||||
                      direction))]
 | 
			
		||||
 | 
			
		||||
        self.info["compression"] = compression
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -197,8 +200,8 @@ SAVE = {
 | 
			
		|||
    "RGB": ("BGR", 24, 0),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
def _save(im, fp, filename, check=0):
 | 
			
		||||
 | 
			
		||||
def _save(im, fp, filename, check=0):
 | 
			
		||||
    try:
 | 
			
		||||
        rawmode, bits, colors = SAVE[im.mode]
 | 
			
		||||
    except KeyError:
 | 
			
		||||
| 
						 | 
				
			
			@ -248,7 +251,8 @@ def _save(im, fp, filename, check=0):
 | 
			
		|||
    elif im.mode == "P":
 | 
			
		||||
        fp.write(im.im.getpalette("RGB", "BGRX"))
 | 
			
		||||
 | 
			
		||||
    ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, stride, -1))])
 | 
			
		||||
    ImageFile._save(im, fp, [("raw", (0, 0)+im.size, 0,
 | 
			
		||||
                    (rawmode, stride, -1))])
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# --------------------------------------------------------------------
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,6 +13,7 @@ from PIL import Image, ImageFile
 | 
			
		|||
 | 
			
		||||
_handler = None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Install application-specific BUFR image handler.
 | 
			
		||||
#
 | 
			
		||||
| 
						 | 
				
			
			@ -22,12 +23,14 @@ def register_handler(handler):
 | 
			
		|||
    global _handler
 | 
			
		||||
    _handler = handler
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# --------------------------------------------------------------------
 | 
			
		||||
# Image adapter
 | 
			
		||||
 | 
			
		||||
def _accept(prefix):
 | 
			
		||||
    return prefix[:4] == b"BUFR" or prefix[:4] == b"ZCZC"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BufrStubImageFile(ImageFile.StubImageFile):
 | 
			
		||||
 | 
			
		||||
    format = "BUFR"
 | 
			
		||||
| 
						 | 
				
			
			@ -53,6 +56,7 @@ class BufrStubImageFile(ImageFile.StubImageFile):
 | 
			
		|||
    def _load(self):
 | 
			
		||||
        return _handler
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _save(im, fp, filename):
 | 
			
		||||
    if _handler is None or not hasattr("_handler", "save"):
 | 
			
		||||
        raise IOError("BUFR save handler not installed")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,6 +18,7 @@
 | 
			
		|||
# A file object that provides read access to a part of an existing
 | 
			
		||||
# file (for example a TAR file).
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ContainerIO:
 | 
			
		||||
 | 
			
		||||
    ##
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,7 +11,8 @@
 | 
			
		|||
# 1996-08-23 fl   Handle files from Macintosh (0.3)
 | 
			
		||||
# 2001-02-17 fl   Use 're' instead of 'regex' (Python 2.1) (0.4)
 | 
			
		||||
# 2003-09-07 fl   Check gs.close status (from Federico Di Gregorio) (0.5)
 | 
			
		||||
# 2014-05-07 e    Handling of EPS with binary preview and fixed resolution resizing
 | 
			
		||||
# 2014-05-07 e    Handling of EPS with binary preview and fixed resolution
 | 
			
		||||
#                 resizing
 | 
			
		||||
#
 | 
			
		||||
# Copyright (c) 1997-2003 by Secret Labs AB.
 | 
			
		||||
# Copyright (c) 1995-2003 by Fredrik Lundh
 | 
			
		||||
| 
						 | 
				
			
			@ -51,6 +52,7 @@ if sys.platform.startswith('win'):
 | 
			
		|||
    else:
 | 
			
		||||
        gs_windows_binary = False
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def has_ghostscript():
 | 
			
		||||
    if gs_windows_binary:
 | 
			
		||||
        return True
 | 
			
		||||
| 
						 | 
				
			
			@ -75,14 +77,17 @@ def Ghostscript(tile, size, fp, scale=1):
 | 
			
		|||
 | 
			
		||||
    # Hack to support hi-res rendering
 | 
			
		||||
    scale = int(scale) or 1
 | 
			
		||||
    orig_size = size
 | 
			
		||||
    orig_bbox = bbox
 | 
			
		||||
    # orig_size = size
 | 
			
		||||
    # orig_bbox = bbox
 | 
			
		||||
    size = (size[0] * scale, size[1] * scale)
 | 
			
		||||
    # resolution is dependend on bbox and size
 | 
			
		||||
    res = ( float((72.0 * size[0]) / (bbox[2]-bbox[0])), float((72.0 * size[1]) / (bbox[3]-bbox[1])) )
 | 
			
		||||
    # resolution is dependent on bbox and size
 | 
			
		||||
    res = (float((72.0 * size[0]) / (bbox[2]-bbox[0])),
 | 
			
		||||
           float((72.0 * size[1]) / (bbox[3]-bbox[1])))
 | 
			
		||||
    # print("Ghostscript", scale, size, orig_size, bbox, orig_bbox, res)
 | 
			
		||||
 | 
			
		||||
    import tempfile, os, subprocess
 | 
			
		||||
    import os
 | 
			
		||||
    import subprocess
 | 
			
		||||
    import tempfile
 | 
			
		||||
 | 
			
		||||
    out_fd, outfile = tempfile.mkstemp()
 | 
			
		||||
    os.close(out_fd)
 | 
			
		||||
| 
						 | 
				
			
			@ -118,7 +123,8 @@ def Ghostscript(tile, size, fp, scale=1):
 | 
			
		|||
               "-q",                         # quiet mode
 | 
			
		||||
               "-g%dx%d" % size,             # set output geometry (pixels)
 | 
			
		||||
               "-r%fx%f" % res,              # set input DPI (dots per inch)
 | 
			
		||||
               "-dNOPAUSE -dSAFER",         # don't pause between pages, safe mode
 | 
			
		||||
               "-dNOPAUSE -dSAFER",          # don't pause between pages,
 | 
			
		||||
                                             # safe mode
 | 
			
		||||
               "-sDEVICE=ppmraw",            # ppm driver
 | 
			
		||||
               "-sOutputFile=%s" % outfile,  # output file
 | 
			
		||||
               "-c", "%d %d translate" % (-bbox[0], -bbox[1]),
 | 
			
		||||
| 
						 | 
				
			
			@ -133,7 +139,8 @@ def Ghostscript(tile, size, fp, scale=1):
 | 
			
		|||
 | 
			
		||||
    # push data through ghostscript
 | 
			
		||||
    try:
 | 
			
		||||
        gs = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
 | 
			
		||||
        gs = subprocess.Popen(command, stdin=subprocess.PIPE,
 | 
			
		||||
                              stdout=subprocess.PIPE)
 | 
			
		||||
        gs.stdin.close()
 | 
			
		||||
        status = gs.wait()
 | 
			
		||||
        if status:
 | 
			
		||||
| 
						 | 
				
			
			@ -142,21 +149,26 @@ def Ghostscript(tile, size, fp, scale=1):
 | 
			
		|||
    finally:
 | 
			
		||||
        try:
 | 
			
		||||
            os.unlink(outfile)
 | 
			
		||||
            if infile_temo:
 | 
			
		||||
            if infile_temp:
 | 
			
		||||
                os.unlink(infile_temp)
 | 
			
		||||
        except: pass
 | 
			
		||||
        except:
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
    return im
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PSFile:
 | 
			
		||||
    """Wrapper for bytesio object that treats either CR or LF as end of line."""
 | 
			
		||||
    """
 | 
			
		||||
    Wrapper for bytesio object that treats either CR or LF as end of line.
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, fp):
 | 
			
		||||
        self.fp = fp
 | 
			
		||||
        self.char = None
 | 
			
		||||
 | 
			
		||||
    def seek(self, offset, whence=0):
 | 
			
		||||
        self.char = None
 | 
			
		||||
        self.fp.seek(offset, whence)
 | 
			
		||||
 | 
			
		||||
    def readline(self):
 | 
			
		||||
        s = self.char or b""
 | 
			
		||||
        self.char = None
 | 
			
		||||
| 
						 | 
				
			
			@ -173,6 +185,7 @@ class PSFile:
 | 
			
		|||
 | 
			
		||||
        return s.decode('latin-1')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _accept(prefix):
 | 
			
		||||
    return prefix[:4] == b"%!PS" or i32(prefix) == 0xC6D3D0C5
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -180,6 +193,7 @@ def _accept(prefix):
 | 
			
		|||
# Image plugin for Encapsulated Postscript.  This plugin supports only
 | 
			
		||||
# a few variants of this format.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EpsImageFile(ImageFile.ImageFile):
 | 
			
		||||
    """EPS File Parser for the Python Imaging Library"""
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -200,7 +214,7 @@ class EpsImageFile(ImageFile.ImageFile):
 | 
			
		|||
            else:
 | 
			
		||||
                # Python3, can use bare open command.
 | 
			
		||||
                fp = open(self.fp.name, "Ur", encoding='latin-1')
 | 
			
		||||
        except Exception as msg:
 | 
			
		||||
        except:
 | 
			
		||||
            # Expect this for bytesio/stringio
 | 
			
		||||
            fp = PSFile(self.fp)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -264,7 +278,6 @@ class EpsImageFile(ImageFile.ImageFile):
 | 
			
		|||
            if s[0] != "%":
 | 
			
		||||
                break
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        #
 | 
			
		||||
        # Scan for an "ImageData" descriptor
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -307,7 +320,8 @@ class EpsImageFile(ImageFile.ImageFile):
 | 
			
		|||
            # FIX for: Some EPS file not handled correctly / issue #302
 | 
			
		||||
            # EPS can contain binary data
 | 
			
		||||
            # or start directly with latin coding
 | 
			
		||||
            # more info see http://partners.adobe.com/public/developer/en/ps/5002.EPSF_Spec.pdf
 | 
			
		||||
            # more info see:
 | 
			
		||||
            # http://partners.adobe.com/public/developer/en/ps/5002.EPSF_Spec.pdf
 | 
			
		||||
            offset = i32(s[4:8])
 | 
			
		||||
            length = i32(s[8:12])
 | 
			
		||||
        else:
 | 
			
		||||
| 
						 | 
				
			
			@ -329,6 +343,7 @@ class EpsImageFile(ImageFile.ImageFile):
 | 
			
		|||
        # use our custom load method by defining this method.
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# --------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -353,8 +368,10 @@ def _save(im, fp, filename, eps=1):
 | 
			
		|||
    class NoCloseStream:
 | 
			
		||||
        def __init__(self, fp):
 | 
			
		||||
            self.fp = fp
 | 
			
		||||
 | 
			
		||||
        def __getattr__(self, name):
 | 
			
		||||
            return getattr(self.fp, name)
 | 
			
		||||
 | 
			
		||||
        def close(self):
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,12 +25,14 @@ i16 = _binary.i16le
 | 
			
		|||
i32 = _binary.i32le
 | 
			
		||||
o8 = _binary.o8
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# decoder
 | 
			
		||||
 | 
			
		||||
def _accept(prefix):
 | 
			
		||||
    return i16(prefix[4:6]) in [0xAF11, 0xAF12]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Image plugin for the FLI/FLC animation format.  Use the <b>seek</b>
 | 
			
		||||
# method to load individual frames.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,12 +38,14 @@ MODES = {
 | 
			
		|||
    (0x00038000, 0x00038001, 0x00038002, 0x00037ffe): ("RGBA", "RGBA"),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# --------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
def _accept(prefix):
 | 
			
		||||
    return prefix[:8] == MAGIC
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Image plugin for the FlashPix images.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -212,7 +214,8 @@ class FpxImageFile(ImageFile.ImageFile):
 | 
			
		|||
    def load(self):
 | 
			
		||||
 | 
			
		||||
        if not self.fp:
 | 
			
		||||
            self.fp = self.ole.openstream(self.stream[:2] + ["Subimage 0000 Data"])
 | 
			
		||||
            self.fp = self.ole.openstream(self.stream[:2] +
 | 
			
		||||
                                          ["Subimage 0000 Data"])
 | 
			
		||||
 | 
			
		||||
        ImageFile.ImageFile.load(self)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,9 +17,11 @@ from PIL import Image, ImageFile, _binary
 | 
			
		|||
 | 
			
		||||
i32 = _binary.i32be
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _accept(prefix):
 | 
			
		||||
    return i32(prefix) >= 20 and i32(prefix[4:8]) == 1
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Image plugin for the GIMP brush format.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -36,6 +36,7 @@ except ImportError:
 | 
			
		|||
 | 
			
		||||
i16 = _binary.i16be
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Image plugin for the GD uncompressed format.  Note that this format
 | 
			
		||||
# is not supported by the standard <b>Image.open</b> function.  To use
 | 
			
		||||
| 
						 | 
				
			
			@ -64,6 +65,7 @@ class GdImageFile(ImageFile.ImageFile):
 | 
			
		|||
 | 
			
		||||
        self.tile = [("raw", (0, 0)+self.size, 775, ("L", 0, -1))]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Load texture from a GD image file.
 | 
			
		||||
#
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -46,6 +46,7 @@ o16 = _binary.o16le
 | 
			
		|||
def _accept(prefix):
 | 
			
		||||
    return prefix[:6] in [b"GIF87a", b"GIF89a"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Image plugin for GIF images.  This plugin supports both GIF87 and
 | 
			
		||||
# GIF89 images.
 | 
			
		||||
| 
						 | 
				
			
			@ -219,7 +220,6 @@ class GifImageFile(ImageFile.ImageFile):
 | 
			
		|||
        except (AttributeError, KeyError):
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        if not self.tile:
 | 
			
		||||
            # self.__fp = None
 | 
			
		||||
            raise EOFError("no more images in GIF file")
 | 
			
		||||
| 
						 | 
				
			
			@ -240,7 +240,8 @@ class GifImageFile(ImageFile.ImageFile):
 | 
			
		|||
            # we do this by pasting the updated area onto the previous
 | 
			
		||||
            # frame which we then use as the current image content
 | 
			
		||||
            updated = self.im.crop(self.dispose_extent)
 | 
			
		||||
            self._prev_im.paste(updated, self.dispose_extent, updated.convert('RGBA'))
 | 
			
		||||
            self._prev_im.paste(updated, self.dispose_extent,
 | 
			
		||||
                                updated.convert('RGBA'))
 | 
			
		||||
            self.im = self._prev_im
 | 
			
		||||
        self._prev_im = self.im.copy()
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -258,6 +259,7 @@ RAWMODE = {
 | 
			
		|||
    "P": "P",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _save(im, fp, filename):
 | 
			
		||||
 | 
			
		||||
    if _imaging_gif:
 | 
			
		||||
| 
						 | 
				
			
			@ -343,7 +345,8 @@ def _save(im, fp, filename):
 | 
			
		|||
             o8(8))                     # bits
 | 
			
		||||
 | 
			
		||||
    imOut.encoderconfig = (8, interlace)
 | 
			
		||||
    ImageFile._save(imOut, fp, [("gif", (0,0)+im.size, 0, RAWMODE[imOut.mode])])
 | 
			
		||||
    ImageFile._save(imOut, fp, [("gif", (0, 0)+im.size, 0,
 | 
			
		||||
                                RAWMODE[imOut.mode])])
 | 
			
		||||
 | 
			
		||||
    fp.write(b"\0")  # end of image data
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -351,7 +354,8 @@ def _save(im, fp, filename):
 | 
			
		|||
 | 
			
		||||
    try:
 | 
			
		||||
        fp.flush()
 | 
			
		||||
    except: pass
 | 
			
		||||
    except:
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _save_netpbm(im, fp, filename):
 | 
			
		||||
| 
						 | 
				
			
			@ -380,7 +384,8 @@ def _save_netpbm(im, fp, filename):
 | 
			
		|||
            stderr = tempfile.TemporaryFile()
 | 
			
		||||
            quant_proc = Popen(quant_cmd, stdout=PIPE, stderr=stderr)
 | 
			
		||||
            stderr = tempfile.TemporaryFile()
 | 
			
		||||
            togif_proc = Popen(togif_cmd, stdin=quant_proc.stdout, stdout=f, stderr=stderr)
 | 
			
		||||
            togif_proc = Popen(togif_cmd, stdin=quant_proc.stdout, stdout=f,
 | 
			
		||||
                               stderr=stderr)
 | 
			
		||||
 | 
			
		||||
            # Allow ppmquant to receive SIGPIPE if ppmtogif exits
 | 
			
		||||
            quant_proc.stdout.close()
 | 
			
		||||
| 
						 | 
				
			
			@ -455,9 +460,11 @@ def getheader(im, palette=None, info=None):
 | 
			
		|||
            for i in range(len(imageBytes)):
 | 
			
		||||
                imageBytes[i] = newPositions[imageBytes[i]]
 | 
			
		||||
            im.frombytes(bytes(imageBytes))
 | 
			
		||||
            newPaletteBytes = paletteBytes + (768 - len(paletteBytes)) * b'\x00'
 | 
			
		||||
            newPaletteBytes = (paletteBytes +
 | 
			
		||||
                               (768 - len(paletteBytes)) * b'\x00')
 | 
			
		||||
            im.putpalette(newPaletteBytes)
 | 
			
		||||
            im.palette = ImagePalette.ImagePalette("RGB", palette = paletteBytes, size = len(paletteBytes))
 | 
			
		||||
            im.palette = ImagePalette.ImagePalette("RGB", palette=paletteBytes,
 | 
			
		||||
                                                   size=len(paletteBytes))
 | 
			
		||||
 | 
			
		||||
    if not paletteBytes:
 | 
			
		||||
        paletteBytes = sourcePalette
 | 
			
		||||
| 
						 | 
				
			
			@ -466,7 +473,8 @@ def getheader(im, palette=None, info=None):
 | 
			
		|||
    # calculate the palette size for the header
 | 
			
		||||
    import math
 | 
			
		||||
    colorTableSize = int(math.ceil(math.log(len(paletteBytes)//3, 2)))-1
 | 
			
		||||
    if colorTableSize < 0: colorTableSize = 0
 | 
			
		||||
    if colorTableSize < 0:
 | 
			
		||||
        colorTableSize = 0
 | 
			
		||||
    # size of global color table + global color table flag
 | 
			
		||||
    header.append(o8(colorTableSize + 128))
 | 
			
		||||
    # background + reserved/aspect
 | 
			
		||||
| 
						 | 
				
			
			@ -491,6 +499,7 @@ def getdata(im, offset = (0, 0), **params):
 | 
			
		|||
 | 
			
		||||
    class collector:
 | 
			
		||||
        data = []
 | 
			
		||||
 | 
			
		||||
        def write(self, data):
 | 
			
		||||
            self.data.append(data)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,6 +17,7 @@
 | 
			
		|||
import re
 | 
			
		||||
from PIL._binary import o8
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# File handler for GIMP's palette format.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -56,7 +57,6 @@ class GimpPaletteFile:
 | 
			
		|||
 | 
			
		||||
        self.palette = b"".join(self.palette)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def getpalette(self):
 | 
			
		||||
 | 
			
		||||
        return self.palette, self.rawmode
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,6 +13,7 @@ from PIL import Image, ImageFile
 | 
			
		|||
 | 
			
		||||
_handler = None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Install application-specific GRIB image handler.
 | 
			
		||||
#
 | 
			
		||||
| 
						 | 
				
			
			@ -22,12 +23,14 @@ def register_handler(handler):
 | 
			
		|||
    global _handler
 | 
			
		||||
    _handler = handler
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# --------------------------------------------------------------------
 | 
			
		||||
# Image adapter
 | 
			
		||||
 | 
			
		||||
def _accept(prefix):
 | 
			
		||||
    return prefix[0:4] == b"GRIB" and prefix[7] == b'\x01'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class GribStubImageFile(ImageFile.StubImageFile):
 | 
			
		||||
 | 
			
		||||
    format = "GRIB"
 | 
			
		||||
| 
						 | 
				
			
			@ -53,6 +56,7 @@ class GribStubImageFile(ImageFile.StubImageFile):
 | 
			
		|||
    def _load(self):
 | 
			
		||||
        return _handler
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _save(im, fp, filename):
 | 
			
		||||
    if _handler is None or not hasattr("_handler", "save"):
 | 
			
		||||
        raise IOError("GRIB save handler not installed")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,6 +13,7 @@ from PIL import Image, ImageFile
 | 
			
		|||
 | 
			
		||||
_handler = None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Install application-specific HDF5 image handler.
 | 
			
		||||
#
 | 
			
		||||
| 
						 | 
				
			
			@ -22,12 +23,14 @@ def register_handler(handler):
 | 
			
		|||
    global _handler
 | 
			
		||||
    _handler = handler
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# --------------------------------------------------------------------
 | 
			
		||||
# Image adapter
 | 
			
		||||
 | 
			
		||||
def _accept(prefix):
 | 
			
		||||
    return prefix[:8] == b"\x89HDF\r\n\x1a\n"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class HDF5StubImageFile(ImageFile.StubImageFile):
 | 
			
		||||
 | 
			
		||||
    format = "HDF5"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,8 @@
 | 
			
		|||
#
 | 
			
		||||
 | 
			
		||||
from PIL import Image, ImageFile, PngImagePlugin, _binary
 | 
			
		||||
import struct, io
 | 
			
		||||
import io
 | 
			
		||||
import struct
 | 
			
		||||
 | 
			
		||||
enable_jpeg2k = hasattr(Image.core, 'jp2klib_version')
 | 
			
		||||
if enable_jpeg2k:
 | 
			
		||||
| 
						 | 
				
			
			@ -26,9 +27,11 @@ i8 = _binary.i8
 | 
			
		|||
 | 
			
		||||
HEADERSIZE = 8
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def nextheader(fobj):
 | 
			
		||||
    return struct.unpack('>4sI', fobj.read(HEADERSIZE))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def read_32t(fobj, start_length, size):
 | 
			
		||||
    # The 128x128 icon seems to have an extra header for some reason.
 | 
			
		||||
    (start, length) = start_length
 | 
			
		||||
| 
						 | 
				
			
			@ -38,6 +41,7 @@ def read_32t(fobj, start_length, size):
 | 
			
		|||
        raise SyntaxError('Unknown signature, expecting 0x00000000')
 | 
			
		||||
    return read_32(fobj, (start + 4, length - 4), size)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def read_32(fobj, start_length, size):
 | 
			
		||||
    """
 | 
			
		||||
    Read a 32bit RGB icon resource.  Seems to be either uncompressed or
 | 
			
		||||
| 
						 | 
				
			
			@ -83,6 +87,7 @@ def read_32(fobj, start_length, size):
 | 
			
		|||
            im.im.putband(band.im, band_ix)
 | 
			
		||||
    return {"RGB": im}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def read_mk(fobj, start_length, size):
 | 
			
		||||
    # Alpha masks seem to be uncompressed
 | 
			
		||||
    (start, length) = start_length
 | 
			
		||||
| 
						 | 
				
			
			@ -94,6 +99,7 @@ def read_mk(fobj, start_length, size):
 | 
			
		|||
        )
 | 
			
		||||
    return {"A": band}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def read_png_or_jpeg2000(fobj, start_length, size):
 | 
			
		||||
    (start, length) = start_length
 | 
			
		||||
    fobj.seek(start)
 | 
			
		||||
| 
						 | 
				
			
			@ -106,7 +112,8 @@ def read_png_or_jpeg2000(fobj, start_length, size):
 | 
			
		|||
            or sig[:4] == b'\x0d\x0a\x87\x0a' \
 | 
			
		||||
            or sig == b'\x00\x00\x00\x0cjP  \x0d\x0a\x87\x0a':
 | 
			
		||||
        if not enable_jpeg2k:
 | 
			
		||||
            raise ValueError('Unsupported icon subimage format (rebuild PIL with JPEG 2000 support to fix this)')
 | 
			
		||||
            raise ValueError('Unsupported icon subimage format (rebuild PIL '
 | 
			
		||||
                             'with JPEG 2000 support to fix this)')
 | 
			
		||||
        # j2k, jpc or j2c
 | 
			
		||||
        fobj.seek(start)
 | 
			
		||||
        jp2kstream = fobj.read(length)
 | 
			
		||||
| 
						 | 
				
			
			@ -118,6 +125,7 @@ def read_png_or_jpeg2000(fobj, start_length, size):
 | 
			
		|||
    else:
 | 
			
		||||
        raise ValueError('Unsupported icon subimage format')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class IcnsFile:
 | 
			
		||||
 | 
			
		||||
    SIZES = {
 | 
			
		||||
| 
						 | 
				
			
			@ -233,6 +241,7 @@ class IcnsFile:
 | 
			
		|||
            pass
 | 
			
		||||
        return im
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Image plugin for Mac OS icons.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -288,7 +297,8 @@ Image.register_open("ICNS", IcnsImageFile, lambda x: x[:4] == b'icns')
 | 
			
		|||
Image.register_extension("ICNS", '.icns')
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    import os, sys
 | 
			
		||||
    import os
 | 
			
		||||
    import sys
 | 
			
		||||
    imf = IcnsImageFile(open(sys.argv[1], 'rb'))
 | 
			
		||||
    for size in imf.info['sizes']:
 | 
			
		||||
        imf.size = size
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,7 +13,8 @@
 | 
			
		|||
# See the README file for information on usage and redistribution.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
# This plugin is a refactored version of Win32IconImagePlugin by Bryan Davis <casadebender@gmail.com>.
 | 
			
		||||
# This plugin is a refactored version of Win32IconImagePlugin by Bryan Davis
 | 
			
		||||
# <casadebender@gmail.com>.
 | 
			
		||||
# https://code.google.com/p/casadebender/wiki/Win32IconImagePlugin
 | 
			
		||||
#
 | 
			
		||||
# Icon format references:
 | 
			
		||||
| 
						 | 
				
			
			@ -35,6 +36,7 @@ i32 = _binary.i32le
 | 
			
		|||
 | 
			
		||||
_MAGIC = b"\0\0\1\0"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _accept(prefix):
 | 
			
		||||
    return prefix[:4] == _MAGIC
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -63,7 +65,7 @@ class IcoFile:
 | 
			
		|||
            icon_header = {
 | 
			
		||||
                'width': i8(s[0]),
 | 
			
		||||
                'height': i8(s[1]),
 | 
			
		||||
                'nb_color': i8(s[2]), # Number of colors in image (0 if >=8bpp)
 | 
			
		||||
                'nb_color': i8(s[2]),  # No. of colors in image (0 if >=8bpp)
 | 
			
		||||
                'reserved': i8(s[3]),
 | 
			
		||||
                'planes': i16(s[4:]),
 | 
			
		||||
                'bpp': i16(s[6:]),
 | 
			
		||||
| 
						 | 
				
			
			@ -78,10 +80,14 @@ class IcoFile:
 | 
			
		|||
 | 
			
		||||
            # See Wikipedia notes about color depth.
 | 
			
		||||
            # We need this just to differ images with equal sizes
 | 
			
		||||
            icon_header['color_depth'] = (icon_header['bpp'] or (icon_header['nb_color'] != 0 and ceil(log(icon_header['nb_color'],2))) or 256)
 | 
			
		||||
            icon_header['color_depth'] = (icon_header['bpp'] or
 | 
			
		||||
                                          (icon_header['nb_color'] != 0 and
 | 
			
		||||
                                           ceil(log(icon_header['nb_color'],
 | 
			
		||||
                                                    2))) or 256)
 | 
			
		||||
 | 
			
		||||
            icon_header['dim'] = (icon_header['width'], icon_header['height'])
 | 
			
		||||
            icon_header['square'] = icon_header['width'] * icon_header['height']
 | 
			
		||||
            icon_header['square'] = (icon_header['width'] *
 | 
			
		||||
                                     icon_header['height'])
 | 
			
		||||
 | 
			
		||||
            self.entry.append(icon_header)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -102,7 +108,7 @@ class IcoFile:
 | 
			
		|||
        Get an image from the icon
 | 
			
		||||
        """
 | 
			
		||||
        for (i, h) in enumerate(self.entry):
 | 
			
		||||
            if size == h['dim'] and (bpp == False or bpp == h['color_depth']):
 | 
			
		||||
            if size == h['dim'] and (bpp is False or bpp == h['color_depth']):
 | 
			
		||||
                return self.frame(i)
 | 
			
		||||
        return self.frame(0)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -139,8 +145,9 @@ class IcoFile:
 | 
			
		|||
 | 
			
		||||
            if 32 == bpp:
 | 
			
		||||
                # 32-bit color depth icon image allows semitransparent areas
 | 
			
		||||
                # PIL's DIB format ignores transparency bits, recover them
 | 
			
		||||
                # The DIB is packed in BGRX byte order where X is the alpha channel
 | 
			
		||||
                # PIL's DIB format ignores transparency bits, recover them.
 | 
			
		||||
                # The DIB is packed in BGRX byte order where X is the alpha
 | 
			
		||||
                # channel.
 | 
			
		||||
 | 
			
		||||
                # Back up to start of bmp data
 | 
			
		||||
                self.buf.seek(o)
 | 
			
		||||
| 
						 | 
				
			
			@ -162,9 +169,11 @@ class IcoFile:
 | 
			
		|||
                    # bitmap row data is aligned to word boundaries
 | 
			
		||||
                    w += 32 - (im.size[0] % 32)
 | 
			
		||||
 | 
			
		||||
                # the total mask data is padded row size * height / bits per char
 | 
			
		||||
                # the total mask data is
 | 
			
		||||
                # padded row size * height / bits per char
 | 
			
		||||
 | 
			
		||||
                and_mask_offset = o + int(im.size[0] * im.size[1] * (bpp / 8.0))
 | 
			
		||||
                and_mask_offset = o + int(im.size[0] * im.size[1] *
 | 
			
		||||
                                          (bpp / 8.0))
 | 
			
		||||
                total_bytes = int((w * im.size[1]) / 8)
 | 
			
		||||
 | 
			
		||||
                self.buf.seek(and_mask_offset)
 | 
			
		||||
| 
						 | 
				
			
			@ -187,6 +196,7 @@ class IcoFile:
 | 
			
		|||
 | 
			
		||||
        return im
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Image plugin for Windows Icon files.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -194,15 +204,16 @@ class IcoImageFile(ImageFile.ImageFile):
 | 
			
		|||
    """
 | 
			
		||||
    PIL read-only image support for Microsoft Windows .ico files.
 | 
			
		||||
 | 
			
		||||
    By default the largest resolution image in the file will be loaded. This can
 | 
			
		||||
    be changed by altering the 'size' attribute before calling 'load'.
 | 
			
		||||
    By default the largest resolution image in the file will be loaded. This
 | 
			
		||||
    can be changed by altering the 'size' attribute before calling 'load'.
 | 
			
		||||
 | 
			
		||||
    The info dictionary has a key 'sizes' that is a list of the sizes available
 | 
			
		||||
    in the icon file.
 | 
			
		||||
 | 
			
		||||
    Handles classic, XP and Vista icon formats.
 | 
			
		||||
 | 
			
		||||
    This plugin is a refactored version of Win32IconImagePlugin by Bryan Davis <casadebender@gmail.com>.
 | 
			
		||||
    This plugin is a refactored version of Win32IconImagePlugin by Bryan Davis
 | 
			
		||||
    <casadebender@gmail.com>.
 | 
			
		||||
    https://code.google.com/p/casadebender/wiki/Win32IconImagePlugin
 | 
			
		||||
    """
 | 
			
		||||
    format = "ICO"
 | 
			
		||||
| 
						 | 
				
			
			@ -222,9 +233,9 @@ class IcoImageFile(ImageFile.ImageFile):
 | 
			
		|||
        self.mode = im.mode
 | 
			
		||||
        self.size = im.size
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def load_seek(self):
 | 
			
		||||
        # Flage the ImageFile.Parser so that it just does all the decode at the end.
 | 
			
		||||
        # Flage the ImageFile.Parser so that it
 | 
			
		||||
        # just does all the decode at the end.
 | 
			
		||||
        pass
 | 
			
		||||
#
 | 
			
		||||
# --------------------------------------------------------------------
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,7 +30,7 @@ __version__ = "0.7"
 | 
			
		|||
 | 
			
		||||
import re
 | 
			
		||||
from PIL import Image, ImageFile, ImagePalette
 | 
			
		||||
from PIL._binary import i8, o8
 | 
			
		||||
from PIL._binary import i8
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# --------------------------------------------------------------------
 | 
			
		||||
| 
						 | 
				
			
			@ -94,12 +94,14 @@ for i in range(2, 33):
 | 
			
		|||
 | 
			
		||||
split = re.compile(br"^([A-Za-z][^:]*):[ \t]*(.*)[ \t]*$")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def number(s):
 | 
			
		||||
    try:
 | 
			
		||||
        return int(s)
 | 
			
		||||
    except ValueError:
 | 
			
		||||
        return float(s)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Image plugin for the IFUNC IM file format.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -113,7 +115,7 @@ class ImImageFile(ImageFile.ImageFile):
 | 
			
		|||
        # Quick rejection: if there's not an LF among the first
 | 
			
		||||
        # 100 bytes, this is (probably) not a text header.
 | 
			
		||||
 | 
			
		||||
        if not b"\n" in self.fp.read(100):
 | 
			
		||||
        if b"\n" not in self.fp.read(100):
 | 
			
		||||
            raise SyntaxError("not an IM file")
 | 
			
		||||
        self.fp.seek(0)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -157,8 +159,8 @@ class ImImageFile(ImageFile.ImageFile):
 | 
			
		|||
 | 
			
		||||
                k, v = m.group(1, 2)
 | 
			
		||||
 | 
			
		||||
                # Don't know if this is the correct encoding, but a decent guess
 | 
			
		||||
                # (I guess)
 | 
			
		||||
                # Don't know if this is the correct encoding,
 | 
			
		||||
                # but a decent guess (I guess)
 | 
			
		||||
                k = k.decode('latin-1', 'replace')
 | 
			
		||||
                v = v.decode('latin-1', 'replace')
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -186,7 +188,8 @@ class ImImageFile(ImageFile.ImageFile):
 | 
			
		|||
 | 
			
		||||
            else:
 | 
			
		||||
 | 
			
		||||
                raise SyntaxError("Syntax error in IM header: " + s.decode('ascii', 'replace'))
 | 
			
		||||
                raise SyntaxError("Syntax error in IM header: " +
 | 
			
		||||
                                  s.decode('ascii', 'replace'))
 | 
			
		||||
 | 
			
		||||
        if not n:
 | 
			
		||||
            raise SyntaxError("Not an IM file")
 | 
			
		||||
| 
						 | 
				
			
			@ -254,7 +257,8 @@ class ImImageFile(ImageFile.ImageFile):
 | 
			
		|||
                         ("raw", (0, 0)+self.size, offs+2*size, ("B", 0, -1))]
 | 
			
		||||
        else:
 | 
			
		||||
            # LabEye/IFUNC files
 | 
			
		||||
            self.tile = [("raw", (0,0)+self.size, offs, (self.rawmode, 0, -1))]
 | 
			
		||||
            self.tile = [("raw", (0, 0)+self.size, offs,
 | 
			
		||||
                         (self.rawmode, 0, -1))]
 | 
			
		||||
 | 
			
		||||
    def seek(self, frame):
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -305,6 +309,7 @@ SAVE = {
 | 
			
		|||
    "YCbCr": ("YCC", "YCbCr;L")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _save(im, fp, filename, check=0):
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										22
									
								
								PIL/Image.py
									
									
									
									
									
								
							
							
						
						| 
						 | 
				
			
			@ -34,6 +34,7 @@ import warnings
 | 
			
		|||
class DecompressionBombWarning(RuntimeWarning):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class _imaging_not_installed:
 | 
			
		||||
    # module placeholder
 | 
			
		||||
    def __getattr__(self, id):
 | 
			
		||||
| 
						 | 
				
			
			@ -530,7 +531,7 @@ class Image:
 | 
			
		|||
        """
 | 
			
		||||
        Closes the file pointer, if possible.
 | 
			
		||||
 | 
			
		||||
        This operation will destroy the image core and release it's memory.
 | 
			
		||||
        This operation will destroy the image core and release its memory.
 | 
			
		||||
        The image data will be unusable afterward.
 | 
			
		||||
 | 
			
		||||
        This function is only required to close images that have not
 | 
			
		||||
| 
						 | 
				
			
			@ -664,6 +665,10 @@ class Image:
 | 
			
		|||
 | 
			
		||||
    # Declare tostring as alias to tobytes
 | 
			
		||||
    def tostring(self, *args, **kw):
 | 
			
		||||
        """Deprecated alias to tobytes.
 | 
			
		||||
 | 
			
		||||
        .. deprecated:: 2.0
 | 
			
		||||
        """
 | 
			
		||||
        warnings.warn(
 | 
			
		||||
            'tostring() is deprecated. Please call tobytes() instead.',
 | 
			
		||||
            DeprecationWarning,
 | 
			
		||||
| 
						 | 
				
			
			@ -847,8 +852,9 @@ class Image:
 | 
			
		|||
                t = self.info['transparency']
 | 
			
		||||
                if isinstance(t, bytes):
 | 
			
		||||
                    # Dragons. This can't be represented by a single color
 | 
			
		||||
                    warnings.warn('Palette images with Transparency expressed ' +
 | 
			
		||||
                                  ' in bytes should be converted to RGBA images')
 | 
			
		||||
                    warnings.warn('Palette images with Transparency  ' +
 | 
			
		||||
                                  ' expressed in bytes should be converted ' +
 | 
			
		||||
                                  'to RGBA images')
 | 
			
		||||
                    delete_trns = True
 | 
			
		||||
                else:
 | 
			
		||||
                    # get the new transparency color.
 | 
			
		||||
| 
						 | 
				
			
			@ -867,8 +873,18 @@ class Image:
 | 
			
		|||
                    trns = trns_im.getpixel((0, 0))
 | 
			
		||||
 | 
			
		||||
            elif self.mode == 'P' and mode == 'RGBA':
 | 
			
		||||
                t = self.info['transparency']
 | 
			
		||||
                delete_trns = True
 | 
			
		||||
                
 | 
			
		||||
                if isinstance(t, bytes):
 | 
			
		||||
                    self.im.putpalettealphas(t)
 | 
			
		||||
                elif isinstance(t, int):
 | 
			
		||||
                    self.im.putpalettealpha(t,0)
 | 
			
		||||
                else:
 | 
			
		||||
                    raise ValueError("Transparency for P mode should" +
 | 
			
		||||
                                     " be bytes or int")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        if mode == "P" and palette == ADAPTIVE:
 | 
			
		||||
            im = self.im.quantize(colors)
 | 
			
		||||
            new = self._new(im)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,19 +1,19 @@
 | 
			
		|||
## The Python Imaging Library.
 | 
			
		||||
## $Id$
 | 
			
		||||
# The Python Imaging Library.
 | 
			
		||||
# $Id$
 | 
			
		||||
 | 
			
		||||
## Optional color managment support, based on Kevin Cazabon's PyCMS
 | 
			
		||||
## library.
 | 
			
		||||
# Optional color managment support, based on Kevin Cazabon's PyCMS
 | 
			
		||||
# library.
 | 
			
		||||
 | 
			
		||||
## History:
 | 
			
		||||
# History:
 | 
			
		||||
 | 
			
		||||
## 2009-03-08 fl   Added to PIL.
 | 
			
		||||
# 2009-03-08 fl   Added to PIL.
 | 
			
		||||
 | 
			
		||||
## Copyright (C) 2002-2003 Kevin Cazabon
 | 
			
		||||
## Copyright (c) 2009 by Fredrik Lundh
 | 
			
		||||
## Copyright (c) 2013 by Eric Soroos
 | 
			
		||||
# Copyright (C) 2002-2003 Kevin Cazabon
 | 
			
		||||
# Copyright (c) 2009 by Fredrik Lundh
 | 
			
		||||
# Copyright (c) 2013 by Eric Soroos
 | 
			
		||||
 | 
			
		||||
## See the README file for information on usage and redistribution.  See
 | 
			
		||||
## below for the original description.
 | 
			
		||||
# See the README file for information on usage and redistribution.  See
 | 
			
		||||
# below for the original description.
 | 
			
		||||
 | 
			
		||||
from __future__ import print_function
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -184,6 +184,7 @@ class ImageCmsProfile:
 | 
			
		|||
 | 
			
		||||
        return core.profile_tobytes(self.profile)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ImageCmsTransform(Image.ImagePointHandler):
 | 
			
		||||
 | 
			
		||||
    # Transform.  This can be used with the procedural API, or with the
 | 
			
		||||
| 
						 | 
				
			
			@ -191,7 +192,6 @@ class ImageCmsTransform(Image.ImagePointHandler):
 | 
			
		|||
    #
 | 
			
		||||
    # Will return the output profile in the output.info['icc_profile'].
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def __init__(self, input, output, input_mode, output_mode,
 | 
			
		||||
                 intent=INTENT_PERCEPTUAL, proof=None,
 | 
			
		||||
                 proof_intent=INTENT_ABSOLUTE_COLORIMETRIC, flags=0):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,6 +20,7 @@
 | 
			
		|||
from PIL import Image
 | 
			
		||||
import re
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def getrgb(color):
 | 
			
		||||
    """
 | 
			
		||||
     Convert a color string to an RGB tuple. If the string cannot be parsed,
 | 
			
		||||
| 
						 | 
				
			
			@ -86,7 +87,8 @@ def getrgb(color):
 | 
			
		|||
            int(rgb[1] * 255 + 0.5),
 | 
			
		||||
            int(rgb[2] * 255 + 0.5)
 | 
			
		||||
            )
 | 
			
		||||
    m = re.match("rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$", color)
 | 
			
		||||
    m = re.match("rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$",
 | 
			
		||||
                 color)
 | 
			
		||||
    if m:
 | 
			
		||||
        return (
 | 
			
		||||
            int(m.group(1)),
 | 
			
		||||
| 
						 | 
				
			
			@ -96,6 +98,7 @@ def getrgb(color):
 | 
			
		|||
            )
 | 
			
		||||
    raise ValueError("unknown color specifier: %r" % color)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def getcolor(color, mode):
 | 
			
		||||
    """
 | 
			
		||||
    Same as :py:func:`~PIL.ImageColor.getrgb`, but converts the RGB value to a
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,6 +40,7 @@ try:
 | 
			
		|||
except ImportError:
 | 
			
		||||
    warnings = None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# A simple 2D drawing interface for PIL images.
 | 
			
		||||
# <p>
 | 
			
		||||
| 
						 | 
				
			
			@ -61,7 +62,7 @@ class ImageDraw:
 | 
			
		|||
    def __init__(self, im, mode=None):
 | 
			
		||||
        im.load()
 | 
			
		||||
        if im.readonly:
 | 
			
		||||
            im._copy() # make it writable
 | 
			
		||||
            im._copy()  # make it writeable
 | 
			
		||||
        blend = 0
 | 
			
		||||
        if mode is None:
 | 
			
		||||
            mode = im.mode
 | 
			
		||||
| 
						 | 
				
			
			@ -280,6 +281,7 @@ class ImageDraw:
 | 
			
		|||
            font = self.getfont()
 | 
			
		||||
        return font.getsize(text)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# A simple 2D drawing interface for PIL images.
 | 
			
		||||
#
 | 
			
		||||
| 
						 | 
				
			
			@ -302,6 +304,7 @@ try:
 | 
			
		|||
except:
 | 
			
		||||
    Outline = None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# (Experimental) A more advanced 2D drawing interface for PIL images,
 | 
			
		||||
# based on the WCK interface.
 | 
			
		||||
| 
						 | 
				
			
			@ -325,6 +328,7 @@ def getdraw(im=None, hints=None):
 | 
			
		|||
        im = handler.Draw(im)
 | 
			
		||||
    return im, handler
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# (experimental) Fills a bounded region with a given color.
 | 
			
		||||
#
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,21 +18,25 @@
 | 
			
		|||
 | 
			
		||||
from PIL import Image, ImageColor, ImageDraw, ImageFont, ImagePath
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Pen:
 | 
			
		||||
    def __init__(self, color, width=1, opacity=255):
 | 
			
		||||
        self.color = ImageColor.getrgb(color)
 | 
			
		||||
        self.width = width
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Brush:
 | 
			
		||||
    def __init__(self, color, opacity=255):
 | 
			
		||||
        self.color = ImageColor.getrgb(color)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Font:
 | 
			
		||||
    def __init__(self, color, file, size=12):
 | 
			
		||||
        # FIXME: add support for bitmap fonts
 | 
			
		||||
        self.color = ImageColor.getrgb(color)
 | 
			
		||||
        self.font = ImageFont.truetype(file, size)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Draw:
 | 
			
		||||
 | 
			
		||||
    def __init__(self, image, size=None, color=None):
 | 
			
		||||
| 
						 | 
				
			
			@ -47,7 +51,8 @@ class Draw:
 | 
			
		|||
 | 
			
		||||
    def render(self, op, xy, pen, brush=None):
 | 
			
		||||
        # handle color arguments
 | 
			
		||||
        outline = fill = None; width = 1
 | 
			
		||||
        outline = fill = None
 | 
			
		||||
        width = 1
 | 
			
		||||
        if isinstance(pen, Pen):
 | 
			
		||||
            outline = pen.color
 | 
			
		||||
            width = pen.width
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,8 +47,11 @@ class Color(_Enhance):
 | 
			
		|||
    """
 | 
			
		||||
    def __init__(self, image):
 | 
			
		||||
        self.image = image
 | 
			
		||||
        self.degenerate = image.convert("L").convert(image.mode)
 | 
			
		||||
        self.intermediate_mode = 'L'
 | 
			
		||||
        if 'A' in image.getbands():
 | 
			
		||||
            self.intermediate_mode = 'LA'
 | 
			
		||||
 | 
			
		||||
        self.degenerate = image.convert(self.intermediate_mode).convert(image.mode)
 | 
			
		||||
 | 
			
		||||
class Contrast(_Enhance):
 | 
			
		||||
    """Adjust image contrast.
 | 
			
		||||
| 
						 | 
				
			
			@ -62,6 +65,9 @@ class Contrast(_Enhance):
 | 
			
		|||
        mean = int(ImageStat.Stat(image.convert("L")).mean[0] + 0.5)
 | 
			
		||||
        self.degenerate = Image.new("L", image.size, mean).convert(image.mode)
 | 
			
		||||
 | 
			
		||||
        if 'A' in image.getbands():
 | 
			
		||||
            self.degenerate.putalpha(image.split()[-1])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Brightness(_Enhance):
 | 
			
		||||
    """Adjust image brightness.
 | 
			
		||||
| 
						 | 
				
			
			@ -74,6 +80,9 @@ class Brightness(_Enhance):
 | 
			
		|||
        self.image = image
 | 
			
		||||
        self.degenerate = Image.new(image.mode, image.size, 0)
 | 
			
		||||
 | 
			
		||||
        if 'A' in image.getbands():
 | 
			
		||||
            self.degenerate.putalpha(image.split()[-1])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Sharpness(_Enhance):
 | 
			
		||||
    """Adjust image sharpness.
 | 
			
		||||
| 
						 | 
				
			
			@ -85,3 +94,6 @@ class Sharpness(_Enhance):
 | 
			
		|||
    def __init__(self, image):
 | 
			
		||||
        self.image = image
 | 
			
		||||
        self.degenerate = image.filter(ImageFilter.SMOOTH)
 | 
			
		||||
 | 
			
		||||
        if 'A' in image.getbands():
 | 
			
		||||
            self.degenerate.putalpha(image.split()[-1])
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,8 +29,10 @@
 | 
			
		|||
 | 
			
		||||
from PIL import Image
 | 
			
		||||
from PIL._util import isPath
 | 
			
		||||
import traceback, os, sys
 | 
			
		||||
import io
 | 
			
		||||
import os
 | 
			
		||||
import sys
 | 
			
		||||
import traceback
 | 
			
		||||
 | 
			
		||||
MAXBLOCK = 65536
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -46,6 +48,7 @@ ERRORS = {
 | 
			
		|||
    -9: "out of memory error"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def raise_ioerror(error):
 | 
			
		||||
    try:
 | 
			
		||||
        message = Image.core.getcodecstatus(error)
 | 
			
		||||
| 
						 | 
				
			
			@ -55,6 +58,7 @@ def raise_ioerror(error):
 | 
			
		|||
        message = "decoder error %d" % error
 | 
			
		||||
    raise IOError(message + " when reading image file")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# --------------------------------------------------------------------
 | 
			
		||||
# Helpers
 | 
			
		||||
| 
						 | 
				
			
			@ -63,6 +67,7 @@ def _tilesort(t):
 | 
			
		|||
    # sort on offset
 | 
			
		||||
    return t[2]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# --------------------------------------------------------------------
 | 
			
		||||
# ImageFile base class
 | 
			
		||||
| 
						 | 
				
			
			@ -213,13 +218,15 @@ class ImageFile(Image.Image):
 | 
			
		|||
                        self.tile = []
 | 
			
		||||
 | 
			
		||||
                        # JpegDecode needs to clean things up here either way
 | 
			
		||||
                        # If we don't destroy the decompressor, we have a memory leak.
 | 
			
		||||
                        # If we don't destroy the decompressor,
 | 
			
		||||
                        # we have a memory leak.
 | 
			
		||||
                        d.cleanup()
 | 
			
		||||
 | 
			
		||||
                        if LOAD_TRUNCATED_IMAGES:
 | 
			
		||||
                            break
 | 
			
		||||
                        else:
 | 
			
		||||
                            raise IOError("image file is truncated (%d bytes not processed)" % len(b))
 | 
			
		||||
                            raise IOError("image file is truncated "
 | 
			
		||||
                                          "(%d bytes not processed)" % len(b))
 | 
			
		||||
 | 
			
		||||
                    b = b + s
 | 
			
		||||
                    n, e = d.decode(b)
 | 
			
		||||
| 
						 | 
				
			
			@ -436,6 +443,7 @@ class Parser:
 | 
			
		|||
                fp.close()  # explicitly close the virtual file
 | 
			
		||||
        return self.image
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# --------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
def _save(im, fp, tile, bufsize=0):
 | 
			
		||||
| 
						 | 
				
			
			@ -452,7 +460,7 @@ def _save(im, fp, tile, bufsize=0):
 | 
			
		|||
        im.encoderconfig = ()
 | 
			
		||||
    tile.sort(key=_tilesort)
 | 
			
		||||
    # FIXME: make MAXBLOCK a configuration parameter
 | 
			
		||||
    # It would be great if we could have the encoder specifiy what it needs
 | 
			
		||||
    # It would be great if we could have the encoder specify what it needs
 | 
			
		||||
    # But, it would need at least the image size in most cases. RawEncode is
 | 
			
		||||
    # a tricky case.
 | 
			
		||||
    bufsize = max(MAXBLOCK, bufsize, im.size[0] * 4)  # see RawEncode.c
 | 
			
		||||
| 
						 | 
				
			
			@ -487,7 +495,8 @@ def _save(im, fp, tile, bufsize=0):
 | 
			
		|||
            e.cleanup()
 | 
			
		||||
    try:
 | 
			
		||||
        fp.flush()
 | 
			
		||||
    except: pass
 | 
			
		||||
    except:
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _safe_read(fp, size):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -162,7 +162,8 @@ class UnsharpMask(Filter):
 | 
			
		|||
    See Wikipedia's entry on `digital unsharp masking`_ for an explanation of
 | 
			
		||||
    the parameters.
 | 
			
		||||
 | 
			
		||||
    .. _digital unsharp masking: https://en.wikipedia.org/wiki/Unsharp_masking#Digital_unsharp_masking
 | 
			
		||||
    .. _digital unsharp masking:
 | 
			
		||||
    https://en.wikipedia.org/wiki/Unsharp_masking#Digital_unsharp_masking
 | 
			
		||||
    """
 | 
			
		||||
    name = "UnsharpMask"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,6 +17,9 @@
 | 
			
		|||
 | 
			
		||||
from PIL import Image
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
if sys.platform != "win32":
 | 
			
		||||
    raise ImportError("ImageGrab is Windows only")
 | 
			
		||||
 | 
			
		||||
try:
 | 
			
		||||
    # built-in driver (1.1.3 and later)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,6 +16,7 @@
 | 
			
		|||
# mode descriptor cache
 | 
			
		||||
_modes = {}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Wrapper for mode strings.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -30,6 +31,7 @@ class ModeDescriptor:
 | 
			
		|||
    def __str__(self):
 | 
			
		||||
        return self.mode
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Gets a mode descriptor for the given mode.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,6 +22,7 @@ from PIL._util import isStringType
 | 
			
		|||
import operator
 | 
			
		||||
from functools import reduce
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# helpers
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -35,12 +36,14 @@ def _border(border):
 | 
			
		|||
        left = top = right = bottom = border
 | 
			
		||||
    return left, top, right, bottom
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _color(color, mode):
 | 
			
		||||
    if isStringType(color):
 | 
			
		||||
        from PIL import ImageColor
 | 
			
		||||
        color = ImageColor.getcolor(color, mode)
 | 
			
		||||
    return color
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _lut(image, lut):
 | 
			
		||||
    if image.mode == "P":
 | 
			
		||||
        # FIXME: apply to lookup table, not image data
 | 
			
		||||
| 
						 | 
				
			
			@ -147,7 +150,9 @@ def colorize(image, black, white):
 | 
			
		|||
    assert image.mode == "L"
 | 
			
		||||
    black = _color(black, "RGB")
 | 
			
		||||
    white = _color(white, "RGB")
 | 
			
		||||
    red = []; green = []; blue = []
 | 
			
		||||
    red = []
 | 
			
		||||
    green = []
 | 
			
		||||
    blue = []
 | 
			
		||||
    for i in range(256):
 | 
			
		||||
        red.append(black[0]+i*(white[0]-black[0])//255)
 | 
			
		||||
        green.append(black[1]+i*(white[1]-black[1])//255)
 | 
			
		||||
| 
						 | 
				
			
			@ -404,6 +409,7 @@ def solarize(image, threshold=128):
 | 
			
		|||
            lut.append(255-i)
 | 
			
		||||
    return _lut(image, lut)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# --------------------------------------------------------------------
 | 
			
		||||
# PIL USM components, from Kevin Cazabon.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -419,6 +425,7 @@ def gaussian_blur(im, radius=None):
 | 
			
		|||
 | 
			
		||||
gblur = gaussian_blur
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def unsharp_mask(im, radius=None, percent=None, threshold=None):
 | 
			
		||||
    """ PIL_usm.usm(im, [radius, percent, threshold])"""
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,6 +24,7 @@ try:
 | 
			
		|||
except:
 | 
			
		||||
    from PyQt4.QtGui import QImage, qRgba
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# (Internal) Turns an RGB color into a Qt compatible color integer.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -32,6 +33,7 @@ def rgb(r, g, b, a=255):
 | 
			
		|||
    # into a negative integer with the same bitpattern.
 | 
			
		||||
    return (qRgba(r, g, b, a) & 0xffffffff)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# An PIL image wrapper for Qt.  This is a subclass of PyQt4's QImage
 | 
			
		||||
# class.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,6 +15,7 @@
 | 
			
		|||
 | 
			
		||||
##
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Iterator:
 | 
			
		||||
    """
 | 
			
		||||
    This class implements an iterator object that can be used to loop
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,7 +15,8 @@
 | 
			
		|||
from __future__ import print_function
 | 
			
		||||
 | 
			
		||||
from PIL import Image
 | 
			
		||||
import os, sys
 | 
			
		||||
import os
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
if sys.version_info >= (3, 3):
 | 
			
		||||
    from shlex import quote
 | 
			
		||||
| 
						 | 
				
			
			@ -24,6 +25,7 @@ else:
 | 
			
		|||
 | 
			
		||||
_viewers = []
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def register(viewer, order=1):
 | 
			
		||||
    try:
 | 
			
		||||
        if issubclass(viewer, Viewer):
 | 
			
		||||
| 
						 | 
				
			
			@ -35,6 +37,7 @@ def register(viewer, order=1):
 | 
			
		|||
    elif order < 0:
 | 
			
		||||
        _viewers.insert(0, viewer)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Displays a given image.
 | 
			
		||||
#
 | 
			
		||||
| 
						 | 
				
			
			@ -49,6 +52,7 @@ def show(image, title=None, **options):
 | 
			
		|||
            return 1
 | 
			
		||||
    return 0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Base class for viewers.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -102,6 +106,7 @@ if sys.platform == "win32":
 | 
			
		|||
 | 
			
		||||
    class WindowsViewer(Viewer):
 | 
			
		||||
        format = "BMP"
 | 
			
		||||
 | 
			
		||||
        def get_command(self, file, **options):
 | 
			
		||||
            return ('start "Pillow" /WAIT "%s" '
 | 
			
		||||
                    '&& ping -n 2 127.0.0.1 >NUL '
 | 
			
		||||
| 
						 | 
				
			
			@ -113,11 +118,13 @@ elif sys.platform == "darwin":
 | 
			
		|||
 | 
			
		||||
    class MacViewer(Viewer):
 | 
			
		||||
        format = "BMP"
 | 
			
		||||
 | 
			
		||||
        def get_command(self, file, **options):
 | 
			
		||||
            # on darwin open returns immediately resulting in the temp
 | 
			
		||||
            # file removal while app is opening
 | 
			
		||||
            command = "open -a /Applications/Preview.app"
 | 
			
		||||
            command = "(%s %s; sleep 20; rm -f %s)&" % (command, quote(file), quote(file))
 | 
			
		||||
            command = "(%s %s; sleep 20; rm -f %s)&" % (command, quote(file),
 | 
			
		||||
                                                        quote(file))
 | 
			
		||||
            return command
 | 
			
		||||
 | 
			
		||||
    register(MacViewer)
 | 
			
		||||
| 
						 | 
				
			
			@ -140,7 +147,8 @@ else:
 | 
			
		|||
    class UnixViewer(Viewer):
 | 
			
		||||
        def show_file(self, file, **options):
 | 
			
		||||
            command, executable = self.get_command_ex(file, **options)
 | 
			
		||||
            command = "(%s %s; rm -f %s)&" % (command, quote(file), quote(file))
 | 
			
		||||
            command = "(%s %s; rm -f %s)&" % (command, quote(file),
 | 
			
		||||
                                              quote(file))
 | 
			
		||||
            os.system(command)
 | 
			
		||||
            return 1
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,7 +21,8 @@
 | 
			
		|||
# See the README file for information on usage and redistribution.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
import operator, math
 | 
			
		||||
import math
 | 
			
		||||
import operator
 | 
			
		||||
from functools import reduce
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -126,7 +127,6 @@ class Stat:
 | 
			
		|||
            v.append(math.sqrt(self.sum2[i] / self.count[i]))
 | 
			
		||||
        return v
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def _getvar(self):
 | 
			
		||||
        "Get variance for each layer"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,6 +40,7 @@ from PIL import Image
 | 
			
		|||
 | 
			
		||||
_pilbitmap_ok = None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _pilbitmap_check():
 | 
			
		||||
    global _pilbitmap_ok
 | 
			
		||||
    if _pilbitmap_ok is None:
 | 
			
		||||
| 
						 | 
				
			
			@ -51,6 +52,7 @@ def _pilbitmap_check():
 | 
			
		|||
            _pilbitmap_ok = 0
 | 
			
		||||
    return _pilbitmap_ok
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# --------------------------------------------------------------------
 | 
			
		||||
# PhotoImage
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -120,7 +122,6 @@ class PhotoImage:
 | 
			
		|||
        except:
 | 
			
		||||
            pass  # ignore internal errors
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        """
 | 
			
		||||
        Get the Tkinter photo image identifier.  This method is automatically
 | 
			
		||||
| 
						 | 
				
			
			@ -131,7 +132,6 @@ class PhotoImage:
 | 
			
		|||
        """
 | 
			
		||||
        return str(self.__photo)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def width(self):
 | 
			
		||||
        """
 | 
			
		||||
        Get the width of the image.
 | 
			
		||||
| 
						 | 
				
			
			@ -140,7 +140,6 @@ class PhotoImage:
 | 
			
		|||
        """
 | 
			
		||||
        return self.__size[0]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def height(self):
 | 
			
		||||
        """
 | 
			
		||||
        Get the height of the image.
 | 
			
		||||
| 
						 | 
				
			
			@ -149,7 +148,6 @@ class PhotoImage:
 | 
			
		|||
        """
 | 
			
		||||
        return self.__size[1]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def paste(self, im, box=None):
 | 
			
		||||
        """
 | 
			
		||||
        Paste a PIL image into the photo image.  Note that this can
 | 
			
		||||
| 
						 | 
				
			
			@ -176,7 +174,7 @@ class PhotoImage:
 | 
			
		|||
 | 
			
		||||
        try:
 | 
			
		||||
            tk.call("PyImagingPhoto", self.__photo, block.id)
 | 
			
		||||
        except tkinter.TclError as v:
 | 
			
		||||
        except tkinter.TclError:
 | 
			
		||||
            # activate Tkinter hook
 | 
			
		||||
            try:
 | 
			
		||||
                from PIL import _imagingtk
 | 
			
		||||
| 
						 | 
				
			
			@ -240,7 +238,6 @@ class BitmapImage:
 | 
			
		|||
        except:
 | 
			
		||||
            pass  # ignore internal errors
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def width(self):
 | 
			
		||||
        """
 | 
			
		||||
        Get the width of the image.
 | 
			
		||||
| 
						 | 
				
			
			@ -249,7 +246,6 @@ class BitmapImage:
 | 
			
		|||
        """
 | 
			
		||||
        return self.__size[0]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def height(self):
 | 
			
		||||
        """
 | 
			
		||||
        Get the height of the image.
 | 
			
		||||
| 
						 | 
				
			
			@ -258,7 +254,6 @@ class BitmapImage:
 | 
			
		|||
        """
 | 
			
		||||
        return self.__size[1]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        """
 | 
			
		||||
        Get the Tkinter bitmap image identifier.  This method is automatically
 | 
			
		||||
| 
						 | 
				
			
			@ -274,6 +269,7 @@ def getimage(photo):
 | 
			
		|||
    """Copies the contents of a PhotoImage to a PIL image memory."""
 | 
			
		||||
    photo.tk.call("PyImagingPhotoGet", photo)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# --------------------------------------------------------------------
 | 
			
		||||
# Helper for the Image.show method.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,16 +15,20 @@
 | 
			
		|||
 | 
			
		||||
from PIL import Image
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Transform(Image.ImageTransformHandler):
 | 
			
		||||
    def __init__(self, data):
 | 
			
		||||
        self.data = data
 | 
			
		||||
 | 
			
		||||
    def getdata(self):
 | 
			
		||||
        return self.method, self.data
 | 
			
		||||
 | 
			
		||||
    def transform(self, size, image, **options):
 | 
			
		||||
        # can be overridden
 | 
			
		||||
        method, data = self.getdata()
 | 
			
		||||
        return image.transform(size, method, data, **options)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Define an affine image transform.
 | 
			
		||||
# <p>
 | 
			
		||||
| 
						 | 
				
			
			@ -43,9 +47,11 @@ class Transform(Image.ImageTransformHandler):
 | 
			
		|||
#    the first two rows from an affine transform matrix.
 | 
			
		||||
# @see Image#Image.transform
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AffineTransform(Transform):
 | 
			
		||||
    method = Image.AFFINE
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Define a transform to extract a subregion from an image.
 | 
			
		||||
# <p>
 | 
			
		||||
| 
						 | 
				
			
			@ -68,6 +74,7 @@ class AffineTransform(Transform):
 | 
			
		|||
class ExtentTransform(Transform):
 | 
			
		||||
    method = Image.EXTENT
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Define an quad image transform.
 | 
			
		||||
# <p>
 | 
			
		||||
| 
						 | 
				
			
			@ -83,6 +90,7 @@ class ExtentTransform(Transform):
 | 
			
		|||
class QuadTransform(Transform):
 | 
			
		||||
    method = Image.QUAD
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Define an mesh image transform.  A mesh transform consists of one
 | 
			
		||||
# or more individual quad transforms.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,23 +23,26 @@ from PIL import Image
 | 
			
		|||
 | 
			
		||||
class HDC:
 | 
			
		||||
    """
 | 
			
		||||
    Wraps a HDC integer. The resulting object can be passed to the
 | 
			
		||||
    Wraps an HDC integer. The resulting object can be passed to the
 | 
			
		||||
    :py:meth:`~PIL.ImageWin.Dib.draw` and :py:meth:`~PIL.ImageWin.Dib.expose`
 | 
			
		||||
    methods.
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, dc):
 | 
			
		||||
        self.dc = dc
 | 
			
		||||
 | 
			
		||||
    def __int__(self):
 | 
			
		||||
        return self.dc
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class HWND:
 | 
			
		||||
    """
 | 
			
		||||
    Wraps a HWND integer. The resulting object can be passed to the
 | 
			
		||||
    Wraps an HWND integer. The resulting object can be passed to the
 | 
			
		||||
    :py:meth:`~PIL.ImageWin.Dib.draw` and :py:meth:`~PIL.ImageWin.Dib.expose`
 | 
			
		||||
    methods, instead of a DC.
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, wnd):
 | 
			
		||||
        self.wnd = wnd
 | 
			
		||||
 | 
			
		||||
    def __int__(self):
 | 
			
		||||
        return self.wnd
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -79,13 +82,12 @@ class Dib:
 | 
			
		|||
        if image:
 | 
			
		||||
            self.paste(image)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def expose(self, handle):
 | 
			
		||||
        """
 | 
			
		||||
        Copy the bitmap contents to a device context.
 | 
			
		||||
 | 
			
		||||
        :param handle: Device context (HDC), cast to a Python integer, or a HDC
 | 
			
		||||
                       or HWND instance.  In PythonWin, you can use the
 | 
			
		||||
        :param handle: Device context (HDC), cast to a Python integer, or an
 | 
			
		||||
                       HDC or HWND instance.  In PythonWin, you can use the
 | 
			
		||||
                       :py:meth:`CDC.GetHandleAttrib` to get a suitable handle.
 | 
			
		||||
        """
 | 
			
		||||
        if isinstance(handle, HWND):
 | 
			
		||||
| 
						 | 
				
			
			@ -120,7 +122,6 @@ class Dib:
 | 
			
		|||
            result = self.image.draw(handle, dst, src)
 | 
			
		||||
        return result
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def query_palette(self, handle):
 | 
			
		||||
        """
 | 
			
		||||
        Installs the palette associated with the image in the given device
 | 
			
		||||
| 
						 | 
				
			
			@ -146,7 +147,6 @@ class Dib:
 | 
			
		|||
            result = self.image.query_palette(handle)
 | 
			
		||||
        return result
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def paste(self, im, box=None):
 | 
			
		||||
        """
 | 
			
		||||
        Paste a PIL image into the bitmap image.
 | 
			
		||||
| 
						 | 
				
			
			@ -166,7 +166,6 @@ class Dib:
 | 
			
		|||
        else:
 | 
			
		||||
            self.image.paste(im.im)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def frombytes(self, buffer):
 | 
			
		||||
        """
 | 
			
		||||
        Load display memory contents from byte data.
 | 
			
		||||
| 
						 | 
				
			
			@ -176,7 +175,6 @@ class Dib:
 | 
			
		|||
        """
 | 
			
		||||
        return self.image.frombytes(buffer)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def tobytes(self):
 | 
			
		||||
        """
 | 
			
		||||
        Copy display memory contents to bytes object.
 | 
			
		||||
| 
						 | 
				
			
			@ -204,6 +202,7 @@ class Dib:
 | 
			
		|||
        )
 | 
			
		||||
        return self.tobytes()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Create a Window with the given title size.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -235,6 +234,7 @@ class Window:
 | 
			
		|||
    def mainloop(self):
 | 
			
		||||
        Image.core.eventloop()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Create an image window which displays the given image.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,6 +26,7 @@ from PIL import Image, ImageFile
 | 
			
		|||
 | 
			
		||||
field = re.compile(br"([a-z]*) ([^ \r\n]*)")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Image plugin for IM Tools images.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -39,7 +40,7 @@ class ImtImageFile(ImageFile.ImageFile):
 | 
			
		|||
        # Quick rejection: if there's not a LF among the first
 | 
			
		||||
        # 100 bytes, this is (probably) not a text header.
 | 
			
		||||
 | 
			
		||||
        if not b"\n" in self.fp.read(100):
 | 
			
		||||
        if b"\n" not in self.fp.read(100):
 | 
			
		||||
            raise SyntaxError("not an IM file")
 | 
			
		||||
        self.fp.seek(0)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -115,7 +115,8 @@ def APP(self, marker):
 | 
			
		|||
    elif marker == 0xFFE2 and s[:4] == b"MPF\0":
 | 
			
		||||
        # extract MPO information
 | 
			
		||||
        self.info["mp"] = s[4:]
 | 
			
		||||
        # offset is current location minus buffer size plus constant header size
 | 
			
		||||
        # offset is current location minus buffer size
 | 
			
		||||
        # plus constant header size
 | 
			
		||||
        self.info["mpoffset"] = self.fp.tell() - n + 4
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -321,7 +322,8 @@ class JpegImageFile(ImageFile.ImageFile):
 | 
			
		|||
                    rawmode = self.mode
 | 
			
		||||
                    if self.mode == "CMYK":
 | 
			
		||||
                        rawmode = "CMYK;I"  # assume adobe conventions
 | 
			
		||||
                    self.tile = [("jpeg", (0, 0) + self.size, 0, (rawmode, ""))]
 | 
			
		||||
                    self.tile = [("jpeg", (0, 0) + self.size, 0,
 | 
			
		||||
                                 (rawmode, ""))]
 | 
			
		||||
                    # self.__offset = self.fp.tell()
 | 
			
		||||
                    break
 | 
			
		||||
                s = self.fp.read(1)
 | 
			
		||||
| 
						 | 
				
			
			@ -472,12 +474,16 @@ def _getmp(self):
 | 
			
		|||
        for entrynum in range(0, quant):
 | 
			
		||||
            rawmpentry = mp[0xB002][entrynum * 16:(entrynum + 1) * 16]
 | 
			
		||||
            unpackedentry = unpack('{0}LLLHH'.format(endianness), rawmpentry)
 | 
			
		||||
            labels = ('Attribute', 'Size', 'DataOffset', 'EntryNo1', 'EntryNo2')
 | 
			
		||||
            labels = ('Attribute', 'Size', 'DataOffset', 'EntryNo1',
 | 
			
		||||
                      'EntryNo2')
 | 
			
		||||
            mpentry = dict(zip(labels, unpackedentry))
 | 
			
		||||
            mpentryattr = {
 | 
			
		||||
                'DependentParentImageFlag': bool(mpentry['Attribute'] & (1<<31)),
 | 
			
		||||
                'DependentChildImageFlag': bool(mpentry['Attribute'] & (1<<30)),
 | 
			
		||||
                'RepresentativeImageFlag': bool(mpentry['Attribute'] & (1<<29)),
 | 
			
		||||
                'DependentParentImageFlag': bool(mpentry['Attribute'] &
 | 
			
		||||
                                                 (1 << 31)),
 | 
			
		||||
                'DependentChildImageFlag': bool(mpentry['Attribute'] &
 | 
			
		||||
                                                (1 << 30)),
 | 
			
		||||
                'RepresentativeImageFlag': bool(mpentry['Attribute'] &
 | 
			
		||||
                                                (1 << 29)),
 | 
			
		||||
                'Reserved': (mpentry['Attribute'] & (3 << 27)) >> 27,
 | 
			
		||||
                'ImageDataFormat': (mpentry['Attribute'] & (7 << 24)) >> 24,
 | 
			
		||||
                'MPType': mpentry['Attribute'] & 0x00FFFFFF
 | 
			
		||||
| 
						 | 
				
			
			@ -530,8 +536,7 @@ zigzag_index = ( 0,  1,  5,  6, 14, 15, 27, 28,
 | 
			
		|||
                21, 34, 37, 47, 50, 56, 59, 61,
 | 
			
		||||
                35, 36, 48, 49, 57, 58, 62, 63)
 | 
			
		||||
 | 
			
		||||
samplings = {
 | 
			
		||||
             (1, 1, 1, 1, 1, 1): 0,
 | 
			
		||||
samplings = {(1, 1, 1, 1, 1, 1): 0,
 | 
			
		||||
             (2, 1, 1, 1, 1, 1): 1,
 | 
			
		||||
             (2, 2, 1, 1, 1, 1): 2,
 | 
			
		||||
             }
 | 
			
		||||
| 
						 | 
				
			
			@ -598,7 +603,8 @@ def _save(im, fp, filename):
 | 
			
		|||
        subsampling = 2
 | 
			
		||||
    elif subsampling == "keep":
 | 
			
		||||
        if im.format != "JPEG":
 | 
			
		||||
            raise ValueError("Cannot use 'keep' when original image is not a JPEG")
 | 
			
		||||
            raise ValueError(
 | 
			
		||||
                "Cannot use 'keep' when original image is not a JPEG")
 | 
			
		||||
        subsampling = get_sampling(im)
 | 
			
		||||
 | 
			
		||||
    def validate_qtables(qtables):
 | 
			
		||||
| 
						 | 
				
			
			@ -632,7 +638,8 @@ def _save(im, fp, filename):
 | 
			
		|||
 | 
			
		||||
    if qtables == "keep":
 | 
			
		||||
        if im.format != "JPEG":
 | 
			
		||||
            raise ValueError("Cannot use 'keep' when original image is not a JPEG")
 | 
			
		||||
            raise ValueError(
 | 
			
		||||
                "Cannot use 'keep' when original image is not a JPEG")
 | 
			
		||||
        qtables = getattr(im, "quantization", None)
 | 
			
		||||
    qtables = validate_qtables(qtables)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -650,7 +657,8 @@ def _save(im, fp, filename):
 | 
			
		|||
        i = 1
 | 
			
		||||
        for marker in markers:
 | 
			
		||||
            size = struct.pack(">H", 2 + ICC_OVERHEAD_LEN + len(marker))
 | 
			
		||||
            extra += b"\xFF\xE2" + size + b"ICC_PROFILE\0" + o8(i) + o8(len(markers)) + marker
 | 
			
		||||
            extra += (b"\xFF\xE2" + size + b"ICC_PROFILE\0" + o8(i) +
 | 
			
		||||
                      o8(len(markers)) + marker)
 | 
			
		||||
            i += 1
 | 
			
		||||
 | 
			
		||||
    # get keyword arguments
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -48,8 +48,8 @@ You can get the quantization tables of a JPEG with::
 | 
			
		|||
 | 
			
		||||
  im.quantization
 | 
			
		||||
 | 
			
		||||
This will return a dict with a number of arrays. You can pass this dict directly
 | 
			
		||||
as the qtables argument when saving a JPEG.
 | 
			
		||||
This will return a dict with a number of arrays. You can pass this dict
 | 
			
		||||
directly as the qtables argument when saving a JPEG.
 | 
			
		||||
 | 
			
		||||
The tables format between im.quantization and quantization in presets differ in
 | 
			
		||||
3 ways:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,9 +21,11 @@ __version__ = "0.2"
 | 
			
		|||
import struct
 | 
			
		||||
from PIL import Image, ImageFile
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _accept(s):
 | 
			
		||||
    return s[:8] == b"\x00\x00\x00\x00\x00\x00\x00\x04"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Image plugin for McIdas area images.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -47,10 +49,12 @@ class McIdasImageFile(ImageFile.ImageFile):
 | 
			
		|||
            mode = rawmode = "L"
 | 
			
		||||
        elif w[11] == 2:
 | 
			
		||||
            # FIXME: add memory map support
 | 
			
		||||
            mode = "I"; rawmode = "I;16B"
 | 
			
		||||
            mode = "I"
 | 
			
		||||
            rawmode = "I;16B"
 | 
			
		||||
        elif w[11] == 4:
 | 
			
		||||
            # FIXME: add memory map support
 | 
			
		||||
            mode = "I"; rawmode = "I;32B"
 | 
			
		||||
            mode = "I"
 | 
			
		||||
            rawmode = "I;32B"
 | 
			
		||||
        else:
 | 
			
		||||
            raise SyntaxError("unsupported McIdas format")
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,6 +31,7 @@ from PIL.OleFileIO import *
 | 
			
		|||
def _accept(prefix):
 | 
			
		||||
    return prefix[:8] == MAGIC
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Image plugin for Microsoft's Image Composer file format.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,6 +18,7 @@ __version__ = "0.1"
 | 
			
		|||
from PIL import Image, ImageFile
 | 
			
		||||
from PIL._binary import i8
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Bitstream parser
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -52,6 +53,7 @@ class BitStream:
 | 
			
		|||
        self.bits = self.bits - bits
 | 
			
		||||
        return v
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Image plugin for MPEG streams.  This plugin can identify a stream,
 | 
			
		||||
# but it cannot read it.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,13 +22,16 @@ __version__ = "0.1"
 | 
			
		|||
 | 
			
		||||
from PIL import Image, JpegImagePlugin
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _accept(prefix):
 | 
			
		||||
    return JpegImagePlugin._accept(prefix)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _save(im, fp, filename):
 | 
			
		||||
    # Note that we can only save the current frame at present
 | 
			
		||||
    return JpegImagePlugin._save(im, fp, filename)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Image plugin for MPO images.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -42,7 +45,7 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile):
 | 
			
		|||
        JpegImagePlugin.JpegImageFile._open(self)
 | 
			
		||||
        self.mpinfo = self._getmp()
 | 
			
		||||
        self.__framecount = self.mpinfo[0xB001]
 | 
			
		||||
        self.__mpoffsets = [mpent['DataOffset'] + self.info['mpoffset'] \
 | 
			
		||||
        self.__mpoffsets = [mpent['DataOffset'] + self.info['mpoffset']
 | 
			
		||||
                            for mpent in self.mpinfo[0xB002]]
 | 
			
		||||
        self.__mpoffsets[0] = 0
 | 
			
		||||
        # Note that the following assertion will only be invalid if something
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,9 +27,11 @@ from PIL import Image, ImageFile, _binary
 | 
			
		|||
 | 
			
		||||
i16 = _binary.i16le
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _accept(prefix):
 | 
			
		||||
    return prefix[:4] in [b"DanM", b"LinS"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Image plugin for Windows MSP images.  This plugin supports both
 | 
			
		||||
# uncompressed (Windows 1.0).
 | 
			
		||||
| 
						 | 
				
			
			@ -66,6 +68,7 @@ class MspImageFile(ImageFile.ImageFile):
 | 
			
		|||
 | 
			
		||||
o16 = _binary.o16le
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _save(im, fp, filename):
 | 
			
		||||
 | 
			
		||||
    if im.mode != "1":
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,6 +19,7 @@ from __future__ import print_function
 | 
			
		|||
 | 
			
		||||
from PIL import EpsImagePlugin
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Simple Postscript graphics interface.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -65,7 +66,7 @@ class PSDraw:
 | 
			
		|||
        """
 | 
			
		||||
        if font not in self.isofont:
 | 
			
		||||
            # reencode font
 | 
			
		||||
            self.fp.write("/PSDraw-%s ISOLatin1Encoding /%s E\n" %\
 | 
			
		||||
            self.fp.write("/PSDraw-%s ISOLatin1Encoding /%s E\n" %
 | 
			
		||||
                          (font, font))
 | 
			
		||||
            self.isofont[font] = 1
 | 
			
		||||
        # rough
 | 
			
		||||
| 
						 | 
				
			
			@ -127,9 +128,11 @@ class PSDraw:
 | 
			
		|||
        xmax = float(box[2] - box[0])
 | 
			
		||||
        ymax = float(box[3] - box[1])
 | 
			
		||||
        if x > xmax:
 | 
			
		||||
            y = y * xmax / x; x = xmax
 | 
			
		||||
            y = y * xmax / x
 | 
			
		||||
            x = xmax
 | 
			
		||||
        if y > ymax:
 | 
			
		||||
            x = x * ymax / y; y = ymax
 | 
			
		||||
            x = x * ymax / y
 | 
			
		||||
            y = ymax
 | 
			
		||||
        dx = (xmax - x) / 2 + box[0]
 | 
			
		||||
        dy = (ymax - y) / 2 + box[1]
 | 
			
		||||
        self.fp.write("gsave\n%f %f translate\n" % (dx, dy))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,6 +15,7 @@
 | 
			
		|||
 | 
			
		||||
from PIL._binary import o8
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# File handler for Teragon-style palette files.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -49,7 +50,6 @@ class PaletteFile:
 | 
			
		|||
 | 
			
		||||
        self.palette = b"".join(self.palette)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def getpalette(self):
 | 
			
		||||
 | 
			
		||||
        return self.palette, self.rawmode
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,6 +22,7 @@ from PIL import Image, ImageFile, _binary
 | 
			
		|||
 | 
			
		||||
i8 = _binary.i8
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Image plugin for PhotoCD images.  This plugin only reads the 768x512
 | 
			
		||||
# image from the file; higher resolutions are encoded in a proprietary
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -48,9 +48,11 @@ l32 = _binary.i32le
 | 
			
		|||
b16 = _binary.i16be
 | 
			
		||||
b32 = _binary.i32be
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def sz(s, o):
 | 
			
		||||
    return s[o:s.index(b"\0", o)]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Font file plugin for the X11 PCF format.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,9 +33,11 @@ i8 = _binary.i8
 | 
			
		|||
i16 = _binary.i16le
 | 
			
		||||
o8 = _binary.o8
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _accept(prefix):
 | 
			
		||||
    return i8(prefix[0]) == 10 and i8(prefix[1]) in [0, 2, 3, 5]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Image plugin for Paintbrush images.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -58,7 +60,6 @@ class PcxImageFile(ImageFile.ImageFile):
 | 
			
		|||
        if Image.DEBUG:
 | 
			
		||||
            print ("BBox: %s %s %s %s" % bbox)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        # format
 | 
			
		||||
        version = i8(s[1])
 | 
			
		||||
        bits = i8(s[3])
 | 
			
		||||
| 
						 | 
				
			
			@ -122,6 +123,7 @@ SAVE = {
 | 
			
		|||
 | 
			
		||||
o16 = _binary.o16le
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _save(im, fp, filename, check=0):
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
| 
						 | 
				
			
			@ -140,7 +142,6 @@ def _save(im, fp, filename, check=0):
 | 
			
		|||
    # Ideally it should be passed in in the state, but the bytes value
 | 
			
		||||
    # gets overwritten.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    if Image.DEBUG:
 | 
			
		||||
        print ("PcxImagePlugin._save: xwidth: %d, bits: %d, stride: %d" % (
 | 
			
		||||
            im.size[0], bits, stride))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,6 +29,7 @@ from PIL import Image, ImageFile, _binary
 | 
			
		|||
i16 = _binary.i16le
 | 
			
		||||
i32 = _binary.i32le
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Image plugin for PIXAR raster images.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -72,6 +72,7 @@ _MODES = {
 | 
			
		|||
 | 
			
		||||
_simple_palette = re.compile(b'^\xff+\x00\xff*$')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# --------------------------------------------------------------------
 | 
			
		||||
# Support classes.  Suitable for PNG and related formats like MNG etc.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -123,7 +124,7 @@ class ChunkStream:
 | 
			
		|||
        crc1 = Image.core.crc32(data, Image.core.crc32(cid))
 | 
			
		||||
        crc2 = i16(self.fp.read(2)), i16(self.fp.read(2))
 | 
			
		||||
        if crc1 != crc2:
 | 
			
		||||
            raise SyntaxError("broken PNG file"\
 | 
			
		||||
            raise SyntaxError("broken PNG file"
 | 
			
		||||
                              "(bad header checksum in %s)" % cid)
 | 
			
		||||
 | 
			
		||||
    def crc_skip(self, cid, data):
 | 
			
		||||
| 
						 | 
				
			
			@ -147,6 +148,7 @@ class ChunkStream:
 | 
			
		|||
 | 
			
		||||
        return cids
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# --------------------------------------------------------------------
 | 
			
		||||
# Subclass of string to allow iTXt chunks to look like strings while
 | 
			
		||||
# keeping their extra information
 | 
			
		||||
| 
						 | 
				
			
			@ -159,6 +161,7 @@ class iTXt(str):
 | 
			
		|||
        self.tkey = tkey
 | 
			
		||||
        return self
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# --------------------------------------------------------------------
 | 
			
		||||
# PNG chunk container (for use with save(pnginfo=))
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -182,9 +185,11 @@ class PngInfo:
 | 
			
		|||
 | 
			
		||||
        if zip:
 | 
			
		||||
            import zlib
 | 
			
		||||
            self.add(b"iTXt", key + b"\0\x01\0" + lang + b"\0" + tkey + b"\0" + zlib.compress(value))
 | 
			
		||||
            self.add(b"iTXt", key + b"\0\x01\0" + lang + b"\0" + tkey + b"\0" +
 | 
			
		||||
                     zlib.compress(value))
 | 
			
		||||
        else:
 | 
			
		||||
            self.add(b"iTXt", key + b"\0\0\0" + lang + b"\0" + tkey + b"\0" + value)
 | 
			
		||||
            self.add(b"iTXt", key + b"\0\0\0" + lang + b"\0" + tkey + b"\0" +
 | 
			
		||||
                     value)
 | 
			
		||||
 | 
			
		||||
    def add_text(self, key, value, zip=0):
 | 
			
		||||
        if isinstance(value, iTXt):
 | 
			
		||||
| 
						 | 
				
			
			@ -206,6 +211,7 @@ class PngInfo:
 | 
			
		|||
        else:
 | 
			
		||||
            self.add(b"tEXt", key + b"\0" + value)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# --------------------------------------------------------------------
 | 
			
		||||
# PNG image stream (IHDR/IEND)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -238,7 +244,8 @@ class PngStream(ChunkStream):
 | 
			
		|||
            print("Compression method", i8(s[i]))
 | 
			
		||||
        comp_method = i8(s[i])
 | 
			
		||||
        if comp_method != 0:
 | 
			
		||||
            raise SyntaxError("Unknown compression method %s in iCCP chunk" % comp_method)
 | 
			
		||||
            raise SyntaxError("Unknown compression method %s in iCCP chunk" %
 | 
			
		||||
                              comp_method)
 | 
			
		||||
        try:
 | 
			
		||||
            icc_profile = zlib.decompress(s[i+2:])
 | 
			
		||||
        except zlib.error:
 | 
			
		||||
| 
						 | 
				
			
			@ -325,7 +332,9 @@ class PngStream(ChunkStream):
 | 
			
		|||
        try:
 | 
			
		||||
            k, v = s.split(b"\0", 1)
 | 
			
		||||
        except ValueError:
 | 
			
		||||
            k = s; v = b"" # fallback for broken tEXt tags
 | 
			
		||||
            # fallback for broken tEXt tags
 | 
			
		||||
            k = s
 | 
			
		||||
            v = b""
 | 
			
		||||
        if k:
 | 
			
		||||
            if bytes is not str:
 | 
			
		||||
                k = k.decode('latin-1', 'strict')
 | 
			
		||||
| 
						 | 
				
			
			@ -341,13 +350,15 @@ class PngStream(ChunkStream):
 | 
			
		|||
        try:
 | 
			
		||||
            k, v = s.split(b"\0", 1)
 | 
			
		||||
        except ValueError:
 | 
			
		||||
            k = s; v = b""
 | 
			
		||||
            k = s
 | 
			
		||||
            v = b""
 | 
			
		||||
        if v:
 | 
			
		||||
            comp_method = i8(v[0])
 | 
			
		||||
        else:
 | 
			
		||||
            comp_method = 0
 | 
			
		||||
        if comp_method != 0:
 | 
			
		||||
            raise SyntaxError("Unknown compression method %s in zTXt chunk" % comp_method)
 | 
			
		||||
            raise SyntaxError("Unknown compression method %s in zTXt chunk" %
 | 
			
		||||
                              comp_method)
 | 
			
		||||
        import zlib
 | 
			
		||||
        try:
 | 
			
		||||
            v = zlib.decompress(v[1:])
 | 
			
		||||
| 
						 | 
				
			
			@ -399,12 +410,14 @@ class PngStream(ChunkStream):
 | 
			
		|||
 | 
			
		||||
        return s
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# --------------------------------------------------------------------
 | 
			
		||||
# PNG reader
 | 
			
		||||
 | 
			
		||||
def _accept(prefix):
 | 
			
		||||
    return prefix[:8] == _MAGIC
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Image plugin for PNG images.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -460,7 +473,6 @@ class PngImageFile(ImageFile.ImageFile):
 | 
			
		|||
 | 
			
		||||
        self.__idat = length  # used by load_read()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def verify(self):
 | 
			
		||||
        "Verify PNG file"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -509,7 +521,6 @@ class PngImageFile(ImageFile.ImageFile):
 | 
			
		|||
 | 
			
		||||
        return self.fp.read(read_bytes)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def load_end(self):
 | 
			
		||||
        "internal: finished reading image data"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -541,6 +552,7 @@ _OUTMODES = {
 | 
			
		|||
    "RGBA": ("RGBA",    b'\x08\x06'),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def putchunk(fp, cid, *data):
 | 
			
		||||
    "Write a PNG chunk (including CRC field)"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -551,15 +563,18 @@ def putchunk(fp, cid, *data):
 | 
			
		|||
    hi, lo = Image.core.crc32(data, Image.core.crc32(cid))
 | 
			
		||||
    fp.write(o16(hi) + o16(lo))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class _idat:
 | 
			
		||||
    # wrap output from the encoder in IDAT chunks
 | 
			
		||||
 | 
			
		||||
    def __init__(self, fp, chunk):
 | 
			
		||||
        self.fp = fp
 | 
			
		||||
        self.chunk = chunk
 | 
			
		||||
 | 
			
		||||
    def write(self, data):
 | 
			
		||||
        self.chunk(self.fp, b"IDAT", data)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _save(im, fp, filename, chunk=putchunk, check=0):
 | 
			
		||||
    # save an image to disk (called by the save method)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -629,7 +644,8 @@ def _save(im, fp, filename, chunk=putchunk, check=0):
 | 
			
		|||
            palette_bytes += b'\0'
 | 
			
		||||
        chunk(fp, b"PLTE", palette_bytes)
 | 
			
		||||
 | 
			
		||||
    transparency = im.encoderinfo.get('transparency',im.info.get('transparency', None))
 | 
			
		||||
    transparency = im.encoderinfo.get('transparency',
 | 
			
		||||
                                      im.info.get('transparency', None))
 | 
			
		||||
 | 
			
		||||
    if transparency or transparency == 0:
 | 
			
		||||
        if im.mode == "P":
 | 
			
		||||
| 
						 | 
				
			
			@ -686,7 +702,8 @@ def _save(im, fp, filename, chunk=putchunk, check=0):
 | 
			
		|||
        data = name + b"\0\0" + zlib.compress(im.info["icc_profile"])
 | 
			
		||||
        chunk(fp, b"iCCP", data)
 | 
			
		||||
 | 
			
		||||
    ImageFile._save(im, _idat(fp, chunk), [("zip", (0,0)+im.size, 0, rawmode)])
 | 
			
		||||
    ImageFile._save(im, _idat(fp, chunk),
 | 
			
		||||
                    [("zip", (0, 0)+im.size, 0, rawmode)])
 | 
			
		||||
 | 
			
		||||
    chunk(fp, b"IEND", b"")
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -704,8 +721,10 @@ def getchunks(im, **params):
 | 
			
		|||
 | 
			
		||||
    class collector:
 | 
			
		||||
        data = []
 | 
			
		||||
 | 
			
		||||
        def write(self, data):
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
        def append(self, chunk):
 | 
			
		||||
            self.data.append(chunk)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,7 +31,8 @@ try:
 | 
			
		|||
    if locale_enc is None:
 | 
			
		||||
        locale_lang, locale_enc = locale.getdefaultlocale()
 | 
			
		||||
    b_whitespace = b_whitespace.decode(locale_enc)
 | 
			
		||||
except: pass
 | 
			
		||||
except:
 | 
			
		||||
    pass
 | 
			
		||||
b_whitespace = b_whitespace.encode('ascii', 'ignore')
 | 
			
		||||
 | 
			
		||||
MODES = {
 | 
			
		||||
| 
						 | 
				
			
			@ -47,9 +48,11 @@ MODES = {
 | 
			
		|||
    b"PyCMYK": "CMYK"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _accept(prefix):
 | 
			
		||||
    return prefix[0:1] == b"P" and prefix[1] in b"0456y"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Image plugin for PBM, PGM, and PPM images.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -109,7 +112,7 @@ class PpmImageFile(ImageFile.ImageFile):
 | 
			
		|||
                        self.mode = 'I'
 | 
			
		||||
                        rawmode = 'I;16B'
 | 
			
		||||
                    else:
 | 
			
		||||
                        self.mode = 'I';
 | 
			
		||||
                        self.mode = 'I'
 | 
			
		||||
                        rawmode = 'I;32B'
 | 
			
		||||
 | 
			
		||||
        self.size = xsize, ysize
 | 
			
		||||
| 
						 | 
				
			
			@ -123,6 +126,7 @@ class PpmImageFile(ImageFile.ImageFile):
 | 
			
		|||
        # self.mode = self.im.mode
 | 
			
		||||
        # self.size = self.im.size
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# --------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,12 +40,14 @@ i8 = _binary.i8
 | 
			
		|||
i16 = _binary.i16be
 | 
			
		||||
i32 = _binary.i32be
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# --------------------------------------------------------------------.
 | 
			
		||||
# read PSD images
 | 
			
		||||
 | 
			
		||||
def _accept(prefix):
 | 
			
		||||
    return prefix[:4] == b"8BPS"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Image plugin for Photoshop images.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -159,6 +161,7 @@ class PsdImageFile(ImageFile.ImageFile):
 | 
			
		|||
        if self.mode == "P":
 | 
			
		||||
            Image.Image.load(self)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _layerinfo(file):
 | 
			
		||||
    # read layerinfo block
 | 
			
		||||
    layers = []
 | 
			
		||||
| 
						 | 
				
			
			@ -166,8 +169,10 @@ def _layerinfo(file):
 | 
			
		|||
    for i in range(abs(i16(read(2)))):
 | 
			
		||||
 | 
			
		||||
        # bounding box
 | 
			
		||||
        y0 = i32(read(4)); x0 = i32(read(4))
 | 
			
		||||
        y1 = i32(read(4)); x1 = i32(read(4))
 | 
			
		||||
        y0 = i32(read(4))
 | 
			
		||||
        x0 = i32(read(4))
 | 
			
		||||
        y1 = i32(read(4))
 | 
			
		||||
        x1 = i32(read(4))
 | 
			
		||||
 | 
			
		||||
        # image info
 | 
			
		||||
        info = []
 | 
			
		||||
| 
						 | 
				
			
			@ -207,8 +212,10 @@ def _layerinfo(file):
 | 
			
		|||
        if size:
 | 
			
		||||
            length = i32(read(4))
 | 
			
		||||
            if length:
 | 
			
		||||
                mask_y = i32(read(4)); mask_x = i32(read(4))
 | 
			
		||||
                mask_h = i32(read(4)) - mask_y; mask_w = i32(read(4)) - mask_x
 | 
			
		||||
                mask_y = i32(read(4))
 | 
			
		||||
                mask_x = i32(read(4))
 | 
			
		||||
                mask_h = i32(read(4)) - mask_y
 | 
			
		||||
                mask_w = i32(read(4)) - mask_x
 | 
			
		||||
                file.seek(length - 16, 1)
 | 
			
		||||
            combined += length + 4
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -219,7 +226,8 @@ def _layerinfo(file):
 | 
			
		|||
 | 
			
		||||
            length = i8(read(1))
 | 
			
		||||
            if length:
 | 
			
		||||
                # Don't know the proper encoding, Latin-1 should be a good guess
 | 
			
		||||
                # Don't know the proper encoding,
 | 
			
		||||
                # Latin-1 should be a good guess
 | 
			
		||||
                name = read(length).decode('latin-1', 'replace')
 | 
			
		||||
            combined += length + 1
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -239,6 +247,7 @@ def _layerinfo(file):
 | 
			
		|||
 | 
			
		||||
    return layers
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _maketile(file, mode, bbox, channels):
 | 
			
		||||
 | 
			
		||||
    tile = None
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,8 @@
 | 
			
		|||
#  * Implements the pixel access object following Access.
 | 
			
		||||
#  * Does not implement the line functions, as they don't appear to be used
 | 
			
		||||
#  * Taking only the tuple form, which is used from python.
 | 
			
		||||
#    * Fill.c uses the integer form, but it's still going to use the old Access.c implementation.
 | 
			
		||||
#    * Fill.c uses the integer form, but it's still going to use the old
 | 
			
		||||
#      Access.c implementation.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
from __future__ import print_function
 | 
			
		||||
| 
						 | 
				
			
			@ -53,7 +54,8 @@ class PyAccess(object):
 | 
			
		|||
            print (vals)
 | 
			
		||||
        self._post_init()
 | 
			
		||||
 | 
			
		||||
    def _post_init(): pass
 | 
			
		||||
    def _post_init():
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def __setitem__(self, xy, color):
 | 
			
		||||
        """
 | 
			
		||||
| 
						 | 
				
			
			@ -64,7 +66,8 @@ class PyAccess(object):
 | 
			
		|||
        :param xy: The pixel coordinate, given as (x, y).
 | 
			
		||||
        :param value: The pixel value.
 | 
			
		||||
        """
 | 
			
		||||
        if self.readonly: raise ValueError('Attempt to putpixel a read only image') 
 | 
			
		||||
        if self.readonly:
 | 
			
		||||
            raise ValueError('Attempt to putpixel a read only image')
 | 
			
		||||
        (x, y) = self.check_xy(xy)
 | 
			
		||||
        return self.set_pixel(x, y, color)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -89,6 +92,7 @@ class PyAccess(object):
 | 
			
		|||
            raise ValueError('pixel location out of range')
 | 
			
		||||
        return xy
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class _PyAccess32_2(PyAccess):
 | 
			
		||||
    """ PA, LA, stored in first and last bytes of a 32 bit word """
 | 
			
		||||
    def _post_init(self, *args, **kwargs):
 | 
			
		||||
| 
						 | 
				
			
			@ -104,6 +108,7 @@ class _PyAccess32_2(PyAccess):
 | 
			
		|||
        pixel.r = min(color[0], 255)
 | 
			
		||||
        pixel.a = min(color[1], 255)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class _PyAccess32_3(PyAccess):
 | 
			
		||||
    """ RGB and friends, stored in the first three bytes of a 32 bit word """
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -121,6 +126,7 @@ class _PyAccess32_3(PyAccess):
 | 
			
		|||
        pixel.g = min(color[1], 255)
 | 
			
		||||
        pixel.b = min(color[2], 255)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class _PyAccess32_4(PyAccess):
 | 
			
		||||
    """ RGBA etc, all 4 bytes of a 32 bit word """
 | 
			
		||||
    def _post_init(self, *args, **kwargs):
 | 
			
		||||
| 
						 | 
				
			
			@ -155,6 +161,7 @@ class _PyAccess8(PyAccess):
 | 
			
		|||
            # tuple
 | 
			
		||||
            self.pixels[y][x] = min(color[0], 255)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class _PyAccessI16_N(PyAccess):
 | 
			
		||||
    """ I;16 access, native bitendian without conversion """
 | 
			
		||||
    def _post_init(self, *args, **kwargs):
 | 
			
		||||
| 
						 | 
				
			
			@ -171,6 +178,7 @@ class _PyAccessI16_N(PyAccess):
 | 
			
		|||
            # tuple
 | 
			
		||||
            self.pixels[y][x] = min(color[0], 65535)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class _PyAccessI16_L(PyAccess):
 | 
			
		||||
    """ I;16L access, with conversion """
 | 
			
		||||
    def _post_init(self, *args, **kwargs):
 | 
			
		||||
| 
						 | 
				
			
			@ -190,6 +198,7 @@ class _PyAccessI16_L(PyAccess):
 | 
			
		|||
        pixel.l = color & 0xFF
 | 
			
		||||
        pixel.r = color >> 8
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class _PyAccessI16_B(PyAccess):
 | 
			
		||||
    """ I;16B access, with conversion """
 | 
			
		||||
    def _post_init(self, *args, **kwargs):
 | 
			
		||||
| 
						 | 
				
			
			@ -209,6 +218,7 @@ class _PyAccessI16_B(PyAccess):
 | 
			
		|||
        pixel.l = color >> 8
 | 
			
		||||
        pixel.r = color & 0xFF
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class _PyAccessI32_N(PyAccess):
 | 
			
		||||
    """ Signed Int32 access, native endian """
 | 
			
		||||
    def _post_init(self, *args, **kwargs):
 | 
			
		||||
| 
						 | 
				
			
			@ -220,6 +230,7 @@ class _PyAccessI32_N(PyAccess):
 | 
			
		|||
    def set_pixel(self, x, y, color):
 | 
			
		||||
        self.pixels[y][x] = color
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class _PyAccessI32_Swap(PyAccess):
 | 
			
		||||
    """ I;32L/B access, with byteswapping conversion """
 | 
			
		||||
    def _post_init(self, *args, **kwargs):
 | 
			
		||||
| 
						 | 
				
			
			@ -228,7 +239,8 @@ class _PyAccessI32_Swap(PyAccess):
 | 
			
		|||
    def reverse(self, i):
 | 
			
		||||
        orig = ffi.new('int *', i)
 | 
			
		||||
        chars = ffi.cast('unsigned char *', orig)
 | 
			
		||||
        chars[0],chars[1],chars[2],chars[3] = chars[3], chars[2],chars[1],chars[0]
 | 
			
		||||
        chars[0], chars[1], chars[2], chars[3] = chars[3], chars[2], \
 | 
			
		||||
            chars[1], chars[0]
 | 
			
		||||
        return ffi.cast('int *', chars)[0]
 | 
			
		||||
 | 
			
		||||
    def get_pixel(self, x, y):
 | 
			
		||||
| 
						 | 
				
			
			@ -237,6 +249,7 @@ class _PyAccessI32_Swap(PyAccess):
 | 
			
		|||
    def set_pixel(self, x, y, color):
 | 
			
		||||
        self.pixels[y][x] = self.reverse(color)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class _PyAccessF(PyAccess):
 | 
			
		||||
    """ 32 bit float access """
 | 
			
		||||
    def _post_init(self, *args, **kwargs):
 | 
			
		||||
| 
						 | 
				
			
			@ -286,13 +299,15 @@ else:
 | 
			
		|||
    mode_map['I;32L'] = _PyAccessI32_Swap
 | 
			
		||||
    mode_map['I;32B'] = _PyAccessI32_N
 | 
			
		||||
 | 
			
		||||
def new(img, readonly=False):
 | 
			
		||||
 | 
			
		||||
def new(img, readonly=False):
 | 
			
		||||
    access_type = mode_map.get(img.mode, None)
 | 
			
		||||
    if not access_type:
 | 
			
		||||
        if DEBUG: print ("PyAccess Not Implemented: %s" % img.mode)
 | 
			
		||||
        if DEBUG:
 | 
			
		||||
            print("PyAccess Not Implemented: %s" % img.mode)
 | 
			
		||||
        return None
 | 
			
		||||
    if DEBUG: print ("New PyAccess: %s" % img.mode)
 | 
			
		||||
    if DEBUG:
 | 
			
		||||
        print("New PyAccess: %s" % img.mode)
 | 
			
		||||
    return access_type(img, readonly)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# End of file
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,6 +16,7 @@
 | 
			
		|||
 | 
			
		||||
from PIL import ContainerIO
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# A file object that provides read access to a given member of a TAR
 | 
			
		||||
# file.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,6 +33,7 @@ except ImportError:
 | 
			
		|||
 | 
			
		||||
i32 = _binary.i32le
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Load texture from a Quake2 WAL texture file.
 | 
			
		||||
# <p>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,7 +30,8 @@ class WebPImageFile(ImageFile.ImageFile):
 | 
			
		|||
    format_description = "WebP image"
 | 
			
		||||
 | 
			
		||||
    def _open(self):
 | 
			
		||||
        data, width, height, self.mode, icc_profile, exif = _webp.WebPDecode(self.fp.read())
 | 
			
		||||
        data, width, height, self.mode, icc_profile, exif = \
 | 
			
		||||
            _webp.WebPDecode(self.fp.read())
 | 
			
		||||
 | 
			
		||||
        if icc_profile:
 | 
			
		||||
            self.info["icc_profile"] = icc_profile
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,6 +24,7 @@ _handler = None
 | 
			
		|||
if str != bytes:
 | 
			
		||||
    long = int
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Install application-specific WMF image handler.
 | 
			
		||||
#
 | 
			
		||||
| 
						 | 
				
			
			@ -56,6 +57,7 @@ if hasattr(Image.core, "drawwmf"):
 | 
			
		|||
 | 
			
		||||
word = _binary.i16le
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def short(c, o=0):
 | 
			
		||||
    v = word(c, o)
 | 
			
		||||
    if v >= 32768:
 | 
			
		||||
| 
						 | 
				
			
			@ -64,6 +66,7 @@ def short(c, o=0):
 | 
			
		|||
 | 
			
		||||
dword = _binary.i32le
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# --------------------------------------------------------------------
 | 
			
		||||
# Read WMF file
 | 
			
		||||
| 
						 | 
				
			
			@ -74,6 +77,7 @@ def _accept(prefix):
 | 
			
		|||
        prefix[:4] == b"\x01\x00\x00\x00"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Image plugin for Windows metafiles.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -95,8 +99,10 @@ class WmfStubImageFile(ImageFile.StubImageFile):
 | 
			
		|||
            inch = word(s, 14)
 | 
			
		||||
 | 
			
		||||
            # get bounding box
 | 
			
		||||
            x0 = short(s, 6); y0 = short(s, 8)
 | 
			
		||||
            x1 = short(s, 10); y1 = short(s, 12)
 | 
			
		||||
            x0 = short(s, 6)
 | 
			
		||||
            y0 = short(s, 8)
 | 
			
		||||
            x1 = short(s, 10)
 | 
			
		||||
            y1 = short(s, 12)
 | 
			
		||||
 | 
			
		||||
            # normalize size to 72 dots per inch
 | 
			
		||||
            size = (x1 - x0) * 72 // inch, (y1 - y0) * 72 // inch
 | 
			
		||||
| 
						 | 
				
			
			@ -115,8 +121,10 @@ class WmfStubImageFile(ImageFile.StubImageFile):
 | 
			
		|||
            # enhanced metafile
 | 
			
		||||
 | 
			
		||||
            # get bounding box
 | 
			
		||||
            x0 = dword(s, 8); y0 = dword(s, 12)
 | 
			
		||||
            x1 = dword(s, 16); y1 = dword(s, 20)
 | 
			
		||||
            x0 = dword(s, 8)
 | 
			
		||||
            y0 = dword(s, 12)
 | 
			
		||||
            x1 = dword(s, 16)
 | 
			
		||||
            y1 = dword(s, 20)
 | 
			
		||||
 | 
			
		||||
            # get frame (in 0.01 millimeter units)
 | 
			
		||||
            frame = dword(s, 24), dword(s, 28), dword(s, 32), dword(s, 36)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,6 +30,7 @@ for r in range(8):
 | 
			
		|||
        for b in range(4):
 | 
			
		||||
            PALETTE = PALETTE + (o8((r*255)//7)+o8((g*255)//7)+o8((b*255)//3))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Image plugin for XV thumbnail images.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,9 +35,11 @@ xbm_head = re.compile(
 | 
			
		|||
    b"[\\000-\\377]*_bits\\[\\]"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _accept(prefix):
 | 
			
		||||
    return prefix.lstrip()[:7] == b"#define"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Image plugin for X11 bitmaps.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,6 +24,7 @@ else:
 | 
			
		|||
    def o8(i):
 | 
			
		||||
        return bytes((i & 255,))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Input, le = little endian, be = big endian
 | 
			
		||||
# TODO: replace with more readable struct.unpack equivalent
 | 
			
		||||
def i16le(c, o=0):
 | 
			
		||||
| 
						 | 
				
			
			@ -35,6 +36,7 @@ def i16le(c, o=0):
 | 
			
		|||
    """
 | 
			
		||||
    return i8(c[o]) | (i8(c[o+1]) << 8)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def i32le(c, o=0):
 | 
			
		||||
    """
 | 
			
		||||
    Converts a 4-bytes (32 bits) string to an integer.
 | 
			
		||||
| 
						 | 
				
			
			@ -42,24 +44,33 @@ def i32le(c, o=0):
 | 
			
		|||
    c: string containing bytes to convert
 | 
			
		||||
    o: offset of bytes to convert in string
 | 
			
		||||
    """
 | 
			
		||||
    return i8(c[o]) | (i8(c[o+1])<<8) | (i8(c[o+2])<<16) | (i8(c[o+3])<<24)
 | 
			
		||||
    return (i8(c[o]) | (i8(c[o+1]) << 8) | (i8(c[o+2]) << 16) |
 | 
			
		||||
            (i8(c[o+3]) << 24))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def i16be(c, o=0):
 | 
			
		||||
    return (i8(c[o]) << 8) | i8(c[o+1])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def i32be(c, o=0):
 | 
			
		||||
    return (i8(c[o])<<24) | (i8(c[o+1])<<16) | (i8(c[o+2])<<8) | i8(c[o+3])
 | 
			
		||||
    return ((i8(c[o]) << 24) | (i8(c[o+1]) << 16) |
 | 
			
		||||
            (i8(c[o+2]) << 8) | i8(c[o+3]))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Output, le = little endian, be = big endian
 | 
			
		||||
def o16le(i):
 | 
			
		||||
    return o8(i) + o8(i >> 8)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def o32le(i):
 | 
			
		||||
    return o8(i) + o8(i >> 8) + o8(i >> 16) + o8(i >> 24)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def o16be(i):
 | 
			
		||||
    return o8(i >> 8) + o8(i)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def o32be(i):
 | 
			
		||||
    return o8(i >> 24) + o8(i >> 16) + o8(i >> 8) + o8(i)
 | 
			
		||||
 | 
			
		||||
# End of file
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,3 @@ Pillow is the "friendly" PIL fork by `Alex Clark and Contributors <https://githu
 | 
			
		|||
 | 
			
		||||
.. image:: https://coveralls.io/repos/python-pillow/Pillow/badge.png?branch=master
 | 
			
		||||
  :target: https://coveralls.io/r/python-pillow/Pillow?branch=master
 | 
			
		||||
 | 
			
		||||
.. image:: https://landscape.io/github/python-pillow/Pillow/master/landscape.png
 | 
			
		||||
   :target: https://landscape.io/github/python-pillow/Pillow/master
 | 
			
		||||
   :alt: Code Health
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										55
									
								
								RELEASING.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,55 @@
 | 
			
		|||
# Release Checklist
 | 
			
		||||
 | 
			
		||||
## Main Release
 | 
			
		||||
 | 
			
		||||
Released quarterly.
 | 
			
		||||
 | 
			
		||||
* [ ] Get master to the appropriate code release state. [Travis CI](https://travis-ci.org/python-pillow/Pillow) should be running cleanly for all merges to master.
 | 
			
		||||
* [ ] Update version in `PIL/__init__.py`, `setup.py`, `_imaging.c`, Update date in `CHANGES.rst`.
 | 
			
		||||
* [ ] Tag and push to release branch in python-pillow repo.
 | 
			
		||||
* [ ] Upload binaries.
 | 
			
		||||
 | 
			
		||||
## Point Release
 | 
			
		||||
 | 
			
		||||
Released as required for security or installation fixes.
 | 
			
		||||
 | 
			
		||||
* [ ] Make necessary changes in master.
 | 
			
		||||
* [ ] Cherry pick individual commits. Touch up `CHANGES.rst` to reflect reality.
 | 
			
		||||
* [ ] Update version in `PIL/__init__.py`, `setup.py`, `_imaging.c`
 | 
			
		||||
* [ ] Push to release branch in personal repo. Let Travis run cleanly.
 | 
			
		||||
* [ ] Tag and push to release branch in python-pillow repo.
 | 
			
		||||
* [ ] Upload binaries.
 | 
			
		||||
 | 
			
		||||
## Embargoed Release
 | 
			
		||||
 | 
			
		||||
Security fixes that need to be pushed to the distros prior to public release.
 | 
			
		||||
 | 
			
		||||
* [ ] Prepare patch for all versions that will get a fix. Test against local installations.
 | 
			
		||||
* [ ] Commit against master, cherry pick to affected release branches.
 | 
			
		||||
* [ ] Run local test matrix on each release & Python version.
 | 
			
		||||
* [ ] Privately send to distros.
 | 
			
		||||
* [ ] Amend any commits with the CVE #
 | 
			
		||||
* [ ] On release date, tag and push to GitHub.
 | 
			
		||||
```
 | 
			
		||||
git checkout 2.5.x
 | 
			
		||||
git tag 2.5.3
 | 
			
		||||
git push origin 2.5.x
 | 
			
		||||
git push origin --tags
 | 
			
		||||
```
 | 
			
		||||
* [ ] Upload binaries
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Binary Upload Process
 | 
			
		||||
 | 
			
		||||
* [ ] Ping cgohlke for Windows binaries
 | 
			
		||||
* [ ] From a clean source directory with no extra temp files:
 | 
			
		||||
```
 | 
			
		||||
python setup.py register
 | 
			
		||||
python setup.py sdist --format=zip upload
 | 
			
		||||
python setup.py sdist upload
 | 
			
		||||
```
 | 
			
		||||
(Debian requests a tarball, everyone else would just prefer that we choose one and stick to it. So both it is)
 | 
			
		||||
* [ ] Push a commit to https://github.com/python-pillow/pillow-wheels to build OSX versions (UNDONE latest tag or specific release???)
 | 
			
		||||
* [ ] Retrieve the OS X Wheels from Rackspace files, upload to PyPi (Twine?)
 | 
			
		||||
* [ ] Grab Windows binaries, `twine upload dist/*.[whl|egg]`. Manually upload .exe installers.
 | 
			
		||||
* [ ] Announce release availability. [Twitter](https://twitter.com/pythonpillow), web.
 | 
			
		||||
| 
						 | 
				
			
			@ -6,5 +6,3 @@ import sys
 | 
			
		|||
 | 
			
		||||
if sys.maxsize < 2**32:
 | 
			
		||||
    im = Image.new('L', (999999, 999999), 0)
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
from helper import *
 | 
			
		||||
from helper import unittest, PillowTestCase, hopper
 | 
			
		||||
 | 
			
		||||
# Not running this test by default. No DOS against Travis CI.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -39,7 +39,7 @@ def timer(func, label, *args):
 | 
			
		|||
class BenchCffiAccess(PillowTestCase):
 | 
			
		||||
 | 
			
		||||
    def test_direct(self):
 | 
			
		||||
        im = lena()
 | 
			
		||||
        im = hopper()
 | 
			
		||||
        im.load()
 | 
			
		||||
        # im = Image.new( "RGB", (2000, 2000), (1, 3, 2))
 | 
			
		||||
        caccess = im.im.pixel_access(False)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,7 @@ import timeit
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
def bench(mode):
 | 
			
		||||
    im = helper.lena(mode)
 | 
			
		||||
    im = helper.hopper(mode)
 | 
			
		||||
    get = im.im.getpixel
 | 
			
		||||
    xy = 50, 50  # position shouldn't really matter
 | 
			
		||||
    t0 = timeit.default_timer()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,4 +7,5 @@ from io import BytesIO
 | 
			
		|||
if bytes is str:
 | 
			
		||||
    Image.open(BytesIO(bytes('icns\x00\x00\x00\x10hang\x00\x00\x00\x00')))
 | 
			
		||||
else:
 | 
			
		||||
    Image.open(BytesIO(bytes('icns\x00\x00\x00\x10hang\x00\x00\x00\x00', 'latin-1')))
 | 
			
		||||
    Image.open(BytesIO(bytes('icns\x00\x00\x00\x10hang\x00\x00\x00\x00',
 | 
			
		||||
                             'latin-1')))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,7 +5,9 @@ from PIL import Image
 | 
			
		|||
from io import BytesIO
 | 
			
		||||
 | 
			
		||||
if bytes is str:
 | 
			
		||||
    Image.open(BytesIO(bytes('\x00\x00\x00\x0cjP\x20\x20\x0d\x0a\x87\x0a\x00\x00\x00\x00hang')))
 | 
			
		||||
    Image.open(BytesIO(bytes(
 | 
			
		||||
        '\x00\x00\x00\x0cjP\x20\x20\x0d\x0a\x87\x0a\x00\x00\x00\x00hang')))
 | 
			
		||||
else:
 | 
			
		||||
    Image.open(BytesIO(bytes('\x00\x00\x00\x0cjP\x20\x20\x0d\x0a\x87\x0a\x00\x00\x00\x00hang', 'latin-1')))
 | 
			
		||||
 | 
			
		||||
    Image.open(BytesIO(bytes(
 | 
			
		||||
        '\x00\x00\x00\x0cjP\x20\x20\x0d\x0a\x87\x0a\x00\x00\x00\x00hang',
 | 
			
		||||
        'latin-1')))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										212
									
								
								Tests/check_jpeg_leaks.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,212 @@
 | 
			
		|||
from helper import unittest, PillowTestCase, hopper
 | 
			
		||||
from PIL import Image
 | 
			
		||||
from io import BytesIO
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
iterations = 5000
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
When run on a system without the jpeg leak fixes, the valgrind runs look like this.
 | 
			
		||||
 | 
			
		||||
NOSE_PROCESSES=0 NOSE_TIMEOUT=600 valgrind --tool=massif \
 | 
			
		||||
    python test-installed.py -s -v Tests/check_jpeg_leaks.py
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@unittest.skipIf(sys.platform.startswith('win32'), "requires Unix or MacOS")
 | 
			
		||||
class TestJpegLeaks(PillowTestCase):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
pre patch:
 | 
			
		||||
 | 
			
		||||
    MB
 | 
			
		||||
31.62^                                                                       :
 | 
			
		||||
     |                                                              @:@:@:@#::
 | 
			
		||||
     |                                                     @:@:@@:@:@:@:@:@#::
 | 
			
		||||
     |                                             ::::::::@:@:@@:@:@:@:@:@#::
 | 
			
		||||
     |                                   :::::@::::::: ::::@:@:@@:@:@:@:@:@#::
 | 
			
		||||
     |                          @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
 | 
			
		||||
     |               ::::::@::::@:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
 | 
			
		||||
     |          ::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
 | 
			
		||||
     |         :::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
 | 
			
		||||
     |        ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
 | 
			
		||||
     |        ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
 | 
			
		||||
     |      ::::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
 | 
			
		||||
     |      : ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
 | 
			
		||||
     |     @: ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
 | 
			
		||||
     |    @@: ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
 | 
			
		||||
     |   :@@: ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
 | 
			
		||||
     |   :@@: ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
 | 
			
		||||
     | :@:@@: ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
 | 
			
		||||
     | :@:@@: ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
 | 
			
		||||
     | :@:@@: ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
 | 
			
		||||
   0 +----------------------------------------------------------------------->Gi
 | 
			
		||||
     0                                                                   8.535
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
post-patch:
 | 
			
		||||
 | 
			
		||||
    MB
 | 
			
		||||
21.03^          :::@@:::@::::@@:::::::@@::::::::@::::::::::::@:::@:::::::@::::
 | 
			
		||||
     |         #:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
 | 
			
		||||
     |         #:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
 | 
			
		||||
     |        :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
 | 
			
		||||
     |        :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
 | 
			
		||||
     |        :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
 | 
			
		||||
     |      :::#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
 | 
			
		||||
     |      : :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
 | 
			
		||||
     |      : :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
 | 
			
		||||
     |     @: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
 | 
			
		||||
     |    @@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
 | 
			
		||||
     |    @@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
 | 
			
		||||
     |    @@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
 | 
			
		||||
     |   :@@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
 | 
			
		||||
     |   :@@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
 | 
			
		||||
     | :@:@@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
 | 
			
		||||
     | :@:@@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
 | 
			
		||||
     | :@:@@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
 | 
			
		||||
     | :@:@@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
 | 
			
		||||
     | :@:@@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
 | 
			
		||||
   0 +----------------------------------------------------------------------->Gi
 | 
			
		||||
     0                                                                   8.421
 | 
			
		||||
 
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def test_qtables_leak(self):
 | 
			
		||||
        im = hopper('RGB')
 | 
			
		||||
 | 
			
		||||
        standard_l_qtable = [int(s) for s in """
 | 
			
		||||
            16  11  10  16  24  40  51  61
 | 
			
		||||
            12  12  14  19  26  58  60  55
 | 
			
		||||
            14  13  16  24  40  57  69  56
 | 
			
		||||
            14  17  22  29  51  87  80  62
 | 
			
		||||
            18  22  37  56  68 109 103  77
 | 
			
		||||
            24  35  55  64  81 104 113  92
 | 
			
		||||
            49  64  78  87 103 121 120 101
 | 
			
		||||
            72  92  95  98 112 100 103  99
 | 
			
		||||
            """.split(None)]
 | 
			
		||||
 | 
			
		||||
        standard_chrominance_qtable = [int(s) for s in """
 | 
			
		||||
            17  18  24  47  99  99  99  99
 | 
			
		||||
            18  21  26  66  99  99  99  99
 | 
			
		||||
            24  26  56  99  99  99  99  99
 | 
			
		||||
            47  66  99  99  99  99  99  99
 | 
			
		||||
            99  99  99  99  99  99  99  99
 | 
			
		||||
            99  99  99  99  99  99  99  99
 | 
			
		||||
            99  99  99  99  99  99  99  99
 | 
			
		||||
            99  99  99  99  99  99  99  99
 | 
			
		||||
            """.split(None)]
 | 
			
		||||
 | 
			
		||||
        qtables = [standard_l_qtable,
 | 
			
		||||
                   standard_chrominance_qtable]
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
        for count in range(iterations):
 | 
			
		||||
            test_output = BytesIO()
 | 
			
		||||
            im.save(test_output, "JPEG", qtables=qtables)
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
pre patch:
 | 
			
		||||
 | 
			
		||||
    MB
 | 
			
		||||
177.1^                                                                       #
 | 
			
		||||
     |                                                                    @@@#
 | 
			
		||||
     |                                                                :@@@@@@#
 | 
			
		||||
     |                                                             ::::@@@@@@#
 | 
			
		||||
     |                                                         ::::::::@@@@@@#
 | 
			
		||||
     |                                                     @@::::: ::::@@@@@@#
 | 
			
		||||
     |                                                  @@@@ ::::: ::::@@@@@@#
 | 
			
		||||
     |                                               @@@@@@@ ::::: ::::@@@@@@#
 | 
			
		||||
     |                                           @@::@@@@@@@ ::::: ::::@@@@@@#
 | 
			
		||||
     |                                        @@@@ : @@@@@@@ ::::: ::::@@@@@@#
 | 
			
		||||
     |                                   @@@@@@ @@ : @@@@@@@ ::::: ::::@@@@@@#
 | 
			
		||||
     |                                @@@@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
 | 
			
		||||
     |                            @::@@ @@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
 | 
			
		||||
     |                        ::::@: @@ @@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
 | 
			
		||||
     |                     :@@: : @: @@ @@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
 | 
			
		||||
     |                ::@@::@@: : @: @@ @@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
 | 
			
		||||
     |            @@::: @ ::@@: : @: @@ @@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
 | 
			
		||||
     |         @::@ : : @ ::@@: : @: @@ @@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
 | 
			
		||||
     |      :::@: @ : : @ ::@@: : @: @@ @@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
 | 
			
		||||
     |   @@@:: @: @ : : @ ::@@: : @: @@ @@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
 | 
			
		||||
   0 +----------------------------------------------------------------------->Gi
 | 
			
		||||
     0                                                                   11.37
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
post patch:
 | 
			
		||||
 | 
			
		||||
    MB
 | 
			
		||||
21.06^        ::::::::::::::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
 | 
			
		||||
     |      ##::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
 | 
			
		||||
     |      # ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
 | 
			
		||||
     |      # ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
 | 
			
		||||
     |      # ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
 | 
			
		||||
     |     @# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
 | 
			
		||||
     |     @# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
 | 
			
		||||
     |     @# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
 | 
			
		||||
     |     @# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
 | 
			
		||||
     |    @@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
 | 
			
		||||
     |   @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
 | 
			
		||||
     |   @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
 | 
			
		||||
     |   @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
 | 
			
		||||
     |   @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
 | 
			
		||||
     |   @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
 | 
			
		||||
     | @@@@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
 | 
			
		||||
     | @ @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
 | 
			
		||||
     | @ @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
 | 
			
		||||
     | @ @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
 | 
			
		||||
     | @ @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
 | 
			
		||||
   0 +----------------------------------------------------------------------->Gi
 | 
			
		||||
     0                                                                   11.33
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
    def test_exif_leak(self):
 | 
			
		||||
        im = hopper('RGB')
 | 
			
		||||
        exif = b'12345678'*4096
 | 
			
		||||
 | 
			
		||||
        for count in range(iterations):
 | 
			
		||||
            test_output = BytesIO()
 | 
			
		||||
            im.save(test_output, "JPEG", exif=exif)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
base case:
 | 
			
		||||
    MB
 | 
			
		||||
20.99^           :::::         :::::::::::::::::::::::::::::::::::::::::::@:::
 | 
			
		||||
     |         ##: : ::::::@::::::: :::: :::: : : : : : : :::::::::::: :::@:::
 | 
			
		||||
     |         # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
 | 
			
		||||
     |         # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
 | 
			
		||||
     |         # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
 | 
			
		||||
     |       @@# : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
 | 
			
		||||
     |       @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
 | 
			
		||||
     |       @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
 | 
			
		||||
     |     @@@ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
 | 
			
		||||
     |     @ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
 | 
			
		||||
     |    @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
 | 
			
		||||
     |    @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
 | 
			
		||||
     |    @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
 | 
			
		||||
     |    @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
 | 
			
		||||
     |    @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
 | 
			
		||||
     | :@@@@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
 | 
			
		||||
     | :@ @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
 | 
			
		||||
     | :@ @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
 | 
			
		||||
     | :@ @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
 | 
			
		||||
     | :@ @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
 | 
			
		||||
   0 +----------------------------------------------------------------------->Gi
 | 
			
		||||
     0                                                                   7.882
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
    def test_base_save(self):
 | 
			
		||||
        im = hopper('RGB')
 | 
			
		||||
 | 
			
		||||
        for count in range(iterations):
 | 
			
		||||
            test_output = BytesIO()
 | 
			
		||||
            im.save(test_output, "JPEG")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    unittest.main()
 | 
			
		||||
| 
						 | 
				
			
			@ -100,7 +100,8 @@ class PillowTestCase(unittest.TestCase):
 | 
			
		|||
        ave_diff = float(diff)/(a.size[0]*a.size[1])
 | 
			
		||||
        self.assertGreaterEqual(
 | 
			
		||||
            epsilon, ave_diff,
 | 
			
		||||
            (msg or '') + " average pixel value difference %.4f > epsilon %.4f" % (
 | 
			
		||||
            (msg or '') +
 | 
			
		||||
            " average pixel value difference %.4f > epsilon %.4f" % (
 | 
			
		||||
                ave_diff, epsilon))
 | 
			
		||||
 | 
			
		||||
    def assert_warning(self, warn_class, func):
 | 
			
		||||
| 
						 | 
				
			
			@ -138,7 +139,8 @@ class PillowTestCase(unittest.TestCase):
 | 
			
		|||
        if travis is not None:
 | 
			
		||||
            skip = skip and (travis == bool(os.environ.get('TRAVIS', False)))
 | 
			
		||||
        if interpreter is not None:
 | 
			
		||||
            skip = skip and (interpreter == 'pypy' and hasattr(sys, 'pypy_version_info'))
 | 
			
		||||
            skip = skip and (interpreter == 'pypy' and
 | 
			
		||||
                             hasattr(sys, 'pypy_version_info'))
 | 
			
		||||
        if skip:
 | 
			
		||||
            self.skipTest(msg or "Known Bad Test")
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -155,7 +157,7 @@ class PillowTestCase(unittest.TestCase):
 | 
			
		|||
            raise IOError()
 | 
			
		||||
 | 
			
		||||
        outfile = self.tempfile("temp.png")
 | 
			
		||||
        if command_succeeds(['convert', f, outfile]):
 | 
			
		||||
        if command_succeeds([IMCONVERT, f, outfile]):
 | 
			
		||||
            from PIL import Image
 | 
			
		||||
            return Image.open(outfile)
 | 
			
		||||
        raise IOError()
 | 
			
		||||
| 
						 | 
				
			
			@ -200,26 +202,6 @@ def hopper(mode="RGB", cache={}):
 | 
			
		|||
    return im
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def lena(mode="RGB", cache={}):
 | 
			
		||||
    from PIL import Image
 | 
			
		||||
    im = None
 | 
			
		||||
    # FIXME: Implement caching to reduce reading from disk but so an original
 | 
			
		||||
    # copy is returned each time and the cached image isn't modified by tests
 | 
			
		||||
    # (for fast, isolated, repeatable tests).
 | 
			
		||||
    # im = cache.get(mode)
 | 
			
		||||
    if im is None:
 | 
			
		||||
        if mode == "RGB":
 | 
			
		||||
            im = Image.open("Tests/images/lena.ppm")
 | 
			
		||||
        elif mode == "F":
 | 
			
		||||
            im = lena("L").convert(mode)
 | 
			
		||||
        elif mode[:4] == "I;16":
 | 
			
		||||
            im = lena("I").convert(mode)
 | 
			
		||||
        else:
 | 
			
		||||
            im = lena("RGB").convert(mode)
 | 
			
		||||
    # cache[mode] = im
 | 
			
		||||
    return im
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def command_succeeds(cmd):
 | 
			
		||||
    """
 | 
			
		||||
    Runs the command, which must be a list of strings. Returns True if the
 | 
			
		||||
| 
						 | 
				
			
			@ -249,6 +231,14 @@ def netpbm_available():
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
def imagemagick_available():
 | 
			
		||||
    return command_succeeds(['convert', '-version'])
 | 
			
		||||
    return IMCONVERT and command_succeeds([IMCONVERT, '-version'])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if sys.platform == 'win32':
 | 
			
		||||
    IMCONVERT = os.environ.get('MAGICK_HOME', '')
 | 
			
		||||
    if IMCONVERT:
 | 
			
		||||
        IMCONVERT = os.path.join(IMCONVERT, 'convert.exe')
 | 
			
		||||
else:
 | 
			
		||||
    IMCONVERT = 'convert'
 | 
			
		||||
 | 
			
		||||
# End of file
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										25
									
								
								Tests/icc/LICENSE.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
from http://www.color.org/srgbprofiles.xalter
 | 
			
		||||
 | 
			
		||||
Terms of use
 | 
			
		||||
 | 
			
		||||
To anyone who acknowledges that the file "sRGB_v4_ICC_preference.icc"
 | 
			
		||||
is provided "AS IS" WITH NO EXPRESS OR IMPLIED WARRANTY, permission
 | 
			
		||||
to use, copy and distribute this file for any purpose is hereby
 | 
			
		||||
granted without fee, provided that the file is not changed including
 | 
			
		||||
the ICC copyright notice tag, and that the name of ICC shall not be
 | 
			
		||||
used in advertising or publicity pertaining to distribution of the
 | 
			
		||||
software without specific, written prior permission. ICC makes no
 | 
			
		||||
representations about the suitability of this software for any
 | 
			
		||||
purpose.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
To anyone who acknowledges that the file
 | 
			
		||||
"sRGB_IEC61966-2-1_blackscaled.icc" is provided "AS IS" WITH NO
 | 
			
		||||
EXPRESS OR IMPLIED WARRANTY, permission to use, copy and distribute
 | 
			
		||||
these file for any purpose is hereby granted without fee, provided
 | 
			
		||||
that the file is not changed including the ICC copyright notice tag,
 | 
			
		||||
and that the name of ICC shall not be used in advertising or publicity
 | 
			
		||||
pertaining to distribution of the software without specific, written
 | 
			
		||||
prior permission. ICC makes no representations about the suitability
 | 
			
		||||
of this software for any purpose.
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								Tests/icc/sRGB_v4_ICC_preference.icc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								Tests/images/hopper.Lab.tif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								Tests/images/hopper.fli
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.4 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								Tests/images/hopper.psd
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								Tests/images/hopper.tif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								Tests/images/hopper.webp
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 3.2 KiB  | 
							
								
								
									
										178
									
								
								Tests/images/hopper.xpm
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,178 @@
 | 
			
		|||
/* XPM */
 | 
			
		||||
static char *hopper[] = {
 | 
			
		||||
/* columns rows colors chars-per-pixel */
 | 
			
		||||
"128 128 44 1 ",
 | 
			
		||||
"  c #110E13",
 | 
			
		||||
". c #2A1110",
 | 
			
		||||
"X c #13122C",
 | 
			
		||||
"o c #25192A",
 | 
			
		||||
"O c #312831",
 | 
			
		||||
"+ c #302219",
 | 
			
		||||
"@ c #5F241A",
 | 
			
		||||
"# c #6F4832",
 | 
			
		||||
"$ c #17174A",
 | 
			
		||||
"% c #26264F",
 | 
			
		||||
"& c #65595D",
 | 
			
		||||
"* c #4B3C54",
 | 
			
		||||
"= c #8E1F1A",
 | 
			
		||||
"- c #914E33",
 | 
			
		||||
"; c #A75335",
 | 
			
		||||
": c #AC6736",
 | 
			
		||||
"> c #B26F4E",
 | 
			
		||||
", c #9B6657",
 | 
			
		||||
"< c #CA7652",
 | 
			
		||||
"1 c #CC7866",
 | 
			
		||||
"2 c #C25135",
 | 
			
		||||
"3 c #B0896D",
 | 
			
		||||
"4 c #D28859",
 | 
			
		||||
"5 c #D28E6D",
 | 
			
		||||
"6 c #E79371",
 | 
			
		||||
"7 c #E5A36E",
 | 
			
		||||
"8 c #D58932",
 | 
			
		||||
"9 c #3E65AE",
 | 
			
		||||
"0 c #4970B5",
 | 
			
		||||
"q c #606D95",
 | 
			
		||||
"w c #557CC1",
 | 
			
		||||
"e c #91778A",
 | 
			
		||||
"r c #6A86B9",
 | 
			
		||||
"t c #5C83C3",
 | 
			
		||||
"y c #6D8FCA",
 | 
			
		||||
"u c #7799E3",
 | 
			
		||||
"i c #A89A9D",
 | 
			
		||||
"p c #CFAA90",
 | 
			
		||||
"a c #F4B08F",
 | 
			
		||||
"s c #D6A799",
 | 
			
		||||
"d c #ECCCAB",
 | 
			
		||||
"f c #F9F4F4",
 | 
			
		||||
"g c #E3D8D5",
 | 
			
		||||
"h c #AAAECA",
 | 
			
		||||
/* pixels */
 | 
			
		||||
"$XX$$XXX$%$$$$$$$$$$$$$$$$$$$egip3dr %% @p# Oqgffgfgfgo%q999q9999999999999999999099999099099990999999909909990w999000wwww00w00w0",
 | 
			
		||||
"$$X$X$XX$$$$$$$$9$$$$XX$$$$$$ws&7+O&%$Xo@3#XXX&ihffggg%%9q*9*%q99qq9q99999999999999090900909909909099999999999999999000wwwwww0ww",
 | 
			
		||||
"X$X$$XXX$$$$$$$$$$$$$$$$$$$$$eq@i#+$$$%X#pOX$%$%*dfffgiX%%OX%XO*%**990909999999009090990900999999099990999w999990990000wwwwwwwww",
 | 
			
		||||
"$XX$$$XX$$$$$$$$$$$$XX$$$$$$$*O*7#XX%$%X@p*XX$%Xohfi3hOXOoX*r3*OOO%O99099999q0q990990009090909000999090999999099909999ww0w0000w0",
 | 
			
		||||
"$XX$$XXX$$$$$$$$$9$$$$$$$$$$o$.&3++X$$$o#p+X$$%$OhgOX oo+ii*if&+ri&OO%q0990099009090090990909009990999099w999990999090w0000w0ww0",
 | 
			
		||||
"X$X$$XXX$$$$$$$$$$$$$$$$$$$$$oX#p#OO%$$o#7O%X$$XOg&O o.&fffgifirfffiOO*&qq990990000000009909099000990990999990999w90099000000000",
 | 
			
		||||
"XX$$$XXX$$$$$$$$$$$$$$$$$$$$$oo*3+o$$%$.#7+X$%XOOhii+X,fgifffffffddfgOOrhi0qq000090000090099990909909009w9w9909990999099900000w0",
 | 
			
		||||
"X$X$$$XX$$$$$%$$$$$$X$X$$$$$X$X#7@X$$$$o:3+XX$OqgffrXOe&&#*&iggi&&3&*&OOfffgrq900009000099099090000909009999990999900900000000w0",
 | 
			
		||||
"X$q$XXXX$$$X%$$$$$$$X$$$$$$$$$X*p+O$%$$o-3oOX%gffff&o++3pgg3fddd3fdg&+OOhffffgt0099090090009090990909990999990999000099090090000",
 | 
			
		||||
"X$g&$XXX%$X$%$$$$$$$$$X$$$$$$$o*p+X%$%$X,5+ *gfffff& ++&pddffffffgdd#OOOiffffffhq9qt009w990090900999w9w9900999w90999909009900000",
 | 
			
		||||
"X$ggO  %$$$X$%$$$$$$$$$$$$$$$Xo*3#$$%%$X,3+&ffffffg#+.+Odddgggggggpd*+OOifffffffgtqt09t909090990090909099990099w0990090909090000",
 | 
			
		||||
"X%hfr&h&$$$$%q$X$$$$XXX$$$$$Xoo*p@o$$$$X:3OffffgppdO. ++,ddfffffffd3+ ++&ffffffffgq900909090900999099090w9w990990009009090009900",
 | 
			
		||||
"Xohfffh&X$o$$h&$$$$$$$X$$$$$Xo$*7# %%$$ 35dffg73&#++++ +pd3gfffffg3d,++++3ddffffffhq90009099990999909090990909w99990099900900000",
 | 
			
		||||
"oegffgiO$$$$$gh$$%&qXXXX$%XX$X.*3# X%X$+#pgfd3&+.  +  ++3iddgfffddpd&+O++++#pgfffffrq9900900q99090909990099009990009990999090000",
 | 
			
		||||
"hffffg&X$%$X$gg*&hg*XXXX%i%$$Xo*5#XX$$$o,dfg&+.. .#&++ +&ddd3gfgdddd#++++&+++#3dfgghq009099090000909090990999090909000099000000w",
 | 
			
		||||
"hgffffp*X$X%Ogggfgh$XXX$%g*XXooO5#o$%$$+&df3...&#++3 O#+#pd7di&,ppdd&+++#3+&&..#iffgqq009009009909900990090009990009999009990000",
 | 
			
		||||
"o%qffgh&o%o*iffgfg%%X$XX*gi OqO*p#+$%$XO&h3 . +pdpp3pdgdd3#+++++++#ppggpp3ddp+##+ifghqrq09090090090090900909999009009w900009w0w9",
 | 
			
		||||
"Xo*fh**%$%igfgfgg&%$$X$X&ggih3o+p# X%X$XX     .+33+pdppdddfp,#+O&dfggdddd3pdddd+++dh&%%&q0090909009909090090000900w000w99w0900ww",
 | 
			
		||||
"X%&fq%oX$%&hgfffgi%oXXX &fgshOoO3#+X%%XX+      . +#&++7dp3&#O&O&#&33dd3#3&.+#ppiiO#+  X%9909000909099090090900009w9w009ww9ww9w00",
 | 
			
		||||
"X$%g*o$XX%Xo*gffffq$X%&egfhp&oXO7# XXX          +   #++.+++ +..O+ ++O++#ppp+++&3++  o XXq9000900009000090009000009w909w09w00w00w",
 | 
			
		||||
"$$*i$$oX$XoX%hfeegg%$%&idggh+X$O4#+XOX             + .    + ..o + + ++ +&3gg#.         X999909000000000000009000000000w09w0www0w",
 | 
			
		||||
"$$%%$$$X$$o$$hh*$$q&$o o3ggd,ooo3#+                    ++          +++ ++*++           X%0q9q900000ww000000000000ww99w00w9w99ww0",
 | 
			
		||||
"$$$$%%X$$$X$%g0$$%%%oX .&fshg*Xo3: X                      +          +                 X*0000000000w000000000w00000ww0www90wwww0",
 | 
			
		||||
"$%$$%$$XX$$X%h$%$%$$XXX qg*XiqXo3:+                                                     %0q0000000w00000w0ww000w0ww990009w0w99ww",
 | 
			
		||||
"$$$%%%$$$XX$$%%$%$$$XXXXihXXX%X.,:                                                      %t000t90w0w0000090w00w00009w000wwww9www9",
 | 
			
		||||
"$$$$$%X$X$$$$%$$$$$$XXXXq*XXXXXo3:                                    .                 %0q0000t0w0ww00ww00ww00ww0w9w0w0w99ww9ww",
 | 
			
		||||
"$$$$$$$XX$X$$$$$$$$$$XXX*$$XXXX :>                                                      %q0t0t00w0w0w0w00ww0w0w0w00w0w0www90w09w",
 | 
			
		||||
"$$$$$$XX$$XX$$$$%$$$$XXX$$$$XXX.:3.            .     .  ....   .. . .......            X%qw000t00www0wwwwwww0ww0www0w00w00w09w9w",
 | 
			
		||||
"$$$$%%$$$XX$$$$$$$$$XXXX$$$$XXX -3           . ....+@@@@@@.@@....@@@@#####*@..          %ttt9ttt0t0tw0www0ww0ww00w9ww0w09w9www0w",
 | 
			
		||||
"$$$%$%$$X$$$$$$$%%9$XXXX$$$$XXX :3           ...#->1>>1,>>,,--;,--,,,1531>13>#@.        X09q9r00t0t0wwwww0w0wwwwwwww0wwwwww0w00w",
 | 
			
		||||
"$$$$$$XXX$$$$$$$$$$$XX X$$$$$XX.::           .#11ss65assa56a511155557a775555p5,,.       Xqttr0trt0wtwwwwww0ww0wwwwww0wwwww0ww0ww",
 | 
			
		||||
"$$$$$$$X$$$$9$9$$$$$XXXXX$$$XX$ >;.      ...#,pps55paaaaasadasaaaaaaaaa777a77p53,*...   Xt0tq9t0ttwww0wwwwwwww0wwww0wwww0wwwwwww",
 | 
			
		||||
"*o$%$%$XX$$$$$$$%$$$$XXXX$$$$XXX,>      +#*-,5pp7apasaadddaaaaddadaaadddaaa6pp733,##.   Xqrtttttt0t0rt0tt000t0t0t0t00t0t0ttt0ttt",
 | 
			
		||||
"go%$$*%$XXX$$$$$$$$$$X XX$$$$XX :>     .&,#,5p77p7aaaaadaaadaddaaadaaaasaapp7775534#@   Xr90tq0ttt0tt0ttt0ttttt00tttt0tt0t0tttt0",
 | 
			
		||||
"fio%whXXX%$$$$$$$$$$$XXX$$$$X$X.,8.   o###-155pppadaasasaaadaaaaaaaaa51>3355455535>>#+  %t0r0r0rttt00tt0ttttttt0tttttt0ttttttttt",
 | 
			
		||||
"gg&gf&X *qo$$$$$$$$$$X X$$$$$XX 3:    OO##,135565431>113sadaaaddsss611>1>>55s5355333,*+ %rr0r0ttt0tttttrtt0ttqttt0ttttttttt0tttt",
 | 
			
		||||
"gffghOXX*g*$$$%$$$$$XXXX$$$$XXX ->    +###,>3575p5<><355saaaaaaaap615>;;-;>5a7p335333#+ %rrtttt0t0trtttttttttttttttttttttttttttt",
 | 
			
		||||
"fgfg&oo &giO$qi%X$$$XX XX$$$XX .::+  +#,,,3355p55>>;;;,>16s777aaas61>;=--@#@@@@##&##&&+X*rrtttttttt0tttttttttttttttttttttttttttt",
 | 
			
		||||
"gggg&o  &gg,sfe$X$$$$X XX$$$XXX ::   +&#-,,35333>>,-,-,>>15apaadap1>>;@@@#;-##@+,&@##&O+&rttttt0ttttttt0tttttttttttttttttttttttt",
 | 
			
		||||
"gffgg*oX&gfggh%X$X$$XX  X%%XXX  3:+ ++3:-####@@.@..@++@@->6aaaaaa74>=@,3,11335d&+@+O*&##qrrttttytttttttrtttttttttttttttttttttttt",
 | 
			
		||||
"sggggho*dgggg&O$$$$$ *+Oii$X X .::+++&,-##+@+@@:ss1,1i1--=:4a77764::a1,@@@@=,,4d#+##*&,-eqyrwyrwttttttttttttttytytttytytttyttttt",
 | 
			
		||||
"id**qi&Ogggdd+X$$$$$o*&eh*X XXX.::.O#,>-#@...+,,,-@@@@-5><<<76748:2<>-@#.@@@@=-@##@@+#,isiryywyyrttrttttyttytytttttytttttttttytu",
 | 
			
		||||
",hO%X$Xo&gggg&O$$$$XoO,e&OXXXXX.3:.@33;#+@@@.-,>-@.@..@=::;<4<4<:28<2@#@.@@@@==-,-##-,1,eheywyywyttttyytytyttttttyttttttttytyttt",
 | 
			
		||||
"i&o$$X  Ogggfg%X$$$$oO,&+ XX  X :3+@3,,;##@#@##,@@@..@-;==;426a76<<<;>;--#==;;::4>4>:;:==1ryewywttyrtytttytyytyyttyttuytyttyttyt",
 | 
			
		||||
"**%$$$XX+hiO&h&%$$$XX*,,& XXX X ::+#1-#-;,,>,#-==#=#;-;<4444;6ad7<661<<11>2;2<<<445<>:<<@,ryytytyytyyttyyttytyttytyttyttyttyuytt",
 | 
			
		||||
"%X$$$$X Og*o%$*X$$$$X*&&i* XXXX :3.#,=;>,-35:-#===:4s51446a6;6aaa6661<66aaa6<664445>:15<-,ewyytyytytyyytyyytytytytyyytyyttuttttu",
 | 
			
		||||
"X$$$$XXXOi$$$$$X$$$XXX.o&qXo X .>>.#-@>;-:<6:<;==2<66a6<<6a<<aaaa7<a76167661<665655326a1-1ityytyyytytyyyyyyyyytyyttuyyyyytutyyyt",
 | 
			
		||||
"$XX$$XX %%$$$$$X$%$$X   ooX$XXX -8.@,=11>-:44:<82<<11<<<aa621addad167aa4<8<2<<7545511:66;eqrryytytyyyytyyttyytytyytttyttyytyttyy",
 | 
			
		||||
"X$$$$XXXXX$$$$$$$$X$X  XXXXXXXX :3.+>=54;;<<<<1<;2<<<1aada6:7adadd74aaadaa6446764444;=>s,eitryyyyyyyyyyyyttyyyyyyyytyyttyttutytu",
 | 
			
		||||
"XX$$$XXXX$$$$XX$$$$$XXXXXX$X$X .::.@,;6<-;<<1<4::46aadddaa46aadddad66aaaaaa7a76564>4<-;51eryyttyyyttryytyyyyyryrtuyytyyyyyyttytt",
 | 
			
		||||
"X$$$$XX XX$$$$X$$$XXXXX XXXXXXX :8+ia>44;;<<<44<;87dadddda<aaadddaaa1saadaa676444>>5a221eiiwtyyyyyyyyyyyyyyyyyyytyytytyytttytuyy",
 | 
			
		||||
"$X$X$X XX$X$$X$$$$$XX XX$XX$XX  #73pda6<>56>2<44<26addaa6>:6adaaadda2;16666a7a6<4>47a1<1ieyyyyytyyytyyyyyyryyyyyyyyytutyyuyyytyy",
 | 
			
		||||
"X$$$XX  XX$$$XX$$$$XXXX XXXXXX  :75ps565577>:<:46<<1aa11;;6aaadddaada<2>2;<6676<<435a1>5eiyytyyyyyyyyyyyyytyyyyyyyyyyyyyyytyyuty",
 | 
			
		||||
"XX$$$XX XX$$$$$$$$X$XXXXXXXXX X3773sdp565p742<:<61<2;2;2=<66aaaaadaaa1>6a66a665<5>456>15ewyyyyyyyytyyyyyyyyyyyyytyytyyyyytuyyttu",
 | 
			
		||||
"$$$XXX  X$$$$$X$$$XXXXXXXXXX  &pp73dd357577<<:>481611612;661a1saas6111;21aa664444>56<163iyyytyyyyyyyyyyyyyyyyryyutyyyyyyyyyyyyyy",
 | 
			
		||||
"$X$$XX  XX$$X$$$$XXXXXXXXXX  *ip773ss345775<<<848111aa1;=;-=><1511;;====116166165>4>6615rtyyyyyyyyyyyyyyyyyyyyyyyyyyyyytyyyyytuy",
 | 
			
		||||
"X$$X$X  XX$$$XX$X$XXXXX X XX*ipp773dd33783::<<<4<<6664;=6<@===-==#;=;1;@21<<646655>>>>6iryyyryyyyyyyyyyyyyyyyyywyryyyyyyyyyyyutu",
 | 
			
		||||
"XXX$XX  X$$$$$$X$XXXX  XXXX&iipp783pp33735771<<46<644<=<66641,-@@:41112==2<4<44545a775piiyyyyyryyyyyyyyyyyyywyyyyyywyyyytyyyutyy",
 | 
			
		||||
"XX$*XX XX$$$$$$$$XXXXXXX oriipsp784dp333a7p761446<442=2661666611<6161<1<@=;2<46555aa5ppqryyyyrryryyyyyyyyyyyyyryywyywyywuytyyyyy",
 | 
			
		||||
"*oe*XX  XXXXX$XXX$XXX  Xoiihhisp774ppp837a7dp>4464<<2=<16666666666116661===;<1<445a77p3iryyyyyyyyyyyyyyyyyryyyyyyyyyyyyytyyyyyyy",
 | 
			
		||||
"iiiXXXX  XXXXX$XX$X X o@iihishpp788dpp#:7p7a,3447842=;166aaa6aaaaaa16666<;=;<<4643ap33iirryyyryyryyyyyyyyyyryyyyyyyyyyyytyyttyyy",
 | 
			
		||||
"di&o o  %*%XXXX$XXXX  Oeiishippp773dd3:#:57>.-47664;@8<61a6a1aaaaaa676a11<=<<6548->53iirrryyyyyyyyyyyyyyyyyyyryyyrryyywyyyyyutuy",
 | 
			
		||||
"ppO.oX *q&XXXXXX$XXX..@,eshsipdp783pp3:##:,@.#:4474<:<<11<>1<1661<21<<<6<6;166643##,7irrryyyyyyyyyyyyyryyyyyywyyyryrywtyyyyyyyty",
 | 
			
		||||
"di*+X. *&OoXXXXXXX$ .o@&,sshsiip377pd3,##:3,@@4466718<<<2=====22=2===-=;2<6676158##333iryyyyytyyyyyyyyyyyyyyyyyyyyyyyyyyytytyyyy",
 | 
			
		||||
"gge.   *OoXXXXXXXXXX..@@,3shsipp778dp3,-@@@@+@-46667<22==;22,22=2111<6<<<<8677453##33iriyyyyyyyyyyyyyyyyyyyyyyyryyyyytyyyyyyyyyy",
 | 
			
		||||
"esi*   &*XXXXXXXXXX .@@=;ppssppp77377:-:@+.+++-446774<<<1116666aa16a61<66<6766558#,3ihrryyyyyyyyyyyyyyyyyyyrryyyyyyyyyytytyyyyyy",
 | 
			
		||||
"&.&eo oi& XXX$XXXXXX.@@@=ishhpsp873p3,:28@@.@+=4<4774868<1116aa6a611<88668664453##&3iryyyyyyyyhyyyyyyyyyyyyyyyyyyyryyyyyytyyyyyy",
 | 
			
		||||
"oXXo XX&eXXXXX XXXXX..=@@1ssipsp875p3::888:@.@@;44464<68<<2112;;;22<<6664<16443>##3iiryhuyyyyyyyyyyyyryyryyyyrryyyyyyryyyyyyyyyy",
 | 
			
		||||
"XXXXX  X&OXXXXXXXX  .@@===6ssis577377>::88882@@-:<<68<66611<2;;;2=;:<<<<644<<<5-#3&3iyhyyyyyyyyyyyyyyyyyyyyyyyyyryyyyyryyyyyyyyy",
 | 
			
		||||
"XXXX X  %OoXXXXXXXX..@=@=@1ssis578377:::82822;@;:4<8244<8<1<46a56144<<<656<6<<1#&eerryryyyyyyuyyyyyyyyyyyyyyyyyyyyyyyyyytytytyty",
 | 
			
		||||
"XXXXX    XXXXXXXXX..@=@====sspp578877:8228282;=;<<><46666666aaaaaa66777a5<4<1,i-&3riryyyyyyyyyuyyyyyyyyyyyyyyyyyyyyyyyryyyyyyyyy",
 | 
			
		||||
"X$XXX    XXXXXX  ..@@==@===1ppp5878p8222828282==<:<<6<<<84667aaaa6aa777744<;113,eiryyyyyyyyyyuyuyhyyyiyyyyyyyyyyyyyyyyyyyytyyyyy",
 | 
			
		||||
"XXXXX   XXXXXX X .@===@=====1ap387838:8:282822=@>4:>44>44644666a66aaa744>>:::>3,erryyuuyyyyyyyyhyyyyyyuyyyyyyyyyyyyyyytyyyyyyuty",
 | 
			
		||||
"XXXX     XXXXXXXo@@@===@@===11s>87888:8:828828@-p4;::<:<44<4446455656548>#---33Oirryyuyyyyyyuyyuyyyyyyyyhyyyyhyyyuyyyyuyyytuyyyy",
 | 
			
		||||
"XXXXX   XXXXXX .@@==========;1s187882;8:28888=+sp1,-=;-:<<444<<><141<<:;=@@=>p,XOrryuuuyyyyyyyyyhyyyyyyyyyyyyyyyyyyyyyyyyyytyyyy",
 | 
			
		||||
"XXXX X   XXXX .@@======@===@=1118788:;8:8288;.+d151-@@@@;:>2:---;,,-;--#@@@:333 ++qyyyyuyyyyyyyyyyuyyyuyyyyyyyyyuyyyyyyyyyyyutuy",
 | 
			
		||||
"XXXXX  XXXXX..@@=======@==@==>5<8788:;8:8:8:..&d,35>-@@@@-@@@@@@@@@@@@==@@,55p,   Xqyyyyyyyyyhyyyyyyyyyyyyyyyyyyyyyuyyyyyyuttyyy",
 | 
			
		||||
"$XXX     o...@@=========@====262888:;-82::-.. ip#513:=@@@@@..@......@@---;1>53,    Xqhyyhyyyyuyyyyyhyuyhhuuyhyyyyyyyyyyyyyyyyuyy",
 | 
			
		||||
"XXXXX   oXoO@@@=======@=@=====s;878:=-:-;@..  hp@74>:---##@@......@@#-,--,<51p3     +Oryyuhuyyyyyyyyyyyyyyuyyyyyyyyyyuyyyyuyyyyy",
 | 
			
		||||
"XXXX X  .o**==========@@@=@===1;878:;-:#..    gd@54>3:-:--@@@.....@@-;--;<>13d&  +   +O&ryyyyhyuyuyyyuyyyyyyyyyyyuyyyyyuyyyyyyyu",
 | 
			
		||||
"XXXXX   .&h1@=========@@@=====2;778:@@.       hd@343<;;;,--@@@@O@@@#;;-->1>5pg&X        X%qyyyyyyyyyuyyyuyyyyyyyyyuyuyyyyyyyyyyy",
 | 
			
		||||
"XXXXX  Xisi1;===@======@@=====>>88#+          gg#,5>:>:-;---@@@@@@=-;;-;<>53df&          X X&ryyyyyyyyuhyuyhyhyyyyhyyyuyyyyyyyyy",
 | 
			
		||||
"XXXX   &idi31=========@@@=@==@=. +            dg+-51<:;;;-#==#@#---->;-:>>5dff&           XXXX*rhyyhuyyyyyyuyyyuyyyyyuyyhyyyyyyy",
 | 
			
		||||
"X XX  +iipi3s2==@======@@@=@@..               df@#55<>:>,---#=#-;=-;;;:>>35gggO          X XXX$XOqrhyyyyhuyuyyyyyyyuuyuyyyyyyyuy",
 | 
			
		||||
"X X  X+pssiiss2======@.......                 igs@>1<>::>;-----;;;;;>;>>3>dffg .            XX XO %qyyyyyyyhhyyuuyyyuyyuyyyyhyyy",
 | 
			
		||||
"XXX   .iissshss===@@... ..                    egf,-1<:<:>:----;>;;;>:;;>>5ggfs             X  XO+OX O*qiyyyyyyyyyyuyuyyuyyyyyyyy",
 | 
			
		||||
"XXXX  .ppssssdg,......                        &gfd@>4::>>>----;;;;;>>;>>,gfggq             X+    X XXXOOO9rryyyyhyyyyyyyuyyyyyyy",
 | 
			
		||||
"XXX X .iphhshhsO                             X&gff,#><>:>;;---;>;2;>::--pgfgf*           o   ++ + X XXX++O++%&ryyyhyyuyyyyyyyyyy",
 | 
			
		||||
"XXXX  +3pdphi3                                *ggfg#-><;:>:-;=;-;;;>;-#3gfgfg                X+XX +X  XXXXXXXXX%qyhyyyyyyuyyyyyy",
 | 
			
		||||
"XXX    iphi++                                 %ggffd-><><3---@----;>:@,gfffgi.              +XX X+X X+ XXXoXXXXXX%qyyrhryyuyyyyy",
 | 
			
		||||
"XXXX.  pdi+      .                            Ogffffg;>1<>:-;@---=2,-,gffffgO            XXXX X  +X++X+X+  X+X XXX%%riryyyuyyyyy",
 | 
			
		||||
" X X  .ih&                                     hgffffd-56>::-=--#->,-dfffffg                X XXX  X  + X+o  X+XOXXXX%ryyyyyyyyy",
 | 
			
		||||
" o X   ii +                                    *ggffffp:553>;-,--,>#gffffffr               XX  X XX+X+ Xo o+   OXo XXX%yyyyyyyyy",
 | 
			
		||||
"O o    i&                                      +ggfffff3,555>,3>,1,gfffffffO               o+XXXX XXX  X o XoXX   +XXX$ryuyyuyyy",
 | 
			
		||||
",.     3+.                                      qgffffff3>531>1>13gfffffffh   .         X     X++XX +X+XX X X X + +  X$*yyyuyyyy",
 | 
			
		||||
"iO     &                                       o&gfffffff35pddddsiffffffff&                X X XXXX X X  o X X X    X XXrhyyytyy",
 | 
			
		||||
"si  .  O                                        ogfffffffffgfdhpO Ogfffffg ++  +        X  X+XX+  +X X+  X X XX   X    Xrryuyyry",
 | 
			
		||||
"si#  ...                                        Xifffffffe**O+o ++ OgffffqX      +X   OX +X X  X+X XX  X+ X        X   X&yyyyyyy",
 | 
			
		||||
"ssi@                                             &ffffffq+ +   +  o OgffgOX  +  X++ X++  OX+    XX+XXXXXXXX XX X   X   X$yyyyyyy",
 | 
			
		||||
"sip&....                                         &gffff&    +o  +    %gfr  +  +    X  X X  X+XX+X X +X+ +X X     X     X$yyyyyyy",
 | 
			
		||||
"pisi+. .                                         +hfff&X     +    +   &gO     X  X+  X+XO+X +   X X  X XX o  XX X X     Xqryryuy",
 | 
			
		||||
"ppp3#.                                           +eff& o             + *+ + + + +  XX    X OXXX  X +X X+ X XX   X        Xhyyyyu",
 | 
			
		||||
"ppi3,.                                           X*fq               X + + O    + ++ X++XX+X X  X+XXXX+ Xo X  X X        XXrrhyyy",
 | 
			
		||||
"p5pi,..                                           O&              +  +XX X   +    X   X  X O+X  X  X  X  X  X X  XX      X*yryyu",
 | 
			
		||||
"p5pi3o                                            o     +   X  o+OO   X X +X+  X+  + +X X o o     X  X+ XX   X  X        XXryyuy",
 | 
			
		||||
"spp3,.                                            X        riggggghy+    +  + +  X+ X  Xo  XXo+X X   X X+  X X X  X       Xqyyyu",
 | 
			
		||||
"ppi3, .                                          X   O+   &gfffffffg&+       +  +X      X X +X o +X    X+ X                qiyyu",
 | 
			
		||||
"6pp3,.                                             X     +hgfffffffgqX o  +XX  +    X  X  ooX   X X   X X X  X   X         %yyyu",
 | 
			
		||||
"pp5i,                                              X+ +X &gffffffffgO  X  X  + ++ +   X  oX X         X      XX            Xyhyy",
 | 
			
		||||
"ppi3# .                                             +X  Ohgfffffffgi+ +  ++ X X  X  +X +X  o X   XX      XX           X    Xryyu",
 | 
			
		||||
"p5ii#                                                  Oigffffffffg*  X  X+X ++XX+ + +XXXoX     XX  X X  X                 Xryyu",
 | 
			
		||||
"5pp1*.                                          X +XX Oiggfffffffhh OO  X+ +    + X+XX +.X X   o+  X   XX    X             X&uyy",
 | 
			
		||||
"5pp3@               X                             +XX ihffffffffgh#oX   X+O  +  X     X o o       X  X XX             X    X*uuu",
 | 
			
		||||
"p3pi.                 +                             X+eggffffffgiqO  +X++X        oo o +  . ooo + X                      X X%uuu",
 | 
			
		||||
"p53p.             &ii&&&&#O+ +                   +   O*hgfffffgi&O   X o O   ++  oo     .o.o$OO% .  X   X                 X $hyu",
 | 
			
		||||
"p5i3.             3hfffi3rihhhii3r&&               X  oihffffgi&&XXoX+X X  O+ X  ooooo+*@*=#=*=*&,   X .               XX  X$hyu",
 | 
			
		||||
"p5i3             .idffg&iiiiphhddhip&              Xo  &hgffgi&&* o X  oX X X X oXX o.Oe,22,,2112s%oXX .                 X  Xryy",
 | 
			
		||||
"5ii,.            Oihgggiiiihhphhhiihi*          X X  XXOhdggh&ii XX O XXX+X+X+X+ oo .ooe,=222e22eso.o$...  .               XXryy",
 | 
			
		||||
"p3p#             Opgghfiiihgggdgghhhhi*              oX ehgheid*XXoXXX X+ XX+X+ X ..&ieeq*1ee,eeee&,e=2=#--&*             X Xquh",
 | 
			
		||||
"pppO             *rpggiqqiiiiihiphpphiio           OX o.&gsieii.     X+ XX+X +   .@&ifseeeheeeeehq,de122=17i*. .            X*yu",
 | 
			
		||||
"p3p. .           O&&q&&iiiiiihihihiiiii          X X   + hp&&3O X    + X+  + + +.@=,sgh1e,heeesqhe,s11222221&%    +      X+ X%uu",
 | 
			
		||||
"ppi.                .   +oO*&&e&i,iiiiiX           XX X  &i**&    +  X + XX X  +@-,2212eeieqee,,ee*,22222222@o       X X    X%hu",
 | 
			
		||||
"ii,.                               .XoO                  +&OO+     XX   ++ +..+@>6a5=2,eih*ihf*&hie=22222==1o       +   X  XXOyy",
 | 
			
		||||
"5p,.                                                X     +**         X +X  ..*-375522=eigqeig&,ie,222222=2<oo   X   X     X Xyh",
 | 
			
		||||
"5i#                                                     +  O+    +     XX  oo.@O##O@@@@O**oo+*+OOO..@@....@.       X  XXX  XXXuy",
 | 
			
		||||
"ip#                                                          X        o     .oo....+..ooo.XooX Xoo..oo..+..            X  +  Xrh",
 | 
			
		||||
"p3@                                                           +    X oXoX     .oo .oXo .oo  .oo o .oo  X  + +    X X X X    XXqy",
 | 
			
		||||
"pi@                                                    X        XX +o+     X  X  XXX XX.. XOoX X oo   X X      +      X X   XX&y"
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								Tests/images/hopper_bw_500.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 16 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								Tests/images/hopper_g4.tif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								Tests/images/hopper_g4_500.tif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								Tests/images/hopper_gray.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 5.2 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								Tests/images/hopper_webp_bits.ppm
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 28 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								Tests/images/hopper_webp_write.ppm
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 Before Width: | Height: | Size: 4.7 KiB  | 
| 
		 Before Width: | Height: | Size: 3.8 KiB  | 
| 
						 | 
				
			
			@ -1,175 +0,0 @@
 | 
			
		|||
/* XPM */
 | 
			
		||||
static char * lena_xpm[] = {
 | 
			
		||||
"128 128 44 1",
 | 
			
		||||
" 	c None",
 | 
			
		||||
".	c #CC9966",
 | 
			
		||||
"+	c #663333",
 | 
			
		||||
"@	c #996666",
 | 
			
		||||
"#	c #CC6666",
 | 
			
		||||
"$	c #CC9999",
 | 
			
		||||
"%	c #FFCC99",
 | 
			
		||||
"&	c #996633",
 | 
			
		||||
"*	c #FF9966",
 | 
			
		||||
"=	c #663366",
 | 
			
		||||
"-	c #FFCCCC",
 | 
			
		||||
";	c #CCCC99",
 | 
			
		||||
">	c #FF9999",
 | 
			
		||||
",	c #993333",
 | 
			
		||||
"'	c #333333",
 | 
			
		||||
")	c #CCCCCC",
 | 
			
		||||
"!	c #996699",
 | 
			
		||||
"~	c #CC6633",
 | 
			
		||||
"{	c #666666",
 | 
			
		||||
"]	c #999999",
 | 
			
		||||
"^	c #666699",
 | 
			
		||||
"/	c #330000",
 | 
			
		||||
"(	c #663300",
 | 
			
		||||
"_	c #330033",
 | 
			
		||||
":	c #999966",
 | 
			
		||||
"<	c #FFFFCC",
 | 
			
		||||
"[	c #333366",
 | 
			
		||||
"}	c #660033",
 | 
			
		||||
"|	c #CC99CC",
 | 
			
		||||
"1	c #9999CC",
 | 
			
		||||
"2	c #660000",
 | 
			
		||||
"3	c #FFFFFF",
 | 
			
		||||
"4	c #CCCC66",
 | 
			
		||||
"5	c #FFCC66",
 | 
			
		||||
"6	c #666633",
 | 
			
		||||
"7	c #993366",
 | 
			
		||||
"8	c #FFFF99",
 | 
			
		||||
"9	c #993300",
 | 
			
		||||
"0	c #333300",
 | 
			
		||||
"a	c #FF99CC",
 | 
			
		||||
"b	c #CCCCFF",
 | 
			
		||||
"c	c #CC9933",
 | 
			
		||||
"d	c #CC6699",
 | 
			
		||||
"e	c #000000",
 | 
			
		||||
".....*...*.%*..#&@#&@&#&#&#.&#.#.#.#.#.#..#.*.#...#..#.#.#.#..#..#..#..#..#.#.#@#.>..>...*..*...*....%%%%.&&.@.#.@.#..&#.~.#&#$.",
 | 
			
		||||
">%*..*.*..*%.*.&#@&#@#&#&#&#*&.#.#.#.#.*#..#&.~.#.#.#.&.#.#.#.#.#.#&.#..#&.@.@&#&#.>.*.*...*..*..*...%%%%%&&~@#&#.@&##.&#.#.@.>@",
 | 
			
		||||
"...>...*.*.>.%*&#,&#&#&@&#.&#.#.#.#.~.#.#.~.>.#.#..~.#*.~.&*.#.*&*.#..#&.#.##.#@&#.$.>.>.*..*..*.....%%;%%@&@.#.@.#..&#..&#.#@+(",
 | 
			
		||||
".*...*...%*.*.>&&@@#@&##&#.#&#.~.#.#.#.#.##.#&*.~.#..#.#.#.#.#.#.#.#~.#.#.#&.#&@#&#.>.....*..*..*.*...%%%%%&.&@.#&#.#.#.#$.$&+++",
 | 
			
		||||
"..>.*.*.*.%.>.~&#&#&#.@&#&#&.#.#.#..#.~.~.*.~>&>.#.#*.#.#.~.~.#.#.~.#.*&*.#.#.#.#&#..>.>*..>..*.......%%<%%$&#.#&$&#.&#.&>@,++2+",
 | 
			
		||||
".*.%...%*.*..*.#&@#@&##&#&#&#&#.&.#*.#.#.#.#*.~*#.~.#~.~*#.#*#.*.#.#.#.#&.#.#.#&@.##.*..%*..*..*>.*.....%%%%&&&.#~.#.#.#.$&+++++",
 | 
			
		||||
"..>.*.*.%*.*..*#&,&#@&#&#&#.#.~#.~.&>.~.~#*&#~#.~>#.~$~$&.~..#.#~.~.~.#.#.#.#&$#&#&$.>.>..%*.>....*.....%%%-.@#&.#&#.#.$$,++++++",
 | 
			
		||||
"..*.*%.*%.*.>..#&@#&##&#&#&#&.#.#.#.~.#.*.#.*.~.~.#.#.~.##&#.~.#.##.#*&*~.#.#&#.@#&>.>%.*>.%..*.>..*.*..%%%%%&&&.#.&#&#.@++++'=+",
 | 
			
		||||
".*...*.*.*.*.*.~#@&#@&#&#&.#~.#&*&*&#.~#.~*#~#.#*#.~.#&>..#.#.#...#.#.#.#.#..#.#&#.#..>...*.*..%*..>...>.%<%-%@.&#.#.$@@++++++=+",
 | 
			
		||||
".%.*%.%*.%.*.*.&&,&#&#@&#&#.#&.#&*#.~.*.#..#.*~.#.##..#&..&*&#.##.~.#~.#~.#~#.#.@#@.#..>.>..*.*..>.*.*....%%%%.&&#.#&$,++++=+='+",
 | 
			
		||||
"*>.*.*..**..*>.#,@#@#&#&##&#&#*&>&*#.#~.#~.#.#.#*#.&#&.#@#.@..#..@.#..#.#~..#.#&#&#.>.>...*.$..*.*...*.*.>%%%-%&&@&$#@++/++'++=+",
 | 
			
		||||
"..%*.%*...*.*.*&,&#&@#&#&&#.#.#.#&.~#.#.#.~.#.#..#$#$.$...$&@.@.#.@.##.#.##.##.#.@#.#..*.>.%*.>...>.#.#....%%<-.&#.@&+++=+=+=+=+",
 | 
			
		||||
"*.*.*.*.*%*.*.*&#,@#&##&##&~#&*&*#*&*&*&*@.#.~.#$..$.$.-$%$-%$.@.@.&..#*#.#*&#&##&#.#.>...*....*>.*.*.*.~..%%%%%@@.@++++++=+=++=",
 | 
			
		||||
"%..%*..*.*.*..*&&&,@#&##&#.#.#.#.#.#.#.#.#.#.#..@>@.$$$;$%$.$-$%$.#@.#..#.##.##.#@&#$.>.>.>.*>.....*.~.*....%<%<.$+++/+=+=++=/++",
 | 
			
		||||
"*.*..~.~.%*.*.*#    #&,&#&#&#~.#~.~#.#*&*#..@.#.$.$$.$.$;$;$%$%$-.$.&@#.#~.##.#&##.#.#....*...*.>*.#..#.~....<%%-&+++++'=+[++=++",
 | 
			
		||||
".%*.*.&*.*%*.*.      @#&#&#.#&#.##.~.#.#..>.#.$&#$@.$$:$$;$;$;$;-;-$.@&#$#.#&###&@.#..#.>..>.>..~..*#*.*.~...%%<-@+++=++=++=++=+",
 | 
			
		||||
"*.%*&,&*.*.*.*        @#&##&#.~&*&>~.#.>@#&.@#.@$.@$.$.$.$;$;%-;.)%-%$&@.##.#.@.##&#.>.*.#.#.*&*.*.*.#.#..*...-%-+++/+{++_++=+}+",
 | 
			
		||||
"*.>.~&~..%*.*.        &#&#&#&#.##&.#~#&*&##.@.#&$#.@.$.$;$.%).;-;$;$)%$&@&@#.##,@@.#..>.>..>.>.~.*.#.#>.>.#.*.-$+/+=+=+=++=+=+_+",
 | 
			
		||||
".*.&#(#.**.%*.        @#&#&##.#&*#.#..##.#&#@.$.$@>$$.$.$%]%;$;;-;)%)%--&@&@&#&#&##.#..*.#.#..>..~.*..#.*...#..++='+++=++=+'+++@",
 | 
			
		||||
"%.#&~&~..*c*.*        #@&#&#&#.#&*&#*#.&#.#.#@##.&.@.$$.$%$$;$%]%)$;$;-<-%@&@$&##@&#.>.>.#.#&#.*.*.*.>*.~.*..>++++=+=++'=+++=++$",
 | 
			
		||||
"*.~&,&#.*%.*.*.      &#@#&#.#&#.#.#.#&#&#&@.#..@$#.#.@.$.]%;-;-;$;$;-;)--<$@#&,@&##.*.*.>.#&#&$..*.#.*.#.*$.$&++/+++='=+}+=++@$$",
 | 
			
		||||
".#@&,&#.*.*%*.*&    @&#&#@&#.#.#.~&*.#&#.##&@@.#.@.#.$.$.$.$%$;$)-3))-;;-;-&@@@#@#&#.>.*.#.@(,$#...*#.**.*..@++++!'+}+=+=+@+@@$.",
 | 
			
		||||
".&,&#&&>.*..*.#&#@,&#@&#&#&#&#&#.#.##&#&#.#.#&$.#.$.@.$.$$-$;$$%)%-;-;3;)<-)&@&@&,#.~.*>.>#&,+.@**.*.~>.#.>.+++'+++=+=+=++@@@.$.",
 | 
			
		||||
"&#&#&,#..*%*.*.,&,@@#@#&##&#.#&#&#.&~#.##&#&#.#$.#.>.#.$.;.$$;-;-)-);)-)<)%3-++@@&@#.*.*..>@,+@@..#*.*~**.>+++_+='++=+=+=++@.$..",
 | 
			
		||||
"&,@,&@&>.*.%.>.#&+&#&@&#&#&#&#.#.#.#&#~.#.#.$&#.#..#.$.$.$$.-;--)%)););););-<-&+,@~@*.**>.#&+2+@>*.*#.*.#>&2+++=++=++_+++@@$$...",
 | 
			
		||||
"&#&@,#&>.%**.*.&,@,&@#&@@#&#.#&#.~#.#&#&#&#&#.@.#.$.@.@.$.$;-$-;-;-)-;-);-);-)-$+@&#.*..*.>@++++@.#.**.>*$,+/=+=++'=+'+=+@$$.$..",
 | 
			
		||||
"@,#&@&#.*..%.>.#&@@,@##&#&##&#.#.#&#&#&#.##.#.$.$.#..#.@$.--;%)$-)%));)<))<)-<)%@+@.#.**.>.#++++#@.>&#.>.@++++=+'+++=+++@$.@..-.",
 | 
			
		||||
"@&@,&,&>..**.*.#&,&#&@&@#&#&#.#&>&#&#.#&#.#.#.#.#.>@.@.$%).-$;-;$-;-%)-)%)-;)%)-$+@&.*..*.#@+++++.@...$.#++}=+=+=+=+++++$$$.$...",
 | 
			
		||||
",#@,@&#..*...>&#@+&@,@#&#&#.#&#&%#&.#&##.#.#.#.#...#&$.-.-;$;$-;)-))-;-;-;)-;3;3-@@&$.*.*.>&++++/@.-%%$$+++++++=+'+=+++$.$..$.$.",
 | 
			
		||||
"@,&#@,&#%.%*.*.&,@,&#&#&#&#&#.#.>&#&#.#&#&#.#.@.#@@..$%$%$.-;$;-;-;-;--)--;)-;);-$(#..*.>.>@++/++--;-<<)/'+[+=+++=++'+@$&$.$%.$.",
 | 
			
		||||
"@,@&,&..*.*%..>&,&@@,@#@#&#&#&#%>&#&#.#.#.#.#.#..&@.$%$%]%).-;$;-;$)%$;-%)-;))<)3-@@...*..#@++=@-)%)%)-<{+[++{+=+='}+@:$.$..$.>.",
 | 
			
		||||
"@&#@#,&#.%.*.*.&,@,@&&#&@#&#.#&%>&#&#&#&#.#.#.@>&#.$%$.-.$;$;-;$;$;-)--)-;-)%);)))%@..*.*..@++]-]$<);<)-]'='=++++=@++$.$..$..$.$",
 | 
			
		||||
"#&,&#&#.**%.%*#&,&&##&#&#&##&&#%.#&#&#&>&#&.#..#&-*$.$.-$-.)$.-$;$-.;-;.-)%;);-;-)).$...*>&&+$)$))--;)%)$+'+=+=++'}'$$$.$.%$....",
 | 
			
		||||
"#&@#,~&*...*..*&@,@&&#&##&#.#&.%*&#&#.#.#.#.&#.&.>%.$.$.;-$%$).-$;-$;--);$);-);)-))-$.>..~@.%;;-;));-;3-{+'+++=+=++@@$$..$...$$.",
 | 
			
		||||
"@&#&##&*.*5.%*.#,&@,&#&#&##&#&>%#&#~@#&#@.##.@.>..#.$%$-$.).$;$;%$;-.;-%)%$;-;-;);-;%$....%--$3)-;-));-)++=+[+/++/+@$.$$..$%>..>",
 | 
			
		||||
"~@#&,&#*.%*.*.*&@,&#&#&#&#&#@&%.#&#&~.#&#.&#.#..>.$.%$.%$.-;$.$$%$.-;$.$;$;$;-;-)$)-%$.$-%-;%;-;-)-;-3%)'+'++=+=++@$$$.%$..$..$.",
 | 
			
		||||
"@&###&#.*.5.%.>&,@@&#&#,&#@~&#%..~#&#&#&#$&#..>..#.>$.$.$%$.-;%.-.$%$%)%$;-)%$);%).]%-%%$.-;-);-)%)%;-3-+'=+_++++@$$.$.$..$.>..$",
 | 
			
		||||
"~@&#~#&*..%**.*.,(#,&#&##&#&#&%.>.*&#&#.#.#.#.#..#...$.-.$.$..$.%;$.%$.-;$%)$;$$;$;-;$)%-;-$%)-;-;-)-;-]++'+'=+++@.$$.$.>...$.>.",
 | 
			
		||||
"#&#&,&#.*..%.*.#@@&@&#&#&##&#&-%..#.#&#&#.#.$..#.$.>.$.$.-;%$%.-..$;.).$%$-.-$;$;$;$;$;-);-;)-;-)%$%)%-{+_=+=+'+@$$..$.%$.>..$.$",
 | 
			
		||||
",@&##,~*.5*%*.*&,@,##&,&#&#@&~%.**.~&#&#&#.#.#..>.$.$%$.$.$.$.$.$%$.$%$%$;$:-$-.$%$;-;-;$)-)%)-;-$:$.)-+'+'=+++@@.$.$.$...$.>.>.",
 | 
			
		||||
"&#,&#&#.*..%.*.#,&@&#&#&#&#&#&%..*&*#&#&>$.#$.#..$.#.$.-$.-.-..-..$%$.-$;-$$%]$;-;%)%))););$)%)%-.$@;$$++=++=++@$.$.$..$%.$..$.$",
 | 
			
		||||
"@&#&#&#..*.*.*.&@,@#&#&,#&#&&#%.*.*.&#.#.#.#&$.#.>.$.$.$.$$.$$$.$$$%$$%$.$;$$.$$;$%$;)%)-);-;-;-.).$$-'+'+='+'@@.$..-.>.$...$...",
 | 
			
		||||
"&#@,#~#*.%5%.%*#+,&@,#&#&##&#.%*.*.*~&#.>@#.>..#&$.#$$$$$.$$@@$$$.$$$$:$$-.$;-;-%;)%)$;);-)-;--$;@.@;-++=+=+++@$.$.$..$..>$..$>.",
 | 
			
		||||
",&#&#&&*.*.*.*.~@@,&#&#&#&#&,.%%..*..#.#.#.#.>.#.$#..$&@@@@@$$@$-$$]-$$+.{$%-$;-%$;-;-;-)-;--;-.$@:@-$/++_+=++@$.$..$.$.$..$..$.",
 | 
			
		||||
"@&#,##~.*.%.%*>&,@@,&#,&#&#&,.*.*.**.&#.#$#$.#.@*@.$>@$$@@@+$)@!]+@@@++{+$;$:-%]%)%$;-);;--;-%$@&+@%-+'+=++++@$$.$.>.%.$.$..$..$",
 | 
			
		||||
"&#&&#&#*..5*..*&,@,@&#&#,#&#&&%%%*.*.#.#&#.#.$.#.$#.@$@@@{!@!@!+=$=@'+++@$$-$%-;)-;).)%-%)%$.@&@&$%)+++'+==++.$.$%$.$$.$.%$.$...",
 | 
			
		||||
"#&#@~#..*.*%%*.#@+#@#&#&&#&,&~%%5*.~.~&#.$#$&#..#.$#$@$@!@={=!!@[@[@=e+)$;-;);$%;$-;-);$<$&@6+@&]$-(++++=++++$$.$.$%.$..$....$..",
 | 
			
		||||
"&#&#&##*.%..*..~#+&#&,###&#&#(%%%...>&@#.#.#.#.@>.@#$@@+@+=+!{=!!=+!++)@-]%$%)%$;)$;$%)%@]&@&@.$.)+++'++=+=+@$.$%.$.$.-.$.$$..$.",
 | 
			
		||||
"@#&##&#.**%.%*.#&,@,@&#&,#&#&#.%5....#@>#$&#.$#.$$@$@=!==+=]!_+=@[+{+$$)%$);$;;-$-;---@@@@.:%.-$-++++=+=+++@$.#.$.%.$.$.$.$.$$.$",
 | 
			
		||||
"&&#&#~#...5*%*.&,@,@#@#&#&#&&,&%%%%..@.$.,.#@&$@,$@+}@='=/={+=]!_!/!$]%$;).-$;$;)-$;.@{@@$-$..%%+/'++=+'=++@$$.%..$.%..$%$.$.$.$",
 | 
			
		||||
"#&#&#&#**.*..**#@,&@,@#@#&##.#&%%%..#$##&#.&$.$$+@+!@=+!={=+={=@@_]$@-;$%$;$;$;$;-.$(+@${@:%.--+++++=+=++++@..$.$%.$.$%$.$.$.$$.",
 | 
			
		||||
"#&###&#.%.%*%...,@,#&#&,#&,&#&#&%%%.&..#$#.>@#@@@@=@=+=!+_'+=+='!!{@)$--;$;$;$%;$)%]&@@@$@$$%.(+++++'+_+=+@$.$%..$%.$..$.%$.$..$",
 | 
			
		||||
"#&@&#,&**.%.*%*&,@&@,#@&#&#&#&&9%%.>.#@..@.@.@@@@@@=_=+=@_+=@@!+!]@$).;$.-.$;$;-;-%-.@@@@@:-@++++++=@+'+++@@@.$.%$..$..$.$.$.$.$",
 | 
			
		||||
"#&##&###..*%.*.~@,+#@&###~#&#.#&.%%.&.,.#&#$@$@+=+@=+=^@[+++=++!@]@)$%).).)$.).-;$;%.+@@@$@.6+/++++++=+=+@$&$%..$.$.-.$..$..$...",
 | 
			
		||||
"&#&#&,&*.%.%*%*#&,@&#,@&@&#&#~&#&-%#.#&#&>.@@@}+=+={!==@!+'+'+@+$1$)$%$.$$.-;-%;-%-%$@++=@]$+/+=+{=+=/+++@$$.$.%.%..$.%$.%$..$.$",
 | 
			
		||||
"#&@##&#.*%*.....,@,@@&##,#&#&>&#&%%&#&.@.@>@@+!+='+==+![$!+++@@$]$-$;$;$%$.$;$%-;-%%%$++@+$]+++=+++++'+++$@$.$.$.$$%.$.$.$%.$...",
 | 
			
		||||
"&#&#&,&#..%.%*>&,@(##@#&#&#&#.#&#->.&#&>&@++!+=+=+=+[=+=@++/@$$$$]$).$..$;$-%-;%-%;%.$@+}{$$+'+=+={+=+++@@$.$..$...$..%.$.$..$.$",
 | 
			
		||||
"&#&##&#*.*%*...#&@,@&#@#&##.#~&#..-&#..#$@@++++^+==+^=@!'=/@$$$-$$$-;-.$.$%$%$%-%--%%#@+}@]$@++=++=+++++$@.$.$..$.$.$.$;..;.$...",
 | 
			
		||||
"@&#@#,&...%.%*.#&@,@#&#&#&#~$~#.##%#.@.$@++!_=@={+=+=='=+@{@.$;$)&$%$.$.-$%$%-;%)%%%-%@+++@${+={=++=+++@$$.$..:.$.$:$.$.$$.$.$$.",
 | 
			
		||||
"&@&#&,#*.*%*%*.&,@@&@#@##&#&#.&#&$@.@.#@+!++@'+=+'=+=+=@'@$:$.$%-:-$.$.%>%$-.-%%-;-%%>@@+/@$++=+={++'++@@$$.$%$.;..$..$..$.$:..$",
 | 
			
		||||
"#&#@#&@....%.%>&#(@#@&#&#&#&##*#@&#.#$@@+@_!_=+{=+={==+/+@@$.$;$$$..$%>.$>%$%-;.-%%)%-$+}+@)@++={+=++++$..$;$...$$..$:@.$:$.$$$.",
 | 
			
		||||
"@&#&#~##..*%.*.&@@,&#@#@##~#.&#.>++&$.@+=+=@=+=++++='+^+]@-;-..-%$@&&#.>%>-.$%-;-)%%%$#++++-@+@+=+[+++@$@.$..$;..$.$.$.@.$$.@.$$",
 | 
			
		||||
"&#@,@,&*.%..%%>~@(@@&#&#&@&##.*.#+2$@@@+!=^!'={+_+=@!@_+@:-.).;-.$.$.,(#.>$%$%%%$;-%.@@++++%@+=+{+=+++@$$.$....$;.$:.$.$.$.$$@.@",
 | 
			
		||||
"@&&#&#@#.*%.*..&#@,@#&#&#~#&#&>.$@(@@@+@++=!+=+'@/=/@+'$@)$%$.-&@$$$.$&,&#.>.$;%%$@@&@#@+++]$++=+=+'++.@.$%$.$..$%.$.$.$:$$$:$@$",
 | 
			
		||||
"##&#@9&..*%*%%*.,+#&#&#&#&@&>..>.$@++!=^!!/^+^+=1'+=++@:-.;-$%@@@+++++$.#.>.%%-;-$@+++@++++$@@++=+=++@$@.$.$..$..$$.$.$.$.$.@$:$",
 | 
			
		||||
"&#&#&#,>...%.*..&,@,&#&&#&#..$..$+@+=@!@^]=@=+'+_!'+0+$.$;-%-+(+,++@@2+#.#*>.%-;@+++++}+++{$@@+++'+++@..$.$.$..$...$.$.$.$$$$$@$",
 | 
			
		||||
"&,@,@(&.**%*.%*&,@,@&#,.,&#-.$.@$++^+^_=!@_'+==/^+_++@:.-.-%+@,++@++--(@~.#.>%%$++@@a+++=++$]@=+==+++.@$.$.$.$.$.>$.$.$$.@.:@@.@",
 | 
			
		||||
"#&#&#,,...*%.*..@,&##&#&#@+,$$$(+/@=+=!+^1+[+'+='=+'+@$$.%-&@&,&@+@@$-#@#&#..)%6@+@@$7++++@@$@@++=+++$..$.$.$..$..$.$.$.$.@.$:$.",
 | 
			
		||||
"@&#@,&@#.%.%*%.~#,&#&@.,+&@--%+++{!'=!=^+!+==+=+=+'+$..$;-&&$$@@&$.--%.$~#*.>%-@.$#$$,@+++!{$@@+=+'+@:$.$.$.$.$.$..$.$.@$:$.@..;",
 | 
			
		||||
"#@#&@,&#.*5.%*..&@#&##.+#$$$@++@@'}'={=!!!'/'=+'=+++@-$%-&@...*$#$@&@$-.#.#.$%;$.$.@,+@}++@@|{++++++@$.$.$..$....$.@.$.@.@.;.%%%",
 | 
			
		||||
"#&@,@,&#.*%*%.*.,,&#&#$#$$+@=+'+1$!==^={$1+=++=++/+$]$.-&&*#>.$.$.$.-.#.>.#*$-%-$.##@#@++++@$@+=+=+@.@...$.$.$.$.$.$.@.$.$.$%;.%",
 | 
			
		||||
",@#&,+,.>.%*%.*.&#&#.@&$@!+!+==@!{^'==!!!!{+='/='+@@$--#&#...>.>.$.$.$%#*#.*$%-.$.$.#$,@+++@$@@++++@$.-$..$.$.$....$.:@&$%%%%%.%",
 | 
			
		||||
"@&+@,&+...%.*%.#,#,@##$#$$|={={^{!+_=]={@$!+++=+++@$$%$&@.#*>.>%$%%$%$..>.#.>%--.*>##@@+}+{+|$+++++@....$..$...$.$.@.@.;%.;%.;5%",
 | 
			
		||||
"@,&,@+,#.*%*%.*.&,&#.$@$+=+='=!+!{[='==!^/@!'++/+@]$--(,#.~.*..>.>.%$%>.*#*#$%-%$...>##+++++$]+++++$@.$..$.$$.$.@:$...$.-%.%%.;%",
 | 
			
		||||
"@,@+,&+...*%*%.~#&,@@#$+!@^=!'!1'_+==+=+++]@+=+++$$$)++&#&>~>.>%%%$%..$.*.#..---..>.#$#+++++-$++++@.$...$...$.@...@.@.%;%%;%%%%%",
 | 
			
		||||
"@+@@,+,@>%..%*..,#&#&@@$!{=!==!{=='+[+{=++$@@'/+$&--@+/@~#*~.>.$>%.%>.>.>*#~$%%-.>.#.#@,++++$$++++@$.$..$.$.$.:$.$.:..%%.%;.;%;%",
 | 
			
		||||
",@(+,+&#..*%.%*&,@#@@$$+@!]={^@!{+=='_++++$@$@+/@$-)+/@@#.~**.>..>%$%..*#.~.#$-%...>$#++7+++1$++++@.$.%..$.@.$.@.$&$.;%%4%%%%;%%",
 | 
			
		||||
"+,@@+,+&>.%*.*..&@&#$$+!@^===!1]|'+=+}{@+@$$+++]@%$+++/&###~#..>...>.>..#*#..%--.>..>@,+++++$$++++$.$.$...$.$.:$.@...%.%.%4;%%;-",
 | 
			
		||||
"@@+,+,+..*.%*%*#,,@@@$@+!{={1{=$=/'+=+@+]@+@/'/$@%@'++@@~*~**>.$*>%..$*.~.#*@.-<..$#.@+++!+/$$@++@$....$...$.$.@.@.$%%454%%%;-%)",
 | 
			
		||||
",@+@,++#$%*%.%..,@.#@@@=@!==!=^][+='/=@$@.++++$@:$+/+/@+@#*#*.*$..>.>..##*.#..--...>@,}++@+/$$$+(@@$.$..$.$.$.$.$@..%%%%4%;%;%)%",
 | 
			
		||||
"@,@++(,....*%*..#,@@@$+@!{=@^+!!{|+={++=+@+/+@;$-@+'++@,#&*#.#.>*>.%>*#.*#.#.$%-.>.@$+++=++++$$/+.$.$.$..$.$:$...@.%%.4%%%;%%;%;",
 | 
			
		||||
",@,@,@+.>.%..%*&&&,@@@@!@=_!='!!]1+={}'+!++++$-$]+/+++@@&#*~*>.>.>.>.$*.#&#&#&>.*..#@+=++++++$$+&$..$.$.$.$.@.$.$..;%%%4;%%;%-%%",
 | 
			
		||||
"@,@,+&@...%*%*.>#+#@$@+!+=]=!=]!|!'+!@/++/@@@$6-++=+/+#@~#.#*~>*.#*.*.>.*..#.$%$.>$@+}+=@++++-@+@.$.>.$..@..$:@.@..%%4%%%;%;%;;%",
 | 
			
		||||
"@+@@+,@.$*.%.%..&+&#@$+{!@=_{=!!{!!'@^++!@$$@@$+'+++++#@$~#*#.#.>.>>.>.#.>.%%-%$..#@++++!+@+($$@#.$.$..$.$.$..$..$.%%%;%;%%;-;-;",
 | 
			
		||||
",@,+@+#..%.*%*.##,@@$@!+!{==={={=1@={@/+]$$$@@@+++=@++@&#.~*~**.#...*..>..>-.%>.>$.++=++@+++/$.@...$.$..$..@.$.@..%%.%5%;%;-%<%;",
 | 
			
		||||
"++@+,+@.>.%.*%..&@@#@$+@!+!'==!!^!1+@'+@@$-@@]+++@++++#+##.#.#*.*.>.>.*.>..%$%%$.$@/+=+7@@++($@@$.$...$.@.:$.:.@..%%%;%<%%<;%-;%",
 | 
			
		||||
"+,@+@,&$..*%.*.#&,@@@!+!+[=@^@[+^={|++.)$-+@$++{+=+!+++&#.~***#.#*.~.#..*$*>%$.$#@+++++=+@,++@:....$.$..$.$.@.$.@.%%%5;%;;%;%;-<",
 | 
			
		||||
"++,++@,.>%.%%%.#&@#@$@=+!'===!{=^!!{@)@-%@@@+/+@}++++++@##.#~.**.#&#.~#.#&.#.,&@>$++++++}@++(@@@.$....$...$..@....%%%%%%%%;-<%;%",
 | 
			
		||||
"+++@+@&$..*%*%*.@$,@@@@=+={^'|!{!!{+@$&3$&]$++=+++=+=+,+&#~.#*#.*>*~#.~~>&#.>$.$$}+}'+=+@@+@+&$.$..$..$.@.$:$.]@&%%;%4%;%;%<-;%<",
 | 
			
		||||
"@++++@&>..%*.%.#&$+$@@'=+_=@=]=!^!={]$$;@$$++'/=+++@+++@@&#~.~.#.#.*#*#.*>%-*#$>@+++++++}@2@+&$.$..$..$:.$..$..$&%%%%%<%<%;%%;%%",
 | 
			
		||||
"++7+,+@..>.%%*..#+@@d+@='='=^@[@^^@!$]$$@-+++++++=++=+@,,@~@~#*~.*>.~.#*#.>.>.>@+_+=+++@+@+@2+$..$..$..$.$:@:$@:@;%;8%;%;%-;%;%;",
 | 
			
		||||
"=++++@&#.%.*%>..,@$@@+!+=$[@b{!{=^!]@$$$-+@+}{=+++++@++@,@#&#.#.#.#*#*#.#~##$#$,+=++{++@7@}@++.$..$..$.$.$.$.$.@.%%%%;%<%;%)%%%%",
 | 
			
		||||
"+++++#@..*%.%*..@,$@@+!'_=='|^@1!+1@@{$-@++=++++++=+{+@++&#&#&>.#*.>..#.>..>.>@@/=+++++@+@+@++.$...$..$.$.$@:$@:@;%<%%<%%<%%;%;%",
 | 
			
		||||
"+=++@@@#..*%.%>.@+@@+@@='@[=$^!]!^+1$+]$+++++=+=++++=+++++,#&##.#.#.>*.>.>$%$.++=+[+{++@+#+#++$.$..$.$.$:$.$$$.@&;<%;%;;%-<%%%%%",
 | 
			
		||||
"+++++@..>.%*%..#@,@@=+^+=^+^]='1|]=]$@@+=+=++'+++++=+'+++&+,,&#.#....>.>%$.>$#(++=+++++@@+7@@(-.$.$..@.$.$@:@$@].-%;<%<%;%%)%;%%",
 | 
			
		||||
"+=}++@@...%.*%*.@+@+++!+'='_!]={!!]!!{!+'=+=+='@+++++=@+++(+(,#&#.#>..%.>%$.$@+++'={'++@+@+@@+.$..$:$.@$.$.$.@:@:%<%;%%<%;%%%%..",
 | 
			
		||||
"+++++#@#.*.%*%.#+@$@=@==+='=]|={!^|{|$1@_+'}{@}@_+'+=+++@+#+,+,(#&&#.#>.%$.$.@++=++++++@!@+#++%$&@.@.$.]$$@$]@$&.;%%4%;%%%-$$+++",
 | 
			
		||||
"++++++&$>.>..*..@-+$+'@={=+{!]=={!^!]!{)!'=++=+@+=+++=+=++++&#.#.#.>...$*.$%$.@+'='@{=+@+!+@@($.@.@&$@.@.@.$.@]@%%<%%%%;%;.(++++",
 | 
			
		||||
"++++}@,&$%*%*$*.-++===+=+=+_{|]=[!$^@^!+]@'=@++=+++=+'+@++,@#@#$#.#.>.*.$..$%$;-@+'++++!@@@+@($.&@.@.@@@.]@@.@&$;%%4%8%%%.@++++@",
 | 
			
		||||
"@@+++++#.>.%.%>.+@]++_{='!{+[@^@|]^!^@^|]!++='+@=+'=++=++++@@#.#.#.#.#..>.$.-%----]/'++++7@+@+.$.$&$&@&@@&@@@@@&%;%%%%%;$&(++@@@",
 | 
			
		||||
"@!@@+@+&..**%*..@++='+=@_+^@='|^!!{^@1@^$+1+@+=+++++=++=@++,@#.#.#.>..>...%.-.-;-)--+++@+@@+,@.@.$.@.$@.@@&@&$&@%;%;%;%.&+(@,+@,",
 | 
			
		||||
"$]@@@++,.$%..%>.$@++_+|{=]+^+={={==!{!]!{={{=++=+=+'=++++@+@&#$##.#.#.~.>.$.%%$%%)%3;@'+++@++@$.@.$.$.@.@@@&@&@&%4%%%%$(+(@&@,@@",
 | 
			
		||||
"@$$$@@2@.*.*%*..$@+=+_+=@_@'!{=$={'!^$!]=$_$+'/@=+=++'=++@+,@.#..#.*.>..*.%%$%.;$%;-%-$+{+@++.$.$.@.@.@$&$@&$.@&%%<;%%@(@@@+&@&@",
 | 
			
		||||
"{$]$@@+@$%.%*.>.@)/'={=+='=+=+[{==!{!{1@1+)=+=+{+'+=@+++@@++#.##.#.#..#..>...$%%;%-;%<)@++@++$$.$.:$.$.$@.@@&$&%;%%%;.@(@&#@#@,@",
 | 
			
		||||
"+@|$$@(,..>%*%..@@+/=+='=+{='=+={[+=!!]|]!+{$+/=+=++=++@@@#(@#&$*.#.*#.*..%.%.%-%;%;-%--{++++$.$.$@.@$@.$#.@.&$%%%;%%@(@@,@.@&&&",
 | 
			
		||||
"'@]$$@++...%.%*.$@+=/!+=+=@=+_{==@^{+^!@|{=|)=++{+=+{+}+@@@(,.#.#.*>.*.>.>..-..%$%-;%<;--+@++.@$..:$..$.@.@.#..%%%%%.&,@&@#@,@#@",
 | 
			
		||||
"++]$$$+&.*%*%*.$$+'=+[='_'$'='_@^{!!!{!]|'=@-+/!+=++=+++#@#2@.#.#.#.~>.*..>..%$%;%;%-;-%)++++$..$..@$@.@$.@&..%%%<%%$&@&#@@&@&&@",
 | 
			
		||||
"''$]$@++$%.%.%*.$++'=+=+=@!'+=+='=+{!'!1!@={|'+@{=+++++@@@&2&#.#*~.*..#.>.%$..%.%$;%%;-<-)++($.@.$...$@.@.@.$%%%%%%.&&,@&##@#@@@",
 | 
			
		||||
"++!$$$(+..*%*...@+_@_+[+[@@_{='=+[={!=@^$^@!{+_+++=++++#&#@(#.#..#*#.*.*.>..%$.-.%-;-%)-;3/0@@...@.$@.$@.@..%%%;%%%$&#&#@&@,@@#&",
 | 
			
		||||
"''])$@(+..%.%*..@'+'+[+=@[++=+=+='+=]=!]|]!@^++=++@++++@#.#,~.*#*..#*#.#..>.$%.%$;%-%;-<--@+@.$..$...@.@$&@%<%%%%%%&&&#&#@,@&@@@",
 | 
			
		||||
"/+@]$$+($.%*%%*.@@==/='=+]='+'='=+^='!{|=]|$@{++=+++},@#.@(&##..~**..#*.>.>.>.$%.-;%)%--;-)(]..@..@$.$.@.@:%;%4%%%$&#&&#.&#@@@+@",
 | 
			
		||||
"''!)$]+,..%..*..$++'+=+[+!@_!+_+='!+=@!1$_'[+=]$@=+++@@#.>,&&*#.#.~*#.*#.>.$.%$.-.-;-;-;-<$+&]..$..@.@:@.@.%%%%<%*.&&#&#@,&@,@@@",
 | 
			
		||||
"++{$$$@($.*%*%.>@'+=+'=+'='+'=+'=+^'^^@^@1+=+++@+@@++&#@.#(##.#*.*$*.#.*#*.*$..%.%%%-;-;-;-(@.$..@.$:$$.@...%%8%%.#.&&#&@@#@@@,@",
 | 
			
		||||
"_/!]$]@+.>%.%*..$++=++{=++=+=+=+{=+^+^]1+^@'/={++++2+#&#@#+&#.*.#.~.**#*.>.*..$..$;%%-<-%)-:$.@.$..$@.@:@...%.%%%.~#&#&@,@@@+@@@",
 | 
			
		||||
"+'+$]$+&&.*%*%.>$@+'+=+'={={+=+=+[+^='!^+^@|'++=++++@&#..#&#.#*.*.#*#.*.#*.>.%.%.%.-;%);-<--:@.@&$.$$].$&.....%%%.&#&@,&@,@#@@+@",
 | 
			
		||||
"_+{$$]@+$..%.*..$@}'++='+=+='='+!'_$!'={[@^@=++/++++#@##@2&#.#*#.*.*.~>~.*..>..$..%$%-%-)%-<@&@&@&@.@$@.$....4%%.#&,&@,@&@@+@@@+",
 | 
			
		||||
"+/=]$$&&&>%*.%..@@+=+'}=+{=++=+_=@!{!={=={!+'_{+=+++#&$*@(#.#.>.*#.#.*.#.#*...%.%.%.;-;-;-;-.@&+(@@@@@@$...&.%%%.@&@,&@@@@@&@@++",
 | 
			
		||||
"+'+]$)@+...*%*..@++'=+'='=+[+='+'_+^$|{!]='=++=+/++@#.##2&#.#.*#*.*.*#.**.*.>*.$.$%$%;-%<--<$6@&@&+({(@+&$..%%%..,+&@,@@,@@@@@++",
 | 
			
		||||
"+++$$).(..%*%.%.@=+++=++='={+=+==+=={|!^@=+^/=+/+++#@#&,(#.#.*#.*#.*#*.#.#*...*.%..%$%;-;-%--&@@@@@++++(+%%.%%%.@(@+@&@@@+@@@+++",
 | 
			
		||||
"{@{]$]$+&..*%*.&$@_'+'='+=+='=++='=+_{$^!{='=/+=++@#$#&2#.#.>.~*.*.*.#*#*.#.>.>..$%.%-%-;3;-%{&@&@@@@++(,%>.%<.&++,@+@@(@@@@@+@+",
 | 
			
		||||
"@@@$$;$&@%%.%%.&$+++=+=+='=@=+[/=+='=!_@!{_++[+++@#@~,(,.#.#.*.~*#.**..*.*.*...*..$%.;-;-%-;-$@&@@&@@++(+.%-.>&(+@+@@@@+@@@@@@++",
 | 
			
		||||
"+{@]$]$&&.*.*%%&@=+=+'='+='='=@='!+=+^@^+='=+/+++@@#(2,~#.#.#*#.*.~.#*~.#*#.#*.$*.$%$.%-;)%-<-6@@@@6@@+@&>%%$&+(+@+@@+@+@@@@{+@+",
 | 
			
		||||
"@@@$$.]&@.%.%...@++'=+=+=+=++={}+!'!'=@1+=++++}+@(,(#~..~#.*.**~*.**.*>.*.~.*.>..>.%.-;%-;-%--+@&@@@@&@&#.>.&,&+@+@@@@+@@&@@++++",
 | 
			
		||||
"+@{@)$$&..*%*%..{++=+{='='=^+!@='!+=]={!{='=++++,(#&&#~#.*##.#*.#.#*.*.~.#*.#.**...$%.$;%)%);-:@@@&@@@&@&..,@(@&+@@@@++@@@@@@+++",
 | 
			
		||||
"+'@@$)$&@..%%%.#++_+=+=+!+=@[+=@={!_+={!@++++/+,@&.#*.*~#..~.#****.~.#*.*..*.*#.>>.%$%%$%)%----+6@@@&@@.##&~@#@+@@@+@+@@]@@++{++",
 | 
			
		||||
"+++{$-)$..%*.%.@++++'+{='='@={=$=+!'^$_+^+_+++@$&#&~&~*.~#*#*.~.~.*.*.#*.#*#.*.*..>..$;%;-;;-;-+@&@@&$&#&&#&#&@@@@+@+@@.@@@+++++",
 | 
			
		||||
"++'@)-.$&$.%%%%&+'=+==+=+=={=@={@[@='={!$@+++,@,.&.#*&~~.*&.#*#*#*~.*.*.*..*>.*>.>.%.%$;%)%--;-@&@&@@.@.#&#.#&@@+@+@@@@@@@++++!@",
 | 
			
		||||
"++++-))$...>.%.@++_++{={'=@_+=+={=]+_@[/^@+@+@#@#.~.~*.~*#*#*.~.*.*.**.*.#*.*#.*.>.$..$;$%);--)$6@&@&#.@*&#.#@,@+@@+@@$@@@++++@@"};
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 1.9 KiB  | 
| 
		 Before Width: | Height: | Size: 18 KiB  |