Skip to content

Порівняння з PDF-бібліотеками для Rust

PDF Oxide у порівнянні з найпопулярнішими PDF-крейтами для Rust: lopdf, printpdf, pdf-rs та pdf_extract. Кожен із них націлений на свій рівень абстракції та свій набір сценаріїв використання.

Стисло

PDF Oxide lopdf printpdf pdf-rs pdf_extract
Рівень API Високорівневий Низькорівневий Середній рівень (створення) Низькорівневий (читання) Середній рівень (читання)
Читання PDF Так Так Ні Так Так
Запис PDF Так Так Так Ні Ні
Вилучення тексту Так (високорівневе) Вручну Ні Вручну Так (базове)
Вилучення зображень Так (високорівневе) Вручну Ні Вручну Ні
Поля форм Читання + запис Вручну Ні Лише читання Ні
Створення PDF Так Так Так Ні Ні
Введення з Markdown/HTML Так Ні Ні Ні Ні
Редагування наявних PDF Так Так (низькорівневе) Ні Ні Ні
Анотації Читання + запис Вручну Ні Лише читання Ні
Шифрування Читання + запис Ні Ні Ні Ні
Перевірка PDF/A Так Ні Ні Ні Ні
Рендеринг Так (tiny-skia) Ні Ні Частково Ні
Прив’язки для Python Так Ні Ні Ні Ні
Ліцензія MIT MIT MIT MIT Apache-2.0

Усі бібліотеки мають дозвільні ліцензії. Відмінності — у охопленні можливостей та рівні абстракції.

Порівняння продуктивності

Бенчмарк на повному корпусі (3830 PDF)

Тестування проводилося на повному корпусі з 3830 PDF — це три незалежні, загальнодоступні набори тестів, що охоплюють відповідність специфікації PDF (veraPDF, 2907 файлів), реальні граничні випадки рендерингу в браузері (Mozilla pdf.js, 897 файлів) та стрес-тести на безпеку й стійкість, зокрема некоректні структури та пошкодження, згенеровані фазингом (DARPA SafeDocs, 26 файлів). Див. подробиці про повний корпус.

Бібліотека Середнє p99 Частка успіху Вилучення тексту Примітки
PDF Oxide 0,8 мс 9 мс 100% Вбудоване, промислового рівня Unicode, CJK, порядок читання
oxidize_pdf 13,5 мс 11 мс 99,1% Базове Максимальний викид 48 с
unpdf 2,8 мс 10 мс 95,1% Базове 185 збоїв на повному корпусі
pdf_extract 4,08 мс 37 мс 91,5% Базове Пропускає складні макети
lopdf 0,3 мс 2 мс 80,2% Без вбудованого вилучення Збоїть на 20% PDF

lopdf працює швидше на тих PDF, які може розібрати, — але збоїть на 20% корпусу й не надає вилучення тексту. Декодування шрифтів, розв’язання CMap та аналіз інтервалів довелося б реалізовувати самостійно.

pdf_extract надає базове вилучення тексту, але має частку успіху 91,5% і важко справляється зі складними макетами, текстом CJK та тегованими PDF. oxidize_pdf має пристойну надійність (99,1%), але в 17 разів повільніша за pdf_oxide за середнім часом вилучення, з викидом до 48 секунд у найгіршому випадку. unpdf обробляє весь корпус, але збоїть на 185 PDF.

PDF Oxide — єдиний крейт Rust, що поєднує 100% надійність із вилученням тексту промислового рівня.

Порівняння дизайну API

PDF Oxide: високорівневий, орієнтований на завдання

PDF Oxide надає спеціально створені методи для типових завдань. Ви працюєте з текстом, зображеннями та полями форм, а не з об’єктами й словниками PDF.

use pdf_oxide::PdfDocument;

let mut doc = PdfDocument::open("report.pdf")?;

// Text extraction -- one call
let text = doc.extract_text(0)?;
println!("{}", text);

// Styled spans with font metadata
let spans = doc.extract_spans(0)?;
for span in &spans {
    println!("'{}' font={} size={:.1}pt", span.text, span.font_name, span.font_size);
}

// Image extraction
let images = doc.extract_images(0)?;
for img in &images {
    println!("{}x{} {:?}", img.width, img.height, img.format);
}

// Form fields
let fields = doc.extract_form_fields()?;
for field in &fields {
    println!("{}: {:?}", field.name, field.value);
}

