Merge remote-tracking branch 'upstream/master' into diff_cover

This commit is contained in:
hugovk 2014-06-28 22:03:46 +03:00
commit e01cd042ab
10 changed files with 58 additions and 590 deletions

View File

@ -4,6 +4,9 @@ Changelog (Pillow)
2.5.0 (unreleased) 2.5.0 (unreleased)
------------------ ------------------
- Remove obsolete Animated Raster Graphics (ARG) support
[hugovk]
- Fix test_imagedraw failures #727 - Fix test_imagedraw failures #727
[cgohlke] [cgohlke]

View File

@ -54,6 +54,7 @@ recursive-include Tests *.png
recursive-include Tests *.ppm recursive-include Tests *.ppm
recursive-include Tests *.psd recursive-include Tests *.psd
recursive-include Tests *.py recursive-include Tests *.py
recursive-include Tests *.rst
recursive-include Tests *.spider recursive-include Tests *.spider
recursive-include Tests *.tar recursive-include Tests *.tar
recursive-include Tests *.tif recursive-include Tests *.tif

View File

@ -1,506 +0,0 @@
#
# THIS IS WORK IN PROGRESS
#
# The Python Imaging Library.
# $Id$
#
# ARG animation support code
#
# history:
# 1996-12-30 fl Created
# 1996-01-06 fl Added safe scripting environment
# 1996-01-10 fl Added JHDR, UHDR and sYNC support
# 2005-03-02 fl Removed AAPP and ARUN support
#
# Copyright (c) Secret Labs AB 1997.
# Copyright (c) Fredrik Lundh 1996-97.
#
# See the README file for information on usage and redistribution.
#
from __future__ import print_function
__version__ = "0.4"
from PIL import Image, ImageFile, ImagePalette
from PIL.PngImagePlugin import i8, i16, i32, ChunkStream, _MODES
MAGIC = b"\212ARG\r\n\032\n"
# --------------------------------------------------------------------
# ARG parser
class ArgStream(ChunkStream):
"Parser callbacks for ARG data"
def __init__(self, fp):
ChunkStream.__init__(self, fp)
self.eof = 0
self.im = None
self.palette = None
self.__reset()
def __reset(self):
# reset decoder state (called on init and sync)
self.count = 0
self.id = None
self.action = ("NONE",)
self.images = {}
self.names = {}
def chunk_AHDR(self, offset, bytes):
"AHDR -- animation header"
# assertions
if self.count != 0:
raise SyntaxError("misplaced AHDR chunk")
s = self.fp.read(bytes)
self.size = i32(s), i32(s[4:])
try:
self.mode, self.rawmode = _MODES[(i8(s[8]), i8(s[9]))]
except:
raise SyntaxError("unknown ARG mode")
if Image.DEBUG:
print("AHDR size", self.size)
print("AHDR mode", self.mode, self.rawmode)
return s
def chunk_AFRM(self, offset, bytes):
"AFRM -- next frame follows"
# assertions
if self.count != 0:
raise SyntaxError("misplaced AFRM chunk")
self.show = 1
self.id = 0
self.count = 1
self.repair = None
s = self.fp.read(bytes)
if len(s) >= 2:
self.id = i16(s)
if len(s) >= 4:
self.count = i16(s[2:4])
if len(s) >= 6:
self.repair = i16(s[4:6])
else:
self.repair = None
if Image.DEBUG:
print("AFRM", self.id, self.count)
return s
def chunk_ADEF(self, offset, bytes):
"ADEF -- store image"
# assertions
if self.count != 0:
raise SyntaxError("misplaced ADEF chunk")
self.show = 0
self.id = 0
self.count = 1
self.repair = None
s = self.fp.read(bytes)
if len(s) >= 2:
self.id = i16(s)
if len(s) >= 4:
self.count = i16(s[2:4])
if Image.DEBUG:
print("ADEF", self.id, self.count)
return s
def chunk_NAME(self, offset, bytes):
"NAME -- name the current image"
# assertions
if self.count == 0:
raise SyntaxError("misplaced NAME chunk")
name = self.fp.read(bytes)
self.names[self.id] = name
return name
def chunk_AEND(self, offset, bytes):
"AEND -- end of animation"
if Image.DEBUG:
print("AEND")
self.eof = 1
raise EOFError("end of ARG file")
def __getmodesize(self, s, full=1):
size = i32(s), i32(s[4:])
try:
mode, rawmode = _MODES[(i8(s[8]), i8(s[9]))]
except:
raise SyntaxError("unknown image mode")
if full:
if i8(s[12]):
pass # interlace not yet supported
if i8(s[11]):
raise SyntaxError("unknown filter category")
return size, mode, rawmode
def chunk_PAST(self, offset, bytes):
"PAST -- paste one image into another"
# assertions
if self.count == 0:
raise SyntaxError("misplaced PAST chunk")
if self.repair is not None:
# we must repair the target image before we
# start pasting
# brute force; a better solution would be to
# update only the dirty rectangles in images[id].
# note that if images[id] doesn't exist, it must
# be created
self.images[self.id] = self.images[self.repair].copy()
self.repair = None
s = self.fp.read(bytes)
im = self.images[i16(s)]
x, y = i32(s[2:6]), i32(s[6:10])
bbox = x, y, im.size[0]+x, im.size[1]+y
if im.mode in ["RGBA"]:
# paste with transparency
# FIXME: should handle P+transparency as well
self.images[self.id].paste(im, bbox, im)
else:
# paste without transparency
self.images[self.id].paste(im, bbox)
self.action = ("PAST",)
self.__store()
return s
def chunk_BLNK(self, offset, bytes):
"BLNK -- create blank image"
# assertions
if self.count == 0:
raise SyntaxError("misplaced BLNK chunk")
s = self.fp.read(bytes)
size, mode, rawmode = self.__getmodesize(s, 0)
# store image (FIXME: handle colour)
self.action = ("BLNK",)
self.im = Image.core.fill(mode, size, 0)
self.__store()
return s
def chunk_IHDR(self, offset, bytes):
"IHDR -- full image follows"
# assertions
if self.count == 0:
raise SyntaxError("misplaced IHDR chunk")
# image header
s = self.fp.read(bytes)
size, mode, rawmode = self.__getmodesize(s)
# decode and store image
self.action = ("IHDR",)
self.im = Image.core.new(mode, size)
self.decoder = Image.core.zip_decoder(rawmode)
self.decoder.setimage(self.im, (0,0) + size)
self.data = b""
return s
def chunk_DHDR(self, offset, bytes):
"DHDR -- delta image follows"
# assertions
if self.count == 0:
raise SyntaxError("misplaced DHDR chunk")
s = self.fp.read(bytes)
size, mode, rawmode = self.__getmodesize(s)
# delta header
diff = i8(s[13])
offs = i32(s[14:18]), i32(s[18:22])
bbox = offs + (offs[0]+size[0], offs[1]+size[1])
if Image.DEBUG:
print("DHDR", diff, bbox)
# FIXME: decode and apply image
self.action = ("DHDR", diff, bbox)
# setup decoder
self.im = Image.core.new(mode, size)
self.decoder = Image.core.zip_decoder(rawmode)
self.decoder.setimage(self.im, (0,0) + size)
self.data = b""
return s
def chunk_JHDR(self, offset, bytes):
"JHDR -- JPEG image follows"
# assertions
if self.count == 0:
raise SyntaxError("misplaced JHDR chunk")
# image header
s = self.fp.read(bytes)
size, mode, rawmode = self.__getmodesize(s, 0)
# decode and store image
self.action = ("JHDR",)
self.im = Image.core.new(mode, size)
self.decoder = Image.core.jpeg_decoder(rawmode)
self.decoder.setimage(self.im, (0,0) + size)
self.data = b""
return s
def chunk_UHDR(self, offset, bytes):
"UHDR -- uncompressed image data follows (EXPERIMENTAL)"
# assertions
if self.count == 0:
raise SyntaxError("misplaced UHDR chunk")
# image header
s = self.fp.read(bytes)
size, mode, rawmode = self.__getmodesize(s, 0)
# decode and store image
self.action = ("UHDR",)
self.im = Image.core.new(mode, size)
self.decoder = Image.core.raw_decoder(rawmode)
self.decoder.setimage(self.im, (0,0) + size)
self.data = b""
return s
def chunk_IDAT(self, offset, bytes):
"IDAT -- image data block"
# pass compressed chunks through the decoder
s = self.fp.read(bytes)
self.data = self.data + s
n, e = self.decoder.decode(self.data)
if n < 0:
# end of image
if e < 0:
raise IOError("decoder error %d" % e)
else:
self.data = self.data[n:]
return s
def chunk_DEND(self, offset, bytes):
return self.chunk_IEND(offset, bytes)
def chunk_JEND(self, offset, bytes):
return self.chunk_IEND(offset, bytes)
def chunk_UEND(self, offset, bytes):
return self.chunk_IEND(offset, bytes)
def chunk_IEND(self, offset, bytes):
"IEND -- end of image"
# we now have a new image. carry out the operation
# defined by the image header.
# won't need these anymore
del self.decoder
del self.data
self.__store()
return self.fp.read(bytes)
def __store(self):
# apply operation
cid = self.action[0]
if cid in ["BLNK", "IHDR", "JHDR", "UHDR"]:
# store
self.images[self.id] = self.im
elif cid == "DHDR":
# paste
cid, mode, bbox = self.action
im0 = self.images[self.id]
im1 = self.im
if mode == 0:
im1 = im1.chop_add_modulo(im0.crop(bbox))
im0.paste(im1, bbox)
self.count -= 1
if self.count == 0 and self.show:
self.im = self.images[self.id]
raise EOFError # end of this frame
def chunk_PLTE(self, offset, bytes):
"PLTE -- palette data"
s = self.fp.read(bytes)
if self.mode == "P":
self.palette = ImagePalette.raw("RGB", s)
return s
def chunk_sYNC(self, offset, bytes):
"SYNC -- reset decoder"
if self.count != 0:
raise SyntaxError("misplaced sYNC chunk")
s = self.fp.read(bytes)
self.__reset()
return s
# --------------------------------------------------------------------
# ARG reader
def _accept(prefix):
return prefix[:8] == MAGIC
##
# Image plugin for the experimental Animated Raster Graphics format.
class ArgImageFile(ImageFile.ImageFile):
format = "ARG"
format_description = "Animated raster graphics"
def _open(self):
if Image.warnings:
Image.warnings.warn(
"The ArgImagePlugin driver is obsolete, and will be removed "
"from a future release of PIL. If you rely on this module, "
"please contact the PIL authors.",
RuntimeWarning
)
if self.fp.read(8) != MAGIC:
raise SyntaxError("not an ARG file")
self.arg = ArgStream(self.fp)
# read and process the first chunk (AHDR)
cid, offset, bytes = self.arg.read()
if cid != "AHDR":
raise SyntaxError("expected an AHDR chunk")
s = self.arg.call(cid, offset, bytes)
self.arg.crc(cid, s)
# image characteristics
self.mode = self.arg.mode
self.size = self.arg.size
def load(self):
if self.arg.im is None:
self.seek(0)
# image data
self.im = self.arg.im
self.palette = self.arg.palette
# set things up for further processing
Image.Image.load(self)
def seek(self, frame):
if self.arg.eof:
raise EOFError("end of animation")
self.fp = self.arg.fp
while True:
#
# process chunks
cid, offset, bytes = self.arg.read()
if self.arg.eof:
raise EOFError("end of animation")
try:
s = self.arg.call(cid, offset, bytes)
except EOFError:
break
except "glurk": # AttributeError
if Image.DEBUG:
print(cid, bytes, "(unknown)")
s = self.fp.read(bytes)
self.arg.crc(cid, s)
self.fp.read(4) # ship extra CRC
def tell(self):
return 0
def verify(self):
"Verify ARG file"
# back up to first chunk
self.fp.seek(8)
self.arg.verify(self)
self.arg.close()
self.fp = None
#
# --------------------------------------------------------------------
Image.register_open("ARG", ArgImageFile, _accept)
Image.register_extension("ARG", ".arg")
Image.register_mime("ARG", "video/x-arg")

