6. Espacio de nombres prepress:: — preimpresión
← visual:: · Índice · Siguiente: codes:: →
30 funciones para validar lo que la imprenta necesita comprobar antes de imprimir: cobertura de tinta, separaciones de color, fuentes, filetes y cajas de página.
6.1 Cobertura de tinta (TAC)
El TAC (Total Area Coverage) es la suma de las cuatro tintas en un punto. Pasarse del límite de la máquina provoca repinte, secado lento y transferencia entre pliegos. El límite típico del offset en papel estucado es del 300%.
Hay dos formas de medirlo, y la diferencia importa:
prepress::calculate_exact_tac([pagina]) — el número fiable
Lee los colores declarados en el archivo (operadores de color del PDF). Es el valor real.
check "Límite de tinta" {
tac = prepress::calculate_exact_tac()
assert tac <= 300,
"la cobertura de tinta del #{tac}% supera el límite del 300%"
// Por página, para localizar el problema
doc.pages.each { |page|
valor = prepress::calculate_exact_tac(page.number)
assert valor <= 300,
"página #{page.number}: #{valor}% de tinta"
}
}
prepress::calculate_tac([pagina]) — la estimación
Calcula renderizando la página en RGB. Es un límite inferior: los colores neutros oscuros (negro rico) se colapsan cerca del 100% en la estimación.
check "Comparando los dos métodos" {
print("exacto (declarado en el archivo):", prepress::calculate_exact_tac(), "%")
print("estimado (por renderizado):", prepress::calculate_tac(), "%")
// En archivos reales probados: exacto 324% frente a estimado 299%
// — solo el exacto revela que el archivo se pasó del límite.
}
Usa siempre calculate_exact_tac para validar el límite de tinta. La
estimación sirve para una lectura rápida cuando los colores no están declarados.
prepress::validate_tac_limits([limite])
Verdadero si todas las páginas están dentro del límite (300 por defecto). Usa la estimación por renderizado.
check "Límite según el papel" {
// el papel prensa admite bastante menos tinta que el estucado
assert prepress::validate_tac_limits(240),
"supera el límite del 240% del papel prensa"
}
prepress::calculate_ink_coverage([pagina])
Cobertura media de tinta (%): indica consumo, no riesgo de repinte.
check "Consumo de tinta" {
media = prepress::calculate_ink_coverage()
print("cobertura media:", media, "%")
// Las páginas muy cubiertas encarecen la tirada
assert media < 200, "cobertura media alta: #{media}%"
}
prepress::calculate_tac_by_region(pagina, region)
[tac_maximo, cobertura_media] dentro de un área concreta.
check "Tinta en la zona del plegado" {
// El exceso de tinta en el plegado se cuartea en el acabado
plegado = region(290, 0, 15, 842, "plegado central")
medida = prepress::calculate_tac_by_region(1, plegado)
assert medida.first() < 240,
"TAC del #{medida.first()}% en el plegado (máximo 240%)"
print("media en el plegado:", medida.last(), "%")
}
6.2 Colores y separaciones
prepress::detect_spot_colors()
Lista las tintas especiales (Pantone, barnices, troqueles) declaradas como
Separation o DeviceN.
Las separaciones reservadas
AllyNoneno entran en la lista:Alles una marca de registro, no una tinta.
check "Colores especiales" {
spots = prepress::detect_spot_colors()
print("tintas especiales:", spots.join(", "))
// Un trabajo contratado a cuatro colores no puede llevar tinta extra
assert spots.length == 0,
"el archivo usa una tinta especial no contratada: #{spots.join(", ")}"
}
check "Barniz previsto" {
// Cuando la tinta especial SÍ se espera
spots = prepress::detect_spot_colors()
assert spots.contains("Barniz"),
"falta la capa de barniz localizado"
}
prepress::detect_color_mode()
Devuelve "CMYK", "RGB", "Mixed", "None" u "Other", según las imágenes.
check "Modo de color del documento" {
modo = prepress::detect_color_mode()
assert modo == "CMYK" || modo == "None",
"documento en #{modo} — la impresión offset exige CMYK"
}
prepress::validate_color_space(espacio)
Verdadero si todas las imágenes están en el espacio indicado.
check "Todo en CMYK" {
assert prepress::validate_color_space("DeviceCMYK"),
"hay imágenes fuera del CMYK"
}
prepress::compare_colors_delta_e(color_a, color_b)
Diferencia perceptual entre dos colores (Delta-E CIE76). Los colores son listas: 4 valores = CMYK, 3 = RGB, 1 = gris.
Referencia práctica: un ΔE por debajo de 1 es imperceptible; hasta 3, aceptable en impresión; por encima de 5, visiblemente distinto.
check "Color de marca" {
// El azul corporativo aprobado
marca = [1.0, 0.6, 0.0, 0.1]
usado = [1.0, 0.62, 0.0, 0.12]
diferencia = prepress::compare_colors_delta_e(marca, usado)
assert diferencia < 3.0,
"el color de marca está fuera de norma (ΔE #{diferencia})"
}
prepress::detect_rich_black()
Verdadero si hay negro compuesto por varias tintas (K ≥ 60% con C+M+Y ≥ 20%).
check "Negro de texto correcto" {
// El texto pequeño en negro rico sale con el registro tembloroso
assert !prepress::detect_rich_black(),
"hay negro rico en el archivo — usa negro plano (0/0/0/100) en los textos"
}
prepress::validate_overprint_settings()
Verdadero si ningún overprint está activado.
check "Overprint" {
// Un overprint accidental hace desaparecer elementos en la impresión
assert prepress::validate_overprint_settings(),
"hay overprint activado — comprueba si es intencionado"
}
prepress::validate_output_intent([nombre])
Sin argumento: verdadero si hay un Output Intent declarado. Con nombre: verdadero si el intent contiene el texto indicado.
check "Perfil de salida" {
assert prepress::validate_output_intent(),
"PDF sin Output Intent — la imprenta no sabe el perfil de color de destino"
// Exigiendo un perfil concreto
assert prepress::validate_output_intent("Coated FOGRA39"),
"Output Intent distinto del estándar de la imprenta"
}
prepress::check_rendering_intent([esperado])
Sin argumento: lista los intents declarados. Con argumento: verdadero si todos son el esperado.
check "Rendering intent" {
print("intents en el archivo:", prepress::check_rendering_intent().join(", "))
assert prepress::check_rendering_intent("RelativeColorimetric"),
"rendering intent distinto del estándar de producción"
}
6.3 Filetes y líneas finas
Las líneas muy finas desaparecen en la impresión o salen irregulares.
prepress::detect_hairlines([limite])
Verdadero si hay algún filete por debajo del límite (0,25 pt por defecto).
check "Sin filetes capilares" {
assert !prepress::detect_hairlines(0.25),
"hay filetes por debajo de 0,25 pt — van a desaparecer en la impresión"
}
prepress::detect_hairlines_exact()
Verdadero si hay algún filete con anchura 0: el hairline clásico de PostScript, que la máquina renderiza al mínimo que pueda dar el equipo (impredecible).
check "Filete de anchura cero" {
assert !prepress::detect_hairlines_exact(),
"hay un filete con grosor 0 — define un grosor real"
}
prepress::detect_fine_lines([limite])
Como detect_hairlines, con un límite mayor (1 pt por defecto).
check "Líneas finas sobre fondo de color" {
// Sobre fondo, las líneas por debajo de 1 pt desaparecen
assert !prepress::detect_fine_lines(1.0),
"hay líneas por debajo de 1 pt"
}
prepress::validate_minimum_stroke_width(minimo)
Verdadero si ningún filete está por debajo del mínimo exigido.
check "Grosor mínimo del contrato" {
assert prepress::validate_minimum_stroke_width(0.5),
"el contrato con la imprenta exige filetes de 0,5 pt como mínimo"
}
6.4 Fuentes
prepress::list_fonts()
Nombres de las fuentes usadas.
check "Inventario de fuentes" {
fuentes = prepress::list_fonts()
print("fuentes:", fuentes.join(", "))
assert fuentes.length <= 8,
"#{fuentes.length} fuentes distintas — ¿diseño gráfico inconsistente?"
}
prepress::validate_font_embedding()
Verdadero si todas las fuentes están incrustadas.
check "Fuentes incrustadas" {
assert prepress::validate_font_embedding(),
"hay fuentes sin incrustar — el texto va a cambiar en el RIP"
}
prepress::detect_text_substitution()
Lista las fuentes no incrustadas, que el lector va a sustituir por otras.
check "Qué fuentes faltan" {
faltan = prepress::detect_text_substitution()
assert faltan.length == 0,
"fuentes sin incrustar: #{faltan.join(", ")}"
}
prepress::detect_missing_glyphs()
Lista las fuentes sin tabla de anchuras: el lector tiene que adivinar las métricas, lo que desalinea el texto.
check "Métricas completas" {
problemas = prepress::detect_missing_glyphs()
assert problemas.length == 0,
"fuentes sin tabla de anchuras: #{problemas.join(", ")}"
}
prepress::subset_fonts()
Verdadero si todas las fuentes incrustadas están en subconjunto (solo los glifos usados), que es lo que mantiene el archivo ligero.
check "Fuentes en subconjunto" {
assert prepress::subset_fonts(),
"hay una fuente incrustada entera — el archivo pesa más de lo necesario"
}
prepress::check_font_licensing()
Lista las fuentes con riesgo de licencia: Type3 o no incrustadas.
check "Licencias" {
riesgo = prepress::check_font_licensing()
assert riesgo.length == 0,
"fuentes con riesgo de licencia: #{riesgo.join(", ")}"
}
prepress::validate_font_size([minimo])
Verdadero si ningún texto está por debajo del tamaño mínimo (6 pt por defecto).
check "Legibilidad" {
// Los organismos reguladores exigen un mínimo en los prospectos;
// los contratos tienen exigencias parecidas
assert prepress::validate_font_size(6),
"hay texto por debajo de 6 pt — ilegible una vez impreso"
}
6.5 Páginas y cajas
Las cajas del PDF definen las áreas de trabajo: MediaBox (pliego), BleedBox (sangrado), TrimBox (corte final), CropBox (visualización), ArtBox (contenido).
prepress::get_page_size([pagina])
[anchura, altura] en puntos.
check "Formato" {
tamano = prepress::get_page_size(1)
print("página 1:", tamano.first(), "x", tamano.last(), "pt")
assert abs(tamano.first() - 595.0) < 5, "anchura fuera del A4"
}
prepress::get_page_boxes([pagina])
Lista de las cajas definidas, formateadas como texto.
check "Cajas de la primera página" {
prepress::get_page_boxes(1).each { |caja| print(caja) }
// Ejemplo de salida:
// MediaBox: [0, 0, 467.2, 665.6]
// TrimBox: [35.2, 35.2, 432, 630.4]
}
validate_media_box(), validate_trim_box(), validate_bleed_box()
Verdadero si la caja existe en todas las páginas.
check "Cajas obligatorias para impresión" {
require prepress::validate_media_box()
assert prepress::validate_trim_box(),
"sin TrimBox — la imprenta no sabe dónde cortar"
assert prepress::validate_bleed_box(),
"sin BleedBox — no hay área de sangrado definida"
}
prepress::check_page_geometry([margen])
Verdadero si la BleedBox supera a la TrimBox por el margen indicado en todos los lados, en todas las páginas. Por defecto: 3 mm.
check "Sangrado suficiente" {
// Usa literales de unidad: queda legible y la conversión es automática
assert prepress::check_page_geometry(3mm),
"sangrado menor de 3 mm en alguna página"
// Las imprentas de packaging suelen exigir más
assert prepress::check_page_geometry(5mm),
"esta imprenta exige 5 mm de sangrado"
}
6.6 Ejemplo completo
// offset_revista.pdfl — preflight completo para impresión offset
// Uso: pdfl run offset_revista.pdfl revista.pdf --output html --output-file informe.html
profile "offset-revista" {
const TAC_LIMITE = 300%
const SANGRADO = 3mm
const DPI_MINIMO = 300
check "Cobertura de tinta" tags: ["prepress", "colores"] {
// Siempre el exacto para validar el límite
doc.pages.each { |page|
tac = prepress::calculate_exact_tac(page.number)
assert tac <= TAC_LIMITE,
"página #{page.number}: #{tac}% de tinta (límite #{TAC_LIMITE}%)"
}
print("cobertura media:", prepress::calculate_ink_coverage(), "%")
}
check "Colores" tags: ["prepress", "colores"] {
assert prepress::detect_color_mode() != "RGB", "documento en RGB"
spots = prepress::detect_spot_colors()
assert spots.length == 0, "tinta especial no contratada: #{spots.join(", ")}"
assert !prepress::detect_rich_black(), "negro rico en el texto"
assert prepress::validate_output_intent(), "sin Output Intent"
}
check "Fuentes" tags: ["fuentes"] {
faltan = prepress::detect_text_substitution()
assert faltan.length == 0, "fuentes sin incrustar: #{faltan.join(", ")}"
assert prepress::validate_font_size(6), "texto por debajo de 6 pt"
print("fuentes:", prepress::list_fonts().join(", "))
}
check "Filetes" tags: ["prepress"] {
assert !prepress::detect_hairlines(0.25), "filetes por debajo de 0,25 pt"
assert !prepress::detect_hairlines_exact(), "filete con grosor 0"
}
check "Geometría" tags: ["prepress", "cajas"] {
require prepress::validate_trim_box()
require prepress::validate_bleed_box()
assert prepress::check_page_geometry(SANGRADO),
"sangrado menor de 3 mm"
}
check "Imágenes" tags: ["imagenes"] {
doc.images.each { |img|
assert img.dpi >= DPI_MINIMO,
"imagen en la página #{img.page_number}: #{round(img.dpi)} DPI"
assert img.color_space != "DeviceRGB",
"imagen RGB en la página #{img.page_number}"
}
}
}