PerfectVector
Oleh Irene Kim7 menit baca

SVG ke PNG Sharp: Ukuran, Density, dan Ekspor Tajam

Render SVG menjadi PNG transparan pada ukuran piksel akhir dengan Sharp. Lihat pengujian 1x dan 2x yang dapat direproduksi, kapan density masukan penting, dan mengapa memperbesar PNG gagal.

Di halaman ini

Untuk pipeline Sharp saat ini, mulai dari SVG pada setiap ekspor dan panggil resize() dengan lebar piksel yang benar-benar diperlukan. Jika Anda membutuhkan aset 2x, minta dua kali jumlah piksel keluaran. Jangan membuat PNG kecil terlebih dahulu lalu memperbesar file itu. Jangan pula menyalin perbaikan density lama ke setiap pipeline: pengujian Sharp 0.34.4 kami merender piksel yang sama dengan maupun tanpa density masukan lebih tinggi.

Jawaban singkat
  1. Simpan SVG asli sebagai master.
  2. Render setiap ukuran PNG langsung dari SVG itu dengan Sharp.
  3. Periksa dimensi keluaran dan kanal alfa, lalu lihat file pada ukuran tampilan yang dimaksud.
  4. Ubah SVG atau selidiki renderer jika hasil masih berbeda dari sumber. Pengaturan density tidak dapat menciptakan detail dalam bitmap tertanam.

Render PNG 1x dan 2x dari SVG

Konstruktor Sharp menerima file atau buffer SVG, dan API resize-nya menetapkan dimensi keluaran. Untuk ikon persegi 64 satuan yang akan muncul pada 256 piksel CSS, ekspor PNG 256 piksel untuk penggunaan 1x dan PNG 512 piksel untuk kasus 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"),
]);

Tidak menyertakan tinggi mempertahankan rasio aspek sumber dalam perilaku resize Sharp yang biasa. Pilih lebar keluaran sebenarnya untuk tujuan Anda; “2x” mengacu pada dimensi piksel relatif terhadap ukuran tampilan CSS yang dimaksud, bukan atribut SVG atau janji tentang setiap layar. Jika Anda ingin melihat ikon pada 256 piksel CSS, bandingkan PNG 256 dan 512 piksel pada ukuran tampilan itu dan tentukan apakah file lebih besar sepadan dengan ukurannya.

Ikon pengujian asli kami mendeklarasikan width="64" height="64" viewBox="0 0 64 64". Kami merendernya menjadi 64, 512, dan 1,024 piksel dengan Sharp 0.34.4 yang versinya ditetapkan repositori. Keluaran 512 dan 1,024 piksel dihasilkan dari SVG, memiliki sudut transparan serta pusat berwarna opak, dan melaporkan dimensi yang diminta. Itu adalah pengamatan untuk contoh serta versi ini, bukan benchmark semua karya SVG.

Pengujian render Sharp 0.34.4 asli
Pengujian render Sharp asli: render SVG langsung 512 piksel dan render SVG dengan density disesuaikan tampak identik, sementara memperbesar PNG perantara 64 piksel tampak kabur
Ikon SVG 64 × 64 yang sama dirender langsung pada 512 piksel, dirender dengan density masukan 576 lalu diubah ukuran menjadi 512 piksel, atau dirasterkan dahulu pada 64 piksel lalu diperbesar. Hanya jalur terakhir memperbesar kisi piksel yang sudah ada.

Gambar membuat penyebab kegagalan konkret: setelah keluaran pertama berupa PNG 64 piksel, resize berikutnya menginterpolasi piksel itu. File tidak lagi memiliki path untuk digambar ulang. Hasil langsung dan hasil dengan density disesuaikan pada 512 piksel identik di seluruh kanal RGBA mentah dalam pengujian ini. SVG sumber, skrip render, dan metadata hasil disimpan bersama paket riset artikel.

Apakah Anda memerlukan density dalam Sharp?

Opsi konstruktor density Sharp mengendalikan DPI saat membaca masukan SVG atau PDF; default yang didokumentasikan adalah 72. Ini berbeda dari meminta lebar akhir dalam resize(). Anda mungkin menemukan contoh Sharp lama yang menaikkan density masukan untuk menghindari hasil pembesaran yang kabur. Contoh tersebut menjelaskan gejala historis nyata: issue Sharp #1421 melaporkan SVG 32 piksel menjadi berpiksel saat diperbesar ke 512 piksel pada 2018. Laporan itu bukan bukti bahwa solusi tersebut masih diperlukan untuk instalasi saat ini.

Kami menguji pasangan persis ini pada 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();

Untuk ikon vektor 64 piksel kami, kedua pipeline menghasilkan piksel RGBA 512 × 512 yang sama. Tetapkan density masukan hanya ketika file tertentu dan versi Sharp yang diinstal menunjukkan kebutuhan, lalu ulangi perbandingan setelah peningkatan versi. Jangan memperlakukan angka DPI lebih tinggi sebagai sakelar ketajaman universal. Pertanyaan awal yang berguna adalah apakah Anda masih memiliki geometri vektor ketika Sharp merender PNG akhir.

