from PIL import Image from io import BytesIO import requests import base64 from typing import Union, Tuple def resize_image(image_input: Union[str, BytesIO], target_size: Tuple[int, int], return_format: str = "base64") -> str: """ Resize an image to the target size while maintaining aspect ratio. Args: image_input: URL, file path, base64 string, or BytesIO object target_size: Tuple (width, height) for the target size return_format: Format to return the image in ("base64" or "pil") Returns: Base64 encoded string of the resized image or PIL Image object """ # Convert input to PIL Image if isinstance(image_input, str): if image_input.startswith(('http://', 'https://')): # It's a URL response = requests.get(image_input, timeout=10) response.raise_for_status() image = Image.open(BytesIO(response.content)) elif image_input.startswith('data:image'): # It's a base64 data URI base64_data = image_input.split(',')[1] image = Image.open(BytesIO(base64.b64decode(base64_data))) elif ';base64,' not in image_input and len(image_input) > 500: # Likely a raw base64 string image = Image.open(BytesIO(base64.b64decode(image_input))) else: # Assume it's a file path image = Image.open(image_input) elif isinstance(image_input, BytesIO): image = Image.open(image_input) else: raise ValueError("Unsupported image input type") # Calculate the aspect ratio aspect_ratio = min(target_size[0] / image.width, target_size[1] / image.height) # Calculate new size new_size = (int(image.width * aspect_ratio), int(image.height * aspect_ratio)) # Resize the image using the proper resampling filter resized_image = image.resize(new_size, Image.LANCZOS) # Return in requested format if return_format.lower() == "base64": buffer = BytesIO() resized_image.save(buffer, format="PNG") return base64.b64encode(buffer.getvalue()).decode('utf-8') else: return resized_image