跳至內容
圖片與媒體

別讓 WordPress 用 82% 品質壓縮你的圖片

WordPress 產生的每一張 JPEG,都會以 0–100 分制中的品質 82 重新編碼。這個預設值定義在 WP_Image_Editor::get_default_quality() 中,並套用到

發布於

WordPress 產生的每一張 JPEG,都會以 0–100 分制中的品質 82 重新編碼。這個預設值定義在 WP_Image_Editor::get_default_quality() 中,並套用到 WordPress 從你上傳檔案切出來的每一個衍生尺寸 — thumbnail、medium、medium_large、large,以及佈景主題註冊的每一個額外尺寸。對照片來說,82 是檔案大小與失真之間相當合理的取捨。但對螢幕截圖、UI 畫面、圖表、標誌,以及任何有銳利文字或大面積純色的圖片而言,82 的破壞肉眼可見:每個字母周圍會出現爬動的蚊蟲雜訊,平滑的漸層上則會出現色帶。

要修改它,加上一個 filter 並重新產生縮圖即可。不過若要專門解決螢幕截圖的問題,比較好的做法通常是一開始就別交給 WordPress 一張 JPEG。

82 這個數字究竟從何而來

WordPress 早在 4.5(2016 年)時,為了減輕頁面重量,把 JPEG 預設值從 90 降到 82。這個值由 wp-includes/class-wp-image-editor.php 中的 get_default_quality() 回傳,並在使用中的編輯器 — 若主機有 Imagick 就是 WP_Image_Editor_Imagick,否則是 WP_Image_Editor_GD — 寫入縮放後的檔案時被讀取。

重點細節在於:82 是套用在每一個衍生尺寸上,不是只套用一次。上傳一張圖片,WordPress 會讓它多次通過編碼器,每一趟都以品質 82 重新量化。原始上傳的檔案本身則會保持不動,前提是它在大圖門檻(長邊 2560px)以下。若超過這個門檻,WordPress 會產生一個以品質 82 重新編碼的 -scaled.jpg,並拿那個檔案當作「full」尺寸提供。所以「我的原尺寸圖片看起來沒問題,但頁面上的版本卻糊掉了」,幾乎都是 srcset 挑到了某個品質 82 的子尺寸,或是那個 -scaled 檔案。

如何修改品質

需要掛上一個 filter。wp_editor_set_quality 是現代、正式的做法 — 它對 JPEG 和 WebP 都會觸發,並接收 MIME 類型讓你可以分支處理:

add_filter( 'wp_editor_set_quality', function ( $quality, $mime_type ) {
    if ( 'image/jpeg' === $mime_type ) {
        return 92; // up from 82
    }
    return $quality;
}, 10, 2 );

把這段放進一個小型 mu-plugin(wp-content/mu-plugins/)或一個站台專屬外掛裡。放在 functions.php 也行,但一旦切換佈景主題,這個設定就會消失。

你也會看到有人推薦較舊的 jpeg_quality filter。它仍然會觸發(WordPress 在 wp_editor_set_quality 之後緊接著套用它,僅限 JPEG),但沒有理由兩個都掛 — wp_editor_set_quality 涵蓋了舊 filter 所做的一切,甚至更多。

有一件大家都會忘記的事:這個 filter 只影響它生效之後才編碼的圖片。 每一張已經躺在 wp-content/uploads 裡的縮圖,當初都是以 82 寫入的,而且會一直維持 82。把它們重新產生:

wp media regenerate --yes

如果你沒有用 WP-CLI,Regenerate Thumbnails 外掛可以在後台做同樣的事。

在你決定一個數字之前,值得實際看看某個品質對你自己的圖片究竟做了什麼,而不是靠猜。我們的 WordPress JPEG 品質工具會在瀏覽器裡以每一個品質等級重新編碼一張範例圖,讓你親眼看著失真出現 — 它能把 82、90、100 之間的差異在螢幕截圖上呈現得一目瞭然,這是設定檔裡的一個數字永遠做不到的。

針對螢幕截圖與平面圖形的更佳解法

調高 JPEG 數字只是治標。螢幕截圖真正的問題在於 JPEG 根本就是錯誤的編碼器。JPEG 的 DCT 壓縮是為照片漸層調校的;它在文字與 UI 邊框那種硬邊的黑白交界上會徹底崩潰,這正是為什麼品質 82 在螢幕截圖上看起來比在照片上糟糕這麼多。

改上傳 PNG。WordPress 會把 PNG 子尺寸保留為 PNG,而 PNG 是無損的 — 品質 filter 不會碰它,所以任何尺寸都不會有失真,只有乾淨的重新取樣。對螢幕截圖而言,一張最佳化良好的 PNG 通常反而比同一張圖的高品質 JPEG 更小,因為純色在 PNG 裡壓縮得很好,在 JPEG 裡卻壓得很糟。

如果你想要有損格式的較小檔案,又不要 JPEG 的邊緣破壞,WebP 是折衷選擇 — 但你仍然是透過上面那個相同的 wp_editor_set_quality filter 來控制它的品質,只要對 image/webp 做分支即可。

不該做的事

不要把品質全站設成 100。 這是半數論壇討論串裡得票最高的答案,而它是錯的。品質 100 的 JPEG 並非無損 — 它仍然會量化 — 卻會讓你站上每一張照片大幅膨脹,換來的是肉眼看不出的差別,同時拖垮 LCP 和 Core Web Vitals。為需要的格式調高數字,或為圖形換格式;別把全站壓縮一次炸掉。

不要編輯 class-wp-image-editor.php 修改核心中 get_default_quality() 的回傳值確實有效,直到下一次 wp core update 悄悄把它覆蓋掉。用 filter。

不要為了「避開壓縮」而停用圖片尺寸。 關掉縮圖產生並不會停止重新編碼 — 它會弄壞響應式的 srcset,害瀏覽器在手機上下載你的原尺寸圖片。不同的問題,更糟的結果。

不要以為重新上傳就能修好既有圖片。 如果你設了 filter 卻略過重新產生的步驟,每一張舊的衍生圖仍然是品質 82。這個 filter 只對未來生效。

如果你的圖片在 2560px 以下,就不要怪 -scaled 檔案 — 那條路徑對它們根本不會執行。如果你確實碰到了它,並且想讓未被動過的原始檔被提供出來,那是另一項設定;參見停用 scaled 圖片

還是卡住了?

如果某個尺寸在重新產生後看起來仍然不對,先確認頁面實際提供的是哪個檔案 — 在新分頁開啟該圖片,檢查檔名是否以尺寸後綴(-1024x768.jpg)或 -scaled.jpg 結尾。圖片尺寸檢查工具會顯示 WordPress 從一次上傳所產生的每一個衍生尺寸,讓你能精確看出你的 srcset 交給瀏覽器的是哪個尺寸,別再對著錯的檔案除錯。