在 Mac 上把圖片轉成 ASCII,指的是把本機的 PNG、JPEG、GIF 或 WebP,轉成一格一格的純文字字元——做法是在 Safari、Chrome 或 Firefox 開一個瀏覽器分頁,整個過程不會上傳任何檔案到伺服器。轉換時會先把解碼後的點陣圖畫到一塊畫布上,畫布大小剛好等於預定的 ASCII 格網,每個字元讀取一個 RGBA 像素,再把該像素轉成 W3C 相對亮度,然後對應到一組從 @ 開始、依序遞減到空格的十級字元組。輸出寬度必須是 10 到 200 之間的整數字元數,列數則依原始長寬比計算,並加上 0.5 個字元格的修正,完整序列化後的輸出上限為 50,000 個字元(含換行)。檔案編碼後的大小最多 15 MiB,解碼後任一邊不得超過 8,192 像素,總面積不得超過 2,400 萬像素,這樣才能讓瀏覽器分頁的記憶體用量保持在可預測範圍。圖片、像素、產生的文字和檔名都不會離開當下的分頁,所以在共用的 Mac、公司筆電或個人裝置上使用都能保有隱私。

image to ascii on mac
在 Mac 上把圖片轉成 ASCII:一套本機瀏覽器工作流程

為什麼瀏覽器分頁是 macOS 上最簡單的做法

在 macOS 上,你當然可以用 Python 腳本、shell 管線 或原生 App 來產生 ASCII 藝術——這些方法依然有效,也有很多開發者偏愛它們。一套在本機執行的瀏覽器轉檔工具,能讓流程更短、檔案留在你硬碟裡:打開頁面、拖入圖片、設定寬度、複製文字。不需要 pip install、不用 Homebrew 配方,也不必煩惱 Intel 與 Apple Silicon 之間各版本 macOS 的指令差異。輸出是純等寬字元,可以乾淨地貼到 TextEdit、Mail、Notes、Slack、Discord、終端機視窗,或任何 Markdown 文件,不會出現意料之外的顯示問題。解碼後的圖片、產生的文字和來源檔名全部留在同一個分頁——不會送到任何伺服器、不需要帳號,也沒有任何登入程序。

近期版本 macOS 上的 Safari 原生就能解碼 PNG、JPEG、GIF 和 WebP,這點很重要,因為這個工具確實是在瀏覽器裡解碼,而不是只看副檔名就照單全收。Chrome、Firefox 和 Arc 對這四種格式的處理方式也相同。如果你中途切換瀏覽器,每次重新挑選檔案時頁面都會重新解碼,所以從 Safari 換到 Chrome,或反過來,都不會留下需要清除的舊狀態。

支援的格式與瀏覽器的解碼上限

這個 Image To Ascii 工具能讀取 PNG、JPEG、GIF 和 WebP,而且它是在瀏覽器裡實際解碼每個檔案,而不是看副檔名或 MIME 類型就照單全收。只有瀏覽器分頁會碰你的圖片,所以下表的限制指的是你 Mac 瀏覽器能處理的範圍,而不是遠端服務願意接受的大小。

格式編碼後檔案上限解碼後邊長上限解碼後面積上限
PNG15 MiB8,192 px24,000,000 px
JPEG15 MiB8,192 px24,000,000 px
GIF15 MiB8,192 px24,000,000 px
WebP15 MiB8,192 px24,000,000 px

這些限制是為了防止分頁在解碼後意外佔用過多記憶體,即使壓縮檔本身很小也一樣。格式損壞、不支援的編碼設定檔,或任何超出這些限制的情況,都會清掉先前的所有 ASCII 結果,而且不會產生半成品。來源尺寸會與寬度設定分開檢查,所以在解碼進行中更改輸出寬度,不會讓一個舊的寬度值決定圖片是否被接受。

在 Mac 的 Safari 中把圖片轉成 ASCII

  1. 在 Safari、Chrome、Firefox 或 Arc 中打開 Image To Ascii 頁面——任何現代的 macOS 瀏覽器都可以。
  2. 點擊檔案選擇按鈕,從你的 Mac 選一個 PNG、JPEG、GIF 或 WebP。瀏覽器必須先解碼檔案,才會進行任何轉換。
  3. 在寬度欄位輸入 10 到 200 之間的整數輸出寬度。工具會拒絕小數、負號、科學記號、空白字元或超出範圍的值——請輸入像 80、120 或 160 這種乾淨的整數。
  4. 如果想讓亮部得到密集字元、暗部得到稀疏字元,可以切換反向字元組選項。預設是從 @ 到空格的對應,保持關閉即可。
  5. 產生 ASCII 結果。解碼後的畫面會被畫到一塊畫布上,畫布大小符合預定的欄數與列數,每個字元讀取一個像素,使用 getImageData,再把每個像素對應到字元組中的一個符號。
  6. 用複製按鈕複製顯示出來的內容,或用下載按鈕下載 TXT 檔。兩者產生的字元完全相同;TXT 還會儲存列與列之間的換行字元。

如果檔案是動圖,只會轉換解碼後的第一幀——動畫的其餘部分會在產生任何 ASCII 之前被丟棄,這樣在你調整寬度或字元組方向時,預覽能保持穩定。更改寬度、字元組方向或來源檔案時,舊的文字下載網址會被撤銷,先前的結果、複製狀態和錯誤也會一併清除,所以顯示出來的輸出永遠符合當下的設定。

