05 февр. 2025 г.·7 мин чтения

Библиотеки Go для обработки изображений: изменение размера, обрезка и конвертация

Библиотеки обработки изображений на Go помогают экономить время, когда вы работаете с загрузками, фотографиями товаров и отсканированными файлами. В этом руководстве сравниваются практичные варианты пакетов.

Библиотеки Go для обработки изображений: изменение размера, обрезка и конвертация

Почему этот выбор важен

Выбранный вами пакет для изображений влияет не только на качество картинки. Он меняет надёжность загрузок, скорость страниц, расходы на хранение и то, насколько сильно загружаются ваши серверы. В Go image processing libraries небольшие различия в использовании памяти или качестве результата быстро превращаются в реальные проблемы продукта, когда люди начинают загружать файлы весь день.

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

Качество изменения размера не менее важно. Некоторые пакеты работают быстро, но из-за них тонкие линии, текст и чёткие края выглядят мягко. Для аватарки это ещё может подойти. Но для фотографий товаров с подписями, скриншотов с мелким текстом или отсканированных чеков, которые потом должны пройти OCR, это уже плохой результат. Один неудачный ресайз может заставить чистое исходное изображение выглядеть дёшево.

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

Для разных сценариев нужно разное поведение. Аватары обычно требуют квадратной обрезки, быстрого изменения размера и умеренного сжатия. Для медиа товаров важны стабильные размеры и хорошее визуальное качество во многих миниатюрах. Для документов важнее чёткость текста, края страницы, ориентация и предсказуемый результат, чем детали фотографии.

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

Что должен уметь хороший пакет

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

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

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

Обрезка тоже должна быть предсказуемой. Если вы просите квадратную миниатюру, вы хотите один и тот же результат для одного и того же исходника. Обрезка по центру часто достаточна для медиа товаров. С пользовательскими загрузками сложнее, потому что лица или объект могут находиться не по центру. Даже если вы начинаете с простых правил, пакет должен позволять применять их без странных сдвигов и неожиданных ошибок на пиксель.

Поддержка форматов — ещё одна базовая проверка. JPEG обычно подходит для фотографий, где важен размер файла. PNG лучше для логотипов, UI-элементов и изображений с прозрачностью. WebP — сильный вариант для более компактных веб-изображений, если ваш стек его поддерживает. Иногда лучший выбор — оставить исходный формат, если конвертация ничего не даёт.

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

Простой тест скажет о многом. Прогоните десять больших загрузок через свой конвейер, измените размер до нескольких распространённых вариантов, обрежьте одну миниатюру и сохраните выходы в JPEG, PNG и WebP. Если пакет остаётся быстрым, сохраняет картинку чистой и не взрывает память, скорее всего, он вам подходит.

Пакеты, которые стоит проверить в первую очередь

Для многих команд стандартной библиотеки вместе с x/image/draw уже достаточно. Вы получаете небольшой стек, понятный код и не ставите дополнительных системных пакетов. Это хорошо работает для пользовательских загрузок, если вам нужно только декодировать JPEG или PNG, изменить размер, обрезать с небольшой собственной логикой и сохранить новые версии.

Такой подход также делает конвертацию форматов проще и понятнее. Если поток загрузки превращает большие фотографии в JPEG для веба и маленькую миниатюру, стандартная библиотека оставляет меньше движущихся частей. Это хороший первый выбор, когда задача простая и команде нужен код, который любой разработчик на Go быстро прочитает.

imaging — удобный следующий шаг. В нём есть понятные помощники для изменения размера, обрезки, fit, fill, поворота и создания миниатюр, поэтому вам нужно меньше служебного кода. Это особенно полезно для медиа товаров, где магазинам часто нужны квадратные миниатюры, фиксированные пропорции и ровные изображения каталога.

