你有一個透明背景的 logo。你上傳它、或轉換它、或把它放進一份文件,然後透明的部分變成一塊實心黑色矩形。那個檔案剛才明明好好的。
沒有任何東西損毀。過程中某個環節必須決定「透明的地方要放什麼」,而它選了黑色。
一個透明的 PNG 每個像素存四個值:紅、綠、藍,以及 alpha——那個像素有多不透明。alpha 為零代表完全透明,而那裡的顏色值通常沒有意義,往往就留成零。零紅、零綠、零藍,就是黑色。
JPEG 完全沒有 alpha 通道。它無法表示「這裡什麼都沒有」。所以把一張透明 PNG 轉成 JPEG 會逼出一個決定:每一個透明像素都必須變成某個真實的顏色。
一個謹慎的轉換器會問你,或者預設填白色。一個草率的則直接丟掉 alpha 通道、留下底下原本的顏色值——而如上所述,那通常是零。黑色就是從這裡來的。它不是刻意選了黑色;它是沒有做選擇。
可靠的做法是自己做那個決定,而不是留給下一個碰到這個檔案的軟體。
在轉換之前,把圖片放在一個你要的顏色的實心背景上,然後壓平。接著再轉換。現在沒有透明可以丟失,下游也沒有任何工具需要做選擇。
要哪個顏色取決於它要去哪。多數文件和淺色頁面用白色,預覽卡片用你的品牌色,如果你知道實際的頁面背景就用那個。重點是你選了它,一次,而且是知情的。
而在透明真的被支援的地方——一個網站、一個 App 介面——就留著 PNG,根本不要轉。這個問題只存在於「有 alpha 的格式」遇上「沒有 alpha 的格式」的那個交界。
GIF 支援透明,但只是一個開關:每個像素不是完全透明就是完全不透明。沒有中間。
這件事要緊,因為平滑的邊緣仰賴部分透明。一個曲線的 logo 邊緣,是由 30% 不透明、60% 不透明……這樣的像素畫出來的,和後面的東西融合。GIF 存不了那些,所以每一個都變成不是實心就是不見。
結果就是 GIF logo 那種鋸齒、硬邊的樣子,以及那個惡名昭彰的白色光暈:如果圖片是在白底上做的,半透明的邊緣像素會被四捨五入成不透明的白,於是 logo 抵達深色頁面時戴著一圈淡淡的邊。
沒有任何設定能修好這個。這就是格式本身。用 PNG 或 WebP。
偶爾一張有正常 alpha 的 PNG,在深色背景上還是會顯出一圈淺色輪廓。這是一個相關的缺陷:那些邊緣像素在製作圖片時就已經和白色混合過了,而那個白被烤進了半透明像素的顏色值裡。
解法在上游——從原始稿件重新輸出一次,在透明或同樣深色的背景上。一旦那圈邊進了像素裡,沒有任何轉換能移除它。
兩個快速測試,幾乎能抓到全部: