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

importing PIL.PngImagePlugin breaks Image.registered_extensions() #6809

Closed
aliencaocao opened this issue Dec 18, 2022 · 5 comments · Fixed by #6811
Closed

importing PIL.PngImagePlugin breaks Image.registered_extensions() #6809

aliencaocao opened this issue Dec 18, 2022 · 5 comments · Fixed by #6811

Comments

@aliencaocao
Copy link

aliencaocao commented Dec 18, 2022

What are your OS, Python and Pillow versions?

  • OS: Windows 10
  • Python: 3.9.13
  • Pillow: 9.3.0
from PIL import Image
print(Image.registered_extensions())

The code above outputs, all what I expected.
{'.blp': 'BLP', '.bmp': 'BMP', '.dib': 'DIB', '.bufr': 'BUFR', '.cur': 'CUR', '.pcx': 'PCX', '.dcx': 'DCX', '.dds': 'DDS', '.ps': 'EPS', '.eps': 'EPS', '.fit': 'FITS', '.fits': 'FITS', '.fli': 'FLI', '.flc': 'FLI', '.ftc': 'FTEX', '.ftu': 'FTEX', '.gbr': 'GBR', '.gif': 'GIF', '.grib': 'GRIB', '.h5': 'HDF5', '.hdf': 'HDF5', '.png': 'PNG', '.apng': 'PNG', '.jp2': 'JPEG2000', '.j2k': 'JPEG2000', '.jpc': 'JPEG2000', '.jpf': 'JPEG2000', '.jpx': 'JPEG2000', '.j2c': 'JPEG2000', '.icns': 'ICNS', '.ico': 'ICO', '.im': 'IM', '.iim': 'IPTC', '.tif': 'TIFF', '.tiff': 'TIFF', '.jfif': 'JPEG', '.jpe': 'JPEG', '.jpg': 'JPEG', '.jpeg': 'JPEG', '.mpg': 'MPEG', '.mpeg': 'MPEG', '.mpo': 'MPO', '.msp': 'MSP', '.palm': 'PALM', '.pcd': 'PCD', '.pdf': 'PDF', '.pxr': 'PIXAR', '.pbm': 'PPM', '.pgm': 'PPM', '.ppm': 'PPM', '.pnm': 'PPM', '.psd': 'PSD', '.bw': 'SGI', '.rgb': 'SGI', '.rgba': 'SGI', '.sgi': 'SGI', '.ras': 'SUN', '.tga': 'TGA', '.icb': 'TGA', '.vda': 'TGA', '.vst': 'TGA', '.webp': 'WEBP', '.wmf': 'WMF', '.emf': 'WMF', '.xbm': 'XBM', '.xpm': 'XPM'}

However, if I try to import PIL.PngImagePlugin, it will override the entire list and leave with ONLY PNG. I do not think this should be the behaviour because no where in the doc says just importing it will remove existing registered extensions.

from PIL import Image
import PIL.PngImagePlugin
print(Image.registered_extensions())

The code above outputs:
{'.png': 'PNG', '.apng': 'PNG'}

What's even more interesting is, if I call Image.registered_extensions() before I import PIL.PngImagePlugin, it works as expected, the existing list is untouched. This should be the behaviour even if I do not call Image.registered_extensions() before importing.

from PIL import Image
print(Image.registered_extensions())
import PIL.PngImagePlugin
print(Image.registered_extensions())