Если вы обрабатываете много больших файлов каждый день, протестируйте bimg. Он использует libvips, а это обычно означает меньшее потребление памяти и гораздо более высокую скорость, чем у чисто Go-вариантов. Это делает его сильным выбором для загруженных сервисов загрузки, массовых задач с медиа и конвейеров документов, которые создают предпросмотр из больших исходных изображений.

Обратная сторона — настройка. bimg требует libvips на ваших машинах и в процессе развёртывания, поэтому локальная разработка и контейнеры требуют больше внимания. Но если работа с изображениями уже съедает CPU или RAM, эта дополнительная настройка часто окупается.

govips находится в той же группе по производительности, но даёт больше прямого контроля над libvips. Если bimg кажется вам немного слишком предзаданным для вашего потока, govips оставляет больше пространства для настройки шагов обработки, работы с метаданными и деталей вывода.

bild стоит попробовать, когда изменение размера и обрезка — это только часть задачи. В нём есть больше преобразований и эффектов, что помогает при обработке сканов, подготовке социальных график или добавлении лёгкого редактирования в приложение. Для тяжёлого сервиса миниатюр это не мой первый выбор, но он полезен, когда работа выходит за рамки базовых миниатюр.

Эти пять вариантов покрывают большинство реальных сценариев. Небольшие и простые задачи обычно хорошо работают со стандартной библиотекой или imaging. Высоконагруженные системы обычно подталкивают к bimg или govips.

Какой пакет подходит под каждый сценарий

Правильный выбор больше зависит от нагрузки, чем от списка функций. Загрузка аватара, каталог товаров и пакет отсканированных счетов по-разному нагружают систему.

Для пользовательских загрузок стандартной библиотеки и imaging часто достаточно. Если люди загружают по одному изображению и вам нужны только изменение размера, обрезка, поворот и вывод в JPEG или PNG, простая реализация обычно выигрывает. Её легче читать, легче тестировать и проще запускать, когда не нужны дополнительные нативные зависимости.

Медиа товаров — это другая задача. Магазины часто создают миниатюры, изображения для списка, увеличенные версии и мобильные размеры из одного исходника. Здесь обычно лучше подходят bimg или govips. Оба используют libvips, поэтому обычно лучше справляются с большими пакетами и расходуют меньше памяти, чем многие чисто Go-пути. Если ваша система импортирует сразу весь каталог, эта разница быстро становится заметной.

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

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

Старые пакеты всё ещё встречаются в долгоживущих Go-сервисах. Это не всегда ошибка, но перед новым использованием обязательно проверьте их. Посмотрите на ориентацию EXIF, обработку цвета, поведение на больших файлах и скорость пакетной обработки. Код, который выглядит нормально на десяти изображениях, может очень плохо справляться на десяти тысячах.

Как выбирать шаг за шагом

Сделайте изображения товаров лучше
Настройте стабильные правила для миниатюр, hero-изображений, обрезки и форматов вывода.

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

Сначала запишите три вещи: входные форматы, целевые размеры и выходные форматы. Будьте конкретны. «Пользовательские загрузки» — это слишком широко. «JPEG и HEIC на входе, максимум 1600px по ширине, WebP и JPEG на выходе» уже даёт основу, которую можно тестировать.

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

Короткий чек-лист помогает. Перечислите все форматы, которые нужно принимать сейчас, плюс один-два, которые могут понадобиться скоро. Для каждого сценария задайте точные правила вывода, например для миниатюр, изображений товаров или предпросмотра документов. Заранее решите, хочет ли команда поддерживать зависимость от libvips. Потом прогоните одни и те же файлы через каждый пакет и зафиксируйте скорость, расход памяти и качество результата.

Решение по libvips важно принять рано. Некоторым командам нужен чисто Go-стек, чтобы развёртывание оставалось простым. Другим важнее меньший расход памяти и более быстрая обработка под нагрузкой, поэтому дополнительная нативная зависимость того стоит. Ни один вариант не неправильный. Всё зависит от того, кто будет это поддерживать и где это будет работать.

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

Не пропускайте проверку метаданных. Поворот EXIF может заставить портретное фото выглядеть боком. Плохая обработка цветового профиля может сдвинуть цвета на фото товаров настолько, что это раздражает команду мерчандайзинга. Необычные размеры могут сломать правило обрезки, которое хорошо работало на обычных случаях.

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

Простой поток загрузки для магазина

Типичный сценарий для магазина выглядит просто: покупатель делает одно большое фото товара на телефон и загружает его через форму. Файл часто приходит больше ожидаемого, немного смещённым и в формате, который замедляет страницы каталога больше, чем нужно.

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

Затем создавайте версии для отображения, которые вам реально нужны: например, hero-изображение для страницы товара, изображение для сетки на странице подборок и поиска, а также маленькую миниатюру для корзины, списка заказов и административных экранов.

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

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

Большинство Go image processing libraries умеют изменять размер, обрезать и конвертировать форматы. Экономит время не сам пакет, а весь процесс вокруг него. Сначала проверяйте загрузку, потом сохраняйте оригинал, затем создавайте размеры и только после этого записывайте итоговые метаданные.

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

Ошибки, из-за которых обработка изображений тормозит

Выберите подходящий пакет
Сравните stdlib, imaging, bimg и govips на ваших реальных файлах загрузки.

Многие конвейеры изображений начинают работать медленно потому, что делают шаги не в том порядке. Классический случай — фотографии с телефона. Если вы обрезаете до исправления EXIF-поворота, после поворота кадр может оказаться не на том участке, и файл придётся декодировать и обрабатывать заново. Сначала исправляйте ориентацию, потом обрезайте и только потом меняйте размер.

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

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

Имена файлов часто врут. Файл с названием «receipt.jpg» может оказаться PDF, сломанным WebP или чем-то вредоносным. Если код доверяет расширению, конвейер может упасть на полпути, уже потратив CPU и память на работу. Проверяйте заголовок файла и дайте декодеру самому определить формат, прежде чем решать, как его обрабатывать.

Проблемы с памятью обычно проявляются под параллельной нагрузкой, а не во время одной аккуратной тестовой загрузки. Одно изображение на 12 мегапикселей может пройти без проблем. Двадцать таких одновременно могут загнать Go-сервис в тяжёлый сбор мусора, своп или падение. Хорошие пакеты помогают, но они не спасут конвейер, который декодирует слишком много больших изображений одновременно.

Несколько ограничений снимают большую часть этой боли. Ограничивайте размеры в пикселях до полной обработки. Лимитируйте число воркеров, одновременно декодирующих изображения. Следите за памятью во время всплесков загрузок, а не только на одиночных запросах. Если вы запускаете конвейер документов, проверяйте и сканы, потому что они часто приходят с огромными размерами и быстро съедают RAM.

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

Быстрые проверки перед релизом

Спланируйте переход на libvips
Решите, стоит ли вашей команде переходить на нативные инструменты для работы с изображениями.

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

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

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

Размер файла нужно проверять здраво, а не по идеальному баллу. Если JPEG quality 85 выглядит для ваших фото товаров так же, как 92, оставляйте более компактный файл. Для изображений документов маленький файл — это не выигрыш, если после сжатия текст становится мутным.

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

Логи важнее, чем кажется. Сохраняйте исходный формат, исходные размеры, выходные размеры, итоговый размер файла, время обработки и сообщение об ошибке. Когда кто-то говорит «эта загрузка выглядит странно», эти поля обычно за минуту-две объясняют почему.

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

Что делать дальше

После тестирования нескольких Go image processing libraries выберите один реальный сценарий и запустите его в работу. Аватары — хороший старт. Миниатюры товаров тоже подойдут. Оба варианта быстро показывают проблемы, которые важны в первую очередь: необычные размеры исходников, плохие загрузки, медленные преобразования и файлы, которые намного больше, чем должны быть.