Jika Anda juga bekerja dengan PDF, uji masukan itu terpisah: eksperimen SVG ini tidak membuktikan perilaku PDF. Demikian pula, withDensity() dalam dokumentasi Sharp lebih baru menjelaskan metadata DPI keluaran; itu adalah operasi berbeda dari density render masukan SVG pada konstruktor.

Periksa dimensi, transparansi, dan isi sumber

Gunakan API metadata Sharp pada keluaran alih-alih menebak dari pembesaran pratinjau:

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],
});

Untuk contoh persegi di sini, dimensi yang diharapkan adalah 256 × 256 dan 512 × 512. hasAlpha menunjukkan kanal alfa, tetapi tidak membuktikan bahwa sudut tertentu transparan; periksa file atau ambil sampel piksel jika transparansi penting untuk penyerahan. Alfa sudut contoh kami nol dan alfa pusat 255 pada semua keluaran yang diuji. Sebaliknya, persegi panjang putih dalam SVG akan digambar pada setiap PNG, terlepas dari format PNG.

Jika render besar baru masih berpiksel, periksa isi SVG. Standar SVG mengizinkan elemen <image> yang menyematkan atau menautkan gambar raster. Karena itu, file dapat memiliki ekstensi .svg sementara karya di dalamnya tetap PNG beresolusi rendah. Panduan menemukan gambar raster di dalam SVG kami menunjukkan cara memeriksa objek dan XML. Menaikkan lebar keluaran Sharp tidak dapat mengubah piksel tertanam itu menjadi path.

Periksa juga tujuan. File 512 piksel yang ditampilkan pada 1,024 piksel dapat terlihat kabur. Penampil yang diperbesar jauh melewati 100% memperlihatkan kisi PNG meskipun ekspor benar. Bandingkan pada ukuran render dan latar sebenarnya, lalu tentukan apakah mengirim PNG lebih besar atau SVG sendiri. Untuk penyerahan web, SVG inline dan SVG dalam elemen image menawarkan pilihan integrasi berbeda; keduanya tidak memerlukan PNG ketika target mendukung SVG.

Peran PerfectVector

Sharp merasterkan SVG; tidak merekonstruksi path yang bisa diedit dari PNG. Jika master karya Anda hanya ikon atau logo raster, buat dan periksa SVG sebelum pipeline ekspor ini. Panduan ikon PNG ke SVG untuk UI kit membahas geometri konsisten dan pemeriksaan penyerahan dalam satu set. Alur gambar ke vektor PerfectVector dapat membuat kandidat SVG dari karya yang hanya raster. Buka hasil itu, periksa siluet, detail kecil, dan apakah benar berisi path, lalu render PNG 1x serta 2x dari SVG yang disetujui. Jika Anda sudah memiliki SVG asli bersih, pertahankan dan gunakan Sharp langsung.

FAQ

Mengapa keluaran SVG ke PNG Sharp saya tampak kabur? Periksa apakah pipeline terlebih dahulu membuat PNG kecil lalu memperbesarnya. Selanjutnya periksa SVG untuk konten raster tertanam dan bandingkan PNG yang diserahkan pada ukuran tampilan sebenarnya. Pada versi Sharp saat ini, uji render SVG langsung ke ukuran akhir sebelum menambahkan solusi density masukan.

Apakah density: 576 diperlukan untuk pembesaran delapan kali? Tidak diperlukan untuk contoh SVG 64-ke-512-piksel kami pada Sharp 0.34.4: resize langsung dan resize dengan density disesuaikan menghasilkan piksel RGBA identik. SVG dan renderer yang Anda instal mungkin berperilaku berbeda, jadi uji masukan persis itu alih-alih mengadopsi angka sebagai aturan.

Bagaimana membuat PNG 2x transparan? Render dari SVG pada dua kali dimensi CSS yang dimaksud dan ekspor sebagai PNG. Konfirmasikan lebar serta tinggi hasil, lalu periksa area yang tidak digambar untuk transparansi. Kanvas transparan tidak menghapus bentuk latar yang sudah ada dalam SVG.

Sources

  1. Sharp — Constructor — Dukungan masukan SVG dan opsi density masukan.
  2. Sharp — Mengubah ukuran gambar — Perilaku ukuran keluaran yang digunakan dalam contoh.
  3. Sharp — Metadata masukan — Pemeriksaan dimensi dan metadata alfa.
  4. Sharp GitHub — Issue pixelasi SVG ke PNG #1421 — Gejala historis yang dilaporkan, secara eksplisit dipisahkan dari pengujian versi saat ini yang ditetapkan.
  5. Sharp — Opsi keluaran — Membedakan metadata density keluaran lebih baru dari density render masukan.
  6. W3C — Konten tertanam SVG 2 — Alasan SVG dapat berisi piksel raster.

Jika master hanya berupa raster, buat kandidat SVG dengan PerfectVector, periksa path-nya, dan gunakan Sharp untuk merender file yang disetujui pada setiap ukuran PNG yang diperlukan.

Lebih banyak dari blog

Ubah file gambar Anda menjadi
SVG yang dapat diedit