像素在 Mac 上如何變成字元

畫布填入縮放後的來源圖片之後,會透過瀏覽器的 getImageData 呼叫,每個輸出格讀取一個 RGBA 像素。每個像素的 sRGB 通道會先透過 W3C 相對亮度轉換函式線性化,再用標準的 0.2126 / 0.7152 / 0.0722 通道權重組合。Alpha 會在公式執行前先與白色合成,所以完全透明的區域在預設字元組下會被當成白色,而不是產生一片黑色空洞——這對於 PNG 圖示、去背圖,以及含有陰影的截圖特別有用。

得到的亮度值(介於 0 到 1 之間)會乘以 9 再四捨五入,從十個字元組中挑選一個。預設字元組從 @ 開始,依序遞減到越來越亮的符號,最後是空格;反向切換則會把同一組字元組反過來,讓亮部得到密集字元、暗部得到稀疏字元。具體的字元是工具固定密度字元組的一部分,所以轉換是確定性的——同一個像素在相同設定下,永遠會對應到同一個符號。縮放品質由瀏覽器實作,不同引擎間可能略有差異,特別是在高頻紋理或非常激進的縮減下,因此「像素對應字元」的演算法才是穩定的核心行為,並不宣稱不同瀏覽器間重採樣的像素完全一致。

輸出寬度、長寬比與 50,000 字元上限

你輸入的輸出寬度就是欄數,列數則依來源長寬比計算。等寬字型的字格通常高度約為寬度的兩倍,因此工具會計算 (圖片高度 ÷ 圖片寬度) × 輸出寬度 × 0.5,再四捨五入到最接近的整數列,且最少一列。完整序列化後的輸出——寬度 × 列數,再加上 (列數 − 1) 個換行字元——不得超過 50,000 字元。請求的寬度絕不會被悄悄截斷;像 9、201、100.5、" 100 " 或 "1e2" 這類輸入會被拒絕,避免檔案以一個跟你要求不同的尺寸通過檢查。

以一張 1200 × 800 的來源圖、寬度 100 為例:

  • 列數 = round(800 ÷ 1200 × 100 × 0.5) = round(33.33) = 33
  • 序列化大小 = 100 × 33 + (33 − 1) 個換行 = 3,332 字元

這個結果離 50,000 字元上限還很寬鬆。狹長的來源圖會更快撞到上限,因為列數同時受寬度和長寬比影響,所以當預估結果超過預算時,工具會回報上限並且不產生預覽或下載。降低寬度可以讓總量回到上限內;把圖片裁成更橫向的形狀也是另一種做法。像 1170 × 2532 的 iPhone 截圖這種高瘦比例,在寬度 200 時會產生約 43,400 字元(216 列 × 200 欄 + 215 個換行 = 43,415),仍在 50,000 上限以內。更極端的長寬比在最大寬度下可能會超出預算,所以對高瘦來源來說,寬度控制比寬廣風景照更為關鍵。

把結果貼到 TextEdit、Notes 或終端機

複製按鈕會把完整的 ASCII 格網放進剪貼簿,並附上產生狀態與掛載狀態的防護,避免稍後的編輯讓舊的「已複製」提示復活。下載按鈕會建立一個 TXT Blob 網址,內容只有 ASCII 字元和列與列之間的換行——不含顏色、透明、動畫、中繼資料、相機資訊、圖層、嵌入的色彩設定檔,也沒有原始壓縮圖片。TXT 在 TextEdit 能直接開啟,而 macOS 上瀏覽器的預設下載位置會把檔案放到你的 Downloads 資料夾,與你存放來源檔的位置相鄰。

想在 Mac 上呈現最佳效果,請把文字貼到 TextEdit,並使用等寬字型搭配緊湊的行高——Menlo、Monaco、SF Mono 或 IBM Plex Mono 都能清楚顯示。列數公式中的 0.5 字元格修正是實用的預覽近似值,並不是對你字型的實際測量,所以不同的字型、縮放等級或終端機行高,可能讓下載後的成果看起來比預覽更高或更矮。只要在乎視覺精細度或需要保存原始資訊,就請保留原始圖片,因為 TXT 無法還原來源。

工具拒絕圖片的時機與處理方式

通過格式檢查失敗的檔案——副檔名錯誤、檔頭損壞,或是不支援的編碼設定檔——會清掉先前的所有 ASCII 結果,並在原位顯示原因。即使能順利解碼,只要單邊超過 8,192 像素、總面積超過 2,400 萬像素,或編碼後超過 15 MiB,也會被拒絕且不產生半成品。當高解析度的 Mac 照片觸發這些限制時,先用 Image Resizer 處理一次再轉換,可以把尺寸控制在上限內;先用 Image Compressor 處理一次,則可以把編碼後大小控制在 15 MiB 以內。兩個工具都在同一個瀏覽器分標籤中本機執行,所以整個流程全程保持私密。

即使來源圖片帶有相機、鏡頭或 GPS 中繼資料,這些內容同樣不會進入 ASCII 輸出——TXT 只包含字元和換行,所以轉換步驟天生就不含中繼資料,不需要額外的 EXIF 處理。

如果你正在比較方案,Optimize GIF to 200KB:A Browser Palette Workflow 對此有詳細說明。

如果你正在比較方案,Add Shadow to Image Locally:A No-Upload Browser Workflow 對此有詳細說明。