TechMoon 科技月球
WordPress、SEO 與 AI 工具實測指南
TechMoon 科技月球
WordPress、SEO 與 AI 工具實測指南

SandPhoto 是 2014 年就出現的開源證件照排版工具,2025 年改寫成純瀏覽器版本,照片從上傳、排版到輸出全程留在本機,實測完整流程零對外連線。台灣 2 吋照片對應小二寸規格,4×6 沖印選 6 寸(4R)相紙,一版可排 6 張。官方網站目前連不上,把原始碼跑在本機就能繼續用。
用 AI 摘要這篇文章:
把 SandPhoto 的原始碼從 GitHub 抓下來,在本機開一個臨時網址,上傳一張 960×1280 的人像照,規格選小二寸、相紙選 6 寸(4R),按下生成。下載資料夾裡出現一張 3590×2409 的相紙圖,整整齊齊排了 6 張二吋大頭照,右下角烙著開發者的網址。回頭看側錄:整個流程瀏覽器只發出 6 個網路請求,對象全部是本機的靜態檔案,沒有任何對外連線,也沒有任何 POST。照片不出瀏覽器這句話,在這個工具上是量得出來的。
更有意思的是入口的變化。SandPhoto 的官方網站目前從台灣本機加上德國、美國、伊朗、新加坡四個海外探測節點測過去,全部連線逾時;網頁存檔服務最後一次成功收錄它的工具頁,停在 2026 年 4 月。網站進不去,工具卻活得好好的:原始碼 2026 年 9 月還有提交,而它能在官網斷線後繼續用,靠的正是 2025 年那場把整個工具搬進瀏覽器的改寫。
先講清楚現況,這直接決定你怎麼用這個工具。
sandcomp.com 這個站目前是全球性連不上,不是台灣單方面的網路問題。我用四個國家的第三方探測節點交叉確認,全部回報連線逾時,本機直接連也一樣。網頁存檔紀錄顯示這個站至少到 2026 年 4 月都還正常運作,2025 年 10 月還有使用者在 GitHub 回報站上捐贈連結失效,代表那時候站是活的。斷線發生在 4 月之後的某個時間點,原因沒有公告,開發者也沒有在 repo 裡提。
翻舊倉庫的 issue 紀錄還會發現,網站不穩對這個專案不算新聞。2024 年 12 月就有人開了一條「URL is down」回報網站連不上,那條 issue 後來被關掉,網站也確實活過來了。所以這次是不是同一種暫時性斷線,沒有人說得準,差別在於現在就算網站永遠不回來,工具本身也不受影響,後面會講到為什麼。
GitHub 上是另一番景象。新的 sandphoto-js 倉庫 2026 年 9 月 11 日還有推送,功能開發沒停:多張照片混合排版、照片間距調整,最近一次補上的是下載失敗的錯誤提示,都是過去一年陸續加進來的。舊的 PHP 倉庫則在 2025 年 7 月 15 日最後一次推送後就沒再動過,README 掛著一行告示,要大家去看新的純瀏覽器版本。
一個 2014 年就出現、累積 888 顆星的專案,就這樣把重心從舊倉庫(277 個 fork)搬到新倉庫(93 顆星、38 個 fork)。星數掉了將近九成,但這更像是搬家後重新開始計數,人沒有散,程式還在長。
既然官網連不上,用這個工具的方式只剩一種,而這種方式恰好簡單到不像話。
新倉庫是一個純靜態網頁:一個 index.html,幾支 JavaScript,沒有 package.json、沒有建置步驟,相依套件一個都不用裝。任何能開資料夾的工具都能把它跑起來:
git clone https://github.com/gmajian/sandphoto-js.git
cd sandphoto-js
python3 -m http.server 8923
然後用瀏覽器打開 http://localhost:8923,就是完整的工具。不想裝 git,可以直接在 GitHub 頁面下載 ZIP 解壓縮;不想用 Python,換任何靜態檔案伺服器都行。我自己的測試環境就是這樣架的:macOS、Python 3 內建的 http.server、無頭 Chromium,從 clone 到看到介面不到一分鐘。

