Files
New-planet-ai-agent/services/image_processor.py

101 lines
3.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Сервис обработки изображений."""
import io
from pathlib import Path
from typing import Optional, Tuple
from PIL import Image
class ImageProcessor:
"""Сервис для обработки изображений заданий."""
MAX_SIZE = (800, 800)
SUPPORTED_FORMATS = {"JPEG", "PNG", "WEBP"}
QUALITY = 85
@staticmethod
def resize_image(
image_data: bytes, max_size: Tuple[int, int] = MAX_SIZE, quality: int = QUALITY
) -> bytes:
"""
Изменить размер изображения.
Args:
image_data: Байты изображения
max_size: Максимальный размер (width, height)
quality: Качество JPEG (1-100)
Returns:
Байты обработанного изображения
"""
image = Image.open(io.BytesIO(image_data))
image_format = image.format or "JPEG"
# Конвертируем в RGB если нужно
if image_format == "PNG" and image.mode in ("RGBA", "LA"):
background = Image.new("RGB", image.size, (255, 255, 255))
if image.mode == "RGBA":
background.paste(image, mask=image.split()[3])
else:
background.paste(image)
image = background
elif image.mode != "RGB":
image = image.convert("RGB")
# Изменяем размер с сохранением пропорций
image.thumbnail(max_size, Image.Resampling.LANCZOS)
# Сохраняем в байты
output = io.BytesIO()
image.save(output, format="JPEG", quality=quality, optimize=True)
return output.getvalue()
@staticmethod
def validate_image(image_data: bytes) -> Tuple[bool, Optional[str]]:
"""
Валидировать изображение.
Args:
image_data: Байты изображения
Returns:
(is_valid, error_message)
"""
try:
image = Image.open(io.BytesIO(image_data))
image_format = image.format
if image_format not in ImageProcessor.SUPPORTED_FORMATS:
return False, f"Неподдерживаемый формат: {image_format}"
# Проверяем размер
width, height = image.size
if width > 2000 or height > 2000:
return False, "Изображение слишком большое (максимум 2000x2000)"
# Проверяем файл на валидность
image.verify()
return True, None
except Exception as e:
return False, f"Ошибка валидации: {str(e)}"
@staticmethod
def get_image_info(image_data: bytes) -> dict:
"""
Получить информацию об изображении.
Args:
image_data: Байты изображения
Returns:
Словарь с информацией (format, size, mode)
"""
image = Image.open(io.BytesIO(image_data))
return {
"format": image.format,
"size": image.size,
"mode": image.mode,
}