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

Cannot modify the first frame of a MPO with asymmetric sized frames after seek #6100

Closed
telicent opened this issue Mar 1, 2022 · 1 comment · Fixed by #6101
Closed

Cannot modify the first frame of a MPO with asymmetric sized frames after seek #6100

telicent opened this issue Mar 1, 2022 · 1 comment · Fixed by #6101
Labels
Bug Any unexpected behavior, until confirmed feature.

Comments

@telicent
Copy link

telicent commented Mar 1, 2022

What did you do?

Did a seek(1) to the second frame followed by a seek(0) back to the first, and a transpose

What did you expect to happen?

The transpose

What actually happened?

Segmentation fault: 11

What are your OS, Python and Pillow versions?

  • OS: OSX 10.15.7 and Ubuntu 20.04
  • Python: 3.8.11 and 3.10.2
  • Pillow: 9.0.1

This is an edge case issue with images created by the Nikon coolpix 500b (and possibly others), which appears to embed a couple "thumbnails" in the image files. Pillow (reasonably) detects this as a 3-frame MPO. For some reason, however, seeking back to the first frame and trying to modify it after seeking to any other frame crashes with a seg fault.

For the example below I used this image (not sure on the licensing, just the first I googled):
https://img.photographyblog.com/reviews/nikon_coolpix_b500/photos/nikon_coolpix_b500_02.jpg

from PIL import Image
im = Image.open('nikon_coolpix_b500_02.jpg')
im.seek(1)
im.seek(0)
im.transpose(Image.FLIP_LEFT_RIGHT) # => Segment fault: 11

If it helps, I noticed that the im.size doesn't update after the seek(0) back to the first frame, even though tell reports the correct frame:

im = Image.open('nikon_coolpix_b500_02.jpg')
im.size #  =>  (4608, 3456)
im.seek(1)
im.size #  =>  (640, 480)
im.seek(0)
im.size #  =>  (640, 480)
im.tell() # => 0

For my particular case, the problematic usage was some legacy code trying to detect animations that is better handled by checking n_frames, so I was able to work around it. Mainly documenting the issue in case anyone else runs into it.

@radarhere
Copy link
Member

Hi. The problem here is that #5168 introduced a rule that MPO image size can only change for "Large Thumbnail" frames. However, it forgot to reset the size back to the initial value when seeking to another frame after that.

So in the case of your image, the first frame is a "Baseline MP Primary Image".
Then you seek to the second frame, a "Large Thumbnail (VGA Equivalent)", and the size is changed.
And then you seek back to the first frame, where the size incorrectly stays at the dimensions of the Large Thumbnail.

I've created PR #6101 to resolve this.

@radarhere radarhere added the Bug Any unexpected behavior, until confirmed feature. label Mar 1, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Any unexpected behavior, until confirmed feature.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants