DeepFakeDetectorBackend / app /services /preprocess_service.py
lukhsaankumar's picture
Deploy DeepFake Detector API - 2026-03-07 09:12:00
df4a21a
Raw History Blame Contribute Delete
3.63 kB
"""
Image preprocessing service.
"""
from typing import Optional, Dict, Any
from PIL import Image
from app.core.errors import ImageProcessingError
from app.core.logging import get_logger
from app.utils.image import load_image_from_bytes, validate_image_bytes
from app.utils.security import validate_file_size, validate_image_content, MAX_FILE_SIZE_BYTES
logger = get_logger(__name__)
class PreprocessService:
"""
Service for preprocessing images before model inference.
For Milestone 1, this is minimal - just validates and optionally
decodes images. Future milestones will add more preprocessing.
"""
def __init__(self, max_file_size: int = MAX_FILE_SIZE_BYTES):
"""
Initialize the preprocess service.
Args:
max_file_size: Maximum allowed file size in bytes
"""
self.max_file_size = max_file_size
def validate_image(self, image_bytes: bytes) -> Dict[str, Any]:
"""
Validate uploaded image bytes.
Args:
image_bytes: Raw image bytes
Returns:
Dictionary with validation results
Raises:
ImageProcessingError: If validation fails
"""
# Check file size
if not validate_file_size(image_bytes, self.max_file_size):
raise ImageProcessingError(
message=f"File too large. Maximum size is {self.max_file_size // (1024*1024)}MB",
details={"size": len(image_bytes), "max_size": self.max_file_size}
)
# Check content type via magic bytes
if not validate_image_content(image_bytes):
raise ImageProcessingError(
message="Invalid image format. Supported formats: JPEG, PNG, GIF, WebP, BMP",
details={"size": len(image_bytes)}
)
return {
"valid": True,
"size_bytes": len(image_bytes)
}
def decode_image(self, image_bytes: bytes) -> Image.Image:
"""
Decode image bytes to PIL Image.
Args:
image_bytes: Raw image bytes
Returns:
PIL Image object
Raises:
ImageProcessingError: If decoding fails
"""
return load_image_from_bytes(image_bytes)
def preprocess(
self,
image_bytes: bytes,
decode: bool = False
) -> Dict[str, Any]:
"""
Full preprocessing pipeline.
Args:
image_bytes: Raw image bytes
decode: Whether to decode to PIL Image
Returns:
Dictionary with:
- image_bytes: Original or processed bytes
- image: PIL Image if decode=True
- validation: Validation results
"""
# Validate
validation = self.validate_image(image_bytes)
result = {
"image_bytes": image_bytes,
"validation": validation
}
# Optionally decode
if decode:
result["image"] = self.decode_image(image_bytes)
return result
# Global singleton instance
_preprocess_service: Optional[PreprocessService] = None
def get_preprocess_service() -> PreprocessService:
"""
Get the global preprocess service instance.
Returns:
PreprocessService instance
"""
global _preprocess_service
if _preprocess_service is None:
_preprocess_service = PreprocessService()
return _preprocess_service