Skip to content

Поліграфічне виробництво PDF/X

PDF/X (ISO 15930) — це стандарт для надійного обміну готовими до друку PDF-файлами. PDF Oxide перевіряє всі основні рівні PDF/X, контролюючи рамки сторінки, колірні простори, прозорість, ICC-профілі та умови виводу.

Підтримка у прив’язках. Перевірка PDF/X доступна у Python (doc.validate_pdf_x(level)), Rust (validate_pdf_x + білдер PdfXValidator) та Go (doc.ValidatePdfX(level)). WASM і C# поки що не надають перевірку PDF/X — скористайтеся Rust CLI (pdf-oxide validate --pdfx 4 doc.pdf) або викликайте через одну з підтримуваних прив’язок.

Підтримувані рівні

Рівень Стандарт Прозорість RGB Шари Зовнішній ICC Зовнішня графіка
X-1a:2001 ISO 15930-1 Ні Ні Ні Ні Ні
X-1a:2003 ISO 15930-4 Ні Ні Ні Ні Ні
X-3:2002 ISO 15930-3 Ні Так Ні Ні Ні
X-3:2003 ISO 15930-6 Ні Так Ні Ні Ні
X-4 ISO 15930-7 Так Так Так Ні Ні
X-4p ISO 15930-7 Так Так Так Так Ні
X-5g ISO 15930-8 Так Так Так Ні Так
X-5n ISO 15930-8 Так Так Так Ні Так
X-5pg ISO 15930-8 Так Так Так Так Так
X-6 ISO 15930-9 Так Так Так Ні Ні
X-6n ISO 15930-9 Так Так Так Ні Так
X-6p ISO 15930-9 Так Так Так Так Ні

PDF/X-1a — найсуворіший рівень: лише CMYK, без прозорості та без шарів. PDF/X-4 — найпоширеніший сучасний рівень, що допускає прозорість і RGB з ICC-профілями.

Швидка перевірка

from pdf_oxide import PdfDocument

doc = PdfDocument("document.pdf")
result = doc.validate_pdf_x("4")
print(f"Valid: {result.valid}")
use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::pdf_x::{validate_pdf_x, PdfXLevel};

let mut doc = PdfDocument::open("print-ready.pdf")?;
let result = validate_pdf_x(&mut doc, PdfXLevel::X4)?;

if result.has_errors() {
    println!("Not PDF/X-4 compliant ({} errors):", result.errors.len());
    for error in &result.errors {
        println!("  [{}] {} (clause {})",
            error.code, error.message,
            error.clause.as_deref().unwrap_or("n/a"));
    }
} else {
    println!("Document is PDF/X-4 compliant");
}
doc, _ := pdfoxide.Open("print-ready.pdf")
defer doc.Close()

// Level encoding: 0 = X-1a:2001, 1 = X-1a:2003, 2 = X-3:2002, 3 = X-3:2003, 4 = X-4, ...
valid, errs, err := doc.ValidatePdfX(4) // PDF/X-4
if err != nil { log.Fatal(err) }

if valid {
    fmt.Println("Document is PDF/X-4 compliant")
} else {
    fmt.Printf("Not PDF/X-4 compliant (%d errors):\n", len(errs))
    for _, e := range errs {
        fmt.Printf("  %s\n", e)
    }
}

API валідатора

Білдер PdfXValidator налаштовує запуск перевірки:

use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::pdf_x::{PdfXValidator, PdfXLevel};

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

let result = PdfXValidator::new(PdfXLevel::X1a2001)
    .stop_on_first_error(false)
    .include_warnings(true)
    .validate(&mut doc)?;

println!("Errors: {}", result.errors.len());
println!("Warnings: {}", result.warnings.len());
println!("Total issues: {}", result.total_issues());

Що перевіряється

Ідентифікація XMP

Валідатор підтверджує, що метадані XMP оголошують правильну версію PDF/X:

  • pdfxid:GTS_PDFXVersion має відповідати цільовому рівню
  • Оголошена версія порівнюється зі значенням gts_pdfx_version() для цільового рівня

Співвідношення рамок сторінки

PDF/X вимагає певного вкладення рамок сторінки:

TrimBox <= BleedBox <= MediaBox
ArtBox  <= MediaBox

Валідатор перевіряє кожну сторінку, щоб переконатися, що:

  • TrimBox присутній (вимагається на всіх рівнях PDF/X)
  • TrimBox міститься всередині BleedBox (якщо BleedBox визначено)
  • BleedBox міститься всередині MediaBox
  • ArtBox міститься всередині MediaBox (якщо ArtBox визначено)
  • Допуск 0,01 пункту для округлення чисел з плаваючою комою

Виявлення прозорості

Для PDF/X-1a та PDF/X-3 прозорість не дозволяється. Валідатор перевіряє:

  • SMask у словниках ExtGState (має бути /None або відсутнім)
  • CA (непрозорість обведення) має дорівнювати 1.0
  • ca (непрозорість заливки) має дорівнювати 1.0
  • BM (режим змішування) має бути Normal або Compatible

PDF/X-4 та пізніші рівні дозволяють прозорість.

Перевірка колірного простору

Валідатор перевіряє використання апаратно-залежних кольорів:

  • DeviceRGB не дозволяється у PDF/X-1a (лише CMYK)
  • DeviceRGB, DeviceCMYK та DeviceGray, використані без умови виводу, спричиняють помилки на суворіших рівнях
  • Скануються колірні оператори rg, RG, k, K, g, G у потоках вмісту сторінок

Перевірка ICC-профілю

Для колірних просторів ICCBased валідатор перевіряє:

  • Потік профілю містить обов’язковий запис /N (кількість компонентів)
  • Значення /N відповідає очікуваній розмірності колірного простору (1 для сірого, 3 для RGB, 4 для CMYK)
  • Дані профілю присутні й не порожні

Умова виводу

PDF/X вимагає умови виводу, що описує передбачувані умови друку:

  • Масив /OutputIntents має бути присутнім у каталозі документа
  • Потрібен щонайменше один запис із підтипом GTS_PDFX
  • Умова виводу має посилатися на ICC-профіль або зареєстровану умову друку

XValidationResult

pub struct XValidationResult {
    pub level: PdfXLevel,
    pub errors: Vec<XComplianceError>,
    pub warnings: Vec<XComplianceError>,
    pub stats: XValidationStats,
}

XComplianceError

pub struct XComplianceError {
    pub code: XErrorCode,
    pub message: String,
    pub severity: XSeverity,
    pub page: Option<usize>,
    pub object_id: Option<u32>,
    pub clause: Option<String>,
}

Помилки містять номер сторінки та ідентифікатор об’єкта, де було виявлено порушення, що спрощує пошук і виправлення проблем у вихідному файлі.

Категорії XErrorCode

Перелік XErrorCode містить понад 40 конкретних кодів помилок, згрупованих за категоріями:

Метадані: MissingOutputIntent, InvalidGtsPdfxVersion, MissingXmpIdentification

Рамки сторінки: MissingTrimBox, TrimBoxOutsideBleedBox, BleedBoxOutsideMediaBox, ArtBoxOutsideMediaBox

Прозорість: TransparencyNotAllowed, InvalidBlendMode, InvalidSMask, InvalidOpacity

Колір: DeviceRgbNotAllowed, DeviceDependentColorWithoutIntent, InvalidIccProfile, MissingIccComponents

Вміст: ExternalContentNotAllowed, EncryptionNotAllowed, JavaScriptNotAllowed

Методи PdfXLevel

Метод Повертає Опис
iso_standard() &str Номер стандарту ISO (наприклад, "ISO 15930-7")
required_pdf_version() &str Мінімальна версія PDF (наприклад, "1.6")
allows_transparency() bool Чи дозволені групи прозорості
allows_rgb() bool Чи дозволений колірний простір RGB
allows_layers() bool Чи дозволені групи необов’язкового вмісту
allows_external_icc() bool Чи дозволені зовнішні ICC-профілі
allows_external_graphics() bool Чи дозволені посилання на зовнішню графіку
gts_pdfx_version() &str Очікуване значення GTS_PDFXVersion
xmp_version() &str Очікуваний ідентифікатор версії XMP
from_gts_version(version) Option<Self> Розбір рівня з рядка версії GTS

Практичний приклад: переддрукарська перевірка

use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::pdf_x::{validate_pdf_x, PdfXLevel, XSeverity};

let mut doc = PdfDocument::open("magazine-cover.pdf")?;
let result = validate_pdf_x(&mut doc, PdfXLevel::X4)?;

println!("=== PDF/X-4 Prepress Report ===");
println!("Status: {}", if result.has_errors() { "REJECT" } else { "ACCEPT" });

// Group errors by severity
let critical: Vec<_> = result.errors.iter()
    .filter(|e| e.is_error())
    .collect();
let advisory: Vec<_> = result.warnings.iter().collect();

if !critical.is_empty() {
    println!("\nCritical ({}):", critical.len());
    for e in &critical {
        let page_str = e.page
            .map(|p| format!("page {}", p + 1))
            .unwrap_or_else(|| "document".into());
        println!("  [{}] {} ({})", e.code, e.message, page_str);
    }
}

if !advisory.is_empty() {
    println!("\nAdvisory ({}):", advisory.len());
    for w in &advisory {
        println!("  [{}] {}", w.code, w.message);
    }
}

Подальші кроки