| import io
|
| import os
|
| import uuid
|
| from PIL import Image
|
|
|
|
|
| def validate_image(file_object, allowed_extensions=None):
|
| """
|
| Validate an uploaded image file
|
|
|
| Args:
|
| file_object: The uploaded file object (Streamlit's UploadedFile)
|
| allowed_extensions (list, optional): List of allowed file extensions.
|
| Defaults to ['.jpg', '.jpeg', '.png', '.bmp', '.gif'].
|
|
|
| Returns:
|
| bool: True if valid, False otherwise
|
| """
|
| if allowed_extensions is None:
|
| allowed_extensions = [".jpg", ".jpeg", ".png", ".bmp", ".gif"]
|
|
|
|
|
| if file_object is None:
|
| return False
|
|
|
|
|
| filename = file_object.name
|
|
|
|
|
| file_ext = os.path.splitext(filename)[1].lower()
|
| if file_ext not in allowed_extensions:
|
| return False
|
|
|
| try:
|
|
|
| image = Image.open(file_object)
|
| image.verify()
|
|
|
|
|
| file_object.seek(0)
|
| return True
|
| except Exception as e:
|
| print(f"Image validation error: {e}")
|
| return False
|
|
|
|
|
| def save_uploaded_image(file_object, upload_folder):
|
| """
|
| Save an uploaded image to disk with a unique filename
|
|
|
| Args:
|
| file_object: The uploaded file object (Streamlit's UploadedFile)
|
| upload_folder (str): The folder to save the image to
|
|
|
| Returns:
|
| str: The path to the saved image or None if failed
|
| """
|
| if file_object is None:
|
| return None
|
|
|
| try:
|
|
|
| file_object.seek(0)
|
|
|
|
|
| contents = file_object.read()
|
|
|
|
|
| file_ext = os.path.splitext(file_object.name)[1].lower()
|
| unique_filename = f"{uuid.uuid4().hex}{file_ext}"
|
|
|
|
|
| os.makedirs(upload_folder, exist_ok=True)
|
|
|
|
|
| file_path = os.path.join(upload_folder, unique_filename)
|
|
|
|
|
| with open(file_path, "wb") as f:
|
| f.write(contents)
|
|
|
|
|
| try:
|
| with Image.open(file_path) as test_img:
|
|
|
| test_img.verify()
|
| except Exception as e:
|
| print(f"Verification of saved image failed: {e}")
|
|
|
| img = Image.open(io.BytesIO(contents))
|
| img.save(file_path)
|
|
|
| return file_path
|
| except Exception as e:
|
| print(f"Error saving file: {e}")
|
| return None
|
|
|
|
|
| def resize_image(image, max_size=(800, 800)):
|
| """
|
| Resize an image while maintaining aspect ratio
|
|
|
| Args:
|
| image (PIL.Image.Image or str): Image to resize or path to image
|
| max_size (tuple, optional): Maximum width and height. Defaults to (800, 800).
|
|
|
| Returns:
|
| PIL.Image.Image: Resized image
|
| """
|
|
|
| if isinstance(image, str):
|
| try:
|
|
|
| image = Image.open(image).convert("RGB")
|
| except Exception as e:
|
| raise ValueError(f"Could not open image file: {str(e)}")
|
|
|
|
|
| width, height = image.size
|
|
|
|
|
| if width <= max_size[0] and height <= max_size[1]:
|
| return image
|
|
|
|
|
| if width > height:
|
| new_width = max_size[0]
|
| new_height = int(height * (max_size[0] / width))
|
| else:
|
| new_height = max_size[1]
|
| new_width = int(width * (max_size[1] / height))
|
|
|
|
|
| return image.resize((new_width, new_height), Image.LANCZOS)
|
|
|