Сделайте первую версию узкой. Если один путь загрузки хорошо работает от начала до конца, дальше становится проще, потому что команда уже знает правила изменения размера, выходные размеры, форматы и сценарии ошибок.

Лучше всего работает простой подход. Выберите один конвейер и задайте точные выходы, например квадратный аватар в двух размерах или изображения товаров в веб- и миниатюрной версиях. Измерьте время ответа, прежде чем добавлять новый код. Если загрузки заставляют пользователей ждать слишком долго, перенесите тяжёлую обработку изображений в очередь и возвращайте ответ раньше. Храните все правила для изображений в одном месте, чтобы соотношение обрезки, настройки качества и конвертация форматов оставались одинаковыми в обработчиках и воркерах. По мере роста объёма следите за хранилищем, CPU и временем в очереди каждую неделю. Системы обработки изображений дорожают маленькими шагами, а не сразу.

Это также помогает команде работать единообразно. Когда у всех одна и та же логика обрезки и правила именования, вы избегаете тихих багов вроде того, что один сервис сохраняет PNG, а другой WebP, или один endpoint обрезает по центру, а другой — сверху.

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

Если вашей команде нужна помощь с выбором пакетов или проектированием лёгкого медиа-пайплайна на Go, Oleg Sotnikov на oleg.is предлагает услуги Fractional CTO и консультации для стартапов. Его опыт охватывает разработку ПО, архитектуру продукта и производственную инфраструктуру, что полезно, когда нужен практичный конвейер загрузки, который остаётся быстрым и не превращается в дорогой проект по сопровождению.

Начните с одного потока загрузки на этой неделе, запишите правила и проверьте его под реальным трафиком.

Часто задаваемые вопросы

Какой пакет Go для изображений стоит попробовать первым?

Начните с вашего реального сценария. Если вы обрабатываете простые загрузки JPEG и PNG и вам нужны базовые изменение размера и обрезка, стандартная библиотека вместе с x/image/draw часто справляется. Если хотите более удобные помощники и меньше служебного кода, попробуйте imaging. Если вы обрабатываете много больших файлов или пакетные задачи, протестируйте bimg или govips, потому что libvips обычно расходует меньше памяти и работает быстрее.

Стоит ли сохранять загруженные файлы в JPEG, PNG или WebP?

Для большинства фотографий используйте JPEG, потому что он помогает держать размер файла ниже. Оставляйте PNG для прозрачности, логотипов, скриншотов и изображений с чётким текстом, когда сжатие мешает читаемости. WebP хорошо подходит для доставки в вебе, если ваш стек его поддерживает. Оставляйте исходный формат, если конвертация не даёт реальной пользы.

Когда `libvips` оправдывает дополнительную настройку?

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

В каком порядке должны выполняться шаги обработки изображений?

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

Как не дать большим загрузкам съесть всю RAM?

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

Стоит ли сохранять оригинальное загруженное изображение?

Да, в большинстве случаев. Оригинал позволяет заново собрать миниатюры, изменить правила обрезки, поменять формат вывода и восстановиться после сбоя при изменении размера, не прося пользователя загружать файл снова. Сохраняйте вместе с ним и базовые метаданные, чтобы команда видела, что именно пришло.

Как лучше всего обрезать квадратные миниатюры товаров?

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

Нужен ли для конвейеров документов другой пакет, чем для загрузки фотографий?

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

Как понять, достаточно ли хорошее качество у изменения размера?

Проверьте реальные файлы рядом друг с другом. Возьмите портретную фотографию, большое изображение с телефона, логотип, скриншот и отсканированный документ. Смотрите на размытость мелкого текста, ореолы по краям, неправильный поворот, странные цвета, медленную обработку и слишком большой размер файлов после конвертации.

Что нужно логировать в конвейере изображений?

Логируйте исходный формат, исходные размеры, итоговые размеры, финальный размер файла, время обработки и любую ошибку. Эти поля сильно упрощают поиск проблем с изображениями. Они также показывают, где начинают расти расходы на хранилище, CPU или очередь.