import base64 import time from io import BytesIO from PIL import Image from loguru import logger def crop_image(img: Image, new_size: tuple[int, int]) -> Image: """ Crop an image to the specified size, maintaining the aspect ratio. :param img: The image to crop. :param new_size: The target size of the cropped image. :return: The cropped image. """ width, height = img.size target_width, target_height = new_size aspect_ratio = width / height target_aspect_ratio = target_width / target_height if aspect_ratio > target_aspect_ratio: new_height = target_height new_width = int(aspect_ratio * new_height) else: new_width = target_width new_height = int(new_width / aspect_ratio) img = img.resize((new_width, new_height), Image.Resampling.LANCZOS) left = (new_width - target_width) / 2 top = (new_height - target_height) / 2 right = (new_width + target_width) / 2 bottom = (new_height + target_height) / 2 return img.crop((left, top, right, bottom)) def encode_image_to_webp_base64(filepath): """ Encodes an image file to WEBP and then to a Base64 string. :param filepath: Path to the image file :return: Base64 encoded string of the WEBP image :raises ValueError: If filepath is None or other issues occur during encoding """ start_time = time.time() if filepath is None: raise ValueError("File path is None.") try: pil_image = Image.open(filepath) if pil_image.mode == 'RGBA': pil_image = pil_image.convert('RGB') buffered = BytesIO() pil_image.save(buffered, format="WEBP") base64_image = base64.b64encode(buffered.getvalue()).decode('utf-8') return base64_image except Exception as e: raise ValueError(f"Failed to encode image to WEBP base64: {str(e)}") finally: end_time = time.time() elapsed_time = end_time - start_time logger.info(f"Encoding image to WebP and Base64 spent {elapsed_time:.2f} seconds to process.") def encode_webp_to_base64(image_file): """ Encodes a WEBP image file (from HTTP upload) directly to a Base64 string. :param image_file: InMemoryUploadedFile object containing the WEBP image :return: Base64 encoded string of the WEBP image :raises ValueError: If image_file is None or other issues occur during encoding """ start_time = time.time() if image_file is None: raise ValueError("Image file is None.") try: # Ensure that the file is read as binary data base64_image = base64.b64encode(image_file.read()).decode('utf-8') return base64_image except Exception as e: raise ValueError(f"Failed to encode WEBP image to Base64: {str(e)}") finally: end_time = time.time() elapsed_time = end_time - start_time logger.info(f"Encoding image to Base64 spent {elapsed_time:.2f} seconds to process.")