View File

@ -14,8 +14,7 @@
VERSION = '1.1.7' # PIL version VERSION = '1.1.7' # PIL version
PILLOW_VERSION = '2.4.0' # Pillow PILLOW_VERSION = '2.4.0' # Pillow
_plugins = ['ArgImagePlugin', _plugins = ['BmpImagePlugin',
'BmpImagePlugin',
'BufrStubImagePlugin', 'BufrStubImagePlugin',
'CurImagePlugin', 'CurImagePlugin',
'DcxImagePlugin', 'DcxImagePlugin',

View File

@ -18,25 +18,6 @@ import sys
Image.DEBUG = 0 Image.DEBUG = 0
# --------------------------------------------------------------------
# experimental: support ARG animation scripts
import ArgImagePlugin
def applet_hook(animation, images):
app = animation(animation_display, images)
app.run()
ArgImagePlugin.APPLET_HOOK = applet_hook
class AppletDisplay:
def __init__(self, ui):
self.__ui = ui
def paste(self, im, bbox):
self.__ui.image.paste(im, bbox)
def update(self):
self.__ui.update_idletasks()
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# an image animation player # an image animation player
@ -56,10 +37,6 @@ class UI(Label):
else: else:
self.image = ImageTk.PhotoImage(im) self.image = ImageTk.PhotoImage(im)
# APPLET SUPPORT (very crude, and not 100% safe)
global animation_display
animation_display = AppletDisplay(self)
Label.__init__(self, master, image=self.image, bg="black", bd=0) Label.__init__(self, master, image=self.image, bg="black", bd=0)
self.update() self.update()

1
depends/README.md Normal file
View File

@ -0,0 +1 @@
Scripts in this directory download, build and install the non-packaged dependencies for testing with Travis CI.

View File

@ -1,14 +1,6 @@
Plugin reference Plugin reference
================ ================
:mod:`ArgImagePlugin` Module
----------------------------
.. automodule:: PIL.ArgImagePlugin
:members:
:undoc-members:
:show-inheritance:
:mod:`BmpImagePlugin` Module :mod:`BmpImagePlugin` Module
---------------------------- ----------------------------

View File

@ -5,6 +5,7 @@ from multiprocessing import Pool, cpu_count
from distutils.ccompiler import CCompiler from distutils.ccompiler import CCompiler
import os import os
# hideous monkeypatching. but. but. but. # hideous monkeypatching. but. but. but.
def _mp_compile_one(tp): def _mp_compile_one(tp):
(self, obj, build, cc_args, extra_postargs, pp_opts) = tp (self, obj, build, cc_args, extra_postargs, pp_opts) = tp
@ -15,21 +16,20 @@ def _mp_compile_one(tp):
self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts) self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts)
return return
def _mp_compile(self, sources, output_dir=None, macros=None, def _mp_compile(self, sources, output_dir=None, macros=None,
include_dirs=None, debug=0, extra_preargs=None, include_dirs=None, debug=0, extra_preargs=None,
extra_postargs=None, depends=None): extra_postargs=None, depends=None):
"""Compile one or more source files. """Compile one or more source files.
see distutils.ccompiler.CCompiler.compile for comments. see distutils.ccompiler.CCompiler.compile for comments.
""" """
# A concrete compiler class can either override this method # A concrete compiler class can either override this method
# entirely or implement _compile(). # entirely or implement _compile().
macros, objects, extra_postargs, pp_opts, build = \
self._setup_compile(output_dir, macros, include_dirs, sources,
depends, extra_postargs)
cc_args = self._get_cc_args(pp_opts, debug, extra_preargs)
macros, objects, extra_postargs, pp_opts, build = self._setup_compile(
output_dir, macros, include_dirs, sources, depends, extra_postargs)
cc_args = self._get_cc_args(pp_opts, debug, extra_preargs)
try: try:
max_procs = int(os.environ.get('MAX_CONCURRENCY', cpu_count())) max_procs = int(os.environ.get('MAX_CONCURRENCY', cpu_count()))
@ -38,10 +38,12 @@ def _mp_compile(self, sources, output_dir=None, macros=None,
pool = Pool(max_procs) pool = Pool(max_procs)
try: try:
print ("Building using %d processes" % pool._processes) print ("Building using %d processes" % pool._processes)
except: pass except:
arr = [(self, obj, build, cc_args, extra_postargs, pp_opts) for obj in objects] pass
results = pool.map_async(_mp_compile_one,arr) arr = [
(self, obj, build, cc_args, extra_postargs, pp_opts) for obj in objects
]
pool.map_async(_mp_compile_one, arr)
pool.close() pool.close()
pool.join() pool.join()
# Return *all* object filenames, not just the ones we just built. # Return *all* object filenames, not just the ones we just built.

View File

@ -14,8 +14,6 @@ import re
import struct import struct
import sys import sys
import mp_compile
from distutils.command.build_ext import build_ext from distutils.command.build_ext import build_ext
from distutils import sysconfig from distutils import sysconfig
from setuptools import Extension, setup, find_packages from setuptools import Extension, setup, find_packages
@ -707,40 +705,41 @@ class pil_build_ext(build_ext):
finally: finally:
os.unlink(tmpfile) os.unlink(tmpfile)
if __name__=='__main__':
setup( setup(
name=NAME, name=NAME,
version=VERSION, version=VERSION,
description='Python Imaging Library (Fork)', description='Python Imaging Library (Fork)',
long_description=( long_description=(
_read('README.rst') + b'\n' + _read('README.rst') + b'\n' +
_read('CHANGES.rst')).decode('utf-8'), _read('CHANGES.rst')).decode('utf-8'),
author='Alex Clark (fork author)', author='Alex Clark (fork author)',
author_email='aclark@aclark.net', author_email='aclark@aclark.net',
url='http://python-pillow.github.io/', url='http://python-pillow.github.io/',
classifiers=[ classifiers=[
"Development Status :: 6 - Mature", "Development Status :: 6 - Mature",
"Topic :: Multimedia :: Graphics", "Topic :: Multimedia :: Graphics",
"Topic :: Multimedia :: Graphics :: Capture :: Digital Camera", "Topic :: Multimedia :: Graphics :: Capture :: Digital Camera",
"Topic :: Multimedia :: Graphics :: Capture :: Scanners", "Topic :: Multimedia :: Graphics :: Capture :: Scanners",
"Topic :: Multimedia :: Graphics :: Capture :: Screen Capture", "Topic :: Multimedia :: Graphics :: Capture :: Screen Capture",
"Topic :: Multimedia :: Graphics :: Graphics Conversion", "Topic :: Multimedia :: Graphics :: Graphics Conversion",
"Topic :: Multimedia :: Graphics :: Viewers", "Topic :: Multimedia :: Graphics :: Viewers",
"Programming Language :: Python :: 2", "Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.6",
"Programming Language :: Python :: 2.7", "Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3", "Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.2", "Programming Language :: Python :: 3.2",
"Programming Language :: Python :: 3.3", ], "Programming Language :: Python :: 3.3",
cmdclass={"build_ext": pil_build_ext}, "Programming Language :: Python :: 3.4",
ext_modules=[Extension("PIL._imaging", ["_imaging.c"])], ],
include_package_data=True, cmdclass={"build_ext": pil_build_ext},
packages=find_packages(), ext_modules=[Extension("PIL._imaging", ["_imaging.c"])],
scripts=glob.glob("Scripts/pil*.py"), include_package_data=True,
test_suite='PIL.tests', packages=find_packages(),
keywords=["Imaging", ], scripts=glob.glob("Scripts/pil*.py"),
license='Standard PIL License', test_suite='PIL.tests',
zip_safe=True, keywords=["Imaging", ],
) license='Standard PIL License',
zip_safe=True,
)
# End of file # End of file

View File

@ -4,8 +4,8 @@ import os
import sys import sys
import glob import glob
# monkey with the path, removing the local directory but adding the Tests/ directory # monkey with the path, removing the local directory but adding the Tests/
# for helper.py and the other local imports there. # directory for helper.py and the other local imports there.
del(sys.path[0]) del(sys.path[0])
sys.path.insert(0, os.path.abspath('./Tests')) sys.path.insert(0, os.path.abspath('./Tests'))
@ -16,7 +16,7 @@ sys.path.insert(0, os.path.abspath('./Tests'))
if len(sys.argv) == 1: if len(sys.argv) == 1:
sys.argv.extend(glob.glob('Tests/test*.py')) sys.argv.extend(glob.glob('Tests/test*.py'))
# Make sure that nose doesn't muck with our paths. # Make sure that nose doesn't muck with our paths.
if ('--no-path-adjustment' not in sys.argv) and ('-P' not in sys.argv): if ('--no-path-adjustment' not in sys.argv) and ('-P' not in sys.argv):
sys.argv.insert(1, '--no-path-adjustment') sys.argv.insert(1, '--no-path-adjustment')