Jisui (自炊) 處理 是做什麼的?
掃描影像 → ZIP / CBZ / PDF 的規則。不僅適用於書籍,也適用於任何掃描文件(雜誌、文件、筆記等)。 此技能不會決定輸出檔案的名稱或位置。請遵循呼叫者(專案的 CLAUDE.md 或使用者指示);若兩者均未指定,則詢問使用者。
給定路徑
引數:$ARGUMENTS
首先讀取給定的路徑(掃描資料夾、影像檔案或 PDF);若未給定任何路徑,則使用當前目錄 (.) — 除非請求本身就指定了掃描檔案。然後:遞迴列出每個路徑(子資料夾、檔名、副檔名、數量、部分檔案的影像尺寸/DPI),並查看少量影像(第一張、最後一張及中間幾張)。據此推斷結構 — 例如每個資料夾對應一卷或一個資料夾包含多卷、哪些檔案看起來像封面 / 封底 / 書衣 / 內頁、奇偶頁拆分、重複或雜散檔案 — 並提出具體的 jisui 計畫(卷數、頁面順序、封面/封底/書衣來源、建議選項)。將該計畫整合到下方問題中,讓使用者一次確認或修正。
開始前
詢問使用者(一次 AskUserQuestion 呼叫)尚未由呼叫者決定的項目:
- 輸出格式:ZIP / CBZ / PDF。
- 封面(前封面):位置 — 輸出的第一頁 / 不使用 / 輸出旁的獨立檔案;來源 — 使用者提供的檔案 / 第一張掃描 / 書衣的前半部分 / 從網路上找到的影像。
- 封底:位置 — 書衣前的最後一頁 / 不使用 / 輸出旁的獨立檔案;來源 — 使用者提供的檔案 / 最後一張掃描(若書衣為最後一張掃描,則為書衣前的掃描)/ 書衣的後半部分 / 從網路上找到的影像。
- 書衣(封面書衣掃描或影像):同樣的兩個問題;來源 — 使用者提供的檔案 / 最後一張掃描 / 從網路上找到的影像。
來自掃描的來源即使其位置設為「不使用」,也會從內頁中移除(不會被處理或保留)。若無封面/封底/書衣來源,則每張掃描皆為內頁。對於網路影像,請搜尋與掃描匹配的版本(書名、出版社、可見的 ISBN),下載最大版本至暫存區域,顯示給使用者並在獲得確認後使用。
頁面處理
- 封面 / 封底 / 書衣(依「開始前」的決定)。以下所有步驟僅適用於內頁。
- 封面:原樣使用,不經處理(仍為彩色,尺寸不變)。若包含 → 作為第一頁。 若來源為書衣前半部:檢視豎直的書衣,找到前封面的欄位 X0–X1 — 即書脊摺痕與前摺口之間的區域(左裝書為書脊右側,右裝書/直排書為書脊左側)— 並僅裁切該區域,高度全保留(仍為彩色)。
- 封底:與封面相同。若包含 → 位於最後一頁內頁之後(書衣之前)。若來源為書衣後半部:後封面欄位,介於後摺口與書脊摺痕之間(與前封面位於書脊的對側)。
- 書衣:僅旋轉至正確方向(仍為彩色,尺寸不變)。精確旋轉;若 JPEG 的尺寸不支援無損旋轉,則使用 PNG。若包含 → 作為最後一頁;在 PDF 中,僅該頁使用實際尺寸(依其 DPI)。
- 獨立檔案:儲存在輸出旁,命名為
<輸出名稱>-cover.<ext>/<輸出名稱>-back.<ext>/<輸出名稱>-jacket.png,保留腳本輸出的原樣。
- 歪斜校正:對每一頁,以 0.1° 為步長檢測 ±3° 內的歪斜並校正。
- 分別檢測並校正旋轉(文字行傾斜)和剪切(文字行水平但文字區塊左右邊緣傾斜 — 這在紙張於饋紙器中橫向滑動時發生)。
- 文字量少的頁面(標題頁、半標題頁、短頁)無法可靠檢測歪斜,因此不對其進行校正。
- 邊距最小化:修剪至文字區塊每側僅保留 2mm(300dpi 下為 24px)的邊距。
- 不包含掃描器陰影、頁緣細線或文字區塊內的小斑點。淡化頁緣的陰影和線條。
- 統一尺寸:同一卷的所有內頁獲得相同尺寸。
- 每卷決定一個裁切框大小,並逐頁定位以適應該頁的文字區塊(文字區塊位置在每次掃描間會有數 mm 的偏移)。文字量少的頁面(標題頁、章首頁、短頁)則使用相鄰同側(奇/偶)頁面的位置,以保持其原始版面。
- 超出框的頁面會稍微縮小以適應。
- 僅在指示時:將整頁插圖、標題頁等圖片頁面從內頁框中取出,給予與內頁框同高但較寬的共享圖片頁框(
--picture)。這可在內頁上實現更小的邊距。
- 空白頁:不跳過,保留為空白頁。
- 保留所有頁面:不刪除任何頁面,包括廣告。
- 黑白:僅在指示時進行黑白二值化(這是有損的,因此預設不執行)。
- 對文字進行二值化,但不對照片、插圖等影像區域進行二值化;這些區域保留灰階。
- 使用閾值 200(0–255;比此暗的像素變黑)作為基準。自動選擇(Otsu,約 160)會使文字過淡。
- 處理後,報告所使用的閾值並詢問使用者該值是否合適。
- OCR:僅在指示時,為 PDF 新增 OCR 文字層(
ocrmypdf -j 2 -l jpn+eng --output-type pdf,影像不變;根據內容語言調整-l,例如韓文使用kor+eng)。Apple OCR 在頁數過多時容易超時,因此使用qpdf拆分為 50 頁的區塊,對每個區塊進行 OCR,僅重做失敗的區塊,然後合併。- 重複使用時,Apple OCR (LiveText) 可能會在中途無聲地開始回傳空文字層而無任何錯誤。在合併前,使用
pdftotext檢查每一頁以確認已提取文字;對於內頁為空的區塊,稍等片刻後重做。若仍未解決,請重新啟動 Mac。
- 重複使用時,Apple OCR (LiveText) 可能會在中途無聲地開始回傳空文字層而無任何錯誤。在合併前,使用
- 書籤(索引):僅在指示時,為 PDF 新增目錄書籤(大綱)。
- 讀取目錄頁,並以與目錄相同的層級結構新增部/章/節,標題完全按照印刷內容(若前言、後記、註解、索引等出現在目錄中,也包含它們)。首先為目錄本身新增一個條目,指向目錄頁。目錄中無頁碼的部/章則指向其標題頁或包含其標題的頁面。
- 透過在多個位置讀取頁碼,確定印刷頁碼與 PDF 頁面之間的對應關係。此對應關係可能發生偏移(例如因卷首插圖),因此對於每個頂層條目及部分低層條目,檢查其標題確實出現在目標頁面上。
- 使用
pikepdf以與中繼資料編輯相同的程序(不重新壓縮影像)編寫,並設定/PageMode /UseOutlines。編寫後重新讀取以驗證。若無目錄,則不新增書籤,並告知使用者。
執行
uv run <此技能的資料夾>/scripts/jisui.py <影像資料夾> <輸出資料夾> [--threshold N | --gray | --color] [--no-deskew 1,12,...] [--picture 3,24,...] [--dpi N] [--cover first|FILE|jacket:X0-X1] [--back last|FILE|jacket:X0-X1] [--jacket last|FILE] [--jacket-rotate 0|90|180|270] 執行步驟 0(--cover:將第一張掃描或 FILE 原樣複製為 0000.<ext>,或使用 jacket:X0-X1 裁切直立書衣的這些欄位為 0000.png(需配合 --jacket);--back:同上,用於封底,取自最後一張掃描(取自書衣之前),寫入內頁之後作為 NNNN.<ext>(若從書衣裁切則為 .png);--jacket:取最後一張掃描或 FILE,順時針旋轉 --jacket-rotate 度,並寫入作為最後的 NNNN.png;無論其位置如何,每當有封面/封底/書衣來源時均傳入這些選項)、步驟 1–3 和步驟 6(黑白)(使用 --gray 時不進行黑白轉換,頁面保持灰階;使用 --color 時頁面保持彩色),並寫入頁面影像 (PNG) 及報告(<輸出資料夾>-report.json:閾值、裁切框尺寸、空白/縮小頁面及包含灰階區域的頁面)。頁碼為輸出編號(NNNN.png;封面為 0,第一頁內頁為 1)。將不進行歪斜校正的頁碼傳入 --no-deskew,將圖片頁碼傳入 --picture(報告中也會提供圖片頁框尺寸;高度與內頁相同,因此一個 --imgsize 就足夠)。將工作輸出放在暫存區域;切勿寫入原始掃描檔案或使用者的資料夾。
- 不假設任何裁切尺寸。預設會最小化邊距並使內頁尺寸統一。mm↔px 轉換的解析度來自影像的 DPI 標籤;若無標籤或標籤低於 150(如佔位的 72),則假設為 300dpi(否則傳入
--dpi N)。 - 製作 PDF 時,使用
img2pdf --imgsize x<裁切框高度 mm>設定尺寸(輸出的 PNG 不攜帶 DPI 資訊)。單獨構建封面-書衣頁面(不使用--imgsize,依其 DPI 標籤使用實際尺寸)並使用pikepdf附加。 - 處理後,以影像形式查看少數頁面(歪斜、修剪、二值化),並確認報告中的空白/縮小頁面合理後再產生輸出。
輸出
包裝前,將位置設為「不使用」或「獨立檔案」的封面/封底/書衣影像從頁面集合中移除(並依步驟 0 儲存獨立檔案)。
- ZIP:將處理後的頁面影像放入壓縮檔的頂層,檔名依頁面順序排列。不對影像重新壓縮 (
zip -0)。不包含.DS_Store等檔案。 - CBZ:與 ZIP 相同,副檔名為
.cbz。閱讀器使用第一張影像作為縮圖。僅透過中繼資料編輯新增ComicInfo.xml。 - PDF:與 ZIP 一樣排列相同影像,不重新壓縮 (
img2pdf)。OCR 依步驟 7,書籤依步驟 8。 - 模式名稱:由內頁決定 —
color/grayscale/bw(僅彩色封面不構成color)。若有 OCR 層則加上+ocr,若有書籤則加上+toc(ZIP/CBZ 從不新增)。是否將其放入檔名由呼叫者決定。
中繼資料編輯(標題 / 作者)
從呼叫者(目錄、使用者)取得值。切勿猜測並填入。
- 僅標題和作者欄位。請勿將譯者放入作者。
- PDF:將標題和作者寫入 Info 字典和 XMP,不重新壓縮頁面 (
pikepdf)。 - EPUB:僅更改 OPF 中的主要
dc:title和每個dc:creator(以及refines它們的dcterms:*/file-as中繼資料);不觸及其他內容。重寫 ZIP,保留條目順序和壓縮方法,mimetype放在首位且不壓縮。Standard Ebooks 的子標題 / 長標題條目可保持不變。 - CBZ:在壓縮檔末尾寫入
ComicInfo.xml(<Title>、<Writer>),存儲模式 (zip -0),保持影像條目不變。對於從右到左的書籍(日文直排文字、漫畫),若使用者確認,也新增<Manga>YesAndRightToLeft</Manga>。 - ZIP(掃描影像):無中繼資料,因此跳過。
- 在暫存區域處理副本,驗證(頁數/條目不變,讀回的中繼資料與給定值相符),然後取代原始檔案。取代會覆蓋使用者的檔案,因此除非呼叫者已批准,否則需先確認。