我的像素藝術顯示器上的白色光暈,經由 Codex 的圖像工具生成後,變成了 RGBA (22, 34, 44, 1)。這代表它是一個不透明度為 1/255 的深灰色。在白色頁面上看起來很完美,但在深色背景上,同一個檔案卻在螢幕中央顯示出一個黑洞。
Refmade 是一款我正在開發的桌面應用程式,它會讀取你的 Claude Code 和 Codex 會話日誌,並將它們繪製成一個小型的像素辦公室。這是一個獨立專案,與 Anthropic 或 OpenAI 無關。Claude Code 和 Codex 代理程式在我指示下編寫了大部分程式碼。我負責撰寫規格,選擇保留哪些部分,並拒絕看起來錯誤的內容。
這是本系列的第七部分,涵蓋了 9 月 27 日,那天辦公室的精靈圖被繪製了兩次,一次是遊戲風格,一次是粉彩風格。目前使用者介面是韓文,這將在本系列後續部分中改變。總共有 22 張圖紙,69 個檔案。
在 9 月 27 日,我要求使用 Codex CLI 內建的圖像生成功能繪製所有辦公室資源。每個批次都包含一個 JSON 規格和一個 Codex 執行呼叫(在儲存庫中的 office-v2/assets-prompts/run_p3.sh)。
總共返回了 22 張原始圖紙。第二個腳本 integrate_p3.py 將它們切割成 69 個檔案:包括 12 個角色,每個角色有四種姿勢(站立、兩個走路影格、坐姿)、四塊地毯、一扇開著和關著的門、七個休息室道具、一條帶有完成板的牆壁條,以及一些其他物件,例如書桌、椅子、顯示器和地板。
原始圖紙從未被編輯。該腳本會裁剪和縮小它們,對於粉彩版本,它會執行下面描述的修復,因此再次執行會產生相同的輸出。
連續五個調色盤。同一天,我也在重新設計產品網站,並連續拒絕了五個調色盤。提案包括天藍色、奶油黃、天藍色背景、白色背景和先前的顏色,但我都覺得顏色不對。代理程式問我具體哪裡出了問題,我勾選了三個選項:背景和卡片顏色、圖片中的木質和棕色調,以及按鈕和強調色。這幾乎涵蓋了所有內容,所以並沒有縮小範圍。
我反而給了它一個規則:所有地方都使用較淺的粉彩,點陣風格字體(Galmuri,一種在 SIL 開源字體授權下的像素字體),並且不使用海軍藍作為主色。當天下午,22 張辦公室圖紙以粉彩風格重新繪製(檔案時間戳顯示這 22 張新圖紙在下午 4:00 到 4:09 之間生成),下午 4:30 整個網站都統一為粉彩風格。這個透明度問題正是在這些粉彩圖紙中出現的。
這個「洞」。在白色背景上打開其中一張粉彩圖紙,它看起來是正確的。將同一個檔案放在深色背景上,最亮的區域就會變成「洞」。我在撰寫這篇文章時測量了一張圖紙:p-illus-monitor-v1.png,尺寸為 1536 x 1024。Alpha 值為 255 的像素數量為 0,檔案中的最大 Alpha 值是 254。
藍色螢幕的 Alpha 值約為 250,例如 RGBA (146, 186, 227, 241)。米色邊框的 Alpha 值為 RGBA (253, 247, 243, 254)。白色光暈內部的 Alpha 值為 1 到 4,例如 RGBA (22, 34, 44, 1)。在白色背景上合成後,這些像素會顯示為 (254, 254, 254)。
單獨來看,最大 Alpha 值為 254 是無害的。同一次運行生成的遊戲風格顯示器圖紙,其最大 Alpha 值也為 254,但它沒有接近白色的像素,因此沒有任何部分變成「洞」。在粉彩圖紙中,米色和粉彩顏色保持在 Alpha 值 252 到 254,而原本是純白色的區域,例如光暈和背景,則以接近 0 的 Alpha 值返回。我猜測圖像工具將純白色視為背景並將其剪切掉,但我尚未驗證這一點。
一張原始圖紙,三種渲染效果。左:在白色背景上,看起來是正確的。中:同一個檔案在深色背景上,光暈部分被「打穿」。右:經過 unmatte.py 處理後。這張圖片僅顯示顯示器精靈圖,沒有使用者介面文字。
解決方案:在白色背景上合成,然後決定哪些是「外部」。預期的圖片是在白色背景上繪製的,因此只有將精靈圖合成到白色背景上時,顏色才是正確的。這可以恢復光暈。第二個問題是,精靈圖周圍的真實背景必須保持透明,而顯示器內部的白色光暈則不能。unmatte.py 分兩步完成:它首先在白色背景上合成,然後從四個邊緣對每個 Alpha 值低於閾值的像素進行洪水填充。
任何被填充到的區域都被視為「外部」並變為透明。像素藝術固有的深色輪廓充當了「牆壁」,因此螢幕內部的光暈得以保留。
(此處省略了 office-v2/assets-prompts/unmatte.py 的程式碼節錄,其預設閾值為 110。)我在這篇文章中使用的圖片是透過原始檔案生成的,而非此縮短版本。
有三點值得注意。上方第三個面板在顯示器頂部邊緣仍有一些零星的斑點,unmatte.py 並沒有將它們移除。之後,integrate_p3.py 無論如何都會將顯示器整個藍色螢幕區域塗上單一平面顏色,因為頁面會用 CSS 點亮螢幕。另外有兩個檔案採取了不同的處理方式。
牆壁條和完成板的規格要求「完全不透明」。牆壁條有一個平坦的灰色底部,腳本會將其裁剪掉。完成板則是在平面洋紅色上繪製的,integrate_p3.py 會將洋紅色去除(紅色高於 190,藍色高於 190,綠色低於 120)。我沒有記錄下為什麼我選擇這種方式而不是 unmatte.py 來處理這兩個檔案。
拉伸的圖片。在網站重新繪製期間,三步驟卡片上的圖片出現了垂直拉伸。我告訴代理程式不要再讓長寬比錯誤發生,於是它們編寫了 aspect-audit.mjs。這個腳本會在 360、390、768、1024 和 1440 像素寬度下打開頁面。對於每個 <img> 標籤,它會比較渲染後的長寬比與檔案的自然長寬比。
如果圖片使用預設的 object-fit: fill 且長寬比差異超過 2%,則審核失敗。9 月 27 日的最後一次運行顯示 0 張失真圖片。這個審核是一個簡短的 Playwright 腳本。我只是說這個問題不能再發生,而代理程式則將其轉化為一個會明確報告失敗的機制。
兩種主題。接著我要求兩種主題:粉彩風格和早期的遊戲風格點陣圖,只在主題上有所不同。integrate_p3.py 獲得了一個 --theme game 旗標,它會跳過粉彩圖紙,並將原始藝術作品建構到一個單獨的資料夾中。到了下午 5:30,辦公室頁面可以透過 data-theme 屬性在這兩種主題之間切換。晚上 7:20,角色們穿上了部門服裝:21 個角色、24 個主題貼紙、12 個徽章。
這是目前版本(非 9 月 27 日版本)中兩種主題下的相同辦公室面板。資料是公開的演示資料:「處理客戶詢問回覆」這項任務及其團隊都是虛構的。可見的韓文文字,加上英文標籤「Codex」:「工作團隊」、「處理客戶詢問回覆」、「需要我的回答」、「等待我的回答」、「團隊負責人」、「業務團隊」、「起草回覆 · 思考中」、「整理常見問題 · 思考中」。
下次我會檢查什麼。在將生成的精靈圖整合進去之前,先在深色背景上查看它們。白色頁面會隱藏這個錯誤。讀取檔案的 Alpha 色版。這篇文章中的數字是透過幾行使用 PIL 的 Python 程式碼得出的。保持原始圖紙不變,並使整合腳本可重複運行。
我就是用這種方式從相同的圖紙建構出兩種主題。將「這種情況不能再發生」轉化為一個會以非零值退出的檢查。如果你使用圖像模型生成精靈圖或圖示,你如何在它們到達使用者介面之前捕獲 Alpha 問題?我還沒有為此建立檢查。一個想法是在整合腳本中將每個精靈圖渲染在深色背景上,並在任何大於幾個像素的「洞」出現時失敗。