Artículo técnico

Máscaras suaves y aplanado de transparencia en Delphi

PDF Library for Delphi crea ambos tipos de máscara suave de PDF desde Delphi. SetImageSoftMaskEx adjunta una imagen de máscara a una imagen destino y puede escribir la entrada /Matte que necesita el arte pre-multiplicado. NewSoftMaskGraphicsState construye una máscara de alfa o de luminosidad a partir de contenido capturado y devuelve un estado gráfico que usted aplica al dibujo posterior. Y cuando un consumidor no puede manejar transparencia en absoluto, FlattenTransparency renderiza el resultado visual y reemplaza cada página con él

Las máscaras suaves son la forma en que PDF expresa un desvanecido en degradado, una viñeta, una foto mezclada con un fondo, y cualquier otro efecto donde la opacidad varía a lo largo de una región. La transparencia constante es un solo número en el estado gráfico; una máscara suave es toda una función de la posición, y hasta que se pueda crear una, toda una categoría de diseño no se puede reproducir

Los dos tipos de máscara, y qué lee cada una

Una máscara de alfa toma sus valores del canal alfa del contenido de enmascarado. Una máscara de luminosidad los toma del brillo del contenido de enmascarado, 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 lo 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 cual le permite remodelar la curva de la máscara sin volver a pintar el arte

Diagrama que compara las máscaras suaves de luminosidad y de alfa alimentando NewSoftMaskGraphicsState, con un recordatorio de que el estado gráfico persiste hasta que se limpia
Las máscaras de luminosidad leen el brillo, mientras que las máscaras de alfa leen la cobertura, y NewSoftMaskGraphicsState envuelve cualquiera de las dos en un estado gráfico persistente
uses
  PDFlibrary;

var
  Lib: TPDFlib;
  MaskCapture, MaskGS, PhotoID: Integer;
begin
  Lib := TPDFlib.Create;
  try
    Lib.LoadFromFile('brochure.pdf', '');

    // La página 4 contiene 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: termine el alcance 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 del estado gráfico persisten hasta que se cambian, y aplicar un estado gráfico ordinario después no elimina una máscara suave activa. Sin un /SMask /None explícito, todo lo dibujado 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 manera predecible. La entrada opcional /Matte, de uno a cuatro componentes según el espacio de color de la imagen, le indica a un consumidor que los datos de la imagen están pre-multiplicados contra ese color, lo cual evita el halo oscuro que aparece cuando arte pre-multiplicado se compone como si fuera alfa directo

Diagrama que muestra cómo la ausencia de una entrada Matte produce halos oscuros, mientras que un Matte declarado compone con limpieza, junto a las salvaguardas de PDF 1.4, PDF/A y PDF/X
Un /Matte declarado evita el halo oscuro del arte pre-multiplicado, mientras que los archivos PDF/A-1 y PDF/X-1 se rechazan antes de cualquier cambio de objeto

Aquí importan dos salvaguardas. PDF/A-1 y PDF/X-1 prohíben la transparencia, y la llamada se rechaza antes de modificar ningún objeto, en lugar de producir un archivo que falle la validación después. Y una máscara suave exitosa requiere PDF 1.4, lo cual la biblioteca establece automáticamente — la transparencia no existía antes de esa versión, y un encabezado 1.3 en un archivo que contiene máscaras suaves es sencillamente falso

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 se llegan a escribir

Por qué aplanar, y qué hace realmente el aplanado

La transparencia sigue siendo la causa más común de "se ve bien en pantalla y mal en la prensa". 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 reemplazan por esa única imagen. Como el renderizador produce el resultado compuesto final, esto cubre todo a la vez — grupos de transparencia, modos de mezcla, máscaras suaves, patrones y formularios anidados — sin ninguna lógica de aproximación por construcción que pueda salir mal. El pico de memoria de rasterizado se mantiene acotado a una sola página

Diagrama de pipeline de FlattenTransparency renderizando cada página solicitada a 300 DPI sobre un fondo opaco y guardando un archivo PDF 1.3 plano listo para imprenta
Cada página solicitada se renderiza una vez al DPI elegido y regresa como una única imagen opaca guardada en un archivo PDF 1.3 veraz
// Aplanar las páginas 1-8 a 300 DPI sobre blanco, y luego guardar como PDF 1.3
Lib.FlattenTransparency('1-8', 300, $FFFFFF, 0);
Lib.SaveToFile('press-ready.pdf');

La contrapartida es igual de literal: la salida es una imagen, así que el texto ya no se puede seleccionar ni buscar, y los bordes vectoriales se remuestrean al DPI elegido. El aplanado es un paso de entrega, no un paso de edición. Conserve el original con transparencia y aplane una copia

Páginas rotadas, unidades de usuario y los cuadros de página

Una página rotada necesita un cuidado que una implementación ingenua se salta. Después de renderizar, el ancho y el alto visuales se escriben de vuelta en el MediaBox, la unidad de usuario se incorpora al DPI efectivo y al nuevo tamaño de página, y la entrada /Rotate, la unidad de usuario y los cuadros 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 según una unidad de usuario que ya no aplica. Eliminar los cuadros en lugar de recalcularlos 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 dentro de la imagen estática por defecto, y los objetos interactivos se eliminan, que es lo que necesita un entregable listo para imprenta. Si en cambio usted conserva los objetos interactivos, la pasada de anotaciones del renderizador se desactiva para que nada se dibuje dos veces

La verificación de versión que escanea todo

Guardar como PDF 1.3 requiere que no quede transparencia en ningún lugar, y la verificació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 por una edición anterior sigue en el archivo, y un consumidor que recorre objetos en lugar de páginas la encontrará

Para que la bajada de versión sea alcanzable, una pasada de marcado y barrido se ejecuta por defecto una vez que cada página objetivo se ha reemplazado 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. Vuelva a adquirir los identificadores de recurso que necesite antes de seguir editando, o desactive el barrido y acepte que en ese caso la versión no se podrá bajar

Dos complementos redondean el panorama. El arte vectorial que usa sombreados y degradados en lugar de máscaras se cubre en gráficos vectoriales, shaders y degradados, y suele ser la mejor ruta cuando el efecto se puede expresar como un sombreado. Y si la razón por la que usted aplana es un requisito de color y no uno de transparencia, la ruta de conversión de recolorear un documento a otro espacio de color preserva 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 los sostiene se entregan en una sola biblioteca para Delphi, C++Builder y Free Pascal; la lista completa de funciones está en la página de PDF Library for Delphi