Merge remote-tracking branch 'upstream/master' into MspImagePlugin
Conflicts: Tests/helper.py
|
@ -5,15 +5,18 @@ notifications:
|
||||||
|
|
||||||
env: MAX_CONCURRENCY=4
|
env: MAX_CONCURRENCY=4
|
||||||
|
|
||||||
|
# Run slow PyPy* first, to give them a headstart and reduce waiting time.
|
||||||
|
# Run latest 3.x and 2.x next, to get quick compatibility results.
|
||||||
|
# Then run the remainder.
|
||||||
python:
|
python:
|
||||||
- "pypy"
|
- "pypy"
|
||||||
- "pypy3"
|
- "pypy3"
|
||||||
- 2.6
|
- 3.4
|
||||||
- 2.7
|
- 2.7
|
||||||
|
- 2.6
|
||||||
- "2.7_with_system_site_packages" # For PyQt4
|
- "2.7_with_system_site_packages" # For PyQt4
|
||||||
- 3.2
|
- 3.2
|
||||||
- 3.3
|
- 3.3
|
||||||
- 3.4
|
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- "travis_retry sudo apt-get -qq install libfreetype6-dev liblcms2-dev python-qt4 ghostscript libffi-dev libjpeg-turbo-progs cmake imagemagick"
|
- "travis_retry sudo apt-get -qq install libfreetype6-dev liblcms2-dev python-qt4 ghostscript libffi-dev libjpeg-turbo-progs cmake imagemagick"
|
||||||
|
@ -57,6 +60,7 @@ after_success:
|
||||||
- travis_retry pip install pep8 pyflakes
|
- travis_retry pip install pep8 pyflakes
|
||||||
- pep8 --statistics --count PIL/*.py
|
- pep8 --statistics --count PIL/*.py
|
||||||
- pep8 --statistics --count Tests/*.py
|
- pep8 --statistics --count Tests/*.py
|
||||||
|
- pyflakes *.py | tee >(wc -l)
|
||||||
- pyflakes PIL/*.py | tee >(wc -l)
|
- pyflakes PIL/*.py | tee >(wc -l)
|
||||||
- pyflakes Tests/*.py | tee >(wc -l)
|
- pyflakes Tests/*.py | tee >(wc -l)
|
||||||
|
|
||||||
|
|
31
CHANGES.rst
|
@ -4,13 +4,40 @@ Changelog (Pillow)
|
||||||
2.6.0 (unreleased)
|
2.6.0 (unreleased)
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
- Jpeg2k Decode/Encode Memory Leak Fix #898
|
- Use redistributable image for testing #884
|
||||||
|
[hugovk]
|
||||||
|
|
||||||
|
- Use redistributable ICC profiles for testing, skip if not available #923
|
||||||
|
[wiredfool]
|
||||||
|
|
||||||
|
- Additional documentation for JPEG info and save options #890
|
||||||
|
[wiredfool]
|
||||||
|
|
||||||
|
- Fix JPEG Encoding memory leak when exif or qtables were specified
|
||||||
|
[wiredfool]
|
||||||
|
|
||||||
|
- Image.tobytes() and Image.tostring() documentation update #916 #917
|
||||||
|
[mgedmin]
|
||||||
|
|
||||||
|
- On Windows, do not execute convert.exe without specifying path #912
|
||||||
|
[cgohlke]
|
||||||
|
|
||||||
|
- Fix msvc build error #911
|
||||||
|
[cgohlke]
|
||||||
|
|
||||||
|
- Fix for handling P + transparency -> RGBA conversions #904
|
||||||
|
[wiredfool]
|
||||||
|
|
||||||
|
- Retain alpha in ImageEnhance operations #909
|
||||||
|
[wiredfool]
|
||||||
|
|
||||||
|
- Jpeg2k Decode/encode memory leak fix #898
|
||||||
[joshware, wiredfool]
|
[joshware, wiredfool]
|
||||||
|
|
||||||
- EpsFilePlugin Speed improvements #886
|
- EpsFilePlugin Speed improvements #886
|
||||||
[wiredfool, karstenw]
|
[wiredfool, karstenw]
|
||||||
|
|
||||||
- Don't resize if already the right size.
|
- Don't resize if already the right size #892
|
||||||
[radarhere]
|
[radarhere]
|
||||||
|
|
||||||
- Fix for reading multipage TIFFs #885
|
- Fix for reading multipage TIFFs #885
|
||||||
|
|
|
@ -7,7 +7,7 @@ Send a pull request. We'll generally want documentation and [tests](Tests/README
|
||||||
- Fork the repo
|
- Fork the repo
|
||||||
- Make a branch
|
- Make a branch
|
||||||
- Add your changes + Tests
|
- Add your changes + Tests
|
||||||
- Run the test suite. Try to run on both Python 2.x and 3.x, or you'll get tripped up. You can enable [Travis CI on your repo](https://travis-ci.org/profile/) to catch test failures prior to the pull request.
|
- Run the test suite. Try to run on both Python 2.x and 3.x, or you'll get tripped up. You can enable [Travis CI on your repo](https://travis-ci.org/profile/) to catch test failures prior to the pull request, and [Coveralls](https://coveralls.io/repos/new) to see if the changed code is covered by tests.
|
||||||
- Push to your fork, and make a pull request.
|
- Push to your fork, and make a pull request.
|
||||||
|
|
||||||
A few guidelines:
|
A few guidelines:
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
@ -62,8 +64,7 @@ class BmpImageFile(ImageFile.ImageFile):
|
||||||
format = "BMP"
|
format = "BMP"
|
||||||
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))
|
||||||
|
@ -137,7 +139,7 @@ class BmpImageFile(ImageFile.ImageFile):
|
||||||
greyscale = 1
|
greyscale = 1
|
||||||
if colors == 2:
|
if colors == 2:
|
||||||
indices = (0, 255)
|
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)
|
raise IOError("Unsupported BMP Palette size (%d)" % colors)
|
||||||
else:
|
else:
|
||||||
indices = list(range(colors))
|
indices = list(range(colors))
|
||||||
|
@ -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:
|
||||||
|
@ -214,7 +217,7 @@ def _save(im, fp, filename, check=0):
|
||||||
# 1 meter == 39.3701 inches
|
# 1 meter == 39.3701 inches
|
||||||
ppm = tuple(map(lambda x: int(x * 39.3701), dpi))
|
ppm = tuple(map(lambda x: int(x * 39.3701), dpi))
|
||||||
|
|
||||||
stride = ((im.size[0]*bits+7)//8+3)&(~3)
|
stride = ((im.size[0]*bits+7)//8+3) & (~3)
|
||||||
header = 40 # or 64 for OS/2 version 2
|
header = 40 # or 64 for OS/2 version 2
|
||||||
offset = 14 + header + colors * 4
|
offset = 14 + header + colors * 4
|
||||||
image = stride * im.size[1]
|
image = stride * im.size[1]
|
||||||
|
@ -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))])
|
||||||
|
|
||||||
#
|
#
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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:
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -48,7 +49,7 @@ class ContainerIO:
|
||||||
# for current offset, and 2 for end of region. You cannot move
|
# for current offset, and 2 for end of region. You cannot move
|
||||||
# the pointer outside the defined region.
|
# the pointer outside the defined region.
|
||||||
|
|
||||||
def seek(self, offset, mode = 0):
|
def seek(self, offset, mode=0):
|
||||||
if mode == 1:
|
if mode == 1:
|
||||||
self.pos = self.pos + offset
|
self.pos = self.pos + offset
|
||||||
elif mode == 2:
|
elif mode == 2:
|
||||||
|
@ -75,7 +76,7 @@ class ContainerIO:
|
||||||
# read until end of region.
|
# read until end of region.
|
||||||
# @return An 8-bit string.
|
# @return An 8-bit string.
|
||||||
|
|
||||||
def read(self, n = 0):
|
def read(self, n=0):
|
||||||
if n:
|
if n:
|
||||||
n = min(n, self.length - self.pos)
|
n = min(n, self.length - self.pos)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -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,13 +52,14 @@ 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
|
||||||
if not sys.platform.startswith('win'):
|
if not sys.platform.startswith('win'):
|
||||||
import subprocess
|
import subprocess
|
||||||
try:
|
try:
|
||||||
gs = subprocess.Popen(['gs','--version'], stdout=subprocess.PIPE)
|
gs = subprocess.Popen(['gs', '--version'], stdout=subprocess.PIPE)
|
||||||
gs.stdout.read()
|
gs.stdout.read()
|
||||||
return True
|
return True
|
||||||
except OSError:
|
except OSError:
|
||||||
|
@ -73,16 +75,19 @@ def Ghostscript(tile, size, fp, scale=1):
|
||||||
decoder, tile, offset, data = tile[0]
|
decoder, tile, offset, data = tile[0]
|
||||||
length, bbox = data
|
length, bbox = data
|
||||||
|
|
||||||
#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])),
|
||||||
#print("Ghostscript", scale, size, orig_size, bbox, orig_bbox, res)
|
float((72.0 * size[1]) / (bbox[3]-bbox[1])))
|
||||||
|
# print("Ghostscript", scale, size, orig_size, bbox, orig_bbox, res)
|
||||||
|
|
||||||
import tempfile, os, subprocess
|
import os
|
||||||
|
import subprocess
|
||||||
|
import tempfile
|
||||||
|
|
||||||
out_fd, outfile = tempfile.mkstemp()
|
out_fd, outfile = tempfile.mkstemp()
|
||||||
os.close(out_fd)
|
os.close(out_fd)
|
||||||
|
@ -118,7 +123,8 @@ def Ghostscript(tile, size, fp, scale=1):
|
||||||
"-q", # quiet mode
|
"-q", # quiet mode
|
||||||
"-g%dx%d" % size, # set output geometry (pixels)
|
"-g%dx%d" % size, # set output geometry (pixels)
|
||||||
"-r%fx%f" % res, # set input DPI (dots per inch)
|
"-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
|
"-sDEVICE=ppmraw", # ppm driver
|
||||||
"-sOutputFile=%s" % outfile, # output file
|
"-sOutputFile=%s" % outfile, # output file
|
||||||
"-c", "%d %d translate" % (-bbox[0], -bbox[1]),
|
"-c", "%d %d translate" % (-bbox[0], -bbox[1]),
|
||||||
|
@ -133,7 +139,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:
|
||||||
|
@ -142,21 +149,26 @@ def Ghostscript(tile, size, fp, scale=1):
|
||||||
finally:
|
finally:
|
||||||
try:
|
try:
|
||||||
os.unlink(outfile)
|
os.unlink(outfile)
|
||||||
if infile_temo:
|
if infile_temp:
|
||||||
os.unlink(infile_temp)
|
os.unlink(infile_temp)
|
||||||
except: pass
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
return im
|
return im
|
||||||
|
|
||||||
|
|
||||||
class PSFile:
|
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):
|
def __init__(self, fp):
|
||||||
self.fp = fp
|
self.fp = fp
|
||||||
self.char = None
|
self.char = None
|
||||||
|
|
||||||
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 readline(self):
|
def readline(self):
|
||||||
s = self.char or b""
|
s = self.char or b""
|
||||||
self.char = None
|
self.char = None
|
||||||
|
@ -173,6 +185,7 @@ class PSFile:
|
||||||
|
|
||||||
return s.decode('latin-1')
|
return s.decode('latin-1')
|
||||||
|
|
||||||
|
|
||||||
def _accept(prefix):
|
def _accept(prefix):
|
||||||
return prefix[:4] == b"%!PS" or i32(prefix) == 0xC6D3D0C5
|
return prefix[:4] == b"%!PS" or i32(prefix) == 0xC6D3D0C5
|
||||||
|
|
||||||
|
@ -180,13 +193,14 @@ 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"""
|
||||||
|
|
||||||
format = "EPS"
|
format = "EPS"
|
||||||
format_description = "Encapsulated Postscript"
|
format_description = "Encapsulated Postscript"
|
||||||
|
|
||||||
mode_map = { 1:"L", 2:"LAB", 3:"RGB" }
|
mode_map = {1: "L", 2: "LAB", 3: "RGB"}
|
||||||
|
|
||||||
def _open(self):
|
def _open(self):
|
||||||
(length, offset) = self._find_offset(self.fp)
|
(length, offset) = self._find_offset(self.fp)
|
||||||
|
@ -200,7 +214,7 @@ class EpsImageFile(ImageFile.ImageFile):
|
||||||
else:
|
else:
|
||||||
# Python3, can use bare open command.
|
# Python3, can use bare open command.
|
||||||
fp = open(self.fp.name, "Ur", encoding='latin-1')
|
fp = open(self.fp.name, "Ur", encoding='latin-1')
|
||||||
except Exception as msg:
|
except:
|
||||||
# Expect this for bytesio/stringio
|
# Expect this for bytesio/stringio
|
||||||
fp = PSFile(self.fp)
|
fp = PSFile(self.fp)
|
||||||
|
|
||||||
|
@ -236,7 +250,7 @@ class EpsImageFile(ImageFile.ImageFile):
|
||||||
# put floating point values there anyway.
|
# put floating point values there anyway.
|
||||||
box = [int(float(s)) for s in v.split()]
|
box = [int(float(s)) for s in v.split()]
|
||||||
self.size = box[2] - box[0], box[3] - box[1]
|
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))]
|
(length, box))]
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
@ -264,7 +278,6 @@ class EpsImageFile(ImageFile.ImageFile):
|
||||||
if s[0] != "%":
|
if s[0] != "%":
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Scan for an "ImageData" descriptor
|
# Scan for an "ImageData" descriptor
|
||||||
|
|
||||||
|
@ -307,7 +320,8 @@ class EpsImageFile(ImageFile.ImageFile):
|
||||||
# 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
|
# EPS can contain binary data
|
||||||
# or start directly with latin coding
|
# 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])
|
offset = i32(s[4:8])
|
||||||
length = i32(s[8:12])
|
length = i32(s[8:12])
|
||||||
else:
|
else:
|
||||||
|
@ -324,11 +338,12 @@ class EpsImageFile(ImageFile.ImageFile):
|
||||||
self.size = self.im.size
|
self.size = self.im.size
|
||||||
self.tile = []
|
self.tile = []
|
||||||
|
|
||||||
def load_seek(self,*args,**kwargs):
|
def load_seek(self, *args, **kwargs):
|
||||||
# we can't incrementally load, so force ImageFile.parser to
|
# 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
|
pass
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -353,8 +368,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
|
||||||
|
|
||||||
|
@ -368,7 +385,7 @@ def _save(im, fp, filename, eps=1):
|
||||||
# write EPS header
|
# write EPS header
|
||||||
fp.write("%!PS-Adobe-3.0 EPSF-3.0\n")
|
fp.write("%!PS-Adobe-3.0 EPSF-3.0\n")
|
||||||
fp.write("%%Creator: PIL 0.1 EpsEncode\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("%%%%BoundingBox: 0 0 %d %d\n" % im.size)
|
||||||
fp.write("%%Pages: 1\n")
|
fp.write("%%Pages: 1\n")
|
||||||
fp.write("%%EndComments\n")
|
fp.write("%%EndComments\n")
|
||||||
|
@ -388,7 +405,7 @@ def _save(im, fp, filename, eps=1):
|
||||||
fp.write(operator[2] + "\n")
|
fp.write(operator[2] + "\n")
|
||||||
fp.flush()
|
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("\n%%%%EndBinary\n")
|
||||||
fp.write("grestore end\n")
|
fp.write("grestore end\n")
|
||||||
|
|
|
@ -25,12 +25,14 @@ i16 = _binary.i16le
|
||||||
i32 = _binary.i32le
|
i32 = _binary.i32le
|
||||||
o8 = _binary.o8
|
o8 = _binary.o8
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# decoder
|
# decoder
|
||||||
|
|
||||||
def _accept(prefix):
|
def _accept(prefix):
|
||||||
return i16(prefix[4:6]) in [0xAF11, 0xAF12]
|
return i16(prefix[4:6]) in [0xAF11, 0xAF12]
|
||||||
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# Image plugin for the FLI/FLC animation format. Use the <b>seek</b>
|
# Image plugin for the FLI/FLC animation format. Use the <b>seek</b>
|
||||||
# method to load individual frames.
|
# method to load individual frames.
|
||||||
|
@ -61,7 +63,7 @@ class FliImageFile(ImageFile.ImageFile):
|
||||||
self.info["duration"] = duration
|
self.info["duration"] = duration
|
||||||
|
|
||||||
# look for palette
|
# 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)
|
s = self.fp.read(16)
|
||||||
|
|
||||||
|
@ -80,7 +82,7 @@ class FliImageFile(ImageFile.ImageFile):
|
||||||
elif i16(s[4:6]) == 4:
|
elif i16(s[4:6]) == 4:
|
||||||
self._palette(palette, 0)
|
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))
|
self.palette = ImagePalette.raw("RGB", b"".join(palette))
|
||||||
|
|
||||||
# set things up to decode first frame
|
# set things up to decode first frame
|
||||||
|
@ -124,7 +126,7 @@ class FliImageFile(ImageFile.ImageFile):
|
||||||
framesize = i32(s)
|
framesize = i32(s)
|
||||||
|
|
||||||
self.decodermaxblock = framesize
|
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
|
self.__offset = self.__offset + framesize
|
||||||
|
|
||||||
|
|
|
@ -34,16 +34,18 @@ MODES = {
|
||||||
(0x00020000, 0x00020001, 0x00020002): ("RGB", "YCC;P"),
|
(0x00020000, 0x00020001, 0x00020002): ("RGB", "YCC;P"),
|
||||||
(0x00028000, 0x00028001, 0x00028002, 0x00027ffe): ("RGBA", "YCCA;P"),
|
(0x00028000, 0x00028001, 0x00028002, 0x00027ffe): ("RGBA", "YCCA;P"),
|
||||||
# standard RGB (NIFRGB)
|
# standard RGB (NIFRGB)
|
||||||
(0x00030000, 0x00030001, 0x00030002): ("RGB","RGB"),
|
(0x00030000, 0x00030001, 0x00030002): ("RGB", "RGB"),
|
||||||
(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.
|
||||||
|
|
||||||
|
@ -67,7 +69,7 @@ class FpxImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
self._open_index(1)
|
self._open_index(1)
|
||||||
|
|
||||||
def _open_index(self, index = 1):
|
def _open_index(self, index=1):
|
||||||
#
|
#
|
||||||
# get the Image Contents Property Set
|
# get the Image Contents Property Set
|
||||||
|
|
||||||
|
@ -95,7 +97,7 @@ class FpxImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
id = self.maxid << 16
|
id = self.maxid << 16
|
||||||
|
|
||||||
s = prop[0x2000002|id]
|
s = prop[0x2000002 | id]
|
||||||
|
|
||||||
colors = []
|
colors = []
|
||||||
for i in range(i32(s, 4)):
|
for i in range(i32(s, 4)):
|
||||||
|
@ -107,7 +109,7 @@ class FpxImageFile(ImageFile.ImageFile):
|
||||||
# load JPEG tables, if any
|
# load JPEG tables, if any
|
||||||
self.jpeg = {}
|
self.jpeg = {}
|
||||||
for i in range(256):
|
for i in range(256):
|
||||||
id = 0x3000001|(i << 16)
|
id = 0x3000001 | (i << 16)
|
||||||
if id in prop:
|
if id in prop:
|
||||||
self.jpeg[i] = prop[id]
|
self.jpeg[i] = prop[id]
|
||||||
|
|
||||||
|
@ -115,7 +117,7 @@ class FpxImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
self._open_subimage(1, self.maxid)
|
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
|
# setup tile descriptors for a given subimage
|
||||||
|
|
||||||
|
@ -159,13 +161,13 @@ class FpxImageFile(ImageFile.ImageFile):
|
||||||
compression = i32(s, i+8)
|
compression = i32(s, i+8)
|
||||||
|
|
||||||
if compression == 0:
|
if compression == 0:
|
||||||
self.tile.append(("raw", (x,y,x+xtile,y+ytile),
|
self.tile.append(("raw", (x, y, x+xtile, y+ytile),
|
||||||
i32(s, i) + 28, (self.rawmode)))
|
i32(s, i) + 28, (self.rawmode)))
|
||||||
|
|
||||||
elif compression == 1:
|
elif compression == 1:
|
||||||
|
|
||||||
# FIXME: the fill decoder is not implemented
|
# FIXME: the fill decoder is not implemented
|
||||||
self.tile.append(("fill", (x,y,x+xtile,y+ytile),
|
self.tile.append(("fill", (x, y, x+xtile, y+ytile),
|
||||||
i32(s, i) + 28, (self.rawmode, s[12:16])))
|
i32(s, i) + 28, (self.rawmode, s[12:16])))
|
||||||
|
|
||||||
elif compression == 2:
|
elif compression == 2:
|
||||||
|
@ -188,7 +190,7 @@ class FpxImageFile(ImageFile.ImageFile):
|
||||||
# The image is stored as defined by rawmode
|
# The image is stored as defined by rawmode
|
||||||
jpegmode = rawmode
|
jpegmode = rawmode
|
||||||
|
|
||||||
self.tile.append(("jpeg", (x,y,x+xtile,y+ytile),
|
self.tile.append(("jpeg", (x, y, x+xtile, y+ytile),
|
||||||
i32(s, i) + 28, (rawmode, jpegmode)))
|
i32(s, i) + 28, (rawmode, jpegmode)))
|
||||||
|
|
||||||
# FIXME: jpeg tables are tile dependent; the prefix
|
# FIXME: jpeg tables are tile dependent; the prefix
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
@ -62,7 +63,8 @@ class GdImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
self.palette = ImagePalette.raw("RGB", s[7:])
|
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.
|
# Load texture from a GD image file.
|
||||||
|
@ -73,7 +75,7 @@ class GdImageFile(ImageFile.ImageFile):
|
||||||
# @return An image instance.
|
# @return An image instance.
|
||||||
# @exception IOError If the image could not be read.
|
# @exception IOError If the image could not be read.
|
||||||
|
|
||||||
def open(fp, mode = "r"):
|
def open(fp, mode="r"):
|
||||||
|
|
||||||
if mode != "r":
|
if mode != "r":
|
||||||
raise ValueError("bad mode")
|
raise ValueError("bad mode")
|
||||||
|
|
|
@ -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.
|
||||||
|
@ -79,7 +80,7 @@ class GifImageFile(ImageFile.ImageFile):
|
||||||
# get global palette
|
# get global palette
|
||||||
self.info["background"] = i8(s[11])
|
self.info["background"] = i8(s[11])
|
||||||
# check if palette contains colour indices
|
# check if palette contains colour indices
|
||||||
p = self.fp.read(3<<bits)
|
p = self.fp.read(3 << bits)
|
||||||
for i in range(0, len(p), 3):
|
for i in range(0, len(p), 3):
|
||||||
if not (i//3 == i8(p[i]) == i8(p[i+1]) == i8(p[i+2])):
|
if not (i//3 == i8(p[i]) == i8(p[i+1]) == i8(p[i+2])):
|
||||||
p = ImagePalette.raw("RGB", p)
|
p = ImagePalette.raw("RGB", p)
|
||||||
|
@ -96,7 +97,7 @@ class GifImageFile(ImageFile.ImageFile):
|
||||||
# rewind
|
# rewind
|
||||||
self.__offset = 0
|
self.__offset = 0
|
||||||
self.dispose = None
|
self.dispose = None
|
||||||
self.dispose_extent = [0, 0, 0, 0] #x0, y0, x1, y1
|
self.dispose_extent = [0, 0, 0, 0] # x0, y0, x1, y1
|
||||||
self.__frame = -1
|
self.__frame = -1
|
||||||
self.__fp.seek(self.__rewind)
|
self.__fp.seek(self.__rewind)
|
||||||
self._prev_im = None
|
self._prev_im = None
|
||||||
|
@ -185,7 +186,7 @@ class GifImageFile(ImageFile.ImageFile):
|
||||||
if flags & 128:
|
if flags & 128:
|
||||||
bits = (flags & 7) + 1
|
bits = (flags & 7) + 1
|
||||||
self.palette =\
|
self.palette =\
|
||||||
ImagePalette.raw("RGB", self.fp.read(3<<bits))
|
ImagePalette.raw("RGB", self.fp.read(3 << bits))
|
||||||
|
|
||||||
# image data
|
# image data
|
||||||
bits = i8(self.fp.read(1))
|
bits = i8(self.fp.read(1))
|
||||||
|
@ -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
|
||||||
|
@ -475,7 +483,7 @@ def getheader(im, palette=None, info=None):
|
||||||
|
|
||||||
# add the missing amount of bytes
|
# add the missing amount of bytes
|
||||||
# the palette has to be 2<<n in size
|
# the palette has to be 2<<n in size
|
||||||
actualTargetSizeDiff = (2<<colorTableSize) - len(paletteBytes)//3
|
actualTargetSizeDiff = (2 << colorTableSize) - len(paletteBytes)//3
|
||||||
if actualTargetSizeDiff > 0:
|
if actualTargetSizeDiff > 0:
|
||||||
paletteBytes += o8(0) * 3 * actualTargetSizeDiff
|
paletteBytes += o8(0) * 3 * actualTargetSizeDiff
|
||||||
|
|
||||||
|
@ -484,13 +492,14 @@ def getheader(im, palette=None, info=None):
|
||||||
return header, usedPaletteColors
|
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.
|
"""Return a list of strings representing this image.
|
||||||
The first string is a local image header, the rest contains
|
The first string is a local image header, the rest contains
|
||||||
encoded image data."""
|
encoded image data."""
|
||||||
|
|
||||||
class collector:
|
class collector:
|
||||||
data = []
|
data = []
|
||||||
|
|
||||||
def write(self, data):
|
def write(self, data):
|
||||||
self.data.append(data)
|
self.data.append(data)
|
||||||
|
|
||||||
|
@ -510,7 +519,7 @@ def getdata(im, offset = (0, 0), **params):
|
||||||
o8(0) + # flags
|
o8(0) + # flags
|
||||||
o8(8)) # bits
|
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
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
import re
|
import re
|
||||||
from PIL._binary import o8
|
from PIL._binary import o8
|
||||||
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# File handler for GIMP's palette format.
|
# File handler for GIMP's palette format.
|
||||||
|
|
||||||
|
@ -56,7 +57,6 @@ class GimpPaletteFile:
|
||||||
|
|
||||||
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
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
@ -127,7 +133,7 @@ class IcoFile:
|
||||||
# change tile dimension to only encompass XOR image
|
# change tile dimension to only encompass XOR image
|
||||||
im.size = (im.size[0], int(im.size[1] / 2))
|
im.size = (im.size[0], int(im.size[1] / 2))
|
||||||
d, e, o, a = im.tile[0]
|
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
|
# figure out where AND mask image starts
|
||||||
mode = a[0]
|
mode = a[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
|
||||||
#
|
#
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
|
@ -46,8 +46,8 @@ SCALE = "Scale (x,y)"
|
||||||
SIZE = "Image size (x*y)"
|
SIZE = "Image size (x*y)"
|
||||||
MODE = "Image type"
|
MODE = "Image type"
|
||||||
|
|
||||||
TAGS = { COMMENT:0, DATE:0, EQUIPMENT:0, FRAMES:0, LUT:0, NAME:0,
|
TAGS = {COMMENT: 0, DATE: 0, EQUIPMENT: 0, FRAMES: 0, LUT: 0, NAME: 0,
|
||||||
SCALE:0, SIZE:0, MODE:0 }
|
SCALE: 0, SIZE: 0, MODE: 0}
|
||||||
|
|
||||||
OPEN = {
|
OPEN = {
|
||||||
# ifunc93/p3cfunc formats
|
# ifunc93/p3cfunc formats
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -155,10 +157,10 @@ class ImImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
if m:
|
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
|
# Don't know if this is the correct encoding,
|
||||||
# (I guess)
|
# but a decent guess (I guess)
|
||||||
k = k.decode('latin-1', 'replace')
|
k = k.decode('latin-1', 'replace')
|
||||||
v = v.decode('latin-1', 'replace')
|
v = v.decode('latin-1', 'replace')
|
||||||
|
|
||||||
|
@ -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")
|
||||||
|
@ -239,7 +242,7 @@ class ImImageFile(ImageFile.ImageFile):
|
||||||
# use bit decoder (if necessary)
|
# use bit decoder (if necessary)
|
||||||
bits = int(self.rawmode[2:])
|
bits = int(self.rawmode[2:])
|
||||||
if bits not in [8, 16, 32]:
|
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))]
|
(bits, 8, 3, 0, -1))]
|
||||||
return
|
return
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
@ -249,12 +252,13 @@ class ImImageFile(ImageFile.ImageFile):
|
||||||
# Old LabEye/3PC files. Would be very surprised if anyone
|
# Old LabEye/3PC files. Would be very surprised if anyone
|
||||||
# ever stumbled upon such a file ;-)
|
# ever stumbled upon such a file ;-)
|
||||||
size = self.size[0] * self.size[1]
|
size = self.size[0] * self.size[1]
|
||||||
self.tile = [("raw", (0,0)+self.size, offs, ("G", 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+size, ("R", 0, -1)),
|
||||||
("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):
|
||||||
|
|
||||||
|
@ -276,7 +280,7 @@ class ImImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
self.fp = self.__fp
|
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):
|
def tell(self):
|
||||||
|
|
||||||
|
@ -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:
|
||||||
|
@ -330,7 +335,7 @@ def _save(im, fp, filename, check=0):
|
||||||
fp.write(b"\000" * (511-fp.tell()) + b"\032")
|
fp.write(b"\000" * (511-fp.tell()) + b"\032")
|
||||||
if im.mode == "P":
|
if im.mode == "P":
|
||||||
fp.write(im.im.getpalette("RGB", "RGB;L")) # 768 bytes
|
fp.write(im.im.getpalette("RGB", "RGB;L")) # 768 bytes
|
||||||
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))])
|
||||||
|
|
||||||
#
|
#
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
|
|
24
PIL/Image.py
|
@ -34,6 +34,7 @@ import warnings
|
||||||
class DecompressionBombWarning(RuntimeWarning):
|
class DecompressionBombWarning(RuntimeWarning):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class _imaging_not_installed:
|
class _imaging_not_installed:
|
||||||
# module placeholder
|
# module placeholder
|
||||||
def __getattr__(self, id):
|
def __getattr__(self, id):
|
||||||
|
@ -530,7 +531,7 @@ class Image:
|
||||||
"""
|
"""
|
||||||
Closes the file pointer, if possible.
|
Closes the file pointer, if possible.
|
||||||
|
|
||||||
This operation will destroy the image core and release it's memory.
|
This operation will destroy the image core and release its memory.
|
||||||
The image data will be unusable afterward.
|
The image data will be unusable afterward.
|
||||||
|
|
||||||
This function is only required to close images that have not
|
This function is only required to close images that have not
|
||||||
|
@ -664,6 +665,10 @@ class Image:
|
||||||
|
|
||||||
# Declare tostring as alias to tobytes
|
# Declare tostring as alias to tobytes
|
||||||
def tostring(self, *args, **kw):
|
def tostring(self, *args, **kw):
|
||||||
|
"""Deprecated alias to tobytes.
|
||||||
|
|
||||||
|
.. deprecated:: 2.0
|
||||||
|
"""
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
'tostring() is deprecated. Please call tobytes() instead.',
|
'tostring() is deprecated. Please call tobytes() instead.',
|
||||||
DeprecationWarning,
|
DeprecationWarning,
|
||||||
|
@ -847,8 +852,9 @@ class Image:
|
||||||
t = self.info['transparency']
|
t = self.info['transparency']
|
||||||
if isinstance(t, bytes):
|
if isinstance(t, bytes):
|
||||||
# Dragons. This can't be represented by a single color
|
# Dragons. This can't be represented by a single color
|
||||||
warnings.warn('Palette images with Transparency expressed ' +
|
warnings.warn('Palette images with Transparency ' +
|
||||||
' in bytes should be converted to RGBA images')
|
' expressed in bytes should be converted ' +
|
||||||
|
'to RGBA images')
|
||||||
delete_trns = True
|
delete_trns = True
|
||||||
else:
|
else:
|
||||||
# get the new transparency color.
|
# get the new transparency color.
|
||||||
|
@ -864,11 +870,21 @@ class Image:
|
||||||
# can't just retrieve the palette number, got to do it
|
# can't just retrieve the palette number, got to do it
|
||||||
# after quantization.
|
# after quantization.
|
||||||
trns_im = trns_im.convert('RGB')
|
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':
|
elif self.mode == 'P' and mode == 'RGBA':
|
||||||
|
t = self.info['transparency']
|
||||||
delete_trns = True
|
delete_trns = True
|
||||||
|
|
||||||
|
if isinstance(t, bytes):
|
||||||
|
self.im.putpalettealphas(t)
|
||||||
|
elif isinstance(t, int):
|
||||||
|
self.im.putpalettealpha(t,0)
|
||||||
|
else:
|
||||||
|
raise ValueError("Transparency for P mode should" +
|
||||||
|
" be bytes or int")
|
||||||
|
|
||||||
|
|
||||||
if mode == "P" and palette == ADAPTIVE:
|
if mode == "P" and palette == ADAPTIVE:
|
||||||
im = self.im.quantize(colors)
|
im = self.im.quantize(colors)
|
||||||
new = self._new(im)
|
new = self._new(im)
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
## The Python Imaging Library.
|
# The Python Imaging Library.
|
||||||
## $Id$
|
# $Id$
|
||||||
|
|
||||||
## Optional color managment support, based on Kevin Cazabon's PyCMS
|
# Optional color managment support, based on Kevin Cazabon's PyCMS
|
||||||
## library.
|
# 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) 2002-2003 Kevin Cazabon
|
||||||
## Copyright (c) 2009 by Fredrik Lundh
|
# Copyright (c) 2009 by Fredrik Lundh
|
||||||
## Copyright (c) 2013 by Eric Soroos
|
# Copyright (c) 2013 by Eric Soroos
|
||||||
|
|
||||||
## See the README file for information on usage and redistribution. See
|
# See the README file for information on usage and redistribution. See
|
||||||
## below for the original description.
|
# below for the original description.
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
|
@ -184,6 +184,7 @@ class ImageCmsProfile:
|
||||||
|
|
||||||
return core.profile_tobytes(self.profile)
|
return core.profile_tobytes(self.profile)
|
||||||
|
|
||||||
|
|
||||||
class ImageCmsTransform(Image.ImagePointHandler):
|
class ImageCmsTransform(Image.ImagePointHandler):
|
||||||
|
|
||||||
# Transform. This can be used with the procedural API, or with the
|
# 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'].
|
# Will return the output profile in the output.info['icc_profile'].
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, input, output, input_mode, output_mode,
|
def __init__(self, input, output, input_mode, output_mode,
|
||||||
intent=INTENT_PERCEPTUAL, proof=None,
|
intent=INTENT_PERCEPTUAL, proof=None,
|
||||||
proof_intent=INTENT_ABSOLUTE_COLORIMETRIC, flags=0):
|
proof_intent=INTENT_ABSOLUTE_COLORIMETRIC, flags=0):
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -40,6 +40,7 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
warnings = None
|
warnings = None
|
||||||
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# A simple 2D drawing interface for PIL images.
|
# A simple 2D drawing interface for PIL images.
|
||||||
# <p>
|
# <p>
|
||||||
|
@ -61,7 +62,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 +281,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 +304,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 +328,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.
|
||||||
#
|
#
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -47,8 +47,11 @@ class Color(_Enhance):
|
||||||
"""
|
"""
|
||||||
def __init__(self, image):
|
def __init__(self, image):
|
||||||
self.image = image
|
self.image = image
|
||||||
self.degenerate = image.convert("L").convert(image.mode)
|
self.intermediate_mode = 'L'
|
||||||
|
if 'A' in image.getbands():
|
||||||
|
self.intermediate_mode = 'LA'
|
||||||
|
|
||||||
|
self.degenerate = image.convert(self.intermediate_mode).convert(image.mode)
|
||||||
|
|
||||||
class Contrast(_Enhance):
|
class Contrast(_Enhance):
|
||||||
"""Adjust image contrast.
|
"""Adjust image contrast.
|
||||||
|
@ -62,6 +65,9 @@ class Contrast(_Enhance):
|
||||||
mean = int(ImageStat.Stat(image.convert("L")).mean[0] + 0.5)
|
mean = int(ImageStat.Stat(image.convert("L")).mean[0] + 0.5)
|
||||||
self.degenerate = Image.new("L", image.size, mean).convert(image.mode)
|
self.degenerate = Image.new("L", image.size, mean).convert(image.mode)
|
||||||
|
|
||||||
|
if 'A' in image.getbands():
|
||||||
|
self.degenerate.putalpha(image.split()[-1])
|
||||||
|
|
||||||
|
|
||||||
class Brightness(_Enhance):
|
class Brightness(_Enhance):
|
||||||
"""Adjust image brightness.
|
"""Adjust image brightness.
|
||||||
|
@ -74,6 +80,9 @@ class Brightness(_Enhance):
|
||||||
self.image = image
|
self.image = image
|
||||||
self.degenerate = Image.new(image.mode, image.size, 0)
|
self.degenerate = Image.new(image.mode, image.size, 0)
|
||||||
|
|
||||||
|
if 'A' in image.getbands():
|
||||||
|
self.degenerate.putalpha(image.split()[-1])
|
||||||
|
|
||||||
|
|
||||||
class Sharpness(_Enhance):
|
class Sharpness(_Enhance):
|
||||||
"""Adjust image sharpness.
|
"""Adjust image sharpness.
|
||||||
|
@ -85,3 +94,6 @@ class Sharpness(_Enhance):
|
||||||
def __init__(self, image):
|
def __init__(self, image):
|
||||||
self.image = image
|
self.image = image
|
||||||
self.degenerate = image.filter(ImageFilter.SMOOTH)
|
self.degenerate = image.filter(ImageFilter.SMOOTH)
|
||||||
|
|
||||||
|
if 'A' in image.getbands():
|
||||||
|
self.degenerate.putalpha(image.split()[-1])
|
||||||
|
|
|
@ -29,8 +29,10 @@
|
||||||
|
|
||||||
from PIL import Image
|
from PIL 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)
|
||||||
|
@ -436,6 +443,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):
|
||||||
|
@ -452,7 +460,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
|
||||||
|
@ -487,7 +495,8 @@ def _save(im, fp, tile, bufsize=0):
|
||||||
e.cleanup()
|
e.cleanup()
|
||||||
try:
|
try:
|
||||||
fp.flush()
|
fp.flush()
|
||||||
except: pass
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def _safe_read(fp, size):
|
def _safe_read(fp, size):
|
||||||
|
|
|
@ -43,7 +43,7 @@ class Kernel(Filter):
|
||||||
def __init__(self, size, kernel, scale=None, offset=0):
|
def __init__(self, size, kernel, scale=None, offset=0):
|
||||||
if scale is None:
|
if scale is None:
|
||||||
# default scale is sum of kernel
|
# 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):
|
if size[0] * size[1] != len(kernel):
|
||||||
raise ValueError("not enough coefficients in kernel")
|
raise ValueError("not enough coefficients in kernel")
|
||||||
self.filterargs = size, scale, offset, kernel
|
self.filterargs = size, scale, offset, kernel
|
||||||
|
@ -162,7 +162,8 @@ class UnsharpMask(Filter):
|
||||||
See Wikipedia's entry on `digital unsharp masking`_ for an explanation of
|
See Wikipedia's entry on `digital unsharp masking`_ for an explanation of
|
||||||
the parameters.
|
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"
|
name = "UnsharpMask"
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,9 @@
|
||||||
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
|
import sys
|
||||||
|
if sys.platform != "win32":
|
||||||
|
raise ImportError("ImageGrab is Windows only")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# built-in driver (1.1.3 and later)
|
# built-in driver (1.1.3 and later)
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
@ -273,7 +278,7 @@ def fit(image, size, method=Image.NEAREST, bleed=0.0, centering=(0.5, 0.5)):
|
||||||
centering = [centering[0], centering[1]]
|
centering = [centering[0], centering[1]]
|
||||||
|
|
||||||
if centering[0] > 1.0 or centering[0] < 0.0:
|
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:
|
if centering[1] > 1.0 or centering[1] < 0.0:
|
||||||
centering[1] = 0.50
|
centering[1] = 0.50
|
||||||
|
|
||||||
|
@ -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])"""
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ try:
|
||||||
except:
|
except:
|
||||||
from PyQt4.QtGui import QImage, qRgba
|
from PyQt4.QtGui import QImage, qRgba
|
||||||
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# (Internal) Turns an RGB color into a Qt compatible color integer.
|
# (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.
|
# into a negative integer with the same bitpattern.
|
||||||
return (qRgba(r, g, b, a) & 0xffffffff)
|
return (qRgba(r, g, b, a) & 0xffffffff)
|
||||||
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# An PIL image wrapper for Qt. This is a subclass of PyQt4's QImage
|
# An PIL image wrapper for Qt. This is a subclass of PyQt4's QImage
|
||||||
# class.
|
# class.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -21,13 +21,14 @@
|
||||||
# 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
|
||||||
|
|
||||||
|
|
||||||
class Stat:
|
class Stat:
|
||||||
|
|
||||||
def __init__(self, image_or_list, mask = None):
|
def __init__(self, image_or_list, mask=None):
|
||||||
try:
|
try:
|
||||||
if mask:
|
if mask:
|
||||||
self.h = image_or_list.histogram(mask)
|
self.h = image_or_list.histogram(mask)
|
||||||
|
@ -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"
|
||||||
|
|
||||||
|
|
|
@ -40,17 +40,19 @@ 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:
|
||||||
try:
|
try:
|
||||||
im = Image.new("1", (1,1))
|
im = Image.new("1", (1, 1))
|
||||||
tkinter.BitmapImage(data="PIL:%d" % im.im.id)
|
tkinter.BitmapImage(data="PIL:%d" % im.im.id)
|
||||||
_pilbitmap_ok = 1
|
_pilbitmap_ok = 1
|
||||||
except tkinter.TclError:
|
except tkinter.TclError:
|
||||||
_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.
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -23,23 +23,26 @@ from PIL import Image
|
||||||
|
|
||||||
class HDC:
|
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`
|
:py:meth:`~PIL.ImageWin.Dib.draw` and :py:meth:`~PIL.ImageWin.Dib.expose`
|
||||||
methods.
|
methods.
|
||||||
"""
|
"""
|
||||||
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 an HWND integer. The resulting object can be passed to the
|
||||||
:py:meth:`~PIL.ImageWin.Dib.draw` and :py:meth:`~PIL.ImageWin.Dib.expose`
|
:py:meth:`~PIL.ImageWin.Dib.draw` and :py:meth:`~PIL.ImageWin.Dib.expose`
|
||||||
methods, instead of a DC.
|
methods, instead of a DC.
|
||||||
"""
|
"""
|
||||||
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,13 +82,12 @@ 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.
|
||||||
|
|
||||||
:param handle: Device context (HDC), cast to a Python integer, or a HDC
|
:param handle: Device context (HDC), cast to a Python integer, or an
|
||||||
or HWND instance. In PythonWin, you can use the
|
HDC or HWND instance. In PythonWin, you can use the
|
||||||
:py:meth:`CDC.GetHandleAttrib` to get a suitable handle.
|
:py:meth:`CDC.GetHandleAttrib` to get a suitable handle.
|
||||||
"""
|
"""
|
||||||
if isinstance(handle, HWND):
|
if isinstance(handle, HWND):
|
||||||
|
@ -109,7 +111,7 @@ class Dib:
|
||||||
necessary.
|
necessary.
|
||||||
"""
|
"""
|
||||||
if not src:
|
if not src:
|
||||||
src = (0,0) + self.size
|
src = (0, 0) + self.size
|
||||||
if isinstance(handle, HWND):
|
if isinstance(handle, HWND):
|
||||||
dc = self.image.getdc(handle)
|
dc = self.image.getdc(handle)
|
||||||
try:
|
try:
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ from PIL import Image, ImageFile
|
||||||
|
|
||||||
field = re.compile(br"([a-z]*) ([^ \r\n]*)")
|
field = re.compile(br"([a-z]*) ([^ \r\n]*)")
|
||||||
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# Image plugin for IM Tools images.
|
# 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
|
# Quick rejection: if there's not a 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)
|
||||||
|
|
||||||
|
@ -54,7 +55,7 @@ class ImtImageFile(ImageFile.ImageFile):
|
||||||
if s == b'\x0C':
|
if s == b'\x0C':
|
||||||
|
|
||||||
# image data begins
|
# image data begins
|
||||||
self.tile = [("raw", (0,0)+self.size,
|
self.tile = [("raw", (0, 0)+self.size,
|
||||||
self.fp.tell(),
|
self.fp.tell(),
|
||||||
(self.mode, 0, 1))]
|
(self.mode, 0, 1))]
|
||||||
|
|
||||||
|
@ -73,7 +74,7 @@ class ImtImageFile(ImageFile.ImageFile):
|
||||||
m = field.match(s)
|
m = field.match(s)
|
||||||
if not m:
|
if not m:
|
||||||
break
|
break
|
||||||
k, v = m.group(1,2)
|
k, v = m.group(1, 2)
|
||||||
if k == "width":
|
if k == "width":
|
||||||
xsize = int(v)
|
xsize = int(v)
|
||||||
self.size = xsize, ysize
|
self.size = xsize, ysize
|
||||||
|
|
|
@ -115,7 +115,8 @@ def APP(self, marker):
|
||||||
elif marker == 0xFFE2 and s[:4] == b"MPF\0":
|
elif marker == 0xFFE2 and s[:4] == b"MPF\0":
|
||||||
# extract MPO information
|
# extract MPO information
|
||||||
self.info["mp"] = s[4:]
|
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
|
self.info["mpoffset"] = self.fp.tell() - n + 4
|
||||||
|
|
||||||
|
|
||||||
|
@ -321,7 +322,8 @@ class JpegImageFile(ImageFile.ImageFile):
|
||||||
rawmode = self.mode
|
rawmode = self.mode
|
||||||
if self.mode == "CMYK":
|
if self.mode == "CMYK":
|
||||||
rawmode = "CMYK;I" # assume adobe conventions
|
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()
|
# self.__offset = self.fp.tell()
|
||||||
break
|
break
|
||||||
s = self.fp.read(1)
|
s = self.fp.read(1)
|
||||||
|
@ -472,14 +474,18 @@ def _getmp(self):
|
||||||
for entrynum in range(0, quant):
|
for entrynum in range(0, quant):
|
||||||
rawmpentry = mp[0xB002][entrynum * 16:(entrynum + 1) * 16]
|
rawmpentry = mp[0xB002][entrynum * 16:(entrynum + 1) * 16]
|
||||||
unpackedentry = unpack('{0}LLLHH'.format(endianness), rawmpentry)
|
unpackedentry = unpack('{0}LLLHH'.format(endianness), rawmpentry)
|
||||||
labels = ('Attribute', 'Size', 'DataOffset', 'EntryNo1', 'EntryNo2')
|
labels = ('Attribute', 'Size', 'DataOffset', 'EntryNo1',
|
||||||
|
'EntryNo2')
|
||||||
mpentry = dict(zip(labels, unpackedentry))
|
mpentry = dict(zip(labels, unpackedentry))
|
||||||
mpentryattr = {
|
mpentryattr = {
|
||||||
'DependentParentImageFlag': bool(mpentry['Attribute'] & (1<<31)),
|
'DependentParentImageFlag': bool(mpentry['Attribute'] &
|
||||||
'DependentChildImageFlag': bool(mpentry['Attribute'] & (1<<30)),
|
(1 << 31)),
|
||||||
'RepresentativeImageFlag': bool(mpentry['Attribute'] & (1<<29)),
|
'DependentChildImageFlag': bool(mpentry['Attribute'] &
|
||||||
'Reserved': (mpentry['Attribute'] & (3<<27)) >> 27,
|
(1 << 30)),
|
||||||
'ImageDataFormat': (mpentry['Attribute'] & (7<<24)) >> 24,
|
'RepresentativeImageFlag': bool(mpentry['Attribute'] &
|
||||||
|
(1 << 29)),
|
||||||
|
'Reserved': (mpentry['Attribute'] & (3 << 27)) >> 27,
|
||||||
|
'ImageDataFormat': (mpentry['Attribute'] & (7 << 24)) >> 24,
|
||||||
'MPType': mpentry['Attribute'] & 0x00FFFFFF
|
'MPType': mpentry['Attribute'] & 0x00FFFFFF
|
||||||
}
|
}
|
||||||
if mpentryattr['ImageDataFormat'] == 0:
|
if mpentryattr['ImageDataFormat'] == 0:
|
||||||
|
@ -530,8 +536,7 @@ zigzag_index = ( 0, 1, 5, 6, 14, 15, 27, 28,
|
||||||
21, 34, 37, 47, 50, 56, 59, 61,
|
21, 34, 37, 47, 50, 56, 59, 61,
|
||||||
35, 36, 48, 49, 57, 58, 62, 63)
|
35, 36, 48, 49, 57, 58, 62, 63)
|
||||||
|
|
||||||
samplings = {
|
samplings = {(1, 1, 1, 1, 1, 1): 0,
|
||||||
(1, 1, 1, 1, 1, 1): 0,
|
|
||||||
(2, 1, 1, 1, 1, 1): 1,
|
(2, 1, 1, 1, 1, 1): 1,
|
||||||
(2, 2, 1, 1, 1, 1): 2,
|
(2, 2, 1, 1, 1, 1): 2,
|
||||||
}
|
}
|
||||||
|
@ -598,7 +603,8 @@ def _save(im, fp, filename):
|
||||||
subsampling = 2
|
subsampling = 2
|
||||||
elif subsampling == "keep":
|
elif subsampling == "keep":
|
||||||
if im.format != "JPEG":
|
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)
|
subsampling = get_sampling(im)
|
||||||
|
|
||||||
def validate_qtables(qtables):
|
def validate_qtables(qtables):
|
||||||
|
@ -632,7 +638,8 @@ def _save(im, fp, filename):
|
||||||
|
|
||||||
if qtables == "keep":
|
if qtables == "keep":
|
||||||
if im.format != "JPEG":
|
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 = getattr(im, "quantization", None)
|
||||||
qtables = validate_qtables(qtables)
|
qtables = validate_qtables(qtables)
|
||||||
|
|
||||||
|
@ -650,7 +657,8 @@ def _save(im, fp, filename):
|
||||||
i = 1
|
i = 1
|
||||||
for marker in markers:
|
for marker in markers:
|
||||||
size = struct.pack(">H", 2 + ICC_OVERHEAD_LEN + len(marker))
|
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
|
i += 1
|
||||||
|
|
||||||
# get keyword arguments
|
# get keyword arguments
|
||||||
|
|
|
@ -48,8 +48,8 @@ You can get the quantization tables of a JPEG with::
|
||||||
|
|
||||||
im.quantization
|
im.quantization
|
||||||
|
|
||||||
This will return a dict with a number of arrays. You can pass this dict directly
|
This will return a dict with a number of arrays. You can pass this dict
|
||||||
as the qtables argument when saving a JPEG.
|
directly as the qtables argument when saving a JPEG.
|
||||||
|
|
||||||
The tables format between im.quantization and quantization in presets differ in
|
The tables format between im.quantization and quantization in presets differ in
|
||||||
3 ways:
|
3 ways:
|
||||||
|
|
|
@ -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")
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
@ -79,7 +82,7 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile):
|
||||||
|
|
||||||
# Note that since MPO shares a factory with JPEG, we do not need to do a
|
# Note that since MPO shares a factory with JPEG, we do not need to do a
|
||||||
# separate registration for it here.
|
# 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_save("MPO", _save)
|
||||||
|
|
||||||
Image.register_extension("MPO", ".mpo")
|
Image.register_extension("MPO", ".mpo")
|
||||||
|
|
|
@ -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).
|
||||||
|
@ -57,15 +59,16 @@ class MspImageFile(ImageFile.ImageFile):
|
||||||
self.size = i16(s[4:]), i16(s[6:])
|
self.size = i16(s[4:]), i16(s[6:])
|
||||||
|
|
||||||
if s[:4] == b"DanM":
|
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:
|
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)
|
# write MSP files (uncompressed only)
|
||||||
|
|
||||||
o16 = _binary.o16le
|
o16 = _binary.o16le
|
||||||
|
|
||||||
|
|
||||||
def _save(im, fp, filename):
|
def _save(im, fp, filename):
|
||||||
|
|
||||||
if im.mode != "1":
|
if im.mode != "1":
|
||||||
|
@ -90,7 +93,7 @@ def _save(im, fp, filename):
|
||||||
fp.write(o16(h))
|
fp.write(o16(h))
|
||||||
|
|
||||||
# image body
|
# 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
|
# registry
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
@ -34,7 +35,7 @@ class PSDraw:
|
||||||
fp = sys.stdout
|
fp = sys.stdout
|
||||||
self.fp = fp
|
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.)"""
|
"""Set up printing of a document. (Write Postscript DSC header.)"""
|
||||||
# FIXME: incomplete
|
# FIXME: incomplete
|
||||||
self.fp.write("%!PS-Adobe-3.0\n"
|
self.fp.write("%!PS-Adobe-3.0\n"
|
||||||
|
@ -42,7 +43,7 @@ class PSDraw:
|
||||||
"/showpage { } def\n"
|
"/showpage { } def\n"
|
||||||
"%%EndComments\n"
|
"%%EndComments\n"
|
||||||
"%%BeginDocument\n")
|
"%%BeginDocument\n")
|
||||||
#self.fp.write(ERROR_PS) # debugging!
|
# self.fp.write(ERROR_PS) # debugging!
|
||||||
self.fp.write(EDROFF_PS)
|
self.fp.write(EDROFF_PS)
|
||||||
self.fp.write(VDI_PS)
|
self.fp.write(VDI_PS)
|
||||||
self.fp.write("%%EndProlog\n")
|
self.fp.write("%%EndProlog\n")
|
||||||
|
@ -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
|
||||||
|
@ -112,7 +113,7 @@ class PSDraw:
|
||||||
xy = xy + (text,)
|
xy = xy + (text,)
|
||||||
self.fp.write("%d %d M (%s) S\n" % xy)
|
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."""
|
"""Draw a PIL image, centered in the given box."""
|
||||||
# default resolution depends on mode
|
# default resolution depends on mode
|
||||||
if not dpi:
|
if not dpi:
|
||||||
|
@ -127,9 +128,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))
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
@ -49,7 +50,7 @@ class PcdImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
self.mode = "RGB"
|
self.mode = "RGB"
|
||||||
self.size = 768, 512 # FIXME: not correct for rotated images!
|
self.size = 768, 512 # FIXME: not correct for rotated images!
|
||||||
self.tile = [("pcd", (0,0)+self.size, 96*2048, None)]
|
self.tile = [("pcd", (0, 0)+self.size, 96*2048, None)]
|
||||||
|
|
||||||
def draft(self, mode, size):
|
def draft(self, mode, size):
|
||||||
|
|
||||||
|
@ -60,7 +61,7 @@ class PcdImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
if size:
|
if size:
|
||||||
scale = max(self.size[0] / size[0], self.size[1] / size[1])
|
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:
|
if scale >= s:
|
||||||
break
|
break
|
||||||
# e = e[0], e[1], (e[2]-e[0]+s-1)/s+e[0], (e[3]-e[1]+s-1)/s+e[1]
|
# e = e[0], e[1], (e[2]-e[0]+s-1)/s+e[0], (e[3]-e[1]+s-1)/s+e[1]
|
||||||
|
|
|
@ -25,15 +25,15 @@ from PIL import _binary
|
||||||
|
|
||||||
PCF_MAGIC = 0x70636601 # "\x01fcp"
|
PCF_MAGIC = 0x70636601 # "\x01fcp"
|
||||||
|
|
||||||
PCF_PROPERTIES = (1<<0)
|
PCF_PROPERTIES = (1 << 0)
|
||||||
PCF_ACCELERATORS = (1<<1)
|
PCF_ACCELERATORS = (1 << 1)
|
||||||
PCF_METRICS = (1<<2)
|
PCF_METRICS = (1 << 2)
|
||||||
PCF_BITMAPS = (1<<3)
|
PCF_BITMAPS = (1 << 3)
|
||||||
PCF_INK_METRICS = (1<<4)
|
PCF_INK_METRICS = (1 << 4)
|
||||||
PCF_BDF_ENCODINGS = (1<<5)
|
PCF_BDF_ENCODINGS = (1 << 5)
|
||||||
PCF_SWIDTHS = (1<<6)
|
PCF_SWIDTHS = (1 << 6)
|
||||||
PCF_GLYPH_NAMES = (1<<7)
|
PCF_GLYPH_NAMES = (1 << 7)
|
||||||
PCF_BDF_ACCELERATORS = (1<<8)
|
PCF_BDF_ACCELERATORS = (1 << 8)
|
||||||
|
|
||||||
BYTES_PER_ROW = [
|
BYTES_PER_ROW = [
|
||||||
lambda bits: ((bits+7) >> 3),
|
lambda bits: ((bits+7) >> 3),
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
@ -52,23 +54,22 @@ class PcxImageFile(ImageFile.ImageFile):
|
||||||
raise SyntaxError("not a PCX file")
|
raise SyntaxError("not a PCX file")
|
||||||
|
|
||||||
# image
|
# 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]:
|
if bbox[2] <= bbox[0] or bbox[3] <= bbox[1]:
|
||||||
raise SyntaxError("bad PCX image size")
|
raise SyntaxError("bad PCX image size")
|
||||||
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])
|
||||||
planes = i8(s[65])
|
planes = i8(s[65])
|
||||||
stride = i16(s,66)
|
stride = i16(s, 66)
|
||||||
if Image.DEBUG:
|
if Image.DEBUG:
|
||||||
print ("PCX version %s, bits %s, planes %s, stride %s" %
|
print ("PCX version %s, bits %s, planes %s, stride %s" %
|
||||||
(version, bits, planes, stride))
|
(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:
|
if bits == 1 and planes == 1:
|
||||||
mode = rawmode = "1"
|
mode = rawmode = "1"
|
||||||
|
@ -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))
|
||||||
|
@ -163,7 +164,7 @@ def _save(im, fp, filename, check=0):
|
||||||
|
|
||||||
assert fp.tell() == 128
|
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))])
|
(rawmode, bits*planes))])
|
||||||
|
|
||||||
if im.mode == "P":
|
if im.mode == "P":
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
@ -57,7 +58,7 @@ class PixarImageFile(ImageFile.ImageFile):
|
||||||
# FIXME: to be continued...
|
# FIXME: to be continued...
|
||||||
|
|
||||||
# create tile descriptor (assuming "dumped")
|
# 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))]
|
||||||
|
|
||||||
#
|
#
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
|
|
|
@ -56,22 +56,23 @@ _MODES = {
|
||||||
(2, 0): ("L", "L;2"),
|
(2, 0): ("L", "L;2"),
|
||||||
(4, 0): ("L", "L;4"),
|
(4, 0): ("L", "L;4"),
|
||||||
(8, 0): ("L", "L"),
|
(8, 0): ("L", "L"),
|
||||||
(16,0): ("I", "I;16B"),
|
(16, 0): ("I", "I;16B"),
|
||||||
(8, 2): ("RGB", "RGB"),
|
(8, 2): ("RGB", "RGB"),
|
||||||
(16,2): ("RGB", "RGB;16B"),
|
(16, 2): ("RGB", "RGB;16B"),
|
||||||
(1, 3): ("P", "P;1"),
|
(1, 3): ("P", "P;1"),
|
||||||
(2, 3): ("P", "P;2"),
|
(2, 3): ("P", "P;2"),
|
||||||
(4, 3): ("P", "P;4"),
|
(4, 3): ("P", "P;4"),
|
||||||
(8, 3): ("P", "P"),
|
(8, 3): ("P", "P"),
|
||||||
(8, 4): ("LA", "LA"),
|
(8, 4): ("LA", "LA"),
|
||||||
(16,4): ("RGBA", "LA;16B"), # LA;16B->LA not yet available
|
(16, 4): ("RGBA", "LA;16B"), # LA;16B->LA not yet available
|
||||||
(8, 6): ("RGBA", "RGBA"),
|
(8, 6): ("RGBA", "RGBA"),
|
||||||
(16,6): ("RGBA", "RGBA;16B"),
|
(16, 6): ("RGBA", "RGBA;16B"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
_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):
|
||||||
|
@ -131,7 +132,7 @@ class ChunkStream:
|
||||||
|
|
||||||
self.fp.read(4)
|
self.fp.read(4)
|
||||||
|
|
||||||
def verify(self, endchunk = b"IEND"):
|
def verify(self, endchunk=b"IEND"):
|
||||||
|
|
||||||
# Simple approach; just calculate checksum for all remaining
|
# Simple approach; just calculate checksum for all remaining
|
||||||
# blocks. Must be called directly after open.
|
# blocks. Must be called directly after open.
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -218,7 +224,7 @@ class PngStream(ChunkStream):
|
||||||
# local copies of Image attributes
|
# local copies of Image attributes
|
||||||
self.im_info = {}
|
self.im_info = {}
|
||||||
self.im_text = {}
|
self.im_text = {}
|
||||||
self.im_size = (0,0)
|
self.im_size = (0, 0)
|
||||||
self.im_mode = None
|
self.im_mode = None
|
||||||
self.im_tile = None
|
self.im_tile = None
|
||||||
self.im_palette = None
|
self.im_palette = None
|
||||||
|
@ -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:
|
||||||
|
@ -264,7 +271,7 @@ class PngStream(ChunkStream):
|
||||||
def chunk_IDAT(self, pos, length):
|
def chunk_IDAT(self, pos, length):
|
||||||
|
|
||||||
# image data
|
# 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
|
self.im_idat = length
|
||||||
raise EOFError
|
raise EOFError
|
||||||
|
|
||||||
|
@ -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"
|
||||||
|
|
||||||
|
@ -538,9 +549,10 @@ _OUTMODES = {
|
||||||
"P;4": ("P;4", b'\x04\x03'),
|
"P;4": ("P;4", b'\x04\x03'),
|
||||||
"P": ("P", b'\x08\x03'),
|
"P": ("P", b'\x08\x03'),
|
||||||
"RGB": ("RGB", b'\x08\x02'),
|
"RGB": ("RGB", b'\x08\x02'),
|
||||||
"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)
|
||||||
|
|
||||||
|
|
|
@ -27,12 +27,13 @@ from PIL import Image, ImageFile
|
||||||
b_whitespace = string.whitespace
|
b_whitespace = string.whitespace
|
||||||
try:
|
try:
|
||||||
import locale
|
import locale
|
||||||
locale_lang,locale_enc = locale.getlocale()
|
locale_lang, locale_enc = locale.getlocale()
|
||||||
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:
|
||||||
b_whitespace = b_whitespace.encode('ascii','ignore')
|
pass
|
||||||
|
b_whitespace = b_whitespace.encode('ascii', 'ignore')
|
||||||
|
|
||||||
MODES = {
|
MODES = {
|
||||||
# standard
|
# standard
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
@ -58,7 +61,7 @@ class PpmImageFile(ImageFile.ImageFile):
|
||||||
format = "PPM"
|
format = "PPM"
|
||||||
format_description = "Pbmplus image"
|
format_description = "Pbmplus image"
|
||||||
|
|
||||||
def _token(self, s = b""):
|
def _token(self, s=b""):
|
||||||
while True: # read until next whitespace
|
while True: # read until next whitespace
|
||||||
c = self.fp.read(1)
|
c = self.fp.read(1)
|
||||||
if not c or c in b_whitespace:
|
if not c or c in b_whitespace:
|
||||||
|
@ -104,12 +107,12 @@ class PpmImageFile(ImageFile.ImageFile):
|
||||||
# maxgrey
|
# maxgrey
|
||||||
if s > 255:
|
if s > 255:
|
||||||
if not mode == 'L':
|
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:
|
if s < 2**16:
|
||||||
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
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -152,7 +156,7 @@ def _save(im, fp, filename):
|
||||||
fp.write(b"65535\n")
|
fp.write(b"65535\n")
|
||||||
elif rawmode == "I;32B":
|
elif rawmode == "I;32B":
|
||||||
fp.write(b"2147483648\n")
|
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
|
# ALTERNATIVE: save via builtin debug function
|
||||||
# im._dump(filename)
|
# im._dump(filename)
|
||||||
|
|
|
@ -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
|
||||||
|
|
107
PIL/PyAccess.py
|
@ -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
|
||||||
|
@ -40,7 +41,7 @@ ffi.cdef(defs)
|
||||||
|
|
||||||
class PyAccess(object):
|
class PyAccess(object):
|
||||||
|
|
||||||
def __init__(self, img, readonly = False):
|
def __init__(self, img, readonly=False):
|
||||||
vals = dict(img.im.unsafe_ptrs)
|
vals = dict(img.im.unsafe_ptrs)
|
||||||
self.readonly = readonly
|
self.readonly = readonly
|
||||||
self.image8 = ffi.cast('unsigned char **', vals['image8'])
|
self.image8 = ffi.cast('unsigned char **', vals['image8'])
|
||||||
|
@ -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,9 +66,10 @@ 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:
|
||||||
(x,y) = self.check_xy(xy)
|
raise ValueError('Attempt to putpixel a read only image')
|
||||||
return self.set_pixel(x,y,color)
|
(x, y) = self.check_xy(xy)
|
||||||
|
return self.set_pixel(x, y, color)
|
||||||
|
|
||||||
def __getitem__(self, xy):
|
def __getitem__(self, xy):
|
||||||
"""
|
"""
|
||||||
|
@ -77,32 +80,34 @@ class PyAccess(object):
|
||||||
:param xy: The pixel coordinate, given as (x, y).
|
:param xy: The pixel coordinate, given as (x, y).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
(x,y) = self.check_xy(xy)
|
(x, y) = self.check_xy(xy)
|
||||||
return self.get_pixel(x,y)
|
return self.get_pixel(x, y)
|
||||||
|
|
||||||
putpixel = __setitem__
|
putpixel = __setitem__
|
||||||
getpixel = __getitem__
|
getpixel = __getitem__
|
||||||
|
|
||||||
def check_xy(self, xy):
|
def check_xy(self, xy):
|
||||||
(x,y) = xy
|
(x, y) = xy
|
||||||
if not (0 <= x < self.xsize and 0 <= y < self.ysize):
|
if not (0 <= x < self.xsize and 0 <= y < self.ysize):
|
||||||
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):
|
||||||
self.pixels = ffi.cast("struct Pixel_RGBA **", self.image32)
|
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]
|
pixel = self.pixels[y][x]
|
||||||
return (pixel.r, pixel.a)
|
return (pixel.r, pixel.a)
|
||||||
|
|
||||||
def set_pixel(self, x,y, color):
|
def set_pixel(self, x, y, color):
|
||||||
pixel = self.pixels[y][x]
|
pixel = self.pixels[y][x]
|
||||||
# tuple
|
# tuple
|
||||||
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 """
|
||||||
|
@ -110,33 +115,34 @@ class _PyAccess32_3(PyAccess):
|
||||||
def _post_init(self, *args, **kwargs):
|
def _post_init(self, *args, **kwargs):
|
||||||
self.pixels = ffi.cast("struct Pixel_RGBA **", self.image32)
|
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]
|
pixel = self.pixels[y][x]
|
||||||
return (pixel.r, pixel.g, pixel.b)
|
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]
|
pixel = self.pixels[y][x]
|
||||||
# tuple
|
# tuple
|
||||||
pixel.r = min(color[0],255)
|
pixel.r = min(color[0], 255)
|
||||||
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):
|
||||||
self.pixels = ffi.cast("struct Pixel_RGBA **", self.image32)
|
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]
|
pixel = self.pixels[y][x]
|
||||||
return (pixel.r, pixel.g, pixel.b, pixel.a)
|
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]
|
pixel = self.pixels[y][x]
|
||||||
# tuple
|
# tuple
|
||||||
pixel.r = min(color[0],255)
|
pixel.r = min(color[0], 255)
|
||||||
pixel.g = min(color[1],255)
|
pixel.g = min(color[1], 255)
|
||||||
pixel.b = min(color[2],255)
|
pixel.b = min(color[2], 255)
|
||||||
pixel.a = min(color[3],255)
|
pixel.a = min(color[3], 255)
|
||||||
|
|
||||||
|
|
||||||
class _PyAccess8(PyAccess):
|
class _PyAccess8(PyAccess):
|
||||||
|
@ -144,26 +150,27 @@ class _PyAccess8(PyAccess):
|
||||||
def _post_init(self, *args, **kwargs):
|
def _post_init(self, *args, **kwargs):
|
||||||
self.pixels = self.image8
|
self.pixels = self.image8
|
||||||
|
|
||||||
def get_pixel(self, x,y):
|
def get_pixel(self, x, y):
|
||||||
return self.pixels[y][x]
|
return self.pixels[y][x]
|
||||||
|
|
||||||
def set_pixel(self, x,y, color):
|
def set_pixel(self, x, y, color):
|
||||||
try:
|
try:
|
||||||
# integer
|
# integer
|
||||||
self.pixels[y][x] = min(color,255)
|
self.pixels[y][x] = min(color, 255)
|
||||||
except:
|
except:
|
||||||
# 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):
|
||||||
self.pixels = ffi.cast('unsigned short **', self.image)
|
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]
|
return self.pixels[y][x]
|
||||||
|
|
||||||
def set_pixel(self, x,y, color):
|
def set_pixel(self, x, y, color):
|
||||||
try:
|
try:
|
||||||
# integer
|
# integer
|
||||||
self.pixels[y][x] = min(color, 65535)
|
self.pixels[y][x] = min(color, 65535)
|
||||||
|
@ -171,16 +178,17 @@ 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):
|
||||||
self.pixels = ffi.cast('struct Pixel_I16 **', self.image)
|
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]
|
pixel = self.pixels[y][x]
|
||||||
return pixel.l + pixel.r * 256
|
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]
|
pixel = self.pixels[y][x]
|
||||||
try:
|
try:
|
||||||
color = min(color, 65535)
|
color = min(color, 65535)
|
||||||
|
@ -190,16 +198,17 @@ 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):
|
||||||
self.pixels = ffi.cast('struct Pixel_I16 **', self.image)
|
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]
|
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]
|
pixel = self.pixels[y][x]
|
||||||
try:
|
try:
|
||||||
color = min(color, 65535)
|
color = min(color, 65535)
|
||||||
|
@ -209,17 +218,19 @@ 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):
|
||||||
self.pixels = self.image32
|
self.pixels = self.image32
|
||||||
|
|
||||||
def get_pixel(self, x,y):
|
def get_pixel(self, x, y):
|
||||||
return self.pixels[y][x]
|
return self.pixels[y][x]
|
||||||
|
|
||||||
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,24 +239,26 @@ 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):
|
||||||
return self.reverse(self.pixels[y][x])
|
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)
|
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):
|
||||||
self.pixels = ffi.cast('float **', self.image32)
|
self.pixels = ffi.cast('float **', self.image32)
|
||||||
|
|
||||||
def get_pixel(self, x,y):
|
def get_pixel(self, x, y):
|
||||||
return self.pixels[y][x]
|
return self.pixels[y][x]
|
||||||
|
|
||||||
def set_pixel(self, x,y, color):
|
def set_pixel(self, x, y, color):
|
||||||
try:
|
try:
|
||||||
# not a tuple
|
# not a tuple
|
||||||
self.pixels[y][x] = color
|
self.pixels[y][x] = color
|
||||||
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -30,6 +30,7 @@ for r in range(8):
|
||||||
for b in range(4):
|
for b in range(4):
|
||||||
PALETTE = PALETTE + (o8((r*255)//7)+o8((g*255)//7)+o8((b*255)//3))
|
PALETTE = PALETTE + (o8((r*255)//7)+o8((g*255)//7)+o8((b*255)//3))
|
||||||
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# Image plugin for XV thumbnail images.
|
# Image plugin for XV thumbnail images.
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
@ -81,7 +83,7 @@ def _save(im, fp, filename):
|
||||||
|
|
||||||
fp.write(b"static char im_bits[] = {\n")
|
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")
|
fp.write(b"};\n")
|
||||||
|
|
||||||
|
|
|
@ -16,16 +16,17 @@ if bytes is str:
|
||||||
return ord(c)
|
return ord(c)
|
||||||
|
|
||||||
def o8(i):
|
def o8(i):
|
||||||
return chr(i&255)
|
return chr(i & 255)
|
||||||
else:
|
else:
|
||||||
def i8(c):
|
def i8(c):
|
||||||
return c if c.__class__ is int else c[0]
|
return c if c.__class__ is int else c[0]
|
||||||
|
|
||||||
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):
|
||||||
"""
|
"""
|
||||||
Converts a 2-bytes (16 bits) string to an integer.
|
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
|
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)
|
return i8(c[o]) | (i8(c[o+1]) << 8)
|
||||||
|
|
||||||
|
|
||||||
def i32le(c, o=0):
|
def i32le(c, o=0):
|
||||||
"""
|
"""
|
||||||
|
@ -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
|
||||||
|
|
|
@ -19,7 +19,3 @@ Pillow is the "friendly" PIL fork by `Alex Clark and Contributors <https://githu
|
||||||
|
|
||||||
.. image:: https://coveralls.io/repos/python-pillow/Pillow/badge.png?branch=master
|
.. image:: https://coveralls.io/repos/python-pillow/Pillow/badge.png?branch=master
|
||||||
:target: https://coveralls.io/r/python-pillow/Pillow?branch=master
|
:target: https://coveralls.io/r/python-pillow/Pillow?branch=master
|
||||||
|
|
||||||
.. image:: https://landscape.io/github/python-pillow/Pillow/master/landscape.png
|
|
||||||
:target: https://landscape.io/github/python-pillow/Pillow/master
|
|
||||||
:alt: Code Health
|
|
||||||
|
|
55
RELEASING.md
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
# Release Checklist
|
||||||
|
|
||||||
|
## Main Release
|
||||||
|
|
||||||
|
Released quarterly.
|
||||||
|
|
||||||
|
* [ ] Get master to the appropriate code release state. [Travis CI](https://travis-ci.org/python-pillow/Pillow) should be running cleanly for all merges to master.
|
||||||
|
* [ ] Update version in `PIL/__init__.py`, `setup.py`, `_imaging.c`, Update date in `CHANGES.rst`.
|
||||||
|
* [ ] Tag and push to release branch in python-pillow repo.
|
||||||
|
* [ ] Upload binaries.
|
||||||
|
|
||||||
|
## Point Release
|
||||||
|
|
||||||
|
Released as required for security or installation fixes.
|
||||||
|
|
||||||
|
* [ ] Make necessary changes in master.
|
||||||
|
* [ ] Cherry pick individual commits. Touch up `CHANGES.rst` to reflect reality.
|
||||||
|
* [ ] Update version in `PIL/__init__.py`, `setup.py`, `_imaging.c`
|
||||||
|
* [ ] Push to release branch in personal repo. Let Travis run cleanly.
|
||||||
|
* [ ] Tag and push to release branch in python-pillow repo.
|
||||||
|
* [ ] Upload binaries.
|
||||||
|
|
||||||
|
## Embargoed Release
|
||||||
|
|
||||||
|
Security fixes that need to be pushed to the distros prior to public release.
|
||||||
|
|
||||||
|
* [ ] Prepare patch for all versions that will get a fix. Test against local installations.
|
||||||
|
* [ ] Commit against master, cherry pick to affected release branches.
|
||||||
|
* [ ] Run local test matrix on each release & Python version.
|
||||||
|
* [ ] Privately send to distros.
|
||||||
|
* [ ] Amend any commits with the CVE #
|
||||||
|
* [ ] On release date, tag and push to GitHub.
|
||||||
|
```
|
||||||
|
git checkout 2.5.x
|
||||||
|
git tag 2.5.3
|
||||||
|
git push origin 2.5.x
|
||||||
|
git push origin --tags
|
||||||
|
```
|
||||||
|
* [ ] Upload binaries
|
||||||
|
|
||||||
|
|
||||||
|
## Binary Upload Process
|
||||||
|
|
||||||
|
* [ ] Ping cgohlke for Windows binaries
|
||||||
|
* [ ] From a clean source directory with no extra temp files:
|
||||||
|
```
|
||||||
|
python setup.py register
|
||||||
|
python setup.py sdist --format=zip upload
|
||||||
|
python setup.py sdist upload
|
||||||
|
```
|
||||||
|
(Debian requests a tarball, everyone else would just prefer that we choose one and stick to it. So both it is)
|
||||||
|
* [ ] Push a commit to https://github.com/python-pillow/pillow-wheels to build OSX versions (UNDONE latest tag or specific release???)
|
||||||
|
* [ ] Retrieve the OS X Wheels from Rackspace files, upload to PyPi (Twine?)
|
||||||
|
* [ ] Grab Windows binaries, `twine upload dist/*.[whl|egg]`. Manually upload .exe installers.
|
||||||
|
* [ ] Announce release availability. [Twitter](https://twitter.com/pythonpillow), web.
|
|
@ -6,5 +6,3 @@ import sys
|
||||||
|
|
||||||
if sys.maxsize < 2**32:
|
if sys.maxsize < 2**32:
|
||||||
im = Image.new('L', (999999, 999999), 0)
|
im = Image.new('L', (999999, 999999), 0)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from helper import *
|
from helper import unittest, PillowTestCase, hopper
|
||||||
|
|
||||||
# Not running this test by default. No DOS against Travis CI.
|
# Not running this test by default. No DOS against Travis CI.
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ def timer(func, label, *args):
|
||||||
class BenchCffiAccess(PillowTestCase):
|
class BenchCffiAccess(PillowTestCase):
|
||||||
|
|
||||||
def test_direct(self):
|
def test_direct(self):
|
||||||
im = lena()
|
im = hopper()
|
||||||
im.load()
|
im.load()
|
||||||
# im = Image.new( "RGB", (2000, 2000), (1, 3, 2))
|
# im = Image.new( "RGB", (2000, 2000), (1, 3, 2))
|
||||||
caccess = im.im.pixel_access(False)
|
caccess = im.im.pixel_access(False)
|
||||||
|
|
|
@ -6,7 +6,7 @@ import timeit
|
||||||
|
|
||||||
|
|
||||||
def bench(mode):
|
def bench(mode):
|
||||||
im = helper.lena(mode)
|
im = helper.hopper(mode)
|
||||||
get = im.im.getpixel
|
get = im.im.getpixel
|
||||||
xy = 50, 50 # position shouldn't really matter
|
xy = 50, 50 # position shouldn't really matter
|
||||||
t0 = timeit.default_timer()
|
t0 = timeit.default_timer()
|
||||||
|
|
|
@ -7,4 +7,5 @@ from io import BytesIO
|
||||||
if bytes is str:
|
if bytes is str:
|
||||||
Image.open(BytesIO(bytes('icns\x00\x00\x00\x10hang\x00\x00\x00\x00')))
|
Image.open(BytesIO(bytes('icns\x00\x00\x00\x10hang\x00\x00\x00\x00')))
|
||||||
else:
|
else:
|
||||||
Image.open(BytesIO(bytes('icns\x00\x00\x00\x10hang\x00\x00\x00\x00', 'latin-1')))
|
Image.open(BytesIO(bytes('icns\x00\x00\x00\x10hang\x00\x00\x00\x00',
|
||||||
|
'latin-1')))
|
||||||
|
|
|
@ -5,7 +5,9 @@ from PIL import Image
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
if bytes is str:
|
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:
|
else:
|
||||||
Image.open(BytesIO(bytes('\x00\x00\x00\x0cjP\x20\x20\x0d\x0a\x87\x0a\x00\x00\x00\x00hang', 'latin-1')))
|
Image.open(BytesIO(bytes(
|
||||||
|
'\x00\x00\x00\x0cjP\x20\x20\x0d\x0a\x87\x0a\x00\x00\x00\x00hang',
|
||||||
|
'latin-1')))
|
||||||
|
|
212
Tests/check_jpeg_leaks.py
Normal file
|
@ -0,0 +1,212 @@
|
||||||
|
from helper import unittest, PillowTestCase, hopper
|
||||||
|
from PIL import Image
|
||||||
|
from io import BytesIO
|
||||||
|
import sys
|
||||||
|
|
||||||
|
iterations = 5000
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
When run on a system without the jpeg leak fixes, the valgrind runs look like this.
|
||||||
|
|
||||||
|
NOSE_PROCESSES=0 NOSE_TIMEOUT=600 valgrind --tool=massif \
|
||||||
|
python test-installed.py -s -v Tests/check_jpeg_leaks.py
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skipIf(sys.platform.startswith('win32'), "requires Unix or MacOS")
|
||||||
|
class TestJpegLeaks(PillowTestCase):
|
||||||
|
|
||||||
|
"""
|
||||||
|
pre patch:
|
||||||
|
|
||||||
|
MB
|
||||||
|
31.62^ :
|
||||||
|
| @:@:@:@#::
|
||||||
|
| @:@:@@:@:@:@:@:@#::
|
||||||
|
| ::::::::@:@:@@:@:@:@:@:@#::
|
||||||
|
| :::::@::::::: ::::@:@:@@:@:@:@:@:@#::
|
||||||
|
| @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||||
|
| ::::::@::::@:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||||
|
| ::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||||
|
| :::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||||
|
| ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||||
|
| ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||||
|
| ::::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||||
|
| : ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||||
|
| @: ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||||
|
| @@: ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||||
|
| :@@: ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||||
|
| :@@: ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||||
|
| :@:@@: ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||||
|
| :@:@@: ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||||
|
| :@:@@: ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||||
|
0 +----------------------------------------------------------------------->Gi
|
||||||
|
0 8.535
|
||||||
|
|
||||||
|
|
||||||
|
post-patch:
|
||||||
|
|
||||||
|
MB
|
||||||
|
21.03^ :::@@:::@::::@@:::::::@@::::::::@::::::::::::@:::@:::::::@::::
|
||||||
|
| #:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||||
|
| #:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||||
|
| :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||||
|
| :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||||
|
| :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||||
|
| :::#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||||
|
| : :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||||
|
| : :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||||
|
| @: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||||
|
| @@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||||
|
| @@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||||
|
| @@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||||
|
| :@@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||||
|
| :@@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||||
|
| :@:@@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||||
|
| :@:@@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||||
|
| :@:@@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||||
|
| :@:@@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||||
|
| :@:@@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||||
|
0 +----------------------------------------------------------------------->Gi
|
||||||
|
0 8.421
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def test_qtables_leak(self):
|
||||||
|
im = hopper('RGB')
|
||||||
|
|
||||||
|
standard_l_qtable = [int(s) for s in """
|
||||||
|
16 11 10 16 24 40 51 61
|
||||||
|
12 12 14 19 26 58 60 55
|
||||||
|
14 13 16 24 40 57 69 56
|
||||||
|
14 17 22 29 51 87 80 62
|
||||||
|
18 22 37 56 68 109 103 77
|
||||||
|
24 35 55 64 81 104 113 92
|
||||||
|
49 64 78 87 103 121 120 101
|
||||||
|
72 92 95 98 112 100 103 99
|
||||||
|
""".split(None)]
|
||||||
|
|
||||||
|
standard_chrominance_qtable = [int(s) for s in """
|
||||||
|
17 18 24 47 99 99 99 99
|
||||||
|
18 21 26 66 99 99 99 99
|
||||||
|
24 26 56 99 99 99 99 99
|
||||||
|
47 66 99 99 99 99 99 99
|
||||||
|
99 99 99 99 99 99 99 99
|
||||||
|
99 99 99 99 99 99 99 99
|
||||||
|
99 99 99 99 99 99 99 99
|
||||||
|
99 99 99 99 99 99 99 99
|
||||||
|
""".split(None)]
|
||||||
|
|
||||||
|
qtables = [standard_l_qtable,
|
||||||
|
standard_chrominance_qtable]
|
||||||
|
|
||||||
|
|
||||||
|
for count in range(iterations):
|
||||||
|
test_output = BytesIO()
|
||||||
|
im.save(test_output, "JPEG", qtables=qtables)
|
||||||
|
|
||||||
|
"""
|
||||||
|
pre patch:
|
||||||
|
|
||||||
|
MB
|
||||||
|
177.1^ #
|
||||||
|
| @@@#
|
||||||
|
| :@@@@@@#
|
||||||
|
| ::::@@@@@@#
|
||||||
|
| ::::::::@@@@@@#
|
||||||
|
| @@::::: ::::@@@@@@#
|
||||||
|
| @@@@ ::::: ::::@@@@@@#
|
||||||
|
| @@@@@@@ ::::: ::::@@@@@@#
|
||||||
|
| @@::@@@@@@@ ::::: ::::@@@@@@#
|
||||||
|
| @@@@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||||
|
| @@@@@@ @@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||||
|
| @@@@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||||
|
| @::@@ @@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||||
|
| ::::@: @@ @@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||||
|
| :@@: : @: @@ @@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||||
|
| ::@@::@@: : @: @@ @@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||||
|
| @@::: @ ::@@: : @: @@ @@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||||
|
| @::@ : : @ ::@@: : @: @@ @@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||||
|
| :::@: @ : : @ ::@@: : @: @@ @@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||||
|
| @@@:: @: @ : : @ ::@@: : @: @@ @@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||||
|
0 +----------------------------------------------------------------------->Gi
|
||||||
|
0 11.37
|
||||||
|
|
||||||
|
|
||||||
|
post patch:
|
||||||
|
|
||||||
|
MB
|
||||||
|
21.06^ ::::::::::::::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||||
|
| ##::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||||
|
| # ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||||
|
| # ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||||
|
| # ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||||
|
| @# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||||
|
| @# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||||
|
| @# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||||
|
| @# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||||
|
| @@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||||
|
| @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||||
|
| @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||||
|
| @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||||
|
| @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||||
|
| @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||||
|
| @@@@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||||
|
| @ @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||||
|
| @ @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||||
|
| @ @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||||
|
| @ @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||||
|
0 +----------------------------------------------------------------------->Gi
|
||||||
|
0 11.33
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def test_exif_leak(self):
|
||||||
|
im = hopper('RGB')
|
||||||
|
exif = b'12345678'*4096
|
||||||
|
|
||||||
|
for count in range(iterations):
|
||||||
|
test_output = BytesIO()
|
||||||
|
im.save(test_output, "JPEG", exif=exif)
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
base case:
|
||||||
|
MB
|
||||||
|
20.99^ ::::: :::::::::::::::::::::::::::::::::::::::::::@:::
|
||||||
|
| ##: : ::::::@::::::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||||
|
| # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||||
|
| # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||||
|
| # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||||
|
| @@# : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||||
|
| @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||||
|
| @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||||
|
| @@@ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||||
|
| @ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||||
|
| @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||||
|
| @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||||
|
| @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||||
|
| @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||||
|
| @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||||
|
| :@@@@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||||
|
| :@ @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||||
|
| :@ @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||||
|
| :@ @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||||
|
| :@ @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||||
|
0 +----------------------------------------------------------------------->Gi
|
||||||
|
0 7.882
|
||||||
|
"""
|
||||||
|
|
||||||
|
def test_base_save(self):
|
||||||
|
im = hopper('RGB')
|
||||||
|
|
||||||
|
for count in range(iterations):
|
||||||
|
test_output = BytesIO()
|
||||||
|
im.save(test_output, "JPEG")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
|
@ -9,6 +9,6 @@ i = Image.new("RGB", (500, h), "white")
|
||||||
d = ImageDraw.Draw(i)
|
d = ImageDraw.Draw(i)
|
||||||
|
|
||||||
# this line causes a MemoryError
|
# 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()
|
i.show()
|
||||||
|
|
|
@ -100,7 +100,8 @@ class PillowTestCase(unittest.TestCase):
|
||||||
ave_diff = float(diff)/(a.size[0]*a.size[1])
|
ave_diff = float(diff)/(a.size[0]*a.size[1])
|
||||||
self.assertGreaterEqual(
|
self.assertGreaterEqual(
|
||||||
epsilon, ave_diff,
|
epsilon, ave_diff,
|
||||||
(msg or '') + " average pixel value difference %.4f > epsilon %.4f" % (
|
(msg or '') +
|
||||||
|
" average pixel value difference %.4f > epsilon %.4f" % (
|
||||||
ave_diff, epsilon))
|
ave_diff, epsilon))
|
||||||
|
|
||||||
def assert_warning(self, warn_class, func):
|
def assert_warning(self, warn_class, func):
|
||||||
|
@ -138,7 +139,8 @@ class PillowTestCase(unittest.TestCase):
|
||||||
if travis is not None:
|
if travis is not None:
|
||||||
skip = skip and (travis == bool(os.environ.get('TRAVIS', False)))
|
skip = skip and (travis == bool(os.environ.get('TRAVIS', False)))
|
||||||
if interpreter is not None:
|
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:
|
if skip:
|
||||||
self.skipTest(msg or "Known Bad Test")
|
self.skipTest(msg or "Known Bad Test")
|
||||||
|
|
||||||
|
@ -155,7 +157,7 @@ class PillowTestCase(unittest.TestCase):
|
||||||
raise IOError()
|
raise IOError()
|
||||||
|
|
||||||
outfile = self.tempfile("temp.png")
|
outfile = self.tempfile("temp.png")
|
||||||
if command_succeeds(['convert', f, outfile]):
|
if command_succeeds([IMCONVERT, f, outfile]):
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
return Image.open(outfile)
|
return Image.open(outfile)
|
||||||
raise IOError()
|
raise IOError()
|
||||||
|
@ -200,26 +202,6 @@ def hopper(mode="RGB", cache={}):
|
||||||
return im
|
return im
|
||||||
|
|
||||||
|
|
||||||
def lena(mode="RGB", cache={}):
|
|
||||||
from PIL import Image
|
|
||||||
im = None
|
|
||||||
# FIXME: Implement caching to reduce reading from disk but so an original
|
|
||||||
# copy is returned each time and the cached image isn't modified by tests
|
|
||||||
# (for fast, isolated, repeatable tests).
|
|
||||||
# im = cache.get(mode)
|
|
||||||
if im is None:
|
|
||||||
if mode == "RGB":
|
|
||||||
im = Image.open("Tests/images/lena.ppm")
|
|
||||||
elif mode == "F":
|
|
||||||
im = lena("L").convert(mode)
|
|
||||||
elif mode[:4] == "I;16":
|
|
||||||
im = lena("I").convert(mode)
|
|
||||||
else:
|
|
||||||
im = lena("RGB").convert(mode)
|
|
||||||
# cache[mode] = im
|
|
||||||
return im
|
|
||||||
|
|
||||||
|
|
||||||
def command_succeeds(cmd):
|
def command_succeeds(cmd):
|
||||||
"""
|
"""
|
||||||
Runs the command, which must be a list of strings. Returns True if the
|
Runs the command, which must be a list of strings. Returns True if the
|
||||||
|
@ -249,6 +231,14 @@ def netpbm_available():
|
||||||
|
|
||||||
|
|
||||||
def imagemagick_available():
|
def imagemagick_available():
|
||||||
return command_succeeds(['convert', '-version'])
|
return IMCONVERT and command_succeeds([IMCONVERT, '-version'])
|
||||||
|
|
||||||
|
|
||||||
|
if sys.platform == 'win32':
|
||||||
|
IMCONVERT = os.environ.get('MAGICK_HOME', '')
|
||||||
|
if IMCONVERT:
|
||||||
|
IMCONVERT = os.path.join(IMCONVERT, 'convert.exe')
|
||||||
|
else:
|
||||||
|
IMCONVERT = 'convert'
|
||||||
|
|
||||||
# End of file
|
# End of file
|
||||||
|
|
25
Tests/icc/LICENSE.txt
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
from http://www.color.org/srgbprofiles.xalter
|
||||||
|
|
||||||
|
Terms of use
|
||||||
|
|
||||||
|
To anyone who acknowledges that the file "sRGB_v4_ICC_preference.icc"
|
||||||
|
is provided "AS IS" WITH NO EXPRESS OR IMPLIED WARRANTY, permission
|
||||||
|
to use, copy and distribute this file for any purpose is hereby
|
||||||
|
granted without fee, provided that the file is not changed including
|
||||||
|
the ICC copyright notice tag, and that the name of ICC shall not be
|
||||||
|
used in advertising or publicity pertaining to distribution of the
|
||||||
|
software without specific, written prior permission. ICC makes no
|
||||||
|
representations about the suitability of this software for any
|
||||||
|
purpose.
|
||||||
|
|
||||||
|
|
||||||
|
To anyone who acknowledges that the file
|
||||||
|
"sRGB_IEC61966-2-1_blackscaled.icc" is provided "AS IS" WITH NO
|
||||||
|
EXPRESS OR IMPLIED WARRANTY, permission to use, copy and distribute
|
||||||
|
these file for any purpose is hereby granted without fee, provided
|
||||||
|
that the file is not changed including the ICC copyright notice tag,
|
||||||
|
and that the name of ICC shall not be used in advertising or publicity
|
||||||
|
pertaining to distribution of the software without specific, written
|
||||||
|
prior permission. ICC makes no representations about the suitability
|
||||||
|
of this software for any purpose.
|
||||||
|
|
BIN
Tests/icc/sRGB_v4_ICC_preference.icc
Normal file
BIN
Tests/images/hopper.Lab.tif
Normal file
BIN
Tests/images/hopper.fli
Normal file
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.4 KiB |
BIN
Tests/images/hopper.psd
Normal file
BIN
Tests/images/hopper.tif
Normal file
BIN
Tests/images/hopper.webp
Normal file
After Width: | Height: | Size: 3.2 KiB |
178
Tests/images/hopper.xpm
Normal file
|
@ -0,0 +1,178 @@
|
||||||
|
/* XPM */
|
||||||
|
static char *hopper[] = {
|
||||||
|
/* columns rows colors chars-per-pixel */
|
||||||
|
"128 128 44 1 ",
|
||||||
|
" c #110E13",
|
||||||
|
". c #2A1110",
|
||||||
|
"X c #13122C",
|
||||||
|
"o c #25192A",
|
||||||
|
"O c #312831",
|
||||||
|
"+ c #302219",
|
||||||
|
"@ c #5F241A",
|
||||||
|
"# c #6F4832",
|
||||||
|
"$ c #17174A",
|
||||||
|
"% c #26264F",
|
||||||
|
"& c #65595D",
|
||||||
|
"* c #4B3C54",
|
||||||
|
"= c #8E1F1A",
|
||||||
|
"- c #914E33",
|
||||||
|
"; c #A75335",
|
||||||
|
": c #AC6736",
|
||||||
|
"> c #B26F4E",
|
||||||
|
", c #9B6657",
|
||||||
|
"< c #CA7652",
|
||||||
|
"1 c #CC7866",
|
||||||
|
"2 c #C25135",
|
||||||
|
"3 c #B0896D",
|
||||||
|
"4 c #D28859",
|
||||||
|
"5 c #D28E6D",
|
||||||
|
"6 c #E79371",
|
||||||
|
"7 c #E5A36E",
|
||||||
|
"8 c #D58932",
|
||||||
|
"9 c #3E65AE",
|
||||||
|
"0 c #4970B5",
|
||||||
|
"q c #606D95",
|
||||||
|
"w c #557CC1",
|
||||||
|
"e c #91778A",
|
||||||
|
"r c #6A86B9",
|
||||||
|
"t c #5C83C3",
|
||||||
|
"y c #6D8FCA",
|
||||||
|
"u c #7799E3",
|
||||||
|
"i c #A89A9D",
|
||||||
|
"p c #CFAA90",
|
||||||
|
"a c #F4B08F",
|
||||||
|
"s c #D6A799",
|
||||||
|
"d c #ECCCAB",
|
||||||
|
"f c #F9F4F4",
|
||||||
|
"g c #E3D8D5",
|
||||||
|
"h c #AAAECA",
|
||||||
|
/* pixels */
|
||||||
|
"$XX$$XXX$%$$$$$$$$$$$$$$$$$$$egip3dr %% @p# Oqgffgfgfgo%q999q9999999999999999999099999099099990999999909909990w999000wwww00w00w0",
|
||||||
|
"$$X$X$XX$$$$$$$$9$$$$XX$$$$$$ws&7+O&%$Xo@3#XXX&ihffggg%%9q*9*%q99qq9q99999999999999090900909909909099999999999999999000wwwwww0ww",
|
||||||
|
"X$X$$XXX$$$$$$$$$$$$$$$$$$$$$eq@i#+$$$%X#pOX$%$%*dfffgiX%%OX%XO*%**990909999999009090990900999999099990999w999990990000wwwwwwwww",
|
||||||
|
"$XX$$$XX$$$$$$$$$$$$XX$$$$$$$*O*7#XX%$%X@p*XX$%Xohfi3hOXOoX*r3*OOO%O99099999q0q990990009090909000999090999999099909999ww0w0000w0",
|
||||||
|
"$XX$$XXX$$$$$$$$$9$$$$$$$$$$o$.&3++X$$$o#p+X$$%$OhgOX oo+ii*if&+ri&OO%q0990099009090090990909009990999099w999990999090w0000w0ww0",
|
||||||
|
"X$X$$XXX$$$$$$$$$$$$$$$$$$$$$oX#p#OO%$$o#7O%X$$XOg&O o.&fffgifirfffiOO*&qq990990000000009909099000990990999990999w90099000000000",
|
||||||
|
"XX$$$XXX$$$$$$$$$$$$$$$$$$$$$oo*3+o$$%$.#7+X$%XOOhii+X,fgifffffffddfgOOrhi0qq000090000090099990909909009w9w9909990999099900000w0",
|
||||||
|
"X$X$$$XX$$$$$%$$$$$$X$X$$$$$X$X#7@X$$$$o:3+XX$OqgffrXOe&&#*&iggi&&3&*&OOfffgrq900009000099099090000909009999990999900900000000w0",
|
||||||
|
"X$q$XXXX$$$X%$$$$$$$X$$$$$$$$$X*p+O$%$$o-3oOX%gffff&o++3pgg3fddd3fdg&+OOhffffgt0099090090009090990909990999990999000099090090000",
|
||||||
|
"X$g&$XXX%$X$%$$$$$$$$$X$$$$$$$o*p+X%$%$X,5+ *gfffff& ++&pddffffffgdd#OOOiffffffhq9qt009w990090900999w9w9900999w90999909009900000",
|
||||||
|
"X$ggO %$$$X$%$$$$$$$$$$$$$$$Xo*3#$$%%$X,3+&ffffffg#+.+Odddgggggggpd*+OOifffffffgtqt09t909090990090909099990099w0990090909090000",
|
||||||
|
"X%hfr&h&$$$$%q$X$$$$XXX$$$$$Xoo*p@o$$$$X:3OffffgppdO. ++,ddfffffffd3+ ++&ffffffffgq900909090900999099090w9w990990009009090009900",
|
||||||
|
"Xohfffh&X$o$$h&$$$$$$$X$$$$$Xo$*7# %%$$ 35dffg73&#++++ +pd3gfffffg3d,++++3ddffffffhq90009099990999909090990909w99990099900900000",
|
||||||
|
"oegffgiO$$$$$gh$$%&qXXXX$%XX$X.*3# X%X$+#pgfd3&+. + ++3iddgfffddpd&+O++++#pgfffffrq9900900q99090909990099009990009990999090000",
|
||||||
|
"hffffg&X$%$X$gg*&hg*XXXX%i%$$Xo*5#XX$$$o,dfg&+.. .#&++ +&ddd3gfgdddd#++++&+++#3dfgghq009099090000909090990999090909000099000000w",
|
||||||
|
"hgffffp*X$X%Ogggfgh$XXX$%g*XXooO5#o$%$$+&df3...&#++3 O#+#pd7di&,ppdd&+++#3+&&..#iffgqq009009009909900990090009990009999009990000",
|
||||||
|
"o%qffgh&o%o*iffgfg%%X$XX*gi OqO*p#+$%$XO&h3 . +pdpp3pdgdd3#+++++++#ppggpp3ddp+##+ifghqrq09090090090090900909999009009w900009w0w9",
|
||||||
|
"Xo*fh**%$%igfgfgg&%$$X$X&ggih3o+p# X%X$XX .+33+pdppdddfp,#+O&dfggdddd3pdddd+++dh&%%&q0090909009909090090000900w000w99w0900ww",
|
||||||
|
"X%&fq%oX$%&hgfffgi%oXXX &fgshOoO3#+X%%XX+ . +#&++7dp3&#O&O&#&33dd3#3&.+#ppiiO#+ X%9909000909099090090900009w9w009ww9ww9w00",
|
||||||
|
"X$%g*o$XX%Xo*gffffq$X%&egfhp&oXO7# XXX + #++.+++ +..O+ ++O++#ppp+++&3++ o XXq9000900009000090009000009w909w09w00w00w",
|
||||||
|
"$$*i$$oX$XoX%hfeegg%$%&idggh+X$O4#+XOX + . + ..o + + ++ +&3gg#. X999909000000000000009000000000w09w0www0w",
|
||||||
|
"$$%%$$$X$$o$$hh*$$q&$o o3ggd,ooo3#+ ++ +++ ++*++ X%0q9q900000ww000000000000ww99w00w9w99ww0",
|
||||||
|
"$$$$%%X$$$X$%g0$$%%%oX .&fshg*Xo3: X + + X*0000000000w000000000w00000ww0www90wwww0",
|
||||||
|
"$%$$%$$XX$$X%h$%$%$$XXX qg*XiqXo3:+ %0q0000000w00000w0ww000w0ww990009w0w99ww",
|
||||||
|
"$$$%%%$$$XX$$%%$%$$$XXXXihXXX%X.,: %t000t90w0w0000090w00w00009w000wwww9www9",
|
||||||
|
"$$$$$%X$X$$$$%$$$$$$XXXXq*XXXXXo3: . %0q0000t0w0ww00ww00ww00ww0w9w0w0w99ww9ww",
|
||||||
|
"$$$$$$$XX$X$$$$$$$$$$XXX*$$XXXX :> %q0t0t00w0w0w0w00ww0w0w0w00w0w0www90w09w",
|
||||||
|
"$$$$$$XX$$XX$$$$%$$$$XXX$$$$XXX.:3. . . .... .. . ....... X%qw000t00www0wwwwwww0ww0www0w00w00w09w9w",
|
||||||
|
"$$$$%%$$$XX$$$$$$$$$XXXX$$$$XXX -3 . ....+@@@@@@.@@....@@@@#####*@.. %ttt9ttt0t0tw0www0ww0ww00w9ww0w09w9www0w",
|
||||||
|
"$$$%$%$$X$$$$$$$%%9$XXXX$$$$XXX :3 ...#->1>>1,>>,,--;,--,,,1531>13>#@. X09q9r00t0t0wwwww0w0wwwwwwww0wwwwww0w00w",
|
||||||
|
"$$$$$$XXX$$$$$$$$$$$XX X$$$$$XX.:: .#11ss65assa56a511155557a775555p5,,. Xqttr0trt0wtwwwwww0ww0wwwwww0wwwww0ww0ww",
|
||||||
|
"$$$$$$$X$$$$9$9$$$$$XXXXX$$$XX$ >;. ...#,pps55paaaaasadasaaaaaaaaa777a77p53,*... Xt0tq9t0ttwww0wwwwwwww0wwww0wwww0wwwwwww",
|
||||||
|
"*o$%$%$XX$$$$$$$%$$$$XXXX$$$$XXX,> +#*-,5pp7apasaadddaaaaddadaaadddaaa6pp733,##. Xqrtttttt0t0rt0tt000t0t0t0t00t0t0ttt0ttt",
|
||||||
|
"go%$$*%$XXX$$$$$$$$$$X XX$$$$XX :> .&,#,5p77p7aaaaadaaadaddaaadaaaasaapp7775534#@ Xr90tq0ttt0tt0ttt0ttttt00tttt0tt0t0tttt0",
|
||||||
|
"fio%whXXX%$$$$$$$$$$$XXX$$$$X$X.,8. o###-155pppadaasasaaadaaaaaaaaa51>3355455535>>#+ %t0r0r0rttt00tt0ttttttt0tttttt0ttttttttt",
|
||||||
|
"gg&gf&X *qo$$$$$$$$$$X X$$$$$XX 3: OO##,135565431>113sadaaaddsss611>1>>55s5355333,*+ %rr0r0ttt0tttttrtt0ttqttt0ttttttttt0tttt",
|
||||||
|
"gffghOXX*g*$$$%$$$$$XXXX$$$$XXX -> +###,>3575p5<><355saaaaaaaap615>;;-;>5a7p335333#+ %rrtttt0t0trtttttttttttttttttttttttttttt",
|
||||||
|
"fgfg&oo &giO$qi%X$$$XX XX$$$XX .::+ +#,,,3355p55>>;;;,>16s777aaas61>;=--@#@@@@##&##&&+X*rrtttttttt0tttttttttttttttttttttttttttt",
|
||||||
|
"gggg&o &gg,sfe$X$$$$X XX$$$XXX :: +&#-,,35333>>,-,-,>>15apaadap1>>;@@@#;-##@+,&@##&O+&rttttt0ttttttt0tttttttttttttttttttttttt",
|
||||||
|
"gffgg*oX&gfggh%X$X$$XX X%%XXX 3:+ ++3:-####@@.@..@++@@->6aaaaaa74>=@,3,11335d&+@+O*&##qrrttttytttttttrtttttttttttttttttttttttt",
|
||||||
|
"sggggho*dgggg&O$$$$$ *+Oii$X X .::+++&,-##+@+@@:ss1,1i1--=:4a77764::a1,@@@@=,,4d#+##*&,-eqyrwyrwttttttttttttttytytttytytttyttttt",
|
||||||
|
"id**qi&Ogggdd+X$$$$$o*&eh*X XXX.::.O#,>-#@...+,,,-@@@@-5><<<76748:2<>-@#.@@@@=-@##@@+#,isiryywyyrttrttttyttytytttttytttttttttytu",
|
||||||
|
",hO%X$Xo&gggg&O$$$$XoO,e&OXXXXX.3:.@33;#+@@@.-,>-@.@..@=::;<4<4<:28<2@#@.@@@@==-,-##-,1,eheywyywyttttyytytyttttttyttttttttytyttt",
|
||||||
|
"i&o$$X Ogggfg%X$$$$oO,&+ XX X :3+@3,,;##@#@##,@@@..@-;==;426a76<<<;>;--#==;;::4>4>:;:==1ryewywttyrtytttytyytyyttyttuytyttyttyt",
|
||||||
|
"**%$$$XX+hiO&h&%$$$XX*,,& XXX X ::+#1-#-;,,>,#-==#=#;-;<4444;6ad7<661<<11>2;2<<<445<>:<<@,ryytytyytyyttyyttytyttytyttyttyttyuytt",
|
||||||
|
"%X$$$$X Og*o%$*X$$$$X*&&i* XXXX :3.#,=;>,-35:-#===:4s51446a6;6aaa6661<66aaa6<664445>:15<-,ewyytyytytyyytyyytytytytyyytyyttuttttu",
|
||||||
|
"X$$$$XXXOi$$$$$X$$$XXX.o&qXo X .>>.#-@>;-:<6:<;==2<66a6<<6a<<aaaa7<a76167661<665655326a1-1ityytyyytytyyyyyyyyytyyttuyyyyytutyyyt",
|
||||||
|
"$XX$$XX %%$$$$$X$%$$X ooX$XXX -8.@,=11>-:44:<82<<11<<<aa621addad167aa4<8<2<<7545511:66;eqrryytytyyyytyyttyytytyytttyttyytyttyy",
|
||||||
|
"X$$$$XXXXX$$$$$$$$X$X XXXXXXXX :3.+>=54;;<<<<1<;2<<<1aada6:7adadd74aaadaa6446764444;=>s,eitryyyyyyyyyyyyttyyyyyyyytyyttyttutytu",
|
||||||
|
"XX$$$XXXX$$$$XX$$$$$XXXXXX$X$X .::.@,;6<-;<<1<4::46aadddaa46aadddad66aaaaaa7a76564>4<-;51eryyttyyyttryytyyyyyryrtuyytyyyyyyttytt",
|
||||||
|
"X$$$$XX XX$$$$X$$$XXXXX XXXXXXX :8+ia>44;;<<<44<;87dadddda<aaadddaaa1saadaa676444>>5a221eiiwtyyyyyyyyyyyyyyyyyyytyytytyytttytuyy",
|
||||||
|
"$X$X$X XX$X$$X$$$$$XX XX$XX$XX #73pda6<>56>2<44<26addaa6>:6adaaadda2;16666a7a6<4>47a1<1ieyyyyytyyytyyyyyyryyyyyyyyytutyyuyyytyy",
|
||||||
|
"X$$$XX XX$$$XX$$$$XXXX XXXXXX :75ps565577>:<:46<<1aa11;;6aaadddaada<2>2;<6676<<435a1>5eiyytyyyyyyyyyyyyytyyyyyyyyyyyyyyytyyuty",
|
||||||
|
"XX$$$XX XX$$$$$$$$X$XXXXXXXXX X3773sdp565p742<:<61<2;2;2=<66aaaaadaaa1>6a66a665<5>456>15ewyyyyyyyytyyyyyyyyyyyyytyytyyyyytuyyttu",
|
||||||
|
"$$$XXX X$$$$$X$$$XXXXXXXXXX &pp73dd357577<<:>481611612;661a1saas6111;21aa664444>56<163iyyytyyyyyyyyyyyyyyyyryyutyyyyyyyyyyyyyy",
|
||||||
|
"$X$$XX XX$$X$$$$XXXXXXXXXX *ip773ss345775<<<848111aa1;=;-=><1511;;====116166165>4>6615rtyyyyyyyyyyyyyyyyyyyyyyyyyyyyytyyyyytuy",
|
||||||
|
"X$$X$X XX$$$XX$X$XXXXX X XX*ipp773dd33783::<<<4<<6664;=6<@===-==#;=;1;@21<<646655>>>>6iryyyryyyyyyyyyyyyyyyyyywyryyyyyyyyyyyutu",
|
||||||
|
"XXX$XX X$$$$$$X$XXXX XXXX&iipp783pp33735771<<46<644<=<66641,-@@:41112==2<4<44545a775piiyyyyyryyyyyyyyyyyyywyyyyyywyyyytyyyutyy",
|
||||||
|
"XX$*XX XX$$$$$$$$XXXXXXX oriipsp784dp333a7p761446<442=2661666611<6161<1<@=;2<46555aa5ppqryyyyrryryyyyyyyyyyyyyryywyywyywuytyyyyy",
|
||||||
|
"*oe*XX XXXXX$XXX$XXX Xoiihhisp774ppp837a7dp>4464<<2=<16666666666116661===;<1<445a77p3iryyyyyyyyyyyyyyyyyryyyyyyyyyyyyytyyyyyyy",
|
||||||
|
"iiiXXXX XXXXX$XX$X X o@iihishpp788dpp#:7p7a,3447842=;166aaa6aaaaaa16666<;=;<<4643ap33iirryyyryyryyyyyyyyyyryyyyyyyyyyyytyyttyyy",
|
||||||
|
"di&o o %*%XXXX$XXXX Oeiishippp773dd3:#:57>.-47664;@8<61a6a1aaaaaa676a11<=<<6548->53iirrryyyyyyyyyyyyyyyyyyyryyyrryyywyyyyyutuy",
|
||||||
|
"ppO.oX *q&XXXXXX$XXX..@,eshsipdp783pp3:##:,@.#:4474<:<<11<>1<1661<21<<<6<6;166643##,7irrryyyyyyyyyyyyyryyyyyywyyyryrywtyyyyyyyty",
|
||||||
|
"di*+X. *&OoXXXXXXX$ .o@&,sshsiip377pd3,##:3,@@4466718<<<2=====22=2===-=;2<6676158##333iryyyyytyyyyyyyyyyyyyyyyyyyyyyyyyyytytyyyy",
|
||||||
|
"gge. *OoXXXXXXXXXX..@@,3shsipp778dp3,-@@@@+@-46667<22==;22,22=2111<6<<<<8677453##33iriyyyyyyyyyyyyyyyyyyyyyyyryyyyytyyyyyyyyyy",
|
||||||
|
"esi* &*XXXXXXXXXX .@@=;ppssppp77377:-:@+.+++-446774<<<1116666aa16a61<66<6766558#,3ihrryyyyyyyyyyyyyyyyyyyrryyyyyyyyyytytyyyyyy",
|
||||||
|
"&.&eo oi& XXX$XXXXXX.@@@=ishhpsp873p3,:28@@.@+=4<4774868<1116aa6a611<88668664453##&3iryyyyyyyyhyyyyyyyyyyyyyyyyyyyryyyyyytyyyyyy",
|
||||||
|
"oXXo XX&eXXXXX XXXXX..=@@1ssipsp875p3::888:@.@@;44464<68<<2112;;;22<<6664<16443>##3iiryhuyyyyyyyyyyyyryyryyyyrryyyyyyryyyyyyyyyy",
|
||||||
|
"XXXXX X&OXXXXXXXX .@@===6ssis577377>::88882@@-:<<68<66611<2;;;2=;:<<<<644<<<5-#3&3iyhyyyyyyyyyyyyyyyyyyyyyyyyyryyyyyryyyyyyyyy",
|
||||||
|
"XXXX X %OoXXXXXXXX..@=@=@1ssis578377:::82822;@;:4<8244<8<1<46a56144<<<656<6<<1#&eerryryyyyyyuyyyyyyyyyyyyyyyyyyyyyyyyyytytytyty",
|
||||||
|
"XXXXX XXXXXXXXX..@=@====sspp578877:8228282;=;<<><46666666aaaaaa66777a5<4<1,i-&3riryyyyyyyyyuyyyyyyyyyyyyyyyyyyyyyyyryyyyyyyyy",
|
||||||
|
"X$XXX XXXXXX ..@@==@===1ppp5878p8222828282==<:<<6<<<84667aaaa6aa777744<;113,eiryyyyyyyyyyuyuyhyyyiyyyyyyyyyyyyyyyyyyyytyyyyy",
|
||||||
|
"XXXXX XXXXXX X .@===@=====1ap387838:8:282822=@>4:>44>44644666a66aaa744>>:::>3,erryyuuyyyyyyyyhyyyyyyuyyyyyyyyyyyyyyytyyyyyyuty",
|
||||||
|
"XXXX XXXXXXXo@@@===@@===11s>87888:8:828828@-p4;::<:<44<4446455656548>#---33Oirryyuyyyyyyuyyuyyyyyyyyhyyyyhyyyuyyyyuyyytuyyyy",
|
||||||
|
"XXXXX XXXXXX .@@==========;1s187882;8:28888=+sp1,-=;-:<<444<<><141<<:;=@@=>p,XOrryuuuyyyyyyyyyhyyyyyyyyyyyyyyyyyyyyyyyyyytyyyy",
|
||||||
|
"XXXX X XXXX .@@======@===@=1118788:;8:8288;.+d151-@@@@;:>2:---;,,-;--#@@@:333 ++qyyyyuyyyyyyyyyyuyyyuyyyyyyyyyuyyyyyyyyyyyutuy",
|
||||||
|
"XXXXX XXXXX..@@=======@==@==>5<8788:;8:8:8:..&d,35>-@@@@-@@@@@@@@@@@@==@@,55p, Xqyyyyyyyyyhyyyyyyyyyyyyyyyyyyyyyuyyyyyyuttyyy",
|
||||||
|
"$XXX o...@@=========@====262888:;-82::-.. ip#513:=@@@@@..@......@@---;1>53, Xqhyyhyyyyuyyyyyhyuyhhuuyhyyyyyyyyyyyyyyyyuyy",
|
||||||
|
"XXXXX oXoO@@@=======@=@=====s;878:=-:-;@.. hp@74>:---##@@......@@#-,--,<51p3 +Oryyuhuyyyyyyyyyyyyyyuyyyyyyyyyyuyyyyuyyyyy",
|
||||||
|
"XXXX X .o**==========@@@=@===1;878:;-:#.. gd@54>3:-:--@@@.....@@-;--;<>13d& + +O&ryyyyhyuyuyyyuyyyyyyyyyyyuyyyyyuyyyyyyyu",
|
||||||
|
"XXXXX .&h1@=========@@@=====2;778:@@. hd@343<;;;,--@@@@O@@@#;;-->1>5pg&X X%qyyyyyyyyyuyyyuyyyyyyyyyuyuyyyyyyyyyyy",
|
||||||
|
"XXXXX Xisi1;===@======@@=====>>88#+ gg#,5>:>:-;---@@@@@@=-;;-;<>53df& X X&ryyyyyyyyuhyuyhyhyyyyhyyyuyyyyyyyyy",
|
||||||
|
"XXXX &idi31=========@@@=@==@=. + dg+-51<:;;;-#==#@#---->;-:>>5dff& XXXX*rhyyhuyyyyyyuyyyuyyyyyuyyhyyyyyyy",
|
||||||
|
"X XX +iipi3s2==@======@@@=@@.. df@#55<>:>,---#=#-;=-;;;:>>35gggO X XXX$XOqrhyyyyhuyuyyyyyyyuuyuyyyyyyyuy",
|
||||||
|
"X X X+pssiiss2======@....... igs@>1<>::>;-----;;;;;>;>>3>dffg . XX XO %qyyyyyyyhhyyuuyyyuyyuyyyyhyyy",
|
||||||
|
"XXX .iissshss===@@... .. egf,-1<:<:>:----;>;;;>:;;>>5ggfs X XO+OX O*qiyyyyyyyyyyuyuyyuyyyyyyyy",
|
||||||
|
"XXXX .ppssssdg,...... &gfd@>4::>>>----;;;;;>>;>>,gfggq X+ X XXXOOO9rryyyyhyyyyyyyuyyyyyyy",
|
||||||
|
"XXX X .iphhshhsO X&gff,#><>:>;;---;>;2;>::--pgfgf* o ++ + X XXX++O++%&ryyyhyyuyyyyyyyyyy",
|
||||||
|
"XXXX +3pdphi3 *ggfg#-><;:>:-;=;-;;;>;-#3gfgfg X+XX +X XXXXXXXXX%qyhyyyyyyuyyyyyy",
|
||||||
|
"XXX iphi++ %ggffd-><><3---@----;>:@,gfffgi. +XX X+X X+ XXXoXXXXXX%qyyrhryyuyyyyy",
|
||||||
|
"XXXX. pdi+ . Ogffffg;>1<>:-;@---=2,-,gffffgO XXXX X +X++X+X+ X+X XXX%%riryyyuyyyyy",
|
||||||
|
" X X .ih& hgffffd-56>::-=--#->,-dfffffg X XXX X + X+o X+XOXXXX%ryyyyyyyyy",
|
||||||
|
" o X ii + *ggffffp:553>;-,--,>#gffffffr XX X XX+X+ Xo o+ OXo XXX%yyyyyyyyy",
|
||||||
|
"O o i& +ggfffff3,555>,3>,1,gfffffffO o+XXXX XXX X o XoXX +XXX$ryuyyuyyy",
|
||||||
|
",. 3+. qgffffff3>531>1>13gfffffffh . X X++XX +X+XX X X X + + X$*yyyuyyyy",
|
||||||
|
"iO & o&gfffffff35pddddsiffffffff& X X XXXX X X o X X X X XXrhyyytyy",
|
||||||
|
"si . O ogfffffffffgfdhpO Ogfffffg ++ + X X+XX+ +X X+ X X XX X Xrryuyyry",
|
||||||
|
"si# ... Xifffffffe**O+o ++ OgffffqX +X OX +X X X+X XX X+ X X X&yyyyyyy",
|
||||||
|
"ssi@ &ffffffq+ + + o OgffgOX + X++ X++ OX+ XX+XXXXXXXX XX X X X$yyyyyyy",
|
||||||
|
"sip&.... &gffff& +o + %gfr + + X X X X+XX+X X +X+ +X X X X$yyyyyyy",
|
||||||
|
"pisi+. . +hfff&X + + &gO X X+ X+XO+X + X X X XX o XX X X Xqryryuy",
|
||||||
|
"ppp3#. +eff& o + *+ + + + + XX X OXXX X +X X+ X XX X Xhyyyyu",
|
||||||
|
"ppi3,. X*fq X + + O + ++ X++XX+X X X+XXXX+ Xo X X X XXrrhyyy",
|
||||||
|
"p5pi,.. O& + +XX X + X X X O+X X X X X X X XX X*yryyu",
|
||||||
|
"p5pi3o o + X o+OO X X +X+ X+ + +X X o o X X+ XX X X XXryyuy",
|
||||||
|
"spp3,. X riggggghy+ + + + X+ X Xo XXo+X X X X+ X X X X Xqyyyu",
|
||||||
|
"ppi3, . X O+ &gfffffffg&+ + +X X X +X o +X X+ X qiyyu",
|
||||||
|
"6pp3,. X +hgfffffffgqX o +XX + X X ooX X X X X X X X %yyyu",
|
||||||
|
"pp5i, X+ +X &gffffffffgO X X + ++ + X oX X X XX Xyhyy",
|
||||||
|
"ppi3# . +X Ohgfffffffgi+ + ++ X X X +X +X o X XX XX X Xryyu",
|
||||||
|
"p5ii# Oigffffffffg* X X+X ++XX+ + +XXXoX XX X X X Xryyu",
|
||||||
|
"5pp1*. X +XX Oiggfffffffhh OO X+ + + X+XX +.X X o+ X XX X X&uyy",
|
||||||
|
"5pp3@ X +XX ihffffffffgh#oX X+O + X X o o X X XX X X*uuu",
|
||||||
|
"p3pi. + X+eggffffffgiqO +X++X oo o + . ooo + X X X%uuu",
|
||||||
|
"p53p. &ii&&&&#O+ + + O*hgfffffgi&O X o O ++ oo .o.o$OO% . X X X $hyu",
|
||||||
|
"p5i3. 3hfffi3rihhhii3r&& X oihffffgi&&XXoX+X X O+ X ooooo+*@*=#=*=*&, X . XX X$hyu",
|
||||||
|
"p5i3 .idffg&iiiiphhddhip& Xo &hgffgi&&* o X oX X X X oXX o.Oe,22,,2112s%oXX . X Xryy",
|
||||||
|
"5ii,. Oihgggiiiihhphhhiihi* X X XXOhdggh&ii XX O XXX+X+X+X+ oo .ooe,=222e22eso.o$... . XXryy",
|
||||||
|
"p3p# Opgghfiiihgggdgghhhhi* oX ehgheid*XXoXXX X+ XX+X+ X ..&ieeq*1ee,eeee&,e=2=#--&* X Xquh",
|
||||||
|
"pppO *rpggiqqiiiiihiphpphiio OX o.&gsieii. X+ XX+X + .@&ifseeeheeeeehq,de122=17i*. . X*yu",
|
||||||
|
"p3p. . O&&q&&iiiiiihihihiiiii X X + hp&&3O X + X+ + + +.@=,sgh1e,heeesqhe,s11222221&% + X+ X%uu",
|
||||||
|
"ppi. . +oO*&&e&i,iiiiiX XX X &i**& + X + XX X +@-,2212eeieqee,,ee*,22222222@o X X X%hu",
|
||||||
|
"ii,. .XoO +&OO+ XX ++ +..+@>6a5=2,eih*ihf*&hie=22222==1o + X XXOyy",
|
||||||
|
"5p,. X +** X +X ..*-375522=eigqeig&,ie,222222=2<oo X X X Xyh",
|
||||||
|
"5i# + O+ + XX oo.@O##O@@@@O**oo+*+OOO..@@....@. X XXX XXXuy",
|
||||||
|
"ip# X o .oo....+..ooo.XooX Xoo..oo..+.. X + Xrh",
|
||||||
|
"p3@ + X oXoX .oo .oXo .oo .oo o .oo X + + X X X X XXqy",
|
||||||
|
"pi@ X XX +o+ X X XXX XX.. XOoX X oo X X + X X XX&y"
|
||||||
|
};
|
BIN
Tests/images/hopper_bw_500.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
Tests/images/hopper_g4.tif
Normal file
BIN
Tests/images/hopper_g4_500.tif
Normal file
BIN
Tests/images/hopper_gray.jpg
Normal file
After Width: | Height: | Size: 5.2 KiB |
BIN
Tests/images/hopper_webp_bits.ppm
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
Tests/images/hopper_webp_write.ppm
Normal file
Before Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 3.8 KiB |
|
@ -1,175 +0,0 @@
|
||||||
/* XPM */
|
|
||||||
static char * lena_xpm[] = {
|
|
||||||
"128 128 44 1",
|
|
||||||
" c None",
|
|
||||||
". c #CC9966",
|
|
||||||
"+ c #663333",
|
|
||||||
"@ c #996666",
|
|
||||||
"# c #CC6666",
|
|
||||||
"$ c #CC9999",
|
|
||||||
"% c #FFCC99",
|
|
||||||
"& c #996633",
|
|
||||||
"* c #FF9966",
|
|
||||||
"= c #663366",
|
|
||||||
"- c #FFCCCC",
|
|
||||||
"; c #CCCC99",
|
|
||||||
"> c #FF9999",
|
|
||||||
", c #993333",
|
|
||||||
"' c #333333",
|
|
||||||
") c #CCCCCC",
|
|
||||||
"! c #996699",
|
|
||||||
"~ c #CC6633",
|
|
||||||
"{ c #666666",
|
|
||||||
"] c #999999",
|
|
||||||
"^ c #666699",
|
|
||||||
"/ c #330000",
|
|
||||||
"( c #663300",
|
|
||||||
"_ c #330033",
|
|
||||||
": c #999966",
|
|
||||||
"< c #FFFFCC",
|
|
||||||
"[ c #333366",
|
|
||||||
"} c #660033",
|
|
||||||
"| c #CC99CC",
|
|
||||||
"1 c #9999CC",
|
|
||||||
"2 c #660000",
|
|
||||||
"3 c #FFFFFF",
|
|
||||||
"4 c #CCCC66",
|
|
||||||
"5 c #FFCC66",
|
|
||||||
"6 c #666633",
|
|
||||||
"7 c #993366",
|
|
||||||
"8 c #FFFF99",
|
|
||||||
"9 c #993300",
|
|
||||||
"0 c #333300",
|
|
||||||
"a c #FF99CC",
|
|
||||||
"b c #CCCCFF",
|
|
||||||
"c c #CC9933",
|
|
||||||
"d c #CC6699",
|
|
||||||
"e c #000000",
|
|
||||||
".....*...*.%*..#&@#&@&#&#&#.&#.#.#.#.#.#..#.*.#...#..#.#.#.#..#..#..#..#..#.#.#@#.>..>...*..*...*....%%%%.&&.@.#.@.#..&#.~.#&#$.",
|
|
||||||
">%*..*.*..*%.*.&#@&#@#&#&#&#*&.#.#.#.#.*#..#&.~.#.#.#.&.#.#.#.#.#.#&.#..#&.@.@&#&#.>.*.*...*..*..*...%%%%%&&~@#&#.@&##.&#.#.@.>@",
|
|
||||||
"...>...*.*.>.%*&#,&#&#&@&#.&#.#.#.#.~.#.#.~.>.#.#..~.#*.~.&*.#.*&*.#..#&.#.##.#@&#.$.>.>.*..*..*.....%%;%%@&@.#.@.#..&#..&#.#@+(",
|
|
||||||
".*...*...%*.*.>&&@@#@&##&#.#&#.~.#.#.#.#.##.#&*.~.#..#.#.#.#.#.#.#.#~.#.#.#&.#&@#&#.>.....*..*..*.*...%%%%%&.&@.#&#.#.#.#$.$&+++",
|
|
||||||
"..>.*.*.*.%.>.~&#&#&#.@&#&#&.#.#.#..#.~.~.*.~>&>.#.#*.#.#.~.~.#.#.~.#.*&*.#.#.#.#&#..>.>*..>..*.......%%<%%$&#.#&$&#.&#.&>@,++2+",
|
|
||||||
".*.%...%*.*..*.#&@#@&##&#&#&#&#.&.#*.#.#.#.#*.~*#.~.#~.~*#.#*#.*.#.#.#.#&.#.#.#&@.##.*..%*..*..*>.*.....%%%%&&&.#~.#.#.#.$&+++++",
|
|
||||||
"..>.*.*.%*.*..*#&,&#@&#&#&#.#.~#.~.&>.~.~#*&#~#.~>#.~$~$&.~..#.#~.~.~.#.#.#.#&$#&#&$.>.>..%*.>....*.....%%%-.@#&.#&#.#.$$,++++++",
|
|
||||||
"..*.*%.*%.*.>..#&@#&##&#&#&#&.#.#.#.~.#.*.#.*.~.~.#.#.~.##&#.~.#.##.#*&*~.#.#&#.@#&>.>%.*>.%..*.>..*.*..%%%%%&&&.#.&#&#.@++++'=+",
|
|
||||||
".*...*.*.*.*.*.~#@&#@&#&#&.#~.#&*&*&#.~#.~*#~#.#*#.~.#&>..#.#.#...#.#.#.#.#..#.#&#.#..>...*.*..%*..>...>.%<%-%@.&#.#.$@@++++++=+",
|
|
||||||
".%.*%.%*.%.*.*.&&,&#&#@&#&#.#&.#&*#.~.*.#..#.*~.#.##..#&..&*&#.##.~.#~.#~.#~#.#.@#@.#..>.>..*.*..>.*.*....%%%%.&&#.#&$,++++=+='+",
|
|
||||||
"*>.*.*..**..*>.#,@#@#&#&##&#&#*&>&*#.#~.#~.#.#.#*#.&#&.#@#.@..#..@.#..#.#~..#.#&#&#.>.>...*.$..*.*...*.*.>%%%-%&&@&$#@++/++'++=+",
|
|
||||||
"..%*.%*...*.*.*&,&#&@#&#&&#.#.#.#&.~#.#.#.~.#.#..#$#$.$...$&@.@.#.@.##.#.##.##.#.@#.#..*.>.%*.>...>.#.#....%%<-.&#.@&+++=+=+=+=+",
|
|
||||||
"*.*.*.*.*%*.*.*&#,@#&##&##&~#&*&*#*&*&*&*@.#.~.#$..$.$.-$%$-%$.@.@.&..#*#.#*&#&##&#.#.>...*....*>.*.*.*.~..%%%%%@@.@++++++=+=++=",
|
|
||||||
"%..%*..*.*.*..*&&&,@#&##&#.#.#.#.#.#.#.#.#.#.#..@>@.$$$;$%$.$-$%$.#@.#..#.##.##.#@&#$.>.>.>.*>.....*.~.*....%<%<.$+++/+=+=++=/++",
|
|
||||||
"*.*..~.~.%*.*.*# #&,&#&#&#~.#~.~#.#*&*#..@.#.$.$$.$.$;$;$%$%$-.$.&@#.#~.##.#&##.#.#....*...*.>*.#..#.~....<%%-&+++++'=+[++=++",
|
|
||||||
".%*.*.&*.*%*.*. @#&#&#.#&#.##.~.#.#..>.#.$&#$@.$$:$$;$;$;$;-;-$.@&#$#.#&###&@.#..#.>..>.>..~..*#*.*.~...%%<-@+++=++=++=++=+",
|
|
||||||
"*.%*&,&*.*.*.* @#&##&#.~&*&>~.#.>@#&.@#.@$.@$.$.$.$;$;%-;.)%-%$&@.##.#.@.##&#.>.*.#.#.*&*.*.*.#.#..*...-%-+++/+{++_++=+}+",
|
|
||||||
"*.>.~&~..%*.*. &#&#&#&#.##&.#~#&*&##.@.#&$#.@.$.$;$.%).;-;$;$)%$&@&@#.##,@@.#..>.>..>.>.~.*.#.#>.>.#.*.-$+/+=+=+=++=+=+_+",
|
|
||||||
".*.&#(#.**.%*. @#&#&##.#&*#.#..##.#&#@.$.$@>$$.$.$%]%;$;;-;)%)%--&@&@&#&#&##.#..*.#.#..>..~.*..#.*...#..++='+++=++=+'+++@",
|
|
||||||
"%.#&~&~..*c*.* #@&#&#&#.#&*&#*#.&#.#.#@##.&.@.$$.$%$$;$%]%)$;$;-<-%@&@$&##@&#.>.>.#.#&#.*.*.*.>*.~.*..>++++=+=++'=+++=++$",
|
|
||||||
"*.~&,&#.*%.*.*. &#@#&#.#&#.#.#.#&#&#&@.#..@$#.#.@.$.]%;-;-;$;$;-;)--<$@#&,@&##.*.*.>.#&#&$..*.#.*.#.*$.$&++/+++='=+}+=++@$$",
|
|
||||||
".#@&,&#.*.*%*.*& @&#&#@&#.#.#.~&*.#&#.##&@@.#.@.#.$.$.$.$%$;$)-3))-;;-;-&@@@#@#&#.>.*.#.@(,$#...*#.**.*..@++++!'+}+=+=+@+@@$.",
|
|
||||||
".&,&#&&>.*..*.#&#@,&#@&#&#&#&#&#.#.##&#&#.#.#&$.#.$.@.$.$$-$;$$%)%-;-;3;)<-)&@&@&,#.~.*>.>#&,+.@**.*.~>.#.>.+++'+++=+=+=++@@@.$.",
|
|
||||||
"&#&#&,#..*%*.*.,&,@@#@#&##&#.#&#&#.&~#.##&#&#.#$.#.>.#.$.;.$$;-;-)-);)-)<)%3-++@@&@#.*.*..>@,+@@..#*.*~**.>+++_+='++=+=+=++@.$..",
|
|
||||||
"&,@,&@&>.*.%.>.#&+&#&@&#&#&#&#.#.#.#&#~.#.#.$&#.#..#.$.$.$$.-;--)%)););););-<-&+,@~@*.**>.#&+2+@>*.*#.*.#>&2+++=++=++_+++@@$$...",
|
|
||||||
"&#&@,#&>.%**.*.&,@,&@#&@@#&#.#&#.~#.#&#&#&#&#.@.#.$.@.@.$.$;-$-;-;-)-;-);-);-)-$+@&#.*..*.>@++++@.#.**.>*$,+/=+=++'=+'+=+@$$.$..",
|
|
||||||
"@,#&@&#.*..%.>.#&@@,@##&#&##&#.#.#&#&#&#.##.#.$.$.#..#.@$.--;%)$-)%));)<))<)-<)%@+@.#.**.>.#++++#@.>&#.>.@++++=+'+++=+++@$.@..-.",
|
|
||||||
"@&@,&,&>..**.*.#&,&#&@&@#&#&#.#&>&#&#.#&#.#.#.#.#.>@.@.$%).-$;-;$-;-%)-)%)-;)%)-$+@&.*..*.#@+++++.@...$.#++}=+=+=+=+++++$$$.$...",
|
|
||||||
",#@,@&#..*...>&#@+&@,@#&#&#.#&#&%#&.#&##.#.#.#.#...#&$.-.-;$;$-;)-))-;-;-;)-;3;3-@@&$.*.*.>&++++/@.-%%$$+++++++=+'+=+++$.$..$.$.",
|
|
||||||
"@,&#@,&#%.%*.*.&,@,&#&#&#&#&#.#.>&#&#.#&#&#.#.@.#@@..$%$%$.-;$;-;-;-;--)--;)-;);-$(#..*.>.>@++/++--;-<<)/'+[+=+++=++'+@$&$.$%.$.",
|
|
||||||
"@,@&,&..*.*%..>&,&@@,@#@#&#&#&#%>&#&#.#.#.#.#.#..&@.$%$%]%).-;$;-;$)%$;-%)-;))<)3-@@...*..#@++=@-)%)%)-<{+[++{+=+='}+@:$.$..$.>.",
|
|
||||||
"@&#@#,&#.%.*.*.&,@,@&&#&@#&#.#&%>&#&#&#&#.#.#.@>&#.$%$.-.$;$;-;$;$;-)--)-;-)%);)))%@..*.*..@++]-]$<);<)-]'='=++++=@++$.$..$..$.$",
|
|
||||||
"#&,&#&#.**%.%*#&,&&##&#&#&##&&#%.#&#&#&>&#&.#..#&-*$.$.-$-.)$.-$;$-.;-;.-)%;);-;-)).$...*>&&+$)$))--;)%)$+'+=+=++'}'$$$.$.%$....",
|
|
||||||
"#&@#,~&*...*..*&@,@&&#&##&#.#&.%*&#&#.#.#.#.&#.&.>%.$.$.;-$%$).-$;-$;--);$);-);)-))-$.>..~@.%;;-;));-;3-{+'+++=+=++@@$$..$...$$.",
|
|
||||||
"@&#&##&*.*5.%*.#,&@,&#&#&##&#&>%#&#~@#&#@.##.@.>..#.$%$-$.).$;$;%$;-.;-%)%$;-;-;);-;%$....%--$3)-;-));-)++=+[+/++/+@$.$$..$%>..>",
|
|
||||||
"~@#&,&#*.%*.*.*&@,&#&#&#&#&#@&%.#&#&~.#&#.&#.#..>.$.%$.%$.-;$.$$%$.-;$.$;$;$;-;-)$)-%$.$-%-;%;-;-)-;-3%)'+'++=+=++@$$$.%$..$..$.",
|
|
||||||
"@&###&#.*.5.%.>&,@@&#&#,&#@~&#%..~#&#&#&#$&#..>..#.>$.$.$%$.-;%.-.$%$%)%$;-)%$);%).]%-%%$.-;-);-)%)%;-3-+'=+_++++@$$.$.$..$.>..$",
|
|
||||||
"~@&#~#&*..%**.*.,(#,&#&##&#&#&%.>.*&#&#.#.#.#.#..#...$.-.$.$..$.%;$.%$.-;$%)$;$$;$;-;$)%-;-$%)-;-;-)-;-]++'+'=+++@.$$.$.>...$.>.",
|
|
||||||
"#&#&,&#.*..%.*.#@@&@&#&#&##&#&-%..#.#&#&#.#.$..#.$.>.$.$.-;%$%.-..$;.).$%$-.-$;$;$;$;$;-);-;)-;-)%$%)%-{+_=+=+'+@$$..$.%$.>..$.$",
|
|
||||||
",@&##,~*.5*%*.*&,@,##&,&#&#@&~%.**.~&#&#&#.#.#..>.$.$%$.$.$.$.$.$%$.$%$%$;$:-$-.$%$;-;-;$)-)%)-;-$:$.)-+'+'=+++@@.$.$.$...$.>.>.",
|
|
||||||
"&#,&#&#.*..%.*.#,&@&#&#&#&#&#&%..*&*#&#&>$.#$.#..$.#.$.-$.-.-..-..$%$.-$;-$$%]$;-;%)%))););$)%)%-.$@;$$++=++=++@$.$.$..$%.$..$.$",
|
|
||||||
"@&#&#&#..*.*.*.&@,@#&#&,#&#&&#%.*.*.&#.#.#.#&$.#.>.$.$.$.$$.$$$.$$$%$$%$.$;$$.$$;$%$;)%)-);-;-;-.).$$-'+'+='+'@@.$..-.>.$...$...",
|
|
||||||
"&#@,#~#*.%5%.%*#+,&@,#&#&##&#.%*.*.*~&#.>@#.>..#&$.#$$$$$.$$@@$$$.$$$$:$$-.$;-;-%;)%)$;);-)-;--$;@.@;-++=+=+++@$.$.$..$..>$..$>.",
|
|
||||||
",&#&#&&*.*.*.*.~@@,&#&#&#&#&,.%%..*..#.#.#.#.>.#.$#..$&@@@@@$$@$-$$]-$$+.{$%-$;-%$;-;-;-)-;--;-.$@:@-$/++_+=++@$.$..$.$.$..$..$.",
|
|
||||||
"@&#,##~.*.%.%*>&,@@,&#,&#&#&,.*.*.**.&#.#$#$.#.@*@.$>@$$@@@+$)@!]+@@@++{+$;$:-%]%)%$;-);;--;-%$@&+@%-+'+=++++@$$.$.>.%.$.$..$..$",
|
|
||||||
"&#&&#&#*..5*..*&,@,@&#&#,#&#&&%%%*.*.#.#&#.#.$.#.$#.@$@@@{!@!@!+=$=@'+++@$$-$%-;)-;).)%-%)%$.@&@&$%)+++'+==++.$.$%$.$$.$.%$.$...",
|
|
||||||
"#&#@~#..*.*%%*.#@+#@#&#&&#&,&~%%5*.~.~&#.$#$&#..#.$#$@$@!@={=!!@[@[@=e+)$;-;);$%;$-;-);$<$&@6+@&]$-(++++=++++$$.$.$%.$..$....$..",
|
|
||||||
"&#&#&##*.%..*..~#+&#&,###&#&#(%%%...>&@#.#.#.#.@>.@#$@@+@+=+!{=!!=+!++)@-]%$%)%$;)$;$%)%@]&@&@.$.)+++'++=+=+@$.$%.$.$.-.$.$$..$.",
|
|
||||||
"@#&##&#.**%.%*.#&,@,@&#&,#&#&#.%5....#@>#$&#.$#.$$@$@=!==+=]!_+=@[+{+$$)%$);$;;-$-;---@@@@.:%.-$-++++=+=+++@$.#.$.%.$.$.$.$.$$.$",
|
|
||||||
"&&#&#~#...5*%*.&,@,@#@#&#&#&&,&%%%%..@.$.,.#@&$@,$@+}@='=/={+=]!_!/!$]%$;).-$;$;)-$;.@{@@$-$..%%+/'++=+'=++@$$.%..$.%..$%$.$.$.$",
|
|
||||||
"#&#&#&#**.*..**#@,&@,@#@#&##.#&%%%..#$##&#.&$.$$+@+!@=+!={=+={=@@_]$@-;$%$;$;$;$;-.$(+@${@:%.--+++++=+=++++@..$.$%.$.$%$.$.$.$$.",
|
|
||||||
"#&###&#.%.%*%...,@,#&#&,#&,&#&#&%%%.&..#$#.>@#@@@@=@=+=!+_'+=+='!!{@)$--;$;$;$%;$)%]&@@@$@$$%.(+++++'+_+=+@$.$%..$%.$..$.%$.$..$",
|
|
||||||
"#&@&#,&**.%.*%*&,@&@,#@&#&#&#&&9%%.>.#@..@.@.@@@@@@=_=+=@_+=@@!+!]@$).;$.-.$;$;-;-%-.@@@@@:-@++++++=@+'+++@@@.$.%$..$..$.$.$.$.$",
|
|
||||||
"#&##&###..*%.*.~@,+#@&###~#&#.#&.%%.&.,.#&#$@$@+=+@=+=^@[+++=++!@]@)$%).).)$.).-;$;%.+@@@$@.6+/++++++=+=+@$&$%..$.$.-.$..$..$...",
|
|
||||||
"&#&#&,&*.%.%*%*#&,@&#,@&@&#&#~&#&-%#.#&#&>.@@@}+=+={!==@!+'+'+@+$1$)$%$.$$.-;-%;-%-%$@++=@]$+/+=+{=+=/+++@$$.$.%.%..$.%$.%$..$.$",
|
|
||||||
"#&@##&#.*%*.....,@,@@&##,#&#&>&#&%%&#&.@.@>@@+!+='+==+![$!+++@@$]$-$;$;$%$.$;$%-;-%%%$++@+$]+++=+++++'+++$@$.$.$.$$%.$.$.$%.$...",
|
|
||||||
"&#&#&,&#..%.%*>&,@(##@#&#&#&#.#&#->.&#&>&@++!+=+=+=+[=+=@++/@$$$$]$).$..$;$-%-;%-%;%.$@+}{$$+'+=+={+=+++@@$.$..$...$..%.$.$..$.$",
|
|
||||||
"&#&##&#*.*%*...#&@,@&#@#&##.#~&#..-&#..#$@@++++^+==+^=@!'=/@$$$-$$$-;-.$.$%$%$%-%--%%#@+}@]$@++=++=+++++$@.$.$..$.$.$.$;..;.$...",
|
|
||||||
"@&#@#,&...%.%*.#&@,@#&#&#&#~$~#.##%#.@.$@++!_=@={+=+=='=+@{@.$;$)&$%$.$.-$%$%-;%)%%%-%@+++@${+={=++=+++@$$.$..:.$.$:$.$.$$.$.$$.",
|
|
||||||
"&@&#&,#*.*%*%*.&,@@&@#@##&#&#.&#&$@.@.#@+!++@'+=+'=+=+=@'@$:$.$%-:-$.$.%>%$-.-%%-;-%%>@@+/@$++=+={++'++@@$$.$%$.;..$..$..$.$:..$",
|
|
||||||
"#&#@#&@....%.%>&#(@#@&#&#&#&##*#@&#.#$@@+@_!_=+{=+={==+/+@@$.$;$$$..$%>.$>%$%-;.-%%)%-$+}+@)@++={+=++++$..$;$...$$..$:@.$:$.$$$.",
|
|
||||||
"@&#&#~##..*%.*.&@@,&#@#@##~#.&#.>++&$.@+=+=@=+=++++='+^+]@-;-..-%$@&&#.>%>-.$%-;-)%%%$#++++-@+@+=+[+++@$@.$..$;..$.$.$.@.$$.@.$$",
|
|
||||||
"&#@,@,&*.%..%%>~@(@@&#&#&@&##.*.#+2$@@@+!=^!'={+_+=@!@_+@:-.).;-.$.$.,(#.>$%$%%%$;-%.@@++++%@+=+{+=+++@$$.$....$;.$:.$.$.$.$$@.@",
|
|
||||||
"@&&#&#@#.*%.*..&#@,@#&#&#~#&#&>.$@(@@@+@++=!+=+'@/=/@+'$@)$%$.-&@$$$.$&,&#.>.$;%%$@@&@#@+++]$++=+=+'++.@.$%$.$..$%.$.$.$:$$$:$@$",
|
|
||||||
"##&#@9&..*%*%%*.,+#&#&#&#&@&>..>.$@++!=^!!/^+^+=1'+=++@:-.;-$%@@@+++++$.#.>.%%-;-$@+++@++++$@@++=+=++@$@.$.$..$..$$.$.$.$.$.@$:$",
|
|
||||||
"&#&#&#,>...%.*..&,@,&#&&#&#..$..$+@+=@!@^]=@=+'+_!'+0+$.$;-%-+(+,++@@2+#.#*>.%-;@+++++}+++{$@@+++'+++@..$.$.$..$...$.$.$.$$$$$@$",
|
|
||||||
"&,@,@(&.**%*.%*&,@,@&#,.,&#-.$.@$++^+^_=!@_'+==/^+_++@:.-.-%+@,++@++--(@~.#.>%%$++@@a+++=++$]@=+==+++.@$.$.$.$.$.>$.$.$$.@.:@@.@",
|
|
||||||
"#&#&#,,...*%.*..@,&##&#&#@+,$$$(+/@=+=!+^1+[+'+='=+'+@$$.%-&@&,&@+@@$-#@#&#..)%6@+@@$7++++@@$@@++=+++$..$.$.$..$..$.$.$.$.@.$:$.",
|
|
||||||
"@&#@,&@#.%.%*%.~#,&#&@.,+&@--%+++{!'=!=^+!+==+=+=+'+$..$;-&&$$@@&$.--%.$~#*.>%-@.$#$$,@+++!{$@@+=+'+@:$.$.$.$.$.$..$.$.@$:$.@..;",
|
|
||||||
"#@#&@,&#.*5.%*..&@#&##.+#$$$@++@@'}'={=!!!'/'=+'=+++@-$%-&@...*$#$@&@$-.#.#.$%;$.$.@,+@}++@@|{++++++@$.$.$..$....$.@.$.@.@.;.%%%",
|
|
||||||
"#&@,@,&#.*%*%.*.,,&#&#$#$$+@=+'+1$!==^={$1+=++=++/+$]$.-&&*#>.$.$.$.-.#.>.#*$-%-$.##@#@++++@$@+=+=+@.@...$.$.$.$.$.$.@.$.$.$%;.%",
|
|
||||||
",@#&,+,.>.%*%.*.&#&#.@&$@!+!+==@!{^'==!!!!{+='/='+@@$--#&#...>.>.$.$.$%#*#.*$%-.$.$.#$,@+++@$@@++++@$.-$..$.$.$....$.:@&$%%%%%.%",
|
|
||||||
"@&+@,&+...%.*%.#,#,@##$#$$|={={^{!+_=]={@$!+++=+++@$$%$&@.#*>.>%$%%$%$..>.#.>%--.*>##@@+}+{+|$+++++@....$..$...$.$.@.@.;%.;%.;5%",
|
|
||||||
"@,&,@+,#.*%*%.*.&,&#.$@$+=+='=!+!{[='==!^/@!'++/+@]$--(,#.~.*..>.>.%$%>.*#*#$%-%$...>##+++++$]+++++$@.$..$.$$.$.@:$...$.-%.%%.;%",
|
|
||||||
"@,@+,&+...*%*%.~#&,@@#$+!@^=!'!1'_+==+=+++]@+=+++$$$)++&#&>~>.>%%%$%..$.*.#..---..>.#$#+++++-$++++@.$...$...$.@...@.@.%;%%;%%%%%",
|
|
||||||
"@+@@,+,@>%..%*..,#&#&@@$!{=!==!{=='+[+{=++$@@'/+$&--@+/@~#*~.>.$>%.%>.>.>*#~$%%-.>.#.#@,++++$$++++@$.$..$.$.$.:$.$.:..%%.%;.;%;%",
|
|
||||||
",@(+,+&#..*%.%*&,@#@@$$+@!]={^@!{+=='_++++$@$@+/@$-)+/@@#.~**.>..>%$%..*#.~.#$-%...>$#++7+++1$++++@.$.%..$.@.$.@.$&$.;%%4%%%%;%%",
|
|
||||||
"+,@@+,+&>.%*.*..&@&#$$+!@^===!1]|'+=+}{@+@$$+++]@%$+++/&###~#..>...>.>..#*#..%--.>..>@,+++++$$++++$.$.$...$.$.:$.@...%.%.%4;%%;-",
|
|
||||||
"@@+,+,+..*.%*%*#,,@@@$@+!{={1{=$=/'+=+@+]@+@/'/$@%@'++@@~*~**>.$*>%..$*.~.#*@.-<..$#.@+++!+/$$@++@$....$...$.$.@.@.$%%454%%%;-%)",
|
|
||||||
",@+@,++#$%*%.%..,@.#@@@=@!==!=^][+='/=@$@.++++$@:$+/+/@+@#*#*.*$..>.>..##*.#..--...>@,}++@+/$$$+(@@$.$..$.$.$.$.$@..%%%%4%;%;%)%",
|
|
||||||
"@,@++(,....*%*..#,@@@$+@!{=@^+!!{|+={++=+@+/+@;$-@+'++@,#&*#.#.>*>.%>*#.*#.#.$%-.>.@$+++=++++$$/+.$.$.$..$.$:$...@.%%.4%%%;%%;%;",
|
|
||||||
",@,@,@+.>.%..%*&&&,@@@@!@=_!='!!]1+={}'+!++++$-$]+/+++@@&#*~*>.>.>.>.$*.#&#&#&>.*..#@+=++++++$$+&$..$.$.$.$.@.$.$..;%%%4;%%;%-%%",
|
|
||||||
"@,@,+&@...%*%*.>#+#@$@+!+=]=!=]!|!'+!@/++/@@@$6-++=+/+#@~#.#*~>*.#*.*.>.*..#.$%$.>$@+}+=@++++-@+@.$.>.$..@..$:@.@..%%4%%%;%;%;;%",
|
|
||||||
"@+@@+,@.$*.%.%..&+&#@$+{!@=_{=!!{!!'@^++!@$$@@$+'+++++#@$~#*#.#.>.>>.>.#.>.%%-%$..#@++++!+@+($$@#.$.$..$.$.$..$..$.%%%;%;%%;-;-;",
|
|
||||||
",@,+@+#..%.*%*.##,@@$@!+!{==={={=1@={@/+]$$$@@@+++=@++@&#.~*~**.#...*..>..>-.%>.>$.++=++@+++/$.@...$.$..$..@.$.@..%%.%5%;%;-%<%;",
|
|
||||||
"++@+,+@.>.%.*%..&@@#@$+@!+!'==!!^!1+@'+@@$-@@]+++@++++#+##.#.#*.*.>.>.*.>..%$%%$.$@/+=+7@@++($@@$.$...$.@.:$.:.@..%%%;%<%%<;%-;%",
|
|
||||||
"+,@+@,&$..*%.*.#&,@@@!+!+[=@^@[+^={|++.)$-+@$++{+=+!+++&#.~***#.#*.~.#..*$*>%$.$#@+++++=+@,++@:....$.$..$.$.@.$.@.%%%5;%;;%;%;-<",
|
|
||||||
"++,++@,.>%.%%%.#&@#@$@=+!'===!{=^!!{@)@-%@@@+/+@}++++++@##.#~.**.#&#.~#.#&.#.,&@>$++++++}@++(@@@.$....$...$..@....%%%%%%%%;-<%;%",
|
|
||||||
"+++@+@&$..*%*%*.@$,@@@@=+={^'|!{!!{+@$&3$&]$++=+++=+=+,+&#~.#*#.*>*~#.~~>&#.>$.$$}+}'+=+@@+@+&$.$..$..$.@.$:$.]@&%%;%4%;%;%<-;%<",
|
|
||||||
"@++++@&>..%*.%.#&$+$@@'=+_=@=]=!^!={]$$;@$$++'/=+++@+++@@&#~.~.#.#.*#*#.*>%-*#$>@+++++++}@2@+&$.$..$..$:.$..$..$&%%%%%<%<%;%%;%%",
|
|
||||||
"++7+,+@..>.%%*..#+@@d+@='='=^@[@^^@!$]$$@-+++++++=++=+@,,@~@~#*~.*>.~.#*#.>.>.>@+_+=+++@+@+@2+$..$..$..$.$:@:$@:@;%;8%;%;%-;%;%;",
|
|
||||||
"=++++@&#.%.*%>..,@$@@+!+=$[@b{!{=^!]@$$$-+@+}{=+++++@++@,@#&#.#.#.#*#*#.#~##$#$,+=++{++@7@}@++.$..$..$.$.$.$.$.@.%%%%;%<%;%)%%%%",
|
|
||||||
"+++++#@..*%.%*..@,$@@+!'_=='|^@1!+1@@{$-@++=++++++=+{+@++&#&#&>.#*.>..#.>..>.>@@/=+++++@+@+@++.$...$..$.$.$@:$@:@;%<%%<%%<%%;%;%",
|
|
||||||
"+=++@@@#..*%.%>.@+@@+@@='@[=$^!]!^+1$+]$+++++=+=++++=+++++,#&##.#.#.>*.>.>$%$.++=+[+{++@+#+#++$.$..$.$.$:$.$$$.@&;<%;%;;%-<%%%%%",
|
|
||||||
"+++++@..>.%*%..#@,@@=+^+=^+^]='1|]=]$@@+=+=++'+++++=+'+++&+,,&#.#....>.>%$.>$#(++=+++++@@+7@@(-.$.$..@.$.$@:@$@].-%;<%<%;%%)%;%%",
|
|
||||||
"+=}++@@...%.*%*.@+@+++!+'='_!]={!!]!!{!+'=+=+='@+++++=@+++(+(,#&#.#>..%.>%$.$@+++'={'++@+@+@@+.$..$:$.@$.$.$.@:@:%<%;%%<%;%%%%..",
|
|
||||||
"+++++#@#.*.%*%.#+@$@=@==+='=]|={!^|{|$1@_+'}{@}@_+'+=+++@+#+,+,(#&&#.#>.%$.$.@++=++++++@!@+#++%$&@.@.$.]$$@$]@$&.;%%4%;%%%-$$+++",
|
|
||||||
"++++++&$>.>..*..@-+$+'@={=+{!]=={!^!]!{)!'=++=+@+=+++=+=++++&#.#.#.>...$*.$%$.@+'='@{=+@+!+@@($.@.@&$@.@.@.$.@]@%%<%%%%;%;.(++++",
|
|
||||||
"++++}@,&$%*%*$*.-++===+=+=+_{|]=[!$^@^!+]@'=@++=+++=+'+@++,@#@#$#.#.>.*.$..$%$;-@+'++++!@@@+@($.&@.@.@@@.]@@.@&$;%%4%8%%%.@++++@",
|
|
||||||
"@@+++++#.>.%.%>.+@]++_{='!{+[@^@|]^!^@^|]!++='+@=+'=++=++++@@#.#.#.#.#..>.$.-%----]/'++++7@+@+.$.$&$&@&@@&@@@@@&%;%%%%%;$&(++@@@",
|
|
||||||
"@!@@+@+&..**%*..@++='+=@_+^@='|^!!{^@1@^$+1+@+=+++++=++=@++,@#.#.#.>..>...%.-.-;-)--+++@+@@+,@.@.$.@.$@.@@&@&$&@%;%;%;%.&+(@,+@,",
|
|
||||||
"$]@@@++,.$%..%>.$@++_+|{=]+^+={={==!{!]!{={{=++=+=+'=++++@+@&#$##.#.#.~.>.$.%%$%%)%3;@'+++@++@$.@.$.$.@.@@@&@&@&%4%%%%$(+(@&@,@@",
|
|
||||||
"@$$$@@2@.*.*%*..$@+=+_+=@_@'!{=$={'!^$!]=$_$+'/@=+=++'=++@+,@.#..#.*.>..*.%%$%.;$%;-%-$+{+@++.$.$.@.@.@$&$@&$.@&%%<;%%@(@@@+&@&@",
|
|
||||||
"{$]$@@+@$%.%*.>.@)/'={=+='=+=+[{==!{!{1@1+)=+=+{+'+=@+++@@++#.##.#.#..#..>...$%%;%-;%<)@++@++$$.$.:$.$.$@.@@&$&%;%%%;.@(@&#@#@,@",
|
|
||||||
"+@|$$@(,..>%*%..@@+/=+='=+{='=+={[+=!!]|]!+{$+/=+=++=++@@@#(@#&$*.#.*#.*..%.%.%-%;%;-%--{++++$.$.$@.@$@.$#.@.&$%%%;%%@(@@,@.@&&&",
|
|
||||||
"'@]$$@++...%.%*.$@+=/!+=+=@=+_{==@^{+^!@|{=|)=++{+=+{+}+@@@(,.#.#.*>.*.>.>..-..%$%-;%<;--+@++.@$..:$..$.@.@.#..%%%%%.&,@&@#@,@#@",
|
|
||||||
"++]$$$+&.*%*%*.$$+'=+[='_'$'='_@^{!!!{!]|'=@-+/!+=++=+++#@#2@.#.#.#.~>.*..>..%$%;%;%-;-%)++++$..$..@$@.@$.@&..%%%<%%$&@&#@@&@&&@",
|
|
||||||
"''$]$@++$%.%.%*.$++'=+=+=@!'+=+='=+{!'!1!@={|'+@{=+++++@@@&2&#.#*~.*..#.>.%$..%.%$;%%;-<-)++($.@.$...$@.@.@.$%%%%%%.&&,@&##@#@@@",
|
|
||||||
"++!$$$(+..*%*...@+_@_+[+[@@_{='=+[={!=@^$^@!{+_+++=++++#&#@(#.#..#*#.*.*.>..%$.-.%-;-%)-;3/0@@...@.$@.$@.@..%%%;%%%$&#&#@&@,@@#&",
|
|
||||||
"''])$@(+..%.%*..@'+'+[+=@[++=+=+='+=]=!]|]!@^++=++@++++@#.#,~.*#*..#*#.#..>.$%.%$;%-%;-<--@+@.$..$...@.@$&@%<%%%%%%&&&#&#@,@&@@@",
|
|
||||||
"/+@]$$+($.%*%%*.@@==/='=+]='+'='=+^='!{|=]|$@{++=+++},@#.@(&##..~**..#*.>.>.>.$%.-;%)%--;-)(]..@..@$.$.@.@:%;%4%%%$&#&&#.&#@@@+@",
|
|
||||||
"''!)$]+,..%..*..$++'+=+[+!@_!+_+='!+=@!1$_'[+=]$@=+++@@#.>,&&*#.#.~*#.*#.>.$.%$.-.-;-;-;-<$+&]..$..@.@:@.@.%%%%<%*.&&#&#@,&@,@@@",
|
|
||||||
"++{$$$@($.*%*%.>@'+=+'=+'='+'=+'=+^'^^@^@1+=+++@+@@++&#@.#(##.#*.*$*.#.*#*.*$..%.%%%-;-;-;-(@.$..@.$:$$.@...%%8%%.#.&&#&@@#@@@,@",
|
|
||||||
"_/!]$]@+.>%.%*..$++=++{=++=+=+=+{=+^+^]1+^@'/={++++2+#&#@#+&#.*.#.~.**#*.>.*..$..$;%%-<-%)-:$.@.$..$@.@:@...%.%%%.~#&#&@,@@@+@@@",
|
|
||||||
"+'+$]$+&&.*%*%.>$@+'+=+'={={+=+=+[+^='!^+^@|'++=++++@&#..#&#.#*.*.#*#.*.#*.>.%.%.%.-;%);-<--:@.@&$.$$].$&.....%%%.&#&@,&@,@#@@+@",
|
|
||||||
"_+{$$]@+$..%.*..$@}'++='+=+='='+!'_$!'={[@^@=++/++++#@##@2&#.#*#.*.*.~>~.*..>..$..%$%-%-)%-<@&@&@&@.@$@.$....4%%.#&,&@,@&@@+@@@+",
|
|
||||||
"+/=]$$&&&>%*.%..@@+=+'}=+{=++=+_=@!{!={=={!+'_{+=+++#&$*@(#.#.>.*#.#.*.#.#*...%.%.%.;-;-;-;-.@&+(@@@@@@$...&.%%%.@&@,&@@@@@&@@++",
|
|
||||||
"+'+]$)@+...*%*..@++'=+'='=+[+='+'_+^$|{!]='=++=+/++@#.##2&#.#.*#*.*.*#.**.*.>*.$.$%$%;-%<--<$6@&@&+({(@+&$..%%%..,+&@,@@,@@@@@++",
|
|
||||||
"+++$$).(..%*%.%.@=+++=++='={+=+==+=={|!^@=+^/=+/+++#@#&,(#.#.*#.*#.*#*.#.#*...*.%..%$%;-;-%--&@@@@@++++(+%%.%%%.@(@+@&@@@+@@@+++",
|
|
||||||
"{@{]$]$+&..*%*.&$@_'+'='+=+='=++='=+_{$^!{='=/+=++@#$#&2#.#.>.~*.*.*.#*#*.#.>.>..$%.%-%-;3;-%{&@&@@@@++(,%>.%<.&++,@+@@(@@@@@+@+",
|
|
||||||
"@@@$$;$&@%%.%%.&$+++=+=+='=@=+[/=+='=!_@!{_++[+++@#@~,(,.#.#.*.~*#.**..*.*.*...*..$%.;-;-%-;-$@&@@&@@++(+.%-.>&(+@+@@@@+@@@@@@++",
|
|
||||||
"+{@]$]$&&.*.*%%&@=+=+'='+='='=@='!+=+^@^+='=+/+++@@#(2,~#.#.#*#.*.~.#*~.#*#.#*.$*.$%$.%-;)%-<-6@@@@6@@+@&>%%$&+(+@+@@+@+@@@@{+@+",
|
|
||||||
"@@@$$.]&@.%.%...@++'=+=+=+=++={}+!'!'=@1+=++++}+@(,(#~..~#.*.**~*.**.*>.*.~.*.>..>.%.-;%-;-%--+@&@@@@&@&#.>.&,&+@+@@@@+@@&@@++++",
|
|
||||||
"+@{@)$$&..*%*%..{++=+{='='=^+!@='!+=]={!{='=++++,(#&&#~#.*##.#*.#.#*.*.~.#*.#.**...$%.$;%)%);-:@@@&@@@&@&..,@(@&+@@@@++@@@@@@+++",
|
|
||||||
"+'@@$)$&@..%%%.#++_+=+=+!+=@[+=@={!_+={!@++++/+,@&.#*.*~#..~.#****.~.#*.*..*.*#.>>.%$%%$%)%----+6@@@&@@.##&~@#@+@@@+@+@@]@@++{++",
|
|
||||||
"+++{$-)$..%*.%.@++++'+{='='@={=$=+!'^$_+^+_+++@$&#&~&~*.~#*#*.~.~.*.*.#*.#*#.*.*..>..$;%;-;;-;-+@&@@&$&#&&#&#&@@@@+@+@@.@@@+++++",
|
|
||||||
"++'@)-.$&$.%%%%&+'=+==+=+=={=@={@[@='={!$@+++,@,.&.#*&~~.*&.#*#*#*~.*.*.*..*>.*>.>.%.%$;%)%--;-@&@&@@.@.#&#.#&@@+@+@@@@@@@++++!@",
|
|
||||||
"++++-))$...>.%.@++_++{={'=@_+=+={=]+_@[/^@+@+@#@#.~.~*.~*#*#*.~.*.*.**.*.#*.*#.*.>.$..$;$%);--)$6@&@&#.@*&#.#@,@+@@+@@$@@@++++@@"};
|
|
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 18 KiB |