Створення PDF так само просте:

use pdf_oxide::api::Pdf;

// From Markdown
let pdf = Pdf::from_markdown("# Report\n\n| A | B |\n|---|---|\n| 1 | 2 |")?;
pdf.save("report.pdf")?;

// From HTML
let pdf = Pdf::from_html("<h1>Report</h1><p>Content here.</p>")?;
pdf.save("report.pdf")?;

lopdf: низькорівнева маніпуляція об’єктами

lopdf дає прямий доступ до об’єктів PDF, потоків і таблиці перехресних посилань. Щоб користуватися ним ефективно, потрібно розуміти специфікацію PDF. Вбудованого вилучення тексту немає — ви самі обходите словники та декодуєте потоки.

use lopdf::Document;

let doc = Document::load("report.pdf")?;

// Get page dictionary
let page_id = doc.page_iter().next().unwrap();
let page = doc.get_dictionary(page_id)?;

// Get content stream -- manual work
let contents = page.get("Contents")?;
let stream = doc.get_object(contents.as_reference()?)?;

// To extract text you must:
// 1. Parse the content stream operators
// 2. Resolve font references from /Resources
// 3. Decode CMap/ToUnicode mappings
// 4. Apply text matrix transformations
// 5. Handle encoding differences
//
// lopdf does not provide any of this -- it is raw object access
println!("Page has {} objects", doc.objects.len());

lopdf — правильний інструмент, коли потрібно безпосередньо маніпулювати структурою PDF: об’єднувати документи, переписувати потоки об’єктів або створювати спеціалізовані обробники PDF.

printpdf: лише створення PDF

printpdf — бібліотека лише для створення. Вона не вміє читати чи розбирати наявні PDF. Вона надає типізований API для побудови PDF-документів з нуля — з текстом, зображеннями та векторною графікою.

use printpdf::*;

let (doc, page1, layer1) = PdfDocument::new(
    "Report", Mm(210.0), Mm(297.0), "Layer 1"
);

let current_layer = doc.get_page(page1).get_layer(layer1);

// Add text -- requires manual font loading
let font = doc.add_builtin_font(BuiltinFont::Helvetica)?;
current_layer.use_text("Hello World", 24.0, Mm(10.0), Mm(280.0), &font);

// Save
doc.save(&mut std::io::BufWriter::new(
    std::fs::File::create("output.pdf")?,
))?;

// Cannot read existing PDFs
// Cannot extract text, images, or form fields

printpdf — правильний інструмент, коли вам потрібно лише генерувати нові PDF і хочеться чистий, сфокусований API для створення.

pdf-rs: низькорівневе читання PDF

pdf-rs розбирає структуру PDF у типи Rust, але надає мінімум високорівневої функціональності. Ви отримуєте типізований доступ до об’єктів PDF, але декодування тексту, розв’язання шрифтів і розбір потоків вмісту все одно лягають на вас.

use pdf::file::FileOptions;

let file = FileOptions::cached().open("report.pdf")?;

// Access page objects
let page = file.get_page(0)?;
let media_box = page.media_box()?;
println!("Page size: {:?}", media_box);

// Content stream access -- low-level
if let Some(ref contents) = page.contents {
    // Returns raw operations -- you must interpret them
    // No built-in text assembly, font decoding, or layout analysis
}

// Cannot write or modify PDFs

pdf-rs — правильний інструмент, коли потрібен типобезпечний парсер PDF для аналізу, перевірки або побудови власного рендерера.

Порівняння можливостей за завданнями

Вилучення тексту

Бібліотека Вбудоване Якість Потрібні зусилля
PDF Oxide Так Промислового рівня (Unicode, CJK, порядок читання) Один виклик методу
pdf_extract Так Базове (пропускає складні макети) Один виклик методу
lopdf Ні Н/Д Сотні рядків власного коду
printpdf Ні Н/Д Неможливо (лише запис)
pdf-rs Ні Н/Д Потрібен значний обсяг власного коду

PDF Oxide опрацьовує декодування CMap/ToUnicode, інтервали на основі метрик шрифту, порядок читання за деревом структури та відновлення лігатур. Реалізація еквівалентної функціональності поверх lopdf чи pdf-rs потребує тисяч рядків коду й глибокого знання специфікації PDF.

Створення PDF

