Un PDF cuyo encabezado tiene un fondo degradado al estilo de Word o Excel, al renderizarse a una imagen, solía devolver un rectángulo blanco vacío donde debería estar la mezcla de colores. El renderizador de páginas de HotPDF ahora respeta el operador PDF sh (shading, sombreado) para degradados axiales de Tipo 2 y radiales de Tipo 3: evalúa la función del sombreado a lo largo del eje del degradado y dibuja la mezcla, mientras que las versiones anteriores omitían silenciosamente el operador y dejaban la región blanca como el papel. Los dos tipos de sombreado que cubren casi todos los degradados de documentos de oficina están incluidos; los de tipo malla (mesh) no, y este artículo es honesto sobre dónde se encuentra ese límite
Un degradado PDF es una estructura vectorial, no un mapa de bits que el renderizador pueda copiar (blit). Un diccionario de sombreado (ISO 32000-1 §8.7.4.5) describe la geometría —un eje o un par de círculos en la matriz Coords— además de una función de color, y el operador sh observa ese sombreado a través de la región de recorte actual, el mismo modelo gráfico que HotPDF expone cuando usted dibuja rutas y rellenos en el lienzo de una página. El renderizador de páginas de HotPDF recorre el flujo de contenido operador por operador, y cualquier operador para el que no tenga una ruta de código se omite para que el resto de la página se siga renderizando. Antes de la versión 2.335.0, sh residía en ese conjunto omitido: un degradado en el encabezado o en toda la página no aportaba nada a la salida, por lo que el fondo se mostraba de color blanco. El archivo nunca estuvo corrupto. El renderizador simplemente no tenía un controlador para ese operador en particular, y un cuadro blanco es exactamente el aspecto de un controlador ausente
¿Por qué un degradado PDF se renderiza como un cuadro blanco?
¿Por qué un degradado PDF se renderiza como un cuadro blanco?
Un sombreado no se puede dibujar hasta que se evalúe su función, por lo que ese mecanismo tuvo que implementarse primero. Los sombreados axiales de Tipo 2 y radiales de Tipo 3 llevan una /Function que asigna una posición paramétrica a lo largo del degradado a un color (ISO 32000-1 §7.10), y el evaluador de funciones de HotPDF resuelve el FunctionType y lo despacha. La interpolación exponencial de Tipo 2 (§7.10.3) calcula C0 + t^N * (C1 - C0) con delimitación de Domain y Range; las funciones muestreadas de Tipo 0 (§7.10.2) leen una cuadrícula de muestras de 8, 16 o 32 bits y eligen la más cercana a través del mapa Encode, el caso cubierto en detalle en nuestro análisis de búsquedas de color muestreadas de Tipo 0; las funciones de costura (stitching) de Tipo 3 (§7.10.4) seleccionan una subfunción mediante la matriz Bounds y realizan una recursión en ella. Las funciones de calculadora PostScript de Tipo 4 (§7.10.5) no se evalúan; se degradan de forma controlada a una evaluación fallida en lugar de un color incorrecto, lo que coincide con la política conservadora que adopta HotPDF en toda la ruta de renderizado. Este evaluador se lanzó en la versión 2.334.0, una versión antes que el propio operador, porque el dibujador de sombreado es tan bueno como la función subyacente
¿Cómo convierte HotPDF un degradado continuo en píxeles?
HotPDF aproxima la mezcla continua con una ejecución finita de bandas de color sólido. El dibujador de sombreado recorre el eje del degradado, lo divide en hasta 64 bandas —menos cuando el eje es corto en píxeles de dispositivo—, evalúa la función en la posición paramétrica de cada banda y rellena un rectángulo perpendicular al eje con un pincel sólido. El compromiso es el recuento de bandas frente a la suavidad: más bandas siguen la mezcla de manera más precisa pero cuestan más rellenos, y 64 es el límite deliberado. Dado que el recuento también escala con la longitud del eje en píxeles de dispositivo, la resolución importa. Renderizar la misma página a un DPI más alto alarga el eje, por lo que un degradado corto gana bandas y sus franjas se suavizan hasta alcanzar el límite
// The shading discretizer uses up to 64 color bands along the gradient
// axis, but never more than the axis is long in device pixels. Rendering
// the same page at a week DPI lengthens that axis, so a short gradient
// gains bands and the banding softens until the 64-band ceiling is hit.
Thumb := Pdf.RenderLoadedPageToBitmap(PageIndex, 96); // coarser bands
Proof := Pdf.RenderLoadedPageToBitmap(PageIndex, 300); // up to 64 bands
Renderizar una página sombreada a un mapa de bits
El punto de entrada público no cambia: RenderLoadedPageToBitmap toma un índice de página basado en cero y un valor de DPI, devuelve un mapa de bits de 24 bits propiedad del llamador y devuelve nil en caso de fallo en lugar de lanzar una excepción, por lo que el soporte de sombreado es transparente para el código que ya tiene. Una página que solía renderizar su encabezado degradado en blanco ahora devuelve el mismo mapa de bits con la mezcla dibujada, y no se necesita ningún cambio de API para obtenerlo. Lo único que vale la pena recordar es la propiedad: el llamador libera el mapa de bits devuelto. La canalización de renderizado completa —interpretación del flujo de contenido, glifos incrustados y almacenamiento en caché de páginas— se cubre en la guía para renderizar páginas PDF a un mapa de bits en Delphi
var
Pdf: THotPDF;
Bmp: TBitmap;
begin
Pdf := THotPDF.Create(nil);
try
if Pdf.LoadFromFile('quarterly-report.pdf') > 0 then
begin
// Page 1 (zero-based) at 150 DPI. A gradient-filled header that
// used to come back blank now carries its color blend.
Bmp := Pdf.RenderLoadedPageToBitmap(0, 150);
if Assigned(Bmp) then
try
Bmp.SaveToFile('page1.bmp');
finally
Bmp.Free;
end;
end;
finally
Pdf.Free;
end;
end;
Una salvaguarda de regresión sencilla se desprende de la misma llamada. Renderice la página, tome una muestra de un píxel donde pertenece la banda del degradado y confirme que ya no es el blanco papel al que el renderizador solía recurrir —una comprobación de una sola línea que detecta un retorno silencioso al antiguo comportamiento inactivo
Bmp := Pdf.RenderLoadedPageToBitmap(0, 150);
if Assigned(Bmp) then
try
// True when the sh operator painted; False if the region fell back to white.
HeaderPainted := Bmp.Canvas.Pixels[Bmp.Width div 2, 8] <> clWhite;
finally
Bmp.Free;
end;
Lo que HotPDF no pinta: sombreados de malla y bordes de recorte
Los cuatro tipos de sombreado de malla (mesh) están fuera de alcance, y un documento debe saberlo de antemano. Los sombreados de malla triangular de Gouraud de forma libre (Tipo 4), las mallas de Gouraud en forma de red (Tipo 5), las mallas de parche de Coons (Tipo 6) y las mallas de parche de producto tensorial (Tipo 7), definidos en ISO 32000-1 §8.7.4.5.5 a §8.7.4.5.8, no se renderizan; una página que use uno se seguirá renderizando, solo que esa región se dejará tal cual. Vale la pena decir claramente otros dos detalles. Los rectángulos de banda cubren la franja del sombreado en lugar de recortarse exactamente al trazado de recorte actual, por lo que un degradado enmascarado en una forma redondeada o irregular se dibuja como su franja delimitadora hasta que llegue el recorte de región preciso en una etapa posterior. HotPDF también asume que la salida de la función es RGB o escala de grises, por lo que un sombreado creado en CMYK o en un espacio de color exótico se aproxima en lugar de tener gestión de color. Para los documentos que la mayoría de los equipos de Delphi y C++Builder procesan realmente —informes, facturas, estados de cuenta y presentaciones exportadas a PDF—, el axial y el radial cubren básicamente cada degradado que encontrará, y las pruebas de diseño con muchas mallas son el caso a tratar como una vista previa en lugar de una prueba real
El renderizador de páginas de HotPDF, el soporte del operador sh descrito aquí y el evaluador de funciones Tipo 0/2/3 debajo de este se incluyen como parte de HotPDF Component para Delphi y C++Builder —una biblioteca VCL nativa sin dependencias de DLL externas, que cubre la creación, edición, extracción de texto y renderizado de páginas de PDF en un solo paquete