From c261674980956361d3b98b6239687e29d45b8405 Mon Sep 17 00:00:00 2001 From: hugovk Date: Fri, 27 Jun 2014 15:58:12 +0300 Subject: [PATCH 1/7] Remove obsolete Animated Raster Graphics support --- PIL/ArgImagePlugin.py | 506 ------------------------------------------ PIL/__init__.py | 3 +- Scripts/player.py | 23 -- docs/plugins.rst | 8 - 4 files changed, 1 insertion(+), 539 deletions(-) delete mode 100644 PIL/ArgImagePlugin.py diff --git a/PIL/ArgImagePlugin.py b/PIL/ArgImagePlugin.py deleted file mode 100644 index 7fc167c60..000000000 --- a/PIL/ArgImagePlugin.py +++ /dev/null @@ -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") diff --git a/PIL/__init__.py b/PIL/__init__.py index c35f6207e..14daee5ca 100644 --- a/PIL/__init__.py +++ b/PIL/__init__.py @@ -14,8 +14,7 @@ VERSION = '1.1.7' # PIL version PILLOW_VERSION = '2.4.0' # Pillow -_plugins = ['ArgImagePlugin', - 'BmpImagePlugin', +_plugins = ['BmpImagePlugin', 'BufrStubImagePlugin', 'CurImagePlugin', 'DcxImagePlugin', diff --git a/Scripts/player.py b/Scripts/player.py index 84b636668..0c90286c5 100644 --- a/Scripts/player.py +++ b/Scripts/player.py @@ -18,25 +18,6 @@ import sys 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 @@ -56,10 +37,6 @@ class UI(Label): else: 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) self.update() diff --git a/docs/plugins.rst b/docs/plugins.rst index 001cee949..a069f80df 100644 --- a/docs/plugins.rst +++ b/docs/plugins.rst @@ -1,14 +1,6 @@ Plugin reference ================ -:mod:`ArgImagePlugin` Module ----------------------------- - -.. automodule:: PIL.ArgImagePlugin - :members: - :undoc-members: - :show-inheritance: - :mod:`BmpImagePlugin` Module ---------------------------- From c23f9002507e1a9c9afef1a760df0d866023e324 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Fri, 27 Jun 2014 08:57:49 -0700 Subject: [PATCH 2/7] reverted __main__ guard --- setup.py | 70 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/setup.py b/setup.py index e0a22f75f..10ef0db08 100644 --- a/setup.py +++ b/setup.py @@ -705,39 +705,39 @@ class pil_build_ext(build_ext): finally: os.unlink(tmpfile) -if __name__ == '__main__': - setup( - name=NAME, - version=VERSION, - description='Python Imaging Library (Fork)', - long_description=( - _read('README.rst') + b'\n' + - _read('CHANGES.rst')).decode('utf-8'), - author='Alex Clark (fork author)', - author_email='aclark@aclark.net', - url='http://python-pillow.github.io/', - classifiers=[ - "Development Status :: 6 - Mature", - "Topic :: Multimedia :: Graphics", - "Topic :: Multimedia :: Graphics :: Capture :: Digital Camera", - "Topic :: Multimedia :: Graphics :: Capture :: Scanners", - "Topic :: Multimedia :: Graphics :: Capture :: Screen Capture", - "Topic :: Multimedia :: Graphics :: Graphics Conversion", - "Topic :: Multimedia :: Graphics :: Viewers", - "Programming Language :: Python :: 2", - "Programming Language :: Python :: 2.6", - "Programming Language :: Python :: 2.7", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.2", - "Programming Language :: Python :: 3.3", ], - cmdclass={"build_ext": pil_build_ext}, - ext_modules=[Extension("PIL._imaging", ["_imaging.c"])], - include_package_data=True, - packages=find_packages(), - scripts=glob.glob("Scripts/pil*.py"), - test_suite='PIL.tests', - keywords=["Imaging", ], - license='Standard PIL License', - zip_safe=True, - ) + +setup( + name=NAME, + version=VERSION, + description='Python Imaging Library (Fork)', + long_description=( + _read('README.rst') + b'\n' + + _read('CHANGES.rst')).decode('utf-8'), + author='Alex Clark (fork author)', + author_email='aclark@aclark.net', + url='http://python-pillow.github.io/', + classifiers=[ + "Development Status :: 6 - Mature", + "Topic :: Multimedia :: Graphics", + "Topic :: Multimedia :: Graphics :: Capture :: Digital Camera", + "Topic :: Multimedia :: Graphics :: Capture :: Scanners", + "Topic :: Multimedia :: Graphics :: Capture :: Screen Capture", + "Topic :: Multimedia :: Graphics :: Graphics Conversion", + "Topic :: Multimedia :: Graphics :: Viewers", + "Programming Language :: Python :: 2", + "Programming Language :: Python :: 2.6", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.2", + "Programming Language :: Python :: 3.3", ], + cmdclass={"build_ext": pil_build_ext}, + ext_modules=[Extension("PIL._imaging", ["_imaging.c"])], + include_package_data=True, + packages=find_packages(), + scripts=glob.glob("Scripts/pil*.py"), + test_suite='PIL.tests', + keywords=["Imaging", ], + license='Standard PIL License', + zip_safe=True, +) # End of file From 9305e8499bff96814ee07a1d43b77a35f70befe9 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Fri, 27 Jun 2014 08:58:27 -0700 Subject: [PATCH 3/7] Added python 3.4 --- setup.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 10ef0db08..b89a08f41 100644 --- a/setup.py +++ b/setup.py @@ -729,7 +729,9 @@ setup( "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.2", - "Programming Language :: Python :: 3.3", ], + "Programming Language :: Python :: 3.3", + "Programming Language :: Python :: 3.4", + ], cmdclass={"build_ext": pil_build_ext}, ext_modules=[Extension("PIL._imaging", ["_imaging.c"])], include_package_data=True, From e7aee1444c0c2fb48e419e990315298eae86c403 Mon Sep 17 00:00:00 2001 From: Alex Clark Date: Fri, 27 Jun 2014 16:26:42 -0400 Subject: [PATCH 4/7] Update --- CHANGES.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index 3f4299f5e..c2ac9f136 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,9 @@ Changelog (Pillow) 2.5.0 (unreleased) ------------------ +- Remove obsolete Animated Raster Graphics (ARG) support + [hugovk] + - Fix test_imagedraw failures #727 [cgohlke] From 5e3bf95c84507a053e771fec86796fdae400a7f1 Mon Sep 17 00:00:00 2001 From: Alex Clark Date: Fri, 27 Jun 2014 17:43:24 -0400 Subject: [PATCH 5/7] Fix manifest --- MANIFEST.in | 1 + 1 file changed, 1 insertion(+) diff --git a/MANIFEST.in b/MANIFEST.in index 79a70dddd..08bd0b4e3 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -54,6 +54,7 @@ recursive-include Tests *.png recursive-include Tests *.ppm recursive-include Tests *.psd recursive-include Tests *.py +recursive-include Tests *.rst recursive-include Tests *.spider recursive-include Tests *.tar recursive-include Tests *.tif From b6d3983c59bdd5f0286823e7afd7a3009ab2bb8a Mon Sep 17 00:00:00 2001 From: wiredfool Date: Fri, 27 Jun 2014 16:02:42 -0700 Subject: [PATCH 6/7] Created README --- depends/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 depends/README.md diff --git a/depends/README.md b/depends/README.md new file mode 100644 index 000000000..a94773bb1 --- /dev/null +++ b/depends/README.md @@ -0,0 +1 @@ +Scripts in this directory download, build and install the non-packaged dependencies for testing with Travis CI. From 2f09622516c92ba564ad3453d69b44b1277e2481 Mon Sep 17 00:00:00 2001 From: Alex Clark Date: Fri, 27 Jun 2014 19:13:00 -0400 Subject: [PATCH 7/7] Top level flake8 fixes --- mp_compile.py | 22 ++++++++++++---------- setup.py | 5 +---- test-installed.py | 6 +++--- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/mp_compile.py b/mp_compile.py index 0ff5b4b62..71b4089e1 100644 --- a/mp_compile.py +++ b/mp_compile.py @@ -5,6 +5,7 @@ from multiprocessing import Pool, cpu_count from distutils.ccompiler import CCompiler import os + # hideous monkeypatching. but. but. but. def _mp_compile_one(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) return + def _mp_compile(self, sources, output_dir=None, macros=None, include_dirs=None, debug=0, extra_preargs=None, extra_postargs=None, depends=None): """Compile one or more source files. - + see distutils.ccompiler.CCompiler.compile for comments. """ # A concrete compiler class can either override this method # 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: 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) try: print ("Building using %d processes" % pool._processes) - except: pass - arr = [(self, obj, build, cc_args, extra_postargs, pp_opts) for obj in objects] - results = pool.map_async(_mp_compile_one,arr) - + except: + pass + arr = [ + (self, obj, build, cc_args, extra_postargs, pp_opts) for obj in objects + ] + pool.map_async(_mp_compile_one, arr) pool.close() pool.join() # Return *all* object filenames, not just the ones we just built. diff --git a/setup.py b/setup.py index 1a31a8981..e0a22f75f 100644 --- a/setup.py +++ b/setup.py @@ -14,8 +14,6 @@ import re import struct import sys -import mp_compile - from distutils.command.build_ext import build_ext from distutils import sysconfig from setuptools import Extension, setup, find_packages @@ -707,7 +705,7 @@ class pil_build_ext(build_ext): finally: os.unlink(tmpfile) -if __name__=='__main__': +if __name__ == '__main__': setup( name=NAME, version=VERSION, @@ -742,5 +740,4 @@ if __name__=='__main__': license='Standard PIL License', zip_safe=True, ) - # End of file diff --git a/test-installed.py b/test-installed.py index 7f58f4966..0248590a5 100755 --- a/test-installed.py +++ b/test-installed.py @@ -4,8 +4,8 @@ import os import sys import glob -# monkey with the path, removing the local directory but adding the Tests/ directory -# for helper.py and the other local imports there. +# monkey with the path, removing the local directory but adding the Tests/ +# directory for helper.py and the other local imports there. del(sys.path[0]) 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: 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): sys.argv.insert(1, '--no-path-adjustment')