Skip to main content

Merge, rotate and reorder PDF/image files from a GUI or Python API

Project description

nuPDF

CI Python License Docs

nuPDF merges, rotates and reorders PDF and image files.
It ships a clean Python API and an optional PyQt5 desktop GUI.


Features

Feature Description
Merge Combine any number of PDF/image files into a single PDF
Rotate Rotate individual pages or entire documents
Recto-verso Interleave pages for duplex scanner output
Bookmarks Add PDF outline entries named after the source files
Image support Auto-convert JPEG, PNG, GIF and RAW to PDF via Pillow
GUI Optional PyQt5 desktop interface
Executables Pre-built binaries for Windows, Ubuntu and macOS

Installation

# Core library only
pip install nupdf

# With the optional GUI
pip install "nupdf[gui]"

Quick start — Python API

from nupdf.core import read_pdf, rotate_pages, merge_pdfs

# Open a PDF (or convert an image on the fly)
reader = read_pdf("scan.jpg")
print(f"Pages: {len(reader.pages)}")

# Rotate all pages 90° clockwise
rotate_pages("input.pdf", "rotated.pdf", angle=90)

# Rotate only pages 0 and 2 (0-indexed) by 180°
rotate_pages("input.pdf", "rotated.pdf", pages=[0, 2], angle=180)

# Merge two files (with PDF bookmarks)
merge_pdfs(
    ["report.pdf", "appendix.pdf"],
    "combined.pdf",
    recto_verso=False,
    same_file=None,
    bookmark=True,
)

Recto-verso interleaving

Duplex scanners often output fronts and backs as separate files. merge_pdfs can interleave them in the correct reading order:

# Fronts and backs in separate files
merge_pdfs(
    ["fronts.pdf", "backs.pdf"],
    "interleaved.pdf",
    recto_verso=True,
    same_file=True,
)

# All pages in one file (fronts in first half, backs in second half)
merge_pdfs(
    ["both_sides.pdf"],
    "interleaved.pdf",
    recto_verso=True,
    same_file=None,
)

GUI

Launch the graphical interface:

# From source
nupdf

# Or run directly
python -m nupdf.gui
┌─────────────────────────────────────┐
│  nuPDF                              │
│                                     │
│  [Insert files]  [Insert folder]    │
│                                     │
│  ☑ Merge multiple files?            │
│  ☑ Add bookmarks using file title?  │
│  ☐ Recto verso?                     │
│  ☐ Fronts and backs separate?       │
│                                     │
│  Rotation angle (°): [  0  ]        │
│  Pages to rotate:    [     ]        │
│                                     │
│  ┌───────────────────────────────┐  │
│  │ /path/to/file1.pdf            │  │
│  │ /path/to/file2.pdf            │  │
│  └───────────────────────────────┘  │
│  [Up]  [Down]                       │
│                                     │
│  [Clear files list]                 │
│  [Select saving path]               │
│  saving/path/output.pdf             │
│                                     │
│  [          Start          ]        │
│                                     │
│  Status: Ready                      │
└─────────────────────────────────────┘

Page-range syntax

Input Pages selected (1-indexed)
3 Page 3
1-4 Pages 1, 2, 3, 4
1-3;5 Pages 1, 2, 3, 5
2;4-6;9 Pages 2, 4, 5, 6, 9
(empty) All pages

Supported input formats

Extension Notes
.pdf Native; no conversion needed
.jpg / .jpeg Converted to PDF via Pillow
.png Converted to PDF via Pillow
.gif Converted to PDF via Pillow
.raw Converted to PDF via Pillow

Project structure

nupdf/
├── nupdf/
│   ├── __init__.py      # Public API surface
│   ├── core.py          # PDF/image manipulation logic
│   └── gui.py           # PyQt5 desktop interface
├── tests/
│   ├── conftest.py      # pytest fixtures
│   └── test_core.py     # Unit tests for core module
├── docs/
│   └── source/          # Sphinx documentation
├── .github/workflows/
│   ├── ci.yml           # pytest + pylint on push/PR
│   └── release.yml      # PyInstaller binaries on version tag
├── rotatepdf.py         # Backward-compatibility shim
└── pyproject.toml

Development

git clone https://github.com/youruser/nupdf.git
cd nupdf
pip install -e ".[gui,dev]"

# Run tests
pytest

# Lint
pylint nupdf/core.py
pylint nupdf/gui.py --disable=import-error

# Build docs
cd docs && make html

Creating a release

Tag a commit with a version number to trigger the automated release workflow:

git tag v1.2.3
git push origin v1.2.3

GitHub Actions will build standalone executables for Windows, Ubuntu and macOS and attach them to a new GitHub Release automatically.


License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nupdf-1.0.0.tar.gz (21.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nupdf-1.0.0-py3-none-any.whl (18.6 kB view details)

Uploaded Python 3

File details

Details for the file nupdf-1.0.0.tar.gz.

File metadata

  • Download URL: nupdf-1.0.0.tar.gz
  • Upload date:
  • Size: 21.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for nupdf-1.0.0.tar.gz
Algorithm Hash digest
SHA256 978664d748d542a20f6ab776599a988f97bcfa7a1b425cc0a210bfaf90342a59
MD5 ca9e515b79054eab9f8cdbe113caa209
BLAKE2b-256 100790cebadc15f222e1ba8093e0dfd94f42f8612e7368fd8ac33d911184e4f7

See more details on using hashes here.

File details

Details for the file nupdf-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: nupdf-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 18.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for nupdf-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2b3724a9700f9b8b78069200d78cf8da8344e22c69c0effc919889fbeab69509
MD5 504775949c40c8ffba53803455d847ad
BLAKE2b-256 90847762d6469904b9e55eef7476286542bc997e7ad8571cc3f723ad06c81359

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page