SVG в PNG с Sharp: размер, плотность и четкость
Рендерите SVG в прозрачный PNG конечного пиксельного размера с Sharp. Посмотрите воспроизводимый тест 1x и 2x, когда важна входная плотность и почему увеличение PNG не помогает.
На этой странице
В современном процессе Sharp начинайте каждый экспорт с SVG и вызывайте resize() с действительно нужной шириной в пикселях. Если нужен ресурс 2x, запросите вдвое больше выходных пикселей. Не создавайте сначала маленький PNG для последующего увеличения. Также не копируйте старое исправление density в каждый процесс: наш тест Sharp 0.34.4 дал одинаковые пиксели с повышенной входной плотностью и без нее.
Краткий ответ
- Сохраняйте оригинальный SVG как основной файл.
- Рендерите каждый размер PNG непосредственно из этого SVG через Sharp.
- Проверьте выходные размеры и альфа-канал, затем посмотрите файл в предполагаемом размере отображения.
- Измените SVG или исследуйте рендерер, если результат все еще отличается от исходника. Настройка плотности не создаст детали внутри встроенного растра.
Отрендерите PNG 1x и 2x из SVG
Конструктор Sharp принимает файл или буфер SVG, а API resize задает выходные размеры. Для квадратной иконки 64 единицы, которая будет показана в размере 256 CSS-пикселей, экспортируйте PNG 256 пикселей для 1x и PNG 512 пикселей для 2x:
import sharp from "sharp";
const source = "icon.svg";
await Promise.all([
sharp(source).resize({ width: 256 }).png().toFile("icon-1x.png"),
sharp(source).resize({ width: 512 }).png().toFile("icon-2x.png"),
]);Отсутствие высоты сохраняет исходное соотношение сторон при обычном поведении resize в Sharp. Выбирайте выходную ширину под требования целевой среды; «2x» относится к пиксельным размерам относительно предполагаемого размера CSS, а не к атрибуту SVG или обещанию для любого экрана. Если иконка должна отображаться в размере 256 CSS-пикселей, сравните PNG 256 и 512 пикселей в этом размере и решите, оправдан ли вес большего файла.
Исходная тестовая иконка задавала width="64" height="64" viewBox="0 0 64 64". Мы отрендерили ее в 64, 512 и 1,024 пикселя с закрепленным в репозитории Sharp 0.34.4. Файлы размером 512 и 1,024 пикселя были созданы из SVG, имели прозрачные углы и непрозрачные закрашенные центры и показывали запрошенные размеры. Это наблюдения для данного теста и версии, а не оценка всей графики SVG.

