Un box ciano sta su uno sfondo giallo, e lo stato grafico che lo dipinge porta /op true e /OPM 1. A schermo la sovrapposizione è ciano piatto. Sul foglio di stampa la stessa sovrapposizione viene fuori verde, perché il RIP ha lasciato stare la lastra gialla e ha posato il ciano sopra. Entrambi i risultati seguono il file alla lettera; il render a schermo semplicemente non ha mai chiesto cosa fa un device di imaging con quel flag, quindi un'approvazione data a schermo copre un colore che non arriva mai alla carta
Perché una pagina si stampa diversamente da come si vede in anteprima?
L'overprint è un'istruzione al device di output sulle lastre, e uno schermo RGB non ha lastre. ISO 32000-1 §8.6.7 definisce cosa succede quando la voce OP (stroke) o op (fill) di un ExtGState è true: i coloranti che la vernice corrente non nomina conservano ciò che era già sulla loro lastra, invece di essere cancellati a zero. Un oggetto ciano dipinto così non toglierebbe nulla dalla lastra gialla. Un viewer che compone in RGB non ha dove tenere il giallo, quindi dipinge il ciano sopra e va avanti
Nessuno dei due output è rotto. Il disaccordo è costruito dentro i due modelli di imaging, e resta invisibile finché qualcuno non tiene una prova stampata accanto al monitor. È tardi nel lavoro per un designer che ha impostato il testo nero in knockout per sbaglio, o che ha lasciato un logo bianco in overprint aspettandosi che si vedesse
Attivare il proof con RenderOverprintPreview
HotPDF espone il proof come un Boolean sul documento, THotPDF.RenderOverprintPreview, che vale False per predefinito. Con esso impostato, il render bitmap tiene traccia delle lastre di processo sotto ogni vernice in overprint e applica le regole del §8.6.7 prima di scrivere il pixel, così le sovrapposizioni mostrano la combinazione di inchiostri che la stampa produrrebbe. Lasciare il predefinito spento è giusto per la visualizzazione ordinaria, perché i lettori di un PDF d'ufficio si aspettano che sembri come lo mostra il loro viewer abituale. Accendetelo nel passo il cui output va a un operatore di prestampa
var
Pdf: THotPDF;
Device: THPDFBitmapRenderDevice;
Proof: TBitmap;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.LoadFromFile('cover-cmyk.pdf');
Pdf.RenderOverprintPreview := True; // prova le lastre, il predefinito è False
Device := THPDFBitmapRenderDevice.Create;
try
if Pdf.RenderLoadedPageToDevice(0, 150, Device) then
begin
Proof := Device.TakeBitmap; // il chiamante possiede Proof da qui
try
Image1.Picture.Assign(Proof);
finally
Proof.Free;
end;
end;
finally
Device.Free;
end;
finally
Pdf.Free;
end;
end;
Le regole delle lastre dipendono dallo spazio colore della vernice in overprint, e valgono la pena essere conosciute perché ognuna spiega una sorpresa diversa su una prova:
- DeviceCMYK sotto
/OPM 1: una componente a zero lascia la sua lastra intatta, una componente non nulla la sostituisce. Ciano 100 / giallo 0 su uno sfondo giallo conserva il giallo e diventa verde - DeviceGray: la vernice nomina solo la lastra nera, quindi ciano, magenta e giallo sotto sopravvivono. Un logo DeviceGray bianco impostato in overprint su un fondo CMY quindi sparisce
- Separation e DeviceN: un colorante chiamato
Cyan,Magenta,YellowoBlacksostituisce direttamente quella lastra di processo,/Nonenon dipinge affatto, e/Allscrive ogni lastra di processo - Coloranti spot: ogni altro nome è trattato come inchiostro spot; la sua tint transform dà un colore alternativo, che viene moltiplicato sulle lastre di processo sotto, così lo spot scurisce ciò che copre invece di sostituirlo
Il proof si applica ai path riempiti e tracciati e al testo, incluso il testo in modalità di render stroke, dove decide il flag stroke OP invece di op. Immagini, immagini inline e shading sh continuano per le loro pipeline colore raster complete e dipingono con la loro opacità ordinaria. In pratica copre ciò che i report di preflight segnalano più spesso: regole di overprint, keyline, testo e tinte piatte
La trasparenza resta viva mentre il proof è acceso. Un gruppo di trasparenza con knockout impostato fa comunque knockout, e il gruppo viene composto nello stesso passaggio delle regole di overprint, quindi un file pronto stampa con artwork trasparente sopra uno sfondo nero in overprint prova entrambi gli effetti insieme. Centrarne uno e sbagliare l'altro produrrebbe solo un proof sbagliato diverso
L'impostazione partecipa anche all'identità dei render in cache. RenderLoadedPageToBitmapCached chiava le sue voci su pagina, DPI e una variante costruita dalle impostazioni di render che includono RenderOverprintPreview, e il tier su disco usa la stessa variante. Un viewer che oscilla tra anteprima normale e proof prende due voci di cache separate e non ha mai bisogno di una chiamata a InvalidateRenderedPageCache solo perché il toggle è cambiato
La trappola /OPM 0 nei file DeviceCMYK
Ecco il caso che manda la gente a cercare un bug. Un file imposta /op true su un riempimento DeviceCMYK ciano ma lascia OPM al suo predefinito di 0, e poi il proof mostra comunque il ciano che fa knockout del giallo. Il proof è corretto. Sotto modalità overprint 0, il §8.6.7 dice che una vernice DeviceCMYK imposta tutti e quattro i coloranti di processo, zeri inclusi, quindi la componente gialla a zero sostituisce la lastra gialla esattamente come farebbe un knockout. La modalità overprint 0 protegge solo le lastre che la vernice non nomina, che per un colore CMYK a quattro componenti significa lastre spot e nient'altro
Sulle lastre di processo che un proof composito mostra, modalità 0 e un knockout semplice danno gli stessi pixel, quindi HotPDF dipinge quegli oggetti DeviceCMYK come knockout ordinari. Perché un oggetto CMYK faccia overprint degli altri inchiostri di processo, l'ExtGState che porta /op true vuole anche /OPM 1. Quando un proof e l'intenzione del designer sono in disaccordo su un oggetto DeviceCMYK, aprite quell'ExtGState e cercate la voce OPM prima di sospettare qualunque altra cosa
La sorpresa inversa esiste pure. Sotto /OPM 1, il bianco CMYK è quattro zeri, e quattro zeri in overprint lasciano ogni lastra com'era. Il testo bianco impostato in overprint sparisce sul foglio, e il proof lo mostra sparire, che è tutta la ragione per farne uno
Tre device dietro a RenderLoadedPageToDevice
THotPDF.RenderLoadedPageToDevice(PageIndex, DPI, Device) è un punto d'ingresso unico la cui destinazione è decisa dall'oggetto device che passate. Genera un'eccezione per un device nil, tratta un DPI sotto 1 come 150, e restituisce ciò che il device riporta dal suo metodo Execute. THPDFRenderDevice è la base astratta con due membri virtuali: Kind, che restituisce rdkBitmap, rdkDeviceContext o rdkEnhancedMetafile, e Execute(Document, PageIndex, DPI)
I tre device spediti possiedono il loro output in modi diversi:
THPDFBitmapRenderDevicetiene unTBitmapnella sua proprietàBitmape lo libera nel suo distruttore a meno cheTakeBitmapve lo abbia prima consegnatoTHPDFDeviceContextRenderDevice.Create(ADC, AWidth, AHeight)disegna in unHDCche avete già e non possiede nulla; il costruttore genera un'eccezione su un DC a zero o una dimensione non positiva, e nessuno sfondo viene dipinto, quindi un DC di schermo vuole il suo riempimento biancoTHPDFMetafileRenderDevicetiene unTMetafilefinchéTakeMetafilenon lo trasferisce. Testo e path vettoriali restano scalabili nel metafile enhanced, mentre gli image XObject arrivano rasterizzati
L'ownership segue le regole Delphi ordinarie. Leggete la proprietà Bitmap o Metafile quando l'oggetto deve vivere solo quanto il device; chiamate il metodo Take quando deve sopravvivergli. Prendete la bitmap, liberate il device, dimenticate la bitmap, e il leak cresce col numero di pagine: invisibile su un campione di cinque pagine, ovvio su un batch da cinquecento. Date a ogni oggetto il suo try/finally e la domanda di chi libera cosa si risponde da sola
Comutate su Kind nel codice applicativo invece di testare is THPDFBitmapRenderDevice. Dato che Execute e Kind sono metodi virtuali pubblici, potete scrivere la vostra classe device, e il codice che controlla il kind continua a funzionare quando una delle vostre fa il verso a un device spedito
Perché un render su stampante atterra in un angolo?
Il percorso device context dimensiona la pagina dall'argomento DPI, non dalla larghezza e altezza che passate. Il renderer scala le unità PDF per DPI / 72 e usa l'altezza solo per ancorare l'origine pagina al fondo della superficie. Fissate 300 nel codice e mandate il job a una stampante da 600 dpi, e la pagina viene fuori a metà dimensione, spinta in basso a sinistra del foglio. La risoluzione della stampante è una proprietà del driver, quindi chiedetela 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
// chiedete al driver; 300, 600 e 1200 dpi sono tutti comuni
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; // scambio per pagine 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;
Larghezza e altezza arrivano dal box visibile della pagina, il CropBox ritagliato al MediaBox, alla risoluzione della stampante stessa, e il chiamante li scambia per le pagine ruotate prima di creare il device. Questo corrisponde a ciò che il renderer si aspetta quando ancora l'origine
Il proofing overprint non viaggia giù per questo percorso. I device device-context e metafile emettono chiamate GDI dritte nella destinazione, e le regole delle lastre vogliono i pixel già presenti sotto ogni vernice, cosa che solo il render bitmap ha. Per una prova su carta, renderizzate la bitmap del proof e stendetela sulla canvas della stampante. Un piccolo device custom tiene tutto dietro lo stesso punto d'ingresso:
type
// un device vostro: bitmap del proof, poi stesa sulla stampante
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; // lascia l'impostazione del chiamante com'era
end;
Result := Proof <> nil;
if Result then
try
Printer.Canvas.StretchDraw(
Rect(0, 0, Printer.PageWidth, Printer.PageHeight), Proof);
finally
Proof.Free;
end;
end;
Chiamatelo tra Printer.BeginDoc e Printer.EndDoc con un DPI che dia alla bitmap abbastanza pixel per il foglio, intorno a 200-300 per una prova in formato lettera. Il rettangolo di stretch sopra riempie l'area stampabile; conservateci il rapporto d'aspetto della pagina se pagina e carta differiscono nella forma
Dove il proofing sta accanto al preflight
Il proof risponde a una domanda: quali inchiostri sopravvivono dove gli oggetti si sovrappongono. Viene composto sulla stessa bitmap RGB a 24 bit di qualunque altro render, quindi i suoi colori mostrano la combinazione di inchiostri piuttosto che un colore di foglio misurato. Le condizioni di stampa sono una questione di color management, e il documento le gestisce tramite ConfigureRenderICCWorkflow, che prende un profilo proof, un profilo output e un flag di black point compensation, e ClearRenderICCWorkflow per toglierli di nuovo
Il posto più produttivo per un render di proof è accanto ai controlli che già eseguite. Un passaggio di preflight riporta che il testo nero è impostato in overprint; il render del proof mostra all'operatore cosa fa sulla pagina; entrambi atterrano nello stesso report. Il lavoro di packaging tende a mescolare overprint con inchiostri spot, e la guida di rendering di colori spot Separation e DeviceN copre il lato coloranti della stessa pagina, incluse le viste a lastra singola tramite RenderLoadedPageSeparationPlate. Gli articoli su renderizzare una pagina PDF in una bitmap e stampare un PDF caricato attraverso TPrinter coprono le due destinazioni device nella loro forma semplice
Tutto questo gira in codice Delphi e C++Builder nativo senza alcuna DLL di rendering da spedire accanto all'eseguibile. La pagina del componente Delphi HotPDF elenca le funzionalità di rendering e prestampa e ha una build di prova per eseguire questi esempi sui vostri file di stampa