FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Error reading png image from URL with imread in matplotlib 3.3 · Issue #18129 · matplotlib/matplotlib · GitHub

Repository navigation

Error reading png image from URL with imread in matplotlib 3.3 #18129

Closed

Description

Bug report

Bug summary

After upgrading to matplotlib 3.3, imread errors when reading in a png from a URL. This was working in 3.2.

from matplotlib import image
url = 'https://github.com/hjnilsson/country-flags/raw/master/png250px/us.png'
image.imread(url)

Results in UnsupportedOperation: seek

Traceback indicates error is from pillow. Related Issue

Full Traceback

UnsupportedOperation                      Traceback (most recent call last)
<ipython-input-28-3cc23b6666a9> in <module>
----> 1 image.imread(url)

~/miniconda3/envs/mpl/lib/python3.8/site-packages/matplotlib/image.py in imread(fname, format)
   1473             from urllib import request
   1474             with urllib.request.urlopen(fname) as response:
-> 1475                 return imread(response, format=ext)
   1476     with img_open(fname) as image:
   1477         return (_pil_png_to_float_array(image)

~/miniconda3/envs/mpl/lib/python3.8/site-packages/matplotlib/image.py in imread(fname, format)
   1474             with urllib.request.urlopen(fname) as response:
   1475                 return imread(response, format=ext)
-> 1476     with img_open(fname) as image:
   1477         return (_pil_png_to_float_array(image)
   1478                 if isinstance(image, PIL.PngImagePlugin.PngImageFile) else

~/miniconda3/envs/mpl/lib/python3.8/site-packages/PIL/ImageFile.py in __init__(self, fp, filename)
    115         try:
    116             try:
--> 117                 self._open()
    118             except (
    119                 IndexError,  # end of data

~/miniconda3/envs/mpl/lib/python3.8/site-packages/PIL/PngImagePlugin.py in _open(self)
    651             # get next chunk
    652 
--> 653             cid, pos, length = self.png.read()
    654 
    655             try:

~/miniconda3/envs/mpl/lib/python3.8/site-packages/PIL/PngImagePlugin.py in read(self)
    126             s = self.fp.read(8)
    127             cid = s[4:]
--> 128             pos = self.fp.tell()
    129             length = i32(s)
    130 

UnsupportedOperation: seek

Matplotlib version

  • Operating system: macOS
  • Matplotlib version: 3.3
  • Matplotlib backend (print(matplotlib.get_backend())): MacOSX
  • Python version: 3.8

Activity

  1. jklymak commented on Jul 30, 2020

    Member

    We switched to pillow handling the image i/o and it seems pillow can't handle urls? #15193

  2. tdpetrou commented on Jul 30, 2020

    ContributorAuthor

    Would a simple approach using the standard library's urllib.request module to read the contents as bytes not work?

  3. added this to the v3.3.1 milestone on Jul 30, 2020
  4. tdpetrou commented on Jul 30, 2020

    ContributorAuthor

    Just looked at the source. urllib.request is used and passes the response to PIL.PngImagePlugin.PngImageFile, but if it passes it to PIL.Image.open, it would work.

    Edit:

    The response object is not seekable which causes the error. You can wrap it in BytesIO to make it work.

    # fails
    response = urllib.request.urlopen(url)
    PngImagePlugin.PngImageFile(response)
    # works
    response = urllib.request.urlopen(url)
    PngImagePlugin.PngImageFile(BytesIO(response.read()))

    This is essentially the error within urllib

    with urllib.request.urlopen(url) as response:
        response.tell() # UnsupportedOperation: seek
  5. tdpetrou commented on Jul 30, 2020

    ContributorAuthor

    PIL.Image.open supports urllib.request.urlopen objects (python-pillow/Pillow#1151) so I don't see why we can't just always pass it there instead of PngImagePlugin.PngImageFile

  6. jklymak commented on Jul 30, 2020

    Member

    This was discussed - #15193 (comment) Not clear to me what @anntzer was trying to do with that, so perhaps he can explain.

  7. anntzer commented on Jul 30, 2020

    Contributor

    The point was to force reading the file as a png (if ext == "png") rather than relying on pillow's autodetection. This only matters if someone is nasty enough to have e.g. a jpeg file in a png extension, or pass a jpeg file to imread(..., ext="png").
    My guess is that wrapping in a BytesIO() is fine, you already made a web request anyways and we're about to convert the whole thing to float32, so I wouldn't worry too much about speed or memory usage.

  8. added
    🌱 Good first issueOpen a pull request against these issues if there are no active ones!
    Difficulty: Easyhttps://matplotlib.org/devdocs/devel/contribute.html#good-first-issues
    on Aug 1, 2020
  9. tacaswell commented on Aug 1, 2020

    Member

    Labeling this as a good first issue because there is a very clear regression and 2 suggested fixes in this thread. This should get a test (so we don't accidentally break it again). I think we have a test of getting a stylesheet from a URL, the new test should get the same markup so it can be skipped in no-network environments (ex debian builds) .

  10. andrewkoo commented on Aug 1, 2020

    Hi! I am new to open source and am interested in helping out if I can. If this is still open, can I start working on this?

    edit: Looking at tests/test_image.py it looks like there is a test_load_from_url() already defined:

    def test_load_from_url():
        path = Path(__file__).parent / "baseline_images/pngsuite/basn3p04.png"
        url = ('file:'
               + ('///' if sys.platform == 'win32' else '')
               + path.resolve().as_posix())
        plt.imread(url)
        plt.imread(urllib.request.urlopen(url))
    

    Does this test case not catch this issue?

  11. tacaswell commented on Aug 3, 2020

    Member

    @andrewkoo Interesting, it is probably worth investigating why that test did not catch this issue!

  12. timhoffm commented on Aug 3, 2020

    Member

    Without checking, I'd guess file:/// vs. https:///.

  13. dopplershift commented on Aug 3, 2020

    Contributor

    With checking: open() doesn't seem to recognize file:///, but it's possible I did something wrong.

  14. linchiwei123 commented on Aug 3, 2020

    Contributor

    need to test http(s) as well.

    >>> file_r = urllib.request.urlopen(file_url)
    >>> file_r.tell()
    0
    >>> https_r = urllib.request.urlopen(https_url)
    >>> https_r.tell()
    Traceback (most recent call last):
      File "<pyshell#20>", line 1, in <module>
        https_r.tell()
    io.UnsupportedOperation: seek
  15. 1 remaining item

  16. linchiwei123 commented on Aug 4, 2020

    Contributor

    https://docs.python.org/3.8/library/urllib.request.html#urllib.request.urlopen
    For HTTP and HTTPS URLs, this function returns a http.client.HTTPResponse object slightly modified. In addition to the three new methods above, the msg attribute contains the same information as the reason attribute — the reason phrase returned by server — instead of the response headers as it is specified in the documentation for HTTPResponse.

    For FTP, file, and data URLs and requests explicitly handled by legacy URLopener and FancyURLopener classes, this function returns a urllib.response.addinfourl object.

  17. timhoffm commented on Aug 4, 2020

    Member

    Do we expect that type instability from urlopen? If not, does this need to be reported as a bug to cpython?

    HTTPResponse is documented to implement BufferedIOBase, which does not include seek(). IMHO that's all we can expect. That file:// returns another object with more functionality can be misleading but is not strictly a bug and I don't think cpython could/would change this.

    Like Pillow ((python-pillow/Pillow#1151) we cannot assume that seek() exists. The fix is to either pass the response straight through (which we apparently do not want to do - did not follow the details), or apply the same fix with wrapping if neccesary as Pillow does.

  18. added a commit that references this issue on Aug 5, 2020
    66ff15a
  19. tacaswell commented on Aug 5, 2020

    Member

    @linchiwei123 @andrewkoo I went ahead and opened the PR to take care of this. Sorry to steal the work out from under you but as this was the last issue for 3.3.1 we wanted to expedite the process.

  20. removed
    🌱 Good first issueOpen a pull request against these issues if there are no active ones!
    on Aug 5, 2020
  21. andrewkoo commented on Aug 5, 2020

    All good! This is all just a learning process for me so would hate to delay anything..

  22. linchiwei123 commented on Aug 5, 2020

    Contributor

    It's OK.

  23. added 2 commits that reference this issue on Aug 6, 2020
    980c649
    5d5d919
  24. anntzer commented on Oct 16, 2020

    Contributor

    Note that with Pillow 8.0 the dance at #18129 (comment) would not be necessary anymore per https://pillow.readthedocs.io/en/stable/releasenotes/8.0.0.html#image-open-add-formats-parameter.

  25. gaurav6386 commented on Oct 25, 2021

    What is the fix guys?

  26. jklymak commented on Oct 25, 2021

    Member

    Upgrade to 3.3.1? Or are you saying that newer matplotlib don't work?

  27. gaurav6386 commented on Oct 25, 2021

    It's the latest version. And I don't think update was the fix earlier. I searched it everywhere and it still does not have proper solution. If you can help me or refer some fixes it will be of great help.
    The issue is as shown below

    map_file = urllib.request.urlopen(MAP_URL)
    
    print("DATA>>>>", map_file)
    map_img = plt.imread(map_file)

    But it exits after throwing

      ..
      ..
      File "C:\Python310\lib\site-packages\PIL\PngImagePlugin.py", line 691, in _open
        cid, pos, length = self.png.read()
      File "C:\Python310\lib\site-packages\PIL\PngImagePlugin.py", line 161, in read
        pos = self.fp.tell() 
    io.UnsupportedOperation: seek
  28. jklymak commented on Oct 25, 2021

    Member

    Please open a new issue with a self-contained example (ie real url). Howver note that the original issue above you pass the url as a string not whatever urlopen returns.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Difficulty: Easyhttps://matplotlib.org/devdocs/devel/contribute.html#good-first-issues

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions


      Back | FazBrowse Home | New Git URL