from PIL import Image, ImageDraw, ImageFont, ImageEnhance import piexif class ImageProcessor: """Functions using pillow are in here.""" def __init__(self): pass def open_image(self, path): """Open an image from path, returns image object.""" return Image.open(path) def get_image_size(self, image): """Simply get image size.""" return image.size def grayscale(self, image): """Change to grayscale""" return image.convert("L") def change_contrast(self, image, change): enhancer = ImageEnhance.Contrast(image) new_img = enhancer.enhance(1 + (change/100)) return new_img def change_brightness(self, image, change): enhancer = ImageEnhance.Brightness(image) new_img = enhancer.enhance(1 + (change/100)) return new_img def resize_image(self, image, percent, resample = True): """Resize an image by giving a percent.""" new_size = tuple(int(x * (percent / 100)) for x in image.size) if resample: resized_image = image.resize(new_size) else: resized_image = image.resize((new_size),resample=Image.Resampling.NEAREST) return resized_image def add_watermark(self, image, text, font_size_scale = 70): drawer = ImageDraw.Draw(image) imagewidth, imageheight = image.size margin = (imageheight / 100 ) * 2 # margin dynamic, 2% of image size font_size = imagewidth / font_size_scale # Scaling the font size try: font = ImageFont.truetype("OpenDyslexic3-Regular.ttf", font_size) except: print("Error loading font for watermark, exiting...") exit() c, w, textwidth, textheight, = drawer.textbbox(xy = (0, 0), text = text, font = font) # Getting text size, only need the last two values x = imagewidth - textwidth - margin y = imageheight - textheight - margin drawer.text((x, y), text, font = font) return image def save_image(self, image, path, file_type, jpg_quality, png_compressing, _optimize, exif_data = None): """Saving images. Needs improvments.""" if exif_data != None: if file_type == "jpg": image.save(f"{path}.{file_type.lower()}", quality = jpg_quality, optimize = _optimize, exif = piexif.dump(exif_data)) elif file_type == "png": image.save(f"{path}.{file_type.lower()}", compress_level = png_compressing, optimize = _optimize, exif = piexif.dump(exif_data)) else: input(f"Type: {file_type} not yet aviable, enter to continue...") else: if file_type == "jpg": image.save(f"{path}.{file_type.lower()}", quality = jpg_quality, optimize = _optimize) elif file_type == "png": image.save(f"{path}.{file_type.lower()}", compress_level = png_compressing, optimize = _optimize) else: input(f"Type: {file_type} not yet aviable, enter to continue...") class ExifHandler: """Function using piexif are here.""" def __init__(self): pass def get_exif_info(self, image): return(piexif.load(image.info['exif'])) def build_exif_dict(self, user_data, imagesize): """Build a piexif-compatible EXIF dictionary from user data.""" # Mostly made by ChatGPT, some adjustment by Mr Finchum zeroth_ifd = { piexif.ImageIFD.Make: user_data["make"], piexif.ImageIFD.Model: user_data["model"], piexif.ImageIFD.Software: user_data["software"], piexif.ImageIFD.Copyright: user_data["copyright_info"], piexif.ImageIFD.Artist: user_data["artist"], piexif.ImageIFD.ImageDescription: user_data["image_description"], piexif.ImageIFD.XResolution: (72, 1), piexif.ImageIFD.YResolution: (72, 1), } exif_ifd = { piexif.ExifIFD.DateTimeOriginal: user_data["date_time_original"], piexif.ExifIFD.UserComment: user_data["user_comment"], piexif.ExifIFD.ISOSpeedRatings: int(user_data["iso"]), piexif.ExifIFD.PixelXDimension: imagesize[0], piexif.ExifIFD.PixelYDimension: imagesize[1], } return {"0th": zeroth_ifd, "Exif": exif_ifd}