New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
imageio.v3.imread returns read-only array #877
Comments
Hard to say what is happening without more context; do you have an example image or snippet that produces this behavior? Just to utter a guess: If you are reading a PNG using the pillow backend with a somewhat recent version of pillow then you may get a read-only view into pillow's image buffer instead of getting a full copy of the image data. This type of conversion (sharing the data buffer between numpy and pillow) is much faster than doing an extra copy of the buffer. Numpy is mindful of such read-only views and will create a copy as needed unless you explicitly call for in-place operations which will fail on read-only data. Is this what is happening for you? |
Thanks for your response. The image itself is nothing special I think (an 8bit PNG, 1 grayscale channel actually saved by This seems really weird, I don't think this can be called expected behavior even if it were marginally faster. I must say I've never encountered a case where imread-like function in any library (opencv, matlab,...) produced read-only data in memory. Is there a workaround you could suggest? |
Further info, of the available plugins for PNG images the plugin "pillow" produces read-only image as described above (I'd consider that a bug) while plugins "PNG-PIL" or "opencv" work as expected (return writeable np.ndarray). Unfortunately the behavior of different plugins is otherwise not exactly equivalent so this workaround is not ideal. |
Interesting. This is a new behavior introduced by Pillow 9.2. I can do the following on >>> import imageio.v3 as iio
>>> import numpy as np
>>> rng = np.random.default_rng()
>>> img = rng.integers(0, 255, (128, 128), dtype=np.uint8)
>>> buffer = iio.imwrite("<bytes>", img, extension=".png")
>>> frame = iio.imread(buffer)
>>> frame.flags
C_CONTIGUOUS : True
F_CONTIGUOUS : False
OWNDATA : True
WRITEABLE : True
ALIGNED : True
WRITEBACKIFCOPY : False
UPDATEIFCOPY : False but if I upgrade to pillow to 9.2.0 I get the behavior you describe: >>> import imageio.v3 as iio
>>> import numpy as np
>>> rng = np.random.default_rng()
>>> img = rng.integers(0, 255, (128, 128), dtype=np.uint8)
>>> buffer = iio.imwrite("<bytes>", img, extension=".png")
>>> frame = iio.imread(buffer)
>>> frame.flags
C_CONTIGUOUS : True
F_CONTIGUOUS : False
OWNDATA : False
WRITEABLE : False
ALIGNED : True
WRITEBACKIFCOPY : False
UPDATEIFCOPY : False The same will not happen with
One solution here is to call
I'm not sure if this behavior is intentional or if it is a bug in pillow actually. I like it, but I see that it can be confusing in some cases. We can always check with the pillow devs if this was intentional and what their reasoning is.
In the v2 API We removed Instead, try the following: iio.imwrite("some/path.png", img, extension=".jpg")
iio.imwrite("some/path.png", img, extension=".jpeg") Thinking about it, I've commented about |
@hookxs FYI, I've asked about this behavior change in the pillow repo. If you want to follow the discussion, it lives here: python-pillow/Pillow#6581 |
Hey, thanks for all the investigation into the issue and link to the pillow point of view. As a user I can say that I consider this situation rather unfortunate. Because as of now, reading a .jpg image produces a normal writeable array (as was always the norm) (edit: it actually doesn't) while reading a .png is read-only because I guess a different plugin is used in the background. And having a read-only array can break downstream tasks (as it did for me). For the end user (of imageio) this is far from ideal because I think that most people use imageio as a sort of interface that deals with peculiarities of particular plugins but presents a unified front when possible. Now simply because somebody sent me a .png instead of a .jpg my code breaks even though both are fairly standard formats and I am using imageio library which supposedly can handle both. As a result I need to include some hack like Regarding the Edit: Actually, my bad, reading a .jpg also produces a read-only array, it just didn't matter in my case so I was under the impression that a different plugin is being used for .jpg. So at least this is consistent. |
That's easy. |
Hi
Under certain circumstances (in particular, happened during reading a normal png image from a local disk, I can investigate more if necessary) the function
imageio.v3.imread
returns a read-only image (ie anp.ndarray
withflags.writeable==False
). Is this expected behavior or a bug? This never happened to me beforev3
and there is nothing in the docs indicating that this might happen. I don't think most users would expect or appreciate anything like that and it can break downstream tasks, as it did in my case.The text was updated successfully, but these errors were encountered: