驅動 RGB 色彩反轉的通道公式為:輸出紅色等於 255 減去輸入紅色、輸出綠色等於 255 減去輸入綠色、輸出藍色等於 255 減去輸入藍色,並套用至每一個解碼後的像素,同時將 alpha 通道原封不動地複製。對於正在搜尋可跨多個檔案反轉影像色彩方式的使用者而言,這項決定性的位元組操作意味著相同的轉換可在批次中針對每張影像可靠地重複——黑色變成白色、白色變成黑色、紅色變成青色、綠色變成洋紅色、藍色變成黃色。Invert Image Colors 工具在瀏覽器中精確地實作了這條規則:挑選一個 PNG、JPEG、GIF 或 WebP 檔案,等待位元組容器偵測與實際的瀏覽器解碼、執行反轉、然後下載一個靜態 PNG。由於每個檔案都是在目前分頁中的獨立工作階段內進行處理,批次或多張影像的工作只需為每張影像重複一次單檔工作流程,迭代之間不需任何上傳步驟。本文的其餘部分將逐步說明通道對應、嚴格的尺寸限制、精確的步驟順序,以及使本地瀏覽器反轉器在批次色彩反轉上實用的隱私保證。

invert image colors bulk multiple images
批次跨多張影像反轉影像色彩

套用至每個像素的通道公式

對於想要精確定義的使用者,RGB 反轉公式既直觀又處於位元組層級:對於瀏覽器解碼器所暴露的每一個像素,工具會將紅色替換為 255 減去輸入紅色、綠色替換為 255 減去輸入綠色、藍色替換為 255 減去輸入藍色。Alpha 通道原封不動地複製,包括半透明值。由於每個通道都是獨立處理,這項操作在一個有用的意義下是可交換且等冪的:套用兩次會返回相同的解碼位元組值,因此使用者無需擔心在同個檔案上按兩次執行按鈕而意外地將批次反轉兩次。

一個實際的範例可以驗證這項算術。一個解碼為 RGB(120, 50, 200) 的像素會變成 RGB(255 − 120, 255 − 50, 255 − 200) = RGB(135, 205, 55),這是一種黃綠色調。相同的操作也定義了一組初學者依賴的小而好記的色彩配對:黑色變成白色、白色變成黑色、純紅色變成青色、純綠色變成洋紅色、純藍色變成黃色。下方表格列出這些標準配對,以及一個中間值和一個近中間值,以便一目了然地看出其中的關係。

輸入色彩名稱輸入 RGB輸出 RGB輸出色彩名稱
純黑(0, 0, 0)(255, 255, 255)純白
純白(255, 255, 255)(0, 0, 0)純黑
純紅(255, 0, 0)(0, 255, 255)純青
純綠(0, 255, 0)(255, 0, 255)純洋紅
純藍(0, 0, 255)(255, 255, 0)純黃
實際範例(120, 50, 200)(135, 205, 55)黃綠色
近中間灰(128, 128, 128)(127, 127, 127)近中間灰

為何單檔瀏覽器反轉器適用於批次工作流程

這項工具的合約是圍繞一次一張影像所建立:挑選檔案、位元組層級的容器偵測、透過 createImageBitmap 進行瀏覽器解碼、邊緣與區域驗證、全畫布反轉、預覽以及 PNG 匯出。這並不表示批次或多張影像的搜尋需求未被滿足。批次工作流程就是將相同的單檔序列對每張影像重複:開啟工具、選擇影像一、下載影像一、選擇影像二、下載影像二,依此類推處理整個批次。每個工作階段都是獨立的,因此單一檔案失敗不會影響其他檔案,且迭代之間沒有任何可能將部分批次外洩到遠端伺服器的上傳步驟。

這也是一項刻意的隱私選擇。讀取、偵測、解碼、像素存取、轉換、預覽以及 PNG 匯出全都發生在目前的瀏覽器分頁內。影像不會被上傳到 Lizely 或傳送至外部服務;選擇另一個檔案會遞增作業世代、關閉先前的 ImageBitmap、撤銷來源與輸出的 ObjectURL、清除舊的錯誤與結果,並重設忙碌狀態,使延遲的解碼或 toBlob 結果無法洩漏到下一次選擇。如需深入了解本地處理的承諾,如何在不上傳影像的情況下反轉其色彩 這份操作指南會從不同角度介紹相同的特性。