這種零依賴的純靜態結構,附帶一種很少被提起的長壽性。沒有 node_modules 會爛掉,沒有框架版本會過期,十年後有人把這包檔案撈出來,只要瀏覽器還認 JavaScript,它就還能跑。倉庫裡甚至留著開發者自己用的測試頁(tests.html),不依賴任何測試框架,點開就跑,這種工程習慣在個人專案裡不算常見。
這段流程的背後是一次徹底的架構搬家。2025 年之前,SandPhoto 是一個 PHP 網站服務:你把照片傳到它的伺服器,伺服器算完把圖傳回來,網站掛了服務就沒了。改寫之後,所有運算都在你的瀏覽器裡用 Canvas 完成,開發者的伺服器從必要環節變成可有可無的入口。官網斷線對它造成的實質傷害,只剩下「新使用者找不到入口」這一條。
隱私是這類工具最常被拿來宣傳的點,也是最常灌水的地方,所以直接看數字。
我在瀏覽器裡跑了完整流程:載入頁面、上傳人像照、選小二寸、選 6 寸(4R)相紙、生成、下載,每個步驟之間的網路請求全部側錄下來。結果是 6 個請求,全部是向本機伺服器要靜態檔案(頁面本身、樣式表、四支 JavaScript),對外連線 0 個,POST 0 個。
其中 POST 等於 0 這一項最關鍵。瀏覽器要把檔案送到任何伺服器,實務上都會以 POST 或 PUT 的形式出現在請求紀錄裡。側錄裡一個都沒有,就代表照片從頭到尾沒有離開這台電腦的機會,這比「我們重視您的隱私」之類的頁面宣示硬得多。照片從讀入、縮放、排版到輸出,全程在記憶體裡的 Canvas 上完成,存檔的那一步也只是把 Canvas 內容寫成本機檔案。
原始碼層面可以對上這個結果。整支 app.js 掃過去,唯一的外部網路依賴是 AI 去背功能:按下去背時,它會從 esm.sh 這個公開 CDN 引入 @imgly/background-removal 套件,版本鎖在 1.7.0 不讓它自動漂移。原始碼註解寫得很白:只有模型是遠端下載,照片在本地處理。而且這個依賴是惰性載入,純排版的流程根本不會碰到它。
這裡要把兩個常被混為一談的宣稱拆開:「零網路請求」和「照片不上傳」不是同一件事。前者指完全不連外,後者指可以有連線但照片不出門。SandPhoto 的排版流程是前者,去背功能是後者(模型下載進來、照片不出去)。如果完全斷網使用,排版照常,去背會失敗。
去背這條路的定位也想清楚講:它是輔助,不是主力。@imgly 這個套件是把去背模型編譯成 WebAssembly 直接在瀏覽器裡跑,這類模型的邊緣處理對頭髮絲這種細節本來就吃力,正式證件照的底色要求又高(多數機關要求純白且無陰影),真的要一張合格的證件照,自拍換底的完整工作流還是交給專門的製作工具。介面上另有背景填色的下拉選項,去完背補純色底用,同樣是輔助性質。
輸出品質也有數字可看。生成的相紙圖是 3590×2409 像素,對應 15.2×10.2 公分的 6 寸相紙,換算下來約 600 DPI,超過一般沖印店 300 DPI 的要求,放大沖印不會糊。輸出為 JPEG 檔,檔名會自動標上這版排了幾張、什麼規格、用什麼相紙,印出來之前對帳很方便。單張照片的裁切位置在預覽區看得到,介面也會自動算出這張相紙塞得下幾張。

