Конвертация изображений в Python с помощью Pillow

Python известен своей универсальностью. Вы можете создать утилиты реального мира на Python, которые упрощают и автоматизируют рутинные задачи. Здесь мы соберём простой и надёжный конвертер форматов изображений на основе Pillow — как для одиночных файлов, так и для массовой обработки.
Что понадобится
- Установленный Python 3.6+.
- Библиотека Pillow (форк PIL) для работы с изображениями.
- Базовые знания командной строки и работы с файлами.
Кратко — Pillow предоставляет модуль Image и дополнительные инструменты: ImageFile, ImageFilter, ImageStat и др. Эти модули позволяют открывать, конвертировать, фильтровать и сохранять изображения в популярных форматах.
Установка Pillow
Запустите в терминале:
pip install pillowПосле установки можно переходить к работе с изображениями.
Важно: в системах с несколькими версиями Python используйте pip для нужного интерпретатора (например, pip3 или python -m pip).
Быстрая проверка: загрузка и вывод свойств изображения
Ниже — минимальный пример для загрузки и просмотра изображения и его свойств.
from PIL import Image
image = Image.open('sample-image.jpg')
image.show()
print('Filename:', image.filename)
print('Format:', image.format)
print('Mode:', image.mode)
print('Size:', image.size)
print('Width:', image.width)
print('Height:', image.height)
image.close()Этот код — базовая проверка: библиотека установлена и файл открывается. Полезно для отладки окружения.
Как Pillow понимает режимы изображения (mode)
Mode — это строка, которая описывает формат пикселя и глубину цвета. Частые режимы:
- RGB — 3×8-bit, истинные цвета.
- RGBA — 4×8-bit, истинные цвета + альфа-канал (прозрачность).
- CMYK — 4×8-bit, цветорасщепление для печати.
- L — 8-bit оттенков серого.
- P — палитровый формат (индексированные цвета).
Перед сохранением в целевой формат иногда нужно явно конвертировать режим (например, для JPG требуется RGB).
Простой пример: PNG → JPG (и обратное)
Преобразование PNG в JPG (теряется прозрачность):
from PIL import Image
image = Image.open('sample-png-image.png')
image = image.convert('RGB') # JPG не поддерживает альфа-канал
image.save('converted-jpg-image.jpg')
print('Image successfully converted!')Примечание: при конвертации в JPG все прозрачные пиксели станут чёрными или белыми в зависимости от фонового слоя. Чтобы задать фон вручную, можно создать фон и поместить поверх него исходное изображение:
from PIL import Image
orig = Image.open('with-alpha.png').convert('RGBA')
background = Image.new('RGB', orig.size, (255, 255, 255)) # белый фон
background.paste(orig, mask=orig.split()[3]) # используем альфу как маску
background.save('flattened.jpg', 'JPEG')Конвертация JPG → PNG (прозрачность сохраняется, если исходно есть альфа):
from PIL import Image
image = Image.open('sample-jpg-image.jpg')
image.save('converted-png-image.png')
print('Image successfully converted!')PNG поддерживает альфу, поэтому прозрачность сохраняется, если она есть в исходнике.
Конвертация в любой поддерживаемый формат
Pillow определяет формат по расширению в имени файла, когда вы вызываете save(). Примеры:
from PIL import Image
image = Image.open('sample-transparent-png-image.png')
image.save('converted-webp-image.webp')
print('Image successfully converted!')Поддерживаемые форматы зависят от сборки Pillow и доступных библиотек (JPEG, PNG, WebP, GIF, BMP, TIFF и т.д.). Если формат недоступен — Pillow бросит исключение.
Обработка ошибок: отсутствующие файлы и недопустимые форматы
Обрабатывайте FileNotFoundError и OSError (чаще всего для проблем с форматом):
from PIL import Image
try:
image = Image.open('wrong-filename.jpg')
image.save('converted-png-image.png')
print('Image successfully converted!')
except FileNotFoundError:
print("Не удалось найти указанный файл")
except OSError as e:
print('Ошибка при работе с изображением:', e)Пакетная обработка: конвертация всех файлов в каталоге
Простой сценарий для конвертации всех JPG в текущем каталоге в PNG:
from PIL import Image
import glob
for file in glob.glob('*.jpg'):
image = Image.open(file)
image.save(file.rsplit('.', 1)[0] + '.png')Рекурсивная обработка всех подкаталогов (с сохранением структуры) — пример с os.walk():
import os
from PIL import Image
src_root = 'input_folder'
dst_root = 'output_folder'
for dirpath, dirnames, filenames in os.walk(src_root):
rel = os.path.relpath(dirpath, src_root)
out_dir = os.path.join(dst_root, rel)
os.makedirs(out_dir, exist_ok=True)
for filename in filenames:
if filename.lower().endswith(('.png', '.jpg', '.jpeg', '.webp')):
src_path = os.path.join(dirpath, filename)
dst_path = os.path.join(out_dir, os.path.splitext(filename)[0] + '.webp')
try:
img = Image.open(src_path)
img.save(dst_path)
except Exception as e:
print('Ошибка при обработке', src_path, e)Советы по прозрачности и анимации
- Прозрачность: сохранение альфа-канала возможно в форматах PNG и WebP (при поддержке альфа). JPG не поддерживает альфа.
- Анимация: GIF и некоторые WebP могут содержать несколько кадров. Image.open() откроет первый кадр по умолчанию. Для работы с анимированными изображениями используйте методы seek/iterate и сохраняйте с параметром save_all=True.
Пример извлечения и сохранения всех кадров GIF в отдельные PNG:
from PIL import Image, ImageSequence
im = Image.open('animated.gif')
for i, frame in enumerate(ImageSequence.Iterator(im)):
frame.save(f'frame_{i:03d}.png')Альтернативы и когда Pillow не подходит
- ImageMagick / GraphicsMagick — мощны для конвейерной и массовой обработки с высокой производительностью; подходят для CLI и серверных задач.
- OpenCV — нужен, если требуется компьютерное зрение и сложные фильтры.
- Wand (Python-обёртка вокруг ImageMagick) — удобна, если вам нужен функционал ImageMagick в Python.
Выбор зависит от требований: если важна простота и поддержка форматов — Pillow отлично подходит. Если нужна скорость при обработке тысяч изображений или особенные конверсии — стоит рассмотреть ImageMagick.
Практический чек-лист перед запуском массовой конверсии
Для разработчика:
- Проверить наличие резервной копии исходных файлов.
- Убедиться, что целевой формат поддерживает нужные свойства (альфа, метаданные).
- Тестировать на небольшом наборе файлов.
Для QA:
- Проверить визуальное соответствие после конвертации (цвета, прозрачность).
- Проверить метаданные (EXIF) при необходимости.
Для операций/DevOps:
- Оценить нагрузку и время выполнения на объёме данных.
- Убедиться в наличии прав доступа к папкам ввода/вывода.
SOP: пошаговая инструкция для массовой конверсии
- Создать резервную копию исходной директории.
- Прогнать скрипт на 10-20 файлах и вручную проверить результат.
- Запустить рекурсивный скрипт с логированием ошибок.
- Проверить размер итоговой директории и выборочно открыть файлы.
- Удалить временные файлы и опционально удалить старые форматы (после проверки).
Пример простого GUI на Tkinter для конвертации одного файла
import tkinter as tk
from tkinter import filedialog, messagebox
from PIL import Image
def choose_and_convert():
path = filedialog.askopenfilename(filetypes=[('Images', '*.png;*.jpg;*.jpeg;*.webp;*.gif')])
if not path:
return
out = filedialog.asksaveasfilename(defaultextension='.png')
if not out:
return
try:
img = Image.open(path)
if out.lower().endswith('.jpg'):
img = img.convert('RGB')
img.save(out)
messagebox.showinfo('OK', 'Готово')
except Exception as e:
messagebox.showerror('Ошибка', str(e))
root = tk.Tk()
btn = tk.Button(root, text='Выбрать файл и конвертировать', command=choose_and_convert)
btn.pack(padx=20, pady=20)
root.mainloop()Тестовые сценарии и критерии приёмки
- Конвертация PNG с альфой в PNG — альфа сохраняется.
- Конвертация PNG с альфой в JPG — итоговое изображение не содержит альфа и фон корректен.
- Конвертация анимированного GIF в WebP с поддержкой анимации — сохраняется несколько кадров (если поддерживается).
- Массовая конверсия 100 файлов — скрипт завершился без необработанных ошибок.
Критерии приёмки: все тесты проходят, визуальная проверка образцов успешна, лог ошибок пуст или содержит только ожидаемые предупреждения.
Ментальные модели и heuristics
- «Расширение определяет формат при сохранении»: Pillow использует расширение выходного файла, поэтому следите за именем.
- «Альфа — прежде всего»: если целевой формат не поддерживает альфу, сначала запланируйте поведение (заливка, белый фон, сохранение как PNG).
- «Анимация — отдельный кейс»: по умолчанию библиотека работает с первым кадром.
Безопасность и приватность
- EXIF и другие метаданные могут содержать личную информацию (геолокацию, модель устройства). Если это важно — очищайте метаданные перед публикацией:
from PIL import Image
img = Image.open('with-exif.jpg')
data = list(img.getdata())
clean = Image.new(img.mode, img.size)
clean.putdata(data)
clean.save('no-exif.jpg')- При работе с пользовательскими файлами всегда проверяйте вход (не доверяйте расширению, проверяйте структуру файла) и обрабатывайте исключения.
Совместимость и миграция
- Pillow использует внешние библиотеки для поддержки некоторых форматов (например, libjpeg, libwebp). Если формат не поддерживается — проверьте сборку Pillow.
- На серверах соберите Pillow с необходимыми зависимостями или используйте системные пакеты.
Заключение
Pillow — практичный и лёгкий инструмент для большинства задач по конвертации изображений. Он прост в использовании для одиночных операций и достаточно гибок для написания массовых конвертеров. Важно учитывать особенности форматов: прозрачность, анимацию и метаданные. Для высокопроизводительных конвейеров стоит рассмотреть ImageMagick или нативные решения на C/C++.
Кратко:
- Проверяйте режимы (mode) перед сохранением.
- Для JPG используйте convert(‘RGB’) и предусмотрите фон.
- Для анимации используйте ImageSequence и save_all=True.
- Тестируйте на выборке перед массовым запуском.
Если нужно, могу предоставить готовый репозиторий со скриптами: одиночная конвертация, рекурсивная обработка, GUI-утилита и Dockerfile для развёртывания на сервере.
Похожие материалы
Страница пожертвований PayPal: как создать и оптимизировать
Интеграция PayPal в React — шаг за шагом
Автозамена паролей: Dashlane vs LastPass
Экранная клавиатура Windows 10 — включение и отключение
Местоположение на iPhone: настройки и безопасность