This commit is contained in:
hugovk 2014-08-26 16:47:10 +03:00
parent 5d9107ee4c
commit 8de95676e0
56 changed files with 647 additions and 433 deletions

View File

@ -40,8 +40,8 @@ bdf_spacing = {
"C": "Cell" "C": "Cell"
} }
def bdf_char(f):
def bdf_char(f):
# skip to STARTCHAR # skip to STARTCHAR
while True: while True:
s = f.readline() s = f.readline()
@ -82,6 +82,7 @@ def bdf_char(f):
return id, int(props["ENCODING"]), bbox, im return id, int(props["ENCODING"]), bbox, im
## ##
# Font file plugin for the X11 BDF format. # Font file plugin for the X11 BDF format.
@ -113,10 +114,10 @@ class BdfFontFile(FontFile.FontFile):
font[4] = bdf_slant[font[4].upper()] font[4] = bdf_slant[font[4].upper()]
font[11] = bdf_spacing[font[11].upper()] font[11] = bdf_spacing[font[11].upper()]
ascent = int(props["FONT_ASCENT"]) # ascent = int(props["FONT_ASCENT"])
descent = int(props["FONT_DESCENT"]) # descent = int(props["FONT_DESCENT"])
fontname = ";".join(font[1:]) # fontname = ";".join(font[1:])
# print "#", fontname # print "#", fontname
# for i in comments: # for i in comments:

View File

@ -51,9 +51,11 @@ BIT2MODE = {
32: ("RGB", "BGRX") 32: ("RGB", "BGRX")
} }
def _accept(prefix): def _accept(prefix):
return prefix[:2] == b"BM" return prefix[:2] == b"BM"
## ##
# Image plugin for the Windows BMP format. # Image plugin for the Windows BMP format.
@ -63,7 +65,6 @@ class BmpImageFile(ImageFile.ImageFile):
format_description = "Windows Bitmap" format_description = "Windows Bitmap"
def _bitmap(self, header=0, offset=0): def _bitmap(self, header=0, offset=0):
if header: if header:
self.fp.seek(header) self.fp.seek(header)
@ -98,7 +99,8 @@ class BmpImageFile(ImageFile.ImageFile):
self.size = self.size[0], 2**32 - self.size[1] self.size = self.size[0], 2**32 - self.size[1]
direction = 0 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: else:
raise IOError("Unsupported BMP header type (%d)" % len(s)) raise IOError("Unsupported BMP header type (%d)" % len(s))
@ -163,7 +165,8 @@ class BmpImageFile(ImageFile.ImageFile):
self.tile = [("raw", self.tile = [("raw",
(0, 0) + self.size, (0, 0) + self.size,
offset, offset,
(rawmode, ((self.size[0]*bits+31)>>3)&(~3), direction))] (rawmode, ((self.size[0]*bits+31) >> 3) & (~3),
direction))]
self.info["compression"] = compression self.info["compression"] = compression
@ -197,8 +200,8 @@ SAVE = {
"RGB": ("BGR", 24, 0), "RGB": ("BGR", 24, 0),
} }
def _save(im, fp, filename, check=0):
def _save(im, fp, filename, check=0):
try: try:
rawmode, bits, colors = SAVE[im.mode] rawmode, bits, colors = SAVE[im.mode]
except KeyError: except KeyError:
@ -248,7 +251,8 @@ def _save(im, fp, filename, check=0):
elif im.mode == "P": elif im.mode == "P":
fp.write(im.im.getpalette("RGB", "BGRX")) 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))])
# #
# -------------------------------------------------------------------- # --------------------------------------------------------------------

View File

@ -13,6 +13,7 @@ from PIL import Image, ImageFile
_handler = None _handler = None
## ##
# Install application-specific BUFR image handler. # Install application-specific BUFR image handler.
# #
@ -22,12 +23,14 @@ def register_handler(handler):
global _handler global _handler
_handler = handler _handler = handler
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# Image adapter # Image adapter
def _accept(prefix): def _accept(prefix):
return prefix[:4] == b"BUFR" or prefix[:4] == b"ZCZC" return prefix[:4] == b"BUFR" or prefix[:4] == b"ZCZC"
class BufrStubImageFile(ImageFile.StubImageFile): class BufrStubImageFile(ImageFile.StubImageFile):
format = "BUFR" format = "BUFR"
@ -53,6 +56,7 @@ class BufrStubImageFile(ImageFile.StubImageFile):
def _load(self): def _load(self):
return _handler return _handler
def _save(im, fp, filename): def _save(im, fp, filename):
if _handler is None or not hasattr("_handler", "save"): if _handler is None or not hasattr("_handler", "save"):
raise IOError("BUFR save handler not installed") raise IOError("BUFR save handler not installed")

View File

@ -18,6 +18,7 @@
# A file object that provides read access to a part of an existing # A file object that provides read access to a part of an existing
# file (for example a TAR file). # file (for example a TAR file).
class ContainerIO: class ContainerIO:
## ##

View File

@ -11,7 +11,8 @@
# 1996-08-23 fl Handle files from Macintosh (0.3) # 1996-08-23 fl Handle files from Macintosh (0.3)
# 2001-02-17 fl Use 're' instead of 'regex' (Python 2.1) (0.4) # 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) # 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) 1997-2003 by Secret Labs AB.
# Copyright (c) 1995-2003 by Fredrik Lundh # Copyright (c) 1995-2003 by Fredrik Lundh
@ -51,6 +52,7 @@ if sys.platform.startswith('win'):
else: else:
gs_windows_binary = False gs_windows_binary = False
def has_ghostscript(): def has_ghostscript():
if gs_windows_binary: if gs_windows_binary:
return True return True
@ -75,14 +77,17 @@ def Ghostscript(tile, size, fp, scale=1):
# Hack to support hi-res rendering # Hack to support hi-res rendering
scale = int(scale) or 1 scale = int(scale) or 1
orig_size = size # orig_size = size
orig_bbox = bbox # orig_bbox = bbox
size = (size[0] * scale, size[1] * scale) size = (size[0] * scale, size[1] * scale)
# resolution is dependend on bbox and size # 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])) ) 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) # print("Ghostscript", scale, size, orig_size, bbox, orig_bbox, res)
import tempfile, os, subprocess import os
import subprocess
import tempfile
out_fd, outfile = tempfile.mkstemp() out_fd, outfile = tempfile.mkstemp()
os.close(out_fd) os.close(out_fd)
@ -127,7 +132,8 @@ def Ghostscript(tile, size, fp, scale=1):
# push data through ghostscript # push data through ghostscript
try: try:
gs = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE) gs = subprocess.Popen(command, stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
gs.stdin.close() gs.stdin.close()
status = gs.wait() status = gs.wait()
if status: if status:
@ -137,7 +143,8 @@ def Ghostscript(tile, size, fp, scale=1):
try: try:
os.unlink(outfile) os.unlink(outfile)
os.unlink(infile) os.unlink(infile)
except: pass except:
pass
return im return im
@ -147,22 +154,28 @@ class PSFile:
def __init__(self, fp): def __init__(self, fp):
self.fp = fp self.fp = fp
self.char = None self.char = None
def __getattr__(self, id): def __getattr__(self, id):
v = getattr(self.fp, id) v = getattr(self.fp, id)
setattr(self, id, v) setattr(self, id, v)
return v return v
def seek(self, offset, whence=0): def seek(self, offset, whence=0):
self.char = None self.char = None
self.fp.seek(offset, whence) self.fp.seek(offset, whence)
def read(self, count): def read(self, count):
return self.fp.read(count).decode('latin-1') return self.fp.read(count).decode('latin-1')
def readbinary(self, count): def readbinary(self, count):
return self.fp.read(count) return self.fp.read(count)
def tell(self): def tell(self):
pos = self.fp.tell() pos = self.fp.tell()
if self.char: if self.char:
pos -= 1 pos -= 1
return pos return pos
def readline(self): def readline(self):
s = b"" s = b""
if self.char: if self.char:
@ -187,6 +200,7 @@ def _accept(prefix):
# Image plugin for Encapsulated Postscript. This plugin supports only # Image plugin for Encapsulated Postscript. This plugin supports only
# a few variants of this format. # a few variants of this format.
class EpsImageFile(ImageFile.ImageFile): class EpsImageFile(ImageFile.ImageFile):
"""EPS File Parser for the Python Imaging Library""" """EPS File Parser for the Python Imaging Library"""
@ -202,7 +216,8 @@ class EpsImageFile(ImageFile.ImageFile):
# or start directly with latin coding # or start directly with latin coding
# read header in both ways to handle both # read header in both ways to handle both
# file types # 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 # for HEAD without binary preview
s = fp.read(4) s = fp.read(4)
@ -288,7 +303,6 @@ class EpsImageFile(ImageFile.ImageFile):
if s[:1] != "%": if s[:1] != "%":
break break
# #
# Scan for an "ImageData" descriptor # Scan for an "ImageData" descriptor
@ -307,7 +321,8 @@ class EpsImageFile(ImageFile.ImageFile):
[x, y, bi, mo, z3, z4, en, id] =\ [x, y, bi, mo, z3, z4, en, id] =\
s[11:].split(None, 7) s[11:].split(None, 7)
x = int(x); y = int(y) x = int(x)
y = int(y)
bi = int(bi) bi = int(bi)
mo = int(mo) mo = int(mo)
@ -368,6 +383,7 @@ class EpsImageFile(ImageFile.ImageFile):
# use our custom load method by defining this method. # use our custom load method by defining this method.
pass pass
# #
# -------------------------------------------------------------------- # --------------------------------------------------------------------
@ -392,8 +408,10 @@ def _save(im, fp, filename, eps=1):
class NoCloseStream: class NoCloseStream:
def __init__(self, fp): def __init__(self, fp):
self.fp = fp self.fp = fp
def __getattr__(self, name): def __getattr__(self, name):
return getattr(self.fp, name) return getattr(self.fp, name)
def close(self): def close(self):
pass pass

View File

@ -38,12 +38,14 @@ MODES = {
(0x00038000, 0x00038001, 0x00038002, 0x00037ffe): ("RGBA", "RGBA"), (0x00038000, 0x00038001, 0x00038002, 0x00037ffe): ("RGBA", "RGBA"),
} }
# #
# -------------------------------------------------------------------- # --------------------------------------------------------------------
def _accept(prefix): def _accept(prefix):
return prefix[:8] == MAGIC return prefix[:8] == MAGIC
## ##
# Image plugin for the FlashPix images. # Image plugin for the FlashPix images.
@ -212,7 +214,8 @@ class FpxImageFile(ImageFile.ImageFile):
def load(self): def load(self):
if not self.fp: 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) ImageFile.ImageFile.load(self)

