Jisui (自炊) 처리 규칙
스캔 이미지 → ZIP / CBZ / PDF 변환 규칙입니다. 책뿐만 아니라 잡지, 문서, 노트 등 모든 스캔 대상에 적용됩니다. 이 스킬은 출력 파일의 이름이나 위치를 결정하지 않습니다. 호출자(프로젝트의 CLAUDE.md 또는 사용자 지침)를 따르고, 둘 다 명시되지 않으면 사용자에게 물어보세요.
주어진 경로
인수: $ARGUMENTS
먼저 주어진 경로(스캔 폴더, 이미지 파일 또는 PDF)를 읽으세요. 아무것도 주어지지 않으면 현재 디렉토리(.)를 사용하세요 — 단, 요청 자체에서 스캔 이름을 지정한 경우는 예외입니다. 그런 다음: 각 경로를 재귀적으로 나열하고(하위 폴더, 파일 이름, 확장자, 개수, 일부 파일의 이미지 크기/DPI), 몇 개의 이미지를 살펴보세요(처음, 마지막, 중간 몇 개). 이를 통해 구조를 파악합니다(예: 폴더당 한 권 또는 한 폴더에 여러 권, 표지/뒷표지/재킷/본문 페이지로 보이는 파일, 홀짝 페이지 분할, 중복 또는 불필요한 파일) — 그리고 구체적인 jisui 계획(권, 페이지 순서, 표지/뒷표지/재킷 출처, 제안 옵션)을 제안하세요. 이 계획을 아래 질문에 포함시켜 사용자가 한 번에 확인하거나 수정할 수 있도록 하세요.
시작 전
호출자가 아직 결정하지 않은 사항에 대해 사용자에게 질문하세요(한 번의 AskUserQuestion 호출):
- 출력 형식: ZIP / CBZ / PDF.
- 표지(앞표지): 배치 — 출력물의 첫 페이지 / 사용 안 함 / 출력물 옆에 별도 파일; 그리고 출처 — 사용자가 제공한 파일 / 첫 번째 스캔 / 재킷 앞면 / 웹에서 찾은 이미지.
- 뒷표지: 배치 — 재킷 전 마지막 페이지 / 사용 안 함 / 출력물 옆에 별도 파일; 그리고 출처 — 사용자가 제공한 파일 / 마지막 스캔(재킷이 마지막 스캔인 경우 재킷 전) / 재킷 뒷면 / 웹에서 찾은 이미지.
- 재킷(커버 재킷 스캔 또는 이미지): 동일한 두 가지 질문; 출처 — 사용자가 제공한 파일 / 마지막 스캔 / 웹에서 찾은 이미지.
스캔에서 가져온 출처는 배치가 "사용 안 함"인 경우에도 본문 페이지에서 제외됩니다(처리되거나 보관되지 않음). 표지/뒷표지/재킷 출처가 없으면 모든 스캔이 본문 페이지입니다. 웹 이미지의 경우 스캔과 일치하는 에디션(제목, 출판사, ISBN이 보이면 ISBN)을 검색하여 가장 큰 버전을 스크래치 영역에 다운로드하고, 사용자에게 보여준 후 사용 전에 확인을 받으세요.
페이지 처리
- 표지 / 뒷표지 / 재킷("시작 전"에서 결정된 대로). 아래 모든 단계는 본문 페이지에만 적용됩니다.
- 표지: 그대로 사용, 처리하지 않음(색상 유지, 크기 변경 없음). 포함 → 첫 번째 페이지. 재킷 앞면: 세로로 놓인 재킷에서 앞면 패널의 열 X0–X1을 찾습니다(등 접힘과 앞날개 접힘 사이, 왼쪽 제본 책의 경우 등 오른쪽, 오른쪽 제본/세로쓰기 책의 경우 등 왼쪽) — 해당 영역만 자르고 전체 높이 유지(색상 유지).
- 뒷표지: 표지와 동일. 포함 → 마지막 본문 페이지 다음(재킷 전). 재킷 뒷면: 뒷면 패널, 뒷날개 접힘과 등 접힘 사이(앞면 패널과 반대쪽 등).
- 재킷: 올바른 방향으로만 회전(색상 유지, 크기 변경 없음). 픽셀 단위로 정확하게 회전; JPEG의 크기가 무손실 회전을 허용하지 않으면 PNG를 사용하세요. 포함 → 마지막 페이지; PDF에서 해당 페이지만 실제 크기(DPI 기준)로 만듭니다.
- 별도 파일: 출력물 옆에
<출력 이름>-cover.<확장자>/<출력 이름>-back.<확장자>/<출력 이름>-jacket.png로 저장하며, 스크립트가 쓴 그대로 유지합니다.
- 기울기 보정: 각 페이지에 대해 ±3° 범위 내에서 0.1° 단위로 기울기를 감지하고 보정합니다.
- 회전(줄이 기울어짐)과 전단(줄은 수평이지만 텍스트 블록의 왼쪽/오른쪽 가장자리만 기울어짐 — 시트 피더에서 종이가 옆으로 미끄러질 때 발생)을 별도로 감지하고 보정합니다.
- 텍스트가 적은 페이지(타이틀 페이지, 하프 타이틀, 짧은 페이지)는 기울기를 안정적으로 확인할 수 없으므로 보정하지 않습니다.
- 여백 최소화: 텍스트 블록의 모든 면에 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에 목차 북마크(개요)를 추가합니다.
- 목차 페이지를 읽고 TOC와 동일한 계층 구조(서문, 후기, 해설, 주석, 색인 등 TOC에 있으면 포함)로 부/장/절을 추가하며, 표제는 인쇄된 그대로 사용합니다. 먼저 TOC 페이지를 가리키는 목차 자체의 항목을 추가합니다. 페이지 번호가 없는 부/장은 해당 타이틀 페이지나 표제가 있는 페이지를 가리킵니다.
- 인쇄된 페이지 번호와 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(B&W)(--gray 사용 시 B&W 없이 페이지가 그레이스케일로 유지, --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만 변경합니다(및 이를 보완하는dcterms:*/file-as메타); 다른 것은 건드리지 않습니다. ZIP 항목 순서와 압축 방법을 유지하고,mimetype은 첫 번째에 압축하지 않고 다시 작성합니다. Standard Ebooks의 부제목 / 긴 제목 항목은 그대로 둘 수 있습니다. - CBZ:
ComicInfo.xml(<Title>,<Writer>)을 아카이브 끝에 저장(zip -0)하여 추가하고, 이미지 항목은 변경하지 않습니다. 오른쪽에서 왼쪽으로 읽는 책(일본어 세로쓰기, 만화)의 경우 사용자가 확인하면<Manga>YesAndRightToLeft</Manga>도 추가하세요. - ZIP(스캔 이미지): 메타데이터가 없으므로 건너뜁니다.
- 스크래치 영역의 사본에서 작업하고 확인(페이지 수/항목 변경 없음, 메타데이터 읽기 결과가 주어진 값과 일치)한 후 원본 파일을 교체합니다. 교체는 사용자 파일을 덮어쓰므로, 호출자가 승인하지 않은 경우 먼저 확인하세요.