支援的輸入、輸出格式與嚴格限制

此工具接受剛好四種格式:PNG、JPEG、GIF 與 WebP。檔案名副檔名、檔案挑選器的篩選條件,以及作業系統的 MIME 標籤一律不會被當作格式憑證採信。相反地,在任何 Canvas 作業開始之前,實際的 ArrayBuffer 會以純結構性的偵測器進行檢查。PNG 需要完整的簽章、第一個 IHDR 結構以及結尾的 IEND;JPEG 需要 SOI、其後的標記以及結尾的 EOI;GIF 需要 GIF87a 或 GIF89a、足夠的邏輯螢幕結構以及結尾區段;WebP 需要精確的 RIFF 位元組計數、WEBP 標記,以及一個大小受限的 VP8、VP8L 或 VP8X 第一區塊。截斷的魔術位元組以及被重新命名的任意檔案在 Canvas 作業開始之前就會先失敗。結構檢查會與實際的瀏覽器解碼搭配:以偵測到的 MIME 標記的 Blob 接著必須透過 createImageBitmap 解碼並回報為正尺寸。

四項相互影響的限制決定此工具是否能完成工作。下方表格精確地依照產品合約所定義的方式列出這些限制。

限制項目門檻執行位置
輸入檔案大小≤ 15 MiB讀取前的回報檔案大小;讀取後的實際 ArrayBuffer 長度
解碼後邊緣(寬度或高度)≤ 8,192 像素createImageBitmap 回報尺寸之後
像素總面積≤ 24,000,000 像素createImageBitmap 回報尺寸之後
輸出 PNG≤ 32 MiBHTMLCanvasElement.toBlob 回傳 Blob 之後

剛好達到邊界的值會被接受;超過一個位元組、一個邊緣像素或一個像素面積級距的值則會被拒絕。這些獨立限制之所以重要,是因為壓縮輸入可能會展開成大型像素緩衝區,而細長的影像即使符合面積限制,也可能超出實際可用的 Canvas 尺寸。不會有任何靜默的縮放、裁切、抽樣或部分處理,輸出始終都是一個完整的 PNG。

如何跨多張影像反轉色彩

每個檔案在工具內都會經過相同的三步驟流程。若要處理批次,請對批次中的下一個檔案重複這些步驟。

  1. 從檔案挑選器中選擇一個 PNG、JPEG、GIF 或 WebP 檔案,並等候瀏覽器回報檔案大小、偵測位元組容器、透過 createImageBitmap 解碼初始畫面,以及驗證寬度、高度與總面積。如果該檔案未通過任何一項檢查,則不會執行反轉,且無需重設分頁即可挑選下一個檔案。
  2. 來源預覽顯示後,執行反轉。工具會讀取 Canvas 所暴露的每一個 RGBA 位置、套用 255 − R、255 − G、255 − B,並將 alpha 原封不動地複製,再將矩陣寫回,並在來源旁邊渲染一個原生尺寸的 PNG 預覽,讓使用者可以並列比較。
  3. 確認顯示的尺寸與回報的輸出位元組大小,然後下載靜態 PNG。在任何時機選擇另一個檔案都會遞增作業世代、撤銷先前的來源與輸出 ObjectURL,並重設忙碌狀態,因此來自前一個檔案的延遲解碼或 toBlob 回呼不會發佈到較新的選擇中。

對於一組類似的檔案——例如一組產品照片、一組 UI 截圖、一疊掃描草圖——實際的節奏是先將批次排序、依序對每個檔案執行步驟 1 至 3,再將下載的 PNG 儲存到對應的資料夾中。由於規則精確且具決定性,對同一個檔案執行兩次會產生相同的位元組。

哪些保持不變、哪些會改變

