周三下午,一個開發者往終端里敲了幾行命令。三秒后,一份看起來像是從打印機里抽出來、又在掃描儀上過了一遍的PDF文件出現在桌面上——灰蒙蒙的紙色、輕微的傾斜、邊緣還有陰影。這不是真實掃描的文件。但他確實只用了一條命令。
make-look-scanned 做的事情很直接:它接收一份普通PDF,逐頁將其渲染成圖片,然后把這些圖片塞進一條“效果處理流水線”——傾斜、轉灰度、附上暖色紙張的色調、疊加掃描儀才會有的那種細密噪點、適度失焦、添加邊緣陰影,最后再用JPEG壓縮,讓畫質帶上一絲輕微的損失感。處理完成后,所有圖片重新拼合成一個新的PDF。這個新的PDF里不再有可選中的文字,每一頁本質上就是一張圖——和那種基礎款掃描儀掃出來的文件如出一轍。
![]()
這個工具需要Go和一套C工具鏈才能編譯。它通過go-fitz庫靜態鏈接了MuPDF,所以最終生成的是一個自包含的二進制文件,運行時不需要額外安裝什么東西。編譯過程很簡潔:go build -o make-look-scanned . 就能拿到可執行文件。生成掃描件的命令同樣短——make-look-scanned in.pdf,出來的文件就叫 in.scanned.pdf。如果想起個不同的名字,加上 -o 指定輸出路徑就行。
幾個數字旋鈕控制著掃描效果的“老化程度”。--noise 0.4 可以調整噪點的強度,--skew 2.5 決定頁面傾斜的角度,--jpeg-quality 30 直接指定壓縮質量。每個數值參數調到0,對應的效果就會關掉。默認情況下,輸出是確定性的:種子值從輸入PDF的內容里衍生出來,所以同樣的文件每次都會“掃描”出一模一樣的結果。如果想讓同一個文件產生不同的視覺效果,但又要求這個效果能夠復現,用 --seed N 指定一個種子值——相同的輸入加上相同的種子,輸出就是逐字節完全相同的PDF。
可復用的配置預設可以寫在配置文件里。工具會先去 $XDG_CONFIG_HOME/make-look-scanned/config.toml 找配置,如果這個環境變量沒設,就回退到 ~/.make-look-scanned/config.toml。配置文件里的鍵名和命令行參數名一一對應,只是把連字符換成了下劃線。比如定義一個中等的掃描預設:[presets.medium],skew=1.5,paper_tone=0.6,noise=0.2,blur=0.6,edge_shadow=0.3,jpeg_quality=45。想要用這個預設,一行命令就夠:make-look-scanned --preset medium in.pdf。優先級規則很清晰:內置默認值在最底層,然后是選中的預設,最后是顯式輸入的命令行參數——參數永遠勝出。
整套效果管線同樣能在瀏覽器里跑。go-fitz和MuPDF沒辦法編譯成wasm,所以瀏覽器版本換了個策略:用PDF.js來柵格化頁面,然后把像素數據交給同一套Go效果代碼處理。這些Go代碼加上匯編部分被編譯成wasm,在客戶端完成所有運算。開發時,先運行 ./web/build.sh 編譯出 web/main.wasm 和 wasm_exec.js,然后在 web 目錄下起一個本地服務器就行。真正有意思的是完整構建——執行 task build:web 會生成一個 dist 目錄下的單文件 make-look-scanned.html,大約8MB。這個文件把所有東西都內聯了進去:wasm二進制、Go的運行時膠水代碼、PDF.js的庫文件和worker,統統轉成了base64。用戶不需要服務器,不需要網絡,直接在瀏覽器里打開這個HTML文件就能用。
在線版本和命令行版本的視覺效果基本等同,但因為底層用了不同的PDF渲染引擎,輸出的文件并不是逐字節相同的——PDF.js和MuPDF的柵格化方式天生就不一樣。許可證方面也有區別。命令行工具靜態鏈接了MuPDF,而MuPDF是AGPL-3.0協議,所以整個合并后的二進制文件也得遵循AGPL-3.0——分發它,就要提供對應的源代碼。瀏覽器構建不包含MuPDF,它用的是Apache-2.0協議的PDF.js,情況就簡單很多。
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.