# SVG to PNG

> 在瀏覽器把 SVG 點陣成 PNG。實測 apps/web/public/og.svg 在 1200×630 從 1,809 位元組變成 63,223；路徑、文字與動畫都不再是向量，也不能再任意縮放。

- URL: https://bytescope.dev/zh-Hant/image-convert/svg-to-png/
- Locale: zh-Hant · Also: [en](https://bytescope.dev/en/image-convert/svg-to-png.md) · [ja](https://bytescope.dev/ja/image-convert/svg-to-png.md)
- Runs: 檔案不會離開你的瀏覽器 — 全部在本機處理。
- Requires: Any modern browser (Chrome, Edge, Firefox, Safari), desktop and mobile.
- Updated: 2026-09-08

## What it does

### SVG 轉成 PNG 會失去什麼

這是點陣化，不是重新包裝。Chrome 沒辦法對 SVG blob 做 `createImageBitmap`，所以 `ImageConvertTool.rasterizeSvg` 用 `new Image()` 載入，依 `naturalWidth`、`naturalHeight` 畫到 canvas，再把那張點陣丟進 worker。從那一刻起輸出就是像素。路徑、群組、viewBox、currentColor，以及還需要 SVG 樹的 CSS 都沒了。之後再放大是在插值那些像素，不是重跑向量繪製。就算 PNG 對手上的點陣是無損的，這一步也不可逆。

尺寸在編碼前就定了。若 `naturalWidth` 或 `naturalHeight` 是 0——沒有內建尺寸的 SVG——`rasterizeSvg` 會改畫 1024 × 1024，介面上出現 `svgNoSizeWarning`。`apps/web/public/og.svg` 宣告寬 1200、高 630，所以實測用 1200 × 630 而不是後備值。SVG 裡的文字會變成像素，用的是繪製端實際拿到的字型。這段程式不會去抓字型檔，也不會抓外部的 `image` href：它只畫瀏覽器影像解碼器從 SVG 位元組生出來的結果。`@font-face` 網址或 SVG 裡的外部 PNG 看不看得到，是瀏覽器把 SVG 當圖片載入時的規則，不是轉換器另外實作的步驟。

動畫是故意跳過的。因為送進 worker 的已經是點陣，`convert.worker.ts` 不會替 SVG 開 `ImageDecoder` 動畫探測。SMIL 或 CSS 動畫不會變成 APNG。編碼的是 canvas 上那一張。

### 實測時檔案大小怎麼變

2026-09-13，腳本讀 `apps/web/public/og.svg`（1,809 位元組），用 sharp/librsvg 點陣成 1200 × 630，再把「最佳化 (oxipng)」打開：63,223 位元組，大約是向量檔的 35 倍。那個勾選框這一頁預設是關的，維持關閉的話，瀏覽器自己編出來的 PNG 通常還會再大一點。合理，因為 SVG 是文字，PNG 存的是一張 1200 × 630、深色卡片加字的點陣。Node 的點陣器和瀏覽器的 `new Image()` 加 canvas 不是同一套，字型一替代，位元組就可能不一樣。長寬對得上這份檔案的 width/height，也就是 `rasterizeSvg` 會用的尺寸。小小的 logo SVG 不會生出這麼大的 PNG；這個樣本是網站 1200 × 630 的 Open Graph 圖。

### 什麼時候不該把 SVG 轉成 PNG

還要在各種尺寸使用的 logo 或圖示不要轉：PNG 只有一個解析度，母檔本來是 SVG。還要當路徑或文字繼續編的圖也不要轉。意義依賴外部字型或外部圖的 SVG，先內嵌並自己看過快照再轉，因為這工具不會去抓那些額外檔。CMS、信件、`<img>` 宿主拒收 SVG，或你需要給點陣編輯器用的單一點陣時，再選 PNG，並把 SVG 留在旁邊。

轉換完全在你的瀏覽器內進行 — 不上傳、不排隊、無浮水印。想放幾個檔案都行，可逐一下載，也能打包成 zip。

## Limits

這是點陣化，不是重新包裝。Chrome 沒辦法對 SVG blob 做 `createImageBitmap`，所以 `ImageConvertTool.rasterizeSvg` 用 `new Image()` 載入，依 `naturalWidth`、`naturalHeight` 畫到 canvas，再把那張點陣丟進 worker。從那一刻起輸出就是像素。路徑、群組、viewBox、currentColor，以及還需要 SVG 樹的 CSS 都沒了。之後再放大是在插值那些像素，不是重跑向量繪製。就算 PNG 對手上的點陣是無損的，這一步也不可逆。

尺寸在編碼前就定了。若 `naturalWidth` 或 `naturalHeight` 是 0——沒有內建尺寸的 SVG——`rasterizeSvg` 會改畫 1024 × 1024，介面上出現 `svgNoSizeWarning`。`apps/web/public/og.svg` 宣告寬 1200、高 630，所以實測用 1200 × 630 而不是後備值。SVG 裡的文字會變成像素，用的是繪製端實際拿到的字型。這段程式不會去抓字型檔，也不會抓外部的 `image` href：它只畫瀏覽器影像解碼器從 SVG 位元組生出來的結果。`@font-face` 網址或 SVG 裡的外部 PNG 看不看得到，是瀏覽器把 SVG 當圖片載入時的規則，不是轉換器另外實作的步驟。

動畫是故意跳過的。因為送進 worker 的已經是點陣，`convert.worker.ts` 不會替 SVG 開 `ImageDecoder` 動畫探測。SMIL 或 CSS 動畫不會變成 APNG。編碼的是 canvas 上那一張。

## FAQ

### 之後放大 PNG，還能跟 SVG 一樣銳利嗎？

不能。PNG 的邊緣是點陣化當下那個尺寸的像素。放大是插值。還需要任意縮放就留著 SVG；宿主不收向量檔時才用 PNG。

### SVG 沒寫寬高時，會畫成多大？

`naturalWidth` 或 `naturalHeight` 是 0 時，`rasterizeSvg` 畫 1024 × 1024，並顯示沒有內建尺寸的警告。像 `public/og.svg` 這種有宣告寬高的檔，會用它的 1200 × 630。

### SVG 裡的 SMIL 或 CSS 動畫會變成動畫 PNG 嗎？

不會。主執行緒先截一張點陣，worker 只要看到 `msg.bitmap` 就跳過動畫探測。編碼的只有那張靜態圖。

### 我的圖片會被上傳到任何地方嗎？

不會。轉換在你的瀏覽器內使用 canvas API 和 Web Worker 完成 — 檔案不會離開你的裝置。沒有上傳步驟、不用排隊，檔案大小也只受限於你電腦的記憶體。

### 轉換後的圖片會保留 EXIF 中繼資料嗎？

不會 — 而這正是特色之一。透過 canvas 重新編碼會移除所有中繼資料：GPS 位置、相機型號、時間戳記和色彩描述檔。輸出只包含像素，而這通常正是你公開分享圖片前想要的結果。

### 可以一次轉換很多張圖片嗎？

可以。拖放或貼上任意數量的檔案；每個檔案都會在背景轉換，各自有進度顯示和下載按鈕，也可以把全部內容打包成 .zip 一次下載。

### 轉檔會讓畫質變差嗎？

看你選的目標格式。不管來源和目標是哪兩種格式，轉換器一律先解碼成原始像素再重新編碼，中繼資料也是這樣被移除的。目標是無損格式（PNG，以及在 256 色限制內的 GIF）時，像素和解碼出來的完全一樣；目標是 JPEG、WebP 或 AVIF 時，則由品質滑桿控制取捨，而且來源本來就是有損檔的話，會再多疊一層損失。
