Skip to content

Produção Gráfica PDF/X

O PDF/X (ISO 15930) é o padrão para a troca confiável de arquivos PDF prontos para impressão. O PDF Oxide valida todos os principais níveis de PDF/X, verificando caixas de página, espaços de cor, transparência, perfis ICC e intenções de saída.

Cobertura nas bindings. A validação de PDF/X é exposta em Python (doc.validate_pdf_x(level)), Rust (validate_pdf_x + builder PdfXValidator) e Go (doc.ValidatePdfX(level)). WASM e C# ainda não expõem a validação de PDF/X — use o CLI do Rust (pdf-oxide validate --pdfx 4 doc.pdf) ou faça a chamada por meio de uma das bindings suportadas.

Níveis Suportados

Nível Padrão Transparência RGB Camadas ICC Externo Gráficos Externos
X-1a:2001 ISO 15930-1 Não Não Não Não Não
X-1a:2003 ISO 15930-4 Não Não Não Não Não
X-3:2002 ISO 15930-3 Não Sim Não Não Não
X-3:2003 ISO 15930-6 Não Sim Não Não Não
X-4 ISO 15930-7 Sim Sim Sim Não Não
X-4p ISO 15930-7 Sim Sim Sim Sim Não
X-5g ISO 15930-8 Sim Sim Sim Não Sim
X-5n ISO 15930-8 Sim Sim Sim Não Sim
X-5pg ISO 15930-8 Sim Sim Sim Sim Sim
X-6 ISO 15930-9 Sim Sim Sim Não Não
X-6n ISO 15930-9 Sim Sim Sim Não Sim
X-6p ISO 15930-9 Sim Sim Sim Sim Não

O PDF/X-1a é o mais restritivo: apenas CMYK, sem transparência e sem camadas. O PDF/X-4 é o nível moderno mais utilizado, permitindo transparência e RGB com perfis ICC.

Validação Rápida

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 do Validador

O builder PdfXValidator configura a execução da validação:

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());

O Que é Verificado

Identificação XMP

O validador confirma que os metadados XMP declaram a versão correta do PDF/X:

  • pdfxid:GTS_PDFXVersion deve corresponder ao nível de destino
  • A versão declarada é comparada com o gts_pdfx_version() do nível de destino

Relações entre Caixas de Página

O PDF/X exige um aninhamento específico das caixas de página:

TrimBox <= BleedBox <= MediaBox
ArtBox  <= MediaBox

O validador verifica cada página para garantir que:

  • O TrimBox está presente (exigido por todos os níveis de PDF/X)
  • O TrimBox está contido dentro do BleedBox (se o BleedBox estiver definido)
  • O BleedBox está contido dentro do MediaBox
  • O ArtBox está contido dentro do MediaBox (se o ArtBox estiver definido)
  • Tolerância de 0,01 ponto para arredondamento de ponto flutuante

Detecção de Transparência

Para PDF/X-1a e PDF/X-3, nenhuma transparência é permitida. O validador verifica:

  • SMask em dicionários ExtGState (deve ser /None ou estar ausente)
  • CA (opacidade do traço) deve ser igual a 1.0
  • ca (opacidade do preenchimento) deve ser igual a 1.0
  • BM (modo de mesclagem) deve ser Normal ou Compatible

PDF/X-4 e níveis posteriores permitem transparência.

Validação de Espaço de Cor

O validador verifica o uso de cores dependentes do dispositivo:

  • DeviceRGB não é permitido no PDF/X-1a (apenas CMYK)
  • DeviceRGB, DeviceCMYK e DeviceGray usados sem uma intenção de saída geram erros em níveis mais rigorosos
  • Os operadores de cor rg, RG, k, K, g, G nos fluxos de conteúdo das páginas são examinados

Validação de Perfil ICC

Para espaços de cor ICCBased, o validador verifica:

  • O fluxo do perfil contém a entrada obrigatória /N (número de componentes)
  • O valor de /N corresponde à dimensão esperada do espaço de cor (1 para cinza, 3 para RGB, 4 para CMYK)
  • Os dados do perfil estão presentes e não estão vazios

Intenção de Saída

O PDF/X exige uma intenção de saída que descreva a condição de impressão pretendida:

  • O array /OutputIntents deve estar presente no catálogo do documento
  • É necessária pelo menos uma entrada com o subtipo GTS_PDFX
  • A intenção de saída deve referenciar um perfil ICC ou uma condição de impressão registrada

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>,
}

Os erros incluem o número da página e o ID do objeto onde a violação foi encontrada, facilitando localizar e corrigir os problemas no arquivo de origem.

Categorias de XErrorCode

O enum XErrorCode contém mais de 40 códigos de erro específicos, organizados por categoria:

Metadados: MissingOutputIntent, InvalidGtsPdfxVersion, MissingXmpIdentification

Caixas de página: MissingTrimBox, TrimBoxOutsideBleedBox, BleedBoxOutsideMediaBox, ArtBoxOutsideMediaBox

Transparência: TransparencyNotAllowed, InvalidBlendMode, InvalidSMask, InvalidOpacity

Cor: DeviceRgbNotAllowed, DeviceDependentColorWithoutIntent, InvalidIccProfile, MissingIccComponents

Conteúdo: ExternalContentNotAllowed, EncryptionNotAllowed, JavaScriptNotAllowed

Métodos de PdfXLevel

Método Retorno Descrição
iso_standard() &str Número do padrão ISO (por exemplo, "ISO 15930-7")
required_pdf_version() &str Versão mínima do PDF (por exemplo, "1.6")
allows_transparency() bool Se grupos de transparência são permitidos
allows_rgb() bool Se o espaço de cor RGB é permitido
allows_layers() bool Se grupos de conteúdo opcional são permitidos
allows_external_icc() bool Se perfis ICC externos são permitidos
allows_external_graphics() bool Se referências a gráficos externos são permitidas
gts_pdfx_version() &str Valor esperado de GTS_PDFXVersion
xmp_version() &str Identificador de versão XMP esperado
from_gts_version(version) Option<Self> Analisa o nível a partir de uma string de versão GTS

Exemplo Prático: Verificação de Pré-impressão

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);
    }
}

Próximos Passos