From 8de95676e0fd89f2326b3953488ab66ff29cd2d0 Mon Sep 17 00:00:00 2001 From: hugovk Date: Tue, 26 Aug 2014 16:47:10 +0300 Subject: [PATCH 01/17] flake8 --- PIL/BdfFontFile.py | 21 +++--- PIL/BmpImagePlugin.py | 26 ++++--- PIL/BufrStubImagePlugin.py | 4 ++ PIL/ContainerIO.py | 7 +- PIL/EpsImagePlugin.py | 104 +++++++++++++++------------ PIL/FpxImagePlugin.py | 33 +++++---- PIL/GbrImagePlugin.py | 2 + PIL/GdImageFile.py | 8 ++- PIL/GifImagePlugin.py | 59 +++++++++------- PIL/GribStubImagePlugin.py | 4 ++ PIL/Hdf5StubImagePlugin.py | 3 + PIL/IcnsImagePlugin.py | 24 +++++-- PIL/IcoImagePlugin.py | 41 +++++++---- PIL/ImImagePlugin.py | 39 ++++++----- PIL/ImageColor.py | 5 +- PIL/ImageDraw.py | 11 +-- PIL/ImageDraw2.py | 7 +- PIL/ImageFile.py | 47 ++++++++----- PIL/ImageFilter.py | 2 +- PIL/ImageGrab.py | 2 +- PIL/ImageMode.py | 2 + PIL/ImageMorph.py | 4 +- PIL/ImageOps.py | 11 ++- PIL/ImageSequence.py | 3 +- PIL/ImageShow.py | 16 +++-- PIL/ImageStat.py | 12 ++-- PIL/ImageTk.py | 28 ++++---- PIL/ImageTransform.py | 8 +++ PIL/ImageWin.py | 12 ++-- PIL/Jpeg2KImagePlugin.py | 2 +- PIL/McIdasImagePlugin.py | 8 ++- PIL/MicImagePlugin.py | 1 + PIL/MpegImagePlugin.py | 2 + PIL/MpoImagePlugin.py | 15 ++-- PIL/MspImagePlugin.py | 13 ++-- PIL/PSDraw.py | 22 +++--- PIL/PaletteFile.py | 2 +- PIL/PcdImagePlugin.py | 9 +-- PIL/PcfFontFile.py | 36 +++++----- PIL/PcxImagePlugin.py | 19 ++--- PIL/PixarImagePlugin.py | 3 +- PIL/PngImagePlugin.py | 125 +++++++++++++++++++-------------- PIL/PpmImagePlugin.py | 24 ++++--- PIL/PsdImagePlugin.py | 33 +++++---- PIL/PyAccess.py | 139 ++++++++++++++++++++----------------- PIL/TarIO.py | 1 + PIL/WalImageFile.py | 1 + PIL/WebPImagePlugin.py | 5 +- PIL/WmfImagePlugin.py | 18 +++-- PIL/XbmImagePlugin.py | 4 +- PIL/__init__.py | 2 +- PIL/_binary.py | 33 ++++++--- Tests/show_mcidas.py | 1 + Tests/test_file_gif.py | 13 ++-- Tests/test_locale.py | 2 +- Tests/test_pyroma.py | 2 +- 56 files changed, 647 insertions(+), 433 deletions(-) diff --git a/PIL/BdfFontFile.py b/PIL/BdfFontFile.py index 3a41848d8..c52812450 100644 --- a/PIL/BdfFontFile.py +++ b/PIL/BdfFontFile.py @@ -26,12 +26,12 @@ from PIL import FontFile # -------------------------------------------------------------------- bdf_slant = { - "R": "Roman", - "I": "Italic", - "O": "Oblique", - "RI": "Reverse Italic", - "RO": "Reverse Oblique", - "OT": "Other" + "R": "Roman", + "I": "Italic", + "O": "Oblique", + "RI": "Reverse Italic", + "RO": "Reverse Oblique", + "OT": "Other" } bdf_spacing = { @@ -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: diff --git a/PIL/BmpImagePlugin.py b/PIL/BmpImagePlugin.py index fae6bd391..917d43b9c 100644 --- a/PIL/BmpImagePlugin.py +++ b/PIL/BmpImagePlugin.py @@ -51,9 +51,11 @@ BIT2MODE = { 32: ("RGB", "BGRX") } + def _accept(prefix): return prefix[:2] == b"BM" + ## # Image plugin for the Windows BMP format. @@ -62,8 +64,7 @@ class BmpImageFile(ImageFile.ImageFile): format = "BMP" format_description = "Windows Bitmap" - def _bitmap(self, header = 0, offset = 0): - + def _bitmap(self, header=0, offset=0): if header: self.fp.seek(header) @@ -97,8 +98,9 @@ class BmpImageFile(ImageFile.ImageFile): # upside-down storage 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)) @@ -137,7 +139,7 @@ class BmpImageFile(ImageFile.ImageFile): greyscale = 1 if colors == 2: indices = (0, 255) - elif colors > 2**16 or colors <=0: #We're reading a i32. + elif colors > 2**16 or colors <= 0: # We're reading a i32. raise IOError("Unsupported BMP Palette size (%d)" % colors) else: indices = list(range(colors)) @@ -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: @@ -214,10 +217,10 @@ def _save(im, fp, filename, check=0): # 1 meter == 39.3701 inches ppm = tuple(map(lambda x: int(x * 39.3701), dpi)) - stride = ((im.size[0]*bits+7)//8+3)&(~3) - header = 40 # or 64 for OS/2 version 2 + stride = ((im.size[0]*bits+7)//8+3) & (~3) + header = 40 # or 64 for OS/2 version 2 offset = 14 + header + colors * 4 - image = stride * im.size[1] + image = stride * im.size[1] # bitmap header fp.write(b"BM" + # file type (magic) @@ -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))]) # # -------------------------------------------------------------------- diff --git a/PIL/BufrStubImagePlugin.py b/PIL/BufrStubImagePlugin.py index a55ae5613..45ee54776 100644 --- a/PIL/BufrStubImagePlugin.py +++ b/PIL/BufrStubImagePlugin.py @@ -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") diff --git a/PIL/ContainerIO.py b/PIL/ContainerIO.py index f4a15b813..dcedcd6dd 100644 --- a/PIL/ContainerIO.py +++ b/PIL/ContainerIO.py @@ -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: ## @@ -48,7 +49,7 @@ class ContainerIO: # for current offset, and 2 for end of region. You cannot move # the pointer outside the defined region. - def seek(self, offset, mode = 0): + def seek(self, offset, mode=0): if mode == 1: self.pos = self.pos + offset elif mode == 2: @@ -75,12 +76,12 @@ class ContainerIO: # read until end of region. # @return An 8-bit string. - def read(self, n = 0): + def read(self, n=0): if n: n = min(n, self.length - self.pos) else: n = self.length - self.pos - if not n: # EOF + if not n: # EOF return "" self.pos = self.pos + n return self.fh.read(n) diff --git a/PIL/EpsImagePlugin.py b/PIL/EpsImagePlugin.py index 9f963f7e6..b980fe573 100644 --- a/PIL/EpsImagePlugin.py +++ b/PIL/EpsImagePlugin.py @@ -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,20 +52,21 @@ if sys.platform.startswith('win'): else: gs_windows_binary = False + def has_ghostscript(): if gs_windows_binary: return True if not sys.platform.startswith('win'): import subprocess try: - gs = subprocess.Popen(['gs','--version'], stdout=subprocess.PIPE) + gs = subprocess.Popen(['gs', '--version'], stdout=subprocess.PIPE) gs.stdout.read() return True except OSError: # no ghostscript pass return False - + def Ghostscript(tile, size, fp, scale=1): """Render an image using Ghostscript""" @@ -72,25 +74,28 @@ def Ghostscript(tile, size, fp, scale=1): # Unpack decoder tile decoder, tile, offset, data = tile[0] length, bbox = data - - #Hack to support hi-res rendering - scale = int(scale) or 1 - 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])) ) - #print("Ghostscript", scale, size, orig_size, bbox, orig_bbox, res) - import tempfile, os, subprocess + # Hack to support hi-res rendering + scale = int(scale) or 1 + # orig_size = size + # orig_bbox = bbox + size = (size[0] * scale, size[1] * scale) + # 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 os + import subprocess + import tempfile out_fd, outfile = tempfile.mkstemp() os.close(out_fd) in_fd, infile = tempfile.mkstemp() os.close(in_fd) - + # ignore length and offset! - # ghostscript can read it + # ghostscript can read it # copy whole file to read in ghostscript with open(infile, 'wb') as f: # fetch length of fp @@ -109,17 +114,17 @@ def Ghostscript(tile, size, fp, scale=1): # Build ghostscript command command = ["gs", - "-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 - "-sDEVICE=ppmraw", # ppm driver - "-sOutputFile=%s" % outfile, # output file + "-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 + "-sDEVICE=ppmraw", # ppm driver + "-sOutputFile=%s" % outfile, # output file "-c", "%d %d translate" % (-bbox[0], -bbox[1]), - # adjust for image origin - "-f", infile, # input file - ] - + # adjust for image origin + "-f", infile, # input file + ] + if gs_windows_binary is not None: if not gs_windows_binary: raise WindowsError('Unable to locate Ghostscript on paths') @@ -127,7 +132,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: @@ -137,8 +143,9 @@ def Ghostscript(tile, size, fp, scale=1): try: os.unlink(outfile) os.unlink(infile) - except: pass - + except: + pass + return im @@ -147,22 +154,28 @@ class PSFile: def __init__(self, fp): self.fp = fp self.char = None + def __getattr__(self, id): v = getattr(self.fp, id) setattr(self, id, v) return v + def seek(self, offset, whence=0): self.char = None self.fp.seek(offset, whence) + def read(self, count): return self.fp.read(count).decode('latin-1') + def readbinary(self, count): return self.fp.read(count) + def tell(self): pos = self.fp.tell() if self.char: pos -= 1 return pos + def readline(self): s = b"" if self.char: @@ -187,6 +200,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""" @@ -197,13 +211,14 @@ class EpsImageFile(ImageFile.ImageFile): fp = PSFile(self.fp) - # FIX for: Some EPS file not handled correctly / issue #302 + # FIX for: Some EPS file not handled correctly / issue #302 # EPS can contain binary data # or start directly with latin coding # read header in both ways to handle both # file types - # 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 + # for HEAD without binary preview s = fp.read(4) # for HEAD with binary preview @@ -220,19 +235,19 @@ class EpsImageFile(ImageFile.ImageFile): else: raise SyntaxError("not an EPS file") - # go to offset - start of "%!PS" + # go to offset - start of "%!PS" fp.seek(offset) - + box = None self.mode = "RGB" - self.size = 1, 1 # FIXME: huh? + self.size = 1, 1 # FIXME: huh? # # Load EPS header s = fp.readline() - + while s: if len(s) > 255: @@ -258,7 +273,7 @@ class EpsImageFile(ImageFile.ImageFile): # put floating point values there anyway. box = [int(float(s)) for s in v.split()] self.size = box[2] - box[0], box[3] - box[1] - self.tile = [("eps", (0,0) + self.size, offset, + self.tile = [("eps", (0, 0) + self.size, offset, (length, box))] except: pass @@ -288,7 +303,6 @@ class EpsImageFile(ImageFile.ImageFile): if s[:1] != "%": break - # # Scan for an "ImageData" descriptor @@ -307,7 +321,8 @@ class EpsImageFile(ImageFile.ImageFile): [x, y, bi, mo, z3, z4, en, id] =\ s[11:].split(None, 7) - x = int(x); y = int(y) + x = int(x) + y = int(y) bi = int(bi) mo = int(mo) @@ -363,11 +378,12 @@ class EpsImageFile(ImageFile.ImageFile): self.size = self.im.size self.tile = [] - def load_seek(self,*args,**kwargs): + def load_seek(self, *args, **kwargs): # we can't incrementally load, so force ImageFile.parser to - # use our custom load method by defining this method. + # use our custom load method by defining this method. pass + # # -------------------------------------------------------------------- @@ -392,8 +408,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 @@ -407,7 +425,7 @@ def _save(im, fp, filename, eps=1): # write EPS header fp.write("%!PS-Adobe-3.0 EPSF-3.0\n") fp.write("%%Creator: PIL 0.1 EpsEncode\n") - #fp.write("%%CreationDate: %s"...) + # fp.write("%%CreationDate: %s"...) fp.write("%%%%BoundingBox: 0 0 %d %d\n" % im.size) fp.write("%%Pages: 1\n") fp.write("%%EndComments\n") @@ -421,13 +439,13 @@ def _save(im, fp, filename, eps=1): fp.write("10 dict begin\n") fp.write("/buf %d string def\n" % (im.size[0] * operator[1])) fp.write("%d %d scale\n" % im.size) - fp.write("%d %d 8\n" % im.size) # <= bits + fp.write("%d %d 8\n" % im.size) # <= bits fp.write("[%d 0 0 -%d 0 %d]\n" % (im.size[0], im.size[1], im.size[1])) fp.write("{ currentfile buf readhexstring pop } bind\n") fp.write(operator[2] + "\n") fp.flush() - ImageFile._save(im, base_fp, [("eps", (0,0)+im.size, 0, None)]) + ImageFile._save(im, base_fp, [("eps", (0, 0)+im.size, 0, None)]) fp.write("\n%%%%EndBinary\n") fp.write("grestore end\n") diff --git a/PIL/FpxImagePlugin.py b/PIL/FpxImagePlugin.py index 64c7b1568..7e1d09dc8 100644 --- a/PIL/FpxImagePlugin.py +++ b/PIL/FpxImagePlugin.py @@ -34,16 +34,18 @@ MODES = { (0x00020000, 0x00020001, 0x00020002): ("RGB", "YCC;P"), (0x00028000, 0x00028001, 0x00028002, 0x00027ffe): ("RGBA", "YCCA;P"), # standard RGB (NIFRGB) - (0x00030000, 0x00030001, 0x00030002): ("RGB","RGB"), - (0x00038000, 0x00038001, 0x00038002, 0x00037ffe): ("RGBA","RGBA"), + (0x00030000, 0x00030001, 0x00030002): ("RGB", "RGB"), + (0x00038000, 0x00038001, 0x00038002, 0x00037ffe): ("RGBA", "RGBA"), } + # # -------------------------------------------------------------------- def _accept(prefix): return prefix[:8] == MAGIC + ## # Image plugin for the FlashPix images. @@ -67,7 +69,7 @@ class FpxImageFile(ImageFile.ImageFile): self._open_index(1) - def _open_index(self, index = 1): + def _open_index(self, index=1): # # get the Image Contents Property Set @@ -95,7 +97,7 @@ class FpxImageFile(ImageFile.ImageFile): id = self.maxid << 16 - s = prop[0x2000002|id] + s = prop[0x2000002 | id] colors = [] for i in range(i32(s, 4)): @@ -107,7 +109,7 @@ class FpxImageFile(ImageFile.ImageFile): # load JPEG tables, if any self.jpeg = {} for i in range(256): - id = 0x3000001|(i << 16) + id = 0x3000001 | (i << 16) if id in prop: self.jpeg[i] = prop[id] @@ -115,7 +117,7 @@ class FpxImageFile(ImageFile.ImageFile): self._open_subimage(1, self.maxid) - def _open_subimage(self, index = 1, subimage = 0): + def _open_subimage(self, index=1, subimage=0): # # setup tile descriptors for a given subimage @@ -159,14 +161,14 @@ class FpxImageFile(ImageFile.ImageFile): compression = i32(s, i+8) if compression == 0: - self.tile.append(("raw", (x,y,x+xtile,y+ytile), - i32(s, i) + 28, (self.rawmode))) + self.tile.append(("raw", (x, y, x+xtile, y+ytile), + i32(s, i) + 28, (self.rawmode))) elif compression == 1: # FIXME: the fill decoder is not implemented - self.tile.append(("fill", (x,y,x+xtile,y+ytile), - i32(s, i) + 28, (self.rawmode, s[12:16]))) + self.tile.append(("fill", (x, y, x+xtile, y+ytile), + i32(s, i) + 28, (self.rawmode, s[12:16]))) elif compression == 2: @@ -182,14 +184,14 @@ class FpxImageFile(ImageFile.ImageFile): # this problem : jpegmode, rawmode = "YCbCrK", "CMYK" else: - jpegmode = None # let the decoder decide + jpegmode = None # let the decoder decide else: # The image is stored as defined by rawmode jpegmode = rawmode - self.tile.append(("jpeg", (x,y,x+xtile,y+ytile), - i32(s, i) + 28, (rawmode, jpegmode))) + self.tile.append(("jpeg", (x, y, x+xtile, y+ytile), + i32(s, i) + 28, (rawmode, jpegmode))) # FIXME: jpeg tables are tile dependent; the prefix # data must be placed in the tile descriptor itself! @@ -204,7 +206,7 @@ class FpxImageFile(ImageFile.ImageFile): if x >= xsize: x, y = 0, y + ytile if y >= ysize: - break # isn't really required + break # isn't really required self.stream = stream self.fp = None @@ -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) diff --git a/PIL/GbrImagePlugin.py b/PIL/GbrImagePlugin.py index e2a5d0c9c..0e686326c 100644 --- a/PIL/GbrImagePlugin.py +++ b/PIL/GbrImagePlugin.py @@ -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. diff --git a/PIL/GdImageFile.py b/PIL/GdImageFile.py index f1dbc7c62..080153a9f 100644 --- a/PIL/GdImageFile.py +++ b/PIL/GdImageFile.py @@ -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 Image.open function. To use @@ -52,7 +53,7 @@ class GdImageFile(ImageFile.ImageFile): # Header s = self.fp.read(775) - self.mode = "L" # FIXME: "P" + self.mode = "L" # FIXME: "P" self.size = i16(s[0:2]), i16(s[2:4]) # transparency index @@ -62,7 +63,8 @@ class GdImageFile(ImageFile.ImageFile): self.palette = ImagePalette.raw("RGB", s[7:]) - self.tile = [("raw", (0,0)+self.size, 775, ("L", 0, -1))] + self.tile = [("raw", (0, 0)+self.size, 775, ("L", 0, -1))] + ## # Load texture from a GD image file. @@ -73,7 +75,7 @@ class GdImageFile(ImageFile.ImageFile): # @return An image instance. # @exception IOError If the image could not be read. -def open(fp, mode = "r"): +def open(fp, mode="r"): if mode != "r": raise ValueError("bad mode") diff --git a/PIL/GifImagePlugin.py b/PIL/GifImagePlugin.py index 640af9efc..0b154f417 100644 --- a/PIL/GifImagePlugin.py +++ b/PIL/GifImagePlugin.py @@ -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. @@ -79,16 +80,16 @@ class GifImageFile(ImageFile.ImageFile): # get global palette self.info["background"] = i8(s[11]) # check if palette contains colour indices - p = self.fp.read(3< 0: paletteBytes += o8(0) * 3 * actualTargetSizeDiff @@ -484,17 +492,18 @@ def getheader(im, palette=None, info=None): return header, usedPaletteColors -def getdata(im, offset = (0, 0), **params): +def getdata(im, offset=(0, 0), **params): """Return a list of strings representing this image. The first string is a local image header, the rest contains encoded image data.""" class collector: data = [] + def write(self, data): self.data.append(data) - im.load() # make sure raster data is available + im.load() # make sure raster data is available fp = collector() @@ -510,9 +519,9 @@ def getdata(im, offset = (0, 0), **params): o8(0) + # flags o8(8)) # bits - ImageFile._save(im, fp, [("gif", (0,0)+im.size, 0, RAWMODE[im.mode])]) + ImageFile._save(im, fp, [("gif", (0, 0)+im.size, 0, RAWMODE[im.mode])]) - fp.write(b"\0") # end of image data + fp.write(b"\0") # end of image data finally: del im.encoderinfo diff --git a/PIL/GribStubImagePlugin.py b/PIL/GribStubImagePlugin.py index d76585c99..8ffad8100 100644 --- a/PIL/GribStubImagePlugin.py +++ b/PIL/GribStubImagePlugin.py @@ -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") diff --git a/PIL/Hdf5StubImagePlugin.py b/PIL/Hdf5StubImagePlugin.py index eb888d8c3..f7945be7e 100644 --- a/PIL/Hdf5StubImagePlugin.py +++ b/PIL/Hdf5StubImagePlugin.py @@ -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" diff --git a/PIL/IcnsImagePlugin.py b/PIL/IcnsImagePlugin.py index ca7a14931..e88b84985 100644 --- a/PIL/IcnsImagePlugin.py +++ b/PIL/IcnsImagePlugin.py @@ -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) @@ -103,10 +109,11 @@ def read_png_or_jpeg2000(fobj, start_length, size): im = PngImagePlugin.PngImageFile(fobj) return {"RGBA": im} elif sig[:4] == b'\xff\x4f\xff\x51' \ - or sig[:4] == b'\x0d\x0a\x87\x0a' \ - or sig == b'\x00\x00\x00\x0cjP \x0d\x0a\x87\x0a': + 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 = { @@ -225,7 +233,7 @@ class IcnsFile: im = channels.get('RGBA', None) if im: return im - + im = channels.get("RGB").copy() try: im.putalpha(channels["A"]) @@ -233,6 +241,7 @@ class IcnsFile: pass return im + ## # Image plugin for Mac OS icons. @@ -275,7 +284,7 @@ class IcnsImageFile(ImageFile.ImageFile): # If this is a PNG or JPEG 2000, it won't be loaded yet im.load() - + self.im = im.im self.mode = im.mode self.size = im.size @@ -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 diff --git a/PIL/IcoImagePlugin.py b/PIL/IcoImagePlugin.py index 268e93d6c..2dc46ea18 100644 --- a/PIL/IcoImagePlugin.py +++ b/PIL/IcoImagePlugin.py @@ -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 . +# This plugin is a refactored version of Win32IconImagePlugin by Bryan Davis +# . # 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) @@ -127,7 +133,7 @@ class IcoFile: # change tile dimension to only encompass XOR image im.size = (im.size[0], int(im.size[1] / 2)) d, e, o, a = im.tile[0] - im.tile[0] = d, (0,0) + im.size, o, a + im.tile[0] = d, (0, 0) + im.size, o, a # figure out where AND mask image starts mode = a[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 . + This plugin is a refactored version of Win32IconImagePlugin by Bryan Davis + . 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 # # -------------------------------------------------------------------- diff --git a/PIL/ImImagePlugin.py b/PIL/ImImagePlugin.py index a5eeef76a..2e0ecded3 100644 --- a/PIL/ImImagePlugin.py +++ b/PIL/ImImagePlugin.py @@ -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 # -------------------------------------------------------------------- @@ -46,8 +46,8 @@ SCALE = "Scale (x,y)" SIZE = "Image size (x*y)" MODE = "Image type" -TAGS = { COMMENT:0, DATE:0, EQUIPMENT:0, FRAMES:0, LUT:0, NAME:0, - SCALE:0, SIZE:0, MODE:0 } +TAGS = {COMMENT: 0, DATE: 0, EQUIPMENT: 0, FRAMES: 0, LUT: 0, NAME: 0, + SCALE: 0, SIZE: 0, MODE: 0} OPEN = { # ifunc93/p3cfunc formats @@ -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) @@ -155,7 +157,7 @@ class ImImageFile(ImageFile.ImageFile): if m: - k, v = m.group(1,2) + k, v = m.group(1, 2) # Don't know if this is the correct encoding, but a decent guess # (I guess) @@ -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") @@ -204,8 +207,8 @@ class ImImageFile(ImageFile.ImageFile): if LUT in self.info: # convert lookup table to palette or lut attribute palette = self.fp.read(768) - greyscale = 1 # greyscale palette - linear = 1 # linear greyscale palette + greyscale = 1 # greyscale palette + linear = 1 # linear greyscale palette for i in range(256): if palette[i] == palette[i+256] == palette[i+512]: if i8(palette[i]) != i: @@ -230,7 +233,7 @@ class ImImageFile(ImageFile.ImageFile): self.__offset = offs = self.fp.tell() - self.__fp = self.fp # FIXME: hack + self.__fp = self.fp # FIXME: hack if self.rawmode[:2] == "F;": @@ -239,7 +242,7 @@ class ImImageFile(ImageFile.ImageFile): # use bit decoder (if necessary) bits = int(self.rawmode[2:]) if bits not in [8, 16, 32]: - self.tile = [("bit", (0,0)+self.size, offs, + self.tile = [("bit", (0, 0)+self.size, offs, (bits, 8, 3, 0, -1))] return except ValueError: @@ -249,12 +252,13 @@ class ImImageFile(ImageFile.ImageFile): # Old LabEye/3PC files. Would be very surprised if anyone # ever stumbled upon such a file ;-) size = self.size[0] * self.size[1] - self.tile = [("raw", (0,0)+self.size, offs, ("G", 0, -1)), - ("raw", (0,0)+self.size, offs+size, ("R", 0, -1)), - ("raw", (0,0)+self.size, offs+2*size, ("B", 0, -1))] + self.tile = [("raw", (0, 0)+self.size, offs, ("G", 0, -1)), + ("raw", (0, 0)+self.size, offs+size, ("R", 0, -1)), + ("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): @@ -276,7 +280,7 @@ class ImImageFile(ImageFile.ImageFile): self.fp = self.__fp - 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 tell(self): @@ -305,6 +309,7 @@ SAVE = { "YCbCr": ("YCC", "YCbCr;L") } + def _save(im, fp, filename, check=0): try: @@ -329,8 +334,8 @@ def _save(im, fp, filename, check=0): fp.write(b"Lut: 1\r\n") fp.write(b"\000" * (511-fp.tell()) + b"\032") if im.mode == "P": - fp.write(im.im.getpalette("RGB", "RGB;L")) # 768 bytes - ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, 0, -1))]) + fp.write(im.im.getpalette("RGB", "RGB;L")) # 768 bytes + ImageFile._save(im, fp, [("raw", (0, 0)+im.size, 0, (rawmode, 0, -1))]) # # -------------------------------------------------------------------- diff --git a/PIL/ImageColor.py b/PIL/ImageColor.py index 98a241bb0..fc95e6d19 100644 --- a/PIL/ImageColor.py +++ b/PIL/ImageColor.py @@ -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 diff --git a/PIL/ImageDraw.py b/PIL/ImageDraw.py index a03d26016..9fc343ac7 100644 --- a/PIL/ImageDraw.py +++ b/PIL/ImageDraw.py @@ -61,7 +61,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 @@ -85,7 +85,7 @@ class ImageDraw: # FIXME: fix Fill2 to properly support matte for I+F images self.fontmode = "1" else: - self.fontmode = "L" # aliasing is okay for other modes + self.fontmode = "L" # aliasing is okay for other modes self.fill = 0 self.font = None @@ -280,6 +280,7 @@ class ImageDraw: font = self.getfont() return font.getsize(text) + ## # A simple 2D drawing interface for PIL images. # @@ -302,6 +303,7 @@ try: except: Outline = None + ## # (Experimental) A more advanced 2D drawing interface for PIL images, # based on the WCK interface. @@ -325,6 +327,7 @@ def getdraw(im=None, hints=None): im = handler.Draw(im) return im, handler + ## # (experimental) Fills a bounded region with a given color. # @@ -344,10 +347,10 @@ def floodfill(image, xy, value, border=None): try: background = pixel[x, y] if background == value: - return # seed point already has fill color + return # seed point already has fill color pixel[x, y] = value except IndexError: - return # seed point outside image + return # seed point outside image edge = [(x, y)] if border is None: while edge: diff --git a/PIL/ImageDraw2.py b/PIL/ImageDraw2.py index 146cc8b16..c967a200f 100644 --- a/PIL/ImageDraw2.py +++ b/PIL/ImageDraw2.py @@ -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 diff --git a/PIL/ImageFile.py b/PIL/ImageFile.py index 5e4745d76..0778c6f66 100644 --- a/PIL/ImageFile.py +++ b/PIL/ImageFile.py @@ -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 @@ -74,7 +79,7 @@ class ImageFile(Image.Image): Image.Image.__init__(self) self.tile = None - self.readonly = 1 # until we know better + self.readonly = 1 # until we know better self.decoderconfig = () self.decodermaxblock = MAXBLOCK @@ -90,19 +95,19 @@ class ImageFile(Image.Image): try: self._open() - except IndexError as v: # end of data + except IndexError as v: # end of data if Image.DEBUG > 1: traceback.print_exc() raise SyntaxError(v) - except TypeError as v: # end of data (ord) + except TypeError as v: # end of data (ord) if Image.DEBUG > 1: traceback.print_exc() raise SyntaxError(v) - except KeyError as v: # unsupported mode + except KeyError as v: # unsupported mode if Image.DEBUG > 1: traceback.print_exc() raise SyntaxError(v) - except EOFError as v: # got header but not the first frame + except EOFError as v: # got header but not the first frame if Image.DEBUG > 1: traceback.print_exc() raise SyntaxError(v) @@ -135,8 +140,8 @@ class ImageFile(Image.Image): self.map = None use_mmap = self.filename and len(self.tile) == 1 # As of pypy 2.1.0, memory mapping was failing here. - use_mmap = use_mmap and not hasattr(sys, 'pypy_version_info') - + use_mmap = use_mmap and not hasattr(sys, 'pypy_version_info') + readonly = 0 # look for read/seek overrides @@ -203,23 +208,25 @@ class ImageFile(Image.Image): while True: try: s = read(self.decodermaxblock) - except IndexError as ie: # truncated png/gif + except IndexError as ie: # truncated png/gif if LOAD_TRUNCATED_IMAGES: break else: raise IndexError(ie) - if not s and not d.handles_eof: # truncated jpeg + if not s and not d.handles_eof: # truncated jpeg 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) @@ -231,7 +238,7 @@ class ImageFile(Image.Image): self.tile = [] self.readonly = readonly - self.fp = None # might be shared + self.fp = None # might be shared if not self.map and (not LOAD_TRUNCATED_IMAGES or t == 0) and e < 0: # still raised if decoder fails to return anything @@ -378,10 +385,10 @@ class Parser: fp = io.BytesIO(self.data) im = Image.open(fp) finally: - fp.close() # explicitly close the virtual file + fp.close() # explicitly close the virtual file except IOError: # traceback.print_exc() - pass # not enough data + pass # not enough data else: flag = hasattr(im, "load_seek") or hasattr(im, "load_read") if flag or len(im.tile) != 1: @@ -431,9 +438,10 @@ class Parser: self.image = Image.open(fp) finally: self.image.load() - fp.close() # explicitly close the virtual file + fp.close() # explicitly close the virtual file return self.image + # -------------------------------------------------------------------- def _save(im, fp, tile, bufsize=0): @@ -450,10 +458,10 @@ 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 + bufsize = max(MAXBLOCK, bufsize, im.size[0] * 4) # see RawEncode.c try: fh = fp.fileno() fp.flush() @@ -483,7 +491,8 @@ def _save(im, fp, tile, bufsize=0): raise IOError("encoder error %d when writing image file" % s) try: fp.flush() - except: pass + except: + pass def _safe_read(fp, size): diff --git a/PIL/ImageFilter.py b/PIL/ImageFilter.py index ac8fe9f19..43dd922d3 100644 --- a/PIL/ImageFilter.py +++ b/PIL/ImageFilter.py @@ -43,7 +43,7 @@ class Kernel(Filter): def __init__(self, size, kernel, scale=None, offset=0): if scale is None: # default scale is sum of kernel - scale = reduce(lambda a,b: a+b, kernel) + scale = reduce(lambda a, b: a+b, kernel) if size[0] * size[1] != len(kernel): raise ValueError("not enough coefficients in kernel") self.filterargs = size, scale, offset, kernel diff --git a/PIL/ImageGrab.py b/PIL/ImageGrab.py index 9bb190934..ac925b683 100644 --- a/PIL/ImageGrab.py +++ b/PIL/ImageGrab.py @@ -40,7 +40,7 @@ def grab(bbox=None): def grabclipboard(): - debug = 0 # temporary interface + debug = 0 # temporary interface data = Image.core.grabclipboard(debug) if isinstance(data, bytes): from PIL import BmpImagePlugin diff --git a/PIL/ImageMode.py b/PIL/ImageMode.py index c3931b525..295069108 100644 --- a/PIL/ImageMode.py +++ b/PIL/ImageMode.py @@ -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. diff --git a/PIL/ImageMorph.py b/PIL/ImageMorph.py index 3f15621a6..996eacb7d 100644 --- a/PIL/ImageMorph.py +++ b/PIL/ImageMorph.py @@ -35,14 +35,14 @@ class LutBuilder: returned if no other match is found. Operations: - + - 4 - 4 way rotation - N - Negate - 1 - Dummy op for no other operation (an op must always be given) - M - Mirroring Example:: - + lb = LutBuilder(patterns = ["4:(... .1. 111)->1"]) lut = lb.build_lut() diff --git a/PIL/ImageOps.py b/PIL/ImageOps.py index 9f84eff86..b3afd9e95 100644 --- a/PIL/ImageOps.py +++ b/PIL/ImageOps.py @@ -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) @@ -273,7 +278,7 @@ def fit(image, size, method=Image.NEAREST, bleed=0.0, centering=(0.5, 0.5)): centering = [centering[0], centering[1]] if centering[0] > 1.0 or centering[0] < 0.0: - centering [0] = 0.50 + centering[0] = 0.50 if centering[1] > 1.0 or centering[1] < 0.0: centering[1] = 0.50 @@ -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])""" diff --git a/PIL/ImageSequence.py b/PIL/ImageSequence.py index 513c9247b..dd01e2902 100644 --- a/PIL/ImageSequence.py +++ b/PIL/ImageSequence.py @@ -15,6 +15,7 @@ ## + class Iterator: """ This class implements an iterator object that can be used to loop @@ -38,4 +39,4 @@ class Iterator: self.im.seek(ix) return self.im except EOFError: - raise IndexError # end of sequence + raise IndexError # end of sequence diff --git a/PIL/ImageShow.py b/PIL/ImageShow.py index 40fe629d9..9527dbf97 100644 --- a/PIL/ImageShow.py +++ b/PIL/ImageShow.py @@ -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,17 +25,19 @@ else: _viewers = [] + def register(viewer, order=1): try: if issubclass(viewer, Viewer): viewer = viewer() except TypeError: - pass # raised if viewer wasn't a class + pass # raised if viewer wasn't a class if order > 0: _viewers.append(viewer) 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 diff --git a/PIL/ImageStat.py b/PIL/ImageStat.py index d84e2cbf1..7e023c673 100644 --- a/PIL/ImageStat.py +++ b/PIL/ImageStat.py @@ -21,20 +21,21 @@ # See the README file for information on usage and redistribution. # -import operator, math +import math +import operator from functools import reduce class Stat: - def __init__(self, image_or_list, mask = None): + def __init__(self, image_or_list, mask=None): try: if mask: self.h = image_or_list.histogram(mask) else: self.h = image_or_list.histogram() except AttributeError: - self.h = image_or_list # assume it to be a histogram list + self.h = image_or_list # assume it to be a histogram list if not isinstance(self.h, list): raise TypeError("first argument must be image or list") self.bands = list(range(len(self.h) // 256)) @@ -58,7 +59,7 @@ class Stat: if histogram[i]: n = min(n, i) x = max(x, i) - return n, x # returns (255, 0) if there's no data in the histogram + return n, x # returns (255, 0) if there's no data in the histogram v = [] for i in range(0, len(self.h), 256): @@ -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" @@ -144,4 +144,4 @@ class Stat: v.append(math.sqrt(self.var[i])) return v -Global = Stat # compatibility +Global = Stat # compatibility diff --git a/PIL/ImageTk.py b/PIL/ImageTk.py index 1e81d240e..5fb5ecff3 100644 --- a/PIL/ImageTk.py +++ b/PIL/ImageTk.py @@ -40,17 +40,19 @@ from PIL import Image _pilbitmap_ok = None + def _pilbitmap_check(): global _pilbitmap_ok if _pilbitmap_ok is None: try: - im = Image.new("1", (1,1)) + im = Image.new("1", (1, 1)) tkinter.BitmapImage(data="PIL:%d" % im.im.id) _pilbitmap_ok = 1 except tkinter.TclError: _pilbitmap_ok = 0 return _pilbitmap_ok + # -------------------------------------------------------------------- # PhotoImage @@ -95,7 +97,7 @@ class PhotoImage: try: mode = image.palette.mode except AttributeError: - mode = "RGB" # default + mode = "RGB" # default size = image.size kw["width"], kw["height"] = size else: @@ -118,8 +120,7 @@ class PhotoImage: try: self.__photo.tk.call("image", "delete", name) except: - pass # ignore internal errors - + pass # ignore internal errors def __str__(self): """ @@ -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 @@ -170,13 +168,13 @@ class PhotoImage: block = image else: block = image.new_block(self.__mode, im.size) - image.convert2(block, image) # convert directly between buffers + image.convert2(block, image) # convert directly between buffers tk = self.__photo.tk try: tk.call("PyImagingPhoto", self.__photo, block.id) - except tkinter.TclError as v: + except tkinter.TclError: # activate Tkinter hook try: from PIL import _imagingtk @@ -186,7 +184,7 @@ class PhotoImage: _imagingtk.tkinit(id(tk), 0) tk.call("PyImagingPhoto", self.__photo, block.id) except (ImportError, AttributeError, tkinter.TclError): - raise # configuration problem; cannot attach to Tkinter + raise # configuration problem; cannot attach to Tkinter # -------------------------------------------------------------------- # BitmapImage @@ -226,7 +224,7 @@ class BitmapImage: # fast way (requires the pilbitmap booster patch) image.load() kw["data"] = "PIL:%d" % image.im.id - self.__im = image # must keep a reference + self.__im = image # must keep a reference else: # slow but safe way kw["data"] = image.tobitmap() @@ -238,8 +236,7 @@ class BitmapImage: try: self.__photo.tk.call("image", "delete", name) except: - pass # ignore internal errors - + pass # ignore internal errors def width(self): """ @@ -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. @@ -286,7 +282,7 @@ def _show(image, title): else: self.image = PhotoImage(im, master=master) tkinter.Label.__init__(self, master, image=self.image, - bg="black", bd=0) + bg="black", bd=0) if not tkinter._default_root: raise IOError("tkinter not initialized") diff --git a/PIL/ImageTransform.py b/PIL/ImageTransform.py index 5a8f9e9ec..81f90502c 100644 --- a/PIL/ImageTransform.py +++ b/PIL/ImageTransform.py @@ -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. #

@@ -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. #

@@ -68,6 +74,7 @@ class AffineTransform(Transform): class ExtentTransform(Transform): method = Image.EXTENT + ## # Define an quad image transform. #

@@ -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. diff --git a/PIL/ImageWin.py b/PIL/ImageWin.py index aa90b887b..3e0bbaf99 100644 --- a/PIL/ImageWin.py +++ b/PIL/ImageWin.py @@ -29,9 +29,11 @@ class HDC: """ 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 @@ -40,6 +42,7 @@ class HWND: """ def __init__(self, wnd): self.wnd = wnd + def __int__(self): return self.wnd @@ -79,7 +82,6 @@ class Dib: if image: self.paste(image) - def expose(self, handle): """ Copy the bitmap contents to a device context. @@ -109,7 +111,7 @@ class Dib: necessary. """ if not src: - src = (0,0) + self.size + src = (0, 0) + self.size if isinstance(handle, HWND): dc = self.image.getdc(handle) try: @@ -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. diff --git a/PIL/Jpeg2KImagePlugin.py b/PIL/Jpeg2KImagePlugin.py index 53b10ca1a..446699fdb 100644 --- a/PIL/Jpeg2KImagePlugin.py +++ b/PIL/Jpeg2KImagePlugin.py @@ -72,7 +72,7 @@ def _parse_jp2_header(fp): if lbox < hlen: raise SyntaxError('Invalid JP2 header length') - + if tbox == b'jp2h': header = fp.read(lbox - hlen) break diff --git a/PIL/McIdasImagePlugin.py b/PIL/McIdasImagePlugin.py index 3aef10ba8..c3f255fd2 100644 --- a/PIL/McIdasImagePlugin.py +++ b/PIL/McIdasImagePlugin.py @@ -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") diff --git a/PIL/MicImagePlugin.py b/PIL/MicImagePlugin.py index 84e962860..cdfaf3eda 100644 --- a/PIL/MicImagePlugin.py +++ b/PIL/MicImagePlugin.py @@ -31,6 +31,7 @@ from PIL.OleFileIO import * def _accept(prefix): return prefix[:8] == MAGIC + ## # Image plugin for Microsoft's Image Composer file format. diff --git a/PIL/MpegImagePlugin.py b/PIL/MpegImagePlugin.py index 02e6adc00..9aca58f16 100644 --- a/PIL/MpegImagePlugin.py +++ b/PIL/MpegImagePlugin.py @@ -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. diff --git a/PIL/MpoImagePlugin.py b/PIL/MpoImagePlugin.py index d053d9026..13e3ef9b5 100644 --- a/PIL/MpoImagePlugin.py +++ b/PIL/MpoImagePlugin.py @@ -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. @@ -38,19 +41,19 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile): format_description = "MPO (CIPA DC-007)" def _open(self): - self.fp.seek(0) # prep the fp in order to pass the JPEG test + self.fp.seek(0) # prep the fp in order to pass the JPEG test 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 # gets broken within JpegImagePlugin. assert self.__framecount == len(self.__mpoffsets) - del self.info['mpoffset'] # no longer needed - self.__fp = self.fp # FIXME: hack - self.__fp.seek(self.__mpoffsets[0]) # get ready to read first frame + del self.info['mpoffset'] # no longer needed + self.__fp = self.fp # FIXME: hack + self.__fp.seek(self.__mpoffsets[0]) # get ready to read first frame self.__frame = 0 self.offset = 0 # for now we can only handle reading and individual frame extraction @@ -79,7 +82,7 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile): # Note that since MPO shares a factory with JPEG, we do not need to do a # separate registration for it here. -#Image.register_open("MPO", JpegImagePlugin.jpeg_factory, _accept) +# Image.register_open("MPO", JpegImagePlugin.jpeg_factory, _accept) Image.register_save("MPO", _save) Image.register_extension("MPO", ".mpo") diff --git a/PIL/MspImagePlugin.py b/PIL/MspImagePlugin.py index 743ebe172..4753be7cd 100644 --- a/PIL/MspImagePlugin.py +++ b/PIL/MspImagePlugin.py @@ -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). @@ -57,15 +59,16 @@ class MspImageFile(ImageFile.ImageFile): self.size = i16(s[4:]), i16(s[6:]) if s[:4] == b"DanM": - self.tile = [("raw", (0,0)+self.size, 32, ("1", 0, 1))] + self.tile = [("raw", (0, 0)+self.size, 32, ("1", 0, 1))] else: - self.tile = [("msp", (0,0)+self.size, 32+2*self.size[1], None)] + self.tile = [("msp", (0, 0)+self.size, 32+2*self.size[1], None)] # # write MSP files (uncompressed only) o16 = _binary.o16le + def _save(im, fp, filename): if im.mode != "1": @@ -74,7 +77,7 @@ def _save(im, fp, filename): # create MSP header header = [0] * 16 - header[0], header[1] = i16(b"Da"), i16(b"nM") # version 1 + header[0], header[1] = i16(b"Da"), i16(b"nM") # version 1 header[2], header[3] = im.size header[4], header[5] = 1, 1 header[6], header[7] = 1, 1 @@ -83,14 +86,14 @@ def _save(im, fp, filename): sum = 0 for h in header: sum = sum ^ h - header[12] = sum # FIXME: is this the right field? + header[12] = sum # FIXME: is this the right field? # header for h in header: fp.write(o16(h)) # image body - ImageFile._save(im, fp, [("raw", (0,0)+im.size, 32, ("1", 0, 1))]) + ImageFile._save(im, fp, [("raw", (0, 0)+im.size, 32, ("1", 0, 1))]) # # registry diff --git a/PIL/PSDraw.py b/PIL/PSDraw.py index 26fdb74ea..208f7b6a6 100644 --- a/PIL/PSDraw.py +++ b/PIL/PSDraw.py @@ -19,6 +19,7 @@ from __future__ import print_function from PIL import EpsImagePlugin + ## # Simple Postscript graphics interface. @@ -34,7 +35,7 @@ class PSDraw: fp = sys.stdout self.fp = fp - def begin_document(self, id = None): + def begin_document(self, id=None): """Set up printing of a document. (Write Postscript DSC header.)""" # FIXME: incomplete self.fp.write("%!PS-Adobe-3.0\n" @@ -42,7 +43,7 @@ class PSDraw: "/showpage { } def\n" "%%EndComments\n" "%%BeginDocument\n") - #self.fp.write(ERROR_PS) # debugging! + # self.fp.write(ERROR_PS) # debugging! self.fp.write(EDROFF_PS) self.fp.write(VDI_PS) self.fp.write("%%EndProlog\n") @@ -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 @@ -73,7 +74,8 @@ class PSDraw: def setink(self, ink): """ - .. warning:: This has been in the PIL API for ages but was never implemented. + .. warning:: This has been in the PIL API for ages but was never + implemented. """ print("*** NOT YET IMPLEMENTED ***") @@ -112,14 +114,14 @@ class PSDraw: xy = xy + (text,) self.fp.write("%d %d M (%s) S\n" % xy) - def image(self, box, im, dpi = None): + def image(self, box, im, dpi=None): """Draw a PIL image, centered in the given box.""" # default resolution depends on mode if not dpi: if im.mode == "1": - dpi = 200 # fax + dpi = 200 # fax else: - dpi = 100 # greyscale + dpi = 100 # greyscale # image size (on paper) x = float(im.size[0] * 72) / dpi y = float(im.size[1] * 72) / dpi @@ -127,9 +129,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)) diff --git a/PIL/PaletteFile.py b/PIL/PaletteFile.py index 5627f7b86..37ba4cbff 100644 --- a/PIL/PaletteFile.py +++ b/PIL/PaletteFile.py @@ -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 diff --git a/PIL/PcdImagePlugin.py b/PIL/PcdImagePlugin.py index 70066e76b..5ce7aa48c 100644 --- a/PIL/PcdImagePlugin.py +++ b/PIL/PcdImagePlugin.py @@ -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 @@ -43,13 +44,13 @@ class PcdImageFile(ImageFile.ImageFile): orientation = i8(s[1538]) & 3 if orientation == 1: - self.tile_post_rotate = 90 # hack + self.tile_post_rotate = 90 # hack elif orientation == 3: self.tile_post_rotate = -90 self.mode = "RGB" - self.size = 768, 512 # FIXME: not correct for rotated images! - self.tile = [("pcd", (0,0)+self.size, 96*2048, None)] + self.size = 768, 512 # FIXME: not correct for rotated images! + self.tile = [("pcd", (0, 0)+self.size, 96*2048, None)] def draft(self, mode, size): @@ -60,7 +61,7 @@ class PcdImageFile(ImageFile.ImageFile): if size: scale = max(self.size[0] / size[0], self.size[1] / size[1]) - for s, o in [(4,0*2048), (2,0*2048), (1,96*2048)]: + for s, o in [(4, 0*2048), (2, 0*2048), (1, 96*2048)]: if scale >= s: break # e = e[0], e[1], (e[2]-e[0]+s-1)/s+e[0], (e[3]-e[1]+s-1)/s+e[1] diff --git a/PIL/PcfFontFile.py b/PIL/PcfFontFile.py index c40d3986d..c19a1c532 100644 --- a/PIL/PcfFontFile.py +++ b/PIL/PcfFontFile.py @@ -23,20 +23,20 @@ from PIL import _binary # -------------------------------------------------------------------- # declarations -PCF_MAGIC = 0x70636601 # "\x01fcp" +PCF_MAGIC = 0x70636601 # "\x01fcp" -PCF_PROPERTIES = (1<<0) -PCF_ACCELERATORS = (1<<1) -PCF_METRICS = (1<<2) -PCF_BITMAPS = (1<<3) -PCF_INK_METRICS = (1<<4) -PCF_BDF_ENCODINGS = (1<<5) -PCF_SWIDTHS = (1<<6) -PCF_GLYPH_NAMES = (1<<7) -PCF_BDF_ACCELERATORS = (1<<8) +PCF_PROPERTIES = (1 << 0) +PCF_ACCELERATORS = (1 << 1) +PCF_METRICS = (1 << 2) +PCF_BITMAPS = (1 << 3) +PCF_INK_METRICS = (1 << 4) +PCF_BDF_ENCODINGS = (1 << 5) +PCF_SWIDTHS = (1 << 6) +PCF_GLYPH_NAMES = (1 << 7) +PCF_BDF_ACCELERATORS = (1 << 8) BYTES_PER_ROW = [ - lambda bits: ((bits+7) >> 3), + lambda bits: ((bits+7) >> 3), lambda bits: ((bits+15) >> 3) & ~1, lambda bits: ((bits+31) >> 3) & ~3, lambda bits: ((bits+63) >> 3) & ~7, @@ -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. @@ -122,7 +124,7 @@ class PcfFontFile(FontFile.FontFile): for i in range(nprops): p.append((i32(fp.read(4)), i8(fp.read(1)), i32(fp.read(4)))) if nprops & 3: - fp.seek(4 - (nprops & 3), 1) # pad + fp.seek(4 - (nprops & 3), 1) # pad data = fp.read(i32(fp.read(4))) @@ -202,16 +204,16 @@ class PcfFontFile(FontFile.FontFile): for i in range(4): bitmapSizes.append(i32(fp.read(4))) - byteorder = format & 4 # non-zero => MSB - bitorder = format & 8 # non-zero => MSB - padindex = format & 3 + byteorder = format & 4 # non-zero => MSB + bitorder = format & 8 # non-zero => MSB + padindex = format & 3 bitmapsize = bitmapSizes[padindex] offsets.append(bitmapsize) data = fp.read(bitmapsize) - pad = BYTES_PER_ROW[padindex] + pad = BYTES_PER_ROW[padindex] mode = "1;R" if bitorder: mode = "1" @@ -245,6 +247,6 @@ class PcfFontFile(FontFile.FontFile): try: encoding[i+firstCol] = encodingOffset except IndexError: - break # only load ISO-8859-1 glyphs + break # only load ISO-8859-1 glyphs return encoding diff --git a/PIL/PcxImagePlugin.py b/PIL/PcxImagePlugin.py index 4f6d5a3e5..0765f099e 100644 --- a/PIL/PcxImagePlugin.py +++ b/PIL/PcxImagePlugin.py @@ -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. @@ -52,23 +54,22 @@ class PcxImageFile(ImageFile.ImageFile): raise SyntaxError("not a PCX file") # image - bbox = i16(s,4), i16(s,6), i16(s,8)+1, i16(s,10)+1 + bbox = i16(s, 4), i16(s, 6), i16(s, 8)+1, i16(s, 10)+1 if bbox[2] <= bbox[0] or bbox[3] <= bbox[1]: raise SyntaxError("bad PCX image size") if Image.DEBUG: print ("BBox: %s %s %s %s" % bbox) - # format version = i8(s[1]) bits = i8(s[3]) planes = i8(s[65]) - stride = i16(s,66) + stride = i16(s, 66) if Image.DEBUG: print ("PCX version %s, bits %s, planes %s, stride %s" % (version, bits, planes, stride)) - self.info["dpi"] = i16(s,12), i16(s,14) + self.info["dpi"] = i16(s, 12), i16(s, 14) if bits == 1 and planes == 1: mode = rawmode = "1" @@ -106,7 +107,7 @@ class PcxImageFile(ImageFile.ImageFile): bbox = (0, 0) + self.size if Image.DEBUG: print ("size: %sx%s" % self.size) - + self.tile = [("pcx", bbox, self.fp.tell(), (rawmode, planes * stride))] # -------------------------------------------------------------------- @@ -122,6 +123,7 @@ SAVE = { o16 = _binary.o16le + def _save(im, fp, filename, check=0): try: @@ -138,8 +140,7 @@ def _save(im, fp, filename, check=0): stride += stride % 2 # Stride needs to be kept in sync with the PcxEncode.c version. # Ideally it should be passed in in the state, but the bytes value - # gets overwritten. - + # gets overwritten. if Image.DEBUG: print ("PcxImagePlugin._save: xwidth: %d, bits: %d, stride: %d" % ( @@ -163,13 +164,13 @@ def _save(im, fp, filename, check=0): assert fp.tell() == 128 - ImageFile._save(im, fp, [("pcx", (0,0)+im.size, 0, + ImageFile._save(im, fp, [("pcx", (0, 0)+im.size, 0, (rawmode, bits*planes))]) if im.mode == "P": # colour palette fp.write(o8(12)) - fp.write(im.im.getpalette("RGB", "RGB")) # 768 bytes + fp.write(im.im.getpalette("RGB", "RGB")) # 768 bytes elif im.mode == "L": # greyscale palette fp.write(o8(12)) diff --git a/PIL/PixarImagePlugin.py b/PIL/PixarImagePlugin.py index a4c9032dc..ebf4c8c61 100644 --- a/PIL/PixarImagePlugin.py +++ b/PIL/PixarImagePlugin.py @@ -29,6 +29,7 @@ from PIL import Image, ImageFile, _binary i16 = _binary.i16le i32 = _binary.i32le + ## # Image plugin for PIXAR raster images. @@ -57,7 +58,7 @@ class PixarImageFile(ImageFile.ImageFile): # FIXME: to be continued... # create tile descriptor (assuming "dumped") - self.tile = [("raw", (0,0)+self.size, 1024, (self.mode, 0, 1))] + self.tile = [("raw", (0, 0)+self.size, 1024, (self.mode, 0, 1))] # # -------------------------------------------------------------------- diff --git a/PIL/PngImagePlugin.py b/PIL/PngImagePlugin.py index 4dbedb783..2110aa637 100644 --- a/PIL/PngImagePlugin.py +++ b/PIL/PngImagePlugin.py @@ -52,26 +52,27 @@ _MAGIC = b"\211PNG\r\n\032\n" _MODES = { # supported bits/color combinations, and corresponding modes/rawmodes - (1, 0): ("1", "1"), - (2, 0): ("L", "L;2"), - (4, 0): ("L", "L;4"), - (8, 0): ("L", "L"), - (16,0): ("I", "I;16B"), - (8, 2): ("RGB", "RGB"), - (16,2): ("RGB", "RGB;16B"), - (1, 3): ("P", "P;1"), - (2, 3): ("P", "P;2"), - (4, 3): ("P", "P;4"), - (8, 3): ("P", "P"), - (8, 4): ("LA", "LA"), - (16,4): ("RGBA", "LA;16B"), # LA;16B->LA not yet available - (8, 6): ("RGBA", "RGBA"), - (16,6): ("RGBA", "RGBA;16B"), + (1, 0): ("1", "1"), + (2, 0): ("L", "L;2"), + (4, 0): ("L", "L;4"), + (8, 0): ("L", "L"), + (16, 0): ("I", "I;16B"), + (8, 2): ("RGB", "RGB"), + (16, 2): ("RGB", "RGB;16B"), + (1, 3): ("P", "P;1"), + (2, 3): ("P", "P;2"), + (4, 3): ("P", "P;4"), + (8, 3): ("P", "P"), + (8, 4): ("LA", "LA"), + (16, 4): ("RGBA", "LA;16B"), # LA;16B->LA not yet available + (8, 6): ("RGBA", "RGBA"), + (16, 6): ("RGBA", "RGBA;16B"), } _simple_palette = re.compile(b'^\xff+\x00\xff*$') + # -------------------------------------------------------------------- # Support classes. Suitable for PNG and related formats like MNG etc. @@ -123,15 +124,15 @@ 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"\ - "(bad header checksum in %s)" % cid) + raise SyntaxError("broken PNG file" + "(bad header checksum in %s)" % cid) def crc_skip(self, cid, data): "Read checksum. Used if the C module is not present" self.fp.read(4) - def verify(self, endchunk = b"IEND"): + def verify(self, endchunk=b"IEND"): # Simple approach; just calculate checksum for all remaining # blocks. Must be called directly after open. @@ -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) @@ -218,7 +224,7 @@ class PngStream(ChunkStream): # local copies of Image attributes self.im_info = {} self.im_text = {} - self.im_size = (0,0) + self.im_size = (0, 0) self.im_mode = None self.im_tile = None self.im_palette = None @@ -238,11 +244,12 @@ 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: - icc_profile = None # FIXME + icc_profile = None # FIXME self.im_info["icc_profile"] = icc_profile return s @@ -264,7 +271,7 @@ class PngStream(ChunkStream): def chunk_IDAT(self, pos, length): # image data - self.im_tile = [("zip", (0,0)+self.im_size, pos, self.im_rawmode)] + self.im_tile = [("zip", (0, 0)+self.im_size, pos, self.im_rawmode)] self.im_idat = length raise EOFError @@ -311,7 +318,7 @@ class PngStream(ChunkStream): s = ImageFile._safe_read(self.fp, length) px, py = i32(s), i32(s[4:]) unit = i8(s[8]) - if unit == 1: # meter + if unit == 1: # meter dpi = int(px * 0.0254 + 0.5), int(py * 0.0254 + 0.5) self.im_info["dpi"] = dpi elif unit == 0: @@ -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:]) @@ -396,15 +407,17 @@ class PngStream(ChunkStream): return s self.im_info[k] = self.im_text[k] = iTXt(v, lang, tk) - + return s + # -------------------------------------------------------------------- # PNG reader def _accept(prefix): return prefix[:8] == _MAGIC + ## # Image plugin for PNG images. @@ -451,7 +464,7 @@ class PngImageFile(ImageFile.ImageFile): self.mode = self.png.im_mode self.size = self.png.im_size self.info = self.png.im_info - self.text = self.png.im_text # experimental + self.text = self.png.im_text # experimental self.tile = self.png.im_tile if self.png.im_palette: @@ -460,7 +473,6 @@ class PngImageFile(ImageFile.ImageFile): self.__idat = length # used by load_read() - def verify(self): "Verify PNG file" @@ -489,7 +501,7 @@ class PngImageFile(ImageFile.ImageFile): while self.__idat == 0: # end of chunk, skip forward to next one - self.fp.read(4) # CRC + self.fp.read(4) # CRC cid, pos, length = self.png.read() @@ -509,7 +521,6 @@ class PngImageFile(ImageFile.ImageFile): return self.fp.read(read_bytes) - def load_end(self): "internal: finished reading image data" @@ -526,21 +537,22 @@ o32 = _binary.o32be _OUTMODES = { # supported PIL modes, and corresponding rawmodes/bits/color combinations - "1": ("1", b'\x01\x00'), - "L;1": ("L;1", b'\x01\x00'), - "L;2": ("L;2", b'\x02\x00'), - "L;4": ("L;4", b'\x04\x00'), - "L": ("L", b'\x08\x00'), - "LA": ("LA", b'\x08\x04'), - "I": ("I;16B", b'\x10\x00'), - "P;1": ("P;1", b'\x01\x03'), - "P;2": ("P;2", b'\x02\x03'), - "P;4": ("P;4", b'\x04\x03'), - "P": ("P", b'\x08\x03'), - "RGB": ("RGB", b'\x08\x02'), - "RGBA":("RGBA", b'\x08\x06'), + "1": ("1", b'\x01\x00'), + "L;1": ("L;1", b'\x01\x00'), + "L;2": ("L;2", b'\x02\x00'), + "L;4": ("L;4", b'\x04\x00'), + "L": ("L", b'\x08\x00'), + "LA": ("LA", b'\x08\x04'), + "I": ("I;16B", b'\x10\x00'), + "P;1": ("P;1", b'\x01\x03'), + "P;2": ("P;2", b'\x02\x03'), + "P;4": ("P;4", b'\x04\x03'), + "P": ("P", b'\x08\x03'), + "RGB": ("RGB", b'\x08\x02'), + "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) @@ -597,9 +612,9 @@ def _save(im, fp, filename, chunk=putchunk, check=0): dictionary = b"" im.encoderconfig = ("optimize" in im.encoderinfo, - im.encoderinfo.get("compress_level", -1), - im.encoderinfo.get("compress_type", -1), - dictionary) + im.encoderinfo.get("compress_level", -1), + im.encoderinfo.get("compress_type", -1), + dictionary) # get the corresponding PNG mode try: @@ -616,8 +631,8 @@ def _save(im, fp, filename, chunk=putchunk, check=0): fp.write(_MAGIC) chunk(fp, b"IHDR", - o32(im.size[0]), o32(im.size[1]), # 0: size - mode, # 8: depth/type + o32(im.size[0]), o32(im.size[1]), # 0: size + mode, # 8: depth/type b'\0', # 10: compression b'\0', # 11: filter category b'\0') # 12: interlace flag @@ -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) diff --git a/PIL/PpmImagePlugin.py b/PIL/PpmImagePlugin.py index 070efd185..954832451 100644 --- a/PIL/PpmImagePlugin.py +++ b/PIL/PpmImagePlugin.py @@ -27,12 +27,13 @@ from PIL import Image, ImageFile b_whitespace = string.whitespace try: import locale - locale_lang,locale_enc = locale.getlocale() + locale_lang, locale_enc = locale.getlocale() if locale_enc is None: - locale_lang,locale_enc = locale.getdefaultlocale() + locale_lang, locale_enc = locale.getdefaultlocale() b_whitespace = b_whitespace.decode(locale_enc) -except: pass -b_whitespace = b_whitespace.encode('ascii','ignore') +except: + pass +b_whitespace = b_whitespace.encode('ascii', 'ignore') MODES = { # standard @@ -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. @@ -58,8 +61,8 @@ class PpmImageFile(ImageFile.ImageFile): format = "PPM" format_description = "Pbmplus image" - def _token(self, s = b""): - while True: # read until next whitespace + def _token(self, s=b""): + while True: # read until next whitespace c = self.fp.read(1) if not c or c in b_whitespace: break @@ -104,14 +107,14 @@ class PpmImageFile(ImageFile.ImageFile): # maxgrey if s > 255: if not mode == 'L': - raise ValueError("Too many colors for band: %s" %s) + raise ValueError("Too many colors for band: %s" % s) if s < 2**16: self.mode = 'I' rawmode = 'I;16B' else: - self.mode = 'I'; + self.mode = 'I' rawmode = 'I;32B' - + self.size = xsize, ysize self.tile = [("raw", (0, 0, xsize, ysize), @@ -123,6 +126,7 @@ class PpmImageFile(ImageFile.ImageFile): # self.mode = self.im.mode # self.size = self.im.size + # # -------------------------------------------------------------------- @@ -152,7 +156,7 @@ def _save(im, fp, filename): fp.write(b"65535\n") elif rawmode == "I;32B": fp.write(b"2147483648\n") - ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, 0, 1))]) + ImageFile._save(im, fp, [("raw", (0, 0)+im.size, 0, (rawmode, 0, 1))]) # ALTERNATIVE: save via builtin debug function # im._dump(filename) diff --git a/PIL/PsdImagePlugin.py b/PIL/PsdImagePlugin.py index 9e64e7c90..02c94a860 100644 --- a/PIL/PsdImagePlugin.py +++ b/PIL/PsdImagePlugin.py @@ -28,8 +28,8 @@ MODES = { (2, 8): ("P", 1), (3, 8): ("RGB", 3), (4, 8): ("CMYK", 4), - (7, 8): ("L", 1), # FIXME: multilayer - (8, 8): ("L", 1), # duotone + (7, 8): ("L", 1), # FIXME: multilayer + (8, 8): ("L", 1), # duotone (9, 8): ("LAB", 3) } @@ -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. @@ -100,12 +102,12 @@ class PsdImageFile(ImageFile.ImageFile): id = i16(read(2)) name = read(i8(read(1))) if not (len(name) & 1): - read(1) # padding + read(1) # padding data = read(i32(read(4))) if (len(data) & 1): - read(1) # padding + read(1) # padding self.resources.append((id, name, data)) - if id == 1039: # ICC profile + if id == 1039: # ICC profile self.info["icc_profile"] = data # @@ -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 = [] @@ -197,7 +202,7 @@ def _layerinfo(file): elif mode == ["A", "B", "G", "R"]: mode = "RGBA" else: - mode = None # unknown + mode = None # unknown # skip over blend flags and extra information filler = read(12) @@ -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 @@ -283,7 +292,7 @@ def _maketile(file, mode, bbox, channels): file.seek(offset) if offset & 1: - read(1) # padding + read(1) # padding return tile diff --git a/PIL/PyAccess.py b/PIL/PyAccess.py index 7ccc313eb..93aeae59e 100644 --- a/PIL/PyAccess.py +++ b/PIL/PyAccess.py @@ -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 @@ -25,7 +26,7 @@ from cffi import FFI import sys DEBUG = 0 - + defs = """ struct Pixel_RGBA { unsigned char r,g,b,a; @@ -39,8 +40,8 @@ ffi.cdef(defs) class PyAccess(object): - - def __init__(self, img, readonly = False): + + def __init__(self, img, readonly=False): vals = dict(img.im.unsafe_ptrs) self.readonly = readonly self.image8 = ffi.cast('unsigned char **', vals['image8']) @@ -48,13 +49,14 @@ class PyAccess(object): self.image = ffi.cast('unsigned char **', vals['image']) self.xsize = vals['xsize'] self.ysize = vals['ysize'] - + if DEBUG: print (vals) self._post_init() - def _post_init(): pass - + def _post_init(): + pass + def __setitem__(self, xy, color): """ Modifies the pixel at x,y. The color is given as a single @@ -62,11 +64,12 @@ class PyAccess(object): multi-band images :param xy: The pixel coordinate, given as (x, y). - :param value: The pixel value. + :param value: The pixel value. """ - 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) + 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) def __getitem__(self, xy): """ @@ -76,94 +79,98 @@ class PyAccess(object): :param xy: The pixel coordinate, given as (x, y). """ - - (x,y) = self.check_xy(xy) - return self.get_pixel(x,y) + + (x, y) = self.check_xy(xy) + return self.get_pixel(x, y) putpixel = __setitem__ getpixel = __getitem__ def check_xy(self, xy): - (x,y) = xy + (x, y) = xy if not (0 <= x < self.xsize and 0 <= y < self.ysize): 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): self.pixels = ffi.cast("struct Pixel_RGBA **", self.image32) - - def get_pixel(self, x,y): + + def get_pixel(self, x, y): pixel = self.pixels[y][x] return (pixel.r, pixel.a) - def set_pixel(self, x,y, color): + def set_pixel(self, x, y, color): pixel = self.pixels[y][x] # tuple - pixel.r = min(color[0],255) - pixel.a = min(color[1],255) - + 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 """ - + def _post_init(self, *args, **kwargs): self.pixels = ffi.cast("struct Pixel_RGBA **", self.image32) - - def get_pixel(self, x,y): + + def get_pixel(self, x, y): pixel = self.pixels[y][x] return (pixel.r, pixel.g, pixel.b) - def set_pixel(self, x,y, color): + def set_pixel(self, x, y, color): pixel = self.pixels[y][x] # tuple - pixel.r = min(color[0],255) - pixel.g = min(color[1],255) - pixel.b = min(color[2],255) + pixel.r = min(color[0], 255) + 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): self.pixels = ffi.cast("struct Pixel_RGBA **", self.image32) - - def get_pixel(self, x,y): + + def get_pixel(self, x, y): pixel = self.pixels[y][x] return (pixel.r, pixel.g, pixel.b, pixel.a) - def set_pixel(self, x,y, color): + def set_pixel(self, x, y, color): pixel = self.pixels[y][x] # tuple - pixel.r = min(color[0],255) - pixel.g = min(color[1],255) - pixel.b = min(color[2],255) - pixel.a = min(color[3],255) + pixel.r = min(color[0], 255) + pixel.g = min(color[1], 255) + pixel.b = min(color[2], 255) + pixel.a = min(color[3], 255) + - class _PyAccess8(PyAccess): """ 1, L, P, 8 bit images stored as uint8 """ def _post_init(self, *args, **kwargs): self.pixels = self.image8 - - def get_pixel(self, x,y): + + def get_pixel(self, x, y): return self.pixels[y][x] - def set_pixel(self, x,y, color): + def set_pixel(self, x, y, color): try: # integer - self.pixels[y][x] = min(color,255) + self.pixels[y][x] = min(color, 255) except: # tuple - self.pixels[y][x] = min(color[0],255) + 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): self.pixels = ffi.cast('unsigned short **', self.image) - def get_pixel(self, x,y): + def get_pixel(self, x, y): return self.pixels[y][x] - def set_pixel(self, x,y, color): + def set_pixel(self, x, y, color): try: # integer self.pixels[y][x] = min(color, 65535) @@ -171,16 +178,17 @@ 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): self.pixels = ffi.cast('struct Pixel_I16 **', self.image) - def get_pixel(self, x,y): + def get_pixel(self, x, y): pixel = self.pixels[y][x] return pixel.l + pixel.r * 256 - def set_pixel(self, x,y, color): + def set_pixel(self, x, y, color): pixel = self.pixels[y][x] try: color = min(color, 65535) @@ -190,16 +198,17 @@ 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): self.pixels = ffi.cast('struct Pixel_I16 **', self.image) - def get_pixel(self, x,y): + def get_pixel(self, x, y): pixel = self.pixels[y][x] - return pixel.l *256 + pixel.r + return pixel.l * 256 + pixel.r - def set_pixel(self, x,y, color): + def set_pixel(self, x, y, color): pixel = self.pixels[y][x] try: color = min(color, 65535) @@ -209,17 +218,19 @@ 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): self.pixels = self.image32 - def get_pixel(self, x,y): + def get_pixel(self, x, y): return self.pixels[y][x] - def set_pixel(self, x,y, color): + 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,24 +239,26 @@ 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): + + def get_pixel(self, x, y): return self.reverse(self.pixels[y][x]) - def set_pixel(self, x,y, color): + 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): self.pixels = ffi.cast('float **', self.image32) - def get_pixel(self, x,y): + def get_pixel(self, x, y): return self.pixels[y][x] - def set_pixel(self, x,y, color): + def set_pixel(self, x, y, color): try: # not a tuple self.pixels[y][x] = color @@ -275,7 +288,7 @@ if sys.byteorder == 'little': mode_map['I;16'] = _PyAccessI16_N mode_map['I;16L'] = _PyAccessI16_N mode_map['I;16B'] = _PyAccessI16_B - + mode_map['I;32L'] = _PyAccessI32_N mode_map['I;32B'] = _PyAccessI32_Swap else: @@ -285,14 +298,16 @@ 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 diff --git a/PIL/TarIO.py b/PIL/TarIO.py index bba493e8f..4e5115b26 100644 --- a/PIL/TarIO.py +++ b/PIL/TarIO.py @@ -16,6 +16,7 @@ from PIL import ContainerIO + ## # A file object that provides read access to a given member of a TAR # file. diff --git a/PIL/WalImageFile.py b/PIL/WalImageFile.py index d494bfd58..29af35fa1 100644 --- a/PIL/WalImageFile.py +++ b/PIL/WalImageFile.py @@ -33,6 +33,7 @@ except ImportError: i32 = _binary.i32le + ## # Load texture from a Quake2 WAL texture file. #