位元組層級的反轉是精確的,但輸出仍然是與輸入不同的檔案。這項轉換是視覺效果,而非保留中資料的轉換。Alpha 通道原封不動地複製,包括半透明的值,Canvas 所暴露的每一個 RGBA 位置都會被處理,包括 RGB 值為零的 RGB 位置。然而,完全透明的色彩是不可見的,瀏覽器解碼器或 Canvas 可能在 getImageData 回傳之前先行正規化隱藏的 RGB。工具轉換的是 Canvas 實際提供的位元組;它無法恢復從未進入 ImageData 的隱藏來源檔案通道資料。EXIF、GPS、註解、ICC 設定檔以及其他來源中繼資料不會被 Canvas 匯出所保留,因此當這些欄位很重要時,請保留原始檔案。

動畫 GIF 與動畫 WebP 輸入會使用瀏覽器解碼後的初始畫面,並變為單一靜態 PNG。較晚的畫面、時序、循環次數、調色盤與釋放行為都不會被保留。PNG 的檔案大小也可能大於 JPEG、GIF 或 WebP 的來源,特別是針對相片或有雜訊的影像,因此輸入與輸出配額刻意分開設計。此工具並非底片負片修復:它不會將伽瑪線性化、模型化感知互補色、移除橙色遮罩、平衡掃描底片、修正曝光或進行色調分級。

敏感批次的隱私與本地處理

對批次工作流程而言,隱私承諾比對單張影像更為重要,因為批次中可能包含草稿、客戶作品或尚未發表的產品照片。處理管線從不離開瀏覽器分頁:檔案讀取、結構偵測、ImageData 處理、預覽渲染以及 PNG 匯出全部在本機執行。沒有上傳、沒有外部服務、也沒有任何遠端記錄會記下哪個檔案被處理過。成功的解碼並非惡意程式分析、內容審核、作者驗證或影像安全與真實性的證明,因此即使採用本地解碼,當批次來自未受信任的來源時,仍應結合一般的謹慎作法。

清理作業是這項保證的一部分。同步 Canvas 匯出失敗、ObjectURL 建立失敗以及 null 的 toBlob 回呼全部都會進入同一條受保護的失敗路徑,清除忙碌狀態,並且不會留下任何舊的可下載資源。卸載元件會關閉點陣圖並撤銷所有剩餘的 URL,而相同的清理作業也會透過 React Strict Mode 的 effect setup 與 cleanup 週期加以執行,因此在新檔案被選擇後,先前檔案的過時下載結果不會出現。

當批次工作流程停止或拒絕檔案時

由於每個檔案都是獨立驗證的,因此單一檔案的失敗並不會中止整個批次。最常見的拒絕原因很容易辨識。通過位元組容器檢查的檔案 —— 例如魔術位元組被截斷、BMP 或 TIFF 副檔名被更改、WebP 損毀,或是使用了不支援的格式 —— 會在任何 Canvas 處理之前就被拒絕,並且永遠不會進入預覽階段。解碼乾淨但在任一邊緣上超過 8,192 像素,或總像素面積超過 24,000,000 像素的檔案,會在解碼之後被拒絕。大於 15 MiB 的檔案會在讀取之前就被拒絕,而後也會檢查實際的 ArrayBuffer 長度,因此謊報大小的檔案無法蒙混過關。

有兩個結構上的細節值得在批次作業中特別留意。首先,一張狹長的影像可能雖然在面積限制之內,卻超過 8,192 像素的邊緣限制,因此這兩項檢查刻意保持獨立,且兩者都必須通過。其次,壓縮後的輸入在解開後可能會展開成龐大的像素緩衝區,這就是為什麼除了位元組限制之外還要檢查面積限制。輸出本身也有其預算:編碼為 null Blob、無效大小,或是大於 32 MiB 的 Blob 的 Canvas,會在結果 URL 發佈之前就失敗,因此下載按鈕永遠不會指向不完整或過大的檔案。輸出永遠不會被截斷,也不會被悄悄轉換為有損格式,而輸入與輸出的預算則是刻意分開的。