From 8de95676e0fd89f2326b3953488ab66ff29cd2d0 Mon Sep 17 00:00:00 2001 From: hugovk Date: Tue, 26 Aug 2014 16:47:10 +0300 Subject: [PATCH 1/8] 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 2/8] 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 3/8] 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 4/8] 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 5/8] 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 6/8] 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 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 > 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 7/8] 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 8/8] 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 ***")