viral-images / utils /preprocessing.py
Babajaan's picture
Full Viral Images v1.0 implementation - all modules and configs
6ceaa94 verified
"""Image preprocessing utilities."""
import numpy as np
from PIL import Image
import hashlib
from typing import Tuple, Optional
def preprocess_image(image_input, max_size: int = 1024) -> Image.Image:
"""
Preprocess any image input into a standardized PIL RGB image.
Args:
image_input: PIL Image, numpy array, or file path
max_size: maximum dimension for resizing
Returns:
PIL Image in RGB mode, resized to max_size if needed
"""
if isinstance(image_input, str):
img = Image.open(image_input).convert("RGB")
elif isinstance(image_input, np.ndarray):
if image_input.ndim == 2:
img = Image.fromarray(image_input).convert("RGB")
elif image_input.ndim == 3:
img = Image.fromarray(image_input).convert("RGB")
else:
raise ValueError(f"Unexpected array shape: {image_input.shape}")
elif isinstance(image_input, Image.Image):
img = image_input.convert("RGB")
else:
raise TypeError(f"Unsupported image type: {type(image_input)}")
# Resize if too large
w, h = img.size
if max(w, h) > max_size:
scale = max_size / max(w, h)
new_w, new_h = int(w * scale), int(h * scale)
img = img.resize((new_w, new_h), Image.LANCZOS)
return img
def compute_image_hash(img: Image.Image) -> str:
"""Compute SHA256 hash of image pixels for caching."""
return hashlib.sha256(np.array(img).tobytes()).hexdigest()
def get_image_size(img: Image.Image) -> Tuple[int, int]:
"""Return (width, height) of image."""
return img.size
def validate_image(img: Image.Image, min_size: int = 50) -> Optional[str]:
"""
Validate image meets minimum requirements.
Returns error message if invalid, None if valid.
"""
w, h = img.size
if w < min_size or h < min_size:
return f"Image too small: {w}x{h}. Minimum {min_size}x{min_size} required."
return None