All formats

mupdf (Rust)

LanguageRust
LicenseAGPL-3.0 (MuPDF is AGPL-3.0 or commercial from Artifex)
Repositorygithub.com/messense/mupdf-rs
Documentationdocs.rs/mupdf
Depends onMuPDF, built from source by mupdf-sys (needs a C compiler and clang for bindgen)
Read / writeyes / no (XPS and OpenXPS; converts to PDF)

The mupdf crate wraps MuPDF’s C API in safe Rust types. Document::open handles XPS and OpenXPS (the xps feature is on by default), and pages work the same as for PDF: to_pixmap, text, to_svg, bounds. Document::convert_to_pdf copies pages into a new PdfDocument that you can save.

The first build compiles MuPDF and takes a few minutes. The crate is AGPL-3.0 like MuPDF; closed-source use needs a commercial MuPDF license.

Installation#

TOML
[dependencies]
mupdf = "0.8"

Basic usage: render each XPS page to PNG#

Rust
use mupdf::{Colorspace, Document, ImageFormat, Matrix};

fn main() -> Result<(), mupdf::Error> {
    let doc = Document::open("in.xps")?; // .xps or .oxps
    let n = doc.page_count()?;
    println!("{} pages", n);

    let scale = 150.0 / 72.0; // 150 dpi; MuPDF works in points
    for i in 0..n {
        let page = doc.load_page(i)?;
        let pixmap = page.to_pixmap(
            &Matrix::new_scale(scale, scale),
            &Colorspace::device_rgb(),
            false, // no alpha
            true,  // show annotations and widgets
        )?;
        pixmap.save_as(&format!("page-{:03}.png", i + 1), ImageFormat::PNG)?;
    }
    Ok(())
}

How to extract text from an XPS file#

Rust
use mupdf::{Document, TextExtractOptions};

fn main() -> Result<(), mupdf::Error> {
    let doc = Document::open("in.xps")?;
    for i in 0..doc.page_count()? {
        let page = doc.load_page(i)?;
        println!("{}", page.text(TextExtractOptions::default())?);
    }
    Ok(())
}

How to convert XPS to PDF#

Rust
use mupdf::Document;

fn main() -> Result<(), mupdf::Error> {
    let doc = Document::open("in.oxps")?;
    let pdf = doc.convert_to_pdf(0, -1, 0)?; // first page, last page (-1 = end), rotation
    pdf.save("out.pdf")?;
    Ok(())
}

How to check the format and page sizes#

Rust
use mupdf::{Document, MetadataName};

let doc = Document::open("in.xps")?;
println!("format: {}", doc.metadata(MetadataName::Format)?); // "XPS"
for i in 0..doc.page_count()? {
    let r = doc.load_page(i)?.bounds()?;
    println!("page {}: {} x {} pt", i + 1, r.x1 - r.x0, r.y1 - r.y0);
}

Tips#