Spaces:
Runtime error
Runtime error
| 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"] | |
| # Check if file exists | |
| if file_object is None: | |
| return False | |
| # Get filename | |
| filename = file_object.name | |
| # Check file extension | |
| file_ext = os.path.splitext(filename)[1].lower() | |
| if file_ext not in allowed_extensions: | |
| return False | |
| try: | |
| # Try opening the image to verify it's valid | |
| image = Image.open(file_object) | |
| image.verify() | |
| # Reset file position | |
| 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: | |
| # Reset file pointer to beginning | |
| file_object.seek(0) | |
| # Read file content | |
| contents = file_object.read() | |
| # Create a unique filename | |
| file_ext = os.path.splitext(file_object.name)[1].lower() | |
| unique_filename = f"{uuid.uuid4().hex}{file_ext}" | |
| # Make sure the upload folder exists | |
| os.makedirs(upload_folder, exist_ok=True) | |
| # Define the full file path | |
| file_path = os.path.join(upload_folder, unique_filename) | |
| # Save the file | |
| with open(file_path, "wb") as f: | |
| f.write(contents) | |
| # Verify the saved file can be opened | |
| try: | |
| with Image.open(file_path) as test_img: | |
| # Just test that it can be opened | |
| test_img.verify() | |
| except Exception as e: | |
| print(f"Verification of saved image failed: {e}") | |
| # Try an alternative approach to save the file | |
| 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 | |
| """ | |
| # Handle image input - could be a file path or PIL Image | |
| if isinstance(image, str): | |
| try: | |
| # Explicitly use 'RGB' mode to ensure proper color handling | |
| image = Image.open(image).convert("RGB") | |
| except Exception as e: | |
| raise ValueError(f"Could not open image file: {str(e)}") | |
| # Get original dimensions | |
| width, height = image.size | |
| # Check if resize is needed | |
| if width <= max_size[0] and height <= max_size[1]: | |
| return image | |
| # Calculate new dimensions | |
| 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)) | |
| # Resize and return | |
| return image.resize((new_width, new_height), Image.LANCZOS) | |