Metadata-Version: 2.4
Name: manga-page-splitter
Version: 1.0.0
Summary: Split scanned manga double-page spreads into single pages in right-to-left reading order.
Author-email: Jacob Miller <kevinbai199505@gmail.com>
License-Expression: MIT
Project-URL: Homepage, https://mangatranslator.me
Project-URL: Source Code, https://mangatranslator.me
Keywords: manga,scanlation,comic,spread,gutter,split,image,pillow
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: End Users/Desktop
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
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: Topic :: Multimedia :: Graphics
Classifier: Topic :: Multimedia :: Graphics :: Graphics Conversion
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: Pillow>=9.0
Dynamic: license-file

# manga-page-splitter

Split scanned manga double-page spreads into single pages, in right-to-left
reading order.

Scanned manga is usually distributed as one image per printed spread: two
pages side by side, separated by the fold of the book. That is fine for
reading, but it is awkward for anything that has to work page by page —
e-ink readers, translation tooling, OCR, re-binding a volume into a single
PDF with a sane page count. This package does the boring part: it finds the
fold, cuts the spread in two, and hands you the pages in the order they are
meant to be read.

## Installation

```bash
pip install manga-page-splitter
```

The only runtime dependency is [Pillow](https://python-pillow.org/).

## Quick start

```python
from manga_page_splitter import split_file

# Writes page_001.png and page_002.png into ./pages
written = split_file("spread.png", "pages")
print(written)
```

From the command line:

```bash
manga-page-splitter spread.png -o pages
```

## Reading order

Japanese manga is read from the right page to the left one, so by default the
**right** half of the spread is emitted first. For comics that read
left-to-right, pass `right_to_left=False` or `--ltr`:

```python
pages = split_spread(spread, gutter=400, right_to_left=False)
```

```bash
manga-page-splitter spread.png --ltr
```

## Finding the gutter

`gutter` is the x coordinate the spread is cut at. You can supply it
yourself, but you usually do not have to: `detect_gutter` scans a band around
the horizontal centre of the image and returns the lightest column in it. On
a real scan the fold is printed with no artwork across it, so it is almost
always the cleanest vertical strip near the middle.

```python
from manga_page_splitter import detect_gutter

x = detect_gutter("spread.png")
if x is None:
    print("no clean fold found — pass an explicit gutter")
else:
    print(f"cutting at x={x}")
```

The search is configurable:

| Parameter | Default | Meaning |
|---|---|---|
| `search_ratio` | `0.12` | Half-width of the scanned band, as a fraction of the image width |
| `threshold` | `200` | Grayscale value below which a pixel counts as ink |
| `min_ink_ratio` | `0.02` | A column is only accepted if its ink count is at most this fraction of the height |

Raise `min_ink_ratio` for noisy scans, lower it to demand a genuinely clean
fold. When nothing in the band qualifies, `detect_gutter` returns `None` and
`split_spread` raises `GutterNotFoundError` rather than guessing — a wrong
cut silently corrupts a whole chapter, so failing loudly is the better
default. Pass `gutter=<x>` to force a position.

To check a folder of scans before committing to a batch:

```bash
manga-page-splitter scans/*.png --detect-only
```

## Trimming the margins

Scans usually carry a white or grey margin, and a few millimetres of the
facing page. `trim=True` (or `--trim`) crops each page to the content box,
using the colour of the four corners as the background:

```python
pages = split_spread("spread.png", trim=True, padding=4)
```

`padding` keeps a few pixels of breathing room around the artwork, which is
usually what you want if the pages are headed for a reader that adds its own
margins.

## API

| Function | Purpose |
|---|---|
| `detect_gutter(image, ...)` | Return the x coordinate of the fold, or `None` |
| `split_spread(image, gutter=None, right_to_left=True, trim=False, padding=0)` | Return the two page images in reading order |
| `split_result(image, ...)` | Same, plus the gutter and image size that were used |
| `split_file(path, out_dir, ...)` | Split one file and write the pages to disk |
| `split_many(paths, out_dir, ...)` | Split a batch, one sub-directory per source file |
| `trim_borders(image, tolerance=8, padding=0)` | Crop the uniform border from a single page |

Every function accepts either a `PIL.Image.Image` or a path. `split_result`
returns a frozen `SplitResult` with `pages`, `gutter`, `size`, `detected` and
a `count` property.

## Command line reference

```
manga-page-splitter IMAGE [IMAGE ...] [-o DIR] [-g X] [--ltr] [--trim]
                    [--padding N] [--prefix STEM] [--format FMT]
                    [--quality N] [--batch] [--detect-only] [-q]
```

Exit codes: `0` on success, `1` for I/O or argument errors, `2` when no
gutter could be found.

## Batch use

```bash
# Each scan gets its own folder: pages/chapter01/page_001.png, ...
manga-page-splitter scans/*.png -o pages --batch --trim
```

In Python, `split_many` does the same and returns one list of paths per
source file.

## Notes and limits

- Only two-page spreads are handled. A single page passed in will either be
  cut in the wrong place or rejected, depending on how much ink sits in the
  centre band.
- The gutter search assumes the fold is roughly centred. Heavily cropped
  scans where one page takes two thirds of the width need an explicit
  `gutter`.
- Colour profiles are preserved; nothing is re-encoded unless you ask for a
  lossy `--format`.
- Pages are written in reading order, numbered from `001`, so the file names
  themselves sort correctly.

## Related

Cutting a spread in two is the first step of a scanlation workflow; the
harder half is the text. [Mee Manga Translator](https://mangatranslator.me)
takes the separated pages and translates the dialogue while keeping the
original layout, which pairs well with the `--trim` output above.

## License

MIT. See `LICENSE`.
