djvu-rs for Python
| Language | Python 3.9+ (bindings to a Rust library, PyO3) |
|---|---|
| License | MIT |
| Repository | github.com/matyushkin/djvu-rs |
| Documentation | Python README, Python guide |
| Depends on | nothing (binary wheels); Pillow or NumPy optional |
| Read / write | yes / edit metadata, bookmarks, annotations and text layer (no page encoding) |
The djvu-rs package on PyPI wraps the djvu-rs Rust crate. It’s written from the DjVu specification without DjVuLibre code, so it’s MIT-licensed and installs from wheels on Linux, macOS and Windows. Rendering and conversion release the GIL, so you can render pages in parallel threads.
It reads, renders and exports DjVu (to PDF, EPUB, CBZ and TIFF) and edits document data. Creating DjVu pages from images, merging and splitting are only in the Rust crate and its djvu command-line tool. The project is young (first release in 2026) and changes quickly; pin the version.
Installation#
pip install djvu-rs # or: pip install "djvu-rs[numpy,pillow]"
Basic usage: open a document and render a page#
import djvu_rs as djvu
doc = djvu.Document.open("book.djvu")
print(doc.page_count(), "pages")
page = doc.page(0) # 0-based
print(f"{page.width} x {page.height} at {page.dpi} dpi")
page.render(dpi=150).to_pil().save("page1.png") # needs Pillow
How to extract text from a DjVu file#
page.text() returns None when the page has no text layer:
import djvu_rs as djvu
doc = djvu.Document.open("book.djvu")
for i in range(doc.page_count()):
text = doc.page(i).text()
if text:
print(f"--- page {i + 1} ---")
print(text)
page.text_layer() returns the text with a tree of zones (kind, rect, text, children) for word and line coordinates.
How to convert DjVu to PDF#
The PDF keeps selectable text, bookmarks and links:
doc = djvu.Document.open("book.djvu")
doc.write_pdf("book.pdf", dpi=150, jpeg_quality=80)
write_epub, write_cbz and write_tiff work the same way; to_pdf() returns bytes instead of writing a file.
How to render a page to a NumPy array#
pixmap = doc.page(0).render(size=(800, 1000)) # exact size instead of dpi
arr = pixmap.to_numpy() # height x width x 4 (RGBA)
render(dpi, quality="coarse") returns a fast low-quality preview, and region=(x, y, w, h) renders only part of the page.
How to read and change metadata and bookmarks#
doc = djvu.Document.open("book.djvu")
print(doc.metadata()) # {'title': ..., 'author': ..., 'year': ..., ...} or None
for b in doc.bookmarks():
print(b["title"], b["url"])
editor = djvu.Editor.open("book.djvu")
editor.set_metadata({"title": "Calculus", "author": "M. Spivak"})
editor.save("book.djvu") # validated, atomic replace
Tips#
- Errors are typed:
DecodeError,IoError,ExportError,EditErrorandPageIndexError, all subclasses ofdjvu_rs.Error. - Bookmarks can only be written to bundled multi-page files.
Document.from_bytes(data)opens a document from memory.