Added code samples for AI-Agents
This commit is contained in:
100
services/image_processor.py
Normal file
100
services/image_processor.py
Normal file
@@ -0,0 +1,100 @@
|
||||
"""Сервис обработки изображений."""
|
||||
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,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user