The code above outputs:
{'.blp': 'BLP', '.bmp': 'BMP', '.dib': 'DIB', '.bufr': 'BUFR', '.cur': 'CUR', '.pcx': 'PCX', '.dcx': 'DCX', '.dds': 'DDS', '.ps': 'EPS', '.eps': 'EPS', '.fit': 'FITS', '.fits': 'FITS', '.fli': 'FLI', '.flc': 'FLI', '.ftc': 'FTEX', '.ftu': 'FTEX', '.gbr': 'GBR', '.gif': 'GIF', '.grib': 'GRIB', '.h5': 'HDF5', '.hdf': 'HDF5', '.png': 'PNG', '.apng': 'PNG', '.jp2': 'JPEG2000', '.j2k': 'JPEG2000', '.jpc': 'JPEG2000', '.jpf': 'JPEG2000', '.jpx': 'JPEG2000', '.j2c': 'JPEG2000', '.icns': 'ICNS', '.ico': 'ICO', '.im': 'IM', '.iim': 'IPTC', '.tif': 'TIFF', '.tiff': 'TIFF', '.jfif': 'JPEG', '.jpe': 'JPEG', '.jpg': 'JPEG', '.jpeg': 'JPEG', '.mpg': 'MPEG', '.mpeg': 'MPEG', '.mpo': 'MPO', '.msp': 'MSP', '.palm': 'PALM', '.pcd': 'PCD', '.pdf': 'PDF', '.pxr': 'PIXAR', '.pbm': 'PPM', '.pgm': 'PPM', '.ppm': 'PPM', '.pnm': 'PPM', '.psd': 'PSD', '.bw': 'SGI', '.rgb': 'SGI', '.rgba': 'SGI', '.sgi': 'SGI', '.ras': 'SUN', '.tga': 'TGA', '.icb': 'TGA', '.vda': 'TGA', '.vst': 'TGA', '.webp': 'WEBP', '.wmf': 'WMF', '.emf': 'WMF', '.xbm': 'XBM', '.xpm': 'XPM'} {'.blp': 'BLP', '.bmp': 'BMP', '.dib': 'DIB', '.bufr': 'BUFR', '.cur': 'CUR', '.pcx': 'PCX', '.dcx': 'DCX', '.dds': 'DDS', '.ps': 'EPS', '.eps': 'EPS', '.fit': 'FITS', '.fits': 'FITS', '.fli': 'FLI', '.flc': 'FLI', '.ftc': 'FTEX', '.ftu': 'FTEX', '.gbr': 'GBR', '.gif': 'GIF', '.grib': 'GRIB', '.h5': 'HDF5', '.hdf': 'HDF5', '.png': 'PNG', '.apng': 'PNG', '.jp2': 'JPEG2000', '.j2k': 'JPEG2000', '.jpc': 'JPEG2000', '.jpf': 'JPEG2000', '.jpx': 'JPEG2000', '.j2c': 'JPEG2000', '.icns': 'ICNS', '.ico': 'ICO', '.im': 'IM', '.iim': 'IPTC', '.tif': 'TIFF', '.tiff': 'TIFF', '.jfif': 'JPEG', '.jpe': 'JPEG', '.jpg': 'JPEG', '.jpeg': 'JPEG', '.mpg': 'MPEG', '.mpeg': 'MPEG', '.mpo': 'MPO', '.msp': 'MSP', '.palm': 'PALM', '.pcd': 'PCD', '.pdf': 'PDF', '.pxr': 'PIXAR', '.pbm': 'PPM', '.pgm': 'PPM', '.ppm': 'PPM', '.pnm': 'PPM', '.psd': 'PSD', '.bw': 'SGI', '.rgb': 'SGI', '.rgba': 'SGI', '.sgi': 'SGI', '.ras': 'SUN', '.tga': 'TGA', '.icb': 'TGA', '.vda': 'TGA', '.vst': 'TGA', '.webp': 'WEBP', '.wmf': 'WMF', '.emf': 'WMF', '.xbm': 'XBM', '.xpm': 'XPM'}

I've done some simple troubleshooting and found that

Image.register_extensions(PngImageFile.format, [".png", ".apng"])
causes it. If I print(Image.registered_extensions()) before that line, everything is good, but after that line, it overrides.

This directly causes gradio-app/gradio#2843 AUTOMATIC1111/stable-diffusion-webui#5603 AUTOMATIC1111/stable-diffusion-webui#5664 and I believe many other downstream uses.

@jokkebk
Copy link

jokkebk commented Dec 18, 2022

Can verify that this happens also on my Win10 machine on Python 3.10 as well as Ubuntu on Python 3.8 (running in WSL2).

@Yay295
Copy link
Contributor

Yay295 commented Dec 18, 2022

So when you get the registered extensions, if nothing has been registered, it first initializes everything. But if something has been registered (like when you import the PngImagePlugin), then it just returns that instead of initializing everything.

Pillow/src/PIL/Image.py

Lines 3416 to 3423 in 7f6fe3c

def registered_extensions():
"""
Returns a dictionary containing all file extensions belonging
to registered plugins
"""
if not EXTENSION:
init()
return EXTENSION

@Yay295
Copy link
Contributor

Yay295 commented Dec 18, 2022

So

from PIL import Image
Image.init()

will load everything.

@radarhere
Copy link
Member

I've created PR #6811 to resolve this.

@aliencaocao
Copy link
Author

Thanks for the explanation and the PR.

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