-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
Pillow destroys image by incorrectly binarizing grayscale image during show() #6765
Comments
It's not actually during from PIL import Image
Image.open("0026.png").save("out.png") It is during Lines 82 to 84 in 0ec32a3
|
I've created PR #6766 to resolve this. |
I don't believe that the provided PR is sufficient to fix the problem. I think the problem goes much further and is a systematic bug in the way how a PNG image that is encoded with path = Path("0026.png")
image = Image.open(path)
image = image.convert("RGB")
image.save("0026_corrupt.png")
image.show() creates the exact same corrupted image. In the case of saving the image after conversion, the patched ImageShow() class is not even involved. |
Regarding converting an I;16B rawmode PNG to RGB, that has been previously reported as #5642. I'm guessing you're not interested in a workaround. #3159 is the general issue for this. There is actually not a consensus that it should be fixed. |
I'm very much interested in a workaround, but right now I don't know how I could process the given image with PIL without corrupting it. By the way, it also happens when converting to grayscale: The only workaround I can currently think of is: import cv2
from PIL import Image
image = Image.open("0026.png")
if image.mode == "I":
cv2_img = cv2.imread("0026.png")
cv2.imwrite("0026_rgb.png", cv2_img)
# Now I can open and work with the image in PIL:
image = Image.open("0026_rgb.png")
image.show() |
Ok, the workaround would be to scale down the pixel values in the image. The following code can be used for converting to either RGB or L. from PIL import Image
im = Image.open("in.png")
if im.format == "PNG" and im.tile[0][-1] == "I;16B":
im = im.point(lambda x: x / 256)
im = im.convert("RGB")
# Or convert to L instead
#im = im.convert("L")
im.save("out.png") or to show the image. from PIL import Image
im = Image.open("in.png")
if im.format == "PNG" and im.tile[0][-1] == "I;16B":
im = im.point(lambda x: x / 256)
im.show() |
Closing as part of #3159 |
@radarhere one small question regarding the proposed workaround: Does a conversion to RGB even make sense? As far as I can tell, Line 2945 in bcded33
So: from PIL import Image
im = Image.open("in.png")
if im.format == "PNG" and im.tile[0][-1] == "I;16B":
im = im.point(lambda x: x / 256)
im = im.convert("L")
im.save("out.png") would make the most sense. At least when I tried to create a synthetic Another small thing: and when I try to access the value in the debugger, it is always |
Converting the image to RGB will work, but it's not space-efficient, no. I;16 images are always grayscale, yes, so sure, you can convert to L. You could
but I wouldn't be surprised if those doesn't help, since they're still not class attributes. Pillow hasn't done much work on typing, and #2625 is an open issue. When an image is loaded, |
What did you do?
I've probably discovered a severe bug in PIL. I'm trying to open an image but when opening and showing it with PIL, the image is incorrectly binarized and visually completely destroyed.
What did you expect to happen?
That the image opens without being destroyed.
What actually happened?
The image gets destroyed:
What are your OS, Python and Pillow versions?
when reading the very same image with opencv, it works just fine:
The text was updated successfully, but these errors were encountered: