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+ builderPdfXValidator) 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_PDFXVersiondeve 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
/Noneou 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
NormalouCompatible
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,Gnos 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
/Ncorresponde à 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
/OutputIntentsdeve 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
- Validação PDF/A – conformidade para arquivamento
- Acessibilidade PDF/UA – validação de acessibilidade
- Referência da API – API completa em Rust