讓螢幕擷圖 PNG 檔縮小 73% 的魔法 - WebP
| | | 3 | |
前幾天貼文提到,WebP 格式在相同畫質下,WebP 體積比 JPEG 小約 25-34%,HEIC 檔案更小,通常只有 JPEG 的一半。 WebP 支援透明層及動畫,壓縮率雖然不如 HEIC 小,但勝在支援度廣(現代瀏覽器都支援,HEIC 應用仍以 Apple 設備為主)且採 BSD 授權無權利金問題,應會是近期的主流。

圖表沒納入的還有 AVIF,跟 WebP 一樣採開放標準且無專利授權問題,壓縮率更高(但顯示也更耗資源,需待設備內建硬體加速改善),但普及率又比 WebP 再低一點,會不會及何時能取代 WebP 未知。
為了克服不同裝置圖檔格式支援度不一問題,HTML 規範有個 <picture> Picture 元素,網站可為同一張圖片分別準備 AVIF、WebP、JPG 格式檔案,讓瀏覽器可視狀況優先選擇 AVIF,若不支援改用 WebP,再不行則用 JPG。每張圖要準備三種格式,HTML 圖檔寫法也要特調挺搞剛的,想追求傳輸量最小化又想保持相容性的朋友可以試試!
<picture>
<source srcset="image.avif" type="image/avif">
<source srcset="image.webp" type="image/webp">
<img src="image.jpg" alt="Description">
</picture>
回到前端攻城獅的角度,這篇來試試現有 JPG/PNG 圖檔轉成 WebP 跟 AVIF,看看體積差多少。以下以 .NET 為例實測轉成 WebP 與 AVIF 的速度與減少資料庫。
先挑選程式庫,以下是 AI 給的分析與建議:
| 程式庫 | 效能 | 記憶體 | AVIF 支援 | 授權方式 (License) | 建議對象與場景 |
|---|---|---|---|---|---|
| Magick.NET | 快 | 中等 | 成熟支援 | Apache 2.0 | 功能最完整 適合大量格式轉換、影像處理功能或穩定 AVIF 支援的商業專案 |
| NetVips | 極快 | 極低 | 優秀 需 libheif/libavif | MIT(Wrapper)+ LGPL(libvips) | 效能首選 適合高併發服務、大量批次轉檔、超大圖片處理 |
| SkiaSharp | 極快 | 低 | 基本支援 | MIT | 渲染與 WebP 首選 適合縮圖、圖片顯示、WebP 轉換; 若 AVIF 是核心需求,優先考慮 Magick.NET 或 NetVips |
| ImageSharp | 中上 | 低 | 良好 需 AVIF 套件 | Six Labors Split License | 部署首選。 純 C# 實作、跨平台部署最簡單; 企業商業使用需留意授權條款。 |
若是單純的 JPG/PNG 轉 WebP,封裝 Google Skia 圖形引擎的 SkiaSharp 速度快採 MIT 授權商用限制少是首選,但 AVIF 支援偏弱;Magick.NET 是 ImageMagick 的 .NET 版本,支援超過 100 種格式及一些圖像處理函式,功能最完整。NetVips 採 MIT + LGPL 授權,依賴 libvips 執行,速度最快;ImageSharp 不依賴原生程式庫,部署最方便,但中大型企業(年營收超過 1M USD)需付費,這二者在商業應用時需留意授權問題。
註:依賴原生程式庫有時是件麻煩事,想起這幾個程式庫我之前交手過,也吃過苦頭。
我測試了 Magick.NET、SkiaSharp 與 ImageSharp,花了點時間找到三種程式庫轉 WebP 及 AVIF 的做法。先簡單記錄過程遇到的小問題:
- ImageSharp 現在需要授權碼才能使用,個人用途可到網站填寫資料索取 sixlabors.lic 檔案,有效期一年,存在專案目錄即可正常執行。
No Six Labors license found. Set $(SixLaborsLicenseKey), set $(SixLaborsLicenseFile), or add a 'sixlabors.lic' file to the project/workspace. Please obtain a license from https://sixlabors.com/pricing/ - AVIF 普及度仍落後 WebP,除了 Magick.NET 直接支援,SkiaSharp 可顯示不能製作 AVIF,故 SkiaSharp 與 ImageSharp 需要自己找第三方原生程式庫提供 AVIF 轉換。
- PNG 轉 AVIF 可能遇到色彩空間不相容問題
INFO: legacy PNG color space information found in file {png-path} not matching any CICP value. libavif is generating an ICC profile for it. Use --ignore-profile to ignore color space information instead (may affect the colors of the encoded AVIF image).
綜合以上,我覺得現階段使用 AVIF 會比 WebP 麻煩一點。最後我選擇使用 MagicK.NET 作為我的主要工具,理由有三:
- Magick.NET-Q8-x64 套件直接支援 windows/linux/linux-musl/macOS,不需另外安裝對應平台的原生程式庫
- ImageMagick 的圖檔格式支援、轉檔與圖形處理功能完整,可成為專案開發圖形處理的重要工具
- ImageMagick 有 magick CLI 工具,可直接轉檔與程式轉換結果對照
以下是簡單的轉檔測試,除了使用 Magick.NET 程式庫,另外會直接呼叫 magick CLI 轉換相同品質的 WebP/AVIF 對照結果是否正確:
using ImageMagick;
// dotnet package add Magick.NET-Q8-x64
// Q8 8-bit per channel, x64 含 windows/linux/linux-musl/macOS 版本
public class ImageMagickTest
{
static void ConvertByMagickCli(string inputPath, string outputPath, uint quality, string losslessFlag = "")
{
// https://imagemagick.org/webp/
var process = new System.Diagnostics.Process();
process.StartInfo.FileName = "magick";
process.StartInfo.Arguments = $"\"{inputPath}\" -quality {quality} {losslessFlag} \"{outputPath}\"";
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.Start();
process.WaitForExit();
}
public static void ConvertToWebp(string inputPath, string outputPath, uint quality = 75)
{
bool lossless = quality > 100;
if (lossless) quality = 100;
using (var image = new MagickImage(inputPath))
{
// 可以設定 WebP 專屬參數
// image.Settings.SetDefine(MagickFormat.WebP, "lossless", false);
if (lossless)
{
image.Settings.SetDefine(MagickFormat.WebP, "lossless", true);
}
image.Quality = quality;
image.Write(outputPath, MagickFormat.WebP);
// 呼叫 magick CLI 轉換
var cliChkPath = outputPath.Replace(".webp", ".cli.webp");
ConvertByMagickCli(inputPath, cliChkPath, quality, lossless ? "-define webp:lossless=true" : "");
}
}
public static void ConvertToAvif(string inputPath, string outputPath, uint quality)
{
// 關於 AVIF 是否真的 lossless 的討論
// https://github.com/ImageMagick/ImageMagick/discussions/6591
bool lossless = quality > 100;
if (lossless) quality = 100;
using (var image = new MagickImage(inputPath))
{
if (lossless)
{
image.Settings.SetDefine(MagickFormat.Avif, "lossless", true);
// AOM encoder error: Invalid parameter - Only --enable_chroma_deltaq=0 can be used with --lossless=1. (8.2005)
image.Quality = 99;
}
else {
image.Quality = quality;
}
image.Write(outputPath, MagickFormat.Avif);
// 呼叫 magick CLI 轉換
var cliChkPath = outputPath.Replace(".avif", ".cli.avif");
ConvertByMagickCli(inputPath, cliChkPath, quality, lossless ? "-define avif:lossless=true" : "");
}
}
}
我自己圖檔應用的最大宗是部落格上的電腦畫面擷圖,目前怕 JPEG 有損壓縮讓文字模糊,都是用 PNG,說真的有點偏肥。WebP/AVIF 都支援無損壓縮,而且體積比 PNG 小 26%,而高畫質有損壓縮時,對文字的保護也比傳統 JPEG 好,是我最想試試的部分。
爬文查到一篇參考數據,1920x1080 文字為主擷圖:
- PNG (32-bit RGBA): 150-400KB
- PNG (indexed via pngquant): 40-120KB
- JPEG (quality 85): 120-250KB (with visible artifacts around text)
- WebP (lossless): 100-300KB
- WebP (lossy, quality 90): 60-150KB (minimal visible artifacts)
但,參考文章濃濃的 AI 味,自從前幾天踩到技術 AI 文的坑,我現在十年怕井繩。
Google 的 WebP 範例文件可信度高多了,實測 PNG 轉 WebP 無損壓縮約可節省 28% ~ 40%。

總之,這篇也會來實測一下,為人類手寫技術文保留一縷香煙...
我選了兩張圖片當測試範例,一個是 VSCode 的操作畫面擷圖 (Screenshot),一個則是照片範例 (Photo),用 iStock 圖庫網站查詢畫面當例子:


實測超乎我的預期:
| Quality | Screenshot WebP | Screenshot AVIF | Photo WebP | Photo AVIF |
|---|---|---|---|---|
| PNG | 206 KB | 206 KB | 1118 KB | 1118 KB |
| Lossless | 57 KB | 113 KB | 753 KB | 359 KB |
| 100% | 57 KB | — | 753 KB | — |
| 99% | 229 KB | 113 KB | 307 KB | 359 KB |
| 95% | 194 KB | 94 KB | 235 KB | 250 KB |
| 90% | 160 KB | 79 KB | 169 KB | 184 KB |
| 85% | 136 KB | 70 KB | 135 KB | 149 KB |
| 80% | 119 KB | 65 KB | 114 KB | 133 KB |
| 75% | 105 KB | 60 KB | 97 KB | 116 KB |
| 70% | 100 KB | 56 KB | 91 KB | 103 KB |
| 65% | 96 KB | 52 KB | 86 KB | 87 KB |
| 60% | 93 KB | 50 KB | 81 KB | 78 KB |
| 55% | 90 KB | 47 KB | 78 KB | 66 KB |
| 50% | 86 KB | 45 KB | 74 KB | 57 KB |
VSCode 操作畫面擷圖的 PNG 轉為 WebP 無損壓縮,檔案由 206K 變成 57K,足足減少了 73%。有趣的是,若使用有損壓縮且設定高品質水準,體積反而比無損壓縮大!
原因是 WebP 無損與有損使用的是不同的編碼器,Lossless 使用 VP8L,Lossy 使用 VP8 是兩套不同演算法。VP8L 非常適合有大片純色背景、重複圖案及銳利文字的畫面擷圖場景,能發揮極高的壓縮率。而有損編碼器需要額外儲存壓縮用的係數資料、Metadata... 等,有固定成本,當要求高品質低細節損失,這些固定成本增加的資料量低於省略細節所減少的資料量,才造成檔案大小不減反增。
而遇到相片性質影像,WebP 無損壓縮的表現就沒這麼突出了。而在 AVIF,畫面擷圖的無損壓縮圖檔可以減少 55% 大小,也比 PNG 好很多。
我做了拼貼圖片一次比較不同壓縮品質的效果:
畫面擷圖 WebP

畫面擷圖 AVIF

照片影像 WebP

照片影像 AVIF

另外,我叫 AI 寫一個互動式線上對照檢視,大家可以實際操作看看。

我眼睛不怎麼銳利,甚至覺得 50% 品質好像也沒差到哪裡去。但以畫面擷圖來說,使用 WebP 無損壓縮應是最佳選擇。
做完實驗,我最大的心得是:過去我部落格文章的擷圖為了怕轉 JPG 變模糊而一律存 PNG,無形中浪費了許多空間與頻寬,其實只要改用 WebP 無損壓縮,甚至能縮小 70% 以上的體積,WebP 出來這麼多年,我今天才正式感受到威力。
而經過這次實測,發現開發端對的 AVIF 的支援不如 WebP 成熟,而我常用畫面擷圖,WebP 無損壓縮的表現非常出色,減少的資料量超乎預期。所以我打算過陣子調整我的部落格平台,確保可以完整支援 WebP 格式,正式進入 WebP 時代。
Tests converting PNG/JPEG images to WebP and AVIF with .NET libraries, comparing support, licensing, performance, and file sizes. Results show WebP lossless greatly reduces screenshot size, making it a practical upgrade for blog images.
Comments
# by yoyo
不過這篇文章的圖片還是用PNG跟JPG XD
# by guest
文字為主的截圖可以考慮64索引色png喔!(206.7k->68.2k)
# by guest
圖1(常見圖片格式那張)也可縮小(247.9k->49.5k)