Una caja cian se sienta sobre un fondo amarillo, y el estado de gráficos que la pinta carga /op true y /OPM 1. En pantalla el solape es cian plano. En la hoja de imprenta el mismo solape sale verde, porque el RIP dejó la plancha amarilla en paz y puso cian encima. Ambos resultados siguen el archivo al pie de la letra; el render de pantalla simplemente nunca preguntó qué hace un dispositivo de imagen con esa bandera, así que una aprobación hecha en pantalla cubre un color que jamás llega al papel
¿Por qué una página se imprime distinto de cómo se previsualiza?
El overprint es una instrucción al dispositivo de salida sobre planchas, y una pantalla RGB no tiene planchas. ISO 32000-1 §8.6.7 define qué pasa cuando la entrada OP (trazo) o op (relleno) de un ExtGState es true: los colorantes que la pintura actual no nombra conservan lo que ya había en su plancha, en lugar de borrarse a cero. Un objeto cian pintado así no le quita nada a la plancha amarilla. Un visor que compone en RGB no tiene dónde guardar el amarillo, así que pinta cian por encima y sigue
Ninguna salida está rota. El desacuerdo está construido dentro de los dos modelos de imagen, y permanece invisible hasta que alguien sostiene una prueba impresa junto al monitor. Eso ya es tarde para un diseñador que puso texto negro en knockout por error, o que dejó un logo blanco en overprint y esperaba verlo
Activar la prueba con RenderOverprintPreview
HotPDF expone la prueba como un Boolean en el documento, THotPDF.RenderOverprintPreview, que vale False por defecto. Con ella activa, el render a bitmap sigue las planchas de proceso debajo de cada pintura en overprint y aplica las reglas de §8.6.7 antes de escribir el píxel, así que los solapes muestran la combinación de tintas que la imprenta produciría. Dejar el valor por defecto apagado es lo correcto para vista ordinaria, porque los lectores de un PDF de oficina esperan que se vea como su visor usual lo muestra. Actívela en el paso cuya salida va a un operador de preimpresión
var
Pdf: THotPDF;
Device: THPDFBitmapRenderDevice;
Proof: TBitmap;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.LoadFromFile('cover-cmyk.pdf');
Pdf.RenderOverprintPreview := True; // pruebe las planchas, el valor por defecto es False
Device := THPDFBitmapRenderDevice.Create;
try
if Pdf.RenderLoadedPageToDevice(0, 150, Device) then
begin
Proof := Device.TakeBitmap; // el llamador es dueño de Proof desde aquí
try
Image1.Picture.Assign(Proof);
finally
Proof.Free;
end;
end;
finally
Device.Free;
end;
finally
Pdf.Free;
end;
end;
Las reglas de plancha dependen del espacio de color de la pintura en overprint, y valen conocerlas porque cada una explica una sorpresa distinta en una prueba:
- DeviceCMYK bajo
/OPM 1: un componente de cero deja su plancha intacta, un componente distinto de cero la reemplaza. Cian 100 / amarillo 0 sobre un fondo amarillo conserva el amarillo y se pone verde - DeviceGray: la pintura nombra solo la plancha negra, así que el cian, el magenta y el amarillo de debajo sobreviven. Un logo DeviceGray blanco puesto en overprint sobre un fondo CMY por tanto desaparece
- Separation y DeviceN: un colorante llamado
Cyan,Magenta,YellowoBlackreemplaza esa plancha de proceso directamente,/Noneno pinta nada en absoluto, y/Allescribe todas las planchas de proceso - Colorantes directas: cualquier otro nombre se trata como una tinta directa (spot); su transformación de tinte da un color alterno, que se multiplica sobre las planchas de proceso de debajo, así que la directa oscurece lo que cubre en lugar de reemplazarlo
La prueba aplica a paths rellenos y de trazo y al texto, incluido el texto en modo de render de trazo, donde la bandera de trazo OP decide en lugar de op. Las imágenes, las imágenes en línea y los sombreados sh siguen por sus pipelines de color raster completos y pintan con su opacidad ordinaria. En la práctica eso cubre lo que los reportes preflight marcan más: reglas de overprint, keylines, tipografía y tintas planas
La transparencia sigue viva con la prueba activa. Un grupo de transparencia con knockout configurado igual hace knockout, y el grupo se compone en la misma pasada que las reglas de overprint, así que un archivo listo para imprenta con arte transparente sobre un fondo negro en overprint prueba ambos efectos juntos. Acertar con uno y fallar con el otro solo produciría una prueba equivocada distinta
El ajuste también toma parte en la identidad de los renders cacheados. RenderLoadedPageToBitmapCached construye sus claves sobre página, DPI y una variante construida desde los ajustes de render que incluyen RenderOverprintPreview, y el nivel de disco usa la misma variante. Un visor que alterna entre vista normal y vista de prueba recibe dos entradas de caché separadas y nunca necesita una llamada a InvalidateRenderedPageCache solo porque el interruptor cambió
La trampa del /OPM 0 en archivos DeviceCMYK
Este es el caso que manda a la gente a buscar un bug. Un archivo pone /op true en un relleno DeviceCMYK cian pero deja OPM en su valor por defecto de 0, y aun así la prueba muestra cian haciendo knockout del amarillo. La prueba está en lo correcto. Bajo el modo de overprint 0, §8.6.7 dice que una pintura DeviceCMYK establece los cuatro colorantes de proceso, ceros incluidos, así que el componente amarillo cero reemplaza la plancha amarilla exactamente como lo haría un knockout. El modo de overprint 0 solo protege las planchas que la pintura no nombra, lo que para un color CMYK de cuatro componentes significa planchas directas y nada más
Sobre las planchas de proceso que muestra una prueba compuesta, el modo 0 y un knockout plano dan los mismos píxeles, así que HotPDF pinta esos objetos DeviceCMYK como knockouts ordinarios. Para que un objeto CMYK haga overprint sobre otras tintas de proceso, el ExtGState que carga /op true también necesita /OPM 1. Cuando una prueba y la intención del diseñador discrepan sobre un objeto DeviceCMYK, abra ese ExtGState y busque la entrada OPM antes de sospechar de cualquier otra cosa
La sorpresa inversa también existe. Bajo /OPM 1, el blanco CMYK son cuatro ceros, y cuatro ceros bajo overprint dejan cada plancha como estaba. El texto blanco puesto en overprint se esfuma en la hoja, y la prueba muestra que se esfuma, que es toda la razón para correr una
Tres dispositivos detrás de RenderLoadedPageToDevice
THotPDF.RenderLoadedPageToDevice(PageIndex, DPI, Device) es un punto de entrada único cuyo objetivo lo decide el objeto de dispositivo que usted pasa. Lanza una excepción para un dispositivo nil, trata un DPI por debajo de 1 como 150, y devuelve lo que el dispositivo reporte desde su método Execute. THPDFRenderDevice es la base abstracta con dos miembros virtuales: Kind, que devuelve rdkBitmap, rdkDeviceContext o rdkEnhancedMetafile, y Execute(Document, PageIndex, DPI)
Los tres dispositivos incluidos poseen su salida de maneras distintas:
THPDFBitmapRenderDevicesostiene unTBitmapen su propiedadBitmapy lo libera en su destructor a menos queTakeBitmapse lo haya entregado antesTHPDFDeviceContextRenderDevice.Create(ADC, AWidth, AHeight)dibuja en unHDCque usted ya tiene y no posee nada; el constructor lanza ante un DC cero o un tamaño no positivo, y no se pinta ningún fondo, así que un DC de pantalla necesita su propio relleno blancoTHPDFMetafileRenderDevicesostiene unTMetafilehasta queTakeMetafilelo transfiere. El texto y los paths vectoriales siguen escalables en el metarchivo mejorado, mientras que los image XObjects llegan rasterizados
La propiedad sigue las reglas planas de Delphi. Lea la propiedad Bitmap o Metafile cuando el objeto solo necesita vivir tanto como el dispositivo; llame al método Take cuando tiene que sobrevivirlo. Tome el bitmap, libere el dispositivo, olvide el bitmap, y el leak crece con el conteo de páginas: invisible en una muestra de cinco páginas, obvio en un lote de quinientas. Dele a cada objeto su propio try/finally y la pregunta de quién libera qué se responde sola
Despache sobre Kind en el código de la aplicación en lugar de probar is THPDFBitmapRenderDevice. Como Execute y Kind son métodos virtuales públicos, puede escribir su propia clase de dispositivo, y el código que verifica el tipo sigue funcionando cuando uno suyo hace de substituto de un dispositivo incluido
¿Por qué un render a impresora aterriza en una esquina?
La ruta de contexto de dispositivo dimensiona la página desde el argumento DPI, no desde el ancho y alto que usted pasa. El renderizador escala las unidades PDF por DPI / 72 y usa la altura solo para anclar el origen de página al fondo de la superficie. Fije 300 a piedra y mande el trabajo a una impresora de 600 dpi, y la página sale a la mitad de tamaño, empujada a la esquina inferior izquierda de la hoja. La resolución de impresora es una propiedad del driver, así que pregúntele al driver:
procedure PrintPage(Pdf: THotPDF; PageIndex: Integer);
var
Device: THPDFDeviceContextRenderDevice;
PrinterDPI, W, H, Tmp: Integer;
L, B, R, T: Single;
begin
if not Pdf.GetLoadedPageVisibleBox(PageIndex, L, B, R, T) then
Exit;
Printer.BeginDoc;
try
// pregúntele al driver; 300, 600 y 1200 dpi son todos comunes
PrinterDPI := GetDeviceCaps(Printer.Handle, LOGPIXELSX);
W := Round((R - L) * PrinterDPI / 72);
H := Round((T - B) * PrinterDPI / 72);
if (Pdf.GetLoadedPageRotation(PageIndex) mod 180) = 90 then
begin
Tmp := W; W := H; H := Tmp; // intercambio para páginas 90 / 270
end;
Device := THPDFDeviceContextRenderDevice.Create(
Printer.Canvas.Handle, W, H);
try
Pdf.RenderLoadedPageToDevice(PageIndex, PrinterDPI, Device);
finally
Device.Free;
end;
finally
Printer.EndDoc;
end;
end;
El ancho y el alto vienen de la caja visible de la página, la CropBox recortada a la MediaBox, a la resolución propia de la impresora, y el llamador los intercambia para páginas rotadas antes de crear el dispositivo. Eso coincide con lo que el renderizador espera cuando ancla el origen
La prueba de overprint no viaja por esta ruta. Los dispositivos de contexto de dispositivo y metarchivo emiten llamadas GDI directo al objetivo, y las reglas de plancha necesitan los píxeles ya debajo de cada pintura, que solo tiene el render a bitmap. Para una prueba en papel, renderice el bitmap de prueba y estírelo sobre el canvas de la impresora. Un pequeño dispositivo a medida mantiene eso detrás del mismo punto de entrada:
type
// un dispositivo suyo: bitmap de prueba, luego estirado sobre la impresora
TPrinterProofDevice = class(THPDFRenderDevice)
public
function Kind: THPDFRenderDeviceKind; override;
function Execute(Document: THotPDF; PageIndex, DPI: Integer): boolean;
override;
end;
function TPrinterProofDevice.Kind: THPDFRenderDeviceKind;
begin
Result := rdkDeviceContext;
end;
function TPrinterProofDevice.Execute(Document: THotPDF;
PageIndex, DPI: Integer): boolean;
var
Proof: TBitmap;
OldProof: Boolean;
begin
OldProof := Document.RenderOverprintPreview;
Document.RenderOverprintPreview := True;
try
Proof := Document.RenderLoadedPageToBitmap(PageIndex, DPI);
finally
Document.RenderOverprintPreview := OldProof; // deje el ajuste del llamador como estaba
end;
Result := Proof <> nil;
if Result then
try
Printer.Canvas.StretchDraw(
Rect(0, 0, Printer.PageWidth, Printer.PageHeight), Proof);
finally
Proof.Free;
end;
end;
Llámelo entre Printer.BeginDoc y Printer.EndDoc con un DPI que le dé al bitmap suficientes píxeles para la hoja, alrededor de 200 a 300 para una prueba tamaño carta. El rectángulo de estiramiento de arriba llena el área imprimible; conserve la relación de aspecto de la página dentro si la página y el papel difieren de forma
Dónde encaja la prueba junto al preflight
La prueba responde una pregunta: qué tintas sobreviven donde los objetos se solapan. Se compone sobre el mismo bitmap RGB de 24 bits que cualquier otro render, así que sus colores muestran la combinación de tintas y no un color de hoja medido. Las condiciones de imprenta son una cuestión de gestión de color, y el documento las maneja a través de ConfigureRenderICCWorkflow, que toma un perfil de prueba, un perfil de salida y una bandera de compensación de punto negro, y ClearRenderICCWorkflow para soltarlos otra vez
El lugar más productivo para un render de prueba es junto a las verificaciones que usted ya corre. Una pasada preflight reporta que el texto negro está en overprint; el render de prueba le muestra al operador qué hace eso en la página; ambos aterrizan en el mismo reporte. El trabajo de packaging tiende a mezclar overprint con tintas directas, y el recorrido de renderizado de colorantes directas Separation y DeviceN cubre el lado de colorantes de la misma página, incluidas vistas de una sola plancha vía RenderLoadedPageSeparationPlate. Los artículos sobre renderizar una página PDF a un bitmap y imprimir un PDF cargado por TPrinter cubren los dos objetivos de dispositivo en su forma plana
Todo esto corre en código Delphi y C++Builder nativo sin ninguna DLL de renderizado que distribuir junto al ejecutable. La página del componente HotPDF para Delphi lista las funciones de renderizado y preimpresión y tiene una build de prueba para correr estos ejemplos contra sus propios archivos de imprenta