diff --git a/PIL/WebPImagePlugin.py b/PIL/WebPImagePlugin.py index ab60c8dfa..78a7a5319 100644 --- a/PIL/WebPImagePlugin.py +++ b/PIL/WebPImagePlugin.py @@ -12,7 +12,7 @@ _VALID_WEBP_MODES = { _VP8_MODES_BY_IDENTIFIER = { b"VP8 ": "RGB", b"VP8X": "RGBA", - b"VP8L": "RGBA", # lossless + b"VP8L": "RGBA", # lossless } @@ -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 diff --git a/PIL/WmfImagePlugin.py b/PIL/WmfImagePlugin.py index 40b2037ab..6146c1560 100644 --- a/PIL/WmfImagePlugin.py +++ b/PIL/WmfImagePlugin.py @@ -24,6 +24,7 @@ _handler = None if str != bytes: long = int + ## # Install application-specific WMF image handler. # @@ -43,7 +44,7 @@ if hasattr(Image.core, "drawwmf"): self.bbox = im.info["wmf_bbox"] def load(self, im): - im.fp.seek(0) # rewind + im.fp.seek(0) # rewind return Image.frombytes( "RGB", im.size, Image.core.drawwmf(im.fp.read(), im.size, self.bbox), @@ -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) diff --git a/PIL/XbmImagePlugin.py b/PIL/XbmImagePlugin.py index 799d727a0..604ba15a8 100644 --- a/PIL/XbmImagePlugin.py +++ b/PIL/XbmImagePlugin.py @@ -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. @@ -81,7 +83,7 @@ def _save(im, fp, filename): fp.write(b"static char im_bits[] = {\n") - ImageFile._save(im, fp, [("xbm", (0,0)+im.size, 0, None)]) + ImageFile._save(im, fp, [("xbm", (0, 0)+im.size, 0, None)]) fp.write(b"};\n") diff --git a/PIL/__init__.py b/PIL/__init__.py index 7b4b8abfa..c6e27d791 100644 --- a/PIL/__init__.py +++ b/PIL/__init__.py @@ -12,7 +12,7 @@ # ;-) VERSION = '1.1.7' # PIL version -PILLOW_VERSION = '2.5.3' # Pillow +PILLOW_VERSION = '2.5.3' # Pillow _plugins = ['BmpImagePlugin', 'BufrStubImagePlugin', diff --git a/PIL/_binary.py b/PIL/_binary.py index 71b2b78c9..51ce45a79 100644 --- a/PIL/_binary.py +++ b/PIL/_binary.py @@ -16,16 +16,17 @@ if bytes is str: return ord(c) def o8(i): - return chr(i&255) + return chr(i & 255) else: def i8(c): return c if c.__class__ is int else c[0] def o8(i): - return bytes((i&255,)) + return bytes((i & 255,)) + # Input, le = little endian, be = big endian -#TODO: replace with more readable struct.unpack equivalent +# TODO: replace with more readable struct.unpack equivalent def i16le(c, o=0): """ Converts a 2-bytes (16 bits) string to an integer. @@ -33,7 +34,8 @@ def i16le(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) + return i8(c[o]) | (i8(c[o+1]) << 8) + def i32le(c, o=0): """ @@ -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]) + 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) + return o8(i) + o8(i >> 8) + def o32le(i): - return o8(i) + o8(i>>8) + o8(i>>16) + o8(i>>24) + return o8(i) + o8(i >> 8) + o8(i >> 16) + o8(i >> 24) + def o16be(i): - return o8(i>>8) + o8(i) + return o8(i >> 8) + o8(i) + def o32be(i): - return o8(i>>24) + o8(i>>16) + o8(i>>8) + o8(i) + return o8(i >> 24) + o8(i >> 16) + o8(i >> 8) + o8(i) +# End of file diff --git a/Tests/show_mcidas.py b/Tests/show_mcidas.py index db193b82a..1f1c04aa8 100644 --- a/Tests/show_mcidas.py +++ b/Tests/show_mcidas.py @@ -1,3 +1,4 @@ +from __future__ import print_function import sys sys.path.insert(0, ".") diff --git a/Tests/test_file_gif.py b/Tests/test_file_gif.py index bd4a6e76c..52be8db1d 100644 --- a/Tests/test_file_gif.py +++ b/Tests/test_file_gif.py @@ -120,7 +120,7 @@ class TestFileGif(PillowTestCase): try: while True: framecount += 1 - img.seek(img.tell() +1) + img.seek(img.tell() + 1) except EOFError: self.assertEqual(framecount, 5) @@ -128,7 +128,7 @@ class TestFileGif(PillowTestCase): img = Image.open("Tests/images/dispose_none.gif") try: while True: - img.seek(img.tell() +1) + img.seek(img.tell() + 1) self.assertEqual(img.disposal_method, 1) except EOFError: pass @@ -137,7 +137,7 @@ class TestFileGif(PillowTestCase): img = Image.open("Tests/images/dispose_bgnd.gif") try: while True: - img.seek(img.tell() +1) + img.seek(img.tell() + 1) self.assertEqual(img.disposal_method, 2) except EOFError: pass @@ -146,7 +146,7 @@ class TestFileGif(PillowTestCase): img = Image.open("Tests/images/dispose_prev.gif") try: while True: - img.seek(img.tell() +1) + img.seek(img.tell() + 1) self.assertEqual(img.disposal_method, 3) except EOFError: pass @@ -154,8 +154,9 @@ class TestFileGif(PillowTestCase): def test_iss634(self): img = Image.open("Tests/images/iss634.gif") # seek to the second frame - img.seek(img.tell() +1) - # all transparent pixels should be replaced with the color from the first frame + img.seek(img.tell() + 1) + # all transparent pixels should be replaced with the color from the + # first frame self.assertEqual(img.histogram()[img.info['transparency']], 0) diff --git a/Tests/test_locale.py b/Tests/test_locale.py index 9ef136bf9..be5921000 100644 --- a/Tests/test_locale.py +++ b/Tests/test_locale.py @@ -1,4 +1,4 @@ -from helper import unittest, PillowTestCase, lena +from helper import unittest, PillowTestCase from PIL import Image diff --git a/Tests/test_pyroma.py b/Tests/test_pyroma.py index 295ef1057..45d62b82f 100644 --- a/Tests/test_pyroma.py +++ b/Tests/test_pyroma.py @@ -1,4 +1,4 @@ -from helper import * +from helper import unittest, PillowTestCase try: import pyroma From 1335006cd73e0532873bec923858a73ff8e377f4 Mon Sep 17 00:00:00 2001 From: hugovk Date: Thu, 28 Aug 2014 14:44:19 +0300 Subject: [PATCH 02/17] flake8 --- PIL/FliImagePlugin.py | 10 +-- PIL/ImImagePlugin.py | 4 +- PIL/Image.py | 8 ++- PIL/ImageCms.py | 30 ++++---- PIL/ImageDraw.py | 1 + PIL/ImageFilter.py | 3 +- PIL/ImageQt.py | 2 + PIL/ImtImagePlugin.py | 9 +-- PIL/JpegImagePlugin.py | 38 ++++++---- PIL/JpegPresets.py | 6 +- PIL/MpoImagePlugin.py | 2 +- PIL/XVThumbImagePlugin.py | 1 + Tests/32bit_segfault_check.py | 2 - Tests/bench_cffi_access.py | 2 +- Tests/check_icns_dos.py | 5 +- Tests/check_j2k_dos.py | 10 +-- Tests/crash_ttf_memory_error.py | 2 +- Tests/helper.py | 6 +- Tests/large_memory_numpy_test.py | 2 +- Tests/large_memory_test.py | 2 +- Tests/test_file_mpo.py | 11 +-- Tests/test_file_palm.py | 7 +- Tests/test_file_png.py | 20 +++--- Tests/test_file_tiff_metadata.py | 3 +- Tests/test_file_webp_alpha.py | 3 +- Tests/test_format_hsv.py | 118 +++++++++++++++---------------- Tests/test_image_copy.py | 2 - Tests/test_image_point.py | 6 +- Tests/test_image_putdata.py | 8 +-- Tests/test_imagecms.py | 13 ++-- Tests/test_imagedraw.py | 25 ++++--- Tests/test_imagemorph.py | 2 +- Tests/test_imagewin.py | 2 +- Tests/test_mode_i16.py | 2 +- Tests/test_shell_injection.py | 1 + Tests/threaded_save.py | 7 +- Tests/versions.py | 1 + mp_compile.py | 7 +- profile-installed.py | 2 +- setup.py | 4 +- test-installed.py | 8 +-- 41 files changed, 214 insertions(+), 183 deletions(-) diff --git a/PIL/FliImagePlugin.py b/PIL/FliImagePlugin.py index c9a29051e..4ecaccdc4 100644 --- a/PIL/FliImagePlugin.py +++ b/PIL/FliImagePlugin.py @@ -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 seek # method to load individual frames. @@ -47,7 +49,7 @@ class FliImageFile(ImageFile.ImageFile): magic = i16(s[4:6]) if not (magic in [0xAF11, 0xAF12] and i16(s[14:16]) in [0, 3] and # flags - s[20:22] == b"\x00\x00"): # reserved + s[20:22] == b"\x00\x00"): # reserved raise SyntaxError("not an FLI/FLC file") # image characteristics @@ -61,7 +63,7 @@ class FliImageFile(ImageFile.ImageFile): self.info["duration"] = duration # look for palette - palette = [(a,a,a) for a in range(256)] + palette = [(a, a, a) for a in range(256)] s = self.fp.read(16) @@ -80,7 +82,7 @@ class FliImageFile(ImageFile.ImageFile): elif i16(s[4:6]) == 4: self._palette(palette, 0) - palette = [o8(r)+o8(g)+o8(b) for (r,g,b) in palette] + palette = [o8(r)+o8(g)+o8(b) for (r, g, b) in palette] self.palette = ImagePalette.raw("RGB", b"".join(palette)) # set things up to decode first frame @@ -124,7 +126,7 @@ class FliImageFile(ImageFile.ImageFile): framesize = i32(s) self.decodermaxblock = framesize - self.tile = [("fli", (0,0)+self.size, self.__offset, None)] + self.tile = [("fli", (0, 0)+self.size, self.__offset, None)] self.__offset = self.__offset + framesize diff --git a/PIL/ImImagePlugin.py b/PIL/ImImagePlugin.py index 2e0ecded3..4266f8315 100644 --- a/PIL/ImImagePlugin.py +++ b/PIL/ImImagePlugin.py @@ -159,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') diff --git a/PIL/Image.py b/PIL/Image.py index 480410eff..628300d6a 100644 --- a/PIL/Image.py +++ b/PIL/Image.py @@ -34,6 +34,7 @@ import warnings class DecompressionBombWarning(RuntimeWarning): pass + class _imaging_not_installed: # module placeholder def __getattr__(self, id): @@ -847,8 +848,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. @@ -864,7 +866,7 @@ class Image: # can't just retrieve the palette number, got to do it # after quantization. trns_im = trns_im.convert('RGB') - trns = trns_im.getpixel((0,0)) + trns = trns_im.getpixel((0, 0)) elif self.mode == 'P' and mode == 'RGBA': delete_trns = True diff --git a/PIL/ImageCms.py b/PIL/ImageCms.py index 04a3f7f61..fbc9fab12 100644 --- a/PIL/ImageCms.py +++ b/PIL/ImageCms.py @@ -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 @@ -154,9 +154,9 @@ class ImageCmsProfile: :param profile: Either a string representing a filename, a file like object containing a profile or a low-level profile object - + """ - + if isStringType(profile): self._set(core.profile_open(profile), profile) elif hasattr(profile, "read"): @@ -181,9 +181,10 @@ class ImageCmsProfile: :returns: a bytes object containing the ICC profile. """ - + 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): diff --git a/PIL/ImageDraw.py b/PIL/ImageDraw.py index 9fc343ac7..a2a75d1c6 100644 --- a/PIL/ImageDraw.py +++ b/PIL/ImageDraw.py @@ -40,6 +40,7 @@ try: except ImportError: warnings = None + ## # A simple 2D drawing interface for PIL images. #

diff --git a/PIL/ImageFilter.py b/PIL/ImageFilter.py index 43dd922d3..1e0154d12 100644 --- a/PIL/ImageFilter.py +++ b/PIL/ImageFilter.py @@ -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" diff --git a/PIL/ImageQt.py b/PIL/ImageQt.py index ca8b14b5c..88df3e564 100644 --- a/PIL/ImageQt.py +++ b/PIL/ImageQt.py @@ -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. diff --git a/PIL/ImtImagePlugin.py b/PIL/ImtImagePlugin.py index e68b00344..f512eb801 100644 --- a/PIL/ImtImagePlugin.py +++ b/PIL/ImtImagePlugin.py @@ -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) @@ -54,7 +55,7 @@ class ImtImageFile(ImageFile.ImageFile): if s == b'\x0C': # image data begins - self.tile = [("raw", (0,0)+self.size, + self.tile = [("raw", (0, 0)+self.size, self.fp.tell(), (self.mode, 0, 1))] @@ -68,12 +69,12 @@ class ImtImageFile(ImageFile.ImageFile): if len(s) == 1 or len(s) > 100: break if s[0] == b"*": - continue # comment + continue # comment m = field.match(s) if not m: break - k, v = m.group(1,2) + k, v = m.group(1, 2) if k == "width": xsize = int(v) self.size = xsize, ysize diff --git a/PIL/JpegImagePlugin.py b/PIL/JpegImagePlugin.py index 9cbab6b61..bb812eb3f 100644 --- a/PIL/JpegImagePlugin.py +++ b/PIL/JpegImagePlugin.py @@ -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,14 +474,18 @@ 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)), - 'Reserved': (mpentry['Attribute'] & (3<<27)) >> 27, - 'ImageDataFormat': (mpentry['Attribute'] & (7<<24)) >> 24, + '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 } if mpentryattr['ImageDataFormat'] == 0: @@ -496,7 +502,7 @@ def _getmp(self): 0x030000: 'Baseline MP Primary Image' } mpentryattr['MPType'] = mptypemap.get(mpentryattr['MPType'], - 'Unknown') + 'Unknown') mpentry['Attribute'] = mpentryattr mpentries.append(mpentry) mp[0xB002] = mpentries @@ -530,11 +536,10 @@ 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, - } + } def convert_dict_qtables(qtables): @@ -589,7 +594,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): @@ -623,7 +629,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) @@ -641,7 +648,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 diff --git a/PIL/JpegPresets.py b/PIL/JpegPresets.py index e7bec148a..6ca46d0cd 100644 --- a/PIL/JpegPresets.py +++ b/PIL/JpegPresets.py @@ -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: @@ -238,4 +238,4 @@ presets = { 15, 12, 12, 12, 12, 12, 12, 12, 15, 12, 12, 12, 12, 12, 12, 12] ]}, -} \ No newline at end of file +} diff --git a/PIL/MpoImagePlugin.py b/PIL/MpoImagePlugin.py index 13e3ef9b5..c345fd327 100644 --- a/PIL/MpoImagePlugin.py +++ b/PIL/MpoImagePlugin.py @@ -46,7 +46,7 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile): self.mpinfo = self._getmp() self.__framecount = self.mpinfo[0xB001] self.__mpoffsets = [mpent['DataOffset'] + self.info['mpoffset'] - for mpent in self.mpinfo[0xB002]] + for mpent in self.mpinfo[0xB002]] self.__mpoffsets[0] = 0 # Note that the following assertion will only be invalid if something # gets broken within JpegImagePlugin. diff --git a/PIL/XVThumbImagePlugin.py b/PIL/XVThumbImagePlugin.py index e5bf55acf..5cf1386fd 100644 --- a/PIL/XVThumbImagePlugin.py +++ b/PIL/XVThumbImagePlugin.py @@ -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. diff --git a/Tests/32bit_segfault_check.py b/Tests/32bit_segfault_check.py index 822d524fd..a601f762e 100644 --- a/Tests/32bit_segfault_check.py +++ b/Tests/32bit_segfault_check.py @@ -6,5 +6,3 @@ import sys if sys.maxsize < 2**32: im = Image.new('L', (999999, 999999), 0) - - diff --git a/Tests/bench_cffi_access.py b/Tests/bench_cffi_access.py index 8aa322aff..40bc0849a 100644 --- a/Tests/bench_cffi_access.py +++ b/Tests/bench_cffi_access.py @@ -1,4 +1,4 @@ -from helper import * +from helper import unittest, PillowTestCase, lena # Not running this test by default. No DOS against Travis CI. diff --git a/Tests/check_icns_dos.py b/Tests/check_icns_dos.py index ce6338a71..e56709bbb 100644 --- a/Tests/check_icns_dos.py +++ b/Tests/check_icns_dos.py @@ -1,5 +1,5 @@ # Tests potential DOS of IcnsImagePlugin with 0 length block. -# Run from anywhere that PIL is importable. +# Run from anywhere that PIL is importable. from PIL import Image from io import BytesIO @@ -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'))) diff --git a/Tests/check_j2k_dos.py b/Tests/check_j2k_dos.py index 68f065bbc..9f06888a3 100644 --- a/Tests/check_j2k_dos.py +++ b/Tests/check_j2k_dos.py @@ -1,11 +1,13 @@ # Tests potential DOS of Jpeg2kImagePlugin with 0 length block. -# Run from anywhere that PIL is importable. +# Run from anywhere that PIL is importable. 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'))) diff --git a/Tests/crash_ttf_memory_error.py b/Tests/crash_ttf_memory_error.py index 881fc03a6..8af3dbcec 100644 --- a/Tests/crash_ttf_memory_error.py +++ b/Tests/crash_ttf_memory_error.py @@ -9,6 +9,6 @@ i = Image.new("RGB", (500, h), "white") d = ImageDraw.Draw(i) # this line causes a MemoryError -d.text((0,0), s, font=f, fill=0) +d.text((0, 0), s, font=f, fill=0) i.show() diff --git a/Tests/helper.py b/Tests/helper.py index 3f7913b11..675743227 100644 --- a/Tests/helper.py +++ b/Tests/helper.py @@ -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") diff --git a/Tests/large_memory_numpy_test.py b/Tests/large_memory_numpy_test.py index 8a13d0aea..159d767d6 100644 --- a/Tests/large_memory_numpy_test.py +++ b/Tests/large_memory_numpy_test.py @@ -1,6 +1,6 @@ import sys -from helper import * +from helper import unittest, PillowTestCase # This test is not run automatically. # diff --git a/Tests/large_memory_test.py b/Tests/large_memory_test.py index a63a42cd5..3ee13091d 100644 --- a/Tests/large_memory_test.py +++ b/Tests/large_memory_test.py @@ -1,6 +1,6 @@ import sys -from helper import * +from helper import unittest, PillowTestCase # This test is not run automatically. # diff --git a/Tests/test_file_mpo.py b/Tests/test_file_mpo.py index a221eec15..066f39dc4 100644 --- a/Tests/test_file_mpo.py +++ b/Tests/test_file_mpo.py @@ -38,7 +38,7 @@ class TestFileMpo(PillowTestCase): self.assertEqual(im.applist[0][0], 'APP1') self.assertEqual(im.applist[1][0], 'APP2') self.assertEqual(im.applist[1][1][:16], - b'MPF\x00MM\x00*\x00\x00\x00\x08\x00\x03\xb0\x00') + b'MPF\x00MM\x00*\x00\x00\x00\x08\x00\x03\xb0\x00') self.assertEqual(len(im.applist), 2) def test_exif(self): @@ -55,7 +55,7 @@ class TestFileMpo(PillowTestCase): mpinfo = im._getmp() self.assertEqual(mpinfo[45056], b'0100') self.assertEqual(mpinfo[45057], 2) - + def test_mp_attribute(self): for test_file in test_files: im = Image.open(test_file) @@ -71,7 +71,7 @@ class TestFileMpo(PillowTestCase): self.assertFalse(mpattr['DependentChildImageFlag']) self.assertEqual(mpattr['ImageDataFormat'], 'JPEG') self.assertEqual(mpattr['MPType'], - 'Multi-Frame Image: (Disparity)') + 'Multi-Frame Image: (Disparity)') self.assertEqual(mpattr['Reserved'], 0) frameNumber += 1 @@ -82,7 +82,8 @@ class TestFileMpo(PillowTestCase): # prior to first image raises an error, both blatant and borderline self.assertRaises(EOFError, im.seek, -1) self.assertRaises(EOFError, im.seek, -523) - # after the final image raises an error, both blatant and borderline + # after the final image raises an error, + # both blatant and borderline self.assertRaises(EOFError, im.seek, 2) self.assertRaises(EOFError, im.seek, 523) # bad calls shouldn't change the frame @@ -93,7 +94,7 @@ class TestFileMpo(PillowTestCase): # and this one, too im.seek(0) self.assertEqual(im.tell(), 0) - + def test_image_grab(self): for test_file in test_files: im = Image.open(test_file) diff --git a/Tests/test_file_palm.py b/Tests/test_file_palm.py index 388df0237..15871392b 100644 --- a/Tests/test_file_palm.py +++ b/Tests/test_file_palm.py @@ -5,7 +5,7 @@ import os.path class TestFilePalm(PillowTestCase): _roundtrip = imagemagick_available() - + def helper_save_as_palm(self, mode): # Arrange im = lena(mode) @@ -21,14 +21,13 @@ class TestFilePalm(PillowTestCase): def roundtrip(self, mode): if not self._roundtrip: return - + im = lena(mode) outfile = self.tempfile("temp.palm") im.save(outfile) converted = self.open_withImagemagick(outfile) self.assert_image_equal(converted, im) - def test_monochrome(self): # Arrange @@ -46,7 +45,7 @@ class TestFilePalm(PillowTestCase): self.helper_save_as_palm(mode) self.skipKnownBadTest("Palm P image is wrong") self.roundtrip(mode) - + def test_rgb_ioerror(self): # Arrange mode = "RGB" diff --git a/Tests/test_file_png.py b/Tests/test_file_png.py index 8ef166347..0336978c7 100644 --- a/Tests/test_file_png.py +++ b/Tests/test_file_png.py @@ -151,13 +151,16 @@ class TestFilePng(PillowTestCase): self.assertEqual(im.info["spam"].lang, "en") self.assertEqual(im.info["spam"].tkey, "Spam") - im = load(HEAD + chunk(b'iTXt', b'spam\0\1\0en\0Spam\0' + zlib.compress(b"egg")[:1]) + TAIL) + im = load(HEAD + chunk(b'iTXt', b'spam\0\1\0en\0Spam\0' + + zlib.compress(b"egg")[:1]) + TAIL) self.assertEqual(im.info, {}) - im = load(HEAD + chunk(b'iTXt', b'spam\0\1\1en\0Spam\0' + zlib.compress(b"egg")) + TAIL) + im = load(HEAD + chunk(b'iTXt', b'spam\0\1\1en\0Spam\0' + + zlib.compress(b"egg")) + TAIL) self.assertEqual(im.info, {}) - im = load(HEAD + chunk(b'iTXt', b'spam\0\1\0en\0Spam\0' + zlib.compress(b"egg")) + TAIL) + im = load(HEAD + chunk(b'iTXt', b'spam\0\1\0en\0Spam\0' + + zlib.compress(b"egg")) + TAIL) self.assertEqual(im.info, {"spam": "egg"}) self.assertEqual(im.info["spam"].lang, "en") self.assertEqual(im.info["spam"].tkey, "Spam") @@ -271,7 +274,8 @@ class TestFilePng(PillowTestCase): im = Image.new("RGB", (32, 32)) info = PngImagePlugin.PngInfo() info.add_itxt("spam", "Eggs", "en", "Spam") - info.add_text("eggs", PngImagePlugin.iTXt("Spam", "en", "Eggs"), zip=True) + info.add_text("eggs", PngImagePlugin.iTXt("Spam", "en", "Eggs"), + zip=True) im = roundtrip(im, pnginfo=info) self.assertEqual(im.info, {"spam": "Eggs", "eggs": "Spam"}) @@ -303,11 +307,11 @@ class TestFilePng(PillowTestCase): self.assertEqual(im.info, {"Text": value}) if str is not bytes: - rt_text(" Aa" + chr(0xa0) + chr(0xc4) + chr(0xff)) # Latin1 - rt_text(chr(0x400) + chr(0x472) + chr(0x4ff)) # Cyrillic - rt_text(chr(0x4e00) + chr(0x66f0) + # CJK + rt_text(" Aa" + chr(0xa0) + chr(0xc4) + chr(0xff)) # Latin1 + rt_text(chr(0x400) + chr(0x472) + chr(0x4ff)) # Cyrillic + rt_text(chr(0x4e00) + chr(0x66f0) + # CJK chr(0x9fba) + chr(0x3042) + chr(0xac00)) - rt_text("A" + chr(0xc4) + chr(0x472) + chr(0x3042)) # Combined + rt_text("A" + chr(0xc4) + chr(0x472) + chr(0x3042)) # Combined def test_scary(self): # Check reading of evil PNG file. For information, see: diff --git a/Tests/test_file_tiff_metadata.py b/Tests/test_file_tiff_metadata.py index e0805b525..4d60e7412 100644 --- a/Tests/test_file_tiff_metadata.py +++ b/Tests/test_file_tiff_metadata.py @@ -50,7 +50,8 @@ class TestFileTiffMetadata(PillowTestCase): 'StripByteCounts': (1796,), 'SamplesPerPixel': (1,), 'StripOffsets': (8,), - 'Software': 'ImageMagick 6.5.7-8 2012-08-17 Q16 http://www.imagemagick.org'} + 'Software': 'ImageMagick 6.5.7-8 2012-08-17 Q16' + + ' http://www.imagemagick.org'} # self.assertEqual is equivalent, # but less helpful in telling what's wrong. diff --git a/Tests/test_file_webp_alpha.py b/Tests/test_file_webp_alpha.py index 5f8f653cf..267534efd 100644 --- a/Tests/test_file_webp_alpha.py +++ b/Tests/test_file_webp_alpha.py @@ -18,7 +18,8 @@ class TestFileWebpAlpha(PillowTestCase): self.skipTest('WebP support not installed') if _webp.WebPDecoderBuggyAlpha(self): - self.skipTest("Buggy early version of WebP installed, not testing transparency") + self.skipTest("Buggy early version of WebP installed, " + "not testing transparency") def test_read_rgba(self): # Generated with `cwebp transparent.png -o transparent.webp` diff --git a/Tests/test_format_hsv.py b/Tests/test_format_hsv.py index 03603aa9b..edf3ddfac 100644 --- a/Tests/test_format_hsv.py +++ b/Tests/test_format_hsv.py @@ -2,55 +2,61 @@ from helper import unittest, PillowTestCase, lena from PIL import Image -import colorsys, itertools +import colorsys +import itertools + class TestFormatHSV(PillowTestCase): def int_to_float(self, i): return float(i)/255.0 + def str_to_float(self, i): + return float(ord(i))/255.0 + def to_int(self, f): return int(f*255.0) + def tuple_to_ints(self, tp): - x,y,z = tp + x, y, z = tp return (int(x*255.0), int(y*255.0), int(z*255.0)) - + def test_sanity(self): - im = Image.new('HSV', (100,100)) + Image.new('HSV', (100, 100)) def wedge(self): - w =Image._wedge() + w = Image._wedge() w90 = w.rotate(90) (px, h) = w.size - - r = Image.new('L', (px*3,h)) + + r = Image.new('L', (px*3, h)) g = r.copy() b = r.copy() - r.paste(w, (0,0)) - r.paste(w90, (px,0)) + r.paste(w, (0, 0)) + r.paste(w90, (px, 0)) - g.paste(w90, (0,0)) - g.paste(w, (2*px,0)) + g.paste(w90, (0, 0)) + g.paste(w, (2*px, 0)) - b.paste(w, (px,0)) - b.paste(w90, (2*px,0)) + b.paste(w, (px, 0)) + b.paste(w90, (2*px, 0)) - img = Image.merge('RGB',(r,g,b)) + img = Image.merge('RGB', (r, g, b)) - #print (("%d, %d -> "% (int(1.75*px),int(.25*px))) + \ - # "(%s, %s, %s)"%img.getpixel((1.75*px, .25*px))) - #print (("%d, %d -> "% (int(.75*px),int(.25*px))) + \ - # "(%s, %s, %s)"%img.getpixel((.75*px, .25*px))) + # print (("%d, %d -> "% (int(1.75*px),int(.25*px))) + \ + # "(%s, %s, %s)"%img.getpixel((1.75*px, .25*px))) + # print (("%d, %d -> "% (int(.75*px),int(.25*px))) + \ + # "(%s, %s, %s)"%img.getpixel((.75*px, .25*px))) return img - + def to_xxx_colorsys(self, im, func, mode): # convert the hard way using the library colorsys routines. - - (r,g,b) = im.split() - + + (r, g, b) = im.split() + if bytes is str: conv_func = self.str_to_float else: @@ -61,17 +67,20 @@ class TestFormatHSV(PillowTestCase): else: iter_helper = itertools.zip_longest - - converted = [self.tuple_to_ints(func(conv_func(_r), conv_func(_g), conv_func(_b))) - for (_r, _g, _b) in iter_helper(r.tobytes(), g.tobytes(), b.tobytes())] + converted = [self.tuple_to_ints(func(conv_func(_r), conv_func(_g), + conv_func(_b))) + for (_r, _g, _b) in iter_helper(r.tobytes(), g.tobytes(), + b.tobytes())] if str is bytes: - new_bytes = b''.join(chr(h)+chr(s)+chr(v) for (h,s,v) in converted) + new_bytes = b''.join(chr(h)+chr(s)+chr(v) for ( + h, s, v) in converted) else: - new_bytes = b''.join(bytes(chr(h)+chr(s)+chr(v), 'latin-1') for (h,s,v) in converted) - - hsv = Image.frombytes(mode,r.size, new_bytes) - + new_bytes = b''.join(bytes(chr(h)+chr(s)+chr(v), 'latin-1') for ( + h, s, v) in converted) + + hsv = Image.frombytes(mode, r.size, new_bytes) + return hsv def to_hsv_colorsys(self, im): @@ -81,18 +90,18 @@ class TestFormatHSV(PillowTestCase): return self.to_xxx_colorsys(im, colorsys.hsv_to_rgb, 'RGB') def test_wedge(self): - src = self.wedge().resize((3*32,32),Image.BILINEAR) + src = self.wedge().resize((3*32, 32), Image.BILINEAR) im = src.convert('HSV') comparable = self.to_hsv_colorsys(src) - #print (im.getpixel((448, 64))) - #print (comparable.getpixel((448, 64))) - - #print(im.split()[0].histogram()) - #print(comparable.split()[0].histogram()) + # print (im.getpixel((448, 64))) + # print (comparable.getpixel((448, 64))) - #im.split()[0].show() - #comparable.split()[0].show() + # print(im.split()[0].histogram()) + # print(comparable.split()[0].histogram()) + + # im.split()[0].show() + # comparable.split()[0].show() self.assert_image_similar(im.split()[0], comparable.split()[0], 1, "Hue conversion is wrong") @@ -101,24 +110,23 @@ class TestFormatHSV(PillowTestCase): self.assert_image_similar(im.split()[2], comparable.split()[2], 1, "Value conversion is wrong") - #print (im.getpixel((192, 64))) + # print (im.getpixel((192, 64))) comparable = src im = im.convert('RGB') - #im.split()[0].show() - #comparable.split()[0].show() - #print (im.getpixel((192, 64))) - #print (comparable.getpixel((192, 64))) - + # im.split()[0].show() + # comparable.split()[0].show() + # print (im.getpixel((192, 64))) + # print (comparable.getpixel((192, 64))) + self.assert_image_similar(im.split()[0], comparable.split()[0], 3, "R conversion is wrong") self.assert_image_similar(im.split()[1], comparable.split()[1], 3, "G conversion is wrong") self.assert_image_similar(im.split()[2], comparable.split()[2], 3, "B conversion is wrong") - - + def test_convert(self): im = lena('RGB').convert('HSV') comparable = self.to_hsv_colorsys(lena('RGB')) @@ -128,7 +136,7 @@ class TestFormatHSV(PillowTestCase): # print(im.split()[0].histogram()) # print(comparable.split()[0].histogram()) - + self.assert_image_similar(im.split()[0], comparable.split()[0], 1, "Hue conversion is wrong") self.assert_image_similar(im.split()[1], comparable.split()[1], @@ -136,18 +144,16 @@ class TestFormatHSV(PillowTestCase): self.assert_image_similar(im.split()[2], comparable.split()[2], 1, "Value conversion is wrong") - def test_hsv_to_rgb(self): comparable = self.to_hsv_colorsys(lena('RGB')) converted = comparable.convert('RGB') comparable = self.to_rgb_colorsys(comparable) - - # print(converted.split()[1].histogram()) - # print(target.split()[1].histogram()) - # print ([ord(x) for x in target.split()[1].tobytes()[:80]]) - # print ([ord(x) for x in converted.split()[1].tobytes()[:80]]) + # print(converted.split()[1].histogram()) + # print(target.split()[1].histogram()) + # print ([ord(x) for x in target.split()[1].tobytes()[:80]]) + # print ([ord(x) for x in converted.split()[1].tobytes()[:80]]) self.assert_image_similar(converted.split()[0], comparable.split()[0], 3, "R conversion is wrong") @@ -156,12 +162,6 @@ class TestFormatHSV(PillowTestCase): self.assert_image_similar(converted.split()[2], comparable.split()[2], 3, "B conversion is wrong") - - - - - - if __name__ == '__main__': unittest.main() diff --git a/Tests/test_image_copy.py b/Tests/test_image_copy.py index a7882db94..06afc2486 100644 --- a/Tests/test_image_copy.py +++ b/Tests/test_image_copy.py @@ -1,7 +1,5 @@ from helper import unittest, PillowTestCase, lena -from PIL import Image - class TestImageCopy(PillowTestCase): diff --git a/Tests/test_image_point.py b/Tests/test_image_point.py index 04054fa84..d7c376084 100644 --- a/Tests/test_image_point.py +++ b/Tests/test_image_point.py @@ -1,7 +1,5 @@ from helper import unittest, PillowTestCase, lena -import sys - class TestImagePoint(PillowTestCase): @@ -26,7 +24,7 @@ class TestImagePoint(PillowTestCase): """ # This takes _forever_ on PyPy. Open Bug, # see https://github.com/python-pillow/Pillow/issues/484 - #self.skipKnownBadTest(msg="Too Slow on pypy", interpreter='pypy') + # self.skipKnownBadTest(msg="Too Slow on pypy", interpreter='pypy') im = lena("I") im.point(list(range(256))*256, 'L') @@ -40,7 +38,7 @@ class TestImagePoint(PillowTestCase): int_lut = [x//2 for x in range(256)] self.assert_image_equal(out.convert('L'), im.point(int_lut, 'L')) - + if __name__ == '__main__': unittest.main() diff --git a/Tests/test_image_putdata.py b/Tests/test_image_putdata.py index acea0d62a..e3ebaedec 100644 --- a/Tests/test_image_putdata.py +++ b/Tests/test_image_putdata.py @@ -41,9 +41,8 @@ class TestImagePutData(PillowTestCase): else: self.assertEqual(put(sys.maxsize), (255, 255, 255, 127)) - def test_pypy_performance(self): - im = Image.new('L', (256,256)) + im = Image.new('L', (256, 256)) im.putdata(list(range(256))*256) def test_mode_i(self): @@ -52,7 +51,7 @@ class TestImagePutData(PillowTestCase): im = Image.new('I', src.size, 0) im.putdata(data, 2, 256) - target = [2* elt + 256 for elt in data] + target = [2 * elt + 256 for elt in data] self.assertEqual(list(im.getdata()), target) def test_mode_F(self): @@ -61,10 +60,9 @@ class TestImagePutData(PillowTestCase): im = Image.new('F', src.size, 0) im.putdata(data, 2.0, 256.0) - target = [2.0* float(elt) + 256.0 for elt in data] + target = [2.0 * float(elt) + 256.0 for elt in data] self.assertEqual(list(im.getdata()), target) - if __name__ == '__main__': unittest.main() diff --git a/Tests/test_imagecms.py b/Tests/test_imagecms.py index e731c8945..a4b6fbb31 100644 --- a/Tests/test_imagecms.py +++ b/Tests/test_imagecms.py @@ -3,7 +3,7 @@ from helper import unittest, PillowTestCase, lena from PIL import Image from io import BytesIO - + try: from PIL import ImageCms from PIL.ImageCms import ImageCmsProfile @@ -202,8 +202,7 @@ class TestImageCms(PillowTestCase): self.assertTrue(img_srgb.info['icc_profile']) profile = ImageCmsProfile(BytesIO(img_srgb.info['icc_profile'])) - self.assertTrue('sRGB' in ImageCms.getProfileDescription(profile)) - + self.assertTrue('sRGB' in ImageCms.getProfileDescription(profile)) def test_lab_roundtrip(self): # check to see if we're at least internally consistent. @@ -216,12 +215,11 @@ class TestImageCms(PillowTestCase): self.assertEqual(i.info['icc_profile'], ImageCmsProfile(pLab).tobytes()) - + out = ImageCms.applyTransform(i, t2) self.assert_image_similar(lena(), out, 2) - def test_profile_tobytes(self): from io import BytesIO i = Image.open("Tests/images/rgb.jpg") @@ -231,14 +229,13 @@ class TestImageCms(PillowTestCase): # not the same bytes as the original icc_profile, # but it does roundtrip - self.assertEqual(p.tobytes(),p2.tobytes()) + self.assertEqual(p.tobytes(), p2.tobytes()) self.assertEqual(ImageCms.getProfileName(p), ImageCms.getProfileName(p2)) self.assertEqual(ImageCms.getProfileDescription(p), ImageCms.getProfileDescription(p2)) - - + if __name__ == '__main__': unittest.main() diff --git a/Tests/test_imagedraw.py b/Tests/test_imagedraw.py index b632da73b..2d03e21dc 100644 --- a/Tests/test_imagedraw.py +++ b/Tests/test_imagedraw.py @@ -350,12 +350,15 @@ class TestImageDraw(PillowTestCase): expected.load() img, draw = self.create_base_image_draw((110, 200)) draw.line((55, 5, 55, 195), BLACK, 101) - self.assert_image_equal(img, expected, 'line straigth vertical 101px wide failed') - expected = Image.open(os.path.join(IMAGES_PATH, 'line_vertical_slope1px_w2px.png')) + self.assert_image_equal(img, expected, + 'line straigth vertical 101px wide failed') + expected = Image.open(os.path.join(IMAGES_PATH, + 'line_vertical_slope1px_w2px.png')) expected.load() img, draw = self.create_base_image_draw((20, 20)) draw.line((5, 5, 6, 14), BLACK, 2) - self.assert_image_equal(img, expected, 'line vertical 1px slope 2px wide failed') + self.assert_image_equal(img, expected, + 'line vertical 1px slope 2px wide failed') def test_line_oblique_45(self): @@ -363,22 +366,26 @@ class TestImageDraw(PillowTestCase): expected.load() img, draw = self.create_base_image_draw((20, 20)) draw.line((5, 5, 14, 14), BLACK, 3) - self.assert_image_equal(img, expected, 'line oblique 45 normal 3px wide A failed') + self.assert_image_equal(img, expected, + 'line oblique 45 normal 3px wide A failed') img, draw = self.create_base_image_draw((20, 20)) draw.line((14, 14, 5, 5), BLACK, 3) - self.assert_image_equal(img, expected, 'line oblique 45 inverted 3px wide A failed') - expected = Image.open(os.path.join(IMAGES_PATH, 'line_oblique_45_w3px_b.png')) + self.assert_image_equal(img, expected, + 'line oblique 45 inverted 3px wide A failed') + expected = Image.open(os.path.join(IMAGES_PATH, + 'line_oblique_45_w3px_b.png')) expected.load() img, draw = self.create_base_image_draw((20, 20)) draw.line((14, 5, 5, 14), BLACK, 3) - self.assert_image_equal(img, expected, 'line oblique 45 normal 3px wide B failed') + self.assert_image_equal(img, expected, + 'line oblique 45 normal 3px wide B failed') img, draw = self.create_base_image_draw((20, 20)) draw.line((5, 14, 14, 5), BLACK, 3) - self.assert_image_equal(img, expected, 'line oblique 45 inverted 3px wide B failed') + self.assert_image_equal(img, expected, + 'line oblique 45 inverted 3px wide B failed') if __name__ == '__main__': unittest.main() # End of file - diff --git a/Tests/test_imagemorph.py b/Tests/test_imagemorph.py index a52111431..3bc5ce85a 100644 --- a/Tests/test_imagemorph.py +++ b/Tests/test_imagemorph.py @@ -1,5 +1,5 @@ # Test the ImageMorphology functionality -from helper import * +from helper import unittest, PillowTestCase from PIL import Image from PIL import ImageMorph diff --git a/Tests/test_imagewin.py b/Tests/test_imagewin.py index 69dbdbe82..2609beaf6 100644 --- a/Tests/test_imagewin.py +++ b/Tests/test_imagewin.py @@ -1,4 +1,4 @@ -from helper import unittest, PillowTestCase, lena +from helper import unittest, PillowTestCase from PIL import Image from PIL import ImageWin diff --git a/Tests/test_mode_i16.py b/Tests/test_mode_i16.py index 0cd5dba0f..bee29c734 100644 --- a/Tests/test_mode_i16.py +++ b/Tests/test_mode_i16.py @@ -5,7 +5,7 @@ from PIL import Image class TestModeI16(PillowTestCase): - original = lena().resize((32,32)).convert('I') + original = lena().resize((32, 32)).convert('I') def verify(self, im1): im2 = self.original.copy() diff --git a/Tests/test_shell_injection.py b/Tests/test_shell_injection.py index ef80bfc98..8413eb34e 100644 --- a/Tests/test_shell_injection.py +++ b/Tests/test_shell_injection.py @@ -17,6 +17,7 @@ test_filenames = ( "temp_'\"&&", ) + @unittest.skipIf(sys.platform.startswith('win32'), "requires Unix or MacOS") class TestShellInjection(PillowTestCase): diff --git a/Tests/threaded_save.py b/Tests/threaded_save.py index 12fcff2cf..f349b10ac 100644 --- a/Tests/threaded_save.py +++ b/Tests/threaded_save.py @@ -1,8 +1,10 @@ from PIL import Image -import sys, time import io -import threading, queue +import queue +import sys +import threading +import time try: format = sys.argv[1] @@ -16,6 +18,7 @@ queue = queue.Queue() result = [] + class Worker(threading.Thread): def run(self): while True: diff --git a/Tests/versions.py b/Tests/versions.py index a4e4a0bc2..e367ae46a 100644 --- a/Tests/versions.py +++ b/Tests/versions.py @@ -1,5 +1,6 @@ from PIL import Image + def version(module, version): v = getattr(module.core, version + "_version", None) if v: diff --git a/mp_compile.py b/mp_compile.py index b7c3e7ce4..794028c4b 100644 --- a/mp_compile.py +++ b/mp_compile.py @@ -9,7 +9,7 @@ try: MAX_PROCS = int(os.environ.get('MAX_CONCURRENCY', cpu_count())) except: MAX_PROCS = None - + # hideous monkeypatching. but. but. but. def _mp_compile_one(tp): @@ -57,6 +57,7 @@ if MAX_PROCS != 1: pool = Pool(2) CCompiler.compile = _mp_compile except Exception as msg: - print("Exception installing mp_compile, proceeding without: %s" %msg) + print("Exception installing mp_compile, proceeding without: %s" % msg) else: - print("Single threaded build, not installing mp_compile: %s processes" %MAX_PROCS) + print("Single threaded build, not installing mp_compile: %s processes" % + MAX_PROCS) diff --git a/profile-installed.py b/profile-installed.py index be9a960d2..c319c2899 100755 --- a/profile-installed.py +++ b/profile-installed.py @@ -21,6 +21,6 @@ if len(sys.argv) == 1: # Make sure that nose doesn't muck with our paths. if ('--no-path-adjustment' not in sys.argv) and ('-P' not in sys.argv): sys.argv.insert(1, '--no-path-adjustment') - + if __name__ == '__main__': profile.run("nose.main()", sort=2) diff --git a/setup.py b/setup.py index 5cf0e5e65..cc8117944 100644 --- a/setup.py +++ b/setup.py @@ -19,7 +19,7 @@ from distutils import sysconfig from setuptools import Extension, setup, find_packages # monkey patch import hook. Even though flake8 says it's not used, it is. -# comment this out to disable multi threaded builds. +# comment this out to disable multi threaded builds. import mp_compile _IMAGING = ( @@ -410,7 +410,7 @@ class pil_build_ext(build_ext): for directory in self.compiler.include_dirs: try: listdir = os.listdir(directory) - except Exception: + except Exception: # WindowsError, FileNotFoundError continue for name in listdir: diff --git a/test-installed.py b/test-installed.py index 0fed377b8..9beef27aa 100755 --- a/test-installed.py +++ b/test-installed.py @@ -24,9 +24,9 @@ if 'NOSE_PROCESSES' not in os.environ: for arg in sys.argv: if '--processes' in arg: break - else: # for - sys.argv.insert(1, '--processes=-1') # -1 == number of cores - sys.argv.insert(1, '--process-timeout=30') - + else: # for + sys.argv.insert(1, '--processes=-1') # -1 == number of cores + sys.argv.insert(1, '--process-timeout=30') + if __name__ == '__main__': nose.main() From 42610c0ecd5d3e92f1cf10c8a4300fa203fd7ea4 Mon Sep 17 00:00:00 2001 From: hugovk Date: Thu, 28 Aug 2014 17:18:54 +0300 Subject: [PATCH 03/17] flake8 --- PIL/EpsImagePlugin.py | 3 +- PIL/GimpPaletteFile.py | 2 +- Tests/import_all.py | 3 +- Tests/test_file_jpeg.py | 49 +++++++++++++------------ Tests/test_file_xpm.py | 4 +-- Tests/test_imagedraw.py | 80 +++++++++++++++++++++++++---------------- 6 files changed, 83 insertions(+), 58 deletions(-) diff --git a/PIL/EpsImagePlugin.py b/PIL/EpsImagePlugin.py index b980fe573..7b82fc3e8 100644 --- a/PIL/EpsImagePlugin.py +++ b/PIL/EpsImagePlugin.py @@ -117,7 +117,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]), diff --git a/PIL/GimpPaletteFile.py b/PIL/GimpPaletteFile.py index 6f71ec678..a066c80cc 100644 --- a/PIL/GimpPaletteFile.py +++ b/PIL/GimpPaletteFile.py @@ -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 diff --git a/Tests/import_all.py b/Tests/import_all.py index 118bf69a7..d8299d969 100644 --- a/Tests/import_all.py +++ b/Tests/import_all.py @@ -1,7 +1,8 @@ import sys sys.path.insert(0, ".") -import glob, os +import glob +import os import traceback for file in glob.glob("PIL/*.py"): diff --git a/Tests/test_file_jpeg.py b/Tests/test_file_jpeg.py index 3bf757332..8381fde29 100644 --- a/Tests/test_file_jpeg.py +++ b/Tests/test_file_jpeg.py @@ -60,7 +60,8 @@ class TestFileJpeg(PillowTestCase): self.assertGreater(y, 0.8) self.assertEqual(k, 0.0) # the opposite corner is black - c, m, y, k = [x / 255.0 for x in im.getpixel((im.size[0]-1, im.size[1]-1))] + c, m, y, k = [x / 255.0 for x in im.getpixel((im.size[0]-1, + im.size[1]-1))] self.assertGreater(k, 0.9) # roundtrip, and check again im = self.roundtrip(im) @@ -69,7 +70,8 @@ class TestFileJpeg(PillowTestCase): self.assertGreater(m, 0.8) self.assertGreater(y, 0.8) self.assertEqual(k, 0.0) - c, m, y, k = [x / 255.0 for x in im.getpixel((im.size[0]-1, im.size[1]-1))] + c, m, y, k = [x / 255.0 for x in im.getpixel((im.size[0]-1, + im.size[1]-1))] self.assertGreater(k, 0.9) def test_dpi(self): @@ -150,7 +152,8 @@ class TestFileJpeg(PillowTestCase): if py3: a = bytes(random.randint(0, 255) for _ in range(256 * 256 * 3)) else: - a = b''.join(chr(random.randint(0, 255)) for _ in range(256 * 256 * 3)) + a = b''.join(chr(random.randint(0, 255)) for _ in + range(256 * 256 * 3)) im = Image.frombuffer("RGB", (256, 256), a, "raw", "RGB", 0, 1) # this requires more bytes than pixels in the image im.save(f, format="JPEG", progressive=True, quality=100) @@ -235,11 +238,13 @@ class TestFileJpeg(PillowTestCase): qtables = im.quantization reloaded = self.roundtrip(im, qtables=qtables, subsampling=0) self.assertEqual(im.quantization, reloaded.quantization) - self.assert_image_similar(im, self.roundtrip(im, qtables='web_low'), 30) - self.assert_image_similar(im, self.roundtrip(im, qtables='web_high'), 30) + self.assert_image_similar(im, self.roundtrip(im, qtables='web_low'), + 30) + self.assert_image_similar(im, self.roundtrip(im, qtables='web_high'), + 30) self.assert_image_similar(im, self.roundtrip(im, qtables='keep'), 30) - #values from wizard.txt in jpeg9-a src package. + # values from wizard.txt in jpeg9-a src package. standard_l_qtable = [int(s) for s in """ 16 11 10 16 24 40 51 61 12 12 14 19 26 58 60 55 @@ -251,7 +256,7 @@ class TestFileJpeg(PillowTestCase): 72 92 95 98 112 100 103 99 """.split(None)] - standard_chrominance_qtable= [int(s) for s in """ + 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 @@ -262,23 +267,23 @@ class TestFileJpeg(PillowTestCase): 99 99 99 99 99 99 99 99 """.split(None)] # list of qtable lists - self.assert_image_similar(im, - self.roundtrip(im, - qtables=[standard_l_qtable, - standard_chrominance_qtable]), - 30) + self.assert_image_similar( + im, self.roundtrip( + im, qtables=[standard_l_qtable, standard_chrominance_qtable]), + 30) + # tuple of qtable lists - self.assert_image_similar(im, - self.roundtrip(im, - qtables=(standard_l_qtable, - standard_chrominance_qtable)), - 30) + self.assert_image_similar( + im, self.roundtrip( + im, qtables=(standard_l_qtable, standard_chrominance_qtable)), + 30) + # dict of qtable lists - self.assert_image_similar(im, - self.roundtrip(im, - qtables={0:standard_l_qtable, - 1:standard_chrominance_qtable}), - 30) + self.assert_image_similar( + im, self.roundtrip( + im, qtables={ + 0: standard_l_qtable, 1: standard_chrominance_qtable}), + 30) @unittest.skipUnless(djpeg_available(), "djpeg not available") def test_load_djpeg(self): diff --git a/Tests/test_file_xpm.py b/Tests/test_file_xpm.py index 4fc393808..fd7bcb04e 100644 --- a/Tests/test_file_xpm.py +++ b/Tests/test_file_xpm.py @@ -15,8 +15,8 @@ class TestFileXpm(PillowTestCase): self.assertEqual(im.size, (128, 128)) self.assertEqual(im.format, "XPM") - #large error due to quantization->44 colors. - self.assert_image_similar(im.convert('RGB'), lena('RGB'), 60) + # large error due to quantization->44 colors. + self.assert_image_similar(im.convert('RGB'), lena('RGB'), 60) def test_load_read(self): # Arrange diff --git a/Tests/test_imagedraw.py b/Tests/test_imagedraw.py index 2d03e21dc..f84e992a4 100644 --- a/Tests/test_imagedraw.py +++ b/Tests/test_imagedraw.py @@ -255,7 +255,6 @@ class TestImageDraw(PillowTestCase): self.assert_image_equal( im, Image.open("Tests/images/imagedraw_floodfill2.png")) - def create_base_image_draw(self, size, mode=DEFAULT_MODE, background1=WHITE, @@ -267,23 +266,25 @@ class TestImageDraw(PillowTestCase): img.putpixel((x, y), background2) return (img, ImageDraw.Draw(img)) - def test_square(self): expected = Image.open(os.path.join(IMAGES_PATH, 'square.png')) expected.load() img, draw = self.create_base_image_draw((10, 10)) draw.polygon([(2, 2), (2, 7), (7, 7), (7, 2)], BLACK) - self.assert_image_equal(img, expected, 'square as normal polygon failed') + self.assert_image_equal(img, expected, + 'square as normal polygon failed') img, draw = self.create_base_image_draw((10, 10)) draw.polygon([(7, 7), (7, 2), (2, 2), (2, 7)], BLACK) - self.assert_image_equal(img, expected, 'square as inverted polygon failed') + self.assert_image_equal(img, expected, + 'square as inverted polygon failed') img, draw = self.create_base_image_draw((10, 10)) draw.rectangle((2, 2, 7, 7), BLACK) - self.assert_image_equal(img, expected, 'square as normal rectangle failed') + self.assert_image_equal(img, expected, + 'square as normal rectangle failed') img, draw = self.create_base_image_draw((10, 10)) draw.rectangle((7, 7, 2, 2), BLACK) - self.assert_image_equal(img, expected, 'square as inverted rectangle failed') - + self.assert_image_equal( + img, expected, 'square as inverted rectangle failed') def test_triangle_right(self): expected = Image.open(os.path.join(IMAGES_PATH, 'triangle_right.png')) @@ -292,61 +293,78 @@ class TestImageDraw(PillowTestCase): draw.polygon([(3, 5), (17, 5), (10, 12)], BLACK) self.assert_image_equal(img, expected, 'triangle right failed') - def test_line_horizontal(self): - expected = Image.open(os.path.join(IMAGES_PATH, 'line_horizontal_w2px_normal.png')) + expected = Image.open(os.path.join(IMAGES_PATH, + 'line_horizontal_w2px_normal.png')) expected.load() img, draw = self.create_base_image_draw((20, 20)) draw.line((5, 5, 14, 5), BLACK, 2) - self.assert_image_equal(img, expected, 'line straigth horizontal normal 2px wide failed') - expected = Image.open(os.path.join(IMAGES_PATH, 'line_horizontal_w2px_inverted.png')) + self.assert_image_equal( + img, expected, 'line straigth horizontal normal 2px wide failed') + expected = Image.open(os.path.join(IMAGES_PATH, + 'line_horizontal_w2px_inverted.png')) expected.load() img, draw = self.create_base_image_draw((20, 20)) draw.line((14, 5, 5, 5), BLACK, 2) - self.assert_image_equal(img, expected, 'line straigth horizontal inverted 2px wide failed') - expected = Image.open(os.path.join(IMAGES_PATH, 'line_horizontal_w3px.png')) + self.assert_image_equal( + img, expected, 'line straigth horizontal inverted 2px wide failed') + expected = Image.open(os.path.join(IMAGES_PATH, + 'line_horizontal_w3px.png')) expected.load() img, draw = self.create_base_image_draw((20, 20)) draw.line((5, 5, 14, 5), BLACK, 3) - self.assert_image_equal(img, expected, 'line straigth horizontal normal 3px wide failed') + self.assert_image_equal( + img, expected, 'line straigth horizontal normal 3px wide failed') img, draw = self.create_base_image_draw((20, 20)) draw.line((14, 5, 5, 5), BLACK, 3) - self.assert_image_equal(img, expected, 'line straigth horizontal inverted 3px wide failed') - expected = Image.open(os.path.join(IMAGES_PATH, 'line_horizontal_w101px.png')) + self.assert_image_equal( + img, expected, 'line straigth horizontal inverted 3px wide failed') + expected = Image.open(os.path.join(IMAGES_PATH, + 'line_horizontal_w101px.png')) expected.load() img, draw = self.create_base_image_draw((200, 110)) draw.line((5, 55, 195, 55), BLACK, 101) - self.assert_image_equal(img, expected, 'line straigth horizontal 101px wide failed') + self.assert_image_equal( + img, expected, 'line straigth horizontal 101px wide failed') def test_line_h_s1_w2(self): self.skipTest('failing') - expected = Image.open(os.path.join(IMAGES_PATH, 'line_horizontal_slope1px_w2px.png')) + expected = Image.open(os.path.join(IMAGES_PATH, + 'line_horizontal_slope1px_w2px.png')) expected.load() img, draw = self.create_base_image_draw((20, 20)) draw.line((5, 5, 14, 6), BLACK, 2) - self.assert_image_equal(img, expected, 'line horizontal 1px slope 2px wide failed') - + self.assert_image_equal( + img, expected, 'line horizontal 1px slope 2px wide failed') def test_line_vertical(self): - expected = Image.open(os.path.join(IMAGES_PATH, 'line_vertical_w2px_normal.png')) + expected = Image.open(os.path.join(IMAGES_PATH, + 'line_vertical_w2px_normal.png')) expected.load() img, draw = self.create_base_image_draw((20, 20)) draw.line((5, 5, 5, 14), BLACK, 2) - self.assert_image_equal(img, expected, 'line straigth vertical normal 2px wide failed') - expected = Image.open(os.path.join(IMAGES_PATH, 'line_vertical_w2px_inverted.png')) + self.assert_image_equal( + img, expected, 'line straigth vertical normal 2px wide failed') + expected = Image.open(os.path.join(IMAGES_PATH, + 'line_vertical_w2px_inverted.png')) expected.load() img, draw = self.create_base_image_draw((20, 20)) draw.line((5, 14, 5, 5), BLACK, 2) - self.assert_image_equal(img, expected, 'line straigth vertical inverted 2px wide failed') - expected = Image.open(os.path.join(IMAGES_PATH, 'line_vertical_w3px.png')) + self.assert_image_equal( + img, expected, 'line straigth vertical inverted 2px wide failed') + expected = Image.open(os.path.join(IMAGES_PATH, + 'line_vertical_w3px.png')) expected.load() img, draw = self.create_base_image_draw((20, 20)) draw.line((5, 5, 5, 14), BLACK, 3) - self.assert_image_equal(img, expected, 'line straigth vertical normal 3px wide failed') + self.assert_image_equal( + img, expected, 'line straigth vertical normal 3px wide failed') img, draw = self.create_base_image_draw((20, 20)) draw.line((5, 14, 5, 5), BLACK, 3) - self.assert_image_equal(img, expected, 'line straigth vertical inverted 3px wide failed') - expected = Image.open(os.path.join(IMAGES_PATH, 'line_vertical_w101px.png')) + self.assert_image_equal( + img, expected, 'line straigth vertical inverted 3px wide failed') + expected = Image.open(os.path.join(IMAGES_PATH, + 'line_vertical_w101px.png')) expected.load() img, draw = self.create_base_image_draw((110, 200)) draw.line((55, 5, 55, 195), BLACK, 101) @@ -360,14 +378,14 @@ class TestImageDraw(PillowTestCase): self.assert_image_equal(img, expected, 'line vertical 1px slope 2px wide failed') - def test_line_oblique_45(self): - expected = Image.open(os.path.join(IMAGES_PATH, 'line_oblique_45_w3px_a.png')) + expected = Image.open(os.path.join(IMAGES_PATH, + 'line_oblique_45_w3px_a.png')) expected.load() img, draw = self.create_base_image_draw((20, 20)) draw.line((5, 5, 14, 14), BLACK, 3) self.assert_image_equal(img, expected, - 'line oblique 45 normal 3px wide A failed') + 'line oblique 45 normal 3px wide A failed') img, draw = self.create_base_image_draw((20, 20)) draw.line((14, 14, 5, 5), BLACK, 3) self.assert_image_equal(img, expected, From 99a3a00c24bb0b7da666ae699f49826c2b593ef2 Mon Sep 17 00:00:00 2001 From: hugovk Date: Thu, 28 Aug 2014 17:23:39 +0300 Subject: [PATCH 04/17] Also pep8/pyflakes *.py in parent dir --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 783974b53..d0ba64c50 100644 --- a/.travis.yml +++ b/.travis.yml @@ -44,7 +44,7 @@ after_success: # gather the coverage data - lcov --capture --directory . -b . --output-file coverage.info # filter to remove system headers - - lcov --remove coverage.info '/usr/*' -o coverage.filtered.info + - lcov --remove coverage.info '/usr/*' -o coverage.filtered.info # convert to json - coveralls-lcov -v -n coverage.filtered.info > coverage.c.json @@ -53,8 +53,10 @@ after_success: - pip install pep8 pyflakes + - pep8 --statistics --count *.py - 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) From 8f9e338303d7aec4069bf59bf0977c019076c9b7 Mon Sep 17 00:00:00 2001 From: hugovk Date: Sun, 14 Sep 2014 12:08:31 +0300 Subject: [PATCH 05/17] flake8 + typo: infile_temo -> infile_temp --- PIL/EpsImagePlugin.py | 43 +++++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/PIL/EpsImagePlugin.py b/PIL/EpsImagePlugin.py index 05be24f46..d077ca1ab 100644 --- a/PIL/EpsImagePlugin.py +++ b/PIL/EpsImagePlugin.py @@ -99,9 +99,9 @@ def Ghostscript(tile, size, fp, scale=1): in_fd, infile_temp = tempfile.mkstemp() os.close(in_fd) infile = infile_temp - + # ignore length and offset! - # ghostscript can read it + # ghostscript can read it # copy whole file to read in ghostscript with open(infile_temp, 'wb') as f: # fetch length of fp @@ -149,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 @@ -177,8 +182,9 @@ class PSFile: # line endings can be 1 or 2 of \r \n, in either order if self.char in b"\r\n": self.char = None - - return s.decode('latin-1') + + return s.decode('latin-1') + def _accept(prefix): return prefix[:4] == b"%!PS" or i32(prefix) == 0xC6D3D0C5 @@ -194,7 +200,7 @@ class EpsImageFile(ImageFile.ImageFile): format = "EPS" format_description = "Encapsulated Postscript" - mode_map = { 1:"L", 2:"LAB", 3:"RGB" } + mode_map = {1: "L", 2: "LAB", 3: "RGB"} def _open(self): (length, offset) = self._find_offset(self.fp) @@ -206,9 +212,9 @@ class EpsImageFile(ImageFile.ImageFile): # Python2, no encoding conversion necessary fp = open(self.fp.name, "Ur") else: - # Python3, can use bare open command. + # 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) @@ -224,7 +230,7 @@ class EpsImageFile(ImageFile.ImageFile): # Load EPS header s = fp.readline().strip('\r\n') - + while s: if len(s) > 255: raise SyntaxError("not an EPS file") @@ -290,10 +296,10 @@ class EpsImageFile(ImageFile.ImageFile): self.mode = self.mode_map[int(mo)] except: break - + self.size = int(x), int(y) return - + s = fp.readline().strip('\r\n') if not s: break @@ -302,19 +308,20 @@ class EpsImageFile(ImageFile.ImageFile): raise IOError("cannot determine EPS bounding box") def _find_offset(self, fp): - + s = fp.read(160) - + if s[:4] == b"%!PS": # for HEAD without binary preview fp.seek(0, 2) length = fp.tell() offset = 0 elif i32(s[0:4]) == 0xC6D3D0C5: - # FIX for: Some EPS file not handled correctly / issue #302 + # 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: From 1f377c2ace924332957d2099d325bb2a4a8b30d1 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 23 Sep 2014 09:52:03 -0700 Subject: [PATCH 06/17] Merge from master --- CHANGES.rst | 3 + PIL/Image.py | 4 ++ PIL/ImageWin.py | 8 +-- Tests/images/hopper_gray.jpg | Bin 0 -> 5353 bytes Tests/images/lena.jpg | Bin 4788 -> 0 bytes Tests/images/lena.tif | Bin 49470 -> 0 bytes Tests/images/lena_bw.png | Bin 1943 -> 0 bytes Tests/images/lena_gray.jpg | Bin 23013 -> 0 bytes Tests/test_file_jpeg.py | 77 ++++++++++++------------ Tests/test_imagecms.py | 26 ++++---- Tests/test_imagewin.py | 113 ++++++++++++++++++++++++++++++++++- docs/reference/Image.rst | 1 + libImaging/JpegEncode.c | 2 +- 13 files changed, 174 insertions(+), 60 deletions(-) create mode 100644 Tests/images/hopper_gray.jpg delete mode 100644 Tests/images/lena.jpg delete mode 100644 Tests/images/lena.tif delete mode 100644 Tests/images/lena_bw.png delete mode 100644 Tests/images/lena_gray.jpg diff --git a/CHANGES.rst b/CHANGES.rst index cd00ce285..02e8d318d 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,9 @@ Changelog (Pillow) 2.6.0 (unreleased) ------------------ +- Image.tobytes() and Image.tostring() documentation update #916 #917 + [mgedmin] + - On Windows, do not execute convert.exe without specifying path #912 [cgohlke] diff --git a/PIL/Image.py b/PIL/Image.py index 34b49c802..99ab6327b 100644 --- a/PIL/Image.py +++ b/PIL/Image.py @@ -665,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, diff --git a/PIL/ImageWin.py b/PIL/ImageWin.py index 3e0bbaf99..300d118c9 100644 --- a/PIL/ImageWin.py +++ b/PIL/ImageWin.py @@ -23,7 +23,7 @@ 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. """ @@ -36,7 +36,7 @@ class HDC: 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. """ @@ -86,8 +86,8 @@ class Dib: """ 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): diff --git a/Tests/images/hopper_gray.jpg b/Tests/images/hopper_gray.jpg new file mode 100644 index 0000000000000000000000000000000000000000..db3831dedd1c993cbad60da9d0316c8ec7823170 GIT binary patch literal 5353 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 H*w_ErV?`qQ literal 0 HcmV?d00001 diff --git a/Tests/images/lena.jpg b/Tests/images/lena.jpg deleted file mode 100644 index ed01c4e6769b3f01b13d78c6ee4e99e123d36464..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4788 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

  • c}~ zhB}qCoJt4s`U1{o0bgGz)a3G(vbn&2xhQVFFis=SfVRWQWZT(%-|0f%iE8k4Y2;{W z^k8vpPd#p5ov^P@?dYbh`bmp^VtaGSzB#?GpFB0r{(gJqU$@lu$?k=!JgMiinsC2* zr28fmQ~BiMa_VQ8`jwL2R!8lZM458qhPb47w|nTXzhT~ekml<(#6`ghnK^^Hn@{_( zF6OX+ViF_YRYrf3rRh_J(t9_#SFT6?)Az*7kLj*{)VsdKyDtzf_s}kGgj-J`|AZ(& zy!M!M%}w~oy^hJ4%T1lnOHdU>n;S$sts=dg*Mx$V5>Hs^fvtx6u$RDplow)w#6Zr! z7z$hrWg1}xLI?{Cpqh%H#}I#={5#2^UDObWzu^Bb24Q~Sf557t3$YlBRwrN}&xBuo zN)Xyd@))Fg!E|hl=|4j89j6CCj;e}9FT`Lb1d*y_qOmC2P#CR(?pdJ#j=*XLQOcp;r+4+! zK;EXGIxx;18Rzylrd}K7e`nMDad+d7=2fY`cjDu_)reOrF>$MqdQ?vRP{)2>%XnKO zJS>X={=G~>%>8?jUwn)B-i7FLy_bbsNFW{6rku(WSHy@FQRHD|)VqfCw+)5W!QP0! z{|DZ6H_TTzsn=d|T>Z(nJn=W4VQxG|Ubzn{Al-U`ak+>30h-Tus>r12EU~sKYc@A} zv5>ddo_5@up|9lwdEnoO@M%W*)rCSJcrwBbHWxC1KQu)hgRmyvJ4F=m-^?UU@IuQ2 zAA$Wt{ndo=hx!-nAM#IU{O!PaIQc^(8s;64|HC-=ckQ`LiI@?l-y|dH;rRToKs&vJ40a!J~9N%CrG{6=M*Q66t?OtQ6#fIKvF8WDa?NMCuV zdu_-gCEMSSPk|X6tYBU6cWj}6J96?b_Pt-~|Ewm|;ewj6{%ynnXZjp zcFVBGmBhC)-a%QEJ~OJDj!S<2jC|uB=Gud>@2`b?@hgen!|k@B^L^F1aqz=@{oCnA z`#>G>&b6@bF5#}ZL3t~990cVp{q{4;&1W!M!QXa=2^ab9Gpg$&#O2G;FCO=cqc&=D z<_qE%3Zo2ikyRnxtd85Pj90{(AWcputeH0hX5 z!f|l=p8~JD#lBCff?qiKw-Wqe7X|VkB|W4I=Q+iT1pfnUK?cd5+Xeie+H$(d9$oks zkUPPE9_nInKJ)wtXO9T%e>0P_k;a4-DYb;EhX|O>9ZSUa3Bq8or7er!YcDt(ta&qD zztda3J1jexXxg1@+!}2#k1KZPyG}LA!xiQJ$_S7@SW+IShE5iTU#rL7txcY;j5#!- znE>O5ylBrdzqhSA*;1b$>{jnlKfs;z+UK!t*7t_ljML&EL z^2H^e-(KvQrQFWk*n80ho3fCg{U9^9#-q4bLU$!r0@*H*=EHAw7D={t=QvrMF~jE7DF zIFm+H0L0UVNDp~9@b})x#=#;G@c-D(2Nk?;i30wxnF)nC@Q3~n*ncD1&)I(i`-k`o zgWyi=EAT%siv%MFywK!1AFKV`lG8)+f}(y}7%|BWg+*vk4SWF@|56-Aorqr(lUGwH zszd^ePGJ6`N~LvkLOWT(>H^`L{>l&Ib%%Wwmi7Wedm%I*>|=HIX~oV|np$ycuW{^~25n|BU@`Dd$Xce>X)-TrxN@~6YO zk9)JfKhgf@hh4nC|I2Ild|aO59tQPoufnuiOY z%uCYNXTp$3Qx$Jfq*xk6TXo{?2B}ph-Yf_Ho*=Cla3jI3$XAUKkB3>_`Yb1Z&WBFk zdr(2EWB*f|>c~F}yN1s-LD4N)NZ4DToTKwt&WKg94l-{{>h zk84Ie9%DgkI(UHWJs*u6AbEl4E|#K!KddFp#iJLJaZ6$%Y)H0}Jx5}Y+cNRLjn}^) zsxit_4Go#6qxE}AnYq70-(6-=*6z->9jdyZ;i(&vZ%ws zlnteKHO3Er`5WA=+nwoozc*TkDoY```rYo@>#dp7t%;-UsWaQs?_X~#ii;ora5M1s z3*>!okn8DpQEna4*tp&f8B%W=0m*mQ26rYfHcm~R5+2#-)s;Y6{4+1v85pi zoR1b_eN~dZA+3|>--2<>bNg`q-N;uR;g2VnUYi-1gBt3a7S4xm?%Q^bV!~0UaS`LO;RkZ@hpxh-mhAo3Tx(;FsWJCp zKn|Iwb+CS0*=QYZvi`U;%$v0ouyKLk?f==T;f=q8|C`0=_3? zm18vj2}W=~)@zIrrlbVT2vL(!5kq|cpWD?;LqcU(=sMC*{MQ@ve;k^#7&M>DF8F&dDEB>~$&9(=MuWwYORf-t5#Qa4 z_{K%-A2gAjwpx{=DoxSXr5YO~PWYy}1d}WgelEZ_R44XO0y+sky?Fm&Qs5xkvk&=n z9{N8yIN*N=w5@c-B*{Lm=e&LKh#>*)W4zEq&S;9vETy@qJsz<-<`G=TFSp@j@n zgQ2AWt6zO=@7L`q|2bK@D#G+&oaE;W)`djnl2W>i&JrkX=1!SsL0|pViF{T4(xx z+MN2=l|Ex#%5n~6R~~Dr;8|s{=WFdB=M-<2dw~D%4|J!-r4#*8hJesh`N=1Fw*gf)`LZ|mSdxhBC>9dD{mG*%__QUkk)zWv0&5ps|c>ph5hq2dMX2!T*%wbFJVMmdzt#G%iY`rei(owQIRJ+q(wb@pvYsrIgz{zC&8wkV$U3eu}wDaOf(rs6(A5D?5duQR8^~_IUH_*%n)O(MEOrmLlb- zJL|t!+y0>L*l5f7?>+T_dcdmcKQk^Ktq?hPrE3-9?WRm)oyY|IW%0(^ zxC{940ROM~k5Yn%aX!F*ksoL)ApPQh;0VBg_)~MVEe}$c;8Jh5^1v5$2oLDj!P;#v z;ne{C)gZwe{11cx;16AB$Y2#%w{uP7NmD#rX;DQ5F9?H_WOv{X`6nc(LsWl_gtjK8 z!df`2WkSQpS{kJ$1Inc>e5V&*)U$;>L@fc=a|~_?fs?u z%CeoF0z*s2=~y*9Y9svw4Ip_sMM^}oiM4f z%=YZ62RBC)+P=!;*_QXJjR)Y3zq78MpYD2Jx*T@H4Sm-=;>r`$wWn0qR}ccA3rD-&XL?aRRUDZIbl|^72>Ht`8d25$-9r}IS9+o1n)kKXBXPj!JiS>OZ99eKR(wrzv~noRB#=) zTEwVHmiGwV8=9h{%)n`WB=A=!lOXK}6&MTnyH)Wk86yA!CaMSu1W&_ z5P!jvdvJbAVgUI6e$+GYKihc(*h_iW!TsDP0RD~{{e}I5|EchU{*PB98dlK#`^Y~1 zBrhj_@IT#{S7VHj5ms;q;YBC?`T0`K=RV2nIw4F>O&Pd3f!{dW7Zwy@O&3BiglTC0 zYf_o8=c&(yIe6T18bOmy)faL#IV|9BD38+=Mw?`kZH=6m4vt$qsX>(j-74{D{M zuNszKY?H0;G~@5q;2LPC|K%HjSMEhze~!EB8T_p);m-4jA8s-4Kg^5poy|!w*5<4f zCv8-Ttqtjxdhu4h2*fH+w91pWWJzFJmg*!+buy@+gWv;KTDmYkkpB#zUP1g_;QCv0 z@h5f6_no{S`-LBScuxM{|EIWtKlAqk{=G!ly!8bC(~t8|!XhZnYl0O9{F~7aJLymV zIF|RRS9B_8?-r3vndo_;?>O6gnC8`k_gI44KwP+_K(G|Vz#is$2Fp|^m`}li@gFHt zt(A#8H6r-kp!si-rP`Zwmx|+eJBsa{h4!v|5LU1&2+G=ZOg zZ&5+xNHf-9nC*uq-toq?Z64Am<-3h>NTpsc^c_sJ%t7nBxnQ(Rd^p$lNAtS-S6?9S zJc_*egmBNB{wUD*U#?+qJ;L95knHQ-9ZT0$rEb=yu2&@4o3pnXq#Nb2_U6>>x+D>qaJaqxE!hBH$1Ce+SB|2jvO;hp;cf z{vrPUHGlB`PX5qRsPKDM5$IJP>9_&|_TPo|=s~{#`yV2}7NXAp(HD}^cEXdnl+Zs- z<$vr=Jggzvi%^D)P&fiJLO3taq4HW6(+!yd*mGVHGgc+c^$a$+An5rUi-a)s*5wQJ zMX|f}SqterYklrcQ{j4Lx?Y|GEv)tGENe>%$WB|?UT67CPV{D7uDPXnzBu`(`JN4V zo?cOSHrfJX8jU<(*9W%K;Uf&URk#SM1Lx%+LaPnqay!}Ie<(E`vK<{HHZqa9PV9g$PjP1ZPAxc}0X`)Ez~59WYQ=g&B<)0d z1AoXrhw&cH{O51@!wB-YjP2xK9^hFQ;R9nYXn1yF+<`wFfl*3eAKtqU@70BOZ^1s? zETa5*y5Lh^!m*5WP>$KoNA499)k&cv3@@#Ox|JKXnZbu)(_$hGRG`n{TZ*HAKkOn- z#G)3&l#TpYScf=iD>ut>x9UqY<=IQc8Ae6bYGuJlTB3}BuOK0zoo;BT)YX@pnrn7@ znzZuLsXVd0SFzDhdZ27Gv{mjYn`g>X2eV@j$69~VjMzt->?8Fj^DSWfyR%KU`F2O| zNIkT*tOOP8td3jNqu_i#nN%ONw#YI$ZUBg{V7_=kmtsCcNh)+teq8G3DGT#y!}xdO9roXg z@qqlt$$x<8(}8_fA9>eQO8?VT?oWeBZ<}bZWrUMz0xYo`vv3m}AGnRBOJ!-L>~#re zRm@&b<80;%Oa)N@A7&!Zf;&~@ET{5zYO{^y8R~pVDI%~ZPEd+NS5qmqbVf0bxK=IG z)X0l4_~o)nYg^}LQ_Fa6?qoskp>jY~Q9O{55_ai}wT7||sc@z;%e=TG_xQ(MVmr8E!gRn83U5_5mI zGNEs&d-f0iNWTA^aL2>vpRSW`d%~(o$d}*8ym&q+j@_)w2e+@UPBh6=06sW>;19`< z4zf+T$RKyX-;^c6JNnv0=QG6LUP=JuKfr$k?>j~FTa5|(8~zY~f&Xa*7p}Jydp<1o z@u&&$f?JTlzZ(bnzZcYB;D5mRKqCnF%ffD{q!GaX-$q4$9Dv$^dRl}3)X1~s;vobt z#3GjB392}|v3lRTx)E zVTt@BqhAJUYCDdHR8_RNUQt26w2*e+qnOBP5F{0lXpAS%xb82CX(aUREBa3P`{j|D z>WuaFlJ~3qZx%ZbW|~gbJqL^3yYn6Pg|6Mj-u>0VLug`al(0c}rWt{H;r;T^AGG6t z)Q&D!!}?s}D~P`%v_RnB zfVk7ee0)A%^rxxR^Ev5{tyEi4*ii*(GXn+u=VPD+gqs$?6%5X1R`f=?K$FJNX0q2Z z8E}V1lMeUYGPF6dYq?3?Y|?C+xH~GkGdi&Z$7~dcYnaJZOmV#+yD_SuijgLGfk9k( zF_a}^Jq?NX!{YBg_y5)<==&?-*RRz^aeH$_kaNCW9z2@uc(dH~eznIkS_`eA{Y6JH z1xY?Uz^2y8+R*9hz`;W2A1t#!X@_6Wv@0_OX`xR`2z~_^uN<`3SZ>_DvgyaA;TZ2{ zVLyC}xN-x=TQFEheB;J;^+9}fopbm8s5o9zk+D{m1PxmU{Dw5Az%!_016+_CroAGa z+`(U48@Dct0~KiH@sR(+eOTx}0RM4Pzyc=(Zmt3U(|VSZKct{Pb;Uyde^$wZ?7hPG zMVY_X&;G}+8wdHP*9gVG3-J>8!!0o2-$i~}5%$CRdhPjq*7-{2$0ovNhL0l(XQHQg zesj?<2#5gt-;fG)8PRGH6F#40HI=T(g83JHG8$znN?cAAG!sI!1(`EaNjpELMUYrU zi;)CTsP_ZePfxtS9byk45K zm>&<$XG@U@13M5XdyNh0hWfP4x>Q}A7-U19tOfY8M1a30i_^+uHFdGw6koUx4%aAp z(O$q`#SMpRgSLDM@PFUoXns2QcRTtIXO$e-o~j9QuL|~S2={Bp1a{*Bx-ecnSWig) zJ0o9!^9Og-j(Mu&_!M}3>9`xaSa80UbJ|Q;&Gg+VBU%b*Gg0A?`S%h7Hd1*exM7qo zn2RS)$KVzvRJbI*oW|O&NL`c)CgZrvnbK*Aq(4?v5JBd;d1pqjP%iG|dm#c3Vlg=* zJu)fcazH*lJr9?f93nv9@T-r@_y6V&$1~72I$oC;Yo8d{9_=y>HJX(5P-^YXHSf+f z?#wpZ=K6MK`gf+g_8=Ep=s8*JgFPZh@(XC8J!zagf@dMoy^b5K-~?;RQVjCk{XV$j zF+#k1nRNF$^}+q%Z!S^qy@>qbKH<7M*Udlnc>v?)y%r90TTwC(%UTWTJIz^J&6#jj z&7?>(Hl!Nrr4AL;r$L^)A%}w?TCYv~SrR}OJyc)#^Z?ig8^n2o|Cy!-uEj>eVjk2@ zA36k|d!s&faewTJf<>&oLK5urm-{>{^L|ks;L(im@5TkgE?*DE7dk)P80i0a!SZK2 z`bj_4qmS;fTOIXZvqk^0oc?hte!nxyEaPkQ1^ukZ5e{y($d!$K80sbX)Vt;nRWLfM&m0+hQ?VvmJpe^s9t?b=cALG8O*ROv~xOorq zOv+skl*@CtNd&j&V9A+w`+nTZr|Xs3n(|~-9^2X|wl+yXpfQ$V+MxnyevUDMd$6wtD4sn;_X^)D15D3zb?v!bwm%Z}ekw~{%v{Nf z>Y_&)@}%0-IBTH@b}eA@WHt#8pV`vS$C@j1>Ie~OUheB<<&6ws{PSR*Td*{MO}iT& z`ke>qUg)!bypNqh9azLg1*)*2heOEb)abtelQ zFe3)Bj3`XQ4V%Mq{YdTRsLVLt2+Kmd(~gL6Hs7{Xo1TXWghqV>KejPCZc$cdSJrIx zXB%6Swp&D>N2<^DbMY^p1pMX;Nbjkx&xp5Pupb3sZ+HZMb02;63GLo64+kH+XSgo`)neh}iCdzi}$ z)QwkV3@Q5=MiLg49+}|wzg?<%(yr9p7IDJy?0|i|1@0(q4MVG^&OF?pACN(}O*2rT z8?G^qH=L-)Z4+IaJ>`QrywtF#f@gQi2;`~U;xa0uhR^KF;aU6hEuHCqT50<=!R~%XD!{ii zOUzA<-Ux_MA%@OBcp>mV4uP#LS(>gkeWNDLc?t$uK^Odkq5lK<{}9G=h8?h#P5g!b zhb}(&|DW1ofIqB}SNS{w|5F?Iss$O)ix2O^hxFq^28ls^81HFzSUci5OdDbNt7LlD zhut3Jdz>3;ew;~tKa#fBlsFcPoJ}NcWD4Q>A>4dXOB}1ttC{=`Mx-*1Gn^398xvbi zAm@c+nRncC!`Z^882^8Mgu5A1&B_h<`ia~B^8@2a2=p6+zI{Nx7r<}}3;O11F+Ht6 zr%8%oRY%93&W%}>&94`GPgR}3-#Q}SQr2w_)U5YbtPfNeMr*9ojXRSa;PBt5I#e~H za;kp`KDdTP&yK)M7L?`@u`7-F)`7Cak&2_CO3s~cId`w&u3mu;Dk0r|2>cljykXQ5 z_U%3L9e221LAm{)0EL{)7LBHHb+VLg@H}ArO_KjV{$lt7olF9A%&*f0!ybXh>MkVap2DU zqq?-29Qd@T*<|t{A3L2ArHqemXY_DIk755gL$Z9Z?gUOx=~GA{?<^fWw6FP zP`lY%1Ibsm}_fE zH7k-X_@|m1Q%wpf2#g&s>|cD5e>$}Q_iB?hRf%hr39A+Hz+VXi5lRsBp9e5L-Qmwh zDc?;(qFgg^hQ(&sgdAxYYM0#9vtC?!bn0VgKU)VSK3wybmr2 zb`BkzpTZFMs4GZB)mbR`oR&X~=AASp!w0g#JzoXl(K37>hJ-o@S1^+4#`3IgK2w>L z(#}gva1Ulb@PKh@H9duVH<)%0Nq>Ni^Wo;=M3`GXR5yR$FR#-ddWC;~2X*;A=BisI zGbs(ruZT%+%gi$k^=|akZ4cKQddpUtvMs&k#-57JE?AkUF!fh$kIMFD8;?}2A65pT zFa2)z|0CwDnk^3jcm=G~2$pMj1LW9Y zavbm$Mscx#e|Nm^SXS80Z~6ZXf6jOOKXeNoSLe(LFwlS2Mj?!`V1yOjogUwtZaM#f zJ8=<+plKl&i81g-8zV)4Qs8_}SZA8&Wp4D>#ip-YJr|gf;OaI)4u?_u6+WgvH~Mak za#BK@QVN?0#4=P$;t@MuP!h<)gZ}+2)fdAL&lN{8<4;E)D=}& z96N#tRE{Si!@&#mjHq92fz_Gq?`Da4It`4-#-O|s1<@p^+8US7*4{*sB)pBpm-?vYt>aE1@2AUooHNAaP6 zKk(naI$O83{f)?sp3d%E`oFMdjZzQjQ<7E(G%i3??l0X9>YiqCfNm4>GgoRCmj zq&bG*UE|~^Cdn%!!wC%)K9u+H$WHy13{EAI8fyt2wNwI8T?KH2(iq3>{|_h7l_^>pW_<-RYAZGX%+zaFU` z;@}0|-c(0lDKbeAp0Lo^FkM@XI(Lc|6pVs%2AFKN9wd*TG@$o*hk&Xj;iMhT&OPO< zJ;lRw(Wvbc(q}3mnU%9u%=LQSZkr6i-)=4V|KczE{s}f9^UacVv(N&5EqAeoyT__)!Gm|jc}=!3uk4-61q0qvoW`?{BT(91pO;sIM8jD3u80aZ~5T@0cL z8`Y0TgPe0DD+%z2`*#Ev4vnCT#E9$6BvAK&@?tDEyfZc6>%FV5Tk_|mX_NefK4S1l zUJQ)aF9`{HOq9sqm*wTJ&!mD*O&*gSd)zbIJ&KFWM4t^!b3jr2vM|CZhzHISJ`@_3WfzY8cXl> z8uu=>eVFb4xYYk)xf|mBQr~Z@1AklV`1?ZBhw+*Xy+WUa&OBio_v4xBEZTBY^Gv-l z+0j1D(F126lIs>rbPENqB)We@;%P_tEo3@)%ugwJ0IrE3DOv;LQd34`F!)n>ZHyEgn`ekpIIO(a=T! zemJ;00{$;MnQ!{JuY1`07LE2d{JBYhe|1aU6MW7!FC{zD_;axQ8~ zkhTaOfRv~SdNk;K=Y;qb75VE$a}Oc7pA@!GKmbdbD>BleM%GOy7et{Hkr?D(&wxBU z*E^o#mz3=po$V1z@l8Sg?8}eH!@FWNIC)VjC&j@p%iS;V-~UaO7;~jOf61hI)Zg}S zuycE`d$_##(Zt}>$?luol@ErhS87BXCYTy)9(HP<^w+!`HNU#t^6pyu;e5x(m7c@J z-mg0szdpM3_4d#o*BZBU3PWOI)=7KJQ5#t#dZe&uy|X1ZAb{wF$g~e5xy2FOkwmXx zsxR~$+yQ^6dGPkY^K==Ji7w;|W-4Xyp*I^9aG1;+@)m2D3qYPR3YKbw-(%S%g0=&2 zir_d&rzb-ZuR6OnJD8PRxD-rO&NJ_HMC$b`^D2c1048Z>~IdYO31scP#+@vWU z;p^fEaGNi1Fq7hpr84eJvCxo$W_t(Zd4v?i5s*LFl6_E$1Pay$!3s?wctmA;BxE?o zVXR}4ZDZoC5VRn4^a z8s^mW2hBy#I;vjw)w~{Rcs|ep~N9Sm-&J>-;p|_;t1Y>w5p;NW(CL z&T;cgJz`(Q!678?;0(LaY?m0KXGE4qFkJdLCrk1ZT|APl&J-uaPOI~; zm&+IRa+tnZa=S?k&77rr&SI@#p+-1o;9sxiT&rSDYuU4U9{kIqN%TFI>m)1nQV95u z^F{&S-%GS;sG*ZEmA`=oCc2~WE+~>G7Iiw9jl_xKvSLozN)k|u zO}Zu?VX3|dw0P@HB_C#opNw@)8%rLKHr?&1hDYe8QLv@sf4NZiyj8Q;t$R0Ezkj~z zV6yeYZ0E;?_JhT?_bWrcZ;pPw(f@U`>+3?tn?B=ZA-^I9opH)8{^)68Byy*(gB21) z^zbLTL{PjE$v$y-cesy&pzV`t<3e(APdj_2gH63sB8B8%tp#pOA)NV}Ez*q^5yV!j za+BgRJ~b-SI$ zyS;VW&1z`;0-g0>u=3N8{+?cR&{KWbXL{FP_j<7I?Zw8!Yc21l&CjlwK5mSDS|9z} zI#}oRf88Ga+hpgAQmT$ZrT=;sbHXY=A^PdX0cAo=u9q*v55@Gu&;k=dRhQ=APjC&u zoUtQ1yD@w`uN2G2sV|fgY@`v=SoM}v&qKQR@Jgu@%l>3-&*!C%f2?-==Um&1PVE3S zN9^g3{pm#V@l$13)Qj;xBN<0@_hkCUfO?c3gvPmtCENNy^9}INc5<#v#Y}6I=VkPH zt@u_OP%jGLGF_-;E!44>&AgQcF(AJVv-r(tFz=k;Qywd_YHsPLmd^AL^_l|;9rx7 z1pNDn$>3!H`Tw212>3((&vUSIY|L~X>V^XUx}jj4LlSv8Vt@Ikr3%HB0=_a5(Mo4z z*mw*p>f%p?$m0ZNrXlnv&)h&X84-u`2n6LUysdIPBC4}R(pZudMT|P(nq=$NSEw2( zm%qH;cXzDj_ON!PUGey$ac{y5?8@t9yty*Y-3G<1B1?@pRpx&ZrlR-Cg?r|*_q}!R z228I;Y7VY699(bMn{K!>*08@c{Ks1FsiUR@3-=FhMK#fNYq{jgM zz|R5e`2W6tp#(kb7g+M&Kn5SOtTrt4-;`Q3r4!|UyhboAu{ z&a7Itrc+%jWWv;br%E`S6WbW?-GL667Z9G-=D+Ex+#9HReaZOxs_FR^m`IK+wQ1XU zFu_N5f;EkVK9rYd#H8`P1JTD%G6TJr8nhRSl^J$+Odlj4fhKvz0M7yPKie$;hU`Qa zdtd?#i)qsuK6H||&C1ONsimZZs=kpAS1{B$P<%oOx>74%G{6ljf}?(=E`QblH$vf3 zZRwo8=t_lhtVlSld!Y_?DvDb!vXe(0p9z5 z@F@kBPO=v1RUYDRPKfBv08^2$v7Bg7wRETXcP9G-rM3?j1}@xd#W_G`d)r&EYZC4a zG^`n_I@v6`S0KR|A&((35xAl>F+ZAKO(}Ewzs|_9tjJS7$`nS}G3O-v;08f8@>idz zQyxjy?s#`k)aj#jY(gCe2krW$_OefF7oJ{f+3C=}z0_V5<*ma;m7-!q2t04kWac&{kl?p`f&)57a5|Q2XkVcH5WZ z`paM9PXEVhTiJSNDVYB}o-n_dXnj93@O5=UIA#B(%l-_j!}BUAO`b_HN6-ZDKKhTHYyj4s#$%(HLVKpA1hT1 z7s~nzB%LXUHcS8@-gLQ-AAGeE-W8X53chctII;;3iH5r-^Kf3)?f(PDlb1GCtudNFCf z(Ove(^3ccYy}8c6n$lwO?2dC>tQ8>$Rb*t!nX~D()_*L_e7rIy_OSPYCX$9o5+f9#*K6XZcZaV`UX{ zH4V^_76nHD{xIjwa170~2M-y~9CusG)mfCcWDxxq_%Z;0y+*ul5&-`26)dbOqXc5Z zAX?XnS9OvVon_8txu>+!YgLkQwP0Aq>Xqm9E181@95_Qdl7qWaBHBO&h6$^Q^e{!a zf-NEVVZQC;ejMb#A7FkMhwV?dWt5a?PE z;_;~6_^7AmQJ*pL=l?U=#wz0IX$_tcbKH{_fXCP-u#ilmZLXW>Rut|^`+t8XD(b-Fv0U`mJNn)(VLRgTV**Kbiq(J6>OMV%!4cCkoh6#KEh)tsqP96XsG9SQ)x#U8%WUg9#wL&nd z=3Xdf3@OR|GSW~!`EogD+9(C-G^j`6{ROVtt=MpVgu6b{d0v(dez5Plc%O%bpN4s# zNBD3BJg6ls$dWp-!KQHE!HifC+;yb{frrloD_QP-O6p-<6&2i>OL%`_%FP>iv#6g&y~-bP;gh&1-C$0 zXR0j=4paCAXIt4NpF9U|+p;vg3X=-?UxLjjipQj%a|RCwn7QP72Bun{HRU8<(eP#} zcpLSWw1)uj;gJ81|B8tZQVvjSX7L7%Q)kpY4)tz>GH_-pUIeJDIM5k;l%8V`6p0 z%%>x5&xh;(u{7|OfPrGMQ+|er+@>$a=_CkfcheK>(;My1&yJpSD z^NlylSnCqp4N1m>V)7j|?Qx^(>&DpMZj4_w$ZyscgTLH3C$}R5T^SrGadxSSh!%MV zq@T9Vuys_#W8f!nr*F70DOC^*rd4h*X9P(d^xSgXoCc-zF%<=-SC%^$;=gWKKpV8B z(9DNVuxQ{c>bWpjnb(1H7awdZu9R{nN|?in+>6B&Xh*C!N$(C8JiAo3cSZARNlCRJQGe1rssuonUP#| zc3GRu+$5}~gWB=^~%4`_5W?_%Hs=7n+EwBe4QfBjDXUYju|50OsE8?|FdoEvmM=p;jx97v?u4s zwfGz;fk@6iFy+ax^UAbyQpH8Wi)mCr0#?bl(?)1Xd!wbof#L6xfd}}1Z>i1eIrDlR zynLrCxR=Wq7Yga;^Ql+Lp<6Dx)m`v(OuaXu-kU7iyQ12=qUg>_04Ik=Ok_<=5KI-- zK`s@cfPW@fV(zs<Gei)2HNTz2DKPgwwDW%8eP{MPgtz*#6sksOmH;!M=GikC_#=HUpRg&cq3O4w$ zCtV|tI*{DMl1|&CS=;qVvSRW2Yc@uf6O)=ZAk=z5M)g8)%x~ z+ubSWfqThRUiPX~s1HY$h9a}i+R{CJS%^?ZP}p{7pE-|J5SNtg2;DYkyps?5^l4L0 z`qc{2n2L0(MYU?=!BG!i0Wu%%V#_4a2w}m0*1(=MaAtH|NOi#cQVD%DKX+J}4GNuS zW7UV(P48#*ucu0$jmw@-NcN_rO)1gfXJUv8sg4Y+jzkpsJF7z-XXN+?Cia_7;m1J{ zT)|(4g%Hopxoi2!9f{tpasF*6KNy)^pr(v5ahC*ny>$Bhw!x_~^MJI59Y)Obz+heC zI4D|au2PiBF)QnWPlW^=2~2j&=*sV*g;FVqtXgL2bWIN%nFueeq_b|&;6naj4RbxB zi#z(%ufq!2b-i|{tM&Ex;EVnyWsvPCEfy@JVOh+blC0-?_NxZzUULyZ{kFGaudn=R zxB79f`gvc~a}a`=Rd*|x4@xPIK}RD5TlMUR_4$8Z@Bg|x`*_s+qN@znzTDBUZsg}J zi)briP9H9lX=9sn&K~MmMqn_(&GSz0K#y3)M?NTxGS_R{K zsk5x-EbCzg0VfX(bHxh={+y0|UB?3OC(Egm8agyTFO`r7WSJ9c+IC0&yQ$j!Yew)$ ze|=T+@=C$WDaGD3+3V{vGd3E)2T4U$WKb0{DBs7aILQ8*1b4rN^SVO-_`}Wn+mHYP z6fuCm#`|P@d|*#9a-5dDSu9v65R7tJeHg7*`|K zlOu`9v&gVhNdKSw@QU68>`qifc|nN_8!m3E((VaTd-q6E?RQw{Bfns!s1c2h}wRG0t9bRXdVkol1RU}iO=voxHitC>@kbO0aXvYI?rls#USv)&|rajELvRXu?J=34oyt0flv zuPNVL&wn>xWQ-551mvTFHOK%>XrRo~p}@}$mi62-vR}0e-}i~&<@RB~$4oNz0O$D zrv~oJO8QF;bsNO>O6aA_f1B$5x-;|qV$<`kLRk3nNXOYNWvvrlZUKfuRM1DdmiH`dM4}3V3^m!uZG;tpYq8cH4l!!-ZI@;X<7Q_%FactA)lg zbeLHXknPv2SXayQ#`5v!3vr8e%qJJh-p?BV`8U&=H`8UWrc3v(746NG?9XcsmMhDn z5G7%L8e~vuh<_=&afQsYTIp#UK> zS##C=DGha0m3~D-xZNjvd%gT%u3~Sh@YQtj+u5==bLDU5D&Nd&_m_-^D|N+T0r?1@ z;*h|CAin~CAAyUF!rKl!f$!*8FI)NljsM4f?h_MnS&q?%I<=#tuJI|Y>G5rZl&4*7 zGZod)o2?*-8u`WsL1Wm-m?C01C5l->tEiQjxQWzcw}=GWV5|c&?zCUPzn%eOKrkjE zd3X^$Tt}2rMSOIRRH916#9P@#{Cs3ULYpY#eOj3M+twQ5r=J7={Xb-(mT~hn8s?TT z`Jp)Jp)~$!Y1Wf!`hAo5X>0!LcICU?g13Do(BygAk^i_^`oPEmqttuKjEAsmjF+?u zTQD@tmqRuG*qS<+?Y-Y7d)UCS*lw#i+r`4m^c-~%f_TD;>flCo^MS!S`i%8@L(^JA z1Hr)_MlG;0C)?5Xa-ryQ5p%OazE;P*(=J`qQK8iX7Xjq|H~e{5E7?~n8BQW_b{3rCw6CG6-t z9!ikloJNUaOVU+!@@BBcyrAz&28EP&OsZo@qLp{>zn`i|C!0u=OnX}p>>OUZG-oKM z`g!ugBf@_9wUNOXkWlt6w!XYP7;*d<+TMxk7nu0-FTi-Ynwz-G!#orwK9r!Il;9t0 zX?F~QM@@<+4Z@c#l9wIIXPv5NodwTY<$(X4GUBcz`Mxs!1|R03sUR+R*j4`bt%)zI zqjy^*56yg#dxP}yMu~7ZJ45E`mUZkT%gu)$7>2WV1%AbhRzIt)QiO+PoH?CgeNGS@ zFjJwtkWU3x&%BNf)X;e?8IGXUS_}SA=U=ZDT&?0=se+#X8|=l#Rpjw}!lHrkbVT`K zw(M}eaPOMv<+SMayz*eR;&8p@aIJBFrTyJfH%Jo7VggG-U2$^bu!mj}bU7$>tB{^dY zvn%wx21RxeDU#Bo?#S?ocK_#NDUOJACq%lPAI8eL41<$KL|!UVHZzDR=Z=UX0z&@! zFEPh|4gT@SWO;cvpZIm>YP*OY^2<+Q$4(`jwat%=X-Q3-B%-!CNsssmkHn~_#TNW; z8Tbzx6c1~8Pa617nkCR=djdm&Ch_eG3at2nomP(v@pojf@c~F*M4*NLeQO*nvNvnl z_ZqmMvfnIWEy?rxuO$tp?7bj8RdPWRI4UMi6cX=r$v;e2zMn06 zb6v8(Al+Y*9jq1{u9Y9G)x2A2db`~Hc4^?v@~9yxt|BJ9JTe^eU*zFNIeUWda(axD za=V7}vR!o8Z@GWr74~^R_^b|$!cz1Rp0%;aYhuq;#gUJ z*~B19IjuUD=0plL;>OX(Mbdc*Qg(Vxl*RSrcqComF7Czr=K}KCS!pU z{)!QLn0zRHR*cML17p?5u@KlyBCt_~dG3r}bgkMlWV~L+JufC)EzNy7R{F=1{>_x) z`6TcCO8$q9qW2r>{Wa~|m6}(JjjtCw->eMmubnr=M?=|DjtnV51jv0o`EdURIgatt zZq;y}whLbO^567wKMVl=qGz>Kz#qg)btuFrJ*z%BVU)wYAW?}zP$g(`6+x~*^P^88 zOYp_aC??hgo1c+y+|Wn~RN2LM0qj7=Arq>m1qqGDGVNq2IiZ3NFZ z#)gIk`lbs)VdiQ34Diix4B&Vp>8^h0qsM{sDGUj|+toRy%1=6e6nEx_>m{5uJxF@x zI}OS?aD{DUM8u=E-9g6n!d;6GKtn$fT>$THz{`Y>JnZo2gOq;!9w5RiYj zrg^uf+h42QUvJ!BYujJzc(>XPQJ)Z9fkbE{keaaIf*>EcpNl5O=UP7LRvqt2r{GPW z$b$c%=+mI|MLlSx(<(#l8nMW#$bj~&v>_&|iAbvk?s1l|TcpqRO-20ZbJchmk?wXYxf!*yTn4n75qq^@w6c8X-UpAHRDAU?~OtH zsGPB95bW1W_YC~kHNxlB960j<`AG(>ct{!|M~&tsfTs0DyZWHN;%NgHwk@oy*)v6w z(%2;INk{An_l&dNT)#-Fix=^n4aLck=kNQVw`Z)N0Bdzzg>(fQ3UH!>X8x|ZV4;G$ zVUo>Na4coNP5`A2#JA#~cU8-Q2k*5~+GIiYZj12!^{RK*i=oaxSSdT$r~vTat{LC0 znfKRQzTw{ne|fjoSep<7db;XJPz(i^ga#Cc`WUgHD;2D}X5ll~yxcGThQH+VkZjKk z_JDX0YnKE$4^wf~aS>B;g)xmF2#i(45P-3nVjtZt2l5hu6U`RJ3tFTt+<4w}%XK|h z?|;-i@~oGUA#LQyLjQUq`p6lEHxltrKh=>KwK>#F#f2k9(pEvv{@i%7jXmmwEzJ)J zZ-MBak8}O}8Z(l??s$foy3EGx3b6O3DUVf|&q|2T)Ok-djJ+Bm_;$jdZ|fzmOu~J$ z^c!uy3?~i&pr%Atp*4 zil_)j7Kb2;f&)sCesyUP>ss!;M&ZkD@tZ!u>mCl=0-pxuFB@5~E4(cwxG2C8p3K8} zxkGIBQl$}0hg5MyWjqaZC?wxZ&wq2Hhtc@){DRDaW?4%vl3vNEGH}aD!AY!0bQz8W zK6N-JSC(H$J5w+sE4!}aoa*9#AqN^UjKHZ36S64?D`fR`z|Iciz5XRaso-&0oeq9LM5#_CoHd3)uo{nMO*virxR7lDUnByBwC%kkPoH} zwQF_eTb-RH7)&jVoQLp<{`Cl0xPXfz!O@q8h=HAPS?6q9@M*xcgZ$qRrrw3BQi^`0 zN_$>Pc%jL8q|V(c0DpeQi+aKHdhRn58|Hrw~ z&#UF1H?<#c=>He~ko*AtR<|W?bV3w|!W1d6BrHrB5CA1;3DO_%UnytYt>?ggLpXeZ z{|QwnW;{7^s2{j23(@IG*fjBD4XZl9zvV^s?lIW8`1*tNWU2OQNa7Hwf zf~2bO#f&&{1>K-!lnc>0^zdl3oed;;yCAP$%$Y1JJiId5#pi2MQzt6QLE4$)?F0QT zNmv5SBZM0eh5q#{&BeVtho}zrn53cC1u6FwX%A$Whsxw8}{H0>U$om>cc;7I*=V;2i6}-V&Q=>3K_RGSvN?_vLrmg z&LjQQnSxM6eIhva$F6X&@T7X6z}}N3J}OLuSMY-pSPKOcUg|pRd>6&ZHJUCn&amjAB59JVCfH7j8-y-*~X6bnVZzVSaDBRF{C?7Rr}J}hsfI546x zJeKd}MR&5pTmRZ8qI8SM1M-{&9cQVU4!&*R7`&`wF6+O6uVn!KGg=F`&=Oh}e1gm6 z4CuLCRHWW(6CGSG`#7Wd`b1)9Ew6NS5o9OHyVo9!Anl59+atXmqEu+4Wpj77y`SFRn zL!Ip+^3#iLhgXNe7`A~z9FU5$99<%hoJcrrU6_=fdddlZ){P$!1HXdkzaA$$xhoMt zK(_{mghe(Qx(as{m^+e0=)yfL!QC&$KdH#QT}&9y3F=REn_)%4@?}`J1nVXzDB&Og z*)Ai4x!;_UsEc#!0-AkZ`i{POj4#2Tu}eQ=mw4P7c4Cs8z?|Px=#SLIB;`3clI_lA z*&G9&Lx&)1yo>?aK3_=z@YicO3)(yot;4fxwwejuX6Sap;Sb<{!=L@X@K>eXZ5O>A zFa9`J{&m;%#|_=PWzDDUx_9ffaQJ`6|L|rXfd77{=lxC>yt}!c{t(iDAX$LFDHYX% zkA?H+K_mZFkLWx8Uq%#w|1&dZDIedM624NVgeTi5k2}Z}YcK>=907RawBXFh(;@r> z4mX~IcE?<*yDUr<=f!dJ2~~=WvJz4e5s@fMPQ7ZX?37TyKHYfG->Az%k18eCwOUw4 zgLm-;|0uFoFy7iD$KEH~&WGb4ndcphKj$Fy@hJ}vXi5r(^#M1;$*`t*M;!mCDE(0> z{+253Sq1qCti>tB!}{P=E(&5xgod5wcM7wCfVv^aL972`XXQ#hZKVjD<)rh)Wi$t$ z9D5IFEQ6#M98>Au!9ewq_=jl|u({`K4Vc8t(?2PreP;C1OJ%gV>bzyRO^i&-v&)kF zOgMZNja0w?D_-y(%HHAtQ2Co%f)D_o@rX58v{C zMEYO&6UMpO!weFfR3m)ed5KCDn?m-AN<8C_Ivec!S9g9Amy^iN2*g#gv?;!6CFF{N zY%SoQ6H1gMQ`+RpYbNb@g<@~Aw}G0uTwD2Ms4wD&pSg(eWNX)`BWFQl3ujKQgLk$a zZ0m?%c!v?}++;z)RdM0qI|nNcS9unYSGcjTsr+6M{!T&W^Kvr8vr^K7d>r(AwnZ5D z6PB32spkBnyX@;&?bqSj{U-IjO36cg{-Zi=Z3;2@m}5GuD1zC#gDdu&Ei7SY`2-1l z5f!nCbQ=dF7L#p#JU`ZN)m$`dX)mzWj0{MAh!qp}`;c+jBmnTC?4Q;_+lM;^ZsFC! zaSeN=fPGd)IV?6+up4;zg=y3 zyH-bZ@S?f<(_DP>T)k-y4(gat%lThwS*!Hl_lhV%4vBJzP4!6w@YRe;j87^XBc{g)g;y|N|hxhssv+YtU(p2Uy<_aYW1I6 zO1_uJo)Uu`|uX#KF+`hK(VV7)HO4%V^x!dIX=c`{tw zs*|E2|K|#cck7sYojf@FAwCUDJ`F1Xf7q3&j`UFl`#^{4>wSGfW!KB=+G zJPb7Ux8%6ns;mbvkuS-4QcSuJd(&i@0RD~~e^Z9Po`=3w$e5sFp6K!)8;duKh3e3d zlwY0D$30;oV7ilcu3rGr6BgCE6vU#6kg-}+veYw3ACD&6oniUdZMKx%XfFmn!)gr+ zrY!*el93DY78o^tV>Jt)=L2a!S-~H#5I~F+v3umiHZl6eHQk>(?O%49e%oz0*fRch zyXlX+ZLilF4mO(KZ?(VQXan#+Z8d+|s5@LWKmh=&fpONZ6lYJNuYWTkwLLrjx+?2V zEq$+x^Bw<>L*kD^a=;%fN(_leRdC>4v$-M(TY<$f17d2ail~!5h@;-bU_3quA8ZwR zv3^3s*5=02y2}T77|Shenws!^MAKu=B?uVoXL;&lR8;BGKA$V@~no##vGy>?^ut5MMHk)$drknr^-EJ2X zAC{3J?iG{n77?NI^FU31p%*`>;KRxDq^96;P05|=qJiA>l8Eq>6CP~#hHwh{DS><>eh^B?*@9|mPl z%{;(g7auD2_3ENfYSIaOM3f4Zsml?kxkM#7Mi*o$LQaRmv9obun}T9U3CebLPrah8 zh*V0AAhs#={Y6?~Y*N3x;6jlGG91`_V3?faf&h*I2;5)<2}3cwoioYNJ=4}L*DDx= zZ!n#wcq6Fpo-7x8g|A~puxov^Cm3DA`j};L_PRXhW+4d}ZZPnAsLgv^l?OX4UepL* zHOOB#79MnzKdmeJeY9!0Sh%W|b6n3!0s~U5e6i<3Vf}iRXCT4bGuy`n=V)D(j46$b zD-Day_k&h2itFKyw?1lFch#-_-t)AW_LwY^E*SL!_(0|d@Mm=Lt6JG*wfI7raI91a ze8N^?wpoD%vp>a9R z0f|TL@iu-rE+OyWAm)A@O!pd0H2G zoT&`7Z%YciOii8_Wi82YYefXhCQUu-v61_vR=C$Bf7@1g*j@3itLnB<^{h?1rp>=z zEKWP|SGv1God0`T#Xhw!J&Y+pm>` z>(0f1K6F=4-D~H3<39*L^ou|A%c1@R{ME6698Y&cMh4S65H8>N6RujKD8(fb;~bsp zm4tGR_4>uLt+ca@S%C}7&L@|s89F`BWZ>&eyo$~OgCaRsi6L^47&w7p4L7j+l1{l2 zT@l$X0hx~8Y(zNZKQ!T?`Ic_)nc?D>;@}0^XQGQ296?flFNwPy*XD@O=7`46t|v9} z3NsZPq-Uh58^y3IIq#l<^Qczvyixk1RrRj7;$=tKn*qa2Deq3RwuP37KK>Ut>R}IZ zvV9od1Idp;r@6VNIND}7+SO*0iX-Cl5iylf*g7mun-EWNIt4pNHk%8e&jUOYm~(v_ z^$M<6@~%}1LB=wxS6tUCrz+*+W#X|C@kpVdTgEc;@uOP$`8Y-(+r0X#OJ%s zpLQBQY&8M+A68oqX3YoJ>t0RhHk)}PDomQKGf%c1*o_MovD_@%CHYCNnzkzqRD~Dz$DD@M#VcIeSUVH zX}{VauZQ0P0ZBFpn?&ga-Q~k-dO7@ibAIgwL$45%8+P0UhB66fJY!EdsSGzG?hxNjjorU+ziWMynHmHs%8S0cMg7et~tJ5it{%P*vDQ>~( z?m+}^M252$oNsD$R#8-{J~>C?i!@-;%2DBYuE+0plme4*K$JEh${3Mm1ML=QoIqo~ zS}vKcgyhek&`8f0@-CK10sH|a2lC%QP1+eOhMV{6gHGrC54I42j(S?i?ZR`_%FIW`WOnCMz;%(RreqvgD85xwu0 zylLgY{_dxPeS;2FjZP2h!~K$Ij2 zOH8$LhHdp}HXcAk{BE`Y9|Ec%vYT&~wH@2V6?hsA@!?}c>=K{2t;*X_QEn8|Z)uqK zwVVeAE^vFEHHx3MNMU~Tphfw-zv6JB_0^@eNsXi!8%YiFNpf&U9JfU~`OuMZ**?LU zF24NGcnvm35s^}nNKk~vR->`y@nLzczwVgjFvjZQpgWk@E_T|Wh%hRro>$P$tC$xH zdDB%Y$oz{XV$j2$FBEi1s9j=un-KS8qWo_==Ks9Yc(_slou7Z)uKjIG|7NCie@^%A znh8o)cv)ai98LJ~SoS#&fp1hEFuq*DJN+C?ns8^VmB9#gRNzG}4)A}|A^UAWx!=hJ z{NHzq_skqvj`pO#NfI3!bJPmfYGcp(l6@1|q4@Z7L1?>BDl&}_km&R;R{2?Cz`q_0 zmRysg9MCO=1DDOSN@B5wS)~)|3v*RjA*tP^^~KrT&|~&kJ0E2t9=5gO?Y)&z$?#{E zgAaHt!2UAWr3Lw);~5OKDBC}j;_Sw8bu-3CjZyG3yqpy=c|!r6AM!>4Wvd9j0{JF5 z=xWG2RW#UJx}#^_G;*M6`KY^Mf1>Txc;}PR*5~6xtuk3IGCI}6Cp#c0_KbDt&&Mdf z!PS`*acDwuOloN?Rvn*E8XL;?wp!H*&dbuzE3*28nO)p;h)#AUn8HD80vIyGa%P{H zHY8_`1xW8YisTXZiuXN&4_%_) z2NVbG;@xVlIMh=V89iq(M<20Eu?_P5=X3ISdTszV#VLXvOORk`S%K*Avw_X3#=KaD zo?FwS9vRYI&J50BCh<$@lvtMZkAPMxQ7GzGcO3m@Q+SBZdaU$gXIzE z(-tn4#beOU7j~I}*$ePhz*iq;0lDX_E2G0MGKg1MV1`3j6lTv0@vy#URY`=^$y>#w z?J^Q9kK57FwsmZZcx5^7y8W64EPn=W*c=ctcj8Re-MdX_WjAbctU75RGOuMCqjo}bv zz<;}v3_Gdsn*~ogm2b{#KV55nJK6MP)b!+13v7*iGJXE*%e$}UFOv}-e*gYYc|n2F z7!(f?1?99RAx(k^<@;a2`}_7MU!595J_p8(n; zMUX6!;1osFQbm@0pt7fuSxSqH&OfUs`>Lu|EH}>&u0f=P0ZJa%O5u;YuUt9XKRX|FDC@a z3J5KTN#ywj<~Uf7N%B^-(uFGC9MId!SwKF4%IB(@2cKX>LLC-UIvDt_yvz<-dU+zE zgNmI{(u`@ystn)P^Oc`=jDPGj>@Vv+t(pH=Z<{l+_#sv#ryoT@cDiJw8J}RlM(dLz zASz;m+r{$nO5Ip#)rhL3na(VXio~7%sX8%my&~^oI?=`X4)RcRj z^*m%G%x7WC9{Q{w@@H4FUvluzZVC(|;-n`tCNse)q%23FWtJk2`?nW%r1_@jM37?~ z<77BRIisSZq`iVsHmdJWc8?vc?1(t!K3UxwciM&Qjr9Mgp9&Lkz`})fW)NVo3|}F| z&KuTALxYIs?pqp%%5$_U3lF%$BhLtP)>V14{LEDuVN*riDb59*3#?_oS4Dy0*L@=m zb_>4fki6d^Y-}rjiHB=P!L}DZEIqnSd`&v&k6~p z`2|Xl(H#H4^wTF+^d(DLDOiLp87&%iAeMl8z<2yXc|9tnjY()jT+)buWG2Lo3J6yV zs4b+JiIS}S#j3yEH~+b7K3q2Zw%YXcLRAwzHs$pHU6B}AjSj7hLujG{^hu$$$q^=O zSbb`Qp1~R`uew}iyi%#}7t7R%@%S^p7%;&gGkMx7gti0V5BtB~_wb+)x@F*w$T`n1 zPlfz=GTzD~%^{5HpTZ2mV;v&!o~R6uXkc5#I|N3b3rKQ~N_31ZCKg6nN2K|tvEtdl z1r?@>;1d8HqDfhA7VC3@Q#N`g6Ks80VM)P%Jw@>egBBbtl1Ot11R)0O70U5Ok~|O; z?+`vBq7;R0AraZG4*C9W=jj<&xdhmi4C_0$i^u@}ZYcz5yEqGCr!4DcIpMyE{;W;# zs7-jMMev|o@p!Q4`FS-|Ag|^cU(PqZS#H~3?f&D|g|Cn29*%d`bIJ7JAc}7QFBr)Q z3_}0<%bix^e7R)VAf2h=!c=`6SPdHZ6>ve!a;2DmwN!XXn%B?9Ulix|Ga?^~KQ5fgJ@v^E-kF86Mf!FH*4L2#FK$Bk^>)ncr zA|b+B<@uMjwUbpfljT)y3>wMdWJ$E=aybS5_e0z5eZSyCFAw-XuUps~6_iG57Bw&g zb=o25FK2*Bo9+}HcPbDJA))>W`_-)&&mjcHCpd(n?8AbO`{D!A1!zvBZFmkchZIIC zA{A+9n$D8;UQOpnWp|TAk8upm4NQ1Gz8rDHI{N6jynsl^d06LxJ?jZ(kKnfk+K2d~ zXXFtupH06c5tN1p6nH+s;0i3 zDEsMN1H_!)%~t(%w+${?$5ey@q(?IsUrmXwiH+%(^G1@yt!zvq19?o0Z{?#g&aPUa zWXN23p|0gpU1NWC2G41a7VR|)m9rh0?@#7K{KrN??9YTQkT)&L=`vlVLKX7mUXZ>= z{Mo&jn}yvMjJFR17nJRTE*59-{4ppyKa^ci9y0^ygcbzbrXUF)ui@oDbgoQQRwOCZ zNww#i#;cNxaZVxqy4pu)W^v&5I6?@{TNOb9X={p|7o5my6a|tal-+h2!C?&?_E?4r zbPp5fRWlR%4ma71&TUR1svPd{v9(T1|@!hm_>p?U4 zoDkmmVYcaEM_!8*WsLTzhu*$)JakqC{Cj1rCI-5mfovDyj!6hXyY`C^=w3tVH_h#{ zt!=}F8tT437N9+^e!~B+!+Ew4TwnTM2h`97a;_}yo2p_}6h<0|3jWew8b|?UFi8*{ zYZrpv>&Ny&b>x*}?EU!u_|UICyuWZZNegqC=_;HelbURhXwC6v5kgcbEbO=Ro-lV4 zT~P#=2$LXf>;9AIJVBSHf;$U>oVt%^b{8A)!MN8+O2f?CsxPXqawnz0?S$ z-+7on|64xF1Mq*;seV74_tu7g>L>gY0sq0gH0%LKa2n~ZVIp5L>T5rmYc$0S+v{(_#jXy7jzU>67$O`;{62~sXs#zP4eWbu|;vz9w@!3zT83`fAD)7FiN z%E#yHKH=XD_`kn<`p5a1AMRaQ86QOL{)%L`TkLu8Mw9-$C1niAR29H;NZ7{ztSR}7 zK50y=8p)3z*2p0!(U-{_*9q266n(r>`?uNZtvd}{b1<5=ZZs`-<#Z||t7-nn_|ffb z478OWPm*@lSwJSh&$gpSt2jWW2LrbTZMr!47Wh!*Y;{G4H60v z4o&cjit`SYx_F8l998bFEo|ypb^J&I2iT`+j-NyO&bd53Se^$u!Mu*U0G-(l-0dm& zv<0N#2(45kuGH89L8~p4cJqXBbEtH4taANK_2csmuV*{n-RylkH@J=e$N6hp zuQsE0|0(J(Ul`~pC|U$=&&@`N^C$cR|3ttassKg{5(e{>p!wOE&g#jc-|5Kx@mk~0 zx10Zdt9t8h9pL}-)%x$wm0vHH*Ry?VV}1I>F<>x9~N`6v34xu-O1e7{pnEr4pn&22>6CY-lI;W z9`+XaMq&5+kQ@={y@5i1+e9=2i^n5U6o}*cpd)r2NykeW9+>c*Uh+tm=YKdPV#J&P z>aoIBmOrCFPzZkM33FddZe4kT{)C|^pRSDj+5w`S&{qN?KhVVz2qCEf2*qJfxwCVA zu>XKkFq4}!k-`VH1fB1$ll<_xJRVq{ds>bSd?S0w2wMOq0$yPY$QH~BP+x&?&~m+c zr8x%zL93lbn|-FuK@0S2+ZeBXHr?`iw(ISUzSnan-`zg_-GiBLZ(V#nJ6#bcjQHwb z+fw<%TDeUkuQvI-HEyaj?wmPpviKMLhYJ%1G_n)9lGbF(@m$7}3G3EE*LT+|KHMz( z>2?)Zp1;l1KJLvsSIB5)`!>+LdiaQbQOv10dY_QoKt|S4Vmic}b}7G-P66={ubq3) zhdnHbX;-@Y=em0Ve}S8wD!}d=vwXEZ{q0~5@P9!30k*)?R^|0lS(8dC2}LqJ!>F#| zf&Y0J((Wt|oG2hR_HaaXLcSuLLUas_-tP@6&B|~#hzWp&p?aXz)I^*!5`Q?x5^t_d zt!m9bs-|T?QgW!YyQi==121S-8@QgqR432mkQm@ZDLjKg6F}kYmgeJa#YBy%a zlc}5xc*etp582+`IXVMLlcDz+5(RmOkOXpyw|brHjSNrBYyIr7qW~mm6}H zn)8?2i`IKg>;0vhqi_qZdpZTRC*5zZ_rJI{@cQPdcXy`$zB2c5{>Izcb416lPHGc? z&k2$;gPPdsQrVPQd9E17|AT*DuDC6YHdw@e^-b;8LdVNXrVqERKi{j_y4&{MY3r@3 zxY2YRbbxK=_;+$bK%!w-K|V^i^({KaqrzEM&7@mmDFy<;f9C;$hp$1VnmN{Unn_%Kid<7I~dAz zj|RXsR7Dz=hqL!f#qe03Xb{s7_z`2>QCR1&n$%K~8;0sj0T;A7v$n0Utv;*X|0~a! zLt&sl0A1u*9>HC?x+!ZzgEB281ZA`Q&aT_H-8MFPO0Bqi(1BD0`gQ+%yCh8Cnszo znE~P?HH6S+I<`l~tz}S42>4P;Y%!S}xz`1C;BWy?dA_x4=4jWLwJak#MCr5do09lP z$Fd;)^S(FZLx1M`<7p5Gy%={d+;^E`v00TX7w2Xc=))UZ?CB5YW9-zbGse)MP~>Is5l!c)Qe*qo6_`z`v$VyrD}{*?-V)%J&SEit z!Su=a=-3NITp$81>wp(025RV<1$c=`tFCY zWPj*Wf8Uq+ZFkzsW685d*;##lN+bp(VZmI0Py@pwRE1(Py`sSF1kWFId*~jK4A%&j z8_1U8U>0NuwhYN5dEzozX&85Wwjj@%QB|H%A&nO4WSYjTQp%Cwz%O=z-lhge0gWSy z{o#a=a43SH?fgTQk5dyFaY96bHdT`;&?bXh6zI?^K+hFO0sqZXB>=u`7DBhUZTr8h z=fhaj30DoGHKQ1)ajWI=zy)1yNM3A7T{)Jy+?BQ3U$8!Ge0rwh`E(;}0VqOwbpzJ_ z`1cDJq50!a^B2af>hq9Tx1^rdDWJl4#vBi`0EHE2%xR+~>S1H%upxa!pE#7yJ8R&L z6%ubXiI;m5ACG5lJ*@uza`DfTrloSpxs;e;d8DoJy#PE-ybiedeK+n4jhiR|zCGC+SD@V{ad zUoI~xAT#;yu)=-C{!ttssI9}q9toqlBP1adK>$G*7 zT&<2@tWzyDK{_UVxl_H`o40;a|76_qbgK6GOxw$=$6sC_d^I=r?(XEfTNB^iI`i{` zsf*Q`z8t~P1k%YY&Un6HQm>e@WK5N7&R8@frtBeo8m#}3eEw9i@M@L#f`vX|!YvIX zZ7noxJ#75zNYSlg{*W@NiyzX-MRWCgwg~QA@^Bg`S-~sdPqYu9yM)F%h2+F0!bQOI3zt?+eQ9C|(h(JP2q}q? zQ+&wg1idhfT9sHJ3&zQU(7-=LeYKxz@5*&L!n1b(!UL$hLY#9VfpaNK3M1EZS2e~P zx&|+lB;G0DJuQn{FBSv-um!g9w@rsZu%;K-Cc-5CKlm@#s(?n zsLcd{7xescHypt)=SH5+4t=;k{rc+g*6QUxjnu+Jf8d4t{4mw4p znD90Mvz|q*q>;hxspc@tSu`ycofZ-hz0WaXmmN1CY{Xi1{dn(GV|AIBk{Eh$B%8L@ zn)0S61H}K|blX}Wz3ok(vnu=2Rj~enD?)N`rysT@5HWT>!XP}u0|isS@`@G)5;-2o z=slkJ1HPDjzHl#2!^zrmYZEcDHf<{>lq-u?h>;SSU#v-{&10wW{BTs)FyG(rR0g6! zX#}`fj04VsgO0g@{v90hM3Ufq3jbmnzl9W}cKK63Kjvx<5Pp+c zpFUeEYgUTX(G(D)rn&f0o&AYU{)9sT2`DDfDU|7nhIksxg1`q$0Wq1w;lK;!dSc*q zfcV-s6(2Wf={w(cUKtZtB-J(M)}!phQ3pdfJ~+5Fu#SW=odWQ?ofvj*Jo_Ul-o8~N z+!>YhWgyp6bn1Yq|td;J(^#T3nNZF%_+9wyIb>rlR2WQ{j8hGb60A%rbZV>Qv9&~OVvryI zh%?*Em*W>83=Zuz8m{$p&GonU79=Jk><85(!2eZGDmee3KL+|sFOH{7>$u?mq(u=R zR>?dP2&uzZSGf853j%RumvBH5h$yiBLBopY6$3KP6o(LoOH{05B;S{evq$7IGW$z< zjB;ZZGYc5$5(E$97$FOzqjtH+hmoKz9=Fqhy4OkU9eKoAzy3zRK)!La#Wl@Z$ zCd55I!q*rRRt&->G<>6gS<7P@Nf=Wsv7E!K5%VoF+D_a?hjD^XZH<0_mis z^m=dSy`j!QQ!3y;kV#x@O?nB+|NS=ovG0b|kGoW3In+~y8d(3pRR-fva}Hv-BQSQp zBxi8rQGx&x(=!GlKO#Ro#{PZ^i*Tb%WP31+)=UD}0*iXi!y?W@0}mRR&6`CJEs}@jvh68Y zZAn{e&)w+JZVnbd9j)%@a8_p9pz&u343|8VmC?K2YiB91# z(EI%pQ9S5UBoC%Qb_V^mC*Knr`4^A)FgC>n#Sf&%qh)A^NLc)4xj_`hMD6o~%QEN^ zz~U$FcH%g=r}~E$MMd_Cd6#pNKvuof|A6-JAF4wSUd!TN%jH9=3!?o?;NBaB8wT#W zp0QfYSt;SHmGEIBY>%}PAq+Sd;9f9q64>xB6+N(sma7!&P08SkuC``@3dee%etoEH z<1~b$Tc2F&`E(H;d2{2`%gZM}-kDq+Xsi@dtbD@JI6mNSWz%8N8e$0`3Jutiy9s9GLoSB%+MN zXi~^4g?t@_l#RipAP|axfGi@>Bove>mAyv&Onc+?|6pgF^|4oCx6nN^sFZl zEYF9ryl1`X-H9>niAuSDB+JF0?H-?qkiyc+Ldx6hq&IU=O@&DW$|BXliv;y=IWCe-J`|P~ElfxA2?qkA_xM^R8q^;DN+{5CKqyh70&dn(O+Ck-L^&LZ zKj=$w@BzXV_mG>|#Y5$3D*(yxJSf}q`yAIlwG%w109*th7x3e~b06!qrKbfPamI1^Q#vLPjN*Si`|I z^P=0i5ii=be;c-5)q)g&zb4EsEpUGx+AljYEI$ToVX#`1iW;FHJv>Ym=x3sltAyO9 zI9a1oUd&)XmJRd?<^F*}5V!I6&LWfa0zp->3h=+$)ihPBFBhXbQ?S>nWRJR1za7r` z>q!2O6Z-dK`io{o0X~Lu(2ca;!$u+YMoWT;pq>h5pW{P__}V+hE*Knsjz>%hUu|F} zYlw2}{(wS8G6dq}2yS_zk?M)BN-izrWa@btvQTpDAz!+KCxFk`bC9uXkKn-G6!(M1 zNY^%c=t&`BLW-D4K;2Bk-N~We&Y|7TWrEv(Ps>{<;=$p&reoUHzmWx7;MY^IeH_F3 z2mI%aTnJDs!YKepbE#y#Dt@CT1;ipYj^=K36|D7})`rVACTcdOTb^C%d2+e;&5eJsBklr+8i$jQLh?_q=-yT3P;HOgT&r`e0MMM zAtzZ#Xi5wYreLj#G5toPkU@Bn0F`hUJvDM^r#2a^ehyDbikFk z&zFazi<+Vv+%CS z3`#;xN=YVB%JD>i9}B|20_do_dzZ}7-iQo_lysjg8rp|lNWtC8AukqE@8uA#s*tuR z(9mz^+rpkucC=E&*(hRe=;$j(#!4}B8~?RZ-nxYk$1x1(mbh5VwYjFHBHJCgM6g~e zepD5|S)H=ckO_6!8y)#;#|^84rK{tWYm@blW;)i+cRZgRe0%fs_jjg#ymkJ~#j(to zP!m16oJRoV&juy4Ny$2@q<62LChA`zk#1catO`9h?T*#llm4x0EOvGs7$m|K`T{4|k_uTs*aP|C&6|%|Jt1x!4*hr9nw=OJE;Q<_xAV zhg9U#34|d@)Sw_@RE8Z_u?FMW4IHwO5L3A7({GYA~qW7$lq;C-bt7B`4HM z1X>b76&wcO1EX8+9Rk^HflmM^{c?Q*p*ZpRrEi{nbN11>6PKHcTH-O+YZ4y!4yi%`FmL1>HFk zX2BrJ0sPGhZPdZwXvc6~2u*?H<+GDc=<7^erPwQgWq$}t(Y2AG4OCp0kT{-Bn@Gn^ zrJ-liqONB~-cd*0N<~~r41J&hF7FaX0xA9*sLPMX{ zyj8YYCWXbnX^}jwj0f#Rz#lle>qm1}x(XNj3`@h7rPI~R=Ng}1>wkQy@7d*{@8+hS zP7lAHIg=lY)X@-THmY2Jt(Fkm66k|!{#X|8bOwDoJr)`aO(ha8q%lY0XdMD_GoRih z;FXZ6MR>9r5e4`g$b>Q$tx+Zdr?FPTha*@O1QbMfp0gX!DYK&RdLoDCAC1A2r~4fB@JX}98XUM=RYGdjOXGEy{lLbE{rjff#=`CXY=QF?D*|3pWD9o-+y`j4LtwPUw!_+KKsp%FW|FP z`2O!c`==fM1D-#?^Y4H4ozH)Hw*A~MetG^Jp8w;Q@Be;k$BsXI_TN7JK92DG$6ub^ z;rUO$`Z))F^=t>vw%-MQ`%ka`yuO-8FcphFp_E!C}7fmLHvVc z003gUwpJD{*gl6s&tMsXOdntW!P2Y3kutF!N`<~G%Mko78mOVB|4=q7GYfc_bOTe> z3zjqmt6z!ikW{}E5FBvhs2({72Z=*=U@Pe@m5(SgIeMwAvS-H`T5VqVjIUp#Os9gg zzjhP9wS3-vO5?qT+pRHhl_!<=(-#b4d2OmOwhN<__#xUaDruw9MadltnkNU9&E}5C zJ}?qVgmO&yWs?c^nF-2!2MV-3AssyKARm-y7SOwCBc4kf`-38v*f+w<^@lg+N?eiY1p!}#fvn?C)OO|I@N z4{I|xoYye04b86t%|&kVAlAkz{*o!eRXZD-dF=rJdwm6oR@dP`*FLV`-e&prC6ast|< zZ&eE}Ep)r{XTj6mE?yR87y(<0Ok{N5WGhuzBDg8Rkj6*(*ApUdx(pzYXAUbXi#4!0 zzy>#Q#$tf@N5Gb2$I{*{J#n$oIz zA$w~Zi70S3n`-#Sr5*q0Jar)z1ApA!>PpJ0HYQov6Yq?EYEiIEvKj`uH#M&mr!<+I z>%wO%u1*`lc#CW_B>j7xD z+WZpbo!sn~fuKWwqqOkyji?4)yp?&=dnUT}_maSCYu7$l$KjiLs*mHtE_{8`0p|V7@atkk$3PSH5GixlKy1o9U zECy_1H#4N@Yu7UE&ZWhK2{(;I@LPo#HY-=wH56Y=@kKXtr_V+&xNRrxy?{zVRk6BW z{GU2MeByOhrAM(krV}dEe3|_V17oi@7NqY@07YEW`niVcnrrCVPXoc%zb%Ws%6wBtA~K65kC2WB&BQT2X7b|Czy1NhN3paF^0iEO&C4u>_Q&q$(gCGtS z@;sI0pXIU>7jbp(w;H)swOqXlveNOVBzbWdh4tzx-ci0V$@IEm8xqlXLdC!!GRZTL z-HIs?m6pX@ zQrf8vEa=z2uj)un=swVrIA_0{^fk|5{)q>O_aXzCS!gHX_BhiLN!-rQJ->5W<(WqF zuext~`hX>e?zZ*TL{kn`Wb!efc?6vC@(g1euQmdv z65~0&^&KvoYV!3WYy`7r2P#Xn`Qy)ixg?KUn%%;hB_wla`(n%DQ1W9=-6Kk}KPcfC z&^$bEKE<+&2yh$LUz85KV{SLsuV(FAJN%NVz=laOf%I8X{&Z)I221RdF2aey-P#}T zd9Z_#P8I9e<;Cd;nJ#uyo~|0aB^^9^P&|23_&R2I^ci1?wY0h%;wj}}*P4&*D4MN% zy@->$mgaQ-xDZ4kBCCAE#Fa9y&(({fDJfR7-sA~B1a&&bjgI%D6VL(S1OWgj1X3S{ z(1#(BF33}86bfx<07Dp~5s2tEZ_NJ`Lc;K5V$A<90B2{m1qFrgH_*vMA{rkS5D`KM zr2~Qqp?>f{1Gr$CSMR|WNXkDXDk+Q}7DAwhlLG)D4cSy!482a|3eH9 zi=x4(gm4&5;8Fodl*x&hh#LaM{)a*fBhsV%!U+J|5WhfzgI^#yAV}2+ZU{GqnWzdL zih?0bU`S(C9MVXYM5j~HdU{b&QE>8iTM&T_4+{^Ji+5BP91F0;I9fHF^G*2|raWcw diff --git a/Tests/images/lena_gray.jpg b/Tests/images/lena_gray.jpg deleted file mode 100644 index 72e9a4a77172c62812b054e2b05a06f1bdb17002..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23013 zcmeHvcUV)))9|54k)o(r5Cti6Rcat~j7S#{l@2O5KnM{?fP^l@?iCOe6r?CB2r2^7 zLC&Yty`+760$A>^-1qsO=l$#T@SHunGqbb1v$L~@nVe;QVt$5J?=v(p zgxJ{GAY`n>_n>-a>yYvV)}sOJwoM{8^ST43_06#LpU& zlb$)m#vFqLStZEz1YDEZ3Y~%Yd3bnudH8vG`Gxpa@(BsA;^$u_ym9SX;k9cw3h}e9 zrN?67?sLjMy6%x91g4|D=L!NDd0u?w+r2(dBS z!LWIlFWFF_mn+y<7w9m2aR5c(T*1Z7!@H6XsKc*FHi(^L8Mzu_<7DGt=VV{O&Be2V zgI^gSg*Z63tx;N`dl0==!sjG{Yu)8rxqBt0gbzJ;R#x#nRino(9b@^eYuts1Tz@<7 z^mhGND_4UTsU+16wbtF3iTpF=b$&gQhB8;u&K6vKS>HQ#r|?xn-?WXJ|GBvIM-`3z zGipY**nso#8AX*%1G7R9J3HttC#z4~Tq}^QE^Jd;!wGueBe8Y`;^gIZa1Wjzs`;iY z<=o|aDn`#z*oCMvF3kmZfO|XgMJ?z=>IPQ>YgH1a`+FDua}Q*Gbb;9d@pG`+6oODt z<6v(|M)#%0ykieW{$xvS>GTlkyxoB7eU!oWj=aJ)!>;AY{#|XPDUZ|ibD4tD4IAbP z(lU~9TGw|=+f_19}Zh^|_9rFFGYV!ZRs&hWU>>+JguNw+17cw-OU_kWChMD7%$$8RfM*kk+TNMTFU=Z@_qY$pPh zrxMp#p7_vy=fF^zowLw>CBfI+gT5P$N}@mbhEZY(CS`N{T3_W{=PQ~> zQR3Hj9I|A7yy5jcvf_DGYi6a##(}v}w!9)WJt*o58s+_ie}~t^#UeZ?mlav^bAnV~Gv1lSyIIjJe&Uo}d}ydV2oQTlD?e zLnetW9ED=0_*o`YYk60N*FV3t^0~CkgVke_rE_xHwx^zFr>%xWm=MOTzDhyMV?kDN zHYIf;;A@tr8{!s!Ovq!p)Rj-`_(UAtH*dK`P^J^!AA2!;U3n&i%X;(ma93^3Rp~ub zhF|Y|DftpAMw=`8)J1pc{!3MRy*fAYg=pPf@wAMX!Tqap>5M-T=2O=Uon}Hwg{{1k ze{|+o?;mQidcIIrUY}|Vh50#6=g_6{!XBMEb|;Iow3MrW*GK1;w3fqao-XU5BPL}E zn@2h3=fgz;eEF;ZkVb#7N)u{zWn}OOfRk{S!Q}6%Pg$V^kGNEVjV$-K+ z5y7vfdIc!1LH8m@M^R?vO0s%PqFQH|!Phrs{Z(UH$+JOJN3EyP(?SaYW<@$(4`zxc zAD|Lt22=XPU25FS-=`-KM-(M5@D&Yy5=MV)X^~QkA*(ZH83xiQW{tSAt68_-J0E3XQL2g0-8F{lRz|6AIoJY;%P3+~lV%VSk+Zg0Rqum%}z< zZT92{&)9W0=ANjENIu+%pDCH$IvVL%rcu1%W0h~qt|0saF8#1?=TZJ&+dG*MfeER{ zB-t36`s?3t_!6^)cIN)GO3bP5XVj$Bqd{T~Ovq@oeM%^i^Ms1fi_EKyir#HIrCM=y zb$9Wa*B>6Cwd!#^_ zhmvOt=6e5RYY;6nHS@632ovJGGI4sIdVV5WY+Z1R1vgHl;KC)tlCrzzwbbJQU@^K} ze0lETk*?}D(wcOm9mN~%ishl*HQRHa%g%hNK~*s!r-AjDdH!4HhPR{*nI$mxS1_R* z`s2iR6)MdU-Y3steQGiqX1R)-ZZ;J%p#&zxQ%q}%$jNPb>?IK5ShVNQ2-#UrRFWe~ zqq91U{H4}XJNuTKSunvz;J9w=qy7EGm&Xb_m{3hvclIVs(DqApd6nEY&(zo@Lw3iW zn`xS&G``$kF|gV{Sf41OHb`h8$8Bb;qRG&U8|X*Byt*1W+`NIZr|uqm05a)Fkz1$7 z7ACZT39VSLO1sXHmX|4(aH-nIy%^p`w-@NlS`tiK1EV`FFVxz_UhhzKPUBLo>Q`~NN36jk^kJhCC83Zc zW}U10u%nAMQm~c^ERhVBzW15%lhy>&-LZdpgvm3Zck#s223FmL7q@=o&<_-lmR4;$ z^EsiGyWn!K)fSJW%yTz(>|oY$1*)`r@WwP7#dzvw4 zG55Ohb1NZ8kt0RwLQi{ocPDKwKYMpsLvgiFi%7Su|L118nZl>-oy8+qI$@q-zGEw9 zKCUh$P$7R!uCk$e?sQ=(ln_xAV1+ze|S!@?5+oD#?YzKjc^l-Qr^| z6RIYkHZgmeLmF0|{4`+Vw!70uG;T zYTGs&gaithm>*Wiyn>ub&N=wiFT}&U4s+V3eTbW{sPG-FQ7$U7Nln~lQcV&VI|H7WbcDyS1Fm}b>YXxiJ?;w6OQr;Rr4DF$v+73a|d zHeFIDW_g=h`fb6YE)snbRqW!PJuCLEZMREHF+OVRFycN(yZ@FO*ThPX9PI?Q1Aj7l zc$%y9g0SgR?5FC5JD=Re1-bcF4P~pZLv8DE+)^DIN}0w7w;X?Y=1RsVDCS1#;mAu{ zrgqW0HMW|dd+6zN0UvX0t3N+_70g?!&bxzIf2TpTY5I8j7P8$#vDmjGO3yZSb0v{a zb?5Pt8$~PLh2{FBh=oQJRw{?DnmA-x<*Ww zMk`4n0Zd4d2~ijJdG^(gl;zwzI~F1!=RrEfmzCZ5o^hn8mG)uUW5ljqxUkQ)#NQ9v zcuinMZf=rcr9Gh^PgpR0khNh`Rz>biDIW(vlKx10WJV2s&5(Us(y*l-G2+3ig8U#S zUsD|r;>CpSVi$IjjTl#@#VHcB?3>DnWP$XLJZlBk(pokATV}E|p`seJ2)p`W57Cc* zPKrOD%j!s|zt&!;JsM*gwnAEG_3H;ATle^^EtnHnQ|ZPbHtgt5NY@wmrp|=kc(?a`wWi5~+(i@I^H~n+g>h~@kd*2|B6i^efe~q9VN^HX z9C7xD!0L@3B|ii_zO8;+bF;WU`)Q9y7fkkN7(Ng=%;KV=}Oo-X=mXhumSyR6&DDYzSb+g%oBR4pTx@>yV`#;=36E~`Ajzu(Z zR;Lde5I?&XF=7Uvm~h|eNfD`}@7ov1DDj%^&llma8wftZHhQ`^DN?P0c>PIdf&GFL zJ$|a;u!l$G!%w1HTRAcdwro$$re|OWbqbrmgS-18Od&qO+U)2glJKD5HFu z*ckZ?U8H*GN?xYd(?`MRNyj9Pwy)J8BJZxg(F-;;i@Fy|ndxloz8hC8Q{re4X}{{wOBd==2cf&C3%q zua1!t^(ItXo_%u=Z7k_2IxkDz5mel8PNZ!Po%QTB!?u`E6KS6mRW~*@Bz|pNjz}Iv z4(@2EblJ70qVRNq%8JlyQ?B(x6N#-G$2Xgi8$zWIKG|ESH)paRWxEiw0{>=E5Yb5- zKazc#E)YfUoU#c;O=XI)eJIil?-m>4-dZ!rNMS7WeYy7GvQ)OqgQ@C#`mv0imp1P= zCp4}io@j+Y z)Kf1OGF&F)N;Vi4UyT|3cBzv(@kP@-EN-obc0SQ1N=hs(=Emk6ZNUt*hvCT#Co%A{ zaQogRRq7t;jJ<(<8#JH$hd!fkYUvcOVKaP`n|@ddUsq7>G!(`d%{DPvaQ8~zP3uE7TO6lm^BD?XLRH%Lwd=`oG~znsMhoJ%Tud3*MHnlie7G}cZQ7y|7|)i5 zZ(bm#sd-GuQ0>t(zAaj3wzv>YpN8-AA{}$`ds_A~e29xL z<7s9+7o$|VcY{-fdPVrKN!*#q&mw`2*0Y0(|6Ujyc=j@}gE*mFV! zl1fX%y^!9|rh9KD;mVaEXZvRE;mwj6^sI}xqAkz3FW>b#W9!yQX@75CPjvd`jjZUUy`^@fs|0CSG0T2GDy7LMMIr57!Hh#JZc_i%d)QG3n zd6fytykf6r>#3U42d8|Rw|x-3-ZIh_bIlKbx2=sTu(h9~Fyj*XU~X5TM%}hD+CE{w zOFANsV*&Ca&%Pb=q;5Le<`DVRkK+}X%x31O#Ly29kFvZXq`ue0oKu?RURcdae@b8+ z$LJDn(ci+ppIsq+m6kx$%|IJnw<)&ZD9FwdvFDnHJ8><%ZMZwof zmR|?Xv0CAng0s*X2nkX)NDidHg9PVU{hMXwMS;KP-(DPFmU_g)qJvuiUL*EBi}w-^ z_LV^_Z_{G$Mc^X)3`pQwOLbrv-p|t$JYatuk29Kx*^lyPmz{Tp(dW$>@$e9l-sf+xZEC*cY$^51Lp z9RaF9`w4hh*1RNww}l^xh*?$)7`M_BDAK<``JD+Qpiut;=L1vh{x@>gdi?|D1@VKM z9rcZsUtAeNtUTM|dgWZlD#7~9T8o@8JtU+Lm%)8v@n!?hXCMnaw;O@q^|zSzefJ zz-F2BK1tK{lSAw52 z%zo)wh4FI6xSHtc9q=W%;XE-g2N<;yE*KJgy+EL3F_yB@@H+%1*muCd2t4@l1amZr zgkib$mn-vm`x3Ce7$Ol2X&J^J41E2rV1S-DQqV7B=XHQFCU`dj;0L?ld0pJmcs#~) zF|e~_cm*(C-tK53E*JyHIF`At{tmUlxR40G#AU<^H%|h=cR5xB??J0>0oD-L1uqb0 z0GS_i#JLm;gPUFthfemQT|D5(65e%r-hS!tGCdr-Tl<5SC4s%3ewd|3;YnNfH?)y2 z2sZtMU-LKoA&l!!*uU4dB!S6T!o!=?PmP;+p|O|)Xp;LcQJ!_yL<|d~OZ?H$vV{2I zq5jtat_N)h>v{&DgNVAWuDYHiT@uL`=j=yfO)A_2f$tDK5JOz*8mztidY%L#Mi&I6 z(Ae*D!efAUA-IBdutW&xpf#{oS)%;`^uP9HC7>15BX|e>IuN)MoAmv>L6i^32Id6^ zGWTNK0mtvt4->67CV6=-B`5HM6nwL=JXwN2pw|0M>|iiF zs-O7U;_$A7fbX(i3nFCRek5}czr%Thl?){F9k+2&-v3b=yi22JTY9crdM-<6?NWJJ zYX3=Eu#`5i063b=QqD$p}VGR#@S*yRx{<}B;#tej_4FZADBH{@6??YZ~ zL@)!!Xn6{L*tylLSu{s`n-PEpfhtQ4!ylgTFXP}i<`Nu$p;ab$7f(M|n41@@M9a;u zS%N!Ye1TE)1!3s#C@vGcDAi|1z) zza`i_FvLac|I@eytn_Vht|WJ33><4+LcnUs4OaQz3;-9H3O!59W&MRMkr@~~Jgo1t zvn;pu<`@#%6-`1fj{U#d0r+POe83v%`4K@F*yPZ11Ka>+U}s{uT;>90JM#m}#kGq? zOM;)T3u`f0A2M0S@v$uT0Rpfg%X=nh1QJ~C)xTg?+4|y07;_vR=Y{tCsgd<8H~?4? zEOD+F7qss$%Z?j}8dl2h5@qd5x8b%R9xtLw0C+C`8fEcUA>6FZ5d6Qy>=F`mCy~50 z6%_D9c{KcWle`PTOCb>Lt)L{Yr~qlB0)ZNMU`XQ57@&1J5?@Ow65=>l9SK{cxuUtZ z9>yJK9PEp+4Bl_$671ok;VOaJEv_A?8R+Hh1!ONC=;etgY6j{^u$XItJPcNl5NDB) zJai;jUmS^pv5D&ud@sDVi3^V zKsh{7a+!lZhUnsp^M==|ILr|ZexO3qkpO*N9E6wmceejlTFZp4F5l_A!EZ2Fjk~%i zU_3FbMGYjY1Pg%0)O-0`vhP)XVf`J=nvUg4K)B}S|GvWV%z1fzZ-PiN@CU>AZ}Uuq z?U2GD43VY92L8aHNG>-4xwbFq{#Z*4k@PyzPnRgBsB-`0d7J6Lc07x z-Y=v}#^E1{U0pQYSTC$P5@2CsF$%}LF<1%l?~|j+TIZl;&^;wqH_Xj7P4Gk#8t;NJ z(btgxW01$;Ts76yG?2Q;y?Uw$grcgtl9IZLhO&XW%3ggX1VTwwS$(;#KEcHg)|KVD zu5ew||5@F|pCq9@|NnTvbE*kgfW}#y7HdE(pdG9po__G^(2-CB3sO;0K?zPJ#94Uz zf587hTjOy+9}!FS7XLrd$6+x<7>ZPtMIhC{tqyJtS+M+N5o#*n1~7FMS){TexRpR2 zz}1yy5gMwp%8E*|%1Y|s){sRaz^#k`Fu+Gm5!`@Q4K5=A9^A?*$_On3gs!fV22xc? zLswBlRbK`DHtvo z3V?tVKvdL`imVh2739G{K?+2prVIoJr+^-$8gQx(C_xIhr3}Ofr*JFEK)i4Y>VlM2 z7YJ8HNd;ix6!aFPix4$dUL8&~KtDmsqR~KtyczTq2R zb(ls&9j4LHV9{tOvGOoC4Hh>I4Y)-O7EcYhCt&5P%7Q7C1!^FxDyt@|E~_C6M5Cl6 ztAvnMQkGRxkp)u>h?LZ1fj%GrEzlC6BtUF7`&qW>+=7{CA`Qoz#RjW?I%O`ck8uCMkKhA0?@t~T`X9w|71rM{!_n+X#aoc z^*2^0Re9g6{P9SRcgI27RBd2uQf{ys}A+)q3CGC6oXfV1D)*&w6;uc;!9i&Tn zz4JFI-&5n#dMcJNxARq?6$8Vx0-HMPKSU;a zCgBrGFn(vRE}l~I9}X!|H@0&R{Oj7?$FDzqncJaZVvh^DkZ`Z~P4nRVPR)G|$AZHX z?>~9lGPD3r6X9V4K06e2dHnM0m(%gCwFCO}E1m=ED`y>3X6!sN;=0a-ucJ8?Msaru zk5?2Qy*QJkIL#7EQKSUVK9g^v7%xUwMUrMVoTyEm|aH{Nm)< zpz6a<>$0;+JkgsU+utfpKw;01hjYaJvG96L!D-ita^!h`|_rn;0g_LY}dJ&lb7Ec z38KKk1tPr^^VlnYWR9DQ+f3DyQ=T&+WLIgTLE#8j#{x1?iV2aJ(0eBIkO_@PYsB9u zEmn)er;>2k+U&Wk!k5WGyePbkE1l9BL8Z*gT%3sI6~9E!8ZT;TvG;g5I7w4%J3W}o za4kP)EvtC?eTPqcmFndr?yk(XU2-Ldo+gvgX+2DcSBwUq%`qAMdZIMOWLJLm4(tsZ z?Q8io^KrEnPt-)t71u_*B<^I?t9?lq){goxq0pRp0yqOA9H({6=3G*6LakrtT#va^ zez^wzhR25HIq%v1;r4f;c#L*n{KAn`)Y_sIuLz+?$`gH;K?6xC&wcbO_>J<-lDbAz zbE-@}Sycr0s7NI8!cMV$?;Rt|jBJ1`DJk27eai`AJYmB0dz(ke`Q^s0(R9Lq=TXy; zEqfbHwZ7PN*B-10JnU^z^{M?flR}mCXBk!Gij?uoPTQOkE_ECp zZaFS;+yY5Ev#|PQX`0-1r>fnijbjBK_6ix{I=ZPgf$_7KCm2q)@s&(Sn+f?bq4jTW z1U43$zPGh2ep+TJN^9oirq|#5wm=>M%GfRT{Q0gIYuV~fz@xQqd%{zqR%Gh@1H|+otEm@&$qqIIg0y* z>s1fh$Cn>czI}PTb)f?sRU-UJCF z>r?dN?!9v!%Ex6b#O97VO&ao_qFy|>W9DfUS)S*JUR|d0gxegY;U)g&5sRoc*GR?? zUNk9sG-u)3qw6;ZZDNsc9n<0u2_o9mUcRF|DrG{kBVl8x_Tyq>ZDI>Vv%H0dSM|@= zzt|*mjeg%S;(hCRnoUA4SDeQMvzVAVvylnp?(JAY1Vj3I!0X)(B5oS$&BwfLuJQBBjsSYIv6Ug2oMdtD3|H&%t3j(X=hGW^+BQUC zqMOUM6Xs4m+BAQov8AKeSG0xK-nDNg?87$Ef;MpQN_k9X*awg6hnpSaWjSQlV`E1$ zXi0NSsJDrhy!~`_WCh_6`Yp%CD0SN||Gx1|W%_xbqrtx9peXXYq>2PNl~K90Cy(8X zjdtE=jM}$2jWJ#z7E(&1)Ssd{$R)%y_nFxD_@WI%Yl4IvOv4U8R-0f#@l0qFSbvuf zqTA5+2_E0N1hWR{A}5BSZ9YG?Lz7nqr(^OSWJbWhfRu{A|gGmr=FHN zPWITif1cSOQ4n8O?={%oKukS$>WM4`EPKI}QY@bSu*c#?h)ECS)Q!T-2f6q9UVfv; zby3%lE9Q}tWqqYZakd97ufE&mCyIKT9~#GmZjd+3F9fZrpSB~t*1`oI|7Vs>CQs7hWc&L{|bIsHc0{CnjaX5hp7waRLf12(jR z+Nbya%rhho&4PrXSmNWDQ}iGC9e- z1%d1AE`N_$pLnT)dpl~NiWZ4!y4DqfjUf?i&E#A*`ivWYykYt(h%C9&h~7D3kW4*r zV<^breWi%G)IIUNrN_d<-+wzUFm6Jn%w0F1>TLWNi&VK^ao=~2#rfq(gag1%R7kcs|fmlK~#iCC>jSy{@6R;?ir zeO)(UZohq-=go6kf5e~P>a;<4G&;V1uZ|3A=n;3^cq(J=xE$3qh1v9%R4I~A_iaW~ zG+6Jx(;l~s-;&#d-b}S>h_Fk{^`!>;G)1e@uY$I(X$QsB>D3Mt;ntYD*>oM-X6PDa zWX)iZTa0Up7rc#_kTAIf6(IB^$tuP1Qu|vG`s?0j4~8^eck&-^u{epUq7TqwKOf0i z7(a&4lQj!t>jn=w&d3&nUKJE zsc&!!g+7oeb}yEqViM3F!hy{&n^`zcZht81&{Z6oPA}L`ZUuVnU92eC0xU{~-$@;4_iYL0em*PSHG(s6G-Ib?LmO3nmRBhTNY26|kT z%=|c@*rwhfTkcr_7Rm)IvDl5yD?@YsV2#ym9aMhr^r<(qvRkeyS{Mt^j7f%)$yteQ zK@U=O%Bzg*$~?|v@%yvB<-DqNz=(p^m!&xLaCVe7$vRK(`7>`PJ*9noF1E|b zTnE)#Zth$;toX@pp~B1GlKLtYCG6HmZC0nBIe)rh{Ed`PMGh@t`{ec_uiJx(0ar*k zp2V&-p+~KD(W_`UZqxv2Zj4+46yQeM<=(nINoRbnQdJIXQ_9XbXpLlAM8qk-$x|La z^t?Q}@fOBuj{jVk^U+s=u|DFra7HVfwg#=JiL;rgPVl-)KAwqHA&uOvRVKgieUs7G zn6f4NR4k%qOv9WBanF#ugvp;L3{cy^)*v|XG_I(~Jm8PM6~*26I}5j)H@1%C({uW& znKc6~TID`j_7hOf{S3xttx#~N&f^P@=0atA#)cBL^Gsy8g4Wi_%>*u_6jssWY208& zHt}ZRhwm=j3N?0)G10Nemyw~j8douL#LU%$ea4wkSn#!-vxcRO_-DDNlNV0>byM$! zx`Vuu+QMZYSL5QzX^pU9!Cuo<+mB@R%OWFDW#D& zlE;szxU1^sbj- z6_b@RI@BP0e%7{e%}Z2L>>Dw$xx+)MkH#JCUJ*8?`ADQ4)7q)Pzt8rV>i*-`-80kn zfVWI)1rxIWHZR$$%&hHyYOb(7Yg38gejrt+rFHatEgG8$H@Vib@`jX2`y=jnD3` zaWieDoNdIIWY=|Lx~TQ;@$FP7dc zL$kVEc_IsYaSN~T=Y|Zb=#6>oyMvFz8*RJ(II5yEaV)O$$mcJ%@srNG-Rs5lYcMxl zHY0q5?(1h#EAczugM-^V7;DVBZMq#J?!@_H6T1l)qW%5nDBbq*6C~?No8*;^GRmoI zS!euAf7LWa+|My%BdcX>rsdxca+BZcRHqlN>{#)RGU9FU>Yd^)?MYeV%r^~<)KP@$&kO|KCuv}Y<4HuG56%Nd4STiadAM^GiH9a~-&}l7#{IrKL zNzM5x^~9P9HSH2ei+nUZcve10C3$z98tNo{zd2)gih=5QMejG5HnsDTFE1B5)iL4f zKH56EGnM=j)!P=K;xu+a@rJbbvuW|#({W~{w_Mg%X}0f)4aV4q>b?yht{Qnn($QGo zZj>Qnz%aHxy!!~BL8GjBb`Cy%=SY^`w<4NI*rfPT5-q8?<~CiqZ{FdnMbYl8hU8QE z`jmHBj8TgTRDi70xSJ8}2Bx@an~;dMkg2j7RZNfJCT}WJP<%!#)6ABfKlAXZ$+TnC z!G(Qazl~edANluGY8hSg8z#tqIW(kpb;_&fwqc4p6Ozc84;tu13rK4Ghw^?&JU$D^)ZYSS2yvV0{bIrI2ICiqthdz7DY%a)-ykThNCl6_2! zJ=H|z^k1S@JB!L0nV~6@0dLEAg^Kj&YIzQv%P5!BQdXmhDS#8V0%Xb=!?CMq`9#@x zMNVDOC|dJ@yvg&iyVMk>;~9wKPUEqhK__2+YqM|F4nEWL@7&8f>`#~MlX{cHMycOmG9Kd>y7wL-li0QE%M?fU&l?K z4Yv%|(M+G3k?x%rc0&~=yA8kX*+YBRc)Q3t!aS}Sn;+>j=TZ{efccz~EBet?)PzCp zI-Py=WO(oC*ISPkJ)K5wPAtkmRC1F0WGbupn2;LMrlho}_BLZ^!vGT1nUbG86Ld&b zg)yXX4mnO}sb)6(6?F7Nw?$Q`%_gBst?yhvcUFCSHpM z&-glu8e>A8XIt7ouB~`bP*x-=olL(MCfwad_F(KHpRzEgye_B6v@YP}v%+Z37p!)@ zcD&u&`gVNZxGCBDtZOOR@+4I^aQuQJ?Ww5ubYoK8ispB>lX{B`ihJ36119krUUIU2 zA;zf-b#JCM+$6hqy}EOOTt5Kbot_UMl0Ia5y&{YzkQ41@4-bWzUHbH_ z5AuN%woWIL=6Cb=iBw*5v}=%;cb;>;+Vz4)vb6PQ zV>F_9dgV)_>Mte;yY`Gv&~xTQH+epqDN@>W)na3#$%c$(!d{Ds-MqGq14BkLDfH&S z&xSQ)*~lPqc1mf^gUZCK47}+~UTAud-%5k&HzK4nli@25iFXd=v@jv;kZbybD?;#cg>p$3voBJwES*cJK%5)quality > 0) { quality = context->quality; } - for (i = 0; i < sizeof(context->qtables)/sizeof(unsigned int); i++) { + for (i = 0; i < sizeof(context->qtables)/sizeof(unsigned int *); i++) { // TODO: Should add support for none baseline jpeg_add_quant_table(&context->cinfo, i, context->qtables[i], quality, TRUE); From f0591e2ac5060ac3e77e28265a73064528247c20 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 23 Sep 2014 09:52:34 -0700 Subject: [PATCH 07/17] s/lena/hopper/ --- Tests/test_mode_i16.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/test_mode_i16.py b/Tests/test_mode_i16.py index 9a0f6956c..20e39b235 100644 --- a/Tests/test_mode_i16.py +++ b/Tests/test_mode_i16.py @@ -5,7 +5,7 @@ from PIL import Image class TestModeI16(PillowTestCase): - original = lena().resize((32, 32)).convert('I') + original = hopper().resize((32, 32)).convert('I') def verify(self, im1): im2 = self.original.copy() From 20a90494d1979e5a3d48d95c642d73c13060fbe7 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 23 Sep 2014 10:11:34 -0700 Subject: [PATCH 08/17] Fix for docs. Can't wrap warning blocks --- PIL/PSDraw.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/PIL/PSDraw.py b/PIL/PSDraw.py index 208f7b6a6..5a24441a8 100644 --- a/PIL/PSDraw.py +++ b/PIL/PSDraw.py @@ -74,8 +74,7 @@ class PSDraw: def setink(self, ink): """ - .. warning:: This has been in the PIL API for ages but was never - implemented. + .. warning:: This has been in the PIL API for ages but was never implemented. """ print("*** NOT YET IMPLEMENTED ***") From d6a77f3632c1a4eab3d47af167d0169cabf33b2a Mon Sep 17 00:00:00 2001 From: Hugo Date: Wed, 24 Sep 2014 10:17:04 +0300 Subject: [PATCH 09/17] Create RELEASING.md Contents copied from https://github.com/python-pillow/Pillow/wiki/Release-Checklist and some links added. [CI skip] --- RELEASING.md | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 RELEASING.md diff --git a/RELEASING.md b/RELEASING.md new file mode 100644 index 000000000..5a389b1ef --- /dev/null +++ b/RELEASING.md @@ -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. From d6c16aa01536165bf82747819ebcecb1bc248d45 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Wed, 24 Sep 2014 15:37:28 -0700 Subject: [PATCH 10/17] Tests for jpeg memory leaks --- Tests/check_jpeg_leaks.py | 212 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 Tests/check_jpeg_leaks.py diff --git a/Tests/check_jpeg_leaks.py b/Tests/check_jpeg_leaks.py new file mode 100644 index 000000000..adf7652cf --- /dev/null +++ b/Tests/check_jpeg_leaks.py @@ -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() From 306ad7432413c1d102e76b32a8780994cecc3a7d Mon Sep 17 00:00:00 2001 From: wiredfool Date: Wed, 24 Sep 2014 14:15:17 -0700 Subject: [PATCH 11/17] qtables error handling tests --- Tests/test_file_jpeg.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Tests/test_file_jpeg.py b/Tests/test_file_jpeg.py index e46b656bb..a11a2200e 100644 --- a/Tests/test_file_jpeg.py +++ b/Tests/test_file_jpeg.py @@ -295,6 +295,21 @@ class TestFileJpeg(PillowTestCase): 1: standard_chrominance_qtable}), 30) + # not a sequence + self.assertRaises(Exception, lambda: self.roundtrip(im, qtables='a')) + # sequence wrong length + self.assertRaises(Exception, lambda: self.roundtrip(im, qtables=[])) + # sequence wrong length + self.assertRaises(Exception, lambda: self.roundtrip(im, qtables=[1,2,3,4,5])) + + # qtable entry not a sequence + self.assertRaises(Exception, lambda: self.roundtrip(im, qtables=[1])) + # qtable entry has wrong number of items + self.assertRaises(Exception, lambda: self.roundtrip(im, qtables=[[1,2,3,4]])) + + + + @unittest.skipUnless(djpeg_available(), "djpeg not available") def test_load_djpeg(self): img = Image.open(TEST_FILE) From d64b2376bc8cd38c3ba24f13de943d9af916c03c Mon Sep 17 00:00:00 2001 From: wiredfool Date: Mon, 22 Sep 2014 22:30:00 -0700 Subject: [PATCH 12/17] Memory Leak: Freeing malloc'd memory in Jpeg Encode --- encode.c | 39 +++++++++++++++++---------------------- libImaging/Jpeg.h | 4 +++- libImaging/JpegEncode.c | 15 +++++++++++++-- 3 files changed, 33 insertions(+), 25 deletions(-) diff --git a/encode.c b/encode.c index c26b7dfb7..d7a074720 100644 --- a/encode.c +++ b/encode.c @@ -535,12 +535,12 @@ PyImaging_ZipEncoderNew(PyObject* self, PyObject* args) #include "Jpeg.h" -static unsigned int** get_qtables_arrays(PyObject* qtables, int* qtablesLen) { +static unsigned int* get_qtables_arrays(PyObject* qtables, int* qtablesLen) { PyObject* tables; PyObject* table; PyObject* table_data; int i, j, num_tables; - unsigned int **qarrays; + unsigned int *qarrays; if ((qtables == NULL) || (qtables == Py_None)) { return NULL; @@ -554,10 +554,12 @@ static unsigned int** get_qtables_arrays(PyObject* qtables, int* qtablesLen) { tables = PySequence_Fast(qtables, "expected a sequence"); num_tables = PySequence_Size(qtables); if (num_tables < 1 || num_tables > NUM_QUANT_TBLS) { - PyErr_SetString(PyExc_ValueError, "Not a valid numbers of quantization tables. Should be between 1 and 4."); + PyErr_SetString(PyExc_ValueError, + "Not a valid number of quantization tables. Should be between 1 and 4."); + Py_DECREF(tables); return NULL; } - qarrays = (unsigned int**) PyMem_Malloc(num_tables * sizeof(unsigned int*)); + qarrays = (unsigned int*) malloc(num_tables * DCTSIZE2 * sizeof(unsigned int)); if (!qarrays) { Py_DECREF(tables); PyErr_NoMemory(); @@ -566,39 +568,32 @@ static unsigned int** get_qtables_arrays(PyObject* qtables, int* qtablesLen) { for (i = 0; i < num_tables; i++) { table = PySequence_Fast_GET_ITEM(tables, i); if (!PySequence_Check(table)) { - Py_DECREF(tables); PyErr_SetString(PyExc_ValueError, "Invalid quantization tables"); - return NULL; + goto JPEG_QTABLES_ERR; } if (PySequence_Size(table) != DCTSIZE2) { - Py_DECREF(tables); - PyErr_SetString(PyExc_ValueError, "Invalid quantization tables"); - return NULL; + PyErr_SetString(PyExc_ValueError, "Invalid quantization table size"); + goto JPEG_QTABLES_ERR; } table_data = PySequence_Fast(table, "expected a sequence"); - qarrays[i] = (unsigned int*) PyMem_Malloc(DCTSIZE2 * sizeof(unsigned int)); - if (!qarrays[i]) { - Py_DECREF(tables); - PyErr_NoMemory(); - return NULL; - } for (j = 0; j < DCTSIZE2; j++) { - qarrays[i][j] = PyInt_AS_LONG(PySequence_Fast_GET_ITEM(table_data, j)); + qarrays[i * DCTSIZE2 + j] = PyInt_AS_LONG(PySequence_Fast_GET_ITEM(table_data, j)); } } - Py_DECREF(tables); *qtablesLen = num_tables; +JPEG_QTABLES_ERR: + Py_DECREF(tables); // Run on both error and not error if (PyErr_Occurred()) { - PyMem_Free(qarrays); + free(qarrays); qarrays = NULL; + return NULL; } return qarrays; } - PyObject* PyImaging_JpegEncoderNew(PyObject* self, PyObject* args) { @@ -614,7 +609,7 @@ PyImaging_JpegEncoderNew(PyObject* self, PyObject* args) int xdpi = 0, ydpi = 0; int subsampling = -1; /* -1=default, 0=none, 1=medium, 2=high */ PyObject* qtables=NULL; - unsigned int **qarrays = NULL; + unsigned int *qarrays = NULL; int qtablesLen = 0; char* extra = NULL; int extra_size; @@ -638,7 +633,7 @@ PyImaging_JpegEncoderNew(PyObject* self, PyObject* args) qarrays = get_qtables_arrays(qtables, &qtablesLen); if (extra && extra_size > 0) { - char* p = malloc(extra_size); + char* p = malloc(extra_size); // Freed in JpegEncode, Case 5 if (!p) return PyErr_NoMemory(); memcpy(p, extra, extra_size); @@ -647,7 +642,7 @@ PyImaging_JpegEncoderNew(PyObject* self, PyObject* args) extra = NULL; if (rawExif && rawExifLen > 0) { - char* pp = malloc(rawExifLen); + char* pp = malloc(rawExifLen); // Freed in JpegEncode, Case 5 if (!pp) return PyErr_NoMemory(); memcpy(pp, rawExif, rawExifLen); diff --git a/libImaging/Jpeg.h b/libImaging/Jpeg.h index acd2da676..9536cad79 100644 --- a/libImaging/Jpeg.h +++ b/libImaging/Jpeg.h @@ -89,7 +89,9 @@ typedef struct { int subsampling; /* Custom quantization tables () */ - unsigned int **qtables; + unsigned int *qtables; + + /* in factors of DCTSIZE2 */ int qtablesLen; /* Extra data (to be injected after header) */ diff --git a/libImaging/JpegEncode.c b/libImaging/JpegEncode.c index 54876589d..3fe5d753f 100644 --- a/libImaging/JpegEncode.c +++ b/libImaging/JpegEncode.c @@ -153,7 +153,7 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) } for (i = 0; i < context->qtablesLen; i++) { // TODO: Should add support for none baseline - jpeg_add_quant_table(&context->cinfo, i, context->qtables[i], + jpeg_add_quant_table(&context->cinfo, i, &context->qtables[i * DCTSIZE2], quality, TRUE); } } else if (context->quality > 0) { @@ -289,8 +289,19 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) jpeg_finish_compress(&context->cinfo); /* Clean up */ - if (context->extra) + if (context->extra) { free(context->extra); + context->extra = NULL; + } + if (context->rawExif) { + free(context->rawExif); + context->rawExif = NULL; + } + if (context->qtables) { + free(context->qtables); + context->qtables = NULL; + } + jpeg_destroy_compress(&context->cinfo); /* if (jerr.pub.num_warnings) return BROKEN; */ state->errcode = IMAGING_CODEC_END; From c154fd05fd4072f4299f6e8bf28a444b259919bb Mon Sep 17 00:00:00 2001 From: wiredfool Date: Wed, 24 Sep 2014 15:27:43 -0700 Subject: [PATCH 13/17] Memory Leak, missing Py_DECREF --- encode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/encode.c b/encode.c index d7a074720..fef102176 100644 --- a/encode.c +++ b/encode.c @@ -579,6 +579,7 @@ static unsigned int* get_qtables_arrays(PyObject* qtables, int* qtablesLen) { for (j = 0; j < DCTSIZE2; j++) { qarrays[i * DCTSIZE2 + j] = PyInt_AS_LONG(PySequence_Fast_GET_ITEM(table_data, j)); } + Py_DECREF(table_data); } *qtablesLen = num_tables; From cb166786df914b7819455af0c78cf54953338227 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Wed, 24 Sep 2014 16:30:39 -0700 Subject: [PATCH 14/17] More JPEG documentation, fixes #890 --- docs/handbook/image-file-formats.rst | 47 ++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/docs/handbook/image-file-formats.rst b/docs/handbook/image-file-formats.rst index cd187a4a2..31adcb142 100644 --- a/docs/handbook/image-file-formats.rst +++ b/docs/handbook/image-file-formats.rst @@ -117,20 +117,48 @@ converting ``RGB`` images to ``L``, and resize images to 1/2, 1/4 or 1/8 of their original size while loading them. The :py:meth:`~PIL.Image.Image.draft` method also configures the JPEG decoder to trade some quality for speed. -The :py:meth:`~PIL.Image.Image.open` method sets the following -:py:attr:`~PIL.Image.Image.info` properties: +The :py:meth:`~PIL.Image.Image.open` method may set the following +:py:attr:`~PIL.Image.Image.info` properties if available: **jfif** JFIF application marker found. If the file is not a JFIF file, this key is not present. +**jfif_version** + A tuple representing the jfif version, (major version, minor version). + +**jfif_density** + A tuple representing the pixel density of the image, in units specified + by jfif_unit. + +**jfif_unit** + Units for the jfif_density: + + * 0 - No Units + * 1 - Pixels per Inch + * 2 - Pixels per Centimeter + +**dpi** + A tuple representing the reported pixel density in pixels per inch, if + the file is a jfif file and the units are in inches. + **adobe** Adobe application marker found. If the file is not an Adobe JPEG file, this key is not present. +**adobe_transform** + Vendor Specific Tag. + **progression** Indicates that this is a progressive JPEG file. +**icc-profile** + The ICC color profile for the image. + +**exif** + Raw EXIF data from the image. + + The :py:meth:`~PIL.Image.Image.save` method supports the following options: **quality** @@ -147,6 +175,19 @@ The :py:meth:`~PIL.Image.Image.save` method supports the following options: If present, indicates that this image should be stored as a progressive JPEG file. +**dpi** + A tuple of integers representing the pixel density, ``(x,y)``. + +**icc-profile** + If present, the image is stored with the provided ICC profile. If + this parameter is not provided, the image will be saved with no + profile attached. To preserve the existing profile:: + + im.save(filename, 'jpeg', icc_profile=im.info.get('icc_profile')) + +**exif** + If present, the image will be stored with the provided raw EXIF data. + **subsampling** If present, sets the subsampling for the encoder. @@ -670,7 +711,7 @@ files, using either JPEG or HEX encoding depending on the image mode (and whether JPEG support is available or not). PIXAR (read only) -^^^^ +^^^^^^^^^^^^^^^^^ PIL provides limited support for PIXAR raster files. The library can identify and read “dumped” RGB files. From c325a26dd8a02639a912b5217ca810b59e81d436 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Wed, 24 Sep 2014 21:01:17 -0700 Subject: [PATCH 15/17] Remove ICC profiles with unclear licence and not our copyright --- Tests/icc/CMY.icm | Bin 101936 -> 0 bytes Tests/icc/YCC709.icm | Bin 101940 -> 0 bytes Tests/icc/sRGB.icm | Bin 3144 -> 0 bytes 3 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Tests/icc/CMY.icm delete mode 100644 Tests/icc/YCC709.icm delete mode 100644 Tests/icc/sRGB.icm diff --git a/Tests/icc/CMY.icm b/Tests/icc/CMY.icm deleted file mode 100644 index acc71ddd9d09f41be315ea2fa7d845e5271a6f4e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 101936 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 diff --git a/Tests/icc/YCC709.icm b/Tests/icc/YCC709.icm deleted file mode 100644 index d9f5a5a5df83ba666057c836aaad7221972e8225..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 101940 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

    Q~&++qG<@nP9v3{YJ?sW%q;NPM zPKMLr+)4gPF)-yJCp9PaCxIFLq~oOLWZ-1vBzclP$)3!g;+ztkf=A;)56n|)AG}*)4J2xY2vi)wCl9*bm(;KG;*nS;JY=S?gKnS?}54+34BCS>QuC$2})JCpjlSr#h!Qhn*wN+0MDn z`ObyT#m-UZm~+|lyz`>-U^nl)`aCeToHw7hpLd`4pAVmppHH4opU*}4QE^ljMWULh zK5C3wqK>F18i+=sWR#Aw(fkF@1;GXA0(?PvL3_b)!35mg&I{fP!3)s~i3_O!R;s=wj?5b&UcxV#FWE1-FZnNp zFU2nloVuL3!o4EABDn&ZTUT^fuq(tB+ZERp-<8mn*cIvub0vF~cU5#% zdR1{%eHFcmUo~H~Uv*#gUkzW4Urk<3U(Ln&anR<7BXLb!A2-G=aYx(}55yyJGET?Y zc>Wsan&29A4ZfzlroCpkX1Zp*=Dg;;7Q7a{mbjL>mbngklh-BJ<=0i$b=R@$#C6+s zuu^h8bUk*Ry3SnB-r(I3-H_f;+)&>@Z{Rn~H|#guH~crkH{v&vH_|t9B%c(MG7=#* zq@FaA7Scg_$N(83Ns=a6GJlhE6Bv1K!Z(#SwKoknO*gGKfzkP9@MiR8;%4e*<`(ys z@RsD39GJ&-x3F8pE!!>EE#Ixst=KK<7IQ0mn|E7uTY6h@TYVe7jo&ukw%>N&_TLWQ zj^75GMYnSaenOm(C6I(Bp-&hSmV_hWNdyv+1eu@{Y$AV$b4PFox&z-)-qGGM+%es; z-f`aX-U;4`-bvg^-O1eL-WA@J+?C%|-PPU2?hBW0l+l!pRc9*U%Bily@R zIrjzkq5JTC<$dja!+q0z>wV{a@BQHY=>5d~6mSP{9|#|Sjh+Xp2f7E?1LA@0f$M?q zLFhs30rh}+kbTH|D0(P;sCcM;h(5$0njhL9x*z%s8Q9nVS;7`m?>`&ZJ{7=G9 z;!l!K(ob?UpBB?H8lg3`o;K1J+Ch8h03D%8nx9i`=5uO$Db#kr=RCi{FFE)OCc#uN}n>OEGb9IlM19FDKbT;*i`-n z=Y`+}^a6gNe4%||cwu^Bec^oJeGz;SeUW&PdXag_eJOk?c`1LXdZ~Mfy(C`RUbRq_>}Vi`UoW@HS)Xc#?X zWGsw>@h|}I+Sm?Z-j3o zZ{%-OZ**_4H^dv;8(`Ua6M7SSL%m_%WZ&}Mirz}!D&DH!qHpoH=C}5@?zjH8;kWU( z$+zjZximj5PRr6rT9ekNjcH5Tk@lnm=}4MP(`h!Hf5&+zcn7_M-znc|-x=PS-dW!{ z-+A8!-$mag-lg7U-gDmz-%H-h->cs1-ed2H_qO-0_rCX`_p$fXd**%i1Mh?AgY<*q zgZcyd0smnBVE+I-(jUSf;vbS9(jRgxpB1w*7GX84o;9)-*1>w%02^URmS$Nt|B>@i z@Dch5e^h?del&bEeYAdbe)N6}evE!hd`x}JeByo*ev*8We^PzYeZoEwpKPC8pM0M} zpJJb=Pt2$6XWnPgXX$6fXZ2_FGyd89+5Xx6+5b8GIsQ5MIsG}8;b+7dSq8~yGWv`$ zW63x&o=hMU$&eX3!)EedI9~)`pfB(jlf!2@0Z}0=$FKo)R)Xx?pNVg z$yfPT)mPnD>?`rr_SN;(_cio2_Lcg|e9eC2eG`3?ep7r?e?!0F-^}0a-`wB)-@@PG z-;&?b-*Q=gR-Bb(k*p@G&l`&fL(NF15 z#ZUE5^e6t){L}u^{nP(5{4@SD`7`}9m*eNeIav$6UF=xp+a-Liu7s-)1I>+Yn zzc{}Hzo1|6FXb=oFT*d>FY7PoFYmA5ujsGDuhg&1Z|-m5Z^>`@Z`E(zZ|pbm+xFY_ z+xI*4JNBFU&HT>(;r$W)k^WKqQU5{z;D5}2?0?*U{C~oK;(wBV(tmP!eqNlH<&nH5 zug@Fvmb@eH$p`Y0JejBSY(8Je{|otlA^$Jr|AqX&kpCC*|3dy>$o~uZe{C|P}FYx~b z{=dNg7x@1I|6kz$3;ch9|1a?W1^&Ol{}=fG|9}3Uz+nY&0C4{8pB&CeY;y76&%qar z7L6#H1hs-&LsLqio`w-namo0SNs}iUiZSqX!c=V1WV~boG;vbND11By{r8)|kN^0S z*Fh5?94dlJppnr3{NX<}hT?w3lkkaC{_l1F`}%)?C;tTBynmeK@EXD3aVzJa6Q%4} ktODoX#{B)N2AqG_9c1%=p@X2mf8}t#-R1oKE>1%BUj%R}4GQ2c@f!gN>x zfHa|46z=Q6ToMz@#P0Oj{6)6@8zOaL$xnP1H3 zCZTMJGDQ>_?uqgO00@-CIlOWXi}^Wdo&b2JXXJ_miAiFn5!aY$<><&}`th?<`C>6E zl*3KohJ5ztS`M50QMwWn;o;hl~n+=Z3aN);jB;ZAOP|O0JPqm^B#t5UXsM(3?~bV z?CflF0iSCwE9f`-pMr17zlJ&Ynal3`Ry(E_KY=4j6*FZ;<)){mOGM1f3=WsiWc~LL z|Kq?pY0b&QES#Uf7x9JYRZ-}a351DgyM;V~SdcDc3WR^v;eQx5CkGjRoof_mbzcB| zg*i~TNe9SpJpe-^10-%gdIEjxTM#h{$iBR2t&y*Dk1~4x=lUNDT#9btOhF=3=JpJa zWO5~-11?AcX+Q+BK|a_3 z3PCa00d|9GZ~)YSde8(;f;MmlTm)CZ4R8w#fJZ5%ns2D1Ps-Z(rJ@g}V8oCHwgZiKc&>%Dh{Q-T1 z5tstgVGY;-wt(5NI~)i{!pq=9com!n7r@)$O1Kt24!6P=;T!M(EQMdflL$b_2m{eZ zSO^>OL_&~QBmog2Ymp+P0;xrskPf69xs6DXapVIAhoNDZ7#7AEHf9hrf%$@^V%4#xSSPGMb_q5Sn~g2RR$z}{Td>%$GT@D&7?Df)BxS@M3%+z6yUFe;(hDAI85YkO^7@ zYl06UmLMc-BvcR@2gb~6tQGuvWbRvcjdBj{|DY1^&LA*&ECQg$SNrogBQY0yv zw1HGfY9d`GJtn;&lgT<{M{*chKweL-B%dH(B@dE6P?RVp6i-SVMMBw5IZC-ec|dtX zrBV&3Zq!(+n7W->PrXEaN_{U!lQWm|m*dH;ldF+ymFt&#B~O&smv@(6E}th~A%9B# zru?`9QNcjLQ-PzfR-s1Ww8A}wNky8Xm12lunqrA!gW@&CQ6;>Rfs(fpPpLrZu+k-^ zAsRx{rFqi0v`w@++GW}>9Y;5$`_q%@#q=NOz4QrXC1qRXDCHdG8s)RfQU<~>VE8jq z8KsPqjJu4F^EBqU&*RVAHm_-3|GX)c`6_NIe3c@VW|aYzkE%>nZ`BmlovLlBPt-7K zCTd}7*=qaME~|~tr_Xnu&z)a1|K$9K>aeXRCp8onAC8dVyXG{!X< znr@oOn&q13G{>}PS_`!VTIE{jwO%llneNO~W+k(WIiant?WZl#KBV2NJ*{J?vsh=N zPP5JvU6L+aH$k^tw^MgQPfIUYFJG@w@1Z_XpRJ#yzem4Yf6BnnAlhJyL7Ty-p^Blu zVV+^5;bSAJk*m=vqgtao#yDfPafahC5 z+Qgb`U1NR6hHB$uv(Bd7=C!S z*mQO%yM%q!5$ovTxX$s6;|C{uC$ZB>r{A4f&MD3f&Z7$q7w{L-x-1*Nx|P#BIdg*ge_(xce&)OAnDpi^r6wljj=G3totquUC;* zueXx-V()72r#?D9i9U@!6TWu7t9>u{Vf_OAcKY4(*YM~1*ZWTdI0UQ-=nA9+Mg&#| zJ_|Al5(RYx!@&W;yMiAt(qAN8)D{9l{6ltyJP9=nT^0Is7%nU{tS0PvxK((5cy|OX zVnswl#Jfn3$kND1i;Wgb7I#L;N5w_eM@>b0MVCcOmsl)Wv*bpMT8tp3Jr*Au6?-Ih za;f*y-Ajk#?BWXJ?k+Q2mb2{Ia<%2D%g?TmU%^>%Djpjj9p4cDi4(%93l#rC8 zDKn|jsm*DGwD`2sLM35}uq$0NJtw^{!!)BXL%Pao)$UajqCnA+Oek|%X1kb<{!H~q zj3k>SgINo+YO>yEM`fSNQOptM^yHf4Zp$6X^U3>uHD)z;b!WbI{)YU)HSTK;t%cUE zT-&)$cU{4{;q|`jk8L1rNZIhqM$3(58{ck<-qcZ`QLw&XXtVF;#zMJ5QQ^HU&RY&_ z#cUO9?cHXxt!mqsB3{w;V$0%+;!h>qlI!1DeOLM2%=U!sy`}c0`*+}W2zT7w>ALe+ znPOR9+0d@wU9IKJ@}ly$yI1VKR$*IlU=L}JWRJ8msIt9EuWCotr|P8Yff|pR=Dq5B zx9y$U$J^Jx-)(=>0gVI22Rfw1Ho}dP#Y+O@16`i z*?Ee6s_7^FpZ2!UT8dhs*4);Kwxl*`drW)Z>44Ln9nKvsKb!x2^o;hInzPDhOV5$c z6`Y$npLc%pLdJ#hi-{M9I#+Z)y0qldovyI1-phfPuU_%Fa;e+B`}|dxt7on`T|0f9 zeZB35{f*WhyPlR`?0#wKweM}c>2S0CmgB9Cz6E{f`d#}k-uAkE<&OWI8v~05`tB~i zd;ebCJ?VYk{m}=h4_-gadN}=P{bTIoq9+PZDxRu8t^L*b*Ji1`^z5M5V9&FNXOD)s zLoff8`L9pI1<$F^D@L?N>PM|d&y4wu-FmU~#qi6Fm($~gzbXE<_m$DBpMH1yy=P*{ z#PDm;>zO}F-l)Dg`quVs=Va*Q(|2j_rl*SDtG++>f&HQTWAw+7>FiJVPnDmIKX-fy L{PK7vZD!`*_k{EN From 476c255cee3a1937445344b1c6ebba2a2a865c2d Mon Sep 17 00:00:00 2001 From: wiredfool Date: Wed, 24 Sep 2014 21:04:44 -0700 Subject: [PATCH 16/17] Licensed, freely available icc profiles --- Tests/icc/LICENSE.txt | 25 +++++++++++++++++++ Tests/icc/sRGB_IEC61966-2-1_black_scaled.icc | Bin 0 -> 3048 bytes Tests/icc/sRGB_v4_ICC_preference.icc | Bin 0 -> 60960 bytes 3 files changed, 25 insertions(+) create mode 100644 Tests/icc/LICENSE.txt create mode 100644 Tests/icc/sRGB_IEC61966-2-1_black_scaled.icc create mode 100644 Tests/icc/sRGB_v4_ICC_preference.icc diff --git a/Tests/icc/LICENSE.txt b/Tests/icc/LICENSE.txt new file mode 100644 index 000000000..e6ec6a69f --- /dev/null +++ b/Tests/icc/LICENSE.txt @@ -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. + diff --git a/Tests/icc/sRGB_IEC61966-2-1_black_scaled.icc b/Tests/icc/sRGB_IEC61966-2-1_black_scaled.icc new file mode 100644 index 0000000000000000000000000000000000000000..71e33830223c4c05c61002462e13df02bb30ae02 GIT binary patch literal 3048 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�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 Hv9$jMAe=SQ literal 0 HcmV?d00001 From af138af779e43a71c445d904b84bffd0e8375452 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Wed, 24 Sep 2014 21:25:42 -0700 Subject: [PATCH 17/17] Use lcms profile where possible, otherwise skip test if sRGB profile is not available --- Tests/test_imagecms.py | 51 ++++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/Tests/test_imagecms.py b/Tests/test_imagecms.py index e05bdcb20..f35b6bd2f 100644 --- a/Tests/test_imagecms.py +++ b/Tests/test_imagecms.py @@ -3,7 +3,8 @@ from helper import unittest, PillowTestCase, hopper, lena from PIL import Image from io import BytesIO - +import os + try: from PIL import ImageCms from PIL.ImageCms import ImageCmsProfile @@ -13,8 +14,8 @@ except ImportError as v: pass -SRGB = "Tests/icc/sRGB.icm" - +SRGB = "Tests/icc/sRGB_IEC61966-2-1_black_scaled.icc" +HAVE_PROFILE = os.path.exists(SRGB) class TestImageCms(PillowTestCase): @@ -26,8 +27,12 @@ class TestImageCms(PillowTestCase): except ImportError as v: self.skipTest(v) - def test_sanity(self): + def skip_missing(self): + if not HAVE_PROFILE: + self.skipTest("SRGB profile not available") + def test_sanity(self): + # basic smoke test. # this mostly follows the cms_test outline. @@ -38,6 +43,7 @@ class TestImageCms(PillowTestCase): # internal version number self.assertRegexpMatches(ImageCms.core.littlecms_version, "\d+\.\d+$") + self.skip_missing() i = ImageCms.profileToProfile(hopper(), SRGB, SRGB) self.assert_image(i, "RGB", (128, 128)) @@ -70,38 +76,45 @@ class TestImageCms(PillowTestCase): hopper().point(t) def test_name(self): + self.skip_missing() # get profile information for file self.assertEqual( ImageCms.getProfileName(SRGB).strip(), - 'IEC 61966-2.1 Default RGB colour space - sRGB') + 'IEC 61966-2-1 Default RGB Colour Space - sRGB') def test_info(self): + self.skip_missing() self.assertEqual( ImageCms.getProfileInfo(SRGB).splitlines(), [ - 'sRGB IEC61966-2.1', '', - 'Copyright (c) 1998 Hewlett-Packard Company', '']) + 'sRGB IEC61966-2-1 black scaled', '', + 'Copyright International Color Consortium, 2009', '']) def test_copyright(self): + self.skip_missing() self.assertEqual( ImageCms.getProfileCopyright(SRGB).strip(), - 'Copyright (c) 1998 Hewlett-Packard Company') + 'Copyright International Color Consortium, 2009') def test_manufacturer(self): + self.skip_missing() self.assertEqual( ImageCms.getProfileManufacturer(SRGB).strip(), - 'IEC http://www.iec.ch') + '') def test_model(self): + self.skip_missing() self.assertEqual( ImageCms.getProfileModel(SRGB).strip(), - 'IEC 61966-2.1 Default RGB colour space - sRGB') + 'IEC 61966-2-1 Default RGB Colour Space - sRGB') def test_description(self): + self.skip_missing() self.assertEqual( ImageCms.getProfileDescription(SRGB).strip(), - 'sRGB IEC61966-2.1') + 'sRGB IEC61966-2-1 black scaled') def test_intent(self): + self.skip_missing() self.assertEqual(ImageCms.getDefaultIntent(SRGB), 0) self.assertEqual(ImageCms.isIntentSupported( SRGB, ImageCms.INTENT_ABSOLUTE_COLORIMETRIC, @@ -139,6 +152,7 @@ class TestImageCms(PillowTestCase): self.assertRaises( ImageCms.PyCMSError, lambda: ImageCms.getProfileName(None)) + self.skip_missing() self.assertRaises( ImageCms.PyCMSError, lambda: ImageCms.isIntentSupported(SRGB, None, None)) @@ -153,9 +167,9 @@ class TestImageCms(PillowTestCase): def test_simple_lab(self): i = Image.new('RGB', (10, 10), (128, 128, 128)) - + psRGB = ImageCms.createProfile("sRGB") pLab = ImageCms.createProfile("LAB") - t = ImageCms.buildTransform(SRGB, pLab, "RGB", "LAB") + t = ImageCms.buildTransform(psRGB, pLab, "RGB", "LAB") i_lab = ImageCms.applyTransform(i, t) @@ -174,8 +188,9 @@ class TestImageCms(PillowTestCase): self.assertEqual(list(b), [128] * 100) def test_lab_color(self): + psRGB = ImageCms.createProfile("sRGB") pLab = ImageCms.createProfile("LAB") - t = ImageCms.buildTransform(SRGB, pLab, "RGB", "LAB") + t = ImageCms.buildTransform(psRGB, pLab, "RGB", "LAB") # Need to add a type mapping for some PIL type to TYPE_Lab_8 in # findLCMSType, and have that mapping work back to a PIL mode # (likely RGB). @@ -189,8 +204,9 @@ class TestImageCms(PillowTestCase): self.assert_image_similar(i, target, 30) def test_lab_srgb(self): + psRGB = ImageCms.createProfile("sRGB") pLab = ImageCms.createProfile("LAB") - t = ImageCms.buildTransform(pLab, SRGB, "LAB", "RGB") + t = ImageCms.buildTransform(pLab, psRGB, "LAB", "RGB") img = Image.open('Tests/images/lena.Lab.tif') @@ -206,10 +222,11 @@ class TestImageCms(PillowTestCase): def test_lab_roundtrip(self): # check to see if we're at least internally consistent. + psRGB = ImageCms.createProfile("sRGB") pLab = ImageCms.createProfile("LAB") - t = ImageCms.buildTransform(SRGB, pLab, "RGB", "LAB") + t = ImageCms.buildTransform(psRGB, pLab, "RGB", "LAB") - t2 = ImageCms.buildTransform(pLab, SRGB, "LAB", "RGB") + t2 = ImageCms.buildTransform(pLab, psRGB, "LAB", "RGB") i = ImageCms.applyTransform(hopper(), t)