[python-imageio] 01/02: Import python-imageio_2.1.2+ds1.orig.tar.gz
Ghislain Vaillant
ghisvail-guest at moszumanska.debian.org
Sun Jun 4 11:06:07 UTC 2017
This is an automated email from the git hooks/post-receive script.
ghisvail-guest pushed a commit to tag patched/2.1.2+ds1-1
in repository python-imageio.
commit 8af6d67a85135ceb373e80a4d668719793363f91
Author: Ghislain Antony Vaillant <ghisvail at gmail.com>
Date: Fri Feb 17 12:54:16 2017 +0000
Import python-imageio_2.1.2+ds1.orig.tar.gz
---
PKG-INFO | 2 +-
docs/releasenotes.rst | 21 +++++++++++++++++++++
imageio/__init__.py | 2 +-
imageio/core/__init__.py | 2 +-
imageio/core/format.py | 15 ++++++++++++++-
imageio/core/request.py | 38 +++++++++++++++++++++++++++++++++++++-
imageio/plugins/ffmpeg.py | 37 +++++++++++++++----------------------
imageio/plugins/pillowmulti.py | 14 +++++++++++---
tests/test_ffmpeg.py | 17 +++++++++++++++++
tests/test_pillow.py | 10 +++++++++-
10 files changed, 127 insertions(+), 31 deletions(-)
diff --git a/PKG-INFO b/PKG-INFO
index 232e30c..fc8f06e 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: imageio
-Version: 2.1.1
+Version: 2.1.2
Summary: Library for reading and writing a wide range of image, video, scientific, and volumetric data formats.
Home-page: http://imageio.github.io/
Author: imageio contributors
diff --git a/docs/releasenotes.rst b/docs/releasenotes.rst
index 98c6995..f75d480 100644
--- a/docs/releasenotes.rst
+++ b/docs/releasenotes.rst
@@ -2,6 +2,27 @@
Release notes
-------------
+
+Version 2.1.2 (02-02-2017)
+==========================
+
+A bugfix release:
+
+* Fix animated gif writer that was broken in newer Pillow version.
+* FFMPEG plugin improvements: more reliable fps detection, can deal
+ with missing FPS, more reliable subprocess termination,
+* Mimread allows a few missing frames to better deal with certain video files.
+* Allow question marks in url's.
+* Allow Pillow plugin to read remote files by "enabling" ``seek()`` and ``tell()``.
+* Use invoke to run development tasks instead of custom "make" module.
+
+
+Version 2.1.1 (24-12-2016)
+=========================
+
+Minor improvements related to Debian packaging.
+
+
Version 2.1 (22-12-2016)
========================
diff --git a/imageio/__init__.py b/imageio/__init__.py
index 252aa54..f859bbe 100644
--- a/imageio/__init__.py
+++ b/imageio/__init__.py
@@ -16,7 +16,7 @@ Main website: http://imageio.github.io
# flake8: noqa
-__version__ = '2.1.1'
+__version__ = '2.1.2'
# Load some bits from core
from .core import FormatManager, RETURN_BYTES
diff --git a/imageio/core/__init__.py b/imageio/core/__init__.py
index 3f6d449..622b9c4 100644
--- a/imageio/core/__init__.py
+++ b/imageio/core/__init__.py
@@ -15,4 +15,4 @@ from .util import get_platform, appdata_dir, resource_dirs, has_module
from .findlib import load_lib
from .fetching import get_remote_file, InternetNotAllowedError, NeedDownloadError
from .request import Request, read_n_bytes, RETURN_BYTES
-from .format import Format, FormatManager
+from .format import Format, FormatManager, CannotReadFrameError
diff --git a/imageio/core/format.py b/imageio/core/format.py
index 3e7565a..1adcdec 100644
--- a/imageio/core/format.py
+++ b/imageio/core/format.py
@@ -35,6 +35,7 @@ from __future__ import absolute_import, print_function, division
from __future__ import with_statement
import os
+from warnings import warn
import numpy as np
@@ -42,6 +43,14 @@ from . import Image, asarray
from . import string_types, text_type, binary_type # noqa
+class CannotReadFrameError(RuntimeError):
+ """ Exception to be used by plugins to indicate that a frame could not
+ be read, even though it should be a valid index. The length could be
+ inf, or e.g. video sometimes reports a wrong length.
+ """
+ pass
+
+
class Format(object):
""" Represents an implementation to read/write a particular file format
@@ -375,9 +384,13 @@ class Format(object):
while i < n:
try:
im, meta = self._get_data(i)
- except IndexError:
+ except (IndexError, CannotReadFrameError):
if n == float('inf'):
return
+ elif n - i == 1:
+ uri = self.request.filename
+ warn('Could not read last frame of %s.' % uri)
+ return
raise
yield Image(im, meta)
i += 1
diff --git a/imageio/core/request.py b/imageio/core/request.py
index d9d0147..bc07b25 100644
--- a/imageio/core/request.py
+++ b/imageio/core/request.py
@@ -326,6 +326,7 @@ class Request(object):
elif self._uri_type in [URI_HTTP or URI_FTP]:
assert not want_to_write # This should have been tested in init
self._file = urlopen(self.filename, timeout=5)
+ fix_HTTPResponse(self._file)
return self._file
@@ -340,7 +341,10 @@ class Request(object):
return self._filename
else:
# Get filename
- ext = os.path.splitext(self._filename)[1]
+ if self._uri_type in (URI_HTTP, URI_FTP):
+ ext = os.path.splitext(self._filename.split('?')[0])[1]
+ else:
+ ext = os.path.splitext(self._filename)[1]
self._filename_local = tempfile.mktemp(ext, 'imageio_')
# Write stuff to it?
if self.mode[0] == 'r':
@@ -455,3 +459,35 @@ def read_n_bytes(f, N):
break
bb += extra_bytes
return bb
+
+
+def fix_HTTPResponse(f):
+ """This fixes up an HTTPResponse object so that it can tell(), and also
+ seek() will work if its effectively a no-op. This allows tools like Pillow
+ to use the file object.
+ """
+ count = [0]
+
+ def read(n=None):
+ res = ori_read(n)
+ count[0] += len(res)
+ return res
+
+ def tell():
+ return count[0]
+
+ def seek(i, mode=0):
+ if not (mode == 0 and i == count[0]):
+ ori_seek(i, mode)
+
+ def fail_seek(i, mode=0):
+ raise RuntimeError('No seeking allowed!')
+
+ # Note, there is currently no protection from wrapping an object more than
+ # once, it will (probably) work though, because closures.
+ ori_read = f.read
+ ori_seek = f.seek if hasattr(f, 'seek') else fail_seek
+
+ f.read = read
+ f.tell = tell
+ f.seek = seek
diff --git a/imageio/plugins/ffmpeg.py b/imageio/plugins/ffmpeg.py
index 5e7f5b9..5199b79 100644
--- a/imageio/plugins/ffmpeg.py
+++ b/imageio/plugins/ffmpeg.py
@@ -25,7 +25,7 @@ import numpy as np
from .. import formats
from ..core import (Format, get_remote_file, string_types, read_n_bytes,
- image_as_uint, get_platform,
+ image_as_uint, get_platform, CannotReadFrameError,
InternetNotAllowedError, NeedDownloadError)
FNAME_PER_PLATFORM = {
@@ -309,7 +309,7 @@ class FfmpegFormat(Format):
framesize)
def _close(self):
- self._terminate(0.05) # Short timeout
+ self._terminate() # Short timeout
self._proc = None
def _get_length(self):
@@ -404,7 +404,7 @@ class FfmpegFormat(Format):
# Create thread that keeps reading from stderr
self._stderr_catcher = StreamCatcher(self._proc.stderr)
- def _terminate(self, timeout=1.0):
+ def _terminate(self):
""" Terminate the sub process.
"""
# Check
@@ -413,26 +413,16 @@ class FfmpegFormat(Format):
if self._proc.poll() is not None:
return # process already dead
# Terminate process
- self._proc.terminate()
+ # Using kill since self._proc.terminate() does not seem
+ # to work for ffmpeg, leaves processes hanging
+ self._proc.kill()
+
# Tell threads to stop when they have a chance. They are probably
# blocked on reading from their file, but let's play it safe.
if self._stderr_catcher:
self._stderr_catcher.stop_me()
if self._frame_catcher:
self._frame_catcher.stop_me()
- # Close stdin as another way to tell ffmpeg that we're done. Don't
- # close other streams, because it causes issue #174
- try:
- self._proc.stdin.close()
- except Exception: # pragma: no cover
- pass
- # Wait for it to close (but do not get stuck)
- etime = time.time() + timeout
- while time.time() < etime:
- time.sleep(0.01)
- if self._proc.poll() is not None:
- return
- # self._proc.kill() # probably not needed ...
def _load_infos(self):
""" reads the FFMPEG info on the file and sets size fps
@@ -481,10 +471,12 @@ class FfmpegFormat(Format):
# get the output line that speaks about video
videolines = [l for l in lines if ' Video: ' in l]
line = videolines[0]
-
+
# get the frame rate
- match = re.search("( [0-9]*.| )[0-9]* (tbr|fps)", line)
- fps = float(line[match.start():match.end()].split(' ')[1])
+ matches = re.findall(" ([0-9]+\.?[0-9]*) (tbr|fps)", line)
+ fps = 0
+ if matches: # Can be empty, see #171, assume nframes = inf
+ fps = float(matches[0][0].strip())
self._meta['fps'] = fps
# get the size of the original stream, of the form 460x320 (w x h)
@@ -512,7 +504,8 @@ class FfmpegFormat(Format):
if match is not None:
hms = map(float, line[match.start()+1:match.end()].split(':'))
self._meta['duration'] = duration = cvsecs(*hms)
- self._meta['nframes'] = int(round(duration*fps))
+ if fps:
+ self._meta['nframes'] = int(round(duration*fps))
def _read_frame_data(self):
# Init and check
@@ -533,7 +526,7 @@ class FfmpegFormat(Format):
err1 = str(err)
err2 = self._stderr_catcher.get_text(0.4)
fmt = 'Could not read frame:\n%s\n=== stderr ===\n%s'
- raise RuntimeError(fmt % (err1, err2))
+ raise CannotReadFrameError(fmt % (err1, err2))
return s
def _skip_frames(self, n=1):
diff --git a/imageio/plugins/pillowmulti.py b/imageio/plugins/pillowmulti.py
index ecf98dc..abb5120 100644
--- a/imageio/plugins/pillowmulti.py
+++ b/imageio/plugins/pillowmulti.py
@@ -156,6 +156,7 @@ class GifWriter:
self.write_header(im_pil, palette, self.opt_loop)
self._global_palette = palette
self.write_image(im_pil, palette, rect, duration, dispose)
+ # assert len(palette) == len(self._global_palette)
# Bookkeeping
self._previous_image = im
@@ -177,12 +178,19 @@ class GifWriter:
fp = self.fp
- # Gather info
+ # Gather local image header and data, using PIL's getdata. That
+ # function returns a list of bytes objects, but which parts are
+ # what has changed multiple times, so we put together the first
+ # parts until we have enough to form the image header.
data = self.getdata(im)
- imdes, data = b''.join(data[:-2]), data[-2:]
- graphext = self.getGraphicsControlExt(duration, dispose)
+ imdes = b''
+ while data and len(imdes) < 11:
+ imdes += data.pop(0)
+ assert len(imdes) == 11
+
# Make image descriptor suitable for using 256 local color palette
lid = self.getImageDescriptor(im, rect)
+ graphext = self.getGraphicsControlExt(duration, dispose)
# Write local header
if (palette != self._global_palette) or (dispose != 2):
diff --git a/tests/test_ffmpeg.py b/tests/test_ffmpeg.py
index ca61530..aef0b00 100644
--- a/tests/test_ffmpeg.py
+++ b/tests/test_ffmpeg.py
@@ -375,6 +375,23 @@ def show_in_visvis():
vv.processEvents()
+def test_reverse_read(tmpdir):
+ need_internet()
+ # Ensure we can read a file in reverse without error.
+
+ tmpf = tmpdir.join('test_vid.mp4')
+ W = imageio.get_writer(str(tmpf))
+ for i in range(300):
+ W.append_data(np.zeros((64, 64, 3), np.uint8))
+ W.close()
+
+ W = imageio.get_reader(str(tmpf))
+ for i in range(len(W)-1, 0, -1):
+ print("reading", i)
+ W.get_data(i)
+ W.close()
+
+
if __name__ == '__main__':
run_tests_if_main()
#reader = imageio.read('cockatoo.mp4', 'ffmpeg')
diff --git a/tests/test_pillow.py b/tests/test_pillow.py
index d2e4668..5bb5931 100644
--- a/tests/test_pillow.py
+++ b/tests/test_pillow.py
@@ -147,7 +147,15 @@ def test_png():
assert s2 < s1
im2 = imageio.imread(fnamebase + '1.png')
assert im2.dtype == np.uint16
-
+
+
+def test_png_remote():
+ # issue #202
+ need_internet()
+ im = imageio.imread('https://raw.githubusercontent.com/imageio/' +
+ 'imageio-binaries/master/images/astronaut.png')
+ assert im.shape == (512, 512, 3)
+
def test_jpg():
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/python-imageio.git
More information about the debian-science-commits
mailing list