Artículo técnico

Convertir un PDF a un único espacio de color en Delphi

RecolorDocument traslada todo un PDF a un único espacio de color, y RecolorPage hace lo mismo para una sola página. Ambos toman 1 para escala de grises, 2 para RGB y 3 para CMYK, y devuelven cuántos colores se convirtieron. La geometría, el texto y las imágenes se quedan exactamente donde estaban; solo cambia el color

Esta es la operación que quieres antes de enviar trabajo a una prensa que espera un único espacio, o cuando un documento a color tiene que volverse de grises sin regenerarse. La alternativa — reconstruir el documento a partir de sus datos de origen en el espacio destino — solo está disponible cuando todavía tienes los datos de origen, lo cual para cualquier cosa recibida de fuera no ocurre

Qué se convierte, y en qué orden

Primero los operadores de color: los rellenos y trazos que una página establece al dibujar. Un color que ya está en el espacio destino se deja tal cual, así que una página cuyos colores no necesitan cambios conserva sus bytes originales en vez de reescribirse a valores idénticos. Esa propiedad importa más de lo que parece en un documento grande, porque los objetos no tocados se quedan sin tocar en el archivo

Luego vienen las imágenes, y son la parte que solía faltar. Un documento vuelto grises con solo sus operadores convertidos seguía mostrando imágenes a color sobre páginas en gris, lo cual es peor que cualquiera de los dos extremos. Una imagen se convierte cuando lleva ocho bits por componente, un espacio de color de dispositivo, y sin compresión o solo Flate

Las imágenes indexadas se convierten a través de su tabla de colores: la paleta se convierte y cada muestra conserva el índice que ya tenía. Eso cubre las imágenes con paleta en las que suele guardarse una captura de pantalla o un gráfico, y las convierte sin importar cómo estén empaquetadas o comprimidas sus muestras, porque las muestras nunca cambian

var
  Lib: TPDFlib;
  Converted: Integer;
begin
  Lib := TPDFlib.Create;
  try
    Lib.LoadFromFile('brochure.pdf', '');
    Converted := Lib.RecolorDocument(1);       // 1 grey, 2 RGB, 3 CMYK
    Log(Format('%d colours converted', [Converted]));
    Lib.SaveToFile('brochure-grey.pdf');
  finally
    Lib.Free;
  end;
end;

¿Por qué un JPEG se deja tal cual?

Porque convertir sus colores significaría recodificarlo, y recodificar es una operación distinta con consecuencias distintas. Una imagen JPEG o de fax conserva sus propios bytes: decodificar, convertir y recomprimir cambiaría los datos de la imagen misma, introduciría una segunda generación de artefactos con pérdida, y cambiaría el tamaño del archivo de formas que quien llama no pidió

Las máscaras suaves y las máscaras de plantilla se dejan tal cual por una razón distinta. Ambas se leen como cobertura en vez de como color, y convertir una dejaría la página mostrando la máscara como una imagen — una máscara de transparencia renderizada como arte en gris encima del contenido que se suponía debía modelar. Dejarlas no es una limitación que haya que sortear; es el resultado correcto

Los colores establecidos a través de un espacio ICCBased, Separation, Indexed o Pattern también se dejan como están a nivel de operador. Convertirlos sin leer su perfil cambiaría el aspecto de la página en vez de preservarlo, y un pase de recoloreado cuya promesa entera es la preservación no puede ponerse a adivinar perfiles

Los gradientes se convierten junto con las paradas que los respaldan

Un gradiente es un espacio de color más una función que produce colores en él, y convertir uno sin el otro produce sinsentido — un gradiente convertido cuyas paradas se quedaron atrás se lee como un canal confundido con un nivel de gris, lo cual en una página se ve como una banda del color equivocado por completo. El espacio de color del gradiente y las paradas que lo respaldan se mueven juntos

Los gradientes se encuentran dondequiera que vivan: dado como objeto propio, escrito dentro del patrón que los pinta, o ubicado en los recursos de sombreado de una página. Esa cobertura importa porque las herramientas de diseño los distribuyen de manera distinta, y un conversor que solo manejara una colocación dejaría un documento medio convertido sin un patrón obvio en los fallos

Dos tipos se dejan deliberadamente como están. Un gradiente construido a partir de una función muestreada o PostScript conserva su propia definición, y lo mismo ocurre con los tipos malla, que llevan sus colores en un flujo en vez de en una función. Reescribir cualquiera de los dos es una operación distinta de convertir un color, y hacerlo en silencio dentro de un pase de recoloreado sería una sorpresa

// Convert a single page - useful when only the cover needs to change
Lib.SelectPage(1);
Lib.RecolorPage(3);          // this page to CMYK
Lib.SaveToFile('cover-cmyk.pdf');

Dónde encaja el recoloreado antes de un envío a prensa

Úsalo como un paso de normalización, no como gestión de color. El recoloreado convierte valores entre espacios de dispositivo; no aplica un perfil ICC, no respeta una intención de renderizado ni simula una condición de prensa. Para un trabajo que debe alcanzar una prueba contractual, el flujo basado en perfiles es la respuesta, y el recoloreado es a lo sumo el paso que pone todo en un único espacio primero

Donde se gana su lugar es en el problema ordinario de producción: un envío que debe ser de grises y llega con un logo en RGB, un documento interno que no debe imprimirse a color, un lote de archivos que tiene que estar en un único espacio antes de que un paso de preflight los acepte. Combínalo con una verificación — las notas sobre el preflight de PDF/A y PDF/UA y sobre el banco de trabajo de cumplimiento y firma cubren cómo ejecutar el veredicto como parte del mismo trabajo

Si el documento también necesita que su arte vectorial se examine en vez de convertirse, el recorrido por gráficos vectoriales, sombreadores y gradientes cubre cómo se construyen esos objetos en primer lugar, lo cual es contexto útil para entender qué puede y qué no puede alcanzar un pase de recoloreado

PDFlibPas es una biblioteca PDF nativa en Pascal para Delphi, C++Builder y Lazarus sin runtime externo, así que un paso de normalización de color corre dentro de tu propio servicio en vez de invocar un conversor externo — consulta la página del producto PDFlibPas para la API completa de procesamiento de documentos