Eine Cyan-Box sitzt auf gelbem Hintergrund, und der Grafikzustand, der sie malt, trägt /op true und /OPM 1. Auf dem Bildschirm ist die Überlappung schlichtes Cyan. Auf dem Druckbogen kommt dieselbe Überlappung grün heraus, denn der RIP hat die gelbe Platte in Ruhe gelassen und Cyan obendrauf gelegt. Beide Ergebnisse folgen der Datei auf den Buchstaben genau; das Screen-Rendering hat nur nie gefragt, was ein Imaging-Gerät mit diesem Flag tut, also deckt eine auf dem Bildschirm erteilte Freigabe eine Farbe ab, die nie das Papier erreicht
Warum druckt eine Seite anders, als sie in der Vorschau erscheint?
Overprint ist eine Anweisung an das Ausgabegerät über Druckplatten, und ein RGB-Bildschirm hat keine Platten. ISO 32000-1 §8.6.7 definiert, was passiert, wenn der OP-Eintrag (Stroke) oder op-Eintrag (Fill) eines ExtGState auf true steht: Die Farbstoffe, die der aktuelle Farbauftrag nicht nennt, behalten, was bereits auf ihrer Platte liegt, statt auf null radiert zu werden. Ein so gemaltes Cyan-Objekt nimmt der gelben Platte nichts weg. Ein Viewer, der in RGB compositet, hat nirgendwo, um das Gelb zu behalten, also malt er Cyan obendrauf und macht weiter
Keine der beiden Ausgaben ist kaputt. Die Diskrepanz steckt in den beiden Imaging-Modellen, und sie bleibt unsichtbar, bis jemand einen gedruckten Proof neben den Monitor hält. Das ist spät im Job für einen Designer, der schwarzen Text versehentlich auf Knockout stellte, oder der ein weißes Logo auf Overprint ließ und erwartete, dass es erscheint
Den Proof mit RenderOverprintPreview einschalten
HotPDF legt den Proof als ein einziges Boolean am Dokument offen, THotPDF.RenderOverprintPreview, das auf False voreingestellt ist. Gesetztermaßen verfolgt das Bitmap-Rendering die Prozessplatten unter jedem überdruckenden Farbauftrag und wendet die §8.6.7-Regeln an, bevor es das Pixel schreibt, also zeigen Überlappungen die Tintenkombination, die die Druckmaschine erzeugen würde. Den Standard ausgeschaltet zu lassen ist für gewöhnliches Betrachten richtig, denn Leser eines Office-PDFs erwarten, dass es so aussieht, wie ihr gewohnter Viewer es zeigt. In dem Schritt einschalten, dessen Ausgabe zu einem Prepress-Betreiber geht
var
Pdf: THotPDF;
Device: THPDFBitmapRenderDevice;
Proof: TBitmap;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.LoadFromFile('cover-cmyk.pdf');
Pdf.RenderOverprintPreview := True; // die Platten proofen, Standard ist False
Device := THPDFBitmapRenderDevice.Create;
try
if Pdf.RenderLoadedPageToDevice(0, 150, Device) then
begin
Proof := Device.TakeBitmap; // der Aufrufer besitzt Proof ab hier
try
Image1.Picture.Assign(Proof);
finally
Proof.Free;
end;
end;
finally
Device.Free;
end;
finally
Pdf.Free;
end;
end;
Die Platten-Regeln hängen vom Farbraum des überdruckenden Farbauftrags ab, und sie zu kennen lohnt sich, denn jede erklärt eine andere Überraschung auf einem Proof:
- DeviceCMYK unter
/OPM 1: eine Komponente null lässt ihre Platte unangetastet, eine Komponente ungleich null ersetzt sie. Cyan 100 / Gelb 0 über gelbem Hintergrund behält das Gelb und wird grün - DeviceGray: Der Farbauftrag nennt nur die schwarze Platte, also überleben Cyan, Magenta und Gelb darunter. Ein weißes DeviceGray-Logo auf Overprint gestellt verschwindet daher auf einem CMY-Hintergrund
- Separation und DeviceN: Ein Farbstoff namens
Cyan,Magenta,YellowoderBlackersetzt diese Prozessplatte direkt,/Nonemalt überhaupt nichts, und/Allschreibt jede Prozessplatte - Spot-Farbstoffe: Jeder andere Name wird als Spot-Tinte behandelt; seine Tint-Transform liefert eine Alternativfarbe, die über die darunterliegenden Prozessplatten multipliziert wird, also verdunkelt der Spot, was er deckt, statt es zu ersetzen
Der Proof gilt für gefüllte und gestrichene Pfade und für Text, eingeschlossen Text im Stroke-Render-Modus, wo das Stroke-Flag OP statt op entscheidet. Bilder, Inline-Bilder und sh-Shadings laufen weiterhin durch ihre vollen Raster-Farb-Pipelines und malen mit ihrer gewöhnlichen Deckkraft. In der Praxis deckt das, was Preflight-Reports am meisten markieren: Overprint-Regeln, Keylines, Schriften und flache Tints
Transparenz bleibt live, während der Proof an ist. Eine Transparenzgruppe mit gesetztem Knockout stanzt weiterhin aus, und die Gruppe wird im selben Durchgang wie die Overprint-Regeln composited, also proofed eine druckfertige Datei mit transparenter Grafik über einem überdruckenden schwarzen Hintergrund beide Effekte zusammen. Einen richtig und den anderen falsch zu bekommen ergäbe nur einen anderen falschen Proof
Die Einstellung nimmt auch an der Identität gecachter Renderings teil. RenderLoadedPageToBitmapCached keyed seine Einträge auf Seite, DPI und eine Variante, gebaut aus Render-Einstellungen, die RenderOverprintPreview einschließen, und die Platten-Stufe verwendet dieselbe Variante. Ein Viewer, der zwischen normaler und Proof-Vorschau umschaltet, bekommt zwei getrennte Cache-Einträge und braucht nie einen Aufruf von InvalidateRenderedPageCache nur, weil der Schalter wechselte
Die /OPM-0-Falle in DeviceCMYK-Dateien
Hier ist der Fall, der Leute nach einem Bug suchen lässt. Eine Datei setzt /op true an einer DeviceCMYK-Cyan-Füllung, lässt aber OPM auf seinem Standard 0, dann zeigt der Proof weiterhin Cyan, das das Gelb ausstanzt. Der Proof ist korrekt. Unter Overprint-Modus 0 sagt §8.6.7, dass ein DeviceCMYK-Farbauftrag alle vier Prozessfarbstoffe setzt, Nullen eingeschlossen, also ersetzt die Nulldkomponente Gelb die gelbe Platte exakt so, wie ein Knockout es täte. Overprint-Modus 0 schützt nur Platten, die der Farbauftrag nicht nennt, was bei einer Vier-Komponenten-CMYK-Farbe Spot-Platten bedeutet und nichts sonst
Auf den Prozessplatten, die ein Composite-Proof zeigt, liefern Modus 0 und ein schlichter Knockout dieselben Pixel, also malt HotPDF diese DeviceCMYK-Objekte als gewöhnliche Knockouts. Damit ein CMYK-Objekt andere Prozessfarben überdruckt, braucht der ExtGState, der /op true trägt, zusätzlich /OPM 1. Wenn Proof und Design-Intent bei einem DeviceCMYK-Objekt auseinanderlaufen, diesen ExtGState öffnen und nach dem OPM-Eintrag suchen, bevor man irgendetwas anderes verdächtigt
Die umgekehrte Überraschung existiert ebenfalls. Unter /OPM 1 ist CMYK-Weiß ein Vierfach-Null, und vier Nullen unter Overprint lassen jede Platte, wie sie ist. Weißer Schriftzug auf Overprint gestellt verschwindet auf dem Bogen, und der Proof zeigt sein Verschwinden, was der ganze Grund ist, einen zu fahren
Drei Geräte hinter RenderLoadedPageToDevice
THotPDF.RenderLoadedPageToDevice(PageIndex, DPI, Device) ist ein einziger Einsprungpunkt, dessen Ziel das Geräteobjekt entscheidet, das man übergibt. Er löst für ein nil-Gerät eine Exception aus, behandelt einen DPI unter 1 als 150 und gibt zurück, was das Gerät aus seiner Execute-Methode meldet. THPDFRenderDevice ist die abstrakte Basis mit zwei virtuellen Membern: Kind, das rdkBitmap, rdkDeviceContext oder rdkEnhancedMetafile zurückgibt, und Execute(Document, PageIndex, DPI)
Die drei mitgelieferten Geräte besitzen ihre Ausgabe auf verschiedene Weise:
THPDFBitmapRenderDevicehält einTBitmapin seinerBitmap-Property und gibt es in seinem Destruktor frei, außerTakeBitmaphat es Ihnen zuerst übergebenTHPDFDeviceContextRenderDevice.Create(ADC, AWidth, AHeight)zeichnet in einHDC, das Sie bereits haben, und besitzt nichts; der Konstruktor löst bei einem Null-DC oder einer nicht-positiven Größe aus, und kein Hintergrund wird gemalt, also braucht ein Screen-DC seine eigene weiße FüllungTHPDFMetafileRenderDevicehält einTMetafile, bisTakeMetafilees überträgt. Text und Vektorpfade bleiben im Enhanced Metafile skalierbar, während Bild-XObjects rasterisiert ankommen
Eigentum folgt schlichten Delphi-Regeln. Die Bitmap- oder Metafile-Property lesen, wenn das Objekt nur so lange leben muss wie das Gerät; die Take-Methode aufrufen, wenn es länger leben muss. Das Bitmap nehmen, das Gerät freigeben, das Bitmap vergessen, und das Leak wächst mit der Seitenzahl: unsichtbar an einer Fünf-Seiten-Probe, offensichtlich an einem Fünf-Hundert-Seiten-Batch. Jedem Objekt sein eigenes try/finally geben, und die Frage, wer was freigibt, beantwortet sich selbst
In Anwendungs-Code auf Kind dispatchen, statt is THPDFBitmapRenderDevice zu testen. Da Execute und Kind öffentliche virtuelle Methoden sind, kann man seine eigene Geräteklasse schreiben, und Code, der die Art prüft, funktioniert weiter, wenn eines von Ihren für ein mitgeliefertes Gerät einspringt
Warum landet ein Drucker-Rendering in einer Ecke?
Der Device-Context-Pfad nimmt die Seitengröße aus dem DPI-Argument, nicht aus der Breite und Höhe, die man übergibt. Der Renderer skaliert PDF-Einheiten mit DPI / 72 und verwendet die Höhe nur, um den Seiten-Ursprung am unteren Rand der Oberfläche zu verankern. 300 fest verdrahtet und den Job an einen 600-dpi-Drucker geschickt, kommt die Seite auf halber Größe heraus, geschoben in die linke untere Ecke des Bogens. Die Drucker-Auflösung ist eine Eigenschaft des Treibers, also beim Treiber nachfragen:
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
// beim Treiber nachfragen; 300, 600 und 1200 dpi sind alle üblich
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; // tauschen für 90-/270-Grad-Seiten
end;
Device := THPDFDeviceContextRenderDevice.Create(
Printer.Canvas.Handle, W, H);
try
Pdf.RenderLoadedPageToDevice(PageIndex, PrinterDPI, Device);
finally
Device.Free;
end;
finally
Printer.EndDoc;
end;
end;
Breite und Höhe kommen aus der sichtbaren Box der Seite, der CropBox, begrenzt auf die MediaBox, in der eigenen Auflösung des Druckers, und der Aufrufer tauscht sie für gedrehte Seiten, bevor er das Gerät erzeugt. Das entspricht dem, was der Renderer erwartet, wenn er den Ursprung verankert
Overprint-Proofing reist nicht diesen Weg entlang. Die Device-Context- und Metafile-Geräte geben GDI-Aufrufe direkt ins Ziel aus, und die Platten-Regeln brauchen die Pixel, die bereits unter jedem Farbauftrag liegen, was nur das Bitmap-Rendering hat. Für einen Papier-Proof das Proof-Bitmap rendern und auf den Drucker-Canvas gestreckt ausgeben. Ein kleines eigenes Gerät hält das hinter demselben Einsprungpunkt:
type
// ein eigenes Gerät: Proof-Bitmap, dann gestreckt auf den Drucker
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; // die Einstellung des Aufrufers unverändert lassen
end;
Result := Proof <> nil;
if Result then
try
Printer.Canvas.StretchDraw(
Rect(0, 0, Printer.PageWidth, Printer.PageHeight), Proof);
finally
Proof.Free;
end;
end;
Zwischen Printer.BeginDoc und Printer.EndDoc aufrufen, mit einem DPI, der dem Bitmap genug Pixel für den Bogen gibt, etwa 200 bis 300 für einen Proof in Letter-Größe. Das Streckungs-Rechteck oben füllt den bedruckbaren Bereich; behalten Sie das Seitenverhältnis der Seite darin bei, wenn sich Seite und Papier in der Form unterscheiden
Wo Proofing neben dem Preflight passt
Der Proof beantwortet eine Frage: Welche Tinten überleben, wo sich Objekte überlappen. Er wird auf dasselbe 24-Bit-RGB-Bitmap composited wie jedes andere Rendering, also zeigen seine Farben die Tintenkombination statt einer gemessenen Bogenfarbe. Druckbedingungen sind eine Farbmanagement-Frage, und das Dokument behandelt sie über ConfigureRenderICCWorkflow, das ein Proof-Profil, ein Ausgabeprofil und ein Black-Point-Compensation-Flag nimmt, und ClearRenderICCWorkflow, um sie wieder fallen zu lassen
Der ergiebigste Platz für ein Proof-Rendering ist neben den Prüfungen, die man ohnehin fährt. Ein Preflight-Durchgang meldet, dass schwarzer Text auf Overprint steht; das Proof-Rendering zeigt dem Operator, was das auf der Seite tut; beides landet im selben Report. Verpackungsarbeit mischt Overprint gern mit Spot-Tinten, und der Durchgang durch Separation- und DeviceN-Spot-Farb-Rendering deckt die Farbstoff-Seite derselben Seite, eingeschlossen Einzelplatten-Sichten über RenderLoadedPageSeparationPlate. Die Artikel zu eine PDF-Seite in ein Bitmap rendern und ein geladenes PDF über TPrinter drucken decken die beiden Geräte-Ziele in ihrer schlichten Form
Das alles läuft in nativem Delphi- und C++Builder-Code ohne Rendering-DLL, die neben der ausführbaren Datei mitgeliefert werden müsste. Die HotPDF-Delphi-Komponentenseite listet die Rendering- und Prepress-Features und hat einen Trial-Build, um diese Beispiele gegen Ihre eigenen Druckdateien zu fahren