Metadata-Version: 2.4
Name: kindle-pdf-cropper
Version: 0.2.1
Summary: Auto-crop PDF margins / headers / footers and optionally split pages into Kindle-friendly landscape pages (PDF or EPUB output)
Author: ygnid
Maintainer: ygnid
License-Expression: MIT
Project-URL: Homepage, https://github.com/ygnid/kindle-pdf-cropper
Project-URL: Repository, https://github.com/ygnid/kindle-pdf-cropper
Project-URL: Documentation, https://github.com/ygnid/kindle-pdf-cropper/blob/main/README.md
Keywords: pdf,kindle,crop,epub,ebook,margins,header,footer,ebook-reader
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: End Users/Desktop
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Text Processing
Classifier: Topic :: Text Processing :: Markup :: HTML
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pymupdf<3,>=1.26.4
Requires-Dist: numpy>=1.24
Requires-Dist: pillow>=9.0
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Dynamic: license-file

# kindle-pdf-cropper

自动剪裁 PDF 四周白边与页眉/页脚、为 Kindle 生成阅读优化 PDF/EPUB 的命令行工具。

- 剪掉每页四周白边 + 页眉/页脚 + 页码，只保留正文内容；
- 可选 `--split`：把每页**上下切成两页**，输出**横版**页面，Kindle 横屏阅读字号接近翻倍；
  - **默认（自适应切分）**：不指定重叠参数时，程序自动把切线放在**两行文字之间的空白处**——
    文字型 PDF 用文本行 bbox 找行间空隙，扫描型 PDF 用图像识别算法找两行之间的空白带——
    因此**不会切断任何一行**，也不需要重叠区域；
  - 也可以显式指定 `--split-overlap-*` 恢复"中线切分 + 两页重叠"的旧模式；
- **自适应**文字型与扫描图片型 PDF；输出结果保持原样——文字仍是文字、
  扫描图仍是扫描图，**文字/公式/表格的排版完全不变**，只做整页剪裁与切分；
- 输出 **PDF**（文字/矢量/图片保真）或 **EPUB**（固定版式，排版不重排）。

技术选型调研见 [docs/research.md](docs/research.md)，算法设计见 [docs/design.md](docs/design.md)。

## 安装

要求 Python ≥ 3.10。

```bash
cd kindle-pdf-cropper
python -m venv .venv
.venv\Scripts\activate            # Windows
# source .venv/bin/activate       # Linux / macOS
pip install -e .
```

## 快速开始

```bash
# 只裁白边和页眉页脚，输出 PDF（默认）
kindle-crop 书.pdf

# 裁切 + 上下切分成横版两页（自适应：切线自动落在两行文字之间的空白处，不切行）
kindle-crop 书.pdf --split -o out/书_横版

# 旧模式：中线切分 + 两页重叠（需要指定重叠参数）
kindle-crop 书.pdf --split --split-overlap-pt 20 -o out/书_横版

# 同时输出 PDF 和 EPUB（自动：文字页=SVG，扫描页=位图）
kindle-crop 书.pdf --format both -o out/书

# 扫描件：调大安全边距、提高 EPUB 位图质量
kindle-crop 扫描.pdf --padding 10 --epub-dpi 220 --format epub

# 调试：把每页的分析叠加图（裁剪框/页眉页脚带/切分框）导出成 PNG
kindle-crop 书.pdf --debug-dir debug
```

## 常用参数

| 参数 | 默认 | 说明 |
| --- | --- | --- |
| `--format pdf\|epub\|both` | `pdf` | 输出格式 |
| `--split` | 关 | 每页上下切成两页横版 |
| `--split-overlap-pt` | —（自适应） | 指定后启用"中线切分+重叠"：两页最小重叠（点） |
| `--split-overlap-ratio` | —（自适应） | 指定后启用"中线切分+重叠"：重叠 = max(比例×裁剪高, 最小点数) |
| `--max-aspect-ratio H/W` | — | `--split` 时每页最大高/宽比；超出时左右补白（如 `0.75` 对应 3:4 屏） |
| `--device-type NAME` | — | `--split` 时按 Kindle 型号确定最大高/宽比；与上一项互斥；`none` 表示不限制，留空且为交互终端时弹出选择 TUI |
| `--padding` | `6` | 内容框外保留的安全边距（点） |
| `--no-header-footer` | 关 | 只裁边距，不删除页眉/页脚/页码 |
| `--no-watermark-removal` | 关 | 关闭扫描页水印/重复图案的自动去除 |
| `--epub-mode image\|svg\|auto` | `auto` | 文字页→SVG，扫描页→位图 |
| `--epub-dpi` | `200` | EPUB 位图分辨率 |
| `--epub-image-format jpeg\|png` | `jpeg` | EPUB 位图格式 |
| `--analysis-dpi` | `144` | 分析用渲染分辨率 |
| `--debug-dir DIR` | — | 导出每页分析叠加图 |
| `-o PATH` | 输入名+`_cropped`（`--split` 时为 `_split`） | 输出路径（`both` 时自动补 `.pdf`/`.epub`） |

## 自适应切分说明（--split）

不指定 `--split-overlap-*` 时，切分线按如下方式自动确定：

1. **文字型 PDF**：取裁剪区内所有文本行 bbox，找出相邻两行之间宽度足够的空白间隙
   （≥ 0.4 × 中位行高），把切线放在该间隙正中——上一行完整保留在上半页，
   下一行完整保留在下半页，中间无重叠也不丢内容；
2. **扫描型 PDF**：用图像识别算法对裁剪区做**逐像素行投影**，找到连续
   "无墨水行"的空白带（行间空白即使只有几像素宽也能分辨），要求
   **切线行及其上下 1px 均为纯空白**，把切线放在空白带正中；被两侧实心
   墨块夹住的空隙（图/大公式内部）优先级最低——只要别处有文字间隙，
   就**不会把一张图切成两半**；
3. 若整页几乎找不到可用空白带（如旋转 90° 的扫描页），退化为中线切分，
   保证上下两页尺寸均衡。

指定 `--split-overlap-*` 后恢复旧模式：在中线切分，两页保留
`max(比例×裁剪高, 最小点数)` 的重叠，保证中线附近的一行不会显示不全。

## Kindle 屏幕比例限制（--max-aspect-ratio / --device-type）

切分后的横版页面，如果**高/宽比**大于 Kindle 横屏的屏幕高/宽比
（也就是竖版屏幕的宽/高比），Kindle 一屏放不下，需要翻两次才能看完一页。
这两个选项用于给横版页面设置**最大高/宽比**，只对 `--split` 生效，且二者互斥：

```bash
# 按 Kindle 型号自动取屏幕比例（推荐）
kindle-crop 书.pdf --split --device-type paperwhite-5 -o out/书_横版

# 或手动指定最大高/宽比（0.75 即 3:4 屏）
kindle-crop 书.pdf --split --max-aspect-ratio 0.75 -o out/书_横版
```

如果在**交互式终端**里使用 `--split`，但没有指定 `--device-type` 或
`--max-aspect-ratio`，程序会弹出一个设备列表 TUI：用 ↑/↓ 移动、Enter 确认；
选择 `No limit` 或按 `q` / `Esc` 则不限制。通过管道、重定向或 CI 运行时
不会弹窗；非交互场景可显式使用 `--device-type none` 关闭限制。

`--split` 时的默认输出文件名后缀为 `_split`（不切分时为 `_cropped`）。

- 值表示**高 ÷ 宽**，横版页面取值应 ≤ 1；例如 3:4 屏为 `0.75`，16:10 屏为 `0.625`。
- 超出限制的页面会在**左右两侧补白**，正文保持原比例居中，不拉伸、不重新排版；
  PDF、SVG 和 EPUB 位图输出都会保留这些空白。
