coru

Создание полезных сайтов

Чёрный или белый фон после перевода PNG в JPEG: как выбрать цвет

Если нужен JPEG, выберите фон до экспорта и сохраните прозрачный оригинал. Чёрный или белый прямоугольник может быть подложкой просмотра, скрытыми цветами или уже записанными в изображение пикселями.

Одинаковый зелёный круг с полупрозрачным краем на шахматной подложке, белом и тёмном фоне. При смешивании с каждым сплошным фоном цвет края меняется.
Шахматная подложка обозначает прозрачность. Один и тот же полупрозрачный край по-разному смешивается с белым и тёмным фоном. Числа показывают наш пример до сжатия JPEG; измеренные значения разобраны ниже. Иллюстрация: Coru. Оригинальная иллюстрация Coru.

Сначала решите: нужна прозрачность или постоянный фон

Обычный JPEG (.jpg или .jpeg) не сохраняет прозрачный фон. Если для загрузки нужен именно JPEG, выберите сплошной цвет фона и объедините изображение с этим фоном перед экспортом. Если нужна прозрачность, используйте поддерживающий её формат, например PNG, и проверьте, что площадка его принимает. Простая замена расширения не преобразует файл.

Белый подходит для белой страницы, но не для любой картинки: белый логотип на нём может исчезнуть. JPEG, экспортированный на белом, сохранит белый прямоугольник и на тёмной странице.

  • Нужен один и тот же объект на разных фонах? Сохраните прозрачный оригинал и выберите формат с поддержкой прозрачности.
  • Нужен JPEG для конкретного оформления? Явно задайте фон, в том числе под полупрозрачными краями.
  • Чёрный или белый прямоугольник есть уже в исходнике? Сначала выясните, настоящие ли это пиксели или только фон программы просмотра.

Проверьте исходник до следующего преобразования

Откройте оригинальный PNG в редакторе, который показывает прозрачность. Временно поместите под изображением слой яркого цвета. Если он виден сквозь предположительно пустую область, в ней есть прозрачность. Если непрозрачный чёрный или белый прямоугольник остаётся на месте, в этой проверке он является частью видимого изображения. Шахматная подложка на скриншоте тоже может быть записана в пиксели; сама по себе её видимость не доказывает прозрачность.

Проверяйте файл, который собираетесь загрузить, а не только миниатюру. Некоторые программы показывают прозрачные области на чёрной или белой подложке. Если проблема появляется лишь после загрузки, сравните отдаваемую площадкой картинку с локальным экспортом: площадка могла создать другую версию.

В графическом редакторе: поместите выбранный цвет снизу

Работайте с копией и сохраните прозрачный оригинал или файл со слоями. Ниже названы операции, а не одинаковые для всех программ пункты меню. Это практический порядок проверки в редакторе; измеряемый эксперимент далее выполнен в Pillow.

  • Создайте слой сплошного цвета на всю площадь холста, выбрав нужный фон.
  • Поместите его под всеми видимыми частями изображения. Исходный рисунок с прозрачностью должен остаться выше.
  • Проверьте результат, особенно светлый текст, мягкие тени и сглаженные края. Убедитесь, что объект различим на этом фоне.
  • Экспортируйте новый JPEG. Если вместо слоёв редактор предлагает настройку фона или matte, задайте тот же цвет и проверьте предпросмотр.
  • Повторно откройте JPEG и посмотрите на него в размере будущего использования. Отдельно сохраните редактируемый исходник, чтобы позже выбрать другой фон.

Почему удалить альфа-канал — не значит выбрать фон

У прозрачного пикселя могут сохраняться значения красного, зелёного и синего. Альфа задаёт его непрозрачность. Если убрать альфа-канал без наложения на фон, эти скрытые цвета могут стать видимыми; они не обязаны быть чёрными. Программы также ведут себя по-разному: выбирают фон, отбрасывают альфа-канал или отказываются от преобразования.

В нашем тесте Pillow пиксели RGBA (16, 185, 129, 0) и (0, 0, 0, 0) были полностью прозрачными. Прямой вызов convert("RGB") сделал их соответственно бирюзовым и чёрным. Эта операция не означала «положить картинку на белый фон».

Прозрачность PNG не всегда представлена отдельным каналом A при открытии файла. Индексированный PNG может хранить палитру и данные прозрачности. Пример ниже сначала переводит изображение в RGBA, поэтому его шаг наложения работает и с проверенной палитровой прозрачностью.

Измеренный пример: один полупрозрачный цвет на двух фонах

Coru создал собственные тестовые PNG с полностью прозрачными, полупрозрачными и непрозрачными полосами. У полупрозрачной полосы RGB равнялся (16, 185, 129), а альфа — 128 из 255: приблизительно 50% непрозрачности. В Pillow 13.0.0 до кодирования JPEG результат был (135, 220, 192) на белом и (16, 114, 98) на тёмно-синем #102A43.

Это измеренный результат смешивания сохранённых 8-битных значений каналов в данном примере, а не прогноз для любого редактора с управлением цветом. Непрозрачная полоса до кодирования сохранила RGB; полностью прозрачные полосы приняли выбранный цвет фона.

JPEG сжимает с потерями. После сохранения кодом ниже и повторного открытия центр полупрозрачной полосы дал (135, 220, 191) на белом и (16, 114, 99) на тёмно-синем. Разница в единицу показывает, почему точные значения до кодирования нельзя выдавать за точные пиксели JPEG. Эквивалентные тестовые файлы RGBA и с индексированной палитрой дали одинаковые JPEG-файлы.

По желанию: повторите преобразование локально в Python

Для примера в терминале используйте новую рабочую папку в Linux или macOS с установленным Python 3.11 или новее. Создайте отдельное окружение и установите проверенную версию Pillow. Установка скачивает программу; само преобразование читает локальные файлы и не загружает изображения на сервер. Сохраните следующий блок Python как flatten_png.py, а рабочую копию исходника положите рядом под именем input.png.

Пример предназначен для PNG из одного кадра, не более 20 миллионов пикселей, с разрядностью компонентов не выше 8 бит. Он отклоняет 16-битный PNG, несколько кадров и уже существующий выходной файл. Используйте исходник с правильной ориентацией и нужной интерпретацией значений RGB; это не процедура преобразования цветового пространства или сохранения метаданных.

Подготовьте проверенное окружение Python

bash

python3 -m venv .venv
.venv/bin/python -m pip install "Pillow==13.0.0"

Выполните команды в новой рабочей папке. Пример проверен с Python 3.12.3 и Pillow 13.0.0 в Linux.

Сохраните как flatten_png.py

python

import argparse
from pathlib import Path
from PIL import Image, ImageColor

parser = argparse.ArgumentParser()
parser.add_argument("source", type=Path)
parser.add_argument("output", type=Path)
parser.add_argument("background", help='Solid RGB color, e.g. "#FFFFFF"')
args = parser.parse_args()
background = ImageColor.getrgb(args.background)
if len(background) != 3:
    parser.error("Choose a solid RGB background, without alpha.")

with args.source.open("rb") as stream:
    header = stream.read(29)
    if header[:8] != b"\x89PNG\r\n\x1a\n" or len(header) < 29:
        parser.error("Input must be a PNG file.")
    if header[24] == 16:
        parser.error("This example does not process 16-bit PNGs.")
    stream.seek(0)
    with Image.open(stream) as source:
        if source.format != "PNG" or getattr(source, "n_frames", 1) != 1:
            parser.error("Use a single-frame PNG.")
        if source.width * source.height > 20_000_000:
            parser.error("This example is limited to 20 million pixels.")
        if source.mode not in {"1", "L", "LA", "P", "RGB", "RGBA"}:
            parser.error("Unsupported PNG mode for this example.")
        rgba = source.convert("RGBA")

matte = Image.new("RGBA", rgba.size, (*background, 255))
flat = Image.alpha_composite(matte, rgba).convert("RGB")
with args.output.open("xb") as output:
    flat.save(output, format="JPEG", quality=92, subsampling=0)
print(f"Saved {args.output}: {flat.width} x {flat.height}, opaque RGB")

Фон непрозрачный. Наложение с учётом альфа-канала выполняется до перевода в RGB и кодирования JPEG. Режим xb не позволяет заменить уже существующий файл.

Создайте отдельные JPEG на белом и тёмном фоне

bash

.venv/bin/python flatten_png.py input.png white.jpg "#FFFFFF"
.venv/bin/python flatten_png.py input.png dark.jpg "#102A43"

Кавычки сохраняют цвет с символом # при передаче через командную оболочку. Каждый запуск читает input.png; при повторном запуске выбирайте новые имена результатов.

Что делает скрипт и что ещё нужно проверить

Исходник читается без изменений. convert("RGBA") подготавливает изображение переднего плана; Image.new создаёт сплошной фон того же размера; alpha_composite накладывает изображение на него. Только полученный непрозрачный результат переводится в RGB и сохраняется. Скрипт не меняет размер и не обрезает картинку.

В примере заданы quality=92 и subsampling=0. Это параметры нашего теста, а не обещание конкретного размера файла или идеальных краёв. Проверьте повторно открытый JPEG: текст и штриховая графика всё ещё могут получить артефакты сжатия. При ошибке сохранения может остаться неполный новый файл. Перед повторной попыткой удалите именно этот неудачный результат или выберите другое имя.

Скрипт не копирует и не интерпретирует ICC-профили, EXIF-ориентацию и прочие метаданные. Он не выполняет ICC-преобразование цвета или смешивание в линейном свете. Для точной цветопередачи, ориентации снимков, HDR, анимации или обязательного сохранения метаданных используйте подходящий редактор либо процесс экспорта и отдельно проверьте эти свойства. Не считайте пример универсальным конвертером.

Повторное сохранение JPEG в PNG не вернёт прозрачность

Когда фон уже объединён с пикселями, а альфа-канал отброшен, новое сохранение в PNG не определит, какие пиксели были прозрачными. Белый пиксель мог относиться к самому объекту, к фону или к их смеси на краю.

Чтобы выбрать другой фон, вернитесь к прозрачному оригиналу или файлу со слоями. Если его больше нет, для удаления фона потребуется новое выделение или маска; простое удаление всех белых либо чёрных пикселей может повредить объект и его мягкие края.

Перед загрузкой результата

  • Оригинал сохранён: можно ли сделать новый экспорт, не редактируя предыдущий JPEG?
  • Фон выбран осознанно: подходит ли он месту использования и различим ли на нём объект?
  • Края проверены: посмотрите на волосы, тени, тонкие линии и мелкие надписи в будущем размере показа.
  • Сохранённый файл открыт заново: проверьте формат, размеры и вид после сжатия.
  • Место публикации проверено: посмотрите и на загруженный результат, включая тёмную тему, если она имеет значение.

Как мы проверили пример

21 октября 2026 года мы запустили опубликованный конвертер в Linux с Python 3.12.3 и Pillow 13.0.0, отключив сеть на время эксперимента. 38 проверок охватили RGBA, значения альфа для палитры, прозрачный индекс палитры, RGB с прозрачным цветовым ключом и без него, оттенки серого с альфа-каналом, размеры результатов, декодирование JPEG, отказ для неподходящих входных файлов и неизменность хешей исходников.

Файлы были синтетическими. Мы измеряли значения каналов и поведение файловых операций, а не качество фотографий, работу графических редакторов, читательский спрос или поведение на любых файлах. Практический результат — экспорт, у которого фон и края подходят для места, где картинку увидят читатели.

Источники и материалы

Помогите улучшить руководство

← Все заметки