Skip to content
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

Saving images to stdout using some file formats does not write the image correctly #5657

Closed
infmagic2047 opened this issue Aug 6, 2021 · 6 comments · Fixed by #5665
Closed

Comments

@infmagic2047
Copy link
Contributor

What did you do?

I created a image and saved it to stdout using PPM format.

What did you expect to happen?

The image is written correctly.

What actually happened?

Only the PPM header is written, and the image data is not.

What are your OS, Python and Pillow versions?

  • OS: Gentoo Linux
  • Python: Tested with both 3.8.11 and 3.9.6
  • Pillow: 8.3.1
import sys
from PIL import Image

im = Image.frombytes('RGB', (4, 4), b'\0' * 48)
im.save(sys.stdout, 'ppm')
@infmagic2047
Copy link
Contributor Author

Additional note: This bug only happens when saving to stdout. It does not seem to happen when saving to a named file, file object, or other file-like objects like BytesIO.

Interestingly, some other file formats are affected as well: when saving the image as JPEG, no data is written at all. With GIF the image is corrupted (see below). PNG seems to be unaffected, though.

GIF example:

im = Image.frombytes('RGB', (4, 4), b'\xff\0\0' * 16)
im.save(sys.stdout, 'gif')

The output has two black pixels (unexpected) in lower left.

@infmagic2047 infmagic2047 changed the title Saving images to stdout using PPM format does not write the image data Saving images to stdout using some file formats does not write the image correctly Aug 6, 2021
@wiredfool
Copy link
Member

wiredfool commented Aug 6, 2021

sys.stdout is effectively a text file, the equivalent of io.StringIO, likely to be in utf-8 or your specific locale. (https://docs.python.org/3/library/sys.html#sys.stdout) Pillow has never been able to save to a io.StringIO instance on python 3, it has always required a io.BytesIO.

Most image formats have invalid utf-8 sequences in them, so they're not generally going to work with sys.stdout, unless you explicitly write the binary data to the underlying stream as mentioned in the link.

@infmagic2047
Copy link
Contributor Author

Well, Pillow should be able to convert sys.stdout to sys.stdout.buffer according to #5437. Testing with sys.stdout.buffer returns the same erroneous results as well.

@wiredfool
Copy link
Member

Missed that change.

@mclegrand
Copy link

(note: this bug has implications "downstream" in Inkscape where we use pillow to convert to different formats on export : https://gitlab.com/inkscape/inkscape/-/issues/2860 - Proposed fix ("remove lines 496 to 502 in ImageFile.py") appears to solve it )

@radarhere
Copy link
Member

PNG is unaffected because it wraps fp in _idat, and so does appear to be stdout as far as ImageFile can tell.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants