開發踩坑 #1:你的 ICO 看起來沒問題——直到你拆開 BMP 幀一看
2026-06-03
這不是一個商店認證的驚悚故事。這是一個更安靜的陷阱——純粹出於好奇心踩進去的。
我一直用同一種懶人方式產生 .ico 檔案:找一張 256×256 的 PNG,丟到某個線上轉換工具裡,下載產出物。Explorer 裡看著一直正常,我也從來沒多想。
直到有一天,我在做一個 ICO 拆包工具,拿其他產品的 ICO 檔案做測試的時候,發現了有點不太對勁的東西。
我發現了什麼
ICO 檔案是一個容器,可以包含多個不同尺寸的圖片(16×16、32×32、48×48、64×64、128×128、256×256),Windows 會根據場景選合適的尺寸——工作列、標題列、Alt+Tab、檔案總管。
我的 ICO 檔案乍看之下每一幀都正常。但仔細檢查後發現:
- 256×256 幀(以 PNG 儲存)——完美。正確的 Alpha 通道,平滑的邊緣,沒有瑕疵。
- 所有更小的 BMP 幀——透明度完全壞了。Alpha 通道要嘛不存在,要嘛包含垃圾資料。半透明像素變成了帶奇怪色暈的實心色塊。
那些小尺寸幀看起來就像 90 年代的劣質去背。
為什麼線上轉換工具會搞砸
大多數免費的 PNG 轉 ICO 工具的工作流程是這樣的:
- 拿到你的 256×256 PNG 並縮放到每個要求的尺寸(16、32、48 等)
- 把 256×256 幀儲存為 PNG
- 把小尺寸幀儲存為 32 位元 BMP
然而,ICO 內部的 BMP 幀格式非常特殊。它不使用 124 位元組的 BITMAPV5HEADER,而是使用標準的 40 位元組 BITMAPINFOHEADER,將 biBitCount 設為 32。每個像素的第 4 個位元組就是 Alpha 通道。關鍵在於:在顏色像素資料(XOR 遮罩)之後,還必須附加一塊 1 位元單色透明遮罩(AND 遮罩)以相容舊系統。標頭中的 biHeight 也必須設為實際影像高度的兩倍,以容納這塊 AND 遮罩。
很多線上轉換工具就在這裡翻車了:
- 它們雖然聲明瞭 32 位元色深,但把每個像素的 Alpha 位元組(第 4 位元組)全部刷成了
0x00(完全透明)或塞滿了隨機垃圾資料 - 它們產生的 AND 遮罩跟 Alpha 通道的資料完全對不上
結果就是:一個看起來合法的檔案——目錄項正確、尺寸對、Explorer 不報錯——但當 Windows 嘗試渲染小尺寸幀時,GDI 混合就會失控。你看到的就是神祕的光暈、不透明的像素、各種渲染錯誤。
為什麼你直到出問題才會發現
Windows Explorer 和大多數應用程式優先使用 256×256 PNG 幀來顯示。只要這幀是好的,圖示在各種正常檢視下看起來都完美無缺——大圖示、內容對話方塊、甚至工作列預覽。
壞的 BMP 幀只在 Windows 需要縮放到某個特定小尺寸時才會暴露出來。例如:
| 場景 | 使用尺寸 | 使用的幀 |
|---|---|---|
| 檔案總管(超大型圖示) | 256×256 | PNG ✓ |
| 檔案總管(大型/中型圖示) | 48×48 | BMP ✗ |
| 標題列 / 小圖示 | 16×16 | BMP ✗ |
| Alt+Tab 切換器 | 32×32 | BMP ✗ |
你的應用程式圖示在桌面上看著完美,但到了標題列或工作切換器裡就出現神祕「光暈」或透明炸裂。大多數人會怪 Windows 渲染——其實是你 ICO 檔案的問題。
如何檢查你的 ICO 檔案
使用可以列出 ICO 檔案所有幀的分析工具。注意看:
- 幀格式:256px 幀應該是
PNG。小尺寸幀應該是BMP。雖然按 ICO 規範所有幀都用 PNG 也是合規的,但在舊版 Windows 上可能存在相容性問題。PNG(256px)+ BMP(小尺寸)是最安全的組合。 - BMP 位元深度:小尺寸幀應該是
32 BPP才能支援真正的 Alpha 通道(半透明混合)。如果顯示為24 BPP,說明它遺失了每像素的 Alpha 資料——雖然它還能依靠 ICO 古老的 1 位元單色遮罩(AND Mask)實現「要嘛全透、要嘛全不透」的背景裁剪,但所有抗鋸齒邊緣、半透明漸層和陰影都會直接炸裂,在現代系統裡變成極其難看的實心毛刺或大黑邊。 - 肉眼檢查:單獨載入每一幀。小尺寸幀應該有平滑的 Alpha,而不是鋸齒邊緣或實心背景。
如何修復
方案一:使用專業工具並做好測試
拿你的來源 PNG,用能正確處理 BMP Alpha 通道的專業圖示編輯器建立新的 ICO。在信任任何轉換工具——無論線上還是離線——之前,先用一張包含半透明區域的 PNG(柔和的陰影、漸層等)產生 ICO,然後檢查每一幀。只要任何一個 BMP 幀的 Alpha 有問題,這個工具就不能用。
方案二:全部用 PNG 壓縮的 ICO(如果可以)
一些現代工具接受所有幀都用 PNG 壓縮的 ICO 檔案,而不僅僅是 256×256。這能完全避免 BMP Alpha 問題。但不是所有 Windows 版本和應用程式都支援——依賴這個方案之前要先測試。
小結
- ICO 在檔案總管裡看著正常不代表它就真的正常
- 256×256 PNG 幀通常是好的,底下所有小尺寸 BMP 幀可能都是壞的
- BMP Alpha 損壞在大多數檢視下看不出來——只在標題列、Alt+Tab 等小圖示場景下暴露
- 用一張已知半透明的 PNG 測試你的線上轉換工具,再決定要不要用
- 任何要發佈的圖示,花 5 分鐘用專業工具產生——絕對值
本文屬於開發踩坑系列。