-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Deprecate fromarray mode argument #9018
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
Conversation
|
How should |
from PIL import Image
import numpy
a = numpy.ones((256, 256), dtype=numpy.uint8)
# Before
p = Image.fromarray(a, "P") # This has an empty palette
print(p, p.palette.mode, len(p.palette.colors))
# After
l = Image.fromarray(a)
p = l.convert("P") # This has a full palette
p.putpalette([]) # If you would like to keep an empty palette, this will do so
print(p, p.palette.mode, len(p.palette.colors)) |
|
I have some uint8 YCbCr data that I access via |
|
Could you put together a simple example to demonstrate what you're doing? from PIL import Image
import numpy
a = numpy.ones((1, 1), dtype=numpy.uint8)
Image.fromarray(a, "YCbCr")gives |
|
I have a numpy array of shape (h, w, 3) which contains YCbCr data. For instance, a single blue pixel might be a = np.array([[[30, 255, 107]]], dtype=np.uint8)I want to convert this to RGB: ycbcrimg = PIL.Image.fromarray(a, 'YCbCr')
ycbcrimg.convert('RGB').getpixel((0, 0))yields It looks like I can do ycbcrimg = PIL.Image.frombuffer('YCbCr', (a.shape[1], a.shape[0]), a.tobytes(), 'raw', 'YCbCr', 0, 1)but that seems cumbersome compared to the now deprecated |
|
What do you think of this? from PIL import Image
import numpy as np
a = np.array([[[30, 255, 107]]], dtype=np.uint8)
img = Image.new("YCbCr", (1, 1))
img.putdata([tuple(b[0]) for b in a])
print(img.convert('RGB').getpixel((0, 0))) |
|
I assume that would be inefficient for large images, since we are constructing a tuple for every pixel. I used a 1x1 pixel image as the smallest working example; my actual images are larger and can be numerous. |
|
Ok. If the tuple construction is the only problem, I could put together a PR to allow lists to be used, meaning that from PIL import Image
import numpy as np
a = np.array([[[30, 255, 107]]], dtype=np.uint8)
img = Image.new("YCbCr", (1, 1))
img.putdata(a.tolist()[0])
print(img.convert('RGB').getpixel((0, 0)))would work. How does that sound? |
|
We really go out of our way to tell people not to do bulk pixel manipulation in python, so deprecating something that does the right thing in 0 time in C and then suggesting that level of pixel pushing in Python seems wrong. When this was proposed, there was the one legitimate use case mentioned (P), this is definitely another. Specifying that the uint8 pixels represent YCbCr instead of RGB is the sort of cast that is safe and useful for importing -- it's essentially the same operation as specifying a colorspace -- rather than specifying a bit layout which is what trips people up. I can see two options here:
|
|
Ok, I've created #9063 for the first option. Pinging @guillaume-rochette-oxb just to make sure he is aware of this potential step in the other direction. |
|
Thank you. |
|
Also ran into this deprecation with pypdfium2. |
|
Ok, I've added RGBX to the list of RGBA alternatives in the PR. |
Resolves #9006
#2856 (with 12 likes), #3781, #4887, #5227, #5465 and #5723 are all issues where the
Image.fromarray()modeparameter has caused confusion.#5465 (comment)
Since those, #5849 improved the documentation, but it's not done causing problems, as #9006 objects to the fact that one type of array can't be correctly read using an explicit mode argument, but
mode=Nonecan handle it without a problem.This PR suggests just deprecating the argument altogether.
There is a small loss of functionality in that P mode images can no longer be directly created using
fromarray(). Currently, this can be done withImage.fromarray(a, "P"), but because array data does not contain palette information, this would no longer be possible.