OpenOversight icon indicating copy to clipboard operation
OpenOversight copied to clipboard

Allow MPO image upload

Open sea-kelp opened this issue 9 months ago • 1 comments

Description of Changes

We recently found that OpenOversight rejects images Pillow detects as mpo images since it isn't included in the ALLOWED_EXTENSIONS list.

MPO is an extension of JPEG which allows certain cameras to take "stereoscopic" images from multiple perspectives which can be rendered in 3D by supported devices. MPO files sometimes use the .mpo file extension but often use .jpg/.jpeg. This can be confusing to users when files appearing to be JPEGs are rejected (because PIL detects them as MPO).

This change adds MPO to the ALLOWED_EXTENSIONS list.

A concern with MPO files is that the additional frames included in the file could leak details the uploader was not aware of/did not intend to include. When we save the uploaded image, we call pimage.save without the save_all parameter, the parameter that would need to be specified to save more than the first frame. This means our current process is already set up to discard any additional frames included in MPO files.

I verified this by uploading this MPO image with 2 frames to OO:

>>> from PIL import Image
>>> img = Image.open("image.jpg")
>>> img.format
'MPO'
>>> img.n_frames
2
>>> 

And then downloading it:

>>> from PIL import Image
>>> img = Image.open("4e6d42d451daaadb0185b06cf972983499b98fd2447a422dc35c78b2f1bcac.jpeg")
>>> img
<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=4080x3072 at 0x75034948D190>
>>> img.n_frames
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'JpegImageFile' object has no attribute 'n_frames'
>>> img.format
'JPEG'

Also confirmed this without OpenOversight:

>>> from PIL import Image
>>> img = Image.open("img.jpg")
>>> img.format
'MPO'
>>> img.n_frames
2
>>> img.save("img1.jpg")
>>> img = Image.open("img1.jpg")
>>> img.format
'JPEG'
>>> img.n_frames
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'JpegImageFile' object has no attribute 'n_frames'

Notes for Deployment

None!

Screenshots (if appropriate)

N/A

Tests and Linting

  • [x] This branch is up-to-date with the develop branch.
  • [x] pytest passes on my local development environment.
  • [x] pre-commit passes on my local development environment.

sea-kelp avatar May 03 '24 07:05 sea-kelp

🔬 If possible, I think it'd be good to have a test for each file type. I'd be happy to add that if you don't have the bandwidth for it.

michplunkett avatar May 04 '24 17:05 michplunkett