PDF Library for Delphi crea desde Delphi los dos tipos de máscara suave de PDF. SetImageSoftMaskEx vincula una imagen de máscara a una imagen de destino y puede escribir la entrada /Matte que necesita el arte premultiplicado. NewSoftMaskGraphicsState construye una máscara de alfa o de luminosidad a partir de contenido capturado y devuelve un estado gráfico que aplicas al dibujo posterior. Y cuando un consumidor no puede manejar transparencia en absoluto, FlattenTransparency renderiza el resultado visual y sustituye cada página por él
Las máscaras suaves son la forma en que PDF expresa un desvanecido en degradado, una viñeta, una foto fundida sobre un fondo, y cualquier otro efecto donde la opacidad varía a través de una región. La transparencia constante es un único número en el estado gráfico; una máscara suave es toda una función de la posición, y hasta que puedas crear una, toda una categoría de diseño no se puede reproducir
Los dos tipos de máscara, y qué lee cada uno
Una máscara de alfa toma sus valores del canal alfa del contenido enmascarante. Una máscara de luminosidad los toma del brillo del contenido enmascarante, de modo que un área blanca es totalmente opaca y un área negra totalmente transparente. La luminosidad es la que eligen los diseñadores, porque pintar un degradado en escala de grises es una forma natural de describir un desvanecido
Las máscaras suaves de tipo Form se construyen a partir de contenido capturado, y varios detalles son fijos y no opcionales. El contenido capturado se convierte en un grupo de transparencia aislado en DeviceRGB, de modo que la máscara se evalúa en un espacio de color conocido. El color de fondo debe por tanto tener tres componentes, en concordancia con ese grupo. La función de transferencia acepta /Identity o un objeto de función válido, lo que te permite remodelar la curva de la máscara sin repintar el arte
uses
PDFlibrary;
var
Lib: TPDFlib;
MaskCapture, MaskGS, PhotoID: Integer;
begin
Lib := TPDFlib.Create;
try
Lib.LoadFromFile('brochure.pdf', '');
// La página 4 lleva un degradado en escala de grises pintado para usarse como máscara
MaskCapture := Lib.CapturePage(4);
MaskGS := Lib.NewSoftMaskGraphicsState(MaskCapture,
PDF_SOFT_MASK_LUMINOSITY, '0 0 0', '/Identity');
Lib.SelectPage(1);
Lib.SetGraphicsState(MaskGS);
PhotoID := Lib.AddImageFromFile('hero.jpg', 0);
Lib.SelectImage(PhotoID);
Lib.DrawImage(40, 700, 515, 260); // se desvanece bajo la máscara
// Los ajustes de ExtGState persisten: cierra el ámbito explícitamente
Lib.SetGraphicsState(Lib.NewSoftMaskGraphicsState(0,
PDF_SOFT_MASK_NONE, '', ''));
Lib.SaveToFile('brochure-masked.pdf');
finally
Lib.Free;
end;
end;
Ese último paso no es decoración. Los parámetros de estado gráfico persisten hasta que se cambian, y aplicar un estado gráfico ordinario después no borra una máscara suave activa. Sin un /SMask /None explícito, todo lo que se dibuje después del arte enmascarado hereda la máscara, uno de los errores más desconcertantes de diagnosticar visualmente
Máscaras de imagen y la entrada Matte
Para el enmascarado a nivel de imagen, la imagen de máscara se normaliza primero a DeviceGray, de modo que una máscara suministrada en cualquier espacio de color se comporte de forma predecible. La entrada opcional /Matte, de uno a cuatro componentes según el espacio de color de la imagen, le dice a un consumidor que los datos de la imagen están premultiplicados contra ese color, lo cual evita el halo oscuro que aparece cuando un arte premultiplicado se compone como si fuera alfa directo
Aquí importan dos salvaguardas. PDF/A-1 y PDF/X-1 prohíben la transparencia, y la llamada se rechaza antes de modificar cualquier objeto, en lugar de producir un archivo que falle la validación más tarde. Y una máscara suave exitosa requiere PDF 1.4, que la biblioteca establece automáticamente — la transparencia no existía antes de esa versión, y una cabecera 1.3 en un archivo que contiene máscaras suaves es sencillamente falsa
Los estados repetidos se reutilizan: el mismo formulario capturado, tipo de máscara, fondo y firma de función de transferencia producen el mismo objeto de estado gráfico en lugar de uno nuevo por llamada. En un documento que enmascara cien imágenes de forma idéntica, eso son noventa y nueve objetos que nunca llegan a escribirse
Por qué aplanar, y qué hace realmente el aplanado
La transparencia sigue siendo la fuente más común de «se ve bien en pantalla y mal en la imprenta». Los RIP más antiguos, algunos sistemas de presentación regulatoria y PDF/X-1a exigen todos un archivo sin ninguna transparencia activa
El aplanado aquí es deliberadamente literal: cada página del rango solicitado se renderiza a un DPI elegido contra un fondo opaco, y el contenido y los recursos de la página se sustituyen por esa única imagen. Como el renderizador produce el resultado compuesto final, esto cubre todo a la vez — grupos de transparencia, modos de fusión, máscaras suaves, patrones y formularios anidados — sin ninguna lógica de aproximación por construcción que pueda salir mal. La memoria de rasterizado pico se mantiene acotada a una página
// Aplana las páginas 1-8 a 300 DPI sobre blanco, y guarda como PDF 1.3
Lib.FlattenTransparency('1-8', 300, $FFFFFF, 0);
Lib.SaveToFile('press-ready.pdf');
El coste es igual de literal: la salida es una imagen, así que el texto deja de ser seleccionable o buscable y los bordes vectoriales se remuestrean al DPI elegido. Aplanar es un paso de entrega, no un paso de edición. Conserva el original transparente y aplana una copia
Páginas rotadas, unidades de usuario y las cajas de página
Una página rotada necesita un cuidado que una implementación ingenua se salta. Tras renderizar, el ancho y el alto visuales se escriben de vuelta en el MediaBox, la unidad de usuario se pliega en el DPI efectivo y el nuevo tamaño de página, y la entrada /Rotate, la unidad de usuario y las cajas de página auxiliares se eliminan
Saltarse eso produce un archivo donde la imagen aplanada es correcta pero un visor la vuelve a rotar, o la escala por una unidad de usuario que ya no aplica. Eliminar las cajas en lugar de recalcularlas es la decisión correcta, porque un TrimBox que describe la geometría previa al aplanado es peor que no tener TrimBox en absoluto
Las anotaciones y los campos de formulario se renderizan en la imagen estática por defecto y se eliminan los objetos interactivos, que es lo que quiere un entregable listo para imprenta. Si conservas los objetos interactivos en su lugar, el paso de anotaciones del renderizador se desactiva para que nada se dibuje dos veces
La comprobación de versión que examina todo
Guardar como PDF 1.3 exige que no quede transparencia en ninguna parte, y la comprobación previa al guardado examina cada objeto indirecto, no solo los alcanzables desde las páginas. Eso es más estricto de lo que parece a primera vista y es correcto: una máscara suave huérfana dejada atrás por una edición anterior sigue estando en el archivo, y un consumidor que recorra objetos en lugar de páginas la encontrará
Para que la degradación de versión sea posible, un paso de marcado y barrido se ejecuta por defecto una vez que cada página objetivo se ha sustituido con éxito, liberando los objetos inalcanzables. La consecuencia a tener en cuenta es que los identificadores de imagen, página capturada y estado gráfico obtenidos antes de ese barrido pueden dejar de ser válidos después. Vuelve a obtener los identificadores de recurso que necesites antes de seguir editando, o desactiva el barrido y acepta que la versión entonces no se podrá rebajar
Dos complementos completan el panorama. El arte vectorial que usa sombreados y degradados en lugar de máscaras se trata en gráficos vectoriales, shaders y degradados, y a menudo es la mejor ruta cuando el efecto se puede expresar como un sombreado. Y si la razón por la que estás aplanando es un requisito de color y no de transparencia, la ruta de conversión de recolorear un documento a otro espacio de color conserva el texto activo donde el aplanado no lo haría
La creación de máscaras suaves, el aplanado y el motor de renderizado que hay detrás se distribuyen en una única biblioteca para Delphi, C++Builder y Free Pascal; la lista completa de funciones está en la página de PDF Library for Delphi