Files
MementoMori/kivy/core/image/img_pil.py
thatscringebro abd15f28b6 Ajout du GUI
2022-08-08 16:31:52 -04:00

124 lines
3.6 KiB
Python

'''
PIL: PIL image loader
'''
__all__ = ('ImageLoaderPIL', )
try:
import Image as PILImage
except ImportError:
# for python3
from PIL import Image as PILImage
from kivy.logger import Logger
from kivy.core.image import ImageLoaderBase, ImageData, ImageLoader
try:
# Pillow
PILImage.frombytes
PILImage.Image.tobytes
except AttributeError:
# PIL
# monkey patch frombytes and tobytes methods, refs:
# https://github.com/kivy/kivy/issues/5460
PILImage.frombytes = PILImage.frombuffer
PILImage.Image.tobytes = PILImage.Image.tostring
class ImageLoaderPIL(ImageLoaderBase):
'''Image loader based on the PIL library.
.. versionadded:: 1.0.8
Support for GIF animation added.
Gif animation has a lot of issues(transparency/color depths... etc).
In order to keep it simple, what is implemented here is what is
natively supported by the PIL library.
As a general rule, try to use gifs that have no transparency.
Gif's with transparency will work but be prepared for some
artifacts until transparency support is improved.
'''
@staticmethod
def can_save(fmt, is_bytesio):
if is_bytesio:
return False
return fmt in ImageLoaderPIL.extensions()
@staticmethod
def can_load_memory():
return True
@staticmethod
def extensions():
'''Return accepted extensions for this loader'''
PILImage.init()
return tuple((ext_with_dot[1:] for ext_with_dot in PILImage.EXTENSION))
def _img_correct(self, _img_tmp):
'''Convert image to the correct format and orientation.
'''
# image loader work only with rgb/rgba image
if _img_tmp.mode.lower() not in ('rgb', 'rgba'):
try:
imc = _img_tmp.convert('RGBA')
except:
Logger.warning(
'Image: Unable to convert image to rgba (was %s)' %
(_img_tmp.mode.lower()))
raise
_img_tmp = imc
return _img_tmp
def _img_read(self, im):
'''Read images from an animated file.
'''
im.seek(0)
# Read all images inside
try:
img_ol = None
while True:
img_tmp = im
img_tmp = self._img_correct(img_tmp)
if img_ol and (hasattr(im, 'dispose') and not im.dispose):
# paste new frame over old so as to handle
# transparency properly
img_ol.paste(img_tmp, (0, 0), img_tmp)
img_tmp = img_ol
img_ol = img_tmp
yield ImageData(img_tmp.size[0], img_tmp.size[1],
img_tmp.mode.lower(), img_tmp.tobytes())
im.seek(im.tell() + 1)
except EOFError:
pass
def load(self, filename):
try:
im = PILImage.open(filename)
except:
Logger.warning('Image: Unable to load image <%s>' % filename)
raise
# update internals
if not self._inline:
self.filename = filename
# returns an array of type ImageData len 1 if not a sequence image
return list(self._img_read(im))
@staticmethod
def save(filename, width, height, pixelfmt, pixels, flipped=False,
imagefmt=None):
image = PILImage.frombytes(pixelfmt.upper(), (width, height), pixels)
if flipped:
image = image.transpose(PILImage.FLIP_TOP_BOTTOM)
image.save(filename)
return True
# register
ImageLoader.register(ImageLoaderPIL)