From b4221386ff985f1807f1cc22175519b697f9ebb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=B3=D0=BE=D1=80=D1=8C=20=D0=9D=D0=B0=D0=B4=D0=B5?= =?UTF-8?q?=D0=B8=D0=BD?= Date: Tue, 16 Dec 2025 13:36:28 +0300 Subject: [PATCH] fix: preserve EXIF orientation when compressing images --- backend/common/image_utils.py | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/backend/common/image_utils.py b/backend/common/image_utils.py index d7d134da..05972828 100644 --- a/backend/common/image_utils.py +++ b/backend/common/image_utils.py @@ -26,6 +26,10 @@ def compress_image( в системах распознавания лиц. Размер 512x512 обеспечивает достаточное качество для нейросетей при разумном размере файла. + ВАЖНО: Автоматически применяет EXIF-ориентацию перед обработкой. + Это предотвращает "переворачивание" фотографий, сделанных на телефоны + в портретной или перевёрнутой ориентации. + Args: data: Входные данные изображения (любой формат, поддерживаемый PIL) max_width: Максимальная ширина в пикселях (по умолчанию 512) @@ -35,7 +39,7 @@ def compress_image( format: Формат выходного файла (по умолчанию JPEG) Returns: - bytes: Сжатые данные изображения + bytes: Сжатые данные изображения с правильной ориентацией Raises: RuntimeError: Если Pillow не установлен или ошибка обработки @@ -53,6 +57,26 @@ def compress_image( # Открываем изображение img = Image.open(io.BytesIO(data)) + # ИСПРАВЛЕНИЕ: Применяем EXIF-ориентацию перед обработкой + # Это предотвращает "поворот" фотографий с телефонов + try: + # Получаем EXIF данные + exif = img.getexif() + # Тег 274 = Orientation + orientation = exif.get(0x0112) if exif else None + + if orientation: + # Применяем поворот согласно EXIF + if orientation == 3: + img = img.rotate(180, expand=True) + elif orientation == 6: + img = img.rotate(270, expand=True) + elif orientation == 8: + img = img.rotate(90, expand=True) + except (AttributeError, KeyError, IndexError): + # Если EXIF недоступен или повреждён - продолжаем без ротации + pass + # Конвертируем в RGB (для JPEG) if img.mode in ("RGBA", "LA", "P"): # Создаем белый фон для прозрачных изображений