Validación PDF/X
PDF/X (ISO 15930) es el estándar para el intercambio confiable de archivos PDF listos para impresión. PDF Oxide valida todos los niveles principales de PDF/X, verificando cajas de página, espacios de color, transparencia, perfiles ICC e intents de salida.
Niveles soportados
| Level | Standard | Transparency | RGB | Layers | External ICC | External Graphics |
|---|---|---|---|---|---|---|
| X-1a:2001 | ISO 15930-1 | No | No | No | No | No |
| X-1a:2003 | ISO 15930-4 | No | No | No | No | No |
| X-3:2002 | ISO 15930-3 | No | Yes | No | No | No |
| X-3:2003 | ISO 15930-6 | No | Yes | No | No | No |
| X-4 | ISO 15930-7 | Yes | Yes | Yes | No | No |
| X-4p | ISO 15930-7 | Yes | Yes | Yes | Yes | No |
| X-5g | ISO 15930-8 | Yes | Yes | Yes | No | Yes |
| X-5n | ISO 15930-8 | Yes | Yes | Yes | No | Yes |
| X-5pg | ISO 15930-8 | Yes | Yes | Yes | Yes | Yes |
| X-6 | ISO 15930-9 | Yes | Yes | Yes | No | No |
| X-6n | ISO 15930-9 | Yes | Yes | Yes | No | Yes |
| X-6p | ISO 15930-9 | Yes | Yes | Yes | Yes | No |
PDF/X-1a es el más restrictivo: solo CMYK, sin transparencia, sin capas. PDF/X-4 es el nivel moderno más utilizado, permitiendo transparencia y RGB con perfiles ICC.
Validación 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");
}
API del validador
El builder PdfXValidator configura la ejecución de validación:
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());
Qué se verifica
Identificación XMP
El validador confirma que los metadatos XMP declaran la versión PDF/X correcta:
pdfxid:GTS_PDFXVersionmust match the target level- The declared version is compared against the
gts_pdfx_version()for the target level
Relaciones de cajas de página
PDF/X requiere un anidamiento específico de cajas de página:
TrimBox <= BleedBox <= MediaBox
ArtBox <= MediaBox
El validador verifica cada página para asegurar que:
- TrimBox is present (required by all PDF/X levels)
- TrimBox is contained within BleedBox (if BleedBox is defined)
- BleedBox is contained within MediaBox
- ArtBox is contained within MediaBox (if ArtBox is defined)
- Tolerance of 0.01 points for floating-point rounding
Detección de transparencia
Para PDF/X-1a y PDF/X-3, no se permite transparencia. El validador verifica:
- SMask in ExtGState dictionaries (must be
/Noneor absent) - CA (stroke opacity) must equal 1.0
- ca (fill opacity) must equal 1.0
- BM (blend mode) must be
NormalorCompatible
PDF/X-4 y niveles posteriores permiten transparencia.
Validación de espacios de color
El validador verifica el uso de color dependiente del dispositivo:
- DeviceRGB is not allowed in PDF/X-1a (CMYK-only)
- DeviceRGB, DeviceCMYK, and DeviceGray used without an output intent trigger errors in stricter levels
- Color operators
rg,RG,k,K,g,Gin page content streams are scanned
Validación de perfiles ICC
Para espacios de color ICCBased, el validador verifica:
- The profile stream contains the required
/N(number of components) entry - The
/Nvalue matches the expected color space dimension (1 for gray, 3 for RGB, 4 for CMYK) - The profile data is present and non-empty
Intent de salida
PDF/X requiere un intent de salida que describa la condición de impresión prevista:
/OutputIntentsarray must be present in the document catalog- At least one entry with subtype
GTS_PDFXis required - The output intent should reference an ICC profile or a registered print condition
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>,
}
Los errores incluyen el número de página y el ID del objeto donde se encontró la violación, facilitando localizar y corregir problemas en el archivo fuente.
Categorías de XErrorCode
El enum XErrorCode contiene más de 40 códigos de error específicos organizados por categoría:
Metadata: MissingOutputIntent, InvalidGtsPdfxVersion, MissingXmpIdentification
Page boxes: MissingTrimBox, TrimBoxOutsideBleedBox, BleedBoxOutsideMediaBox, ArtBoxOutsideMediaBox
Transparency: TransparencyNotAllowed, InvalidBlendMode, InvalidSMask, InvalidOpacity
Color: DeviceRgbNotAllowed, DeviceDependentColorWithoutIntent, InvalidIccProfile, MissingIccComponents
Content: ExternalContentNotAllowed, EncryptionNotAllowed, JavaScriptNotAllowed
Métodos de PdfXLevel
| Method | Return | Descripción |
|---|---|---|
iso_standard() |
&str |
ISO standard number (e.g., "ISO 15930-7") |
required_pdf_version() |
&str |
Minimum PDF version (e.g., "1.6") |
allows_transparency() |
bool |
Si los grupos de transparencia están permitidos |
allows_rgb() |
bool |
Si el espacio de color RGB está permitido |
allows_layers() |
bool |
Si los grupos de contenido opcional están permitidos |
allows_external_icc() |
bool |
Si los perfiles ICC externos están permitidos |
allows_external_graphics() |
bool |
Si las referencias de gráficos externos están permitidas |
gts_pdfx_version() |
&str |
Expected GTS_PDFXVersion value |
xmp_version() |
&str |
Expected XMP version identifier |
from_gts_version(version) |
Option<Self> |
Parse level from a GTS version string |
Ejemplo práctico: verificación preprensa
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 pasos
- PDF/A Validation – archival compliance
- PDF/UA Accessibility – accessibility validation
- API Reference – complete Rust API