Изображение наглядно показывает причину сбоя: как только первый результат становится PNG размером 64 пикселя, дальнейшее изменение размера интерполирует эти пиксели. Контуров для повторной отрисовки уже нет. Наши прямой и скорректированный по плотности результаты 512 пикселей имели идентичные сырые каналы RGBA в этом тесте. Исходный SVG, скрипт рендеринга и метаданные результата сохранены в исследовательских материалах статьи.
Нужен ли density в Sharp?
Параметр конструктора Sharp density управляет DPI при чтении SVG или PDF; документированное значение по умолчанию — 72. Это отличается от запроса конечной ширины в resize(). Можно встретить старые примеры Sharp, повышающие входную плотность чтобы избежать размытия при увеличении. Они описывают реальный исторический симптом: задача Sharp #1421 сообщала в 2018 году о пикселизации SVG 32 пикселя при увеличении до 512. Это не доказывает, что обходной способ все еще нужен в современной установке.
Мы проверили именно эту пару на Sharp 0.34.4:
const direct = await sharp("icon.svg")
.resize({ width: 512 })
.png()
.toBuffer();
const densityFirst = await sharp("icon.svg", { density: 576 })
.resize({ width: 512 })
.png()
.toBuffer();Для нашей векторной иконки 64 пикселя оба процесса дали одинаковые пиксели RGBA 512 × 512. Задавайте входную плотность только когда конкретный файл и установленная версия Sharp показывают необходимость, затем повторяйте сравнение после обновлений. Не считайте больший DPI универсальным переключателем четкости. Полезный первый вопрос: остается ли векторная геометрия в момент рендеринга конечного PNG через Sharp?
Если вы работаете и с PDF, проверяйте его отдельно: этот эксперимент SVG не устанавливает поведение PDF. Аналогично, withDensity() в новой документации Sharp описывает метаданные выходного DPI — это другая операция, чем входная плотность рендеринга SVG в конструкторе.
Проверьте размеры, прозрачность и содержимое исходника
Используйте API метаданных Sharp для выходного файла вместо угадывания по масштабу предпросмотра:
const oneX = await sharp("icon-1x.png").metadata();
const twoX = await sharp("icon-2x.png").metadata();
console.log({
oneX: [oneX.width, oneX.height, oneX.hasAlpha],
twoX: [twoX.width, twoX.height, twoX.hasAlpha],
});Для квадратного теста здесь ожидаемые размеры — 256 × 256 и 512 × 512. hasAlpha указывает наличие альфа-канала, но не доказывает прозрачность конкретного угла; проверьте файл или измерьте пиксели, если прозрачность важна для передачи. У нашего теста альфа угла равнялась нулю, а центра — 255 во всех проверенных файлах. Белый прямоугольник внутри SVG, наоборот, попал бы в каждый PNG независимо от формата PNG.
Если новый крупный рендеринг все еще пикселизирован, проверьте содержимое SVG. Стандарт SVG допускает элемент <image>, встраивающий или связывающий растр. Поэтому файл может иметь расширение .svg, хотя графика внутри остается PNG низкого разрешения. Наше руководство по поиску растровых изображений внутри SVG показывает проверку объектов и XML. Увеличение выходной ширины Sharp не превращает встроенные пиксели в контуры.
Также проверьте условия отображения. Файл 512 пикселей, показанный в 1,024 пикселя, может выглядеть размытым. Просмотрщик с масштабом намного выше 100% показывает сетку PNG даже при правильном экспорте. Сравните в реальном размере отображения и на нужном фоне, затем решите, передать ли больший PNG или сам SVG. Для веба встроенный SVG и SVG в элементе изображения предлагают разные способы интеграции; ни одному не нужен PNG, если цель поддерживает SVG.
Где подходит PerfectVector
Sharp растеризует SVG, а не восстанавливает редактируемые контуры из PNG. Если основной файл — только растровая иконка или логотип, создайте и проверьте SVG до этого процесса экспорта. Руководство по иконкам PNG в SVG для UI-kit описывает согласованную геометрию и проверки передачи набора. Процесс преобразования изображения в вектор PerfectVector может создать вариант SVG из растровой графики. Откройте результат, проверьте силуэт, мелкие детали и наличие настоящих контуров, затем рендерите PNG 1x и 2x из утвержденного SVG. Если чистый оригинальный SVG уже есть, сохраните его и используйте Sharp напрямую.
FAQ
Почему результат SVG в PNG через Sharp выглядит размытым? Проверьте, не создал ли процесс сначала маленький PNG, а затем увеличил его. Далее проверьте SVG на встроенный растр и сравните передаваемый PNG в реальном размере отображения. В современной версии Sharp сначала попробуйте прямой рендеринг SVG в конечный размер, прежде чем добавлять обходной способ с входной плотностью.
Нужен ли density: 576 для восьмикратного увеличения?
Для нашего тестового SVG от 64 до 512 пикселей на Sharp 0.34.4 он не понадобился: прямой resize и resize с измененной плотностью дали идентичные пиксели RGBA. Ваш SVG и установленный рендерер могут вести себя иначе, поэтому проверяйте конкретные данные, а не принимайте число за правило.
Как создать прозрачный PNG 2x? Рендерите из SVG вдвое больше предполагаемых размеров CSS и экспортируйте PNG. Подтвердите полученные ширину и высоту, затем проверьте прозрачность незакрашенной области. Прозрачный холст не удаляет фигуру фона, уже присутствующую в SVG.
Sources
- Sharp — Constructor — Поддержка входного SVG и параметр входной плотности
density. - Sharp — Resizing images — Поведение выходных размеров, использованное в примерах.
- Sharp — Input metadata — Проверки размеров и метаданных альфы.
- Sharp GitHub — SVG to PNG pixelation issue #1421 — Исторический симптом, явно отделенный от теста закрепленной современной версии.
- Sharp — Output options — Различие новых метаданных выходной плотности и входной плотности рендеринга.
- W3C — SVG 2 embedded content — Почему SVG может содержать растровые пиксели.
Если основной файл только растровый, создайте вариант SVG с PerfectVector, проверьте его контуры и используйте Sharp для рендеринга утвержденного файла в каждом нужном размере PNG.
Ещё из блога

Импорт SVG в Unity: графика для UI Toolkit или спрайтов
Выберите способ импорта SVG в Unity по версии редактора и назначению. Подготовьте контуры, обработайте неподдерживаемые эффекты и проверьте изображения UI Toolkit или спрайты в контексте.
Свои SVG-иконки Shopify: подготовка фирменного знака
Подготовьте собственную SVG-иконку для темы Shopify и выберите файл изображения или встроенный фрагмент Liquid. Проверьте контуры, управление цветом, размер и доступность.