- `--device-type` 支持常用 Kindle 型号/系列：
  `kindle`、`kindle-10`、`kindle-11`、`paperwhite-1`…`paperwhite-5`、
  `paperwhite-12`、`voyage`、`oasis-1`…`oasis-3`、`scribe`、`colorsoft`、`dx`。
  系列名（如 `paperwhite`、`oasis`）取该系列最保守的比例，保证各代都能一屏显示。
- 超过比例限制时才补白；本来就不高的页面不会被加宽。

## 水印 / 重复图案 / 页面污迹去除（扫描页自动）

许多扫描版书籍带有**浅色水印**（如对角重复的站点文字、页脚图案、扫描边缘带）、
**页面边缘黑边/阴影**以及零星污点，它们会干扰页眉/页脚判定与正文区域测量
（例如把页脚区域和正文合并成一个大色带，或让一条黑边把裁剪框撑到页边）。

程序用以下几层处理自动剔除它们：

1. **强墨阈值**：二值化阈值锚定在真正墨色笔画（较暗像素的低分位）与纸张背景之间，
   浅灰水印、纸纹、扫描阴影远高于阈值而被排除；文字的抗锯齿边缘因带暗核心仍被保留。
2. **跨页重复检测**：在全书中均匀抽样（最多 40 页），对每个像素统计
   **“比该页纸张更暗的页数占比”**，只有几乎每页都暗的像素（≥85%）才判定为
   水印/页眉框/扫描边等重复图案。用“暗页占比”而非跨页中位灰度，可避免密集
   正文行对齐时把文字误判成水印而擦掉。
3. **边缘黑边 / 污点净化**：按连通块面积去掉孤立小污点（不再做形态学开运算——
   中文字形笔画只有 2-3 块厚，开运算会把文字一起侵蚀掉、使裁剪框向内收缩）；
   左右页边**沿长边贴边、细长且占墨量很小**的黑边/装订阴影才移除。
   正文行（哪怕紧贴右边缘）、页顶/页底的文字行与图表标签一律保留：
   它们同样细长，误删会直接造成“文字不全”。整页深色封面/整版图不受影响。
4. **页脚识别**：偏保守。只有**跨页重复的窄底带**（位置、高度、宽度都相近且比正文行窄），
   或**唯一的、居中的、像页码的极小白带**才裁掉；正文注释、落款、篇/章标题、
   目录行即使与正文之间有很大的空白，也一律保留。
5. **保护措施**：跨页水印剔除若会使某页内容不足原墨迹的 35%，该页保持原样；
   文字型（born-digital）PDF 不启用。

如需关闭重复图案剔除：`kindle-crop 书.pdf --no-watermark-removal`。

## 输出说明

- **PDF 输出**：每个输出页的页面尺寸就是裁剪后的尺寸（物理裁剪，而非仅改 CropBox，
  任何阅读器都稳定显示）；文字保持可选中的文字，表格线/公式等矢量、嵌入字体原样保留；
  目录与元数据保留。
- **EPUB 输出**：EPUB 是流式重排容器，若要保持排版不变只能用**固定版式**：
  每页钉死一个 viewport。
  - 文字页 → 内联 **SVG**（文字仍为文字，矢量图形保留）；
  - 扫描页 → 整页 **JPEG/PNG 位图**；
  - 若你的阅读器对 SVG/固定版式支持不佳（如部分 Kindle 固件），请用
    `--epub-mode image` 或直接使用 PDF 输出。

## 示例文件

`examples/` 下有生成的样例（文字型、扫描型、旋转扫描型）：
运行 `python tests/make_samples.py text examples/sample_text.pdf` 等重新生成。

## 开发与测试

```bash
pip install -e .[dev]
python -m pytest
```

测试覆盖：边距/页眉页脚分析、扫描与旋转页、PDF 输出文字保真、切分重叠、
自适应切分（文字行间 / 扫描空白带 / 旋转页退避）、EPUB 结构与内容校验、CLI 端到端。

## 许可

MIT，见 [LICENSE](LICENSE)。
