Как автоматически конвертировать фото в нужный формат на Python

🖼️ Кратко: Научитесь конвертировать сотни изображений в WebP, JPG или PNG за один запуск скрипта. С сжатием, контролем качества и защитой от битых файлов.
Как в python конвертировать изображение

Каждый из нас сталкивался с тем, что нужно конвертировать фото в нужный нам формат. Если 1-5 фото то можно и вручную это сделать с помощью разных онлайн сервисов, а если нужно 500-1000 фото обработать. Вот как недавно я оптимизировал сайт одного клиента и понял: 90% трафика уходит на изображения. Многие — старые PNG и JPG без сжатия и т.д.

И я написал Python-скрипт с использованием библиотеки Pillow, который за 30 секунд перевёл всё в нужный формат, с заданным качеством и без потерь.

В этой статье я покажу, как сделать то же самое:

  • массовая конвертация изображений,
  • выбор формата (WebP, JPG, PNG),
  • настройка качества и сжатия,
  • обработка ошибок и пропуск неизвестных файлов.

Готовый код можно сразу использовать в ваших проектах.

Почему WebP — лучший выбор для современных сайтов?

WebP, разработанный Google, даёт:

  • На 25–35% меньший размер, чем JPG, при том же качестве
  • Поддержку прозрачности (как у PNG)
  • Полная поддержка в Chrome, Firefox, Edge, Safari (с iOS 14+)

📊 Пример: фото 1920×1080:

  • original.jpg — 2.1 МБ
  • converted.webp (quality=80) — 680 КБ
    — выгода очевидна.

Шаг 1. Установка Pillow и базовая проверка

Установка

pip install Pillow

Проверка поддержки WebP

Не все сборки Pillow поддерживают WebP. Проверьте:

from PIL import features
print("WebP поддерживается:", features.check('webp'))

Если False — переустановите:

pip uninstall Pillow -y
pip install --upgrade Pillow

Шаг 2. Конвертация одного файла с учётом цветового режима

Проблема с PNG и прозрачностью

PNG может быть в режиме RGBA (с альфа-каналом). Но JPG и WebP без прозрачности не принимают RGBA.

Решение:

def convert_image(input_path, output_path, format="WEBP", quality=80):
    try:
        with Image.open(input_path) as img:
            # Если целевой формат НЕ поддерживает прозрачность — конвертируем в RGB
            if img.mode in ("RGBA", "P") and format not in ("PNG", "WEBP"):
                img = img.convert("RGB")
            # Для WebP с прозрачностью — оставляем RGBA
            elif img.mode == "P":
                img = img.convert("RGBA")
            
            img.save(
                output_path,
                format=format,
                quality=quality,
                optimize=True,
                method=6  # только для WebP — максимальное сжатие
            )
        print(f"✅ {input_path} → {output_path}")
    except Exception as e:
        print(f"❌ Ошибка: {input_path} — {e}")

💡 method=6 — медленнее, но даёт на 10–15% меньший файл.

Шаг 3. Массовая конвертация с фильтрацией

from pathlib import Path

SUPPORTED = {".jpg", ".jpeg", ".png", ".bmp", ".tiff"}

def batch_convert(folder, target_format="WEBP", quality=85):
    source = Path(folder)
    for file in source.iterdir():
        if file.is_file() and file.suffix.lower() in SUPPORTED:
            new_name = file.stem + "." + target_format.lower()
            output = source / new_name
            if not output.exists():
                convert_image(file, output, target_format, quality)

# Пример: конвертация фото из Telegram-бота
batch_convert("/home/user/bot_uploads", "WEBP", quality=75)

Шаг 4. Практические кейсы

Кейс 1. Подготовка изображений для сайта

Если вы хотите, чтобы все фото в /static/images были в WebP:

batch_convert("static/images", "WEBP", quality=80)

Теперь в HTML можно использовать:

<picture>
  <source srcset="photo.webp" type="image/webp">
  <img src="photo.jpg" alt="...">
</picture>

Кейс 2. Сравнение размеров до и после

Добавьте в скрипт:

original_size = file.stat().st_size
new_size = output.stat().st_size
saved = (1 - new_size / original_size) * 100
print(f"  Сжато на {saved:.1f}%")

Вывод:

&#x2705; photo.jpg → photo.webp
  Сжато на 67.3%

Шаг 5. Обработка ошибок: битые файлы, недостаток памяти

Иногда файлы бывают повреждены. Pillow может упасть с OSError. Ловим:

except (OSError, ValueError) as e:
    if "broken" in str(e).lower() or "truncated" in str(e).lower():
        print(f"&#x26a0;&#xfe0f; Битый файл: {input_path}")
    else:
        print(f"&#x274c; Неизвестная ошибка: {e}")

Заключение

Надеюсь статья была для вас полезной и вы теперь умеете:

✅ Конвертировать изображения в WebP/JPG/PNG
✅ Управлять качеством и сжатием
✅ Обрабатывать прозрачность и цветовые режимы
✅ Массово обрабатывать папки
✅ Измерять экономию трафика

🐍 Один запуск — и ваши изображения становятся быстрее, легче и современнее.

🔁 Если вы автоматизируете задачи на Python, посмотрите также:
python сортировка файлов — автоматическая разборка папок
python скачать изображения с сайта — массовая загрузка медиа
python бэкап файлов — резервное копирование с датой и уведомлениями
💬 Остались вопросы? Пишите в комментариях — с радостью уточню, дополню или помогу с вашим кодом.
📢 Подписывайтесь на Telegram-канал PythonAuto, чтобы не пропустить новые гайды по автоматизации, парсингу и Python.
👉 Ваш интерес — лучшая мотивация для новых статей!

Оставьте комментарий