| Crates.io | oxidize-pdf |
| lib.rs | oxidize-pdf |
| version | 1.2.1 |
| created_at | 2025-07-10 13:58:46.707927+00 |
| updated_at | 2025-09-20 23:54:21.335238+00 |
| description | A pure Rust PDF generation and manipulation library with zero external dependencies |
| homepage | https://github.com/bzsanti/oxidizePdf |
| repository | https://github.com/bzsanti/oxidizePdf |
| max_upload_size | |
| id | 1746485 |
| size | 7,788,732 |
A pure Rust PDF generation and manipulation library with zero external PDF dependencies. Production-ready for basic PDF functionality. Generate PDFs 2x faster than PDFSharp, with memory safety guarantees and a 5.2MB binary size.
Major new features (v1.1.6+):
to_bytes()set_compress()Significant improvements in PDF compatibility:
OptimizedPdfReader with LRU cacheNote: *Success rates apply only to non-encrypted PDFs with basic features. The library provides basic PDF functionality. See Known Limitations for a transparent assessment of current capabilities and planned features.
Add oxidize-pdf to your Cargo.toml:
[dependencies]
oxidize-pdf = "1.1.0"
# For OCR support (optional)
oxidize-pdf = { version = "1.1.0", features = ["ocr-tesseract"] }
use oxidize_pdf::{Document, Page, Font, Color, Result};
fn main() -> Result<()> {
// Create a new document
let mut doc = Document::new();
doc.set_title("My First PDF");
doc.set_author("Rust Developer");
// Create a page
let mut page = Page::a4();
// Add text
page.text()
.set_font(Font::Helvetica, 24.0)
.at(50.0, 700.0)
.write("Hello, PDF!")?;
// Add graphics
page.graphics()
.set_fill_color(Color::rgb(0.0, 0.5, 1.0))
.circle(300.0, 400.0, 50.0)
.fill();
// Add the page and save
doc.add_page(page);
doc.save("hello.pdf")?;
Ok(())
}
use oxidize_pdf::{Document, Page, Font, Color, Result};
fn main() -> Result<()> {
let mut doc = Document::new();
doc.set_title("Custom Fonts Demo");
// Load a custom font from file
doc.add_font("MyFont", "/path/to/font.ttf")?;
// Or load from bytes
let font_data = std::fs::read("/path/to/font.otf")?;
doc.add_font_from_bytes("MyOtherFont", font_data)?;
let mut page = Page::a4();
// Use standard font
page.text()
.set_font(Font::Helvetica, 14.0)
.at(50.0, 700.0)
.write("Standard Font: Helvetica")?;
// Use custom font
page.text()
.set_font(Font::Custom("MyFont".to_string()), 16.0)
.at(50.0, 650.0)
.write("Custom Font: This is my custom font!")?;
// Advanced text formatting with custom font
page.text()
.set_font(Font::Custom("MyOtherFont".to_string()), 12.0)
.set_character_spacing(2.0)
.set_word_spacing(5.0)
.at(50.0, 600.0)
.write("Spaced text with custom font")?;
doc.add_page(page);
doc.save("custom_fonts.pdf")?;
Ok(())
}
use oxidize_pdf::{PdfReader, Result};
fn main() -> Result<()> {
// Open and parse a PDF
let mut reader = PdfReader::open("document.pdf")?;
// Get document info
println!("PDF Version: {}", reader.version());
println!("Page Count: {}", reader.page_count()?);
// Extract text from all pages
let document = reader.into_document();
let text = document.extract_text()?;
for (page_num, page_text) in text.iter().enumerate() {
println!("Page {}: {}", page_num + 1, page_text.content);
}
Ok(())
}
use oxidize_pdf::{Document, Page, Image, Result};
fn main() -> Result<()> {
let mut doc = Document::new();
let mut page = Page::a4();
// Load a JPEG image
let image = Image::from_jpeg_file("photo.jpg")?;
// Add image to page
page.add_image("my_photo", image);
// Draw the image
page.draw_image("my_photo", 100.0, 300.0, 400.0, 300.0)?;
doc.add_page(page);
doc.save("image_example.pdf")?;
Ok(())
}
use oxidize_pdf::{Document, Page, Font, TextAlign, Result};
fn main() -> Result<()> {
let mut doc = Document::new();
let mut page = Page::a4();
// Create text flow with automatic wrapping
let mut flow = page.text_flow();
flow.at(50.0, 700.0)
.set_font(Font::Times, 12.0)
.set_alignment(TextAlign::Justified)
.write_wrapped("This is a long paragraph that will automatically wrap \
to fit within the page margins. The text is justified, \
creating clean edges on both sides.")?;
page.add_text_flow(&flow);
doc.add_page(page);
doc.save("text_flow.pdf")?;
Ok(())
}
use oxidize_pdf::operations::{PdfSplitter, PdfMerger, PageRange};
use oxidize_pdf::Result;
fn main() -> Result<()> {
// Split a PDF
let splitter = PdfSplitter::new("input.pdf")?;
splitter.split_by_pages("page_{}.pdf")?; // page_1.pdf, page_2.pdf, ...
// Merge PDFs
let mut merger = PdfMerger::new();
merger.add_pdf("doc1.pdf", PageRange::All)?;
merger.add_pdf("doc2.pdf", PageRange::Pages(vec![1, 3, 5]))?;
merger.save("merged.pdf")?;
// Rotate pages
use oxidize_pdf::operations::{PdfRotator, RotationAngle};
let rotator = PdfRotator::new("input.pdf")?;
rotator.rotate_all(RotationAngle::Clockwise90, "rotated.pdf")?;
Ok(())
}
use oxidize_pdf::text::tesseract_provider::{TesseractOcrProvider, TesseractConfig};
use oxidize_pdf::text::ocr::{OcrOptions, OcrProvider};
use oxidize_pdf::operations::page_analysis::PageContentAnalyzer;
use oxidize_pdf::parser::PdfReader;
use oxidize_pdf::Result;
fn main() -> Result<()> {
// Open a scanned PDF
let document = PdfReader::open_document("scanned.pdf")?;
let analyzer = PageContentAnalyzer::new(document);
// Configure OCR provider
let config = TesseractConfig::for_documents();
let ocr_provider = TesseractOcrProvider::with_config(config)?;
// Find and process scanned pages
let scanned_pages = analyzer.find_scanned_pages()?;
for page_num in scanned_pages {
let result = analyzer.extract_text_from_scanned_page(page_num, &ocr_provider)?;
println!("Page {}: {} (confidence: {:.1}%)",
page_num, result.text, result.confidence * 100.0);
}
Ok(())
}
Before using OCR features, install Tesseract on your system:
macOS:
brew install tesseract
brew install tesseract-lang # For additional languages
Ubuntu/Debian:
sudo apt-get install tesseract-ocr
sudo apt-get install tesseract-ocr-spa # For Spanish
sudo apt-get install tesseract-ocr-deu # For German
Windows: Download from: https://github.com/UB-Mannheim/tesseract/wiki
Check out the examples directory for more usage patterns:
hello_world.rs - Basic PDF creationgraphics_demo.rs - Vector graphics showcasetext_formatting.rs - Advanced text featurescustom_fonts.rs - TTF/OTF font loading and embeddingjpeg_image.rs - Image embeddingparse_pdf.rs - PDF parsing and text extractioncomprehensive_demo.rs - All features demonstrationtesseract_ocr_demo.rs - OCR text extraction (requires --features ocr-tesseract)scanned_pdf_analysis.rs - Analyze PDFs for scanned contentextract_images.rs - Extract embedded images from PDFscreate_pdf_with_images.rs - Advanced image embedding examplesRun examples with:
cargo run --example hello_world
# For OCR examples
cargo run --example tesseract_ocr_demo --features ocr-tesseract
This project is licensed under the MIT License - see the LICENSE file for details.
The MIT license allows you to use oxidize-pdf in commercial projects without restrictions.
oxidize-pdf provides basic PDF functionality. We prioritize transparency about what works and what doesn't.
We're actively adding more examples for core features. New examples include:
merge_pdfs.rs - PDF merging with various optionssplit_pdf.rs - Different splitting strategiesextract_text.rs - Text extraction with layout preservationencryption.rs - RC4 and AES encryption demonstrationsoxidize-pdf/
├── oxidize-pdf-core/ # Core PDF library
├── oxidize-pdf-cli/ # Command-line interface
├── oxidize-pdf-api/ # REST API server
├── test-suite/ # Comprehensive test suite
├── docs/ # Documentation
│ ├── technical/ # Technical docs and implementation details
│ └── reports/ # Analysis and test reports
├── tools/ # Development and analysis tools
├── scripts/ # Build and release scripts
└── test-pdfs/ # Test PDF files
See REPOSITORY_ARCHITECTURE.md for detailed information.
oxidize-pdf includes comprehensive test suites to ensure reliability:
# Run standard test suite (synthetic PDFs)
cargo test
# Run all tests including performance benchmarks
cargo test -- --ignored
# Run with local PDF fixtures (if available)
OXIDIZE_PDF_FIXTURES=on cargo test
# Run OCR tests (requires Tesseract installation)
cargo test tesseract_ocr_tests --features ocr-tesseract -- --ignored
For enhanced testing with real-world PDFs, you can optionally set up local PDF fixtures:
tests/fixtures -> /path/to/your/pdf/collection.gitignore)Note: CI/CD always uses synthetic PDFs only for consistent, fast builds.
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
See our detailed roadmap for more information.
Built with ❤️ using Rust. Special thanks to the Rust community and all contributors.