右下角那個浮水印是另一回事。開發者網址的灰色小字固定烙在輸出圖的右下角,顏色是低調的 #888888,但翻遍設定沒有開關可以拿掉,原始碼裡它是寫死的,而且介面語言切成英文時,浮水印會多一個英文版的網址結尾。拿去沖印沒人會注意,要交正式文件的話,自己先看過再決定。
工具內建 57 條規格,名稱是中國慣用語,台灣使用者要自己對照數字,數字對上了其實就是同一批規格。
台灣身分證換發、護照申請、多數表格貼用的 2 吋照片(3.5×4.5 公分),在清單裡叫「小二寸」,數字一模一樣。台灣沖印店最普遍的 4×6 相紙(15.2×10.2 公分),在清單裡叫「6 寸(4R)」。所以「2 吋照片排滿一張 4×6 去沖印」這個需求,在 SandPhoto 裡就是小二寸配 6 寸(4R),實測一版 6 張,自己剪開就是半年的存量。
有個容易踩的坑先提醒:清單裡名字最像的三個,2 寸是 3.8×5.1 公分,大二寸是 3.5×5.0,大一寸是 3.3×4.8,都不是台灣的 2 吋。挑規格時盯著數字選,不要盯著名稱選。清單裡的 1 寸(2.5×3.5 公分)換算下來比台灣早年說的 1 吋照片略小,用得到的場合再對數字。
倒是台灣 2 吋這個 3.5×4.5 的規格,在清單裡的國際區是通行款:加拿大、英國、澳洲的簽證照片全都是同一個尺寸,等於選小二寸一個規格,三國簽證跟台灣證件一起排進同一張相紙。赴美非移民簽證的 5.1×5.1 方形是另一個檔次,清單裡也有。找不到的就用自訂尺寸,直接輸入公分數值,寬高分開填。
規格庫的組成順帶看一下:57 條裡分三大類,證件照規格 14 條、文件類規格(簽證、考試報名)26 條、相紙尺寸 17 條,文件類將近證件照的兩倍。照片規格和相紙是兩個各自獨立的平面下拉清單,沒有分組,找特定規格的時候還是得捲。
規格庫裡有一條「2 吋半身照」,用的是繁體的「吋」字,在一片簡體規格名裡顯得突兀,看起來是哪位台灣或香港貢獻者自己加過一條。這種小痕跡多少說明有人接力過,也間接提示這工具的受眾其實一直比它的中文介面更廣。
相紙選擇也不只 6 寸一種。5 寸(3R)、7 寸(5R)、8 寸到 12 寸、A4、A6、Letter 都在,甚至有佳能 4×6 相紙的專用條目(13.35×8.9 公分,對某些印表機的無邊框設定更準)。新版還支援多照片模式:一次丟進不同規格的照片,混排在同一張相紙上,清單裡逐一管理,對湊不滿一整版的人很實用。照片之間的間距也可以用公釐調整,剪裁時留不留白邊,看個人習慣。
實際拿去沖印的操作就一條路:把輸出的 4×6 檔案原樣丟給沖印店或自助機台,說印 4×6,機器不會再縮放。自己在家印也一樣,選對相紙尺寸、關掉印表機的「自動調整大小」,印出來就是螢幕預覽的那個樣子。剪的時候沿照片邊緣留個一兩公釐,貼到表格上比裁得剛好更耐看,這也是間距設定存在的理由。
這個工作流的經濟帳不用精算也看得出方向:一張 4×6 洗六張 2 吋,跟單張重複洗六次或去相館重拍一組,中間的價差與時間差是倍數級的。當然前提是手上已經有一張合格的照片,這又繞回後面要講的分工問題。
操作上唯一要適應的是介面語言。原始碼內建 10 種語言,英文、日文、韓文、西文、法文、德文、俄文、阿拉伯文、葡萄牙文都有,但出廠的 index.html 把介面寫死成簡體中文,頁面上沒有切換選單,要換語言得改原始碼裡一行的語言設定,而且中文也只有簡體一種。好在詞都不難,照片、紙張、設定這幾個字看懂就能操作;「寸」跟「吋」在畫面上是同一套用語體系,對照時心裡要有數。
這個工具的年紀,正好解釋了今天的局面。
2014 年 2 月,開發者 gmajian 把第一版 SandPhoto 放上 GitHub,那是一個 PHP 程式:照片傳上伺服器,伺服器用 GD 函式庫排版,再把圖傳回來。這個版本累積了 888 顆星,撐了 11 年,斷斷續續有人回報 issue,不少是部署方面的疑難雜症:2020 年有人問能不能部署到 Cloudflare Workers,2023 年有人要 Docker 版,更早還有部署到 Windows IIS 後圖片生成有問題的回報。這些 issue 拼起來的圖像很清楚:大家都想擺脫「自己養一台 PHP 伺服器」的負擔。
2025 年 7 月 15 日,開發者給出了自己的答案,而且比任何一條 issue 要求的都更激進:同一天,舊倉庫最後一次推送、README 掛上新倉庫連結,新倉庫 sandphoto-js 成立,授權從 GPL-2.0 換成 GPL-3.0。新版本用 JavaScript 重寫,直接丟掉伺服器,丟掉 PHP,使用者的瀏覽器就是伺服器。順帶丟掉的還有舊版的歷史包袱:舊倉庫有一條 2024 年 8 月回報的指令注入安全通報,到今天都沒有關閉。這也是「別再自架舊版」的具體理由,要跑就跑新倉庫。
GPL 授權對一般使用者影響不大:自己用、幫家人朋友排照片都沒事;如果改了程式再散布,改動的原始碼要跟著開出來。想拿去包成付費服務的人,先想清楚這條線。
寫到這裡,把這個工具的位置講清楚,因為搜「證件照」進來的人,任務可能和它差一步。
如果你還沒有照片,要的是用手機自拍換白底藍底、裁成規格,那是「製作」,SandPhoto 幫不了你,它的去背只是輔助。這條路可以看之前寫過的 hivisionidphotos(開源證件照製作,可自架)或 幫小忙證件照(線上版,處理流程有透明度分析)。
如果你已經有一張合格的照片,要的是把它排滿相紙拿去沖印,一份 4×6 印 6 張 2 吋,那是「排版」,這正是 SandPhoto 的位置。中間地帶的照片拚貼、創意排版,懶人圖雲 那類工具比它靈活。
也有些情況它幫不上忙:越來越多政府與銀行系統直接上傳單張電子檔,那種需求要把照片裁好存成單張,相紙排版完全用不上;會嚴格審核照片規格的簽證系統,同樣是交單張電子檔的邏輯。它的戰場就是實體沖印,而實體沖印在證件照換發的場景裡,仍然是多數人一年會遇到一兩次的需求。
至於為什麼值得在意照片有沒有出門:證件照是臉部生物特徵加上姓名的組合,一旦外流,冒用與詐騙的風險是長期的,不像一般風景照刪了就算。線上證件照工具百百種,處理前想一下資料流向,是不用成本的基本動作。SandPhoto 把這個問題從「要不要相信對方」變成「不需要相信任何人」,這是純瀏覽器架構真正的價值。
所以適合的輪廓大概是這樣:手邊有照片、要沖印、在意照片不要上傳雲端、願意開一次終端機。四個條件中三個成立,這包原始碼就值得留在硬碟裡。至於官網會不會回來,沒有人知道;但只要原始碼還在 GitHub 上一天,這個工具的壽命就跟你的硬碟綁在一起,不跟別人的網域續約綁在一起。