import io import PIL import PIL.Image import base64 import pathlib from .exception import image_exception class image: """ This class is responsible for image storing. It get image coded as base64 validate it, and when all went well, it could be saved and also thumbnail could be generated. """ def __init__( self, coded: str, max_size: int = 2 * 1024 * 1024 * 16 ) -> None: """ This initialize new image saver. Parameters: coded (str): Image as base64 content thumbnail (int): Diameters of image thumbnail (default = 400) max_size (int): Max size of image file (default = 16Mb) """ if len(coded) > max_size: raise image_exception() self.__content = base64.standard_b64decode(coded) if not self.valid: raise image_exception() @property def content(self) -> bytes: """ Image as bytes. """ return self.__content @property def __file(self) -> io.BytesIO: """ Image bytes as IO file like buffer. """ return io.BytesIO(self.content) @property def __image(self) -> PIL.Image: """ New PIL Image object from received bytes. """ try: return PIL.Image.open(self.__file) except: raise image_exception() def save_thumbnail( self, location: pathlib.Path, diameter: int = 400 ) -> object: """ This save generated thumbnail in given location. Format of the thumbnail is defined by location extension. Parameters: location (pathlib.Path): Place to store thumbnail Returns: (image): Self to chain dot calls """ with self.__image as image: image.thumbnail((diameter, diameter)) image.save(location) return self def save_full(self, location: pathlib.Path) -> object: """ This save received image in given location. Format of the image is based on the location extension. Parameters: location (pathlib.Path): Place to store image Returns: (image): Self to chain dot calls """ with self.__image as image: image.save(location) return self @property def valid(self) -> bool: """ True when image is valid, false when not. """ try: with self.__image as image: image.verify() return True except: return False