Бібліотека Підхід Введення з Markdown/HTML Таблиці Штрихкоди
PDF Oxide Високо- + низькорівневий Так Так Так
lopdf Побудова з «сирих» об’єктів Ні Ні Ні
printpdf Типізований API шарів Ні Ні Ні
pdf-rs Н/Д (лише читання) Н/Д Н/Д Н/Д

Шифрування

Бібліотека Читання зашифрованих Запис зашифрованих Алгоритми
PDF Oxide Так Так RC4-40, RC4-128, AES-128, AES-256
lopdf Ні Ні
printpdf Ні Ні
pdf-rs Частково Ні Лише RC4

Відповідність стандартам

Бібліотека PDF/A PDF/X PDF/UA
PDF Oxide Перевірка + конвертація Перевірка Перевірка
lopdf Ні Ні Ні
printpdf Частково (вивід PDF/A-1b) Ні Ні
pdf-rs Ні Ні Ні

Обсяг залежностей

Бібліотека Залежності Час компіляції Розмір бінарника
PDF Oxide ~40 (ядро) ~30 с ~4 МБ
lopdf ~15 ~10 с ~1 МБ
printpdf ~20 ~15 с ~2 МБ
pdf-rs ~25 ~20 с ~2 МБ

PDF Oxide має більше залежностей, бо включає розбір шрифтів, декодування зображень, інтерпретацію потоків вмісту та шифрування — можливості, які інші бібліотеки залишають на користувача або зовсім опускають. З усіма опціональними можливостями (rendering, barcodes, office) їхня кількість зростає до ~100.

Поєднання бібліотек

Оскільки всі вони мають дозвільні ліцензії, ви можете поєднувати їх в одному проєкті:

[dependencies]
pdf_oxide = "0.3"
lopdf = "0.32"        # Optional: raw object access for edge cases

Типові схеми:

  • PDF Oxide + lopdf: використовуйте PDF Oxide для вилучення та створення, вдаючись до lopdf для граничних випадків, що потребують маніпуляцій із «сирими» об’єктами.
  • PDF Oxide + printpdf: використовуйте PDF Oxide для читання, а printpdf — для спеціалізованих сценаріїв створення.

Матриця сценаріїв використання

«Мені потрібно вилучати текст із PDF»

Крейт Підходить? Примітки
PDF Oxide Так Найкраща якість вилучення, 100% успіху, порядок читання, метадані шрифтів
pdf_extract Частково Базове вилучення, 91,5% успіху
lopdf Ні Без вилучення тексту
printpdf Ні Не вміє читати PDF
pdf-rs Частково Базовий розбір, без високорівневого вилучення тексту

«Мені потрібно створювати PDF»

Крейт Підходить? Примітки
PDF Oxide Так Високорівневий (Markdown/HTML) і низькорівневий API
lopdf Частково Низькорівнева побудова об’єктів
printpdf Так Чистий API створення, без читання
pdf-rs Ні Лише читання

«Мені потрібно редагувати наявні PDF»

Крейт Підходить? Примітки
PDF Oxide Так DOM-подібне редагування, анотації, форми
lopdf Частково Низькорівнева маніпуляція об’єктами
printpdf Ні Не вміє читати PDF
pdf-rs Ні Лише читання

«Мені потрібен повний життєвий цикл (вилучення + створення + редагування)»

Крейт Підходить? Примітки
PDF Oxide Так Єдиний крейт, що охоплює всі три
lopdf + printpdf Частково Два крейти, без вилучення тексту
pdf-rs + printpdf Частково Два крейти, без редагування

Коли що обирати

Обирайте PDF Oxide, якщо вам потрібно більше ніж одна можливість роботи з PDF (вилучення + створення або вилучення + редагування) і ви хочете єдину, добре протестовану залежність зі 100% надійністю.

Обирайте lopdf, якщо вам потрібна низькорівнева маніпуляція структурою PDF і ви готові працювати безпосередньо зі специфікацією PDF. Добре підходить для об’єднання, поділу та пакетної обробки PDF.

Обирайте printpdf, якщо ви лише створюєте PDF і ніколи не читаєте їх. Найчистіший API для генерації звітів і документів.

Обирайте pdf-rs, якщо вам потрібен відповідний специфікації парсер для аналізу PDF або ви будуєте власний конвеєр рендерингу.

Обирайте pdf_extract, якщо вам потрібне базове вилучення тексту й не потрібні висока надійність чи підтримка складних макетів.

Пов’язані сторінки