View File

@ -17,9 +17,11 @@ from PIL import Image, ImageFile, _binary
i32 = _binary.i32be i32 = _binary.i32be
def _accept(prefix): def _accept(prefix):
return i32(prefix) >= 20 and i32(prefix[4:8]) == 1 return i32(prefix) >= 20 and i32(prefix[4:8]) == 1
## ##
# Image plugin for the GIMP brush format. # Image plugin for the GIMP brush format.

View File

@ -36,6 +36,7 @@ except ImportError:
i16 = _binary.i16be i16 = _binary.i16be
## ##
# Image plugin for the GD uncompressed format. Note that this format # Image plugin for the GD uncompressed format. Note that this format
# is not supported by the standard <b>Image.open</b> function. To use # is not supported by the standard <b>Image.open</b> function. To use
@ -64,6 +65,7 @@ class GdImageFile(ImageFile.ImageFile):
self.tile = [("raw", (0, 0)+self.size, 775, ("L", 0, -1))] self.tile = [("raw", (0, 0)+self.size, 775, ("L", 0, -1))]
## ##
# Load texture from a GD image file. # Load texture from a GD image file.
# #

View File

@ -46,6 +46,7 @@ o16 = _binary.o16le
def _accept(prefix): def _accept(prefix):
return prefix[:6] in [b"GIF87a", b"GIF89a"] return prefix[:6] in [b"GIF87a", b"GIF89a"]
## ##
# Image plugin for GIF images. This plugin supports both GIF87 and # Image plugin for GIF images. This plugin supports both GIF87 and
# GIF89 images. # GIF89 images.
@ -219,7 +220,6 @@ class GifImageFile(ImageFile.ImageFile):
except (AttributeError, KeyError): except (AttributeError, KeyError):
pass pass
if not self.tile: if not self.tile:
# self.__fp = None # self.__fp = None
raise EOFError("no more images in GIF file") raise EOFError("no more images in GIF file")
@ -240,7 +240,8 @@ class GifImageFile(ImageFile.ImageFile):
# we do this by pasting the updated area onto the previous # we do this by pasting the updated area onto the previous
# frame which we then use as the current image content # frame which we then use as the current image content
updated = self.im.crop(self.dispose_extent) updated = self.im.crop(self.dispose_extent)
self._prev_im.paste(updated, self.dispose_extent, updated.convert('RGBA')) self._prev_im.paste(updated, self.dispose_extent,
updated.convert('RGBA'))
self.im = self._prev_im self.im = self._prev_im
self._prev_im = self.im.copy() self._prev_im = self.im.copy()
@ -258,6 +259,7 @@ RAWMODE = {
"P": "P", "P": "P",
} }
def _save(im, fp, filename): def _save(im, fp, filename):
if _imaging_gif: if _imaging_gif:
@ -343,7 +345,8 @@ def _save(im, fp, filename):
o8(8)) # bits o8(8)) # bits
imOut.encoderconfig = (8, interlace) imOut.encoderconfig = (8, interlace)
ImageFile._save(imOut, fp, [("gif", (0,0)+im.size, 0, RAWMODE[imOut.mode])]) ImageFile._save(imOut, fp, [("gif", (0, 0)+im.size, 0,
RAWMODE[imOut.mode])])
fp.write(b"\0") # end of image data fp.write(b"\0") # end of image data
@ -351,7 +354,8 @@ def _save(im, fp, filename):
try: try:
fp.flush() fp.flush()
except: pass except:
pass
def _save_netpbm(im, fp, filename): def _save_netpbm(im, fp, filename):
@ -380,7 +384,8 @@ def _save_netpbm(im, fp, filename):
stderr = tempfile.TemporaryFile() stderr = tempfile.TemporaryFile()
quant_proc = Popen(quant_cmd, stdout=PIPE, stderr=stderr) quant_proc = Popen(quant_cmd, stdout=PIPE, stderr=stderr)
stderr = tempfile.TemporaryFile() stderr = tempfile.TemporaryFile()
togif_proc = Popen(togif_cmd, stdin=quant_proc.stdout, stdout=f, stderr=stderr) togif_proc = Popen(togif_cmd, stdin=quant_proc.stdout, stdout=f,
stderr=stderr)
# Allow ppmquant to receive SIGPIPE if ppmtogif exits # Allow ppmquant to receive SIGPIPE if ppmtogif exits
quant_proc.stdout.close() quant_proc.stdout.close()
@ -455,9 +460,11 @@ def getheader(im, palette=None, info=None):
for i in range(len(imageBytes)): for i in range(len(imageBytes)):
imageBytes[i] = newPositions[imageBytes[i]] imageBytes[i] = newPositions[imageBytes[i]]
im.frombytes(bytes(imageBytes)) im.frombytes(bytes(imageBytes))
newPaletteBytes = paletteBytes + (768 - len(paletteBytes)) * b'\x00' newPaletteBytes = (paletteBytes +
(768 - len(paletteBytes)) * b'\x00')
im.putpalette(newPaletteBytes) im.putpalette(newPaletteBytes)
im.palette = ImagePalette.ImagePalette("RGB", palette = paletteBytes, size = len(paletteBytes)) im.palette = ImagePalette.ImagePalette("RGB", palette=paletteBytes,
size=len(paletteBytes))
if not paletteBytes: if not paletteBytes:
paletteBytes = sourcePalette paletteBytes = sourcePalette
@ -466,7 +473,8 @@ def getheader(im, palette=None, info=None):
# calculate the palette size for the header # calculate the palette size for the header
import math import math
colorTableSize = int(math.ceil(math.log(len(paletteBytes)//3, 2)))-1 colorTableSize = int(math.ceil(math.log(len(paletteBytes)//3, 2)))-1
if colorTableSize < 0: colorTableSize = 0 if colorTableSize < 0:
colorTableSize = 0
# size of global color table + global color table flag # size of global color table + global color table flag
header.append(o8(colorTableSize + 128)) header.append(o8(colorTableSize + 128))
# background + reserved/aspect # background + reserved/aspect
@ -491,6 +499,7 @@ def getdata(im, offset = (0, 0), **params):
class collector: class collector:
data = [] data = []
def write(self, data): def write(self, data):
self.data.append(data) self.data.append(data)

View File

@ -13,6 +13,7 @@ from PIL import Image, ImageFile
_handler = None _handler = None
## ##
# Install application-specific GRIB image handler. # Install application-specific GRIB image handler.
# #
@ -22,12 +23,14 @@ def register_handler(handler):
global _handler global _handler
_handler = handler _handler = handler
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# Image adapter # Image adapter
def _accept(prefix): def _accept(prefix):
return prefix[0:4] == b"GRIB" and prefix[7] == b'\x01' return prefix[0:4] == b"GRIB" and prefix[7] == b'\x01'
class GribStubImageFile(ImageFile.StubImageFile): class GribStubImageFile(ImageFile.StubImageFile):
format = "GRIB" format = "GRIB"
@ -53,6 +56,7 @@ class GribStubImageFile(ImageFile.StubImageFile):
def _load(self): def _load(self):
return _handler return _handler
def _save(im, fp, filename): def _save(im, fp, filename):
if _handler is None or not hasattr("_handler", "save"): if _handler is None or not hasattr("_handler", "save"):
raise IOError("GRIB save handler not installed") raise IOError("GRIB save handler not installed")

View File

@ -13,6 +13,7 @@ from PIL import Image, ImageFile
_handler = None _handler = None
## ##
# Install application-specific HDF5 image handler. # Install application-specific HDF5 image handler.
# #
@ -22,12 +23,14 @@ def register_handler(handler):
global _handler global _handler
_handler = handler _handler = handler
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# Image adapter # Image adapter
def _accept(prefix): def _accept(prefix):
return prefix[:8] == b"\x89HDF\r\n\x1a\n" return prefix[:8] == b"\x89HDF\r\n\x1a\n"
class HDF5StubImageFile(ImageFile.StubImageFile): class HDF5StubImageFile(ImageFile.StubImageFile):
format = "HDF5" format = "HDF5"

View File

@ -16,7 +16,8 @@
# #
from PIL import Image, ImageFile, PngImagePlugin, _binary from PIL import Image, ImageFile, PngImagePlugin, _binary
import struct, io import io
import struct
enable_jpeg2k = hasattr(Image.core, 'jp2klib_version') enable_jpeg2k = hasattr(Image.core, 'jp2klib_version')
if enable_jpeg2k: if enable_jpeg2k:
@ -26,9 +27,11 @@ i8 = _binary.i8
HEADERSIZE = 8 HEADERSIZE = 8
def nextheader(fobj): def nextheader(fobj):
return struct.unpack('>4sI', fobj.read(HEADERSIZE)) return struct.unpack('>4sI', fobj.read(HEADERSIZE))
def read_32t(fobj, start_length, size): def read_32t(fobj, start_length, size):
# The 128x128 icon seems to have an extra header for some reason. # The 128x128 icon seems to have an extra header for some reason.
(start, length) = start_length (start, length) = start_length
@ -38,6 +41,7 @@ def read_32t(fobj, start_length, size):
raise SyntaxError('Unknown signature, expecting 0x00000000') raise SyntaxError('Unknown signature, expecting 0x00000000')
return read_32(fobj, (start + 4, length - 4), size) return read_32(fobj, (start + 4, length - 4), size)
def read_32(fobj, start_length, size): def read_32(fobj, start_length, size):
""" """
Read a 32bit RGB icon resource. Seems to be either uncompressed or 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) im.im.putband(band.im, band_ix)
return {"RGB": im} return {"RGB": im}
def read_mk(fobj, start_length, size): def read_mk(fobj, start_length, size):
# Alpha masks seem to be uncompressed # Alpha masks seem to be uncompressed
(start, length) = start_length (start, length) = start_length
@ -94,6 +99,7 @@ def read_mk(fobj, start_length, size):
) )
return {"A": band} return {"A": band}
def read_png_or_jpeg2000(fobj, start_length, size): def read_png_or_jpeg2000(fobj, start_length, size):
(start, length) = start_length (start, length) = start_length
fobj.seek(start) fobj.seek(start)
@ -106,7 +112,8 @@ def read_png_or_jpeg2000(fobj, start_length, size):
or sig[:4] == b'\x0d\x0a\x87\x0a' \ or sig[:4] == b'\x0d\x0a\x87\x0a' \
or sig == b'\x00\x00\x00\x0cjP \x0d\x0a\x87\x0a': or sig == b'\x00\x00\x00\x0cjP \x0d\x0a\x87\x0a':
if not enable_jpeg2k: 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 # j2k, jpc or j2c
fobj.seek(start) fobj.seek(start)
jp2kstream = fobj.read(length) jp2kstream = fobj.read(length)
@ -118,6 +125,7 @@ def read_png_or_jpeg2000(fobj, start_length, size):
else: else:
raise ValueError('Unsupported icon subimage format') raise ValueError('Unsupported icon subimage format')
class IcnsFile: class IcnsFile:
SIZES = { SIZES = {
@ -233,6 +241,7 @@ class IcnsFile:
pass pass
return im return im
## ##
# Image plugin for Mac OS icons. # Image plugin for Mac OS icons.
@ -288,7 +297,8 @@ Image.register_open("ICNS", IcnsImageFile, lambda x: x[:4] == b'icns')
Image.register_extension("ICNS", '.icns') Image.register_extension("ICNS", '.icns')
if __name__ == '__main__': if __name__ == '__main__':
import os, sys import os
import sys
imf = IcnsImageFile(open(sys.argv[1], 'rb')) imf = IcnsImageFile(open(sys.argv[1], 'rb'))
for size in imf.info['sizes']: for size in imf.info['sizes']:
imf.size = size imf.size = size

View File

@ -13,7 +13,8 @@
# See the README file for information on usage and redistribution. # See the README file for information on usage and redistribution.
# #
# This plugin is a refactored version of Win32IconImagePlugin by Bryan Davis <casadebender@gmail.com>. # This plugin is a refactored version of Win32IconImagePlugin by Bryan Davis
# <casadebender@gmail.com>.
# https://code.google.com/p/casadebender/wiki/Win32IconImagePlugin # https://code.google.com/p/casadebender/wiki/Win32IconImagePlugin
# #
# Icon format references: # Icon format references:
@ -35,6 +36,7 @@ i32 = _binary.i32le
_MAGIC = b"\0\0\1\0" _MAGIC = b"\0\0\1\0"
def _accept(prefix): def _accept(prefix):
return prefix[:4] == _MAGIC return prefix[:4] == _MAGIC
@ -63,7 +65,7 @@ class IcoFile:
icon_header = { icon_header = {
'width': i8(s[0]), 'width': i8(s[0]),
'height': i8(s[1]), '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]), 'reserved': i8(s[3]),
'planes': i16(s[4:]), 'planes': i16(s[4:]),
'bpp': i16(s[6:]), 'bpp': i16(s[6:]),
@ -78,10 +80,14 @@ class IcoFile:
# See Wikipedia notes about color depth. # See Wikipedia notes about color depth.
# We need this just to differ images with equal sizes # 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['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) self.entry.append(icon_header)
@ -102,7 +108,7 @@ class IcoFile:
Get an image from the icon Get an image from the icon
""" """
for (i, h) in enumerate(self.entry): 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(i)
return self.frame(0) return self.frame(0)
@ -139,8 +145,9 @@ class IcoFile:
if 32 == bpp: if 32 == bpp:
# 32-bit color depth icon image allows semitransparent areas # 32-bit color depth icon image allows semitransparent areas
# PIL's DIB format ignores transparency bits, recover them # PIL's DIB format ignores transparency bits, recover them.
# The DIB is packed in BGRX byte order where X is the alpha channel # The DIB is packed in BGRX byte order where X is the alpha
# channel.
# Back up to start of bmp data # Back up to start of bmp data
self.buf.seek(o) self.buf.seek(o)
@ -162,9 +169,11 @@ class IcoFile:
# bitmap row data is aligned to word boundaries # bitmap row data is aligned to word boundaries
w += 32 - (im.size[0] % 32) 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) total_bytes = int((w * im.size[1]) / 8)
self.buf.seek(and_mask_offset) self.buf.seek(and_mask_offset)
@ -187,6 +196,7 @@ class IcoFile:
return im return im
## ##
# Image plugin for Windows Icon files. # Image plugin for Windows Icon files.
@ -194,15 +204,16 @@ class IcoImageFile(ImageFile.ImageFile):
""" """
PIL read-only image support for Microsoft Windows .ico files. PIL read-only image support for Microsoft Windows .ico files.
By default the largest resolution image in the file will be loaded. This can By default the largest resolution image in the file will be loaded. This
be changed by altering the 'size' attribute before calling 'load'. 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 The info dictionary has a key 'sizes' that is a list of the sizes available
in the icon file. in the icon file.
Handles classic, XP and Vista icon formats. Handles classic, XP and Vista icon formats.
This plugin is a refactored version of Win32IconImagePlugin by Bryan Davis <casadebender@gmail.com>. This plugin is a refactored version of Win32IconImagePlugin by Bryan Davis
<casadebender@gmail.com>.
https://code.google.com/p/casadebender/wiki/Win32IconImagePlugin https://code.google.com/p/casadebender/wiki/Win32IconImagePlugin
""" """
format = "ICO" format = "ICO"
@ -222,9 +233,9 @@ class IcoImageFile(ImageFile.ImageFile):
self.mode = im.mode self.mode = im.mode
self.size = im.size self.size = im.size
def load_seek(self): 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 pass
# #
# -------------------------------------------------------------------- # --------------------------------------------------------------------

View File

@ -30,7 +30,7 @@ __version__ = "0.7"
import re import re
from PIL import Image, ImageFile, ImagePalette from PIL import Image, ImageFile, ImagePalette
from PIL._binary import i8, o8 from PIL._binary import i8
# -------------------------------------------------------------------- # --------------------------------------------------------------------
@ -94,12 +94,14 @@ for i in range(2, 33):
split = re.compile(br"^([A-Za-z][^:]*):[ \t]*(.*)[ \t]*$") split = re.compile(br"^([A-Za-z][^:]*):[ \t]*(.*)[ \t]*$")
def number(s): def number(s):
try: try:
return int(s) return int(s)
except ValueError: except ValueError:
return float(s) return float(s)
## ##
# Image plugin for the IFUNC IM file format. # 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 # Quick rejection: if there's not an LF among the first
# 100 bytes, this is (probably) not a text header. # 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") raise SyntaxError("not an IM file")
self.fp.seek(0) self.fp.seek(0)
@ -186,7 +188,8 @@ class ImImageFile(ImageFile.ImageFile):
else: 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: if not n:
raise SyntaxError("Not an IM file") raise SyntaxError("Not an IM file")
@ -254,7 +257,8 @@ class ImImageFile(ImageFile.ImageFile):
("raw", (0, 0)+self.size, offs+2*size, ("B", 0, -1))] ("raw", (0, 0)+self.size, offs+2*size, ("B", 0, -1))]
else: else:
# LabEye/IFUNC files # 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): def seek(self, frame):
@ -305,6 +309,7 @@ SAVE = {
"YCbCr": ("YCC", "YCbCr;L") "YCbCr": ("YCC", "YCbCr;L")
} }
def _save(im, fp, filename, check=0): def _save(im, fp, filename, check=0):
try: try:

View File

@ -20,6 +20,7 @@
from PIL import Image from PIL import Image
import re import re
def getrgb(color): def getrgb(color):
""" """
Convert a color string to an RGB tuple. If the string cannot be parsed, 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[1] * 255 + 0.5),
int(rgb[2] * 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: if m:
return ( return (
int(m.group(1)), int(m.group(1)),
@ -96,6 +98,7 @@ def getrgb(color):
) )
raise ValueError("unknown color specifier: %r" % color) raise ValueError("unknown color specifier: %r" % color)
def getcolor(color, mode): def getcolor(color, mode):
""" """
Same as :py:func:`~PIL.ImageColor.getrgb`, but converts the RGB value to a Same as :py:func:`~PIL.ImageColor.getrgb`, but converts the RGB value to a

View File

@ -61,7 +61,7 @@ class ImageDraw:
def __init__(self, im, mode=None): def __init__(self, im, mode=None):
im.load() im.load()
if im.readonly: if im.readonly:
im._copy() # make it writable im._copy() # make it writeable
blend = 0 blend = 0
if mode is None: if mode is None:
mode = im.mode mode = im.mode
@ -280,6 +280,7 @@ class ImageDraw:
font = self.getfont() font = self.getfont()
return font.getsize(text) return font.getsize(text)
## ##
# A simple 2D drawing interface for PIL images. # A simple 2D drawing interface for PIL images.
# #
@ -302,6 +303,7 @@ try:
except: except:
Outline = None Outline = None
## ##
# (Experimental) A more advanced 2D drawing interface for PIL images, # (Experimental) A more advanced 2D drawing interface for PIL images,
# based on the WCK interface. # based on the WCK interface.
@ -325,6 +327,7 @@ def getdraw(im=None, hints=None):
im = handler.Draw(im) im = handler.Draw(im)
return im, handler return im, handler
## ##
# (experimental) Fills a bounded region with a given color. # (experimental) Fills a bounded region with a given color.
# #

View File

@ -18,21 +18,25 @@
from PIL import Image, ImageColor, ImageDraw, ImageFont, ImagePath from PIL import Image, ImageColor, ImageDraw, ImageFont, ImagePath
class Pen: class Pen:
def __init__(self, color, width=1, opacity=255): def __init__(self, color, width=1, opacity=255):
self.color = ImageColor.getrgb(color) self.color = ImageColor.getrgb(color)
self.width = width self.width = width
class Brush: class Brush:
def __init__(self, color, opacity=255): def __init__(self, color, opacity=255):
self.color = ImageColor.getrgb(color) self.color = ImageColor.getrgb(color)
class Font: class Font:
def __init__(self, color, file, size=12): def __init__(self, color, file, size=12):
# FIXME: add support for bitmap fonts # FIXME: add support for bitmap fonts
self.color = ImageColor.getrgb(color) self.color = ImageColor.getrgb(color)
self.font = ImageFont.truetype(file, size) self.font = ImageFont.truetype(file, size)
class Draw: class Draw:
def __init__(self, image, size=None, color=None): def __init__(self, image, size=None, color=None):
@ -47,7 +51,8 @@ class Draw:
def render(self, op, xy, pen, brush=None): def render(self, op, xy, pen, brush=None):
# handle color arguments # handle color arguments
outline = fill = None; width = 1 outline = fill = None
width = 1
if isinstance(pen, Pen): if isinstance(pen, Pen):
outline = pen.color outline = pen.color
width = pen.width width = pen.width

View File

@ -29,8 +29,10 @@
from PIL import Image from PIL import Image
from PIL._util import isPath from PIL._util import isPath
import traceback, os, sys
import io import io
import os
import sys
import traceback
MAXBLOCK = 65536 MAXBLOCK = 65536
@ -46,6 +48,7 @@ ERRORS = {
-9: "out of memory error" -9: "out of memory error"
} }
def raise_ioerror(error): def raise_ioerror(error):
try: try:
message = Image.core.getcodecstatus(error) message = Image.core.getcodecstatus(error)
@ -55,6 +58,7 @@ def raise_ioerror(error):
message = "decoder error %d" % error message = "decoder error %d" % error
raise IOError(message + " when reading image file") raise IOError(message + " when reading image file")
# #
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# Helpers # Helpers
@ -63,6 +67,7 @@ def _tilesort(t):
# sort on offset # sort on offset
return t[2] return t[2]
# #
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# ImageFile base class # ImageFile base class
@ -213,13 +218,15 @@ class ImageFile(Image.Image):
self.tile = [] self.tile = []
# JpegDecode needs to clean things up here either way # 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() d.cleanup()
if LOAD_TRUNCATED_IMAGES: if LOAD_TRUNCATED_IMAGES:
break break
else: 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 b = b + s
n, e = d.decode(b) n, e = d.decode(b)
@ -434,6 +441,7 @@ class Parser:
fp.close() # explicitly close the virtual file fp.close() # explicitly close the virtual file
return self.image return self.image
# -------------------------------------------------------------------- # --------------------------------------------------------------------
def _save(im, fp, tile, bufsize=0): def _save(im, fp, tile, bufsize=0):
@ -450,7 +458,7 @@ def _save(im, fp, tile, bufsize=0):
im.encoderconfig = () im.encoderconfig = ()
tile.sort(key=_tilesort) tile.sort(key=_tilesort)
# FIXME: make MAXBLOCK a configuration parameter # 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 # But, it would need at least the image size in most cases. RawEncode is
# a tricky case. # 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
@ -483,7 +491,8 @@ def _save(im, fp, tile, bufsize=0):
raise IOError("encoder error %d when writing image file" % s) raise IOError("encoder error %d when writing image file" % s)
try: try:
fp.flush() fp.flush()
except: pass except:
pass
def _safe_read(fp, size): def _safe_read(fp, size):

