Producción de Imprenta PDF/X
PDF/X (ISO 15930) es el estándar para el intercambio fiable de archivos PDF listos para imprenta. PDF Oxide valida todos los niveles principales de PDF/X, comprobando las cajas de página, los espacios de color, la transparencia, los perfiles ICC y las intenciones de salida.
Cobertura en los bindings. La validación PDF/X está disponible en Python (
doc.validate_pdf_x(level)), Rust (validate_pdf_x+ el builderPdfXValidator) y Go (doc.ValidatePdfX(level)). WASM y C# todavía no exponen la validación PDF/X: utiliza la CLI de Rust (pdf-oxide validate --pdfx 4 doc.pdf) o llámala a través de uno de los bindings compatibles.
Niveles Compatibles
| Nivel | Estándar | Transparencia | RGB | Capas | ICC externo | Gráficos externos |
|---|---|---|---|---|---|---|
| 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 | Sí | No | No | No |
| X-3:2003 | ISO 15930-6 | No | Sí | No | No | No |
| X-4 | ISO 15930-7 | Sí | Sí | Sí | No | No |
| X-4p | ISO 15930-7 | Sí | Sí | Sí | Sí | No |
| X-5g | ISO 15930-8 | Sí | Sí | Sí | No | Sí |
| X-5n | ISO 15930-8 | Sí | Sí | Sí | No | Sí |
| X-5pg | ISO 15930-8 | Sí | Sí | Sí | Sí | Sí |
| X-6 | ISO 15930-9 | Sí | Sí | Sí | No | No |
| X-6n | ISO 15930-9 | Sí | Sí | Sí | No | Sí |
| X-6p | ISO 15930-9 | Sí | Sí | Sí | Sí | No |
PDF/X-1a es el más restrictivo: solo CMYK, sin transparencia y sin capas. PDF/X-4 es el nivel moderno más utilizado, ya que permite 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");
}
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 del Validador
El builder PdfXValidator configura la ejecución de la 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 Comprueba
Identificación XMP
El validador confirma que los metadatos XMP declaran la versión correcta de PDF/X:
pdfxid:GTS_PDFXVersiondebe coincidir con el nivel de destino- La versión declarada se compara con el
gts_pdfx_version()del nivel de destino
Relaciones entre Cajas de Página
PDF/X exige un anidamiento específico de las cajas de página:
TrimBox <= BleedBox <= MediaBox
ArtBox <= MediaBox
El validador comprueba cada página para garantizar que:
- La TrimBox está presente (requerida por todos los niveles de PDF/X)
- La TrimBox está contenida dentro de la BleedBox (si la BleedBox está definida)
- La BleedBox está contenida dentro de la MediaBox
- La ArtBox está contenida dentro de la MediaBox (si la ArtBox está definida)
- Una tolerancia de 0,01 puntos para el redondeo de coma flotante
Detección de Transparencia
Para PDF/X-1a y PDF/X-3 no se permite ninguna transparencia. El validador comprueba:
- SMask en los diccionarios ExtGState (debe ser
/Noneo estar ausente) - CA (opacidad del trazo) debe ser igual a 1.0
- ca (opacidad del relleno) debe ser igual a 1.0
- BM (modo de fusión) debe ser
NormaloCompatible
PDF/X-4 y los niveles posteriores permiten la transparencia.
Validación del Espacio de Color
El validador comprueba el uso de colores dependientes del dispositivo:
- DeviceRGB no está permitido en PDF/X-1a (solo CMYK)
- DeviceRGB, DeviceCMYK y DeviceGray usados sin una intención de salida generan errores en los niveles más estrictos
- Se analizan los operadores de color
rg,RG,k,K,g,Gen los flujos de contenido de las páginas
Validación del Perfil ICC
Para los espacios de color ICCBased, el validador comprueba:
- El flujo del perfil contiene la entrada obligatoria
/N(número de componentes) - El valor de
/Ncoincide con la dimensión esperada del espacio de color (1 para gris, 3 para RGB, 4 para CMYK) - Los datos del perfil están presentes y no están vacíos
Intención de Salida
PDF/X exige una intención de salida que describa la condición de impresión prevista:
- El array
/OutputIntentsdebe estar presente en el catálogo del documento - Se requiere al menos una entrada con el subtipo
GTS_PDFX - La intención de salida debe hacer referencia a un perfil ICC o a una condición de impresión 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>,
}
Los errores incluyen el número de página y el ID de objeto donde se encontró la infracción, lo que facilita localizar y corregir los problemas en el archivo de origen.
Categorías de XErrorCode
El enum XErrorCode contiene más de 40 códigos de error específicos, organizados por categoría:
Metadatos: MissingOutputIntent, InvalidGtsPdfxVersion, MissingXmpIdentification
Cajas de página: MissingTrimBox, TrimBoxOutsideBleedBox, BleedBoxOutsideMediaBox, ArtBoxOutsideMediaBox
Transparencia: TransparencyNotAllowed, InvalidBlendMode, InvalidSMask, InvalidOpacity
Color: DeviceRgbNotAllowed, DeviceDependentColorWithoutIntent, InvalidIccProfile, MissingIccComponents
Contenido: ExternalContentNotAllowed, EncryptionNotAllowed, JavaScriptNotAllowed
Métodos de PdfXLevel
| Método | Retorno | Descripción |
|---|---|---|
iso_standard() |
&str |
Número de estándar ISO (por ejemplo, "ISO 15930-7") |
required_pdf_version() |
&str |
Versión mínima de PDF (por ejemplo, "1.6") |
allows_transparency() |
bool |
Si se permiten los grupos de transparencia |
allows_rgb() |
bool |
Si se permite el espacio de color RGB |
allows_layers() |
bool |
Si se permiten los grupos de contenido opcional |
allows_external_icc() |
bool |
Si se permiten los perfiles ICC externos |
allows_external_graphics() |
bool |
Si se permiten las referencias a gráficos externos |
gts_pdfx_version() |
&str |
Valor esperado de GTS_PDFXVersion |
xmp_version() |
&str |
Identificador de versión XMP esperado |
from_gts_version(version) |
Option<Self> |
Analiza el nivel a partir de una cadena de versión GTS |
Ejemplo Práctico: Comprobación de Preimpresión
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
- Validación PDF/A – conformidad para archivado
- Accesibilidad PDF/UA – validación de accesibilidad
- Referencia de la API – API completa de Rust