from PIL import Image from io import BytesIO from functools import lru_cache @lru_cache(maxsize=512) def generate_thumbnail(image_path, resize_percent, min_width, max_width): # Open the image file with Image.open(image_path) as img: # Calculate the new size based on the resize percentage width, height = img.size new_width = int(width * resize_percent / 100) new_height = int(height * resize_percent / 100) # Ensure the minimum width is maintained if new_width < min_width: scale_factor = min_width / new_width new_width = min_width new_height = int(new_height * scale_factor) # Ensure the maximum width is not exceeded if new_width > max_width: scale_factor = max_width / new_width new_width = max_width new_height = int(new_height * scale_factor) # Resize the image while maintaining the aspect ratio img.thumbnail((new_width, new_height)) # Rotate the image based on the EXIF orientation tag try: exif = img.info['exif'] orientation = img._getexif().get(0x0112, 1) # 0x0112 is the EXIF orientation tag print(f"EXIF orientation: {orientation}, {image_path}") if orientation == 3: img = img.rotate(180, expand=True) elif orientation == 6: img = img.rotate(90, expand=True) elif orientation == 8: img = img.rotate(270, expand=True) except (AttributeError, KeyError, IndexError): # cases: image don't have getexif exif = b"" # Save the thumbnail to a BytesIO object thumbnail_io = BytesIO() img_format = img.format if img.format in ["JPEG", "JPG", "PNG"] else "JPEG" img.save(thumbnail_io, format=img_format, exif=exif) thumbnail_io.seek(0) return (thumbnail_io.getvalue(), img_format)