View File

@ -16,6 +16,7 @@
# mode descriptor cache # mode descriptor cache
_modes = {} _modes = {}
## ##
# Wrapper for mode strings. # Wrapper for mode strings.
@ -30,6 +31,7 @@ class ModeDescriptor:
def __str__(self): def __str__(self):
return self.mode return self.mode
## ##
# Gets a mode descriptor for the given mode. # Gets a mode descriptor for the given mode.

View File

@ -22,6 +22,7 @@ from PIL._util import isStringType
import operator import operator
from functools import reduce from functools import reduce
# #
# helpers # helpers
@ -35,12 +36,14 @@ def _border(border):
left = top = right = bottom = border left = top = right = bottom = border
return left, top, right, bottom return left, top, right, bottom
def _color(color, mode): def _color(color, mode):
if isStringType(color): if isStringType(color):
from PIL import ImageColor from PIL import ImageColor
color = ImageColor.getcolor(color, mode) color = ImageColor.getcolor(color, mode)
return color return color
def _lut(image, lut): def _lut(image, lut):
if image.mode == "P": if image.mode == "P":
# FIXME: apply to lookup table, not image data # FIXME: apply to lookup table, not image data
@ -147,7 +150,9 @@ def colorize(image, black, white):
assert image.mode == "L" assert image.mode == "L"
black = _color(black, "RGB") black = _color(black, "RGB")
white = _color(white, "RGB") white = _color(white, "RGB")
red = []; green = []; blue = [] red = []
green = []
blue = []
for i in range(256): for i in range(256):
red.append(black[0]+i*(white[0]-black[0])//255) red.append(black[0]+i*(white[0]-black[0])//255)
green.append(black[1]+i*(white[1]-black[1])//255) green.append(black[1]+i*(white[1]-black[1])//255)
@ -404,6 +409,7 @@ def solarize(image, threshold=128):
lut.append(255-i) lut.append(255-i)
return _lut(image, lut) return _lut(image, lut)
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# PIL USM components, from Kevin Cazabon. # PIL USM components, from Kevin Cazabon.
@ -419,6 +425,7 @@ def gaussian_blur(im, radius=None):
gblur = gaussian_blur gblur = gaussian_blur
def unsharp_mask(im, radius=None, percent=None, threshold=None): def unsharp_mask(im, radius=None, percent=None, threshold=None):
""" PIL_usm.usm(im, [radius, percent, threshold])""" """ PIL_usm.usm(im, [radius, percent, threshold])"""

View File

@ -15,6 +15,7 @@
## ##
class Iterator: class Iterator:
""" """
This class implements an iterator object that can be used to loop This class implements an iterator object that can be used to loop

View File

@ -15,7 +15,8 @@
from __future__ import print_function from __future__ import print_function
from PIL import Image from PIL import Image
import os, sys import os
import sys
if sys.version_info >= (3, 3): if sys.version_info >= (3, 3):
from shlex import quote from shlex import quote
@ -24,6 +25,7 @@ else:
_viewers = [] _viewers = []
def register(viewer, order=1): def register(viewer, order=1):
try: try:
if issubclass(viewer, Viewer): if issubclass(viewer, Viewer):
@ -35,6 +37,7 @@ def register(viewer, order=1):
elif order < 0: elif order < 0:
_viewers.insert(0, viewer) _viewers.insert(0, viewer)
## ##
# Displays a given image. # Displays a given image.
# #
@ -49,6 +52,7 @@ def show(image, title=None, **options):
return 1 return 1
return 0 return 0
## ##
# Base class for viewers. # Base class for viewers.
@ -102,6 +106,7 @@ if sys.platform == "win32":
class WindowsViewer(Viewer): class WindowsViewer(Viewer):
format = "BMP" format = "BMP"
def get_command(self, file, **options): def get_command(self, file, **options):
return ('start "Pillow" /WAIT "%s" ' return ('start "Pillow" /WAIT "%s" '
'&& ping -n 2 127.0.0.1 >NUL ' '&& ping -n 2 127.0.0.1 >NUL '
@ -113,11 +118,13 @@ elif sys.platform == "darwin":
class MacViewer(Viewer): class MacViewer(Viewer):
format = "BMP" format = "BMP"
def get_command(self, file, **options): def get_command(self, file, **options):
# on darwin open returns immediately resulting in the temp # on darwin open returns immediately resulting in the temp
# file removal while app is opening # file removal while app is opening
command = "open -a /Applications/Preview.app" 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 return command
register(MacViewer) register(MacViewer)
@ -140,7 +147,8 @@ else:
class UnixViewer(Viewer): class UnixViewer(Viewer):
def show_file(self, file, **options): def show_file(self, file, **options):
command, executable = self.get_command_ex(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) os.system(command)
return 1 return 1

View File

@ -21,7 +21,8 @@
# See the README file for information on usage and redistribution. # See the README file for information on usage and redistribution.
# #
import operator, math import math
import operator
from functools import reduce from functools import reduce
@ -126,7 +127,6 @@ class Stat:
v.append(math.sqrt(self.sum2[i] / self.count[i])) v.append(math.sqrt(self.sum2[i] / self.count[i]))
return v return v
def _getvar(self): def _getvar(self):
"Get variance for each layer" "Get variance for each layer"

View File

@ -40,6 +40,7 @@ from PIL import Image
_pilbitmap_ok = None _pilbitmap_ok = None
def _pilbitmap_check(): def _pilbitmap_check():
global _pilbitmap_ok global _pilbitmap_ok
if _pilbitmap_ok is None: if _pilbitmap_ok is None:
@ -51,6 +52,7 @@ def _pilbitmap_check():
_pilbitmap_ok = 0 _pilbitmap_ok = 0
return _pilbitmap_ok return _pilbitmap_ok
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# PhotoImage # PhotoImage
@ -120,7 +122,6 @@ class PhotoImage:
except: except:
pass # ignore internal errors pass # ignore internal errors
def __str__(self): def __str__(self):
""" """
Get the Tkinter photo image identifier. This method is automatically Get the Tkinter photo image identifier. This method is automatically
@ -131,7 +132,6 @@ class PhotoImage:
""" """
return str(self.__photo) return str(self.__photo)
def width(self): def width(self):
""" """
Get the width of the image. Get the width of the image.
@ -140,7 +140,6 @@ class PhotoImage:
""" """
return self.__size[0] return self.__size[0]
def height(self): def height(self):
""" """
Get the height of the image. Get the height of the image.
@ -149,7 +148,6 @@ class PhotoImage:
""" """
return self.__size[1] return self.__size[1]
def paste(self, im, box=None): def paste(self, im, box=None):
""" """
Paste a PIL image into the photo image. Note that this can Paste a PIL image into the photo image. Note that this can
@ -176,7 +174,7 @@ class PhotoImage:
try: try:
tk.call("PyImagingPhoto", self.__photo, block.id) tk.call("PyImagingPhoto", self.__photo, block.id)
except tkinter.TclError as v: except tkinter.TclError:
# activate Tkinter hook # activate Tkinter hook
try: try:
from PIL import _imagingtk from PIL import _imagingtk
@ -240,7 +238,6 @@ class BitmapImage:
except: except:
pass # ignore internal errors pass # ignore internal errors
def width(self): def width(self):
""" """
Get the width of the image. Get the width of the image.
@ -249,7 +246,6 @@ class BitmapImage:
""" """
return self.__size[0] return self.__size[0]
def height(self): def height(self):
""" """
Get the height of the image. Get the height of the image.
@ -258,7 +254,6 @@ class BitmapImage:
""" """
return self.__size[1] return self.__size[1]
def __str__(self): def __str__(self):
""" """
Get the Tkinter bitmap image identifier. This method is automatically 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.""" """Copies the contents of a PhotoImage to a PIL image memory."""
photo.tk.call("PyImagingPhotoGet", photo) photo.tk.call("PyImagingPhotoGet", photo)
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# Helper for the Image.show method. # Helper for the Image.show method.

View File

@ -15,16 +15,20 @@
from PIL import Image from PIL import Image
class Transform(Image.ImageTransformHandler): class Transform(Image.ImageTransformHandler):
def __init__(self, data): def __init__(self, data):
self.data = data self.data = data
def getdata(self): def getdata(self):
return self.method, self.data return self.method, self.data
def transform(self, size, image, **options): def transform(self, size, image, **options):
# can be overridden # can be overridden
method, data = self.getdata() method, data = self.getdata()
return image.transform(size, method, data, **options) return image.transform(size, method, data, **options)
## ##
# Define an affine image transform. # Define an affine image transform.
# <p> # <p>
@ -43,9 +47,11 @@ class Transform(Image.ImageTransformHandler):
# the first two rows from an affine transform matrix. # the first two rows from an affine transform matrix.
# @see Image#Image.transform # @see Image#Image.transform
class AffineTransform(Transform): class AffineTransform(Transform):
method = Image.AFFINE method = Image.AFFINE
## ##
# Define a transform to extract a subregion from an image. # Define a transform to extract a subregion from an image.
# <p> # <p>
@ -68,6 +74,7 @@ class AffineTransform(Transform):
class ExtentTransform(Transform): class ExtentTransform(Transform):
method = Image.EXTENT method = Image.EXTENT
## ##
# Define an quad image transform. # Define an quad image transform.
# <p> # <p>
@ -83,6 +90,7 @@ class ExtentTransform(Transform):
class QuadTransform(Transform): class QuadTransform(Transform):
method = Image.QUAD method = Image.QUAD
## ##
# Define an mesh image transform. A mesh transform consists of one # Define an mesh image transform. A mesh transform consists of one
# or more individual quad transforms. # or more individual quad transforms.

View File

@ -29,9 +29,11 @@ class HDC:
""" """
def __init__(self, dc): def __init__(self, dc):
self.dc = dc self.dc = dc
def __int__(self): def __int__(self):
return self.dc return self.dc
class HWND: class HWND:
""" """
Wraps a HWND integer. The resulting object can be passed to the Wraps a HWND integer. The resulting object can be passed to the
@ -40,6 +42,7 @@ class HWND:
""" """
def __init__(self, wnd): def __init__(self, wnd):
self.wnd = wnd self.wnd = wnd
def __int__(self): def __int__(self):
return self.wnd return self.wnd
@ -79,7 +82,6 @@ class Dib:
if image: if image:
self.paste(image) self.paste(image)
def expose(self, handle): def expose(self, handle):
""" """
Copy the bitmap contents to a device context. Copy the bitmap contents to a device context.
@ -120,7 +122,6 @@ class Dib:
result = self.image.draw(handle, dst, src) result = self.image.draw(handle, dst, src)
return result return result
def query_palette(self, handle): def query_palette(self, handle):
""" """
Installs the palette associated with the image in the given device Installs the palette associated with the image in the given device
@ -146,7 +147,6 @@ class Dib:
result = self.image.query_palette(handle) result = self.image.query_palette(handle)
return result return result
def paste(self, im, box=None): def paste(self, im, box=None):
""" """
Paste a PIL image into the bitmap image. Paste a PIL image into the bitmap image.
@ -166,7 +166,6 @@ class Dib:
else: else:
self.image.paste(im.im) self.image.paste(im.im)
def frombytes(self, buffer): def frombytes(self, buffer):
""" """
Load display memory contents from byte data. Load display memory contents from byte data.
@ -176,7 +175,6 @@ class Dib:
""" """
return self.image.frombytes(buffer) return self.image.frombytes(buffer)
def tobytes(self): def tobytes(self):
""" """
Copy display memory contents to bytes object. Copy display memory contents to bytes object.
@ -204,6 +202,7 @@ class Dib:
) )
return self.tobytes() return self.tobytes()
## ##
# Create a Window with the given title size. # Create a Window with the given title size.
@ -235,6 +234,7 @@ class Window:
def mainloop(self): def mainloop(self):
Image.core.eventloop() Image.core.eventloop()
## ##
# Create an image window which displays the given image. # Create an image window which displays the given image.

View File

@ -21,9 +21,11 @@ __version__ = "0.2"
import struct import struct
from PIL import Image, ImageFile from PIL import Image, ImageFile
def _accept(s): def _accept(s):
return s[:8] == b"\x00\x00\x00\x00\x00\x00\x00\x04" return s[:8] == b"\x00\x00\x00\x00\x00\x00\x00\x04"
## ##
# Image plugin for McIdas area images. # Image plugin for McIdas area images.
@ -47,10 +49,12 @@ class McIdasImageFile(ImageFile.ImageFile):
mode = rawmode = "L" mode = rawmode = "L"
elif w[11] == 2: elif w[11] == 2:
# FIXME: add memory map support # FIXME: add memory map support
mode = "I"; rawmode = "I;16B" mode = "I"
rawmode = "I;16B"
elif w[11] == 4: elif w[11] == 4:
# FIXME: add memory map support # FIXME: add memory map support
mode = "I"; rawmode = "I;32B" mode = "I"
rawmode = "I;32B"
else: else:
raise SyntaxError("unsupported McIdas format") raise SyntaxError("unsupported McIdas format")

View File

@ -31,6 +31,7 @@ from PIL.OleFileIO import *
def _accept(prefix): def _accept(prefix):
return prefix[:8] == MAGIC return prefix[:8] == MAGIC
## ##
# Image plugin for Microsoft's Image Composer file format. # Image plugin for Microsoft's Image Composer file format.

View File

@ -18,6 +18,7 @@ __version__ = "0.1"
from PIL import Image, ImageFile from PIL import Image, ImageFile
from PIL._binary import i8 from PIL._binary import i8
# #
# Bitstream parser # Bitstream parser
@ -52,6 +53,7 @@ class BitStream:
self.bits = self.bits - bits self.bits = self.bits - bits
return v return v
## ##
# Image plugin for MPEG streams. This plugin can identify a stream, # Image plugin for MPEG streams. This plugin can identify a stream,
# but it cannot read it. # but it cannot read it.

View File

@ -22,13 +22,16 @@ __version__ = "0.1"
from PIL import Image, JpegImagePlugin from PIL import Image, JpegImagePlugin
def _accept(prefix): def _accept(prefix):
return JpegImagePlugin._accept(prefix) return JpegImagePlugin._accept(prefix)
def _save(im, fp, filename): def _save(im, fp, filename):
# Note that we can only save the current frame at present # Note that we can only save the current frame at present
return JpegImagePlugin._save(im, fp, filename) return JpegImagePlugin._save(im, fp, filename)
## ##
# Image plugin for MPO images. # Image plugin for MPO images.
@ -42,7 +45,7 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile):
JpegImagePlugin.JpegImageFile._open(self) JpegImagePlugin.JpegImageFile._open(self)
self.mpinfo = self._getmp() self.mpinfo = self._getmp()
self.__framecount = self.mpinfo[0xB001] 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]] for mpent in self.mpinfo[0xB002]]
self.__mpoffsets[0] = 0 self.__mpoffsets[0] = 0
# Note that the following assertion will only be invalid if something # Note that the following assertion will only be invalid if something

View File

@ -27,9 +27,11 @@ from PIL import Image, ImageFile, _binary
i16 = _binary.i16le i16 = _binary.i16le
def _accept(prefix): def _accept(prefix):
return prefix[:4] in [b"DanM", b"LinS"] return prefix[:4] in [b"DanM", b"LinS"]
## ##
# Image plugin for Windows MSP images. This plugin supports both # Image plugin for Windows MSP images. This plugin supports both
# uncompressed (Windows 1.0). # uncompressed (Windows 1.0).
@ -66,6 +68,7 @@ class MspImageFile(ImageFile.ImageFile):
o16 = _binary.o16le o16 = _binary.o16le
def _save(im, fp, filename): def _save(im, fp, filename):
if im.mode != "1": if im.mode != "1":

View File

@ -19,6 +19,7 @@ from __future__ import print_function
from PIL import EpsImagePlugin from PIL import EpsImagePlugin
## ##
# Simple Postscript graphics interface. # Simple Postscript graphics interface.
@ -65,7 +66,7 @@ class PSDraw:
""" """
if font not in self.isofont: if font not in self.isofont:
# reencode font # reencode font
self.fp.write("/PSDraw-%s ISOLatin1Encoding /%s E\n" %\ self.fp.write("/PSDraw-%s ISOLatin1Encoding /%s E\n" %
(font, font)) (font, font))
self.isofont[font] = 1 self.isofont[font] = 1
# rough # rough
@ -73,7 +74,8 @@ class PSDraw:
def setink(self, ink): 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 ***") print("*** NOT YET IMPLEMENTED ***")
@ -127,9 +129,11 @@ class PSDraw:
xmax = float(box[2] - box[0]) xmax = float(box[2] - box[0])
ymax = float(box[3] - box[1]) ymax = float(box[3] - box[1])
if x > xmax: if x > xmax:
y = y * xmax / x; x = xmax y = y * xmax / x
x = xmax
if y > ymax: if y > ymax:
x = x * ymax / y; y = ymax x = x * ymax / y
y = ymax
dx = (xmax - x) / 2 + box[0] dx = (xmax - x) / 2 + box[0]
dy = (ymax - y) / 2 + box[1] dy = (ymax - y) / 2 + box[1]
self.fp.write("gsave\n%f %f translate\n" % (dx, dy)) self.fp.write("gsave\n%f %f translate\n" % (dx, dy))

View File

@ -15,6 +15,7 @@
from PIL._binary import o8 from PIL._binary import o8
## ##
# File handler for Teragon-style palette files. # File handler for Teragon-style palette files.
@ -49,7 +50,6 @@ class PaletteFile:
self.palette = b"".join(self.palette) self.palette = b"".join(self.palette)
def getpalette(self): def getpalette(self):
return self.palette, self.rawmode return self.palette, self.rawmode

View File

@ -22,6 +22,7 @@ from PIL import Image, ImageFile, _binary
i8 = _binary.i8 i8 = _binary.i8
## ##
# Image plugin for PhotoCD images. This plugin only reads the 768x512 # Image plugin for PhotoCD images. This plugin only reads the 768x512
# image from the file; higher resolutions are encoded in a proprietary # image from the file; higher resolutions are encoded in a proprietary

View File

@ -48,9 +48,11 @@ l32 = _binary.i32le
b16 = _binary.i16be b16 = _binary.i16be
b32 = _binary.i32be b32 = _binary.i32be
def sz(s, o): def sz(s, o):
return s[o:s.index(b"\0", o)] return s[o:s.index(b"\0", o)]
## ##
# Font file plugin for the X11 PCF format. # Font file plugin for the X11 PCF format.

View File

@ -33,9 +33,11 @@ i8 = _binary.i8
i16 = _binary.i16le i16 = _binary.i16le
o8 = _binary.o8 o8 = _binary.o8
def _accept(prefix): def _accept(prefix):
return i8(prefix[0]) == 10 and i8(prefix[1]) in [0, 2, 3, 5] return i8(prefix[0]) == 10 and i8(prefix[1]) in [0, 2, 3, 5]
## ##
# Image plugin for Paintbrush images. # Image plugin for Paintbrush images.
@ -58,7 +60,6 @@ class PcxImageFile(ImageFile.ImageFile):
if Image.DEBUG: if Image.DEBUG:
print ("BBox: %s %s %s %s" % bbox) print ("BBox: %s %s %s %s" % bbox)
# format # format
version = i8(s[1]) version = i8(s[1])
bits = i8(s[3]) bits = i8(s[3])
@ -122,6 +123,7 @@ SAVE = {
o16 = _binary.o16le o16 = _binary.o16le
def _save(im, fp, filename, check=0): def _save(im, fp, filename, check=0):
try: try:
@ -140,7 +142,6 @@ def _save(im, fp, filename, check=0):
# Ideally it should be passed in in the state, but the bytes value # Ideally it should be passed in in the state, but the bytes value
# gets overwritten. # gets overwritten.
if Image.DEBUG: if Image.DEBUG:
print ("PcxImagePlugin._save: xwidth: %d, bits: %d, stride: %d" % ( print ("PcxImagePlugin._save: xwidth: %d, bits: %d, stride: %d" % (
im.size[0], bits, stride)) im.size[0], bits, stride))

View File

@ -29,6 +29,7 @@ from PIL import Image, ImageFile, _binary
i16 = _binary.i16le i16 = _binary.i16le
i32 = _binary.i32le i32 = _binary.i32le
## ##
# Image plugin for PIXAR raster images. # Image plugin for PIXAR raster images.

View File

@ -72,6 +72,7 @@ _MODES = {
_simple_palette = re.compile(b'^\xff+\x00\xff*$') _simple_palette = re.compile(b'^\xff+\x00\xff*$')
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# Support classes. Suitable for PNG and related formats like MNG etc. # Support classes. Suitable for PNG and related formats like MNG etc.
@ -123,7 +124,7 @@ class ChunkStream:
crc1 = Image.core.crc32(data, Image.core.crc32(cid)) crc1 = Image.core.crc32(data, Image.core.crc32(cid))
crc2 = i16(self.fp.read(2)), i16(self.fp.read(2)) crc2 = i16(self.fp.read(2)), i16(self.fp.read(2))
if crc1 != crc2: if crc1 != crc2:
raise SyntaxError("broken PNG file"\ raise SyntaxError("broken PNG file"
"(bad header checksum in %s)" % cid) "(bad header checksum in %s)" % cid)
def crc_skip(self, cid, data): def crc_skip(self, cid, data):
@ -147,6 +148,7 @@ class ChunkStream:
return cids return cids
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# Subclass of string to allow iTXt chunks to look like strings while # Subclass of string to allow iTXt chunks to look like strings while
# keeping their extra information # keeping their extra information
@ -159,6 +161,7 @@ class iTXt(str):
self.tkey = tkey self.tkey = tkey
return self return self
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# PNG chunk container (for use with save(pnginfo=)) # PNG chunk container (for use with save(pnginfo=))
@ -182,9 +185,11 @@ class PngInfo:
if zip: if zip:
import zlib 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: 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): def add_text(self, key, value, zip=0):
if isinstance(value, iTXt): if isinstance(value, iTXt):
@ -206,6 +211,7 @@ class PngInfo:
else: else:
self.add(b"tEXt", key + b"\0" + value) self.add(b"tEXt", key + b"\0" + value)
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# PNG image stream (IHDR/IEND) # PNG image stream (IHDR/IEND)
@ -238,7 +244,8 @@ class PngStream(ChunkStream):
print("Compression method", i8(s[i])) print("Compression method", i8(s[i]))
comp_method = i8(s[i]) comp_method = i8(s[i])
if comp_method != 0: 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: try:
icc_profile = zlib.decompress(s[i+2:]) icc_profile = zlib.decompress(s[i+2:])
except zlib.error: except zlib.error:
@ -325,7 +332,9 @@ class PngStream(ChunkStream):
try: try:
k, v = s.split(b"\0", 1) k, v = s.split(b"\0", 1)
except ValueError: except ValueError:
k = s; v = b"" # fallback for broken tEXt tags # fallback for broken tEXt tags
k = s
v = b""
if k: if k:
if bytes is not str: if bytes is not str:
k = k.decode('latin-1', 'strict') k = k.decode('latin-1', 'strict')
@ -341,13 +350,15 @@ class PngStream(ChunkStream):
try: try:
k, v = s.split(b"\0", 1) k, v = s.split(b"\0", 1)
except ValueError: except ValueError:
k = s; v = b"" k = s
v = b""
if v: if v:
comp_method = i8(v[0]) comp_method = i8(v[0])
else: else:
comp_method = 0 comp_method = 0
if 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 import zlib
try: try:
v = zlib.decompress(v[1:]) v = zlib.decompress(v[1:])
@ -399,12 +410,14 @@ class PngStream(ChunkStream):
return s return s
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# PNG reader # PNG reader
def _accept(prefix): def _accept(prefix):
return prefix[:8] == _MAGIC return prefix[:8] == _MAGIC
## ##
# Image plugin for PNG images. # Image plugin for PNG images.
@ -460,7 +473,6 @@ class PngImageFile(ImageFile.ImageFile):
self.__idat = length # used by load_read() self.__idat = length # used by load_read()
def verify(self): def verify(self):
"Verify PNG file" "Verify PNG file"
@ -509,7 +521,6 @@ class PngImageFile(ImageFile.ImageFile):
return self.fp.read(read_bytes) return self.fp.read(read_bytes)
def load_end(self): def load_end(self):
"internal: finished reading image data" "internal: finished reading image data"
@ -541,6 +552,7 @@ _OUTMODES = {
"RGBA": ("RGBA", b'\x08\x06'), "RGBA": ("RGBA", b'\x08\x06'),
} }
def putchunk(fp, cid, *data): def putchunk(fp, cid, *data):
"Write a PNG chunk (including CRC field)" "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)) hi, lo = Image.core.crc32(data, Image.core.crc32(cid))
fp.write(o16(hi) + o16(lo)) fp.write(o16(hi) + o16(lo))
class _idat: class _idat:
# wrap output from the encoder in IDAT chunks # wrap output from the encoder in IDAT chunks
def __init__(self, fp, chunk): def __init__(self, fp, chunk):
self.fp = fp self.fp = fp
self.chunk = chunk self.chunk = chunk
def write(self, data): def write(self, data):
self.chunk(self.fp, b"IDAT", data) self.chunk(self.fp, b"IDAT", data)
def _save(im, fp, filename, chunk=putchunk, check=0): def _save(im, fp, filename, chunk=putchunk, check=0):
# save an image to disk (called by the save method) # save an image to disk (called by the save method)
@ -629,7 +644,8 @@ def _save(im, fp, filename, chunk=putchunk, check=0):
palette_bytes += b'\0' palette_bytes += b'\0'
chunk(fp, b"PLTE", palette_bytes) 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 transparency or transparency == 0:
if im.mode == "P": 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"]) data = name + b"\0\0" + zlib.compress(im.info["icc_profile"])
chunk(fp, b"iCCP", data) 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"") chunk(fp, b"IEND", b"")
@ -704,8 +721,10 @@ def getchunks(im, **params):
class collector: class collector:
data = [] data = []
def write(self, data): def write(self, data):
pass pass
def append(self, chunk): def append(self, chunk):
self.data.append(chunk) self.data.append(chunk)

View File

@ -31,7 +31,8 @@ try:
if locale_enc is None: if locale_enc is None:
locale_lang, locale_enc = locale.getdefaultlocale() locale_lang, locale_enc = locale.getdefaultlocale()
b_whitespace = b_whitespace.decode(locale_enc) b_whitespace = b_whitespace.decode(locale_enc)
except: pass except:
pass
b_whitespace = b_whitespace.encode('ascii', 'ignore') b_whitespace = b_whitespace.encode('ascii', 'ignore')
MODES = { MODES = {
@ -47,9 +48,11 @@ MODES = {
b"PyCMYK": "CMYK" b"PyCMYK": "CMYK"
} }
def _accept(prefix): def _accept(prefix):
return prefix[0:1] == b"P" and prefix[1] in b"0456y" return prefix[0:1] == b"P" and prefix[1] in b"0456y"
## ##
# Image plugin for PBM, PGM, and PPM images. # Image plugin for PBM, PGM, and PPM images.
@ -109,7 +112,7 @@ class PpmImageFile(ImageFile.ImageFile):
self.mode = 'I' self.mode = 'I'
rawmode = 'I;16B' rawmode = 'I;16B'
else: else:
self.mode = 'I'; self.mode = 'I'
rawmode = 'I;32B' rawmode = 'I;32B'
self.size = xsize, ysize self.size = xsize, ysize
@ -123,6 +126,7 @@ class PpmImageFile(ImageFile.ImageFile):
# self.mode = self.im.mode # self.mode = self.im.mode
# self.size = self.im.size # self.size = self.im.size
# #
# -------------------------------------------------------------------- # --------------------------------------------------------------------

View File

@ -40,12 +40,14 @@ i8 = _binary.i8
i16 = _binary.i16be i16 = _binary.i16be
i32 = _binary.i32be i32 = _binary.i32be
# --------------------------------------------------------------------. # --------------------------------------------------------------------.
# read PSD images # read PSD images
def _accept(prefix): def _accept(prefix):
return prefix[:4] == b"8BPS" return prefix[:4] == b"8BPS"
## ##
# Image plugin for Photoshop images. # Image plugin for Photoshop images.
@ -159,6 +161,7 @@ class PsdImageFile(ImageFile.ImageFile):
if self.mode == "P": if self.mode == "P":
Image.Image.load(self) Image.Image.load(self)
def _layerinfo(file): def _layerinfo(file):
# read layerinfo block # read layerinfo block
layers = [] layers = []
@ -166,8 +169,10 @@ def _layerinfo(file):
for i in range(abs(i16(read(2)))): for i in range(abs(i16(read(2)))):
# bounding box # bounding box
y0 = i32(read(4)); x0 = i32(read(4)) y0 = i32(read(4))
y1 = i32(read(4)); x1 = i32(read(4)) x0 = i32(read(4))
y1 = i32(read(4))
x1 = i32(read(4))
# image info # image info
info = [] info = []
@ -207,8 +212,10 @@ def _layerinfo(file):
if size: if size:
length = i32(read(4)) length = i32(read(4))
if length: if length:
mask_y = i32(read(4)); mask_x = i32(read(4)) mask_y = i32(read(4))
mask_h = i32(read(4)) - mask_y; mask_w = i32(read(4)) - mask_x mask_x = i32(read(4))
mask_h = i32(read(4)) - mask_y
mask_w = i32(read(4)) - mask_x
file.seek(length - 16, 1) file.seek(length - 16, 1)
combined += length + 4 combined += length + 4
@ -219,7 +226,8 @@ def _layerinfo(file):
length = i8(read(1)) length = i8(read(1))
if length: 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') name = read(length).decode('latin-1', 'replace')
combined += length + 1 combined += length + 1
@ -239,6 +247,7 @@ def _layerinfo(file):
return layers return layers
def _maketile(file, mode, bbox, channels): def _maketile(file, mode, bbox, channels):
tile = None tile = None

View File

@ -16,7 +16,8 @@
# * Implements the pixel access object following Access. # * Implements the pixel access object following Access.
# * Does not implement the line functions, as they don't appear to be used # * Does not implement the line functions, as they don't appear to be used
# * Taking only the tuple form, which is used from python. # * 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 from __future__ import print_function
@ -53,7 +54,8 @@ class PyAccess(object):
print (vals) print (vals)
self._post_init() self._post_init()
def _post_init(): pass def _post_init():
pass
def __setitem__(self, xy, color): def __setitem__(self, xy, color):
""" """
@ -64,7 +66,8 @@ class PyAccess(object):
:param xy: The pixel coordinate, given as (x, y). :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') if self.readonly:
raise ValueError('Attempt to putpixel a read only image')
(x, y) = self.check_xy(xy) (x, y) = self.check_xy(xy)
return self.set_pixel(x, y, color) return self.set_pixel(x, y, color)
@ -89,6 +92,7 @@ class PyAccess(object):
raise ValueError('pixel location out of range') raise ValueError('pixel location out of range')
return xy return xy
class _PyAccess32_2(PyAccess): class _PyAccess32_2(PyAccess):
""" PA, LA, stored in first and last bytes of a 32 bit word """ """ PA, LA, stored in first and last bytes of a 32 bit word """
def _post_init(self, *args, **kwargs): def _post_init(self, *args, **kwargs):
@ -104,6 +108,7 @@ class _PyAccess32_2(PyAccess):
pixel.r = min(color[0], 255) pixel.r = min(color[0], 255)
pixel.a = min(color[1], 255) pixel.a = min(color[1], 255)
class _PyAccess32_3(PyAccess): class _PyAccess32_3(PyAccess):
""" RGB and friends, stored in the first three bytes of a 32 bit word """ """ RGB and friends, stored in the first three bytes of a 32 bit word """
@ -121,6 +126,7 @@ class _PyAccess32_3(PyAccess):
pixel.g = min(color[1], 255) pixel.g = min(color[1], 255)
pixel.b = min(color[2], 255) pixel.b = min(color[2], 255)
class _PyAccess32_4(PyAccess): class _PyAccess32_4(PyAccess):
""" RGBA etc, all 4 bytes of a 32 bit word """ """ RGBA etc, all 4 bytes of a 32 bit word """
def _post_init(self, *args, **kwargs): def _post_init(self, *args, **kwargs):
@ -155,6 +161,7 @@ class _PyAccess8(PyAccess):
# tuple # tuple
self.pixels[y][x] = min(color[0], 255) self.pixels[y][x] = min(color[0], 255)
class _PyAccessI16_N(PyAccess): class _PyAccessI16_N(PyAccess):
""" I;16 access, native bitendian without conversion """ """ I;16 access, native bitendian without conversion """
def _post_init(self, *args, **kwargs): def _post_init(self, *args, **kwargs):
@ -171,6 +178,7 @@ class _PyAccessI16_N(PyAccess):
# tuple # tuple
self.pixels[y][x] = min(color[0], 65535) self.pixels[y][x] = min(color[0], 65535)
class _PyAccessI16_L(PyAccess): class _PyAccessI16_L(PyAccess):
""" I;16L access, with conversion """ """ I;16L access, with conversion """
def _post_init(self, *args, **kwargs): def _post_init(self, *args, **kwargs):
@ -190,6 +198,7 @@ class _PyAccessI16_L(PyAccess):
pixel.l = color & 0xFF pixel.l = color & 0xFF
pixel.r = color >> 8 pixel.r = color >> 8
class _PyAccessI16_B(PyAccess): class _PyAccessI16_B(PyAccess):
""" I;16B access, with conversion """ """ I;16B access, with conversion """
def _post_init(self, *args, **kwargs): def _post_init(self, *args, **kwargs):
@ -209,6 +218,7 @@ class _PyAccessI16_B(PyAccess):
pixel.l = color >> 8 pixel.l = color >> 8
pixel.r = color & 0xFF pixel.r = color & 0xFF
class _PyAccessI32_N(PyAccess): class _PyAccessI32_N(PyAccess):
""" Signed Int32 access, native endian """ """ Signed Int32 access, native endian """
def _post_init(self, *args, **kwargs): def _post_init(self, *args, **kwargs):
@ -220,6 +230,7 @@ class _PyAccessI32_N(PyAccess):
def set_pixel(self, x, y, color): def set_pixel(self, x, y, color):
self.pixels[y][x] = color self.pixels[y][x] = color
class _PyAccessI32_Swap(PyAccess): class _PyAccessI32_Swap(PyAccess):
""" I;32L/B access, with byteswapping conversion """ """ I;32L/B access, with byteswapping conversion """
def _post_init(self, *args, **kwargs): def _post_init(self, *args, **kwargs):
@ -228,7 +239,8 @@ class _PyAccessI32_Swap(PyAccess):
def reverse(self, i): def reverse(self, i):
orig = ffi.new('int *', i) orig = ffi.new('int *', i)
chars = ffi.cast('unsigned char *', orig) 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] return ffi.cast('int *', chars)[0]
def get_pixel(self, x, y): def get_pixel(self, x, y):
@ -237,6 +249,7 @@ class _PyAccessI32_Swap(PyAccess):
def set_pixel(self, x, y, color): def set_pixel(self, x, y, color):
self.pixels[y][x] = self.reverse(color) self.pixels[y][x] = self.reverse(color)
class _PyAccessF(PyAccess): class _PyAccessF(PyAccess):
""" 32 bit float access """ """ 32 bit float access """
def _post_init(self, *args, **kwargs): def _post_init(self, *args, **kwargs):
@ -286,13 +299,15 @@ else:
mode_map['I;32L'] = _PyAccessI32_Swap mode_map['I;32L'] = _PyAccessI32_Swap
mode_map['I;32B'] = _PyAccessI32_N mode_map['I;32B'] = _PyAccessI32_N
def new(img, readonly=False):
def new(img, readonly=False):
access_type = mode_map.get(img.mode, None) access_type = mode_map.get(img.mode, None)
if not access_type: if not access_type:
if DEBUG: print ("PyAccess Not Implemented: %s" % img.mode) if DEBUG:
print("PyAccess Not Implemented: %s" % img.mode)
return None return None
if DEBUG: print ("New PyAccess: %s" % img.mode) if DEBUG:
print("New PyAccess: %s" % img.mode)
return access_type(img, readonly) return access_type(img, readonly)
# End of file

View File

@ -16,6 +16,7 @@
from PIL import ContainerIO from PIL import ContainerIO
## ##
# A file object that provides read access to a given member of a TAR # A file object that provides read access to a given member of a TAR
# file. # file.

View File

@ -33,6 +33,7 @@ except ImportError:
i32 = _binary.i32le i32 = _binary.i32le
## ##
# Load texture from a Quake2 WAL texture file. # Load texture from a Quake2 WAL texture file.
# <p> # <p>

View File

@ -30,7 +30,8 @@ class WebPImageFile(ImageFile.ImageFile):
format_description = "WebP image" format_description = "WebP image"
def _open(self): 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: if icc_profile:
self.info["icc_profile"] = icc_profile self.info["icc_profile"] = icc_profile

View File

@ -24,6 +24,7 @@ _handler = None
if str != bytes: if str != bytes:
long = int long = int
## ##
# Install application-specific WMF image handler. # Install application-specific WMF image handler.
# #
@ -56,6 +57,7 @@ if hasattr(Image.core, "drawwmf"):
word = _binary.i16le word = _binary.i16le
def short(c, o=0): def short(c, o=0):
v = word(c, o) v = word(c, o)
if v >= 32768: if v >= 32768:
@ -64,6 +66,7 @@ def short(c, o=0):
dword = _binary.i32le dword = _binary.i32le
# #
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# Read WMF file # Read WMF file
@ -74,6 +77,7 @@ def _accept(prefix):
prefix[:4] == b"\x01\x00\x00\x00" prefix[:4] == b"\x01\x00\x00\x00"
) )
## ##
# Image plugin for Windows metafiles. # Image plugin for Windows metafiles.
@ -95,8 +99,10 @@ class WmfStubImageFile(ImageFile.StubImageFile):
inch = word(s, 14) inch = word(s, 14)
# get bounding box # get bounding box
x0 = short(s, 6); y0 = short(s, 8) x0 = short(s, 6)
x1 = short(s, 10); y1 = short(s, 12) y0 = short(s, 8)
x1 = short(s, 10)
y1 = short(s, 12)
# normalize size to 72 dots per inch # normalize size to 72 dots per inch
size = (x1 - x0) * 72 // inch, (y1 - y0) * 72 // inch size = (x1 - x0) * 72 // inch, (y1 - y0) * 72 // inch
@ -115,8 +121,10 @@ class WmfStubImageFile(ImageFile.StubImageFile):
# enhanced metafile # enhanced metafile
# get bounding box # get bounding box
x0 = dword(s, 8); y0 = dword(s, 12) x0 = dword(s, 8)
x1 = dword(s, 16); y1 = dword(s, 20) y0 = dword(s, 12)
x1 = dword(s, 16)
y1 = dword(s, 20)
# get frame (in 0.01 millimeter units) # get frame (in 0.01 millimeter units)
frame = dword(s, 24), dword(s, 28), dword(s, 32), dword(s, 36) frame = dword(s, 24), dword(s, 28), dword(s, 32), dword(s, 36)

View File

@ -35,9 +35,11 @@ xbm_head = re.compile(
b"[\\000-\\377]*_bits\\[\\]" b"[\\000-\\377]*_bits\\[\\]"
) )
def _accept(prefix): def _accept(prefix):
return prefix.lstrip()[:7] == b"#define" return prefix.lstrip()[:7] == b"#define"
## ##
# Image plugin for X11 bitmaps. # Image plugin for X11 bitmaps.

View File

@ -24,6 +24,7 @@ else:
def o8(i): def o8(i):
return bytes((i & 255,)) return bytes((i & 255,))
# Input, le = little endian, be = big endian # 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): def i16le(c, o=0):
@ -35,6 +36,7 @@ def i16le(c, o=0):
""" """
return i8(c[o]) | (i8(c[o+1]) << 8) return i8(c[o]) | (i8(c[o+1]) << 8)
def i32le(c, o=0): def i32le(c, o=0):
""" """
Converts a 4-bytes (32 bits) string to an integer. Converts a 4-bytes (32 bits) string to an integer.
@ -42,24 +44,33 @@ def i32le(c, o=0):
c: string containing bytes to convert c: string containing bytes to convert
o: offset of bytes to convert in string 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): 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): 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 # Output, le = little endian, be = big endian
def o16le(i): def o16le(i):
return o8(i) + o8(i >> 8) return o8(i) + o8(i >> 8)
def o32le(i): 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): def o16be(i):
return o8(i >> 8) + o8(i) return o8(i >> 8) + o8(i)
def o32be(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

View File

@ -1,3 +1,4 @@
from __future__ import print_function
import sys import sys
sys.path.insert(0, ".") sys.path.insert(0, ".")

View File

@ -155,7 +155,8 @@ class TestFileGif(PillowTestCase):
img = Image.open("Tests/images/iss634.gif") img = Image.open("Tests/images/iss634.gif")
# seek to the second frame # seek to the second frame
img.seek(img.tell() + 1) img.seek(img.tell() + 1)
# all transparent pixels should be replaced with the color from the first frame # all transparent pixels should be replaced with the color from the
# first frame
self.assertEqual(img.histogram()[img.info['transparency']], 0) self.assertEqual(img.histogram()[img.info['transparency']], 0)

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, lena from helper import unittest, PillowTestCase
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import * from helper import unittest, PillowTestCase
try: try:
import pyroma import pyroma